From: Sasha Levin Date: Fri, 10 Nov 2023 17:35:01 +0000 (-0500) Subject: Fixes for 5.15 X-Git-Tag: v4.14.330~68 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=1d13322f3c839efc4e8c7a0dff04db3c5203bd49;p=thirdparty%2Fkernel%2Fstable-queue.git Fixes for 5.15 Signed-off-by: Sasha Levin --- diff --git a/queue-5.15/9p-net-fix-possible-memory-leak-in-p9_check_errors.patch b/queue-5.15/9p-net-fix-possible-memory-leak-in-p9_check_errors.patch new file mode 100644 index 00000000000..6b698d91909 --- /dev/null +++ b/queue-5.15/9p-net-fix-possible-memory-leak-in-p9_check_errors.patch @@ -0,0 +1,47 @@ +From 77446d67560d46864a1986e48ef9b9633f232f1b Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 27 Oct 2023 11:03:02 +0800 +Subject: 9p/net: fix possible memory leak in p9_check_errors() + +From: Hangyu Hua + +[ 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 +Signed-off-by: Hangyu Hua +Message-ID: <20231027030302.11927-1-hbh25y@gmail.com> +Signed-off-by: Dominique Martinet +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-5.15/acpi-sysfs-fix-create_pnp_modalias-and-create_of_mod.patch b/queue-5.15/acpi-sysfs-fix-create_pnp_modalias-and-create_of_mod.patch new file mode 100644 index 00000000000..8bfbe9f495a --- /dev/null +++ b/queue-5.15/acpi-sysfs-fix-create_pnp_modalias-and-create_of_mod.patch @@ -0,0 +1,62 @@ +From 6480654ad6e5e47192c9ec7a883c6cbdbdcc9dd5 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 23 Oct 2023 20:32:54 +0200 +Subject: ACPI: sysfs: Fix create_pnp_modalias() and create_of_modalias() + +From: Christophe JAILLET + +[ 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 +[ rjw: Merge two patches into one, combine changelogs, add subject ] +Signed-off-by: Rafael J. Wysocki +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-5.15/arm-9321-1-memset-cast-the-constant-byte-to-unsigned.patch b/queue-5.15/arm-9321-1-memset-cast-the-constant-byte-to-unsigned.patch new file mode 100644 index 00000000000..1bcdc8e76ba --- /dev/null +++ b/queue-5.15/arm-9321-1-memset-cast-the-constant-byte-to-unsigned.patch @@ -0,0 +1,63 @@ +From f71e01feff5b06f29dea7be9408bbe282c83427a Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 22 Aug 2023 15:06:06 +0100 +Subject: ARM: 9321/1: memset: cast the constant byte to unsigned char + +From: Kursad Oney + +[ 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 + +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 +Reviewed-by: Linus Walleij +Signed-off-by: Kursad Oney +Signed-off-by: Russell King (Oracle) +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-5.15/arm-dts-qcom-mdm9615-populate-vsdcc-fixed-regulator.patch b/queue-5.15/arm-dts-qcom-mdm9615-populate-vsdcc-fixed-regulator.patch new file mode 100644 index 00000000000..d74c875d6e2 --- /dev/null +++ b/queue-5.15/arm-dts-qcom-mdm9615-populate-vsdcc-fixed-regulator.patch @@ -0,0 +1,51 @@ +From 2411013ead0e25a4e5c8c391b302dcdfcadaa9ad Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 24 Sep 2023 20:39:13 +0200 +Subject: ARM: dts: qcom: mdm9615: populate vsdcc fixed regulator + +From: Krzysztof Kozlowski + +[ 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 +Reviewed-by: Dmitry Baryshkov +Link: https://lore.kernel.org/r/20230924183914.51414-3-krzysztof.kozlowski@linaro.org +Signed-off-by: Bjorn Andersson +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-5.15/arm-dts-renesas-blanche-fix-typo-in-gp_11_2-pin-name.patch b/queue-5.15/arm-dts-renesas-blanche-fix-typo-in-gp_11_2-pin-name.patch new file mode 100644 index 00000000000..808ffa6a8ec --- /dev/null +++ b/queue-5.15/arm-dts-renesas-blanche-fix-typo-in-gp_11_2-pin-name.patch @@ -0,0 +1,39 @@ +From 7a182f164433cc2a8a6f6952bea4850c8d9ae35d Mon Sep 17 00:00:00 2001 +From: Sasha Levin +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 + +[ 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 +Link: https://lore.kernel.org/r/203128eca2261ffc33b83637818dd39c488f42b0.1693408326.git.geert+renesas@glider.be +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-5.15/arm64-arm-xen-enlighten-fix-kpti-checks.patch b/queue-5.15/arm64-arm-xen-enlighten-fix-kpti-checks.patch new file mode 100644 index 00000000000..bb9d4dd1ffa --- /dev/null +++ b/queue-5.15/arm64-arm-xen-enlighten-fix-kpti-checks.patch @@ -0,0 +1,128 @@ +From b41800afaa64ab8b9b88c7c8d60b3c38d3fda01f Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 16 Oct 2023 11:24:25 +0100 +Subject: arm64/arm: xen: enlighten: Fix KPTI checks + +From: Mark Rutland + +[ 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 +Cc: Bertrand Marquis +Cc: Boris Ostrovsky +Cc: Juergen Gross +Cc: Stefano Stabellini +Cc: Suzuki K Poulose +Cc: Will Deacon +Signed-off-by: Catalin Marinas +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-5.15/arm64-dts-imx8mm-add-sound-dai-cells-to-micfil-node.patch b/queue-5.15/arm64-dts-imx8mm-add-sound-dai-cells-to-micfil-node.patch new file mode 100644 index 00000000000..a6782a81e03 --- /dev/null +++ b/queue-5.15/arm64-dts-imx8mm-add-sound-dai-cells-to-micfil-node.patch @@ -0,0 +1,36 @@ +From d5c8ff6cc9cc9d3474c42000f82c3122e7cf636a Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 4 Oct 2023 18:01:58 -0500 +Subject: arm64: dts: imx8mm: Add sound-dai-cells to micfil node + +From: Adam Ford + +[ 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 +Reviewed-by: Fabio Estevam +Signed-off-by: Shawn Guo +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-5.15/arm64-dts-imx8mn-add-sound-dai-cells-to-micfil-node.patch b/queue-5.15/arm64-dts-imx8mn-add-sound-dai-cells-to-micfil-node.patch new file mode 100644 index 00000000000..86a1db719ff --- /dev/null +++ b/queue-5.15/arm64-dts-imx8mn-add-sound-dai-cells-to-micfil-node.patch @@ -0,0 +1,36 @@ +From adf10134d080fcb3d98adea7dbd18f4b0838f192 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 4 Oct 2023 18:01:59 -0500 +Subject: arm64: dts: imx8mn: Add sound-dai-cells to micfil node + +From: Adam Ford + +[ 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 +Reviewed-by: Fabio Estevam +Signed-off-by: Shawn Guo +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-5.15/arm64-dts-imx8qm-ss-img-fix-jpegenc-compatible-entry.patch b/queue-5.15/arm64-dts-imx8qm-ss-img-fix-jpegenc-compatible-entry.patch new file mode 100644 index 00000000000..e78e7c98b0d --- /dev/null +++ b/queue-5.15/arm64-dts-imx8qm-ss-img-fix-jpegenc-compatible-entry.patch @@ -0,0 +1,42 @@ +From ca067a45f64a175c8def5f99b855687b1180e821 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 26 Sep 2023 11:27:36 -0300 +Subject: arm64: dts: imx8qm-ss-img: Fix jpegenc compatible entry + +From: Fabio Estevam + +[ 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 +Reviewed-by: Mirela Rabulea +Reviewed-by: Krzysztof Kozlowski +Signed-off-by: Shawn Guo +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-5.15/arm64-dts-marvell-cn9310-use-appropriate-label-for-s.patch b/queue-5.15/arm64-dts-marvell-cn9310-use-appropriate-label-for-s.patch new file mode 100644 index 00000000000..78b7e7150b3 --- /dev/null +++ b/queue-5.15/arm64-dts-marvell-cn9310-use-appropriate-label-for-s.patch @@ -0,0 +1,72 @@ +From 1fae08c62af0928245ef3a5dc36df4520e9e4af5 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 21 Aug 2023 10:51:25 +1200 +Subject: ARM64: dts: marvell: cn9310: Use appropriate label for spi1 pins + +From: Chris Packham + +[ 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 +Reviewed-by: Andrew Lunn +Signed-off-by: Gregory CLEMENT +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-5.15/arm64-dts-qcom-apq8016-sbc-add-missing-adv7533-regul.patch b/queue-5.15/arm64-dts-qcom-apq8016-sbc-add-missing-adv7533-regul.patch new file mode 100644 index 00000000000..cbf06066a00 --- /dev/null +++ b/queue-5.15/arm64-dts-qcom-apq8016-sbc-add-missing-adv7533-regul.patch @@ -0,0 +1,45 @@ +From 65a05cd16e035e672bb57b27bb1eb0333cef14a5 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 22 Sep 2023 12:49:55 +0200 +Subject: arm64: dts: qcom: apq8016-sbc: Add missing ADV7533 regulators + +From: Stephan Gerhold + +[ 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 +Reviewed-by: Dmitry Baryshkov +Link: https://lore.kernel.org/r/20230922-db410c-adv7533-regulators-v1-1-68aba71e529b@gerhold.net +Signed-off-by: Bjorn Andersson +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-5.15/arm64-dts-qcom-msm8916-fix-iommu-local-address-range.patch b/queue-5.15/arm64-dts-qcom-msm8916-fix-iommu-local-address-range.patch new file mode 100644 index 00000000000..2f688713dcc --- /dev/null +++ b/queue-5.15/arm64-dts-qcom-msm8916-fix-iommu-local-address-range.patch @@ -0,0 +1,40 @@ +From ff76ee86e94d159c87e0ec611d3973ae18f5c01b Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 15 Sep 2023 20:03:04 +0530 +Subject: arm64: dts: qcom: msm8916: Fix iommu local address range + +From: Gaurav Kohli + +[ 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 +Tested-by: Bryan O'Donoghue +Signed-off-by: Gaurav Kohli +Reviewed-by: Stephan Gerhold +Acked-by: Konrad Dybcio +Link: https://lore.kernel.org/r/20230915143304.477-1-quic_gkohli@quicinc.com +Signed-off-by: Bjorn Andersson +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-5.15/arm64-dts-qcom-msm8992-libra-drop-duplicated-reserve.patch b/queue-5.15/arm64-dts-qcom-msm8992-libra-drop-duplicated-reserve.patch new file mode 100644 index 00000000000..e16da1b0833 --- /dev/null +++ b/queue-5.15/arm64-dts-qcom-msm8992-libra-drop-duplicated-reserve.patch @@ -0,0 +1,42 @@ +From cb43a19df3ed3620f0645c93b3f69a1b7d998e29 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 20 Jul 2023 09:20:48 +0200 +Subject: arm64: dts: qcom: msm8992-libra: drop duplicated reserved memory + +From: Krzysztof Kozlowski + +[ 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 +Link: https://lore.kernel.org/r/20230720072048.10093-2-krzysztof.kozlowski@linaro.org +Signed-off-by: Bjorn Andersson +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-5.15/arm64-dts-qcom-sc7280-add-missing-lmh-interrupts.patch b/queue-5.15/arm64-dts-qcom-sc7280-add-missing-lmh-interrupts.patch new file mode 100644 index 00000000000..a45d27a5405 --- /dev/null +++ b/queue-5.15/arm64-dts-qcom-sc7280-add-missing-lmh-interrupts.patch @@ -0,0 +1,43 @@ +From cda075d471bc310e17c682d4866112465202e40e Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 11 Aug 2023 22:58:22 +0200 +Subject: arm64: dts: qcom: sc7280: Add missing LMH interrupts + +From: Konrad Dybcio + +[ 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 +Link: https://lore.kernel.org/r/20230811-topic-7280_lmhirq-v1-1-c262b6a25c8f@linaro.org +Signed-off-by: Bjorn Andersson +Signed-off-by: Sasha Levin +--- + 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 = , ++ , ++ ; ++ 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 + diff --git a/queue-5.15/arm64-dts-qcom-sdm845-mtp-fix-wifi-configuration.patch b/queue-5.15/arm64-dts-qcom-sdm845-mtp-fix-wifi-configuration.patch new file mode 100644 index 00000000000..1bd962dba16 --- /dev/null +++ b/queue-5.15/arm64-dts-qcom-sdm845-mtp-fix-wifi-configuration.patch @@ -0,0 +1,37 @@ +From 2a4076b88121ad10d1d8b2ac66e06c384dc561a3 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 27 Aug 2023 01:19:11 +0300 +Subject: arm64: dts: qcom: sdm845-mtp: fix WiFi configuration + +From: Dmitry Baryshkov + +[ 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 +Link: https://lore.kernel.org/r/20230826221915.846937-2-dmitry.baryshkov@linaro.org +Signed-off-by: Bjorn Andersson +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-5.15/asoc-ams-delta.c-use-component-after-check.patch b/queue-5.15/asoc-ams-delta.c-use-component-after-check.patch new file mode 100644 index 00000000000..b9cf0c42b1f --- /dev/null +++ b/queue-5.15/asoc-ams-delta.c-use-component-after-check.patch @@ -0,0 +1,56 @@ +From 52958aa8fd7da647dbf672f70621ae6a14b5fcf2 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 27 Oct 2023 00:09:56 +0000 +Subject: ASoC: ams-delta.c: use component after check + +From: Kuninori Morimoto + +[ 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 +Closes: https://lore.kernel.org/r/3e608474-e99a-4866-ae98-3054a4221f09@moroto.mountain +Signed-off-by: Kuninori Morimoto +Link: https://lore.kernel.org/r/87ttqdq623.wl-kuninori.morimoto.gx@renesas.com +Signed-off-by: Mark Brown +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-5.15/asoc-fsl-fix-pm-disable-depth-imbalance-in-fsl_easrc.patch b/queue-5.15/asoc-fsl-fix-pm-disable-depth-imbalance-in-fsl_easrc.patch new file mode 100644 index 00000000000..483dfdb1a32 --- /dev/null +++ b/queue-5.15/asoc-fsl-fix-pm-disable-depth-imbalance-in-fsl_easrc.patch @@ -0,0 +1,54 @@ +From 4c56916f378b9946593628dc57d9dc5075a70720 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 12 Oct 2023 21:03:15 +0800 +Subject: ASoC: fsl: Fix PM disable depth imbalance in fsl_easrc_probe + +From: Zhang Shurong + +[ 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 +Link: https://lore.kernel.org/r/tencent_C0D62E6D89818179A02A04A0C248F0DDC40A@qq.com +Signed-off-by: Mark Brown +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-5.15/asoc-fsl-mpc5200_dma.c-fix-warning-of-function-param.patch b/queue-5.15/asoc-fsl-mpc5200_dma.c-fix-warning-of-function-param.patch new file mode 100644 index 00000000000..738442bbe9f --- /dev/null +++ b/queue-5.15/asoc-fsl-mpc5200_dma.c-fix-warning-of-function-param.patch @@ -0,0 +1,45 @@ +From e119dc31cda92cf17e6d5dd7624d77a7dbdfa1ae Mon Sep 17 00:00:00 2001 +From: Sasha Levin +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 + +[ 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 +Closes: https://lore.kernel.org/oe-kbuild-all/202310061914.jJuekdHs-lkp@intel.com/ +Signed-off-by: Kuninori Morimoto +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 +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-5.15/asoc-intel-skylake-fix-mem-leak-when-parsing-uuids-f.patch b/queue-5.15/asoc-intel-skylake-fix-mem-leak-when-parsing-uuids-f.patch new file mode 100644 index 00000000000..3f5e8970243 --- /dev/null +++ b/queue-5.15/asoc-intel-skylake-fix-mem-leak-when-parsing-uuids-f.patch @@ -0,0 +1,40 @@ +From 609ec476cdb15c434068cb193a0696c7d62ea978 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +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 + +[ 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 +Signed-off-by: Amadeusz Sławiński +Link: https://lore.kernel.org/r/20231026082558.1864910-1-amadeuszx.slawinski@linux.intel.com +Signed-off-by: Mark Brown +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-5.15/can-dev-can_put_echo_skb-don-t-crash-kernel-if-can_p.patch b/queue-5.15/can-dev-can_put_echo_skb-don-t-crash-kernel-if-can_p.patch new file mode 100644 index 00000000000..ed377eaddc8 --- /dev/null +++ b/queue-5.15/can-dev-can_put_echo_skb-don-t-crash-kernel-if-can_p.patch @@ -0,0 +1,43 @@ +From fe1be58f7710425d08a491ee2649d44668c0a5eb Mon Sep 17 00:00:00 2001 +From: Sasha Levin +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 + +[ 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 +Signed-off-by: Marc Kleine-Budde +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-5.15/can-dev-can_restart-don-t-crash-kernel-if-carrier-is.patch b/queue-5.15/can-dev-can_restart-don-t-crash-kernel-if-carrier-is.patch new file mode 100644 index 00000000000..fe09a8ac48d --- /dev/null +++ b/queue-5.15/can-dev-can_restart-don-t-crash-kernel-if-carrier-is.patch @@ -0,0 +1,46 @@ +From 0fd33d1593eab375917f8b559caea53bac5d0be1 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +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 + +[ 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 +Signed-off-by: Marc Kleine-Budde +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-5.15/can-dev-can_restart-fix-race-condition-between-contr.patch b/queue-5.15/can-dev-can_restart-fix-race-condition-between-contr.patch new file mode 100644 index 00000000000..da549653f64 --- /dev/null +++ b/queue-5.15/can-dev-can_restart-fix-race-condition-between-contr.patch @@ -0,0 +1,102 @@ +From 892d069ad88acb25a3552266ae5beca25ab8fcc6 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +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 + +[ 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 +Signed-off-by: Marc Kleine-Budde +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-5.15/chtls-fix-tp-rcv_tstamp-initialization.patch b/queue-5.15/chtls-fix-tp-rcv_tstamp-initialization.patch new file mode 100644 index 00000000000..db808490e8b --- /dev/null +++ b/queue-5.15/chtls-fix-tp-rcv_tstamp-initialization.patch @@ -0,0 +1,36 @@ +From 593c13d625955550aa7ffa47759e797846efc6df Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 20 Oct 2023 12:57:36 +0000 +Subject: chtls: fix tp->rcv_tstamp initialization + +From: Eric Dumazet + +[ 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 +Cc: Ayush Sawal +Signed-off-by: David S. Miller +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-5.15/clk-imx-imx8mq-correct-error-handling-path.patch b/queue-5.15/clk-imx-imx8mq-correct-error-handling-path.patch new file mode 100644 index 00000000000..1f25d30d95c --- /dev/null +++ b/queue-5.15/clk-imx-imx8mq-correct-error-handling-path.patch @@ -0,0 +1,71 @@ +From 9683bf7a8a50c0400d177b859a7c6e822941246f Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 1 Oct 2023 20:26:18 +0800 +Subject: clk: imx: imx8mq: correct error handling path + +From: Peng Fan + +[ 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 +Reported-by: Dan Carpenter +Closes: https://lore.kernel.org/r/202309240551.e46NllPa-lkp@intel.com/ +Signed-off-by: Peng Fan +Link: https://lore.kernel.org/r/20231001122618.194498-1-peng.fan@oss.nxp.com +Signed-off-by: Abel Vesa +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-5.15/clk-imx-imx8qxp-fix-elcdif_pll-clock.patch b/queue-5.15/clk-imx-imx8qxp-fix-elcdif_pll-clock.patch new file mode 100644 index 00000000000..aabc640fd9c --- /dev/null +++ b/queue-5.15/clk-imx-imx8qxp-fix-elcdif_pll-clock.patch @@ -0,0 +1,45 @@ +From d6a6ca157dab879ff2dc40df4966263d55969531 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 12 Sep 2023 17:19:00 +0800 +Subject: clk: imx: imx8qxp: Fix elcdif_pll clock + +From: Robert Chiras + +[ 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 +Acked-by: Laurentiu Palcu +Signed-off-by: Robert Chiras +Signed-off-by: Peng Fan +Reviewed-by: Abel Vesa +Link: https://lore.kernel.org/r/20230912-imx8-clk-v1-v1-2-69a34bcfcae1@nxp.com +Signed-off-by: Abel Vesa +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-5.15/clk-imx-select-mxc_clk-for-clk_imx8qxp.patch b/queue-5.15/clk-imx-select-mxc_clk-for-clk_imx8qxp.patch new file mode 100644 index 00000000000..b057d44aabc --- /dev/null +++ b/queue-5.15/clk-imx-select-mxc_clk-for-clk_imx8qxp.patch @@ -0,0 +1,43 @@ +From 65b10dc863f9858c9b7ac79af5cc6e849a269591 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 21 Sep 2023 12:23:54 +0300 +Subject: clk: imx: Select MXC_CLK for CLK_IMX8QXP + +From: Abel Vesa + +[ 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 +Reviewed-by: Peng Fan +Acked-by: Randy Dunlap +Tested-by: Randy Dunlap +Signed-off-by: Abel Vesa +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-5.15/clk-keystone-pll-fix-a-couple-null-vs-is_err-checks.patch b/queue-5.15/clk-keystone-pll-fix-a-couple-null-vs-is_err-checks.patch new file mode 100644 index 00000000000..3744d472405 --- /dev/null +++ b/queue-5.15/clk-keystone-pll-fix-a-couple-null-vs-is_err-checks.patch @@ -0,0 +1,61 @@ +From 5cf3428205b12862d4919d13000062d26026a298 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 5 Oct 2023 17:01:57 +0300 +Subject: clk: keystone: pll: fix a couple NULL vs IS_ERR() checks + +From: Dan Carpenter + +[ 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 +Link: https://lore.kernel.org/r/d9da4c97-0da9-499f-9a21-1f8e3f148dc1@moroto.mountain +Signed-off-by: Stephen Boyd +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-5.15/clk-mediatek-clk-mt2701-add-check-for-mtk_alloc_clk_.patch b/queue-5.15/clk-mediatek-clk-mt2701-add-check-for-mtk_alloc_clk_.patch new file mode 100644 index 00000000000..3f414373d64 --- /dev/null +++ b/queue-5.15/clk-mediatek-clk-mt2701-add-check-for-mtk_alloc_clk_.patch @@ -0,0 +1,66 @@ +From f05e4cb17055005277c77564a9513ee8b9d18d19 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 1 Sep 2023 10:46:58 +0800 +Subject: clk: mediatek: clk-mt2701: Add check for mtk_alloc_clk_data + +From: Jiasheng Jiang + +[ 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 +Link: https://lore.kernel.org/r/20230901024658.23405-1-jiasheng@iscas.ac.cn +Reviewed-by: Markus Schneider-Pargmann +Reviewed-by: AngeloGioacchino Del Regno +Signed-off-by: Stephen Boyd +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-5.15/clk-mediatek-clk-mt6765-add-check-for-mtk_alloc_clk_.patch b/queue-5.15/clk-mediatek-clk-mt6765-add-check-for-mtk_alloc_clk_.patch new file mode 100644 index 00000000000..2694358af46 --- /dev/null +++ b/queue-5.15/clk-mediatek-clk-mt6765-add-check-for-mtk_alloc_clk_.patch @@ -0,0 +1,56 @@ +From 07f6013877e72deff29b426f11ba2d8188126ce5 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 12 Sep 2023 17:34:03 +0800 +Subject: clk: mediatek: clk-mt6765: Add check for mtk_alloc_clk_data + +From: Jiasheng Jiang + +[ 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 +Link: https://lore.kernel.org/r/20230912093407.21505-1-jiasheng@iscas.ac.cn +Reviewed-by: AngeloGioacchino Del Regno +Signed-off-by: Stephen Boyd +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-5.15/clk-mediatek-clk-mt6779-add-check-for-mtk_alloc_clk_.patch b/queue-5.15/clk-mediatek-clk-mt6779-add-check-for-mtk_alloc_clk_.patch new file mode 100644 index 00000000000..d2ccb34512d --- /dev/null +++ b/queue-5.15/clk-mediatek-clk-mt6779-add-check-for-mtk_alloc_clk_.patch @@ -0,0 +1,47 @@ +From bd70ccf02e0ec0559e977bc1bd2ddb67ecd80737 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 12 Sep 2023 17:34:04 +0800 +Subject: clk: mediatek: clk-mt6779: Add check for mtk_alloc_clk_data + +From: Jiasheng Jiang + +[ 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 +Link: https://lore.kernel.org/r/20230912093407.21505-2-jiasheng@iscas.ac.cn +Reviewed-by: AngeloGioacchino Del Regno +Signed-off-by: Stephen Boyd +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-5.15/clk-mediatek-clk-mt6797-add-check-for-mtk_alloc_clk_.patch b/queue-5.15/clk-mediatek-clk-mt6797-add-check-for-mtk_alloc_clk_.patch new file mode 100644 index 00000000000..2f6100999fe --- /dev/null +++ b/queue-5.15/clk-mediatek-clk-mt6797-add-check-for-mtk_alloc_clk_.patch @@ -0,0 +1,56 @@ +From 8cb7e491e03e9d409ba1d3f8d53ca54b1d3c48cd Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 12 Sep 2023 17:34:05 +0800 +Subject: clk: mediatek: clk-mt6797: Add check for mtk_alloc_clk_data + +From: Jiasheng Jiang + +[ 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 +Link: https://lore.kernel.org/r/20230912093407.21505-3-jiasheng@iscas.ac.cn +Reviewed-by: AngeloGioacchino Del Regno +Signed-off-by: Stephen Boyd +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-5.15/clk-mediatek-clk-mt7629-add-check-for-mtk_alloc_clk_.patch b/queue-5.15/clk-mediatek-clk-mt7629-add-check-for-mtk_alloc_clk_.patch new file mode 100644 index 00000000000..1e6cdae1337 --- /dev/null +++ b/queue-5.15/clk-mediatek-clk-mt7629-add-check-for-mtk_alloc_clk_.patch @@ -0,0 +1,56 @@ +From f8d533ac0c023bfea138a1bc41fb12d3e80882a1 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 12 Sep 2023 17:34:07 +0800 +Subject: clk: mediatek: clk-mt7629: Add check for mtk_alloc_clk_data + +From: Jiasheng Jiang + +[ 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 +Link: https://lore.kernel.org/r/20230912093407.21505-5-jiasheng@iscas.ac.cn +Reviewed-by: AngeloGioacchino Del Regno +Signed-off-by: Stephen Boyd +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-5.15/clk-mediatek-clk-mt7629-eth-add-check-for-mtk_alloc_.patch b/queue-5.15/clk-mediatek-clk-mt7629-eth-add-check-for-mtk_alloc_.patch new file mode 100644 index 00000000000..05217f7c65e --- /dev/null +++ b/queue-5.15/clk-mediatek-clk-mt7629-eth-add-check-for-mtk_alloc_.patch @@ -0,0 +1,47 @@ +From 8bfe49196be6c6f670d0b13a82621495aa7bb10f Mon Sep 17 00:00:00 2001 +From: Sasha Levin +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 + +[ 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 +Link: https://lore.kernel.org/r/20230912093407.21505-4-jiasheng@iscas.ac.cn +Reviewed-by: AngeloGioacchino Del Regno +Signed-off-by: Stephen Boyd +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-5.15/clk-npcm7xx-fix-incorrect-kfree.patch b/queue-5.15/clk-npcm7xx-fix-incorrect-kfree.patch new file mode 100644 index 00000000000..9729c0c104b --- /dev/null +++ b/queue-5.15/clk-npcm7xx-fix-incorrect-kfree.patch @@ -0,0 +1,45 @@ +From 5595f28a9c086eda9a4591e7066e87e4f8f99413 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +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 + +[ 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 +Link: https://lore.kernel.org/r/20230923133127.1815621-1-j.neuschaefer@gmx.net +Signed-off-by: Stephen Boyd +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-5.15/clk-qcom-clk-rcg2-fix-clock-rate-overflow-for-high-p.patch b/queue-5.15/clk-qcom-clk-rcg2-fix-clock-rate-overflow-for-high-p.patch new file mode 100644 index 00000000000..929be5f8907 --- /dev/null +++ b/queue-5.15/clk-qcom-clk-rcg2-fix-clock-rate-overflow-for-high-p.patch @@ -0,0 +1,57 @@ +From 20b4e82214a052df587655e66af5ec6b94b9a3ea Mon Sep 17 00:00:00 2001 +From: Sasha Levin +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 + +[ 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 +Reviewed-by: Marijn Suijten +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 +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-5.15/clk-qcom-config-ipq_apss_6018-should-depend-on-qcom_.patch b/queue-5.15/clk-qcom-config-ipq_apss_6018-should-depend-on-qcom_.patch new file mode 100644 index 00000000000..67f3e66867b --- /dev/null +++ b/queue-5.15/clk-qcom-config-ipq_apss_6018-should-depend-on-qcom_.patch @@ -0,0 +1,41 @@ +From 0ee71b3a9b744bccc836be50094481e8f7c39c41 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 20 Oct 2023 11:49:31 +0530 +Subject: clk: qcom: config IPQ_APSS_6018 should depend on QCOM_SMEM + +From: Varadarajan Narayanan + +[ 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 +Closes: https://lore.kernel.org/r/202310181650.g8THtfsm-lkp@intel.com/ +Signed-off-by: Varadarajan Narayanan +Link: https://lore.kernel.org/r/f4c4d65a7cb71e807d6d472c63c7718408c8f5f0.1697781921.git.quic_varada@quicinc.com +Signed-off-by: Bjorn Andersson +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-5.15/clk-qcom-gcc-msm8996-drop-unsupported-clock-sources.patch b/queue-5.15/clk-qcom-gcc-msm8996-drop-unsupported-clock-sources.patch new file mode 100644 index 00000000000..9c05275f40e --- /dev/null +++ b/queue-5.15/clk-qcom-gcc-msm8996-drop-unsupported-clock-sources.patch @@ -0,0 +1,123 @@ +From 6deb0edb736574297922aed9e13ccedb386f1b4d Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 28 Dec 2021 07:54:12 +0300 +Subject: clk: qcom: gcc-msm8996: drop unsupported clock sources + +From: Dmitry Baryshkov + +[ 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 +Signed-off-by: Bjorn Andersson +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 +--- + 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 + diff --git a/queue-5.15/clk-qcom-gcc-msm8996-move-clock-parent-tables-down.patch b/queue-5.15/clk-qcom-gcc-msm8996-move-clock-parent-tables-down.patch new file mode 100644 index 00000000000..157f7d3ee2f --- /dev/null +++ b/queue-5.15/clk-qcom-gcc-msm8996-move-clock-parent-tables-down.patch @@ -0,0 +1,228 @@ +From 2a8dabd8d0b8c34e0d9370ba081e1277d05f94e1 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 28 Dec 2021 07:54:13 +0300 +Subject: clk: qcom: gcc-msm8996: move clock parent tables down + +From: Dmitry Baryshkov + +[ 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 +Reviewed-by: Marijn Suijten +Reviewed-by: Stephen Boyd +Signed-off-by: Bjorn Andersson +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 +--- + 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 + diff --git a/queue-5.15/clk-qcom-gcc-msm8996-remove-rpm-bus-clocks.patch b/queue-5.15/clk-qcom-gcc-msm8996-remove-rpm-bus-clocks.patch new file mode 100644 index 00000000000..f87c10cddeb --- /dev/null +++ b/queue-5.15/clk-qcom-gcc-msm8996-remove-rpm-bus-clocks.patch @@ -0,0 +1,521 @@ +From 783e6719b00d27745f10d2aeb57ad31cbeeeb7c7 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 31 Aug 2023 11:39:14 +0200 +Subject: clk: qcom: gcc-msm8996: Remove RPM bus clocks + +From: Konrad Dybcio + +[ 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 +Reviewed-by: Dmitry Baryshkov +Tested-by: Dmitry Baryshkov +Link: https://lore.kernel.org/r/20230830-topic-rpmbusclocks8996gcc-v1-1-9e99bedcdc3b@linaro.org +Signed-off-by: Bjorn Andersson +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-5.15/clk-qcom-gcc-msm8996-use-array_size-instead-of-speci.patch b/queue-5.15/clk-qcom-gcc-msm8996-use-array_size-instead-of-speci.patch new file mode 100644 index 00000000000..33cefd139a6 --- /dev/null +++ b/queue-5.15/clk-qcom-gcc-msm8996-use-array_size-instead-of-speci.patch @@ -0,0 +1,579 @@ +From fb74a203f8a020b7db1e36bf34c90943cf3233b4 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +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 + +[ 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 +Reviewed-by: Marijn Suijten +Signed-off-by: Bjorn Andersson +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 +--- + 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 + diff --git a/queue-5.15/clk-qcom-gcc-msm8996-use-parent_hws-_data-instead-of.patch b/queue-5.15/clk-qcom-gcc-msm8996-use-parent_hws-_data-instead-of.patch new file mode 100644 index 00000000000..4c448033b49 --- /dev/null +++ b/queue-5.15/clk-qcom-gcc-msm8996-use-parent_hws-_data-instead-of.patch @@ -0,0 +1,2060 @@ +From 2c539d7b261e3a9e80e634d0a8dbb891641c152b Mon Sep 17 00:00:00 2001 +From: Sasha Levin +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 + +[ 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 +Reviewed-by: Marijn Suijten +Signed-off-by: Bjorn Andersson +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 +--- + 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 + diff --git a/queue-5.15/clk-qcom-gcc-sm8150-fix-gcc_sdcc2_apps_clk_src.patch b/queue-5.15/clk-qcom-gcc-sm8150-fix-gcc_sdcc2_apps_clk_src.patch new file mode 100644 index 00000000000..1175b371ee0 --- /dev/null +++ b/queue-5.15/clk-qcom-gcc-sm8150-fix-gcc_sdcc2_apps_clk_src.patch @@ -0,0 +1,39 @@ +From fc166442fa13945f36174f30a9e9220d700cc11e Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 13 Sep 2023 20:56:11 +0300 +Subject: clk: qcom: gcc-sm8150: Fix gcc_sdcc2_apps_clk_src + +From: Danila Tikhonov + +[ 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 +Signed-off-by: Danila Tikhonov +Reviewed-by: Konrad Dybcio +Link: https://lore.kernel.org/r/20230913175612.8685-1-danila@jiaxyga.com +Signed-off-by: Bjorn Andersson +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-5.15/clk-qcom-mmcc-msm8998-don-t-check-halt-bit-on-some-b.patch b/queue-5.15/clk-qcom-mmcc-msm8998-don-t-check-halt-bit-on-some-b.patch new file mode 100644 index 00000000000..56718355711 --- /dev/null +++ b/queue-5.15/clk-qcom-mmcc-msm8998-don-t-check-halt-bit-on-some-b.patch @@ -0,0 +1,55 @@ +From adfe05319d175bbf17fbb7bc8943fa6d72785993 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +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 + +[ 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 +Signed-off-by: Konrad Dybcio +Link: https://lore.kernel.org/r/20230531-topic-8998_mmssclk-v3-4-ba1b1fd9ee75@linaro.org +Signed-off-by: Bjorn Andersson +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-5.15/clk-qcom-mmcc-msm8998-fix-the-smmu-gdsc.patch b/queue-5.15/clk-qcom-mmcc-msm8998-fix-the-smmu-gdsc.patch new file mode 100644 index 00000000000..1d77141a591 --- /dev/null +++ b/queue-5.15/clk-qcom-mmcc-msm8998-fix-the-smmu-gdsc.patch @@ -0,0 +1,48 @@ +From 5b22ce30176315e1b2fc0a5f1005a442a463c81c Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 9 Aug 2023 21:20:28 +0200 +Subject: clk: qcom: mmcc-msm8998: Fix the SMMU GDSC + +From: Konrad Dybcio + +[ 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 +Reviewed-by: Jeffrey Hugo +Link: https://lore.kernel.org/r/20230531-topic-8998_mmssclk-v3-5-ba1b1fd9ee75@linaro.org +Signed-off-by: Bjorn Andersson +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-5.15/clk-renesas-rzg2l-fix-computation-formula.patch b/queue-5.15/clk-renesas-rzg2l-fix-computation-formula.patch new file mode 100644 index 00000000000..64d5dd6de6a --- /dev/null +++ b/queue-5.15/clk-renesas-rzg2l-fix-computation-formula.patch @@ -0,0 +1,70 @@ +From c59e1960079eee8ff88445181ee8e3862002557a Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 29 Sep 2023 08:38:52 +0300 +Subject: clk: renesas: rzg2l: Fix computation formula + +From: Claudiu Beznea + +[ 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 +Reviewed-by: Geert Uytterhoeven +Link: https://lore.kernel.org/r/20230929053915.1530607-6-claudiu.beznea@bp.renesas.com +Signed-off-by: Geert Uytterhoeven +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-5.15/clk-renesas-rzg2l-simplify-multiplication-shift-logi.patch b/queue-5.15/clk-renesas-rzg2l-simplify-multiplication-shift-logi.patch new file mode 100644 index 00000000000..6e1d306cf7f --- /dev/null +++ b/queue-5.15/clk-renesas-rzg2l-simplify-multiplication-shift-logi.patch @@ -0,0 +1,37 @@ +From 470e9f76be081fe2f1e0d9231cc4e992cdc1988f Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 21 Feb 2022 17:25:20 +0100 +Subject: clk: renesas: rzg2l: Simplify multiplication/shift logic + +From: Geert Uytterhoeven + +[ Upstream commit 29db30c45f07c929c86c40a5b85f18b69c89c638 ] + +"a * (1 << b)" == "a << b". + +No change in generated code. + +Signed-off-by: Geert Uytterhoeven +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 +--- + 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 + diff --git a/queue-5.15/clk-renesas-rzg2l-use-field_get-for-pll-register-fie.patch b/queue-5.15/clk-renesas-rzg2l-use-field_get-for-pll-register-fie.patch new file mode 100644 index 00000000000..454f636f3e8 --- /dev/null +++ b/queue-5.15/clk-renesas-rzg2l-use-field_get-for-pll-register-fie.patch @@ -0,0 +1,55 @@ +From 35f907c3056a04fc7785faffab4742304c7096dc Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 12 Sep 2023 07:51:33 +0300 +Subject: clk: renesas: rzg2l: Use FIELD_GET() for PLL register fields + +From: Claudiu Beznea + +[ Upstream commit 72977f07b035e488c3f1928832a1616c6cae7278 ] + +Use FIELD_GET() for PLL register fields. This is its purpose. + +Signed-off-by: Claudiu Beznea +Reviewed-by: Geert Uytterhoeven +Link: https://lore.kernel.org/r/20230912045157.177966-14-claudiu.beznea.uj@bp.renesas.com +Signed-off-by: Geert Uytterhoeven +Stable-dep-of: a2b23159499e ("clk: renesas: rzg2l: Fix computation formula") +Signed-off-by: Sasha Levin +--- + 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 + #include + #include + #include +@@ -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 + diff --git a/queue-5.15/clk-scmi-free-scmi_clk-allocated-when-the-clocks-wit.patch b/queue-5.15/clk-scmi-free-scmi_clk-allocated-when-the-clocks-wit.patch new file mode 100644 index 00000000000..77164e4c545 --- /dev/null +++ b/queue-5.15/clk-scmi-free-scmi_clk-allocated-when-the-clocks-wit.patch @@ -0,0 +1,40 @@ +From 2fc5a9726d8632d69afa3aa5f144d44a875e5d3b Mon Sep 17 00:00:00 2001 +From: Sasha Levin +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 + +[ Upstream commit 3537a75e73f3420614a358d0c8b390ea483cc87d ] + +Add the missing devm_kfree() when we skip the clocks with invalid or +missing information from the firmware. + +Cc: Cristian Marussi +Cc: Michael Turquette +Cc: Stephen Boyd +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 +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-5.15/clk-ti-add-ti_dt_clk_name-helper-to-use-clock-output.patch b/queue-5.15/clk-ti-add-ti_dt_clk_name-helper-to-use-clock-output.patch new file mode 100644 index 00000000000..a7e016149d0 --- /dev/null +++ b/queue-5.15/clk-ti-add-ti_dt_clk_name-helper-to-use-clock-output.patch @@ -0,0 +1,76 @@ +From 73685d5219ed276863a1eda06b155529f022956a Mon Sep 17 00:00:00 2001 +From: Sasha Levin +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 + +[ 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 +Link: https://lore.kernel.org/r/20220204071449.16762-7-tony@atomide.com +Signed-off-by: Stephen Boyd +Stable-dep-of: 7af5b9eadd64 ("clk: ti: fix double free in of_ti_divider_clk_setup()") +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-5.15/clk-ti-change-ti_clk_register-_omap_hw-api.patch b/queue-5.15/clk-ti-change-ti_clk_register-_omap_hw-api.patch new file mode 100644 index 00000000000..a7fa14b49cf --- /dev/null +++ b/queue-5.15/clk-ti-change-ti_clk_register-_omap_hw-api.patch @@ -0,0 +1,383 @@ +From 272f8514e89246faf3b2039ed057bdf9d83966d4 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 13 Nov 2022 19:11:46 +0100 +Subject: clk: ti: change ti_clk_register[_omap_hw]() API + +From: Dario Binacchi + +[ 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 +Tested-by: Tony Lindgren +Reviewed-by: Tony Lindgren +Link: https://lore.kernel.org/r/20221113181147.1626585-1-dario.binacchi@amarulasolutions.com +Signed-off-by: Stephen Boyd +Stable-dep-of: 7af5b9eadd64 ("clk: ti: fix double free in of_ti_divider_clk_setup()") +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-5.15/clk-ti-fix-double-free-in-of_ti_divider_clk_setup.patch b/queue-5.15/clk-ti-fix-double-free-in-of_ti_divider_clk_setup.patch new file mode 100644 index 00000000000..35de55d494a --- /dev/null +++ b/queue-5.15/clk-ti-fix-double-free-in-of_ti_divider_clk_setup.patch @@ -0,0 +1,51 @@ +From 3eb6c9b627fee0d03c9f5bd460fad4141187cb55 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 2 Oct 2023 10:04:36 +0300 +Subject: clk: ti: fix double free in of_ti_divider_clk_setup() + +From: Dan Carpenter + +[ 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 +Link: https://lore.kernel.org/r/6d36eeec-6c8a-4f11-a579-aa3cd7c38749@moroto.mountain +Reviewed-by: Tony Lindgren +Signed-off-by: Stephen Boyd +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-5.15/clk-ti-update-component-clocks-to-use-ti_dt_clk_name.patch b/queue-5.15/clk-ti-update-component-clocks-to-use-ti_dt_clk_name.patch new file mode 100644 index 00000000000..819b397a07d --- /dev/null +++ b/queue-5.15/clk-ti-update-component-clocks-to-use-ti_dt_clk_name.patch @@ -0,0 +1,212 @@ +From 815a983c9995ddd0e0da5beaf2a7f63a4fd660d3 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 4 Feb 2022 09:14:49 +0200 +Subject: clk: ti: Update component clocks to use ti_dt_clk_name() + +From: Tony Lindgren + +[ 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 +Link: https://lore.kernel.org/r/20220204071449.16762-9-tony@atomide.com +Signed-off-by: Stephen Boyd +Stable-dep-of: 7af5b9eadd64 ("clk: ti: fix double free in of_ti_divider_clk_setup()") +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-5.15/clk-ti-update-pll-and-clockdomain-clocks-to-use-ti_d.patch b/queue-5.15/clk-ti-update-pll-and-clockdomain-clocks-to-use-ti_d.patch new file mode 100644 index 00000000000..2779fd69fd9 --- /dev/null +++ b/queue-5.15/clk-ti-update-pll-and-clockdomain-clocks-to-use-ti_d.patch @@ -0,0 +1,189 @@ +From 3f872f672656ea4f9f168f8cf5ed146cf6c449d2 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +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 + +[ 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 +Link: https://lore.kernel.org/r/20220204071449.16762-8-tony@atomide.com +Signed-off-by: Stephen Boyd +Stable-dep-of: 7af5b9eadd64 ("clk: ti: fix double free in of_ti_divider_clk_setup()") +Signed-off-by: Sasha Levin +--- + 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 + #include + ++#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 + diff --git a/queue-5.15/crypto-caam-jr-fix-chacha20-poly1305-self-test-failu.patch b/queue-5.15/crypto-caam-jr-fix-chacha20-poly1305-self-test-failu.patch new file mode 100644 index 00000000000..43e84097b79 --- /dev/null +++ b/queue-5.15/crypto-caam-jr-fix-chacha20-poly1305-self-test-failu.patch @@ -0,0 +1,39 @@ +From 51648916509b04fb13d4b445e7bf85355ea8e330 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 21 Sep 2023 18:12:37 +0530 +Subject: crypto: caam/jr - fix Chacha20 + Poly1305 self test failure + +From: Gaurav Jain + +[ 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 +Signed-off-by: Herbert Xu +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-5.15/crypto-caam-qi2-fix-chacha20-poly1305-self-test-fail.patch b/queue-5.15/crypto-caam-qi2-fix-chacha20-poly1305-self-test-fail.patch new file mode 100644 index 00000000000..42b18ac17ed --- /dev/null +++ b/queue-5.15/crypto-caam-qi2-fix-chacha20-poly1305-self-test-fail.patch @@ -0,0 +1,39 @@ +From 8e7a1bce651a8d8ecac288a59a7a119fc147db55 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 21 Sep 2023 15:14:44 +0530 +Subject: crypto: caam/qi2 - fix Chacha20 + Poly1305 self test failure + +From: Gaurav Jain + +[ 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 +Signed-off-by: Herbert Xu +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-5.15/crypto-hisilicon-hpre-fix-a-erroneous-check-after-sn.patch b/queue-5.15/crypto-hisilicon-hpre-fix-a-erroneous-check-after-sn.patch new file mode 100644 index 00000000000..903f2c1a65f --- /dev/null +++ b/queue-5.15/crypto-hisilicon-hpre-fix-a-erroneous-check-after-sn.patch @@ -0,0 +1,36 @@ +From 3d7fbdb353d28bd8b18652d9136803a479eefebc Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 4 Sep 2023 22:17:29 +0200 +Subject: crypto: hisilicon/hpre - Fix a erroneous check after snprintf() + +From: Christophe JAILLET + +[ 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 +Signed-off-by: Herbert Xu +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-5.15/crypto-qat-fix-deadlock-in-backlog-processing.patch b/queue-5.15/crypto-qat-fix-deadlock-in-backlog-processing.patch new file mode 100644 index 00000000000..f08071f063a --- /dev/null +++ b/queue-5.15/crypto-qat-fix-deadlock-in-backlog-processing.patch @@ -0,0 +1,110 @@ +From 6b3d9ebde2c07386924ccc81f4ad196bf6e8fa88 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 20 Oct 2023 16:33:21 +0100 +Subject: crypto: qat - fix deadlock in backlog processing + +From: Giovanni Cabiddu + +[ 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 +Closes: https://lore.kernel.org/all/af9581e2-58f9-cc19-428f-6f18f1f83d54@redhat.com/T/ +Signed-off-by: Giovanni Cabiddu +Reviewed-by: Mikulas Patocka +Signed-off-by: Herbert Xu +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-5.15/crypto-qat-increase-size-of-buffers.patch b/queue-5.15/crypto-qat-increase-size-of-buffers.patch new file mode 100644 index 00000000000..a72b9c0007a --- /dev/null +++ b/queue-5.15/crypto-qat-increase-size-of-buffers.patch @@ -0,0 +1,72 @@ +From 8549520c34980a2bed97a24a4a34a7e1da4892e4 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +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 + +[ 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 +Reviewed-by: Damian Muszynski +Signed-off-by: Herbert Xu +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-5.15/cxl-mbox-introduce-the-mbox_send-operation.patch b/queue-5.15/cxl-mbox-introduce-the-mbox_send-operation.patch new file mode 100644 index 00000000000..4e64c30b9a7 --- /dev/null +++ b/queue-5.15/cxl-mbox-introduce-the-mbox_send-operation.patch @@ -0,0 +1,249 @@ +From 95450736c43196f26156fd19c4304c558fc7cc04 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 8 Sep 2021 22:12:21 -0700 +Subject: cxl/mbox: Introduce the mbox_send operation + +From: Dan Williams + +[ 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 +Reviewed-by: Jonathan Cameron +Reviewed-by: Ben Widawsky +Link: https://lore.kernel.org/r/163116434098.2460985.9004760022659400540.stgit@dwillia2-desk3.amr.corp.intel.com +Signed-off-by: Dan Williams +Stable-dep-of: 88d3917f82ed ("cxl/mem: Fix shutdown order") +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-5.15/cxl-mbox-move-mailbox-and-other-non-pci-specific-inf.patch b/queue-5.15/cxl-mbox-move-mailbox-and-other-non-pci-specific-inf.patch new file mode 100644 index 00000000000..8bcdfab1a25 --- /dev/null +++ b/queue-5.15/cxl-mbox-move-mailbox-and-other-non-pci-specific-inf.patch @@ -0,0 +1,2190 @@ +From ee60d6cb210a5458e01c8c2e243b44605f8744d0 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +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 + +[ 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 +Reported-by: kernel test robot +Reviewed-by: Jonathan Cameron +Link: https://lore.kernel.org/r/163116435233.2460985.16197340449713287180.stgit@dwillia2-desk3.amr.corp.intel.com +Signed-off-by: Dan Williams +Stable-dep-of: 88d3917f82ed ("cxl/mem: Fix shutdown order") +Signed-off-by: Sasha Levin +--- + .../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 ++#include ++#include ++#include ++#include ++#include ++ ++#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 + #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 + #include + #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 +-#include +-#include ++#include + #include + #include + #include + #include +-#include + #include + #include +-#include + #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 + diff --git a/queue-5.15/cxl-mem-fix-shutdown-order.patch b/queue-5.15/cxl-mem-fix-shutdown-order.patch new file mode 100644 index 00000000000..5b54673c6b7 --- /dev/null +++ b/queue-5.15/cxl-mem-fix-shutdown-order.patch @@ -0,0 +1,84 @@ +From 4cb065db9dcd2f5640134546185d56f521b9567a Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 28 Sep 2023 18:02:07 -0700 +Subject: cxl/mem: Fix shutdown order + +From: Dan Williams + +[ 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: + + 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 +Reviewed-by: Davidlohr Bueso +Reviewed-by: Dave Jiang +Reviewed-by: Jonathan Cameron +Reviewed-by: Ira Weiny +Tested-by: Ira Weiny +Signed-off-by: Dan Williams +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-5.15/cxl-pci-clean-up-cxl_mem_get_partition_info.patch b/queue-5.15/cxl-pci-clean-up-cxl_mem_get_partition_info.patch new file mode 100644 index 00000000000..5e4d4734a2b --- /dev/null +++ b/queue-5.15/cxl-pci-clean-up-cxl_mem_get_partition_info.patch @@ -0,0 +1,136 @@ +From 2aa7660aae4c8173c4527cb49fa9dcc9d81e01cc Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 13 Sep 2021 15:24:32 -0700 +Subject: cxl/pci: Clean up cxl_mem_get_partition_info() + +From: Dan Williams + +[ 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 +Reported-by: Ben Widawsky +Reviewed-by: Jonathan Cameron +Link: https://lore.kernel.org/r/163157174216.2653013.1277706528753990974.stgit@dwillia2-desk3.amr.corp.intel.com +Signed-off-by: Dan Williams +Stable-dep-of: 88d3917f82ed ("cxl/mem: Fix shutdown order") +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-5.15/cxl-pci-drop-idr.h.patch b/queue-5.15/cxl-pci-drop-idr.h.patch new file mode 100644 index 00000000000..34aee166bce --- /dev/null +++ b/queue-5.15/cxl-pci-drop-idr.h.patch @@ -0,0 +1,39 @@ +From 450f15a5d86562de77ca4dc7fd882f5f0067d251 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 8 Sep 2021 22:12:26 -0700 +Subject: cxl/pci: Drop idr.h + +From: Dan Williams + +[ 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 +Reported-by: Jonathan Cameron +Reviewed-by: Jonathan Cameron +Reviewed-by: Ben Widawsky +Link: https://lore.kernel.org/r/163116434668.2460985.12264757586266849616.stgit@dwillia2-desk3.amr.corp.intel.com +Signed-off-by: Dan Williams +Stable-dep-of: 88d3917f82ed ("cxl/mem: Fix shutdown order") +Signed-off-by: Sasha Levin +--- + 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 + #include + #include +-#include + #include + #include + #include +-- +2.42.0 + diff --git a/queue-5.15/cxl-pci-make-struct-cxl_mem-device-type-generic.patch b/queue-5.15/cxl-pci-make-struct-cxl_mem-device-type-generic.patch new file mode 100644 index 00000000000..74b8107caf7 --- /dev/null +++ b/queue-5.15/cxl-pci-make-struct-cxl_mem-device-type-generic.patch @@ -0,0 +1,355 @@ +From fec63be32a3f61c396c2ba2b911db98b92a54107 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 8 Sep 2021 22:12:09 -0700 +Subject: cxl/pci: Make 'struct cxl_mem' device type generic + +From: Dan Williams + +[ 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 +Reviewed-by: Jonathan Cameron +Reviewed-by: Ben Widawsky +Link: https://lore.kernel.org/r/163116432973.2460985.7553504957932024222.stgit@dwillia2-desk3.amr.corp.intel.com +Signed-off-by: Dan Williams +Stable-dep-of: 88d3917f82ed ("cxl/mem: Fix shutdown order") +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-5.15/dmaengine-idxd-register-dsa_bus_type-before-register.patch b/queue-5.15/dmaengine-idxd-register-dsa_bus_type-before-register.patch new file mode 100644 index 00000000000..ff260538fbd --- /dev/null +++ b/queue-5.15/dmaengine-idxd-register-dsa_bus_type-before-register.patch @@ -0,0 +1,63 @@ +From cef30404d7f329fd0a8c3b58d65b02f3fe799dfd Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 24 Sep 2023 09:22:32 -0700 +Subject: dmaengine: idxd: Register dsa_bus_type before registering idxd + sub-drivers + +From: Fenghua Yu + +[ 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 +Signed-off-by: Fenghua Yu +Reviewed-by: Dave Jiang +Reviewed-by: Lijun Pan +Tested-by: Lijun Pan +Link: https://lore.kernel.org/r/20230924162232.1409454-1-fenghua.yu@intel.com +Signed-off-by: Vinod Koul +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-5.15/dmaengine-pxa_dma-remove-an-erroneous-bug_on-in-pxad.patch b/queue-5.15/dmaengine-pxa_dma-remove-an-erroneous-bug_on-in-pxad.patch new file mode 100644 index 00000000000..e3a392ffc43 --- /dev/null +++ b/queue-5.15/dmaengine-pxa_dma-remove-an-erroneous-bug_on-in-pxad.patch @@ -0,0 +1,43 @@ +From b293bb4c2bf0ee22c8ab169c53a13b9c0fc26be4 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +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 + +[ 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 +Link: https://lore.kernel.org/r/c8fc5563c9593c914fde41f0f7d1489a21b45a9a.1696676782.git.christophe.jaillet@wanadoo.fr +Signed-off-by: Vinod Koul +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-5.15/dmaengine-ti-edma-handle-irq_of_parse_and_map-errors.patch b/queue-5.15/dmaengine-ti-edma-handle-irq_of_parse_and_map-errors.patch new file mode 100644 index 00000000000..3ed4f0cb658 --- /dev/null +++ b/queue-5.15/dmaengine-ti-edma-handle-irq_of_parse_and_map-errors.patch @@ -0,0 +1,48 @@ +From 21cbc9a74b2edd6e2fd17e7c47c28ba0530f60a3 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 15 Sep 2023 15:59:59 +0300 +Subject: dmaengine: ti: edma: handle irq_of_parse_and_map() errors + +From: Dan Carpenter + +[ 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 +Acked-by: Peter Ujfalusi +Link: https://lore.kernel.org/r/f15cb6a7-8449-4f79-98b6-34072f04edbc@moroto.mountain +Signed-off-by: Vinod Koul +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-5.15/drm-amdkfd-fix-some-race-conditions-in-vram-buffer-a.patch b/queue-5.15/drm-amdkfd-fix-some-race-conditions-in-vram-buffer-a.patch new file mode 100644 index 00000000000..52e73bd75a6 --- /dev/null +++ b/queue-5.15/drm-amdkfd-fix-some-race-conditions-in-vram-buffer-a.patch @@ -0,0 +1,50 @@ +From 49d2451d6b1a1e1518954a829261c73a3f2bb3ff Mon Sep 17 00:00:00 2001 +From: Sasha Levin +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 + +[ 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 +Reviewed-by: Felix Kuehling +Signed-off-by: Alex Deucher +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-5.15/drm-bridge-lt8912b-add-hot-plug-detection.patch b/queue-5.15/drm-bridge-lt8912b-add-hot-plug-detection.patch new file mode 100644 index 00000000000..1d5f2739d2d --- /dev/null +++ b/queue-5.15/drm-bridge-lt8912b-add-hot-plug-detection.patch @@ -0,0 +1,74 @@ +From ac2522362394c2b4eda54d4b81f1135836b4edce Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 28 Nov 2022 12:23:20 +0100 +Subject: drm/bridge: lt8912b: Add hot plug detection + +From: Stefan Eichenberger + +[ 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 +Signed-off-by: Francesco Dolcini +Reviewed-by: Adrien Grassein +Reviewed-by: Robert Foss +Signed-off-by: Robert Foss +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 +--- + 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 + diff --git a/queue-5.15/drm-bridge-lt8912b-add-missing-drm_bridge_attach-cal.patch b/queue-5.15/drm-bridge-lt8912b-add-missing-drm_bridge_attach-cal.patch new file mode 100644 index 00000000000..e1c24128639 --- /dev/null +++ b/queue-5.15/drm-bridge-lt8912b-add-missing-drm_bridge_attach-cal.patch @@ -0,0 +1,46 @@ +From e0842810e16a4adfac827f17a838c9e9e724d703 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 4 Aug 2023 13:48:13 +0300 +Subject: drm/bridge: lt8912b: Add missing drm_bridge_attach call + +From: Tomi Valkeinen + +[ 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 +Reviewed-by: Robert Foss +Signed-off-by: Robert Foss +Link: https://patchwork.freedesktop.org/patch/msgid/20230804-lt8912b-v1-4-c542692c6a2f@ideasonboard.com +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-5.15/drm-bridge-lt8912b-fix-bridge_detach.patch b/queue-5.15/drm-bridge-lt8912b-fix-bridge_detach.patch new file mode 100644 index 00000000000..de54ea0ad0d --- /dev/null +++ b/queue-5.15/drm-bridge-lt8912b-fix-bridge_detach.patch @@ -0,0 +1,82 @@ +From 91da7a12a3eb0d3b19a628f1dd58c2f0e4024054 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 4 Aug 2023 13:48:10 +0300 +Subject: drm/bridge: lt8912b: Fix bridge_detach + +From: Tomi Valkeinen + +[ 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 +Reviewed-by: Robert Foss +Signed-off-by: Robert Foss +Link: https://patchwork.freedesktop.org/patch/msgid/20230804-lt8912b-v1-1-c542692c6a2f@ideasonboard.com +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-5.15/drm-bridge-lt8912b-fix-crash-on-bridge-detach.patch b/queue-5.15/drm-bridge-lt8912b-fix-crash-on-bridge-detach.patch new file mode 100644 index 00000000000..41c3283ec3e --- /dev/null +++ b/queue-5.15/drm-bridge-lt8912b-fix-crash-on-bridge-detach.patch @@ -0,0 +1,109 @@ +From b0f481c45c01d2a386e38f0c1e4912aa7a661981 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 4 Aug 2023 13:48:11 +0300 +Subject: drm/bridge: lt8912b: Fix crash on bridge detach + +From: Tomi Valkeinen + +[ 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 +Reviewed-by: Robert Foss +Signed-off-by: Robert Foss +Link: https://patchwork.freedesktop.org/patch/msgid/20230804-lt8912b-v1-2-c542692c6a2f@ideasonboard.com +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-5.15/drm-bridge-lt8912b-manually-disable-hpd-only-if-it-w.patch b/queue-5.15/drm-bridge-lt8912b-manually-disable-hpd-only-if-it-w.patch new file mode 100644 index 00000000000..49c9c24c21c --- /dev/null +++ b/queue-5.15/drm-bridge-lt8912b-manually-disable-hpd-only-if-it-w.patch @@ -0,0 +1,44 @@ +From 47f9aa56c92b0ee9b131f1fa7c30d75fb2560be2 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 4 Aug 2023 13:48:12 +0300 +Subject: drm/bridge: lt8912b: Manually disable HPD only if it was enabled + +From: Tomi Valkeinen + +[ 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 +Tested-by: Marcel Ziswiler +Reviewed-by: Robert Foss +Signed-off-by: Robert Foss +Link: https://patchwork.freedesktop.org/patch/msgid/20230804-lt8912b-v1-3-c542692c6a2f@ideasonboard.com +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-5.15/drm-bridge-lt8912b-register-and-attach-our-dsi-devic.patch b/queue-5.15/drm-bridge-lt8912b-register-and-attach-our-dsi-devic.patch new file mode 100644 index 00000000000..28572bf2734 --- /dev/null +++ b/queue-5.15/drm-bridge-lt8912b-register-and-attach-our-dsi-devic.patch @@ -0,0 +1,56 @@ +From 3c4515b29563df7f164c18188c98821f2da3f2d8 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 25 Oct 2021 17:15:21 +0200 +Subject: drm/bridge: lt8912b: Register and attach our DSI device at probe + +From: Maxime Ripard + +[ 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 +Signed-off-by: Maxime Ripard +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 +--- + 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 + diff --git a/queue-5.15/drm-bridge-lt8912b-switch-to-devm-mipi-dsi-helpers.patch b/queue-5.15/drm-bridge-lt8912b-switch-to-devm-mipi-dsi-helpers.patch new file mode 100644 index 00000000000..6c29b29f80c --- /dev/null +++ b/queue-5.15/drm-bridge-lt8912b-switch-to-devm-mipi-dsi-helpers.patch @@ -0,0 +1,77 @@ +From 9e99f0286e16b79585c4303b7ecb03979e67ef29 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 25 Oct 2021 17:15:20 +0200 +Subject: drm/bridge: lt8912b: Switch to devm MIPI-DSI helpers + +From: Maxime Ripard + +[ Upstream commit 1fdbf66e3d40257902b4c5cdf872730dae24004f ] + +Let's switch to the new devm MIPI-DSI function to register and attach +our secondary device. + +Acked-by: Sam Ravnborg +Signed-off-by: Maxime Ripard +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 +--- + 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 + diff --git a/queue-5.15/drm-bridge-lt9611uxc-fix-the-race-in-the-error-path.patch b/queue-5.15/drm-bridge-lt9611uxc-fix-the-race-in-the-error-path.patch new file mode 100644 index 00000000000..b17650b43e1 --- /dev/null +++ b/queue-5.15/drm-bridge-lt9611uxc-fix-the-race-in-the-error-path.patch @@ -0,0 +1,97 @@ +From e361bf4a5728d60658080eea4a8fe30ee27820cd Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 12 Oct 2023 01:00:02 +0300 +Subject: drm/bridge: lt9611uxc: fix the race in the error path + +From: Dmitry Baryshkov + +[ 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): [] finish_task_switch.isra.0+0xa8/0x278 +hardirqs last disabled at (15798): [] __schedule+0x7b8/0xbd8 +softirqs last enabled at (15794): [] __do_softirq+0x498/0x4e0 +softirqs last disabled at (15771): [] ____do_softirq+0x10/0x1c + +Fixes: bc6fa8676ebb ("drm/bridge/lontium-lt9611uxc: move HPD notification out of IRQ handler") +Signed-off-by: Dmitry Baryshkov +Reviewed-by: Robert Foss +Signed-off-by: Robert Foss +Link: https://patchwork.freedesktop.org/patch/msgid/20231011220002.382422-1-dmitry.baryshkov@linaro.org +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-5.15/drm-bridge-lt9611uxc-register-and-attach-our-dsi-dev.patch b/queue-5.15/drm-bridge-lt9611uxc-register-and-attach-our-dsi-dev.patch new file mode 100644 index 00000000000..b2bd8c29ee0 --- /dev/null +++ b/queue-5.15/drm-bridge-lt9611uxc-register-and-attach-our-dsi-dev.patch @@ -0,0 +1,76 @@ +From b5b7ebc758de810cde1fe1a8b6dc0c360a16ce5f Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 25 Oct 2021 17:15:25 +0200 +Subject: drm/bridge: lt9611uxc: Register and attach our DSI device at probe + +From: Maxime Ripard + +[ 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 +Signed-off-by: Maxime Ripard +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 +--- + 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 + diff --git a/queue-5.15/drm-bridge-lt9611uxc-switch-to-devm-mipi-dsi-helpers.patch b/queue-5.15/drm-bridge-lt9611uxc-switch-to-devm-mipi-dsi-helpers.patch new file mode 100644 index 00000000000..057b66079d9 --- /dev/null +++ b/queue-5.15/drm-bridge-lt9611uxc-switch-to-devm-mipi-dsi-helpers.patch @@ -0,0 +1,113 @@ +From 3efc5c224d70063d85d9dbedcf4c850335afe2c8 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 25 Oct 2021 17:15:24 +0200 +Subject: drm/bridge: lt9611uxc: Switch to devm MIPI-DSI helpers + +From: Maxime Ripard + +[ Upstream commit 293ada7b058e536d9d53d0d8840c6ba8c2f718e4 ] + +Let's switch to the new devm MIPI-DSI function to register and attach +our secondary device. + +Acked-by: Sam Ravnborg +Signed-off-by: Maxime Ripard +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 +--- + 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 + diff --git a/queue-5.15/drm-bridge-tc358768-disable-non-continuous-clock-mod.patch b/queue-5.15/drm-bridge-tc358768-disable-non-continuous-clock-mod.patch new file mode 100644 index 00000000000..0ba3d45050e --- /dev/null +++ b/queue-5.15/drm-bridge-tc358768-disable-non-continuous-clock-mod.patch @@ -0,0 +1,78 @@ +From b2d5f4025af48f6cacb05d6613566856e094ecca Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 3 Oct 2021 02:34:46 +0300 +Subject: drm/bridge: tc358768: Disable non-continuous clock mode + +From: Dmitry Osipenko + +[ 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 # Asus TF700T +Tested-by: Maxim Schwalm #TF700T +Signed-off-by: Dmitry Osipenko +Reviewed-by: Robert Foss +Signed-off-by: Robert Foss +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 +--- + 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 + diff --git a/queue-5.15/drm-bridge-tc358768-fix-bit-updates.patch b/queue-5.15/drm-bridge-tc358768-fix-bit-updates.patch new file mode 100644 index 00000000000..d743ca06f12 --- /dev/null +++ b/queue-5.15/drm-bridge-tc358768-fix-bit-updates.patch @@ -0,0 +1,66 @@ +From 7692a35b9d796feffb0b88e02c0695f34ace12ed Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 6 Sep 2023 09:50:51 +0300 +Subject: drm/bridge: tc358768: Fix bit updates + +From: Tomi Valkeinen + +[ 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 +Tested-by: Maxim Schwalm # Asus TF700T +Tested-by: Marcel Ziswiler +Signed-off-by: Tomi Valkeinen +Signed-off-by: Robert Foss +Link: https://patchwork.freedesktop.org/patch/msgid/20230906-tc358768-v4-4-31725f008a50@ideasonboard.com +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-5.15/drm-bridge-tc358768-fix-use-of-uninitialized-variabl.patch b/queue-5.15/drm-bridge-tc358768-fix-use-of-uninitialized-variabl.patch new file mode 100644 index 00000000000..0936acbafbe --- /dev/null +++ b/queue-5.15/drm-bridge-tc358768-fix-use-of-uninitialized-variabl.patch @@ -0,0 +1,46 @@ +From 2c1f76f09b61b3c16b1e286a8a739e2588f61aa0 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 6 Sep 2023 09:50:49 +0300 +Subject: drm/bridge: tc358768: Fix use of uninitialized variable + +From: Tomi Valkeinen + +[ 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 +Tested-by: Maxim Schwalm # Asus TF700T +Tested-by: Marcel Ziswiler +Signed-off-by: Tomi Valkeinen +Signed-off-by: Robert Foss +Link: https://patchwork.freedesktop.org/patch/msgid/20230906-tc358768-v4-2-31725f008a50@ideasonboard.com +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-5.15/drm-mediatek-fix-iommu-fault-by-swapping-fbs-after-u.patch b/queue-5.15/drm-mediatek-fix-iommu-fault-by-swapping-fbs-after-u.patch new file mode 100644 index 00000000000..03fa3f6cb21 --- /dev/null +++ b/queue-5.15/drm-mediatek-fix-iommu-fault-by-swapping-fbs-after-u.patch @@ -0,0 +1,47 @@ +From 61b1471f1681c392ead9e8516f865c36748d38ec Mon Sep 17 00:00:00 2001 +From: Sasha Levin +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 + +[ 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 +Reviewed-by: AngeloGioacchino Del Regno +Reviewed-by: CK Hu +Reviewed-by: Alexandre Mergnat +Link: https://patchwork.kernel.org/project/linux-mediatek/patch/20230809125722.24112-2-jason-jh.lin@mediatek.com/ +Signed-off-by: Chun-Kuang Hu +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-5.15/drm-mediatek-fix-iommu-fault-during-crtc-enabling.patch b/queue-5.15/drm-mediatek-fix-iommu-fault-during-crtc-enabling.patch new file mode 100644 index 00000000000..90433b2750e --- /dev/null +++ b/queue-5.15/drm-mediatek-fix-iommu-fault-during-crtc-enabling.patch @@ -0,0 +1,55 @@ +From bea5db616f5d960066aceae0cf963881dab6b52b Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 9 Aug 2023 20:57:22 +0800 +Subject: drm/mediatek: Fix iommu fault during crtc enabling + +From: Jason-JH.Lin + +[ 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 +Reviewed-by: Alexandre Mergnat +Reviewed-by: AngeloGioacchino Del Regno +Reviewed-by: CK Hu +Link: https://patchwork.kernel.org/project/linux-mediatek/patch/20230809125722.24112-3-jason-jh.lin@mediatek.com/ +Signed-off-by: Chun-Kuang Hu +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-5.15/drm-mediatek-mtk_dsi-fix-no_eot_packet-settings-hand.patch b/queue-5.15/drm-mediatek-mtk_dsi-fix-no_eot_packet-settings-hand.patch new file mode 100644 index 00000000000..2e6e8536540 --- /dev/null +++ b/queue-5.15/drm-mediatek-mtk_dsi-fix-no_eot_packet-settings-hand.patch @@ -0,0 +1,67 @@ +From 9020fdcd57d70b8d51b55548a0854f43f34607ec Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 23 May 2023 12:42:34 +0200 +Subject: drm: mediatek: mtk_dsi: Fix NO_EOT_PACKET settings/handling + +From: AngeloGioacchino Del Regno + +[ 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 +Reviewed-by: Alexandre Mergnat +Tested-by: Michael Walle +Link: https://patchwork.kernel.org/project/dri-devel/patch/20230523104234.7849-1-angelogioacchino.delregno@collabora.com/ +Signed-off-by: Chun-Kuang Hu +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-5.15/drm-mipi-dsi-create-devm-device-attachment.patch b/queue-5.15/drm-mipi-dsi-create-devm-device-attachment.patch new file mode 100644 index 00000000000..9ae8f678386 --- /dev/null +++ b/queue-5.15/drm-mipi-dsi-create-devm-device-attachment.patch @@ -0,0 +1,89 @@ +From 48507e6d11abce4b0ad9519d5bd9dfc0518d4e68 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 10 Sep 2021 12:11:58 +0200 +Subject: drm/mipi-dsi: Create devm device attachment + +From: Maxime Ripard + +[ 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 +Signed-off-by: Maxime Ripard +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 +--- + 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 + diff --git a/queue-5.15/drm-mipi-dsi-create-devm-device-registration.patch b/queue-5.15/drm-mipi-dsi-create-devm-device-registration.patch new file mode 100644 index 00000000000..d3e378f4aed --- /dev/null +++ b/queue-5.15/drm-mipi-dsi-create-devm-device-registration.patch @@ -0,0 +1,103 @@ +From c3d566132ac0cbd3f5eec283f97b610e8a88fd11 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 10 Sep 2021 12:11:57 +0200 +Subject: drm/mipi-dsi: Create devm device registration + +From: Maxime Ripard + +[ 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 +Signed-off-by: Maxime Ripard +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 +--- + 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 + diff --git a/queue-5.15/drm-msm-dsi-use-msm_gem_kernel_put-to-free-tx-buffer.patch b/queue-5.15/drm-msm-dsi-use-msm_gem_kernel_put-to-free-tx-buffer.patch new file mode 100644 index 00000000000..ddea5c99dd7 --- /dev/null +++ b/queue-5.15/drm-msm-dsi-use-msm_gem_kernel_put-to-free-tx-buffer.patch @@ -0,0 +1,41 @@ +From 188d674b81875a5a1bcca02e0cbf34c92729e588 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +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 + +[ 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 +Reviewed-by: Abhinav Kumar +Patchwork: https://patchwork.freedesktop.org/patch/562239/ +Signed-off-by: Rob Clark +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-5.15/drm-radeon-possible-buffer-overflow.patch b/queue-5.15/drm-radeon-possible-buffer-overflow.patch new file mode 100644 index 00000000000..1f85c3915dc --- /dev/null +++ b/queue-5.15/drm-radeon-possible-buffer-overflow.patch @@ -0,0 +1,47 @@ +From 065d07e8165b48868062d4d6e4c91bbe4597a9a0 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 17 Aug 2023 19:33:49 +0800 +Subject: drm/radeon: possible buffer overflow + +From: Konstantin Meskhidze + +[ 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 +Signed-off-by: Konstantin Meskhidze +Signed-off-by: Alex Deucher +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-5.15/drm-rockchip-cdn-dp-fix-some-error-handling-paths-in.patch b/queue-5.15/drm-rockchip-cdn-dp-fix-some-error-handling-paths-in.patch new file mode 100644 index 00000000000..97634accc34 --- /dev/null +++ b/queue-5.15/drm-rockchip-cdn-dp-fix-some-error-handling-paths-in.patch @@ -0,0 +1,60 @@ +From e449edee866e355fc4c0bc4f3679fc4e526aac99 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +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 + +[ 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 +Signed-off-by: Heiko Stuebner +Link: https://patchwork.freedesktop.org/patch/msgid/8494a41602fadb7439630921a9779640698f2f9f.1693676045.git.christophe.jaillet@wanadoo.fr +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-5.15/drm-rockchip-fix-type-promotion-bug-in-rockchip_gem_.patch b/queue-5.15/drm-rockchip-fix-type-promotion-bug-in-rockchip_gem_.patch new file mode 100644 index 00000000000..9c465f812fe --- /dev/null +++ b/queue-5.15/drm-rockchip-fix-type-promotion-bug-in-rockchip_gem_.patch @@ -0,0 +1,40 @@ +From 0636b7dca86cf5cfbceda917d3028d4ff66a952c Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 11 Oct 2023 11:01:48 +0300 +Subject: drm/rockchip: Fix type promotion bug in rockchip_gem_iommu_map() + +From: Dan Carpenter + +[ 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 +Signed-off-by: Heiko Stuebner +Link: https://patchwork.freedesktop.org/patch/msgid/2bfa28b5-145d-4b9e-a18a-98819dd686ce@moroto.mountain +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-5.15/drm-rockchip-vop-fix-call-to-crtc-reset-helper.patch b/queue-5.15/drm-rockchip-vop-fix-call-to-crtc-reset-helper.patch new file mode 100644 index 00000000000..7a5916093a5 --- /dev/null +++ b/queue-5.15/drm-rockchip-vop-fix-call-to-crtc-reset-helper.patch @@ -0,0 +1,43 @@ +From e27ba74b2b93f483b670ff56b0e2c74eb16db249 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 21 Jun 2023 22:33:20 +0000 +Subject: drm/rockchip: vop: Fix call to crtc reset helper + +From: Jonas Karlman + +[ 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 +Reviewed-by: Sascha Hauer +Signed-off-by: Heiko Stuebner +Link: https://patchwork.freedesktop.org/patch/msgid/20230621223311.2239547-4-jonas@kwiboo.se +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-5.15/drm-rockchip-vop-fix-reset-of-state-in-duplicate-sta.patch b/queue-5.15/drm-rockchip-vop-fix-reset-of-state-in-duplicate-sta.patch new file mode 100644 index 00000000000..f4b51c04065 --- /dev/null +++ b/queue-5.15/drm-rockchip-vop-fix-reset-of-state-in-duplicate-sta.patch @@ -0,0 +1,42 @@ +From e3caefcd279b2e0e489933d3bf46e837aa650187 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +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 + +[ 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 +Reviewed-by: Sascha Hauer +Signed-off-by: Heiko Stuebner +Link: https://patchwork.freedesktop.org/patch/msgid/20230621223311.2239547-2-jonas@kwiboo.se +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-5.15/ext4-move-ix-sanity-check-to-corrent-position.patch b/queue-5.15/ext4-move-ix-sanity-check-to-corrent-position.patch new file mode 100644 index 00000000000..c8b570edaa7 --- /dev/null +++ b/queue-5.15/ext4-move-ix-sanity-check-to-corrent-position.patch @@ -0,0 +1,51 @@ +From 42e0e3b8eaa789b7ac858238cfe15530b78587c7 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 6 Sep 2023 09:33:41 +0800 +Subject: ext4: move 'ix' sanity check to corrent position + +From: Gou Hao + +[ Upstream commit af90a8f4a09ec4a3de20142e37f37205d4687f28 ] + +Check 'ix' before it is used. + +Fixes: 80e675f906db ("ext4: optimize memmmove lengths in extent/index insertions") +Signed-off-by: Gou Hao +Link: https://lore.kernel.org/r/20230906013341.7199-1-gouhao@uniontech.com +Signed-off-by: Theodore Ts'o +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-5.15/f2fs-compress-fix-to-avoid-redundant-compress-extens.patch b/queue-5.15/f2fs-compress-fix-to-avoid-redundant-compress-extens.patch new file mode 100644 index 00000000000..68633c9da1e --- /dev/null +++ b/queue-5.15/f2fs-compress-fix-to-avoid-redundant-compress-extens.patch @@ -0,0 +1,89 @@ +From 809b2204b7fe3fa4a5a481f30f7e10fad9e2a574 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 28 Aug 2023 22:04:17 +0800 +Subject: f2fs: compress: fix to avoid redundant compress extension + +From: Chao Yu + +[ 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 +Signed-off-by: Jaegeuk Kim +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-5.15/f2fs-compress-fix-to-avoid-use-after-free-on-dic.patch b/queue-5.15/f2fs-compress-fix-to-avoid-use-after-free-on-dic.patch new file mode 100644 index 00000000000..2619ab72cd7 --- /dev/null +++ b/queue-5.15/f2fs-compress-fix-to-avoid-use-after-free-on-dic.patch @@ -0,0 +1,57 @@ +From 4b3f3e8a75fee21870255ec82c982863079b7e15 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 28 Aug 2023 22:04:15 +0800 +Subject: f2fs: compress: fix to avoid use-after-free on dic + +From: Chao Yu + +[ 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 +Signed-off-by: Jaegeuk Kim +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-5.15/f2fs-fix-to-initialize-map.m_pblk-in-f2fs_precache_e.patch b/queue-5.15/f2fs-fix-to-initialize-map.m_pblk-in-f2fs_precache_e.patch new file mode 100644 index 00000000000..80bdfcc0052 --- /dev/null +++ b/queue-5.15/f2fs-fix-to-initialize-map.m_pblk-in-f2fs_precache_e.patch @@ -0,0 +1,37 @@ +From 1ddef868efdb207edd5d4711d9ce2e07461e0bbc Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 7 Oct 2023 15:45:52 +0800 +Subject: f2fs: fix to initialize map.m_pblk in f2fs_precache_extents() + +From: Chao Yu + +[ 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 +Signed-off-by: Jaegeuk Kim +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-5.15/f2fs-handle-decompress-only-post-processing-in-softi.patch b/queue-5.15/f2fs-handle-decompress-only-post-processing-in-softi.patch new file mode 100644 index 00000000000..39cddcd1e5b --- /dev/null +++ b/queue-5.15/f2fs-handle-decompress-only-post-processing-in-softi.patch @@ -0,0 +1,582 @@ +From 219e7b6fea8ca67b3a430cdbb5b53a2e98a5bad7 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 2 Aug 2022 12:24:37 -0700 +Subject: f2fs: handle decompress only post processing in softirq + +From: Daeho Jeong + +[ 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 +Reviewed-by: Chao Yu +Signed-off-by: Jaegeuk Kim +Stable-dep-of: b0327c84e91a ("f2fs: compress: fix to avoid use-after-free on dic") +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-5.15/f2fs-introduce-memory-mode.patch b/queue-5.15/f2fs-introduce-memory-mode.patch new file mode 100644 index 00000000000..297b88c7ae8 --- /dev/null +++ b/queue-5.15/f2fs-introduce-memory-mode.patch @@ -0,0 +1,146 @@ +From c9b88216941edab0e607dea249f4d4d0df4776c3 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 20 Jun 2022 10:38:42 -0700 +Subject: f2fs: introduce memory mode + +From: Daeho Jeong + +[ 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 +Reviewed-by: Chao Yu +Signed-off-by: Jaegeuk Kim +Stable-dep-of: b0327c84e91a ("f2fs: compress: fix to avoid use-after-free on dic") +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-5.15/firmware-arm_ffa-assign-the-missing-idr-allocation-i.patch b/queue-5.15/firmware-arm_ffa-assign-the-missing-idr-allocation-i.patch new file mode 100644 index 00000000000..e9ee8d08d5a --- /dev/null +++ b/queue-5.15/firmware-arm_ffa-assign-the-missing-idr-allocation-i.patch @@ -0,0 +1,70 @@ +From b9b6b78ff78fa1b883a3dda105c6ee1e6649b7a7 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +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 + +[ 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 +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-5.15/firmware-ti_sci-mark-driver-as-non-removable.patch b/queue-5.15/firmware-ti_sci-mark-driver-as-non-removable.patch new file mode 100644 index 00000000000..79fafdc0622 --- /dev/null +++ b/queue-5.15/firmware-ti_sci-mark-driver-as-non-removable.patch @@ -0,0 +1,113 @@ +From ca7ed6d47f7a09b28aa7b5cd0d0d4ab41c04591f Mon Sep 17 00:00:00 2001 +From: Sasha Levin +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 + +[ 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 +Closes: https://lore.kernel.org/linux-arm-kernel/20230216083908.mvmydic5lpi3ogo7@pengutronix.de/ +Suggested-by: Uwe Kleine-König +Acked-by: Uwe Kleine-König +Signed-off-by: Dhruva Gole +Link: https://lore.kernel.org/r/20230921091025.133130-1-d-gole@ti.com +Signed-off-by: Nishanth Menon +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-5.15/futex-don-t-include-process-mm-in-futex-key-on-no-mm.patch b/queue-5.15/futex-don-t-include-process-mm-in-futex-key-on-no-mm.patch new file mode 100644 index 00000000000..16231363569 --- /dev/null +++ b/queue-5.15/futex-don-t-include-process-mm-in-futex-key-on-no-mm.patch @@ -0,0 +1,62 @@ +From 4301f30ac42a567a4911a36ab8318851b5868d00 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +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 + +[ 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 +Signed-off-by: Ingo Molnar +Acked-by: Peter Zijlstra +Cc: Thomas Gleixner +Cc: Darren Hart +Cc: Davidlohr Bueso +Cc: André Almeida +Link: https://lore.kernel.org/r/20231019204548.1236437-2-ben.wolsieffer@hefring.com +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-5.15/genirq-matrix-exclude-managed-interrupts-in-irq_matr.patch b/queue-5.15/genirq-matrix-exclude-managed-interrupts-in-irq_matr.patch new file mode 100644 index 00000000000..6d0ab57672c --- /dev/null +++ b/queue-5.15/genirq-matrix-exclude-managed-interrupts-in-irq_matr.patch @@ -0,0 +1,73 @@ +From 6c60c61136951810bd21dc1124499ead1d83f2e5 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 20 Oct 2023 15:25:22 +0800 +Subject: genirq/matrix: Exclude managed interrupts in irq_matrix_allocated() + +From: Chen Yu + +[ 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 +Signed-off-by: Chen Yu +Signed-off-by: Thomas Gleixner +Link: https://lore.kernel.org/r/20231020072522.557846-1-yu.c.chen@intel.com +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-5.15/gpio-add-helpers-to-ease-the-transition-towards-immu.patch b/queue-5.15/gpio-add-helpers-to-ease-the-transition-towards-immu.patch new file mode 100644 index 00000000000..8e2045f02c6 --- /dev/null +++ b/queue-5.15/gpio-add-helpers-to-ease-the-transition-towards-immu.patch @@ -0,0 +1,54 @@ +From 0043afef0d43ad2bc0e3da4bc8d4b7abc4f87a19 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 19 Apr 2022 15:18:39 +0100 +Subject: gpio: Add helpers to ease the transition towards immutable irq_chip + +From: Marc Zyngier + +[ 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 +Reviewed-by: Bartosz Golaszewski +Signed-off-by: Marc Zyngier +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 +--- + 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 + diff --git a/queue-5.15/gpio-don-t-fiddle-with-irqchips-marked-as-immutable.patch b/queue-5.15/gpio-don-t-fiddle-with-irqchips-marked-as-immutable.patch new file mode 100644 index 00000000000..5f254b43fd3 --- /dev/null +++ b/queue-5.15/gpio-don-t-fiddle-with-irqchips-marked-as-immutable.patch @@ -0,0 +1,89 @@ +From 67223eb1b98579c9464871d1938a5924fe06e220 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 19 Apr 2022 15:18:37 +0100 +Subject: gpio: Don't fiddle with irqchips marked as immutable + +From: Marc Zyngier + +[ 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 +Reviewed-by: Bartosz Golaszewski +Signed-off-by: Marc Zyngier +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 +--- + 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 +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 + diff --git a/queue-5.15/gpio-expose-the-gpiochip_irq_re-ql-res-helpers.patch b/queue-5.15/gpio-expose-the-gpiochip_irq_re-ql-res-helpers.patch new file mode 100644 index 00000000000..2e10a543996 --- /dev/null +++ b/queue-5.15/gpio-expose-the-gpiochip_irq_re-ql-res-helpers.patch @@ -0,0 +1,70 @@ +From bf522c0ca975b2c9887f891c4124f72f6e7c7b27 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 19 Apr 2022 15:18:38 +0100 +Subject: gpio: Expose the gpiochip_irq_re[ql]res helpers + +From: Marc Zyngier + +[ 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 +Reviewed-by: Bartosz Golaszewski +Signed-off-by: Marc Zyngier +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 +--- + 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 + diff --git a/queue-5.15/gve-use-size_add-in-call-to-struct_size.patch b/queue-5.15/gve-use-size_add-in-call-to-struct_size.patch new file mode 100644 index 00000000000..fc28d2b15d8 --- /dev/null +++ b/queue-5.15/gve-use-size_add-in-call-to-struct_size.patch @@ -0,0 +1,38 @@ +From 0471a02340208d9d614db6fadd193daadaa4b742 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 15 Sep 2023 12:17:49 -0600 +Subject: gve: Use size_add() in call to struct_size() + +From: Gustavo A. R. Silva + +[ 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 +Reviewed-by: Kees Cook +Signed-off-by: David S. Miller +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-5.15/hid-cp2112-fix-duplicate-workqueue-initialization.patch b/queue-5.15/hid-cp2112-fix-duplicate-workqueue-initialization.patch new file mode 100644 index 00000000000..c9ecd6ed275 --- /dev/null +++ b/queue-5.15/hid-cp2112-fix-duplicate-workqueue-initialization.patch @@ -0,0 +1,50 @@ +From de9f97b2e2f67cccc8e942bfc7652a4206f8a2fd Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 19 Sep 2023 16:22:45 -0500 +Subject: hid: cp2112: Fix duplicate workqueue initialization + +From: Danny Kaehn + +[ 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 +Signed-off-by: Jiri Kosina +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-5.15/hid-cp2112-fix-irq-shutdown-stopping-polling-for-all.patch b/queue-5.15/hid-cp2112-fix-irq-shutdown-stopping-polling-for-all.patch new file mode 100644 index 00000000000..bb3b1405e80 --- /dev/null +++ b/queue-5.15/hid-cp2112-fix-irq-shutdown-stopping-polling-for-all.patch @@ -0,0 +1,48 @@ +From 71e783cfea753e5f37131882afbd29500d1d365e Mon Sep 17 00:00:00 2001 +From: Sasha Levin +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 + +[ 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 +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 +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-5.15/hid-cp2112-make-irq_chip-immutable.patch b/queue-5.15/hid-cp2112-make-irq_chip-immutable.patch new file mode 100644 index 00000000000..8da7c538bd9 --- /dev/null +++ b/queue-5.15/hid-cp2112-make-irq_chip-immutable.patch @@ -0,0 +1,109 @@ +From 197afd0c04462b3f50de1aa00415135c7dc26f77 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 3 Jul 2023 21:52:13 +0300 +Subject: HID: cp2112: Make irq_chip immutable + +From: Andy Shevchenko + +[ 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 +Link: https://lore.kernel.org/r/20230703185222.50554-4-andriy.shevchenko@linux.intel.com +Signed-off-by: Benjamin Tissoires +Stable-dep-of: dc3115e6c5d9 ("hid: cp2112: Fix IRQ shutdown stopping polling for all IRQs on chip") +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-5.15/hid-logitech-hidpp-don-t-restart-io-instead-defer-hi.patch b/queue-5.15/hid-logitech-hidpp-don-t-restart-io-instead-defer-hi.patch new file mode 100644 index 00000000000..a37720030e6 --- /dev/null +++ b/queue-5.15/hid-logitech-hidpp-don-t-restart-io-instead-defer-hi.patch @@ -0,0 +1,119 @@ +From e320737df23de27f8e34d4a963b88d45934b31b3 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +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 + +[ 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 +Signed-off-by: Hans de Goede +Link: https://lore.kernel.org/r/20231010102029.111003-2-hdegoede@redhat.com +Signed-off-by: Benjamin Tissoires +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-5.15/hid-logitech-hidpp-move-get_wireless_feature_index-c.patch b/queue-5.15/hid-logitech-hidpp-move-get_wireless_feature_index-c.patch new file mode 100644 index 00000000000..6c9a774a34e --- /dev/null +++ b/queue-5.15/hid-logitech-hidpp-move-get_wireless_feature_index-c.patch @@ -0,0 +1,98 @@ +From 10eaf8f72122eafdf4d0f32b633c7a2a002128ed Mon Sep 17 00:00:00 2001 +From: Sasha Levin +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 + +[ 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 +Link: https://lore.kernel.org/r/20231010102029.111003-4-hdegoede@redhat.com +Signed-off-by: Benjamin Tissoires +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-5.15/hid-logitech-hidpp-remove-hidpp_quirk_no_hidinput-qu.patch b/queue-5.15/hid-logitech-hidpp-remove-hidpp_quirk_no_hidinput-qu.patch new file mode 100644 index 00000000000..1d266b248bc --- /dev/null +++ b/queue-5.15/hid-logitech-hidpp-remove-hidpp_quirk_no_hidinput-qu.patch @@ -0,0 +1,69 @@ +From cd57c30374e05dd788412acea0c6e92ccc9aeb65 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 25 Jan 2023 13:17:23 +0100 +Subject: HID: logitech-hidpp: Remove HIDPP_QUIRK_NO_HIDINPUT quirk + +From: Bastien Nocera + +[ 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 +Link: https://lore.kernel.org/r/20230125121723.3122-2-hadess@hadess.net +Signed-off-by: Benjamin Tissoires +Stable-dep-of: 11ca0322a419 ("HID: logitech-hidpp: Don't restart IO, instead defer hid_connect() only") +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-5.15/hid-logitech-hidpp-revert-don-t-restart-communicatio.patch b/queue-5.15/hid-logitech-hidpp-revert-don-t-restart-communicatio.patch new file mode 100644 index 00000000000..fa129757b9a --- /dev/null +++ b/queue-5.15/hid-logitech-hidpp-revert-don-t-restart-communicatio.patch @@ -0,0 +1,129 @@ +From 9c18aadf637a853cf129e072614cb02ec81764b7 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +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 + +[ 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 +Link: https://lore.kernel.org/r/20231010102029.111003-3-hdegoede@redhat.com +Signed-off-by: Benjamin Tissoires +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-5.15/hwmon-axi-fan-control-fix-possible-null-pointer-dere.patch b/queue-5.15/hwmon-axi-fan-control-fix-possible-null-pointer-dere.patch new file mode 100644 index 00000000000..314383b4eb2 --- /dev/null +++ b/queue-5.15/hwmon-axi-fan-control-fix-possible-null-pointer-dere.patch @@ -0,0 +1,74 @@ +From 2df8169ee4c9d11efdb3b3b4c4a85afb921775a1 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 25 Oct 2023 15:21:00 +0200 +Subject: hwmon: (axi-fan-control) Fix possible NULL pointer dereference + +From: Dragos Bogdan + +[ 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 +Signed-off-by: Nuno Sa +Link: https://lore.kernel.org/r/20231025132100.649499-1-nuno.sa@analog.com +Signed-off-by: Guenter Roeck +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-5.15/hwmon-coretemp-fix-potentially-truncated-sysfs-attri.patch b/queue-5.15/hwmon-coretemp-fix-potentially-truncated-sysfs-attri.patch new file mode 100644 index 00000000000..f72ecec7ed5 --- /dev/null +++ b/queue-5.15/hwmon-coretemp-fix-potentially-truncated-sysfs-attri.patch @@ -0,0 +1,59 @@ +From 5a7a3bc9892d481822a86b391bf8e981fec489a2 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 25 Oct 2023 20:23:16 +0800 +Subject: hwmon: (coretemp) Fix potentially truncated sysfs attribute name + +From: Zhang Rui + +[ 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 +Fixes: 7108b80a542b ("hwmon/coretemp: Handle large core ID value") +Reported-by: kernel test robot +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 +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-5.15/hwrng-geode-fix-accessing-registers.patch b/queue-5.15/hwrng-geode-fix-accessing-registers.patch new file mode 100644 index 00000000000..598db89a0bb --- /dev/null +++ b/queue-5.15/hwrng-geode-fix-accessing-registers.patch @@ -0,0 +1,58 @@ +From 72cd0a15f2c92c0c6afe1967f85fcb9f935caf8f Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 10 Sep 2023 10:34:17 +0200 +Subject: hwrng: geode - fix accessing registers + +From: Jonas Gorski + +[ 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 +Closes: https://bugzilla.kernel.org/show_bug.cgi?id=217882 +Tested-by: Timur I. Davletshin +Suggested-by: Jo-Philipp Wich +Signed-off-by: Jonas Gorski +Signed-off-by: Herbert Xu +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-5.15/i3c-fix-potential-refcount-leak-in-i3c_master_regist.patch b/queue-5.15/i3c-fix-potential-refcount-leak-in-i3c_master_regist.patch new file mode 100644 index 00000000000..483f6438848 --- /dev/null +++ b/queue-5.15/i3c-fix-potential-refcount-leak-in-i3c_master_regist.patch @@ -0,0 +1,41 @@ +From e9563cdcebb4f51aedeebcc83f88dcb5269f72c0 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +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 + +[ 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 +Link: https://lore.kernel.org/r/20230921082410.25548-1-dinghao.liu@zju.edu.cn +Signed-off-by: Alexandre Belloni +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-5.15/i40e-fix-potential-memory-leaks-in-i40e_remove.patch b/queue-5.15/i40e-fix-potential-memory-leaks-in-i40e_remove.patch new file mode 100644 index 00000000000..9dfe7e7b422 --- /dev/null +++ b/queue-5.15/i40e-fix-potential-memory-leaks-in-i40e_remove.patch @@ -0,0 +1,50 @@ +From 9ccc3bc6ed5f19fc4710e77aef42458aa86e3444 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 8 Sep 2023 14:42:01 +0200 +Subject: i40e: fix potential memory leaks in i40e_remove() + +From: Andrii Staikov + +[ 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 +Signed-off-by: Aleksandr Loktionov +Reviewed-by: Simon Horman +Signed-off-by: Tony Nguyen +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-5.15/ib-mlx5-fix-rdma-counter-binding-for-raw-qp.patch b/queue-5.15/ib-mlx5-fix-rdma-counter-binding-for-raw-qp.patch new file mode 100644 index 00000000000..b0e3fcb0b79 --- /dev/null +++ b/queue-5.15/ib-mlx5-fix-rdma-counter-binding-for-raw-qp.patch @@ -0,0 +1,76 @@ +From 8123f0dfb81bf6bfa34216ef662a4f938ea8cb27 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 9 Oct 2023 13:41:20 +0300 +Subject: IB/mlx5: Fix rdma counter binding for RAW QP + +From: Patrisious Haddad + +[ 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 +Reviewed-by: Mark Zhang +Link: https://lore.kernel.org/r/2e5ab6713784a8fe997d19c508187a0dfecf2dfc.1696847964.git.leon@kernel.org +Signed-off-by: Leon Romanovsky +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-5.15/iov_iter-x86-be-consistent-about-the-__user-tag-on-c.patch b/queue-5.15/iov_iter-x86-be-consistent-about-the-__user-tag-on-c.patch new file mode 100644 index 00000000000..5b929345d0f --- /dev/null +++ b/queue-5.15/iov_iter-x86-be-consistent-about-the-__user-tag-on-c.patch @@ -0,0 +1,90 @@ +From e92523621671328b093c0835e5693a6f920c3f77 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +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 + +[ 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 +Link: https://lore.kernel.org/r/20230925120309.1731676-3-dhowells@redhat.com +cc: Dan Williams +cc: Thomas Gleixner +cc: Ingo Molnar +cc: Borislav Petkov +cc: Dave Hansen +cc: "H. Peter Anvin" +cc: Alexander Viro +cc: Jens Axboe +cc: Christoph Hellwig +cc: Christian Brauner +cc: Matthew Wilcox +cc: Linus Torvalds +cc: David Laight +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 +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-5.15/ipv6-avoid-atomic-fragment-on-gso-packets.patch b/queue-5.15/ipv6-avoid-atomic-fragment-on-gso-packets.patch new file mode 100644 index 00000000000..7a11937568c --- /dev/null +++ b/queue-5.15/ipv6-avoid-atomic-fragment-on-gso-packets.patch @@ -0,0 +1,54 @@ +From b1b2a0fb684cbeeca74f27767135240a722cccba Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 24 Oct 2023 07:26:40 -0700 +Subject: ipv6: avoid atomic fragment on GSO packets + +From: Yan Zhai + +[ 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 +Signed-off-by: Yan Zhai +Link: https://lore.kernel.org/r/90912e3503a242dca0bc36958b11ed03a2696e5e.1698156966.git.yan@cloudflare.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-5.15/ipvlan-properly-track-tx_errors.patch b/queue-5.15/ipvlan-properly-track-tx_errors.patch new file mode 100644 index 00000000000..8d7503e4d67 --- /dev/null +++ b/queue-5.15/ipvlan-properly-track-tx_errors.patch @@ -0,0 +1,81 @@ +From a9eb562c8273dd550a00f55bca46a57141fab486 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 26 Oct 2023 13:14:46 +0000 +Subject: ipvlan: properly track tx_errors + +From: Eric Dumazet + +[ 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 +Cc: Mahesh Bandewar +Link: https://lore.kernel.org/r/20231026131446.3933175-1-edumazet@google.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-5.15/iwlwifi-pcie-adjust-to-bz-completion-descriptor.patch b/queue-5.15/iwlwifi-pcie-adjust-to-bz-completion-descriptor.patch new file mode 100644 index 00000000000..2588a4b405c --- /dev/null +++ b/queue-5.15/iwlwifi-pcie-adjust-to-bz-completion-descriptor.patch @@ -0,0 +1,193 @@ +From f93cdbebdd96bfbffd89a9a8437af95f66acc337 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 4 Feb 2022 12:25:04 +0200 +Subject: iwlwifi: pcie: adjust to Bz completion descriptor + +From: Johannes Berg + +[ 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 +Signed-off-by: Luca Coelho +Link: https://lore.kernel.org/r/iwlwifi.20220204122220.bef461a04110.I90c8885550fa54eb0aaa4363d322f50e301175a6@changeid +Signed-off-by: Luca Coelho +Stable-dep-of: 37fb29bd1f90 ("wifi: iwlwifi: pcie: synchronize IRQs before NAPI") +Signed-off-by: Sasha Levin +--- + .../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 + diff --git a/queue-5.15/iwlwifi-remove-contact-information.patch b/queue-5.15/iwlwifi-remove-contact-information.patch new file mode 100644 index 00000000000..58fa33d4ee3 --- /dev/null +++ b/queue-5.15/iwlwifi-remove-contact-information.patch @@ -0,0 +1,613 @@ +From 03f60855381d9fc05d24e477a589cfa386d00da9 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 17 Oct 2021 11:43:48 +0300 +Subject: iwlwifi: remove contact information + +From: Johannes Berg + +[ 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 +Signed-off-by: Luca Coelho +Link: https://lore.kernel.org/r/iwlwifi.20211017113927.f73e3b6384cb.I967fd394995461277eafa149bb25cefd1673751e@changeid +Signed-off-by: Luca Coelho +Stable-dep-of: 658939fc68d3 ("wifi: iwlwifi: empty overflow queue during flush") +Signed-off-by: Sasha Levin +--- + 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 +- * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 +- * + *****************************************************************************/ + + #include +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 +- * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 +- * + *****************************************************************************/ + + #include +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 +- * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 +- * + *****************************************************************************/ + + #include +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 +- * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 +- * + *****************************************************************************/ + + #include +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 +- * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 + *****************************************************************************/ + + #include +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 +- * 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 +- * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 +- * + *****************************************************************************/ + + #include +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 +- * 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 +- * 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 +- * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 +- * + *****************************************************************************/ + #include + #include +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 +- * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 +- * + *****************************************************************************/ + #include + #include +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 +- * 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 +- * 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 +- * 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 +- * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 +- * + *****************************************************************************/ + #include + #include +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 +- * 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 +- * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 +- * + *****************************************************************************/ + + #include +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 +- * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 +- * + *****************************************************************************/ + + #include +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 +- * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 + *****************************************************************************/ + #include + #include +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 +- * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 +- * + *****************************************************************************/ + #include + #include +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 +- * 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 +- * 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 +- * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 +- * + *****************************************************************************/ + + #include +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 +- * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 +- * + *****************************************************************************/ + + #include +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 +- * 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 +- * 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 +- * 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 +- * 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 +- * 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 +- * 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 +- * 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 +- * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 +- * + *****************************************************************************/ + + #include +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 +- * 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 +- * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 +- * + *****************************************************************************/ + #include + #include +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 +- * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 +- * + *****************************************************************************/ + + #ifndef __rs_h__ +-- +2.42.0 + diff --git a/queue-5.15/leds-pwm-don-t-disable-the-pwm-when-the-led-should-b.patch b/queue-5.15/leds-pwm-don-t-disable-the-pwm-when-the-led-should-b.patch new file mode 100644 index 00000000000..c9e6555c36d --- /dev/null +++ b/queue-5.15/leds-pwm-don-t-disable-the-pwm-when-the-led-should-b.patch @@ -0,0 +1,53 @@ +From 5b33040c9dd2e8f375c80bc63cde7c7141a6957c Mon Sep 17 00:00:00 2001 +From: Sasha Levin +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 + +[ 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 +Reported-by: Fabio Estevam +Signed-off-by: Uwe Kleine-König +Reviewed-by: Fabio Estevam +Link: https://lore.kernel.org/r/20230922192834.1695727-1-u.kleine-koenig@pengutronix.de +Signed-off-by: Lee Jones +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-5.15/leds-trigger-ledtrig-cpu-fix-output-may-be-truncated.patch b/queue-5.15/leds-trigger-ledtrig-cpu-fix-output-may-be-truncated.patch new file mode 100644 index 00000000000..64d1430d59d --- /dev/null +++ b/queue-5.15/leds-trigger-ledtrig-cpu-fix-output-may-be-truncated.patch @@ -0,0 +1,63 @@ +From cd739f47f7fac08a46e75d1aab0cd73eb18763b1 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +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 + +[ 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 +Link: https://lore.kernel.org/r/3f4be7a99933cf8566e630da54f6ab913caac432.1695453322.git.christophe.jaillet@wanadoo.fr +Signed-off-by: Lee Jones +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-5.15/leds-turris-omnia-do-not-use-smbus-calls.patch b/queue-5.15/leds-turris-omnia-do-not-use-smbus-calls.patch new file mode 100644 index 00000000000..b39a488f549 --- /dev/null +++ b/queue-5.15/leds-turris-omnia-do-not-use-smbus-calls.patch @@ -0,0 +1,155 @@ +From 6782733af78201d9e6cd0fd38d22a6037748f07e Mon Sep 17 00:00:00 2001 +From: Sasha Levin +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 + +[ 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 +Link: https://lore.kernel.org/r/20230918161104.20860-2-kabel@kernel.org +Signed-off-by: Lee Jones +Signed-off-by: Sasha Levin +--- + 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 ++ * 2020, 2023 by Marek Behún + */ + + #include +@@ -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 + diff --git a/queue-5.15/leds-turris-omnia-drop-unnecessary-mutex-locking.patch b/queue-5.15/leds-turris-omnia-drop-unnecessary-mutex-locking.patch new file mode 100644 index 00000000000..78a8141d7b4 --- /dev/null +++ b/queue-5.15/leds-turris-omnia-drop-unnecessary-mutex-locking.patch @@ -0,0 +1,75 @@ +From 30bb182d004bb1cd904b708d1ac76eea8a4463c2 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +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 + +[ 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 +Reviewed-by: Lee Jones +Link: https://lore.kernel.org/r/20230802160748.11208-2-kabel@kernel.org +Signed-off-by: Lee Jones +Stable-dep-of: 6de283b96b31 ("leds: turris-omnia: Do not use SMBUS calls") +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-5.15/libnvdimm-of_pmem-use-devm_kstrdup-instead-of-kstrdu.patch b/queue-5.15/libnvdimm-of_pmem-use-devm_kstrdup-instead-of-kstrdu.patch new file mode 100644 index 00000000000..1d20e194a3d --- /dev/null +++ b/queue-5.15/libnvdimm-of_pmem-use-devm_kstrdup-instead-of-kstrdu.patch @@ -0,0 +1,45 @@ +From 0c207427730935626e4b9b576d692b1596208030 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +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 + +[ 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 +Reviewed-by: Ira Weiny +Reviewed-by: Dave Jiang +Signed-off-by: Ira Weiny +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-5.15/livepatch-fix-missing-newline-character-in-klp_resol.patch b/queue-5.15/livepatch-fix-missing-newline-character-in-klp_resol.patch new file mode 100644 index 00000000000..a206f136ddb --- /dev/null +++ b/queue-5.15/livepatch-fix-missing-newline-character-in-klp_resol.patch @@ -0,0 +1,38 @@ +From b2eb747a35f3a70092ea2b14feaca991b6e9e631 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 14 Sep 2023 15:26:44 +0800 +Subject: livepatch: Fix missing newline character in klp_resolve_symbols() + +From: Zheng Yejian + +[ 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 +Reviewed-by: Petr Mladek +Signed-off-by: Petr Mladek +Link: https://lore.kernel.org/r/20230914072644.4098857-1-zhengyejian1@huawei.com +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-5.15/media-bttv-fix-use-after-free-error-due-to-btv-timeo.patch b/queue-5.15/media-bttv-fix-use-after-free-error-due-to-btv-timeo.patch new file mode 100644 index 00000000000..bd07c0fe0bb --- /dev/null +++ b/queue-5.15/media-bttv-fix-use-after-free-error-due-to-btv-timeo.patch @@ -0,0 +1,52 @@ +From dd2954050ae6d0c26c2eae1ab5fb30b2e678c543 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +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 + +[ 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 +Signed-off-by: Hans Verkuil +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-5.15/media-cadence-csi2rx-unregister-v4l2-async-notifier.patch b/queue-5.15/media-cadence-csi2rx-unregister-v4l2-async-notifier.patch new file mode 100644 index 00000000000..58b348cda82 --- /dev/null +++ b/queue-5.15/media-cadence-csi2rx-unregister-v4l2-async-notifier.patch @@ -0,0 +1,67 @@ +From 3ac4667d6c72e2927cb3a9ed1b9a963481b47e76 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 9 Oct 2023 18:39:29 +0530 +Subject: media: cadence: csi2rx: Unregister v4l2 async notifier + +From: Pratyush Yadav + +[ 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 +Tested-by: Julien Massot +Reviewed-by: Laurent Pinchart +Reviewed-by: Tomi Valkeinen +Reviewed-by: Maxime Ripard +Signed-off-by: Jai Luthra +Signed-off-by: Sakari Ailus +Signed-off-by: Hans Verkuil +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-5.15/media-cedrus-fix-clock-reset-sequence.patch b/queue-5.15/media-cedrus-fix-clock-reset-sequence.patch new file mode 100644 index 00000000000..c2af941cc9f --- /dev/null +++ b/queue-5.15/media-cedrus-fix-clock-reset-sequence.patch @@ -0,0 +1,87 @@ +From e90bf6d3fed2e9da1cac2e745647e0db1c9ce2b0 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 11 Sep 2023 20:46:12 +0200 +Subject: media: cedrus: Fix clock/reset sequence + +From: Jernej Skrabec + +[ 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 +Acked-by: Paul Kocialkowski +Signed-off-by: Hans Verkuil +Signed-off-by: Sasha Levin +--- + .../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 + diff --git a/queue-5.15/media-dvb-usb-v2-af9035-fix-missing-unlock.patch b/queue-5.15/media-dvb-usb-v2-af9035-fix-missing-unlock.patch new file mode 100644 index 00000000000..5fa70999f03 --- /dev/null +++ b/queue-5.15/media-dvb-usb-v2-af9035-fix-missing-unlock.patch @@ -0,0 +1,67 @@ +From ee7502625d7ea83a5c24cf2ce73e95920438f523 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 6 Oct 2023 12:08:45 +0200 +Subject: media: dvb-usb-v2: af9035: fix missing unlock + +From: Hans Verkuil + +[ 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 +Fixes: 7bf744f2de0a ("media: dvb-usb-v2: af9035: Fix null-ptr-deref in af9035_i2c_master_xfer") +Signed-off-by: Hans Verkuil +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-5.15/media-i2c-max9286-fix-some-redundant-of_node_put-cal.patch b/queue-5.15/media-i2c-max9286-fix-some-redundant-of_node_put-cal.patch new file mode 100644 index 00000000000..665b244706b --- /dev/null +++ b/queue-5.15/media-i2c-max9286-fix-some-redundant-of_node_put-cal.patch @@ -0,0 +1,50 @@ +From deea8c3040538bca1beb03eb5437b57920548192 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 26 Aug 2023 00:13:40 +0200 +Subject: media: i2c: max9286: Fix some redundant of_node_put() calls + +From: Christophe JAILLET + +[ 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 +Reviewed-by: Jacopo Mondi +Reviewed-by: Laurent Pinchart +Reviewed-by: Kieran Bingham +Signed-off-by: Sakari Ailus +Signed-off-by: Hans Verkuil +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-5.15/media-rcar-vin-improve-async-notifier-cleanup-paths.patch b/queue-5.15/media-rcar-vin-improve-async-notifier-cleanup-paths.patch new file mode 100644 index 00000000000..3d4b971422e --- /dev/null +++ b/queue-5.15/media-rcar-vin-improve-async-notifier-cleanup-paths.patch @@ -0,0 +1,130 @@ +From cd2471ec6c14b24a75e2abe01c1a9bb97e8d7f3d Mon Sep 17 00:00:00 2001 +From: Sasha Levin +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 + +[ 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 +Reviewed-by: Jacopo Mondi +Signed-off-by: Sakari Ailus +Signed-off-by: Mauro Carvalho Chehab +Stable-dep-of: b2701715301a ("media: cadence: csi2rx: Unregister v4l2 async notifier") +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-5.15/media-rcar-vin-move-group-async-notifier.patch b/queue-5.15/media-rcar-vin-move-group-async-notifier.patch new file mode 100644 index 00000000000..fd31ed8e364 --- /dev/null +++ b/queue-5.15/media-rcar-vin-move-group-async-notifier.patch @@ -0,0 +1,520 @@ +From 51d1516951f0775a766867ae7a06e55ebd0eed68 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +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 + +[ 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 +Reviewed-by: Jacopo Mondi +Signed-off-by: Sakari Ailus +Signed-off-by: Mauro Carvalho Chehab +Stable-dep-of: b2701715301a ("media: cadence: csi2rx: Unregister v4l2 async notifier") +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-5.15/media-rcar-vin-refactor-controls-creation-for-video-.patch b/queue-5.15/media-rcar-vin-refactor-controls-creation-for-video-.patch new file mode 100644 index 00000000000..82b5d3ab9ac --- /dev/null +++ b/queue-5.15/media-rcar-vin-refactor-controls-creation-for-video-.patch @@ -0,0 +1,164 @@ +From 74d2f9b2f92e12a66216f4cad650e2731d3d8540 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +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 + +[ 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 +Reviewed-by: Jacopo Mondi +Signed-off-by: Sakari Ailus +Signed-off-by: Mauro Carvalho Chehab +Stable-dep-of: b2701715301a ("media: cadence: csi2rx: Unregister v4l2 async notifier") +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-5.15/media-rcar-vin-rename-array-storing-subdevice-inform.patch b/queue-5.15/media-rcar-vin-rename-array-storing-subdevice-inform.patch new file mode 100644 index 00000000000..93f709275e5 --- /dev/null +++ b/queue-5.15/media-rcar-vin-rename-array-storing-subdevice-inform.patch @@ -0,0 +1,165 @@ +From e97f8defd2cb0817e26dcab2e9e5ae1b8c2abd3a Mon Sep 17 00:00:00 2001 +From: Sasha Levin +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 + +[ 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 +Reviewed-by: Jacopo Mondi +Signed-off-by: Sakari Ailus +Signed-off-by: Mauro Carvalho Chehab +Stable-dep-of: b2701715301a ("media: cadence: csi2rx: Unregister v4l2 async notifier") +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-5.15/media-s3c-camif-avoid-inappropriate-kfree.patch b/queue-5.15/media-s3c-camif-avoid-inappropriate-kfree.patch new file mode 100644 index 00000000000..30fa8a45796 --- /dev/null +++ b/queue-5.15/media-s3c-camif-avoid-inappropriate-kfree.patch @@ -0,0 +1,54 @@ +From 11146f33ed2d6ba7198dc674e9a438cbf03abdec Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 22 Sep 2023 14:55:06 +0300 +Subject: media: s3c-camif: Avoid inappropriate kfree() + +From: Katya Orlova + +[ 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 +Signed-off-by: Hans Verkuil +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-5.15/media-v4l-async-rename-async-nf-functions-clean-up-l.patch b/queue-5.15/media-v4l-async-rename-async-nf-functions-clean-up-l.patch new file mode 100644 index 00000000000..d1d52f89d78 --- /dev/null +++ b/queue-5.15/media-v4l-async-rename-async-nf-functions-clean-up-l.patch @@ -0,0 +1,2923 @@ +From 9da6daba0739fbf48b32eaa2695cd30c7d12b1de Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 5 Mar 2021 18:13:12 +0100 +Subject: media: v4l: async: Rename async nf functions, clean up long lines + +From: Sakari Ailus + +[ 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 +Reviewed-by: Jacopo Mondi +Reviewed-by: Rui Miguel Silva (imx7) +Signed-off-by: Mauro Carvalho Chehab +Stable-dep-of: b2701715301a ("media: cadence: csi2rx: Unregister v4l2 async notifier") +Signed-off-by: Sasha Levin +--- + .../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 + #include + +-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 + diff --git a/queue-5.15/media-vidtv-mux-add-check-and-kfree-for-kstrdup.patch b/queue-5.15/media-vidtv-mux-add-check-and-kfree-for-kstrdup.patch new file mode 100644 index 00000000000..e1e39edbdc7 --- /dev/null +++ b/queue-5.15/media-vidtv-mux-add-check-and-kfree-for-kstrdup.patch @@ -0,0 +1,56 @@ +From ac72e3bee2a0ab408d6920be85269e70b30239de Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 19 Jun 2023 16:12:02 +0800 +Subject: media: vidtv: mux: Add check and kfree for kstrdup + +From: Jiasheng Jiang + +[ 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 +Signed-off-by: Hans Verkuil +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-5.15/media-vidtv-psi-add-check-for-kstrdup.patch b/queue-5.15/media-vidtv-psi-add-check-for-kstrdup.patch new file mode 100644 index 00000000000..a42978bd00b --- /dev/null +++ b/queue-5.15/media-vidtv-psi-add-check-for-kstrdup.patch @@ -0,0 +1,111 @@ +From c87b962ba806c7ccfb1dff3fcc072ef0a9e80b10 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 19 Jun 2023 16:12:01 +0800 +Subject: media: vidtv: psi: Add check for kstrdup + +From: Jiasheng Jiang + +[ 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 +Signed-off-by: Hans Verkuil +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-5.15/mfd-arizona-spi-set-pdata.hpdet_channel-for-acpi-enu.patch b/queue-5.15/mfd-arizona-spi-set-pdata.hpdet_channel-for-acpi-enu.patch new file mode 100644 index 00000000000..2455999cd4f --- /dev/null +++ b/queue-5.15/mfd-arizona-spi-set-pdata.hpdet_channel-for-acpi-enu.patch @@ -0,0 +1,50 @@ +From 27e0903b660081f285211c9ae8bb3263d5d1d2c9 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +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 + +[ 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 +Link: https://lore.kernel.org/r/20231014205414.59415-1-hdegoede@redhat.com +Signed-off-by: Lee Jones +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-5.15/mfd-core-ensure-disabled-devices-are-skipped-without.patch b/queue-5.15/mfd-core-ensure-disabled-devices-are-skipped-without.patch new file mode 100644 index 00000000000..9e10b51f272 --- /dev/null +++ b/queue-5.15/mfd-core-ensure-disabled-devices-are-skipped-without.patch @@ -0,0 +1,77 @@ +From 30b1659c73f46697ed9a223329120b52371a0ba0 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 18 Aug 2023 18:39:17 +0200 +Subject: mfd: core: Ensure disabled devices are skipped without aborting + +From: Herve Codina + +[ 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 +Reviewed-by: Christophe Leroy +Signed-off-by: Christophe Leroy +Link: https://lore.kernel.org/r/528425d6472176bb1d02d79596b51f8c28a551cc.1692376361.git.christophe.leroy@csgroup.eu +Signed-off-by: Lee Jones +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-5.15/mfd-core-un-constify-mfd_cell.of_reg.patch b/queue-5.15/mfd-core-un-constify-mfd_cell.of_reg.patch new file mode 100644 index 00000000000..322b737cb35 --- /dev/null +++ b/queue-5.15/mfd-core-un-constify-mfd_cell.of_reg.patch @@ -0,0 +1,40 @@ +From 3823c590ee7fe24654d4847acb932eecd16d7b54 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +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 + +[ 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 +Link: https://lore.kernel.org/r/b73fe4bc4bd6ba1af90940a640ed65fe254c0408.1693253717.git.mirq-linux@rere.qmqm.pl +Signed-off-by: Lee Jones +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-5.15/mfd-dln2-fix-double-put-in-dln2_probe.patch b/queue-5.15/mfd-dln2-fix-double-put-in-dln2_probe.patch new file mode 100644 index 00000000000..f207e4ee40c --- /dev/null +++ b/queue-5.15/mfd-dln2-fix-double-put-in-dln2_probe.patch @@ -0,0 +1,37 @@ +From c148b085e07062ac10c46ccfb5b75604a2ad4a93 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 25 Sep 2023 10:41:33 +0800 +Subject: mfd: dln2: Fix double put in dln2_probe + +From: Dinghao Liu + +[ 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 +Link: https://lore.kernel.org/r/20230925024134.9683-1-dinghao.liu@zju.edu.cn +Signed-off-by: Lee Jones +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-5.15/misc-st_core-do-not-call-kfree_skb-under-spin_lock_i.patch b/queue-5.15/misc-st_core-do-not-call-kfree_skb-under-spin_lock_i.patch new file mode 100644 index 00000000000..0b064855ac9 --- /dev/null +++ b/queue-5.15/misc-st_core-do-not-call-kfree_skb-under-spin_lock_i.patch @@ -0,0 +1,65 @@ +From 84fae41037c49a5c56fd72682f397b1779fc2158 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +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 + +[ 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 +Link: https://lore.kernel.org/r/20230823035020.1281892-1-ruanjinjie@huawei.com +Signed-off-by: Greg Kroah-Hartman +Signed-off-by: Sasha Levin +--- + 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 + + #include ++#include + + 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 + diff --git a/queue-5.15/mlxsw-use-size_mul-in-call-to-struct_size.patch b/queue-5.15/mlxsw-use-size_mul-in-call-to-struct_size.patch new file mode 100644 index 00000000000..7bedb397af1 --- /dev/null +++ b/queue-5.15/mlxsw-use-size_mul-in-call-to-struct_size.patch @@ -0,0 +1,39 @@ +From 6f6564f53844662b1fcd6011e3669a2b62b1399f Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 15 Sep 2023 13:01:23 -0600 +Subject: mlxsw: Use size_mul() in call to struct_size() + +From: Gustavo A. R. Silva + +[ 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 +Reviewed-by: Kees Cook +Reviewed-by: Ido Schimmel +Signed-off-by: David S. Miller +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-5.15/modpost-fix-tee-module_device_table-built-on-big-end.patch b/queue-5.15/modpost-fix-tee-module_device_table-built-on-big-end.patch new file mode 100644 index 00000000000..cc8aab98af6 --- /dev/null +++ b/queue-5.15/modpost-fix-tee-module_device_table-built-on-big-end.patch @@ -0,0 +1,71 @@ +From f52c3bfbcbaaaa7d56960215ebc75cafdc1da9da Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 8 Oct 2023 02:04:44 +0900 +Subject: modpost: fix tee MODULE_DEVICE_TABLE built on big-endian host + +From: Masahiro Yamada + +[ 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 +Reviewed-by: Sumit Garg +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-5.15/mt76-add-support-for-overriding-the-device-used-for-.patch b/queue-5.15/mt76-add-support-for-overriding-the-device-used-for-.patch new file mode 100644 index 00000000000..3246cc96914 --- /dev/null +++ b/queue-5.15/mt76-add-support-for-overriding-the-device-used-for-.patch @@ -0,0 +1,172 @@ +From 8cca2b28f42b2fb0317d172f3a7bcd7568555193 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 6 Jan 2022 13:22:28 +0100 +Subject: mt76: add support for overriding the device used for DMA mapping + +From: Felix Fietkau + +[ 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 +Stable-dep-of: 317620593349 ("wifi: mt76: mt7603: improve stuck beacon handling") +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-5.15/mt76-dma-use-kzalloc-instead-of-devm_kzalloc-for-txw.patch b/queue-5.15/mt76-dma-use-kzalloc-instead-of-devm_kzalloc-for-txw.patch new file mode 100644 index 00000000000..3c66d46279c --- /dev/null +++ b/queue-5.15/mt76-dma-use-kzalloc-instead-of-devm_kzalloc-for-txw.patch @@ -0,0 +1,48 @@ +From 14935965b05e31f7016304cf4c0cf3f081eef7ce Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 19 Mar 2022 21:56:20 +0100 +Subject: mt76: dma: use kzalloc instead of devm_kzalloc for txwi + +From: Felix Fietkau + +[ 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 +Stable-dep-of: 317620593349 ("wifi: mt76: mt7603: improve stuck beacon handling") +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-5.15/mt76-pass-original-queue-id-from-__mt76_tx_queue_skb.patch b/queue-5.15/mt76-pass-original-queue-id-from-__mt76_tx_queue_skb.patch new file mode 100644 index 00000000000..5d487d9d8a5 --- /dev/null +++ b/queue-5.15/mt76-pass-original-queue-id-from-__mt76_tx_queue_skb.patch @@ -0,0 +1,181 @@ +From e8400b54904e13be73dc574a8a89d7ba3ef46af6 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +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 + +[ Upstream commit d08295f5be8e63e64f9e664572f1b582ede7958b ] + +MT7615 and newer map multiple software tx queues to the hardware id + +Signed-off-by: Felix Fietkau +Stable-dep-of: 317620593349 ("wifi: mt76: mt7603: improve stuck beacon handling") +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-5.15/nd_btt-make-btt-lanes-preemptible.patch b/queue-5.15/nd_btt-make-btt-lanes-preemptible.patch new file mode 100644 index 00000000000..63be755fcd5 --- /dev/null +++ b/queue-5.15/nd_btt-make-btt-lanes-preemptible.patch @@ -0,0 +1,94 @@ +From aba9f0451f31b86461de4108d4778361dcfce011 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 20 Sep 2023 07:37:12 +0200 +Subject: nd_btt: Make BTT lanes preemptible + +From: Tomas Glozar + +[ 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: +[] nd_region_acquire_lane+0x15/0x90 [libnvdimm] +Call Trace: + + 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 + ... + + +Fixes: 5212e11fde4d ("nd_btt: atomic sector updates") +Signed-off-by: Tomas Glozar +Reviewed-by: Ira Weiny +Reviewed-by: Vishal Verma +Signed-off-by: Ira Weiny +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-5.15/net-add-dev_stats_read-helper.patch b/queue-5.15/net-add-dev_stats_read-helper.patch new file mode 100644 index 00000000000..4b739137d53 --- /dev/null +++ b/queue-5.15/net-add-dev_stats_read-helper.patch @@ -0,0 +1,55 @@ +From c3efe8573fe7882a19dd660a3ee05cf9f8bf7ead Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 21 Sep 2023 08:52:16 +0000 +Subject: net: add DEV_STATS_READ() helper + +From: Eric Dumazet + +[ 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 +Signed-off-by: David S. Miller +Stable-dep-of: ff672b9ffeb3 ("ipvlan: properly track tx_errors") +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-5.15/net-spider_net-use-size_add-in-call-to-struct_size.patch b/queue-5.15/net-spider_net-use-size_add-in-call-to-struct_size.patch new file mode 100644 index 00000000000..073462638be --- /dev/null +++ b/queue-5.15/net-spider_net-use-size_add-in-call-to-struct_size.patch @@ -0,0 +1,40 @@ +From e6524459e9454e9e55647f2e238c565fa1011439 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +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 + +[ 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 +Reviewed-by: Kees Cook +Signed-off-by: Geoff Levand +Signed-off-by: David S. Miller +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-5.15/netfilter-nf_tables-drop-pointless-memset-when-dumpi.patch b/queue-5.15/netfilter-nf_tables-drop-pointless-memset-when-dumpi.patch new file mode 100644 index 00000000000..f260a640bcd --- /dev/null +++ b/queue-5.15/netfilter-nf_tables-drop-pointless-memset-when-dumpi.patch @@ -0,0 +1,38 @@ +From e3c1064486cfb437c7d1170cb69679609efa632e Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 29 Sep 2023 21:19:19 +0200 +Subject: netfilter: nf_tables: Drop pointless memset when dumping rules + +From: Phil Sutter + +[ 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 +Signed-off-by: Florian Westphal +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-5.15/padata-fix-refcnt-handling-in-padata_free_shell.patch b/queue-5.15/padata-fix-refcnt-handling-in-padata_free_shell.patch new file mode 100644 index 00000000000..bed48be3904 --- /dev/null +++ b/queue-5.15/padata-fix-refcnt-handling-in-padata_free_shell.patch @@ -0,0 +1,110 @@ +From f42a1130daa9f11fd1dd673b35f78826a13404e7 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 16 Oct 2023 09:15:21 +0800 +Subject: padata: Fix refcnt handling in padata_free_shell() + +From: WangJinchao + +[ 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 +Acked-by: Daniel Jordan +Acked-by: Daniel Jordan +Signed-off-by: Herbert Xu +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-5.15/pcmcia-cs-fix-possible-hung-task-and-memory-leak-pcc.patch b/queue-5.15/pcmcia-cs-fix-possible-hung-task-and-memory-leak-pcc.patch new file mode 100644 index 00000000000..86e059b0667 --- /dev/null +++ b/queue-5.15/pcmcia-cs-fix-possible-hung-task-and-memory-leak-pcc.patch @@ -0,0 +1,43 @@ +From bfd42c01aa52bd286c1320a5920f6bacc06220ab Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 12 Nov 2022 17:25:41 +0800 +Subject: pcmcia: cs: fix possible hung task and memory leak pccardd() + +From: Yang Yingliang + +[ 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 +Signed-off-by: Dominik Brodowski +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-5.15/pcmcia-ds-fix-possible-name-leak-in-error-path-in-pc.patch b/queue-5.15/pcmcia-ds-fix-possible-name-leak-in-error-path-in-pc.patch new file mode 100644 index 00000000000..e9cac7ebab6 --- /dev/null +++ b/queue-5.15/pcmcia-ds-fix-possible-name-leak-in-error-path-in-pc.patch @@ -0,0 +1,53 @@ +From 28725e8ddb54255485eb63173bc75e94a35b05b5 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +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 + +[ 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 +[linux@dominikbrodowski.net: simplification, commit message modified] +Signed-off-by: Dominik Brodowski +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-5.15/pcmcia-ds-fix-refcount-leak-in-pcmcia_device_add.patch b/queue-5.15/pcmcia-ds-fix-refcount-leak-in-pcmcia_device_add.patch new file mode 100644 index 00000000000..68b582cf385 --- /dev/null +++ b/queue-5.15/pcmcia-ds-fix-refcount-leak-in-pcmcia_device_add.patch @@ -0,0 +1,49 @@ +From 13d67d54d1de77a8f35da3948aaa3d9f3a57db95 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 12 Nov 2022 17:29:23 +0800 +Subject: pcmcia: ds: fix refcount leak in pcmcia_device_add() + +From: Yang Yingliang + +[ 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 +[linux@dominikbrodowski.net: simplification, commit message rewrite] +Signed-off-by: Dominik Brodowski +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-5.15/perf-evlist-add-evlist__add_dummy_on_all_cpus.patch b/queue-5.15/perf-evlist-add-evlist__add_dummy_on_all_cpus.patch new file mode 100644 index 00000000000..483906301bf --- /dev/null +++ b/queue-5.15/perf-evlist-add-evlist__add_dummy_on_all_cpus.patch @@ -0,0 +1,106 @@ +From a4455e5be294c717c5f1b67c1ef9471f3229e41f Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 24 May 2022 10:54:26 +0300 +Subject: perf evlist: Add evlist__add_dummy_on_all_cpus() + +From: Adrian Hunter + +[ 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 +Acked-by: Ian Rogers +Acked-by: Namhyung Kim +Cc: Alexey Bayduraev +Cc: Ian Rogers +Cc: Jiri Olsa +Cc: Leo Yan +Link: https://lore.kernel.org/r/20220524075436.29144-6-adrian.hunter@intel.com +Signed-off-by: Arnaldo Carvalho de Melo +Stable-dep-of: f9cdeb58a9cf ("perf evlist: Avoid frequency mode for the dummy event") +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-5.15/perf-evlist-avoid-frequency-mode-for-the-dummy-event.patch b/queue-5.15/perf-evlist-avoid-frequency-mode-for-the-dummy-event.patch new file mode 100644 index 00000000000..4c3b3c56ed4 --- /dev/null +++ b/queue-5.15/perf-evlist-avoid-frequency-mode-for-the-dummy-event.patch @@ -0,0 +1,86 @@ +From dce002fd193111afa04774420e3798b77c54e543 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 15 Sep 2023 20:56:40 -0700 +Subject: perf evlist: Avoid frequency mode for the dummy event + +From: Ian Rogers + +[ 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 +Signed-off-by: Ian Rogers +Acked-by: Adrian Hunter +Cc: Yang Jihong +Cc: Kan Liang +Link: https://lore.kernel.org/r/20230916035640.1074422-1-irogers@google.com +Signed-off-by: Namhyung Kim +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-5.15/perf-hisi-fix-use-after-free-when-register-pmu-fails.patch b/queue-5.15/perf-hisi-fix-use-after-free-when-register-pmu-fails.patch new file mode 100644 index 00000000000..012247415d1 --- /dev/null +++ b/queue-5.15/perf-hisi-fix-use-after-free-when-register-pmu-fails.patch @@ -0,0 +1,62 @@ +From 9a4221bcf19da839b0e44457b8ea21cdc9352b5a Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 24 Oct 2023 19:36:30 +0800 +Subject: perf: hisi: Fix use-after-free when register pmu fails + +From: Junhao He + +[ 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 +Link: https://lore.kernel.org/r/20231024113630.13472-1-hejunhao3@huawei.com +Signed-off-by: Will Deacon +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-5.15/perf-hist-add-missing-puts-to-hist__account_cycles.patch b/queue-5.15/perf-hist-add-missing-puts-to-hist__account_cycles.patch new file mode 100644 index 00000000000..902429be41d --- /dev/null +++ b/queue-5.15/perf-hist-add-missing-puts-to-hist__account_cycles.patch @@ -0,0 +1,81 @@ +From 97b7b4274c2ef00e21401c010ce1366d7038ef1a Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 24 Oct 2023 15:23:08 -0700 +Subject: perf hist: Add missing puts to hist__account_cycles + +From: Ian Rogers + +[ 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 +Cc: K Prateek Nayak +Cc: Ravi Bangoria +Cc: Sandipan Das +Cc: Anshuman Khandual +Cc: German Gomez +Cc: James Clark +Cc: Nick Terrell +Cc: Sean Christopherson +Cc: Changbin Du +Cc: liuwenyu +Cc: Yang Jihong +Cc: Masami Hiramatsu +Cc: Miguel Ojeda +Cc: Song Liu +Cc: Leo Yan +Cc: Kajol Jain +Cc: Andi Kleen +Cc: Kan Liang +Cc: Athira Rajeev +Cc: Yanteng Si +Cc: Liam Howlett +Cc: Paolo Bonzini +Link: https://lore.kernel.org/r/20231024222353.3024098-6-irogers@google.com +Signed-off-by: Namhyung Kim +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-5.15/perf-machine-avoid-out-of-bounds-lbr-memory-read.patch b/queue-5.15/perf-machine-avoid-out-of-bounds-lbr-memory-read.patch new file mode 100644 index 00000000000..a132c4983a9 --- /dev/null +++ b/queue-5.15/perf-machine-avoid-out-of-bounds-lbr-memory-read.patch @@ -0,0 +1,80 @@ +From 94ef4f4326d44d2915eaacff0e2d3e0f557fafa0 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 24 Oct 2023 15:23:05 -0700 +Subject: perf machine: Avoid out of bounds LBR memory read + +From: Ian Rogers + +[ 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 +Cc: K Prateek Nayak +Cc: Ravi Bangoria +Cc: Sandipan Das +Cc: Anshuman Khandual +Cc: German Gomez +Cc: James Clark +Cc: Nick Terrell +Cc: Sean Christopherson +Cc: Changbin Du +Cc: liuwenyu +Cc: Yang Jihong +Cc: Masami Hiramatsu +Cc: Miguel Ojeda +Cc: Song Liu +Cc: Leo Yan +Cc: Kajol Jain +Cc: Andi Kleen +Cc: Kan Liang +Cc: Athira Rajeev +Cc: Yanteng Si +Cc: Liam Howlett +Cc: Paolo Bonzini +Link: https://lore.kernel.org/r/20231024222353.3024098-3-irogers@google.com +Signed-off-by: Namhyung Kim +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-5.15/perf-tools-get-rid-of-evlist__add_on_all_cpus.patch b/queue-5.15/perf-tools-get-rid-of-evlist__add_on_all_cpus.patch new file mode 100644 index 00000000000..5fcda1f69f4 --- /dev/null +++ b/queue-5.15/perf-tools-get-rid-of-evlist__add_on_all_cpus.patch @@ -0,0 +1,81 @@ +From 0bad7dc2bbd481839db55a75620e7603c114eee2 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 3 Oct 2022 13:46:45 -0700 +Subject: perf tools: Get rid of evlist__add_on_all_cpus() + +From: Namhyung Kim + +[ 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 +Signed-off-by: Namhyung Kim +Cc: Ian Rogers +Cc: Ingo Molnar +Cc: Jiri Olsa +Cc: Kan Liang +Cc: Leo Yan +Cc: Peter Zijlstra +Link: https://lore.kernel.org/r/20221003204647.1481128-4-namhyung@kernel.org +Signed-off-by: Arnaldo Carvalho de Melo +Stable-dep-of: f9cdeb58a9cf ("perf evlist: Avoid frequency mode for the dummy event") +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-5.15/platform-x86-wmi-fix-opening-of-char-device.patch b/queue-5.15/platform-x86-wmi-fix-opening-of-char-device.patch new file mode 100644 index 00000000000..bd05df60888 --- /dev/null +++ b/queue-5.15/platform-x86-wmi-fix-opening-of-char-device.patch @@ -0,0 +1,69 @@ +From aff140ddac1b15e0ca9ad483da85784ef7fce10a Mon Sep 17 00:00:00 2001 +From: Sasha Levin +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 + +[ 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 +Link: https://lore.kernel.org/r/20231020211005.38216-5-W_Armin@gmx.de +Reviewed-by: Ilpo Järvinen +Signed-off-by: Ilpo Järvinen +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-5.15/platform-x86-wmi-fix-probe-failure-when-failing-to-r.patch b/queue-5.15/platform-x86-wmi-fix-probe-failure-when-failing-to-r.patch new file mode 100644 index 00000000000..0d67cda85b8 --- /dev/null +++ b/queue-5.15/platform-x86-wmi-fix-probe-failure-when-failing-to-r.patch @@ -0,0 +1,84 @@ +From 7723b028daf17e2a0ebf61dd46224bb24a3ee1ad Mon Sep 17 00:00:00 2001 +From: Sasha Levin +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 + +[ 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 +Link: https://lore.kernel.org/r/20231020211005.38216-4-W_Armin@gmx.de +Reviewed-by: Ilpo Järvinen +Signed-off-by: Ilpo Järvinen +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-5.15/platform-x86-wmi-remove-unnecessary-initializations.patch b/queue-5.15/platform-x86-wmi-remove-unnecessary-initializations.patch new file mode 100644 index 00000000000..b679bd0c962 --- /dev/null +++ b/queue-5.15/platform-x86-wmi-remove-unnecessary-initializations.patch @@ -0,0 +1,94 @@ +From c2639adbd067567b5bf3b3732092a2fa44d0a9bd Mon Sep 17 00:00:00 2001 +From: Sasha Levin +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 + +[ 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 +Link: https://lore.kernel.org/r/20210904175450.156801-6-pobrn@protonmail.com +Reviewed-by: Hans de Goede +Signed-off-by: Hans de Goede +Stable-dep-of: eba9ac7abab9 ("platform/x86: wmi: Fix opening of char device") +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-5.15/pm-devfreq-rockchip-dfi-make-pmu-regmap-mandatory.patch b/queue-5.15/pm-devfreq-rockchip-dfi-make-pmu-regmap-mandatory.patch new file mode 100644 index 00000000000..01b04b2c2aa --- /dev/null +++ b/queue-5.15/pm-devfreq-rockchip-dfi-make-pmu-regmap-mandatory.patch @@ -0,0 +1,53 @@ +From 1c9089c867fac0beefc1ab3cea9605ff8a841af8 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 4 Jul 2023 11:32:17 +0200 +Subject: PM / devfreq: rockchip-dfi: Make pmu regmap mandatory + +From: Sascha Hauer + +[ 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 +Signed-off-by: Sascha Hauer +Signed-off-by: Chanwoo Choi +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-5.15/powerpc-40x-remove-stale-pte_atomic_updates-macro.patch b/queue-5.15/powerpc-40x-remove-stale-pte_atomic_updates-macro.patch new file mode 100644 index 00000000000..edda97ab448 --- /dev/null +++ b/queue-5.15/powerpc-40x-remove-stale-pte_atomic_updates-macro.patch @@ -0,0 +1,44 @@ +From 041abb3e9fbef36ac40e41310f0e314e42877c2b Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 25 Sep 2023 20:31:17 +0200 +Subject: powerpc/40x: Remove stale PTE_ATOMIC_UPDATES macro + +From: Christophe Leroy + +[ 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 +Signed-off-by: Michael Ellerman +Link: https://msgid.link/f061db5857fcd748f84a6707aad01754686ce97e.1695659959.git.christophe.leroy@csgroup.eu +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-5.15/powerpc-imc-pmu-use-the-correct-spinlock-initializer.patch b/queue-5.15/powerpc-imc-pmu-use-the-correct-spinlock-initializer.patch new file mode 100644 index 00000000000..d5ceffeaa80 --- /dev/null +++ b/queue-5.15/powerpc-imc-pmu-use-the-correct-spinlock-initializer.patch @@ -0,0 +1,40 @@ +From 8b52563e4794fb7f023064d62286db1297877a22 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 9 Mar 2023 14:48:31 +0100 +Subject: powerpc/imc-pmu: Use the correct spinlock initializer. + +From: Sebastian Andrzej Siewior + +[ 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 +Signed-off-by: Michael Ellerman +Link: https://msgid.link/20230309134831.Nz12nqsU@linutronix.de +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-5.15/powerpc-only-define-__parse_fpscr-when-required.patch b/queue-5.15/powerpc-only-define-__parse_fpscr-when-required.patch new file mode 100644 index 00000000000..63688714d75 --- /dev/null +++ b/queue-5.15/powerpc-only-define-__parse_fpscr-when-required.patch @@ -0,0 +1,55 @@ +From c94bb87ef35f6796772323a3d7c40b2018ee1823 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 22 Sep 2023 14:33:13 +0200 +Subject: powerpc: Only define __parse_fpscr() when required + +From: Christophe Leroy + +[ 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 +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 +Signed-off-by: Michael Ellerman +Link: https://msgid.link/5de2998c57f3983563b27b39228ea9a7229d4110.1695385984.git.christophe.leroy@csgroup.eu +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-5.15/powerpc-pseries-fix-potential-memory-leak-in-init_cp.patch b/queue-5.15/powerpc-pseries-fix-potential-memory-leak-in-init_cp.patch new file mode 100644 index 00000000000..8d50ed4ae63 --- /dev/null +++ b/queue-5.15/powerpc-pseries-fix-potential-memory-leak-in-init_cp.patch @@ -0,0 +1,43 @@ +From 50d3fd64250fa8af779b91a74d3b826f34fea471 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 14 Dec 2022 15:46:23 +0800 +Subject: powerpc/pseries: fix potential memory leak in + init_cpu_associativity() + +From: Wang Yufen + +[ 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 +Reviewed-by: "Naveen N. Rao" +Signed-off-by: Michael Ellerman +Link: https://msgid.link/1671003983-10794-1-git-send-email-wangyufen@huawei.com +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-5.15/powerpc-xive-fix-endian-conversion-size.patch b/queue-5.15/powerpc-xive-fix-endian-conversion-size.patch new file mode 100644 index 00000000000..f49598f0205 --- /dev/null +++ b/queue-5.15/powerpc-xive-fix-endian-conversion-size.patch @@ -0,0 +1,41 @@ +From 607f3f59c5816b3d7b64f7794ba42661b5c2adcf Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 11 Oct 2023 16:37:00 +1100 +Subject: powerpc/xive: Fix endian conversion size + +From: Benjamin Gray + +[ 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 +Signed-off-by: Michael Ellerman +Link: https://msgid.link/20231011053711.93427-2-bgray@linux.ibm.com +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-5.15/pstore-platform-add-check-for-kstrdup.patch b/queue-5.15/pstore-platform-add-check-for-kstrdup.patch new file mode 100644 index 00000000000..ad4b03e7d6d --- /dev/null +++ b/queue-5.15/pstore-platform-add-check-for-kstrdup.patch @@ -0,0 +1,63 @@ +From e384beef309da2c7d0e211f19129261e8759337a Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 23 Jun 2023 10:27:06 +0800 +Subject: pstore/platform: Add check for kstrdup + +From: Jiasheng Jiang + +[ 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 +Link: https://lore.kernel.org/r/20230623022706.32125-1-jiasheng@iscas.ac.cn +Signed-off-by: Kees Cook +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-5.15/r8169-fix-rare-issue-with-broken-rx-after-link-down-.patch b/queue-5.15/r8169-fix-rare-issue-with-broken-rx-after-link-down-.patch new file mode 100644 index 00000000000..5f396fdbbe6 --- /dev/null +++ b/queue-5.15/r8169-fix-rare-issue-with-broken-rx-after-link-down-.patch @@ -0,0 +1,52 @@ +From 9fa06c0e8bfa31ac60ee8edb31ec9ad07818f456 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +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 + +[ 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 +Link: https://lore.kernel.org/netdev/97ec2232-3257-316c-c3e7-a08192ce16a6@gmail.com/T/ +Signed-off-by: Heiner Kallweit +Link: https://lore.kernel.org/r/9edde757-9c3b-4730-be3b-0ef3a374ff71@gmail.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-5.15/r8169-use-tp_to_dev-instead-of-open-code.patch b/queue-5.15/r8169-use-tp_to_dev-instead-of-open-code.patch new file mode 100644 index 00000000000..98259ba354e --- /dev/null +++ b/queue-5.15/r8169-use-tp_to_dev-instead-of-open-code.patch @@ -0,0 +1,49 @@ +From b69734d3fae7bdfdca28a40866231859f293fba2 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 30 Nov 2022 01:12:44 +0900 +Subject: r8169: use tp_to_dev instead of open code + +From: Juhee Kang + +[ 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 +Reviewed-by: Heiner Kallweit +Link: https://lore.kernel.org/r/20221129161244.5356-1-claudiajkang@gmail.com +Signed-off-by: Paolo Abeni +Stable-dep-of: 621735f59064 ("r8169: fix rare issue with broken rx after link-down on RTL8125") +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-5.15/rdma-core-use-size_-add-sub-mul-in-calls-to-struct_s.patch b/queue-5.15/rdma-core-use-size_-add-sub-mul-in-calls-to-struct_s.patch new file mode 100644 index 00000000000..70be05bf938 --- /dev/null +++ b/queue-5.15/rdma-core-use-size_-add-sub-mul-in-calls-to-struct_s.patch @@ -0,0 +1,118 @@ +From 4194d26e5a49ffb3de4f8a8481a1784ad1e96e82 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +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 + +[ 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 +Link: https://lore.kernel.org/r/ZQdt4NsJFwwOYxUR@work +Signed-off-by: Leon Romanovsky +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-5.15/rdma-hfi1-workaround-truncation-compilation-error.patch b/queue-5.15/rdma-hfi1-workaround-truncation-compilation-error.patch new file mode 100644 index 00000000000..3a16703fd22 --- /dev/null +++ b/queue-5.15/rdma-hfi1-workaround-truncation-compilation-error.patch @@ -0,0 +1,57 @@ +From afedc1e5f9e5e434fc0aa45cb5d1e0a38dff95aa Mon Sep 17 00:00:00 2001 +From: Sasha Levin +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 + +[ 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 +Link: https://lore.kernel.org/r/238fa39a8fd60e87a5ad7e1ca6584fcdf32e9519.1698159993.git.leonro@nvidia.com +Acked-by: Dennis Dalessandro +Signed-off-by: Leon Romanovsky +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-5.15/rdma-hns-fix-signed-unsigned-mixed-comparisons.patch b/queue-5.15/rdma-hns-fix-signed-unsigned-mixed-comparisons.patch new file mode 100644 index 00000000000..b15a1b71c5f --- /dev/null +++ b/queue-5.15/rdma-hns-fix-signed-unsigned-mixed-comparisons.patch @@ -0,0 +1,41 @@ +From 20217d7520a0d288a89595dbb3afa32221ac8ae3 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 17 Oct 2023 20:52:35 +0800 +Subject: RDMA/hns: Fix signed-unsigned mixed comparisons + +From: Chengchang Tang + +[ 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 +Signed-off-by: Junxian Huang +Link: https://lore.kernel.org/r/20231017125239.164455-4-huangjunxian6@hisilicon.com +Signed-off-by: Leon Romanovsky +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-5.15/rdma-hns-fix-uninitialized-ucmd-in-hns_roce_create_q.patch b/queue-5.15/rdma-hns-fix-uninitialized-ucmd-in-hns_roce_create_q.patch new file mode 100644 index 00000000000..7901a040b7e --- /dev/null +++ b/queue-5.15/rdma-hns-fix-uninitialized-ucmd-in-hns_roce_create_q.patch @@ -0,0 +1,44 @@ +From 17a4849ae3a46872333e77a4ac26d307221ec7e0 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 17 Oct 2023 20:52:34 +0800 +Subject: RDMA/hns: Fix uninitialized ucmd in hns_roce_create_qp_common() + +From: Chengchang Tang + +[ 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 +Signed-off-by: Junxian Huang +Link: https://lore.kernel.org/r/20231017125239.164455-3-huangjunxian6@hisilicon.com +Signed-off-by: Leon Romanovsky +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-5.15/rdma-hns-the-ud-mode-can-only-be-configured-with-dcq.patch b/queue-5.15/rdma-hns-the-ud-mode-can-only-be-configured-with-dcq.patch new file mode 100644 index 00000000000..fbc8f4e6d00 --- /dev/null +++ b/queue-5.15/rdma-hns-the-ud-mode-can-only-be-configured-with-dcq.patch @@ -0,0 +1,39 @@ +From c5b784263a978e49b65607bbc0a7dae4c333469b Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 17 Oct 2023 20:52:37 +0800 +Subject: RDMA/hns: The UD mode can only be configured with DCQCN + +From: Luoyouming + +[ 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 +Signed-off-by: Junxian Huang +Link: https://lore.kernel.org/r/20231017125239.164455-6-huangjunxian6@hisilicon.com +Signed-off-by: Leon Romanovsky +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-5.15/regmap-debugfs-fix-a-erroneous-check-after-snprintf.patch b/queue-5.15/regmap-debugfs-fix-a-erroneous-check-after-snprintf.patch new file mode 100644 index 00000000000..fe9d3da4b28 --- /dev/null +++ b/queue-5.15/regmap-debugfs-fix-a-erroneous-check-after-snprintf.patch @@ -0,0 +1,37 @@ +From beed7db9fb4538c34ca371d7ff5c1f0b733a1349 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 4 Sep 2023 22:04:06 +0200 +Subject: regmap: debugfs: Fix a erroneous check after snprintf() + +From: Christophe JAILLET + +[ 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 +Link: https://lore.kernel.org/r/8595de2462c490561f70020a6d11f4d6b652b468.1693857825.git.christophe.jaillet@wanadoo.fr +Signed-off-by: Mark Brown +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-5.15/regmap-prevent-noinc-writes-from-clobbering-cache.patch b/queue-5.15/regmap-prevent-noinc-writes-from-clobbering-cache.patch new file mode 100644 index 00000000000..30f6e0a6f29 --- /dev/null +++ b/queue-5.15/regmap-prevent-noinc-writes-from-clobbering-cache.patch @@ -0,0 +1,57 @@ +From 2f7d595cf67e4d2d02e08939cdfa2564978c5685 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 1 Nov 2023 10:29:27 -0400 +Subject: regmap: prevent noinc writes from clobbering cache + +From: Ben Wolsieffer + +[ 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 +Link: https://lore.kernel.org/r/20231101142926.2722603-2-ben.wolsieffer@hefring.com +Signed-off-by: Mark Brown +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-5.15/revert-hid-logitech-hidpp-add-a-module-parameter-to-.patch b/queue-5.15/revert-hid-logitech-hidpp-add-a-module-parameter-to-.patch new file mode 100644 index 00000000000..15e802602ff --- /dev/null +++ b/queue-5.15/revert-hid-logitech-hidpp-add-a-module-parameter-to-.patch @@ -0,0 +1,59 @@ +From 1a2cbb57a00114d1acfdf051523abb3ca0b22e3e Mon Sep 17 00:00:00 2001 +From: Sasha Levin +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 + +[ 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 +Signed-off-by: Benjamin Tissoires +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 +--- + 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 "); + MODULE_AUTHOR("Nestor Lopez Casado "); + +-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 + diff --git a/queue-5.15/rtc-pcf85363-fix-wrong-mask-val-parameters-in-regmap.patch b/queue-5.15/rtc-pcf85363-fix-wrong-mask-val-parameters-in-regmap.patch new file mode 100644 index 00000000000..455c2887ac6 --- /dev/null +++ b/queue-5.15/rtc-pcf85363-fix-wrong-mask-val-parameters-in-regmap.patch @@ -0,0 +1,43 @@ +From 5e8708a4c644e752b5fe7edda7a5e96864282124 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +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 + +[ 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 +Link: https://lore.kernel.org/r/20231013-topic-pcf85363_regmap_update_bits-v1-1-c454f016f71f@gmail.com +Signed-off-by: Alexandre Belloni +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-5.15/sched-fix-stop_one_cpu_nowait-vs-hotplug.patch b/queue-5.15/sched-fix-stop_one_cpu_nowait-vs-hotplug.patch new file mode 100644 index 00000000000..8eb3ee43fad --- /dev/null +++ b/queue-5.15/sched-fix-stop_one_cpu_nowait-vs-hotplug.patch @@ -0,0 +1,211 @@ +From 22d4391b5f37f0131cd523bb129bf339f547e629 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +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 + +[ 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..) + + + 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 (張建文)" +Signed-off-by: Peter Zijlstra (Intel) +Tested-by: "Kuyo Chang (張建文)" +Link: https://lkml.kernel.org/r/20231010200442.GA16515@noisy.programming.kicks-ass.net +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-5.15/sched-uclamp-ignore-util-0-optimization-in-feec-when.patch b/queue-5.15/sched-uclamp-ignore-util-0-optimization-in-feec-when.patch new file mode 100644 index 00000000000..09ccb595283 --- /dev/null +++ b/queue-5.15/sched-uclamp-ignore-util-0-optimization-in-feec-when.patch @@ -0,0 +1,73 @@ +From b9941c37b8c431cbc36a1690a001706f049d2841 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +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 + +[ 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) +Signed-off-by: Ingo Molnar +Reviewed-by: Vincent Guittot +Reviewed-by: Dietmar Eggemann +Acked-by: Peter Zijlstra (Intel) +Link: https://lore.kernel.org/r/20230916232955.2099394-3-qyousef@layalina.io +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-5.15/scsi-ibmvfc-fix-erroneous-use-of-rtas_busy_delay-wit.patch b/queue-5.15/scsi-ibmvfc-fix-erroneous-use-of-rtas_busy_delay-wit.patch new file mode 100644 index 00000000000..1d54004c1f7 --- /dev/null +++ b/queue-5.15/scsi-ibmvfc-fix-erroneous-use-of-rtas_busy_delay-wit.patch @@ -0,0 +1,51 @@ +From af7a97175d47ce62f77cd7a452552b5a8e76b1d3 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +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 + +[ 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 +Link: https://lore.kernel.org/r/20230921225435.3537728-5-tyreld@linux.ibm.com +Reviewed-by: Brian King +Signed-off-by: Martin K. Petersen +Signed-off-by: Sasha Levin +--- + 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 + #include + #include +-#include + #include + #include + #include +@@ -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 + diff --git a/queue-5.15/scsi-ufs-core-leave-space-for-0-in-utf8-desc-string.patch b/queue-5.15/scsi-ufs-core-leave-space-for-0-in-utf8-desc-string.patch new file mode 100644 index 00000000000..8afb6f44a24 --- /dev/null +++ b/queue-5.15/scsi-ufs-core-leave-space-for-0-in-utf8-desc-string.patch @@ -0,0 +1,48 @@ +From 28c867debc183b2773635a065525148a79533e91 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 17 Oct 2023 11:20:26 -0700 +Subject: scsi: ufs: core: Leave space for '\0' in utf8 desc string + +From: Daniel Mentz + +[ 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 +Reviewed-by: Bart Van Assche +Reviewed-by: Yen-lin Lai +Signed-off-by: Daniel Mentz +Link: https://lore.kernel.org/r/20231017182026.2141163-1-danielmentz@google.com +Reviewed-by: Avri Altman +Signed-off-by: Martin K. Petersen +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-5.15/selftests-bpf-correct-map_fd-to-data_fd-in-tailcalls.patch b/queue-5.15/selftests-bpf-correct-map_fd-to-data_fd-in-tailcalls.patch new file mode 100644 index 00000000000..0e3a4568a35 --- /dev/null +++ b/queue-5.15/selftests-bpf-correct-map_fd-to-data_fd-in-tailcalls.patch @@ -0,0 +1,121 @@ +From ca6b75eaf16ab2394cf8f037f509b6bad7e59b3d Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 6 Sep 2023 23:42:56 +0800 +Subject: selftests/bpf: Correct map_fd to data_fd in tailcalls + +From: Leon Hwang + +[ 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 +Reviewed-by: Maciej Fijalkowski +Link: https://lore.kernel.org/r/20230906154256.95461-1-hffilwlqm@gmail.com +Signed-off-by: Martin KaFai Lau +Signed-off-by: Sasha Levin +--- + .../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 + diff --git a/queue-5.15/selftests-bpf-test-tail-call-counting-with-bpf2bpf-a.patch b/queue-5.15/selftests-bpf-test-tail-call-counting-with-bpf2bpf-a.patch new file mode 100644 index 00000000000..28bb297b4df --- /dev/null +++ b/queue-5.15/selftests-bpf-test-tail-call-counting-with-bpf2bpf-a.patch @@ -0,0 +1,146 @@ +From 77b5a4342528531848fa52864d6ff0dde588a1cb Mon Sep 17 00:00:00 2001 +From: Sasha Levin +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 + +[ 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 +Signed-off-by: Daniel Borkmann +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 +--- + .../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 ++#include ++ ++#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 + diff --git a/queue-5.15/selftests-pidfd-fix-ksft-print-formats.patch b/queue-5.15/selftests-pidfd-fix-ksft-print-formats.patch new file mode 100644 index 00000000000..6bf8c3d1619 --- /dev/null +++ b/queue-5.15/selftests-pidfd-fix-ksft-print-formats.patch @@ -0,0 +1,102 @@ +From 26cca3cb737c6bf3a9956c7157705f24f08505ba Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 13 Oct 2023 13:36:28 +0200 +Subject: selftests/pidfd: Fix ksft print formats + +From: Maciej Wieczor-Retman + +[ 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 +Signed-off-by: Shuah Khan +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-5.15/selftests-resctrl-ensure-the-benchmark-commands-fits.patch b/queue-5.15/selftests-resctrl-ensure-the-benchmark-commands-fits.patch new file mode 100644 index 00000000000..fabefe3265d --- /dev/null +++ b/queue-5.15/selftests-resctrl-ensure-the-benchmark-commands-fits.patch @@ -0,0 +1,55 @@ +From 955fee01b3b81a9193909804e6c64f481679c2b3 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +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 + +[ 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 +Tested-by: Shaopeng Tan +Reviewed-by: Shaopeng Tan +Reviewed-by: "Wieczor-Retman, Maciej" +Reviewed-by: Reinette Chatre +Signed-off-by: Shuah Khan +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-5.15/series b/queue-5.15/series index e69de29bb2d..bd3d5101837 100644 --- a/queue-5.15/series +++ b/queue-5.15/series @@ -0,0 +1,231 @@ +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 diff --git a/queue-5.15/sh-bios-revive-earlyprintk-support.patch b/queue-5.15/sh-bios-revive-earlyprintk-support.patch new file mode 100644 index 00000000000..052f7e87038 --- /dev/null +++ b/queue-5.15/sh-bios-revive-earlyprintk-support.patch @@ -0,0 +1,52 @@ +From 5f5603f7a36845d0b7a7ff9579c5b377a7741fd1 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 19 Oct 2023 11:46:43 +0200 +Subject: sh: bios: Revive earlyprintk support + +From: Geert Uytterhoeven + +[ 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 +Reviewed-by: John Paul Adrian Glaubitz +Link: https://lore.kernel.org/r/c40972dfec3dcc6719808d5df388857360262878.1697708489.git.geert+renesas@glider.be +Signed-off-by: John Paul Adrian Glaubitz +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-5.15/soc-qcom-llcc-handle-a-second-device-without-data-co.patch b/queue-5.15/soc-qcom-llcc-handle-a-second-device-without-data-co.patch new file mode 100644 index 00000000000..384d9ee1d29 --- /dev/null +++ b/queue-5.15/soc-qcom-llcc-handle-a-second-device-without-data-co.patch @@ -0,0 +1,42 @@ +From 7f47cdd199a68ad3bbf04fec0b990e40892e0cad Mon Sep 17 00:00:00 2001 +From: Sasha Levin +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 + +[ 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 +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 +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-5.15/spi-nxp-fspi-use-the-correct-ioremap-function.patch b/queue-5.15/spi-nxp-fspi-use-the-correct-ioremap-function.patch new file mode 100644 index 00000000000..4483ab70177 --- /dev/null +++ b/queue-5.15/spi-nxp-fspi-use-the-correct-ioremap-function.patch @@ -0,0 +1,38 @@ +From 4a6264aa637e6b8cae9ab9297a9738a610bfbbe3 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 10 Oct 2023 15:15:24 -0500 +Subject: spi: nxp-fspi: use the correct ioremap function + +From: Han Xu + +[ 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 +Link: https://lore.kernel.org/r/20231010201524.2021340-1-han.xu@nxp.com +Signed-off-by: Mark Brown +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-5.15/spi-tegra-fix-missing-irq-check-in-tegra_slink_probe.patch b/queue-5.15/spi-tegra-fix-missing-irq-check-in-tegra_slink_probe.patch new file mode 100644 index 00000000000..9902c13d9fa --- /dev/null +++ b/queue-5.15/spi-tegra-fix-missing-irq-check-in-tegra_slink_probe.patch @@ -0,0 +1,41 @@ +From 5b2c41ee1809edfa8dd1602343fb0f2a0aad77a6 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 26 Aug 2023 18:02:54 +0800 +Subject: spi: tegra: Fix missing IRQ check in tegra_slink_probe() + +From: Zhang Shurong + +[ 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 +Reviewed-by: Helen Koike +Link: https://lore.kernel.org/r/tencent_73FCC06A3D1C14EE5175253C6FB46A07B709@qq.com +Signed-off-by: Mark Brown +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-5.15/tcp-call-tcp_try_undo_recovery-when-an-rtod-tfo-syna.patch b/queue-5.15/tcp-call-tcp_try_undo_recovery-when-an-rtod-tfo-syna.patch new file mode 100644 index 00000000000..46245728b60 --- /dev/null +++ b/queue-5.15/tcp-call-tcp_try_undo_recovery-when-an-rtod-tfo-syna.patch @@ -0,0 +1,71 @@ +From d9021c6cfc3509d3da7704eb68d927f1df9f450c Mon Sep 17 00:00:00 2001 +From: Sasha Levin +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 + +[ 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 +Signed-off-by: Neal Cardwell +Signed-off-by: Yuchung Cheng +Reviewed-by: Eric Dumazet +Signed-off-by: David S. Miller +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-5.15/tcp-fix-cookie_init_timestamp-overflows.patch b/queue-5.15/tcp-fix-cookie_init_timestamp-overflows.patch new file mode 100644 index 00000000000..a03cef40d5a --- /dev/null +++ b/queue-5.15/tcp-fix-cookie_init_timestamp-overflows.patch @@ -0,0 +1,102 @@ +From cd5bb3844366e4f6ef3c63785007bc85f8e78c5a Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 20 Oct 2023 12:57:37 +0000 +Subject: tcp: fix cookie_init_timestamp() overflows + +From: Eric Dumazet + +[ 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 +Signed-off-by: David S. Miller +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-5.15/tcp_metrics-add-missing-barriers-on-delete.patch b/queue-5.15/tcp_metrics-add-missing-barriers-on-delete.patch new file mode 100644 index 00000000000..6dba3ce67f7 --- /dev/null +++ b/queue-5.15/tcp_metrics-add-missing-barriers-on-delete.patch @@ -0,0 +1,47 @@ +From fce31316e4b550cc8672727e129b28d0fb4f8079 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 22 Sep 2023 22:03:53 +0000 +Subject: tcp_metrics: add missing barriers on delete + +From: Eric Dumazet + +[ 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 +Reviewed-by: David Ahern +Acked-by: Neal Cardwell +Signed-off-by: Paolo Abeni +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-5.15/tcp_metrics-do-not-create-an-entry-from-tcp_init_met.patch b/queue-5.15/tcp_metrics-do-not-create-an-entry-from-tcp_init_met.patch new file mode 100644 index 00000000000..90c9a72120b --- /dev/null +++ b/queue-5.15/tcp_metrics-do-not-create-an-entry-from-tcp_init_met.patch @@ -0,0 +1,39 @@ +From 420dc90fe28f010a1da43274d71055c403080e5c Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 22 Sep 2023 22:03:55 +0000 +Subject: tcp_metrics: do not create an entry from tcp_init_metrics() + +From: Eric Dumazet + +[ 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 +Reviewed-by: David Ahern +Acked-by: Neal Cardwell +Signed-off-by: Paolo Abeni +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-5.15/tcp_metrics-properly-set-tp-snd_ssthresh-in-tcp_init.patch b/queue-5.15/tcp_metrics-properly-set-tp-snd_ssthresh-in-tcp_init.patch new file mode 100644 index 00000000000..b11ba9332f9 --- /dev/null +++ b/queue-5.15/tcp_metrics-properly-set-tp-snd_ssthresh-in-tcp_init.patch @@ -0,0 +1,52 @@ +From 1fb52480f7dc4a585d4960194fd0dc276f683d48 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 22 Sep 2023 22:03:54 +0000 +Subject: tcp_metrics: properly set tp->snd_ssthresh in tcp_init_metrics() + +From: Eric Dumazet + +[ 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 +Reviewed-by: David Ahern +Acked-by: Neal Cardwell +Signed-off-by: Paolo Abeni +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-5.15/thermal-core-prevent-potential-string-overflow.patch b/queue-5.15/thermal-core-prevent-potential-string-overflow.patch new file mode 100644 index 00000000000..6d815afcc6b --- /dev/null +++ b/queue-5.15/thermal-core-prevent-potential-string-overflow.patch @@ -0,0 +1,47 @@ +From 021b8603e7b5364da65b188690f275f7e8fe072e Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 7 Oct 2023 11:59:39 +0300 +Subject: thermal: core: prevent potential string overflow + +From: Dan Carpenter + +[ 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 +Signed-off-by: Rafael J. Wysocki +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-5.15/tipc-use-size_add-in-calls-to-struct_size.patch b/queue-5.15/tipc-use-size_add-in-calls-to-struct_size.patch new file mode 100644 index 00000000000..5dad8f03c83 --- /dev/null +++ b/queue-5.15/tipc-use-size_add-in-calls-to-struct_size.patch @@ -0,0 +1,48 @@ +From 11b6cb694766a9f679c6dd5037e08d675cbb83cf Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 15 Sep 2023 13:16:26 -0600 +Subject: tipc: Use size_add() in calls to struct_size() + +From: Gustavo A. R. Silva + +[ 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 +Reviewed-by: Kees Cook +Signed-off-by: David S. Miller +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-5.15/tools-iio-iio_generic_buffer-ensure-alignment.patch b/queue-5.15/tools-iio-iio_generic_buffer-ensure-alignment.patch new file mode 100644 index 00000000000..41359855520 --- /dev/null +++ b/queue-5.15/tools-iio-iio_generic_buffer-ensure-alignment.patch @@ -0,0 +1,65 @@ +From b82cf78c2f77bcdf6586f25ab6e05730161f2c60 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 3 Oct 2023 12:57:47 +0300 +Subject: tools: iio: iio_generic_buffer ensure alignment + +From: Matti Vaittinen + +[ 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 +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 +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-5.15/tty-tty_jobctrl-fix-pid-memleak-in-disassociate_ctty.patch b/queue-5.15/tty-tty_jobctrl-fix-pid-memleak-in-disassociate_ctty.patch new file mode 100644 index 00000000000..48b652d846c --- /dev/null +++ b/queue-5.15/tty-tty_jobctrl-fix-pid-memleak-in-disassociate_ctty.patch @@ -0,0 +1,117 @@ +From 53981e27429c5077c12c761c7621818010d57f74 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 31 Aug 2023 10:33:29 +0800 +Subject: tty: tty_jobctrl: fix pid memleak in disassociate_ctty() + +From: Yi Yang + +[ 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: + [] kmem_cache_alloc+0x5c6/0x9b0 + [] alloc_pid+0x72/0x570 + [] copy_process+0x1374/0x2470 + [] kernel_clone+0xb7/0x900 + [] __se_sys_clone+0x85/0xb0 + [] __x64_sys_clone+0x2b/0x30 + [] do_syscall_64+0x32/0x80 + [] 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 +Co-developed-by: GUO Zihua +Signed-off-by: GUO Zihua +Link: https://lore.kernel.org/r/20230831023329.165737-1-yiyang13@huawei.com +Signed-off-by: Greg Kroah-Hartman +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-5.15/udp-add-missing-write_once-around-up-encap_rcv.patch b/queue-5.15/udp-add-missing-write_once-around-up-encap_rcv.patch new file mode 100644 index 00000000000..839d46b8aa5 --- /dev/null +++ b/queue-5.15/udp-add-missing-write_once-around-up-encap_rcv.patch @@ -0,0 +1,43 @@ +From 4fa35740ebd4b5ba6682f8337655b8e954afd6be Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 12 Sep 2023 09:17:25 +0000 +Subject: udp: add missing WRITE_ONCE() around up->encap_rcv + +From: Eric Dumazet + +[ 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 +Reviewed-by: Willem de Bruijn +Signed-off-by: Paolo Abeni +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-5.15/usb-chipidea-fix-dma-overwrite-for-tegra.patch b/queue-5.15/usb-chipidea-fix-dma-overwrite-for-tegra.patch new file mode 100644 index 00000000000..c06be1581de --- /dev/null +++ b/queue-5.15/usb-chipidea-fix-dma-overwrite-for-tegra.patch @@ -0,0 +1,102 @@ +From a7585e98da4b84f04295759e4587280593f4b1e9 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +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 + +[ 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 +Link: https://lore.kernel.org/r/ef8466b834c1726f5404c95c3e192e90460146f8.1695934946.git.mirq-linux@rere.qmqm.pl +Signed-off-by: Greg Kroah-Hartman +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-5.15/usb-chipidea-simplify-tegra-dma-alignment-code.patch b/queue-5.15/usb-chipidea-simplify-tegra-dma-alignment-code.patch new file mode 100644 index 00000000000..147bdd1e696 --- /dev/null +++ b/queue-5.15/usb-chipidea-simplify-tegra-dma-alignment-code.patch @@ -0,0 +1,138 @@ +From ce3e3ad8261597a12d609dad27dda4bd3132cdfe Mon Sep 17 00:00:00 2001 +From: Sasha Levin +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 + +[ 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 +Link: https://lore.kernel.org/r/a0d917d492b1f91ee0019e68b8e8bca9c585393f.1695934946.git.mirq-linux@rere.qmqm.pl +Signed-off-by: Greg Kroah-Hartman +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-5.15/usb-dwc2-fix-possible-null-pointer-dereference-cause.patch b/queue-5.15/usb-dwc2-fix-possible-null-pointer-dereference-cause.patch new file mode 100644 index 00000000000..583c386591c --- /dev/null +++ b/queue-5.15/usb-dwc2-fix-possible-null-pointer-dereference-cause.patch @@ -0,0 +1,69 @@ +From dfa86a5a32e52280c0dfe2858e28e466ce4eb57a Mon Sep 17 00:00:00 2001 +From: Sasha Levin +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 + +[ 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 +Link: https://lore.kernel.org/r/20230926024404.832096-1-baijiaju@buaa.edu.cn +Signed-off-by: Greg Kroah-Hartman +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-5.15/usb-host-xhci-plat-fix-possible-kernel-oops-while-re.patch b/queue-5.15/usb-host-xhci-plat-fix-possible-kernel-oops-while-re.patch new file mode 100644 index 00000000000..b4349a3b5c2 --- /dev/null +++ b/queue-5.15/usb-host-xhci-plat-fix-possible-kernel-oops-while-re.patch @@ -0,0 +1,80 @@ +From 1d6dc3db9e9b0ecc2fd795aac35e6b479386f6b1 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 19 Oct 2023 13:29:23 +0300 +Subject: usb: host: xhci-plat: fix possible kernel oops while resuming + +From: Sergey Shtylyov + +[ 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 +Signed-off-by: Mathias Nyman +Link: https://lore.kernel.org/r/20231019102924.2797346-19-mathias.nyman@linux.intel.com +Signed-off-by: Greg Kroah-Hartman +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-5.15/usb-usbip-fix-stub_dev-hub-disconnect.patch b/queue-5.15/usb-usbip-fix-stub_dev-hub-disconnect.patch new file mode 100644 index 00000000000..05fc6c569e9 --- /dev/null +++ b/queue-5.15/usb-usbip-fix-stub_dev-hub-disconnect.patch @@ -0,0 +1,46 @@ +From dd3452b179005743b4c2a4490a20b3d7d97b8f25 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 15 Jun 2023 11:28:10 +0200 +Subject: USB: usbip: fix stub_dev hub disconnect + +From: Jonas Blixt + +[ 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 +Acked-by: Shuah Khan +Link: https://lore.kernel.org/r/20230615092810.1215490-1-jonas.blixt@actia.se +Signed-off-by: Greg Kroah-Hartman +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-5.15/vfs-fix-readahead-2-on-block-devices.patch b/queue-5.15/vfs-fix-readahead-2-on-block-devices.patch new file mode 100644 index 00000000000..fd19067c6dc --- /dev/null +++ b/queue-5.15/vfs-fix-readahead-2-on-block-devices.patch @@ -0,0 +1,43 @@ +From 8ca31451a374146f5664b0f0ecac349b71459ccc Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 2 Oct 2023 20:57:04 -0500 +Subject: vfs: fix readahead(2) on block devices + +From: Reuben Hawkins + +[ 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 +Link: https://lore.kernel.org/r/20231003015704.2415-1-reubenhwk@gmail.com +Reviewed-by: Amir Goldstein +Signed-off-by: Christian Brauner +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-5.15/wifi-iwlwifi-call-napi_synchronize-before-freeing-rx.patch b/queue-5.15/wifi-iwlwifi-call-napi_synchronize-before-freeing-rx.patch new file mode 100644 index 00000000000..97d2171d246 --- /dev/null +++ b/queue-5.15/wifi-iwlwifi-call-napi_synchronize-before-freeing-rx.patch @@ -0,0 +1,100 @@ +From 5ee571844915fa6aee9cbffedf96b7fc018c4da2 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 16 Apr 2023 15:47:26 +0300 +Subject: wifi: iwlwifi: call napi_synchronize() before freeing rx/tx queues + +From: Gregory Greenman + +[ 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 +Co-developed-by: Benjamin Berg +Signed-off-by: Benjamin Berg +Link: https://lore.kernel.org/r/20230416154301.5171ee44dcc1.Iff18718540da412e084e7d8266447d40730600ed@changeid +Signed-off-by: Johannes Berg +Stable-dep-of: 37fb29bd1f90 ("wifi: iwlwifi: pcie: synchronize IRQs before NAPI") +Signed-off-by: Sasha Levin +--- + .../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 + diff --git a/queue-5.15/wifi-iwlwifi-empty-overflow-queue-during-flush.patch b/queue-5.15/wifi-iwlwifi-empty-overflow-queue-during-flush.patch new file mode 100644 index 00000000000..d53a9067523 --- /dev/null +++ b/queue-5.15/wifi-iwlwifi-empty-overflow-queue-during-flush.patch @@ -0,0 +1,169 @@ +From b06b261a4be64d97fef63f2490b947ba976a08ce Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 22 Oct 2023 17:55:51 +0300 +Subject: wifi: iwlwifi: empty overflow queue during flush + +From: Miri Korenblit + +[ 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 +Signed-off-by: Gregory Greenman +Link: https://lore.kernel.org/r/20231022173519.caf06c8709d9.Ibf664ccb3f952e836f8fa461ea58fc08e5c46e88@changeid +Signed-off-by: Johannes Berg +Signed-off-by: Sasha Levin +--- + 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 +@@ -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 + diff --git a/queue-5.15/wifi-iwlwifi-pcie-synchronize-irqs-before-napi.patch b/queue-5.15/wifi-iwlwifi-pcie-synchronize-irqs-before-napi.patch new file mode 100644 index 00000000000..fede7ea015a --- /dev/null +++ b/queue-5.15/wifi-iwlwifi-pcie-synchronize-irqs-before-napi.patch @@ -0,0 +1,55 @@ +From d3102f071138f3aeaa76a38b5e1d64371320fce3 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 17 Oct 2023 12:16:43 +0300 +Subject: wifi: iwlwifi: pcie: synchronize IRQs before NAPI + +From: Johannes Berg + +[ 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 +Signed-off-by: Gregory Greenman +Link: https://lore.kernel.org/r/20231017115047.a0f4104b479a.Id5c50a944f709092aa6256e32d8c63b2b8d8d3ac@changeid +Signed-off-by: Johannes Berg +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-5.15/wifi-iwlwifi-use-fw-rate-for-non-data-frames.patch b/queue-5.15/wifi-iwlwifi-use-fw-rate-for-non-data-frames.patch new file mode 100644 index 00000000000..dbbccec46e6 --- /dev/null +++ b/queue-5.15/wifi-iwlwifi-use-fw-rate-for-non-data-frames.patch @@ -0,0 +1,64 @@ +From e6fd3bc394c77358025424a510f61d5c0184e39b Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 13 Sep 2023 14:56:45 +0300 +Subject: wifi: iwlwifi: Use FW rate for non-data frames + +From: Miri Korenblit + +[ 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 +Signed-off-by: Gregory Greenman +Link: https://lore.kernel.org/r/20230913145231.6c7e59620ee0.I6eaed3ccdd6dd62b9e664facc484081fc5275843@changeid +Signed-off-by: Johannes Berg +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-5.15/wifi-mt76-mt7603-improve-stuck-beacon-handling.patch b/queue-5.15/wifi-mt76-mt7603-improve-stuck-beacon-handling.patch new file mode 100644 index 00000000000..d5db2fd771e --- /dev/null +++ b/queue-5.15/wifi-mt76-mt7603-improve-stuck-beacon-handling.patch @@ -0,0 +1,177 @@ +From 96730d9a1dcbb0718c555443e8b8a9d4875ecdd0 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 28 Jul 2023 16:21:18 +0200 +Subject: wifi: mt76: mt7603: improve stuck beacon handling + +From: Felix Fietkau + +[ 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 +Signed-off-by: Sasha Levin +--- + .../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 + diff --git a/queue-5.15/wifi-mt76-mt7603-rework-fix-rx-pse-hang-check.patch b/queue-5.15/wifi-mt76-mt7603-rework-fix-rx-pse-hang-check.patch new file mode 100644 index 00000000000..8eb942e08f9 --- /dev/null +++ b/queue-5.15/wifi-mt76-mt7603-rework-fix-rx-pse-hang-check.patch @@ -0,0 +1,87 @@ +From 6682a4eabf184dc9531c06caa13c870603d23080 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 28 Jul 2023 09:51:01 +0200 +Subject: wifi: mt76: mt7603: rework/fix rx pse hang check + +From: Felix Fietkau + +[ 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 +Signed-off-by: Sasha Levin +--- + .../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 + diff --git a/queue-5.15/wifi-rtlwifi-fix-edca-limit-set-by-bt-coexistence.patch b/queue-5.15/wifi-rtlwifi-fix-edca-limit-set-by-bt-coexistence.patch new file mode 100644 index 00000000000..1c58ec6108d --- /dev/null +++ b/queue-5.15/wifi-rtlwifi-fix-edca-limit-set-by-bt-coexistence.patch @@ -0,0 +1,70 @@ +From 3b553ab3adb0cf95678bdfaf4e5a0b5bcc096ab1 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 28 Sep 2023 08:23:19 +0300 +Subject: wifi: rtlwifi: fix EDCA limit set by BT coexistence + +From: Dmitry Antipov + +[ 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 +Acked-by: Ping-Ke Shih +Signed-off-by: Kalle Valo +Link: https://lore.kernel.org/r/20230928052327.120178-1-dmantipov@yandex.ru +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-5.15/wifi-rtw88-debug-fix-the-null-vs-is_err-bug-for-debu.patch b/queue-5.15/wifi-rtw88-debug-fix-the-null-vs-is_err-bug-for-debu.patch new file mode 100644 index 00000000000..25214032f0d --- /dev/null +++ b/queue-5.15/wifi-rtw88-debug-fix-the-null-vs-is_err-bug-for-debu.patch @@ -0,0 +1,42 @@ +From 4496cb8842faab5d630699152d5c4a4c6ba5ccaf Mon Sep 17 00:00:00 2001 +From: Sasha Levin +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 + +[ 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 +Acked-by: Ping-Ke Shih +Signed-off-by: Kalle Valo +Link: https://lore.kernel.org/r/20230919050651.962694-1-ruanjinjie@huawei.com +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-5.15/writeback-cgroup-switch-inodes-with-dirty-timestamps.patch b/queue-5.15/writeback-cgroup-switch-inodes-with-dirty-timestamps.patch new file mode 100644 index 00000000000..f557ae03436 --- /dev/null +++ b/queue-5.15/writeback-cgroup-switch-inodes-with-dirty-timestamps.patch @@ -0,0 +1,103 @@ +From fe85b92bd3f43749108ec8f19c4c7d1627242f16 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 14 Oct 2023 20:55:11 +0800 +Subject: writeback, cgroup: switch inodes with dirty timestamps to release + dying cgwbs + +From: Jingbo Xu + +[ 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 +Signed-off-by: Jingbo Xu +Link: https://lore.kernel.org/r/20231014125511.102978-1-jefflexu@linux.alibaba.com +Acked-by: Tejun Heo +Signed-off-by: Christian Brauner +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-5.15/x86-boot-fix-incorrect-startup_gdt_descr.size.patch b/queue-5.15/x86-boot-fix-incorrect-startup_gdt_descr.size.patch new file mode 100644 index 00000000000..3449f190f07 --- /dev/null +++ b/queue-5.15/x86-boot-fix-incorrect-startup_gdt_descr.size.patch @@ -0,0 +1,42 @@ +From 5395bf30a449d855b798a6aa8b629d4a9b58c0bf Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 7 Aug 2023 16:45:47 +0800 +Subject: x86/boot: Fix incorrect startup_gdt_descr.size + +From: Yuntao Wang + +[ 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 +Signed-off-by: Ingo Molnar +Cc: "H. Peter Anvin" +Link: https://lore.kernel.org/r/20230807084547.217390-1-ytcoode@gmail.com +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-5.15/x86-sev-es-allow-copy_from_kernel_nofault-in-earlier.patch b/queue-5.15/x86-sev-es-allow-copy_from_kernel_nofault-in-earlier.patch new file mode 100644 index 00000000000..01c6366e318 --- /dev/null +++ b/queue-5.15/x86-sev-es-allow-copy_from_kernel_nofault-in-earlier.patch @@ -0,0 +1,64 @@ +From f19374e16420910ac130ee121f442856fd76ee61 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 11 Sep 2023 17:27:02 -0700 +Subject: x86/sev-es: Allow copy_from_kernel_nofault() in earlier boot + +From: Adam Dunlap + +[ 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 +Signed-off-by: Adam Dunlap +Signed-off-by: Ingo Molnar +Tested-by: Jacob Xu +Link: https://lore.kernel.org/r/20230912002703.3924521-2-acdunlap@google.com +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-5.15/x86-share-definition-of-__is_canonical_address.patch b/queue-5.15/x86-share-definition-of-__is_canonical_address.patch new file mode 100644 index 00000000000..087b35a82ff --- /dev/null +++ b/queue-5.15/x86-share-definition-of-__is_canonical_address.patch @@ -0,0 +1,165 @@ +From 783cca8b1d06919e09ca10f39d7b35c5098c9ee0 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 31 Jan 2022 09:24:50 +0200 +Subject: x86: Share definition of __is_canonical_address() + +From: Adrian Hunter + +[ Upstream commit 1fb85d06ad6754796cd1b920639ca9d8840abefd ] + +Reduce code duplication by moving canonical address code to a common header +file. + +Signed-off-by: Adrian Hunter +Signed-off-by: Peter Zijlstra (Intel) +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 +--- + 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 +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 + + #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 + diff --git a/queue-5.15/x86-srso-fix-sbpb-enablement-for-possible-future-fix.patch b/queue-5.15/x86-srso-fix-sbpb-enablement-for-possible-future-fix.patch new file mode 100644 index 00000000000..615377adc4a --- /dev/null +++ b/queue-5.15/x86-srso-fix-sbpb-enablement-for-possible-future-fix.patch @@ -0,0 +1,39 @@ +From 21dde46cd1c49dd2047aab1ae01be2fe6c7d8be1 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 4 Sep 2023 22:04:49 -0700 +Subject: x86/srso: Fix SBPB enablement for (possible) future fixed HW + +From: Josh Poimboeuf + +[ 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 +Signed-off-by: Ingo Molnar +Signed-off-by: Borislav Petkov (AMD) +Acked-by: Borislav Petkov (AMD) +Link: https://lore.kernel.org/r/cee5050db750b391c9f35f5334f8ff40e66c01b9.1693889988.git.jpoimboe@kernel.org +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-5.15/xen-pciback-consider-intx-disabled-when-msi-msi-x-is.patch b/queue-5.15/xen-pciback-consider-intx-disabled-when-msi-msi-x-is.patch new file mode 100644 index 00000000000..c730ea2454f --- /dev/null +++ b/queue-5.15/xen-pciback-consider-intx-disabled-when-msi-msi-x-is.patch @@ -0,0 +1,131 @@ +From 47071c5ce4d324df14134b3191a0d79400903e2a Mon Sep 17 00:00:00 2001 +From: Sasha Levin +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 + +[ 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 +Acked-by: Juergen Gross +Link: https://lore.kernel.org/r/20231016131348.1734721-1-marmarek@invisiblethingslab.com +Signed-off-by: Juergen Gross +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-5.15/xhci-loosen-rpm-as-default-policy-to-cover-for-amd-x.patch b/queue-5.15/xhci-loosen-rpm-as-default-policy-to-cover-for-amd-x.patch new file mode 100644 index 00000000000..dd2469ab982 --- /dev/null +++ b/queue-5.15/xhci-loosen-rpm-as-default-policy-to-cover-for-amd-x.patch @@ -0,0 +1,47 @@ +From 9e1321cf0ac5aae326a44a0c07cd98ec3582a31b Mon Sep 17 00:00:00 2001 +From: Sasha Levin +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 + +[ 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 +Signed-off-by: Mario Limonciello +Signed-off-by: Basavaraj Natikar +Signed-off-by: Mathias Nyman +Link: https://lore.kernel.org/r/20231019102924.2797346-15-mathias.nyman@linux.intel.com +Signed-off-by: Greg Kroah-Hartman +Signed-off-by: Sasha Levin +--- + 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 +