--- /dev/null
+From 77446d67560d46864a1986e48ef9b9633f232f1b Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 27 Oct 2023 11:03:02 +0800
+Subject: 9p/net: fix possible memory leak in p9_check_errors()
+
+From: Hangyu Hua <hbh25y@gmail.com>
+
+[ Upstream commit ce07087964208eee2ca2f9ee4a98f8b5d9027fe6 ]
+
+When p9pdu_readf() is called with "s?d" attribute, it allocates a pointer
+that will store a string. But when p9pdu_readf() fails while handling "d"
+then this pointer will not be freed in p9_check_errors().
+
+Fixes: 51a87c552dfd ("9p: rework client code to use new protocol support functions")
+Reviewed-by: Christian Schoenebeck <linux_oss@crudebyte.com>
+Signed-off-by: Hangyu Hua <hbh25y@gmail.com>
+Message-ID: <20231027030302.11927-1-hbh25y@gmail.com>
+Signed-off-by: Dominique Martinet <asmadeus@codewreck.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/9p/client.c | 6 ++++--
+ 1 file changed, 4 insertions(+), 2 deletions(-)
+
+diff --git a/net/9p/client.c b/net/9p/client.c
+index c4c1e44cd7ca3..9fdcaa956c008 100644
+--- a/net/9p/client.c
++++ b/net/9p/client.c
+@@ -520,12 +520,14 @@ static int p9_check_errors(struct p9_client *c, struct p9_req_t *req)
+ return 0;
+
+ if (!p9_is_proto_dotl(c)) {
+- char *ename;
++ char *ename = NULL;
+
+ err = p9pdu_readf(&req->rc, c->proto_version, "s?d",
+ &ename, &ecode);
+- if (err)
++ if (err) {
++ kfree(ename);
+ goto out_err;
++ }
+
+ if (p9_is_proto_dotu(c) && ecode < 512)
+ err = -ecode;
+--
+2.42.0
+
--- /dev/null
+From 6480654ad6e5e47192c9ec7a883c6cbdbdcc9dd5 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 23 Oct 2023 20:32:54 +0200
+Subject: ACPI: sysfs: Fix create_pnp_modalias() and create_of_modalias()
+
+From: Christophe JAILLET <christophe.jaillet@wanadoo.fr>
+
+[ Upstream commit 48cf49d31994ff97b33c4044e618560ec84d35fb ]
+
+snprintf() does not return negative values on error.
+
+To know if the buffer was too small, the returned value needs to be
+compared with the length of the passed buffer. If it is greater or
+equal, the output has been truncated, so add checks for the truncation
+to create_pnp_modalias() and create_of_modalias(). Also make them
+return -ENOMEM in that case, as they already do that elsewhere.
+
+Moreover, the remaining size of the buffer used by snprintf() needs to
+be updated after the first write to avoid out-of-bounds access as
+already done correctly in create_pnp_modalias(), but not in
+create_of_modalias(), so change the latter accordingly.
+
+Fixes: 8765c5ba1949 ("ACPI / scan: Rework modalias creation when "compatible" is present")
+Signed-off-by: Christophe JAILLET <christophe.jaillet@wanadoo.fr>
+[ rjw: Merge two patches into one, combine changelogs, add subject ]
+Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/acpi/device_sysfs.c | 10 ++++++----
+ 1 file changed, 6 insertions(+), 4 deletions(-)
+
+diff --git a/drivers/acpi/device_sysfs.c b/drivers/acpi/device_sysfs.c
+index 61271e61c3073..da9cd11adfb56 100644
+--- a/drivers/acpi/device_sysfs.c
++++ b/drivers/acpi/device_sysfs.c
+@@ -157,8 +157,8 @@ static int create_pnp_modalias(struct acpi_device *acpi_dev, char *modalias,
+ return 0;
+
+ len = snprintf(modalias, size, "acpi:");
+- if (len <= 0)
+- return len;
++ if (len >= size)
++ return -ENOMEM;
+
+ size -= len;
+
+@@ -211,8 +211,10 @@ static int create_of_modalias(struct acpi_device *acpi_dev, char *modalias,
+ len = snprintf(modalias, size, "of:N%sT", (char *)buf.pointer);
+ ACPI_FREE(buf.pointer);
+
+- if (len <= 0)
+- return len;
++ if (len >= size)
++ return -ENOMEM;
++
++ size -= len;
+
+ of_compatible = acpi_dev->data.of_compatible;
+ if (of_compatible->type == ACPI_TYPE_PACKAGE) {
+--
+2.42.0
+
--- /dev/null
+From f71e01feff5b06f29dea7be9408bbe282c83427a Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 22 Aug 2023 15:06:06 +0100
+Subject: ARM: 9321/1: memset: cast the constant byte to unsigned char
+
+From: Kursad Oney <kursad.oney@broadcom.com>
+
+[ Upstream commit c0e824661f443b8cab3897006c1bbc69fd0e7bc4 ]
+
+memset() description in ISO/IEC 9899:1999 (and elsewhere) says:
+
+ The memset function copies the value of c (converted to an
+ unsigned char) into each of the first n characters of the
+ object pointed to by s.
+
+The kernel's arm32 memset does not cast c to unsigned char. This results
+in the following code to produce erroneous output:
+
+ char a[128];
+ memset(a, -128, sizeof(a));
+
+This is because gcc will generally emit the following code before
+it calls memset() :
+
+ mov r0, r7
+ mvn r1, #127 ; 0x7f
+ bl 00000000 <memset>
+
+r1 ends up with 0xffffff80 before being used by memset() and the
+'a' array will have -128 once in every four bytes while the other
+bytes will be set incorrectly to -1 like this (printing the first
+8 bytes) :
+
+ test_module: -128 -1 -1 -1
+ test_module: -1 -1 -1 -128
+
+The change here is to 'and' r1 with 255 before it is used.
+
+Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2")
+Reviewed-by: Ard Biesheuvel <ardb@kernel.org>
+Reviewed-by: Linus Walleij <linus.walleij@linaro.org>
+Signed-off-by: Kursad Oney <kursad.oney@broadcom.com>
+Signed-off-by: Russell King (Oracle) <rmk+kernel@armlinux.org.uk>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ arch/arm/lib/memset.S | 1 +
+ 1 file changed, 1 insertion(+)
+
+diff --git a/arch/arm/lib/memset.S b/arch/arm/lib/memset.S
+index 9817cb258c1a5..0481b9bbbd004 100644
+--- a/arch/arm/lib/memset.S
++++ b/arch/arm/lib/memset.S
+@@ -17,6 +17,7 @@ ENTRY(__memset)
+ ENTRY(mmioset)
+ WEAK(memset)
+ UNWIND( .fnstart )
++ and r1, r1, #255 @ cast to unsigned char
+ ands r3, r0, #3 @ 1 unaligned?
+ mov ip, r0 @ preserve r0 as return value
+ bne 6f @ 1
+--
+2.42.0
+
--- /dev/null
+From 2411013ead0e25a4e5c8c391b302dcdfcadaa9ad Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sun, 24 Sep 2023 20:39:13 +0200
+Subject: ARM: dts: qcom: mdm9615: populate vsdcc fixed regulator
+
+From: Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
+
+[ Upstream commit 09f8ee81b6da5f76de8b83c8bfc4475b54e101e0 ]
+
+Fixed regulator put under "regulators" node will not be populated,
+unless simple-bus or something similar is used. Drop the "regulators"
+wrapper node to fix this.
+
+Fixes: 2c5e596524e7 ("ARM: dts: Add MDM9615 dtsi")
+Signed-off-by: Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
+Reviewed-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
+Link: https://lore.kernel.org/r/20230924183914.51414-3-krzysztof.kozlowski@linaro.org
+Signed-off-by: Bjorn Andersson <andersson@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ arch/arm/boot/dts/qcom-mdm9615.dtsi | 14 ++++++--------
+ 1 file changed, 6 insertions(+), 8 deletions(-)
+
+diff --git a/arch/arm/boot/dts/qcom-mdm9615.dtsi b/arch/arm/boot/dts/qcom-mdm9615.dtsi
+index ad9b52d53ef9b..982f3c3921965 100644
+--- a/arch/arm/boot/dts/qcom-mdm9615.dtsi
++++ b/arch/arm/boot/dts/qcom-mdm9615.dtsi
+@@ -82,14 +82,12 @@ cxo_board {
+ };
+ };
+
+- regulators {
+- vsdcc_fixed: vsdcc-regulator {
+- compatible = "regulator-fixed";
+- regulator-name = "SDCC Power";
+- regulator-min-microvolt = <2700000>;
+- regulator-max-microvolt = <2700000>;
+- regulator-always-on;
+- };
++ vsdcc_fixed: vsdcc-regulator {
++ compatible = "regulator-fixed";
++ regulator-name = "SDCC Power";
++ regulator-min-microvolt = <2700000>;
++ regulator-max-microvolt = <2700000>;
++ regulator-always-on;
+ };
+
+ soc: soc {
+--
+2.42.0
+
--- /dev/null
+From 7a182f164433cc2a8a6f6952bea4850c8d9ae35d Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 30 Aug 2023 17:21:38 +0200
+Subject: ARM: dts: renesas: blanche: Fix typo in GP_11_2 pin name
+
+From: Geert Uytterhoeven <geert+renesas@glider.be>
+
+[ Upstream commit edc6ef026fe69154bb6b70dd6e7f278cfd7d6919 ]
+
+On blanche, the GPIO keyboard fails to probe with:
+
+ sh-pfc e6060000.pinctrl: could not map pin config for "GP_11_02"
+
+Fix this by correcting the name for this pin to "GP_11_2".
+
+Fixes: 1f27fedead91eb60 ("ARM: dts: blanche: Configure pull-up for SOFT_SW and SW25 GPIO keys")
+Signed-off-by: Geert Uytterhoeven <geert+renesas@glider.be>
+Link: https://lore.kernel.org/r/203128eca2261ffc33b83637818dd39c488f42b0.1693408326.git.geert+renesas@glider.be
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ arch/arm/boot/dts/r8a7792-blanche.dts | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/arch/arm/boot/dts/r8a7792-blanche.dts b/arch/arm/boot/dts/r8a7792-blanche.dts
+index 62aa9f61321be..089fef40c4c49 100644
+--- a/arch/arm/boot/dts/r8a7792-blanche.dts
++++ b/arch/arm/boot/dts/r8a7792-blanche.dts
+@@ -239,7 +239,7 @@ du1_pins: du1 {
+ };
+
+ keyboard_pins: keyboard {
+- pins = "GP_3_10", "GP_3_11", "GP_3_12", "GP_3_15", "GP_11_02";
++ pins = "GP_3_10", "GP_3_11", "GP_3_12", "GP_3_15", "GP_11_2";
+ bias-pull-up;
+ };
+
+--
+2.42.0
+
--- /dev/null
+From b41800afaa64ab8b9b88c7c8d60b3c38d3fda01f Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 16 Oct 2023 11:24:25 +0100
+Subject: arm64/arm: xen: enlighten: Fix KPTI checks
+
+From: Mark Rutland <mark.rutland@arm.com>
+
+[ Upstream commit 20f3b8eafe0ba5d3c69d5011a9b07739e9645132 ]
+
+When KPTI is in use, we cannot register a runstate region as XEN
+requires that this is always a valid VA, which we cannot guarantee. Due
+to this, xen_starting_cpu() must avoid registering each CPU's runstate
+region, and xen_guest_init() must avoid setting up features that depend
+upon it.
+
+We tried to ensure that in commit:
+
+ f88af7229f6f22ce (" xen/arm: do not setup the runstate info page if kpti is enabled")
+
+... where we added checks for xen_kernel_unmapped_at_usr(), which wraps
+arm64_kernel_unmapped_at_el0() on arm64 and is always false on 32-bit
+arm.
+
+Unfortunately, as xen_guest_init() is an early_initcall, this happens
+before secondary CPUs are booted and arm64 has finalized the
+ARM64_UNMAP_KERNEL_AT_EL0 cpucap which backs
+arm64_kernel_unmapped_at_el0(), and so this can subsequently be set as
+secondary CPUs are onlined. On a big.LITTLE system where the boot CPU
+does not require KPTI but some secondary CPUs do, this will result in
+xen_guest_init() intializing features that depend on the runstate
+region, and xen_starting_cpu() registering the runstate region on some
+CPUs before KPTI is subsequent enabled, resulting the the problems the
+aforementioned commit tried to avoid.
+
+Handle this more robsutly by deferring the initialization of the
+runstate region until secondary CPUs have been initialized and the
+ARM64_UNMAP_KERNEL_AT_EL0 cpucap has been finalized. The per-cpu work is
+moved into a new hotplug starting function which is registered later
+when we're certain that KPTI will not be used.
+
+Fixes: f88af7229f6f ("xen/arm: do not setup the runstate info page if kpti is enabled")
+Signed-off-by: Mark Rutland <mark.rutland@arm.com>
+Cc: Bertrand Marquis <bertrand.marquis@arm.com>
+Cc: Boris Ostrovsky <boris.ostrovsky@oracle.com>
+Cc: Juergen Gross <jgross@suse.com>
+Cc: Stefano Stabellini <sstabellini@kernel.org>
+Cc: Suzuki K Poulose <suzuki.poulose@arm.com>
+Cc: Will Deacon <will@kernel.org>
+Signed-off-by: Catalin Marinas <catalin.marinas@arm.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ arch/arm/xen/enlighten.c | 25 ++++++++++++++++---------
+ include/linux/cpuhotplug.h | 1 +
+ 2 files changed, 17 insertions(+), 9 deletions(-)
+
+diff --git a/arch/arm/xen/enlighten.c b/arch/arm/xen/enlighten.c
+index 7f1c106b746f8..27277d6bbfa5a 100644
+--- a/arch/arm/xen/enlighten.c
++++ b/arch/arm/xen/enlighten.c
+@@ -159,9 +159,6 @@ static int xen_starting_cpu(unsigned int cpu)
+ BUG_ON(err);
+ per_cpu(xen_vcpu, cpu) = vcpup;
+
+- if (!xen_kernel_unmapped_at_usr())
+- xen_setup_runstate_info(cpu);
+-
+ after_register_vcpu_info:
+ enable_percpu_irq(xen_events_irq, 0);
+ return 0;
+@@ -394,9 +391,6 @@ static int __init xen_guest_init(void)
+ return -EINVAL;
+ }
+
+- if (!xen_kernel_unmapped_at_usr())
+- xen_time_setup_guest();
+-
+ if (xen_initial_domain())
+ pvclock_gtod_register_notifier(&xen_pvclock_gtod_notifier);
+
+@@ -406,7 +400,13 @@ static int __init xen_guest_init(void)
+ }
+ early_initcall(xen_guest_init);
+
+-static int __init xen_pm_init(void)
++static int xen_starting_runstate_cpu(unsigned int cpu)
++{
++ xen_setup_runstate_info(cpu);
++ return 0;
++}
++
++static int __init xen_late_init(void)
+ {
+ if (!xen_domain())
+ return -ENODEV;
+@@ -419,9 +419,16 @@ static int __init xen_pm_init(void)
+ do_settimeofday64(&ts);
+ }
+
+- return 0;
++ if (xen_kernel_unmapped_at_usr())
++ return 0;
++
++ xen_time_setup_guest();
++
++ return cpuhp_setup_state(CPUHP_AP_ARM_XEN_RUNSTATE_STARTING,
++ "arm/xen_runstate:starting",
++ xen_starting_runstate_cpu, NULL);
+ }
+-late_initcall(xen_pm_init);
++late_initcall(xen_late_init);
+
+
+ /* empty stubs */
+diff --git a/include/linux/cpuhotplug.h b/include/linux/cpuhotplug.h
+index dbca858ffa6da..c7156bb56e831 100644
+--- a/include/linux/cpuhotplug.h
++++ b/include/linux/cpuhotplug.h
+@@ -188,6 +188,7 @@ enum cpuhp_state {
+ /* Must be the last timer callback */
+ CPUHP_AP_DUMMY_TIMER_STARTING,
+ CPUHP_AP_ARM_XEN_STARTING,
++ CPUHP_AP_ARM_XEN_RUNSTATE_STARTING,
+ CPUHP_AP_ARM_CORESIGHT_STARTING,
+ CPUHP_AP_ARM_CORESIGHT_CTI_STARTING,
+ CPUHP_AP_ARM64_ISNDEP_STARTING,
+--
+2.42.0
+
--- /dev/null
+From d5c8ff6cc9cc9d3474c42000f82c3122e7cf636a Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 4 Oct 2023 18:01:58 -0500
+Subject: arm64: dts: imx8mm: Add sound-dai-cells to micfil node
+
+From: Adam Ford <aford173@gmail.com>
+
+[ Upstream commit 0e6cc2b8bb7d67733f4a47720787eff1ce2666f2 ]
+
+Per the DT bindings, the micfil node should have a sound-dai-cells
+entry.
+
+Fixes: 3bd0788c43d9 ("arm64: dts: imx8mm: Add support for micfil")
+Signed-off-by: Adam Ford <aford173@gmail.com>
+Reviewed-by: Fabio Estevam <festevam@gmail.com>
+Signed-off-by: Shawn Guo <shawnguo@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ arch/arm64/boot/dts/freescale/imx8mm.dtsi | 1 +
+ 1 file changed, 1 insertion(+)
+
+diff --git a/arch/arm64/boot/dts/freescale/imx8mm.dtsi b/arch/arm64/boot/dts/freescale/imx8mm.dtsi
+index 2a67122c5624c..86731850a6bd6 100644
+--- a/arch/arm64/boot/dts/freescale/imx8mm.dtsi
++++ b/arch/arm64/boot/dts/freescale/imx8mm.dtsi
+@@ -366,6 +366,7 @@ micfil: audio-controller@30080000 {
+ "pll8k", "pll11k", "clkext3";
+ dmas = <&sdma2 24 25 0x80000000>;
+ dma-names = "rx";
++ #sound-dai-cells = <0>;
+ status = "disabled";
+ };
+
+--
+2.42.0
+
--- /dev/null
+From adf10134d080fcb3d98adea7dbd18f4b0838f192 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 4 Oct 2023 18:01:59 -0500
+Subject: arm64: dts: imx8mn: Add sound-dai-cells to micfil node
+
+From: Adam Ford <aford173@gmail.com>
+
+[ Upstream commit db1925454a2e7cadcac8756442ca7c3198332336 ]
+
+Per the DT bindings, the micfil node should have a sound-dai-cells
+entry.
+
+Fixes: cca69ef6eba5 ("arm64: dts: imx8mn: Add support for micfil")
+Signed-off-by: Adam Ford <aford173@gmail.com>
+Reviewed-by: Fabio Estevam <festevam@gmail.com>
+Signed-off-by: Shawn Guo <shawnguo@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ arch/arm64/boot/dts/freescale/imx8mn.dtsi | 1 +
+ 1 file changed, 1 insertion(+)
+
+diff --git a/arch/arm64/boot/dts/freescale/imx8mn.dtsi b/arch/arm64/boot/dts/freescale/imx8mn.dtsi
+index 16a5efba17f39..8f01848b7c6a9 100644
+--- a/arch/arm64/boot/dts/freescale/imx8mn.dtsi
++++ b/arch/arm64/boot/dts/freescale/imx8mn.dtsi
+@@ -340,6 +340,7 @@ micfil: audio-controller@30080000 {
+ "pll8k", "pll11k", "clkext3";
+ dmas = <&sdma2 24 25 0x80000000>;
+ dma-names = "rx";
++ #sound-dai-cells = <0>;
+ status = "disabled";
+ };
+
+--
+2.42.0
+
--- /dev/null
+From ca067a45f64a175c8def5f99b855687b1180e821 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 26 Sep 2023 11:27:36 -0300
+Subject: arm64: dts: imx8qm-ss-img: Fix jpegenc compatible entry
+
+From: Fabio Estevam <festevam@denx.de>
+
+[ Upstream commit 1d33cd614d89b0ec024d25ec45acf4632211b5a7 ]
+
+The first compatible entry for the jpegenc should be 'nxp,imx8qm-jpgenc'.
+
+Change it accordingly to fix the following schema warning:
+
+imx8qm-apalis-eval.dtb: jpegenc@58450000: compatible: 'oneOf' conditional failed, one must be fixed:
+ 'nxp,imx8qm-jpgdec' is not one of ['nxp,imx8qxp-jpgdec', 'nxp,imx8qxp-jpgenc']
+ 'nxp,imx8qm-jpgenc' was expected
+ 'nxp,imx8qxp-jpgdec' was expected
+
+Fixes: 5bb279171afc ("arm64: dts: imx8: Add jpeg encoder/decoder nodes")
+Signed-off-by: Fabio Estevam <festevam@denx.de>
+Reviewed-by: Mirela Rabulea <mirela.rabulea@nxp.com>
+Reviewed-by: Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
+Signed-off-by: Shawn Guo <shawnguo@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ arch/arm64/boot/dts/freescale/imx8qm-ss-img.dtsi | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/arch/arm64/boot/dts/freescale/imx8qm-ss-img.dtsi b/arch/arm64/boot/dts/freescale/imx8qm-ss-img.dtsi
+index 7764b4146e0ab..2bbdacb1313f9 100644
+--- a/arch/arm64/boot/dts/freescale/imx8qm-ss-img.dtsi
++++ b/arch/arm64/boot/dts/freescale/imx8qm-ss-img.dtsi
+@@ -8,5 +8,5 @@ &jpegdec {
+ };
+
+ &jpegenc {
+- compatible = "nxp,imx8qm-jpgdec", "nxp,imx8qxp-jpgenc";
++ compatible = "nxp,imx8qm-jpgenc", "nxp,imx8qxp-jpgenc";
+ };
+--
+2.42.0
+
--- /dev/null
+From 1fae08c62af0928245ef3a5dc36df4520e9e4af5 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 21 Aug 2023 10:51:25 +1200
+Subject: ARM64: dts: marvell: cn9310: Use appropriate label for spi1 pins
+
+From: Chris Packham <chris.packham@alliedtelesis.co.nz>
+
+[ Upstream commit 0878fd86f554ab98aa493996c7e0c72dff58437f ]
+
+Both the CN9130-CRB and CN9130-DB use the SPI1 interface but had the
+pinctrl node labelled as "cp0_spi0_pins". Use the label "cp0_spi1_pins"
+and update the node name to "cp0-spi-pins-1" to avoid confusion with the
+pinctrl options for SPI0.
+
+Fixes: 4c43a41e5b8c ("arm64: dts: cn913x: add device trees for topology B boards")
+Fixes: 5c0ee54723f3 ("arm64: dts: add support for Marvell cn9130-crb platform")
+Signed-off-by: Chris Packham <chris.packham@alliedtelesis.co.nz>
+Reviewed-by: Andrew Lunn <andrew@lunn.ch>
+Signed-off-by: Gregory CLEMENT <gregory.clement@bootlin.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ arch/arm64/boot/dts/marvell/cn9130-crb.dtsi | 4 ++--
+ arch/arm64/boot/dts/marvell/cn9130-db.dtsi | 4 ++--
+ 2 files changed, 4 insertions(+), 4 deletions(-)
+
+diff --git a/arch/arm64/boot/dts/marvell/cn9130-crb.dtsi b/arch/arm64/boot/dts/marvell/cn9130-crb.dtsi
+index 505ae69289f6d..ce49702dc4936 100644
+--- a/arch/arm64/boot/dts/marvell/cn9130-crb.dtsi
++++ b/arch/arm64/boot/dts/marvell/cn9130-crb.dtsi
+@@ -107,7 +107,7 @@ cp0_sdhci_pins: cp0-sdhi-pins-0 {
+ "mpp59", "mpp60", "mpp61";
+ marvell,function = "sdio";
+ };
+- cp0_spi0_pins: cp0-spi-pins-0 {
++ cp0_spi1_pins: cp0-spi-pins-1 {
+ marvell,pins = "mpp13", "mpp14", "mpp15", "mpp16";
+ marvell,function = "spi1";
+ };
+@@ -149,7 +149,7 @@ &cp0_sdhci0 {
+
+ &cp0_spi1 {
+ pinctrl-names = "default";
+- pinctrl-0 = <&cp0_spi0_pins>;
++ pinctrl-0 = <&cp0_spi1_pins>;
+ reg = <0x700680 0x50>, /* control */
+ <0x2000000 0x1000000>; /* CS0 */
+ status = "okay";
+diff --git a/arch/arm64/boot/dts/marvell/cn9130-db.dtsi b/arch/arm64/boot/dts/marvell/cn9130-db.dtsi
+index c00b69b88bd2f..c53253f668403 100644
+--- a/arch/arm64/boot/dts/marvell/cn9130-db.dtsi
++++ b/arch/arm64/boot/dts/marvell/cn9130-db.dtsi
+@@ -307,7 +307,7 @@ &cp0_sdhci0 {
+ &cp0_spi1 {
+ status = "disabled";
+ pinctrl-names = "default";
+- pinctrl-0 = <&cp0_spi0_pins>;
++ pinctrl-0 = <&cp0_spi1_pins>;
+ reg = <0x700680 0x50>;
+
+ spi-flash@0 {
+@@ -371,7 +371,7 @@ cp0_sdhci_pins: cp0-sdhi-pins-0 {
+ "mpp59", "mpp60", "mpp61";
+ marvell,function = "sdio";
+ };
+- cp0_spi0_pins: cp0-spi-pins-0 {
++ cp0_spi1_pins: cp0-spi-pins-1 {
+ marvell,pins = "mpp13", "mpp14", "mpp15", "mpp16";
+ marvell,function = "spi1";
+ };
+--
+2.42.0
+
--- /dev/null
+From 65a05cd16e035e672bb57b27bb1eb0333cef14a5 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 22 Sep 2023 12:49:55 +0200
+Subject: arm64: dts: qcom: apq8016-sbc: Add missing ADV7533 regulators
+
+From: Stephan Gerhold <stephan@gerhold.net>
+
+[ Upstream commit 33e9032a1875bb1aee3c68a4540f5a577ff44130 ]
+
+Add the missing regulator supplies to the ADV7533 HDMI bridge to fix
+the following dtbs_check warnings. They are all also supplied by
+pm8916_l6 so there is no functional difference.
+
+apq8016-sbc.dtb: bridge@39: 'dvdd-supply' is a required property
+apq8016-sbc.dtb: bridge@39: 'pvdd-supply' is a required property
+apq8016-sbc.dtb: bridge@39: 'a2vdd-supply' is a required property
+ from schema display/bridge/adi,adv7533.yaml
+
+Fixes: 28546b095511 ("arm64: dts: apq8016-sbc: Add HDMI display support")
+Signed-off-by: Stephan Gerhold <stephan@gerhold.net>
+Reviewed-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
+Link: https://lore.kernel.org/r/20230922-db410c-adv7533-regulators-v1-1-68aba71e529b@gerhold.net
+Signed-off-by: Bjorn Andersson <andersson@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ arch/arm64/boot/dts/qcom/apq8016-sbc.dts | 3 +++
+ 1 file changed, 3 insertions(+)
+
+diff --git a/arch/arm64/boot/dts/qcom/apq8016-sbc.dts b/arch/arm64/boot/dts/qcom/apq8016-sbc.dts
+index ad4c2ccec63ee..0153be6d2a2b1 100644
+--- a/arch/arm64/boot/dts/qcom/apq8016-sbc.dts
++++ b/arch/arm64/boot/dts/qcom/apq8016-sbc.dts
+@@ -190,6 +190,9 @@ adv_bridge: bridge@39 {
+ pd-gpios = <&msmgpio 32 GPIO_ACTIVE_HIGH>;
+
+ avdd-supply = <&pm8916_l6>;
++ a2vdd-supply = <&pm8916_l6>;
++ dvdd-supply = <&pm8916_l6>;
++ pvdd-supply = <&pm8916_l6>;
+ v1p2-supply = <&pm8916_l6>;
+ v3p3-supply = <&pm8916_l17>;
+
+--
+2.42.0
+
--- /dev/null
+From ff76ee86e94d159c87e0ec611d3973ae18f5c01b Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 15 Sep 2023 20:03:04 +0530
+Subject: arm64: dts: qcom: msm8916: Fix iommu local address range
+
+From: Gaurav Kohli <quic_gkohli@quicinc.com>
+
+[ Upstream commit 2de8ee9f58fa51f707c71f8fbcd8470ab0078102 ]
+
+Fix the apps iommu local address space range as per data sheet.
+
+Fixes: 6a6729f38436 ("arm64: dts: qcom: msm8916: Add IOMMU support")
+Reviewed-by: Bryan O'Donoghue <bryan.odonoghue@linaro.org>
+Tested-by: Bryan O'Donoghue <bryan.odonoghue@linaro.org>
+Signed-off-by: Gaurav Kohli <quic_gkohli@quicinc.com>
+Reviewed-by: Stephan Gerhold <stephan@gerhold.net>
+Acked-by: Konrad Dybcio <konrad.dybcio@linaro.org>
+Link: https://lore.kernel.org/r/20230915143304.477-1-quic_gkohli@quicinc.com
+Signed-off-by: Bjorn Andersson <andersson@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ arch/arm64/boot/dts/qcom/msm8916.dtsi | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/arch/arm64/boot/dts/qcom/msm8916.dtsi b/arch/arm64/boot/dts/qcom/msm8916.dtsi
+index fcc9f757c9e14..668674059d485 100644
+--- a/arch/arm64/boot/dts/qcom/msm8916.dtsi
++++ b/arch/arm64/boot/dts/qcom/msm8916.dtsi
+@@ -1233,7 +1233,7 @@ apps_iommu: iommu@1ef0000 {
+ #size-cells = <1>;
+ #iommu-cells = <1>;
+ compatible = "qcom,msm8916-iommu", "qcom,msm-iommu-v1";
+- ranges = <0 0x01e20000 0x40000>;
++ ranges = <0 0x01e20000 0x20000>;
+ reg = <0x01ef0000 0x3000>;
+ clocks = <&gcc GCC_SMMU_CFG_CLK>,
+ <&gcc GCC_APSS_TCU_CLK>;
+--
+2.42.0
+
--- /dev/null
+From cb43a19df3ed3620f0645c93b3f69a1b7d998e29 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 20 Jul 2023 09:20:48 +0200
+Subject: arm64: dts: qcom: msm8992-libra: drop duplicated reserved memory
+
+From: Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
+
+[ Upstream commit f32096602c19e68fb9bf04b494d13f1190602554 ]
+
+There are two entries for similar reserved memory: qseecom@cb400000 and
+audio@cb400000. Keep the qseecom as it is longer.
+
+ Warning (unique_unit_address_if_enabled): /reserved-memory/audio@cb400000: duplicate unit-address (also used in node /reserved-memory/qseecom@cb400000)
+
+Fixes: 69876bc6fd4d ("arm64: dts: qcom: msm8992-libra: Fix the memory map")
+Signed-off-by: Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
+Link: https://lore.kernel.org/r/20230720072048.10093-2-krzysztof.kozlowski@linaro.org
+Signed-off-by: Bjorn Andersson <andersson@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ arch/arm64/boot/dts/qcom/msm8992-xiaomi-libra.dts | 5 -----
+ 1 file changed, 5 deletions(-)
+
+diff --git a/arch/arm64/boot/dts/qcom/msm8992-xiaomi-libra.dts b/arch/arm64/boot/dts/qcom/msm8992-xiaomi-libra.dts
+index d08659c606b9a..5433ae0c45907 100644
+--- a/arch/arm64/boot/dts/qcom/msm8992-xiaomi-libra.dts
++++ b/arch/arm64/boot/dts/qcom/msm8992-xiaomi-libra.dts
+@@ -99,11 +99,6 @@ rmtfs_mem: rmtfs@ca100000 {
+ qcom,client-id = <1>;
+ };
+
+- audio_mem: audio@cb400000 {
+- reg = <0 0xcb000000 0 0x400000>;
+- no-mem;
+- };
+-
+ qseecom_mem: qseecom@cb400000 {
+ reg = <0 0xcb400000 0 0x1c00000>;
+ no-mem;
+--
+2.42.0
+
--- /dev/null
+From cda075d471bc310e17c682d4866112465202e40e Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 11 Aug 2023 22:58:22 +0200
+Subject: arm64: dts: qcom: sc7280: Add missing LMH interrupts
+
+From: Konrad Dybcio <konrad.dybcio@linaro.org>
+
+[ Upstream commit 3f93d119c9d6e1744d55cd48af764160a1a3aca3 ]
+
+Hook up the interrupts that signal the Limits Management Hardware has
+started some sort of throttling action.
+
+Fixes: 7dbd121a2c58 ("arm64: dts: qcom: sc7280: Add cpufreq hw node")
+Signed-off-by: Konrad Dybcio <konrad.dybcio@linaro.org>
+Link: https://lore.kernel.org/r/20230811-topic-7280_lmhirq-v1-1-c262b6a25c8f@linaro.org
+Signed-off-by: Bjorn Andersson <andersson@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ arch/arm64/boot/dts/qcom/sc7280.dtsi | 8 ++++++++
+ 1 file changed, 8 insertions(+)
+
+diff --git a/arch/arm64/boot/dts/qcom/sc7280.dtsi b/arch/arm64/boot/dts/qcom/sc7280.dtsi
+index fb6473a0aa4b3..dc4aab258ff6f 100644
+--- a/arch/arm64/boot/dts/qcom/sc7280.dtsi
++++ b/arch/arm64/boot/dts/qcom/sc7280.dtsi
+@@ -1851,6 +1851,14 @@ cpufreq_hw: cpufreq@18591000 {
+ reg = <0 0x18591000 0 0x1000>,
+ <0 0x18592000 0 0x1000>,
+ <0 0x18593000 0 0x1000>;
++
++ interrupts = <GIC_SPI 30 IRQ_TYPE_LEVEL_HIGH>,
++ <GIC_SPI 31 IRQ_TYPE_LEVEL_HIGH>,
++ <GIC_SPI 19 IRQ_TYPE_LEVEL_HIGH>;
++ interrupt-names = "dcvsh-irq-0",
++ "dcvsh-irq-1",
++ "dcvsh-irq-2";
++
+ clocks = <&rpmhcc RPMH_CXO_CLK>, <&gcc GCC_GPLL0>;
+ clock-names = "xo", "alternate";
+ #freq-domain-cells = <1>;
+--
+2.42.0
+
--- /dev/null
+From 2a4076b88121ad10d1d8b2ac66e06c384dc561a3 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sun, 27 Aug 2023 01:19:11 +0300
+Subject: arm64: dts: qcom: sdm845-mtp: fix WiFi configuration
+
+From: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
+
+[ Upstream commit b33868a52f342d9b1f20aa5bffe40cbd69bd0a4b ]
+
+Enable the host-cap-8bit quirk on this device. It is required for the
+WiFi to function properly.
+
+Fixes: 022bccb840b7 ("arm64: dts: sdm845: Add WCN3990 WLAN module device node")
+Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
+Link: https://lore.kernel.org/r/20230826221915.846937-2-dmitry.baryshkov@linaro.org
+Signed-off-by: Bjorn Andersson <andersson@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ arch/arm64/boot/dts/qcom/sdm845-mtp.dts | 2 ++
+ 1 file changed, 2 insertions(+)
+
+diff --git a/arch/arm64/boot/dts/qcom/sdm845-mtp.dts b/arch/arm64/boot/dts/qcom/sdm845-mtp.dts
+index 52dd7a858231e..cf2fad5bcac1b 100644
+--- a/arch/arm64/boot/dts/qcom/sdm845-mtp.dts
++++ b/arch/arm64/boot/dts/qcom/sdm845-mtp.dts
+@@ -572,6 +572,8 @@ &wifi {
+ vdd-1.8-xo-supply = <&vreg_l7a_1p8>;
+ vdd-1.3-rfa-supply = <&vreg_l17a_1p3>;
+ vdd-3.3-ch0-supply = <&vreg_l25a_3p3>;
++
++ qcom,snoc-host-cap-8bit-quirk;
+ };
+
+ /* PINCTRL - additions to nodes defined in sdm845.dtsi */
+--
+2.42.0
+
--- /dev/null
+From 52958aa8fd7da647dbf672f70621ae6a14b5fcf2 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 27 Oct 2023 00:09:56 +0000
+Subject: ASoC: ams-delta.c: use component after check
+
+From: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
+
+[ Upstream commit bd0f7498bc9084d8cccc5484cd004b40f314b763 ]
+
+ static void cx81801_close()
+ {
+ ...
+(A) struct snd_soc_dapm_context *dapm = &component->card->dapm;
+ ...
+(B) if (!component)
+ return;
+ }
+
+(A) uses component before NULL check (B). This patch moves it after (B).
+
+Fixes: d0fdfe34080c ("ASoC: cx20442: replace codec to component")
+Reported-by: Dan Carpenter <dan.carpenter@linaro.org>
+Closes: https://lore.kernel.org/r/3e608474-e99a-4866-ae98-3054a4221f09@moroto.mountain
+Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
+Link: https://lore.kernel.org/r/87ttqdq623.wl-kuninori.morimoto.gx@renesas.com
+Signed-off-by: Mark Brown <broonie@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ sound/soc/ti/ams-delta.c | 4 +++-
+ 1 file changed, 3 insertions(+), 1 deletion(-)
+
+diff --git a/sound/soc/ti/ams-delta.c b/sound/soc/ti/ams-delta.c
+index ecd24d412a9b0..4537ef1b676f5 100644
+--- a/sound/soc/ti/ams-delta.c
++++ b/sound/soc/ti/ams-delta.c
+@@ -303,7 +303,7 @@ static int cx81801_open(struct tty_struct *tty)
+ static void cx81801_close(struct tty_struct *tty)
+ {
+ struct snd_soc_component *component = tty->disc_data;
+- struct snd_soc_dapm_context *dapm = &component->card->dapm;
++ struct snd_soc_dapm_context *dapm;
+
+ del_timer_sync(&cx81801_timer);
+
+@@ -315,6 +315,8 @@ static void cx81801_close(struct tty_struct *tty)
+
+ v253_ops.close(tty);
+
++ dapm = &component->card->dapm;
++
+ /* Revert back to default audio input/output constellation */
+ snd_soc_dapm_mutex_lock(dapm);
+
+--
+2.42.0
+
--- /dev/null
+From 4c56916f378b9946593628dc57d9dc5075a70720 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 12 Oct 2023 21:03:15 +0800
+Subject: ASoC: fsl: Fix PM disable depth imbalance in fsl_easrc_probe
+
+From: Zhang Shurong <zhang_shurong@foxmail.com>
+
+[ Upstream commit 9e630efb5a4af56fdb15aa10405f5cfd3f5f5b83 ]
+
+The pm_runtime_enable will increase power disable depth. Thus
+a pairing decrement is needed on the error handling path to
+keep it balanced according to context. We fix it by calling
+pm_runtime_disable when error returns.
+
+Fixes: 955ac624058f ("ASoC: fsl_easrc: Add EASRC ASoC CPU DAI drivers")
+Signed-off-by: Zhang Shurong <zhang_shurong@foxmail.com>
+Link: https://lore.kernel.org/r/tencent_C0D62E6D89818179A02A04A0C248F0DDC40A@qq.com
+Signed-off-by: Mark Brown <broonie@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ sound/soc/fsl/fsl_easrc.c | 8 ++++++--
+ 1 file changed, 6 insertions(+), 2 deletions(-)
+
+diff --git a/sound/soc/fsl/fsl_easrc.c b/sound/soc/fsl/fsl_easrc.c
+index cf0e10d17dbe3..c7ff48208d005 100644
+--- a/sound/soc/fsl/fsl_easrc.c
++++ b/sound/soc/fsl/fsl_easrc.c
+@@ -1965,17 +1965,21 @@ static int fsl_easrc_probe(struct platform_device *pdev)
+ &fsl_easrc_dai, 1);
+ if (ret) {
+ dev_err(dev, "failed to register ASoC DAI\n");
+- return ret;
++ goto err_pm_disable;
+ }
+
+ ret = devm_snd_soc_register_component(dev, &fsl_asrc_component,
+ NULL, 0);
+ if (ret) {
+ dev_err(&pdev->dev, "failed to register ASoC platform\n");
+- return ret;
++ goto err_pm_disable;
+ }
+
+ return 0;
++
++err_pm_disable:
++ pm_runtime_disable(&pdev->dev);
++ return ret;
+ }
+
+ static int fsl_easrc_remove(struct platform_device *pdev)
+--
+2.42.0
+
--- /dev/null
+From e119dc31cda92cf17e6d5dd7624d77a7dbdfa1ae Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 9 Oct 2023 23:39:43 +0000
+Subject: ASoC: fsl: mpc5200_dma.c: Fix warning of Function parameter or member
+ not described
+
+From: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
+
+[ Upstream commit 4a221b2e3340f4a3c2b414c46c846a26c6caf820 ]
+
+This patch fixes the warnings of "Function parameter or member 'xxx'
+not described".
+
+>> sound/soc/fsl/mpc5200_dma.c:116: warning: Function parameter or member 'component' not described in 'psc_dma_trigger'
+ sound/soc/fsl/mpc5200_dma.c:116: warning: Function parameter or member 'substream' not described in 'psc_dma_trigger'
+ sound/soc/fsl/mpc5200_dma.c:116: warning: Function parameter or member 'cmd' not described in 'psc_dma_trigger'
+
+Reported-by: kernel test robot <lkp@intel.com>
+Closes: https://lore.kernel.org/oe-kbuild-all/202310061914.jJuekdHs-lkp@intel.com/
+Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
+Fixes: 6d1048bc1152 ("ASoC: fsl: mpc5200_dma: remove snd_pcm_ops")
+Link: https://lore.kernel.org/r/87il7fcqm8.wl-kuninori.morimoto.gx@renesas.com
+Signed-off-by: Mark Brown <broonie@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ sound/soc/fsl/mpc5200_dma.c | 3 +++
+ 1 file changed, 3 insertions(+)
+
+diff --git a/sound/soc/fsl/mpc5200_dma.c b/sound/soc/fsl/mpc5200_dma.c
+index 9014978100207..3f7ccae3f6b1a 100644
+--- a/sound/soc/fsl/mpc5200_dma.c
++++ b/sound/soc/fsl/mpc5200_dma.c
+@@ -100,6 +100,9 @@ static irqreturn_t psc_dma_bcom_irq(int irq, void *_psc_dma_stream)
+
+ /**
+ * psc_dma_trigger: start and stop the DMA transfer.
++ * @component: triggered component
++ * @substream: triggered substream
++ * @cmd: triggered command
+ *
+ * This function is called by ALSA to start, stop, pause, and resume the DMA
+ * transfer of data.
+--
+2.42.0
+
--- /dev/null
+From 609ec476cdb15c434068cb193a0696c7d62ea978 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 26 Oct 2023 10:25:58 +0200
+Subject: ASoC: Intel: Skylake: Fix mem leak when parsing UUIDs fails
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Cezary Rojewski <cezary.rojewski@intel.com>
+
+[ Upstream commit 168d97844a61db302dec76d44406e9d4d7106b8e ]
+
+Error path in snd_skl_parse_uuids() shall free last allocated module if
+its instance_id allocation fails.
+
+Fixes: f8e066521192 ("ASoC: Intel: Skylake: Fix uuid_module memory leak in failure case")
+Signed-off-by: Cezary Rojewski <cezary.rojewski@intel.com>
+Signed-off-by: Amadeusz Sławiński <amadeuszx.slawinski@linux.intel.com>
+Link: https://lore.kernel.org/r/20231026082558.1864910-1-amadeuszx.slawinski@linux.intel.com
+Signed-off-by: Mark Brown <broonie@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ sound/soc/intel/skylake/skl-sst-utils.c | 1 +
+ 1 file changed, 1 insertion(+)
+
+diff --git a/sound/soc/intel/skylake/skl-sst-utils.c b/sound/soc/intel/skylake/skl-sst-utils.c
+index 57ea815d3f041..b776c58dcf47a 100644
+--- a/sound/soc/intel/skylake/skl-sst-utils.c
++++ b/sound/soc/intel/skylake/skl-sst-utils.c
+@@ -299,6 +299,7 @@ int snd_skl_parse_uuids(struct sst_dsp *ctx, const struct firmware *fw,
+ module->instance_id = devm_kzalloc(ctx->dev, size, GFP_KERNEL);
+ if (!module->instance_id) {
+ ret = -ENOMEM;
++ kfree(module);
+ goto free_uuid_list;
+ }
+
+--
+2.42.0
+
--- /dev/null
+From fe1be58f7710425d08a491ee2649d44668c0a5eb Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 29 Sep 2023 10:23:47 +0200
+Subject: can: dev: can_put_echo_skb(): don't crash kernel if
+ can_priv::echo_skb is accessed out of bounds
+
+From: Marc Kleine-Budde <mkl@pengutronix.de>
+
+[ Upstream commit 6411959c10fe917288cbb1038886999148560057 ]
+
+If the "struct can_priv::echoo_skb" is accessed out of bounds, this
+would cause a kernel crash. Instead, issue a meaningful warning
+message and return with an error.
+
+Fixes: a6e4bc530403 ("can: make the number of echo skb's configurable")
+Link: https://lore.kernel.org/all/20231005-can-dev-fix-can-restart-v2-5-91b5c1fd922c@pengutronix.de
+Reviewed-by: Vincent Mailhol <mailhol.vincent@wanadoo.fr>
+Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/can/dev/skb.c | 6 +++++-
+ 1 file changed, 5 insertions(+), 1 deletion(-)
+
+diff --git a/drivers/net/can/dev/skb.c b/drivers/net/can/dev/skb.c
+index 61660248c69ef..e59d5cbb644a1 100644
+--- a/drivers/net/can/dev/skb.c
++++ b/drivers/net/can/dev/skb.c
+@@ -42,7 +42,11 @@ int can_put_echo_skb(struct sk_buff *skb, struct net_device *dev,
+ {
+ struct can_priv *priv = netdev_priv(dev);
+
+- BUG_ON(idx >= priv->echo_skb_max);
++ if (idx >= priv->echo_skb_max) {
++ netdev_err(dev, "%s: BUG! Trying to access can_priv::echo_skb out of bounds (%u/max %u)\n",
++ __func__, idx, priv->echo_skb_max);
++ return -EINVAL;
++ }
+
+ /* check flag whether this packet has to be looped back */
+ if (!(dev->flags & IFF_ECHO) ||
+--
+2.42.0
+
--- /dev/null
+From 0fd33d1593eab375917f8b559caea53bac5d0be1 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 28 Sep 2023 21:58:23 +0200
+Subject: can: dev: can_restart(): don't crash kernel if carrier is OK
+
+From: Marc Kleine-Budde <mkl@pengutronix.de>
+
+[ Upstream commit fe5c9940dfd8ba0c73672dddb30acd1b7a11d4c7 ]
+
+During testing, I triggered a can_restart() with the netif carrier
+being OK [1]. The BUG_ON, which checks if the carrier is OK, results
+in a fatal kernel crash. This is neither helpful for debugging nor for
+a production system.
+
+[1] The root cause is a race condition in can_restart() which will be
+fixed in the next patch.
+
+Do not crash the kernel, issue an error message instead, and continue
+restarting the CAN device anyway.
+
+Fixes: 39549eef3587 ("can: CAN Network device driver and Netlink interface")
+Link: https://lore.kernel.org/all/20231005-can-dev-fix-can-restart-v2-1-91b5c1fd922c@pengutronix.de
+Reviewed-by: Vincent Mailhol <mailhol.vincent@wanadoo.fr>
+Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/can/dev/dev.c | 3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+diff --git a/drivers/net/can/dev/dev.c b/drivers/net/can/dev/dev.c
+index e3d840b81357d..ed2841a681d72 100644
+--- a/drivers/net/can/dev/dev.c
++++ b/drivers/net/can/dev/dev.c
+@@ -141,7 +141,8 @@ static void can_restart(struct net_device *dev)
+ struct can_frame *cf;
+ int err;
+
+- BUG_ON(netif_carrier_ok(dev));
++ if (netif_carrier_ok(dev))
++ netdev_err(dev, "Attempt to restart for bus-off recovery, but carrier is OK?\n");
+
+ /* No synchronization needed because the device is bus-off and
+ * no messages can come in or go out.
+--
+2.42.0
+
--- /dev/null
+From 892d069ad88acb25a3552266ae5beca25ab8fcc6 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 29 Sep 2023 10:25:11 +0200
+Subject: can: dev: can_restart(): fix race condition between controller
+ restart and netif_carrier_on()
+
+From: Marc Kleine-Budde <mkl@pengutronix.de>
+
+[ Upstream commit 6841cab8c4504835e4011689cbdb3351dec693fd ]
+
+This race condition was discovered while updating the at91_can driver
+to use can_bus_off(). The following scenario describes how the
+converted at91_can driver would behave.
+
+When a CAN device goes into BUS-OFF state, the driver usually
+stops/resets the CAN device and calls can_bus_off().
+
+This function sets the netif carrier to off, and (if configured by
+user space) schedules a delayed work that calls can_restart() to
+restart the CAN device.
+
+The can_restart() function first checks if the carrier is off and
+triggers an error message if the carrier is OK.
+
+Then it calls the driver's do_set_mode() function to restart the
+device, then it sets the netif carrier to on. There is a race window
+between these two calls.
+
+The at91 CAN controller (observed on the sama5d3, a single core 32 bit
+ARM CPU) has a hardware limitation. If the device goes into bus-off
+while sending a CAN frame, there is no way to abort the sending of
+this frame. After the controller is enabled again, another attempt is
+made to send it.
+
+If the bus is still faulty, the device immediately goes back to the
+bus-off state. The driver calls can_bus_off(), the netif carrier is
+switched off and another can_restart is scheduled. This occurs within
+the race window before the original can_restart() handler marks the
+netif carrier as OK. This would cause the 2nd can_restart() to be
+called with an OK netif carrier, resulting in an error message.
+
+The flow of the 1st can_restart() looks like this:
+
+can_restart()
+ // bail out if netif_carrier is OK
+
+ netif_carrier_ok(dev)
+ priv->do_set_mode(dev, CAN_MODE_START)
+ // enable CAN controller
+ // sama5d3 restarts sending old message
+
+ // CAN devices goes into BUS_OFF, triggers IRQ
+
+// IRQ handler start
+ at91_irq()
+ at91_irq_err_line()
+ can_bus_off()
+ netif_carrier_off()
+ schedule_delayed_work()
+// IRQ handler end
+
+ netif_carrier_on()
+
+The 2nd can_restart() will be called with an OK netif carrier and the
+error message will be printed.
+
+To close the race window, first set the netif carrier to on, then
+restart the controller. In case the restart fails with an error code,
+roll back the netif carrier to off.
+
+Fixes: 39549eef3587 ("can: CAN Network device driver and Netlink interface")
+Link: https://lore.kernel.org/all/20231005-can-dev-fix-can-restart-v2-2-91b5c1fd922c@pengutronix.de
+Reviewed-by: Vincent Mailhol <mailhol.vincent@wanadoo.fr>
+Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/can/dev/dev.c | 7 ++++---
+ 1 file changed, 4 insertions(+), 3 deletions(-)
+
+diff --git a/drivers/net/can/dev/dev.c b/drivers/net/can/dev/dev.c
+index ed2841a681d72..94916f2d24d41 100644
+--- a/drivers/net/can/dev/dev.c
++++ b/drivers/net/can/dev/dev.c
+@@ -166,11 +166,12 @@ static void can_restart(struct net_device *dev)
+ priv->can_stats.restarts++;
+
+ /* Now restart the device */
+- err = priv->do_set_mode(dev, CAN_MODE_START);
+-
+ netif_carrier_on(dev);
+- if (err)
++ err = priv->do_set_mode(dev, CAN_MODE_START);
++ if (err) {
+ netdev_err(dev, "Error %d during restart", err);
++ netif_carrier_off(dev);
++ }
+ }
+
+ static void can_restart_work(struct work_struct *work)
+--
+2.42.0
+
--- /dev/null
+From 593c13d625955550aa7ffa47759e797846efc6df Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 20 Oct 2023 12:57:36 +0000
+Subject: chtls: fix tp->rcv_tstamp initialization
+
+From: Eric Dumazet <edumazet@google.com>
+
+[ Upstream commit 225d9ddbacb102621af6d28ff7bf5a0b4ce249d8 ]
+
+tp->rcv_tstamp should be set to tcp_jiffies, not tcp_time_stamp().
+
+Fixes: cc35c88ae4db ("crypto : chtls - CPL handler definition")
+Signed-off-by: Eric Dumazet <edumazet@google.com>
+Cc: Ayush Sawal <ayush.sawal@chelsio.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/ethernet/chelsio/inline_crypto/chtls/chtls_cm.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/drivers/net/ethernet/chelsio/inline_crypto/chtls/chtls_cm.c b/drivers/net/ethernet/chelsio/inline_crypto/chtls/chtls_cm.c
+index ddfe9208529a5..65d4a39634be4 100644
+--- a/drivers/net/ethernet/chelsio/inline_crypto/chtls/chtls_cm.c
++++ b/drivers/net/ethernet/chelsio/inline_crypto/chtls/chtls_cm.c
+@@ -2260,7 +2260,7 @@ static void chtls_rx_ack(struct sock *sk, struct sk_buff *skb)
+
+ if (tp->snd_una != snd_una) {
+ tp->snd_una = snd_una;
+- tp->rcv_tstamp = tcp_time_stamp(tp);
++ tp->rcv_tstamp = tcp_jiffies32;
+ if (tp->snd_una == tp->snd_nxt &&
+ !csk_flag_nochk(csk, CSK_TX_FAILOVER))
+ csk_reset_flag(csk, CSK_TX_WAIT_IDLE);
+--
+2.42.0
+
--- /dev/null
+From 9683bf7a8a50c0400d177b859a7c6e822941246f Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sun, 1 Oct 2023 20:26:18 +0800
+Subject: clk: imx: imx8mq: correct error handling path
+
+From: Peng Fan <peng.fan@nxp.com>
+
+[ Upstream commit 577ad169966e6e75b10e004389a3f79813e84b5d ]
+
+Avoid memory leak in error handling path. It does not make
+much sense for the SoC without clk driver, to make program behavior
+correct, let's fix it.
+
+Fixes: b80522040cd3 ("clk: imx: Add clock driver for i.MX8MQ CCM")
+Reported-by: kernel test robot <lkp@intel.com>
+Reported-by: Dan Carpenter <error27@gmail.com>
+Closes: https://lore.kernel.org/r/202309240551.e46NllPa-lkp@intel.com/
+Signed-off-by: Peng Fan <peng.fan@nxp.com>
+Link: https://lore.kernel.org/r/20231001122618.194498-1-peng.fan@oss.nxp.com
+Signed-off-by: Abel Vesa <abel.vesa@linaro.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/clk/imx/clk-imx8mq.c | 17 ++++++++++-------
+ 1 file changed, 10 insertions(+), 7 deletions(-)
+
+diff --git a/drivers/clk/imx/clk-imx8mq.c b/drivers/clk/imx/clk-imx8mq.c
+index 83cc2b1c32947..791f6bdd88b8a 100644
+--- a/drivers/clk/imx/clk-imx8mq.c
++++ b/drivers/clk/imx/clk-imx8mq.c
+@@ -288,8 +288,7 @@ static int imx8mq_clocks_probe(struct platform_device *pdev)
+ void __iomem *base;
+ int err;
+
+- clk_hw_data = kzalloc(struct_size(clk_hw_data, hws,
+- IMX8MQ_CLK_END), GFP_KERNEL);
++ clk_hw_data = devm_kzalloc(dev, struct_size(clk_hw_data, hws, IMX8MQ_CLK_END), GFP_KERNEL);
+ if (WARN_ON(!clk_hw_data))
+ return -ENOMEM;
+
+@@ -306,10 +305,12 @@ static int imx8mq_clocks_probe(struct platform_device *pdev)
+ hws[IMX8MQ_CLK_EXT4] = imx_obtain_fixed_clk_hw(np, "clk_ext4");
+
+ np = of_find_compatible_node(NULL, NULL, "fsl,imx8mq-anatop");
+- base = of_iomap(np, 0);
++ base = devm_of_iomap(dev, np, 0, NULL);
+ of_node_put(np);
+- if (WARN_ON(!base))
+- return -ENOMEM;
++ if (WARN_ON(IS_ERR(base))) {
++ err = PTR_ERR(base);
++ goto unregister_hws;
++ }
+
+ hws[IMX8MQ_ARM_PLL_REF_SEL] = imx_clk_hw_mux("arm_pll_ref_sel", base + 0x28, 16, 2, pll_ref_sels, ARRAY_SIZE(pll_ref_sels));
+ hws[IMX8MQ_GPU_PLL_REF_SEL] = imx_clk_hw_mux("gpu_pll_ref_sel", base + 0x18, 16, 2, pll_ref_sels, ARRAY_SIZE(pll_ref_sels));
+@@ -395,8 +396,10 @@ static int imx8mq_clocks_probe(struct platform_device *pdev)
+
+ np = dev->of_node;
+ base = devm_platform_ioremap_resource(pdev, 0);
+- if (WARN_ON(IS_ERR(base)))
+- return PTR_ERR(base);
++ if (WARN_ON(IS_ERR(base))) {
++ err = PTR_ERR(base);
++ goto unregister_hws;
++ }
+
+ /* CORE */
+ hws[IMX8MQ_CLK_A53_DIV] = imx8m_clk_hw_composite_core("arm_a53_div", imx8mq_a53_sels, base + 0x8000);
+--
+2.42.0
+
--- /dev/null
+From d6a6ca157dab879ff2dc40df4966263d55969531 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 12 Sep 2023 17:19:00 +0800
+Subject: clk: imx: imx8qxp: Fix elcdif_pll clock
+
+From: Robert Chiras <robert.chiras@nxp.com>
+
+[ Upstream commit 15cee75dacb82ade710d61bfd536011933ef9bf2 ]
+
+Move the elcdif_pll clock initialization before the lcd_clk, since the
+elcdif_clk needs to be initialized ahead of lcd_clk, being its parent.
+This change fixes issues with the LCD clocks during suspend/resume.
+
+Fixes: babfaa9556d7 ("clk: imx: scu: add more scu clocks")
+Suggested-by: Ranjani Vaidyanathan <ranjani.vaidyanathan@nxp.com>
+Acked-by: Laurentiu Palcu <laurentiu.palcu@nxp.com>
+Signed-off-by: Robert Chiras <robert.chiras@nxp.com>
+Signed-off-by: Peng Fan <peng.fan@nxp.com>
+Reviewed-by: Abel Vesa <abel.vesa@linaro.org>
+Link: https://lore.kernel.org/r/20230912-imx8-clk-v1-v1-2-69a34bcfcae1@nxp.com
+Signed-off-by: Abel Vesa <abel.vesa@linaro.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/clk/imx/clk-imx8qxp.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/drivers/clk/imx/clk-imx8qxp.c b/drivers/clk/imx/clk-imx8qxp.c
+index 40a2efb1329be..32df47c56621a 100644
+--- a/drivers/clk/imx/clk-imx8qxp.c
++++ b/drivers/clk/imx/clk-imx8qxp.c
+@@ -148,10 +148,10 @@ static int imx8qxp_clk_probe(struct platform_device *pdev)
+ imx_clk_scu("adc0_clk", IMX_SC_R_ADC_0, IMX_SC_PM_CLK_PER);
+ imx_clk_scu("adc1_clk", IMX_SC_R_ADC_1, IMX_SC_PM_CLK_PER);
+ imx_clk_scu("pwm_clk", IMX_SC_R_LCD_0_PWM_0, IMX_SC_PM_CLK_PER);
++ imx_clk_scu("elcdif_pll", IMX_SC_R_ELCDIF_PLL, IMX_SC_PM_CLK_PLL);
+ imx_clk_scu2("lcd_clk", lcd_sels, ARRAY_SIZE(lcd_sels), IMX_SC_R_LCD_0, IMX_SC_PM_CLK_PER);
+ imx_clk_scu2("lcd_pxl_clk", lcd_pxl_sels, ARRAY_SIZE(lcd_pxl_sels), IMX_SC_R_LCD_0, IMX_SC_PM_CLK_MISC0);
+ imx_clk_scu("lcd_pxl_bypass_div_clk", IMX_SC_R_LCD_0, IMX_SC_PM_CLK_BYPASS);
+- imx_clk_scu("elcdif_pll", IMX_SC_R_ELCDIF_PLL, IMX_SC_PM_CLK_PLL);
+
+ /* Audio SS */
+ imx_clk_scu("audio_pll0_clk", IMX_SC_R_AUDIO_PLL_0, IMX_SC_PM_CLK_PLL);
+--
+2.42.0
+
--- /dev/null
+From 65b10dc863f9858c9b7ac79af5cc6e849a269591 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 21 Sep 2023 12:23:54 +0300
+Subject: clk: imx: Select MXC_CLK for CLK_IMX8QXP
+
+From: Abel Vesa <abel.vesa@linaro.org>
+
+[ Upstream commit 317e69c49b4ceef8aebb47d771498ccb3571bdf9 ]
+
+If the i.MX8QXP clock provider is built-in but the MXC_CLK is
+built as module, build fails:
+
+aarch64-linux-ld: drivers/clk/imx/clk-imx8-acm.o: in function `imx8_acm_clk_probe':
+clk-imx8-acm.c:(.text+0x3d0): undefined reference to `imx_check_clk_hws'
+
+Fix that by selecting MXC_CLK in case of CLK_IMX8QXP.
+
+Fixes: c2cccb6d0b33 ("clk: imx: add imx8qxp clk driver")
+Closes: https://lore.kernel.org/all/8b77219e-b59e-40f1-96f1-980a0b2debcf@infradead.org/
+Reported-by: Randy Dunlap <rdunlap@infradead.org>
+Reviewed-by: Peng Fan <peng.fan@nxp.com>
+Acked-by: Randy Dunlap <rdunlap@infradead.org>
+Tested-by: Randy Dunlap <rdunlap@infradead.org>
+Signed-off-by: Abel Vesa <abel.vesa@linaro.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/clk/imx/Kconfig | 1 +
+ 1 file changed, 1 insertion(+)
+
+diff --git a/drivers/clk/imx/Kconfig b/drivers/clk/imx/Kconfig
+index 47d9ec3abd2f7..d3d730610cb4f 100644
+--- a/drivers/clk/imx/Kconfig
++++ b/drivers/clk/imx/Kconfig
+@@ -96,5 +96,6 @@ config CLK_IMX8QXP
+ depends on (ARCH_MXC && ARM64) || COMPILE_TEST
+ depends on IMX_SCU && HAVE_ARM_SMCCC
+ select MXC_CLK_SCU
++ select MXC_CLK
+ help
+ Build the driver for IMX8QXP SCU based clocks.
+--
+2.42.0
+
--- /dev/null
+From 5cf3428205b12862d4919d13000062d26026a298 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 5 Oct 2023 17:01:57 +0300
+Subject: clk: keystone: pll: fix a couple NULL vs IS_ERR() checks
+
+From: Dan Carpenter <dan.carpenter@linaro.org>
+
+[ Upstream commit a5d14f8b551eb1551c10053653ee8e27f19672fa ]
+
+The clk_register_divider() and clk_register_mux() functions returns
+error pointers on error but this code checks for NULL. Fix that.
+
+Fixes: b9e0d40c0d83 ("clk: keystone: add Keystone PLL clock driver")
+Signed-off-by: Dan Carpenter <dan.carpenter@linaro.org>
+Link: https://lore.kernel.org/r/d9da4c97-0da9-499f-9a21-1f8e3f148dc1@moroto.mountain
+Signed-off-by: Stephen Boyd <sboyd@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/clk/keystone/pll.c | 15 +++++++++------
+ 1 file changed, 9 insertions(+), 6 deletions(-)
+
+diff --git a/drivers/clk/keystone/pll.c b/drivers/clk/keystone/pll.c
+index ee5c72369334f..6bbdd4705d71f 100644
+--- a/drivers/clk/keystone/pll.c
++++ b/drivers/clk/keystone/pll.c
+@@ -281,12 +281,13 @@ static void __init of_pll_div_clk_init(struct device_node *node)
+
+ clk = clk_register_divider(NULL, clk_name, parent_name, 0, reg, shift,
+ mask, 0, NULL);
+- if (clk) {
+- of_clk_add_provider(node, of_clk_src_simple_get, clk);
+- } else {
++ if (IS_ERR(clk)) {
+ pr_err("%s: error registering divider %s\n", __func__, clk_name);
+ iounmap(reg);
++ return;
+ }
++
++ of_clk_add_provider(node, of_clk_src_simple_get, clk);
+ }
+ CLK_OF_DECLARE(pll_divider_clock, "ti,keystone,pll-divider-clock", of_pll_div_clk_init);
+
+@@ -328,10 +329,12 @@ static void __init of_pll_mux_clk_init(struct device_node *node)
+ clk = clk_register_mux(NULL, clk_name, (const char **)&parents,
+ ARRAY_SIZE(parents) , 0, reg, shift, mask,
+ 0, NULL);
+- if (clk)
+- of_clk_add_provider(node, of_clk_src_simple_get, clk);
+- else
++ if (IS_ERR(clk)) {
+ pr_err("%s: error registering mux %s\n", __func__, clk_name);
++ return;
++ }
++
++ of_clk_add_provider(node, of_clk_src_simple_get, clk);
+ }
+ CLK_OF_DECLARE(pll_mux_clock, "ti,keystone,pll-mux-clock", of_pll_mux_clk_init);
+
+--
+2.42.0
+
--- /dev/null
+From f05e4cb17055005277c77564a9513ee8b9d18d19 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 1 Sep 2023 10:46:58 +0800
+Subject: clk: mediatek: clk-mt2701: Add check for mtk_alloc_clk_data
+
+From: Jiasheng Jiang <jiasheng@iscas.ac.cn>
+
+[ Upstream commit 0d6e24b422a2166a9297a8286ff2e6ab9a5e8cd3 ]
+
+Add the check for the return value of mtk_alloc_clk_data() in order to
+avoid NULL pointer dereference.
+
+Fixes: e9862118272a ("clk: mediatek: Add MT2701 clock support")
+Signed-off-by: Jiasheng Jiang <jiasheng@iscas.ac.cn>
+Link: https://lore.kernel.org/r/20230901024658.23405-1-jiasheng@iscas.ac.cn
+Reviewed-by: Markus Schneider-Pargmann <msp@baylibre.com>
+Reviewed-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
+Signed-off-by: Stephen Boyd <sboyd@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/clk/mediatek/clk-mt2701.c | 8 ++++++++
+ 1 file changed, 8 insertions(+)
+
+diff --git a/drivers/clk/mediatek/clk-mt2701.c b/drivers/clk/mediatek/clk-mt2701.c
+index 695be0f774270..c67cd73aca171 100644
+--- a/drivers/clk/mediatek/clk-mt2701.c
++++ b/drivers/clk/mediatek/clk-mt2701.c
+@@ -675,6 +675,8 @@ static int mtk_topckgen_init(struct platform_device *pdev)
+ return PTR_ERR(base);
+
+ clk_data = mtk_alloc_clk_data(CLK_TOP_NR);
++ if (!clk_data)
++ return -ENOMEM;
+
+ mtk_clk_register_fixed_clks(top_fixed_clks, ARRAY_SIZE(top_fixed_clks),
+ clk_data);
+@@ -742,6 +744,8 @@ static void __init mtk_infrasys_init_early(struct device_node *node)
+
+ if (!infra_clk_data) {
+ infra_clk_data = mtk_alloc_clk_data(CLK_INFRA_NR);
++ if (!infra_clk_data)
++ return;
+
+ for (i = 0; i < CLK_INFRA_NR; i++)
+ infra_clk_data->clks[i] = ERR_PTR(-EPROBE_DEFER);
+@@ -768,6 +772,8 @@ static int mtk_infrasys_init(struct platform_device *pdev)
+
+ if (!infra_clk_data) {
+ infra_clk_data = mtk_alloc_clk_data(CLK_INFRA_NR);
++ if (!infra_clk_data)
++ return -ENOMEM;
+ } else {
+ for (i = 0; i < CLK_INFRA_NR; i++) {
+ if (infra_clk_data->clks[i] == ERR_PTR(-EPROBE_DEFER))
+@@ -896,6 +902,8 @@ static int mtk_pericfg_init(struct platform_device *pdev)
+ return PTR_ERR(base);
+
+ clk_data = mtk_alloc_clk_data(CLK_PERI_NR);
++ if (!clk_data)
++ return -ENOMEM;
+
+ mtk_clk_register_gates(node, peri_clks, ARRAY_SIZE(peri_clks),
+ clk_data);
+--
+2.42.0
+
--- /dev/null
+From 07f6013877e72deff29b426f11ba2d8188126ce5 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 12 Sep 2023 17:34:03 +0800
+Subject: clk: mediatek: clk-mt6765: Add check for mtk_alloc_clk_data
+
+From: Jiasheng Jiang <jiasheng@iscas.ac.cn>
+
+[ Upstream commit b82681042724924ae3ba0f2f2eeec217fa31e830 ]
+
+Add the check for the return value of mtk_alloc_clk_data() in order to
+avoid NULL pointer dereference.
+
+Fixes: 1aca9939bf72 ("clk: mediatek: Add MT6765 clock support")
+Signed-off-by: Jiasheng Jiang <jiasheng@iscas.ac.cn>
+Link: https://lore.kernel.org/r/20230912093407.21505-1-jiasheng@iscas.ac.cn
+Reviewed-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
+Signed-off-by: Stephen Boyd <sboyd@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/clk/mediatek/clk-mt6765.c | 6 ++++++
+ 1 file changed, 6 insertions(+)
+
+diff --git a/drivers/clk/mediatek/clk-mt6765.c b/drivers/clk/mediatek/clk-mt6765.c
+index d77ea5aff2920..17352342b6989 100644
+--- a/drivers/clk/mediatek/clk-mt6765.c
++++ b/drivers/clk/mediatek/clk-mt6765.c
+@@ -785,6 +785,8 @@ static int clk_mt6765_apmixed_probe(struct platform_device *pdev)
+ }
+
+ clk_data = mtk_alloc_clk_data(CLK_APMIXED_NR_CLK);
++ if (!clk_data)
++ return -ENOMEM;
+
+ mtk_clk_register_plls(node, plls, ARRAY_SIZE(plls), clk_data);
+
+@@ -820,6 +822,8 @@ static int clk_mt6765_top_probe(struct platform_device *pdev)
+ }
+
+ clk_data = mtk_alloc_clk_data(CLK_TOP_NR_CLK);
++ if (!clk_data)
++ return -ENOMEM;
+
+ mtk_clk_register_fixed_clks(fixed_clks, ARRAY_SIZE(fixed_clks),
+ clk_data);
+@@ -860,6 +864,8 @@ static int clk_mt6765_ifr_probe(struct platform_device *pdev)
+ }
+
+ clk_data = mtk_alloc_clk_data(CLK_IFR_NR_CLK);
++ if (!clk_data)
++ return -ENOMEM;
+
+ mtk_clk_register_gates(node, ifr_clks, ARRAY_SIZE(ifr_clks),
+ clk_data);
+--
+2.42.0
+
--- /dev/null
+From bd70ccf02e0ec0559e977bc1bd2ddb67ecd80737 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 12 Sep 2023 17:34:04 +0800
+Subject: clk: mediatek: clk-mt6779: Add check for mtk_alloc_clk_data
+
+From: Jiasheng Jiang <jiasheng@iscas.ac.cn>
+
+[ Upstream commit 1f57f78fbacf630430bf954e5a84caafdfea30c0 ]
+
+Add the check for the return value of mtk_alloc_clk_data() in order to
+avoid NULL pointer dereference.
+
+Fixes: 710774e04861 ("clk: mediatek: Add MT6779 clock support")
+Signed-off-by: Jiasheng Jiang <jiasheng@iscas.ac.cn>
+Link: https://lore.kernel.org/r/20230912093407.21505-2-jiasheng@iscas.ac.cn
+Reviewed-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
+Signed-off-by: Stephen Boyd <sboyd@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/clk/mediatek/clk-mt6779.c | 4 ++++
+ 1 file changed, 4 insertions(+)
+
+diff --git a/drivers/clk/mediatek/clk-mt6779.c b/drivers/clk/mediatek/clk-mt6779.c
+index 6e0d3a1667291..cf720651fc536 100644
+--- a/drivers/clk/mediatek/clk-mt6779.c
++++ b/drivers/clk/mediatek/clk-mt6779.c
+@@ -1216,6 +1216,8 @@ static int clk_mt6779_apmixed_probe(struct platform_device *pdev)
+ struct device_node *node = pdev->dev.of_node;
+
+ clk_data = mtk_alloc_clk_data(CLK_APMIXED_NR_CLK);
++ if (!clk_data)
++ return -ENOMEM;
+
+ mtk_clk_register_plls(node, plls, ARRAY_SIZE(plls), clk_data);
+
+@@ -1236,6 +1238,8 @@ static int clk_mt6779_top_probe(struct platform_device *pdev)
+ return PTR_ERR(base);
+
+ clk_data = mtk_alloc_clk_data(CLK_TOP_NR_CLK);
++ if (!clk_data)
++ return -ENOMEM;
+
+ mtk_clk_register_fixed_clks(top_fixed_clks, ARRAY_SIZE(top_fixed_clks),
+ clk_data);
+--
+2.42.0
+
--- /dev/null
+From 8cb7e491e03e9d409ba1d3f8d53ca54b1d3c48cd Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 12 Sep 2023 17:34:05 +0800
+Subject: clk: mediatek: clk-mt6797: Add check for mtk_alloc_clk_data
+
+From: Jiasheng Jiang <jiasheng@iscas.ac.cn>
+
+[ Upstream commit 606f6366a35a3329545e38129804d65ef26ed7d2 ]
+
+Add the check for the return value of mtk_alloc_clk_data() in order to
+avoid NULL pointer dereference.
+
+Fixes: 96596aa06628 ("clk: mediatek: add clk support for MT6797")
+Signed-off-by: Jiasheng Jiang <jiasheng@iscas.ac.cn>
+Link: https://lore.kernel.org/r/20230912093407.21505-3-jiasheng@iscas.ac.cn
+Reviewed-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
+Signed-off-by: Stephen Boyd <sboyd@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/clk/mediatek/clk-mt6797.c | 6 ++++++
+ 1 file changed, 6 insertions(+)
+
+diff --git a/drivers/clk/mediatek/clk-mt6797.c b/drivers/clk/mediatek/clk-mt6797.c
+index 428eb24ffec55..98d456023f4e4 100644
+--- a/drivers/clk/mediatek/clk-mt6797.c
++++ b/drivers/clk/mediatek/clk-mt6797.c
+@@ -391,6 +391,8 @@ static int mtk_topckgen_init(struct platform_device *pdev)
+ return PTR_ERR(base);
+
+ clk_data = mtk_alloc_clk_data(CLK_TOP_NR);
++ if (!clk_data)
++ return -ENOMEM;
+
+ mtk_clk_register_factors(top_fixed_divs, ARRAY_SIZE(top_fixed_divs),
+ clk_data);
+@@ -563,6 +565,8 @@ static void mtk_infrasys_init_early(struct device_node *node)
+
+ if (!infra_clk_data) {
+ infra_clk_data = mtk_alloc_clk_data(CLK_INFRA_NR);
++ if (!infra_clk_data)
++ return;
+
+ for (i = 0; i < CLK_INFRA_NR; i++)
+ infra_clk_data->clks[i] = ERR_PTR(-EPROBE_DEFER);
+@@ -587,6 +591,8 @@ static int mtk_infrasys_init(struct platform_device *pdev)
+
+ if (!infra_clk_data) {
+ infra_clk_data = mtk_alloc_clk_data(CLK_INFRA_NR);
++ if (!infra_clk_data)
++ return -ENOMEM;
+ } else {
+ for (i = 0; i < CLK_INFRA_NR; i++) {
+ if (infra_clk_data->clks[i] == ERR_PTR(-EPROBE_DEFER))
+--
+2.42.0
+
--- /dev/null
+From f8d533ac0c023bfea138a1bc41fb12d3e80882a1 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 12 Sep 2023 17:34:07 +0800
+Subject: clk: mediatek: clk-mt7629: Add check for mtk_alloc_clk_data
+
+From: Jiasheng Jiang <jiasheng@iscas.ac.cn>
+
+[ Upstream commit 2befa515c1bb6cdd33c262b909d93d1973a219aa ]
+
+Add the check for the return value of mtk_alloc_clk_data() in order to
+avoid NULL pointer dereference.
+
+Fixes: 3b5e748615e7 ("clk: mediatek: add clock support for MT7629 SoC")
+Signed-off-by: Jiasheng Jiang <jiasheng@iscas.ac.cn>
+Link: https://lore.kernel.org/r/20230912093407.21505-5-jiasheng@iscas.ac.cn
+Reviewed-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
+Signed-off-by: Stephen Boyd <sboyd@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/clk/mediatek/clk-mt7629.c | 6 ++++++
+ 1 file changed, 6 insertions(+)
+
+diff --git a/drivers/clk/mediatek/clk-mt7629.c b/drivers/clk/mediatek/clk-mt7629.c
+index a0ee079670c7e..f791e53b812ab 100644
+--- a/drivers/clk/mediatek/clk-mt7629.c
++++ b/drivers/clk/mediatek/clk-mt7629.c
+@@ -580,6 +580,8 @@ static int mtk_topckgen_init(struct platform_device *pdev)
+ return PTR_ERR(base);
+
+ clk_data = mtk_alloc_clk_data(CLK_TOP_NR_CLK);
++ if (!clk_data)
++ return -ENOMEM;
+
+ mtk_clk_register_fixed_clks(top_fixed_clks, ARRAY_SIZE(top_fixed_clks),
+ clk_data);
+@@ -603,6 +605,8 @@ static int mtk_infrasys_init(struct platform_device *pdev)
+ struct clk_onecell_data *clk_data;
+
+ clk_data = mtk_alloc_clk_data(CLK_INFRA_NR_CLK);
++ if (!clk_data)
++ return -ENOMEM;
+
+ mtk_clk_register_gates(node, infra_clks, ARRAY_SIZE(infra_clks),
+ clk_data);
+@@ -626,6 +630,8 @@ static int mtk_pericfg_init(struct platform_device *pdev)
+ return PTR_ERR(base);
+
+ clk_data = mtk_alloc_clk_data(CLK_PERI_NR_CLK);
++ if (!clk_data)
++ return -ENOMEM;
+
+ mtk_clk_register_gates(node, peri_clks, ARRAY_SIZE(peri_clks),
+ clk_data);
+--
+2.42.0
+
--- /dev/null
+From 8bfe49196be6c6f670d0b13a82621495aa7bb10f Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 12 Sep 2023 17:34:06 +0800
+Subject: clk: mediatek: clk-mt7629-eth: Add check for mtk_alloc_clk_data
+
+From: Jiasheng Jiang <jiasheng@iscas.ac.cn>
+
+[ Upstream commit 0884393c63cc9a1772f7121a6645ba7bd76feeb9 ]
+
+Add the check for the return value of mtk_alloc_clk_data() in order to
+avoid NULL pointer dereference.
+
+Fixes: 3b5e748615e7 ("clk: mediatek: add clock support for MT7629 SoC")
+Signed-off-by: Jiasheng Jiang <jiasheng@iscas.ac.cn>
+Link: https://lore.kernel.org/r/20230912093407.21505-4-jiasheng@iscas.ac.cn
+Reviewed-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
+Signed-off-by: Stephen Boyd <sboyd@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/clk/mediatek/clk-mt7629-eth.c | 4 ++++
+ 1 file changed, 4 insertions(+)
+
+diff --git a/drivers/clk/mediatek/clk-mt7629-eth.c b/drivers/clk/mediatek/clk-mt7629-eth.c
+index 88279d0ea1a76..3ab7b672f8c70 100644
+--- a/drivers/clk/mediatek/clk-mt7629-eth.c
++++ b/drivers/clk/mediatek/clk-mt7629-eth.c
+@@ -83,6 +83,8 @@ static int clk_mt7629_ethsys_init(struct platform_device *pdev)
+ int r;
+
+ clk_data = mtk_alloc_clk_data(CLK_ETH_NR_CLK);
++ if (!clk_data)
++ return -ENOMEM;
+
+ mtk_clk_register_gates(node, eth_clks, CLK_ETH_NR_CLK, clk_data);
+
+@@ -105,6 +107,8 @@ static int clk_mt7629_sgmiisys_init(struct platform_device *pdev)
+ int r;
+
+ clk_data = mtk_alloc_clk_data(CLK_SGMII_NR_CLK);
++ if (!clk_data)
++ return -ENOMEM;
+
+ mtk_clk_register_gates(node, sgmii_clks[id++], CLK_SGMII_NR_CLK,
+ clk_data);
+--
+2.42.0
+
--- /dev/null
+From 5595f28a9c086eda9a4591e7066e87e4f8f99413 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sat, 23 Sep 2023 15:31:27 +0200
+Subject: clk: npcm7xx: Fix incorrect kfree
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Jonathan Neuschäfer <j.neuschaefer@gmx.net>
+
+[ Upstream commit bbc5080bef4a245106aa8e8d424ba8847ca7c0ca ]
+
+The corresponding allocation is:
+
+> npcm7xx_clk_data = kzalloc(struct_size(npcm7xx_clk_data, hws,
+> NPCM7XX_NUM_CLOCKS), GFP_KERNEL);
+
+... so, kfree should be applied to npcm7xx_clk_data, not
+npcm7xx_clk_data->hws.
+
+Fixes: fcfd14369856 ("clk: npcm7xx: add clock controller")
+Signed-off-by: Jonathan Neuschäfer <j.neuschaefer@gmx.net>
+Link: https://lore.kernel.org/r/20230923133127.1815621-1-j.neuschaefer@gmx.net
+Signed-off-by: Stephen Boyd <sboyd@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/clk/clk-npcm7xx.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/drivers/clk/clk-npcm7xx.c b/drivers/clk/clk-npcm7xx.c
+index e677bb5a784b9..c10f04f9070a5 100644
+--- a/drivers/clk/clk-npcm7xx.c
++++ b/drivers/clk/clk-npcm7xx.c
+@@ -539,7 +539,7 @@ static void __init npcm7xx_clk_init(struct device_node *clk_np)
+ return;
+
+ npcm7xx_init_fail:
+- kfree(npcm7xx_clk_data->hws);
++ kfree(npcm7xx_clk_data);
+ npcm7xx_init_np_err:
+ iounmap(clk_base);
+ npcm7xx_init_error:
+--
+2.42.0
+
--- /dev/null
+From 20b4e82214a052df587655e66af5ec6b94b9a3ea Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 1 Sep 2023 13:06:40 +0530
+Subject: clk: qcom: clk-rcg2: Fix clock rate overflow for high parent
+ frequencies
+
+From: Devi Priya <quic_devipriy@quicinc.com>
+
+[ Upstream commit f7b7d30158cff246667273bd2a62fc93ee0725d2 ]
+
+If the parent clock rate is greater than unsigned long max/2 then
+integer overflow happens when calculating the clock rate on 32-bit systems.
+As RCG2 uses half integer dividers, the clock rate is first being
+multiplied by 2 which will overflow the unsigned long max value.
+Hence, replace the common pattern of doing 64-bit multiplication
+and then a do_div() call with simpler mult_frac call.
+
+Fixes: bcd61c0f535a ("clk: qcom: Add support for root clock generators (RCGs)")
+Signed-off-by: Devi Priya <quic_devipriy@quicinc.com>
+Reviewed-by: Marijn Suijten <marijn.suijten@somainline.org>
+Link: https://lore.kernel.org/r/20230901073640.4973-1-quic_devipriy@quicinc.com
+[bjorn: Also drop unnecessary {} around single statements]
+Signed-off-by: Bjorn Andersson <andersson@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/clk/qcom/clk-rcg2.c | 14 ++++----------
+ 1 file changed, 4 insertions(+), 10 deletions(-)
+
+diff --git a/drivers/clk/qcom/clk-rcg2.c b/drivers/clk/qcom/clk-rcg2.c
+index c3823cc32edc6..f3c225ed57377 100644
+--- a/drivers/clk/qcom/clk-rcg2.c
++++ b/drivers/clk/qcom/clk-rcg2.c
+@@ -148,17 +148,11 @@ static int clk_rcg2_set_parent(struct clk_hw *hw, u8 index)
+ static unsigned long
+ calc_rate(unsigned long rate, u32 m, u32 n, u32 mode, u32 hid_div)
+ {
+- if (hid_div) {
+- rate *= 2;
+- rate /= hid_div + 1;
+- }
++ if (hid_div)
++ rate = mult_frac(rate, 2, hid_div + 1);
+
+- if (mode) {
+- u64 tmp = rate;
+- tmp *= m;
+- do_div(tmp, n);
+- rate = tmp;
+- }
++ if (mode)
++ rate = mult_frac(rate, m, n);
+
+ return rate;
+ }
+--
+2.42.0
+
--- /dev/null
+From 0ee71b3a9b744bccc836be50094481e8f7c39c41 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 20 Oct 2023 11:49:31 +0530
+Subject: clk: qcom: config IPQ_APSS_6018 should depend on QCOM_SMEM
+
+From: Varadarajan Narayanan <quic_varada@quicinc.com>
+
+[ Upstream commit 6a15647d0adc686226045e8046369f34d6ab03ed ]
+
+The config IPQ_APSS_6018 should depend on QCOM_SMEM, to
+avoid the following error reported by 'kernel test robot'
+
+ loongarch64-linux-ld: drivers/clk/qcom/apss-ipq6018.o: in function `apss_ipq6018_probe':
+ >> apss-ipq6018.c:(.text+0xd0): undefined reference to `qcom_smem_get_soc_id'
+
+Fixes: 5e77b4ef1b19 ("clk: qcom: Add ipq6018 apss clock controller")
+Reported-by: kernel test robot <yujie.liu@intel.com>
+Closes: https://lore.kernel.org/r/202310181650.g8THtfsm-lkp@intel.com/
+Signed-off-by: Varadarajan Narayanan <quic_varada@quicinc.com>
+Link: https://lore.kernel.org/r/f4c4d65a7cb71e807d6d472c63c7718408c8f5f0.1697781921.git.quic_varada@quicinc.com
+Signed-off-by: Bjorn Andersson <andersson@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/clk/qcom/Kconfig | 1 +
+ 1 file changed, 1 insertion(+)
+
+diff --git a/drivers/clk/qcom/Kconfig b/drivers/clk/qcom/Kconfig
+index 6ba86cffc4135..4c8bb23ca7304 100644
+--- a/drivers/clk/qcom/Kconfig
++++ b/drivers/clk/qcom/Kconfig
+@@ -127,6 +127,7 @@ config IPQ_APSS_6018
+ tristate "IPQ APSS Clock Controller"
+ select IPQ_APSS_PLL
+ depends on QCOM_APCS_IPC || COMPILE_TEST
++ depends on QCOM_SMEM
+ help
+ Support for APSS clock controller on IPQ platforms. The
+ APSS clock controller manages the Mux and enable block that feeds the
+--
+2.42.0
+
--- /dev/null
+From 6deb0edb736574297922aed9e13ccedb386f1b4d Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 28 Dec 2021 07:54:12 +0300
+Subject: clk: qcom: gcc-msm8996: drop unsupported clock sources
+
+From: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
+
+[ Upstream commit b554a687b4971ae137e92ee3feddc38e85a38d60 ]
+
+In preparation of updating the msm8996 gcc driver, drop all unsupported
+GPLL sources (gpll1/gpll1_early_div, gpll2/gpll2_early and gpll3).
+Downstream kernel also does not provide support for these GPLL sources,
+so it is safe to drop them.
+
+Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
+Signed-off-by: Bjorn Andersson <bjorn.andersson@linaro.org>
+Link: https://lore.kernel.org/r/20211228045415.20543-14-dmitry.baryshkov@linaro.org
+Stable-dep-of: 4afda5f6bcdf ("clk: qcom: gcc-msm8996: Remove RPM bus clocks")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/clk/qcom/gcc-msm8996.c | 55 ++++------------------------------
+ 1 file changed, 6 insertions(+), 49 deletions(-)
+
+diff --git a/drivers/clk/qcom/gcc-msm8996.c b/drivers/clk/qcom/gcc-msm8996.c
+index d95814025c65e..4c85b3935a819 100644
+--- a/drivers/clk/qcom/gcc-msm8996.c
++++ b/drivers/clk/qcom/gcc-msm8996.c
+@@ -27,15 +27,10 @@
+ enum {
+ P_XO,
+ P_GPLL0,
+- P_GPLL2,
+- P_GPLL3,
+- P_GPLL1,
+- P_GPLL2_EARLY,
+ P_GPLL0_EARLY_DIV,
+ P_SLEEP_CLK,
+ P_GPLL4,
+ P_AUD_REF_CLK,
+- P_GPLL1_EARLY_DIV
+ };
+
+ static const struct parent_map gcc_sleep_clk_map[] = {
+@@ -130,44 +125,6 @@ static const char * const gcc_xo_gpll0_gpll4_gpll0_early_div[] = {
+ "gpll0_early_div"
+ };
+
+-static const struct parent_map gcc_xo_gpll0_gpll1_early_div_gpll1_gpll4_gpll0_early_div_map[] = {
+- { P_XO, 0 },
+- { P_GPLL0, 1 },
+- { P_GPLL1_EARLY_DIV, 3 },
+- { P_GPLL1, 4 },
+- { P_GPLL4, 5 },
+- { P_GPLL0_EARLY_DIV, 6 }
+-};
+-
+-static const char * const gcc_xo_gpll0_gpll1_early_div_gpll1_gpll4_gpll0_early_div[] = {
+- "xo",
+- "gpll0",
+- "gpll1_early_div",
+- "gpll1",
+- "gpll4",
+- "gpll0_early_div"
+-};
+-
+-static const struct parent_map gcc_xo_gpll0_gpll2_gpll3_gpll1_gpll2_early_gpll0_early_div_map[] = {
+- { P_XO, 0 },
+- { P_GPLL0, 1 },
+- { P_GPLL2, 2 },
+- { P_GPLL3, 3 },
+- { P_GPLL1, 4 },
+- { P_GPLL2_EARLY, 5 },
+- { P_GPLL0_EARLY_DIV, 6 }
+-};
+-
+-static const char * const gcc_xo_gpll0_gpll2_gpll3_gpll1_gpll2_early_gpll0_early_div[] = {
+- "xo",
+- "gpll0",
+- "gpll2",
+- "gpll3",
+- "gpll1",
+- "gpll2_early",
+- "gpll0_early_div"
+-};
+-
+ static struct clk_fixed_factor xo = {
+ .mult = 1,
+ .div = 1,
+@@ -285,12 +242,12 @@ static const struct freq_tbl ftbl_system_noc_clk_src[] = {
+ static struct clk_rcg2 system_noc_clk_src = {
+ .cmd_rcgr = 0x0401c,
+ .hid_width = 5,
+- .parent_map = gcc_xo_gpll0_gpll2_gpll3_gpll1_gpll2_early_gpll0_early_div_map,
++ .parent_map = gcc_xo_gpll0_gpll0_early_div_map,
+ .freq_tbl = ftbl_system_noc_clk_src,
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "system_noc_clk_src",
+- .parent_names = gcc_xo_gpll0_gpll2_gpll3_gpll1_gpll2_early_gpll0_early_div,
+- .num_parents = ARRAY_SIZE(gcc_xo_gpll0_gpll2_gpll3_gpll1_gpll2_early_gpll0_early_div),
++ .parent_names = gcc_xo_gpll0_gpll0_early_div,
++ .num_parents = ARRAY_SIZE(gcc_xo_gpll0_gpll0_early_div),
+ .ops = &clk_rcg2_ops,
+ },
+ };
+@@ -1257,12 +1214,12 @@ static const struct freq_tbl ftbl_qspi_ser_clk_src[] = {
+ static struct clk_rcg2 qspi_ser_clk_src = {
+ .cmd_rcgr = 0x8b00c,
+ .hid_width = 5,
+- .parent_map = gcc_xo_gpll0_gpll1_early_div_gpll1_gpll4_gpll0_early_div_map,
++ .parent_map = gcc_xo_gpll0_gpll4_gpll0_early_div_map,
+ .freq_tbl = ftbl_qspi_ser_clk_src,
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "qspi_ser_clk_src",
+- .parent_names = gcc_xo_gpll0_gpll1_early_div_gpll1_gpll4_gpll0_early_div,
+- .num_parents = ARRAY_SIZE(gcc_xo_gpll0_gpll1_early_div_gpll1_gpll4_gpll0_early_div),
++ .parent_names = gcc_xo_gpll0_gpll4_gpll0_early_div,
++ .num_parents = ARRAY_SIZE(gcc_xo_gpll0_gpll4_gpll0_early_div),
+ .ops = &clk_rcg2_ops,
+ },
+ };
+--
+2.42.0
+
--- /dev/null
+From 2a8dabd8d0b8c34e0d9370ba081e1277d05f94e1 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 28 Dec 2021 07:54:13 +0300
+Subject: clk: qcom: gcc-msm8996: move clock parent tables down
+
+From: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
+
+[ Upstream commit 1a2789cff03ccdeb70084157387f4a7bf4d2099f ]
+
+Move clock parent tables down, after the GPLL declrataions, so that we
+can use gpll hw clock fields in the next commit.
+
+Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
+Reviewed-by: Marijn Suijten <marijn.suijten@somainline.org>
+Reviewed-by: Stephen Boyd <sboyd@kernel.org>
+Signed-off-by: Bjorn Andersson <bjorn.andersson@linaro.org>
+Link: https://lore.kernel.org/r/20211228045415.20543-15-dmitry.baryshkov@linaro.org
+Stable-dep-of: 4afda5f6bcdf ("clk: qcom: gcc-msm8996: Remove RPM bus clocks")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/clk/qcom/gcc-msm8996.c | 184 ++++++++++++++++-----------------
+ 1 file changed, 92 insertions(+), 92 deletions(-)
+
+diff --git a/drivers/clk/qcom/gcc-msm8996.c b/drivers/clk/qcom/gcc-msm8996.c
+index 4c85b3935a819..8531f2f3665fe 100644
+--- a/drivers/clk/qcom/gcc-msm8996.c
++++ b/drivers/clk/qcom/gcc-msm8996.c
+@@ -33,98 +33,6 @@ enum {
+ P_AUD_REF_CLK,
+ };
+
+-static const struct parent_map gcc_sleep_clk_map[] = {
+- { P_SLEEP_CLK, 5 }
+-};
+-
+-static const char * const gcc_sleep_clk[] = {
+- "sleep_clk"
+-};
+-
+-static const struct parent_map gcc_xo_gpll0_map[] = {
+- { P_XO, 0 },
+- { P_GPLL0, 1 }
+-};
+-
+-static const char * const gcc_xo_gpll0[] = {
+- "xo",
+- "gpll0"
+-};
+-
+-static const struct parent_map gcc_xo_sleep_clk_map[] = {
+- { P_XO, 0 },
+- { P_SLEEP_CLK, 5 }
+-};
+-
+-static const char * const gcc_xo_sleep_clk[] = {
+- "xo",
+- "sleep_clk"
+-};
+-
+-static const struct parent_map gcc_xo_gpll0_gpll0_early_div_map[] = {
+- { P_XO, 0 },
+- { P_GPLL0, 1 },
+- { P_GPLL0_EARLY_DIV, 6 }
+-};
+-
+-static const char * const gcc_xo_gpll0_gpll0_early_div[] = {
+- "xo",
+- "gpll0",
+- "gpll0_early_div"
+-};
+-
+-static const struct parent_map gcc_xo_gpll0_gpll4_map[] = {
+- { P_XO, 0 },
+- { P_GPLL0, 1 },
+- { P_GPLL4, 5 }
+-};
+-
+-static const char * const gcc_xo_gpll0_gpll4[] = {
+- "xo",
+- "gpll0",
+- "gpll4"
+-};
+-
+-static const struct parent_map gcc_xo_gpll0_aud_ref_clk_map[] = {
+- { P_XO, 0 },
+- { P_GPLL0, 1 },
+- { P_AUD_REF_CLK, 2 }
+-};
+-
+-static const char * const gcc_xo_gpll0_aud_ref_clk[] = {
+- "xo",
+- "gpll0",
+- "aud_ref_clk"
+-};
+-
+-static const struct parent_map gcc_xo_gpll0_sleep_clk_gpll0_early_div_map[] = {
+- { P_XO, 0 },
+- { P_GPLL0, 1 },
+- { P_SLEEP_CLK, 5 },
+- { P_GPLL0_EARLY_DIV, 6 }
+-};
+-
+-static const char * const gcc_xo_gpll0_sleep_clk_gpll0_early_div[] = {
+- "xo",
+- "gpll0",
+- "sleep_clk",
+- "gpll0_early_div"
+-};
+-
+-static const struct parent_map gcc_xo_gpll0_gpll4_gpll0_early_div_map[] = {
+- { P_XO, 0 },
+- { P_GPLL0, 1 },
+- { P_GPLL4, 5 },
+- { P_GPLL0_EARLY_DIV, 6 }
+-};
+-
+-static const char * const gcc_xo_gpll0_gpll4_gpll0_early_div[] = {
+- "xo",
+- "gpll0",
+- "gpll4",
+- "gpll0_early_div"
+-};
+-
+ static struct clk_fixed_factor xo = {
+ .mult = 1,
+ .div = 1,
+@@ -229,6 +137,98 @@ static struct clk_alpha_pll_postdiv gpll4 = {
+ },
+ };
+
++static const struct parent_map gcc_sleep_clk_map[] = {
++ { P_SLEEP_CLK, 5 }
++};
++
++static const char * const gcc_sleep_clk[] = {
++ "sleep_clk"
++};
++
++static const struct parent_map gcc_xo_gpll0_map[] = {
++ { P_XO, 0 },
++ { P_GPLL0, 1 }
++};
++
++static const char * const gcc_xo_gpll0[] = {
++ "xo",
++ "gpll0"
++};
++
++static const struct parent_map gcc_xo_sleep_clk_map[] = {
++ { P_XO, 0 },
++ { P_SLEEP_CLK, 5 }
++};
++
++static const char * const gcc_xo_sleep_clk[] = {
++ "xo",
++ "sleep_clk"
++};
++
++static const struct parent_map gcc_xo_gpll0_gpll0_early_div_map[] = {
++ { P_XO, 0 },
++ { P_GPLL0, 1 },
++ { P_GPLL0_EARLY_DIV, 6 }
++};
++
++static const char * const gcc_xo_gpll0_gpll0_early_div[] = {
++ "xo",
++ "gpll0",
++ "gpll0_early_div"
++};
++
++static const struct parent_map gcc_xo_gpll0_gpll4_map[] = {
++ { P_XO, 0 },
++ { P_GPLL0, 1 },
++ { P_GPLL4, 5 }
++};
++
++static const char * const gcc_xo_gpll0_gpll4[] = {
++ "xo",
++ "gpll0",
++ "gpll4"
++};
++
++static const struct parent_map gcc_xo_gpll0_aud_ref_clk_map[] = {
++ { P_XO, 0 },
++ { P_GPLL0, 1 },
++ { P_AUD_REF_CLK, 2 }
++};
++
++static const char * const gcc_xo_gpll0_aud_ref_clk[] = {
++ "xo",
++ "gpll0",
++ "aud_ref_clk"
++};
++
++static const struct parent_map gcc_xo_gpll0_sleep_clk_gpll0_early_div_map[] = {
++ { P_XO, 0 },
++ { P_GPLL0, 1 },
++ { P_SLEEP_CLK, 5 },
++ { P_GPLL0_EARLY_DIV, 6 }
++};
++
++static const char * const gcc_xo_gpll0_sleep_clk_gpll0_early_div[] = {
++ "xo",
++ "gpll0",
++ "sleep_clk",
++ "gpll0_early_div"
++};
++
++static const struct parent_map gcc_xo_gpll0_gpll4_gpll0_early_div_map[] = {
++ { P_XO, 0 },
++ { P_GPLL0, 1 },
++ { P_GPLL4, 5 },
++ { P_GPLL0_EARLY_DIV, 6 }
++};
++
++static const char * const gcc_xo_gpll0_gpll4_gpll0_early_div[] = {
++ "xo",
++ "gpll0",
++ "gpll4",
++ "gpll0_early_div"
++};
++
+ static const struct freq_tbl ftbl_system_noc_clk_src[] = {
+ F(19200000, P_XO, 1, 0, 0),
+ F(50000000, P_GPLL0_EARLY_DIV, 6, 0, 0),
+--
+2.42.0
+
--- /dev/null
+From 783e6719b00d27745f10d2aeb57ad31cbeeeb7c7 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 31 Aug 2023 11:39:14 +0200
+Subject: clk: qcom: gcc-msm8996: Remove RPM bus clocks
+
+From: Konrad Dybcio <konrad.dybcio@linaro.org>
+
+[ Upstream commit 4afda5f6bcdf673ef2556fcfa458daf3a5a648d8 ]
+
+The GCC driver contains clocks that are owned (meaning configured and
+scaled) by the RPM core.
+
+Remove them from Linux to stop interjecting the RPM's logic.
+
+Fixes: b1e010c0730a ("clk: qcom: Add MSM8996 Global Clock Control (GCC) driver")
+Signed-off-by: Konrad Dybcio <konrad.dybcio@linaro.org>
+Reviewed-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
+Tested-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
+Link: https://lore.kernel.org/r/20230830-topic-rpmbusclocks8996gcc-v1-1-9e99bedcdc3b@linaro.org
+Signed-off-by: Bjorn Andersson <andersson@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/clk/qcom/gcc-msm8996.c | 237 +--------------------------------
+ 1 file changed, 5 insertions(+), 232 deletions(-)
+
+diff --git a/drivers/clk/qcom/gcc-msm8996.c b/drivers/clk/qcom/gcc-msm8996.c
+index 6b36024583b4a..2d79a73da1055 100644
+--- a/drivers/clk/qcom/gcc-msm8996.c
++++ b/drivers/clk/qcom/gcc-msm8996.c
+@@ -245,71 +245,6 @@ static const struct clk_parent_data gcc_xo_gpll0_gpll4_gpll0_early_div[] = {
+ { .hw = &gpll0_early_div.hw }
+ };
+
+-static const struct freq_tbl ftbl_system_noc_clk_src[] = {
+- F(19200000, P_XO, 1, 0, 0),
+- F(50000000, P_GPLL0_EARLY_DIV, 6, 0, 0),
+- F(100000000, P_GPLL0, 6, 0, 0),
+- F(150000000, P_GPLL0, 4, 0, 0),
+- F(200000000, P_GPLL0, 3, 0, 0),
+- F(240000000, P_GPLL0, 2.5, 0, 0),
+- { }
+-};
+-
+-static struct clk_rcg2 system_noc_clk_src = {
+- .cmd_rcgr = 0x0401c,
+- .hid_width = 5,
+- .parent_map = gcc_xo_gpll0_gpll0_early_div_map,
+- .freq_tbl = ftbl_system_noc_clk_src,
+- .clkr.hw.init = &(struct clk_init_data){
+- .name = "system_noc_clk_src",
+- .parent_data = gcc_xo_gpll0_gpll0_early_div,
+- .num_parents = ARRAY_SIZE(gcc_xo_gpll0_gpll0_early_div),
+- .ops = &clk_rcg2_ops,
+- },
+-};
+-
+-static const struct freq_tbl ftbl_config_noc_clk_src[] = {
+- F(19200000, P_XO, 1, 0, 0),
+- F(37500000, P_GPLL0, 16, 0, 0),
+- F(75000000, P_GPLL0, 8, 0, 0),
+- { }
+-};
+-
+-static struct clk_rcg2 config_noc_clk_src = {
+- .cmd_rcgr = 0x0500c,
+- .hid_width = 5,
+- .parent_map = gcc_xo_gpll0_map,
+- .freq_tbl = ftbl_config_noc_clk_src,
+- .clkr.hw.init = &(struct clk_init_data){
+- .name = "config_noc_clk_src",
+- .parent_data = gcc_xo_gpll0,
+- .num_parents = ARRAY_SIZE(gcc_xo_gpll0),
+- .ops = &clk_rcg2_ops,
+- },
+-};
+-
+-static const struct freq_tbl ftbl_periph_noc_clk_src[] = {
+- F(19200000, P_XO, 1, 0, 0),
+- F(37500000, P_GPLL0, 16, 0, 0),
+- F(50000000, P_GPLL0, 12, 0, 0),
+- F(75000000, P_GPLL0, 8, 0, 0),
+- F(100000000, P_GPLL0, 6, 0, 0),
+- { }
+-};
+-
+-static struct clk_rcg2 periph_noc_clk_src = {
+- .cmd_rcgr = 0x06014,
+- .hid_width = 5,
+- .parent_map = gcc_xo_gpll0_map,
+- .freq_tbl = ftbl_periph_noc_clk_src,
+- .clkr.hw.init = &(struct clk_init_data){
+- .name = "periph_noc_clk_src",
+- .parent_data = gcc_xo_gpll0,
+- .num_parents = ARRAY_SIZE(gcc_xo_gpll0),
+- .ops = &clk_rcg2_ops,
+- },
+-};
+-
+ static const struct freq_tbl ftbl_usb30_master_clk_src[] = {
+ F(19200000, P_XO, 1, 0, 0),
+ F(120000000, P_GPLL0, 5, 0, 0),
+@@ -1298,11 +1233,7 @@ static struct clk_branch gcc_mmss_noc_cfg_ahb_clk = {
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_mmss_noc_cfg_ahb_clk",
+- .parent_hws = (const struct clk_hw*[]){
+- &config_noc_clk_src.clkr.hw,
+- },
+- .num_parents = 1,
+- .flags = CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED,
++ .flags = CLK_IGNORE_UNUSED,
+ .ops = &clk_branch2_ops,
+ },
+ },
+@@ -1465,11 +1396,6 @@ static struct clk_branch gcc_usb_phy_cfg_ahb2phy_clk = {
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_usb_phy_cfg_ahb2phy_clk",
+- .parent_hws = (const struct clk_hw*[]){
+- &periph_noc_clk_src.clkr.hw,
+- },
+- .num_parents = 1,
+- .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+@@ -1499,11 +1425,6 @@ static struct clk_branch gcc_sdcc1_ahb_clk = {
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_sdcc1_ahb_clk",
+- .parent_hws = (const struct clk_hw*[]){
+- &periph_noc_clk_src.clkr.hw,
+- },
+- .num_parents = 1,
+- .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+@@ -1550,11 +1471,6 @@ static struct clk_branch gcc_sdcc2_ahb_clk = {
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_sdcc2_ahb_clk",
+- .parent_hws = (const struct clk_hw*[]){
+- &periph_noc_clk_src.clkr.hw,
+- },
+- .num_parents = 1,
+- .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+@@ -1584,11 +1500,6 @@ static struct clk_branch gcc_sdcc3_ahb_clk = {
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_sdcc3_ahb_clk",
+- .parent_hws = (const struct clk_hw*[]){
+- &periph_noc_clk_src.clkr.hw,
+- },
+- .num_parents = 1,
+- .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+@@ -1618,11 +1529,6 @@ static struct clk_branch gcc_sdcc4_ahb_clk = {
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_sdcc4_ahb_clk",
+- .parent_hws = (const struct clk_hw*[]){
+- &periph_noc_clk_src.clkr.hw,
+- },
+- .num_parents = 1,
+- .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+@@ -1636,11 +1542,6 @@ static struct clk_branch gcc_blsp1_ahb_clk = {
+ .enable_mask = BIT(17),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_blsp1_ahb_clk",
+- .parent_hws = (const struct clk_hw*[]){
+- &periph_noc_clk_src.clkr.hw,
+- },
+- .num_parents = 1,
+- .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+@@ -1978,11 +1879,6 @@ static struct clk_branch gcc_blsp2_ahb_clk = {
+ .enable_mask = BIT(15),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_blsp2_ahb_clk",
+- .parent_hws = (const struct clk_hw*[]){
+- &periph_noc_clk_src.clkr.hw,
+- },
+- .num_parents = 1,
+- .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+@@ -2319,11 +2215,6 @@ static struct clk_branch gcc_pdm_ahb_clk = {
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_pdm_ahb_clk",
+- .parent_hws = (const struct clk_hw*[]){
+- &periph_noc_clk_src.clkr.hw,
+- },
+- .num_parents = 1,
+- .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+@@ -2354,11 +2245,6 @@ static struct clk_branch gcc_prng_ahb_clk = {
+ .enable_mask = BIT(13),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_prng_ahb_clk",
+- .parent_hws = (const struct clk_hw*[]){
+- &config_noc_clk_src.clkr.hw,
+- },
+- .num_parents = 1,
+- .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+@@ -2371,11 +2257,6 @@ static struct clk_branch gcc_tsif_ahb_clk = {
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_tsif_ahb_clk",
+- .parent_hws = (const struct clk_hw*[]){
+- &periph_noc_clk_src.clkr.hw,
+- },
+- .num_parents = 1,
+- .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+@@ -2423,11 +2304,6 @@ static struct clk_branch gcc_boot_rom_ahb_clk = {
+ .enable_mask = BIT(10),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_boot_rom_ahb_clk",
+- .parent_hws = (const struct clk_hw*[]){
+- &config_noc_clk_src.clkr.hw,
+- },
+- .num_parents = 1,
+- .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+@@ -2521,11 +2397,6 @@ static struct clk_branch gcc_pcie_0_slv_axi_clk = {
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_pcie_0_slv_axi_clk",
+- .parent_hws = (const struct clk_hw*[]){
+- &system_noc_clk_src.clkr.hw,
+- },
+- .num_parents = 1,
+- .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+@@ -2538,11 +2409,6 @@ static struct clk_branch gcc_pcie_0_mstr_axi_clk = {
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_pcie_0_mstr_axi_clk",
+- .parent_hws = (const struct clk_hw*[]){
+- &system_noc_clk_src.clkr.hw,
+- },
+- .num_parents = 1,
+- .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+@@ -2555,11 +2421,6 @@ static struct clk_branch gcc_pcie_0_cfg_ahb_clk = {
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_pcie_0_cfg_ahb_clk",
+- .parent_hws = (const struct clk_hw*[]){
+- &config_noc_clk_src.clkr.hw,
+- },
+- .num_parents = 1,
+- .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+@@ -2607,11 +2468,6 @@ static struct clk_branch gcc_pcie_1_slv_axi_clk = {
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_pcie_1_slv_axi_clk",
+- .parent_hws = (const struct clk_hw*[]){
+- &system_noc_clk_src.clkr.hw,
+- },
+- .num_parents = 1,
+- .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+@@ -2624,11 +2480,6 @@ static struct clk_branch gcc_pcie_1_mstr_axi_clk = {
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_pcie_1_mstr_axi_clk",
+- .parent_hws = (const struct clk_hw*[]){
+- &system_noc_clk_src.clkr.hw,
+- },
+- .num_parents = 1,
+- .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+@@ -2641,11 +2492,6 @@ static struct clk_branch gcc_pcie_1_cfg_ahb_clk = {
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_pcie_1_cfg_ahb_clk",
+- .parent_hws = (const struct clk_hw*[]){
+- &config_noc_clk_src.clkr.hw,
+- },
+- .num_parents = 1,
+- .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+@@ -2693,11 +2539,6 @@ static struct clk_branch gcc_pcie_2_slv_axi_clk = {
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_pcie_2_slv_axi_clk",
+- .parent_hws = (const struct clk_hw*[]){
+- &system_noc_clk_src.clkr.hw,
+- },
+- .num_parents = 1,
+- .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+@@ -2710,11 +2551,6 @@ static struct clk_branch gcc_pcie_2_mstr_axi_clk = {
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_pcie_2_mstr_axi_clk",
+- .parent_hws = (const struct clk_hw*[]){
+- &system_noc_clk_src.clkr.hw,
+- },
+- .num_parents = 1,
+- .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+@@ -2727,11 +2563,6 @@ static struct clk_branch gcc_pcie_2_cfg_ahb_clk = {
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_pcie_2_cfg_ahb_clk",
+- .parent_hws = (const struct clk_hw*[]){
+- &config_noc_clk_src.clkr.hw,
+- },
+- .num_parents = 1,
+- .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+@@ -2779,11 +2610,6 @@ static struct clk_branch gcc_pcie_phy_cfg_ahb_clk = {
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_pcie_phy_cfg_ahb_clk",
+- .parent_hws = (const struct clk_hw*[]){
+- &config_noc_clk_src.clkr.hw,
+- },
+- .num_parents = 1,
+- .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+@@ -2830,11 +2656,6 @@ static struct clk_branch gcc_ufs_ahb_clk = {
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_ufs_ahb_clk",
+- .parent_hws = (const struct clk_hw*[]){
+- &config_noc_clk_src.clkr.hw,
+- },
+- .num_parents = 1,
+- .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+@@ -3061,11 +2882,7 @@ static struct clk_branch gcc_aggre0_snoc_axi_clk = {
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_aggre0_snoc_axi_clk",
+- .parent_hws = (const struct clk_hw*[]){
+- &system_noc_clk_src.clkr.hw,
+- },
+- .num_parents = 1,
+- .flags = CLK_SET_RATE_PARENT | CLK_IS_CRITICAL,
++ .flags = CLK_IS_CRITICAL,
+ .ops = &clk_branch2_ops,
+ },
+ },
+@@ -3078,11 +2895,7 @@ static struct clk_branch gcc_aggre0_cnoc_ahb_clk = {
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_aggre0_cnoc_ahb_clk",
+- .parent_hws = (const struct clk_hw*[]){
+- &config_noc_clk_src.clkr.hw,
+- },
+- .num_parents = 1,
+- .flags = CLK_SET_RATE_PARENT | CLK_IS_CRITICAL,
++ .flags = CLK_IS_CRITICAL,
+ .ops = &clk_branch2_ops,
+ },
+ },
+@@ -3095,11 +2908,7 @@ static struct clk_branch gcc_smmu_aggre0_axi_clk = {
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_smmu_aggre0_axi_clk",
+- .parent_hws = (const struct clk_hw*[]){
+- &system_noc_clk_src.clkr.hw,
+- },
+- .num_parents = 1,
+- .flags = CLK_SET_RATE_PARENT | CLK_IS_CRITICAL,
++ .flags = CLK_IS_CRITICAL,
+ .ops = &clk_branch2_ops,
+ },
+ },
+@@ -3112,11 +2921,7 @@ static struct clk_branch gcc_smmu_aggre0_ahb_clk = {
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_smmu_aggre0_ahb_clk",
+- .parent_hws = (const struct clk_hw*[]){
+- &config_noc_clk_src.clkr.hw,
+- },
+- .num_parents = 1,
+- .flags = CLK_SET_RATE_PARENT | CLK_IS_CRITICAL,
++ .flags = CLK_IS_CRITICAL,
+ .ops = &clk_branch2_ops,
+ },
+ },
+@@ -3163,10 +2968,6 @@ static struct clk_branch gcc_dcc_ahb_clk = {
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_dcc_ahb_clk",
+- .parent_hws = (const struct clk_hw*[]){
+- &config_noc_clk_src.clkr.hw,
+- },
+- .num_parents = 1,
+ .ops = &clk_branch2_ops,
+ },
+ },
+@@ -3179,10 +2980,6 @@ static struct clk_branch gcc_aggre0_noc_mpu_cfg_ahb_clk = {
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_aggre0_noc_mpu_cfg_ahb_clk",
+- .parent_hws = (const struct clk_hw*[]){
+- &config_noc_clk_src.clkr.hw,
+- },
+- .num_parents = 1,
+ .ops = &clk_branch2_ops,
+ },
+ },
+@@ -3195,11 +2992,6 @@ static struct clk_branch gcc_qspi_ahb_clk = {
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_qspi_ahb_clk",
+- .parent_hws = (const struct clk_hw*[]){
+- &periph_noc_clk_src.clkr.hw,
+- },
+- .num_parents = 1,
+- .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+@@ -3348,10 +3140,6 @@ static struct clk_branch gcc_mss_cfg_ahb_clk = {
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_mss_cfg_ahb_clk",
+- .parent_hws = (const struct clk_hw*[]){
+- &config_noc_clk_src.clkr.hw,
+- },
+- .num_parents = 1,
+ .ops = &clk_branch2_ops,
+ },
+ },
+@@ -3364,10 +3152,6 @@ static struct clk_branch gcc_mss_mnoc_bimc_axi_clk = {
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_mss_mnoc_bimc_axi_clk",
+- .parent_hws = (const struct clk_hw*[]){
+- &system_noc_clk_src.clkr.hw,
+- },
+- .num_parents = 1,
+ .ops = &clk_branch2_ops,
+ },
+ },
+@@ -3380,10 +3164,6 @@ static struct clk_branch gcc_mss_snoc_axi_clk = {
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_mss_snoc_axi_clk",
+- .parent_hws = (const struct clk_hw*[]){
+- &system_noc_clk_src.clkr.hw,
+- },
+- .num_parents = 1,
+ .ops = &clk_branch2_ops,
+ },
+ },
+@@ -3396,10 +3176,6 @@ static struct clk_branch gcc_mss_q6_bimc_axi_clk = {
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_mss_q6_bimc_axi_clk",
+- .parent_hws = (const struct clk_hw*[]){
+- &system_noc_clk_src.clkr.hw,
+- },
+- .num_parents = 1,
+ .ops = &clk_branch2_ops,
+ },
+ },
+@@ -3495,9 +3271,6 @@ static struct clk_regmap *gcc_msm8996_clocks[] = {
+ [GPLL0] = &gpll0.clkr,
+ [GPLL4_EARLY] = &gpll4_early.clkr,
+ [GPLL4] = &gpll4.clkr,
+- [SYSTEM_NOC_CLK_SRC] = &system_noc_clk_src.clkr,
+- [CONFIG_NOC_CLK_SRC] = &config_noc_clk_src.clkr,
+- [PERIPH_NOC_CLK_SRC] = &periph_noc_clk_src.clkr,
+ [USB30_MASTER_CLK_SRC] = &usb30_master_clk_src.clkr,
+ [USB30_MOCK_UTMI_CLK_SRC] = &usb30_mock_utmi_clk_src.clkr,
+ [USB3_PHY_AUX_CLK_SRC] = &usb3_phy_aux_clk_src.clkr,
+--
+2.42.0
+
--- /dev/null
+From fb74a203f8a020b7db1e36bf34c90943cf3233b4 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 28 Dec 2021 07:54:11 +0300
+Subject: clk: qcom: gcc-msm8996: use ARRAY_SIZE instead of specifying
+ num_parents
+
+From: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
+
+[ Upstream commit ed96df3d461eeb2c40cb06ca5fd51644d0f4a2c0 ]
+
+Use ARRAY_SIZE() instead of manually specifying num_parents. This makes
+adding/removing entries to/from parent_data easy and errorproof.
+
+Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
+Reviewed-by: Marijn Suijten <marijn.suijten@somainline.org>
+Signed-off-by: Bjorn Andersson <bjorn.andersson@linaro.org>
+Link: https://lore.kernel.org/r/20211228045415.20543-13-dmitry.baryshkov@linaro.org
+Stable-dep-of: 4afda5f6bcdf ("clk: qcom: gcc-msm8996: Remove RPM bus clocks")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/clk/qcom/gcc-msm8996.c | 122 ++++++++++++++++-----------------
+ 1 file changed, 61 insertions(+), 61 deletions(-)
+
+diff --git a/drivers/clk/qcom/gcc-msm8996.c b/drivers/clk/qcom/gcc-msm8996.c
+index 9b1674b28d45d..d95814025c65e 100644
+--- a/drivers/clk/qcom/gcc-msm8996.c
++++ b/drivers/clk/qcom/gcc-msm8996.c
+@@ -290,7 +290,7 @@ static struct clk_rcg2 system_noc_clk_src = {
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "system_noc_clk_src",
+ .parent_names = gcc_xo_gpll0_gpll2_gpll3_gpll1_gpll2_early_gpll0_early_div,
+- .num_parents = 7,
++ .num_parents = ARRAY_SIZE(gcc_xo_gpll0_gpll2_gpll3_gpll1_gpll2_early_gpll0_early_div),
+ .ops = &clk_rcg2_ops,
+ },
+ };
+@@ -310,7 +310,7 @@ static struct clk_rcg2 config_noc_clk_src = {
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "config_noc_clk_src",
+ .parent_names = gcc_xo_gpll0,
+- .num_parents = 2,
++ .num_parents = ARRAY_SIZE(gcc_xo_gpll0),
+ .ops = &clk_rcg2_ops,
+ },
+ };
+@@ -332,7 +332,7 @@ static struct clk_rcg2 periph_noc_clk_src = {
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "periph_noc_clk_src",
+ .parent_names = gcc_xo_gpll0,
+- .num_parents = 2,
++ .num_parents = ARRAY_SIZE(gcc_xo_gpll0),
+ .ops = &clk_rcg2_ops,
+ },
+ };
+@@ -353,7 +353,7 @@ static struct clk_rcg2 usb30_master_clk_src = {
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "usb30_master_clk_src",
+ .parent_names = gcc_xo_gpll0_gpll0_early_div,
+- .num_parents = 3,
++ .num_parents = ARRAY_SIZE(gcc_xo_gpll0_gpll0_early_div),
+ .ops = &clk_rcg2_ops,
+ },
+ };
+@@ -371,7 +371,7 @@ static struct clk_rcg2 usb30_mock_utmi_clk_src = {
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "usb30_mock_utmi_clk_src",
+ .parent_names = gcc_xo_gpll0_gpll0_early_div,
+- .num_parents = 3,
++ .num_parents = ARRAY_SIZE(gcc_xo_gpll0_gpll0_early_div),
+ .ops = &clk_rcg2_ops,
+ },
+ };
+@@ -389,7 +389,7 @@ static struct clk_rcg2 usb3_phy_aux_clk_src = {
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "usb3_phy_aux_clk_src",
+ .parent_names = gcc_xo_sleep_clk,
+- .num_parents = 2,
++ .num_parents = ARRAY_SIZE(gcc_xo_sleep_clk),
+ .ops = &clk_rcg2_ops,
+ },
+ };
+@@ -408,7 +408,7 @@ static struct clk_rcg2 usb20_master_clk_src = {
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "usb20_master_clk_src",
+ .parent_names = gcc_xo_gpll0_gpll0_early_div,
+- .num_parents = 3,
++ .num_parents = ARRAY_SIZE(gcc_xo_gpll0_gpll0_early_div),
+ .ops = &clk_rcg2_ops,
+ },
+ };
+@@ -421,7 +421,7 @@ static struct clk_rcg2 usb20_mock_utmi_clk_src = {
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "usb20_mock_utmi_clk_src",
+ .parent_names = gcc_xo_gpll0_gpll0_early_div,
+- .num_parents = 3,
++ .num_parents = ARRAY_SIZE(gcc_xo_gpll0_gpll0_early_div),
+ .ops = &clk_rcg2_ops,
+ },
+ };
+@@ -447,7 +447,7 @@ static struct clk_rcg2 sdcc1_apps_clk_src = {
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "sdcc1_apps_clk_src",
+ .parent_names = gcc_xo_gpll0_gpll4_gpll0_early_div,
+- .num_parents = 4,
++ .num_parents = ARRAY_SIZE(gcc_xo_gpll0_gpll4_gpll0_early_div),
+ .ops = &clk_rcg2_floor_ops,
+ },
+ };
+@@ -467,7 +467,7 @@ static struct clk_rcg2 sdcc1_ice_core_clk_src = {
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "sdcc1_ice_core_clk_src",
+ .parent_names = gcc_xo_gpll0_gpll4_gpll0_early_div,
+- .num_parents = 4,
++ .num_parents = ARRAY_SIZE(gcc_xo_gpll0_gpll4_gpll0_early_div),
+ .ops = &clk_rcg2_ops,
+ },
+ };
+@@ -492,7 +492,7 @@ static struct clk_rcg2 sdcc2_apps_clk_src = {
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "sdcc2_apps_clk_src",
+ .parent_names = gcc_xo_gpll0_gpll4,
+- .num_parents = 3,
++ .num_parents = ARRAY_SIZE(gcc_xo_gpll0_gpll4),
+ .ops = &clk_rcg2_floor_ops,
+ },
+ };
+@@ -506,7 +506,7 @@ static struct clk_rcg2 sdcc3_apps_clk_src = {
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "sdcc3_apps_clk_src",
+ .parent_names = gcc_xo_gpll0_gpll4,
+- .num_parents = 3,
++ .num_parents = ARRAY_SIZE(gcc_xo_gpll0_gpll4),
+ .ops = &clk_rcg2_floor_ops,
+ },
+ };
+@@ -530,7 +530,7 @@ static struct clk_rcg2 sdcc4_apps_clk_src = {
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "sdcc4_apps_clk_src",
+ .parent_names = gcc_xo_gpll0,
+- .num_parents = 2,
++ .num_parents = ARRAY_SIZE(gcc_xo_gpll0),
+ .ops = &clk_rcg2_floor_ops,
+ },
+ };
+@@ -555,7 +555,7 @@ static struct clk_rcg2 blsp1_qup1_spi_apps_clk_src = {
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "blsp1_qup1_spi_apps_clk_src",
+ .parent_names = gcc_xo_gpll0,
+- .num_parents = 2,
++ .num_parents = ARRAY_SIZE(gcc_xo_gpll0),
+ .ops = &clk_rcg2_ops,
+ },
+ };
+@@ -574,7 +574,7 @@ static struct clk_rcg2 blsp1_qup1_i2c_apps_clk_src = {
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "blsp1_qup1_i2c_apps_clk_src",
+ .parent_names = gcc_xo_gpll0,
+- .num_parents = 2,
++ .num_parents = ARRAY_SIZE(gcc_xo_gpll0),
+ .ops = &clk_rcg2_ops,
+ },
+ };
+@@ -607,7 +607,7 @@ static struct clk_rcg2 blsp1_uart1_apps_clk_src = {
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "blsp1_uart1_apps_clk_src",
+ .parent_names = gcc_xo_gpll0,
+- .num_parents = 2,
++ .num_parents = ARRAY_SIZE(gcc_xo_gpll0),
+ .ops = &clk_rcg2_ops,
+ },
+ };
+@@ -621,7 +621,7 @@ static struct clk_rcg2 blsp1_qup2_spi_apps_clk_src = {
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "blsp1_qup2_spi_apps_clk_src",
+ .parent_names = gcc_xo_gpll0,
+- .num_parents = 2,
++ .num_parents = ARRAY_SIZE(gcc_xo_gpll0),
+ .ops = &clk_rcg2_ops,
+ },
+ };
+@@ -634,7 +634,7 @@ static struct clk_rcg2 blsp1_qup2_i2c_apps_clk_src = {
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "blsp1_qup2_i2c_apps_clk_src",
+ .parent_names = gcc_xo_gpll0,
+- .num_parents = 2,
++ .num_parents = ARRAY_SIZE(gcc_xo_gpll0),
+ .ops = &clk_rcg2_ops,
+ },
+ };
+@@ -648,7 +648,7 @@ static struct clk_rcg2 blsp1_uart2_apps_clk_src = {
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "blsp1_uart2_apps_clk_src",
+ .parent_names = gcc_xo_gpll0,
+- .num_parents = 2,
++ .num_parents = ARRAY_SIZE(gcc_xo_gpll0),
+ .ops = &clk_rcg2_ops,
+ },
+ };
+@@ -662,7 +662,7 @@ static struct clk_rcg2 blsp1_qup3_spi_apps_clk_src = {
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "blsp1_qup3_spi_apps_clk_src",
+ .parent_names = gcc_xo_gpll0,
+- .num_parents = 2,
++ .num_parents = ARRAY_SIZE(gcc_xo_gpll0),
+ .ops = &clk_rcg2_ops,
+ },
+ };
+@@ -675,7 +675,7 @@ static struct clk_rcg2 blsp1_qup3_i2c_apps_clk_src = {
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "blsp1_qup3_i2c_apps_clk_src",
+ .parent_names = gcc_xo_gpll0,
+- .num_parents = 2,
++ .num_parents = ARRAY_SIZE(gcc_xo_gpll0),
+ .ops = &clk_rcg2_ops,
+ },
+ };
+@@ -689,7 +689,7 @@ static struct clk_rcg2 blsp1_uart3_apps_clk_src = {
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "blsp1_uart3_apps_clk_src",
+ .parent_names = gcc_xo_gpll0,
+- .num_parents = 2,
++ .num_parents = ARRAY_SIZE(gcc_xo_gpll0),
+ .ops = &clk_rcg2_ops,
+ },
+ };
+@@ -703,7 +703,7 @@ static struct clk_rcg2 blsp1_qup4_spi_apps_clk_src = {
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "blsp1_qup4_spi_apps_clk_src",
+ .parent_names = gcc_xo_gpll0,
+- .num_parents = 2,
++ .num_parents = ARRAY_SIZE(gcc_xo_gpll0),
+ .ops = &clk_rcg2_ops,
+ },
+ };
+@@ -716,7 +716,7 @@ static struct clk_rcg2 blsp1_qup4_i2c_apps_clk_src = {
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "blsp1_qup4_i2c_apps_clk_src",
+ .parent_names = gcc_xo_gpll0,
+- .num_parents = 2,
++ .num_parents = ARRAY_SIZE(gcc_xo_gpll0),
+ .ops = &clk_rcg2_ops,
+ },
+ };
+@@ -730,7 +730,7 @@ static struct clk_rcg2 blsp1_uart4_apps_clk_src = {
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "blsp1_uart4_apps_clk_src",
+ .parent_names = gcc_xo_gpll0,
+- .num_parents = 2,
++ .num_parents = ARRAY_SIZE(gcc_xo_gpll0),
+ .ops = &clk_rcg2_ops,
+ },
+ };
+@@ -744,7 +744,7 @@ static struct clk_rcg2 blsp1_qup5_spi_apps_clk_src = {
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "blsp1_qup5_spi_apps_clk_src",
+ .parent_names = gcc_xo_gpll0,
+- .num_parents = 2,
++ .num_parents = ARRAY_SIZE(gcc_xo_gpll0),
+ .ops = &clk_rcg2_ops,
+ },
+ };
+@@ -757,7 +757,7 @@ static struct clk_rcg2 blsp1_qup5_i2c_apps_clk_src = {
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "blsp1_qup5_i2c_apps_clk_src",
+ .parent_names = gcc_xo_gpll0,
+- .num_parents = 2,
++ .num_parents = ARRAY_SIZE(gcc_xo_gpll0),
+ .ops = &clk_rcg2_ops,
+ },
+ };
+@@ -771,7 +771,7 @@ static struct clk_rcg2 blsp1_uart5_apps_clk_src = {
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "blsp1_uart5_apps_clk_src",
+ .parent_names = gcc_xo_gpll0,
+- .num_parents = 2,
++ .num_parents = ARRAY_SIZE(gcc_xo_gpll0),
+ .ops = &clk_rcg2_ops,
+ },
+ };
+@@ -785,7 +785,7 @@ static struct clk_rcg2 blsp1_qup6_spi_apps_clk_src = {
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "blsp1_qup6_spi_apps_clk_src",
+ .parent_names = gcc_xo_gpll0,
+- .num_parents = 2,
++ .num_parents = ARRAY_SIZE(gcc_xo_gpll0),
+ .ops = &clk_rcg2_ops,
+ },
+ };
+@@ -798,7 +798,7 @@ static struct clk_rcg2 blsp1_qup6_i2c_apps_clk_src = {
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "blsp1_qup6_i2c_apps_clk_src",
+ .parent_names = gcc_xo_gpll0,
+- .num_parents = 2,
++ .num_parents = ARRAY_SIZE(gcc_xo_gpll0),
+ .ops = &clk_rcg2_ops,
+ },
+ };
+@@ -812,7 +812,7 @@ static struct clk_rcg2 blsp1_uart6_apps_clk_src = {
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "blsp1_uart6_apps_clk_src",
+ .parent_names = gcc_xo_gpll0,
+- .num_parents = 2,
++ .num_parents = ARRAY_SIZE(gcc_xo_gpll0),
+ .ops = &clk_rcg2_ops,
+ },
+ };
+@@ -826,7 +826,7 @@ static struct clk_rcg2 blsp2_qup1_spi_apps_clk_src = {
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "blsp2_qup1_spi_apps_clk_src",
+ .parent_names = gcc_xo_gpll0,
+- .num_parents = 2,
++ .num_parents = ARRAY_SIZE(gcc_xo_gpll0),
+ .ops = &clk_rcg2_ops,
+ },
+ };
+@@ -839,7 +839,7 @@ static struct clk_rcg2 blsp2_qup1_i2c_apps_clk_src = {
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "blsp2_qup1_i2c_apps_clk_src",
+ .parent_names = gcc_xo_gpll0,
+- .num_parents = 2,
++ .num_parents = ARRAY_SIZE(gcc_xo_gpll0),
+ .ops = &clk_rcg2_ops,
+ },
+ };
+@@ -853,7 +853,7 @@ static struct clk_rcg2 blsp2_uart1_apps_clk_src = {
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "blsp2_uart1_apps_clk_src",
+ .parent_names = gcc_xo_gpll0,
+- .num_parents = 2,
++ .num_parents = ARRAY_SIZE(gcc_xo_gpll0),
+ .ops = &clk_rcg2_ops,
+ },
+ };
+@@ -867,7 +867,7 @@ static struct clk_rcg2 blsp2_qup2_spi_apps_clk_src = {
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "blsp2_qup2_spi_apps_clk_src",
+ .parent_names = gcc_xo_gpll0,
+- .num_parents = 2,
++ .num_parents = ARRAY_SIZE(gcc_xo_gpll0),
+ .ops = &clk_rcg2_ops,
+ },
+ };
+@@ -880,7 +880,7 @@ static struct clk_rcg2 blsp2_qup2_i2c_apps_clk_src = {
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "blsp2_qup2_i2c_apps_clk_src",
+ .parent_names = gcc_xo_gpll0,
+- .num_parents = 2,
++ .num_parents = ARRAY_SIZE(gcc_xo_gpll0),
+ .ops = &clk_rcg2_ops,
+ },
+ };
+@@ -894,7 +894,7 @@ static struct clk_rcg2 blsp2_uart2_apps_clk_src = {
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "blsp2_uart2_apps_clk_src",
+ .parent_names = gcc_xo_gpll0,
+- .num_parents = 2,
++ .num_parents = ARRAY_SIZE(gcc_xo_gpll0),
+ .ops = &clk_rcg2_ops,
+ },
+ };
+@@ -908,7 +908,7 @@ static struct clk_rcg2 blsp2_qup3_spi_apps_clk_src = {
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "blsp2_qup3_spi_apps_clk_src",
+ .parent_names = gcc_xo_gpll0,
+- .num_parents = 2,
++ .num_parents = ARRAY_SIZE(gcc_xo_gpll0),
+ .ops = &clk_rcg2_ops,
+ },
+ };
+@@ -921,7 +921,7 @@ static struct clk_rcg2 blsp2_qup3_i2c_apps_clk_src = {
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "blsp2_qup3_i2c_apps_clk_src",
+ .parent_names = gcc_xo_gpll0,
+- .num_parents = 2,
++ .num_parents = ARRAY_SIZE(gcc_xo_gpll0),
+ .ops = &clk_rcg2_ops,
+ },
+ };
+@@ -935,7 +935,7 @@ static struct clk_rcg2 blsp2_uart3_apps_clk_src = {
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "blsp2_uart3_apps_clk_src",
+ .parent_names = gcc_xo_gpll0,
+- .num_parents = 2,
++ .num_parents = ARRAY_SIZE(gcc_xo_gpll0),
+ .ops = &clk_rcg2_ops,
+ },
+ };
+@@ -949,7 +949,7 @@ static struct clk_rcg2 blsp2_qup4_spi_apps_clk_src = {
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "blsp2_qup4_spi_apps_clk_src",
+ .parent_names = gcc_xo_gpll0,
+- .num_parents = 2,
++ .num_parents = ARRAY_SIZE(gcc_xo_gpll0),
+ .ops = &clk_rcg2_ops,
+ },
+ };
+@@ -962,7 +962,7 @@ static struct clk_rcg2 blsp2_qup4_i2c_apps_clk_src = {
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "blsp2_qup4_i2c_apps_clk_src",
+ .parent_names = gcc_xo_gpll0,
+- .num_parents = 2,
++ .num_parents = ARRAY_SIZE(gcc_xo_gpll0),
+ .ops = &clk_rcg2_ops,
+ },
+ };
+@@ -976,7 +976,7 @@ static struct clk_rcg2 blsp2_uart4_apps_clk_src = {
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "blsp2_uart4_apps_clk_src",
+ .parent_names = gcc_xo_gpll0,
+- .num_parents = 2,
++ .num_parents = ARRAY_SIZE(gcc_xo_gpll0),
+ .ops = &clk_rcg2_ops,
+ },
+ };
+@@ -990,7 +990,7 @@ static struct clk_rcg2 blsp2_qup5_spi_apps_clk_src = {
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "blsp2_qup5_spi_apps_clk_src",
+ .parent_names = gcc_xo_gpll0,
+- .num_parents = 2,
++ .num_parents = ARRAY_SIZE(gcc_xo_gpll0),
+ .ops = &clk_rcg2_ops,
+ },
+ };
+@@ -1003,7 +1003,7 @@ static struct clk_rcg2 blsp2_qup5_i2c_apps_clk_src = {
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "blsp2_qup5_i2c_apps_clk_src",
+ .parent_names = gcc_xo_gpll0,
+- .num_parents = 2,
++ .num_parents = ARRAY_SIZE(gcc_xo_gpll0),
+ .ops = &clk_rcg2_ops,
+ },
+ };
+@@ -1017,7 +1017,7 @@ static struct clk_rcg2 blsp2_uart5_apps_clk_src = {
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "blsp2_uart5_apps_clk_src",
+ .parent_names = gcc_xo_gpll0,
+- .num_parents = 2,
++ .num_parents = ARRAY_SIZE(gcc_xo_gpll0),
+ .ops = &clk_rcg2_ops,
+ },
+ };
+@@ -1031,7 +1031,7 @@ static struct clk_rcg2 blsp2_qup6_spi_apps_clk_src = {
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "blsp2_qup6_spi_apps_clk_src",
+ .parent_names = gcc_xo_gpll0,
+- .num_parents = 2,
++ .num_parents = ARRAY_SIZE(gcc_xo_gpll0),
+ .ops = &clk_rcg2_ops,
+ },
+ };
+@@ -1044,7 +1044,7 @@ static struct clk_rcg2 blsp2_qup6_i2c_apps_clk_src = {
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "blsp2_qup6_i2c_apps_clk_src",
+ .parent_names = gcc_xo_gpll0,
+- .num_parents = 2,
++ .num_parents = ARRAY_SIZE(gcc_xo_gpll0),
+ .ops = &clk_rcg2_ops,
+ },
+ };
+@@ -1058,7 +1058,7 @@ static struct clk_rcg2 blsp2_uart6_apps_clk_src = {
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "blsp2_uart6_apps_clk_src",
+ .parent_names = gcc_xo_gpll0,
+- .num_parents = 2,
++ .num_parents = ARRAY_SIZE(gcc_xo_gpll0),
+ .ops = &clk_rcg2_ops,
+ },
+ };
+@@ -1076,7 +1076,7 @@ static struct clk_rcg2 pdm2_clk_src = {
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "pdm2_clk_src",
+ .parent_names = gcc_xo_gpll0,
+- .num_parents = 2,
++ .num_parents = ARRAY_SIZE(gcc_xo_gpll0),
+ .ops = &clk_rcg2_ops,
+ },
+ };
+@@ -1095,7 +1095,7 @@ static struct clk_rcg2 tsif_ref_clk_src = {
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "tsif_ref_clk_src",
+ .parent_names = gcc_xo_gpll0_aud_ref_clk,
+- .num_parents = 3,
++ .num_parents = ARRAY_SIZE(gcc_xo_gpll0_aud_ref_clk),
+ .ops = &clk_rcg2_ops,
+ },
+ };
+@@ -1107,7 +1107,7 @@ static struct clk_rcg2 gcc_sleep_clk_src = {
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "gcc_sleep_clk_src",
+ .parent_names = gcc_sleep_clk,
+- .num_parents = 1,
++ .num_parents = ARRAY_SIZE(gcc_sleep_clk),
+ .ops = &clk_rcg2_ops,
+ },
+ };
+@@ -1120,7 +1120,7 @@ static struct clk_rcg2 hmss_rbcpr_clk_src = {
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "hmss_rbcpr_clk_src",
+ .parent_names = gcc_xo_gpll0,
+- .num_parents = 2,
++ .num_parents = ARRAY_SIZE(gcc_xo_gpll0),
+ .ops = &clk_rcg2_ops,
+ },
+ };
+@@ -1132,7 +1132,7 @@ static struct clk_rcg2 hmss_gpll0_clk_src = {
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "hmss_gpll0_clk_src",
+ .parent_names = gcc_xo_gpll0,
+- .num_parents = 2,
++ .num_parents = ARRAY_SIZE(gcc_xo_gpll0),
+ .ops = &clk_rcg2_ops,
+ },
+ };
+@@ -1153,7 +1153,7 @@ static struct clk_rcg2 gp1_clk_src = {
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "gp1_clk_src",
+ .parent_names = gcc_xo_gpll0_sleep_clk_gpll0_early_div,
+- .num_parents = 4,
++ .num_parents = ARRAY_SIZE(gcc_xo_gpll0_sleep_clk_gpll0_early_div),
+ .ops = &clk_rcg2_ops,
+ },
+ };
+@@ -1167,7 +1167,7 @@ static struct clk_rcg2 gp2_clk_src = {
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "gp2_clk_src",
+ .parent_names = gcc_xo_gpll0_sleep_clk_gpll0_early_div,
+- .num_parents = 4,
++ .num_parents = ARRAY_SIZE(gcc_xo_gpll0_sleep_clk_gpll0_early_div),
+ .ops = &clk_rcg2_ops,
+ },
+ };
+@@ -1181,7 +1181,7 @@ static struct clk_rcg2 gp3_clk_src = {
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "gp3_clk_src",
+ .parent_names = gcc_xo_gpll0_sleep_clk_gpll0_early_div,
+- .num_parents = 4,
++ .num_parents = ARRAY_SIZE(gcc_xo_gpll0_sleep_clk_gpll0_early_div),
+ .ops = &clk_rcg2_ops,
+ },
+ };
+@@ -1200,7 +1200,7 @@ static struct clk_rcg2 pcie_aux_clk_src = {
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "pcie_aux_clk_src",
+ .parent_names = gcc_xo_sleep_clk,
+- .num_parents = 2,
++ .num_parents = ARRAY_SIZE(gcc_xo_sleep_clk),
+ .ops = &clk_rcg2_ops,
+ },
+ };
+@@ -1221,7 +1221,7 @@ static struct clk_rcg2 ufs_axi_clk_src = {
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "ufs_axi_clk_src",
+ .parent_names = gcc_xo_gpll0,
+- .num_parents = 2,
++ .num_parents = ARRAY_SIZE(gcc_xo_gpll0),
+ .ops = &clk_rcg2_ops,
+ },
+ };
+@@ -1241,7 +1241,7 @@ static struct clk_rcg2 ufs_ice_core_clk_src = {
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "ufs_ice_core_clk_src",
+ .parent_names = gcc_xo_gpll0,
+- .num_parents = 2,
++ .num_parents = ARRAY_SIZE(gcc_xo_gpll0),
+ .ops = &clk_rcg2_ops,
+ },
+ };
+@@ -1262,7 +1262,7 @@ static struct clk_rcg2 qspi_ser_clk_src = {
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "qspi_ser_clk_src",
+ .parent_names = gcc_xo_gpll0_gpll1_early_div_gpll1_gpll4_gpll0_early_div,
+- .num_parents = 6,
++ .num_parents = ARRAY_SIZE(gcc_xo_gpll0_gpll1_early_div_gpll1_gpll4_gpll0_early_div),
+ .ops = &clk_rcg2_ops,
+ },
+ };
+--
+2.42.0
+
--- /dev/null
+From 2c539d7b261e3a9e80e634d0a8dbb891641c152b Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 28 Dec 2021 07:54:14 +0300
+Subject: clk: qcom: gcc-msm8996: use parent_hws/_data instead of parent_names
+
+From: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
+
+[ Upstream commit b3867679d460d67aaef5aa76e4512197a5375514 ]
+
+Convert the clock driver to specify parent data rather than parent
+names, to actually bind using 'clock-names' specified in the DTS rather
+than global clock names. Use parent_hws where possible to refer parent
+clocks directly, skipping the lookup.
+
+Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
+Reviewed-by: Marijn Suijten <marijn.suijten@somainline.org>
+Signed-off-by: Bjorn Andersson <bjorn.andersson@linaro.org>
+Link: https://lore.kernel.org/r/20211228045415.20543-16-dmitry.baryshkov@linaro.org
+Stable-dep-of: 4afda5f6bcdf ("clk: qcom: gcc-msm8996: Remove RPM bus clocks")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/clk/qcom/gcc-msm8996.c | 678 ++++++++++++++++++++++-----------
+ 1 file changed, 463 insertions(+), 215 deletions(-)
+
+diff --git a/drivers/clk/qcom/gcc-msm8996.c b/drivers/clk/qcom/gcc-msm8996.c
+index 8531f2f3665fe..6b36024583b4a 100644
+--- a/drivers/clk/qcom/gcc-msm8996.c
++++ b/drivers/clk/qcom/gcc-msm8996.c
+@@ -38,7 +38,9 @@ static struct clk_fixed_factor xo = {
+ .div = 1,
+ .hw.init = &(struct clk_init_data){
+ .name = "xo",
+- .parent_names = (const char *[]){ "xo_board" },
++ .parent_data = &(const struct clk_parent_data){
++ .fw_name = "cxo", .name = "xo_board",
++ },
+ .num_parents = 1,
+ .ops = &clk_fixed_factor_ops,
+ },
+@@ -52,7 +54,9 @@ static struct clk_alpha_pll gpll0_early = {
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gpll0_early",
+- .parent_names = (const char *[]){ "xo" },
++ .parent_hws = (const struct clk_hw*[]){
++ &xo.hw,
++ },
+ .num_parents = 1,
+ .ops = &clk_alpha_pll_ops,
+ },
+@@ -64,7 +68,9 @@ static struct clk_fixed_factor gpll0_early_div = {
+ .div = 2,
+ .hw.init = &(struct clk_init_data){
+ .name = "gpll0_early_div",
+- .parent_names = (const char *[]){ "gpll0_early" },
++ .parent_hws = (const struct clk_hw*[]){
++ &gpll0_early.clkr.hw,
++ },
+ .num_parents = 1,
+ .ops = &clk_fixed_factor_ops,
+ },
+@@ -75,7 +81,9 @@ static struct clk_alpha_pll_postdiv gpll0 = {
+ .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_DEFAULT],
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "gpll0",
+- .parent_names = (const char *[]){ "gpll0_early" },
++ .parent_hws = (const struct clk_hw*[]){
++ &gpll0_early.clkr.hw,
++ },
+ .num_parents = 1,
+ .ops = &clk_alpha_pll_postdiv_ops,
+ },
+@@ -88,7 +96,9 @@ static struct clk_branch gcc_mmss_gpll0_div_clk = {
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_mmss_gpll0_div_clk",
+- .parent_names = (const char *[]){ "gpll0" },
++ .parent_hws = (const struct clk_hw*[]){
++ &gpll0.clkr.hw,
++ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+@@ -103,7 +113,9 @@ static struct clk_branch gcc_mss_gpll0_div_clk = {
+ .enable_mask = BIT(2),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_mss_gpll0_div_clk",
+- .parent_names = (const char *[]){ "gpll0" },
++ .parent_hws = (const struct clk_hw*[]){
++ &gpll0.clkr.hw,
++ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops
+@@ -119,7 +131,9 @@ static struct clk_alpha_pll gpll4_early = {
+ .enable_mask = BIT(4),
+ .hw.init = &(struct clk_init_data){
+ .name = "gpll4_early",
+- .parent_names = (const char *[]){ "xo" },
++ .parent_hws = (const struct clk_hw*[]){
++ &xo.hw,
++ },
+ .num_parents = 1,
+ .ops = &clk_alpha_pll_ops,
+ },
+@@ -131,7 +145,9 @@ static struct clk_alpha_pll_postdiv gpll4 = {
+ .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_DEFAULT],
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "gpll4",
+- .parent_names = (const char *[]){ "gpll4_early" },
++ .parent_hws = (const struct clk_hw*[]){
++ &gpll4_early.clkr.hw,
++ },
+ .num_parents = 1,
+ .ops = &clk_alpha_pll_postdiv_ops,
+ },
+@@ -141,8 +157,8 @@ static const struct parent_map gcc_sleep_clk_map[] = {
+ { P_SLEEP_CLK, 5 }
+ };
+
+-static const char * const gcc_sleep_clk[] = {
+- "sleep_clk"
++static const struct clk_parent_data gcc_sleep_clk[] = {
++ { .fw_name = "sleep_clk", .name = "sleep_clk" }
+ };
+
+ static const struct parent_map gcc_xo_gpll0_map[] = {
+@@ -150,9 +166,9 @@ static const struct parent_map gcc_xo_gpll0_map[] = {
+ { P_GPLL0, 1 }
+ };
+
+-static const char * const gcc_xo_gpll0[] = {
+- "xo",
+- "gpll0"
++static const struct clk_parent_data gcc_xo_gpll0[] = {
++ { .hw = &xo.hw },
++ { .hw = &gpll0.clkr.hw }
+ };
+
+ static const struct parent_map gcc_xo_sleep_clk_map[] = {
+@@ -160,9 +176,9 @@ static const struct parent_map gcc_xo_sleep_clk_map[] = {
+ { P_SLEEP_CLK, 5 }
+ };
+
+-static const char * const gcc_xo_sleep_clk[] = {
+- "xo",
+- "sleep_clk"
++static const struct clk_parent_data gcc_xo_sleep_clk[] = {
++ { .hw = &xo.hw },
++ { .fw_name = "sleep_clk", .name = "sleep_clk" }
+ };
+
+ static const struct parent_map gcc_xo_gpll0_gpll0_early_div_map[] = {
+@@ -171,10 +187,10 @@ static const struct parent_map gcc_xo_gpll0_gpll0_early_div_map[] = {
+ { P_GPLL0_EARLY_DIV, 6 }
+ };
+
+-static const char * const gcc_xo_gpll0_gpll0_early_div[] = {
+- "xo",
+- "gpll0",
+- "gpll0_early_div"
++static const struct clk_parent_data gcc_xo_gpll0_gpll0_early_div[] = {
++ { .hw = &xo.hw },
++ { .hw = &gpll0.clkr.hw },
++ { .hw = &gpll0_early_div.hw }
+ };
+
+ static const struct parent_map gcc_xo_gpll0_gpll4_map[] = {
+@@ -183,10 +199,10 @@ static const struct parent_map gcc_xo_gpll0_gpll4_map[] = {
+ { P_GPLL4, 5 }
+ };
+
+-static const char * const gcc_xo_gpll0_gpll4[] = {
+- "xo",
+- "gpll0",
+- "gpll4"
++static const struct clk_parent_data gcc_xo_gpll0_gpll4[] = {
++ { .hw = &xo.hw },
++ { .hw = &gpll0.clkr.hw },
++ { .hw = &gpll4.clkr.hw }
+ };
+
+ static const struct parent_map gcc_xo_gpll0_aud_ref_clk_map[] = {
+@@ -195,10 +211,10 @@ static const struct parent_map gcc_xo_gpll0_aud_ref_clk_map[] = {
+ { P_AUD_REF_CLK, 2 }
+ };
+
+-static const char * const gcc_xo_gpll0_aud_ref_clk[] = {
+- "xo",
+- "gpll0",
+- "aud_ref_clk"
++static const struct clk_parent_data gcc_xo_gpll0_aud_ref_clk[] = {
++ { .hw = &xo.hw },
++ { .hw = &gpll0.clkr.hw },
++ { .fw_name = "aud_ref_clk", .name = "aud_ref_clk" }
+ };
+
+ static const struct parent_map gcc_xo_gpll0_sleep_clk_gpll0_early_div_map[] = {
+@@ -208,11 +224,11 @@ static const struct parent_map gcc_xo_gpll0_sleep_clk_gpll0_early_div_map[] = {
+ { P_GPLL0_EARLY_DIV, 6 }
+ };
+
+-static const char * const gcc_xo_gpll0_sleep_clk_gpll0_early_div[] = {
+- "xo",
+- "gpll0",
+- "sleep_clk",
+- "gpll0_early_div"
++static const struct clk_parent_data gcc_xo_gpll0_sleep_clk_gpll0_early_div[] = {
++ { .hw = &xo.hw },
++ { .hw = &gpll0.clkr.hw },
++ { .fw_name = "sleep_clk", .name = "sleep_clk" },
++ { .hw = &gpll0_early_div.hw }
+ };
+
+ static const struct parent_map gcc_xo_gpll0_gpll4_gpll0_early_div_map[] = {
+@@ -222,11 +238,11 @@ static const struct parent_map gcc_xo_gpll0_gpll4_gpll0_early_div_map[] = {
+ { P_GPLL0_EARLY_DIV, 6 }
+ };
+
+-static const char * const gcc_xo_gpll0_gpll4_gpll0_early_div[] = {
+- "xo",
+- "gpll0",
+- "gpll4",
+- "gpll0_early_div"
++static const struct clk_parent_data gcc_xo_gpll0_gpll4_gpll0_early_div[] = {
++ { .hw = &xo.hw },
++ { .hw = &gpll0.clkr.hw },
++ { .hw = &gpll4.clkr.hw },
++ { .hw = &gpll0_early_div.hw }
+ };
+
+ static const struct freq_tbl ftbl_system_noc_clk_src[] = {
+@@ -246,7 +262,7 @@ static struct clk_rcg2 system_noc_clk_src = {
+ .freq_tbl = ftbl_system_noc_clk_src,
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "system_noc_clk_src",
+- .parent_names = gcc_xo_gpll0_gpll0_early_div,
++ .parent_data = gcc_xo_gpll0_gpll0_early_div,
+ .num_parents = ARRAY_SIZE(gcc_xo_gpll0_gpll0_early_div),
+ .ops = &clk_rcg2_ops,
+ },
+@@ -266,7 +282,7 @@ static struct clk_rcg2 config_noc_clk_src = {
+ .freq_tbl = ftbl_config_noc_clk_src,
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "config_noc_clk_src",
+- .parent_names = gcc_xo_gpll0,
++ .parent_data = gcc_xo_gpll0,
+ .num_parents = ARRAY_SIZE(gcc_xo_gpll0),
+ .ops = &clk_rcg2_ops,
+ },
+@@ -288,7 +304,7 @@ static struct clk_rcg2 periph_noc_clk_src = {
+ .freq_tbl = ftbl_periph_noc_clk_src,
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "periph_noc_clk_src",
+- .parent_names = gcc_xo_gpll0,
++ .parent_data = gcc_xo_gpll0,
+ .num_parents = ARRAY_SIZE(gcc_xo_gpll0),
+ .ops = &clk_rcg2_ops,
+ },
+@@ -309,7 +325,7 @@ static struct clk_rcg2 usb30_master_clk_src = {
+ .freq_tbl = ftbl_usb30_master_clk_src,
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "usb30_master_clk_src",
+- .parent_names = gcc_xo_gpll0_gpll0_early_div,
++ .parent_data = gcc_xo_gpll0_gpll0_early_div,
+ .num_parents = ARRAY_SIZE(gcc_xo_gpll0_gpll0_early_div),
+ .ops = &clk_rcg2_ops,
+ },
+@@ -327,7 +343,7 @@ static struct clk_rcg2 usb30_mock_utmi_clk_src = {
+ .freq_tbl = ftbl_usb30_mock_utmi_clk_src,
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "usb30_mock_utmi_clk_src",
+- .parent_names = gcc_xo_gpll0_gpll0_early_div,
++ .parent_data = gcc_xo_gpll0_gpll0_early_div,
+ .num_parents = ARRAY_SIZE(gcc_xo_gpll0_gpll0_early_div),
+ .ops = &clk_rcg2_ops,
+ },
+@@ -345,7 +361,7 @@ static struct clk_rcg2 usb3_phy_aux_clk_src = {
+ .freq_tbl = ftbl_usb3_phy_aux_clk_src,
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "usb3_phy_aux_clk_src",
+- .parent_names = gcc_xo_sleep_clk,
++ .parent_data = gcc_xo_sleep_clk,
+ .num_parents = ARRAY_SIZE(gcc_xo_sleep_clk),
+ .ops = &clk_rcg2_ops,
+ },
+@@ -364,7 +380,7 @@ static struct clk_rcg2 usb20_master_clk_src = {
+ .freq_tbl = ftbl_usb20_master_clk_src,
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "usb20_master_clk_src",
+- .parent_names = gcc_xo_gpll0_gpll0_early_div,
++ .parent_data = gcc_xo_gpll0_gpll0_early_div,
+ .num_parents = ARRAY_SIZE(gcc_xo_gpll0_gpll0_early_div),
+ .ops = &clk_rcg2_ops,
+ },
+@@ -377,7 +393,7 @@ static struct clk_rcg2 usb20_mock_utmi_clk_src = {
+ .freq_tbl = ftbl_usb30_mock_utmi_clk_src,
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "usb20_mock_utmi_clk_src",
+- .parent_names = gcc_xo_gpll0_gpll0_early_div,
++ .parent_data = gcc_xo_gpll0_gpll0_early_div,
+ .num_parents = ARRAY_SIZE(gcc_xo_gpll0_gpll0_early_div),
+ .ops = &clk_rcg2_ops,
+ },
+@@ -403,7 +419,7 @@ static struct clk_rcg2 sdcc1_apps_clk_src = {
+ .freq_tbl = ftbl_sdcc1_apps_clk_src,
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "sdcc1_apps_clk_src",
+- .parent_names = gcc_xo_gpll0_gpll4_gpll0_early_div,
++ .parent_data = gcc_xo_gpll0_gpll4_gpll0_early_div,
+ .num_parents = ARRAY_SIZE(gcc_xo_gpll0_gpll4_gpll0_early_div),
+ .ops = &clk_rcg2_floor_ops,
+ },
+@@ -423,7 +439,7 @@ static struct clk_rcg2 sdcc1_ice_core_clk_src = {
+ .freq_tbl = ftbl_sdcc1_ice_core_clk_src,
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "sdcc1_ice_core_clk_src",
+- .parent_names = gcc_xo_gpll0_gpll4_gpll0_early_div,
++ .parent_data = gcc_xo_gpll0_gpll4_gpll0_early_div,
+ .num_parents = ARRAY_SIZE(gcc_xo_gpll0_gpll4_gpll0_early_div),
+ .ops = &clk_rcg2_ops,
+ },
+@@ -448,7 +464,7 @@ static struct clk_rcg2 sdcc2_apps_clk_src = {
+ .freq_tbl = ftbl_sdcc2_apps_clk_src,
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "sdcc2_apps_clk_src",
+- .parent_names = gcc_xo_gpll0_gpll4,
++ .parent_data = gcc_xo_gpll0_gpll4,
+ .num_parents = ARRAY_SIZE(gcc_xo_gpll0_gpll4),
+ .ops = &clk_rcg2_floor_ops,
+ },
+@@ -462,7 +478,7 @@ static struct clk_rcg2 sdcc3_apps_clk_src = {
+ .freq_tbl = ftbl_sdcc2_apps_clk_src,
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "sdcc3_apps_clk_src",
+- .parent_names = gcc_xo_gpll0_gpll4,
++ .parent_data = gcc_xo_gpll0_gpll4,
+ .num_parents = ARRAY_SIZE(gcc_xo_gpll0_gpll4),
+ .ops = &clk_rcg2_floor_ops,
+ },
+@@ -486,7 +502,7 @@ static struct clk_rcg2 sdcc4_apps_clk_src = {
+ .freq_tbl = ftbl_sdcc4_apps_clk_src,
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "sdcc4_apps_clk_src",
+- .parent_names = gcc_xo_gpll0,
++ .parent_data = gcc_xo_gpll0,
+ .num_parents = ARRAY_SIZE(gcc_xo_gpll0),
+ .ops = &clk_rcg2_floor_ops,
+ },
+@@ -511,7 +527,7 @@ static struct clk_rcg2 blsp1_qup1_spi_apps_clk_src = {
+ .freq_tbl = ftbl_blsp1_qup1_spi_apps_clk_src,
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "blsp1_qup1_spi_apps_clk_src",
+- .parent_names = gcc_xo_gpll0,
++ .parent_data = gcc_xo_gpll0,
+ .num_parents = ARRAY_SIZE(gcc_xo_gpll0),
+ .ops = &clk_rcg2_ops,
+ },
+@@ -530,7 +546,7 @@ static struct clk_rcg2 blsp1_qup1_i2c_apps_clk_src = {
+ .freq_tbl = ftbl_blsp1_qup1_i2c_apps_clk_src,
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "blsp1_qup1_i2c_apps_clk_src",
+- .parent_names = gcc_xo_gpll0,
++ .parent_data = gcc_xo_gpll0,
+ .num_parents = ARRAY_SIZE(gcc_xo_gpll0),
+ .ops = &clk_rcg2_ops,
+ },
+@@ -563,7 +579,7 @@ static struct clk_rcg2 blsp1_uart1_apps_clk_src = {
+ .freq_tbl = ftbl_blsp1_uart1_apps_clk_src,
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "blsp1_uart1_apps_clk_src",
+- .parent_names = gcc_xo_gpll0,
++ .parent_data = gcc_xo_gpll0,
+ .num_parents = ARRAY_SIZE(gcc_xo_gpll0),
+ .ops = &clk_rcg2_ops,
+ },
+@@ -577,7 +593,7 @@ static struct clk_rcg2 blsp1_qup2_spi_apps_clk_src = {
+ .freq_tbl = ftbl_blsp1_qup1_spi_apps_clk_src,
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "blsp1_qup2_spi_apps_clk_src",
+- .parent_names = gcc_xo_gpll0,
++ .parent_data = gcc_xo_gpll0,
+ .num_parents = ARRAY_SIZE(gcc_xo_gpll0),
+ .ops = &clk_rcg2_ops,
+ },
+@@ -590,7 +606,7 @@ static struct clk_rcg2 blsp1_qup2_i2c_apps_clk_src = {
+ .freq_tbl = ftbl_blsp1_qup1_i2c_apps_clk_src,
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "blsp1_qup2_i2c_apps_clk_src",
+- .parent_names = gcc_xo_gpll0,
++ .parent_data = gcc_xo_gpll0,
+ .num_parents = ARRAY_SIZE(gcc_xo_gpll0),
+ .ops = &clk_rcg2_ops,
+ },
+@@ -604,7 +620,7 @@ static struct clk_rcg2 blsp1_uart2_apps_clk_src = {
+ .freq_tbl = ftbl_blsp1_uart1_apps_clk_src,
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "blsp1_uart2_apps_clk_src",
+- .parent_names = gcc_xo_gpll0,
++ .parent_data = gcc_xo_gpll0,
+ .num_parents = ARRAY_SIZE(gcc_xo_gpll0),
+ .ops = &clk_rcg2_ops,
+ },
+@@ -618,7 +634,7 @@ static struct clk_rcg2 blsp1_qup3_spi_apps_clk_src = {
+ .freq_tbl = ftbl_blsp1_qup1_spi_apps_clk_src,
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "blsp1_qup3_spi_apps_clk_src",
+- .parent_names = gcc_xo_gpll0,
++ .parent_data = gcc_xo_gpll0,
+ .num_parents = ARRAY_SIZE(gcc_xo_gpll0),
+ .ops = &clk_rcg2_ops,
+ },
+@@ -631,7 +647,7 @@ static struct clk_rcg2 blsp1_qup3_i2c_apps_clk_src = {
+ .freq_tbl = ftbl_blsp1_qup1_i2c_apps_clk_src,
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "blsp1_qup3_i2c_apps_clk_src",
+- .parent_names = gcc_xo_gpll0,
++ .parent_data = gcc_xo_gpll0,
+ .num_parents = ARRAY_SIZE(gcc_xo_gpll0),
+ .ops = &clk_rcg2_ops,
+ },
+@@ -645,7 +661,7 @@ static struct clk_rcg2 blsp1_uart3_apps_clk_src = {
+ .freq_tbl = ftbl_blsp1_uart1_apps_clk_src,
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "blsp1_uart3_apps_clk_src",
+- .parent_names = gcc_xo_gpll0,
++ .parent_data = gcc_xo_gpll0,
+ .num_parents = ARRAY_SIZE(gcc_xo_gpll0),
+ .ops = &clk_rcg2_ops,
+ },
+@@ -659,7 +675,7 @@ static struct clk_rcg2 blsp1_qup4_spi_apps_clk_src = {
+ .freq_tbl = ftbl_blsp1_qup1_spi_apps_clk_src,
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "blsp1_qup4_spi_apps_clk_src",
+- .parent_names = gcc_xo_gpll0,
++ .parent_data = gcc_xo_gpll0,
+ .num_parents = ARRAY_SIZE(gcc_xo_gpll0),
+ .ops = &clk_rcg2_ops,
+ },
+@@ -672,7 +688,7 @@ static struct clk_rcg2 blsp1_qup4_i2c_apps_clk_src = {
+ .freq_tbl = ftbl_blsp1_qup1_i2c_apps_clk_src,
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "blsp1_qup4_i2c_apps_clk_src",
+- .parent_names = gcc_xo_gpll0,
++ .parent_data = gcc_xo_gpll0,
+ .num_parents = ARRAY_SIZE(gcc_xo_gpll0),
+ .ops = &clk_rcg2_ops,
+ },
+@@ -686,7 +702,7 @@ static struct clk_rcg2 blsp1_uart4_apps_clk_src = {
+ .freq_tbl = ftbl_blsp1_uart1_apps_clk_src,
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "blsp1_uart4_apps_clk_src",
+- .parent_names = gcc_xo_gpll0,
++ .parent_data = gcc_xo_gpll0,
+ .num_parents = ARRAY_SIZE(gcc_xo_gpll0),
+ .ops = &clk_rcg2_ops,
+ },
+@@ -700,7 +716,7 @@ static struct clk_rcg2 blsp1_qup5_spi_apps_clk_src = {
+ .freq_tbl = ftbl_blsp1_qup1_spi_apps_clk_src,
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "blsp1_qup5_spi_apps_clk_src",
+- .parent_names = gcc_xo_gpll0,
++ .parent_data = gcc_xo_gpll0,
+ .num_parents = ARRAY_SIZE(gcc_xo_gpll0),
+ .ops = &clk_rcg2_ops,
+ },
+@@ -713,7 +729,7 @@ static struct clk_rcg2 blsp1_qup5_i2c_apps_clk_src = {
+ .freq_tbl = ftbl_blsp1_qup1_i2c_apps_clk_src,
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "blsp1_qup5_i2c_apps_clk_src",
+- .parent_names = gcc_xo_gpll0,
++ .parent_data = gcc_xo_gpll0,
+ .num_parents = ARRAY_SIZE(gcc_xo_gpll0),
+ .ops = &clk_rcg2_ops,
+ },
+@@ -727,7 +743,7 @@ static struct clk_rcg2 blsp1_uart5_apps_clk_src = {
+ .freq_tbl = ftbl_blsp1_uart1_apps_clk_src,
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "blsp1_uart5_apps_clk_src",
+- .parent_names = gcc_xo_gpll0,
++ .parent_data = gcc_xo_gpll0,
+ .num_parents = ARRAY_SIZE(gcc_xo_gpll0),
+ .ops = &clk_rcg2_ops,
+ },
+@@ -741,7 +757,7 @@ static struct clk_rcg2 blsp1_qup6_spi_apps_clk_src = {
+ .freq_tbl = ftbl_blsp1_qup1_spi_apps_clk_src,
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "blsp1_qup6_spi_apps_clk_src",
+- .parent_names = gcc_xo_gpll0,
++ .parent_data = gcc_xo_gpll0,
+ .num_parents = ARRAY_SIZE(gcc_xo_gpll0),
+ .ops = &clk_rcg2_ops,
+ },
+@@ -754,7 +770,7 @@ static struct clk_rcg2 blsp1_qup6_i2c_apps_clk_src = {
+ .freq_tbl = ftbl_blsp1_qup1_i2c_apps_clk_src,
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "blsp1_qup6_i2c_apps_clk_src",
+- .parent_names = gcc_xo_gpll0,
++ .parent_data = gcc_xo_gpll0,
+ .num_parents = ARRAY_SIZE(gcc_xo_gpll0),
+ .ops = &clk_rcg2_ops,
+ },
+@@ -768,7 +784,7 @@ static struct clk_rcg2 blsp1_uart6_apps_clk_src = {
+ .freq_tbl = ftbl_blsp1_uart1_apps_clk_src,
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "blsp1_uart6_apps_clk_src",
+- .parent_names = gcc_xo_gpll0,
++ .parent_data = gcc_xo_gpll0,
+ .num_parents = ARRAY_SIZE(gcc_xo_gpll0),
+ .ops = &clk_rcg2_ops,
+ },
+@@ -782,7 +798,7 @@ static struct clk_rcg2 blsp2_qup1_spi_apps_clk_src = {
+ .freq_tbl = ftbl_blsp1_qup1_spi_apps_clk_src,
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "blsp2_qup1_spi_apps_clk_src",
+- .parent_names = gcc_xo_gpll0,
++ .parent_data = gcc_xo_gpll0,
+ .num_parents = ARRAY_SIZE(gcc_xo_gpll0),
+ .ops = &clk_rcg2_ops,
+ },
+@@ -795,7 +811,7 @@ static struct clk_rcg2 blsp2_qup1_i2c_apps_clk_src = {
+ .freq_tbl = ftbl_blsp1_qup1_i2c_apps_clk_src,
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "blsp2_qup1_i2c_apps_clk_src",
+- .parent_names = gcc_xo_gpll0,
++ .parent_data = gcc_xo_gpll0,
+ .num_parents = ARRAY_SIZE(gcc_xo_gpll0),
+ .ops = &clk_rcg2_ops,
+ },
+@@ -809,7 +825,7 @@ static struct clk_rcg2 blsp2_uart1_apps_clk_src = {
+ .freq_tbl = ftbl_blsp1_uart1_apps_clk_src,
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "blsp2_uart1_apps_clk_src",
+- .parent_names = gcc_xo_gpll0,
++ .parent_data = gcc_xo_gpll0,
+ .num_parents = ARRAY_SIZE(gcc_xo_gpll0),
+ .ops = &clk_rcg2_ops,
+ },
+@@ -823,7 +839,7 @@ static struct clk_rcg2 blsp2_qup2_spi_apps_clk_src = {
+ .freq_tbl = ftbl_blsp1_qup1_spi_apps_clk_src,
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "blsp2_qup2_spi_apps_clk_src",
+- .parent_names = gcc_xo_gpll0,
++ .parent_data = gcc_xo_gpll0,
+ .num_parents = ARRAY_SIZE(gcc_xo_gpll0),
+ .ops = &clk_rcg2_ops,
+ },
+@@ -836,7 +852,7 @@ static struct clk_rcg2 blsp2_qup2_i2c_apps_clk_src = {
+ .freq_tbl = ftbl_blsp1_qup1_i2c_apps_clk_src,
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "blsp2_qup2_i2c_apps_clk_src",
+- .parent_names = gcc_xo_gpll0,
++ .parent_data = gcc_xo_gpll0,
+ .num_parents = ARRAY_SIZE(gcc_xo_gpll0),
+ .ops = &clk_rcg2_ops,
+ },
+@@ -850,7 +866,7 @@ static struct clk_rcg2 blsp2_uart2_apps_clk_src = {
+ .freq_tbl = ftbl_blsp1_uart1_apps_clk_src,
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "blsp2_uart2_apps_clk_src",
+- .parent_names = gcc_xo_gpll0,
++ .parent_data = gcc_xo_gpll0,
+ .num_parents = ARRAY_SIZE(gcc_xo_gpll0),
+ .ops = &clk_rcg2_ops,
+ },
+@@ -864,7 +880,7 @@ static struct clk_rcg2 blsp2_qup3_spi_apps_clk_src = {
+ .freq_tbl = ftbl_blsp1_qup1_spi_apps_clk_src,
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "blsp2_qup3_spi_apps_clk_src",
+- .parent_names = gcc_xo_gpll0,
++ .parent_data = gcc_xo_gpll0,
+ .num_parents = ARRAY_SIZE(gcc_xo_gpll0),
+ .ops = &clk_rcg2_ops,
+ },
+@@ -877,7 +893,7 @@ static struct clk_rcg2 blsp2_qup3_i2c_apps_clk_src = {
+ .freq_tbl = ftbl_blsp1_qup1_i2c_apps_clk_src,
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "blsp2_qup3_i2c_apps_clk_src",
+- .parent_names = gcc_xo_gpll0,
++ .parent_data = gcc_xo_gpll0,
+ .num_parents = ARRAY_SIZE(gcc_xo_gpll0),
+ .ops = &clk_rcg2_ops,
+ },
+@@ -891,7 +907,7 @@ static struct clk_rcg2 blsp2_uart3_apps_clk_src = {
+ .freq_tbl = ftbl_blsp1_uart1_apps_clk_src,
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "blsp2_uart3_apps_clk_src",
+- .parent_names = gcc_xo_gpll0,
++ .parent_data = gcc_xo_gpll0,
+ .num_parents = ARRAY_SIZE(gcc_xo_gpll0),
+ .ops = &clk_rcg2_ops,
+ },
+@@ -905,7 +921,7 @@ static struct clk_rcg2 blsp2_qup4_spi_apps_clk_src = {
+ .freq_tbl = ftbl_blsp1_qup1_spi_apps_clk_src,
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "blsp2_qup4_spi_apps_clk_src",
+- .parent_names = gcc_xo_gpll0,
++ .parent_data = gcc_xo_gpll0,
+ .num_parents = ARRAY_SIZE(gcc_xo_gpll0),
+ .ops = &clk_rcg2_ops,
+ },
+@@ -918,7 +934,7 @@ static struct clk_rcg2 blsp2_qup4_i2c_apps_clk_src = {
+ .freq_tbl = ftbl_blsp1_qup1_i2c_apps_clk_src,
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "blsp2_qup4_i2c_apps_clk_src",
+- .parent_names = gcc_xo_gpll0,
++ .parent_data = gcc_xo_gpll0,
+ .num_parents = ARRAY_SIZE(gcc_xo_gpll0),
+ .ops = &clk_rcg2_ops,
+ },
+@@ -932,7 +948,7 @@ static struct clk_rcg2 blsp2_uart4_apps_clk_src = {
+ .freq_tbl = ftbl_blsp1_uart1_apps_clk_src,
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "blsp2_uart4_apps_clk_src",
+- .parent_names = gcc_xo_gpll0,
++ .parent_data = gcc_xo_gpll0,
+ .num_parents = ARRAY_SIZE(gcc_xo_gpll0),
+ .ops = &clk_rcg2_ops,
+ },
+@@ -946,7 +962,7 @@ static struct clk_rcg2 blsp2_qup5_spi_apps_clk_src = {
+ .freq_tbl = ftbl_blsp1_qup1_spi_apps_clk_src,
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "blsp2_qup5_spi_apps_clk_src",
+- .parent_names = gcc_xo_gpll0,
++ .parent_data = gcc_xo_gpll0,
+ .num_parents = ARRAY_SIZE(gcc_xo_gpll0),
+ .ops = &clk_rcg2_ops,
+ },
+@@ -959,7 +975,7 @@ static struct clk_rcg2 blsp2_qup5_i2c_apps_clk_src = {
+ .freq_tbl = ftbl_blsp1_qup1_i2c_apps_clk_src,
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "blsp2_qup5_i2c_apps_clk_src",
+- .parent_names = gcc_xo_gpll0,
++ .parent_data = gcc_xo_gpll0,
+ .num_parents = ARRAY_SIZE(gcc_xo_gpll0),
+ .ops = &clk_rcg2_ops,
+ },
+@@ -973,7 +989,7 @@ static struct clk_rcg2 blsp2_uart5_apps_clk_src = {
+ .freq_tbl = ftbl_blsp1_uart1_apps_clk_src,
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "blsp2_uart5_apps_clk_src",
+- .parent_names = gcc_xo_gpll0,
++ .parent_data = gcc_xo_gpll0,
+ .num_parents = ARRAY_SIZE(gcc_xo_gpll0),
+ .ops = &clk_rcg2_ops,
+ },
+@@ -987,7 +1003,7 @@ static struct clk_rcg2 blsp2_qup6_spi_apps_clk_src = {
+ .freq_tbl = ftbl_blsp1_qup1_spi_apps_clk_src,
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "blsp2_qup6_spi_apps_clk_src",
+- .parent_names = gcc_xo_gpll0,
++ .parent_data = gcc_xo_gpll0,
+ .num_parents = ARRAY_SIZE(gcc_xo_gpll0),
+ .ops = &clk_rcg2_ops,
+ },
+@@ -1000,7 +1016,7 @@ static struct clk_rcg2 blsp2_qup6_i2c_apps_clk_src = {
+ .freq_tbl = ftbl_blsp1_qup1_i2c_apps_clk_src,
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "blsp2_qup6_i2c_apps_clk_src",
+- .parent_names = gcc_xo_gpll0,
++ .parent_data = gcc_xo_gpll0,
+ .num_parents = ARRAY_SIZE(gcc_xo_gpll0),
+ .ops = &clk_rcg2_ops,
+ },
+@@ -1014,7 +1030,7 @@ static struct clk_rcg2 blsp2_uart6_apps_clk_src = {
+ .freq_tbl = ftbl_blsp1_uart1_apps_clk_src,
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "blsp2_uart6_apps_clk_src",
+- .parent_names = gcc_xo_gpll0,
++ .parent_data = gcc_xo_gpll0,
+ .num_parents = ARRAY_SIZE(gcc_xo_gpll0),
+ .ops = &clk_rcg2_ops,
+ },
+@@ -1032,7 +1048,7 @@ static struct clk_rcg2 pdm2_clk_src = {
+ .freq_tbl = ftbl_pdm2_clk_src,
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "pdm2_clk_src",
+- .parent_names = gcc_xo_gpll0,
++ .parent_data = gcc_xo_gpll0,
+ .num_parents = ARRAY_SIZE(gcc_xo_gpll0),
+ .ops = &clk_rcg2_ops,
+ },
+@@ -1051,7 +1067,7 @@ static struct clk_rcg2 tsif_ref_clk_src = {
+ .freq_tbl = ftbl_tsif_ref_clk_src,
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "tsif_ref_clk_src",
+- .parent_names = gcc_xo_gpll0_aud_ref_clk,
++ .parent_data = gcc_xo_gpll0_aud_ref_clk,
+ .num_parents = ARRAY_SIZE(gcc_xo_gpll0_aud_ref_clk),
+ .ops = &clk_rcg2_ops,
+ },
+@@ -1063,7 +1079,7 @@ static struct clk_rcg2 gcc_sleep_clk_src = {
+ .parent_map = gcc_sleep_clk_map,
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "gcc_sleep_clk_src",
+- .parent_names = gcc_sleep_clk,
++ .parent_data = gcc_sleep_clk,
+ .num_parents = ARRAY_SIZE(gcc_sleep_clk),
+ .ops = &clk_rcg2_ops,
+ },
+@@ -1076,7 +1092,7 @@ static struct clk_rcg2 hmss_rbcpr_clk_src = {
+ .freq_tbl = ftbl_usb30_mock_utmi_clk_src,
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "hmss_rbcpr_clk_src",
+- .parent_names = gcc_xo_gpll0,
++ .parent_data = gcc_xo_gpll0,
+ .num_parents = ARRAY_SIZE(gcc_xo_gpll0),
+ .ops = &clk_rcg2_ops,
+ },
+@@ -1088,7 +1104,7 @@ static struct clk_rcg2 hmss_gpll0_clk_src = {
+ .parent_map = gcc_xo_gpll0_map,
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "hmss_gpll0_clk_src",
+- .parent_names = gcc_xo_gpll0,
++ .parent_data = gcc_xo_gpll0,
+ .num_parents = ARRAY_SIZE(gcc_xo_gpll0),
+ .ops = &clk_rcg2_ops,
+ },
+@@ -1109,7 +1125,7 @@ static struct clk_rcg2 gp1_clk_src = {
+ .freq_tbl = ftbl_gp1_clk_src,
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "gp1_clk_src",
+- .parent_names = gcc_xo_gpll0_sleep_clk_gpll0_early_div,
++ .parent_data = gcc_xo_gpll0_sleep_clk_gpll0_early_div,
+ .num_parents = ARRAY_SIZE(gcc_xo_gpll0_sleep_clk_gpll0_early_div),
+ .ops = &clk_rcg2_ops,
+ },
+@@ -1123,7 +1139,7 @@ static struct clk_rcg2 gp2_clk_src = {
+ .freq_tbl = ftbl_gp1_clk_src,
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "gp2_clk_src",
+- .parent_names = gcc_xo_gpll0_sleep_clk_gpll0_early_div,
++ .parent_data = gcc_xo_gpll0_sleep_clk_gpll0_early_div,
+ .num_parents = ARRAY_SIZE(gcc_xo_gpll0_sleep_clk_gpll0_early_div),
+ .ops = &clk_rcg2_ops,
+ },
+@@ -1137,7 +1153,7 @@ static struct clk_rcg2 gp3_clk_src = {
+ .freq_tbl = ftbl_gp1_clk_src,
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "gp3_clk_src",
+- .parent_names = gcc_xo_gpll0_sleep_clk_gpll0_early_div,
++ .parent_data = gcc_xo_gpll0_sleep_clk_gpll0_early_div,
+ .num_parents = ARRAY_SIZE(gcc_xo_gpll0_sleep_clk_gpll0_early_div),
+ .ops = &clk_rcg2_ops,
+ },
+@@ -1156,7 +1172,7 @@ static struct clk_rcg2 pcie_aux_clk_src = {
+ .freq_tbl = ftbl_pcie_aux_clk_src,
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "pcie_aux_clk_src",
+- .parent_names = gcc_xo_sleep_clk,
++ .parent_data = gcc_xo_sleep_clk,
+ .num_parents = ARRAY_SIZE(gcc_xo_sleep_clk),
+ .ops = &clk_rcg2_ops,
+ },
+@@ -1177,7 +1193,7 @@ static struct clk_rcg2 ufs_axi_clk_src = {
+ .freq_tbl = ftbl_ufs_axi_clk_src,
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "ufs_axi_clk_src",
+- .parent_names = gcc_xo_gpll0,
++ .parent_data = gcc_xo_gpll0,
+ .num_parents = ARRAY_SIZE(gcc_xo_gpll0),
+ .ops = &clk_rcg2_ops,
+ },
+@@ -1197,7 +1213,7 @@ static struct clk_rcg2 ufs_ice_core_clk_src = {
+ .freq_tbl = ftbl_ufs_ice_core_clk_src,
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "ufs_ice_core_clk_src",
+- .parent_names = gcc_xo_gpll0,
++ .parent_data = gcc_xo_gpll0,
+ .num_parents = ARRAY_SIZE(gcc_xo_gpll0),
+ .ops = &clk_rcg2_ops,
+ },
+@@ -1218,7 +1234,7 @@ static struct clk_rcg2 qspi_ser_clk_src = {
+ .freq_tbl = ftbl_qspi_ser_clk_src,
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "qspi_ser_clk_src",
+- .parent_names = gcc_xo_gpll0_gpll4_gpll0_early_div,
++ .parent_data = gcc_xo_gpll0_gpll4_gpll0_early_div,
+ .num_parents = ARRAY_SIZE(gcc_xo_gpll0_gpll4_gpll0_early_div),
+ .ops = &clk_rcg2_ops,
+ },
+@@ -1231,7 +1247,9 @@ static struct clk_branch gcc_sys_noc_usb3_axi_clk = {
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_sys_noc_usb3_axi_clk",
+- .parent_names = (const char *[]){ "usb30_master_clk_src" },
++ .parent_hws = (const struct clk_hw*[]){
++ &usb30_master_clk_src.clkr.hw,
++ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+@@ -1246,7 +1264,9 @@ static struct clk_branch gcc_sys_noc_ufs_axi_clk = {
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_sys_noc_ufs_axi_clk",
+- .parent_names = (const char *[]){ "ufs_axi_clk_src" },
++ .parent_hws = (const struct clk_hw*[]){
++ &ufs_axi_clk_src.clkr.hw,
++ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+@@ -1261,7 +1281,9 @@ static struct clk_branch gcc_periph_noc_usb20_ahb_clk = {
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_periph_noc_usb20_ahb_clk",
+- .parent_names = (const char *[]){ "usb20_master_clk_src" },
++ .parent_hws = (const struct clk_hw*[]){
++ &usb20_master_clk_src.clkr.hw,
++ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+@@ -1276,7 +1298,9 @@ static struct clk_branch gcc_mmss_noc_cfg_ahb_clk = {
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_mmss_noc_cfg_ahb_clk",
+- .parent_names = (const char *[]){ "config_noc_clk_src" },
++ .parent_hws = (const struct clk_hw*[]){
++ &config_noc_clk_src.clkr.hw,
++ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED,
+ .ops = &clk_branch2_ops,
+@@ -1304,7 +1328,9 @@ static struct clk_branch gcc_usb30_master_clk = {
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_usb30_master_clk",
+- .parent_names = (const char *[]){ "usb30_master_clk_src" },
++ .parent_hws = (const struct clk_hw*[]){
++ &usb30_master_clk_src.clkr.hw,
++ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+@@ -1319,7 +1345,9 @@ static struct clk_branch gcc_usb30_sleep_clk = {
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_usb30_sleep_clk",
+- .parent_names = (const char *[]){ "gcc_sleep_clk_src" },
++ .parent_hws = (const struct clk_hw*[]){
++ &gcc_sleep_clk_src.clkr.hw,
++ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+@@ -1334,7 +1362,9 @@ static struct clk_branch gcc_usb30_mock_utmi_clk = {
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_usb30_mock_utmi_clk",
+- .parent_names = (const char *[]){ "usb30_mock_utmi_clk_src" },
++ .parent_hws = (const struct clk_hw*[]){
++ &usb30_mock_utmi_clk_src.clkr.hw,
++ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+@@ -1349,7 +1379,9 @@ static struct clk_branch gcc_usb3_phy_aux_clk = {
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_usb3_phy_aux_clk",
+- .parent_names = (const char *[]){ "usb3_phy_aux_clk_src" },
++ .parent_hws = (const struct clk_hw*[]){
++ &usb3_phy_aux_clk_src.clkr.hw,
++ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+@@ -1365,7 +1397,9 @@ static struct clk_branch gcc_usb3_phy_pipe_clk = {
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_usb3_phy_pipe_clk",
+- .parent_names = (const char *[]){ "usb3_phy_pipe_clk_src" },
++ .parent_data = &(const struct clk_parent_data){
++ .fw_name = "usb3_phy_pipe_clk_src", .name = "usb3_phy_pipe_clk_src",
++ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+@@ -1380,7 +1414,9 @@ static struct clk_branch gcc_usb20_master_clk = {
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_usb20_master_clk",
+- .parent_names = (const char *[]){ "usb20_master_clk_src" },
++ .parent_hws = (const struct clk_hw*[]){
++ &usb20_master_clk_src.clkr.hw,
++ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+@@ -1395,7 +1431,9 @@ static struct clk_branch gcc_usb20_sleep_clk = {
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_usb20_sleep_clk",
+- .parent_names = (const char *[]){ "gcc_sleep_clk_src" },
++ .parent_hws = (const struct clk_hw*[]){
++ &gcc_sleep_clk_src.clkr.hw,
++ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+@@ -1410,7 +1448,9 @@ static struct clk_branch gcc_usb20_mock_utmi_clk = {
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_usb20_mock_utmi_clk",
+- .parent_names = (const char *[]){ "usb20_mock_utmi_clk_src" },
++ .parent_hws = (const struct clk_hw*[]){
++ &usb20_mock_utmi_clk_src.clkr.hw,
++ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+@@ -1425,7 +1465,9 @@ static struct clk_branch gcc_usb_phy_cfg_ahb2phy_clk = {
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_usb_phy_cfg_ahb2phy_clk",
+- .parent_names = (const char *[]){ "periph_noc_clk_src" },
++ .parent_hws = (const struct clk_hw*[]){
++ &periph_noc_clk_src.clkr.hw,
++ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+@@ -1440,7 +1482,9 @@ static struct clk_branch gcc_sdcc1_apps_clk = {
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_sdcc1_apps_clk",
+- .parent_names = (const char *[]){ "sdcc1_apps_clk_src" },
++ .parent_hws = (const struct clk_hw*[]){
++ &sdcc1_apps_clk_src.clkr.hw,
++ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+@@ -1455,7 +1499,9 @@ static struct clk_branch gcc_sdcc1_ahb_clk = {
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_sdcc1_ahb_clk",
+- .parent_names = (const char *[]){ "periph_noc_clk_src" },
++ .parent_hws = (const struct clk_hw*[]){
++ &periph_noc_clk_src.clkr.hw,
++ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+@@ -1470,7 +1516,9 @@ static struct clk_branch gcc_sdcc1_ice_core_clk = {
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_sdcc1_ice_core_clk",
+- .parent_names = (const char *[]){ "sdcc1_ice_core_clk_src" },
++ .parent_hws = (const struct clk_hw*[]){
++ &sdcc1_ice_core_clk_src.clkr.hw,
++ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+@@ -1485,7 +1533,9 @@ static struct clk_branch gcc_sdcc2_apps_clk = {
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_sdcc2_apps_clk",
+- .parent_names = (const char *[]){ "sdcc2_apps_clk_src" },
++ .parent_hws = (const struct clk_hw*[]){
++ &sdcc2_apps_clk_src.clkr.hw,
++ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+@@ -1500,7 +1550,9 @@ static struct clk_branch gcc_sdcc2_ahb_clk = {
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_sdcc2_ahb_clk",
+- .parent_names = (const char *[]){ "periph_noc_clk_src" },
++ .parent_hws = (const struct clk_hw*[]){
++ &periph_noc_clk_src.clkr.hw,
++ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+@@ -1515,7 +1567,9 @@ static struct clk_branch gcc_sdcc3_apps_clk = {
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_sdcc3_apps_clk",
+- .parent_names = (const char *[]){ "sdcc3_apps_clk_src" },
++ .parent_hws = (const struct clk_hw*[]){
++ &sdcc3_apps_clk_src.clkr.hw,
++ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+@@ -1530,7 +1584,9 @@ static struct clk_branch gcc_sdcc3_ahb_clk = {
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_sdcc3_ahb_clk",
+- .parent_names = (const char *[]){ "periph_noc_clk_src" },
++ .parent_hws = (const struct clk_hw*[]){
++ &periph_noc_clk_src.clkr.hw,
++ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+@@ -1545,7 +1601,9 @@ static struct clk_branch gcc_sdcc4_apps_clk = {
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_sdcc4_apps_clk",
+- .parent_names = (const char *[]){ "sdcc4_apps_clk_src" },
++ .parent_hws = (const struct clk_hw*[]){
++ &sdcc4_apps_clk_src.clkr.hw,
++ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+@@ -1560,7 +1618,9 @@ static struct clk_branch gcc_sdcc4_ahb_clk = {
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_sdcc4_ahb_clk",
+- .parent_names = (const char *[]){ "periph_noc_clk_src" },
++ .parent_hws = (const struct clk_hw*[]){
++ &periph_noc_clk_src.clkr.hw,
++ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+@@ -1576,7 +1636,9 @@ static struct clk_branch gcc_blsp1_ahb_clk = {
+ .enable_mask = BIT(17),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_blsp1_ahb_clk",
+- .parent_names = (const char *[]){ "periph_noc_clk_src" },
++ .parent_hws = (const struct clk_hw*[]){
++ &periph_noc_clk_src.clkr.hw,
++ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+@@ -1592,7 +1654,9 @@ static struct clk_branch gcc_blsp1_sleep_clk = {
+ .enable_mask = BIT(16),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_blsp1_sleep_clk",
+- .parent_names = (const char *[]){ "gcc_sleep_clk_src" },
++ .parent_hws = (const struct clk_hw*[]){
++ &gcc_sleep_clk_src.clkr.hw,
++ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+@@ -1607,7 +1671,9 @@ static struct clk_branch gcc_blsp1_qup1_spi_apps_clk = {
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_blsp1_qup1_spi_apps_clk",
+- .parent_names = (const char *[]){ "blsp1_qup1_spi_apps_clk_src" },
++ .parent_hws = (const struct clk_hw*[]){
++ &blsp1_qup1_spi_apps_clk_src.clkr.hw,
++ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+@@ -1622,7 +1688,9 @@ static struct clk_branch gcc_blsp1_qup1_i2c_apps_clk = {
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_blsp1_qup1_i2c_apps_clk",
+- .parent_names = (const char *[]){ "blsp1_qup1_i2c_apps_clk_src" },
++ .parent_hws = (const struct clk_hw*[]){
++ &blsp1_qup1_i2c_apps_clk_src.clkr.hw,
++ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+@@ -1637,7 +1705,9 @@ static struct clk_branch gcc_blsp1_uart1_apps_clk = {
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_blsp1_uart1_apps_clk",
+- .parent_names = (const char *[]){ "blsp1_uart1_apps_clk_src" },
++ .parent_hws = (const struct clk_hw*[]){
++ &blsp1_uart1_apps_clk_src.clkr.hw,
++ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+@@ -1652,7 +1722,9 @@ static struct clk_branch gcc_blsp1_qup2_spi_apps_clk = {
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_blsp1_qup2_spi_apps_clk",
+- .parent_names = (const char *[]){ "blsp1_qup2_spi_apps_clk_src" },
++ .parent_hws = (const struct clk_hw*[]){
++ &blsp1_qup2_spi_apps_clk_src.clkr.hw,
++ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+@@ -1667,7 +1739,9 @@ static struct clk_branch gcc_blsp1_qup2_i2c_apps_clk = {
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_blsp1_qup2_i2c_apps_clk",
+- .parent_names = (const char *[]){ "blsp1_qup2_i2c_apps_clk_src" },
++ .parent_hws = (const struct clk_hw*[]){
++ &blsp1_qup2_i2c_apps_clk_src.clkr.hw,
++ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+@@ -1682,7 +1756,9 @@ static struct clk_branch gcc_blsp1_uart2_apps_clk = {
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_blsp1_uart2_apps_clk",
+- .parent_names = (const char *[]){ "blsp1_uart2_apps_clk_src" },
++ .parent_hws = (const struct clk_hw*[]){
++ &blsp1_uart2_apps_clk_src.clkr.hw,
++ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+@@ -1697,7 +1773,9 @@ static struct clk_branch gcc_blsp1_qup3_spi_apps_clk = {
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_blsp1_qup3_spi_apps_clk",
+- .parent_names = (const char *[]){ "blsp1_qup3_spi_apps_clk_src" },
++ .parent_hws = (const struct clk_hw*[]){
++ &blsp1_qup3_spi_apps_clk_src.clkr.hw,
++ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+@@ -1712,7 +1790,9 @@ static struct clk_branch gcc_blsp1_qup3_i2c_apps_clk = {
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_blsp1_qup3_i2c_apps_clk",
+- .parent_names = (const char *[]){ "blsp1_qup3_i2c_apps_clk_src" },
++ .parent_hws = (const struct clk_hw*[]){
++ &blsp1_qup3_i2c_apps_clk_src.clkr.hw,
++ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+@@ -1727,7 +1807,9 @@ static struct clk_branch gcc_blsp1_uart3_apps_clk = {
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_blsp1_uart3_apps_clk",
+- .parent_names = (const char *[]){ "blsp1_uart3_apps_clk_src" },
++ .parent_hws = (const struct clk_hw*[]){
++ &blsp1_uart3_apps_clk_src.clkr.hw,
++ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+@@ -1742,7 +1824,9 @@ static struct clk_branch gcc_blsp1_qup4_spi_apps_clk = {
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_blsp1_qup4_spi_apps_clk",
+- .parent_names = (const char *[]){ "blsp1_qup4_spi_apps_clk_src" },
++ .parent_hws = (const struct clk_hw*[]){
++ &blsp1_qup4_spi_apps_clk_src.clkr.hw,
++ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+@@ -1757,7 +1841,9 @@ static struct clk_branch gcc_blsp1_qup4_i2c_apps_clk = {
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_blsp1_qup4_i2c_apps_clk",
+- .parent_names = (const char *[]){ "blsp1_qup4_i2c_apps_clk_src" },
++ .parent_hws = (const struct clk_hw*[]){
++ &blsp1_qup4_i2c_apps_clk_src.clkr.hw,
++ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+@@ -1772,7 +1858,9 @@ static struct clk_branch gcc_blsp1_uart4_apps_clk = {
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_blsp1_uart4_apps_clk",
+- .parent_names = (const char *[]){ "blsp1_uart4_apps_clk_src" },
++ .parent_hws = (const struct clk_hw*[]){
++ &blsp1_uart4_apps_clk_src.clkr.hw,
++ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+@@ -1787,7 +1875,9 @@ static struct clk_branch gcc_blsp1_qup5_spi_apps_clk = {
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_blsp1_qup5_spi_apps_clk",
+- .parent_names = (const char *[]){ "blsp1_qup5_spi_apps_clk_src" },
++ .parent_hws = (const struct clk_hw*[]){
++ &blsp1_qup5_spi_apps_clk_src.clkr.hw,
++ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+@@ -1802,7 +1892,9 @@ static struct clk_branch gcc_blsp1_qup5_i2c_apps_clk = {
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_blsp1_qup5_i2c_apps_clk",
+- .parent_names = (const char *[]){ "blsp1_qup5_i2c_apps_clk_src" },
++ .parent_hws = (const struct clk_hw*[]){
++ &blsp1_qup5_i2c_apps_clk_src.clkr.hw,
++ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+@@ -1817,7 +1909,9 @@ static struct clk_branch gcc_blsp1_uart5_apps_clk = {
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_blsp1_uart5_apps_clk",
+- .parent_names = (const char *[]){ "blsp1_uart5_apps_clk_src" },
++ .parent_hws = (const struct clk_hw*[]){
++ &blsp1_uart5_apps_clk_src.clkr.hw,
++ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+@@ -1832,7 +1926,9 @@ static struct clk_branch gcc_blsp1_qup6_spi_apps_clk = {
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_blsp1_qup6_spi_apps_clk",
+- .parent_names = (const char *[]){ "blsp1_qup6_spi_apps_clk_src" },
++ .parent_hws = (const struct clk_hw*[]){
++ &blsp1_qup6_spi_apps_clk_src.clkr.hw,
++ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+@@ -1847,7 +1943,9 @@ static struct clk_branch gcc_blsp1_qup6_i2c_apps_clk = {
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_blsp1_qup6_i2c_apps_clk",
+- .parent_names = (const char *[]){ "blsp1_qup6_i2c_apps_clk_src" },
++ .parent_hws = (const struct clk_hw*[]){
++ &blsp1_qup6_i2c_apps_clk_src.clkr.hw,
++ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+@@ -1862,7 +1960,9 @@ static struct clk_branch gcc_blsp1_uart6_apps_clk = {
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_blsp1_uart6_apps_clk",
+- .parent_names = (const char *[]){ "blsp1_uart6_apps_clk_src" },
++ .parent_hws = (const struct clk_hw*[]){
++ &blsp1_uart6_apps_clk_src.clkr.hw,
++ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+@@ -1878,7 +1978,9 @@ static struct clk_branch gcc_blsp2_ahb_clk = {
+ .enable_mask = BIT(15),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_blsp2_ahb_clk",
+- .parent_names = (const char *[]){ "periph_noc_clk_src" },
++ .parent_hws = (const struct clk_hw*[]){
++ &periph_noc_clk_src.clkr.hw,
++ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+@@ -1894,7 +1996,9 @@ static struct clk_branch gcc_blsp2_sleep_clk = {
+ .enable_mask = BIT(14),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_blsp2_sleep_clk",
+- .parent_names = (const char *[]){ "gcc_sleep_clk_src" },
++ .parent_hws = (const struct clk_hw*[]){
++ &gcc_sleep_clk_src.clkr.hw,
++ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+@@ -1909,7 +2013,9 @@ static struct clk_branch gcc_blsp2_qup1_spi_apps_clk = {
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_blsp2_qup1_spi_apps_clk",
+- .parent_names = (const char *[]){ "blsp2_qup1_spi_apps_clk_src" },
++ .parent_hws = (const struct clk_hw*[]){
++ &blsp2_qup1_spi_apps_clk_src.clkr.hw,
++ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+@@ -1924,7 +2030,9 @@ static struct clk_branch gcc_blsp2_qup1_i2c_apps_clk = {
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_blsp2_qup1_i2c_apps_clk",
+- .parent_names = (const char *[]){ "blsp2_qup1_i2c_apps_clk_src" },
++ .parent_hws = (const struct clk_hw*[]){
++ &blsp2_qup1_i2c_apps_clk_src.clkr.hw,
++ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+@@ -1939,7 +2047,9 @@ static struct clk_branch gcc_blsp2_uart1_apps_clk = {
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_blsp2_uart1_apps_clk",
+- .parent_names = (const char *[]){ "blsp2_uart1_apps_clk_src" },
++ .parent_hws = (const struct clk_hw*[]){
++ &blsp2_uart1_apps_clk_src.clkr.hw,
++ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+@@ -1954,7 +2064,9 @@ static struct clk_branch gcc_blsp2_qup2_spi_apps_clk = {
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_blsp2_qup2_spi_apps_clk",
+- .parent_names = (const char *[]){ "blsp2_qup2_spi_apps_clk_src" },
++ .parent_hws = (const struct clk_hw*[]){
++ &blsp2_qup2_spi_apps_clk_src.clkr.hw,
++ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+@@ -1969,7 +2081,9 @@ static struct clk_branch gcc_blsp2_qup2_i2c_apps_clk = {
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_blsp2_qup2_i2c_apps_clk",
+- .parent_names = (const char *[]){ "blsp2_qup2_i2c_apps_clk_src" },
++ .parent_hws = (const struct clk_hw*[]){
++ &blsp2_qup2_i2c_apps_clk_src.clkr.hw,
++ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+@@ -1984,7 +2098,9 @@ static struct clk_branch gcc_blsp2_uart2_apps_clk = {
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_blsp2_uart2_apps_clk",
+- .parent_names = (const char *[]){ "blsp2_uart2_apps_clk_src" },
++ .parent_hws = (const struct clk_hw*[]){
++ &blsp2_uart2_apps_clk_src.clkr.hw,
++ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+@@ -1999,7 +2115,9 @@ static struct clk_branch gcc_blsp2_qup3_spi_apps_clk = {
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_blsp2_qup3_spi_apps_clk",
+- .parent_names = (const char *[]){ "blsp2_qup3_spi_apps_clk_src" },
++ .parent_hws = (const struct clk_hw*[]){
++ &blsp2_qup3_spi_apps_clk_src.clkr.hw,
++ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+@@ -2014,7 +2132,9 @@ static struct clk_branch gcc_blsp2_qup3_i2c_apps_clk = {
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_blsp2_qup3_i2c_apps_clk",
+- .parent_names = (const char *[]){ "blsp2_qup3_i2c_apps_clk_src" },
++ .parent_hws = (const struct clk_hw*[]){
++ &blsp2_qup3_i2c_apps_clk_src.clkr.hw,
++ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+@@ -2029,7 +2149,9 @@ static struct clk_branch gcc_blsp2_uart3_apps_clk = {
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_blsp2_uart3_apps_clk",
+- .parent_names = (const char *[]){ "blsp2_uart3_apps_clk_src" },
++ .parent_hws = (const struct clk_hw*[]){
++ &blsp2_uart3_apps_clk_src.clkr.hw,
++ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+@@ -2044,7 +2166,9 @@ static struct clk_branch gcc_blsp2_qup4_spi_apps_clk = {
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_blsp2_qup4_spi_apps_clk",
+- .parent_names = (const char *[]){ "blsp2_qup4_spi_apps_clk_src" },
++ .parent_hws = (const struct clk_hw*[]){
++ &blsp2_qup4_spi_apps_clk_src.clkr.hw,
++ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+@@ -2059,7 +2183,9 @@ static struct clk_branch gcc_blsp2_qup4_i2c_apps_clk = {
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_blsp2_qup4_i2c_apps_clk",
+- .parent_names = (const char *[]){ "blsp2_qup4_i2c_apps_clk_src" },
++ .parent_hws = (const struct clk_hw*[]){
++ &blsp2_qup4_i2c_apps_clk_src.clkr.hw,
++ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+@@ -2074,7 +2200,9 @@ static struct clk_branch gcc_blsp2_uart4_apps_clk = {
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_blsp2_uart4_apps_clk",
+- .parent_names = (const char *[]){ "blsp2_uart4_apps_clk_src" },
++ .parent_hws = (const struct clk_hw*[]){
++ &blsp2_uart4_apps_clk_src.clkr.hw,
++ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+@@ -2089,7 +2217,9 @@ static struct clk_branch gcc_blsp2_qup5_spi_apps_clk = {
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_blsp2_qup5_spi_apps_clk",
+- .parent_names = (const char *[]){ "blsp2_qup5_spi_apps_clk_src" },
++ .parent_hws = (const struct clk_hw*[]){
++ &blsp2_qup5_spi_apps_clk_src.clkr.hw,
++ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+@@ -2104,7 +2234,9 @@ static struct clk_branch gcc_blsp2_qup5_i2c_apps_clk = {
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_blsp2_qup5_i2c_apps_clk",
+- .parent_names = (const char *[]){ "blsp2_qup5_i2c_apps_clk_src" },
++ .parent_hws = (const struct clk_hw*[]){
++ &blsp2_qup5_i2c_apps_clk_src.clkr.hw,
++ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+@@ -2119,7 +2251,9 @@ static struct clk_branch gcc_blsp2_uart5_apps_clk = {
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_blsp2_uart5_apps_clk",
+- .parent_names = (const char *[]){ "blsp2_uart5_apps_clk_src" },
++ .parent_hws = (const struct clk_hw*[]){
++ &blsp2_uart5_apps_clk_src.clkr.hw,
++ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+@@ -2134,7 +2268,9 @@ static struct clk_branch gcc_blsp2_qup6_spi_apps_clk = {
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_blsp2_qup6_spi_apps_clk",
+- .parent_names = (const char *[]){ "blsp2_qup6_spi_apps_clk_src" },
++ .parent_hws = (const struct clk_hw*[]){
++ &blsp2_qup6_spi_apps_clk_src.clkr.hw,
++ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+@@ -2149,7 +2285,9 @@ static struct clk_branch gcc_blsp2_qup6_i2c_apps_clk = {
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_blsp2_qup6_i2c_apps_clk",
+- .parent_names = (const char *[]){ "blsp2_qup6_i2c_apps_clk_src" },
++ .parent_hws = (const struct clk_hw*[]){
++ &blsp2_qup6_i2c_apps_clk_src.clkr.hw,
++ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+@@ -2164,7 +2302,9 @@ static struct clk_branch gcc_blsp2_uart6_apps_clk = {
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_blsp2_uart6_apps_clk",
+- .parent_names = (const char *[]){ "blsp2_uart6_apps_clk_src" },
++ .parent_hws = (const struct clk_hw*[]){
++ &blsp2_uart6_apps_clk_src.clkr.hw,
++ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+@@ -2179,7 +2319,9 @@ static struct clk_branch gcc_pdm_ahb_clk = {
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_pdm_ahb_clk",
+- .parent_names = (const char *[]){ "periph_noc_clk_src" },
++ .parent_hws = (const struct clk_hw*[]){
++ &periph_noc_clk_src.clkr.hw,
++ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+@@ -2194,7 +2336,9 @@ static struct clk_branch gcc_pdm2_clk = {
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_pdm2_clk",
+- .parent_names = (const char *[]){ "pdm2_clk_src" },
++ .parent_hws = (const struct clk_hw*[]){
++ &pdm2_clk_src.clkr.hw,
++ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+@@ -2210,7 +2354,9 @@ static struct clk_branch gcc_prng_ahb_clk = {
+ .enable_mask = BIT(13),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_prng_ahb_clk",
+- .parent_names = (const char *[]){ "config_noc_clk_src" },
++ .parent_hws = (const struct clk_hw*[]){
++ &config_noc_clk_src.clkr.hw,
++ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+@@ -2225,7 +2371,9 @@ static struct clk_branch gcc_tsif_ahb_clk = {
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_tsif_ahb_clk",
+- .parent_names = (const char *[]){ "periph_noc_clk_src" },
++ .parent_hws = (const struct clk_hw*[]){
++ &periph_noc_clk_src.clkr.hw,
++ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+@@ -2240,7 +2388,9 @@ static struct clk_branch gcc_tsif_ref_clk = {
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_tsif_ref_clk",
+- .parent_names = (const char *[]){ "tsif_ref_clk_src" },
++ .parent_hws = (const struct clk_hw*[]){
++ &tsif_ref_clk_src.clkr.hw,
++ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+@@ -2255,7 +2405,9 @@ static struct clk_branch gcc_tsif_inactivity_timers_clk = {
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_tsif_inactivity_timers_clk",
+- .parent_names = (const char *[]){ "gcc_sleep_clk_src" },
++ .parent_hws = (const struct clk_hw*[]){
++ &gcc_sleep_clk_src.clkr.hw,
++ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+@@ -2271,7 +2423,9 @@ static struct clk_branch gcc_boot_rom_ahb_clk = {
+ .enable_mask = BIT(10),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_boot_rom_ahb_clk",
+- .parent_names = (const char *[]){ "config_noc_clk_src" },
++ .parent_hws = (const struct clk_hw*[]){
++ &config_noc_clk_src.clkr.hw,
++ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+@@ -2299,7 +2453,9 @@ static struct clk_branch gcc_hmss_rbcpr_clk = {
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_hmss_rbcpr_clk",
+- .parent_names = (const char *[]){ "hmss_rbcpr_clk_src" },
++ .parent_hws = (const struct clk_hw*[]){
++ &hmss_rbcpr_clk_src.clkr.hw,
++ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+@@ -2314,7 +2470,9 @@ static struct clk_branch gcc_gp1_clk = {
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_gp1_clk",
+- .parent_names = (const char *[]){ "gp1_clk_src" },
++ .parent_hws = (const struct clk_hw*[]){
++ &gp1_clk_src.clkr.hw,
++ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+@@ -2329,7 +2487,9 @@ static struct clk_branch gcc_gp2_clk = {
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_gp2_clk",
+- .parent_names = (const char *[]){ "gp2_clk_src" },
++ .parent_hws = (const struct clk_hw*[]){
++ &gp2_clk_src.clkr.hw,
++ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+@@ -2344,7 +2504,9 @@ static struct clk_branch gcc_gp3_clk = {
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_gp3_clk",
+- .parent_names = (const char *[]){ "gp3_clk_src" },
++ .parent_hws = (const struct clk_hw*[]){
++ &gp3_clk_src.clkr.hw,
++ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+@@ -2359,7 +2521,9 @@ static struct clk_branch gcc_pcie_0_slv_axi_clk = {
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_pcie_0_slv_axi_clk",
+- .parent_names = (const char *[]){ "system_noc_clk_src" },
++ .parent_hws = (const struct clk_hw*[]){
++ &system_noc_clk_src.clkr.hw,
++ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+@@ -2374,7 +2538,9 @@ static struct clk_branch gcc_pcie_0_mstr_axi_clk = {
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_pcie_0_mstr_axi_clk",
+- .parent_names = (const char *[]){ "system_noc_clk_src" },
++ .parent_hws = (const struct clk_hw*[]){
++ &system_noc_clk_src.clkr.hw,
++ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+@@ -2389,7 +2555,9 @@ static struct clk_branch gcc_pcie_0_cfg_ahb_clk = {
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_pcie_0_cfg_ahb_clk",
+- .parent_names = (const char *[]){ "config_noc_clk_src" },
++ .parent_hws = (const struct clk_hw*[]){
++ &config_noc_clk_src.clkr.hw,
++ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+@@ -2404,7 +2572,9 @@ static struct clk_branch gcc_pcie_0_aux_clk = {
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_pcie_0_aux_clk",
+- .parent_names = (const char *[]){ "pcie_aux_clk_src" },
++ .parent_hws = (const struct clk_hw*[]){
++ &pcie_aux_clk_src.clkr.hw,
++ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+@@ -2420,7 +2590,9 @@ static struct clk_branch gcc_pcie_0_pipe_clk = {
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_pcie_0_pipe_clk",
+- .parent_names = (const char *[]){ "pcie_0_pipe_clk_src" },
++ .parent_data = &(const struct clk_parent_data){
++ .fw_name = "pcie_0_pipe_clk_src", .name = "pcie_0_pipe_clk_src",
++ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+@@ -2435,7 +2607,9 @@ static struct clk_branch gcc_pcie_1_slv_axi_clk = {
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_pcie_1_slv_axi_clk",
+- .parent_names = (const char *[]){ "system_noc_clk_src" },
++ .parent_hws = (const struct clk_hw*[]){
++ &system_noc_clk_src.clkr.hw,
++ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+@@ -2450,7 +2624,9 @@ static struct clk_branch gcc_pcie_1_mstr_axi_clk = {
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_pcie_1_mstr_axi_clk",
+- .parent_names = (const char *[]){ "system_noc_clk_src" },
++ .parent_hws = (const struct clk_hw*[]){
++ &system_noc_clk_src.clkr.hw,
++ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+@@ -2465,7 +2641,9 @@ static struct clk_branch gcc_pcie_1_cfg_ahb_clk = {
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_pcie_1_cfg_ahb_clk",
+- .parent_names = (const char *[]){ "config_noc_clk_src" },
++ .parent_hws = (const struct clk_hw*[]){
++ &config_noc_clk_src.clkr.hw,
++ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+@@ -2480,7 +2658,9 @@ static struct clk_branch gcc_pcie_1_aux_clk = {
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_pcie_1_aux_clk",
+- .parent_names = (const char *[]){ "pcie_aux_clk_src" },
++ .parent_hws = (const struct clk_hw*[]){
++ &pcie_aux_clk_src.clkr.hw,
++ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+@@ -2496,7 +2676,9 @@ static struct clk_branch gcc_pcie_1_pipe_clk = {
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_pcie_1_pipe_clk",
+- .parent_names = (const char *[]){ "pcie_1_pipe_clk_src" },
++ .parent_data = &(const struct clk_parent_data){
++ .fw_name = "pcie_1_pipe_clk_src", .name = "pcie_1_pipe_clk_src",
++ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+@@ -2511,7 +2693,9 @@ static struct clk_branch gcc_pcie_2_slv_axi_clk = {
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_pcie_2_slv_axi_clk",
+- .parent_names = (const char *[]){ "system_noc_clk_src" },
++ .parent_hws = (const struct clk_hw*[]){
++ &system_noc_clk_src.clkr.hw,
++ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+@@ -2526,7 +2710,9 @@ static struct clk_branch gcc_pcie_2_mstr_axi_clk = {
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_pcie_2_mstr_axi_clk",
+- .parent_names = (const char *[]){ "system_noc_clk_src" },
++ .parent_hws = (const struct clk_hw*[]){
++ &system_noc_clk_src.clkr.hw,
++ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+@@ -2541,7 +2727,9 @@ static struct clk_branch gcc_pcie_2_cfg_ahb_clk = {
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_pcie_2_cfg_ahb_clk",
+- .parent_names = (const char *[]){ "config_noc_clk_src" },
++ .parent_hws = (const struct clk_hw*[]){
++ &config_noc_clk_src.clkr.hw,
++ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+@@ -2556,7 +2744,9 @@ static struct clk_branch gcc_pcie_2_aux_clk = {
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_pcie_2_aux_clk",
+- .parent_names = (const char *[]){ "pcie_aux_clk_src" },
++ .parent_hws = (const struct clk_hw*[]){
++ &pcie_aux_clk_src.clkr.hw,
++ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+@@ -2572,7 +2762,9 @@ static struct clk_branch gcc_pcie_2_pipe_clk = {
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_pcie_2_pipe_clk",
+- .parent_names = (const char *[]){ "pcie_2_pipe_clk_src" },
++ .parent_data = &(const struct clk_parent_data){
++ .fw_name = "pcie_2_pipe_clk_src", .name = "pcie_2_pipe_clk_src",
++ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+@@ -2587,7 +2779,9 @@ static struct clk_branch gcc_pcie_phy_cfg_ahb_clk = {
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_pcie_phy_cfg_ahb_clk",
+- .parent_names = (const char *[]){ "config_noc_clk_src" },
++ .parent_hws = (const struct clk_hw*[]){
++ &config_noc_clk_src.clkr.hw,
++ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+@@ -2602,7 +2796,9 @@ static struct clk_branch gcc_pcie_phy_aux_clk = {
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_pcie_phy_aux_clk",
+- .parent_names = (const char *[]){ "pcie_aux_clk_src" },
++ .parent_hws = (const struct clk_hw*[]){
++ &pcie_aux_clk_src.clkr.hw,
++ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+@@ -2617,7 +2813,9 @@ static struct clk_branch gcc_ufs_axi_clk = {
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_ufs_axi_clk",
+- .parent_names = (const char *[]){ "ufs_axi_clk_src" },
++ .parent_hws = (const struct clk_hw*[]){
++ &ufs_axi_clk_src.clkr.hw,
++ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+@@ -2632,7 +2830,9 @@ static struct clk_branch gcc_ufs_ahb_clk = {
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_ufs_ahb_clk",
+- .parent_names = (const char *[]){ "config_noc_clk_src" },
++ .parent_hws = (const struct clk_hw*[]){
++ &config_noc_clk_src.clkr.hw,
++ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+@@ -2645,7 +2845,9 @@ static struct clk_fixed_factor ufs_tx_cfg_clk_src = {
+ .div = 16,
+ .hw.init = &(struct clk_init_data){
+ .name = "ufs_tx_cfg_clk_src",
+- .parent_names = (const char *[]){ "ufs_axi_clk_src" },
++ .parent_hws = (const struct clk_hw*[]){
++ &ufs_axi_clk_src.clkr.hw,
++ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_fixed_factor_ops,
+@@ -2659,7 +2861,9 @@ static struct clk_branch gcc_ufs_tx_cfg_clk = {
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_ufs_tx_cfg_clk",
+- .parent_names = (const char *[]){ "ufs_tx_cfg_clk_src" },
++ .parent_hws = (const struct clk_hw*[]){
++ &ufs_tx_cfg_clk_src.hw,
++ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+@@ -2672,7 +2876,9 @@ static struct clk_fixed_factor ufs_rx_cfg_clk_src = {
+ .div = 16,
+ .hw.init = &(struct clk_init_data){
+ .name = "ufs_rx_cfg_clk_src",
+- .parent_names = (const char *[]){ "ufs_axi_clk_src" },
++ .parent_hws = (const struct clk_hw*[]){
++ &ufs_axi_clk_src.clkr.hw,
++ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_fixed_factor_ops,
+@@ -2712,7 +2918,9 @@ static struct clk_branch gcc_ufs_rx_cfg_clk = {
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_ufs_rx_cfg_clk",
+- .parent_names = (const char *[]){ "ufs_rx_cfg_clk_src" },
++ .parent_hws = (const struct clk_hw*[]){
++ &ufs_rx_cfg_clk_src.hw,
++ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+@@ -2728,7 +2936,9 @@ static struct clk_branch gcc_ufs_tx_symbol_0_clk = {
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_ufs_tx_symbol_0_clk",
+- .parent_names = (const char *[]){ "ufs_tx_symbol_0_clk_src" },
++ .parent_data = &(const struct clk_parent_data){
++ .fw_name = "ufs_tx_symbol_0_clk_src", .name = "ufs_tx_symbol_0_clk_src",
++ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+@@ -2744,7 +2954,9 @@ static struct clk_branch gcc_ufs_rx_symbol_0_clk = {
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_ufs_rx_symbol_0_clk",
+- .parent_names = (const char *[]){ "ufs_rx_symbol_0_clk_src" },
++ .parent_data = &(const struct clk_parent_data){
++ .fw_name = "ufs_rx_symbol_0_clk_src", .name = "ufs_rx_symbol_0_clk_src",
++ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+@@ -2760,7 +2972,9 @@ static struct clk_branch gcc_ufs_rx_symbol_1_clk = {
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_ufs_rx_symbol_1_clk",
+- .parent_names = (const char *[]){ "ufs_rx_symbol_1_clk_src" },
++ .parent_data = &(const struct clk_parent_data){
++ .fw_name = "ufs_rx_symbol_1_clk_src", .name = "ufs_rx_symbol_1_clk_src",
++ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+@@ -2773,7 +2987,9 @@ static struct clk_fixed_factor ufs_ice_core_postdiv_clk_src = {
+ .div = 2,
+ .hw.init = &(struct clk_init_data){
+ .name = "ufs_ice_core_postdiv_clk_src",
+- .parent_names = (const char *[]){ "ufs_ice_core_clk_src" },
++ .parent_hws = (const struct clk_hw*[]){
++ &ufs_ice_core_clk_src.clkr.hw,
++ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_fixed_factor_ops,
+@@ -2787,7 +3003,9 @@ static struct clk_branch gcc_ufs_unipro_core_clk = {
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_ufs_unipro_core_clk",
+- .parent_names = (const char *[]){ "ufs_ice_core_postdiv_clk_src" },
++ .parent_hws = (const struct clk_hw*[]){
++ &ufs_ice_core_postdiv_clk_src.hw,
++ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+@@ -2802,7 +3020,9 @@ static struct clk_branch gcc_ufs_ice_core_clk = {
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_ufs_ice_core_clk",
+- .parent_names = (const char *[]){ "ufs_ice_core_clk_src" },
++ .parent_hws = (const struct clk_hw*[]){
++ &ufs_ice_core_clk_src.clkr.hw,
++ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+@@ -2841,7 +3061,9 @@ static struct clk_branch gcc_aggre0_snoc_axi_clk = {
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_aggre0_snoc_axi_clk",
+- .parent_names = (const char *[]){ "system_noc_clk_src" },
++ .parent_hws = (const struct clk_hw*[]){
++ &system_noc_clk_src.clkr.hw,
++ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT | CLK_IS_CRITICAL,
+ .ops = &clk_branch2_ops,
+@@ -2856,7 +3078,9 @@ static struct clk_branch gcc_aggre0_cnoc_ahb_clk = {
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_aggre0_cnoc_ahb_clk",
+- .parent_names = (const char *[]){ "config_noc_clk_src" },
++ .parent_hws = (const struct clk_hw*[]){
++ &config_noc_clk_src.clkr.hw,
++ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT | CLK_IS_CRITICAL,
+ .ops = &clk_branch2_ops,
+@@ -2871,7 +3095,9 @@ static struct clk_branch gcc_smmu_aggre0_axi_clk = {
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_smmu_aggre0_axi_clk",
+- .parent_names = (const char *[]){ "system_noc_clk_src" },
++ .parent_hws = (const struct clk_hw*[]){
++ &system_noc_clk_src.clkr.hw,
++ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT | CLK_IS_CRITICAL,
+ .ops = &clk_branch2_ops,
+@@ -2886,7 +3112,9 @@ static struct clk_branch gcc_smmu_aggre0_ahb_clk = {
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_smmu_aggre0_ahb_clk",
+- .parent_names = (const char *[]){ "config_noc_clk_src" },
++ .parent_hws = (const struct clk_hw*[]){
++ &config_noc_clk_src.clkr.hw,
++ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT | CLK_IS_CRITICAL,
+ .ops = &clk_branch2_ops,
+@@ -2901,7 +3129,9 @@ static struct clk_branch gcc_aggre2_ufs_axi_clk = {
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_aggre2_ufs_axi_clk",
+- .parent_names = (const char *[]){ "ufs_axi_clk_src" },
++ .parent_hws = (const struct clk_hw*[]){
++ &ufs_axi_clk_src.clkr.hw,
++ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+@@ -2916,7 +3146,9 @@ static struct clk_branch gcc_aggre2_usb3_axi_clk = {
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_aggre2_usb3_axi_clk",
+- .parent_names = (const char *[]){ "usb30_master_clk_src" },
++ .parent_hws = (const struct clk_hw*[]){
++ &usb30_master_clk_src.clkr.hw,
++ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+@@ -2931,7 +3163,9 @@ static struct clk_branch gcc_dcc_ahb_clk = {
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_dcc_ahb_clk",
+- .parent_names = (const char *[]){ "config_noc_clk_src" },
++ .parent_hws = (const struct clk_hw*[]){
++ &config_noc_clk_src.clkr.hw,
++ },
+ .num_parents = 1,
+ .ops = &clk_branch2_ops,
+ },
+@@ -2945,7 +3179,9 @@ static struct clk_branch gcc_aggre0_noc_mpu_cfg_ahb_clk = {
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_aggre0_noc_mpu_cfg_ahb_clk",
+- .parent_names = (const char *[]){ "config_noc_clk_src" },
++ .parent_hws = (const struct clk_hw*[]){
++ &config_noc_clk_src.clkr.hw,
++ },
+ .num_parents = 1,
+ .ops = &clk_branch2_ops,
+ },
+@@ -2959,7 +3195,9 @@ static struct clk_branch gcc_qspi_ahb_clk = {
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_qspi_ahb_clk",
+- .parent_names = (const char *[]){ "periph_noc_clk_src" },
++ .parent_hws = (const struct clk_hw*[]){
++ &periph_noc_clk_src.clkr.hw,
++ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+@@ -2974,7 +3212,9 @@ static struct clk_branch gcc_qspi_ser_clk = {
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_qspi_ser_clk",
+- .parent_names = (const char *[]){ "qspi_ser_clk_src" },
++ .parent_hws = (const struct clk_hw*[]){
++ &qspi_ser_clk_src.clkr.hw,
++ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+@@ -3108,7 +3348,9 @@ static struct clk_branch gcc_mss_cfg_ahb_clk = {
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_mss_cfg_ahb_clk",
+- .parent_names = (const char *[]){ "config_noc_clk_src" },
++ .parent_hws = (const struct clk_hw*[]){
++ &config_noc_clk_src.clkr.hw,
++ },
+ .num_parents = 1,
+ .ops = &clk_branch2_ops,
+ },
+@@ -3122,7 +3364,9 @@ static struct clk_branch gcc_mss_mnoc_bimc_axi_clk = {
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_mss_mnoc_bimc_axi_clk",
+- .parent_names = (const char *[]){ "system_noc_clk_src" },
++ .parent_hws = (const struct clk_hw*[]){
++ &system_noc_clk_src.clkr.hw,
++ },
+ .num_parents = 1,
+ .ops = &clk_branch2_ops,
+ },
+@@ -3136,7 +3380,9 @@ static struct clk_branch gcc_mss_snoc_axi_clk = {
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_mss_snoc_axi_clk",
+- .parent_names = (const char *[]){ "system_noc_clk_src" },
++ .parent_hws = (const struct clk_hw*[]){
++ &system_noc_clk_src.clkr.hw,
++ },
+ .num_parents = 1,
+ .ops = &clk_branch2_ops,
+ },
+@@ -3150,7 +3396,9 @@ static struct clk_branch gcc_mss_q6_bimc_axi_clk = {
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_mss_q6_bimc_axi_clk",
+- .parent_names = (const char *[]){ "system_noc_clk_src" },
++ .parent_hws = (const struct clk_hw*[]){
++ &system_noc_clk_src.clkr.hw,
++ },
+ .num_parents = 1,
+ .ops = &clk_branch2_ops,
+ },
+--
+2.42.0
+
--- /dev/null
+From fc166442fa13945f36174f30a9e9220d700cc11e Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 13 Sep 2023 20:56:11 +0300
+Subject: clk: qcom: gcc-sm8150: Fix gcc_sdcc2_apps_clk_src
+
+From: Danila Tikhonov <danila@jiaxyga.com>
+
+[ Upstream commit 7138c244fb293f24ce8ab782961022eff00a10c4 ]
+
+Set .flags = CLK_OPS_PARENT_ENABLE to fix "gcc_sdcc2_apps_clk_src: rcg
+didn't update its configuration" error.
+
+Fixes: 2a1d7eb854bb ("clk: qcom: gcc: Add global clock controller driver for SM8150")
+Tested-by: Arseniy Velikanov <adomerlee@gmail.com>
+Signed-off-by: Danila Tikhonov <danila@jiaxyga.com>
+Reviewed-by: Konrad Dybcio <konrad.dybcio@linaro.org>
+Link: https://lore.kernel.org/r/20230913175612.8685-1-danila@jiaxyga.com
+Signed-off-by: Bjorn Andersson <andersson@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/clk/qcom/gcc-sm8150.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/drivers/clk/qcom/gcc-sm8150.c b/drivers/clk/qcom/gcc-sm8150.c
+index 2457944857197..e9ed963f129da 100644
+--- a/drivers/clk/qcom/gcc-sm8150.c
++++ b/drivers/clk/qcom/gcc-sm8150.c
+@@ -792,7 +792,7 @@ static struct clk_rcg2 gcc_sdcc2_apps_clk_src = {
+ .name = "gcc_sdcc2_apps_clk_src",
+ .parent_data = gcc_parents_6,
+ .num_parents = ARRAY_SIZE(gcc_parents_6),
+- .flags = CLK_SET_RATE_PARENT,
++ .flags = CLK_OPS_PARENT_ENABLE,
+ .ops = &clk_rcg2_floor_ops,
+ },
+ };
+--
+2.42.0
+
--- /dev/null
+From adfe05319d175bbf17fbb7bc8943fa6d72785993 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 9 Aug 2023 21:20:27 +0200
+Subject: clk: qcom: mmcc-msm8998: Don't check halt bit on some branch clks
+
+From: Konrad Dybcio <konrad.dybcio@linaro.org>
+
+[ Upstream commit 9906c4140897bbdbff7bb71c6ae67903cb9954ce ]
+
+Some branch clocks are governed externally and we're only supposed to
+send a request concerning their shutdown, not actually ensure it happens.
+
+Use the BRANCH_HALT_SKIP define to skip checking the halt bit.
+
+Fixes: d14b15b5931c ("clk: qcom: Add MSM8998 Multimedia Clock Controller (MMCC) driver")
+Reviewed-by: Jeffrey Hugo <quic_jhugo@quicinc.com>
+Signed-off-by: Konrad Dybcio <konrad.dybcio@linaro.org>
+Link: https://lore.kernel.org/r/20230531-topic-8998_mmssclk-v3-4-ba1b1fd9ee75@linaro.org
+Signed-off-by: Bjorn Andersson <andersson@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/clk/qcom/mmcc-msm8998.c | 3 +++
+ 1 file changed, 3 insertions(+)
+
+diff --git a/drivers/clk/qcom/mmcc-msm8998.c b/drivers/clk/qcom/mmcc-msm8998.c
+index 467dadccde026..8768cdcf0aa3c 100644
+--- a/drivers/clk/qcom/mmcc-msm8998.c
++++ b/drivers/clk/qcom/mmcc-msm8998.c
+@@ -2487,6 +2487,7 @@ static struct clk_branch fd_ahb_clk = {
+
+ static struct clk_branch mnoc_ahb_clk = {
+ .halt_reg = 0x5024,
++ .halt_check = BRANCH_HALT_SKIP,
+ .clkr = {
+ .enable_reg = 0x5024,
+ .enable_mask = BIT(0),
+@@ -2502,6 +2503,7 @@ static struct clk_branch mnoc_ahb_clk = {
+
+ static struct clk_branch bimc_smmu_ahb_clk = {
+ .halt_reg = 0xe004,
++ .halt_check = BRANCH_HALT_SKIP,
+ .hwcg_reg = 0xe004,
+ .hwcg_bit = 1,
+ .clkr = {
+@@ -2519,6 +2521,7 @@ static struct clk_branch bimc_smmu_ahb_clk = {
+
+ static struct clk_branch bimc_smmu_axi_clk = {
+ .halt_reg = 0xe008,
++ .halt_check = BRANCH_HALT_SKIP,
+ .hwcg_reg = 0xe008,
+ .hwcg_bit = 1,
+ .clkr = {
+--
+2.42.0
+
--- /dev/null
+From 5b22ce30176315e1b2fc0a5f1005a442a463c81c Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 9 Aug 2023 21:20:28 +0200
+Subject: clk: qcom: mmcc-msm8998: Fix the SMMU GDSC
+
+From: Konrad Dybcio <konrad.dybcio@linaro.org>
+
+[ Upstream commit 1fc62c8347397faf4e18249e88ecd4470c0a5357 ]
+
+The SMMU GDSC doesn't have to be ALWAYS-ON and shouldn't feature the
+HW_CTRL flag (it's separate from hw_ctrl_addr). In addition to that,
+it should feature a cxc entry for bimc_smmu_axi_clk and be marked as
+votable.
+
+Fix all of these issues.
+
+Fixes: d14b15b5931c ("clk: qcom: Add MSM8998 Multimedia Clock Controller (MMCC) driver")
+Signed-off-by: Konrad Dybcio <konrad.dybcio@linaro.org>
+Reviewed-by: Jeffrey Hugo <quic_jhugo@quicinc.com>
+Link: https://lore.kernel.org/r/20230531-topic-8998_mmssclk-v3-5-ba1b1fd9ee75@linaro.org
+Signed-off-by: Bjorn Andersson <andersson@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/clk/qcom/mmcc-msm8998.c | 4 +++-
+ 1 file changed, 3 insertions(+), 1 deletion(-)
+
+diff --git a/drivers/clk/qcom/mmcc-msm8998.c b/drivers/clk/qcom/mmcc-msm8998.c
+index 8768cdcf0aa3c..a68764cfb7930 100644
+--- a/drivers/clk/qcom/mmcc-msm8998.c
++++ b/drivers/clk/qcom/mmcc-msm8998.c
+@@ -2662,11 +2662,13 @@ static struct gdsc camss_cpp_gdsc = {
+ static struct gdsc bimc_smmu_gdsc = {
+ .gdscr = 0xe020,
+ .gds_hw_ctrl = 0xe024,
++ .cxcs = (unsigned int []){ 0xe008 },
++ .cxc_count = 1,
+ .pd = {
+ .name = "bimc_smmu",
+ },
+ .pwrsts = PWRSTS_OFF_ON,
+- .flags = HW_CTRL | ALWAYS_ON,
++ .flags = VOTABLE,
+ };
+
+ static struct clk_regmap *mmcc_msm8998_clocks[] = {
+--
+2.42.0
+
--- /dev/null
+From c59e1960079eee8ff88445181ee8e3862002557a Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 29 Sep 2023 08:38:52 +0300
+Subject: clk: renesas: rzg2l: Fix computation formula
+
+From: Claudiu Beznea <claudiu.beznea.uj@bp.renesas.com>
+
+[ Upstream commit a2b23159499efd36b2d63b3c4534075d12ddc97a ]
+
+According to the hardware manual for RZ/G2L
+(r01uh0914ej0130-rzg2l-rzg2lc.pdf), the computation formula for PLL rate
+is as follows:
+
+ Fout = ((m + k/65536) * Fin) / (p * 2^s)
+
+and k has values in the range [-32768, 32767]. Dividing k by 65536 with
+integer arithmetic gives zero all the time, causing slight differences
+b/w what has been set vs. what is displayed. Thus, get rid of this and
+decompose the formula before dividing k by 65536.
+
+Fixes: ef3c613ccd68a ("clk: renesas: Add CPG core wrapper for RZ/G2L SoC")
+Signed-off-by: Claudiu Beznea <claudiu.beznea.uj@bp.renesas.com>
+Reviewed-by: Geert Uytterhoeven <geert+renesas@glider.be>
+Link: https://lore.kernel.org/r/20230929053915.1530607-6-claudiu.beznea@bp.renesas.com
+Signed-off-by: Geert Uytterhoeven <geert+renesas@glider.be>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/clk/renesas/rzg2l-cpg.c | 12 ++++++------
+ 1 file changed, 6 insertions(+), 6 deletions(-)
+
+diff --git a/drivers/clk/renesas/rzg2l-cpg.c b/drivers/clk/renesas/rzg2l-cpg.c
+index a2eee53e1406a..79e4e977b23b1 100644
+--- a/drivers/clk/renesas/rzg2l-cpg.c
++++ b/drivers/clk/renesas/rzg2l-cpg.c
+@@ -41,7 +41,7 @@
+ #define GET_SHIFT(val) ((val >> 12) & 0xff)
+ #define GET_WIDTH(val) ((val >> 8) & 0xf)
+
+-#define KDIV(val) FIELD_GET(GENMASK(31, 16), val)
++#define KDIV(val) ((s16)FIELD_GET(GENMASK(31, 16), val))
+ #define MDIV(val) FIELD_GET(GENMASK(15, 6), val)
+ #define PDIV(val) FIELD_GET(GENMASK(5, 0), val)
+ #define SDIV(val) FIELD_GET(GENMASK(2, 0), val)
+@@ -146,18 +146,18 @@ static unsigned long rzg2l_cpg_pll_clk_recalc_rate(struct clk_hw *hw,
+ struct pll_clk *pll_clk = to_pll(hw);
+ struct rzg2l_cpg_priv *priv = pll_clk->priv;
+ unsigned int val1, val2;
+- unsigned int mult = 1;
+- unsigned int div = 1;
++ u64 rate;
+
+ if (pll_clk->type != CLK_TYPE_SAM_PLL)
+ return parent_rate;
+
+ val1 = readl(priv->base + GET_REG_SAMPLL_CLK1(pll_clk->conf));
+ val2 = readl(priv->base + GET_REG_SAMPLL_CLK2(pll_clk->conf));
+- mult = MDIV(val1) + KDIV(val1) / 65536;
+- div = PDIV(val1) << SDIV(val2);
+
+- return DIV_ROUND_CLOSEST_ULL((u64)parent_rate * mult, div);
++ rate = mul_u64_u32_shr(parent_rate, (MDIV(val1) << 16) + KDIV(val1),
++ 16 + SDIV(val2));
++
++ return DIV_ROUND_CLOSEST_ULL(rate, PDIV(val1));
+ }
+
+ static const struct clk_ops rzg2l_cpg_pll_ops = {
+--
+2.42.0
+
--- /dev/null
+From 470e9f76be081fe2f1e0d9231cc4e992cdc1988f Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 21 Feb 2022 17:25:20 +0100
+Subject: clk: renesas: rzg2l: Simplify multiplication/shift logic
+
+From: Geert Uytterhoeven <geert+renesas@glider.be>
+
+[ Upstream commit 29db30c45f07c929c86c40a5b85f18b69c89c638 ]
+
+"a * (1 << b)" == "a << b".
+
+No change in generated code.
+
+Signed-off-by: Geert Uytterhoeven <geert+renesas@glider.be>
+Link: https://lore.kernel.org/r/71e1cf2e30fb2d7966fc8ec6bab23eb7e24aa1c4.1645460687.git.geert+renesas@glider.be
+Stable-dep-of: a2b23159499e ("clk: renesas: rzg2l: Fix computation formula")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/clk/renesas/rzg2l-cpg.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/drivers/clk/renesas/rzg2l-cpg.c b/drivers/clk/renesas/rzg2l-cpg.c
+index 1c92e73cd2b8c..e435d88d9da89 100644
+--- a/drivers/clk/renesas/rzg2l-cpg.c
++++ b/drivers/clk/renesas/rzg2l-cpg.c
+@@ -155,7 +155,7 @@ static unsigned long rzg2l_cpg_pll_clk_recalc_rate(struct clk_hw *hw,
+ val1 = readl(priv->base + GET_REG_SAMPLL_CLK1(pll_clk->conf));
+ val2 = readl(priv->base + GET_REG_SAMPLL_CLK2(pll_clk->conf));
+ mult = MDIV(val1) + KDIV(val1) / 65536;
+- div = PDIV(val1) * (1 << SDIV(val2));
++ div = PDIV(val1) << SDIV(val2);
+
+ return DIV_ROUND_CLOSEST_ULL((u64)parent_rate * mult, div);
+ }
+--
+2.42.0
+
--- /dev/null
+From 35f907c3056a04fc7785faffab4742304c7096dc Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 12 Sep 2023 07:51:33 +0300
+Subject: clk: renesas: rzg2l: Use FIELD_GET() for PLL register fields
+
+From: Claudiu Beznea <claudiu.beznea.uj@bp.renesas.com>
+
+[ Upstream commit 72977f07b035e488c3f1928832a1616c6cae7278 ]
+
+Use FIELD_GET() for PLL register fields. This is its purpose.
+
+Signed-off-by: Claudiu Beznea <claudiu.beznea.uj@bp.renesas.com>
+Reviewed-by: Geert Uytterhoeven <geert+renesas@glider.be>
+Link: https://lore.kernel.org/r/20230912045157.177966-14-claudiu.beznea.uj@bp.renesas.com
+Signed-off-by: Geert Uytterhoeven <geert+renesas@glider.be>
+Stable-dep-of: a2b23159499e ("clk: renesas: rzg2l: Fix computation formula")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/clk/renesas/rzg2l-cpg.c | 10 +++++-----
+ 1 file changed, 5 insertions(+), 5 deletions(-)
+
+diff --git a/drivers/clk/renesas/rzg2l-cpg.c b/drivers/clk/renesas/rzg2l-cpg.c
+index e435d88d9da89..a2eee53e1406a 100644
+--- a/drivers/clk/renesas/rzg2l-cpg.c
++++ b/drivers/clk/renesas/rzg2l-cpg.c
+@@ -11,6 +11,7 @@
+ * Copyright (C) 2015 Renesas Electronics Corp.
+ */
+
++#include <linux/bitfield.h>
+ #include <linux/clk.h>
+ #include <linux/clk-provider.h>
+ #include <linux/clk/renesas.h>
+@@ -37,14 +38,13 @@
+ #define WARN_DEBUG(x) do { } while (0)
+ #endif
+
+-#define DIV_RSMASK(v, s, m) ((v >> s) & m)
+ #define GET_SHIFT(val) ((val >> 12) & 0xff)
+ #define GET_WIDTH(val) ((val >> 8) & 0xf)
+
+-#define KDIV(val) DIV_RSMASK(val, 16, 0xffff)
+-#define MDIV(val) DIV_RSMASK(val, 6, 0x3ff)
+-#define PDIV(val) DIV_RSMASK(val, 0, 0x3f)
+-#define SDIV(val) DIV_RSMASK(val, 0, 0x7)
++#define KDIV(val) FIELD_GET(GENMASK(31, 16), val)
++#define MDIV(val) FIELD_GET(GENMASK(15, 6), val)
++#define PDIV(val) FIELD_GET(GENMASK(5, 0), val)
++#define SDIV(val) FIELD_GET(GENMASK(2, 0), val)
+
+ #define CLK_ON_R(reg) (reg)
+ #define CLK_MON_R(reg) (0x180 + (reg))
+--
+2.42.0
+
--- /dev/null
+From 2fc5a9726d8632d69afa3aa5f144d44a875e5d3b Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 4 Oct 2023 20:36:00 +0100
+Subject: clk: scmi: Free scmi_clk allocated when the clocks with invalid info
+ are skipped
+
+From: Sudeep Holla <sudeep.holla@arm.com>
+
+[ Upstream commit 3537a75e73f3420614a358d0c8b390ea483cc87d ]
+
+Add the missing devm_kfree() when we skip the clocks with invalid or
+missing information from the firmware.
+
+Cc: Cristian Marussi <cristian.marussi@arm.com>
+Cc: Michael Turquette <mturquette@baylibre.com>
+Cc: Stephen Boyd <sboyd@kernel.org>
+Cc: linux-clk@vger.kernel.org
+Fixes: 6d6a1d82eaef ("clk: add support for clocks provided by SCMI")
+Link: https://lore.kernel.org/r/20231004193600.66232-1-sudeep.holla@arm.com
+Signed-off-by: Sudeep Holla <sudeep.holla@arm.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/clk/clk-scmi.c | 1 +
+ 1 file changed, 1 insertion(+)
+
+diff --git a/drivers/clk/clk-scmi.c b/drivers/clk/clk-scmi.c
+index 1e357d364ca26..a26027597a0ac 100644
+--- a/drivers/clk/clk-scmi.c
++++ b/drivers/clk/clk-scmi.c
+@@ -178,6 +178,7 @@ static int scmi_clocks_probe(struct scmi_device *sdev)
+ sclk->info = scmi_proto_clk_ops->info_get(ph, idx);
+ if (!sclk->info) {
+ dev_dbg(dev, "invalid clock info for idx %d\n", idx);
++ devm_kfree(dev, sclk);
+ continue;
+ }
+
+--
+2.42.0
+
--- /dev/null
+From 73685d5219ed276863a1eda06b155529f022956a Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 4 Feb 2022 09:14:47 +0200
+Subject: clk: ti: Add ti_dt_clk_name() helper to use clock-output-names
+
+From: Tony Lindgren <tony@atomide.com>
+
+[ Upstream commit 2c1593328d7f02fe49de5ad6b42c36296c9d6922 ]
+
+Let's create the clock alias based on the clock-output-names property if
+available. Also the component clock drivers can use ti_dt_clk_name() in
+the following patches.
+
+Signed-off-by: Tony Lindgren <tony@atomide.com>
+Link: https://lore.kernel.org/r/20220204071449.16762-7-tony@atomide.com
+Signed-off-by: Stephen Boyd <sboyd@kernel.org>
+Stable-dep-of: 7af5b9eadd64 ("clk: ti: fix double free in of_ti_divider_clk_setup()")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/clk/ti/clk.c | 20 +++++++++++++++++++-
+ drivers/clk/ti/clock.h | 1 +
+ 2 files changed, 20 insertions(+), 1 deletion(-)
+
+diff --git a/drivers/clk/ti/clk.c b/drivers/clk/ti/clk.c
+index 29eafab4353ef..b941ce0f3c394 100644
+--- a/drivers/clk/ti/clk.c
++++ b/drivers/clk/ti/clk.c
+@@ -402,6 +402,24 @@ static const struct of_device_id simple_clk_match_table[] __initconst = {
+ { }
+ };
+
++/**
++ * ti_dt_clk_name - init clock name from first output name or node name
++ * @np: device node
++ *
++ * Use the first clock-output-name for the clock name if found. Fall back
++ * to legacy naming based on node name.
++ */
++const char *ti_dt_clk_name(struct device_node *np)
++{
++ const char *name;
++
++ if (!of_property_read_string_index(np, "clock-output-names", 0,
++ &name))
++ return name;
++
++ return np->name;
++}
++
+ /**
+ * ti_clk_add_aliases - setup clock aliases
+ *
+@@ -418,7 +436,7 @@ void __init ti_clk_add_aliases(void)
+ clkspec.np = np;
+ clk = of_clk_get_from_provider(&clkspec);
+
+- ti_clk_add_alias(NULL, clk, np->name);
++ ti_clk_add_alias(NULL, clk, ti_dt_clk_name(np));
+ }
+ }
+
+diff --git a/drivers/clk/ti/clock.h b/drivers/clk/ti/clock.h
+index f1dd62de2bfcb..938f34e290ed2 100644
+--- a/drivers/clk/ti/clock.h
++++ b/drivers/clk/ti/clock.h
+@@ -214,6 +214,7 @@ struct clk *ti_clk_register(struct device *dev, struct clk_hw *hw,
+ const char *con);
+ struct clk *ti_clk_register_omap_hw(struct device *dev, struct clk_hw *hw,
+ const char *con);
++const char *ti_dt_clk_name(struct device_node *np);
+ int ti_clk_add_alias(struct device *dev, struct clk *clk, const char *con);
+ void ti_clk_add_aliases(void);
+
+--
+2.42.0
+
--- /dev/null
+From 272f8514e89246faf3b2039ed057bdf9d83966d4 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sun, 13 Nov 2022 19:11:46 +0100
+Subject: clk: ti: change ti_clk_register[_omap_hw]() API
+
+From: Dario Binacchi <dario.binacchi@amarulasolutions.com>
+
+[ Upstream commit 3400d546a741a2b2001d88e7fa29110d45a3930d ]
+
+The ti_clk_register() and ti_clk_register_omap_hw() functions are always
+called with the parameter of type "struct device" set to NULL, since the
+functions from which they are called always have a parameter of type
+"struct device_node". Replacing "struct device" type parameter with
+"struct device_node" will allow you to register a TI clock to the common
+clock framework by taking advantage of the facilities provided by the
+"struct device_node" type. Further, adding the "of_" prefix to the name
+of these functions explicitly binds them to the "struct device_node"
+type.
+
+The patch has been tested on a Beaglebone board.
+
+Signed-off-by: Dario Binacchi <dario.binacchi@amarulasolutions.com>
+Tested-by: Tony Lindgren <tony@atomide.com>
+Reviewed-by: Tony Lindgren <tony@atomide.com>
+Link: https://lore.kernel.org/r/20221113181147.1626585-1-dario.binacchi@amarulasolutions.com
+Signed-off-by: Stephen Boyd <sboyd@kernel.org>
+Stable-dep-of: 7af5b9eadd64 ("clk: ti: fix double free in of_ti_divider_clk_setup()")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/clk/ti/apll.c | 4 ++--
+ drivers/clk/ti/clk-dra7-atl.c | 2 +-
+ drivers/clk/ti/clk.c | 34 ++++++++++++++++------------------
+ drivers/clk/ti/clkctrl.c | 4 ++--
+ drivers/clk/ti/clock.h | 10 +++++-----
+ drivers/clk/ti/composite.c | 2 +-
+ drivers/clk/ti/divider.c | 2 +-
+ drivers/clk/ti/dpll.c | 4 ++--
+ drivers/clk/ti/fixed-factor.c | 2 +-
+ drivers/clk/ti/gate.c | 6 +++---
+ drivers/clk/ti/interface.c | 7 ++++---
+ drivers/clk/ti/mux.c | 6 +++---
+ 12 files changed, 41 insertions(+), 42 deletions(-)
+
+diff --git a/drivers/clk/ti/apll.c b/drivers/clk/ti/apll.c
+index e4db6b9a55c61..f921c6812852f 100644
+--- a/drivers/clk/ti/apll.c
++++ b/drivers/clk/ti/apll.c
+@@ -168,7 +168,7 @@ static void __init omap_clk_register_apll(void *user,
+ ad->clk_bypass = __clk_get_hw(clk);
+
+ name = ti_dt_clk_name(node);
+- clk = ti_clk_register_omap_hw(NULL, &clk_hw->hw, name);
++ clk = of_ti_clk_register_omap_hw(node, &clk_hw->hw, name);
+ if (!IS_ERR(clk)) {
+ of_clk_add_provider(node, of_clk_src_simple_get, clk);
+ kfree(init->parent_names);
+@@ -408,7 +408,7 @@ static void __init of_omap2_apll_setup(struct device_node *node)
+ goto cleanup;
+
+ name = ti_dt_clk_name(node);
+- clk = ti_clk_register_omap_hw(NULL, &clk_hw->hw, name);
++ clk = of_ti_clk_register_omap_hw(node, &clk_hw->hw, name);
+ if (!IS_ERR(clk)) {
+ of_clk_add_provider(node, of_clk_src_simple_get, clk);
+ kfree(init);
+diff --git a/drivers/clk/ti/clk-dra7-atl.c b/drivers/clk/ti/clk-dra7-atl.c
+index 5c278d6c985e9..62508e74a47a7 100644
+--- a/drivers/clk/ti/clk-dra7-atl.c
++++ b/drivers/clk/ti/clk-dra7-atl.c
+@@ -205,7 +205,7 @@ static void __init of_dra7_atl_clock_setup(struct device_node *node)
+
+ init.parent_names = parent_names;
+
+- clk = ti_clk_register(NULL, &clk_hw->hw, name);
++ clk = of_ti_clk_register(node, &clk_hw->hw, name);
+
+ if (!IS_ERR(clk)) {
+ of_clk_add_provider(node, of_clk_src_simple_get, clk);
+diff --git a/drivers/clk/ti/clk.c b/drivers/clk/ti/clk.c
+index b941ce0f3c394..6a39fb051b2ee 100644
+--- a/drivers/clk/ti/clk.c
++++ b/drivers/clk/ti/clk.c
+@@ -436,7 +436,7 @@ void __init ti_clk_add_aliases(void)
+ clkspec.np = np;
+ clk = of_clk_get_from_provider(&clkspec);
+
+- ti_clk_add_alias(NULL, clk, ti_dt_clk_name(np));
++ ti_clk_add_alias(clk, ti_dt_clk_name(np));
+ }
+ }
+
+@@ -489,7 +489,6 @@ void omap2_clk_enable_init_clocks(const char **clk_names, u8 num_clocks)
+
+ /**
+ * ti_clk_add_alias - add a clock alias for a TI clock
+- * @dev: device alias for this clock
+ * @clk: clock handle to create alias for
+ * @con: connection ID for this clock
+ *
+@@ -497,7 +496,7 @@ void omap2_clk_enable_init_clocks(const char **clk_names, u8 num_clocks)
+ * and assigns the data to it. Returns 0 if successful, negative error
+ * value otherwise.
+ */
+-int ti_clk_add_alias(struct device *dev, struct clk *clk, const char *con)
++int ti_clk_add_alias(struct clk *clk, const char *con)
+ {
+ struct clk_lookup *cl;
+
+@@ -511,8 +510,6 @@ int ti_clk_add_alias(struct device *dev, struct clk *clk, const char *con)
+ if (!cl)
+ return -ENOMEM;
+
+- if (dev)
+- cl->dev_id = dev_name(dev);
+ cl->con_id = con;
+ cl->clk = clk;
+
+@@ -522,8 +519,8 @@ int ti_clk_add_alias(struct device *dev, struct clk *clk, const char *con)
+ }
+
+ /**
+- * ti_clk_register - register a TI clock to the common clock framework
+- * @dev: device for this clock
++ * of_ti_clk_register - register a TI clock to the common clock framework
++ * @node: device node for this clock
+ * @hw: hardware clock handle
+ * @con: connection ID for this clock
+ *
+@@ -531,17 +528,18 @@ int ti_clk_add_alias(struct device *dev, struct clk *clk, const char *con)
+ * alias for it. Returns a handle to the registered clock if successful,
+ * ERR_PTR value in failure.
+ */
+-struct clk *ti_clk_register(struct device *dev, struct clk_hw *hw,
+- const char *con)
++struct clk *of_ti_clk_register(struct device_node *node, struct clk_hw *hw,
++ const char *con)
+ {
+ struct clk *clk;
+ int ret;
+
+- clk = clk_register(dev, hw);
+- if (IS_ERR(clk))
+- return clk;
++ ret = of_clk_hw_register(node, hw);
++ if (ret)
++ return ERR_PTR(ret);
+
+- ret = ti_clk_add_alias(dev, clk, con);
++ clk = hw->clk;
++ ret = ti_clk_add_alias(clk, con);
+ if (ret) {
+ clk_unregister(clk);
+ return ERR_PTR(ret);
+@@ -551,8 +549,8 @@ struct clk *ti_clk_register(struct device *dev, struct clk_hw *hw,
+ }
+
+ /**
+- * ti_clk_register_omap_hw - register a clk_hw_omap to the clock framework
+- * @dev: device for this clock
++ * of_ti_clk_register_omap_hw - register a clk_hw_omap to the clock framework
++ * @node: device node for this clock
+ * @hw: hardware clock handle
+ * @con: connection ID for this clock
+ *
+@@ -561,13 +559,13 @@ struct clk *ti_clk_register(struct device *dev, struct clk_hw *hw,
+ * Returns a handle to the registered clock if successful, ERR_PTR value
+ * in failure.
+ */
+-struct clk *ti_clk_register_omap_hw(struct device *dev, struct clk_hw *hw,
+- const char *con)
++struct clk *of_ti_clk_register_omap_hw(struct device_node *node,
++ struct clk_hw *hw, const char *con)
+ {
+ struct clk *clk;
+ struct clk_hw_omap *oclk;
+
+- clk = ti_clk_register(dev, hw, con);
++ clk = of_ti_clk_register(node, hw, con);
+ if (IS_ERR(clk))
+ return clk;
+
+diff --git a/drivers/clk/ti/clkctrl.c b/drivers/clk/ti/clkctrl.c
+index 157abc46dcf44..1424b615a4cc5 100644
+--- a/drivers/clk/ti/clkctrl.c
++++ b/drivers/clk/ti/clkctrl.c
+@@ -317,7 +317,7 @@ _ti_clkctrl_clk_register(struct omap_clkctrl_provider *provider,
+ init.ops = ops;
+ init.flags = 0;
+
+- clk = ti_clk_register(NULL, clk_hw, init.name);
++ clk = of_ti_clk_register(node, clk_hw, init.name);
+ if (IS_ERR_OR_NULL(clk)) {
+ ret = -EINVAL;
+ goto cleanup;
+@@ -701,7 +701,7 @@ static void __init _ti_omap4_clkctrl_setup(struct device_node *node)
+ init.ops = &omap4_clkctrl_clk_ops;
+ hw->hw.init = &init;
+
+- clk = ti_clk_register_omap_hw(NULL, &hw->hw, init.name);
++ clk = of_ti_clk_register_omap_hw(node, &hw->hw, init.name);
+ if (IS_ERR_OR_NULL(clk))
+ goto cleanup;
+
+diff --git a/drivers/clk/ti/clock.h b/drivers/clk/ti/clock.h
+index 938f34e290ed2..821f33ee330e4 100644
+--- a/drivers/clk/ti/clock.h
++++ b/drivers/clk/ti/clock.h
+@@ -210,12 +210,12 @@ extern const struct omap_clkctrl_data dm816_clkctrl_data[];
+
+ typedef void (*ti_of_clk_init_cb_t)(void *, struct device_node *);
+
+-struct clk *ti_clk_register(struct device *dev, struct clk_hw *hw,
+- const char *con);
+-struct clk *ti_clk_register_omap_hw(struct device *dev, struct clk_hw *hw,
+- const char *con);
++struct clk *of_ti_clk_register(struct device_node *node, struct clk_hw *hw,
++ const char *con);
++struct clk *of_ti_clk_register_omap_hw(struct device_node *node,
++ struct clk_hw *hw, const char *con);
+ const char *ti_dt_clk_name(struct device_node *np);
+-int ti_clk_add_alias(struct device *dev, struct clk *clk, const char *con);
++int ti_clk_add_alias(struct clk *clk, const char *con);
+ void ti_clk_add_aliases(void);
+
+ void ti_clk_latch(struct clk_omap_reg *reg, s8 shift);
+diff --git a/drivers/clk/ti/composite.c b/drivers/clk/ti/composite.c
+index 8d60319be3683..78d44158fb7d9 100644
+--- a/drivers/clk/ti/composite.c
++++ b/drivers/clk/ti/composite.c
+@@ -184,7 +184,7 @@ static void __init _register_composite(void *user,
+ &ti_composite_gate_ops, 0);
+
+ if (!IS_ERR(clk)) {
+- ret = ti_clk_add_alias(NULL, clk, name);
++ ret = ti_clk_add_alias(clk, name);
+ if (ret) {
+ clk_unregister(clk);
+ goto cleanup;
+diff --git a/drivers/clk/ti/divider.c b/drivers/clk/ti/divider.c
+index 9fbea0997b432..83931cc299713 100644
+--- a/drivers/clk/ti/divider.c
++++ b/drivers/clk/ti/divider.c
+@@ -334,7 +334,7 @@ static struct clk *_register_divider(struct device_node *node,
+ div->hw.init = &init;
+
+ /* register the clock */
+- clk = ti_clk_register(NULL, &div->hw, name);
++ clk = of_ti_clk_register(node, &div->hw, name);
+
+ if (IS_ERR(clk))
+ kfree(div);
+diff --git a/drivers/clk/ti/dpll.c b/drivers/clk/ti/dpll.c
+index 7c6dc8449b22f..9ef7133f2f57b 100644
+--- a/drivers/clk/ti/dpll.c
++++ b/drivers/clk/ti/dpll.c
+@@ -195,7 +195,7 @@ static void __init _register_dpll(void *user,
+
+ /* register the clock */
+ name = ti_dt_clk_name(node);
+- clk = ti_clk_register_omap_hw(NULL, &clk_hw->hw, name);
++ clk = of_ti_clk_register_omap_hw(node, &clk_hw->hw, name);
+
+ if (!IS_ERR(clk)) {
+ of_clk_add_provider(node, of_clk_src_simple_get, clk);
+@@ -267,7 +267,7 @@ static void _register_dpll_x2(struct device_node *node,
+ #endif
+
+ /* register the clock */
+- clk = ti_clk_register_omap_hw(NULL, &clk_hw->hw, name);
++ clk = of_ti_clk_register_omap_hw(node, &clk_hw->hw, name);
+
+ if (IS_ERR(clk))
+ kfree(clk_hw);
+diff --git a/drivers/clk/ti/fixed-factor.c b/drivers/clk/ti/fixed-factor.c
+index 8cb00d0af9662..a4f9c1c156137 100644
+--- a/drivers/clk/ti/fixed-factor.c
++++ b/drivers/clk/ti/fixed-factor.c
+@@ -62,7 +62,7 @@ static void __init of_ti_fixed_factor_clk_setup(struct device_node *node)
+ if (!IS_ERR(clk)) {
+ of_clk_add_provider(node, of_clk_src_simple_get, clk);
+ of_ti_clk_autoidle_setup(node);
+- ti_clk_add_alias(NULL, clk, clk_name);
++ ti_clk_add_alias(clk, clk_name);
+ }
+ }
+ CLK_OF_DECLARE(ti_fixed_factor_clk, "ti,fixed-factor-clock",
+diff --git a/drivers/clk/ti/gate.c b/drivers/clk/ti/gate.c
+index 0033de9beb4cd..b0d9d357861c2 100644
+--- a/drivers/clk/ti/gate.c
++++ b/drivers/clk/ti/gate.c
+@@ -93,7 +93,7 @@ static int omap36xx_gate_clk_enable_with_hsdiv_restore(struct clk_hw *hw)
+ return ret;
+ }
+
+-static struct clk *_register_gate(struct device *dev, const char *name,
++static struct clk *_register_gate(struct device_node *node, const char *name,
+ const char *parent_name, unsigned long flags,
+ struct clk_omap_reg *reg, u8 bit_idx,
+ u8 clk_gate_flags, const struct clk_ops *ops,
+@@ -123,7 +123,7 @@ static struct clk *_register_gate(struct device *dev, const char *name,
+
+ init.flags = flags;
+
+- clk = ti_clk_register_omap_hw(NULL, &clk_hw->hw, name);
++ clk = of_ti_clk_register_omap_hw(node, &clk_hw->hw, name);
+
+ if (IS_ERR(clk))
+ kfree(clk_hw);
+@@ -166,7 +166,7 @@ static void __init _of_ti_gate_clk_setup(struct device_node *node,
+ clk_gate_flags |= INVERT_ENABLE;
+
+ name = ti_dt_clk_name(node);
+- clk = _register_gate(NULL, name, parent_name, flags, ®,
++ clk = _register_gate(node, name, parent_name, flags, ®,
+ enable_bit, clk_gate_flags, ops, hw_ops);
+
+ if (!IS_ERR(clk))
+diff --git a/drivers/clk/ti/interface.c b/drivers/clk/ti/interface.c
+index dd2b455183a91..1ccd5dbf2bb48 100644
+--- a/drivers/clk/ti/interface.c
++++ b/drivers/clk/ti/interface.c
+@@ -32,7 +32,8 @@ static const struct clk_ops ti_interface_clk_ops = {
+ .is_enabled = &omap2_dflt_clk_is_enabled,
+ };
+
+-static struct clk *_register_interface(struct device *dev, const char *name,
++static struct clk *_register_interface(struct device_node *node,
++ const char *name,
+ const char *parent_name,
+ struct clk_omap_reg *reg, u8 bit_idx,
+ const struct clk_hw_omap_ops *ops)
+@@ -57,7 +58,7 @@ static struct clk *_register_interface(struct device *dev, const char *name,
+ init.num_parents = 1;
+ init.parent_names = &parent_name;
+
+- clk = ti_clk_register_omap_hw(NULL, &clk_hw->hw, name);
++ clk = of_ti_clk_register_omap_hw(node, &clk_hw->hw, name);
+
+ if (IS_ERR(clk))
+ kfree(clk_hw);
+@@ -88,7 +89,7 @@ static void __init _of_ti_interface_clk_setup(struct device_node *node,
+ }
+
+ name = ti_dt_clk_name(node);
+- clk = _register_interface(NULL, name, parent_name, ®,
++ clk = _register_interface(node, name, parent_name, ®,
+ enable_bit, ops);
+
+ if (!IS_ERR(clk))
+diff --git a/drivers/clk/ti/mux.c b/drivers/clk/ti/mux.c
+index 15de513d2d818..4205ff4bad217 100644
+--- a/drivers/clk/ti/mux.c
++++ b/drivers/clk/ti/mux.c
+@@ -126,7 +126,7 @@ const struct clk_ops ti_clk_mux_ops = {
+ .restore_context = clk_mux_restore_context,
+ };
+
+-static struct clk *_register_mux(struct device *dev, const char *name,
++static struct clk *_register_mux(struct device_node *node, const char *name,
+ const char * const *parent_names,
+ u8 num_parents, unsigned long flags,
+ struct clk_omap_reg *reg, u8 shift, u32 mask,
+@@ -156,7 +156,7 @@ static struct clk *_register_mux(struct device *dev, const char *name,
+ mux->table = table;
+ mux->hw.init = &init;
+
+- clk = ti_clk_register(dev, &mux->hw, name);
++ clk = of_ti_clk_register(node, &mux->hw, name);
+
+ if (IS_ERR(clk))
+ kfree(mux);
+@@ -215,7 +215,7 @@ static void of_mux_clk_setup(struct device_node *node)
+ mask = (1 << fls(mask)) - 1;
+
+ name = ti_dt_clk_name(node);
+- clk = _register_mux(NULL, name, parent_names, num_parents,
++ clk = _register_mux(node, name, parent_names, num_parents,
+ flags, ®, shift, mask, latch, clk_mux_flags,
+ NULL);
+
+--
+2.42.0
+
--- /dev/null
+From 3eb6c9b627fee0d03c9f5bd460fad4141187cb55 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 2 Oct 2023 10:04:36 +0300
+Subject: clk: ti: fix double free in of_ti_divider_clk_setup()
+
+From: Dan Carpenter <dan.carpenter@linaro.org>
+
+[ Upstream commit 7af5b9eadd64c9e02a71f97c45bcdf3b64841f6b ]
+
+The "div" pointer is freed in _register_divider() and again in
+of_ti_divider_clk_setup(). Delete the free in _register_divider()
+
+Fixes: fbbc18591585 ("clk: ti: divider: cleanup _register_divider and ti_clk_get_div_table")
+Signed-off-by: Dan Carpenter <dan.carpenter@linaro.org>
+Link: https://lore.kernel.org/r/6d36eeec-6c8a-4f11-a579-aa3cd7c38749@moroto.mountain
+Reviewed-by: Tony Lindgren <tony@atomide.com>
+Signed-off-by: Stephen Boyd <sboyd@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/clk/ti/divider.c | 8 +-------
+ 1 file changed, 1 insertion(+), 7 deletions(-)
+
+diff --git a/drivers/clk/ti/divider.c b/drivers/clk/ti/divider.c
+index 83931cc299713..4cc0aaa6cb139 100644
+--- a/drivers/clk/ti/divider.c
++++ b/drivers/clk/ti/divider.c
+@@ -317,7 +317,6 @@ static struct clk *_register_divider(struct device_node *node,
+ u32 flags,
+ struct clk_omap_divider *div)
+ {
+- struct clk *clk;
+ struct clk_init_data init;
+ const char *parent_name;
+ const char *name;
+@@ -334,12 +333,7 @@ static struct clk *_register_divider(struct device_node *node,
+ div->hw.init = &init;
+
+ /* register the clock */
+- clk = of_ti_clk_register(node, &div->hw, name);
+-
+- if (IS_ERR(clk))
+- kfree(div);
+-
+- return clk;
++ return of_ti_clk_register(node, &div->hw, name);
+ }
+
+ int ti_clk_parse_divider_data(int *div_table, int num_dividers, int max_div,
+--
+2.42.0
+
--- /dev/null
+From 815a983c9995ddd0e0da5beaf2a7f63a4fd660d3 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 4 Feb 2022 09:14:49 +0200
+Subject: clk: ti: Update component clocks to use ti_dt_clk_name()
+
+From: Tony Lindgren <tony@atomide.com>
+
+[ Upstream commit ed06099c5d0b329082cc19c58eace0b20bf7fe70 ]
+
+Let's update all the TI component clocks to use ti_dt_clk_name() instead
+of devicetree node name if available.
+
+Signed-off-by: Tony Lindgren <tony@atomide.com>
+Link: https://lore.kernel.org/r/20220204071449.16762-9-tony@atomide.com
+Signed-off-by: Stephen Boyd <sboyd@kernel.org>
+Stable-dep-of: 7af5b9eadd64 ("clk: ti: fix double free in of_ti_divider_clk_setup()")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/clk/ti/autoidle.c | 2 +-
+ drivers/clk/ti/clk-dra7-atl.c | 6 ++++--
+ drivers/clk/ti/composite.c | 6 ++++--
+ drivers/clk/ti/divider.c | 6 ++++--
+ drivers/clk/ti/fixed-factor.c | 2 +-
+ drivers/clk/ti/gate.c | 4 +++-
+ drivers/clk/ti/interface.c | 4 +++-
+ drivers/clk/ti/mux.c | 4 +++-
+ 8 files changed, 23 insertions(+), 11 deletions(-)
+
+diff --git a/drivers/clk/ti/autoidle.c b/drivers/clk/ti/autoidle.c
+index f6f8a409f148f..d6e5f1511ace8 100644
+--- a/drivers/clk/ti/autoidle.c
++++ b/drivers/clk/ti/autoidle.c
+@@ -205,7 +205,7 @@ int __init of_ti_clk_autoidle_setup(struct device_node *node)
+ return -ENOMEM;
+
+ clk->shift = shift;
+- clk->name = node->name;
++ clk->name = ti_dt_clk_name(node);
+ ret = ti_clk_get_reg_addr(node, 0, &clk->reg);
+ if (ret) {
+ kfree(clk);
+diff --git a/drivers/clk/ti/clk-dra7-atl.c b/drivers/clk/ti/clk-dra7-atl.c
+index e2e59d78c173f..5c278d6c985e9 100644
+--- a/drivers/clk/ti/clk-dra7-atl.c
++++ b/drivers/clk/ti/clk-dra7-atl.c
+@@ -173,6 +173,7 @@ static void __init of_dra7_atl_clock_setup(struct device_node *node)
+ struct dra7_atl_desc *clk_hw = NULL;
+ struct clk_init_data init = { NULL };
+ const char **parent_names = NULL;
++ const char *name;
+ struct clk *clk;
+
+ clk_hw = kzalloc(sizeof(*clk_hw), GFP_KERNEL);
+@@ -183,7 +184,8 @@ static void __init of_dra7_atl_clock_setup(struct device_node *node)
+
+ clk_hw->hw.init = &init;
+ clk_hw->divider = 1;
+- init.name = node->name;
++ name = ti_dt_clk_name(node);
++ init.name = name;
+ init.ops = &atl_clk_ops;
+ init.flags = CLK_IGNORE_UNUSED;
+ init.num_parents = of_clk_get_parent_count(node);
+@@ -203,7 +205,7 @@ static void __init of_dra7_atl_clock_setup(struct device_node *node)
+
+ init.parent_names = parent_names;
+
+- clk = ti_clk_register(NULL, &clk_hw->hw, node->name);
++ clk = ti_clk_register(NULL, &clk_hw->hw, name);
+
+ if (!IS_ERR(clk)) {
+ of_clk_add_provider(node, of_clk_src_simple_get, clk);
+diff --git a/drivers/clk/ti/composite.c b/drivers/clk/ti/composite.c
+index eaa43575cfa5e..8d60319be3683 100644
+--- a/drivers/clk/ti/composite.c
++++ b/drivers/clk/ti/composite.c
+@@ -125,6 +125,7 @@ static void __init _register_composite(void *user,
+ struct component_clk *comp;
+ int num_parents = 0;
+ const char **parent_names = NULL;
++ const char *name;
+ int i;
+ int ret;
+
+@@ -172,7 +173,8 @@ static void __init _register_composite(void *user,
+ goto cleanup;
+ }
+
+- clk = clk_register_composite(NULL, node->name,
++ name = ti_dt_clk_name(node);
++ clk = clk_register_composite(NULL, name,
+ parent_names, num_parents,
+ _get_hw(cclk, CLK_COMPONENT_TYPE_MUX),
+ &ti_clk_mux_ops,
+@@ -182,7 +184,7 @@ static void __init _register_composite(void *user,
+ &ti_composite_gate_ops, 0);
+
+ if (!IS_ERR(clk)) {
+- ret = ti_clk_add_alias(NULL, clk, node->name);
++ ret = ti_clk_add_alias(NULL, clk, name);
+ if (ret) {
+ clk_unregister(clk);
+ goto cleanup;
+diff --git a/drivers/clk/ti/divider.c b/drivers/clk/ti/divider.c
+index 28080df92f722..9fbea0997b432 100644
+--- a/drivers/clk/ti/divider.c
++++ b/drivers/clk/ti/divider.c
+@@ -320,10 +320,12 @@ static struct clk *_register_divider(struct device_node *node,
+ struct clk *clk;
+ struct clk_init_data init;
+ const char *parent_name;
++ const char *name;
+
+ parent_name = of_clk_get_parent_name(node, 0);
+
+- init.name = node->name;
++ name = ti_dt_clk_name(node);
++ init.name = name;
+ init.ops = &ti_clk_divider_ops;
+ init.flags = flags;
+ init.parent_names = (parent_name ? &parent_name : NULL);
+@@ -332,7 +334,7 @@ static struct clk *_register_divider(struct device_node *node,
+ div->hw.init = &init;
+
+ /* register the clock */
+- clk = ti_clk_register(NULL, &div->hw, node->name);
++ clk = ti_clk_register(NULL, &div->hw, name);
+
+ if (IS_ERR(clk))
+ kfree(div);
+diff --git a/drivers/clk/ti/fixed-factor.c b/drivers/clk/ti/fixed-factor.c
+index 7cbe896db0716..8cb00d0af9662 100644
+--- a/drivers/clk/ti/fixed-factor.c
++++ b/drivers/clk/ti/fixed-factor.c
+@@ -36,7 +36,7 @@
+ static void __init of_ti_fixed_factor_clk_setup(struct device_node *node)
+ {
+ struct clk *clk;
+- const char *clk_name = node->name;
++ const char *clk_name = ti_dt_clk_name(node);
+ const char *parent_name;
+ u32 div, mult;
+ u32 flags = 0;
+diff --git a/drivers/clk/ti/gate.c b/drivers/clk/ti/gate.c
+index b1d0fdb40a75a..0033de9beb4cd 100644
+--- a/drivers/clk/ti/gate.c
++++ b/drivers/clk/ti/gate.c
+@@ -138,6 +138,7 @@ static void __init _of_ti_gate_clk_setup(struct device_node *node,
+ struct clk *clk;
+ const char *parent_name;
+ struct clk_omap_reg reg;
++ const char *name;
+ u8 enable_bit = 0;
+ u32 val;
+ u32 flags = 0;
+@@ -164,7 +165,8 @@ static void __init _of_ti_gate_clk_setup(struct device_node *node,
+ if (of_property_read_bool(node, "ti,set-bit-to-disable"))
+ clk_gate_flags |= INVERT_ENABLE;
+
+- clk = _register_gate(NULL, node->name, parent_name, flags, ®,
++ name = ti_dt_clk_name(node);
++ clk = _register_gate(NULL, name, parent_name, flags, ®,
+ enable_bit, clk_gate_flags, ops, hw_ops);
+
+ if (!IS_ERR(clk))
+diff --git a/drivers/clk/ti/interface.c b/drivers/clk/ti/interface.c
+index 83e34429d3b10..dd2b455183a91 100644
+--- a/drivers/clk/ti/interface.c
++++ b/drivers/clk/ti/interface.c
+@@ -72,6 +72,7 @@ static void __init _of_ti_interface_clk_setup(struct device_node *node,
+ const char *parent_name;
+ struct clk_omap_reg reg;
+ u8 enable_bit = 0;
++ const char *name;
+ u32 val;
+
+ if (ti_clk_get_reg_addr(node, 0, ®))
+@@ -86,7 +87,8 @@ static void __init _of_ti_interface_clk_setup(struct device_node *node,
+ return;
+ }
+
+- clk = _register_interface(NULL, node->name, parent_name, ®,
++ name = ti_dt_clk_name(node);
++ clk = _register_interface(NULL, name, parent_name, ®,
+ enable_bit, ops);
+
+ if (!IS_ERR(clk))
+diff --git a/drivers/clk/ti/mux.c b/drivers/clk/ti/mux.c
+index 0069e7cf3ebcc..15de513d2d818 100644
+--- a/drivers/clk/ti/mux.c
++++ b/drivers/clk/ti/mux.c
+@@ -176,6 +176,7 @@ static void of_mux_clk_setup(struct device_node *node)
+ struct clk_omap_reg reg;
+ unsigned int num_parents;
+ const char **parent_names;
++ const char *name;
+ u8 clk_mux_flags = 0;
+ u32 mask = 0;
+ u32 shift = 0;
+@@ -213,7 +214,8 @@ static void of_mux_clk_setup(struct device_node *node)
+
+ mask = (1 << fls(mask)) - 1;
+
+- clk = _register_mux(NULL, node->name, parent_names, num_parents,
++ name = ti_dt_clk_name(node);
++ clk = _register_mux(NULL, name, parent_names, num_parents,
+ flags, ®, shift, mask, latch, clk_mux_flags,
+ NULL);
+
+--
+2.42.0
+
--- /dev/null
+From 3f872f672656ea4f9f168f8cf5ed146cf6c449d2 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 4 Feb 2022 09:14:48 +0200
+Subject: clk: ti: Update pll and clockdomain clocks to use ti_dt_clk_name()
+
+From: Tony Lindgren <tony@atomide.com>
+
+[ Upstream commit 9e56a7d4263ca1c51d867e811cf2dd7e61b6469e ]
+
+Let's update the TI pll and clockdomain clocks to use ti_dt_clk_name()
+instead of devicetree node name if available.
+
+Signed-off-by: Tony Lindgren <tony@atomide.com>
+Link: https://lore.kernel.org/r/20220204071449.16762-8-tony@atomide.com
+Signed-off-by: Stephen Boyd <sboyd@kernel.org>
+Stable-dep-of: 7af5b9eadd64 ("clk: ti: fix double free in of_ti_divider_clk_setup()")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/clk/ti/apll.c | 13 +++++++++----
+ drivers/clk/ti/clockdomain.c | 2 +-
+ drivers/clk/ti/dpll.c | 8 +++++---
+ drivers/clk/ti/fapll.c | 11 +++++++----
+ 4 files changed, 22 insertions(+), 12 deletions(-)
+
+diff --git a/drivers/clk/ti/apll.c b/drivers/clk/ti/apll.c
+index ac5bc8857a514..e4db6b9a55c61 100644
+--- a/drivers/clk/ti/apll.c
++++ b/drivers/clk/ti/apll.c
+@@ -139,6 +139,7 @@ static void __init omap_clk_register_apll(void *user,
+ struct clk_hw *hw = user;
+ struct clk_hw_omap *clk_hw = to_clk_hw_omap(hw);
+ struct dpll_data *ad = clk_hw->dpll_data;
++ const char *name;
+ struct clk *clk;
+ const struct clk_init_data *init = clk_hw->hw.init;
+
+@@ -166,7 +167,8 @@ static void __init omap_clk_register_apll(void *user,
+
+ ad->clk_bypass = __clk_get_hw(clk);
+
+- clk = ti_clk_register_omap_hw(NULL, &clk_hw->hw, node->name);
++ name = ti_dt_clk_name(node);
++ clk = ti_clk_register_omap_hw(NULL, &clk_hw->hw, name);
+ if (!IS_ERR(clk)) {
+ of_clk_add_provider(node, of_clk_src_simple_get, clk);
+ kfree(init->parent_names);
+@@ -198,7 +200,7 @@ static void __init of_dra7_apll_setup(struct device_node *node)
+ clk_hw->dpll_data = ad;
+ clk_hw->hw.init = init;
+
+- init->name = node->name;
++ init->name = ti_dt_clk_name(node);
+ init->ops = &apll_ck_ops;
+
+ init->num_parents = of_clk_get_parent_count(node);
+@@ -347,6 +349,7 @@ static void __init of_omap2_apll_setup(struct device_node *node)
+ struct dpll_data *ad = NULL;
+ struct clk_hw_omap *clk_hw = NULL;
+ struct clk_init_data *init = NULL;
++ const char *name;
+ struct clk *clk;
+ const char *parent_name;
+ u32 val;
+@@ -362,7 +365,8 @@ static void __init of_omap2_apll_setup(struct device_node *node)
+ clk_hw->dpll_data = ad;
+ clk_hw->hw.init = init;
+ init->ops = &omap2_apll_ops;
+- init->name = node->name;
++ name = ti_dt_clk_name(node);
++ init->name = name;
+ clk_hw->ops = &omap2_apll_hwops;
+
+ init->num_parents = of_clk_get_parent_count(node);
+@@ -403,7 +407,8 @@ static void __init of_omap2_apll_setup(struct device_node *node)
+ if (ret)
+ goto cleanup;
+
+- clk = ti_clk_register_omap_hw(NULL, &clk_hw->hw, node->name);
++ name = ti_dt_clk_name(node);
++ clk = ti_clk_register_omap_hw(NULL, &clk_hw->hw, name);
+ if (!IS_ERR(clk)) {
+ of_clk_add_provider(node, of_clk_src_simple_get, clk);
+ kfree(init);
+diff --git a/drivers/clk/ti/clockdomain.c b/drivers/clk/ti/clockdomain.c
+index 74831b2752b3b..24179c907774a 100644
+--- a/drivers/clk/ti/clockdomain.c
++++ b/drivers/clk/ti/clockdomain.c
+@@ -131,7 +131,7 @@ static void __init of_ti_clockdomain_setup(struct device_node *node)
+ {
+ struct clk *clk;
+ struct clk_hw *clk_hw;
+- const char *clkdm_name = node->name;
++ const char *clkdm_name = ti_dt_clk_name(node);
+ int i;
+ unsigned int num_clks;
+
+diff --git a/drivers/clk/ti/dpll.c b/drivers/clk/ti/dpll.c
+index e9f9aee936ae8..7c6dc8449b22f 100644
+--- a/drivers/clk/ti/dpll.c
++++ b/drivers/clk/ti/dpll.c
+@@ -164,6 +164,7 @@ static void __init _register_dpll(void *user,
+ struct clk_hw *hw = user;
+ struct clk_hw_omap *clk_hw = to_clk_hw_omap(hw);
+ struct dpll_data *dd = clk_hw->dpll_data;
++ const char *name;
+ struct clk *clk;
+ const struct clk_init_data *init = hw->init;
+
+@@ -193,7 +194,8 @@ static void __init _register_dpll(void *user,
+ dd->clk_bypass = __clk_get_hw(clk);
+
+ /* register the clock */
+- clk = ti_clk_register_omap_hw(NULL, &clk_hw->hw, node->name);
++ name = ti_dt_clk_name(node);
++ clk = ti_clk_register_omap_hw(NULL, &clk_hw->hw, name);
+
+ if (!IS_ERR(clk)) {
+ of_clk_add_provider(node, of_clk_src_simple_get, clk);
+@@ -227,7 +229,7 @@ static void _register_dpll_x2(struct device_node *node,
+ struct clk *clk;
+ struct clk_init_data init = { NULL };
+ struct clk_hw_omap *clk_hw;
+- const char *name = node->name;
++ const char *name = ti_dt_clk_name(node);
+ const char *parent_name;
+
+ parent_name = of_clk_get_parent_name(node, 0);
+@@ -304,7 +306,7 @@ static void __init of_ti_dpll_setup(struct device_node *node,
+ clk_hw->ops = &clkhwops_omap3_dpll;
+ clk_hw->hw.init = init;
+
+- init->name = node->name;
++ init->name = ti_dt_clk_name(node);
+ init->ops = ops;
+
+ init->num_parents = of_clk_get_parent_count(node);
+diff --git a/drivers/clk/ti/fapll.c b/drivers/clk/ti/fapll.c
+index 8024c6d2b9e95..749c6b73abff3 100644
+--- a/drivers/clk/ti/fapll.c
++++ b/drivers/clk/ti/fapll.c
+@@ -19,6 +19,8 @@
+ #include <linux/of_address.h>
+ #include <linux/clk/ti.h>
+
++#include "clock.h"
++
+ /* FAPLL Control Register PLL_CTRL */
+ #define FAPLL_MAIN_MULT_N_SHIFT 16
+ #define FAPLL_MAIN_DIV_P_SHIFT 8
+@@ -542,6 +544,7 @@ static void __init ti_fapll_setup(struct device_node *node)
+ struct clk_init_data *init = NULL;
+ const char *parent_name[2];
+ struct clk *pll_clk;
++ const char *name;
+ int i;
+
+ fd = kzalloc(sizeof(*fd), GFP_KERNEL);
+@@ -559,7 +562,8 @@ static void __init ti_fapll_setup(struct device_node *node)
+ goto free;
+
+ init->ops = &ti_fapll_ops;
+- init->name = node->name;
++ name = ti_dt_clk_name(node);
++ init->name = name;
+
+ init->num_parents = of_clk_get_parent_count(node);
+ if (init->num_parents != 2) {
+@@ -591,7 +595,7 @@ static void __init ti_fapll_setup(struct device_node *node)
+ if (fapll_is_ddr_pll(fd->base))
+ fd->bypass_bit_inverted = true;
+
+- fd->name = node->name;
++ fd->name = name;
+ fd->hw.init = init;
+
+ /* Register the parent PLL */
+@@ -638,8 +642,7 @@ static void __init ti_fapll_setup(struct device_node *node)
+ freq = NULL;
+ }
+ synth_clk = ti_fapll_synth_setup(fd, freq, div, output_instance,
+- output_name, node->name,
+- pll_clk);
++ output_name, name, pll_clk);
+ if (IS_ERR(synth_clk))
+ continue;
+
+--
+2.42.0
+
--- /dev/null
+From 51648916509b04fb13d4b445e7bf85355ea8e330 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 21 Sep 2023 18:12:37 +0530
+Subject: crypto: caam/jr - fix Chacha20 + Poly1305 self test failure
+
+From: Gaurav Jain <gaurav.jain@nxp.com>
+
+[ Upstream commit a8d3cdcc092fb2f2882acb6c20473a1be0ef4484 ]
+
+key buffer is not copied in chachapoly_setkey function,
+results in wrong output for encryption/decryption operation.
+
+fix this by memcpy the key in caam_ctx key arrary
+
+Fixes: d6bbd4eea243 ("crypto: caam/jr - add support for Chacha20 + Poly1305")
+Signed-off-by: Gaurav Jain <gaurav.jain@nxp.com>
+Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/crypto/caam/caamalg.c | 3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+diff --git a/drivers/crypto/caam/caamalg.c b/drivers/crypto/caam/caamalg.c
+index d3d8bb0a69900..e156238b4da90 100644
+--- a/drivers/crypto/caam/caamalg.c
++++ b/drivers/crypto/caam/caamalg.c
+@@ -566,7 +566,8 @@ static int chachapoly_setkey(struct crypto_aead *aead, const u8 *key,
+ if (keylen != CHACHA_KEY_SIZE + saltlen)
+ return -EINVAL;
+
+- ctx->cdata.key_virt = key;
++ memcpy(ctx->key, key, keylen);
++ ctx->cdata.key_virt = ctx->key;
+ ctx->cdata.keylen = keylen - saltlen;
+
+ return chachapoly_set_sh_desc(aead);
+--
+2.42.0
+
--- /dev/null
+From 8e7a1bce651a8d8ecac288a59a7a119fc147db55 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 21 Sep 2023 15:14:44 +0530
+Subject: crypto: caam/qi2 - fix Chacha20 + Poly1305 self test failure
+
+From: Gaurav Jain <gaurav.jain@nxp.com>
+
+[ Upstream commit 7b8c6aee0d5b864e70c0da82583f9862e374eaf3 ]
+
+key buffer is not copied in chachapoly_setkey function,
+results in wrong output for encryption/decryption operation.
+
+fix this by memcpy the key in caam_ctx key arrary
+
+Fixes: c10a53367901 ("crypto: caam/qi2 - add support for Chacha20 + Poly1305")
+Signed-off-by: Gaurav Jain <gaurav.jain@nxp.com>
+Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/crypto/caam/caamalg_qi2.c | 3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+diff --git a/drivers/crypto/caam/caamalg_qi2.c b/drivers/crypto/caam/caamalg_qi2.c
+index 6753f0e6e55d1..35c4e29033d55 100644
+--- a/drivers/crypto/caam/caamalg_qi2.c
++++ b/drivers/crypto/caam/caamalg_qi2.c
+@@ -639,7 +639,8 @@ static int chachapoly_setkey(struct crypto_aead *aead, const u8 *key,
+ if (keylen != CHACHA_KEY_SIZE + saltlen)
+ return -EINVAL;
+
+- ctx->cdata.key_virt = key;
++ memcpy(ctx->key, key, keylen);
++ ctx->cdata.key_virt = ctx->key;
+ ctx->cdata.keylen = keylen - saltlen;
+
+ return chachapoly_set_sh_desc(aead);
+--
+2.42.0
+
--- /dev/null
+From 3d7fbdb353d28bd8b18652d9136803a479eefebc Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 4 Sep 2023 22:17:29 +0200
+Subject: crypto: hisilicon/hpre - Fix a erroneous check after snprintf()
+
+From: Christophe JAILLET <christophe.jaillet@wanadoo.fr>
+
+[ Upstream commit c977950146720abff14e46d8c53f5638b06a9182 ]
+
+This error handling looks really strange.
+Check if the string has been truncated instead.
+
+Fixes: 02ab994635eb ("crypto: hisilicon - Fixed some tiny bugs of HPRE")
+Signed-off-by: Christophe JAILLET <christophe.jaillet@wanadoo.fr>
+Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/crypto/hisilicon/hpre/hpre_main.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/drivers/crypto/hisilicon/hpre/hpre_main.c b/drivers/crypto/hisilicon/hpre/hpre_main.c
+index edc61e4105f30..08e56f1da365c 100644
+--- a/drivers/crypto/hisilicon/hpre/hpre_main.c
++++ b/drivers/crypto/hisilicon/hpre/hpre_main.c
+@@ -854,7 +854,7 @@ static int hpre_cluster_debugfs_init(struct hisi_qm *qm)
+
+ for (i = 0; i < clusters_num; i++) {
+ ret = snprintf(buf, HPRE_DBGFS_VAL_MAX_LEN, "cluster%d", i);
+- if (ret < 0)
++ if (ret >= HPRE_DBGFS_VAL_MAX_LEN)
+ return -EINVAL;
+ tmp_d = debugfs_create_dir(buf, qm->debug.debug_root);
+
+--
+2.42.0
+
--- /dev/null
+From 6b3d9ebde2c07386924ccc81f4ad196bf6e8fa88 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 20 Oct 2023 16:33:21 +0100
+Subject: crypto: qat - fix deadlock in backlog processing
+
+From: Giovanni Cabiddu <giovanni.cabiddu@intel.com>
+
+[ Upstream commit 203b01001c4d741205b9c329acddc5193ed56fbd ]
+
+If a request has the flag CRYPTO_TFM_REQ_MAY_BACKLOG set, the function
+qat_alg_send_message_maybacklog(), enqueues it in a backlog list if
+either (1) there is already at least one request in the backlog list, or
+(2) the HW ring is nearly full or (3) the enqueue to the HW ring fails.
+If an interrupt occurs right before the lock in qat_alg_backlog_req() is
+taken and the backlog queue is being emptied, then there is no request
+in the HW queues that can trigger a subsequent interrupt that can clear
+the backlog queue. In addition subsequent requests are enqueued to the
+backlog list and not sent to the hardware.
+
+Fix it by holding the lock while taking the decision if the request
+needs to be included in the backlog queue or not. This synchronizes the
+flow with the interrupt handler that drains the backlog queue.
+
+For performance reasons, the logic has been changed to try to enqueue
+first without holding the lock.
+
+Fixes: 386823839732 ("crypto: qat - add backlog mechanism")
+Reported-by: Mikulas Patocka <mpatocka@redhat.com>
+Closes: https://lore.kernel.org/all/af9581e2-58f9-cc19-428f-6f18f1f83d54@redhat.com/T/
+Signed-off-by: Giovanni Cabiddu <giovanni.cabiddu@intel.com>
+Reviewed-by: Mikulas Patocka <mpatocka@redhat.com>
+Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/crypto/qat/qat_common/qat_algs_send.c | 46 ++++++++++---------
+ 1 file changed, 25 insertions(+), 21 deletions(-)
+
+diff --git a/drivers/crypto/qat/qat_common/qat_algs_send.c b/drivers/crypto/qat/qat_common/qat_algs_send.c
+index ff5b4347f7831..607ed88f4b197 100644
+--- a/drivers/crypto/qat/qat_common/qat_algs_send.c
++++ b/drivers/crypto/qat/qat_common/qat_algs_send.c
+@@ -39,40 +39,44 @@ void qat_alg_send_backlog(struct qat_instance_backlog *backlog)
+ spin_unlock_bh(&backlog->lock);
+ }
+
+-static void qat_alg_backlog_req(struct qat_alg_req *req,
+- struct qat_instance_backlog *backlog)
+-{
+- INIT_LIST_HEAD(&req->list);
+-
+- spin_lock_bh(&backlog->lock);
+- list_add_tail(&req->list, &backlog->list);
+- spin_unlock_bh(&backlog->lock);
+-}
+-
+-static int qat_alg_send_message_maybacklog(struct qat_alg_req *req)
++static bool qat_alg_try_enqueue(struct qat_alg_req *req)
+ {
+ struct qat_instance_backlog *backlog = req->backlog;
+ struct adf_etr_ring_data *tx_ring = req->tx_ring;
+ u32 *fw_req = req->fw_req;
+
+- /* If any request is already backlogged, then add to backlog list */
++ /* Check if any request is already backlogged */
+ if (!list_empty(&backlog->list))
+- goto enqueue;
++ return false;
+
+- /* If ring is nearly full, then add to backlog list */
++ /* Check if ring is nearly full */
+ if (adf_ring_nearly_full(tx_ring))
+- goto enqueue;
++ return false;
+
+- /* If adding request to HW ring fails, then add to backlog list */
++ /* Try to enqueue to HW ring */
+ if (adf_send_message(tx_ring, fw_req))
+- goto enqueue;
++ return false;
+
+- return -EINPROGRESS;
++ return true;
++}
+
+-enqueue:
+- qat_alg_backlog_req(req, backlog);
+
+- return -EBUSY;
++static int qat_alg_send_message_maybacklog(struct qat_alg_req *req)
++{
++ struct qat_instance_backlog *backlog = req->backlog;
++ int ret = -EINPROGRESS;
++
++ if (qat_alg_try_enqueue(req))
++ return ret;
++
++ spin_lock_bh(&backlog->lock);
++ if (!qat_alg_try_enqueue(req)) {
++ list_add_tail(&req->list, &backlog->list);
++ ret = -EBUSY;
++ }
++ spin_unlock_bh(&backlog->lock);
++
++ return ret;
+ }
+
+ int qat_alg_send_message(struct qat_alg_req *req)
+--
+2.42.0
+
--- /dev/null
+From 8549520c34980a2bed97a24a4a34a7e1da4892e4 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 22 Sep 2023 10:03:47 +0100
+Subject: crypto: qat - increase size of buffers
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Giovanni Cabiddu <giovanni.cabiddu@intel.com>
+
+[ Upstream commit 4e4e2ed22d505c5bacf65c6a39bfb6d120d24785 ]
+
+Increase the size of the buffers used for composing the names used for
+the transport debugfs entries and the vector name to avoid a potential
+truncation.
+
+This resolves the following errors when compiling the driver with W=1
+and KCFLAGS=-Werror on GCC 12.3.1:
+
+ drivers/crypto/intel/qat/qat_common/adf_transport_debug.c: In function ‘adf_ring_debugfs_add’:
+ drivers/crypto/intel/qat/qat_common/adf_transport_debug.c:100:60: error: ‘snprintf’ output may be truncated before the last format character [-Werror=format-truncation=]
+ drivers/crypto/intel/qat/qat_common/adf_isr.c: In function ‘adf_isr_resource_alloc’:
+ drivers/crypto/intel/qat/qat_common/adf_isr.c:197:47: error: ‘%d’ directive output may be truncated writing between 1 and 11 bytes into a region of size between 0 and 5 [-Werror=format-truncation=]
+
+Fixes: a672a9dc872e ("crypto: qat - Intel(R) QAT transport code")
+Signed-off-by: Giovanni Cabiddu <giovanni.cabiddu@intel.com>
+Reviewed-by: Damian Muszynski <damian.muszynski@intel.com>
+Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/crypto/qat/qat_common/adf_accel_devices.h | 2 +-
+ drivers/crypto/qat/qat_common/adf_transport_debug.c | 4 ++--
+ 2 files changed, 3 insertions(+), 3 deletions(-)
+
+diff --git a/drivers/crypto/qat/qat_common/adf_accel_devices.h b/drivers/crypto/qat/qat_common/adf_accel_devices.h
+index 580566cfcb04c..3bb67b22edd6e 100644
+--- a/drivers/crypto/qat/qat_common/adf_accel_devices.h
++++ b/drivers/crypto/qat/qat_common/adf_accel_devices.h
+@@ -24,7 +24,7 @@
+ #define ADF_PCI_MAX_BARS 3
+ #define ADF_DEVICE_NAME_LENGTH 32
+ #define ADF_ETR_MAX_RINGS_PER_BANK 16
+-#define ADF_MAX_MSIX_VECTOR_NAME 16
++#define ADF_MAX_MSIX_VECTOR_NAME 48
+ #define ADF_DEVICE_NAME_PREFIX "qat_"
+
+ enum adf_accel_capabilities {
+diff --git a/drivers/crypto/qat/qat_common/adf_transport_debug.c b/drivers/crypto/qat/qat_common/adf_transport_debug.c
+index e69e5907f5950..006867f410bd3 100644
+--- a/drivers/crypto/qat/qat_common/adf_transport_debug.c
++++ b/drivers/crypto/qat/qat_common/adf_transport_debug.c
+@@ -90,7 +90,7 @@ DEFINE_SEQ_ATTRIBUTE(adf_ring_debug);
+ int adf_ring_debugfs_add(struct adf_etr_ring_data *ring, const char *name)
+ {
+ struct adf_etr_ring_debug_entry *ring_debug;
+- char entry_name[8];
++ char entry_name[16];
+
+ ring_debug = kzalloc(sizeof(*ring_debug), GFP_KERNEL);
+ if (!ring_debug)
+@@ -192,7 +192,7 @@ int adf_bank_debugfs_add(struct adf_etr_bank_data *bank)
+ {
+ struct adf_accel_dev *accel_dev = bank->accel_dev;
+ struct dentry *parent = accel_dev->transport->debug;
+- char name[8];
++ char name[16];
+
+ snprintf(name, sizeof(name), "bank_%02d", bank->bank_number);
+ bank->bank_debug_dir = debugfs_create_dir(name, parent);
+--
+2.42.0
+
--- /dev/null
+From 95450736c43196f26156fd19c4304c558fc7cc04 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 8 Sep 2021 22:12:21 -0700
+Subject: cxl/mbox: Introduce the mbox_send operation
+
+From: Dan Williams <dan.j.williams@intel.com>
+
+[ Upstream commit b64955a92929346f16df058ad2bb53630eb80466 ]
+
+In preparation for implementing a unit test backend transport for ioctl
+operations, and making the mailbox available to the cxl/pmem
+infrastructure, move the existing PCI specific portion of mailbox handling
+to an "mbox_send" operation.
+
+With this split all the PCI-specific transport details are comprehended
+by a single operation and the rest of the mailbox infrastructure is
+'struct cxl_mem' and 'struct cxl_memdev' generic.
+
+Acked-by: Ben Widawsky <ben.widawsky@intel.com>
+Reviewed-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
+Reviewed-by: Ben Widawsky <ben.widawsky@intel.com>
+Link: https://lore.kernel.org/r/163116434098.2460985.9004760022659400540.stgit@dwillia2-desk3.amr.corp.intel.com
+Signed-off-by: Dan Williams <dan.j.williams@intel.com>
+Stable-dep-of: 88d3917f82ed ("cxl/mem: Fix shutdown order")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/cxl/cxlmem.h | 42 ++++++++++++++++++++++++
+ drivers/cxl/pci.c | 76 ++++++++++++--------------------------------
+ 2 files changed, 63 insertions(+), 55 deletions(-)
+
+diff --git a/drivers/cxl/cxlmem.h b/drivers/cxl/cxlmem.h
+index e14bcd7a1ba14..c142532db8cb6 100644
+--- a/drivers/cxl/cxlmem.h
++++ b/drivers/cxl/cxlmem.h
+@@ -66,6 +66,45 @@ struct cxl_memdev *
+ devm_cxl_add_memdev(struct cxl_mem *cxlm,
+ const struct cdevm_file_operations *cdevm_fops);
+
++/**
++ * struct cxl_mbox_cmd - A command to be submitted to hardware.
++ * @opcode: (input) The command set and command submitted to hardware.
++ * @payload_in: (input) Pointer to the input payload.
++ * @payload_out: (output) Pointer to the output payload. Must be allocated by
++ * the caller.
++ * @size_in: (input) Number of bytes to load from @payload_in.
++ * @size_out: (input) Max number of bytes loaded into @payload_out.
++ * (output) Number of bytes generated by the device. For fixed size
++ * outputs commands this is always expected to be deterministic. For
++ * variable sized output commands, it tells the exact number of bytes
++ * written.
++ * @return_code: (output) Error code returned from hardware.
++ *
++ * This is the primary mechanism used to send commands to the hardware.
++ * All the fields except @payload_* correspond exactly to the fields described in
++ * Command Register section of the CXL 2.0 8.2.8.4.5. @payload_in and
++ * @payload_out are written to, and read from the Command Payload Registers
++ * defined in CXL 2.0 8.2.8.4.8.
++ */
++struct cxl_mbox_cmd {
++ u16 opcode;
++ void *payload_in;
++ void *payload_out;
++ size_t size_in;
++ size_t size_out;
++ u16 return_code;
++#define CXL_MBOX_SUCCESS 0
++};
++
++/*
++ * CXL 2.0 - Memory capacity multiplier
++ * See Section 8.2.9.5
++ *
++ * Volatile, Persistent, and Partition capacities are specified to be in
++ * multiples of 256MB - define a multiplier to convert to/from bytes.
++ */
++#define CXL_CAPACITY_MULTIPLIER SZ_256M
++
+ /**
+ * struct cxl_mem - A CXL memory device
+ * @dev: The device associated with this CXL device.
+@@ -88,6 +127,7 @@ devm_cxl_add_memdev(struct cxl_mem *cxlm,
+ * @active_persistent_bytes: sum of hard + soft persistent
+ * @next_volatile_bytes: volatile capacity change pending device reset
+ * @next_persistent_bytes: persistent capacity change pending device reset
++ * @mbox_send: @dev specific transport for transmitting mailbox commands
+ *
+ * See section 8.2.9.5.2 Capacity Configuration and Label Storage for
+ * details on capacity parameters.
+@@ -115,5 +155,7 @@ struct cxl_mem {
+ u64 active_persistent_bytes;
+ u64 next_volatile_bytes;
+ u64 next_persistent_bytes;
++
++ int (*mbox_send)(struct cxl_mem *cxlm, struct cxl_mbox_cmd *cmd);
+ };
+ #endif /* __CXL_MEM_H__ */
+diff --git a/drivers/cxl/pci.c b/drivers/cxl/pci.c
+index a242bcd950800..e6cf607448bfe 100644
+--- a/drivers/cxl/pci.c
++++ b/drivers/cxl/pci.c
+@@ -64,45 +64,6 @@ enum opcode {
+ CXL_MBOX_OP_MAX = 0x10000
+ };
+
+-/*
+- * CXL 2.0 - Memory capacity multiplier
+- * See Section 8.2.9.5
+- *
+- * Volatile, Persistent, and Partition capacities are specified to be in
+- * multiples of 256MB - define a multiplier to convert to/from bytes.
+- */
+-#define CXL_CAPACITY_MULTIPLIER SZ_256M
+-
+-/**
+- * struct mbox_cmd - A command to be submitted to hardware.
+- * @opcode: (input) The command set and command submitted to hardware.
+- * @payload_in: (input) Pointer to the input payload.
+- * @payload_out: (output) Pointer to the output payload. Must be allocated by
+- * the caller.
+- * @size_in: (input) Number of bytes to load from @payload_in.
+- * @size_out: (input) Max number of bytes loaded into @payload_out.
+- * (output) Number of bytes generated by the device. For fixed size
+- * outputs commands this is always expected to be deterministic. For
+- * variable sized output commands, it tells the exact number of bytes
+- * written.
+- * @return_code: (output) Error code returned from hardware.
+- *
+- * This is the primary mechanism used to send commands to the hardware.
+- * All the fields except @payload_* correspond exactly to the fields described in
+- * Command Register section of the CXL 2.0 8.2.8.4.5. @payload_in and
+- * @payload_out are written to, and read from the Command Payload Registers
+- * defined in CXL 2.0 8.2.8.4.8.
+- */
+-struct mbox_cmd {
+- u16 opcode;
+- void *payload_in;
+- void *payload_out;
+- size_t size_in;
+- size_t size_out;
+- u16 return_code;
+-#define CXL_MBOX_SUCCESS 0
+-};
+-
+ static DECLARE_RWSEM(cxl_memdev_rwsem);
+ static struct dentry *cxl_debugfs;
+ static bool cxl_raw_allow_all;
+@@ -266,7 +227,7 @@ static bool cxl_is_security_command(u16 opcode)
+ }
+
+ static void cxl_mem_mbox_timeout(struct cxl_mem *cxlm,
+- struct mbox_cmd *mbox_cmd)
++ struct cxl_mbox_cmd *mbox_cmd)
+ {
+ struct device *dev = cxlm->dev;
+
+@@ -297,7 +258,7 @@ static void cxl_mem_mbox_timeout(struct cxl_mem *cxlm,
+ * mailbox.
+ */
+ static int __cxl_mem_mbox_send_cmd(struct cxl_mem *cxlm,
+- struct mbox_cmd *mbox_cmd)
++ struct cxl_mbox_cmd *mbox_cmd)
+ {
+ void __iomem *payload = cxlm->regs.mbox + CXLDEV_MBOX_PAYLOAD_OFFSET;
+ struct device *dev = cxlm->dev;
+@@ -472,6 +433,20 @@ static void cxl_mem_mbox_put(struct cxl_mem *cxlm)
+ mutex_unlock(&cxlm->mbox_mutex);
+ }
+
++static int cxl_pci_mbox_send(struct cxl_mem *cxlm, struct cxl_mbox_cmd *cmd)
++{
++ int rc;
++
++ rc = cxl_mem_mbox_get(cxlm);
++ if (rc)
++ return rc;
++
++ rc = __cxl_mem_mbox_send_cmd(cxlm, cmd);
++ cxl_mem_mbox_put(cxlm);
++
++ return rc;
++}
++
+ /**
+ * handle_mailbox_cmd_from_user() - Dispatch a mailbox command for userspace.
+ * @cxlm: The CXL memory device to communicate with.
+@@ -503,7 +478,7 @@ static int handle_mailbox_cmd_from_user(struct cxl_mem *cxlm,
+ s32 *size_out, u32 *retval)
+ {
+ struct device *dev = cxlm->dev;
+- struct mbox_cmd mbox_cmd = {
++ struct cxl_mbox_cmd mbox_cmd = {
+ .opcode = cmd->opcode,
+ .size_in = cmd->info.size_in,
+ .size_out = cmd->info.size_out,
+@@ -525,10 +500,6 @@ static int handle_mailbox_cmd_from_user(struct cxl_mem *cxlm,
+ }
+ }
+
+- rc = cxl_mem_mbox_get(cxlm);
+- if (rc)
+- goto out;
+-
+ dev_dbg(dev,
+ "Submitting %s command for user\n"
+ "\topcode: %x\n"
+@@ -539,8 +510,7 @@ static int handle_mailbox_cmd_from_user(struct cxl_mem *cxlm,
+ dev_WARN_ONCE(dev, cmd->info.id == CXL_MEM_COMMAND_ID_RAW,
+ "raw command path used\n");
+
+- rc = __cxl_mem_mbox_send_cmd(cxlm, &mbox_cmd);
+- cxl_mem_mbox_put(cxlm);
++ rc = cxlm->mbox_send(cxlm, &mbox_cmd);
+ if (rc)
+ goto out;
+
+@@ -874,7 +844,7 @@ static int cxl_mem_mbox_send_cmd(struct cxl_mem *cxlm, u16 opcode,
+ void *out, size_t out_size)
+ {
+ const struct cxl_mem_command *cmd = cxl_mem_find_command(opcode);
+- struct mbox_cmd mbox_cmd = {
++ struct cxl_mbox_cmd mbox_cmd = {
+ .opcode = opcode,
+ .payload_in = in,
+ .size_in = in_size,
+@@ -886,12 +856,7 @@ static int cxl_mem_mbox_send_cmd(struct cxl_mem *cxlm, u16 opcode,
+ if (out_size > cxlm->payload_size)
+ return -E2BIG;
+
+- rc = cxl_mem_mbox_get(cxlm);
+- if (rc)
+- return rc;
+-
+- rc = __cxl_mem_mbox_send_cmd(cxlm, &mbox_cmd);
+- cxl_mem_mbox_put(cxlm);
++ rc = cxlm->mbox_send(cxlm, &mbox_cmd);
+ if (rc)
+ return rc;
+
+@@ -913,6 +878,7 @@ static int cxl_mem_setup_mailbox(struct cxl_mem *cxlm)
+ {
+ const int cap = readl(cxlm->regs.mbox + CXLDEV_MBOX_CAPS_OFFSET);
+
++ cxlm->mbox_send = cxl_pci_mbox_send;
+ cxlm->payload_size =
+ 1 << FIELD_GET(CXLDEV_MBOX_CAP_PAYLOAD_SIZE_MASK, cap);
+
+--
+2.42.0
+
--- /dev/null
+From ee60d6cb210a5458e01c8c2e243b44605f8744d0 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 8 Sep 2021 22:12:32 -0700
+Subject: cxl/mbox: Move mailbox and other non-PCI specific infrastructure to
+ the core
+
+From: Dan Williams <dan.j.williams@intel.com>
+
+[ Upstream commit 4faf31b43468c58e2c8c91cc5fa26f08a6b733be ]
+
+Now that the internals of mailbox operations are abstracted from the PCI
+specifics a bulk of infrastructure can move to the core.
+
+The CXL_PMEM driver intends to proxy LIBNVDIMM UAPI and driver requests
+to the equivalent functionality provided by the CXL hardware mailbox
+interface. In support of that intent move the mailbox implementation to
+a shared location for the CXL_PCI driver native IOCTL path and CXL_PMEM
+nvdimm command proxy path to share.
+
+A unit test framework seeks to implement a unit test backend transport
+for mailbox commands to communicate mocked up payloads. It can reuse all
+of the mailbox infrastructure minus the PCI specifics, so that also gets
+moved to the core.
+
+Finally with the mailbox infrastructure and ioctl handling being
+transport generic there is no longer any need to pass file
+file_operations to devm_cxl_add_memdev(). That allows all the ioctl
+boilerplate to move into the core for unit test reuse.
+
+No functional change intended, just code movement.
+
+Acked-by: Ben Widawsky <ben.widawsky@intel.com>
+Reported-by: kernel test robot <lkp@intel.com>
+Reviewed-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
+Link: https://lore.kernel.org/r/163116435233.2460985.16197340449713287180.stgit@dwillia2-desk3.amr.corp.intel.com
+Signed-off-by: Dan Williams <dan.j.williams@intel.com>
+Stable-dep-of: 88d3917f82ed ("cxl/mem: Fix shutdown order")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ .../driver-api/cxl/memory-devices.rst | 3 +
+ drivers/cxl/core/Makefile | 1 +
+ drivers/cxl/core/bus.c | 4 +
+ drivers/cxl/core/core.h | 8 +
+ drivers/cxl/core/mbox.c | 825 ++++++++++++++++
+ drivers/cxl/core/memdev.c | 81 +-
+ drivers/cxl/cxlmem.h | 78 +-
+ drivers/cxl/pci.c | 924 +-----------------
+ 8 files changed, 975 insertions(+), 949 deletions(-)
+ create mode 100644 drivers/cxl/core/mbox.c
+
+diff --git a/Documentation/driver-api/cxl/memory-devices.rst b/Documentation/driver-api/cxl/memory-devices.rst
+index 50ebcda17ad05..4624951b5c38e 100644
+--- a/Documentation/driver-api/cxl/memory-devices.rst
++++ b/Documentation/driver-api/cxl/memory-devices.rst
+@@ -45,6 +45,9 @@ CXL Core
+ .. kernel-doc:: drivers/cxl/core/regs.c
+ :doc: cxl registers
+
++.. kernel-doc:: drivers/cxl/core/mbox.c
++ :doc: cxl mbox
++
+ External Interfaces
+ ===================
+
+diff --git a/drivers/cxl/core/Makefile b/drivers/cxl/core/Makefile
+index 0fdbf3c6ac1a3..07eb8e1fb8a67 100644
+--- a/drivers/cxl/core/Makefile
++++ b/drivers/cxl/core/Makefile
+@@ -6,3 +6,4 @@ cxl_core-y := bus.o
+ cxl_core-y += pmem.o
+ cxl_core-y += regs.o
+ cxl_core-y += memdev.o
++cxl_core-y += mbox.o
+diff --git a/drivers/cxl/core/bus.c b/drivers/cxl/core/bus.c
+index 0987a6423ee06..e37bd74c4d9e7 100644
+--- a/drivers/cxl/core/bus.c
++++ b/drivers/cxl/core/bus.c
+@@ -639,6 +639,8 @@ static __init int cxl_core_init(void)
+ {
+ int rc;
+
++ cxl_mbox_init();
++
+ rc = cxl_memdev_init();
+ if (rc)
+ return rc;
+@@ -650,6 +652,7 @@ static __init int cxl_core_init(void)
+
+ err:
+ cxl_memdev_exit();
++ cxl_mbox_exit();
+ return rc;
+ }
+
+@@ -657,6 +660,7 @@ static void cxl_core_exit(void)
+ {
+ bus_unregister(&cxl_bus_type);
+ cxl_memdev_exit();
++ cxl_mbox_exit();
+ }
+
+ module_init(cxl_core_init);
+diff --git a/drivers/cxl/core/core.h b/drivers/cxl/core/core.h
+index 036a3c8106b44..c85b7fbad02dd 100644
+--- a/drivers/cxl/core/core.h
++++ b/drivers/cxl/core/core.h
+@@ -14,7 +14,15 @@ static inline void unregister_cxl_dev(void *dev)
+ device_unregister(dev);
+ }
+
++struct cxl_send_command;
++struct cxl_mem_query_commands;
++int cxl_query_cmd(struct cxl_memdev *cxlmd,
++ struct cxl_mem_query_commands __user *q);
++int cxl_send_cmd(struct cxl_memdev *cxlmd, struct cxl_send_command __user *s);
++
+ int cxl_memdev_init(void);
+ void cxl_memdev_exit(void);
++void cxl_mbox_init(void);
++void cxl_mbox_exit(void);
+
+ #endif /* __CXL_CORE_H__ */
+diff --git a/drivers/cxl/core/mbox.c b/drivers/cxl/core/mbox.c
+new file mode 100644
+index 0000000000000..31e1839917262
+--- /dev/null
++++ b/drivers/cxl/core/mbox.c
+@@ -0,0 +1,825 @@
++// SPDX-License-Identifier: GPL-2.0-only
++/* Copyright(c) 2020 Intel Corporation. All rights reserved. */
++#include <linux/io-64-nonatomic-lo-hi.h>
++#include <linux/security.h>
++#include <linux/debugfs.h>
++#include <linux/mutex.h>
++#include <cxlmem.h>
++#include <cxl.h>
++
++#include "core.h"
++
++static bool cxl_raw_allow_all;
++
++/**
++ * DOC: cxl mbox
++ *
++ * Core implementation of the CXL 2.0 Type-3 Memory Device Mailbox. The
++ * implementation is used by the cxl_pci driver to initialize the device
++ * and implement the cxl_mem.h IOCTL UAPI. It also implements the
++ * backend of the cxl_pmem_ctl() transport for LIBNVDIMM.
++ */
++
++#define cxl_for_each_cmd(cmd) \
++ for ((cmd) = &cxl_mem_commands[0]; \
++ ((cmd) - cxl_mem_commands) < ARRAY_SIZE(cxl_mem_commands); (cmd)++)
++
++#define CXL_CMD(_id, sin, sout, _flags) \
++ [CXL_MEM_COMMAND_ID_##_id] = { \
++ .info = { \
++ .id = CXL_MEM_COMMAND_ID_##_id, \
++ .size_in = sin, \
++ .size_out = sout, \
++ }, \
++ .opcode = CXL_MBOX_OP_##_id, \
++ .flags = _flags, \
++ }
++
++/*
++ * This table defines the supported mailbox commands for the driver. This table
++ * is made up of a UAPI structure. Non-negative values as parameters in the
++ * table will be validated against the user's input. For example, if size_in is
++ * 0, and the user passed in 1, it is an error.
++ */
++static struct cxl_mem_command cxl_mem_commands[CXL_MEM_COMMAND_ID_MAX] = {
++ CXL_CMD(IDENTIFY, 0, 0x43, CXL_CMD_FLAG_FORCE_ENABLE),
++#ifdef CONFIG_CXL_MEM_RAW_COMMANDS
++ CXL_CMD(RAW, ~0, ~0, 0),
++#endif
++ CXL_CMD(GET_SUPPORTED_LOGS, 0, ~0, CXL_CMD_FLAG_FORCE_ENABLE),
++ CXL_CMD(GET_FW_INFO, 0, 0x50, 0),
++ CXL_CMD(GET_PARTITION_INFO, 0, 0x20, 0),
++ CXL_CMD(GET_LSA, 0x8, ~0, 0),
++ CXL_CMD(GET_HEALTH_INFO, 0, 0x12, 0),
++ CXL_CMD(GET_LOG, 0x18, ~0, CXL_CMD_FLAG_FORCE_ENABLE),
++ CXL_CMD(SET_PARTITION_INFO, 0x0a, 0, 0),
++ CXL_CMD(SET_LSA, ~0, 0, 0),
++ CXL_CMD(GET_ALERT_CONFIG, 0, 0x10, 0),
++ CXL_CMD(SET_ALERT_CONFIG, 0xc, 0, 0),
++ CXL_CMD(GET_SHUTDOWN_STATE, 0, 0x1, 0),
++ CXL_CMD(SET_SHUTDOWN_STATE, 0x1, 0, 0),
++ CXL_CMD(GET_POISON, 0x10, ~0, 0),
++ CXL_CMD(INJECT_POISON, 0x8, 0, 0),
++ CXL_CMD(CLEAR_POISON, 0x48, 0, 0),
++ CXL_CMD(GET_SCAN_MEDIA_CAPS, 0x10, 0x4, 0),
++ CXL_CMD(SCAN_MEDIA, 0x11, 0, 0),
++ CXL_CMD(GET_SCAN_MEDIA, 0, ~0, 0),
++};
++
++/*
++ * Commands that RAW doesn't permit. The rationale for each:
++ *
++ * CXL_MBOX_OP_ACTIVATE_FW: Firmware activation requires adjustment /
++ * coordination of transaction timeout values at the root bridge level.
++ *
++ * CXL_MBOX_OP_SET_PARTITION_INFO: The device memory map may change live
++ * and needs to be coordinated with HDM updates.
++ *
++ * CXL_MBOX_OP_SET_LSA: The label storage area may be cached by the
++ * driver and any writes from userspace invalidates those contents.
++ *
++ * CXL_MBOX_OP_SET_SHUTDOWN_STATE: Set shutdown state assumes no writes
++ * to the device after it is marked clean, userspace can not make that
++ * assertion.
++ *
++ * CXL_MBOX_OP_[GET_]SCAN_MEDIA: The kernel provides a native error list that
++ * is kept up to date with patrol notifications and error management.
++ */
++static u16 cxl_disabled_raw_commands[] = {
++ CXL_MBOX_OP_ACTIVATE_FW,
++ CXL_MBOX_OP_SET_PARTITION_INFO,
++ CXL_MBOX_OP_SET_LSA,
++ CXL_MBOX_OP_SET_SHUTDOWN_STATE,
++ CXL_MBOX_OP_SCAN_MEDIA,
++ CXL_MBOX_OP_GET_SCAN_MEDIA,
++};
++
++/*
++ * Command sets that RAW doesn't permit. All opcodes in this set are
++ * disabled because they pass plain text security payloads over the
++ * user/kernel boundary. This functionality is intended to be wrapped
++ * behind the keys ABI which allows for encrypted payloads in the UAPI
++ */
++static u8 security_command_sets[] = {
++ 0x44, /* Sanitize */
++ 0x45, /* Persistent Memory Data-at-rest Security */
++ 0x46, /* Security Passthrough */
++};
++
++static bool cxl_is_security_command(u16 opcode)
++{
++ int i;
++
++ for (i = 0; i < ARRAY_SIZE(security_command_sets); i++)
++ if (security_command_sets[i] == (opcode >> 8))
++ return true;
++ return false;
++}
++
++static struct cxl_mem_command *cxl_mem_find_command(u16 opcode)
++{
++ struct cxl_mem_command *c;
++
++ cxl_for_each_cmd(c)
++ if (c->opcode == opcode)
++ return c;
++
++ return NULL;
++}
++
++/**
++ * cxl_mem_mbox_send_cmd() - Send a mailbox command to a memory device.
++ * @cxlm: The CXL memory device to communicate with.
++ * @opcode: Opcode for the mailbox command.
++ * @in: The input payload for the mailbox command.
++ * @in_size: The length of the input payload
++ * @out: Caller allocated buffer for the output.
++ * @out_size: Expected size of output.
++ *
++ * Context: Any context. Will acquire and release mbox_mutex.
++ * Return:
++ * * %>=0 - Number of bytes returned in @out.
++ * * %-E2BIG - Payload is too large for hardware.
++ * * %-EBUSY - Couldn't acquire exclusive mailbox access.
++ * * %-EFAULT - Hardware error occurred.
++ * * %-ENXIO - Command completed, but device reported an error.
++ * * %-EIO - Unexpected output size.
++ *
++ * Mailbox commands may execute successfully yet the device itself reported an
++ * error. While this distinction can be useful for commands from userspace, the
++ * kernel will only be able to use results when both are successful.
++ *
++ * See __cxl_mem_mbox_send_cmd()
++ */
++int cxl_mem_mbox_send_cmd(struct cxl_mem *cxlm, u16 opcode, void *in,
++ size_t in_size, void *out, size_t out_size)
++{
++ const struct cxl_mem_command *cmd = cxl_mem_find_command(opcode);
++ struct cxl_mbox_cmd mbox_cmd = {
++ .opcode = opcode,
++ .payload_in = in,
++ .size_in = in_size,
++ .size_out = out_size,
++ .payload_out = out,
++ };
++ int rc;
++
++ if (out_size > cxlm->payload_size)
++ return -E2BIG;
++
++ rc = cxlm->mbox_send(cxlm, &mbox_cmd);
++ if (rc)
++ return rc;
++
++ /* TODO: Map return code to proper kernel style errno */
++ if (mbox_cmd.return_code != CXL_MBOX_SUCCESS)
++ return -ENXIO;
++
++ /*
++ * Variable sized commands can't be validated and so it's up to the
++ * caller to do that if they wish.
++ */
++ if (cmd->info.size_out >= 0 && mbox_cmd.size_out != out_size)
++ return -EIO;
++
++ return 0;
++}
++EXPORT_SYMBOL_GPL(cxl_mem_mbox_send_cmd);
++
++static bool cxl_mem_raw_command_allowed(u16 opcode)
++{
++ int i;
++
++ if (!IS_ENABLED(CONFIG_CXL_MEM_RAW_COMMANDS))
++ return false;
++
++ if (security_locked_down(LOCKDOWN_PCI_ACCESS))
++ return false;
++
++ if (cxl_raw_allow_all)
++ return true;
++
++ if (cxl_is_security_command(opcode))
++ return false;
++
++ for (i = 0; i < ARRAY_SIZE(cxl_disabled_raw_commands); i++)
++ if (cxl_disabled_raw_commands[i] == opcode)
++ return false;
++
++ return true;
++}
++
++/**
++ * cxl_validate_cmd_from_user() - Check fields for CXL_MEM_SEND_COMMAND.
++ * @cxlm: &struct cxl_mem device whose mailbox will be used.
++ * @send_cmd: &struct cxl_send_command copied in from userspace.
++ * @out_cmd: Sanitized and populated &struct cxl_mem_command.
++ *
++ * Return:
++ * * %0 - @out_cmd is ready to send.
++ * * %-ENOTTY - Invalid command specified.
++ * * %-EINVAL - Reserved fields or invalid values were used.
++ * * %-ENOMEM - Input or output buffer wasn't sized properly.
++ * * %-EPERM - Attempted to use a protected command.
++ *
++ * The result of this command is a fully validated command in @out_cmd that is
++ * safe to send to the hardware.
++ *
++ * See handle_mailbox_cmd_from_user()
++ */
++static int cxl_validate_cmd_from_user(struct cxl_mem *cxlm,
++ const struct cxl_send_command *send_cmd,
++ struct cxl_mem_command *out_cmd)
++{
++ const struct cxl_command_info *info;
++ struct cxl_mem_command *c;
++
++ if (send_cmd->id == 0 || send_cmd->id >= CXL_MEM_COMMAND_ID_MAX)
++ return -ENOTTY;
++
++ /*
++ * The user can never specify an input payload larger than what hardware
++ * supports, but output can be arbitrarily large (simply write out as
++ * much data as the hardware provides).
++ */
++ if (send_cmd->in.size > cxlm->payload_size)
++ return -EINVAL;
++
++ /*
++ * Checks are bypassed for raw commands but a WARN/taint will occur
++ * later in the callchain
++ */
++ if (send_cmd->id == CXL_MEM_COMMAND_ID_RAW) {
++ const struct cxl_mem_command temp = {
++ .info = {
++ .id = CXL_MEM_COMMAND_ID_RAW,
++ .flags = 0,
++ .size_in = send_cmd->in.size,
++ .size_out = send_cmd->out.size,
++ },
++ .opcode = send_cmd->raw.opcode
++ };
++
++ if (send_cmd->raw.rsvd)
++ return -EINVAL;
++
++ /*
++ * Unlike supported commands, the output size of RAW commands
++ * gets passed along without further checking, so it must be
++ * validated here.
++ */
++ if (send_cmd->out.size > cxlm->payload_size)
++ return -EINVAL;
++
++ if (!cxl_mem_raw_command_allowed(send_cmd->raw.opcode))
++ return -EPERM;
++
++ memcpy(out_cmd, &temp, sizeof(temp));
++
++ return 0;
++ }
++
++ if (send_cmd->flags & ~CXL_MEM_COMMAND_FLAG_MASK)
++ return -EINVAL;
++
++ if (send_cmd->rsvd)
++ return -EINVAL;
++
++ if (send_cmd->in.rsvd || send_cmd->out.rsvd)
++ return -EINVAL;
++
++ /* Convert user's command into the internal representation */
++ c = &cxl_mem_commands[send_cmd->id];
++ info = &c->info;
++
++ /* Check that the command is enabled for hardware */
++ if (!test_bit(info->id, cxlm->enabled_cmds))
++ return -ENOTTY;
++
++ /* Check the input buffer is the expected size */
++ if (info->size_in >= 0 && info->size_in != send_cmd->in.size)
++ return -ENOMEM;
++
++ /* Check the output buffer is at least large enough */
++ if (info->size_out >= 0 && send_cmd->out.size < info->size_out)
++ return -ENOMEM;
++
++ memcpy(out_cmd, c, sizeof(*c));
++ out_cmd->info.size_in = send_cmd->in.size;
++ /*
++ * XXX: out_cmd->info.size_out will be controlled by the driver, and the
++ * specified number of bytes @send_cmd->out.size will be copied back out
++ * to userspace.
++ */
++
++ return 0;
++}
++
++#define cxl_cmd_count ARRAY_SIZE(cxl_mem_commands)
++
++int cxl_query_cmd(struct cxl_memdev *cxlmd,
++ struct cxl_mem_query_commands __user *q)
++{
++ struct device *dev = &cxlmd->dev;
++ struct cxl_mem_command *cmd;
++ u32 n_commands;
++ int j = 0;
++
++ dev_dbg(dev, "Query IOCTL\n");
++
++ if (get_user(n_commands, &q->n_commands))
++ return -EFAULT;
++
++ /* returns the total number if 0 elements are requested. */
++ if (n_commands == 0)
++ return put_user(cxl_cmd_count, &q->n_commands);
++
++ /*
++ * otherwise, return max(n_commands, total commands) cxl_command_info
++ * structures.
++ */
++ cxl_for_each_cmd(cmd) {
++ const struct cxl_command_info *info = &cmd->info;
++
++ if (copy_to_user(&q->commands[j++], info, sizeof(*info)))
++ return -EFAULT;
++
++ if (j == n_commands)
++ break;
++ }
++
++ return 0;
++}
++
++/**
++ * handle_mailbox_cmd_from_user() - Dispatch a mailbox command for userspace.
++ * @cxlm: The CXL memory device to communicate with.
++ * @cmd: The validated command.
++ * @in_payload: Pointer to userspace's input payload.
++ * @out_payload: Pointer to userspace's output payload.
++ * @size_out: (Input) Max payload size to copy out.
++ * (Output) Payload size hardware generated.
++ * @retval: Hardware generated return code from the operation.
++ *
++ * Return:
++ * * %0 - Mailbox transaction succeeded. This implies the mailbox
++ * protocol completed successfully not that the operation itself
++ * was successful.
++ * * %-ENOMEM - Couldn't allocate a bounce buffer.
++ * * %-EFAULT - Something happened with copy_to/from_user.
++ * * %-EINTR - Mailbox acquisition interrupted.
++ * * %-EXXX - Transaction level failures.
++ *
++ * Creates the appropriate mailbox command and dispatches it on behalf of a
++ * userspace request. The input and output payloads are copied between
++ * userspace.
++ *
++ * See cxl_send_cmd().
++ */
++static int handle_mailbox_cmd_from_user(struct cxl_mem *cxlm,
++ const struct cxl_mem_command *cmd,
++ u64 in_payload, u64 out_payload,
++ s32 *size_out, u32 *retval)
++{
++ struct device *dev = cxlm->dev;
++ struct cxl_mbox_cmd mbox_cmd = {
++ .opcode = cmd->opcode,
++ .size_in = cmd->info.size_in,
++ .size_out = cmd->info.size_out,
++ };
++ int rc;
++
++ if (cmd->info.size_out) {
++ mbox_cmd.payload_out = kvzalloc(cmd->info.size_out, GFP_KERNEL);
++ if (!mbox_cmd.payload_out)
++ return -ENOMEM;
++ }
++
++ if (cmd->info.size_in) {
++ mbox_cmd.payload_in = vmemdup_user(u64_to_user_ptr(in_payload),
++ cmd->info.size_in);
++ if (IS_ERR(mbox_cmd.payload_in)) {
++ kvfree(mbox_cmd.payload_out);
++ return PTR_ERR(mbox_cmd.payload_in);
++ }
++ }
++
++ dev_dbg(dev,
++ "Submitting %s command for user\n"
++ "\topcode: %x\n"
++ "\tsize: %ub\n",
++ cxl_command_names[cmd->info.id].name, mbox_cmd.opcode,
++ cmd->info.size_in);
++
++ dev_WARN_ONCE(dev, cmd->info.id == CXL_MEM_COMMAND_ID_RAW,
++ "raw command path used\n");
++
++ rc = cxlm->mbox_send(cxlm, &mbox_cmd);
++ if (rc)
++ goto out;
++
++ /*
++ * @size_out contains the max size that's allowed to be written back out
++ * to userspace. While the payload may have written more output than
++ * this it will have to be ignored.
++ */
++ if (mbox_cmd.size_out) {
++ dev_WARN_ONCE(dev, mbox_cmd.size_out > *size_out,
++ "Invalid return size\n");
++ if (copy_to_user(u64_to_user_ptr(out_payload),
++ mbox_cmd.payload_out, mbox_cmd.size_out)) {
++ rc = -EFAULT;
++ goto out;
++ }
++ }
++
++ *size_out = mbox_cmd.size_out;
++ *retval = mbox_cmd.return_code;
++
++out:
++ kvfree(mbox_cmd.payload_in);
++ kvfree(mbox_cmd.payload_out);
++ return rc;
++}
++
++int cxl_send_cmd(struct cxl_memdev *cxlmd, struct cxl_send_command __user *s)
++{
++ struct cxl_mem *cxlm = cxlmd->cxlm;
++ struct device *dev = &cxlmd->dev;
++ struct cxl_send_command send;
++ struct cxl_mem_command c;
++ int rc;
++
++ dev_dbg(dev, "Send IOCTL\n");
++
++ if (copy_from_user(&send, s, sizeof(send)))
++ return -EFAULT;
++
++ rc = cxl_validate_cmd_from_user(cxlmd->cxlm, &send, &c);
++ if (rc)
++ return rc;
++
++ /* Prepare to handle a full payload for variable sized output */
++ if (c.info.size_out < 0)
++ c.info.size_out = cxlm->payload_size;
++
++ rc = handle_mailbox_cmd_from_user(cxlm, &c, send.in.payload,
++ send.out.payload, &send.out.size,
++ &send.retval);
++ if (rc)
++ return rc;
++
++ if (copy_to_user(s, &send, sizeof(send)))
++ return -EFAULT;
++
++ return 0;
++}
++
++static int cxl_xfer_log(struct cxl_mem *cxlm, uuid_t *uuid, u32 size, u8 *out)
++{
++ u32 remaining = size;
++ u32 offset = 0;
++
++ while (remaining) {
++ u32 xfer_size = min_t(u32, remaining, cxlm->payload_size);
++ struct cxl_mbox_get_log {
++ uuid_t uuid;
++ __le32 offset;
++ __le32 length;
++ } __packed log = {
++ .uuid = *uuid,
++ .offset = cpu_to_le32(offset),
++ .length = cpu_to_le32(xfer_size)
++ };
++ int rc;
++
++ rc = cxl_mem_mbox_send_cmd(cxlm, CXL_MBOX_OP_GET_LOG, &log,
++ sizeof(log), out, xfer_size);
++ if (rc < 0)
++ return rc;
++
++ out += xfer_size;
++ remaining -= xfer_size;
++ offset += xfer_size;
++ }
++
++ return 0;
++}
++
++/**
++ * cxl_walk_cel() - Walk through the Command Effects Log.
++ * @cxlm: Device.
++ * @size: Length of the Command Effects Log.
++ * @cel: CEL
++ *
++ * Iterate over each entry in the CEL and determine if the driver supports the
++ * command. If so, the command is enabled for the device and can be used later.
++ */
++static void cxl_walk_cel(struct cxl_mem *cxlm, size_t size, u8 *cel)
++{
++ struct cel_entry {
++ __le16 opcode;
++ __le16 effect;
++ } __packed * cel_entry;
++ const int cel_entries = size / sizeof(*cel_entry);
++ int i;
++
++ cel_entry = (struct cel_entry *)cel;
++
++ for (i = 0; i < cel_entries; i++) {
++ u16 opcode = le16_to_cpu(cel_entry[i].opcode);
++ struct cxl_mem_command *cmd = cxl_mem_find_command(opcode);
++
++ if (!cmd) {
++ dev_dbg(cxlm->dev,
++ "Opcode 0x%04x unsupported by driver", opcode);
++ continue;
++ }
++
++ set_bit(cmd->info.id, cxlm->enabled_cmds);
++ }
++}
++
++struct cxl_mbox_get_supported_logs {
++ __le16 entries;
++ u8 rsvd[6];
++ struct gsl_entry {
++ uuid_t uuid;
++ __le32 size;
++ } __packed entry[];
++} __packed;
++
++static struct cxl_mbox_get_supported_logs *cxl_get_gsl(struct cxl_mem *cxlm)
++{
++ struct cxl_mbox_get_supported_logs *ret;
++ int rc;
++
++ ret = kvmalloc(cxlm->payload_size, GFP_KERNEL);
++ if (!ret)
++ return ERR_PTR(-ENOMEM);
++
++ rc = cxl_mem_mbox_send_cmd(cxlm, CXL_MBOX_OP_GET_SUPPORTED_LOGS, NULL,
++ 0, ret, cxlm->payload_size);
++ if (rc < 0) {
++ kvfree(ret);
++ return ERR_PTR(rc);
++ }
++
++ return ret;
++}
++
++enum {
++ CEL_UUID,
++ VENDOR_DEBUG_UUID,
++};
++
++/* See CXL 2.0 Table 170. Get Log Input Payload */
++static const uuid_t log_uuid[] = {
++ [CEL_UUID] = UUID_INIT(0xda9c0b5, 0xbf41, 0x4b78, 0x8f, 0x79, 0x96,
++ 0xb1, 0x62, 0x3b, 0x3f, 0x17),
++ [VENDOR_DEBUG_UUID] = UUID_INIT(0xe1819d9, 0x11a9, 0x400c, 0x81, 0x1f,
++ 0xd6, 0x07, 0x19, 0x40, 0x3d, 0x86),
++};
++
++/**
++ * cxl_mem_enumerate_cmds() - Enumerate commands for a device.
++ * @cxlm: The device.
++ *
++ * Returns 0 if enumerate completed successfully.
++ *
++ * CXL devices have optional support for certain commands. This function will
++ * determine the set of supported commands for the hardware and update the
++ * enabled_cmds bitmap in the @cxlm.
++ */
++int cxl_mem_enumerate_cmds(struct cxl_mem *cxlm)
++{
++ struct cxl_mbox_get_supported_logs *gsl;
++ struct device *dev = cxlm->dev;
++ struct cxl_mem_command *cmd;
++ int i, rc;
++
++ gsl = cxl_get_gsl(cxlm);
++ if (IS_ERR(gsl))
++ return PTR_ERR(gsl);
++
++ rc = -ENOENT;
++ for (i = 0; i < le16_to_cpu(gsl->entries); i++) {
++ u32 size = le32_to_cpu(gsl->entry[i].size);
++ uuid_t uuid = gsl->entry[i].uuid;
++ u8 *log;
++
++ dev_dbg(dev, "Found LOG type %pU of size %d", &uuid, size);
++
++ if (!uuid_equal(&uuid, &log_uuid[CEL_UUID]))
++ continue;
++
++ log = kvmalloc(size, GFP_KERNEL);
++ if (!log) {
++ rc = -ENOMEM;
++ goto out;
++ }
++
++ rc = cxl_xfer_log(cxlm, &uuid, size, log);
++ if (rc) {
++ kvfree(log);
++ goto out;
++ }
++
++ cxl_walk_cel(cxlm, size, log);
++ kvfree(log);
++
++ /* In case CEL was bogus, enable some default commands. */
++ cxl_for_each_cmd(cmd)
++ if (cmd->flags & CXL_CMD_FLAG_FORCE_ENABLE)
++ set_bit(cmd->info.id, cxlm->enabled_cmds);
++
++ /* Found the required CEL */
++ rc = 0;
++ }
++
++out:
++ kvfree(gsl);
++ return rc;
++}
++EXPORT_SYMBOL_GPL(cxl_mem_enumerate_cmds);
++
++/**
++ * cxl_mem_get_partition_info - Get partition info
++ * @cxlm: cxl_mem instance to update partition info
++ *
++ * Retrieve the current partition info for the device specified. The active
++ * values are the current capacity in bytes. If not 0, the 'next' values are
++ * the pending values, in bytes, which take affect on next cold reset.
++ *
++ * Return: 0 if no error: or the result of the mailbox command.
++ *
++ * See CXL @8.2.9.5.2.1 Get Partition Info
++ */
++static int cxl_mem_get_partition_info(struct cxl_mem *cxlm)
++{
++ struct cxl_mbox_get_partition_info {
++ __le64 active_volatile_cap;
++ __le64 active_persistent_cap;
++ __le64 next_volatile_cap;
++ __le64 next_persistent_cap;
++ } __packed pi;
++ int rc;
++
++ rc = cxl_mem_mbox_send_cmd(cxlm, CXL_MBOX_OP_GET_PARTITION_INFO,
++ NULL, 0, &pi, sizeof(pi));
++
++ if (rc)
++ return rc;
++
++ cxlm->active_volatile_bytes =
++ le64_to_cpu(pi.active_volatile_cap) * CXL_CAPACITY_MULTIPLIER;
++ cxlm->active_persistent_bytes =
++ le64_to_cpu(pi.active_persistent_cap) * CXL_CAPACITY_MULTIPLIER;
++ cxlm->next_volatile_bytes =
++ le64_to_cpu(pi.next_volatile_cap) * CXL_CAPACITY_MULTIPLIER;
++ cxlm->next_persistent_bytes =
++ le64_to_cpu(pi.next_volatile_cap) * CXL_CAPACITY_MULTIPLIER;
++
++ return 0;
++}
++
++/**
++ * cxl_mem_identify() - Send the IDENTIFY command to the device.
++ * @cxlm: The device to identify.
++ *
++ * Return: 0 if identify was executed successfully.
++ *
++ * This will dispatch the identify command to the device and on success populate
++ * structures to be exported to sysfs.
++ */
++int cxl_mem_identify(struct cxl_mem *cxlm)
++{
++ /* See CXL 2.0 Table 175 Identify Memory Device Output Payload */
++ struct cxl_mbox_identify {
++ char fw_revision[0x10];
++ __le64 total_capacity;
++ __le64 volatile_capacity;
++ __le64 persistent_capacity;
++ __le64 partition_align;
++ __le16 info_event_log_size;
++ __le16 warning_event_log_size;
++ __le16 failure_event_log_size;
++ __le16 fatal_event_log_size;
++ __le32 lsa_size;
++ u8 poison_list_max_mer[3];
++ __le16 inject_poison_limit;
++ u8 poison_caps;
++ u8 qos_telemetry_caps;
++ } __packed id;
++ int rc;
++
++ rc = cxl_mem_mbox_send_cmd(cxlm, CXL_MBOX_OP_IDENTIFY, NULL, 0, &id,
++ sizeof(id));
++ if (rc < 0)
++ return rc;
++
++ cxlm->total_bytes =
++ le64_to_cpu(id.total_capacity) * CXL_CAPACITY_MULTIPLIER;
++ cxlm->volatile_only_bytes =
++ le64_to_cpu(id.volatile_capacity) * CXL_CAPACITY_MULTIPLIER;
++ cxlm->persistent_only_bytes =
++ le64_to_cpu(id.persistent_capacity) * CXL_CAPACITY_MULTIPLIER;
++ cxlm->partition_align_bytes =
++ le64_to_cpu(id.partition_align) * CXL_CAPACITY_MULTIPLIER;
++
++ dev_dbg(cxlm->dev,
++ "Identify Memory Device\n"
++ " total_bytes = %#llx\n"
++ " volatile_only_bytes = %#llx\n"
++ " persistent_only_bytes = %#llx\n"
++ " partition_align_bytes = %#llx\n",
++ cxlm->total_bytes, cxlm->volatile_only_bytes,
++ cxlm->persistent_only_bytes, cxlm->partition_align_bytes);
++
++ cxlm->lsa_size = le32_to_cpu(id.lsa_size);
++ memcpy(cxlm->firmware_version, id.fw_revision, sizeof(id.fw_revision));
++
++ return 0;
++}
++EXPORT_SYMBOL_GPL(cxl_mem_identify);
++
++int cxl_mem_create_range_info(struct cxl_mem *cxlm)
++{
++ int rc;
++
++ if (cxlm->partition_align_bytes == 0) {
++ cxlm->ram_range.start = 0;
++ cxlm->ram_range.end = cxlm->volatile_only_bytes - 1;
++ cxlm->pmem_range.start = cxlm->volatile_only_bytes;
++ cxlm->pmem_range.end = cxlm->volatile_only_bytes +
++ cxlm->persistent_only_bytes - 1;
++ return 0;
++ }
++
++ rc = cxl_mem_get_partition_info(cxlm);
++ if (rc) {
++ dev_err(cxlm->dev, "Failed to query partition information\n");
++ return rc;
++ }
++
++ dev_dbg(cxlm->dev,
++ "Get Partition Info\n"
++ " active_volatile_bytes = %#llx\n"
++ " active_persistent_bytes = %#llx\n"
++ " next_volatile_bytes = %#llx\n"
++ " next_persistent_bytes = %#llx\n",
++ cxlm->active_volatile_bytes, cxlm->active_persistent_bytes,
++ cxlm->next_volatile_bytes, cxlm->next_persistent_bytes);
++
++ cxlm->ram_range.start = 0;
++ cxlm->ram_range.end = cxlm->active_volatile_bytes - 1;
++
++ cxlm->pmem_range.start = cxlm->active_volatile_bytes;
++ cxlm->pmem_range.end =
++ cxlm->active_volatile_bytes + cxlm->active_persistent_bytes - 1;
++
++ return 0;
++}
++EXPORT_SYMBOL_GPL(cxl_mem_create_range_info);
++
++struct cxl_mem *cxl_mem_create(struct device *dev)
++{
++ struct cxl_mem *cxlm;
++
++ cxlm = devm_kzalloc(dev, sizeof(*cxlm), GFP_KERNEL);
++ if (!cxlm) {
++ dev_err(dev, "No memory available\n");
++ return ERR_PTR(-ENOMEM);
++ }
++
++ mutex_init(&cxlm->mbox_mutex);
++ cxlm->dev = dev;
++ cxlm->enabled_cmds =
++ devm_kmalloc_array(dev, BITS_TO_LONGS(cxl_cmd_count),
++ sizeof(unsigned long),
++ GFP_KERNEL | __GFP_ZERO);
++ if (!cxlm->enabled_cmds) {
++ dev_err(dev, "No memory available for bitmap\n");
++ return ERR_PTR(-ENOMEM);
++ }
++
++ return cxlm;
++}
++EXPORT_SYMBOL_GPL(cxl_mem_create);
++
++static struct dentry *cxl_debugfs;
++
++void __init cxl_mbox_init(void)
++{
++ struct dentry *mbox_debugfs;
++
++ cxl_debugfs = debugfs_create_dir("cxl", NULL);
++ mbox_debugfs = debugfs_create_dir("mbox", cxl_debugfs);
++ debugfs_create_bool("raw_allow_all", 0600, mbox_debugfs,
++ &cxl_raw_allow_all);
++}
++
++void cxl_mbox_exit(void)
++{
++ debugfs_remove_recursive(cxl_debugfs);
++}
+diff --git a/drivers/cxl/core/memdev.c b/drivers/cxl/core/memdev.c
+index 331ef7d6c5984..df2ba87238c29 100644
+--- a/drivers/cxl/core/memdev.c
++++ b/drivers/cxl/core/memdev.c
+@@ -8,6 +8,8 @@
+ #include <cxlmem.h>
+ #include "core.h"
+
++static DECLARE_RWSEM(cxl_memdev_rwsem);
++
+ /*
+ * An entire PCI topology full of devices should be enough for any
+ * config
+@@ -132,16 +134,21 @@ static const struct device_type cxl_memdev_type = {
+ .groups = cxl_memdev_attribute_groups,
+ };
+
++static void cxl_memdev_shutdown(struct device *dev)
++{
++ struct cxl_memdev *cxlmd = to_cxl_memdev(dev);
++
++ down_write(&cxl_memdev_rwsem);
++ cxlmd->cxlm = NULL;
++ up_write(&cxl_memdev_rwsem);
++}
++
+ static void cxl_memdev_unregister(void *_cxlmd)
+ {
+ struct cxl_memdev *cxlmd = _cxlmd;
+ struct device *dev = &cxlmd->dev;
+- struct cdev *cdev = &cxlmd->cdev;
+- const struct cdevm_file_operations *cdevm_fops;
+-
+- cdevm_fops = container_of(cdev->ops, typeof(*cdevm_fops), fops);
+- cdevm_fops->shutdown(dev);
+
++ cxl_memdev_shutdown(dev);
+ cdev_device_del(&cxlmd->cdev, dev);
+ put_device(dev);
+ }
+@@ -180,16 +187,72 @@ static struct cxl_memdev *cxl_memdev_alloc(struct cxl_mem *cxlm,
+ return ERR_PTR(rc);
+ }
+
++static long __cxl_memdev_ioctl(struct cxl_memdev *cxlmd, unsigned int cmd,
++ unsigned long arg)
++{
++ switch (cmd) {
++ case CXL_MEM_QUERY_COMMANDS:
++ return cxl_query_cmd(cxlmd, (void __user *)arg);
++ case CXL_MEM_SEND_COMMAND:
++ return cxl_send_cmd(cxlmd, (void __user *)arg);
++ default:
++ return -ENOTTY;
++ }
++}
++
++static long cxl_memdev_ioctl(struct file *file, unsigned int cmd,
++ unsigned long arg)
++{
++ struct cxl_memdev *cxlmd = file->private_data;
++ int rc = -ENXIO;
++
++ down_read(&cxl_memdev_rwsem);
++ if (cxlmd->cxlm)
++ rc = __cxl_memdev_ioctl(cxlmd, cmd, arg);
++ up_read(&cxl_memdev_rwsem);
++
++ return rc;
++}
++
++static int cxl_memdev_open(struct inode *inode, struct file *file)
++{
++ struct cxl_memdev *cxlmd =
++ container_of(inode->i_cdev, typeof(*cxlmd), cdev);
++
++ get_device(&cxlmd->dev);
++ file->private_data = cxlmd;
++
++ return 0;
++}
++
++static int cxl_memdev_release_file(struct inode *inode, struct file *file)
++{
++ struct cxl_memdev *cxlmd =
++ container_of(inode->i_cdev, typeof(*cxlmd), cdev);
++
++ put_device(&cxlmd->dev);
++
++ return 0;
++}
++
++static const struct file_operations cxl_memdev_fops = {
++ .owner = THIS_MODULE,
++ .unlocked_ioctl = cxl_memdev_ioctl,
++ .open = cxl_memdev_open,
++ .release = cxl_memdev_release_file,
++ .compat_ioctl = compat_ptr_ioctl,
++ .llseek = noop_llseek,
++};
++
+ struct cxl_memdev *
+-devm_cxl_add_memdev(struct cxl_mem *cxlm,
+- const struct cdevm_file_operations *cdevm_fops)
++devm_cxl_add_memdev(struct cxl_mem *cxlm)
+ {
+ struct cxl_memdev *cxlmd;
+ struct device *dev;
+ struct cdev *cdev;
+ int rc;
+
+- cxlmd = cxl_memdev_alloc(cxlm, &cdevm_fops->fops);
++ cxlmd = cxl_memdev_alloc(cxlm, &cxl_memdev_fops);
+ if (IS_ERR(cxlmd))
+ return cxlmd;
+
+@@ -219,7 +282,7 @@ devm_cxl_add_memdev(struct cxl_mem *cxlm,
+ * The cdev was briefly live, shutdown any ioctl operations that
+ * saw that state.
+ */
+- cdevm_fops->shutdown(dev);
++ cxl_memdev_shutdown(dev);
+ put_device(dev);
+ return ERR_PTR(rc);
+ }
+diff --git a/drivers/cxl/cxlmem.h b/drivers/cxl/cxlmem.h
+index c142532db8cb6..f5d3326a1d0b1 100644
+--- a/drivers/cxl/cxlmem.h
++++ b/drivers/cxl/cxlmem.h
+@@ -2,6 +2,7 @@
+ /* Copyright(c) 2020-2021 Intel Corporation. */
+ #ifndef __CXL_MEM_H__
+ #define __CXL_MEM_H__
++#include <uapi/linux/cxl_mem.h>
+ #include <linux/cdev.h>
+ #include "cxl.h"
+
+@@ -28,21 +29,6 @@
+ (FIELD_GET(CXLMDEV_RESET_NEEDED_MASK, status) != \
+ CXLMDEV_RESET_NEEDED_NOT)
+
+-/**
+- * struct cdevm_file_operations - devm coordinated cdev file operations
+- * @fops: file operations that are synchronized against @shutdown
+- * @shutdown: disconnect driver data
+- *
+- * @shutdown is invoked in the devres release path to disconnect any
+- * driver instance data from @dev. It assumes synchronization with any
+- * fops operation that requires driver data. After @shutdown an
+- * operation may only reference @device data.
+- */
+-struct cdevm_file_operations {
+- struct file_operations fops;
+- void (*shutdown)(struct device *dev);
+-};
+-
+ /**
+ * struct cxl_memdev - CXL bus object representing a Type-3 Memory Device
+ * @dev: driver core device object
+@@ -62,9 +48,7 @@ static inline struct cxl_memdev *to_cxl_memdev(struct device *dev)
+ return container_of(dev, struct cxl_memdev, dev);
+ }
+
+-struct cxl_memdev *
+-devm_cxl_add_memdev(struct cxl_mem *cxlm,
+- const struct cdevm_file_operations *cdevm_fops);
++struct cxl_memdev *devm_cxl_add_memdev(struct cxl_mem *cxlm);
+
+ /**
+ * struct cxl_mbox_cmd - A command to be submitted to hardware.
+@@ -158,4 +142,62 @@ struct cxl_mem {
+
+ int (*mbox_send)(struct cxl_mem *cxlm, struct cxl_mbox_cmd *cmd);
+ };
++
++enum cxl_opcode {
++ CXL_MBOX_OP_INVALID = 0x0000,
++ CXL_MBOX_OP_RAW = CXL_MBOX_OP_INVALID,
++ CXL_MBOX_OP_GET_FW_INFO = 0x0200,
++ CXL_MBOX_OP_ACTIVATE_FW = 0x0202,
++ CXL_MBOX_OP_GET_SUPPORTED_LOGS = 0x0400,
++ CXL_MBOX_OP_GET_LOG = 0x0401,
++ CXL_MBOX_OP_IDENTIFY = 0x4000,
++ CXL_MBOX_OP_GET_PARTITION_INFO = 0x4100,
++ CXL_MBOX_OP_SET_PARTITION_INFO = 0x4101,
++ CXL_MBOX_OP_GET_LSA = 0x4102,
++ CXL_MBOX_OP_SET_LSA = 0x4103,
++ CXL_MBOX_OP_GET_HEALTH_INFO = 0x4200,
++ CXL_MBOX_OP_GET_ALERT_CONFIG = 0x4201,
++ CXL_MBOX_OP_SET_ALERT_CONFIG = 0x4202,
++ CXL_MBOX_OP_GET_SHUTDOWN_STATE = 0x4203,
++ CXL_MBOX_OP_SET_SHUTDOWN_STATE = 0x4204,
++ CXL_MBOX_OP_GET_POISON = 0x4300,
++ CXL_MBOX_OP_INJECT_POISON = 0x4301,
++ CXL_MBOX_OP_CLEAR_POISON = 0x4302,
++ CXL_MBOX_OP_GET_SCAN_MEDIA_CAPS = 0x4303,
++ CXL_MBOX_OP_SCAN_MEDIA = 0x4304,
++ CXL_MBOX_OP_GET_SCAN_MEDIA = 0x4305,
++ CXL_MBOX_OP_MAX = 0x10000
++};
++
++/**
++ * struct cxl_mem_command - Driver representation of a memory device command
++ * @info: Command information as it exists for the UAPI
++ * @opcode: The actual bits used for the mailbox protocol
++ * @flags: Set of flags effecting driver behavior.
++ *
++ * * %CXL_CMD_FLAG_FORCE_ENABLE: In cases of error, commands with this flag
++ * will be enabled by the driver regardless of what hardware may have
++ * advertised.
++ *
++ * The cxl_mem_command is the driver's internal representation of commands that
++ * are supported by the driver. Some of these commands may not be supported by
++ * the hardware. The driver will use @info to validate the fields passed in by
++ * the user then submit the @opcode to the hardware.
++ *
++ * See struct cxl_command_info.
++ */
++struct cxl_mem_command {
++ struct cxl_command_info info;
++ enum cxl_opcode opcode;
++ u32 flags;
++#define CXL_CMD_FLAG_NONE 0
++#define CXL_CMD_FLAG_FORCE_ENABLE BIT(0)
++};
++
++int cxl_mem_mbox_send_cmd(struct cxl_mem *cxlm, u16 opcode, void *in,
++ size_t in_size, void *out, size_t out_size);
++int cxl_mem_identify(struct cxl_mem *cxlm);
++int cxl_mem_enumerate_cmds(struct cxl_mem *cxlm);
++int cxl_mem_create_range_info(struct cxl_mem *cxlm);
++struct cxl_mem *cxl_mem_create(struct device *dev);
+ #endif /* __CXL_MEM_H__ */
+diff --git a/drivers/cxl/pci.c b/drivers/cxl/pci.c
+index 36b2dbf407120..f6f2d1268062a 100644
+--- a/drivers/cxl/pci.c
++++ b/drivers/cxl/pci.c
+@@ -1,16 +1,12 @@
+ // SPDX-License-Identifier: GPL-2.0-only
+ /* Copyright(c) 2020 Intel Corporation. All rights reserved. */
+-#include <uapi/linux/cxl_mem.h>
+-#include <linux/security.h>
+-#include <linux/debugfs.h>
++#include <linux/io-64-nonatomic-lo-hi.h>
+ #include <linux/module.h>
+ #include <linux/sizes.h>
+ #include <linux/mutex.h>
+ #include <linux/list.h>
+-#include <linux/cdev.h>
+ #include <linux/pci.h>
+ #include <linux/io.h>
+-#include <linux/io-64-nonatomic-lo-hi.h>
+ #include "cxlmem.h"
+ #include "pci.h"
+ #include "cxl.h"
+@@ -37,162 +33,6 @@
+ /* CXL 2.0 - 8.2.8.4 */
+ #define CXL_MAILBOX_TIMEOUT_MS (2 * HZ)
+
+-enum opcode {
+- CXL_MBOX_OP_INVALID = 0x0000,
+- CXL_MBOX_OP_RAW = CXL_MBOX_OP_INVALID,
+- CXL_MBOX_OP_GET_FW_INFO = 0x0200,
+- CXL_MBOX_OP_ACTIVATE_FW = 0x0202,
+- CXL_MBOX_OP_GET_SUPPORTED_LOGS = 0x0400,
+- CXL_MBOX_OP_GET_LOG = 0x0401,
+- CXL_MBOX_OP_IDENTIFY = 0x4000,
+- CXL_MBOX_OP_GET_PARTITION_INFO = 0x4100,
+- CXL_MBOX_OP_SET_PARTITION_INFO = 0x4101,
+- CXL_MBOX_OP_GET_LSA = 0x4102,
+- CXL_MBOX_OP_SET_LSA = 0x4103,
+- CXL_MBOX_OP_GET_HEALTH_INFO = 0x4200,
+- CXL_MBOX_OP_GET_ALERT_CONFIG = 0x4201,
+- CXL_MBOX_OP_SET_ALERT_CONFIG = 0x4202,
+- CXL_MBOX_OP_GET_SHUTDOWN_STATE = 0x4203,
+- CXL_MBOX_OP_SET_SHUTDOWN_STATE = 0x4204,
+- CXL_MBOX_OP_GET_POISON = 0x4300,
+- CXL_MBOX_OP_INJECT_POISON = 0x4301,
+- CXL_MBOX_OP_CLEAR_POISON = 0x4302,
+- CXL_MBOX_OP_GET_SCAN_MEDIA_CAPS = 0x4303,
+- CXL_MBOX_OP_SCAN_MEDIA = 0x4304,
+- CXL_MBOX_OP_GET_SCAN_MEDIA = 0x4305,
+- CXL_MBOX_OP_MAX = 0x10000
+-};
+-
+-static DECLARE_RWSEM(cxl_memdev_rwsem);
+-static struct dentry *cxl_debugfs;
+-static bool cxl_raw_allow_all;
+-
+-enum {
+- CEL_UUID,
+- VENDOR_DEBUG_UUID,
+-};
+-
+-/* See CXL 2.0 Table 170. Get Log Input Payload */
+-static const uuid_t log_uuid[] = {
+- [CEL_UUID] = UUID_INIT(0xda9c0b5, 0xbf41, 0x4b78, 0x8f, 0x79, 0x96,
+- 0xb1, 0x62, 0x3b, 0x3f, 0x17),
+- [VENDOR_DEBUG_UUID] = UUID_INIT(0xe1819d9, 0x11a9, 0x400c, 0x81, 0x1f,
+- 0xd6, 0x07, 0x19, 0x40, 0x3d, 0x86),
+-};
+-
+-/**
+- * struct cxl_mem_command - Driver representation of a memory device command
+- * @info: Command information as it exists for the UAPI
+- * @opcode: The actual bits used for the mailbox protocol
+- * @flags: Set of flags effecting driver behavior.
+- *
+- * * %CXL_CMD_FLAG_FORCE_ENABLE: In cases of error, commands with this flag
+- * will be enabled by the driver regardless of what hardware may have
+- * advertised.
+- *
+- * The cxl_mem_command is the driver's internal representation of commands that
+- * are supported by the driver. Some of these commands may not be supported by
+- * the hardware. The driver will use @info to validate the fields passed in by
+- * the user then submit the @opcode to the hardware.
+- *
+- * See struct cxl_command_info.
+- */
+-struct cxl_mem_command {
+- struct cxl_command_info info;
+- enum opcode opcode;
+- u32 flags;
+-#define CXL_CMD_FLAG_NONE 0
+-#define CXL_CMD_FLAG_FORCE_ENABLE BIT(0)
+-};
+-
+-#define CXL_CMD(_id, sin, sout, _flags) \
+- [CXL_MEM_COMMAND_ID_##_id] = { \
+- .info = { \
+- .id = CXL_MEM_COMMAND_ID_##_id, \
+- .size_in = sin, \
+- .size_out = sout, \
+- }, \
+- .opcode = CXL_MBOX_OP_##_id, \
+- .flags = _flags, \
+- }
+-
+-/*
+- * This table defines the supported mailbox commands for the driver. This table
+- * is made up of a UAPI structure. Non-negative values as parameters in the
+- * table will be validated against the user's input. For example, if size_in is
+- * 0, and the user passed in 1, it is an error.
+- */
+-static struct cxl_mem_command mem_commands[CXL_MEM_COMMAND_ID_MAX] = {
+- CXL_CMD(IDENTIFY, 0, 0x43, CXL_CMD_FLAG_FORCE_ENABLE),
+-#ifdef CONFIG_CXL_MEM_RAW_COMMANDS
+- CXL_CMD(RAW, ~0, ~0, 0),
+-#endif
+- CXL_CMD(GET_SUPPORTED_LOGS, 0, ~0, CXL_CMD_FLAG_FORCE_ENABLE),
+- CXL_CMD(GET_FW_INFO, 0, 0x50, 0),
+- CXL_CMD(GET_PARTITION_INFO, 0, 0x20, 0),
+- CXL_CMD(GET_LSA, 0x8, ~0, 0),
+- CXL_CMD(GET_HEALTH_INFO, 0, 0x12, 0),
+- CXL_CMD(GET_LOG, 0x18, ~0, CXL_CMD_FLAG_FORCE_ENABLE),
+- CXL_CMD(SET_PARTITION_INFO, 0x0a, 0, 0),
+- CXL_CMD(SET_LSA, ~0, 0, 0),
+- CXL_CMD(GET_ALERT_CONFIG, 0, 0x10, 0),
+- CXL_CMD(SET_ALERT_CONFIG, 0xc, 0, 0),
+- CXL_CMD(GET_SHUTDOWN_STATE, 0, 0x1, 0),
+- CXL_CMD(SET_SHUTDOWN_STATE, 0x1, 0, 0),
+- CXL_CMD(GET_POISON, 0x10, ~0, 0),
+- CXL_CMD(INJECT_POISON, 0x8, 0, 0),
+- CXL_CMD(CLEAR_POISON, 0x48, 0, 0),
+- CXL_CMD(GET_SCAN_MEDIA_CAPS, 0x10, 0x4, 0),
+- CXL_CMD(SCAN_MEDIA, 0x11, 0, 0),
+- CXL_CMD(GET_SCAN_MEDIA, 0, ~0, 0),
+-};
+-
+-/*
+- * Commands that RAW doesn't permit. The rationale for each:
+- *
+- * CXL_MBOX_OP_ACTIVATE_FW: Firmware activation requires adjustment /
+- * coordination of transaction timeout values at the root bridge level.
+- *
+- * CXL_MBOX_OP_SET_PARTITION_INFO: The device memory map may change live
+- * and needs to be coordinated with HDM updates.
+- *
+- * CXL_MBOX_OP_SET_LSA: The label storage area may be cached by the
+- * driver and any writes from userspace invalidates those contents.
+- *
+- * CXL_MBOX_OP_SET_SHUTDOWN_STATE: Set shutdown state assumes no writes
+- * to the device after it is marked clean, userspace can not make that
+- * assertion.
+- *
+- * CXL_MBOX_OP_[GET_]SCAN_MEDIA: The kernel provides a native error list that
+- * is kept up to date with patrol notifications and error management.
+- */
+-static u16 cxl_disabled_raw_commands[] = {
+- CXL_MBOX_OP_ACTIVATE_FW,
+- CXL_MBOX_OP_SET_PARTITION_INFO,
+- CXL_MBOX_OP_SET_LSA,
+- CXL_MBOX_OP_SET_SHUTDOWN_STATE,
+- CXL_MBOX_OP_SCAN_MEDIA,
+- CXL_MBOX_OP_GET_SCAN_MEDIA,
+-};
+-
+-/*
+- * Command sets that RAW doesn't permit. All opcodes in this set are
+- * disabled because they pass plain text security payloads over the
+- * user/kernel boundary. This functionality is intended to be wrapped
+- * behind the keys ABI which allows for encrypted payloads in the UAPI
+- */
+-static u8 security_command_sets[] = {
+- 0x44, /* Sanitize */
+- 0x45, /* Persistent Memory Data-at-rest Security */
+- 0x46, /* Security Passthrough */
+-};
+-
+-#define cxl_for_each_cmd(cmd) \
+- for ((cmd) = &mem_commands[0]; \
+- ((cmd) - mem_commands) < ARRAY_SIZE(mem_commands); (cmd)++)
+-
+-#define cxl_cmd_count ARRAY_SIZE(mem_commands)
+-
+ static int cxl_mem_wait_for_doorbell(struct cxl_mem *cxlm)
+ {
+ const unsigned long start = jiffies;
+@@ -215,16 +55,6 @@ static int cxl_mem_wait_for_doorbell(struct cxl_mem *cxlm)
+ return 0;
+ }
+
+-static bool cxl_is_security_command(u16 opcode)
+-{
+- int i;
+-
+- for (i = 0; i < ARRAY_SIZE(security_command_sets); i++)
+- if (security_command_sets[i] == (opcode >> 8))
+- return true;
+- return false;
+-}
+-
+ static void cxl_mem_mbox_timeout(struct cxl_mem *cxlm,
+ struct cxl_mbox_cmd *mbox_cmd)
+ {
+@@ -446,433 +276,6 @@ static int cxl_pci_mbox_send(struct cxl_mem *cxlm, struct cxl_mbox_cmd *cmd)
+ return rc;
+ }
+
+-/**
+- * handle_mailbox_cmd_from_user() - Dispatch a mailbox command for userspace.
+- * @cxlm: The CXL memory device to communicate with.
+- * @cmd: The validated command.
+- * @in_payload: Pointer to userspace's input payload.
+- * @out_payload: Pointer to userspace's output payload.
+- * @size_out: (Input) Max payload size to copy out.
+- * (Output) Payload size hardware generated.
+- * @retval: Hardware generated return code from the operation.
+- *
+- * Return:
+- * * %0 - Mailbox transaction succeeded. This implies the mailbox
+- * protocol completed successfully not that the operation itself
+- * was successful.
+- * * %-ENOMEM - Couldn't allocate a bounce buffer.
+- * * %-EFAULT - Something happened with copy_to/from_user.
+- * * %-EINTR - Mailbox acquisition interrupted.
+- * * %-EXXX - Transaction level failures.
+- *
+- * Creates the appropriate mailbox command and dispatches it on behalf of a
+- * userspace request. The input and output payloads are copied between
+- * userspace.
+- *
+- * See cxl_send_cmd().
+- */
+-static int handle_mailbox_cmd_from_user(struct cxl_mem *cxlm,
+- const struct cxl_mem_command *cmd,
+- u64 in_payload, u64 out_payload,
+- s32 *size_out, u32 *retval)
+-{
+- struct device *dev = cxlm->dev;
+- struct cxl_mbox_cmd mbox_cmd = {
+- .opcode = cmd->opcode,
+- .size_in = cmd->info.size_in,
+- .size_out = cmd->info.size_out,
+- };
+- int rc;
+-
+- if (cmd->info.size_out) {
+- mbox_cmd.payload_out = kvzalloc(cmd->info.size_out, GFP_KERNEL);
+- if (!mbox_cmd.payload_out)
+- return -ENOMEM;
+- }
+-
+- if (cmd->info.size_in) {
+- mbox_cmd.payload_in = vmemdup_user(u64_to_user_ptr(in_payload),
+- cmd->info.size_in);
+- if (IS_ERR(mbox_cmd.payload_in)) {
+- kvfree(mbox_cmd.payload_out);
+- return PTR_ERR(mbox_cmd.payload_in);
+- }
+- }
+-
+- dev_dbg(dev,
+- "Submitting %s command for user\n"
+- "\topcode: %x\n"
+- "\tsize: %ub\n",
+- cxl_command_names[cmd->info.id].name, mbox_cmd.opcode,
+- cmd->info.size_in);
+-
+- dev_WARN_ONCE(dev, cmd->info.id == CXL_MEM_COMMAND_ID_RAW,
+- "raw command path used\n");
+-
+- rc = cxlm->mbox_send(cxlm, &mbox_cmd);
+- if (rc)
+- goto out;
+-
+- /*
+- * @size_out contains the max size that's allowed to be written back out
+- * to userspace. While the payload may have written more output than
+- * this it will have to be ignored.
+- */
+- if (mbox_cmd.size_out) {
+- dev_WARN_ONCE(dev, mbox_cmd.size_out > *size_out,
+- "Invalid return size\n");
+- if (copy_to_user(u64_to_user_ptr(out_payload),
+- mbox_cmd.payload_out, mbox_cmd.size_out)) {
+- rc = -EFAULT;
+- goto out;
+- }
+- }
+-
+- *size_out = mbox_cmd.size_out;
+- *retval = mbox_cmd.return_code;
+-
+-out:
+- kvfree(mbox_cmd.payload_in);
+- kvfree(mbox_cmd.payload_out);
+- return rc;
+-}
+-
+-static bool cxl_mem_raw_command_allowed(u16 opcode)
+-{
+- int i;
+-
+- if (!IS_ENABLED(CONFIG_CXL_MEM_RAW_COMMANDS))
+- return false;
+-
+- if (security_locked_down(LOCKDOWN_PCI_ACCESS))
+- return false;
+-
+- if (cxl_raw_allow_all)
+- return true;
+-
+- if (cxl_is_security_command(opcode))
+- return false;
+-
+- for (i = 0; i < ARRAY_SIZE(cxl_disabled_raw_commands); i++)
+- if (cxl_disabled_raw_commands[i] == opcode)
+- return false;
+-
+- return true;
+-}
+-
+-/**
+- * cxl_validate_cmd_from_user() - Check fields for CXL_MEM_SEND_COMMAND.
+- * @cxlm: &struct cxl_mem device whose mailbox will be used.
+- * @send_cmd: &struct cxl_send_command copied in from userspace.
+- * @out_cmd: Sanitized and populated &struct cxl_mem_command.
+- *
+- * Return:
+- * * %0 - @out_cmd is ready to send.
+- * * %-ENOTTY - Invalid command specified.
+- * * %-EINVAL - Reserved fields or invalid values were used.
+- * * %-ENOMEM - Input or output buffer wasn't sized properly.
+- * * %-EPERM - Attempted to use a protected command.
+- *
+- * The result of this command is a fully validated command in @out_cmd that is
+- * safe to send to the hardware.
+- *
+- * See handle_mailbox_cmd_from_user()
+- */
+-static int cxl_validate_cmd_from_user(struct cxl_mem *cxlm,
+- const struct cxl_send_command *send_cmd,
+- struct cxl_mem_command *out_cmd)
+-{
+- const struct cxl_command_info *info;
+- struct cxl_mem_command *c;
+-
+- if (send_cmd->id == 0 || send_cmd->id >= CXL_MEM_COMMAND_ID_MAX)
+- return -ENOTTY;
+-
+- /*
+- * The user can never specify an input payload larger than what hardware
+- * supports, but output can be arbitrarily large (simply write out as
+- * much data as the hardware provides).
+- */
+- if (send_cmd->in.size > cxlm->payload_size)
+- return -EINVAL;
+-
+- /*
+- * Checks are bypassed for raw commands but a WARN/taint will occur
+- * later in the callchain
+- */
+- if (send_cmd->id == CXL_MEM_COMMAND_ID_RAW) {
+- const struct cxl_mem_command temp = {
+- .info = {
+- .id = CXL_MEM_COMMAND_ID_RAW,
+- .flags = 0,
+- .size_in = send_cmd->in.size,
+- .size_out = send_cmd->out.size,
+- },
+- .opcode = send_cmd->raw.opcode
+- };
+-
+- if (send_cmd->raw.rsvd)
+- return -EINVAL;
+-
+- /*
+- * Unlike supported commands, the output size of RAW commands
+- * gets passed along without further checking, so it must be
+- * validated here.
+- */
+- if (send_cmd->out.size > cxlm->payload_size)
+- return -EINVAL;
+-
+- if (!cxl_mem_raw_command_allowed(send_cmd->raw.opcode))
+- return -EPERM;
+-
+- memcpy(out_cmd, &temp, sizeof(temp));
+-
+- return 0;
+- }
+-
+- if (send_cmd->flags & ~CXL_MEM_COMMAND_FLAG_MASK)
+- return -EINVAL;
+-
+- if (send_cmd->rsvd)
+- return -EINVAL;
+-
+- if (send_cmd->in.rsvd || send_cmd->out.rsvd)
+- return -EINVAL;
+-
+- /* Convert user's command into the internal representation */
+- c = &mem_commands[send_cmd->id];
+- info = &c->info;
+-
+- /* Check that the command is enabled for hardware */
+- if (!test_bit(info->id, cxlm->enabled_cmds))
+- return -ENOTTY;
+-
+- /* Check the input buffer is the expected size */
+- if (info->size_in >= 0 && info->size_in != send_cmd->in.size)
+- return -ENOMEM;
+-
+- /* Check the output buffer is at least large enough */
+- if (info->size_out >= 0 && send_cmd->out.size < info->size_out)
+- return -ENOMEM;
+-
+- memcpy(out_cmd, c, sizeof(*c));
+- out_cmd->info.size_in = send_cmd->in.size;
+- /*
+- * XXX: out_cmd->info.size_out will be controlled by the driver, and the
+- * specified number of bytes @send_cmd->out.size will be copied back out
+- * to userspace.
+- */
+-
+- return 0;
+-}
+-
+-static int cxl_query_cmd(struct cxl_memdev *cxlmd,
+- struct cxl_mem_query_commands __user *q)
+-{
+- struct device *dev = &cxlmd->dev;
+- struct cxl_mem_command *cmd;
+- u32 n_commands;
+- int j = 0;
+-
+- dev_dbg(dev, "Query IOCTL\n");
+-
+- if (get_user(n_commands, &q->n_commands))
+- return -EFAULT;
+-
+- /* returns the total number if 0 elements are requested. */
+- if (n_commands == 0)
+- return put_user(cxl_cmd_count, &q->n_commands);
+-
+- /*
+- * otherwise, return max(n_commands, total commands) cxl_command_info
+- * structures.
+- */
+- cxl_for_each_cmd(cmd) {
+- const struct cxl_command_info *info = &cmd->info;
+-
+- if (copy_to_user(&q->commands[j++], info, sizeof(*info)))
+- return -EFAULT;
+-
+- if (j == n_commands)
+- break;
+- }
+-
+- return 0;
+-}
+-
+-static int cxl_send_cmd(struct cxl_memdev *cxlmd,
+- struct cxl_send_command __user *s)
+-{
+- struct cxl_mem *cxlm = cxlmd->cxlm;
+- struct device *dev = &cxlmd->dev;
+- struct cxl_send_command send;
+- struct cxl_mem_command c;
+- int rc;
+-
+- dev_dbg(dev, "Send IOCTL\n");
+-
+- if (copy_from_user(&send, s, sizeof(send)))
+- return -EFAULT;
+-
+- rc = cxl_validate_cmd_from_user(cxlmd->cxlm, &send, &c);
+- if (rc)
+- return rc;
+-
+- /* Prepare to handle a full payload for variable sized output */
+- if (c.info.size_out < 0)
+- c.info.size_out = cxlm->payload_size;
+-
+- rc = handle_mailbox_cmd_from_user(cxlm, &c, send.in.payload,
+- send.out.payload, &send.out.size,
+- &send.retval);
+- if (rc)
+- return rc;
+-
+- if (copy_to_user(s, &send, sizeof(send)))
+- return -EFAULT;
+-
+- return 0;
+-}
+-
+-static long __cxl_memdev_ioctl(struct cxl_memdev *cxlmd, unsigned int cmd,
+- unsigned long arg)
+-{
+- switch (cmd) {
+- case CXL_MEM_QUERY_COMMANDS:
+- return cxl_query_cmd(cxlmd, (void __user *)arg);
+- case CXL_MEM_SEND_COMMAND:
+- return cxl_send_cmd(cxlmd, (void __user *)arg);
+- default:
+- return -ENOTTY;
+- }
+-}
+-
+-static long cxl_memdev_ioctl(struct file *file, unsigned int cmd,
+- unsigned long arg)
+-{
+- struct cxl_memdev *cxlmd = file->private_data;
+- int rc = -ENXIO;
+-
+- down_read(&cxl_memdev_rwsem);
+- if (cxlmd->cxlm)
+- rc = __cxl_memdev_ioctl(cxlmd, cmd, arg);
+- up_read(&cxl_memdev_rwsem);
+-
+- return rc;
+-}
+-
+-static int cxl_memdev_open(struct inode *inode, struct file *file)
+-{
+- struct cxl_memdev *cxlmd =
+- container_of(inode->i_cdev, typeof(*cxlmd), cdev);
+-
+- get_device(&cxlmd->dev);
+- file->private_data = cxlmd;
+-
+- return 0;
+-}
+-
+-static int cxl_memdev_release_file(struct inode *inode, struct file *file)
+-{
+- struct cxl_memdev *cxlmd =
+- container_of(inode->i_cdev, typeof(*cxlmd), cdev);
+-
+- put_device(&cxlmd->dev);
+-
+- return 0;
+-}
+-
+-static void cxl_memdev_shutdown(struct device *dev)
+-{
+- struct cxl_memdev *cxlmd = to_cxl_memdev(dev);
+-
+- down_write(&cxl_memdev_rwsem);
+- cxlmd->cxlm = NULL;
+- up_write(&cxl_memdev_rwsem);
+-}
+-
+-static const struct cdevm_file_operations cxl_memdev_fops = {
+- .fops = {
+- .owner = THIS_MODULE,
+- .unlocked_ioctl = cxl_memdev_ioctl,
+- .open = cxl_memdev_open,
+- .release = cxl_memdev_release_file,
+- .compat_ioctl = compat_ptr_ioctl,
+- .llseek = noop_llseek,
+- },
+- .shutdown = cxl_memdev_shutdown,
+-};
+-
+-static inline struct cxl_mem_command *cxl_mem_find_command(u16 opcode)
+-{
+- struct cxl_mem_command *c;
+-
+- cxl_for_each_cmd(c)
+- if (c->opcode == opcode)
+- return c;
+-
+- return NULL;
+-}
+-
+-/**
+- * cxl_mem_mbox_send_cmd() - Send a mailbox command to a memory device.
+- * @cxlm: The CXL memory device to communicate with.
+- * @opcode: Opcode for the mailbox command.
+- * @in: The input payload for the mailbox command.
+- * @in_size: The length of the input payload
+- * @out: Caller allocated buffer for the output.
+- * @out_size: Expected size of output.
+- *
+- * Context: Any context. Will acquire and release mbox_mutex.
+- * Return:
+- * * %>=0 - Number of bytes returned in @out.
+- * * %-E2BIG - Payload is too large for hardware.
+- * * %-EBUSY - Couldn't acquire exclusive mailbox access.
+- * * %-EFAULT - Hardware error occurred.
+- * * %-ENXIO - Command completed, but device reported an error.
+- * * %-EIO - Unexpected output size.
+- *
+- * Mailbox commands may execute successfully yet the device itself reported an
+- * error. While this distinction can be useful for commands from userspace, the
+- * kernel will only be able to use results when both are successful.
+- *
+- * See __cxl_mem_mbox_send_cmd()
+- */
+-static int cxl_mem_mbox_send_cmd(struct cxl_mem *cxlm, u16 opcode,
+- void *in, size_t in_size,
+- void *out, size_t out_size)
+-{
+- const struct cxl_mem_command *cmd = cxl_mem_find_command(opcode);
+- struct cxl_mbox_cmd mbox_cmd = {
+- .opcode = opcode,
+- .payload_in = in,
+- .size_in = in_size,
+- .size_out = out_size,
+- .payload_out = out,
+- };
+- int rc;
+-
+- if (out_size > cxlm->payload_size)
+- return -E2BIG;
+-
+- rc = cxlm->mbox_send(cxlm, &mbox_cmd);
+- if (rc)
+- return rc;
+-
+- /* TODO: Map return code to proper kernel style errno */
+- if (mbox_cmd.return_code != CXL_MBOX_SUCCESS)
+- return -ENXIO;
+-
+- /*
+- * Variable sized commands can't be validated and so it's up to the
+- * caller to do that if they wish.
+- */
+- if (cmd->info.size_out >= 0 && mbox_cmd.size_out != out_size)
+- return -EIO;
+-
+- return 0;
+-}
+-
+ static int cxl_mem_setup_mailbox(struct cxl_mem *cxlm)
+ {
+ const int cap = readl(cxlm->regs.mbox + CXLDEV_MBOX_CAPS_OFFSET);
+@@ -901,30 +304,6 @@ static int cxl_mem_setup_mailbox(struct cxl_mem *cxlm)
+ return 0;
+ }
+
+-static struct cxl_mem *cxl_mem_create(struct device *dev)
+-{
+- struct cxl_mem *cxlm;
+-
+- cxlm = devm_kzalloc(dev, sizeof(*cxlm), GFP_KERNEL);
+- if (!cxlm) {
+- dev_err(dev, "No memory available\n");
+- return ERR_PTR(-ENOMEM);
+- }
+-
+- mutex_init(&cxlm->mbox_mutex);
+- cxlm->dev = dev;
+- cxlm->enabled_cmds =
+- devm_kmalloc_array(dev, BITS_TO_LONGS(cxl_cmd_count),
+- sizeof(unsigned long),
+- GFP_KERNEL | __GFP_ZERO);
+- if (!cxlm->enabled_cmds) {
+- dev_err(dev, "No memory available for bitmap\n");
+- return ERR_PTR(-ENOMEM);
+- }
+-
+- return cxlm;
+-}
+-
+ static void __iomem *cxl_mem_map_regblock(struct cxl_mem *cxlm,
+ u8 bar, u64 offset)
+ {
+@@ -1132,298 +511,6 @@ static int cxl_mem_setup_regs(struct cxl_mem *cxlm)
+ return ret;
+ }
+
+-static int cxl_xfer_log(struct cxl_mem *cxlm, uuid_t *uuid, u32 size, u8 *out)
+-{
+- u32 remaining = size;
+- u32 offset = 0;
+-
+- while (remaining) {
+- u32 xfer_size = min_t(u32, remaining, cxlm->payload_size);
+- struct cxl_mbox_get_log {
+- uuid_t uuid;
+- __le32 offset;
+- __le32 length;
+- } __packed log = {
+- .uuid = *uuid,
+- .offset = cpu_to_le32(offset),
+- .length = cpu_to_le32(xfer_size)
+- };
+- int rc;
+-
+- rc = cxl_mem_mbox_send_cmd(cxlm, CXL_MBOX_OP_GET_LOG, &log,
+- sizeof(log), out, xfer_size);
+- if (rc < 0)
+- return rc;
+-
+- out += xfer_size;
+- remaining -= xfer_size;
+- offset += xfer_size;
+- }
+-
+- return 0;
+-}
+-
+-/**
+- * cxl_walk_cel() - Walk through the Command Effects Log.
+- * @cxlm: Device.
+- * @size: Length of the Command Effects Log.
+- * @cel: CEL
+- *
+- * Iterate over each entry in the CEL and determine if the driver supports the
+- * command. If so, the command is enabled for the device and can be used later.
+- */
+-static void cxl_walk_cel(struct cxl_mem *cxlm, size_t size, u8 *cel)
+-{
+- struct cel_entry {
+- __le16 opcode;
+- __le16 effect;
+- } __packed * cel_entry;
+- const int cel_entries = size / sizeof(*cel_entry);
+- int i;
+-
+- cel_entry = (struct cel_entry *)cel;
+-
+- for (i = 0; i < cel_entries; i++) {
+- u16 opcode = le16_to_cpu(cel_entry[i].opcode);
+- struct cxl_mem_command *cmd = cxl_mem_find_command(opcode);
+-
+- if (!cmd) {
+- dev_dbg(cxlm->dev,
+- "Opcode 0x%04x unsupported by driver", opcode);
+- continue;
+- }
+-
+- set_bit(cmd->info.id, cxlm->enabled_cmds);
+- }
+-}
+-
+-struct cxl_mbox_get_supported_logs {
+- __le16 entries;
+- u8 rsvd[6];
+- struct gsl_entry {
+- uuid_t uuid;
+- __le32 size;
+- } __packed entry[];
+-} __packed;
+-
+-static struct cxl_mbox_get_supported_logs *cxl_get_gsl(struct cxl_mem *cxlm)
+-{
+- struct cxl_mbox_get_supported_logs *ret;
+- int rc;
+-
+- ret = kvmalloc(cxlm->payload_size, GFP_KERNEL);
+- if (!ret)
+- return ERR_PTR(-ENOMEM);
+-
+- rc = cxl_mem_mbox_send_cmd(cxlm, CXL_MBOX_OP_GET_SUPPORTED_LOGS, NULL,
+- 0, ret, cxlm->payload_size);
+- if (rc < 0) {
+- kvfree(ret);
+- return ERR_PTR(rc);
+- }
+-
+- return ret;
+-}
+-
+-/**
+- * cxl_mem_get_partition_info - Get partition info
+- * @cxlm: cxl_mem instance to update partition info
+- *
+- * Retrieve the current partition info for the device specified. If not 0, the
+- * 'next' values are pending and take affect on next cold reset.
+- *
+- * Return: 0 if no error: or the result of the mailbox command.
+- *
+- * See CXL @8.2.9.5.2.1 Get Partition Info
+- */
+-static int cxl_mem_get_partition_info(struct cxl_mem *cxlm)
+-{
+- struct cxl_mbox_get_partition_info {
+- __le64 active_volatile_cap;
+- __le64 active_persistent_cap;
+- __le64 next_volatile_cap;
+- __le64 next_persistent_cap;
+- } __packed pi;
+- int rc;
+-
+- rc = cxl_mem_mbox_send_cmd(cxlm, CXL_MBOX_OP_GET_PARTITION_INFO,
+- NULL, 0, &pi, sizeof(pi));
+- if (rc)
+- return rc;
+-
+- cxlm->active_volatile_bytes =
+- le64_to_cpu(pi.active_volatile_cap) * CXL_CAPACITY_MULTIPLIER;
+- cxlm->active_persistent_bytes =
+- le64_to_cpu(pi.active_persistent_cap) * CXL_CAPACITY_MULTIPLIER;
+- cxlm->next_volatile_bytes =
+- le64_to_cpu(pi.next_volatile_cap) * CXL_CAPACITY_MULTIPLIER;
+- cxlm->next_persistent_bytes =
+- le64_to_cpu(pi.next_volatile_cap) * CXL_CAPACITY_MULTIPLIER;
+-
+- return 0;
+-}
+-
+-/**
+- * cxl_mem_enumerate_cmds() - Enumerate commands for a device.
+- * @cxlm: The device.
+- *
+- * Returns 0 if enumerate completed successfully.
+- *
+- * CXL devices have optional support for certain commands. This function will
+- * determine the set of supported commands for the hardware and update the
+- * enabled_cmds bitmap in the @cxlm.
+- */
+-static int cxl_mem_enumerate_cmds(struct cxl_mem *cxlm)
+-{
+- struct cxl_mbox_get_supported_logs *gsl;
+- struct device *dev = cxlm->dev;
+- struct cxl_mem_command *cmd;
+- int i, rc;
+-
+- gsl = cxl_get_gsl(cxlm);
+- if (IS_ERR(gsl))
+- return PTR_ERR(gsl);
+-
+- rc = -ENOENT;
+- for (i = 0; i < le16_to_cpu(gsl->entries); i++) {
+- u32 size = le32_to_cpu(gsl->entry[i].size);
+- uuid_t uuid = gsl->entry[i].uuid;
+- u8 *log;
+-
+- dev_dbg(dev, "Found LOG type %pU of size %d", &uuid, size);
+-
+- if (!uuid_equal(&uuid, &log_uuid[CEL_UUID]))
+- continue;
+-
+- log = kvmalloc(size, GFP_KERNEL);
+- if (!log) {
+- rc = -ENOMEM;
+- goto out;
+- }
+-
+- rc = cxl_xfer_log(cxlm, &uuid, size, log);
+- if (rc) {
+- kvfree(log);
+- goto out;
+- }
+-
+- cxl_walk_cel(cxlm, size, log);
+- kvfree(log);
+-
+- /* In case CEL was bogus, enable some default commands. */
+- cxl_for_each_cmd(cmd)
+- if (cmd->flags & CXL_CMD_FLAG_FORCE_ENABLE)
+- set_bit(cmd->info.id, cxlm->enabled_cmds);
+-
+- /* Found the required CEL */
+- rc = 0;
+- }
+-
+-out:
+- kvfree(gsl);
+- return rc;
+-}
+-
+-/**
+- * cxl_mem_identify() - Send the IDENTIFY command to the device.
+- * @cxlm: The device to identify.
+- *
+- * Return: 0 if identify was executed successfully.
+- *
+- * This will dispatch the identify command to the device and on success populate
+- * structures to be exported to sysfs.
+- */
+-static int cxl_mem_identify(struct cxl_mem *cxlm)
+-{
+- /* See CXL 2.0 Table 175 Identify Memory Device Output Payload */
+- struct cxl_mbox_identify {
+- char fw_revision[0x10];
+- __le64 total_capacity;
+- __le64 volatile_capacity;
+- __le64 persistent_capacity;
+- __le64 partition_align;
+- __le16 info_event_log_size;
+- __le16 warning_event_log_size;
+- __le16 failure_event_log_size;
+- __le16 fatal_event_log_size;
+- __le32 lsa_size;
+- u8 poison_list_max_mer[3];
+- __le16 inject_poison_limit;
+- u8 poison_caps;
+- u8 qos_telemetry_caps;
+- } __packed id;
+- int rc;
+-
+- rc = cxl_mem_mbox_send_cmd(cxlm, CXL_MBOX_OP_IDENTIFY, NULL, 0, &id,
+- sizeof(id));
+- if (rc < 0)
+- return rc;
+-
+- cxlm->total_bytes = le64_to_cpu(id.total_capacity);
+- cxlm->total_bytes *= CXL_CAPACITY_MULTIPLIER;
+-
+- cxlm->volatile_only_bytes = le64_to_cpu(id.volatile_capacity);
+- cxlm->volatile_only_bytes *= CXL_CAPACITY_MULTIPLIER;
+-
+- cxlm->persistent_only_bytes = le64_to_cpu(id.persistent_capacity);
+- cxlm->persistent_only_bytes *= CXL_CAPACITY_MULTIPLIER;
+-
+- cxlm->partition_align_bytes = le64_to_cpu(id.partition_align);
+- cxlm->partition_align_bytes *= CXL_CAPACITY_MULTIPLIER;
+-
+- dev_dbg(cxlm->dev,
+- "Identify Memory Device\n"
+- " total_bytes = %#llx\n"
+- " volatile_only_bytes = %#llx\n"
+- " persistent_only_bytes = %#llx\n"
+- " partition_align_bytes = %#llx\n",
+- cxlm->total_bytes, cxlm->volatile_only_bytes,
+- cxlm->persistent_only_bytes, cxlm->partition_align_bytes);
+-
+- cxlm->lsa_size = le32_to_cpu(id.lsa_size);
+- memcpy(cxlm->firmware_version, id.fw_revision, sizeof(id.fw_revision));
+-
+- return 0;
+-}
+-
+-static int cxl_mem_create_range_info(struct cxl_mem *cxlm)
+-{
+- int rc;
+-
+- if (cxlm->partition_align_bytes == 0) {
+- cxlm->ram_range.start = 0;
+- cxlm->ram_range.end = cxlm->volatile_only_bytes - 1;
+- cxlm->pmem_range.start = cxlm->volatile_only_bytes;
+- cxlm->pmem_range.end = cxlm->volatile_only_bytes +
+- cxlm->persistent_only_bytes - 1;
+- return 0;
+- }
+-
+- rc = cxl_mem_get_partition_info(cxlm);
+- if (rc < 0) {
+- dev_err(cxlm->dev, "Failed to query partition information\n");
+- return rc;
+- }
+-
+- dev_dbg(cxlm->dev,
+- "Get Partition Info\n"
+- " active_volatile_bytes = %#llx\n"
+- " active_persistent_bytes = %#llx\n"
+- " next_volatile_bytes = %#llx\n"
+- " next_persistent_bytes = %#llx\n",
+- cxlm->active_volatile_bytes, cxlm->active_persistent_bytes,
+- cxlm->next_volatile_bytes, cxlm->next_persistent_bytes);
+-
+- cxlm->ram_range.start = 0;
+- cxlm->ram_range.end = cxlm->active_volatile_bytes - 1;
+-
+- cxlm->pmem_range.start = cxlm->active_volatile_bytes;
+- cxlm->pmem_range.end = cxlm->active_volatile_bytes +
+- cxlm->active_persistent_bytes - 1;
+-
+- return 0;
+-}
+-
+ static int cxl_mem_probe(struct pci_dev *pdev, const struct pci_device_id *id)
+ {
+ struct cxl_memdev *cxlmd;
+@@ -1458,7 +545,7 @@ static int cxl_mem_probe(struct pci_dev *pdev, const struct pci_device_id *id)
+ if (rc)
+ return rc;
+
+- cxlmd = devm_cxl_add_memdev(cxlm, &cxl_memdev_fops);
++ cxlmd = devm_cxl_add_memdev(cxlm);
+ if (IS_ERR(cxlmd))
+ return PTR_ERR(cxlmd);
+
+@@ -1486,7 +573,6 @@ static struct pci_driver cxl_mem_driver = {
+
+ static __init int cxl_mem_init(void)
+ {
+- struct dentry *mbox_debugfs;
+ int rc;
+
+ /* Double check the anonymous union trickery in struct cxl_regs */
+@@ -1497,17 +583,11 @@ static __init int cxl_mem_init(void)
+ if (rc)
+ return rc;
+
+- cxl_debugfs = debugfs_create_dir("cxl", NULL);
+- mbox_debugfs = debugfs_create_dir("mbox", cxl_debugfs);
+- debugfs_create_bool("raw_allow_all", 0600, mbox_debugfs,
+- &cxl_raw_allow_all);
+-
+ return 0;
+ }
+
+ static __exit void cxl_mem_exit(void)
+ {
+- debugfs_remove_recursive(cxl_debugfs);
+ pci_unregister_driver(&cxl_mem_driver);
+ }
+
+--
+2.42.0
+
--- /dev/null
+From 4cb065db9dcd2f5640134546185d56f521b9567a Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 28 Sep 2023 18:02:07 -0700
+Subject: cxl/mem: Fix shutdown order
+
+From: Dan Williams <dan.j.williams@intel.com>
+
+[ Upstream commit 88d3917f82ed4215a2154432c26de1480a61b209 ]
+
+Ira reports that removing cxl_mock_mem causes a crash with the following
+trace:
+
+ BUG: kernel NULL pointer dereference, address: 0000000000000044
+ [..]
+ RIP: 0010:cxl_region_decode_reset+0x7f/0x180 [cxl_core]
+ [..]
+ Call Trace:
+ <TASK>
+ cxl_region_detach+0xe8/0x210 [cxl_core]
+ cxl_decoder_kill_region+0x27/0x40 [cxl_core]
+ cxld_unregister+0x29/0x40 [cxl_core]
+ devres_release_all+0xb8/0x110
+ device_unbind_cleanup+0xe/0x70
+ device_release_driver_internal+0x1d2/0x210
+ bus_remove_device+0xd7/0x150
+ device_del+0x155/0x3e0
+ device_unregister+0x13/0x60
+ devm_release_action+0x4d/0x90
+ ? __pfx_unregister_port+0x10/0x10 [cxl_core]
+ delete_endpoint+0x121/0x130 [cxl_core]
+ devres_release_all+0xb8/0x110
+ device_unbind_cleanup+0xe/0x70
+ device_release_driver_internal+0x1d2/0x210
+ bus_remove_device+0xd7/0x150
+ device_del+0x155/0x3e0
+ ? lock_release+0x142/0x290
+ cdev_device_del+0x15/0x50
+ cxl_memdev_unregister+0x54/0x70 [cxl_core]
+
+This crash is due to the clearing out the cxl_memdev's driver context
+(@cxlds) before the subsystem is done with it. This is ultimately due to
+the region(s), that this memdev is a member, being torn down and expecting
+to be able to de-reference @cxlds, like here:
+
+static int cxl_region_decode_reset(struct cxl_region *cxlr, int count)
+...
+ if (cxlds->rcd)
+ goto endpoint_reset;
+...
+
+Fix it by keeping the driver context valid until memdev-device
+unregistration, and subsequently the entire stack of related
+dependencies, unwinds.
+
+Fixes: 9cc238c7a526 ("cxl/pci: Introduce cdevm_file_operations")
+Reported-by: Ira Weiny <ira.weiny@intel.com>
+Reviewed-by: Davidlohr Bueso <dave@stgolabs.net>
+Reviewed-by: Dave Jiang <dave.jiang@intel.com>
+Reviewed-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
+Reviewed-by: Ira Weiny <ira.weiny@intel.com>
+Tested-by: Ira Weiny <ira.weiny@intel.com>
+Signed-off-by: Dan Williams <dan.j.williams@intel.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/cxl/core/memdev.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/drivers/cxl/core/memdev.c b/drivers/cxl/core/memdev.c
+index df2ba87238c29..235758d23ee02 100644
+--- a/drivers/cxl/core/memdev.c
++++ b/drivers/cxl/core/memdev.c
+@@ -148,8 +148,8 @@ static void cxl_memdev_unregister(void *_cxlmd)
+ struct cxl_memdev *cxlmd = _cxlmd;
+ struct device *dev = &cxlmd->dev;
+
+- cxl_memdev_shutdown(dev);
+ cdev_device_del(&cxlmd->cdev, dev);
++ cxl_memdev_shutdown(dev);
+ put_device(dev);
+ }
+
+--
+2.42.0
+
--- /dev/null
+From 2aa7660aae4c8173c4527cb49fa9dcc9d81e01cc Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 13 Sep 2021 15:24:32 -0700
+Subject: cxl/pci: Clean up cxl_mem_get_partition_info()
+
+From: Dan Williams <dan.j.williams@intel.com>
+
+[ Upstream commit 13e7749d06b335774bbb341c65a0232484beb457 ]
+
+Commit 0b9159d0ff21 ("cxl/pci: Store memory capacity values") missed
+updating the kernel-doc for 'struct cxl_mem' leading to the following
+warnings:
+
+./scripts/kernel-doc -v drivers/cxl/cxlmem.h 2>&1 | grep warn
+drivers/cxl/cxlmem.h:107: warning: Function parameter or member 'total_bytes' not described in 'cxl_mem'
+drivers/cxl/cxlmem.h:107: warning: Function parameter or member 'volatile_only_bytes' not described in 'cxl_mem'
+drivers/cxl/cxlmem.h:107: warning: Function parameter or member 'persistent_only_bytes' not described in 'cxl_mem'
+drivers/cxl/cxlmem.h:107: warning: Function parameter or member 'partition_align_bytes' not described in 'cxl_mem'
+drivers/cxl/cxlmem.h:107: warning: Function parameter or member 'active_volatile_bytes' not described in 'cxl_mem'
+drivers/cxl/cxlmem.h:107: warning: Function parameter or member 'active_persistent_bytes' not described in 'cxl_mem'
+drivers/cxl/cxlmem.h:107: warning: Function parameter or member 'next_volatile_bytes' not described in 'cxl_mem'
+drivers/cxl/cxlmem.h:107: warning: Function parameter or member 'next_persistent_bytes' not described in 'cxl_mem'
+
+Also, it is redundant to describe those same parameters in the
+kernel-doc for cxl_mem_get_partition_info(). Given the only user of that
+routine updates the values in @cxlm, just do that implicitly internal to
+the helper.
+
+Cc: Ira Weiny <ira.weiny@intel.com>
+Reported-by: Ben Widawsky <ben.widawsky@intel.com>
+Reviewed-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
+Link: https://lore.kernel.org/r/163157174216.2653013.1277706528753990974.stgit@dwillia2-desk3.amr.corp.intel.com
+Signed-off-by: Dan Williams <dan.j.williams@intel.com>
+Stable-dep-of: 88d3917f82ed ("cxl/mem: Fix shutdown order")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/cxl/cxlmem.h | 15 +++++++++++++--
+ drivers/cxl/pci.c | 35 +++++++++++------------------------
+ 2 files changed, 24 insertions(+), 26 deletions(-)
+
+diff --git a/drivers/cxl/cxlmem.h b/drivers/cxl/cxlmem.h
+index d5334df83fb25..e14bcd7a1ba14 100644
+--- a/drivers/cxl/cxlmem.h
++++ b/drivers/cxl/cxlmem.h
+@@ -78,8 +78,19 @@ devm_cxl_add_memdev(struct cxl_mem *cxlm,
+ * @mbox_mutex: Mutex to synchronize mailbox access.
+ * @firmware_version: Firmware version for the memory device.
+ * @enabled_cmds: Hardware commands found enabled in CEL.
+- * @pmem_range: Persistent memory capacity information.
+- * @ram_range: Volatile memory capacity information.
++ * @pmem_range: Active Persistent memory capacity configuration
++ * @ram_range: Active Volatile memory capacity configuration
++ * @total_bytes: sum of all possible capacities
++ * @volatile_only_bytes: hard volatile capacity
++ * @persistent_only_bytes: hard persistent capacity
++ * @partition_align_bytes: alignment size for partition-able capacity
++ * @active_volatile_bytes: sum of hard + soft volatile
++ * @active_persistent_bytes: sum of hard + soft persistent
++ * @next_volatile_bytes: volatile capacity change pending device reset
++ * @next_persistent_bytes: persistent capacity change pending device reset
++ *
++ * See section 8.2.9.5.2 Capacity Configuration and Label Storage for
++ * details on capacity parameters.
+ */
+ struct cxl_mem {
+ struct device *dev;
+diff --git a/drivers/cxl/pci.c b/drivers/cxl/pci.c
+index 7b8ff6e592c46..a242bcd950800 100644
+--- a/drivers/cxl/pci.c
++++ b/drivers/cxl/pci.c
+@@ -1262,11 +1262,7 @@ static struct cxl_mbox_get_supported_logs *cxl_get_gsl(struct cxl_mem *cxlm)
+
+ /**
+ * cxl_mem_get_partition_info - Get partition info
+- * @cxlm: The device to act on
+- * @active_volatile_bytes: returned active volatile capacity
+- * @active_persistent_bytes: returned active persistent capacity
+- * @next_volatile_bytes: return next volatile capacity
+- * @next_persistent_bytes: return next persistent capacity
++ * @cxlm: cxl_mem instance to update partition info
+ *
+ * Retrieve the current partition info for the device specified. If not 0, the
+ * 'next' values are pending and take affect on next cold reset.
+@@ -1275,11 +1271,7 @@ static struct cxl_mbox_get_supported_logs *cxl_get_gsl(struct cxl_mem *cxlm)
+ *
+ * See CXL @8.2.9.5.2.1 Get Partition Info
+ */
+-static int cxl_mem_get_partition_info(struct cxl_mem *cxlm,
+- u64 *active_volatile_bytes,
+- u64 *active_persistent_bytes,
+- u64 *next_volatile_bytes,
+- u64 *next_persistent_bytes)
++static int cxl_mem_get_partition_info(struct cxl_mem *cxlm)
+ {
+ struct cxl_mbox_get_partition_info {
+ __le64 active_volatile_cap;
+@@ -1294,15 +1286,14 @@ static int cxl_mem_get_partition_info(struct cxl_mem *cxlm,
+ if (rc)
+ return rc;
+
+- *active_volatile_bytes = le64_to_cpu(pi.active_volatile_cap);
+- *active_persistent_bytes = le64_to_cpu(pi.active_persistent_cap);
+- *next_volatile_bytes = le64_to_cpu(pi.next_volatile_cap);
+- *next_persistent_bytes = le64_to_cpu(pi.next_volatile_cap);
+-
+- *active_volatile_bytes *= CXL_CAPACITY_MULTIPLIER;
+- *active_persistent_bytes *= CXL_CAPACITY_MULTIPLIER;
+- *next_volatile_bytes *= CXL_CAPACITY_MULTIPLIER;
+- *next_persistent_bytes *= CXL_CAPACITY_MULTIPLIER;
++ cxlm->active_volatile_bytes =
++ le64_to_cpu(pi.active_volatile_cap) * CXL_CAPACITY_MULTIPLIER;
++ cxlm->active_persistent_bytes =
++ le64_to_cpu(pi.active_persistent_cap) * CXL_CAPACITY_MULTIPLIER;
++ cxlm->next_volatile_bytes =
++ le64_to_cpu(pi.next_volatile_cap) * CXL_CAPACITY_MULTIPLIER;
++ cxlm->next_persistent_bytes =
++ le64_to_cpu(pi.next_volatile_cap) * CXL_CAPACITY_MULTIPLIER;
+
+ return 0;
+ }
+@@ -1443,11 +1434,7 @@ static int cxl_mem_create_range_info(struct cxl_mem *cxlm)
+ return 0;
+ }
+
+- rc = cxl_mem_get_partition_info(cxlm,
+- &cxlm->active_volatile_bytes,
+- &cxlm->active_persistent_bytes,
+- &cxlm->next_volatile_bytes,
+- &cxlm->next_persistent_bytes);
++ rc = cxl_mem_get_partition_info(cxlm);
+ if (rc < 0) {
+ dev_err(cxlm->dev, "Failed to query partition information\n");
+ return rc;
+--
+2.42.0
+
--- /dev/null
+From 450f15a5d86562de77ca4dc7fd882f5f0067d251 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 8 Sep 2021 22:12:26 -0700
+Subject: cxl/pci: Drop idr.h
+
+From: Dan Williams <dan.j.williams@intel.com>
+
+[ Upstream commit 4cb35f1ca05a42acbc4a3c8cf7de1029a06558d0 ]
+
+Commit 3d135db51024 ("cxl/core: Move memdev management to core") left
+this straggling include for cxl_memdev setup. Clean it up.
+
+Cc: Ben Widawsky <ben.widawsky@intel.com>
+Reported-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
+Reviewed-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
+Reviewed-by: Ben Widawsky <ben.widawsky@intel.com>
+Link: https://lore.kernel.org/r/163116434668.2460985.12264757586266849616.stgit@dwillia2-desk3.amr.corp.intel.com
+Signed-off-by: Dan Williams <dan.j.williams@intel.com>
+Stable-dep-of: 88d3917f82ed ("cxl/mem: Fix shutdown order")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/cxl/pci.c | 1 -
+ 1 file changed, 1 deletion(-)
+
+diff --git a/drivers/cxl/pci.c b/drivers/cxl/pci.c
+index e6cf607448bfe..36b2dbf407120 100644
+--- a/drivers/cxl/pci.c
++++ b/drivers/cxl/pci.c
+@@ -8,7 +8,6 @@
+ #include <linux/mutex.h>
+ #include <linux/list.h>
+ #include <linux/cdev.h>
+-#include <linux/idr.h>
+ #include <linux/pci.h>
+ #include <linux/io.h>
+ #include <linux/io-64-nonatomic-lo-hi.h>
+--
+2.42.0
+
--- /dev/null
+From fec63be32a3f61c396c2ba2b911db98b92a54107 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 8 Sep 2021 22:12:09 -0700
+Subject: cxl/pci: Make 'struct cxl_mem' device type generic
+
+From: Dan Williams <dan.j.williams@intel.com>
+
+[ Upstream commit 99e222a5f1b67dd17c2c780f4eb9a694707d3bf7 ]
+
+In preparation for adding a unit test provider of a cxl_memdev, convert
+the 'struct cxl_mem' driver context to carry a generic device rather
+than a pci device.
+
+Note, some dev_dbg() lines needed extra reformatting per clang-format.
+
+This conversion also allows the cxl_mem_create() and
+devm_cxl_add_memdev() calling conventions to be simplified. The "host"
+for a cxl_memdev, must be the same device for the driver that allocated
+@cxlm.
+
+Acked-by: Ben Widawsky <ben.widawsky@intel.com>
+Reviewed-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
+Reviewed-by: Ben Widawsky <ben.widawsky@intel.com>
+Link: https://lore.kernel.org/r/163116432973.2460985.7553504957932024222.stgit@dwillia2-desk3.amr.corp.intel.com
+Signed-off-by: Dan Williams <dan.j.williams@intel.com>
+Stable-dep-of: 88d3917f82ed ("cxl/mem: Fix shutdown order")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/cxl/core/memdev.c | 7 ++--
+ drivers/cxl/cxlmem.h | 6 ++--
+ drivers/cxl/pci.c | 75 ++++++++++++++++++---------------------
+ 3 files changed, 41 insertions(+), 47 deletions(-)
+
+diff --git a/drivers/cxl/core/memdev.c b/drivers/cxl/core/memdev.c
+index a9c317e320107..331ef7d6c5984 100644
+--- a/drivers/cxl/core/memdev.c
++++ b/drivers/cxl/core/memdev.c
+@@ -149,7 +149,6 @@ static void cxl_memdev_unregister(void *_cxlmd)
+ static struct cxl_memdev *cxl_memdev_alloc(struct cxl_mem *cxlm,
+ const struct file_operations *fops)
+ {
+- struct pci_dev *pdev = cxlm->pdev;
+ struct cxl_memdev *cxlmd;
+ struct device *dev;
+ struct cdev *cdev;
+@@ -166,7 +165,7 @@ static struct cxl_memdev *cxl_memdev_alloc(struct cxl_mem *cxlm,
+
+ dev = &cxlmd->dev;
+ device_initialize(dev);
+- dev->parent = &pdev->dev;
++ dev->parent = cxlm->dev;
+ dev->bus = &cxl_bus_type;
+ dev->devt = MKDEV(cxl_mem_major, cxlmd->id);
+ dev->type = &cxl_memdev_type;
+@@ -182,7 +181,7 @@ static struct cxl_memdev *cxl_memdev_alloc(struct cxl_mem *cxlm,
+ }
+
+ struct cxl_memdev *
+-devm_cxl_add_memdev(struct device *host, struct cxl_mem *cxlm,
++devm_cxl_add_memdev(struct cxl_mem *cxlm,
+ const struct cdevm_file_operations *cdevm_fops)
+ {
+ struct cxl_memdev *cxlmd;
+@@ -210,7 +209,7 @@ devm_cxl_add_memdev(struct device *host, struct cxl_mem *cxlm,
+ if (rc)
+ goto err;
+
+- rc = devm_add_action_or_reset(host, cxl_memdev_unregister, cxlmd);
++ rc = devm_add_action_or_reset(cxlm->dev, cxl_memdev_unregister, cxlmd);
+ if (rc)
+ return ERR_PTR(rc);
+ return cxlmd;
+diff --git a/drivers/cxl/cxlmem.h b/drivers/cxl/cxlmem.h
+index 6c0b1e2ea97c7..d5334df83fb25 100644
+--- a/drivers/cxl/cxlmem.h
++++ b/drivers/cxl/cxlmem.h
+@@ -63,12 +63,12 @@ static inline struct cxl_memdev *to_cxl_memdev(struct device *dev)
+ }
+
+ struct cxl_memdev *
+-devm_cxl_add_memdev(struct device *host, struct cxl_mem *cxlm,
++devm_cxl_add_memdev(struct cxl_mem *cxlm,
+ const struct cdevm_file_operations *cdevm_fops);
+
+ /**
+ * struct cxl_mem - A CXL memory device
+- * @pdev: The PCI device associated with this CXL device.
++ * @dev: The device associated with this CXL device.
+ * @cxlmd: Logical memory device chardev / interface
+ * @regs: Parsed register blocks
+ * @payload_size: Size of space for payload
+@@ -82,7 +82,7 @@ devm_cxl_add_memdev(struct device *host, struct cxl_mem *cxlm,
+ * @ram_range: Volatile memory capacity information.
+ */
+ struct cxl_mem {
+- struct pci_dev *pdev;
++ struct device *dev;
+ struct cxl_memdev *cxlmd;
+
+ struct cxl_regs regs;
+diff --git a/drivers/cxl/pci.c b/drivers/cxl/pci.c
+index 5444b5a7fd3c4..7b8ff6e592c46 100644
+--- a/drivers/cxl/pci.c
++++ b/drivers/cxl/pci.c
+@@ -250,7 +250,7 @@ static int cxl_mem_wait_for_doorbell(struct cxl_mem *cxlm)
+ cpu_relax();
+ }
+
+- dev_dbg(&cxlm->pdev->dev, "Doorbell wait took %dms",
++ dev_dbg(cxlm->dev, "Doorbell wait took %dms",
+ jiffies_to_msecs(end) - jiffies_to_msecs(start));
+ return 0;
+ }
+@@ -268,7 +268,7 @@ static bool cxl_is_security_command(u16 opcode)
+ static void cxl_mem_mbox_timeout(struct cxl_mem *cxlm,
+ struct mbox_cmd *mbox_cmd)
+ {
+- struct device *dev = &cxlm->pdev->dev;
++ struct device *dev = cxlm->dev;
+
+ dev_dbg(dev, "Mailbox command (opcode: %#x size: %zub) timed out\n",
+ mbox_cmd->opcode, mbox_cmd->size_in);
+@@ -300,6 +300,7 @@ static int __cxl_mem_mbox_send_cmd(struct cxl_mem *cxlm,
+ struct mbox_cmd *mbox_cmd)
+ {
+ void __iomem *payload = cxlm->regs.mbox + CXLDEV_MBOX_PAYLOAD_OFFSET;
++ struct device *dev = cxlm->dev;
+ u64 cmd_reg, status_reg;
+ size_t out_len;
+ int rc;
+@@ -325,8 +326,7 @@ static int __cxl_mem_mbox_send_cmd(struct cxl_mem *cxlm,
+
+ /* #1 */
+ if (cxl_doorbell_busy(cxlm)) {
+- dev_err_ratelimited(&cxlm->pdev->dev,
+- "Mailbox re-busy after acquiring\n");
++ dev_err_ratelimited(dev, "Mailbox re-busy after acquiring\n");
+ return -EBUSY;
+ }
+
+@@ -345,7 +345,7 @@ static int __cxl_mem_mbox_send_cmd(struct cxl_mem *cxlm,
+ writeq(cmd_reg, cxlm->regs.mbox + CXLDEV_MBOX_CMD_OFFSET);
+
+ /* #4 */
+- dev_dbg(&cxlm->pdev->dev, "Sending command\n");
++ dev_dbg(dev, "Sending command\n");
+ writel(CXLDEV_MBOX_CTRL_DOORBELL,
+ cxlm->regs.mbox + CXLDEV_MBOX_CTRL_OFFSET);
+
+@@ -362,7 +362,7 @@ static int __cxl_mem_mbox_send_cmd(struct cxl_mem *cxlm,
+ FIELD_GET(CXLDEV_MBOX_STATUS_RET_CODE_MASK, status_reg);
+
+ if (mbox_cmd->return_code != 0) {
+- dev_dbg(&cxlm->pdev->dev, "Mailbox operation had an error\n");
++ dev_dbg(dev, "Mailbox operation had an error\n");
+ return 0;
+ }
+
+@@ -399,7 +399,7 @@ static int __cxl_mem_mbox_send_cmd(struct cxl_mem *cxlm,
+ */
+ static int cxl_mem_mbox_get(struct cxl_mem *cxlm)
+ {
+- struct device *dev = &cxlm->pdev->dev;
++ struct device *dev = cxlm->dev;
+ u64 md_status;
+ int rc;
+
+@@ -502,7 +502,7 @@ static int handle_mailbox_cmd_from_user(struct cxl_mem *cxlm,
+ u64 in_payload, u64 out_payload,
+ s32 *size_out, u32 *retval)
+ {
+- struct device *dev = &cxlm->pdev->dev;
++ struct device *dev = cxlm->dev;
+ struct mbox_cmd mbox_cmd = {
+ .opcode = cmd->opcode,
+ .size_in = cmd->info.size_in,
+@@ -925,20 +925,19 @@ static int cxl_mem_setup_mailbox(struct cxl_mem *cxlm)
+ */
+ cxlm->payload_size = min_t(size_t, cxlm->payload_size, SZ_1M);
+ if (cxlm->payload_size < 256) {
+- dev_err(&cxlm->pdev->dev, "Mailbox is too small (%zub)",
++ dev_err(cxlm->dev, "Mailbox is too small (%zub)",
+ cxlm->payload_size);
+ return -ENXIO;
+ }
+
+- dev_dbg(&cxlm->pdev->dev, "Mailbox payload sized %zu",
++ dev_dbg(cxlm->dev, "Mailbox payload sized %zu",
+ cxlm->payload_size);
+
+ return 0;
+ }
+
+-static struct cxl_mem *cxl_mem_create(struct pci_dev *pdev)
++static struct cxl_mem *cxl_mem_create(struct device *dev)
+ {
+- struct device *dev = &pdev->dev;
+ struct cxl_mem *cxlm;
+
+ cxlm = devm_kzalloc(dev, sizeof(*cxlm), GFP_KERNEL);
+@@ -948,7 +947,7 @@ static struct cxl_mem *cxl_mem_create(struct pci_dev *pdev)
+ }
+
+ mutex_init(&cxlm->mbox_mutex);
+- cxlm->pdev = pdev;
++ cxlm->dev = dev;
+ cxlm->enabled_cmds =
+ devm_kmalloc_array(dev, BITS_TO_LONGS(cxl_cmd_count),
+ sizeof(unsigned long),
+@@ -964,9 +963,9 @@ static struct cxl_mem *cxl_mem_create(struct pci_dev *pdev)
+ static void __iomem *cxl_mem_map_regblock(struct cxl_mem *cxlm,
+ u8 bar, u64 offset)
+ {
+- struct pci_dev *pdev = cxlm->pdev;
+- struct device *dev = &pdev->dev;
+ void __iomem *addr;
++ struct device *dev = cxlm->dev;
++ struct pci_dev *pdev = to_pci_dev(dev);
+
+ /* Basic sanity check that BAR is big enough */
+ if (pci_resource_len(pdev, bar) < offset) {
+@@ -989,7 +988,7 @@ static void __iomem *cxl_mem_map_regblock(struct cxl_mem *cxlm,
+
+ static void cxl_mem_unmap_regblock(struct cxl_mem *cxlm, void __iomem *base)
+ {
+- pci_iounmap(cxlm->pdev, base);
++ pci_iounmap(to_pci_dev(cxlm->dev), base);
+ }
+
+ static int cxl_mem_dvsec(struct pci_dev *pdev, int dvsec)
+@@ -1018,10 +1017,9 @@ static int cxl_mem_dvsec(struct pci_dev *pdev, int dvsec)
+ static int cxl_probe_regs(struct cxl_mem *cxlm, void __iomem *base,
+ struct cxl_register_map *map)
+ {
+- struct pci_dev *pdev = cxlm->pdev;
+- struct device *dev = &pdev->dev;
+ struct cxl_component_reg_map *comp_map;
+ struct cxl_device_reg_map *dev_map;
++ struct device *dev = cxlm->dev;
+
+ switch (map->reg_type) {
+ case CXL_REGLOC_RBI_COMPONENT:
+@@ -1057,8 +1055,8 @@ static int cxl_probe_regs(struct cxl_mem *cxlm, void __iomem *base,
+
+ static int cxl_map_regs(struct cxl_mem *cxlm, struct cxl_register_map *map)
+ {
+- struct pci_dev *pdev = cxlm->pdev;
+- struct device *dev = &pdev->dev;
++ struct device *dev = cxlm->dev;
++ struct pci_dev *pdev = to_pci_dev(dev);
+
+ switch (map->reg_type) {
+ case CXL_REGLOC_RBI_COMPONENT:
+@@ -1096,13 +1094,12 @@ static void cxl_decode_register_block(u32 reg_lo, u32 reg_hi,
+ */
+ static int cxl_mem_setup_regs(struct cxl_mem *cxlm)
+ {
+- struct pci_dev *pdev = cxlm->pdev;
+- struct device *dev = &pdev->dev;
+- u32 regloc_size, regblocks;
+ void __iomem *base;
+- int regloc, i, n_maps;
++ u32 regloc_size, regblocks;
++ int regloc, i, n_maps, ret = 0;
++ struct device *dev = cxlm->dev;
++ struct pci_dev *pdev = to_pci_dev(dev);
+ struct cxl_register_map *map, maps[CXL_REGLOC_RBI_TYPES];
+- int ret = 0;
+
+ regloc = cxl_mem_dvsec(pdev, PCI_DVSEC_ID_CXL_REGLOC_DVSEC_ID);
+ if (!regloc) {
+@@ -1226,7 +1223,7 @@ static void cxl_walk_cel(struct cxl_mem *cxlm, size_t size, u8 *cel)
+ struct cxl_mem_command *cmd = cxl_mem_find_command(opcode);
+
+ if (!cmd) {
+- dev_dbg(&cxlm->pdev->dev,
++ dev_dbg(cxlm->dev,
+ "Opcode 0x%04x unsupported by driver", opcode);
+ continue;
+ }
+@@ -1323,7 +1320,7 @@ static int cxl_mem_get_partition_info(struct cxl_mem *cxlm,
+ static int cxl_mem_enumerate_cmds(struct cxl_mem *cxlm)
+ {
+ struct cxl_mbox_get_supported_logs *gsl;
+- struct device *dev = &cxlm->pdev->dev;
++ struct device *dev = cxlm->dev;
+ struct cxl_mem_command *cmd;
+ int i, rc;
+
+@@ -1418,15 +1415,14 @@ static int cxl_mem_identify(struct cxl_mem *cxlm)
+ cxlm->partition_align_bytes = le64_to_cpu(id.partition_align);
+ cxlm->partition_align_bytes *= CXL_CAPACITY_MULTIPLIER;
+
+- dev_dbg(&cxlm->pdev->dev, "Identify Memory Device\n"
++ dev_dbg(cxlm->dev,
++ "Identify Memory Device\n"
+ " total_bytes = %#llx\n"
+ " volatile_only_bytes = %#llx\n"
+ " persistent_only_bytes = %#llx\n"
+ " partition_align_bytes = %#llx\n",
+- cxlm->total_bytes,
+- cxlm->volatile_only_bytes,
+- cxlm->persistent_only_bytes,
+- cxlm->partition_align_bytes);
++ cxlm->total_bytes, cxlm->volatile_only_bytes,
++ cxlm->persistent_only_bytes, cxlm->partition_align_bytes);
+
+ cxlm->lsa_size = le32_to_cpu(id.lsa_size);
+ memcpy(cxlm->firmware_version, id.fw_revision, sizeof(id.fw_revision));
+@@ -1453,19 +1449,18 @@ static int cxl_mem_create_range_info(struct cxl_mem *cxlm)
+ &cxlm->next_volatile_bytes,
+ &cxlm->next_persistent_bytes);
+ if (rc < 0) {
+- dev_err(&cxlm->pdev->dev, "Failed to query partition information\n");
++ dev_err(cxlm->dev, "Failed to query partition information\n");
+ return rc;
+ }
+
+- dev_dbg(&cxlm->pdev->dev, "Get Partition Info\n"
++ dev_dbg(cxlm->dev,
++ "Get Partition Info\n"
+ " active_volatile_bytes = %#llx\n"
+ " active_persistent_bytes = %#llx\n"
+ " next_volatile_bytes = %#llx\n"
+ " next_persistent_bytes = %#llx\n",
+- cxlm->active_volatile_bytes,
+- cxlm->active_persistent_bytes,
+- cxlm->next_volatile_bytes,
+- cxlm->next_persistent_bytes);
++ cxlm->active_volatile_bytes, cxlm->active_persistent_bytes,
++ cxlm->next_volatile_bytes, cxlm->next_persistent_bytes);
+
+ cxlm->ram_range.start = 0;
+ cxlm->ram_range.end = cxlm->active_volatile_bytes - 1;
+@@ -1487,7 +1482,7 @@ static int cxl_mem_probe(struct pci_dev *pdev, const struct pci_device_id *id)
+ if (rc)
+ return rc;
+
+- cxlm = cxl_mem_create(pdev);
++ cxlm = cxl_mem_create(&pdev->dev);
+ if (IS_ERR(cxlm))
+ return PTR_ERR(cxlm);
+
+@@ -1511,7 +1506,7 @@ static int cxl_mem_probe(struct pci_dev *pdev, const struct pci_device_id *id)
+ if (rc)
+ return rc;
+
+- cxlmd = devm_cxl_add_memdev(&pdev->dev, cxlm, &cxl_memdev_fops);
++ cxlmd = devm_cxl_add_memdev(cxlm, &cxl_memdev_fops);
+ if (IS_ERR(cxlmd))
+ return PTR_ERR(cxlmd);
+
+--
+2.42.0
+
--- /dev/null
+From cef30404d7f329fd0a8c3b58d65b02f3fe799dfd Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sun, 24 Sep 2023 09:22:32 -0700
+Subject: dmaengine: idxd: Register dsa_bus_type before registering idxd
+ sub-drivers
+
+From: Fenghua Yu <fenghua.yu@intel.com>
+
+[ Upstream commit 88928addeec577386e8c83b48b5bc24d28ba97fd ]
+
+idxd sub-drivers belong to bus dsa_bus_type. Thus, dsa_bus_type must be
+registered in dsa bus init before idxd drivers can be registered.
+
+But the order is wrong when both idxd and idxd_bus are builtin drivers.
+In this case, idxd driver is compiled and linked before idxd_bus driver.
+Since the initcall order is determined by the link order, idxd sub-drivers
+are registered in idxd initcall before dsa_bus_type is registered
+in idxd_bus initcall. idxd initcall fails:
+
+[ 21.562803] calling idxd_init_module+0x0/0x110 @ 1
+[ 21.570761] Driver 'idxd' was unable to register with bus_type 'dsa' because the bus was not initialized.
+[ 21.586475] initcall idxd_init_module+0x0/0x110 returned -22 after 15717 usecs
+[ 21.597178] calling dsa_bus_init+0x0/0x20 @ 1
+
+To fix the issue, compile and link idxd_bus driver before idxd driver
+to ensure the right registration order.
+
+Fixes: d9e5481fca74 ("dmaengine: dsa: move dsa_bus_type out of idxd driver to standalone")
+Reported-by: Michael Prinke <michael.prinke@intel.com>
+Signed-off-by: Fenghua Yu <fenghua.yu@intel.com>
+Reviewed-by: Dave Jiang <dave.jiang@intel.com>
+Reviewed-by: Lijun Pan <lijun.pan@intel.com>
+Tested-by: Lijun Pan <lijun.pan@intel.com>
+Link: https://lore.kernel.org/r/20230924162232.1409454-1-fenghua.yu@intel.com
+Signed-off-by: Vinod Koul <vkoul@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/dma/idxd/Makefile | 6 +++---
+ 1 file changed, 3 insertions(+), 3 deletions(-)
+
+diff --git a/drivers/dma/idxd/Makefile b/drivers/dma/idxd/Makefile
+index a1e9f2b3a37cc..817ffa95a9b11 100644
+--- a/drivers/dma/idxd/Makefile
++++ b/drivers/dma/idxd/Makefile
+@@ -1,12 +1,12 @@
+ ccflags-y += -DDEFAULT_SYMBOL_NAMESPACE=IDXD
+
++obj-$(CONFIG_INTEL_IDXD_BUS) += idxd_bus.o
++idxd_bus-y := bus.o
++
+ obj-$(CONFIG_INTEL_IDXD) += idxd.o
+ idxd-y := init.o irq.o device.o sysfs.o submit.o dma.o cdev.o
+
+ idxd-$(CONFIG_INTEL_IDXD_PERFMON) += perfmon.o
+
+-obj-$(CONFIG_INTEL_IDXD_BUS) += idxd_bus.o
+-idxd_bus-y := bus.o
+-
+ obj-$(CONFIG_INTEL_IDXD_COMPAT) += idxd_compat.o
+ idxd_compat-y := compat.o
+--
+2.42.0
+
--- /dev/null
+From b293bb4c2bf0ee22c8ab169c53a13b9c0fc26be4 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sat, 7 Oct 2023 13:13:09 +0200
+Subject: dmaengine: pxa_dma: Remove an erroneous BUG_ON() in pxad_free_desc()
+
+From: Christophe JAILLET <christophe.jaillet@wanadoo.fr>
+
+[ Upstream commit 83c761f568733277ce1f7eb9dc9e890649c29a8c ]
+
+If pxad_alloc_desc() fails on the first dma_pool_alloc() call, then
+sw_desc->nb_desc is zero.
+In such a case pxad_free_desc() is called and it will BUG_ON().
+
+Remove this erroneous BUG_ON().
+
+It is also useless, because if "sw_desc->nb_desc == 0", then, on the first
+iteration of the for loop, i is -1 and the loop will not be executed.
+(both i and sw_desc->nb_desc are 'int')
+
+Fixes: a57e16cf0333 ("dmaengine: pxa: add pxa dmaengine driver")
+Signed-off-by: Christophe JAILLET <christophe.jaillet@wanadoo.fr>
+Link: https://lore.kernel.org/r/c8fc5563c9593c914fde41f0f7d1489a21b45a9a.1696676782.git.christophe.jaillet@wanadoo.fr
+Signed-off-by: Vinod Koul <vkoul@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/dma/pxa_dma.c | 1 -
+ 1 file changed, 1 deletion(-)
+
+diff --git a/drivers/dma/pxa_dma.c b/drivers/dma/pxa_dma.c
+index e613ace79ea83..2731dc27f9d71 100644
+--- a/drivers/dma/pxa_dma.c
++++ b/drivers/dma/pxa_dma.c
+@@ -722,7 +722,6 @@ static void pxad_free_desc(struct virt_dma_desc *vd)
+ dma_addr_t dma;
+ struct pxad_desc_sw *sw_desc = to_pxad_sw_desc(vd);
+
+- BUG_ON(sw_desc->nb_desc == 0);
+ for (i = sw_desc->nb_desc - 1; i >= 0; i--) {
+ if (i > 0)
+ dma = sw_desc->hw_desc[i - 1]->ddadr;
+--
+2.42.0
+
--- /dev/null
+From 21cbc9a74b2edd6e2fd17e7c47c28ba0530f60a3 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 15 Sep 2023 15:59:59 +0300
+Subject: dmaengine: ti: edma: handle irq_of_parse_and_map() errors
+
+From: Dan Carpenter <dan.carpenter@linaro.org>
+
+[ Upstream commit 14f6d317913f634920a640e9047aa2e66f5bdcb7 ]
+
+Zero is not a valid IRQ for in-kernel code and the irq_of_parse_and_map()
+function returns zero on error. So this check for valid IRQs should only
+accept values > 0.
+
+Fixes: 2b6b3b742019 ("ARM/dmaengine: edma: Merge the two drivers under drivers/dma/")
+Signed-off-by: Dan Carpenter <dan.carpenter@linaro.org>
+Acked-by: Peter Ujfalusi <peter.ujfalusi@gmail.com>
+Link: https://lore.kernel.org/r/f15cb6a7-8449-4f79-98b6-34072f04edbc@moroto.mountain
+Signed-off-by: Vinod Koul <vkoul@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/dma/ti/edma.c | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/drivers/dma/ti/edma.c b/drivers/dma/ti/edma.c
+index 35d81bd857f11..a1adc8d91fd8d 100644
+--- a/drivers/dma/ti/edma.c
++++ b/drivers/dma/ti/edma.c
+@@ -2459,7 +2459,7 @@ static int edma_probe(struct platform_device *pdev)
+ if (irq < 0 && node)
+ irq = irq_of_parse_and_map(node, 0);
+
+- if (irq >= 0) {
++ if (irq > 0) {
+ irq_name = devm_kasprintf(dev, GFP_KERNEL, "%s_ccint",
+ dev_name(dev));
+ ret = devm_request_irq(dev, irq, dma_irq_handler, 0, irq_name,
+@@ -2475,7 +2475,7 @@ static int edma_probe(struct platform_device *pdev)
+ if (irq < 0 && node)
+ irq = irq_of_parse_and_map(node, 2);
+
+- if (irq >= 0) {
++ if (irq > 0) {
+ irq_name = devm_kasprintf(dev, GFP_KERNEL, "%s_ccerrint",
+ dev_name(dev));
+ ret = devm_request_irq(dev, irq, dma_ccerr_handler, 0, irq_name,
+--
+2.42.0
+
--- /dev/null
+From 49d2451d6b1a1e1518954a829261c73a3f2bb3ff Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 20 Sep 2023 11:02:51 -0500
+Subject: drm/amdkfd: fix some race conditions in vram buffer alloc/free of svm
+ code
+
+From: Xiaogang Chen <xiaogang.chen@amd.com>
+
+[ Upstream commit 7bfaa160caed8192f8262c4638f552cad94bcf5a ]
+
+This patch fixes:
+1: ref number of prange's svm_bo got decreased by an async call from hmm. When
+wait svm_bo of prange got released we shoul also wait prang->svm_bo become NULL,
+otherwise prange->svm_bo may be set to null after allocate new vram buffer.
+
+2: During waiting svm_bo of prange got released in a while loop should reschedule
+current task to give other tasks oppotunity to run, specially the the workque
+task that handles svm_bo ref release, otherwise we may enter to softlock.
+
+Signed-off-by: Xiaogang.Chen <xiaogang.chen@amd.com>
+Reviewed-by: Felix Kuehling <Felix.Kuehling@amd.com>
+Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/gpu/drm/amd/amdkfd/kfd_svm.c | 8 ++++----
+ 1 file changed, 4 insertions(+), 4 deletions(-)
+
+diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_svm.c b/drivers/gpu/drm/amd/amdkfd/kfd_svm.c
+index 22a70aaccf13c..86135ca33e5be 100644
+--- a/drivers/gpu/drm/amd/amdkfd/kfd_svm.c
++++ b/drivers/gpu/drm/amd/amdkfd/kfd_svm.c
+@@ -433,11 +433,11 @@ svm_range_validate_svm_bo(struct amdgpu_device *adev, struct svm_range *prange)
+
+ /* We need a new svm_bo. Spin-loop to wait for concurrent
+ * svm_range_bo_release to finish removing this range from
+- * its range list. After this, it is safe to reuse the
+- * svm_bo pointer and svm_bo_list head.
++ * its range list and set prange->svm_bo to null. After this,
++ * it is safe to reuse the svm_bo pointer and svm_bo_list head.
+ */
+- while (!list_empty_careful(&prange->svm_bo_list))
+- ;
++ while (!list_empty_careful(&prange->svm_bo_list) || prange->svm_bo)
++ cond_resched();
+
+ return false;
+ }
+--
+2.42.0
+
--- /dev/null
+From ac2522362394c2b4eda54d4b81f1135836b4edce Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 28 Nov 2022 12:23:20 +0100
+Subject: drm/bridge: lt8912b: Add hot plug detection
+
+From: Stefan Eichenberger <stefan.eichenberger@toradex.com>
+
+[ Upstream commit 3b0a01a6a5224ed9b3f69f44edaa889b2e2b9779 ]
+
+Enable hot plug detection when it is available on the HDMI port.
+Without this connecting to a different monitor with incompatible timing
+before the 10 seconds poll period will lead to a broken display output.
+
+Fixes: 30e2ae943c26 ("drm/bridge: Introduce LT8912B DSI to HDMI bridge")
+Signed-off-by: Stefan Eichenberger <stefan.eichenberger@toradex.com>
+Signed-off-by: Francesco Dolcini <francesco.dolcini@toradex.com>
+Reviewed-by: Adrien Grassein <adrien.grassein@gmail.com>
+Reviewed-by: Robert Foss <robert.foss@linaro.org>
+Signed-off-by: Robert Foss <robert.foss@linaro.org>
+Link: https://patchwork.freedesktop.org/patch/msgid/20221128112320.25708-1-francesco@dolcini.it
+Stable-dep-of: 941882a0e96d ("drm/bridge: lt8912b: Fix bridge_detach")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/gpu/drm/bridge/lontium-lt8912b.c | 21 +++++++++++++++++++--
+ 1 file changed, 19 insertions(+), 2 deletions(-)
+
+diff --git a/drivers/gpu/drm/bridge/lontium-lt8912b.c b/drivers/gpu/drm/bridge/lontium-lt8912b.c
+index 6ad3b2d1819f1..a89e505aa3811 100644
+--- a/drivers/gpu/drm/bridge/lontium-lt8912b.c
++++ b/drivers/gpu/drm/bridge/lontium-lt8912b.c
+@@ -506,14 +506,27 @@ static int lt8912_attach_dsi(struct lt8912 *lt)
+ return 0;
+ }
+
++static void lt8912_bridge_hpd_cb(void *data, enum drm_connector_status status)
++{
++ struct lt8912 *lt = data;
++
++ if (lt->bridge.dev)
++ drm_helper_hpd_irq_event(lt->bridge.dev);
++}
++
+ static int lt8912_bridge_connector_init(struct drm_bridge *bridge)
+ {
+ int ret;
+ struct lt8912 *lt = bridge_to_lt8912(bridge);
+ struct drm_connector *connector = <->connector;
+
+- connector->polled = DRM_CONNECTOR_POLL_CONNECT |
+- DRM_CONNECTOR_POLL_DISCONNECT;
++ if (lt->hdmi_port->ops & DRM_BRIDGE_OP_HPD) {
++ drm_bridge_hpd_enable(lt->hdmi_port, lt8912_bridge_hpd_cb, lt);
++ connector->polled = DRM_CONNECTOR_POLL_HPD;
++ } else {
++ connector->polled = DRM_CONNECTOR_POLL_CONNECT |
++ DRM_CONNECTOR_POLL_DISCONNECT;
++ }
+
+ ret = drm_connector_init(bridge->dev, connector,
+ <8912_connector_funcs,
+@@ -567,6 +580,10 @@ static void lt8912_bridge_detach(struct drm_bridge *bridge)
+
+ if (lt->is_attached) {
+ lt8912_hard_power_off(lt);
++
++ if (lt->hdmi_port->ops & DRM_BRIDGE_OP_HPD)
++ drm_bridge_hpd_disable(lt->hdmi_port);
++
+ drm_connector_unregister(<->connector);
+ drm_connector_cleanup(<->connector);
+ }
+--
+2.42.0
+
--- /dev/null
+From e0842810e16a4adfac827f17a838c9e9e724d703 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 4 Aug 2023 13:48:13 +0300
+Subject: drm/bridge: lt8912b: Add missing drm_bridge_attach call
+
+From: Tomi Valkeinen <tomi.valkeinen@ideasonboard.com>
+
+[ Upstream commit f45acf7acf75921c0409d452f0165f51a19a74fd ]
+
+The driver does not call drm_bridge_attach(), which causes the next
+bridge to not be added to the bridge chain. This causes the pipeline
+init to fail when DRM_BRIDGE_ATTACH_NO_CONNECTOR is used.
+
+Add the call to drm_bridge_attach().
+
+Fixes: 30e2ae943c26 ("drm/bridge: Introduce LT8912B DSI to HDMI bridge")
+Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ideasonboard.com>
+Reviewed-by: Robert Foss <rfoss@kernel.org>
+Signed-off-by: Robert Foss <rfoss@kernel.org>
+Link: https://patchwork.freedesktop.org/patch/msgid/20230804-lt8912b-v1-4-c542692c6a2f@ideasonboard.com
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/gpu/drm/bridge/lontium-lt8912b.c | 7 +++++++
+ 1 file changed, 7 insertions(+)
+
+diff --git a/drivers/gpu/drm/bridge/lontium-lt8912b.c b/drivers/gpu/drm/bridge/lontium-lt8912b.c
+index 73b6fcae6dca8..6891863ed5104 100644
+--- a/drivers/gpu/drm/bridge/lontium-lt8912b.c
++++ b/drivers/gpu/drm/bridge/lontium-lt8912b.c
+@@ -548,6 +548,13 @@ static int lt8912_bridge_attach(struct drm_bridge *bridge,
+ struct lt8912 *lt = bridge_to_lt8912(bridge);
+ int ret;
+
++ ret = drm_bridge_attach(bridge->encoder, lt->hdmi_port, bridge,
++ DRM_BRIDGE_ATTACH_NO_CONNECTOR);
++ if (ret < 0) {
++ dev_err(lt->dev, "Failed to attach next bridge (%d)\n", ret);
++ return ret;
++ }
++
+ if (!(flags & DRM_BRIDGE_ATTACH_NO_CONNECTOR)) {
+ ret = lt8912_bridge_connector_init(bridge);
+ if (ret) {
+--
+2.42.0
+
--- /dev/null
+From 91da7a12a3eb0d3b19a628f1dd58c2f0e4024054 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 4 Aug 2023 13:48:10 +0300
+Subject: drm/bridge: lt8912b: Fix bridge_detach
+
+From: Tomi Valkeinen <tomi.valkeinen@ideasonboard.com>
+
+[ Upstream commit 941882a0e96d245f38116e940912b404b6a93c6f ]
+
+The driver calls lt8912_bridge_detach() from its lt8912_remove()
+function. As the DRM core detaches bridges automatically, this leads to
+calling lt8912_bridge_detach() twice. The code probably has tried to
+manage the double-call with the 'is_attached' variable, but the driver
+never sets the variable to false, so its of no help.
+
+Fix the issue by dropping the call to lt8912_bridge_detach() from
+lt8912_remove(), as the DRM core will handle the detach call for us,
+and also drop the useless is_attached field.
+
+Fixes: 30e2ae943c26 ("drm/bridge: Introduce LT8912B DSI to HDMI bridge")
+Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ideasonboard.com>
+Reviewed-by: Robert Foss <rfoss@kernel.org>
+Signed-off-by: Robert Foss <rfoss@kernel.org>
+Link: https://patchwork.freedesktop.org/patch/msgid/20230804-lt8912b-v1-1-c542692c6a2f@ideasonboard.com
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/gpu/drm/bridge/lontium-lt8912b.c | 16 +++++-----------
+ 1 file changed, 5 insertions(+), 11 deletions(-)
+
+diff --git a/drivers/gpu/drm/bridge/lontium-lt8912b.c b/drivers/gpu/drm/bridge/lontium-lt8912b.c
+index a89e505aa3811..d435cb3ed3808 100644
+--- a/drivers/gpu/drm/bridge/lontium-lt8912b.c
++++ b/drivers/gpu/drm/bridge/lontium-lt8912b.c
+@@ -43,7 +43,6 @@ struct lt8912 {
+
+ u8 data_lanes;
+ bool is_power_on;
+- bool is_attached;
+ };
+
+ static int lt8912_write_init_config(struct lt8912 *lt)
+@@ -565,8 +564,6 @@ static int lt8912_bridge_attach(struct drm_bridge *bridge,
+ if (ret)
+ goto error;
+
+- lt->is_attached = true;
+-
+ return 0;
+
+ error:
+@@ -578,15 +575,13 @@ static void lt8912_bridge_detach(struct drm_bridge *bridge)
+ {
+ struct lt8912 *lt = bridge_to_lt8912(bridge);
+
+- if (lt->is_attached) {
+- lt8912_hard_power_off(lt);
++ lt8912_hard_power_off(lt);
+
+- if (lt->hdmi_port->ops & DRM_BRIDGE_OP_HPD)
+- drm_bridge_hpd_disable(lt->hdmi_port);
++ if (lt->hdmi_port->ops & DRM_BRIDGE_OP_HPD)
++ drm_bridge_hpd_disable(lt->hdmi_port);
+
+- drm_connector_unregister(<->connector);
+- drm_connector_cleanup(<->connector);
+- }
++ drm_connector_unregister(<->connector);
++ drm_connector_cleanup(<->connector);
+ }
+
+ static enum drm_connector_status
+@@ -746,7 +741,6 @@ static int lt8912_remove(struct i2c_client *client)
+ {
+ struct lt8912 *lt = i2c_get_clientdata(client);
+
+- lt8912_bridge_detach(<->bridge);
+ drm_bridge_remove(<->bridge);
+ lt8912_free_i2c(lt);
+ lt8912_put_dt(lt);
+--
+2.42.0
+
--- /dev/null
+From b0f481c45c01d2a386e38f0c1e4912aa7a661981 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 4 Aug 2023 13:48:11 +0300
+Subject: drm/bridge: lt8912b: Fix crash on bridge detach
+
+From: Tomi Valkeinen <tomi.valkeinen@ideasonboard.com>
+
+[ Upstream commit 44283993144a03af9df31934d6c32bbd42d1a347 ]
+
+The lt8912b driver, in its bridge detach function, calls
+drm_connector_unregister() and drm_connector_cleanup().
+
+drm_connector_unregister() should be called only for connectors
+explicitly registered with drm_connector_register(), which is not the
+case in lt8912b.
+
+The driver's drm_connector_funcs.destroy hook is set to
+drm_connector_cleanup().
+
+Thus the driver should not call either drm_connector_unregister() nor
+drm_connector_cleanup() in its lt8912_bridge_detach(), as they cause a
+crash on bridge detach:
+
+Unable to handle kernel NULL pointer dereference at virtual address 0000000000000000
+Mem abort info:
+ ESR = 0x0000000096000006
+ EC = 0x25: DABT (current EL), IL = 32 bits
+ SET = 0, FnV = 0
+ EA = 0, S1PTW = 0
+ FSC = 0x06: level 2 translation fault
+Data abort info:
+ ISV = 0, ISS = 0x00000006, ISS2 = 0x00000000
+ CM = 0, WnR = 0, TnD = 0, TagAccess = 0
+ GCS = 0, Overlay = 0, DirtyBit = 0, Xs = 0
+user pgtable: 4k pages, 48-bit VAs, pgdp=00000000858f3000
+[0000000000000000] pgd=0800000085918003, p4d=0800000085918003, pud=0800000085431003, pmd=0000000000000000
+Internal error: Oops: 0000000096000006 [#1] PREEMPT SMP
+Modules linked in: tidss(-) display_connector lontium_lt8912b tc358768 panel_lvds panel_simple drm_dma_helper drm_kms_helper drm drm_panel_orientation_quirks
+CPU: 3 PID: 462 Comm: rmmod Tainted: G W 6.5.0-rc2+ #2
+Hardware name: Toradex Verdin AM62 on Verdin Development Board (DT)
+pstate: 80000005 (Nzcv daif -PAN -UAO -TCO -DIT -SSBS BTYPE=--)
+pc : drm_connector_cleanup+0x78/0x2d4 [drm]
+lr : lt8912_bridge_detach+0x54/0x6c [lontium_lt8912b]
+sp : ffff800082ed3a90
+x29: ffff800082ed3a90 x28: ffff0000040c1940 x27: 0000000000000000
+x26: 0000000000000000 x25: dead000000000122 x24: dead000000000122
+x23: dead000000000100 x22: ffff000003fb6388 x21: 0000000000000000
+x20: 0000000000000000 x19: ffff000003fb6260 x18: fffffffffffe56e8
+x17: 0000000000000000 x16: 0010000000000000 x15: 0000000000000038
+x14: 0000000000000000 x13: ffff800081914b48 x12: 000000000000040e
+x11: 000000000000015a x10: ffff80008196ebb8 x9 : ffff800081914b48
+x8 : 00000000ffffefff x7 : ffff0000040c1940 x6 : ffff80007aa649d0
+x5 : 0000000000000000 x4 : 0000000000000001 x3 : ffff80008159e008
+x2 : 0000000000000000 x1 : 0000000000000000 x0 : 0000000000000000
+Call trace:
+ drm_connector_cleanup+0x78/0x2d4 [drm]
+ lt8912_bridge_detach+0x54/0x6c [lontium_lt8912b]
+ drm_bridge_detach+0x44/0x84 [drm]
+ drm_encoder_cleanup+0x40/0xb8 [drm]
+ drmm_encoder_alloc_release+0x1c/0x30 [drm]
+ drm_managed_release+0xac/0x148 [drm]
+ drm_dev_put.part.0+0x88/0xb8 [drm]
+ devm_drm_dev_init_release+0x14/0x24 [drm]
+ devm_action_release+0x14/0x20
+ release_nodes+0x5c/0x90
+ devres_release_all+0x8c/0xe0
+ device_unbind_cleanup+0x18/0x68
+ device_release_driver_internal+0x208/0x23c
+ driver_detach+0x4c/0x94
+ bus_remove_driver+0x70/0xf4
+ driver_unregister+0x30/0x60
+ platform_driver_unregister+0x14/0x20
+ tidss_platform_driver_exit+0x18/0xb2c [tidss]
+ __arm64_sys_delete_module+0x1a0/0x2b4
+ invoke_syscall+0x48/0x110
+ el0_svc_common.constprop.0+0x60/0x10c
+ do_el0_svc_compat+0x1c/0x40
+ el0_svc_compat+0x40/0xac
+ el0t_32_sync_handler+0xb0/0x138
+ el0t_32_sync+0x194/0x198
+Code: 9104a276 f2fbd5b7 aa0203e1 91008af8 (f85c0420)
+
+Fixes: 30e2ae943c26 ("drm/bridge: Introduce LT8912B DSI to HDMI bridge")
+Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ideasonboard.com>
+Reviewed-by: Robert Foss <rfoss@kernel.org>
+Signed-off-by: Robert Foss <rfoss@kernel.org>
+Link: https://patchwork.freedesktop.org/patch/msgid/20230804-lt8912b-v1-2-c542692c6a2f@ideasonboard.com
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/gpu/drm/bridge/lontium-lt8912b.c | 3 ---
+ 1 file changed, 3 deletions(-)
+
+diff --git a/drivers/gpu/drm/bridge/lontium-lt8912b.c b/drivers/gpu/drm/bridge/lontium-lt8912b.c
+index d435cb3ed3808..b1e5acca171be 100644
+--- a/drivers/gpu/drm/bridge/lontium-lt8912b.c
++++ b/drivers/gpu/drm/bridge/lontium-lt8912b.c
+@@ -579,9 +579,6 @@ static void lt8912_bridge_detach(struct drm_bridge *bridge)
+
+ if (lt->hdmi_port->ops & DRM_BRIDGE_OP_HPD)
+ drm_bridge_hpd_disable(lt->hdmi_port);
+-
+- drm_connector_unregister(<->connector);
+- drm_connector_cleanup(<->connector);
+ }
+
+ static enum drm_connector_status
+--
+2.42.0
+
--- /dev/null
+From 47f9aa56c92b0ee9b131f1fa7c30d75fb2560be2 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 4 Aug 2023 13:48:12 +0300
+Subject: drm/bridge: lt8912b: Manually disable HPD only if it was enabled
+
+From: Tomi Valkeinen <tomi.valkeinen@ideasonboard.com>
+
+[ Upstream commit 6985c5efc4057bc79137807295d84ada3123d051 ]
+
+lt8912b only calls drm_bridge_hpd_enable() if it creates a connector and
+the next bridge has DRM_BRIDGE_OP_HPD set. However, when calling
+drm_bridge_hpd_disable() it misses checking if a connector was created,
+calling drm_bridge_hpd_disable() even if HPD was never enabled. I don't
+see any issues caused by this wrong call, though.
+
+Add the check to avoid wrongly calling drm_bridge_hpd_disable().
+
+Fixes: 3b0a01a6a522 ("drm/bridge: lt8912b: Add hot plug detection")
+Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ideasonboard.com>
+Tested-by: Marcel Ziswiler <marcel.ziswiler@toradex.com>
+Reviewed-by: Robert Foss <rfoss@kernel.org>
+Signed-off-by: Robert Foss <rfoss@kernel.org>
+Link: https://patchwork.freedesktop.org/patch/msgid/20230804-lt8912b-v1-3-c542692c6a2f@ideasonboard.com
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/gpu/drm/bridge/lontium-lt8912b.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/drivers/gpu/drm/bridge/lontium-lt8912b.c b/drivers/gpu/drm/bridge/lontium-lt8912b.c
+index b1e5acca171be..73b6fcae6dca8 100644
+--- a/drivers/gpu/drm/bridge/lontium-lt8912b.c
++++ b/drivers/gpu/drm/bridge/lontium-lt8912b.c
+@@ -577,7 +577,7 @@ static void lt8912_bridge_detach(struct drm_bridge *bridge)
+
+ lt8912_hard_power_off(lt);
+
+- if (lt->hdmi_port->ops & DRM_BRIDGE_OP_HPD)
++ if (lt->connector.dev && lt->hdmi_port->ops & DRM_BRIDGE_OP_HPD)
+ drm_bridge_hpd_disable(lt->hdmi_port);
+ }
+
+--
+2.42.0
+
--- /dev/null
+From 3c4515b29563df7f164c18188c98821f2da3f2d8 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 25 Oct 2021 17:15:21 +0200
+Subject: drm/bridge: lt8912b: Register and attach our DSI device at probe
+
+From: Maxime Ripard <maxime@cerno.tech>
+
+[ Upstream commit d89078c37b10f05fa4f4791b71db2572db361b68 ]
+
+In order to avoid any probe ordering issue, the best practice is to move
+the secondary MIPI-DSI device registration and attachment to the
+MIPI-DSI host at probe time. Let's do this.
+
+Acked-by: Sam Ravnborg <sam@ravnborg.org>
+Signed-off-by: Maxime Ripard <maxime@cerno.tech>
+Link: https://patchwork.freedesktop.org/patch/msgid/20211025151536.1048186-7-maxime@cerno.tech
+Stable-dep-of: 941882a0e96d ("drm/bridge: lt8912b: Fix bridge_detach")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/gpu/drm/bridge/lontium-lt8912b.c | 11 +++++++----
+ 1 file changed, 7 insertions(+), 4 deletions(-)
+
+diff --git a/drivers/gpu/drm/bridge/lontium-lt8912b.c b/drivers/gpu/drm/bridge/lontium-lt8912b.c
+index 24ca22b0b9f56..6ad3b2d1819f1 100644
+--- a/drivers/gpu/drm/bridge/lontium-lt8912b.c
++++ b/drivers/gpu/drm/bridge/lontium-lt8912b.c
+@@ -552,10 +552,6 @@ static int lt8912_bridge_attach(struct drm_bridge *bridge,
+ if (ret)
+ goto error;
+
+- ret = lt8912_attach_dsi(lt);
+- if (ret)
+- goto error;
+-
+ lt->is_attached = true;
+
+ return 0;
+@@ -714,8 +710,15 @@ static int lt8912_probe(struct i2c_client *client,
+
+ drm_bridge_add(<->bridge);
+
++ ret = lt8912_attach_dsi(lt);
++ if (ret)
++ goto err_attach;
++
+ return 0;
+
++err_attach:
++ drm_bridge_remove(<->bridge);
++ lt8912_free_i2c(lt);
+ err_i2c:
+ lt8912_put_dt(lt);
+ err_dt_parse:
+--
+2.42.0
+
--- /dev/null
+From 9e99f0286e16b79585c4303b7ecb03979e67ef29 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 25 Oct 2021 17:15:20 +0200
+Subject: drm/bridge: lt8912b: Switch to devm MIPI-DSI helpers
+
+From: Maxime Ripard <maxime@cerno.tech>
+
+[ Upstream commit 1fdbf66e3d40257902b4c5cdf872730dae24004f ]
+
+Let's switch to the new devm MIPI-DSI function to register and attach
+our secondary device.
+
+Acked-by: Sam Ravnborg <sam@ravnborg.org>
+Signed-off-by: Maxime Ripard <maxime@cerno.tech>
+Link: https://patchwork.freedesktop.org/patch/msgid/20211025151536.1048186-6-maxime@cerno.tech
+Stable-dep-of: 941882a0e96d ("drm/bridge: lt8912b: Fix bridge_detach")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/gpu/drm/bridge/lontium-lt8912b.c | 20 ++++----------------
+ 1 file changed, 4 insertions(+), 16 deletions(-)
+
+diff --git a/drivers/gpu/drm/bridge/lontium-lt8912b.c b/drivers/gpu/drm/bridge/lontium-lt8912b.c
+index d3fd76a0a34ae..24ca22b0b9f56 100644
+--- a/drivers/gpu/drm/bridge/lontium-lt8912b.c
++++ b/drivers/gpu/drm/bridge/lontium-lt8912b.c
+@@ -481,11 +481,11 @@ static int lt8912_attach_dsi(struct lt8912 *lt)
+ return -EPROBE_DEFER;
+ }
+
+- dsi = mipi_dsi_device_register_full(host, &info);
++ dsi = devm_mipi_dsi_device_register_full(dev, host, &info);
+ if (IS_ERR(dsi)) {
+ ret = PTR_ERR(dsi);
+ dev_err(dev, "failed to create dsi device (%d)\n", ret);
+- goto err_dsi_device;
++ return ret;
+ }
+
+ lt->dsi = dsi;
+@@ -497,24 +497,13 @@ static int lt8912_attach_dsi(struct lt8912 *lt)
+ MIPI_DSI_MODE_LPM |
+ MIPI_DSI_MODE_NO_EOT_PACKET;
+
+- ret = mipi_dsi_attach(dsi);
++ ret = devm_mipi_dsi_attach(dev, dsi);
+ if (ret < 0) {
+ dev_err(dev, "failed to attach dsi to host\n");
+- goto err_dsi_attach;
++ return ret;
+ }
+
+ return 0;
+-
+-err_dsi_attach:
+- mipi_dsi_device_unregister(dsi);
+-err_dsi_device:
+- return ret;
+-}
+-
+-static void lt8912_detach_dsi(struct lt8912 *lt)
+-{
+- mipi_dsi_detach(lt->dsi);
+- mipi_dsi_device_unregister(lt->dsi);
+ }
+
+ static int lt8912_bridge_connector_init(struct drm_bridge *bridge)
+@@ -581,7 +570,6 @@ static void lt8912_bridge_detach(struct drm_bridge *bridge)
+ struct lt8912 *lt = bridge_to_lt8912(bridge);
+
+ if (lt->is_attached) {
+- lt8912_detach_dsi(lt);
+ lt8912_hard_power_off(lt);
+ drm_connector_unregister(<->connector);
+ drm_connector_cleanup(<->connector);
+--
+2.42.0
+
--- /dev/null
+From e361bf4a5728d60658080eea4a8fe30ee27820cd Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 12 Oct 2023 01:00:02 +0300
+Subject: drm/bridge: lt9611uxc: fix the race in the error path
+
+From: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
+
+[ Upstream commit 15fe53be46eaf4f6339cd433972ecc90513e3076 ]
+
+If DSI host attachment fails, the LT9611UXC driver will remove the
+bridge without ensuring that there is no outstanding HPD work being
+done. In rare cases this can result in the warnings regarding the mutex
+being incorrect. Fix this by forcebly freing IRQ and flushing the work.
+
+DEBUG_LOCKS_WARN_ON(lock->magic != lock)
+WARNING: CPU: 0 PID: 10 at kernel/locking/mutex.c:582 __mutex_lock+0x468/0x77c
+Modules linked in:
+CPU: 0 PID: 10 Comm: kworker/0:1 Tainted: G U 6.6.0-rc5-next-20231011-gd81f81c2b682-dirty #1206
+Hardware name: Qualcomm Technologies, Inc. Robotics RB5 (DT)
+Workqueue: events lt9611uxc_hpd_work
+pstate: 60400005 (nZCv daif +PAN -UAO -TCO -DIT -SSBS BTYPE=--)
+pc : __mutex_lock+0x468/0x77c
+lr : __mutex_lock+0x468/0x77c
+sp : ffff8000800a3c70
+x29: ffff8000800a3c70 x28: 0000000000000000 x27: ffffd595fe333000
+x26: ffff7c2f0002c005 x25: ffffd595ff1b3000 x24: ffffd595fccda5a0
+x23: 0000000000000000 x22: 0000000000000002 x21: ffff7c2f056d91c8
+x20: 0000000000000000 x19: ffff7c2f056d91c8 x18: fffffffffffe8db0
+x17: 000000040044ffff x16: 005000f2b5503510 x15: 0000000000000000
+x14: 000000000006efb8 x13: 0000000000000000 x12: 0000000000000037
+x11: 0000000000000001 x10: 0000000000001470 x9 : ffff8000800a3ae0
+x8 : ffff7c2f0027f8d0 x7 : ffff7c2f0027e400 x6 : ffffd595fc702b54
+x5 : 0000000000000000 x4 : ffff8000800a0000 x3 : 0000000000000000
+x2 : 0000000000000000 x1 : 0000000000000000 x0 : ffff7c2f0027e400
+Call trace:
+ __mutex_lock+0x468/0x77c
+ mutex_lock_nested+0x24/0x30
+ drm_bridge_hpd_notify+0x2c/0x5c
+ lt9611uxc_hpd_work+0x6c/0x80
+ process_one_work+0x1ec/0x51c
+ worker_thread+0x1ec/0x3e4
+ kthread+0x120/0x124
+ ret_from_fork+0x10/0x20
+irq event stamp: 15799
+hardirqs last enabled at (15799): [<ffffd595fc702ba4>] finish_task_switch.isra.0+0xa8/0x278
+hardirqs last disabled at (15798): [<ffffd595fd5a1580>] __schedule+0x7b8/0xbd8
+softirqs last enabled at (15794): [<ffffd595fc690698>] __do_softirq+0x498/0x4e0
+softirqs last disabled at (15771): [<ffffd595fc69615c>] ____do_softirq+0x10/0x1c
+
+Fixes: bc6fa8676ebb ("drm/bridge/lontium-lt9611uxc: move HPD notification out of IRQ handler")
+Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
+Reviewed-by: Robert Foss <rfoss@kernel.org>
+Signed-off-by: Robert Foss <rfoss@kernel.org>
+Link: https://patchwork.freedesktop.org/patch/msgid/20231011220002.382422-1-dmitry.baryshkov@linaro.org
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/gpu/drm/bridge/lontium-lt9611uxc.c | 10 ++++++----
+ 1 file changed, 6 insertions(+), 4 deletions(-)
+
+diff --git a/drivers/gpu/drm/bridge/lontium-lt9611uxc.c b/drivers/gpu/drm/bridge/lontium-lt9611uxc.c
+index 1e33b3150bdc5..2a848e14181bd 100644
+--- a/drivers/gpu/drm/bridge/lontium-lt9611uxc.c
++++ b/drivers/gpu/drm/bridge/lontium-lt9611uxc.c
+@@ -927,9 +927,9 @@ static int lt9611uxc_probe(struct i2c_client *client,
+ init_waitqueue_head(<9611uxc->wq);
+ INIT_WORK(<9611uxc->work, lt9611uxc_hpd_work);
+
+- ret = devm_request_threaded_irq(dev, client->irq, NULL,
+- lt9611uxc_irq_thread_handler,
+- IRQF_ONESHOT, "lt9611uxc", lt9611uxc);
++ ret = request_threaded_irq(client->irq, NULL,
++ lt9611uxc_irq_thread_handler,
++ IRQF_ONESHOT, "lt9611uxc", lt9611uxc);
+ if (ret) {
+ dev_err(dev, "failed to request irq\n");
+ goto err_disable_regulators;
+@@ -965,6 +965,8 @@ static int lt9611uxc_probe(struct i2c_client *client,
+ return lt9611uxc_audio_init(dev, lt9611uxc);
+
+ err_remove_bridge:
++ free_irq(client->irq, lt9611uxc);
++ cancel_work_sync(<9611uxc->work);
+ drm_bridge_remove(<9611uxc->bridge);
+
+ err_disable_regulators:
+@@ -981,7 +983,7 @@ static int lt9611uxc_remove(struct i2c_client *client)
+ {
+ struct lt9611uxc *lt9611uxc = i2c_get_clientdata(client);
+
+- disable_irq(client->irq);
++ free_irq(client->irq, lt9611uxc);
+ cancel_work_sync(<9611uxc->work);
+ lt9611uxc_audio_exit(lt9611uxc);
+ drm_bridge_remove(<9611uxc->bridge);
+--
+2.42.0
+
--- /dev/null
+From b5b7ebc758de810cde1fe1a8b6dc0c360a16ce5f Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 25 Oct 2021 17:15:25 +0200
+Subject: drm/bridge: lt9611uxc: Register and attach our DSI device at probe
+
+From: Maxime Ripard <maxime@cerno.tech>
+
+[ Upstream commit 4a46ace5ac621c0f84b3910bc3c93acf6c93963b ]
+
+In order to avoid any probe ordering issue, the best practice is to move
+the secondary MIPI-DSI device registration and attachment to the
+MIPI-DSI host at probe time. Let's do this.
+
+Acked-by: Sam Ravnborg <sam@ravnborg.org>
+Signed-off-by: Maxime Ripard <maxime@cerno.tech>
+Link: https://patchwork.freedesktop.org/patch/msgid/20211025151536.1048186-11-maxime@cerno.tech
+Stable-dep-of: 15fe53be46ea ("drm/bridge: lt9611uxc: fix the race in the error path")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/gpu/drm/bridge/lontium-lt9611uxc.c | 31 +++++++++++++---------
+ 1 file changed, 19 insertions(+), 12 deletions(-)
+
+diff --git a/drivers/gpu/drm/bridge/lontium-lt9611uxc.c b/drivers/gpu/drm/bridge/lontium-lt9611uxc.c
+index b58842f69fff1..1e33b3150bdc5 100644
+--- a/drivers/gpu/drm/bridge/lontium-lt9611uxc.c
++++ b/drivers/gpu/drm/bridge/lontium-lt9611uxc.c
+@@ -367,18 +367,6 @@ static int lt9611uxc_bridge_attach(struct drm_bridge *bridge,
+ return ret;
+ }
+
+- /* Attach primary DSI */
+- lt9611uxc->dsi0 = lt9611uxc_attach_dsi(lt9611uxc, lt9611uxc->dsi0_node);
+- if (IS_ERR(lt9611uxc->dsi0))
+- return PTR_ERR(lt9611uxc->dsi0);
+-
+- /* Attach secondary DSI, if specified */
+- if (lt9611uxc->dsi1_node) {
+- lt9611uxc->dsi1 = lt9611uxc_attach_dsi(lt9611uxc, lt9611uxc->dsi1_node);
+- if (IS_ERR(lt9611uxc->dsi1))
+- return PTR_ERR(lt9611uxc->dsi1);
+- }
+-
+ return 0;
+ }
+
+@@ -958,8 +946,27 @@ static int lt9611uxc_probe(struct i2c_client *client,
+
+ drm_bridge_add(<9611uxc->bridge);
+
++ /* Attach primary DSI */
++ lt9611uxc->dsi0 = lt9611uxc_attach_dsi(lt9611uxc, lt9611uxc->dsi0_node);
++ if (IS_ERR(lt9611uxc->dsi0)) {
++ ret = PTR_ERR(lt9611uxc->dsi0);
++ goto err_remove_bridge;
++ }
++
++ /* Attach secondary DSI, if specified */
++ if (lt9611uxc->dsi1_node) {
++ lt9611uxc->dsi1 = lt9611uxc_attach_dsi(lt9611uxc, lt9611uxc->dsi1_node);
++ if (IS_ERR(lt9611uxc->dsi1)) {
++ ret = PTR_ERR(lt9611uxc->dsi1);
++ goto err_remove_bridge;
++ }
++ }
++
+ return lt9611uxc_audio_init(dev, lt9611uxc);
+
++err_remove_bridge:
++ drm_bridge_remove(<9611uxc->bridge);
++
+ err_disable_regulators:
+ regulator_bulk_disable(ARRAY_SIZE(lt9611uxc->supplies), lt9611uxc->supplies);
+
+--
+2.42.0
+
--- /dev/null
+From 3efc5c224d70063d85d9dbedcf4c850335afe2c8 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 25 Oct 2021 17:15:24 +0200
+Subject: drm/bridge: lt9611uxc: Switch to devm MIPI-DSI helpers
+
+From: Maxime Ripard <maxime@cerno.tech>
+
+[ Upstream commit 293ada7b058e536d9d53d0d8840c6ba8c2f718e4 ]
+
+Let's switch to the new devm MIPI-DSI function to register and attach
+our secondary device.
+
+Acked-by: Sam Ravnborg <sam@ravnborg.org>
+Signed-off-by: Maxime Ripard <maxime@cerno.tech>
+Link: https://patchwork.freedesktop.org/patch/msgid/20211025151536.1048186-10-maxime@cerno.tech
+Stable-dep-of: 15fe53be46ea ("drm/bridge: lt9611uxc: fix the race in the error path")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/gpu/drm/bridge/lontium-lt9611uxc.c | 38 +++++-----------------
+ 1 file changed, 8 insertions(+), 30 deletions(-)
+
+diff --git a/drivers/gpu/drm/bridge/lontium-lt9611uxc.c b/drivers/gpu/drm/bridge/lontium-lt9611uxc.c
+index c4454d0f6cad5..b58842f69fff1 100644
+--- a/drivers/gpu/drm/bridge/lontium-lt9611uxc.c
++++ b/drivers/gpu/drm/bridge/lontium-lt9611uxc.c
+@@ -258,17 +258,18 @@ static struct mipi_dsi_device *lt9611uxc_attach_dsi(struct lt9611uxc *lt9611uxc,
+ const struct mipi_dsi_device_info info = { "lt9611uxc", 0, NULL };
+ struct mipi_dsi_device *dsi;
+ struct mipi_dsi_host *host;
++ struct device *dev = lt9611uxc->dev;
+ int ret;
+
+ host = of_find_mipi_dsi_host_by_node(dsi_node);
+ if (!host) {
+- dev_err(lt9611uxc->dev, "failed to find dsi host\n");
++ dev_err(dev, "failed to find dsi host\n");
+ return ERR_PTR(-EPROBE_DEFER);
+ }
+
+- dsi = mipi_dsi_device_register_full(host, &info);
++ dsi = devm_mipi_dsi_device_register_full(dev, host, &info);
+ if (IS_ERR(dsi)) {
+- dev_err(lt9611uxc->dev, "failed to create dsi device\n");
++ dev_err(dev, "failed to create dsi device\n");
+ return dsi;
+ }
+
+@@ -277,10 +278,9 @@ static struct mipi_dsi_device *lt9611uxc_attach_dsi(struct lt9611uxc *lt9611uxc,
+ dsi->mode_flags = MIPI_DSI_MODE_VIDEO | MIPI_DSI_MODE_VIDEO_SYNC_PULSE |
+ MIPI_DSI_MODE_VIDEO_HSE;
+
+- ret = mipi_dsi_attach(dsi);
++ ret = devm_mipi_dsi_attach(dev, dsi);
+ if (ret < 0) {
+- dev_err(lt9611uxc->dev, "failed to attach dsi to host\n");
+- mipi_dsi_device_unregister(dsi);
++ dev_err(dev, "failed to attach dsi to host\n");
+ return ERR_PTR(ret);
+ }
+
+@@ -355,19 +355,6 @@ static int lt9611uxc_connector_init(struct drm_bridge *bridge, struct lt9611uxc
+ return drm_connector_attach_encoder(<9611uxc->connector, bridge->encoder);
+ }
+
+-static void lt9611uxc_bridge_detach(struct drm_bridge *bridge)
+-{
+- struct lt9611uxc *lt9611uxc = bridge_to_lt9611uxc(bridge);
+-
+- if (lt9611uxc->dsi1) {
+- mipi_dsi_detach(lt9611uxc->dsi1);
+- mipi_dsi_device_unregister(lt9611uxc->dsi1);
+- }
+-
+- mipi_dsi_detach(lt9611uxc->dsi0);
+- mipi_dsi_device_unregister(lt9611uxc->dsi0);
+-}
+-
+ static int lt9611uxc_bridge_attach(struct drm_bridge *bridge,
+ enum drm_bridge_attach_flags flags)
+ {
+@@ -388,19 +375,11 @@ static int lt9611uxc_bridge_attach(struct drm_bridge *bridge,
+ /* Attach secondary DSI, if specified */
+ if (lt9611uxc->dsi1_node) {
+ lt9611uxc->dsi1 = lt9611uxc_attach_dsi(lt9611uxc, lt9611uxc->dsi1_node);
+- if (IS_ERR(lt9611uxc->dsi1)) {
+- ret = PTR_ERR(lt9611uxc->dsi1);
+- goto err_unregister_dsi0;
+- }
++ if (IS_ERR(lt9611uxc->dsi1))
++ return PTR_ERR(lt9611uxc->dsi1);
+ }
+
+ return 0;
+-
+-err_unregister_dsi0:
+- mipi_dsi_detach(lt9611uxc->dsi0);
+- mipi_dsi_device_unregister(lt9611uxc->dsi0);
+-
+- return ret;
+ }
+
+ static enum drm_mode_status
+@@ -544,7 +523,6 @@ static struct edid *lt9611uxc_bridge_get_edid(struct drm_bridge *bridge,
+
+ static const struct drm_bridge_funcs lt9611uxc_bridge_funcs = {
+ .attach = lt9611uxc_bridge_attach,
+- .detach = lt9611uxc_bridge_detach,
+ .mode_valid = lt9611uxc_bridge_mode_valid,
+ .mode_set = lt9611uxc_bridge_mode_set,
+ .detect = lt9611uxc_bridge_detect,
+--
+2.42.0
+
--- /dev/null
+From b2d5f4025af48f6cacb05d6613566856e094ecca Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sun, 3 Oct 2021 02:34:46 +0300
+Subject: drm/bridge: tc358768: Disable non-continuous clock mode
+
+From: Dmitry Osipenko <digetx@gmail.com>
+
+[ Upstream commit fbc5a90e82c1131869e76ce5b082693b8a75c121 ]
+
+Non-continuous clock mode doesn't work because driver doesn't support it
+properly. The bridge driver programs wrong bitfields that are required by
+the non-continuous mode (BTACNTRL1 register bitfields are swapped in the
+code), but fixing them doesn't help.
+
+Display panel of ASUS Transformer TF700T tablet supports non-continuous
+mode and display doesn't work at all using that mode. There are no
+device-trees that are actively using this DSI bridge in upstream yet,
+so clearly the broken mode wasn't ever tested properly. It's a bit too
+difficult to get LP mode working, hence let's disable the offending mode
+for now and fall back to continuous mode.
+
+Tested-by: Andreas Westman Dorcsak <hedmoo@yahoo.com> # Asus TF700T
+Tested-by: Maxim Schwalm <maxim.schwalm@gmail.com> #TF700T
+Signed-off-by: Dmitry Osipenko <digetx@gmail.com>
+Reviewed-by: Robert Foss <robert.foss@linaro.org>
+Signed-off-by: Robert Foss <robert.foss@linaro.org>
+Link: https://patchwork.freedesktop.org/patch/msgid/20211002233447.1105-5-digetx@gmail.com
+Stable-dep-of: 66962d5c3c51 ("drm/bridge: tc358768: Fix bit updates")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/gpu/drm/bridge/tc358768.c | 10 ++++++++--
+ 1 file changed, 8 insertions(+), 2 deletions(-)
+
+diff --git a/drivers/gpu/drm/bridge/tc358768.c b/drivers/gpu/drm/bridge/tc358768.c
+index da37dfd81a6fb..1e5304274ce20 100644
+--- a/drivers/gpu/drm/bridge/tc358768.c
++++ b/drivers/gpu/drm/bridge/tc358768.c
+@@ -637,6 +637,7 @@ static void tc358768_bridge_pre_enable(struct drm_bridge *bridge)
+ {
+ struct tc358768_priv *priv = bridge_to_tc358768(bridge);
+ struct mipi_dsi_device *dsi_dev = priv->output.dev;
++ unsigned long mode_flags = dsi_dev->mode_flags;
+ u32 val, val2, lptxcnt, hact, data_type;
+ s32 raw_val;
+ const struct drm_display_mode *mode;
+@@ -644,6 +645,11 @@ static void tc358768_bridge_pre_enable(struct drm_bridge *bridge)
+ u32 dsiclk, dsibclk;
+ int ret, i;
+
++ if (mode_flags & MIPI_DSI_CLOCK_NON_CONTINUOUS) {
++ dev_warn_once(priv->dev, "Non-continuous mode unimplemented, falling back to continuous\n");
++ mode_flags &= ~MIPI_DSI_CLOCK_NON_CONTINUOUS;
++ }
++
+ tc358768_hw_enable(priv);
+
+ ret = tc358768_sw_reset(priv);
+@@ -779,7 +785,7 @@ static void tc358768_bridge_pre_enable(struct drm_bridge *bridge)
+ val |= BIT(i + 1);
+ tc358768_write(priv, TC358768_HSTXVREGEN, val);
+
+- if (!(dsi_dev->mode_flags & MIPI_DSI_CLOCK_NON_CONTINUOUS))
++ if (!(mode_flags & MIPI_DSI_CLOCK_NON_CONTINUOUS))
+ tc358768_write(priv, TC358768_TXOPTIONCNTRL, 0x1);
+
+ /* TXTAGOCNT[26:16] RXTASURECNT[10:0] */
+@@ -836,7 +842,7 @@ static void tc358768_bridge_pre_enable(struct drm_bridge *bridge)
+
+ val |= TC358768_DSI_CONTROL_TXMD;
+
+- if (!(dsi_dev->mode_flags & MIPI_DSI_CLOCK_NON_CONTINUOUS))
++ if (!(mode_flags & MIPI_DSI_CLOCK_NON_CONTINUOUS))
+ val |= TC358768_DSI_CONTROL_HSCKMD;
+
+ if (dsi_dev->mode_flags & MIPI_DSI_MODE_NO_EOT_PACKET)
+--
+2.42.0
+
--- /dev/null
+From 7692a35b9d796feffb0b88e02c0695f34ace12ed Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 6 Sep 2023 09:50:51 +0300
+Subject: drm/bridge: tc358768: Fix bit updates
+
+From: Tomi Valkeinen <tomi.valkeinen@ideasonboard.com>
+
+[ Upstream commit 66962d5c3c51377b9b90cae35b7e038950438e02 ]
+
+The driver has a few places where it does:
+
+if (thing_is_enabled_in_config)
+ update_thing_bit_in_hw()
+
+This means that if the thing is _not_ enabled, the bit never gets
+cleared. This affects the h/vsyncs and continuous DSI clock bits.
+
+Fix the driver to always update the bit.
+
+Fixes: ff1ca6397b1d ("drm/bridge: Add tc358768 driver")
+Reviewed-by: Peter Ujfalusi <peter.ujfalusi@gmail.com>
+Tested-by: Maxim Schwalm <maxim.schwalm@gmail.com> # Asus TF700T
+Tested-by: Marcel Ziswiler <marcel.ziswiler@toradex.com>
+Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ideasonboard.com>
+Signed-off-by: Robert Foss <rfoss@kernel.org>
+Link: https://patchwork.freedesktop.org/patch/msgid/20230906-tc358768-v4-4-31725f008a50@ideasonboard.com
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/gpu/drm/bridge/tc358768.c | 13 +++++++------
+ 1 file changed, 7 insertions(+), 6 deletions(-)
+
+diff --git a/drivers/gpu/drm/bridge/tc358768.c b/drivers/gpu/drm/bridge/tc358768.c
+index 1e5304274ce20..d81c35a85330b 100644
+--- a/drivers/gpu/drm/bridge/tc358768.c
++++ b/drivers/gpu/drm/bridge/tc358768.c
+@@ -785,8 +785,8 @@ static void tc358768_bridge_pre_enable(struct drm_bridge *bridge)
+ val |= BIT(i + 1);
+ tc358768_write(priv, TC358768_HSTXVREGEN, val);
+
+- if (!(mode_flags & MIPI_DSI_CLOCK_NON_CONTINUOUS))
+- tc358768_write(priv, TC358768_TXOPTIONCNTRL, 0x1);
++ tc358768_write(priv, TC358768_TXOPTIONCNTRL,
++ (mode_flags & MIPI_DSI_CLOCK_NON_CONTINUOUS) ? 0 : BIT(0));
+
+ /* TXTAGOCNT[26:16] RXTASURECNT[10:0] */
+ val = tc358768_to_ns((lptxcnt + 1) * dsibclk_nsk * 4);
+@@ -822,11 +822,12 @@ static void tc358768_bridge_pre_enable(struct drm_bridge *bridge)
+ tc358768_write(priv, TC358768_DSI_HACT, hact);
+
+ /* VSYNC polarity */
+- if (!(mode->flags & DRM_MODE_FLAG_NVSYNC))
+- tc358768_update_bits(priv, TC358768_CONFCTL, BIT(5), BIT(5));
++ tc358768_update_bits(priv, TC358768_CONFCTL, BIT(5),
++ (mode->flags & DRM_MODE_FLAG_PVSYNC) ? BIT(5) : 0);
++
+ /* HSYNC polarity */
+- if (mode->flags & DRM_MODE_FLAG_PHSYNC)
+- tc358768_update_bits(priv, TC358768_PP_MISC, BIT(0), BIT(0));
++ tc358768_update_bits(priv, TC358768_PP_MISC, BIT(0),
++ (mode->flags & DRM_MODE_FLAG_PHSYNC) ? BIT(0) : 0);
+
+ /* Start DSI Tx */
+ tc358768_write(priv, TC358768_DSI_START, 0x1);
+--
+2.42.0
+
--- /dev/null
+From 2c1f76f09b61b3c16b1e286a8a739e2588f61aa0 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 6 Sep 2023 09:50:49 +0300
+Subject: drm/bridge: tc358768: Fix use of uninitialized variable
+
+From: Tomi Valkeinen <tomi.valkeinen@ideasonboard.com>
+
+[ Upstream commit a2d9036615f0adfa5b0a46bb2ce42ef1d9a04fbe ]
+
+smatch reports:
+
+drivers/gpu/drm/bridge/tc358768.c:223 tc358768_update_bits() error: uninitialized symbol 'orig'.
+
+Fix this by bailing out from tc358768_update_bits() if the
+tc358768_read() produces an error.
+
+Fixes: ff1ca6397b1d ("drm/bridge: Add tc358768 driver")
+Reviewed-by: Peter Ujfalusi <peter.ujfalusi@gmail.com>
+Tested-by: Maxim Schwalm <maxim.schwalm@gmail.com> # Asus TF700T
+Tested-by: Marcel Ziswiler <marcel.ziswiler@toradex.com>
+Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ideasonboard.com>
+Signed-off-by: Robert Foss <rfoss@kernel.org>
+Link: https://patchwork.freedesktop.org/patch/msgid/20230906-tc358768-v4-2-31725f008a50@ideasonboard.com
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/gpu/drm/bridge/tc358768.c | 4 ++++
+ 1 file changed, 4 insertions(+)
+
+diff --git a/drivers/gpu/drm/bridge/tc358768.c b/drivers/gpu/drm/bridge/tc358768.c
+index 8b1bdffc5005d..da37dfd81a6fb 100644
+--- a/drivers/gpu/drm/bridge/tc358768.c
++++ b/drivers/gpu/drm/bridge/tc358768.c
+@@ -217,6 +217,10 @@ static void tc358768_update_bits(struct tc358768_priv *priv, u32 reg, u32 mask,
+ u32 tmp, orig;
+
+ tc358768_read(priv, reg, &orig);
++
++ if (priv->error)
++ return;
++
+ tmp = orig & ~mask;
+ tmp |= val & mask;
+ if (tmp != orig)
+--
+2.42.0
+
--- /dev/null
+From 61b1471f1681c392ead9e8516f865c36748d38ec Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 9 Aug 2023 20:57:21 +0800
+Subject: drm/mediatek: Fix iommu fault by swapping FBs after updating plane
+ state
+
+From: Jason-JH.Lin <jason-jh.lin@mediatek.com>
+
+[ Upstream commit 3ec71e05ae6e7f46512e568ed81c92be589003dd ]
+
+According to the comment in drm_atomic_helper_async_commit(),
+we should make sure FBs have been swapped, so that cleanups in the
+new_state performs a cleanup in the old FB.
+
+So we should move swapping FBs after calling mtk_plane_update_new_state(),
+to avoid using the old FB which could be freed.
+
+Fixes: 1a64a7aff8da ("drm/mediatek: Fix cursor plane no update")
+Signed-off-by: Jason-JH.Lin <jason-jh.lin@mediatek.com>
+Reviewed-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
+Reviewed-by: CK Hu <ck.hu@mediatek.com>
+Reviewed-by: Alexandre Mergnat <amergnat@baylibre.com>
+Link: https://patchwork.kernel.org/project/linux-mediatek/patch/20230809125722.24112-2-jason-jh.lin@mediatek.com/
+Signed-off-by: Chun-Kuang Hu <chunkuang.hu@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/gpu/drm/mediatek/mtk_drm_plane.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/drivers/gpu/drm/mediatek/mtk_drm_plane.c b/drivers/gpu/drm/mediatek/mtk_drm_plane.c
+index 734a1fb052dfd..eda072a3bf9ae 100644
+--- a/drivers/gpu/drm/mediatek/mtk_drm_plane.c
++++ b/drivers/gpu/drm/mediatek/mtk_drm_plane.c
+@@ -154,9 +154,9 @@ static void mtk_plane_atomic_async_update(struct drm_plane *plane,
+ plane->state->src_y = new_state->src_y;
+ plane->state->src_h = new_state->src_h;
+ plane->state->src_w = new_state->src_w;
+- swap(plane->state->fb, new_state->fb);
+
+ mtk_plane_update_new_state(new_state, new_plane_state);
++ swap(plane->state->fb, new_state->fb);
+ wmb(); /* Make sure the above parameters are set before update */
+ new_plane_state->pending.async_dirty = true;
+ mtk_drm_crtc_async_update(new_state->crtc, plane, state);
+--
+2.42.0
+
--- /dev/null
+From bea5db616f5d960066aceae0cf963881dab6b52b Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 9 Aug 2023 20:57:22 +0800
+Subject: drm/mediatek: Fix iommu fault during crtc enabling
+
+From: Jason-JH.Lin <jason-jh.lin@mediatek.com>
+
+[ Upstream commit 53412dc2905401207f264dc30890f6b9e41524a6 ]
+
+The difference between drm_atomic_helper_commit_tail() and
+drm_atomic_helper_commit_tail_rpm() is
+drm_atomic_helper_commit_tail() will commit plane first and
+then enable crtc, drm_atomic_helper_commit_tail_rpm() will
+enable crtc first and then commit plane.
+
+Before mediatek-drm enables crtc, the power and clk required
+by OVL have not been turned on, so the commit plane cannot be
+committed before crtc is enabled. That means OVL layer should
+not be enabled before crtc is enabled.
+Therefore, the atomic_commit_tail of mediatek-drm is hooked with
+drm_atomic_helper_commit_tail_rpm().
+
+Another reason is that the plane_state of drm_atomic_state is not
+synchronized with the plane_state stored in mtk_crtc during crtc enablng,
+so just set all planes to disabled.
+
+Fixes: 119f5173628a ("drm/mediatek: Add DRM Driver for Mediatek SoC MT8173.")
+Signed-off-by: Jason-JH.Lin <jason-jh.lin@mediatek.com>
+Reviewed-by: Alexandre Mergnat <amergnat@baylibre.com>
+Reviewed-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
+Reviewed-by: CK Hu <ck.hu@mediatek.com>
+Link: https://patchwork.kernel.org/project/linux-mediatek/patch/20230809125722.24112-3-jason-jh.lin@mediatek.com/
+Signed-off-by: Chun-Kuang Hu <chunkuang.hu@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/gpu/drm/mediatek/mtk_drm_crtc.c | 3 +++
+ 1 file changed, 3 insertions(+)
+
+diff --git a/drivers/gpu/drm/mediatek/mtk_drm_crtc.c b/drivers/gpu/drm/mediatek/mtk_drm_crtc.c
+index 0b93013061e6a..f2264633be1b7 100644
+--- a/drivers/gpu/drm/mediatek/mtk_drm_crtc.c
++++ b/drivers/gpu/drm/mediatek/mtk_drm_crtc.c
+@@ -362,6 +362,9 @@ static int mtk_crtc_ddp_hw_init(struct mtk_drm_crtc *mtk_crtc)
+ unsigned int local_layer;
+
+ plane_state = to_mtk_plane_state(plane->state);
++
++ /* should not enable layer before crtc enabled */
++ plane_state->pending.enable = false;
+ comp = mtk_drm_ddp_comp_for_plane(crtc, plane, &local_layer);
+ if (comp)
+ mtk_ddp_comp_layer_config(comp, local_layer,
+--
+2.42.0
+
--- /dev/null
+From 9020fdcd57d70b8d51b55548a0854f43f34607ec Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 23 May 2023 12:42:34 +0200
+Subject: drm: mediatek: mtk_dsi: Fix NO_EOT_PACKET settings/handling
+
+From: AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
+
+[ Upstream commit 5855d422a6f250f3518f43b49092c8e87a5e42be ]
+
+Due to the initial confusion about MIPI_DSI_MODE_EOT_PACKET, properly
+renamed to MIPI_DSI_MODE_NO_EOT_PACKET, reflecting its actual meaning,
+both the DSI_TXRX_CON register setting for bit (HSTX_)DIS_EOT and the
+later calculation for horizontal sync-active (HSA), back (HBP) and
+front (HFP) porches got incorrect due to the logic being inverted.
+
+This means that a number of settings were wrong because....:
+ - DSI_TXRX_CON register setting: bit (HSTX_)DIS_EOT should be
+ set in order to disable the End of Transmission packet;
+ - Horizontal Sync and Back/Front porches: The delta used to
+ calculate all of HSA, HBP and HFP should account for the
+ additional EOT packet.
+
+Before this change...
+ - Bit (HSTX_)DIS_EOT was being set when EOT packet was enabled;
+ - For HSA/HBP/HFP delta... all three were wrong, as words were
+ added when EOT disabled, instead of when EOT packet enabled!
+
+Invert the logic around flag MIPI_DSI_MODE_NO_EOT_PACKET in the
+MediaTek DSI driver to fix the aforementioned issues.
+
+Fixes: 8b2b99fd7931 ("drm/mediatek: dsi: Fine tune the line time caused by EOTp")
+Fixes: c87d1c4b5b9a ("drm/mediatek: dsi: Use symbolized register definition")
+Signed-off-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
+Reviewed-by: Alexandre Mergnat <amergnat@baylibre.com>
+Tested-by: Michael Walle <mwalle@kernel.org>
+Link: https://patchwork.kernel.org/project/dri-devel/patch/20230523104234.7849-1-angelogioacchino.delregno@collabora.com/
+Signed-off-by: Chun-Kuang Hu <chunkuang.hu@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/gpu/drm/mediatek/mtk_dsi.c | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/drivers/gpu/drm/mediatek/mtk_dsi.c b/drivers/gpu/drm/mediatek/mtk_dsi.c
+index 98b1204c92906..57eaf111b6a8a 100644
+--- a/drivers/gpu/drm/mediatek/mtk_dsi.c
++++ b/drivers/gpu/drm/mediatek/mtk_dsi.c
+@@ -406,7 +406,7 @@ static void mtk_dsi_rxtx_control(struct mtk_dsi *dsi)
+ if (dsi->mode_flags & MIPI_DSI_CLOCK_NON_CONTINUOUS)
+ tmp_reg |= HSTX_CKLP_EN;
+
+- if (!(dsi->mode_flags & MIPI_DSI_MODE_NO_EOT_PACKET))
++ if (dsi->mode_flags & MIPI_DSI_MODE_NO_EOT_PACKET)
+ tmp_reg |= DIS_EOT;
+
+ writel(tmp_reg, dsi->regs + DSI_TXRX_CTRL);
+@@ -483,7 +483,7 @@ static void mtk_dsi_config_vdo_timing(struct mtk_dsi *dsi)
+ timing->da_hs_zero + timing->da_hs_exit + 3;
+
+ delta = dsi->mode_flags & MIPI_DSI_MODE_VIDEO_BURST ? 18 : 12;
+- delta += dsi->mode_flags & MIPI_DSI_MODE_NO_EOT_PACKET ? 2 : 0;
++ delta += dsi->mode_flags & MIPI_DSI_MODE_NO_EOT_PACKET ? 0 : 2;
+
+ horizontal_frontporch_byte = vm->hfront_porch * dsi_tmp_buf_bpp;
+ horizontal_front_back_byte = horizontal_frontporch_byte + horizontal_backporch_byte;
+--
+2.42.0
+
--- /dev/null
+From 48507e6d11abce4b0ad9519d5bd9dfc0518d4e68 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 10 Sep 2021 12:11:58 +0200
+Subject: drm/mipi-dsi: Create devm device attachment
+
+From: Maxime Ripard <maxime@cerno.tech>
+
+[ Upstream commit db6568498b35a4d5d5a99420df27ed25fae31406 ]
+
+MIPI-DSI devices need to call mipi_dsi_attach() when their probe is done
+to attach against their host.
+
+However, at removal or when an error occurs, that attachment needs to be
+undone through a call to mipi_dsi_detach().
+
+Let's create a device-managed variant of the attachment function that
+will automatically detach the device at unbind.
+
+Reviewed-by: Andrzej Hajda <a.hajda@samsung.com>
+Signed-off-by: Maxime Ripard <maxime@cerno.tech>
+Link: https://patchwork.freedesktop.org/patch/msgid/20210910101218.1632297-5-maxime@cerno.tech
+Stable-dep-of: 941882a0e96d ("drm/bridge: lt8912b: Fix bridge_detach")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/gpu/drm/drm_mipi_dsi.c | 35 ++++++++++++++++++++++++++++++++++
+ include/drm/drm_mipi_dsi.h | 1 +
+ 2 files changed, 36 insertions(+)
+
+diff --git a/drivers/gpu/drm/drm_mipi_dsi.c b/drivers/gpu/drm/drm_mipi_dsi.c
+index bedbbfeab2a98..d98b08c65db93 100644
+--- a/drivers/gpu/drm/drm_mipi_dsi.c
++++ b/drivers/gpu/drm/drm_mipi_dsi.c
+@@ -392,6 +392,41 @@ int mipi_dsi_detach(struct mipi_dsi_device *dsi)
+ }
+ EXPORT_SYMBOL(mipi_dsi_detach);
+
++static void devm_mipi_dsi_detach(void *arg)
++{
++ struct mipi_dsi_device *dsi = arg;
++
++ mipi_dsi_detach(dsi);
++}
++
++/**
++ * devm_mipi_dsi_attach - Attach a MIPI-DSI device to its DSI Host
++ * @dev: device to tie the MIPI-DSI device attachment lifetime to
++ * @dsi: DSI peripheral
++ *
++ * This is the managed version of mipi_dsi_attach() which automatically
++ * calls mipi_dsi_detach() when @dev is unbound.
++ *
++ * Returns:
++ * 0 on success, a negative error code on failure.
++ */
++int devm_mipi_dsi_attach(struct device *dev,
++ struct mipi_dsi_device *dsi)
++{
++ int ret;
++
++ ret = mipi_dsi_attach(dsi);
++ if (ret)
++ return ret;
++
++ ret = devm_add_action_or_reset(dev, devm_mipi_dsi_detach, dsi);
++ if (ret)
++ return ret;
++
++ return 0;
++}
++EXPORT_SYMBOL_GPL(devm_mipi_dsi_attach);
++
+ static ssize_t mipi_dsi_device_transfer(struct mipi_dsi_device *dsi,
+ struct mipi_dsi_msg *msg)
+ {
+diff --git a/include/drm/drm_mipi_dsi.h b/include/drm/drm_mipi_dsi.h
+index 5105464052704..d9af72024d66d 100644
+--- a/include/drm/drm_mipi_dsi.h
++++ b/include/drm/drm_mipi_dsi.h
+@@ -233,6 +233,7 @@ devm_mipi_dsi_device_register_full(struct device *dev, struct mipi_dsi_host *hos
+ struct mipi_dsi_device *of_find_mipi_dsi_device_by_node(struct device_node *np);
+ int mipi_dsi_attach(struct mipi_dsi_device *dsi);
+ int mipi_dsi_detach(struct mipi_dsi_device *dsi);
++int devm_mipi_dsi_attach(struct device *dev, struct mipi_dsi_device *dsi);
+ int mipi_dsi_shutdown_peripheral(struct mipi_dsi_device *dsi);
+ int mipi_dsi_turn_on_peripheral(struct mipi_dsi_device *dsi);
+ int mipi_dsi_set_maximum_return_packet_size(struct mipi_dsi_device *dsi,
+--
+2.42.0
+
--- /dev/null
+From c3d566132ac0cbd3f5eec283f97b610e8a88fd11 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 10 Sep 2021 12:11:57 +0200
+Subject: drm/mipi-dsi: Create devm device registration
+
+From: Maxime Ripard <maxime@cerno.tech>
+
+[ Upstream commit a1419fb4a73e47f0eab2985dff594ed52397471b ]
+
+Devices that take their data through the MIPI-DSI bus but are controlled
+through a secondary bus like I2C have to register a secondary device on
+the MIPI-DSI bus through the mipi_dsi_device_register_full() function.
+
+At removal or when an error occurs, that device needs to be removed
+through a call to mipi_dsi_device_unregister().
+
+Let's create a device-managed variant of the registration function that
+will automatically unregister the device at unbind.
+
+Reviewed-by: Andrzej Hajda <a.hajda@samsung.com>
+Signed-off-by: Maxime Ripard <maxime@cerno.tech>
+Link: https://patchwork.freedesktop.org/patch/msgid/20210910101218.1632297-4-maxime@cerno.tech
+Stable-dep-of: 941882a0e96d ("drm/bridge: lt8912b: Fix bridge_detach")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/gpu/drm/drm_mipi_dsi.c | 46 ++++++++++++++++++++++++++++++++++
+ include/drm/drm_mipi_dsi.h | 3 +++
+ 2 files changed, 49 insertions(+)
+
+diff --git a/drivers/gpu/drm/drm_mipi_dsi.c b/drivers/gpu/drm/drm_mipi_dsi.c
+index 0c806e99e8690..bedbbfeab2a98 100644
+--- a/drivers/gpu/drm/drm_mipi_dsi.c
++++ b/drivers/gpu/drm/drm_mipi_dsi.c
+@@ -246,6 +246,52 @@ void mipi_dsi_device_unregister(struct mipi_dsi_device *dsi)
+ }
+ EXPORT_SYMBOL(mipi_dsi_device_unregister);
+
++static void devm_mipi_dsi_device_unregister(void *arg)
++{
++ struct mipi_dsi_device *dsi = arg;
++
++ mipi_dsi_device_unregister(dsi);
++}
++
++/**
++ * devm_mipi_dsi_device_register_full - create a managed MIPI DSI device
++ * @dev: device to tie the MIPI-DSI device lifetime to
++ * @host: DSI host to which this device is connected
++ * @info: pointer to template containing DSI device information
++ *
++ * Create a MIPI DSI device by using the device information provided by
++ * mipi_dsi_device_info template
++ *
++ * This is the managed version of mipi_dsi_device_register_full() which
++ * automatically calls mipi_dsi_device_unregister() when @dev is
++ * unbound.
++ *
++ * Returns:
++ * A pointer to the newly created MIPI DSI device, or, a pointer encoded
++ * with an error
++ */
++struct mipi_dsi_device *
++devm_mipi_dsi_device_register_full(struct device *dev,
++ struct mipi_dsi_host *host,
++ const struct mipi_dsi_device_info *info)
++{
++ struct mipi_dsi_device *dsi;
++ int ret;
++
++ dsi = mipi_dsi_device_register_full(host, info);
++ if (IS_ERR(dsi))
++ return dsi;
++
++ ret = devm_add_action_or_reset(dev,
++ devm_mipi_dsi_device_unregister,
++ dsi);
++ if (ret)
++ return ERR_PTR(ret);
++
++ return dsi;
++}
++EXPORT_SYMBOL_GPL(devm_mipi_dsi_device_register_full);
++
+ static DEFINE_MUTEX(host_lock);
+ static LIST_HEAD(host_list);
+
+diff --git a/include/drm/drm_mipi_dsi.h b/include/drm/drm_mipi_dsi.h
+index 1d263eb0b2e12..5105464052704 100644
+--- a/include/drm/drm_mipi_dsi.h
++++ b/include/drm/drm_mipi_dsi.h
+@@ -227,6 +227,9 @@ struct mipi_dsi_device *
+ mipi_dsi_device_register_full(struct mipi_dsi_host *host,
+ const struct mipi_dsi_device_info *info);
+ void mipi_dsi_device_unregister(struct mipi_dsi_device *dsi);
++struct mipi_dsi_device *
++devm_mipi_dsi_device_register_full(struct device *dev, struct mipi_dsi_host *host,
++ const struct mipi_dsi_device_info *info);
+ struct mipi_dsi_device *of_find_mipi_dsi_device_by_node(struct device_node *np);
+ int mipi_dsi_attach(struct mipi_dsi_device *dsi);
+ int mipi_dsi_detach(struct mipi_dsi_device *dsi);
+--
+2.42.0
+
--- /dev/null
+From 188d674b81875a5a1bcca02e0cbf34c92729e588 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 12 Oct 2023 04:29:08 +0300
+Subject: drm/msm/dsi: use msm_gem_kernel_put to free TX buffer
+
+From: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
+
+[ Upstream commit 69b321b2c3df4f7e51a9de587e41f324b0b717b0 ]
+
+Use exiting function to free the allocated GEM object instead of
+open-coding it. This has a bonus of internally calling
+msm_gem_put_vaddr() to compensate for msm_gem_get_vaddr() in
+msm_get_kernel_new().
+
+Fixes: 1e29dff00400 ("drm/msm: Add a common function to free kernel buffer objects")
+Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
+Reviewed-by: Abhinav Kumar <quic_abhinavk@quicinc.com>
+Patchwork: https://patchwork.freedesktop.org/patch/562239/
+Signed-off-by: Rob Clark <robdclark@chromium.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/gpu/drm/msm/dsi/dsi_host.c | 3 +--
+ 1 file changed, 1 insertion(+), 2 deletions(-)
+
+diff --git a/drivers/gpu/drm/msm/dsi/dsi_host.c b/drivers/gpu/drm/msm/dsi/dsi_host.c
+index 85dec6167e0b6..8d0612caf6c21 100644
+--- a/drivers/gpu/drm/msm/dsi/dsi_host.c
++++ b/drivers/gpu/drm/msm/dsi/dsi_host.c
+@@ -1154,8 +1154,7 @@ static void dsi_tx_buf_free(struct msm_dsi_host *msm_host)
+
+ priv = dev->dev_private;
+ if (msm_host->tx_gem_obj) {
+- msm_gem_unpin_iova(msm_host->tx_gem_obj, priv->kms->aspace);
+- drm_gem_object_put(msm_host->tx_gem_obj);
++ msm_gem_kernel_put(msm_host->tx_gem_obj, priv->kms->aspace);
+ msm_host->tx_gem_obj = NULL;
+ }
+
+--
+2.42.0
+
--- /dev/null
+From 065d07e8165b48868062d4d6e4c91bbe4597a9a0 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 17 Aug 2023 19:33:49 +0800
+Subject: drm/radeon: possible buffer overflow
+
+From: Konstantin Meskhidze <konstantin.meskhidze@huawei.com>
+
+[ Upstream commit dd05484f99d16715a88eedfca363828ef9a4c2d4 ]
+
+Buffer 'afmt_status' of size 6 could overflow, since index 'afmt_idx' is
+checked after access.
+
+Fixes: 5cc4e5fc293b ("drm/radeon: Cleanup HDMI audio interrupt handling for evergreen")
+Co-developed-by: Ivanov Mikhail <ivanov.mikhail1@huawei-partners.com>
+Signed-off-by: Konstantin Meskhidze <konstantin.meskhidze@huawei.com>
+Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/gpu/drm/radeon/evergreen.c | 7 ++++---
+ 1 file changed, 4 insertions(+), 3 deletions(-)
+
+diff --git a/drivers/gpu/drm/radeon/evergreen.c b/drivers/gpu/drm/radeon/evergreen.c
+index eeb590d2dec2e..e84596bb98f7a 100644
+--- a/drivers/gpu/drm/radeon/evergreen.c
++++ b/drivers/gpu/drm/radeon/evergreen.c
+@@ -4820,14 +4820,15 @@ int evergreen_irq_process(struct radeon_device *rdev)
+ break;
+ case 44: /* hdmi */
+ afmt_idx = src_data;
+- if (!(afmt_status[afmt_idx] & AFMT_AZ_FORMAT_WTRIG))
+- DRM_DEBUG("IH: IH event w/o asserted irq bit?\n");
+-
+ if (afmt_idx > 5) {
+ DRM_ERROR("Unhandled interrupt: %d %d\n",
+ src_id, src_data);
+ break;
+ }
++
++ if (!(afmt_status[afmt_idx] & AFMT_AZ_FORMAT_WTRIG))
++ DRM_DEBUG("IH: IH event w/o asserted irq bit?\n");
++
+ afmt_status[afmt_idx] &= ~AFMT_AZ_FORMAT_WTRIG;
+ queue_hdmi = true;
+ DRM_DEBUG("IH: HDMI%d\n", afmt_idx + 1);
+--
+2.42.0
+
--- /dev/null
+From e449edee866e355fc4c0bc4f3679fc4e526aac99 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sat, 2 Sep 2023 19:34:31 +0200
+Subject: drm/rockchip: cdn-dp: Fix some error handling paths in cdn_dp_probe()
+
+From: Christophe JAILLET <christophe.jaillet@wanadoo.fr>
+
+[ Upstream commit 44b968d0d0868b7a9b7a5c64464ada464ff4d532 ]
+
+cdn_dp_audio_codec_init() can fail. So add some error handling.
+
+If component_add() fails, the previous cdn_dp_audio_codec_init() call
+should be undone, as already done in the remove function.
+
+Fixes: 88582f564692 ("drm/rockchip: cdn-dp: Don't unregister audio dev when unbinding")
+Signed-off-by: Christophe JAILLET <christophe.jaillet@wanadoo.fr>
+Signed-off-by: Heiko Stuebner <heiko@sntech.de>
+Link: https://patchwork.freedesktop.org/patch/msgid/8494a41602fadb7439630921a9779640698f2f9f.1693676045.git.christophe.jaillet@wanadoo.fr
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/gpu/drm/rockchip/cdn-dp-core.c | 15 +++++++++++++--
+ 1 file changed, 13 insertions(+), 2 deletions(-)
+
+diff --git a/drivers/gpu/drm/rockchip/cdn-dp-core.c b/drivers/gpu/drm/rockchip/cdn-dp-core.c
+index 20e63cadec8c7..b9ef35a35c857 100644
+--- a/drivers/gpu/drm/rockchip/cdn-dp-core.c
++++ b/drivers/gpu/drm/rockchip/cdn-dp-core.c
+@@ -1146,6 +1146,7 @@ static int cdn_dp_probe(struct platform_device *pdev)
+ struct cdn_dp_device *dp;
+ struct extcon_dev *extcon;
+ struct phy *phy;
++ int ret;
+ int i;
+
+ dp = devm_kzalloc(dev, sizeof(*dp), GFP_KERNEL);
+@@ -1186,9 +1187,19 @@ static int cdn_dp_probe(struct platform_device *pdev)
+ mutex_init(&dp->lock);
+ dev_set_drvdata(dev, dp);
+
+- cdn_dp_audio_codec_init(dp, dev);
++ ret = cdn_dp_audio_codec_init(dp, dev);
++ if (ret)
++ return ret;
++
++ ret = component_add(dev, &cdn_dp_component_ops);
++ if (ret)
++ goto err_audio_deinit;
+
+- return component_add(dev, &cdn_dp_component_ops);
++ return 0;
++
++err_audio_deinit:
++ platform_device_unregister(dp->audio_pdev);
++ return ret;
+ }
+
+ static int cdn_dp_remove(struct platform_device *pdev)
+--
+2.42.0
+
--- /dev/null
+From 0636b7dca86cf5cfbceda917d3028d4ff66a952c Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 11 Oct 2023 11:01:48 +0300
+Subject: drm/rockchip: Fix type promotion bug in rockchip_gem_iommu_map()
+
+From: Dan Carpenter <dan.carpenter@linaro.org>
+
+[ Upstream commit 6471da5ee311d53ef46eebcb7725bc94266cc0cf ]
+
+The "ret" variable is declared as ssize_t and it can hold negative error
+codes but the "rk_obj->base.size" variable is type size_t. This means
+that when we compare them, they are both type promoted to size_t and the
+negative error code becomes a high unsigned value and is treated as
+success. Add a cast to fix this.
+
+Fixes: 38f993b7c59e ("drm/rockchip: Do not use DMA mapping API if attached to IOMMU domain")
+Signed-off-by: Dan Carpenter <dan.carpenter@linaro.org>
+Signed-off-by: Heiko Stuebner <heiko@sntech.de>
+Link: https://patchwork.freedesktop.org/patch/msgid/2bfa28b5-145d-4b9e-a18a-98819dd686ce@moroto.mountain
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/gpu/drm/rockchip/rockchip_drm_gem.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_gem.c b/drivers/gpu/drm/rockchip/rockchip_drm_gem.c
+index 3b18b6a7acd3e..bde358d8309c3 100644
+--- a/drivers/gpu/drm/rockchip/rockchip_drm_gem.c
++++ b/drivers/gpu/drm/rockchip/rockchip_drm_gem.c
+@@ -39,7 +39,7 @@ static int rockchip_gem_iommu_map(struct rockchip_gem_object *rk_obj)
+
+ ret = iommu_map_sgtable(private->domain, rk_obj->dma_addr, rk_obj->sgt,
+ prot);
+- if (ret < rk_obj->base.size) {
++ if (ret < (ssize_t)rk_obj->base.size) {
+ DRM_ERROR("failed to map buffer: size=%zd request_size=%zd\n",
+ ret, rk_obj->base.size);
+ ret = -ENOMEM;
+--
+2.42.0
+
--- /dev/null
+From e27ba74b2b93f483b670ff56b0e2c74eb16db249 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 21 Jun 2023 22:33:20 +0000
+Subject: drm/rockchip: vop: Fix call to crtc reset helper
+
+From: Jonas Karlman <jonas@kwiboo.se>
+
+[ Upstream commit 5aacd290837828c089a83ac9795c74c4c9e2c923 ]
+
+Allocation of crtc_state may fail in vop_crtc_reset, causing an invalid
+pointer to be passed to __drm_atomic_helper_crtc_reset.
+
+Fix this by adding a NULL check of crtc_state, similar to other drivers.
+
+Fixes: 01e2eaf40c9d ("drm/rockchip: Convert to using __drm_atomic_helper_crtc_reset() for reset.")
+Signed-off-by: Jonas Karlman <jonas@kwiboo.se>
+Reviewed-by: Sascha Hauer <s.hauer@pengutronix.de>
+Signed-off-by: Heiko Stuebner <heiko@sntech.de>
+Link: https://patchwork.freedesktop.org/patch/msgid/20230621223311.2239547-4-jonas@kwiboo.se
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/gpu/drm/rockchip/rockchip_drm_vop.c | 5 ++++-
+ 1 file changed, 4 insertions(+), 1 deletion(-)
+
+diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c
+index 4bb68c058422d..e53b1ecbd7bc0 100644
+--- a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c
++++ b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c
+@@ -1580,7 +1580,10 @@ static void vop_crtc_reset(struct drm_crtc *crtc)
+ if (crtc->state)
+ vop_crtc_destroy_state(crtc, crtc->state);
+
+- __drm_atomic_helper_crtc_reset(crtc, &crtc_state->base);
++ if (crtc_state)
++ __drm_atomic_helper_crtc_reset(crtc, &crtc_state->base);
++ else
++ __drm_atomic_helper_crtc_reset(crtc, NULL);
+ }
+
+ #ifdef CONFIG_DRM_ANALOGIX_DP
+--
+2.42.0
+
--- /dev/null
+From e3caefcd279b2e0e489933d3bf46e837aa650187 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 21 Jun 2023 22:33:17 +0000
+Subject: drm/rockchip: vop: Fix reset of state in duplicate state crtc funcs
+
+From: Jonas Karlman <jonas@kwiboo.se>
+
+[ Upstream commit 13fc28804bf10ca0b7bce3efbba95c534836d7ca ]
+
+struct rockchip_crtc_state members such as output_type, output_bpc and
+enable_afbc is always reset to zero in the atomic_duplicate_state crtc
+funcs.
+
+Fix this by using kmemdup on the subclass rockchip_crtc_state struct.
+
+Fixes: 4e257d9eee23 ("drm/rockchip: get rid of rockchip_drm_crtc_mode_config")
+Signed-off-by: Jonas Karlman <jonas@kwiboo.se>
+Reviewed-by: Sascha Hauer <s.hauer@pengutronix.de>
+Signed-off-by: Heiko Stuebner <heiko@sntech.de>
+Link: https://patchwork.freedesktop.org/patch/msgid/20230621223311.2239547-2-jonas@kwiboo.se
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/gpu/drm/rockchip/rockchip_drm_vop.c | 3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c
+index cfe13b203b891..4bb68c058422d 100644
+--- a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c
++++ b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c
+@@ -1554,7 +1554,8 @@ static struct drm_crtc_state *vop_crtc_duplicate_state(struct drm_crtc *crtc)
+ if (WARN_ON(!crtc->state))
+ return NULL;
+
+- rockchip_state = kzalloc(sizeof(*rockchip_state), GFP_KERNEL);
++ rockchip_state = kmemdup(to_rockchip_crtc_state(crtc->state),
++ sizeof(*rockchip_state), GFP_KERNEL);
+ if (!rockchip_state)
+ return NULL;
+
+--
+2.42.0
+
--- /dev/null
+From 42e0e3b8eaa789b7ac858238cfe15530b78587c7 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 6 Sep 2023 09:33:41 +0800
+Subject: ext4: move 'ix' sanity check to corrent position
+
+From: Gou Hao <gouhao@uniontech.com>
+
+[ Upstream commit af90a8f4a09ec4a3de20142e37f37205d4687f28 ]
+
+Check 'ix' before it is used.
+
+Fixes: 80e675f906db ("ext4: optimize memmmove lengths in extent/index insertions")
+Signed-off-by: Gou Hao <gouhao@uniontech.com>
+Link: https://lore.kernel.org/r/20230906013341.7199-1-gouhao@uniontech.com
+Signed-off-by: Theodore Ts'o <tytso@mit.edu>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ fs/ext4/extents.c | 10 +++++-----
+ 1 file changed, 5 insertions(+), 5 deletions(-)
+
+diff --git a/fs/ext4/extents.c b/fs/ext4/extents.c
+index 13497bd4e14bb..592be39e3d51f 100644
+--- a/fs/ext4/extents.c
++++ b/fs/ext4/extents.c
+@@ -1004,6 +1004,11 @@ static int ext4_ext_insert_index(handle_t *handle, struct inode *inode,
+ ix = curp->p_idx;
+ }
+
++ if (unlikely(ix > EXT_MAX_INDEX(curp->p_hdr))) {
++ EXT4_ERROR_INODE(inode, "ix > EXT_MAX_INDEX!");
++ return -EFSCORRUPTED;
++ }
++
+ len = EXT_LAST_INDEX(curp->p_hdr) - ix + 1;
+ BUG_ON(len < 0);
+ if (len > 0) {
+@@ -1013,11 +1018,6 @@ static int ext4_ext_insert_index(handle_t *handle, struct inode *inode,
+ memmove(ix + 1, ix, len * sizeof(struct ext4_extent_idx));
+ }
+
+- if (unlikely(ix > EXT_MAX_INDEX(curp->p_hdr))) {
+- EXT4_ERROR_INODE(inode, "ix > EXT_MAX_INDEX!");
+- return -EFSCORRUPTED;
+- }
+-
+ ix->ei_block = cpu_to_le32(logical);
+ ext4_idx_store_pblock(ix, ptr);
+ le16_add_cpu(&curp->p_hdr->eh_entries, 1);
+--
+2.42.0
+
--- /dev/null
+From 809b2204b7fe3fa4a5a481f30f7e10fad9e2a574 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 28 Aug 2023 22:04:17 +0800
+Subject: f2fs: compress: fix to avoid redundant compress extension
+
+From: Chao Yu <chao@kernel.org>
+
+[ Upstream commit 7e1b150fece033703a824df1bbc03df091ea53cc ]
+
+With below script, redundant compress extension will be parsed and added
+by parse_options(), because parse_options() doesn't check whether the
+extension is existed or not, fix it.
+
+1. mount -t f2fs -o compress_extension=so /dev/vdb /mnt/f2fs
+2. mount -t f2fs -o remount,compress_extension=so /mnt/f2fs
+3. mount|grep f2fs
+
+/dev/vdb on /mnt/f2fs type f2fs (...,compress_extension=so,compress_extension=so,...)
+
+Fixes: 4c8ff7095bef ("f2fs: support data compression")
+Fixes: 151b1982be5d ("f2fs: compress: add nocompress extensions support")
+Signed-off-by: Chao Yu <chao@kernel.org>
+Signed-off-by: Jaegeuk Kim <jaegeuk@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ fs/f2fs/super.c | 33 +++++++++++++++++++++++++++++++++
+ 1 file changed, 33 insertions(+)
+
+diff --git a/fs/f2fs/super.c b/fs/f2fs/super.c
+index 4b862e4a6a110..6823c09c32521 100644
+--- a/fs/f2fs/super.c
++++ b/fs/f2fs/super.c
+@@ -542,6 +542,29 @@ static int f2fs_set_test_dummy_encryption(struct super_block *sb,
+ }
+
+ #ifdef CONFIG_F2FS_FS_COMPRESSION
++static bool is_compress_extension_exist(struct f2fs_sb_info *sbi,
++ const char *new_ext, bool is_ext)
++{
++ unsigned char (*ext)[F2FS_EXTENSION_LEN];
++ int ext_cnt;
++ int i;
++
++ if (is_ext) {
++ ext = F2FS_OPTION(sbi).extensions;
++ ext_cnt = F2FS_OPTION(sbi).compress_ext_cnt;
++ } else {
++ ext = F2FS_OPTION(sbi).noextensions;
++ ext_cnt = F2FS_OPTION(sbi).nocompress_ext_cnt;
++ }
++
++ for (i = 0; i < ext_cnt; i++) {
++ if (!strcasecmp(new_ext, ext[i]))
++ return true;
++ }
++
++ return false;
++}
++
+ /*
+ * 1. The same extension name cannot not appear in both compress and non-compress extension
+ * at the same time.
+@@ -1156,6 +1179,11 @@ static int parse_options(struct super_block *sb, char *options, bool is_remount)
+ return -EINVAL;
+ }
+
++ if (is_compress_extension_exist(sbi, name, true)) {
++ kfree(name);
++ break;
++ }
++
+ strcpy(ext[ext_cnt], name);
+ F2FS_OPTION(sbi).compress_ext_cnt++;
+ kfree(name);
+@@ -1180,6 +1208,11 @@ static int parse_options(struct super_block *sb, char *options, bool is_remount)
+ return -EINVAL;
+ }
+
++ if (is_compress_extension_exist(sbi, name, false)) {
++ kfree(name);
++ break;
++ }
++
+ strcpy(noext[noext_cnt], name);
+ F2FS_OPTION(sbi).nocompress_ext_cnt++;
+ kfree(name);
+--
+2.42.0
+
--- /dev/null
+From 4b3f3e8a75fee21870255ec82c982863079b7e15 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 28 Aug 2023 22:04:15 +0800
+Subject: f2fs: compress: fix to avoid use-after-free on dic
+
+From: Chao Yu <chao@kernel.org>
+
+[ Upstream commit b0327c84e91a0f4f0abced8cb83ec86a7083f086 ]
+
+Call trace:
+ __memcpy+0x128/0x250
+ f2fs_read_multi_pages+0x940/0xf7c
+ f2fs_mpage_readpages+0x5a8/0x624
+ f2fs_readahead+0x5c/0x110
+ page_cache_ra_unbounded+0x1b8/0x590
+ do_sync_mmap_readahead+0x1dc/0x2e4
+ filemap_fault+0x254/0xa8c
+ f2fs_filemap_fault+0x2c/0x104
+ __do_fault+0x7c/0x238
+ do_handle_mm_fault+0x11bc/0x2d14
+ do_mem_abort+0x3a8/0x1004
+ el0_da+0x3c/0xa0
+ el0t_64_sync_handler+0xc4/0xec
+ el0t_64_sync+0x1b4/0x1b8
+
+In f2fs_read_multi_pages(), once f2fs_decompress_cluster() was called if
+we hit cached page in compress_inode's cache, dic may be released, it needs
+break the loop rather than continuing it, in order to avoid accessing
+invalid dic pointer.
+
+Fixes: 6ce19aff0b8c ("f2fs: compress: add compress_inode to cache compressed blocks")
+Signed-off-by: Chao Yu <chao@kernel.org>
+Signed-off-by: Jaegeuk Kim <jaegeuk@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ fs/f2fs/data.c | 4 +++-
+ 1 file changed, 3 insertions(+), 1 deletion(-)
+
+diff --git a/fs/f2fs/data.c b/fs/f2fs/data.c
+index 93c14dae4460a..7894a22c15993 100644
+--- a/fs/f2fs/data.c
++++ b/fs/f2fs/data.c
+@@ -2269,8 +2269,10 @@ int f2fs_read_multi_pages(struct compress_ctx *cc, struct bio **bio_ret,
+ f2fs_wait_on_block_writeback(inode, blkaddr);
+
+ if (f2fs_load_compressed_page(sbi, page, blkaddr)) {
+- if (atomic_dec_and_test(&dic->remaining_pages))
++ if (atomic_dec_and_test(&dic->remaining_pages)) {
+ f2fs_decompress_cluster(dic, true);
++ break;
++ }
+ continue;
+ }
+
+--
+2.42.0
+
--- /dev/null
+From 1ddef868efdb207edd5d4711d9ce2e07461e0bbc Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sat, 7 Oct 2023 15:45:52 +0800
+Subject: f2fs: fix to initialize map.m_pblk in f2fs_precache_extents()
+
+From: Chao Yu <chao@kernel.org>
+
+[ Upstream commit 8b07c1fb0f1ad139373c8253f2fad8bc43fab07d ]
+
+Otherwise, it may print random physical block address in tracepoint
+of f2fs_map_blocks() as below:
+
+f2fs_map_blocks: dev = (253,16), ino = 2297, file offset = 0, start blkaddr = 0xa356c421, len = 0x0, flags = 0
+
+Fixes: c4020b2da4c9 ("f2fs: support F2FS_IOC_PRECACHE_EXTENTS")
+Signed-off-by: Chao Yu <chao@kernel.org>
+Signed-off-by: Jaegeuk Kim <jaegeuk@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ fs/f2fs/file.c | 1 +
+ 1 file changed, 1 insertion(+)
+
+diff --git a/fs/f2fs/file.c b/fs/f2fs/file.c
+index e1131af0396b9..58fd32db025da 100644
+--- a/fs/f2fs/file.c
++++ b/fs/f2fs/file.c
+@@ -3210,6 +3210,7 @@ int f2fs_precache_extents(struct inode *inode)
+ return -EOPNOTSUPP;
+
+ map.m_lblk = 0;
++ map.m_pblk = 0;
+ map.m_next_pgofs = NULL;
+ map.m_next_extent = &m_next_extent;
+ map.m_seg_type = NO_CHECK_TYPE;
+--
+2.42.0
+
--- /dev/null
+From 219e7b6fea8ca67b3a430cdbb5b53a2e98a5bad7 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 2 Aug 2022 12:24:37 -0700
+Subject: f2fs: handle decompress only post processing in softirq
+
+From: Daeho Jeong <daehojeong@google.com>
+
+[ Upstream commit bff139b49d9f70c1ac5384aac94554846aa834de ]
+
+Now decompression is being handled in workqueue and it makes read I/O
+latency non-deterministic, because of the non-deterministic scheduling
+nature of workqueues. So, I made it handled in softirq context only if
+possible, not in low memory devices, since this modification will
+maintain decompresion related memory a little longer.
+
+Signed-off-by: Daeho Jeong <daehojeong@google.com>
+Reviewed-by: Chao Yu <chao@kernel.org>
+Signed-off-by: Jaegeuk Kim <jaegeuk@kernel.org>
+Stable-dep-of: b0327c84e91a ("f2fs: compress: fix to avoid use-after-free on dic")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ fs/f2fs/compress.c | 203 ++++++++++++++++++++++++++++++---------------
+ fs/f2fs/data.c | 52 ++++++++----
+ fs/f2fs/f2fs.h | 17 ++--
+ 3 files changed, 179 insertions(+), 93 deletions(-)
+
+diff --git a/fs/f2fs/compress.c b/fs/f2fs/compress.c
+index 455fac164fda0..3849252b1b06f 100644
+--- a/fs/f2fs/compress.c
++++ b/fs/f2fs/compress.c
+@@ -738,14 +738,19 @@ static int f2fs_compress_pages(struct compress_ctx *cc)
+ return ret;
+ }
+
+-void f2fs_decompress_cluster(struct decompress_io_ctx *dic)
++static int f2fs_prepare_decomp_mem(struct decompress_io_ctx *dic,
++ bool pre_alloc);
++static void f2fs_release_decomp_mem(struct decompress_io_ctx *dic,
++ bool bypass_destroy_callback, bool pre_alloc);
++
++void f2fs_decompress_cluster(struct decompress_io_ctx *dic, bool in_task)
+ {
+ struct f2fs_sb_info *sbi = F2FS_I_SB(dic->inode);
+ struct f2fs_inode_info *fi = F2FS_I(dic->inode);
+ const struct f2fs_compress_ops *cops =
+ f2fs_cops[fi->i_compress_algorithm];
++ bool bypass_callback = false;
+ int ret;
+- int i;
+
+ trace_f2fs_decompress_pages_start(dic->inode, dic->cluster_idx,
+ dic->cluster_size, fi->i_compress_algorithm);
+@@ -755,41 +760,10 @@ void f2fs_decompress_cluster(struct decompress_io_ctx *dic)
+ goto out_end_io;
+ }
+
+- dic->tpages = page_array_alloc(dic->inode, dic->cluster_size);
+- if (!dic->tpages) {
+- ret = -ENOMEM;
+- goto out_end_io;
+- }
+-
+- for (i = 0; i < dic->cluster_size; i++) {
+- if (dic->rpages[i]) {
+- dic->tpages[i] = dic->rpages[i];
+- continue;
+- }
+-
+- dic->tpages[i] = f2fs_compress_alloc_page();
+- if (!dic->tpages[i]) {
+- ret = -ENOMEM;
+- goto out_end_io;
+- }
+- }
+-
+- if (cops->init_decompress_ctx) {
+- ret = cops->init_decompress_ctx(dic);
+- if (ret)
+- goto out_end_io;
+- }
+-
+- dic->rbuf = f2fs_vmap(dic->tpages, dic->cluster_size);
+- if (!dic->rbuf) {
+- ret = -ENOMEM;
+- goto out_destroy_decompress_ctx;
+- }
+-
+- dic->cbuf = f2fs_vmap(dic->cpages, dic->nr_cpages);
+- if (!dic->cbuf) {
+- ret = -ENOMEM;
+- goto out_vunmap_rbuf;
++ ret = f2fs_prepare_decomp_mem(dic, false);
++ if (ret) {
++ bypass_callback = true;
++ goto out_release;
+ }
+
+ dic->clen = le32_to_cpu(dic->cbuf->clen);
+@@ -797,7 +771,7 @@ void f2fs_decompress_cluster(struct decompress_io_ctx *dic)
+
+ if (dic->clen > PAGE_SIZE * dic->nr_cpages - COMPRESS_HEADER_SIZE) {
+ ret = -EFSCORRUPTED;
+- goto out_vunmap_cbuf;
++ goto out_release;
+ }
+
+ ret = cops->decompress_pages(dic);
+@@ -818,17 +792,13 @@ void f2fs_decompress_cluster(struct decompress_io_ctx *dic)
+ }
+ }
+
+-out_vunmap_cbuf:
+- vm_unmap_ram(dic->cbuf, dic->nr_cpages);
+-out_vunmap_rbuf:
+- vm_unmap_ram(dic->rbuf, dic->cluster_size);
+-out_destroy_decompress_ctx:
+- if (cops->destroy_decompress_ctx)
+- cops->destroy_decompress_ctx(dic);
++out_release:
++ f2fs_release_decomp_mem(dic, bypass_callback, false);
++
+ out_end_io:
+ trace_f2fs_decompress_pages_end(dic->inode, dic->cluster_idx,
+ dic->clen, ret);
+- f2fs_decompress_end_io(dic, ret);
++ f2fs_decompress_end_io(dic, ret, in_task);
+ }
+
+ /*
+@@ -838,7 +808,7 @@ void f2fs_decompress_cluster(struct decompress_io_ctx *dic)
+ * (or in the case of a failure, cleans up without actually decompressing).
+ */
+ void f2fs_end_read_compressed_page(struct page *page, bool failed,
+- block_t blkaddr)
++ block_t blkaddr, bool in_task)
+ {
+ struct decompress_io_ctx *dic =
+ (struct decompress_io_ctx *)page_private(page);
+@@ -848,12 +818,12 @@ void f2fs_end_read_compressed_page(struct page *page, bool failed,
+
+ if (failed)
+ WRITE_ONCE(dic->failed, true);
+- else if (blkaddr)
++ else if (blkaddr && in_task)
+ f2fs_cache_compressed_page(sbi, page,
+ dic->inode->i_ino, blkaddr);
+
+ if (atomic_dec_and_test(&dic->remaining_pages))
+- f2fs_decompress_cluster(dic);
++ f2fs_decompress_cluster(dic, in_task);
+ }
+
+ static bool is_page_in_cluster(struct compress_ctx *cc, pgoff_t index)
+@@ -1552,16 +1522,85 @@ int f2fs_write_multi_pages(struct compress_ctx *cc,
+ return err;
+ }
+
+-static void f2fs_free_dic(struct decompress_io_ctx *dic);
++static inline bool allow_memalloc_for_decomp(struct f2fs_sb_info *sbi,
++ bool pre_alloc)
++{
++ return pre_alloc ^ f2fs_low_mem_mode(sbi);
++}
++
++static int f2fs_prepare_decomp_mem(struct decompress_io_ctx *dic,
++ bool pre_alloc)
++{
++ const struct f2fs_compress_ops *cops =
++ f2fs_cops[F2FS_I(dic->inode)->i_compress_algorithm];
++ int i;
++
++ if (!allow_memalloc_for_decomp(F2FS_I_SB(dic->inode), pre_alloc))
++ return 0;
++
++ dic->tpages = page_array_alloc(dic->inode, dic->cluster_size);
++ if (!dic->tpages)
++ return -ENOMEM;
++
++ for (i = 0; i < dic->cluster_size; i++) {
++ if (dic->rpages[i]) {
++ dic->tpages[i] = dic->rpages[i];
++ continue;
++ }
++
++ dic->tpages[i] = f2fs_compress_alloc_page();
++ if (!dic->tpages[i])
++ return -ENOMEM;
++ }
++
++ dic->rbuf = f2fs_vmap(dic->tpages, dic->cluster_size);
++ if (!dic->rbuf)
++ return -ENOMEM;
++
++ dic->cbuf = f2fs_vmap(dic->cpages, dic->nr_cpages);
++ if (!dic->cbuf)
++ return -ENOMEM;
++
++ if (cops->init_decompress_ctx) {
++ int ret = cops->init_decompress_ctx(dic);
++
++ if (ret)
++ return ret;
++ }
++
++ return 0;
++}
++
++static void f2fs_release_decomp_mem(struct decompress_io_ctx *dic,
++ bool bypass_destroy_callback, bool pre_alloc)
++{
++ const struct f2fs_compress_ops *cops =
++ f2fs_cops[F2FS_I(dic->inode)->i_compress_algorithm];
++
++ if (!allow_memalloc_for_decomp(F2FS_I_SB(dic->inode), pre_alloc))
++ return;
++
++ if (!bypass_destroy_callback && cops->destroy_decompress_ctx)
++ cops->destroy_decompress_ctx(dic);
++
++ if (dic->cbuf)
++ vm_unmap_ram(dic->cbuf, dic->nr_cpages);
++
++ if (dic->rbuf)
++ vm_unmap_ram(dic->rbuf, dic->cluster_size);
++}
++
++static void f2fs_free_dic(struct decompress_io_ctx *dic,
++ bool bypass_destroy_callback);
+
+ struct decompress_io_ctx *f2fs_alloc_dic(struct compress_ctx *cc)
+ {
+ struct decompress_io_ctx *dic;
+ pgoff_t start_idx = start_idx_of_cluster(cc);
+- int i;
++ struct f2fs_sb_info *sbi = F2FS_I_SB(cc->inode);
++ int i, ret;
+
+- dic = f2fs_kmem_cache_alloc(dic_entry_slab, GFP_F2FS_ZERO,
+- false, F2FS_I_SB(cc->inode));
++ dic = f2fs_kmem_cache_alloc(dic_entry_slab, GFP_F2FS_ZERO, false, sbi);
+ if (!dic)
+ return ERR_PTR(-ENOMEM);
+
+@@ -1587,32 +1626,43 @@ struct decompress_io_ctx *f2fs_alloc_dic(struct compress_ctx *cc)
+ dic->nr_rpages = cc->cluster_size;
+
+ dic->cpages = page_array_alloc(dic->inode, dic->nr_cpages);
+- if (!dic->cpages)
++ if (!dic->cpages) {
++ ret = -ENOMEM;
+ goto out_free;
++ }
+
+ for (i = 0; i < dic->nr_cpages; i++) {
+ struct page *page;
+
+ page = f2fs_compress_alloc_page();
+- if (!page)
++ if (!page) {
++ ret = -ENOMEM;
+ goto out_free;
++ }
+
+ f2fs_set_compressed_page(page, cc->inode,
+ start_idx + i + 1, dic);
+ dic->cpages[i] = page;
+ }
+
++ ret = f2fs_prepare_decomp_mem(dic, true);
++ if (ret)
++ goto out_free;
++
+ return dic;
+
+ out_free:
+- f2fs_free_dic(dic);
+- return ERR_PTR(-ENOMEM);
++ f2fs_free_dic(dic, true);
++ return ERR_PTR(ret);
+ }
+
+-static void f2fs_free_dic(struct decompress_io_ctx *dic)
++static void f2fs_free_dic(struct decompress_io_ctx *dic,
++ bool bypass_destroy_callback)
+ {
+ int i;
+
++ f2fs_release_decomp_mem(dic, bypass_destroy_callback, true);
++
+ if (dic->tpages) {
+ for (i = 0; i < dic->cluster_size; i++) {
+ if (dic->rpages[i])
+@@ -1637,17 +1687,33 @@ static void f2fs_free_dic(struct decompress_io_ctx *dic)
+ kmem_cache_free(dic_entry_slab, dic);
+ }
+
+-static void f2fs_put_dic(struct decompress_io_ctx *dic)
++static void f2fs_late_free_dic(struct work_struct *work)
++{
++ struct decompress_io_ctx *dic =
++ container_of(work, struct decompress_io_ctx, free_work);
++
++ f2fs_free_dic(dic, false);
++}
++
++static void f2fs_put_dic(struct decompress_io_ctx *dic, bool in_task)
+ {
+- if (refcount_dec_and_test(&dic->refcnt))
+- f2fs_free_dic(dic);
++ if (refcount_dec_and_test(&dic->refcnt)) {
++ if (in_task) {
++ f2fs_free_dic(dic, false);
++ } else {
++ INIT_WORK(&dic->free_work, f2fs_late_free_dic);
++ queue_work(F2FS_I_SB(dic->inode)->post_read_wq,
++ &dic->free_work);
++ }
++ }
+ }
+
+ /*
+ * Update and unlock the cluster's pagecache pages, and release the reference to
+ * the decompress_io_ctx that was being held for I/O completion.
+ */
+-static void __f2fs_decompress_end_io(struct decompress_io_ctx *dic, bool failed)
++static void __f2fs_decompress_end_io(struct decompress_io_ctx *dic, bool failed,
++ bool in_task)
+ {
+ int i;
+
+@@ -1668,7 +1734,7 @@ static void __f2fs_decompress_end_io(struct decompress_io_ctx *dic, bool failed)
+ unlock_page(rpage);
+ }
+
+- f2fs_put_dic(dic);
++ f2fs_put_dic(dic, in_task);
+ }
+
+ static void f2fs_verify_cluster(struct work_struct *work)
+@@ -1685,14 +1751,15 @@ static void f2fs_verify_cluster(struct work_struct *work)
+ SetPageError(rpage);
+ }
+
+- __f2fs_decompress_end_io(dic, false);
++ __f2fs_decompress_end_io(dic, false, true);
+ }
+
+ /*
+ * This is called when a compressed cluster has been decompressed
+ * (or failed to be read and/or decompressed).
+ */
+-void f2fs_decompress_end_io(struct decompress_io_ctx *dic, bool failed)
++void f2fs_decompress_end_io(struct decompress_io_ctx *dic, bool failed,
++ bool in_task)
+ {
+ if (!failed && dic->need_verity) {
+ /*
+@@ -1704,7 +1771,7 @@ void f2fs_decompress_end_io(struct decompress_io_ctx *dic, bool failed)
+ INIT_WORK(&dic->verity_work, f2fs_verify_cluster);
+ fsverity_enqueue_verify_work(&dic->verity_work);
+ } else {
+- __f2fs_decompress_end_io(dic, failed);
++ __f2fs_decompress_end_io(dic, failed, in_task);
+ }
+ }
+
+@@ -1713,12 +1780,12 @@ void f2fs_decompress_end_io(struct decompress_io_ctx *dic, bool failed)
+ *
+ * This is called when the page is no longer needed and can be freed.
+ */
+-void f2fs_put_page_dic(struct page *page)
++void f2fs_put_page_dic(struct page *page, bool in_task)
+ {
+ struct decompress_io_ctx *dic =
+ (struct decompress_io_ctx *)page_private(page);
+
+- f2fs_put_dic(dic);
++ f2fs_put_dic(dic, in_task);
+ }
+
+ /*
+diff --git a/fs/f2fs/data.c b/fs/f2fs/data.c
+index 3956852ad1de0..93c14dae4460a 100644
+--- a/fs/f2fs/data.c
++++ b/fs/f2fs/data.c
+@@ -120,7 +120,7 @@ struct bio_post_read_ctx {
+ block_t fs_blkaddr;
+ };
+
+-static void f2fs_finish_read_bio(struct bio *bio)
++static void f2fs_finish_read_bio(struct bio *bio, bool in_task)
+ {
+ struct bio_vec *bv;
+ struct bvec_iter_all iter_all;
+@@ -134,8 +134,9 @@ static void f2fs_finish_read_bio(struct bio *bio)
+
+ if (f2fs_is_compressed_page(page)) {
+ if (bio->bi_status)
+- f2fs_end_read_compressed_page(page, true, 0);
+- f2fs_put_page_dic(page);
++ f2fs_end_read_compressed_page(page, true, 0,
++ in_task);
++ f2fs_put_page_dic(page, in_task);
+ continue;
+ }
+
+@@ -192,7 +193,7 @@ static void f2fs_verify_bio(struct work_struct *work)
+ fsverity_verify_bio(bio);
+ }
+
+- f2fs_finish_read_bio(bio);
++ f2fs_finish_read_bio(bio, true);
+ }
+
+ /*
+@@ -204,7 +205,7 @@ static void f2fs_verify_bio(struct work_struct *work)
+ * can involve reading verity metadata pages from the file, and these verity
+ * metadata pages may be encrypted and/or compressed.
+ */
+-static void f2fs_verify_and_finish_bio(struct bio *bio)
++static void f2fs_verify_and_finish_bio(struct bio *bio, bool in_task)
+ {
+ struct bio_post_read_ctx *ctx = bio->bi_private;
+
+@@ -212,7 +213,7 @@ static void f2fs_verify_and_finish_bio(struct bio *bio)
+ INIT_WORK(&ctx->work, f2fs_verify_bio);
+ fsverity_enqueue_verify_work(&ctx->work);
+ } else {
+- f2fs_finish_read_bio(bio);
++ f2fs_finish_read_bio(bio, in_task);
+ }
+ }
+
+@@ -225,7 +226,8 @@ static void f2fs_verify_and_finish_bio(struct bio *bio)
+ * that the bio includes at least one compressed page. The actual decompression
+ * is done on a per-cluster basis, not a per-bio basis.
+ */
+-static void f2fs_handle_step_decompress(struct bio_post_read_ctx *ctx)
++static void f2fs_handle_step_decompress(struct bio_post_read_ctx *ctx,
++ bool in_task)
+ {
+ struct bio_vec *bv;
+ struct bvec_iter_all iter_all;
+@@ -238,7 +240,7 @@ static void f2fs_handle_step_decompress(struct bio_post_read_ctx *ctx)
+ /* PG_error was set if decryption failed. */
+ if (f2fs_is_compressed_page(page))
+ f2fs_end_read_compressed_page(page, PageError(page),
+- blkaddr);
++ blkaddr, in_task);
+ else
+ all_compressed = false;
+
+@@ -263,15 +265,16 @@ static void f2fs_post_read_work(struct work_struct *work)
+ fscrypt_decrypt_bio(ctx->bio);
+
+ if (ctx->enabled_steps & STEP_DECOMPRESS)
+- f2fs_handle_step_decompress(ctx);
++ f2fs_handle_step_decompress(ctx, true);
+
+- f2fs_verify_and_finish_bio(ctx->bio);
++ f2fs_verify_and_finish_bio(ctx->bio, true);
+ }
+
+ static void f2fs_read_end_io(struct bio *bio)
+ {
+ struct f2fs_sb_info *sbi = F2FS_P_SB(bio_first_page_all(bio));
+ struct bio_post_read_ctx *ctx;
++ bool intask = in_task();
+
+ iostat_update_and_unbind_ctx(bio, 0);
+ ctx = bio->bi_private;
+@@ -282,16 +285,29 @@ static void f2fs_read_end_io(struct bio *bio)
+ }
+
+ if (bio->bi_status) {
+- f2fs_finish_read_bio(bio);
++ f2fs_finish_read_bio(bio, intask);
+ return;
+ }
+
+- if (ctx && (ctx->enabled_steps & (STEP_DECRYPT | STEP_DECOMPRESS))) {
+- INIT_WORK(&ctx->work, f2fs_post_read_work);
+- queue_work(ctx->sbi->post_read_wq, &ctx->work);
+- } else {
+- f2fs_verify_and_finish_bio(bio);
++ if (ctx) {
++ unsigned int enabled_steps = ctx->enabled_steps &
++ (STEP_DECRYPT | STEP_DECOMPRESS);
++
++ /*
++ * If we have only decompression step between decompression and
++ * decrypt, we don't need post processing for this.
++ */
++ if (enabled_steps == STEP_DECOMPRESS &&
++ !f2fs_low_mem_mode(sbi)) {
++ f2fs_handle_step_decompress(ctx, intask);
++ } else if (enabled_steps) {
++ INIT_WORK(&ctx->work, f2fs_post_read_work);
++ queue_work(ctx->sbi->post_read_wq, &ctx->work);
++ return;
++ }
+ }
++
++ f2fs_verify_and_finish_bio(bio, intask);
+ }
+
+ static void f2fs_write_end_io(struct bio *bio)
+@@ -2254,7 +2270,7 @@ int f2fs_read_multi_pages(struct compress_ctx *cc, struct bio **bio_ret,
+
+ if (f2fs_load_compressed_page(sbi, page, blkaddr)) {
+ if (atomic_dec_and_test(&dic->remaining_pages))
+- f2fs_decompress_cluster(dic);
++ f2fs_decompress_cluster(dic, true);
+ continue;
+ }
+
+@@ -2272,7 +2288,7 @@ int f2fs_read_multi_pages(struct compress_ctx *cc, struct bio **bio_ret,
+ page->index, for_write);
+ if (IS_ERR(bio)) {
+ ret = PTR_ERR(bio);
+- f2fs_decompress_end_io(dic, ret);
++ f2fs_decompress_end_io(dic, ret, true);
+ f2fs_put_dnode(&dn);
+ *bio_ret = NULL;
+ return ret;
+diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h
+index fb53a35f31b04..1f6b735edc4d5 100644
+--- a/fs/f2fs/f2fs.h
++++ b/fs/f2fs/f2fs.h
+@@ -1557,6 +1557,7 @@ struct decompress_io_ctx {
+ void *private; /* payload buffer for specified decompression algorithm */
+ void *private2; /* extra payload buffer */
+ struct work_struct verity_work; /* work to verify the decompressed pages */
++ struct work_struct free_work; /* work for late free this structure itself */
+ };
+
+ #define NULL_CLUSTER ((unsigned int)(~0))
+@@ -4058,9 +4059,9 @@ void f2fs_compress_write_end_io(struct bio *bio, struct page *page);
+ bool f2fs_is_compress_backend_ready(struct inode *inode);
+ int f2fs_init_compress_mempool(void);
+ void f2fs_destroy_compress_mempool(void);
+-void f2fs_decompress_cluster(struct decompress_io_ctx *dic);
++void f2fs_decompress_cluster(struct decompress_io_ctx *dic, bool in_task);
+ void f2fs_end_read_compressed_page(struct page *page, bool failed,
+- block_t blkaddr);
++ block_t blkaddr, bool in_task);
+ bool f2fs_cluster_is_empty(struct compress_ctx *cc);
+ bool f2fs_cluster_can_merge_page(struct compress_ctx *cc, pgoff_t index);
+ bool f2fs_sanity_check_cluster(struct dnode_of_data *dn);
+@@ -4077,8 +4078,9 @@ int f2fs_read_multi_pages(struct compress_ctx *cc, struct bio **bio_ret,
+ unsigned nr_pages, sector_t *last_block_in_bio,
+ bool is_readahead, bool for_write);
+ struct decompress_io_ctx *f2fs_alloc_dic(struct compress_ctx *cc);
+-void f2fs_decompress_end_io(struct decompress_io_ctx *dic, bool failed);
+-void f2fs_put_page_dic(struct page *page);
++void f2fs_decompress_end_io(struct decompress_io_ctx *dic, bool failed,
++ bool in_task);
++void f2fs_put_page_dic(struct page *page, bool in_task);
+ unsigned int f2fs_cluster_blocks_are_contiguous(struct dnode_of_data *dn);
+ int f2fs_init_compress_ctx(struct compress_ctx *cc);
+ void f2fs_destroy_compress_ctx(struct compress_ctx *cc, bool reuse);
+@@ -4124,13 +4126,14 @@ static inline struct page *f2fs_compress_control_page(struct page *page)
+ }
+ static inline int f2fs_init_compress_mempool(void) { return 0; }
+ static inline void f2fs_destroy_compress_mempool(void) { }
+-static inline void f2fs_decompress_cluster(struct decompress_io_ctx *dic) { }
++static inline void f2fs_decompress_cluster(struct decompress_io_ctx *dic,
++ bool in_task) { }
+ static inline void f2fs_end_read_compressed_page(struct page *page,
+- bool failed, block_t blkaddr)
++ bool failed, block_t blkaddr, bool in_task)
+ {
+ WARN_ON_ONCE(1);
+ }
+-static inline void f2fs_put_page_dic(struct page *page)
++static inline void f2fs_put_page_dic(struct page *page, bool in_task)
+ {
+ WARN_ON_ONCE(1);
+ }
+--
+2.42.0
+
--- /dev/null
+From c9b88216941edab0e607dea249f4d4d0df4776c3 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 20 Jun 2022 10:38:42 -0700
+Subject: f2fs: introduce memory mode
+
+From: Daeho Jeong <daehojeong@google.com>
+
+[ Upstream commit 7a8fc586180d8c57db5cc1e2acb32bb9986f642b ]
+
+Introduce memory mode to supports "normal" and "low" memory modes.
+"low" mode is to support low memory devices. Because of the nature of
+low memory devices, in this mode, f2fs will try to save memory sometimes
+by sacrificing performance. "normal" mode is the default mode and same
+as before.
+
+Signed-off-by: Daeho Jeong <daehojeong@google.com>
+Reviewed-by: Chao Yu <chao@kernel.org>
+Signed-off-by: Jaegeuk Kim <jaegeuk@kernel.org>
+Stable-dep-of: b0327c84e91a ("f2fs: compress: fix to avoid use-after-free on dic")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ Documentation/filesystems/f2fs.rst | 5 +++++
+ fs/f2fs/f2fs.h | 13 +++++++++++++
+ fs/f2fs/super.c | 24 ++++++++++++++++++++++++
+ 3 files changed, 42 insertions(+)
+
+diff --git a/Documentation/filesystems/f2fs.rst b/Documentation/filesystems/f2fs.rst
+index 7fe50b0bccde9..415bba41597c3 100644
+--- a/Documentation/filesystems/f2fs.rst
++++ b/Documentation/filesystems/f2fs.rst
+@@ -323,6 +323,11 @@ discard_unit=%s Control discard unit, the argument can be "block", "segment"
+ default, it is helpful for large sized SMR or ZNS devices to
+ reduce memory cost by getting rid of fs metadata supports small
+ discard.
++memory=%s Control memory mode. This supports "normal" and "low" modes.
++ "low" mode is introduced to support low memory devices.
++ Because of the nature of low memory devices, in this mode, f2fs
++ will try to save memory sometimes by sacrificing performance.
++ "normal" mode is the default mode and same as before.
+ ======================== ============================================================
+
+ Debugfs Entries
+diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h
+index 835ef98643bd4..fb53a35f31b04 100644
+--- a/fs/f2fs/f2fs.h
++++ b/fs/f2fs/f2fs.h
+@@ -142,6 +142,7 @@ struct f2fs_mount_info {
+ int fsync_mode; /* fsync policy */
+ int fs_mode; /* fs mode: LFS or ADAPTIVE */
+ int bggc_mode; /* bggc mode: off, on or sync */
++ int memory_mode; /* memory mode */
+ int discard_unit; /*
+ * discard command's offset/size should
+ * be aligned to this unit: block,
+@@ -1330,6 +1331,13 @@ enum {
+ DISCARD_UNIT_SECTION, /* basic discard unit is section */
+ };
+
++enum {
++ MEMORY_MODE_NORMAL, /* memory mode for normal devices */
++ MEMORY_MODE_LOW, /* memory mode for low memry devices */
++};
++
++
++
+ static inline int f2fs_test_bit(unsigned int nr, char *addr);
+ static inline void f2fs_set_bit(unsigned int nr, char *addr);
+ static inline void f2fs_clear_bit(unsigned int nr, char *addr);
+@@ -4294,6 +4302,11 @@ static inline bool f2fs_lfs_mode(struct f2fs_sb_info *sbi)
+ return F2FS_OPTION(sbi).fs_mode == FS_MODE_LFS;
+ }
+
++static inline bool f2fs_low_mem_mode(struct f2fs_sb_info *sbi)
++{
++ return F2FS_OPTION(sbi).memory_mode == MEMORY_MODE_LOW;
++}
++
+ static inline bool f2fs_may_compress(struct inode *inode)
+ {
+ if (IS_SWAPFILE(inode) || f2fs_is_pinned_file(inode) ||
+diff --git a/fs/f2fs/super.c b/fs/f2fs/super.c
+index 5c0b2b300aa1b..4b862e4a6a110 100644
+--- a/fs/f2fs/super.c
++++ b/fs/f2fs/super.c
+@@ -159,6 +159,7 @@ enum {
+ Opt_gc_merge,
+ Opt_nogc_merge,
+ Opt_discard_unit,
++ Opt_memory_mode,
+ Opt_err,
+ };
+
+@@ -236,6 +237,7 @@ static match_table_t f2fs_tokens = {
+ {Opt_gc_merge, "gc_merge"},
+ {Opt_nogc_merge, "nogc_merge"},
+ {Opt_discard_unit, "discard_unit=%s"},
++ {Opt_memory_mode, "memory=%s"},
+ {Opt_err, NULL},
+ };
+
+@@ -1241,6 +1243,22 @@ static int parse_options(struct super_block *sb, char *options, bool is_remount)
+ }
+ kfree(name);
+ break;
++ case Opt_memory_mode:
++ name = match_strdup(&args[0]);
++ if (!name)
++ return -ENOMEM;
++ if (!strcmp(name, "normal")) {
++ F2FS_OPTION(sbi).memory_mode =
++ MEMORY_MODE_NORMAL;
++ } else if (!strcmp(name, "low")) {
++ F2FS_OPTION(sbi).memory_mode =
++ MEMORY_MODE_LOW;
++ } else {
++ kfree(name);
++ return -EINVAL;
++ }
++ kfree(name);
++ break;
+ default:
+ f2fs_err(sbi, "Unrecognized mount option \"%s\" or missing value",
+ p);
+@@ -2012,6 +2030,11 @@ static int f2fs_show_options(struct seq_file *seq, struct dentry *root)
+ else if (F2FS_OPTION(sbi).discard_unit == DISCARD_UNIT_SECTION)
+ seq_printf(seq, ",discard_unit=%s", "section");
+
++ if (F2FS_OPTION(sbi).memory_mode == MEMORY_MODE_NORMAL)
++ seq_printf(seq, ",memory=%s", "normal");
++ else if (F2FS_OPTION(sbi).memory_mode == MEMORY_MODE_LOW)
++ seq_printf(seq, ",memory=%s", "low");
++
+ return 0;
+ }
+
+@@ -2034,6 +2057,7 @@ static void default_options(struct f2fs_sb_info *sbi)
+ F2FS_OPTION(sbi).compress_ext_cnt = 0;
+ F2FS_OPTION(sbi).compress_mode = COMPR_MODE_FS;
+ F2FS_OPTION(sbi).bggc_mode = BGGC_MODE_ON;
++ F2FS_OPTION(sbi).memory_mode = MEMORY_MODE_NORMAL;
+
+ sbi->sb->s_flags &= ~SB_INLINECRYPT;
+
+--
+2.42.0
+
--- /dev/null
+From b9b6b78ff78fa1b883a3dda105c6ee1e6649b7a7 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 3 Oct 2023 09:59:32 +0100
+Subject: firmware: arm_ffa: Assign the missing IDR allocation ID to the FFA
+ device
+
+From: Sudeep Holla <sudeep.holla@arm.com>
+
+[ Upstream commit 7d0bc6360f17ea323ab25939a34857123d7d87e5 ]
+
+Commit 19b8766459c4 ("firmware: arm_ffa: Fix FFA device names for logical
+partitions") added an ID to the FFA device using ida_alloc() and append
+the same to "arm-ffa" to make up a unique device name. However it missed
+to stash the id value in ffa_dev to help freeing the ID later when the
+device is destroyed.
+
+Due to the missing/unassigned ID in FFA device, we get the following
+warning when the FF-A device is unregistered.
+
+ | ida_free called for id=0 which is not allocated.
+ | WARNING: CPU: 7 PID: 1 at lib/idr.c:525 ida_free+0x114/0x164
+ | CPU: 7 PID: 1 Comm: swapper/0 Not tainted 6.6.0-rc4 #209
+ | pstate: 61400009 (nZCv daif +PAN -UAO -TCO +DIT -SSBS BTYPE=--)
+ | pc : ida_free+0x114/0x164
+ | lr : ida_free+0x114/0x164
+ | Call trace:
+ | ida_free+0x114/0x164
+ | ffa_release_device+0x24/0x3c
+ | device_release+0x34/0x8c
+ | kobject_put+0x94/0xf8
+ | put_device+0x18/0x24
+ | klist_devices_put+0x14/0x20
+ | klist_next+0xc8/0x114
+ | bus_for_each_dev+0xd8/0x144
+ | arm_ffa_bus_exit+0x30/0x54
+ | ffa_init+0x68/0x330
+ | do_one_initcall+0xdc/0x250
+ | do_initcall_level+0x8c/0xac
+ | do_initcalls+0x54/0x94
+ | do_basic_setup+0x1c/0x28
+ | kernel_init_freeable+0x104/0x170
+ | kernel_init+0x20/0x1a0
+ | ret_from_fork+0x10/0x20
+
+Fix the same by actually assigning the ID in the FFA device this time
+for real.
+
+Fixes: 19b8766459c4 ("firmware: arm_ffa: Fix FFA device names for logical partitions")
+Link: https://lore.kernel.org/r/20231003085932.3553985-1-sudeep.holla@arm.com
+Signed-off-by: Sudeep Holla <sudeep.holla@arm.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/firmware/arm_ffa/bus.c | 1 +
+ 1 file changed, 1 insertion(+)
+
+diff --git a/drivers/firmware/arm_ffa/bus.c b/drivers/firmware/arm_ffa/bus.c
+index edef31c413123..f79ba6f733ba4 100644
+--- a/drivers/firmware/arm_ffa/bus.c
++++ b/drivers/firmware/arm_ffa/bus.c
+@@ -192,6 +192,7 @@ struct ffa_device *ffa_device_register(const uuid_t *uuid, int vm_id)
+ dev->release = ffa_release_device;
+ dev_set_name(&ffa_dev->dev, "arm-ffa-%d", id);
+
++ ffa_dev->id = id;
+ ffa_dev->vm_id = vm_id;
+ uuid_copy(&ffa_dev->uuid, uuid);
+
+--
+2.42.0
+
--- /dev/null
+From ca7ed6d47f7a09b28aa7b5cd0d0d4ab41c04591f Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 21 Sep 2023 14:40:26 +0530
+Subject: firmware: ti_sci: Mark driver as non removable
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Dhruva Gole <d-gole@ti.com>
+
+[ Upstream commit 7b7a224b1ba1703583b25a3641ad9798f34d832a ]
+
+The TI-SCI message protocol provides a way to communicate between
+various compute processors with a central system controller entity. It
+provides the fundamental device management capability and clock control
+in the SOCs that it's used in.
+
+The remove function failed to do all the necessary cleanup if
+there are registered users. Some things are freed however which
+likely results in an oops later on.
+
+Ensure that the driver isn't unbound by suppressing its bind and unbind
+sysfs attributes. As the driver is built-in there is no way to remove
+device once bound.
+
+We can also remove the ti_sci_remove call along with the
+ti_sci_debugfs_destroy as there are no callers for it any longer.
+
+Fixes: aa276781a64a ("firmware: Add basic support for TI System Control Interface (TI-SCI) protocol")
+Reported-by: Uwe Kleine-König <u.kleine-koenig@pengutronix.de>
+Closes: https://lore.kernel.org/linux-arm-kernel/20230216083908.mvmydic5lpi3ogo7@pengutronix.de/
+Suggested-by: Uwe Kleine-König <u.kleine-koenig@pengutronix.de>
+Acked-by: Uwe Kleine-König <u.kleine-koenig@pengutronix.de>
+Signed-off-by: Dhruva Gole <d-gole@ti.com>
+Link: https://lore.kernel.org/r/20230921091025.133130-1-d-gole@ti.com
+Signed-off-by: Nishanth Menon <nm@ti.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/firmware/ti_sci.c | 46 +--------------------------------------
+ 1 file changed, 1 insertion(+), 45 deletions(-)
+
+diff --git a/drivers/firmware/ti_sci.c b/drivers/firmware/ti_sci.c
+index 235c7e7869aa7..c2fafe49c2e85 100644
+--- a/drivers/firmware/ti_sci.c
++++ b/drivers/firmware/ti_sci.c
+@@ -190,19 +190,6 @@ static int ti_sci_debugfs_create(struct platform_device *pdev,
+ return 0;
+ }
+
+-/**
+- * ti_sci_debugfs_destroy() - clean up log debug file
+- * @pdev: platform device pointer
+- * @info: Pointer to SCI entity information
+- */
+-static void ti_sci_debugfs_destroy(struct platform_device *pdev,
+- struct ti_sci_info *info)
+-{
+- if (IS_ERR(info->debug_region))
+- return;
+-
+- debugfs_remove(info->d);
+-}
+ #else /* CONFIG_DEBUG_FS */
+ static inline int ti_sci_debugfs_create(struct platform_device *dev,
+ struct ti_sci_info *info)
+@@ -3435,43 +3422,12 @@ static int ti_sci_probe(struct platform_device *pdev)
+ return ret;
+ }
+
+-static int ti_sci_remove(struct platform_device *pdev)
+-{
+- struct ti_sci_info *info;
+- struct device *dev = &pdev->dev;
+- int ret = 0;
+-
+- of_platform_depopulate(dev);
+-
+- info = platform_get_drvdata(pdev);
+-
+- if (info->nb.notifier_call)
+- unregister_restart_handler(&info->nb);
+-
+- mutex_lock(&ti_sci_list_mutex);
+- if (info->users)
+- ret = -EBUSY;
+- else
+- list_del(&info->node);
+- mutex_unlock(&ti_sci_list_mutex);
+-
+- if (!ret) {
+- ti_sci_debugfs_destroy(pdev, info);
+-
+- /* Safe to free channels since no more users */
+- mbox_free_channel(info->chan_tx);
+- mbox_free_channel(info->chan_rx);
+- }
+-
+- return ret;
+-}
+-
+ static struct platform_driver ti_sci_driver = {
+ .probe = ti_sci_probe,
+- .remove = ti_sci_remove,
+ .driver = {
+ .name = "ti-sci",
+ .of_match_table = of_match_ptr(ti_sci_of_match),
++ .suppress_bind_attrs = true,
+ },
+ };
+ module_platform_driver(ti_sci_driver);
+--
+2.42.0
+
--- /dev/null
+From 4301f30ac42a567a4911a36ab8318851b5868d00 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 19 Oct 2023 16:45:49 -0400
+Subject: futex: Don't include process MM in futex key on no-MMU
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Ben Wolsieffer <ben.wolsieffer@hefring.com>
+
+[ Upstream commit c73801ae4f22b390228ebf471d55668e824198b6 ]
+
+On no-MMU, all futexes are treated as private because there is no need
+to map a virtual address to physical to match the futex across
+processes. This doesn't quite work though, because private futexes
+include the current process's mm_struct as part of their key. This makes
+it impossible for one process to wake up a shared futex being waited on
+in another process.
+
+Fix this bug by excluding the mm_struct from the key. With
+a single address space, the futex address is already a unique key.
+
+Fixes: 784bdf3bb694 ("futex: Assume all mappings are private on !MMU systems")
+Signed-off-by: Ben Wolsieffer <ben.wolsieffer@hefring.com>
+Signed-off-by: Ingo Molnar <mingo@kernel.org>
+Acked-by: Peter Zijlstra <peterz@infradead.org>
+Cc: Thomas Gleixner <tglx@linutronix.de>
+Cc: Darren Hart <dvhart@infradead.org>
+Cc: Davidlohr Bueso <dave@stgolabs.net>
+Cc: André Almeida <andrealmeid@igalia.com>
+Link: https://lore.kernel.org/r/20231019204548.1236437-2-ben.wolsieffer@hefring.com
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ kernel/futex/core.c | 12 +++++++++++-
+ 1 file changed, 11 insertions(+), 1 deletion(-)
+
+diff --git a/kernel/futex/core.c b/kernel/futex/core.c
+index 764e73622b386..d42245170a7a0 100644
+--- a/kernel/futex/core.c
++++ b/kernel/futex/core.c
+@@ -570,7 +570,17 @@ static int get_futex_key(u32 __user *uaddr, bool fshared, union futex_key *key,
+ * but access_ok() should be faster than find_vma()
+ */
+ if (!fshared) {
+- key->private.mm = mm;
++ /*
++ * On no-MMU, shared futexes are treated as private, therefore
++ * we must not include the current process in the key. Since
++ * there is only one address space, the address is a unique key
++ * on its own.
++ */
++ if (IS_ENABLED(CONFIG_MMU))
++ key->private.mm = mm;
++ else
++ key->private.mm = NULL;
++
+ key->private.address = address;
+ return 0;
+ }
+--
+2.42.0
+
--- /dev/null
+From 6c60c61136951810bd21dc1124499ead1d83f2e5 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 20 Oct 2023 15:25:22 +0800
+Subject: genirq/matrix: Exclude managed interrupts in irq_matrix_allocated()
+
+From: Chen Yu <yu.c.chen@intel.com>
+
+[ Upstream commit a0b0bad10587ae2948a7c36ca4ffc206007fbcf3 ]
+
+When a CPU is about to be offlined, x86 validates that all active
+interrupts which are targeted to this CPU can be migrated to the remaining
+online CPUs. If not, the offline operation is aborted.
+
+The validation uses irq_matrix_allocated() to retrieve the number of
+vectors which are allocated on the outgoing CPU. The returned number of
+allocated vectors includes also vectors which are associated to managed
+interrupts.
+
+That's overaccounting because managed interrupts are:
+
+ - not migrated when the affinity mask of the interrupt targets only
+ the outgoing CPU
+
+ - migrated to another CPU, but in that case the vector is already
+ pre-allocated on the potential target CPUs and must not be taken into
+ account.
+
+As a consequence the check whether the remaining online CPUs have enough
+capacity for migrating the allocated vectors from the outgoing CPU might
+fail incorrectly.
+
+Let irq_matrix_allocated() return only the number of allocated non-managed
+interrupts to make this validation check correct.
+
+[ tglx: Amend changelog and fixup kernel-doc comment ]
+
+Fixes: 2f75d9e1c905 ("genirq: Implement bitmap matrix allocator")
+Reported-by: Wendy Wang <wendy.wang@intel.com>
+Signed-off-by: Chen Yu <yu.c.chen@intel.com>
+Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
+Link: https://lore.kernel.org/r/20231020072522.557846-1-yu.c.chen@intel.com
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ kernel/irq/matrix.c | 6 +++---
+ 1 file changed, 3 insertions(+), 3 deletions(-)
+
+diff --git a/kernel/irq/matrix.c b/kernel/irq/matrix.c
+index bbfb26489aa1c..f9467637eab65 100644
+--- a/kernel/irq/matrix.c
++++ b/kernel/irq/matrix.c
+@@ -466,16 +466,16 @@ unsigned int irq_matrix_reserved(struct irq_matrix *m)
+ }
+
+ /**
+- * irq_matrix_allocated - Get the number of allocated irqs on the local cpu
++ * irq_matrix_allocated - Get the number of allocated non-managed irqs on the local CPU
+ * @m: Pointer to the matrix to search
+ *
+- * This returns number of allocated irqs
++ * This returns number of allocated non-managed interrupts.
+ */
+ unsigned int irq_matrix_allocated(struct irq_matrix *m)
+ {
+ struct cpumap *cm = this_cpu_ptr(m->maps);
+
+- return cm->allocated;
++ return cm->allocated - cm->managed_allocated;
+ }
+
+ #ifdef CONFIG_GENERIC_IRQ_DEBUGFS
+--
+2.42.0
+
--- /dev/null
+From 0043afef0d43ad2bc0e3da4bc8d4b7abc4f87a19 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 19 Apr 2022 15:18:39 +0100
+Subject: gpio: Add helpers to ease the transition towards immutable irq_chip
+
+From: Marc Zyngier <maz@kernel.org>
+
+[ Upstream commit 36b78aae4bfee749bbde73be570796bfd0f56bec ]
+
+Add a couple of new helpers to make it slightly simpler to convert
+drivers to immutable irq_chip structures:
+
+- GPIOCHIP_IRQ_RESOURCE_HELPERS populates the irq_chip structure
+ with the resource management callbacks
+
+- gpio_irq_chip_set_chip() populates the gpio_irq_chip.chip
+ structure, avoiding the proliferation of ugly casts
+
+Reviewed-by: Andy Shevchenko <andy.shevchenko@gmail.com>
+Reviewed-by: Bartosz Golaszewski <brgl@bgdev.pl>
+Signed-off-by: Marc Zyngier <maz@kernel.org>
+Link: https://lore.kernel.org/r/20220419141846.598305-4-maz@kernel.org
+Stable-dep-of: dc3115e6c5d9 ("hid: cp2112: Fix IRQ shutdown stopping polling for all IRQs on chip")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ include/linux/gpio/driver.h | 12 ++++++++++++
+ 1 file changed, 12 insertions(+)
+
+diff --git a/include/linux/gpio/driver.h b/include/linux/gpio/driver.h
+index b241fc23ff3a2..91f60d1e3eb31 100644
+--- a/include/linux/gpio/driver.h
++++ b/include/linux/gpio/driver.h
+@@ -599,6 +599,18 @@ void gpiochip_enable_irq(struct gpio_chip *gc, unsigned int offset);
+ int gpiochip_irq_reqres(struct irq_data *data);
+ void gpiochip_irq_relres(struct irq_data *data);
+
++/* Paste this in your irq_chip structure */
++#define GPIOCHIP_IRQ_RESOURCE_HELPERS \
++ .irq_request_resources = gpiochip_irq_reqres, \
++ .irq_release_resources = gpiochip_irq_relres
++
++static inline void gpio_irq_chip_set_chip(struct gpio_irq_chip *girq,
++ const struct irq_chip *chip)
++{
++ /* Yes, dropping const is ugly, but it isn't like we have a choice */
++ girq->chip = (struct irq_chip *)chip;
++}
++
+ /* Line status inquiry for drivers */
+ bool gpiochip_line_is_open_drain(struct gpio_chip *gc, unsigned int offset);
+ bool gpiochip_line_is_open_source(struct gpio_chip *gc, unsigned int offset);
+--
+2.42.0
+
--- /dev/null
+From 67223eb1b98579c9464871d1938a5924fe06e220 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 19 Apr 2022 15:18:37 +0100
+Subject: gpio: Don't fiddle with irqchips marked as immutable
+
+From: Marc Zyngier <maz@kernel.org>
+
+[ Upstream commit 6c846d026d490b2383d395bc8e7b06336219667b ]
+
+In order to move away from gpiolib messing with the internals of
+unsuspecting irqchips, add a flag by which irqchips advertise
+that they are not to be messed with, and do solemnly swear that
+they correctly call into the gpiolib helpers when required.
+
+Also nudge the users into converting their drivers to the
+new model.
+
+Reviewed-by: Andy Shevchenko <andy.shevchenko@gmail.com>
+Reviewed-by: Bartosz Golaszewski <brgl@bgdev.pl>
+Signed-off-by: Marc Zyngier <maz@kernel.org>
+Link: https://lore.kernel.org/r/20220419141846.598305-2-maz@kernel.org
+Stable-dep-of: dc3115e6c5d9 ("hid: cp2112: Fix IRQ shutdown stopping polling for all IRQs on chip")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/gpio/gpiolib.c | 7 ++++++-
+ include/linux/irq.h | 2 ++
+ kernel/irq/debugfs.c | 1 +
+ 3 files changed, 9 insertions(+), 1 deletion(-)
+
+diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c
+index f9fdd117c654c..e572c30a202ad 100644
+--- a/drivers/gpio/gpiolib.c
++++ b/drivers/gpio/gpiolib.c
+@@ -1483,6 +1483,11 @@ static void gpiochip_set_irq_hooks(struct gpio_chip *gc)
+ {
+ struct irq_chip *irqchip = gc->irq.chip;
+
++ if (irqchip->flags & IRQCHIP_IMMUTABLE)
++ return;
++
++ chip_warn(gc, "not an immutable chip, please consider fixing it!\n");
++
+ if (!irqchip->irq_request_resources &&
+ !irqchip->irq_release_resources) {
+ irqchip->irq_request_resources = gpiochip_irq_reqres;
+@@ -1650,7 +1655,7 @@ static void gpiochip_irqchip_remove(struct gpio_chip *gc)
+ irq_domain_remove(gc->irq.domain);
+ }
+
+- if (irqchip) {
++ if (irqchip && !(irqchip->flags & IRQCHIP_IMMUTABLE)) {
+ if (irqchip->irq_request_resources == gpiochip_irq_reqres) {
+ irqchip->irq_request_resources = NULL;
+ irqchip->irq_release_resources = NULL;
+diff --git a/include/linux/irq.h b/include/linux/irq.h
+index f9e6449fbbbae..296ef3b7d7afa 100644
+--- a/include/linux/irq.h
++++ b/include/linux/irq.h
+@@ -570,6 +570,7 @@ struct irq_chip {
+ * IRQCHIP_ENABLE_WAKEUP_ON_SUSPEND: Invokes __enable_irq()/__disable_irq() for wake irqs
+ * in the suspend path if they are in disabled state
+ * IRQCHIP_AFFINITY_PRE_STARTUP: Default affinity update before startup
++ * IRQCHIP_IMMUTABLE: Don't ever change anything in this chip
+ */
+ enum {
+ IRQCHIP_SET_TYPE_MASKED = (1 << 0),
+@@ -583,6 +584,7 @@ enum {
+ IRQCHIP_SUPPORTS_NMI = (1 << 8),
+ IRQCHIP_ENABLE_WAKEUP_ON_SUSPEND = (1 << 9),
+ IRQCHIP_AFFINITY_PRE_STARTUP = (1 << 10),
++ IRQCHIP_IMMUTABLE = (1 << 11),
+ };
+
+ #include <linux/irqdesc.h>
+diff --git a/kernel/irq/debugfs.c b/kernel/irq/debugfs.c
+index e4cff358b437e..7ff52d94b42c0 100644
+--- a/kernel/irq/debugfs.c
++++ b/kernel/irq/debugfs.c
+@@ -58,6 +58,7 @@ static const struct irq_bit_descr irqchip_flags[] = {
+ BIT_MASK_DESCR(IRQCHIP_SUPPORTS_LEVEL_MSI),
+ BIT_MASK_DESCR(IRQCHIP_SUPPORTS_NMI),
+ BIT_MASK_DESCR(IRQCHIP_ENABLE_WAKEUP_ON_SUSPEND),
++ BIT_MASK_DESCR(IRQCHIP_IMMUTABLE),
+ };
+
+ static void
+--
+2.42.0
+
--- /dev/null
+From bf522c0ca975b2c9887f891c4124f72f6e7c7b27 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 19 Apr 2022 15:18:38 +0100
+Subject: gpio: Expose the gpiochip_irq_re[ql]res helpers
+
+From: Marc Zyngier <maz@kernel.org>
+
+[ Upstream commit 704f08753b6dcd0e08c1953af0b2c7f3fac87111 ]
+
+The GPIO subsystem has a couple of internal helpers to manage
+resources on behalf of the irqchip. Expose them so that GPIO
+drivers can use them directly.
+
+Reviewed-by: Andy Shevchenko <andy.shevchenko@gmail.com>
+Reviewed-by: Bartosz Golaszewski <brgl@bgdev.pl>
+Signed-off-by: Marc Zyngier <maz@kernel.org>
+Link: https://lore.kernel.org/r/20220419141846.598305-3-maz@kernel.org
+Stable-dep-of: dc3115e6c5d9 ("hid: cp2112: Fix IRQ shutdown stopping polling for all IRQs on chip")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/gpio/gpiolib.c | 6 ++++--
+ include/linux/gpio/driver.h | 4 ++++
+ 2 files changed, 8 insertions(+), 2 deletions(-)
+
+diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c
+index e572c30a202ad..57e726d65904b 100644
+--- a/drivers/gpio/gpiolib.c
++++ b/drivers/gpio/gpiolib.c
+@@ -1431,19 +1431,21 @@ static int gpiochip_to_irq(struct gpio_chip *gc, unsigned int offset)
+ return irq_create_mapping(domain, offset);
+ }
+
+-static int gpiochip_irq_reqres(struct irq_data *d)
++int gpiochip_irq_reqres(struct irq_data *d)
+ {
+ struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
+
+ return gpiochip_reqres_irq(gc, d->hwirq);
+ }
++EXPORT_SYMBOL(gpiochip_irq_reqres);
+
+-static void gpiochip_irq_relres(struct irq_data *d)
++void gpiochip_irq_relres(struct irq_data *d)
+ {
+ struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
+
+ gpiochip_relres_irq(gc, d->hwirq);
+ }
++EXPORT_SYMBOL(gpiochip_irq_relres);
+
+ static void gpiochip_irq_mask(struct irq_data *d)
+ {
+diff --git a/include/linux/gpio/driver.h b/include/linux/gpio/driver.h
+index 65df2ce96f0b1..b241fc23ff3a2 100644
+--- a/include/linux/gpio/driver.h
++++ b/include/linux/gpio/driver.h
+@@ -595,6 +595,10 @@ void gpiochip_relres_irq(struct gpio_chip *gc, unsigned int offset);
+ void gpiochip_disable_irq(struct gpio_chip *gc, unsigned int offset);
+ void gpiochip_enable_irq(struct gpio_chip *gc, unsigned int offset);
+
++/* irq_data versions of the above */
++int gpiochip_irq_reqres(struct irq_data *data);
++void gpiochip_irq_relres(struct irq_data *data);
++
+ /* Line status inquiry for drivers */
+ bool gpiochip_line_is_open_drain(struct gpio_chip *gc, unsigned int offset);
+ bool gpiochip_line_is_open_source(struct gpio_chip *gc, unsigned int offset);
+--
+2.42.0
+
--- /dev/null
+From 0471a02340208d9d614db6fadd193daadaa4b742 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 15 Sep 2023 12:17:49 -0600
+Subject: gve: Use size_add() in call to struct_size()
+
+From: Gustavo A. R. Silva <gustavoars@kernel.org>
+
+[ Upstream commit d692873cbe861a870cdc9cbfb120eefd113c3dfd ]
+
+If, for any reason, `tx_stats_num + rx_stats_num` wraps around, the
+protection that struct_size() adds against potential integer overflows
+is defeated. Fix this by hardening call to struct_size() with size_add().
+
+Fixes: 691f4077d560 ("gve: Replace zero-length array with flexible-array member")
+Signed-off-by: Gustavo A. R. Silva <gustavoars@kernel.org>
+Reviewed-by: Kees Cook <keescook@chromium.org>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/ethernet/google/gve/gve_main.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/drivers/net/ethernet/google/gve/gve_main.c b/drivers/net/ethernet/google/gve/gve_main.c
+index c0ea1b185e1bd..4327d66878976 100644
+--- a/drivers/net/ethernet/google/gve/gve_main.c
++++ b/drivers/net/ethernet/google/gve/gve_main.c
+@@ -139,7 +139,7 @@ static int gve_alloc_stats_report(struct gve_priv *priv)
+ rx_stats_num = (GVE_RX_STATS_REPORT_NUM + NIC_RX_STATS_REPORT_NUM) *
+ priv->rx_cfg.num_queues;
+ priv->stats_report_len = struct_size(priv->stats_report, stats,
+- tx_stats_num + rx_stats_num);
++ size_add(tx_stats_num, rx_stats_num));
+ priv->stats_report =
+ dma_alloc_coherent(&priv->pdev->dev, priv->stats_report_len,
+ &priv->stats_report_bus, GFP_KERNEL);
+--
+2.42.0
+
--- /dev/null
+From de9f97b2e2f67cccc8e942bfc7652a4206f8a2fd Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 19 Sep 2023 16:22:45 -0500
+Subject: hid: cp2112: Fix duplicate workqueue initialization
+
+From: Danny Kaehn <danny.kaehn@plexus.com>
+
+[ Upstream commit e3c2d2d144c082dd71596953193adf9891491f42 ]
+
+Previously the cp2112 driver called INIT_DELAYED_WORK within
+cp2112_gpio_irq_startup, resulting in duplicate initilizations of the
+workqueue on subsequent IRQ startups following an initial request. This
+resulted in a warning in set_work_data in workqueue.c, as well as a rare
+NULL dereference within process_one_work in workqueue.c.
+
+Initialize the workqueue within _probe instead.
+
+Fixes: 13de9cca514e ("HID: cp2112: add IRQ chip handling")
+Signed-off-by: Danny Kaehn <danny.kaehn@plexus.com>
+Signed-off-by: Jiri Kosina <jkosina@suse.cz>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/hid/hid-cp2112.c | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/drivers/hid/hid-cp2112.c b/drivers/hid/hid-cp2112.c
+index d902fe43cb818..a683d38200267 100644
+--- a/drivers/hid/hid-cp2112.c
++++ b/drivers/hid/hid-cp2112.c
+@@ -1157,8 +1157,6 @@ static unsigned int cp2112_gpio_irq_startup(struct irq_data *d)
+ struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
+ struct cp2112_device *dev = gpiochip_get_data(gc);
+
+- INIT_DELAYED_WORK(&dev->gpio_poll_worker, cp2112_gpio_poll_callback);
+-
+ if (!dev->gpio_poll) {
+ dev->gpio_poll = true;
+ schedule_delayed_work(&dev->gpio_poll_worker, 0);
+@@ -1354,6 +1352,8 @@ static int cp2112_probe(struct hid_device *hdev, const struct hid_device_id *id)
+ girq->handler = handle_simple_irq;
+ girq->threaded = true;
+
++ INIT_DELAYED_WORK(&dev->gpio_poll_worker, cp2112_gpio_poll_callback);
++
+ ret = gpiochip_add_data(&dev->gc, dev);
+ if (ret < 0) {
+ hid_err(hdev, "error registering gpio chip\n");
+--
+2.42.0
+
--- /dev/null
+From 71e783cfea753e5f37131882afbd29500d1d365e Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 11 Oct 2023 13:23:17 -0500
+Subject: hid: cp2112: Fix IRQ shutdown stopping polling for all IRQs on chip
+
+From: Danny Kaehn <danny.kaehn@plexus.com>
+
+[ Upstream commit dc3115e6c5d9863ec1a9ff1acf004ede93c34361 ]
+
+Previously cp2112_gpio_irq_shutdown() always cancelled the
+gpio_poll_worker, even if other IRQs were still active, and did not set
+the gpio_poll flag to false. This resulted in any call to _shutdown()
+resulting in interrupts no longer functioning on the chip until a
+_remove() occurred (a.e. the cp2112 is unplugged or system rebooted).
+
+Only cancel polling if all IRQs are disabled/masked, and correctly set
+the gpio_poll flag, allowing polling to restart when an interrupt is
+next enabled.
+
+Signed-off-by: Danny Kaehn <danny.kaehn@plexus.com>
+Fixes: 13de9cca514e ("HID: cp2112: add IRQ chip handling")
+Link: https://lore.kernel.org/r/20231011182317.1053344-1-danny.kaehn@plexus.com
+Signed-off-by: Benjamin Tissoires <bentiss@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/hid/hid-cp2112.c | 6 +++++-
+ 1 file changed, 5 insertions(+), 1 deletion(-)
+
+diff --git a/drivers/hid/hid-cp2112.c b/drivers/hid/hid-cp2112.c
+index 704aebb1a588f..ee983ddc7fd03 100644
+--- a/drivers/hid/hid-cp2112.c
++++ b/drivers/hid/hid-cp2112.c
+@@ -1175,7 +1175,11 @@ static void cp2112_gpio_irq_shutdown(struct irq_data *d)
+ struct cp2112_device *dev = gpiochip_get_data(gc);
+
+ cp2112_gpio_irq_mask(d);
+- cancel_delayed_work_sync(&dev->gpio_poll_worker);
++
++ if (!dev->irq_mask) {
++ dev->gpio_poll = false;
++ cancel_delayed_work_sync(&dev->gpio_poll_worker);
++ }
+ }
+
+ static int cp2112_gpio_irq_type(struct irq_data *d, unsigned int type)
+--
+2.42.0
+
--- /dev/null
+From 197afd0c04462b3f50de1aa00415135c7dc26f77 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 3 Jul 2023 21:52:13 +0300
+Subject: HID: cp2112: Make irq_chip immutable
+
+From: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
+
+[ Upstream commit 3e2977c425ad2789ca18084fff913cceacae75a2 ]
+
+Since recently, the kernel is nagging about mutable irq_chips:
+
+ "not an immutable chip, please consider fixing it!"
+
+Drop the unneeded copy, flag it as IRQCHIP_IMMUTABLE, add the new
+helper functions and call the appropriate gpiolib functions.
+
+Signed-off-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
+Link: https://lore.kernel.org/r/20230703185222.50554-4-andriy.shevchenko@linux.intel.com
+Signed-off-by: Benjamin Tissoires <bentiss@kernel.org>
+Stable-dep-of: dc3115e6c5d9 ("hid: cp2112: Fix IRQ shutdown stopping polling for all IRQs on chip")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/hid/hid-cp2112.c | 33 ++++++++++++++++++++-------------
+ 1 file changed, 20 insertions(+), 13 deletions(-)
+
+diff --git a/drivers/hid/hid-cp2112.c b/drivers/hid/hid-cp2112.c
+index a683d38200267..704aebb1a588f 100644
+--- a/drivers/hid/hid-cp2112.c
++++ b/drivers/hid/hid-cp2112.c
+@@ -161,7 +161,6 @@ struct cp2112_device {
+ atomic_t read_avail;
+ atomic_t xfer_avail;
+ struct gpio_chip gc;
+- struct irq_chip irq;
+ u8 *in_out_buffer;
+ struct mutex lock;
+
+@@ -1078,16 +1077,20 @@ static void cp2112_gpio_irq_mask(struct irq_data *d)
+ {
+ struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
+ struct cp2112_device *dev = gpiochip_get_data(gc);
++ irq_hw_number_t hwirq = irqd_to_hwirq(d);
+
+- __clear_bit(d->hwirq, &dev->irq_mask);
++ __clear_bit(hwirq, &dev->irq_mask);
++ gpiochip_disable_irq(gc, hwirq);
+ }
+
+ static void cp2112_gpio_irq_unmask(struct irq_data *d)
+ {
+ struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
+ struct cp2112_device *dev = gpiochip_get_data(gc);
++ irq_hw_number_t hwirq = irqd_to_hwirq(d);
+
+- __set_bit(d->hwirq, &dev->irq_mask);
++ gpiochip_enable_irq(gc, hwirq);
++ __set_bit(hwirq, &dev->irq_mask);
+ }
+
+ static void cp2112_gpio_poll_callback(struct work_struct *work)
+@@ -1171,6 +1174,7 @@ static void cp2112_gpio_irq_shutdown(struct irq_data *d)
+ struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
+ struct cp2112_device *dev = gpiochip_get_data(gc);
+
++ cp2112_gpio_irq_mask(d);
+ cancel_delayed_work_sync(&dev->gpio_poll_worker);
+ }
+
+@@ -1224,6 +1228,18 @@ static int __maybe_unused cp2112_allocate_irq(struct cp2112_device *dev,
+ return ret;
+ }
+
++static const struct irq_chip cp2112_gpio_irqchip = {
++ .name = "cp2112-gpio",
++ .irq_startup = cp2112_gpio_irq_startup,
++ .irq_shutdown = cp2112_gpio_irq_shutdown,
++ .irq_ack = cp2112_gpio_irq_ack,
++ .irq_mask = cp2112_gpio_irq_mask,
++ .irq_unmask = cp2112_gpio_irq_unmask,
++ .irq_set_type = cp2112_gpio_irq_type,
++ .flags = IRQCHIP_MASK_ON_SUSPEND | IRQCHIP_IMMUTABLE,
++ GPIOCHIP_IRQ_RESOURCE_HELPERS,
++};
++
+ static int cp2112_probe(struct hid_device *hdev, const struct hid_device_id *id)
+ {
+ struct cp2112_device *dev;
+@@ -1333,17 +1349,8 @@ static int cp2112_probe(struct hid_device *hdev, const struct hid_device_id *id)
+ dev->gc.can_sleep = 1;
+ dev->gc.parent = &hdev->dev;
+
+- dev->irq.name = "cp2112-gpio";
+- dev->irq.irq_startup = cp2112_gpio_irq_startup;
+- dev->irq.irq_shutdown = cp2112_gpio_irq_shutdown;
+- dev->irq.irq_ack = cp2112_gpio_irq_ack;
+- dev->irq.irq_mask = cp2112_gpio_irq_mask;
+- dev->irq.irq_unmask = cp2112_gpio_irq_unmask;
+- dev->irq.irq_set_type = cp2112_gpio_irq_type;
+- dev->irq.flags = IRQCHIP_MASK_ON_SUSPEND;
+-
+ girq = &dev->gc.irq;
+- girq->chip = &dev->irq;
++ gpio_irq_chip_set_chip(girq, &cp2112_gpio_irqchip);
+ /* The event comes from the outside so no parent handler */
+ girq->parent_handler = NULL;
+ girq->num_parents = 0;
+--
+2.42.0
+
--- /dev/null
+From e320737df23de27f8e34d4a963b88d45934b31b3 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 10 Oct 2023 12:20:18 +0200
+Subject: HID: logitech-hidpp: Don't restart IO, instead defer hid_connect()
+ only
+
+From: Hans de Goede <hdegoede@redhat.com>
+
+[ Upstream commit 11ca0322a41920df2b462d2e45b0731e47ff475b ]
+
+Restarting IO causes 2 problems:
+
+1. Some devices do not like IO being restarted this was addressed in
+ commit 498ba2069035 ("HID: logitech-hidpp: Don't restart communication
+ if not necessary"), but that change has issues of its own and needs to
+ be reverted.
+
+2. Restarting IO and specifically calling hid_device_io_stop() causes
+ received packets to be missed, which may cause connect-events to
+ get missed.
+
+Restarting IO was introduced in commit 91cf9a98ae41 ("HID: logitech-hidpp:
+make .probe usbhid capable") to allow to retrieve the device's name and
+serial number and store these in hdev->name and hdev->uniq before
+connecting any hid subdrivers (hid-input, hidraw) exporting this info
+to userspace.
+
+But this does not require restarting IO, this merely requires deferring
+calling hid_connect(). Calling hid_hw_start() with a connect-mask of
+0 makes it skip calling hid_connect(), so hidpp_probe() can simply call
+hid_connect() later without needing to restart IO.
+
+Remove the stop + restart of IO and instead just call hid_connect() later
+to avoid the issues caused by restarting IO.
+
+Now that IO is no longer stopped, hid_hw_close() must be called at the end
+of probe() to balance the hid_hw_open() done at the beginning probe().
+
+This series has been tested on the following devices:
+Logitech Bluetooth Laser Travel Mouse (bluetooth, HID++ 1.0)
+Logitech M720 Triathlon (bluetooth, HID++ 4.5)
+Logitech M720 Triathlon (unifying, HID++ 4.5)
+Logitech K400 Pro (unifying, HID++ 4.1)
+Logitech K270 (eQUAD nano Lite, HID++ 2.0)
+Logitech M185 (eQUAD nano Lite, HID++ 4.5)
+Logitech LX501 keyboard (27 Mhz, HID++ builtin scroll-wheel, HID++ 1.0)
+Logitech M-RAZ105 mouse (27 Mhz, HID++ extra mouse buttons, HID++ 1.0)
+
+And by bentiss:
+Logitech Touchpad T650 (unifying)
+Logitech Touchpad T651 (bluetooth)
+Logitech MX Master 3B (BLE)
+Logitech G403 (plain USB / Gaming receiver)
+
+Fixes: 498ba2069035 ("HID: logitech-hidpp: Don't restart communication if not necessary")
+Suggested-by: Benjamin Tissoires <bentiss@kernel.org>
+Signed-off-by: Hans de Goede <hdegoede@redhat.com>
+Link: https://lore.kernel.org/r/20231010102029.111003-2-hdegoede@redhat.com
+Signed-off-by: Benjamin Tissoires <bentiss@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/hid/hid-logitech-hidpp.c | 22 ++++++++++++----------
+ 1 file changed, 12 insertions(+), 10 deletions(-)
+
+diff --git a/drivers/hid/hid-logitech-hidpp.c b/drivers/hid/hid-logitech-hidpp.c
+index a716c6f3bfb58..907f45dfef4c1 100644
+--- a/drivers/hid/hid-logitech-hidpp.c
++++ b/drivers/hid/hid-logitech-hidpp.c
+@@ -4155,8 +4155,10 @@ static int hidpp_probe(struct hid_device *hdev, const struct hid_device_id *id)
+ hdev->name);
+
+ /*
+- * Plain USB connections need to actually call start and open
+- * on the transport driver to allow incoming data.
++ * First call hid_hw_start(hdev, 0) to allow IO without connecting any
++ * hid subdrivers (hid-input, hidraw). This allows retrieving the dev's
++ * name and serial number and store these in hdev->name and hdev->uniq,
++ * before the hid-input and hidraw drivers expose these to userspace.
+ */
+ ret = hid_hw_start(hdev, will_restart ? 0 : connect_mask);
+ if (ret) {
+@@ -4214,19 +4216,14 @@ static int hidpp_probe(struct hid_device *hdev, const struct hid_device_id *id)
+ flush_work(&hidpp->work);
+
+ if (will_restart) {
+- /* Reset the HID node state */
+- hid_device_io_stop(hdev);
+- hid_hw_close(hdev);
+- hid_hw_stop(hdev);
+-
+ if (hidpp->quirks & HIDPP_QUIRK_DELAYED_INIT)
+ connect_mask &= ~HID_CONNECT_HIDINPUT;
+
+ /* Now export the actual inputs and hidraw nodes to the world */
+- ret = hid_hw_start(hdev, connect_mask);
++ ret = hid_connect(hdev, connect_mask);
+ if (ret) {
+- hid_err(hdev, "%s:hid_hw_start returned error\n", __func__);
+- goto hid_hw_start_fail;
++ hid_err(hdev, "%s:hid_connect returned error %d\n", __func__, ret);
++ goto hid_hw_init_fail;
+ }
+ }
+
+@@ -4238,6 +4235,11 @@ static int hidpp_probe(struct hid_device *hdev, const struct hid_device_id *id)
+ ret);
+ }
+
++ /*
++ * This relies on logi_dj_ll_close() being a no-op so that DJ connection
++ * events will still be received.
++ */
++ hid_hw_close(hdev);
+ return ret;
+
+ hid_hw_init_fail:
+--
+2.42.0
+
--- /dev/null
+From 10eaf8f72122eafdf4d0f32b633c7a2a002128ed Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 10 Oct 2023 12:20:20 +0200
+Subject: HID: logitech-hidpp: Move get_wireless_feature_index() check to
+ hidpp_connect_event()
+
+From: Hans de Goede <hdegoede@redhat.com>
+
+[ Upstream commit ba9de350509504fb748837b71e23d7e84c83d93c ]
+
+Calling get_wireless_feature_index() from probe() causes
+the wireless_feature_index to only get set for unifying devices which
+are already connected at probe() time. It does not get set for devices
+which connect later.
+
+Fix this by moving get_wireless_feature_index() to hidpp_connect_event(),
+this does not make a difference for devices connected at probe() since
+probe() will queue the hidpp_connect_event() for those at probe time.
+
+This series has been tested on the following devices:
+Logitech Bluetooth Laser Travel Mouse (bluetooth, HID++ 1.0)
+Logitech M720 Triathlon (bluetooth, HID++ 4.5)
+Logitech M720 Triathlon (unifying, HID++ 4.5)
+Logitech K400 Pro (unifying, HID++ 4.1)
+Logitech K270 (eQUAD nano Lite, HID++ 2.0)
+Logitech M185 (eQUAD nano Lite, HID++ 4.5)
+Logitech LX501 keyboard (27 Mhz, HID++ builtin scroll-wheel, HID++ 1.0)
+Logitech M-RAZ105 mouse (27 Mhz, HID++ extra mouse buttons, HID++ 1.0)
+
+And by bentiss:
+Logitech Touchpad T650 (unifying)
+Logitech Touchpad T651 (bluetooth)
+Logitech MX Master 3B (BLE)
+Logitech G403 (plain USB / Gaming receiver)
+
+Fixes: 0da0a63b7cba ("HID: logitech-hidpp: Support WirelessDeviceStatus connect events")
+Signed-off-by: Hans de Goede <hdegoede@redhat.com>
+Link: https://lore.kernel.org/r/20231010102029.111003-4-hdegoede@redhat.com
+Signed-off-by: Benjamin Tissoires <bentiss@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/hid/hid-logitech-hidpp.c | 20 +++++++++-----------
+ 1 file changed, 9 insertions(+), 11 deletions(-)
+
+diff --git a/drivers/hid/hid-logitech-hidpp.c b/drivers/hid/hid-logitech-hidpp.c
+index f7d6927f95076..fb287c4cbd5b8 100644
+--- a/drivers/hid/hid-logitech-hidpp.c
++++ b/drivers/hid/hid-logitech-hidpp.c
+@@ -1753,15 +1753,14 @@ static int hidpp_battery_get_property(struct power_supply *psy,
+ /* -------------------------------------------------------------------------- */
+ #define HIDPP_PAGE_WIRELESS_DEVICE_STATUS 0x1d4b
+
+-static int hidpp_set_wireless_feature_index(struct hidpp_device *hidpp)
++static int hidpp_get_wireless_feature_index(struct hidpp_device *hidpp, u8 *feature_index)
+ {
+ u8 feature_type;
+ int ret;
+
+ ret = hidpp_root_get_feature(hidpp,
+ HIDPP_PAGE_WIRELESS_DEVICE_STATUS,
+- &hidpp->wireless_feature_index,
+- &feature_type);
++ feature_index, &feature_type);
+
+ return ret;
+ }
+@@ -3950,6 +3949,13 @@ static void hidpp_connect_event(struct hidpp_device *hidpp)
+ }
+ }
+
++ if (hidpp->protocol_major >= 2) {
++ u8 feature_index;
++
++ if (!hidpp_get_wireless_feature_index(hidpp, &feature_index))
++ hidpp->wireless_feature_index = feature_index;
++ }
++
+ if (hidpp->name == hdev->name && hidpp->protocol_major >= 2) {
+ name = hidpp_get_device_name(hidpp);
+ if (name) {
+@@ -4188,14 +4194,6 @@ static int hidpp_probe(struct hid_device *hdev, const struct hid_device_id *id)
+ hidpp_overwrite_name(hdev);
+ }
+
+- if (connected && hidpp->protocol_major >= 2) {
+- ret = hidpp_set_wireless_feature_index(hidpp);
+- if (ret == -ENOENT)
+- hidpp->wireless_feature_index = 0;
+- else if (ret)
+- goto hid_hw_init_fail;
+- }
+-
+ if (connected && (hidpp->quirks & HIDPP_QUIRK_CLASS_WTP)) {
+ ret = wtp_get_config(hidpp);
+ if (ret)
+--
+2.42.0
+
--- /dev/null
+From cd57c30374e05dd788412acea0c6e92ccc9aeb65 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 25 Jan 2023 13:17:23 +0100
+Subject: HID: logitech-hidpp: Remove HIDPP_QUIRK_NO_HIDINPUT quirk
+
+From: Bastien Nocera <hadess@hadess.net>
+
+[ Upstream commit d83956c8855c6c2ed4bd16cec4a5083d63df17e4 ]
+
+HIDPP_QUIRK_NO_HIDINPUT isn't used by any devices but still happens to
+work as HIDPP_QUIRK_DELAYED_INIT is defined to the same value. Remove
+HIDPP_QUIRK_NO_HIDINPUT and use HIDPP_QUIRK_DELAYED_INIT everywhere
+instead.
+
+Tested on a T650 which requires that quirk, and a number of unifying and
+Bluetooth devices that don't.
+
+Signed-off-by: Bastien Nocera <hadess@hadess.net>
+Link: https://lore.kernel.org/r/20230125121723.3122-2-hadess@hadess.net
+Signed-off-by: Benjamin Tissoires <benjamin.tissoires@redhat.com>
+Stable-dep-of: 11ca0322a419 ("HID: logitech-hidpp: Don't restart IO, instead defer hid_connect() only")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/hid/hid-logitech-hidpp.c | 8 +++-----
+ 1 file changed, 3 insertions(+), 5 deletions(-)
+
+diff --git a/drivers/hid/hid-logitech-hidpp.c b/drivers/hid/hid-logitech-hidpp.c
+index 7681a3fa67dab..a716c6f3bfb58 100644
+--- a/drivers/hid/hid-logitech-hidpp.c
++++ b/drivers/hid/hid-logitech-hidpp.c
+@@ -63,7 +63,7 @@ MODULE_PARM_DESC(disable_tap_to_click,
+ /* bits 2..20 are reserved for classes */
+ /* #define HIDPP_QUIRK_CONNECT_EVENTS BIT(21) disabled */
+ #define HIDPP_QUIRK_WTP_PHYSICAL_BUTTONS BIT(22)
+-#define HIDPP_QUIRK_NO_HIDINPUT BIT(23)
++#define HIDPP_QUIRK_DELAYED_INIT BIT(23)
+ #define HIDPP_QUIRK_FORCE_OUTPUT_REPORTS BIT(24)
+ #define HIDPP_QUIRK_UNIFYING BIT(25)
+ #define HIDPP_QUIRK_HI_RES_SCROLL_1P0 BIT(26)
+@@ -82,8 +82,6 @@ MODULE_PARM_DESC(disable_tap_to_click,
+ HIDPP_QUIRK_HI_RES_SCROLL_X2120 | \
+ HIDPP_QUIRK_HI_RES_SCROLL_X2121)
+
+-#define HIDPP_QUIRK_DELAYED_INIT HIDPP_QUIRK_NO_HIDINPUT
+-
+ #define HIDPP_CAPABILITY_HIDPP10_BATTERY BIT(0)
+ #define HIDPP_CAPABILITY_HIDPP20_BATTERY BIT(1)
+ #define HIDPP_CAPABILITY_BATTERY_MILEAGE BIT(2)
+@@ -3988,7 +3986,7 @@ static void hidpp_connect_event(struct hidpp_device *hidpp)
+ if (hidpp->quirks & HIDPP_QUIRK_HI_RES_SCROLL)
+ hi_res_scroll_enable(hidpp);
+
+- if (!(hidpp->quirks & HIDPP_QUIRK_NO_HIDINPUT) || hidpp->delayed_input)
++ if (!(hidpp->quirks & HIDPP_QUIRK_DELAYED_INIT) || hidpp->delayed_input)
+ /* if the input nodes are already created, we can stop now */
+ return;
+
+@@ -4221,7 +4219,7 @@ static int hidpp_probe(struct hid_device *hdev, const struct hid_device_id *id)
+ hid_hw_close(hdev);
+ hid_hw_stop(hdev);
+
+- if (hidpp->quirks & HIDPP_QUIRK_NO_HIDINPUT)
++ if (hidpp->quirks & HIDPP_QUIRK_DELAYED_INIT)
+ connect_mask &= ~HID_CONNECT_HIDINPUT;
+
+ /* Now export the actual inputs and hidraw nodes to the world */
+--
+2.42.0
+
--- /dev/null
+From 9c18aadf637a853cf129e072614cb02ec81764b7 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 10 Oct 2023 12:20:19 +0200
+Subject: HID: logitech-hidpp: Revert "Don't restart communication if not
+ necessary"
+
+From: Hans de Goede <hdegoede@redhat.com>
+
+[ Upstream commit 55bf70362ffc4ddd7c8745e2fe880edac00e4aff ]
+
+Commit 91cf9a98ae41 ("HID: logitech-hidpp: make .probe usbhid capable")
+makes hidpp_probe() first call hid_hw_start(hdev, 0) to allow IO
+without connecting any hid subdrivers (hid-input, hidraw).
+
+This is done to allow to retrieve the device's name and serial number
+and store these in hdev->name and hdev->uniq.
+
+Then later on IO was stopped and started again with hid_hw_start(hdev,
+HID_CONNECT_DEFAULT) connecting hid-input and hidraw after the name
+and serial number have been setup.
+
+Commit 498ba2069035 ("HID: logitech-hidpp: Don't restart communication
+if not necessary") changed the probe() code to only do the start with
+a 0 connect-mask + restart later for unifying devices.
+
+But for non unifying devices hdev->name and hdev->uniq are updated too.
+So this change re-introduces the problem for which the start with
+a 0 connect-mask + restart later behavior was introduced.
+
+The previous patch in this series changes the unifying path to instead of
+restarting IO only call hid_connect() later. This avoids possible issues
+with restarting IO seen on non unifying devices.
+
+Revert the change to limit the restart behavior to unifying devices to
+fix hdev->name changing after userspace facing devices have already been
+registered.
+
+This series has been tested on the following devices:
+Logitech Bluetooth Laser Travel Mouse (bluetooth, HID++ 1.0)
+Logitech M720 Triathlon (bluetooth, HID++ 4.5)
+Logitech M720 Triathlon (unifying, HID++ 4.5)
+Logitech K400 Pro (unifying, HID++ 4.1)
+Logitech K270 (eQUAD nano Lite, HID++ 2.0)
+Logitech M185 (eQUAD nano Lite, HID++ 4.5)
+Logitech LX501 keyboard (27 Mhz, HID++ builtin scroll-wheel, HID++ 1.0)
+Logitech M-RAZ105 mouse (27 Mhz, HID++ extra mouse buttons, HID++ 1.0)
+
+And by bentiss:
+Logitech Touchpad T650 (unifying)
+Logitech Touchpad T651 (bluetooth)
+Logitech MX Master 3B (BLE)
+Logitech G403 (plain USB / Gaming receiver)
+
+Fixes: 498ba2069035 ("HID: logitech-hidpp: Don't restart communication if not necessary")
+Signed-off-by: Hans de Goede <hdegoede@redhat.com>
+Link: https://lore.kernel.org/r/20231010102029.111003-3-hdegoede@redhat.com
+Signed-off-by: Benjamin Tissoires <bentiss@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/hid/hid-logitech-hidpp.c | 24 ++++++++----------------
+ 1 file changed, 8 insertions(+), 16 deletions(-)
+
+diff --git a/drivers/hid/hid-logitech-hidpp.c b/drivers/hid/hid-logitech-hidpp.c
+index 907f45dfef4c1..f7d6927f95076 100644
+--- a/drivers/hid/hid-logitech-hidpp.c
++++ b/drivers/hid/hid-logitech-hidpp.c
+@@ -4089,7 +4089,6 @@ static int hidpp_probe(struct hid_device *hdev, const struct hid_device_id *id)
+ bool connected;
+ unsigned int connect_mask = HID_CONNECT_DEFAULT;
+ struct hidpp_ff_private_data data;
+- bool will_restart = false;
+
+ /* report_fixup needs drvdata to be set before we call hid_parse */
+ hidpp = devm_kzalloc(&hdev->dev, sizeof(*hidpp), GFP_KERNEL);
+@@ -4140,10 +4139,6 @@ static int hidpp_probe(struct hid_device *hdev, const struct hid_device_id *id)
+ return ret;
+ }
+
+- if (hidpp->quirks & HIDPP_QUIRK_DELAYED_INIT ||
+- hidpp->quirks & HIDPP_QUIRK_UNIFYING)
+- will_restart = true;
+-
+ INIT_WORK(&hidpp->work, delayed_work_cb);
+ mutex_init(&hidpp->send_mutex);
+ init_waitqueue_head(&hidpp->wait);
+@@ -4160,7 +4155,7 @@ static int hidpp_probe(struct hid_device *hdev, const struct hid_device_id *id)
+ * name and serial number and store these in hdev->name and hdev->uniq,
+ * before the hid-input and hidraw drivers expose these to userspace.
+ */
+- ret = hid_hw_start(hdev, will_restart ? 0 : connect_mask);
++ ret = hid_hw_start(hdev, 0);
+ if (ret) {
+ hid_err(hdev, "hw start failed\n");
+ goto hid_hw_start_fail;
+@@ -4199,7 +4194,6 @@ static int hidpp_probe(struct hid_device *hdev, const struct hid_device_id *id)
+ hidpp->wireless_feature_index = 0;
+ else if (ret)
+ goto hid_hw_init_fail;
+- ret = 0;
+ }
+
+ if (connected && (hidpp->quirks & HIDPP_QUIRK_CLASS_WTP)) {
+@@ -4215,16 +4209,14 @@ static int hidpp_probe(struct hid_device *hdev, const struct hid_device_id *id)
+ schedule_work(&hidpp->work);
+ flush_work(&hidpp->work);
+
+- if (will_restart) {
+- if (hidpp->quirks & HIDPP_QUIRK_DELAYED_INIT)
+- connect_mask &= ~HID_CONNECT_HIDINPUT;
++ if (hidpp->quirks & HIDPP_QUIRK_DELAYED_INIT)
++ connect_mask &= ~HID_CONNECT_HIDINPUT;
+
+- /* Now export the actual inputs and hidraw nodes to the world */
+- ret = hid_connect(hdev, connect_mask);
+- if (ret) {
+- hid_err(hdev, "%s:hid_connect returned error %d\n", __func__, ret);
+- goto hid_hw_init_fail;
+- }
++ /* Now export the actual inputs and hidraw nodes to the world */
++ ret = hid_connect(hdev, connect_mask);
++ if (ret) {
++ hid_err(hdev, "%s:hid_connect returned error %d\n", __func__, ret);
++ goto hid_hw_init_fail;
+ }
+
+ if (hidpp->quirks & HIDPP_QUIRK_CLASS_G920) {
+--
+2.42.0
+
--- /dev/null
+From 2df8169ee4c9d11efdb3b3b4c4a85afb921775a1 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 25 Oct 2023 15:21:00 +0200
+Subject: hwmon: (axi-fan-control) Fix possible NULL pointer dereference
+
+From: Dragos Bogdan <dragos.bogdan@analog.com>
+
+[ Upstream commit 2a5b3370a1d9750eca325292e291c8c7cb8cf2e0 ]
+
+axi_fan_control_irq_handler(), dependent on the private
+axi_fan_control_data structure, might be called before the hwmon
+device is registered. That will cause an "Unable to handle kernel
+NULL pointer dereference" error.
+
+Fixes: 8412b410fa5e ("hwmon: Support ADI Fan Control IP")
+Signed-off-by: Dragos Bogdan <dragos.bogdan@analog.com>
+Signed-off-by: Nuno Sa <nuno.sa@analog.com>
+Link: https://lore.kernel.org/r/20231025132100.649499-1-nuno.sa@analog.com
+Signed-off-by: Guenter Roeck <linux@roeck-us.net>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/hwmon/axi-fan-control.c | 29 ++++++++++++++++-------------
+ 1 file changed, 16 insertions(+), 13 deletions(-)
+
+diff --git a/drivers/hwmon/axi-fan-control.c b/drivers/hwmon/axi-fan-control.c
+index d2092c17d9935..7af18018a32ff 100644
+--- a/drivers/hwmon/axi-fan-control.c
++++ b/drivers/hwmon/axi-fan-control.c
+@@ -508,6 +508,21 @@ static int axi_fan_control_probe(struct platform_device *pdev)
+ return -ENODEV;
+ }
+
++ ret = axi_fan_control_init(ctl, pdev->dev.of_node);
++ if (ret) {
++ dev_err(&pdev->dev, "Failed to initialize device\n");
++ return ret;
++ }
++
++ ctl->hdev = devm_hwmon_device_register_with_info(&pdev->dev,
++ name,
++ ctl,
++ &axi_chip_info,
++ axi_fan_control_groups);
++
++ if (IS_ERR(ctl->hdev))
++ return PTR_ERR(ctl->hdev);
++
+ ctl->irq = platform_get_irq(pdev, 0);
+ if (ctl->irq < 0)
+ return ctl->irq;
+@@ -521,19 +536,7 @@ static int axi_fan_control_probe(struct platform_device *pdev)
+ return ret;
+ }
+
+- ret = axi_fan_control_init(ctl, pdev->dev.of_node);
+- if (ret) {
+- dev_err(&pdev->dev, "Failed to initialize device\n");
+- return ret;
+- }
+-
+- ctl->hdev = devm_hwmon_device_register_with_info(&pdev->dev,
+- name,
+- ctl,
+- &axi_chip_info,
+- axi_fan_control_groups);
+-
+- return PTR_ERR_OR_ZERO(ctl->hdev);
++ return 0;
+ }
+
+ static struct platform_driver axi_fan_control_driver = {
+--
+2.42.0
+
--- /dev/null
+From 5a7a3bc9892d481822a86b391bf8e981fec489a2 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 25 Oct 2023 20:23:16 +0800
+Subject: hwmon: (coretemp) Fix potentially truncated sysfs attribute name
+
+From: Zhang Rui <rui.zhang@intel.com>
+
+[ Upstream commit bbfff736d30e5283ad09e748caff979d75ddef7f ]
+
+When build with W=1 and "-Werror=format-truncation", below error is
+observed in coretemp driver,
+
+ drivers/hwmon/coretemp.c: In function 'create_core_data':
+>> drivers/hwmon/coretemp.c:393:34: error: '%s' directive output may be truncated writing likely 5 or more bytes into a region of size between 3 and 13 [-Werror=format-truncation=]
+ 393 | "temp%d_%s", attr_no, suffixes[i]);
+ | ^~
+ drivers/hwmon/coretemp.c:393:26: note: assuming directive output of 5 bytes
+ 393 | "temp%d_%s", attr_no, suffixes[i]);
+ | ^~~~~~~~~~~
+ drivers/hwmon/coretemp.c:392:17: note: 'snprintf' output 7 or more bytes (assuming 22) into a destination of size 19
+ 392 | snprintf(tdata->attr_name[i], CORETEMP_NAME_LENGTH,
+ | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ 393 | "temp%d_%s", attr_no, suffixes[i]);
+ | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ cc1: all warnings being treated as errors
+
+Given that
+1. '%d' could take 10 charactors,
+2. '%s' could take 10 charactors ("crit_alarm"),
+3. "temp", "_" and the NULL terminator take 6 charactors,
+fix the problem by increasing CORETEMP_NAME_LENGTH to 28.
+
+Signed-off-by: Zhang Rui <rui.zhang@intel.com>
+Fixes: 7108b80a542b ("hwmon/coretemp: Handle large core ID value")
+Reported-by: kernel test robot <lkp@intel.com>
+Closes: https://lore.kernel.org/oe-kbuild-all/202310200443.iD3tUbbK-lkp@intel.com/
+Link: https://lore.kernel.org/r/20231025122316.836400-1-rui.zhang@intel.com
+Signed-off-by: Guenter Roeck <linux@roeck-us.net>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/hwmon/coretemp.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/drivers/hwmon/coretemp.c b/drivers/hwmon/coretemp.c
+index eaae5de2ab616..5b2057ce5a59d 100644
+--- a/drivers/hwmon/coretemp.c
++++ b/drivers/hwmon/coretemp.c
+@@ -41,7 +41,7 @@ MODULE_PARM_DESC(tjmax, "TjMax value in degrees Celsius");
+ #define PKG_SYSFS_ATTR_NO 1 /* Sysfs attribute for package temp */
+ #define BASE_SYSFS_ATTR_NO 2 /* Sysfs Base attr no for coretemp */
+ #define NUM_REAL_CORES 128 /* Number of Real cores per cpu */
+-#define CORETEMP_NAME_LENGTH 19 /* String Length of attrs */
++#define CORETEMP_NAME_LENGTH 28 /* String Length of attrs */
+ #define MAX_CORE_ATTRS 4 /* Maximum no of basic attrs */
+ #define TOTAL_ATTRS (MAX_CORE_ATTRS + 1)
+ #define MAX_CORE_DATA (NUM_REAL_CORES + BASE_SYSFS_ATTR_NO)
+--
+2.42.0
+
--- /dev/null
+From 72cd0a15f2c92c0c6afe1967f85fcb9f935caf8f Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sun, 10 Sep 2023 10:34:17 +0200
+Subject: hwrng: geode - fix accessing registers
+
+From: Jonas Gorski <jonas.gorski@gmail.com>
+
+[ Upstream commit 464bd8ec2f06707f3773676a1bd2c64832a3c805 ]
+
+When the membase and pci_dev pointer were moved to a new struct in priv,
+the actual membase users were left untouched, and they started reading
+out arbitrary memory behind the struct instead of registers. This
+unfortunately turned the RNG into a constant number generator, depending
+on the content of what was at that offset.
+
+To fix this, update geode_rng_data_{read,present}() to also get the
+membase via amd_geode_priv, and properly read from the right addresses
+again.
+
+Fixes: 9f6ec8dc574e ("hwrng: geode - Fix PCI device refcount leak")
+Reported-by: Timur I. Davletshin <timur.davletshin@gmail.com>
+Closes: https://bugzilla.kernel.org/show_bug.cgi?id=217882
+Tested-by: Timur I. Davletshin <timur.davletshin@gmail.com>
+Suggested-by: Jo-Philipp Wich <jo@mein.io>
+Signed-off-by: Jonas Gorski <jonas.gorski@gmail.com>
+Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/char/hw_random/geode-rng.c | 6 ++++--
+ 1 file changed, 4 insertions(+), 2 deletions(-)
+
+diff --git a/drivers/char/hw_random/geode-rng.c b/drivers/char/hw_random/geode-rng.c
+index 12fbe80918319..159baf00a8675 100644
+--- a/drivers/char/hw_random/geode-rng.c
++++ b/drivers/char/hw_random/geode-rng.c
+@@ -58,7 +58,8 @@ struct amd_geode_priv {
+
+ static int geode_rng_data_read(struct hwrng *rng, u32 *data)
+ {
+- void __iomem *mem = (void __iomem *)rng->priv;
++ struct amd_geode_priv *priv = (struct amd_geode_priv *)rng->priv;
++ void __iomem *mem = priv->membase;
+
+ *data = readl(mem + GEODE_RNG_DATA_REG);
+
+@@ -67,7 +68,8 @@ static int geode_rng_data_read(struct hwrng *rng, u32 *data)
+
+ static int geode_rng_data_present(struct hwrng *rng, int wait)
+ {
+- void __iomem *mem = (void __iomem *)rng->priv;
++ struct amd_geode_priv *priv = (struct amd_geode_priv *)rng->priv;
++ void __iomem *mem = priv->membase;
+ int data, i;
+
+ for (i = 0; i < 20; i++) {
+--
+2.42.0
+
--- /dev/null
+From e9563cdcebb4f51aedeebcc83f88dcb5269f72c0 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 21 Sep 2023 16:24:10 +0800
+Subject: i3c: Fix potential refcount leak in i3c_master_register_new_i3c_devs
+
+From: Dinghao Liu <dinghao.liu@zju.edu.cn>
+
+[ Upstream commit cab63f64887616e3c4e31cfd8103320be6ebc8d3 ]
+
+put_device() needs to be called on failure of device_register()
+to give up the reference initialized in it to avoid refcount leak.
+
+Fixes: 3a379bbcea0a ("i3c: Add core I3C infrastructure")
+Signed-off-by: Dinghao Liu <dinghao.liu@zju.edu.cn>
+Link: https://lore.kernel.org/r/20230921082410.25548-1-dinghao.liu@zju.edu.cn
+Signed-off-by: Alexandre Belloni <alexandre.belloni@bootlin.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/i3c/master.c | 4 +++-
+ 1 file changed, 3 insertions(+), 1 deletion(-)
+
+diff --git a/drivers/i3c/master.c b/drivers/i3c/master.c
+index dfe18dcd008d4..b6abbb0acbbd3 100644
+--- a/drivers/i3c/master.c
++++ b/drivers/i3c/master.c
+@@ -1506,9 +1506,11 @@ i3c_master_register_new_i3c_devs(struct i3c_master_controller *master)
+ desc->dev->dev.of_node = desc->boardinfo->of_node;
+
+ ret = device_register(&desc->dev->dev);
+- if (ret)
++ if (ret) {
+ dev_err(&master->dev,
+ "Failed to add I3C device (err = %d)\n", ret);
++ put_device(&desc->dev->dev);
++ }
+ }
+ }
+
+--
+2.42.0
+
--- /dev/null
+From 9ccc3bc6ed5f19fc4710e77aef42458aa86e3444 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 8 Sep 2023 14:42:01 +0200
+Subject: i40e: fix potential memory leaks in i40e_remove()
+
+From: Andrii Staikov <andrii.staikov@intel.com>
+
+[ Upstream commit 5ca636d927a106780451d957734f02589b972e2b ]
+
+Instead of freeing memory of a single VSI, make sure
+the memory for all VSIs is cleared before releasing VSIs.
+Add releasing of their resources in a loop with the iteration
+number equal to the number of allocated VSIs.
+
+Fixes: 41c445ff0f48 ("i40e: main driver core")
+Signed-off-by: Andrii Staikov <andrii.staikov@intel.com>
+Signed-off-by: Aleksandr Loktionov <aleksandr.loktionov@intel.com>
+Reviewed-by: Simon Horman <horms@kernel.org>
+Signed-off-by: Tony Nguyen <anthony.l.nguyen@intel.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/ethernet/intel/i40e/i40e_main.c | 10 +++++++---
+ 1 file changed, 7 insertions(+), 3 deletions(-)
+
+diff --git a/drivers/net/ethernet/intel/i40e/i40e_main.c b/drivers/net/ethernet/intel/i40e/i40e_main.c
+index 539bb69548f23..20e26aa5b81c8 100644
+--- a/drivers/net/ethernet/intel/i40e/i40e_main.c
++++ b/drivers/net/ethernet/intel/i40e/i40e_main.c
+@@ -16258,11 +16258,15 @@ static void i40e_remove(struct pci_dev *pdev)
+ i40e_switch_branch_release(pf->veb[i]);
+ }
+
+- /* Now we can shutdown the PF's VSI, just before we kill
++ /* Now we can shutdown the PF's VSIs, just before we kill
+ * adminq and hmc.
+ */
+- if (pf->vsi[pf->lan_vsi])
+- i40e_vsi_release(pf->vsi[pf->lan_vsi]);
++ for (i = pf->num_alloc_vsi; i--;)
++ if (pf->vsi[i]) {
++ i40e_vsi_close(pf->vsi[i]);
++ i40e_vsi_release(pf->vsi[i]);
++ pf->vsi[i] = NULL;
++ }
+
+ i40e_cloud_filter_exit(pf);
+
+--
+2.42.0
+
--- /dev/null
+From 8123f0dfb81bf6bfa34216ef662a4f938ea8cb27 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 9 Oct 2023 13:41:20 +0300
+Subject: IB/mlx5: Fix rdma counter binding for RAW QP
+
+From: Patrisious Haddad <phaddad@nvidia.com>
+
+[ Upstream commit c1336bb4aa5e809a622a87d74311275514086596 ]
+
+Previously when we had a RAW QP, we bound a counter to it when it moved
+to INIT state, using the counter context inside RQC.
+
+But when we try to modify that counter later in RTS state we used
+modify QP which tries to change the counter inside QPC instead of RQC.
+
+Now we correctly modify the counter set_id inside of RQC instead of QPC
+for the RAW QP.
+
+Fixes: d14133dd4161 ("IB/mlx5: Support set qp counter")
+Signed-off-by: Patrisious Haddad <phaddad@nvidia.com>
+Reviewed-by: Mark Zhang <markzhang@nvidia.com>
+Link: https://lore.kernel.org/r/2e5ab6713784a8fe997d19c508187a0dfecf2dfc.1696847964.git.leon@kernel.org
+Signed-off-by: Leon Romanovsky <leon@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/infiniband/hw/mlx5/qp.c | 27 +++++++++++++++++++++++++++
+ 1 file changed, 27 insertions(+)
+
+diff --git a/drivers/infiniband/hw/mlx5/qp.c b/drivers/infiniband/hw/mlx5/qp.c
+index 1080daf3a546f..d4b5ce37c2cbd 100644
+--- a/drivers/infiniband/hw/mlx5/qp.c
++++ b/drivers/infiniband/hw/mlx5/qp.c
+@@ -3955,6 +3955,30 @@ static unsigned int get_tx_affinity(struct ib_qp *qp,
+ return tx_affinity;
+ }
+
++static int __mlx5_ib_qp_set_raw_qp_counter(struct mlx5_ib_qp *qp, u32 set_id,
++ struct mlx5_core_dev *mdev)
++{
++ struct mlx5_ib_raw_packet_qp *raw_packet_qp = &qp->raw_packet_qp;
++ struct mlx5_ib_rq *rq = &raw_packet_qp->rq;
++ u32 in[MLX5_ST_SZ_DW(modify_rq_in)] = {};
++ void *rqc;
++
++ if (!qp->rq.wqe_cnt)
++ return 0;
++
++ MLX5_SET(modify_rq_in, in, rq_state, rq->state);
++ MLX5_SET(modify_rq_in, in, uid, to_mpd(qp->ibqp.pd)->uid);
++
++ rqc = MLX5_ADDR_OF(modify_rq_in, in, ctx);
++ MLX5_SET(rqc, rqc, state, MLX5_RQC_STATE_RDY);
++
++ MLX5_SET64(modify_rq_in, in, modify_bitmask,
++ MLX5_MODIFY_RQ_IN_MODIFY_BITMASK_RQ_COUNTER_SET_ID);
++ MLX5_SET(rqc, rqc, counter_set_id, set_id);
++
++ return mlx5_core_modify_rq(mdev, rq->base.mqp.qpn, in);
++}
++
+ static int __mlx5_ib_qp_set_counter(struct ib_qp *qp,
+ struct rdma_counter *counter)
+ {
+@@ -3970,6 +3994,9 @@ static int __mlx5_ib_qp_set_counter(struct ib_qp *qp,
+ else
+ set_id = mlx5_ib_get_counters_id(dev, mqp->port - 1);
+
++ if (mqp->type == IB_QPT_RAW_PACKET)
++ return __mlx5_ib_qp_set_raw_qp_counter(mqp, set_id, dev->mdev);
++
+ base = &mqp->trans_qp.base;
+ MLX5_SET(rts2rts_qp_in, in, opcode, MLX5_CMD_OP_RTS2RTS_QP);
+ MLX5_SET(rts2rts_qp_in, in, qpn, base->mqp.qpn);
+--
+2.42.0
+
--- /dev/null
+From e92523621671328b093c0835e5693a6f920c3f77 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 25 Sep 2023 13:02:59 +0100
+Subject: iov_iter, x86: Be consistent about the __user tag on
+ copy_mc_to_user()
+
+From: David Howells <dhowells@redhat.com>
+
+[ Upstream commit 066baf92bed934c9fb4bcee97a193f47aa63431c ]
+
+copy_mc_to_user() has the destination marked __user on powerpc, but not on
+x86; the latter results in a sparse warning in lib/iov_iter.c.
+
+Fix this by applying the tag on x86 too.
+
+Fixes: ec6347bb4339 ("x86, powerpc: Rename memcpy_mcsafe() to copy_mc_to_{user, kernel}()")
+Signed-off-by: David Howells <dhowells@redhat.com>
+Link: https://lore.kernel.org/r/20230925120309.1731676-3-dhowells@redhat.com
+cc: Dan Williams <dan.j.williams@intel.com>
+cc: Thomas Gleixner <tglx@linutronix.de>
+cc: Ingo Molnar <mingo@redhat.com>
+cc: Borislav Petkov <bp@alien8.de>
+cc: Dave Hansen <dave.hansen@linux.intel.com>
+cc: "H. Peter Anvin" <hpa@zytor.com>
+cc: Alexander Viro <viro@zeniv.linux.org.uk>
+cc: Jens Axboe <axboe@kernel.dk>
+cc: Christoph Hellwig <hch@lst.de>
+cc: Christian Brauner <christian@brauner.io>
+cc: Matthew Wilcox <willy@infradead.org>
+cc: Linus Torvalds <torvalds@linux-foundation.org>
+cc: David Laight <David.Laight@ACULAB.COM>
+cc: x86@kernel.org
+cc: linux-block@vger.kernel.org
+cc: linux-fsdevel@vger.kernel.org
+cc: linux-mm@kvack.org
+Signed-off-by: Christian Brauner <brauner@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ arch/x86/include/asm/uaccess.h | 2 +-
+ arch/x86/lib/copy_mc.c | 8 ++++----
+ 2 files changed, 5 insertions(+), 5 deletions(-)
+
+diff --git a/arch/x86/include/asm/uaccess.h b/arch/x86/include/asm/uaccess.h
+index ab5e577373093..3616fd4ba3953 100644
+--- a/arch/x86/include/asm/uaccess.h
++++ b/arch/x86/include/asm/uaccess.h
+@@ -543,7 +543,7 @@ copy_mc_to_kernel(void *to, const void *from, unsigned len);
+ #define copy_mc_to_kernel copy_mc_to_kernel
+
+ unsigned long __must_check
+-copy_mc_to_user(void *to, const void *from, unsigned len);
++copy_mc_to_user(void __user *to, const void *from, unsigned len);
+ #endif
+
+ /*
+diff --git a/arch/x86/lib/copy_mc.c b/arch/x86/lib/copy_mc.c
+index 80efd45a77617..6e8b7e600def5 100644
+--- a/arch/x86/lib/copy_mc.c
++++ b/arch/x86/lib/copy_mc.c
+@@ -70,23 +70,23 @@ unsigned long __must_check copy_mc_to_kernel(void *dst, const void *src, unsigne
+ }
+ EXPORT_SYMBOL_GPL(copy_mc_to_kernel);
+
+-unsigned long __must_check copy_mc_to_user(void *dst, const void *src, unsigned len)
++unsigned long __must_check copy_mc_to_user(void __user *dst, const void *src, unsigned len)
+ {
+ unsigned long ret;
+
+ if (copy_mc_fragile_enabled) {
+ __uaccess_begin();
+- ret = copy_mc_fragile(dst, src, len);
++ ret = copy_mc_fragile((__force void *)dst, src, len);
+ __uaccess_end();
+ return ret;
+ }
+
+ if (static_cpu_has(X86_FEATURE_ERMS)) {
+ __uaccess_begin();
+- ret = copy_mc_enhanced_fast_string(dst, src, len);
++ ret = copy_mc_enhanced_fast_string((__force void *)dst, src, len);
+ __uaccess_end();
+ return ret;
+ }
+
+- return copy_user_generic(dst, src, len);
++ return copy_user_generic((__force void *)dst, src, len);
+ }
+--
+2.42.0
+
--- /dev/null
+From b1b2a0fb684cbeeca74f27767135240a722cccba Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 24 Oct 2023 07:26:40 -0700
+Subject: ipv6: avoid atomic fragment on GSO packets
+
+From: Yan Zhai <yan@cloudflare.com>
+
+[ Upstream commit 03d6c848bfb406e9ef6d9846d759e97beaeea113 ]
+
+When the ipv6 stack output a GSO packet, if its gso_size is larger than
+dst MTU, then all segments would be fragmented. However, it is possible
+for a GSO packet to have a trailing segment with smaller actual size
+than both gso_size as well as the MTU, which leads to an "atomic
+fragment". Atomic fragments are considered harmful in RFC-8021. An
+Existing report from APNIC also shows that atomic fragments are more
+likely to be dropped even it is equivalent to a no-op [1].
+
+Add an extra check in the GSO slow output path. For each segment from
+the original over-sized packet, if it fits with the path MTU, then avoid
+generating an atomic fragment.
+
+Link: https://www.potaroo.net/presentations/2022-03-01-ipv6-frag.pdf [1]
+Fixes: b210de4f8c97 ("net: ipv6: Validate GSO SKB before finish IPv6 processing")
+Reported-by: David Wragg <dwragg@cloudflare.com>
+Signed-off-by: Yan Zhai <yan@cloudflare.com>
+Link: https://lore.kernel.org/r/90912e3503a242dca0bc36958b11ed03a2696e5e.1698156966.git.yan@cloudflare.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/ipv6/ip6_output.c | 8 +++++++-
+ 1 file changed, 7 insertions(+), 1 deletion(-)
+
+diff --git a/net/ipv6/ip6_output.c b/net/ipv6/ip6_output.c
+index 2207acd7108c1..5045b479c2a95 100644
+--- a/net/ipv6/ip6_output.c
++++ b/net/ipv6/ip6_output.c
+@@ -159,7 +159,13 @@ ip6_finish_output_gso_slowpath_drop(struct net *net, struct sock *sk,
+ int err;
+
+ skb_mark_not_on_list(segs);
+- err = ip6_fragment(net, sk, segs, ip6_finish_output2);
++ /* Last GSO segment can be smaller than gso_size (and MTU).
++ * Adding a fragment header would produce an "atomic fragment",
++ * which is considered harmful (RFC-8021). Avoid that.
++ */
++ err = segs->len > mtu ?
++ ip6_fragment(net, sk, segs, ip6_finish_output2) :
++ ip6_finish_output2(net, sk, segs);
+ if (err && ret == 0)
+ ret = err;
+ }
+--
+2.42.0
+
--- /dev/null
+From a9eb562c8273dd550a00f55bca46a57141fab486 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 26 Oct 2023 13:14:46 +0000
+Subject: ipvlan: properly track tx_errors
+
+From: Eric Dumazet <edumazet@google.com>
+
+[ Upstream commit ff672b9ffeb3f82135488ac16c5c5eb4b992999b ]
+
+Both ipvlan_process_v4_outbound() and ipvlan_process_v6_outbound()
+increment dev->stats.tx_errors in case of errors.
+
+Unfortunately there are two issues :
+
+1) ipvlan_get_stats64() does not propagate dev->stats.tx_errors to user.
+
+2) Increments are not atomic. KCSAN would complain eventually.
+
+Use DEV_STATS_INC() to not miss an update, and change ipvlan_get_stats64()
+to copy the value back to user.
+
+Fixes: 2ad7bf363841 ("ipvlan: Initial check-in of the IPVLAN driver.")
+Signed-off-by: Eric Dumazet <edumazet@google.com>
+Cc: Mahesh Bandewar <maheshb@google.com>
+Link: https://lore.kernel.org/r/20231026131446.3933175-1-edumazet@google.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/ipvlan/ipvlan_core.c | 8 ++++----
+ drivers/net/ipvlan/ipvlan_main.c | 1 +
+ 2 files changed, 5 insertions(+), 4 deletions(-)
+
+diff --git a/drivers/net/ipvlan/ipvlan_core.c b/drivers/net/ipvlan/ipvlan_core.c
+index e10cb98b0f4f5..905542df3b682 100644
+--- a/drivers/net/ipvlan/ipvlan_core.c
++++ b/drivers/net/ipvlan/ipvlan_core.c
+@@ -442,12 +442,12 @@ static int ipvlan_process_v4_outbound(struct sk_buff *skb)
+
+ err = ip_local_out(net, skb->sk, skb);
+ if (unlikely(net_xmit_eval(err)))
+- dev->stats.tx_errors++;
++ DEV_STATS_INC(dev, tx_errors);
+ else
+ ret = NET_XMIT_SUCCESS;
+ goto out;
+ err:
+- dev->stats.tx_errors++;
++ DEV_STATS_INC(dev, tx_errors);
+ kfree_skb(skb);
+ out:
+ return ret;
+@@ -483,12 +483,12 @@ static int ipvlan_process_v6_outbound(struct sk_buff *skb)
+
+ err = ip6_local_out(net, skb->sk, skb);
+ if (unlikely(net_xmit_eval(err)))
+- dev->stats.tx_errors++;
++ DEV_STATS_INC(dev, tx_errors);
+ else
+ ret = NET_XMIT_SUCCESS;
+ goto out;
+ err:
+- dev->stats.tx_errors++;
++ DEV_STATS_INC(dev, tx_errors);
+ kfree_skb(skb);
+ out:
+ return ret;
+diff --git a/drivers/net/ipvlan/ipvlan_main.c b/drivers/net/ipvlan/ipvlan_main.c
+index c199f0b465cd0..8660d452f642b 100644
+--- a/drivers/net/ipvlan/ipvlan_main.c
++++ b/drivers/net/ipvlan/ipvlan_main.c
+@@ -324,6 +324,7 @@ static void ipvlan_get_stats64(struct net_device *dev,
+ s->rx_dropped = rx_errs;
+ s->tx_dropped = tx_drps;
+ }
++ s->tx_errors = DEV_STATS_READ(dev, tx_errors);
+ }
+
+ static int ipvlan_vlan_rx_add_vid(struct net_device *dev, __be16 proto, u16 vid)
+--
+2.42.0
+
--- /dev/null
+From f93cdbebdd96bfbffd89a9a8437af95f66acc337 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 4 Feb 2022 12:25:04 +0200
+Subject: iwlwifi: pcie: adjust to Bz completion descriptor
+
+From: Johannes Berg <johannes.berg@intel.com>
+
+[ Upstream commit 5d19e2087fea28651eff7eadf4510fa1564688a2 ]
+
+The Bz devices got a new completion descriptor again since
+we only ever really used 4 out of 32 bytes anyway. Adjust
+the code to deal with that. Note that the intention was to
+reduce the size, but the hardware was implemented wrongly.
+
+While at it, do some cleanups and remove the union to simplify
+the code, clean up iwl_pcie_free_bd_size() to no longer need
+an argument and add iwl_pcie_used_bd_size() with the logic to
+selct completion descriptor size.
+
+Signed-off-by: Johannes Berg <johannes.berg@intel.com>
+Signed-off-by: Luca Coelho <luciano.coelho@intel.com>
+Link: https://lore.kernel.org/r/iwlwifi.20220204122220.bef461a04110.I90c8885550fa54eb0aaa4363d322f50e301175a6@changeid
+Signed-off-by: Luca Coelho <luciano.coelho@intel.com>
+Stable-dep-of: 37fb29bd1f90 ("wifi: iwlwifi: pcie: synchronize IRQs before NAPI")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ .../wireless/intel/iwlwifi/pcie/internal.h | 20 +++++--
+ drivers/net/wireless/intel/iwlwifi/pcie/rx.c | 56 ++++++++++++-------
+ 2 files changed, 51 insertions(+), 25 deletions(-)
+
+diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/internal.h b/drivers/net/wireless/intel/iwlwifi/pcie/internal.h
+index 6dce36d326935..775ee03e5b128 100644
+--- a/drivers/net/wireless/intel/iwlwifi/pcie/internal.h
++++ b/drivers/net/wireless/intel/iwlwifi/pcie/internal.h
+@@ -1,6 +1,6 @@
+ /* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
+ /*
+- * Copyright (C) 2003-2015, 2018-2021 Intel Corporation
++ * Copyright (C) 2003-2015, 2018-2022 Intel Corporation
+ * Copyright (C) 2013-2015 Intel Mobile Communications GmbH
+ * Copyright (C) 2016-2017 Intel Deutschland GmbH
+ */
+@@ -103,6 +103,18 @@ struct iwl_rx_completion_desc {
+ u8 reserved2[25];
+ } __packed;
+
++/**
++ * struct iwl_rx_completion_desc_bz - Bz completion descriptor
++ * @rbid: unique tag of the received buffer
++ * @flags: flags (0: fragmented, all others: reserved)
++ * @reserved: reserved
++ */
++struct iwl_rx_completion_desc_bz {
++ __le16 rbid;
++ u8 flags;
++ u8 reserved[1];
++} __packed;
++
+ /**
+ * struct iwl_rxq - Rx queue
+ * @id: queue index
+@@ -133,11 +145,7 @@ struct iwl_rxq {
+ int id;
+ void *bd;
+ dma_addr_t bd_dma;
+- union {
+- void *used_bd;
+- __le32 *bd_32;
+- struct iwl_rx_completion_desc *cd;
+- };
++ void *used_bd;
+ dma_addr_t used_bd_dma;
+ u32 read;
+ u32 write;
+diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/rx.c b/drivers/net/wireless/intel/iwlwifi/pcie/rx.c
+index f82fb17450165..74b4280221e0f 100644
+--- a/drivers/net/wireless/intel/iwlwifi/pcie/rx.c
++++ b/drivers/net/wireless/intel/iwlwifi/pcie/rx.c
+@@ -1,6 +1,6 @@
+ // SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
+ /*
+- * Copyright (C) 2003-2014, 2018-2021 Intel Corporation
++ * Copyright (C) 2003-2014, 2018-2022 Intel Corporation
+ * Copyright (C) 2013-2015 Intel Mobile Communications GmbH
+ * Copyright (C) 2016-2017 Intel Deutschland GmbH
+ */
+@@ -652,23 +652,30 @@ void iwl_pcie_rx_allocator_work(struct work_struct *data)
+ iwl_pcie_rx_allocator(trans_pcie->trans);
+ }
+
+-static int iwl_pcie_free_bd_size(struct iwl_trans *trans, bool use_rx_td)
++static int iwl_pcie_free_bd_size(struct iwl_trans *trans)
+ {
+- struct iwl_rx_transfer_desc *rx_td;
++ if (trans->trans_cfg->device_family >= IWL_DEVICE_FAMILY_AX210)
++ return sizeof(struct iwl_rx_transfer_desc);
+
+- if (use_rx_td)
+- return sizeof(*rx_td);
+- else
+- return trans->trans_cfg->mq_rx_supported ? sizeof(__le64) :
+- sizeof(__le32);
++ return trans->trans_cfg->mq_rx_supported ?
++ sizeof(__le64) : sizeof(__le32);
++}
++
++static int iwl_pcie_used_bd_size(struct iwl_trans *trans)
++{
++ if (trans->trans_cfg->device_family >= IWL_DEVICE_FAMILY_BZ)
++ return sizeof(struct iwl_rx_completion_desc_bz);
++
++ if (trans->trans_cfg->device_family >= IWL_DEVICE_FAMILY_AX210)
++ return sizeof(struct iwl_rx_completion_desc);
++
++ return sizeof(__le32);
+ }
+
+ static void iwl_pcie_free_rxq_dma(struct iwl_trans *trans,
+ struct iwl_rxq *rxq)
+ {
+- bool use_rx_td = (trans->trans_cfg->device_family >=
+- IWL_DEVICE_FAMILY_AX210);
+- int free_size = iwl_pcie_free_bd_size(trans, use_rx_td);
++ int free_size = iwl_pcie_free_bd_size(trans);
+
+ if (rxq->bd)
+ dma_free_coherent(trans->dev,
+@@ -682,8 +689,8 @@ static void iwl_pcie_free_rxq_dma(struct iwl_trans *trans,
+
+ if (rxq->used_bd)
+ dma_free_coherent(trans->dev,
+- (use_rx_td ? sizeof(*rxq->cd) :
+- sizeof(__le32)) * rxq->queue_size,
++ iwl_pcie_used_bd_size(trans) *
++ rxq->queue_size,
+ rxq->used_bd, rxq->used_bd_dma);
+ rxq->used_bd_dma = 0;
+ rxq->used_bd = NULL;
+@@ -707,7 +714,7 @@ static int iwl_pcie_alloc_rxq_dma(struct iwl_trans *trans,
+ else
+ rxq->queue_size = RX_QUEUE_SIZE;
+
+- free_size = iwl_pcie_free_bd_size(trans, use_rx_td);
++ free_size = iwl_pcie_free_bd_size(trans);
+
+ /*
+ * Allocate the circular buffer of Read Buffer Descriptors
+@@ -720,7 +727,8 @@ static int iwl_pcie_alloc_rxq_dma(struct iwl_trans *trans,
+
+ if (trans->trans_cfg->mq_rx_supported) {
+ rxq->used_bd = dma_alloc_coherent(dev,
+- (use_rx_td ? sizeof(*rxq->cd) : sizeof(__le32)) * rxq->queue_size,
++ iwl_pcie_used_bd_size(trans) *
++ rxq->queue_size,
+ &rxq->used_bd_dma,
+ GFP_KERNEL);
+ if (!rxq->used_bd)
+@@ -1419,6 +1427,7 @@ static struct iwl_rx_mem_buffer *iwl_pcie_get_rxb(struct iwl_trans *trans,
+ u16 vid;
+
+ BUILD_BUG_ON(sizeof(struct iwl_rx_completion_desc) != 32);
++ BUILD_BUG_ON(sizeof(struct iwl_rx_completion_desc_bz) != 4);
+
+ if (!trans->trans_cfg->mq_rx_supported) {
+ rxb = rxq->queue[i];
+@@ -1426,11 +1435,20 @@ static struct iwl_rx_mem_buffer *iwl_pcie_get_rxb(struct iwl_trans *trans,
+ return rxb;
+ }
+
+- if (trans->trans_cfg->device_family >= IWL_DEVICE_FAMILY_AX210) {
+- vid = le16_to_cpu(rxq->cd[i].rbid);
+- *join = rxq->cd[i].flags & IWL_RX_CD_FLAGS_FRAGMENTED;
++ if (trans->trans_cfg->device_family >= IWL_DEVICE_FAMILY_BZ) {
++ struct iwl_rx_completion_desc_bz *cd = rxq->used_bd;
++
++ vid = le16_to_cpu(cd[i].rbid);
++ *join = cd[i].flags & IWL_RX_CD_FLAGS_FRAGMENTED;
++ } else if (trans->trans_cfg->device_family >= IWL_DEVICE_FAMILY_AX210) {
++ struct iwl_rx_completion_desc *cd = rxq->used_bd;
++
++ vid = le16_to_cpu(cd[i].rbid);
++ *join = cd[i].flags & IWL_RX_CD_FLAGS_FRAGMENTED;
+ } else {
+- vid = le32_to_cpu(rxq->bd_32[i]) & 0x0FFF; /* 12-bit VID */
++ __le32 *cd = rxq->used_bd;
++
++ vid = le32_to_cpu(cd[i]) & 0x0FFF; /* 12-bit VID */
+ }
+
+ if (!vid || vid > RX_POOL_SIZE(trans_pcie->num_rx_bufs))
+--
+2.42.0
+
--- /dev/null
+From 03f60855381d9fc05d24e477a589cfa386d00da9 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sun, 17 Oct 2021 11:43:48 +0300
+Subject: iwlwifi: remove contact information
+
+From: Johannes Berg <johannes.berg@intel.com>
+
+[ Upstream commit 854fe828e58ceafbab92d408ad344a168ea41555 ]
+
+The list address is going away, and the postal address isn't
+useful, remove all the contact information.
+
+Signed-off-by: Johannes Berg <johannes.berg@intel.com>
+Signed-off-by: Luca Coelho <luciano.coelho@intel.com>
+Link: https://lore.kernel.org/r/iwlwifi.20211017113927.f73e3b6384cb.I967fd394995461277eafa149bb25cefd1673751e@changeid
+Signed-off-by: Luca Coelho <luciano.coelho@intel.com>
+Stable-dep-of: 658939fc68d3 ("wifi: iwlwifi: empty overflow queue during flush")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/wireless/intel/iwlwifi/cfg/1000.c | 5 -----
+ drivers/net/wireless/intel/iwlwifi/cfg/2000.c | 5 -----
+ drivers/net/wireless/intel/iwlwifi/cfg/5000.c | 5 -----
+ drivers/net/wireless/intel/iwlwifi/cfg/6000.c | 5 -----
+ drivers/net/wireless/intel/iwlwifi/dvm/debugfs.c | 4 ----
+ drivers/net/wireless/intel/iwlwifi/dvm/dev.h | 5 -----
+ drivers/net/wireless/intel/iwlwifi/dvm/devices.c | 5 -----
+ drivers/net/wireless/intel/iwlwifi/dvm/led.c | 5 -----
+ drivers/net/wireless/intel/iwlwifi/dvm/led.h | 5 -----
+ drivers/net/wireless/intel/iwlwifi/dvm/lib.c | 5 -----
+ drivers/net/wireless/intel/iwlwifi/dvm/mac80211.c | 5 -----
+ drivers/net/wireless/intel/iwlwifi/dvm/main.c | 5 -----
+ drivers/net/wireless/intel/iwlwifi/dvm/power.c | 4 ----
+ drivers/net/wireless/intel/iwlwifi/dvm/power.h | 4 ----
+ drivers/net/wireless/intel/iwlwifi/dvm/rs.c | 5 -----
+ drivers/net/wireless/intel/iwlwifi/dvm/rs.h | 5 -----
+ drivers/net/wireless/intel/iwlwifi/dvm/rx.c | 5 -----
+ drivers/net/wireless/intel/iwlwifi/dvm/rxon.c | 5 -----
+ drivers/net/wireless/intel/iwlwifi/dvm/scan.c | 4 ----
+ drivers/net/wireless/intel/iwlwifi/dvm/sta.c | 5 -----
+ drivers/net/wireless/intel/iwlwifi/dvm/tt.c | 4 ----
+ drivers/net/wireless/intel/iwlwifi/dvm/tt.h | 4 ----
+ drivers/net/wireless/intel/iwlwifi/dvm/tx.c | 5 -----
+ drivers/net/wireless/intel/iwlwifi/dvm/ucode.c | 5 -----
+ drivers/net/wireless/intel/iwlwifi/fw/img.c | 5 -----
+ drivers/net/wireless/intel/iwlwifi/iwl-debug.h | 5 -----
+ drivers/net/wireless/intel/iwlwifi/iwl-devtrace-data.h | 5 -----
+ drivers/net/wireless/intel/iwlwifi/iwl-devtrace-io.h | 5 -----
+ drivers/net/wireless/intel/iwlwifi/iwl-devtrace-iwlwifi.h | 5 -----
+ drivers/net/wireless/intel/iwlwifi/iwl-devtrace-msg.h | 5 -----
+ drivers/net/wireless/intel/iwlwifi/iwl-devtrace-ucode.h | 5 -----
+ drivers/net/wireless/intel/iwlwifi/iwl-devtrace.c | 5 -----
+ drivers/net/wireless/intel/iwlwifi/iwl-devtrace.h | 5 -----
+ drivers/net/wireless/intel/iwlwifi/mvm/rs.c | 5 -----
+ drivers/net/wireless/intel/iwlwifi/mvm/rs.h | 5 -----
+ 35 files changed, 169 deletions(-)
+
+diff --git a/drivers/net/wireless/intel/iwlwifi/cfg/1000.c b/drivers/net/wireless/intel/iwlwifi/cfg/1000.c
+index 44c4fe9753901..116defb15afbd 100644
+--- a/drivers/net/wireless/intel/iwlwifi/cfg/1000.c
++++ b/drivers/net/wireless/intel/iwlwifi/cfg/1000.c
+@@ -3,11 +3,6 @@
+ *
+ * Copyright(c) 2008 - 2014 Intel Corporation. All rights reserved.
+ * Copyright(c) 2018 - 2020 Intel Corporation
+- *
+- * Contact Information:
+- * Intel Linux Wireless <linuxwifi@intel.com>
+- * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
+- *
+ *****************************************************************************/
+
+ #include <linux/module.h>
+diff --git a/drivers/net/wireless/intel/iwlwifi/cfg/2000.c b/drivers/net/wireless/intel/iwlwifi/cfg/2000.c
+index df6ac00340b26..ab2038a3fbe21 100644
+--- a/drivers/net/wireless/intel/iwlwifi/cfg/2000.c
++++ b/drivers/net/wireless/intel/iwlwifi/cfg/2000.c
+@@ -3,11 +3,6 @@
+ *
+ * Copyright(c) 2008 - 2014 Intel Corporation. All rights reserved.
+ * Copyright(c) 2018 - 2020 Intel Corporation
+- *
+- * Contact Information:
+- * Intel Linux Wireless <linuxwifi@intel.com>
+- * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
+- *
+ *****************************************************************************/
+
+ #include <linux/module.h>
+diff --git a/drivers/net/wireless/intel/iwlwifi/cfg/5000.c b/drivers/net/wireless/intel/iwlwifi/cfg/5000.c
+index 6cdd7d983bdae..e2e23d2bc1fe5 100644
+--- a/drivers/net/wireless/intel/iwlwifi/cfg/5000.c
++++ b/drivers/net/wireless/intel/iwlwifi/cfg/5000.c
+@@ -3,11 +3,6 @@
+ *
+ * Copyright(c) 2007 - 2014 Intel Corporation. All rights reserved.
+ * Copyright(c) 2018 - 2020 Intel Corporation
+- *
+- * Contact Information:
+- * Intel Linux Wireless <linuxwifi@intel.com>
+- * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
+- *
+ *****************************************************************************/
+
+ #include <linux/module.h>
+diff --git a/drivers/net/wireless/intel/iwlwifi/cfg/6000.c b/drivers/net/wireless/intel/iwlwifi/cfg/6000.c
+index 541a3ec857770..20929e59c2f4d 100644
+--- a/drivers/net/wireless/intel/iwlwifi/cfg/6000.c
++++ b/drivers/net/wireless/intel/iwlwifi/cfg/6000.c
+@@ -3,11 +3,6 @@
+ *
+ * Copyright(c) 2008 - 2014 Intel Corporation. All rights reserved.
+ * Copyright(c) 2018 - 2020 Intel Corporation
+- *
+- * Contact Information:
+- * Intel Linux Wireless <linuxwifi@intel.com>
+- * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
+- *
+ *****************************************************************************/
+
+ #include <linux/module.h>
+diff --git a/drivers/net/wireless/intel/iwlwifi/dvm/debugfs.c b/drivers/net/wireless/intel/iwlwifi/dvm/debugfs.c
+index 9110492018387..b246dbd371b35 100644
+--- a/drivers/net/wireless/intel/iwlwifi/dvm/debugfs.c
++++ b/drivers/net/wireless/intel/iwlwifi/dvm/debugfs.c
+@@ -3,10 +3,6 @@
+ *
+ * Copyright(c) 2008 - 2014 Intel Corporation. All rights reserved.
+ * Copyright (C) 2018 Intel Corporation
+- *
+- * Contact Information:
+- * Intel Linux Wireless <linuxwifi@intel.com>
+- * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
+ *****************************************************************************/
+
+ #include <linux/slab.h>
+diff --git a/drivers/net/wireless/intel/iwlwifi/dvm/dev.h b/drivers/net/wireless/intel/iwlwifi/dvm/dev.h
+index 4bd792c06ff6e..bbd5740912012 100644
+--- a/drivers/net/wireless/intel/iwlwifi/dvm/dev.h
++++ b/drivers/net/wireless/intel/iwlwifi/dvm/dev.h
+@@ -2,11 +2,6 @@
+ /******************************************************************************
+ *
+ * Copyright(c) 2003 - 2014, 2020 Intel Corporation. All rights reserved.
+- *
+- * Contact Information:
+- * Intel Linux Wireless <linuxwifi@intel.com>
+- * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
+- *
+ *****************************************************************************/
+ /*
+ * Please use this file (dev.h) for driver implementation definitions.
+diff --git a/drivers/net/wireless/intel/iwlwifi/dvm/devices.c b/drivers/net/wireless/intel/iwlwifi/dvm/devices.c
+index c3e25885d1943..39e40901fa464 100644
+--- a/drivers/net/wireless/intel/iwlwifi/dvm/devices.c
++++ b/drivers/net/wireless/intel/iwlwifi/dvm/devices.c
+@@ -3,11 +3,6 @@
+ *
+ * Copyright(c) 2008 - 2014 Intel Corporation. All rights reserved.
+ * Copyright (C) 2019 Intel Corporation
+- *
+- * Contact Information:
+- * Intel Linux Wireless <linuxwifi@intel.com>
+- * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
+- *
+ *****************************************************************************/
+
+ #include <linux/units.h>
+diff --git a/drivers/net/wireless/intel/iwlwifi/dvm/led.c b/drivers/net/wireless/intel/iwlwifi/dvm/led.c
+index e8a4d604b9106..71f67a019cf60 100644
+--- a/drivers/net/wireless/intel/iwlwifi/dvm/led.c
++++ b/drivers/net/wireless/intel/iwlwifi/dvm/led.c
+@@ -3,11 +3,6 @@
+ *
+ * Copyright(c) 2003 - 2014 Intel Corporation. All rights reserved.
+ * Copyright (C) 2019 Intel Corporation
+- *
+- * Contact Information:
+- * Intel Linux Wireless <linuxwifi@intel.com>
+- * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
+- *
+ *****************************************************************************/
+
+
+diff --git a/drivers/net/wireless/intel/iwlwifi/dvm/led.h b/drivers/net/wireless/intel/iwlwifi/dvm/led.h
+index 6fe20180dc87c..5038fc378a1f7 100644
+--- a/drivers/net/wireless/intel/iwlwifi/dvm/led.h
++++ b/drivers/net/wireless/intel/iwlwifi/dvm/led.h
+@@ -2,11 +2,6 @@
+ /******************************************************************************
+ *
+ * Copyright(c) 2003 - 2014 Intel Corporation. All rights reserved.
+- *
+- * Contact Information:
+- * Intel Linux Wireless <linuxwifi@intel.com>
+- * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
+- *
+ *****************************************************************************/
+
+ #ifndef __iwl_leds_h__
+diff --git a/drivers/net/wireless/intel/iwlwifi/dvm/lib.c b/drivers/net/wireless/intel/iwlwifi/dvm/lib.c
+index 3b937a7dd4032..40d790b36d85b 100644
+--- a/drivers/net/wireless/intel/iwlwifi/dvm/lib.c
++++ b/drivers/net/wireless/intel/iwlwifi/dvm/lib.c
+@@ -2,11 +2,6 @@
+ /******************************************************************************
+ *
+ * Copyright(c) 2008 - 2014 Intel Corporation. All rights reserved.
+- *
+- * Contact Information:
+- * Intel Linux Wireless <linuxwifi@intel.com>
+- * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
+- *
+ *****************************************************************************/
+ #include <linux/etherdevice.h>
+ #include <linux/kernel.h>
+diff --git a/drivers/net/wireless/intel/iwlwifi/dvm/mac80211.c b/drivers/net/wireless/intel/iwlwifi/dvm/mac80211.c
+index 90fe4adca4926..e8bd4f0e3d2dc 100644
+--- a/drivers/net/wireless/intel/iwlwifi/dvm/mac80211.c
++++ b/drivers/net/wireless/intel/iwlwifi/dvm/mac80211.c
+@@ -6,11 +6,6 @@
+ *
+ * Portions of this file are derived from the ipw3945 project, as well
+ * as portions of the ieee80211 subsystem header files.
+- *
+- * Contact Information:
+- * Intel Linux Wireless <linuxwifi@intel.com>
+- * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
+- *
+ *****************************************************************************/
+ #include <linux/kernel.h>
+ #include <linux/module.h>
+diff --git a/drivers/net/wireless/intel/iwlwifi/dvm/main.c b/drivers/net/wireless/intel/iwlwifi/dvm/main.c
+index cc7b69fd14d37..353f660a84928 100644
+--- a/drivers/net/wireless/intel/iwlwifi/dvm/main.c
++++ b/drivers/net/wireless/intel/iwlwifi/dvm/main.c
+@@ -6,11 +6,6 @@
+ *
+ * Portions of this file are derived from the ipw3945 project, as well
+ * as portions of the ieee80211 subsystem header files.
+- *
+- * Contact Information:
+- * Intel Linux Wireless <linuxwifi@intel.com>
+- * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
+- *
+ *****************************************************************************/
+
+ #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+diff --git a/drivers/net/wireless/intel/iwlwifi/dvm/power.c b/drivers/net/wireless/intel/iwlwifi/dvm/power.c
+index 93ef023905c96..6d16a7105656c 100644
+--- a/drivers/net/wireless/intel/iwlwifi/dvm/power.c
++++ b/drivers/net/wireless/intel/iwlwifi/dvm/power.c
+@@ -6,10 +6,6 @@
+ *
+ * Portions of this file are derived from the ipw3945 project, as well
+ * as portions of the ieee80211 subsystem header files.
+- *
+- * Contact Information:
+- * Intel Linux Wireless <linuxwifi@intel.com>
+- * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
+ *****************************************************************************/
+
+
+diff --git a/drivers/net/wireless/intel/iwlwifi/dvm/power.h b/drivers/net/wireless/intel/iwlwifi/dvm/power.h
+index 3f8db1fc4b590..f38201ce1e991 100644
+--- a/drivers/net/wireless/intel/iwlwifi/dvm/power.h
++++ b/drivers/net/wireless/intel/iwlwifi/dvm/power.h
+@@ -5,10 +5,6 @@
+ *
+ * Portions of this file are derived from the ipw3945 project, as well
+ * as portions of the ieee80211 subsystem header files.
+- *
+- * Contact Information:
+- * Intel Linux Wireless <linuxwifi@intel.com>
+- * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
+ *****************************************************************************/
+ #ifndef __iwl_power_setting_h__
+ #define __iwl_power_setting_h__
+diff --git a/drivers/net/wireless/intel/iwlwifi/dvm/rs.c b/drivers/net/wireless/intel/iwlwifi/dvm/rs.c
+index 548540dd0c0f7..b7c8b209bfea4 100644
+--- a/drivers/net/wireless/intel/iwlwifi/dvm/rs.c
++++ b/drivers/net/wireless/intel/iwlwifi/dvm/rs.c
+@@ -3,11 +3,6 @@
+ *
+ * Copyright(c) 2005 - 2014 Intel Corporation. All rights reserved.
+ * Copyright (C) 2019 - 2020 Intel Corporation
+- *
+- * Contact Information:
+- * Intel Linux Wireless <linuxwifi@intel.com>
+- * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
+- *
+ *****************************************************************************/
+ #include <linux/kernel.h>
+ #include <linux/skbuff.h>
+diff --git a/drivers/net/wireless/intel/iwlwifi/dvm/rs.h b/drivers/net/wireless/intel/iwlwifi/dvm/rs.h
+index 68a840d739e83..0b47f1993c5db 100644
+--- a/drivers/net/wireless/intel/iwlwifi/dvm/rs.h
++++ b/drivers/net/wireless/intel/iwlwifi/dvm/rs.h
+@@ -2,11 +2,6 @@
+ /******************************************************************************
+ *
+ * Copyright(c) 2003 - 2014 Intel Corporation. All rights reserved.
+- *
+- * Contact Information:
+- * Intel Linux Wireless <linuxwifi@intel.com>
+- * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
+- *
+ *****************************************************************************/
+
+ #ifndef __iwl_agn_rs_h__
+diff --git a/drivers/net/wireless/intel/iwlwifi/dvm/rx.c b/drivers/net/wireless/intel/iwlwifi/dvm/rx.c
+index 3cd7b423c588d..db0c41bbeb0e1 100644
+--- a/drivers/net/wireless/intel/iwlwifi/dvm/rx.c
++++ b/drivers/net/wireless/intel/iwlwifi/dvm/rx.c
+@@ -7,11 +7,6 @@
+ *
+ * Portions of this file are derived from the ipw3945 project, as well
+ * as portionhelp of the ieee80211 subsystem header files.
+- *
+- * Contact Information:
+- * Intel Linux Wireless <linuxwifi@intel.com>
+- * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
+- *
+ *****************************************************************************/
+
+ #include <linux/etherdevice.h>
+diff --git a/drivers/net/wireless/intel/iwlwifi/dvm/rxon.c b/drivers/net/wireless/intel/iwlwifi/dvm/rxon.c
+index 12a3d464ae640..70338bc7bb540 100644
+--- a/drivers/net/wireless/intel/iwlwifi/dvm/rxon.c
++++ b/drivers/net/wireless/intel/iwlwifi/dvm/rxon.c
+@@ -3,11 +3,6 @@
+ *
+ * Copyright(c) 2003 - 2014 Intel Corporation. All rights reserved.
+ * Copyright(c) 2015 Intel Deutschland GmbH
+- *
+- * Contact Information:
+- * Intel Linux Wireless <linuxwifi@intel.com>
+- * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
+- *
+ *****************************************************************************/
+
+ #include <linux/etherdevice.h>
+diff --git a/drivers/net/wireless/intel/iwlwifi/dvm/scan.c b/drivers/net/wireless/intel/iwlwifi/dvm/scan.c
+index c4ecf6ed21860..2d38227dfdd20 100644
+--- a/drivers/net/wireless/intel/iwlwifi/dvm/scan.c
++++ b/drivers/net/wireless/intel/iwlwifi/dvm/scan.c
+@@ -3,10 +3,6 @@
+ *
+ * Copyright(c) 2008 - 2014 Intel Corporation. All rights reserved.
+ * Copyright(c) 2018 Intel Corporation
+- *
+- * Contact Information:
+- * Intel Linux Wireless <linuxwifi@intel.com>
+- * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
+ *****************************************************************************/
+ #include <linux/slab.h>
+ #include <linux/types.h>
+diff --git a/drivers/net/wireless/intel/iwlwifi/dvm/sta.c b/drivers/net/wireless/intel/iwlwifi/dvm/sta.c
+index 7c3168145e58a..03ceb0615368b 100644
+--- a/drivers/net/wireless/intel/iwlwifi/dvm/sta.c
++++ b/drivers/net/wireless/intel/iwlwifi/dvm/sta.c
+@@ -5,11 +5,6 @@
+ *
+ * Portions of this file are derived from the ipw3945 project, as well
+ * as portions of the ieee80211 subsystem header files.
+- *
+- * Contact Information:
+- * Intel Linux Wireless <linuxwifi@intel.com>
+- * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
+- *
+ *****************************************************************************/
+ #include <linux/etherdevice.h>
+ #include <net/mac80211.h>
+diff --git a/drivers/net/wireless/intel/iwlwifi/dvm/tt.c b/drivers/net/wireless/intel/iwlwifi/dvm/tt.c
+index 2684a924ba574..43e8d04d5a8b2 100644
+--- a/drivers/net/wireless/intel/iwlwifi/dvm/tt.c
++++ b/drivers/net/wireless/intel/iwlwifi/dvm/tt.c
+@@ -6,10 +6,6 @@
+ *
+ * Portions of this file are derived from the ipw3945 project, as well
+ * as portions of the ieee80211 subsystem header files.
+- *
+- * Contact Information:
+- * Intel Linux Wireless <linuxwifi@intel.com>
+- * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
+ *****************************************************************************/
+
+
+diff --git a/drivers/net/wireless/intel/iwlwifi/dvm/tt.h b/drivers/net/wireless/intel/iwlwifi/dvm/tt.h
+index 3b0ff458a158b..7ace052fc78a4 100644
+--- a/drivers/net/wireless/intel/iwlwifi/dvm/tt.h
++++ b/drivers/net/wireless/intel/iwlwifi/dvm/tt.h
+@@ -5,10 +5,6 @@
+ *
+ * Portions of this file are derived from the ipw3945 project, as well
+ * as portions of the ieee80211 subsystem header files.
+- *
+- * Contact Information:
+- * Intel Linux Wireless <linuxwifi@intel.com>
+- * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
+ *****************************************************************************/
+ #ifndef __iwl_tt_setting_h__
+ #define __iwl_tt_setting_h__
+diff --git a/drivers/net/wireless/intel/iwlwifi/dvm/tx.c b/drivers/net/wireless/intel/iwlwifi/dvm/tx.c
+index 847b8e07f81c5..60a7b61d59aa3 100644
+--- a/drivers/net/wireless/intel/iwlwifi/dvm/tx.c
++++ b/drivers/net/wireless/intel/iwlwifi/dvm/tx.c
+@@ -3,11 +3,6 @@
+ *
+ * Copyright(c) 2008 - 2014 Intel Corporation. All rights reserved.
+ * Copyright (C) 2019 Intel Corporation
+- *
+- * Contact Information:
+- * Intel Linux Wireless <linuxwifi@intel.com>
+- * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
+- *
+ *****************************************************************************/
+
+ #include <linux/kernel.h>
+diff --git a/drivers/net/wireless/intel/iwlwifi/dvm/ucode.c b/drivers/net/wireless/intel/iwlwifi/dvm/ucode.c
+index 24194c7912181..4b27a53d0bb4a 100644
+--- a/drivers/net/wireless/intel/iwlwifi/dvm/ucode.c
++++ b/drivers/net/wireless/intel/iwlwifi/dvm/ucode.c
+@@ -3,11 +3,6 @@
+ *
+ * Copyright(c) 2008 - 2014 Intel Corporation. All rights reserved.
+ * Copyright(c) 2015 Intel Deutschland GmbH
+- *
+- * Contact Information:
+- * Intel Linux Wireless <linuxwifi@intel.com>
+- * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
+- *
+ *****************************************************************************/
+
+ #include <linux/kernel.h>
+diff --git a/drivers/net/wireless/intel/iwlwifi/fw/img.c b/drivers/net/wireless/intel/iwlwifi/fw/img.c
+index c2a4e60518bc7..5755e179066ae 100644
+--- a/drivers/net/wireless/intel/iwlwifi/fw/img.c
++++ b/drivers/net/wireless/intel/iwlwifi/fw/img.c
+@@ -18,11 +18,6 @@
+ *
+ * The full GNU General Public License is included in this distribution
+ * in the file called COPYING.
+- *
+- * Contact Information:
+- * Intel Linux Wireless <linuxwifi@intel.com>
+- * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
+- *
+ * BSD LICENSE
+ *
+ * Copyright(c) 2019 - 2020 Intel Corporation
+diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-debug.h b/drivers/net/wireless/intel/iwlwifi/iwl-debug.h
+index 528eba441926d..8db7aeddfd057 100644
+--- a/drivers/net/wireless/intel/iwlwifi/iwl-debug.h
++++ b/drivers/net/wireless/intel/iwlwifi/iwl-debug.h
+@@ -5,11 +5,6 @@
+ * Copyright(c) 2018 - 2020 Intel Corporation
+ *
+ * Portions of this file are derived from the ipw3945 project.
+- *
+- * Contact Information:
+- * Intel Linux Wireless <linuxwifi@intel.com>
+- * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
+- *
+ *****************************************************************************/
+
+ #ifndef __iwl_debug_h__
+diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-devtrace-data.h b/drivers/net/wireless/intel/iwlwifi/iwl-devtrace-data.h
+index 1bc6ecc321404..347fd95c4e3a5 100644
+--- a/drivers/net/wireless/intel/iwlwifi/iwl-devtrace-data.h
++++ b/drivers/net/wireless/intel/iwlwifi/iwl-devtrace-data.h
+@@ -4,11 +4,6 @@
+ * Copyright(c) 2009 - 2014 Intel Corporation. All rights reserved.
+ * Copyright(c) 2015 Intel Deutschland GmbH
+ * Copyright(c) 2018 - 2019 Intel Corporation
+- *
+- * Contact Information:
+- * Intel Linux Wireless <linuxwifi@intel.com>
+- * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
+- *
+ *****************************************************************************/
+
+ #if !defined(__IWLWIFI_DEVICE_TRACE_DATA) || defined(TRACE_HEADER_MULTI_READ)
+diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-devtrace-io.h b/drivers/net/wireless/intel/iwlwifi/iwl-devtrace-io.h
+index a57019241a780..0af9d8362c5b8 100644
+--- a/drivers/net/wireless/intel/iwlwifi/iwl-devtrace-io.h
++++ b/drivers/net/wireless/intel/iwlwifi/iwl-devtrace-io.h
+@@ -3,11 +3,6 @@
+ *
+ * Copyright(c) 2009 - 2014 Intel Corporation. All rights reserved.
+ * Copyright(c) 2016-2017 Intel Deutschland GmbH
+- *
+- * Contact Information:
+- * Intel Linux Wireless <linuxwifi@intel.com>
+- * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
+- *
+ *****************************************************************************/
+
+ #if !defined(__IWLWIFI_DEVICE_TRACE_IO) || defined(TRACE_HEADER_MULTI_READ)
+diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-devtrace-iwlwifi.h b/drivers/net/wireless/intel/iwlwifi/iwl-devtrace-iwlwifi.h
+index 72ca882daed5e..46ed723f138a6 100644
+--- a/drivers/net/wireless/intel/iwlwifi/iwl-devtrace-iwlwifi.h
++++ b/drivers/net/wireless/intel/iwlwifi/iwl-devtrace-iwlwifi.h
+@@ -5,11 +5,6 @@
+ * Copyright(c) 2015 Intel Mobile Communications GmbH
+ * Copyright(c) 2016 - 2017 Intel Deutschland GmbH
+ * Copyright(c) 2018 Intel Corporation
+- *
+- * Contact Information:
+- * Intel Linux Wireless <linuxwifi@intel.com>
+- * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
+- *
+ *****************************************************************************/
+
+ #if !defined(__IWLWIFI_DEVICE_TRACE_IWLWIFI) || defined(TRACE_HEADER_MULTI_READ)
+diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-devtrace-msg.h b/drivers/net/wireless/intel/iwlwifi/iwl-devtrace-msg.h
+index d0467da5af034..7dd70011fd1ef 100644
+--- a/drivers/net/wireless/intel/iwlwifi/iwl-devtrace-msg.h
++++ b/drivers/net/wireless/intel/iwlwifi/iwl-devtrace-msg.h
+@@ -2,11 +2,6 @@
+ /******************************************************************************
+ *
+ * Copyright(c) 2009 - 2014 Intel Corporation. All rights reserved.
+- *
+- * Contact Information:
+- * Intel Linux Wireless <linuxwifi@intel.com>
+- * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
+- *
+ *****************************************************************************/
+
+ #if !defined(__IWLWIFI_DEVICE_TRACE_MSG) || defined(TRACE_HEADER_MULTI_READ)
+diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-devtrace-ucode.h b/drivers/net/wireless/intel/iwlwifi/iwl-devtrace-ucode.h
+index 2228faefffbca..3ec0205ac9f90 100644
+--- a/drivers/net/wireless/intel/iwlwifi/iwl-devtrace-ucode.h
++++ b/drivers/net/wireless/intel/iwlwifi/iwl-devtrace-ucode.h
+@@ -2,11 +2,6 @@
+ /******************************************************************************
+ *
+ * Copyright(c) 2009 - 2014 Intel Corporation. All rights reserved.
+- *
+- * Contact Information:
+- * Intel Linux Wireless <linuxwifi@intel.com>
+- * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
+- *
+ *****************************************************************************/
+
+ #if !defined(__IWLWIFI_DEVICE_TRACE_UCODE) || defined(TRACE_HEADER_MULTI_READ)
+diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-devtrace.c b/drivers/net/wireless/intel/iwlwifi/iwl-devtrace.c
+index b5037db0c3817..999b7c652289d 100644
+--- a/drivers/net/wireless/intel/iwlwifi/iwl-devtrace.c
++++ b/drivers/net/wireless/intel/iwlwifi/iwl-devtrace.c
+@@ -3,11 +3,6 @@
+ *
+ * Copyright(c) 2009 - 2014 Intel Corporation. All rights reserved.
+ * Copyright (C) 2018 Intel Corporation
+- *
+- * Contact Information:
+- * Intel Linux Wireless <linuxwifi@intel.com>
+- * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
+- *
+ *****************************************************************************/
+
+ #include <linux/module.h>
+diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-devtrace.h b/drivers/net/wireless/intel/iwlwifi/iwl-devtrace.h
+index fc8bc212ee847..1455b578358bf 100644
+--- a/drivers/net/wireless/intel/iwlwifi/iwl-devtrace.h
++++ b/drivers/net/wireless/intel/iwlwifi/iwl-devtrace.h
+@@ -4,11 +4,6 @@
+ * Copyright(c) 2009 - 2014 Intel Corporation. All rights reserved.
+ * Copyright(C) 2016 Intel Deutschland GmbH
+ * Copyright(c) 2018 Intel Corporation
+- *
+- * Contact Information:
+- * Intel Linux Wireless <linuxwifi@intel.com>
+- * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
+- *
+ *****************************************************************************/
+
+ #ifndef __IWLWIFI_DEVICE_TRACE
+diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/rs.c b/drivers/net/wireless/intel/iwlwifi/mvm/rs.c
+index b97708cb869d5..c66aa61b4ba31 100644
+--- a/drivers/net/wireless/intel/iwlwifi/mvm/rs.c
++++ b/drivers/net/wireless/intel/iwlwifi/mvm/rs.c
+@@ -4,11 +4,6 @@
+ * Copyright(c) 2005 - 2014, 2018 - 2021 Intel Corporation. All rights reserved.
+ * Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH
+ * Copyright(c) 2016 - 2017 Intel Deutschland GmbH
+- *
+- * Contact Information:
+- * Intel Linux Wireless <linuxwifi@intel.com>
+- * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
+- *
+ *****************************************************************************/
+ #include <linux/kernel.h>
+ #include <linux/skbuff.h>
+diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/rs.h b/drivers/net/wireless/intel/iwlwifi/mvm/rs.h
+index 32104c9f8f5ee..3e206df57347c 100644
+--- a/drivers/net/wireless/intel/iwlwifi/mvm/rs.h
++++ b/drivers/net/wireless/intel/iwlwifi/mvm/rs.h
+@@ -5,11 +5,6 @@
+ * Copyright(c) 2015 Intel Mobile Communications GmbH
+ * Copyright(c) 2017 Intel Deutschland GmbH
+ * Copyright(c) 2018 - 2019 Intel Corporation
+- *
+- * Contact Information:
+- * Intel Linux Wireless <linuxwifi@intel.com>
+- * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
+- *
+ *****************************************************************************/
+
+ #ifndef __rs_h__
+--
+2.42.0
+
--- /dev/null
+From 5b33040c9dd2e8f375c80bc63cde7c7141a6957c Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 22 Sep 2023 21:28:34 +0200
+Subject: leds: pwm: Don't disable the PWM when the LED should be off
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Uwe Kleine-König <u.kleine-koenig@pengutronix.de>
+
+[ Upstream commit 76fe464c8e64e71b2e4af11edeef0e5d85eeb6aa ]
+
+Disabling a PWM (i.e. calling pwm_apply_state with .enabled = false)
+gives no guarantees what the PWM output does. It might freeze where it
+currently is, or go in a High-Z state or drive the active or inactive
+state, it might even continue to toggle.
+
+To ensure that the LED gets really disabled, don't disable the PWM even
+when .duty_cycle is zero.
+
+This fixes disabling a leds-pwm LED on i.MX28. The PWM on this SoC is
+one of those that freezes its output on disable, so if you disable an
+LED that is full on, it stays on. If you disable a LED with half
+brightness it goes off in 50% of the cases and full on in the other 50%.
+
+Fixes: 41c42ff5dbe2 ("leds: simple driver for pwm driven LEDs")
+Reported-by: Rogan Dawes <rogan@dawes.za.net>
+Reported-by: Fabio Estevam <festevam@denx.de>
+Signed-off-by: Uwe Kleine-König <u.kleine-koenig@pengutronix.de>
+Reviewed-by: Fabio Estevam <festevam@denx.de>
+Link: https://lore.kernel.org/r/20230922192834.1695727-1-u.kleine-koenig@pengutronix.de
+Signed-off-by: Lee Jones <lee@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/leds/leds-pwm.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/drivers/leds/leds-pwm.c b/drivers/leds/leds-pwm.c
+index cc892ecd52408..6d3e33e8b5f91 100644
+--- a/drivers/leds/leds-pwm.c
++++ b/drivers/leds/leds-pwm.c
+@@ -53,7 +53,7 @@ static int led_pwm_set(struct led_classdev *led_cdev,
+ duty = led_dat->pwmstate.period - duty;
+
+ led_dat->pwmstate.duty_cycle = duty;
+- led_dat->pwmstate.enabled = duty > 0;
++ led_dat->pwmstate.enabled = true;
+ return pwm_apply_state(led_dat->pwm, &led_dat->pwmstate);
+ }
+
+--
+2.42.0
+
--- /dev/null
+From cd739f47f7fac08a46e75d1aab0cd73eb18763b1 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sat, 23 Sep 2023 09:15:38 +0200
+Subject: leds: trigger: ledtrig-cpu:: Fix 'output may be truncated' issue for
+ 'cpu'
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Christophe JAILLET <christophe.jaillet@wanadoo.fr>
+
+[ Upstream commit ff50f53276131a3059e8307d11293af388ed2bcd ]
+
+In order to teach the compiler that 'trig->name' will never be truncated,
+we need to tell it that 'cpu' is not negative.
+
+When building with W=1, this fixes the following warnings:
+
+ drivers/leds/trigger/ledtrig-cpu.c: In function ‘ledtrig_cpu_init’:
+ drivers/leds/trigger/ledtrig-cpu.c:155:56: error: ‘%d’ directive output may be truncated writing between 1 and 11 bytes into a region of size 5 [-Werror=format-truncation=]
+ 155 | snprintf(trig->name, MAX_NAME_LEN, "cpu%d", cpu);
+ | ^~
+ drivers/leds/trigger/ledtrig-cpu.c:155:52: note: directive argument in the range [-2147483648, 7]
+ 155 | snprintf(trig->name, MAX_NAME_LEN, "cpu%d", cpu);
+ | ^~~~~~~
+ drivers/leds/trigger/ledtrig-cpu.c:155:17: note: ‘snprintf’ output between 5 and 15 bytes into a destination of size 8
+ 155 | snprintf(trig->name, MAX_NAME_LEN, "cpu%d", cpu);
+ | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Fixes: 8f88731d052d ("led-triggers: create a trigger for CPU activity")
+Signed-off-by: Christophe JAILLET <christophe.jaillet@wanadoo.fr>
+Link: https://lore.kernel.org/r/3f4be7a99933cf8566e630da54f6ab913caac432.1695453322.git.christophe.jaillet@wanadoo.fr
+Signed-off-by: Lee Jones <lee@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/leds/trigger/ledtrig-cpu.c | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/drivers/leds/trigger/ledtrig-cpu.c b/drivers/leds/trigger/ledtrig-cpu.c
+index 8af4f9bb9cde8..05848a2fecff6 100644
+--- a/drivers/leds/trigger/ledtrig-cpu.c
++++ b/drivers/leds/trigger/ledtrig-cpu.c
+@@ -130,7 +130,7 @@ static int ledtrig_prepare_down_cpu(unsigned int cpu)
+
+ static int __init ledtrig_cpu_init(void)
+ {
+- int cpu;
++ unsigned int cpu;
+ int ret;
+
+ /* Supports up to 9999 cpu cores */
+@@ -152,7 +152,7 @@ static int __init ledtrig_cpu_init(void)
+ if (cpu >= 8)
+ continue;
+
+- snprintf(trig->name, MAX_NAME_LEN, "cpu%d", cpu);
++ snprintf(trig->name, MAX_NAME_LEN, "cpu%u", cpu);
+
+ led_trigger_register_simple(trig->name, &trig->_trig);
+ }
+--
+2.42.0
+
--- /dev/null
+From 6782733af78201d9e6cd0fd38d22a6037748f07e Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 18 Sep 2023 18:11:01 +0200
+Subject: leds: turris-omnia: Do not use SMBUS calls
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Marek Behún <kabel@kernel.org>
+
+[ Upstream commit 6de283b96b31b4890e3ee8c86caca2a3a30d1011 ]
+
+The leds-turris-omnia driver uses three function for I2C access:
+- i2c_smbus_write_byte_data() and i2c_smbus_read_byte_data(), which
+ cause an emulated SMBUS transfer,
+- i2c_master_send(), which causes an ordinary I2C transfer.
+
+The Turris Omnia MCU LED controller is not semantically SMBUS, it
+operates as a simple I2C bus. It does not implement any of the SMBUS
+specific features, like PEC, or procedure calls, or anything. Moreover
+the I2C controller driver also does not implement SMBUS, and so the
+emulated SMBUS procedure from drivers/i2c/i2c-core-smbus.c is used for
+the SMBUS calls, which gives an unnecessary overhead.
+
+When I first wrote the driver, I was unaware of these facts, and I
+simply used the first function that worked.
+
+Drop the I2C SMBUS calls and instead use simple I2C transfers.
+
+Fixes: 089381b27abe ("leds: initial support for Turris Omnia LEDs")
+Signed-off-by: Marek Behún <kabel@kernel.org>
+Link: https://lore.kernel.org/r/20230918161104.20860-2-kabel@kernel.org
+Signed-off-by: Lee Jones <lee@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/leds/leds-turris-omnia.c | 54 +++++++++++++++++++++++++-------
+ 1 file changed, 42 insertions(+), 12 deletions(-)
+
+diff --git a/drivers/leds/leds-turris-omnia.c b/drivers/leds/leds-turris-omnia.c
+index c9e7c467e5acd..ebc6cf3ce3cad 100644
+--- a/drivers/leds/leds-turris-omnia.c
++++ b/drivers/leds/leds-turris-omnia.c
+@@ -2,7 +2,7 @@
+ /*
+ * CZ.NIC's Turris Omnia LEDs driver
+ *
+- * 2020 by Marek Behún <kabel@kernel.org>
++ * 2020, 2023 by Marek Behún <kabel@kernel.org>
+ */
+
+ #include <linux/i2c.h>
+@@ -41,6 +41,37 @@ struct omnia_leds {
+ struct omnia_led leds[];
+ };
+
++static int omnia_cmd_write_u8(const struct i2c_client *client, u8 cmd, u8 val)
++{
++ u8 buf[2] = { cmd, val };
++
++ return i2c_master_send(client, buf, sizeof(buf));
++}
++
++static int omnia_cmd_read_u8(const struct i2c_client *client, u8 cmd)
++{
++ struct i2c_msg msgs[2];
++ u8 reply;
++ int ret;
++
++ msgs[0].addr = client->addr;
++ msgs[0].flags = 0;
++ msgs[0].len = 1;
++ msgs[0].buf = &cmd;
++ msgs[1].addr = client->addr;
++ msgs[1].flags = I2C_M_RD;
++ msgs[1].len = 1;
++ msgs[1].buf = &reply;
++
++ ret = i2c_transfer(client->adapter, msgs, ARRAY_SIZE(msgs));
++ if (likely(ret == ARRAY_SIZE(msgs)))
++ return reply;
++ else if (ret < 0)
++ return ret;
++ else
++ return -EIO;
++}
++
+ static int omnia_led_brightness_set_blocking(struct led_classdev *cdev,
+ enum led_brightness brightness)
+ {
+@@ -64,7 +95,7 @@ static int omnia_led_brightness_set_blocking(struct led_classdev *cdev,
+ if (buf[2] || buf[3] || buf[4])
+ state |= CMD_LED_STATE_ON;
+
+- ret = i2c_smbus_write_byte_data(leds->client, CMD_LED_STATE, state);
++ ret = omnia_cmd_write_u8(leds->client, CMD_LED_STATE, state);
+ if (ret >= 0 && (state & CMD_LED_STATE_ON))
+ ret = i2c_master_send(leds->client, buf, 5);
+
+@@ -114,9 +145,9 @@ static int omnia_led_register(struct i2c_client *client, struct omnia_led *led,
+ cdev->brightness_set_blocking = omnia_led_brightness_set_blocking;
+
+ /* put the LED into software mode */
+- ret = i2c_smbus_write_byte_data(client, CMD_LED_MODE,
+- CMD_LED_MODE_LED(led->reg) |
+- CMD_LED_MODE_USER);
++ ret = omnia_cmd_write_u8(client, CMD_LED_MODE,
++ CMD_LED_MODE_LED(led->reg) |
++ CMD_LED_MODE_USER);
+ if (ret < 0) {
+ dev_err(dev, "Cannot set LED %pOF to software mode: %i\n", np,
+ ret);
+@@ -124,8 +155,8 @@ static int omnia_led_register(struct i2c_client *client, struct omnia_led *led,
+ }
+
+ /* disable the LED */
+- ret = i2c_smbus_write_byte_data(client, CMD_LED_STATE,
+- CMD_LED_STATE_LED(led->reg));
++ ret = omnia_cmd_write_u8(client, CMD_LED_STATE,
++ CMD_LED_STATE_LED(led->reg));
+ if (ret < 0) {
+ dev_err(dev, "Cannot set LED %pOF brightness: %i\n", np, ret);
+ return ret;
+@@ -158,7 +189,7 @@ static ssize_t brightness_show(struct device *dev, struct device_attribute *a,
+ struct i2c_client *client = to_i2c_client(dev);
+ int ret;
+
+- ret = i2c_smbus_read_byte_data(client, CMD_LED_GET_BRIGHTNESS);
++ ret = omnia_cmd_read_u8(client, CMD_LED_GET_BRIGHTNESS);
+
+ if (ret < 0)
+ return ret;
+@@ -179,8 +210,7 @@ static ssize_t brightness_store(struct device *dev, struct device_attribute *a,
+ if (brightness > 100)
+ return -EINVAL;
+
+- ret = i2c_smbus_write_byte_data(client, CMD_LED_SET_BRIGHTNESS,
+- (u8)brightness);
++ ret = omnia_cmd_write_u8(client, CMD_LED_SET_BRIGHTNESS, brightness);
+
+ return ret < 0 ? ret : count;
+ }
+@@ -241,8 +271,8 @@ static int omnia_leds_remove(struct i2c_client *client)
+ u8 buf[5];
+
+ /* put all LEDs into default (HW triggered) mode */
+- i2c_smbus_write_byte_data(client, CMD_LED_MODE,
+- CMD_LED_MODE_LED(OMNIA_BOARD_LEDS));
++ omnia_cmd_write_u8(client, CMD_LED_MODE,
++ CMD_LED_MODE_LED(OMNIA_BOARD_LEDS));
+
+ /* set all LEDs color to [255, 255, 255] */
+ buf[0] = CMD_LED_COLOR;
+--
+2.42.0
+
--- /dev/null
+From 30bb182d004bb1cd904b708d1ac76eea8a4463c2 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 2 Aug 2023 18:07:43 +0200
+Subject: leds: turris-omnia: Drop unnecessary mutex locking
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Marek Behún <kabel@kernel.org>
+
+[ Upstream commit 760b6b7925bf09491aafa4727eef74fc6bf738b0 ]
+
+Do not lock driver mutex in the global LED panel brightness sysfs
+accessors brightness_show() and brightness_store().
+
+The mutex locking is unnecessary here. The I2C transfers are guarded by
+I2C core locking mechanism, and the LED commands itself do not interfere
+with other commands.
+
+Fixes: 089381b27abe ("leds: initial support for Turris Omnia LEDs")
+Signed-off-by: Marek Behún <kabel@kernel.org>
+Reviewed-by: Lee Jones <lee@kernel.org>
+Link: https://lore.kernel.org/r/20230802160748.11208-2-kabel@kernel.org
+Signed-off-by: Lee Jones <lee@kernel.org>
+Stable-dep-of: 6de283b96b31 ("leds: turris-omnia: Do not use SMBUS calls")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/leds/leds-turris-omnia.c | 11 +----------
+ 1 file changed, 1 insertion(+), 10 deletions(-)
+
+diff --git a/drivers/leds/leds-turris-omnia.c b/drivers/leds/leds-turris-omnia.c
+index 1adfed1c0619b..c9e7c467e5acd 100644
+--- a/drivers/leds/leds-turris-omnia.c
++++ b/drivers/leds/leds-turris-omnia.c
+@@ -156,12 +156,9 @@ static ssize_t brightness_show(struct device *dev, struct device_attribute *a,
+ char *buf)
+ {
+ struct i2c_client *client = to_i2c_client(dev);
+- struct omnia_leds *leds = i2c_get_clientdata(client);
+ int ret;
+
+- mutex_lock(&leds->lock);
+ ret = i2c_smbus_read_byte_data(client, CMD_LED_GET_BRIGHTNESS);
+- mutex_unlock(&leds->lock);
+
+ if (ret < 0)
+ return ret;
+@@ -173,7 +170,6 @@ static ssize_t brightness_store(struct device *dev, struct device_attribute *a,
+ const char *buf, size_t count)
+ {
+ struct i2c_client *client = to_i2c_client(dev);
+- struct omnia_leds *leds = i2c_get_clientdata(client);
+ unsigned long brightness;
+ int ret;
+
+@@ -183,15 +179,10 @@ static ssize_t brightness_store(struct device *dev, struct device_attribute *a,
+ if (brightness > 100)
+ return -EINVAL;
+
+- mutex_lock(&leds->lock);
+ ret = i2c_smbus_write_byte_data(client, CMD_LED_SET_BRIGHTNESS,
+ (u8)brightness);
+- mutex_unlock(&leds->lock);
+-
+- if (ret < 0)
+- return ret;
+
+- return count;
++ return ret < 0 ? ret : count;
+ }
+ static DEVICE_ATTR_RW(brightness);
+
+--
+2.42.0
+
--- /dev/null
+From 0c207427730935626e4b9b576d692b1596208030 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 14 Sep 2023 07:03:27 +0000
+Subject: libnvdimm/of_pmem: Use devm_kstrdup instead of kstrdup and check its
+ return value
+
+From: Chen Ni <nichen@iscas.ac.cn>
+
+[ Upstream commit 6fd4ebfc4d61e3097b595ab2725d513e3bbd6739 ]
+
+Use devm_kstrdup() instead of kstrdup() and check its return value to
+avoid memory leak.
+
+Fixes: 49bddc73d15c ("libnvdimm/of_pmem: Provide a unique name for bus provider")
+Signed-off-by: Chen Ni <nichen@iscas.ac.cn>
+Reviewed-by: Ira Weiny <ira.weiny@intel.com>
+Reviewed-by: Dave Jiang <dave.jiang@intel.com>
+Signed-off-by: Ira Weiny <ira.weiny@intel.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/nvdimm/of_pmem.c | 8 +++++++-
+ 1 file changed, 7 insertions(+), 1 deletion(-)
+
+diff --git a/drivers/nvdimm/of_pmem.c b/drivers/nvdimm/of_pmem.c
+index 10dbdcdfb9ce9..0243789ba914b 100644
+--- a/drivers/nvdimm/of_pmem.c
++++ b/drivers/nvdimm/of_pmem.c
+@@ -30,7 +30,13 @@ static int of_pmem_region_probe(struct platform_device *pdev)
+ if (!priv)
+ return -ENOMEM;
+
+- priv->bus_desc.provider_name = kstrdup(pdev->name, GFP_KERNEL);
++ priv->bus_desc.provider_name = devm_kstrdup(&pdev->dev, pdev->name,
++ GFP_KERNEL);
++ if (!priv->bus_desc.provider_name) {
++ kfree(priv);
++ return -ENOMEM;
++ }
++
+ priv->bus_desc.module = THIS_MODULE;
+ priv->bus_desc.of_node = np;
+
+--
+2.42.0
+
--- /dev/null
+From b2eb747a35f3a70092ea2b14feaca991b6e9e631 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 14 Sep 2023 15:26:44 +0800
+Subject: livepatch: Fix missing newline character in klp_resolve_symbols()
+
+From: Zheng Yejian <zhengyejian1@huawei.com>
+
+[ Upstream commit 67e18e132f0fd738f8c8cac3aa1420312073f795 ]
+
+Without the newline character, the log may not be printed immediately
+after the error occurs.
+
+Fixes: ca376a937486 ("livepatch: Prevent module-specific KLP rela sections from referencing vmlinux symbols")
+Signed-off-by: Zheng Yejian <zhengyejian1@huawei.com>
+Reviewed-by: Petr Mladek <pmladek@suse.com>
+Signed-off-by: Petr Mladek <pmladek@suse.com>
+Link: https://lore.kernel.org/r/20230914072644.4098857-1-zhengyejian1@huawei.com
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ kernel/livepatch/core.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/kernel/livepatch/core.c b/kernel/livepatch/core.c
+index c0789383807b9..147ed154ebc77 100644
+--- a/kernel/livepatch/core.c
++++ b/kernel/livepatch/core.c
+@@ -244,7 +244,7 @@ static int klp_resolve_symbols(Elf_Shdr *sechdrs, const char *strtab,
+ * symbols are exported and normal relas can be used instead.
+ */
+ if (!sec_vmlinux && sym_vmlinux) {
+- pr_err("invalid access to vmlinux symbol '%s' from module-specific livepatch relocation section",
++ pr_err("invalid access to vmlinux symbol '%s' from module-specific livepatch relocation section\n",
+ sym_name);
+ return -EINVAL;
+ }
+--
+2.42.0
+
--- /dev/null
+From dd2954050ae6d0c26c2eae1ab5fb30b2e678c543 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 13 Apr 2023 11:49:42 +0800
+Subject: media: bttv: fix use after free error due to btv->timeout timer
+
+From: Zheng Wang <zyytlz.wz@163.com>
+
+[ Upstream commit bd5b50b329e850d467e7bcc07b2b6bde3752fbda ]
+
+There may be some a race condition between timer function
+bttv_irq_timeout and bttv_remove. The timer is setup in
+probe and there is no timer_delete operation in remove
+function. When it hit kfree btv, the function might still be
+invoked, which will cause use after free bug.
+
+This bug is found by static analysis, it may be false positive.
+
+Fix it by adding del_timer_sync invoking to the remove function.
+
+cpu0 cpu1
+ bttv_probe
+ ->timer_setup
+ ->bttv_set_dma
+ ->mod_timer;
+bttv_remove
+ ->kfree(btv);
+ ->bttv_irq_timeout
+ ->USE btv
+
+Fixes: 162e6376ac58 ("media: pci: Convert timers to use timer_setup()")
+Signed-off-by: Zheng Wang <zyytlz.wz@163.com>
+Signed-off-by: Hans Verkuil <hverkuil-cisco@xs4all.nl>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/media/pci/bt8xx/bttv-driver.c | 1 +
+ 1 file changed, 1 insertion(+)
+
+diff --git a/drivers/media/pci/bt8xx/bttv-driver.c b/drivers/media/pci/bt8xx/bttv-driver.c
+index 661ebfa7bf3f5..c4bf7b7109ce4 100644
+--- a/drivers/media/pci/bt8xx/bttv-driver.c
++++ b/drivers/media/pci/bt8xx/bttv-driver.c
+@@ -4250,6 +4250,7 @@ static void bttv_remove(struct pci_dev *pci_dev)
+
+ /* free resources */
+ free_irq(btv->c.pci->irq,btv);
++ del_timer_sync(&btv->timeout);
+ iounmap(btv->bt848_mmio);
+ release_mem_region(pci_resource_start(btv->c.pci,0),
+ pci_resource_len(btv->c.pci,0));
+--
+2.42.0
+
--- /dev/null
+From 3ac4667d6c72e2927cb3a9ed1b9a963481b47e76 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 9 Oct 2023 18:39:29 +0530
+Subject: media: cadence: csi2rx: Unregister v4l2 async notifier
+
+From: Pratyush Yadav <p.yadav@ti.com>
+
+[ Upstream commit b2701715301a49b53d05c7d43f3fedc3b8743bfc ]
+
+The notifier is added to the global notifier list when registered. When
+the module is removed, the struct csi2rx_priv in which the notifier is
+embedded, is destroyed. As a result the notifier list has a reference to
+a notifier that no longer exists. This causes invalid memory accesses
+when the list is iterated over. Similar for when the probe fails.
+Unregister and clean up the notifier to avoid this.
+
+Fixes: 1fc3b37f34f6 ("media: v4l: cadence: Add Cadence MIPI-CSI2 RX driver")
+
+Signed-off-by: Pratyush Yadav <p.yadav@ti.com>
+Tested-by: Julien Massot <julien.massot@collabora.com>
+Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
+Reviewed-by: Tomi Valkeinen <tomi.valkeinen@ideasonboard.com>
+Reviewed-by: Maxime Ripard <mripard@kernel.org>
+Signed-off-by: Jai Luthra <j-luthra@ti.com>
+Signed-off-by: Sakari Ailus <sakari.ailus@linux.intel.com>
+Signed-off-by: Hans Verkuil <hverkuil-cisco@xs4all.nl>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/media/platform/cadence/cdns-csi2rx.c | 7 ++++++-
+ 1 file changed, 6 insertions(+), 1 deletion(-)
+
+diff --git a/drivers/media/platform/cadence/cdns-csi2rx.c b/drivers/media/platform/cadence/cdns-csi2rx.c
+index 7b44ab2b8c9ad..292044588ae2c 100644
+--- a/drivers/media/platform/cadence/cdns-csi2rx.c
++++ b/drivers/media/platform/cadence/cdns-csi2rx.c
+@@ -406,8 +406,10 @@ static int csi2rx_parse_dt(struct csi2rx_priv *csi2rx)
+ asd = v4l2_async_nf_add_fwnode_remote(&csi2rx->notifier, fwh,
+ struct v4l2_async_subdev);
+ of_node_put(ep);
+- if (IS_ERR(asd))
++ if (IS_ERR(asd)) {
++ v4l2_async_nf_cleanup(&csi2rx->notifier);
+ return PTR_ERR(asd);
++ }
+
+ csi2rx->notifier.ops = &csi2rx_notifier_ops;
+
+@@ -469,6 +471,7 @@ static int csi2rx_probe(struct platform_device *pdev)
+ return 0;
+
+ err_cleanup:
++ v4l2_async_nf_unregister(&csi2rx->notifier);
+ v4l2_async_nf_cleanup(&csi2rx->notifier);
+ err_free_priv:
+ kfree(csi2rx);
+@@ -479,6 +482,8 @@ static int csi2rx_remove(struct platform_device *pdev)
+ {
+ struct csi2rx_priv *csi2rx = platform_get_drvdata(pdev);
+
++ v4l2_async_nf_unregister(&csi2rx->notifier);
++ v4l2_async_nf_cleanup(&csi2rx->notifier);
+ v4l2_async_unregister_subdev(&csi2rx->subdev);
+ kfree(csi2rx);
+
+--
+2.42.0
+
--- /dev/null
+From e90bf6d3fed2e9da1cac2e745647e0db1c9ce2b0 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 11 Sep 2023 20:46:12 +0200
+Subject: media: cedrus: Fix clock/reset sequence
+
+From: Jernej Skrabec <jernej.skrabec@gmail.com>
+
+[ Upstream commit 36fe515c1a3cd5eac148e8a591a82108d92d5522 ]
+
+According to H6 user manual, resets should always be de-asserted before
+clocks are enabled. This is also consistent with vendor driver.
+
+Fixes: d5aecd289bab ("media: cedrus: Implement runtime PM")
+Signed-off-by: Jernej Skrabec <jernej.skrabec@gmail.com>
+Acked-by: Paul Kocialkowski <paul.kocialkowski@bootlin.com>
+Signed-off-by: Hans Verkuil <hverkuil-cisco@xs4all.nl>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ .../staging/media/sunxi/cedrus/cedrus_hw.c | 24 +++++++++----------
+ 1 file changed, 12 insertions(+), 12 deletions(-)
+
+diff --git a/drivers/staging/media/sunxi/cedrus/cedrus_hw.c b/drivers/staging/media/sunxi/cedrus/cedrus_hw.c
+index e2f2ff609c7e6..0904aea782b1e 100644
+--- a/drivers/staging/media/sunxi/cedrus/cedrus_hw.c
++++ b/drivers/staging/media/sunxi/cedrus/cedrus_hw.c
+@@ -147,12 +147,12 @@ int cedrus_hw_suspend(struct device *device)
+ {
+ struct cedrus_dev *dev = dev_get_drvdata(device);
+
+- reset_control_assert(dev->rstc);
+-
+ clk_disable_unprepare(dev->ram_clk);
+ clk_disable_unprepare(dev->mod_clk);
+ clk_disable_unprepare(dev->ahb_clk);
+
++ reset_control_assert(dev->rstc);
++
+ return 0;
+ }
+
+@@ -161,11 +161,18 @@ int cedrus_hw_resume(struct device *device)
+ struct cedrus_dev *dev = dev_get_drvdata(device);
+ int ret;
+
++ ret = reset_control_reset(dev->rstc);
++ if (ret) {
++ dev_err(dev->dev, "Failed to apply reset\n");
++
++ return ret;
++ }
++
+ ret = clk_prepare_enable(dev->ahb_clk);
+ if (ret) {
+ dev_err(dev->dev, "Failed to enable AHB clock\n");
+
+- return ret;
++ goto err_rst;
+ }
+
+ ret = clk_prepare_enable(dev->mod_clk);
+@@ -182,21 +189,14 @@ int cedrus_hw_resume(struct device *device)
+ goto err_mod_clk;
+ }
+
+- ret = reset_control_reset(dev->rstc);
+- if (ret) {
+- dev_err(dev->dev, "Failed to apply reset\n");
+-
+- goto err_ram_clk;
+- }
+-
+ return 0;
+
+-err_ram_clk:
+- clk_disable_unprepare(dev->ram_clk);
+ err_mod_clk:
+ clk_disable_unprepare(dev->mod_clk);
+ err_ahb_clk:
+ clk_disable_unprepare(dev->ahb_clk);
++err_rst:
++ reset_control_assert(dev->rstc);
+
+ return ret;
+ }
+--
+2.42.0
+
--- /dev/null
+From ee7502625d7ea83a5c24cf2ce73e95920438f523 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 6 Oct 2023 12:08:45 +0200
+Subject: media: dvb-usb-v2: af9035: fix missing unlock
+
+From: Hans Verkuil <hverkuil-cisco@xs4all.nl>
+
+[ Upstream commit f31b2cb85f0ee165d78e1c43f6d69f82cc3b2145 ]
+
+Instead of returning an error, goto the mutex unlock at
+the end of the function.
+
+Fixes smatch warning:
+
+drivers/media/usb/dvb-usb-v2/af9035.c:467 af9035_i2c_master_xfer() warn: inconsistent returns '&d->i2c_mutex'.
+ Locked on : 326,387
+ Unlocked on: 465,467
+
+Signed-off-by: Hans Verkuil <hverkuil-cisco@xs4all.nl>
+Fixes: 7bf744f2de0a ("media: dvb-usb-v2: af9035: Fix null-ptr-deref in af9035_i2c_master_xfer")
+Signed-off-by: Hans Verkuil <hverkuil-cisco@xs4all.nl>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/media/usb/dvb-usb-v2/af9035.c | 13 +++++++++----
+ 1 file changed, 9 insertions(+), 4 deletions(-)
+
+diff --git a/drivers/media/usb/dvb-usb-v2/af9035.c b/drivers/media/usb/dvb-usb-v2/af9035.c
+index 56bb507fca214..dabfe9b332226 100644
+--- a/drivers/media/usb/dvb-usb-v2/af9035.c
++++ b/drivers/media/usb/dvb-usb-v2/af9035.c
+@@ -323,8 +323,10 @@ static int af9035_i2c_master_xfer(struct i2c_adapter *adap,
+ ret = -EOPNOTSUPP;
+ } else if ((msg[0].addr == state->af9033_i2c_addr[0]) ||
+ (msg[0].addr == state->af9033_i2c_addr[1])) {
+- if (msg[0].len < 3 || msg[1].len < 1)
+- return -EOPNOTSUPP;
++ if (msg[0].len < 3 || msg[1].len < 1) {
++ ret = -EOPNOTSUPP;
++ goto unlock;
++ }
+ /* demod access via firmware interface */
+ reg = msg[0].buf[0] << 16 | msg[0].buf[1] << 8 |
+ msg[0].buf[2];
+@@ -384,8 +386,10 @@ static int af9035_i2c_master_xfer(struct i2c_adapter *adap,
+ ret = -EOPNOTSUPP;
+ } else if ((msg[0].addr == state->af9033_i2c_addr[0]) ||
+ (msg[0].addr == state->af9033_i2c_addr[1])) {
+- if (msg[0].len < 3)
+- return -EOPNOTSUPP;
++ if (msg[0].len < 3) {
++ ret = -EOPNOTSUPP;
++ goto unlock;
++ }
+ /* demod access via firmware interface */
+ reg = msg[0].buf[0] << 16 | msg[0].buf[1] << 8 |
+ msg[0].buf[2];
+@@ -460,6 +464,7 @@ static int af9035_i2c_master_xfer(struct i2c_adapter *adap,
+ ret = -EOPNOTSUPP;
+ }
+
++unlock:
+ mutex_unlock(&d->i2c_mutex);
+
+ if (ret < 0)
+--
+2.42.0
+
--- /dev/null
+From deea8c3040538bca1beb03eb5437b57920548192 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sat, 26 Aug 2023 00:13:40 +0200
+Subject: media: i2c: max9286: Fix some redundant of_node_put() calls
+
+From: Christophe JAILLET <christophe.jaillet@wanadoo.fr>
+
+[ Upstream commit 0822315e46b400f611cba1193456ee6a5dc3e41d ]
+
+This is odd to have a of_node_put() just after a for_each_child_of_node()
+or a for_each_endpoint_of_node() loop. It should already be called
+during the last iteration.
+
+Remove these calls.
+
+Fixes: 66d8c9d2422d ("media: i2c: Add MAX9286 driver")
+Signed-off-by: Christophe JAILLET <christophe.jaillet@wanadoo.fr>
+Reviewed-by: Jacopo Mondi <jacopo.mondi@ideasonboard.com>
+Reviewed-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
+Reviewed-by: Kieran Bingham <kieran.bingham+renesas@ideasonboard.com>
+Signed-off-by: Sakari Ailus <sakari.ailus@linux.intel.com>
+Signed-off-by: Hans Verkuil <hverkuil-cisco@xs4all.nl>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/media/i2c/max9286.c | 2 --
+ 1 file changed, 2 deletions(-)
+
+diff --git a/drivers/media/i2c/max9286.c b/drivers/media/i2c/max9286.c
+index 404a03f48b976..1b9beaee6bea7 100644
+--- a/drivers/media/i2c/max9286.c
++++ b/drivers/media/i2c/max9286.c
+@@ -1231,7 +1231,6 @@ static int max9286_parse_dt(struct max9286_priv *priv)
+
+ i2c_mux_mask |= BIT(id);
+ }
+- of_node_put(node);
+ of_node_put(i2c_mux);
+
+ /* Parse the endpoints */
+@@ -1295,7 +1294,6 @@ static int max9286_parse_dt(struct max9286_priv *priv)
+ priv->source_mask |= BIT(ep.port);
+ priv->nsources++;
+ }
+- of_node_put(node);
+
+ /*
+ * Parse the initial value of the reverse channel amplitude from
+--
+2.42.0
+
--- /dev/null
+From cd2471ec6c14b24a75e2abe01c1a9bb97e8d7f3d Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 9 Jul 2021 16:25:52 +0200
+Subject: media: rcar-vin: Improve async notifier cleanup paths
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Niklas Söderlund <niklas.soderlund+renesas@ragnatech.se>
+
+[ Upstream commit 6df3057792911c59032327886599d9625534958a ]
+
+The cleanup code for the async notifiers can be refactored to own
+functions to reduce code duplication and improve readability. While at
+it rename the CSI-2 initialization function _csi2_ instead of _mc_ to
+match.
+
+Signed-off-by: Niklas Söderlund <niklas.soderlund+renesas@ragnatech.se>
+Reviewed-by: Jacopo Mondi <jacopo+renesas@jmondi.org>
+Signed-off-by: Sakari Ailus <sakari.ailus@linux.intel.com>
+Signed-off-by: Mauro Carvalho Chehab <mchehab+huawei@kernel.org>
+Stable-dep-of: b2701715301a ("media: cadence: csi2rx: Unregister v4l2 async notifier")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/media/platform/rcar-vin/rcar-core.c | 51 ++++++++++++---------
+ 1 file changed, 30 insertions(+), 21 deletions(-)
+
+diff --git a/drivers/media/platform/rcar-vin/rcar-core.c b/drivers/media/platform/rcar-vin/rcar-core.c
+index 6ea561fcd7a39..93a32be692e9a 100644
+--- a/drivers/media/platform/rcar-vin/rcar-core.c
++++ b/drivers/media/platform/rcar-vin/rcar-core.c
+@@ -383,6 +383,16 @@ static void rvin_group_put(struct rvin_dev *vin)
+ kref_put(&group->refcount, rvin_group_release);
+ }
+
++static void rvin_group_notifier_cleanup(struct rvin_dev *vin)
++{
++ mutex_lock(&vin->group->lock);
++ if (&vin->v4l2_dev == vin->group->notifier.v4l2_dev) {
++ v4l2_async_notifier_unregister(&vin->group->notifier);
++ v4l2_async_notifier_cleanup(&vin->group->notifier);
++ }
++ mutex_unlock(&vin->group->lock);
++}
++
+ /* -----------------------------------------------------------------------------
+ * Controls
+ */
+@@ -676,6 +686,12 @@ static int rvin_parallel_parse_of(struct rvin_dev *vin)
+ return ret;
+ }
+
++static void rvin_parallel_cleanup(struct rvin_dev *vin)
++{
++ v4l2_async_notifier_unregister(&vin->notifier);
++ v4l2_async_notifier_cleanup(&vin->notifier);
++}
++
+ static int rvin_parallel_init(struct rvin_dev *vin)
+ {
+ int ret;
+@@ -937,7 +953,16 @@ static int rvin_mc_parse_of_graph(struct rvin_dev *vin)
+ return 0;
+ }
+
+-static int rvin_mc_init(struct rvin_dev *vin)
++static void rvin_csi2_cleanup(struct rvin_dev *vin)
++{
++ if (!vin->info->use_mc)
++ return;
++
++ rvin_group_notifier_cleanup(vin);
++ rvin_group_put(vin);
++}
++
++static int rvin_csi2_init(struct rvin_dev *vin)
+ {
+ int ret;
+
+@@ -1443,7 +1468,7 @@ static int rcar_vin_probe(struct platform_device *pdev)
+ platform_set_drvdata(pdev, vin);
+
+ if (vin->info->use_mc) {
+- ret = rvin_mc_init(vin);
++ ret = rvin_csi2_init(vin);
+ if (ret)
+ goto error_dma_unregister;
+ }
+@@ -1456,20 +1481,9 @@ static int rcar_vin_probe(struct platform_device *pdev)
+ pm_runtime_enable(&pdev->dev);
+
+ return 0;
+-
+ error_group_unregister:
+ rvin_free_controls(vin);
+-
+- if (vin->info->use_mc) {
+- mutex_lock(&vin->group->lock);
+- if (&vin->v4l2_dev == vin->group->notifier.v4l2_dev) {
+- v4l2_async_notifier_unregister(&vin->group->notifier);
+- v4l2_async_notifier_cleanup(&vin->group->notifier);
+- }
+- mutex_unlock(&vin->group->lock);
+- rvin_group_put(vin);
+- }
+-
++ rvin_csi2_cleanup(vin);
+ error_dma_unregister:
+ rvin_dma_unregister(vin);
+
+@@ -1484,14 +1498,9 @@ static int rcar_vin_remove(struct platform_device *pdev)
+
+ rvin_v4l2_unregister(vin);
+
+- v4l2_async_notifier_unregister(&vin->notifier);
+- v4l2_async_notifier_cleanup(&vin->notifier);
++ rvin_parallel_cleanup(vin);
+
+- if (vin->info->use_mc) {
+- v4l2_async_notifier_unregister(&vin->group->notifier);
+- v4l2_async_notifier_cleanup(&vin->group->notifier);
+- rvin_group_put(vin);
+- }
++ rvin_csi2_cleanup(vin);
+
+ rvin_free_controls(vin);
+
+--
+2.42.0
+
--- /dev/null
+From 51d1516951f0775a766867ae7a06e55ebd0eed68 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 9 Jul 2021 16:25:55 +0200
+Subject: media: rcar-vin: Move group async notifier
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Niklas Söderlund <niklas.soderlund+renesas@ragnatech.se>
+
+[ Upstream commit 2070893aed113338f80350bd76e5956c9a8cf07f ]
+
+The VIN group notifier code is intertwined with the media graph layout
+code for R-Car CSI-2 subdevices, this makes it hard to extend the group
+to also support the R-Car ISP channel selector.
+
+Before breaking the two concepts apart and extending it move the group
+code to its final location. There is no functional change and all
+functions are moved verbatim.
+
+Signed-off-by: Niklas Söderlund <niklas.soderlund+renesas@ragnatech.se>
+Reviewed-by: Jacopo Mondi <jacopo+renesas@jmondi.org>
+Signed-off-by: Sakari Ailus <sakari.ailus@linux.intel.com>
+Signed-off-by: Mauro Carvalho Chehab <mchehab+huawei@kernel.org>
+Stable-dep-of: b2701715301a ("media: cadence: csi2rx: Unregister v4l2 async notifier")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/media/platform/rcar-vin/rcar-core.c | 460 ++++++++++----------
+ 1 file changed, 230 insertions(+), 230 deletions(-)
+
+diff --git a/drivers/media/platform/rcar-vin/rcar-core.c b/drivers/media/platform/rcar-vin/rcar-core.c
+index 867d8fd7a77d3..5a280d8ff7dd0 100644
+--- a/drivers/media/platform/rcar-vin/rcar-core.c
++++ b/drivers/media/platform/rcar-vin/rcar-core.c
+@@ -383,6 +383,176 @@ static void rvin_group_put(struct rvin_dev *vin)
+ kref_put(&group->refcount, rvin_group_release);
+ }
+
++static int rvin_group_notify_complete(struct v4l2_async_notifier *notifier)
++{
++ struct rvin_dev *vin = v4l2_dev_to_vin(notifier->v4l2_dev);
++ const struct rvin_group_route *route;
++ unsigned int i;
++ int ret;
++
++ ret = media_device_register(&vin->group->mdev);
++ if (ret)
++ return ret;
++
++ ret = v4l2_device_register_subdev_nodes(&vin->v4l2_dev);
++ if (ret) {
++ vin_err(vin, "Failed to register subdev nodes\n");
++ return ret;
++ }
++
++ /* Register all video nodes for the group. */
++ for (i = 0; i < RCAR_VIN_NUM; i++) {
++ if (vin->group->vin[i] &&
++ !video_is_registered(&vin->group->vin[i]->vdev)) {
++ ret = rvin_v4l2_register(vin->group->vin[i]);
++ if (ret)
++ return ret;
++ }
++ }
++
++ /* Create all media device links between VINs and CSI-2's. */
++ mutex_lock(&vin->group->lock);
++ for (route = vin->info->routes; route->mask; route++) {
++ struct media_pad *source_pad, *sink_pad;
++ struct media_entity *source, *sink;
++ unsigned int source_idx;
++
++ /* Check that VIN is part of the group. */
++ if (!vin->group->vin[route->vin])
++ continue;
++
++ /* Check that VIN' master is part of the group. */
++ if (!vin->group->vin[rvin_group_id_to_master(route->vin)])
++ continue;
++
++ /* Check that CSI-2 is part of the group. */
++ if (!vin->group->remotes[route->csi].subdev)
++ continue;
++
++ source = &vin->group->remotes[route->csi].subdev->entity;
++ source_idx = rvin_group_csi_channel_to_pad(route->channel);
++ source_pad = &source->pads[source_idx];
++
++ sink = &vin->group->vin[route->vin]->vdev.entity;
++ sink_pad = &sink->pads[0];
++
++ /* Skip if link already exists. */
++ if (media_entity_find_link(source_pad, sink_pad))
++ continue;
++
++ ret = media_create_pad_link(source, source_idx, sink, 0, 0);
++ if (ret) {
++ vin_err(vin, "Error adding link from %s to %s\n",
++ source->name, sink->name);
++ break;
++ }
++ }
++ mutex_unlock(&vin->group->lock);
++
++ return ret;
++}
++
++static void rvin_group_notify_unbind(struct v4l2_async_notifier *notifier,
++ struct v4l2_subdev *subdev,
++ struct v4l2_async_subdev *asd)
++{
++ struct rvin_dev *vin = v4l2_dev_to_vin(notifier->v4l2_dev);
++ unsigned int i;
++
++ for (i = 0; i < RCAR_VIN_NUM; i++)
++ if (vin->group->vin[i])
++ rvin_v4l2_unregister(vin->group->vin[i]);
++
++ mutex_lock(&vin->group->lock);
++
++ for (i = 0; i < RVIN_CSI_MAX; i++) {
++ if (vin->group->remotes[i].asd != asd)
++ continue;
++ vin->group->remotes[i].subdev = NULL;
++ vin_dbg(vin, "Unbind %s from slot %u\n", subdev->name, i);
++ break;
++ }
++
++ mutex_unlock(&vin->group->lock);
++
++ media_device_unregister(&vin->group->mdev);
++}
++
++static int rvin_group_notify_bound(struct v4l2_async_notifier *notifier,
++ struct v4l2_subdev *subdev,
++ struct v4l2_async_subdev *asd)
++{
++ struct rvin_dev *vin = v4l2_dev_to_vin(notifier->v4l2_dev);
++ unsigned int i;
++
++ mutex_lock(&vin->group->lock);
++
++ for (i = 0; i < RVIN_CSI_MAX; i++) {
++ if (vin->group->remotes[i].asd != asd)
++ continue;
++ vin->group->remotes[i].subdev = subdev;
++ vin_dbg(vin, "Bound %s to slot %u\n", subdev->name, i);
++ break;
++ }
++
++ mutex_unlock(&vin->group->lock);
++
++ return 0;
++}
++
++static const struct v4l2_async_notifier_operations rvin_group_notify_ops = {
++ .bound = rvin_group_notify_bound,
++ .unbind = rvin_group_notify_unbind,
++ .complete = rvin_group_notify_complete,
++};
++
++static int rvin_mc_parse_of(struct rvin_dev *vin, unsigned int id)
++{
++ struct fwnode_handle *ep, *fwnode;
++ struct v4l2_fwnode_endpoint vep = {
++ .bus_type = V4L2_MBUS_CSI2_DPHY,
++ };
++ struct v4l2_async_subdev *asd;
++ int ret;
++
++ ep = fwnode_graph_get_endpoint_by_id(dev_fwnode(vin->dev), 1, id, 0);
++ if (!ep)
++ return 0;
++
++ fwnode = fwnode_graph_get_remote_endpoint(ep);
++ ret = v4l2_fwnode_endpoint_parse(ep, &vep);
++ fwnode_handle_put(ep);
++ if (ret) {
++ vin_err(vin, "Failed to parse %pOF\n", to_of_node(fwnode));
++ ret = -EINVAL;
++ goto out;
++ }
++
++ if (!of_device_is_available(to_of_node(fwnode))) {
++ vin_dbg(vin, "OF device %pOF disabled, ignoring\n",
++ to_of_node(fwnode));
++ ret = -ENOTCONN;
++ goto out;
++ }
++
++ asd = v4l2_async_notifier_add_fwnode_subdev(&vin->group->notifier,
++ fwnode,
++ struct v4l2_async_subdev);
++ if (IS_ERR(asd)) {
++ ret = PTR_ERR(asd);
++ goto out;
++ }
++
++ vin->group->remotes[vep.base.id].asd = asd;
++
++ vin_dbg(vin, "Add group OF device %pOF to slot %u\n",
++ to_of_node(fwnode), vep.base.id);
++out:
++ fwnode_handle_put(fwnode);
++
++ return ret;
++}
++
+ static void rvin_group_notifier_cleanup(struct rvin_dev *vin)
+ {
+ mutex_lock(&vin->group->lock);
+@@ -393,6 +563,65 @@ static void rvin_group_notifier_cleanup(struct rvin_dev *vin)
+ mutex_unlock(&vin->group->lock);
+ }
+
++static int rvin_mc_parse_of_graph(struct rvin_dev *vin)
++{
++ unsigned int count = 0, vin_mask = 0;
++ unsigned int i, id;
++ int ret;
++
++ mutex_lock(&vin->group->lock);
++
++ /* If not all VIN's are registered don't register the notifier. */
++ for (i = 0; i < RCAR_VIN_NUM; i++) {
++ if (vin->group->vin[i]) {
++ count++;
++ vin_mask |= BIT(i);
++ }
++ }
++
++ if (vin->group->count != count) {
++ mutex_unlock(&vin->group->lock);
++ return 0;
++ }
++
++ mutex_unlock(&vin->group->lock);
++
++ v4l2_async_notifier_init(&vin->group->notifier);
++
++ /*
++ * Have all VIN's look for CSI-2 subdevices. Some subdevices will
++ * overlap but the parser function can handle it, so each subdevice
++ * will only be registered once with the group notifier.
++ */
++ for (i = 0; i < RCAR_VIN_NUM; i++) {
++ if (!(vin_mask & BIT(i)))
++ continue;
++
++ for (id = 0; id < RVIN_CSI_MAX; id++) {
++ if (vin->group->remotes[id].asd)
++ continue;
++
++ ret = rvin_mc_parse_of(vin->group->vin[i], id);
++ if (ret)
++ return ret;
++ }
++ }
++
++ if (list_empty(&vin->group->notifier.asd_list))
++ return 0;
++
++ vin->group->notifier.ops = &rvin_group_notify_ops;
++ ret = v4l2_async_notifier_register(&vin->v4l2_dev,
++ &vin->group->notifier);
++ if (ret < 0) {
++ vin_err(vin, "Notifier registration failed\n");
++ v4l2_async_notifier_cleanup(&vin->group->notifier);
++ return ret;
++ }
++
++ return 0;
++}
++
+ /* -----------------------------------------------------------------------------
+ * Controls
+ */
+@@ -721,238 +950,9 @@ static int rvin_parallel_init(struct rvin_dev *vin)
+ }
+
+ /* -----------------------------------------------------------------------------
+- * Group async notifier
++ * CSI-2
+ */
+
+-static int rvin_group_notify_complete(struct v4l2_async_notifier *notifier)
+-{
+- struct rvin_dev *vin = v4l2_dev_to_vin(notifier->v4l2_dev);
+- const struct rvin_group_route *route;
+- unsigned int i;
+- int ret;
+-
+- ret = media_device_register(&vin->group->mdev);
+- if (ret)
+- return ret;
+-
+- ret = v4l2_device_register_subdev_nodes(&vin->v4l2_dev);
+- if (ret) {
+- vin_err(vin, "Failed to register subdev nodes\n");
+- return ret;
+- }
+-
+- /* Register all video nodes for the group. */
+- for (i = 0; i < RCAR_VIN_NUM; i++) {
+- if (vin->group->vin[i] &&
+- !video_is_registered(&vin->group->vin[i]->vdev)) {
+- ret = rvin_v4l2_register(vin->group->vin[i]);
+- if (ret)
+- return ret;
+- }
+- }
+-
+- /* Create all media device links between VINs and CSI-2's. */
+- mutex_lock(&vin->group->lock);
+- for (route = vin->info->routes; route->mask; route++) {
+- struct media_pad *source_pad, *sink_pad;
+- struct media_entity *source, *sink;
+- unsigned int source_idx;
+-
+- /* Check that VIN is part of the group. */
+- if (!vin->group->vin[route->vin])
+- continue;
+-
+- /* Check that VIN' master is part of the group. */
+- if (!vin->group->vin[rvin_group_id_to_master(route->vin)])
+- continue;
+-
+- /* Check that CSI-2 is part of the group. */
+- if (!vin->group->remotes[route->csi].subdev)
+- continue;
+-
+- source = &vin->group->remotes[route->csi].subdev->entity;
+- source_idx = rvin_group_csi_channel_to_pad(route->channel);
+- source_pad = &source->pads[source_idx];
+-
+- sink = &vin->group->vin[route->vin]->vdev.entity;
+- sink_pad = &sink->pads[0];
+-
+- /* Skip if link already exists. */
+- if (media_entity_find_link(source_pad, sink_pad))
+- continue;
+-
+- ret = media_create_pad_link(source, source_idx, sink, 0, 0);
+- if (ret) {
+- vin_err(vin, "Error adding link from %s to %s\n",
+- source->name, sink->name);
+- break;
+- }
+- }
+- mutex_unlock(&vin->group->lock);
+-
+- return ret;
+-}
+-
+-static void rvin_group_notify_unbind(struct v4l2_async_notifier *notifier,
+- struct v4l2_subdev *subdev,
+- struct v4l2_async_subdev *asd)
+-{
+- struct rvin_dev *vin = v4l2_dev_to_vin(notifier->v4l2_dev);
+- unsigned int i;
+-
+- for (i = 0; i < RCAR_VIN_NUM; i++)
+- if (vin->group->vin[i])
+- rvin_v4l2_unregister(vin->group->vin[i]);
+-
+- mutex_lock(&vin->group->lock);
+-
+- for (i = 0; i < RVIN_CSI_MAX; i++) {
+- if (vin->group->remotes[i].asd != asd)
+- continue;
+- vin->group->remotes[i].subdev = NULL;
+- vin_dbg(vin, "Unbind %s from slot %u\n", subdev->name, i);
+- break;
+- }
+-
+- mutex_unlock(&vin->group->lock);
+-
+- media_device_unregister(&vin->group->mdev);
+-}
+-
+-static int rvin_group_notify_bound(struct v4l2_async_notifier *notifier,
+- struct v4l2_subdev *subdev,
+- struct v4l2_async_subdev *asd)
+-{
+- struct rvin_dev *vin = v4l2_dev_to_vin(notifier->v4l2_dev);
+- unsigned int i;
+-
+- mutex_lock(&vin->group->lock);
+-
+- for (i = 0; i < RVIN_CSI_MAX; i++) {
+- if (vin->group->remotes[i].asd != asd)
+- continue;
+- vin->group->remotes[i].subdev = subdev;
+- vin_dbg(vin, "Bound %s to slot %u\n", subdev->name, i);
+- break;
+- }
+-
+- mutex_unlock(&vin->group->lock);
+-
+- return 0;
+-}
+-
+-static const struct v4l2_async_notifier_operations rvin_group_notify_ops = {
+- .bound = rvin_group_notify_bound,
+- .unbind = rvin_group_notify_unbind,
+- .complete = rvin_group_notify_complete,
+-};
+-
+-static int rvin_mc_parse_of(struct rvin_dev *vin, unsigned int id)
+-{
+- struct fwnode_handle *ep, *fwnode;
+- struct v4l2_fwnode_endpoint vep = {
+- .bus_type = V4L2_MBUS_CSI2_DPHY,
+- };
+- struct v4l2_async_subdev *asd;
+- int ret;
+-
+- ep = fwnode_graph_get_endpoint_by_id(dev_fwnode(vin->dev), 1, id, 0);
+- if (!ep)
+- return 0;
+-
+- fwnode = fwnode_graph_get_remote_endpoint(ep);
+- ret = v4l2_fwnode_endpoint_parse(ep, &vep);
+- fwnode_handle_put(ep);
+- if (ret) {
+- vin_err(vin, "Failed to parse %pOF\n", to_of_node(fwnode));
+- ret = -EINVAL;
+- goto out;
+- }
+-
+- if (!of_device_is_available(to_of_node(fwnode))) {
+- vin_dbg(vin, "OF device %pOF disabled, ignoring\n",
+- to_of_node(fwnode));
+- ret = -ENOTCONN;
+- goto out;
+- }
+-
+- asd = v4l2_async_notifier_add_fwnode_subdev(&vin->group->notifier,
+- fwnode,
+- struct v4l2_async_subdev);
+- if (IS_ERR(asd)) {
+- ret = PTR_ERR(asd);
+- goto out;
+- }
+-
+- vin->group->remotes[vep.base.id].asd = asd;
+-
+- vin_dbg(vin, "Add group OF device %pOF to slot %u\n",
+- to_of_node(fwnode), vep.base.id);
+-out:
+- fwnode_handle_put(fwnode);
+-
+- return ret;
+-}
+-
+-static int rvin_mc_parse_of_graph(struct rvin_dev *vin)
+-{
+- unsigned int count = 0, vin_mask = 0;
+- unsigned int i, id;
+- int ret;
+-
+- mutex_lock(&vin->group->lock);
+-
+- /* If not all VIN's are registered don't register the notifier. */
+- for (i = 0; i < RCAR_VIN_NUM; i++) {
+- if (vin->group->vin[i]) {
+- count++;
+- vin_mask |= BIT(i);
+- }
+- }
+-
+- if (vin->group->count != count) {
+- mutex_unlock(&vin->group->lock);
+- return 0;
+- }
+-
+- mutex_unlock(&vin->group->lock);
+-
+- v4l2_async_notifier_init(&vin->group->notifier);
+-
+- /*
+- * Have all VIN's look for CSI-2 subdevices. Some subdevices will
+- * overlap but the parser function can handle it, so each subdevice
+- * will only be registered once with the group notifier.
+- */
+- for (i = 0; i < RCAR_VIN_NUM; i++) {
+- if (!(vin_mask & BIT(i)))
+- continue;
+-
+- for (id = 0; id < RVIN_CSI_MAX; id++) {
+- if (vin->group->remotes[id].asd)
+- continue;
+-
+- ret = rvin_mc_parse_of(vin->group->vin[i], id);
+- if (ret)
+- return ret;
+- }
+- }
+-
+- if (list_empty(&vin->group->notifier.asd_list))
+- return 0;
+-
+- vin->group->notifier.ops = &rvin_group_notify_ops;
+- ret = v4l2_async_notifier_register(&vin->v4l2_dev,
+- &vin->group->notifier);
+- if (ret < 0) {
+- vin_err(vin, "Notifier registration failed\n");
+- v4l2_async_notifier_cleanup(&vin->group->notifier);
+- return ret;
+- }
+-
+- return 0;
+-}
+-
+ static void rvin_csi2_cleanup(struct rvin_dev *vin)
+ {
+ if (!vin->info->use_mc)
+--
+2.42.0
+
--- /dev/null
+From 74d2f9b2f92e12a66216f4cad650e2731d3d8540 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 9 Jul 2021 16:25:50 +0200
+Subject: media: rcar-vin: Refactor controls creation for video device
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Niklas Söderlund <niklas.soderlund+renesas@ragnatech.se>
+
+[ Upstream commit b2dc5680aeb418deeacbe9628697fa0b0f2dc54a ]
+
+The controls for the video device are created in different code paths
+depending on if the driver is using the media graph centric model (Gen3)
+or the device centric model (Gen2 and earlier). This have lead to code
+duplication that can be consolidated.
+
+Signed-off-by: Niklas Söderlund <niklas.soderlund+renesas@ragnatech.se>
+Reviewed-by: Jacopo Mondi <jacopo+renesas@jmondi.org>
+Signed-off-by: Sakari Ailus <sakari.ailus@linux.intel.com>
+Signed-off-by: Mauro Carvalho Chehab <mchehab+huawei@kernel.org>
+Stable-dep-of: b2701715301a ("media: cadence: csi2rx: Unregister v4l2 async notifier")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/media/platform/rcar-vin/rcar-core.c | 82 +++++++++++----------
+ 1 file changed, 45 insertions(+), 37 deletions(-)
+
+diff --git a/drivers/media/platform/rcar-vin/rcar-core.c b/drivers/media/platform/rcar-vin/rcar-core.c
+index 33957cc9118ca..6ea561fcd7a39 100644
+--- a/drivers/media/platform/rcar-vin/rcar-core.c
++++ b/drivers/media/platform/rcar-vin/rcar-core.c
+@@ -405,6 +405,45 @@ static const struct v4l2_ctrl_ops rvin_ctrl_ops = {
+ .s_ctrl = rvin_s_ctrl,
+ };
+
++static void rvin_free_controls(struct rvin_dev *vin)
++{
++ v4l2_ctrl_handler_free(&vin->ctrl_handler);
++ vin->vdev.ctrl_handler = NULL;
++}
++
++static int rvin_create_controls(struct rvin_dev *vin, struct v4l2_subdev *subdev)
++{
++ int ret;
++
++ ret = v4l2_ctrl_handler_init(&vin->ctrl_handler, 16);
++ if (ret < 0)
++ return ret;
++
++ /* The VIN directly deals with alpha component. */
++ v4l2_ctrl_new_std(&vin->ctrl_handler, &rvin_ctrl_ops,
++ V4L2_CID_ALPHA_COMPONENT, 0, 255, 1, 255);
++
++ if (vin->ctrl_handler.error) {
++ ret = vin->ctrl_handler.error;
++ rvin_free_controls(vin);
++ return ret;
++ }
++
++ /* For the non-MC mode add controls from the subdevice. */
++ if (subdev) {
++ ret = v4l2_ctrl_add_handler(&vin->ctrl_handler,
++ subdev->ctrl_handler, NULL, true);
++ if (ret < 0) {
++ rvin_free_controls(vin);
++ return ret;
++ }
++ }
++
++ vin->vdev.ctrl_handler = &vin->ctrl_handler;
++
++ return 0;
++}
++
+ /* -----------------------------------------------------------------------------
+ * Async notifier
+ */
+@@ -490,28 +529,10 @@ static int rvin_parallel_subdevice_attach(struct rvin_dev *vin,
+ return ret;
+
+ /* Add the controls */
+- ret = v4l2_ctrl_handler_init(&vin->ctrl_handler, 16);
++ ret = rvin_create_controls(vin, subdev);
+ if (ret < 0)
+ return ret;
+
+- v4l2_ctrl_new_std(&vin->ctrl_handler, &rvin_ctrl_ops,
+- V4L2_CID_ALPHA_COMPONENT, 0, 255, 1, 255);
+-
+- if (vin->ctrl_handler.error) {
+- ret = vin->ctrl_handler.error;
+- v4l2_ctrl_handler_free(&vin->ctrl_handler);
+- return ret;
+- }
+-
+- ret = v4l2_ctrl_add_handler(&vin->ctrl_handler, subdev->ctrl_handler,
+- NULL, true);
+- if (ret < 0) {
+- v4l2_ctrl_handler_free(&vin->ctrl_handler);
+- return ret;
+- }
+-
+- vin->vdev.ctrl_handler = &vin->ctrl_handler;
+-
+ vin->parallel.subdev = subdev;
+
+ return 0;
+@@ -522,10 +543,8 @@ static void rvin_parallel_subdevice_detach(struct rvin_dev *vin)
+ rvin_v4l2_unregister(vin);
+ vin->parallel.subdev = NULL;
+
+- if (!vin->info->use_mc) {
+- v4l2_ctrl_handler_free(&vin->ctrl_handler);
+- vin->vdev.ctrl_handler = NULL;
+- }
++ if (!vin->info->use_mc)
++ rvin_free_controls(vin);
+ }
+
+ static int rvin_parallel_notify_complete(struct v4l2_async_notifier *notifier)
+@@ -935,21 +954,10 @@ static int rvin_mc_init(struct rvin_dev *vin)
+ if (ret)
+ rvin_group_put(vin);
+
+- ret = v4l2_ctrl_handler_init(&vin->ctrl_handler, 1);
++ ret = rvin_create_controls(vin, NULL);
+ if (ret < 0)
+ return ret;
+
+- v4l2_ctrl_new_std(&vin->ctrl_handler, &rvin_ctrl_ops,
+- V4L2_CID_ALPHA_COMPONENT, 0, 255, 1, 255);
+-
+- if (vin->ctrl_handler.error) {
+- ret = vin->ctrl_handler.error;
+- v4l2_ctrl_handler_free(&vin->ctrl_handler);
+- return ret;
+- }
+-
+- vin->vdev.ctrl_handler = &vin->ctrl_handler;
+-
+ return ret;
+ }
+
+@@ -1450,7 +1458,7 @@ static int rcar_vin_probe(struct platform_device *pdev)
+ return 0;
+
+ error_group_unregister:
+- v4l2_ctrl_handler_free(&vin->ctrl_handler);
++ rvin_free_controls(vin);
+
+ if (vin->info->use_mc) {
+ mutex_lock(&vin->group->lock);
+@@ -1485,7 +1493,7 @@ static int rcar_vin_remove(struct platform_device *pdev)
+ rvin_group_put(vin);
+ }
+
+- v4l2_ctrl_handler_free(&vin->ctrl_handler);
++ rvin_free_controls(vin);
+
+ rvin_dma_unregister(vin);
+
+--
+2.42.0
+
--- /dev/null
+From e97f8defd2cb0817e26dcab2e9e5ae1b8c2abd3a Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 9 Jul 2021 16:25:54 +0200
+Subject: media: rcar-vin: Rename array storing subdevice information
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Niklas Söderlund <niklas.soderlund+renesas@ragnatech.se>
+
+[ Upstream commit 161b56a82dba29c70fd92c5eb1a8502731a0c832 ]
+
+The VIN group have always been connected to CSI-2 receivers and this
+have spilled over to the naming of the array storing the subdevice
+information. In preparation for connecting other types of subdevices
+rename the array to remotes.
+
+Signed-off-by: Niklas Söderlund <niklas.soderlund+renesas@ragnatech.se>
+Reviewed-by: Jacopo Mondi <jacopo+renesas@jmondi.org>
+Signed-off-by: Sakari Ailus <sakari.ailus@linux.intel.com>
+Signed-off-by: Mauro Carvalho Chehab <mchehab+huawei@kernel.org>
+Stable-dep-of: b2701715301a ("media: cadence: csi2rx: Unregister v4l2 async notifier")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/media/platform/rcar-vin/rcar-core.c | 32 ++++++++++-----------
+ drivers/media/platform/rcar-vin/rcar-vin.h | 8 ++++--
+ 2 files changed, 21 insertions(+), 19 deletions(-)
+
+diff --git a/drivers/media/platform/rcar-vin/rcar-core.c b/drivers/media/platform/rcar-vin/rcar-core.c
+index 93a32be692e9a..867d8fd7a77d3 100644
+--- a/drivers/media/platform/rcar-vin/rcar-core.c
++++ b/drivers/media/platform/rcar-vin/rcar-core.c
+@@ -49,16 +49,16 @@
+ */
+
+ /* group lock should be held when calling this function. */
+-static int rvin_group_entity_to_csi_id(struct rvin_group *group,
+- struct media_entity *entity)
++static int rvin_group_entity_to_remote_id(struct rvin_group *group,
++ struct media_entity *entity)
+ {
+ struct v4l2_subdev *sd;
+ unsigned int i;
+
+ sd = media_entity_to_v4l2_subdev(entity);
+
+- for (i = 0; i < RVIN_CSI_MAX; i++)
+- if (group->csi[i].subdev == sd)
++ for (i = 0; i < RVIN_REMOTES_MAX; i++)
++ if (group->remotes[i].subdev == sd)
+ return i;
+
+ return -ENODEV;
+@@ -163,14 +163,14 @@ static int rvin_group_link_notify(struct media_link *link, u32 flags,
+ if (!csi_pad)
+ continue;
+
+- csi_id = rvin_group_entity_to_csi_id(group, csi_pad->entity);
++ csi_id = rvin_group_entity_to_remote_id(group, csi_pad->entity);
+ channel = rvin_group_csi_pad_to_channel(csi_pad->index);
+
+ mask &= rvin_group_get_mask(group->vin[i], csi_id, channel);
+ }
+
+ /* Add the new link to the existing mask and check if it works. */
+- csi_id = rvin_group_entity_to_csi_id(group, link->source->entity);
++ csi_id = rvin_group_entity_to_remote_id(group, link->source->entity);
+
+ if (csi_id == -ENODEV) {
+ struct v4l2_subdev *sd;
+@@ -767,10 +767,10 @@ static int rvin_group_notify_complete(struct v4l2_async_notifier *notifier)
+ continue;
+
+ /* Check that CSI-2 is part of the group. */
+- if (!vin->group->csi[route->csi].subdev)
++ if (!vin->group->remotes[route->csi].subdev)
+ continue;
+
+- source = &vin->group->csi[route->csi].subdev->entity;
++ source = &vin->group->remotes[route->csi].subdev->entity;
+ source_idx = rvin_group_csi_channel_to_pad(route->channel);
+ source_pad = &source->pads[source_idx];
+
+@@ -807,10 +807,10 @@ static void rvin_group_notify_unbind(struct v4l2_async_notifier *notifier,
+ mutex_lock(&vin->group->lock);
+
+ for (i = 0; i < RVIN_CSI_MAX; i++) {
+- if (vin->group->csi[i].asd != asd)
++ if (vin->group->remotes[i].asd != asd)
+ continue;
+- vin->group->csi[i].subdev = NULL;
+- vin_dbg(vin, "Unbind CSI-2 %s from slot %u\n", subdev->name, i);
++ vin->group->remotes[i].subdev = NULL;
++ vin_dbg(vin, "Unbind %s from slot %u\n", subdev->name, i);
+ break;
+ }
+
+@@ -829,10 +829,10 @@ static int rvin_group_notify_bound(struct v4l2_async_notifier *notifier,
+ mutex_lock(&vin->group->lock);
+
+ for (i = 0; i < RVIN_CSI_MAX; i++) {
+- if (vin->group->csi[i].asd != asd)
++ if (vin->group->remotes[i].asd != asd)
+ continue;
+- vin->group->csi[i].subdev = subdev;
+- vin_dbg(vin, "Bound CSI-2 %s to slot %u\n", subdev->name, i);
++ vin->group->remotes[i].subdev = subdev;
++ vin_dbg(vin, "Bound %s to slot %u\n", subdev->name, i);
+ break;
+ }
+
+@@ -884,7 +884,7 @@ static int rvin_mc_parse_of(struct rvin_dev *vin, unsigned int id)
+ goto out;
+ }
+
+- vin->group->csi[vep.base.id].asd = asd;
++ vin->group->remotes[vep.base.id].asd = asd;
+
+ vin_dbg(vin, "Add group OF device %pOF to slot %u\n",
+ to_of_node(fwnode), vep.base.id);
+@@ -929,7 +929,7 @@ static int rvin_mc_parse_of_graph(struct rvin_dev *vin)
+ continue;
+
+ for (id = 0; id < RVIN_CSI_MAX; id++) {
+- if (vin->group->csi[id].asd)
++ if (vin->group->remotes[id].asd)
+ continue;
+
+ ret = rvin_mc_parse_of(vin->group->vin[i], id);
+diff --git a/drivers/media/platform/rcar-vin/rcar-vin.h b/drivers/media/platform/rcar-vin/rcar-vin.h
+index b263ead4db2bf..39207aaf39ef9 100644
+--- a/drivers/media/platform/rcar-vin/rcar-vin.h
++++ b/drivers/media/platform/rcar-vin/rcar-vin.h
+@@ -48,6 +48,8 @@ enum rvin_csi_id {
+ RVIN_CSI_MAX,
+ };
+
++#define RVIN_REMOTES_MAX RVIN_CSI_MAX
++
+ /**
+ * enum rvin_dma_state - DMA states
+ * @STOPPED: No operation in progress
+@@ -267,8 +269,8 @@ struct rvin_dev {
+ * @count: number of enabled VIN instances found in DT
+ * @notifier: group notifier for CSI-2 async subdevices
+ * @vin: VIN instances which are part of the group
+- * @csi: array of pairs of fwnode and subdev pointers
+- * to all CSI-2 subdevices.
++ * @remotes: array of pairs of fwnode and subdev pointers
++ * to all remote subdevices.
+ */
+ struct rvin_group {
+ struct kref refcount;
+@@ -283,7 +285,7 @@ struct rvin_group {
+ struct {
+ struct v4l2_async_subdev *asd;
+ struct v4l2_subdev *subdev;
+- } csi[RVIN_CSI_MAX];
++ } remotes[RVIN_REMOTES_MAX];
+ };
+
+ int rvin_dma_register(struct rvin_dev *vin, int irq);
+--
+2.42.0
+
--- /dev/null
+From 11146f33ed2d6ba7198dc674e9a438cbf03abdec Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 22 Sep 2023 14:55:06 +0300
+Subject: media: s3c-camif: Avoid inappropriate kfree()
+
+From: Katya Orlova <e.orlova@ispras.ru>
+
+[ Upstream commit 61334819aca018c3416ee6c330a08a49c1524fc3 ]
+
+s3c_camif_register_video_node() works with video_device structure stored
+as a field of camif_vp, so it should not be kfreed.
+But there is video_device_release() on error path that do it.
+
+Found by Linux Verification Center (linuxtesting.org) with SVACE.
+
+Fixes: babde1c243b2 ("[media] V4L: Add driver for S3C24XX/S3C64XX SoC series camera interface")
+Signed-off-by: Katya Orlova <e.orlova@ispras.ru>
+Signed-off-by: Hans Verkuil <hverkuil-cisco@xs4all.nl>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/media/platform/s3c-camif/camif-capture.c | 6 ++----
+ 1 file changed, 2 insertions(+), 4 deletions(-)
+
+diff --git a/drivers/media/platform/s3c-camif/camif-capture.c b/drivers/media/platform/s3c-camif/camif-capture.c
+index 140854ab4dd8c..d6b7fbd49a5cc 100644
+--- a/drivers/media/platform/s3c-camif/camif-capture.c
++++ b/drivers/media/platform/s3c-camif/camif-capture.c
+@@ -1132,12 +1132,12 @@ int s3c_camif_register_video_node(struct camif_dev *camif, int idx)
+
+ ret = vb2_queue_init(q);
+ if (ret)
+- goto err_vd_rel;
++ return ret;
+
+ vp->pad.flags = MEDIA_PAD_FL_SINK;
+ ret = media_entity_pads_init(&vfd->entity, 1, &vp->pad);
+ if (ret)
+- goto err_vd_rel;
++ return ret;
+
+ video_set_drvdata(vfd, vp);
+
+@@ -1170,8 +1170,6 @@ int s3c_camif_register_video_node(struct camif_dev *camif, int idx)
+ v4l2_ctrl_handler_free(&vp->ctrl_handler);
+ err_me_cleanup:
+ media_entity_cleanup(&vfd->entity);
+-err_vd_rel:
+- video_device_release(vfd);
+ return ret;
+ }
+
+--
+2.42.0
+
--- /dev/null
+From 9da6daba0739fbf48b32eaa2695cd30c7d12b1de Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 5 Mar 2021 18:13:12 +0100
+Subject: media: v4l: async: Rename async nf functions, clean up long lines
+
+From: Sakari Ailus <sakari.ailus@linux.intel.com>
+
+[ Upstream commit 3c8c153914812a98eaa0b5a6cf09c511a06aafbe ]
+
+Rename V4L2 async notifier functions, replacing "notifier" with "nf" and
+removing "_subdev" at the end of the function names adding subdevs as you
+can only add subdevs to a notifier. Also wrap and otherwise clean up long
+lines.
+
+Signed-off-by: Sakari Ailus <sakari.ailus@linux.intel.com>
+Reviewed-by: Jacopo Mondi <jacopo@jmondi.org>
+Reviewed-by: Rui Miguel Silva <rmfrfs@gmail.com> (imx7)
+Signed-off-by: Mauro Carvalho Chehab <mchehab+huawei@kernel.org>
+Stable-dep-of: b2701715301a ("media: cadence: csi2rx: Unregister v4l2 async notifier")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ .../driver-api/media/v4l2-subdev.rst | 14 +-
+ drivers/media/i2c/max9286.c | 17 +-
+ drivers/media/i2c/st-mipid02.c | 22 ++-
+ drivers/media/pci/intel/ipu3/ipu3-cio2-main.c | 17 +-
+ drivers/media/platform/am437x/am437x-vpfe.c | 19 +-
+ drivers/media/platform/atmel/atmel-isc-base.c | 4 +-
+ drivers/media/platform/atmel/atmel-isi.c | 17 +-
+ .../media/platform/atmel/atmel-sama5d2-isc.c | 15 +-
+ .../media/platform/atmel/atmel-sama7g5-isc.c | 15 +-
+ drivers/media/platform/cadence/cdns-csi2rx.c | 14 +-
+ drivers/media/platform/davinci/vpif_capture.c | 21 +--
+ drivers/media/platform/exynos4-is/media-dev.c | 20 +--
+ .../media/platform/marvell-ccic/cafe-driver.c | 9 +-
+ .../media/platform/marvell-ccic/mcam-core.c | 10 +-
+ .../media/platform/marvell-ccic/mmp-driver.c | 6 +-
+ drivers/media/platform/omap3isp/isp.c | 21 ++-
+ drivers/media/platform/pxa_camera.c | 26 ++-
+ drivers/media/platform/qcom/camss/camss.c | 18 +-
+ drivers/media/platform/rcar-vin/rcar-core.c | 30 ++--
+ drivers/media/platform/rcar-vin/rcar-csi2.c | 19 +-
+ drivers/media/platform/rcar_drif.c | 14 +-
+ drivers/media/platform/renesas-ceu.c | 29 ++-
+ .../platform/rockchip/rkisp1/rkisp1-dev.c | 17 +-
+ drivers/media/platform/stm32/stm32-dcmi.c | 18 +-
+ .../platform/sunxi/sun4i-csi/sun4i_csi.c | 12 +-
+ .../platform/sunxi/sun6i-csi/sun6i_csi.c | 19 +-
+ drivers/media/platform/ti-vpe/cal.c | 16 +-
+ drivers/media/platform/video-mux.c | 17 +-
+ drivers/media/platform/xilinx/xilinx-vipp.c | 17 +-
+ drivers/media/v4l2-core/v4l2-async.c | 168 +++++++++---------
+ drivers/media/v4l2-core/v4l2-fwnode.c | 74 ++++----
+ drivers/staging/media/imx/imx-media-csi.c | 17 +-
+ .../staging/media/imx/imx-media-dev-common.c | 7 +-
+ drivers/staging/media/imx/imx-media-dev.c | 6 +-
+ drivers/staging/media/imx/imx-media-of.c | 6 +-
+ drivers/staging/media/imx/imx6-mipi-csi2.c | 17 +-
+ drivers/staging/media/imx/imx7-media-csi.c | 24 +--
+ drivers/staging/media/imx/imx7-mipi-csis.c | 16 +-
+ drivers/staging/media/imx/imx8mq-mipi-csi2.c | 16 +-
+ drivers/staging/media/tegra-video/vi.c | 17 +-
+ include/media/v4l2-async.h | 105 ++++++-----
+ include/media/v4l2-fwnode.h | 12 +-
+ 42 files changed, 479 insertions(+), 499 deletions(-)
+
+diff --git a/Documentation/driver-api/media/v4l2-subdev.rst b/Documentation/driver-api/media/v4l2-subdev.rst
+index 7736da077fb87..08ea2673b19e3 100644
+--- a/Documentation/driver-api/media/v4l2-subdev.rst
++++ b/Documentation/driver-api/media/v4l2-subdev.rst
+@@ -191,21 +191,21 @@ registered this way are stored in a global list of subdevices, ready to be
+ picked up by bridge drivers.
+
+ Bridge drivers in turn have to register a notifier object. This is
+-performed using the :c:func:`v4l2_async_notifier_register` call. To
++performed using the :c:func:`v4l2_async_nf_register` call. To
+ unregister the notifier the driver has to call
+-:c:func:`v4l2_async_notifier_unregister`. The former of the two functions
++:c:func:`v4l2_async_nf_unregister`. The former of the two functions
+ takes two arguments: a pointer to struct :c:type:`v4l2_device` and a
+ pointer to struct :c:type:`v4l2_async_notifier`.
+
+ Before registering the notifier, bridge drivers must do two things: first, the
+-notifier must be initialized using the :c:func:`v4l2_async_notifier_init`.
++notifier must be initialized using the :c:func:`v4l2_async_nf_init`.
+ Second, bridge drivers can then begin to form a list of subdevice descriptors
+ that the bridge device needs for its operation. Several functions are available
+ to add subdevice descriptors to a notifier, depending on the type of device and
+ the needs of the driver.
+
+-:c:func:`v4l2_async_notifier_add_fwnode_remote_subdev` and
+-:c:func:`v4l2_async_notifier_add_i2c_subdev` are for bridge and ISP drivers for
++:c:func:`v4l2_async_nf_add_fwnode_remote` and
++:c:func:`v4l2_async_nf_add_i2c` are for bridge and ISP drivers for
+ registering their async sub-devices with the notifier.
+
+ :c:func:`v4l2_async_register_subdev_sensor` is a helper function for
+@@ -230,8 +230,8 @@ These functions allocate an async sub-device descriptor which is of type struct
+
+ ...
+
+- my_asd = v4l2_async_notifier_add_fwnode_remote_subdev(¬ifier, ep,
+- struct my_async_subdev);
++ my_asd = v4l2_async_nf_add_fwnode_remote(¬ifier, ep,
++ struct my_async_subdev);
+ fwnode_handle_put(ep);
+
+ if (IS_ERR(asd))
+diff --git a/drivers/media/i2c/max9286.c b/drivers/media/i2c/max9286.c
+index 1b9beaee6bea7..b5fed8a52c44b 100644
+--- a/drivers/media/i2c/max9286.c
++++ b/drivers/media/i2c/max9286.c
+@@ -609,19 +609,18 @@ static int max9286_v4l2_notifier_register(struct max9286_priv *priv)
+ if (!priv->nsources)
+ return 0;
+
+- v4l2_async_notifier_init(&priv->notifier);
++ v4l2_async_nf_init(&priv->notifier);
+
+ for_each_source(priv, source) {
+ unsigned int i = to_index(priv, source);
+ struct max9286_asd *mas;
+
+- mas = v4l2_async_notifier_add_fwnode_subdev(&priv->notifier,
+- source->fwnode,
+- struct max9286_asd);
++ mas = v4l2_async_nf_add_fwnode(&priv->notifier, source->fwnode,
++ struct max9286_asd);
+ if (IS_ERR(mas)) {
+ dev_err(dev, "Failed to add subdev for source %u: %ld",
+ i, PTR_ERR(mas));
+- v4l2_async_notifier_cleanup(&priv->notifier);
++ v4l2_async_nf_cleanup(&priv->notifier);
+ return PTR_ERR(mas);
+ }
+
+@@ -630,10 +629,10 @@ static int max9286_v4l2_notifier_register(struct max9286_priv *priv)
+
+ priv->notifier.ops = &max9286_notify_ops;
+
+- ret = v4l2_async_subdev_notifier_register(&priv->sd, &priv->notifier);
++ ret = v4l2_async_subdev_nf_register(&priv->sd, &priv->notifier);
+ if (ret) {
+ dev_err(dev, "Failed to register subdev_notifier");
+- v4l2_async_notifier_cleanup(&priv->notifier);
++ v4l2_async_nf_cleanup(&priv->notifier);
+ return ret;
+ }
+
+@@ -645,8 +644,8 @@ static void max9286_v4l2_notifier_unregister(struct max9286_priv *priv)
+ if (!priv->nsources)
+ return;
+
+- v4l2_async_notifier_unregister(&priv->notifier);
+- v4l2_async_notifier_cleanup(&priv->notifier);
++ v4l2_async_nf_unregister(&priv->notifier);
++ v4l2_async_nf_cleanup(&priv->notifier);
+ }
+
+ static int max9286_s_stream(struct v4l2_subdev *sd, int enable)
+diff --git a/drivers/media/i2c/st-mipid02.c b/drivers/media/i2c/st-mipid02.c
+index cf55c57a79707..f8615d95b4826 100644
+--- a/drivers/media/i2c/st-mipid02.c
++++ b/drivers/media/i2c/st-mipid02.c
+@@ -881,11 +881,10 @@ static int mipid02_parse_rx_ep(struct mipid02_dev *bridge)
+ bridge->rx = ep;
+
+ /* register async notifier so we get noticed when sensor is connected */
+- v4l2_async_notifier_init(&bridge->notifier);
+- asd = v4l2_async_notifier_add_fwnode_remote_subdev(
+- &bridge->notifier,
+- of_fwnode_handle(ep_node),
+- struct v4l2_async_subdev);
++ v4l2_async_nf_init(&bridge->notifier);
++ asd = v4l2_async_nf_add_fwnode_remote(&bridge->notifier,
++ of_fwnode_handle(ep_node),
++ struct v4l2_async_subdev);
+ of_node_put(ep_node);
+
+ if (IS_ERR(asd)) {
+@@ -895,10 +894,9 @@ static int mipid02_parse_rx_ep(struct mipid02_dev *bridge)
+ }
+ bridge->notifier.ops = &mipid02_notifier_ops;
+
+- ret = v4l2_async_subdev_notifier_register(&bridge->sd,
+- &bridge->notifier);
++ ret = v4l2_async_subdev_nf_register(&bridge->sd, &bridge->notifier);
+ if (ret)
+- v4l2_async_notifier_cleanup(&bridge->notifier);
++ v4l2_async_nf_cleanup(&bridge->notifier);
+
+ return ret;
+
+@@ -1036,8 +1034,8 @@ static int mipid02_probe(struct i2c_client *client)
+ return 0;
+
+ unregister_notifier:
+- v4l2_async_notifier_unregister(&bridge->notifier);
+- v4l2_async_notifier_cleanup(&bridge->notifier);
++ v4l2_async_nf_unregister(&bridge->notifier);
++ v4l2_async_nf_cleanup(&bridge->notifier);
+ power_off:
+ mipid02_set_power_off(bridge);
+ entity_cleanup:
+@@ -1053,8 +1051,8 @@ static int mipid02_remove(struct i2c_client *client)
+ struct v4l2_subdev *sd = i2c_get_clientdata(client);
+ struct mipid02_dev *bridge = to_mipid02_dev(sd);
+
+- v4l2_async_notifier_unregister(&bridge->notifier);
+- v4l2_async_notifier_cleanup(&bridge->notifier);
++ v4l2_async_nf_unregister(&bridge->notifier);
++ v4l2_async_nf_cleanup(&bridge->notifier);
+ v4l2_async_unregister_subdev(&bridge->sd);
+ mipid02_set_power_off(bridge);
+ media_entity_cleanup(&bridge->sd.entity);
+diff --git a/drivers/media/pci/intel/ipu3/ipu3-cio2-main.c b/drivers/media/pci/intel/ipu3/ipu3-cio2-main.c
+index 162ab089124f3..00e2225f1ea3d 100644
+--- a/drivers/media/pci/intel/ipu3/ipu3-cio2-main.c
++++ b/drivers/media/pci/intel/ipu3/ipu3-cio2-main.c
+@@ -1478,8 +1478,9 @@ static int cio2_parse_firmware(struct cio2_device *cio2)
+ if (ret)
+ goto err_parse;
+
+- s_asd = v4l2_async_notifier_add_fwnode_remote_subdev(
+- &cio2->notifier, ep, struct sensor_async_subdev);
++ s_asd = v4l2_async_nf_add_fwnode_remote(&cio2->notifier, ep,
++ struct
++ sensor_async_subdev);
+ if (IS_ERR(s_asd)) {
+ ret = PTR_ERR(s_asd);
+ goto err_parse;
+@@ -1502,7 +1503,7 @@ static int cio2_parse_firmware(struct cio2_device *cio2)
+ * suspend.
+ */
+ cio2->notifier.ops = &cio2_async_ops;
+- ret = v4l2_async_notifier_register(&cio2->v4l2_dev, &cio2->notifier);
++ ret = v4l2_async_nf_register(&cio2->v4l2_dev, &cio2->notifier);
+ if (ret)
+ dev_err(&cio2->pci_dev->dev,
+ "failed to register async notifier : %d\n", ret);
+@@ -1804,7 +1805,7 @@ static int cio2_pci_probe(struct pci_dev *pci_dev,
+ if (r)
+ goto fail_v4l2_device_unregister;
+
+- v4l2_async_notifier_init(&cio2->notifier);
++ v4l2_async_nf_init(&cio2->notifier);
+
+ /* Register notifier for subdevices we care */
+ r = cio2_parse_firmware(cio2);
+@@ -1824,8 +1825,8 @@ static int cio2_pci_probe(struct pci_dev *pci_dev,
+ return 0;
+
+ fail_clean_notifier:
+- v4l2_async_notifier_unregister(&cio2->notifier);
+- v4l2_async_notifier_cleanup(&cio2->notifier);
++ v4l2_async_nf_unregister(&cio2->notifier);
++ v4l2_async_nf_cleanup(&cio2->notifier);
+ cio2_queues_exit(cio2);
+ fail_v4l2_device_unregister:
+ v4l2_device_unregister(&cio2->v4l2_dev);
+@@ -1844,8 +1845,8 @@ static void cio2_pci_remove(struct pci_dev *pci_dev)
+ struct cio2_device *cio2 = pci_get_drvdata(pci_dev);
+
+ media_device_unregister(&cio2->media_dev);
+- v4l2_async_notifier_unregister(&cio2->notifier);
+- v4l2_async_notifier_cleanup(&cio2->notifier);
++ v4l2_async_nf_unregister(&cio2->notifier);
++ v4l2_async_nf_cleanup(&cio2->notifier);
+ cio2_queues_exit(cio2);
+ cio2_fbpt_exit_dummy(cio2);
+ v4l2_device_unregister(&cio2->v4l2_dev);
+diff --git a/drivers/media/platform/am437x/am437x-vpfe.c b/drivers/media/platform/am437x/am437x-vpfe.c
+index c1ce93efc6559..38fe7f67d51e5 100644
+--- a/drivers/media/platform/am437x/am437x-vpfe.c
++++ b/drivers/media/platform/am437x/am437x-vpfe.c
+@@ -2298,7 +2298,7 @@ vpfe_get_pdata(struct vpfe_device *vpfe)
+
+ dev_dbg(dev, "vpfe_get_pdata\n");
+
+- v4l2_async_notifier_init(&vpfe->notifier);
++ v4l2_async_nf_init(&vpfe->notifier);
+
+ if (!IS_ENABLED(CONFIG_OF) || !dev->of_node)
+ return dev->platform_data;
+@@ -2366,9 +2366,10 @@ vpfe_get_pdata(struct vpfe_device *vpfe)
+ goto cleanup;
+ }
+
+- pdata->asd[i] = v4l2_async_notifier_add_fwnode_subdev(
+- &vpfe->notifier, of_fwnode_handle(rem),
+- struct v4l2_async_subdev);
++ pdata->asd[i] = v4l2_async_nf_add_fwnode(&vpfe->notifier,
++ of_fwnode_handle(rem),
++ struct
++ v4l2_async_subdev);
+ of_node_put(rem);
+ if (IS_ERR(pdata->asd[i]))
+ goto cleanup;
+@@ -2378,7 +2379,7 @@ vpfe_get_pdata(struct vpfe_device *vpfe)
+ return pdata;
+
+ cleanup:
+- v4l2_async_notifier_cleanup(&vpfe->notifier);
++ v4l2_async_nf_cleanup(&vpfe->notifier);
+ of_node_put(endpoint);
+ return NULL;
+ }
+@@ -2466,7 +2467,7 @@ static int vpfe_probe(struct platform_device *pdev)
+ }
+
+ vpfe->notifier.ops = &vpfe_async_ops;
+- ret = v4l2_async_notifier_register(&vpfe->v4l2_dev, &vpfe->notifier);
++ ret = v4l2_async_nf_register(&vpfe->v4l2_dev, &vpfe->notifier);
+ if (ret) {
+ vpfe_err(vpfe, "Error registering async notifier\n");
+ ret = -EINVAL;
+@@ -2478,7 +2479,7 @@ static int vpfe_probe(struct platform_device *pdev)
+ probe_out_v4l2_unregister:
+ v4l2_device_unregister(&vpfe->v4l2_dev);
+ probe_out_cleanup:
+- v4l2_async_notifier_cleanup(&vpfe->notifier);
++ v4l2_async_nf_cleanup(&vpfe->notifier);
+ return ret;
+ }
+
+@@ -2491,8 +2492,8 @@ static int vpfe_remove(struct platform_device *pdev)
+
+ pm_runtime_disable(&pdev->dev);
+
+- v4l2_async_notifier_unregister(&vpfe->notifier);
+- v4l2_async_notifier_cleanup(&vpfe->notifier);
++ v4l2_async_nf_unregister(&vpfe->notifier);
++ v4l2_async_nf_cleanup(&vpfe->notifier);
+ v4l2_device_unregister(&vpfe->v4l2_dev);
+ video_unregister_device(&vpfe->video_dev);
+
+diff --git a/drivers/media/platform/atmel/atmel-isc-base.c b/drivers/media/platform/atmel/atmel-isc-base.c
+index f768be3c40595..24807782c9e50 100644
+--- a/drivers/media/platform/atmel/atmel-isc-base.c
++++ b/drivers/media/platform/atmel/atmel-isc-base.c
+@@ -2217,8 +2217,8 @@ void isc_subdev_cleanup(struct isc_device *isc)
+ struct isc_subdev_entity *subdev_entity;
+
+ list_for_each_entry(subdev_entity, &isc->subdev_entities, list) {
+- v4l2_async_notifier_unregister(&subdev_entity->notifier);
+- v4l2_async_notifier_cleanup(&subdev_entity->notifier);
++ v4l2_async_nf_unregister(&subdev_entity->notifier);
++ v4l2_async_nf_cleanup(&subdev_entity->notifier);
+ }
+
+ INIT_LIST_HEAD(&isc->subdev_entities);
+diff --git a/drivers/media/platform/atmel/atmel-isi.c b/drivers/media/platform/atmel/atmel-isi.c
+index 095d80c4f59e7..4d15814e4481c 100644
+--- a/drivers/media/platform/atmel/atmel-isi.c
++++ b/drivers/media/platform/atmel/atmel-isi.c
+@@ -1159,12 +1159,11 @@ static int isi_graph_init(struct atmel_isi *isi)
+ if (!ep)
+ return -EINVAL;
+
+- v4l2_async_notifier_init(&isi->notifier);
++ v4l2_async_nf_init(&isi->notifier);
+
+- asd = v4l2_async_notifier_add_fwnode_remote_subdev(
+- &isi->notifier,
+- of_fwnode_handle(ep),
+- struct v4l2_async_subdev);
++ asd = v4l2_async_nf_add_fwnode_remote(&isi->notifier,
++ of_fwnode_handle(ep),
++ struct v4l2_async_subdev);
+ of_node_put(ep);
+
+ if (IS_ERR(asd))
+@@ -1172,10 +1171,10 @@ static int isi_graph_init(struct atmel_isi *isi)
+
+ isi->notifier.ops = &isi_graph_notify_ops;
+
+- ret = v4l2_async_notifier_register(&isi->v4l2_dev, &isi->notifier);
++ ret = v4l2_async_nf_register(&isi->v4l2_dev, &isi->notifier);
+ if (ret < 0) {
+ dev_err(isi->dev, "Notifier registration failed\n");
+- v4l2_async_notifier_cleanup(&isi->notifier);
++ v4l2_async_nf_cleanup(&isi->notifier);
+ return ret;
+ }
+
+@@ -1327,8 +1326,8 @@ static int atmel_isi_remove(struct platform_device *pdev)
+ isi->p_fb_descriptors,
+ isi->fb_descriptors_phys);
+ pm_runtime_disable(&pdev->dev);
+- v4l2_async_notifier_unregister(&isi->notifier);
+- v4l2_async_notifier_cleanup(&isi->notifier);
++ v4l2_async_nf_unregister(&isi->notifier);
++ v4l2_async_nf_cleanup(&isi->notifier);
+ v4l2_device_unregister(&isi->v4l2_dev);
+
+ return 0;
+diff --git a/drivers/media/platform/atmel/atmel-sama5d2-isc.c b/drivers/media/platform/atmel/atmel-sama5d2-isc.c
+index 7421bc51709c4..a1fd240c6aeb8 100644
+--- a/drivers/media/platform/atmel/atmel-sama5d2-isc.c
++++ b/drivers/media/platform/atmel/atmel-sama5d2-isc.c
+@@ -499,13 +499,14 @@ static int atmel_isc_probe(struct platform_device *pdev)
+
+ list_for_each_entry(subdev_entity, &isc->subdev_entities, list) {
+ struct v4l2_async_subdev *asd;
++ struct fwnode_handle *fwnode =
++ of_fwnode_handle(subdev_entity->epn);
+
+- v4l2_async_notifier_init(&subdev_entity->notifier);
++ v4l2_async_nf_init(&subdev_entity->notifier);
+
+- asd = v4l2_async_notifier_add_fwnode_remote_subdev(
+- &subdev_entity->notifier,
+- of_fwnode_handle(subdev_entity->epn),
+- struct v4l2_async_subdev);
++ asd = v4l2_async_nf_add_fwnode_remote(&subdev_entity->notifier,
++ fwnode,
++ struct v4l2_async_subdev);
+
+ of_node_put(subdev_entity->epn);
+ subdev_entity->epn = NULL;
+@@ -517,8 +518,8 @@ static int atmel_isc_probe(struct platform_device *pdev)
+
+ subdev_entity->notifier.ops = &isc_async_ops;
+
+- ret = v4l2_async_notifier_register(&isc->v4l2_dev,
+- &subdev_entity->notifier);
++ ret = v4l2_async_nf_register(&isc->v4l2_dev,
++ &subdev_entity->notifier);
+ if (ret) {
+ dev_err(dev, "fail to register async notifier\n");
+ goto cleanup_subdev;
+diff --git a/drivers/media/platform/atmel/atmel-sama7g5-isc.c b/drivers/media/platform/atmel/atmel-sama7g5-isc.c
+index a4defc30cf412..366f2afcda193 100644
+--- a/drivers/media/platform/atmel/atmel-sama7g5-isc.c
++++ b/drivers/media/platform/atmel/atmel-sama7g5-isc.c
+@@ -493,13 +493,14 @@ static int microchip_xisc_probe(struct platform_device *pdev)
+
+ list_for_each_entry(subdev_entity, &isc->subdev_entities, list) {
+ struct v4l2_async_subdev *asd;
++ struct fwnode_handle *fwnode =
++ of_fwnode_handle(subdev_entity->epn);
+
+- v4l2_async_notifier_init(&subdev_entity->notifier);
++ v4l2_async_nf_init(&subdev_entity->notifier);
+
+- asd = v4l2_async_notifier_add_fwnode_remote_subdev(
+- &subdev_entity->notifier,
+- of_fwnode_handle(subdev_entity->epn),
+- struct v4l2_async_subdev);
++ asd = v4l2_async_nf_add_fwnode_remote(&subdev_entity->notifier,
++ fwnode,
++ struct v4l2_async_subdev);
+
+ of_node_put(subdev_entity->epn);
+ subdev_entity->epn = NULL;
+@@ -511,8 +512,8 @@ static int microchip_xisc_probe(struct platform_device *pdev)
+
+ subdev_entity->notifier.ops = &isc_async_ops;
+
+- ret = v4l2_async_notifier_register(&isc->v4l2_dev,
+- &subdev_entity->notifier);
++ ret = v4l2_async_nf_register(&isc->v4l2_dev,
++ &subdev_entity->notifier);
+ if (ret) {
+ dev_err(dev, "fail to register async notifier\n");
+ goto cleanup_subdev;
+diff --git a/drivers/media/platform/cadence/cdns-csi2rx.c b/drivers/media/platform/cadence/cdns-csi2rx.c
+index f2b4ddd31177b..7b44ab2b8c9ad 100644
+--- a/drivers/media/platform/cadence/cdns-csi2rx.c
++++ b/drivers/media/platform/cadence/cdns-csi2rx.c
+@@ -401,21 +401,19 @@ static int csi2rx_parse_dt(struct csi2rx_priv *csi2rx)
+ return -EINVAL;
+ }
+
+- v4l2_async_notifier_init(&csi2rx->notifier);
++ v4l2_async_nf_init(&csi2rx->notifier);
+
+- asd = v4l2_async_notifier_add_fwnode_remote_subdev(&csi2rx->notifier,
+- fwh,
+- struct v4l2_async_subdev);
++ asd = v4l2_async_nf_add_fwnode_remote(&csi2rx->notifier, fwh,
++ struct v4l2_async_subdev);
+ of_node_put(ep);
+ if (IS_ERR(asd))
+ return PTR_ERR(asd);
+
+ csi2rx->notifier.ops = &csi2rx_notifier_ops;
+
+- ret = v4l2_async_subdev_notifier_register(&csi2rx->subdev,
+- &csi2rx->notifier);
++ ret = v4l2_async_subdev_nf_register(&csi2rx->subdev, &csi2rx->notifier);
+ if (ret)
+- v4l2_async_notifier_cleanup(&csi2rx->notifier);
++ v4l2_async_nf_cleanup(&csi2rx->notifier);
+
+ return ret;
+ }
+@@ -471,7 +469,7 @@ static int csi2rx_probe(struct platform_device *pdev)
+ return 0;
+
+ err_cleanup:
+- v4l2_async_notifier_cleanup(&csi2rx->notifier);
++ v4l2_async_nf_cleanup(&csi2rx->notifier);
+ err_free_priv:
+ kfree(csi2rx);
+ return ret;
+diff --git a/drivers/media/platform/davinci/vpif_capture.c b/drivers/media/platform/davinci/vpif_capture.c
+index c034e25dd9aae..ae92e2c206d04 100644
+--- a/drivers/media/platform/davinci/vpif_capture.c
++++ b/drivers/media/platform/davinci/vpif_capture.c
+@@ -1506,7 +1506,7 @@ vpif_capture_get_pdata(struct platform_device *pdev)
+ struct vpif_capture_chan_config *chan;
+ unsigned int i;
+
+- v4l2_async_notifier_init(&vpif_obj.notifier);
++ v4l2_async_nf_init(&vpif_obj.notifier);
+
+ /*
+ * DT boot: OF node from parent device contains
+@@ -1582,9 +1582,10 @@ vpif_capture_get_pdata(struct platform_device *pdev)
+ dev_dbg(&pdev->dev, "Remote device %pOF found\n", rem);
+ sdinfo->name = rem->full_name;
+
+- pdata->asd[i] = v4l2_async_notifier_add_fwnode_subdev(
+- &vpif_obj.notifier, of_fwnode_handle(rem),
+- struct v4l2_async_subdev);
++ pdata->asd[i] = v4l2_async_nf_add_fwnode(&vpif_obj.notifier,
++ of_fwnode_handle(rem),
++ struct
++ v4l2_async_subdev);
+ if (IS_ERR(pdata->asd[i]))
+ goto err_cleanup;
+
+@@ -1602,7 +1603,7 @@ vpif_capture_get_pdata(struct platform_device *pdev)
+ err_cleanup:
+ of_node_put(rem);
+ of_node_put(endpoint);
+- v4l2_async_notifier_cleanup(&vpif_obj.notifier);
++ v4l2_async_nf_cleanup(&vpif_obj.notifier);
+
+ return NULL;
+ }
+@@ -1692,8 +1693,8 @@ static __init int vpif_probe(struct platform_device *pdev)
+ goto probe_subdev_out;
+ } else {
+ vpif_obj.notifier.ops = &vpif_async_ops;
+- err = v4l2_async_notifier_register(&vpif_obj.v4l2_dev,
+- &vpif_obj.notifier);
++ err = v4l2_async_nf_register(&vpif_obj.v4l2_dev,
++ &vpif_obj.notifier);
+ if (err) {
+ vpif_err("Error registering async notifier\n");
+ err = -EINVAL;
+@@ -1711,7 +1712,7 @@ static __init int vpif_probe(struct platform_device *pdev)
+ vpif_free:
+ free_vpif_objs();
+ cleanup:
+- v4l2_async_notifier_cleanup(&vpif_obj.notifier);
++ v4l2_async_nf_cleanup(&vpif_obj.notifier);
+
+ return err;
+ }
+@@ -1727,8 +1728,8 @@ static int vpif_remove(struct platform_device *device)
+ struct channel_obj *ch;
+ int i;
+
+- v4l2_async_notifier_unregister(&vpif_obj.notifier);
+- v4l2_async_notifier_cleanup(&vpif_obj.notifier);
++ v4l2_async_nf_unregister(&vpif_obj.notifier);
++ v4l2_async_nf_cleanup(&vpif_obj.notifier);
+ v4l2_device_unregister(&vpif_obj.v4l2_dev);
+
+ kfree(vpif_obj.sd);
+diff --git a/drivers/media/platform/exynos4-is/media-dev.c b/drivers/media/platform/exynos4-is/media-dev.c
+index b19d7c8ddc06b..b2d8b2c0ab4d6 100644
+--- a/drivers/media/platform/exynos4-is/media-dev.c
++++ b/drivers/media/platform/exynos4-is/media-dev.c
+@@ -464,9 +464,9 @@ static int fimc_md_parse_one_endpoint(struct fimc_md *fmd,
+ return -EINVAL;
+ }
+
+- asd = v4l2_async_notifier_add_fwnode_remote_subdev(
+- &fmd->subdev_notifier, of_fwnode_handle(ep),
+- struct v4l2_async_subdev);
++ asd = v4l2_async_nf_add_fwnode_remote(&fmd->subdev_notifier,
++ of_fwnode_handle(ep),
++ struct v4l2_async_subdev);
+
+ of_node_put(ep);
+
+@@ -557,7 +557,7 @@ static int fimc_md_register_sensor_entities(struct fimc_md *fmd)
+
+ cleanup:
+ of_node_put(ports);
+- v4l2_async_notifier_cleanup(&fmd->subdev_notifier);
++ v4l2_async_nf_cleanup(&fmd->subdev_notifier);
+ pm_runtime_put(fmd->pmf);
+ return ret;
+ }
+@@ -1479,7 +1479,7 @@ static int fimc_md_probe(struct platform_device *pdev)
+
+ platform_set_drvdata(pdev, fmd);
+
+- v4l2_async_notifier_init(&fmd->subdev_notifier);
++ v4l2_async_nf_init(&fmd->subdev_notifier);
+
+ ret = fimc_md_register_platform_entities(fmd, dev->of_node);
+ if (ret)
+@@ -1507,8 +1507,8 @@ static int fimc_md_probe(struct platform_device *pdev)
+ fmd->subdev_notifier.ops = &subdev_notifier_ops;
+ fmd->num_sensors = 0;
+
+- ret = v4l2_async_notifier_register(&fmd->v4l2_dev,
+- &fmd->subdev_notifier);
++ ret = v4l2_async_nf_register(&fmd->v4l2_dev,
++ &fmd->subdev_notifier);
+ if (ret)
+ goto err_clk_p;
+ }
+@@ -1520,7 +1520,7 @@ static int fimc_md_probe(struct platform_device *pdev)
+ err_attr:
+ device_remove_file(&pdev->dev, &dev_attr_subdev_conf_mode);
+ err_cleanup:
+- v4l2_async_notifier_cleanup(&fmd->subdev_notifier);
++ v4l2_async_nf_cleanup(&fmd->subdev_notifier);
+ err_m_ent:
+ fimc_md_unregister_entities(fmd);
+ err_clk:
+@@ -1540,8 +1540,8 @@ static int fimc_md_remove(struct platform_device *pdev)
+ return 0;
+
+ fimc_md_unregister_clk_provider(fmd);
+- v4l2_async_notifier_unregister(&fmd->subdev_notifier);
+- v4l2_async_notifier_cleanup(&fmd->subdev_notifier);
++ v4l2_async_nf_unregister(&fmd->subdev_notifier);
++ v4l2_async_nf_cleanup(&fmd->subdev_notifier);
+
+ v4l2_device_unregister(&fmd->v4l2_dev);
+ device_remove_file(&pdev->dev, &dev_attr_subdev_conf_mode);
+diff --git a/drivers/media/platform/marvell-ccic/cafe-driver.c b/drivers/media/platform/marvell-ccic/cafe-driver.c
+index 9aa374fa8b364..b61b9d9551af5 100644
+--- a/drivers/media/platform/marvell-ccic/cafe-driver.c
++++ b/drivers/media/platform/marvell-ccic/cafe-driver.c
+@@ -544,12 +544,11 @@ static int cafe_pci_probe(struct pci_dev *pdev,
+ if (ret)
+ goto out_pdown;
+
+- v4l2_async_notifier_init(&mcam->notifier);
++ v4l2_async_nf_init(&mcam->notifier);
+
+- asd = v4l2_async_notifier_add_i2c_subdev(&mcam->notifier,
+- i2c_adapter_id(cam->i2c_adapter),
+- ov7670_info.addr,
+- struct v4l2_async_subdev);
++ asd = v4l2_async_nf_add_i2c(&mcam->notifier,
++ i2c_adapter_id(cam->i2c_adapter),
++ ov7670_info.addr, struct v4l2_async_subdev);
+ if (IS_ERR(asd)) {
+ ret = PTR_ERR(asd);
+ goto out_smbus_shutdown;
+diff --git a/drivers/media/platform/marvell-ccic/mcam-core.c b/drivers/media/platform/marvell-ccic/mcam-core.c
+index 58f9463f3b8ce..ad4a7922d0d74 100644
+--- a/drivers/media/platform/marvell-ccic/mcam-core.c
++++ b/drivers/media/platform/marvell-ccic/mcam-core.c
+@@ -1877,7 +1877,7 @@ int mccic_register(struct mcam_camera *cam)
+ cam->mbus_code = mcam_def_mbus_code;
+
+ cam->notifier.ops = &mccic_notify_ops;
+- ret = v4l2_async_notifier_register(&cam->v4l2_dev, &cam->notifier);
++ ret = v4l2_async_nf_register(&cam->v4l2_dev, &cam->notifier);
+ if (ret < 0) {
+ cam_warn(cam, "failed to register a sensor notifier");
+ goto out;
+@@ -1914,9 +1914,9 @@ int mccic_register(struct mcam_camera *cam)
+ return 0;
+
+ out:
+- v4l2_async_notifier_unregister(&cam->notifier);
++ v4l2_async_nf_unregister(&cam->notifier);
+ v4l2_device_unregister(&cam->v4l2_dev);
+- v4l2_async_notifier_cleanup(&cam->notifier);
++ v4l2_async_nf_cleanup(&cam->notifier);
+ return ret;
+ }
+ EXPORT_SYMBOL_GPL(mccic_register);
+@@ -1936,9 +1936,9 @@ void mccic_shutdown(struct mcam_camera *cam)
+ if (cam->buffer_mode == B_vmalloc)
+ mcam_free_dma_bufs(cam);
+ v4l2_ctrl_handler_free(&cam->ctrl_handler);
+- v4l2_async_notifier_unregister(&cam->notifier);
++ v4l2_async_nf_unregister(&cam->notifier);
+ v4l2_device_unregister(&cam->v4l2_dev);
+- v4l2_async_notifier_cleanup(&cam->notifier);
++ v4l2_async_nf_cleanup(&cam->notifier);
+ }
+ EXPORT_SYMBOL_GPL(mccic_shutdown);
+
+diff --git a/drivers/media/platform/marvell-ccic/mmp-driver.c b/drivers/media/platform/marvell-ccic/mmp-driver.c
+index f2f09cea751d8..343ab4f7d807b 100644
+--- a/drivers/media/platform/marvell-ccic/mmp-driver.c
++++ b/drivers/media/platform/marvell-ccic/mmp-driver.c
+@@ -239,10 +239,10 @@ static int mmpcam_probe(struct platform_device *pdev)
+ if (!ep)
+ return -ENODEV;
+
+- v4l2_async_notifier_init(&mcam->notifier);
++ v4l2_async_nf_init(&mcam->notifier);
+
+- asd = v4l2_async_notifier_add_fwnode_remote_subdev(&mcam->notifier, ep,
+- struct v4l2_async_subdev);
++ asd = v4l2_async_nf_add_fwnode_remote(&mcam->notifier, ep,
++ struct v4l2_async_subdev);
+ fwnode_handle_put(ep);
+ if (IS_ERR(asd)) {
+ ret = PTR_ERR(asd);
+diff --git a/drivers/media/platform/omap3isp/isp.c b/drivers/media/platform/omap3isp/isp.c
+index 3222c98b83630..beafe85f28cca 100644
+--- a/drivers/media/platform/omap3isp/isp.c
++++ b/drivers/media/platform/omap3isp/isp.c
+@@ -2003,7 +2003,7 @@ static int isp_remove(struct platform_device *pdev)
+ {
+ struct isp_device *isp = platform_get_drvdata(pdev);
+
+- v4l2_async_notifier_unregister(&isp->notifier);
++ v4l2_async_nf_unregister(&isp->notifier);
+ isp_unregister_entities(isp);
+ isp_cleanup_modules(isp);
+ isp_xclk_cleanup(isp);
+@@ -2013,7 +2013,7 @@ static int isp_remove(struct platform_device *pdev)
+ __omap3isp_put(isp, false);
+
+ media_entity_enum_cleanup(&isp->crashed);
+- v4l2_async_notifier_cleanup(&isp->notifier);
++ v4l2_async_nf_cleanup(&isp->notifier);
+
+ kfree(isp);
+
+@@ -2172,8 +2172,9 @@ static int isp_parse_of_endpoints(struct isp_device *isp)
+ ret = v4l2_fwnode_endpoint_parse(ep, &vep);
+
+ if (!ret) {
+- isd = v4l2_async_notifier_add_fwnode_remote_subdev(
+- &isp->notifier, ep, struct isp_async_subdev);
++ isd = v4l2_async_nf_add_fwnode_remote(&isp->notifier,
++ ep, struct
++ isp_async_subdev);
+ if (!IS_ERR(isd))
+ isp_parse_of_parallel_endpoint(isp->dev, &vep, &isd->bus);
+ }
+@@ -2211,8 +2212,10 @@ static int isp_parse_of_endpoints(struct isp_device *isp)
+ }
+
+ if (!ret) {
+- isd = v4l2_async_notifier_add_fwnode_remote_subdev(
+- &isp->notifier, ep, struct isp_async_subdev);
++ isd = v4l2_async_nf_add_fwnode_remote(&isp->notifier,
++ ep,
++ struct
++ isp_async_subdev);
+
+ if (!IS_ERR(isd)) {
+ switch (vep.bus_type) {
+@@ -2289,7 +2292,7 @@ static int isp_probe(struct platform_device *pdev)
+
+ mutex_init(&isp->isp_mutex);
+ spin_lock_init(&isp->stat_lock);
+- v4l2_async_notifier_init(&isp->notifier);
++ v4l2_async_nf_init(&isp->notifier);
+ isp->dev = &pdev->dev;
+
+ ret = isp_parse_of_endpoints(isp);
+@@ -2427,7 +2430,7 @@ static int isp_probe(struct platform_device *pdev)
+
+ isp->notifier.ops = &isp_subdev_notifier_ops;
+
+- ret = v4l2_async_notifier_register(&isp->v4l2_dev, &isp->notifier);
++ ret = v4l2_async_nf_register(&isp->v4l2_dev, &isp->notifier);
+ if (ret)
+ goto error_register_entities;
+
+@@ -2446,7 +2449,7 @@ static int isp_probe(struct platform_device *pdev)
+ isp_xclk_cleanup(isp);
+ __omap3isp_put(isp, false);
+ error:
+- v4l2_async_notifier_cleanup(&isp->notifier);
++ v4l2_async_nf_cleanup(&isp->notifier);
+ mutex_destroy(&isp->isp_mutex);
+ error_release_isp:
+ kfree(isp);
+diff --git a/drivers/media/platform/pxa_camera.c b/drivers/media/platform/pxa_camera.c
+index ec4c010644cae..3ba00b0f93200 100644
+--- a/drivers/media/platform/pxa_camera.c
++++ b/drivers/media/platform/pxa_camera.c
+@@ -2249,10 +2249,9 @@ static int pxa_camera_pdata_from_dt(struct device *dev,
+ if (ep.bus.parallel.flags & V4L2_MBUS_PCLK_SAMPLE_FALLING)
+ pcdev->platform_flags |= PXA_CAMERA_PCLK_EN;
+
+- asd = v4l2_async_notifier_add_fwnode_remote_subdev(
+- &pcdev->notifier,
+- of_fwnode_handle(np),
+- struct v4l2_async_subdev);
++ asd = v4l2_async_nf_add_fwnode_remote(&pcdev->notifier,
++ of_fwnode_handle(np),
++ struct v4l2_async_subdev);
+ if (IS_ERR(asd))
+ err = PTR_ERR(asd);
+ out:
+@@ -2289,7 +2288,7 @@ static int pxa_camera_probe(struct platform_device *pdev)
+ if (IS_ERR(pcdev->clk))
+ return PTR_ERR(pcdev->clk);
+
+- v4l2_async_notifier_init(&pcdev->notifier);
++ v4l2_async_nf_init(&pcdev->notifier);
+ pcdev->res = res;
+ pcdev->pdata = pdev->dev.platform_data;
+ if (pcdev->pdata) {
+@@ -2297,11 +2296,10 @@ static int pxa_camera_probe(struct platform_device *pdev)
+
+ pcdev->platform_flags = pcdev->pdata->flags;
+ pcdev->mclk = pcdev->pdata->mclk_10khz * 10000;
+- asd = v4l2_async_notifier_add_i2c_subdev(
+- &pcdev->notifier,
+- pcdev->pdata->sensor_i2c_adapter_id,
+- pcdev->pdata->sensor_i2c_address,
+- struct v4l2_async_subdev);
++ asd = v4l2_async_nf_add_i2c(&pcdev->notifier,
++ pcdev->pdata->sensor_i2c_adapter_id,
++ pcdev->pdata->sensor_i2c_address,
++ struct v4l2_async_subdev);
+ if (IS_ERR(asd))
+ err = PTR_ERR(asd);
+ } else if (pdev->dev.of_node) {
+@@ -2402,13 +2400,13 @@ static int pxa_camera_probe(struct platform_device *pdev)
+ goto exit_notifier_cleanup;
+
+ pcdev->notifier.ops = &pxa_camera_sensor_ops;
+- err = v4l2_async_notifier_register(&pcdev->v4l2_dev, &pcdev->notifier);
++ err = v4l2_async_nf_register(&pcdev->v4l2_dev, &pcdev->notifier);
+ if (err)
+ goto exit_notifier_cleanup;
+
+ return 0;
+ exit_notifier_cleanup:
+- v4l2_async_notifier_cleanup(&pcdev->notifier);
++ v4l2_async_nf_cleanup(&pcdev->notifier);
+ v4l2_device_unregister(&pcdev->v4l2_dev);
+ exit_deactivate:
+ pxa_camera_deactivate(pcdev);
+@@ -2432,8 +2430,8 @@ static int pxa_camera_remove(struct platform_device *pdev)
+ dma_release_channel(pcdev->dma_chans[1]);
+ dma_release_channel(pcdev->dma_chans[2]);
+
+- v4l2_async_notifier_unregister(&pcdev->notifier);
+- v4l2_async_notifier_cleanup(&pcdev->notifier);
++ v4l2_async_nf_unregister(&pcdev->notifier);
++ v4l2_async_nf_cleanup(&pcdev->notifier);
+
+ v4l2_device_unregister(&pcdev->v4l2_dev);
+
+diff --git a/drivers/media/platform/qcom/camss/camss.c b/drivers/media/platform/qcom/camss/camss.c
+index ef100d5f77636..be091c50a3c0c 100644
+--- a/drivers/media/platform/qcom/camss/camss.c
++++ b/drivers/media/platform/qcom/camss/camss.c
+@@ -886,9 +886,9 @@ static int camss_of_parse_ports(struct camss *camss)
+ goto err_cleanup;
+ }
+
+- csd = v4l2_async_notifier_add_fwnode_subdev(
+- &camss->notifier, of_fwnode_handle(remote),
+- struct camss_async_subdev);
++ csd = v4l2_async_nf_add_fwnode(&camss->notifier,
++ of_fwnode_handle(remote),
++ struct camss_async_subdev);
+ of_node_put(remote);
+ if (IS_ERR(csd)) {
+ ret = PTR_ERR(csd);
+@@ -1361,7 +1361,7 @@ static int camss_probe(struct platform_device *pdev)
+ goto err_free;
+ }
+
+- v4l2_async_notifier_init(&camss->notifier);
++ v4l2_async_nf_init(&camss->notifier);
+
+ num_subdevs = camss_of_parse_ports(camss);
+ if (num_subdevs < 0) {
+@@ -1397,8 +1397,8 @@ static int camss_probe(struct platform_device *pdev)
+ if (num_subdevs) {
+ camss->notifier.ops = &camss_subdev_notifier_ops;
+
+- ret = v4l2_async_notifier_register(&camss->v4l2_dev,
+- &camss->notifier);
++ ret = v4l2_async_nf_register(&camss->v4l2_dev,
++ &camss->notifier);
+ if (ret) {
+ dev_err(dev,
+ "Failed to register async subdev nodes: %d\n",
+@@ -1436,7 +1436,7 @@ static int camss_probe(struct platform_device *pdev)
+ err_register_entities:
+ v4l2_device_unregister(&camss->v4l2_dev);
+ err_cleanup:
+- v4l2_async_notifier_cleanup(&camss->notifier);
++ v4l2_async_nf_cleanup(&camss->notifier);
+ err_free:
+ kfree(camss);
+
+@@ -1478,8 +1478,8 @@ static int camss_remove(struct platform_device *pdev)
+ {
+ struct camss *camss = platform_get_drvdata(pdev);
+
+- v4l2_async_notifier_unregister(&camss->notifier);
+- v4l2_async_notifier_cleanup(&camss->notifier);
++ v4l2_async_nf_unregister(&camss->notifier);
++ v4l2_async_nf_cleanup(&camss->notifier);
+ camss_unregister_entities(camss);
+
+ if (atomic_read(&camss->ref_count) == 0)
+diff --git a/drivers/media/platform/rcar-vin/rcar-core.c b/drivers/media/platform/rcar-vin/rcar-core.c
+index 5a280d8ff7dd0..d1786aa8a7ecd 100644
+--- a/drivers/media/platform/rcar-vin/rcar-core.c
++++ b/drivers/media/platform/rcar-vin/rcar-core.c
+@@ -535,9 +535,8 @@ static int rvin_mc_parse_of(struct rvin_dev *vin, unsigned int id)
+ goto out;
+ }
+
+- asd = v4l2_async_notifier_add_fwnode_subdev(&vin->group->notifier,
+- fwnode,
+- struct v4l2_async_subdev);
++ asd = v4l2_async_nf_add_fwnode(&vin->group->notifier, fwnode,
++ struct v4l2_async_subdev);
+ if (IS_ERR(asd)) {
+ ret = PTR_ERR(asd);
+ goto out;
+@@ -557,8 +556,8 @@ static void rvin_group_notifier_cleanup(struct rvin_dev *vin)
+ {
+ mutex_lock(&vin->group->lock);
+ if (&vin->v4l2_dev == vin->group->notifier.v4l2_dev) {
+- v4l2_async_notifier_unregister(&vin->group->notifier);
+- v4l2_async_notifier_cleanup(&vin->group->notifier);
++ v4l2_async_nf_unregister(&vin->group->notifier);
++ v4l2_async_nf_cleanup(&vin->group->notifier);
+ }
+ mutex_unlock(&vin->group->lock);
+ }
+@@ -586,7 +585,7 @@ static int rvin_mc_parse_of_graph(struct rvin_dev *vin)
+
+ mutex_unlock(&vin->group->lock);
+
+- v4l2_async_notifier_init(&vin->group->notifier);
++ v4l2_async_nf_init(&vin->group->notifier);
+
+ /*
+ * Have all VIN's look for CSI-2 subdevices. Some subdevices will
+@@ -611,11 +610,10 @@ static int rvin_mc_parse_of_graph(struct rvin_dev *vin)
+ return 0;
+
+ vin->group->notifier.ops = &rvin_group_notify_ops;
+- ret = v4l2_async_notifier_register(&vin->v4l2_dev,
+- &vin->group->notifier);
++ ret = v4l2_async_nf_register(&vin->v4l2_dev, &vin->group->notifier);
+ if (ret < 0) {
+ vin_err(vin, "Notifier registration failed\n");
+- v4l2_async_notifier_cleanup(&vin->group->notifier);
++ v4l2_async_nf_cleanup(&vin->group->notifier);
+ return ret;
+ }
+
+@@ -899,8 +897,8 @@ static int rvin_parallel_parse_of(struct rvin_dev *vin)
+ goto out;
+ }
+
+- asd = v4l2_async_notifier_add_fwnode_subdev(&vin->notifier, fwnode,
+- struct v4l2_async_subdev);
++ asd = v4l2_async_nf_add_fwnode(&vin->notifier, fwnode,
++ struct v4l2_async_subdev);
+ if (IS_ERR(asd)) {
+ ret = PTR_ERR(asd);
+ goto out;
+@@ -917,15 +915,15 @@ static int rvin_parallel_parse_of(struct rvin_dev *vin)
+
+ static void rvin_parallel_cleanup(struct rvin_dev *vin)
+ {
+- v4l2_async_notifier_unregister(&vin->notifier);
+- v4l2_async_notifier_cleanup(&vin->notifier);
++ v4l2_async_nf_unregister(&vin->notifier);
++ v4l2_async_nf_cleanup(&vin->notifier);
+ }
+
+ static int rvin_parallel_init(struct rvin_dev *vin)
+ {
+ int ret;
+
+- v4l2_async_notifier_init(&vin->notifier);
++ v4l2_async_nf_init(&vin->notifier);
+
+ ret = rvin_parallel_parse_of(vin);
+ if (ret)
+@@ -939,10 +937,10 @@ static int rvin_parallel_init(struct rvin_dev *vin)
+ to_of_node(vin->parallel.asd->match.fwnode));
+
+ vin->notifier.ops = &rvin_parallel_notify_ops;
+- ret = v4l2_async_notifier_register(&vin->v4l2_dev, &vin->notifier);
++ ret = v4l2_async_nf_register(&vin->v4l2_dev, &vin->notifier);
+ if (ret < 0) {
+ vin_err(vin, "Notifier registration failed\n");
+- v4l2_async_notifier_cleanup(&vin->notifier);
++ v4l2_async_nf_cleanup(&vin->notifier);
+ return ret;
+ }
+
+diff --git a/drivers/media/platform/rcar-vin/rcar-csi2.c b/drivers/media/platform/rcar-vin/rcar-csi2.c
+index 0c5e2f7e04beb..5e9cb72676e39 100644
+--- a/drivers/media/platform/rcar-vin/rcar-csi2.c
++++ b/drivers/media/platform/rcar-vin/rcar-csi2.c
+@@ -926,19 +926,18 @@ static int rcsi2_parse_dt(struct rcar_csi2 *priv)
+
+ dev_dbg(priv->dev, "Found '%pOF'\n", to_of_node(fwnode));
+
+- v4l2_async_notifier_init(&priv->notifier);
++ v4l2_async_nf_init(&priv->notifier);
+ priv->notifier.ops = &rcar_csi2_notify_ops;
+
+- asd = v4l2_async_notifier_add_fwnode_subdev(&priv->notifier, fwnode,
+- struct v4l2_async_subdev);
++ asd = v4l2_async_nf_add_fwnode(&priv->notifier, fwnode,
++ struct v4l2_async_subdev);
+ fwnode_handle_put(fwnode);
+ if (IS_ERR(asd))
+ return PTR_ERR(asd);
+
+- ret = v4l2_async_subdev_notifier_register(&priv->subdev,
+- &priv->notifier);
++ ret = v4l2_async_subdev_nf_register(&priv->subdev, &priv->notifier);
+ if (ret)
+- v4l2_async_notifier_cleanup(&priv->notifier);
++ v4l2_async_nf_cleanup(&priv->notifier);
+
+ return ret;
+ }
+@@ -1301,8 +1300,8 @@ static int rcsi2_probe(struct platform_device *pdev)
+ return 0;
+
+ error:
+- v4l2_async_notifier_unregister(&priv->notifier);
+- v4l2_async_notifier_cleanup(&priv->notifier);
++ v4l2_async_nf_unregister(&priv->notifier);
++ v4l2_async_nf_cleanup(&priv->notifier);
+
+ return ret;
+ }
+@@ -1311,8 +1310,8 @@ static int rcsi2_remove(struct platform_device *pdev)
+ {
+ struct rcar_csi2 *priv = platform_get_drvdata(pdev);
+
+- v4l2_async_notifier_unregister(&priv->notifier);
+- v4l2_async_notifier_cleanup(&priv->notifier);
++ v4l2_async_nf_unregister(&priv->notifier);
++ v4l2_async_nf_cleanup(&priv->notifier);
+ v4l2_async_unregister_subdev(&priv->subdev);
+
+ pm_runtime_disable(&pdev->dev);
+diff --git a/drivers/media/platform/rcar_drif.c b/drivers/media/platform/rcar_drif.c
+index 1e3b68a8743af..a505d991548bb 100644
+--- a/drivers/media/platform/rcar_drif.c
++++ b/drivers/media/platform/rcar_drif.c
+@@ -1212,7 +1212,7 @@ static int rcar_drif_parse_subdevs(struct rcar_drif_sdr *sdr)
+ struct fwnode_handle *fwnode, *ep;
+ struct v4l2_async_subdev *asd;
+
+- v4l2_async_notifier_init(notifier);
++ v4l2_async_nf_init(notifier);
+
+ ep = fwnode_graph_get_next_endpoint(of_fwnode_handle(sdr->dev->of_node),
+ NULL);
+@@ -1229,8 +1229,8 @@ static int rcar_drif_parse_subdevs(struct rcar_drif_sdr *sdr)
+ return -EINVAL;
+ }
+
+- asd = v4l2_async_notifier_add_fwnode_subdev(notifier, fwnode,
+- struct v4l2_async_subdev);
++ asd = v4l2_async_nf_add_fwnode(notifier, fwnode,
++ struct v4l2_async_subdev);
+ fwnode_handle_put(fwnode);
+ if (IS_ERR(asd))
+ return PTR_ERR(asd);
+@@ -1346,7 +1346,7 @@ static int rcar_drif_sdr_probe(struct rcar_drif_sdr *sdr)
+ sdr->notifier.ops = &rcar_drif_notify_ops;
+
+ /* Register notifier */
+- ret = v4l2_async_notifier_register(&sdr->v4l2_dev, &sdr->notifier);
++ ret = v4l2_async_nf_register(&sdr->v4l2_dev, &sdr->notifier);
+ if (ret < 0) {
+ dev_err(sdr->dev, "failed: notifier register ret %d\n", ret);
+ goto cleanup;
+@@ -1355,7 +1355,7 @@ static int rcar_drif_sdr_probe(struct rcar_drif_sdr *sdr)
+ return ret;
+
+ cleanup:
+- v4l2_async_notifier_cleanup(&sdr->notifier);
++ v4l2_async_nf_cleanup(&sdr->notifier);
+ error:
+ v4l2_device_unregister(&sdr->v4l2_dev);
+
+@@ -1365,8 +1365,8 @@ static int rcar_drif_sdr_probe(struct rcar_drif_sdr *sdr)
+ /* V4L2 SDR device remove */
+ static void rcar_drif_sdr_remove(struct rcar_drif_sdr *sdr)
+ {
+- v4l2_async_notifier_unregister(&sdr->notifier);
+- v4l2_async_notifier_cleanup(&sdr->notifier);
++ v4l2_async_nf_unregister(&sdr->notifier);
++ v4l2_async_nf_cleanup(&sdr->notifier);
+ v4l2_device_unregister(&sdr->v4l2_dev);
+ }
+
+diff --git a/drivers/media/platform/renesas-ceu.c b/drivers/media/platform/renesas-ceu.c
+index f432032c7084f..9376eb363748b 100644
+--- a/drivers/media/platform/renesas-ceu.c
++++ b/drivers/media/platform/renesas-ceu.c
+@@ -1513,12 +1513,12 @@ static int ceu_parse_platform_data(struct ceu_device *ceudev,
+
+ /* Setup the ceu subdevice and the async subdevice. */
+ async_sd = &pdata->subdevs[i];
+- ceu_sd = v4l2_async_notifier_add_i2c_subdev(&ceudev->notifier,
+- async_sd->i2c_adapter_id,
+- async_sd->i2c_address,
+- struct ceu_subdev);
++ ceu_sd = v4l2_async_nf_add_i2c(&ceudev->notifier,
++ async_sd->i2c_adapter_id,
++ async_sd->i2c_address,
++ struct ceu_subdev);
+ if (IS_ERR(ceu_sd)) {
+- v4l2_async_notifier_cleanup(&ceudev->notifier);
++ v4l2_async_nf_cleanup(&ceudev->notifier);
+ return PTR_ERR(ceu_sd);
+ }
+ ceu_sd->mbus_flags = async_sd->flags;
+@@ -1576,9 +1576,9 @@ static int ceu_parse_dt(struct ceu_device *ceudev)
+ }
+
+ /* Setup the ceu subdevice and the async subdevice. */
+- ceu_sd = v4l2_async_notifier_add_fwnode_remote_subdev(
+- &ceudev->notifier, of_fwnode_handle(ep),
+- struct ceu_subdev);
++ ceu_sd = v4l2_async_nf_add_fwnode_remote(&ceudev->notifier,
++ of_fwnode_handle(ep),
++ struct ceu_subdev);
+ if (IS_ERR(ceu_sd)) {
+ ret = PTR_ERR(ceu_sd);
+ goto error_cleanup;
+@@ -1592,7 +1592,7 @@ static int ceu_parse_dt(struct ceu_device *ceudev)
+ return num_ep;
+
+ error_cleanup:
+- v4l2_async_notifier_cleanup(&ceudev->notifier);
++ v4l2_async_nf_cleanup(&ceudev->notifier);
+ of_node_put(ep);
+ return ret;
+ }
+@@ -1669,7 +1669,7 @@ static int ceu_probe(struct platform_device *pdev)
+ if (ret)
+ goto error_pm_disable;
+
+- v4l2_async_notifier_init(&ceudev->notifier);
++ v4l2_async_nf_init(&ceudev->notifier);
+
+ if (IS_ENABLED(CONFIG_OF) && dev->of_node) {
+ ceu_data = of_device_get_match_data(dev);
+@@ -1691,8 +1691,7 @@ static int ceu_probe(struct platform_device *pdev)
+
+ ceudev->notifier.v4l2_dev = &ceudev->v4l2_dev;
+ ceudev->notifier.ops = &ceu_notify_ops;
+- ret = v4l2_async_notifier_register(&ceudev->v4l2_dev,
+- &ceudev->notifier);
++ ret = v4l2_async_nf_register(&ceudev->v4l2_dev, &ceudev->notifier);
+ if (ret)
+ goto error_cleanup;
+
+@@ -1701,7 +1700,7 @@ static int ceu_probe(struct platform_device *pdev)
+ return 0;
+
+ error_cleanup:
+- v4l2_async_notifier_cleanup(&ceudev->notifier);
++ v4l2_async_nf_cleanup(&ceudev->notifier);
+ error_v4l2_unregister:
+ v4l2_device_unregister(&ceudev->v4l2_dev);
+ error_pm_disable:
+@@ -1718,9 +1717,9 @@ static int ceu_remove(struct platform_device *pdev)
+
+ pm_runtime_disable(ceudev->dev);
+
+- v4l2_async_notifier_unregister(&ceudev->notifier);
++ v4l2_async_nf_unregister(&ceudev->notifier);
+
+- v4l2_async_notifier_cleanup(&ceudev->notifier);
++ v4l2_async_nf_cleanup(&ceudev->notifier);
+
+ v4l2_device_unregister(&ceudev->v4l2_dev);
+
+diff --git a/drivers/media/platform/rockchip/rkisp1/rkisp1-dev.c b/drivers/media/platform/rockchip/rkisp1/rkisp1-dev.c
+index 560f928c37520..b6a4522c2970d 100644
+--- a/drivers/media/platform/rockchip/rkisp1/rkisp1-dev.c
++++ b/drivers/media/platform/rockchip/rkisp1/rkisp1-dev.c
+@@ -246,7 +246,7 @@ static int rkisp1_subdev_notifier(struct rkisp1_device *rkisp1)
+ unsigned int next_id = 0;
+ int ret;
+
+- v4l2_async_notifier_init(ntf);
++ v4l2_async_nf_init(ntf);
+
+ while (1) {
+ struct v4l2_fwnode_endpoint vep = {
+@@ -265,8 +265,9 @@ static int rkisp1_subdev_notifier(struct rkisp1_device *rkisp1)
+ if (ret)
+ goto err_parse;
+
+- rk_asd = v4l2_async_notifier_add_fwnode_remote_subdev(ntf, ep,
+- struct rkisp1_sensor_async);
++ rk_asd = v4l2_async_nf_add_fwnode_remote(ntf, ep,
++ struct
++ rkisp1_sensor_async);
+ if (IS_ERR(rk_asd)) {
+ ret = PTR_ERR(rk_asd);
+ goto err_parse;
+@@ -286,16 +287,16 @@ static int rkisp1_subdev_notifier(struct rkisp1_device *rkisp1)
+ continue;
+ err_parse:
+ fwnode_handle_put(ep);
+- v4l2_async_notifier_cleanup(ntf);
++ v4l2_async_nf_cleanup(ntf);
+ return ret;
+ }
+
+ if (next_id == 0)
+ dev_dbg(rkisp1->dev, "no remote subdevice found\n");
+ ntf->ops = &rkisp1_subdev_notifier_ops;
+- ret = v4l2_async_notifier_register(&rkisp1->v4l2_dev, ntf);
++ ret = v4l2_async_nf_register(&rkisp1->v4l2_dev, ntf);
+ if (ret) {
+- v4l2_async_notifier_cleanup(ntf);
++ v4l2_async_nf_cleanup(ntf);
+ return ret;
+ }
+ return 0;
+@@ -542,8 +543,8 @@ static int rkisp1_remove(struct platform_device *pdev)
+ {
+ struct rkisp1_device *rkisp1 = platform_get_drvdata(pdev);
+
+- v4l2_async_notifier_unregister(&rkisp1->notifier);
+- v4l2_async_notifier_cleanup(&rkisp1->notifier);
++ v4l2_async_nf_unregister(&rkisp1->notifier);
++ v4l2_async_nf_cleanup(&rkisp1->notifier);
+
+ rkisp1_params_unregister(rkisp1);
+ rkisp1_stats_unregister(rkisp1);
+diff --git a/drivers/media/platform/stm32/stm32-dcmi.c b/drivers/media/platform/stm32/stm32-dcmi.c
+index 6110718645a4f..e1b17c05229cf 100644
+--- a/drivers/media/platform/stm32/stm32-dcmi.c
++++ b/drivers/media/platform/stm32/stm32-dcmi.c
+@@ -1833,11 +1833,11 @@ static int dcmi_graph_init(struct stm32_dcmi *dcmi)
+ return -EINVAL;
+ }
+
+- v4l2_async_notifier_init(&dcmi->notifier);
++ v4l2_async_nf_init(&dcmi->notifier);
+
+- asd = v4l2_async_notifier_add_fwnode_remote_subdev(
+- &dcmi->notifier, of_fwnode_handle(ep),
+- struct v4l2_async_subdev);
++ asd = v4l2_async_nf_add_fwnode_remote(&dcmi->notifier,
++ of_fwnode_handle(ep),
++ struct v4l2_async_subdev);
+
+ of_node_put(ep);
+
+@@ -1848,10 +1848,10 @@ static int dcmi_graph_init(struct stm32_dcmi *dcmi)
+
+ dcmi->notifier.ops = &dcmi_graph_notify_ops;
+
+- ret = v4l2_async_notifier_register(&dcmi->v4l2_dev, &dcmi->notifier);
++ ret = v4l2_async_nf_register(&dcmi->v4l2_dev, &dcmi->notifier);
+ if (ret < 0) {
+ dev_err(dcmi->dev, "Failed to register notifier\n");
+- v4l2_async_notifier_cleanup(&dcmi->notifier);
++ v4l2_async_nf_cleanup(&dcmi->notifier);
+ return ret;
+ }
+
+@@ -2063,7 +2063,7 @@ static int dcmi_probe(struct platform_device *pdev)
+ return 0;
+
+ err_cleanup:
+- v4l2_async_notifier_cleanup(&dcmi->notifier);
++ v4l2_async_nf_cleanup(&dcmi->notifier);
+ err_media_entity_cleanup:
+ media_entity_cleanup(&dcmi->vdev->entity);
+ err_device_release:
+@@ -2083,8 +2083,8 @@ static int dcmi_remove(struct platform_device *pdev)
+
+ pm_runtime_disable(&pdev->dev);
+
+- v4l2_async_notifier_unregister(&dcmi->notifier);
+- v4l2_async_notifier_cleanup(&dcmi->notifier);
++ v4l2_async_nf_unregister(&dcmi->notifier);
++ v4l2_async_nf_cleanup(&dcmi->notifier);
+ media_entity_cleanup(&dcmi->vdev->entity);
+ v4l2_device_unregister(&dcmi->v4l2_dev);
+ media_device_cleanup(&dcmi->mdev);
+diff --git a/drivers/media/platform/sunxi/sun4i-csi/sun4i_csi.c b/drivers/media/platform/sunxi/sun4i-csi/sun4i_csi.c
+index 8d40a7acba9c4..94e98e470aff7 100644
+--- a/drivers/media/platform/sunxi/sun4i-csi/sun4i_csi.c
++++ b/drivers/media/platform/sunxi/sun4i-csi/sun4i_csi.c
+@@ -122,7 +122,7 @@ static int sun4i_csi_notifier_init(struct sun4i_csi *csi)
+ struct fwnode_handle *ep;
+ int ret;
+
+- v4l2_async_notifier_init(&csi->notifier);
++ v4l2_async_nf_init(&csi->notifier);
+
+ ep = fwnode_graph_get_endpoint_by_id(dev_fwnode(csi->dev), 0, 0,
+ FWNODE_GRAPH_ENDPOINT_NEXT);
+@@ -135,8 +135,8 @@ static int sun4i_csi_notifier_init(struct sun4i_csi *csi)
+
+ csi->bus = vep.bus.parallel;
+
+- asd = v4l2_async_notifier_add_fwnode_remote_subdev(&csi->notifier, ep,
+- struct v4l2_async_subdev);
++ asd = v4l2_async_nf_add_fwnode_remote(&csi->notifier, ep,
++ struct v4l2_async_subdev);
+ if (IS_ERR(asd)) {
+ ret = PTR_ERR(asd);
+ goto out;
+@@ -244,7 +244,7 @@ static int sun4i_csi_probe(struct platform_device *pdev)
+ if (ret)
+ goto err_unregister_media;
+
+- ret = v4l2_async_notifier_register(&csi->v4l, &csi->notifier);
++ ret = v4l2_async_nf_register(&csi->v4l, &csi->notifier);
+ if (ret) {
+ dev_err(csi->dev, "Couldn't register our notifier.\n");
+ goto err_unregister_media;
+@@ -268,8 +268,8 @@ static int sun4i_csi_remove(struct platform_device *pdev)
+ {
+ struct sun4i_csi *csi = platform_get_drvdata(pdev);
+
+- v4l2_async_notifier_unregister(&csi->notifier);
+- v4l2_async_notifier_cleanup(&csi->notifier);
++ v4l2_async_nf_unregister(&csi->notifier);
++ v4l2_async_nf_cleanup(&csi->notifier);
+ vb2_video_unregister_device(&csi->vdev);
+ media_device_unregister(&csi->mdev);
+ sun4i_csi_dma_unregister(csi);
+diff --git a/drivers/media/platform/sunxi/sun6i-csi/sun6i_csi.c b/drivers/media/platform/sunxi/sun6i-csi/sun6i_csi.c
+index 27935f1e9555e..08df0c833423b 100644
+--- a/drivers/media/platform/sunxi/sun6i-csi/sun6i_csi.c
++++ b/drivers/media/platform/sunxi/sun6i-csi/sun6i_csi.c
+@@ -717,8 +717,8 @@ static int sun6i_csi_fwnode_parse(struct device *dev,
+ static void sun6i_csi_v4l2_cleanup(struct sun6i_csi *csi)
+ {
+ media_device_unregister(&csi->media_dev);
+- v4l2_async_notifier_unregister(&csi->notifier);
+- v4l2_async_notifier_cleanup(&csi->notifier);
++ v4l2_async_nf_unregister(&csi->notifier);
++ v4l2_async_nf_cleanup(&csi->notifier);
+ sun6i_video_cleanup(&csi->video);
+ v4l2_device_unregister(&csi->v4l2_dev);
+ v4l2_ctrl_handler_free(&csi->ctrl_handler);
+@@ -737,7 +737,7 @@ static int sun6i_csi_v4l2_init(struct sun6i_csi *csi)
+ "platform:%s", dev_name(csi->dev));
+
+ media_device_init(&csi->media_dev);
+- v4l2_async_notifier_init(&csi->notifier);
++ v4l2_async_nf_init(&csi->notifier);
+
+ ret = v4l2_ctrl_handler_init(&csi->ctrl_handler, 0);
+ if (ret) {
+@@ -759,16 +759,17 @@ static int sun6i_csi_v4l2_init(struct sun6i_csi *csi)
+ if (ret)
+ goto unreg_v4l2;
+
+- ret = v4l2_async_notifier_parse_fwnode_endpoints(csi->dev,
+- &csi->notifier,
+- sizeof(struct v4l2_async_subdev),
+- sun6i_csi_fwnode_parse);
++ ret = v4l2_async_nf_parse_fwnode_endpoints(csi->dev,
++ &csi->notifier,
++ sizeof(struct
++ v4l2_async_subdev),
++ sun6i_csi_fwnode_parse);
+ if (ret)
+ goto clean_video;
+
+ csi->notifier.ops = &sun6i_csi_async_ops;
+
+- ret = v4l2_async_notifier_register(&csi->v4l2_dev, &csi->notifier);
++ ret = v4l2_async_nf_register(&csi->v4l2_dev, &csi->notifier);
+ if (ret) {
+ dev_err(csi->dev, "notifier registration failed\n");
+ goto clean_video;
+@@ -783,7 +784,7 @@ static int sun6i_csi_v4l2_init(struct sun6i_csi *csi)
+ free_ctrl:
+ v4l2_ctrl_handler_free(&csi->ctrl_handler);
+ clean_media:
+- v4l2_async_notifier_cleanup(&csi->notifier);
++ v4l2_async_nf_cleanup(&csi->notifier);
+ media_device_cleanup(&csi->media_dev);
+
+ return ret;
+diff --git a/drivers/media/platform/ti-vpe/cal.c b/drivers/media/platform/ti-vpe/cal.c
+index 35d62eb1321fb..0e583120266ff 100644
+--- a/drivers/media/platform/ti-vpe/cal.c
++++ b/drivers/media/platform/ti-vpe/cal.c
+@@ -781,7 +781,7 @@ static int cal_async_notifier_register(struct cal_dev *cal)
+ unsigned int i;
+ int ret;
+
+- v4l2_async_notifier_init(&cal->notifier);
++ v4l2_async_nf_init(&cal->notifier);
+ cal->notifier.ops = &cal_async_notifier_ops;
+
+ for (i = 0; i < cal->data->num_csi2_phy; ++i) {
+@@ -793,9 +793,9 @@ static int cal_async_notifier_register(struct cal_dev *cal)
+ continue;
+
+ fwnode = of_fwnode_handle(phy->source_node);
+- casd = v4l2_async_notifier_add_fwnode_subdev(&cal->notifier,
+- fwnode,
+- struct cal_v4l2_async_subdev);
++ casd = v4l2_async_nf_add_fwnode(&cal->notifier,
++ fwnode,
++ struct cal_v4l2_async_subdev);
+ if (IS_ERR(casd)) {
+ phy_err(phy, "Failed to add subdev to notifier\n");
+ ret = PTR_ERR(casd);
+@@ -805,7 +805,7 @@ static int cal_async_notifier_register(struct cal_dev *cal)
+ casd->phy = phy;
+ }
+
+- ret = v4l2_async_notifier_register(&cal->v4l2_dev, &cal->notifier);
++ ret = v4l2_async_nf_register(&cal->v4l2_dev, &cal->notifier);
+ if (ret) {
+ cal_err(cal, "Error registering async notifier\n");
+ goto error;
+@@ -814,14 +814,14 @@ static int cal_async_notifier_register(struct cal_dev *cal)
+ return 0;
+
+ error:
+- v4l2_async_notifier_cleanup(&cal->notifier);
++ v4l2_async_nf_cleanup(&cal->notifier);
+ return ret;
+ }
+
+ static void cal_async_notifier_unregister(struct cal_dev *cal)
+ {
+- v4l2_async_notifier_unregister(&cal->notifier);
+- v4l2_async_notifier_cleanup(&cal->notifier);
++ v4l2_async_nf_unregister(&cal->notifier);
++ v4l2_async_nf_cleanup(&cal->notifier);
+ }
+
+ /* ------------------------------------------------------------------
+diff --git a/drivers/media/platform/video-mux.c b/drivers/media/platform/video-mux.c
+index 905005e271ca9..fda8fc0e48143 100644
+--- a/drivers/media/platform/video-mux.c
++++ b/drivers/media/platform/video-mux.c
+@@ -360,7 +360,7 @@ static int video_mux_async_register(struct video_mux *vmux,
+ unsigned int i;
+ int ret;
+
+- v4l2_async_notifier_init(&vmux->notifier);
++ v4l2_async_nf_init(&vmux->notifier);
+
+ for (i = 0; i < num_input_pads; i++) {
+ struct v4l2_async_subdev *asd;
+@@ -380,8 +380,8 @@ static int video_mux_async_register(struct video_mux *vmux,
+ }
+ fwnode_handle_put(remote_ep);
+
+- asd = v4l2_async_notifier_add_fwnode_remote_subdev(
+- &vmux->notifier, ep, struct v4l2_async_subdev);
++ asd = v4l2_async_nf_add_fwnode_remote(&vmux->notifier, ep,
++ struct v4l2_async_subdev);
+
+ fwnode_handle_put(ep);
+
+@@ -395,8 +395,7 @@ static int video_mux_async_register(struct video_mux *vmux,
+
+ vmux->notifier.ops = &video_mux_notify_ops;
+
+- ret = v4l2_async_subdev_notifier_register(&vmux->subdev,
+- &vmux->notifier);
++ ret = v4l2_async_subdev_nf_register(&vmux->subdev, &vmux->notifier);
+ if (ret)
+ return ret;
+
+@@ -477,8 +476,8 @@ static int video_mux_probe(struct platform_device *pdev)
+
+ ret = video_mux_async_register(vmux, num_pads - 1);
+ if (ret) {
+- v4l2_async_notifier_unregister(&vmux->notifier);
+- v4l2_async_notifier_cleanup(&vmux->notifier);
++ v4l2_async_nf_unregister(&vmux->notifier);
++ v4l2_async_nf_cleanup(&vmux->notifier);
+ }
+
+ return ret;
+@@ -489,8 +488,8 @@ static int video_mux_remove(struct platform_device *pdev)
+ struct video_mux *vmux = platform_get_drvdata(pdev);
+ struct v4l2_subdev *sd = &vmux->subdev;
+
+- v4l2_async_notifier_unregister(&vmux->notifier);
+- v4l2_async_notifier_cleanup(&vmux->notifier);
++ v4l2_async_nf_unregister(&vmux->notifier);
++ v4l2_async_nf_cleanup(&vmux->notifier);
+ v4l2_async_unregister_subdev(sd);
+ media_entity_cleanup(&sd->entity);
+
+diff --git a/drivers/media/platform/xilinx/xilinx-vipp.c b/drivers/media/platform/xilinx/xilinx-vipp.c
+index 5896a662da3ba..0a16c218a50a7 100644
+--- a/drivers/media/platform/xilinx/xilinx-vipp.c
++++ b/drivers/media/platform/xilinx/xilinx-vipp.c
+@@ -382,9 +382,8 @@ static int xvip_graph_parse_one(struct xvip_composite_device *xdev,
+ continue;
+ }
+
+- xge = v4l2_async_notifier_add_fwnode_subdev(
+- &xdev->notifier, remote,
+- struct xvip_graph_entity);
++ xge = v4l2_async_nf_add_fwnode(&xdev->notifier, remote,
++ struct xvip_graph_entity);
+ fwnode_handle_put(remote);
+ if (IS_ERR(xge)) {
+ ret = PTR_ERR(xge);
+@@ -395,7 +394,7 @@ static int xvip_graph_parse_one(struct xvip_composite_device *xdev,
+ return 0;
+
+ err_notifier_cleanup:
+- v4l2_async_notifier_cleanup(&xdev->notifier);
++ v4l2_async_nf_cleanup(&xdev->notifier);
+ fwnode_handle_put(ep);
+ return ret;
+ }
+@@ -420,7 +419,7 @@ static int xvip_graph_parse(struct xvip_composite_device *xdev)
+ entity = to_xvip_entity(asd);
+ ret = xvip_graph_parse_one(xdev, entity->asd.match.fwnode);
+ if (ret < 0) {
+- v4l2_async_notifier_cleanup(&xdev->notifier);
++ v4l2_async_nf_cleanup(&xdev->notifier);
+ break;
+ }
+ }
+@@ -497,8 +496,8 @@ static void xvip_graph_cleanup(struct xvip_composite_device *xdev)
+ struct xvip_dma *dmap;
+ struct xvip_dma *dma;
+
+- v4l2_async_notifier_unregister(&xdev->notifier);
+- v4l2_async_notifier_cleanup(&xdev->notifier);
++ v4l2_async_nf_unregister(&xdev->notifier);
++ v4l2_async_nf_cleanup(&xdev->notifier);
+
+ list_for_each_entry_safe(dma, dmap, &xdev->dmas, list) {
+ xvip_dma_cleanup(dma);
+@@ -533,7 +532,7 @@ static int xvip_graph_init(struct xvip_composite_device *xdev)
+ /* Register the subdevices notifier. */
+ xdev->notifier.ops = &xvip_graph_notify_ops;
+
+- ret = v4l2_async_notifier_register(&xdev->v4l2_dev, &xdev->notifier);
++ ret = v4l2_async_nf_register(&xdev->v4l2_dev, &xdev->notifier);
+ if (ret < 0) {
+ dev_err(xdev->dev, "notifier registration failed\n");
+ goto done;
+@@ -597,7 +596,7 @@ static int xvip_composite_probe(struct platform_device *pdev)
+
+ xdev->dev = &pdev->dev;
+ INIT_LIST_HEAD(&xdev->dmas);
+- v4l2_async_notifier_init(&xdev->notifier);
++ v4l2_async_nf_init(&xdev->notifier);
+
+ ret = xvip_composite_v4l2_init(xdev);
+ if (ret < 0)
+diff --git a/drivers/media/v4l2-core/v4l2-async.c b/drivers/media/v4l2-core/v4l2-async.c
+index cd9e78c63791b..0404267f1ae4f 100644
+--- a/drivers/media/v4l2-core/v4l2-async.c
++++ b/drivers/media/v4l2-core/v4l2-async.c
+@@ -24,9 +24,9 @@
+ #include <media/v4l2-fwnode.h>
+ #include <media/v4l2-subdev.h>
+
+-static int v4l2_async_notifier_call_bound(struct v4l2_async_notifier *n,
+- struct v4l2_subdev *subdev,
+- struct v4l2_async_subdev *asd)
++static int v4l2_async_nf_call_bound(struct v4l2_async_notifier *n,
++ struct v4l2_subdev *subdev,
++ struct v4l2_async_subdev *asd)
+ {
+ if (!n->ops || !n->ops->bound)
+ return 0;
+@@ -34,9 +34,9 @@ static int v4l2_async_notifier_call_bound(struct v4l2_async_notifier *n,
+ return n->ops->bound(n, subdev, asd);
+ }
+
+-static void v4l2_async_notifier_call_unbind(struct v4l2_async_notifier *n,
+- struct v4l2_subdev *subdev,
+- struct v4l2_async_subdev *asd)
++static void v4l2_async_nf_call_unbind(struct v4l2_async_notifier *n,
++ struct v4l2_subdev *subdev,
++ struct v4l2_async_subdev *asd)
+ {
+ if (!n->ops || !n->ops->unbind)
+ return;
+@@ -44,7 +44,7 @@ static void v4l2_async_notifier_call_unbind(struct v4l2_async_notifier *n,
+ n->ops->unbind(n, subdev, asd);
+ }
+
+-static int v4l2_async_notifier_call_complete(struct v4l2_async_notifier *n)
++static int v4l2_async_nf_call_complete(struct v4l2_async_notifier *n)
+ {
+ if (!n->ops || !n->ops->complete)
+ return 0;
+@@ -215,7 +215,7 @@ v4l2_async_find_subdev_notifier(struct v4l2_subdev *sd)
+
+ /* Get v4l2_device related to the notifier if one can be found. */
+ static struct v4l2_device *
+-v4l2_async_notifier_find_v4l2_dev(struct v4l2_async_notifier *notifier)
++v4l2_async_nf_find_v4l2_dev(struct v4l2_async_notifier *notifier)
+ {
+ while (notifier->parent)
+ notifier = notifier->parent;
+@@ -227,7 +227,7 @@ v4l2_async_notifier_find_v4l2_dev(struct v4l2_async_notifier *notifier)
+ * Return true if all child sub-device notifiers are complete, false otherwise.
+ */
+ static bool
+-v4l2_async_notifier_can_complete(struct v4l2_async_notifier *notifier)
++v4l2_async_nf_can_complete(struct v4l2_async_notifier *notifier)
+ {
+ struct v4l2_subdev *sd;
+
+@@ -239,7 +239,7 @@ v4l2_async_notifier_can_complete(struct v4l2_async_notifier *notifier)
+ v4l2_async_find_subdev_notifier(sd);
+
+ if (subdev_notifier &&
+- !v4l2_async_notifier_can_complete(subdev_notifier))
++ !v4l2_async_nf_can_complete(subdev_notifier))
+ return false;
+ }
+
+@@ -251,7 +251,7 @@ v4l2_async_notifier_can_complete(struct v4l2_async_notifier *notifier)
+ * sub-devices have been bound; v4l2_device is also available then.
+ */
+ static int
+-v4l2_async_notifier_try_complete(struct v4l2_async_notifier *notifier)
++v4l2_async_nf_try_complete(struct v4l2_async_notifier *notifier)
+ {
+ /* Quick check whether there are still more sub-devices here. */
+ if (!list_empty(¬ifier->waiting))
+@@ -266,14 +266,14 @@ v4l2_async_notifier_try_complete(struct v4l2_async_notifier *notifier)
+ return 0;
+
+ /* Is everything ready? */
+- if (!v4l2_async_notifier_can_complete(notifier))
++ if (!v4l2_async_nf_can_complete(notifier))
+ return 0;
+
+- return v4l2_async_notifier_call_complete(notifier);
++ return v4l2_async_nf_call_complete(notifier);
+ }
+
+ static int
+-v4l2_async_notifier_try_all_subdevs(struct v4l2_async_notifier *notifier);
++v4l2_async_nf_try_all_subdevs(struct v4l2_async_notifier *notifier);
+
+ static int v4l2_async_match_notify(struct v4l2_async_notifier *notifier,
+ struct v4l2_device *v4l2_dev,
+@@ -287,7 +287,7 @@ static int v4l2_async_match_notify(struct v4l2_async_notifier *notifier,
+ if (ret < 0)
+ return ret;
+
+- ret = v4l2_async_notifier_call_bound(notifier, sd, asd);
++ ret = v4l2_async_nf_call_bound(notifier, sd, asd);
+ if (ret < 0) {
+ v4l2_device_unregister_subdev(sd);
+ return ret;
+@@ -315,15 +315,15 @@ static int v4l2_async_match_notify(struct v4l2_async_notifier *notifier,
+ */
+ subdev_notifier->parent = notifier;
+
+- return v4l2_async_notifier_try_all_subdevs(subdev_notifier);
++ return v4l2_async_nf_try_all_subdevs(subdev_notifier);
+ }
+
+ /* Test all async sub-devices in a notifier for a match. */
+ static int
+-v4l2_async_notifier_try_all_subdevs(struct v4l2_async_notifier *notifier)
++v4l2_async_nf_try_all_subdevs(struct v4l2_async_notifier *notifier)
+ {
+ struct v4l2_device *v4l2_dev =
+- v4l2_async_notifier_find_v4l2_dev(notifier);
++ v4l2_async_nf_find_v4l2_dev(notifier);
+ struct v4l2_subdev *sd;
+
+ if (!v4l2_dev)
+@@ -367,7 +367,7 @@ static void v4l2_async_cleanup(struct v4l2_subdev *sd)
+
+ /* Unbind all sub-devices in the notifier tree. */
+ static void
+-v4l2_async_notifier_unbind_all_subdevs(struct v4l2_async_notifier *notifier)
++v4l2_async_nf_unbind_all_subdevs(struct v4l2_async_notifier *notifier)
+ {
+ struct v4l2_subdev *sd, *tmp;
+
+@@ -376,9 +376,9 @@ v4l2_async_notifier_unbind_all_subdevs(struct v4l2_async_notifier *notifier)
+ v4l2_async_find_subdev_notifier(sd);
+
+ if (subdev_notifier)
+- v4l2_async_notifier_unbind_all_subdevs(subdev_notifier);
++ v4l2_async_nf_unbind_all_subdevs(subdev_notifier);
+
+- v4l2_async_notifier_call_unbind(notifier, sd, sd->asd);
++ v4l2_async_nf_call_unbind(notifier, sd, sd->asd);
+ v4l2_async_cleanup(sd);
+
+ list_move(&sd->async_list, &subdev_list);
+@@ -389,8 +389,8 @@ v4l2_async_notifier_unbind_all_subdevs(struct v4l2_async_notifier *notifier)
+
+ /* See if an async sub-device can be found in a notifier's lists. */
+ static bool
+-__v4l2_async_notifier_has_async_subdev(struct v4l2_async_notifier *notifier,
+- struct v4l2_async_subdev *asd)
++__v4l2_async_nf_has_async_subdev(struct v4l2_async_notifier *notifier,
++ struct v4l2_async_subdev *asd)
+ {
+ struct v4l2_async_subdev *asd_y;
+ struct v4l2_subdev *sd;
+@@ -416,9 +416,8 @@ __v4l2_async_notifier_has_async_subdev(struct v4l2_async_notifier *notifier,
+ * If @this_index < 0, search the notifier's entire @asd_list.
+ */
+ static bool
+-v4l2_async_notifier_has_async_subdev(struct v4l2_async_notifier *notifier,
+- struct v4l2_async_subdev *asd,
+- int this_index)
++v4l2_async_nf_has_async_subdev(struct v4l2_async_notifier *notifier,
++ struct v4l2_async_subdev *asd, int this_index)
+ {
+ struct v4l2_async_subdev *asd_y;
+ int j = 0;
+@@ -435,15 +434,15 @@ v4l2_async_notifier_has_async_subdev(struct v4l2_async_notifier *notifier,
+
+ /* Check that an asd does not exist in other notifiers. */
+ list_for_each_entry(notifier, ¬ifier_list, list)
+- if (__v4l2_async_notifier_has_async_subdev(notifier, asd))
++ if (__v4l2_async_nf_has_async_subdev(notifier, asd))
+ return true;
+
+ return false;
+ }
+
+-static int v4l2_async_notifier_asd_valid(struct v4l2_async_notifier *notifier,
+- struct v4l2_async_subdev *asd,
+- int this_index)
++static int v4l2_async_nf_asd_valid(struct v4l2_async_notifier *notifier,
++ struct v4l2_async_subdev *asd,
++ int this_index)
+ {
+ struct device *dev =
+ notifier->v4l2_dev ? notifier->v4l2_dev->dev : NULL;
+@@ -454,8 +453,7 @@ static int v4l2_async_notifier_asd_valid(struct v4l2_async_notifier *notifier,
+ switch (asd->match_type) {
+ case V4L2_ASYNC_MATCH_I2C:
+ case V4L2_ASYNC_MATCH_FWNODE:
+- if (v4l2_async_notifier_has_async_subdev(notifier, asd,
+- this_index)) {
++ if (v4l2_async_nf_has_async_subdev(notifier, asd, this_index)) {
+ dev_dbg(dev, "subdev descriptor already listed in this or other notifiers\n");
+ return -EEXIST;
+ }
+@@ -469,13 +467,13 @@ static int v4l2_async_notifier_asd_valid(struct v4l2_async_notifier *notifier,
+ return 0;
+ }
+
+-void v4l2_async_notifier_init(struct v4l2_async_notifier *notifier)
++void v4l2_async_nf_init(struct v4l2_async_notifier *notifier)
+ {
+ INIT_LIST_HEAD(¬ifier->asd_list);
+ }
+-EXPORT_SYMBOL(v4l2_async_notifier_init);
++EXPORT_SYMBOL(v4l2_async_nf_init);
+
+-static int __v4l2_async_notifier_register(struct v4l2_async_notifier *notifier)
++static int __v4l2_async_nf_register(struct v4l2_async_notifier *notifier)
+ {
+ struct v4l2_async_subdev *asd;
+ int ret, i = 0;
+@@ -486,18 +484,18 @@ static int __v4l2_async_notifier_register(struct v4l2_async_notifier *notifier)
+ mutex_lock(&list_lock);
+
+ list_for_each_entry(asd, ¬ifier->asd_list, asd_list) {
+- ret = v4l2_async_notifier_asd_valid(notifier, asd, i++);
++ ret = v4l2_async_nf_asd_valid(notifier, asd, i++);
+ if (ret)
+ goto err_unlock;
+
+ list_add_tail(&asd->list, ¬ifier->waiting);
+ }
+
+- ret = v4l2_async_notifier_try_all_subdevs(notifier);
++ ret = v4l2_async_nf_try_all_subdevs(notifier);
+ if (ret < 0)
+ goto err_unbind;
+
+- ret = v4l2_async_notifier_try_complete(notifier);
++ ret = v4l2_async_nf_try_complete(notifier);
+ if (ret < 0)
+ goto err_unbind;
+
+@@ -512,7 +510,7 @@ static int __v4l2_async_notifier_register(struct v4l2_async_notifier *notifier)
+ /*
+ * On failure, unbind all sub-devices registered through this notifier.
+ */
+- v4l2_async_notifier_unbind_all_subdevs(notifier);
++ v4l2_async_nf_unbind_all_subdevs(notifier);
+
+ err_unlock:
+ mutex_unlock(&list_lock);
+@@ -520,8 +518,8 @@ static int __v4l2_async_notifier_register(struct v4l2_async_notifier *notifier)
+ return ret;
+ }
+
+-int v4l2_async_notifier_register(struct v4l2_device *v4l2_dev,
+- struct v4l2_async_notifier *notifier)
++int v4l2_async_nf_register(struct v4l2_device *v4l2_dev,
++ struct v4l2_async_notifier *notifier)
+ {
+ int ret;
+
+@@ -530,16 +528,16 @@ int v4l2_async_notifier_register(struct v4l2_device *v4l2_dev,
+
+ notifier->v4l2_dev = v4l2_dev;
+
+- ret = __v4l2_async_notifier_register(notifier);
++ ret = __v4l2_async_nf_register(notifier);
+ if (ret)
+ notifier->v4l2_dev = NULL;
+
+ return ret;
+ }
+-EXPORT_SYMBOL(v4l2_async_notifier_register);
++EXPORT_SYMBOL(v4l2_async_nf_register);
+
+-int v4l2_async_subdev_notifier_register(struct v4l2_subdev *sd,
+- struct v4l2_async_notifier *notifier)
++int v4l2_async_subdev_nf_register(struct v4l2_subdev *sd,
++ struct v4l2_async_notifier *notifier)
+ {
+ int ret;
+
+@@ -548,21 +546,21 @@ int v4l2_async_subdev_notifier_register(struct v4l2_subdev *sd,
+
+ notifier->sd = sd;
+
+- ret = __v4l2_async_notifier_register(notifier);
++ ret = __v4l2_async_nf_register(notifier);
+ if (ret)
+ notifier->sd = NULL;
+
+ return ret;
+ }
+-EXPORT_SYMBOL(v4l2_async_subdev_notifier_register);
++EXPORT_SYMBOL(v4l2_async_subdev_nf_register);
+
+ static void
+-__v4l2_async_notifier_unregister(struct v4l2_async_notifier *notifier)
++__v4l2_async_nf_unregister(struct v4l2_async_notifier *notifier)
+ {
+ if (!notifier || (!notifier->v4l2_dev && !notifier->sd))
+ return;
+
+- v4l2_async_notifier_unbind_all_subdevs(notifier);
++ v4l2_async_nf_unbind_all_subdevs(notifier);
+
+ notifier->sd = NULL;
+ notifier->v4l2_dev = NULL;
+@@ -570,17 +568,17 @@ __v4l2_async_notifier_unregister(struct v4l2_async_notifier *notifier)
+ list_del(¬ifier->list);
+ }
+
+-void v4l2_async_notifier_unregister(struct v4l2_async_notifier *notifier)
++void v4l2_async_nf_unregister(struct v4l2_async_notifier *notifier)
+ {
+ mutex_lock(&list_lock);
+
+- __v4l2_async_notifier_unregister(notifier);
++ __v4l2_async_nf_unregister(notifier);
+
+ mutex_unlock(&list_lock);
+ }
+-EXPORT_SYMBOL(v4l2_async_notifier_unregister);
++EXPORT_SYMBOL(v4l2_async_nf_unregister);
+
+-static void __v4l2_async_notifier_cleanup(struct v4l2_async_notifier *notifier)
++static void __v4l2_async_nf_cleanup(struct v4l2_async_notifier *notifier)
+ {
+ struct v4l2_async_subdev *asd, *tmp;
+
+@@ -601,24 +599,24 @@ static void __v4l2_async_notifier_cleanup(struct v4l2_async_notifier *notifier)
+ }
+ }
+
+-void v4l2_async_notifier_cleanup(struct v4l2_async_notifier *notifier)
++void v4l2_async_nf_cleanup(struct v4l2_async_notifier *notifier)
+ {
+ mutex_lock(&list_lock);
+
+- __v4l2_async_notifier_cleanup(notifier);
++ __v4l2_async_nf_cleanup(notifier);
+
+ mutex_unlock(&list_lock);
+ }
+-EXPORT_SYMBOL_GPL(v4l2_async_notifier_cleanup);
++EXPORT_SYMBOL_GPL(v4l2_async_nf_cleanup);
+
+-int __v4l2_async_notifier_add_subdev(struct v4l2_async_notifier *notifier,
+- struct v4l2_async_subdev *asd)
++int __v4l2_async_nf_add_subdev(struct v4l2_async_notifier *notifier,
++ struct v4l2_async_subdev *asd)
+ {
+ int ret;
+
+ mutex_lock(&list_lock);
+
+- ret = v4l2_async_notifier_asd_valid(notifier, asd, -1);
++ ret = v4l2_async_nf_asd_valid(notifier, asd, -1);
+ if (ret)
+ goto unlock;
+
+@@ -628,12 +626,12 @@ int __v4l2_async_notifier_add_subdev(struct v4l2_async_notifier *notifier,
+ mutex_unlock(&list_lock);
+ return ret;
+ }
+-EXPORT_SYMBOL_GPL(__v4l2_async_notifier_add_subdev);
++EXPORT_SYMBOL_GPL(__v4l2_async_nf_add_subdev);
+
+ struct v4l2_async_subdev *
+-__v4l2_async_notifier_add_fwnode_subdev(struct v4l2_async_notifier *notifier,
+- struct fwnode_handle *fwnode,
+- unsigned int asd_struct_size)
++__v4l2_async_nf_add_fwnode(struct v4l2_async_notifier *notifier,
++ struct fwnode_handle *fwnode,
++ unsigned int asd_struct_size)
+ {
+ struct v4l2_async_subdev *asd;
+ int ret;
+@@ -645,7 +643,7 @@ __v4l2_async_notifier_add_fwnode_subdev(struct v4l2_async_notifier *notifier,
+ asd->match_type = V4L2_ASYNC_MATCH_FWNODE;
+ asd->match.fwnode = fwnode_handle_get(fwnode);
+
+- ret = __v4l2_async_notifier_add_subdev(notifier, asd);
++ ret = __v4l2_async_nf_add_subdev(notifier, asd);
+ if (ret) {
+ fwnode_handle_put(fwnode);
+ kfree(asd);
+@@ -654,12 +652,12 @@ __v4l2_async_notifier_add_fwnode_subdev(struct v4l2_async_notifier *notifier,
+
+ return asd;
+ }
+-EXPORT_SYMBOL_GPL(__v4l2_async_notifier_add_fwnode_subdev);
++EXPORT_SYMBOL_GPL(__v4l2_async_nf_add_fwnode);
+
+ struct v4l2_async_subdev *
+-__v4l2_async_notifier_add_fwnode_remote_subdev(struct v4l2_async_notifier *notif,
+- struct fwnode_handle *endpoint,
+- unsigned int asd_struct_size)
++__v4l2_async_nf_add_fwnode_remote(struct v4l2_async_notifier *notif,
++ struct fwnode_handle *endpoint,
++ unsigned int asd_struct_size)
+ {
+ struct v4l2_async_subdev *asd;
+ struct fwnode_handle *remote;
+@@ -668,21 +666,19 @@ __v4l2_async_notifier_add_fwnode_remote_subdev(struct v4l2_async_notifier *notif
+ if (!remote)
+ return ERR_PTR(-ENOTCONN);
+
+- asd = __v4l2_async_notifier_add_fwnode_subdev(notif, remote,
+- asd_struct_size);
++ asd = __v4l2_async_nf_add_fwnode(notif, remote, asd_struct_size);
+ /*
+- * Calling __v4l2_async_notifier_add_fwnode_subdev grabs a refcount,
++ * Calling __v4l2_async_nf_add_fwnode grabs a refcount,
+ * so drop the one we got in fwnode_graph_get_remote_port_parent.
+ */
+ fwnode_handle_put(remote);
+ return asd;
+ }
+-EXPORT_SYMBOL_GPL(__v4l2_async_notifier_add_fwnode_remote_subdev);
++EXPORT_SYMBOL_GPL(__v4l2_async_nf_add_fwnode_remote);
+
+ struct v4l2_async_subdev *
+-__v4l2_async_notifier_add_i2c_subdev(struct v4l2_async_notifier *notifier,
+- int adapter_id, unsigned short address,
+- unsigned int asd_struct_size)
++__v4l2_async_nf_add_i2c(struct v4l2_async_notifier *notifier, int adapter_id,
++ unsigned short address, unsigned int asd_struct_size)
+ {
+ struct v4l2_async_subdev *asd;
+ int ret;
+@@ -695,7 +691,7 @@ __v4l2_async_notifier_add_i2c_subdev(struct v4l2_async_notifier *notifier,
+ asd->match.i2c.adapter_id = adapter_id;
+ asd->match.i2c.address = address;
+
+- ret = __v4l2_async_notifier_add_subdev(notifier, asd);
++ ret = __v4l2_async_nf_add_subdev(notifier, asd);
+ if (ret) {
+ kfree(asd);
+ return ERR_PTR(ret);
+@@ -703,7 +699,7 @@ __v4l2_async_notifier_add_i2c_subdev(struct v4l2_async_notifier *notifier,
+
+ return asd;
+ }
+-EXPORT_SYMBOL_GPL(__v4l2_async_notifier_add_i2c_subdev);
++EXPORT_SYMBOL_GPL(__v4l2_async_nf_add_i2c);
+
+ int v4l2_async_register_subdev(struct v4l2_subdev *sd)
+ {
+@@ -725,7 +721,7 @@ int v4l2_async_register_subdev(struct v4l2_subdev *sd)
+
+ list_for_each_entry(notifier, ¬ifier_list, list) {
+ struct v4l2_device *v4l2_dev =
+- v4l2_async_notifier_find_v4l2_dev(notifier);
++ v4l2_async_nf_find_v4l2_dev(notifier);
+ struct v4l2_async_subdev *asd;
+
+ if (!v4l2_dev)
+@@ -739,7 +735,7 @@ int v4l2_async_register_subdev(struct v4l2_subdev *sd)
+ if (ret)
+ goto err_unbind;
+
+- ret = v4l2_async_notifier_try_complete(notifier);
++ ret = v4l2_async_nf_try_complete(notifier);
+ if (ret)
+ goto err_unbind;
+
+@@ -761,10 +757,10 @@ int v4l2_async_register_subdev(struct v4l2_subdev *sd)
+ */
+ subdev_notifier = v4l2_async_find_subdev_notifier(sd);
+ if (subdev_notifier)
+- v4l2_async_notifier_unbind_all_subdevs(subdev_notifier);
++ v4l2_async_nf_unbind_all_subdevs(subdev_notifier);
+
+ if (sd->asd)
+- v4l2_async_notifier_call_unbind(notifier, sd, sd->asd);
++ v4l2_async_nf_call_unbind(notifier, sd, sd->asd);
+ v4l2_async_cleanup(sd);
+
+ mutex_unlock(&list_lock);
+@@ -780,8 +776,8 @@ void v4l2_async_unregister_subdev(struct v4l2_subdev *sd)
+
+ mutex_lock(&list_lock);
+
+- __v4l2_async_notifier_unregister(sd->subdev_notifier);
+- __v4l2_async_notifier_cleanup(sd->subdev_notifier);
++ __v4l2_async_nf_unregister(sd->subdev_notifier);
++ __v4l2_async_nf_cleanup(sd->subdev_notifier);
+ kfree(sd->subdev_notifier);
+ sd->subdev_notifier = NULL;
+
+@@ -790,7 +786,7 @@ void v4l2_async_unregister_subdev(struct v4l2_subdev *sd)
+
+ list_add(&sd->asd->list, ¬ifier->waiting);
+
+- v4l2_async_notifier_call_unbind(notifier, sd, sd->asd);
++ v4l2_async_nf_call_unbind(notifier, sd, sd->asd);
+ }
+
+ v4l2_async_cleanup(sd);
+@@ -825,7 +821,7 @@ static void print_waiting_subdev(struct seq_file *s,
+ }
+
+ static const char *
+-v4l2_async_notifier_name(struct v4l2_async_notifier *notifier)
++v4l2_async_nf_name(struct v4l2_async_notifier *notifier)
+ {
+ if (notifier->v4l2_dev)
+ return notifier->v4l2_dev->name;
+@@ -843,7 +839,7 @@ static int pending_subdevs_show(struct seq_file *s, void *data)
+ mutex_lock(&list_lock);
+
+ list_for_each_entry(notif, ¬ifier_list, list) {
+- seq_printf(s, "%s:\n", v4l2_async_notifier_name(notif));
++ seq_printf(s, "%s:\n", v4l2_async_nf_name(notif));
+ list_for_each_entry(asd, ¬if->waiting, list)
+ print_waiting_subdev(s, asd);
+ }
+diff --git a/drivers/media/v4l2-core/v4l2-fwnode.c b/drivers/media/v4l2-core/v4l2-fwnode.c
+index 5d2eaad1fa684..eb14193cc5aed 100644
+--- a/drivers/media/v4l2-core/v4l2-fwnode.c
++++ b/drivers/media/v4l2-core/v4l2-fwnode.c
+@@ -790,11 +790,11 @@ int v4l2_fwnode_device_parse(struct device *dev,
+ EXPORT_SYMBOL_GPL(v4l2_fwnode_device_parse);
+
+ static int
+-v4l2_async_notifier_fwnode_parse_endpoint(struct device *dev,
+- struct v4l2_async_notifier *notifier,
+- struct fwnode_handle *endpoint,
+- unsigned int asd_struct_size,
+- parse_endpoint_func parse_endpoint)
++v4l2_async_nf_fwnode_parse_endpoint(struct device *dev,
++ struct v4l2_async_notifier *notifier,
++ struct fwnode_handle *endpoint,
++ unsigned int asd_struct_size,
++ parse_endpoint_func parse_endpoint)
+ {
+ struct v4l2_fwnode_endpoint vep = { .bus_type = 0 };
+ struct v4l2_async_subdev *asd;
+@@ -832,7 +832,7 @@ v4l2_async_notifier_fwnode_parse_endpoint(struct device *dev,
+ if (ret < 0)
+ goto out_err;
+
+- ret = __v4l2_async_notifier_add_subdev(notifier, asd);
++ ret = __v4l2_async_nf_add_subdev(notifier, asd);
+ if (ret < 0) {
+ /* not an error if asd already exists */
+ if (ret == -EEXIST)
+@@ -850,12 +850,11 @@ v4l2_async_notifier_fwnode_parse_endpoint(struct device *dev,
+ }
+
+ static int
+-__v4l2_async_notifier_parse_fwnode_ep(struct device *dev,
+- struct v4l2_async_notifier *notifier,
+- size_t asd_struct_size,
+- unsigned int port,
+- bool has_port,
+- parse_endpoint_func parse_endpoint)
++__v4l2_async_nf_parse_fwnode_ep(struct device *dev,
++ struct v4l2_async_notifier *notifier,
++ size_t asd_struct_size, unsigned int port,
++ bool has_port,
++ parse_endpoint_func parse_endpoint)
+ {
+ struct fwnode_handle *fwnode;
+ int ret = 0;
+@@ -884,11 +883,10 @@ __v4l2_async_notifier_parse_fwnode_ep(struct device *dev,
+ continue;
+ }
+
+- ret = v4l2_async_notifier_fwnode_parse_endpoint(dev,
+- notifier,
+- fwnode,
+- asd_struct_size,
+- parse_endpoint);
++ ret = v4l2_async_nf_fwnode_parse_endpoint(dev, notifier,
++ fwnode,
++ asd_struct_size,
++ parse_endpoint);
+ if (ret < 0)
+ break;
+ }
+@@ -899,16 +897,15 @@ __v4l2_async_notifier_parse_fwnode_ep(struct device *dev,
+ }
+
+ int
+-v4l2_async_notifier_parse_fwnode_endpoints(struct device *dev,
+- struct v4l2_async_notifier *notifier,
+- size_t asd_struct_size,
+- parse_endpoint_func parse_endpoint)
++v4l2_async_nf_parse_fwnode_endpoints(struct device *dev,
++ struct v4l2_async_notifier *notifier,
++ size_t asd_struct_size,
++ parse_endpoint_func parse_endpoint)
+ {
+- return __v4l2_async_notifier_parse_fwnode_ep(dev, notifier,
+- asd_struct_size, 0,
+- false, parse_endpoint);
++ return __v4l2_async_nf_parse_fwnode_ep(dev, notifier, asd_struct_size,
++ 0, false, parse_endpoint);
+ }
+-EXPORT_SYMBOL_GPL(v4l2_async_notifier_parse_fwnode_endpoints);
++EXPORT_SYMBOL_GPL(v4l2_async_nf_parse_fwnode_endpoints);
+
+ /*
+ * v4l2_fwnode_reference_parse - parse references for async sub-devices
+@@ -952,9 +949,8 @@ static int v4l2_fwnode_reference_parse(struct device *dev,
+ index++) {
+ struct v4l2_async_subdev *asd;
+
+- asd = v4l2_async_notifier_add_fwnode_subdev(notifier,
+- args.fwnode,
+- struct v4l2_async_subdev);
++ asd = v4l2_async_nf_add_fwnode(notifier, args.fwnode,
++ struct v4l2_async_subdev);
+ fwnode_handle_put(args.fwnode);
+ if (IS_ERR(asd)) {
+ /* not an error if asd already exists */
+@@ -1253,8 +1249,8 @@ v4l2_fwnode_reference_parse_int_props(struct device *dev,
+ index++) {
+ struct v4l2_async_subdev *asd;
+
+- asd = v4l2_async_notifier_add_fwnode_subdev(notifier, fwnode,
+- struct v4l2_async_subdev);
++ asd = v4l2_async_nf_add_fwnode(notifier, fwnode,
++ struct v4l2_async_subdev);
+ fwnode_handle_put(fwnode);
+ if (IS_ERR(asd)) {
+ ret = PTR_ERR(asd);
+@@ -1270,7 +1266,7 @@ v4l2_fwnode_reference_parse_int_props(struct device *dev,
+ }
+
+ /**
+- * v4l2_async_notifier_parse_fwnode_sensor - parse common references on
++ * v4l2_async_nf_parse_fwnode_sensor - parse common references on
+ * sensors for async sub-devices
+ * @dev: the device node the properties of which are parsed for references
+ * @notifier: the async notifier where the async subdevs will be added
+@@ -1279,7 +1275,7 @@ v4l2_fwnode_reference_parse_int_props(struct device *dev,
+ * sensor and set up async sub-devices for them.
+ *
+ * Any notifier populated using this function must be released with a call to
+- * v4l2_async_notifier_release() after it has been unregistered and the async
++ * v4l2_async_nf_release() after it has been unregistered and the async
+ * sub-devices are no longer in use, even in the case the function returned an
+ * error.
+ *
+@@ -1288,8 +1284,8 @@ v4l2_fwnode_reference_parse_int_props(struct device *dev,
+ * -EINVAL if property parsing failed
+ */
+ static int
+-v4l2_async_notifier_parse_fwnode_sensor(struct device *dev,
+- struct v4l2_async_notifier *notifier)
++v4l2_async_nf_parse_fwnode_sensor(struct device *dev,
++ struct v4l2_async_notifier *notifier)
+ {
+ static const char * const led_props[] = { "led" };
+ static const struct v4l2_fwnode_int_props props[] = {
+@@ -1330,13 +1326,13 @@ int v4l2_async_register_subdev_sensor(struct v4l2_subdev *sd)
+ if (!notifier)
+ return -ENOMEM;
+
+- v4l2_async_notifier_init(notifier);
++ v4l2_async_nf_init(notifier);
+
+- ret = v4l2_async_notifier_parse_fwnode_sensor(sd->dev, notifier);
++ ret = v4l2_async_nf_parse_fwnode_sensor(sd->dev, notifier);
+ if (ret < 0)
+ goto out_cleanup;
+
+- ret = v4l2_async_subdev_notifier_register(sd, notifier);
++ ret = v4l2_async_subdev_nf_register(sd, notifier);
+ if (ret < 0)
+ goto out_cleanup;
+
+@@ -1349,10 +1345,10 @@ int v4l2_async_register_subdev_sensor(struct v4l2_subdev *sd)
+ return 0;
+
+ out_unregister:
+- v4l2_async_notifier_unregister(notifier);
++ v4l2_async_nf_unregister(notifier);
+
+ out_cleanup:
+- v4l2_async_notifier_cleanup(notifier);
++ v4l2_async_nf_cleanup(notifier);
+ kfree(notifier);
+
+ return ret;
+diff --git a/drivers/staging/media/imx/imx-media-csi.c b/drivers/staging/media/imx/imx-media-csi.c
+index bb1305c9daaf5..45f9d797b9da6 100644
+--- a/drivers/staging/media/imx/imx-media-csi.c
++++ b/drivers/staging/media/imx/imx-media-csi.c
+@@ -1924,7 +1924,7 @@ static int imx_csi_async_register(struct csi_priv *priv)
+ unsigned int port;
+ int ret;
+
+- v4l2_async_notifier_init(&priv->notifier);
++ v4l2_async_nf_init(&priv->notifier);
+
+ /* get this CSI's port id */
+ ret = fwnode_property_read_u32(dev_fwnode(priv->dev), "reg", &port);
+@@ -1935,8 +1935,8 @@ static int imx_csi_async_register(struct csi_priv *priv)
+ port, 0,
+ FWNODE_GRAPH_ENDPOINT_NEXT);
+ if (ep) {
+- asd = v4l2_async_notifier_add_fwnode_remote_subdev(
+- &priv->notifier, ep, struct v4l2_async_subdev);
++ asd = v4l2_async_nf_add_fwnode_remote(&priv->notifier, ep,
++ struct v4l2_async_subdev);
+
+ fwnode_handle_put(ep);
+
+@@ -1950,8 +1950,7 @@ static int imx_csi_async_register(struct csi_priv *priv)
+
+ priv->notifier.ops = &csi_notify_ops;
+
+- ret = v4l2_async_subdev_notifier_register(&priv->sd,
+- &priv->notifier);
++ ret = v4l2_async_subdev_nf_register(&priv->sd, &priv->notifier);
+ if (ret)
+ return ret;
+
+@@ -2040,8 +2039,8 @@ static int imx_csi_probe(struct platform_device *pdev)
+ return 0;
+
+ cleanup:
+- v4l2_async_notifier_unregister(&priv->notifier);
+- v4l2_async_notifier_cleanup(&priv->notifier);
++ v4l2_async_nf_unregister(&priv->notifier);
++ v4l2_async_nf_cleanup(&priv->notifier);
+ free:
+ v4l2_ctrl_handler_free(&priv->ctrl_hdlr);
+ mutex_destroy(&priv->lock);
+@@ -2055,8 +2054,8 @@ static int imx_csi_remove(struct platform_device *pdev)
+
+ v4l2_ctrl_handler_free(&priv->ctrl_hdlr);
+ mutex_destroy(&priv->lock);
+- v4l2_async_notifier_unregister(&priv->notifier);
+- v4l2_async_notifier_cleanup(&priv->notifier);
++ v4l2_async_nf_unregister(&priv->notifier);
++ v4l2_async_nf_cleanup(&priv->notifier);
+ v4l2_async_unregister_subdev(sd);
+ media_entity_cleanup(&sd->entity);
+
+diff --git a/drivers/staging/media/imx/imx-media-dev-common.c b/drivers/staging/media/imx/imx-media-dev-common.c
+index 4d873726a461b..80b69a9a752cb 100644
+--- a/drivers/staging/media/imx/imx-media-dev-common.c
++++ b/drivers/staging/media/imx/imx-media-dev-common.c
+@@ -381,7 +381,7 @@ struct imx_media_dev *imx_media_dev_init(struct device *dev,
+
+ INIT_LIST_HEAD(&imxmd->vdev_list);
+
+- v4l2_async_notifier_init(&imxmd->notifier);
++ v4l2_async_nf_init(&imxmd->notifier);
+
+ return imxmd;
+
+@@ -405,11 +405,10 @@ int imx_media_dev_notifier_register(struct imx_media_dev *imxmd,
+
+ /* prepare the async subdev notifier and register it */
+ imxmd->notifier.ops = ops ? ops : &imx_media_notifier_ops;
+- ret = v4l2_async_notifier_register(&imxmd->v4l2_dev,
+- &imxmd->notifier);
++ ret = v4l2_async_nf_register(&imxmd->v4l2_dev, &imxmd->notifier);
+ if (ret) {
+ v4l2_err(&imxmd->v4l2_dev,
+- "v4l2_async_notifier_register failed with %d\n", ret);
++ "v4l2_async_nf_register failed with %d\n", ret);
+ return ret;
+ }
+
+diff --git a/drivers/staging/media/imx/imx-media-dev.c b/drivers/staging/media/imx/imx-media-dev.c
+index 338b8bd0bb076..f85462214e221 100644
+--- a/drivers/staging/media/imx/imx-media-dev.c
++++ b/drivers/staging/media/imx/imx-media-dev.c
+@@ -94,7 +94,7 @@ static int imx_media_probe(struct platform_device *pdev)
+ return 0;
+
+ cleanup:
+- v4l2_async_notifier_cleanup(&imxmd->notifier);
++ v4l2_async_nf_cleanup(&imxmd->notifier);
+ v4l2_device_unregister(&imxmd->v4l2_dev);
+ media_device_cleanup(&imxmd->md);
+
+@@ -113,9 +113,9 @@ static int imx_media_remove(struct platform_device *pdev)
+ imxmd->m2m_vdev = NULL;
+ }
+
+- v4l2_async_notifier_unregister(&imxmd->notifier);
++ v4l2_async_nf_unregister(&imxmd->notifier);
+ imx_media_unregister_ipu_internal_subdevs(imxmd);
+- v4l2_async_notifier_cleanup(&imxmd->notifier);
++ v4l2_async_nf_cleanup(&imxmd->notifier);
+ media_device_unregister(&imxmd->md);
+ v4l2_device_unregister(&imxmd->v4l2_dev);
+ media_device_cleanup(&imxmd->md);
+diff --git a/drivers/staging/media/imx/imx-media-of.c b/drivers/staging/media/imx/imx-media-of.c
+index b677cf0e0c849..59f1eb7b62bcd 100644
+--- a/drivers/staging/media/imx/imx-media-of.c
++++ b/drivers/staging/media/imx/imx-media-of.c
+@@ -29,9 +29,9 @@ int imx_media_of_add_csi(struct imx_media_dev *imxmd,
+ }
+
+ /* add CSI fwnode to async notifier */
+- asd = v4l2_async_notifier_add_fwnode_subdev(&imxmd->notifier,
+- of_fwnode_handle(csi_np),
+- struct v4l2_async_subdev);
++ asd = v4l2_async_nf_add_fwnode(&imxmd->notifier,
++ of_fwnode_handle(csi_np),
++ struct v4l2_async_subdev);
+ if (IS_ERR(asd)) {
+ ret = PTR_ERR(asd);
+ if (ret == -EEXIST)
+diff --git a/drivers/staging/media/imx/imx6-mipi-csi2.c b/drivers/staging/media/imx/imx6-mipi-csi2.c
+index 9de0ebd439dc6..a0941fc2907b7 100644
+--- a/drivers/staging/media/imx/imx6-mipi-csi2.c
++++ b/drivers/staging/media/imx/imx6-mipi-csi2.c
+@@ -647,7 +647,7 @@ static int csi2_async_register(struct csi2_dev *csi2)
+ struct fwnode_handle *ep;
+ int ret;
+
+- v4l2_async_notifier_init(&csi2->notifier);
++ v4l2_async_nf_init(&csi2->notifier);
+
+ ep = fwnode_graph_get_endpoint_by_id(dev_fwnode(csi2->dev), 0, 0,
+ FWNODE_GRAPH_ENDPOINT_NEXT);
+@@ -663,8 +663,8 @@ static int csi2_async_register(struct csi2_dev *csi2)
+ dev_dbg(csi2->dev, "data lanes: %d\n", vep.bus.mipi_csi2.num_data_lanes);
+ dev_dbg(csi2->dev, "flags: 0x%08x\n", vep.bus.mipi_csi2.flags);
+
+- asd = v4l2_async_notifier_add_fwnode_remote_subdev(
+- &csi2->notifier, ep, struct v4l2_async_subdev);
++ asd = v4l2_async_nf_add_fwnode_remote(&csi2->notifier, ep,
++ struct v4l2_async_subdev);
+ fwnode_handle_put(ep);
+
+ if (IS_ERR(asd))
+@@ -672,8 +672,7 @@ static int csi2_async_register(struct csi2_dev *csi2)
+
+ csi2->notifier.ops = &csi2_notify_ops;
+
+- ret = v4l2_async_subdev_notifier_register(&csi2->sd,
+- &csi2->notifier);
++ ret = v4l2_async_subdev_nf_register(&csi2->sd, &csi2->notifier);
+ if (ret)
+ return ret;
+
+@@ -768,8 +767,8 @@ static int csi2_probe(struct platform_device *pdev)
+ return 0;
+
+ clean_notifier:
+- v4l2_async_notifier_unregister(&csi2->notifier);
+- v4l2_async_notifier_cleanup(&csi2->notifier);
++ v4l2_async_nf_unregister(&csi2->notifier);
++ v4l2_async_nf_cleanup(&csi2->notifier);
+ clk_disable_unprepare(csi2->dphy_clk);
+ pllref_off:
+ clk_disable_unprepare(csi2->pllref_clk);
+@@ -783,8 +782,8 @@ static int csi2_remove(struct platform_device *pdev)
+ struct v4l2_subdev *sd = platform_get_drvdata(pdev);
+ struct csi2_dev *csi2 = sd_to_dev(sd);
+
+- v4l2_async_notifier_unregister(&csi2->notifier);
+- v4l2_async_notifier_cleanup(&csi2->notifier);
++ v4l2_async_nf_unregister(&csi2->notifier);
++ v4l2_async_nf_cleanup(&csi2->notifier);
+ v4l2_async_unregister_subdev(sd);
+ clk_disable_unprepare(csi2->dphy_clk);
+ clk_disable_unprepare(csi2->pllref_clk);
+diff --git a/drivers/staging/media/imx/imx7-media-csi.c b/drivers/staging/media/imx/imx7-media-csi.c
+index 1271837329124..2288dadb2683a 100644
+--- a/drivers/staging/media/imx/imx7-media-csi.c
++++ b/drivers/staging/media/imx/imx7-media-csi.c
+@@ -1099,13 +1099,13 @@ static int imx7_csi_async_register(struct imx7_csi *csi)
+ struct fwnode_handle *ep;
+ int ret;
+
+- v4l2_async_notifier_init(&csi->notifier);
++ v4l2_async_nf_init(&csi->notifier);
+
+ ep = fwnode_graph_get_endpoint_by_id(dev_fwnode(csi->dev), 0, 0,
+ FWNODE_GRAPH_ENDPOINT_NEXT);
+ if (ep) {
+- asd = v4l2_async_notifier_add_fwnode_remote_subdev(
+- &csi->notifier, ep, struct v4l2_async_subdev);
++ asd = v4l2_async_nf_add_fwnode_remote(&csi->notifier, ep,
++ struct v4l2_async_subdev);
+
+ fwnode_handle_put(ep);
+
+@@ -1119,7 +1119,7 @@ static int imx7_csi_async_register(struct imx7_csi *csi)
+
+ csi->notifier.ops = &imx7_csi_notify_ops;
+
+- ret = v4l2_async_subdev_notifier_register(&csi->sd, &csi->notifier);
++ ret = v4l2_async_subdev_nf_register(&csi->sd, &csi->notifier);
+ if (ret)
+ return ret;
+
+@@ -1210,12 +1210,12 @@ static int imx7_csi_probe(struct platform_device *pdev)
+ return 0;
+
+ subdev_notifier_cleanup:
+- v4l2_async_notifier_unregister(&csi->notifier);
+- v4l2_async_notifier_cleanup(&csi->notifier);
++ v4l2_async_nf_unregister(&csi->notifier);
++ v4l2_async_nf_cleanup(&csi->notifier);
+
+ cleanup:
+- v4l2_async_notifier_unregister(&imxmd->notifier);
+- v4l2_async_notifier_cleanup(&imxmd->notifier);
++ v4l2_async_nf_unregister(&imxmd->notifier);
++ v4l2_async_nf_cleanup(&imxmd->notifier);
+ v4l2_device_unregister(&imxmd->v4l2_dev);
+ media_device_unregister(&imxmd->md);
+ media_device_cleanup(&imxmd->md);
+@@ -1232,15 +1232,15 @@ static int imx7_csi_remove(struct platform_device *pdev)
+ struct imx7_csi *csi = v4l2_get_subdevdata(sd);
+ struct imx_media_dev *imxmd = csi->imxmd;
+
+- v4l2_async_notifier_unregister(&imxmd->notifier);
+- v4l2_async_notifier_cleanup(&imxmd->notifier);
++ v4l2_async_nf_unregister(&imxmd->notifier);
++ v4l2_async_nf_cleanup(&imxmd->notifier);
+
+ media_device_unregister(&imxmd->md);
+ v4l2_device_unregister(&imxmd->v4l2_dev);
+ media_device_cleanup(&imxmd->md);
+
+- v4l2_async_notifier_unregister(&csi->notifier);
+- v4l2_async_notifier_cleanup(&csi->notifier);
++ v4l2_async_nf_unregister(&csi->notifier);
++ v4l2_async_nf_cleanup(&csi->notifier);
+ v4l2_async_unregister_subdev(sd);
+
+ mutex_destroy(&csi->lock);
+diff --git a/drivers/staging/media/imx/imx7-mipi-csis.c b/drivers/staging/media/imx/imx7-mipi-csis.c
+index d35e523741168..9ea723bb5f209 100644
+--- a/drivers/staging/media/imx/imx7-mipi-csis.c
++++ b/drivers/staging/media/imx/imx7-mipi-csis.c
+@@ -1160,7 +1160,7 @@ static int mipi_csis_async_register(struct csi_state *state)
+ unsigned int i;
+ int ret;
+
+- v4l2_async_notifier_init(&state->notifier);
++ v4l2_async_nf_init(&state->notifier);
+
+ ep = fwnode_graph_get_endpoint_by_id(dev_fwnode(state->dev), 0, 0,
+ FWNODE_GRAPH_ENDPOINT_NEXT);
+@@ -1185,8 +1185,8 @@ static int mipi_csis_async_register(struct csi_state *state)
+ dev_dbg(state->dev, "data lanes: %d\n", state->bus.num_data_lanes);
+ dev_dbg(state->dev, "flags: 0x%08x\n", state->bus.flags);
+
+- asd = v4l2_async_notifier_add_fwnode_remote_subdev(
+- &state->notifier, ep, struct v4l2_async_subdev);
++ asd = v4l2_async_nf_add_fwnode_remote(&state->notifier, ep,
++ struct v4l2_async_subdev);
+ if (IS_ERR(asd)) {
+ ret = PTR_ERR(asd);
+ goto err_parse;
+@@ -1196,7 +1196,7 @@ static int mipi_csis_async_register(struct csi_state *state)
+
+ state->notifier.ops = &mipi_csis_notify_ops;
+
+- ret = v4l2_async_subdev_notifier_register(&state->sd, &state->notifier);
++ ret = v4l2_async_subdev_nf_register(&state->sd, &state->notifier);
+ if (ret)
+ return ret;
+
+@@ -1427,8 +1427,8 @@ static int mipi_csis_probe(struct platform_device *pdev)
+ mipi_csis_debugfs_exit(state);
+ cleanup:
+ media_entity_cleanup(&state->sd.entity);
+- v4l2_async_notifier_unregister(&state->notifier);
+- v4l2_async_notifier_cleanup(&state->notifier);
++ v4l2_async_nf_unregister(&state->notifier);
++ v4l2_async_nf_cleanup(&state->notifier);
+ v4l2_async_unregister_subdev(&state->sd);
+ disable_clock:
+ mipi_csis_clk_disable(state);
+@@ -1443,8 +1443,8 @@ static int mipi_csis_remove(struct platform_device *pdev)
+ struct csi_state *state = mipi_sd_to_csis_state(sd);
+
+ mipi_csis_debugfs_exit(state);
+- v4l2_async_notifier_unregister(&state->notifier);
+- v4l2_async_notifier_cleanup(&state->notifier);
++ v4l2_async_nf_unregister(&state->notifier);
++ v4l2_async_nf_cleanup(&state->notifier);
+ v4l2_async_unregister_subdev(&state->sd);
+
+ pm_runtime_disable(&pdev->dev);
+diff --git a/drivers/staging/media/imx/imx8mq-mipi-csi2.c b/drivers/staging/media/imx/imx8mq-mipi-csi2.c
+index 1d28313dbed7d..3b9fa75efac6b 100644
+--- a/drivers/staging/media/imx/imx8mq-mipi-csi2.c
++++ b/drivers/staging/media/imx/imx8mq-mipi-csi2.c
+@@ -640,7 +640,7 @@ static int imx8mq_mipi_csi_async_register(struct csi_state *state)
+ unsigned int i;
+ int ret;
+
+- v4l2_async_notifier_init(&state->notifier);
++ v4l2_async_nf_init(&state->notifier);
+
+ ep = fwnode_graph_get_endpoint_by_id(dev_fwnode(state->dev), 0, 0,
+ FWNODE_GRAPH_ENDPOINT_NEXT);
+@@ -666,8 +666,8 @@ static int imx8mq_mipi_csi_async_register(struct csi_state *state)
+ state->bus.num_data_lanes,
+ state->bus.flags);
+
+- asd = v4l2_async_notifier_add_fwnode_remote_subdev(&state->notifier,
+- ep, struct v4l2_async_subdev);
++ asd = v4l2_async_nf_add_fwnode_remote(&state->notifier, ep,
++ struct v4l2_async_subdev);
+ if (IS_ERR(asd)) {
+ ret = PTR_ERR(asd);
+ goto err_parse;
+@@ -677,7 +677,7 @@ static int imx8mq_mipi_csi_async_register(struct csi_state *state)
+
+ state->notifier.ops = &imx8mq_mipi_csi_notify_ops;
+
+- ret = v4l2_async_subdev_notifier_register(&state->sd, &state->notifier);
++ ret = v4l2_async_subdev_nf_register(&state->sd, &state->notifier);
+ if (ret)
+ return ret;
+
+@@ -957,8 +957,8 @@ static int imx8mq_mipi_csi_probe(struct platform_device *pdev)
+ imx8mq_mipi_csi_runtime_suspend(&pdev->dev);
+
+ media_entity_cleanup(&state->sd.entity);
+- v4l2_async_notifier_unregister(&state->notifier);
+- v4l2_async_notifier_cleanup(&state->notifier);
++ v4l2_async_nf_unregister(&state->notifier);
++ v4l2_async_nf_cleanup(&state->notifier);
+ v4l2_async_unregister_subdev(&state->sd);
+ icc:
+ imx8mq_mipi_csi_release_icc(pdev);
+@@ -973,8 +973,8 @@ static int imx8mq_mipi_csi_remove(struct platform_device *pdev)
+ struct v4l2_subdev *sd = platform_get_drvdata(pdev);
+ struct csi_state *state = mipi_sd_to_csi2_state(sd);
+
+- v4l2_async_notifier_unregister(&state->notifier);
+- v4l2_async_notifier_cleanup(&state->notifier);
++ v4l2_async_nf_unregister(&state->notifier);
++ v4l2_async_nf_cleanup(&state->notifier);
+ v4l2_async_unregister_subdev(&state->sd);
+
+ pm_runtime_disable(&pdev->dev);
+diff --git a/drivers/staging/media/tegra-video/vi.c b/drivers/staging/media/tegra-video/vi.c
+index d321790b07d95..69d9787d53384 100644
+--- a/drivers/staging/media/tegra-video/vi.c
++++ b/drivers/staging/media/tegra-video/vi.c
+@@ -1272,7 +1272,7 @@ static int tegra_channel_init(struct tegra_vi_channel *chan)
+ }
+
+ if (!IS_ENABLED(CONFIG_VIDEO_TEGRA_TPG))
+- v4l2_async_notifier_init(&chan->notifier);
++ v4l2_async_nf_init(&chan->notifier);
+
+ return 0;
+
+@@ -1811,8 +1811,8 @@ static int tegra_vi_graph_parse_one(struct tegra_vi_channel *chan,
+ continue;
+ }
+
+- tvge = v4l2_async_notifier_add_fwnode_subdev(&chan->notifier, remote,
+- struct tegra_vi_graph_entity);
++ tvge = v4l2_async_nf_add_fwnode(&chan->notifier, remote,
++ struct tegra_vi_graph_entity);
+ if (IS_ERR(tvge)) {
+ ret = PTR_ERR(tvge);
+ dev_err(vi->dev,
+@@ -1834,7 +1834,7 @@ static int tegra_vi_graph_parse_one(struct tegra_vi_channel *chan,
+
+ cleanup:
+ dev_err(vi->dev, "failed parsing the graph: %d\n", ret);
+- v4l2_async_notifier_cleanup(&chan->notifier);
++ v4l2_async_nf_cleanup(&chan->notifier);
+ of_node_put(node);
+ return ret;
+ }
+@@ -1868,13 +1868,12 @@ static int tegra_vi_graph_init(struct tegra_vi *vi)
+ continue;
+
+ chan->notifier.ops = &tegra_vi_async_ops;
+- ret = v4l2_async_notifier_register(&vid->v4l2_dev,
+- &chan->notifier);
++ ret = v4l2_async_nf_register(&vid->v4l2_dev, &chan->notifier);
+ if (ret < 0) {
+ dev_err(vi->dev,
+ "failed to register channel %d notifier: %d\n",
+ chan->portnos[0], ret);
+- v4l2_async_notifier_cleanup(&chan->notifier);
++ v4l2_async_nf_cleanup(&chan->notifier);
+ }
+ }
+
+@@ -1887,8 +1886,8 @@ static void tegra_vi_graph_cleanup(struct tegra_vi *vi)
+
+ list_for_each_entry(chan, &vi->vi_chans, list) {
+ vb2_video_unregister_device(&chan->video);
+- v4l2_async_notifier_unregister(&chan->notifier);
+- v4l2_async_notifier_cleanup(&chan->notifier);
++ v4l2_async_nf_unregister(&chan->notifier);
++ v4l2_async_nf_cleanup(&chan->notifier);
+ }
+ }
+
+diff --git a/include/media/v4l2-async.h b/include/media/v4l2-async.h
+index fa4901162663b..13ff3ad948f43 100644
+--- a/include/media/v4l2-async.h
++++ b/include/media/v4l2-async.h
+@@ -123,45 +123,45 @@ struct v4l2_async_notifier {
+ void v4l2_async_debug_init(struct dentry *debugfs_dir);
+
+ /**
+- * v4l2_async_notifier_init - Initialize a notifier.
++ * v4l2_async_nf_init - Initialize a notifier.
+ *
+ * @notifier: pointer to &struct v4l2_async_notifier
+ *
+ * This function initializes the notifier @asd_list. It must be called
+ * before adding a subdevice to a notifier, using one of:
+- * v4l2_async_notifier_add_fwnode_remote_subdev(),
+- * v4l2_async_notifier_add_fwnode_subdev(),
+- * v4l2_async_notifier_add_i2c_subdev(),
+- * __v4l2_async_notifier_add_subdev() or
+- * v4l2_async_notifier_parse_fwnode_endpoints().
++ * v4l2_async_nf_add_fwnode_remote(),
++ * v4l2_async_nf_add_fwnode(),
++ * v4l2_async_nf_add_i2c(),
++ * __v4l2_async_nf_add_subdev() or
++ * v4l2_async_nf_parse_fwnode_endpoints().
+ */
+-void v4l2_async_notifier_init(struct v4l2_async_notifier *notifier);
++void v4l2_async_nf_init(struct v4l2_async_notifier *notifier);
+
+ /**
+- * __v4l2_async_notifier_add_subdev - Add an async subdev to the
++ * __v4l2_async_nf_add_subdev - Add an async subdev to the
+ * notifier's master asd list.
+ *
+ * @notifier: pointer to &struct v4l2_async_notifier
+ * @asd: pointer to &struct v4l2_async_subdev
+ *
+ * \warning: Drivers should avoid using this function and instead use one of:
+- * v4l2_async_notifier_add_fwnode_subdev(),
+- * v4l2_async_notifier_add_fwnode_remote_subdev() or
+- * v4l2_async_notifier_add_i2c_subdev().
++ * v4l2_async_nf_add_fwnode(),
++ * v4l2_async_nf_add_fwnode_remote() or
++ * v4l2_async_nf_add_i2c().
+ *
+ * Call this function before registering a notifier to link the provided @asd to
+ * the notifiers master @asd_list. The @asd must be allocated with k*alloc() as
+ * it will be freed by the framework when the notifier is destroyed.
+ */
+-int __v4l2_async_notifier_add_subdev(struct v4l2_async_notifier *notifier,
+- struct v4l2_async_subdev *asd);
++int __v4l2_async_nf_add_subdev(struct v4l2_async_notifier *notifier,
++ struct v4l2_async_subdev *asd);
+
+ struct v4l2_async_subdev *
+-__v4l2_async_notifier_add_fwnode_subdev(struct v4l2_async_notifier *notifier,
+- struct fwnode_handle *fwnode,
+- unsigned int asd_struct_size);
++__v4l2_async_nf_add_fwnode(struct v4l2_async_notifier *notifier,
++ struct fwnode_handle *fwnode,
++ unsigned int asd_struct_size);
+ /**
+- * v4l2_async_notifier_add_fwnode_subdev - Allocate and add a fwnode async
++ * v4l2_async_nf_add_fwnode - Allocate and add a fwnode async
+ * subdev to the notifier's master asd_list.
+ *
+ * @notifier: pointer to &struct v4l2_async_notifier
+@@ -175,16 +175,15 @@ __v4l2_async_notifier_add_fwnode_subdev(struct v4l2_async_notifier *notifier,
+ * notifiers @asd_list. The function also gets a reference of the fwnode which
+ * is released later at notifier cleanup time.
+ */
+-#define v4l2_async_notifier_add_fwnode_subdev(notifier, fwnode, type) \
+- ((type *)__v4l2_async_notifier_add_fwnode_subdev(notifier, fwnode, \
+- sizeof(type)))
++#define v4l2_async_nf_add_fwnode(notifier, fwnode, type) \
++ ((type *)__v4l2_async_nf_add_fwnode(notifier, fwnode, sizeof(type)))
+
+ struct v4l2_async_subdev *
+-__v4l2_async_notifier_add_fwnode_remote_subdev(struct v4l2_async_notifier *notif,
+- struct fwnode_handle *endpoint,
+- unsigned int asd_struct_size);
++__v4l2_async_nf_add_fwnode_remote(struct v4l2_async_notifier *notif,
++ struct fwnode_handle *endpoint,
++ unsigned int asd_struct_size);
+ /**
+- * v4l2_async_notifier_add_fwnode_remote_subdev - Allocate and add a fwnode
++ * v4l2_async_nf_add_fwnode_remote - Allocate and add a fwnode
+ * remote async subdev to the
+ * notifier's master asd_list.
+ *
+@@ -200,20 +199,18 @@ __v4l2_async_notifier_add_fwnode_remote_subdev(struct v4l2_async_notifier *notif
+ * function also gets a reference of the fwnode which is released later at
+ * notifier cleanup time.
+ *
+- * This is just like v4l2_async_notifier_add_fwnode_subdev(), but with the
++ * This is just like v4l2_async_nf_add_fwnode(), but with the
+ * exception that the fwnode refers to a local endpoint, not the remote one.
+ */
+-#define v4l2_async_notifier_add_fwnode_remote_subdev(notifier, ep, type) \
+- ((type *) \
+- __v4l2_async_notifier_add_fwnode_remote_subdev(notifier, ep, \
+- sizeof(type)))
++#define v4l2_async_nf_add_fwnode_remote(notifier, ep, type) \
++ ((type *)__v4l2_async_nf_add_fwnode_remote(notifier, ep, sizeof(type)))
+
+ struct v4l2_async_subdev *
+-__v4l2_async_notifier_add_i2c_subdev(struct v4l2_async_notifier *notifier,
+- int adapter_id, unsigned short address,
+- unsigned int asd_struct_size);
++__v4l2_async_nf_add_i2c(struct v4l2_async_notifier *notifier,
++ int adapter_id, unsigned short address,
++ unsigned int asd_struct_size);
+ /**
+- * v4l2_async_notifier_add_i2c_subdev - Allocate and add an i2c async
++ * v4l2_async_nf_add_i2c - Allocate and add an i2c async
+ * subdev to the notifier's master asd_list.
+ *
+ * @notifier: pointer to &struct v4l2_async_notifier
+@@ -223,59 +220,59 @@ __v4l2_async_notifier_add_i2c_subdev(struct v4l2_async_notifier *notifier,
+ * v4l2_async_subdev shall be the first member of the driver's async
+ * sub-device struct, i.e. both begin at the same memory address.
+ *
+- * Same as v4l2_async_notifier_add_fwnode_subdev() but for I2C matched
++ * Same as v4l2_async_nf_add_fwnode() but for I2C matched
+ * sub-devices.
+ */
+-#define v4l2_async_notifier_add_i2c_subdev(notifier, adapter, address, type) \
+- ((type *)__v4l2_async_notifier_add_i2c_subdev(notifier, adapter, \
+- address, sizeof(type)))
++#define v4l2_async_nf_add_i2c(notifier, adapter, address, type) \
++ ((type *)__v4l2_async_nf_add_i2c(notifier, adapter, address, \
++ sizeof(type)))
+
+ /**
+- * v4l2_async_notifier_register - registers a subdevice asynchronous notifier
++ * v4l2_async_nf_register - registers a subdevice asynchronous notifier
+ *
+ * @v4l2_dev: pointer to &struct v4l2_device
+ * @notifier: pointer to &struct v4l2_async_notifier
+ */
+-int v4l2_async_notifier_register(struct v4l2_device *v4l2_dev,
+- struct v4l2_async_notifier *notifier);
++int v4l2_async_nf_register(struct v4l2_device *v4l2_dev,
++ struct v4l2_async_notifier *notifier);
+
+ /**
+- * v4l2_async_subdev_notifier_register - registers a subdevice asynchronous
++ * v4l2_async_subdev_nf_register - registers a subdevice asynchronous
+ * notifier for a sub-device
+ *
+ * @sd: pointer to &struct v4l2_subdev
+ * @notifier: pointer to &struct v4l2_async_notifier
+ */
+-int v4l2_async_subdev_notifier_register(struct v4l2_subdev *sd,
+- struct v4l2_async_notifier *notifier);
++int v4l2_async_subdev_nf_register(struct v4l2_subdev *sd,
++ struct v4l2_async_notifier *notifier);
+
+ /**
+- * v4l2_async_notifier_unregister - unregisters a subdevice
++ * v4l2_async_nf_unregister - unregisters a subdevice
+ * asynchronous notifier
+ *
+ * @notifier: pointer to &struct v4l2_async_notifier
+ */
+-void v4l2_async_notifier_unregister(struct v4l2_async_notifier *notifier);
++void v4l2_async_nf_unregister(struct v4l2_async_notifier *notifier);
+
+ /**
+- * v4l2_async_notifier_cleanup - clean up notifier resources
++ * v4l2_async_nf_cleanup - clean up notifier resources
+ * @notifier: the notifier the resources of which are to be cleaned up
+ *
+ * Release memory resources related to a notifier, including the async
+ * sub-devices allocated for the purposes of the notifier but not the notifier
+ * itself. The user is responsible for calling this function to clean up the
+ * notifier after calling
+- * v4l2_async_notifier_add_fwnode_remote_subdev(),
+- * v4l2_async_notifier_add_fwnode_subdev(),
+- * v4l2_async_notifier_add_i2c_subdev(),
+- * __v4l2_async_notifier_add_subdev() or
+- * v4l2_async_notifier_parse_fwnode_endpoints().
++ * v4l2_async_nf_add_fwnode_remote(),
++ * v4l2_async_nf_add_fwnode(),
++ * v4l2_async_nf_add_i2c(),
++ * __v4l2_async_nf_add_subdev() or
++ * v4l2_async_nf_parse_fwnode_endpoints().
+ *
+- * There is no harm from calling v4l2_async_notifier_cleanup() in other
++ * There is no harm from calling v4l2_async_nf_cleanup() in other
+ * cases as long as its memory has been zeroed after it has been
+ * allocated.
+ */
+-void v4l2_async_notifier_cleanup(struct v4l2_async_notifier *notifier);
++void v4l2_async_nf_cleanup(struct v4l2_async_notifier *notifier);
+
+ /**
+ * v4l2_async_register_subdev - registers a sub-device to the asynchronous
+@@ -295,7 +292,7 @@ int v4l2_async_register_subdev(struct v4l2_subdev *sd);
+ *
+ * This function is just like v4l2_async_register_subdev() with the exception
+ * that calling it will also parse firmware interfaces for remote references
+- * using v4l2_async_notifier_parse_fwnode_sensor() and registers the
++ * using v4l2_async_nf_parse_fwnode_sensor() and registers the
+ * async sub-devices. The sub-device is similarly unregistered by calling
+ * v4l2_async_unregister_subdev().
+ *
+diff --git a/include/media/v4l2-fwnode.h b/include/media/v4l2-fwnode.h
+index 7ab033b819eb0..9c97f1dbd1c68 100644
+--- a/include/media/v4l2-fwnode.h
++++ b/include/media/v4l2-fwnode.h
+@@ -463,7 +463,7 @@ typedef int (*parse_endpoint_func)(struct device *dev,
+ struct v4l2_async_subdev *asd);
+
+ /**
+- * v4l2_async_notifier_parse_fwnode_endpoints - Parse V4L2 fwnode endpoints in a
++ * v4l2_async_nf_parse_fwnode_endpoints - Parse V4L2 fwnode endpoints in a
+ * device node
+ * @dev: the device the endpoints of which are to be parsed
+ * @notifier: notifier for @dev
+@@ -496,7 +496,7 @@ typedef int (*parse_endpoint_func)(struct device *dev,
+ * to retain that configuration, the user needs to allocate memory for it.
+ *
+ * Any notifier populated using this function must be released with a call to
+- * v4l2_async_notifier_cleanup() after it has been unregistered and the async
++ * v4l2_async_nf_cleanup() after it has been unregistered and the async
+ * sub-devices are no longer in use, even if the function returned an error.
+ *
+ * Return: %0 on success, including when no async sub-devices are found
+@@ -505,10 +505,10 @@ typedef int (*parse_endpoint_func)(struct device *dev,
+ * Other error codes as returned by @parse_endpoint
+ */
+ int
+-v4l2_async_notifier_parse_fwnode_endpoints(struct device *dev,
+- struct v4l2_async_notifier *notifier,
+- size_t asd_struct_size,
+- parse_endpoint_func parse_endpoint);
++v4l2_async_nf_parse_fwnode_endpoints(struct device *dev,
++ struct v4l2_async_notifier *notifier,
++ size_t asd_struct_size,
++ parse_endpoint_func parse_endpoint);
+
+ /* Helper macros to access the connector links. */
+
+--
+2.42.0
+
--- /dev/null
+From ac72e3bee2a0ab408d6920be85269e70b30239de Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 19 Jun 2023 16:12:02 +0800
+Subject: media: vidtv: mux: Add check and kfree for kstrdup
+
+From: Jiasheng Jiang <jiasheng@iscas.ac.cn>
+
+[ Upstream commit 1fd6eb12642e0c32692924ff359c07de4b781d78 ]
+
+Add check for the return value of kstrdup() and return the error
+if it fails in order to avoid NULL pointer dereference.
+Moreover, use kfree() in the later error handling in order to avoid
+memory leak.
+
+Fixes: c2f78f0cb294 ("media: vidtv: psi: add a Network Information Table (NIT)")
+Signed-off-by: Jiasheng Jiang <jiasheng@iscas.ac.cn>
+Signed-off-by: Hans Verkuil <hverkuil-cisco@xs4all.nl>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/media/test-drivers/vidtv/vidtv_mux.c | 7 ++++++-
+ 1 file changed, 6 insertions(+), 1 deletion(-)
+
+diff --git a/drivers/media/test-drivers/vidtv/vidtv_mux.c b/drivers/media/test-drivers/vidtv/vidtv_mux.c
+index b51e6a3b8cbeb..f99878eff7ace 100644
+--- a/drivers/media/test-drivers/vidtv/vidtv_mux.c
++++ b/drivers/media/test-drivers/vidtv/vidtv_mux.c
+@@ -504,13 +504,16 @@ struct vidtv_mux *vidtv_mux_init(struct dvb_frontend *fe,
+ m->priv = args->priv;
+ m->network_id = args->network_id;
+ m->network_name = kstrdup(args->network_name, GFP_KERNEL);
++ if (!m->network_name)
++ goto free_mux_buf;
++
+ m->timing.current_jiffies = get_jiffies_64();
+
+ if (args->channels)
+ m->channels = args->channels;
+ else
+ if (vidtv_channels_init(m) < 0)
+- goto free_mux_buf;
++ goto free_mux_network_name;
+
+ /* will alloc data for pmt_sections after initializing pat */
+ if (vidtv_channel_si_init(m) < 0)
+@@ -527,6 +530,8 @@ struct vidtv_mux *vidtv_mux_init(struct dvb_frontend *fe,
+ vidtv_channel_si_destroy(m);
+ free_channels:
+ vidtv_channels_destroy(m);
++free_mux_network_name:
++ kfree(m->network_name);
+ free_mux_buf:
+ vfree(m->mux_buf);
+ free_mux:
+--
+2.42.0
+
--- /dev/null
+From c87b962ba806c7ccfb1dff3fcc072ef0a9e80b10 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 19 Jun 2023 16:12:01 +0800
+Subject: media: vidtv: psi: Add check for kstrdup
+
+From: Jiasheng Jiang <jiasheng@iscas.ac.cn>
+
+[ Upstream commit 76a2c5df6ca8bd8ada45e953b8c72b746f42918d ]
+
+Add check for the return value of kstrdup() and return the error
+if it fails in order to avoid NULL pointer dereference.
+
+Fixes: 7a7899f6f58e ("media: vidtv: psi: Implement an Event Information Table (EIT)")
+Fixes: c2f78f0cb294 ("media: vidtv: psi: add a Network Information Table (NIT)")
+Fixes: f90cf6079bf6 ("media: vidtv: add a bridge driver")
+Signed-off-by: Jiasheng Jiang <jiasheng@iscas.ac.cn>
+Signed-off-by: Hans Verkuil <hverkuil-cisco@xs4all.nl>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/media/test-drivers/vidtv/vidtv_psi.c | 45 +++++++++++++++++---
+ 1 file changed, 40 insertions(+), 5 deletions(-)
+
+diff --git a/drivers/media/test-drivers/vidtv/vidtv_psi.c b/drivers/media/test-drivers/vidtv/vidtv_psi.c
+index c11ac8dca73df..988324587c4ed 100644
+--- a/drivers/media/test-drivers/vidtv/vidtv_psi.c
++++ b/drivers/media/test-drivers/vidtv/vidtv_psi.c
+@@ -307,16 +307,29 @@ struct vidtv_psi_desc_service *vidtv_psi_service_desc_init(struct vidtv_psi_desc
+
+ desc->service_name_len = service_name_len;
+
+- if (service_name && service_name_len)
++ if (service_name && service_name_len) {
+ desc->service_name = kstrdup(service_name, GFP_KERNEL);
++ if (!desc->service_name)
++ goto free_desc;
++ }
+
+ desc->provider_name_len = provider_name_len;
+
+- if (provider_name && provider_name_len)
++ if (provider_name && provider_name_len) {
+ desc->provider_name = kstrdup(provider_name, GFP_KERNEL);
++ if (!desc->provider_name)
++ goto free_desc_service_name;
++ }
+
+ vidtv_psi_desc_chain(head, (struct vidtv_psi_desc *)desc);
+ return desc;
++
++free_desc_service_name:
++ if (service_name && service_name_len)
++ kfree(desc->service_name);
++free_desc:
++ kfree(desc);
++ return NULL;
+ }
+
+ struct vidtv_psi_desc_registration
+@@ -361,8 +374,13 @@ struct vidtv_psi_desc_network_name
+
+ desc->length = network_name_len;
+
+- if (network_name && network_name_len)
++ if (network_name && network_name_len) {
+ desc->network_name = kstrdup(network_name, GFP_KERNEL);
++ if (!desc->network_name) {
++ kfree(desc);
++ return NULL;
++ }
++ }
+
+ vidtv_psi_desc_chain(head, (struct vidtv_psi_desc *)desc);
+ return desc;
+@@ -448,15 +466,32 @@ struct vidtv_psi_desc_short_event
+ iso_language_code = "eng";
+
+ desc->iso_language_code = kstrdup(iso_language_code, GFP_KERNEL);
++ if (!desc->iso_language_code)
++ goto free_desc;
+
+- if (event_name && event_name_len)
++ if (event_name && event_name_len) {
+ desc->event_name = kstrdup(event_name, GFP_KERNEL);
++ if (!desc->event_name)
++ goto free_desc_language_code;
++ }
+
+- if (text && text_len)
++ if (text && text_len) {
+ desc->text = kstrdup(text, GFP_KERNEL);
++ if (!desc->text)
++ goto free_desc_event_name;
++ }
+
+ vidtv_psi_desc_chain(head, (struct vidtv_psi_desc *)desc);
+ return desc;
++
++free_desc_event_name:
++ if (event_name && event_name_len)
++ kfree(desc->event_name);
++free_desc_language_code:
++ kfree(desc->iso_language_code);
++free_desc:
++ kfree(desc);
++ return NULL;
+ }
+
+ struct vidtv_psi_desc *vidtv_psi_desc_clone(struct vidtv_psi_desc *desc)
+--
+2.42.0
+
--- /dev/null
+From 27e0903b660081f285211c9ae8bb3263d5d1d2c9 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sat, 14 Oct 2023 22:54:14 +0200
+Subject: mfd: arizona-spi: Set pdata.hpdet_channel for ACPI enumerated devs
+
+From: Hans de Goede <hdegoede@redhat.com>
+
+[ Upstream commit 831d1af85133e1763d41e20414912d9a1058ea72 ]
+
+Commit 9e86b2ad4c11 changed the channel used for HPDET detection
+(headphones vs lineout detection) from being hardcoded to
+ARIZONA_ACCDET_MODE_HPL (HP left channel) to it being configurable
+through arizona_pdata.hpdet_channel the DT/OF parsing added for
+filling arizona_pdata on devicetree platforms ensures that
+arizona_pdata.hpdet_channel gets set to ARIZONA_ACCDET_MODE_HPL
+when not specified in the devicetree-node.
+
+But on ACPI platforms where arizona_pdata is filled by
+arizona_spi_acpi_probe() arizona_pdata.hpdet_channel was not
+getting set, causing it to default to 0 aka ARIZONA_ACCDET_MODE_MIC.
+
+This causes headphones to get misdetected as line-out on some models.
+Fix this by setting hpdet_channel = ARIZONA_ACCDET_MODE_HPL.
+
+Fixes: e933836744a2 ("mfd: arizona: Add support for ACPI enumeration of WM5102 connected over SPI")
+Signed-off-by: Hans de Goede <hdegoede@redhat.com>
+Link: https://lore.kernel.org/r/20231014205414.59415-1-hdegoede@redhat.com
+Signed-off-by: Lee Jones <lee@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/mfd/arizona-spi.c | 3 +++
+ 1 file changed, 3 insertions(+)
+
+diff --git a/drivers/mfd/arizona-spi.c b/drivers/mfd/arizona-spi.c
+index aa1d6f94ae532..8d826b58732dc 100644
+--- a/drivers/mfd/arizona-spi.c
++++ b/drivers/mfd/arizona-spi.c
+@@ -118,6 +118,9 @@ static int arizona_spi_acpi_probe(struct arizona *arizona)
+ arizona->pdata.micd_ranges = arizona_micd_aosp_ranges;
+ arizona->pdata.num_micd_ranges = ARRAY_SIZE(arizona_micd_aosp_ranges);
+
++ /* Use left headphone speaker for HP vs line-out detection */
++ arizona->pdata.hpdet_channel = ARIZONA_ACCDET_MODE_HPL;
++
+ return 0;
+ }
+
+--
+2.42.0
+
--- /dev/null
+From 30b1659c73f46697ed9a223329120b52371a0ba0 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 18 Aug 2023 18:39:17 +0200
+Subject: mfd: core: Ensure disabled devices are skipped without aborting
+
+From: Herve Codina <herve.codina@bootlin.com>
+
+[ Upstream commit 7ba7bdef4d14e3722e2842da3b48cbadb73e52d6 ]
+
+The loop searching for a matching device based on its compatible
+string is aborted when a matching disabled device is found.
+This abort prevents to add devices as soon as one disabled device
+is found.
+
+Continue searching for an other device instead of aborting on the
+first disabled one fixes the issue.
+
+Fixes: 22380b65dc70 ("mfd: mfd-core: Ensure disabled devices are ignored without error")
+Signed-off-by: Herve Codina <herve.codina@bootlin.com>
+Reviewed-by: Christophe Leroy <christophe.leroy@csgroup.eu>
+Signed-off-by: Christophe Leroy <christophe.leroy@csgroup.eu>
+Link: https://lore.kernel.org/r/528425d6472176bb1d02d79596b51f8c28a551cc.1692376361.git.christophe.leroy@csgroup.eu
+Signed-off-by: Lee Jones <lee@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/mfd/mfd-core.c | 17 ++++++++++++-----
+ 1 file changed, 12 insertions(+), 5 deletions(-)
+
+diff --git a/drivers/mfd/mfd-core.c b/drivers/mfd/mfd-core.c
+index 684a011a63968..53ea3fab66a46 100644
+--- a/drivers/mfd/mfd-core.c
++++ b/drivers/mfd/mfd-core.c
+@@ -159,6 +159,7 @@ static int mfd_add_device(struct device *parent, int id,
+ struct platform_device *pdev;
+ struct device_node *np = NULL;
+ struct mfd_of_node_entry *of_entry, *tmp;
++ bool disabled = false;
+ int ret = -ENOMEM;
+ int platform_id;
+ int r;
+@@ -196,11 +197,10 @@ static int mfd_add_device(struct device *parent, int id,
+ if (IS_ENABLED(CONFIG_OF) && parent->of_node && cell->of_compatible) {
+ for_each_child_of_node(parent->of_node, np) {
+ if (of_device_is_compatible(np, cell->of_compatible)) {
+- /* Ignore 'disabled' devices error free */
++ /* Skip 'disabled' devices */
+ if (!of_device_is_available(np)) {
+- of_node_put(np);
+- ret = 0;
+- goto fail_alias;
++ disabled = true;
++ continue;
+ }
+
+ ret = mfd_match_of_node_to_dev(pdev, np, cell);
+@@ -210,10 +210,17 @@ static int mfd_add_device(struct device *parent, int id,
+ if (ret)
+ goto fail_alias;
+
+- break;
++ goto match;
+ }
+ }
+
++ if (disabled) {
++ /* Ignore 'disabled' devices error free */
++ ret = 0;
++ goto fail_alias;
++ }
++
++match:
+ if (!pdev->dev.of_node)
+ pr_warn("%s: Failed to locate of_node [id: %d]\n",
+ cell->name, platform_id);
+--
+2.42.0
+
--- /dev/null
+From 3823c590ee7fe24654d4847acb932eecd16d7b54 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 28 Aug 2023 22:16:11 +0200
+Subject: mfd: core: Un-constify mfd_cell.of_reg
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Michał Mirosław <mirq-linux@rere.qmqm.pl>
+
+[ Upstream commit 3c70342f1f0045dc827bb2f02d814ce31e0e0d05 ]
+
+Enable dynamically filling in the whole mfd_cell structure. All other
+fields already allow that.
+
+Fixes: 466a62d7642f ("mfd: core: Make a best effort attempt to match devices with the correct of_nodes")
+Signed-off-by: Michał Mirosław <mirq-linux@rere.qmqm.pl>
+Link: https://lore.kernel.org/r/b73fe4bc4bd6ba1af90940a640ed65fe254c0408.1693253717.git.mirq-linux@rere.qmqm.pl
+Signed-off-by: Lee Jones <lee@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ include/linux/mfd/core.h | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/include/linux/mfd/core.h b/include/linux/mfd/core.h
+index 0bc7cba798a34..b449765b5cac1 100644
+--- a/include/linux/mfd/core.h
++++ b/include/linux/mfd/core.h
+@@ -92,7 +92,7 @@ struct mfd_cell {
+ * (above) when matching OF nodes with devices that have identical
+ * compatible strings
+ */
+- const u64 of_reg;
++ u64 of_reg;
+
+ /* Set to 'true' to use 'of_reg' (above) - allows for of_reg=0 */
+ bool use_of_reg;
+--
+2.42.0
+
--- /dev/null
+From c148b085e07062ac10c46ccfb5b75604a2ad4a93 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 25 Sep 2023 10:41:33 +0800
+Subject: mfd: dln2: Fix double put in dln2_probe
+
+From: Dinghao Liu <dinghao.liu@zju.edu.cn>
+
+[ Upstream commit 759c409bc5fc496cbc22cd0b392d3cbb0c0e23eb ]
+
+The dln2_free() already contains usb_put_dev(). Therefore,
+the redundant usb_put_dev() before dln2_free() may lead to
+a double free.
+
+Fixes: 96da8f148396 ("mfd: dln2: Fix memory leak in dln2_probe()")
+Signed-off-by: Dinghao Liu <dinghao.liu@zju.edu.cn>
+Link: https://lore.kernel.org/r/20230925024134.9683-1-dinghao.liu@zju.edu.cn
+Signed-off-by: Lee Jones <lee@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/mfd/dln2.c | 1 -
+ 1 file changed, 1 deletion(-)
+
+diff --git a/drivers/mfd/dln2.c b/drivers/mfd/dln2.c
+index fc65f9e25fda8..852129ea07666 100644
+--- a/drivers/mfd/dln2.c
++++ b/drivers/mfd/dln2.c
+@@ -836,7 +836,6 @@ static int dln2_probe(struct usb_interface *interface,
+ dln2_stop_rx_urbs(dln2);
+
+ out_free:
+- usb_put_dev(dln2->usb_dev);
+ dln2_free(dln2);
+
+ return ret;
+--
+2.42.0
+
--- /dev/null
+From 84fae41037c49a5c56fd72682f397b1779fc2158 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 23 Aug 2023 11:50:20 +0800
+Subject: misc: st_core: Do not call kfree_skb() under spin_lock_irqsave()
+
+From: Jinjie Ruan <ruanjinjie@huawei.com>
+
+[ Upstream commit 4d08c3d12b61022501989f9f071514d2d6f77c47 ]
+
+It is not allowed to call kfree_skb() from hardware interrupt
+context or with hardware interrupts being disabled.
+So replace kfree_skb() with dev_kfree_skb_irq() under
+spin_lock_irqsave(). Compile tested only.
+
+Fixes: 53618cc1e51e ("Staging: sources for ST core")
+Signed-off-by: Jinjie Ruan <ruanjinjie@huawei.com>
+Link: https://lore.kernel.org/r/20230823035020.1281892-1-ruanjinjie@huawei.com
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/misc/ti-st/st_core.c | 7 ++++---
+ 1 file changed, 4 insertions(+), 3 deletions(-)
+
+diff --git a/drivers/misc/ti-st/st_core.c b/drivers/misc/ti-st/st_core.c
+index 7f6976a9f508b..48e0f8377e659 100644
+--- a/drivers/misc/ti-st/st_core.c
++++ b/drivers/misc/ti-st/st_core.c
+@@ -15,6 +15,7 @@
+ #include <linux/skbuff.h>
+
+ #include <linux/ti_wilink_st.h>
++#include <linux/netdevice.h>
+
+ extern void st_kim_recv(void *, const unsigned char *, long);
+ void st_int_recv(void *, const unsigned char *, long);
+@@ -435,7 +436,7 @@ static void st_int_enqueue(struct st_data_s *st_gdata, struct sk_buff *skb)
+ case ST_LL_AWAKE_TO_ASLEEP:
+ pr_err("ST LL is illegal state(%ld),"
+ "purging received skb.", st_ll_getstate(st_gdata));
+- kfree_skb(skb);
++ dev_kfree_skb_irq(skb);
+ break;
+ case ST_LL_ASLEEP:
+ skb_queue_tail(&st_gdata->tx_waitq, skb);
+@@ -444,7 +445,7 @@ static void st_int_enqueue(struct st_data_s *st_gdata, struct sk_buff *skb)
+ default:
+ pr_err("ST LL is illegal state(%ld),"
+ "purging received skb.", st_ll_getstate(st_gdata));
+- kfree_skb(skb);
++ dev_kfree_skb_irq(skb);
+ break;
+ }
+
+@@ -498,7 +499,7 @@ void st_tx_wakeup(struct st_data_s *st_data)
+ spin_unlock_irqrestore(&st_data->lock, flags);
+ break;
+ }
+- kfree_skb(skb);
++ dev_kfree_skb_irq(skb);
+ spin_unlock_irqrestore(&st_data->lock, flags);
+ }
+ /* if wake-up is set in another context- restart sending */
+--
+2.42.0
+
--- /dev/null
+From 6f6564f53844662b1fcd6011e3669a2b62b1399f Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 15 Sep 2023 13:01:23 -0600
+Subject: mlxsw: Use size_mul() in call to struct_size()
+
+From: Gustavo A. R. Silva <gustavoars@kernel.org>
+
+[ Upstream commit e22c6ea025013ae447fe269269753ffec763dde5 ]
+
+If, for any reason, the open-coded arithmetic causes a wraparound, the
+protection that `struct_size()` adds against potential integer overflows
+is defeated. Fix this by hardening call to `struct_size()` with `size_mul()`.
+
+Fixes: 2285ec872d9d ("mlxsw: spectrum_acl_bloom_filter: use struct_size() in kzalloc()")
+Signed-off-by: Gustavo A. R. Silva <gustavoars@kernel.org>
+Reviewed-by: Kees Cook <keescook@chromium.org>
+Reviewed-by: Ido Schimmel <idosch@nvidia.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_bloom_filter.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_bloom_filter.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_bloom_filter.c
+index dbd3bebf11eca..2e8b17e3b9358 100644
+--- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_bloom_filter.c
++++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_bloom_filter.c
+@@ -251,7 +251,7 @@ mlxsw_sp_acl_bf_init(struct mlxsw_sp *mlxsw_sp, unsigned int num_erp_banks)
+ * is 2^ACL_MAX_BF_LOG
+ */
+ bf_bank_size = 1 << MLXSW_CORE_RES_GET(mlxsw_sp->core, ACL_MAX_BF_LOG);
+- bf = kzalloc(struct_size(bf, refcnt, bf_bank_size * num_erp_banks),
++ bf = kzalloc(struct_size(bf, refcnt, size_mul(bf_bank_size, num_erp_banks)),
+ GFP_KERNEL);
+ if (!bf)
+ return ERR_PTR(-ENOMEM);
+--
+2.42.0
+
--- /dev/null
+From f52c3bfbcbaaaa7d56960215ebc75cafdc1da9da Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sun, 8 Oct 2023 02:04:44 +0900
+Subject: modpost: fix tee MODULE_DEVICE_TABLE built on big-endian host
+
+From: Masahiro Yamada <masahiroy@kernel.org>
+
+[ Upstream commit 7f54e00e5842663c2cea501bbbdfa572c94348a3 ]
+
+When MODULE_DEVICE_TABLE(tee, ) is built on a host with a different
+endianness from the target architecture, it results in an incorrect
+MODULE_ALIAS().
+
+For example, see a case where drivers/char/hw_random/optee-rng.c
+is built as a module for ARM little-endian.
+
+If you build it on a little-endian host, you will get the correct
+MODULE_ALIAS:
+
+ $ grep MODULE_ALIAS drivers/char/hw_random/optee-rng.mod.c
+ MODULE_ALIAS("tee:ab7a617c-b8e7-4d8f-8301-d09b61036b64*");
+
+However, if you build it on a big-endian host, you will get a wrong
+MODULE_ALIAS:
+
+ $ grep MODULE_ALIAS drivers/char/hw_random/optee-rng.mod.c
+ MODULE_ALIAS("tee:646b0361-9bd0-0183-8f4d-e7b87c617aab*");
+
+The same problem also occurs when you enable CONFIG_CPU_BIG_ENDIAN,
+and build it on a little-endian host.
+
+This issue has been unnoticed because the ARM kernel is configured for
+little-endian by default, and most likely built on a little-endian host
+(cross-build on x86 or native-build on ARM).
+
+The uuid field must not be reversed because uuid_t is an array of __u8.
+
+Fixes: 0fc1db9d1059 ("tee: add bus driver framework for TEE based devices")
+Signed-off-by: Masahiro Yamada <masahiroy@kernel.org>
+Reviewed-by: Sumit Garg <sumit.garg@linaro.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ scripts/mod/file2alias.c | 10 +++++-----
+ 1 file changed, 5 insertions(+), 5 deletions(-)
+
+diff --git a/scripts/mod/file2alias.c b/scripts/mod/file2alias.c
+index 05089ef5cc0ec..23e7102abe0cd 100644
+--- a/scripts/mod/file2alias.c
++++ b/scripts/mod/file2alias.c
+@@ -1339,13 +1339,13 @@ static int do_typec_entry(const char *filename, void *symval, char *alias)
+ /* Looks like: tee:uuid */
+ static int do_tee_entry(const char *filename, void *symval, char *alias)
+ {
+- DEF_FIELD(symval, tee_client_device_id, uuid);
++ DEF_FIELD_ADDR(symval, tee_client_device_id, uuid);
+
+ sprintf(alias, "tee:%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x",
+- uuid.b[0], uuid.b[1], uuid.b[2], uuid.b[3], uuid.b[4],
+- uuid.b[5], uuid.b[6], uuid.b[7], uuid.b[8], uuid.b[9],
+- uuid.b[10], uuid.b[11], uuid.b[12], uuid.b[13], uuid.b[14],
+- uuid.b[15]);
++ uuid->b[0], uuid->b[1], uuid->b[2], uuid->b[3], uuid->b[4],
++ uuid->b[5], uuid->b[6], uuid->b[7], uuid->b[8], uuid->b[9],
++ uuid->b[10], uuid->b[11], uuid->b[12], uuid->b[13], uuid->b[14],
++ uuid->b[15]);
+
+ add_wildcard(alias);
+ return 1;
+--
+2.42.0
+
--- /dev/null
+From 8cca2b28f42b2fb0317d172f3a7bcd7568555193 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 6 Jan 2022 13:22:28 +0100
+Subject: mt76: add support for overriding the device used for DMA mapping
+
+From: Felix Fietkau <nbd@nbd.name>
+
+[ Upstream commit d1ddc536df93ae406ef671deb3218898d3515ea4 ]
+
+WED support requires using non-coherent DMA, whereas the PCI device might
+be configured for coherent DMA.
+The WED driver will take care of changing the PCI HIF coherent IO setting
+on attach.
+
+Signed-off-by: Felix Fietkau <nbd@nbd.name>
+Stable-dep-of: 317620593349 ("wifi: mt76: mt7603: improve stuck beacon handling")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/wireless/mediatek/mt76/dma.c | 34 +++++++++----------
+ drivers/net/wireless/mediatek/mt76/mac80211.c | 1 +
+ drivers/net/wireless/mediatek/mt76/mt76.h | 1 +
+ 3 files changed, 19 insertions(+), 17 deletions(-)
+
+diff --git a/drivers/net/wireless/mediatek/mt76/dma.c b/drivers/net/wireless/mediatek/mt76/dma.c
+index 1344c88729a84..71a04c92117a6 100644
+--- a/drivers/net/wireless/mediatek/mt76/dma.c
++++ b/drivers/net/wireless/mediatek/mt76/dma.c
+@@ -20,7 +20,7 @@ mt76_alloc_txwi(struct mt76_dev *dev)
+ if (!txwi)
+ return NULL;
+
+- addr = dma_map_single(dev->dev, txwi, dev->drv->txwi_size,
++ addr = dma_map_single(dev->dma_dev, txwi, dev->drv->txwi_size,
+ DMA_TO_DEVICE);
+ t = (struct mt76_txwi_cache *)(txwi + dev->drv->txwi_size);
+ t->dma_addr = addr;
+@@ -74,7 +74,7 @@ mt76_free_pending_txwi(struct mt76_dev *dev)
+
+ local_bh_disable();
+ while ((t = __mt76_get_txwi(dev)) != NULL) {
+- dma_unmap_single(dev->dev, t->dma_addr, dev->drv->txwi_size,
++ dma_unmap_single(dev->dma_dev, t->dma_addr, dev->drv->txwi_size,
+ DMA_TO_DEVICE);
+ kfree(mt76_get_txwi_ptr(dev, t));
+ }
+@@ -123,7 +123,7 @@ mt76_dma_alloc_queue(struct mt76_dev *dev, struct mt76_queue *q,
+ q->hw_idx = idx;
+
+ size = q->ndesc * sizeof(struct mt76_desc);
+- q->desc = dmam_alloc_coherent(dev->dev, size, &q->desc_dma, GFP_KERNEL);
++ q->desc = dmam_alloc_coherent(dev->dma_dev, size, &q->desc_dma, GFP_KERNEL);
+ if (!q->desc)
+ return -ENOMEM;
+
+@@ -205,11 +205,11 @@ mt76_dma_tx_cleanup_idx(struct mt76_dev *dev, struct mt76_queue *q, int idx,
+ struct mt76_queue_entry *e = &q->entry[idx];
+
+ if (!e->skip_buf0)
+- dma_unmap_single(dev->dev, e->dma_addr[0], e->dma_len[0],
++ dma_unmap_single(dev->dma_dev, e->dma_addr[0], e->dma_len[0],
+ DMA_TO_DEVICE);
+
+ if (!e->skip_buf1)
+- dma_unmap_single(dev->dev, e->dma_addr[1], e->dma_len[1],
++ dma_unmap_single(dev->dma_dev, e->dma_addr[1], e->dma_len[1],
+ DMA_TO_DEVICE);
+
+ if (e->txwi == DMA_DUMMY_DATA)
+@@ -290,7 +290,7 @@ mt76_dma_get_buf(struct mt76_dev *dev, struct mt76_queue *q, int idx,
+ if (info)
+ *info = le32_to_cpu(desc->info);
+
+- dma_unmap_single(dev->dev, buf_addr, buf_len, DMA_FROM_DEVICE);
++ dma_unmap_single(dev->dma_dev, buf_addr, buf_len, DMA_FROM_DEVICE);
+ e->buf = NULL;
+
+ return buf;
+@@ -327,9 +327,9 @@ mt76_dma_tx_queue_skb_raw(struct mt76_dev *dev, struct mt76_queue *q,
+ if (q->queued + 1 >= q->ndesc - 1)
+ goto error;
+
+- addr = dma_map_single(dev->dev, skb->data, skb->len,
++ addr = dma_map_single(dev->dma_dev, skb->data, skb->len,
+ DMA_TO_DEVICE);
+- if (unlikely(dma_mapping_error(dev->dev, addr)))
++ if (unlikely(dma_mapping_error(dev->dma_dev, addr)))
+ goto error;
+
+ buf.addr = addr;
+@@ -376,8 +376,8 @@ mt76_dma_tx_queue_skb(struct mt76_dev *dev, struct mt76_queue *q,
+ mt76_insert_hdr_pad(skb);
+
+ len = skb_headlen(skb);
+- addr = dma_map_single(dev->dev, skb->data, len, DMA_TO_DEVICE);
+- if (unlikely(dma_mapping_error(dev->dev, addr)))
++ addr = dma_map_single(dev->dma_dev, skb->data, len, DMA_TO_DEVICE);
++ if (unlikely(dma_mapping_error(dev->dma_dev, addr)))
+ goto free;
+
+ tx_info.buf[n].addr = t->dma_addr;
+@@ -389,9 +389,9 @@ mt76_dma_tx_queue_skb(struct mt76_dev *dev, struct mt76_queue *q,
+ if (n == ARRAY_SIZE(tx_info.buf))
+ goto unmap;
+
+- addr = dma_map_single(dev->dev, iter->data, iter->len,
++ addr = dma_map_single(dev->dma_dev, iter->data, iter->len,
+ DMA_TO_DEVICE);
+- if (unlikely(dma_mapping_error(dev->dev, addr)))
++ if (unlikely(dma_mapping_error(dev->dma_dev, addr)))
+ goto unmap;
+
+ tx_info.buf[n].addr = addr;
+@@ -404,10 +404,10 @@ mt76_dma_tx_queue_skb(struct mt76_dev *dev, struct mt76_queue *q,
+ goto unmap;
+ }
+
+- dma_sync_single_for_cpu(dev->dev, t->dma_addr, dev->drv->txwi_size,
++ dma_sync_single_for_cpu(dev->dma_dev, t->dma_addr, dev->drv->txwi_size,
+ DMA_TO_DEVICE);
+ ret = dev->drv->tx_prepare_skb(dev, txwi, q->qid, wcid, sta, &tx_info);
+- dma_sync_single_for_device(dev->dev, t->dma_addr, dev->drv->txwi_size,
++ dma_sync_single_for_device(dev->dma_dev, t->dma_addr, dev->drv->txwi_size,
+ DMA_TO_DEVICE);
+ if (ret < 0)
+ goto unmap;
+@@ -417,7 +417,7 @@ mt76_dma_tx_queue_skb(struct mt76_dev *dev, struct mt76_queue *q,
+
+ unmap:
+ for (n--; n > 0; n--)
+- dma_unmap_single(dev->dev, tx_info.buf[n].addr,
++ dma_unmap_single(dev->dma_dev, tx_info.buf[n].addr,
+ tx_info.buf[n].len, DMA_TO_DEVICE);
+
+ free:
+@@ -461,8 +461,8 @@ mt76_dma_rx_fill(struct mt76_dev *dev, struct mt76_queue *q)
+ if (!buf)
+ break;
+
+- addr = dma_map_single(dev->dev, buf, len, DMA_FROM_DEVICE);
+- if (unlikely(dma_mapping_error(dev->dev, addr))) {
++ addr = dma_map_single(dev->dma_dev, buf, len, DMA_FROM_DEVICE);
++ if (unlikely(dma_mapping_error(dev->dma_dev, addr))) {
+ skb_free_frag(buf);
+ break;
+ }
+diff --git a/drivers/net/wireless/mediatek/mt76/mac80211.c b/drivers/net/wireless/mediatek/mt76/mac80211.c
+index 028519a739fd1..3c7d5abe9cc2a 100644
+--- a/drivers/net/wireless/mediatek/mt76/mac80211.c
++++ b/drivers/net/wireless/mediatek/mt76/mac80211.c
+@@ -428,6 +428,7 @@ mt76_alloc_device(struct device *pdev, unsigned int size,
+ dev->hw = hw;
+ dev->dev = pdev;
+ dev->drv = drv_ops;
++ dev->dma_dev = pdev;
+
+ phy = &dev->phy;
+ phy->dev = dev;
+diff --git a/drivers/net/wireless/mediatek/mt76/mt76.h b/drivers/net/wireless/mediatek/mt76/mt76.h
+index eb1fb955b7777..87ae528581bbf 100644
+--- a/drivers/net/wireless/mediatek/mt76/mt76.h
++++ b/drivers/net/wireless/mediatek/mt76/mt76.h
+@@ -660,6 +660,7 @@ struct mt76_dev {
+ const struct mt76_driver_ops *drv;
+ const struct mt76_mcu_ops *mcu_ops;
+ struct device *dev;
++ struct device *dma_dev;
+
+ struct mt76_mcu mcu;
+
+--
+2.42.0
+
--- /dev/null
+From 14935965b05e31f7016304cf4c0cf3f081eef7ce Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sat, 19 Mar 2022 21:56:20 +0100
+Subject: mt76: dma: use kzalloc instead of devm_kzalloc for txwi
+
+From: Felix Fietkau <nbd@nbd.name>
+
+[ Upstream commit 402e01092e79583923579662f244bc538f466f36 ]
+
+dma unmap is already needed for cleanup anyway, so we don't need the extra
+tracking and can save a bit of memory here
+
+Signed-off-by: Felix Fietkau <nbd@nbd.name>
+Stable-dep-of: 317620593349 ("wifi: mt76: mt7603: improve stuck beacon handling")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/wireless/mediatek/mt76/dma.c | 6 ++++--
+ 1 file changed, 4 insertions(+), 2 deletions(-)
+
+diff --git a/drivers/net/wireless/mediatek/mt76/dma.c b/drivers/net/wireless/mediatek/mt76/dma.c
+index 69e0e68757f53..1344c88729a84 100644
+--- a/drivers/net/wireless/mediatek/mt76/dma.c
++++ b/drivers/net/wireless/mediatek/mt76/dma.c
+@@ -16,7 +16,7 @@ mt76_alloc_txwi(struct mt76_dev *dev)
+ int size;
+
+ size = L1_CACHE_ALIGN(dev->drv->txwi_size + sizeof(*t));
+- txwi = devm_kzalloc(dev->dev, size, GFP_ATOMIC);
++ txwi = kzalloc(size, GFP_ATOMIC);
+ if (!txwi)
+ return NULL;
+
+@@ -73,9 +73,11 @@ mt76_free_pending_txwi(struct mt76_dev *dev)
+ struct mt76_txwi_cache *t;
+
+ local_bh_disable();
+- while ((t = __mt76_get_txwi(dev)) != NULL)
++ while ((t = __mt76_get_txwi(dev)) != NULL) {
+ dma_unmap_single(dev->dev, t->dma_addr, dev->drv->txwi_size,
+ DMA_TO_DEVICE);
++ kfree(mt76_get_txwi_ptr(dev, t));
++ }
+ local_bh_enable();
+ }
+
+--
+2.42.0
+
--- /dev/null
+From e8400b54904e13be73dc574a8a89d7ba3ef46af6 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sun, 3 Jul 2022 17:52:24 +0200
+Subject: mt76: pass original queue id from __mt76_tx_queue_skb to the driver
+
+From: Felix Fietkau <nbd@nbd.name>
+
+[ Upstream commit d08295f5be8e63e64f9e664572f1b582ede7958b ]
+
+MT7615 and newer map multiple software tx queues to the hardware id
+
+Signed-off-by: Felix Fietkau <nbd@nbd.name>
+Stable-dep-of: 317620593349 ("wifi: mt76: mt7603: improve stuck beacon handling")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/wireless/mediatek/mt76/dma.c | 6 +++---
+ drivers/net/wireless/mediatek/mt76/mt76.h | 4 ++--
+ drivers/net/wireless/mediatek/mt76/mt7603/beacon.c | 6 +++---
+ drivers/net/wireless/mediatek/mt76/mt76x02_mmio.c | 3 ++-
+ drivers/net/wireless/mediatek/mt76/sdio.c | 6 +++---
+ drivers/net/wireless/mediatek/mt76/testmode.c | 4 ++--
+ drivers/net/wireless/mediatek/mt76/tx.c | 2 +-
+ drivers/net/wireless/mediatek/mt76/usb.c | 6 +++---
+ 8 files changed, 19 insertions(+), 18 deletions(-)
+
+diff --git a/drivers/net/wireless/mediatek/mt76/dma.c b/drivers/net/wireless/mediatek/mt76/dma.c
+index 71a04c92117a6..f225a34e21861 100644
+--- a/drivers/net/wireless/mediatek/mt76/dma.c
++++ b/drivers/net/wireless/mediatek/mt76/dma.c
+@@ -349,8 +349,8 @@ mt76_dma_tx_queue_skb_raw(struct mt76_dev *dev, struct mt76_queue *q,
+
+ static int
+ mt76_dma_tx_queue_skb(struct mt76_dev *dev, struct mt76_queue *q,
+- struct sk_buff *skb, struct mt76_wcid *wcid,
+- struct ieee80211_sta *sta)
++ enum mt76_txq_id qid, struct sk_buff *skb,
++ struct mt76_wcid *wcid, struct ieee80211_sta *sta)
+ {
+ struct ieee80211_tx_status status = {
+ .sta = sta,
+@@ -406,7 +406,7 @@ mt76_dma_tx_queue_skb(struct mt76_dev *dev, struct mt76_queue *q,
+
+ dma_sync_single_for_cpu(dev->dma_dev, t->dma_addr, dev->drv->txwi_size,
+ DMA_TO_DEVICE);
+- ret = dev->drv->tx_prepare_skb(dev, txwi, q->qid, wcid, sta, &tx_info);
++ ret = dev->drv->tx_prepare_skb(dev, txwi, qid, wcid, sta, &tx_info);
+ dma_sync_single_for_device(dev->dma_dev, t->dma_addr, dev->drv->txwi_size,
+ DMA_TO_DEVICE);
+ if (ret < 0)
+diff --git a/drivers/net/wireless/mediatek/mt76/mt76.h b/drivers/net/wireless/mediatek/mt76/mt76.h
+index 87ae528581bbf..27f04fb2796d7 100644
+--- a/drivers/net/wireless/mediatek/mt76/mt76.h
++++ b/drivers/net/wireless/mediatek/mt76/mt76.h
+@@ -195,8 +195,8 @@ struct mt76_queue_ops {
+ u32 ring_base);
+
+ int (*tx_queue_skb)(struct mt76_dev *dev, struct mt76_queue *q,
+- struct sk_buff *skb, struct mt76_wcid *wcid,
+- struct ieee80211_sta *sta);
++ enum mt76_txq_id qid, struct sk_buff *skb,
++ struct mt76_wcid *wcid, struct ieee80211_sta *sta);
+
+ int (*tx_queue_skb_raw)(struct mt76_dev *dev, struct mt76_queue *q,
+ struct sk_buff *skb, u32 tx_info);
+diff --git a/drivers/net/wireless/mediatek/mt76/mt7603/beacon.c b/drivers/net/wireless/mediatek/mt76/mt7603/beacon.c
+index 5d4522f440b74..e35e0a68c6e48 100644
+--- a/drivers/net/wireless/mediatek/mt76/mt7603/beacon.c
++++ b/drivers/net/wireless/mediatek/mt76/mt7603/beacon.c
+@@ -24,8 +24,8 @@ mt7603_update_beacon_iter(void *priv, u8 *mac, struct ieee80211_vif *vif)
+ if (!skb)
+ return;
+
+- mt76_tx_queue_skb(dev, dev->mphy.q_tx[MT_TXQ_BEACON], skb,
+- &mvif->sta.wcid, NULL);
++ mt76_tx_queue_skb(dev, dev->mphy.q_tx[MT_TXQ_BEACON],
++ MT_TXQ_BEACON, skb, &mvif->sta.wcid, NULL);
+
+ spin_lock_bh(&dev->ps_lock);
+ mt76_wr(dev, MT_DMA_FQCR0, MT_DMA_FQCR0_BUSY |
+@@ -123,7 +123,7 @@ void mt7603_pre_tbtt_tasklet(struct tasklet_struct *t)
+ struct ieee80211_vif *vif = info->control.vif;
+ struct mt7603_vif *mvif = (struct mt7603_vif *)vif->drv_priv;
+
+- mt76_tx_queue_skb(dev, q, skb, &mvif->sta.wcid, NULL);
++ mt76_tx_queue_skb(dev, q, MT_TXQ_CAB, skb, &mvif->sta.wcid, NULL);
+ }
+ mt76_queue_kick(dev, q);
+ spin_unlock_bh(&q->lock);
+diff --git a/drivers/net/wireless/mediatek/mt76/mt76x02_mmio.c b/drivers/net/wireless/mediatek/mt76/mt76x02_mmio.c
+index b50084bbe83de..6ba3a7975e1bf 100644
+--- a/drivers/net/wireless/mediatek/mt76/mt76x02_mmio.c
++++ b/drivers/net/wireless/mediatek/mt76/mt76x02_mmio.c
+@@ -59,7 +59,8 @@ static void mt76x02_pre_tbtt_tasklet(struct tasklet_struct *t)
+ struct ieee80211_vif *vif = info->control.vif;
+ struct mt76x02_vif *mvif = (struct mt76x02_vif *)vif->drv_priv;
+
+- mt76_tx_queue_skb(dev, q, skb, &mvif->group_wcid, NULL);
++ mt76_tx_queue_skb(dev, q, MT_TXQ_PSD, skb, &mvif->group_wcid,
++ NULL);
+ }
+ spin_unlock_bh(&q->lock);
+ }
+diff --git a/drivers/net/wireless/mediatek/mt76/sdio.c b/drivers/net/wireless/mediatek/mt76/sdio.c
+index 9e639d0b9c631..4964f19558be2 100644
+--- a/drivers/net/wireless/mediatek/mt76/sdio.c
++++ b/drivers/net/wireless/mediatek/mt76/sdio.c
+@@ -243,8 +243,8 @@ static void mt76s_tx_status_data(struct work_struct *work)
+
+ static int
+ mt76s_tx_queue_skb(struct mt76_dev *dev, struct mt76_queue *q,
+- struct sk_buff *skb, struct mt76_wcid *wcid,
+- struct ieee80211_sta *sta)
++ enum mt76_txq_id qid, struct sk_buff *skb,
++ struct mt76_wcid *wcid, struct ieee80211_sta *sta)
+ {
+ struct mt76_tx_info tx_info = {
+ .skb = skb,
+@@ -256,7 +256,7 @@ mt76s_tx_queue_skb(struct mt76_dev *dev, struct mt76_queue *q,
+ return -ENOSPC;
+
+ skb->prev = skb->next = NULL;
+- err = dev->drv->tx_prepare_skb(dev, NULL, q->qid, wcid, sta, &tx_info);
++ err = dev->drv->tx_prepare_skb(dev, NULL, qid, wcid, sta, &tx_info);
+ if (err < 0)
+ return err;
+
+diff --git a/drivers/net/wireless/mediatek/mt76/testmode.c b/drivers/net/wireless/mediatek/mt76/testmode.c
+index 0109433e8c2fe..12b13946fba18 100644
+--- a/drivers/net/wireless/mediatek/mt76/testmode.c
++++ b/drivers/net/wireless/mediatek/mt76/testmode.c
+@@ -49,8 +49,8 @@ void mt76_testmode_tx_pending(struct mt76_phy *phy)
+ q->queued < q->ndesc / 2) {
+ int ret;
+
+- ret = dev->queue_ops->tx_queue_skb(dev, q, skb_get(skb), wcid,
+- NULL);
++ ret = dev->queue_ops->tx_queue_skb(dev, q, qid, skb_get(skb),
++ wcid, NULL);
+ if (ret < 0)
+ break;
+
+diff --git a/drivers/net/wireless/mediatek/mt76/tx.c b/drivers/net/wireless/mediatek/mt76/tx.c
+index 7d126634547f1..134a735a06329 100644
+--- a/drivers/net/wireless/mediatek/mt76/tx.c
++++ b/drivers/net/wireless/mediatek/mt76/tx.c
+@@ -259,7 +259,7 @@ __mt76_tx_queue_skb(struct mt76_phy *phy, int qid, struct sk_buff *skb,
+ int idx;
+
+ non_aql = !info->tx_time_est;
+- idx = dev->queue_ops->tx_queue_skb(dev, q, skb, wcid, sta);
++ idx = dev->queue_ops->tx_queue_skb(dev, q, qid, skb, wcid, sta);
+ if (idx < 0 || !sta)
+ return idx;
+
+diff --git a/drivers/net/wireless/mediatek/mt76/usb.c b/drivers/net/wireless/mediatek/mt76/usb.c
+index b47343e321b81..392632c3f1b1d 100644
+--- a/drivers/net/wireless/mediatek/mt76/usb.c
++++ b/drivers/net/wireless/mediatek/mt76/usb.c
+@@ -901,8 +901,8 @@ mt76u_tx_setup_buffers(struct mt76_dev *dev, struct sk_buff *skb,
+
+ static int
+ mt76u_tx_queue_skb(struct mt76_dev *dev, struct mt76_queue *q,
+- struct sk_buff *skb, struct mt76_wcid *wcid,
+- struct ieee80211_sta *sta)
++ enum mt76_txq_id qid, struct sk_buff *skb,
++ struct mt76_wcid *wcid, struct ieee80211_sta *sta)
+ {
+ struct mt76_tx_info tx_info = {
+ .skb = skb,
+@@ -914,7 +914,7 @@ mt76u_tx_queue_skb(struct mt76_dev *dev, struct mt76_queue *q,
+ return -ENOSPC;
+
+ skb->prev = skb->next = NULL;
+- err = dev->drv->tx_prepare_skb(dev, NULL, q->qid, wcid, sta, &tx_info);
++ err = dev->drv->tx_prepare_skb(dev, NULL, qid, wcid, sta, &tx_info);
+ if (err < 0)
+ return err;
+
+--
+2.42.0
+
--- /dev/null
+From aba9f0451f31b86461de4108d4778361dcfce011 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 20 Sep 2023 07:37:12 +0200
+Subject: nd_btt: Make BTT lanes preemptible
+
+From: Tomas Glozar <tglozar@redhat.com>
+
+[ Upstream commit 36c75ce3bd299878fd9b238e9803d3817ddafbf3 ]
+
+nd_region_acquire_lane uses get_cpu, which disables preemption. This is
+an issue on PREEMPT_RT kernels, since btt_write_pg and also
+nd_region_acquire_lane itself take a spin lock, resulting in BUG:
+sleeping function called from invalid context.
+
+Fix the issue by replacing get_cpu with smp_process_id and
+migrate_disable when needed. This makes BTT operations preemptible, thus
+permitting the use of spin_lock.
+
+BUG example occurring when running ndctl tests on PREEMPT_RT kernel:
+
+BUG: sleeping function called from invalid context at
+kernel/locking/spinlock_rt.c:48
+in_atomic(): 1, irqs_disabled(): 0, non_block: 0, pid: 4903, name:
+libndctl
+preempt_count: 1, expected: 0
+RCU nest depth: 0, expected: 0
+Preemption disabled at:
+[<ffffffffc1313db5>] nd_region_acquire_lane+0x15/0x90 [libnvdimm]
+Call Trace:
+ <TASK>
+ dump_stack_lvl+0x8e/0xb0
+ __might_resched+0x19b/0x250
+ rt_spin_lock+0x4c/0x100
+ ? btt_write_pg+0x2d7/0x500 [nd_btt]
+ btt_write_pg+0x2d7/0x500 [nd_btt]
+ ? local_clock_noinstr+0x9/0xc0
+ btt_submit_bio+0x16d/0x270 [nd_btt]
+ __submit_bio+0x48/0x80
+ __submit_bio_noacct+0x7e/0x1e0
+ submit_bio_wait+0x58/0xb0
+ __blkdev_direct_IO_simple+0x107/0x240
+ ? inode_set_ctime_current+0x51/0x110
+ ? __pfx_submit_bio_wait_endio+0x10/0x10
+ blkdev_write_iter+0x1d8/0x290
+ vfs_write+0x237/0x330
+ ...
+ </TASK>
+
+Fixes: 5212e11fde4d ("nd_btt: atomic sector updates")
+Signed-off-by: Tomas Glozar <tglozar@redhat.com>
+Reviewed-by: Ira Weiny <ira.weiny@intel.com>
+Reviewed-by: Vishal Verma <vishal.l.verma@intel.com>
+Signed-off-by: Ira Weiny <ira.weiny@intel.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/nvdimm/region_devs.c | 8 ++++----
+ 1 file changed, 4 insertions(+), 4 deletions(-)
+
+diff --git a/drivers/nvdimm/region_devs.c b/drivers/nvdimm/region_devs.c
+index 70ad891a76bae..c2d3343b5596b 100644
+--- a/drivers/nvdimm/region_devs.c
++++ b/drivers/nvdimm/region_devs.c
+@@ -966,7 +966,8 @@ unsigned int nd_region_acquire_lane(struct nd_region *nd_region)
+ {
+ unsigned int cpu, lane;
+
+- cpu = get_cpu();
++ migrate_disable();
++ cpu = smp_processor_id();
+ if (nd_region->num_lanes < nr_cpu_ids) {
+ struct nd_percpu_lane *ndl_lock, *ndl_count;
+
+@@ -985,16 +986,15 @@ EXPORT_SYMBOL(nd_region_acquire_lane);
+ void nd_region_release_lane(struct nd_region *nd_region, unsigned int lane)
+ {
+ if (nd_region->num_lanes < nr_cpu_ids) {
+- unsigned int cpu = get_cpu();
++ unsigned int cpu = smp_processor_id();
+ struct nd_percpu_lane *ndl_lock, *ndl_count;
+
+ ndl_count = per_cpu_ptr(nd_region->lane, cpu);
+ ndl_lock = per_cpu_ptr(nd_region->lane, lane);
+ if (--ndl_count->count == 0)
+ spin_unlock(&ndl_lock->lock);
+- put_cpu();
+ }
+- put_cpu();
++ migrate_enable();
+ }
+ EXPORT_SYMBOL(nd_region_release_lane);
+
+--
+2.42.0
+
--- /dev/null
+From c3efe8573fe7882a19dd660a3ee05cf9f8bf7ead Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 21 Sep 2023 08:52:16 +0000
+Subject: net: add DEV_STATS_READ() helper
+
+From: Eric Dumazet <edumazet@google.com>
+
+[ Upstream commit 0b068c714ca9479d2783cc333fff5bc2d4a6d45c ]
+
+Companion of DEV_STATS_INC() & DEV_STATS_ADD().
+
+This is going to be used in the series.
+
+Use it in macsec_get_stats64().
+
+Signed-off-by: Eric Dumazet <edumazet@google.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Stable-dep-of: ff672b9ffeb3 ("ipvlan: properly track tx_errors")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/macsec.c | 6 +++---
+ include/linux/netdevice.h | 1 +
+ 2 files changed, 4 insertions(+), 3 deletions(-)
+
+diff --git a/drivers/net/macsec.c b/drivers/net/macsec.c
+index 07c822c301185..ab134fe1fda62 100644
+--- a/drivers/net/macsec.c
++++ b/drivers/net/macsec.c
+@@ -3681,9 +3681,9 @@ static void macsec_get_stats64(struct net_device *dev,
+
+ dev_fetch_sw_netstats(s, dev->tstats);
+
+- s->rx_dropped = atomic_long_read(&dev->stats.__rx_dropped);
+- s->tx_dropped = atomic_long_read(&dev->stats.__tx_dropped);
+- s->rx_errors = atomic_long_read(&dev->stats.__rx_errors);
++ s->rx_dropped = DEV_STATS_READ(dev, rx_dropped);
++ s->tx_dropped = DEV_STATS_READ(dev, tx_dropped);
++ s->rx_errors = DEV_STATS_READ(dev, rx_errors);
+ }
+
+ static int macsec_get_iflink(const struct net_device *dev)
+diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h
+index 132f4344fee9f..829ebde5d50d5 100644
+--- a/include/linux/netdevice.h
++++ b/include/linux/netdevice.h
+@@ -5499,5 +5499,6 @@ extern struct net_device *blackhole_netdev;
+ #define DEV_STATS_INC(DEV, FIELD) atomic_long_inc(&(DEV)->stats.__##FIELD)
+ #define DEV_STATS_ADD(DEV, FIELD, VAL) \
+ atomic_long_add((VAL), &(DEV)->stats.__##FIELD)
++#define DEV_STATS_READ(DEV, FIELD) atomic_long_read(&(DEV)->stats.__##FIELD)
+
+ #endif /* _LINUX_NETDEVICE_H */
+--
+2.42.0
+
--- /dev/null
+From e6524459e9454e9e55647f2e238c565fa1011439 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 15 Sep 2023 13:25:36 -0600
+Subject: net: spider_net: Use size_add() in call to struct_size()
+
+From: Gustavo A. R. Silva <gustavoars@kernel.org>
+
+[ Upstream commit 0201409079b975e46cc40e8bdff4bd61329ee10f ]
+
+If, for any reason, the open-coded arithmetic causes a wraparound,
+the protection that `struct_size()` adds against potential integer
+overflows is defeated. Fix this by hardening call to `struct_size()`
+with `size_add()`.
+
+Fixes: 3f1071ec39f7 ("net: spider_net: Use struct_size() helper")
+Signed-off-by: Gustavo A. R. Silva <gustavoars@kernel.org>
+Reviewed-by: Kees Cook <keescook@chromium.org>
+Signed-off-by: Geoff Levand <geoff@infradead.org>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/ethernet/toshiba/spider_net.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/drivers/net/ethernet/toshiba/spider_net.c b/drivers/net/ethernet/toshiba/spider_net.c
+index 66d4e024d11e9..f62fbb1087a9e 100644
+--- a/drivers/net/ethernet/toshiba/spider_net.c
++++ b/drivers/net/ethernet/toshiba/spider_net.c
+@@ -2332,7 +2332,7 @@ spider_net_alloc_card(void)
+ struct spider_net_card *card;
+
+ netdev = alloc_etherdev(struct_size(card, darray,
+- tx_descriptors + rx_descriptors));
++ size_add(tx_descriptors, rx_descriptors)));
+ if (!netdev)
+ return NULL;
+
+--
+2.42.0
+
--- /dev/null
+From e3c1064486cfb437c7d1170cb69679609efa632e Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 29 Sep 2023 21:19:19 +0200
+Subject: netfilter: nf_tables: Drop pointless memset when dumping rules
+
+From: Phil Sutter <phil@nwl.cc>
+
+[ Upstream commit 30fa41a0f6df4c85790cc6499ddc4a926a113bfa ]
+
+None of the dump callbacks uses netlink_callback::args beyond the first
+element, no need to zero the data.
+
+Fixes: 96518518cc41 ("netfilter: add nftables")
+Signed-off-by: Phil Sutter <phil@nwl.cc>
+Signed-off-by: Florian Westphal <fw@strlen.de>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/netfilter/nf_tables_api.c | 4 ----
+ 1 file changed, 4 deletions(-)
+
+diff --git a/net/netfilter/nf_tables_api.c b/net/netfilter/nf_tables_api.c
+index 8a4cd1c16e0e4..8f12e83280cbd 100644
+--- a/net/netfilter/nf_tables_api.c
++++ b/net/netfilter/nf_tables_api.c
+@@ -3184,10 +3184,6 @@ static int __nf_tables_dump_rules(struct sk_buff *skb,
+ goto cont_skip;
+ if (*idx < s_idx)
+ goto cont;
+- if (*idx > s_idx) {
+- memset(&cb->args[1], 0,
+- sizeof(cb->args) - sizeof(cb->args[0]));
+- }
+ if (prule)
+ handle = prule->handle;
+ else
+--
+2.42.0
+
--- /dev/null
+From f42a1130daa9f11fd1dd673b35f78826a13404e7 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 16 Oct 2023 09:15:21 +0800
+Subject: padata: Fix refcnt handling in padata_free_shell()
+
+From: WangJinchao <wangjinchao@xfusion.com>
+
+[ Upstream commit 7ddc21e317b360c3444de3023bcc83b85fabae2f ]
+
+In a high-load arm64 environment, the pcrypt_aead01 test in LTP can lead
+to system UAF (Use-After-Free) issues. Due to the lengthy analysis of
+the pcrypt_aead01 function call, I'll describe the problem scenario
+using a simplified model:
+
+Suppose there's a user of padata named `user_function` that adheres to
+the padata requirement of calling `padata_free_shell` after `serial()`
+has been invoked, as demonstrated in the following code:
+
+```c
+struct request {
+ struct padata_priv padata;
+ struct completion *done;
+};
+
+void parallel(struct padata_priv *padata) {
+ do_something();
+}
+
+void serial(struct padata_priv *padata) {
+ struct request *request = container_of(padata,
+ struct request,
+ padata);
+ complete(request->done);
+}
+
+void user_function() {
+ DECLARE_COMPLETION(done)
+ padata->parallel = parallel;
+ padata->serial = serial;
+ padata_do_parallel();
+ wait_for_completion(&done);
+ padata_free_shell();
+}
+```
+
+In the corresponding padata.c file, there's the following code:
+
+```c
+static void padata_serial_worker(struct work_struct *serial_work) {
+ ...
+ cnt = 0;
+
+ while (!list_empty(&local_list)) {
+ ...
+ padata->serial(padata);
+ cnt++;
+ }
+
+ local_bh_enable();
+
+ if (refcount_sub_and_test(cnt, &pd->refcnt))
+ padata_free_pd(pd);
+}
+```
+
+Because of the high system load and the accumulation of unexecuted
+softirq at this moment, `local_bh_enable()` in padata takes longer
+to execute than usual. Subsequently, when accessing `pd->refcnt`,
+`pd` has already been released by `padata_free_shell()`, resulting
+in a UAF issue with `pd->refcnt`.
+
+The fix is straightforward: add `refcount_dec_and_test` before calling
+`padata_free_pd` in `padata_free_shell`.
+
+Fixes: 07928d9bfc81 ("padata: Remove broken queue flushing")
+
+Signed-off-by: WangJinchao <wangjinchao@xfusion.com>
+Acked-by: Daniel Jordan <daniel.m.jordan@oracle.com>
+Acked-by: Daniel Jordan <daniel.m.jordan@oracle.com>
+Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ kernel/padata.c | 6 +++++-
+ 1 file changed, 5 insertions(+), 1 deletion(-)
+
+diff --git a/kernel/padata.c b/kernel/padata.c
+index c17f772cc315a..c6025a48fb49e 100644
+--- a/kernel/padata.c
++++ b/kernel/padata.c
+@@ -1094,12 +1094,16 @@ EXPORT_SYMBOL(padata_alloc_shell);
+ */
+ void padata_free_shell(struct padata_shell *ps)
+ {
++ struct parallel_data *pd;
++
+ if (!ps)
+ return;
+
+ mutex_lock(&ps->pinst->lock);
+ list_del(&ps->list);
+- padata_free_pd(rcu_dereference_protected(ps->pd, 1));
++ pd = rcu_dereference_protected(ps->pd, 1);
++ if (refcount_dec_and_test(&pd->refcnt))
++ padata_free_pd(pd);
+ mutex_unlock(&ps->pinst->lock);
+
+ kfree(ps);
+--
+2.42.0
+
--- /dev/null
+From bfd42c01aa52bd286c1320a5920f6bacc06220ab Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sat, 12 Nov 2022 17:25:41 +0800
+Subject: pcmcia: cs: fix possible hung task and memory leak pccardd()
+
+From: Yang Yingliang <yangyingliang@huawei.com>
+
+[ Upstream commit e3ea1b4847e49234e691c0d66bf030bd65bb7f2b ]
+
+If device_register() returns error in pccardd(), it leads two issues:
+
+1. The socket_released has never been completed, it will block
+ pcmcia_unregister_socket(), because of waiting for completion
+ of socket_released.
+2. The device name allocated by dev_set_name() is leaked.
+
+Fix this two issues by calling put_device() when device_register() fails.
+socket_released can be completed in pcmcia_release_socket(), the name can
+be freed in kobject_cleanup().
+
+Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2")
+Signed-off-by: Yang Yingliang <yangyingliang@huawei.com>
+Signed-off-by: Dominik Brodowski <linux@dominikbrodowski.net>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/pcmcia/cs.c | 1 +
+ 1 file changed, 1 insertion(+)
+
+diff --git a/drivers/pcmcia/cs.c b/drivers/pcmcia/cs.c
+index f70197154a362..820cce7c8b400 100644
+--- a/drivers/pcmcia/cs.c
++++ b/drivers/pcmcia/cs.c
+@@ -605,6 +605,7 @@ static int pccardd(void *__skt)
+ dev_warn(&skt->dev, "PCMCIA: unable to register socket\n");
+ skt->thread = NULL;
+ complete(&skt->thread_done);
++ put_device(&skt->dev);
+ return 0;
+ }
+ ret = pccard_sysfs_add_socket(&skt->dev);
+--
+2.42.0
+
--- /dev/null
+From 28725e8ddb54255485eb63173bc75e94a35b05b5 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sat, 12 Nov 2022 17:29:24 +0800
+Subject: pcmcia: ds: fix possible name leak in error path in
+ pcmcia_device_add()
+
+From: Yang Yingliang <yangyingliang@huawei.com>
+
+[ Upstream commit 99e1241049a92dd3e9a90a0f91e32ce390133278 ]
+
+Afer commit 1fa5ae857bb1 ("driver core: get rid of struct device's
+bus_id string array"), the name of device is allocated dynamically.
+Therefore, it needs to be freed, which is done by the driver core for
+us once all references to the device are gone. Therefore, move the
+dev_set_name() call immediately before the call device_register(), which
+either succeeds (then the freeing will be done upon subsequent remvoal),
+or puts the reference in the error call. Also, it is not unusual that the
+return value of dev_set_name is not checked.
+
+Fixes: 1fa5ae857bb1 ("driver core: get rid of struct device's bus_id string array")
+Signed-off-by: Yang Yingliang <yangyingliang@huawei.com>
+[linux@dominikbrodowski.net: simplification, commit message modified]
+Signed-off-by: Dominik Brodowski <linux@dominikbrodowski.net>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/pcmcia/ds.c | 4 +---
+ 1 file changed, 1 insertion(+), 3 deletions(-)
+
+diff --git a/drivers/pcmcia/ds.c b/drivers/pcmcia/ds.c
+index bdbd38fed94d2..f8baf178ef3c6 100644
+--- a/drivers/pcmcia/ds.c
++++ b/drivers/pcmcia/ds.c
+@@ -513,9 +513,6 @@ static struct pcmcia_device *pcmcia_device_add(struct pcmcia_socket *s,
+ /* by default don't allow DMA */
+ p_dev->dma_mask = 0;
+ p_dev->dev.dma_mask = &p_dev->dma_mask;
+- dev_set_name(&p_dev->dev, "%d.%d", p_dev->socket->sock, p_dev->device_no);
+- if (!dev_name(&p_dev->dev))
+- goto err_free;
+ p_dev->devname = kasprintf(GFP_KERNEL, "pcmcia%s", dev_name(&p_dev->dev));
+ if (!p_dev->devname)
+ goto err_free;
+@@ -573,6 +570,7 @@ static struct pcmcia_device *pcmcia_device_add(struct pcmcia_socket *s,
+
+ pcmcia_device_query(p_dev);
+
++ dev_set_name(&p_dev->dev, "%d.%d", p_dev->socket->sock, p_dev->device_no);
+ if (device_register(&p_dev->dev)) {
+ mutex_lock(&s->ops_mutex);
+ list_del(&p_dev->socket_device_list);
+--
+2.42.0
+
--- /dev/null
+From 13d67d54d1de77a8f35da3948aaa3d9f3a57db95 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sat, 12 Nov 2022 17:29:23 +0800
+Subject: pcmcia: ds: fix refcount leak in pcmcia_device_add()
+
+From: Yang Yingliang <yangyingliang@huawei.com>
+
+[ Upstream commit 402ab979b29126068e0b596b641422ff7490214c ]
+
+As the comment of device_register() says, it should use put_device()
+to give up the reference in the error path. Then, insofar resources
+will be freed in pcmcia_release_dev(), the error path is no longer
+needed. In particular, this means that the (previously missing) dropping
+of the reference to &p_dev->function_config->ref is now handled by
+pcmcia_release_dev().
+
+Fixes: 360b65b95bae ("[PATCH] pcmcia: make config_t independent, add reference counting")
+Signed-off-by: Yang Yingliang <yangyingliang@huawei.com>
+[linux@dominikbrodowski.net: simplification, commit message rewrite]
+Signed-off-by: Dominik Brodowski <linux@dominikbrodowski.net>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/pcmcia/ds.c | 10 ++++++++--
+ 1 file changed, 8 insertions(+), 2 deletions(-)
+
+diff --git a/drivers/pcmcia/ds.c b/drivers/pcmcia/ds.c
+index 5bd1b80424e72..bdbd38fed94d2 100644
+--- a/drivers/pcmcia/ds.c
++++ b/drivers/pcmcia/ds.c
+@@ -573,8 +573,14 @@ static struct pcmcia_device *pcmcia_device_add(struct pcmcia_socket *s,
+
+ pcmcia_device_query(p_dev);
+
+- if (device_register(&p_dev->dev))
+- goto err_unreg;
++ if (device_register(&p_dev->dev)) {
++ mutex_lock(&s->ops_mutex);
++ list_del(&p_dev->socket_device_list);
++ s->device_count--;
++ mutex_unlock(&s->ops_mutex);
++ put_device(&p_dev->dev);
++ return NULL;
++ }
+
+ return p_dev;
+
+--
+2.42.0
+
--- /dev/null
+From a4455e5be294c717c5f1b67c1ef9471f3229e41f Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 24 May 2022 10:54:26 +0300
+Subject: perf evlist: Add evlist__add_dummy_on_all_cpus()
+
+From: Adrian Hunter <adrian.hunter@intel.com>
+
+[ Upstream commit 126d68fdcabed8c2ca5ffaba785add93ef722da8 ]
+
+Add evlist__add_dummy_on_all_cpus() to enable creating a system-wide dummy
+event that sets up the system-wide maps before map propagation.
+
+For convenience, add evlist__add_aux_dummy() so that the logic can be used
+whether or not the event needs to be system-wide.
+
+Signed-off-by: Adrian Hunter <adrian.hunter@intel.com>
+Acked-by: Ian Rogers <irogers@google.com>
+Acked-by: Namhyung Kim <namhyung@kernel.org>
+Cc: Alexey Bayduraev <alexey.v.bayduraev@linux.intel.com>
+Cc: Ian Rogers <irogers@google.com>
+Cc: Jiri Olsa <jolsa@kernel.org>
+Cc: Leo Yan <leo.yan@linaro.org>
+Link: https://lore.kernel.org/r/20220524075436.29144-6-adrian.hunter@intel.com
+Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
+Stable-dep-of: f9cdeb58a9cf ("perf evlist: Avoid frequency mode for the dummy event")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ tools/perf/util/evlist.c | 45 ++++++++++++++++++++++++++++++++++++++++
+ tools/perf/util/evlist.h | 5 +++++
+ 2 files changed, 50 insertions(+)
+
+diff --git a/tools/perf/util/evlist.c b/tools/perf/util/evlist.c
+index 39d294f6c3218..a75cdcf381308 100644
+--- a/tools/perf/util/evlist.c
++++ b/tools/perf/util/evlist.c
+@@ -258,6 +258,51 @@ int evlist__add_dummy(struct evlist *evlist)
+ return 0;
+ }
+
++static void evlist__add_on_all_cpus(struct evlist *evlist, struct evsel *evsel)
++{
++ evsel->core.system_wide = true;
++
++ /*
++ * All CPUs.
++ *
++ * Note perf_event_open() does not accept CPUs that are not online, so
++ * in fact this CPU list will include only all online CPUs.
++ */
++ perf_cpu_map__put(evsel->core.own_cpus);
++ evsel->core.own_cpus = perf_cpu_map__new(NULL);
++ perf_cpu_map__put(evsel->core.cpus);
++ evsel->core.cpus = perf_cpu_map__get(evsel->core.own_cpus);
++
++ /* No threads */
++ perf_thread_map__put(evsel->core.threads);
++ evsel->core.threads = perf_thread_map__new_dummy();
++
++ evlist__add(evlist, evsel);
++}
++
++struct evsel *evlist__add_aux_dummy(struct evlist *evlist, bool system_wide)
++{
++ struct evsel *evsel = evlist__dummy_event(evlist);
++
++ if (!evsel)
++ return NULL;
++
++ evsel->core.attr.exclude_kernel = 1;
++ evsel->core.attr.exclude_guest = 1;
++ evsel->core.attr.exclude_hv = 1;
++ evsel->core.attr.freq = 0;
++ evsel->core.attr.sample_period = 1;
++ evsel->no_aux_samples = true;
++ evsel->name = strdup("dummy:u");
++
++ if (system_wide)
++ evlist__add_on_all_cpus(evlist, evsel);
++ else
++ evlist__add(evlist, evsel);
++
++ return evsel;
++}
++
+ static int evlist__add_attrs(struct evlist *evlist, struct perf_event_attr *attrs, size_t nr_attrs)
+ {
+ struct evsel *evsel, *n;
+diff --git a/tools/perf/util/evlist.h b/tools/perf/util/evlist.h
+index ec177f783ee67..decf5c944adba 100644
+--- a/tools/perf/util/evlist.h
++++ b/tools/perf/util/evlist.h
+@@ -112,6 +112,11 @@ int __evlist__add_default_attrs(struct evlist *evlist,
+ int arch_evlist__add_default_attrs(struct evlist *evlist);
+
+ int evlist__add_dummy(struct evlist *evlist);
++struct evsel *evlist__add_aux_dummy(struct evlist *evlist, bool system_wide);
++static inline struct evsel *evlist__add_dummy_on_all_cpus(struct evlist *evlist)
++{
++ return evlist__add_aux_dummy(evlist, true);
++}
+
+ int evlist__add_sb_event(struct evlist *evlist, struct perf_event_attr *attr,
+ evsel__sb_cb_t cb, void *data);
+--
+2.42.0
+
--- /dev/null
+From dce002fd193111afa04774420e3798b77c54e543 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 15 Sep 2023 20:56:40 -0700
+Subject: perf evlist: Avoid frequency mode for the dummy event
+
+From: Ian Rogers <irogers@google.com>
+
+[ Upstream commit f9cdeb58a9cf46c09b56f5f661ea8da24b6458c3 ]
+
+Dummy events are created with an attribute where the period and freq
+are zero. evsel__config will then see the uninitialized values and
+initialize them in evsel__default_freq_period. As fequency mode is
+used by default the dummy event would be set to use frequency
+mode. However, this has no effect on the dummy event but does cause
+unnecessary timers/interrupts. Avoid this overhead by setting the
+period to 1 for dummy events.
+
+evlist__add_aux_dummy calls evlist__add_dummy then sets freq=0 and
+period=1. This isn't necessary after this change and so the setting is
+removed.
+
+From Stephane:
+
+The dummy event is not counting anything. It is used to collect mmap
+records and avoid a race condition during the synthesize mmap phase of
+perf record. As such, it should not cause any overhead during active
+profiling. Yet, it did. Because of a bug the dummy event was
+programmed as a sampling event in frequency mode. Events in that mode
+incur more kernel overheads because on timer tick, the kernel has to
+look at the number of samples for each event and potentially adjust
+the sampling period to achieve the desired frequency. The dummy event
+was therefore adding a frequency event to task and ctx contexts we may
+otherwise not have any, e.g.,
+
+ perf record -a -e cpu/event=0x3c,period=10000000/.
+
+On each timer tick the perf_adjust_freq_unthr_context() is invoked and
+if ctx->nr_freq is non-zero, then the kernel will loop over ALL the
+events of the context looking for frequency mode ones. In doing, so it
+locks the context, and enable/disable the PMU of each hw event. If all
+the events of the context are in period mode, the kernel will have to
+traverse the list for nothing incurring overhead. The overhead is
+multiplied by a very large factor when this happens in a guest kernel.
+There is no need for the dummy event to be in frequency mode, it does
+not count anything and therefore should not cause extra overhead for
+no reason.
+
+Fixes: 5bae0250237f ("perf evlist: Introduce perf_evlist__new_dummy constructor")
+Reported-by: Stephane Eranian <eranian@google.com>
+Signed-off-by: Ian Rogers <irogers@google.com>
+Acked-by: Adrian Hunter <adrian.hunter@intel.com>
+Cc: Yang Jihong <yangjihong1@huawei.com>
+Cc: Kan Liang <kan.liang@linux.intel.com>
+Link: https://lore.kernel.org/r/20230916035640.1074422-1-irogers@google.com
+Signed-off-by: Namhyung Kim <namhyung@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ tools/perf/util/evlist.c | 5 +++--
+ 1 file changed, 3 insertions(+), 2 deletions(-)
+
+diff --git a/tools/perf/util/evlist.c b/tools/perf/util/evlist.c
+index 63ef40543a9fe..9d0f2feb25671 100644
+--- a/tools/perf/util/evlist.c
++++ b/tools/perf/util/evlist.c
+@@ -248,6 +248,9 @@ int evlist__add_dummy(struct evlist *evlist)
+ .type = PERF_TYPE_SOFTWARE,
+ .config = PERF_COUNT_SW_DUMMY,
+ .size = sizeof(attr), /* to capture ABI version */
++ /* Avoid frequency mode for dummy events to avoid associated timers. */
++ .freq = 0,
++ .sample_period = 1,
+ };
+ struct evsel *evsel = evsel__new_idx(&attr, evlist->core.nr_entries);
+
+@@ -268,8 +271,6 @@ struct evsel *evlist__add_aux_dummy(struct evlist *evlist, bool system_wide)
+ evsel->core.attr.exclude_kernel = 1;
+ evsel->core.attr.exclude_guest = 1;
+ evsel->core.attr.exclude_hv = 1;
+- evsel->core.attr.freq = 0;
+- evsel->core.attr.sample_period = 1;
+ evsel->core.system_wide = system_wide;
+ evsel->no_aux_samples = true;
+ evsel->name = strdup("dummy:u");
+--
+2.42.0
+
--- /dev/null
+From 9a4221bcf19da839b0e44457b8ea21cdc9352b5a Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 24 Oct 2023 19:36:30 +0800
+Subject: perf: hisi: Fix use-after-free when register pmu fails
+
+From: Junhao He <hejunhao3@huawei.com>
+
+[ Upstream commit b805cafc604bfdb671fae7347a57f51154afa735 ]
+
+When we fail to register the uncore pmu, the pmu context may not been
+allocated. The error handing will call cpuhp_state_remove_instance()
+to call uncore pmu offline callback, which migrate the pmu context.
+Since that's liable to lead to some kind of use-after-free.
+
+Use cpuhp_state_remove_instance_nocalls() instead of
+cpuhp_state_remove_instance() so that the notifiers don't execute after
+the PMU device has been failed to register.
+
+Fixes: a0ab25cd82ee ("drivers/perf: hisi: Add support for HiSilicon PA PMU driver")
+FIxes: 3bf30882c3c7 ("drivers/perf: hisi: Add support for HiSilicon SLLC PMU driver")
+Signed-off-by: Junhao He <hejunhao3@huawei.com>
+Link: https://lore.kernel.org/r/20231024113630.13472-1-hejunhao3@huawei.com
+Signed-off-by: Will Deacon <will@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/perf/hisilicon/hisi_uncore_pa_pmu.c | 4 ++--
+ drivers/perf/hisilicon/hisi_uncore_sllc_pmu.c | 4 ++--
+ 2 files changed, 4 insertions(+), 4 deletions(-)
+
+diff --git a/drivers/perf/hisilicon/hisi_uncore_pa_pmu.c b/drivers/perf/hisilicon/hisi_uncore_pa_pmu.c
+index 83264ec0a9573..7b096f1dc9eb1 100644
+--- a/drivers/perf/hisilicon/hisi_uncore_pa_pmu.c
++++ b/drivers/perf/hisilicon/hisi_uncore_pa_pmu.c
+@@ -434,8 +434,8 @@ static int hisi_pa_pmu_probe(struct platform_device *pdev)
+ ret = perf_pmu_register(&pa_pmu->pmu, name, -1);
+ if (ret) {
+ dev_err(pa_pmu->dev, "PMU register failed, ret = %d\n", ret);
+- cpuhp_state_remove_instance(CPUHP_AP_PERF_ARM_HISI_PA_ONLINE,
+- &pa_pmu->node);
++ cpuhp_state_remove_instance_nocalls(CPUHP_AP_PERF_ARM_HISI_PA_ONLINE,
++ &pa_pmu->node);
+ return ret;
+ }
+
+diff --git a/drivers/perf/hisilicon/hisi_uncore_sllc_pmu.c b/drivers/perf/hisilicon/hisi_uncore_sllc_pmu.c
+index 6aedc303ff56a..f3cd00fc9bbe6 100644
+--- a/drivers/perf/hisilicon/hisi_uncore_sllc_pmu.c
++++ b/drivers/perf/hisilicon/hisi_uncore_sllc_pmu.c
+@@ -463,8 +463,8 @@ static int hisi_sllc_pmu_probe(struct platform_device *pdev)
+ ret = perf_pmu_register(&sllc_pmu->pmu, name, -1);
+ if (ret) {
+ dev_err(sllc_pmu->dev, "PMU register failed, ret = %d\n", ret);
+- cpuhp_state_remove_instance(CPUHP_AP_PERF_ARM_HISI_SLLC_ONLINE,
+- &sllc_pmu->node);
++ cpuhp_state_remove_instance_nocalls(CPUHP_AP_PERF_ARM_HISI_SLLC_ONLINE,
++ &sllc_pmu->node);
+ return ret;
+ }
+
+--
+2.42.0
+
--- /dev/null
+From 97b7b4274c2ef00e21401c010ce1366d7038ef1a Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 24 Oct 2023 15:23:08 -0700
+Subject: perf hist: Add missing puts to hist__account_cycles
+
+From: Ian Rogers <irogers@google.com>
+
+[ Upstream commit c1149037f65bcf0334886180ebe3d5efcf214912 ]
+
+Caught using reference count checking on perf top with
+"--call-graph=lbr". After this no memory leaks were detected.
+
+Fixes: 57849998e2cd ("perf report: Add processing for cycle histograms")
+Signed-off-by: Ian Rogers <irogers@google.com>
+Cc: K Prateek Nayak <kprateek.nayak@amd.com>
+Cc: Ravi Bangoria <ravi.bangoria@amd.com>
+Cc: Sandipan Das <sandipan.das@amd.com>
+Cc: Anshuman Khandual <anshuman.khandual@arm.com>
+Cc: German Gomez <german.gomez@arm.com>
+Cc: James Clark <james.clark@arm.com>
+Cc: Nick Terrell <terrelln@fb.com>
+Cc: Sean Christopherson <seanjc@google.com>
+Cc: Changbin Du <changbin.du@huawei.com>
+Cc: liuwenyu <liuwenyu7@huawei.com>
+Cc: Yang Jihong <yangjihong1@huawei.com>
+Cc: Masami Hiramatsu <mhiramat@kernel.org>
+Cc: Miguel Ojeda <ojeda@kernel.org>
+Cc: Song Liu <song@kernel.org>
+Cc: Leo Yan <leo.yan@linaro.org>
+Cc: Kajol Jain <kjain@linux.ibm.com>
+Cc: Andi Kleen <ak@linux.intel.com>
+Cc: Kan Liang <kan.liang@linux.intel.com>
+Cc: Athira Rajeev <atrajeev@linux.vnet.ibm.com>
+Cc: Yanteng Si <siyanteng@loongson.cn>
+Cc: Liam Howlett <liam.howlett@oracle.com>
+Cc: Paolo Bonzini <pbonzini@redhat.com>
+Link: https://lore.kernel.org/r/20231024222353.3024098-6-irogers@google.com
+Signed-off-by: Namhyung Kim <namhyung@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ tools/perf/util/hist.c | 10 +++++++---
+ 1 file changed, 7 insertions(+), 3 deletions(-)
+
+diff --git a/tools/perf/util/hist.c b/tools/perf/util/hist.c
+index b776465e04ef3..e67935b1e3060 100644
+--- a/tools/perf/util/hist.c
++++ b/tools/perf/util/hist.c
+@@ -2635,8 +2635,6 @@ void hist__account_cycles(struct branch_stack *bs, struct addr_location *al,
+
+ /* If we have branch cycles always annotate them. */
+ if (bs && bs->nr && entries[0].flags.cycles) {
+- int i;
+-
+ bi = sample__resolve_bstack(sample, al);
+ if (bi) {
+ struct addr_map_symbol *prev = NULL;
+@@ -2651,7 +2649,7 @@ void hist__account_cycles(struct branch_stack *bs, struct addr_location *al,
+ * Note that perf stores branches reversed from
+ * program order!
+ */
+- for (i = bs->nr - 1; i >= 0; i--) {
++ for (int i = bs->nr - 1; i >= 0; i--) {
+ addr_map_symbol__account_cycles(&bi[i].from,
+ nonany_branch_mode ? NULL : prev,
+ bi[i].flags.cycles);
+@@ -2660,6 +2658,12 @@ void hist__account_cycles(struct branch_stack *bs, struct addr_location *al,
+ if (total_cycles)
+ *total_cycles += bi[i].flags.cycles;
+ }
++ for (unsigned int i = 0; i < bs->nr; i++) {
++ map__put(bi[i].to.ms.map);
++ maps__put(bi[i].to.ms.maps);
++ map__put(bi[i].from.ms.map);
++ maps__put(bi[i].from.ms.maps);
++ }
+ free(bi);
+ }
+ }
+--
+2.42.0
+
--- /dev/null
+From 94ef4f4326d44d2915eaacff0e2d3e0f557fafa0 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 24 Oct 2023 15:23:05 -0700
+Subject: perf machine: Avoid out of bounds LBR memory read
+
+From: Ian Rogers <irogers@google.com>
+
+[ Upstream commit ab8ce150781d326c6bfbe1e09f175ffde1186f80 ]
+
+Running perf top with address sanitizer and "--call-graph=lbr" fails
+due to reading sample 0 when no samples exist. Add a guard to prevent
+this.
+
+Fixes: e2b23483eb1d ("perf machine: Factor out lbr_callchain_add_lbr_ip()")
+Signed-off-by: Ian Rogers <irogers@google.com>
+Cc: K Prateek Nayak <kprateek.nayak@amd.com>
+Cc: Ravi Bangoria <ravi.bangoria@amd.com>
+Cc: Sandipan Das <sandipan.das@amd.com>
+Cc: Anshuman Khandual <anshuman.khandual@arm.com>
+Cc: German Gomez <german.gomez@arm.com>
+Cc: James Clark <james.clark@arm.com>
+Cc: Nick Terrell <terrelln@fb.com>
+Cc: Sean Christopherson <seanjc@google.com>
+Cc: Changbin Du <changbin.du@huawei.com>
+Cc: liuwenyu <liuwenyu7@huawei.com>
+Cc: Yang Jihong <yangjihong1@huawei.com>
+Cc: Masami Hiramatsu <mhiramat@kernel.org>
+Cc: Miguel Ojeda <ojeda@kernel.org>
+Cc: Song Liu <song@kernel.org>
+Cc: Leo Yan <leo.yan@linaro.org>
+Cc: Kajol Jain <kjain@linux.ibm.com>
+Cc: Andi Kleen <ak@linux.intel.com>
+Cc: Kan Liang <kan.liang@linux.intel.com>
+Cc: Athira Rajeev <atrajeev@linux.vnet.ibm.com>
+Cc: Yanteng Si <siyanteng@loongson.cn>
+Cc: Liam Howlett <liam.howlett@oracle.com>
+Cc: Paolo Bonzini <pbonzini@redhat.com>
+Link: https://lore.kernel.org/r/20231024222353.3024098-3-irogers@google.com
+Signed-off-by: Namhyung Kim <namhyung@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ tools/perf/util/machine.c | 22 ++++++++++++----------
+ 1 file changed, 12 insertions(+), 10 deletions(-)
+
+diff --git a/tools/perf/util/machine.c b/tools/perf/util/machine.c
+index 55a041329990c..a0df9d24b2cb4 100644
+--- a/tools/perf/util/machine.c
++++ b/tools/perf/util/machine.c
+@@ -2437,16 +2437,18 @@ static int lbr_callchain_add_lbr_ip(struct thread *thread,
+ save_lbr_cursor_node(thread, cursor, i);
+ }
+
+- /* Add LBR ip from first entries.to */
+- ip = entries[0].to;
+- flags = &entries[0].flags;
+- *branch_from = entries[0].from;
+- err = add_callchain_ip(thread, cursor, parent,
+- root_al, &cpumode, ip,
+- true, flags, NULL,
+- *branch_from);
+- if (err)
+- return err;
++ if (lbr_nr > 0) {
++ /* Add LBR ip from first entries.to */
++ ip = entries[0].to;
++ flags = &entries[0].flags;
++ *branch_from = entries[0].from;
++ err = add_callchain_ip(thread, cursor, parent,
++ root_al, &cpumode, ip,
++ true, flags, NULL,
++ *branch_from);
++ if (err)
++ return err;
++ }
+
+ return 0;
+ }
+--
+2.42.0
+
--- /dev/null
+From 0bad7dc2bbd481839db55a75620e7603c114eee2 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 3 Oct 2022 13:46:45 -0700
+Subject: perf tools: Get rid of evlist__add_on_all_cpus()
+
+From: Namhyung Kim <namhyung@kernel.org>
+
+[ Upstream commit 60ea006f72512fd7c36f16cdbe91f4fc284f8115 ]
+
+The cpu and thread maps are properly handled in libperf now. No need to
+do it in the perf tools anymore. Let's remove the logic.
+
+Reviewed-by: Adrian Hunter <adrian.hunter@intel.com>
+Signed-off-by: Namhyung Kim <namhyung@kernel.org>
+Cc: Ian Rogers <irogers@google.com>
+Cc: Ingo Molnar <mingo@kernel.org>
+Cc: Jiri Olsa <jolsa@kernel.org>
+Cc: Kan Liang <kan.liang@linux.intel.com>
+Cc: Leo Yan <leo.yan@linaro.org>
+Cc: Peter Zijlstra <peterz@infradead.org>
+Link: https://lore.kernel.org/r/20221003204647.1481128-4-namhyung@kernel.org
+Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
+Stable-dep-of: f9cdeb58a9cf ("perf evlist: Avoid frequency mode for the dummy event")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ tools/perf/util/evlist.c | 29 ++---------------------------
+ 1 file changed, 2 insertions(+), 27 deletions(-)
+
+diff --git a/tools/perf/util/evlist.c b/tools/perf/util/evlist.c
+index a75cdcf381308..63ef40543a9fe 100644
+--- a/tools/perf/util/evlist.c
++++ b/tools/perf/util/evlist.c
+@@ -258,28 +258,6 @@ int evlist__add_dummy(struct evlist *evlist)
+ return 0;
+ }
+
+-static void evlist__add_on_all_cpus(struct evlist *evlist, struct evsel *evsel)
+-{
+- evsel->core.system_wide = true;
+-
+- /*
+- * All CPUs.
+- *
+- * Note perf_event_open() does not accept CPUs that are not online, so
+- * in fact this CPU list will include only all online CPUs.
+- */
+- perf_cpu_map__put(evsel->core.own_cpus);
+- evsel->core.own_cpus = perf_cpu_map__new(NULL);
+- perf_cpu_map__put(evsel->core.cpus);
+- evsel->core.cpus = perf_cpu_map__get(evsel->core.own_cpus);
+-
+- /* No threads */
+- perf_thread_map__put(evsel->core.threads);
+- evsel->core.threads = perf_thread_map__new_dummy();
+-
+- evlist__add(evlist, evsel);
+-}
+-
+ struct evsel *evlist__add_aux_dummy(struct evlist *evlist, bool system_wide)
+ {
+ struct evsel *evsel = evlist__dummy_event(evlist);
+@@ -292,14 +270,11 @@ struct evsel *evlist__add_aux_dummy(struct evlist *evlist, bool system_wide)
+ evsel->core.attr.exclude_hv = 1;
+ evsel->core.attr.freq = 0;
+ evsel->core.attr.sample_period = 1;
++ evsel->core.system_wide = system_wide;
+ evsel->no_aux_samples = true;
+ evsel->name = strdup("dummy:u");
+
+- if (system_wide)
+- evlist__add_on_all_cpus(evlist, evsel);
+- else
+- evlist__add(evlist, evsel);
+-
++ evlist__add(evlist, evsel);
+ return evsel;
+ }
+
+--
+2.42.0
+
--- /dev/null
+From aff140ddac1b15e0ca9ad483da85784ef7fce10a Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 20 Oct 2023 23:10:04 +0200
+Subject: platform/x86: wmi: Fix opening of char device
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Armin Wolf <W_Armin@gmx.de>
+
+[ Upstream commit eba9ac7abab91c8f6d351460239108bef5e7a0b6 ]
+
+Since commit fa1f68db6ca7 ("drivers: misc: pass miscdevice pointer via
+file private data"), the miscdevice stores a pointer to itself inside
+filp->private_data, which means that private_data will not be NULL when
+wmi_char_open() is called. This might cause memory corruption should
+wmi_char_open() be unable to find its driver, something which can
+happen when the associated WMI device is deleted in wmi_free_devices().
+
+Fix the problem by using the miscdevice pointer to retrieve the WMI
+device data associated with a char device using container_of(). This
+also avoids wmi_char_open() picking a wrong WMI device bound to a
+driver with the same name as the original driver.
+
+Fixes: 44b6b7661132 ("platform/x86: wmi: create userspace interface for drivers")
+Signed-off-by: Armin Wolf <W_Armin@gmx.de>
+Link: https://lore.kernel.org/r/20231020211005.38216-5-W_Armin@gmx.de
+Reviewed-by: Ilpo Järvinen <ilpo.jarvinen@linux.intel.com>
+Signed-off-by: Ilpo Järvinen <ilpo.jarvinen@linux.intel.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/platform/x86/wmi.c | 20 ++++++--------------
+ 1 file changed, 6 insertions(+), 14 deletions(-)
+
+diff --git a/drivers/platform/x86/wmi.c b/drivers/platform/x86/wmi.c
+index 530778dbdd093..63265ab964245 100644
+--- a/drivers/platform/x86/wmi.c
++++ b/drivers/platform/x86/wmi.c
+@@ -827,21 +827,13 @@ static int wmi_dev_match(struct device *dev, struct device_driver *driver)
+ }
+ static int wmi_char_open(struct inode *inode, struct file *filp)
+ {
+- const char *driver_name = filp->f_path.dentry->d_iname;
+- struct wmi_block *wblock;
+- struct wmi_block *next;
+-
+- list_for_each_entry_safe(wblock, next, &wmi_block_list, list) {
+- if (!wblock->dev.dev.driver)
+- continue;
+- if (strcmp(driver_name, wblock->dev.dev.driver->name) == 0) {
+- filp->private_data = wblock;
+- break;
+- }
+- }
++ /*
++ * The miscdevice already stores a pointer to itself
++ * inside filp->private_data
++ */
++ struct wmi_block *wblock = container_of(filp->private_data, struct wmi_block, char_dev);
+
+- if (!filp->private_data)
+- return -ENODEV;
++ filp->private_data = wblock;
+
+ return nonseekable_open(inode, filp);
+ }
+--
+2.42.0
+
--- /dev/null
+From 7723b028daf17e2a0ebf61dd46224bb24a3ee1ad Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 20 Oct 2023 23:10:03 +0200
+Subject: platform/x86: wmi: Fix probe failure when failing to register WMI
+ devices
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Armin Wolf <W_Armin@gmx.de>
+
+[ Upstream commit ed85891a276edaf7a867de0e9acd0837bc3008f2 ]
+
+When a WMI device besides the first one somehow fails to register,
+retval is returned while still containing a negative error code. This
+causes the ACPI device fail to probe, leaving behind zombie WMI devices
+leading to various errors later.
+
+Handle the single error path separately and return 0 unconditionally
+after trying to register all WMI devices to solve the issue. Also
+continue to register WMI devices even if some fail to allocate memory.
+
+Fixes: 6ee50aaa9a20 ("platform/x86: wmi: Instantiate all devices before adding them")
+Signed-off-by: Armin Wolf <W_Armin@gmx.de>
+Link: https://lore.kernel.org/r/20231020211005.38216-4-W_Armin@gmx.de
+Reviewed-by: Ilpo Järvinen <ilpo.jarvinen@linux.intel.com>
+Signed-off-by: Ilpo Järvinen <ilpo.jarvinen@linux.intel.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/platform/x86/wmi.c | 16 ++++++++--------
+ 1 file changed, 8 insertions(+), 8 deletions(-)
+
+diff --git a/drivers/platform/x86/wmi.c b/drivers/platform/x86/wmi.c
+index 7ce0408d3bfdd..e87ed10fd6269 100644
+--- a/drivers/platform/x86/wmi.c
++++ b/drivers/platform/x86/wmi.c
+@@ -1161,8 +1161,8 @@ static int parse_wdg(struct device *wmi_bus_dev, struct acpi_device *device)
+ struct wmi_block *wblock, *next;
+ union acpi_object *obj;
+ acpi_status status;
+- int retval = 0;
+ u32 i, total;
++ int retval;
+
+ status = acpi_evaluate_object(device->handle, "_WDG", NULL, &out);
+ if (ACPI_FAILURE(status))
+@@ -1173,8 +1173,8 @@ static int parse_wdg(struct device *wmi_bus_dev, struct acpi_device *device)
+ return -ENXIO;
+
+ if (obj->type != ACPI_TYPE_BUFFER) {
+- retval = -ENXIO;
+- goto out_free_pointer;
++ kfree(obj);
++ return -ENXIO;
+ }
+
+ gblock = (const struct guid_block *)obj->buffer.pointer;
+@@ -1195,8 +1195,8 @@ static int parse_wdg(struct device *wmi_bus_dev, struct acpi_device *device)
+
+ wblock = kzalloc(sizeof(struct wmi_block), GFP_KERNEL);
+ if (!wblock) {
+- retval = -ENOMEM;
+- break;
++ dev_err(wmi_bus_dev, "Failed to allocate %pUL\n", &gblock[i].guid);
++ continue;
+ }
+
+ wblock->acpi_device = device;
+@@ -1235,9 +1235,9 @@ static int parse_wdg(struct device *wmi_bus_dev, struct acpi_device *device)
+ }
+ }
+
+-out_free_pointer:
+- kfree(out.pointer);
+- return retval;
++ kfree(obj);
++
++ return 0;
+ }
+
+ /*
+--
+2.42.0
+
--- /dev/null
+From c2639adbd067567b5bf3b3732092a2fa44d0a9bd Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sat, 4 Sep 2021 17:55:10 +0000
+Subject: platform/x86: wmi: remove unnecessary initializations
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Barnabás Pőcze <pobrn@protonmail.com>
+
+[ Upstream commit 43aacf838ef7384d985ef5385ecb0124f8c70007 ]
+
+Some pointers are initialized when they are defined,
+but they are almost immediately reassigned in the
+following lines. Remove these superfluous assignments.
+
+Signed-off-by: Barnabás Pőcze <pobrn@protonmail.com>
+Link: https://lore.kernel.org/r/20210904175450.156801-6-pobrn@protonmail.com
+Reviewed-by: Hans de Goede <hdegoede@redhat.com>
+Signed-off-by: Hans de Goede <hdegoede@redhat.com>
+Stable-dep-of: eba9ac7abab9 ("platform/x86: wmi: Fix opening of char device")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/platform/x86/wmi.c | 18 +++++++++---------
+ 1 file changed, 9 insertions(+), 9 deletions(-)
+
+diff --git a/drivers/platform/x86/wmi.c b/drivers/platform/x86/wmi.c
+index e87ed10fd6269..530778dbdd093 100644
+--- a/drivers/platform/x86/wmi.c
++++ b/drivers/platform/x86/wmi.c
+@@ -188,7 +188,7 @@ static int get_subobj_info(acpi_handle handle, const char *pathname,
+
+ static acpi_status wmi_method_enable(struct wmi_block *wblock, int enable)
+ {
+- struct guid_block *block = NULL;
++ struct guid_block *block;
+ char method[5];
+ acpi_status status;
+ acpi_handle handle;
+@@ -262,8 +262,8 @@ EXPORT_SYMBOL_GPL(wmi_evaluate_method);
+ acpi_status wmidev_evaluate_method(struct wmi_device *wdev, u8 instance,
+ u32 method_id, const struct acpi_buffer *in, struct acpi_buffer *out)
+ {
+- struct guid_block *block = NULL;
+- struct wmi_block *wblock = NULL;
++ struct guid_block *block;
++ struct wmi_block *wblock;
+ acpi_handle handle;
+ acpi_status status;
+ struct acpi_object_list input;
+@@ -310,7 +310,7 @@ EXPORT_SYMBOL_GPL(wmidev_evaluate_method);
+ static acpi_status __query_block(struct wmi_block *wblock, u8 instance,
+ struct acpi_buffer *out)
+ {
+- struct guid_block *block = NULL;
++ struct guid_block *block;
+ acpi_handle handle;
+ acpi_status status, wc_status = AE_ERROR;
+ struct acpi_object_list input;
+@@ -423,8 +423,8 @@ EXPORT_SYMBOL_GPL(wmidev_block_query);
+ acpi_status wmi_set_block(const char *guid_string, u8 instance,
+ const struct acpi_buffer *in)
+ {
+- struct guid_block *block = NULL;
+ struct wmi_block *wblock = NULL;
++ struct guid_block *block;
+ acpi_handle handle;
+ struct acpi_object_list input;
+ union acpi_object params[2];
+@@ -828,8 +828,8 @@ static int wmi_dev_match(struct device *dev, struct device_driver *driver)
+ static int wmi_char_open(struct inode *inode, struct file *filp)
+ {
+ const char *driver_name = filp->f_path.dentry->d_iname;
+- struct wmi_block *wblock = NULL;
+- struct wmi_block *next = NULL;
++ struct wmi_block *wblock;
++ struct wmi_block *next;
+
+ list_for_each_entry_safe(wblock, next, &wmi_block_list, list) {
+ if (!wblock->dev.dev.driver)
+@@ -861,8 +861,8 @@ static long wmi_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
+ struct wmi_ioctl_buffer __user *input =
+ (struct wmi_ioctl_buffer __user *) arg;
+ struct wmi_block *wblock = filp->private_data;
+- struct wmi_ioctl_buffer *buf = NULL;
+- struct wmi_driver *wdriver = NULL;
++ struct wmi_ioctl_buffer *buf;
++ struct wmi_driver *wdriver;
+ int ret;
+
+ if (_IOC_TYPE(cmd) != WMI_IOC)
+--
+2.42.0
+
--- /dev/null
+From 1c9089c867fac0beefc1ab3cea9605ff8a841af8 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 4 Jul 2023 11:32:17 +0200
+Subject: PM / devfreq: rockchip-dfi: Make pmu regmap mandatory
+
+From: Sascha Hauer <s.hauer@pengutronix.de>
+
+[ Upstream commit 1e0731c05c985deb68a97fa44c1adcd3305dda90 ]
+
+As a matter of fact the regmap_pmu already is mandatory because
+it is used unconditionally in the driver. Bail out gracefully in
+probe() rather than crashing later.
+
+Link: https://lore.kernel.org/lkml/20230704093242.583575-2-s.hauer@pengutronix.de/
+Fixes: b9d1262bca0af ("PM / devfreq: event: support rockchip dfi controller")
+Reviewed-by: Sebastian Reichel <sebastian.reichel@collabora.com>
+Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
+Signed-off-by: Chanwoo Choi <cw00.choi@samsung.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/devfreq/event/rockchip-dfi.c | 15 ++++++++-------
+ 1 file changed, 8 insertions(+), 7 deletions(-)
+
+diff --git a/drivers/devfreq/event/rockchip-dfi.c b/drivers/devfreq/event/rockchip-dfi.c
+index 9a88faaf8b27f..4dafdf23197b9 100644
+--- a/drivers/devfreq/event/rockchip-dfi.c
++++ b/drivers/devfreq/event/rockchip-dfi.c
+@@ -194,14 +194,15 @@ static int rockchip_dfi_probe(struct platform_device *pdev)
+ return PTR_ERR(data->clk);
+ }
+
+- /* try to find the optional reference to the pmu syscon */
+ node = of_parse_phandle(np, "rockchip,pmu", 0);
+- if (node) {
+- data->regmap_pmu = syscon_node_to_regmap(node);
+- of_node_put(node);
+- if (IS_ERR(data->regmap_pmu))
+- return PTR_ERR(data->regmap_pmu);
+- }
++ if (!node)
++ return dev_err_probe(&pdev->dev, -ENODEV, "Can't find pmu_grf registers\n");
++
++ data->regmap_pmu = syscon_node_to_regmap(node);
++ of_node_put(node);
++ if (IS_ERR(data->regmap_pmu))
++ return PTR_ERR(data->regmap_pmu);
++
+ data->dev = dev;
+
+ desc = devm_kzalloc(dev, sizeof(*desc), GFP_KERNEL);
+--
+2.42.0
+
--- /dev/null
+From 041abb3e9fbef36ac40e41310f0e314e42877c2b Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 25 Sep 2023 20:31:17 +0200
+Subject: powerpc/40x: Remove stale PTE_ATOMIC_UPDATES macro
+
+From: Christophe Leroy <christophe.leroy@csgroup.eu>
+
+[ Upstream commit cc8ee288f484a2a59c01ccd4d8a417d6ed3466e3 ]
+
+40x TLB handlers were reworked by commit 2c74e2586bb9 ("powerpc/40x:
+Rework 40x PTE access and TLB miss") to not require PTE_ATOMIC_UPDATES
+anymore.
+
+Then commit 4e1df545e2fa ("powerpc/pgtable: Drop PTE_ATOMIC_UPDATES")
+removed all code related to PTE_ATOMIC_UPDATES.
+
+Remove left over PTE_ATOMIC_UPDATES macro.
+
+Fixes: 2c74e2586bb9 ("powerpc/40x: Rework 40x PTE access and TLB miss")
+Signed-off-by: Christophe Leroy <christophe.leroy@csgroup.eu>
+Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
+Link: https://msgid.link/f061db5857fcd748f84a6707aad01754686ce97e.1695659959.git.christophe.leroy@csgroup.eu
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ arch/powerpc/include/asm/nohash/32/pte-40x.h | 3 ---
+ 1 file changed, 3 deletions(-)
+
+diff --git a/arch/powerpc/include/asm/nohash/32/pte-40x.h b/arch/powerpc/include/asm/nohash/32/pte-40x.h
+index 2d3153cfc0d79..acf61242e85bf 100644
+--- a/arch/powerpc/include/asm/nohash/32/pte-40x.h
++++ b/arch/powerpc/include/asm/nohash/32/pte-40x.h
+@@ -69,9 +69,6 @@
+
+ #define _PTE_NONE_MASK 0
+
+-/* Until my rework is finished, 40x still needs atomic PTE updates */
+-#define PTE_ATOMIC_UPDATES 1
+-
+ #define _PAGE_BASE_NC (_PAGE_PRESENT | _PAGE_ACCESSED)
+ #define _PAGE_BASE (_PAGE_BASE_NC)
+
+--
+2.42.0
+
--- /dev/null
+From 8b52563e4794fb7f023064d62286db1297877a22 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 9 Mar 2023 14:48:31 +0100
+Subject: powerpc/imc-pmu: Use the correct spinlock initializer.
+
+From: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
+
+[ Upstream commit 007240d59c11f87ac4f6cfc6a1d116630b6b634c ]
+
+The macro __SPIN_LOCK_INITIALIZER() is implementation specific. Users
+that desire to initialize a spinlock in a struct must use
+__SPIN_LOCK_UNLOCKED().
+
+Use __SPIN_LOCK_UNLOCKED() for the spinlock_t in imc_global_refc.
+
+Fixes: 76d588dddc459 ("powerpc/imc-pmu: Fix use of mutex in IRQs disabled section")
+Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
+Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
+Link: https://msgid.link/20230309134831.Nz12nqsU@linutronix.de
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ arch/powerpc/perf/imc-pmu.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/arch/powerpc/perf/imc-pmu.c b/arch/powerpc/perf/imc-pmu.c
+index b8a100b9736c7..55a853edc3bea 100644
+--- a/arch/powerpc/perf/imc-pmu.c
++++ b/arch/powerpc/perf/imc-pmu.c
+@@ -50,7 +50,7 @@ static int trace_imc_mem_size;
+ * core and trace-imc
+ */
+ static struct imc_pmu_ref imc_global_refc = {
+- .lock = __SPIN_LOCK_INITIALIZER(imc_global_refc.lock),
++ .lock = __SPIN_LOCK_UNLOCKED(imc_global_refc.lock),
+ .id = 0,
+ .refc = 0,
+ };
+--
+2.42.0
+
--- /dev/null
+From c94bb87ef35f6796772323a3d7c40b2018ee1823 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 22 Sep 2023 14:33:13 +0200
+Subject: powerpc: Only define __parse_fpscr() when required
+
+From: Christophe Leroy <christophe.leroy@csgroup.eu>
+
+[ Upstream commit c7e0d9bb9154c6e6b2ac8746faba27b53393f25e ]
+
+Clang 17 reports:
+
+arch/powerpc/kernel/traps.c:1167:19: error: unused function '__parse_fpscr' [-Werror,-Wunused-function]
+
+__parse_fpscr() is called from two sites. First call is guarded
+by #ifdef CONFIG_PPC_FPU_REGS
+
+Second call is guarded by CONFIG_MATH_EMULATION which selects
+CONFIG_PPC_FPU_REGS.
+
+So only define __parse_fpscr() when CONFIG_PPC_FPU_REGS is defined.
+
+Reported-by: kernel test robot <lkp@intel.com>
+Closes: https://lore.kernel.org/oe-kbuild-all/202309210327.WkqSd5Bq-lkp@intel.com/
+Fixes: b6254ced4da6 ("powerpc/signal: Don't manage floating point regs when no FPU")
+Signed-off-by: Christophe Leroy <christophe.leroy@csgroup.eu>
+Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
+Link: https://msgid.link/5de2998c57f3983563b27b39228ea9a7229d4110.1695385984.git.christophe.leroy@csgroup.eu
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ arch/powerpc/kernel/traps.c | 2 ++
+ 1 file changed, 2 insertions(+)
+
+diff --git a/arch/powerpc/kernel/traps.c b/arch/powerpc/kernel/traps.c
+index a08bb7cefdc54..fe912983ced96 100644
+--- a/arch/powerpc/kernel/traps.c
++++ b/arch/powerpc/kernel/traps.c
+@@ -1148,6 +1148,7 @@ static void emulate_single_step(struct pt_regs *regs)
+ __single_step_exception(regs);
+ }
+
++#ifdef CONFIG_PPC_FPU_REGS
+ static inline int __parse_fpscr(unsigned long fpscr)
+ {
+ int ret = FPE_FLTUNK;
+@@ -1174,6 +1175,7 @@ static inline int __parse_fpscr(unsigned long fpscr)
+
+ return ret;
+ }
++#endif
+
+ static void parse_fpe(struct pt_regs *regs)
+ {
+--
+2.42.0
+
--- /dev/null
+From 50d3fd64250fa8af779b91a74d3b826f34fea471 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 14 Dec 2022 15:46:23 +0800
+Subject: powerpc/pseries: fix potential memory leak in
+ init_cpu_associativity()
+
+From: Wang Yufen <wangyufen@huawei.com>
+
+[ Upstream commit 95f1a128cd728a7257d78e868f1f5a145fc43736 ]
+
+If the vcpu_associativity alloc memory successfully but the
+pcpu_associativity fails to alloc memory, the vcpu_associativity
+memory leaks.
+
+Fixes: d62c8deeb6e6 ("powerpc/pseries: Provide vcpu dispatch statistics")
+Signed-off-by: Wang Yufen <wangyufen@huawei.com>
+Reviewed-by: "Naveen N. Rao" <naveen.n.rao@linux.vnet.ibm.com>
+Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
+Link: https://msgid.link/1671003983-10794-1-git-send-email-wangyufen@huawei.com
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ arch/powerpc/platforms/pseries/lpar.c | 4 +++-
+ 1 file changed, 3 insertions(+), 1 deletion(-)
+
+diff --git a/arch/powerpc/platforms/pseries/lpar.c b/arch/powerpc/platforms/pseries/lpar.c
+index d133597a84ca0..fce0237b07155 100644
+--- a/arch/powerpc/platforms/pseries/lpar.c
++++ b/arch/powerpc/platforms/pseries/lpar.c
+@@ -524,8 +524,10 @@ static ssize_t vcpudispatch_stats_write(struct file *file, const char __user *p,
+
+ if (cmd) {
+ rc = init_cpu_associativity();
+- if (rc)
++ if (rc) {
++ destroy_cpu_associativity();
+ goto out;
++ }
+
+ for_each_possible_cpu(cpu) {
+ disp = per_cpu_ptr(&vcpu_disp_data, cpu);
+--
+2.42.0
+
--- /dev/null
+From 607f3f59c5816b3d7b64f7794ba42661b5c2adcf Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 11 Oct 2023 16:37:00 +1100
+Subject: powerpc/xive: Fix endian conversion size
+
+From: Benjamin Gray <bgray@linux.ibm.com>
+
+[ Upstream commit ff7a60ab1e065257a0e467c13b519f4debcd7fcf ]
+
+Sparse reports a size mismatch in the endian swap. The Opal
+implementation[1] passes the value as a __be64, and the receiving
+variable out_qsize is a u64, so the use of be32_to_cpu() appears to be
+an error.
+
+[1]: https://github.com/open-power/skiboot/blob/80e2b1dc73/hw/xive.c#L3854
+
+Fixes: 88ec6b93c8e7 ("powerpc/xive: add OPAL extensions for the XIVE native exploitation support")
+Signed-off-by: Benjamin Gray <bgray@linux.ibm.com>
+Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
+Link: https://msgid.link/20231011053711.93427-2-bgray@linux.ibm.com
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ arch/powerpc/sysdev/xive/native.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/arch/powerpc/sysdev/xive/native.c b/arch/powerpc/sysdev/xive/native.c
+index 1aec282cd650d..b6323bdecfa4c 100644
+--- a/arch/powerpc/sysdev/xive/native.c
++++ b/arch/powerpc/sysdev/xive/native.c
+@@ -786,7 +786,7 @@ int xive_native_get_queue_info(u32 vp_id, u32 prio,
+ if (out_qpage)
+ *out_qpage = be64_to_cpu(qpage);
+ if (out_qsize)
+- *out_qsize = be32_to_cpu(qsize);
++ *out_qsize = be64_to_cpu(qsize);
+ if (out_qeoi_page)
+ *out_qeoi_page = be64_to_cpu(qeoi_page);
+ if (out_escalate_irq)
+--
+2.42.0
+
--- /dev/null
+From e384beef309da2c7d0e211f19129261e8759337a Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 23 Jun 2023 10:27:06 +0800
+Subject: pstore/platform: Add check for kstrdup
+
+From: Jiasheng Jiang <jiasheng@iscas.ac.cn>
+
+[ Upstream commit a19d48f7c5d57c0f0405a7d4334d1d38fe9d3c1c ]
+
+Add check for the return value of kstrdup() and return the error
+if it fails in order to avoid NULL pointer dereference.
+
+Fixes: 563ca40ddf40 ("pstore/platform: Switch pstore_info::name to const")
+Signed-off-by: Jiasheng Jiang <jiasheng@iscas.ac.cn>
+Link: https://lore.kernel.org/r/20230623022706.32125-1-jiasheng@iscas.ac.cn
+Signed-off-by: Kees Cook <keescook@chromium.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ fs/pstore/platform.c | 9 ++++++++-
+ 1 file changed, 8 insertions(+), 1 deletion(-)
+
+diff --git a/fs/pstore/platform.c b/fs/pstore/platform.c
+index ad96ba97d8f97..3fc4739f82d86 100644
+--- a/fs/pstore/platform.c
++++ b/fs/pstore/platform.c
+@@ -561,6 +561,8 @@ static int pstore_write_user_compat(struct pstore_record *record,
+ */
+ int pstore_register(struct pstore_info *psi)
+ {
++ char *new_backend;
++
+ if (backend && strcmp(backend, psi->name)) {
+ pr_warn("ignoring unexpected backend '%s'\n", psi->name);
+ return -EPERM;
+@@ -580,11 +582,16 @@ int pstore_register(struct pstore_info *psi)
+ return -EINVAL;
+ }
+
++ new_backend = kstrdup(psi->name, GFP_KERNEL);
++ if (!new_backend)
++ return -ENOMEM;
++
+ mutex_lock(&psinfo_lock);
+ if (psinfo) {
+ pr_warn("backend '%s' already loaded: ignoring '%s'\n",
+ psinfo->name, psi->name);
+ mutex_unlock(&psinfo_lock);
++ kfree(new_backend);
+ return -EBUSY;
+ }
+
+@@ -617,7 +624,7 @@ int pstore_register(struct pstore_info *psi)
+ * Update the module parameter backend, so it is visible
+ * through /sys/module/pstore/parameters/backend
+ */
+- backend = kstrdup(psi->name, GFP_KERNEL);
++ backend = new_backend;
+
+ pr_info("Registered %s as persistent store backend\n", psi->name);
+
+--
+2.42.0
+
--- /dev/null
+From 9fa06c0e8bfa31ac60ee8edb31ec9ad07818f456 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 12 Oct 2023 08:51:13 +0200
+Subject: r8169: fix rare issue with broken rx after link-down on RTL8125
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Heiner Kallweit <hkallweit1@gmail.com>
+
+[ Upstream commit 621735f590643e3048ca2060c285b80551660601 ]
+
+In very rare cases (I've seen two reports so far about different
+RTL8125 chip versions) it seems the MAC locks up when link goes down
+and requires a software reset to get revived.
+Realtek doesn't publish hw errata information, therefore the root cause
+is unknown. Realtek vendor drivers do a full hw re-initialization on
+each link-up event, the slimmed-down variant here was reported to fix
+the issue for the reporting user.
+It's not fully clear which parts of the NIC are reset as part of the
+software reset, therefore I can't rule out side effects.
+
+Fixes: f1bce4ad2f1c ("r8169: add support for RTL8125")
+Reported-by: Martin Kjær Jørgensen <me@lagy.org>
+Link: https://lore.kernel.org/netdev/97ec2232-3257-316c-c3e7-a08192ce16a6@gmail.com/T/
+Signed-off-by: Heiner Kallweit <hkallweit1@gmail.com>
+Link: https://lore.kernel.org/r/9edde757-9c3b-4730-be3b-0ef3a374ff71@gmail.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/ethernet/realtek/r8169_main.c | 4 ++++
+ 1 file changed, 4 insertions(+)
+
+diff --git a/drivers/net/ethernet/realtek/r8169_main.c b/drivers/net/ethernet/realtek/r8169_main.c
+index 73bbcb72cf3f0..ab84c623a7c62 100644
+--- a/drivers/net/ethernet/realtek/r8169_main.c
++++ b/drivers/net/ethernet/realtek/r8169_main.c
+@@ -4661,7 +4661,11 @@ static void r8169_phylink_handler(struct net_device *ndev)
+ if (netif_carrier_ok(ndev)) {
+ rtl_link_chg_patch(tp);
+ pm_request_resume(d);
++ netif_wake_queue(tp->dev);
+ } else {
++ /* In few cases rx is broken after link-down otherwise */
++ if (rtl_is_8125(tp))
++ rtl_reset_work(tp);
+ pm_runtime_idle(d);
+ }
+
+--
+2.42.0
+
--- /dev/null
+From b69734d3fae7bdfdca28a40866231859f293fba2 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 30 Nov 2022 01:12:44 +0900
+Subject: r8169: use tp_to_dev instead of open code
+
+From: Juhee Kang <claudiajkang@gmail.com>
+
+[ Upstream commit 4b6c6065fca123d419afef005a696f51e6590470 ]
+
+The open code is defined as a helper function(tp_to_dev) on r8169_main.c,
+which the open code is &tp->pci_dev->dev. The helper function was added
+in commit 1e1205b7d3e9 ("r8169: add helper tp_to_dev"). And then later,
+commit f1e911d5d0df ("r8169: add basic phylib support") added
+r8169_phylink_handler function but it didn't use the helper function.
+Thus, tp_to_dev() replaces the open code. This patch doesn't change logic.
+
+Signed-off-by: Juhee Kang <claudiajkang@gmail.com>
+Reviewed-by: Heiner Kallweit <hkallweit1@gmail.com>
+Link: https://lore.kernel.org/r/20221129161244.5356-1-claudiajkang@gmail.com
+Signed-off-by: Paolo Abeni <pabeni@redhat.com>
+Stable-dep-of: 621735f59064 ("r8169: fix rare issue with broken rx after link-down on RTL8125")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/ethernet/realtek/r8169_main.c | 5 +++--
+ 1 file changed, 3 insertions(+), 2 deletions(-)
+
+diff --git a/drivers/net/ethernet/realtek/r8169_main.c b/drivers/net/ethernet/realtek/r8169_main.c
+index 1cd0928472c0c..73bbcb72cf3f0 100644
+--- a/drivers/net/ethernet/realtek/r8169_main.c
++++ b/drivers/net/ethernet/realtek/r8169_main.c
+@@ -4656,12 +4656,13 @@ static int rtl8169_poll(struct napi_struct *napi, int budget)
+ static void r8169_phylink_handler(struct net_device *ndev)
+ {
+ struct rtl8169_private *tp = netdev_priv(ndev);
++ struct device *d = tp_to_dev(tp);
+
+ if (netif_carrier_ok(ndev)) {
+ rtl_link_chg_patch(tp);
+- pm_request_resume(&tp->pci_dev->dev);
++ pm_request_resume(d);
+ } else {
+- pm_runtime_idle(&tp->pci_dev->dev);
++ pm_runtime_idle(d);
+ }
+
+ if (net_ratelimit())
+--
+2.42.0
+
--- /dev/null
+From 4194d26e5a49ffb3de4f8a8481a1784ad1e96e82 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sun, 17 Sep 2023 15:21:36 -0600
+Subject: RDMA/core: Use size_{add,sub,mul}() in calls to struct_size()
+
+From: Gustavo A. R. Silva <gustavoars@kernel.org>
+
+[ Upstream commit 81760bedc65194ff38e1e4faefd5f9f0c95c19a4 ]
+
+If, for any reason, the open-coded arithmetic causes a wraparound,
+the protection that `struct_size()` provides against potential integer
+overflows is defeated. Fix this by hardening calls to `struct_size()`
+with `size_add()`, `size_sub()` and `size_mul()`.
+
+Fixes: 467f432a521a ("RDMA/core: Split port and device counter sysfs attributes")
+Fixes: a4676388e2e2 ("RDMA/core: Simplify how the gid_attrs sysfs is created")
+Fixes: e9dd5daf884c ("IB/umad: Refactor code to use cdev_device_add()")
+Fixes: 324e227ea7c9 ("RDMA/device: Add ib_device_get_by_netdev()")
+Fixes: 5aad26a7eac5 ("IB/core: Use struct_size() in kzalloc()")
+Signed-off-by: Gustavo A. R. Silva <gustavoars@kernel.org>
+Link: https://lore.kernel.org/r/ZQdt4NsJFwwOYxUR@work
+Signed-off-by: Leon Romanovsky <leon@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/infiniband/core/device.c | 2 +-
+ drivers/infiniband/core/sa_query.c | 4 +++-
+ drivers/infiniband/core/sysfs.c | 10 +++++-----
+ drivers/infiniband/core/user_mad.c | 4 +++-
+ 4 files changed, 12 insertions(+), 8 deletions(-)
+
+diff --git a/drivers/infiniband/core/device.c b/drivers/infiniband/core/device.c
+index ab2106a09f9c6..2c2ac63b39c42 100644
+--- a/drivers/infiniband/core/device.c
++++ b/drivers/infiniband/core/device.c
+@@ -803,7 +803,7 @@ static int alloc_port_data(struct ib_device *device)
+ * empty slots at the beginning.
+ */
+ pdata_rcu = kzalloc(struct_size(pdata_rcu, pdata,
+- rdma_end_port(device) + 1),
++ size_add(rdma_end_port(device), 1)),
+ GFP_KERNEL);
+ if (!pdata_rcu)
+ return -ENOMEM;
+diff --git a/drivers/infiniband/core/sa_query.c b/drivers/infiniband/core/sa_query.c
+index c00f8e28aab75..1557c71dd152f 100644
+--- a/drivers/infiniband/core/sa_query.c
++++ b/drivers/infiniband/core/sa_query.c
+@@ -2132,7 +2132,9 @@ static int ib_sa_add_one(struct ib_device *device)
+ s = rdma_start_port(device);
+ e = rdma_end_port(device);
+
+- sa_dev = kzalloc(struct_size(sa_dev, port, e - s + 1), GFP_KERNEL);
++ sa_dev = kzalloc(struct_size(sa_dev, port,
++ size_add(size_sub(e, s), 1)),
++ GFP_KERNEL);
+ if (!sa_dev)
+ return -ENOMEM;
+
+diff --git a/drivers/infiniband/core/sysfs.c b/drivers/infiniband/core/sysfs.c
+index 253ccaf343f69..afc59048c40c8 100644
+--- a/drivers/infiniband/core/sysfs.c
++++ b/drivers/infiniband/core/sysfs.c
+@@ -902,7 +902,7 @@ alloc_hw_stats_device(struct ib_device *ibdev)
+ * Two extra attribue elements here, one for the lifespan entry and
+ * one to NULL terminate the list for the sysfs core code
+ */
+- data = kzalloc(struct_size(data, attrs, stats->num_counters + 1),
++ data = kzalloc(struct_size(data, attrs, size_add(stats->num_counters, 1)),
+ GFP_KERNEL);
+ if (!data)
+ goto err_free_stats;
+@@ -1001,7 +1001,7 @@ alloc_hw_stats_port(struct ib_port *port, struct attribute_group *group)
+ * Two extra attribue elements here, one for the lifespan entry and
+ * one to NULL terminate the list for the sysfs core code
+ */
+- data = kzalloc(struct_size(data, attrs, stats->num_counters + 1),
++ data = kzalloc(struct_size(data, attrs, size_add(stats->num_counters, 1)),
+ GFP_KERNEL);
+ if (!data)
+ goto err_free_stats;
+@@ -1125,7 +1125,7 @@ static int setup_gid_attrs(struct ib_port *port,
+ int ret;
+
+ gid_attr_group = kzalloc(struct_size(gid_attr_group, attrs_list,
+- attr->gid_tbl_len * 2),
++ size_mul(attr->gid_tbl_len, 2)),
+ GFP_KERNEL);
+ if (!gid_attr_group)
+ return -ENOMEM;
+@@ -1190,8 +1190,8 @@ static struct ib_port *setup_port(struct ib_core_device *coredev, int port_num,
+ int ret;
+
+ p = kvzalloc(struct_size(p, attrs_list,
+- attr->gid_tbl_len + attr->pkey_tbl_len),
+- GFP_KERNEL);
++ size_add(attr->gid_tbl_len, attr->pkey_tbl_len)),
++ GFP_KERNEL);
+ if (!p)
+ return ERR_PTR(-ENOMEM);
+ p->ibdev = device;
+diff --git a/drivers/infiniband/core/user_mad.c b/drivers/infiniband/core/user_mad.c
+index a61c9ede43387..5c284dfbe6923 100644
+--- a/drivers/infiniband/core/user_mad.c
++++ b/drivers/infiniband/core/user_mad.c
+@@ -1378,7 +1378,9 @@ static int ib_umad_add_one(struct ib_device *device)
+ s = rdma_start_port(device);
+ e = rdma_end_port(device);
+
+- umad_dev = kzalloc(struct_size(umad_dev, ports, e - s + 1), GFP_KERNEL);
++ umad_dev = kzalloc(struct_size(umad_dev, ports,
++ size_add(size_sub(e, s), 1)),
++ GFP_KERNEL);
+ if (!umad_dev)
+ return -ENOMEM;
+
+--
+2.42.0
+
--- /dev/null
+From afedc1e5f9e5e434fc0aa45cb5d1e0a38dff95aa Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 24 Oct 2023 18:07:31 +0300
+Subject: RDMA/hfi1: Workaround truncation compilation error
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Leon Romanovsky <leonro@nvidia.com>
+
+[ Upstream commit d4b2d165714c0ce8777d5131f6e0aad617b7adc4 ]
+
+Increase name array to be large enough to overcome the following
+compilation error.
+
+drivers/infiniband/hw/hfi1/efivar.c: In function ‘read_hfi1_efi_var’:
+drivers/infiniband/hw/hfi1/efivar.c:124:44: error: ‘snprintf’ output may be truncated before the last format character [-Werror=format-truncation=]
+ 124 | snprintf(name, sizeof(name), "%s-%s", prefix_name, kind);
+ | ^
+drivers/infiniband/hw/hfi1/efivar.c:124:9: note: ‘snprintf’ output 2 or more bytes (assuming 65) into a destination of size 64
+ 124 | snprintf(name, sizeof(name), "%s-%s", prefix_name, kind);
+ | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+drivers/infiniband/hw/hfi1/efivar.c:133:52: error: ‘snprintf’ output may be truncated before the last format character [-Werror=format-truncation=]
+ 133 | snprintf(name, sizeof(name), "%s-%s", prefix_name, kind);
+ | ^
+drivers/infiniband/hw/hfi1/efivar.c:133:17: note: ‘snprintf’ output 2 or more bytes (assuming 65) into a destination of size 64
+ 133 | snprintf(name, sizeof(name), "%s-%s", prefix_name, kind);
+ | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+cc1: all warnings being treated as errors
+make[6]: *** [scripts/Makefile.build:243: drivers/infiniband/hw/hfi1/efivar.o] Error 1
+
+Fixes: c03c08d50b3d ("IB/hfi1: Check upper-case EFI variables")
+Signed-off-by: Leon Romanovsky <leonro@nvidia.com>
+Link: https://lore.kernel.org/r/238fa39a8fd60e87a5ad7e1ca6584fcdf32e9519.1698159993.git.leonro@nvidia.com
+Acked-by: Dennis Dalessandro <dennis.dalessandro@cornelisnetworks.com>
+Signed-off-by: Leon Romanovsky <leon@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/infiniband/hw/hfi1/efivar.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/drivers/infiniband/hw/hfi1/efivar.c b/drivers/infiniband/hw/hfi1/efivar.c
+index f275dd1abed85..7a3caf2cd9071 100644
+--- a/drivers/infiniband/hw/hfi1/efivar.c
++++ b/drivers/infiniband/hw/hfi1/efivar.c
+@@ -110,7 +110,7 @@ int read_hfi1_efi_var(struct hfi1_devdata *dd, const char *kind,
+ unsigned long *size, void **return_data)
+ {
+ char prefix_name[64];
+- char name[64];
++ char name[128];
+ int result;
+ int i;
+
+--
+2.42.0
+
--- /dev/null
+From 20217d7520a0d288a89595dbb3afa32221ac8ae3 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 17 Oct 2023 20:52:35 +0800
+Subject: RDMA/hns: Fix signed-unsigned mixed comparisons
+
+From: Chengchang Tang <tangchengchang@huawei.com>
+
+[ Upstream commit b5f9efff101b06fd06a5e280a2b00b1335f5f476 ]
+
+The ib_mtu_enum_to_int() and uverbs_attr_get_len() may returns a negative
+value. In this case, mixed comparisons of signed and unsigned types will
+throw wrong results.
+
+This patch adds judgement for this situation.
+
+Fixes: 30b707886aeb ("RDMA/hns: Support inline data in extented sge space for RC")
+Signed-off-by: Chengchang Tang <tangchengchang@huawei.com>
+Signed-off-by: Junxian Huang <huangjunxian6@hisilicon.com>
+Link: https://lore.kernel.org/r/20231017125239.164455-4-huangjunxian6@hisilicon.com
+Signed-off-by: Leon Romanovsky <leon@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/infiniband/hw/hns/hns_roce_hw_v2.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/drivers/infiniband/hw/hns/hns_roce_hw_v2.c b/drivers/infiniband/hw/hns/hns_roce_hw_v2.c
+index 4554d3e78b37b..59e1f51022f16 100644
+--- a/drivers/infiniband/hw/hns/hns_roce_hw_v2.c
++++ b/drivers/infiniband/hw/hns/hns_roce_hw_v2.c
+@@ -244,7 +244,7 @@ static bool check_inl_data_len(struct hns_roce_qp *qp, unsigned int len)
+ struct hns_roce_dev *hr_dev = to_hr_dev(qp->ibqp.device);
+ int mtu = ib_mtu_enum_to_int(qp->path_mtu);
+
+- if (len > qp->max_inline_data || len > mtu) {
++ if (mtu < 0 || len > qp->max_inline_data || len > mtu) {
+ ibdev_err(&hr_dev->ib_dev,
+ "invalid length of data, data len = %u, max inline len = %u, path mtu = %d.\n",
+ len, qp->max_inline_data, mtu);
+--
+2.42.0
+
--- /dev/null
+From 17a4849ae3a46872333e77a4ac26d307221ec7e0 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 17 Oct 2023 20:52:34 +0800
+Subject: RDMA/hns: Fix uninitialized ucmd in hns_roce_create_qp_common()
+
+From: Chengchang Tang <tangchengchang@huawei.com>
+
+[ Upstream commit c64e9710f9241e38a1c761ed1c1a30854784da66 ]
+
+ucmd in hns_roce_create_qp_common() are not initialized. But it works fine
+until new member sdb_addr is added to struct hns_roce_ib_create_qp.
+
+If the user-mode driver uses an old version ABI, then the value of the new
+member will be undefined after ib_copy_from_udata().
+
+This patch fixes it by initialize this variable to 0. And the default value
+of the new member sdb_addr will be 0 which is invalid.
+
+Fixes: 0425e3e6e0c7 ("RDMA/hns: Support flush cqe for hip08 in kernel space")
+Signed-off-by: Chengchang Tang <tangchengchang@huawei.com>
+Signed-off-by: Junxian Huang <huangjunxian6@hisilicon.com>
+Link: https://lore.kernel.org/r/20231017125239.164455-3-huangjunxian6@hisilicon.com
+Signed-off-by: Leon Romanovsky <leon@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/infiniband/hw/hns/hns_roce_qp.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/drivers/infiniband/hw/hns/hns_roce_qp.c b/drivers/infiniband/hw/hns/hns_roce_qp.c
+index 00dade1cfff20..d085998b19c87 100644
+--- a/drivers/infiniband/hw/hns/hns_roce_qp.c
++++ b/drivers/infiniband/hw/hns/hns_roce_qp.c
+@@ -1049,7 +1049,7 @@ static int hns_roce_create_qp_common(struct hns_roce_dev *hr_dev,
+ {
+ struct hns_roce_ib_create_qp_resp resp = {};
+ struct ib_device *ibdev = &hr_dev->ib_dev;
+- struct hns_roce_ib_create_qp ucmd;
++ struct hns_roce_ib_create_qp ucmd = {};
+ int ret;
+
+ mutex_init(&hr_qp->mutex);
+--
+2.42.0
+
--- /dev/null
+From c5b784263a978e49b65607bbc0a7dae4c333469b Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 17 Oct 2023 20:52:37 +0800
+Subject: RDMA/hns: The UD mode can only be configured with DCQCN
+
+From: Luoyouming <luoyouming@huawei.com>
+
+[ Upstream commit 27c5fd271d8b8730fc0bb1b6cae953ad7808a874 ]
+
+Due to hardware limitations, only DCQCN is supported for UD. Therefore, the
+default algorithm for UD is set to DCQCN.
+
+Fixes: f91696f2f053 ("RDMA/hns: Support congestion control type selection according to the FW")
+Signed-off-by: Luoyouming <luoyouming@huawei.com>
+Signed-off-by: Junxian Huang <huangjunxian6@hisilicon.com>
+Link: https://lore.kernel.org/r/20231017125239.164455-6-huangjunxian6@hisilicon.com
+Signed-off-by: Leon Romanovsky <leon@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/infiniband/hw/hns/hns_roce_hw_v2.c | 3 +++
+ 1 file changed, 3 insertions(+)
+
+diff --git a/drivers/infiniband/hw/hns/hns_roce_hw_v2.c b/drivers/infiniband/hw/hns/hns_roce_hw_v2.c
+index 59e1f51022f16..f034021f3adc1 100644
+--- a/drivers/infiniband/hw/hns/hns_roce_hw_v2.c
++++ b/drivers/infiniband/hw/hns/hns_roce_hw_v2.c
+@@ -4556,6 +4556,9 @@ static int check_cong_type(struct ib_qp *ibqp,
+ {
+ struct hns_roce_dev *hr_dev = to_hr_dev(ibqp->device);
+
++ if (ibqp->qp_type == IB_QPT_UD)
++ hr_dev->caps.cong_type = CONG_TYPE_DCQCN;
++
+ /* different congestion types match different configurations */
+ switch (hr_dev->caps.cong_type) {
+ case CONG_TYPE_DCQCN:
+--
+2.42.0
+
--- /dev/null
+From beed7db9fb4538c34ca371d7ff5c1f0b733a1349 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 4 Sep 2023 22:04:06 +0200
+Subject: regmap: debugfs: Fix a erroneous check after snprintf()
+
+From: Christophe JAILLET <christophe.jaillet@wanadoo.fr>
+
+[ Upstream commit d3601857e14de6369f00ae19564f1d817d175d19 ]
+
+This error handling looks really strange.
+Check if the string has been truncated instead.
+
+Fixes: f0c2319f9f19 ("regmap: Expose the driver name in debugfs")
+Signed-off-by: Christophe JAILLET <christophe.jaillet@wanadoo.fr>
+Link: https://lore.kernel.org/r/8595de2462c490561f70020a6d11f4d6b652b468.1693857825.git.christophe.jaillet@wanadoo.fr
+Signed-off-by: Mark Brown <broonie@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/base/regmap/regmap-debugfs.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/drivers/base/regmap/regmap-debugfs.c b/drivers/base/regmap/regmap-debugfs.c
+index ad684d37c2dae..6caed4b556365 100644
+--- a/drivers/base/regmap/regmap-debugfs.c
++++ b/drivers/base/regmap/regmap-debugfs.c
+@@ -48,7 +48,7 @@ static ssize_t regmap_name_read_file(struct file *file,
+ name = map->dev->driver->name;
+
+ ret = snprintf(buf, PAGE_SIZE, "%s\n", name);
+- if (ret < 0) {
++ if (ret >= PAGE_SIZE) {
+ kfree(buf);
+ return ret;
+ }
+--
+2.42.0
+
--- /dev/null
+From 2f7d595cf67e4d2d02e08939cdfa2564978c5685 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 1 Nov 2023 10:29:27 -0400
+Subject: regmap: prevent noinc writes from clobbering cache
+
+From: Ben Wolsieffer <ben.wolsieffer@hefring.com>
+
+[ Upstream commit 984a4afdc87a1fc226fd657b1cd8255c13d3fc1a ]
+
+Currently, noinc writes are cached as if they were standard incrementing
+writes, overwriting unrelated register values in the cache. Instead, we
+want to cache the last value written to the register, as is done in the
+accelerated noinc handler (regmap_noinc_readwrite).
+
+Fixes: cdf6b11daa77 ("regmap: Add regmap_noinc_write API")
+Signed-off-by: Ben Wolsieffer <ben.wolsieffer@hefring.com>
+Link: https://lore.kernel.org/r/20231101142926.2722603-2-ben.wolsieffer@hefring.com
+Signed-off-by: Mark Brown <broonie@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/base/regmap/regmap.c | 16 +++++++++-------
+ 1 file changed, 9 insertions(+), 7 deletions(-)
+
+diff --git a/drivers/base/regmap/regmap.c b/drivers/base/regmap/regmap.c
+index 617d51a278497..7621b54975b57 100644
+--- a/drivers/base/regmap/regmap.c
++++ b/drivers/base/regmap/regmap.c
+@@ -1683,17 +1683,19 @@ static int _regmap_raw_write_impl(struct regmap *map, unsigned int reg,
+ }
+
+ if (!map->cache_bypass && map->format.parse_val) {
+- unsigned int ival;
++ unsigned int ival, offset;
+ int val_bytes = map->format.val_bytes;
+- for (i = 0; i < val_len / val_bytes; i++) {
+- ival = map->format.parse_val(val + (i * val_bytes));
+- ret = regcache_write(map,
+- reg + regmap_get_offset(map, i),
+- ival);
++
++ /* Cache the last written value for noinc writes */
++ i = noinc ? val_len - val_bytes : 0;
++ for (; i < val_len; i += val_bytes) {
++ ival = map->format.parse_val(val + i);
++ offset = noinc ? 0 : regmap_get_offset(map, i / val_bytes);
++ ret = regcache_write(map, reg + offset, ival);
+ if (ret) {
+ dev_err(map->dev,
+ "Error in caching of register: %x ret: %d\n",
+- reg + regmap_get_offset(map, i), ret);
++ reg + offset, ret);
+ return ret;
+ }
+ }
+--
+2.42.0
+
--- /dev/null
+From 1a2cbb57a00114d1acfdf051523abb3ca0b22e3e Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 20 Dec 2022 16:43:43 +0100
+Subject: Revert "HID: logitech-hidpp: add a module parameter to keep firmware
+ gestures"
+
+From: Bastien Nocera <hadess@hadess.net>
+
+[ Upstream commit cae253d6033da885e71c29c1591b22838a52de76 ]
+
+Now that we're in 2022, and the majority of desktop environments can and
+should support touchpad gestures through libinput, remove the legacy
+module parameter that made it possible to use gestures implemented in
+firmware.
+
+This will eventually allow simplifying the driver's initialisation code.
+
+This reverts commit 9188dbaed68a4b23dc96eba165265c08caa7dc2a.
+
+Signed-off-by: Bastien Nocera <hadess@hadess.net>
+Signed-off-by: Benjamin Tissoires <benjamin.tissoires@redhat.com>
+Link: https://lore.kernel.org/r/20221220154345.474596-1-hadess@hadess.net
+Stable-dep-of: 11ca0322a419 ("HID: logitech-hidpp: Don't restart IO, instead defer hid_connect() only")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/hid/hid-logitech-hidpp.c | 10 ----------
+ 1 file changed, 10 deletions(-)
+
+diff --git a/drivers/hid/hid-logitech-hidpp.c b/drivers/hid/hid-logitech-hidpp.c
+index 25fa235934880..7681a3fa67dab 100644
+--- a/drivers/hid/hid-logitech-hidpp.c
++++ b/drivers/hid/hid-logitech-hidpp.c
+@@ -31,11 +31,6 @@ MODULE_LICENSE("GPL");
+ MODULE_AUTHOR("Benjamin Tissoires <benjamin.tissoires@gmail.com>");
+ MODULE_AUTHOR("Nestor Lopez Casado <nlopezcasad@logitech.com>");
+
+-static bool disable_raw_mode;
+-module_param(disable_raw_mode, bool, 0644);
+-MODULE_PARM_DESC(disable_raw_mode,
+- "Disable Raw mode reporting for touchpads and keep firmware gestures.");
+-
+ static bool disable_tap_to_click;
+ module_param(disable_tap_to_click, bool, 0644);
+ MODULE_PARM_DESC(disable_tap_to_click,
+@@ -4137,11 +4132,6 @@ static int hidpp_probe(struct hid_device *hdev, const struct hid_device_id *id)
+ hidpp_application_equals(hdev, HID_GD_KEYBOARD))
+ hidpp->quirks |= HIDPP_QUIRK_HIDPP_CONSUMER_VENDOR_KEYS;
+
+- if (disable_raw_mode) {
+- hidpp->quirks &= ~HIDPP_QUIRK_CLASS_WTP;
+- hidpp->quirks &= ~HIDPP_QUIRK_NO_HIDINPUT;
+- }
+-
+ if (hidpp->quirks & HIDPP_QUIRK_CLASS_WTP) {
+ ret = wtp_allocate(hdev, id);
+ if (ret)
+--
+2.42.0
+
--- /dev/null
+From 5e8708a4c644e752b5fe7edda7a5e96864282124 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 13 Oct 2023 16:34:21 +0200
+Subject: rtc: pcf85363: fix wrong mask/val parameters in regmap_update_bits
+ call
+
+From: Javier Carrasco <javier.carrasco.cruz@gmail.com>
+
+[ Upstream commit 2be36c09b6b07306be33519e1aa70d2e2a2161bb ]
+
+The current implementation passes PIN_IO_INTA_OUT (2) as a mask and
+PIN_IO_INTAPM (GENMASK(1, 0)) as a value.
+Swap the variables to assign mask and value the right way.
+
+This error was first introduced with the alarm support. For better or
+worse it worked as expected because 0x02 was applied as a mask to 0x03,
+resulting 0x02 anyway. This will of course not work for any other value.
+
+Fixes: e5aac267a10a ("rtc: pcf85363: add alarm support")
+Signed-off-by: Javier Carrasco <javier.carrasco.cruz@gmail.com>
+Link: https://lore.kernel.org/r/20231013-topic-pcf85363_regmap_update_bits-v1-1-c454f016f71f@gmail.com
+Signed-off-by: Alexandre Belloni <alexandre.belloni@bootlin.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/rtc/rtc-pcf85363.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/drivers/rtc/rtc-pcf85363.c b/drivers/rtc/rtc-pcf85363.c
+index bb3e9ba75f6c6..80e3839e1e86a 100644
+--- a/drivers/rtc/rtc-pcf85363.c
++++ b/drivers/rtc/rtc-pcf85363.c
+@@ -403,7 +403,7 @@ static int pcf85363_probe(struct i2c_client *client,
+ if (client->irq > 0) {
+ regmap_write(pcf85363->regmap, CTRL_FLAGS, 0);
+ regmap_update_bits(pcf85363->regmap, CTRL_PIN_IO,
+- PIN_IO_INTA_OUT, PIN_IO_INTAPM);
++ PIN_IO_INTAPM, PIN_IO_INTA_OUT);
+ ret = devm_request_threaded_irq(&client->dev, client->irq,
+ NULL, pcf85363_rtc_handle_irq,
+ IRQF_TRIGGER_LOW | IRQF_ONESHOT,
+--
+2.42.0
+
--- /dev/null
+From 22d4391b5f37f0131cd523bb129bf339f547e629 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 10 Oct 2023 20:57:39 +0200
+Subject: sched: Fix stop_one_cpu_nowait() vs hotplug
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Peter Zijlstra <peterz@infradead.org>
+
+[ Upstream commit f0498d2a54e7966ce23cd7c7ff42c64fa0059b07 ]
+
+Kuyo reported sporadic failures on a sched_setaffinity() vs CPU
+hotplug stress-test -- notably affine_move_task() remains stuck in
+wait_for_completion(), leading to a hung-task detector warning.
+
+Specifically, it was reported that stop_one_cpu_nowait(.fn =
+migration_cpu_stop) returns false -- this stopper is responsible for
+the matching complete().
+
+The race scenario is:
+
+ CPU0 CPU1
+
+ // doing _cpu_down()
+
+ __set_cpus_allowed_ptr()
+ task_rq_lock();
+ takedown_cpu()
+ stop_machine_cpuslocked(take_cpu_down..)
+
+ <PREEMPT: cpu_stopper_thread()
+ MULTI_STOP_PREPARE
+ ...
+ __set_cpus_allowed_ptr_locked()
+ affine_move_task()
+ task_rq_unlock();
+
+ <PREEMPT: cpu_stopper_thread()\>
+ ack_state()
+ MULTI_STOP_RUN
+ take_cpu_down()
+ __cpu_disable();
+ stop_machine_park();
+ stopper->enabled = false;
+ />
+ />
+ stop_one_cpu_nowait(.fn = migration_cpu_stop);
+ if (stopper->enabled) // false!!!
+
+That is, by doing stop_one_cpu_nowait() after dropping rq-lock, the
+stopper thread gets a chance to preempt and allows the cpu-down for
+the target CPU to complete.
+
+OTOH, since stop_one_cpu_nowait() / cpu_stop_queue_work() needs to
+issue a wakeup, it must not be ran under the scheduler locks.
+
+Solve this apparent contradiction by keeping preemption disabled over
+the unlock + queue_stopper combination:
+
+ preempt_disable();
+ task_rq_unlock(...);
+ if (!stop_pending)
+ stop_one_cpu_nowait(...)
+ preempt_enable();
+
+This respects the lock ordering contraints while still avoiding the
+above race. That is, if we find the CPU is online under rq-lock, the
+targeted stop_one_cpu_nowait() must succeed.
+
+Apply this pattern to all similar stop_one_cpu_nowait() invocations.
+
+Fixes: 6d337eab041d ("sched: Fix migrate_disable() vs set_cpus_allowed_ptr()")
+Reported-by: "Kuyo Chang (張建文)" <Kuyo.Chang@mediatek.com>
+Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
+Tested-by: "Kuyo Chang (張建文)" <Kuyo.Chang@mediatek.com>
+Link: https://lkml.kernel.org/r/20231010200442.GA16515@noisy.programming.kicks-ass.net
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ kernel/sched/core.c | 10 ++++++++--
+ kernel/sched/deadline.c | 2 ++
+ kernel/sched/fair.c | 4 +++-
+ kernel/sched/rt.c | 4 ++++
+ 4 files changed, 17 insertions(+), 3 deletions(-)
+
+diff --git a/kernel/sched/core.c b/kernel/sched/core.c
+index 2324b7055260a..25b8ea91168ea 100644
+--- a/kernel/sched/core.c
++++ b/kernel/sched/core.c
+@@ -2377,9 +2377,11 @@ static int migration_cpu_stop(void *data)
+ * it.
+ */
+ WARN_ON_ONCE(!pending->stop_pending);
++ preempt_disable();
+ task_rq_unlock(rq, p, &rf);
+ stop_one_cpu_nowait(task_cpu(p), migration_cpu_stop,
+ &pending->arg, &pending->stop_work);
++ preempt_enable();
+ return 0;
+ }
+ out:
+@@ -2660,12 +2662,13 @@ static int affine_move_task(struct rq *rq, struct task_struct *p, struct rq_flag
+ complete = true;
+ }
+
++ preempt_disable();
+ task_rq_unlock(rq, p, rf);
+-
+ if (push_task) {
+ stop_one_cpu_nowait(rq->cpu, push_cpu_stop,
+ p, &rq->push_work);
+ }
++ preempt_enable();
+
+ if (complete)
+ complete_all(&pending->done);
+@@ -2731,12 +2734,13 @@ static int affine_move_task(struct rq *rq, struct task_struct *p, struct rq_flag
+ if (flags & SCA_MIGRATE_ENABLE)
+ p->migration_flags &= ~MDF_PUSH;
+
++ preempt_disable();
+ task_rq_unlock(rq, p, rf);
+-
+ if (!stop_pending) {
+ stop_one_cpu_nowait(cpu_of(rq), migration_cpu_stop,
+ &pending->arg, &pending->stop_work);
+ }
++ preempt_enable();
+
+ if (flags & SCA_MIGRATE_ENABLE)
+ return 0;
+@@ -8961,9 +8965,11 @@ static void balance_push(struct rq *rq)
+ * Temporarily drop rq->lock such that we can wake-up the stop task.
+ * Both preemption and IRQs are still disabled.
+ */
++ preempt_disable();
+ raw_spin_rq_unlock(rq);
+ stop_one_cpu_nowait(rq->cpu, __balance_push_cpu_stop, push_task,
+ this_cpu_ptr(&push_work));
++ preempt_enable();
+ /*
+ * At this point need_resched() is true and we'll take the loop in
+ * schedule(). The next pick is obviously going to be the stop task
+diff --git a/kernel/sched/deadline.c b/kernel/sched/deadline.c
+index de45e4d2c61fa..0a6d6899be5bd 100644
+--- a/kernel/sched/deadline.c
++++ b/kernel/sched/deadline.c
+@@ -2308,9 +2308,11 @@ static void pull_dl_task(struct rq *this_rq)
+ double_unlock_balance(this_rq, src_rq);
+
+ if (push_task) {
++ preempt_disable();
+ raw_spin_rq_unlock(this_rq);
+ stop_one_cpu_nowait(src_rq->cpu, push_cpu_stop,
+ push_task, &src_rq->push_work);
++ preempt_enable();
+ raw_spin_rq_lock(this_rq);
+ }
+ }
+diff --git a/kernel/sched/fair.c b/kernel/sched/fair.c
+index e9ea3244fa4d1..fd8b5656641b7 100644
+--- a/kernel/sched/fair.c
++++ b/kernel/sched/fair.c
+@@ -10364,13 +10364,15 @@ static int load_balance(int this_cpu, struct rq *this_rq,
+ busiest->push_cpu = this_cpu;
+ active_balance = 1;
+ }
+- raw_spin_rq_unlock_irqrestore(busiest, flags);
+
++ preempt_disable();
++ raw_spin_rq_unlock_irqrestore(busiest, flags);
+ if (active_balance) {
+ stop_one_cpu_nowait(cpu_of(busiest),
+ active_load_balance_cpu_stop, busiest,
+ &busiest->active_balance_work);
+ }
++ preempt_enable();
+ }
+ } else {
+ sd->nr_balance_failed = 0;
+diff --git a/kernel/sched/rt.c b/kernel/sched/rt.c
+index 4b9281e6b1ccd..7045595aacac6 100644
+--- a/kernel/sched/rt.c
++++ b/kernel/sched/rt.c
+@@ -1951,9 +1951,11 @@ static int push_rt_task(struct rq *rq, bool pull)
+ */
+ push_task = get_push_task(rq);
+ if (push_task) {
++ preempt_disable();
+ raw_spin_rq_unlock(rq);
+ stop_one_cpu_nowait(rq->cpu, push_cpu_stop,
+ push_task, &rq->push_work);
++ preempt_enable();
+ raw_spin_rq_lock(rq);
+ }
+
+@@ -2290,9 +2292,11 @@ static void pull_rt_task(struct rq *this_rq)
+ double_unlock_balance(this_rq, src_rq);
+
+ if (push_task) {
++ preempt_disable();
+ raw_spin_rq_unlock(this_rq);
+ stop_one_cpu_nowait(src_rq->cpu, push_cpu_stop,
+ push_task, &src_rq->push_work);
++ preempt_enable();
+ raw_spin_rq_lock(this_rq);
+ }
+ }
+--
+2.42.0
+
--- /dev/null
+From b9941c37b8c431cbc36a1690a001706f049d2841 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sun, 17 Sep 2023 00:29:54 +0100
+Subject: sched/uclamp: Ignore (util == 0) optimization in feec() when
+ p_util_max = 0
+
+From: Qais Yousef <qyousef@layalina.io>
+
+[ Upstream commit 23c9519def98ee0fa97ea5871535e9b136f522fc ]
+
+find_energy_efficient_cpu() bails out early if effective util of the
+task is 0 as the delta at this point will be zero and there's nothing
+for EAS to do. When uclamp is being used, this could lead to wrong
+decisions when uclamp_max is set to 0. In this case the task is capped
+to performance point 0, but it is actually running and consuming energy
+and we can benefit from EAS energy calculations.
+
+Rework the condition so that it bails out when both util and uclamp_min
+are 0.
+
+We can do that without needing to use uclamp_task_util(); remove it.
+
+Fixes: d81304bc6193 ("sched/uclamp: Cater for uclamp in find_energy_efficient_cpu()'s early exit condition")
+Signed-off-by: Qais Yousef (Google) <qyousef@layalina.io>
+Signed-off-by: Ingo Molnar <mingo@kernel.org>
+Reviewed-by: Vincent Guittot <vincent.guittot@linaro.org>
+Reviewed-by: Dietmar Eggemann <dietmar.eggemann@arm.com>
+Acked-by: Peter Zijlstra (Intel) <peterz@infradead.org>
+Link: https://lore.kernel.org/r/20230916232955.2099394-3-qyousef@layalina.io
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ kernel/sched/fair.c | 18 +-----------------
+ 1 file changed, 1 insertion(+), 17 deletions(-)
+
+diff --git a/kernel/sched/fair.c b/kernel/sched/fair.c
+index 646a6ae4b2509..e9ea3244fa4d1 100644
+--- a/kernel/sched/fair.c
++++ b/kernel/sched/fair.c
+@@ -3987,22 +3987,6 @@ static inline unsigned long task_util_est(struct task_struct *p)
+ return max(task_util(p), _task_util_est(p));
+ }
+
+-#ifdef CONFIG_UCLAMP_TASK
+-static inline unsigned long uclamp_task_util(struct task_struct *p,
+- unsigned long uclamp_min,
+- unsigned long uclamp_max)
+-{
+- return clamp(task_util_est(p), uclamp_min, uclamp_max);
+-}
+-#else
+-static inline unsigned long uclamp_task_util(struct task_struct *p,
+- unsigned long uclamp_min,
+- unsigned long uclamp_max)
+-{
+- return task_util_est(p);
+-}
+-#endif
+-
+ static inline void util_est_enqueue(struct cfs_rq *cfs_rq,
+ struct task_struct *p)
+ {
+@@ -7037,7 +7021,7 @@ static int find_energy_efficient_cpu(struct task_struct *p, int prev_cpu)
+ target = prev_cpu;
+
+ sync_entity_load_avg(&p->se);
+- if (!uclamp_task_util(p, p_util_min, p_util_max))
++ if (!task_util_est(p) && p_util_min == 0)
+ goto unlock;
+
+ for (; pd; pd = pd->next) {
+--
+2.42.0
+
--- /dev/null
+From af7a97175d47ce62f77cd7a452552b5a8e76b1d3 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 21 Sep 2023 17:54:28 -0500
+Subject: scsi: ibmvfc: Fix erroneous use of rtas_busy_delay with hcall return
+ code
+
+From: Tyrel Datwyler <tyreld@linux.ibm.com>
+
+[ Upstream commit 670106eb4c8b23475f8c2b3416005a312afa622f ]
+
+Commit 0217a272fe13 ("scsi: ibmvfc: Store return code of H_FREE_SUB_CRQ
+during cleanup") wrongly changed the busy loop check to use
+rtas_busy_delay() instead of H_BUSY and H_IS_LONG_BUSY(). The busy return
+codes for RTAS and hypercalls are not the same.
+
+Fix this issue by restoring the use of H_BUSY and H_IS_LONG_BUSY().
+
+Fixes: 0217a272fe13 ("scsi: ibmvfc: Store return code of H_FREE_SUB_CRQ during cleanup")
+Signed-off-by: Tyrel Datwyler <tyreld@linux.ibm.com>
+Link: https://lore.kernel.org/r/20230921225435.3537728-5-tyreld@linux.ibm.com
+Reviewed-by: Brian King <brking@linux.vnet.ibm.com>
+Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/scsi/ibmvscsi/ibmvfc.c | 3 +--
+ 1 file changed, 1 insertion(+), 2 deletions(-)
+
+diff --git a/drivers/scsi/ibmvscsi/ibmvfc.c b/drivers/scsi/ibmvscsi/ibmvfc.c
+index 45ef78f388dc9..d169ba772450f 100644
+--- a/drivers/scsi/ibmvscsi/ibmvfc.c
++++ b/drivers/scsi/ibmvscsi/ibmvfc.c
+@@ -22,7 +22,6 @@
+ #include <linux/bsg-lib.h>
+ #include <asm/firmware.h>
+ #include <asm/irq.h>
+-#include <asm/rtas.h>
+ #include <asm/vio.h>
+ #include <scsi/scsi.h>
+ #include <scsi/scsi_cmnd.h>
+@@ -5802,7 +5801,7 @@ static int ibmvfc_register_scsi_channel(struct ibmvfc_host *vhost,
+ irq_failed:
+ do {
+ rc = plpar_hcall_norets(H_FREE_SUB_CRQ, vdev->unit_address, scrq->cookie);
+- } while (rtas_busy_delay(rc));
++ } while (rc == H_BUSY || H_IS_LONG_BUSY(rc));
+ reg_failed:
+ LEAVE;
+ return rc;
+--
+2.42.0
+
--- /dev/null
+From 28c867debc183b2773635a065525148a79533e91 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 17 Oct 2023 11:20:26 -0700
+Subject: scsi: ufs: core: Leave space for '\0' in utf8 desc string
+
+From: Daniel Mentz <danielmentz@google.com>
+
+[ Upstream commit a75a16c62a2540f11eeae4f2b50e95deefb652ea ]
+
+utf16s_to_utf8s does not NULL terminate the output string. For us to be
+able to add a NULL character when utf16s_to_utf8s returns, we need to make
+sure that there is space for such NULL character at the end of the output
+buffer. We can achieve this by passing an output buffer size to
+utf16s_to_utf8s that is one character less than what we allocated.
+
+Other call sites of utf16s_to_utf8s appear to be using the same technique
+where they artificially reduce the buffer size by one to leave space for a
+NULL character or line feed character.
+
+Fixes: 4b828fe156a6 ("scsi: ufs: revamp string descriptor reading")
+Reviewed-by: Mars Cheng <marscheng@google.com>
+Reviewed-by: Bart Van Assche <bvanassche@acm.org>
+Reviewed-by: Yen-lin Lai <yenlinlai@google.com>
+Signed-off-by: Daniel Mentz <danielmentz@google.com>
+Link: https://lore.kernel.org/r/20231017182026.2141163-1-danielmentz@google.com
+Reviewed-by: Avri Altman <avri.altman@wdc.com>
+Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/scsi/ufs/ufshcd.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c
+index f48036f09eab5..e78461f66400c 100644
+--- a/drivers/scsi/ufs/ufshcd.c
++++ b/drivers/scsi/ufs/ufshcd.c
+@@ -3465,7 +3465,7 @@ int ufshcd_read_string_desc(struct ufs_hba *hba, u8 desc_index,
+ */
+ ret = utf16s_to_utf8s(uc_str->uc,
+ uc_str->len - QUERY_DESC_HDR_SIZE,
+- UTF16_BIG_ENDIAN, str, ascii_len);
++ UTF16_BIG_ENDIAN, str, ascii_len - 1);
+
+ /* replace non-printable or non-ASCII characters with spaces */
+ for (i = 0; i < ret; i++)
+--
+2.42.0
+
--- /dev/null
+From ca6b75eaf16ab2394cf8f037f509b6bad7e59b3d Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 6 Sep 2023 23:42:56 +0800
+Subject: selftests/bpf: Correct map_fd to data_fd in tailcalls
+
+From: Leon Hwang <hffilwlqm@gmail.com>
+
+[ Upstream commit 96daa9874211d5497aa70fa409b67afc29f0cb86 ]
+
+Get and check data_fd. It should not check map_fd again.
+
+Meanwhile, correct some 'return' to 'goto out'.
+
+Thank the suggestion from Maciej in "bpf, x64: Fix tailcall infinite
+loop"[0] discussions.
+
+[0] https://lore.kernel.org/bpf/e496aef8-1f80-0f8e-dcdd-25a8c300319a@gmail.com/T/#m7d3b601066ba66400d436b7e7579b2df4a101033
+
+Fixes: 79d49ba048ec ("bpf, testing: Add various tail call test cases")
+Fixes: 3b0379111197 ("selftests/bpf: Add tailcall_bpf2bpf tests")
+Fixes: 5e0b0a4c52d3 ("selftests/bpf: Test tail call counting with bpf2bpf and data on stack")
+Signed-off-by: Leon Hwang <hffilwlqm@gmail.com>
+Reviewed-by: Maciej Fijalkowski <maciej.fijalkowski@intel.com>
+Link: https://lore.kernel.org/r/20230906154256.95461-1-hffilwlqm@gmail.com
+Signed-off-by: Martin KaFai Lau <martin.lau@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ .../selftests/bpf/prog_tests/tailcalls.c | 32 +++++++++----------
+ 1 file changed, 16 insertions(+), 16 deletions(-)
+
+diff --git a/tools/testing/selftests/bpf/prog_tests/tailcalls.c b/tools/testing/selftests/bpf/prog_tests/tailcalls.c
+index b7b9f28e1c3dd..28e30ad4a30e8 100644
+--- a/tools/testing/selftests/bpf/prog_tests/tailcalls.c
++++ b/tools/testing/selftests/bpf/prog_tests/tailcalls.c
+@@ -272,11 +272,11 @@ static void test_tailcall_3(void)
+
+ data_map = bpf_object__find_map_by_name(obj, "tailcall.bss");
+ if (CHECK_FAIL(!data_map || !bpf_map__is_internal(data_map)))
+- return;
++ goto out;
+
+ data_fd = bpf_map__fd(data_map);
+- if (CHECK_FAIL(map_fd < 0))
+- return;
++ if (CHECK_FAIL(data_fd < 0))
++ goto out;
+
+ i = 0;
+ err = bpf_map_lookup_elem(data_fd, &i, &val);
+@@ -334,11 +334,11 @@ static void test_tailcall_4(void)
+
+ data_map = bpf_object__find_map_by_name(obj, "tailcall.bss");
+ if (CHECK_FAIL(!data_map || !bpf_map__is_internal(data_map)))
+- return;
++ goto out;
+
+ data_fd = bpf_map__fd(data_map);
+- if (CHECK_FAIL(map_fd < 0))
+- return;
++ if (CHECK_FAIL(data_fd < 0))
++ goto out;
+
+ for (i = 0; i < bpf_map__def(prog_array)->max_entries; i++) {
+ snprintf(prog_name, sizeof(prog_name), "classifier/%i", i);
+@@ -422,11 +422,11 @@ static void test_tailcall_5(void)
+
+ data_map = bpf_object__find_map_by_name(obj, "tailcall.bss");
+ if (CHECK_FAIL(!data_map || !bpf_map__is_internal(data_map)))
+- return;
++ goto out;
+
+ data_fd = bpf_map__fd(data_map);
+- if (CHECK_FAIL(map_fd < 0))
+- return;
++ if (CHECK_FAIL(data_fd < 0))
++ goto out;
+
+ for (i = 0; i < bpf_map__def(prog_array)->max_entries; i++) {
+ snprintf(prog_name, sizeof(prog_name), "classifier/%i", i);
+@@ -610,11 +610,11 @@ static void test_tailcall_bpf2bpf_2(void)
+
+ data_map = bpf_object__find_map_by_name(obj, "tailcall.bss");
+ if (CHECK_FAIL(!data_map || !bpf_map__is_internal(data_map)))
+- return;
++ goto out;
+
+ data_fd = bpf_map__fd(data_map);
+- if (CHECK_FAIL(map_fd < 0))
+- return;
++ if (CHECK_FAIL(data_fd < 0))
++ goto out;
+
+ i = 0;
+ err = bpf_map_lookup_elem(data_fd, &i, &val);
+@@ -783,11 +783,11 @@ static void test_tailcall_bpf2bpf_4(bool noise)
+
+ data_map = bpf_object__find_map_by_name(obj, "tailcall.bss");
+ if (CHECK_FAIL(!data_map || !bpf_map__is_internal(data_map)))
+- return;
++ goto out;
+
+ data_fd = bpf_map__fd(data_map);
+- if (CHECK_FAIL(map_fd < 0))
+- return;
++ if (CHECK_FAIL(data_fd < 0))
++ goto out;
+
+ i = 0;
+ val.noise = noise;
+@@ -851,7 +851,7 @@ static void test_tailcall_bpf2bpf_6(void)
+ ASSERT_EQ(topts.retval, 0, "tailcall retval");
+
+ data_fd = bpf_map__fd(obj->maps.bss);
+- if (!ASSERT_GE(map_fd, 0, "bss map fd"))
++ if (!ASSERT_GE(data_fd, 0, "bss map fd"))
+ goto out;
+
+ i = 0;
+--
+2.42.0
+
--- /dev/null
+From 77b5a4342528531848fa52864d6ff0dde588a1cb Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 16 Jun 2022 18:20:37 +0200
+Subject: selftests/bpf: Test tail call counting with bpf2bpf and data on stack
+
+From: Jakub Sitnicki <jakub@cloudflare.com>
+
+[ Upstream commit 5e0b0a4c52d30bb09659446f40b77a692361600d ]
+
+Cover the case when tail call count needs to be passed from BPF function to
+BPF function, and the caller has data on stack. Specifically when the size
+of data allocated on BPF stack is not a multiple on 8.
+
+Signed-off-by: Jakub Sitnicki <jakub@cloudflare.com>
+Signed-off-by: Daniel Borkmann <daniel@iogearbox.net>
+Link: https://lore.kernel.org/bpf/20220616162037.535469-3-jakub@cloudflare.com
+Stable-dep-of: 96daa9874211 ("selftests/bpf: Correct map_fd to data_fd in tailcalls")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ .../selftests/bpf/prog_tests/tailcalls.c | 55 +++++++++++++++++++
+ .../selftests/bpf/progs/tailcall_bpf2bpf6.c | 42 ++++++++++++++
+ 2 files changed, 97 insertions(+)
+ create mode 100644 tools/testing/selftests/bpf/progs/tailcall_bpf2bpf6.c
+
+diff --git a/tools/testing/selftests/bpf/prog_tests/tailcalls.c b/tools/testing/selftests/bpf/prog_tests/tailcalls.c
+index b5940e6ca67cb..b7b9f28e1c3dd 100644
+--- a/tools/testing/selftests/bpf/prog_tests/tailcalls.c
++++ b/tools/testing/selftests/bpf/prog_tests/tailcalls.c
+@@ -810,6 +810,59 @@ static void test_tailcall_bpf2bpf_4(bool noise)
+ bpf_object__close(obj);
+ }
+
++#include "tailcall_bpf2bpf6.skel.h"
++
++/* Tail call counting works even when there is data on stack which is
++ * not aligned to 8 bytes.
++ */
++static void test_tailcall_bpf2bpf_6(void)
++{
++ struct tailcall_bpf2bpf6 *obj;
++ int err, map_fd, prog_fd, main_fd, data_fd, i, val;
++ LIBBPF_OPTS(bpf_test_run_opts, topts,
++ .data_in = &pkt_v4,
++ .data_size_in = sizeof(pkt_v4),
++ .repeat = 1,
++ );
++
++ obj = tailcall_bpf2bpf6__open_and_load();
++ if (!ASSERT_OK_PTR(obj, "open and load"))
++ return;
++
++ main_fd = bpf_program__fd(obj->progs.entry);
++ if (!ASSERT_GE(main_fd, 0, "entry prog fd"))
++ goto out;
++
++ map_fd = bpf_map__fd(obj->maps.jmp_table);
++ if (!ASSERT_GE(map_fd, 0, "jmp_table map fd"))
++ goto out;
++
++ prog_fd = bpf_program__fd(obj->progs.classifier_0);
++ if (!ASSERT_GE(prog_fd, 0, "classifier_0 prog fd"))
++ goto out;
++
++ i = 0;
++ err = bpf_map_update_elem(map_fd, &i, &prog_fd, BPF_ANY);
++ if (!ASSERT_OK(err, "jmp_table map update"))
++ goto out;
++
++ err = bpf_prog_test_run_opts(main_fd, &topts);
++ ASSERT_OK(err, "entry prog test run");
++ ASSERT_EQ(topts.retval, 0, "tailcall retval");
++
++ data_fd = bpf_map__fd(obj->maps.bss);
++ if (!ASSERT_GE(map_fd, 0, "bss map fd"))
++ goto out;
++
++ i = 0;
++ err = bpf_map_lookup_elem(data_fd, &i, &val);
++ ASSERT_OK(err, "bss map lookup");
++ ASSERT_EQ(val, 1, "done flag is set");
++
++out:
++ tailcall_bpf2bpf6__destroy(obj);
++}
++
+ void test_tailcalls(void)
+ {
+ if (test__start_subtest("tailcall_1"))
+@@ -832,4 +885,6 @@ void test_tailcalls(void)
+ test_tailcall_bpf2bpf_4(false);
+ if (test__start_subtest("tailcall_bpf2bpf_5"))
+ test_tailcall_bpf2bpf_4(true);
++ if (test__start_subtest("tailcall_bpf2bpf_6"))
++ test_tailcall_bpf2bpf_6();
+ }
+diff --git a/tools/testing/selftests/bpf/progs/tailcall_bpf2bpf6.c b/tools/testing/selftests/bpf/progs/tailcall_bpf2bpf6.c
+new file mode 100644
+index 0000000000000..41ce83da78e8b
+--- /dev/null
++++ b/tools/testing/selftests/bpf/progs/tailcall_bpf2bpf6.c
+@@ -0,0 +1,42 @@
++// SPDX-License-Identifier: GPL-2.0
++#include <linux/bpf.h>
++#include <bpf/bpf_helpers.h>
++
++#define __unused __attribute__((unused))
++
++struct {
++ __uint(type, BPF_MAP_TYPE_PROG_ARRAY);
++ __uint(max_entries, 1);
++ __uint(key_size, sizeof(__u32));
++ __uint(value_size, sizeof(__u32));
++} jmp_table SEC(".maps");
++
++int done = 0;
++
++SEC("tc")
++int classifier_0(struct __sk_buff *skb __unused)
++{
++ done = 1;
++ return 0;
++}
++
++static __noinline
++int subprog_tail(struct __sk_buff *skb)
++{
++ /* Don't propagate the constant to the caller */
++ volatile int ret = 1;
++
++ bpf_tail_call_static(skb, &jmp_table, 0);
++ return ret;
++}
++
++SEC("tc")
++int entry(struct __sk_buff *skb)
++{
++ /* Have data on stack which size is not a multiple of 8 */
++ volatile char arr[1] = {};
++
++ return subprog_tail(skb);
++}
++
++char __license[] SEC("license") = "GPL";
+--
+2.42.0
+
--- /dev/null
+From 26cca3cb737c6bf3a9956c7157705f24f08505ba Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 13 Oct 2023 13:36:28 +0200
+Subject: selftests/pidfd: Fix ksft print formats
+
+From: Maciej Wieczor-Retman <maciej.wieczor-retman@intel.com>
+
+[ Upstream commit 4d7f4e8158b62f63031510cdc24acc520956c091 ]
+
+Compiling pidfd selftest after adding a __printf() attribute to
+ksft_print_msg() and ksft_test_result_pass() exposes -Wformat warnings
+in error_report(), test_pidfd_poll_exec_thread(),
+child_poll_exec_test(), test_pidfd_poll_leader_exit_thread(),
+child_poll_leader_exit_test().
+
+The ksft_test_result_pass() in error_report() expects a string but
+doesn't provide any argument after the format string. All the other
+calls to ksft_print_msg() in the functions mentioned above have format
+strings that don't match with other passed arguments.
+
+Fix format specifiers so they match the passed variables.
+
+Add a missing variable to ksft_test_result_pass() inside
+error_report() so it matches other cases in the switch statement.
+
+Fixes: 2def297ec7fb ("pidfd: add tests for NSpid info in fdinfo")
+
+Signed-off-by: Maciej Wieczor-Retman <maciej.wieczor-retman@intel.com>
+Signed-off-by: Shuah Khan <skhan@linuxfoundation.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ tools/testing/selftests/pidfd/pidfd_fdinfo_test.c | 2 +-
+ tools/testing/selftests/pidfd/pidfd_test.c | 12 ++++++------
+ 2 files changed, 7 insertions(+), 7 deletions(-)
+
+diff --git a/tools/testing/selftests/pidfd/pidfd_fdinfo_test.c b/tools/testing/selftests/pidfd/pidfd_fdinfo_test.c
+index 3fd8e903118f5..3bc46d6151f44 100644
+--- a/tools/testing/selftests/pidfd/pidfd_fdinfo_test.c
++++ b/tools/testing/selftests/pidfd/pidfd_fdinfo_test.c
+@@ -62,7 +62,7 @@ static void error_report(struct error *err, const char *test_name)
+ break;
+
+ case PIDFD_PASS:
+- ksft_test_result_pass("%s test: Passed\n");
++ ksft_test_result_pass("%s test: Passed\n", test_name);
+ break;
+
+ default:
+diff --git a/tools/testing/selftests/pidfd/pidfd_test.c b/tools/testing/selftests/pidfd/pidfd_test.c
+index 9a2d64901d591..79f543ad394c2 100644
+--- a/tools/testing/selftests/pidfd/pidfd_test.c
++++ b/tools/testing/selftests/pidfd/pidfd_test.c
+@@ -380,13 +380,13 @@ static int test_pidfd_send_signal_syscall_support(void)
+
+ static void *test_pidfd_poll_exec_thread(void *priv)
+ {
+- ksft_print_msg("Child Thread: starting. pid %d tid %d ; and sleeping\n",
++ ksft_print_msg("Child Thread: starting. pid %d tid %ld ; and sleeping\n",
+ getpid(), syscall(SYS_gettid));
+ ksft_print_msg("Child Thread: doing exec of sleep\n");
+
+ execl("/bin/sleep", "sleep", str(CHILD_THREAD_MIN_WAIT), (char *)NULL);
+
+- ksft_print_msg("Child Thread: DONE. pid %d tid %d\n",
++ ksft_print_msg("Child Thread: DONE. pid %d tid %ld\n",
+ getpid(), syscall(SYS_gettid));
+ return NULL;
+ }
+@@ -426,7 +426,7 @@ static int child_poll_exec_test(void *args)
+ {
+ pthread_t t1;
+
+- ksft_print_msg("Child (pidfd): starting. pid %d tid %d\n", getpid(),
++ ksft_print_msg("Child (pidfd): starting. pid %d tid %ld\n", getpid(),
+ syscall(SYS_gettid));
+ pthread_create(&t1, NULL, test_pidfd_poll_exec_thread, NULL);
+ /*
+@@ -477,10 +477,10 @@ static void test_pidfd_poll_exec(int use_waitpid)
+
+ static void *test_pidfd_poll_leader_exit_thread(void *priv)
+ {
+- ksft_print_msg("Child Thread: starting. pid %d tid %d ; and sleeping\n",
++ ksft_print_msg("Child Thread: starting. pid %d tid %ld ; and sleeping\n",
+ getpid(), syscall(SYS_gettid));
+ sleep(CHILD_THREAD_MIN_WAIT);
+- ksft_print_msg("Child Thread: DONE. pid %d tid %d\n", getpid(), syscall(SYS_gettid));
++ ksft_print_msg("Child Thread: DONE. pid %d tid %ld\n", getpid(), syscall(SYS_gettid));
+ return NULL;
+ }
+
+@@ -489,7 +489,7 @@ static int child_poll_leader_exit_test(void *args)
+ {
+ pthread_t t1, t2;
+
+- ksft_print_msg("Child: starting. pid %d tid %d\n", getpid(), syscall(SYS_gettid));
++ ksft_print_msg("Child: starting. pid %d tid %ld\n", getpid(), syscall(SYS_gettid));
+ pthread_create(&t1, NULL, test_pidfd_poll_leader_exit_thread, NULL);
+ pthread_create(&t2, NULL, test_pidfd_poll_leader_exit_thread, NULL);
+
+--
+2.42.0
+
--- /dev/null
+From 955fee01b3b81a9193909804e6c64f481679c2b3 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 4 Sep 2023 12:53:32 +0300
+Subject: selftests/resctrl: Ensure the benchmark commands fits to its array
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Ilpo Järvinen <ilpo.jarvinen@linux.intel.com>
+
+[ Upstream commit 4a28c7665c2a1ac0400864eabb0c641e135f61aa ]
+
+Benchmark command is copied into an array in the stack. The array is
+BENCHMARK_ARGS items long but the command line could try to provide a
+longer command. Argument size is also fixed by BENCHMARK_ARG_SIZE (63
+bytes of space after fitting the terminating \0 character) and user
+could have inputted argument longer than that.
+
+Return error in case the benchmark command does not fit to the space
+allocated for it.
+
+Fixes: ecdbb911f22d ("selftests/resctrl: Add MBM test")
+Signed-off-by: Ilpo Järvinen <ilpo.jarvinen@linux.intel.com>
+Tested-by: Shaopeng Tan <tan.shaopeng@jp.fujitsu.com>
+Reviewed-by: Shaopeng Tan <tan.shaopeng@jp.fujitsu.com>
+Reviewed-by: "Wieczor-Retman, Maciej" <maciej.wieczor-retman@intel.com>
+Reviewed-by: Reinette Chatre <reinette.chatre@intel.com>
+Signed-off-by: Shuah Khan <skhan@linuxfoundation.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ tools/testing/selftests/resctrl/resctrl_tests.c | 5 +++++
+ 1 file changed, 5 insertions(+)
+
+diff --git a/tools/testing/selftests/resctrl/resctrl_tests.c b/tools/testing/selftests/resctrl/resctrl_tests.c
+index 3e7cdf1125df4..e9895ebd2a2d0 100644
+--- a/tools/testing/selftests/resctrl/resctrl_tests.c
++++ b/tools/testing/selftests/resctrl/resctrl_tests.c
+@@ -224,9 +224,14 @@ int main(int argc, char **argv)
+ return ksft_exit_fail_msg("Not running as root, abort testing.\n");
+
+ if (has_ben) {
++ if (argc - ben_ind >= BENCHMARK_ARGS)
++ ksft_exit_fail_msg("Too long benchmark command.\n");
++
+ /* Extract benchmark command from command line. */
+ for (i = ben_ind; i < argc; i++) {
+ benchmark_cmd[i - ben_ind] = benchmark_cmd_area[i];
++ if (strlen(argv[i]) >= BENCHMARK_ARG_SIZE)
++ ksft_exit_fail_msg("Too long benchmark command argument.\n");
+ sprintf(benchmark_cmd[i - ben_ind], "%s", argv[i]);
+ }
+ benchmark_cmd[ben_count] = NULL;
+--
+2.42.0
+
+iov_iter-x86-be-consistent-about-the-__user-tag-on-c.patch
+sched-uclamp-ignore-util-0-optimization-in-feec-when.patch
+sched-fix-stop_one_cpu_nowait-vs-hotplug.patch
+vfs-fix-readahead-2-on-block-devices.patch
+writeback-cgroup-switch-inodes-with-dirty-timestamps.patch
+x86-srso-fix-sbpb-enablement-for-possible-future-fix.patch
+futex-don-t-include-process-mm-in-futex-key-on-no-mm.patch
+x86-share-definition-of-__is_canonical_address.patch
+x86-sev-es-allow-copy_from_kernel_nofault-in-earlier.patch
+x86-boot-fix-incorrect-startup_gdt_descr.size.patch
+pstore-platform-add-check-for-kstrdup.patch
+genirq-matrix-exclude-managed-interrupts-in-irq_matr.patch
+i40e-fix-potential-memory-leaks-in-i40e_remove.patch
+selftests-bpf-test-tail-call-counting-with-bpf2bpf-a.patch
+selftests-bpf-correct-map_fd-to-data_fd-in-tailcalls.patch
+wifi-iwlwifi-use-fw-rate-for-non-data-frames.patch
+udp-add-missing-write_once-around-up-encap_rcv.patch
+tcp-call-tcp_try_undo_recovery-when-an-rtod-tfo-syna.patch
+gve-use-size_add-in-call-to-struct_size.patch
+mlxsw-use-size_mul-in-call-to-struct_size.patch
+tipc-use-size_add-in-calls-to-struct_size.patch
+net-spider_net-use-size_add-in-call-to-struct_size.patch
+wifi-rtw88-debug-fix-the-null-vs-is_err-bug-for-debu.patch
+wifi-mt76-mt7603-rework-fix-rx-pse-hang-check.patch
+mt76-dma-use-kzalloc-instead-of-devm_kzalloc-for-txw.patch
+mt76-add-support-for-overriding-the-device-used-for-.patch
+mt76-pass-original-queue-id-from-__mt76_tx_queue_skb.patch
+wifi-mt76-mt7603-improve-stuck-beacon-handling.patch
+tcp_metrics-add-missing-barriers-on-delete.patch
+tcp_metrics-properly-set-tp-snd_ssthresh-in-tcp_init.patch
+tcp_metrics-do-not-create-an-entry-from-tcp_init_met.patch
+wifi-rtlwifi-fix-edca-limit-set-by-bt-coexistence.patch
+can-dev-can_restart-don-t-crash-kernel-if-carrier-is.patch
+can-dev-can_restart-fix-race-condition-between-contr.patch
+can-dev-can_put_echo_skb-don-t-crash-kernel-if-can_p.patch
+pm-devfreq-rockchip-dfi-make-pmu-regmap-mandatory.patch
+netfilter-nf_tables-drop-pointless-memset-when-dumpi.patch
+thermal-core-prevent-potential-string-overflow.patch
+r8169-use-tp_to_dev-instead-of-open-code.patch
+r8169-fix-rare-issue-with-broken-rx-after-link-down-.patch
+chtls-fix-tp-rcv_tstamp-initialization.patch
+tcp-fix-cookie_init_timestamp-overflows.patch
+iwlwifi-pcie-adjust-to-bz-completion-descriptor.patch
+wifi-iwlwifi-call-napi_synchronize-before-freeing-rx.patch
+wifi-iwlwifi-pcie-synchronize-irqs-before-napi.patch
+iwlwifi-remove-contact-information.patch
+wifi-iwlwifi-empty-overflow-queue-during-flush.patch
+acpi-sysfs-fix-create_pnp_modalias-and-create_of_mod.patch
+ipv6-avoid-atomic-fragment-on-gso-packets.patch
+net-add-dev_stats_read-helper.patch
+ipvlan-properly-track-tx_errors.patch
+regmap-debugfs-fix-a-erroneous-check-after-snprintf.patch
+spi-tegra-fix-missing-irq-check-in-tegra_slink_probe.patch
+clk-qcom-gcc-msm8996-use-array_size-instead-of-speci.patch
+clk-qcom-gcc-msm8996-drop-unsupported-clock-sources.patch
+clk-qcom-gcc-msm8996-move-clock-parent-tables-down.patch
+clk-qcom-gcc-msm8996-use-parent_hws-_data-instead-of.patch
+clk-qcom-gcc-msm8996-remove-rpm-bus-clocks.patch
+clk-qcom-clk-rcg2-fix-clock-rate-overflow-for-high-p.patch
+clk-qcom-mmcc-msm8998-don-t-check-halt-bit-on-some-b.patch
+clk-qcom-mmcc-msm8998-fix-the-smmu-gdsc.patch
+clk-qcom-gcc-sm8150-fix-gcc_sdcc2_apps_clk_src.patch
+clk-imx-select-mxc_clk-for-clk_imx8qxp.patch
+clk-imx-imx8mq-correct-error-handling-path.patch
+clk-imx-imx8qxp-fix-elcdif_pll-clock.patch
+clk-renesas-rzg2l-simplify-multiplication-shift-logi.patch
+clk-renesas-rzg2l-use-field_get-for-pll-register-fie.patch
+clk-renesas-rzg2l-fix-computation-formula.patch
+spi-nxp-fspi-use-the-correct-ioremap-function.patch
+clk-keystone-pll-fix-a-couple-null-vs-is_err-checks.patch
+clk-ti-add-ti_dt_clk_name-helper-to-use-clock-output.patch
+clk-ti-update-pll-and-clockdomain-clocks-to-use-ti_d.patch
+clk-ti-update-component-clocks-to-use-ti_dt_clk_name.patch
+clk-ti-change-ti_clk_register-_omap_hw-api.patch
+clk-ti-fix-double-free-in-of_ti_divider_clk_setup.patch
+clk-npcm7xx-fix-incorrect-kfree.patch
+clk-mediatek-clk-mt6765-add-check-for-mtk_alloc_clk_.patch
+clk-mediatek-clk-mt6779-add-check-for-mtk_alloc_clk_.patch
+clk-mediatek-clk-mt6797-add-check-for-mtk_alloc_clk_.patch
+clk-mediatek-clk-mt7629-eth-add-check-for-mtk_alloc_.patch
+clk-mediatek-clk-mt7629-add-check-for-mtk_alloc_clk_.patch
+clk-mediatek-clk-mt2701-add-check-for-mtk_alloc_clk_.patch
+clk-qcom-config-ipq_apss_6018-should-depend-on-qcom_.patch
+platform-x86-wmi-fix-probe-failure-when-failing-to-r.patch
+platform-x86-wmi-remove-unnecessary-initializations.patch
+platform-x86-wmi-fix-opening-of-char-device.patch
+hwmon-axi-fan-control-fix-possible-null-pointer-dere.patch
+hwmon-coretemp-fix-potentially-truncated-sysfs-attri.patch
+drm-rockchip-vop-fix-reset-of-state-in-duplicate-sta.patch
+drm-rockchip-vop-fix-call-to-crtc-reset-helper.patch
+drm-radeon-possible-buffer-overflow.patch
+drm-mipi-dsi-create-devm-device-registration.patch
+drm-mipi-dsi-create-devm-device-attachment.patch
+drm-bridge-lt8912b-switch-to-devm-mipi-dsi-helpers.patch
+drm-bridge-lt8912b-register-and-attach-our-dsi-devic.patch
+drm-bridge-lt8912b-add-hot-plug-detection.patch
+drm-bridge-lt8912b-fix-bridge_detach.patch
+drm-bridge-lt8912b-fix-crash-on-bridge-detach.patch
+drm-bridge-lt8912b-manually-disable-hpd-only-if-it-w.patch
+drm-bridge-lt8912b-add-missing-drm_bridge_attach-cal.patch
+drm-bridge-tc358768-fix-use-of-uninitialized-variabl.patch
+drm-bridge-tc358768-disable-non-continuous-clock-mod.patch
+drm-bridge-tc358768-fix-bit-updates.patch
+drm-amdkfd-fix-some-race-conditions-in-vram-buffer-a.patch
+drm-mediatek-fix-iommu-fault-by-swapping-fbs-after-u.patch
+drm-mediatek-fix-iommu-fault-during-crtc-enabling.patch
+drm-rockchip-cdn-dp-fix-some-error-handling-paths-in.patch
+drm-bridge-lt9611uxc-switch-to-devm-mipi-dsi-helpers.patch
+drm-bridge-lt9611uxc-register-and-attach-our-dsi-dev.patch
+drm-bridge-lt9611uxc-fix-the-race-in-the-error-path.patch
+arm64-arm-xen-enlighten-fix-kpti-checks.patch
+drm-rockchip-fix-type-promotion-bug-in-rockchip_gem_.patch
+xen-pciback-consider-intx-disabled-when-msi-msi-x-is.patch
+drm-msm-dsi-use-msm_gem_kernel_put-to-free-tx-buffer.patch
+drm-mediatek-mtk_dsi-fix-no_eot_packet-settings-hand.patch
+perf-hisi-fix-use-after-free-when-register-pmu-fails.patch
+arm-dts-renesas-blanche-fix-typo-in-gp_11_2-pin-name.patch
+arm64-dts-qcom-msm8916-fix-iommu-local-address-range.patch
+arm64-dts-qcom-msm8992-libra-drop-duplicated-reserve.patch
+arm64-dts-qcom-sc7280-add-missing-lmh-interrupts.patch
+arm64-dts-qcom-sdm845-mtp-fix-wifi-configuration.patch
+arm64-dts-marvell-cn9310-use-appropriate-label-for-s.patch
+arm64-dts-qcom-apq8016-sbc-add-missing-adv7533-regul.patch
+arm-dts-qcom-mdm9615-populate-vsdcc-fixed-regulator.patch
+soc-qcom-llcc-handle-a-second-device-without-data-co.patch
+firmware-ti_sci-mark-driver-as-non-removable.patch
+firmware-arm_ffa-assign-the-missing-idr-allocation-i.patch
+clk-scmi-free-scmi_clk-allocated-when-the-clocks-wit.patch
+arm64-dts-imx8qm-ss-img-fix-jpegenc-compatible-entry.patch
+arm64-dts-imx8mm-add-sound-dai-cells-to-micfil-node.patch
+arm64-dts-imx8mn-add-sound-dai-cells-to-micfil-node.patch
+selftests-pidfd-fix-ksft-print-formats.patch
+selftests-resctrl-ensure-the-benchmark-commands-fits.patch
+crypto-hisilicon-hpre-fix-a-erroneous-check-after-sn.patch
+hwrng-geode-fix-accessing-registers.patch
+rdma-core-use-size_-add-sub-mul-in-calls-to-struct_s.patch
+scsi-ibmvfc-fix-erroneous-use-of-rtas_busy_delay-wit.patch
+libnvdimm-of_pmem-use-devm_kstrdup-instead-of-kstrdu.patch
+nd_btt-make-btt-lanes-preemptible.patch
+crypto-caam-qi2-fix-chacha20-poly1305-self-test-fail.patch
+crypto-caam-jr-fix-chacha20-poly1305-self-test-failu.patch
+crypto-qat-increase-size-of-buffers.patch
+hid-cp2112-fix-duplicate-workqueue-initialization.patch
+arm-9321-1-memset-cast-the-constant-byte-to-unsigned.patch
+ext4-move-ix-sanity-check-to-corrent-position.patch
+asoc-fsl-mpc5200_dma.c-fix-warning-of-function-param.patch
+ib-mlx5-fix-rdma-counter-binding-for-raw-qp.patch
+rdma-hns-fix-uninitialized-ucmd-in-hns_roce_create_q.patch
+rdma-hns-fix-signed-unsigned-mixed-comparisons.patch
+rdma-hns-the-ud-mode-can-only-be-configured-with-dcq.patch
+asoc-fsl-fix-pm-disable-depth-imbalance-in-fsl_easrc.patch
+scsi-ufs-core-leave-space-for-0-in-utf8-desc-string.patch
+rdma-hfi1-workaround-truncation-compilation-error.patch
+gpio-don-t-fiddle-with-irqchips-marked-as-immutable.patch
+gpio-expose-the-gpiochip_irq_re-ql-res-helpers.patch
+gpio-add-helpers-to-ease-the-transition-towards-immu.patch
+hid-cp2112-make-irq_chip-immutable.patch
+hid-cp2112-fix-irq-shutdown-stopping-polling-for-all.patch
+sh-bios-revive-earlyprintk-support.patch
+revert-hid-logitech-hidpp-add-a-module-parameter-to-.patch
+hid-logitech-hidpp-remove-hidpp_quirk_no_hidinput-qu.patch
+hid-logitech-hidpp-don-t-restart-io-instead-defer-hi.patch
+hid-logitech-hidpp-revert-don-t-restart-communicatio.patch
+hid-logitech-hidpp-move-get_wireless_feature_index-c.patch
+asoc-intel-skylake-fix-mem-leak-when-parsing-uuids-f.patch
+padata-fix-refcnt-handling-in-padata_free_shell.patch
+crypto-qat-fix-deadlock-in-backlog-processing.patch
+asoc-ams-delta.c-use-component-after-check.patch
+mfd-core-un-constify-mfd_cell.of_reg.patch
+mfd-core-ensure-disabled-devices-are-skipped-without.patch
+mfd-dln2-fix-double-put-in-dln2_probe.patch
+mfd-arizona-spi-set-pdata.hpdet_channel-for-acpi-enu.patch
+leds-turris-omnia-drop-unnecessary-mutex-locking.patch
+leds-turris-omnia-do-not-use-smbus-calls.patch
+leds-pwm-don-t-disable-the-pwm-when-the-led-should-b.patch
+leds-trigger-ledtrig-cpu-fix-output-may-be-truncated.patch
+f2fs-introduce-memory-mode.patch
+f2fs-handle-decompress-only-post-processing-in-softi.patch
+f2fs-compress-fix-to-avoid-use-after-free-on-dic.patch
+f2fs-compress-fix-to-avoid-redundant-compress-extens.patch
+tty-tty_jobctrl-fix-pid-memleak-in-disassociate_ctty.patch
+livepatch-fix-missing-newline-character-in-klp_resol.patch
+perf-evlist-add-evlist__add_dummy_on_all_cpus.patch
+perf-tools-get-rid-of-evlist__add_on_all_cpus.patch
+perf-evlist-avoid-frequency-mode-for-the-dummy-event.patch
+dmaengine-idxd-register-dsa_bus_type-before-register.patch
+usb-dwc2-fix-possible-null-pointer-dereference-cause.patch
+usb-chipidea-fix-dma-overwrite-for-tegra.patch
+usb-chipidea-simplify-tegra-dma-alignment-code.patch
+dmaengine-ti-edma-handle-irq_of_parse_and_map-errors.patch
+misc-st_core-do-not-call-kfree_skb-under-spin_lock_i.patch
+tools-iio-iio_generic_buffer-ensure-alignment.patch
+usb-usbip-fix-stub_dev-hub-disconnect.patch
+dmaengine-pxa_dma-remove-an-erroneous-bug_on-in-pxad.patch
+f2fs-fix-to-initialize-map.m_pblk-in-f2fs_precache_e.patch
+powerpc-only-define-__parse_fpscr-when-required.patch
+modpost-fix-tee-module_device_table-built-on-big-end.patch
+powerpc-40x-remove-stale-pte_atomic_updates-macro.patch
+powerpc-xive-fix-endian-conversion-size.patch
+powerpc-imc-pmu-use-the-correct-spinlock-initializer.patch
+powerpc-pseries-fix-potential-memory-leak-in-init_cp.patch
+xhci-loosen-rpm-as-default-policy-to-cover-for-amd-x.patch
+usb-host-xhci-plat-fix-possible-kernel-oops-while-re.patch
+perf-machine-avoid-out-of-bounds-lbr-memory-read.patch
+perf-hist-add-missing-puts-to-hist__account_cycles.patch
+9p-net-fix-possible-memory-leak-in-p9_check_errors.patch
+i3c-fix-potential-refcount-leak-in-i3c_master_regist.patch
+cxl-pci-make-struct-cxl_mem-device-type-generic.patch
+cxl-pci-clean-up-cxl_mem_get_partition_info.patch
+cxl-mbox-introduce-the-mbox_send-operation.patch
+cxl-pci-drop-idr.h.patch
+cxl-mbox-move-mailbox-and-other-non-pci-specific-inf.patch
+cxl-mem-fix-shutdown-order.patch
+rtc-pcf85363-fix-wrong-mask-val-parameters-in-regmap.patch
+pcmcia-cs-fix-possible-hung-task-and-memory-leak-pcc.patch
+pcmcia-ds-fix-refcount-leak-in-pcmcia_device_add.patch
+pcmcia-ds-fix-possible-name-leak-in-error-path-in-pc.patch
+media-i2c-max9286-fix-some-redundant-of_node_put-cal.patch
+media-bttv-fix-use-after-free-error-due-to-btv-timeo.patch
+media-s3c-camif-avoid-inappropriate-kfree.patch
+media-vidtv-psi-add-check-for-kstrdup.patch
+media-vidtv-mux-add-check-and-kfree-for-kstrdup.patch
+media-cedrus-fix-clock-reset-sequence.patch
+media-rcar-vin-refactor-controls-creation-for-video-.patch
+media-rcar-vin-improve-async-notifier-cleanup-paths.patch
+media-rcar-vin-rename-array-storing-subdevice-inform.patch
+media-rcar-vin-move-group-async-notifier.patch
+media-v4l-async-rename-async-nf-functions-clean-up-l.patch
+media-cadence-csi2rx-unregister-v4l2-async-notifier.patch
+media-dvb-usb-v2-af9035-fix-missing-unlock.patch
+regmap-prevent-noinc-writes-from-clobbering-cache.patch
--- /dev/null
+From 5f5603f7a36845d0b7a7ff9579c5b377a7741fd1 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 19 Oct 2023 11:46:43 +0200
+Subject: sh: bios: Revive earlyprintk support
+
+From: Geert Uytterhoeven <geert+renesas@glider.be>
+
+[ Upstream commit 553f7ac78fbb41b2c93ab9b9d78e42274d27daa9 ]
+
+The SuperH BIOS earlyprintk code is protected by CONFIG_EARLY_PRINTK.
+However, when this protection was added, it was missed that SuperH no
+longer defines an EARLY_PRINTK config symbol since commit
+e76fe57447e88916 ("sh: Remove old early serial console code V2"), so
+BIOS earlyprintk can no longer be used.
+
+Fix this by reviving the EARLY_PRINTK config symbol.
+
+Fixes: d0380e6c3c0f6edb ("early_printk: consolidate random copies of identical code")
+Signed-off-by: Geert Uytterhoeven <geert+renesas@glider.be>
+Reviewed-by: John Paul Adrian Glaubitz <glaubitz@physik.fu-berlin.de>
+Link: https://lore.kernel.org/r/c40972dfec3dcc6719808d5df388857360262878.1697708489.git.geert+renesas@glider.be
+Signed-off-by: John Paul Adrian Glaubitz <glaubitz@physik.fu-berlin.de>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ arch/sh/Kconfig.debug | 11 +++++++++++
+ 1 file changed, 11 insertions(+)
+
+diff --git a/arch/sh/Kconfig.debug b/arch/sh/Kconfig.debug
+index c449e7c1b20ff..8bcd6c1431a95 100644
+--- a/arch/sh/Kconfig.debug
++++ b/arch/sh/Kconfig.debug
+@@ -22,6 +22,17 @@ config STACK_DEBUG
+ every function call and will therefore incur a major
+ performance hit. Most users should say N.
+
++config EARLY_PRINTK
++ bool "Early printk"
++ depends on SH_STANDARD_BIOS
++ help
++ Say Y here to redirect kernel printk messages to the serial port
++ used by the SH-IPL bootloader, starting very early in the boot
++ process and ending when the kernel's serial console is initialised.
++ This option is only useful while porting the kernel to a new machine,
++ when the kernel may crash or hang before the serial console is
++ initialised. If unsure, say N.
++
+ config 4KSTACKS
+ bool "Use 4Kb for kernel stacks instead of 8Kb"
+ depends on DEBUG_KERNEL && (MMU || BROKEN) && !PAGE_SIZE_64KB
+--
+2.42.0
+
--- /dev/null
+From 7f47cdd199a68ad3bbf04fec0b990e40892e0cad Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 26 Sep 2023 10:32:29 +0200
+Subject: soc: qcom: llcc: Handle a second device without data corruption
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Uwe Kleine-König <u.kleine-koenig@pengutronix.de>
+
+[ Upstream commit f1a1bc8775b26345aba2be278118999e7f661d3d ]
+
+Usually there is only one llcc device. But if there were a second, even
+a failed probe call would modify the global drv_data pointer. So check
+if drv_data is valid before overwriting it.
+
+Signed-off-by: Uwe Kleine-König <u.kleine-koenig@pengutronix.de>
+Fixes: a3134fb09e0b ("drivers: soc: Add LLCC driver")
+Link: https://lore.kernel.org/r/20230926083229.2073890-1-u.kleine-koenig@pengutronix.de
+Signed-off-by: Bjorn Andersson <andersson@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/soc/qcom/llcc-qcom.c | 3 +++
+ 1 file changed, 3 insertions(+)
+
+diff --git a/drivers/soc/qcom/llcc-qcom.c b/drivers/soc/qcom/llcc-qcom.c
+index 47d41804fdf67..fabc5ce828af3 100644
+--- a/drivers/soc/qcom/llcc-qcom.c
++++ b/drivers/soc/qcom/llcc-qcom.c
+@@ -537,6 +537,9 @@ static int qcom_llcc_probe(struct platform_device *pdev)
+ u32 sz;
+ u32 version;
+
++ if (!IS_ERR(drv_data))
++ return -EBUSY;
++
+ drv_data = devm_kzalloc(dev, sizeof(*drv_data), GFP_KERNEL);
+ if (!drv_data) {
+ ret = -ENOMEM;
+--
+2.42.0
+
--- /dev/null
+From 4a6264aa637e6b8cae9ab9297a9738a610bfbbe3 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 10 Oct 2023 15:15:24 -0500
+Subject: spi: nxp-fspi: use the correct ioremap function
+
+From: Han Xu <han.xu@nxp.com>
+
+[ Upstream commit c3aa5cb264a38ae9bbcce32abca4c155af0456df ]
+
+AHB memory as MMIO should be mapped with ioremap rather than ioremap_wc,
+which should have been used initially just to handle unaligned access as
+a workaround.
+
+Fixes: d166a73503ef ("spi: fspi: dynamically alloc AHB memory")
+Signed-off-by: Han Xu <han.xu@nxp.com>
+Link: https://lore.kernel.org/r/20231010201524.2021340-1-han.xu@nxp.com
+Signed-off-by: Mark Brown <broonie@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/spi/spi-nxp-fspi.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/drivers/spi/spi-nxp-fspi.c b/drivers/spi/spi-nxp-fspi.c
+index 23e4c30e6a60a..45961249c976e 100644
+--- a/drivers/spi/spi-nxp-fspi.c
++++ b/drivers/spi/spi-nxp-fspi.c
+@@ -708,7 +708,7 @@ static int nxp_fspi_read_ahb(struct nxp_fspi *f, const struct spi_mem_op *op)
+ f->memmap_len = len > NXP_FSPI_MIN_IOMAP ?
+ len : NXP_FSPI_MIN_IOMAP;
+
+- f->ahb_addr = ioremap_wc(f->memmap_phy + f->memmap_start,
++ f->ahb_addr = ioremap(f->memmap_phy + f->memmap_start,
+ f->memmap_len);
+
+ if (!f->ahb_addr) {
+--
+2.42.0
+
--- /dev/null
+From 5b2c41ee1809edfa8dd1602343fb0f2a0aad77a6 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sat, 26 Aug 2023 18:02:54 +0800
+Subject: spi: tegra: Fix missing IRQ check in tegra_slink_probe()
+
+From: Zhang Shurong <zhang_shurong@foxmail.com>
+
+[ Upstream commit eb9913b511f10968a02cfa5329a896855dd152a3 ]
+
+This func misses checking for platform_get_irq()'s call and may passes the
+negative error codes to request_irq(), which takes unsigned IRQ #,
+causing it to fail with -EINVAL, overriding an original error code.
+
+Fix this by stop calling request_irq() with invalid IRQ #s.
+
+Fixes: dc4dc3605639 ("spi: tegra: add spi driver for SLINK controller")
+Signed-off-by: Zhang Shurong <zhang_shurong@foxmail.com>
+Reviewed-by: Helen Koike <helen.koike@collabora.com>
+Link: https://lore.kernel.org/r/tencent_73FCC06A3D1C14EE5175253C6FB46A07B709@qq.com
+Signed-off-by: Mark Brown <broonie@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/spi/spi-tegra20-slink.c | 2 ++
+ 1 file changed, 2 insertions(+)
+
+diff --git a/drivers/spi/spi-tegra20-slink.c b/drivers/spi/spi-tegra20-slink.c
+index cf61bf302a059..c611fedda7de9 100644
+--- a/drivers/spi/spi-tegra20-slink.c
++++ b/drivers/spi/spi-tegra20-slink.c
+@@ -1087,6 +1087,8 @@ static int tegra_slink_probe(struct platform_device *pdev)
+ reset_control_deassert(tspi->rst);
+
+ spi_irq = platform_get_irq(pdev, 0);
++ if (spi_irq < 0)
++ return spi_irq;
+ tspi->irq = spi_irq;
+ ret = request_threaded_irq(tspi->irq, tegra_slink_isr,
+ tegra_slink_isr_thread, IRQF_ONESHOT,
+--
+2.42.0
+
--- /dev/null
+From d9021c6cfc3509d3da7704eb68d927f1df9f450c Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 14 Sep 2023 14:36:20 +0000
+Subject: tcp: call tcp_try_undo_recovery when an RTOd TFO SYNACK is ACKed
+
+From: Aananth V <aananthv@google.com>
+
+[ Upstream commit e326578a21414738de45f77badd332fb00bd0f58 ]
+
+For passive TCP Fast Open sockets that had SYN/ACK timeout and did not
+send more data in SYN_RECV, upon receiving the final ACK in 3WHS, the
+congestion state may awkwardly stay in CA_Loss mode unless the CA state
+was undone due to TCP timestamp checks. However, if
+tcp_rcv_synrecv_state_fastopen() decides not to undo, then we should
+enter CA_Open, because at that point we have received an ACK covering
+the retransmitted SYNACKs. Currently, the icsk_ca_state is only set to
+CA_Open after we receive an ACK for a data-packet. This is because
+tcp_ack does not call tcp_fastretrans_alert (and tcp_process_loss) if
+!prior_packets
+
+Note that tcp_process_loss() calls tcp_try_undo_recovery(), so having
+tcp_rcv_synrecv_state_fastopen() decide that if we're in CA_Loss we
+should call tcp_try_undo_recovery() is consistent with that, and
+low risk.
+
+Fixes: dad8cea7add9 ("tcp: fix TFO SYNACK undo to avoid double-timestamp-undo")
+Signed-off-by: Aananth V <aananthv@google.com>
+Signed-off-by: Neal Cardwell <ncardwell@google.com>
+Signed-off-by: Yuchung Cheng <ycheng@google.com>
+Reviewed-by: Eric Dumazet <edumazet@google.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/ipv4/tcp_input.c | 9 +++++----
+ 1 file changed, 5 insertions(+), 4 deletions(-)
+
+diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c
+index 8e4b42d394bed..a3453b4ac339c 100644
+--- a/net/ipv4/tcp_input.c
++++ b/net/ipv4/tcp_input.c
+@@ -6376,22 +6376,23 @@ static int tcp_rcv_synsent_state_process(struct sock *sk, struct sk_buff *skb,
+
+ static void tcp_rcv_synrecv_state_fastopen(struct sock *sk)
+ {
++ struct tcp_sock *tp = tcp_sk(sk);
+ struct request_sock *req;
+
+ /* If we are still handling the SYNACK RTO, see if timestamp ECR allows
+ * undo. If peer SACKs triggered fast recovery, we can't undo here.
+ */
+- if (inet_csk(sk)->icsk_ca_state == TCP_CA_Loss)
+- tcp_try_undo_loss(sk, false);
++ if (inet_csk(sk)->icsk_ca_state == TCP_CA_Loss && !tp->packets_out)
++ tcp_try_undo_recovery(sk);
+
+ /* Reset rtx states to prevent spurious retransmits_timed_out() */
+- tcp_sk(sk)->retrans_stamp = 0;
++ tp->retrans_stamp = 0;
+ inet_csk(sk)->icsk_retransmits = 0;
+
+ /* Once we leave TCP_SYN_RECV or TCP_FIN_WAIT_1,
+ * we no longer need req so release it.
+ */
+- req = rcu_dereference_protected(tcp_sk(sk)->fastopen_rsk,
++ req = rcu_dereference_protected(tp->fastopen_rsk,
+ lockdep_sock_is_held(sk));
+ reqsk_fastopen_remove(sk, req, false);
+
+--
+2.42.0
+
--- /dev/null
+From cd5bb3844366e4f6ef3c63785007bc85f8e78c5a Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 20 Oct 2023 12:57:37 +0000
+Subject: tcp: fix cookie_init_timestamp() overflows
+
+From: Eric Dumazet <edumazet@google.com>
+
+[ Upstream commit 73ed8e03388d16c12fc577e5c700b58a29045a15 ]
+
+cookie_init_timestamp() is supposed to return a 64bit timestamp
+suitable for both TSval determination and setting of skb->tstamp.
+
+Unfortunately it uses 32bit fields and overflows after
+2^32 * 10^6 nsec (~49 days) of uptime.
+
+Generated TSval are still correct, but skb->tstamp might be set
+far away in the past, potentially confusing other layers.
+
+tcp_ns_to_ts() is changed to return a full 64bit value,
+ts and ts_now variables are changed to u64 type,
+and TSMASK is removed in favor of shifts operations.
+
+While we are at it, change this sequence:
+ ts >>= TSBITS;
+ ts--;
+ ts <<= TSBITS;
+ ts |= options;
+to:
+ ts -= (1UL << TSBITS);
+
+Fixes: 9a568de4818d ("tcp: switch TCP TS option (RFC 7323) to 1ms clock")
+Signed-off-by: Eric Dumazet <edumazet@google.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ include/net/tcp.h | 2 +-
+ net/ipv4/syncookies.c | 20 +++++++-------------
+ 2 files changed, 8 insertions(+), 14 deletions(-)
+
+diff --git a/include/net/tcp.h b/include/net/tcp.h
+index 3aee02ad0116b..fe9fc568b2888 100644
+--- a/include/net/tcp.h
++++ b/include/net/tcp.h
+@@ -786,7 +786,7 @@ static inline u32 tcp_time_stamp(const struct tcp_sock *tp)
+ }
+
+ /* Convert a nsec timestamp into TCP TSval timestamp (ms based currently) */
+-static inline u32 tcp_ns_to_ts(u64 ns)
++static inline u64 tcp_ns_to_ts(u64 ns)
+ {
+ return div_u64(ns, NSEC_PER_SEC / TCP_TS_HZ);
+ }
+diff --git a/net/ipv4/syncookies.c b/net/ipv4/syncookies.c
+index 3aab914eb1039..03b0505178f9a 100644
+--- a/net/ipv4/syncookies.c
++++ b/net/ipv4/syncookies.c
+@@ -43,7 +43,6 @@ static siphash_key_t syncookie_secret[2] __read_mostly;
+ * requested/supported by the syn/synack exchange.
+ */
+ #define TSBITS 6
+-#define TSMASK (((__u32)1 << TSBITS) - 1)
+
+ static u32 cookie_hash(__be32 saddr, __be32 daddr, __be16 sport, __be16 dport,
+ u32 count, int c)
+@@ -64,27 +63,22 @@ static u32 cookie_hash(__be32 saddr, __be32 daddr, __be16 sport, __be16 dport,
+ */
+ u64 cookie_init_timestamp(struct request_sock *req, u64 now)
+ {
+- struct inet_request_sock *ireq;
+- u32 ts, ts_now = tcp_ns_to_ts(now);
++ const struct inet_request_sock *ireq = inet_rsk(req);
++ u64 ts, ts_now = tcp_ns_to_ts(now);
+ u32 options = 0;
+
+- ireq = inet_rsk(req);
+-
+ options = ireq->wscale_ok ? ireq->snd_wscale : TS_OPT_WSCALE_MASK;
+ if (ireq->sack_ok)
+ options |= TS_OPT_SACK;
+ if (ireq->ecn_ok)
+ options |= TS_OPT_ECN;
+
+- ts = ts_now & ~TSMASK;
++ ts = (ts_now >> TSBITS) << TSBITS;
+ ts |= options;
+- if (ts > ts_now) {
+- ts >>= TSBITS;
+- ts--;
+- ts <<= TSBITS;
+- ts |= options;
+- }
+- return (u64)ts * (NSEC_PER_SEC / TCP_TS_HZ);
++ if (ts > ts_now)
++ ts -= (1UL << TSBITS);
++
++ return ts * (NSEC_PER_SEC / TCP_TS_HZ);
+ }
+
+
+--
+2.42.0
+
--- /dev/null
+From fce31316e4b550cc8672727e129b28d0fb4f8079 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 22 Sep 2023 22:03:53 +0000
+Subject: tcp_metrics: add missing barriers on delete
+
+From: Eric Dumazet <edumazet@google.com>
+
+[ Upstream commit cbc3a153222805d65f821e10f4f78b6afce06f86 ]
+
+When removing an item from RCU protected list, we must prevent
+store-tearing, using rcu_assign_pointer() or WRITE_ONCE().
+
+Fixes: 04f721c671656 ("tcp_metrics: Rewrite tcp_metrics_flush_all")
+Signed-off-by: Eric Dumazet <edumazet@google.com>
+Reviewed-by: David Ahern <dsahern@kernel.org>
+Acked-by: Neal Cardwell <ncardwell@google.com>
+Signed-off-by: Paolo Abeni <pabeni@redhat.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/ipv4/tcp_metrics.c | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/net/ipv4/tcp_metrics.c b/net/ipv4/tcp_metrics.c
+index 5df97aaac252e..0275bf7570b4c 100644
+--- a/net/ipv4/tcp_metrics.c
++++ b/net/ipv4/tcp_metrics.c
+@@ -908,7 +908,7 @@ static void tcp_metrics_flush_all(struct net *net)
+ match = net ? net_eq(tm_net(tm), net) :
+ !refcount_read(&tm_net(tm)->ns.count);
+ if (match) {
+- *pp = tm->tcpm_next;
++ rcu_assign_pointer(*pp, tm->tcpm_next);
+ kfree_rcu(tm, rcu_head);
+ } else {
+ pp = &tm->tcpm_next;
+@@ -949,7 +949,7 @@ static int tcp_metrics_nl_cmd_del(struct sk_buff *skb, struct genl_info *info)
+ if (addr_same(&tm->tcpm_daddr, &daddr) &&
+ (!src || addr_same(&tm->tcpm_saddr, &saddr)) &&
+ net_eq(tm_net(tm), net)) {
+- *pp = tm->tcpm_next;
++ rcu_assign_pointer(*pp, tm->tcpm_next);
+ kfree_rcu(tm, rcu_head);
+ found = true;
+ } else {
+--
+2.42.0
+
--- /dev/null
+From 420dc90fe28f010a1da43274d71055c403080e5c Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 22 Sep 2023 22:03:55 +0000
+Subject: tcp_metrics: do not create an entry from tcp_init_metrics()
+
+From: Eric Dumazet <edumazet@google.com>
+
+[ Upstream commit a135798e6e200ecb2f864cecca6d257ba278370c ]
+
+tcp_init_metrics() only wants to get metrics if they were
+previously stored in the cache. Creating an entry is adding
+useless costs, especially when tcp_no_metrics_save is set.
+
+Fixes: 51c5d0c4b169 ("tcp: Maintain dynamic metrics in local cache.")
+Signed-off-by: Eric Dumazet <edumazet@google.com>
+Reviewed-by: David Ahern <dsahern@kernel.org>
+Acked-by: Neal Cardwell <ncardwell@google.com>
+Signed-off-by: Paolo Abeni <pabeni@redhat.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/ipv4/tcp_metrics.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/net/ipv4/tcp_metrics.c b/net/ipv4/tcp_metrics.c
+index 940f75df19358..def337f72c860 100644
+--- a/net/ipv4/tcp_metrics.c
++++ b/net/ipv4/tcp_metrics.c
+@@ -478,7 +478,7 @@ void tcp_init_metrics(struct sock *sk)
+ goto reset;
+
+ rcu_read_lock();
+- tm = tcp_get_metrics(sk, dst, true);
++ tm = tcp_get_metrics(sk, dst, false);
+ if (!tm) {
+ rcu_read_unlock();
+ goto reset;
+--
+2.42.0
+
--- /dev/null
+From 1fb52480f7dc4a585d4960194fd0dc276f683d48 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 22 Sep 2023 22:03:54 +0000
+Subject: tcp_metrics: properly set tp->snd_ssthresh in tcp_init_metrics()
+
+From: Eric Dumazet <edumazet@google.com>
+
+[ Upstream commit 081480014a64a69d901f8ef1ffdd56d6085cf87e ]
+
+We need to set tp->snd_ssthresh to TCP_INFINITE_SSTHRESH
+in the case tcp_get_metrics() fails for some reason.
+
+Fixes: 9ad7c049f0f7 ("tcp: RFC2988bis + taking RTT sample from 3WHS for the passive open side")
+Signed-off-by: Eric Dumazet <edumazet@google.com>
+Reviewed-by: David Ahern <dsahern@kernel.org>
+Acked-by: Neal Cardwell <ncardwell@google.com>
+Signed-off-by: Paolo Abeni <pabeni@redhat.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/ipv4/tcp_metrics.c | 9 ++++-----
+ 1 file changed, 4 insertions(+), 5 deletions(-)
+
+diff --git a/net/ipv4/tcp_metrics.c b/net/ipv4/tcp_metrics.c
+index 0275bf7570b4c..940f75df19358 100644
+--- a/net/ipv4/tcp_metrics.c
++++ b/net/ipv4/tcp_metrics.c
+@@ -470,6 +470,10 @@ void tcp_init_metrics(struct sock *sk)
+ u32 val, crtt = 0; /* cached RTT scaled by 8 */
+
+ sk_dst_confirm(sk);
++ /* ssthresh may have been reduced unnecessarily during.
++ * 3WHS. Restore it back to its initial default.
++ */
++ tp->snd_ssthresh = TCP_INFINITE_SSTHRESH;
+ if (!dst)
+ goto reset;
+
+@@ -489,11 +493,6 @@ void tcp_init_metrics(struct sock *sk)
+ tp->snd_ssthresh = val;
+ if (tp->snd_ssthresh > tp->snd_cwnd_clamp)
+ tp->snd_ssthresh = tp->snd_cwnd_clamp;
+- } else {
+- /* ssthresh may have been reduced unnecessarily during.
+- * 3WHS. Restore it back to its initial default.
+- */
+- tp->snd_ssthresh = TCP_INFINITE_SSTHRESH;
+ }
+ val = tcp_metric_get(tm, TCP_METRIC_REORDERING);
+ if (val && tp->reordering != val)
+--
+2.42.0
+
--- /dev/null
+From 021b8603e7b5364da65b188690f275f7e8fe072e Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sat, 7 Oct 2023 11:59:39 +0300
+Subject: thermal: core: prevent potential string overflow
+
+From: Dan Carpenter <dan.carpenter@linaro.org>
+
+[ Upstream commit c99626092efca3061b387043d4a7399bf75fbdd5 ]
+
+The dev->id value comes from ida_alloc() so it's a number between zero
+and INT_MAX. If it's too high then these sprintf()s will overflow.
+
+Fixes: 203d3d4aa482 ("the generic thermal sysfs driver")
+Signed-off-by: Dan Carpenter <dan.carpenter@linaro.org>
+Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/thermal/thermal_core.c | 6 ++++--
+ 1 file changed, 4 insertions(+), 2 deletions(-)
+
+diff --git a/drivers/thermal/thermal_core.c b/drivers/thermal/thermal_core.c
+index 052e8e8fbb21e..ce748e03e4331 100644
+--- a/drivers/thermal/thermal_core.c
++++ b/drivers/thermal/thermal_core.c
+@@ -671,7 +671,8 @@ int thermal_zone_bind_cooling_device(struct thermal_zone_device *tz,
+ if (result)
+ goto release_ida;
+
+- sprintf(dev->attr_name, "cdev%d_trip_point", dev->id);
++ snprintf(dev->attr_name, sizeof(dev->attr_name), "cdev%d_trip_point",
++ dev->id);
+ sysfs_attr_init(&dev->attr.attr);
+ dev->attr.attr.name = dev->attr_name;
+ dev->attr.attr.mode = 0444;
+@@ -680,7 +681,8 @@ int thermal_zone_bind_cooling_device(struct thermal_zone_device *tz,
+ if (result)
+ goto remove_symbol_link;
+
+- sprintf(dev->weight_attr_name, "cdev%d_weight", dev->id);
++ snprintf(dev->weight_attr_name, sizeof(dev->weight_attr_name),
++ "cdev%d_weight", dev->id);
+ sysfs_attr_init(&dev->weight_attr.attr);
+ dev->weight_attr.attr.name = dev->weight_attr_name;
+ dev->weight_attr.attr.mode = S_IWUSR | S_IRUGO;
+--
+2.42.0
+
--- /dev/null
+From 11b6cb694766a9f679c6dd5037e08d675cbb83cf Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 15 Sep 2023 13:16:26 -0600
+Subject: tipc: Use size_add() in calls to struct_size()
+
+From: Gustavo A. R. Silva <gustavoars@kernel.org>
+
+[ Upstream commit 2506a91734754de690869824fb0d1ac592ec1266 ]
+
+If, for any reason, the open-coded arithmetic causes a wraparound,
+the protection that `struct_size()` adds against potential integer
+overflows is defeated. Fix this by hardening call to `struct_size()`
+with `size_add()`.
+
+Fixes: e034c6d23bc4 ("tipc: Use struct_size() helper")
+Signed-off-by: Gustavo A. R. Silva <gustavoars@kernel.org>
+Reviewed-by: Kees Cook <keescook@chromium.org>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/tipc/link.c | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/net/tipc/link.c b/net/tipc/link.c
+index 655a2e1b6dfe4..d13a85b9cdb2d 100644
+--- a/net/tipc/link.c
++++ b/net/tipc/link.c
+@@ -1445,7 +1445,7 @@ u16 tipc_get_gap_ack_blks(struct tipc_gap_ack_blks **ga, struct tipc_link *l,
+ p = (struct tipc_gap_ack_blks *)msg_data(hdr);
+ sz = ntohs(p->len);
+ /* Sanity check */
+- if (sz == struct_size(p, gacks, p->ugack_cnt + p->bgack_cnt)) {
++ if (sz == struct_size(p, gacks, size_add(p->ugack_cnt, p->bgack_cnt))) {
+ /* Good, check if the desired type exists */
+ if ((uc && p->ugack_cnt) || (!uc && p->bgack_cnt))
+ goto ok;
+@@ -1532,7 +1532,7 @@ static u16 tipc_build_gap_ack_blks(struct tipc_link *l, struct tipc_msg *hdr)
+ __tipc_build_gap_ack_blks(ga, l, ga->bgack_cnt) : 0;
+
+ /* Total len */
+- len = struct_size(ga, gacks, ga->bgack_cnt + ga->ugack_cnt);
++ len = struct_size(ga, gacks, size_add(ga->bgack_cnt, ga->ugack_cnt));
+ ga->len = htons(len);
+ return len;
+ }
+--
+2.42.0
+
--- /dev/null
+From b82cf78c2f77bcdf6586f25ab6e05730161f2c60 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 3 Oct 2023 12:57:47 +0300
+Subject: tools: iio: iio_generic_buffer ensure alignment
+
+From: Matti Vaittinen <mazziesaccount@gmail.com>
+
+[ Upstream commit 2d3dff577dd0ea8fe9637a13822f7603c4a881c8 ]
+
+The iio_generic_buffer can return garbage values when the total size of
+scan data is not a multiple of the largest element in the scan. This can be
+demonstrated by reading a scan, consisting, for example of one 4-byte and
+one 2-byte element, where the 4-byte element is first in the buffer.
+
+The IIO generic buffer code does not take into account the last two
+padding bytes that are needed to ensure that the 4-byte data for next
+scan is correctly aligned.
+
+Add the padding bytes required to align the next sample with the scan size.
+
+Signed-off-by: Matti Vaittinen <mazziesaccount@gmail.com>
+Fixes: e58537ccce73 ("staging: iio: update example application.")
+Link: https://lore.kernel.org/r/ZRvlm4ktNLu+qmlf@dc78bmyyyyyyyyyyyyydt-3.rev.dnainternet.fi
+Signed-off-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ tools/iio/iio_generic_buffer.c | 13 ++++++++++++-
+ 1 file changed, 12 insertions(+), 1 deletion(-)
+
+diff --git a/tools/iio/iio_generic_buffer.c b/tools/iio/iio_generic_buffer.c
+index 44bbf80f0cfdd..0d0a7a19d6f95 100644
+--- a/tools/iio/iio_generic_buffer.c
++++ b/tools/iio/iio_generic_buffer.c
+@@ -54,9 +54,12 @@ enum autochan {
+ static unsigned int size_from_channelarray(struct iio_channel_info *channels, int num_channels)
+ {
+ unsigned int bytes = 0;
+- int i = 0;
++ int i = 0, max = 0;
++ unsigned int misalignment;
+
+ while (i < num_channels) {
++ if (channels[i].bytes > max)
++ max = channels[i].bytes;
+ if (bytes % channels[i].bytes == 0)
+ channels[i].location = bytes;
+ else
+@@ -66,6 +69,14 @@ static unsigned int size_from_channelarray(struct iio_channel_info *channels, in
+ bytes = channels[i].location + channels[i].bytes;
+ i++;
+ }
++ /*
++ * We want the data in next sample to also be properly aligned so
++ * we'll add padding at the end if needed. Adding padding only
++ * works for channel data which size is 2^n bytes.
++ */
++ misalignment = bytes % max;
++ if (misalignment)
++ bytes += max - misalignment;
+
+ return bytes;
+ }
+--
+2.42.0
+
--- /dev/null
+From 53981e27429c5077c12c761c7621818010d57f74 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 31 Aug 2023 10:33:29 +0800
+Subject: tty: tty_jobctrl: fix pid memleak in disassociate_ctty()
+
+From: Yi Yang <yiyang13@huawei.com>
+
+[ Upstream commit 11e7f27b79757b6586645d87b95d5b78375ecdfc ]
+
+There is a pid leakage:
+------------------------------
+unreferenced object 0xffff88810c181940 (size 224):
+ comm "sshd", pid 8191, jiffies 4294946950 (age 524.570s)
+ hex dump (first 32 bytes):
+ 01 00 00 00 00 00 00 00 00 00 00 00 ad 4e ad de .............N..
+ ff ff ff ff 6b 6b 6b 6b ff ff ff ff ff ff ff ff ....kkkk........
+ backtrace:
+ [<ffffffff814774e6>] kmem_cache_alloc+0x5c6/0x9b0
+ [<ffffffff81177342>] alloc_pid+0x72/0x570
+ [<ffffffff81140ac4>] copy_process+0x1374/0x2470
+ [<ffffffff81141d77>] kernel_clone+0xb7/0x900
+ [<ffffffff81142645>] __se_sys_clone+0x85/0xb0
+ [<ffffffff8114269b>] __x64_sys_clone+0x2b/0x30
+ [<ffffffff83965a72>] do_syscall_64+0x32/0x80
+ [<ffffffff83a00085>] entry_SYSCALL_64_after_hwframe+0x61/0xc6
+
+It turns out that there is a race condition between disassociate_ctty() and
+tty_signal_session_leader(), which caused this leakage.
+
+The pid memleak is triggered by the following race:
+task[sshd] task[bash]
+----------------------- -----------------------
+ disassociate_ctty();
+ spin_lock_irq(¤t->sighand->siglock);
+ put_pid(current->signal->tty_old_pgrp);
+ current->signal->tty_old_pgrp = NULL;
+ tty = tty_kref_get(current->signal->tty);
+ spin_unlock_irq(¤t->sighand->siglock);
+tty_vhangup();
+tty_lock(tty);
+...
+tty_signal_session_leader();
+spin_lock_irq(&p->sighand->siglock);
+...
+if (tty->ctrl.pgrp) //tty->ctrl.pgrp is not NULL
+p->signal->tty_old_pgrp = get_pid(tty->ctrl.pgrp); //An extra get
+spin_unlock_irq(&p->sighand->siglock);
+...
+tty_unlock(tty);
+ if (tty) {
+ tty_lock(tty);
+ ...
+ put_pid(tty->ctrl.pgrp);
+ tty->ctrl.pgrp = NULL; //It's too late
+ ...
+ tty_unlock(tty);
+ }
+
+The issue is believed to be introduced by commit c8bcd9c5be24 ("tty:
+Fix ->session locking") who moves the unlock of siglock in
+disassociate_ctty() above "if (tty)", making a small window allowing
+tty_signal_session_leader() to kick in. It can be easily reproduced by
+adding a delay before "if (tty)" and at the entrance of
+tty_signal_session_leader().
+
+To fix this issue, we move "put_pid(current->signal->tty_old_pgrp)" after
+"tty->ctrl.pgrp = NULL".
+
+Fixes: c8bcd9c5be24 ("tty: Fix ->session locking")
+Signed-off-by: Yi Yang <yiyang13@huawei.com>
+Co-developed-by: GUO Zihua <guozihua@huawei.com>
+Signed-off-by: GUO Zihua <guozihua@huawei.com>
+Link: https://lore.kernel.org/r/20230831023329.165737-1-yiyang13@huawei.com
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/tty/tty_jobctrl.c | 17 +++++++++++------
+ 1 file changed, 11 insertions(+), 6 deletions(-)
+
+diff --git a/drivers/tty/tty_jobctrl.c b/drivers/tty/tty_jobctrl.c
+index 80b86a7992b50..8ede78488c5b0 100644
+--- a/drivers/tty/tty_jobctrl.c
++++ b/drivers/tty/tty_jobctrl.c
+@@ -300,12 +300,7 @@ void disassociate_ctty(int on_exit)
+ return;
+ }
+
+- spin_lock_irq(¤t->sighand->siglock);
+- put_pid(current->signal->tty_old_pgrp);
+- current->signal->tty_old_pgrp = NULL;
+- tty = tty_kref_get(current->signal->tty);
+- spin_unlock_irq(¤t->sighand->siglock);
+-
++ tty = get_current_tty();
+ if (tty) {
+ unsigned long flags;
+
+@@ -320,6 +315,16 @@ void disassociate_ctty(int on_exit)
+ tty_kref_put(tty);
+ }
+
++ /* If tty->ctrl.pgrp is not NULL, it may be assigned to
++ * current->signal->tty_old_pgrp in a race condition, and
++ * cause pid memleak. Release current->signal->tty_old_pgrp
++ * after tty->ctrl.pgrp set to NULL.
++ */
++ spin_lock_irq(¤t->sighand->siglock);
++ put_pid(current->signal->tty_old_pgrp);
++ current->signal->tty_old_pgrp = NULL;
++ spin_unlock_irq(¤t->sighand->siglock);
++
+ /* Now clear signal->tty under the lock */
+ read_lock(&tasklist_lock);
+ session_clear_tty(task_session(current));
+--
+2.42.0
+
--- /dev/null
+From 4fa35740ebd4b5ba6682f8337655b8e954afd6be Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 12 Sep 2023 09:17:25 +0000
+Subject: udp: add missing WRITE_ONCE() around up->encap_rcv
+
+From: Eric Dumazet <edumazet@google.com>
+
+[ Upstream commit 6d5a12eb91224d707f8691dccb40a5719fe5466d ]
+
+UDP_ENCAP_ESPINUDP_NON_IKE setsockopt() writes over up->encap_rcv
+while other cpus read it.
+
+Fixes: 067b207b281d ("[UDP]: Cleanup UDP encapsulation code")
+Signed-off-by: Eric Dumazet <edumazet@google.com>
+Reviewed-by: Willem de Bruijn <willemb@google.com>
+Signed-off-by: Paolo Abeni <pabeni@redhat.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/ipv4/udp.c | 6 ++++--
+ 1 file changed, 4 insertions(+), 2 deletions(-)
+
+diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c
+index 198d8e07413d3..c454daa78a2f8 100644
+--- a/net/ipv4/udp.c
++++ b/net/ipv4/udp.c
+@@ -2711,10 +2711,12 @@ int udp_lib_setsockopt(struct sock *sk, int level, int optname,
+ case UDP_ENCAP_ESPINUDP_NON_IKE:
+ #if IS_ENABLED(CONFIG_IPV6)
+ if (sk->sk_family == AF_INET6)
+- up->encap_rcv = ipv6_stub->xfrm6_udp_encap_rcv;
++ WRITE_ONCE(up->encap_rcv,
++ ipv6_stub->xfrm6_udp_encap_rcv);
+ else
+ #endif
+- up->encap_rcv = xfrm4_udp_encap_rcv;
++ WRITE_ONCE(up->encap_rcv,
++ xfrm4_udp_encap_rcv);
+ #endif
+ fallthrough;
+ case UDP_ENCAP_L2TPINUDP:
+--
+2.42.0
+
--- /dev/null
+From a7585e98da4b84f04295759e4587280593f4b1e9 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 28 Sep 2023 23:06:03 +0200
+Subject: usb: chipidea: Fix DMA overwrite for Tegra
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Michał Mirosław <mirq-linux@rere.qmqm.pl>
+
+[ Upstream commit 7ab8716713c931ac79988f2592e1cf8b2e4fec1b ]
+
+Tegra USB controllers seem to issue DMA in full 32-bit words only and thus
+may overwrite unevenly-sized buffers. One such occurrence is detected by
+SLUB when receiving a reply to a 1-byte buffer (below). Fix this by
+allocating a bounce buffer also for buffers with sizes not a multiple of 4.
+
+=============================================================================
+BUG kmalloc-64 (Tainted: G B ): kmalloc Redzone overwritten
+-----------------------------------------------------------------------------
+
+0x8555cd02-0x8555cd03 @offset=3330. First byte 0x0 instead of 0xcc
+Allocated in usb_get_status+0x2b/0xac age=1 cpu=3 pid=41
+ __kmem_cache_alloc_node+0x12f/0x1e4
+ __kmalloc+0x33/0x8c
+ usb_get_status+0x2b/0xac
+ hub_probe+0x5e9/0xcec
+ usb_probe_interface+0xbf/0x21c
+ really_probe+0xa5/0x2c4
+ __driver_probe_device+0x75/0x174
+ driver_probe_device+0x31/0x94
+ __device_attach_driver+0x65/0xc0
+ bus_for_each_drv+0x4b/0x74
+ __device_attach+0x69/0x120
+ bus_probe_device+0x65/0x6c
+ device_add+0x48b/0x5f8
+ usb_set_configuration+0x37b/0x6b4
+ usb_generic_driver_probe+0x37/0x68
+ usb_probe_device+0x35/0xb4
+Slab 0xbf622b80 objects=21 used=18 fp=0x8555cdc0 flags=0x800(slab|zone=0)
+Object 0x8555cd00 @offset=3328 fp=0x00000000
+
+Redzone 8555ccc0: cc cc cc cc cc cc cc cc cc cc cc cc cc cc cc cc ................
+Redzone 8555ccd0: cc cc cc cc cc cc cc cc cc cc cc cc cc cc cc cc ................
+Redzone 8555cce0: cc cc cc cc cc cc cc cc cc cc cc cc cc cc cc cc ................
+Redzone 8555ccf0: cc cc cc cc cc cc cc cc cc cc cc cc cc cc cc cc ................
+Object 8555cd00: 01 00 00 00 cc cc cc cc cc cc cc cc cc cc cc cc ................
+Object 8555cd10: cc cc cc cc cc cc cc cc cc cc cc cc cc cc cc cc ................
+Object 8555cd20: cc cc cc cc cc cc cc cc cc cc cc cc cc cc cc cc ................
+Object 8555cd30: cc cc cc cc cc cc cc cc cc cc cc cc cc cc cc cc ................
+Redzone 8555cd40: cc cc cc cc ....
+Padding 8555cd74: 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a ZZZZZZZZZZZZ
+CPU: 3 PID: 41 Comm: kworker/3:1 Tainted: G B 6.6.0-rc1mq-00118-g59786f827ea1 #1115
+Hardware name: NVIDIA Tegra SoC (Flattened Device Tree)
+Workqueue: usb_hub_wq hub_event
+[<8010ca28>] (unwind_backtrace) from [<801090a5>] (show_stack+0x11/0x14)
+[<801090a5>] (show_stack) from [<805da2fb>] (dump_stack_lvl+0x4d/0x7c)
+[<805da2fb>] (dump_stack_lvl) from [<8026464f>] (check_bytes_and_report+0xb3/0xe4)
+[<8026464f>] (check_bytes_and_report) from [<802648e1>] (check_object+0x261/0x290)
+[<802648e1>] (check_object) from [<802671b1>] (free_to_partial_list+0x105/0x3f8)
+[<802671b1>] (free_to_partial_list) from [<80268613>] (__kmem_cache_free+0x103/0x128)
+[<80268613>] (__kmem_cache_free) from [<80425a67>] (usb_get_status+0x73/0xac)
+[<80425a67>] (usb_get_status) from [<80421b31>] (hub_probe+0x5e9/0xcec)
+[<80421b31>] (hub_probe) from [<80428bbb>] (usb_probe_interface+0xbf/0x21c)
+[<80428bbb>] (usb_probe_interface) from [<803ee13d>] (really_probe+0xa5/0x2c4)
+[<803ee13d>] (really_probe) from [<803ee3d1>] (__driver_probe_device+0x75/0x174)
+[<803ee3d1>] (__driver_probe_device) from [<803ee501>] (driver_probe_device+0x31/0x94)
+usb 1-1: device descriptor read/8, error -71
+
+Fixes: fc53d5279094 ("usb: chipidea: tegra: Support host mode")
+Signed-off-by: Michał Mirosław <mirq-linux@rere.qmqm.pl>
+Link: https://lore.kernel.org/r/ef8466b834c1726f5404c95c3e192e90460146f8.1695934946.git.mirq-linux@rere.qmqm.pl
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/usb/chipidea/host.c | 7 ++++---
+ 1 file changed, 4 insertions(+), 3 deletions(-)
+
+diff --git a/drivers/usb/chipidea/host.c b/drivers/usb/chipidea/host.c
+index bdc3885c0d493..de1e7a4322ada 100644
+--- a/drivers/usb/chipidea/host.c
++++ b/drivers/usb/chipidea/host.c
+@@ -403,12 +403,13 @@ static int ci_hdrc_alloc_dma_aligned_buffer(struct urb *urb, gfp_t mem_flags)
+ const unsigned int ci_hdrc_usb_dma_align = 32;
+ size_t kmalloc_size;
+
+- if (urb->num_sgs || urb->sg || urb->transfer_buffer_length == 0 ||
+- !((uintptr_t)urb->transfer_buffer & (ci_hdrc_usb_dma_align - 1)))
++ if (urb->num_sgs || urb->sg || urb->transfer_buffer_length == 0)
++ return 0;
++ if (!((uintptr_t)urb->transfer_buffer & (ci_hdrc_usb_dma_align - 1)) && !(urb->transfer_buffer_length & 3))
+ return 0;
+
+ /* Allocate a buffer with enough padding for alignment */
+- kmalloc_size = urb->transfer_buffer_length +
++ kmalloc_size = ALIGN(urb->transfer_buffer_length, 4) +
+ sizeof(struct ci_hdrc_dma_aligned_buffer) +
+ ci_hdrc_usb_dma_align - 1;
+
+--
+2.42.0
+
--- /dev/null
+From ce3e3ad8261597a12d609dad27dda4bd3132cdfe Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 28 Sep 2023 23:06:03 +0200
+Subject: usb: chipidea: Simplify Tegra DMA alignment code
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Michał Mirosław <mirq-linux@rere.qmqm.pl>
+
+[ Upstream commit 2ae61a2562c0d1720545b0845829a65fb6a9c2c6 ]
+
+The USB host on Tegra3 works with 32-bit alignment. Previous code tried
+to align the buffer, but it did align the wrapper struct instead, so
+the buffer was at a constant offset of 8 bytes (two pointers) from
+expected alignment. Since kmalloc() guarantees at least 8-byte
+alignment already, the alignment-extending is removed.
+
+Fixes: fc53d5279094 ("usb: chipidea: tegra: Support host mode")
+Signed-off-by: Michał Mirosław <mirq-linux@rere.qmqm.pl>
+Link: https://lore.kernel.org/r/a0d917d492b1f91ee0019e68b8e8bca9c585393f.1695934946.git.mirq-linux@rere.qmqm.pl
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/usb/chipidea/host.c | 45 +++++++++++++++----------------------
+ 1 file changed, 18 insertions(+), 27 deletions(-)
+
+diff --git a/drivers/usb/chipidea/host.c b/drivers/usb/chipidea/host.c
+index de1e7a4322ada..786ddb3c32899 100644
+--- a/drivers/usb/chipidea/host.c
++++ b/drivers/usb/chipidea/host.c
+@@ -30,8 +30,7 @@ struct ehci_ci_priv {
+ };
+
+ struct ci_hdrc_dma_aligned_buffer {
+- void *kmalloc_ptr;
+- void *old_xfer_buffer;
++ void *original_buffer;
+ u8 data[];
+ };
+
+@@ -372,60 +371,52 @@ static int ci_ehci_bus_suspend(struct usb_hcd *hcd)
+ return 0;
+ }
+
+-static void ci_hdrc_free_dma_aligned_buffer(struct urb *urb)
++static void ci_hdrc_free_dma_aligned_buffer(struct urb *urb, bool copy_back)
+ {
+ struct ci_hdrc_dma_aligned_buffer *temp;
+- size_t length;
+
+ if (!(urb->transfer_flags & URB_ALIGNED_TEMP_BUFFER))
+ return;
++ urb->transfer_flags &= ~URB_ALIGNED_TEMP_BUFFER;
+
+ temp = container_of(urb->transfer_buffer,
+ struct ci_hdrc_dma_aligned_buffer, data);
++ urb->transfer_buffer = temp->original_buffer;
++
++ if (copy_back && usb_urb_dir_in(urb)) {
++ size_t length;
+
+- if (usb_urb_dir_in(urb)) {
+ if (usb_pipeisoc(urb->pipe))
+ length = urb->transfer_buffer_length;
+ else
+ length = urb->actual_length;
+
+- memcpy(temp->old_xfer_buffer, temp->data, length);
++ memcpy(temp->original_buffer, temp->data, length);
+ }
+- urb->transfer_buffer = temp->old_xfer_buffer;
+- kfree(temp->kmalloc_ptr);
+
+- urb->transfer_flags &= ~URB_ALIGNED_TEMP_BUFFER;
++ kfree(temp);
+ }
+
+ static int ci_hdrc_alloc_dma_aligned_buffer(struct urb *urb, gfp_t mem_flags)
+ {
+- struct ci_hdrc_dma_aligned_buffer *temp, *kmalloc_ptr;
+- const unsigned int ci_hdrc_usb_dma_align = 32;
+- size_t kmalloc_size;
++ struct ci_hdrc_dma_aligned_buffer *temp;
+
+ if (urb->num_sgs || urb->sg || urb->transfer_buffer_length == 0)
+ return 0;
+- if (!((uintptr_t)urb->transfer_buffer & (ci_hdrc_usb_dma_align - 1)) && !(urb->transfer_buffer_length & 3))
++ if (IS_ALIGNED((uintptr_t)urb->transfer_buffer, 4)
++ && IS_ALIGNED(urb->transfer_buffer_length, 4))
+ return 0;
+
+- /* Allocate a buffer with enough padding for alignment */
+- kmalloc_size = ALIGN(urb->transfer_buffer_length, 4) +
+- sizeof(struct ci_hdrc_dma_aligned_buffer) +
+- ci_hdrc_usb_dma_align - 1;
+-
+- kmalloc_ptr = kmalloc(kmalloc_size, mem_flags);
+- if (!kmalloc_ptr)
++ temp = kmalloc(sizeof(*temp) + ALIGN(urb->transfer_buffer_length, 4), mem_flags);
++ if (!temp)
+ return -ENOMEM;
+
+- /* Position our struct dma_aligned_buffer such that data is aligned */
+- temp = PTR_ALIGN(kmalloc_ptr + 1, ci_hdrc_usb_dma_align) - 1;
+- temp->kmalloc_ptr = kmalloc_ptr;
+- temp->old_xfer_buffer = urb->transfer_buffer;
+ if (usb_urb_dir_out(urb))
+ memcpy(temp->data, urb->transfer_buffer,
+ urb->transfer_buffer_length);
+- urb->transfer_buffer = temp->data;
+
++ temp->original_buffer = urb->transfer_buffer;
++ urb->transfer_buffer = temp->data;
+ urb->transfer_flags |= URB_ALIGNED_TEMP_BUFFER;
+
+ return 0;
+@@ -442,7 +433,7 @@ static int ci_hdrc_map_urb_for_dma(struct usb_hcd *hcd, struct urb *urb,
+
+ ret = usb_hcd_map_urb_for_dma(hcd, urb, mem_flags);
+ if (ret)
+- ci_hdrc_free_dma_aligned_buffer(urb);
++ ci_hdrc_free_dma_aligned_buffer(urb, false);
+
+ return ret;
+ }
+@@ -450,7 +441,7 @@ static int ci_hdrc_map_urb_for_dma(struct usb_hcd *hcd, struct urb *urb,
+ static void ci_hdrc_unmap_urb_for_dma(struct usb_hcd *hcd, struct urb *urb)
+ {
+ usb_hcd_unmap_urb_for_dma(hcd, urb);
+- ci_hdrc_free_dma_aligned_buffer(urb);
++ ci_hdrc_free_dma_aligned_buffer(urb, true);
+ }
+
+ int ci_hdrc_host_init(struct ci_hdrc *ci)
+--
+2.42.0
+
--- /dev/null
+From dfa86a5a32e52280c0dfe2858e28e466ce4eb57a Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 26 Sep 2023 10:44:04 +0800
+Subject: usb: dwc2: fix possible NULL pointer dereference caused by driver
+ concurrency
+
+From: Jia-Ju Bai <baijiaju@buaa.edu.cn>
+
+[ Upstream commit ef307bc6ef04e8c1ea843231db58e3afaafa9fa6 ]
+
+In _dwc2_hcd_urb_enqueue(), "urb->hcpriv = NULL" is executed without
+holding the lock "hsotg->lock". In _dwc2_hcd_urb_dequeue():
+
+ spin_lock_irqsave(&hsotg->lock, flags);
+ ...
+ if (!urb->hcpriv) {
+ dev_dbg(hsotg->dev, "## urb->hcpriv is NULL ##\n");
+ goto out;
+ }
+ rc = dwc2_hcd_urb_dequeue(hsotg, urb->hcpriv); // Use urb->hcpriv
+ ...
+out:
+ spin_unlock_irqrestore(&hsotg->lock, flags);
+
+When _dwc2_hcd_urb_enqueue() and _dwc2_hcd_urb_dequeue() are
+concurrently executed, the NULL check of "urb->hcpriv" can be executed
+before "urb->hcpriv = NULL". After urb->hcpriv is NULL, it can be used
+in the function call to dwc2_hcd_urb_dequeue(), which can cause a NULL
+pointer dereference.
+
+This possible bug is found by an experimental static analysis tool
+developed by myself. This tool analyzes the locking APIs to extract
+function pairs that can be concurrently executed, and then analyzes the
+instructions in the paired functions to identify possible concurrency
+bugs including data races and atomicity violations. The above possible
+bug is reported, when my tool analyzes the source code of Linux 6.5.
+
+To fix this possible bug, "urb->hcpriv = NULL" should be executed with
+holding the lock "hsotg->lock". After using this patch, my tool never
+reports the possible bug, with the kernelconfiguration allyesconfig for
+x86_64. Because I have no associated hardware, I cannot test the patch
+in runtime testing, and just verify it according to the code logic.
+
+Fixes: 33ad261aa62b ("usb: dwc2: host: spinlock urb_enqueue")
+Signed-off-by: Jia-Ju Bai <baijiaju@buaa.edu.cn>
+Link: https://lore.kernel.org/r/20230926024404.832096-1-baijiaju@buaa.edu.cn
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/usb/dwc2/hcd.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/drivers/usb/dwc2/hcd.c b/drivers/usb/dwc2/hcd.c
+index 82322696b903b..d17a1dd6d0d93 100644
+--- a/drivers/usb/dwc2/hcd.c
++++ b/drivers/usb/dwc2/hcd.c
+@@ -4802,8 +4802,8 @@ static int _dwc2_hcd_urb_enqueue(struct usb_hcd *hcd, struct urb *urb,
+ if (qh_allocated && qh->channel && qh->channel->qh == qh)
+ qh->channel->qh = NULL;
+ fail2:
+- spin_unlock_irqrestore(&hsotg->lock, flags);
+ urb->hcpriv = NULL;
++ spin_unlock_irqrestore(&hsotg->lock, flags);
+ kfree(qtd);
+ fail1:
+ if (qh_allocated) {
+--
+2.42.0
+
--- /dev/null
+From 1d6dc3db9e9b0ecc2fd795aac35e6b479386f6b1 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 19 Oct 2023 13:29:23 +0300
+Subject: usb: host: xhci-plat: fix possible kernel oops while resuming
+
+From: Sergey Shtylyov <s.shtylyov@omp.ru>
+
+[ Upstream commit a5f928db59519a15e82ecba4ae3e7cbf5a44715a ]
+
+If this driver enables the xHC clocks while resuming from sleep, it calls
+clk_prepare_enable() without checking for errors and blithely goes on to
+read/write the xHC's registers -- which, with the xHC not being clocked,
+at least on ARM32 usually causes an imprecise external abort exceptions
+which cause kernel oops. Currently, the chips for which the driver does
+the clock dance on suspend/resume seem to be the Broadcom STB SoCs, based
+on ARM32 CPUs, as it seems...
+
+Found by Linux Verification Center (linuxtesting.org) with the Svace static
+analysis tool.
+
+Fixes: 8bd954c56197 ("usb: host: xhci-plat: suspend and resume clocks")
+Signed-off-by: Sergey Shtylyov <s.shtylyov@omp.ru>
+Signed-off-by: Mathias Nyman <mathias.nyman@linux.intel.com>
+Link: https://lore.kernel.org/r/20231019102924.2797346-19-mathias.nyman@linux.intel.com
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/usb/host/xhci-plat.c | 23 +++++++++++++++++++----
+ 1 file changed, 19 insertions(+), 4 deletions(-)
+
+diff --git a/drivers/usb/host/xhci-plat.c b/drivers/usb/host/xhci-plat.c
+index 972a44b2a7f12..e56a1fb9715a7 100644
+--- a/drivers/usb/host/xhci-plat.c
++++ b/drivers/usb/host/xhci-plat.c
+@@ -466,23 +466,38 @@ static int __maybe_unused xhci_plat_resume(struct device *dev)
+ int ret;
+
+ if (!device_may_wakeup(dev) && (xhci->quirks & XHCI_SUSPEND_RESUME_CLKS)) {
+- clk_prepare_enable(xhci->clk);
+- clk_prepare_enable(xhci->reg_clk);
++ ret = clk_prepare_enable(xhci->clk);
++ if (ret)
++ return ret;
++
++ ret = clk_prepare_enable(xhci->reg_clk);
++ if (ret) {
++ clk_disable_unprepare(xhci->clk);
++ return ret;
++ }
+ }
+
+ ret = xhci_priv_resume_quirk(hcd);
+ if (ret)
+- return ret;
++ goto disable_clks;
+
+ ret = xhci_resume(xhci, 0);
+ if (ret)
+- return ret;
++ goto disable_clks;
+
+ pm_runtime_disable(dev);
+ pm_runtime_set_active(dev);
+ pm_runtime_enable(dev);
+
+ return 0;
++
++disable_clks:
++ if (!device_may_wakeup(dev) && (xhci->quirks & XHCI_SUSPEND_RESUME_CLKS)) {
++ clk_disable_unprepare(xhci->clk);
++ clk_disable_unprepare(xhci->reg_clk);
++ }
++
++ return ret;
+ }
+
+ static int __maybe_unused xhci_plat_runtime_suspend(struct device *dev)
+--
+2.42.0
+
--- /dev/null
+From dd3452b179005743b4c2a4490a20b3d7d97b8f25 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 15 Jun 2023 11:28:10 +0200
+Subject: USB: usbip: fix stub_dev hub disconnect
+
+From: Jonas Blixt <jonas.blixt@actia.se>
+
+[ Upstream commit 97475763484245916735a1aa9a3310a01d46b008 ]
+
+If a hub is disconnected that has device(s) that's attached to the usbip layer
+the disconnect function might fail because it tries to release the port
+on an already disconnected hub.
+
+Fixes: 6080cd0e9239 ("staging: usbip: claim ports used by shared devices")
+Signed-off-by: Jonas Blixt <jonas.blixt@actia.se>
+Acked-by: Shuah Khan <skhan@linuxfoundation.org>
+Link: https://lore.kernel.org/r/20230615092810.1215490-1-jonas.blixt@actia.se
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/usb/usbip/stub_dev.c | 9 +++++++--
+ 1 file changed, 7 insertions(+), 2 deletions(-)
+
+diff --git a/drivers/usb/usbip/stub_dev.c b/drivers/usb/usbip/stub_dev.c
+index 3c6d452e3bf40..4104eea03e806 100644
+--- a/drivers/usb/usbip/stub_dev.c
++++ b/drivers/usb/usbip/stub_dev.c
+@@ -462,8 +462,13 @@ static void stub_disconnect(struct usb_device *udev)
+ /* release port */
+ rc = usb_hub_release_port(udev->parent, udev->portnum,
+ (struct usb_dev_state *) udev);
+- if (rc) {
+- dev_dbg(&udev->dev, "unable to release port\n");
++ /*
++ * NOTE: If a HUB disconnect triggered disconnect of the down stream
++ * device usb_hub_release_port will return -ENODEV so we can safely ignore
++ * that error here.
++ */
++ if (rc && (rc != -ENODEV)) {
++ dev_dbg(&udev->dev, "unable to release port (%i)\n", rc);
+ return;
+ }
+
+--
+2.42.0
+
--- /dev/null
+From 8ca31451a374146f5664b0f0ecac349b71459ccc Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 2 Oct 2023 20:57:04 -0500
+Subject: vfs: fix readahead(2) on block devices
+
+From: Reuben Hawkins <reubenhwk@gmail.com>
+
+[ Upstream commit 7116c0af4b8414b2f19fdb366eea213cbd9d91c2 ]
+
+Readahead was factored to call generic_fadvise. That refactor added an
+S_ISREG restriction which broke readahead on block devices.
+
+In addition to S_ISREG, this change checks S_ISBLK to fix block device
+readahead. There is no change in behavior with any file type besides block
+devices in this change.
+
+Fixes: 3d8f7615319b ("vfs: implement readahead(2) using POSIX_FADV_WILLNEED")
+Signed-off-by: Reuben Hawkins <reubenhwk@gmail.com>
+Link: https://lore.kernel.org/r/20231003015704.2415-1-reubenhwk@gmail.com
+Reviewed-by: Amir Goldstein <amir73il@gmail.com>
+Signed-off-by: Christian Brauner <brauner@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ mm/readahead.c | 3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+diff --git a/mm/readahead.c b/mm/readahead.c
+index 41b75d76d36e1..a8f7e4e550f43 100644
+--- a/mm/readahead.c
++++ b/mm/readahead.c
+@@ -627,7 +627,8 @@ ssize_t ksys_readahead(int fd, loff_t offset, size_t count)
+ */
+ ret = -EINVAL;
+ if (!f.file->f_mapping || !f.file->f_mapping->a_ops ||
+- !S_ISREG(file_inode(f.file)->i_mode))
++ (!S_ISREG(file_inode(f.file)->i_mode) &&
++ !S_ISBLK(file_inode(f.file)->i_mode)))
+ goto out;
+
+ ret = vfs_fadvise(f.file, offset, count, POSIX_FADV_WILLNEED);
+--
+2.42.0
+
--- /dev/null
+From 5ee571844915fa6aee9cbffedf96b7fc018c4da2 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sun, 16 Apr 2023 15:47:26 +0300
+Subject: wifi: iwlwifi: call napi_synchronize() before freeing rx/tx queues
+
+From: Gregory Greenman <gregory.greenman@intel.com>
+
+[ Upstream commit 5af2bb3168db6b0af9988eb25cccf2e3bc4455e2 ]
+
+When rx/tx queues are being freed, on a different CPU there could be
+still rx flow running. Call napi_synchronize() to prevent such a race.
+
+Signed-off-by: Gregory Greenman <gregory.greenman@intel.com>
+Co-developed-by: Benjamin Berg <benjamin.berg@intel.com>
+Signed-off-by: Benjamin Berg <benjamin.berg@intel.com>
+Link: https://lore.kernel.org/r/20230416154301.5171ee44dcc1.Iff18718540da412e084e7d8266447d40730600ed@changeid
+Signed-off-by: Johannes Berg <johannes.berg@intel.com>
+Stable-dep-of: 37fb29bd1f90 ("wifi: iwlwifi: pcie: synchronize IRQs before NAPI")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ .../net/wireless/intel/iwlwifi/pcie/internal.h | 1 +
+ drivers/net/wireless/intel/iwlwifi/pcie/rx.c | 18 +++++++++++++++++-
+ .../wireless/intel/iwlwifi/pcie/trans-gen2.c | 1 +
+ .../net/wireless/intel/iwlwifi/pcie/trans.c | 1 +
+ 4 files changed, 20 insertions(+), 1 deletion(-)
+
+diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/internal.h b/drivers/net/wireless/intel/iwlwifi/pcie/internal.h
+index 775ee03e5b128..74959de9d7002 100644
+--- a/drivers/net/wireless/intel/iwlwifi/pcie/internal.h
++++ b/drivers/net/wireless/intel/iwlwifi/pcie/internal.h
+@@ -480,6 +480,7 @@ int iwl_pcie_rx_stop(struct iwl_trans *trans);
+ void iwl_pcie_rx_free(struct iwl_trans *trans);
+ void iwl_pcie_free_rbs_pool(struct iwl_trans *trans);
+ void iwl_pcie_rx_init_rxb_lists(struct iwl_rxq *rxq);
++void iwl_pcie_rx_napi_sync(struct iwl_trans *trans);
+ void iwl_pcie_rxq_alloc_rbs(struct iwl_trans *trans, gfp_t priority,
+ struct iwl_rxq *rxq);
+
+diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/rx.c b/drivers/net/wireless/intel/iwlwifi/pcie/rx.c
+index 74b4280221e0f..df201d40f6c95 100644
+--- a/drivers/net/wireless/intel/iwlwifi/pcie/rx.c
++++ b/drivers/net/wireless/intel/iwlwifi/pcie/rx.c
+@@ -1,6 +1,6 @@
+ // SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
+ /*
+- * Copyright (C) 2003-2014, 2018-2022 Intel Corporation
++ * Copyright (C) 2003-2014, 2018-2023 Intel Corporation
+ * Copyright (C) 2013-2015 Intel Mobile Communications GmbH
+ * Copyright (C) 2016-2017 Intel Deutschland GmbH
+ */
+@@ -1050,6 +1050,22 @@ static int iwl_pcie_napi_poll_msix(struct napi_struct *napi, int budget)
+ return ret;
+ }
+
++void iwl_pcie_rx_napi_sync(struct iwl_trans *trans)
++{
++ struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
++ int i;
++
++ if (unlikely(!trans_pcie->rxq))
++ return;
++
++ for (i = 0; i < trans->num_rx_queues; i++) {
++ struct iwl_rxq *rxq = &trans_pcie->rxq[i];
++
++ if (rxq && rxq->napi.poll)
++ napi_synchronize(&rxq->napi);
++ }
++}
++
+ static int _iwl_pcie_rx_init(struct iwl_trans *trans)
+ {
+ struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
+diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/trans-gen2.c b/drivers/net/wireless/intel/iwlwifi/pcie/trans-gen2.c
+index a9c19be29e92e..69e2c2c98281f 100644
+--- a/drivers/net/wireless/intel/iwlwifi/pcie/trans-gen2.c
++++ b/drivers/net/wireless/intel/iwlwifi/pcie/trans-gen2.c
+@@ -165,6 +165,7 @@ void _iwl_trans_pcie_gen2_stop_device(struct iwl_trans *trans)
+ if (test_and_clear_bit(STATUS_DEVICE_ENABLED, &trans->status)) {
+ IWL_DEBUG_INFO(trans,
+ "DEVICE_ENABLED bit was set and is now cleared\n");
++ iwl_pcie_rx_napi_sync(trans);
+ iwl_txq_gen2_tx_free(trans);
+ iwl_pcie_rx_stop(trans);
+ }
+diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/trans.c b/drivers/net/wireless/intel/iwlwifi/pcie/trans.c
+index 4456aef930cf4..337f26e725315 100644
+--- a/drivers/net/wireless/intel/iwlwifi/pcie/trans.c
++++ b/drivers/net/wireless/intel/iwlwifi/pcie/trans.c
+@@ -1197,6 +1197,7 @@ static void _iwl_trans_pcie_stop_device(struct iwl_trans *trans)
+ if (test_and_clear_bit(STATUS_DEVICE_ENABLED, &trans->status)) {
+ IWL_DEBUG_INFO(trans,
+ "DEVICE_ENABLED bit was set and is now cleared\n");
++ iwl_pcie_rx_napi_sync(trans);
+ iwl_pcie_tx_stop(trans);
+ iwl_pcie_rx_stop(trans);
+
+--
+2.42.0
+
--- /dev/null
+From b06b261a4be64d97fef63f2490b947ba976a08ce Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sun, 22 Oct 2023 17:55:51 +0300
+Subject: wifi: iwlwifi: empty overflow queue during flush
+
+From: Miri Korenblit <miriam.rachel.korenblit@intel.com>
+
+[ Upstream commit 658939fc68d3241f9a0019e224cd7154438c23f2 ]
+
+If a TX queue has no space for new TX frames, the driver will keep
+these frames in the overflow queue, and during reclaim flow it
+will retry to send the frames from that queue.
+But if the reclaim flow was invoked from TX queue flush, we will also
+TX these frames, which is wrong as we don't want to TX anything
+after flush.
+This might also cause assert 0x125F when removing the queue,
+saying that the driver removes a non-empty queue
+Fix this by TXing the overflow queue's frames only if we are
+not in flush queue flow.
+
+Fixes: a44509805895 ("iwlwifi: move reclaim flows to the queue file")
+Signed-off-by: Miri Korenblit <miriam.rachel.korenblit@intel.com>
+Signed-off-by: Gregory Greenman <gregory.greenman@intel.com>
+Link: https://lore.kernel.org/r/20231022173519.caf06c8709d9.Ibf664ccb3f952e836f8fa461ea58fc08e5c46e88@changeid
+Signed-off-by: Johannes Berg <johannes.berg@intel.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/wireless/intel/iwlwifi/dvm/tx.c | 5 +++--
+ drivers/net/wireless/intel/iwlwifi/iwl-trans.h | 7 ++++---
+ drivers/net/wireless/intel/iwlwifi/mvm/tx.c | 4 ++--
+ drivers/net/wireless/intel/iwlwifi/queue/tx.c | 9 +++++----
+ drivers/net/wireless/intel/iwlwifi/queue/tx.h | 2 +-
+ 5 files changed, 15 insertions(+), 12 deletions(-)
+
+diff --git a/drivers/net/wireless/intel/iwlwifi/dvm/tx.c b/drivers/net/wireless/intel/iwlwifi/dvm/tx.c
+index 60a7b61d59aa3..ca1daec641c4f 100644
+--- a/drivers/net/wireless/intel/iwlwifi/dvm/tx.c
++++ b/drivers/net/wireless/intel/iwlwifi/dvm/tx.c
+@@ -3,6 +3,7 @@
+ *
+ * Copyright(c) 2008 - 2014 Intel Corporation. All rights reserved.
+ * Copyright (C) 2019 Intel Corporation
++ * Copyright (C) 2023 Intel Corporation
+ *****************************************************************************/
+
+ #include <linux/kernel.h>
+@@ -1169,7 +1170,7 @@ void iwlagn_rx_reply_tx(struct iwl_priv *priv, struct iwl_rx_cmd_buffer *rxb)
+ iwlagn_check_ratid_empty(priv, sta_id, tid);
+ }
+
+- iwl_trans_reclaim(priv->trans, txq_id, ssn, &skbs);
++ iwl_trans_reclaim(priv->trans, txq_id, ssn, &skbs, false);
+
+ freed = 0;
+
+@@ -1315,7 +1316,7 @@ void iwlagn_rx_reply_compressed_ba(struct iwl_priv *priv,
+ * block-ack window (we assume that they've been successfully
+ * transmitted ... if not, it's too late anyway). */
+ iwl_trans_reclaim(priv->trans, scd_flow, ba_resp_scd_ssn,
+- &reclaimed_skbs);
++ &reclaimed_skbs, false);
+
+ IWL_DEBUG_TX_REPLY(priv, "REPLY_COMPRESSED_BA [%d] Received from %pM, "
+ "sta_id = %d\n",
+diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-trans.h b/drivers/net/wireless/intel/iwlwifi/iwl-trans.h
+index 8f0ff540f4398..a2919a32d7081 100644
+--- a/drivers/net/wireless/intel/iwlwifi/iwl-trans.h
++++ b/drivers/net/wireless/intel/iwlwifi/iwl-trans.h
+@@ -539,7 +539,7 @@ struct iwl_trans_ops {
+ int (*tx)(struct iwl_trans *trans, struct sk_buff *skb,
+ struct iwl_device_tx_cmd *dev_cmd, int queue);
+ void (*reclaim)(struct iwl_trans *trans, int queue, int ssn,
+- struct sk_buff_head *skbs);
++ struct sk_buff_head *skbs, bool is_flush);
+
+ void (*set_q_ptrs)(struct iwl_trans *trans, int queue, int ptr);
+
+@@ -1122,14 +1122,15 @@ static inline int iwl_trans_tx(struct iwl_trans *trans, struct sk_buff *skb,
+ }
+
+ static inline void iwl_trans_reclaim(struct iwl_trans *trans, int queue,
+- int ssn, struct sk_buff_head *skbs)
++ int ssn, struct sk_buff_head *skbs,
++ bool is_flush)
+ {
+ if (WARN_ON_ONCE(trans->state != IWL_TRANS_FW_ALIVE)) {
+ IWL_ERR(trans, "%s bad state = %d\n", __func__, trans->state);
+ return;
+ }
+
+- trans->ops->reclaim(trans, queue, ssn, skbs);
++ trans->ops->reclaim(trans, queue, ssn, skbs, is_flush);
+ }
+
+ static inline void iwl_trans_set_q_ptrs(struct iwl_trans *trans, int queue,
+diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/tx.c b/drivers/net/wireless/intel/iwlwifi/mvm/tx.c
+index 5304edd351db2..08dd227bad4b1 100644
+--- a/drivers/net/wireless/intel/iwlwifi/mvm/tx.c
++++ b/drivers/net/wireless/intel/iwlwifi/mvm/tx.c
+@@ -1436,7 +1436,7 @@ static void iwl_mvm_rx_tx_cmd_single(struct iwl_mvm *mvm,
+ seq_ctl = le16_to_cpu(tx_resp->seq_ctl);
+
+ /* we can free until ssn % q.n_bd not inclusive */
+- iwl_trans_reclaim(mvm->trans, txq_id, ssn, &skbs);
++ iwl_trans_reclaim(mvm->trans, txq_id, ssn, &skbs, false);
+
+ while (!skb_queue_empty(&skbs)) {
+ struct sk_buff *skb = __skb_dequeue(&skbs);
+@@ -1781,7 +1781,7 @@ static void iwl_mvm_tx_reclaim(struct iwl_mvm *mvm, int sta_id, int tid,
+ * block-ack window (we assume that they've been successfully
+ * transmitted ... if not, it's too late anyway).
+ */
+- iwl_trans_reclaim(mvm->trans, txq, index, &reclaimed_skbs);
++ iwl_trans_reclaim(mvm->trans, txq, index, &reclaimed_skbs, is_flush);
+
+ skb_queue_walk(&reclaimed_skbs, skb) {
+ struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
+diff --git a/drivers/net/wireless/intel/iwlwifi/queue/tx.c b/drivers/net/wireless/intel/iwlwifi/queue/tx.c
+index 8522cdfc9e5d3..cd852b95d8125 100644
+--- a/drivers/net/wireless/intel/iwlwifi/queue/tx.c
++++ b/drivers/net/wireless/intel/iwlwifi/queue/tx.c
+@@ -1520,7 +1520,7 @@ void iwl_txq_progress(struct iwl_txq *txq)
+
+ /* Frees buffers until index _not_ inclusive */
+ void iwl_txq_reclaim(struct iwl_trans *trans, int txq_id, int ssn,
+- struct sk_buff_head *skbs)
++ struct sk_buff_head *skbs, bool is_flush)
+ {
+ struct iwl_txq *txq = trans->txqs.txq[txq_id];
+ int tfd_num = iwl_txq_get_cmd_index(txq, ssn);
+@@ -1591,9 +1591,11 @@ void iwl_txq_reclaim(struct iwl_trans *trans, int txq_id, int ssn,
+ if (iwl_txq_space(trans, txq) > txq->low_mark &&
+ test_bit(txq_id, trans->txqs.queue_stopped)) {
+ struct sk_buff_head overflow_skbs;
++ struct sk_buff *skb;
+
+ __skb_queue_head_init(&overflow_skbs);
+- skb_queue_splice_init(&txq->overflow_q, &overflow_skbs);
++ skb_queue_splice_init(&txq->overflow_q,
++ is_flush ? skbs : &overflow_skbs);
+
+ /*
+ * We are going to transmit from the overflow queue.
+@@ -1613,8 +1615,7 @@ void iwl_txq_reclaim(struct iwl_trans *trans, int txq_id, int ssn,
+ */
+ spin_unlock_bh(&txq->lock);
+
+- while (!skb_queue_empty(&overflow_skbs)) {
+- struct sk_buff *skb = __skb_dequeue(&overflow_skbs);
++ while ((skb = __skb_dequeue(&overflow_skbs))) {
+ struct iwl_device_tx_cmd *dev_cmd_ptr;
+
+ dev_cmd_ptr = *(void **)((u8 *)skb->cb +
+diff --git a/drivers/net/wireless/intel/iwlwifi/queue/tx.h b/drivers/net/wireless/intel/iwlwifi/queue/tx.h
+index 19178c88bb229..f488fc9f6b83e 100644
+--- a/drivers/net/wireless/intel/iwlwifi/queue/tx.h
++++ b/drivers/net/wireless/intel/iwlwifi/queue/tx.h
+@@ -174,7 +174,7 @@ void iwl_txq_gen1_update_byte_cnt_tbl(struct iwl_trans *trans,
+ struct iwl_txq *txq, u16 byte_cnt,
+ int num_tbs);
+ void iwl_txq_reclaim(struct iwl_trans *trans, int txq_id, int ssn,
+- struct sk_buff_head *skbs);
++ struct sk_buff_head *skbs, bool is_flush);
+ void iwl_txq_set_q_ptrs(struct iwl_trans *trans, int txq_id, int ptr);
+ void iwl_trans_txq_freeze_timer(struct iwl_trans *trans, unsigned long txqs,
+ bool freeze);
+--
+2.42.0
+
--- /dev/null
+From d3102f071138f3aeaa76a38b5e1d64371320fce3 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 17 Oct 2023 12:16:43 +0300
+Subject: wifi: iwlwifi: pcie: synchronize IRQs before NAPI
+
+From: Johannes Berg <johannes.berg@intel.com>
+
+[ Upstream commit 37fb29bd1f90f16d1abc95c0e9f0ff8eec9829ad ]
+
+When we want to synchronize the NAPI, which was added in
+commit 5af2bb3168db ("wifi: iwlwifi: call napi_synchronize()
+before freeing rx/tx queues"), we also need to make sure we
+can't actually reschedule the NAPI. Yes, this happens while
+interrupts are disabled, but interrupts may still be running
+or pending. Also call iwl_pcie_synchronize_irqs() to ensure
+we won't reschedule the NAPI.
+
+Fixes: 4cf2f5904d97 ("iwlwifi: queue: avoid memory leak in reset flow")
+Signed-off-by: Johannes Berg <johannes.berg@intel.com>
+Signed-off-by: Gregory Greenman <gregory.greenman@intel.com>
+Link: https://lore.kernel.org/r/20231017115047.a0f4104b479a.Id5c50a944f709092aa6256e32d8c63b2b8d8d3ac@changeid
+Signed-off-by: Johannes Berg <johannes.berg@intel.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/wireless/intel/iwlwifi/pcie/trans-gen2.c | 1 +
+ drivers/net/wireless/intel/iwlwifi/pcie/trans.c | 1 +
+ 2 files changed, 2 insertions(+)
+
+diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/trans-gen2.c b/drivers/net/wireless/intel/iwlwifi/pcie/trans-gen2.c
+index 69e2c2c98281f..1b25a6627e5c7 100644
+--- a/drivers/net/wireless/intel/iwlwifi/pcie/trans-gen2.c
++++ b/drivers/net/wireless/intel/iwlwifi/pcie/trans-gen2.c
+@@ -165,6 +165,7 @@ void _iwl_trans_pcie_gen2_stop_device(struct iwl_trans *trans)
+ if (test_and_clear_bit(STATUS_DEVICE_ENABLED, &trans->status)) {
+ IWL_DEBUG_INFO(trans,
+ "DEVICE_ENABLED bit was set and is now cleared\n");
++ iwl_pcie_synchronize_irqs(trans);
+ iwl_pcie_rx_napi_sync(trans);
+ iwl_txq_gen2_tx_free(trans);
+ iwl_pcie_rx_stop(trans);
+diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/trans.c b/drivers/net/wireless/intel/iwlwifi/pcie/trans.c
+index 337f26e725315..b7b2d28b3e436 100644
+--- a/drivers/net/wireless/intel/iwlwifi/pcie/trans.c
++++ b/drivers/net/wireless/intel/iwlwifi/pcie/trans.c
+@@ -1197,6 +1197,7 @@ static void _iwl_trans_pcie_stop_device(struct iwl_trans *trans)
+ if (test_and_clear_bit(STATUS_DEVICE_ENABLED, &trans->status)) {
+ IWL_DEBUG_INFO(trans,
+ "DEVICE_ENABLED bit was set and is now cleared\n");
++ iwl_pcie_synchronize_irqs(trans);
+ iwl_pcie_rx_napi_sync(trans);
+ iwl_pcie_tx_stop(trans);
+ iwl_pcie_rx_stop(trans);
+--
+2.42.0
+
--- /dev/null
+From e6fd3bc394c77358025424a510f61d5c0184e39b Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 13 Sep 2023 14:56:45 +0300
+Subject: wifi: iwlwifi: Use FW rate for non-data frames
+
+From: Miri Korenblit <miriam.rachel.korenblit@intel.com>
+
+[ Upstream commit 499d02790495958506a64f37ceda7e97345a50a8 ]
+
+Currently we are setting the rate in the tx cmd for
+mgmt frames (e.g. during connection establishment).
+This was problematic when sending mgmt frames in eSR mode,
+as we don't know what link this frame will be sent on
+(This is decided by the FW), so we don't know what is the
+lowest rate.
+Fix this by not setting the rate in tx cmd and rely
+on FW to choose the right one.
+Set rate only for injected frames with fixed rate,
+or when no sta is given.
+Also set for important frames (EAPOL etc.) the High Priority flag.
+
+Fixes: 055b22e770dd ("iwlwifi: mvm: Set Tx rate and flags when there is not station")
+Signed-off-by: Miri Korenblit <miriam.rachel.korenblit@intel.com>
+Signed-off-by: Gregory Greenman <gregory.greenman@intel.com>
+Link: https://lore.kernel.org/r/20230913145231.6c7e59620ee0.I6eaed3ccdd6dd62b9e664facc484081fc5275843@changeid
+Signed-off-by: Johannes Berg <johannes.berg@intel.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/wireless/intel/iwlwifi/mvm/tx.c | 14 +++++++++-----
+ 1 file changed, 9 insertions(+), 5 deletions(-)
+
+diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/tx.c b/drivers/net/wireless/intel/iwlwifi/mvm/tx.c
+index b127e0b527ce0..5304edd351db2 100644
+--- a/drivers/net/wireless/intel/iwlwifi/mvm/tx.c
++++ b/drivers/net/wireless/intel/iwlwifi/mvm/tx.c
+@@ -479,16 +479,20 @@ iwl_mvm_set_tx_params(struct iwl_mvm *mvm, struct sk_buff *skb,
+ flags |= IWL_TX_FLAGS_ENCRYPT_DIS;
+
+ /*
+- * For data packets rate info comes from the fw. Only
+- * set rate/antenna during connection establishment or in case
+- * no station is given.
++ * For data and mgmt packets rate info comes from the fw. Only
++ * set rate/antenna for injected frames with fixed rate, or
++ * when no sta is given.
+ */
+- if (!sta || !ieee80211_is_data(hdr->frame_control) ||
+- mvmsta->sta_state < IEEE80211_STA_AUTHORIZED) {
++ if (unlikely(!sta ||
++ info->control.flags & IEEE80211_TX_CTRL_RATE_INJECT)) {
+ flags |= IWL_TX_FLAGS_CMD_RATE;
+ rate_n_flags =
+ iwl_mvm_get_tx_rate_n_flags(mvm, info, sta,
+ hdr->frame_control);
++ } else if (!ieee80211_is_data(hdr->frame_control) ||
++ mvmsta->sta_state < IEEE80211_STA_AUTHORIZED) {
++ /* These are important frames */
++ flags |= IWL_TX_FLAGS_HIGH_PRI;
+ }
+
+ if (mvm->trans->trans_cfg->device_family >=
+--
+2.42.0
+
--- /dev/null
+From 96730d9a1dcbb0718c555443e8b8a9d4875ecdd0 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 28 Jul 2023 16:21:18 +0200
+Subject: wifi: mt76: mt7603: improve stuck beacon handling
+
+From: Felix Fietkau <nbd@nbd.name>
+
+[ Upstream commit 3176205933494bd184c6acd70e796c382bc729b5 ]
+
+Before preparing the new beacon, check the queue status, flush out all
+previous beacons and buffered multicast packets, then (if necessary)
+try to recover more gracefully from a stuck beacon condition by making a
+less invasive attempt at getting the MAC un-stuck.
+
+Fixes: c8846e101502 ("mt76: add driver for MT7603E and MT7628/7688")
+Signed-off-by: Felix Fietkau <nbd@nbd.name>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ .../wireless/mediatek/mt76/mt7603/beacon.c | 76 ++++++++++++++-----
+ .../net/wireless/mediatek/mt76/mt7603/regs.h | 5 ++
+ 2 files changed, 60 insertions(+), 21 deletions(-)
+
+diff --git a/drivers/net/wireless/mediatek/mt76/mt7603/beacon.c b/drivers/net/wireless/mediatek/mt76/mt7603/beacon.c
+index e35e0a68c6e48..7fa6b0ed9d478 100644
+--- a/drivers/net/wireless/mediatek/mt76/mt7603/beacon.c
++++ b/drivers/net/wireless/mediatek/mt76/mt7603/beacon.c
+@@ -9,6 +9,23 @@ struct beacon_bc_data {
+ int count[MT7603_MAX_INTERFACES];
+ };
+
++static void
++mt7603_mac_stuck_beacon_recovery(struct mt7603_dev *dev)
++{
++ if (dev->beacon_check % 5 != 4)
++ return;
++
++ mt76_clear(dev, MT_WPDMA_GLO_CFG, MT_WPDMA_GLO_CFG_TX_DMA_EN);
++ mt76_set(dev, MT_SCH_4, MT_SCH_4_RESET);
++ mt76_clear(dev, MT_SCH_4, MT_SCH_4_RESET);
++ mt76_set(dev, MT_WPDMA_GLO_CFG, MT_WPDMA_GLO_CFG_TX_DMA_EN);
++
++ mt76_set(dev, MT_WF_CFG_OFF_WOCCR, MT_WF_CFG_OFF_WOCCR_TMAC_GC_DIS);
++ mt76_set(dev, MT_ARB_SCR, MT_ARB_SCR_TX_DISABLE);
++ mt76_clear(dev, MT_ARB_SCR, MT_ARB_SCR_TX_DISABLE);
++ mt76_clear(dev, MT_WF_CFG_OFF_WOCCR, MT_WF_CFG_OFF_WOCCR_TMAC_GC_DIS);
++}
++
+ static void
+ mt7603_update_beacon_iter(void *priv, u8 *mac, struct ieee80211_vif *vif)
+ {
+@@ -16,6 +33,8 @@ mt7603_update_beacon_iter(void *priv, u8 *mac, struct ieee80211_vif *vif)
+ struct mt76_dev *mdev = &dev->mt76;
+ struct mt7603_vif *mvif = (struct mt7603_vif *)vif->drv_priv;
+ struct sk_buff *skb = NULL;
++ u32 om_idx = mvif->idx;
++ u32 val;
+
+ if (!(mdev->beacon_mask & BIT(mvif->idx)))
+ return;
+@@ -24,20 +43,33 @@ mt7603_update_beacon_iter(void *priv, u8 *mac, struct ieee80211_vif *vif)
+ if (!skb)
+ return;
+
+- mt76_tx_queue_skb(dev, dev->mphy.q_tx[MT_TXQ_BEACON],
+- MT_TXQ_BEACON, skb, &mvif->sta.wcid, NULL);
++ if (om_idx)
++ om_idx |= 0x10;
++ val = MT_DMA_FQCR0_BUSY | MT_DMA_FQCR0_MODE |
++ FIELD_PREP(MT_DMA_FQCR0_TARGET_BSS, om_idx) |
++ FIELD_PREP(MT_DMA_FQCR0_DEST_PORT_ID, 3) |
++ FIELD_PREP(MT_DMA_FQCR0_DEST_QUEUE_ID, 8);
+
+ spin_lock_bh(&dev->ps_lock);
+- mt76_wr(dev, MT_DMA_FQCR0, MT_DMA_FQCR0_BUSY |
+- FIELD_PREP(MT_DMA_FQCR0_TARGET_WCID, mvif->sta.wcid.idx) |
+- FIELD_PREP(MT_DMA_FQCR0_TARGET_QID,
+- dev->mphy.q_tx[MT_TXQ_CAB]->hw_idx) |
+- FIELD_PREP(MT_DMA_FQCR0_DEST_PORT_ID, 3) |
+- FIELD_PREP(MT_DMA_FQCR0_DEST_QUEUE_ID, 8));
+
+- if (!mt76_poll(dev, MT_DMA_FQCR0, MT_DMA_FQCR0_BUSY, 0, 5000))
++ mt76_wr(dev, MT_DMA_FQCR0, val |
++ FIELD_PREP(MT_DMA_FQCR0_TARGET_QID, MT_TX_HW_QUEUE_BCN));
++ if (!mt76_poll(dev, MT_DMA_FQCR0, MT_DMA_FQCR0_BUSY, 0, 5000)) {
+ dev->beacon_check = MT7603_WATCHDOG_TIMEOUT;
++ goto out;
++ }
++
++ mt76_wr(dev, MT_DMA_FQCR0, val |
++ FIELD_PREP(MT_DMA_FQCR0_TARGET_QID, MT_TX_HW_QUEUE_BMC));
++ if (!mt76_poll(dev, MT_DMA_FQCR0, MT_DMA_FQCR0_BUSY, 0, 5000)) {
++ dev->beacon_check = MT7603_WATCHDOG_TIMEOUT;
++ goto out;
++ }
+
++ mt76_tx_queue_skb(dev, dev->mphy.q_tx[MT_TXQ_BEACON],
++ MT_TXQ_BEACON, skb, &mvif->sta.wcid, NULL);
++
++out:
+ spin_unlock_bh(&dev->ps_lock);
+ }
+
+@@ -81,6 +113,18 @@ void mt7603_pre_tbtt_tasklet(struct tasklet_struct *t)
+ data.dev = dev;
+ __skb_queue_head_init(&data.q);
+
++ /* Flush all previous CAB queue packets and beacons */
++ mt76_wr(dev, MT_WF_ARB_CAB_FLUSH, GENMASK(30, 16) | BIT(0));
++
++ mt76_queue_tx_cleanup(dev, dev->mphy.q_tx[MT_TXQ_CAB], false);
++ mt76_queue_tx_cleanup(dev, dev->mphy.q_tx[MT_TXQ_BEACON], false);
++
++ if (dev->mphy.q_tx[MT_TXQ_BEACON]->queued > 0)
++ dev->beacon_check++;
++ else
++ dev->beacon_check = 0;
++ mt7603_mac_stuck_beacon_recovery(dev);
++
+ q = dev->mphy.q_tx[MT_TXQ_BEACON];
+ spin_lock_bh(&q->lock);
+ ieee80211_iterate_active_interfaces_atomic(mt76_hw(dev),
+@@ -89,14 +133,9 @@ void mt7603_pre_tbtt_tasklet(struct tasklet_struct *t)
+ mt76_queue_kick(dev, q);
+ spin_unlock_bh(&q->lock);
+
+- /* Flush all previous CAB queue packets */
+- mt76_wr(dev, MT_WF_ARB_CAB_FLUSH, GENMASK(30, 16) | BIT(0));
+-
+- mt76_queue_tx_cleanup(dev, dev->mphy.q_tx[MT_TXQ_CAB], false);
+-
+ mt76_csa_check(mdev);
+ if (mdev->csa_complete)
+- goto out;
++ return;
+
+ q = dev->mphy.q_tx[MT_TXQ_CAB];
+ do {
+@@ -108,7 +147,7 @@ void mt7603_pre_tbtt_tasklet(struct tasklet_struct *t)
+ skb_queue_len(&data.q) < 8);
+
+ if (skb_queue_empty(&data.q))
+- goto out;
++ return;
+
+ for (i = 0; i < ARRAY_SIZE(data.tail); i++) {
+ if (!data.tail[i])
+@@ -136,11 +175,6 @@ void mt7603_pre_tbtt_tasklet(struct tasklet_struct *t)
+ MT_WF_ARB_CAB_START_BSSn(0) |
+ (MT_WF_ARB_CAB_START_BSS0n(1) *
+ ((1 << (MT7603_MAX_INTERFACES - 1)) - 1)));
+-
+-out:
+- mt76_queue_tx_cleanup(dev, dev->mphy.q_tx[MT_TXQ_BEACON], false);
+- if (dev->mphy.q_tx[MT_TXQ_BEACON]->queued > hweight8(mdev->beacon_mask))
+- dev->beacon_check++;
+ }
+
+ void mt7603_beacon_set_timer(struct mt7603_dev *dev, int idx, int intval)
+diff --git a/drivers/net/wireless/mediatek/mt76/mt7603/regs.h b/drivers/net/wireless/mediatek/mt76/mt7603/regs.h
+index 3b901090b29c6..9b84db233aceb 100644
+--- a/drivers/net/wireless/mediatek/mt76/mt7603/regs.h
++++ b/drivers/net/wireless/mediatek/mt76/mt7603/regs.h
+@@ -462,6 +462,11 @@ enum {
+ #define MT_WF_SEC_BASE 0x21a00
+ #define MT_WF_SEC(ofs) (MT_WF_SEC_BASE + (ofs))
+
++#define MT_WF_CFG_OFF_BASE 0x21e00
++#define MT_WF_CFG_OFF(ofs) (MT_WF_CFG_OFF_BASE + (ofs))
++#define MT_WF_CFG_OFF_WOCCR MT_WF_CFG_OFF(0x004)
++#define MT_WF_CFG_OFF_WOCCR_TMAC_GC_DIS BIT(4)
++
+ #define MT_SEC_SCR MT_WF_SEC(0x004)
+ #define MT_SEC_SCR_MASK_ORDER GENMASK(1, 0)
+
+--
+2.42.0
+
--- /dev/null
+From 6682a4eabf184dc9531c06caa13c870603d23080 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 28 Jul 2023 09:51:01 +0200
+Subject: wifi: mt76: mt7603: rework/fix rx pse hang check
+
+From: Felix Fietkau <nbd@nbd.name>
+
+[ Upstream commit baa19b2e4b7bbb509a7ca7939c8785477dcd40ee ]
+
+It turns out that the code in mt7603_rx_pse_busy() does not detect actual
+hardware hangs, it only checks for busy conditions in PSE.
+A reset should only be performed if these conditions are true and if there
+is no rx activity as well.
+Reset the counter whenever a rx interrupt occurs. In order to also deal with
+a fully loaded CPU that leaves interrupts disabled with continuous NAPI
+polling, also check for pending rx interrupts in the function itself.
+
+Fixes: c8846e101502 ("mt76: add driver for MT7603E and MT7628/7688")
+Signed-off-by: Felix Fietkau <nbd@nbd.name>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ .../net/wireless/mediatek/mt76/mt7603/core.c | 2 ++
+ .../net/wireless/mediatek/mt76/mt7603/mac.c | 23 +++++++++++++------
+ 2 files changed, 18 insertions(+), 7 deletions(-)
+
+diff --git a/drivers/net/wireless/mediatek/mt76/mt7603/core.c b/drivers/net/wireless/mediatek/mt76/mt7603/core.c
+index 60a996b63c0c0..915b8349146af 100644
+--- a/drivers/net/wireless/mediatek/mt76/mt7603/core.c
++++ b/drivers/net/wireless/mediatek/mt76/mt7603/core.c
+@@ -42,11 +42,13 @@ irqreturn_t mt7603_irq_handler(int irq, void *dev_instance)
+ }
+
+ if (intr & MT_INT_RX_DONE(0)) {
++ dev->rx_pse_check = 0;
+ mt7603_irq_disable(dev, MT_INT_RX_DONE(0));
+ napi_schedule(&dev->mt76.napi[0]);
+ }
+
+ if (intr & MT_INT_RX_DONE(1)) {
++ dev->rx_pse_check = 0;
+ mt7603_irq_disable(dev, MT_INT_RX_DONE(1));
+ napi_schedule(&dev->mt76.napi[1]);
+ }
+diff --git a/drivers/net/wireless/mediatek/mt76/mt7603/mac.c b/drivers/net/wireless/mediatek/mt76/mt7603/mac.c
+index 3745512b1eb3c..915a1043c869e 100644
+--- a/drivers/net/wireless/mediatek/mt76/mt7603/mac.c
++++ b/drivers/net/wireless/mediatek/mt76/mt7603/mac.c
+@@ -1561,20 +1561,29 @@ static bool mt7603_rx_pse_busy(struct mt7603_dev *dev)
+ {
+ u32 addr, val;
+
+- if (mt76_rr(dev, MT_MCU_DEBUG_RESET) & MT_MCU_DEBUG_RESET_QUEUES)
+- return true;
+-
+ if (mt7603_rx_fifo_busy(dev))
+- return false;
++ goto out;
+
+ addr = mt7603_reg_map(dev, MT_CLIENT_BASE_PHYS_ADDR + MT_CLIENT_STATUS);
+ mt76_wr(dev, addr, 3);
+ val = mt76_rr(dev, addr) >> 16;
+
+- if (is_mt7628(dev) && (val & 0x4001) == 0x4001)
+- return true;
++ if (!(val & BIT(0)))
++ return false;
++
++ if (is_mt7628(dev))
++ val &= 0xa000;
++ else
++ val &= 0x8000;
++ if (!val)
++ return false;
++
++out:
++ if (mt76_rr(dev, MT_INT_SOURCE_CSR) &
++ (MT_INT_RX_DONE(0) | MT_INT_RX_DONE(1)))
++ return false;
+
+- return (val & 0x8001) == 0x8001 || (val & 0xe001) == 0xe001;
++ return true;
+ }
+
+ static bool
+--
+2.42.0
+
--- /dev/null
+From 3b553ab3adb0cf95678bdfaf4e5a0b5bcc096ab1 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 28 Sep 2023 08:23:19 +0300
+Subject: wifi: rtlwifi: fix EDCA limit set by BT coexistence
+
+From: Dmitry Antipov <dmantipov@yandex.ru>
+
+[ Upstream commit 3391ee7f9ea508c375d443cd712c2e699be235b4 ]
+
+In 'rtl92c_dm_check_edca_turbo()', 'rtl88e_dm_check_edca_turbo()',
+and 'rtl8723e_dm_check_edca_turbo()', the DL limit should be set
+from the corresponding field of 'rtlpriv->btcoexist' rather than
+UL. Compile tested only.
+
+Fixes: 0529c6b81761 ("rtlwifi: rtl8723ae: Update driver to match 06/28/14 Realtek version")
+Fixes: c151aed6aa14 ("rtlwifi: rtl8188ee: Update driver to match Realtek release of 06282014")
+Fixes: beb5bc402043 ("rtlwifi: rtl8192c-common: Convert common dynamic management routines for addition of rtl8192se and rtl8192de")
+Signed-off-by: Dmitry Antipov <dmantipov@yandex.ru>
+Acked-by: Ping-Ke Shih <pkshih@realtek.com>
+Signed-off-by: Kalle Valo <kvalo@kernel.org>
+Link: https://lore.kernel.org/r/20230928052327.120178-1-dmantipov@yandex.ru
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/wireless/realtek/rtlwifi/rtl8188ee/dm.c | 2 +-
+ drivers/net/wireless/realtek/rtlwifi/rtl8192c/dm_common.c | 2 +-
+ drivers/net/wireless/realtek/rtlwifi/rtl8723ae/dm.c | 2 +-
+ 3 files changed, 3 insertions(+), 3 deletions(-)
+
+diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/dm.c b/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/dm.c
+index 6f61d6a106272..5a34894a533be 100644
+--- a/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/dm.c
++++ b/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/dm.c
+@@ -799,7 +799,7 @@ static void rtl88e_dm_check_edca_turbo(struct ieee80211_hw *hw)
+ }
+
+ if (rtlpriv->btcoexist.bt_edca_dl != 0) {
+- edca_be_ul = rtlpriv->btcoexist.bt_edca_dl;
++ edca_be_dl = rtlpriv->btcoexist.bt_edca_dl;
+ bt_change_edca = true;
+ }
+
+diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192c/dm_common.c b/drivers/net/wireless/realtek/rtlwifi/rtl8192c/dm_common.c
+index 0b6a15c2e5ccd..d92aad60edfe9 100644
+--- a/drivers/net/wireless/realtek/rtlwifi/rtl8192c/dm_common.c
++++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192c/dm_common.c
+@@ -640,7 +640,7 @@ static void rtl92c_dm_check_edca_turbo(struct ieee80211_hw *hw)
+ }
+
+ if (rtlpriv->btcoexist.bt_edca_dl != 0) {
+- edca_be_ul = rtlpriv->btcoexist.bt_edca_dl;
++ edca_be_dl = rtlpriv->btcoexist.bt_edca_dl;
+ bt_change_edca = true;
+ }
+
+diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/dm.c b/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/dm.c
+index 8ada31380efa4..0ff8e355c23a4 100644
+--- a/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/dm.c
++++ b/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/dm.c
+@@ -466,7 +466,7 @@ static void rtl8723e_dm_check_edca_turbo(struct ieee80211_hw *hw)
+ }
+
+ if (rtlpriv->btcoexist.bt_edca_dl != 0) {
+- edca_be_ul = rtlpriv->btcoexist.bt_edca_dl;
++ edca_be_dl = rtlpriv->btcoexist.bt_edca_dl;
+ bt_change_edca = true;
+ }
+
+--
+2.42.0
+
--- /dev/null
+From 4496cb8842faab5d630699152d5c4a4c6ba5ccaf Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 19 Sep 2023 13:06:50 +0800
+Subject: wifi: rtw88: debug: Fix the NULL vs IS_ERR() bug for
+ debugfs_create_file()
+
+From: Jinjie Ruan <ruanjinjie@huawei.com>
+
+[ Upstream commit 74f7957c9b1b95553faaf146a2553e023a9d1720 ]
+
+Since debugfs_create_file() return ERR_PTR and never return NULL, so use
+IS_ERR() to check it instead of checking NULL.
+
+Fixes: e3037485c68e ("rtw88: new Realtek 802.11ac driver")
+Signed-off-by: Jinjie Ruan <ruanjinjie@huawei.com>
+Acked-by: Ping-Ke Shih <pkshih@realtek.com>
+Signed-off-by: Kalle Valo <kvalo@kernel.org>
+Link: https://lore.kernel.org/r/20230919050651.962694-1-ruanjinjie@huawei.com
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/wireless/realtek/rtw88/debug.c | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/drivers/net/wireless/realtek/rtw88/debug.c b/drivers/net/wireless/realtek/rtw88/debug.c
+index dfd52cff5d02f..1cc2b7b948044 100644
+--- a/drivers/net/wireless/realtek/rtw88/debug.c
++++ b/drivers/net/wireless/realtek/rtw88/debug.c
+@@ -1061,9 +1061,9 @@ static struct rtw_debugfs_priv rtw_debug_priv_dm_cap = {
+ #define rtw_debugfs_add_core(name, mode, fopname, parent) \
+ do { \
+ rtw_debug_priv_ ##name.rtwdev = rtwdev; \
+- if (!debugfs_create_file(#name, mode, \
++ if (IS_ERR(debugfs_create_file(#name, mode, \
+ parent, &rtw_debug_priv_ ##name,\
+- &file_ops_ ##fopname)) \
++ &file_ops_ ##fopname))) \
+ pr_debug("Unable to initialize debugfs:%s\n", \
+ #name); \
+ } while (0)
+--
+2.42.0
+
--- /dev/null
+From fe85b92bd3f43749108ec8f19c4c7d1627242f16 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sat, 14 Oct 2023 20:55:11 +0800
+Subject: writeback, cgroup: switch inodes with dirty timestamps to release
+ dying cgwbs
+
+From: Jingbo Xu <jefflexu@linux.alibaba.com>
+
+[ Upstream commit 6654408a33e6297d8e1d2773409431d487399b95 ]
+
+The cgwb cleanup routine will try to release the dying cgwb by switching
+the attached inodes. It fetches the attached inodes from wb->b_attached
+list, omitting the fact that inodes only with dirty timestamps reside in
+wb->b_dirty_time list, which is the case when lazytime is enabled. This
+causes enormous zombie memory cgroup when lazytime is enabled, as inodes
+with dirty timestamps can not be switched to a live cgwb for a long time.
+
+It is reasonable not to switch cgwb for inodes with dirty data, as
+otherwise it may break the bandwidth restrictions. However since the
+writeback of inode metadata is not accounted for, let's also switch
+inodes with dirty timestamps to avoid zombie memory and block cgroups
+when laztytime is enabled.
+
+Fixes: c22d70a162d3 ("writeback, cgroup: release dying cgwbs by switching attached inodes")
+Reviewed-by: Jan Kara <jack@suse.cz>
+Signed-off-by: Jingbo Xu <jefflexu@linux.alibaba.com>
+Link: https://lore.kernel.org/r/20231014125511.102978-1-jefflexu@linux.alibaba.com
+Acked-by: Tejun Heo <tj@kernel.org>
+Signed-off-by: Christian Brauner <brauner@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ fs/fs-writeback.c | 41 +++++++++++++++++++++++++++++------------
+ 1 file changed, 29 insertions(+), 12 deletions(-)
+
+diff --git a/fs/fs-writeback.c b/fs/fs-writeback.c
+index 5f0abea107e46..672d176524f5c 100644
+--- a/fs/fs-writeback.c
++++ b/fs/fs-writeback.c
+@@ -609,6 +609,24 @@ static void inode_switch_wbs(struct inode *inode, int new_wb_id)
+ kfree(isw);
+ }
+
++static bool isw_prepare_wbs_switch(struct inode_switch_wbs_context *isw,
++ struct list_head *list, int *nr)
++{
++ struct inode *inode;
++
++ list_for_each_entry(inode, list, i_io_list) {
++ if (!inode_prepare_wbs_switch(inode, isw->new_wb))
++ continue;
++
++ isw->inodes[*nr] = inode;
++ (*nr)++;
++
++ if (*nr >= WB_MAX_INODES_PER_ISW - 1)
++ return true;
++ }
++ return false;
++}
++
+ /**
+ * cleanup_offline_cgwb - detach associated inodes
+ * @wb: target wb
+@@ -621,7 +639,6 @@ bool cleanup_offline_cgwb(struct bdi_writeback *wb)
+ {
+ struct cgroup_subsys_state *memcg_css;
+ struct inode_switch_wbs_context *isw;
+- struct inode *inode;
+ int nr;
+ bool restart = false;
+
+@@ -643,17 +660,17 @@ bool cleanup_offline_cgwb(struct bdi_writeback *wb)
+
+ nr = 0;
+ spin_lock(&wb->list_lock);
+- list_for_each_entry(inode, &wb->b_attached, i_io_list) {
+- if (!inode_prepare_wbs_switch(inode, isw->new_wb))
+- continue;
+-
+- isw->inodes[nr++] = inode;
+-
+- if (nr >= WB_MAX_INODES_PER_ISW - 1) {
+- restart = true;
+- break;
+- }
+- }
++ /*
++ * In addition to the inodes that have completed writeback, also switch
++ * cgwbs for those inodes only with dirty timestamps. Otherwise, those
++ * inodes won't be written back for a long time when lazytime is
++ * enabled, and thus pinning the dying cgwbs. It won't break the
++ * bandwidth restrictions, as writeback of inode metadata is not
++ * accounted for.
++ */
++ restart = isw_prepare_wbs_switch(isw, &wb->b_attached, &nr);
++ if (!restart)
++ restart = isw_prepare_wbs_switch(isw, &wb->b_dirty_time, &nr);
+ spin_unlock(&wb->list_lock);
+
+ /* no attached inodes? bail out */
+--
+2.42.0
+
--- /dev/null
+From 5395bf30a449d855b798a6aa8b629d4a9b58c0bf Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 7 Aug 2023 16:45:47 +0800
+Subject: x86/boot: Fix incorrect startup_gdt_descr.size
+
+From: Yuntao Wang <ytcoode@gmail.com>
+
+[ Upstream commit 001470fed5959d01faecbd57fcf2f60294da0de1 ]
+
+Since the size value is added to the base address to yield the last valid
+byte address of the GDT, the current size value of startup_gdt_descr is
+incorrect (too large by one), fix it.
+
+[ mingo: This probably never mattered, because startup_gdt[] is only used
+ in a very controlled fashion - but make it consistent nevertheless. ]
+
+Fixes: 866b556efa12 ("x86/head/64: Install startup GDT")
+Signed-off-by: Yuntao Wang <ytcoode@gmail.com>
+Signed-off-by: Ingo Molnar <mingo@kernel.org>
+Cc: "H. Peter Anvin" <hpa@zytor.com>
+Link: https://lore.kernel.org/r/20230807084547.217390-1-ytcoode@gmail.com
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ arch/x86/kernel/head64.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/arch/x86/kernel/head64.c b/arch/x86/kernel/head64.c
+index 5036104d54707..2375f5f4f763f 100644
+--- a/arch/x86/kernel/head64.c
++++ b/arch/x86/kernel/head64.c
+@@ -79,7 +79,7 @@ static struct desc_struct startup_gdt[GDT_ENTRIES] = {
+ * while the kernel still uses a direct mapping.
+ */
+ static struct desc_ptr startup_gdt_descr = {
+- .size = sizeof(startup_gdt),
++ .size = sizeof(startup_gdt)-1,
+ .address = 0,
+ };
+
+--
+2.42.0
+
--- /dev/null
+From f19374e16420910ac130ee121f442856fd76ee61 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 11 Sep 2023 17:27:02 -0700
+Subject: x86/sev-es: Allow copy_from_kernel_nofault() in earlier boot
+
+From: Adam Dunlap <acdunlap@google.com>
+
+[ Upstream commit f79936545fb122856bd78b189d3c7ee59928c751 ]
+
+Previously, if copy_from_kernel_nofault() was called before
+boot_cpu_data.x86_virt_bits was set up, then it would trigger undefined
+behavior due to a shift by 64.
+
+This ended up causing boot failures in the latest version of ubuntu2204
+in the gcp project when using SEV-SNP.
+
+Specifically, this function is called during an early #VC handler which
+is triggered by a CPUID to check if NX is implemented.
+
+Fixes: 1aa9aa8ee517 ("x86/sev-es: Setup GHCB-based boot #VC handler")
+Suggested-by: Dave Hansen <dave.hansen@linux.intel.com>
+Signed-off-by: Adam Dunlap <acdunlap@google.com>
+Signed-off-by: Ingo Molnar <mingo@kernel.org>
+Tested-by: Jacob Xu <jacobhxu@google.com>
+Link: https://lore.kernel.org/r/20230912002703.3924521-2-acdunlap@google.com
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ arch/x86/mm/maccess.c | 19 ++++++++++++++-----
+ 1 file changed, 14 insertions(+), 5 deletions(-)
+
+diff --git a/arch/x86/mm/maccess.c b/arch/x86/mm/maccess.c
+index 5a53c2cc169cc..6993f026adec9 100644
+--- a/arch/x86/mm/maccess.c
++++ b/arch/x86/mm/maccess.c
+@@ -9,12 +9,21 @@ bool copy_from_kernel_nofault_allowed(const void *unsafe_src, size_t size)
+ unsigned long vaddr = (unsigned long)unsafe_src;
+
+ /*
+- * Range covering the highest possible canonical userspace address
+- * as well as non-canonical address range. For the canonical range
+- * we also need to include the userspace guard page.
++ * Do not allow userspace addresses. This disallows
++ * normal userspace and the userspace guard page:
+ */
+- return vaddr >= TASK_SIZE_MAX + PAGE_SIZE &&
+- __is_canonical_address(vaddr, boot_cpu_data.x86_virt_bits);
++ if (vaddr < TASK_SIZE_MAX + PAGE_SIZE)
++ return false;
++
++ /*
++ * Allow everything during early boot before 'x86_virt_bits'
++ * is initialized. Needed for instruction decoding in early
++ * exception handlers.
++ */
++ if (!boot_cpu_data.x86_virt_bits)
++ return true;
++
++ return __is_canonical_address(vaddr, boot_cpu_data.x86_virt_bits);
+ }
+ #else
+ bool copy_from_kernel_nofault_allowed(const void *unsafe_src, size_t size)
+--
+2.42.0
+
--- /dev/null
+From 783cca8b1d06919e09ca10f39d7b35c5098c9ee0 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 31 Jan 2022 09:24:50 +0200
+Subject: x86: Share definition of __is_canonical_address()
+
+From: Adrian Hunter <adrian.hunter@intel.com>
+
+[ Upstream commit 1fb85d06ad6754796cd1b920639ca9d8840abefd ]
+
+Reduce code duplication by moving canonical address code to a common header
+file.
+
+Signed-off-by: Adrian Hunter <adrian.hunter@intel.com>
+Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
+Link: https://lore.kernel.org/r/20220131072453.2839535-3-adrian.hunter@intel.com
+Stable-dep-of: f79936545fb1 ("x86/sev-es: Allow copy_from_kernel_nofault() in earlier boot")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ arch/x86/events/intel/pt.c | 14 ++------------
+ arch/x86/include/asm/page.h | 10 ++++++++++
+ arch/x86/kvm/emulate.c | 4 ++--
+ arch/x86/kvm/x86.c | 2 +-
+ arch/x86/kvm/x86.h | 7 +------
+ arch/x86/mm/maccess.c | 7 +------
+ 6 files changed, 17 insertions(+), 27 deletions(-)
+
+diff --git a/arch/x86/events/intel/pt.c b/arch/x86/events/intel/pt.c
+index d0295240c78a8..a85d3138839c5 100644
+--- a/arch/x86/events/intel/pt.c
++++ b/arch/x86/events/intel/pt.c
+@@ -1360,20 +1360,10 @@ static void pt_addr_filters_fini(struct perf_event *event)
+ }
+
+ #ifdef CONFIG_X86_64
+-static u64 canonical_address(u64 vaddr, u8 vaddr_bits)
+-{
+- return ((s64)vaddr << (64 - vaddr_bits)) >> (64 - vaddr_bits);
+-}
+-
+-static u64 is_canonical_address(u64 vaddr, u8 vaddr_bits)
+-{
+- return canonical_address(vaddr, vaddr_bits) == vaddr;
+-}
+-
+ /* Clamp to a canonical address greater-than-or-equal-to the address given */
+ static u64 clamp_to_ge_canonical_addr(u64 vaddr, u8 vaddr_bits)
+ {
+- return is_canonical_address(vaddr, vaddr_bits) ?
++ return __is_canonical_address(vaddr, vaddr_bits) ?
+ vaddr :
+ -BIT_ULL(vaddr_bits - 1);
+ }
+@@ -1381,7 +1371,7 @@ static u64 clamp_to_ge_canonical_addr(u64 vaddr, u8 vaddr_bits)
+ /* Clamp to a canonical address less-than-or-equal-to the address given */
+ static u64 clamp_to_le_canonical_addr(u64 vaddr, u8 vaddr_bits)
+ {
+- return is_canonical_address(vaddr, vaddr_bits) ?
++ return __is_canonical_address(vaddr, vaddr_bits) ?
+ vaddr :
+ BIT_ULL(vaddr_bits - 1) - 1;
+ }
+diff --git a/arch/x86/include/asm/page.h b/arch/x86/include/asm/page.h
+index 4d5810c8fab74..9cc82f305f4bf 100644
+--- a/arch/x86/include/asm/page.h
++++ b/arch/x86/include/asm/page.h
+@@ -71,6 +71,16 @@ static inline void copy_user_page(void *to, void *from, unsigned long vaddr,
+ extern bool __virt_addr_valid(unsigned long kaddr);
+ #define virt_addr_valid(kaddr) __virt_addr_valid((unsigned long) (kaddr))
+
++static __always_inline u64 __canonical_address(u64 vaddr, u8 vaddr_bits)
++{
++ return ((s64)vaddr << (64 - vaddr_bits)) >> (64 - vaddr_bits);
++}
++
++static __always_inline u64 __is_canonical_address(u64 vaddr, u8 vaddr_bits)
++{
++ return __canonical_address(vaddr, vaddr_bits) == vaddr;
++}
++
+ #endif /* __ASSEMBLY__ */
+
+ #include <asm-generic/memory_model.h>
+diff --git a/arch/x86/kvm/emulate.c b/arch/x86/kvm/emulate.c
+index cb96e4354f317..98b25a7af8ce8 100644
+--- a/arch/x86/kvm/emulate.c
++++ b/arch/x86/kvm/emulate.c
+@@ -687,7 +687,7 @@ static inline u8 ctxt_virt_addr_bits(struct x86_emulate_ctxt *ctxt)
+ static inline bool emul_is_noncanonical_address(u64 la,
+ struct x86_emulate_ctxt *ctxt)
+ {
+- return get_canonical(la, ctxt_virt_addr_bits(ctxt)) != la;
++ return !__is_canonical_address(la, ctxt_virt_addr_bits(ctxt));
+ }
+
+ /*
+@@ -737,7 +737,7 @@ static __always_inline int __linearize(struct x86_emulate_ctxt *ctxt,
+ case X86EMUL_MODE_PROT64:
+ *linear = la;
+ va_bits = ctxt_virt_addr_bits(ctxt);
+- if (get_canonical(la, va_bits) != la)
++ if (!__is_canonical_address(la, va_bits))
+ goto bad;
+
+ *max_size = min_t(u64, ~0u, (1ull << va_bits) - la);
+diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
+index a26200c3e82b5..7e9b615653065 100644
+--- a/arch/x86/kvm/x86.c
++++ b/arch/x86/kvm/x86.c
+@@ -1745,7 +1745,7 @@ static int __kvm_set_msr(struct kvm_vcpu *vcpu, u32 index, u64 data,
+ * value, and that something deterministic happens if the guest
+ * invokes 64-bit SYSENTER.
+ */
+- data = get_canonical(data, vcpu_virt_addr_bits(vcpu));
++ data = __canonical_address(data, vcpu_virt_addr_bits(vcpu));
+ break;
+ case MSR_TSC_AUX:
+ if (!kvm_is_supported_user_return_msr(MSR_TSC_AUX))
+diff --git a/arch/x86/kvm/x86.h b/arch/x86/kvm/x86.h
+index cd0c93ec72fad..f7854e742e8ce 100644
+--- a/arch/x86/kvm/x86.h
++++ b/arch/x86/kvm/x86.h
+@@ -211,14 +211,9 @@ static inline u8 vcpu_virt_addr_bits(struct kvm_vcpu *vcpu)
+ return kvm_read_cr4_bits(vcpu, X86_CR4_LA57) ? 57 : 48;
+ }
+
+-static inline u64 get_canonical(u64 la, u8 vaddr_bits)
+-{
+- return ((int64_t)la << (64 - vaddr_bits)) >> (64 - vaddr_bits);
+-}
+-
+ static inline bool is_noncanonical_address(u64 la, struct kvm_vcpu *vcpu)
+ {
+- return get_canonical(la, vcpu_virt_addr_bits(vcpu)) != la;
++ return !__is_canonical_address(la, vcpu_virt_addr_bits(vcpu));
+ }
+
+ static inline void vcpu_cache_mmio_info(struct kvm_vcpu *vcpu,
+diff --git a/arch/x86/mm/maccess.c b/arch/x86/mm/maccess.c
+index 92ec176a72937..5a53c2cc169cc 100644
+--- a/arch/x86/mm/maccess.c
++++ b/arch/x86/mm/maccess.c
+@@ -4,11 +4,6 @@
+ #include <linux/kernel.h>
+
+ #ifdef CONFIG_X86_64
+-static __always_inline u64 canonical_address(u64 vaddr, u8 vaddr_bits)
+-{
+- return ((s64)vaddr << (64 - vaddr_bits)) >> (64 - vaddr_bits);
+-}
+-
+ bool copy_from_kernel_nofault_allowed(const void *unsafe_src, size_t size)
+ {
+ unsigned long vaddr = (unsigned long)unsafe_src;
+@@ -19,7 +14,7 @@ bool copy_from_kernel_nofault_allowed(const void *unsafe_src, size_t size)
+ * we also need to include the userspace guard page.
+ */
+ return vaddr >= TASK_SIZE_MAX + PAGE_SIZE &&
+- canonical_address(vaddr, boot_cpu_data.x86_virt_bits) == vaddr;
++ __is_canonical_address(vaddr, boot_cpu_data.x86_virt_bits);
+ }
+ #else
+ bool copy_from_kernel_nofault_allowed(const void *unsafe_src, size_t size)
+--
+2.42.0
+
--- /dev/null
+From 21dde46cd1c49dd2047aab1ae01be2fe6c7d8be1 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 4 Sep 2023 22:04:49 -0700
+Subject: x86/srso: Fix SBPB enablement for (possible) future fixed HW
+
+From: Josh Poimboeuf <jpoimboe@kernel.org>
+
+[ Upstream commit 1d1142ac51307145dbb256ac3535a1d43a1c9800 ]
+
+Make the SBPB check more robust against the (possible) case where future
+HW has SRSO fixed but doesn't have the SRSO_NO bit set.
+
+Fixes: 1b5277c0ea0b ("x86/srso: Add SRSO_NO support")
+Signed-off-by: Josh Poimboeuf <jpoimboe@kernel.org>
+Signed-off-by: Ingo Molnar <mingo@kernel.org>
+Signed-off-by: Borislav Petkov (AMD) <bp@alien8.de>
+Acked-by: Borislav Petkov (AMD) <bp@alien8.de>
+Link: https://lore.kernel.org/r/cee5050db750b391c9f35f5334f8ff40e66c01b9.1693889988.git.jpoimboe@kernel.org
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ arch/x86/kernel/cpu/bugs.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/arch/x86/kernel/cpu/bugs.c b/arch/x86/kernel/cpu/bugs.c
+index 6322a08edbba5..d1ba55ea46a7b 100644
+--- a/arch/x86/kernel/cpu/bugs.c
++++ b/arch/x86/kernel/cpu/bugs.c
+@@ -2477,7 +2477,7 @@ static void __init srso_select_mitigation(void)
+ pr_info("%s%s\n", srso_strings[srso_mitigation], (has_microcode ? "" : ", no microcode"));
+
+ pred_cmd:
+- if ((boot_cpu_has(X86_FEATURE_SRSO_NO) || srso_cmd == SRSO_CMD_OFF) &&
++ if ((!boot_cpu_has_bug(X86_BUG_SRSO) || srso_cmd == SRSO_CMD_OFF) &&
+ boot_cpu_has(X86_FEATURE_SBPB))
+ x86_pred_cmd = PRED_CMD_SBPB;
+ }
+--
+2.42.0
+
--- /dev/null
+From 47071c5ce4d324df14134b3191a0d79400903e2a Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 16 Oct 2023 15:13:25 +0200
+Subject: xen-pciback: Consider INTx disabled when MSI/MSI-X is enabled
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Marek Marczykowski-Górecki <marmarek@invisiblethingslab.com>
+
+[ Upstream commit 2c269f42d0f382743ab230308b836ffe5ae9b2ae ]
+
+Linux enables MSI-X before disabling INTx, but keeps MSI-X masked until
+the table is filled. Then it disables INTx just before clearing MASKALL
+bit. Currently this approach is rejected by xen-pciback.
+According to the PCIe spec, device cannot use INTx when MSI/MSI-X is
+enabled (in other words: enabling MSI/MSI-X implicitly disables INTx).
+
+Change the logic to consider INTx disabled if MSI/MSI-X is enabled. This
+applies to three places:
+ - checking currently enabled interrupts type,
+ - transition to MSI/MSI-X - where INTx would be implicitly disabled,
+ - clearing INTx disable bit - which can be allowed even if MSI/MSI-X is
+ enabled, as device should consider INTx disabled anyway in that case
+
+Fixes: 5e29500eba2a ("xen-pciback: Allow setting PCI_MSIX_FLAGS_MASKALL too")
+Signed-off-by: Marek Marczykowski-Górecki <marmarek@invisiblethingslab.com>
+Acked-by: Juergen Gross <jgross@suse.com>
+Link: https://lore.kernel.org/r/20231016131348.1734721-1-marmarek@invisiblethingslab.com
+Signed-off-by: Juergen Gross <jgross@suse.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/xen/xen-pciback/conf_space.c | 19 +++++++++++------
+ .../xen/xen-pciback/conf_space_capability.c | 8 ++++++-
+ drivers/xen/xen-pciback/conf_space_header.c | 21 +++----------------
+ 3 files changed, 23 insertions(+), 25 deletions(-)
+
+diff --git a/drivers/xen/xen-pciback/conf_space.c b/drivers/xen/xen-pciback/conf_space.c
+index 059de92aea7d0..d47eee6c51435 100644
+--- a/drivers/xen/xen-pciback/conf_space.c
++++ b/drivers/xen/xen-pciback/conf_space.c
+@@ -288,12 +288,6 @@ int xen_pcibk_get_interrupt_type(struct pci_dev *dev)
+ u16 val;
+ int ret = 0;
+
+- err = pci_read_config_word(dev, PCI_COMMAND, &val);
+- if (err)
+- return err;
+- if (!(val & PCI_COMMAND_INTX_DISABLE))
+- ret |= INTERRUPT_TYPE_INTX;
+-
+ /*
+ * Do not trust dev->msi(x)_enabled here, as enabling could be done
+ * bypassing the pci_*msi* functions, by the qemu.
+@@ -316,6 +310,19 @@ int xen_pcibk_get_interrupt_type(struct pci_dev *dev)
+ if (val & PCI_MSIX_FLAGS_ENABLE)
+ ret |= INTERRUPT_TYPE_MSIX;
+ }
++
++ /*
++ * PCIe spec says device cannot use INTx if MSI/MSI-X is enabled,
++ * so check for INTx only when both are disabled.
++ */
++ if (!ret) {
++ err = pci_read_config_word(dev, PCI_COMMAND, &val);
++ if (err)
++ return err;
++ if (!(val & PCI_COMMAND_INTX_DISABLE))
++ ret |= INTERRUPT_TYPE_INTX;
++ }
++
+ return ret ?: INTERRUPT_TYPE_NONE;
+ }
+
+diff --git a/drivers/xen/xen-pciback/conf_space_capability.c b/drivers/xen/xen-pciback/conf_space_capability.c
+index 097316a741268..1948a9700c8fa 100644
+--- a/drivers/xen/xen-pciback/conf_space_capability.c
++++ b/drivers/xen/xen-pciback/conf_space_capability.c
+@@ -236,10 +236,16 @@ static int msi_msix_flags_write(struct pci_dev *dev, int offset, u16 new_value,
+ return PCIBIOS_SET_FAILED;
+
+ if (new_value & field_config->enable_bit) {
+- /* don't allow enabling together with other interrupt types */
++ /*
++ * Don't allow enabling together with other interrupt type, but do
++ * allow enabling MSI(-X) while INTx is still active to please Linuxes
++ * MSI(-X) startup sequence. It is safe to do, as according to PCI
++ * spec, device with enabled MSI(-X) shouldn't use INTx.
++ */
+ int int_type = xen_pcibk_get_interrupt_type(dev);
+
+ if (int_type == INTERRUPT_TYPE_NONE ||
++ int_type == INTERRUPT_TYPE_INTX ||
+ int_type == field_config->int_type)
+ goto write;
+ return PCIBIOS_SET_FAILED;
+diff --git a/drivers/xen/xen-pciback/conf_space_header.c b/drivers/xen/xen-pciback/conf_space_header.c
+index ac45cdc38e859..fcaa050d692d2 100644
+--- a/drivers/xen/xen-pciback/conf_space_header.c
++++ b/drivers/xen/xen-pciback/conf_space_header.c
+@@ -104,24 +104,9 @@ static int command_write(struct pci_dev *dev, int offset, u16 value, void *data)
+ pci_clear_mwi(dev);
+ }
+
+- if (dev_data && dev_data->allow_interrupt_control) {
+- if ((cmd->val ^ value) & PCI_COMMAND_INTX_DISABLE) {
+- if (value & PCI_COMMAND_INTX_DISABLE) {
+- pci_intx(dev, 0);
+- } else {
+- /* Do not allow enabling INTx together with MSI or MSI-X. */
+- switch (xen_pcibk_get_interrupt_type(dev)) {
+- case INTERRUPT_TYPE_NONE:
+- pci_intx(dev, 1);
+- break;
+- case INTERRUPT_TYPE_INTX:
+- break;
+- default:
+- return PCIBIOS_SET_FAILED;
+- }
+- }
+- }
+- }
++ if (dev_data && dev_data->allow_interrupt_control &&
++ ((cmd->val ^ value) & PCI_COMMAND_INTX_DISABLE))
++ pci_intx(dev, !(value & PCI_COMMAND_INTX_DISABLE));
+
+ cmd->val = value;
+
+--
+2.42.0
+
--- /dev/null
+From 9e1321cf0ac5aae326a44a0c07cd98ec3582a31b Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 19 Oct 2023 13:29:19 +0300
+Subject: xhci: Loosen RPM as default policy to cover for AMD xHC 1.1
+
+From: Basavaraj Natikar <Basavaraj.Natikar@amd.com>
+
+[ Upstream commit 4baf1218150985ee3ab0a27220456a1f027ea0ac ]
+
+The AMD USB host controller (1022:43f7) isn't going into PCI D3 by default
+without anything connected. This is because the policy that was introduced
+by commit a611bf473d1f ("xhci-pci: Set runtime PM as default policy on all
+xHC 1.2 or later devices") only covered 1.2 or later.
+
+The 1.1 specification also has the same requirement as the 1.2
+specification for D3 support. So expand the runtime PM as default policy
+to all AMD 1.1 devices as well.
+
+Fixes: a611bf473d1f ("xhci-pci: Set runtime PM as default policy on all xHC 1.2 or later devices")
+Link: https://composter.com.ua/documents/xHCI_Specification_for_USB.pdf
+Co-developed-by: Mario Limonciello <mario.limonciello@amd.com>
+Signed-off-by: Mario Limonciello <mario.limonciello@amd.com>
+Signed-off-by: Basavaraj Natikar <Basavaraj.Natikar@amd.com>
+Signed-off-by: Mathias Nyman <mathias.nyman@linux.intel.com>
+Link: https://lore.kernel.org/r/20231019102924.2797346-15-mathias.nyman@linux.intel.com
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/usb/host/xhci-pci.c | 2 ++
+ 1 file changed, 2 insertions(+)
+
+diff --git a/drivers/usb/host/xhci-pci.c b/drivers/usb/host/xhci-pci.c
+index 29a442b621182..d0223facb92a1 100644
+--- a/drivers/usb/host/xhci-pci.c
++++ b/drivers/usb/host/xhci-pci.c
+@@ -349,6 +349,8 @@ static void xhci_pci_quirks(struct device *dev, struct xhci_hcd *xhci)
+ /* xHC spec requires PCI devices to support D3hot and D3cold */
+ if (xhci->hci_version >= 0x120)
+ xhci->quirks |= XHCI_DEFAULT_PM_RUNTIME_ALLOW;
++ else if (pdev->vendor == PCI_VENDOR_ID_AMD && xhci->hci_version >= 0x110)
++ xhci->quirks |= XHCI_DEFAULT_PM_RUNTIME_ALLOW;
+
+ if (xhci->quirks & XHCI_RESET_ON_RESUME)
+ xhci_dbg_trace(xhci, trace_xhci_dbg_quirks,
+--
+2.42.0
+