--- /dev/null
+From 5943b8f7449df9881b273db07bdde1e7120dccf0 Mon Sep 17 00:00:00 2001
+From: AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
+Date: Mon, 27 Nov 2023 14:20:26 +0100
+Subject: arm64: dts: mediatek: cherry: Fix interrupt cells for MT6360 on I2C7
+
+From: AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
+
+commit 5943b8f7449df9881b273db07bdde1e7120dccf0 upstream.
+
+Change interrupt cells to 2 to suppress interrupts_property warning.
+
+Cc: stable@vger.kernel.org
+Fixes: 0de0fe950f1b ("arm64: dts: mediatek: cherry: Enable MT6360 sub-pmic on I2C7")
+Link: https://lore.kernel.org/r/20231127132026.165027-1-angelogioacchino.delregno@collabora.com
+Signed-off-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ arch/arm64/boot/dts/mediatek/mt8195-cherry.dtsi | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/arch/arm64/boot/dts/mediatek/mt8195-cherry.dtsi
++++ b/arch/arm64/boot/dts/mediatek/mt8195-cherry.dtsi
+@@ -362,7 +362,7 @@
+ pinctrl-0 = <&i2c7_pins>;
+
+ pmic@34 {
+- #interrupt-cells = <1>;
++ #interrupt-cells = <2>;
+ compatible = "mediatek,mt6360";
+ reg = <0x34>;
+ interrupt-controller;
--- /dev/null
+From 8e6ecbfd44b5542a7598c1c5fc9c6dcb5d367f2a Mon Sep 17 00:00:00 2001
+From: Eugen Hristev <eugen.hristev@collabora.com>
+Date: Mon, 14 Aug 2023 09:50:42 +0300
+Subject: arm64: dts: mediatek: mt7622: fix memory node warning check
+
+From: Eugen Hristev <eugen.hristev@collabora.com>
+
+commit 8e6ecbfd44b5542a7598c1c5fc9c6dcb5d367f2a upstream.
+
+dtbs_check throws a warning at the memory node:
+Warning (unit_address_vs_reg): /memory: node has a reg or ranges property, but no unit name
+
+fix by adding the address into the node name.
+
+Cc: stable@vger.kernel.org
+Fixes: 0b6286dd96c0 ("arm64: dts: mt7622: add bananapi BPI-R64 board")
+Signed-off-by: Eugen Hristev <eugen.hristev@collabora.com>
+Reviewed-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
+Link: https://lore.kernel.org/r/20230814065042.4973-1-eugen.hristev@collabora.com
+Signed-off-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ arch/arm64/boot/dts/mediatek/mt7622-bananapi-bpi-r64.dts | 2 +-
+ arch/arm64/boot/dts/mediatek/mt7622-rfb1.dts | 2 +-
+ 2 files changed, 2 insertions(+), 2 deletions(-)
+
+--- a/arch/arm64/boot/dts/mediatek/mt7622-bananapi-bpi-r64.dts
++++ b/arch/arm64/boot/dts/mediatek/mt7622-bananapi-bpi-r64.dts
+@@ -73,7 +73,7 @@
+ };
+ };
+
+- memory {
++ memory@40000000 {
+ reg = <0 0x40000000 0 0x40000000>;
+ };
+
+--- a/arch/arm64/boot/dts/mediatek/mt7622-rfb1.dts
++++ b/arch/arm64/boot/dts/mediatek/mt7622-rfb1.dts
+@@ -55,7 +55,7 @@
+ };
+ };
+
+- memory {
++ memory@40000000 {
+ reg = <0 0x40000000 0 0x20000000>;
+ };
+
--- /dev/null
+From 24165c5dad7ba7c7624d05575a5e0cc851396c71 Mon Sep 17 00:00:00 2001
+From: AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
+Date: Wed, 25 Oct 2023 11:38:15 +0200
+Subject: arm64: dts: mediatek: mt8173-evb: Fix regulator-fixed node names
+
+From: AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
+
+commit 24165c5dad7ba7c7624d05575a5e0cc851396c71 upstream.
+
+Fix a unit_address_vs_reg warning for the USB VBUS fixed regulators
+by renaming the regulator nodes from regulator@{0,1} to regulator-usb-p0
+and regulator-usb-p1.
+
+Cc: stable@vger.kernel.org
+Fixes: c0891284a74a ("arm64: dts: mediatek: add USB3 DRD driver")
+Link: https://lore.kernel.org/r/20231025093816.44327-8-angelogioacchino.delregno@collabora.com
+Signed-off-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ arch/arm64/boot/dts/mediatek/mt8173-evb.dts | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+--- a/arch/arm64/boot/dts/mediatek/mt8173-evb.dts
++++ b/arch/arm64/boot/dts/mediatek/mt8173-evb.dts
+@@ -44,7 +44,7 @@
+ id-gpio = <&pio 16 GPIO_ACTIVE_HIGH>;
+ };
+
+- usb_p1_vbus: regulator@0 {
++ usb_p1_vbus: regulator-usb-p1 {
+ compatible = "regulator-fixed";
+ regulator-name = "usb_vbus";
+ regulator-min-microvolt = <5000000>;
+@@ -53,7 +53,7 @@
+ enable-active-high;
+ };
+
+- usb_p0_vbus: regulator@1 {
++ usb_p0_vbus: regulator-usb-p0 {
+ compatible = "regulator-fixed";
+ regulator-name = "vbus";
+ regulator-min-microvolt = <5000000>;
--- /dev/null
+From 9dea1c724fc36643e83216c1f5a26613412150db Mon Sep 17 00:00:00 2001
+From: AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
+Date: Wed, 25 Oct 2023 11:38:14 +0200
+Subject: arm64: dts: mediatek: mt8183-evb: Fix unit_address_vs_reg warning on ntc
+
+From: AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
+
+commit 9dea1c724fc36643e83216c1f5a26613412150db upstream.
+
+The NTC is defined as ntc@0 but it doesn't need any address at all.
+Fix the unit_address_vs_reg warning by dropping the unit address: since
+the node name has to be generic also fully rename it from ntc@0 to
+thermal-sensor.
+
+Cc: stable@vger.kernel.org
+Fixes: ff9ea5c62279 ("arm64: dts: mediatek: mt8183-evb: Add node for thermistor")
+Link: https://lore.kernel.org/r/20231025093816.44327-7-angelogioacchino.delregno@collabora.com
+Signed-off-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ arch/arm64/boot/dts/mediatek/mt8183-evb.dts | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/arch/arm64/boot/dts/mediatek/mt8183-evb.dts
++++ b/arch/arm64/boot/dts/mediatek/mt8183-evb.dts
+@@ -38,7 +38,7 @@
+ };
+ };
+
+- ntc@0 {
++ thermal-sensor {
+ compatible = "murata,ncp03wf104";
+ pullup-uv = <1800000>;
+ pullup-ohm = <390000>;
--- /dev/null
+From 19cba9a6c071db57888dc6b2ec1d9bf8996ea681 Mon Sep 17 00:00:00 2001
+From: AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
+Date: Wed, 25 Oct 2023 11:38:13 +0200
+Subject: arm64: dts: mediatek: mt8183: Fix unit address for scp reserved memory
+
+From: AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
+
+commit 19cba9a6c071db57888dc6b2ec1d9bf8996ea681 upstream.
+
+The reserved memory for scp had node name "scp_mem_region" and also
+without unit-address: change the name to "memory@(address)".
+This fixes a unit_address_vs_reg warning.
+
+Cc: stable@vger.kernel.org
+Fixes: 1652dbf7363a ("arm64: dts: mt8183: add scp node")
+Link: https://lore.kernel.org/r/20231025093816.44327-6-angelogioacchino.delregno@collabora.com
+Signed-off-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ arch/arm64/boot/dts/mediatek/mt8183-evb.dts | 2 +-
+ arch/arm64/boot/dts/mediatek/mt8183-kukui.dtsi | 2 +-
+ 2 files changed, 2 insertions(+), 2 deletions(-)
+
+--- a/arch/arm64/boot/dts/mediatek/mt8183-evb.dts
++++ b/arch/arm64/boot/dts/mediatek/mt8183-evb.dts
+@@ -31,7 +31,7 @@
+ #address-cells = <2>;
+ #size-cells = <2>;
+ ranges;
+- scp_mem_reserved: scp_mem_region {
++ scp_mem_reserved: memory@50000000 {
+ compatible = "shared-dma-pool";
+ reg = <0 0x50000000 0 0x2900000>;
+ no-map;
+--- a/arch/arm64/boot/dts/mediatek/mt8183-kukui.dtsi
++++ b/arch/arm64/boot/dts/mediatek/mt8183-kukui.dtsi
+@@ -108,7 +108,7 @@
+ #size-cells = <2>;
+ ranges;
+
+- scp_mem_reserved: scp_mem_region {
++ scp_mem_reserved: memory@50000000 {
+ compatible = "shared-dma-pool";
+ reg = <0 0x50000000 0 0x2900000>;
+ no-map;
--- /dev/null
+From 74543b303a9abfe4fa253d1fa215281baa05ff3a Mon Sep 17 00:00:00 2001
+From: Eugen Hristev <eugen.hristev@collabora.com>
+Date: Mon, 14 Aug 2023 10:10:53 +0300
+Subject: arm64: dts: mediatek: mt8183-kukui-jacuzzi: fix dsi unnecessary cells properties
+
+From: Eugen Hristev <eugen.hristev@collabora.com>
+
+commit 74543b303a9abfe4fa253d1fa215281baa05ff3a upstream.
+
+dtbs_check throws a warning at the dsi node:
+Warning (avoid_unnecessary_addr_size): /soc/dsi@14014000: unnecessary #address-cells/#size-cells without "ranges" or child "reg" property
+
+Other DTS have a panel child node with a reg, so the parent dtsi
+must have the address-cells and size-cells, however this specific DT
+has the panel removed, but not the cells, hence the warning above.
+
+If panel is deleted then the cells must also be deleted since they are
+tied together, as the child node in this DT does not have a reg.
+
+Cc: stable@vger.kernel.org
+Fixes: cabc71b08eb5 ("arm64: dts: mt8183: Add kukui-jacuzzi-damu board")
+Signed-off-by: Eugen Hristev <eugen.hristev@collabora.com>
+Reviewed-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
+Link: https://lore.kernel.org/r/20230814071053.5459-1-eugen.hristev@collabora.com
+Signed-off-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ arch/arm64/boot/dts/mediatek/mt8183-kukui-jacuzzi.dtsi | 2 ++
+ 1 file changed, 2 insertions(+)
+
+--- a/arch/arm64/boot/dts/mediatek/mt8183-kukui-jacuzzi.dtsi
++++ b/arch/arm64/boot/dts/mediatek/mt8183-kukui-jacuzzi.dtsi
+@@ -91,6 +91,8 @@
+
+ &dsi0 {
+ status = "okay";
++ /delete-property/#size-cells;
++ /delete-property/#address-cells;
+ /delete-node/panel@0;
+ ports {
+ port {
--- /dev/null
+From 5a60d63439694590cd5ab1f998fc917ff7ba1c1d Mon Sep 17 00:00:00 2001
+From: AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
+Date: Wed, 25 Oct 2023 11:38:16 +0200
+Subject: arm64: dts: mediatek: mt8183: Move thermal-zones to the root node
+
+From: AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
+
+commit 5a60d63439694590cd5ab1f998fc917ff7ba1c1d upstream.
+
+The thermal zones are not a soc bus device: move it to the root
+node to solve simple_bus_reg warnings.
+
+Cc: stable@vger.kernel.org
+Fixes: b325ce39785b ("arm64: dts: mt8183: add thermal zone node")
+Link: https://lore.kernel.org/r/20231025093816.44327-9-angelogioacchino.delregno@collabora.com
+Signed-off-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ arch/arm64/boot/dts/mediatek/mt8183.dtsi | 242 +++++++++++++++----------------
+ 1 file changed, 121 insertions(+), 121 deletions(-)
+
+--- a/arch/arm64/boot/dts/mediatek/mt8183.dtsi
++++ b/arch/arm64/boot/dts/mediatek/mt8183.dtsi
+@@ -1210,127 +1210,6 @@
+ nvmem-cell-names = "calibration-data";
+ };
+
+- thermal_zones: thermal-zones {
+- cpu_thermal: cpu-thermal {
+- polling-delay-passive = <100>;
+- polling-delay = <500>;
+- thermal-sensors = <&thermal 0>;
+- sustainable-power = <5000>;
+-
+- trips {
+- threshold: trip-point0 {
+- temperature = <68000>;
+- hysteresis = <2000>;
+- type = "passive";
+- };
+-
+- target: trip-point1 {
+- temperature = <80000>;
+- hysteresis = <2000>;
+- type = "passive";
+- };
+-
+- cpu_crit: cpu-crit {
+- temperature = <115000>;
+- hysteresis = <2000>;
+- type = "critical";
+- };
+- };
+-
+- cooling-maps {
+- map0 {
+- trip = <&target>;
+- cooling-device = <&cpu0
+- THERMAL_NO_LIMIT
+- THERMAL_NO_LIMIT>,
+- <&cpu1
+- THERMAL_NO_LIMIT
+- THERMAL_NO_LIMIT>,
+- <&cpu2
+- THERMAL_NO_LIMIT
+- THERMAL_NO_LIMIT>,
+- <&cpu3
+- THERMAL_NO_LIMIT
+- THERMAL_NO_LIMIT>;
+- contribution = <3072>;
+- };
+- map1 {
+- trip = <&target>;
+- cooling-device = <&cpu4
+- THERMAL_NO_LIMIT
+- THERMAL_NO_LIMIT>,
+- <&cpu5
+- THERMAL_NO_LIMIT
+- THERMAL_NO_LIMIT>,
+- <&cpu6
+- THERMAL_NO_LIMIT
+- THERMAL_NO_LIMIT>,
+- <&cpu7
+- THERMAL_NO_LIMIT
+- THERMAL_NO_LIMIT>;
+- contribution = <1024>;
+- };
+- };
+- };
+-
+- /* The tzts1 ~ tzts6 don't need to polling */
+- /* The tzts1 ~ tzts6 don't need to thermal throttle */
+-
+- tzts1: tzts1 {
+- polling-delay-passive = <0>;
+- polling-delay = <0>;
+- thermal-sensors = <&thermal 1>;
+- sustainable-power = <5000>;
+- trips {};
+- cooling-maps {};
+- };
+-
+- tzts2: tzts2 {
+- polling-delay-passive = <0>;
+- polling-delay = <0>;
+- thermal-sensors = <&thermal 2>;
+- sustainable-power = <5000>;
+- trips {};
+- cooling-maps {};
+- };
+-
+- tzts3: tzts3 {
+- polling-delay-passive = <0>;
+- polling-delay = <0>;
+- thermal-sensors = <&thermal 3>;
+- sustainable-power = <5000>;
+- trips {};
+- cooling-maps {};
+- };
+-
+- tzts4: tzts4 {
+- polling-delay-passive = <0>;
+- polling-delay = <0>;
+- thermal-sensors = <&thermal 4>;
+- sustainable-power = <5000>;
+- trips {};
+- cooling-maps {};
+- };
+-
+- tzts5: tzts5 {
+- polling-delay-passive = <0>;
+- polling-delay = <0>;
+- thermal-sensors = <&thermal 5>;
+- sustainable-power = <5000>;
+- trips {};
+- cooling-maps {};
+- };
+-
+- tztsABB: tztsABB {
+- polling-delay-passive = <0>;
+- polling-delay = <0>;
+- thermal-sensors = <&thermal 6>;
+- sustainable-power = <5000>;
+- trips {};
+- cooling-maps {};
+- };
+- };
+-
+ pwm0: pwm@1100e000 {
+ compatible = "mediatek,mt8183-disp-pwm";
+ reg = <0 0x1100e000 0 0x1000>;
+@@ -2105,4 +1984,125 @@
+ power-domains = <&spm MT8183_POWER_DOMAIN_CAM>;
+ };
+ };
++
++ thermal_zones: thermal-zones {
++ cpu_thermal: cpu-thermal {
++ polling-delay-passive = <100>;
++ polling-delay = <500>;
++ thermal-sensors = <&thermal 0>;
++ sustainable-power = <5000>;
++
++ trips {
++ threshold: trip-point0 {
++ temperature = <68000>;
++ hysteresis = <2000>;
++ type = "passive";
++ };
++
++ target: trip-point1 {
++ temperature = <80000>;
++ hysteresis = <2000>;
++ type = "passive";
++ };
++
++ cpu_crit: cpu-crit {
++ temperature = <115000>;
++ hysteresis = <2000>;
++ type = "critical";
++ };
++ };
++
++ cooling-maps {
++ map0 {
++ trip = <&target>;
++ cooling-device = <&cpu0
++ THERMAL_NO_LIMIT
++ THERMAL_NO_LIMIT>,
++ <&cpu1
++ THERMAL_NO_LIMIT
++ THERMAL_NO_LIMIT>,
++ <&cpu2
++ THERMAL_NO_LIMIT
++ THERMAL_NO_LIMIT>,
++ <&cpu3
++ THERMAL_NO_LIMIT
++ THERMAL_NO_LIMIT>;
++ contribution = <3072>;
++ };
++ map1 {
++ trip = <&target>;
++ cooling-device = <&cpu4
++ THERMAL_NO_LIMIT
++ THERMAL_NO_LIMIT>,
++ <&cpu5
++ THERMAL_NO_LIMIT
++ THERMAL_NO_LIMIT>,
++ <&cpu6
++ THERMAL_NO_LIMIT
++ THERMAL_NO_LIMIT>,
++ <&cpu7
++ THERMAL_NO_LIMIT
++ THERMAL_NO_LIMIT>;
++ contribution = <1024>;
++ };
++ };
++ };
++
++ /* The tzts1 ~ tzts6 don't need to polling */
++ /* The tzts1 ~ tzts6 don't need to thermal throttle */
++
++ tzts1: tzts1 {
++ polling-delay-passive = <0>;
++ polling-delay = <0>;
++ thermal-sensors = <&thermal 1>;
++ sustainable-power = <5000>;
++ trips {};
++ cooling-maps {};
++ };
++
++ tzts2: tzts2 {
++ polling-delay-passive = <0>;
++ polling-delay = <0>;
++ thermal-sensors = <&thermal 2>;
++ sustainable-power = <5000>;
++ trips {};
++ cooling-maps {};
++ };
++
++ tzts3: tzts3 {
++ polling-delay-passive = <0>;
++ polling-delay = <0>;
++ thermal-sensors = <&thermal 3>;
++ sustainable-power = <5000>;
++ trips {};
++ cooling-maps {};
++ };
++
++ tzts4: tzts4 {
++ polling-delay-passive = <0>;
++ polling-delay = <0>;
++ thermal-sensors = <&thermal 4>;
++ sustainable-power = <5000>;
++ trips {};
++ cooling-maps {};
++ };
++
++ tzts5: tzts5 {
++ polling-delay-passive = <0>;
++ polling-delay = <0>;
++ thermal-sensors = <&thermal 5>;
++ sustainable-power = <5000>;
++ trips {};
++ cooling-maps {};
++ };
++
++ tztsABB: tztsABB {
++ polling-delay-passive = <0>;
++ polling-delay = <0>;
++ thermal-sensors = <&thermal 6>;
++ sustainable-power = <5000>;
++ trips {};
++ cooling-maps {};
++ };
++ };
+ };
--- /dev/null
+From 59fa1e51ba54e1f513985a8177969b62973f7fd5 Mon Sep 17 00:00:00 2001
+From: AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
+Date: Thu, 5 Oct 2023 17:11:50 +0200
+Subject: arm64: dts: mediatek: mt8186: Change gpu speedbin nvmem cell name
+
+From: AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
+
+commit 59fa1e51ba54e1f513985a8177969b62973f7fd5 upstream.
+
+MT8186's GPU speedbin value must be interpreted, or the value will not
+be meaningful.
+Use the correct "gpu-speedbin" nvmem cell name for the GPU speedbin to
+allow triggering the cell info fixup handler, hence feeding the right
+speedbin number to the users.
+
+Cc: stable@vger.kernel.org
+Fixes: 263d2fd02afc ("arm64: dts: mediatek: mt8186: Add GPU speed bin NVMEM cells")
+Reviewed-by: Chen-Yu Tsai <wenst@chromium.org>
+Link: https://lore.kernel.org/r/20231005151150.355536-1-angelogioacchino.delregno@collabora.com
+Signed-off-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ arch/arm64/boot/dts/mediatek/mt8186.dtsi | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/arch/arm64/boot/dts/mediatek/mt8186.dtsi
++++ b/arch/arm64/boot/dts/mediatek/mt8186.dtsi
+@@ -1668,7 +1668,7 @@
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+- gpu_speedbin: gpu-speed-bin@59c {
++ gpu_speedbin: gpu-speedbin@59c {
+ reg = <0x59c 0x4>;
+ bits = <0 3>;
+ };
--- /dev/null
+From 9adf7580f6d498a5839e02fa1d1535e934364602 Mon Sep 17 00:00:00 2001
+From: Eugen Hristev <eugen.hristev@collabora.com>
+Date: Thu, 5 Oct 2023 13:30:41 +0300
+Subject: arm64: dts: mediatek: mt8186: fix clock names for power domains
+
+From: Eugen Hristev <eugen.hristev@collabora.com>
+
+commit 9adf7580f6d498a5839e02fa1d1535e934364602 upstream.
+
+Clocks for each power domain are split into big categories: pd clocks
+and subsys clocks.
+According to the binding, all clocks which have a dash '-' in their name
+are treated as subsys clocks, and must be placed at the end of the list.
+The other clocks which are pd clocks must come first.
+Fixed the naming and the placing of all clocks in the power domains.
+For the avoidance of doubt, prefixed all subsys clocks with the 'subsys'
+prefix. The binding does not enforce strict clock names, the driver
+uses them in bulk, only making a difference for pd clocks vs subsys clocks.
+
+The above problem appears to be trivial, however, it leads to incorrect
+power up and power down sequence of the power domains, because some
+clocks will be mistakenly taken for subsys clocks and viceversa.
+One consequence is the fact that if the DIS power domain goes power down
+and power back up during the boot process, when it comes back up, there
+are still transactions left on the bus which makes the display inoperable.
+
+Some of the clocks for the DIS power domain were wrongly using '_' instead
+of '-', which again made these clocks being treated as pd clocks instead of
+subsys clocks.
+
+Cc: stable@vger.kernel.org
+Fixes: d9e43c1e7a38 ("arm64: dts: mt8186: Add power domains controller")
+Signed-off-by: Eugen Hristev <eugen.hristev@collabora.com>
+Tested-by: Chen-Yu Tsai <wenst@chromium.org>
+Reviewed-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
+Tested-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
+Reviewed-by: Alexandre Mergnat <amergnat@baylibre.com>
+Link: https://lore.kernel.org/r/20231005103041.352478-1-eugen.hristev@collabora.com
+Signed-off-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ arch/arm64/boot/dts/mediatek/mt8186.dtsi | 42 +++++++++++++++---------
+ 1 file changed, 27 insertions(+), 15 deletions(-)
+
+diff --git a/arch/arm64/boot/dts/mediatek/mt8186.dtsi b/arch/arm64/boot/dts/mediatek/mt8186.dtsi
+index f4c4f61c779d..df0c04f2ba1d 100644
+--- a/arch/arm64/boot/dts/mediatek/mt8186.dtsi
++++ b/arch/arm64/boot/dts/mediatek/mt8186.dtsi
+@@ -924,7 +924,8 @@ power-domain@MT8186_POWER_DOMAIN_CSIRX_TOP {
+ reg = <MT8186_POWER_DOMAIN_CSIRX_TOP>;
+ clocks = <&topckgen CLK_TOP_SENINF>,
+ <&topckgen CLK_TOP_SENINF1>;
+- clock-names = "csirx_top0", "csirx_top1";
++ clock-names = "subsys-csirx-top0",
++ "subsys-csirx-top1";
+ #power-domain-cells = <0>;
+ };
+
+@@ -942,7 +943,8 @@ power-domain@MT8186_POWER_DOMAIN_ADSP_AO {
+ reg = <MT8186_POWER_DOMAIN_ADSP_AO>;
+ clocks = <&topckgen CLK_TOP_AUDIODSP>,
+ <&topckgen CLK_TOP_ADSP_BUS>;
+- clock-names = "audioadsp", "adsp_bus";
++ clock-names = "audioadsp",
++ "subsys-adsp-bus";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ #power-domain-cells = <1>;
+@@ -975,8 +977,11 @@ power-domain@MT8186_POWER_DOMAIN_DIS {
+ <&mmsys CLK_MM_SMI_COMMON>,
+ <&mmsys CLK_MM_SMI_GALS>,
+ <&mmsys CLK_MM_SMI_IOMMU>;
+- clock-names = "disp", "mdp", "smi_infra", "smi_common",
+- "smi_gals", "smi_iommu";
++ clock-names = "disp", "mdp",
++ "subsys-smi-infra",
++ "subsys-smi-common",
++ "subsys-smi-gals",
++ "subsys-smi-iommu";
+ mediatek,infracfg = <&infracfg_ao>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+@@ -993,15 +998,17 @@ power-domain@MT8186_POWER_DOMAIN_VDEC {
+
+ power-domain@MT8186_POWER_DOMAIN_CAM {
+ reg = <MT8186_POWER_DOMAIN_CAM>;
+- clocks = <&topckgen CLK_TOP_CAM>,
+- <&topckgen CLK_TOP_SENINF>,
++ clocks = <&topckgen CLK_TOP_SENINF>,
+ <&topckgen CLK_TOP_SENINF1>,
+ <&topckgen CLK_TOP_SENINF2>,
+ <&topckgen CLK_TOP_SENINF3>,
++ <&camsys CLK_CAM2MM_GALS>,
+ <&topckgen CLK_TOP_CAMTM>,
+- <&camsys CLK_CAM2MM_GALS>;
+- clock-names = "cam-top", "cam0", "cam1", "cam2",
+- "cam3", "cam-tm", "gals";
++ <&topckgen CLK_TOP_CAM>;
++ clock-names = "cam0", "cam1", "cam2",
++ "cam3", "gals",
++ "subsys-cam-tm",
++ "subsys-cam-top";
+ mediatek,infracfg = <&infracfg_ao>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+@@ -1020,9 +1027,9 @@ power-domain@MT8186_POWER_DOMAIN_CAM_RAWA {
+
+ power-domain@MT8186_POWER_DOMAIN_IMG {
+ reg = <MT8186_POWER_DOMAIN_IMG>;
+- clocks = <&topckgen CLK_TOP_IMG1>,
+- <&imgsys1 CLK_IMG1_GALS_IMG1>;
+- clock-names = "img-top", "gals";
++ clocks = <&imgsys1 CLK_IMG1_GALS_IMG1>,
++ <&topckgen CLK_TOP_IMG1>;
++ clock-names = "gals", "subsys-img-top";
+ mediatek,infracfg = <&infracfg_ao>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+@@ -1041,8 +1048,11 @@ power-domain@MT8186_POWER_DOMAIN_IPE {
+ <&ipesys CLK_IPE_LARB20>,
+ <&ipesys CLK_IPE_SMI_SUBCOM>,
+ <&ipesys CLK_IPE_GALS_IPE>;
+- clock-names = "ipe-top", "ipe-larb0", "ipe-larb1",
+- "ipe-smi", "ipe-gals";
++ clock-names = "subsys-ipe-top",
++ "subsys-ipe-larb0",
++ "subsys-ipe-larb1",
++ "subsys-ipe-smi",
++ "subsys-ipe-gals";
+ mediatek,infracfg = <&infracfg_ao>;
+ #power-domain-cells = <0>;
+ };
+@@ -1061,7 +1071,9 @@ power-domain@MT8186_POWER_DOMAIN_WPE {
+ clocks = <&topckgen CLK_TOP_WPE>,
+ <&wpesys CLK_WPE_SMI_LARB8_CK_EN>,
+ <&wpesys CLK_WPE_SMI_LARB8_PCLK_EN>;
+- clock-names = "wpe0", "larb-ck", "larb-pclk";
++ clock-names = "wpe0",
++ "subsys-larb-ck",
++ "subsys-larb-pclk";
+ mediatek,infracfg = <&infracfg_ao>;
+ #power-domain-cells = <0>;
+ };
+--
+2.43.0
+
--- /dev/null
+From 61b94d54421a1f3670ddd5396ec70afe833e9405 Mon Sep 17 00:00:00 2001
+From: AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
+Date: Thu, 6 Jul 2023 11:58:41 +0200
+Subject: arm64: dts: mediatek: mt8195: Fix PM suspend/resume with venc clocks
+
+From: AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
+
+commit 61b94d54421a1f3670ddd5396ec70afe833e9405 upstream.
+
+Before suspending the LARBs we're making sure that any operation is
+done: this never happens because we are unexpectedly unclocking the
+LARB20 before executing the suspend handler for the MediaTek Smart
+Multimedia Interface (SMI) and the cause of this is incorrect clocks
+on this LARB.
+
+Fix this issue by changing the Local Arbiter 20 (used by the video
+encoder secondary core) apb clock to CLK_VENC_CORE1_VENC;
+furthermore, in order to make sure that both the PM resume and video
+encoder operation is stable, add the CLK_VENC(_CORE1)_LARB clock to
+the VENC (main core) and VENC_CORE1 power domains, as this IP cannot
+communicate with the rest of the system (the AP) without local
+arbiter clocks being operational.
+
+Cc: stable@vger.kernel.org
+Fixes: 3b5838d1d82e ("arm64: dts: mt8195: Add iommu and smi nodes")
+Fixes: 2b515194bf0c ("arm64: dts: mt8195: Add power domains controller")
+Reviewed-by: Alexandre Mergnat <amergnat@baylibre.com>
+Link: https://lore.kernel.org/r/20230706095841.109315-1-angelogioacchino.delregno@collabora.com
+Signed-off-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ arch/arm64/boot/dts/mediatek/mt8195.dtsi | 6 +++++-
+ 1 file changed, 5 insertions(+), 1 deletion(-)
+
+--- a/arch/arm64/boot/dts/mediatek/mt8195.dtsi
++++ b/arch/arm64/boot/dts/mediatek/mt8195.dtsi
+@@ -627,6 +627,8 @@
+
+ power-domain@MT8195_POWER_DOMAIN_VENC_CORE1 {
+ reg = <MT8195_POWER_DOMAIN_VENC_CORE1>;
++ clocks = <&vencsys_core1 CLK_VENC_CORE1_LARB>;
++ clock-names = "venc1-larb";
+ mediatek,infracfg = <&infracfg_ao>;
+ #power-domain-cells = <0>;
+ };
+@@ -689,6 +691,8 @@
+
+ power-domain@MT8195_POWER_DOMAIN_VENC {
+ reg = <MT8195_POWER_DOMAIN_VENC>;
++ clocks = <&vencsys CLK_VENC_LARB>;
++ clock-names = "venc0-larb";
+ mediatek,infracfg = <&infracfg_ao>;
+ #power-domain-cells = <0>;
+ };
+@@ -2665,7 +2669,7 @@
+ reg = <0 0x1b010000 0 0x1000>;
+ mediatek,larb-id = <20>;
+ mediatek,smi = <&smi_common_vpp>;
+- clocks = <&vencsys_core1 CLK_VENC_CORE1_LARB>,
++ clocks = <&vencsys_core1 CLK_VENC_CORE1_VENC>,
+ <&vencsys_core1 CLK_VENC_CORE1_GALS>,
+ <&vppsys0 CLK_VPP0_GALS_VDO0_VDO1_VENCSYS_CORE1>;
+ clock-names = "apb", "smi", "gals";
--- /dev/null
+From 1fcda8ceb014aafd56f10b33e0077c93b5dd45d1 Mon Sep 17 00:00:00 2001
+From: Frank Wunderlich <frank-w@public-files.de>
+Date: Wed, 25 Oct 2023 19:08:30 +0200
+Subject: arm64: dts: mt7986: change cooling trips
+
+From: Frank Wunderlich <frank-w@public-files.de>
+
+commit 1fcda8ceb014aafd56f10b33e0077c93b5dd45d1 upstream.
+
+Add Critical and hot trips for emergency system shutdown and limiting
+system load.
+
+Change passive trip to active to make sure fan is activated on the
+lowest trip.
+
+Cc: stable@vger.kernel.org
+Fixes: 1f5be05132f3 ("arm64: dts: mt7986: add thermal-zones")
+Fixes: c26f779a2295 ("arm64: dts: mt7986: add pwm-fan and cooling-maps to BPI-R3 dts")
+Suggested-by: Daniel Golle <daniel@makrotopia.org>
+Signed-off-by: Frank Wunderlich <frank-w@public-files.de>
+Reviewed-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
+Link: https://lore.kernel.org/r/20231025170832.78727-4-linux@fw-web.de
+Signed-off-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ arch/arm64/boot/dts/mediatek/mt7986a-bananapi-bpi-r3.dts | 10 +++----
+ arch/arm64/boot/dts/mediatek/mt7986a.dtsi | 20 ++++++++++++---
+ 2 files changed, 21 insertions(+), 9 deletions(-)
+
+--- a/arch/arm64/boot/dts/mediatek/mt7986a-bananapi-bpi-r3.dts
++++ b/arch/arm64/boot/dts/mediatek/mt7986a-bananapi-bpi-r3.dts
+@@ -150,16 +150,16 @@
+ trip = <&cpu_trip_active_high>;
+ };
+
+- cpu-active-low {
++ cpu-active-med {
+ /* active: set fan to cooling level 1 */
+ cooling-device = <&fan 1 1>;
+- trip = <&cpu_trip_active_low>;
++ trip = <&cpu_trip_active_med>;
+ };
+
+- cpu-passive {
+- /* passive: set fan to cooling level 0 */
++ cpu-active-low {
++ /* active: set fan to cooling level 0 */
+ cooling-device = <&fan 0 0>;
+- trip = <&cpu_trip_passive>;
++ trip = <&cpu_trip_active_low>;
+ };
+ };
+ };
+--- a/arch/arm64/boot/dts/mediatek/mt7986a.dtsi
++++ b/arch/arm64/boot/dts/mediatek/mt7986a.dtsi
+@@ -610,22 +610,34 @@
+ thermal-sensors = <&thermal 0>;
+
+ trips {
++ cpu_trip_crit: crit {
++ temperature = <125000>;
++ hysteresis = <2000>;
++ type = "critical";
++ };
++
++ cpu_trip_hot: hot {
++ temperature = <120000>;
++ hysteresis = <2000>;
++ type = "hot";
++ };
++
+ cpu_trip_active_high: active-high {
+ temperature = <115000>;
+ hysteresis = <2000>;
+ type = "active";
+ };
+
+- cpu_trip_active_low: active-low {
++ cpu_trip_active_med: active-med {
+ temperature = <85000>;
+ hysteresis = <2000>;
+ type = "active";
+ };
+
+- cpu_trip_passive: passive {
+- temperature = <40000>;
++ cpu_trip_active_low: active-low {
++ temperature = <60000>;
+ hysteresis = <2000>;
+- type = "passive";
++ type = "active";
+ };
+ };
+ };
--- /dev/null
+From 6413cbc17f89b3a160f3a6f3fad1232b1678fe40 Mon Sep 17 00:00:00 2001
+From: Frank Wunderlich <frank-w@public-files.de>
+Date: Wed, 25 Oct 2023 19:08:29 +0200
+Subject: arm64: dts: mt7986: define 3W max power to both SFP on BPI-R3
+
+From: Frank Wunderlich <frank-w@public-files.de>
+
+commit 6413cbc17f89b3a160f3a6f3fad1232b1678fe40 upstream.
+
+All SFP power supplies are connected to the system VDD33 which is 3v3/8A.
+Set 3A per SFP slot to allow SFPs work which need more power than the
+default 1W.
+
+Cc: stable@vger.kernel.org
+Fixes: 8e01fb15b815 ("arm64: dts: mt7986: add Bananapi R3")
+Signed-off-by: Frank Wunderlich <frank-w@public-files.de>
+Reviewed-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
+Link: https://lore.kernel.org/r/20231025170832.78727-3-linux@fw-web.de
+Signed-off-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ arch/arm64/boot/dts/mediatek/mt7986a-bananapi-bpi-r3.dts | 2 ++
+ 1 file changed, 2 insertions(+)
+
+diff --git a/arch/arm64/boot/dts/mediatek/mt7986a-bananapi-bpi-r3.dts b/arch/arm64/boot/dts/mediatek/mt7986a-bananapi-bpi-r3.dts
+index af4a4309bda4..f9702284607a 100644
+--- a/arch/arm64/boot/dts/mediatek/mt7986a-bananapi-bpi-r3.dts
++++ b/arch/arm64/boot/dts/mediatek/mt7986a-bananapi-bpi-r3.dts
+@@ -126,6 +126,7 @@ sfp1: sfp-1 {
+ compatible = "sff,sfp";
+ i2c-bus = <&i2c_sfp1>;
+ los-gpios = <&pio 46 GPIO_ACTIVE_HIGH>;
++ maximum-power-milliwatt = <3000>;
+ mod-def0-gpios = <&pio 49 GPIO_ACTIVE_LOW>;
+ tx-disable-gpios = <&pio 20 GPIO_ACTIVE_HIGH>;
+ tx-fault-gpios = <&pio 7 GPIO_ACTIVE_HIGH>;
+@@ -137,6 +138,7 @@ sfp2: sfp-2 {
+ i2c-bus = <&i2c_sfp2>;
+ los-gpios = <&pio 31 GPIO_ACTIVE_HIGH>;
+ mod-def0-gpios = <&pio 47 GPIO_ACTIVE_LOW>;
++ maximum-power-milliwatt = <3000>;
+ tx-disable-gpios = <&pio 15 GPIO_ACTIVE_HIGH>;
+ tx-fault-gpios = <&pio 48 GPIO_ACTIVE_HIGH>;
+ };
+--
+2.43.0
+
--- /dev/null
+From 8dfe51c3f6ef31502fca3e2da8cd250ebbe4b8f2 Mon Sep 17 00:00:00 2001
+From: Eric Woudstra <ericwouds@gmail.com>
+Date: Wed, 25 Oct 2023 19:08:28 +0200
+Subject: arm64: dts: mt7986: fix emmc hs400 mode without uboot initialization
+
+From: Eric Woudstra <ericwouds@gmail.com>
+
+commit 8dfe51c3f6ef31502fca3e2da8cd250ebbe4b8f2 upstream.
+
+Eric reports errors on emmc with hs400 mode when booting linux on bpi-r3
+without uboot [1]. Booting with uboot does not show this because clocks
+seem to be initialized by uboot.
+
+Fix this by adding assigned-clocks and assigned-clock-parents like it's
+done in uboot [2].
+
+[1] https://forum.banana-pi.org/t/bpi-r3-kernel-fails-setting-emmc-clock-to-416m-depends-on-u-boot/15170
+[2] https://github.com/u-boot/u-boot/blob/master/arch/arm/dts/mt7986.dtsi#L287
+
+Cc: stable@vger.kernel.org
+Fixes: 513b49d19b34 ("arm64: dts: mt7986: add mmc related device nodes")
+Signed-off-by: Eric Woudstra <ericwouds@gmail.com>
+Signed-off-by: Frank Wunderlich <frank-w@public-files.de>
+Reviewed-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
+Link: https://lore.kernel.org/r/20231025170832.78727-2-linux@fw-web.de
+Signed-off-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ arch/arm64/boot/dts/mediatek/mt7986a.dtsi | 4 ++++
+ 1 file changed, 4 insertions(+)
+
+diff --git a/arch/arm64/boot/dts/mediatek/mt7986a.dtsi b/arch/arm64/boot/dts/mediatek/mt7986a.dtsi
+index 24eda00e320d..77ddd9e44ed2 100644
+--- a/arch/arm64/boot/dts/mediatek/mt7986a.dtsi
++++ b/arch/arm64/boot/dts/mediatek/mt7986a.dtsi
+@@ -374,6 +374,10 @@ mmc0: mmc@11230000 {
+ reg = <0 0x11230000 0 0x1000>,
+ <0 0x11c20000 0 0x1000>;
+ interrupts = <GIC_SPI 143 IRQ_TYPE_LEVEL_HIGH>;
++ assigned-clocks = <&topckgen CLK_TOP_EMMC_416M_SEL>,
++ <&topckgen CLK_TOP_EMMC_250M_SEL>;
++ assigned-clock-parents = <&apmixedsys CLK_APMIXED_MPLL>,
++ <&topckgen CLK_TOP_NET1PLL_D5_D2>;
+ clocks = <&topckgen CLK_TOP_EMMC_416M_SEL>,
+ <&infracfg CLK_INFRA_MSDC_HCK_CK>,
+ <&infracfg CLK_INFRA_MSDC_CK>,
+--
+2.43.0
+
--- /dev/null
+From cff5f49d433fcd0063c8be7dd08fa5bf190c6c37 Mon Sep 17 00:00:00 2001
+From: Tim Van Patten <timvp@google.com>
+Date: Wed, 15 Nov 2023 09:20:43 -0700
+Subject: cgroup_freezer: cgroup_freezing: Check if not frozen
+
+From: Tim Van Patten <timvp@google.com>
+
+commit cff5f49d433fcd0063c8be7dd08fa5bf190c6c37 upstream.
+
+__thaw_task() was recently updated to warn if the task being thawed was
+part of a freezer cgroup that is still currently freezing:
+
+ void __thaw_task(struct task_struct *p)
+ {
+ ...
+ if (WARN_ON_ONCE(freezing(p)))
+ goto unlock;
+
+This has exposed a bug in cgroup1 freezing where when CGROUP_FROZEN is
+asserted, the CGROUP_FREEZING bits are not also cleared at the same
+time. Meaning, when a cgroup is marked FROZEN it continues to be marked
+FREEZING as well. This causes the WARNING to trigger, because
+cgroup_freezing() thinks the cgroup is still freezing.
+
+There are two ways to fix this:
+
+1. Whenever FROZEN is set, clear FREEZING for the cgroup and all
+children cgroups.
+2. Update cgroup_freezing() to also verify that FROZEN is not set.
+
+This patch implements option (2), since it's smaller and more
+straightforward.
+
+Signed-off-by: Tim Van Patten <timvp@google.com>
+Tested-by: Mark Hasemeyer <markhas@chromium.org>
+Fixes: f5d39b020809 ("freezer,sched: Rewrite core freezer logic")
+Cc: stable@vger.kernel.org # v6.1+
+Signed-off-by: Tejun Heo <tj@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ kernel/cgroup/legacy_freezer.c | 8 +++++++-
+ 1 file changed, 7 insertions(+), 1 deletion(-)
+
+--- a/kernel/cgroup/legacy_freezer.c
++++ b/kernel/cgroup/legacy_freezer.c
+@@ -66,9 +66,15 @@ static struct freezer *parent_freezer(st
+ bool cgroup_freezing(struct task_struct *task)
+ {
+ bool ret;
++ unsigned int state;
+
+ rcu_read_lock();
+- ret = task_freezer(task)->state & CGROUP_FREEZING;
++ /* Check if the cgroup is still FREEZING, but not FROZEN. The extra
++ * !FROZEN check is required, because the FREEZING bit is not cleared
++ * when the state FROZEN is reached.
++ */
++ state = task_freezer(task)->state;
++ ret = (state & CGROUP_FREEZING) && !(state & CGROUP_FROZEN);
+ rcu_read_unlock();
+
+ return ret;
--- /dev/null
+From ee34db3f271cea4d4252048617919c2caafe698b Mon Sep 17 00:00:00 2001
+From: Heiko Carstens <hca@linux.ibm.com>
+Date: Mon, 20 Nov 2023 19:37:17 +0100
+Subject: checkstack: fix printed address
+
+From: Heiko Carstens <hca@linux.ibm.com>
+
+commit ee34db3f271cea4d4252048617919c2caafe698b upstream.
+
+All addresses printed by checkstack have an extra incorrect 0 appended at
+the end.
+
+This was introduced with commit 677f1410e058 ("scripts/checkstack.pl: don't
+display $dre as different entity"): since then the address is taken from
+the line which contains the function name, instead of the line which
+contains stack consumption. E.g. on s390:
+
+0000000000100a30 <do_one_initcall>:
+...
+ 100a44: e3 f0 ff 70 ff 71 lay %r15,-144(%r15)
+
+So the used regex which matches spaces and hexadecimal numbers to extract
+an address now matches a different substring. Subsequently replacing spaces
+with 0 appends a zero at the and, instead of replacing leading spaces.
+
+Fix this by using the proper regex, and simplify the code a bit.
+
+Link: https://lkml.kernel.org/r/20231120183719.2188479-2-hca@linux.ibm.com
+Fixes: 677f1410e058 ("scripts/checkstack.pl: don't display $dre as different entity")
+Signed-off-by: Heiko Carstens <hca@linux.ibm.com>
+Cc: Maninder Singh <maninder1.s@samsung.com>
+Cc: Masahiro Yamada <masahiroy@kernel.org>
+Cc: Vaneet Narang <v.narang@samsung.com>
+Cc: <stable@vger.kernel.org>
+Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ scripts/checkstack.pl | 8 ++------
+ 1 file changed, 2 insertions(+), 6 deletions(-)
+
+--- a/scripts/checkstack.pl
++++ b/scripts/checkstack.pl
+@@ -139,15 +139,11 @@ $total_size = 0;
+ while (my $line = <STDIN>) {
+ if ($line =~ m/$funcre/) {
+ $func = $1;
+- next if $line !~ m/^($xs*)/;
++ next if $line !~ m/^($x*)/;
+ if ($total_size > $min_stack) {
+ push @stack, "$intro$total_size\n";
+ }
+-
+- $addr = $1;
+- $addr =~ s/ /0/g;
+- $addr = "0x$addr";
+-
++ $addr = "0x$1";
+ $intro = "$addr $func [$file]:";
+ my $padlen = 56 - length($intro);
+ while ($padlen > 0) {
--- /dev/null
+From 4e9e2e4c65136dfd32dd0afe555961433d1cf906 Mon Sep 17 00:00:00 2001
+From: Baoquan He <bhe@redhat.com>
+Date: Tue, 28 Nov 2023 13:52:48 +0800
+Subject: drivers/base/cpu: crash data showing should depends on KEXEC_CORE
+
+From: Baoquan He <bhe@redhat.com>
+
+commit 4e9e2e4c65136dfd32dd0afe555961433d1cf906 upstream.
+
+After commit 88a6f8994421 ("crash: memory and CPU hotplug sysfs
+attributes"), on x86_64, if only below kernel configs related to kdump are
+set, compiling error are triggered.
+
+----
+CONFIG_CRASH_CORE=y
+CONFIG_KEXEC_CORE=y
+CONFIG_CRASH_DUMP=y
+CONFIG_CRASH_HOTPLUG=y
+------
+
+------------------------------------------------------
+drivers/base/cpu.c: In function `crash_hotplug_show':
+drivers/base/cpu.c:309:40: error: implicit declaration of function `crash_hotplug_cpu_support'; did you mean `crash_hotplug_show'? [-Werror=implicit-function-declaration]
+ 309 | return sysfs_emit(buf, "%d\n", crash_hotplug_cpu_support());
+ | ^~~~~~~~~~~~~~~~~~~~~~~~~
+ | crash_hotplug_show
+cc1: some warnings being treated as errors
+------------------------------------------------------
+
+CONFIG_KEXEC is used to enable kexec_load interface, the
+crash_notes/crash_notes_size/crash_hotplug showing depends on
+CONFIG_KEXEC is incorrect. It should depend on KEXEC_CORE instead.
+
+Fix it now.
+
+Link: https://lkml.kernel.org/r/20231128055248.659808-1-bhe@redhat.com
+Fixes: 88a6f8994421 ("crash: memory and CPU hotplug sysfs attributes")
+Signed-off-by: Baoquan He <bhe@redhat.com>
+Tested-by: Ignat Korchagin <ignat@cloudflare.com> [compile-time only]
+Tested-by: Alexander Gordeev <agordeev@linux.ibm.com>
+Reviewed-by: Eric DeVolder <eric_devolder@yahoo.com>
+Cc: <stable@vger.kernel.org>
+Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/base/cpu.c | 6 +++---
+ 1 file changed, 3 insertions(+), 3 deletions(-)
+
+diff --git a/drivers/base/cpu.c b/drivers/base/cpu.c
+index 9ea22e165acd..548491de818e 100644
+--- a/drivers/base/cpu.c
++++ b/drivers/base/cpu.c
+@@ -144,7 +144,7 @@ static DEVICE_ATTR(release, S_IWUSR, NULL, cpu_release_store);
+ #endif /* CONFIG_ARCH_CPU_PROBE_RELEASE */
+ #endif /* CONFIG_HOTPLUG_CPU */
+
+-#ifdef CONFIG_KEXEC
++#ifdef CONFIG_KEXEC_CORE
+ #include <linux/kexec.h>
+
+ static ssize_t crash_notes_show(struct device *dev,
+@@ -189,14 +189,14 @@ static const struct attribute_group crash_note_cpu_attr_group = {
+ #endif
+
+ static const struct attribute_group *common_cpu_attr_groups[] = {
+-#ifdef CONFIG_KEXEC
++#ifdef CONFIG_KEXEC_CORE
+ &crash_note_cpu_attr_group,
+ #endif
+ NULL
+ };
+
+ static const struct attribute_group *hotplugable_cpu_attr_groups[] = {
+-#ifdef CONFIG_KEXEC
++#ifdef CONFIG_KEXEC_CORE
+ &crash_note_cpu_attr_group,
+ #endif
+ NULL
+--
+2.43.0
+
--- /dev/null
+From e0f04e41e8eedd4e5a1275f2318df7e1841855f2 Mon Sep 17 00:00:00 2001
+From: Thomas Zimmermann <tzimmermann@suse.de>
+Date: Mon, 4 Dec 2023 09:32:33 +0100
+Subject: drm/atomic-helpers: Invoke end_fb_access while owning plane state
+
+From: Thomas Zimmermann <tzimmermann@suse.de>
+
+commit e0f04e41e8eedd4e5a1275f2318df7e1841855f2 upstream.
+
+Invoke drm_plane_helper_funcs.end_fb_access before
+drm_atomic_helper_commit_hw_done(). The latter function hands over
+ownership of the plane state to the following commit, which might
+free it. Releasing resources in end_fb_access then operates on undefined
+state. This bug has been observed with non-blocking commits when they
+are being queued up quickly.
+
+Here is an example stack trace from the bug report. The plane state has
+been free'd already, so the pages for drm_gem_fb_vunmap() are gone.
+
+Unable to handle kernel paging request at virtual address 0000000100000049
+[...]
+ drm_gem_fb_vunmap+0x18/0x74
+ drm_gem_end_shadow_fb_access+0x1c/0x2c
+ drm_atomic_helper_cleanup_planes+0x58/0xd8
+ drm_atomic_helper_commit_tail+0x90/0xa0
+ commit_tail+0x15c/0x188
+ commit_work+0x14/0x20
+
+Fix this by running end_fb_access immediately after updating all planes
+in drm_atomic_helper_commit_planes(). The existing clean-up helper
+drm_atomic_helper_cleanup_planes() now only handles cleanup_fb.
+
+For aborted commits, roll back from drm_atomic_helper_prepare_planes()
+in the new helper drm_atomic_helper_unprepare_planes(). This case is
+different from regular cleanup, as we have to release the new state;
+regular cleanup releases the old state. The new helper also invokes
+cleanup_fb for all planes.
+
+The changes mostly involve DRM's atomic helpers. Only two drivers, i915
+and nouveau, implement their own commit function. Update them to invoke
+drm_atomic_helper_unprepare_planes(). Drivers with custom commit_tail
+function do not require changes.
+
+v4:
+ * fix documentation (kernel test robot)
+v3:
+ * add drm_atomic_helper_unprepare_planes() for rolling back
+ * use correct state for end_fb_access
+v2:
+ * fix test in drm_atomic_helper_cleanup_planes()
+
+Reported-by: Alyssa Ross <hi@alyssa.is>
+Closes: https://lore.kernel.org/dri-devel/87leazm0ya.fsf@alyssa.is/
+Suggested-by: Daniel Vetter <daniel@ffwll.ch>
+Fixes: 94d879eaf7fb ("drm/atomic-helper: Add {begin,end}_fb_access to plane helpers")
+Tested-by: Alyssa Ross <hi@alyssa.is>
+Reviewed-by: Alyssa Ross <hi@alyssa.is>
+Signed-off-by: Thomas Zimmermann <tzimmermann@suse.de>
+Cc: <stable@vger.kernel.org> # v6.2+
+Link: https://patchwork.freedesktop.org/patch/msgid/20231204083247.22006-1-tzimmermann@suse.de
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/gpu/drm/drm_atomic_helper.c | 78 ++++++++++++++++++---------
+ drivers/gpu/drm/i915/display/intel_display.c | 2
+ drivers/gpu/drm/nouveau/dispnv50/disp.c | 2
+ include/drm/drm_atomic_helper.h | 2
+ 4 files changed, 56 insertions(+), 28 deletions(-)
+
+--- a/drivers/gpu/drm/drm_atomic_helper.c
++++ b/drivers/gpu/drm/drm_atomic_helper.c
+@@ -2012,7 +2012,7 @@ int drm_atomic_helper_commit(struct drm_
+ return ret;
+
+ drm_atomic_helper_async_commit(dev, state);
+- drm_atomic_helper_cleanup_planes(dev, state);
++ drm_atomic_helper_unprepare_planes(dev, state);
+
+ return 0;
+ }
+@@ -2072,7 +2072,7 @@ int drm_atomic_helper_commit(struct drm_
+ return 0;
+
+ err:
+- drm_atomic_helper_cleanup_planes(dev, state);
++ drm_atomic_helper_unprepare_planes(dev, state);
+ return ret;
+ }
+ EXPORT_SYMBOL(drm_atomic_helper_commit);
+@@ -2650,6 +2650,39 @@ fail_prepare_fb:
+ }
+ EXPORT_SYMBOL(drm_atomic_helper_prepare_planes);
+
++/**
++ * drm_atomic_helper_unprepare_planes - release plane resources on aborts
++ * @dev: DRM device
++ * @state: atomic state object with old state structures
++ *
++ * This function cleans up plane state, specifically framebuffers, from the
++ * atomic state. It undoes the effects of drm_atomic_helper_prepare_planes()
++ * when aborting an atomic commit. For cleaning up after a successful commit
++ * use drm_atomic_helper_cleanup_planes().
++ */
++void drm_atomic_helper_unprepare_planes(struct drm_device *dev,
++ struct drm_atomic_state *state)
++{
++ struct drm_plane *plane;
++ struct drm_plane_state *new_plane_state;
++ int i;
++
++ for_each_new_plane_in_state(state, plane, new_plane_state, i) {
++ const struct drm_plane_helper_funcs *funcs = plane->helper_private;
++
++ if (funcs->end_fb_access)
++ funcs->end_fb_access(plane, new_plane_state);
++ }
++
++ for_each_new_plane_in_state(state, plane, new_plane_state, i) {
++ const struct drm_plane_helper_funcs *funcs = plane->helper_private;
++
++ if (funcs->cleanup_fb)
++ funcs->cleanup_fb(plane, new_plane_state);
++ }
++}
++EXPORT_SYMBOL(drm_atomic_helper_unprepare_planes);
++
+ static bool plane_crtc_active(const struct drm_plane_state *state)
+ {
+ return state->crtc && state->crtc->state->active;
+@@ -2784,6 +2817,17 @@ void drm_atomic_helper_commit_planes(str
+
+ funcs->atomic_flush(crtc, old_state);
+ }
++
++ /*
++ * Signal end of framebuffer access here before hw_done. After hw_done,
++ * a later commit might have already released the plane state.
++ */
++ for_each_old_plane_in_state(old_state, plane, old_plane_state, i) {
++ const struct drm_plane_helper_funcs *funcs = plane->helper_private;
++
++ if (funcs->end_fb_access)
++ funcs->end_fb_access(plane, old_plane_state);
++ }
+ }
+ EXPORT_SYMBOL(drm_atomic_helper_commit_planes);
+
+@@ -2911,40 +2955,22 @@ EXPORT_SYMBOL(drm_atomic_helper_disable_
+ * configuration. Hence the old configuration must be perserved in @old_state to
+ * be able to call this function.
+ *
+- * This function must also be called on the new state when the atomic update
+- * fails at any point after calling drm_atomic_helper_prepare_planes().
++ * This function may not be called on the new state when the atomic update
++ * fails at any point after calling drm_atomic_helper_prepare_planes(). Use
++ * drm_atomic_helper_unprepare_planes() in this case.
+ */
+ void drm_atomic_helper_cleanup_planes(struct drm_device *dev,
+ struct drm_atomic_state *old_state)
+ {
+ struct drm_plane *plane;
+- struct drm_plane_state *old_plane_state, *new_plane_state;
++ struct drm_plane_state *old_plane_state;
+ int i;
+
+- for_each_oldnew_plane_in_state(old_state, plane, old_plane_state, new_plane_state, i) {
++ for_each_old_plane_in_state(old_state, plane, old_plane_state, i) {
+ const struct drm_plane_helper_funcs *funcs = plane->helper_private;
+
+- if (funcs->end_fb_access)
+- funcs->end_fb_access(plane, new_plane_state);
+- }
+-
+- for_each_oldnew_plane_in_state(old_state, plane, old_plane_state, new_plane_state, i) {
+- const struct drm_plane_helper_funcs *funcs;
+- struct drm_plane_state *plane_state;
+-
+- /*
+- * This might be called before swapping when commit is aborted,
+- * in which case we have to cleanup the new state.
+- */
+- if (old_plane_state == plane->state)
+- plane_state = new_plane_state;
+- else
+- plane_state = old_plane_state;
+-
+- funcs = plane->helper_private;
+-
+ if (funcs->cleanup_fb)
+- funcs->cleanup_fb(plane, plane_state);
++ funcs->cleanup_fb(plane, old_plane_state);
+ }
+ }
+ EXPORT_SYMBOL(drm_atomic_helper_cleanup_planes);
+--- a/drivers/gpu/drm/i915/display/intel_display.c
++++ b/drivers/gpu/drm/i915/display/intel_display.c
+@@ -7279,7 +7279,7 @@ int intel_atomic_commit(struct drm_devic
+ for_each_new_intel_crtc_in_state(state, crtc, new_crtc_state, i)
+ intel_color_cleanup_commit(new_crtc_state);
+
+- drm_atomic_helper_cleanup_planes(dev, &state->base);
++ drm_atomic_helper_unprepare_planes(dev, &state->base);
+ intel_runtime_pm_put(&dev_priv->runtime_pm, state->wakeref);
+ return ret;
+ }
+--- a/drivers/gpu/drm/nouveau/dispnv50/disp.c
++++ b/drivers/gpu/drm/nouveau/dispnv50/disp.c
+@@ -2310,7 +2310,7 @@ nv50_disp_atomic_commit(struct drm_devic
+
+ err_cleanup:
+ if (ret)
+- drm_atomic_helper_cleanup_planes(dev, state);
++ drm_atomic_helper_unprepare_planes(dev, state);
+ done:
+ pm_runtime_put_autosuspend(dev->dev);
+ return ret;
+--- a/include/drm/drm_atomic_helper.h
++++ b/include/drm/drm_atomic_helper.h
+@@ -97,6 +97,8 @@ void drm_atomic_helper_commit_modeset_en
+
+ int drm_atomic_helper_prepare_planes(struct drm_device *dev,
+ struct drm_atomic_state *state);
++void drm_atomic_helper_unprepare_planes(struct drm_device *dev,
++ struct drm_atomic_state *state);
+
+ #define DRM_PLANE_COMMIT_ACTIVE_ONLY BIT(0)
+ #define DRM_PLANE_COMMIT_NO_DISABLE_AFTER_MODESET BIT(1)
--- /dev/null
+From 7cf82b25dd91d7f330d9df2de868caca14289ba1 Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= <ville.syrjala@linux.intel.com>
+Date: Mon, 27 Nov 2023 16:50:26 +0200
+Subject: drm/i915/mst: Fix .mode_valid_ctx() return values
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Ville Syrjälä <ville.syrjala@linux.intel.com>
+
+commit 7cf82b25dd91d7f330d9df2de868caca14289ba1 upstream.
+
+.mode_valid_ctx() returns an errno, not the mode status. Fix
+the code to do the right thing.
+
+Cc: stable@vger.kernel.org
+Cc: Stanislav Lisovskiy <stanislav.lisovskiy@intel.com>
+Fixes: d51f25eb479a ("drm/i915: Add DSC support to MST path")
+Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
+Link: https://patchwork.freedesktop.org/patch/msgid/20231127145028.4899-2-ville.syrjala@linux.intel.com
+Reviewed-by: Jani Nikula <jani.nikula@intel.com>
+(cherry picked from commit c1799032d2ef6616113b733428dfaa2199a5604b)
+Signed-off-by: Jani Nikula <jani.nikula@intel.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/gpu/drm/i915/display/intel_dp_mst.c | 12 ++++++++----
+ 1 file changed, 8 insertions(+), 4 deletions(-)
+
+--- a/drivers/gpu/drm/i915/display/intel_dp_mst.c
++++ b/drivers/gpu/drm/i915/display/intel_dp_mst.c
+@@ -988,11 +988,15 @@ intel_dp_mst_mode_valid_ctx(struct drm_c
+ * Big joiner configuration needs DSC for TGL which is not true for
+ * XE_LPD where uncompressed joiner is supported.
+ */
+- if (DISPLAY_VER(dev_priv) < 13 && bigjoiner && !dsc)
+- return MODE_CLOCK_HIGH;
++ if (DISPLAY_VER(dev_priv) < 13 && bigjoiner && !dsc) {
++ *status = MODE_CLOCK_HIGH;
++ return 0;
++ }
+
+- if (mode_rate > max_rate && !dsc)
+- return MODE_CLOCK_HIGH;
++ if (mode_rate > max_rate && !dsc) {
++ *status = MODE_CLOCK_HIGH;
++ return 0;
++ }
+
+ *status = intel_mode_valid_max_plane_size(dev_priv, mode, false);
+ return 0;
--- /dev/null
+From dd7eb65c493615fda7d459501c3d4a46e00ea5ba Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= <ville.syrjala@linux.intel.com>
+Date: Mon, 27 Nov 2023 16:50:27 +0200
+Subject: drm/i915/mst: Reject modes that require the bigjoiner
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Ville Syrjälä <ville.syrjala@linux.intel.com>
+
+commit dd7eb65c493615fda7d459501c3d4a46e00ea5ba upstream.
+
+We have no bigjoiner support in the MST code, so .mode_valid()
+pretending otherwise is just going to result black screens for
+users. Reject any mode that needs the joiner.
+
+Cc: stable@vger.kernel.org
+Cc: Stanislav Lisovskiy <stanislav.lisovskiy@intel.com>
+Fixes: d51f25eb479a ("drm/i915: Add DSC support to MST path")
+Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
+Link: https://patchwork.freedesktop.org/patch/msgid/20231127145028.4899-3-ville.syrjala@linux.intel.com
+Reviewed-by: Jani Nikula <jani.nikula@intel.com>
+(cherry picked from commit 9c058492b16f90bb772cb0dad567e8acc68e155d)
+Signed-off-by: Jani Nikula <jani.nikula@intel.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/gpu/drm/i915/display/intel_dp_mst.c | 4 ++++
+ 1 file changed, 4 insertions(+)
+
+--- a/drivers/gpu/drm/i915/display/intel_dp_mst.c
++++ b/drivers/gpu/drm/i915/display/intel_dp_mst.c
+@@ -955,6 +955,10 @@ intel_dp_mst_mode_valid_ctx(struct drm_c
+ if (intel_dp_need_bigjoiner(intel_dp, mode->hdisplay, target_clock)) {
+ bigjoiner = true;
+ max_dotclk *= 2;
++
++ /* TODO: add support for bigjoiner */
++ *status = MODE_CLOCK_HIGH;
++ return 0;
+ }
+
+ if (DISPLAY_VER(dev_priv) >= 10 &&
--- /dev/null
+From 20c2dbff342aec13bf93c2f6c951da198916a455 Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= <ville.syrjala@linux.intel.com>
+Date: Mon, 27 Nov 2023 16:50:25 +0200
+Subject: drm/i915: Skip some timing checks on BXT/GLK DSI transcoders
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Ville Syrjälä <ville.syrjala@linux.intel.com>
+
+commit 20c2dbff342aec13bf93c2f6c951da198916a455 upstream.
+
+Apparently some BXT/GLK systems have DSI panels whose timings
+don't agree with the normal cpu transcoder hblank>=32 limitation.
+This is perhaps fine as there are no specific hblank/etc. limits
+listed for the BXT/GLK DSI transcoders.
+
+Move those checks out from the global intel_mode_valid() into
+into connector specific .mode_valid() hooks, skipping BXT/GLK
+DSI connectors. We'll leave the basic [hv]display/[hv]total
+checks in intel_mode_valid() as those seem like sensible upper
+limits regardless of the transcoder used.
+
+Cc: stable@vger.kernel.org
+Closes: https://gitlab.freedesktop.org/drm/intel/-/issues/9720
+Fixes: 8f4b1068e7fc ("drm/i915: Check some transcoder timing minimum limits")
+Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
+Link: https://patchwork.freedesktop.org/patch/msgid/20231127145028.4899-1-ville.syrjala@linux.intel.com
+Reviewed-by: Jani Nikula <jani.nikula@intel.com>
+(cherry picked from commit e0ef2daa8ca8ce4dbc2fd0959e383b753a87fd7d)
+Signed-off-by: Jani Nikula <jani.nikula@intel.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/gpu/drm/i915/display/icl_dsi.c | 7 +++++++
+ drivers/gpu/drm/i915/display/intel_crt.c | 5 +++++
+ drivers/gpu/drm/i915/display/intel_display.c | 10 ++++++++++
+ drivers/gpu/drm/i915/display/intel_display.h | 3 +++
+ drivers/gpu/drm/i915/display/intel_dp.c | 4 ++++
+ drivers/gpu/drm/i915/display/intel_dp_mst.c | 4 ++++
+ drivers/gpu/drm/i915/display/intel_dvo.c | 6 ++++++
+ drivers/gpu/drm/i915/display/intel_hdmi.c | 4 ++++
+ drivers/gpu/drm/i915/display/intel_lvds.c | 5 +++++
+ drivers/gpu/drm/i915/display/intel_sdvo.c | 8 +++++++-
+ drivers/gpu/drm/i915/display/intel_tv.c | 8 +++++++-
+ drivers/gpu/drm/i915/display/vlv_dsi.c | 18 +++++++++++++++++-
+ 12 files changed, 79 insertions(+), 3 deletions(-)
+
+--- a/drivers/gpu/drm/i915/display/icl_dsi.c
++++ b/drivers/gpu/drm/i915/display/icl_dsi.c
+@@ -1440,6 +1440,13 @@ static void gen11_dsi_post_disable(struc
+ static enum drm_mode_status gen11_dsi_mode_valid(struct drm_connector *connector,
+ struct drm_display_mode *mode)
+ {
++ struct drm_i915_private *i915 = to_i915(connector->dev);
++ enum drm_mode_status status;
++
++ status = intel_cpu_transcoder_mode_valid(i915, mode);
++ if (status != MODE_OK)
++ return status;
++
+ /* FIXME: DSC? */
+ return intel_dsi_mode_valid(connector, mode);
+ }
+--- a/drivers/gpu/drm/i915/display/intel_crt.c
++++ b/drivers/gpu/drm/i915/display/intel_crt.c
+@@ -348,8 +348,13 @@ intel_crt_mode_valid(struct drm_connecto
+ struct drm_device *dev = connector->dev;
+ struct drm_i915_private *dev_priv = to_i915(dev);
+ int max_dotclk = dev_priv->max_dotclk_freq;
++ enum drm_mode_status status;
+ int max_clock;
+
++ status = intel_cpu_transcoder_mode_valid(dev_priv, mode);
++ if (status != MODE_OK)
++ return status;
++
+ if (mode->flags & DRM_MODE_FLAG_DBLSCAN)
+ return MODE_NO_DBLESCAN;
+
+--- a/drivers/gpu/drm/i915/display/intel_display.c
++++ b/drivers/gpu/drm/i915/display/intel_display.c
+@@ -7660,6 +7660,16 @@ enum drm_mode_status intel_mode_valid(st
+ mode->vtotal > vtotal_max)
+ return MODE_V_ILLEGAL;
+
++ return MODE_OK;
++}
++
++enum drm_mode_status intel_cpu_transcoder_mode_valid(struct drm_i915_private *dev_priv,
++ const struct drm_display_mode *mode)
++{
++ /*
++ * Additional transcoder timing limits,
++ * excluding BXT/GLK DSI transcoders.
++ */
+ if (DISPLAY_VER(dev_priv) >= 5) {
+ if (mode->hdisplay < 64 ||
+ mode->htotal - mode->hdisplay < 32)
+--- a/drivers/gpu/drm/i915/display/intel_display.h
++++ b/drivers/gpu/drm/i915/display/intel_display.h
+@@ -405,6 +405,9 @@ enum drm_mode_status
+ intel_mode_valid_max_plane_size(struct drm_i915_private *dev_priv,
+ const struct drm_display_mode *mode,
+ bool bigjoiner);
++enum drm_mode_status
++intel_cpu_transcoder_mode_valid(struct drm_i915_private *i915,
++ const struct drm_display_mode *mode);
+ enum phy intel_port_to_phy(struct drm_i915_private *i915, enum port port);
+ bool is_trans_port_sync_mode(const struct intel_crtc_state *state);
+ bool is_trans_port_sync_master(const struct intel_crtc_state *state);
+--- a/drivers/gpu/drm/i915/display/intel_dp.c
++++ b/drivers/gpu/drm/i915/display/intel_dp.c
+@@ -1127,6 +1127,10 @@ intel_dp_mode_valid(struct drm_connector
+ enum drm_mode_status status;
+ bool dsc = false, bigjoiner = false;
+
++ status = intel_cpu_transcoder_mode_valid(dev_priv, mode);
++ if (status != MODE_OK)
++ return status;
++
+ if (mode->flags & DRM_MODE_FLAG_DBLCLK)
+ return MODE_H_ILLEGAL;
+
+--- a/drivers/gpu/drm/i915/display/intel_dp_mst.c
++++ b/drivers/gpu/drm/i915/display/intel_dp_mst.c
+@@ -921,6 +921,10 @@ intel_dp_mst_mode_valid_ctx(struct drm_c
+ return 0;
+ }
+
++ *status = intel_cpu_transcoder_mode_valid(dev_priv, mode);
++ if (*status != MODE_OK)
++ return 0;
++
+ if (mode->flags & DRM_MODE_FLAG_DBLSCAN) {
+ *status = MODE_NO_DBLESCAN;
+ return 0;
+--- a/drivers/gpu/drm/i915/display/intel_dvo.c
++++ b/drivers/gpu/drm/i915/display/intel_dvo.c
+@@ -217,11 +217,17 @@ intel_dvo_mode_valid(struct drm_connecto
+ struct drm_display_mode *mode)
+ {
+ struct intel_connector *connector = to_intel_connector(_connector);
++ struct drm_i915_private *i915 = to_i915(connector->base.dev);
+ struct intel_dvo *intel_dvo = intel_attached_dvo(connector);
+ const struct drm_display_mode *fixed_mode =
+ intel_panel_fixed_mode(connector, mode);
+ int max_dotclk = to_i915(connector->base.dev)->max_dotclk_freq;
+ int target_clock = mode->clock;
++ enum drm_mode_status status;
++
++ status = intel_cpu_transcoder_mode_valid(i915, mode);
++ if (status != MODE_OK)
++ return status;
+
+ if (mode->flags & DRM_MODE_FLAG_DBLSCAN)
+ return MODE_NO_DBLESCAN;
+--- a/drivers/gpu/drm/i915/display/intel_hdmi.c
++++ b/drivers/gpu/drm/i915/display/intel_hdmi.c
+@@ -1986,6 +1986,10 @@ intel_hdmi_mode_valid(struct drm_connect
+ bool ycbcr_420_only;
+ enum intel_output_format sink_format;
+
++ status = intel_cpu_transcoder_mode_valid(dev_priv, mode);
++ if (status != MODE_OK)
++ return status;
++
+ if ((mode->flags & DRM_MODE_FLAG_3D_MASK) == DRM_MODE_FLAG_3D_FRAME_PACKING)
+ clock *= 2;
+
+--- a/drivers/gpu/drm/i915/display/intel_lvds.c
++++ b/drivers/gpu/drm/i915/display/intel_lvds.c
+@@ -389,11 +389,16 @@ intel_lvds_mode_valid(struct drm_connect
+ struct drm_display_mode *mode)
+ {
+ struct intel_connector *connector = to_intel_connector(_connector);
++ struct drm_i915_private *i915 = to_i915(connector->base.dev);
+ const struct drm_display_mode *fixed_mode =
+ intel_panel_fixed_mode(connector, mode);
+ int max_pixclk = to_i915(connector->base.dev)->max_dotclk_freq;
+ enum drm_mode_status status;
+
++ status = intel_cpu_transcoder_mode_valid(i915, mode);
++ if (status != MODE_OK)
++ return status;
++
+ if (mode->flags & DRM_MODE_FLAG_DBLSCAN)
+ return MODE_NO_DBLESCAN;
+
+--- a/drivers/gpu/drm/i915/display/intel_sdvo.c
++++ b/drivers/gpu/drm/i915/display/intel_sdvo.c
+@@ -1906,13 +1906,19 @@ static enum drm_mode_status
+ intel_sdvo_mode_valid(struct drm_connector *connector,
+ struct drm_display_mode *mode)
+ {
++ struct drm_i915_private *i915 = to_i915(connector->dev);
+ struct intel_sdvo *intel_sdvo = intel_attached_sdvo(to_intel_connector(connector));
+ struct intel_sdvo_connector *intel_sdvo_connector =
+ to_intel_sdvo_connector(connector);
+- int max_dotclk = to_i915(connector->dev)->max_dotclk_freq;
+ bool has_hdmi_sink = intel_has_hdmi_sink(intel_sdvo_connector, connector->state);
++ int max_dotclk = i915->max_dotclk_freq;
++ enum drm_mode_status status;
+ int clock = mode->clock;
+
++ status = intel_cpu_transcoder_mode_valid(i915, mode);
++ if (status != MODE_OK)
++ return status;
++
+ if (mode->flags & DRM_MODE_FLAG_DBLSCAN)
+ return MODE_NO_DBLESCAN;
+
+--- a/drivers/gpu/drm/i915/display/intel_tv.c
++++ b/drivers/gpu/drm/i915/display/intel_tv.c
+@@ -958,8 +958,14 @@ static enum drm_mode_status
+ intel_tv_mode_valid(struct drm_connector *connector,
+ struct drm_display_mode *mode)
+ {
++ struct drm_i915_private *i915 = to_i915(connector->dev);
+ const struct tv_mode *tv_mode = intel_tv_mode_find(connector->state);
+- int max_dotclk = to_i915(connector->dev)->max_dotclk_freq;
++ int max_dotclk = i915->max_dotclk_freq;
++ enum drm_mode_status status;
++
++ status = intel_cpu_transcoder_mode_valid(i915, mode);
++ if (status != MODE_OK)
++ return status;
+
+ if (mode->flags & DRM_MODE_FLAG_DBLSCAN)
+ return MODE_NO_DBLESCAN;
+--- a/drivers/gpu/drm/i915/display/vlv_dsi.c
++++ b/drivers/gpu/drm/i915/display/vlv_dsi.c
+@@ -1540,9 +1540,25 @@ static const struct drm_encoder_funcs in
+ .destroy = intel_dsi_encoder_destroy,
+ };
+
++static enum drm_mode_status vlv_dsi_mode_valid(struct drm_connector *connector,
++ struct drm_display_mode *mode)
++{
++ struct drm_i915_private *i915 = to_i915(connector->dev);
++
++ if (IS_VALLEYVIEW(i915) || IS_CHERRYVIEW(i915)) {
++ enum drm_mode_status status;
++
++ status = intel_cpu_transcoder_mode_valid(i915, mode);
++ if (status != MODE_OK)
++ return status;
++ }
++
++ return intel_dsi_mode_valid(connector, mode);
++}
++
+ static const struct drm_connector_helper_funcs intel_dsi_connector_helper_funcs = {
+ .get_modes = intel_dsi_get_modes,
+- .mode_valid = intel_dsi_mode_valid,
++ .mode_valid = vlv_dsi_mode_valid,
+ .atomic_check = intel_digital_connector_atomic_check,
+ };
+
--- /dev/null
+From 73424d00dc63ba681856e06cfb0a5abbdb62e2b5 Mon Sep 17 00:00:00 2001
+From: Su Hui <suhui@nfschina.com>
+Date: Thu, 30 Nov 2023 11:40:18 +0800
+Subject: highmem: fix a memory copy problem in memcpy_from_folio
+
+From: Su Hui <suhui@nfschina.com>
+
+commit 73424d00dc63ba681856e06cfb0a5abbdb62e2b5 upstream.
+
+Clang static checker complains that value stored to 'from' is never read.
+And memcpy_from_folio() only copy the last chunk memory from folio to
+destination. Use 'to += chunk' to replace 'from += chunk' to fix this
+typo problem.
+
+Link: https://lkml.kernel.org/r/20231130034017.1210429-1-suhui@nfschina.com
+Fixes: b23d03ef7af5 ("highmem: add memcpy_to_folio() and memcpy_from_folio()")
+Signed-off-by: Su Hui <suhui@nfschina.com>
+Reviewed-by: Matthew Wilcox (Oracle) <willy@infradead.org>
+Cc: Ira Weiny <ira.weiny@intel.com>
+Cc: Jiaqi Yan <jiaqiyan@google.com>
+Cc: Nathan Chancellor <nathan@kernel.org>
+Cc: Nick Desaulniers <ndesaulniers@google.com>
+Cc: Peter Collingbourne <pcc@google.com>
+Cc: Tom Rix <trix@redhat.com>
+Cc: Tony Luck <tony.luck@intel.com>
+Cc: <stable@vger.kernel.org>
+Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ include/linux/highmem.h | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/include/linux/highmem.h b/include/linux/highmem.h
+index 4cacc0e43b51..be20cff4ba73 100644
+--- a/include/linux/highmem.h
++++ b/include/linux/highmem.h
+@@ -454,7 +454,7 @@ static inline void memcpy_from_folio(char *to, struct folio *folio,
+ memcpy(to, from, chunk);
+ kunmap_local(from);
+
+- from += chunk;
++ to += chunk;
+ offset += chunk;
+ len -= chunk;
+ } while (len > 0);
+--
+2.43.0
+
--- /dev/null
+From 187da0f8250aa94bd96266096aef6f694e0b4cd2 Mon Sep 17 00:00:00 2001
+From: Mike Kravetz <mike.kravetz@oracle.com>
+Date: Mon, 13 Nov 2023 17:20:33 -0800
+Subject: hugetlb: fix null-ptr-deref in hugetlb_vma_lock_write
+
+From: Mike Kravetz <mike.kravetz@oracle.com>
+
+commit 187da0f8250aa94bd96266096aef6f694e0b4cd2 upstream.
+
+The routine __vma_private_lock tests for the existence of a reserve map
+associated with a private hugetlb mapping. A pointer to the reserve map
+is in vma->vm_private_data. __vma_private_lock was checking the pointer
+for NULL. However, it is possible that the low bits of the pointer could
+be used as flags. In such instances, vm_private_data is not NULL and not
+a valid pointer. This results in the null-ptr-deref reported by syzbot:
+
+general protection fault, probably for non-canonical address 0xdffffc000000001d:
+ 0000 [#1] PREEMPT SMP KASAN
+KASAN: null-ptr-deref in range [0x00000000000000e8-0x00000000000000ef]
+CPU: 0 PID: 5048 Comm: syz-executor139 Not tainted 6.6.0-rc7-syzkaller-00142-g88
+8cf78c29e2 #0
+Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS Google 1
+0/09/2023
+RIP: 0010:__lock_acquire+0x109/0x5de0 kernel/locking/lockdep.c:5004
+...
+Call Trace:
+ <TASK>
+ lock_acquire kernel/locking/lockdep.c:5753 [inline]
+ lock_acquire+0x1ae/0x510 kernel/locking/lockdep.c:5718
+ down_write+0x93/0x200 kernel/locking/rwsem.c:1573
+ hugetlb_vma_lock_write mm/hugetlb.c:300 [inline]
+ hugetlb_vma_lock_write+0xae/0x100 mm/hugetlb.c:291
+ __hugetlb_zap_begin+0x1e9/0x2b0 mm/hugetlb.c:5447
+ hugetlb_zap_begin include/linux/hugetlb.h:258 [inline]
+ unmap_vmas+0x2f4/0x470 mm/memory.c:1733
+ exit_mmap+0x1ad/0xa60 mm/mmap.c:3230
+ __mmput+0x12a/0x4d0 kernel/fork.c:1349
+ mmput+0x62/0x70 kernel/fork.c:1371
+ exit_mm kernel/exit.c:567 [inline]
+ do_exit+0x9ad/0x2a20 kernel/exit.c:861
+ __do_sys_exit kernel/exit.c:991 [inline]
+ __se_sys_exit kernel/exit.c:989 [inline]
+ __x64_sys_exit+0x42/0x50 kernel/exit.c:989
+ do_syscall_x64 arch/x86/entry/common.c:50 [inline]
+ do_syscall_64+0x38/0xb0 arch/x86/entry/common.c:80
+ entry_SYSCALL_64_after_hwframe+0x63/0xcd
+
+Mask off low bit flags before checking for NULL pointer. In addition, the
+reserve map only 'belongs' to the OWNER (parent in parent/child
+relationships) so also check for the OWNER flag.
+
+Link: https://lkml.kernel.org/r/20231114012033.259600-1-mike.kravetz@oracle.com
+Reported-by: syzbot+6ada951e7c0f7bc8a71e@syzkaller.appspotmail.com
+Closes: https://lore.kernel.org/linux-mm/00000000000078d1e00608d7878b@google.com/
+Fixes: bf4916922c60 ("hugetlbfs: extend hugetlb_vma_lock to private VMAs")
+Signed-off-by: Mike Kravetz <mike.kravetz@oracle.com>
+Reviewed-by: Rik van Riel <riel@surriel.com>
+Cc: Edward Adam Davis <eadavis@qq.com>
+Cc: Muchun Song <muchun.song@linux.dev>
+Cc: Nathan Chancellor <nathan@kernel.org>
+Cc: Nick Desaulniers <ndesaulniers@google.com>
+Cc: Tom Rix <trix@redhat.com>
+Cc: <stable@vger.kernel.org>
+Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ include/linux/hugetlb.h | 5 +----
+ mm/hugetlb.c | 7 +++++++
+ 2 files changed, 8 insertions(+), 4 deletions(-)
+
+--- a/include/linux/hugetlb.h
++++ b/include/linux/hugetlb.h
+@@ -1265,10 +1265,7 @@ static inline bool __vma_shareable_lock(
+ return (vma->vm_flags & VM_MAYSHARE) && vma->vm_private_data;
+ }
+
+-static inline bool __vma_private_lock(struct vm_area_struct *vma)
+-{
+- return (!(vma->vm_flags & VM_MAYSHARE)) && vma->vm_private_data;
+-}
++bool __vma_private_lock(struct vm_area_struct *vma);
+
+ /*
+ * Safe version of huge_pte_offset() to check the locks. See comments
+--- a/mm/hugetlb.c
++++ b/mm/hugetlb.c
+@@ -1189,6 +1189,13 @@ static int is_vma_resv_set(struct vm_are
+ return (get_vma_private_data(vma) & flag) != 0;
+ }
+
++bool __vma_private_lock(struct vm_area_struct *vma)
++{
++ return !(vma->vm_flags & VM_MAYSHARE) &&
++ get_vma_private_data(vma) & ~HPAGE_RESV_MASK &&
++ is_vma_resv_set(vma, HPAGE_RESV_OWNER);
++}
++
+ void hugetlb_dup_vma_private(struct vm_area_struct *vma)
+ {
+ VM_BUG_ON_VMA(!is_vm_hugetlb_page(vma), vma);
--- /dev/null
+From fe2b1226656afae56702d1d84c6900f6b67df297 Mon Sep 17 00:00:00 2001
+From: Heiner Kallweit <hkallweit1@gmail.com>
+Date: Fri, 1 Dec 2023 11:23:22 +0100
+Subject: leds: trigger: netdev: fix RTNL handling to prevent potential deadlock
+
+From: Heiner Kallweit <hkallweit1@gmail.com>
+
+commit fe2b1226656afae56702d1d84c6900f6b67df297 upstream.
+
+When working on LED support for r8169 I got the following lockdep
+warning. Easiest way to prevent this scenario seems to be to take
+the RTNL lock before the trigger_data lock in set_device_name().
+
+======================================================
+WARNING: possible circular locking dependency detected
+6.7.0-rc2-next-20231124+ #2 Not tainted
+------------------------------------------------------
+bash/383 is trying to acquire lock:
+ffff888103aa1c68 (&trigger_data->lock){+.+.}-{3:3}, at: netdev_trig_notify+0xec/0x190 [ledtrig_netdev]
+
+but task is already holding lock:
+ffffffff8cddf808 (rtnl_mutex){+.+.}-{3:3}, at: rtnl_lock+0x12/0x20
+
+which lock already depends on the new lock.
+
+the existing dependency chain (in reverse order) is:
+
+-> #1 (rtnl_mutex){+.+.}-{3:3}:
+ __mutex_lock+0x9b/0xb50
+ mutex_lock_nested+0x16/0x20
+ rtnl_lock+0x12/0x20
+ set_device_name+0xa9/0x120 [ledtrig_netdev]
+ netdev_trig_activate+0x1a1/0x230 [ledtrig_netdev]
+ led_trigger_set+0x172/0x2c0
+ led_trigger_write+0xf1/0x140
+ sysfs_kf_bin_write+0x5d/0x80
+ kernfs_fop_write_iter+0x15d/0x210
+ vfs_write+0x1f0/0x510
+ ksys_write+0x6c/0xf0
+ __x64_sys_write+0x14/0x20
+ do_syscall_64+0x3f/0xf0
+ entry_SYSCALL_64_after_hwframe+0x6c/0x74
+
+-> #0 (&trigger_data->lock){+.+.}-{3:3}:
+ __lock_acquire+0x1459/0x25a0
+ lock_acquire+0xc8/0x2d0
+ __mutex_lock+0x9b/0xb50
+ mutex_lock_nested+0x16/0x20
+ netdev_trig_notify+0xec/0x190 [ledtrig_netdev]
+ call_netdevice_register_net_notifiers+0x5a/0x100
+ register_netdevice_notifier+0x85/0x120
+ netdev_trig_activate+0x1d4/0x230 [ledtrig_netdev]
+ led_trigger_set+0x172/0x2c0
+ led_trigger_write+0xf1/0x140
+ sysfs_kf_bin_write+0x5d/0x80
+ kernfs_fop_write_iter+0x15d/0x210
+ vfs_write+0x1f0/0x510
+ ksys_write+0x6c/0xf0
+ __x64_sys_write+0x14/0x20
+ do_syscall_64+0x3f/0xf0
+ entry_SYSCALL_64_after_hwframe+0x6c/0x74
+
+other info that might help us debug this:
+
+ Possible unsafe locking scenario:
+
+ CPU0 CPU1
+ ---- ----
+ lock(rtnl_mutex);
+ lock(&trigger_data->lock);
+ lock(rtnl_mutex);
+ lock(&trigger_data->lock);
+
+ *** DEADLOCK ***
+
+8 locks held by bash/383:
+ #0: ffff888103ff33f0 (sb_writers#3){.+.+}-{0:0}, at: ksys_write+0x6c/0xf0
+ #1: ffff888103aa1e88 (&of->mutex){+.+.}-{3:3}, at: kernfs_fop_write_iter+0x114/0x210
+ #2: ffff8881036f1890 (kn->active#82){.+.+}-{0:0}, at: kernfs_fop_write_iter+0x11d/0x210
+ #3: ffff888108e2c358 (&led_cdev->led_access){+.+.}-{3:3}, at: led_trigger_write+0x30/0x140
+ #4: ffffffff8cdd9e10 (triggers_list_lock){++++}-{3:3}, at: led_trigger_write+0x75/0x140
+ #5: ffff888108e2c270 (&led_cdev->trigger_lock){++++}-{3:3}, at: led_trigger_write+0xe3/0x140
+ #6: ffffffff8cdde3d0 (pernet_ops_rwsem){++++}-{3:3}, at: register_netdevice_notifier+0x1c/0x120
+ #7: ffffffff8cddf808 (rtnl_mutex){+.+.}-{3:3}, at: rtnl_lock+0x12/0x20
+
+stack backtrace:
+CPU: 0 PID: 383 Comm: bash Not tainted 6.7.0-rc2-next-20231124+ #2
+Hardware name: Default string Default string/Default string, BIOS ADLN.M6.SODIMM.ZB.CY.015 08/08/2023
+Call Trace:
+ <TASK>
+ dump_stack_lvl+0x5c/0xd0
+ dump_stack+0x10/0x20
+ print_circular_bug+0x2dd/0x410
+ check_noncircular+0x131/0x150
+ __lock_acquire+0x1459/0x25a0
+ lock_acquire+0xc8/0x2d0
+ ? netdev_trig_notify+0xec/0x190 [ledtrig_netdev]
+ __mutex_lock+0x9b/0xb50
+ ? netdev_trig_notify+0xec/0x190 [ledtrig_netdev]
+ ? __this_cpu_preempt_check+0x13/0x20
+ ? netdev_trig_notify+0xec/0x190 [ledtrig_netdev]
+ ? __cancel_work_timer+0x11c/0x1b0
+ ? __mutex_lock+0x123/0xb50
+ mutex_lock_nested+0x16/0x20
+ ? mutex_lock_nested+0x16/0x20
+ netdev_trig_notify+0xec/0x190 [ledtrig_netdev]
+ call_netdevice_register_net_notifiers+0x5a/0x100
+ register_netdevice_notifier+0x85/0x120
+ netdev_trig_activate+0x1d4/0x230 [ledtrig_netdev]
+ led_trigger_set+0x172/0x2c0
+ ? preempt_count_add+0x49/0xc0
+ led_trigger_write+0xf1/0x140
+ sysfs_kf_bin_write+0x5d/0x80
+ kernfs_fop_write_iter+0x15d/0x210
+ vfs_write+0x1f0/0x510
+ ksys_write+0x6c/0xf0
+ __x64_sys_write+0x14/0x20
+ do_syscall_64+0x3f/0xf0
+ entry_SYSCALL_64_after_hwframe+0x6c/0x74
+RIP: 0033:0x7f269055d034
+Code: c7 00 16 00 00 00 b8 ff ff ff ff c3 66 2e 0f 1f 84 00 00 00 00 00 f3 0f 1e fa 80 3d 35 c3 0d 00 00 74 13 b8 01 00 00 00 0f 05 <48> 3d 00 f0 ff ff 77 54 c3 0f 1f 00 48 83 ec 28 48 89 54 24 18 48
+RSP: 002b:00007ffddb7ef748 EFLAGS: 00000202 ORIG_RAX: 0000000000000001
+RAX: ffffffffffffffda RBX: 0000000000000007 RCX: 00007f269055d034
+RDX: 0000000000000007 RSI: 000055bf5f4af3c0 RDI: 0000000000000001
+RBP: 000055bf5f4af3c0 R08: 0000000000000073 R09: 0000000000000001
+R10: 0000000000000000 R11: 0000000000000202 R12: 0000000000000007
+R13: 00007f26906325c0 R14: 00007f269062ff20 R15: 0000000000000000
+ </TASK>
+
+Fixes: d5e01266e7f5 ("leds: trigger: netdev: add additional specific link speed mode")
+Cc: stable@vger.kernel.org
+Signed-off-by: Heiner Kallweit <hkallweit1@gmail.com>
+Reviewed-by: Andrew Lunn <andrew@lunn.ch>
+Acked-by: Lee Jones <lee@kernel.org>
+Link: https://lore.kernel.org/r/fb5c8294-2a10-4bf5-8f10-3d2b77d2757e@gmail.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/leds/trigger/ledtrig-netdev.c | 11 +++++++----
+ 1 file changed, 7 insertions(+), 4 deletions(-)
+
+diff --git a/drivers/leds/trigger/ledtrig-netdev.c b/drivers/leds/trigger/ledtrig-netdev.c
+index e358e77e4b38..d76214fa9ad8 100644
+--- a/drivers/leds/trigger/ledtrig-netdev.c
++++ b/drivers/leds/trigger/ledtrig-netdev.c
+@@ -226,6 +226,11 @@ static int set_device_name(struct led_netdev_data *trigger_data,
+
+ cancel_delayed_work_sync(&trigger_data->work);
+
++ /*
++ * Take RTNL lock before trigger_data lock to prevent potential
++ * deadlock with netdev notifier registration.
++ */
++ rtnl_lock();
+ mutex_lock(&trigger_data->lock);
+
+ if (trigger_data->net_dev) {
+@@ -245,16 +250,14 @@ static int set_device_name(struct led_netdev_data *trigger_data,
+ trigger_data->carrier_link_up = false;
+ trigger_data->link_speed = SPEED_UNKNOWN;
+ trigger_data->duplex = DUPLEX_UNKNOWN;
+- if (trigger_data->net_dev != NULL) {
+- rtnl_lock();
++ if (trigger_data->net_dev)
+ get_device_state(trigger_data);
+- rtnl_unlock();
+- }
+
+ trigger_data->last_activity = 0;
+
+ set_baseline_state(trigger_data);
+ mutex_unlock(&trigger_data->lock);
++ rtnl_unlock();
+
+ return 0;
+ }
+--
+2.43.0
+
--- /dev/null
+From 0263f92fadbb9d294d5971ac57743f882c93b2b3 Mon Sep 17 00:00:00 2001
+From: Ming Lei <ming.lei@redhat.com>
+Date: Mon, 20 Nov 2023 16:35:59 +0800
+Subject: lib/group_cpus.c: avoid acquiring cpu hotplug lock in group_cpus_evenly
+
+From: Ming Lei <ming.lei@redhat.com>
+
+commit 0263f92fadbb9d294d5971ac57743f882c93b2b3 upstream.
+
+group_cpus_evenly() could be part of storage driver's error handler, such
+as nvme driver, when may happen during CPU hotplug, in which storage queue
+has to drain its pending IOs because all CPUs associated with the queue
+are offline and the queue is becoming inactive. And handling IO needs
+error handler to provide forward progress.
+
+Then deadlock is caused:
+
+1) inside CPU hotplug handler, CPU hotplug lock is held, and blk-mq's
+ handler is waiting for inflight IO
+
+2) error handler is waiting for CPU hotplug lock
+
+3) inflight IO can't be completed in blk-mq's CPU hotplug handler
+ because error handling can't provide forward progress.
+
+Solve the deadlock by not holding CPU hotplug lock in group_cpus_evenly(),
+in which two stage spreads are taken: 1) the 1st stage is over all present
+CPUs; 2) the end stage is over all other CPUs.
+
+Turns out the two stage spread just needs consistent 'cpu_present_mask',
+and remove the CPU hotplug lock by storing it into one local cache. This
+way doesn't change correctness, because all CPUs are still covered.
+
+Link: https://lkml.kernel.org/r/20231120083559.285174-1-ming.lei@redhat.com
+Signed-off-by: Ming Lei <ming.lei@redhat.com>
+Reported-by: Yi Zhang <yi.zhang@redhat.com>
+Reported-by: Guangwu Zhang <guazhang@redhat.com>
+Tested-by: Guangwu Zhang <guazhang@redhat.com>
+Reviewed-by: Chengming Zhou <zhouchengming@bytedance.com>
+Reviewed-by: Jens Axboe <axboe@kernel.dk>
+Cc: Keith Busch <kbusch@kernel.org>
+Cc: <stable@vger.kernel.org>
+Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ lib/group_cpus.c | 22 ++++++++++++++++------
+ 1 file changed, 16 insertions(+), 6 deletions(-)
+
+--- a/lib/group_cpus.c
++++ b/lib/group_cpus.c
+@@ -366,13 +366,25 @@ struct cpumask *group_cpus_evenly(unsign
+ if (!masks)
+ goto fail_node_to_cpumask;
+
+- /* Stabilize the cpumasks */
+- cpus_read_lock();
+ build_node_to_cpumask(node_to_cpumask);
+
++ /*
++ * Make a local cache of 'cpu_present_mask', so the two stages
++ * spread can observe consistent 'cpu_present_mask' without holding
++ * cpu hotplug lock, then we can reduce deadlock risk with cpu
++ * hotplug code.
++ *
++ * Here CPU hotplug may happen when reading `cpu_present_mask`, and
++ * we can live with the case because it only affects that hotplug
++ * CPU is handled in the 1st or 2nd stage, and either way is correct
++ * from API user viewpoint since 2-stage spread is sort of
++ * optimization.
++ */
++ cpumask_copy(npresmsk, data_race(cpu_present_mask));
++
+ /* grouping present CPUs first */
+ ret = __group_cpus_evenly(curgrp, numgrps, node_to_cpumask,
+- cpu_present_mask, nmsk, masks);
++ npresmsk, nmsk, masks);
+ if (ret < 0)
+ goto fail_build_affinity;
+ nr_present = ret;
+@@ -387,15 +399,13 @@ struct cpumask *group_cpus_evenly(unsign
+ curgrp = 0;
+ else
+ curgrp = nr_present;
+- cpumask_andnot(npresmsk, cpu_possible_mask, cpu_present_mask);
++ cpumask_andnot(npresmsk, cpu_possible_mask, npresmsk);
+ ret = __group_cpus_evenly(curgrp, numgrps, node_to_cpumask,
+ npresmsk, nmsk, masks);
+ if (ret >= 0)
+ nr_others = ret;
+
+ fail_build_affinity:
+- cpus_read_unlock();
+-
+ if (ret >= 0)
+ WARN_ON(nr_present + nr_others < numgrps);
+
--- /dev/null
+From c467e97f079f0019870c314996fae952cc768e82 Mon Sep 17 00:00:00 2001
+From: David Jeffery <djeffery@redhat.com>
+Date: Tue, 28 Nov 2023 13:11:39 -0500
+Subject: md/raid6: use valid sector values to determine if an I/O should wait on the reshape
+
+From: David Jeffery <djeffery@redhat.com>
+
+commit c467e97f079f0019870c314996fae952cc768e82 upstream.
+
+During a reshape or a RAID6 array such as expanding by adding an additional
+disk, I/Os to the region of the array which have not yet been reshaped can
+stall indefinitely. This is from errors in the stripe_ahead_of_reshape
+function causing md to think the I/O is to a region in the actively
+undergoing the reshape.
+
+stripe_ahead_of_reshape fails to account for the q disk having a sector
+value of 0. By not excluding the q disk from the for loop, raid6 will always
+generate a min_sector value of 0, causing a return value which stalls.
+
+The function's max_sector calculation also uses min() when it should use
+max(), causing the max_sector value to always be 0. During a backwards
+rebuild this can cause the opposite problem where it allows I/O to advance
+when it should wait.
+
+Fixing these errors will allow safe I/O to advance in a timely manner and
+delay only I/O which is unsafe due to stripes in the middle of undergoing
+the reshape.
+
+Fixes: 486f60558607 ("md/raid5: Check all disks in a stripe_head for reshape progress")
+Cc: stable@vger.kernel.org # v6.0+
+Signed-off-by: David Jeffery <djeffery@redhat.com>
+Tested-by: Laurence Oberman <loberman@redhat.com>
+Signed-off-by: Song Liu <song@kernel.org>
+Link: https://lore.kernel.org/r/20231128181233.6187-1-djeffery@redhat.com
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/md/raid5.c | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+--- a/drivers/md/raid5.c
++++ b/drivers/md/raid5.c
+@@ -5892,11 +5892,11 @@ static bool stripe_ahead_of_reshape(stru
+ int dd_idx;
+
+ for (dd_idx = 0; dd_idx < sh->disks; dd_idx++) {
+- if (dd_idx == sh->pd_idx)
++ if (dd_idx == sh->pd_idx || dd_idx == sh->qd_idx)
+ continue;
+
+ min_sector = min(min_sector, sh->dev[dd_idx].sector);
+- max_sector = min(max_sector, sh->dev[dd_idx].sector);
++ max_sector = max(max_sector, sh->dev[dd_idx].sector);
+ }
+
+ spin_lock_irq(&conf->device_lock);
--- /dev/null
+From 9aa1345d66b8132745ffb99b348b1492088da9e2 Mon Sep 17 00:00:00 2001
+From: Hugh Dickins <hughd@google.com>
+Date: Fri, 17 Nov 2023 00:49:18 -0800
+Subject: mm: fix oops when filemap_map_pmd() without prealloc_pte
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Hugh Dickins <hughd@google.com>
+
+commit 9aa1345d66b8132745ffb99b348b1492088da9e2 upstream.
+
+syzbot reports oops in lockdep's __lock_acquire(), called from
+__pte_offset_map_lock() called from filemap_map_pages(); or when I run the
+repro, the oops comes in pmd_install(), called from filemap_map_pmd()
+called from filemap_map_pages(), just before the __pte_offset_map_lock().
+
+The problem is that filemap_map_pmd() has been assuming that when it finds
+pmd_none(), a page table has already been prepared in prealloc_pte; and
+indeed do_fault_around() has been careful to preallocate one there, when
+it finds pmd_none(): but what if *pmd became none in between?
+
+My 6.6 mods in mm/khugepaged.c, avoiding mmap_lock for write, have made it
+easy for *pmd to be cleared while servicing a page fault; but even before
+those, a huge *pmd might be zapped while a fault is serviced.
+
+The difference in symptomatic stack traces comes from the "memory model"
+in use: pmd_install() uses pmd_populate() uses page_to_pfn(): in some
+models that is strict, and will oops on the NULL prealloc_pte; in other
+models, it will construct a bogus value to be populated into *pmd, then
+__pte_offset_map_lock() oops when trying to access split ptlock pointer
+(or some other symptom in normal case of ptlock embedded not pointer).
+
+Link: https://lore.kernel.org/linux-mm/20231115065506.19780-1-jose.pekkarinen@foxhound.fi/
+Link: https://lkml.kernel.org/r/6ed0c50c-78ef-0719-b3c5-60c0c010431c@google.com
+Fixes: f9ce0be71d1f ("mm: Cleanup faultaround and finish_fault() codepaths")
+Signed-off-by: Hugh Dickins <hughd@google.com>
+Reported-and-tested-by: syzbot+89edd67979b52675ddec@syzkaller.appspotmail.com
+Closes: https://lore.kernel.org/linux-mm/0000000000005e44550608a0806c@google.com/
+Reviewed-by: David Hildenbrand <david@redhat.com>
+Cc: Jann Horn <jannh@google.com>,
+Cc: José Pekkarinen <jose.pekkarinen@foxhound.fi>
+Cc: Kirill A. Shutemov <kirill.shutemov@linux.intel.com>
+Cc: Matthew Wilcox (Oracle) <willy@infradead.org>
+Cc: <stable@vger.kernel.org> [5.12+]
+Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ mm/filemap.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/mm/filemap.c
++++ b/mm/filemap.c
+@@ -3422,7 +3422,7 @@ static bool filemap_map_pmd(struct vm_fa
+ }
+ }
+
+- if (pmd_none(*vmf->pmd))
++ if (pmd_none(*vmf->pmd) && vmf->prealloc_pte)
+ pmd_install(mm, vmf->pmd, &vmf->prealloc_pte);
+
+ return false;
--- /dev/null
+From 001002e73712cdf6b8d9a103648cda3040ad7647 Mon Sep 17 00:00:00 2001
+From: Sumanth Korikkar <sumanthk@linux.ibm.com>
+Date: Mon, 20 Nov 2023 15:53:52 +0100
+Subject: mm/memory_hotplug: add missing mem_hotplug_lock
+
+From: Sumanth Korikkar <sumanthk@linux.ibm.com>
+
+commit 001002e73712cdf6b8d9a103648cda3040ad7647 upstream.
+
+From Documentation/core-api/memory-hotplug.rst:
+When adding/removing/onlining/offlining memory or adding/removing
+heterogeneous/device memory, we should always hold the mem_hotplug_lock
+in write mode to serialise memory hotplug (e.g. access to global/zone
+variables).
+
+mhp_(de)init_memmap_on_memory() functions can change zone stats and
+struct page content, but they are currently called w/o the
+mem_hotplug_lock.
+
+When memory block is being offlined and when kmemleak goes through each
+populated zone, the following theoretical race conditions could occur:
+CPU 0: | CPU 1:
+memory_offline() |
+-> offline_pages() |
+ -> mem_hotplug_begin() |
+ ... |
+ -> mem_hotplug_done() |
+ | kmemleak_scan()
+ | -> get_online_mems()
+ | ...
+-> mhp_deinit_memmap_on_memory() |
+ [not protected by mem_hotplug_begin/done()]|
+ Marks memory section as offline, | Retrieves zone_start_pfn
+ poisons vmemmap struct pages and updates | and struct page members.
+ the zone related data |
+ | ...
+ | -> put_online_mems()
+
+Fix this by ensuring mem_hotplug_lock is taken before performing
+mhp_init_memmap_on_memory(). Also ensure that
+mhp_deinit_memmap_on_memory() holds the lock.
+
+online/offline_pages() are currently only called from
+memory_block_online/offline(), so it is safe to move the locking there.
+
+Link: https://lkml.kernel.org/r/20231120145354.308999-2-sumanthk@linux.ibm.com
+Fixes: a08a2ae34613 ("mm,memory_hotplug: allocate memmap from the added memory range")
+Signed-off-by: Sumanth Korikkar <sumanthk@linux.ibm.com>
+Reviewed-by: Gerald Schaefer <gerald.schaefer@linux.ibm.com>
+Acked-by: David Hildenbrand <david@redhat.com>
+Cc: Alexander Gordeev <agordeev@linux.ibm.com>
+Cc: Aneesh Kumar K.V <aneesh.kumar@linux.ibm.com>
+Cc: Anshuman Khandual <anshuman.khandual@arm.com>
+Cc: Heiko Carstens <hca@linux.ibm.com>
+Cc: Michal Hocko <mhocko@suse.com>
+Cc: Oscar Salvador <osalvador@suse.de>
+Cc: Vasily Gorbik <gor@linux.ibm.com>
+Cc: kernel test robot <lkp@intel.com>
+Cc: <stable@vger.kernel.org> [5.15+]
+Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/base/memory.c | 18 +++++++++++++++---
+ mm/memory_hotplug.c | 13 ++++++-------
+ 2 files changed, 21 insertions(+), 10 deletions(-)
+
+--- a/drivers/base/memory.c
++++ b/drivers/base/memory.c
+@@ -180,6 +180,9 @@ static inline unsigned long memblk_nr_po
+ }
+ #endif
+
++/*
++ * Must acquire mem_hotplug_lock in write mode.
++ */
+ static int memory_block_online(struct memory_block *mem)
+ {
+ unsigned long start_pfn = section_nr_to_pfn(mem->start_section_nr);
+@@ -204,10 +207,11 @@ static int memory_block_online(struct me
+ if (mem->altmap)
+ nr_vmemmap_pages = mem->altmap->free;
+
++ mem_hotplug_begin();
+ if (nr_vmemmap_pages) {
+ ret = mhp_init_memmap_on_memory(start_pfn, nr_vmemmap_pages, zone);
+ if (ret)
+- return ret;
++ goto out;
+ }
+
+ ret = online_pages(start_pfn + nr_vmemmap_pages,
+@@ -215,7 +219,7 @@ static int memory_block_online(struct me
+ if (ret) {
+ if (nr_vmemmap_pages)
+ mhp_deinit_memmap_on_memory(start_pfn, nr_vmemmap_pages);
+- return ret;
++ goto out;
+ }
+
+ /*
+@@ -227,9 +231,14 @@ static int memory_block_online(struct me
+ nr_vmemmap_pages);
+
+ mem->zone = zone;
++out:
++ mem_hotplug_done();
+ return ret;
+ }
+
++/*
++ * Must acquire mem_hotplug_lock in write mode.
++ */
+ static int memory_block_offline(struct memory_block *mem)
+ {
+ unsigned long start_pfn = section_nr_to_pfn(mem->start_section_nr);
+@@ -247,6 +256,7 @@ static int memory_block_offline(struct m
+ if (mem->altmap)
+ nr_vmemmap_pages = mem->altmap->free;
+
++ mem_hotplug_begin();
+ if (nr_vmemmap_pages)
+ adjust_present_page_count(pfn_to_page(start_pfn), mem->group,
+ -nr_vmemmap_pages);
+@@ -258,13 +268,15 @@ static int memory_block_offline(struct m
+ if (nr_vmemmap_pages)
+ adjust_present_page_count(pfn_to_page(start_pfn),
+ mem->group, nr_vmemmap_pages);
+- return ret;
++ goto out;
+ }
+
+ if (nr_vmemmap_pages)
+ mhp_deinit_memmap_on_memory(start_pfn, nr_vmemmap_pages);
+
+ mem->zone = NULL;
++out:
++ mem_hotplug_done();
+ return ret;
+ }
+
+--- a/mm/memory_hotplug.c
++++ b/mm/memory_hotplug.c
+@@ -1129,6 +1129,9 @@ void mhp_deinit_memmap_on_memory(unsigne
+ kasan_remove_zero_shadow(__va(PFN_PHYS(pfn)), PFN_PHYS(nr_pages));
+ }
+
++/*
++ * Must be called with mem_hotplug_lock in write mode.
++ */
+ int __ref online_pages(unsigned long pfn, unsigned long nr_pages,
+ struct zone *zone, struct memory_group *group)
+ {
+@@ -1149,7 +1152,6 @@ int __ref online_pages(unsigned long pfn
+ !IS_ALIGNED(pfn + nr_pages, PAGES_PER_SECTION)))
+ return -EINVAL;
+
+- mem_hotplug_begin();
+
+ /* associate pfn range with the zone */
+ move_pfn_range_to_zone(zone, pfn, nr_pages, NULL, MIGRATE_ISOLATE);
+@@ -1208,7 +1210,6 @@ int __ref online_pages(unsigned long pfn
+ writeback_set_ratelimit();
+
+ memory_notify(MEM_ONLINE, &arg);
+- mem_hotplug_done();
+ return 0;
+
+ failed_addition:
+@@ -1217,7 +1218,6 @@ failed_addition:
+ (((unsigned long long) pfn + nr_pages) << PAGE_SHIFT) - 1);
+ memory_notify(MEM_CANCEL_ONLINE, &arg);
+ remove_pfn_range_from_zone(zone, pfn, nr_pages);
+- mem_hotplug_done();
+ return ret;
+ }
+
+@@ -1863,6 +1863,9 @@ static int count_system_ram_pages_cb(uns
+ return 0;
+ }
+
++/*
++ * Must be called with mem_hotplug_lock in write mode.
++ */
+ int __ref offline_pages(unsigned long start_pfn, unsigned long nr_pages,
+ struct zone *zone, struct memory_group *group)
+ {
+@@ -1885,8 +1888,6 @@ int __ref offline_pages(unsigned long st
+ !IS_ALIGNED(start_pfn + nr_pages, PAGES_PER_SECTION)))
+ return -EINVAL;
+
+- mem_hotplug_begin();
+-
+ /*
+ * Don't allow to offline memory blocks that contain holes.
+ * Consequently, memory blocks with holes can never get onlined
+@@ -2027,7 +2028,6 @@ int __ref offline_pages(unsigned long st
+
+ memory_notify(MEM_OFFLINE, &arg);
+ remove_pfn_range_from_zone(zone, start_pfn, nr_pages);
+- mem_hotplug_done();
+ return 0;
+
+ failed_removal_isolated:
+@@ -2042,7 +2042,6 @@ failed_removal:
+ (unsigned long long) start_pfn << PAGE_SHIFT,
+ ((unsigned long long) end_pfn << PAGE_SHIFT) - 1,
+ reason);
+- mem_hotplug_done();
+ return ret;
+ }
+
--- /dev/null
+From f42ce5f087eb69e47294ababd2e7e6f88a82d308 Mon Sep 17 00:00:00 2001
+From: Sumanth Korikkar <sumanthk@linux.ibm.com>
+Date: Mon, 20 Nov 2023 15:53:53 +0100
+Subject: mm/memory_hotplug: fix error handling in add_memory_resource()
+
+From: Sumanth Korikkar <sumanthk@linux.ibm.com>
+
+commit f42ce5f087eb69e47294ababd2e7e6f88a82d308 upstream.
+
+In add_memory_resource(), creation of memory block devices occurs after
+successful call to arch_add_memory(). However, creation of memory block
+devices could fail. In that case, arch_remove_memory() is called to
+perform necessary cleanup.
+
+Currently with or without altmap support, arch_remove_memory() is always
+passed with altmap set to NULL during error handling. This leads to
+freeing of struct pages using free_pages(), eventhough the allocation
+might have been performed with altmap support via
+altmap_alloc_block_buf().
+
+Fix the error handling by passing altmap in arch_remove_memory(). This
+ensures the following:
+* When altmap is disabled, deallocation of the struct pages array occurs
+ via free_pages().
+* When altmap is enabled, deallocation occurs via vmem_altmap_free().
+
+Link: https://lkml.kernel.org/r/20231120145354.308999-3-sumanthk@linux.ibm.com
+Fixes: a08a2ae34613 ("mm,memory_hotplug: allocate memmap from the added memory range")
+Signed-off-by: Sumanth Korikkar <sumanthk@linux.ibm.com>
+Reviewed-by: Gerald Schaefer <gerald.schaefer@linux.ibm.com>
+Acked-by: David Hildenbrand <david@redhat.com>
+Cc: Alexander Gordeev <agordeev@linux.ibm.com>
+Cc: Aneesh Kumar K.V <aneesh.kumar@linux.ibm.com>
+Cc: Anshuman Khandual <anshuman.khandual@arm.com>
+Cc: Heiko Carstens <hca@linux.ibm.com>
+Cc: kernel test robot <lkp@intel.com>
+Cc: Michal Hocko <mhocko@suse.com>
+Cc: Oscar Salvador <osalvador@suse.de>
+Cc: Vasily Gorbik <gor@linux.ibm.com>
+Cc: <stable@vger.kernel.org> [5.15+]
+Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ mm/memory_hotplug.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/mm/memory_hotplug.c
++++ b/mm/memory_hotplug.c
+@@ -1458,7 +1458,7 @@ int __ref add_memory_resource(int nid, s
+ /* create memory block devices after memory was added */
+ ret = create_memory_block_devices(start, size, params.altmap, group);
+ if (ret) {
+- arch_remove_memory(start, size, NULL);
++ arch_remove_memory(start, size, params.altmap);
+ goto error_free;
+ }
+
--- /dev/null
+From 0ad722bd9ee3a9bdfca9613148645e4c9b7f26cf Mon Sep 17 00:00:00 2001
+From: Hui Zhou <hui.zhou@corigine.com>
+Date: Tue, 5 Dec 2023 11:26:25 +0200
+Subject: nfp: flower: fix for take a mutex lock in soft irq context and rcu lock
+
+From: Hui Zhou <hui.zhou@corigine.com>
+
+commit 0ad722bd9ee3a9bdfca9613148645e4c9b7f26cf upstream.
+
+The neighbour event callback call the function nfp_tun_write_neigh,
+this function will take a mutex lock and it is in soft irq context,
+change the work queue to process the neighbour event.
+
+Move the nfp_tun_write_neigh function out of range rcu_read_lock/unlock()
+in function nfp_tunnel_request_route_v4 and nfp_tunnel_request_route_v6.
+
+Fixes: abc210952af7 ("nfp: flower: tunnel neigh support bond offload")
+CC: stable@vger.kernel.org # 6.2+
+Signed-off-by: Hui Zhou <hui.zhou@corigine.com>
+Signed-off-by: Louis Peens <louis.peens@corigine.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ .../netronome/nfp/flower/tunnel_conf.c | 127 +++++++++++++-----
+ 1 file changed, 95 insertions(+), 32 deletions(-)
+
+diff --git a/drivers/net/ethernet/netronome/nfp/flower/tunnel_conf.c b/drivers/net/ethernet/netronome/nfp/flower/tunnel_conf.c
+index 060a77f2265d..e522845c7c21 100644
+--- a/drivers/net/ethernet/netronome/nfp/flower/tunnel_conf.c
++++ b/drivers/net/ethernet/netronome/nfp/flower/tunnel_conf.c
+@@ -160,6 +160,18 @@ struct nfp_tun_mac_addr_offload {
+ u8 addr[ETH_ALEN];
+ };
+
++/**
++ * struct nfp_neigh_update_work - update neighbour information to nfp
++ * @work: Work queue for writing neigh to the nfp
++ * @n: neighbour entry
++ * @app: Back pointer to app
++ */
++struct nfp_neigh_update_work {
++ struct work_struct work;
++ struct neighbour *n;
++ struct nfp_app *app;
++};
++
+ enum nfp_flower_mac_offload_cmd {
+ NFP_TUNNEL_MAC_OFFLOAD_ADD = 0,
+ NFP_TUNNEL_MAC_OFFLOAD_DEL = 1,
+@@ -607,38 +619,30 @@ nfp_tun_write_neigh(struct net_device *netdev, struct nfp_app *app,
+ nfp_flower_cmsg_warn(app, "Neighbour configuration failed.\n");
+ }
+
+-static int
+-nfp_tun_neigh_event_handler(struct notifier_block *nb, unsigned long event,
+- void *ptr)
++static void
++nfp_tun_release_neigh_update_work(struct nfp_neigh_update_work *update_work)
+ {
+- struct nfp_flower_priv *app_priv;
+- struct netevent_redirect *redir;
+- struct neighbour *n;
++ neigh_release(update_work->n);
++ kfree(update_work);
++}
++
++static void nfp_tun_neigh_update(struct work_struct *work)
++{
++ struct nfp_neigh_update_work *update_work;
+ struct nfp_app *app;
++ struct neighbour *n;
+ bool neigh_invalid;
+ int err;
+
+- switch (event) {
+- case NETEVENT_REDIRECT:
+- redir = (struct netevent_redirect *)ptr;
+- n = redir->neigh;
+- break;
+- case NETEVENT_NEIGH_UPDATE:
+- n = (struct neighbour *)ptr;
+- break;
+- default:
+- return NOTIFY_DONE;
+- }
+-
+- neigh_invalid = !(n->nud_state & NUD_VALID) || n->dead;
+-
+- app_priv = container_of(nb, struct nfp_flower_priv, tun.neigh_nb);
+- app = app_priv->app;
++ update_work = container_of(work, struct nfp_neigh_update_work, work);
++ app = update_work->app;
++ n = update_work->n;
+
+ if (!nfp_flower_get_port_id_from_netdev(app, n->dev))
+- return NOTIFY_DONE;
++ goto out;
+
+ #if IS_ENABLED(CONFIG_INET)
++ neigh_invalid = !(n->nud_state & NUD_VALID) || n->dead;
+ if (n->tbl->family == AF_INET6) {
+ #if IS_ENABLED(CONFIG_IPV6)
+ struct flowi6 flow6 = {};
+@@ -655,13 +659,11 @@ nfp_tun_neigh_event_handler(struct notifier_block *nb, unsigned long event,
+ dst = ip6_dst_lookup_flow(dev_net(n->dev), NULL,
+ &flow6, NULL);
+ if (IS_ERR(dst))
+- return NOTIFY_DONE;
++ goto out;
+
+ dst_release(dst);
+ }
+ nfp_tun_write_neigh(n->dev, app, &flow6, n, true, false);
+-#else
+- return NOTIFY_DONE;
+ #endif /* CONFIG_IPV6 */
+ } else {
+ struct flowi4 flow4 = {};
+@@ -678,17 +680,71 @@ nfp_tun_neigh_event_handler(struct notifier_block *nb, unsigned long event,
+ rt = ip_route_output_key(dev_net(n->dev), &flow4);
+ err = PTR_ERR_OR_ZERO(rt);
+ if (err)
+- return NOTIFY_DONE;
++ goto out;
+
+ ip_rt_put(rt);
+ }
+ nfp_tun_write_neigh(n->dev, app, &flow4, n, false, false);
+ }
+-#else
+- return NOTIFY_DONE;
+ #endif /* CONFIG_INET */
++out:
++ nfp_tun_release_neigh_update_work(update_work);
++}
+
+- return NOTIFY_OK;
++static struct nfp_neigh_update_work *
++nfp_tun_alloc_neigh_update_work(struct nfp_app *app, struct neighbour *n)
++{
++ struct nfp_neigh_update_work *update_work;
++
++ update_work = kzalloc(sizeof(*update_work), GFP_ATOMIC);
++ if (!update_work)
++ return NULL;
++
++ INIT_WORK(&update_work->work, nfp_tun_neigh_update);
++ neigh_hold(n);
++ update_work->n = n;
++ update_work->app = app;
++
++ return update_work;
++}
++
++static int
++nfp_tun_neigh_event_handler(struct notifier_block *nb, unsigned long event,
++ void *ptr)
++{
++ struct nfp_neigh_update_work *update_work;
++ struct nfp_flower_priv *app_priv;
++ struct netevent_redirect *redir;
++ struct neighbour *n;
++ struct nfp_app *app;
++
++ switch (event) {
++ case NETEVENT_REDIRECT:
++ redir = (struct netevent_redirect *)ptr;
++ n = redir->neigh;
++ break;
++ case NETEVENT_NEIGH_UPDATE:
++ n = (struct neighbour *)ptr;
++ break;
++ default:
++ return NOTIFY_DONE;
++ }
++#if IS_ENABLED(CONFIG_IPV6)
++ if (n->tbl != ipv6_stub->nd_tbl && n->tbl != &arp_tbl)
++#else
++ if (n->tbl != &arp_tbl)
++#endif
++ return NOTIFY_DONE;
++
++ app_priv = container_of(nb, struct nfp_flower_priv, tun.neigh_nb);
++ app = app_priv->app;
++ update_work = nfp_tun_alloc_neigh_update_work(app, n);
++ if (!update_work)
++ return NOTIFY_DONE;
++
++ queue_work(system_highpri_wq, &update_work->work);
++
++ return NOTIFY_DONE;
+ }
+
+ void nfp_tunnel_request_route_v4(struct nfp_app *app, struct sk_buff *skb)
+@@ -706,6 +762,7 @@ void nfp_tunnel_request_route_v4(struct nfp_app *app, struct sk_buff *skb)
+ netdev = nfp_app_dev_get(app, be32_to_cpu(payload->ingress_port), NULL);
+ if (!netdev)
+ goto fail_rcu_unlock;
++ dev_hold(netdev);
+
+ flow.daddr = payload->ipv4_addr;
+ flow.flowi4_proto = IPPROTO_UDP;
+@@ -725,13 +782,16 @@ void nfp_tunnel_request_route_v4(struct nfp_app *app, struct sk_buff *skb)
+ ip_rt_put(rt);
+ if (!n)
+ goto fail_rcu_unlock;
++ rcu_read_unlock();
++
+ nfp_tun_write_neigh(n->dev, app, &flow, n, false, true);
+ neigh_release(n);
+- rcu_read_unlock();
++ dev_put(netdev);
+ return;
+
+ fail_rcu_unlock:
+ rcu_read_unlock();
++ dev_put(netdev);
+ nfp_flower_cmsg_warn(app, "Requested route not found.\n");
+ }
+
+@@ -749,6 +809,7 @@ void nfp_tunnel_request_route_v6(struct nfp_app *app, struct sk_buff *skb)
+ netdev = nfp_app_dev_get(app, be32_to_cpu(payload->ingress_port), NULL);
+ if (!netdev)
+ goto fail_rcu_unlock;
++ dev_hold(netdev);
+
+ flow.daddr = payload->ipv6_addr;
+ flow.flowi6_proto = IPPROTO_UDP;
+@@ -766,14 +827,16 @@ void nfp_tunnel_request_route_v6(struct nfp_app *app, struct sk_buff *skb)
+ dst_release(dst);
+ if (!n)
+ goto fail_rcu_unlock;
++ rcu_read_unlock();
+
+ nfp_tun_write_neigh(n->dev, app, &flow, n, true, true);
+ neigh_release(n);
+- rcu_read_unlock();
++ dev_put(netdev);
+ return;
+
+ fail_rcu_unlock:
+ rcu_read_unlock();
++ dev_put(netdev);
+ nfp_flower_cmsg_warn(app, "Requested IPv6 route not found.\n");
+ }
+
+--
+2.43.0
+
--- /dev/null
+From d61d0ab573649789bf9eb909c89a1a193b2e3d10 Mon Sep 17 00:00:00 2001
+From: Ryusuke Konishi <konishi.ryusuke@gmail.com>
+Date: Wed, 29 Nov 2023 23:15:47 +0900
+Subject: nilfs2: fix missing error check for sb_set_blocksize call
+
+From: Ryusuke Konishi <konishi.ryusuke@gmail.com>
+
+commit d61d0ab573649789bf9eb909c89a1a193b2e3d10 upstream.
+
+When mounting a filesystem image with a block size larger than the page
+size, nilfs2 repeatedly outputs long error messages with stack traces to
+the kernel log, such as the following:
+
+ getblk(): invalid block size 8192 requested
+ logical block size: 512
+ ...
+ Call Trace:
+ dump_stack_lvl+0x92/0xd4
+ dump_stack+0xd/0x10
+ bdev_getblk+0x33a/0x354
+ __breadahead+0x11/0x80
+ nilfs_search_super_root+0xe2/0x704 [nilfs2]
+ load_nilfs+0x72/0x504 [nilfs2]
+ nilfs_mount+0x30f/0x518 [nilfs2]
+ legacy_get_tree+0x1b/0x40
+ vfs_get_tree+0x18/0xc4
+ path_mount+0x786/0xa88
+ __ia32_sys_mount+0x147/0x1a8
+ __do_fast_syscall_32+0x56/0xc8
+ do_fast_syscall_32+0x29/0x58
+ do_SYSENTER_32+0x15/0x18
+ entry_SYSENTER_32+0x98/0xf1
+ ...
+
+This overloads the system logger. And to make matters worse, it sometimes
+crashes the kernel with a memory access violation.
+
+This is because the return value of the sb_set_blocksize() call, which
+should be checked for errors, is not checked.
+
+The latter issue is due to out-of-buffer memory being accessed based on a
+large block size that caused sb_set_blocksize() to fail for buffers read
+with the initial minimum block size that remained unupdated in the
+super_block structure.
+
+Since nilfs2 mkfs tool does not accept block sizes larger than the system
+page size, this has been overlooked. However, it is possible to create
+this situation by intentionally modifying the tool or by passing a
+filesystem image created on a system with a large page size to a system
+with a smaller page size and mounting it.
+
+Fix this issue by inserting the expected error handling for the call to
+sb_set_blocksize().
+
+Link: https://lkml.kernel.org/r/20231129141547.4726-1-konishi.ryusuke@gmail.com
+Signed-off-by: Ryusuke Konishi <konishi.ryusuke@gmail.com>
+Tested-by: Ryusuke Konishi <konishi.ryusuke@gmail.com>
+Cc: <stable@vger.kernel.org>
+Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ fs/nilfs2/the_nilfs.c | 6 +++++-
+ 1 file changed, 5 insertions(+), 1 deletion(-)
+
+--- a/fs/nilfs2/the_nilfs.c
++++ b/fs/nilfs2/the_nilfs.c
+@@ -716,7 +716,11 @@ int init_nilfs(struct the_nilfs *nilfs,
+ goto failed_sbh;
+ }
+ nilfs_release_super_block(nilfs);
+- sb_set_blocksize(sb, blocksize);
++ if (!sb_set_blocksize(sb, blocksize)) {
++ nilfs_err(sb, "bad blocksize %d", blocksize);
++ err = -EINVAL;
++ goto out;
++ }
+
+ err = nilfs_load_super_block(nilfs, sb, blocksize, &sbp);
+ if (err)
--- /dev/null
+From 675abf8df1353e0e3bde314993e0796c524cfbf0 Mon Sep 17 00:00:00 2001
+From: Ryusuke Konishi <konishi.ryusuke@gmail.com>
+Date: Tue, 5 Dec 2023 17:59:47 +0900
+Subject: nilfs2: prevent WARNING in nilfs_sufile_set_segment_usage()
+
+From: Ryusuke Konishi <konishi.ryusuke@gmail.com>
+
+commit 675abf8df1353e0e3bde314993e0796c524cfbf0 upstream.
+
+If nilfs2 reads a disk image with corrupted segment usage metadata, and
+its segment usage information is marked as an error for the segment at the
+write location, nilfs_sufile_set_segment_usage() can trigger WARN_ONs
+during log writing.
+
+Segments newly allocated for writing with nilfs_sufile_alloc() will not
+have this error flag set, but this unexpected situation will occur if the
+segment indexed by either nilfs->ns_segnum or nilfs->ns_nextnum (active
+segment) was marked in error.
+
+Fix this issue by inserting a sanity check to treat it as a file system
+corruption.
+
+Since error returns are not allowed during the execution phase where
+nilfs_sufile_set_segment_usage() is used, this inserts the sanity check
+into nilfs_sufile_mark_dirty() which pre-reads the buffer containing the
+segment usage record to be updated and sets it up in a dirty state for
+writing.
+
+In addition, nilfs_sufile_set_segment_usage() is also called when
+canceling log writing and undoing segment usage update, so in order to
+avoid issuing the same kernel warning in that case, in case of
+cancellation, avoid checking the error flag in
+nilfs_sufile_set_segment_usage().
+
+Link: https://lkml.kernel.org/r/20231205085947.4431-1-konishi.ryusuke@gmail.com
+Signed-off-by: Ryusuke Konishi <konishi.ryusuke@gmail.com>
+Reported-by: syzbot+14e9f834f6ddecece094@syzkaller.appspotmail.com
+Closes: https://syzkaller.appspot.com/bug?extid=14e9f834f6ddecece094
+Tested-by: Ryusuke Konishi <konishi.ryusuke@gmail.com>
+Cc: <stable@vger.kernel.org>
+Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ fs/nilfs2/sufile.c | 42 +++++++++++++++++++++++++++++++++++-------
+ 1 file changed, 35 insertions(+), 7 deletions(-)
+
+--- a/fs/nilfs2/sufile.c
++++ b/fs/nilfs2/sufile.c
+@@ -501,15 +501,38 @@ int nilfs_sufile_mark_dirty(struct inode
+
+ down_write(&NILFS_MDT(sufile)->mi_sem);
+ ret = nilfs_sufile_get_segment_usage_block(sufile, segnum, 0, &bh);
+- if (!ret) {
+- mark_buffer_dirty(bh);
+- nilfs_mdt_mark_dirty(sufile);
+- kaddr = kmap_atomic(bh->b_page);
+- su = nilfs_sufile_block_get_segment_usage(sufile, segnum, bh, kaddr);
++ if (ret)
++ goto out_sem;
++
++ kaddr = kmap_atomic(bh->b_page);
++ su = nilfs_sufile_block_get_segment_usage(sufile, segnum, bh, kaddr);
++ if (unlikely(nilfs_segment_usage_error(su))) {
++ struct the_nilfs *nilfs = sufile->i_sb->s_fs_info;
++
++ kunmap_atomic(kaddr);
++ brelse(bh);
++ if (nilfs_segment_is_active(nilfs, segnum)) {
++ nilfs_error(sufile->i_sb,
++ "active segment %llu is erroneous",
++ (unsigned long long)segnum);
++ } else {
++ /*
++ * Segments marked erroneous are never allocated by
++ * nilfs_sufile_alloc(); only active segments, ie,
++ * the segments indexed by ns_segnum or ns_nextnum,
++ * can be erroneous here.
++ */
++ WARN_ON_ONCE(1);
++ }
++ ret = -EIO;
++ } else {
+ nilfs_segment_usage_set_dirty(su);
+ kunmap_atomic(kaddr);
++ mark_buffer_dirty(bh);
++ nilfs_mdt_mark_dirty(sufile);
+ brelse(bh);
+ }
++out_sem:
+ up_write(&NILFS_MDT(sufile)->mi_sem);
+ return ret;
+ }
+@@ -536,9 +559,14 @@ int nilfs_sufile_set_segment_usage(struc
+
+ kaddr = kmap_atomic(bh->b_page);
+ su = nilfs_sufile_block_get_segment_usage(sufile, segnum, bh, kaddr);
+- WARN_ON(nilfs_segment_usage_error(su));
+- if (modtime)
++ if (modtime) {
++ /*
++ * Check segusage error and set su_lastmod only when updating
++ * this entry with a valid timestamp, not for cancellation.
++ */
++ WARN_ON_ONCE(nilfs_segment_usage_error(su));
+ su->su_lastmod = cpu_to_le64(modtime);
++ }
+ su->su_nblocks = cpu_to_le32(nblocks);
+ kunmap_atomic(kaddr);
+
--- /dev/null
+From db3fadacaf0c817b222090290d06ca2a338422d0 Mon Sep 17 00:00:00 2001
+From: Daniel Borkmann <daniel@iogearbox.net>
+Date: Fri, 1 Dec 2023 14:10:21 +0100
+Subject: packet: Move reference count in packet_sock to atomic_long_t
+
+From: Daniel Borkmann <daniel@iogearbox.net>
+
+commit db3fadacaf0c817b222090290d06ca2a338422d0 upstream.
+
+In some potential instances the reference count on struct packet_sock
+could be saturated and cause overflows which gets the kernel a bit
+confused. To prevent this, move to a 64-bit atomic reference count on
+64-bit architectures to prevent the possibility of this type to overflow.
+
+Because we can not handle saturation, using refcount_t is not possible
+in this place. Maybe someday in the future if it changes it could be
+used. Also, instead of using plain atomic64_t, use atomic_long_t instead.
+32-bit machines tend to be memory-limited (i.e. anything that increases
+a reference uses so much memory that you can't actually get to 2**32
+references). 32-bit architectures also tend to have serious problems
+with 64-bit atomics. Hence, atomic_long_t is the more natural solution.
+
+Reported-by: "The UK's National Cyber Security Centre (NCSC)" <security@ncsc.gov.uk>
+Co-developed-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Signed-off-by: Daniel Borkmann <daniel@iogearbox.net>
+Cc: Linus Torvalds <torvalds@linux-foundation.org>
+Cc: stable@kernel.org
+Reviewed-by: Willem de Bruijn <willemb@google.com>
+Reviewed-by: Eric Dumazet <edumazet@google.com>
+Link: https://lore.kernel.org/r/20231201131021.19999-1-daniel@iogearbox.net
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ net/packet/af_packet.c | 16 ++++++++--------
+ net/packet/internal.h | 2 +-
+ 2 files changed, 9 insertions(+), 9 deletions(-)
+
+--- a/net/packet/af_packet.c
++++ b/net/packet/af_packet.c
+@@ -4300,7 +4300,7 @@ static void packet_mm_open(struct vm_are
+ struct sock *sk = sock->sk;
+
+ if (sk)
+- atomic_inc(&pkt_sk(sk)->mapped);
++ atomic_long_inc(&pkt_sk(sk)->mapped);
+ }
+
+ static void packet_mm_close(struct vm_area_struct *vma)
+@@ -4310,7 +4310,7 @@ static void packet_mm_close(struct vm_ar
+ struct sock *sk = sock->sk;
+
+ if (sk)
+- atomic_dec(&pkt_sk(sk)->mapped);
++ atomic_long_dec(&pkt_sk(sk)->mapped);
+ }
+
+ static const struct vm_operations_struct packet_mmap_ops = {
+@@ -4405,7 +4405,7 @@ static int packet_set_ring(struct sock *
+
+ err = -EBUSY;
+ if (!closing) {
+- if (atomic_read(&po->mapped))
++ if (atomic_long_read(&po->mapped))
+ goto out;
+ if (packet_read_pending(rb))
+ goto out;
+@@ -4508,7 +4508,7 @@ static int packet_set_ring(struct sock *
+
+ err = -EBUSY;
+ mutex_lock(&po->pg_vec_lock);
+- if (closing || atomic_read(&po->mapped) == 0) {
++ if (closing || atomic_long_read(&po->mapped) == 0) {
+ err = 0;
+ spin_lock_bh(&rb_queue->lock);
+ swap(rb->pg_vec, pg_vec);
+@@ -4526,9 +4526,9 @@ static int packet_set_ring(struct sock *
+ po->prot_hook.func = (po->rx_ring.pg_vec) ?
+ tpacket_rcv : packet_rcv;
+ skb_queue_purge(rb_queue);
+- if (atomic_read(&po->mapped))
+- pr_err("packet_mmap: vma is busy: %d\n",
+- atomic_read(&po->mapped));
++ if (atomic_long_read(&po->mapped))
++ pr_err("packet_mmap: vma is busy: %ld\n",
++ atomic_long_read(&po->mapped));
+ }
+ mutex_unlock(&po->pg_vec_lock);
+
+@@ -4606,7 +4606,7 @@ static int packet_mmap(struct file *file
+ }
+ }
+
+- atomic_inc(&po->mapped);
++ atomic_long_inc(&po->mapped);
+ vma->vm_ops = &packet_mmap_ops;
+ err = 0;
+
+--- a/net/packet/internal.h
++++ b/net/packet/internal.h
+@@ -122,7 +122,7 @@ struct packet_sock {
+ __be16 num;
+ struct packet_rollover *rollover;
+ struct packet_mclist *mclist;
+- atomic_t mapped;
++ atomic_long_t mapped;
+ enum tpacket_versions tp_version;
+ unsigned int tp_hdrlen;
+ unsigned int tp_reserve;
--- /dev/null
+From c8820c92caf0770bec976b01fa9e82bb993c5865 Mon Sep 17 00:00:00 2001
+From: Francesco Dolcini <francesco.dolcini@toradex.com>
+Date: Tue, 28 Nov 2023 20:49:35 +0100
+Subject: platform/surface: aggregator: fix recv_buf() return value
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Francesco Dolcini <francesco.dolcini@toradex.com>
+
+commit c8820c92caf0770bec976b01fa9e82bb993c5865 upstream.
+
+Serdev recv_buf() callback is supposed to return the amount of bytes
+consumed, therefore an int in between 0 and count.
+
+Do not return negative number in case of issue, when
+ssam_controller_receive_buf() returns ESHUTDOWN just returns 0, e.g. no
+bytes consumed, this keep the exact same behavior as it was before.
+
+This fixes a potential WARN in serdev-ttyport.c:ttyport_receive_buf().
+
+Fixes: c167b9c7e3d6 ("platform/surface: Add Surface Aggregator subsystem")
+Cc: stable@vger.kernel.org
+Signed-off-by: Francesco Dolcini <francesco.dolcini@toradex.com>
+Reviewed-by: Maximilian Luz <luzmaximilian@gmail.com>
+Link: https://lore.kernel.org/r/20231128194935.11350-1-francesco@dolcini.it
+Reviewed-by: Ilpo Järvinen <ilpo.jarvinen@linux.intel.com>
+Signed-off-by: Ilpo Järvinen <ilpo.jarvinen@linux.intel.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/platform/surface/aggregator/core.c | 5 ++++-
+ 1 file changed, 4 insertions(+), 1 deletion(-)
+
+--- a/drivers/platform/surface/aggregator/core.c
++++ b/drivers/platform/surface/aggregator/core.c
+@@ -231,9 +231,12 @@ static int ssam_receive_buf(struct serde
+ size_t n)
+ {
+ struct ssam_controller *ctrl;
++ int ret;
+
+ ctrl = serdev_device_get_drvdata(dev);
+- return ssam_controller_receive_buf(ctrl, buf, n);
++ ret = ssam_controller_receive_buf(ctrl, buf, n);
++
++ return ret < 0 ? 0 : ret;
+ }
+
+ static void ssam_write_wakeup(struct serdev_device *dev)
--- /dev/null
+From bdefd9913bdd453991ef756b6f7176e8ad80d786 Mon Sep 17 00:00:00 2001
+From: Lukasz Luba <lukasz.luba@arm.com>
+Date: Fri, 1 Dec 2023 12:32:05 +0000
+Subject: powercap: DTPM: Fix missing cpufreq_cpu_put() calls
+
+From: Lukasz Luba <lukasz.luba@arm.com>
+
+commit bdefd9913bdd453991ef756b6f7176e8ad80d786 upstream.
+
+The policy returned by cpufreq_cpu_get() has to be released with
+the help of cpufreq_cpu_put() to balance its kobject reference counter
+properly.
+
+Add the missing calls to cpufreq_cpu_put() in the code.
+
+Fixes: 0aea2e4ec2a2 ("powercap/dtpm_cpu: Reset per_cpu variable in the release function")
+Fixes: 0e8f68d7f048 ("powercap/drivers/dtpm: Add CPU energy model based support")
+Cc: v5.16+ <stable@vger.kernel.org> # v5.16+
+Signed-off-by: Lukasz Luba <lukasz.luba@arm.com>
+Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/powercap/dtpm_cpu.c | 17 +++++++++++++----
+ 1 file changed, 13 insertions(+), 4 deletions(-)
+
+--- a/drivers/powercap/dtpm_cpu.c
++++ b/drivers/powercap/dtpm_cpu.c
+@@ -140,6 +140,8 @@ static void pd_release(struct dtpm *dtpm
+ if (policy) {
+ for_each_cpu(dtpm_cpu->cpu, policy->related_cpus)
+ per_cpu(dtpm_per_cpu, dtpm_cpu->cpu) = NULL;
++
++ cpufreq_cpu_put(policy);
+ }
+
+ kfree(dtpm_cpu);
+@@ -191,12 +193,16 @@ static int __dtpm_cpu_setup(int cpu, str
+ return 0;
+
+ pd = em_cpu_get(cpu);
+- if (!pd || em_is_artificial(pd))
+- return -EINVAL;
++ if (!pd || em_is_artificial(pd)) {
++ ret = -EINVAL;
++ goto release_policy;
++ }
+
+ dtpm_cpu = kzalloc(sizeof(*dtpm_cpu), GFP_KERNEL);
+- if (!dtpm_cpu)
+- return -ENOMEM;
++ if (!dtpm_cpu) {
++ ret = -ENOMEM;
++ goto release_policy;
++ }
+
+ dtpm_init(&dtpm_cpu->dtpm, &dtpm_ops);
+ dtpm_cpu->cpu = cpu;
+@@ -216,6 +222,7 @@ static int __dtpm_cpu_setup(int cpu, str
+ if (ret)
+ goto out_dtpm_unregister;
+
++ cpufreq_cpu_put(policy);
+ return 0;
+
+ out_dtpm_unregister:
+@@ -227,6 +234,8 @@ out_kfree_dtpm_cpu:
+ per_cpu(dtpm_per_cpu, cpu) = NULL;
+ kfree(dtpm_cpu);
+
++release_policy:
++ cpufreq_cpu_put(policy);
+ return ret;
+ }
+
--- /dev/null
+From 4b0768b6556af56ee9b7cf4e68452a2b6289ae45 Mon Sep 17 00:00:00 2001
+From: ChunHao Lin <hau@realtek.com>
+Date: Wed, 29 Nov 2023 23:53:50 +0800
+Subject: r8169: fix rtl8125b PAUSE frames blasting when suspended
+
+From: ChunHao Lin <hau@realtek.com>
+
+commit 4b0768b6556af56ee9b7cf4e68452a2b6289ae45 upstream.
+
+When FIFO reaches near full state, device will issue pause frame.
+If pause slot is enabled(set to 1), in this time, device will issue
+pause frame only once. But if pause slot is disabled(set to 0), device
+will keep sending pause frames until FIFO reaches near empty state.
+
+When pause slot is disabled, if there is no one to handle receive
+packets, device FIFO will reach near full state and keep sending
+pause frames. That will impact entire local area network.
+
+This issue can be reproduced in Chromebox (not Chromebook) in
+developer mode running a test image (and v5.10 kernel):
+1) ping -f $CHROMEBOX (from workstation on same local network)
+2) run "powerd_dbus_suspend" from command line on the $CHROMEBOX
+3) ping $ROUTER (wait until ping fails from workstation)
+
+Takes about ~20-30 seconds after step 2 for the local network to
+stop working.
+
+Fix this issue by enabling pause slot to only send pause frame once
+when FIFO reaches near full state.
+
+Fixes: f1bce4ad2f1c ("r8169: add support for RTL8125")
+Reported-by: Grant Grundler <grundler@chromium.org>
+Tested-by: Grant Grundler <grundler@chromium.org>
+Cc: stable@vger.kernel.org
+Signed-off-by: ChunHao Lin <hau@realtek.com>
+Reviewed-by: Jacob Keller <jacob.e.keller@intel.com>
+Reviewed-by: Heiner Kallweit <hkallweit1@gmail.com>
+Link: https://lore.kernel.org/r/20231129155350.5843-1-hau@realtek.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/net/ethernet/realtek/r8169_main.c | 7 ++++++-
+ 1 file changed, 6 insertions(+), 1 deletion(-)
+
+--- a/drivers/net/ethernet/realtek/r8169_main.c
++++ b/drivers/net/ethernet/realtek/r8169_main.c
+@@ -196,6 +196,7 @@ enum rtl_registers {
+ /* No threshold before first PCI xfer */
+ #define RX_FIFO_THRESH (7 << RXCFG_FIFO_SHIFT)
+ #define RX_EARLY_OFF (1 << 11)
++#define RX_PAUSE_SLOT_ON (1 << 11) /* 8125b and later */
+ #define RXCFG_DMA_SHIFT 8
+ /* Unlimited maximum PCI burst. */
+ #define RX_DMA_BURST (7 << RXCFG_DMA_SHIFT)
+@@ -2306,9 +2307,13 @@ static void rtl_init_rxcfg(struct rtl816
+ case RTL_GIGA_MAC_VER_40 ... RTL_GIGA_MAC_VER_53:
+ RTL_W32(tp, RxConfig, RX128_INT_EN | RX_MULTI_EN | RX_DMA_BURST | RX_EARLY_OFF);
+ break;
+- case RTL_GIGA_MAC_VER_61 ... RTL_GIGA_MAC_VER_63:
++ case RTL_GIGA_MAC_VER_61:
+ RTL_W32(tp, RxConfig, RX_FETCH_DFLT_8125 | RX_DMA_BURST);
+ break;
++ case RTL_GIGA_MAC_VER_63:
++ RTL_W32(tp, RxConfig, RX_FETCH_DFLT_8125 | RX_DMA_BURST |
++ RX_PAUSE_SLOT_ON);
++ break;
+ default:
+ RTL_W32(tp, RxConfig, RX128_INT_EN | RX_DMA_BURST);
+ break;
--- /dev/null
+From fea88064445a59584460f7f67d102b6e5fc1ca1d Mon Sep 17 00:00:00 2001
+From: Matthias Reichl <hias@horus.com>
+Date: Sun, 3 Dec 2023 23:22:16 +0100
+Subject: regmap: fix bogus error on regcache_sync success
+
+From: Matthias Reichl <hias@horus.com>
+
+commit fea88064445a59584460f7f67d102b6e5fc1ca1d upstream.
+
+Since commit 0ec7731655de ("regmap: Ensure range selector registers
+are updated after cache sync") opening pcm512x based soundcards fail
+with EINVAL and dmesg shows sync cache and pm_runtime_get errors:
+
+[ 228.794676] pcm512x 1-004c: Failed to sync cache: -22
+[ 228.794740] pcm512x 1-004c: ASoC: error at snd_soc_pcm_component_pm_runtime_get on pcm512x.1-004c: -22
+
+This is caused by the cache check result leaking out into the
+regcache_sync return value.
+
+Fix this by making the check local-only, as the comment above the
+regcache_read call states a non-zero return value means there's
+nothing to do so the return value should not be altered.
+
+Fixes: 0ec7731655de ("regmap: Ensure range selector registers are updated after cache sync")
+Cc: stable@vger.kernel.org
+Signed-off-by: Matthias Reichl <hias@horus.com>
+Link: https://lore.kernel.org/r/20231203222216.96547-1-hias@horus.com
+Signed-off-by: Mark Brown <broonie@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/base/regmap/regcache.c | 3 +--
+ 1 file changed, 1 insertion(+), 2 deletions(-)
+
+--- a/drivers/base/regmap/regcache.c
++++ b/drivers/base/regmap/regcache.c
+@@ -410,8 +410,7 @@ out:
+ rb_entry(node, struct regmap_range_node, node);
+
+ /* If there's nothing in the cache there's nothing to sync */
+- ret = regcache_read(map, this->selector_reg, &i);
+- if (ret != 0)
++ if (regcache_read(map, this->selector_reg, &i) != 0)
+ continue;
+
+ ret = _regmap_write(map, this->selector_reg, i);
--- /dev/null
+From b2dd797543cfa6580eac8408dd67fa02164d9e56 Mon Sep 17 00:00:00 2001
+From: "Steven Rostedt (Google)" <rostedt@goodmis.org>
+Date: Wed, 6 Dec 2023 10:02:44 -0500
+Subject: ring-buffer: Force absolute timestamp on discard of event
+
+From: Steven Rostedt (Google) <rostedt@goodmis.org>
+
+commit b2dd797543cfa6580eac8408dd67fa02164d9e56 upstream.
+
+There's a race where if an event is discarded from the ring buffer and an
+interrupt were to happen at that time and insert an event, the time stamp
+is still used from the discarded event as an offset. This can screw up the
+timings.
+
+If the event is going to be discarded, set the "before_stamp" to zero.
+When a new event comes in, it compares the "before_stamp" with the
+"write_stamp" and if they are not equal, it will insert an absolute
+timestamp. This will prevent the timings from getting out of sync due to
+the discarded event.
+
+Link: https://lore.kernel.org/linux-trace-kernel/20231206100244.5130f9b3@gandalf.local.home
+
+Cc: stable@vger.kernel.org
+Cc: Masami Hiramatsu <mhiramat@kernel.org>
+Cc: Mark Rutland <mark.rutland@arm.com>
+Cc: Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
+Fixes: 6f6be606e763f ("ring-buffer: Force before_stamp and write_stamp to be different on discard")
+Signed-off-by: Steven Rostedt (Google) <rostedt@goodmis.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ kernel/trace/ring_buffer.c | 19 ++++++++-----------
+ 1 file changed, 8 insertions(+), 11 deletions(-)
+
+--- a/kernel/trace/ring_buffer.c
++++ b/kernel/trace/ring_buffer.c
+@@ -3030,23 +3030,20 @@ rb_try_to_discard(struct ring_buffer_per
+ local_read(&bpage->write) & ~RB_WRITE_MASK;
+ unsigned long event_length = rb_event_length(event);
+
++ /*
++ * For the before_stamp to be different than the write_stamp
++ * to make sure that the next event adds an absolute
++ * value and does not rely on the saved write stamp, which
++ * is now going to be bogus.
++ */
++ rb_time_set(&cpu_buffer->before_stamp, 0);
++
+ /* Something came in, can't discard */
+ if (!rb_time_cmpxchg(&cpu_buffer->write_stamp,
+ write_stamp, write_stamp - delta))
+ return false;
+
+ /*
+- * It's possible that the event time delta is zero
+- * (has the same time stamp as the previous event)
+- * in which case write_stamp and before_stamp could
+- * be the same. In such a case, force before_stamp
+- * to be different than write_stamp. It doesn't
+- * matter what it is, as long as its different.
+- */
+- if (!delta)
+- rb_time_set(&cpu_buffer->before_stamp, 0);
+-
+- /*
+ * If an event were to come in now, it would see that the
+ * write_stamp and the before_stamp are different, and assume
+ * that this event just added itself before updating
--- /dev/null
+From f458a1453424e03462b5bb539673c9a3cddda480 Mon Sep 17 00:00:00 2001
+From: "Steven Rostedt (Google)" <rostedt@goodmis.org>
+Date: Wed, 6 Dec 2023 10:00:50 -0500
+Subject: ring-buffer: Test last update in 32bit version of __rb_time_read()
+
+From: Steven Rostedt (Google) <rostedt@goodmis.org>
+
+commit f458a1453424e03462b5bb539673c9a3cddda480 upstream.
+
+Since 64 bit cmpxchg() is very expensive on 32bit architectures, the
+timestamp used by the ring buffer does some interesting tricks to be able
+to still have an atomic 64 bit number. It originally just used 60 bits and
+broke it up into two 32 bit words where the extra 2 bits were used for
+synchronization. But this was not enough for all use cases, and all 64
+bits were required.
+
+The 32bit version of the ring buffer timestamp was then broken up into 3
+32bit words using the same counter trick. But one update was not done. The
+check to see if the read operation was done without interruption only
+checked the first two words and not last one (like it had before this
+update). Fix it by making sure all three updates happen without
+interruption by comparing the initial counter with the last updated
+counter.
+
+Link: https://lore.kernel.org/linux-trace-kernel/20231206100050.3100b7bb@gandalf.local.home
+
+Cc: stable@vger.kernel.org
+Cc: Masami Hiramatsu <mhiramat@kernel.org>
+Cc: Mark Rutland <mark.rutland@arm.com>
+Cc: Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
+Fixes: f03f2abce4f39 ("ring-buffer: Have 32 bit time stamps use all 64 bits")
+Signed-off-by: Steven Rostedt (Google) <rostedt@goodmis.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ kernel/trace/ring_buffer.c | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+--- a/kernel/trace/ring_buffer.c
++++ b/kernel/trace/ring_buffer.c
+@@ -644,8 +644,8 @@ static inline bool __rb_time_read(rb_tim
+
+ *cnt = rb_time_cnt(top);
+
+- /* If top and bottom counts don't match, this interrupted a write */
+- if (*cnt != rb_time_cnt(bottom))
++ /* If top and msb counts don't match, this interrupted a write */
++ if (*cnt != rb_time_cnt(msb))
+ return false;
+
+ /* The shift to msb will lose its cnt bits */
alsa-hda-realtek-add-new-framework-laptop-to-quirks.patch
alsa-hda-realtek-add-framework-laptop-16-to-quirks.patch
alsa-hda-realtek-add-quirk-for-lenovo-yoga-pro-7.patch
+ring-buffer-test-last-update-in-32bit-version-of-__rb_time_read.patch
+ring-buffer-force-absolute-timestamp-on-discard-of-event.patch
+highmem-fix-a-memory-copy-problem-in-memcpy_from_folio.patch
+nilfs2-fix-missing-error-check-for-sb_set_blocksize-call.patch
+nilfs2-prevent-warning-in-nilfs_sufile_set_segment_usage.patch
+lib-group_cpus.c-avoid-acquiring-cpu-hotplug-lock-in-group_cpus_evenly.patch
+cgroup_freezer-cgroup_freezing-check-if-not-frozen.patch
+checkstack-fix-printed-address.patch
+tracing-always-update-snapshot-buffer-size.patch
+tracing-stop-current-tracer-when-resizing-buffer.patch
+tracing-disable-snapshot-buffer-when-stopping-instance-tracers.patch
+tracing-fix-incomplete-locking-when-disabling-buffered-events.patch
+tracing-fix-a-possible-race-when-disabling-buffered-events.patch
+leds-trigger-netdev-fix-rtnl-handling-to-prevent-potential-deadlock.patch
+nfp-flower-fix-for-take-a-mutex-lock-in-soft-irq-context-and-rcu-lock.patch
+packet-move-reference-count-in-packet_sock-to-atomic_long_t.patch
+r8169-fix-rtl8125b-pause-frames-blasting-when-suspended.patch
+regmap-fix-bogus-error-on-regcache_sync-success.patch
+platform-surface-aggregator-fix-recv_buf-return-value.patch
+workqueue-make-sure-that-wq_unbound_cpumask-is-never-empty.patch
+hugetlb-fix-null-ptr-deref-in-hugetlb_vma_lock_write.patch
+drivers-base-cpu-crash-data-showing-should-depends-on-kexec_core.patch
+mm-memory_hotplug-add-missing-mem_hotplug_lock.patch
+mm-fix-oops-when-filemap_map_pmd-without-prealloc_pte.patch
+mm-memory_hotplug-fix-error-handling-in-add_memory_resource.patch
+powercap-dtpm-fix-missing-cpufreq_cpu_put-calls.patch
+md-raid6-use-valid-sector-values-to-determine-if-an-i-o-should-wait-on-the-reshape.patch
+drm-atomic-helpers-invoke-end_fb_access-while-owning-plane-state.patch
+drm-i915-mst-fix-.mode_valid_ctx-return-values.patch
+drm-i915-mst-reject-modes-that-require-the-bigjoiner.patch
+drm-i915-skip-some-timing-checks-on-bxt-glk-dsi-transcoders.patch
+arm64-dts-mt7986-change-cooling-trips.patch
+arm64-dts-mt7986-define-3w-max-power-to-both-sfp-on-bpi-r3.patch
+arm64-dts-mt7986-fix-emmc-hs400-mode-without-uboot-initialization.patch
+arm64-dts-mediatek-mt7622-fix-memory-node-warning-check.patch
+arm64-dts-mediatek-mt8183-kukui-jacuzzi-fix-dsi-unnecessary-cells-properties.patch
+arm64-dts-mediatek-cherry-fix-interrupt-cells-for-mt6360-on-i2c7.patch
+arm64-dts-mediatek-mt8173-evb-fix-regulator-fixed-node-names.patch
+arm64-dts-mediatek-mt8195-fix-pm-suspend-resume-with-venc-clocks.patch
+arm64-dts-mediatek-mt8183-fix-unit-address-for-scp-reserved-memory.patch
+arm64-dts-mediatek-mt8183-move-thermal-zones-to-the-root-node.patch
+arm64-dts-mediatek-mt8183-evb-fix-unit_address_vs_reg-warning-on-ntc.patch
+arm64-dts-mediatek-mt8186-fix-clock-names-for-power-domains.patch
+arm64-dts-mediatek-mt8186-change-gpu-speedbin-nvmem-cell-name.patch
--- /dev/null
+From 7be76461f302ec05cbd62b90b2a05c64299ca01f Mon Sep 17 00:00:00 2001
+From: "Steven Rostedt (Google)" <rostedt@goodmis.org>
+Date: Tue, 5 Dec 2023 16:52:09 -0500
+Subject: tracing: Always update snapshot buffer size
+
+From: Steven Rostedt (Google) <rostedt@goodmis.org>
+
+commit 7be76461f302ec05cbd62b90b2a05c64299ca01f upstream.
+
+It use to be that only the top level instance had a snapshot buffer (for
+latency tracers like wakeup and irqsoff). The update of the ring buffer
+size would check if the instance was the top level and if so, it would
+also update the snapshot buffer as it needs to be the same as the main
+buffer.
+
+Now that lower level instances also has a snapshot buffer, they too need
+to update their snapshot buffer sizes when the main buffer is changed,
+otherwise the following can be triggered:
+
+ # cd /sys/kernel/tracing
+ # echo 1500 > buffer_size_kb
+ # mkdir instances/foo
+ # echo irqsoff > instances/foo/current_tracer
+ # echo 1000 > instances/foo/buffer_size_kb
+
+Produces:
+
+ WARNING: CPU: 2 PID: 856 at kernel/trace/trace.c:1938 update_max_tr_single.part.0+0x27d/0x320
+
+Which is:
+
+ ret = ring_buffer_swap_cpu(tr->max_buffer.buffer, tr->array_buffer.buffer, cpu);
+
+ if (ret == -EBUSY) {
+ [..]
+ }
+
+ WARN_ON_ONCE(ret && ret != -EAGAIN && ret != -EBUSY); <== here
+
+That's because ring_buffer_swap_cpu() has:
+
+ int ret = -EINVAL;
+
+ [..]
+
+ /* At least make sure the two buffers are somewhat the same */
+ if (cpu_buffer_a->nr_pages != cpu_buffer_b->nr_pages)
+ goto out;
+
+ [..]
+ out:
+ return ret;
+ }
+
+Instead, update all instances' snapshot buffer sizes when their main
+buffer size is updated.
+
+Link: https://lkml.kernel.org/r/20231205220010.454662151@goodmis.org
+
+Cc: stable@vger.kernel.org
+Cc: Masami Hiramatsu <mhiramat@kernel.org>
+Cc: Mark Rutland <mark.rutland@arm.com>
+Cc: Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
+Cc: Andrew Morton <akpm@linux-foundation.org>
+Fixes: 6d9b3fa5e7f6 ("tracing: Move tracing_max_latency into trace_array")
+Signed-off-by: Steven Rostedt (Google) <rostedt@goodmis.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ kernel/trace/trace.c | 3 +--
+ 1 file changed, 1 insertion(+), 2 deletions(-)
+
+--- a/kernel/trace/trace.c
++++ b/kernel/trace/trace.c
+@@ -6399,8 +6399,7 @@ static int __tracing_resize_ring_buffer(
+ return ret;
+
+ #ifdef CONFIG_TRACER_MAX_TRACE
+- if (!(tr->flags & TRACE_ARRAY_FL_GLOBAL) ||
+- !tr->current_trace->use_max_tr)
++ if (!tr->current_trace->use_max_tr)
+ goto out;
+
+ ret = ring_buffer_resize(tr->max_buffer.buffer, size, cpu);
--- /dev/null
+From b538bf7d0ec11ca49f536dfda742a5f6db90a798 Mon Sep 17 00:00:00 2001
+From: "Steven Rostedt (Google)" <rostedt@goodmis.org>
+Date: Tue, 5 Dec 2023 16:52:11 -0500
+Subject: tracing: Disable snapshot buffer when stopping instance tracers
+
+From: Steven Rostedt (Google) <rostedt@goodmis.org>
+
+commit b538bf7d0ec11ca49f536dfda742a5f6db90a798 upstream.
+
+It use to be that only the top level instance had a snapshot buffer (for
+latency tracers like wakeup and irqsoff). When stopping a tracer in an
+instance would not disable the snapshot buffer. This could have some
+unintended consequences if the irqsoff tracer is enabled.
+
+Consolidate the tracing_start/stop() with tracing_start/stop_tr() so that
+all instances behave the same. The tracing_start/stop() functions will
+just call their respective tracing_start/stop_tr() with the global_array
+passed in.
+
+Link: https://lkml.kernel.org/r/20231205220011.041220035@goodmis.org
+
+Cc: stable@vger.kernel.org
+Cc: Masami Hiramatsu <mhiramat@kernel.org>
+Cc: Mark Rutland <mark.rutland@arm.com>
+Cc: Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
+Cc: Andrew Morton <akpm@linux-foundation.org>
+Fixes: 6d9b3fa5e7f6 ("tracing: Move tracing_max_latency into trace_array")
+Signed-off-by: Steven Rostedt (Google) <rostedt@goodmis.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ kernel/trace/trace.c | 110 +++++++++++++++------------------------------------
+ 1 file changed, 34 insertions(+), 76 deletions(-)
+
+--- a/kernel/trace/trace.c
++++ b/kernel/trace/trace.c
+@@ -2359,13 +2359,7 @@ int is_tracing_stopped(void)
+ return global_trace.stop_count;
+ }
+
+-/**
+- * tracing_start - quick start of the tracer
+- *
+- * If tracing is enabled but was stopped by tracing_stop,
+- * this will start the tracer back up.
+- */
+-void tracing_start(void)
++static void tracing_start_tr(struct trace_array *tr)
+ {
+ struct trace_buffer *buffer;
+ unsigned long flags;
+@@ -2373,119 +2367,83 @@ void tracing_start(void)
+ if (tracing_disabled)
+ return;
+
+- raw_spin_lock_irqsave(&global_trace.start_lock, flags);
+- if (--global_trace.stop_count) {
+- if (global_trace.stop_count < 0) {
++ raw_spin_lock_irqsave(&tr->start_lock, flags);
++ if (--tr->stop_count) {
++ if (WARN_ON_ONCE(tr->stop_count < 0)) {
+ /* Someone screwed up their debugging */
+- WARN_ON_ONCE(1);
+- global_trace.stop_count = 0;
++ tr->stop_count = 0;
+ }
+ goto out;
+ }
+
+ /* Prevent the buffers from switching */
+- arch_spin_lock(&global_trace.max_lock);
++ arch_spin_lock(&tr->max_lock);
+
+- buffer = global_trace.array_buffer.buffer;
++ buffer = tr->array_buffer.buffer;
+ if (buffer)
+ ring_buffer_record_enable(buffer);
+
+ #ifdef CONFIG_TRACER_MAX_TRACE
+- buffer = global_trace.max_buffer.buffer;
++ buffer = tr->max_buffer.buffer;
+ if (buffer)
+ ring_buffer_record_enable(buffer);
+ #endif
+
+- arch_spin_unlock(&global_trace.max_lock);
+-
+- out:
+- raw_spin_unlock_irqrestore(&global_trace.start_lock, flags);
+-}
+-
+-static void tracing_start_tr(struct trace_array *tr)
+-{
+- struct trace_buffer *buffer;
+- unsigned long flags;
+-
+- if (tracing_disabled)
+- return;
+-
+- /* If global, we need to also start the max tracer */
+- if (tr->flags & TRACE_ARRAY_FL_GLOBAL)
+- return tracing_start();
+-
+- raw_spin_lock_irqsave(&tr->start_lock, flags);
+-
+- if (--tr->stop_count) {
+- if (tr->stop_count < 0) {
+- /* Someone screwed up their debugging */
+- WARN_ON_ONCE(1);
+- tr->stop_count = 0;
+- }
+- goto out;
+- }
+-
+- buffer = tr->array_buffer.buffer;
+- if (buffer)
+- ring_buffer_record_enable(buffer);
++ arch_spin_unlock(&tr->max_lock);
+
+ out:
+ raw_spin_unlock_irqrestore(&tr->start_lock, flags);
+ }
+
+ /**
+- * tracing_stop - quick stop of the tracer
++ * tracing_start - quick start of the tracer
+ *
+- * Light weight way to stop tracing. Use in conjunction with
+- * tracing_start.
++ * If tracing is enabled but was stopped by tracing_stop,
++ * this will start the tracer back up.
+ */
+-void tracing_stop(void)
++void tracing_start(void)
++
++{
++ return tracing_start_tr(&global_trace);
++}
++
++static void tracing_stop_tr(struct trace_array *tr)
+ {
+ struct trace_buffer *buffer;
+ unsigned long flags;
+
+- raw_spin_lock_irqsave(&global_trace.start_lock, flags);
+- if (global_trace.stop_count++)
++ raw_spin_lock_irqsave(&tr->start_lock, flags);
++ if (tr->stop_count++)
+ goto out;
+
+ /* Prevent the buffers from switching */
+- arch_spin_lock(&global_trace.max_lock);
++ arch_spin_lock(&tr->max_lock);
+
+- buffer = global_trace.array_buffer.buffer;
++ buffer = tr->array_buffer.buffer;
+ if (buffer)
+ ring_buffer_record_disable(buffer);
+
+ #ifdef CONFIG_TRACER_MAX_TRACE
+- buffer = global_trace.max_buffer.buffer;
++ buffer = tr->max_buffer.buffer;
+ if (buffer)
+ ring_buffer_record_disable(buffer);
+ #endif
+
+- arch_spin_unlock(&global_trace.max_lock);
++ arch_spin_unlock(&tr->max_lock);
+
+ out:
+- raw_spin_unlock_irqrestore(&global_trace.start_lock, flags);
++ raw_spin_unlock_irqrestore(&tr->start_lock, flags);
+ }
+
+-static void tracing_stop_tr(struct trace_array *tr)
++/**
++ * tracing_stop - quick stop of the tracer
++ *
++ * Light weight way to stop tracing. Use in conjunction with
++ * tracing_start.
++ */
++void tracing_stop(void)
+ {
+- struct trace_buffer *buffer;
+- unsigned long flags;
+-
+- /* If global, we need to also stop the max tracer */
+- if (tr->flags & TRACE_ARRAY_FL_GLOBAL)
+- return tracing_stop();
+-
+- raw_spin_lock_irqsave(&tr->start_lock, flags);
+- if (tr->stop_count++)
+- goto out;
+-
+- buffer = tr->array_buffer.buffer;
+- if (buffer)
+- ring_buffer_record_disable(buffer);
+-
+- out:
+- raw_spin_unlock_irqrestore(&tr->start_lock, flags);
++ return tracing_stop_tr(&global_trace);
+ }
+
+ static int trace_save_cmdline(struct task_struct *tsk)
--- /dev/null
+From c0591b1cccf708a47bc465c62436d669a4213323 Mon Sep 17 00:00:00 2001
+From: Petr Pavlu <petr.pavlu@suse.com>
+Date: Tue, 5 Dec 2023 17:17:36 +0100
+Subject: tracing: Fix a possible race when disabling buffered events
+
+From: Petr Pavlu <petr.pavlu@suse.com>
+
+commit c0591b1cccf708a47bc465c62436d669a4213323 upstream.
+
+Function trace_buffered_event_disable() is responsible for freeing pages
+backing buffered events and this process can run concurrently with
+trace_event_buffer_lock_reserve().
+
+The following race is currently possible:
+
+* Function trace_buffered_event_disable() is called on CPU 0. It
+ increments trace_buffered_event_cnt on each CPU and waits via
+ synchronize_rcu() for each user of trace_buffered_event to complete.
+
+* After synchronize_rcu() is finished, function
+ trace_buffered_event_disable() has the exclusive access to
+ trace_buffered_event. All counters trace_buffered_event_cnt are at 1
+ and all pointers trace_buffered_event are still valid.
+
+* At this point, on a different CPU 1, the execution reaches
+ trace_event_buffer_lock_reserve(). The function calls
+ preempt_disable_notrace() and only now enters an RCU read-side
+ critical section. The function proceeds and reads a still valid
+ pointer from trace_buffered_event[CPU1] into the local variable
+ "entry". However, it doesn't yet read trace_buffered_event_cnt[CPU1]
+ which happens later.
+
+* Function trace_buffered_event_disable() continues. It frees
+ trace_buffered_event[CPU1] and decrements
+ trace_buffered_event_cnt[CPU1] back to 0.
+
+* Function trace_event_buffer_lock_reserve() continues. It reads and
+ increments trace_buffered_event_cnt[CPU1] from 0 to 1. This makes it
+ believe that it can use the "entry" that it already obtained but the
+ pointer is now invalid and any access results in a use-after-free.
+
+Fix the problem by making a second synchronize_rcu() call after all
+trace_buffered_event values are set to NULL. This waits on all potential
+users in trace_event_buffer_lock_reserve() that still read a previous
+pointer from trace_buffered_event.
+
+Link: https://lore.kernel.org/all/20231127151248.7232-2-petr.pavlu@suse.com/
+Link: https://lkml.kernel.org/r/20231205161736.19663-4-petr.pavlu@suse.com
+
+Cc: stable@vger.kernel.org
+Fixes: 0fc1b09ff1ff ("tracing: Use temp buffer when filtering events")
+Signed-off-by: Petr Pavlu <petr.pavlu@suse.com>
+Signed-off-by: Steven Rostedt (Google) <rostedt@goodmis.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ kernel/trace/trace.c | 12 ++++++++----
+ 1 file changed, 8 insertions(+), 4 deletions(-)
+
+--- a/kernel/trace/trace.c
++++ b/kernel/trace/trace.c
+@@ -2790,13 +2790,17 @@ void trace_buffered_event_disable(void)
+ free_page((unsigned long)per_cpu(trace_buffered_event, cpu));
+ per_cpu(trace_buffered_event, cpu) = NULL;
+ }
++
+ /*
+- * Make sure trace_buffered_event is NULL before clearing
+- * trace_buffered_event_cnt.
++ * Wait for all CPUs that potentially started checking if they can use
++ * their event buffer only after the previous synchronize_rcu() call and
++ * they still read a valid pointer from trace_buffered_event. It must be
++ * ensured they don't see cleared trace_buffered_event_cnt else they
++ * could wrongly decide to use the pointed-to buffer which is now freed.
+ */
+- smp_wmb();
++ synchronize_rcu();
+
+- /* Do the work on each cpu */
++ /* For each CPU, relinquish the buffer */
+ on_each_cpu_mask(tracing_buffer_mask, enable_trace_buffered_event, NULL,
+ true);
+ }
--- /dev/null
+From 7fed14f7ac9cf5e38c693836fe4a874720141845 Mon Sep 17 00:00:00 2001
+From: Petr Pavlu <petr.pavlu@suse.com>
+Date: Tue, 5 Dec 2023 17:17:34 +0100
+Subject: tracing: Fix incomplete locking when disabling buffered events
+
+From: Petr Pavlu <petr.pavlu@suse.com>
+
+commit 7fed14f7ac9cf5e38c693836fe4a874720141845 upstream.
+
+The following warning appears when using buffered events:
+
+[ 203.556451] WARNING: CPU: 53 PID: 10220 at kernel/trace/ring_buffer.c:3912 ring_buffer_discard_commit+0x2eb/0x420
+[...]
+[ 203.670690] CPU: 53 PID: 10220 Comm: stress-ng-sysin Tainted: G E 6.7.0-rc2-default #4 56e6d0fcf5581e6e51eaaecbdaec2a2338c80f3a
+[ 203.670704] Hardware name: Intel Corp. GROVEPORT/GROVEPORT, BIOS GVPRCRB1.86B.0016.D04.1705030402 05/03/2017
+[ 203.670709] RIP: 0010:ring_buffer_discard_commit+0x2eb/0x420
+[ 203.735721] Code: 4c 8b 4a 50 48 8b 42 48 49 39 c1 0f 84 b3 00 00 00 49 83 e8 01 75 b1 48 8b 42 10 f0 ff 40 08 0f 0b e9 fc fe ff ff f0 ff 47 08 <0f> 0b e9 77 fd ff ff 48 8b 42 10 f0 ff 40 08 0f 0b e9 f5 fe ff ff
+[ 203.735734] RSP: 0018:ffffb4ae4f7b7d80 EFLAGS: 00010202
+[ 203.735745] RAX: 0000000000000000 RBX: ffffb4ae4f7b7de0 RCX: ffff8ac10662c000
+[ 203.735754] RDX: ffff8ac0c750be00 RSI: ffff8ac10662c000 RDI: ffff8ac0c004d400
+[ 203.781832] RBP: ffff8ac0c039cea0 R08: 0000000000000000 R09: 0000000000000000
+[ 203.781839] R10: 0000000000000000 R11: 0000000000000000 R12: 0000000000000000
+[ 203.781842] R13: ffff8ac10662c000 R14: ffff8ac0c004d400 R15: ffff8ac10662c008
+[ 203.781846] FS: 00007f4cd8a67740(0000) GS:ffff8ad798880000(0000) knlGS:0000000000000000
+[ 203.781851] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
+[ 203.781855] CR2: 0000559766a74028 CR3: 00000001804c4000 CR4: 00000000001506f0
+[ 203.781862] Call Trace:
+[ 203.781870] <TASK>
+[ 203.851949] trace_event_buffer_commit+0x1ea/0x250
+[ 203.851967] trace_event_raw_event_sys_enter+0x83/0xe0
+[ 203.851983] syscall_trace_enter.isra.0+0x182/0x1a0
+[ 203.851990] do_syscall_64+0x3a/0xe0
+[ 203.852075] entry_SYSCALL_64_after_hwframe+0x6e/0x76
+[ 203.852090] RIP: 0033:0x7f4cd870fa77
+[ 203.982920] Code: 00 b8 ff ff ff ff c3 66 2e 0f 1f 84 00 00 00 00 00 66 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 66 90 b8 89 00 00 00 0f 05 <48> 3d 01 f0 ff ff 73 01 c3 48 8b 0d e9 43 0e 00 f7 d8 64 89 01 48
+[ 203.982932] RSP: 002b:00007fff99717dd8 EFLAGS: 00000246 ORIG_RAX: 0000000000000089
+[ 203.982942] RAX: ffffffffffffffda RBX: 0000558ea1d7b6f0 RCX: 00007f4cd870fa77
+[ 203.982948] RDX: 0000000000000000 RSI: 00007fff99717de0 RDI: 0000558ea1d7b6f0
+[ 203.982957] RBP: 00007fff99717de0 R08: 00007fff997180e0 R09: 00007fff997180e0
+[ 203.982962] R10: 00007fff997180e0 R11: 0000000000000246 R12: 00007fff99717f40
+[ 204.049239] R13: 00007fff99718590 R14: 0000558e9f2127a8 R15: 00007fff997180b0
+[ 204.049256] </TASK>
+
+For instance, it can be triggered by running these two commands in
+parallel:
+
+ $ while true; do
+ echo hist:key=id.syscall:val=hitcount > \
+ /sys/kernel/debug/tracing/events/raw_syscalls/sys_enter/trigger;
+ done
+ $ stress-ng --sysinfo $(nproc)
+
+The warning indicates that the current ring_buffer_per_cpu is not in the
+committing state. It happens because the active ring_buffer_event
+doesn't actually come from the ring_buffer_per_cpu but is allocated from
+trace_buffered_event.
+
+The bug is in function trace_buffered_event_disable() where the
+following normally happens:
+
+* The code invokes disable_trace_buffered_event() via
+ smp_call_function_many() and follows it by synchronize_rcu(). This
+ increments the per-CPU variable trace_buffered_event_cnt on each
+ target CPU and grants trace_buffered_event_disable() the exclusive
+ access to the per-CPU variable trace_buffered_event.
+
+* Maintenance is performed on trace_buffered_event, all per-CPU event
+ buffers get freed.
+
+* The code invokes enable_trace_buffered_event() via
+ smp_call_function_many(). This decrements trace_buffered_event_cnt and
+ releases the access to trace_buffered_event.
+
+A problem is that smp_call_function_many() runs a given function on all
+target CPUs except on the current one. The following can then occur:
+
+* Task X executing trace_buffered_event_disable() runs on CPU 0.
+
+* The control reaches synchronize_rcu() and the task gets rescheduled on
+ another CPU 1.
+
+* The RCU synchronization finishes. At this point,
+ trace_buffered_event_disable() has the exclusive access to all
+ trace_buffered_event variables except trace_buffered_event[CPU0]
+ because trace_buffered_event_cnt[CPU0] is never incremented and if the
+ buffer is currently unused, remains set to 0.
+
+* A different task Y is scheduled on CPU 0 and hits a trace event. The
+ code in trace_event_buffer_lock_reserve() sees that
+ trace_buffered_event_cnt[CPU0] is set to 0 and decides the use the
+ buffer provided by trace_buffered_event[CPU0].
+
+* Task X continues its execution in trace_buffered_event_disable(). The
+ code incorrectly frees the event buffer pointed by
+ trace_buffered_event[CPU0] and resets the variable to NULL.
+
+* Task Y writes event data to the now freed buffer and later detects the
+ created inconsistency.
+
+The issue is observable since commit dea499781a11 ("tracing: Fix warning
+in trace_buffered_event_disable()") which moved the call of
+trace_buffered_event_disable() in __ftrace_event_enable_disable()
+earlier, prior to invoking call->class->reg(.. TRACE_REG_UNREGISTER ..).
+The underlying problem in trace_buffered_event_disable() is however
+present since the original implementation in commit 0fc1b09ff1ff
+("tracing: Use temp buffer when filtering events").
+
+Fix the problem by replacing the two smp_call_function_many() calls with
+on_each_cpu_mask() which invokes a given callback on all CPUs.
+
+Link: https://lore.kernel.org/all/20231127151248.7232-2-petr.pavlu@suse.com/
+Link: https://lkml.kernel.org/r/20231205161736.19663-2-petr.pavlu@suse.com
+
+Cc: stable@vger.kernel.org
+Fixes: 0fc1b09ff1ff ("tracing: Use temp buffer when filtering events")
+Fixes: dea499781a11 ("tracing: Fix warning in trace_buffered_event_disable()")
+Signed-off-by: Petr Pavlu <petr.pavlu@suse.com>
+Signed-off-by: Steven Rostedt (Google) <rostedt@goodmis.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ kernel/trace/trace.c | 12 ++++--------
+ 1 file changed, 4 insertions(+), 8 deletions(-)
+
+--- a/kernel/trace/trace.c
++++ b/kernel/trace/trace.c
+@@ -2779,11 +2779,9 @@ void trace_buffered_event_disable(void)
+ if (--trace_buffered_event_ref)
+ return;
+
+- preempt_disable();
+ /* For each CPU, set the buffer as used. */
+- smp_call_function_many(tracing_buffer_mask,
+- disable_trace_buffered_event, NULL, 1);
+- preempt_enable();
++ on_each_cpu_mask(tracing_buffer_mask, disable_trace_buffered_event,
++ NULL, true);
+
+ /* Wait for all current users to finish */
+ synchronize_rcu();
+@@ -2798,11 +2796,9 @@ void trace_buffered_event_disable(void)
+ */
+ smp_wmb();
+
+- preempt_disable();
+ /* Do the work on each cpu */
+- smp_call_function_many(tracing_buffer_mask,
+- enable_trace_buffered_event, NULL, 1);
+- preempt_enable();
++ on_each_cpu_mask(tracing_buffer_mask, enable_trace_buffered_event, NULL,
++ true);
+ }
+
+ static struct trace_buffer *temp_buffer;
--- /dev/null
+From d78ab792705c7be1b91243b2544d1a79406a2ad7 Mon Sep 17 00:00:00 2001
+From: "Steven Rostedt (Google)" <rostedt@goodmis.org>
+Date: Tue, 5 Dec 2023 16:52:10 -0500
+Subject: tracing: Stop current tracer when resizing buffer
+
+From: Steven Rostedt (Google) <rostedt@goodmis.org>
+
+commit d78ab792705c7be1b91243b2544d1a79406a2ad7 upstream.
+
+When the ring buffer is being resized, it can cause side effects to the
+running tracer. For instance, there's a race with irqsoff tracer that
+swaps individual per cpu buffers between the main buffer and the snapshot
+buffer. The resize operation modifies the main buffer and then the
+snapshot buffer. If a swap happens in between those two operations it will
+break the tracer.
+
+Simply stop the running tracer before resizing the buffers and enable it
+again when finished.
+
+Link: https://lkml.kernel.org/r/20231205220010.748996423@goodmis.org
+
+Cc: stable@vger.kernel.org
+Cc: Masami Hiramatsu <mhiramat@kernel.org>
+Cc: Mark Rutland <mark.rutland@arm.com>
+Cc: Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
+Cc: Andrew Morton <akpm@linux-foundation.org>
+Fixes: 3928a8a2d9808 ("ftrace: make work with new ring buffer")
+Signed-off-by: Steven Rostedt (Google) <rostedt@goodmis.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ kernel/trace/trace.c | 10 +++++++---
+ 1 file changed, 7 insertions(+), 3 deletions(-)
+
+--- a/kernel/trace/trace.c
++++ b/kernel/trace/trace.c
+@@ -6394,9 +6394,12 @@ static int __tracing_resize_ring_buffer(
+ if (!tr->array_buffer.buffer)
+ return 0;
+
++ /* Do not allow tracing while resizng ring buffer */
++ tracing_stop_tr(tr);
++
+ ret = ring_buffer_resize(tr->array_buffer.buffer, size, cpu);
+ if (ret < 0)
+- return ret;
++ goto out_start;
+
+ #ifdef CONFIG_TRACER_MAX_TRACE
+ if (!tr->current_trace->use_max_tr)
+@@ -6424,7 +6427,7 @@ static int __tracing_resize_ring_buffer(
+ WARN_ON(1);
+ tracing_disabled = 1;
+ }
+- return ret;
++ goto out_start;
+ }
+
+ update_buffer_entries(&tr->max_buffer, cpu);
+@@ -6433,7 +6436,8 @@ static int __tracing_resize_ring_buffer(
+ #endif /* CONFIG_TRACER_MAX_TRACE */
+
+ update_buffer_entries(&tr->array_buffer, cpu);
+-
++ out_start:
++ tracing_start_tr(tr);
+ return ret;
+ }
+
--- /dev/null
+From 4a6c5607d4502ccd1b15b57d57f17d12b6f257a7 Mon Sep 17 00:00:00 2001
+From: Tejun Heo <tj@kernel.org>
+Date: Tue, 21 Nov 2023 11:39:36 -1000
+Subject: workqueue: Make sure that wq_unbound_cpumask is never empty
+
+From: Tejun Heo <tj@kernel.org>
+
+commit 4a6c5607d4502ccd1b15b57d57f17d12b6f257a7 upstream.
+
+During boot, depending on how the housekeeping and workqueue.unbound_cpus
+masks are set, wq_unbound_cpumask can end up empty. Since 8639ecebc9b1
+("workqueue: Implement non-strict affinity scope for unbound workqueues"),
+this may end up feeding -1 as a CPU number into scheduler leading to oopses.
+
+ BUG: unable to handle page fault for address: ffffffff8305e9c0
+ #PF: supervisor read access in kernel mode
+ #PF: error_code(0x0000) - not-present page
+ ...
+ Call Trace:
+ <TASK>
+ select_idle_sibling+0x79/0xaf0
+ select_task_rq_fair+0x1cb/0x7b0
+ try_to_wake_up+0x29c/0x5c0
+ wake_up_process+0x19/0x20
+ kick_pool+0x5e/0xb0
+ __queue_work+0x119/0x430
+ queue_work_on+0x29/0x30
+ ...
+
+An empty wq_unbound_cpumask is a clear misconfiguration and already
+disallowed once system is booted up. Let's warn on and ignore
+unbound_cpumask restrictions which lead to no unbound cpus. While at it,
+also remove now unncessary empty check on wq_unbound_cpumask in
+wq_select_unbound_cpu().
+
+Signed-off-by: Tejun Heo <tj@kernel.org>
+Reported-and-Tested-by: Yong He <alexyonghe@tencent.com>
+Link: http://lkml.kernel.org/r/20231120121623.119780-1-alexyonghe@tencent.com
+Fixes: 8639ecebc9b1 ("workqueue: Implement non-strict affinity scope for unbound workqueues")
+Cc: stable@vger.kernel.org # v6.6+
+Reviewed-by: Waiman Long <longman@redhat.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ kernel/workqueue.c | 22 +++++++++++++++-------
+ 1 file changed, 15 insertions(+), 7 deletions(-)
+
+diff --git a/kernel/workqueue.c b/kernel/workqueue.c
+index 6e578f576a6f..2989b57e154a 100644
+--- a/kernel/workqueue.c
++++ b/kernel/workqueue.c
+@@ -1684,9 +1684,6 @@ static int wq_select_unbound_cpu(int cpu)
+ pr_warn_once("workqueue: round-robin CPU selection forced, expect performance impact\n");
+ }
+
+- if (cpumask_empty(wq_unbound_cpumask))
+- return cpu;
+-
+ new_cpu = __this_cpu_read(wq_rr_cpu_last);
+ new_cpu = cpumask_next_and(new_cpu, wq_unbound_cpumask, cpu_online_mask);
+ if (unlikely(new_cpu >= nr_cpu_ids)) {
+@@ -6515,6 +6512,17 @@ static inline void wq_watchdog_init(void) { }
+
+ #endif /* CONFIG_WQ_WATCHDOG */
+
++static void __init restrict_unbound_cpumask(const char *name, const struct cpumask *mask)
++{
++ if (!cpumask_intersects(wq_unbound_cpumask, mask)) {
++ pr_warn("workqueue: Restricting unbound_cpumask (%*pb) with %s (%*pb) leaves no CPU, ignoring\n",
++ cpumask_pr_args(wq_unbound_cpumask), name, cpumask_pr_args(mask));
++ return;
++ }
++
++ cpumask_and(wq_unbound_cpumask, wq_unbound_cpumask, mask);
++}
++
+ /**
+ * workqueue_init_early - early init for workqueue subsystem
+ *
+@@ -6534,11 +6542,11 @@ void __init workqueue_init_early(void)
+ BUILD_BUG_ON(__alignof__(struct pool_workqueue) < __alignof__(long long));
+
+ BUG_ON(!alloc_cpumask_var(&wq_unbound_cpumask, GFP_KERNEL));
+- cpumask_copy(wq_unbound_cpumask, housekeeping_cpumask(HK_TYPE_WQ));
+- cpumask_and(wq_unbound_cpumask, wq_unbound_cpumask, housekeeping_cpumask(HK_TYPE_DOMAIN));
+-
++ cpumask_copy(wq_unbound_cpumask, cpu_possible_mask);
++ restrict_unbound_cpumask("HK_TYPE_WQ", housekeeping_cpumask(HK_TYPE_WQ));
++ restrict_unbound_cpumask("HK_TYPE_DOMAIN", housekeeping_cpumask(HK_TYPE_DOMAIN));
+ if (!cpumask_empty(&wq_cmdline_cpumask))
+- cpumask_and(wq_unbound_cpumask, wq_unbound_cpumask, &wq_cmdline_cpumask);
++ restrict_unbound_cpumask("workqueue.unbound_cpus", &wq_cmdline_cpumask);
+
+ pwq_cache = KMEM_CACHE(pool_workqueue, SLAB_PANIC);
+
+--
+2.43.0
+