--- /dev/null
+From c9a113dea3a1bf99eed327789c3416828d3e7768 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 7 Aug 2023 11:44:08 +0200
+Subject: ACPI: video: Add backlight=native DMI quirk for Apple iMac12,1 and
+ iMac12,2
+
+From: Hans de Goede <hdegoede@redhat.com>
+
+[ Upstream commit 8cf04bb321f036dd2e523e993897e0789bd5265c ]
+
+Linux defaults to picking the non-working ACPI video backlight interface
+on the Apple iMac12,1 and iMac12,2.
+
+Add a DMI quirk to pick the working native radeon_bl0 interface instead.
+
+Link: https://gitlab.freedesktop.org/drm/amd/-/issues/1838
+Link: https://gitlab.freedesktop.org/drm/amd/-/issues/2753
+Signed-off-by: Hans de Goede <hdegoede@redhat.com>
+Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/acpi/video_detect.c | 18 ++++++++++++++++++
+ 1 file changed, 18 insertions(+)
+
+diff --git a/drivers/acpi/video_detect.c b/drivers/acpi/video_detect.c
+index 0c376edd64fe1..442396f6ed1f9 100644
+--- a/drivers/acpi/video_detect.c
++++ b/drivers/acpi/video_detect.c
+@@ -495,6 +495,24 @@ static const struct dmi_system_id video_detect_dmi_table[] = {
+ DMI_MATCH(DMI_PRODUCT_NAME, "iMac11,3"),
+ },
+ },
++ {
++ /* https://gitlab.freedesktop.org/drm/amd/-/issues/1838 */
++ .callback = video_detect_force_native,
++ /* Apple iMac12,1 */
++ .matches = {
++ DMI_MATCH(DMI_SYS_VENDOR, "Apple Inc."),
++ DMI_MATCH(DMI_PRODUCT_NAME, "iMac12,1"),
++ },
++ },
++ {
++ /* https://gitlab.freedesktop.org/drm/amd/-/issues/2753 */
++ .callback = video_detect_force_native,
++ /* Apple iMac12,2 */
++ .matches = {
++ DMI_MATCH(DMI_SYS_VENDOR, "Apple Inc."),
++ DMI_MATCH(DMI_PRODUCT_NAME, "iMac12,2"),
++ },
++ },
+ {
+ /* https://bugzilla.redhat.com/show_bug.cgi?id=1217249 */
+ .callback = video_detect_force_native,
+--
+2.40.1
+
--- /dev/null
+From 65ea05f982888ba760d308e90846e2e6d62ba6e1 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 18 Apr 2023 08:42:00 +0200
+Subject: ACPI: video: Add backlight=native DMI quirk for Lenovo Ideapad Z470
+
+From: Jiri Slaby (SUSE) <jirislaby@kernel.org>
+
+[ Upstream commit 96b709be183c56293933ef45b8b75f8af268c6de ]
+
+The Lenovo Ideapad Z470 predates Windows 8, so it defaults to using
+acpi_video for backlight control. But this is not functional on this
+model.
+
+Add a DMI quirk to use the native backlight interface which works.
+
+Link: https://bugzilla.suse.com/show_bug.cgi?id=1208724
+Signed-off-by: Jiri Slaby (SUSE) <jirislaby@kernel.org>
+Reviewed-by: Hans de Goede <hdegoede@redhat.com>
+Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/acpi/video_detect.c | 9 +++++++++
+ 1 file changed, 9 insertions(+)
+
+diff --git a/drivers/acpi/video_detect.c b/drivers/acpi/video_detect.c
+index 18cc08c858cf2..0c376edd64fe1 100644
+--- a/drivers/acpi/video_detect.c
++++ b/drivers/acpi/video_detect.c
+@@ -445,6 +445,15 @@ static const struct dmi_system_id video_detect_dmi_table[] = {
+ DMI_MATCH(DMI_BOARD_NAME, "Lenovo IdeaPad S405"),
+ },
+ },
++ {
++ /* https://bugzilla.suse.com/show_bug.cgi?id=1208724 */
++ .callback = video_detect_force_native,
++ /* Lenovo Ideapad Z470 */
++ .matches = {
++ DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
++ DMI_MATCH(DMI_PRODUCT_VERSION, "IdeaPad Z470"),
++ },
++ },
+ {
+ /* https://bugzilla.redhat.com/show_bug.cgi?id=1187004 */
+ .callback = video_detect_force_native,
+--
+2.40.1
+
--- /dev/null
+From 1815c1db2a9d8c640f3bed0d5e2538a88af9882f Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 18 Aug 2023 14:40:03 -0500
+Subject: ACPI: x86: s2idle: Catch multiple ACPI_TYPE_PACKAGE objects
+
+From: Mario Limonciello <mario.limonciello@amd.com>
+
+[ Upstream commit 883cf0d4cf288313b71146ddebdf5d647b76c78b ]
+
+If a badly constructed firmware includes multiple `ACPI_TYPE_PACKAGE`
+objects while evaluating the AMD LPS0 _DSM, there will be a memory
+leak. Explicitly guard against this.
+
+Suggested-by: Bjorn Helgaas <helgaas@kernel.org>
+Signed-off-by: Mario Limonciello <mario.limonciello@amd.com>
+Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/acpi/x86/s2idle.c | 6 ++++++
+ 1 file changed, 6 insertions(+)
+
+diff --git a/drivers/acpi/x86/s2idle.c b/drivers/acpi/x86/s2idle.c
+index 60cc4605169c5..60835953ebfc4 100644
+--- a/drivers/acpi/x86/s2idle.c
++++ b/drivers/acpi/x86/s2idle.c
+@@ -113,6 +113,12 @@ static void lpi_device_get_constraints_amd(void)
+ union acpi_object *package = &out_obj->package.elements[i];
+
+ if (package->type == ACPI_TYPE_PACKAGE) {
++ if (lpi_constraints_table) {
++ acpi_handle_err(lps0_device_handle,
++ "Duplicate constraints list\n");
++ goto free_acpi_buffer;
++ }
++
+ lpi_constraints_table = kcalloc(package->package.count,
+ sizeof(*lpi_constraints_table),
+ GFP_KERNEL);
+--
+2.40.1
+
--- /dev/null
+From 5fe8082ea480d073139fd9141d4c159acc63ef95 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 26 Jun 2023 22:26:06 +0000
+Subject: ACPICA: Add AML_NO_OPERAND_RESOLVE flag to Timer
+
+From: Abhishek Mainkar <abmainkar@nvidia.com>
+
+[ Upstream commit 3a21ffdbc825e0919db9da0e27ee5ff2cc8a863e ]
+
+ACPICA commit 90310989a0790032f5a0140741ff09b545af4bc5
+
+According to the ACPI specification 19.6.134, no argument is required to be passed for ASL Timer instruction. For taking care of no argument, AML_NO_OPERAND_RESOLVE flag is added to ASL Timer instruction opcode.
+
+When ASL timer instruction interpreted by ACPI interpreter, getting error. After adding AML_NO_OPERAND_RESOLVE flag to ASL Timer instruction opcode, issue is not observed.
+
+=============================================================
+UBSAN: array-index-out-of-bounds in acpica/dswexec.c:401:12 index -1 is out of range for type 'union acpi_operand_object *[9]'
+CPU: 37 PID: 1678 Comm: cat Not tainted
+6.0.0-dev-th500-6.0.y-1+bcf8c46459e407-generic-64k
+HW name: NVIDIA BIOS v1.1.1-d7acbfc-dirty 12/19/2022 Call trace:
+ dump_backtrace+0xe0/0x130
+ show_stack+0x20/0x60
+ dump_stack_lvl+0x68/0x84
+ dump_stack+0x18/0x34
+ ubsan_epilogue+0x10/0x50
+ __ubsan_handle_out_of_bounds+0x80/0x90
+ acpi_ds_exec_end_op+0x1bc/0x6d8
+ acpi_ps_parse_loop+0x57c/0x618
+ acpi_ps_parse_aml+0x1e0/0x4b4
+ acpi_ps_execute_method+0x24c/0x2b8
+ acpi_ns_evaluate+0x3a8/0x4bc
+ acpi_evaluate_object+0x15c/0x37c
+ acpi_evaluate_integer+0x54/0x15c
+ show_power+0x8c/0x12c [acpi_power_meter]
+
+Link: https://github.com/acpica/acpica/commit/90310989
+Signed-off-by: Abhishek Mainkar <abmainkar@nvidia.com>
+Signed-off-by: Bob Moore <robert.moore@intel.com>
+Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/acpi/acpica/psopcode.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/drivers/acpi/acpica/psopcode.c b/drivers/acpi/acpica/psopcode.c
+index 09029fe545f14..39e31030e5f49 100644
+--- a/drivers/acpi/acpica/psopcode.c
++++ b/drivers/acpi/acpica/psopcode.c
+@@ -603,7 +603,7 @@ const struct acpi_opcode_info acpi_gbl_aml_op_info[AML_NUM_OPCODES] = {
+
+ /* 7E */ ACPI_OP("Timer", ARGP_TIMER_OP, ARGI_TIMER_OP, ACPI_TYPE_ANY,
+ AML_CLASS_EXECUTE, AML_TYPE_EXEC_0A_0T_1R,
+- AML_FLAGS_EXEC_0A_0T_1R),
++ AML_FLAGS_EXEC_0A_0T_1R | AML_NO_OPERAND_RESOLVE),
+
+ /* ACPI 5.0 opcodes */
+
+--
+2.40.1
+
--- /dev/null
+From 1d6c692fde9f6b38f4bb03f9aab7462ca50193ea Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 2 Aug 2023 10:01:04 -0500
+Subject: ALSA: hda: intel-dsp-cfg: add LunarLake support
+
+From: Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>
+
+[ Upstream commit d2852b8c045ebd31d753b06f2810df5be30ed56a ]
+
+One more PCI ID for the road.
+
+Signed-off-by: Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>
+Reviewed-by: Ranjani Sridharan <ranjani.sridharan@linux.intel.com>
+Reviewed-by: Bard Liao <yung-chuan.liao@linux.intel.com>
+Link: https://lore.kernel.org/r/20230802150105.24604-5-pierre-louis.bossart@linux.intel.com
+Signed-off-by: Takashi Iwai <tiwai@suse.de>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ sound/hda/intel-dsp-config.c | 8 ++++++++
+ 1 file changed, 8 insertions(+)
+
+diff --git a/sound/hda/intel-dsp-config.c b/sound/hda/intel-dsp-config.c
+index 317bdf6dcbef4..2873420c9aca8 100644
+--- a/sound/hda/intel-dsp-config.c
++++ b/sound/hda/intel-dsp-config.c
+@@ -481,6 +481,14 @@ static const struct config_entry config_table[] = {
+ },
+ #endif
+
++/* Lunar Lake */
++#if IS_ENABLED(CONFIG_SND_SOC_SOF_LUNARLAKE)
++ /* Lunarlake-P */
++ {
++ .flags = FLAG_SOF | FLAG_SOF_ONLY_IF_DMIC_OR_SOUNDWIRE,
++ .device = PCI_DEVICE_ID_INTEL_HDA_LNL_P,
++ },
++#endif
+ };
+
+ static const struct config_entry *snd_intel_dsp_find_config
+--
+2.40.1
+
--- /dev/null
+From 3388463a27d0199c61c21ba82eb9cd5177d36574 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 21 Aug 2023 09:32:18 +0800
+Subject: alx: fix OOB-read compiler warning
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: GONG, Ruiqi <gongruiqi1@huawei.com>
+
+[ Upstream commit 3a198c95c95da10ad844cbeade2fe40bdf14c411 ]
+
+The following message shows up when compiling with W=1:
+
+In function ‘fortify_memcpy_chk’,
+ inlined from ‘alx_get_ethtool_stats’ at drivers/net/ethernet/atheros/alx/ethtool.c:297:2:
+./include/linux/fortify-string.h:592:4: error: call to ‘__read_overflow2_field’
+declared with attribute warning: detected read beyond size of field (2nd parameter);
+maybe use struct_group()? [-Werror=attribute-warning]
+ 592 | __read_overflow2_field(q_size_field, size);
+ | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+In order to get alx stats altogether, alx_get_ethtool_stats() reads
+beyond hw->stats.rx_ok. Fix this warning by directly copying hw->stats,
+and refactor the unnecessarily complicated BUILD_BUG_ON btw.
+
+Signed-off-by: GONG, Ruiqi <gongruiqi1@huawei.com>
+Reviewed-by: Simon Horman <horms@kernel.org>
+Link: https://lore.kernel.org/r/20230821013218.1614265-1-gongruiqi@huaweicloud.com
+Signed-off-by: Paolo Abeni <pabeni@redhat.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/ethernet/atheros/alx/ethtool.c | 5 ++---
+ 1 file changed, 2 insertions(+), 3 deletions(-)
+
+diff --git a/drivers/net/ethernet/atheros/alx/ethtool.c b/drivers/net/ethernet/atheros/alx/ethtool.c
+index b716adacd8159..7f6b69a523676 100644
+--- a/drivers/net/ethernet/atheros/alx/ethtool.c
++++ b/drivers/net/ethernet/atheros/alx/ethtool.c
+@@ -292,9 +292,8 @@ static void alx_get_ethtool_stats(struct net_device *netdev,
+ spin_lock(&alx->stats_lock);
+
+ alx_update_hw_stats(hw);
+- BUILD_BUG_ON(sizeof(hw->stats) - offsetof(struct alx_hw_stats, rx_ok) <
+- ALX_NUM_STATS * sizeof(u64));
+- memcpy(data, &hw->stats.rx_ok, ALX_NUM_STATS * sizeof(u64));
++ BUILD_BUG_ON(sizeof(hw->stats) != ALX_NUM_STATS * sizeof(u64));
++ memcpy(data, &hw->stats, sizeof(hw->stats));
+
+ spin_unlock(&alx->stats_lock);
+ }
+--
+2.40.1
+
--- /dev/null
+From a9743bb4d8a23ed852f3468668b287ec01ea814f Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 8 Aug 2023 09:37:32 +0100
+Subject: ARM: 9317/1: kexec: Make smp stop calls asynchronous
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: MÃ¥rten Lindahl <marten.lindahl@axis.com>
+
+[ Upstream commit 8922ba71c969d2a0c01a94372a71477d879470de ]
+
+If a panic is triggered by a hrtimer interrupt all online cpus will be
+notified and set offline. But as highlighted by commit 19dbdcb8039c
+("smp: Warn on function calls from softirq context") this call should
+not be made synchronous with disabled interrupts:
+
+ softdog: Initiating panic
+ Kernel panic - not syncing: Software Watchdog Timer expired
+ WARNING: CPU: 1 PID: 0 at kernel/smp.c:753 smp_call_function_many_cond
+ unwind_backtrace:
+ show_stack
+ dump_stack_lvl
+ __warn
+ warn_slowpath_fmt
+ smp_call_function_many_cond
+ smp_call_function
+ crash_smp_send_stop.part.0
+ machine_crash_shutdown
+ __crash_kexec
+ panic
+ softdog_fire
+ __hrtimer_run_queues
+ hrtimer_interrupt
+
+Make the smp call for machine_crash_nonpanic_core() asynchronous.
+
+Signed-off-by: MÃ¥rten Lindahl <marten.lindahl@axis.com>
+Signed-off-by: Russell King (Oracle) <rmk+kernel@armlinux.org.uk>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ arch/arm/kernel/machine_kexec.c | 14 +++++++++++++-
+ 1 file changed, 13 insertions(+), 1 deletion(-)
+
+diff --git a/arch/arm/kernel/machine_kexec.c b/arch/arm/kernel/machine_kexec.c
+index 46364b699cc30..5d07cf9e0044d 100644
+--- a/arch/arm/kernel/machine_kexec.c
++++ b/arch/arm/kernel/machine_kexec.c
+@@ -94,16 +94,28 @@ static void machine_crash_nonpanic_core(void *unused)
+ }
+ }
+
++static DEFINE_PER_CPU(call_single_data_t, cpu_stop_csd) =
++ CSD_INIT(machine_crash_nonpanic_core, NULL);
++
+ void crash_smp_send_stop(void)
+ {
+ static int cpus_stopped;
+ unsigned long msecs;
++ call_single_data_t *csd;
++ int cpu, this_cpu = raw_smp_processor_id();
+
+ if (cpus_stopped)
+ return;
+
+ atomic_set(&waiting_for_crash_ipi, num_online_cpus() - 1);
+- smp_call_function(machine_crash_nonpanic_core, NULL, false);
++ for_each_online_cpu(cpu) {
++ if (cpu == this_cpu)
++ continue;
++
++ csd = &per_cpu(cpu_stop_csd, cpu);
++ smp_call_function_single_async(cpu, csd);
++ }
++
+ msecs = 1000; /* Wait at most a second for the other cpus to stop */
+ while ((atomic_read(&waiting_for_crash_ipi) > 0) && msecs) {
+ mdelay(1);
+--
+2.40.1
+
--- /dev/null
+From 2ee89570b5fd9cdc61e00749f8d3a2aefef65aac Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sat, 5 Aug 2023 11:01:33 +0200
+Subject: arm64: dts: qcom: sc8280xp-x13s: Add camera activity LED
+
+From: Konrad Dybcio <konrad.dybcio@linaro.org>
+
+[ Upstream commit 1c63dd1c5fdafa8854526d7d60d2b741c813678d ]
+
+Disappointigly, the camera activity LED is implemented in software.
+Hook it up as a gpio-led and (until we have camera *and* a "camera on"
+LED trigger) configure it as a panic indicator.
+
+Signed-off-by: Konrad Dybcio <konrad.dybcio@linaro.org>
+Link: https://lore.kernel.org/r/20230805-topic-x13s_cam_led-v1-1-443d752158c4@linaro.org
+Signed-off-by: Bjorn Andersson <andersson@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ .../dts/qcom/sc8280xp-lenovo-thinkpad-x13s.dts | 16 ++++++++++++++++
+ 1 file changed, 16 insertions(+)
+
+diff --git a/arch/arm64/boot/dts/qcom/sc8280xp-lenovo-thinkpad-x13s.dts b/arch/arm64/boot/dts/qcom/sc8280xp-lenovo-thinkpad-x13s.dts
+index 059dfccdfe7c2..b51787b6561d7 100644
+--- a/arch/arm64/boot/dts/qcom/sc8280xp-lenovo-thinkpad-x13s.dts
++++ b/arch/arm64/boot/dts/qcom/sc8280xp-lenovo-thinkpad-x13s.dts
+@@ -12,6 +12,7 @@
+ #include <dt-bindings/iio/qcom,spmi-adc7-pmr735a.h>
+ #include <dt-bindings/input/gpio-keys.h>
+ #include <dt-bindings/input/input.h>
++#include <dt-bindings/leds/common.h>
+ #include <dt-bindings/regulator/qcom,rpmh-regulator.h>
+
+ #include "sc8280xp.dtsi"
+@@ -78,6 +79,21 @@ switch-lid {
+ };
+ };
+
++ leds {
++ compatible = "gpio-leds";
++
++ led-camera-indicator {
++ label = "white:camera-indicator";
++ function = LED_FUNCTION_INDICATOR;
++ color = <LED_COLOR_ID_WHITE>;
++ gpios = <&tlmm 28 GPIO_ACTIVE_HIGH>;
++ linux,default-trigger = "none";
++ default-state = "off";
++ /* Reuse as a panic indicator until we get a "camera on" trigger */
++ panic-indicator;
++ };
++ };
++
+ pmic-glink {
+ compatible = "qcom,sc8280xp-pmic-glink", "qcom,pmic-glink";
+
+--
+2.40.1
+
--- /dev/null
+From 391926109fa5426a1753762849e03572aa9c6151 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sun, 18 Jun 2023 13:44:38 +0200
+Subject: arm64: dts: qcom: sm6125-pdx201: correct ramoops pmsg-size
+
+From: Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
+
+[ Upstream commit c42f5452de6ad2599c6e5e2a64c180a4ac835d27 ]
+
+There is no 'msg-size' property in ramoops, so assume intention was for
+'pmsg-size':
+
+ sm6125-sony-xperia-seine-pdx201.dtb: ramoops@ffc00000: Unevaluated properties are not allowed ('msg-size' was unexpected)
+
+Signed-off-by: Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
+Reviewed-by: Konrad Dybcio <konrad.dybcio@linaro.org>
+Link: https://lore.kernel.org/r/20230618114442.140185-3-krzysztof.kozlowski@linaro.org
+Signed-off-by: Bjorn Andersson <andersson@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ arch/arm64/boot/dts/qcom/sm6125-sony-xperia-seine-pdx201.dts | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/arch/arm64/boot/dts/qcom/sm6125-sony-xperia-seine-pdx201.dts b/arch/arm64/boot/dts/qcom/sm6125-sony-xperia-seine-pdx201.dts
+index 9f8a9ef398a26..de85086c65adc 100644
+--- a/arch/arm64/boot/dts/qcom/sm6125-sony-xperia-seine-pdx201.dts
++++ b/arch/arm64/boot/dts/qcom/sm6125-sony-xperia-seine-pdx201.dts
+@@ -79,7 +79,7 @@ pstore_mem: ramoops@ffc00000 {
+ reg = <0x0 0xffc40000 0x0 0xc0000>;
+ record-size = <0x1000>;
+ console-size = <0x40000>;
+- msg-size = <0x20000 0x20000>;
++ pmsg-size = <0x20000>;
+ };
+
+ cmdline_mem: memory@ffd00000 {
+--
+2.40.1
+
--- /dev/null
+From 4d1a93dc24049c123f5165bd4b596a693ed1d198 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sun, 18 Jun 2023 13:44:39 +0200
+Subject: arm64: dts: qcom: sm6125-sprout: correct ramoops pmsg-size
+
+From: Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
+
+[ Upstream commit 2951e7e7611a3ea04de98d0f1bfc4e7ec609ef29 ]
+
+There is no 'msg-size' property in ramoops, so assume intention was for
+'pmsg-size':
+
+ sm6125-xiaomi-laurel-sprout.dtb: ramoops@ffc00000: Unevaluated properties are not allowed ('msg-size' was unexpected)
+
+Signed-off-by: Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
+Reviewed-by: Konrad Dybcio <konrad.dybcio@linaro.org>
+Link: https://lore.kernel.org/r/20230618114442.140185-4-krzysztof.kozlowski@linaro.org
+Signed-off-by: Bjorn Andersson <andersson@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ arch/arm64/boot/dts/qcom/sm6125-xiaomi-laurel-sprout.dts | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/arch/arm64/boot/dts/qcom/sm6125-xiaomi-laurel-sprout.dts b/arch/arm64/boot/dts/qcom/sm6125-xiaomi-laurel-sprout.dts
+index a7f4aeae9c1a5..7c58d1299a609 100644
+--- a/arch/arm64/boot/dts/qcom/sm6125-xiaomi-laurel-sprout.dts
++++ b/arch/arm64/boot/dts/qcom/sm6125-xiaomi-laurel-sprout.dts
+@@ -52,7 +52,7 @@ pstore_mem: ramoops@ffc00000 {
+ reg = <0x0 0xffc40000 0x0 0xc0000>;
+ record-size = <0x1000>;
+ console-size = <0x40000>;
+- msg-size = <0x20000 0x20000>;
++ pmsg-size = <0x20000>;
+ };
+
+ cmdline_mem: memory@ffd00000 {
+--
+2.40.1
+
--- /dev/null
+From e02b3f8099e3127447ef6f9f0fc393b983c2ef46 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sun, 18 Jun 2023 13:44:40 +0200
+Subject: arm64: dts: qcom: sm6350: correct ramoops pmsg-size
+
+From: Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
+
+[ Upstream commit c86b97a72065e06eacb993dc71fa9febc93422af ]
+
+There is no 'msg-size' property in ramoops, so assume intention was for
+'pmsg-size':
+
+ sm6350-sony-xperia-lena-pdx213.dtb: ramoops@ffc00000: Unevaluated properties are not allowed ('msg-size' was unexpected)
+
+Signed-off-by: Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
+Reviewed-by: Konrad Dybcio <konrad.dybcio@linaro.org>
+Link: https://lore.kernel.org/r/20230618114442.140185-5-krzysztof.kozlowski@linaro.org
+Signed-off-by: Bjorn Andersson <andersson@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ arch/arm64/boot/dts/qcom/sm6350.dtsi | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/arch/arm64/boot/dts/qcom/sm6350.dtsi b/arch/arm64/boot/dts/qcom/sm6350.dtsi
+index 7cafb32fbb941..4b4ea156a92c5 100644
+--- a/arch/arm64/boot/dts/qcom/sm6350.dtsi
++++ b/arch/arm64/boot/dts/qcom/sm6350.dtsi
+@@ -673,7 +673,7 @@ ramoops: ramoops@ffc00000 {
+ reg = <0 0xffc00000 0 0x100000>;
+ record-size = <0x1000>;
+ console-size = <0x40000>;
+- msg-size = <0x20000 0x20000>;
++ pmsg-size = <0x20000>;
+ ecc-size = <16>;
+ no-map;
+ };
+--
+2.40.1
+
--- /dev/null
+From 4e9064b25046b6d9e2076b8ec71986a16fe1f977 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sun, 18 Jun 2023 13:44:41 +0200
+Subject: arm64: dts: qcom: sm8150-kumano: correct ramoops pmsg-size
+
+From: Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
+
+[ Upstream commit 4e6b942f092653ebcdbbc0819b2d1f08ab415bdc ]
+
+There is no 'msg-size' property in ramoops, so assume intention was for
+'pmsg-size':
+
+ sm8150-sony-xperia-kumano-griffin.dtb: ramoops@ffc00000: Unevaluated properties are not allowed ('msg-size' was unexpected)
+
+Signed-off-by: Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
+Reviewed-by: Konrad Dybcio <konrad.dybcio@linaro.org>
+Link: https://lore.kernel.org/r/20230618114442.140185-6-krzysztof.kozlowski@linaro.org
+Signed-off-by: Bjorn Andersson <andersson@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ arch/arm64/boot/dts/qcom/sm8150-sony-xperia-kumano.dtsi | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/arch/arm64/boot/dts/qcom/sm8150-sony-xperia-kumano.dtsi b/arch/arm64/boot/dts/qcom/sm8150-sony-xperia-kumano.dtsi
+index baafea53770bf..ae0ca48b89a59 100644
+--- a/arch/arm64/boot/dts/qcom/sm8150-sony-xperia-kumano.dtsi
++++ b/arch/arm64/boot/dts/qcom/sm8150-sony-xperia-kumano.dtsi
+@@ -222,7 +222,7 @@ ramoops@ffc00000 {
+ reg = <0x0 0xffc00000 0x0 0x100000>;
+ record-size = <0x1000>;
+ console-size = <0x40000>;
+- msg-size = <0x20000 0x20000>;
++ pmsg-size = <0x20000>;
+ ecc-size = <16>;
+ no-map;
+ };
+--
+2.40.1
+
--- /dev/null
+From c762d780d55c7237f862440c00ca349e6a63df66 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sun, 18 Jun 2023 13:44:42 +0200
+Subject: arm64: dts: qcom: sm8250-edo: correct ramoops pmsg-size
+
+From: Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
+
+[ Upstream commit 7dc3606f91427414d00a2fb09e6e0e32c14c2093 ]
+
+There is no 'msg-size' property in ramoops, so assume intention was for
+'pmsg-size':
+
+ sm8250-sony-xperia-edo-pdx206.dtb: ramoops@ffc00000: Unevaluated properties are not allowed ('msg-size' was unexpected)
+
+Signed-off-by: Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
+Reviewed-by: Konrad Dybcio <konrad.dybcio@linaro.org>
+Link: https://lore.kernel.org/r/20230618114442.140185-7-krzysztof.kozlowski@linaro.org
+Signed-off-by: Bjorn Andersson <andersson@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ arch/arm64/boot/dts/qcom/sm8250-sony-xperia-edo.dtsi | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/arch/arm64/boot/dts/qcom/sm8250-sony-xperia-edo.dtsi b/arch/arm64/boot/dts/qcom/sm8250-sony-xperia-edo.dtsi
+index b044cffb419e5..6b044eca7ad5a 100644
+--- a/arch/arm64/boot/dts/qcom/sm8250-sony-xperia-edo.dtsi
++++ b/arch/arm64/boot/dts/qcom/sm8250-sony-xperia-edo.dtsi
+@@ -126,7 +126,7 @@ ramoops@ffc00000 {
+ reg = <0x0 0xffc00000 0x0 0x100000>;
+ record-size = <0x1000>;
+ console-size = <0x40000>;
+- msg-size = <0x20000 0x20000>;
++ pmsg-size = <0x20000>;
+ ecc-size = <16>;
+ no-map;
+ };
+--
+2.40.1
+
--- /dev/null
+From b1e2f06be6330f44a5728c6da3d8c9f8fc2cf7b6 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 31 Jul 2023 16:42:38 -0500
+Subject: ASoC: Intel: sof_sdw: Update BT offload config for soundwire config
+
+From: Uday M Bhat <uday.m.bhat@intel.com>
+
+[ Upstream commit a14aded9299187bb17ef90700eb2cf1120ef5885 ]
+
+For soundwire config, SSP1 is used for BT offload. This is enabled
+in sof_sdw_quirk_table
+
+Reviewed-by: Kai Vehmanen <kai.vehmanen@linux.intel.com>
+Reviewed-by: Ranjani Sridharan <ranjani.sridharan@linux.intel.com>
+Reviewed-by: Bard Liao <yung-chuan.liao@linux.intel.com>
+Signed-off-by: Uday M Bhat <uday.m.bhat@intel.com>
+Signed-off-by: Jairaj Arava <jairaj.arava@intel.com>
+Signed-off-by: Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>
+Link: https://lore.kernel.org/r/20230731214257.444605-5-pierre-louis.bossart@linux.intel.com
+Signed-off-by: Mark Brown <broonie@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ sound/soc/intel/boards/sof_sdw.c | 4 +++-
+ 1 file changed, 3 insertions(+), 1 deletion(-)
+
+diff --git a/sound/soc/intel/boards/sof_sdw.c b/sound/soc/intel/boards/sof_sdw.c
+index 0201029899cad..c86f8f9a61003 100644
+--- a/sound/soc/intel/boards/sof_sdw.c
++++ b/sound/soc/intel/boards/sof_sdw.c
+@@ -467,7 +467,9 @@ static const struct dmi_system_id sof_sdw_quirk_table[] = {
+ DMI_MATCH(DMI_SYS_VENDOR, "Google"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "Rex"),
+ },
+- .driver_data = (void *)(SOF_SDW_PCH_DMIC),
++ .driver_data = (void *)(SOF_SDW_PCH_DMIC |
++ SOF_BT_OFFLOAD_SSP(1) |
++ SOF_SSP_BT_OFFLOAD_PRESENT),
+ },
+ /* LunarLake devices */
+ {
+--
+2.40.1
+
--- /dev/null
+From db647398618c5e4a5562fa528405f5ed1768890b Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 23 Aug 2023 13:03:38 +0530
+Subject: ASoC: SOF: amd: clear panic mask status when panic occurs
+
+From: Vijendar Mukunda <Vijendar.Mukunda@amd.com>
+
+[ Upstream commit 3d02e1c439b4140215b624d423aa3c7554b17a5a ]
+
+Due to scratch memory persistence, Once the DSP panic is reported, need to
+clear the panic mask after handling DSP panic. Otherwise, It results in DSP
+panic on next reboot.
+
+Signed-off-by: Vijendar Mukunda <Vijendar.Mukunda@amd.com>
+Link: https://lore.kernel.org/r/20230823073340.2829821-6-Vijendar.Mukunda@amd.com
+Signed-off-by: Mark Brown <broonie@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ sound/soc/sof/amd/acp-ipc.c | 4 ++++
+ 1 file changed, 4 insertions(+)
+
+diff --git a/sound/soc/sof/amd/acp-ipc.c b/sound/soc/sof/amd/acp-ipc.c
+index 8a0fc635a997c..d07dc78074cc3 100644
+--- a/sound/soc/sof/amd/acp-ipc.c
++++ b/sound/soc/sof/amd/acp-ipc.c
+@@ -168,6 +168,8 @@ irqreturn_t acp_sof_ipc_irq_thread(int irq, void *context)
+ if ((status & SOF_IPC_PANIC_MAGIC_MASK) == SOF_IPC_PANIC_MAGIC) {
+ snd_sof_dsp_panic(sdev, sdev->dsp_box.offset + sizeof(status),
+ true);
++ status = 0;
++ acp_mailbox_write(sdev, sdev->dsp_box.offset, &status, sizeof(status));
+ return IRQ_HANDLED;
+ }
+ snd_sof_ipc_msgs_rx(sdev);
+@@ -197,6 +199,8 @@ irqreturn_t acp_sof_ipc_irq_thread(int irq, void *context)
+ acp_mailbox_read(sdev, sdev->debug_box.offset, &status, sizeof(u32));
+ if ((status & SOF_IPC_PANIC_MAGIC_MASK) == SOF_IPC_PANIC_MAGIC) {
+ snd_sof_dsp_panic(sdev, sdev->dsp_oops_offset, true);
++ status = 0;
++ acp_mailbox_write(sdev, sdev->debug_box.offset, &status, sizeof(status));
+ return IRQ_HANDLED;
+ }
+
+--
+2.40.1
+
--- /dev/null
+From 0d14a4290b981b0d78fe9371e97337fd6d79257a Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 31 Jul 2023 16:37:43 -0500
+Subject: ASoC: SOF: topology: simplify code to prevent static analysis
+ warnings
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>
+
+[ Upstream commit 55cb3dc271d81f1982c949a2ac483a6daf613b92 ]
+
+make KCFLAGS='-fanalyzer' sound/soc/sof/intel/ reports a possible NULL
+pointer dereference.
+
+sound/soc/sof/topology.c:1136:21: error: dereference of NULL ‘w’
+[CWE-476] [-Werror=analyzer-null-dereference]
+
+ 1136 | strcmp(w->sname, rtd->dai_link->stream_name))
+
+The code is rather confusing and can be simplified to make static
+analysis happy. No functionality change.
+
+Signed-off-by: Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>
+Reviewed-by: Rander Wang <rander.wang@intel.com>
+Reviewed-by: Daniel Baluta <daniel.baluta@nxp.com>
+Reviewed-by: Yaochun Hung <yc.hung@mediatek.com>
+Link: https://lore.kernel.org/r/20230731213748.440285-4-pierre-louis.bossart@linux.intel.com
+Signed-off-by: Mark Brown <broonie@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ sound/soc/sof/topology.c | 5 +++--
+ 1 file changed, 3 insertions(+), 2 deletions(-)
+
+diff --git a/sound/soc/sof/topology.c b/sound/soc/sof/topology.c
+index 698129dccc7df..3866dd3cba695 100644
+--- a/sound/soc/sof/topology.c
++++ b/sound/soc/sof/topology.c
+@@ -1117,10 +1117,11 @@ static void sof_disconnect_dai_widget(struct snd_soc_component *scomp,
+ {
+ struct snd_soc_card *card = scomp->card;
+ struct snd_soc_pcm_runtime *rtd;
++ const char *sname = w->sname;
+ struct snd_soc_dai *cpu_dai;
+ int i, stream;
+
+- if (!w->sname)
++ if (!sname)
+ return;
+
+ if (w->id == snd_soc_dapm_dai_out)
+@@ -1133,7 +1134,7 @@ static void sof_disconnect_dai_widget(struct snd_soc_component *scomp,
+ list_for_each_entry(rtd, &card->rtd_list, list) {
+ /* does stream match DAI link ? */
+ if (!rtd->dai_link->stream_name ||
+- strcmp(w->sname, rtd->dai_link->stream_name))
++ strcmp(sname, rtd->dai_link->stream_name))
+ continue;
+
+ for_each_rtd_cpu_dais(rtd, i, cpu_dai)
+--
+2.40.1
+
--- /dev/null
+From e0d5ca37f6dea43f58be8cd072f3af6924aaaf2e Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 13 Sep 2023 17:04:43 +0200
+Subject: ata: libata-core: fetch sense data for successful commands iff CDL
+ enabled
+
+From: Niklas Cassel <niklas.cassel@wdc.com>
+
+[ Upstream commit 5e35a9ac3fe3a0d571b899a16ca84253e53dc70c ]
+
+Currently, we fetch sense data for a _successful_ command if either:
+1) Command was NCQ and ATA_DFLAG_CDL_ENABLED flag set (flag
+ ATA_DFLAG_CDL_ENABLED will only be set if the Successful NCQ command
+ sense data supported bit is set); or
+2) Command was non-NCQ and regular sense data reporting is enabled.
+
+This means that case 2) will trigger for a non-NCQ command which has
+ATA_SENSE bit set, regardless if CDL is enabled or not.
+
+This decision was by design. If the device reports that it has sense data
+available, it makes sense to fetch that sense data, since the sk/asc/ascq
+could be important information regardless if CDL is enabled or not.
+
+However, the fetching of sense data for a successful command is done via
+ATA EH. Considering how intricate the ATA EH is, we really do not want to
+invoke ATA EH unless absolutely needed.
+
+Before commit 18bd7718b5c4 ("scsi: ata: libata: Handle completion of CDL
+commands using policy 0xD") we never fetched sense data for successful
+commands.
+
+In order to not invoke the ATA EH unless absolutely necessary, even if the
+device claims support for sense data reporting, only fetch sense data for
+successful (NCQ and non-NCQ commands) commands that are using CDL.
+
+[Damien] Modified the check to test the qc flag ATA_QCFLAG_HAS_CDL
+instead of the device support for CDL, which is implied for commands
+using CDL.
+
+Fixes: 3ac873c76d79 ("ata: libata-core: fix when to fetch sense data for successful commands")
+Signed-off-by: Niklas Cassel <niklas.cassel@wdc.com>
+Signed-off-by: Damien Le Moal <dlemoal@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/ata/libata-core.c | 7 ++-----
+ 1 file changed, 2 insertions(+), 5 deletions(-)
+
+diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c
+index c7a29c3ac6701..291e128f4d2b4 100644
+--- a/drivers/ata/libata-core.c
++++ b/drivers/ata/libata-core.c
+@@ -4919,11 +4919,8 @@ void ata_qc_complete(struct ata_queued_cmd *qc)
+ * been aborted by the device due to a limit timeout using the policy
+ * 0xD. For these commands, invoke EH to get the command sense data.
+ */
+- if (qc->result_tf.status & ATA_SENSE &&
+- ((ata_is_ncq(qc->tf.protocol) &&
+- dev->flags & ATA_DFLAG_CDL_ENABLED) ||
+- (!ata_is_ncq(qc->tf.protocol) &&
+- ata_id_sense_reporting_enabled(dev->id)))) {
++ if (qc->flags & ATA_QCFLAG_HAS_CDL &&
++ qc->result_tf.status & ATA_SENSE) {
+ /*
+ * Tell SCSI EH to not overwrite scmd->result even if this
+ * command is finished with result SAM_STAT_GOOD.
+--
+2.40.1
+
--- /dev/null
+From 8df03fd2bc8c18590abf842bc2d997fb2972ceb4 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 31 Jul 2023 16:34:12 +0200
+Subject: ata: libata: remove references to non-existing error_handler()
+
+From: Hannes Reinecke <hare@suse.de>
+
+[ Upstream commit ff8072d589dcff7c1f0345a6ec98b5fc1e9ee2a1 ]
+
+With commit 65a15d6560df ("scsi: ipr: Remove SATA support") all
+libata drivers now have the error_handler() callback provided,
+so we can stop checking for non-existing error_handler callback.
+
+Signed-off-by: Hannes Reinecke <hare@suse.de>
+[niklas: fixed review comments, rebased, solved conflicts during rebase,
+fixed bug that unconditionally dumped all QCs, removed the now unused
+function ata_dump_status(), removed the now unreachable failure paths in
+atapi_qc_complete(), removed the non-EH function to request ATAPI sense]
+Signed-off-by: Niklas Cassel <niklas.cassel@wdc.com>
+Reviewed-by: John Garry <john.g.garry@oracle.com>
+Reviewed-by: Jason Yan <yanaijie@huawei.com>
+Reviewed-by: Martin K. Petersen <martin.petersen@oracle.com>
+Signed-off-by: Damien Le Moal <dlemoal@kernel.org>
+Stable-dep-of: 5e35a9ac3fe3 ("ata: libata-core: fetch sense data for successful commands iff CDL enabled")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/ata/libata-core.c | 209 +++++++++++++++-----------------------
+ drivers/ata/libata-eh.c | 152 ++++++++++++---------------
+ drivers/ata/libata-sata.c | 7 +-
+ drivers/ata/libata-scsi.c | 161 ++---------------------------
+ drivers/ata/libata-sff.c | 30 ++----
+ include/linux/libata.h | 2 +-
+ 6 files changed, 170 insertions(+), 391 deletions(-)
+
+diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c
+index 04db0f2c683a7..c7a29c3ac6701 100644
+--- a/drivers/ata/libata-core.c
++++ b/drivers/ata/libata-core.c
+@@ -1586,13 +1586,11 @@ static unsigned ata_exec_internal_sg(struct ata_device *dev,
+ }
+ }
+
+- if (ap->ops->error_handler)
+- ata_eh_release(ap);
++ ata_eh_release(ap);
+
+ rc = wait_for_completion_timeout(&wait, msecs_to_jiffies(timeout));
+
+- if (ap->ops->error_handler)
+- ata_eh_acquire(ap);
++ ata_eh_acquire(ap);
+
+ ata_sff_flush_pio_task(ap);
+
+@@ -1607,10 +1605,7 @@ static unsigned ata_exec_internal_sg(struct ata_device *dev,
+ if (qc->flags & ATA_QCFLAG_ACTIVE) {
+ qc->err_mask |= AC_ERR_TIMEOUT;
+
+- if (ap->ops->error_handler)
+- ata_port_freeze(ap);
+- else
+- ata_qc_complete(qc);
++ ata_port_freeze(ap);
+
+ ata_dev_warn(dev, "qc timeout after %u msecs (cmd 0x%x)\n",
+ timeout, command);
+@@ -4874,126 +4869,103 @@ static void ata_verify_xfer(struct ata_queued_cmd *qc)
+ void ata_qc_complete(struct ata_queued_cmd *qc)
+ {
+ struct ata_port *ap = qc->ap;
++ struct ata_device *dev = qc->dev;
++ struct ata_eh_info *ehi = &dev->link->eh_info;
+
+ /* Trigger the LED (if available) */
+ ledtrig_disk_activity(!!(qc->tf.flags & ATA_TFLAG_WRITE));
+
+- /* XXX: New EH and old EH use different mechanisms to
+- * synchronize EH with regular execution path.
+- *
+- * In new EH, a qc owned by EH is marked with ATA_QCFLAG_EH.
+- * Normal execution path is responsible for not accessing a
+- * qc owned by EH. libata core enforces the rule by returning NULL
+- * from ata_qc_from_tag() for qcs owned by EH.
++ /*
++ * In order to synchronize EH with the regular execution path, a qc that
++ * is owned by EH is marked with ATA_QCFLAG_EH.
+ *
+- * Old EH depends on ata_qc_complete() nullifying completion
+- * requests if ATA_QCFLAG_EH_SCHEDULED is set. Old EH does
+- * not synchronize with interrupt handler. Only PIO task is
+- * taken care of.
++ * The normal execution path is responsible for not accessing a qc owned
++ * by EH. libata core enforces the rule by returning NULL from
++ * ata_qc_from_tag() for qcs owned by EH.
+ */
+- if (ap->ops->error_handler) {
+- struct ata_device *dev = qc->dev;
+- struct ata_eh_info *ehi = &dev->link->eh_info;
+-
+- if (unlikely(qc->err_mask))
+- qc->flags |= ATA_QCFLAG_EH;
++ if (unlikely(qc->err_mask))
++ qc->flags |= ATA_QCFLAG_EH;
+
+- /*
+- * Finish internal commands without any further processing
+- * and always with the result TF filled.
+- */
+- if (unlikely(ata_tag_internal(qc->tag))) {
+- fill_result_tf(qc);
+- trace_ata_qc_complete_internal(qc);
+- __ata_qc_complete(qc);
+- return;
+- }
++ /*
++ * Finish internal commands without any further processing and always
++ * with the result TF filled.
++ */
++ if (unlikely(ata_tag_internal(qc->tag))) {
++ fill_result_tf(qc);
++ trace_ata_qc_complete_internal(qc);
++ __ata_qc_complete(qc);
++ return;
++ }
+
+- /*
+- * Non-internal qc has failed. Fill the result TF and
+- * summon EH.
+- */
+- if (unlikely(qc->flags & ATA_QCFLAG_EH)) {
+- fill_result_tf(qc);
+- trace_ata_qc_complete_failed(qc);
+- ata_qc_schedule_eh(qc);
+- return;
+- }
++ /* Non-internal qc has failed. Fill the result TF and summon EH. */
++ if (unlikely(qc->flags & ATA_QCFLAG_EH)) {
++ fill_result_tf(qc);
++ trace_ata_qc_complete_failed(qc);
++ ata_qc_schedule_eh(qc);
++ return;
++ }
+
+- WARN_ON_ONCE(ata_port_is_frozen(ap));
++ WARN_ON_ONCE(ata_port_is_frozen(ap));
+
+- /* read result TF if requested */
+- if (qc->flags & ATA_QCFLAG_RESULT_TF)
+- fill_result_tf(qc);
++ /* read result TF if requested */
++ if (qc->flags & ATA_QCFLAG_RESULT_TF)
++ fill_result_tf(qc);
+
+- trace_ata_qc_complete_done(qc);
++ trace_ata_qc_complete_done(qc);
+
++ /*
++ * For CDL commands that completed without an error, check if we have
++ * sense data (ATA_SENSE is set). If we do, then the command may have
++ * been aborted by the device due to a limit timeout using the policy
++ * 0xD. For these commands, invoke EH to get the command sense data.
++ */
++ if (qc->result_tf.status & ATA_SENSE &&
++ ((ata_is_ncq(qc->tf.protocol) &&
++ dev->flags & ATA_DFLAG_CDL_ENABLED) ||
++ (!ata_is_ncq(qc->tf.protocol) &&
++ ata_id_sense_reporting_enabled(dev->id)))) {
+ /*
+- * For CDL commands that completed without an error, check if
+- * we have sense data (ATA_SENSE is set). If we do, then the
+- * command may have been aborted by the device due to a limit
+- * timeout using the policy 0xD. For these commands, invoke EH
+- * to get the command sense data.
++ * Tell SCSI EH to not overwrite scmd->result even if this
++ * command is finished with result SAM_STAT_GOOD.
+ */
+- if (qc->result_tf.status & ATA_SENSE &&
+- ((ata_is_ncq(qc->tf.protocol) &&
+- dev->flags & ATA_DFLAG_CDL_ENABLED) ||
+- (!ata_is_ncq(qc->tf.protocol) &&
+- ata_id_sense_reporting_enabled(dev->id)))) {
+- /*
+- * Tell SCSI EH to not overwrite scmd->result even if
+- * this command is finished with result SAM_STAT_GOOD.
+- */
+- qc->scsicmd->flags |= SCMD_FORCE_EH_SUCCESS;
+- qc->flags |= ATA_QCFLAG_EH_SUCCESS_CMD;
+- ehi->dev_action[dev->devno] |= ATA_EH_GET_SUCCESS_SENSE;
+-
+- /*
+- * set pending so that ata_qc_schedule_eh() does not
+- * trigger fast drain, and freeze the port.
+- */
+- ap->pflags |= ATA_PFLAG_EH_PENDING;
+- ata_qc_schedule_eh(qc);
+- return;
+- }
++ qc->scsicmd->flags |= SCMD_FORCE_EH_SUCCESS;
++ qc->flags |= ATA_QCFLAG_EH_SUCCESS_CMD;
++ ehi->dev_action[dev->devno] |= ATA_EH_GET_SUCCESS_SENSE;
+
+- /* Some commands need post-processing after successful
+- * completion.
++ /*
++ * set pending so that ata_qc_schedule_eh() does not trigger
++ * fast drain, and freeze the port.
+ */
+- switch (qc->tf.command) {
+- case ATA_CMD_SET_FEATURES:
+- if (qc->tf.feature != SETFEATURES_WC_ON &&
+- qc->tf.feature != SETFEATURES_WC_OFF &&
+- qc->tf.feature != SETFEATURES_RA_ON &&
+- qc->tf.feature != SETFEATURES_RA_OFF)
+- break;
+- fallthrough;
+- case ATA_CMD_INIT_DEV_PARAMS: /* CHS translation changed */
+- case ATA_CMD_SET_MULTI: /* multi_count changed */
+- /* revalidate device */
+- ehi->dev_action[dev->devno] |= ATA_EH_REVALIDATE;
+- ata_port_schedule_eh(ap);
+- break;
++ ap->pflags |= ATA_PFLAG_EH_PENDING;
++ ata_qc_schedule_eh(qc);
++ return;
++ }
+
+- case ATA_CMD_SLEEP:
+- dev->flags |= ATA_DFLAG_SLEEPING;
++ /* Some commands need post-processing after successful completion. */
++ switch (qc->tf.command) {
++ case ATA_CMD_SET_FEATURES:
++ if (qc->tf.feature != SETFEATURES_WC_ON &&
++ qc->tf.feature != SETFEATURES_WC_OFF &&
++ qc->tf.feature != SETFEATURES_RA_ON &&
++ qc->tf.feature != SETFEATURES_RA_OFF)
+ break;
+- }
+-
+- if (unlikely(dev->flags & ATA_DFLAG_DUBIOUS_XFER))
+- ata_verify_xfer(qc);
++ fallthrough;
++ case ATA_CMD_INIT_DEV_PARAMS: /* CHS translation changed */
++ case ATA_CMD_SET_MULTI: /* multi_count changed */
++ /* revalidate device */
++ ehi->dev_action[dev->devno] |= ATA_EH_REVALIDATE;
++ ata_port_schedule_eh(ap);
++ break;
+
+- __ata_qc_complete(qc);
+- } else {
+- if (qc->flags & ATA_QCFLAG_EH_SCHEDULED)
+- return;
++ case ATA_CMD_SLEEP:
++ dev->flags |= ATA_DFLAG_SLEEPING;
++ break;
++ }
+
+- /* read result TF if failed or requested */
+- if (qc->err_mask || qc->flags & ATA_QCFLAG_RESULT_TF)
+- fill_result_tf(qc);
++ if (unlikely(dev->flags & ATA_DFLAG_DUBIOUS_XFER))
++ ata_verify_xfer(qc);
+
+- __ata_qc_complete(qc);
+- }
++ __ata_qc_complete(qc);
+ }
+ EXPORT_SYMBOL_GPL(ata_qc_complete);
+
+@@ -5039,11 +5011,8 @@ void ata_qc_issue(struct ata_queued_cmd *qc)
+ struct ata_link *link = qc->dev->link;
+ u8 prot = qc->tf.protocol;
+
+- /* Make sure only one non-NCQ command is outstanding. The
+- * check is skipped for old EH because it reuses active qc to
+- * request ATAPI sense.
+- */
+- WARN_ON_ONCE(ap->ops->error_handler && ata_tag_valid(link->active_tag));
++ /* Make sure only one non-NCQ command is outstanding. */
++ WARN_ON_ONCE(ata_tag_valid(link->active_tag));
+
+ if (ata_is_ncq(prot)) {
+ WARN_ON_ONCE(link->sactive & (1 << qc->hw_tag));
+@@ -5917,15 +5886,9 @@ void __ata_port_probe(struct ata_port *ap)
+
+ int ata_port_probe(struct ata_port *ap)
+ {
+- int rc = 0;
+-
+- if (ap->ops->error_handler) {
+- __ata_port_probe(ap);
+- ata_port_wait_eh(ap);
+- } else {
+- rc = ata_bus_probe(ap);
+- }
+- return rc;
++ __ata_port_probe(ap);
++ ata_port_wait_eh(ap);
++ return 0;
+ }
+
+
+@@ -6130,9 +6093,6 @@ static void ata_port_detach(struct ata_port *ap)
+ struct ata_link *link;
+ struct ata_device *dev;
+
+- if (!ap->ops->error_handler)
+- goto skip_eh;
+-
+ /* tell EH we're leaving & flush EH */
+ spin_lock_irqsave(ap->lock, flags);
+ ap->pflags |= ATA_PFLAG_UNLOADING;
+@@ -6148,7 +6108,6 @@ static void ata_port_detach(struct ata_port *ap)
+ cancel_delayed_work_sync(&ap->hotplug_task);
+ cancel_delayed_work_sync(&ap->scsi_rescan_task);
+
+- skip_eh:
+ /* clean up zpodd on port removal */
+ ata_for_each_link(link, ap, HOST_FIRST) {
+ ata_for_each_dev(dev, link, ALL) {
+diff --git a/drivers/ata/libata-eh.c b/drivers/ata/libata-eh.c
+index 35e03679b0bfe..9d6affabf225a 100644
+--- a/drivers/ata/libata-eh.c
++++ b/drivers/ata/libata-eh.c
+@@ -571,13 +571,10 @@ void ata_scsi_cmd_error_handler(struct Scsi_Host *host, struct ata_port *ap,
+ /* make sure sff pio task is not running */
+ ata_sff_flush_pio_task(ap);
+
+- if (!ap->ops->error_handler)
+- return;
+-
+ /* synchronize with host lock and sort out timeouts */
+
+ /*
+- * For new EH, all qcs are finished in one of three ways -
++ * For EH, all qcs are finished in one of three ways -
+ * normal completion, error completion, and SCSI timeout.
+ * Both completions can race against SCSI timeout. When normal
+ * completion wins, the qc never reaches EH. When error
+@@ -659,94 +656,87 @@ EXPORT_SYMBOL(ata_scsi_cmd_error_handler);
+ void ata_scsi_port_error_handler(struct Scsi_Host *host, struct ata_port *ap)
+ {
+ unsigned long flags;
++ struct ata_link *link;
+
+- /* invoke error handler */
+- if (ap->ops->error_handler) {
+- struct ata_link *link;
+-
+- /* acquire EH ownership */
+- ata_eh_acquire(ap);
++ /* acquire EH ownership */
++ ata_eh_acquire(ap);
+ repeat:
+- /* kill fast drain timer */
+- del_timer_sync(&ap->fastdrain_timer);
++ /* kill fast drain timer */
++ del_timer_sync(&ap->fastdrain_timer);
+
+- /* process port resume request */
+- ata_eh_handle_port_resume(ap);
++ /* process port resume request */
++ ata_eh_handle_port_resume(ap);
+
+- /* fetch & clear EH info */
+- spin_lock_irqsave(ap->lock, flags);
++ /* fetch & clear EH info */
++ spin_lock_irqsave(ap->lock, flags);
+
+- ata_for_each_link(link, ap, HOST_FIRST) {
+- struct ata_eh_context *ehc = &link->eh_context;
+- struct ata_device *dev;
++ ata_for_each_link(link, ap, HOST_FIRST) {
++ struct ata_eh_context *ehc = &link->eh_context;
++ struct ata_device *dev;
+
+- memset(&link->eh_context, 0, sizeof(link->eh_context));
+- link->eh_context.i = link->eh_info;
+- memset(&link->eh_info, 0, sizeof(link->eh_info));
++ memset(&link->eh_context, 0, sizeof(link->eh_context));
++ link->eh_context.i = link->eh_info;
++ memset(&link->eh_info, 0, sizeof(link->eh_info));
+
+- ata_for_each_dev(dev, link, ENABLED) {
+- int devno = dev->devno;
++ ata_for_each_dev(dev, link, ENABLED) {
++ int devno = dev->devno;
+
+- ehc->saved_xfer_mode[devno] = dev->xfer_mode;
+- if (ata_ncq_enabled(dev))
+- ehc->saved_ncq_enabled |= 1 << devno;
+- }
++ ehc->saved_xfer_mode[devno] = dev->xfer_mode;
++ if (ata_ncq_enabled(dev))
++ ehc->saved_ncq_enabled |= 1 << devno;
+ }
++ }
+
+- ap->pflags |= ATA_PFLAG_EH_IN_PROGRESS;
+- ap->pflags &= ~ATA_PFLAG_EH_PENDING;
+- ap->excl_link = NULL; /* don't maintain exclusion over EH */
++ ap->pflags |= ATA_PFLAG_EH_IN_PROGRESS;
++ ap->pflags &= ~ATA_PFLAG_EH_PENDING;
++ ap->excl_link = NULL; /* don't maintain exclusion over EH */
+
+- spin_unlock_irqrestore(ap->lock, flags);
++ spin_unlock_irqrestore(ap->lock, flags);
+
+- /* invoke EH, skip if unloading or suspended */
+- if (!(ap->pflags & (ATA_PFLAG_UNLOADING | ATA_PFLAG_SUSPENDED)))
+- ap->ops->error_handler(ap);
+- else {
+- /* if unloading, commence suicide */
+- if ((ap->pflags & ATA_PFLAG_UNLOADING) &&
+- !(ap->pflags & ATA_PFLAG_UNLOADED))
+- ata_eh_unload(ap);
+- ata_eh_finish(ap);
+- }
++ /* invoke EH, skip if unloading or suspended */
++ if (!(ap->pflags & (ATA_PFLAG_UNLOADING | ATA_PFLAG_SUSPENDED)))
++ ap->ops->error_handler(ap);
++ else {
++ /* if unloading, commence suicide */
++ if ((ap->pflags & ATA_PFLAG_UNLOADING) &&
++ !(ap->pflags & ATA_PFLAG_UNLOADED))
++ ata_eh_unload(ap);
++ ata_eh_finish(ap);
++ }
+
+- /* process port suspend request */
+- ata_eh_handle_port_suspend(ap);
++ /* process port suspend request */
++ ata_eh_handle_port_suspend(ap);
+
+- /* Exception might have happened after ->error_handler
+- * recovered the port but before this point. Repeat
+- * EH in such case.
+- */
+- spin_lock_irqsave(ap->lock, flags);
++ /*
++ * Exception might have happened after ->error_handler recovered the
++ * port but before this point. Repeat EH in such case.
++ */
++ spin_lock_irqsave(ap->lock, flags);
+
+- if (ap->pflags & ATA_PFLAG_EH_PENDING) {
+- if (--ap->eh_tries) {
+- spin_unlock_irqrestore(ap->lock, flags);
+- goto repeat;
+- }
+- ata_port_err(ap,
+- "EH pending after %d tries, giving up\n",
+- ATA_EH_MAX_TRIES);
+- ap->pflags &= ~ATA_PFLAG_EH_PENDING;
++ if (ap->pflags & ATA_PFLAG_EH_PENDING) {
++ if (--ap->eh_tries) {
++ spin_unlock_irqrestore(ap->lock, flags);
++ goto repeat;
+ }
++ ata_port_err(ap,
++ "EH pending after %d tries, giving up\n",
++ ATA_EH_MAX_TRIES);
++ ap->pflags &= ~ATA_PFLAG_EH_PENDING;
++ }
+
+- /* this run is complete, make sure EH info is clear */
+- ata_for_each_link(link, ap, HOST_FIRST)
+- memset(&link->eh_info, 0, sizeof(link->eh_info));
++ /* this run is complete, make sure EH info is clear */
++ ata_for_each_link(link, ap, HOST_FIRST)
++ memset(&link->eh_info, 0, sizeof(link->eh_info));
+
+- /* end eh (clear host_eh_scheduled) while holding
+- * ap->lock such that if exception occurs after this
+- * point but before EH completion, SCSI midlayer will
+- * re-initiate EH.
+- */
+- ap->ops->end_eh(ap);
++ /*
++ * end eh (clear host_eh_scheduled) while holding ap->lock such that if
++ * exception occurs after this point but before EH completion, SCSI
++ * midlayer will re-initiate EH.
++ */
++ ap->ops->end_eh(ap);
+
+- spin_unlock_irqrestore(ap->lock, flags);
+- ata_eh_release(ap);
+- } else {
+- WARN_ON(ata_qc_from_tag(ap, ap->link.active_tag) == NULL);
+- ap->ops->eng_timeout(ap);
+- }
++ spin_unlock_irqrestore(ap->lock, flags);
++ ata_eh_release(ap);
+
+ scsi_eh_flush_done_q(&ap->eh_done_q);
+
+@@ -912,8 +902,6 @@ void ata_qc_schedule_eh(struct ata_queued_cmd *qc)
+ {
+ struct ata_port *ap = qc->ap;
+
+- WARN_ON(!ap->ops->error_handler);
+-
+ qc->flags |= ATA_QCFLAG_EH;
+ ata_eh_set_pending(ap, 1);
+
+@@ -934,8 +922,6 @@ void ata_qc_schedule_eh(struct ata_queued_cmd *qc)
+ */
+ void ata_std_sched_eh(struct ata_port *ap)
+ {
+- WARN_ON(!ap->ops->error_handler);
+-
+ if (ap->pflags & ATA_PFLAG_INITIALIZING)
+ return;
+
+@@ -989,8 +975,6 @@ static int ata_do_link_abort(struct ata_port *ap, struct ata_link *link)
+ struct ata_queued_cmd *qc;
+ int tag, nr_aborted = 0;
+
+- WARN_ON(!ap->ops->error_handler);
+-
+ /* we're gonna abort all commands, no need for fast drain */
+ ata_eh_set_pending(ap, 0);
+
+@@ -1065,8 +1049,6 @@ EXPORT_SYMBOL_GPL(ata_port_abort);
+ */
+ static void __ata_port_freeze(struct ata_port *ap)
+ {
+- WARN_ON(!ap->ops->error_handler);
+-
+ if (ap->ops->freeze)
+ ap->ops->freeze(ap);
+
+@@ -1091,8 +1073,6 @@ static void __ata_port_freeze(struct ata_port *ap)
+ */
+ int ata_port_freeze(struct ata_port *ap)
+ {
+- WARN_ON(!ap->ops->error_handler);
+-
+ __ata_port_freeze(ap);
+
+ return ata_port_abort(ap);
+@@ -1112,9 +1092,6 @@ void ata_eh_freeze_port(struct ata_port *ap)
+ {
+ unsigned long flags;
+
+- if (!ap->ops->error_handler)
+- return;
+-
+ spin_lock_irqsave(ap->lock, flags);
+ __ata_port_freeze(ap);
+ spin_unlock_irqrestore(ap->lock, flags);
+@@ -1134,9 +1111,6 @@ void ata_eh_thaw_port(struct ata_port *ap)
+ {
+ unsigned long flags;
+
+- if (!ap->ops->error_handler)
+- return;
+-
+ spin_lock_irqsave(ap->lock, flags);
+
+ ap->pflags &= ~ATA_PFLAG_FROZEN;
+diff --git a/drivers/ata/libata-sata.c b/drivers/ata/libata-sata.c
+index 85e279a12f62c..99d4ab04bcce6 100644
+--- a/drivers/ata/libata-sata.c
++++ b/drivers/ata/libata-sata.c
+@@ -1158,12 +1158,7 @@ EXPORT_SYMBOL_GPL(ata_sas_port_alloc);
+ */
+ int ata_sas_port_start(struct ata_port *ap)
+ {
+- /*
+- * the port is marked as frozen at allocation time, but if we don't
+- * have new eh, we won't thaw it
+- */
+- if (!ap->ops->error_handler)
+- ap->pflags &= ~ATA_PFLAG_FROZEN;
++ /* the port is marked as frozen at allocation time */
+ return 0;
+ }
+ EXPORT_SYMBOL_GPL(ata_sas_port_start);
+diff --git a/drivers/ata/libata-scsi.c b/drivers/ata/libata-scsi.c
+index c6ece32de8e31..e55db9a6826f3 100644
+--- a/drivers/ata/libata-scsi.c
++++ b/drivers/ata/libata-scsi.c
+@@ -709,47 +709,6 @@ static void ata_qc_set_pc_nbytes(struct ata_queued_cmd *qc)
+ qc->nbytes = scsi_bufflen(scmd) + qc->extrabytes;
+ }
+
+-/**
+- * ata_dump_status - user friendly display of error info
+- * @ap: the port in question
+- * @tf: ptr to filled out taskfile
+- *
+- * Decode and dump the ATA error/status registers for the user so
+- * that they have some idea what really happened at the non
+- * make-believe layer.
+- *
+- * LOCKING:
+- * inherited from caller
+- */
+-static void ata_dump_status(struct ata_port *ap, struct ata_taskfile *tf)
+-{
+- u8 stat = tf->status, err = tf->error;
+-
+- if (stat & ATA_BUSY) {
+- ata_port_warn(ap, "status=0x%02x {Busy} ", stat);
+- } else {
+- ata_port_warn(ap, "status=0x%02x { %s%s%s%s%s%s%s} ", stat,
+- stat & ATA_DRDY ? "DriveReady " : "",
+- stat & ATA_DF ? "DeviceFault " : "",
+- stat & ATA_DSC ? "SeekComplete " : "",
+- stat & ATA_DRQ ? "DataRequest " : "",
+- stat & ATA_CORR ? "CorrectedError " : "",
+- stat & ATA_SENSE ? "Sense " : "",
+- stat & ATA_ERR ? "Error " : "");
+- if (err)
+- ata_port_warn(ap, "error=0x%02x {%s%s%s%s%s%s", err,
+- err & ATA_ABORTED ?
+- "DriveStatusError " : "",
+- err & ATA_ICRC ?
+- (err & ATA_ABORTED ?
+- "BadCRC " : "Sector ") : "",
+- err & ATA_UNC ? "UncorrectableError " : "",
+- err & ATA_IDNF ? "SectorIdNotFound " : "",
+- err & ATA_TRK0NF ? "TrackZeroNotFound " : "",
+- err & ATA_AMNF ? "AddrMarkNotFound " : "");
+- }
+-}
+-
+ /**
+ * ata_to_sense_error - convert ATA error to SCSI error
+ * @id: ATA device number
+@@ -758,7 +717,6 @@ static void ata_dump_status(struct ata_port *ap, struct ata_taskfile *tf)
+ * @sk: the sense key we'll fill out
+ * @asc: the additional sense code we'll fill out
+ * @ascq: the additional sense code qualifier we'll fill out
+- * @verbose: be verbose
+ *
+ * Converts an ATA error into a SCSI error. Fill out pointers to
+ * SK, ASC, and ASCQ bytes for later use in fixed or descriptor
+@@ -768,7 +726,7 @@ static void ata_dump_status(struct ata_port *ap, struct ata_taskfile *tf)
+ * spin_lock_irqsave(host lock)
+ */
+ static void ata_to_sense_error(unsigned id, u8 drv_stat, u8 drv_err, u8 *sk,
+- u8 *asc, u8 *ascq, int verbose)
++ u8 *asc, u8 *ascq)
+ {
+ int i;
+
+@@ -847,7 +805,7 @@ static void ata_to_sense_error(unsigned id, u8 drv_stat, u8 drv_err, u8 *sk,
+ *sk = sense_table[i][1];
+ *asc = sense_table[i][2];
+ *ascq = sense_table[i][3];
+- goto translate_done;
++ return;
+ }
+ }
+ }
+@@ -862,7 +820,7 @@ static void ata_to_sense_error(unsigned id, u8 drv_stat, u8 drv_err, u8 *sk,
+ *sk = stat_table[i][1];
+ *asc = stat_table[i][2];
+ *ascq = stat_table[i][3];
+- goto translate_done;
++ return;
+ }
+ }
+
+@@ -873,12 +831,6 @@ static void ata_to_sense_error(unsigned id, u8 drv_stat, u8 drv_err, u8 *sk,
+ *sk = ABORTED_COMMAND;
+ *asc = 0x00;
+ *ascq = 0x00;
+-
+- translate_done:
+- if (verbose)
+- pr_err("ata%u: translated ATA stat/err 0x%02x/%02x to SCSI SK/ASC/ASCQ 0x%x/%02x/%02x\n",
+- id, drv_stat, drv_err, *sk, *asc, *ascq);
+- return;
+ }
+
+ /*
+@@ -904,7 +856,6 @@ static void ata_gen_passthru_sense(struct ata_queued_cmd *qc)
+ struct ata_taskfile *tf = &qc->result_tf;
+ unsigned char *sb = cmd->sense_buffer;
+ unsigned char *desc = sb + 8;
+- int verbose = qc->ap->ops->error_handler == NULL;
+ u8 sense_key, asc, ascq;
+
+ memset(sb, 0, SCSI_SENSE_BUFFERSIZE);
+@@ -916,7 +867,7 @@ static void ata_gen_passthru_sense(struct ata_queued_cmd *qc)
+ if (qc->err_mask ||
+ tf->status & (ATA_BUSY | ATA_DF | ATA_ERR | ATA_DRQ)) {
+ ata_to_sense_error(qc->ap->print_id, tf->status, tf->error,
+- &sense_key, &asc, &ascq, verbose);
++ &sense_key, &asc, &ascq);
+ ata_scsi_set_sense(qc->dev, cmd, sense_key, asc, ascq);
+ } else {
+ /*
+@@ -999,7 +950,6 @@ static void ata_gen_ata_sense(struct ata_queued_cmd *qc)
+ struct scsi_cmnd *cmd = qc->scsicmd;
+ struct ata_taskfile *tf = &qc->result_tf;
+ unsigned char *sb = cmd->sense_buffer;
+- int verbose = qc->ap->ops->error_handler == NULL;
+ u64 block;
+ u8 sense_key, asc, ascq;
+
+@@ -1017,7 +967,7 @@ static void ata_gen_ata_sense(struct ata_queued_cmd *qc)
+ if (qc->err_mask ||
+ tf->status & (ATA_BUSY | ATA_DF | ATA_ERR | ATA_DRQ)) {
+ ata_to_sense_error(qc->ap->print_id, tf->status, tf->error,
+- &sense_key, &asc, &ascq, verbose);
++ &sense_key, &asc, &ascq);
+ ata_scsi_set_sense(dev, cmd, sense_key, asc, ascq);
+ } else {
+ /* Could not decode error */
+@@ -1186,9 +1136,6 @@ void ata_scsi_slave_destroy(struct scsi_device *sdev)
+ unsigned long flags;
+ struct ata_device *dev;
+
+- if (!ap->ops->error_handler)
+- return;
+-
+ spin_lock_irqsave(ap->lock, flags);
+ dev = __ata_scsi_find_dev(ap, sdev);
+ if (dev && dev->sdev) {
+@@ -1675,7 +1622,6 @@ static void ata_qc_done(struct ata_queued_cmd *qc)
+
+ static void ata_scsi_qc_complete(struct ata_queued_cmd *qc)
+ {
+- struct ata_port *ap = qc->ap;
+ struct scsi_cmnd *cmd = qc->scsicmd;
+ u8 *cdb = cmd->cmnd;
+ int need_sense = (qc->err_mask != 0) &&
+@@ -1699,9 +1645,6 @@ static void ata_scsi_qc_complete(struct ata_queued_cmd *qc)
+ /* Keep the SCSI ML and status byte, clear host byte. */
+ cmd->result &= 0x0000ffff;
+
+- if (need_sense && !ap->ops->error_handler)
+- ata_dump_status(ap, &qc->result_tf);
+-
+ ata_qc_done(qc);
+ }
+
+@@ -2608,71 +2551,6 @@ static unsigned int ata_scsiop_report_luns(struct ata_scsi_args *args, u8 *rbuf)
+ return 0;
+ }
+
+-static void atapi_sense_complete(struct ata_queued_cmd *qc)
+-{
+- if (qc->err_mask && ((qc->err_mask & AC_ERR_DEV) == 0)) {
+- /* FIXME: not quite right; we don't want the
+- * translation of taskfile registers into
+- * a sense descriptors, since that's only
+- * correct for ATA, not ATAPI
+- */
+- ata_gen_passthru_sense(qc);
+- }
+-
+- ata_qc_done(qc);
+-}
+-
+-/* is it pointless to prefer PIO for "safety reasons"? */
+-static inline int ata_pio_use_silly(struct ata_port *ap)
+-{
+- return (ap->flags & ATA_FLAG_PIO_DMA);
+-}
+-
+-static void atapi_request_sense(struct ata_queued_cmd *qc)
+-{
+- struct ata_port *ap = qc->ap;
+- struct scsi_cmnd *cmd = qc->scsicmd;
+-
+- memset(cmd->sense_buffer, 0, SCSI_SENSE_BUFFERSIZE);
+-
+-#ifdef CONFIG_ATA_SFF
+- if (ap->ops->sff_tf_read)
+- ap->ops->sff_tf_read(ap, &qc->tf);
+-#endif
+-
+- /* fill these in, for the case where they are -not- overwritten */
+- cmd->sense_buffer[0] = 0x70;
+- cmd->sense_buffer[2] = qc->tf.error >> 4;
+-
+- ata_qc_reinit(qc);
+-
+- /* setup sg table and init transfer direction */
+- sg_init_one(&qc->sgent, cmd->sense_buffer, SCSI_SENSE_BUFFERSIZE);
+- ata_sg_init(qc, &qc->sgent, 1);
+- qc->dma_dir = DMA_FROM_DEVICE;
+-
+- memset(&qc->cdb, 0, qc->dev->cdb_len);
+- qc->cdb[0] = REQUEST_SENSE;
+- qc->cdb[4] = SCSI_SENSE_BUFFERSIZE;
+-
+- qc->tf.flags |= ATA_TFLAG_ISADDR | ATA_TFLAG_DEVICE;
+- qc->tf.command = ATA_CMD_PACKET;
+-
+- if (ata_pio_use_silly(ap)) {
+- qc->tf.protocol = ATAPI_PROT_DMA;
+- qc->tf.feature |= ATAPI_PKT_DMA;
+- } else {
+- qc->tf.protocol = ATAPI_PROT_PIO;
+- qc->tf.lbam = SCSI_SENSE_BUFFERSIZE;
+- qc->tf.lbah = 0;
+- }
+- qc->nbytes = SCSI_SENSE_BUFFERSIZE;
+-
+- qc->complete_fn = atapi_sense_complete;
+-
+- ata_qc_issue(qc);
+-}
+-
+ /*
+ * ATAPI devices typically report zero for their SCSI version, and sometimes
+ * deviate from the spec WRT response data format. If SCSI version is
+@@ -2698,9 +2576,8 @@ static void atapi_qc_complete(struct ata_queued_cmd *qc)
+ struct scsi_cmnd *cmd = qc->scsicmd;
+ unsigned int err_mask = qc->err_mask;
+
+- /* handle completion from new EH */
+- if (unlikely(qc->ap->ops->error_handler &&
+- (err_mask || qc->flags & ATA_QCFLAG_SENSE_VALID))) {
++ /* handle completion from EH */
++ if (unlikely(err_mask || qc->flags & ATA_QCFLAG_SENSE_VALID)) {
+
+ if (!(qc->flags & ATA_QCFLAG_SENSE_VALID)) {
+ /* FIXME: not quite right; we don't want the
+@@ -2732,23 +2609,10 @@ static void atapi_qc_complete(struct ata_queued_cmd *qc)
+ return;
+ }
+
+- /* successful completion or old EH failure path */
+- if (unlikely(err_mask & AC_ERR_DEV)) {
+- cmd->result = SAM_STAT_CHECK_CONDITION;
+- atapi_request_sense(qc);
+- return;
+- } else if (unlikely(err_mask)) {
+- /* FIXME: not quite right; we don't want the
+- * translation of taskfile registers into
+- * a sense descriptors, since that's only
+- * correct for ATA, not ATAPI
+- */
+- ata_gen_passthru_sense(qc);
+- } else {
+- if (cmd->cmnd[0] == INQUIRY && (cmd->cmnd[1] & 0x03) == 0)
+- atapi_fixup_inquiry(cmd);
+- cmd->result = SAM_STAT_GOOD;
+- }
++ /* successful completion path */
++ if (cmd->cmnd[0] == INQUIRY && (cmd->cmnd[1] & 0x03) == 0)
++ atapi_fixup_inquiry(cmd);
++ cmd->result = SAM_STAT_GOOD;
+
+ ata_qc_done(qc);
+ }
+@@ -4797,9 +4661,6 @@ int ata_scsi_user_scan(struct Scsi_Host *shost, unsigned int channel,
+ unsigned long flags;
+ int devno, rc = 0;
+
+- if (!ap->ops->error_handler)
+- return -EOPNOTSUPP;
+-
+ if (lun != SCAN_WILD_CARD && lun)
+ return -EINVAL;
+
+diff --git a/drivers/ata/libata-sff.c b/drivers/ata/libata-sff.c
+index 9d28badfe41d6..84471d92cd1b9 100644
+--- a/drivers/ata/libata-sff.c
++++ b/drivers/ata/libata-sff.c
+@@ -883,31 +883,21 @@ static void ata_hsm_qc_complete(struct ata_queued_cmd *qc, int in_wq)
+ {
+ struct ata_port *ap = qc->ap;
+
+- if (ap->ops->error_handler) {
+- if (in_wq) {
+- /* EH might have kicked in while host lock is
+- * released.
+- */
+- qc = ata_qc_from_tag(ap, qc->tag);
+- if (qc) {
+- if (likely(!(qc->err_mask & AC_ERR_HSM))) {
+- ata_sff_irq_on(ap);
+- ata_qc_complete(qc);
+- } else
+- ata_port_freeze(ap);
+- }
+- } else {
+- if (likely(!(qc->err_mask & AC_ERR_HSM)))
++ if (in_wq) {
++ /* EH might have kicked in while host lock is released. */
++ qc = ata_qc_from_tag(ap, qc->tag);
++ if (qc) {
++ if (likely(!(qc->err_mask & AC_ERR_HSM))) {
++ ata_sff_irq_on(ap);
+ ata_qc_complete(qc);
+- else
++ } else
+ ata_port_freeze(ap);
+ }
+ } else {
+- if (in_wq) {
+- ata_sff_irq_on(ap);
+- ata_qc_complete(qc);
+- } else
++ if (likely(!(qc->err_mask & AC_ERR_HSM)))
+ ata_qc_complete(qc);
++ else
++ ata_port_freeze(ap);
+ }
+ }
+
+diff --git a/include/linux/libata.h b/include/linux/libata.h
+index 820f7a3a2749b..3eeea76c30de4 100644
+--- a/include/linux/libata.h
++++ b/include/linux/libata.h
+@@ -1785,7 +1785,7 @@ static inline struct ata_queued_cmd *ata_qc_from_tag(struct ata_port *ap,
+ {
+ struct ata_queued_cmd *qc = __ata_qc_from_tag(ap, tag);
+
+- if (unlikely(!qc) || !ap->ops->error_handler)
++ if (unlikely(!qc))
+ return qc;
+
+ if ((qc->flags & (ATA_QCFLAG_ACTIVE |
+--
+2.40.1
+
--- /dev/null
+From 3d3f1a1f0368dbbe588de3620cacee76eab1ffc8 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 4 Aug 2023 13:33:12 +0800
+Subject: autofs: fix memory leak of waitqueues in autofs_catatonic_mode
+
+From: Fedor Pchelkin <pchelkin@ispras.ru>
+
+[ Upstream commit ccbe77f7e45dfb4420f7f531b650c00c6e9c7507 ]
+
+Syzkaller reports a memory leak:
+
+BUG: memory leak
+unreferenced object 0xffff88810b279e00 (size 96):
+ comm "syz-executor399", pid 3631, jiffies 4294964921 (age 23.870s)
+ hex dump (first 32 bytes):
+ 00 00 00 00 00 00 00 00 08 9e 27 0b 81 88 ff ff ..........'.....
+ 08 9e 27 0b 81 88 ff ff 00 00 00 00 00 00 00 00 ..'.............
+ backtrace:
+ [<ffffffff814cfc90>] kmalloc_trace+0x20/0x90 mm/slab_common.c:1046
+ [<ffffffff81bb75ca>] kmalloc include/linux/slab.h:576 [inline]
+ [<ffffffff81bb75ca>] autofs_wait+0x3fa/0x9a0 fs/autofs/waitq.c:378
+ [<ffffffff81bb88a7>] autofs_do_expire_multi+0xa7/0x3e0 fs/autofs/expire.c:593
+ [<ffffffff81bb8c33>] autofs_expire_multi+0x53/0x80 fs/autofs/expire.c:619
+ [<ffffffff81bb6972>] autofs_root_ioctl_unlocked+0x322/0x3b0 fs/autofs/root.c:897
+ [<ffffffff81bb6a95>] autofs_root_ioctl+0x25/0x30 fs/autofs/root.c:910
+ [<ffffffff81602a9c>] vfs_ioctl fs/ioctl.c:51 [inline]
+ [<ffffffff81602a9c>] __do_sys_ioctl fs/ioctl.c:870 [inline]
+ [<ffffffff81602a9c>] __se_sys_ioctl fs/ioctl.c:856 [inline]
+ [<ffffffff81602a9c>] __x64_sys_ioctl+0xfc/0x140 fs/ioctl.c:856
+ [<ffffffff84608225>] do_syscall_x64 arch/x86/entry/common.c:50 [inline]
+ [<ffffffff84608225>] do_syscall_64+0x35/0xb0 arch/x86/entry/common.c:80
+ [<ffffffff84800087>] entry_SYSCALL_64_after_hwframe+0x63/0xcd
+
+autofs_wait_queue structs should be freed if their wait_ctr becomes zero.
+Otherwise they will be lost.
+
+In this case an AUTOFS_IOC_EXPIRE_MULTI ioctl is done, then a new
+waitqueue struct is allocated in autofs_wait(), its initial wait_ctr
+equals 2. After that wait_event_killable() is interrupted (it returns
+-ERESTARTSYS), so that 'wq->name.name == NULL' condition may be not
+satisfied. Actually, this condition can be satisfied when
+autofs_wait_release() or autofs_catatonic_mode() is called and, what is
+also important, wait_ctr is decremented in those places. Upon the exit of
+autofs_wait(), wait_ctr is decremented to 1. Then the unmounting process
+begins: kill_sb calls autofs_catatonic_mode(), which should have freed the
+waitqueues, but it only decrements its usage counter to zero which is not
+a correct behaviour.
+
+edit:imk
+This description is of course not correct. The umount performed as a result
+of an expire is a umount of a mount that has been automounted, it's not the
+autofs mount itself. They happen independently, usually after everything
+mounted within the autofs file system has been expired away. If everything
+hasn't been expired away the automount daemon can still exit leaving mounts
+in place. But expires done in both cases will result in a notification that
+calls autofs_wait_release() with a result status. The problem case is the
+summary execution of of the automount daemon. In this case any waiting
+processes won't be woken up until either they are terminated or the mount
+is umounted.
+end edit: imk
+
+So in catatonic mode we should free waitqueues which counter becomes zero.
+
+edit: imk
+Initially I was concerned that the calling of autofs_wait_release() and
+autofs_catatonic_mode() was not mutually exclusive but that can't be the
+case (obviously) because the queue entry (or entries) is removed from the
+list when either of these two functions are called. Consequently the wait
+entry will be freed by only one of these functions or by the woken process
+in autofs_wait() depending on the order of the calls.
+end edit: imk
+
+Reported-by: syzbot+5e53f70e69ff0c0a1c0c@syzkaller.appspotmail.com
+Suggested-by: Takeshi Misawa <jeliantsurux@gmail.com>
+Signed-off-by: Fedor Pchelkin <pchelkin@ispras.ru>
+Signed-off-by: Alexey Khoroshilov <khoroshilov@ispras.ru>
+Signed-off-by: Ian Kent <raven@themaw.net>
+Cc: Matthew Wilcox <willy@infradead.org>
+Cc: Andrei Vagin <avagin@gmail.com>
+Cc: autofs@vger.kernel.org
+Cc: linux-kernel@vger.kernel.org
+Message-Id: <169112719161.7590.6700123246297365841.stgit@donald.themaw.net>
+Signed-off-by: Christian Brauner <brauner@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ fs/autofs/waitq.c | 3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+diff --git a/fs/autofs/waitq.c b/fs/autofs/waitq.c
+index 54c1f8b8b0757..efdc76732faed 100644
+--- a/fs/autofs/waitq.c
++++ b/fs/autofs/waitq.c
+@@ -32,8 +32,9 @@ void autofs_catatonic_mode(struct autofs_sb_info *sbi)
+ wq->status = -ENOENT; /* Magic is gone - report failure */
+ kfree(wq->name.name - wq->offset);
+ wq->name.name = NULL;
+- wq->wait_ctr--;
+ wake_up_interruptible(&wq->queue);
++ if (!--wq->wait_ctr)
++ kfree(wq);
+ wq = nwq;
+ }
+ fput(sbi->pipe); /* Close the pipe */
+--
+2.40.1
+
--- /dev/null
+From 27a486968e71cda6512269f614fd4ec685755bbd Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 21 Aug 2023 17:56:00 +0800
+Subject: blk-mq: fix tags leak when shrink nr_hw_queues
+
+From: Chengming Zhou <zhouchengming@bytedance.com>
+
+[ Upstream commit e1dd7bc93029024af5688253b0c05181d6e01f8e ]
+
+Although we don't need to realloc set->tags[] when shrink nr_hw_queues,
+we need to free them. Or these tags will be leaked.
+
+How to reproduce:
+1. mount -t configfs configfs /mnt
+2. modprobe null_blk nr_devices=0 submit_queues=8
+3. mkdir /mnt/nullb/nullb0
+4. echo 1 > /mnt/nullb/nullb0/power
+5. echo 4 > /mnt/nullb/nullb0/submit_queues
+6. rmdir /mnt/nullb/nullb0
+
+In step 4, will alloc 9 tags (8 submit queues and 1 poll queue), then
+in step 5, new_nr_hw_queues = 5 (4 submit queues and 1 poll queue).
+At last in step 6, only these 5 tags are freed, the other 4 tags leaked.
+
+Signed-off-by: Chengming Zhou <zhouchengming@bytedance.com>
+Reviewed-by: Ming Lei <ming.lei@redhat.com>
+Link: https://lore.kernel.org/r/20230821095602.70742-1-chengming.zhou@linux.dev
+Signed-off-by: Jens Axboe <axboe@kernel.dk>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ block/blk-mq.c | 6 +++++-
+ 1 file changed, 5 insertions(+), 1 deletion(-)
+
+diff --git a/block/blk-mq.c b/block/blk-mq.c
+index 953f08354c8c3..d9b365c2eaa0d 100644
+--- a/block/blk-mq.c
++++ b/block/blk-mq.c
+@@ -4402,9 +4402,13 @@ static int blk_mq_realloc_tag_set_tags(struct blk_mq_tag_set *set,
+ int new_nr_hw_queues)
+ {
+ struct blk_mq_tags **new_tags;
++ int i;
+
+- if (set->nr_hw_queues >= new_nr_hw_queues)
++ if (set->nr_hw_queues >= new_nr_hw_queues) {
++ for (i = new_nr_hw_queues; i < set->nr_hw_queues; i++)
++ __blk_mq_free_map_and_rqs(set, i);
+ goto done;
++ }
+
+ new_tags = kcalloc_node(new_nr_hw_queues, sizeof(struct blk_mq_tags *),
+ GFP_KERNEL, set->numa_node);
+--
+2.40.1
+
--- /dev/null
+From 21e83fd7bf60c763036a94ec5f1f8aca8f29d3d5 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 8 Sep 2023 08:57:02 +0800
+Subject: blk-mq: fix tags UAF when shrinking q->nr_hw_queues
+
+From: Chengming Zhou <zhouchengming@bytedance.com>
+
+[ Upstream commit 6be6d112419713334ddd9c01f219ca16adaa4c76 ]
+
+When nr_hw_queues shrink, we free the excess tags before realloc'ing
+hw_ctxs for each queue. During that resize, we may need to access those
+tags, like blk_mq_tag_idle(hctx) will access queue shared tags.
+
+This can cause a slab use-after-free, as reported by KASAN. Fix it by
+moving the releasing of excess tags to the end.
+
+Fixes: e1dd7bc93029 ("blk-mq: fix tags leak when shrink nr_hw_queues")
+Reported-by: Yi Zhang <yi.zhang@redhat.com>
+Closes: https://lore.kernel.org/all/CAHj4cs_CK63uoDpGBGZ6DN4OCTpzkR3UaVgK=LX8Owr8ej2ieQ@mail.gmail.com/
+Cc: Ming Lei <ming.lei@redhat.com>
+Signed-off-by: Chengming Zhou <zhouchengming@bytedance.com>
+Reviewed-by: Hannes Reinecke <hare@suse.de>
+Link: https://lore.kernel.org/r/20230908005702.2183908-1-chengming.zhou@linux.dev
+Signed-off-by: Jens Axboe <axboe@kernel.dk>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ block/blk-mq.c | 13 +++++++------
+ 1 file changed, 7 insertions(+), 6 deletions(-)
+
+diff --git a/block/blk-mq.c b/block/blk-mq.c
+index d9b365c2eaa0d..a90f1efb1c978 100644
+--- a/block/blk-mq.c
++++ b/block/blk-mq.c
+@@ -4404,11 +4404,8 @@ static int blk_mq_realloc_tag_set_tags(struct blk_mq_tag_set *set,
+ struct blk_mq_tags **new_tags;
+ int i;
+
+- if (set->nr_hw_queues >= new_nr_hw_queues) {
+- for (i = new_nr_hw_queues; i < set->nr_hw_queues; i++)
+- __blk_mq_free_map_and_rqs(set, i);
++ if (set->nr_hw_queues >= new_nr_hw_queues)
+ goto done;
+- }
+
+ new_tags = kcalloc_node(new_nr_hw_queues, sizeof(struct blk_mq_tags *),
+ GFP_KERNEL, set->numa_node);
+@@ -4708,7 +4705,8 @@ static void __blk_mq_update_nr_hw_queues(struct blk_mq_tag_set *set,
+ {
+ struct request_queue *q;
+ LIST_HEAD(head);
+- int prev_nr_hw_queues;
++ int prev_nr_hw_queues = set->nr_hw_queues;
++ int i;
+
+ lockdep_assert_held(&set->tag_list_lock);
+
+@@ -4735,7 +4733,6 @@ static void __blk_mq_update_nr_hw_queues(struct blk_mq_tag_set *set,
+ blk_mq_sysfs_unregister_hctxs(q);
+ }
+
+- prev_nr_hw_queues = set->nr_hw_queues;
+ if (blk_mq_realloc_tag_set_tags(set, nr_hw_queues) < 0)
+ goto reregister;
+
+@@ -4771,6 +4768,10 @@ static void __blk_mq_update_nr_hw_queues(struct blk_mq_tag_set *set,
+
+ list_for_each_entry(q, &set->tag_list, tag_set_list)
+ blk_mq_unfreeze_queue(q);
++
++ /* Free the excess tags when nr_hw_queues shrink. */
++ for (i = set->nr_hw_queues; i < prev_nr_hw_queues; i++)
++ __blk_mq_free_map_and_rqs(set, i);
+ }
+
+ void blk_mq_update_nr_hw_queues(struct blk_mq_tag_set *set, int nr_hw_queues)
+--
+2.40.1
+
--- /dev/null
+From 0500541602ed56dc37421a0587ee2adb0d703730 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 30 Jun 2023 21:32:30 +0800
+Subject: Bluetooth: btusb: Add a new VID/PID 0489/e0f6 for MT7922
+
+From: Chris Lu <chris.lu@mediatek.com>
+
+[ Upstream commit b6cfa1c29afb6d527652938b0eb8db17b194bddc ]
+
+Add VID/PID 0489/e0f6 for MediaTek MT7922 USB Bluetooth chip.
+
+The information in /sys/kernel/debug/usb/devices about the Bluetooth
+device is listed as the below.
+
+T: Bus=01 Lev=01 Prnt=01 Port=04 Cnt=03 Dev#= 4 Spd=480 MxCh= 0
+D: Ver= 2.10 Cls=ef(misc ) Sub=02 Prot=01 MxPS=64 #Cfgs= 1
+P: Vendor=0489 ProdID=e0f6 Rev= 1.00
+S: Manufacturer=MediaTek Inc.
+S: Product=Wireless_Device
+S: SerialNumber=000000000
+C:* #Ifs= 3 Cfg#= 1 Atr=e0 MxPwr=100mA
+A: FirstIf#= 0 IfCount= 3 Cls=e0(wlcon) Sub=01 Prot=01
+I:* If#= 0 Alt= 0 #EPs= 3 Cls=e0(wlcon) Sub=01 Prot=01 Driver=btusb
+E: Ad=81(I) Atr=03(Int.) MxPS= 16 Ivl=125us
+E: Ad=82(I) Atr=02(Bulk) MxPS= 512 Ivl=0ms
+E: Ad=02(O) Atr=02(Bulk) MxPS= 512 Ivl=0ms
+I:* If#= 1 Alt= 0 #EPs= 2 Cls=e0(wlcon) Sub=01 Prot=01 Driver=btusb
+E: Ad=83(I) Atr=01(Isoc) MxPS= 0 Ivl=1ms
+E: Ad=03(O) Atr=01(Isoc) MxPS= 0 Ivl=1ms
+I: If#= 1 Alt= 1 #EPs= 2 Cls=e0(wlcon) Sub=01 Prot=01 Driver=btusb
+E: Ad=83(I) Atr=01(Isoc) MxPS= 9 Ivl=1ms
+E: Ad=03(O) Atr=01(Isoc) MxPS= 9 Ivl=1ms
+I: If#= 1 Alt= 2 #EPs= 2 Cls=e0(wlcon) Sub=01 Prot=01 Driver=btusb
+E: Ad=83(I) Atr=01(Isoc) MxPS= 17 Ivl=1ms
+E: Ad=03(O) Atr=01(Isoc) MxPS= 17 Ivl=1ms
+I: If#= 1 Alt= 3 #EPs= 2 Cls=e0(wlcon) Sub=01 Prot=01 Driver=btusb
+E: Ad=83(I) Atr=01(Isoc) MxPS= 25 Ivl=1ms
+E: Ad=03(O) Atr=01(Isoc) MxPS= 25 Ivl=1ms
+I: If#= 1 Alt= 4 #EPs= 2 Cls=e0(wlcon) Sub=01 Prot=01 Driver=btusb
+E: Ad=83(I) Atr=01(Isoc) MxPS= 33 Ivl=1ms
+E: Ad=03(O) Atr=01(Isoc) MxPS= 33 Ivl=1ms
+I: If#= 1 Alt= 5 #EPs= 2 Cls=e0(wlcon) Sub=01 Prot=01 Driver=btusb
+E: Ad=83(I) Atr=01(Isoc) MxPS= 49 Ivl=1ms
+E: Ad=03(O) Atr=01(Isoc) MxPS= 49 Ivl=1ms
+I: If#= 1 Alt= 6 #EPs= 2 Cls=e0(wlcon) Sub=01 Prot=01 Driver=btusb
+E: Ad=83(I) Atr=01(Isoc) MxPS= 63 Ivl=1ms
+E: Ad=03(O) Atr=01(Isoc) MxPS= 63 Ivl=1ms
+I:* If#= 2 Alt= 0 #EPs= 2 Cls=e0(wlcon) Sub=01 Prot=01 Driver=(none)
+E: Ad=8a(I) Atr=03(Int.) MxPS= 64 Ivl=125us
+E: Ad=0a(O) Atr=03(Int.) MxPS= 64 Ivl=125us
+I: If#= 2 Alt= 1 #EPs= 2 Cls=e0(wlcon) Sub=01 Prot=01 Driver=(none)
+E: Ad=8a(I) Atr=03(Int.) MxPS= 512 Ivl=125us
+E: Ad=0a(O) Atr=03(Int.) MxPS= 512 Ivl=125us
+
+Signed-off-by: Chris Lu <chris.lu@mediatek.com>
+Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/bluetooth/btusb.c | 3 +++
+ 1 file changed, 3 insertions(+)
+
+diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c
+index e5c7852f8b133..3cdb2dea1f559 100644
+--- a/drivers/bluetooth/btusb.c
++++ b/drivers/bluetooth/btusb.c
+@@ -631,6 +631,9 @@ static const struct usb_device_id blacklist_table[] = {
+ { USB_DEVICE(0x0489, 0xe0f5), .driver_info = BTUSB_MEDIATEK |
+ BTUSB_WIDEBAND_SPEECH |
+ BTUSB_VALID_LE_STATES },
++ { USB_DEVICE(0x0489, 0xe0f6), .driver_info = BTUSB_MEDIATEK |
++ BTUSB_WIDEBAND_SPEECH |
++ BTUSB_VALID_LE_STATES },
+
+ /* Additional Realtek 8723AE Bluetooth devices */
+ { USB_DEVICE(0x0930, 0x021d), .driver_info = BTUSB_REALTEK },
+--
+2.40.1
+
--- /dev/null
+From 588c90ec0ef2d90cde1fd7b87ae4e6ae751ad2de Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sun, 2 Jul 2023 23:01:38 +0200
+Subject: Bluetooth: btusb: Add device 0489:e0f5 as MT7922 device
+
+From: Valentin David <valentin.david@gmail.com>
+
+[ Upstream commit e160a8f4e920e5cf4e16a17f57367954c9436aea ]
+
+Asus ROG Ally gaming computer has a MediaTek MT7922 chip that uses USB id
+0489:e0f5 and needs to be added to the table. Without this, the device is
+not usable and gives the following error:
+
+Bluetooth: hci0: Opcode 0x c03 failed: -110
+
+Output from /sys/kernel/debug/usb/devices:
+
+T: Bus=01 Lev=01 Prnt=01 Port=03 Cnt=03 Dev#= 4 Spd=480 MxCh= 0
+D: Ver= 2.10 Cls=ef(misc ) Sub=02 Prot=01 MxPS=64 #Cfgs= 1
+P: Vendor=0489 ProdID=e0f5 Rev= 1.00
+S: Manufacturer=MediaTek Inc.
+S: Product=Wireless_Device
+S: SerialNumber=000000000
+C:* #Ifs= 3 Cfg#= 1 Atr=e0 MxPwr=100mA
+A: FirstIf#= 0 IfCount= 3 Cls=e0(wlcon) Sub=01 Prot=01
+I:* If#= 0 Alt= 0 #EPs= 3 Cls=e0(wlcon) Sub=01 Prot=01 Driver=btusb
+E: Ad=81(I) Atr=03(Int.) MxPS= 16 Ivl=125us
+E: Ad=82(I) Atr=02(Bulk) MxPS= 512 Ivl=0ms
+E: Ad=02(O) Atr=02(Bulk) MxPS= 512 Ivl=0ms
+I:* If#= 1 Alt= 0 #EPs= 2 Cls=e0(wlcon) Sub=01 Prot=01 Driver=btusb
+E: Ad=83(I) Atr=01(Isoc) MxPS= 0 Ivl=1ms
+E: Ad=03(O) Atr=01(Isoc) MxPS= 0 Ivl=1ms
+I: If#= 1 Alt= 1 #EPs= 2 Cls=e0(wlcon) Sub=01 Prot=01 Driver=btusb
+E: Ad=83(I) Atr=01(Isoc) MxPS= 9 Ivl=1ms
+E: Ad=03(O) Atr=01(Isoc) MxPS= 9 Ivl=1ms
+I: If#= 1 Alt= 2 #EPs= 2 Cls=e0(wlcon) Sub=01 Prot=01 Driver=btusb
+E: Ad=83(I) Atr=01(Isoc) MxPS= 17 Ivl=1ms
+E: Ad=03(O) Atr=01(Isoc) MxPS= 17 Ivl=1ms
+I: If#= 1 Alt= 3 #EPs= 2 Cls=e0(wlcon) Sub=01 Prot=01 Driver=btusb
+E: Ad=83(I) Atr=01(Isoc) MxPS= 25 Ivl=1ms
+E: Ad=03(O) Atr=01(Isoc) MxPS= 25 Ivl=1ms
+I: If#= 1 Alt= 4 #EPs= 2 Cls=e0(wlcon) Sub=01 Prot=01 Driver=btusb
+E: Ad=83(I) Atr=01(Isoc) MxPS= 33 Ivl=1ms
+E: Ad=03(O) Atr=01(Isoc) MxPS= 33 Ivl=1ms
+I: If#= 1 Alt= 5 #EPs= 2 Cls=e0(wlcon) Sub=01 Prot=01 Driver=btusb
+E: Ad=83(I) Atr=01(Isoc) MxPS= 49 Ivl=1ms
+E: Ad=03(O) Atr=01(Isoc) MxPS= 49 Ivl=1ms
+I: If#= 1 Alt= 6 #EPs= 2 Cls=e0(wlcon) Sub=01 Prot=01 Driver=btusb
+E: Ad=83(I) Atr=01(Isoc) MxPS= 63 Ivl=1ms
+E: Ad=03(O) Atr=01(Isoc) MxPS= 63 Ivl=1ms
+I:* If#= 2 Alt= 0 #EPs= 2 Cls=e0(wlcon) Sub=01 Prot=01 Driver=(none)
+E: Ad=8a(I) Atr=03(Int.) MxPS= 64 Ivl=125us
+E: Ad=0a(O) Atr=03(Int.) MxPS= 64 Ivl=125us
+I: If#= 2 Alt= 1 #EPs= 2 Cls=e0(wlcon) Sub=01 Prot=01 Driver=(none)
+E: Ad=8a(I) Atr=03(Int.) MxPS= 512 Ivl=125us
+E: Ad=0a(O) Atr=03(Int.) MxPS= 512 Ivl=125us
+
+Signed-off-by: Valentin David <valentin.david@gmail.com>
+Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/bluetooth/btusb.c | 3 +++
+ 1 file changed, 3 insertions(+)
+
+diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c
+index e685acc5cacd9..e5c7852f8b133 100644
+--- a/drivers/bluetooth/btusb.c
++++ b/drivers/bluetooth/btusb.c
+@@ -628,6 +628,9 @@ static const struct usb_device_id blacklist_table[] = {
+ { USB_DEVICE(0x0489, 0xe0f2), .driver_info = BTUSB_MEDIATEK |
+ BTUSB_WIDEBAND_SPEECH |
+ BTUSB_VALID_LE_STATES },
++ { USB_DEVICE(0x0489, 0xe0f5), .driver_info = BTUSB_MEDIATEK |
++ BTUSB_WIDEBAND_SPEECH |
++ BTUSB_VALID_LE_STATES },
+
+ /* Additional Realtek 8723AE Bluetooth devices */
+ { USB_DEVICE(0x0930, 0x021d), .driver_info = BTUSB_REALTEK },
+--
+2.40.1
+
--- /dev/null
+From a048f5fe9535c89f1805271df93435d4f779cbee Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 7 Jul 2023 14:29:58 +0800
+Subject: Bluetooth: btusb: Add new VID/PID 0489/e102 for MT7922
+
+From: Chris Lu <chris.lu@mediatek.com>
+
+[ Upstream commit bf809efdcc4df4132c8c261fbba7121909dc6211 ]
+
+Add VID 0489 & PID e102 for MediaTek MT7922 USB Bluetooth chip.
+
+The information in /sys/kernel/debug/usb/devices about the Bluetooth
+device is listed as the below.
+
+T: Bus=05 Lev=01 Prnt=01 Port=00 Cnt=01 Dev#= 2 Spd=480 MxCh= 0
+D: Ver= 2.10 Cls=ef(misc ) Sub=02 Prot=01 MxPS=64 #Cfgs= 1
+P: Vendor=0489 ProdID=e102 Rev= 1.00
+S: Manufacturer=MediaTek Inc.
+S: Product=Wireless_Device
+S: SerialNumber=000000000
+C:* #Ifs= 3 Cfg#= 1 Atr=e0 MxPwr=100mA
+A: FirstIf#= 0 IfCount= 3 Cls=e0(wlcon) Sub=01 Prot=01
+I:* If#= 0 Alt= 0 #EPs= 3 Cls=e0(wlcon) Sub=01 Prot=01 Driver=btusb
+E: Ad=81(I) Atr=03(Int.) MxPS= 16 Ivl=125us
+E: Ad=82(I) Atr=02(Bulk) MxPS= 512 Ivl=0ms
+E: Ad=02(O) Atr=02(Bulk) MxPS= 512 Ivl=0ms
+I:* If#= 1 Alt= 0 #EPs= 2 Cls=e0(wlcon) Sub=01 Prot=01 Driver=btusb
+E: Ad=83(I) Atr=01(Isoc) MxPS= 0 Ivl=1ms
+E: Ad=03(O) Atr=01(Isoc) MxPS= 0 Ivl=1ms
+I: If#= 1 Alt= 1 #EPs= 2 Cls=e0(wlcon) Sub=01 Prot=01 Driver=btusb
+E: Ad=83(I) Atr=01(Isoc) MxPS= 9 Ivl=1ms
+E: Ad=03(O) Atr=01(Isoc) MxPS= 9 Ivl=1ms
+I: If#= 1 Alt= 2 #EPs= 2 Cls=e0(wlcon) Sub=01 Prot=01 Driver=btusb
+E: Ad=83(I) Atr=01(Isoc) MxPS= 17 Ivl=1ms
+E: Ad=03(O) Atr=01(Isoc) MxPS= 17 Ivl=1ms
+I: If#= 1 Alt= 3 #EPs= 2 Cls=e0(wlcon) Sub=01 Prot=01 Driver=btusb
+E: Ad=83(I) Atr=01(Isoc) MxPS= 25 Ivl=1ms
+E: Ad=03(O) Atr=01(Isoc) MxPS= 25 Ivl=1ms
+I: If#= 1 Alt= 4 #EPs= 2 Cls=e0(wlcon) Sub=01 Prot=01 Driver=btusb
+E: Ad=83(I) Atr=01(Isoc) MxPS= 33 Ivl=1ms
+E: Ad=03(O) Atr=01(Isoc) MxPS= 33 Ivl=1ms
+I: If#= 1 Alt= 5 #EPs= 2 Cls=e0(wlcon) Sub=01 Prot=01 Driver=btusb
+E: Ad=83(I) Atr=01(Isoc) MxPS= 49 Ivl=1ms
+E: Ad=03(O) Atr=01(Isoc) MxPS= 49 Ivl=1ms
+I: If#= 1 Alt= 6 #EPs= 2 Cls=e0(wlcon) Sub=01 Prot=01 Driver=btusb
+E: Ad=83(I) Atr=01(Isoc) MxPS= 63 Ivl=1ms
+E: Ad=03(O) Atr=01(Isoc) MxPS= 63 Ivl=1ms
+I:* If#= 2 Alt= 0 #EPs= 2 Cls=e0(wlcon) Sub=01 Prot=01 Driver=(none)
+E: Ad=8a(I) Atr=03(Int.) MxPS= 64 Ivl=125us
+E: Ad=0a(O) Atr=03(Int.) MxPS= 64 Ivl=125us
+I: If#= 2 Alt= 1 #EPs= 2 Cls=e0(wlcon) Sub=01 Prot=01 Driver=(none)
+E: Ad=8a(I) Atr=03(Int.) MxPS= 512 Ivl=125us
+E: Ad=0a(O) Atr=03(Int.) MxPS= 512 Ivl=125us
+
+Signed-off-by: Chris Lu <chris.lu@mediatek.com>
+Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/bluetooth/btusb.c | 3 +++
+ 1 file changed, 3 insertions(+)
+
+diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c
+index 3cdb2dea1f559..81a58f3e1db42 100644
+--- a/drivers/bluetooth/btusb.c
++++ b/drivers/bluetooth/btusb.c
+@@ -634,6 +634,9 @@ static const struct usb_device_id blacklist_table[] = {
+ { USB_DEVICE(0x0489, 0xe0f6), .driver_info = BTUSB_MEDIATEK |
+ BTUSB_WIDEBAND_SPEECH |
+ BTUSB_VALID_LE_STATES },
++ { USB_DEVICE(0x0489, 0xe102), .driver_info = BTUSB_MEDIATEK |
++ BTUSB_WIDEBAND_SPEECH |
++ BTUSB_VALID_LE_STATES },
+
+ /* Additional Realtek 8723AE Bluetooth devices */
+ { USB_DEVICE(0x0930, 0x021d), .driver_info = BTUSB_REALTEK },
+--
+2.40.1
+
--- /dev/null
+From 63ef608d69a1203de7644487c7032b202ebf5102 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 7 Jul 2023 14:29:59 +0800
+Subject: Bluetooth: btusb: Add new VID/PID 04ca/3804 for MT7922
+
+From: Chris Lu <chris.lu@mediatek.com>
+
+[ Upstream commit 59be4be82bd3639cd9dbfb92df0f6263ab2c2e28 ]
+
+Add VID 04ca & PID 3804 for MediaTek MT7922 USB Bluetooth chip.
+
+The information in /sys/kernel/debug/usb/devices about the Bluetooth
+device is listed as the below.
+
+T: Bus=05 Lev=01 Prnt=01 Port=00 Cnt=01 Dev#= 2 Spd=480 MxCh= 0
+D: Ver= 2.10 Cls=ef(misc ) Sub=02 Prot=01 MxPS=64 #Cfgs= 1
+P: Vendor=04ca ProdID=3804 Rev= 1.00
+S: Manufacturer=MediaTek Inc.
+S: Product=Wireless_Device
+S: SerialNumber=000000000
+C:* #Ifs= 3 Cfg#= 1 Atr=e0 MxPwr=100mA
+A: FirstIf#= 0 IfCount= 3 Cls=e0(wlcon) Sub=01 Prot=01
+I:* If#= 0 Alt= 0 #EPs= 3 Cls=e0(wlcon) Sub=01 Prot=01 Driver=btusb
+E: Ad=81(I) Atr=03(Int.) MxPS= 16 Ivl=125us
+E: Ad=82(I) Atr=02(Bulk) MxPS= 512 Ivl=0ms
+E: Ad=02(O) Atr=02(Bulk) MxPS= 512 Ivl=0ms
+I:* If#= 1 Alt= 0 #EPs= 2 Cls=e0(wlcon) Sub=01 Prot=01 Driver=btusb
+E: Ad=83(I) Atr=01(Isoc) MxPS= 0 Ivl=1ms
+E: Ad=03(O) Atr=01(Isoc) MxPS= 0 Ivl=1ms
+I: If#= 1 Alt= 1 #EPs= 2 Cls=e0(wlcon) Sub=01 Prot=01 Driver=btusb
+E: Ad=83(I) Atr=01(Isoc) MxPS= 9 Ivl=1ms
+E: Ad=03(O) Atr=01(Isoc) MxPS= 9 Ivl=1ms
+I: If#= 1 Alt= 2 #EPs= 2 Cls=e0(wlcon) Sub=01 Prot=01 Driver=btusb
+E: Ad=83(I) Atr=01(Isoc) MxPS= 17 Ivl=1ms
+E: Ad=03(O) Atr=01(Isoc) MxPS= 17 Ivl=1ms
+I: If#= 1 Alt= 3 #EPs= 2 Cls=e0(wlcon) Sub=01 Prot=01 Driver=btusb
+E: Ad=83(I) Atr=01(Isoc) MxPS= 25 Ivl=1ms
+E: Ad=03(O) Atr=01(Isoc) MxPS= 25 Ivl=1ms
+I: If#= 1 Alt= 4 #EPs= 2 Cls=e0(wlcon) Sub=01 Prot=01 Driver=btusb
+E: Ad=83(I) Atr=01(Isoc) MxPS= 33 Ivl=1ms
+E: Ad=03(O) Atr=01(Isoc) MxPS= 33 Ivl=1ms
+I: If#= 1 Alt= 5 #EPs= 2 Cls=e0(wlcon) Sub=01 Prot=01 Driver=btusb
+E: Ad=83(I) Atr=01(Isoc) MxPS= 49 Ivl=1ms
+E: Ad=03(O) Atr=01(Isoc) MxPS= 49 Ivl=1ms
+I: If#= 1 Alt= 6 #EPs= 2 Cls=e0(wlcon) Sub=01 Prot=01 Driver=btusb
+E: Ad=83(I) Atr=01(Isoc) MxPS= 63 Ivl=1ms
+E: Ad=03(O) Atr=01(Isoc) MxPS= 63 Ivl=1ms
+I:* If#= 2 Alt= 0 #EPs= 2 Cls=e0(wlcon) Sub=01 Prot=01 Driver=(none)
+E: Ad=8a(I) Atr=03(Int.) MxPS= 64 Ivl=125us
+E: Ad=0a(O) Atr=03(Int.) MxPS= 64 Ivl=125us
+I: If#= 2 Alt= 1 #EPs= 2 Cls=e0(wlcon) Sub=01 Prot=01 Driver=(none)
+E: Ad=8a(I) Atr=03(Int.) MxPS= 512 Ivl=125us
+E: Ad=0a(O) Atr=03(Int.) MxPS= 512 Ivl=125us
+
+Signed-off-by: Chris Lu <chris.lu@mediatek.com>
+Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/bluetooth/btusb.c | 3 +++
+ 1 file changed, 3 insertions(+)
+
+diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c
+index 81a58f3e1db42..26203b16ad911 100644
+--- a/drivers/bluetooth/btusb.c
++++ b/drivers/bluetooth/btusb.c
+@@ -637,6 +637,9 @@ static const struct usb_device_id blacklist_table[] = {
+ { USB_DEVICE(0x0489, 0xe102), .driver_info = BTUSB_MEDIATEK |
+ BTUSB_WIDEBAND_SPEECH |
+ BTUSB_VALID_LE_STATES },
++ { USB_DEVICE(0x04ca, 0x3804), .driver_info = BTUSB_MEDIATEK |
++ BTUSB_WIDEBAND_SPEECH |
++ BTUSB_VALID_LE_STATES },
+
+ /* Additional Realtek 8723AE Bluetooth devices */
+ { USB_DEVICE(0x0930, 0x021d), .driver_info = BTUSB_REALTEK },
+--
+2.40.1
+
--- /dev/null
+From 8d2f1e5ecc96d452156c5f87ceefd383fca6d73e Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 12 Jul 2023 22:36:02 +0100
+Subject: Bluetooth: btusb: Add support for another MediaTek 7922 VID/PID
+
+From: Roger Gammans <rgammans@gammascience.co.uk>
+
+[ Upstream commit 0cefdaed944d1617852762ff1f66364199cf5d7d ]
+
+This one is found on the Dell Inspiron 2-in-1 7435
+
+The information in /sys/kernel/debug/usb/devices about the Bluetooth
+device is listed as the below.
+
+T: Bus=03 Lev=01 Prnt=01 Port=02 Cnt=01 Dev#= 2 Spd=480 MxCh= 0
+D: Ver= 2.10 Cls=ef(misc ) Sub=02 Prot=01 MxPS=64 #Cfgs= 1
+P: Vendor=0489 ProdID=e0f1 Rev= 1.00
+S: Manufacturer=MediaTek Inc.
+S: Product=Wireless_Device
+S: SerialNumber=000000000
+C:* #Ifs= 3 Cfg#= 1 Atr=e0 MxPwr=100mA
+A: FirstIf#= 0 IfCount= 3 Cls=e0(wlcon) Sub=01 Prot=01
+I:* If#= 0 Alt= 0 #EPs= 3 Cls=e0(wlcon) Sub=01 Prot=01 Driver=btusb
+E: Ad=81(I) Atr=03(Int.) MxPS= 16 Ivl=125us
+E: Ad=82(I) Atr=02(Bulk) MxPS= 512 Ivl=0ms
+E: Ad=02(O) Atr=02(Bulk) MxPS= 512 Ivl=0ms
+I:* If#= 1 Alt= 0 #EPs= 2 Cls=e0(wlcon) Sub=01 Prot=01 Driver=btusb
+E: Ad=83(I) Atr=01(Isoc) MxPS= 0 Ivl=1ms
+E: Ad=03(O) Atr=01(Isoc) MxPS= 0 Ivl=1ms
+I: If#= 1 Alt= 1 #EPs= 2 Cls=e0(wlcon) Sub=01 Prot=01 Driver=btusb
+E: Ad=83(I) Atr=01(Isoc) MxPS= 9 Ivl=1ms
+E: Ad=03(O) Atr=01(Isoc) MxPS= 9 Ivl=1ms
+I: If#= 1 Alt= 2 #EPs= 2 Cls=e0(wlcon) Sub=01 Prot=01 Driver=btusb
+E: Ad=83(I) Atr=01(Isoc) MxPS= 17 Ivl=1ms
+E: Ad=03(O) Atr=01(Isoc) MxPS= 17 Ivl=1ms
+I: If#= 1 Alt= 3 #EPs= 2 Cls=e0(wlcon) Sub=01 Prot=01 Driver=btusb
+E: Ad=83(I) Atr=01(Isoc) MxPS= 25 Ivl=1ms
+E: Ad=03(O) Atr=01(Isoc) MxPS= 25 Ivl=1ms
+I: If#= 1 Alt= 4 #EPs= 2 Cls=e0(wlcon) Sub=01 Prot=01 Driver=btusb
+E: Ad=83(I) Atr=01(Isoc) MxPS= 33 Ivl=1ms
+E: Ad=03(O) Atr=01(Isoc) MxPS= 33 Ivl=1ms
+I: If#= 1 Alt= 5 #EPs= 2 Cls=e0(wlcon) Sub=01 Prot=01 Driver=btusb
+E: Ad=83(I) Atr=01(Isoc) MxPS= 49 Ivl=1ms
+E: Ad=03(O) Atr=01(Isoc) MxPS= 49 Ivl=1ms
+I: If#= 1 Alt= 6 #EPs= 2 Cls=e0(wlcon) Sub=01 Prot=01 Driver=btusb
+E: Ad=83(I) Atr=01(Isoc) MxPS= 63 Ivl=1ms
+E: Ad=03(O) Atr=01(Isoc) MxPS= 63 Ivl=1ms
+I:* If#= 2 Alt= 0 #EPs= 2 Cls=e0(wlcon) Sub=01 Prot=01 Driver=(none)
+E: Ad=8a(I) Atr=03(Int.) MxPS= 64 Ivl=125us
+E: Ad=0a(O) Atr=03(Int.) MxPS= 64 Ivl=125us
+I: If#= 2 Alt= 1 #EPs= 2 Cls=e0(wlcon) Sub=01 Prot=01 Driver=(none)
+E: Ad=8a(I) Atr=03(Int.) MxPS= 512 Ivl=125us
+E: Ad=0a(O) Atr=03(Int.) MxPS= 512 Ivl=125us
+
+Signed-off-by: Roger Gammans <rgammans@gammascience.co.uk>
+Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/bluetooth/btusb.c | 3 +++
+ 1 file changed, 3 insertions(+)
+
+diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c
+index 26203b16ad911..dfdfb72d350fe 100644
+--- a/drivers/bluetooth/btusb.c
++++ b/drivers/bluetooth/btusb.c
+@@ -625,6 +625,9 @@ static const struct usb_device_id blacklist_table[] = {
+ { USB_DEVICE(0x0489, 0xe0e4), .driver_info = BTUSB_MEDIATEK |
+ BTUSB_WIDEBAND_SPEECH |
+ BTUSB_VALID_LE_STATES },
++ { USB_DEVICE(0x0489, 0xe0f1), .driver_info = BTUSB_MEDIATEK |
++ BTUSB_WIDEBAND_SPEECH |
++ BTUSB_VALID_LE_STATES },
+ { USB_DEVICE(0x0489, 0xe0f2), .driver_info = BTUSB_MEDIATEK |
+ BTUSB_WIDEBAND_SPEECH |
+ BTUSB_VALID_LE_STATES },
+--
+2.40.1
+
--- /dev/null
+From 01191ba045cba26364de1b42ace1f0d7e42d11a7 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 5 Jul 2023 21:06:47 +0000
+Subject: Bluetooth: Fix hci_suspend_sync crash
+
+From: Ying Hsu <yinghsu@chromium.org>
+
+[ Upstream commit 573ebae162111063eedc6c838a659ba628f66a0f ]
+
+If hci_unregister_dev() frees the hci_dev object but hci_suspend_notifier
+may still be accessing it, it can cause the program to crash.
+Here's the call trace:
+ <4>[102152.653246] Call Trace:
+ <4>[102152.653254] hci_suspend_sync+0x109/0x301 [bluetooth]
+ <4>[102152.653259] hci_suspend_dev+0x78/0xcd [bluetooth]
+ <4>[102152.653263] hci_suspend_notifier+0x42/0x7a [bluetooth]
+ <4>[102152.653268] notifier_call_chain+0x43/0x6b
+ <4>[102152.653271] __blocking_notifier_call_chain+0x48/0x69
+ <4>[102152.653273] __pm_notifier_call_chain+0x22/0x39
+ <4>[102152.653276] pm_suspend+0x287/0x57c
+ <4>[102152.653278] state_store+0xae/0xe5
+ <4>[102152.653281] kernfs_fop_write+0x109/0x173
+ <4>[102152.653284] __vfs_write+0x16f/0x1a2
+ <4>[102152.653287] ? selinux_file_permission+0xca/0x16f
+ <4>[102152.653289] ? security_file_permission+0x36/0x109
+ <4>[102152.653291] vfs_write+0x114/0x21d
+ <4>[102152.653293] __x64_sys_write+0x7b/0xdb
+ <4>[102152.653296] do_syscall_64+0x59/0x194
+ <4>[102152.653299] entry_SYSCALL_64_after_hwframe+0x5c/0xc1
+
+This patch holds the reference count of the hci_dev object while
+processing it in hci_suspend_notifier to avoid potential crash
+caused by the race condition.
+
+Signed-off-by: Ying Hsu <yinghsu@chromium.org>
+Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/bluetooth/hci_core.c | 4 ++++
+ 1 file changed, 4 insertions(+)
+
+diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c
+index 2c845c9a26be0..29ae9b254a34e 100644
+--- a/net/bluetooth/hci_core.c
++++ b/net/bluetooth/hci_core.c
+@@ -2436,6 +2436,9 @@ static int hci_suspend_notifier(struct notifier_block *nb, unsigned long action,
+ if (hci_dev_test_flag(hdev, HCI_USER_CHANNEL))
+ return NOTIFY_DONE;
+
++ /* To avoid a potential race with hci_unregister_dev. */
++ hci_dev_hold(hdev);
++
+ if (action == PM_SUSPEND_PREPARE)
+ ret = hci_suspend_dev(hdev);
+ else if (action == PM_POST_SUSPEND)
+@@ -2445,6 +2448,7 @@ static int hci_suspend_notifier(struct notifier_block *nb, unsigned long action,
+ bt_dev_err(hdev, "Suspend notifier action (%lu) failed: %d",
+ action, ret);
+
++ hci_dev_put(hdev);
+ return NOTIFY_DONE;
+ }
+
+--
+2.40.1
+
--- /dev/null
+From 7d407207b328dbc8a991d00aa763a4d583a368b1 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 21 Aug 2023 12:33:09 -0700
+Subject: bpf: Consider non-owning refs to refcounted nodes RCU protected
+
+From: Dave Marchevsky <davemarchevsky@fb.com>
+
+[ Upstream commit 0816b8c6bf7fc87cec4273dc199e8f0764b9e7b1 ]
+
+An earlier patch in the series ensures that the underlying memory of
+nodes with bpf_refcount - which can have multiple owners - is not reused
+until RCU grace period has elapsed. This prevents
+use-after-free with non-owning references that may point to
+recently-freed memory. While RCU read lock is held, it's safe to
+dereference such a non-owning ref, as by definition RCU GP couldn't have
+elapsed and therefore underlying memory couldn't have been reused.
+
+From the perspective of verifier "trustedness" non-owning refs to
+refcounted nodes are now trusted only in RCU CS and therefore should no
+longer pass is_trusted_reg, but rather is_rcu_reg. Let's mark them
+MEM_RCU in order to reflect this new state.
+
+Signed-off-by: Dave Marchevsky <davemarchevsky@fb.com>
+Link: https://lore.kernel.org/r/20230821193311.3290257-6-davemarchevsky@fb.com
+Signed-off-by: Alexei Starovoitov <ast@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ include/linux/bpf.h | 3 ++-
+ kernel/bpf/verifier.c | 13 ++++++++++++-
+ 2 files changed, 14 insertions(+), 2 deletions(-)
+
+diff --git a/include/linux/bpf.h b/include/linux/bpf.h
+index f316affcd2e13..28e2e0ce2ed07 100644
+--- a/include/linux/bpf.h
++++ b/include/linux/bpf.h
+@@ -640,7 +640,8 @@ enum bpf_type_flag {
+ MEM_RCU = BIT(13 + BPF_BASE_TYPE_BITS),
+
+ /* Used to tag PTR_TO_BTF_ID | MEM_ALLOC references which are non-owning.
+- * Currently only valid for linked-list and rbtree nodes.
++ * Currently only valid for linked-list and rbtree nodes. If the nodes
++ * have a bpf_refcount_field, they must be tagged MEM_RCU as well.
+ */
+ NON_OWN_REF = BIT(14 + BPF_BASE_TYPE_BITS),
+
+diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c
+index 76845dd22cd26..9cdba4ce23d2b 100644
+--- a/kernel/bpf/verifier.c
++++ b/kernel/bpf/verifier.c
+@@ -7841,6 +7841,7 @@ int check_func_arg_reg_off(struct bpf_verifier_env *env,
+ case PTR_TO_BTF_ID | PTR_TRUSTED:
+ case PTR_TO_BTF_ID | MEM_RCU:
+ case PTR_TO_BTF_ID | MEM_ALLOC | NON_OWN_REF:
++ case PTR_TO_BTF_ID | MEM_ALLOC | NON_OWN_REF | MEM_RCU:
+ /* When referenced PTR_TO_BTF_ID is passed to release function,
+ * its fixed offset must be 0. In the other cases, fixed offset
+ * can be non-zero. This was already checked above. So pass
+@@ -10302,6 +10303,7 @@ static int process_kf_arg_ptr_to_btf_id(struct bpf_verifier_env *env,
+ static int ref_set_non_owning(struct bpf_verifier_env *env, struct bpf_reg_state *reg)
+ {
+ struct bpf_verifier_state *state = env->cur_state;
++ struct btf_record *rec = reg_btf_record(reg);
+
+ if (!state->active_lock.ptr) {
+ verbose(env, "verifier internal error: ref_set_non_owning w/o active lock\n");
+@@ -10314,6 +10316,9 @@ static int ref_set_non_owning(struct bpf_verifier_env *env, struct bpf_reg_state
+ }
+
+ reg->type |= NON_OWN_REF;
++ if (rec->refcount_off >= 0)
++ reg->type |= MEM_RCU;
++
+ return 0;
+ }
+
+@@ -11154,6 +11159,11 @@ static int check_kfunc_call(struct bpf_verifier_env *env, struct bpf_insn *insn,
+ struct bpf_func_state *state;
+ struct bpf_reg_state *reg;
+
++ if (in_rbtree_lock_required_cb(env) && (rcu_lock || rcu_unlock)) {
++ verbose(env, "Calling bpf_rcu_read_{lock,unlock} in unnecessary rbtree callback\n");
++ return -EACCES;
++ }
++
+ if (rcu_lock) {
+ verbose(env, "nested rcu read lock (kernel function %s)\n", func_name);
+ return -EINVAL;
+@@ -16453,7 +16463,8 @@ static int do_check(struct bpf_verifier_env *env)
+ return -EINVAL;
+ }
+
+- if (env->cur_state->active_rcu_lock) {
++ if (env->cur_state->active_rcu_lock &&
++ !in_rbtree_lock_required_cb(env)) {
+ verbose(env, "bpf_rcu_read_unlock is missing\n");
+ return -EINVAL;
+ }
+--
+2.40.1
+
--- /dev/null
+From edf42ff1b974487da39b94b4287ffcd252589250 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 21 Aug 2023 12:33:06 -0700
+Subject: bpf: Consider non-owning refs trusted
+
+From: Dave Marchevsky <davemarchevsky@fb.com>
+
+[ Upstream commit 2a6d50b50d6d589d43a90d6ca990b8b811e67701 ]
+
+Recent discussions around default kptr "trustedness" led to changes such
+as commit 6fcd486b3a0a ("bpf: Refactor RCU enforcement in the
+verifier."). One of the conclusions of those discussions, as expressed
+in code and comments in that patch, is that we'd like to move away from
+'raw' PTR_TO_BTF_ID without some type flag or other register state
+indicating trustedness. Although PTR_TRUSTED and PTR_UNTRUSTED flags mark
+this state explicitly, the verifier currently considers trustedness
+implied by other register state. For example, owning refs to graph
+collection nodes must have a nonzero ref_obj_id, so they pass the
+is_trusted_reg check despite having no explicit PTR_{UN}TRUSTED flag.
+This patch makes trustedness of non-owning refs to graph collection
+nodes explicit as well.
+
+By definition, non-owning refs are currently trusted. Although the ref
+has no control over pointee lifetime, due to non-owning ref clobbering
+rules (see invalidate_non_owning_refs) dereferencing a non-owning ref is
+safe in the critical section controlled by bpf_spin_lock associated with
+its owning collection.
+
+Note that the previous statement does not hold true for nodes with shared
+ownership due to the use-after-free issue that this series is
+addressing. True shared ownership was disabled by commit 7deca5eae833
+("bpf: Disable bpf_refcount_acquire kfunc calls until race conditions are fixed"),
+though, so the statement holds for now. Further patches in the series will change
+the trustedness state of non-owning refs before re-enabling
+bpf_refcount_acquire.
+
+Let's add NON_OWN_REF type flag to BPF_REG_TRUSTED_MODIFIERS such that a
+non-owning ref reg state would pass is_trusted_reg check. Somewhat
+surprisingly, this doesn't result in any change to user-visible
+functionality elsewhere in the verifier: graph collection nodes are all
+marked MEM_ALLOC, which tends to be handled in separate codepaths from
+"raw" PTR_TO_BTF_ID. Regardless, let's be explicit here and document the
+current state of things before changing it elsewhere in the series.
+
+Signed-off-by: Dave Marchevsky <davemarchevsky@fb.com>
+Acked-by: Yonghong Song <yonghong.song@linux.dev>
+Link: https://lore.kernel.org/r/20230821193311.3290257-3-davemarchevsky@fb.com
+Signed-off-by: Alexei Starovoitov <ast@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ include/linux/bpf_verifier.h | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/include/linux/bpf_verifier.h b/include/linux/bpf_verifier.h
+index f70f9ac884d24..b6e58dab8e275 100644
+--- a/include/linux/bpf_verifier.h
++++ b/include/linux/bpf_verifier.h
+@@ -745,7 +745,7 @@ static inline bool bpf_prog_check_recur(const struct bpf_prog *prog)
+ }
+ }
+
+-#define BPF_REG_TRUSTED_MODIFIERS (MEM_ALLOC | PTR_TRUSTED)
++#define BPF_REG_TRUSTED_MODIFIERS (MEM_ALLOC | PTR_TRUSTED | NON_OWN_REF)
+
+ static inline bool bpf_type_has_unsafe_modifiers(u32 type)
+ {
+--
+2.40.1
+
--- /dev/null
+From d51f341460f11bb99cd5bb33abbc865e4e582859 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 31 Jul 2023 19:16:32 +0800
+Subject: btrfs: add a helper to read the superblock metadata_uuid
+
+From: Anand Jain <anand.jain@oracle.com>
+
+[ Upstream commit 4844c3664a72d36cc79752cb651c78860b14c240 ]
+
+In some cases, we need to read the FSID from the superblock when the
+metadata_uuid is not set, and otherwise, read the metadata_uuid. So,
+add a helper.
+
+Reviewed-by: Johannes Thumshirn <johannes.thumshirn@wdc.com>
+Tested-by: Guilherme G. Piccoli <gpiccoli@igalia.com>
+Signed-off-by: Anand Jain <anand.jain@oracle.com>
+Reviewed-by: David Sterba <dsterba@suse.com>
+Signed-off-by: David Sterba <dsterba@suse.com>
+Stable-dep-of: 6bfe3959b0e7 ("btrfs: compare the correct fsid/metadata_uuid in btrfs_validate_super")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ fs/btrfs/volumes.c | 8 ++++++++
+ fs/btrfs/volumes.h | 1 +
+ 2 files changed, 9 insertions(+)
+
+diff --git a/fs/btrfs/volumes.c b/fs/btrfs/volumes.c
+index 6aa9bf3661ac8..51070c0d4141e 100644
+--- a/fs/btrfs/volumes.c
++++ b/fs/btrfs/volumes.c
+@@ -681,6 +681,14 @@ static int btrfs_open_one_device(struct btrfs_fs_devices *fs_devices,
+ return -EINVAL;
+ }
+
++u8 *btrfs_sb_fsid_ptr(struct btrfs_super_block *sb)
++{
++ bool has_metadata_uuid = (btrfs_super_incompat_flags(sb) &
++ BTRFS_FEATURE_INCOMPAT_METADATA_UUID);
++
++ return has_metadata_uuid ? sb->metadata_uuid : sb->fsid;
++}
++
+ /*
+ * Handle scanned device having its CHANGING_FSID_V2 flag set and the fs_devices
+ * being created with a disk that has already completed its fsid change. Such
+diff --git a/fs/btrfs/volumes.h b/fs/btrfs/volumes.h
+index b8c51f16ba867..0f87057bb575f 100644
+--- a/fs/btrfs/volumes.h
++++ b/fs/btrfs/volumes.h
+@@ -749,5 +749,6 @@ int btrfs_verify_dev_extents(struct btrfs_fs_info *fs_info);
+ bool btrfs_repair_one_zone(struct btrfs_fs_info *fs_info, u64 logical);
+
+ bool btrfs_pinned_by_swapfile(struct btrfs_fs_info *fs_info, void *ptr);
++u8 *btrfs_sb_fsid_ptr(struct btrfs_super_block *sb);
+
+ #endif
+--
+2.40.1
+
--- /dev/null
+From b78d7b64beb89e103958ac4b4d61c20470e03f1f Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 31 Jul 2023 19:16:35 +0800
+Subject: btrfs: compare the correct fsid/metadata_uuid in btrfs_validate_super
+
+From: Anand Jain <anand.jain@oracle.com>
+
+[ Upstream commit 6bfe3959b0e7a526f5c64747801a8613f002f05a ]
+
+The function btrfs_validate_super() should verify the metadata_uuid in
+the provided superblock argument. Because, all its callers expect it to
+do that.
+
+Such as in the following stacks:
+
+ write_all_supers()
+ sb = fs_info->super_for_commit;
+ btrfs_validate_write_super(.., sb)
+ btrfs_validate_super(.., sb, ..)
+
+ scrub_one_super()
+ btrfs_validate_super(.., sb, ..)
+
+And
+ check_dev_super()
+ btrfs_validate_super(.., sb, ..)
+
+However, it currently verifies the fs_info::super_copy::metadata_uuid
+instead. Fix this using the correct metadata_uuid in the superblock
+argument.
+
+CC: stable@vger.kernel.org # 5.4+
+Reviewed-by: Johannes Thumshirn <johannes.thumshirn@wdc.com>
+Tested-by: Guilherme G. Piccoli <gpiccoli@igalia.com>
+Signed-off-by: Anand Jain <anand.jain@oracle.com>
+Reviewed-by: David Sterba <dsterba@suse.com>
+Signed-off-by: David Sterba <dsterba@suse.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ fs/btrfs/disk-io.c | 8 +++-----
+ 1 file changed, 3 insertions(+), 5 deletions(-)
+
+diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c
+index 4494883a19abc..0593f8f458a6e 100644
+--- a/fs/btrfs/disk-io.c
++++ b/fs/btrfs/disk-io.c
+@@ -2391,13 +2391,11 @@ int btrfs_validate_super(struct btrfs_fs_info *fs_info,
+ ret = -EINVAL;
+ }
+
+- if (btrfs_fs_incompat(fs_info, METADATA_UUID) &&
+- memcmp(fs_info->fs_devices->metadata_uuid,
+- fs_info->super_copy->metadata_uuid, BTRFS_FSID_SIZE)) {
++ if (memcmp(fs_info->fs_devices->metadata_uuid, btrfs_sb_fsid_ptr(sb),
++ BTRFS_FSID_SIZE) != 0) {
+ btrfs_err(fs_info,
+ "superblock metadata_uuid doesn't match metadata uuid of fs_devices: %pU != %pU",
+- fs_info->super_copy->metadata_uuid,
+- fs_info->fs_devices->metadata_uuid);
++ btrfs_sb_fsid_ptr(sb), fs_info->fs_devices->metadata_uuid);
+ ret = -EINVAL;
+ }
+
+--
+2.40.1
+
--- /dev/null
+From 3f125860f5144bcab7ac817a61fc5bae1806855a Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 9 Aug 2023 15:08:21 +0800
+Subject: btrfs: handle errors properly in update_inline_extent_backref()
+
+From: Qu Wenruo <wqu@suse.com>
+
+[ Upstream commit 257614301a5db9f7b0548584ca207ad7785c8b89 ]
+
+[PROBLEM]
+Inside function update_inline_extent_backref(), we have several
+BUG_ON()s along with some ASSERT()s which can be triggered by corrupted
+filesystem.
+
+[ANAYLYSE]
+Most of those BUG_ON()s and ASSERT()s are just a way of handling
+unexpected on-disk data.
+
+Although we have tree-checker to rule out obviously incorrect extent
+tree blocks, it's not enough for these ones. Thus we need proper error
+handling for them.
+
+[FIX]
+Thankfully all the callers of update_inline_extent_backref() would
+eventually handle the errror by aborting the current transaction.
+So this patch would do the proper error handling by:
+
+- Make update_inline_extent_backref() to return int
+ The return value would be either 0 or -EUCLEAN.
+
+- Replace BUG_ON()s and ASSERT()s with proper error handling
+ This includes:
+ * Dump the bad extent tree leaf
+ * Output an error message for the cause
+ This would include the extent bytenr, num_bytes (if needed), the bad
+ values and expected good values.
+ * Return -EUCLEAN
+
+ Note here we remove all the WARN_ON()s, as eventually the transaction
+ would be aborted, thus a backtrace would be triggered anyway.
+
+- Better comments on why we expect refs == 1 and refs_to_mode == -1 for
+ tree blocks
+
+Reviewed-by: Josef Bacik <josef@toxicpanda.com>
+Signed-off-by: Qu Wenruo <wqu@suse.com>
+Reviewed-by: David Sterba <dsterba@suse.com>
+Signed-off-by: David Sterba <dsterba@suse.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ fs/btrfs/extent-tree.c | 73 +++++++++++++++++++++++++++++++++++-------
+ 1 file changed, 61 insertions(+), 12 deletions(-)
+
+diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c
+index e5566827da17e..c47fbb99e99d9 100644
+--- a/fs/btrfs/extent-tree.c
++++ b/fs/btrfs/extent-tree.c
+@@ -402,11 +402,11 @@ int btrfs_get_extent_inline_ref_type(const struct extent_buffer *eb,
+ }
+ }
+
++ WARN_ON(1);
+ btrfs_print_leaf(eb);
+ btrfs_err(eb->fs_info,
+ "eb %llu iref 0x%lx invalid extent inline ref type %d",
+ eb->start, (unsigned long)iref, type);
+- WARN_ON(1);
+
+ return BTRFS_REF_TYPE_INVALID;
+ }
+@@ -1079,13 +1079,13 @@ static int lookup_extent_backref(struct btrfs_trans_handle *trans,
+ /*
+ * helper to update/remove inline back ref
+ */
+-static noinline_for_stack
+-void update_inline_extent_backref(struct btrfs_path *path,
++static noinline_for_stack int update_inline_extent_backref(struct btrfs_path *path,
+ struct btrfs_extent_inline_ref *iref,
+ int refs_to_mod,
+ struct btrfs_delayed_extent_op *extent_op)
+ {
+ struct extent_buffer *leaf = path->nodes[0];
++ struct btrfs_fs_info *fs_info = leaf->fs_info;
+ struct btrfs_extent_item *ei;
+ struct btrfs_extent_data_ref *dref = NULL;
+ struct btrfs_shared_data_ref *sref = NULL;
+@@ -1098,18 +1098,33 @@ void update_inline_extent_backref(struct btrfs_path *path,
+
+ ei = btrfs_item_ptr(leaf, path->slots[0], struct btrfs_extent_item);
+ refs = btrfs_extent_refs(leaf, ei);
+- WARN_ON(refs_to_mod < 0 && refs + refs_to_mod <= 0);
++ if (unlikely(refs_to_mod < 0 && refs + refs_to_mod <= 0)) {
++ struct btrfs_key key;
++ u32 extent_size;
++
++ btrfs_item_key_to_cpu(leaf, &key, path->slots[0]);
++ if (key.type == BTRFS_METADATA_ITEM_KEY)
++ extent_size = fs_info->nodesize;
++ else
++ extent_size = key.offset;
++ btrfs_print_leaf(leaf);
++ btrfs_err(fs_info,
++ "invalid refs_to_mod for extent %llu num_bytes %u, has %d expect >= -%llu",
++ key.objectid, extent_size, refs_to_mod, refs);
++ return -EUCLEAN;
++ }
+ refs += refs_to_mod;
+ btrfs_set_extent_refs(leaf, ei, refs);
+ if (extent_op)
+ __run_delayed_extent_op(extent_op, leaf, ei);
+
++ type = btrfs_get_extent_inline_ref_type(leaf, iref, BTRFS_REF_TYPE_ANY);
+ /*
+- * If type is invalid, we should have bailed out after
+- * lookup_inline_extent_backref().
++ * Function btrfs_get_extent_inline_ref_type() has already printed
++ * error messages.
+ */
+- type = btrfs_get_extent_inline_ref_type(leaf, iref, BTRFS_REF_TYPE_ANY);
+- ASSERT(type != BTRFS_REF_TYPE_INVALID);
++ if (unlikely(type == BTRFS_REF_TYPE_INVALID))
++ return -EUCLEAN;
+
+ if (type == BTRFS_EXTENT_DATA_REF_KEY) {
+ dref = (struct btrfs_extent_data_ref *)(&iref->offset);
+@@ -1119,10 +1134,43 @@ void update_inline_extent_backref(struct btrfs_path *path,
+ refs = btrfs_shared_data_ref_count(leaf, sref);
+ } else {
+ refs = 1;
+- BUG_ON(refs_to_mod != -1);
++ /*
++ * For tree blocks we can only drop one ref for it, and tree
++ * blocks should not have refs > 1.
++ *
++ * Furthermore if we're inserting a new inline backref, we
++ * won't reach this path either. That would be
++ * setup_inline_extent_backref().
++ */
++ if (unlikely(refs_to_mod != -1)) {
++ struct btrfs_key key;
++
++ btrfs_item_key_to_cpu(leaf, &key, path->slots[0]);
++
++ btrfs_print_leaf(leaf);
++ btrfs_err(fs_info,
++ "invalid refs_to_mod for tree block %llu, has %d expect -1",
++ key.objectid, refs_to_mod);
++ return -EUCLEAN;
++ }
+ }
+
+- BUG_ON(refs_to_mod < 0 && refs < -refs_to_mod);
++ if (unlikely(refs_to_mod < 0 && refs < -refs_to_mod)) {
++ struct btrfs_key key;
++ u32 extent_size;
++
++ btrfs_item_key_to_cpu(leaf, &key, path->slots[0]);
++ if (key.type == BTRFS_METADATA_ITEM_KEY)
++ extent_size = fs_info->nodesize;
++ else
++ extent_size = key.offset;
++ btrfs_print_leaf(leaf);
++ btrfs_err(fs_info,
++"invalid refs_to_mod for backref entry, iref %lu extent %llu num_bytes %u, has %d expect >= -%llu",
++ (unsigned long)iref, key.objectid, extent_size,
++ refs_to_mod, refs);
++ return -EUCLEAN;
++ }
+ refs += refs_to_mod;
+
+ if (refs > 0) {
+@@ -1142,6 +1190,7 @@ void update_inline_extent_backref(struct btrfs_path *path,
+ btrfs_truncate_item(path, item_size, 1);
+ }
+ btrfs_mark_buffer_dirty(leaf);
++ return 0;
+ }
+
+ static noinline_for_stack
+@@ -1170,7 +1219,7 @@ int insert_inline_extent_backref(struct btrfs_trans_handle *trans,
+ bytenr, num_bytes, root_objectid, path->slots[0]);
+ return -EUCLEAN;
+ }
+- update_inline_extent_backref(path, iref, refs_to_add, extent_op);
++ ret = update_inline_extent_backref(path, iref, refs_to_add, extent_op);
+ } else if (ret == -ENOENT) {
+ setup_inline_extent_backref(trans->fs_info, path, iref, parent,
+ root_objectid, owner, offset,
+@@ -1190,7 +1239,7 @@ static int remove_extent_backref(struct btrfs_trans_handle *trans,
+
+ BUG_ON(!is_data && refs_to_drop != 1);
+ if (iref)
+- update_inline_extent_backref(path, iref, -refs_to_drop, NULL);
++ ret = update_inline_extent_backref(path, iref, -refs_to_drop, NULL);
+ else if (is_data)
+ ret = remove_extent_data_ref(trans, root, path, refs_to_drop);
+ else
+--
+2.40.1
+
--- /dev/null
+From 3021d0d6437a85e3510bf2c79c3051a43b904019 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 8 Aug 2023 01:12:31 +0900
+Subject: btrfs: introduce struct to consolidate extent buffer write context
+
+From: Naohiro Aota <naohiro.aota@wdc.com>
+
+[ Upstream commit 861093eff4f01319edfc1d1ee276a7f2bf720f1d ]
+
+Introduce btrfs_eb_write_context to consolidate writeback_control and the
+exntent buffer context. This will help adding a block group context as
+well.
+
+While at it, move the eb context setting before
+btrfs_check_meta_write_pointer(). We can set it here because we anyway need
+to skip pages in the same eb if that eb is rejected by
+btrfs_check_meta_write_pointer().
+
+Suggested-by: Christoph Hellwig <hch@infradead.org>
+Reviewed-by: Christoph Hellwig <hch@lst.de>
+Reviewed-by: Johannes Thumshirn <johannes.thumshirn@wdc.com>
+Signed-off-by: Naohiro Aota <naohiro.aota@wdc.com>
+Reviewed-by: David Sterba <dsterba@suse.com>
+Signed-off-by: David Sterba <dsterba@suse.com>
+Stable-dep-of: 13bb483d32ab ("btrfs: zoned: activate metadata block group on write time")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ fs/btrfs/extent_io.c | 14 +++++++-------
+ fs/btrfs/extent_io.h | 5 +++++
+ 2 files changed, 12 insertions(+), 7 deletions(-)
+
+diff --git a/fs/btrfs/extent_io.c b/fs/btrfs/extent_io.c
+index 90ad3006ef3a7..b3bf2e2704888 100644
+--- a/fs/btrfs/extent_io.c
++++ b/fs/btrfs/extent_io.c
+@@ -1877,9 +1877,9 @@ static int submit_eb_subpage(struct page *page, struct writeback_control *wbc)
+ * previous call.
+ * Return <0 for fatal error.
+ */
+-static int submit_eb_page(struct page *page, struct writeback_control *wbc,
+- struct extent_buffer **eb_context)
++static int submit_eb_page(struct page *page, struct btrfs_eb_write_context *ctx)
+ {
++ struct writeback_control *wbc = ctx->wbc;
+ struct address_space *mapping = page->mapping;
+ struct btrfs_block_group *cache = NULL;
+ struct extent_buffer *eb;
+@@ -1908,7 +1908,7 @@ static int submit_eb_page(struct page *page, struct writeback_control *wbc,
+ return 0;
+ }
+
+- if (eb == *eb_context) {
++ if (eb == ctx->eb) {
+ spin_unlock(&mapping->private_lock);
+ return 0;
+ }
+@@ -1917,6 +1917,8 @@ static int submit_eb_page(struct page *page, struct writeback_control *wbc,
+ if (!ret)
+ return 0;
+
++ ctx->eb = eb;
++
+ if (!btrfs_check_meta_write_pointer(eb->fs_info, eb, &cache)) {
+ /*
+ * If for_sync, this hole will be filled with
+@@ -1930,8 +1932,6 @@ static int submit_eb_page(struct page *page, struct writeback_control *wbc,
+ return ret;
+ }
+
+- *eb_context = eb;
+-
+ if (!lock_extent_buffer_for_io(eb, wbc)) {
+ btrfs_revert_meta_write_pointer(cache, eb);
+ if (cache)
+@@ -1954,7 +1954,7 @@ static int submit_eb_page(struct page *page, struct writeback_control *wbc,
+ int btree_write_cache_pages(struct address_space *mapping,
+ struct writeback_control *wbc)
+ {
+- struct extent_buffer *eb_context = NULL;
++ struct btrfs_eb_write_context ctx = { .wbc = wbc };
+ struct btrfs_fs_info *fs_info = BTRFS_I(mapping->host)->root->fs_info;
+ int ret = 0;
+ int done = 0;
+@@ -1996,7 +1996,7 @@ int btree_write_cache_pages(struct address_space *mapping,
+ for (i = 0; i < nr_folios; i++) {
+ struct folio *folio = fbatch.folios[i];
+
+- ret = submit_eb_page(&folio->page, wbc, &eb_context);
++ ret = submit_eb_page(&folio->page, &ctx);
+ if (ret == 0)
+ continue;
+ if (ret < 0) {
+diff --git a/fs/btrfs/extent_io.h b/fs/btrfs/extent_io.h
+index c5fae3a7d911b..ecc1660007c11 100644
+--- a/fs/btrfs/extent_io.h
++++ b/fs/btrfs/extent_io.h
+@@ -94,6 +94,11 @@ struct extent_buffer {
+ #endif
+ };
+
++struct btrfs_eb_write_context {
++ struct writeback_control *wbc;
++ struct extent_buffer *eb;
++};
++
+ /*
+ * Get the correct offset inside the page of extent buffer.
+ *
+--
+2.40.1
+
--- /dev/null
+From bdb73444dfe4f9e25201328d85d0da9939ccce6a Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 1 Aug 2023 19:02:28 +0800
+Subject: btrfs: output extra debug info if we failed to find an inline backref
+
+From: Qu Wenruo <wqu@suse.com>
+
+[ Upstream commit 7f72f50547b7af4ddf985b07fc56600a4deba281 ]
+
+[BUG]
+Syzbot reported several warning triggered inside
+lookup_inline_extent_backref().
+
+[CAUSE]
+As usual, the reproducer doesn't reliably trigger locally here, but at
+least we know the WARN_ON() is triggered when an inline backref can not
+be found, and it can only be triggered when @insert is true. (I.e.
+inserting a new inline backref, which means the backref should already
+exist)
+
+[ENHANCEMENT]
+After the WARN_ON(), dump all the parameters and the extent tree
+leaf to help debug.
+
+Link: https://syzkaller.appspot.com/bug?extid=d6f9ff86c1d804ba2bc6
+Signed-off-by: Qu Wenruo <wqu@suse.com>
+Reviewed-by: David Sterba <dsterba@suse.com>
+Signed-off-by: David Sterba <dsterba@suse.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ fs/btrfs/extent-tree.c | 5 +++++
+ 1 file changed, 5 insertions(+)
+
+diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c
+index c47fbb99e99d9..0917c5f39e3d0 100644
+--- a/fs/btrfs/extent-tree.c
++++ b/fs/btrfs/extent-tree.c
+@@ -869,6 +869,11 @@ int lookup_inline_extent_backref(struct btrfs_trans_handle *trans,
+ err = -ENOENT;
+ goto out;
+ } else if (WARN_ON(ret)) {
++ btrfs_print_leaf(path->nodes[0]);
++ btrfs_err(fs_info,
++"extent item not found for insert, bytenr %llu num_bytes %llu parent %llu root_objectid %llu owner %llu offset %llu",
++ bytenr, num_bytes, parent, root_objectid, owner,
++ offset);
+ err = -EIO;
+ goto out;
+ }
+--
+2.40.1
+
--- /dev/null
+From e0f9d17b787d1fae190f05f699ba6a4907ac6b2e Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 8 Aug 2023 01:12:37 +0900
+Subject: btrfs: zoned: activate metadata block group on write time
+
+From: Naohiro Aota <naohiro.aota@wdc.com>
+
+[ Upstream commit 13bb483d32abb6f8ebd40141d87eb68f11cc2dd2 ]
+
+In the current implementation, block groups are activated at reservation
+time to ensure that all reserved bytes can be written to an active metadata
+block group. However, this approach has proven to be less efficient, as it
+activates block groups more frequently than necessary, putting pressure on
+the active zone resource and leading to potential issues such as early
+ENOSPC or hung_task.
+
+Another drawback of the current method is that it hampers metadata
+over-commit, and necessitates additional flush operations and block group
+allocations, resulting in decreased overall performance.
+
+To address these issues, this commit introduces a write-time activation of
+metadata and system block group. This involves reserving at least one
+active block group specifically for a metadata and system block group.
+
+Since metadata write-out is always allocated sequentially, when we need to
+write to a non-active block group, we can wait for the ongoing IOs to
+complete, activate a new block group, and then proceed with writing to the
+new block group.
+
+Fixes: b09315139136 ("btrfs: zoned: activate metadata block group on flush_space")
+CC: stable@vger.kernel.org # 6.1+
+Signed-off-by: Naohiro Aota <naohiro.aota@wdc.com>
+Signed-off-by: David Sterba <dsterba@suse.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ fs/btrfs/block-group.c | 11 ++++++
+ fs/btrfs/fs.h | 3 ++
+ fs/btrfs/zoned.c | 81 ++++++++++++++++++++++++++++++++++++++++--
+ 3 files changed, 93 insertions(+), 2 deletions(-)
+
+diff --git a/fs/btrfs/block-group.c b/fs/btrfs/block-group.c
+index 82324c327a502..75385503a35b6 100644
+--- a/fs/btrfs/block-group.c
++++ b/fs/btrfs/block-group.c
+@@ -4273,6 +4273,17 @@ int btrfs_free_block_groups(struct btrfs_fs_info *info)
+ struct btrfs_caching_control *caching_ctl;
+ struct rb_node *n;
+
++ if (btrfs_is_zoned(info)) {
++ if (info->active_meta_bg) {
++ btrfs_put_block_group(info->active_meta_bg);
++ info->active_meta_bg = NULL;
++ }
++ if (info->active_system_bg) {
++ btrfs_put_block_group(info->active_system_bg);
++ info->active_system_bg = NULL;
++ }
++ }
++
+ write_lock(&info->block_group_cache_lock);
+ while (!list_empty(&info->caching_block_groups)) {
+ caching_ctl = list_entry(info->caching_block_groups.next,
+diff --git a/fs/btrfs/fs.h b/fs/btrfs/fs.h
+index 203d2a2678287..1f2d331121064 100644
+--- a/fs/btrfs/fs.h
++++ b/fs/btrfs/fs.h
+@@ -766,6 +766,9 @@ struct btrfs_fs_info {
+ u64 data_reloc_bg;
+ struct mutex zoned_data_reloc_io_lock;
+
++ struct btrfs_block_group *active_meta_bg;
++ struct btrfs_block_group *active_system_bg;
++
+ u64 nr_global_roots;
+
+ spinlock_t zone_active_bgs_lock;
+diff --git a/fs/btrfs/zoned.c b/fs/btrfs/zoned.c
+index cc117283d0c88..f97e927499d7a 100644
+--- a/fs/btrfs/zoned.c
++++ b/fs/btrfs/zoned.c
+@@ -65,6 +65,9 @@
+
+ #define SUPER_INFO_SECTORS ((u64)BTRFS_SUPER_INFO_SIZE >> SECTOR_SHIFT)
+
++static void wait_eb_writebacks(struct btrfs_block_group *block_group);
++static int do_zone_finish(struct btrfs_block_group *block_group, bool fully_written);
++
+ static inline bool sb_zone_is_full(const struct blk_zone *zone)
+ {
+ return (zone->cond == BLK_ZONE_COND_FULL) ||
+@@ -1758,6 +1761,62 @@ void btrfs_finish_ordered_zoned(struct btrfs_ordered_extent *ordered)
+ }
+ }
+
++static bool check_bg_is_active(struct btrfs_eb_write_context *ctx,
++ struct btrfs_block_group **active_bg)
++{
++ const struct writeback_control *wbc = ctx->wbc;
++ struct btrfs_block_group *block_group = ctx->zoned_bg;
++ struct btrfs_fs_info *fs_info = block_group->fs_info;
++
++ if (test_bit(BLOCK_GROUP_FLAG_ZONE_IS_ACTIVE, &block_group->runtime_flags))
++ return true;
++
++ if (fs_info->treelog_bg == block_group->start) {
++ if (!btrfs_zone_activate(block_group)) {
++ int ret_fin = btrfs_zone_finish_one_bg(fs_info);
++
++ if (ret_fin != 1 || !btrfs_zone_activate(block_group))
++ return false;
++ }
++ } else if (*active_bg != block_group) {
++ struct btrfs_block_group *tgt = *active_bg;
++
++ /* zoned_meta_io_lock protects fs_info->active_{meta,system}_bg. */
++ lockdep_assert_held(&fs_info->zoned_meta_io_lock);
++
++ if (tgt) {
++ /*
++ * If there is an unsent IO left in the allocated area,
++ * we cannot wait for them as it may cause a deadlock.
++ */
++ if (tgt->meta_write_pointer < tgt->start + tgt->alloc_offset) {
++ if (wbc->sync_mode == WB_SYNC_NONE ||
++ (wbc->sync_mode == WB_SYNC_ALL && !wbc->for_sync))
++ return false;
++ }
++
++ /* Pivot active metadata/system block group. */
++ btrfs_zoned_meta_io_unlock(fs_info);
++ wait_eb_writebacks(tgt);
++ do_zone_finish(tgt, true);
++ btrfs_zoned_meta_io_lock(fs_info);
++ if (*active_bg == tgt) {
++ btrfs_put_block_group(tgt);
++ *active_bg = NULL;
++ }
++ }
++ if (!btrfs_zone_activate(block_group))
++ return false;
++ if (*active_bg != block_group) {
++ ASSERT(*active_bg == NULL);
++ *active_bg = block_group;
++ btrfs_get_block_group(block_group);
++ }
++ }
++
++ return true;
++}
++
+ /*
+ * Check if @ctx->eb is aligned to the write pointer.
+ *
+@@ -1792,8 +1851,26 @@ int btrfs_check_meta_write_pointer(struct btrfs_fs_info *fs_info,
+ ctx->zoned_bg = block_group;
+ }
+
+- if (block_group->meta_write_pointer == eb->start)
+- return 0;
++ if (block_group->meta_write_pointer == eb->start) {
++ struct btrfs_block_group **tgt;
++
++ if (!test_bit(BTRFS_FS_ACTIVE_ZONE_TRACKING, &fs_info->flags))
++ return 0;
++
++ if (block_group->flags & BTRFS_BLOCK_GROUP_SYSTEM)
++ tgt = &fs_info->active_system_bg;
++ else
++ tgt = &fs_info->active_meta_bg;
++ if (check_bg_is_active(ctx, tgt))
++ return 0;
++ }
++
++ /*
++ * Since we may release fs_info->zoned_meta_io_lock, someone can already
++ * start writing this eb. In that case, we can just bail out.
++ */
++ if (block_group->meta_write_pointer > eb->start)
++ return -EBUSY;
+
+ /* If for_sync, this hole will be filled with trasnsaction commit. */
+ if (wbc->sync_mode == WB_SYNC_ALL && !wbc->for_sync)
+--
+2.40.1
+
--- /dev/null
+From 6788945b73431a1e3dc65d7ae4e2e75614827987 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 8 Aug 2023 01:12:34 +0900
+Subject: btrfs: zoned: defer advancing meta write pointer
+
+From: Naohiro Aota <naohiro.aota@wdc.com>
+
+[ Upstream commit 0356ad41e0ddb8cf0ea4d68820c92598413e445b ]
+
+We currently advance the meta_write_pointer in
+btrfs_check_meta_write_pointer(). That makes it necessary to revert it
+when locking the buffer failed. Instead, we can advance it just before
+sending the buffer.
+
+Also, this is necessary for the following commit. In the commit, it needs
+to release the zoned_meta_io_lock to allow IOs to come in and wait for them
+to fill the currently active block group. If we advance the
+meta_write_pointer before locking the extent buffer, the following extent
+buffer can pass the meta_write_pointer check, resulting in an unaligned
+write failure.
+
+Advancing the pointer is still thread-safe as the extent buffer is locked.
+
+Reviewed-by: Christoph Hellwig <hch@lst.de>
+Reviewed-by: Johannes Thumshirn <johannes.thumshirn@wdc.com>
+Signed-off-by: Naohiro Aota <naohiro.aota@wdc.com>
+Reviewed-by: David Sterba <dsterba@suse.com>
+Signed-off-by: David Sterba <dsterba@suse.com>
+Stable-dep-of: 13bb483d32ab ("btrfs: zoned: activate metadata block group on write time")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ fs/btrfs/extent_io.c | 7 +++----
+ fs/btrfs/zoned.c | 15 +--------------
+ fs/btrfs/zoned.h | 8 --------
+ 3 files changed, 4 insertions(+), 26 deletions(-)
+
+diff --git a/fs/btrfs/extent_io.c b/fs/btrfs/extent_io.c
+index d4bac66cee533..2ebc982e8eccb 100644
+--- a/fs/btrfs/extent_io.c
++++ b/fs/btrfs/extent_io.c
+@@ -1927,15 +1927,14 @@ static int submit_eb_page(struct page *page, struct btrfs_eb_write_context *ctx)
+ }
+
+ if (!lock_extent_buffer_for_io(eb, wbc)) {
+- btrfs_revert_meta_write_pointer(ctx->zoned_bg, eb);
+ free_extent_buffer(eb);
+ return 0;
+ }
++ /* Implies write in zoned mode. */
+ if (ctx->zoned_bg) {
+- /*
+- * Implies write in zoned mode. Mark the last eb in a block group.
+- */
++ /* Mark the last eb in the block group. */
+ btrfs_schedule_zone_finish_bg(ctx->zoned_bg, eb);
++ ctx->zoned_bg->meta_write_pointer += eb->len;
+ }
+ write_one_eb(eb, wbc);
+ free_extent_buffer(eb);
+diff --git a/fs/btrfs/zoned.c b/fs/btrfs/zoned.c
+index 6e406f1b0d21e..cc117283d0c88 100644
+--- a/fs/btrfs/zoned.c
++++ b/fs/btrfs/zoned.c
+@@ -1792,11 +1792,8 @@ int btrfs_check_meta_write_pointer(struct btrfs_fs_info *fs_info,
+ ctx->zoned_bg = block_group;
+ }
+
+- if (block_group->meta_write_pointer == eb->start) {
+- block_group->meta_write_pointer = eb->start + eb->len;
+-
++ if (block_group->meta_write_pointer == eb->start)
+ return 0;
+- }
+
+ /* If for_sync, this hole will be filled with trasnsaction commit. */
+ if (wbc->sync_mode == WB_SYNC_ALL && !wbc->for_sync)
+@@ -1804,16 +1801,6 @@ int btrfs_check_meta_write_pointer(struct btrfs_fs_info *fs_info,
+ return -EBUSY;
+ }
+
+-void btrfs_revert_meta_write_pointer(struct btrfs_block_group *cache,
+- struct extent_buffer *eb)
+-{
+- if (!btrfs_is_zoned(eb->fs_info) || !cache)
+- return;
+-
+- ASSERT(cache->meta_write_pointer == eb->start + eb->len);
+- cache->meta_write_pointer = eb->start;
+-}
+-
+ int btrfs_zoned_issue_zeroout(struct btrfs_device *device, u64 physical, u64 length)
+ {
+ if (!btrfs_dev_is_sequential(device, physical))
+diff --git a/fs/btrfs/zoned.h b/fs/btrfs/zoned.h
+index c0859d8be1520..74ec37a25808a 100644
+--- a/fs/btrfs/zoned.h
++++ b/fs/btrfs/zoned.h
+@@ -60,8 +60,6 @@ bool btrfs_use_zone_append(struct btrfs_bio *bbio);
+ void btrfs_record_physical_zoned(struct btrfs_bio *bbio);
+ int btrfs_check_meta_write_pointer(struct btrfs_fs_info *fs_info,
+ struct btrfs_eb_write_context *ctx);
+-void btrfs_revert_meta_write_pointer(struct btrfs_block_group *cache,
+- struct extent_buffer *eb);
+ int btrfs_zoned_issue_zeroout(struct btrfs_device *device, u64 physical, u64 length);
+ int btrfs_sync_zone_write_pointer(struct btrfs_device *tgt_dev, u64 logical,
+ u64 physical_start, u64 physical_pos);
+@@ -194,12 +192,6 @@ static inline int btrfs_check_meta_write_pointer(struct btrfs_fs_info *fs_info,
+ return 0;
+ }
+
+-static inline void btrfs_revert_meta_write_pointer(
+- struct btrfs_block_group *cache,
+- struct extent_buffer *eb)
+-{
+-}
+-
+ static inline int btrfs_zoned_issue_zeroout(struct btrfs_device *device,
+ u64 physical, u64 length)
+ {
+--
+2.40.1
+
--- /dev/null
+From 3f40bc328cc1bf4e100d886abf45c56868f6f7da Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 8 Aug 2023 01:12:32 +0900
+Subject: btrfs: zoned: introduce block group context to btrfs_eb_write_context
+
+From: Naohiro Aota <naohiro.aota@wdc.com>
+
+[ Upstream commit 7db94301a980c9da4168ac7ce61e7bde297306ba ]
+
+For metadata write out on the zoned mode, we call
+btrfs_check_meta_write_pointer() to check if an extent buffer to be written
+is aligned to the write pointer.
+
+We look up a block group containing the extent buffer for every extent
+buffer, which takes unnecessary effort as the writing extent buffers are
+mostly contiguous.
+
+Introduce "zoned_bg" to cache the block group working on. Also, while
+at it, rename "cache" to "block_group".
+
+Reviewed-by: Christoph Hellwig <hch@lst.de>
+Reviewed-by: Johannes Thumshirn <johannes.thumshirn@wdc.com>
+Signed-off-by: Naohiro Aota <naohiro.aota@wdc.com>
+Reviewed-by: David Sterba <dsterba@suse.com>
+Signed-off-by: David Sterba <dsterba@suse.com>
+Stable-dep-of: 13bb483d32ab ("btrfs: zoned: activate metadata block group on write time")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ fs/btrfs/extent_io.c | 15 +++++++--------
+ fs/btrfs/extent_io.h | 2 ++
+ fs/btrfs/zoned.c | 35 ++++++++++++++++++++---------------
+ fs/btrfs/zoned.h | 6 ++----
+ 4 files changed, 31 insertions(+), 27 deletions(-)
+
+diff --git a/fs/btrfs/extent_io.c b/fs/btrfs/extent_io.c
+index b3bf2e2704888..c2be1561a52cb 100644
+--- a/fs/btrfs/extent_io.c
++++ b/fs/btrfs/extent_io.c
+@@ -1881,7 +1881,6 @@ static int submit_eb_page(struct page *page, struct btrfs_eb_write_context *ctx)
+ {
+ struct writeback_control *wbc = ctx->wbc;
+ struct address_space *mapping = page->mapping;
+- struct btrfs_block_group *cache = NULL;
+ struct extent_buffer *eb;
+ int ret;
+
+@@ -1919,7 +1918,7 @@ static int submit_eb_page(struct page *page, struct btrfs_eb_write_context *ctx)
+
+ ctx->eb = eb;
+
+- if (!btrfs_check_meta_write_pointer(eb->fs_info, eb, &cache)) {
++ if (!btrfs_check_meta_write_pointer(eb->fs_info, ctx)) {
+ /*
+ * If for_sync, this hole will be filled with
+ * trasnsaction commit.
+@@ -1933,18 +1932,15 @@ static int submit_eb_page(struct page *page, struct btrfs_eb_write_context *ctx)
+ }
+
+ if (!lock_extent_buffer_for_io(eb, wbc)) {
+- btrfs_revert_meta_write_pointer(cache, eb);
+- if (cache)
+- btrfs_put_block_group(cache);
++ btrfs_revert_meta_write_pointer(ctx->zoned_bg, eb);
+ free_extent_buffer(eb);
+ return 0;
+ }
+- if (cache) {
++ if (ctx->zoned_bg) {
+ /*
+ * Implies write in zoned mode. Mark the last eb in a block group.
+ */
+- btrfs_schedule_zone_finish_bg(cache, eb);
+- btrfs_put_block_group(cache);
++ btrfs_schedule_zone_finish_bg(ctx->zoned_bg, eb);
+ }
+ write_one_eb(eb, wbc);
+ free_extent_buffer(eb);
+@@ -2057,6 +2053,9 @@ int btree_write_cache_pages(struct address_space *mapping,
+ ret = 0;
+ if (!ret && BTRFS_FS_ERROR(fs_info))
+ ret = -EROFS;
++
++ if (ctx.zoned_bg)
++ btrfs_put_block_group(ctx.zoned_bg);
+ btrfs_zoned_meta_io_unlock(fs_info);
+ return ret;
+ }
+diff --git a/fs/btrfs/extent_io.h b/fs/btrfs/extent_io.h
+index ecc1660007c11..f61b7896320a1 100644
+--- a/fs/btrfs/extent_io.h
++++ b/fs/btrfs/extent_io.h
+@@ -97,6 +97,8 @@ struct extent_buffer {
+ struct btrfs_eb_write_context {
+ struct writeback_control *wbc;
+ struct extent_buffer *eb;
++ /* Block group @eb resides in. Only used for zoned mode. */
++ struct btrfs_block_group *zoned_bg;
+ };
+
+ /*
+diff --git a/fs/btrfs/zoned.c b/fs/btrfs/zoned.c
+index d9e6df2da272c..92f11176216b5 100644
+--- a/fs/btrfs/zoned.c
++++ b/fs/btrfs/zoned.c
+@@ -1759,30 +1759,35 @@ void btrfs_finish_ordered_zoned(struct btrfs_ordered_extent *ordered)
+ }
+
+ bool btrfs_check_meta_write_pointer(struct btrfs_fs_info *fs_info,
+- struct extent_buffer *eb,
+- struct btrfs_block_group **cache_ret)
++ struct btrfs_eb_write_context *ctx)
+ {
+- struct btrfs_block_group *cache;
+- bool ret = true;
++ const struct extent_buffer *eb = ctx->eb;
++ struct btrfs_block_group *block_group = ctx->zoned_bg;
+
+ if (!btrfs_is_zoned(fs_info))
+ return true;
+
+- cache = btrfs_lookup_block_group(fs_info, eb->start);
+- if (!cache)
+- return true;
++ if (block_group) {
++ if (block_group->start > eb->start ||
++ block_group->start + block_group->length <= eb->start) {
++ btrfs_put_block_group(block_group);
++ block_group = NULL;
++ ctx->zoned_bg = NULL;
++ }
++ }
+
+- if (cache->meta_write_pointer != eb->start) {
+- btrfs_put_block_group(cache);
+- cache = NULL;
+- ret = false;
+- } else {
+- cache->meta_write_pointer = eb->start + eb->len;
++ if (!block_group) {
++ block_group = btrfs_lookup_block_group(fs_info, eb->start);
++ if (!block_group)
++ return true;
++ ctx->zoned_bg = block_group;
+ }
+
+- *cache_ret = cache;
++ if (block_group->meta_write_pointer != eb->start)
++ return false;
++ block_group->meta_write_pointer = eb->start + eb->len;
+
+- return ret;
++ return true;
+ }
+
+ void btrfs_revert_meta_write_pointer(struct btrfs_block_group *cache,
+diff --git a/fs/btrfs/zoned.h b/fs/btrfs/zoned.h
+index 27322b926038c..49d5bd87245c5 100644
+--- a/fs/btrfs/zoned.h
++++ b/fs/btrfs/zoned.h
+@@ -59,8 +59,7 @@ void btrfs_redirty_list_add(struct btrfs_transaction *trans,
+ bool btrfs_use_zone_append(struct btrfs_bio *bbio);
+ void btrfs_record_physical_zoned(struct btrfs_bio *bbio);
+ bool btrfs_check_meta_write_pointer(struct btrfs_fs_info *fs_info,
+- struct extent_buffer *eb,
+- struct btrfs_block_group **cache_ret);
++ struct btrfs_eb_write_context *ctx);
+ void btrfs_revert_meta_write_pointer(struct btrfs_block_group *cache,
+ struct extent_buffer *eb);
+ int btrfs_zoned_issue_zeroout(struct btrfs_device *device, u64 physical, u64 length);
+@@ -190,8 +189,7 @@ static inline void btrfs_record_physical_zoned(struct btrfs_bio *bbio)
+ }
+
+ static inline bool btrfs_check_meta_write_pointer(struct btrfs_fs_info *fs_info,
+- struct extent_buffer *eb,
+- struct btrfs_block_group **cache_ret)
++ struct btrfs_eb_write_context *ctx)
+ {
+ return true;
+ }
+--
+2.40.1
+
--- /dev/null
+From e1ca319bf461817cea6dded666c0f59d65d20d01 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 8 Aug 2023 01:12:33 +0900
+Subject: btrfs: zoned: return int from btrfs_check_meta_write_pointer
+
+From: Naohiro Aota <naohiro.aota@wdc.com>
+
+[ Upstream commit 2ad8c0510a965113404cfe670b41ddc34fb66100 ]
+
+Now that we have writeback_control passed to
+btrfs_check_meta_write_pointer(), we can move the wbc condition in
+submit_eb_page() to btrfs_check_meta_write_pointer() and return int.
+
+Reviewed-by: Christoph Hellwig <hch@lst.de>
+Reviewed-by: Johannes Thumshirn <johannes.thumshirn@wdc.com>
+Signed-off-by: Naohiro Aota <naohiro.aota@wdc.com>
+Reviewed-by: David Sterba <dsterba@suse.com>
+Signed-off-by: David Sterba <dsterba@suse.com>
+Stable-dep-of: 13bb483d32ab ("btrfs: zoned: activate metadata block group on write time")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ fs/btrfs/extent_io.c | 11 +++--------
+ fs/btrfs/zoned.c | 30 ++++++++++++++++++++++--------
+ fs/btrfs/zoned.h | 10 +++++-----
+ 3 files changed, 30 insertions(+), 21 deletions(-)
+
+diff --git a/fs/btrfs/extent_io.c b/fs/btrfs/extent_io.c
+index c2be1561a52cb..d4bac66cee533 100644
+--- a/fs/btrfs/extent_io.c
++++ b/fs/btrfs/extent_io.c
+@@ -1918,14 +1918,9 @@ static int submit_eb_page(struct page *page, struct btrfs_eb_write_context *ctx)
+
+ ctx->eb = eb;
+
+- if (!btrfs_check_meta_write_pointer(eb->fs_info, ctx)) {
+- /*
+- * If for_sync, this hole will be filled with
+- * trasnsaction commit.
+- */
+- if (wbc->sync_mode == WB_SYNC_ALL && !wbc->for_sync)
+- ret = -EAGAIN;
+- else
++ ret = btrfs_check_meta_write_pointer(eb->fs_info, ctx);
++ if (ret) {
++ if (ret == -EBUSY)
+ ret = 0;
+ free_extent_buffer(eb);
+ return ret;
+diff --git a/fs/btrfs/zoned.c b/fs/btrfs/zoned.c
+index 92f11176216b5..6e406f1b0d21e 100644
+--- a/fs/btrfs/zoned.c
++++ b/fs/btrfs/zoned.c
+@@ -1758,14 +1758,23 @@ void btrfs_finish_ordered_zoned(struct btrfs_ordered_extent *ordered)
+ }
+ }
+
+-bool btrfs_check_meta_write_pointer(struct btrfs_fs_info *fs_info,
+- struct btrfs_eb_write_context *ctx)
++/*
++ * Check if @ctx->eb is aligned to the write pointer.
++ *
++ * Return:
++ * 0: @ctx->eb is at the write pointer. You can write it.
++ * -EAGAIN: There is a hole. The caller should handle the case.
++ * -EBUSY: There is a hole, but the caller can just bail out.
++ */
++int btrfs_check_meta_write_pointer(struct btrfs_fs_info *fs_info,
++ struct btrfs_eb_write_context *ctx)
+ {
++ const struct writeback_control *wbc = ctx->wbc;
+ const struct extent_buffer *eb = ctx->eb;
+ struct btrfs_block_group *block_group = ctx->zoned_bg;
+
+ if (!btrfs_is_zoned(fs_info))
+- return true;
++ return 0;
+
+ if (block_group) {
+ if (block_group->start > eb->start ||
+@@ -1779,15 +1788,20 @@ bool btrfs_check_meta_write_pointer(struct btrfs_fs_info *fs_info,
+ if (!block_group) {
+ block_group = btrfs_lookup_block_group(fs_info, eb->start);
+ if (!block_group)
+- return true;
++ return 0;
+ ctx->zoned_bg = block_group;
+ }
+
+- if (block_group->meta_write_pointer != eb->start)
+- return false;
+- block_group->meta_write_pointer = eb->start + eb->len;
++ if (block_group->meta_write_pointer == eb->start) {
++ block_group->meta_write_pointer = eb->start + eb->len;
+
+- return true;
++ return 0;
++ }
++
++ /* If for_sync, this hole will be filled with trasnsaction commit. */
++ if (wbc->sync_mode == WB_SYNC_ALL && !wbc->for_sync)
++ return -EAGAIN;
++ return -EBUSY;
+ }
+
+ void btrfs_revert_meta_write_pointer(struct btrfs_block_group *cache,
+diff --git a/fs/btrfs/zoned.h b/fs/btrfs/zoned.h
+index 49d5bd87245c5..c0859d8be1520 100644
+--- a/fs/btrfs/zoned.h
++++ b/fs/btrfs/zoned.h
+@@ -58,8 +58,8 @@ void btrfs_redirty_list_add(struct btrfs_transaction *trans,
+ struct extent_buffer *eb);
+ bool btrfs_use_zone_append(struct btrfs_bio *bbio);
+ void btrfs_record_physical_zoned(struct btrfs_bio *bbio);
+-bool btrfs_check_meta_write_pointer(struct btrfs_fs_info *fs_info,
+- struct btrfs_eb_write_context *ctx);
++int btrfs_check_meta_write_pointer(struct btrfs_fs_info *fs_info,
++ struct btrfs_eb_write_context *ctx);
+ void btrfs_revert_meta_write_pointer(struct btrfs_block_group *cache,
+ struct extent_buffer *eb);
+ int btrfs_zoned_issue_zeroout(struct btrfs_device *device, u64 physical, u64 length);
+@@ -188,10 +188,10 @@ static inline void btrfs_record_physical_zoned(struct btrfs_bio *bbio)
+ {
+ }
+
+-static inline bool btrfs_check_meta_write_pointer(struct btrfs_fs_info *fs_info,
+- struct btrfs_eb_write_context *ctx)
++static inline int btrfs_check_meta_write_pointer(struct btrfs_fs_info *fs_info,
++ struct btrfs_eb_write_context *ctx)
+ {
+- return true;
++ return 0;
+ }
+
+ static inline void btrfs_revert_meta_write_pointer(
+--
+2.40.1
+
--- /dev/null
+From 789ef46a286770e7722ad6af3745b4aa3cc3af0b Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 4 Aug 2023 13:38:01 +0300
+Subject: bus: ti-sysc: Configure uart quirks for k3 SoC
+
+From: Tony Lindgren <tony@atomide.com>
+
+[ Upstream commit 03a711d3cb83692733f865312f49e665c49de6de ]
+
+Enable the uart quirks similar to the earlier SoCs. Let's assume we are
+likely going to need a k3 specific quirk mask separate from the earlier
+SoCs, so let's not start changing the revision register mask at this point.
+
+Note that SYSC_QUIRK_LEGACY_IDLE will be needed until we can remove the
+need for pm_runtime_irq_safe() from 8250_omap driver.
+
+Reviewed-by: Nishanth Menon <nm@ti.com>
+Signed-off-by: Tony Lindgren <tony@atomide.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/bus/ti-sysc.c | 2 ++
+ 1 file changed, 2 insertions(+)
+
+diff --git a/drivers/bus/ti-sysc.c b/drivers/bus/ti-sysc.c
+index c95fa4335fee2..9766dbf607f97 100644
+--- a/drivers/bus/ti-sysc.c
++++ b/drivers/bus/ti-sysc.c
+@@ -1525,6 +1525,8 @@ static const struct sysc_revision_quirk sysc_revision_quirks[] = {
+ SYSC_QUIRK_SWSUP_SIDLE | SYSC_QUIRK_LEGACY_IDLE),
+ SYSC_QUIRK("uart", 0, 0x50, 0x54, 0x58, 0x47422e03, 0xffffffff,
+ SYSC_QUIRK_SWSUP_SIDLE | SYSC_QUIRK_LEGACY_IDLE),
++ SYSC_QUIRK("uart", 0, 0x50, 0x54, 0x58, 0x47424e03, 0xffffffff,
++ SYSC_QUIRK_SWSUP_SIDLE | SYSC_QUIRK_LEGACY_IDLE),
+
+ /* Quirks that need to be set based on the module address */
+ SYSC_QUIRK("mcpdm", 0x40132000, 0, 0x10, -ENODEV, 0x50000800, 0xffffffff,
+--
+2.40.1
+
--- /dev/null
+From a0394423eb7c8129b231e15bc889b6a641f0ccc2 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sat, 22 Jul 2023 08:15:52 +1000
+Subject: can: sun4i_can: Add acceptance register quirk
+
+From: John Watts <contact@jookia.org>
+
+[ Upstream commit 8cda0c6dfd42ee6f2586e7dffb553aaf1fcb62ca ]
+
+The Allwinner D1's CAN controllers have the ACPC and ACPM registers
+moved down. Compensate for this by adding an offset quirk for the
+acceptance registers.
+
+Signed-off-by: John Watts <contact@jookia.org>
+Link: https://lore.kernel.org/all/20230721221552.1973203-5-contact@jookia.org
+Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/can/sun4i_can.c | 10 ++++++++--
+ 1 file changed, 8 insertions(+), 2 deletions(-)
+
+diff --git a/drivers/net/can/sun4i_can.c b/drivers/net/can/sun4i_can.c
+index 0827830bbf28c..1f90fe6dbb8bb 100644
+--- a/drivers/net/can/sun4i_can.c
++++ b/drivers/net/can/sun4i_can.c
+@@ -205,9 +205,11 @@
+ * struct sun4ican_quirks - Differences between SoC variants.
+ *
+ * @has_reset: SoC needs reset deasserted.
++ * @acp_offset: Offset of ACPC and ACPM registers
+ */
+ struct sun4ican_quirks {
+ bool has_reset;
++ int acp_offset;
+ };
+
+ struct sun4ican_priv {
+@@ -216,6 +218,7 @@ struct sun4ican_priv {
+ struct clk *clk;
+ struct reset_control *reset;
+ spinlock_t cmdreg_lock; /* lock for concurrent cmd register writes */
++ int acp_offset;
+ };
+
+ static const struct can_bittiming_const sun4ican_bittiming_const = {
+@@ -338,8 +341,8 @@ static int sun4i_can_start(struct net_device *dev)
+ }
+
+ /* set filters - we accept all */
+- writel(0x00000000, priv->base + SUN4I_REG_ACPC_ADDR);
+- writel(0xFFFFFFFF, priv->base + SUN4I_REG_ACPM_ADDR);
++ writel(0x00000000, priv->base + SUN4I_REG_ACPC_ADDR + priv->acp_offset);
++ writel(0xFFFFFFFF, priv->base + SUN4I_REG_ACPM_ADDR + priv->acp_offset);
+
+ /* clear error counters and error code capture */
+ writel(0, priv->base + SUN4I_REG_ERRC_ADDR);
+@@ -768,10 +771,12 @@ static const struct ethtool_ops sun4ican_ethtool_ops = {
+
+ static const struct sun4ican_quirks sun4ican_quirks_a10 = {
+ .has_reset = false,
++ .acp_offset = 0,
+ };
+
+ static const struct sun4ican_quirks sun4ican_quirks_r40 = {
+ .has_reset = true,
++ .acp_offset = 0,
+ };
+
+ static const struct of_device_id sun4ican_of_match[] = {
+@@ -870,6 +875,7 @@ static int sun4ican_probe(struct platform_device *pdev)
+ priv->base = addr;
+ priv->clk = clk;
+ priv->reset = reset;
++ priv->acp_offset = quirks->acp_offset;
+ spin_lock_init(&priv->cmdreg_lock);
+
+ platform_set_drvdata(pdev, dev);
+--
+2.40.1
+
--- /dev/null
+From 4bcd425e7d66fddd134b66f7c2f6225cf7ab5e5c Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sat, 22 Jul 2023 08:15:53 +1000
+Subject: can: sun4i_can: Add support for the Allwinner D1
+
+From: John Watts <contact@jookia.org>
+
+[ Upstream commit 8abb95250ae6af2d51993da8fcae18da2ce24cc4 ]
+
+The controllers present in the D1 are extremely similar to the R40
+and require the same reset quirks, but An extra quirk is needed to support
+receiving packets.
+
+Signed-off-by: John Watts <contact@jookia.org>
+Link: https://lore.kernel.org/all/20230721221552.1973203-6-contact@jookia.org
+Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/can/Kconfig | 4 ++--
+ drivers/net/can/sun4i_can.c | 12 +++++++++++-
+ 2 files changed, 13 insertions(+), 3 deletions(-)
+
+diff --git a/drivers/net/can/Kconfig b/drivers/net/can/Kconfig
+index a5c5036dfb943..e626de33e735d 100644
+--- a/drivers/net/can/Kconfig
++++ b/drivers/net/can/Kconfig
+@@ -185,10 +185,10 @@ config CAN_SLCAN
+
+ config CAN_SUN4I
+ tristate "Allwinner A10 CAN controller"
+- depends on MACH_SUN4I || MACH_SUN7I || COMPILE_TEST
++ depends on MACH_SUN4I || MACH_SUN7I || RISCV || COMPILE_TEST
+ help
+ Say Y here if you want to use CAN controller found on Allwinner
+- A10/A20 SoCs.
++ A10/A20/D1 SoCs.
+
+ To compile this driver as a module, choose M here: the module will
+ be called sun4i_can.
+diff --git a/drivers/net/can/sun4i_can.c b/drivers/net/can/sun4i_can.c
+index 1f90fe6dbb8bb..c508a328e38d4 100644
+--- a/drivers/net/can/sun4i_can.c
++++ b/drivers/net/can/sun4i_can.c
+@@ -91,6 +91,8 @@
+ #define SUN4I_REG_BUF12_ADDR 0x0070 /* CAN Tx/Rx Buffer 12 */
+ #define SUN4I_REG_ACPC_ADDR 0x0040 /* CAN Acceptance Code 0 */
+ #define SUN4I_REG_ACPM_ADDR 0x0044 /* CAN Acceptance Mask 0 */
++#define SUN4I_REG_ACPC_ADDR_D1 0x0028 /* CAN Acceptance Code 0 on the D1 */
++#define SUN4I_REG_ACPM_ADDR_D1 0x002C /* CAN Acceptance Mask 0 on the D1 */
+ #define SUN4I_REG_RBUF_RBACK_START_ADDR 0x0180 /* CAN transmit buffer start */
+ #define SUN4I_REG_RBUF_RBACK_END_ADDR 0x01b0 /* CAN transmit buffer end */
+
+@@ -779,6 +781,11 @@ static const struct sun4ican_quirks sun4ican_quirks_r40 = {
+ .acp_offset = 0,
+ };
+
++static const struct sun4ican_quirks sun4ican_quirks_d1 = {
++ .has_reset = true,
++ .acp_offset = (SUN4I_REG_ACPC_ADDR_D1 - SUN4I_REG_ACPC_ADDR),
++};
++
+ static const struct of_device_id sun4ican_of_match[] = {
+ {
+ .compatible = "allwinner,sun4i-a10-can",
+@@ -789,6 +796,9 @@ static const struct of_device_id sun4ican_of_match[] = {
+ }, {
+ .compatible = "allwinner,sun8i-r40-can",
+ .data = &sun4ican_quirks_r40
++ }, {
++ .compatible = "allwinner,sun20i-d1-can",
++ .data = &sun4ican_quirks_d1
+ }, {
+ /* sentinel */
+ },
+@@ -913,4 +923,4 @@ module_platform_driver(sun4i_can_driver);
+ MODULE_AUTHOR("Peter Chen <xingkongcp@gmail.com>");
+ MODULE_AUTHOR("Gerhard Bertelsmann <info@gerhard-bertelsmann.de>");
+ MODULE_LICENSE("Dual BSD/GPL");
+-MODULE_DESCRIPTION("CAN driver for Allwinner SoCs (A10/A20)");
++MODULE_DESCRIPTION("CAN driver for Allwinner SoCs (A10/A20/D1)");
+--
+2.40.1
+
--- /dev/null
+From cf50f7682532c293a2d4898c72221ec0b1cec56a Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 4 Aug 2023 09:32:18 +0000
+Subject: crypto: lib/mpi - avoid null pointer deref in mpi_cmp_ui()
+
+From: Mark O'Donovan <shiftee@posteo.net>
+
+[ Upstream commit 9e47a758b70167c9301d2b44d2569f86c7796f2d ]
+
+During NVMeTCP Authentication a controller can trigger a kernel
+oops by specifying the 8192 bit Diffie Hellman group and passing
+a correctly sized, but zeroed Diffie Hellamn value.
+mpi_cmp_ui() was detecting this if the second parameter was 0,
+but 1 is passed from dh_is_pubkey_valid(). This causes the null
+pointer u->d to be dereferenced towards the end of mpi_cmp_ui()
+
+Signed-off-by: Mark O'Donovan <shiftee@posteo.net>
+Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ lib/mpi/mpi-cmp.c | 8 ++++++--
+ 1 file changed, 6 insertions(+), 2 deletions(-)
+
+diff --git a/lib/mpi/mpi-cmp.c b/lib/mpi/mpi-cmp.c
+index c4cfa3ff05818..0835b6213235e 100644
+--- a/lib/mpi/mpi-cmp.c
++++ b/lib/mpi/mpi-cmp.c
+@@ -25,8 +25,12 @@ int mpi_cmp_ui(MPI u, unsigned long v)
+ mpi_limb_t limb = v;
+
+ mpi_normalize(u);
+- if (!u->nlimbs && !limb)
+- return 0;
++ if (u->nlimbs == 0) {
++ if (v == 0)
++ return 0;
++ else
++ return -1;
++ }
+ if (u->sign)
+ return -1;
+ if (u->nlimbs > 1)
+--
+2.40.1
+
--- /dev/null
+From 8f28a0d00ecaac41e3ac103e315f77ad187f8999 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 20 Jun 2023 20:08:32 +0000
+Subject: crypto: lrw,xts - Replace strlcpy with strscpy
+
+From: Azeem Shaikh <azeemshaikh38@gmail.com>
+
+[ Upstream commit babb80b3ecc6f40c962e13c654ebcd27f25ee327 ]
+
+strlcpy() reads the entire source buffer first.
+This read may exceed the destination size limit.
+This is both inefficient and can lead to linear read
+overflows if a source string is not NUL-terminated [1].
+In an effort to remove strlcpy() completely [2], replace
+strlcpy() here with strscpy().
+
+Direct replacement is safe here since return value of -errno
+is used to check for truncation instead of sizeof(dest).
+
+[1] https://www.kernel.org/doc/html/latest/process/deprecated.html#strlcpy
+[2] https://github.com/KSPP/linux/issues/89
+
+Signed-off-by: Azeem Shaikh <azeemshaikh38@gmail.com>
+Reviewed-by: Kees Cook <keescook@chromium.org>
+Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ crypto/lrw.c | 6 +++---
+ crypto/xts.c | 6 +++---
+ 2 files changed, 6 insertions(+), 6 deletions(-)
+
+diff --git a/crypto/lrw.c b/crypto/lrw.c
+index 1b0f76ba3eb5e..59260aefed280 100644
+--- a/crypto/lrw.c
++++ b/crypto/lrw.c
+@@ -357,10 +357,10 @@ static int lrw_create(struct crypto_template *tmpl, struct rtattr **tb)
+ * cipher name.
+ */
+ if (!strncmp(cipher_name, "ecb(", 4)) {
+- unsigned len;
++ int len;
+
+- len = strlcpy(ecb_name, cipher_name + 4, sizeof(ecb_name));
+- if (len < 2 || len >= sizeof(ecb_name))
++ len = strscpy(ecb_name, cipher_name + 4, sizeof(ecb_name));
++ if (len < 2)
+ goto err_free_inst;
+
+ if (ecb_name[len - 1] != ')')
+diff --git a/crypto/xts.c b/crypto/xts.c
+index 09be909a6a1aa..548b302c6c6a0 100644
+--- a/crypto/xts.c
++++ b/crypto/xts.c
+@@ -396,10 +396,10 @@ static int xts_create(struct crypto_template *tmpl, struct rtattr **tb)
+ * cipher name.
+ */
+ if (!strncmp(cipher_name, "ecb(", 4)) {
+- unsigned len;
++ int len;
+
+- len = strlcpy(ctx->name, cipher_name + 4, sizeof(ctx->name));
+- if (len < 2 || len >= sizeof(ctx->name))
++ len = strscpy(ctx->name, cipher_name + 4, sizeof(ctx->name));
++ if (len < 2)
+ goto err_free_inst;
+
+ if (ctx->name[len - 1] != ')')
+--
+2.40.1
+
--- /dev/null
+From 092971e3bc31c372733fe0e60d7fed43c19827c8 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 13 Jul 2023 11:44:19 +0200
+Subject: devlink: remove reload failed checks in params get/set callbacks
+
+From: Jiri Pirko <jiri@nvidia.com>
+
+[ Upstream commit 633d76ad01ad0321a1ace3e5cc4fed06753d7ac4 ]
+
+The checks in question were introduced by:
+commit 6b4db2e528f6 ("devlink: Fix use-after-free after a failed reload").
+That fixed an issue of reload with mlxsw driver.
+
+Back then, that was a valid fix, because there was a limitation
+in place that prevented drivers from registering/unregistering params
+when devlink instance was registered.
+
+It was possible to do the fix differently by changing drivers to
+register/unregister params in appropriate places making sure the ops
+operate only on memory which is allocated and initialized. But that,
+as a dependency, would require to remove the limitation mentioned above.
+
+Eventually, this limitation was lifted by:
+commit 1d18bb1a4ddd ("devlink: allow registering parameters after the instance")
+
+Also, the alternative fix (which also fixed another issue) was done by:
+commit 74cbc3c03c82 ("mlxsw: spectrum_acl_tcam: Move devlink param to TCAM code").
+
+Therefore, the checks are no longer relevant. Each driver should make
+sure to have the params registered only when the memory the ops
+are working with is allocated and initialized.
+
+So remove the checks.
+
+Signed-off-by: Jiri Pirko <jiri@nvidia.com>
+Reviewed-by: Ido Schimmel <idosch@nvidia.com>
+Reviewed-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/devlink/leftover.c | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/net/devlink/leftover.c b/net/devlink/leftover.c
+index bfed7929a904f..5277eb3c7d0a1 100644
+--- a/net/devlink/leftover.c
++++ b/net/devlink/leftover.c
+@@ -3946,7 +3946,7 @@ static int devlink_param_get(struct devlink *devlink,
+ const struct devlink_param *param,
+ struct devlink_param_gset_ctx *ctx)
+ {
+- if (!param->get || devlink->reload_failed)
++ if (!param->get)
+ return -EOPNOTSUPP;
+ return param->get(devlink, param->id, ctx);
+ }
+@@ -3955,7 +3955,7 @@ static int devlink_param_set(struct devlink *devlink,
+ const struct devlink_param *param,
+ struct devlink_param_gset_ctx *ctx)
+ {
+- if (!param->set || devlink->reload_failed)
++ if (!param->set)
+ return -EOPNOTSUPP;
+ return param->set(devlink, param->id, ctx);
+ }
+--
+2.40.1
+
--- /dev/null
+From 2fc4e68e9746ea47bbab63d153532970277f9a6a Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 10 Apr 2023 20:00:46 -0400
+Subject: drm/amd/display: Add stream overhead in BW calculations for 128b/132b
+
+From: George Shen <george.shen@amd.com>
+
+[ Upstream commit 974764180838516f80a13257da67a1ec6afb87d4 ]
+
+[Why]
+Current BW calculations do not account for the additional padding added
+for uncompressed pixel-to-symbol packing.
+
+This results in X.Y being too low for 128b/132b SST streams in certain
+scenarios. If X.Y is too low, end user can observe image corruption.
+
+[How]
+Add function to calculate stream overhead to timing BW calculation for
+128b/132b SST cases.
+
+Reviewed-by: Wenjing Liu <wenjing.liu@amd.com>
+Acked-by: Alan Liu <haoping.liu@amd.com>
+Signed-off-by: George Shen <george.shen@amd.com>
+Tested-by: Daniel Wheeler <daniel.wheeler@amd.com>
+Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/gpu/drm/amd/display/dc/dc.h | 2 +
+ drivers/gpu/drm/amd/display/dc/dsc/dc_dsc.c | 42 +++++++++++++++++++++
+ 2 files changed, 44 insertions(+)
+
+diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h
+index 63948170fd6d9..3d4180f7ba349 100644
+--- a/drivers/gpu/drm/amd/display/dc/dc.h
++++ b/drivers/gpu/drm/amd/display/dc/dc.h
+@@ -1409,6 +1409,8 @@ struct dc_plane_state *dc_get_surface_for_mpcc(struct dc *dc,
+
+ uint32_t dc_get_opp_for_plane(struct dc *dc, struct dc_plane_state *plane);
+
++void dc_set_disable_128b_132b_stream_overhead(bool disable);
++
+ /* The function returns minimum bandwidth required to drive a given timing
+ * return - minimum required timing bandwidth in kbps.
+ */
+diff --git a/drivers/gpu/drm/amd/display/dc/dsc/dc_dsc.c b/drivers/gpu/drm/amd/display/dc/dsc/dc_dsc.c
+index 58dd62cce4bb9..aed0d3dafa247 100644
+--- a/drivers/gpu/drm/amd/display/dc/dsc/dc_dsc.c
++++ b/drivers/gpu/drm/amd/display/dc/dsc/dc_dsc.c
+@@ -40,6 +40,8 @@ static bool dsc_policy_enable_dsc_when_not_needed;
+
+ static bool dsc_policy_disable_dsc_stream_overhead;
+
++static bool disable_128b_132b_stream_overhead;
++
+ #ifndef MAX
+ #define MAX(X, Y) ((X) > (Y) ? (X) : (Y))
+ #endif
+@@ -47,6 +49,41 @@ static bool dsc_policy_disable_dsc_stream_overhead;
+ #define MIN(X, Y) ((X) < (Y) ? (X) : (Y))
+ #endif
+
++/* Need to account for padding due to pixel-to-symbol packing
++ * for uncompressed 128b/132b streams.
++ */
++static uint32_t apply_128b_132b_stream_overhead(
++ const struct dc_crtc_timing *timing, const uint32_t kbps)
++{
++ uint32_t total_kbps = kbps;
++
++ if (disable_128b_132b_stream_overhead)
++ return kbps;
++
++ if (!timing->flags.DSC) {
++ struct fixed31_32 bpp;
++ struct fixed31_32 overhead_factor;
++
++ bpp = dc_fixpt_from_int(kbps);
++ bpp = dc_fixpt_div_int(bpp, timing->pix_clk_100hz / 10);
++
++ /* Symbols_per_HActive = HActive * bpp / (4 lanes * 32-bit symbol size)
++ * Overhead_factor = ceil(Symbols_per_HActive) / Symbols_per_HActive
++ */
++ overhead_factor = dc_fixpt_from_int(timing->h_addressable);
++ overhead_factor = dc_fixpt_mul(overhead_factor, bpp);
++ overhead_factor = dc_fixpt_div_int(overhead_factor, 128);
++ overhead_factor = dc_fixpt_div(
++ dc_fixpt_from_int(dc_fixpt_ceil(overhead_factor)),
++ overhead_factor);
++
++ total_kbps = dc_fixpt_ceil(
++ dc_fixpt_mul_int(overhead_factor, total_kbps));
++ }
++
++ return total_kbps;
++}
++
+ uint32_t dc_bandwidth_in_kbps_from_timing(
+ const struct dc_crtc_timing *timing)
+ {
+@@ -1165,6 +1202,11 @@ void dc_dsc_policy_set_disable_dsc_stream_overhead(bool disable)
+ dsc_policy_disable_dsc_stream_overhead = disable;
+ }
+
++void dc_set_disable_128b_132b_stream_overhead(bool disable)
++{
++ disable_128b_132b_stream_overhead = disable;
++}
++
+ void dc_dsc_get_default_config_option(const struct dc *dc, struct dc_dsc_config_options *options)
+ {
+ options->dsc_min_slice_height_override = dc->debug.dsc_min_slice_height_override;
+--
+2.40.1
+
--- /dev/null
+From 09e9e5a0a89140c1a657101179b451dc0d487f7b Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 24 Jul 2023 16:57:36 -0400
+Subject: drm/amd/display: Blocking invalid 420 modes on HDMI TMDS for DCN31
+
+From: Leo Chen <sancchen@amd.com>
+
+[ Upstream commit 026a71babf48efb6b9884a3a66fa31aec9e1ea54 ]
+
+[Why & How]
+HDMI TMDS does not have ODM support. Filtering 420 modes that
+exceed the 4096 FMT limitation on DCN31 will resolve
+intermittent corruptions issues.
+
+Reviewed-by: Nicholas Kazlauskas <nicholas.kazlauskas@amd.com>
+Acked-by: Tom Chung <chiahsuan.chung@amd.com>
+Signed-off-by: Leo Chen <sancchen@amd.com>
+Tested-by: Daniel Wheeler <daniel.wheeler@amd.com>
+Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ .../gpu/drm/amd/display/dc/dml/dcn31/display_mode_vba_31.c | 4 +++-
+ 1 file changed, 3 insertions(+), 1 deletion(-)
+
+diff --git a/drivers/gpu/drm/amd/display/dc/dml/dcn31/display_mode_vba_31.c b/drivers/gpu/drm/amd/display/dc/dml/dcn31/display_mode_vba_31.c
+index 43016c462251f..9d996d5fc3ffa 100644
+--- a/drivers/gpu/drm/amd/display/dc/dml/dcn31/display_mode_vba_31.c
++++ b/drivers/gpu/drm/amd/display/dc/dml/dcn31/display_mode_vba_31.c
+@@ -4135,7 +4135,9 @@ void dml31_ModeSupportAndSystemConfigurationFull(struct display_mode_lib *mode_l
+ }
+ if (v->OutputFormat[k] == dm_420 && v->HActive[k] > DCN31_MAX_FMT_420_BUFFER_WIDTH
+ && v->ODMCombineEnablePerState[i][k] != dm_odm_combine_mode_4to1) {
+- if (v->HActive[k] / 2 > DCN31_MAX_FMT_420_BUFFER_WIDTH) {
++ if (v->Output[k] == dm_hdmi) {
++ FMTBufferExceeded = true;
++ } else if (v->HActive[k] / 2 > DCN31_MAX_FMT_420_BUFFER_WIDTH) {
+ v->ODMCombineEnablePerState[i][k] = dm_odm_combine_mode_4to1;
+ v->PlaneRequiredDISPCLK = v->PlaneRequiredDISPCLKWithODMCombine4To1;
+
+--
+2.40.1
+
--- /dev/null
+From 68f72fe6a747de97433d07fe89e0db9cdcce203a Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 26 Jul 2023 22:44:13 -0400
+Subject: drm/amd/display: Blocking invalid 420 modes on HDMI TMDS for DCN314
+
+From: Leo Chen <sancchen@amd.com>
+
+[ Upstream commit 4c6107a653ccf361cb1b6ba35d558a1a5e6e57ac ]
+
+[Why & How]
+HDMI TMDS does not have ODM support. Filtering 420 modes that
+exceed the 4096 FMT limitation on DCN314 will resolve
+intermittent corruptions issues.
+
+Reviewed-by: Nicholas Kazlauskas <nicholas.kazlauskas@amd.com>
+Acked-by: Tom Chung <chiahsuan.chung@amd.com>
+Signed-off-by: Leo Chen <sancchen@amd.com>
+Tested-by: Daniel Wheeler <daniel.wheeler@amd.com>
+Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ .../gpu/drm/amd/display/dc/dml/dcn314/display_mode_vba_314.c | 4 +++-
+ 1 file changed, 3 insertions(+), 1 deletion(-)
+
+diff --git a/drivers/gpu/drm/amd/display/dc/dml/dcn314/display_mode_vba_314.c b/drivers/gpu/drm/amd/display/dc/dml/dcn314/display_mode_vba_314.c
+index 9010c47476e92..b763786bfcc85 100644
+--- a/drivers/gpu/drm/amd/display/dc/dml/dcn314/display_mode_vba_314.c
++++ b/drivers/gpu/drm/amd/display/dc/dml/dcn314/display_mode_vba_314.c
+@@ -4227,7 +4227,9 @@ void dml314_ModeSupportAndSystemConfigurationFull(struct display_mode_lib *mode_
+ }
+ if (v->OutputFormat[k] == dm_420 && v->HActive[k] > DCN314_MAX_FMT_420_BUFFER_WIDTH
+ && v->ODMCombineEnablePerState[i][k] != dm_odm_combine_mode_4to1) {
+- if (v->HActive[k] / 2 > DCN314_MAX_FMT_420_BUFFER_WIDTH) {
++ if (v->Output[k] == dm_hdmi) {
++ FMTBufferExceeded = true;
++ } else if (v->HActive[k] / 2 > DCN314_MAX_FMT_420_BUFFER_WIDTH) {
+ v->ODMCombineEnablePerState[i][k] = dm_odm_combine_mode_4to1;
+ v->PlaneRequiredDISPCLK = v->PlaneRequiredDISPCLKWithODMCombine4To1;
+
+--
+2.40.1
+
--- /dev/null
+From 4df09bdac63020e113948249cffcb72e21fa51f7 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 6 Jul 2023 16:17:03 -0400
+Subject: drm/amd/display: Fix underflow issue on 175hz timing
+
+From: Leo Ma <hanghong.ma@amd.com>
+
+[ Upstream commit 735688eb905db529efea0c78466fccc1461c3fde ]
+
+[Why]
+Screen underflows happen on 175hz timing for 3 plane overlay case.
+
+[How]
+Based on dst y prefetch value clamp to equ or oto for bandwidth
+calculation.
+
+Reviewed-by: Dillon Varone <dillon.varone@amd.com>
+Acked-by: Alex Hung <alex.hung@amd.com>
+Signed-off-by: Leo Ma <hanghong.ma@amd.com>
+Tested-by: Daniel Wheeler <daniel.wheeler@amd.com>
+Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ .../amd/display/dc/dml/dcn32/display_mode_vba_util_32.c | 7 ++++++-
+ 1 file changed, 6 insertions(+), 1 deletion(-)
+
+diff --git a/drivers/gpu/drm/amd/display/dc/dml/dcn32/display_mode_vba_util_32.c b/drivers/gpu/drm/amd/display/dc/dml/dcn32/display_mode_vba_util_32.c
+index a50e7f4dce421..f74e5fc8218f5 100644
+--- a/drivers/gpu/drm/amd/display/dc/dml/dcn32/display_mode_vba_util_32.c
++++ b/drivers/gpu/drm/amd/display/dc/dml/dcn32/display_mode_vba_util_32.c
+@@ -3459,6 +3459,7 @@ bool dml32_CalculatePrefetchSchedule(
+ double TimeForFetchingMetaPTE = 0;
+ double TimeForFetchingRowInVBlank = 0;
+ double LinesToRequestPrefetchPixelData = 0;
++ double LinesForPrefetchBandwidth = 0;
+ unsigned int HostVMDynamicLevelsTrips;
+ double trip_to_mem;
+ double Tvm_trips;
+@@ -3888,11 +3889,15 @@ bool dml32_CalculatePrefetchSchedule(
+ TimeForFetchingMetaPTE = Tvm_oto;
+ TimeForFetchingRowInVBlank = Tr0_oto;
+ *PrefetchBandwidth = prefetch_bw_oto;
++ /* Clamp to oto for bandwidth calculation */
++ LinesForPrefetchBandwidth = dst_y_prefetch_oto;
+ } else {
+ *DestinationLinesForPrefetch = dst_y_prefetch_equ;
+ TimeForFetchingMetaPTE = Tvm_equ;
+ TimeForFetchingRowInVBlank = Tr0_equ;
+ *PrefetchBandwidth = prefetch_bw_equ;
++ /* Clamp to equ for bandwidth calculation */
++ LinesForPrefetchBandwidth = dst_y_prefetch_equ;
+ }
+
+ *DestinationLinesToRequestVMInVBlank = dml_ceil(4.0 * TimeForFetchingMetaPTE / LineTime, 1.0) / 4.0;
+@@ -3900,7 +3905,7 @@ bool dml32_CalculatePrefetchSchedule(
+ *DestinationLinesToRequestRowInVBlank =
+ dml_ceil(4.0 * TimeForFetchingRowInVBlank / LineTime, 1.0) / 4.0;
+
+- LinesToRequestPrefetchPixelData = *DestinationLinesForPrefetch -
++ LinesToRequestPrefetchPixelData = LinesForPrefetchBandwidth -
+ *DestinationLinesToRequestVMInVBlank - 2 * *DestinationLinesToRequestRowInVBlank;
+
+ #ifdef __DML_VBA_DEBUG__
+--
+2.40.1
+
--- /dev/null
+From 2264559251479851e027f5c248244491d8ef33ff Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 26 Jul 2023 10:40:48 -0400
+Subject: drm/amd/display: Use DTBCLK as refclk instead of DPREFCLK
+
+From: Austin Zheng <austin.zheng@amd.com>
+
+[ Upstream commit 4a30cc2bd281fa176a68b5305cd3695d636152ad ]
+
+[Why]
+Flash of corruption observed when UCLK switching after transitioning
+from DTBCLK to DPREFCLK on subVP(DP) + subVP(HDMI) config
+Scenario where DPREFCLK is required instead of DTBCLK is not expected
+
+[How]
+Always set the DTBCLK source as DTBCLK0
+
+Reviewed-by: Alvin Lee <alvin.lee2@amd.com>
+Acked-by: Tom Chung <chiahsuan.chung@amd.com>
+Signed-off-by: Austin Zheng <austin.zheng@amd.com>
+Tested-by: Daniel Wheeler <daniel.wheeler@amd.com>
+Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/gpu/drm/amd/display/dc/dcn32/dcn32_dccg.c | 3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+diff --git a/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_dccg.c b/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_dccg.c
+index 61ceff6bc0b19..921f58c0c729b 100644
+--- a/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_dccg.c
++++ b/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_dccg.c
+@@ -281,7 +281,8 @@ static void dccg32_set_dpstreamclk(
+ struct dcn_dccg *dccg_dcn = TO_DCN_DCCG(dccg);
+
+ /* set the dtbclk_p source */
+- dccg32_set_dtbclk_p_src(dccg, src, otg_inst);
++ /* always program refclk as DTBCLK. No use-case expected to require DPREFCLK as refclk */
++ dccg32_set_dtbclk_p_src(dccg, DTBCLK0, otg_inst);
+
+ /* enabled to select one of the DTBCLKs for pipe */
+ switch (dp_hpo_inst) {
+--
+2.40.1
+
--- /dev/null
+From 7c62c1e05b73ca042f704993bd20b2133de8fa8a Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 27 Jul 2023 14:23:13 -0400
+Subject: drm/amd/display: Use max memclk variable when setting max memclk
+
+From: Alvin Lee <alvin.lee2@amd.com>
+
+[ Upstream commit 2b1b838ea8e5437ef06a29818d16e9efdfaf0037 ]
+
+[Description]
+In overclocking scenarios the max memclk could be higher
+than the DC mode limit. However, for configs that don't
+support MCLK switching we need to set the max memclk to
+the overclocked max instead of the DC mode max or we
+could result in underflow.
+
+Reviewed-by: Samson Tam <samson.tam@amd.com>
+Acked-by: Tom Chung <chiahsuan.chung@amd.com>
+Signed-off-by: Alvin Lee <alvin.lee2@amd.com>
+Tested-by: Daniel Wheeler <daniel.wheeler@amd.com>
+Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/gpu/drm/amd/display/dc/clk_mgr/dcn32/dcn32_clk_mgr.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn32/dcn32_clk_mgr.c b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn32/dcn32_clk_mgr.c
+index cb992aca760dc..5fc78bf927bbc 100644
+--- a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn32/dcn32_clk_mgr.c
++++ b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn32/dcn32_clk_mgr.c
+@@ -802,7 +802,7 @@ static void dcn32_set_hard_min_memclk(struct clk_mgr *clk_mgr_base, bool current
+ khz_to_mhz_ceil(clk_mgr_base->clks.dramclk_khz));
+ else
+ dcn32_smu_set_hard_min_by_freq(clk_mgr, PPCLK_UCLK,
+- clk_mgr_base->bw_params->clk_table.entries[clk_mgr_base->bw_params->clk_table.num_entries_per_clk.num_memclk_levels - 1].memclk_mhz);
++ clk_mgr_base->bw_params->max_memclk_mhz);
+ } else {
+ dcn32_smu_set_hard_min_by_freq(clk_mgr, PPCLK_UCLK,
+ clk_mgr_base->bw_params->clk_table.entries[0].memclk_mhz);
+--
+2.40.1
+
--- /dev/null
+From fd3b49a620bb7ec27ff805d98db36b63f1420df9 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 7 Jul 2023 09:55:18 -0400
+Subject: drm/amdgpu: Increase soft IH ring size
+
+From: Philip Yang <Philip.Yang@amd.com>
+
+[ Upstream commit bf80d34b6c58ad1c4f76067ecd460a148eab9d39 ]
+
+Retry faults are delegated to soft IH ring and then processed by
+deferred worker. Current soft IH ring size PAGE_SIZE can store 128
+entries, which may overflow and drop retry faults, causes HW stucks
+because the retry fault is not recovered.
+
+Increase soft IH ring size to 8KB, enough to store 256 CAM entries
+because we clear the CAM entry after handling the retry fault from soft
+ring.
+
+Define macro IH_RING_SIZE and IH_SW_RING_SIZE to remove duplicate
+constant.
+
+Show warning message if soft IH ring overflows with CAM enabled because
+this should not happen.
+
+Signed-off-by: Philip Yang <Philip.Yang@amd.com>
+Reviewed-by: Felix Kuehling <Felix.Kuehling@amd.com>
+Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/gpu/drm/amd/amdgpu/amdgpu_ih.c | 8 ++++++--
+ drivers/gpu/drm/amd/amdgpu/amdgpu_ih.h | 7 +++++--
+ drivers/gpu/drm/amd/amdgpu/amdgpu_irq.c | 2 +-
+ drivers/gpu/drm/amd/amdgpu/ih_v6_0.c | 4 ++--
+ drivers/gpu/drm/amd/amdgpu/navi10_ih.c | 4 ++--
+ drivers/gpu/drm/amd/amdgpu/vega10_ih.c | 4 ++--
+ drivers/gpu/drm/amd/amdgpu/vega20_ih.c | 4 ++--
+ 7 files changed, 20 insertions(+), 13 deletions(-)
+
+diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ih.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ih.c
+index fceb3b384955a..f3b0aaf3ebc69 100644
+--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ih.c
++++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ih.c
+@@ -138,6 +138,7 @@ void amdgpu_ih_ring_fini(struct amdgpu_device *adev, struct amdgpu_ih_ring *ih)
+ /**
+ * amdgpu_ih_ring_write - write IV to the ring buffer
+ *
++ * @adev: amdgpu_device pointer
+ * @ih: ih ring to write to
+ * @iv: the iv to write
+ * @num_dw: size of the iv in dw
+@@ -145,8 +146,8 @@ void amdgpu_ih_ring_fini(struct amdgpu_device *adev, struct amdgpu_ih_ring *ih)
+ * Writes an IV to the ring buffer using the CPU and increment the wptr.
+ * Used for testing and delegating IVs to a software ring.
+ */
+-void amdgpu_ih_ring_write(struct amdgpu_ih_ring *ih, const uint32_t *iv,
+- unsigned int num_dw)
++void amdgpu_ih_ring_write(struct amdgpu_device *adev, struct amdgpu_ih_ring *ih,
++ const uint32_t *iv, unsigned int num_dw)
+ {
+ uint32_t wptr = le32_to_cpu(*ih->wptr_cpu) >> 2;
+ unsigned int i;
+@@ -161,6 +162,9 @@ void amdgpu_ih_ring_write(struct amdgpu_ih_ring *ih, const uint32_t *iv,
+ if (wptr != READ_ONCE(ih->rptr)) {
+ wmb();
+ WRITE_ONCE(*ih->wptr_cpu, cpu_to_le32(wptr));
++ } else if (adev->irq.retry_cam_enabled) {
++ dev_warn_once(adev->dev, "IH soft ring buffer overflow 0x%X, 0x%X\n",
++ wptr, ih->rptr);
+ }
+ }
+
+diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ih.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_ih.h
+index dd1c2eded6b9d..6c6184f0dbc17 100644
+--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ih.h
++++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ih.h
+@@ -27,6 +27,9 @@
+ /* Maximum number of IVs processed at once */
+ #define AMDGPU_IH_MAX_NUM_IVS 32
+
++#define IH_RING_SIZE (256 * 1024)
++#define IH_SW_RING_SIZE (8 * 1024) /* enough for 256 CAM entries */
++
+ struct amdgpu_device;
+ struct amdgpu_iv_entry;
+
+@@ -97,8 +100,8 @@ struct amdgpu_ih_funcs {
+ int amdgpu_ih_ring_init(struct amdgpu_device *adev, struct amdgpu_ih_ring *ih,
+ unsigned ring_size, bool use_bus_addr);
+ void amdgpu_ih_ring_fini(struct amdgpu_device *adev, struct amdgpu_ih_ring *ih);
+-void amdgpu_ih_ring_write(struct amdgpu_ih_ring *ih, const uint32_t *iv,
+- unsigned int num_dw);
++void amdgpu_ih_ring_write(struct amdgpu_device *adev, struct amdgpu_ih_ring *ih,
++ const uint32_t *iv, unsigned int num_dw);
+ int amdgpu_ih_wait_on_checkpoint_process_ts(struct amdgpu_device *adev,
+ struct amdgpu_ih_ring *ih);
+ int amdgpu_ih_process(struct amdgpu_device *adev, struct amdgpu_ih_ring *ih);
+diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_irq.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_irq.c
+index 5273decc5753b..fa6d0adcec206 100644
+--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_irq.c
++++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_irq.c
+@@ -493,7 +493,7 @@ void amdgpu_irq_delegate(struct amdgpu_device *adev,
+ struct amdgpu_iv_entry *entry,
+ unsigned int num_dw)
+ {
+- amdgpu_ih_ring_write(&adev->irq.ih_soft, entry->iv_entry, num_dw);
++ amdgpu_ih_ring_write(adev, &adev->irq.ih_soft, entry->iv_entry, num_dw);
+ schedule_work(&adev->irq.ih_soft_work);
+ }
+
+diff --git a/drivers/gpu/drm/amd/amdgpu/ih_v6_0.c b/drivers/gpu/drm/amd/amdgpu/ih_v6_0.c
+index b02e1cef78a76..980b241200803 100644
+--- a/drivers/gpu/drm/amd/amdgpu/ih_v6_0.c
++++ b/drivers/gpu/drm/amd/amdgpu/ih_v6_0.c
+@@ -535,7 +535,7 @@ static int ih_v6_0_sw_init(void *handle)
+ * use bus address for ih ring by psp bl */
+ use_bus_addr =
+ (adev->firmware.load_type == AMDGPU_FW_LOAD_PSP) ? false : true;
+- r = amdgpu_ih_ring_init(adev, &adev->irq.ih, 256 * 1024, use_bus_addr);
++ r = amdgpu_ih_ring_init(adev, &adev->irq.ih, IH_RING_SIZE, use_bus_addr);
+ if (r)
+ return r;
+
+@@ -548,7 +548,7 @@ static int ih_v6_0_sw_init(void *handle)
+ /* initialize ih control register offset */
+ ih_v6_0_init_register_offset(adev);
+
+- r = amdgpu_ih_ring_init(adev, &adev->irq.ih_soft, PAGE_SIZE, true);
++ r = amdgpu_ih_ring_init(adev, &adev->irq.ih_soft, IH_SW_RING_SIZE, true);
+ if (r)
+ return r;
+
+diff --git a/drivers/gpu/drm/amd/amdgpu/navi10_ih.c b/drivers/gpu/drm/amd/amdgpu/navi10_ih.c
+index eec13cb5bf758..b6a8478dabf43 100644
+--- a/drivers/gpu/drm/amd/amdgpu/navi10_ih.c
++++ b/drivers/gpu/drm/amd/amdgpu/navi10_ih.c
+@@ -565,7 +565,7 @@ static int navi10_ih_sw_init(void *handle)
+ use_bus_addr = false;
+ else
+ use_bus_addr = true;
+- r = amdgpu_ih_ring_init(adev, &adev->irq.ih, 256 * 1024, use_bus_addr);
++ r = amdgpu_ih_ring_init(adev, &adev->irq.ih, IH_RING_SIZE, use_bus_addr);
+ if (r)
+ return r;
+
+@@ -578,7 +578,7 @@ static int navi10_ih_sw_init(void *handle)
+ /* initialize ih control registers offset */
+ navi10_ih_init_register_offset(adev);
+
+- r = amdgpu_ih_ring_init(adev, &adev->irq.ih_soft, PAGE_SIZE, true);
++ r = amdgpu_ih_ring_init(adev, &adev->irq.ih_soft, IH_SW_RING_SIZE, true);
+ if (r)
+ return r;
+
+diff --git a/drivers/gpu/drm/amd/amdgpu/vega10_ih.c b/drivers/gpu/drm/amd/amdgpu/vega10_ih.c
+index 1e83db0c5438d..d364c6dd152c3 100644
+--- a/drivers/gpu/drm/amd/amdgpu/vega10_ih.c
++++ b/drivers/gpu/drm/amd/amdgpu/vega10_ih.c
+@@ -485,7 +485,7 @@ static int vega10_ih_sw_init(void *handle)
+ if (r)
+ return r;
+
+- r = amdgpu_ih_ring_init(adev, &adev->irq.ih, 256 * 1024, true);
++ r = amdgpu_ih_ring_init(adev, &adev->irq.ih, IH_RING_SIZE, true);
+ if (r)
+ return r;
+
+@@ -510,7 +510,7 @@ static int vega10_ih_sw_init(void *handle)
+ /* initialize ih control registers offset */
+ vega10_ih_init_register_offset(adev);
+
+- r = amdgpu_ih_ring_init(adev, &adev->irq.ih_soft, PAGE_SIZE, true);
++ r = amdgpu_ih_ring_init(adev, &adev->irq.ih_soft, IH_SW_RING_SIZE, true);
+ if (r)
+ return r;
+
+diff --git a/drivers/gpu/drm/amd/amdgpu/vega20_ih.c b/drivers/gpu/drm/amd/amdgpu/vega20_ih.c
+index 4d719df376a72..544ee55a22da6 100644
+--- a/drivers/gpu/drm/amd/amdgpu/vega20_ih.c
++++ b/drivers/gpu/drm/amd/amdgpu/vega20_ih.c
+@@ -539,7 +539,7 @@ static int vega20_ih_sw_init(void *handle)
+ (adev->ip_versions[OSSSYS_HWIP][0] == IP_VERSION(4, 4, 2)))
+ use_bus_addr = false;
+
+- r = amdgpu_ih_ring_init(adev, &adev->irq.ih, 256 * 1024, use_bus_addr);
++ r = amdgpu_ih_ring_init(adev, &adev->irq.ih, IH_RING_SIZE, use_bus_addr);
+ if (r)
+ return r;
+
+@@ -565,7 +565,7 @@ static int vega20_ih_sw_init(void *handle)
+ /* initialize ih control registers offset */
+ vega20_ih_init_register_offset(adev);
+
+- r = amdgpu_ih_ring_init(adev, &adev->irq.ih_soft, PAGE_SIZE, use_bus_addr);
++ r = amdgpu_ih_ring_init(adev, &adev->irq.ih_soft, IH_SW_RING_SIZE, use_bus_addr);
+ if (r)
+ return r;
+
+--
+2.40.1
+
--- /dev/null
+From d36c4abee346da3e302b698be5bb6442c69bf621 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 18 Jul 2023 17:41:45 +0530
+Subject: drm/amdgpu: Update ring scheduler info as needed
+
+From: Lijo Lazar <lijo.lazar@amd.com>
+
+[ Upstream commit 6cb209ed68e45c8e4b71d97a037ac6b7dbce9b50 ]
+
+Not all rings have scheduler associated. Only update scheduler data for
+rings with scheduler. It could result in out of bound access as total
+rings are more than those associated with particular IPs.
+
+Signed-off-by: Lijo Lazar <lijo.lazar@amd.com>
+Reviewed-by: James Zhu <James.Zhu@amd.com>
+Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/gpu/drm/amd/amdgpu/aqua_vanjaram_reg_init.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/drivers/gpu/drm/amd/amdgpu/aqua_vanjaram_reg_init.c b/drivers/gpu/drm/amd/amdgpu/aqua_vanjaram_reg_init.c
+index 72b629a78c62c..d0fc62784e821 100644
+--- a/drivers/gpu/drm/amd/amdgpu/aqua_vanjaram_reg_init.c
++++ b/drivers/gpu/drm/amd/amdgpu/aqua_vanjaram_reg_init.c
+@@ -134,7 +134,7 @@ static int aqua_vanjaram_xcp_sched_list_update(
+
+ for (i = 0; i < AMDGPU_MAX_RINGS; i++) {
+ ring = adev->rings[i];
+- if (!ring || !ring->sched.ready)
++ if (!ring || !ring->sched.ready || ring->no_scheduler)
+ continue;
+
+ aqua_vanjaram_xcp_gpu_sched_update(adev, ring, ring->xcp_id);
+--
+2.40.1
+
--- /dev/null
+From f596948fa4c365dcd5ac905f960bfeb06b537f62 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 15 Jun 2023 22:15:11 +0200
+Subject: drm: bridge: samsung-dsim: Drain command transfer FIFO before
+ transfer
+
+From: Marek Vasut <marex@denx.de>
+
+[ Upstream commit 14806c6415820b1c4bc317655c40784d050a2edb ]
+
+Wait until the command transfer FIFO is empty before loading in the next
+command. The previous behavior where the code waited until command transfer
+FIFO was not full suffered from transfer corruption, where the last command
+in the FIFO could be overwritten in case the FIFO indicates not full, but
+also does not have enough space to store another transfer yet.
+
+Signed-off-by: Marek Vasut <marex@denx.de>
+Reviewed-by: Jagan Teki <jagan@amarulasolutions.com>
+Tested-by: Jagan Teki <jagan@amarulasolutions.com> # imx8mm-icore
+Link: https://patchwork.freedesktop.org/patch/msgid/20230615201511.565923-1-marex@denx.de
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/gpu/drm/bridge/samsung-dsim.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/drivers/gpu/drm/bridge/samsung-dsim.c b/drivers/gpu/drm/bridge/samsung-dsim.c
+index 73ec60757dbcb..9e253af69c7a1 100644
+--- a/drivers/gpu/drm/bridge/samsung-dsim.c
++++ b/drivers/gpu/drm/bridge/samsung-dsim.c
+@@ -1009,7 +1009,7 @@ static int samsung_dsim_wait_for_hdr_fifo(struct samsung_dsim *dsi)
+ do {
+ u32 reg = samsung_dsim_read(dsi, DSIM_FIFOCTRL_REG);
+
+- if (!(reg & DSIM_SFR_HEADER_FULL))
++ if (reg & DSIM_SFR_HEADER_EMPTY)
+ return 0;
+
+ if (!cond_resched())
+--
+2.40.1
+
--- /dev/null
+From b64c86d7842d48ce04dc6d2627efc973b8f7ae19 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 15 Jun 2023 22:19:00 +0200
+Subject: drm/bridge: tc358762: Instruct DSI host to generate HSE packets
+
+From: Marek Vasut <marex@denx.de>
+
+[ Upstream commit 362fa8f6e6a05089872809f4465bab9d011d05b3 ]
+
+This bridge seems to need the HSE packet, otherwise the image is
+shifted up and corrupted at the bottom. This makes the bridge
+work with Samsung DSIM on i.MX8MM and i.MX8MP.
+
+Signed-off-by: Marek Vasut <marex@denx.de>
+Reviewed-by: Sam Ravnborg <sam@ravnborg.org>
+Signed-off-by: Robert Foss <rfoss@kernel.org>
+Link: https://patchwork.freedesktop.org/patch/msgid/20230615201902.566182-3-marex@denx.de
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/gpu/drm/bridge/tc358762.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/drivers/gpu/drm/bridge/tc358762.c b/drivers/gpu/drm/bridge/tc358762.c
+index 5641395fd310e..11445c50956e1 100644
+--- a/drivers/gpu/drm/bridge/tc358762.c
++++ b/drivers/gpu/drm/bridge/tc358762.c
+@@ -231,7 +231,7 @@ static int tc358762_probe(struct mipi_dsi_device *dsi)
+ dsi->lanes = 1;
+ dsi->format = MIPI_DSI_FMT_RGB888;
+ dsi->mode_flags = MIPI_DSI_MODE_VIDEO | MIPI_DSI_MODE_VIDEO_SYNC_PULSE |
+- MIPI_DSI_MODE_LPM;
++ MIPI_DSI_MODE_LPM | MIPI_DSI_MODE_VIDEO_HSE;
+
+ ret = tc358762_parse_dt(ctx);
+ if (ret < 0)
+--
+2.40.1
+
--- /dev/null
+From 63d43d875b36d570496512239700d3cb59551663 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 20 Jun 2023 23:19:03 -0700
+Subject: drm/edid: Add quirk for OSVR HDK 2.0
+
+From: Ralph Campbell <rcampbell@nvidia.com>
+
+[ Upstream commit 98d4cb705bc00afd4a9a71cc1e84f7111682639a ]
+
+The OSVR virtual reality headset HDK 2.0 uses a different EDID
+vendor and device identifier than the HDK 1.1 - 1.4 headsets.
+Add the HDK 2.0 vendor and device identifier to the quirks table so
+that window managers do not try to display the desktop screen on the
+headset display.
+
+Closes: https://gitlab.freedesktop.org/drm/misc/-/issues/30
+Signed-off-by: Ralph Campbell <rcampbell@nvidia.com>
+Tested-by: Ralph Campbell <rcampbell@nvidia.com>
+Signed-off-by: Jani Nikula <jani.nikula@intel.com>
+Link: https://patchwork.freedesktop.org/patch/msgid/20230621061903.3422648-1-rcampbell@nvidia.com
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/gpu/drm/drm_edid.c | 1 +
+ 1 file changed, 1 insertion(+)
+
+diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c
+index 1f470968ed14b..9271e47d66572 100644
+--- a/drivers/gpu/drm/drm_edid.c
++++ b/drivers/gpu/drm/drm_edid.c
+@@ -230,6 +230,7 @@ static const struct edid_quirk {
+
+ /* OSVR HDK and HDK2 VR Headsets */
+ EDID_QUIRK('S', 'V', 'R', 0x1019, EDID_QUIRK_NON_DESKTOP),
++ EDID_QUIRK('A', 'U', 'O', 0x1111, EDID_QUIRK_NON_DESKTOP),
+ };
+
+ /*
+--
+2.40.1
+
--- /dev/null
+From 5909398d89ede573510295f6e0b6db5dedfd1c1c Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 30 Jun 2023 10:19:06 +0800
+Subject: drm/exynos: fix a possible null-pointer dereference due to data race
+ in exynos_drm_crtc_atomic_disable()
+
+From: Tuo Li <islituo@gmail.com>
+
+[ Upstream commit 2e63972a2de14482d0eae1a03a73e379f1c3f44c ]
+
+The variable crtc->state->event is often protected by the lock
+crtc->dev->event_lock when is accessed. However, it is accessed as a
+condition of an if statement in exynos_drm_crtc_atomic_disable() without
+holding the lock:
+
+ if (crtc->state->event && !crtc->state->active)
+
+However, if crtc->state->event is changed to NULL by another thread right
+after the conditions of the if statement is checked to be true, a
+null-pointer dereference can occur in drm_crtc_send_vblank_event():
+
+ e->pipe = pipe;
+
+To fix this possible null-pointer dereference caused by data race, the
+spin lock coverage is extended to protect the if statement as well as the
+function call to drm_crtc_send_vblank_event().
+
+Reported-by: BassCheck <bass@buaa.edu.cn>
+Link: https://sites.google.com/view/basscheck/home
+Signed-off-by: Tuo Li <islituo@gmail.com>
+Reviewed-by: Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
+Added relevant link.
+Signed-off-by: Inki Dae <inki.dae@samsung.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/gpu/drm/exynos/exynos_drm_crtc.c | 5 ++---
+ 1 file changed, 2 insertions(+), 3 deletions(-)
+
+diff --git a/drivers/gpu/drm/exynos/exynos_drm_crtc.c b/drivers/gpu/drm/exynos/exynos_drm_crtc.c
+index 4153f302de7c4..d19e796c20613 100644
+--- a/drivers/gpu/drm/exynos/exynos_drm_crtc.c
++++ b/drivers/gpu/drm/exynos/exynos_drm_crtc.c
+@@ -39,13 +39,12 @@ static void exynos_drm_crtc_atomic_disable(struct drm_crtc *crtc,
+ if (exynos_crtc->ops->atomic_disable)
+ exynos_crtc->ops->atomic_disable(exynos_crtc);
+
++ spin_lock_irq(&crtc->dev->event_lock);
+ if (crtc->state->event && !crtc->state->active) {
+- spin_lock_irq(&crtc->dev->event_lock);
+ drm_crtc_send_vblank_event(crtc, crtc->state->event);
+- spin_unlock_irq(&crtc->dev->event_lock);
+-
+ crtc->state->event = NULL;
+ }
++ spin_unlock_irq(&crtc->dev->event_lock);
+ }
+
+ static int exynos_crtc_atomic_check(struct drm_crtc *crtc,
+--
+2.40.1
+
--- /dev/null
+From 89147983e2128e96a42a596af1f0b52abdb1fa2d Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 4 Sep 2023 10:14:20 +0800
+Subject: drm: gm12u320: Fix the timeout usage for usb_bulk_msg()
+
+From: Jinjie Ruan <ruanjinjie@huawei.com>
+
+[ Upstream commit 7583028d359db3cd0072badcc576b4f9455fd27a ]
+
+The timeout arg of usb_bulk_msg() is ms already, which has been converted
+to jiffies by msecs_to_jiffies() in usb_start_wait_urb(). So fix the usage
+by removing the redundant msecs_to_jiffies() in the macros.
+
+And as Hans suggested, also remove msecs_to_jiffies() for the IDLE_TIMEOUT
+macro to make it consistent here and so change IDLE_TIMEOUT to
+msecs_to_jiffies(IDLE_TIMEOUT) where it is used.
+
+Fixes: e4f86e437164 ("drm: Add Grain Media GM12U320 driver v2")
+Signed-off-by: Jinjie Ruan <ruanjinjie@huawei.com>
+Suggested-by: Hans de Goede <hdegoede@redhat.com>
+Reviewed-by: Hans de Goede <hdegoede@redhat.com>
+Signed-off-by: Thomas Zimmermann <tzimmermann@suse.de>
+Link: https://patchwork.freedesktop.org/patch/msgid/20230904021421.1663892-1-ruanjinjie@huawei.com
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/gpu/drm/tiny/gm12u320.c | 10 +++++-----
+ 1 file changed, 5 insertions(+), 5 deletions(-)
+
+diff --git a/drivers/gpu/drm/tiny/gm12u320.c b/drivers/gpu/drm/tiny/gm12u320.c
+index c5bb683e440c5..0187539ff5eaa 100644
+--- a/drivers/gpu/drm/tiny/gm12u320.c
++++ b/drivers/gpu/drm/tiny/gm12u320.c
+@@ -70,10 +70,10 @@ MODULE_PARM_DESC(eco_mode, "Turn on Eco mode (less bright, more silent)");
+ #define READ_STATUS_SIZE 13
+ #define MISC_VALUE_SIZE 4
+
+-#define CMD_TIMEOUT msecs_to_jiffies(200)
+-#define DATA_TIMEOUT msecs_to_jiffies(1000)
+-#define IDLE_TIMEOUT msecs_to_jiffies(2000)
+-#define FIRST_FRAME_TIMEOUT msecs_to_jiffies(2000)
++#define CMD_TIMEOUT 200
++#define DATA_TIMEOUT 1000
++#define IDLE_TIMEOUT 2000
++#define FIRST_FRAME_TIMEOUT 2000
+
+ #define MISC_REQ_GET_SET_ECO_A 0xff
+ #define MISC_REQ_GET_SET_ECO_B 0x35
+@@ -389,7 +389,7 @@ static void gm12u320_fb_update_work(struct work_struct *work)
+ * switches back to showing its logo.
+ */
+ queue_delayed_work(system_long_wq, &gm12u320->fb_update.work,
+- IDLE_TIMEOUT);
++ msecs_to_jiffies(IDLE_TIMEOUT));
+
+ return;
+ err:
+--
+2.40.1
+
--- /dev/null
+From 16b726fd8e949d1a1030e5ebd7716243b5a3fdc8 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 25 Jul 2023 09:32:26 +0200
+Subject: drm/mediatek: dp: Change logging to dev for mtk_dp_aux_transfer()
+
+From: AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
+
+[ Upstream commit fd70e2019bfbcb0ed90c5e23839bf510ce6acf8f ]
+
+Change logging from drm_{err,info}() to dev_{err,info}() in functions
+mtk_dp_aux_transfer() and mtk_dp_aux_do_transfer(): this will be
+essential to avoid getting NULL pointer kernel panics if any kind
+of error happens during AUX transfers happening before the bridge
+is attached.
+
+This may potentially start happening in a later commit implementing
+aux-bus support, as AUX transfers will be triggered from the panel
+driver (for EDID) before the mtk-dp bridge gets attached, and it's
+done in preparation for the same.
+
+Signed-off-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
+Tested-by: Chen-Yu Tsai <wenst@chromium.org>
+Reviewed-by: CK Hu <ck.hu@mediatek.com>
+Reviewed-by: Alexandre Mergnat <amergnat@baylibre.com>
+Link: https://patchwork.kernel.org/project/dri-devel/patch/20230725073234.55892-4-angelogioacchino.delregno@collabora.com/
+Signed-off-by: Chun-Kuang Hu <chunkuang.hu@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/gpu/drm/mediatek/mtk_dp.c | 6 +++---
+ 1 file changed, 3 insertions(+), 3 deletions(-)
+
+diff --git a/drivers/gpu/drm/mediatek/mtk_dp.c b/drivers/gpu/drm/mediatek/mtk_dp.c
+index c58b775877a31..076aa54910571 100644
+--- a/drivers/gpu/drm/mediatek/mtk_dp.c
++++ b/drivers/gpu/drm/mediatek/mtk_dp.c
+@@ -847,7 +847,7 @@ static int mtk_dp_aux_do_transfer(struct mtk_dp *mtk_dp, bool is_read, u8 cmd,
+ u32 phy_status = mtk_dp_read(mtk_dp, MTK_DP_AUX_P0_3628) &
+ AUX_RX_PHY_STATE_AUX_TX_P0_MASK;
+ if (phy_status != AUX_RX_PHY_STATE_AUX_TX_P0_RX_IDLE) {
+- drm_err(mtk_dp->drm_dev,
++ dev_err(mtk_dp->dev,
+ "AUX Rx Aux hang, need SW reset\n");
+ return -EIO;
+ }
+@@ -2062,7 +2062,7 @@ static ssize_t mtk_dp_aux_transfer(struct drm_dp_aux *mtk_aux,
+ is_read = true;
+ break;
+ default:
+- drm_err(mtk_aux->drm_dev, "invalid aux cmd = %d\n",
++ dev_err(mtk_dp->dev, "invalid aux cmd = %d\n",
+ msg->request);
+ ret = -EINVAL;
+ goto err;
+@@ -2078,7 +2078,7 @@ static ssize_t mtk_dp_aux_transfer(struct drm_dp_aux *mtk_aux,
+ to_access, &msg->reply);
+
+ if (ret) {
+- drm_info(mtk_dp->drm_dev,
++ dev_info(mtk_dp->dev,
+ "Failed to do AUX transfer: %d\n", ret);
+ goto err;
+ }
+--
+2.40.1
+
--- /dev/null
+From eb1bc3fd1565469ea560183057e85baa239dd78c Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 27 Jul 2023 14:20:09 -0700
+Subject: drm/msm/adreno: Use quirk identify hw_apriv
+
+From: Rob Clark <robdclark@chromium.org>
+
+[ Upstream commit 459f9e26e7d49f80f587d7592ccb78e00ab458e4 ]
+
+Rather than just open coding a list of gpu-id matches.
+
+Signed-off-by: Rob Clark <robdclark@chromium.org>
+Reviewed-by: Konrad Dybcio <konrad.dybcio@linaro.org>
+Reviewed-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
+Patchwork: https://patchwork.freedesktop.org/patch/549764/
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/gpu/drm/msm/adreno/a6xx_gpu.c | 3 +--
+ drivers/gpu/drm/msm/adreno/adreno_device.c | 4 ++++
+ drivers/gpu/drm/msm/adreno/adreno_gpu.h | 1 +
+ 3 files changed, 6 insertions(+), 2 deletions(-)
+
+diff --git a/drivers/gpu/drm/msm/adreno/a6xx_gpu.c b/drivers/gpu/drm/msm/adreno/a6xx_gpu.c
+index a2513f7168238..f6c6147640173 100644
+--- a/drivers/gpu/drm/msm/adreno/a6xx_gpu.c
++++ b/drivers/gpu/drm/msm/adreno/a6xx_gpu.c
+@@ -2489,8 +2489,7 @@ struct msm_gpu *a6xx_gpu_init(struct drm_device *dev)
+ /* Quirk data */
+ adreno_gpu->info = info;
+
+- if (adreno_is_a650(adreno_gpu) || adreno_is_a660_family(adreno_gpu))
+- adreno_gpu->base.hw_apriv = true;
++ adreno_gpu->base.hw_apriv = !!(info->quirks & ADRENO_QUIRK_HAS_HW_APRIV);
+
+ a6xx_llc_slices_init(pdev, a6xx_gpu);
+
+diff --git a/drivers/gpu/drm/msm/adreno/adreno_device.c b/drivers/gpu/drm/msm/adreno/adreno_device.c
+index 6e3c1368c5e15..41bccf6009fb6 100644
+--- a/drivers/gpu/drm/msm/adreno/adreno_device.c
++++ b/drivers/gpu/drm/msm/adreno/adreno_device.c
+@@ -325,6 +325,7 @@ static const struct adreno_info gpulist[] = {
+ },
+ .gmem = SZ_1M + SZ_128K,
+ .inactive_period = DRM_MSM_INACTIVE_PERIOD,
++ .quirks = ADRENO_QUIRK_HAS_HW_APRIV,
+ .init = a6xx_gpu_init,
+ .zapfw = "a650_zap.mdt",
+ .hwcg = a650_hwcg,
+@@ -339,6 +340,7 @@ static const struct adreno_info gpulist[] = {
+ },
+ .gmem = SZ_1M + SZ_512K,
+ .inactive_period = DRM_MSM_INACTIVE_PERIOD,
++ .quirks = ADRENO_QUIRK_HAS_HW_APRIV,
+ .init = a6xx_gpu_init,
+ .zapfw = "a660_zap.mdt",
+ .hwcg = a660_hwcg,
+@@ -351,6 +353,7 @@ static const struct adreno_info gpulist[] = {
+ },
+ .gmem = SZ_512K,
+ .inactive_period = DRM_MSM_INACTIVE_PERIOD,
++ .quirks = ADRENO_QUIRK_HAS_HW_APRIV,
+ .init = a6xx_gpu_init,
+ .hwcg = a660_hwcg,
+ .address_space_size = SZ_16G,
+@@ -375,6 +378,7 @@ static const struct adreno_info gpulist[] = {
+ },
+ .gmem = SZ_4M,
+ .inactive_period = DRM_MSM_INACTIVE_PERIOD,
++ .quirks = ADRENO_QUIRK_HAS_HW_APRIV,
+ .init = a6xx_gpu_init,
+ .zapfw = "a690_zap.mdt",
+ .hwcg = a690_hwcg,
+diff --git a/drivers/gpu/drm/msm/adreno/adreno_gpu.h b/drivers/gpu/drm/msm/adreno/adreno_gpu.h
+index 845019891ad19..a925e04a2283c 100644
+--- a/drivers/gpu/drm/msm/adreno/adreno_gpu.h
++++ b/drivers/gpu/drm/msm/adreno/adreno_gpu.h
+@@ -32,6 +32,7 @@ enum {
+ #define ADRENO_QUIRK_TWO_PASS_USE_WFI BIT(0)
+ #define ADRENO_QUIRK_FAULT_DETECT_MASK BIT(1)
+ #define ADRENO_QUIRK_LMLOADKILL_DISABLE BIT(2)
++#define ADRENO_QUIRK_HAS_HW_APRIV BIT(3)
+
+ struct adreno_rev {
+ uint8_t core;
+--
+2.40.1
+
--- /dev/null
+From c64a6b79ed4daacc215ec3a30f7231a340310e64 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 27 Jul 2023 14:20:10 -0700
+Subject: drm/msm/adreno: Use quirk to identify cached-coherent support
+
+From: Rob Clark <robdclark@chromium.org>
+
+[ Upstream commit 155668ef412fc82ff3172666831d95770141cdd6 ]
+
+It is better to explicitly list it. With the move to opaque chip-id's
+for future devices, we should avoid trying to infer things like
+generation from the numerical value.
+
+Signed-off-by: Rob Clark <robdclark@chromium.org>
+Reviewed-by: Konrad Dybcio <konrad.dybcio@linaro.org>
+Reviewed-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
+Patchwork: https://patchwork.freedesktop.org/patch/549765/
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/gpu/drm/msm/adreno/adreno_device.c | 23 +++++++++++++++-------
+ drivers/gpu/drm/msm/adreno/adreno_gpu.h | 1 +
+ 2 files changed, 17 insertions(+), 7 deletions(-)
+
+diff --git a/drivers/gpu/drm/msm/adreno/adreno_device.c b/drivers/gpu/drm/msm/adreno/adreno_device.c
+index 41bccf6009fb6..b2283faa173ac 100644
+--- a/drivers/gpu/drm/msm/adreno/adreno_device.c
++++ b/drivers/gpu/drm/msm/adreno/adreno_device.c
+@@ -275,6 +275,7 @@ static const struct adreno_info gpulist[] = {
+ },
+ .gmem = SZ_512K,
+ .inactive_period = DRM_MSM_INACTIVE_PERIOD,
++ .quirks = ADRENO_QUIRK_HAS_CACHED_COHERENT,
+ .init = a6xx_gpu_init,
+ }, {
+ .rev = ADRENO_REV(6, 1, 9, ANY_ID),
+@@ -286,6 +287,7 @@ static const struct adreno_info gpulist[] = {
+ },
+ .gmem = SZ_512K,
+ .inactive_period = DRM_MSM_INACTIVE_PERIOD,
++ .quirks = ADRENO_QUIRK_HAS_CACHED_COHERENT,
+ .init = a6xx_gpu_init,
+ .zapfw = "a615_zap.mdt",
+ .hwcg = a615_hwcg,
+@@ -299,6 +301,7 @@ static const struct adreno_info gpulist[] = {
+ },
+ .gmem = SZ_1M,
+ .inactive_period = DRM_MSM_INACTIVE_PERIOD,
++ .quirks = ADRENO_QUIRK_HAS_CACHED_COHERENT,
+ .init = a6xx_gpu_init,
+ .zapfw = "a630_zap.mdt",
+ .hwcg = a630_hwcg,
+@@ -312,6 +315,7 @@ static const struct adreno_info gpulist[] = {
+ },
+ .gmem = SZ_1M,
+ .inactive_period = DRM_MSM_INACTIVE_PERIOD,
++ .quirks = ADRENO_QUIRK_HAS_CACHED_COHERENT,
+ .init = a6xx_gpu_init,
+ .zapfw = "a640_zap.mdt",
+ .hwcg = a640_hwcg,
+@@ -325,7 +329,8 @@ static const struct adreno_info gpulist[] = {
+ },
+ .gmem = SZ_1M + SZ_128K,
+ .inactive_period = DRM_MSM_INACTIVE_PERIOD,
+- .quirks = ADRENO_QUIRK_HAS_HW_APRIV,
++ .quirks = ADRENO_QUIRK_HAS_CACHED_COHERENT |
++ ADRENO_QUIRK_HAS_HW_APRIV,
+ .init = a6xx_gpu_init,
+ .zapfw = "a650_zap.mdt",
+ .hwcg = a650_hwcg,
+@@ -340,7 +345,8 @@ static const struct adreno_info gpulist[] = {
+ },
+ .gmem = SZ_1M + SZ_512K,
+ .inactive_period = DRM_MSM_INACTIVE_PERIOD,
+- .quirks = ADRENO_QUIRK_HAS_HW_APRIV,
++ .quirks = ADRENO_QUIRK_HAS_CACHED_COHERENT |
++ ADRENO_QUIRK_HAS_HW_APRIV,
+ .init = a6xx_gpu_init,
+ .zapfw = "a660_zap.mdt",
+ .hwcg = a660_hwcg,
+@@ -353,7 +359,8 @@ static const struct adreno_info gpulist[] = {
+ },
+ .gmem = SZ_512K,
+ .inactive_period = DRM_MSM_INACTIVE_PERIOD,
+- .quirks = ADRENO_QUIRK_HAS_HW_APRIV,
++ .quirks = ADRENO_QUIRK_HAS_CACHED_COHERENT |
++ ADRENO_QUIRK_HAS_HW_APRIV,
+ .init = a6xx_gpu_init,
+ .hwcg = a660_hwcg,
+ .address_space_size = SZ_16G,
+@@ -367,6 +374,7 @@ static const struct adreno_info gpulist[] = {
+ },
+ .gmem = SZ_2M,
+ .inactive_period = DRM_MSM_INACTIVE_PERIOD,
++ .quirks = ADRENO_QUIRK_HAS_CACHED_COHERENT,
+ .init = a6xx_gpu_init,
+ .zapfw = "a640_zap.mdt",
+ .hwcg = a640_hwcg,
+@@ -378,7 +386,8 @@ static const struct adreno_info gpulist[] = {
+ },
+ .gmem = SZ_4M,
+ .inactive_period = DRM_MSM_INACTIVE_PERIOD,
+- .quirks = ADRENO_QUIRK_HAS_HW_APRIV,
++ .quirks = ADRENO_QUIRK_HAS_CACHED_COHERENT |
++ ADRENO_QUIRK_HAS_HW_APRIV,
+ .init = a6xx_gpu_init,
+ .zapfw = "a690_zap.mdt",
+ .hwcg = a690_hwcg,
+@@ -590,9 +599,9 @@ static int adreno_bind(struct device *dev, struct device *master, void *data)
+ if (ret)
+ return ret;
+
+- if (config.rev.core >= 6)
+- if (!adreno_has_gmu_wrapper(to_adreno_gpu(gpu)))
+- priv->has_cached_coherent = true;
++ priv->has_cached_coherent =
++ !!(info->quirks & ADRENO_QUIRK_HAS_CACHED_COHERENT) &&
++ !adreno_has_gmu_wrapper(to_adreno_gpu(gpu));
+
+ return 0;
+ }
+diff --git a/drivers/gpu/drm/msm/adreno/adreno_gpu.h b/drivers/gpu/drm/msm/adreno/adreno_gpu.h
+index a925e04a2283c..129771563f3fd 100644
+--- a/drivers/gpu/drm/msm/adreno/adreno_gpu.h
++++ b/drivers/gpu/drm/msm/adreno/adreno_gpu.h
+@@ -33,6 +33,7 @@ enum {
+ #define ADRENO_QUIRK_FAULT_DETECT_MASK BIT(1)
+ #define ADRENO_QUIRK_LMLOADKILL_DISABLE BIT(2)
+ #define ADRENO_QUIRK_HAS_HW_APRIV BIT(3)
++#define ADRENO_QUIRK_HAS_CACHED_COHERENT BIT(4)
+
+ struct adreno_rev {
+ uint8_t core;
+--
+2.40.1
+
--- /dev/null
+From 9fc76127512229b74539276e0e7880beea85c0bf Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 16 Aug 2023 21:05:57 +0200
+Subject: efi/unaccepted: Use ACPI reclaim memory for unaccepted memory table
+
+From: Ard Biesheuvel <ardb@kernel.org>
+
+[ Upstream commit e7761d827e99919c32400056a884e481ef008ec4 ]
+
+Kyril reports that crashkernels fail to work on confidential VMs that
+rely on the unaccepted memory table, and this appears to be caused by
+the fact that it is not considered part of the set of firmware tables
+that the crashkernel needs to map.
+
+This is an oversight, and a result of the use of the EFI_LOADER_DATA
+memory type for this table. The correct memory type to use for any
+firmware table is EFI_ACPI_RECLAIM_MEMORY (including ones created by the
+EFI stub), even though the name suggests that is it specific to ACPI.
+ACPI reclaim means that the memory is used by the firmware to expose
+information to the operating system, but that the memory region has no
+special significance to the firmware itself, and the OS is free to
+reclaim the memory and use it as ordinary memory if it is not interested
+in the contents, or if it has already consumed them. In Linux, this
+memory is never reclaimed, but it is always covered by the kernel direct
+map and generally made accessible as ordinary memory.
+
+On x86, ACPI reclaim memory is translated into E820_ACPI, which the
+kexec logic already recognizes as memory that the crashkernel may need
+to to access, and so it will be mapped and accessible to the booting
+crash kernel.
+
+Fixes: 745e3ed85f71 ("efi/libstub: Implement support for unaccepted memory")
+Reported-by: Kirill A. Shutemov <kirill.shutemov@linux.intel.com>
+Signed-off-by: Ard Biesheuvel <ardb@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/firmware/efi/libstub/unaccepted_memory.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/drivers/firmware/efi/libstub/unaccepted_memory.c b/drivers/firmware/efi/libstub/unaccepted_memory.c
+index ca61f4733ea58..9a655f30ba47d 100644
+--- a/drivers/firmware/efi/libstub/unaccepted_memory.c
++++ b/drivers/firmware/efi/libstub/unaccepted_memory.c
+@@ -62,7 +62,7 @@ efi_status_t allocate_unaccepted_bitmap(__u32 nr_desc,
+ bitmap_size = DIV_ROUND_UP(unaccepted_end - unaccepted_start,
+ EFI_UNACCEPTED_UNIT_SIZE * BITS_PER_BYTE);
+
+- status = efi_bs_call(allocate_pool, EFI_LOADER_DATA,
++ status = efi_bs_call(allocate_pool, EFI_ACPI_RECLAIM_MEMORY,
+ sizeof(*unaccepted_table) + bitmap_size,
+ (void **)&unaccepted_table);
+ if (status != EFI_SUCCESS) {
+--
+2.40.1
+
--- /dev/null
+From 5b822d83e40e1b537c7d5f9aca1e6d45d235c0c6 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sun, 10 Sep 2023 06:54:45 +0200
+Subject: efivarfs: fix statfs() on efivarfs
+
+From: Heinrich Schuchardt <heinrich.schuchardt@canonical.com>
+
+[ Upstream commit 79b83606abc778aa3cbee535b362ce905d0b9448 ]
+
+Some firmware (notably U-Boot) provides GetVariable() and
+GetNextVariableName() but not QueryVariableInfo().
+
+With commit d86ff3333cb1 ("efivarfs: expose used and total size") the
+statfs syscall was broken for such firmware.
+
+If QueryVariableInfo() does not exist or returns EFI_UNSUPPORTED, just
+report the file system size as 0 as statfs_simple() previously did.
+
+Fixes: d86ff3333cb1 ("efivarfs: expose used and total size")
+Link: https://lore.kernel.org/all/20230910045445.41632-1-heinrich.schuchardt@canonical.com/
+Signed-off-by: Heinrich Schuchardt <heinrich.schuchardt@canonical.com>
+[ardb: log warning on QueryVariableInfo() failure]
+Reviewed-by: Ilias Apalodimas <ilias.apalodimas@linaro.org>
+Signed-off-by: Ard Biesheuvel <ardb@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ fs/efivarfs/super.c | 14 ++++++++++----
+ 1 file changed, 10 insertions(+), 4 deletions(-)
+
+diff --git a/fs/efivarfs/super.c b/fs/efivarfs/super.c
+index e028fafa04f38..996271473609a 100644
+--- a/fs/efivarfs/super.c
++++ b/fs/efivarfs/super.c
+@@ -32,10 +32,16 @@ static int efivarfs_statfs(struct dentry *dentry, struct kstatfs *buf)
+ u64 storage_space, remaining_space, max_variable_size;
+ efi_status_t status;
+
+- status = efivar_query_variable_info(attr, &storage_space, &remaining_space,
+- &max_variable_size);
+- if (status != EFI_SUCCESS)
+- return efi_status_to_err(status);
++ /* Some UEFI firmware does not implement QueryVariableInfo() */
++ storage_space = remaining_space = 0;
++ if (efi_rt_services_supported(EFI_RT_SUPPORTED_QUERY_VARIABLE_INFO)) {
++ status = efivar_query_variable_info(attr, &storage_space,
++ &remaining_space,
++ &max_variable_size);
++ if (status != EFI_SUCCESS && status != EFI_UNSUPPORTED)
++ pr_warn_ratelimited("query_variable_info() failed: 0x%lx\n",
++ status);
++ }
+
+ /*
+ * This is not a normal filesystem, so no point in pretending it has a block
+--
+2.40.1
+
--- /dev/null
+From 093427c9ed7b436520d43af315a7edc30a0826d5 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 15 Aug 2023 12:03:40 +0200
+Subject: ext2: fix datatype of block number in ext2_xattr_set2()
+
+From: Georg Ottinger <g.ottinger@gmx.at>
+
+[ Upstream commit e88076348425b7d0491c8c98d8732a7df8de7aa3 ]
+
+I run a small server that uses external hard drives for backups. The
+backup software I use uses ext2 filesystems with 4KiB block size and
+the server is running SELinux and therefore relies on xattr. I recently
+upgraded the hard drives from 4TB to 12TB models. I noticed that after
+transferring some TBs I got a filesystem error "Freeing blocks not in
+datazone - block = 18446744071529317386, count = 1" and the backup
+process stopped. Trying to fix the fs with e2fsck resulted in a
+completely corrupted fs. The error probably came from ext2_free_blocks(),
+and because of the large number 18e19 this problem immediately looked
+like some kind of integer overflow. Whereas the 4TB fs was about 1e9
+blocks, the new 12TB is about 3e9 blocks. So, searching the ext2 code,
+I came across the line in fs/ext2/xattr.c:745 where ext2_new_block()
+is called and the resulting block number is stored in the variable block
+as an int datatype. If a block with a block number greater than
+INT32_MAX is returned, this variable overflows and the call to
+sb_getblk() at line fs/ext2/xattr.c:750 fails, then the call to
+ext2_free_blocks() produces the error.
+
+Signed-off-by: Georg Ottinger <g.ottinger@gmx.at>
+Signed-off-by: Jan Kara <jack@suse.cz>
+Message-Id: <20230815100340.22121-1-g.ottinger@gmx.at>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ fs/ext2/xattr.c | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/fs/ext2/xattr.c b/fs/ext2/xattr.c
+index 8906ba479aafb..89517937d36c4 100644
+--- a/fs/ext2/xattr.c
++++ b/fs/ext2/xattr.c
+@@ -742,10 +742,10 @@ ext2_xattr_set2(struct inode *inode, struct buffer_head *old_bh,
+ /* We need to allocate a new block */
+ ext2_fsblk_t goal = ext2_group_first_block_no(sb,
+ EXT2_I(inode)->i_block_group);
+- int block = ext2_new_block(inode, goal, &error);
++ ext2_fsblk_t block = ext2_new_block(inode, goal, &error);
+ if (error)
+ goto cleanup;
+- ea_idebug(inode, "creating block %d", block);
++ ea_idebug(inode, "creating block %lu", block);
+
+ new_bh = sb_getblk(sb, block);
+ if (unlikely(!new_bh)) {
+--
+2.40.1
+
--- /dev/null
+From fe6f11874433799f3964a59aae0283140898d017 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 24 Jul 2023 20:10:57 +0800
+Subject: ext4: add two helper functions extent_logical_end() and
+ pa_logical_end()
+
+From: Baokun Li <libaokun1@huawei.com>
+
+[ Upstream commit 43bbddc067883d94de7a43d5756a295439fbe37d ]
+
+When we use lstart + len to calculate the end of free extent or prealloc
+space, it may exceed the maximum value of 4294967295(0xffffffff) supported
+by ext4_lblk_t and cause overflow, which may lead to various problems.
+
+Therefore, we add two helper functions, extent_logical_end() and
+pa_logical_end(), to limit the type of end to loff_t, and also convert
+lstart to loff_t for calculation to avoid overflow.
+
+Signed-off-by: Baokun Li <libaokun1@huawei.com>
+Reviewed-by: Ritesh Harjani (IBM) <ritesh.list@gmail.com>
+Link: https://lore.kernel.org/r/20230724121059.11834-2-libaokun1@huawei.com
+Signed-off-by: Theodore Ts'o <tytso@mit.edu>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ fs/ext4/mballoc.c | 9 +++------
+ fs/ext4/mballoc.h | 14 ++++++++++++++
+ 2 files changed, 17 insertions(+), 6 deletions(-)
+
+diff --git a/fs/ext4/mballoc.c b/fs/ext4/mballoc.c
+index a197ef71b7b02..627c813cf0759 100644
+--- a/fs/ext4/mballoc.c
++++ b/fs/ext4/mballoc.c
+@@ -4433,7 +4433,7 @@ ext4_mb_normalize_request(struct ext4_allocation_context *ac,
+
+ /* first, let's learn actual file size
+ * given current request is allocated */
+- size = ac->ac_o_ex.fe_logical + EXT4_C2B(sbi, ac->ac_o_ex.fe_len);
++ size = extent_logical_end(sbi, &ac->ac_o_ex);
+ size = size << bsbits;
+ if (size < i_size_read(ac->ac_inode))
+ size = i_size_read(ac->ac_inode);
+@@ -4767,7 +4767,6 @@ ext4_mb_use_preallocated(struct ext4_allocation_context *ac)
+ struct ext4_inode_info *ei = EXT4_I(ac->ac_inode);
+ struct ext4_locality_group *lg;
+ struct ext4_prealloc_space *tmp_pa = NULL, *cpa = NULL;
+- loff_t tmp_pa_end;
+ struct rb_node *iter;
+ ext4_fsblk_t goal_block;
+
+@@ -4863,9 +4862,7 @@ ext4_mb_use_preallocated(struct ext4_allocation_context *ac)
+ * pa can possibly satisfy the request hence check if it overlaps
+ * original logical start and stop searching if it doesn't.
+ */
+- tmp_pa_end = (loff_t)tmp_pa->pa_lstart + EXT4_C2B(sbi, tmp_pa->pa_len);
+-
+- if (ac->ac_o_ex.fe_logical >= tmp_pa_end) {
++ if (ac->ac_o_ex.fe_logical >= pa_logical_end(sbi, tmp_pa)) {
+ spin_unlock(&tmp_pa->pa_lock);
+ goto try_group_pa;
+ }
+@@ -5770,7 +5767,7 @@ static void ext4_mb_group_or_file(struct ext4_allocation_context *ac)
+
+ group_pa_eligible = sbi->s_mb_group_prealloc > 0;
+ inode_pa_eligible = true;
+- size = ac->ac_o_ex.fe_logical + EXT4_C2B(sbi, ac->ac_o_ex.fe_len);
++ size = extent_logical_end(sbi, &ac->ac_o_ex);
+ isize = (i_size_read(ac->ac_inode) + ac->ac_sb->s_blocksize - 1)
+ >> bsbits;
+
+diff --git a/fs/ext4/mballoc.h b/fs/ext4/mballoc.h
+index df6b5e7c22741..d7aeb5da7d867 100644
+--- a/fs/ext4/mballoc.h
++++ b/fs/ext4/mballoc.h
+@@ -233,6 +233,20 @@ static inline ext4_fsblk_t ext4_grp_offs_to_block(struct super_block *sb,
+ (fex->fe_start << EXT4_SB(sb)->s_cluster_bits);
+ }
+
++static inline loff_t extent_logical_end(struct ext4_sb_info *sbi,
++ struct ext4_free_extent *fex)
++{
++ /* Use loff_t to avoid end exceeding ext4_lblk_t max. */
++ return (loff_t)fex->fe_logical + EXT4_C2B(sbi, fex->fe_len);
++}
++
++static inline loff_t pa_logical_end(struct ext4_sb_info *sbi,
++ struct ext4_prealloc_space *pa)
++{
++ /* Use loff_t to avoid end exceeding ext4_lblk_t max. */
++ return (loff_t)pa->pa_lstart + EXT4_C2B(sbi, pa->pa_len);
++}
++
+ typedef int (*ext4_mballoc_query_range_fn)(
+ struct super_block *sb,
+ ext4_group_t agno,
+--
+2.40.1
+
--- /dev/null
+From 0452d65101de63b63569eeb8aed51334fb5c4008 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 24 Jul 2023 20:10:59 +0800
+Subject: ext4: avoid overlapping preallocations due to overflow
+
+From: Baokun Li <libaokun1@huawei.com>
+
+[ Upstream commit bedc5d34632c21b5adb8ca7143d4c1f794507e4c ]
+
+Let's say we want to allocate 2 blocks starting from 4294966386, after
+predicting the file size, start is aligned to 4294965248, len is changed
+to 2048, then end = start + size = 0x100000000. Since end is of
+type ext4_lblk_t, i.e. uint, end is truncated to 0.
+
+This causes (pa->pa_lstart >= end) to always hold when checking if the
+current extent to be allocated crosses already preallocated blocks, so the
+resulting ac_g_ex may cross already preallocated blocks. Hence we convert
+the end type to loff_t and use pa_logical_end() to avoid overflow.
+
+Signed-off-by: Baokun Li <libaokun1@huawei.com>
+Reviewed-by: Ritesh Harjani (IBM) <ritesh.list@gmail.com>
+Link: https://lore.kernel.org/r/20230724121059.11834-4-libaokun1@huawei.com
+Signed-off-by: Theodore Ts'o <tytso@mit.edu>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ fs/ext4/mballoc.c | 21 ++++++++++-----------
+ 1 file changed, 10 insertions(+), 11 deletions(-)
+
+diff --git a/fs/ext4/mballoc.c b/fs/ext4/mballoc.c
+index 627c813cf0759..5c3055a32e57a 100644
+--- a/fs/ext4/mballoc.c
++++ b/fs/ext4/mballoc.c
+@@ -4223,12 +4223,13 @@ ext4_mb_pa_rb_next_iter(ext4_lblk_t new_start, ext4_lblk_t cur_start, struct rb_
+
+ static inline void
+ ext4_mb_pa_assert_overlap(struct ext4_allocation_context *ac,
+- ext4_lblk_t start, ext4_lblk_t end)
++ ext4_lblk_t start, loff_t end)
+ {
+ struct ext4_sb_info *sbi = EXT4_SB(ac->ac_sb);
+ struct ext4_inode_info *ei = EXT4_I(ac->ac_inode);
+ struct ext4_prealloc_space *tmp_pa;
+- ext4_lblk_t tmp_pa_start, tmp_pa_end;
++ ext4_lblk_t tmp_pa_start;
++ loff_t tmp_pa_end;
+ struct rb_node *iter;
+
+ read_lock(&ei->i_prealloc_lock);
+@@ -4237,7 +4238,7 @@ ext4_mb_pa_assert_overlap(struct ext4_allocation_context *ac,
+ tmp_pa = rb_entry(iter, struct ext4_prealloc_space,
+ pa_node.inode_node);
+ tmp_pa_start = tmp_pa->pa_lstart;
+- tmp_pa_end = tmp_pa->pa_lstart + EXT4_C2B(sbi, tmp_pa->pa_len);
++ tmp_pa_end = pa_logical_end(sbi, tmp_pa);
+
+ spin_lock(&tmp_pa->pa_lock);
+ if (tmp_pa->pa_deleted == 0)
+@@ -4259,14 +4260,14 @@ ext4_mb_pa_assert_overlap(struct ext4_allocation_context *ac,
+ */
+ static inline void
+ ext4_mb_pa_adjust_overlap(struct ext4_allocation_context *ac,
+- ext4_lblk_t *start, ext4_lblk_t *end)
++ ext4_lblk_t *start, loff_t *end)
+ {
+ struct ext4_inode_info *ei = EXT4_I(ac->ac_inode);
+ struct ext4_sb_info *sbi = EXT4_SB(ac->ac_sb);
+ struct ext4_prealloc_space *tmp_pa = NULL, *left_pa = NULL, *right_pa = NULL;
+ struct rb_node *iter;
+- ext4_lblk_t new_start, new_end;
+- ext4_lblk_t tmp_pa_start, tmp_pa_end, left_pa_end = -1, right_pa_start = -1;
++ ext4_lblk_t new_start, tmp_pa_start, right_pa_start = -1;
++ loff_t new_end, tmp_pa_end, left_pa_end = -1;
+
+ new_start = *start;
+ new_end = *end;
+@@ -4285,7 +4286,7 @@ ext4_mb_pa_adjust_overlap(struct ext4_allocation_context *ac,
+ tmp_pa = rb_entry(iter, struct ext4_prealloc_space,
+ pa_node.inode_node);
+ tmp_pa_start = tmp_pa->pa_lstart;
+- tmp_pa_end = tmp_pa->pa_lstart + EXT4_C2B(sbi, tmp_pa->pa_len);
++ tmp_pa_end = pa_logical_end(sbi, tmp_pa);
+
+ /* PA must not overlap original request */
+ spin_lock(&tmp_pa->pa_lock);
+@@ -4365,8 +4366,7 @@ ext4_mb_pa_adjust_overlap(struct ext4_allocation_context *ac,
+ }
+
+ if (left_pa) {
+- left_pa_end =
+- left_pa->pa_lstart + EXT4_C2B(sbi, left_pa->pa_len);
++ left_pa_end = pa_logical_end(sbi, left_pa);
+ BUG_ON(left_pa_end > ac->ac_o_ex.fe_logical);
+ }
+
+@@ -4405,8 +4405,7 @@ ext4_mb_normalize_request(struct ext4_allocation_context *ac,
+ struct ext4_sb_info *sbi = EXT4_SB(ac->ac_sb);
+ struct ext4_super_block *es = sbi->s_es;
+ int bsbits, max;
+- ext4_lblk_t end;
+- loff_t size, start_off;
++ loff_t size, start_off, end;
+ loff_t orig_size __maybe_unused;
+ ext4_lblk_t start;
+
+--
+2.40.1
+
--- /dev/null
+From b519bdc661be04e28785821a7032a84f11ce5d36 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 24 Jul 2023 20:10:58 +0800
+Subject: ext4: fix BUG in ext4_mb_new_inode_pa() due to overflow
+
+From: Baokun Li <libaokun1@huawei.com>
+
+[ Upstream commit bc056e7163ac7db945366de219745cf94f32a3e6 ]
+
+When we calculate the end position of ext4_free_extent, this position may
+be exactly where ext4_lblk_t (i.e. uint) overflows. For example, if
+ac_g_ex.fe_logical is 4294965248 and ac_orig_goal_len is 2048, then the
+computed end is 0x100000000, which is 0. If ac->ac_o_ex.fe_logical is not
+the first case of adjusting the best extent, that is, new_bex_end > 0, the
+following BUG_ON will be triggered:
+
+=========================================================
+kernel BUG at fs/ext4/mballoc.c:5116!
+invalid opcode: 0000 [#1] PREEMPT SMP PTI
+CPU: 3 PID: 673 Comm: xfs_io Tainted: G E 6.5.0-rc1+ #279
+RIP: 0010:ext4_mb_new_inode_pa+0xc5/0x430
+Call Trace:
+ <TASK>
+ ext4_mb_use_best_found+0x203/0x2f0
+ ext4_mb_try_best_found+0x163/0x240
+ ext4_mb_regular_allocator+0x158/0x1550
+ ext4_mb_new_blocks+0x86a/0xe10
+ ext4_ext_map_blocks+0xb0c/0x13a0
+ ext4_map_blocks+0x2cd/0x8f0
+ ext4_iomap_begin+0x27b/0x400
+ iomap_iter+0x222/0x3d0
+ __iomap_dio_rw+0x243/0xcb0
+ iomap_dio_rw+0x16/0x80
+=========================================================
+
+A simple reproducer demonstrating the problem:
+
+ mkfs.ext4 -F /dev/sda -b 4096 100M
+ mount /dev/sda /tmp/test
+ fallocate -l1M /tmp/test/tmp
+ fallocate -l10M /tmp/test/file
+ fallocate -i -o 1M -l16777203M /tmp/test/file
+ fsstress -d /tmp/test -l 0 -n 100000 -p 8 &
+ sleep 10 && killall -9 fsstress
+ rm -f /tmp/test/tmp
+ xfs_io -c "open -ad /tmp/test/file" -c "pwrite -S 0xff 0 8192"
+
+We simply refactor the logic for adjusting the best extent by adding
+a temporary ext4_free_extent ex and use extent_logical_end() to avoid
+overflow, which also simplifies the code.
+
+Cc: stable@kernel.org # 6.4
+Fixes: 93cdf49f6eca ("ext4: Fix best extent lstart adjustment logic in ext4_mb_new_inode_pa()")
+Signed-off-by: Baokun Li <libaokun1@huawei.com>
+Reviewed-by: Ritesh Harjani (IBM) <ritesh.list@gmail.com>
+Link: https://lore.kernel.org/r/20230724121059.11834-3-libaokun1@huawei.com
+Signed-off-by: Theodore Ts'o <tytso@mit.edu>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ fs/ext4/mballoc.c | 31 ++++++++++++++-----------------
+ 1 file changed, 14 insertions(+), 17 deletions(-)
+
+diff --git a/fs/ext4/mballoc.c b/fs/ext4/mballoc.c
+index 5c3055a32e57a..bd7557d8dec41 100644
+--- a/fs/ext4/mballoc.c
++++ b/fs/ext4/mballoc.c
+@@ -5177,8 +5177,11 @@ ext4_mb_new_inode_pa(struct ext4_allocation_context *ac)
+ pa = ac->ac_pa;
+
+ if (ac->ac_b_ex.fe_len < ac->ac_orig_goal_len) {
+- int new_bex_start;
+- int new_bex_end;
++ struct ext4_free_extent ex = {
++ .fe_logical = ac->ac_g_ex.fe_logical,
++ .fe_len = ac->ac_orig_goal_len,
++ };
++ loff_t orig_goal_end = extent_logical_end(sbi, &ex);
+
+ /* we can't allocate as much as normalizer wants.
+ * so, found space must get proper lstart
+@@ -5197,29 +5200,23 @@ ext4_mb_new_inode_pa(struct ext4_allocation_context *ac)
+ * still cover original start
+ * 3. Else, keep the best ex at start of original request.
+ */
+- new_bex_end = ac->ac_g_ex.fe_logical +
+- EXT4_C2B(sbi, ac->ac_orig_goal_len);
+- new_bex_start = new_bex_end - EXT4_C2B(sbi, ac->ac_b_ex.fe_len);
+- if (ac->ac_o_ex.fe_logical >= new_bex_start)
+- goto adjust_bex;
++ ex.fe_len = ac->ac_b_ex.fe_len;
+
+- new_bex_start = ac->ac_g_ex.fe_logical;
+- new_bex_end =
+- new_bex_start + EXT4_C2B(sbi, ac->ac_b_ex.fe_len);
+- if (ac->ac_o_ex.fe_logical < new_bex_end)
++ ex.fe_logical = orig_goal_end - EXT4_C2B(sbi, ex.fe_len);
++ if (ac->ac_o_ex.fe_logical >= ex.fe_logical)
+ goto adjust_bex;
+
+- new_bex_start = ac->ac_o_ex.fe_logical;
+- new_bex_end =
+- new_bex_start + EXT4_C2B(sbi, ac->ac_b_ex.fe_len);
++ ex.fe_logical = ac->ac_g_ex.fe_logical;
++ if (ac->ac_o_ex.fe_logical < extent_logical_end(sbi, &ex))
++ goto adjust_bex;
+
++ ex.fe_logical = ac->ac_o_ex.fe_logical;
+ adjust_bex:
+- ac->ac_b_ex.fe_logical = new_bex_start;
++ ac->ac_b_ex.fe_logical = ex.fe_logical;
+
+ BUG_ON(ac->ac_o_ex.fe_logical < ac->ac_b_ex.fe_logical);
+ BUG_ON(ac->ac_o_ex.fe_len > ac->ac_b_ex.fe_len);
+- BUG_ON(new_bex_end > (ac->ac_g_ex.fe_logical +
+- EXT4_C2B(sbi, ac->ac_orig_goal_len)));
++ BUG_ON(extent_logical_end(sbi, &ex) > orig_goal_end);
+ }
+
+ pa->pa_lstart = ac->ac_b_ex.fe_logical;
+--
+2.40.1
+
--- /dev/null
+From b068db538d3ed9567c80c479b13942904789ac10 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 8 Aug 2023 20:44:48 -0400
+Subject: Fix nomenclature for USB and PCI wireless devices
+
+From: Alan Stern <stern@rowland.harvard.edu>
+
+[ Upstream commit 5d7cf67f72ae34d38e090bdfa673da4aefe4048e ]
+
+A mouse that uses a USB connection is called a "USB mouse" device (or
+"USB mouse" for short), not a "mouse USB" device. By analogy, a WiFi
+adapter that connects to the host computer via USB is a "USB wireless"
+device, not a "wireless USB" device. (The latter term more properly
+refers to a defunct Wireless USB specification, which described a
+technology for sending USB protocol messages over an ultra wideband
+radio link.)
+
+Similarly for a WiFi adapter card that plugs into a PCIe slot: It is a
+"PCIe wireless" device, not a "wireless PCIe" device.
+
+Rephrase the text in the kernel source where the word ordering is
+wrong.
+
+Signed-off-by: Alan Stern <stern@rowland.harvard.edu>
+Reviewed-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Signed-off-by: Kalle Valo <kvalo@kernel.org>
+Link: https://lore.kernel.org/r/57da7c80-0e48-41b5-8427-884a02648f55@rowland.harvard.edu
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/wireless/ath/ath10k/pci.c | 2 +-
+ drivers/net/wireless/ath/ath10k/usb.c | 2 +-
+ drivers/net/wireless/ath/ath11k/pci.c | 2 +-
+ drivers/net/wireless/ath/ath12k/pci.c | 2 +-
+ drivers/net/wireless/atmel/at76c50x-usb.c | 8 ++--
+ .../wireless/intersil/orinoco/orinoco_usb.c | 12 ++---
+ drivers/net/wireless/legacy/rndis_wlan.c | 2 +-
+ .../net/wireless/mediatek/mt76/mt7603/Kconfig | 2 +-
+ .../net/wireless/mediatek/mt76/mt7615/Kconfig | 2 +-
+ .../net/wireless/mediatek/mt76/mt76x0/Kconfig | 4 +-
+ .../net/wireless/mediatek/mt76/mt76x2/Kconfig | 4 +-
+ .../net/wireless/mediatek/mt76/mt7915/Kconfig | 2 +-
+ .../net/wireless/mediatek/mt76/mt7996/Kconfig | 2 +-
+ drivers/net/wireless/mediatek/mt7601u/Kconfig | 2 +-
+ drivers/net/wireless/purelifi/plfxlc/Kconfig | 2 +-
+ drivers/net/wireless/ralink/rt2x00/Kconfig | 2 +-
+ drivers/net/wireless/realtek/rtw88/pci.c | 2 +-
+ drivers/net/wireless/realtek/rtw88/usb.c | 2 +-
+ drivers/net/wireless/realtek/rtw89/pci.c | 2 +-
+ drivers/net/wireless/zydas/zd1201.c | 6 +--
+ drivers/platform/x86/eeepc-laptop.c | 2 +-
+ drivers/staging/wlan-ng/prism2usb.c | 48 +++++++++----------
+ 22 files changed, 57 insertions(+), 57 deletions(-)
+
+diff --git a/drivers/net/wireless/ath/ath10k/pci.c b/drivers/net/wireless/ath/ath10k/pci.c
+index 9275a672f90cb..73463ded42045 100644
+--- a/drivers/net/wireless/ath/ath10k/pci.c
++++ b/drivers/net/wireless/ath/ath10k/pci.c
+@@ -3817,7 +3817,7 @@ static void __exit ath10k_pci_exit(void)
+ module_exit(ath10k_pci_exit);
+
+ MODULE_AUTHOR("Qualcomm Atheros");
+-MODULE_DESCRIPTION("Driver support for Qualcomm Atheros 802.11ac WLAN PCIe/AHB devices");
++MODULE_DESCRIPTION("Driver support for Qualcomm Atheros PCIe/AHB 802.11ac WLAN devices");
+ MODULE_LICENSE("Dual BSD/GPL");
+
+ /* QCA988x 2.0 firmware files */
+diff --git a/drivers/net/wireless/ath/ath10k/usb.c b/drivers/net/wireless/ath/ath10k/usb.c
+index b0067af685b16..3c482baacec10 100644
+--- a/drivers/net/wireless/ath/ath10k/usb.c
++++ b/drivers/net/wireless/ath/ath10k/usb.c
+@@ -1126,5 +1126,5 @@ static struct usb_driver ath10k_usb_driver = {
+ module_usb_driver(ath10k_usb_driver);
+
+ MODULE_AUTHOR("Atheros Communications, Inc.");
+-MODULE_DESCRIPTION("Driver support for Qualcomm Atheros 802.11ac WLAN USB devices");
++MODULE_DESCRIPTION("Driver support for Qualcomm Atheros USB 802.11ac WLAN devices");
+ MODULE_LICENSE("Dual BSD/GPL");
+diff --git a/drivers/net/wireless/ath/ath11k/pci.c b/drivers/net/wireless/ath/ath11k/pci.c
+index ec40adc1cb235..a181563ec0851 100644
+--- a/drivers/net/wireless/ath/ath11k/pci.c
++++ b/drivers/net/wireless/ath/ath11k/pci.c
+@@ -1036,7 +1036,7 @@ static void ath11k_pci_exit(void)
+
+ module_exit(ath11k_pci_exit);
+
+-MODULE_DESCRIPTION("Driver support for Qualcomm Technologies 802.11ax WLAN PCIe devices");
++MODULE_DESCRIPTION("Driver support for Qualcomm Technologies PCIe 802.11ax WLAN devices");
+ MODULE_LICENSE("Dual BSD/GPL");
+
+ /* firmware files */
+diff --git a/drivers/net/wireless/ath/ath12k/pci.c b/drivers/net/wireless/ath/ath12k/pci.c
+index e4f08a066ca10..fae5dfd6e9d70 100644
+--- a/drivers/net/wireless/ath/ath12k/pci.c
++++ b/drivers/net/wireless/ath/ath12k/pci.c
+@@ -1411,5 +1411,5 @@ static void ath12k_pci_exit(void)
+
+ module_exit(ath12k_pci_exit);
+
+-MODULE_DESCRIPTION("Driver support for Qualcomm Technologies 802.11be WLAN PCIe devices");
++MODULE_DESCRIPTION("Driver support for Qualcomm Technologies PCIe 802.11be WLAN devices");
+ MODULE_LICENSE("Dual BSD/GPL");
+diff --git a/drivers/net/wireless/atmel/at76c50x-usb.c b/drivers/net/wireless/atmel/at76c50x-usb.c
+index 009bca34ece30..447b51cff8f96 100644
+--- a/drivers/net/wireless/atmel/at76c50x-usb.c
++++ b/drivers/net/wireless/atmel/at76c50x-usb.c
+@@ -10,7 +10,7 @@
+ * Copyright (c) 2007 Kalle Valo <kalle.valo@iki.fi>
+ * Copyright (c) 2010 Sebastian Smolorz <sesmo@gmx.net>
+ *
+- * This file is part of the Berlios driver for WLAN USB devices based on the
++ * This file is part of the Berlios driver for USB WLAN devices based on the
+ * Atmel AT76C503A/505/505A.
+ *
+ * Some iw_handler code was taken from airo.c, (C) 1999 Benjamin Reed
+@@ -143,7 +143,7 @@ static const struct usb_device_id dev_table[] = {
+ { USB_DEVICE(0x0cde, 0x0001), USB_DEVICE_DATA(BOARD_503_ISL3861) },
+ /* Dynalink/Askey WLL013 (intersil) */
+ { USB_DEVICE(0x069a, 0x0320), USB_DEVICE_DATA(BOARD_503_ISL3861) },
+- /* EZ connect 11Mpbs Wireless USB Adapter SMC2662W v1 */
++ /* EZ connect 11Mpbs USB Wireless Adapter SMC2662W v1 */
+ { USB_DEVICE(0x0d5c, 0xa001), USB_DEVICE_DATA(BOARD_503_ISL3861) },
+ /* BenQ AWL300 */
+ { USB_DEVICE(0x04a5, 0x9000), USB_DEVICE_DATA(BOARD_503_ISL3861) },
+@@ -195,7 +195,7 @@ static const struct usb_device_id dev_table[] = {
+ { USB_DEVICE(0x04a5, 0x9001), USB_DEVICE_DATA(BOARD_503) },
+ /* 3Com 3CRSHEW696 */
+ { USB_DEVICE(0x0506, 0x0a01), USB_DEVICE_DATA(BOARD_503) },
+- /* Siemens Santis ADSL WLAN USB adapter WLL 013 */
++ /* Siemens Santis ADSL USB WLAN adapter WLL 013 */
+ { USB_DEVICE(0x0681, 0x001b), USB_DEVICE_DATA(BOARD_503) },
+ /* Belkin F5D6050, version 2 */
+ { USB_DEVICE(0x050d, 0x0050), USB_DEVICE_DATA(BOARD_503) },
+@@ -238,7 +238,7 @@ static const struct usb_device_id dev_table[] = {
+ { USB_DEVICE(0x1915, 0x2233), USB_DEVICE_DATA(BOARD_505_2958) },
+ /* Xterasys XN-2122B, IBlitzz BWU613B/BWU613SB */
+ { USB_DEVICE(0x12fd, 0x1001), USB_DEVICE_DATA(BOARD_505_2958) },
+- /* Corega WLAN USB Stick 11 */
++ /* Corega USB WLAN Stick 11 */
+ { USB_DEVICE(0x07aa, 0x7613), USB_DEVICE_DATA(BOARD_505_2958) },
+ /* Microstar MSI Box MS6978 */
+ { USB_DEVICE(0x0db0, 0x1020), USB_DEVICE_DATA(BOARD_505_2958) },
+diff --git a/drivers/net/wireless/intersil/orinoco/orinoco_usb.c b/drivers/net/wireless/intersil/orinoco/orinoco_usb.c
+index dd31929261ab9..866e0230df251 100644
+--- a/drivers/net/wireless/intersil/orinoco/orinoco_usb.c
++++ b/drivers/net/wireless/intersil/orinoco/orinoco_usb.c
+@@ -129,18 +129,18 @@ MODULE_FIRMWARE("orinoco_ezusb_fw");
+
+ #define USB_AVAYA8_VENDOR_ID 0x0D98
+ #define USB_AVAYAE_VENDOR_ID 0x0D9E
+-#define USB_AVAYA_WIRELESS_ID 0x0300 /* Avaya Wireless USB Card */
++#define USB_AVAYA_WIRELESS_ID 0x0300 /* Avaya USB Wireless Card */
+
+ #define USB_AGERE_VENDOR_ID 0x0D4E /* Agere Systems */
+-#define USB_AGERE_MODEL0801_ID 0x1000 /* Wireless USB Card Model 0801 */
+-#define USB_AGERE_MODEL0802_ID 0x1001 /* Wireless USB Card Model 0802 */
+-#define USB_AGERE_REBRANDED_ID 0x047A /* WLAN USB Card */
++#define USB_AGERE_MODEL0801_ID 0x1000 /* USB Wireless Card Model 0801 */
++#define USB_AGERE_MODEL0802_ID 0x1001 /* USB Wireless Card Model 0802 */
++#define USB_AGERE_REBRANDED_ID 0x047A /* USB WLAN Card */
+
+ #define USB_ELSA_VENDOR_ID 0x05CC
+ #define USB_ELSA_AIRLANCER_ID 0x3100 /* ELSA AirLancer USB-11 */
+
+ #define USB_LEGEND_VENDOR_ID 0x0E7C
+-#define USB_LEGEND_JOYNET_ID 0x0300 /* Joynet WLAN USB Card */
++#define USB_LEGEND_JOYNET_ID 0x0300 /* Joynet USB WLAN Card */
+
+ #define USB_SAMSUNG_VENDOR_ID 0x04E8
+ #define USB_SAMSUNG_SEW2001U1_ID 0x5002 /* Samsung SEW-2001u Card */
+@@ -154,7 +154,7 @@ MODULE_FIRMWARE("orinoco_ezusb_fw");
+ #define USB_FUJITSU_E1100_ID 0x1002 /* connect2AIR WLAN E-1100 USB */
+
+ #define USB_2WIRE_VENDOR_ID 0x1630
+-#define USB_2WIRE_WIRELESS_ID 0xff81 /* 2Wire Wireless USB adapter */
++#define USB_2WIRE_WIRELESS_ID 0xff81 /* 2Wire USB Wireless adapter */
+
+
+ #define EZUSB_REQUEST_FW_TRANS 0xA0
+diff --git a/drivers/net/wireless/legacy/rndis_wlan.c b/drivers/net/wireless/legacy/rndis_wlan.c
+index 712038d46bdb3..e7fea7ded6d5c 100644
+--- a/drivers/net/wireless/legacy/rndis_wlan.c
++++ b/drivers/net/wireless/legacy/rndis_wlan.c
+@@ -1,6 +1,6 @@
+ // SPDX-License-Identifier: GPL-2.0-or-later
+ /*
+- * Driver for RNDIS based wireless USB devices.
++ * Driver for RNDIS based USB wireless devices.
+ *
+ * Copyright (C) 2007 by Bjorge Dijkstra <bjd@jooz.net>
+ * Copyright (C) 2008-2009 by Jussi Kivilinna <jussi.kivilinna@iki.fi>
+diff --git a/drivers/net/wireless/mediatek/mt76/mt7603/Kconfig b/drivers/net/wireless/mediatek/mt76/mt7603/Kconfig
+index 6a0080f1d91c7..dd16acfd9735d 100644
+--- a/drivers/net/wireless/mediatek/mt76/mt7603/Kconfig
++++ b/drivers/net/wireless/mediatek/mt76/mt7603/Kconfig
+@@ -5,7 +5,7 @@ config MT7603E
+ depends on MAC80211
+ depends on PCI
+ help
+- This adds support for MT7603E wireless PCIe devices and the WLAN core
++ This adds support for MT7603E PCIe wireless devices and the WLAN core
+ on MT7628/MT7688 SoC devices. This family supports IEEE 802.11n 2x2
+ to 300Mbps PHY rate
+
+diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/Kconfig b/drivers/net/wireless/mediatek/mt76/mt7615/Kconfig
+index 30fba36ff46bb..1ab1439143f41 100644
+--- a/drivers/net/wireless/mediatek/mt76/mt7615/Kconfig
++++ b/drivers/net/wireless/mediatek/mt76/mt7615/Kconfig
+@@ -11,7 +11,7 @@ config MT7615E
+ depends on MAC80211
+ depends on PCI
+ help
+- This adds support for MT7615-based wireless PCIe devices,
++ This adds support for MT7615-based PCIe wireless devices,
+ which support concurrent dual-band operation at both 5GHz
+ and 2.4GHz, IEEE 802.11ac 4x4:4SS 1733Mbps PHY rate, wave2
+ MU-MIMO up to 4 users/group and 160MHz channels.
+diff --git a/drivers/net/wireless/mediatek/mt76/mt76x0/Kconfig b/drivers/net/wireless/mediatek/mt76/mt76x0/Kconfig
+index 7c88ed8b8f1e9..3ed888782a709 100644
+--- a/drivers/net/wireless/mediatek/mt76/mt76x0/Kconfig
++++ b/drivers/net/wireless/mediatek/mt76/mt76x0/Kconfig
+@@ -10,7 +10,7 @@ config MT76x0U
+ depends on MAC80211
+ depends on USB
+ help
+- This adds support for MT7610U-based wireless USB 2.0 dongles,
++ This adds support for MT7610U-based USB 2.0 wireless dongles,
+ which comply with IEEE 802.11ac standards and support 1x1
+ 433Mbps PHY rate.
+
+@@ -22,7 +22,7 @@ config MT76x0E
+ depends on MAC80211
+ depends on PCI
+ help
+- This adds support for MT7610/MT7630-based wireless PCIe devices,
++ This adds support for MT7610/MT7630-based PCIe wireless devices,
+ which comply with IEEE 802.11ac standards and support 1x1
+ 433Mbps PHY rate.
+
+diff --git a/drivers/net/wireless/mediatek/mt76/mt76x2/Kconfig b/drivers/net/wireless/mediatek/mt76/mt76x2/Kconfig
+index 5fd4973e32dfb..482a32b70ddfe 100644
+--- a/drivers/net/wireless/mediatek/mt76/mt76x2/Kconfig
++++ b/drivers/net/wireless/mediatek/mt76/mt76x2/Kconfig
+@@ -9,7 +9,7 @@ config MT76x2E
+ depends on MAC80211
+ depends on PCI
+ help
+- This adds support for MT7612/MT7602/MT7662-based wireless PCIe
++ This adds support for MT7612/MT7602/MT7662-based PCIe wireless
+ devices, which comply with IEEE 802.11ac standards and support
+ 2SS to 866Mbit/s PHY rate.
+
+@@ -22,7 +22,7 @@ config MT76x2U
+ depends on MAC80211
+ depends on USB
+ help
+- This adds support for MT7612U-based wireless USB 3.0 dongles,
++ This adds support for MT7612U-based USB 3.0 wireless dongles,
+ which comply with IEEE 802.11ac standards and support 2SS to
+ 866Mbit/s PHY rate.
+
+diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/Kconfig b/drivers/net/wireless/mediatek/mt76/mt7915/Kconfig
+index d710726d47bfd..3337cdfed0109 100644
+--- a/drivers/net/wireless/mediatek/mt76/mt7915/Kconfig
++++ b/drivers/net/wireless/mediatek/mt76/mt7915/Kconfig
+@@ -7,7 +7,7 @@ config MT7915E
+ depends on PCI
+ select RELAY
+ help
+- This adds support for MT7915-based wireless PCIe devices,
++ This adds support for MT7915-based PCIe wireless devices,
+ which support concurrent dual-band operation at both 5GHz
+ and 2.4GHz IEEE 802.11ax 4x4:4SS 1024-QAM, 160MHz channels,
+ OFDMA, spatial reuse and dual carrier modulation.
+diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/Kconfig b/drivers/net/wireless/mediatek/mt76/mt7996/Kconfig
+index 1afa2f662e473..bb44d4a5e2dc9 100644
+--- a/drivers/net/wireless/mediatek/mt76/mt7996/Kconfig
++++ b/drivers/net/wireless/mediatek/mt76/mt7996/Kconfig
+@@ -7,7 +7,7 @@ config MT7996E
+ depends on MAC80211
+ depends on PCI
+ help
+- This adds support for MT7996-based wireless PCIe devices,
++ This adds support for MT7996-based PCIe wireless devices,
+ which support concurrent tri-band operation at 6GHz, 5GHz,
+ and 2.4GHz IEEE 802.11be 4x4:4SS 4096-QAM, 320MHz channels.
+
+diff --git a/drivers/net/wireless/mediatek/mt7601u/Kconfig b/drivers/net/wireless/mediatek/mt7601u/Kconfig
+index 4a8b962806707..4880fc053d9d3 100644
+--- a/drivers/net/wireless/mediatek/mt7601u/Kconfig
++++ b/drivers/net/wireless/mediatek/mt7601u/Kconfig
+@@ -4,4 +4,4 @@ config MT7601U
+ depends on MAC80211
+ depends on USB
+ help
+- This adds support for MT7601U-based wireless USB dongles.
++ This adds support for MT7601U-based USB wireless dongles.
+diff --git a/drivers/net/wireless/purelifi/plfxlc/Kconfig b/drivers/net/wireless/purelifi/plfxlc/Kconfig
+index 4e0be27a5e0eb..dd5fca480d7ef 100644
+--- a/drivers/net/wireless/purelifi/plfxlc/Kconfig
++++ b/drivers/net/wireless/purelifi/plfxlc/Kconfig
+@@ -3,7 +3,7 @@ config PLFXLC
+ tristate "pureLiFi X, XL, XC device support"
+ depends on CFG80211 && MAC80211 && USB
+ help
+- This option adds support for pureLiFi LiFi wireless USB
++ This option adds support for pureLiFi LiFi USB wireless
+ adapters. The pureLiFi X, XL, XC USB devices are based on
+ 802.11 OFDM PHY but uses light as the transmission medium.
+ The driver supports common 802.11 encryption/authentication
+diff --git a/drivers/net/wireless/ralink/rt2x00/Kconfig b/drivers/net/wireless/ralink/rt2x00/Kconfig
+index dcccc290a7f52..d1fd66d44a7ed 100644
+--- a/drivers/net/wireless/ralink/rt2x00/Kconfig
++++ b/drivers/net/wireless/ralink/rt2x00/Kconfig
+@@ -170,7 +170,7 @@ config RT2800USB_RT35XX
+ config RT2800USB_RT3573
+ bool "rt2800usb - Include support for rt3573 devices (EXPERIMENTAL)"
+ help
+- This enables support for RT3573 chipset based wireless USB devices
++ This enables support for RT3573 chipset based USB wireless devices
+ in the rt2800usb driver.
+
+ config RT2800USB_RT53XX
+diff --git a/drivers/net/wireless/realtek/rtw88/pci.c b/drivers/net/wireless/realtek/rtw88/pci.c
+index 44a8fff34cddf..2bfc0e822b8d0 100644
+--- a/drivers/net/wireless/realtek/rtw88/pci.c
++++ b/drivers/net/wireless/realtek/rtw88/pci.c
+@@ -1828,5 +1828,5 @@ void rtw_pci_shutdown(struct pci_dev *pdev)
+ EXPORT_SYMBOL(rtw_pci_shutdown);
+
+ MODULE_AUTHOR("Realtek Corporation");
+-MODULE_DESCRIPTION("Realtek 802.11ac wireless PCI driver");
++MODULE_DESCRIPTION("Realtek PCI 802.11ac wireless driver");
+ MODULE_LICENSE("Dual BSD/GPL");
+diff --git a/drivers/net/wireless/realtek/rtw88/usb.c b/drivers/net/wireless/realtek/rtw88/usb.c
+index 875a61c9c80d4..c279a500b4bdb 100644
+--- a/drivers/net/wireless/realtek/rtw88/usb.c
++++ b/drivers/net/wireless/realtek/rtw88/usb.c
+@@ -930,5 +930,5 @@ void rtw_usb_disconnect(struct usb_interface *intf)
+ EXPORT_SYMBOL(rtw_usb_disconnect);
+
+ MODULE_AUTHOR("Realtek Corporation");
+-MODULE_DESCRIPTION("Realtek 802.11ac wireless USB driver");
++MODULE_DESCRIPTION("Realtek USB 802.11ac wireless driver");
+ MODULE_LICENSE("Dual BSD/GPL");
+diff --git a/drivers/net/wireless/realtek/rtw89/pci.c b/drivers/net/wireless/realtek/rtw89/pci.c
+index 9402f1a0caea8..3a4bfc44142b6 100644
+--- a/drivers/net/wireless/realtek/rtw89/pci.c
++++ b/drivers/net/wireless/realtek/rtw89/pci.c
+@@ -3939,5 +3939,5 @@ void rtw89_pci_remove(struct pci_dev *pdev)
+ EXPORT_SYMBOL(rtw89_pci_remove);
+
+ MODULE_AUTHOR("Realtek Corporation");
+-MODULE_DESCRIPTION("Realtek 802.11ax wireless PCI driver");
++MODULE_DESCRIPTION("Realtek PCI 802.11ax wireless driver");
+ MODULE_LICENSE("Dual BSD/GPL");
+diff --git a/drivers/net/wireless/zydas/zd1201.c b/drivers/net/wireless/zydas/zd1201.c
+index a85fe7e4c6d47..2814df1ecc78f 100644
+--- a/drivers/net/wireless/zydas/zd1201.c
++++ b/drivers/net/wireless/zydas/zd1201.c
+@@ -1,6 +1,6 @@
+ // SPDX-License-Identifier: GPL-2.0-only
+ /*
+- * Driver for ZyDAS zd1201 based wireless USB devices.
++ * Driver for ZyDAS zd1201 based USB wireless devices.
+ *
+ * Copyright (c) 2004, 2005 Jeroen Vreeken (pe1rxq@amsat.org)
+ *
+@@ -23,8 +23,8 @@
+ #include "zd1201.h"
+
+ static const struct usb_device_id zd1201_table[] = {
+- {USB_DEVICE(0x0586, 0x3400)}, /* Peabird Wireless USB Adapter */
+- {USB_DEVICE(0x0ace, 0x1201)}, /* ZyDAS ZD1201 Wireless USB Adapter */
++ {USB_DEVICE(0x0586, 0x3400)}, /* Peabird USB Wireless Adapter */
++ {USB_DEVICE(0x0ace, 0x1201)}, /* ZyDAS ZD1201 USB Wireless Adapter */
+ {USB_DEVICE(0x050d, 0x6051)}, /* Belkin F5D6051 usb adapter */
+ {USB_DEVICE(0x0db0, 0x6823)}, /* MSI UB11B usb adapter */
+ {USB_DEVICE(0x1044, 0x8004)}, /* Gigabyte GN-WLBZ101 */
+diff --git a/drivers/platform/x86/eeepc-laptop.c b/drivers/platform/x86/eeepc-laptop.c
+index 62b71e8e3567a..ff1b70269ccbf 100644
+--- a/drivers/platform/x86/eeepc-laptop.c
++++ b/drivers/platform/x86/eeepc-laptop.c
+@@ -1394,7 +1394,7 @@ static int eeepc_acpi_add(struct acpi_device *device)
+ * and machine-specific scripts find the fixed name convenient. But
+ * It's also good for us to exclude multiple instances because both
+ * our hwmon and our wlan rfkill subdevice use global ACPI objects
+- * (the EC and the wlan PCI slot respectively).
++ * (the EC and the PCI wlan slot respectively).
+ */
+ result = eeepc_platform_init(eeepc);
+ if (result)
+diff --git a/drivers/staging/wlan-ng/prism2usb.c b/drivers/staging/wlan-ng/prism2usb.c
+index 80e36d03c4e25..0e0ccef4871e9 100644
+--- a/drivers/staging/wlan-ng/prism2usb.c
++++ b/drivers/staging/wlan-ng/prism2usb.c
+@@ -11,45 +11,45 @@
+
+ static const struct usb_device_id usb_prism_tbl[] = {
+ PRISM_DEV(0x04bb, 0x0922, "IOData AirPort WN-B11/USBS"),
+- PRISM_DEV(0x07aa, 0x0012, "Corega Wireless LAN USB Stick-11"),
+- PRISM_DEV(0x09aa, 0x3642, "Prism2.x 11Mbps WLAN USB Adapter"),
+- PRISM_DEV(0x1668, 0x0408, "Actiontec Prism2.5 11Mbps WLAN USB Adapter"),
+- PRISM_DEV(0x1668, 0x0421, "Actiontec Prism2.5 11Mbps WLAN USB Adapter"),
+- PRISM_DEV(0x1915, 0x2236, "Linksys WUSB11v3.0 11Mbps WLAN USB Adapter"),
+- PRISM_DEV(0x066b, 0x2212, "Linksys WUSB11v2.5 11Mbps WLAN USB Adapter"),
+- PRISM_DEV(0x066b, 0x2213, "Linksys WUSB12v1.1 11Mbps WLAN USB Adapter"),
++ PRISM_DEV(0x07aa, 0x0012, "Corega USB Wireless LAN Stick-11"),
++ PRISM_DEV(0x09aa, 0x3642, "Prism2.x 11Mbps USB WLAN Adapter"),
++ PRISM_DEV(0x1668, 0x0408, "Actiontec Prism2.5 11Mbps USB WLAN Adapter"),
++ PRISM_DEV(0x1668, 0x0421, "Actiontec Prism2.5 11Mbps USB WLAN Adapter"),
++ PRISM_DEV(0x1915, 0x2236, "Linksys WUSB11v3.0 11Mbps USB WLAN Adapter"),
++ PRISM_DEV(0x066b, 0x2212, "Linksys WUSB11v2.5 11Mbps USB WLAN Adapter"),
++ PRISM_DEV(0x066b, 0x2213, "Linksys WUSB12v1.1 11Mbps USB WLAN Adapter"),
+ PRISM_DEV(0x0411, 0x0016, "Melco WLI-USB-S11 11Mbps WLAN Adapter"),
+- PRISM_DEV(0x08de, 0x7a01, "PRISM25 IEEE 802.11 Mini USB Adapter"),
+- PRISM_DEV(0x8086, 0x1111, "Intel PRO/Wireless 2011B LAN USB Adapter"),
++ PRISM_DEV(0x08de, 0x7a01, "PRISM25 USB IEEE 802.11 Mini Adapter"),
++ PRISM_DEV(0x8086, 0x1111, "Intel PRO/Wireless 2011B USB LAN Adapter"),
+ PRISM_DEV(0x0d8e, 0x7a01, "PRISM25 IEEE 802.11 Mini USB Adapter"),
+- PRISM_DEV(0x045e, 0x006e, "Microsoft MN510 Wireless USB Adapter"),
++ PRISM_DEV(0x045e, 0x006e, "Microsoft MN510 USB Wireless Adapter"),
+ PRISM_DEV(0x0967, 0x0204, "Acer Warplink USB Adapter"),
+ PRISM_DEV(0x0cde, 0x0002, "Z-Com 725/726 Prism2.5 USB/USB Integrated"),
+- PRISM_DEV(0x0cde, 0x0005, "Z-Com Xl735 Wireless 802.11b USB Adapter"),
+- PRISM_DEV(0x413c, 0x8100, "Dell TrueMobile 1180 Wireless USB Adapter"),
+- PRISM_DEV(0x0b3b, 0x1601, "ALLNET 0193 11Mbps WLAN USB Adapter"),
+- PRISM_DEV(0x0b3b, 0x1602, "ZyXEL ZyAIR B200 Wireless USB Adapter"),
+- PRISM_DEV(0x0baf, 0x00eb, "USRobotics USR1120 Wireless USB Adapter"),
++ PRISM_DEV(0x0cde, 0x0005, "Z-Com Xl735 USB Wireless 802.11b Adapter"),
++ PRISM_DEV(0x413c, 0x8100, "Dell TrueMobile 1180 USB Wireless Adapter"),
++ PRISM_DEV(0x0b3b, 0x1601, "ALLNET 0193 11Mbps USB WLAN Adapter"),
++ PRISM_DEV(0x0b3b, 0x1602, "ZyXEL ZyAIR B200 USB Wireless Adapter"),
++ PRISM_DEV(0x0baf, 0x00eb, "USRobotics USR1120 USB Wireless Adapter"),
+ PRISM_DEV(0x0411, 0x0027, "Melco WLI-USB-KS11G 11Mbps WLAN Adapter"),
+ PRISM_DEV(0x04f1, 0x3009, "JVC MP-XP7250 Builtin USB WLAN Adapter"),
+ PRISM_DEV(0x0846, 0x4110, "NetGear MA111"),
+ PRISM_DEV(0x03f3, 0x0020, "Adaptec AWN-8020 USB WLAN Adapter"),
+- PRISM_DEV(0x2821, 0x3300, "ASUS-WL140 / Hawking HighDB Wireless USB Adapter"),
+- PRISM_DEV(0x2001, 0x3700, "DWL-122 Wireless USB Adapter"),
+- PRISM_DEV(0x2001, 0x3702, "DWL-120 Rev F Wireless USB Adapter"),
++ PRISM_DEV(0x2821, 0x3300, "ASUS-WL140 / Hawking HighDB USB Wireless Adapter"),
++ PRISM_DEV(0x2001, 0x3700, "DWL-122 USB Wireless Adapter"),
++ PRISM_DEV(0x2001, 0x3702, "DWL-120 Rev F USB Wireless Adapter"),
+ PRISM_DEV(0x50c2, 0x4013, "Averatec USB WLAN Adapter"),
+- PRISM_DEV(0x2c02, 0x14ea, "Planex GW-US11H WLAN USB Adapter"),
+- PRISM_DEV(0x124a, 0x168b, "Airvast PRISM3 WLAN USB Adapter"),
++ PRISM_DEV(0x2c02, 0x14ea, "Planex GW-US11H USB WLAN Adapter"),
++ PRISM_DEV(0x124a, 0x168b, "Airvast PRISM3 USB WLAN Adapter"),
+ PRISM_DEV(0x083a, 0x3503, "T-Sinus 111 USB WLAN Adapter"),
+ PRISM_DEV(0x0411, 0x0044, "Melco WLI-USB-KB11 11Mbps WLAN Adapter"),
+- PRISM_DEV(0x1668, 0x6106, "ROPEX FreeLan 802.11b USB Adapter"),
+- PRISM_DEV(0x124a, 0x4017, "Pheenet WL-503IA 802.11b USB Adapter"),
++ PRISM_DEV(0x1668, 0x6106, "ROPEX FreeLan USB 802.11b Adapter"),
++ PRISM_DEV(0x124a, 0x4017, "Pheenet WL-503IA USB 802.11b Adapter"),
+ PRISM_DEV(0x0bb2, 0x0302, "Ambit Microsystems Corp."),
+- PRISM_DEV(0x9016, 0x182d, "Sitecom WL-022 802.11b USB Adapter"),
++ PRISM_DEV(0x9016, 0x182d, "Sitecom WL-022 USB 802.11b Adapter"),
+ PRISM_DEV(0x0543, 0x0f01,
+ "ViewSonic Airsync USB Adapter 11Mbps (Prism2.5)"),
+ PRISM_DEV(0x067c, 0x1022,
+- "Siemens SpeedStream 1022 11Mbps WLAN USB Adapter"),
++ "Siemens SpeedStream 1022 11Mbps USB WLAN Adapter"),
+ PRISM_DEV(0x049f, 0x0033,
+ "Compaq/Intel W100 PRO/Wireless 11Mbps multiport WLAN Adapter"),
+ { } /* terminator */
+--
+2.40.1
+
--- /dev/null
+From 338d5209852e83c75b5f9e17916adc5047960994 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sat, 1 Jul 2023 17:05:42 +0300
+Subject: fs/jfs: prevent double-free in dbUnmount() after failed jfs_remount()
+
+From: Andrew Kanner <andrew.kanner@gmail.com>
+
+[ Upstream commit cade5397e5461295f3cb87880534b6a07cafa427 ]
+
+Syzkaller reported the following issue:
+==================================================================
+BUG: KASAN: double-free in slab_free mm/slub.c:3787 [inline]
+BUG: KASAN: double-free in __kmem_cache_free+0x71/0x110 mm/slub.c:3800
+Free of addr ffff888086408000 by task syz-executor.4/12750
+[...]
+Call Trace:
+ <TASK>
+[...]
+ kasan_report_invalid_free+0xac/0xd0 mm/kasan/report.c:482
+ ____kasan_slab_free+0xfb/0x120
+ kasan_slab_free include/linux/kasan.h:177 [inline]
+ slab_free_hook mm/slub.c:1781 [inline]
+ slab_free_freelist_hook+0x12e/0x1a0 mm/slub.c:1807
+ slab_free mm/slub.c:3787 [inline]
+ __kmem_cache_free+0x71/0x110 mm/slub.c:3800
+ dbUnmount+0xf4/0x110 fs/jfs/jfs_dmap.c:264
+ jfs_umount+0x248/0x3b0 fs/jfs/jfs_umount.c:87
+ jfs_put_super+0x86/0x190 fs/jfs/super.c:194
+ generic_shutdown_super+0x130/0x310 fs/super.c:492
+ kill_block_super+0x79/0xd0 fs/super.c:1386
+ deactivate_locked_super+0xa7/0xf0 fs/super.c:332
+ cleanup_mnt+0x494/0x520 fs/namespace.c:1291
+ task_work_run+0x243/0x300 kernel/task_work.c:179
+ resume_user_mode_work include/linux/resume_user_mode.h:49 [inline]
+ exit_to_user_mode_loop+0x124/0x150 kernel/entry/common.c:171
+ exit_to_user_mode_prepare+0xb2/0x140 kernel/entry/common.c:203
+ __syscall_exit_to_user_mode_work kernel/entry/common.c:285 [inline]
+ syscall_exit_to_user_mode+0x26/0x60 kernel/entry/common.c:296
+ do_syscall_64+0x49/0xb0 arch/x86/entry/common.c:86
+ entry_SYSCALL_64_after_hwframe+0x63/0xcd
+[...]
+ </TASK>
+
+Allocated by task 13352:
+ kasan_save_stack mm/kasan/common.c:45 [inline]
+ kasan_set_track+0x3d/0x60 mm/kasan/common.c:52
+ ____kasan_kmalloc mm/kasan/common.c:371 [inline]
+ __kasan_kmalloc+0x97/0xb0 mm/kasan/common.c:380
+ kmalloc include/linux/slab.h:580 [inline]
+ dbMount+0x54/0x980 fs/jfs/jfs_dmap.c:164
+ jfs_mount+0x1dd/0x830 fs/jfs/jfs_mount.c:121
+ jfs_fill_super+0x590/0xc50 fs/jfs/super.c:556
+ mount_bdev+0x26c/0x3a0 fs/super.c:1359
+ legacy_get_tree+0xea/0x180 fs/fs_context.c:610
+ vfs_get_tree+0x88/0x270 fs/super.c:1489
+ do_new_mount+0x289/0xad0 fs/namespace.c:3145
+ do_mount fs/namespace.c:3488 [inline]
+ __do_sys_mount fs/namespace.c:3697 [inline]
+ __se_sys_mount+0x2d3/0x3c0 fs/namespace.c:3674
+ do_syscall_x64 arch/x86/entry/common.c:50 [inline]
+ do_syscall_64+0x3d/0xb0 arch/x86/entry/common.c:80
+ entry_SYSCALL_64_after_hwframe+0x63/0xcd
+
+Freed by task 13352:
+ kasan_save_stack mm/kasan/common.c:45 [inline]
+ kasan_set_track+0x3d/0x60 mm/kasan/common.c:52
+ kasan_save_free_info+0x27/0x40 mm/kasan/generic.c:518
+ ____kasan_slab_free+0xd6/0x120 mm/kasan/common.c:236
+ kasan_slab_free include/linux/kasan.h:177 [inline]
+ slab_free_hook mm/slub.c:1781 [inline]
+ slab_free_freelist_hook+0x12e/0x1a0 mm/slub.c:1807
+ slab_free mm/slub.c:3787 [inline]
+ __kmem_cache_free+0x71/0x110 mm/slub.c:3800
+ dbUnmount+0xf4/0x110 fs/jfs/jfs_dmap.c:264
+ jfs_mount_rw+0x545/0x740 fs/jfs/jfs_mount.c:247
+ jfs_remount+0x3db/0x710 fs/jfs/super.c:454
+ reconfigure_super+0x3bc/0x7b0 fs/super.c:935
+ vfs_fsconfig_locked fs/fsopen.c:254 [inline]
+ __do_sys_fsconfig fs/fsopen.c:439 [inline]
+ __se_sys_fsconfig+0xad5/0x1060 fs/fsopen.c:314
+ do_syscall_x64 arch/x86/entry/common.c:50 [inline]
+ do_syscall_64+0x3d/0xb0 arch/x86/entry/common.c:80
+ entry_SYSCALL_64_after_hwframe+0x63/0xcd
+[...]
+
+JFS_SBI(ipbmap->i_sb)->bmap wasn't set to NULL after kfree() in
+dbUnmount().
+
+Syzkaller uses faultinject to reproduce this KASAN double-free
+warning. The issue is triggered if either diMount() or dbMount() fail
+in jfs_remount(), since diUnmount() or dbUnmount() already happened in
+such a case - they will do double-free on next execution: jfs_umount
+or jfs_remount.
+
+Tested on both upstream and jfs-next by syzkaller.
+
+Reported-and-tested-by: syzbot+6a93efb725385bc4b2e9@syzkaller.appspotmail.com
+Closes: https://lore.kernel.org/all/000000000000471f2d05f1ce8bad@google.com/T/
+Link: https://syzkaller.appspot.com/bug?extid=6a93efb725385bc4b2e9
+Signed-off-by: Andrew Kanner <andrew.kanner@gmail.com>
+Signed-off-by: Dave Kleikamp <dave.kleikamp@oracle.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ fs/jfs/jfs_dmap.c | 1 +
+ 1 file changed, 1 insertion(+)
+
+diff --git a/fs/jfs/jfs_dmap.c b/fs/jfs/jfs_dmap.c
+index a14a0f18a4c40..88afd108c2dd2 100644
+--- a/fs/jfs/jfs_dmap.c
++++ b/fs/jfs/jfs_dmap.c
+@@ -269,6 +269,7 @@ int dbUnmount(struct inode *ipbmap, int mounterror)
+
+ /* free the memory for the in-memory bmap. */
+ kfree(bmp);
++ JFS_SBI(ipbmap->i_sb)->bmap = NULL;
+
+ return (0);
+ }
+--
+2.40.1
+
--- /dev/null
+From 579f7fbb827f60efe1e46a663b5803d61b534523 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 5 Jun 2023 12:19:23 -0700
+Subject: hw_breakpoint: fix single-stepping when using bpf_overflow_handler
+
+From: Tomislav Novak <tnovak@meta.com>
+
+[ Upstream commit d11a69873d9a7435fe6a48531e165ab80a8b1221 ]
+
+Arm platforms use is_default_overflow_handler() to determine if the
+hw_breakpoint code should single-step over the breakpoint trigger or
+let the custom handler deal with it.
+
+Since bpf_overflow_handler() currently isn't recognized as a default
+handler, attaching a BPF program to a PERF_TYPE_BREAKPOINT event causes
+it to keep firing (the instruction triggering the data abort exception
+is never skipped). For example:
+
+ # bpftrace -e 'watchpoint:0x10000:4:w { print("hit") }' -c ./test
+ Attaching 1 probe...
+ hit
+ hit
+ [...]
+ ^C
+
+(./test performs a single 4-byte store to 0x10000)
+
+This patch replaces the check with uses_default_overflow_handler(),
+which accounts for the bpf_overflow_handler() case by also testing
+if one of the perf_event_output functions gets invoked indirectly,
+via orig_default_handler.
+
+Signed-off-by: Tomislav Novak <tnovak@meta.com>
+Tested-by: Samuel Gosselin <sgosselin@google.com> # arm64
+Reviewed-by: Catalin Marinas <catalin.marinas@arm.com>
+Acked-by: Alexei Starovoitov <ast@kernel.org>
+Link: https://lore.kernel.org/linux-arm-kernel/20220923203644.2731604-1-tnovak@fb.com/
+Link: https://lore.kernel.org/r/20230605191923.1219974-1-tnovak@meta.com
+Signed-off-by: Will Deacon <will@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ arch/arm/kernel/hw_breakpoint.c | 8 ++++----
+ arch/arm64/kernel/hw_breakpoint.c | 4 ++--
+ include/linux/perf_event.h | 22 +++++++++++++++++++---
+ 3 files changed, 25 insertions(+), 9 deletions(-)
+
+diff --git a/arch/arm/kernel/hw_breakpoint.c b/arch/arm/kernel/hw_breakpoint.c
+index 054e9199f30db..dc0fb7a813715 100644
+--- a/arch/arm/kernel/hw_breakpoint.c
++++ b/arch/arm/kernel/hw_breakpoint.c
+@@ -626,7 +626,7 @@ int hw_breakpoint_arch_parse(struct perf_event *bp,
+ hw->address &= ~alignment_mask;
+ hw->ctrl.len <<= offset;
+
+- if (is_default_overflow_handler(bp)) {
++ if (uses_default_overflow_handler(bp)) {
+ /*
+ * Mismatch breakpoints are required for single-stepping
+ * breakpoints.
+@@ -798,7 +798,7 @@ static void watchpoint_handler(unsigned long addr, unsigned int fsr,
+ * Otherwise, insert a temporary mismatch breakpoint so that
+ * we can single-step over the watchpoint trigger.
+ */
+- if (!is_default_overflow_handler(wp))
++ if (!uses_default_overflow_handler(wp))
+ continue;
+ step:
+ enable_single_step(wp, instruction_pointer(regs));
+@@ -811,7 +811,7 @@ static void watchpoint_handler(unsigned long addr, unsigned int fsr,
+ info->trigger = addr;
+ pr_debug("watchpoint fired: address = 0x%x\n", info->trigger);
+ perf_bp_event(wp, regs);
+- if (is_default_overflow_handler(wp))
++ if (uses_default_overflow_handler(wp))
+ enable_single_step(wp, instruction_pointer(regs));
+ }
+
+@@ -886,7 +886,7 @@ static void breakpoint_handler(unsigned long unknown, struct pt_regs *regs)
+ info->trigger = addr;
+ pr_debug("breakpoint fired: address = 0x%x\n", addr);
+ perf_bp_event(bp, regs);
+- if (is_default_overflow_handler(bp))
++ if (uses_default_overflow_handler(bp))
+ enable_single_step(bp, addr);
+ goto unlock;
+ }
+diff --git a/arch/arm64/kernel/hw_breakpoint.c b/arch/arm64/kernel/hw_breakpoint.c
+index db2a1861bb978..35225632d70ad 100644
+--- a/arch/arm64/kernel/hw_breakpoint.c
++++ b/arch/arm64/kernel/hw_breakpoint.c
+@@ -654,7 +654,7 @@ static int breakpoint_handler(unsigned long unused, unsigned long esr,
+ perf_bp_event(bp, regs);
+
+ /* Do we need to handle the stepping? */
+- if (is_default_overflow_handler(bp))
++ if (uses_default_overflow_handler(bp))
+ step = 1;
+ unlock:
+ rcu_read_unlock();
+@@ -733,7 +733,7 @@ static u64 get_distance_from_watchpoint(unsigned long addr, u64 val,
+ static int watchpoint_report(struct perf_event *wp, unsigned long addr,
+ struct pt_regs *regs)
+ {
+- int step = is_default_overflow_handler(wp);
++ int step = uses_default_overflow_handler(wp);
+ struct arch_hw_breakpoint *info = counter_arch_bp(wp);
+
+ info->trigger = addr;
+diff --git a/include/linux/perf_event.h b/include/linux/perf_event.h
+index 2166a69e3bf2e..e657916c9509c 100644
+--- a/include/linux/perf_event.h
++++ b/include/linux/perf_event.h
+@@ -1316,15 +1316,31 @@ extern int perf_event_output(struct perf_event *event,
+ struct pt_regs *regs);
+
+ static inline bool
+-is_default_overflow_handler(struct perf_event *event)
++__is_default_overflow_handler(perf_overflow_handler_t overflow_handler)
+ {
+- if (likely(event->overflow_handler == perf_event_output_forward))
++ if (likely(overflow_handler == perf_event_output_forward))
+ return true;
+- if (unlikely(event->overflow_handler == perf_event_output_backward))
++ if (unlikely(overflow_handler == perf_event_output_backward))
+ return true;
+ return false;
+ }
+
++#define is_default_overflow_handler(event) \
++ __is_default_overflow_handler((event)->overflow_handler)
++
++#ifdef CONFIG_BPF_SYSCALL
++static inline bool uses_default_overflow_handler(struct perf_event *event)
++{
++ if (likely(is_default_overflow_handler(event)))
++ return true;
++
++ return __is_default_overflow_handler(event->orig_overflow_handler);
++}
++#else
++#define uses_default_overflow_handler(event) \
++ is_default_overflow_handler(event)
++#endif
++
+ extern void
+ perf_event_header__init_id(struct perf_event_header *header,
+ struct perf_sample_data *data,
+--
+2.40.1
+
--- /dev/null
+From ebb447d1c2e9383a5b770215de9817a45dd1120e Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 12 Jul 2023 13:03:28 +0200
+Subject: ice: Don't tx before switchdev is fully configured
+
+From: Wojciech Drewek <wojciech.drewek@intel.com>
+
+[ Upstream commit 7aa529a69e92b9aff585e569d5003f7c15d8d60b ]
+
+There is possibility that ice_eswitch_port_start_xmit might be
+called while some resources are still not allocated which might
+cause NULL pointer dereference. Fix this by checking if switchdev
+configuration was finished.
+
+Reviewed-by: Paul Menzel <pmenzel@molgen.mpg.de>
+Reviewed-by: Simon Horman <simon.horman@corigine.com>
+Signed-off-by: Wojciech Drewek <wojciech.drewek@intel.com>
+Tested-by: Sujai Buvaneswaran <sujai.buvaneswaran@intel.com>
+Signed-off-by: Tony Nguyen <anthony.l.nguyen@intel.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/ethernet/intel/ice/ice_eswitch.c | 3 +++
+ 1 file changed, 3 insertions(+)
+
+diff --git a/drivers/net/ethernet/intel/ice/ice_eswitch.c b/drivers/net/ethernet/intel/ice/ice_eswitch.c
+index 8f232c41a89e3..459e32f6adb50 100644
+--- a/drivers/net/ethernet/intel/ice/ice_eswitch.c
++++ b/drivers/net/ethernet/intel/ice/ice_eswitch.c
+@@ -331,6 +331,9 @@ ice_eswitch_port_start_xmit(struct sk_buff *skb, struct net_device *netdev)
+ np = netdev_priv(netdev);
+ vsi = np->vsi;
+
++ if (!vsi || !ice_is_switchdev_running(vsi->back))
++ return NETDEV_TX_BUSY;
++
+ if (ice_is_reset_in_progress(vsi->back->state) ||
+ test_bit(ICE_VF_DIS, vsi->back->state))
+ return NETDEV_TX_BUSY;
+--
+2.40.1
+
--- /dev/null
+From a9e87075c2d9991cdb110144660a7831a307dbf6 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 7 Aug 2023 10:11:40 -0700
+Subject: interconnect: Fix locking for runpm vs reclaim
+
+From: Rob Clark <robdclark@chromium.org>
+
+[ Upstream commit af42269c3523492d71ebbe11fefae2653e9cdc78 ]
+
+For cases where icc_bw_set() can be called in callbaths that could
+deadlock against shrinker/reclaim, such as runpm resume, we need to
+decouple the icc locking. Introduce a new icc_bw_lock for cases where
+we need to serialize bw aggregation and update to decouple that from
+paths that require memory allocation such as node/link creation/
+destruction.
+
+Fixes this lockdep splat:
+
+ ======================================================
+ WARNING: possible circular locking dependency detected
+ 6.2.0-rc8-debug+ #554 Not tainted
+ ------------------------------------------------------
+ ring0/132 is trying to acquire lock:
+ ffffff80871916d0 (&gmu->lock){+.+.}-{3:3}, at: a6xx_pm_resume+0xf0/0x234
+
+ but task is already holding lock:
+ ffffffdb5aee57e8 (dma_fence_map){++++}-{0:0}, at: msm_job_run+0x68/0x150
+
+ which lock already depends on the new lock.
+
+ the existing dependency chain (in reverse order) is:
+
+ -> #4 (dma_fence_map){++++}-{0:0}:
+ __dma_fence_might_wait+0x74/0xc0
+ dma_resv_lockdep+0x1f4/0x2f4
+ do_one_initcall+0x104/0x2bc
+ kernel_init_freeable+0x344/0x34c
+ kernel_init+0x30/0x134
+ ret_from_fork+0x10/0x20
+
+ -> #3 (mmu_notifier_invalidate_range_start){+.+.}-{0:0}:
+ fs_reclaim_acquire+0x80/0xa8
+ slab_pre_alloc_hook.constprop.0+0x40/0x25c
+ __kmem_cache_alloc_node+0x60/0x1cc
+ __kmalloc+0xd8/0x100
+ topology_parse_cpu_capacity+0x8c/0x178
+ get_cpu_for_node+0x88/0xc4
+ parse_cluster+0x1b0/0x28c
+ parse_cluster+0x8c/0x28c
+ init_cpu_topology+0x168/0x188
+ smp_prepare_cpus+0x24/0xf8
+ kernel_init_freeable+0x18c/0x34c
+ kernel_init+0x30/0x134
+ ret_from_fork+0x10/0x20
+
+ -> #2 (fs_reclaim){+.+.}-{0:0}:
+ __fs_reclaim_acquire+0x3c/0x48
+ fs_reclaim_acquire+0x54/0xa8
+ slab_pre_alloc_hook.constprop.0+0x40/0x25c
+ __kmem_cache_alloc_node+0x60/0x1cc
+ __kmalloc+0xd8/0x100
+ kzalloc.constprop.0+0x14/0x20
+ icc_node_create_nolock+0x4c/0xc4
+ icc_node_create+0x38/0x58
+ qcom_icc_rpmh_probe+0x1b8/0x248
+ platform_probe+0x70/0xc4
+ really_probe+0x158/0x290
+ __driver_probe_device+0xc8/0xe0
+ driver_probe_device+0x44/0x100
+ __driver_attach+0xf8/0x108
+ bus_for_each_dev+0x78/0xc4
+ driver_attach+0x2c/0x38
+ bus_add_driver+0xd0/0x1d8
+ driver_register+0xbc/0xf8
+ __platform_driver_register+0x30/0x3c
+ qnoc_driver_init+0x24/0x30
+ do_one_initcall+0x104/0x2bc
+ kernel_init_freeable+0x344/0x34c
+ kernel_init+0x30/0x134
+ ret_from_fork+0x10/0x20
+
+ -> #1 (icc_lock){+.+.}-{3:3}:
+ __mutex_lock+0xcc/0x3c8
+ mutex_lock_nested+0x30/0x44
+ icc_set_bw+0x88/0x2b4
+ _set_opp_bw+0x8c/0xd8
+ _set_opp+0x19c/0x300
+ dev_pm_opp_set_opp+0x84/0x94
+ a6xx_gmu_resume+0x18c/0x804
+ a6xx_pm_resume+0xf8/0x234
+ adreno_runtime_resume+0x2c/0x38
+ pm_generic_runtime_resume+0x30/0x44
+ __rpm_callback+0x15c/0x174
+ rpm_callback+0x78/0x7c
+ rpm_resume+0x318/0x524
+ __pm_runtime_resume+0x78/0xbc
+ adreno_load_gpu+0xc4/0x17c
+ msm_open+0x50/0x120
+ drm_file_alloc+0x17c/0x228
+ drm_open_helper+0x74/0x118
+ drm_open+0xa0/0x144
+ drm_stub_open+0xd4/0xe4
+ chrdev_open+0x1b8/0x1e4
+ do_dentry_open+0x2f8/0x38c
+ vfs_open+0x34/0x40
+ path_openat+0x64c/0x7b4
+ do_filp_open+0x54/0xc4
+ do_sys_openat2+0x9c/0x100
+ do_sys_open+0x50/0x7c
+ __arm64_sys_openat+0x28/0x34
+ invoke_syscall+0x8c/0x128
+ el0_svc_common.constprop.0+0xa0/0x11c
+ do_el0_svc+0xac/0xbc
+ el0_svc+0x48/0xa0
+ el0t_64_sync_handler+0xac/0x13c
+ el0t_64_sync+0x190/0x194
+
+ -> #0 (&gmu->lock){+.+.}-{3:3}:
+ __lock_acquire+0xe00/0x1060
+ lock_acquire+0x1e0/0x2f8
+ __mutex_lock+0xcc/0x3c8
+ mutex_lock_nested+0x30/0x44
+ a6xx_pm_resume+0xf0/0x234
+ adreno_runtime_resume+0x2c/0x38
+ pm_generic_runtime_resume+0x30/0x44
+ __rpm_callback+0x15c/0x174
+ rpm_callback+0x78/0x7c
+ rpm_resume+0x318/0x524
+ __pm_runtime_resume+0x78/0xbc
+ pm_runtime_get_sync.isra.0+0x14/0x20
+ msm_gpu_submit+0x58/0x178
+ msm_job_run+0x78/0x150
+ drm_sched_main+0x290/0x370
+ kthread+0xf0/0x100
+ ret_from_fork+0x10/0x20
+
+ other info that might help us debug this:
+
+ Chain exists of:
+ &gmu->lock --> mmu_notifier_invalidate_range_start --> dma_fence_map
+
+ Possible unsafe locking scenario:
+
+ CPU0 CPU1
+ ---- ----
+ lock(dma_fence_map);
+ lock(mmu_notifier_invalidate_range_start);
+ lock(dma_fence_map);
+ lock(&gmu->lock);
+
+ *** DEADLOCK ***
+
+ 2 locks held by ring0/132:
+ #0: ffffff8087191170 (&gpu->lock){+.+.}-{3:3}, at: msm_job_run+0x64/0x150
+ #1: ffffffdb5aee57e8 (dma_fence_map){++++}-{0:0}, at: msm_job_run+0x68/0x150
+
+ stack backtrace:
+ CPU: 7 PID: 132 Comm: ring0 Not tainted 6.2.0-rc8-debug+ #554
+ Hardware name: Google Lazor (rev1 - 2) with LTE (DT)
+ Call trace:
+ dump_backtrace.part.0+0xb4/0xf8
+ show_stack+0x20/0x38
+ dump_stack_lvl+0x9c/0xd0
+ dump_stack+0x18/0x34
+ print_circular_bug+0x1b4/0x1f0
+ check_noncircular+0x78/0xac
+ __lock_acquire+0xe00/0x1060
+ lock_acquire+0x1e0/0x2f8
+ __mutex_lock+0xcc/0x3c8
+ mutex_lock_nested+0x30/0x44
+ a6xx_pm_resume+0xf0/0x234
+ adreno_runtime_resume+0x2c/0x38
+ pm_generic_runtime_resume+0x30/0x44
+ __rpm_callback+0x15c/0x174
+ rpm_callback+0x78/0x7c
+ rpm_resume+0x318/0x524
+ __pm_runtime_resume+0x78/0xbc
+ pm_runtime_get_sync.isra.0+0x14/0x20
+ msm_gpu_submit+0x58/0x178
+ msm_job_run+0x78/0x150
+ drm_sched_main+0x290/0x370
+ kthread+0xf0/0x100
+ ret_from_fork+0x10/0x20
+
+Signed-off-by: Rob Clark <robdclark@chromium.org>
+Link: https://lore.kernel.org/r/20230807171148.210181-7-robdclark@gmail.com
+Signed-off-by: Georgi Djakov <djakov@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/interconnect/core.c | 8 ++++++--
+ 1 file changed, 6 insertions(+), 2 deletions(-)
+
+diff --git a/drivers/interconnect/core.c b/drivers/interconnect/core.c
+index 5fac448c28fda..e15a92a79df1a 100644
+--- a/drivers/interconnect/core.c
++++ b/drivers/interconnect/core.c
+@@ -28,6 +28,7 @@ static LIST_HEAD(icc_providers);
+ static int providers_count;
+ static bool synced_state;
+ static DEFINE_MUTEX(icc_lock);
++static DEFINE_MUTEX(icc_bw_lock);
+ static struct dentry *icc_debugfs_dir;
+
+ static void icc_summary_show_one(struct seq_file *s, struct icc_node *n)
+@@ -631,7 +632,7 @@ int icc_set_bw(struct icc_path *path, u32 avg_bw, u32 peak_bw)
+ if (WARN_ON(IS_ERR(path) || !path->num_nodes))
+ return -EINVAL;
+
+- mutex_lock(&icc_lock);
++ mutex_lock(&icc_bw_lock);
+
+ old_avg = path->reqs[0].avg_bw;
+ old_peak = path->reqs[0].peak_bw;
+@@ -663,7 +664,7 @@ int icc_set_bw(struct icc_path *path, u32 avg_bw, u32 peak_bw)
+ apply_constraints(path);
+ }
+
+- mutex_unlock(&icc_lock);
++ mutex_unlock(&icc_bw_lock);
+
+ trace_icc_set_bw_end(path, ret);
+
+@@ -872,6 +873,7 @@ void icc_node_add(struct icc_node *node, struct icc_provider *provider)
+ return;
+
+ mutex_lock(&icc_lock);
++ mutex_lock(&icc_bw_lock);
+
+ node->provider = provider;
+ list_add_tail(&node->node_list, &provider->nodes);
+@@ -900,6 +902,7 @@ void icc_node_add(struct icc_node *node, struct icc_provider *provider)
+ node->avg_bw = 0;
+ node->peak_bw = 0;
+
++ mutex_unlock(&icc_bw_lock);
+ mutex_unlock(&icc_lock);
+ }
+ EXPORT_SYMBOL_GPL(icc_node_add);
+@@ -1025,6 +1028,7 @@ void icc_sync_state(struct device *dev)
+ return;
+
+ mutex_lock(&icc_lock);
++ mutex_lock(&icc_bw_lock);
+ synced_state = true;
+ list_for_each_entry(p, &icc_providers, provider_list) {
+ dev_dbg(p->dev, "interconnect provider is in synced state\n");
+--
+2.40.1
+
--- /dev/null
+From 29f9b2894cfea72ed4c8c4b55307cae789094a8c Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 2 Aug 2023 14:38:01 -0600
+Subject: io_uring: annotate the struct io_kiocb slab for appropriate user copy
+
+From: Jens Axboe <axboe@kernel.dk>
+
+[ Upstream commit b97f96e22f051d59d07a527dbd7d90408b661ca8 ]
+
+When compiling the kernel with clang and having HARDENED_USERCOPY
+enabled, the liburing openat2.t test case fails during request setup:
+
+usercopy: Kernel memory overwrite attempt detected to SLUB object 'io_kiocb' (offset 24, size 24)!
+------------[ cut here ]------------
+kernel BUG at mm/usercopy.c:102!
+invalid opcode: 0000 [#1] PREEMPT SMP DEBUG_PAGEALLOC
+CPU: 3 PID: 413 Comm: openat2.t Tainted: G N 6.4.3-g6995e2de6891-dirty #19
+Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS rel-1.16.1-0-g3208b098f51a-prebuilt.qemu.org 04/01/2014
+RIP: 0010:usercopy_abort+0x84/0x90
+Code: ce 49 89 ce 48 c7 c3 68 48 98 82 48 0f 44 de 48 c7 c7 56 c6 94 82 4c 89 de 48 89 c1 41 52 41 56 53 e8 e0 51 c5 00 48 83 c4 18 <0f> 0b 66 2e 0f 1f 84 00 00 00 00 00 0f 1f 44 00 00 55 41 57 41 56
+RSP: 0018:ffffc900016b3da0 EFLAGS: 00010296
+RAX: 0000000000000062 RBX: ffffffff82984868 RCX: 4e9b661ac6275b00
+RDX: ffff8881b90ec580 RSI: ffffffff82949a64 RDI: 00000000ffffffff
+RBP: 0000000000000018 R08: 0000000000000000 R09: 0000000000000000
+R10: ffffc900016b3c88 R11: ffffc900016b3c30 R12: 00007ffe549659e0
+R13: ffff888119014000 R14: 0000000000000018 R15: 0000000000000018
+FS: 00007f862e3ca680(0000) GS:ffff8881b90c0000(0000) knlGS:0000000000000000
+CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
+CR2: 00005571483542a8 CR3: 0000000118c11000 CR4: 00000000003506e0
+Call Trace:
+ <TASK>
+ ? __die_body+0x63/0xb0
+ ? die+0x9d/0xc0
+ ? do_trap+0xa7/0x180
+ ? usercopy_abort+0x84/0x90
+ ? do_error_trap+0xc6/0x110
+ ? usercopy_abort+0x84/0x90
+ ? handle_invalid_op+0x2c/0x40
+ ? usercopy_abort+0x84/0x90
+ ? exc_invalid_op+0x2f/0x40
+ ? asm_exc_invalid_op+0x16/0x20
+ ? usercopy_abort+0x84/0x90
+ __check_heap_object+0xe2/0x110
+ __check_object_size+0x142/0x3d0
+ io_openat2_prep+0x68/0x140
+ io_submit_sqes+0x28a/0x680
+ __se_sys_io_uring_enter+0x120/0x580
+ do_syscall_64+0x3d/0x80
+ entry_SYSCALL_64_after_hwframe+0x46/0xb0
+RIP: 0033:0x55714834de26
+Code: ca 01 0f b6 82 d0 00 00 00 8b ba cc 00 00 00 45 31 c0 31 d2 41 b9 08 00 00 00 83 e0 01 c1 e0 04 41 09 c2 b8 aa 01 00 00 0f 05 <c3> 66 0f 1f 84 00 00 00 00 00 89 30 eb 89 0f 1f 40 00 8b 00 a8 06
+RSP: 002b:00007ffe549659c8 EFLAGS: 00000246 ORIG_RAX: 00000000000001aa
+RAX: ffffffffffffffda RBX: 00007ffe54965a50 RCX: 000055714834de26
+RDX: 0000000000000000 RSI: 0000000000000001 RDI: 0000000000000003
+RBP: 0000000000000000 R08: 0000000000000000 R09: 0000000000000008
+R10: 0000000000000000 R11: 0000000000000246 R12: 000055714834f057
+R13: 00007ffe54965a50 R14: 0000000000000001 R15: 0000557148351dd8
+ </TASK>
+Modules linked in:
+---[ end trace 0000000000000000 ]---
+
+when it tries to copy struct open_how from userspace into the per-command
+space in the io_kiocb. There's nothing wrong with the copy, but we're
+missing the appropriate annotations for allowing user copies to/from the
+io_kiocb slab.
+
+Allow copies in the per-command area, which is from the 'file' pointer to
+when 'opcode' starts. We do have existing user copies there, but they are
+not all annotated like the one that openat2_prep() uses,
+copy_struct_from_user(). But in practice opcodes should be allowed to
+copy data into their per-command area in the io_kiocb.
+
+Reported-by: Breno Leitao <leitao@debian.org>
+Signed-off-by: Jens Axboe <axboe@kernel.dk>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ io_uring/io_uring.c | 16 ++++++++++++++--
+ 1 file changed, 14 insertions(+), 2 deletions(-)
+
+diff --git a/io_uring/io_uring.c b/io_uring/io_uring.c
+index 4e9217c1eb2e0..a1562f2cf3f3c 100644
+--- a/io_uring/io_uring.c
++++ b/io_uring/io_uring.c
+@@ -4628,8 +4628,20 @@ static int __init io_uring_init(void)
+
+ io_uring_optable_init();
+
+- req_cachep = KMEM_CACHE(io_kiocb, SLAB_HWCACHE_ALIGN | SLAB_PANIC |
+- SLAB_ACCOUNT | SLAB_TYPESAFE_BY_RCU);
++ /*
++ * Allow user copy in the per-command field, which starts after the
++ * file in io_kiocb and until the opcode field. The openat2 handling
++ * requires copying in user memory into the io_kiocb object in that
++ * range, and HARDENED_USERCOPY will complain if we haven't
++ * correctly annotated this range.
++ */
++ req_cachep = kmem_cache_create_usercopy("io_kiocb",
++ sizeof(struct io_kiocb), 0,
++ SLAB_HWCACHE_ALIGN | SLAB_PANIC |
++ SLAB_ACCOUNT | SLAB_TYPESAFE_BY_RCU,
++ offsetof(struct io_kiocb, cmd.data),
++ sizeof_field(struct io_kiocb, cmd.data), NULL);
++
+ return 0;
+ };
+ __initcall(io_uring_init);
+--
+2.40.1
+
--- /dev/null
+From 569ce80392aab7dff975ebb74e7e8fd5fabe69bf Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 10 Jul 2023 14:12:22 -0700
+Subject: iomap: Fix possible overflow condition in iomap_write_delalloc_scan
+
+From: Ritesh Harjani (IBM) <ritesh.list@gmail.com>
+
+[ Upstream commit eee2d2e6ea5550118170dbd5bb1316ceb38455fb ]
+
+folio_next_index() returns an unsigned long value which left shifted
+by PAGE_SHIFT could possibly cause an overflow on 32-bit system. Instead
+use folio_pos(folio) + folio_size(folio), which does this correctly.
+
+Suggested-by: Matthew Wilcox <willy@infradead.org>
+Signed-off-by: Ritesh Harjani (IBM) <ritesh.list@gmail.com>
+Reviewed-by: Darrick J. Wong <djwong@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ fs/iomap/buffered-io.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/fs/iomap/buffered-io.c b/fs/iomap/buffered-io.c
+index 7d2f70708f37d..794fda5bd9bc6 100644
+--- a/fs/iomap/buffered-io.c
++++ b/fs/iomap/buffered-io.c
+@@ -927,7 +927,7 @@ static int iomap_write_delalloc_scan(struct inode *inode,
+ * the end of this data range, not the end of the folio.
+ */
+ *punch_start_byte = min_t(loff_t, end_byte,
+- folio_next_index(folio) << PAGE_SHIFT);
++ folio_pos(folio) + folio_size(folio));
+ }
+
+ /* move offset to start of next folio in range */
+--
+2.40.1
+
--- /dev/null
+From 56206bcf32ec03c2406c114f067ef0e595bdbbbc Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 1 Dec 2022 20:46:28 +0800
+Subject: jfs: fix invalid free of JFS_IP(ipimap)->i_imap in diUnmount
+
+From: Liu Shixin via Jfs-discussion <jfs-discussion@lists.sourceforge.net>
+
+[ Upstream commit 6e2bda2c192d0244b5a78b787ef20aa10cb319b7 ]
+
+syzbot found an invalid-free in diUnmount:
+
+BUG: KASAN: double-free in slab_free mm/slub.c:3661 [inline]
+BUG: KASAN: double-free in __kmem_cache_free+0x71/0x110 mm/slub.c:3674
+Free of addr ffff88806f410000 by task syz-executor131/3632
+
+ CPU: 0 PID: 3632 Comm: syz-executor131 Not tainted 6.1.0-rc7-syzkaller-00012-gca57f02295f1 #0
+ Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS Google 10/26/2022
+ Call Trace:
+ <TASK>
+ __dump_stack lib/dump_stack.c:88 [inline]
+ dump_stack_lvl+0x1b1/0x28e lib/dump_stack.c:106
+ print_address_description+0x74/0x340 mm/kasan/report.c:284
+ print_report+0x107/0x1f0 mm/kasan/report.c:395
+ kasan_report_invalid_free+0xac/0xd0 mm/kasan/report.c:460
+ ____kasan_slab_free+0xfb/0x120
+ kasan_slab_free include/linux/kasan.h:177 [inline]
+ slab_free_hook mm/slub.c:1724 [inline]
+ slab_free_freelist_hook+0x12e/0x1a0 mm/slub.c:1750
+ slab_free mm/slub.c:3661 [inline]
+ __kmem_cache_free+0x71/0x110 mm/slub.c:3674
+ diUnmount+0xef/0x100 fs/jfs/jfs_imap.c:195
+ jfs_umount+0x108/0x370 fs/jfs/jfs_umount.c:63
+ jfs_put_super+0x86/0x190 fs/jfs/super.c:194
+ generic_shutdown_super+0x130/0x310 fs/super.c:492
+ kill_block_super+0x79/0xd0 fs/super.c:1428
+ deactivate_locked_super+0xa7/0xf0 fs/super.c:332
+ cleanup_mnt+0x494/0x520 fs/namespace.c:1186
+ task_work_run+0x243/0x300 kernel/task_work.c:179
+ exit_task_work include/linux/task_work.h:38 [inline]
+ do_exit+0x664/0x2070 kernel/exit.c:820
+ do_group_exit+0x1fd/0x2b0 kernel/exit.c:950
+ __do_sys_exit_group kernel/exit.c:961 [inline]
+ __se_sys_exit_group kernel/exit.c:959 [inline]
+ __x64_sys_exit_group+0x3b/0x40 kernel/exit.c:959
+ do_syscall_x64 arch/x86/entry/common.c:50 [inline]
+ do_syscall_64+0x3d/0xb0 arch/x86/entry/common.c:80
+ entry_SYSCALL_64_after_hwframe+0x63/0xcd
+[...]
+
+JFS_IP(ipimap)->i_imap is not setting to NULL after free in diUnmount.
+If jfs_remount() free JFS_IP(ipimap)->i_imap but then failed at diMount().
+JFS_IP(ipimap)->i_imap will be freed once again.
+Fix this problem by setting JFS_IP(ipimap)->i_imap to NULL after free.
+
+Reported-by: syzbot+90a11e6b1e810785c6ff@syzkaller.appspotmail.com
+Signed-off-by: Liu Shixin <liushixin2@huawei.com>
+Signed-off-by: Dave Kleikamp <dave.kleikamp@oracle.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ fs/jfs/jfs_imap.c | 1 +
+ 1 file changed, 1 insertion(+)
+
+diff --git a/fs/jfs/jfs_imap.c b/fs/jfs/jfs_imap.c
+index 390cbfce391fc..6fb28572cb2c6 100644
+--- a/fs/jfs/jfs_imap.c
++++ b/fs/jfs/jfs_imap.c
+@@ -193,6 +193,7 @@ int diUnmount(struct inode *ipimap, int mounterror)
+ * free in-memory control structure
+ */
+ kfree(imap);
++ JFS_IP(ipimap)->i_imap = NULL;
+
+ return (0);
+ }
+--
+2.40.1
+
--- /dev/null
+From 9a15cb505648355b783756191e373224ea5f7546 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 14 Jun 2023 09:23:21 -0300
+Subject: kernel/fork: beware of __put_task_struct() calling context
+
+From: Wander Lairson Costa <wander@redhat.com>
+
+[ Upstream commit d243b34459cea30cfe5f3a9b2feb44e7daff9938 ]
+
+Under PREEMPT_RT, __put_task_struct() indirectly acquires sleeping
+locks. Therefore, it can't be called from an non-preemptible context.
+
+One practical example is splat inside inactive_task_timer(), which is
+called in a interrupt context:
+
+ CPU: 1 PID: 2848 Comm: life Kdump: loaded Tainted: G W ---------
+ Hardware name: HP ProLiant DL388p Gen8, BIOS P70 07/15/2012
+ Call Trace:
+ dump_stack_lvl+0x57/0x7d
+ mark_lock_irq.cold+0x33/0xba
+ mark_lock+0x1e7/0x400
+ mark_usage+0x11d/0x140
+ __lock_acquire+0x30d/0x930
+ lock_acquire.part.0+0x9c/0x210
+ rt_spin_lock+0x27/0xe0
+ refill_obj_stock+0x3d/0x3a0
+ kmem_cache_free+0x357/0x560
+ inactive_task_timer+0x1ad/0x340
+ __run_hrtimer+0x8a/0x1a0
+ __hrtimer_run_queues+0x91/0x130
+ hrtimer_interrupt+0x10f/0x220
+ __sysvec_apic_timer_interrupt+0x7b/0xd0
+ sysvec_apic_timer_interrupt+0x4f/0xd0
+ asm_sysvec_apic_timer_interrupt+0x12/0x20
+ RIP: 0033:0x7fff196bf6f5
+
+Instead of calling __put_task_struct() directly, we defer it using
+call_rcu(). A more natural approach would use a workqueue, but since
+in PREEMPT_RT, we can't allocate dynamic memory from atomic context,
+the code would become more complex because we would need to put the
+work_struct instance in the task_struct and initialize it when we
+allocate a new task_struct.
+
+The issue is reproducible with stress-ng:
+
+ while true; do
+ stress-ng --sched deadline --sched-period 1000000000 \
+ --sched-runtime 800000000 --sched-deadline \
+ 1000000000 --mmapfork 23 -t 20
+ done
+
+Reported-by: Hu Chunyu <chuhu@redhat.com>
+Suggested-by: Oleg Nesterov <oleg@redhat.com>
+Suggested-by: Valentin Schneider <vschneid@redhat.com>
+Suggested-by: Peter Zijlstra <peterz@infradead.org>
+Signed-off-by: Wander Lairson Costa <wander@redhat.com>
+Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
+Link: https://lore.kernel.org/r/20230614122323.37957-2-wander@redhat.com
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ include/linux/sched/task.h | 28 +++++++++++++++++++++++++++-
+ kernel/fork.c | 8 ++++++++
+ 2 files changed, 35 insertions(+), 1 deletion(-)
+
+diff --git a/include/linux/sched/task.h b/include/linux/sched/task.h
+index dd35ce28bb908..6b687c155fb6c 100644
+--- a/include/linux/sched/task.h
++++ b/include/linux/sched/task.h
+@@ -118,10 +118,36 @@ static inline struct task_struct *get_task_struct(struct task_struct *t)
+ }
+
+ extern void __put_task_struct(struct task_struct *t);
++extern void __put_task_struct_rcu_cb(struct rcu_head *rhp);
+
+ static inline void put_task_struct(struct task_struct *t)
+ {
+- if (refcount_dec_and_test(&t->usage))
++ if (!refcount_dec_and_test(&t->usage))
++ return;
++
++ /*
++ * under PREEMPT_RT, we can't call put_task_struct
++ * in atomic context because it will indirectly
++ * acquire sleeping locks.
++ *
++ * call_rcu() will schedule delayed_put_task_struct_rcu()
++ * to be called in process context.
++ *
++ * __put_task_struct() is called when
++ * refcount_dec_and_test(&t->usage) succeeds.
++ *
++ * This means that it can't "conflict" with
++ * put_task_struct_rcu_user() which abuses ->rcu the same
++ * way; rcu_users has a reference so task->usage can't be
++ * zero after rcu_users 1 -> 0 transition.
++ *
++ * delayed_free_task() also uses ->rcu, but it is only called
++ * when it fails to fork a process. Therefore, there is no
++ * way it can conflict with put_task_struct().
++ */
++ if (IS_ENABLED(CONFIG_PREEMPT_RT) && !preemptible())
++ call_rcu(&t->rcu, __put_task_struct_rcu_cb);
++ else
+ __put_task_struct(t);
+ }
+
+diff --git a/kernel/fork.c b/kernel/fork.c
+index d2e12b6d2b180..f81149739eb9f 100644
+--- a/kernel/fork.c
++++ b/kernel/fork.c
+@@ -985,6 +985,14 @@ void __put_task_struct(struct task_struct *tsk)
+ }
+ EXPORT_SYMBOL_GPL(__put_task_struct);
+
++void __put_task_struct_rcu_cb(struct rcu_head *rhp)
++{
++ struct task_struct *task = container_of(rhp, struct task_struct, rcu);
++
++ __put_task_struct(task);
++}
++EXPORT_SYMBOL_GPL(__put_task_struct_rcu_cb);
++
+ void __init __weak arch_task_cache_init(void) { }
+
+ /*
+--
+2.40.1
+
--- /dev/null
+From 739da96e344561b58bc8a6ef86e66d9489daf63e Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sat, 5 Aug 2023 16:41:13 +0800
+Subject: kobject: Add sanity check for kset->kobj.ktype in kset_register()
+
+From: Zhen Lei <thunder.leizhen@huawei.com>
+
+[ Upstream commit 4d0fe8c52bb3029d83e323c961221156ab98680b ]
+
+When I register a kset in the following way:
+ static struct kset my_kset;
+ kobject_set_name(&my_kset.kobj, "my_kset");
+ ret = kset_register(&my_kset);
+
+A null pointer dereference exception is occurred:
+[ 4453.568337] Unable to handle kernel NULL pointer dereference at \
+virtual address 0000000000000028
+... ...
+[ 4453.810361] Call trace:
+[ 4453.813062] kobject_get_ownership+0xc/0x34
+[ 4453.817493] kobject_add_internal+0x98/0x274
+[ 4453.822005] kset_register+0x5c/0xb4
+[ 4453.825820] my_kobj_init+0x44/0x1000 [my_kset]
+... ...
+
+Because I didn't initialize my_kset.kobj.ktype.
+
+According to the description in Documentation/core-api/kobject.rst:
+ - A ktype is the type of object that embeds a kobject. Every structure
+ that embeds a kobject needs a corresponding ktype.
+
+So add sanity check to make sure kset->kobj.ktype is not NULL.
+
+Signed-off-by: Zhen Lei <thunder.leizhen@huawei.com>
+Link: https://lore.kernel.org/r/20230805084114.1298-2-thunder.leizhen@huaweicloud.com
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ lib/kobject.c | 5 +++++
+ 1 file changed, 5 insertions(+)
+
+diff --git a/lib/kobject.c b/lib/kobject.c
+index 16d530f9c174b..4c7a990d6f120 100644
+--- a/lib/kobject.c
++++ b/lib/kobject.c
+@@ -854,6 +854,11 @@ int kset_register(struct kset *k)
+ if (!k)
+ return -EINVAL;
+
++ if (!k->kobj.ktype) {
++ pr_err("must have a ktype to be initialized properly!\n");
++ return -EINVAL;
++ }
++
+ kset_init(k);
+ err = kobject_add_internal(&k->kobj);
+ if (err) {
+--
+2.40.1
+
--- /dev/null
+From 159d05f1029d60bee18bba46d48b5bc20600d39c Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 15 Aug 2023 15:49:15 +0800
+Subject: kselftest/arm64: fix a memleak in zt_regs_run()
+
+From: Ding Xiang <dingxiang@cmss.chinamobile.com>
+
+[ Upstream commit 46862da15e37efedb7d2d21e167f506c0b533772 ]
+
+If memcmp() does not return 0, "zeros" need to be freed to prevent memleak
+
+Signed-off-by: Ding Xiang <dingxiang@cmss.chinamobile.com>
+Link: https://lore.kernel.org/r/20230815074915.245528-1-dingxiang@cmss.chinamobile.com
+Signed-off-by: Will Deacon <will@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ tools/testing/selftests/arm64/signal/testcases/zt_regs.c | 1 +
+ 1 file changed, 1 insertion(+)
+
+diff --git a/tools/testing/selftests/arm64/signal/testcases/zt_regs.c b/tools/testing/selftests/arm64/signal/testcases/zt_regs.c
+index e1eb4d5c027ab..2e384d731618b 100644
+--- a/tools/testing/selftests/arm64/signal/testcases/zt_regs.c
++++ b/tools/testing/selftests/arm64/signal/testcases/zt_regs.c
+@@ -65,6 +65,7 @@ int zt_regs_run(struct tdescr *td, siginfo_t *si, ucontext_t *uc)
+ if (memcmp(zeros, (char *)zt + ZT_SIG_REGS_OFFSET,
+ ZT_SIG_REGS_SIZE(zt->nregs)) != 0) {
+ fprintf(stderr, "ZT data invalid\n");
++ free(zeros);
+ return 1;
+ }
+
+--
+2.40.1
+
--- /dev/null
+From 65c39a29590502dc02985d5f6452acf29b27ad04 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 22 Aug 2023 12:38:40 -0700
+Subject: libbpf: Free btf_vmlinux when closing bpf_object
+
+From: Hao Luo <haoluo@google.com>
+
+[ Upstream commit 29d67fdebc42af6466d1909c60fdd1ef4f3e5240 ]
+
+I hit a memory leak when testing bpf_program__set_attach_target().
+Basically, set_attach_target() may allocate btf_vmlinux, for example,
+when setting attach target for bpf_iter programs. But btf_vmlinux
+is freed only in bpf_object_load(), which means if we only open
+bpf object but not load it, setting attach target may leak
+btf_vmlinux.
+
+So let's free btf_vmlinux in bpf_object__close() anyway.
+
+Signed-off-by: Hao Luo <haoluo@google.com>
+Signed-off-by: Andrii Nakryiko <andrii@kernel.org>
+Link: https://lore.kernel.org/bpf/20230822193840.1509809-1-haoluo@google.com
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ tools/lib/bpf/libbpf.c | 1 +
+ 1 file changed, 1 insertion(+)
+
+diff --git a/tools/lib/bpf/libbpf.c b/tools/lib/bpf/libbpf.c
+index e07dff7eba600..13b5623b720f1 100644
+--- a/tools/lib/bpf/libbpf.c
++++ b/tools/lib/bpf/libbpf.c
+@@ -8356,6 +8356,7 @@ void bpf_object__close(struct bpf_object *obj)
+ bpf_object__elf_finish(obj);
+ bpf_object_unload(obj);
+ btf__free(obj->btf);
++ btf__free(obj->btf_vmlinux);
+ btf_ext__free(obj->btf_ext);
+
+ for (i = 0; i < obj->nr_maps; i++)
+--
+2.40.1
+
--- /dev/null
+From 9f7bb89950b68d2c402b0a85bf636a1087e6a4a9 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 21 Jul 2023 13:19:04 +0800
+Subject: locks: fix KASAN: use-after-free in
+ trace_event_raw_event_filelock_lock
+
+From: Will Shiu <Will.Shiu@mediatek.com>
+
+[ Upstream commit 74f6f5912693ce454384eaeec48705646a21c74f ]
+
+As following backtrace, the struct file_lock request , in posix_lock_inode
+is free before ftrace function using.
+Replace the ftrace function ahead free flow could fix the use-after-free
+issue.
+
+[name:report&]===============================================
+BUG:KASAN: use-after-free in trace_event_raw_event_filelock_lock+0x80/0x12c
+[name:report&]Read at addr f6ffff8025622620 by task NativeThread/16753
+[name:report_hw_tags&]Pointer tag: [f6], memory tag: [fe]
+[name:report&]
+BT:
+Hardware name: MT6897 (DT)
+Call trace:
+ dump_backtrace+0xf8/0x148
+ show_stack+0x18/0x24
+ dump_stack_lvl+0x60/0x7c
+ print_report+0x2c8/0xa08
+ kasan_report+0xb0/0x120
+ __do_kernel_fault+0xc8/0x248
+ do_bad_area+0x30/0xdc
+ do_tag_check_fault+0x1c/0x30
+ do_mem_abort+0x58/0xbc
+ el1_abort+0x3c/0x5c
+ el1h_64_sync_handler+0x54/0x90
+ el1h_64_sync+0x68/0x6c
+ trace_event_raw_event_filelock_lock+0x80/0x12c
+ posix_lock_inode+0xd0c/0xd60
+ do_lock_file_wait+0xb8/0x190
+ fcntl_setlk+0x2d8/0x440
+...
+[name:report&]
+[name:report&]Allocated by task 16752:
+...
+ slab_post_alloc_hook+0x74/0x340
+ kmem_cache_alloc+0x1b0/0x2f0
+ posix_lock_inode+0xb0/0xd60
+...
+ [name:report&]
+ [name:report&]Freed by task 16752:
+...
+ kmem_cache_free+0x274/0x5b0
+ locks_dispose_list+0x3c/0x148
+ posix_lock_inode+0xc40/0xd60
+ do_lock_file_wait+0xb8/0x190
+ fcntl_setlk+0x2d8/0x440
+ do_fcntl+0x150/0xc18
+...
+
+Signed-off-by: Will Shiu <Will.Shiu@mediatek.com>
+Signed-off-by: Jeff Layton <jlayton@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ fs/locks.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/fs/locks.c b/fs/locks.c
+index df8b26a425248..a552bdb6badc0 100644
+--- a/fs/locks.c
++++ b/fs/locks.c
+@@ -1301,6 +1301,7 @@ static int posix_lock_inode(struct inode *inode, struct file_lock *request,
+ out:
+ spin_unlock(&ctx->flc_lock);
+ percpu_up_read(&file_rwsem);
++ trace_posix_lock_inode(inode, request, error);
+ /*
+ * Free any unused locks.
+ */
+@@ -1309,7 +1310,6 @@ static int posix_lock_inode(struct inode *inode, struct file_lock *request,
+ if (new_fl2)
+ locks_free_lock(new_fl2);
+ locks_dispose_list(&dispose);
+- trace_posix_lock_inode(inode, request, error);
+
+ return error;
+ }
+--
+2.40.1
+
--- /dev/null
+From 9308ea378e77610f8a79dd345156bf4b01c0ada0 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 25 Aug 2023 10:55:31 +0800
+Subject: md: don't dereference mddev after export_rdev()
+
+From: Yu Kuai <yukuai3@huawei.com>
+
+[ Upstream commit 7deac114be5fb25a4e865212ed0feaf5f85f2a28 ]
+
+Except for initial reference, mddev->kobject is referenced by
+rdev->kobject, and if the last rdev is freed, there is no guarantee that
+mddev is still valid. Hence mddev should not be used anymore after
+export_rdev().
+
+This problem can be triggered by following test for mdadm at very
+low rate:
+
+New file: mdadm/tests/23rdev-lifetime
+
+devname=${dev0##*/}
+devt=`cat /sys/block/$devname/dev`
+pid=""
+runtime=2
+
+clean_up_test() {
+ pill -9 $pid
+ echo clear > /sys/block/md0/md/array_state
+}
+
+trap 'clean_up_test' EXIT
+
+add_by_sysfs() {
+ while true; do
+ echo $devt > /sys/block/md0/md/new_dev
+ done
+}
+
+remove_by_sysfs(){
+ while true; do
+ echo remove > /sys/block/md0/md/dev-${devname}/state
+ done
+}
+
+echo md0 > /sys/module/md_mod/parameters/new_array || die "create md0 failed"
+
+add_by_sysfs &
+pid="$pid $!"
+
+remove_by_sysfs &
+pid="$pid $!"
+
+sleep $runtime
+exit 0
+
+Test cmd:
+
+./test --save-logs --logdir=/tmp/ --keep-going --dev=loop --tests=23rdev-lifetime
+
+Test result:
+
+general protection fault, probably for non-canonical address 0x6b6b6b6b6b6b6bcb: 0000 [#4] PREEMPT SMP
+CPU: 0 PID: 1292 Comm: test Tainted: G D W 6.5.0-rc2-00121-g01e55c376936 #562
+RIP: 0010:md_wakeup_thread+0x9e/0x320 [md_mod]
+Call Trace:
+ <TASK>
+ mddev_unlock+0x1b6/0x310 [md_mod]
+ rdev_attr_store+0xec/0x190 [md_mod]
+ sysfs_kf_write+0x52/0x70
+ kernfs_fop_write_iter+0x19a/0x2a0
+ vfs_write+0x3b5/0x770
+ ksys_write+0x74/0x150
+ __x64_sys_write+0x22/0x30
+ do_syscall_64+0x40/0x90
+ entry_SYSCALL_64_after_hwframe+0x63/0xcd
+
+Fix this problem by don't dereference mddev after export_rdev().
+
+Fixes: 3ce94ce5d05a ("md: fix duplicate filename for rdev")
+Signed-off-by: Yu Kuai <yukuai3@huawei.com>
+Signed-off-by: Song Liu <song@kernel.org>
+Link: https://lore.kernel.org/r/20230825025532.1523008-2-yukuai1@huaweicloud.com
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/md/md.c | 6 +++---
+ 1 file changed, 3 insertions(+), 3 deletions(-)
+
+diff --git a/drivers/md/md.c b/drivers/md/md.c
+index 2a4a3d3039fae..fba2809cd384a 100644
+--- a/drivers/md/md.c
++++ b/drivers/md/md.c
+@@ -798,14 +798,14 @@ void mddev_unlock(struct mddev *mddev)
+ } else
+ mutex_unlock(&mddev->reconfig_mutex);
+
++ md_wakeup_thread(mddev->thread);
++ wake_up(&mddev->sb_wait);
++
+ list_for_each_entry_safe(rdev, tmp, &delete, same_set) {
+ list_del_init(&rdev->same_set);
+ kobject_del(&rdev->kobj);
+ export_rdev(rdev, mddev);
+ }
+-
+- md_wakeup_thread(mddev->thread);
+- wake_up(&mddev->sb_wait);
+ }
+ EXPORT_SYMBOL_GPL(mddev_unlock);
+
+--
+2.40.1
+
--- /dev/null
+From 3fdf3c8479dc83ac79470e580b1d2a8feca8b618 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 25 Aug 2023 10:55:32 +0800
+Subject: md: fix warning for holder mismatch from export_rdev()
+
+From: Yu Kuai <yukuai3@huawei.com>
+
+[ Upstream commit 99892147f028d711f9d40fefad4f33632593864c ]
+
+Commit a1d767191096 ("md: use mddev->external to select holder in
+export_rdev()") fix the problem that 'claim_rdev' is used for
+blkdev_get_by_dev() while 'rdev' is used for blkdev_put().
+
+However, if mddev->external is changed from 0 to 1, then 'rdev' is used
+for blkdev_get_by_dev() while 'claim_rdev' is used for blkdev_put(). And
+this problem can be reporduced reliably by following:
+
+New file: mdadm/tests/23rdev-lifetime
+
+devname=${dev0##*/}
+devt=`cat /sys/block/$devname/dev`
+pid=""
+runtime=2
+
+clean_up_test() {
+ pill -9 $pid
+ echo clear > /sys/block/md0/md/array_state
+}
+
+trap 'clean_up_test' EXIT
+
+add_by_sysfs() {
+ while true; do
+ echo $devt > /sys/block/md0/md/new_dev
+ done
+}
+
+remove_by_sysfs(){
+ while true; do
+ echo remove > /sys/block/md0/md/dev-${devname}/state
+ done
+}
+
+echo md0 > /sys/module/md_mod/parameters/new_array || die "create md0 failed"
+
+add_by_sysfs &
+pid="$pid $!"
+
+remove_by_sysfs &
+pid="$pid $!"
+
+sleep $runtime
+exit 0
+
+Test cmd:
+
+./test --save-logs --logdir=/tmp/ --keep-going --dev=loop --tests=23rdev-lifetime
+
+Test result:
+
+------------[ cut here ]------------
+WARNING: CPU: 0 PID: 960 at block/bdev.c:618 blkdev_put+0x27c/0x330
+Modules linked in: multipath md_mod loop
+CPU: 0 PID: 960 Comm: test Not tainted 6.5.0-rc2-00121-g01e55c376936-dirty #50
+RIP: 0010:blkdev_put+0x27c/0x330
+Call Trace:
+ <TASK>
+ export_rdev.isra.23+0x50/0xa0 [md_mod]
+ mddev_unlock+0x19d/0x300 [md_mod]
+ rdev_attr_store+0xec/0x190 [md_mod]
+ sysfs_kf_write+0x52/0x70
+ kernfs_fop_write_iter+0x19a/0x2a0
+ vfs_write+0x3b5/0x770
+ ksys_write+0x74/0x150
+ __x64_sys_write+0x22/0x30
+ do_syscall_64+0x40/0x90
+ entry_SYSCALL_64_after_hwframe+0x63/0xcd
+
+Fix the problem by recording if 'rdev' is used as holder.
+
+Fixes: a1d767191096 ("md: use mddev->external to select holder in export_rdev()")
+Signed-off-by: Yu Kuai <yukuai3@huawei.com>
+Signed-off-by: Song Liu <song@kernel.org>
+Link: https://lore.kernel.org/r/20230825025532.1523008-3-yukuai1@huaweicloud.com
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/md/md.c | 15 ++++++++++++---
+ drivers/md/md.h | 3 +++
+ 2 files changed, 15 insertions(+), 3 deletions(-)
+
+diff --git a/drivers/md/md.c b/drivers/md/md.c
+index fba2809cd384a..06a8ccdb5135d 100644
+--- a/drivers/md/md.c
++++ b/drivers/md/md.c
+@@ -2452,7 +2452,8 @@ static void export_rdev(struct md_rdev *rdev, struct mddev *mddev)
+ if (test_bit(AutoDetected, &rdev->flags))
+ md_autodetect_dev(rdev->bdev->bd_dev);
+ #endif
+- blkdev_put(rdev->bdev, mddev->external ? &claim_rdev : rdev);
++ blkdev_put(rdev->bdev,
++ test_bit(Holder, &rdev->flags) ? rdev : &claim_rdev);
+ rdev->bdev = NULL;
+ kobject_put(&rdev->kobj);
+ }
+@@ -3632,6 +3633,7 @@ EXPORT_SYMBOL_GPL(md_rdev_init);
+ static struct md_rdev *md_import_device(dev_t newdev, int super_format, int super_minor)
+ {
+ struct md_rdev *rdev;
++ struct md_rdev *holder;
+ sector_t size;
+ int err;
+
+@@ -3646,8 +3648,15 @@ static struct md_rdev *md_import_device(dev_t newdev, int super_format, int supe
+ if (err)
+ goto out_clear_rdev;
+
++ if (super_format == -2) {
++ holder = &claim_rdev;
++ } else {
++ holder = rdev;
++ set_bit(Holder, &rdev->flags);
++ }
++
+ rdev->bdev = blkdev_get_by_dev(newdev, BLK_OPEN_READ | BLK_OPEN_WRITE,
+- super_format == -2 ? &claim_rdev : rdev, NULL);
++ holder, NULL);
+ if (IS_ERR(rdev->bdev)) {
+ pr_warn("md: could not open device unknown-block(%u,%u).\n",
+ MAJOR(newdev), MINOR(newdev));
+@@ -3684,7 +3693,7 @@ static struct md_rdev *md_import_device(dev_t newdev, int super_format, int supe
+ return rdev;
+
+ out_blkdev_put:
+- blkdev_put(rdev->bdev, super_format == -2 ? &claim_rdev : rdev);
++ blkdev_put(rdev->bdev, holder);
+ out_clear_rdev:
+ md_rdev_clear(rdev);
+ out_free_rdev:
+diff --git a/drivers/md/md.h b/drivers/md/md.h
+index 1aef86bf3fc31..b0a0f5a5c7836 100644
+--- a/drivers/md/md.h
++++ b/drivers/md/md.h
+@@ -211,6 +211,9 @@ enum flag_bits {
+ * check if there is collision between raid1
+ * serial bios.
+ */
++ Holder, /* rdev is used as holder while opening
++ * underlying disk exclusively.
++ */
+ };
+
+ static inline int is_badblock(struct md_rdev *rdev, sector_t s, int sectors,
+--
+2.40.1
+
--- /dev/null
+From 9401b654fb8fd3a84a73316b9d7af924f17c7046 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 11 Sep 2023 14:25:23 -0700
+Subject: md/raid1: fix error: ISO C90 forbids mixed declarations
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Nigel Croxon <ncroxon@redhat.com>
+
+[ Upstream commit df203da47f4428bc286fc99318936416253a321c ]
+
+There is a compile error when this commit is added:
+md: raid1: fix potential OOB in raid1_remove_disk()
+
+drivers/md/raid1.c: In function 'raid1_remove_disk':
+drivers/md/raid1.c:1844:9: error: ISO C90 forbids mixed declarations
+and code [-Werror=declaration-after-statement]
+1844 |Â Â Â Â Â Â Â Â struct raid1_info *p = conf->mirrors + number;
+ Â Â Â Â |Â Â Â Â Â Â Â Â ^~~~~~
+
+That's because the new code was inserted before the struct.
+The change is move the struct command above this commit.
+
+Fixes: 8b0472b50bcf ("md: raid1: fix potential OOB in raid1_remove_disk()")
+Signed-off-by: Nigel Croxon <ncroxon@redhat.com>
+Signed-off-by: Song Liu <song@kernel.org>
+Link: https://lore.kernel.org/r/46d929d0-2aab-4cf2-b2bf-338963e8ba5a@redhat.com
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/md/raid1.c | 3 +--
+ 1 file changed, 1 insertion(+), 2 deletions(-)
+
+diff --git a/drivers/md/raid1.c b/drivers/md/raid1.c
+index 80aeee63dfb78..a60acd72210aa 100644
+--- a/drivers/md/raid1.c
++++ b/drivers/md/raid1.c
+@@ -1829,12 +1829,11 @@ static int raid1_remove_disk(struct mddev *mddev, struct md_rdev *rdev)
+ struct r1conf *conf = mddev->private;
+ int err = 0;
+ int number = rdev->raid_disk;
++ struct raid1_info *p = conf->mirrors + number;
+
+ if (unlikely(number >= conf->raid_disks))
+ goto abort;
+
+- struct raid1_info *p = conf->mirrors + number;
+-
+ if (rdev != p->rdev)
+ p = conf->mirrors + conf->raid_disks + number;
+
+--
+2.40.1
+
--- /dev/null
+From e5abf80d4ad8c4714a7d953ff7c7bae372883da2 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sat, 22 Jul 2023 15:53:53 +0800
+Subject: md: raid1: fix potential OOB in raid1_remove_disk()
+
+From: Zhang Shurong <zhang_shurong@foxmail.com>
+
+[ Upstream commit 8b0472b50bcf0f19a5119b00a53b63579c8e1e4d ]
+
+If rddev->raid_disk is greater than mddev->raid_disks, there will be
+an out-of-bounds in raid1_remove_disk(). We have already found
+similar reports as follows:
+
+1) commit d17f744e883b ("md-raid10: fix KASAN warning")
+2) commit 1ebc2cec0b7d ("dm raid: fix KASAN warning in raid5_remove_disk")
+
+Fix this bug by checking whether the "number" variable is
+valid.
+
+Signed-off-by: Zhang Shurong <zhang_shurong@foxmail.com>
+Reviewed-by: Yu Kuai <yukuai3@huawei.com>
+Link: https://lore.kernel.org/r/tencent_0D24426FAC6A21B69AC0C03CE4143A508F09@qq.com
+Signed-off-by: Song Liu <song@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/md/raid1.c | 4 ++++
+ 1 file changed, 4 insertions(+)
+
+diff --git a/drivers/md/raid1.c b/drivers/md/raid1.c
+index dd25832eb0452..80aeee63dfb78 100644
+--- a/drivers/md/raid1.c
++++ b/drivers/md/raid1.c
+@@ -1829,6 +1829,10 @@ static int raid1_remove_disk(struct mddev *mddev, struct md_rdev *rdev)
+ struct r1conf *conf = mddev->private;
+ int err = 0;
+ int number = rdev->raid_disk;
++
++ if (unlikely(number >= conf->raid_disks))
++ goto abort;
++
+ struct raid1_info *p = conf->mirrors + number;
+
+ if (rdev != p->rdev)
+--
+2.40.1
+
--- /dev/null
+From b0a266dd48cb8c69d58d5bcae24fc620660a44b1 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sat, 8 Jul 2023 23:24:11 +0800
+Subject: media: af9005: Fix null-ptr-deref in af9005_i2c_xfer
+
+From: Zhang Shurong <zhang_shurong@foxmail.com>
+
+[ Upstream commit f4ee84f27625ce1fdf41e8483fa0561a1b837d10 ]
+
+In af9005_i2c_xfer, msg is controlled by user. When msg[i].buf
+is null and msg[i].len is zero, former checks on msg[i].buf would be
+passed. Malicious data finally reach af9005_i2c_xfer. If accessing
+msg[i].buf[0] without sanity check, null ptr deref would happen.
+We add check on msg[i].len to prevent crash.
+
+Similar commit:
+commit 0ed554fd769a
+("media: dvb-usb: az6027: fix null-ptr-deref in az6027_i2c_xfer()")
+
+Signed-off-by: Zhang Shurong <zhang_shurong@foxmail.com>
+Signed-off-by: Hans Verkuil <hverkuil-cisco@xs4all.nl>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/media/usb/dvb-usb/af9005.c | 5 +++++
+ 1 file changed, 5 insertions(+)
+
+diff --git a/drivers/media/usb/dvb-usb/af9005.c b/drivers/media/usb/dvb-usb/af9005.c
+index 0827bf3d4e8c7..13604e6acdb83 100644
+--- a/drivers/media/usb/dvb-usb/af9005.c
++++ b/drivers/media/usb/dvb-usb/af9005.c
+@@ -422,6 +422,10 @@ static int af9005_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msg[],
+ if (ret == 0)
+ ret = 2;
+ } else {
++ if (msg[0].len < 2) {
++ ret = -EOPNOTSUPP;
++ goto unlock;
++ }
+ /* write one or more registers */
+ reg = msg[0].buf[0];
+ addr = msg[0].addr;
+@@ -431,6 +435,7 @@ static int af9005_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msg[],
+ ret = 1;
+ }
+
++unlock:
+ mutex_unlock(&d->i2c_mutex);
+ return ret;
+ }
+--
+2.40.1
+
--- /dev/null
+From 749dd1e56f58cb5273a03a62c82d88ff88401d03 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sun, 9 Jul 2023 00:02:20 +0800
+Subject: media: anysee: fix null-ptr-deref in anysee_master_xfer
+
+From: Zhang Shurong <zhang_shurong@foxmail.com>
+
+[ Upstream commit c30411266fd67ea3c02a05c157231654d5a3bdc9 ]
+
+In anysee_master_xfer, msg is controlled by user. When msg[i].buf
+is null and msg[i].len is zero, former checks on msg[i].buf would be
+passed. Malicious data finally reach anysee_master_xfer. If accessing
+msg[i].buf[0] without sanity check, null ptr deref would happen.
+We add check on msg[i].len to prevent crash.
+
+Similar commit:
+commit 0ed554fd769a
+("media: dvb-usb: az6027: fix null-ptr-deref in az6027_i2c_xfer()")
+
+Signed-off-by: Zhang Shurong <zhang_shurong@foxmail.com>
+Signed-off-by: Hans Verkuil <hverkuil-cisco@xs4all.nl>
+[hverkuil: add spaces around +]
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/media/usb/dvb-usb-v2/anysee.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/drivers/media/usb/dvb-usb-v2/anysee.c b/drivers/media/usb/dvb-usb-v2/anysee.c
+index aa45b5d263f6b..a1235d0cce92f 100644
+--- a/drivers/media/usb/dvb-usb-v2/anysee.c
++++ b/drivers/media/usb/dvb-usb-v2/anysee.c
+@@ -202,7 +202,7 @@ static int anysee_master_xfer(struct i2c_adapter *adap, struct i2c_msg *msg,
+
+ while (i < num) {
+ if (num > i + 1 && (msg[i+1].flags & I2C_M_RD)) {
+- if (msg[i].len > 2 || msg[i+1].len > 60) {
++ if (msg[i].len != 2 || msg[i + 1].len > 60) {
+ ret = -EOPNOTSUPP;
+ break;
+ }
+--
+2.40.1
+
--- /dev/null
+From 4303f0e4febbc49f2a1d511ddf4a26dedf0c76fb Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sun, 9 Jul 2023 00:28:17 +0800
+Subject: media: az6007: Fix null-ptr-deref in az6007_i2c_xfer()
+
+From: Zhang Shurong <zhang_shurong@foxmail.com>
+
+[ Upstream commit 1047f9343011f2cedc73c64829686206a7e9fc3f ]
+
+In az6007_i2c_xfer, msg is controlled by user. When msg[i].buf
+is null and msg[i].len is zero, former checks on msg[i].buf would be
+passed. Malicious data finally reach az6007_i2c_xfer. If accessing
+msg[i].buf[0] without sanity check, null ptr deref would happen.
+We add check on msg[i].len to prevent crash.
+
+Similar commit:
+commit 0ed554fd769a
+("media: dvb-usb: az6027: fix null-ptr-deref in az6027_i2c_xfer()")
+
+Signed-off-by: Zhang Shurong <zhang_shurong@foxmail.com>
+Signed-off-by: Hans Verkuil <hverkuil-cisco@xs4all.nl>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/media/usb/dvb-usb-v2/az6007.c | 8 ++++++++
+ 1 file changed, 8 insertions(+)
+
+diff --git a/drivers/media/usb/dvb-usb-v2/az6007.c b/drivers/media/usb/dvb-usb-v2/az6007.c
+index 2dcbb49d66dab..2410054ddb2c3 100644
+--- a/drivers/media/usb/dvb-usb-v2/az6007.c
++++ b/drivers/media/usb/dvb-usb-v2/az6007.c
+@@ -788,6 +788,10 @@ static int az6007_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[],
+ if (az6007_xfer_debug)
+ printk(KERN_DEBUG "az6007: I2C W addr=0x%x len=%d\n",
+ addr, msgs[i].len);
++ if (msgs[i].len < 1) {
++ ret = -EIO;
++ goto err;
++ }
+ req = AZ6007_I2C_WR;
+ index = msgs[i].buf[0];
+ value = addr | (1 << 8);
+@@ -802,6 +806,10 @@ static int az6007_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[],
+ if (az6007_xfer_debug)
+ printk(KERN_DEBUG "az6007: I2C R addr=0x%x len=%d\n",
+ addr, msgs[i].len);
++ if (msgs[i].len < 1) {
++ ret = -EIO;
++ goto err;
++ }
+ req = AZ6007_I2C_RD;
+ index = msgs[i].buf[0];
+ value = addr;
+--
+2.40.1
+
--- /dev/null
+From 31ec1ff1f4e0ca78943cfc77007c49a6113858ad Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 6 Jul 2023 00:06:54 +0800
+Subject: media: dvb-usb-v2: af9035: Fix null-ptr-deref in
+ af9035_i2c_master_xfer
+
+From: Zhang Shurong <zhang_shurong@foxmail.com>
+
+[ Upstream commit 7bf744f2de0a848fb1d717f5831b03db96feae89 ]
+
+In af9035_i2c_master_xfer, msg is controlled by user. When msg[i].buf
+is null and msg[i].len is zero, former checks on msg[i].buf would be
+passed. Malicious data finally reach af9035_i2c_master_xfer. If accessing
+msg[i].buf[0] without sanity check, null ptr deref would happen.
+We add check on msg[i].len to prevent crash.
+
+Similar commit:
+commit 0ed554fd769a
+("media: dvb-usb: az6027: fix null-ptr-deref in az6027_i2c_xfer()")
+
+Signed-off-by: Zhang Shurong <zhang_shurong@foxmail.com>
+Signed-off-by: Hans Verkuil <hverkuil-cisco@xs4all.nl>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/media/usb/dvb-usb-v2/af9035.c | 9 +++++----
+ 1 file changed, 5 insertions(+), 4 deletions(-)
+
+diff --git a/drivers/media/usb/dvb-usb-v2/af9035.c b/drivers/media/usb/dvb-usb-v2/af9035.c
+index 1e9c8d01523be..33a2aa8907e65 100644
+--- a/drivers/media/usb/dvb-usb-v2/af9035.c
++++ b/drivers/media/usb/dvb-usb-v2/af9035.c
+@@ -322,6 +322,8 @@ static int af9035_i2c_master_xfer(struct i2c_adapter *adap,
+ ret = -EOPNOTSUPP;
+ } else if ((msg[0].addr == state->af9033_i2c_addr[0]) ||
+ (msg[0].addr == state->af9033_i2c_addr[1])) {
++ if (msg[0].len < 3 || msg[1].len < 1)
++ return -EOPNOTSUPP;
+ /* demod access via firmware interface */
+ u32 reg = msg[0].buf[0] << 16 | msg[0].buf[1] << 8 |
+ msg[0].buf[2];
+@@ -381,6 +383,8 @@ static int af9035_i2c_master_xfer(struct i2c_adapter *adap,
+ ret = -EOPNOTSUPP;
+ } else if ((msg[0].addr == state->af9033_i2c_addr[0]) ||
+ (msg[0].addr == state->af9033_i2c_addr[1])) {
++ if (msg[0].len < 3)
++ return -EOPNOTSUPP;
+ /* demod access via firmware interface */
+ u32 reg = msg[0].buf[0] << 16 | msg[0].buf[1] << 8 |
+ msg[0].buf[2];
+@@ -388,10 +392,7 @@ static int af9035_i2c_master_xfer(struct i2c_adapter *adap,
+ if (msg[0].addr == state->af9033_i2c_addr[1])
+ reg |= 0x100000;
+
+- ret = (msg[0].len >= 3) ? af9035_wr_regs(d, reg,
+- &msg[0].buf[3],
+- msg[0].len - 3)
+- : -EOPNOTSUPP;
++ ret = af9035_wr_regs(d, reg, &msg[0].buf[3], msg[0].len - 3);
+ } else {
+ /* I2C write */
+ u8 buf[MAX_XFER_SIZE];
+--
+2.40.1
+
--- /dev/null
+From 72bec26ec7596b865b08a3cde7fdf3091808ec48 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 10 Jul 2023 13:32:13 +0800
+Subject: media: dvb-usb-v2: gl861: Fix null-ptr-deref in gl861_i2c_master_xfer
+
+From: Zhang Shurong <zhang_shurong@foxmail.com>
+
+[ Upstream commit b97719a66970601cd3151a3e2020f4454a1c4ff6 ]
+
+In gl861_i2c_master_xfer, msg is controlled by user. When msg[i].buf
+is null and msg[i].len is zero, former checks on msg[i].buf would be
+passed. Malicious data finally reach gl861_i2c_master_xfer. If accessing
+msg[i].buf[0] without sanity check, null ptr deref would happen.
+We add check on msg[i].len to prevent crash.
+
+Similar commit:
+commit 0ed554fd769a
+("media: dvb-usb: az6027: fix null-ptr-deref in az6027_i2c_xfer()")
+
+Signed-off-by: Zhang Shurong <zhang_shurong@foxmail.com>
+Signed-off-by: Hans Verkuil <hverkuil-cisco@xs4all.nl>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/media/usb/dvb-usb-v2/gl861.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/drivers/media/usb/dvb-usb-v2/gl861.c b/drivers/media/usb/dvb-usb-v2/gl861.c
+index 0c434259c36f1..c71e7b93476de 100644
+--- a/drivers/media/usb/dvb-usb-v2/gl861.c
++++ b/drivers/media/usb/dvb-usb-v2/gl861.c
+@@ -120,7 +120,7 @@ static int gl861_i2c_master_xfer(struct i2c_adapter *adap, struct i2c_msg msg[],
+ } else if (num == 2 && !(msg[0].flags & I2C_M_RD) &&
+ (msg[1].flags & I2C_M_RD)) {
+ /* I2C write + read */
+- if (msg[0].len > 1 || msg[1].len > sizeof(ctx->buf)) {
++ if (msg[0].len != 1 || msg[1].len > sizeof(ctx->buf)) {
+ ret = -EOPNOTSUPP;
+ goto err;
+ }
+--
+2.40.1
+
--- /dev/null
+From 9b4aeff70f8f1670985e10bb68bfa68a65ce0f3a Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sat, 8 Jul 2023 18:22:52 +0800
+Subject: media: dw2102: Fix null-ptr-deref in dw2102_i2c_transfer()
+
+From: Zhang Shurong <zhang_shurong@foxmail.com>
+
+[ Upstream commit 5ae544d94abc8ff77b1b9bf8774def3fa5689b5b ]
+
+In dw2102_i2c_transfer, msg is controlled by user. When msg[i].buf
+is null and msg[i].len is zero, former checks on msg[i].buf would be
+passed. Malicious data finally reach dw2102_i2c_transfer. If accessing
+msg[i].buf[0] without sanity check, null ptr deref would happen.
+We add check on msg[i].len to prevent crash.
+
+Similar commit:
+commit 950e252cb469
+("[media] dw2102: limit messages to buffer size")
+
+Signed-off-by: Zhang Shurong <zhang_shurong@foxmail.com>
+Signed-off-by: Hans Verkuil <hverkuil-cisco@xs4all.nl>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/media/usb/dvb-usb/dw2102.c | 24 ++++++++++++++++++++++++
+ 1 file changed, 24 insertions(+)
+
+diff --git a/drivers/media/usb/dvb-usb/dw2102.c b/drivers/media/usb/dvb-usb/dw2102.c
+index 970b84c3f0b5a..b3bb1805829ad 100644
+--- a/drivers/media/usb/dvb-usb/dw2102.c
++++ b/drivers/media/usb/dvb-usb/dw2102.c
+@@ -128,6 +128,10 @@ static int dw2102_i2c_transfer(struct i2c_adapter *adap, struct i2c_msg msg[],
+
+ switch (num) {
+ case 2:
++ if (msg[0].len < 1) {
++ num = -EOPNOTSUPP;
++ break;
++ }
+ /* read stv0299 register */
+ value = msg[0].buf[0];/* register */
+ for (i = 0; i < msg[1].len; i++) {
+@@ -139,6 +143,10 @@ static int dw2102_i2c_transfer(struct i2c_adapter *adap, struct i2c_msg msg[],
+ case 1:
+ switch (msg[0].addr) {
+ case 0x68:
++ if (msg[0].len < 2) {
++ num = -EOPNOTSUPP;
++ break;
++ }
+ /* write to stv0299 register */
+ buf6[0] = 0x2a;
+ buf6[1] = msg[0].buf[0];
+@@ -148,6 +156,10 @@ static int dw2102_i2c_transfer(struct i2c_adapter *adap, struct i2c_msg msg[],
+ break;
+ case 0x60:
+ if (msg[0].flags == 0) {
++ if (msg[0].len < 4) {
++ num = -EOPNOTSUPP;
++ break;
++ }
+ /* write to tuner pll */
+ buf6[0] = 0x2c;
+ buf6[1] = 5;
+@@ -159,6 +171,10 @@ static int dw2102_i2c_transfer(struct i2c_adapter *adap, struct i2c_msg msg[],
+ dw210x_op_rw(d->udev, 0xb2, 0, 0,
+ buf6, 7, DW210X_WRITE_MSG);
+ } else {
++ if (msg[0].len < 1) {
++ num = -EOPNOTSUPP;
++ break;
++ }
+ /* read from tuner */
+ dw210x_op_rw(d->udev, 0xb5, 0, 0,
+ buf6, 1, DW210X_READ_MSG);
+@@ -166,12 +182,20 @@ static int dw2102_i2c_transfer(struct i2c_adapter *adap, struct i2c_msg msg[],
+ }
+ break;
+ case (DW2102_RC_QUERY):
++ if (msg[0].len < 2) {
++ num = -EOPNOTSUPP;
++ break;
++ }
+ dw210x_op_rw(d->udev, 0xb8, 0, 0,
+ buf6, 2, DW210X_READ_MSG);
+ msg[0].buf[0] = buf6[0];
+ msg[0].buf[1] = buf6[1];
+ break;
+ case (DW2102_VOLTAGE_CTRL):
++ if (msg[0].len < 1) {
++ num = -EOPNOTSUPP;
++ break;
++ }
+ buf6[0] = 0x30;
+ buf6[1] = msg[0].buf[0];
+ dw210x_op_rw(d->udev, 0xb2, 0, 0,
+--
+2.40.1
+
--- /dev/null
+From 5e45499931eac3712b3c4462cc73ff7ee418fbca Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 30 May 2023 18:17:18 +0800
+Subject: media: mdp3: Fix resource leaks in of_find_device_by_node
+
+From: Lu Hongfei <luhongfei@vivo.com>
+
+[ Upstream commit 35ca8ce495366909b4c2e701d1356570dd40c4e2 ]
+
+Use put_device to release the object get through of_find_device_by_node,
+avoiding resource leaks.
+
+Signed-off-by: Lu Hongfei <luhongfei@vivo.com>
+Signed-off-by: Hans Verkuil <hverkuil-cisco@xs4all.nl>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/media/platform/mediatek/mdp3/mtk-mdp3-comp.c | 2 ++
+ 1 file changed, 2 insertions(+)
+
+diff --git a/drivers/media/platform/mediatek/mdp3/mtk-mdp3-comp.c b/drivers/media/platform/mediatek/mdp3/mtk-mdp3-comp.c
+index a605e80c7dc36..b0ca2b3a8a739 100644
+--- a/drivers/media/platform/mediatek/mdp3/mtk-mdp3-comp.c
++++ b/drivers/media/platform/mediatek/mdp3/mtk-mdp3-comp.c
+@@ -892,11 +892,13 @@ static int mdp_get_subsys_id(struct mdp_dev *mdp, struct device *dev,
+ ret = cmdq_dev_get_client_reg(&comp_pdev->dev, &cmdq_reg, index);
+ if (ret != 0) {
+ dev_err(&comp_pdev->dev, "cmdq_dev_get_subsys fail!\n");
++ put_device(&comp_pdev->dev);
+ return -EINVAL;
+ }
+
+ comp->subsys_id = cmdq_reg.subsys;
+ dev_dbg(&comp_pdev->dev, "subsys id=%d\n", cmdq_reg.subsys);
++ put_device(&comp_pdev->dev);
+
+ return 0;
+ }
+--
+2.40.1
+
--- /dev/null
+From 741d4fafccfd036570b93e0afcd4056589ccdecf Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 21 Jul 2023 10:23:42 +0200
+Subject: media: pci: cx23885: replace BUG with error return
+
+From: Hans Verkuil <hverkuil-cisco@xs4all.nl>
+
+[ Upstream commit 2e1796fd4904fdd6062a8e4589778ea899ea0c8d ]
+
+It was completely unnecessary to use BUG in buffer_prepare().
+Just replace it with an error return. This also fixes a smatch warning:
+
+drivers/media/pci/cx23885/cx23885-video.c:422 buffer_prepare() error: uninitialized symbol 'ret'.
+
+Signed-off-by: Hans Verkuil <hverkuil-cisco@xs4all.nl>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/media/pci/cx23885/cx23885-video.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/drivers/media/pci/cx23885/cx23885-video.c b/drivers/media/pci/cx23885/cx23885-video.c
+index 671fc0588e431..9af2c5596121c 100644
+--- a/drivers/media/pci/cx23885/cx23885-video.c
++++ b/drivers/media/pci/cx23885/cx23885-video.c
+@@ -413,7 +413,7 @@ static int buffer_prepare(struct vb2_buffer *vb)
+ dev->height >> 1);
+ break;
+ default:
+- BUG();
++ return -EINVAL; /* should not happen */
+ }
+ dprintk(2, "[%p/%d] buffer_init - %dx%d %dbpp 0x%08x - dma=0x%08lx\n",
+ buf, buf->vb.vb2_buf.index,
+--
+2.40.1
+
--- /dev/null
+From b721d1c83c3b91e58c3d61fdd6edd8c6ff90e806 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 1 Aug 2023 10:14:30 +0300
+Subject: media: pci: ipu3-cio2: Initialise timing struct to avoid a compiler
+ warning
+
+From: Sakari Ailus <sakari.ailus@linux.intel.com>
+
+[ Upstream commit 9d7531be3085a8f013cf173ccc4e72e3cf493538 ]
+
+Initialise timing struct in cio2_hw_init() to zero in order to avoid a
+compiler warning. The warning was a false positive.
+
+Reported-by: Hans Verkuil <hverkuil-cisco@xs4all.nl>
+Signed-off-by: Sakari Ailus <sakari.ailus@linux.intel.com>
+Signed-off-by: Hans Verkuil <hverkuil-cisco@xs4all.nl>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/media/pci/intel/ipu3/ipu3-cio2-main.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/drivers/media/pci/intel/ipu3/ipu3-cio2-main.c b/drivers/media/pci/intel/ipu3/ipu3-cio2-main.c
+index dc09fbdb062b0..ca51776a961fb 100644
+--- a/drivers/media/pci/intel/ipu3/ipu3-cio2-main.c
++++ b/drivers/media/pci/intel/ipu3/ipu3-cio2-main.c
+@@ -355,7 +355,7 @@ static int cio2_hw_init(struct cio2_device *cio2, struct cio2_queue *q)
+ void __iomem *const base = cio2->base;
+ u8 lanes, csi2bus = q->csi2.port;
+ u8 sensor_vc = SENSOR_VIR_CH_DFLT;
+- struct cio2_csi2_timing timing;
++ struct cio2_csi2_timing timing = { 0 };
+ int i, r;
+
+ fmt = cio2_find_format(NULL, &q->subdev_fmt.code);
+--
+2.40.1
+
--- /dev/null
+From 0a85e2a7e80df5c260d26b445a83e076ea1804b8 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 20 Jul 2023 08:20:51 +0200
+Subject: media: tuners: qt1010: replace BUG_ON with a regular error
+
+From: Hans Verkuil <hverkuil-cisco@xs4all.nl>
+
+[ Upstream commit ee630b29ea44d1851bb6c903f400956604834463 ]
+
+BUG_ON is unnecessary here, and in addition it confuses smatch.
+Replacing this with an error return help resolve this smatch
+warning:
+
+drivers/media/tuners/qt1010.c:350 qt1010_init() error: buffer overflow 'i2c_data' 34 <= 34
+
+Signed-off-by: Hans Verkuil <hverkuil-cisco@xs4all.nl>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/media/tuners/qt1010.c | 11 ++++++-----
+ 1 file changed, 6 insertions(+), 5 deletions(-)
+
+diff --git a/drivers/media/tuners/qt1010.c b/drivers/media/tuners/qt1010.c
+index 60931367b82ca..48fc79cd40273 100644
+--- a/drivers/media/tuners/qt1010.c
++++ b/drivers/media/tuners/qt1010.c
+@@ -345,11 +345,12 @@ static int qt1010_init(struct dvb_frontend *fe)
+ else
+ valptr = &tmpval;
+
+- BUG_ON(i >= ARRAY_SIZE(i2c_data) - 1);
+-
+- err = qt1010_init_meas1(priv, i2c_data[i+1].reg,
+- i2c_data[i].reg,
+- i2c_data[i].val, valptr);
++ if (i >= ARRAY_SIZE(i2c_data) - 1)
++ err = -EIO;
++ else
++ err = qt1010_init_meas1(priv, i2c_data[i + 1].reg,
++ i2c_data[i].reg,
++ i2c_data[i].val, valptr);
+ i++;
+ break;
+ }
+--
+2.40.1
+
--- /dev/null
+From 63694d090b26fc6c4146bc75a8ec4dd4068d8be4 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 7 Jul 2023 21:58:47 +0800
+Subject: misc: open-dice: make OPEN_DICE depend on HAS_IOMEM
+
+From: Baoquan He <bhe@redhat.com>
+
+[ Upstream commit aefc8b57af7787c80686e49a5841e9289cb11f53 ]
+
+On s390 systems (aka mainframes), it has classic channel devices for
+networking and permanent storage that are currently even more common
+than PCI devices. Hence it could have a fully functional s390 kernel
+with CONFIG_PCI=n, then the relevant iomem mapping functions
+[including ioremap(), devm_ioremap(), etc.] are not available.
+
+Here let OPEN_DICE depend on HAS_IOMEM so that it won't be built
+to cause below compiling error if PCI is unset:
+
+------
+ERROR: modpost: "devm_memremap" [drivers/misc/open-dice.ko] undefined!
+ERROR: modpost: "devm_memunmap" [drivers/misc/open-dice.ko] undefined!
+------
+
+Reported-by: kernel test robot <lkp@intel.com>
+Closes: https://lore.kernel.org/oe-kbuild-all/202306211329.ticOJCSv-lkp@intel.com/
+Signed-off-by: Baoquan He <bhe@redhat.com>
+Cc: Derek Kiernan <derek.kiernan@amd.com>
+Cc: Dragan Cvetic <dragan.cvetic@amd.com>
+Cc: Arnd Bergmann <arnd@arndb.de>
+Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Link: https://lore.kernel.org/r/20230707135852.24292-4-bhe@redhat.com
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/misc/Kconfig | 1 +
+ 1 file changed, 1 insertion(+)
+
+diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig
+index 75e427f124b28..cadd4a820c033 100644
+--- a/drivers/misc/Kconfig
++++ b/drivers/misc/Kconfig
+@@ -496,6 +496,7 @@ config HISI_HIKEY_USB
+ config OPEN_DICE
+ tristate "Open Profile for DICE driver"
+ depends on OF_RESERVED_MEM
++ depends on HAS_IOMEM
+ help
+ This driver exposes a DICE reserved memory region to userspace via
+ a character device. The memory region contains Compound Device
+--
+2.40.1
+
--- /dev/null
+From 40449789b4501c54edafec30f6c130a5d837fe03 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 11 Aug 2023 23:48:53 +0200
+Subject: mmc: sdhci-esdhc-imx: improve ESDHC_FLAG_ERR010450
+
+From: Giulio Benetti <giulio.benetti@benettiengineering.com>
+
+[ Upstream commit 5ae4b0d8875caa44946e579420c7fd5740d58653 ]
+
+Errata ERR010450 only shows up if voltage is 1.8V, but if the device is
+supplied by 3v3 the errata can be ignored. So let's check for if quirk
+SDHCI_QUIRK2_NO_1_8_V is defined or not before limiting the frequency.
+
+Cc: Jim Reinhart <jimr@tekvox.com>
+Cc: James Autry <jautry@tekvox.com>
+Cc: Matthew Maron <matthewm@tekvox.com>
+Signed-off-by: Giulio Benetti <giulio.benetti@benettiengineering.com>
+Acked-by: Haibo Chen <haibo.chen@nxp.com>
+Acked-by: Adrian Hunter <adrian.hunter@intel.com>
+Link: https://lore.kernel.org/r/20230811214853.8623-1-giulio.benetti@benettiengineering.com
+Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/mmc/host/sdhci-esdhc-imx.c | 7 ++++---
+ 1 file changed, 4 insertions(+), 3 deletions(-)
+
+diff --git a/drivers/mmc/host/sdhci-esdhc-imx.c b/drivers/mmc/host/sdhci-esdhc-imx.c
+index eebf94604a7fd..cddecc1e1ac2f 100644
+--- a/drivers/mmc/host/sdhci-esdhc-imx.c
++++ b/drivers/mmc/host/sdhci-esdhc-imx.c
+@@ -171,8 +171,8 @@
+ #define ESDHC_FLAG_HS400 BIT(9)
+ /*
+ * The IP has errata ERR010450
+- * uSDHC: Due to the I/O timing limit, for SDR mode, SD card clock can't
+- * exceed 150MHz, for DDR mode, SD card clock can't exceed 45MHz.
++ * uSDHC: At 1.8V due to the I/O timing limit, for SDR mode, SD card
++ * clock can't exceed 150MHz, for DDR mode, SD card clock can't exceed 45MHz.
+ */
+ #define ESDHC_FLAG_ERR010450 BIT(10)
+ /* The IP supports HS400ES mode */
+@@ -961,7 +961,8 @@ static inline void esdhc_pltfm_set_clock(struct sdhci_host *host,
+ | ESDHC_CLOCK_MASK);
+ sdhci_writel(host, temp, ESDHC_SYSTEM_CONTROL);
+
+- if (imx_data->socdata->flags & ESDHC_FLAG_ERR010450) {
++ if ((imx_data->socdata->flags & ESDHC_FLAG_ERR010450) &&
++ (!(host->quirks2 & SDHCI_QUIRK2_NO_1_8_V))) {
+ unsigned int max_clock;
+
+ max_clock = imx_data->is_ddr ? 45000000 : 150000000;
+--
+2.40.1
+
--- /dev/null
+From 702dcd436419b6e4a195d70042a0825d04fcbfc2 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 20 Apr 2023 15:24:51 -0400
+Subject: mt76: mt7921: don't assume adequate headroom for SDIO headers
+
+From: Matt Whitlock <kernel@mattwhitlock.name>
+
+[ Upstream commit 98c4d0abf5c478db1ad126ff0c187dbb84c0803c ]
+
+mt7921_usb_sdio_tx_prepare_skb() calls mt7921_usb_sdio_write_txwi() and
+mt7921_skb_add_usb_sdio_hdr(), both of which blindly assume that
+adequate headroom will be available in the passed skb. This assumption
+typically is satisfied when the skb was allocated in the net core for
+transmission via the mt7921 netdev (although even that is only an
+optimization and is not strictly guaranteed), but the assumption is
+sometimes not satisfied when the skb originated in the receive path of
+another netdev and was passed through to the mt7921, such as by the
+bridge layer. Blindly prepending bytes to an skb is always wrong.
+
+This commit introduces a call to skb_cow_head() before the call to
+mt7921_usb_sdio_write_txwi() in mt7921_usb_sdio_tx_prepare_skb() to
+ensure that at least MT_SDIO_TXD_SIZE + MT_SDIO_HDR_SIZE bytes can be
+pushed onto the skb.
+
+Without this fix, I can trivially cause kernel panics by bridging an
+MT7921AU-based USB 802.11ax interface with an Ethernet interface on an
+Intel Atom-based x86 system using its onboard RTL8169 PCI Ethernet
+adapter and also on an ARM-based Raspberry Pi 1 using its onboard
+SMSC9512 USB Ethernet adapter. Note that the panics do not occur in
+every system configuration, as they occur only if the receiving netdev
+leaves less headroom in its received skbs than the mt7921 needs for its
+SDIO headers.
+
+Here is an example stack trace of this panic on Raspberry Pi OS Lite
+2023-02-21 running kernel 6.1.24+ [1]:
+
+ skb_panic from skb_push+0x44/0x48
+ skb_push from mt7921_usb_sdio_tx_prepare_skb+0xd4/0x190 [mt7921_common]
+ mt7921_usb_sdio_tx_prepare_skb [mt7921_common] from mt76u_tx_queue_skb+0x94/0x1d0 [mt76_usb]
+ mt76u_tx_queue_skb [mt76_usb] from __mt76_tx_queue_skb+0x4c/0xc8 [mt76]
+ __mt76_tx_queue_skb [mt76] from mt76_txq_schedule.part.0+0x13c/0x398 [mt76]
+ mt76_txq_schedule.part.0 [mt76] from mt76_txq_schedule_all+0x24/0x30 [mt76]
+ mt76_txq_schedule_all [mt76] from mt7921_tx_worker+0x58/0xf4 [mt7921_common]
+ mt7921_tx_worker [mt7921_common] from __mt76_worker_fn+0x9c/0xec [mt76]
+ __mt76_worker_fn [mt76] from kthread+0xbc/0xe0
+ kthread from ret_from_fork+0x14/0x34
+
+After this fix, bridging the mt7921 interface works fine on both of my
+previously problematic systems.
+
+[1] https://github.com/raspberrypi/firmware/tree/5c276f55a4b21345cd4d6200a504ee991851ff7a
+
+Link: https://github.com/openwrt/openwrt/issues/11796
+Signed-off-by: Matt Whitlock <kernel@mattwhitlock.name>
+Signed-off-by: Felix Fietkau <nbd@nbd.name>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/wireless/mediatek/mt76/mt7921/mac.c | 4 ++++
+ 1 file changed, 4 insertions(+)
+
+diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/mac.c b/drivers/net/wireless/mediatek/mt76/mt7921/mac.c
+index 1675bf5204812..a671c601c5836 100644
+--- a/drivers/net/wireless/mediatek/mt76/mt7921/mac.c
++++ b/drivers/net/wireless/mediatek/mt76/mt7921/mac.c
+@@ -1180,6 +1180,10 @@ int mt7921_usb_sdio_tx_prepare_skb(struct mt76_dev *mdev, void *txwi_ptr,
+ if (unlikely(tx_info->skb->len <= ETH_HLEN))
+ return -EINVAL;
+
++ err = skb_cow_head(skb, MT_SDIO_TXD_SIZE + MT_SDIO_HDR_SIZE);
++ if (err)
++ return err;
++
+ if (!wcid)
+ wcid = &dev->mt76.global_wcid;
+
+--
+2.40.1
+
--- /dev/null
+From aa3b20d8aa0191e86db7e62f6c784bf670bdaa09 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 26 Jul 2023 10:52:48 +0300
+Subject: mtd: spi-nor: spansion: preserve CFR2V[7] when writing MEMLAT
+
+From: Takahiro Kuwano <Takahiro.Kuwano@infineon.com>
+
+[ Upstream commit 1e611e104b9acb6310b8c684d5acee0e11ca7bd1 ]
+
+CFR2V[7] is assigned to Flash's address mode (3- or 4-ybte) and must not
+be changed when writing MEMLAT (CFR2V[3:0]). CFR2V shall be used in a read,
+update, write back fashion.
+
+Fixes: c3266af101f2 ("mtd: spi-nor: spansion: add support for Cypress Semper flash")
+Signed-off-by: Takahiro Kuwano <Takahiro.Kuwano@infineon.com>
+Cc: stable@vger.kernel.org
+Link: https://lore.kernel.org/r/20230726075257.12985-3-tudor.ambarus@linaro.org
+Signed-off-by: Tudor Ambarus <tudor.ambarus@linaro.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/mtd/spi-nor/spansion.c | 14 +++++++++++++-
+ 1 file changed, 13 insertions(+), 1 deletion(-)
+
+diff --git a/drivers/mtd/spi-nor/spansion.c b/drivers/mtd/spi-nor/spansion.c
+index 9edc1b7ac091a..4fbaa6fba45a6 100644
+--- a/drivers/mtd/spi-nor/spansion.c
++++ b/drivers/mtd/spi-nor/spansion.c
+@@ -4,6 +4,7 @@
+ * Copyright (C) 2014, Freescale Semiconductor, Inc.
+ */
+
++#include <linux/bitfield.h>
+ #include <linux/device.h>
+ #include <linux/mtd/spi-nor.h>
+
+@@ -28,6 +29,7 @@
+ #define SPINOR_REG_CYPRESS_CFR2 0x3
+ #define SPINOR_REG_CYPRESS_CFR2V \
+ (SPINOR_REG_CYPRESS_VREG + SPINOR_REG_CYPRESS_CFR2)
++#define SPINOR_REG_CYPRESS_CFR2_MEMLAT_MASK GENMASK(3, 0)
+ #define SPINOR_REG_CYPRESS_CFR2_MEMLAT_11_24 0xb
+ #define SPINOR_REG_CYPRESS_CFR2_ADRBYT BIT(7)
+ #define SPINOR_REG_CYPRESS_CFR3 0x4
+@@ -161,8 +163,18 @@ static int cypress_nor_octal_dtr_en(struct spi_nor *nor)
+ int ret;
+ u8 addr_mode_nbytes = nor->params->addr_mode_nbytes;
+
++ op = (struct spi_mem_op)
++ CYPRESS_NOR_RD_ANY_REG_OP(addr_mode_nbytes,
++ SPINOR_REG_CYPRESS_CFR2V, 0, buf);
++
++ ret = spi_nor_read_any_reg(nor, &op, nor->reg_proto);
++ if (ret)
++ return ret;
++
+ /* Use 24 dummy cycles for memory array reads. */
+- *buf = SPINOR_REG_CYPRESS_CFR2_MEMLAT_11_24;
++ *buf &= ~SPINOR_REG_CYPRESS_CFR2_MEMLAT_MASK;
++ *buf |= FIELD_PREP(SPINOR_REG_CYPRESS_CFR2_MEMLAT_MASK,
++ SPINOR_REG_CYPRESS_CFR2_MEMLAT_11_24);
+ op = (struct spi_mem_op)
+ CYPRESS_NOR_WR_ANY_REG_OP(addr_mode_nbytes,
+ SPINOR_REG_CYPRESS_CFR2V, 1, buf);
+--
+2.40.1
+
--- /dev/null
+From d6c419079b6cd3a26f6825c78481c7a78d7d7c81 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 26 Jul 2023 10:52:47 +0300
+Subject: mtd: spi-nor: spansion: use CLPEF as an alternative to CLSR
+
+From: Takahiro Kuwano <Takahiro.Kuwano@infineon.com>
+
+[ Upstream commit d534fd9787d5925d9637752410e3ea92ca7f4cfa ]
+
+Infineon S28Hx (SEMPER Octal) and S25FS256T (SEMPER Nano) support Clear
+Program and Erase Failure Flags (CLPEF, 82h) instead of CLSR(30h).
+Introduce a new mfr_flag together with the infrastructure to allow
+manufacturer private data in the core. With this we remove the need
+to have if checks in the code at runtime and instead set the correct
+opcodes at probe time. S25Hx (SEMPER QSPI) supports CLSR but it may
+be disabled by CFR3x[2] while CLPEF is always available. Therefore,
+the mfr_flag is also applied to S25Hx for safety.
+
+Signed-off-by: Takahiro Kuwano <Takahiro.Kuwano@infineon.com>
+Link: https://lore.kernel.org/r/20230726075257.12985-2-tudor.ambarus@linaro.org
+Signed-off-by: Tudor Ambarus <tudor.ambarus@linaro.org>
+Stable-dep-of: 1e611e104b9a ("mtd: spi-nor: spansion: preserve CFR2V[7] when writing MEMLAT")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/mtd/spi-nor/atmel.c | 8 +++-
+ drivers/mtd/spi-nor/core.c | 23 +++++++----
+ drivers/mtd/spi-nor/core.h | 4 +-
+ drivers/mtd/spi-nor/issi.c | 4 +-
+ drivers/mtd/spi-nor/macronix.c | 4 +-
+ drivers/mtd/spi-nor/micron-st.c | 4 +-
+ drivers/mtd/spi-nor/spansion.c | 72 ++++++++++++++++++++++++++-------
+ drivers/mtd/spi-nor/sst.c | 8 +++-
+ drivers/mtd/spi-nor/winbond.c | 4 +-
+ drivers/mtd/spi-nor/xilinx.c | 4 +-
+ 10 files changed, 103 insertions(+), 32 deletions(-)
+
+diff --git a/drivers/mtd/spi-nor/atmel.c b/drivers/mtd/spi-nor/atmel.c
+index 656dd80a0be79..58968c1e7d2f8 100644
+--- a/drivers/mtd/spi-nor/atmel.c
++++ b/drivers/mtd/spi-nor/atmel.c
+@@ -48,9 +48,11 @@ static const struct spi_nor_locking_ops at25fs_nor_locking_ops = {
+ .is_locked = at25fs_nor_is_locked,
+ };
+
+-static void at25fs_nor_late_init(struct spi_nor *nor)
++static int at25fs_nor_late_init(struct spi_nor *nor)
+ {
+ nor->params->locking_ops = &at25fs_nor_locking_ops;
++
++ return 0;
+ }
+
+ static const struct spi_nor_fixups at25fs_nor_fixups = {
+@@ -149,9 +151,11 @@ static const struct spi_nor_locking_ops atmel_nor_global_protection_ops = {
+ .is_locked = atmel_nor_is_global_protected,
+ };
+
+-static void atmel_nor_global_protection_late_init(struct spi_nor *nor)
++static int atmel_nor_global_protection_late_init(struct spi_nor *nor)
+ {
+ nor->params->locking_ops = &atmel_nor_global_protection_ops;
++
++ return 0;
+ }
+
+ static const struct spi_nor_fixups atmel_nor_global_protection_fixups = {
+diff --git a/drivers/mtd/spi-nor/core.c b/drivers/mtd/spi-nor/core.c
+index 55f4a902b8be9..72973cfb1d201 100644
+--- a/drivers/mtd/spi-nor/core.c
++++ b/drivers/mtd/spi-nor/core.c
+@@ -2898,16 +2898,23 @@ static void spi_nor_init_fixup_flags(struct spi_nor *nor)
+ * SFDP standard, or where SFDP tables are not defined at all.
+ * Will replace the spi_nor_manufacturer_init_params() method.
+ */
+-static void spi_nor_late_init_params(struct spi_nor *nor)
++static int spi_nor_late_init_params(struct spi_nor *nor)
+ {
+ struct spi_nor_flash_parameter *params = nor->params;
++ int ret;
+
+ if (nor->manufacturer && nor->manufacturer->fixups &&
+- nor->manufacturer->fixups->late_init)
+- nor->manufacturer->fixups->late_init(nor);
++ nor->manufacturer->fixups->late_init) {
++ ret = nor->manufacturer->fixups->late_init(nor);
++ if (ret)
++ return ret;
++ }
+
+- if (nor->info->fixups && nor->info->fixups->late_init)
+- nor->info->fixups->late_init(nor);
++ if (nor->info->fixups && nor->info->fixups->late_init) {
++ ret = nor->info->fixups->late_init(nor);
++ if (ret)
++ return ret;
++ }
+
+ /* Default method kept for backward compatibility. */
+ if (!params->set_4byte_addr_mode)
+@@ -2925,6 +2932,8 @@ static void spi_nor_late_init_params(struct spi_nor *nor)
+
+ if (nor->info->n_banks > 1)
+ params->bank_size = div64_u64(params->size, nor->info->n_banks);
++
++ return 0;
+ }
+
+ /**
+@@ -3083,9 +3092,7 @@ static int spi_nor_init_params(struct spi_nor *nor)
+ spi_nor_init_params_deprecated(nor);
+ }
+
+- spi_nor_late_init_params(nor);
+-
+- return 0;
++ return spi_nor_late_init_params(nor);
+ }
+
+ /** spi_nor_octal_dtr_enable() - enable Octal DTR I/O if needed
+diff --git a/drivers/mtd/spi-nor/core.h b/drivers/mtd/spi-nor/core.h
+index 4fb5ff09c63a9..2453bd5743ac9 100644
+--- a/drivers/mtd/spi-nor/core.h
++++ b/drivers/mtd/spi-nor/core.h
+@@ -377,6 +377,7 @@ struct spi_nor_otp {
+ * than reading the status register to indicate they
+ * are ready for a new command
+ * @locking_ops: SPI NOR locking methods.
++ * @priv: flash's private data.
+ */
+ struct spi_nor_flash_parameter {
+ u64 bank_size;
+@@ -405,6 +406,7 @@ struct spi_nor_flash_parameter {
+ int (*ready)(struct spi_nor *nor);
+
+ const struct spi_nor_locking_ops *locking_ops;
++ void *priv;
+ };
+
+ /**
+@@ -431,7 +433,7 @@ struct spi_nor_fixups {
+ const struct sfdp_parameter_header *bfpt_header,
+ const struct sfdp_bfpt *bfpt);
+ int (*post_sfdp)(struct spi_nor *nor);
+- void (*late_init)(struct spi_nor *nor);
++ int (*late_init)(struct spi_nor *nor);
+ };
+
+ /**
+diff --git a/drivers/mtd/spi-nor/issi.c b/drivers/mtd/spi-nor/issi.c
+index 400e2b42f45af..accdf7aa2bfde 100644
+--- a/drivers/mtd/spi-nor/issi.c
++++ b/drivers/mtd/spi-nor/issi.c
+@@ -29,7 +29,7 @@ static const struct spi_nor_fixups is25lp256_fixups = {
+ .post_bfpt = is25lp256_post_bfpt_fixups,
+ };
+
+-static void pm25lv_nor_late_init(struct spi_nor *nor)
++static int pm25lv_nor_late_init(struct spi_nor *nor)
+ {
+ struct spi_nor_erase_map *map = &nor->params->erase_map;
+ int i;
+@@ -38,6 +38,8 @@ static void pm25lv_nor_late_init(struct spi_nor *nor)
+ for (i = 0; i < SNOR_ERASE_TYPE_MAX; i++)
+ if (map->erase_type[i].size == 4096)
+ map->erase_type[i].opcode = SPINOR_OP_BE_4K_PMC;
++
++ return 0;
+ }
+
+ static const struct spi_nor_fixups pm25lv_nor_fixups = {
+diff --git a/drivers/mtd/spi-nor/macronix.c b/drivers/mtd/spi-nor/macronix.c
+index 04888258e8914..eb149e517c1fe 100644
+--- a/drivers/mtd/spi-nor/macronix.c
++++ b/drivers/mtd/spi-nor/macronix.c
+@@ -110,10 +110,12 @@ static void macronix_nor_default_init(struct spi_nor *nor)
+ nor->params->quad_enable = spi_nor_sr1_bit6_quad_enable;
+ }
+
+-static void macronix_nor_late_init(struct spi_nor *nor)
++static int macronix_nor_late_init(struct spi_nor *nor)
+ {
+ if (!nor->params->set_4byte_addr_mode)
+ nor->params->set_4byte_addr_mode = spi_nor_set_4byte_addr_mode_en4b_ex4b;
++
++ return 0;
+ }
+
+ static const struct spi_nor_fixups macronix_nor_fixups = {
+diff --git a/drivers/mtd/spi-nor/micron-st.c b/drivers/mtd/spi-nor/micron-st.c
+index 4b919756a2055..28c9c14a4b293 100644
+--- a/drivers/mtd/spi-nor/micron-st.c
++++ b/drivers/mtd/spi-nor/micron-st.c
+@@ -429,7 +429,7 @@ static void micron_st_nor_default_init(struct spi_nor *nor)
+ nor->params->quad_enable = NULL;
+ }
+
+-static void micron_st_nor_late_init(struct spi_nor *nor)
++static int micron_st_nor_late_init(struct spi_nor *nor)
+ {
+ struct spi_nor_flash_parameter *params = nor->params;
+
+@@ -438,6 +438,8 @@ static void micron_st_nor_late_init(struct spi_nor *nor)
+
+ if (!params->set_4byte_addr_mode)
+ params->set_4byte_addr_mode = spi_nor_set_4byte_addr_mode_wren_en4b_ex4b;
++
++ return 0;
+ }
+
+ static const struct spi_nor_fixups micron_st_nor_fixups = {
+diff --git a/drivers/mtd/spi-nor/spansion.c b/drivers/mtd/spi-nor/spansion.c
+index 15f9a80c10b9b..9edc1b7ac091a 100644
+--- a/drivers/mtd/spi-nor/spansion.c
++++ b/drivers/mtd/spi-nor/spansion.c
+@@ -4,14 +4,17 @@
+ * Copyright (C) 2014, Freescale Semiconductor, Inc.
+ */
+
++#include <linux/device.h>
+ #include <linux/mtd/spi-nor.h>
+
+ #include "core.h"
+
+ /* flash_info mfr_flag. Used to clear sticky prorietary SR bits. */
+ #define USE_CLSR BIT(0)
++#define USE_CLPEF BIT(1)
+
+ #define SPINOR_OP_CLSR 0x30 /* Clear status register 1 */
++#define SPINOR_OP_CLPEF 0x82 /* Clear program/erase failure flags */
+ #define SPINOR_OP_RD_ANY_REG 0x65 /* Read any register */
+ #define SPINOR_OP_WR_ANY_REG 0x71 /* Write any register */
+ #define SPINOR_REG_CYPRESS_VREG 0x00800000
+@@ -57,22 +60,32 @@
+ SPI_MEM_OP_DUMMY(ndummy, 0), \
+ SPI_MEM_OP_DATA_IN(1, buf, 0))
+
+-#define SPANSION_CLSR_OP \
+- SPI_MEM_OP(SPI_MEM_OP_CMD(SPINOR_OP_CLSR, 0), \
++#define SPANSION_OP(opcode) \
++ SPI_MEM_OP(SPI_MEM_OP_CMD(opcode, 0), \
+ SPI_MEM_OP_NO_ADDR, \
+ SPI_MEM_OP_NO_DUMMY, \
+ SPI_MEM_OP_NO_DATA)
+
++/**
++ * struct spansion_nor_params - Spansion private parameters.
++ * @clsr: Clear Status Register or Clear Program and Erase Failure Flag
++ * opcode.
++ */
++struct spansion_nor_params {
++ u8 clsr;
++};
++
+ /**
+ * spansion_nor_clear_sr() - Clear the Status Register.
+ * @nor: pointer to 'struct spi_nor'.
+ */
+ static void spansion_nor_clear_sr(struct spi_nor *nor)
+ {
++ const struct spansion_nor_params *priv_params = nor->params->priv;
+ int ret;
+
+ if (nor->spimem) {
+- struct spi_mem_op op = SPANSION_CLSR_OP;
++ struct spi_mem_op op = SPANSION_OP(priv_params->clsr);
+
+ spi_nor_spimem_setup_op(nor, &op, nor->reg_proto);
+
+@@ -528,9 +541,11 @@ static int s25fs256t_post_sfdp_fixup(struct spi_nor *nor)
+ return 0;
+ }
+
+-static void s25fs256t_late_init(struct spi_nor *nor)
++static int s25fs256t_late_init(struct spi_nor *nor)
+ {
+ cypress_nor_ecc_init(nor);
++
++ return 0;
+ }
+
+ static struct spi_nor_fixups s25fs256t_fixups = {
+@@ -586,7 +601,7 @@ static int s25hx_t_post_sfdp_fixup(struct spi_nor *nor)
+ return cypress_nor_get_page_size(nor);
+ }
+
+-static void s25hx_t_late_init(struct spi_nor *nor)
++static int s25hx_t_late_init(struct spi_nor *nor)
+ {
+ struct spi_nor_flash_parameter *params = nor->params;
+
+@@ -598,6 +613,8 @@ static void s25hx_t_late_init(struct spi_nor *nor)
+ /* Replace ready() with multi die version */
+ if (params->n_dice)
+ params->ready = cypress_nor_sr_ready_and_clear;
++
++ return 0;
+ }
+
+ static struct spi_nor_fixups s25hx_t_fixups = {
+@@ -665,10 +682,12 @@ static int s28hx_t_post_bfpt_fixup(struct spi_nor *nor,
+ return 0;
+ }
+
+-static void s28hx_t_late_init(struct spi_nor *nor)
++static int s28hx_t_late_init(struct spi_nor *nor)
+ {
+ nor->params->octal_dtr_enable = cypress_nor_octal_dtr_enable;
+ cypress_nor_ecc_init(nor);
++
++ return 0;
+ }
+
+ static const struct spi_nor_fixups s28hx_t_fixups = {
+@@ -792,47 +811,54 @@ static const struct flash_info spansion_nor_parts[] = {
+ FIXUP_FLAGS(SPI_NOR_4B_OPCODES) },
+ { "s25fs256t", INFO6(0x342b19, 0x0f0890, 0, 0)
+ PARSE_SFDP
++ MFR_FLAGS(USE_CLPEF)
+ .fixups = &s25fs256t_fixups },
+ { "s25hl512t", INFO6(0x342a1a, 0x0f0390, 256 * 1024, 256)
+ PARSE_SFDP
+- MFR_FLAGS(USE_CLSR)
++ MFR_FLAGS(USE_CLPEF)
+ .fixups = &s25hx_t_fixups },
+ { "s25hl01gt", INFO6(0x342a1b, 0x0f0390, 256 * 1024, 512)
+ PARSE_SFDP
+- MFR_FLAGS(USE_CLSR)
++ MFR_FLAGS(USE_CLPEF)
+ .fixups = &s25hx_t_fixups },
+ { "s25hl02gt", INFO6(0x342a1c, 0x0f0090, 0, 0)
+ PARSE_SFDP
++ MFR_FLAGS(USE_CLPEF)
+ FLAGS(NO_CHIP_ERASE)
+ .fixups = &s25hx_t_fixups },
+ { "s25hs512t", INFO6(0x342b1a, 0x0f0390, 256 * 1024, 256)
+ PARSE_SFDP
+- MFR_FLAGS(USE_CLSR)
++ MFR_FLAGS(USE_CLPEF)
+ .fixups = &s25hx_t_fixups },
+ { "s25hs01gt", INFO6(0x342b1b, 0x0f0390, 256 * 1024, 512)
+ PARSE_SFDP
+- MFR_FLAGS(USE_CLSR)
++ MFR_FLAGS(USE_CLPEF)
+ .fixups = &s25hx_t_fixups },
+ { "s25hs02gt", INFO6(0x342b1c, 0x0f0090, 0, 0)
+ PARSE_SFDP
++ MFR_FLAGS(USE_CLPEF)
+ FLAGS(NO_CHIP_ERASE)
+ .fixups = &s25hx_t_fixups },
+ { "cy15x104q", INFO6(0x042cc2, 0x7f7f7f, 512 * 1024, 1)
+ FLAGS(SPI_NOR_NO_ERASE) },
+ { "s28hl512t", INFO(0x345a1a, 0, 256 * 1024, 256)
+ PARSE_SFDP
++ MFR_FLAGS(USE_CLPEF)
+ .fixups = &s28hx_t_fixups,
+ },
+ { "s28hl01gt", INFO(0x345a1b, 0, 256 * 1024, 512)
+ PARSE_SFDP
++ MFR_FLAGS(USE_CLPEF)
+ .fixups = &s28hx_t_fixups,
+ },
+ { "s28hs512t", INFO(0x345b1a, 0, 256 * 1024, 256)
+ PARSE_SFDP
++ MFR_FLAGS(USE_CLPEF)
+ .fixups = &s28hx_t_fixups,
+ },
+ { "s28hs01gt", INFO(0x345b1b, 0, 256 * 1024, 512)
+ PARSE_SFDP
++ MFR_FLAGS(USE_CLPEF)
+ .fixups = &s28hx_t_fixups,
+ },
+ };
+@@ -876,17 +902,35 @@ static int spansion_nor_sr_ready_and_clear(struct spi_nor *nor)
+ return !(nor->bouncebuf[0] & SR_WIP);
+ }
+
+-static void spansion_nor_late_init(struct spi_nor *nor)
++static int spansion_nor_late_init(struct spi_nor *nor)
+ {
+- if (nor->params->size > SZ_16M) {
++ struct spi_nor_flash_parameter *params = nor->params;
++ struct spansion_nor_params *priv_params;
++ u8 mfr_flags = nor->info->mfr_flags;
++
++ if (params->size > SZ_16M) {
+ nor->flags |= SNOR_F_4B_OPCODES;
+ /* No small sector erase for 4-byte command set */
+ nor->erase_opcode = SPINOR_OP_SE;
+ nor->mtd.erasesize = nor->info->sector_size;
+ }
+
+- if (nor->info->mfr_flags & USE_CLSR)
+- nor->params->ready = spansion_nor_sr_ready_and_clear;
++ if (mfr_flags & (USE_CLSR | USE_CLPEF)) {
++ priv_params = devm_kmalloc(nor->dev, sizeof(*priv_params),
++ GFP_KERNEL);
++ if (!priv_params)
++ return -ENOMEM;
++
++ if (mfr_flags & USE_CLSR)
++ priv_params->clsr = SPINOR_OP_CLSR;
++ else if (mfr_flags & USE_CLPEF)
++ priv_params->clsr = SPINOR_OP_CLPEF;
++
++ params->priv = priv_params;
++ params->ready = spansion_nor_sr_ready_and_clear;
++ }
++
++ return 0;
+ }
+
+ static const struct spi_nor_fixups spansion_nor_fixups = {
+diff --git a/drivers/mtd/spi-nor/sst.c b/drivers/mtd/spi-nor/sst.c
+index 688eb20c763e9..09fdc7023e09a 100644
+--- a/drivers/mtd/spi-nor/sst.c
++++ b/drivers/mtd/spi-nor/sst.c
+@@ -49,9 +49,11 @@ static const struct spi_nor_locking_ops sst26vf_nor_locking_ops = {
+ .is_locked = sst26vf_nor_is_locked,
+ };
+
+-static void sst26vf_nor_late_init(struct spi_nor *nor)
++static int sst26vf_nor_late_init(struct spi_nor *nor)
+ {
+ nor->params->locking_ops = &sst26vf_nor_locking_ops;
++
++ return 0;
+ }
+
+ static const struct spi_nor_fixups sst26vf_nor_fixups = {
+@@ -203,10 +205,12 @@ static int sst_nor_write(struct mtd_info *mtd, loff_t to, size_t len,
+ return ret;
+ }
+
+-static void sst_nor_late_init(struct spi_nor *nor)
++static int sst_nor_late_init(struct spi_nor *nor)
+ {
+ if (nor->info->mfr_flags & SST_WRITE)
+ nor->mtd._write = sst_nor_write;
++
++ return 0;
+ }
+
+ static const struct spi_nor_fixups sst_nor_fixups = {
+diff --git a/drivers/mtd/spi-nor/winbond.c b/drivers/mtd/spi-nor/winbond.c
+index 63ba8e3a96f51..cd99c9a1c5688 100644
+--- a/drivers/mtd/spi-nor/winbond.c
++++ b/drivers/mtd/spi-nor/winbond.c
+@@ -217,7 +217,7 @@ static const struct spi_nor_otp_ops winbond_nor_otp_ops = {
+ .is_locked = spi_nor_otp_is_locked_sr2,
+ };
+
+-static void winbond_nor_late_init(struct spi_nor *nor)
++static int winbond_nor_late_init(struct spi_nor *nor)
+ {
+ struct spi_nor_flash_parameter *params = nor->params;
+
+@@ -233,6 +233,8 @@ static void winbond_nor_late_init(struct spi_nor *nor)
+ * from BFPT, if any.
+ */
+ params->set_4byte_addr_mode = winbond_nor_set_4byte_addr_mode;
++
++ return 0;
+ }
+
+ static const struct spi_nor_fixups winbond_nor_fixups = {
+diff --git a/drivers/mtd/spi-nor/xilinx.c b/drivers/mtd/spi-nor/xilinx.c
+index 7175de8aa336a..00d53eae5ee83 100644
+--- a/drivers/mtd/spi-nor/xilinx.c
++++ b/drivers/mtd/spi-nor/xilinx.c
+@@ -155,10 +155,12 @@ static int xilinx_nor_setup(struct spi_nor *nor,
+ return 0;
+ }
+
+-static void xilinx_nor_late_init(struct spi_nor *nor)
++static int xilinx_nor_late_init(struct spi_nor *nor)
+ {
+ nor->params->setup = xilinx_nor_setup;
+ nor->params->ready = xilinx_nor_sr_ready;
++
++ return 0;
+ }
+
+ static const struct spi_nor_fixups xilinx_nor_fixups = {
+--
+2.40.1
+
--- /dev/null
+From 3fb1b967a90fe1e8fde581c49b4ace73fd51f847 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 7 Aug 2023 01:54:08 +0000
+Subject: net/ipv4: return the real errno instead of -EINVAL
+
+From: xu xin <xu.xin16@zte.com.cn>
+
+[ Upstream commit c67180efc507e04a87f22aa68bd7dd832db006b7 ]
+
+For now, No matter what error pointer ip_neigh_for_gw() returns,
+ip_finish_output2() always return -EINVAL, which may mislead the upper
+users.
+
+For exemple, an application uses sendto to send an UDP packet, but when the
+neighbor table overflows, sendto() will get a value of -EINVAL, and it will
+cause users to waste a lot of time checking parameters for errors.
+
+Return the real errno instead of -EINVAL.
+
+Signed-off-by: xu xin <xu.xin16@zte.com.cn>
+Reviewed-by: Yang Yang <yang.yang29@zte.com.cn>
+Cc: Si Hao <si.hao@zte.com.cn>
+Reviewed-by: Kuniyuki Iwashima <kuniyu@amazon.com>
+Reviewed-by: Vadim Fedorenko <vadim.fedorenko@linux.dev>
+Link: https://lore.kernel.org/r/20230807015408.248237-1-xu.xin16@zte.com.cn
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/ipv4/ip_output.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/net/ipv4/ip_output.c b/net/ipv4/ip_output.c
+index 6935d07a60c35..a8d2e8b1ff415 100644
+--- a/net/ipv4/ip_output.c
++++ b/net/ipv4/ip_output.c
+@@ -236,7 +236,7 @@ static int ip_finish_output2(struct net *net, struct sock *sk, struct sk_buff *s
+ net_dbg_ratelimited("%s: No header cache and no neighbour!\n",
+ __func__);
+ kfree_skb_reason(skb, SKB_DROP_REASON_NEIGH_CREATEFAIL);
+- return -EINVAL;
++ return PTR_ERR(neigh);
+ }
+
+ static int ip_finish_output_gso(struct net *net, struct sock *sk,
+--
+2.40.1
+
--- /dev/null
+From 9c9cd57351a2f9c85963dce9d5185a261237b2d3 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 18 Jul 2023 00:06:30 +0800
+Subject: net: stmmac: use per-queue 64 bit statistics where necessary
+
+From: Jisheng Zhang <jszhang@kernel.org>
+
+[ Upstream commit 133466c3bbe171f826294161db203f7670bb30c8 ]
+
+Currently, there are two major issues with stmmac driver statistics
+First of all, statistics in stmmac_extra_stats, stmmac_rxq_stats
+and stmmac_txq_stats are 32 bit variables on 32 bit platforms. This
+can cause some stats to overflow after several minutes of
+high traffic, for example rx_pkt_n, tx_pkt_n and so on.
+
+Secondly, if HW supports multiqueues, there are frequent cacheline
+ping pongs on some driver statistic vars, for example, normal_irq_n,
+tx_pkt_n and so on. What's more, frequent cacheline ping pongs on
+normal_irq_n happens in ISR, this makes the situation worse.
+
+To improve the driver, we convert those statistics to 64 bit, implement
+ndo_get_stats64 and update .get_ethtool_stats implementation
+accordingly. We also use per-queue statistics where necessary to remove
+the cacheline ping pongs as much as possible to make multiqueue
+operations faster. Those statistics which are not possible to overflow
+and not frequently updated are kept as is.
+
+Signed-off-by: Jisheng Zhang <jszhang@kernel.org>
+Link: https://lore.kernel.org/r/20230717160630.1892-3-jszhang@kernel.org
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/ethernet/stmicro/stmmac/common.h | 39 ++--
+ .../net/ethernet/stmicro/stmmac/dwmac-sun8i.c | 12 +-
+ .../ethernet/stmicro/stmmac/dwmac100_dma.c | 7 +-
+ .../ethernet/stmicro/stmmac/dwmac4_descs.c | 16 +-
+ .../net/ethernet/stmicro/stmmac/dwmac4_lib.c | 15 +-
+ .../net/ethernet/stmicro/stmmac/dwmac_lib.c | 12 +-
+ .../ethernet/stmicro/stmmac/dwxgmac2_descs.c | 6 +-
+ .../ethernet/stmicro/stmmac/dwxgmac2_dma.c | 14 +-
+ .../net/ethernet/stmicro/stmmac/enh_desc.c | 20 +-
+ drivers/net/ethernet/stmicro/stmmac/hwif.h | 12 +-
+ .../net/ethernet/stmicro/stmmac/norm_desc.c | 15 +-
+ drivers/net/ethernet/stmicro/stmmac/stmmac.h | 2 +
+ .../ethernet/stmicro/stmmac/stmmac_ethtool.c | 123 ++++++++---
+ .../net/ethernet/stmicro/stmmac/stmmac_main.c | 200 ++++++++++++++----
+ 14 files changed, 335 insertions(+), 158 deletions(-)
+
+diff --git a/drivers/net/ethernet/stmicro/stmmac/common.h b/drivers/net/ethernet/stmicro/stmmac/common.h
+index 16e67c18b6f71..57f2137bbe9d9 100644
+--- a/drivers/net/ethernet/stmicro/stmmac/common.h
++++ b/drivers/net/ethernet/stmicro/stmmac/common.h
+@@ -59,13 +59,25 @@
+ /* #define FRAME_FILTER_DEBUG */
+
+ struct stmmac_txq_stats {
+- unsigned long tx_pkt_n;
+- unsigned long tx_normal_irq_n;
++ u64 tx_bytes;
++ u64 tx_packets;
++ u64 tx_pkt_n;
++ u64 tx_normal_irq_n;
++ u64 napi_poll;
++ u64 tx_clean;
++ u64 tx_set_ic_bit;
++ u64 tx_tso_frames;
++ u64 tx_tso_nfrags;
++ struct u64_stats_sync syncp;
+ };
+
+ struct stmmac_rxq_stats {
+- unsigned long rx_pkt_n;
+- unsigned long rx_normal_irq_n;
++ u64 rx_bytes;
++ u64 rx_packets;
++ u64 rx_pkt_n;
++ u64 rx_normal_irq_n;
++ u64 napi_poll;
++ struct u64_stats_sync syncp;
+ };
+
+ /* Extra statistic and debug information exposed by ethtool */
+@@ -81,6 +93,7 @@ struct stmmac_extra_stats {
+ unsigned long tx_frame_flushed;
+ unsigned long tx_payload_error;
+ unsigned long tx_ip_header_error;
++ unsigned long tx_collision;
+ /* Receive errors */
+ unsigned long rx_desc;
+ unsigned long sa_filter_fail;
+@@ -113,14 +126,6 @@ struct stmmac_extra_stats {
+ /* Tx/Rx IRQ Events */
+ unsigned long rx_early_irq;
+ unsigned long threshold;
+- unsigned long tx_pkt_n;
+- unsigned long rx_pkt_n;
+- unsigned long normal_irq_n;
+- unsigned long rx_normal_irq_n;
+- unsigned long napi_poll;
+- unsigned long tx_normal_irq_n;
+- unsigned long tx_clean;
+- unsigned long tx_set_ic_bit;
+ unsigned long irq_receive_pmt_irq_n;
+ /* MMC info */
+ unsigned long mmc_tx_irq_n;
+@@ -190,18 +195,16 @@ struct stmmac_extra_stats {
+ unsigned long mtl_rx_fifo_ctrl_active;
+ unsigned long mac_rx_frame_ctrl_fifo;
+ unsigned long mac_gmii_rx_proto_engine;
+- /* TSO */
+- unsigned long tx_tso_frames;
+- unsigned long tx_tso_nfrags;
+ /* EST */
+ unsigned long mtl_est_cgce;
+ unsigned long mtl_est_hlbs;
+ unsigned long mtl_est_hlbf;
+ unsigned long mtl_est_btre;
+ unsigned long mtl_est_btrlm;
+- /* per queue statistics */
+- struct stmmac_txq_stats txq_stats[MTL_MAX_TX_QUEUES];
+- struct stmmac_rxq_stats rxq_stats[MTL_MAX_RX_QUEUES];
++ unsigned long rx_dropped;
++ unsigned long rx_errors;
++ unsigned long tx_dropped;
++ unsigned long tx_errors;
+ };
+
+ /* Safety Feature statistics exposed by ethtool */
+diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-sun8i.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-sun8i.c
+index 1e714380d1250..b20f8ba34efd9 100644
+--- a/drivers/net/ethernet/stmicro/stmmac/dwmac-sun8i.c
++++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-sun8i.c
+@@ -440,8 +440,10 @@ static int sun8i_dwmac_dma_interrupt(struct stmmac_priv *priv,
+ struct stmmac_extra_stats *x, u32 chan,
+ u32 dir)
+ {
+- u32 v;
++ struct stmmac_rx_queue *rx_q = &priv->dma_conf.rx_queue[chan];
++ struct stmmac_tx_queue *tx_q = &priv->dma_conf.tx_queue[chan];
+ int ret = 0;
++ u32 v;
+
+ v = readl(ioaddr + EMAC_INT_STA);
+
+@@ -452,7 +454,9 @@ static int sun8i_dwmac_dma_interrupt(struct stmmac_priv *priv,
+
+ if (v & EMAC_TX_INT) {
+ ret |= handle_tx;
+- x->tx_normal_irq_n++;
++ u64_stats_update_begin(&tx_q->txq_stats.syncp);
++ tx_q->txq_stats.tx_normal_irq_n++;
++ u64_stats_update_end(&tx_q->txq_stats.syncp);
+ }
+
+ if (v & EMAC_TX_DMA_STOP_INT)
+@@ -474,7 +478,9 @@ static int sun8i_dwmac_dma_interrupt(struct stmmac_priv *priv,
+
+ if (v & EMAC_RX_INT) {
+ ret |= handle_rx;
+- x->rx_normal_irq_n++;
++ u64_stats_update_begin(&rx_q->rxq_stats.syncp);
++ rx_q->rxq_stats.rx_normal_irq_n++;
++ u64_stats_update_end(&rx_q->rxq_stats.syncp);
+ }
+
+ if (v & EMAC_RX_BUF_UA_INT)
+diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac100_dma.c b/drivers/net/ethernet/stmicro/stmmac/dwmac100_dma.c
+index 1c32b1788f02e..dea270f60cc3e 100644
+--- a/drivers/net/ethernet/stmicro/stmmac/dwmac100_dma.c
++++ b/drivers/net/ethernet/stmicro/stmmac/dwmac100_dma.c
+@@ -82,29 +82,24 @@ static void dwmac100_dump_dma_regs(struct stmmac_priv *priv,
+ }
+
+ /* DMA controller has two counters to track the number of the missed frames. */
+-static void dwmac100_dma_diagnostic_fr(struct net_device_stats *stats,
+- struct stmmac_extra_stats *x,
++static void dwmac100_dma_diagnostic_fr(struct stmmac_extra_stats *x,
+ void __iomem *ioaddr)
+ {
+ u32 csr8 = readl(ioaddr + DMA_MISSED_FRAME_CTR);
+
+ if (unlikely(csr8)) {
+ if (csr8 & DMA_MISSED_FRAME_OVE) {
+- stats->rx_over_errors += 0x800;
+ x->rx_overflow_cntr += 0x800;
+ } else {
+ unsigned int ove_cntr;
+ ove_cntr = ((csr8 & DMA_MISSED_FRAME_OVE_CNTR) >> 17);
+- stats->rx_over_errors += ove_cntr;
+ x->rx_overflow_cntr += ove_cntr;
+ }
+
+ if (csr8 & DMA_MISSED_FRAME_OVE_M) {
+- stats->rx_missed_errors += 0xffff;
+ x->rx_missed_cntr += 0xffff;
+ } else {
+ unsigned int miss_f = (csr8 & DMA_MISSED_FRAME_M_CNTR);
+- stats->rx_missed_errors += miss_f;
+ x->rx_missed_cntr += miss_f;
+ }
+ }
+diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac4_descs.c b/drivers/net/ethernet/stmicro/stmmac/dwmac4_descs.c
+index 6a011d8633e8e..89a14084c6117 100644
+--- a/drivers/net/ethernet/stmicro/stmmac/dwmac4_descs.c
++++ b/drivers/net/ethernet/stmicro/stmmac/dwmac4_descs.c
+@@ -13,8 +13,7 @@
+ #include "dwmac4.h"
+ #include "dwmac4_descs.h"
+
+-static int dwmac4_wrback_get_tx_status(struct net_device_stats *stats,
+- struct stmmac_extra_stats *x,
++static int dwmac4_wrback_get_tx_status(struct stmmac_extra_stats *x,
+ struct dma_desc *p,
+ void __iomem *ioaddr)
+ {
+@@ -40,15 +39,13 @@ static int dwmac4_wrback_get_tx_status(struct net_device_stats *stats,
+ x->tx_frame_flushed++;
+ if (unlikely(tdes3 & TDES3_LOSS_CARRIER)) {
+ x->tx_losscarrier++;
+- stats->tx_carrier_errors++;
+ }
+ if (unlikely(tdes3 & TDES3_NO_CARRIER)) {
+ x->tx_carrier++;
+- stats->tx_carrier_errors++;
+ }
+ if (unlikely((tdes3 & TDES3_LATE_COLLISION) ||
+ (tdes3 & TDES3_EXCESSIVE_COLLISION)))
+- stats->collisions +=
++ x->tx_collision +=
+ (tdes3 & TDES3_COLLISION_COUNT_MASK)
+ >> TDES3_COLLISION_COUNT_SHIFT;
+
+@@ -73,8 +70,7 @@ static int dwmac4_wrback_get_tx_status(struct net_device_stats *stats,
+ return ret;
+ }
+
+-static int dwmac4_wrback_get_rx_status(struct net_device_stats *stats,
+- struct stmmac_extra_stats *x,
++static int dwmac4_wrback_get_rx_status(struct stmmac_extra_stats *x,
+ struct dma_desc *p)
+ {
+ unsigned int rdes1 = le32_to_cpu(p->des1);
+@@ -93,7 +89,7 @@ static int dwmac4_wrback_get_rx_status(struct net_device_stats *stats,
+
+ if (unlikely(rdes3 & RDES3_ERROR_SUMMARY)) {
+ if (unlikely(rdes3 & RDES3_GIANT_PACKET))
+- stats->rx_length_errors++;
++ x->rx_length++;
+ if (unlikely(rdes3 & RDES3_OVERFLOW_ERROR))
+ x->rx_gmac_overflow++;
+
+@@ -103,10 +99,8 @@ static int dwmac4_wrback_get_rx_status(struct net_device_stats *stats,
+ if (unlikely(rdes3 & RDES3_RECEIVE_ERROR))
+ x->rx_mii++;
+
+- if (unlikely(rdes3 & RDES3_CRC_ERROR)) {
++ if (unlikely(rdes3 & RDES3_CRC_ERROR))
+ x->rx_crc_errors++;
+- stats->rx_crc_errors++;
+- }
+
+ if (unlikely(rdes3 & RDES3_DRIBBLE_ERROR))
+ x->dribbling_bit++;
+diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac4_lib.c b/drivers/net/ethernet/stmicro/stmmac/dwmac4_lib.c
+index 03ceb6a940732..980e5f8a37ec5 100644
+--- a/drivers/net/ethernet/stmicro/stmmac/dwmac4_lib.c
++++ b/drivers/net/ethernet/stmicro/stmmac/dwmac4_lib.c
+@@ -171,6 +171,8 @@ int dwmac4_dma_interrupt(struct stmmac_priv *priv, void __iomem *ioaddr,
+ const struct dwmac4_addrs *dwmac4_addrs = priv->plat->dwmac4_addrs;
+ u32 intr_status = readl(ioaddr + DMA_CHAN_STATUS(dwmac4_addrs, chan));
+ u32 intr_en = readl(ioaddr + DMA_CHAN_INTR_ENA(dwmac4_addrs, chan));
++ struct stmmac_rx_queue *rx_q = &priv->dma_conf.rx_queue[chan];
++ struct stmmac_tx_queue *tx_q = &priv->dma_conf.tx_queue[chan];
+ int ret = 0;
+
+ if (dir == DMA_DIR_RX)
+@@ -198,18 +200,19 @@ int dwmac4_dma_interrupt(struct stmmac_priv *priv, void __iomem *ioaddr,
+ }
+ }
+ /* TX/RX NORMAL interrupts */
+- if (likely(intr_status & DMA_CHAN_STATUS_NIS))
+- x->normal_irq_n++;
+ if (likely(intr_status & DMA_CHAN_STATUS_RI)) {
+- x->rx_normal_irq_n++;
+- x->rxq_stats[chan].rx_normal_irq_n++;
++ u64_stats_update_begin(&rx_q->rxq_stats.syncp);
++ rx_q->rxq_stats.rx_normal_irq_n++;
++ u64_stats_update_end(&rx_q->rxq_stats.syncp);
+ ret |= handle_rx;
+ }
+ if (likely(intr_status & DMA_CHAN_STATUS_TI)) {
+- x->tx_normal_irq_n++;
+- x->txq_stats[chan].tx_normal_irq_n++;
++ u64_stats_update_begin(&tx_q->txq_stats.syncp);
++ tx_q->txq_stats.tx_normal_irq_n++;
++ u64_stats_update_end(&tx_q->txq_stats.syncp);
+ ret |= handle_tx;
+ }
++
+ if (unlikely(intr_status & DMA_CHAN_STATUS_TBU))
+ ret |= handle_tx;
+ if (unlikely(intr_status & DMA_CHAN_STATUS_ERI))
+diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac_lib.c b/drivers/net/ethernet/stmicro/stmmac/dwmac_lib.c
+index 0b6f999a83052..aaa09b16b016f 100644
+--- a/drivers/net/ethernet/stmicro/stmmac/dwmac_lib.c
++++ b/drivers/net/ethernet/stmicro/stmmac/dwmac_lib.c
+@@ -10,6 +10,7 @@
+ #include <linux/iopoll.h>
+ #include "common.h"
+ #include "dwmac_dma.h"
++#include "stmmac.h"
+
+ #define GMAC_HI_REG_AE 0x80000000
+
+@@ -161,6 +162,8 @@ static void show_rx_process_state(unsigned int status)
+ int dwmac_dma_interrupt(struct stmmac_priv *priv, void __iomem *ioaddr,
+ struct stmmac_extra_stats *x, u32 chan, u32 dir)
+ {
++ struct stmmac_rx_queue *rx_q = &priv->dma_conf.rx_queue[chan];
++ struct stmmac_tx_queue *tx_q = &priv->dma_conf.tx_queue[chan];
+ int ret = 0;
+ /* read the status register (CSR5) */
+ u32 intr_status = readl(ioaddr + DMA_STATUS);
+@@ -208,17 +211,20 @@ int dwmac_dma_interrupt(struct stmmac_priv *priv, void __iomem *ioaddr,
+ }
+ /* TX/RX NORMAL interrupts */
+ if (likely(intr_status & DMA_STATUS_NIS)) {
+- x->normal_irq_n++;
+ if (likely(intr_status & DMA_STATUS_RI)) {
+ u32 value = readl(ioaddr + DMA_INTR_ENA);
+ /* to schedule NAPI on real RIE event. */
+ if (likely(value & DMA_INTR_ENA_RIE)) {
+- x->rx_normal_irq_n++;
++ u64_stats_update_begin(&rx_q->rxq_stats.syncp);
++ rx_q->rxq_stats.rx_normal_irq_n++;
++ u64_stats_update_end(&rx_q->rxq_stats.syncp);
+ ret |= handle_rx;
+ }
+ }
+ if (likely(intr_status & DMA_STATUS_TI)) {
+- x->tx_normal_irq_n++;
++ u64_stats_update_begin(&tx_q->txq_stats.syncp);
++ tx_q->txq_stats.tx_normal_irq_n++;
++ u64_stats_update_end(&tx_q->txq_stats.syncp);
+ ret |= handle_tx;
+ }
+ if (unlikely(intr_status & DMA_STATUS_ERI))
+diff --git a/drivers/net/ethernet/stmicro/stmmac/dwxgmac2_descs.c b/drivers/net/ethernet/stmicro/stmmac/dwxgmac2_descs.c
+index 13c347ee8be9c..fc82862a612c7 100644
+--- a/drivers/net/ethernet/stmicro/stmmac/dwxgmac2_descs.c
++++ b/drivers/net/ethernet/stmicro/stmmac/dwxgmac2_descs.c
+@@ -8,8 +8,7 @@
+ #include "common.h"
+ #include "dwxgmac2.h"
+
+-static int dwxgmac2_get_tx_status(struct net_device_stats *stats,
+- struct stmmac_extra_stats *x,
++static int dwxgmac2_get_tx_status(struct stmmac_extra_stats *x,
+ struct dma_desc *p, void __iomem *ioaddr)
+ {
+ unsigned int tdes3 = le32_to_cpu(p->des3);
+@@ -23,8 +22,7 @@ static int dwxgmac2_get_tx_status(struct net_device_stats *stats,
+ return ret;
+ }
+
+-static int dwxgmac2_get_rx_status(struct net_device_stats *stats,
+- struct stmmac_extra_stats *x,
++static int dwxgmac2_get_rx_status(struct stmmac_extra_stats *x,
+ struct dma_desc *p)
+ {
+ unsigned int rdes3 = le32_to_cpu(p->des3);
+diff --git a/drivers/net/ethernet/stmicro/stmmac/dwxgmac2_dma.c b/drivers/net/ethernet/stmicro/stmmac/dwxgmac2_dma.c
+index 070bd912580b7..3b5f8c595219b 100644
+--- a/drivers/net/ethernet/stmicro/stmmac/dwxgmac2_dma.c
++++ b/drivers/net/ethernet/stmicro/stmmac/dwxgmac2_dma.c
+@@ -337,6 +337,8 @@ static int dwxgmac2_dma_interrupt(struct stmmac_priv *priv,
+ struct stmmac_extra_stats *x, u32 chan,
+ u32 dir)
+ {
++ struct stmmac_rx_queue *rx_q = &priv->dma_conf.rx_queue[chan];
++ struct stmmac_tx_queue *tx_q = &priv->dma_conf.tx_queue[chan];
+ u32 intr_status = readl(ioaddr + XGMAC_DMA_CH_STATUS(chan));
+ u32 intr_en = readl(ioaddr + XGMAC_DMA_CH_INT_EN(chan));
+ int ret = 0;
+@@ -364,16 +366,16 @@ static int dwxgmac2_dma_interrupt(struct stmmac_priv *priv,
+
+ /* TX/RX NORMAL interrupts */
+ if (likely(intr_status & XGMAC_NIS)) {
+- x->normal_irq_n++;
+-
+ if (likely(intr_status & XGMAC_RI)) {
+- x->rx_normal_irq_n++;
+- x->rxq_stats[chan].rx_normal_irq_n++;
++ u64_stats_update_begin(&rx_q->rxq_stats.syncp);
++ rx_q->rxq_stats.rx_normal_irq_n++;
++ u64_stats_update_end(&rx_q->rxq_stats.syncp);
+ ret |= handle_rx;
+ }
+ if (likely(intr_status & (XGMAC_TI | XGMAC_TBU))) {
+- x->tx_normal_irq_n++;
+- x->txq_stats[chan].tx_normal_irq_n++;
++ u64_stats_update_begin(&tx_q->txq_stats.syncp);
++ tx_q->txq_stats.tx_normal_irq_n++;
++ u64_stats_update_end(&tx_q->txq_stats.syncp);
+ ret |= handle_tx;
+ }
+ }
+diff --git a/drivers/net/ethernet/stmicro/stmmac/enh_desc.c b/drivers/net/ethernet/stmicro/stmmac/enh_desc.c
+index a91d8f13a931d..937b7a0466fca 100644
+--- a/drivers/net/ethernet/stmicro/stmmac/enh_desc.c
++++ b/drivers/net/ethernet/stmicro/stmmac/enh_desc.c
+@@ -12,8 +12,7 @@
+ #include "common.h"
+ #include "descs_com.h"
+
+-static int enh_desc_get_tx_status(struct net_device_stats *stats,
+- struct stmmac_extra_stats *x,
++static int enh_desc_get_tx_status(struct stmmac_extra_stats *x,
+ struct dma_desc *p, void __iomem *ioaddr)
+ {
+ unsigned int tdes0 = le32_to_cpu(p->des0);
+@@ -38,15 +37,13 @@ static int enh_desc_get_tx_status(struct net_device_stats *stats,
+
+ if (unlikely(tdes0 & ETDES0_LOSS_CARRIER)) {
+ x->tx_losscarrier++;
+- stats->tx_carrier_errors++;
+ }
+ if (unlikely(tdes0 & ETDES0_NO_CARRIER)) {
+ x->tx_carrier++;
+- stats->tx_carrier_errors++;
+ }
+ if (unlikely((tdes0 & ETDES0_LATE_COLLISION) ||
+ (tdes0 & ETDES0_EXCESSIVE_COLLISIONS)))
+- stats->collisions +=
++ x->tx_collision +=
+ (tdes0 & ETDES0_COLLISION_COUNT_MASK) >> 3;
+
+ if (unlikely(tdes0 & ETDES0_EXCESSIVE_DEFERRAL))
+@@ -117,8 +114,7 @@ static int enh_desc_coe_rdes0(int ipc_err, int type, int payload_err)
+ return ret;
+ }
+
+-static void enh_desc_get_ext_status(struct net_device_stats *stats,
+- struct stmmac_extra_stats *x,
++static void enh_desc_get_ext_status(struct stmmac_extra_stats *x,
+ struct dma_extended_desc *p)
+ {
+ unsigned int rdes0 = le32_to_cpu(p->basic.des0);
+@@ -182,8 +178,7 @@ static void enh_desc_get_ext_status(struct net_device_stats *stats,
+ }
+ }
+
+-static int enh_desc_get_rx_status(struct net_device_stats *stats,
+- struct stmmac_extra_stats *x,
++static int enh_desc_get_rx_status(struct stmmac_extra_stats *x,
+ struct dma_desc *p)
+ {
+ unsigned int rdes0 = le32_to_cpu(p->des0);
+@@ -193,14 +188,14 @@ static int enh_desc_get_rx_status(struct net_device_stats *stats,
+ return dma_own;
+
+ if (unlikely(!(rdes0 & RDES0_LAST_DESCRIPTOR))) {
+- stats->rx_length_errors++;
++ x->rx_length++;
+ return discard_frame;
+ }
+
+ if (unlikely(rdes0 & RDES0_ERROR_SUMMARY)) {
+ if (unlikely(rdes0 & RDES0_DESCRIPTOR_ERROR)) {
+ x->rx_desc++;
+- stats->rx_length_errors++;
++ x->rx_length++;
+ }
+ if (unlikely(rdes0 & RDES0_OVERFLOW_ERROR))
+ x->rx_gmac_overflow++;
+@@ -209,7 +204,7 @@ static int enh_desc_get_rx_status(struct net_device_stats *stats,
+ pr_err("\tIPC Csum Error/Giant frame\n");
+
+ if (unlikely(rdes0 & RDES0_COLLISION))
+- stats->collisions++;
++ x->rx_collision++;
+ if (unlikely(rdes0 & RDES0_RECEIVE_WATCHDOG))
+ x->rx_watchdog++;
+
+@@ -218,7 +213,6 @@ static int enh_desc_get_rx_status(struct net_device_stats *stats,
+
+ if (unlikely(rdes0 & RDES0_CRC_ERROR)) {
+ x->rx_crc_errors++;
+- stats->rx_crc_errors++;
+ }
+ ret = discard_frame;
+ }
+diff --git a/drivers/net/ethernet/stmicro/stmmac/hwif.h b/drivers/net/ethernet/stmicro/stmmac/hwif.h
+index 6ee7cf07cfd76..652af8f6e75ff 100644
+--- a/drivers/net/ethernet/stmicro/stmmac/hwif.h
++++ b/drivers/net/ethernet/stmicro/stmmac/hwif.h
+@@ -57,8 +57,7 @@ struct stmmac_desc_ops {
+ /* Last tx segment reports the transmit status */
+ int (*get_tx_ls)(struct dma_desc *p);
+ /* Return the transmit status looking at the TDES1 */
+- int (*tx_status)(struct net_device_stats *stats,
+- struct stmmac_extra_stats *x,
++ int (*tx_status)(struct stmmac_extra_stats *x,
+ struct dma_desc *p, void __iomem *ioaddr);
+ /* Get the buffer size from the descriptor */
+ int (*get_tx_len)(struct dma_desc *p);
+@@ -67,11 +66,9 @@ struct stmmac_desc_ops {
+ /* Get the receive frame size */
+ int (*get_rx_frame_len)(struct dma_desc *p, int rx_coe_type);
+ /* Return the reception status looking at the RDES1 */
+- int (*rx_status)(struct net_device_stats *stats,
+- struct stmmac_extra_stats *x,
++ int (*rx_status)(struct stmmac_extra_stats *x,
+ struct dma_desc *p);
+- void (*rx_extended_status)(struct net_device_stats *stats,
+- struct stmmac_extra_stats *x,
++ void (*rx_extended_status)(struct stmmac_extra_stats *x,
+ struct dma_extended_desc *p);
+ /* Set tx timestamp enable bit */
+ void (*enable_tx_timestamp) (struct dma_desc *p);
+@@ -191,8 +188,7 @@ struct stmmac_dma_ops {
+ void (*dma_tx_mode)(struct stmmac_priv *priv, void __iomem *ioaddr,
+ int mode, u32 channel, int fifosz, u8 qmode);
+ /* To track extra statistic (if supported) */
+- void (*dma_diagnostic_fr)(struct net_device_stats *stats,
+- struct stmmac_extra_stats *x,
++ void (*dma_diagnostic_fr)(struct stmmac_extra_stats *x,
+ void __iomem *ioaddr);
+ void (*enable_dma_transmission) (void __iomem *ioaddr);
+ void (*enable_dma_irq)(struct stmmac_priv *priv, void __iomem *ioaddr,
+diff --git a/drivers/net/ethernet/stmicro/stmmac/norm_desc.c b/drivers/net/ethernet/stmicro/stmmac/norm_desc.c
+index 350e6670a5766..68a7cfcb1d8f3 100644
+--- a/drivers/net/ethernet/stmicro/stmmac/norm_desc.c
++++ b/drivers/net/ethernet/stmicro/stmmac/norm_desc.c
+@@ -12,8 +12,7 @@
+ #include "common.h"
+ #include "descs_com.h"
+
+-static int ndesc_get_tx_status(struct net_device_stats *stats,
+- struct stmmac_extra_stats *x,
++static int ndesc_get_tx_status(struct stmmac_extra_stats *x,
+ struct dma_desc *p, void __iomem *ioaddr)
+ {
+ unsigned int tdes0 = le32_to_cpu(p->des0);
+@@ -31,15 +30,12 @@ static int ndesc_get_tx_status(struct net_device_stats *stats,
+ if (unlikely(tdes0 & TDES0_ERROR_SUMMARY)) {
+ if (unlikely(tdes0 & TDES0_UNDERFLOW_ERROR)) {
+ x->tx_underflow++;
+- stats->tx_fifo_errors++;
+ }
+ if (unlikely(tdes0 & TDES0_NO_CARRIER)) {
+ x->tx_carrier++;
+- stats->tx_carrier_errors++;
+ }
+ if (unlikely(tdes0 & TDES0_LOSS_CARRIER)) {
+ x->tx_losscarrier++;
+- stats->tx_carrier_errors++;
+ }
+ if (unlikely((tdes0 & TDES0_EXCESSIVE_DEFERRAL) ||
+ (tdes0 & TDES0_EXCESSIVE_COLLISIONS) ||
+@@ -47,7 +43,7 @@ static int ndesc_get_tx_status(struct net_device_stats *stats,
+ unsigned int collisions;
+
+ collisions = (tdes0 & TDES0_COLLISION_COUNT_MASK) >> 3;
+- stats->collisions += collisions;
++ x->tx_collision += collisions;
+ }
+ ret = tx_err;
+ }
+@@ -70,8 +66,7 @@ static int ndesc_get_tx_len(struct dma_desc *p)
+ * and, if required, updates the multicast statistics.
+ * In case of success, it returns good_frame because the GMAC device
+ * is supposed to be able to compute the csum in HW. */
+-static int ndesc_get_rx_status(struct net_device_stats *stats,
+- struct stmmac_extra_stats *x,
++static int ndesc_get_rx_status(struct stmmac_extra_stats *x,
+ struct dma_desc *p)
+ {
+ int ret = good_frame;
+@@ -81,7 +76,7 @@ static int ndesc_get_rx_status(struct net_device_stats *stats,
+ return dma_own;
+
+ if (unlikely(!(rdes0 & RDES0_LAST_DESCRIPTOR))) {
+- stats->rx_length_errors++;
++ x->rx_length++;
+ return discard_frame;
+ }
+
+@@ -96,11 +91,9 @@ static int ndesc_get_rx_status(struct net_device_stats *stats,
+ x->ipc_csum_error++;
+ if (unlikely(rdes0 & RDES0_COLLISION)) {
+ x->rx_collision++;
+- stats->collisions++;
+ }
+ if (unlikely(rdes0 & RDES0_CRC_ERROR)) {
+ x->rx_crc_errors++;
+- stats->rx_crc_errors++;
+ }
+ ret = discard_frame;
+ }
+diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac.h b/drivers/net/ethernet/stmicro/stmmac/stmmac.h
+index 07ea5ab0a60ba..4ce5eaaae5135 100644
+--- a/drivers/net/ethernet/stmicro/stmmac/stmmac.h
++++ b/drivers/net/ethernet/stmicro/stmmac/stmmac.h
+@@ -77,6 +77,7 @@ struct stmmac_tx_queue {
+ dma_addr_t dma_tx_phy;
+ dma_addr_t tx_tail_addr;
+ u32 mss;
++ struct stmmac_txq_stats txq_stats;
+ };
+
+ struct stmmac_rx_buffer {
+@@ -121,6 +122,7 @@ struct stmmac_rx_queue {
+ unsigned int len;
+ unsigned int error;
+ } state;
++ struct stmmac_rxq_stats rxq_stats;
+ };
+
+ struct stmmac_channel {
+diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c
+index 2ae73ab842d45..b7ac7abecdd35 100644
+--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c
++++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c
+@@ -89,14 +89,6 @@ static const struct stmmac_stats stmmac_gstrings_stats[] = {
+ /* Tx/Rx IRQ Events */
+ STMMAC_STAT(rx_early_irq),
+ STMMAC_STAT(threshold),
+- STMMAC_STAT(tx_pkt_n),
+- STMMAC_STAT(rx_pkt_n),
+- STMMAC_STAT(normal_irq_n),
+- STMMAC_STAT(rx_normal_irq_n),
+- STMMAC_STAT(napi_poll),
+- STMMAC_STAT(tx_normal_irq_n),
+- STMMAC_STAT(tx_clean),
+- STMMAC_STAT(tx_set_ic_bit),
+ STMMAC_STAT(irq_receive_pmt_irq_n),
+ /* MMC info */
+ STMMAC_STAT(mmc_tx_irq_n),
+@@ -163,9 +155,6 @@ static const struct stmmac_stats stmmac_gstrings_stats[] = {
+ STMMAC_STAT(mtl_rx_fifo_ctrl_active),
+ STMMAC_STAT(mac_rx_frame_ctrl_fifo),
+ STMMAC_STAT(mac_gmii_rx_proto_engine),
+- /* TSO */
+- STMMAC_STAT(tx_tso_frames),
+- STMMAC_STAT(tx_tso_nfrags),
+ /* EST */
+ STMMAC_STAT(mtl_est_cgce),
+ STMMAC_STAT(mtl_est_hlbs),
+@@ -175,6 +164,23 @@ static const struct stmmac_stats stmmac_gstrings_stats[] = {
+ };
+ #define STMMAC_STATS_LEN ARRAY_SIZE(stmmac_gstrings_stats)
+
++/* statistics collected in queue which will be summed up for all TX or RX
++ * queues, or summed up for both TX and RX queues(napi_poll, normal_irq_n).
++ */
++static const char stmmac_qstats_string[][ETH_GSTRING_LEN] = {
++ "rx_pkt_n",
++ "rx_normal_irq_n",
++ "tx_pkt_n",
++ "tx_normal_irq_n",
++ "tx_clean",
++ "tx_set_ic_bit",
++ "tx_tso_frames",
++ "tx_tso_nfrags",
++ "normal_irq_n",
++ "napi_poll",
++};
++#define STMMAC_QSTATS ARRAY_SIZE(stmmac_qstats_string)
++
+ /* HW MAC Management counters (if supported) */
+ #define STMMAC_MMC_STAT(m) \
+ { #m, sizeof_field(struct stmmac_counters, m), \
+@@ -535,23 +541,44 @@ static void stmmac_get_per_qstats(struct stmmac_priv *priv, u64 *data)
+ {
+ u32 tx_cnt = priv->plat->tx_queues_to_use;
+ u32 rx_cnt = priv->plat->rx_queues_to_use;
++ unsigned int start;
+ int q, stat;
++ u64 *pos;
+ char *p;
+
++ pos = data;
+ for (q = 0; q < tx_cnt; q++) {
+- p = (char *)priv + offsetof(struct stmmac_priv,
+- xstats.txq_stats[q].tx_pkt_n);
++ struct stmmac_tx_queue *tx_q = &priv->dma_conf.tx_queue[q];
++ struct stmmac_txq_stats snapshot;
++
++ data = pos;
++ do {
++ start = u64_stats_fetch_begin(&tx_q->txq_stats.syncp);
++ snapshot = tx_q->txq_stats;
++ } while (u64_stats_fetch_retry(&tx_q->txq_stats.syncp, start));
++
++ p = (char *)&snapshot + offsetof(struct stmmac_txq_stats, tx_pkt_n);
+ for (stat = 0; stat < STMMAC_TXQ_STATS; stat++) {
+- *data++ = (*(unsigned long *)p);
+- p += sizeof(unsigned long);
++ *data++ += (*(u64 *)p);
++ p += sizeof(u64);
+ }
+ }
++
++ pos = data;
+ for (q = 0; q < rx_cnt; q++) {
+- p = (char *)priv + offsetof(struct stmmac_priv,
+- xstats.rxq_stats[q].rx_pkt_n);
++ struct stmmac_rx_queue *rx_q = &priv->dma_conf.rx_queue[q];
++ struct stmmac_rxq_stats snapshot;
++
++ data = pos;
++ do {
++ start = u64_stats_fetch_begin(&rx_q->rxq_stats.syncp);
++ snapshot = rx_q->rxq_stats;
++ } while (u64_stats_fetch_retry(&rx_q->rxq_stats.syncp, start));
++
++ p = (char *)&snapshot + offsetof(struct stmmac_rxq_stats, rx_pkt_n);
+ for (stat = 0; stat < STMMAC_RXQ_STATS; stat++) {
+- *data++ = (*(unsigned long *)p);
+- p += sizeof(unsigned long);
++ *data++ += (*(u64 *)p);
++ p += sizeof(u64);
+ }
+ }
+ }
+@@ -562,8 +589,10 @@ static void stmmac_get_ethtool_stats(struct net_device *dev,
+ struct stmmac_priv *priv = netdev_priv(dev);
+ u32 rx_queues_count = priv->plat->rx_queues_to_use;
+ u32 tx_queues_count = priv->plat->tx_queues_to_use;
++ u64 napi_poll = 0, normal_irq_n = 0;
++ int i, j = 0, pos, ret;
+ unsigned long count;
+- int i, j = 0, ret;
++ unsigned int start;
+
+ if (priv->dma_cap.asp) {
+ for (i = 0; i < STMMAC_SAFETY_FEAT_SIZE; i++) {
+@@ -574,8 +603,7 @@ static void stmmac_get_ethtool_stats(struct net_device *dev,
+ }
+
+ /* Update the DMA HW counters for dwmac10/100 */
+- ret = stmmac_dma_diagnostic_fr(priv, &dev->stats, (void *) &priv->xstats,
+- priv->ioaddr);
++ ret = stmmac_dma_diagnostic_fr(priv, &priv->xstats, priv->ioaddr);
+ if (ret) {
+ /* If supported, for new GMAC chips expose the MMC counters */
+ if (priv->dma_cap.rmon) {
+@@ -606,6 +634,48 @@ static void stmmac_get_ethtool_stats(struct net_device *dev,
+ data[j++] = (stmmac_gstrings_stats[i].sizeof_stat ==
+ sizeof(u64)) ? (*(u64 *)p) : (*(u32 *)p);
+ }
++
++ pos = j;
++ for (i = 0; i < rx_queues_count; i++) {
++ struct stmmac_rx_queue *rx_q = &priv->dma_conf.rx_queue[i];
++ struct stmmac_rxq_stats snapshot;
++
++ j = pos;
++ do {
++ start = u64_stats_fetch_begin(&rx_q->rxq_stats.syncp);
++ snapshot = rx_q->rxq_stats;
++ } while (u64_stats_fetch_retry(&rx_q->rxq_stats.syncp, start));
++
++ data[j++] += snapshot.rx_pkt_n;
++ data[j++] += snapshot.rx_normal_irq_n;
++ normal_irq_n += snapshot.rx_normal_irq_n;
++ napi_poll += snapshot.napi_poll;
++ }
++
++ pos = j;
++ for (i = 0; i < tx_queues_count; i++) {
++ struct stmmac_tx_queue *tx_q = &priv->dma_conf.tx_queue[i];
++ struct stmmac_txq_stats snapshot;
++
++ j = pos;
++ do {
++ start = u64_stats_fetch_begin(&tx_q->txq_stats.syncp);
++ snapshot = tx_q->txq_stats;
++ } while (u64_stats_fetch_retry(&tx_q->txq_stats.syncp, start));
++
++ data[j++] += snapshot.tx_pkt_n;
++ data[j++] += snapshot.tx_normal_irq_n;
++ normal_irq_n += snapshot.tx_normal_irq_n;
++ data[j++] += snapshot.tx_clean;
++ data[j++] += snapshot.tx_set_ic_bit;
++ data[j++] += snapshot.tx_tso_frames;
++ data[j++] += snapshot.tx_tso_nfrags;
++ napi_poll += snapshot.napi_poll;
++ }
++ normal_irq_n += priv->xstats.rx_early_irq;
++ data[j++] = normal_irq_n;
++ data[j++] = napi_poll;
++
+ stmmac_get_per_qstats(priv, &data[j]);
+ }
+
+@@ -618,7 +688,7 @@ static int stmmac_get_sset_count(struct net_device *netdev, int sset)
+
+ switch (sset) {
+ case ETH_SS_STATS:
+- len = STMMAC_STATS_LEN +
++ len = STMMAC_STATS_LEN + STMMAC_QSTATS +
+ STMMAC_TXQ_STATS * tx_cnt +
+ STMMAC_RXQ_STATS * rx_cnt;
+
+@@ -691,8 +761,11 @@ static void stmmac_get_strings(struct net_device *dev, u32 stringset, u8 *data)
+ p += ETH_GSTRING_LEN;
+ }
+ for (i = 0; i < STMMAC_STATS_LEN; i++) {
+- memcpy(p, stmmac_gstrings_stats[i].stat_string,
+- ETH_GSTRING_LEN);
++ memcpy(p, stmmac_gstrings_stats[i].stat_string, ETH_GSTRING_LEN);
++ p += ETH_GSTRING_LEN;
++ }
++ for (i = 0; i < STMMAC_QSTATS; i++) {
++ memcpy(p, stmmac_qstats_string[i], ETH_GSTRING_LEN);
+ p += ETH_GSTRING_LEN;
+ }
+ stmmac_get_qstats_string(priv, p);
+diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
+index 6931973028aef..def490a1e2120 100644
+--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
++++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
+@@ -2432,6 +2432,8 @@ static bool stmmac_xdp_xmit_zc(struct stmmac_priv *priv, u32 queue, u32 budget)
+ struct dma_desc *tx_desc = NULL;
+ struct xdp_desc xdp_desc;
+ bool work_done = true;
++ u32 tx_set_ic_bit = 0;
++ unsigned long flags;
+
+ /* Avoids TX time-out as we are sharing with slow path */
+ txq_trans_cond_update(nq);
+@@ -2492,7 +2494,7 @@ static bool stmmac_xdp_xmit_zc(struct stmmac_priv *priv, u32 queue, u32 budget)
+ if (set_ic) {
+ tx_q->tx_count_frames = 0;
+ stmmac_set_tx_ic(priv, tx_desc);
+- priv->xstats.tx_set_ic_bit++;
++ tx_set_ic_bit++;
+ }
+
+ stmmac_prepare_tx_desc(priv, tx_desc, 1, xdp_desc.len,
+@@ -2504,6 +2506,9 @@ static bool stmmac_xdp_xmit_zc(struct stmmac_priv *priv, u32 queue, u32 budget)
+ tx_q->cur_tx = STMMAC_GET_ENTRY(tx_q->cur_tx, priv->dma_conf.dma_tx_size);
+ entry = tx_q->cur_tx;
+ }
++ flags = u64_stats_update_begin_irqsave(&tx_q->txq_stats.syncp);
++ tx_q->txq_stats.tx_set_ic_bit += tx_set_ic_bit;
++ u64_stats_update_end_irqrestore(&tx_q->txq_stats.syncp, flags);
+
+ if (tx_desc) {
+ stmmac_flush_tx_descriptors(priv, queue);
+@@ -2545,11 +2550,11 @@ static int stmmac_tx_clean(struct stmmac_priv *priv, int budget, u32 queue)
+ struct stmmac_tx_queue *tx_q = &priv->dma_conf.tx_queue[queue];
+ unsigned int bytes_compl = 0, pkts_compl = 0;
+ unsigned int entry, xmits = 0, count = 0;
++ u32 tx_packets = 0, tx_errors = 0;
++ unsigned long flags;
+
+ __netif_tx_lock_bh(netdev_get_tx_queue(priv->dev, queue));
+
+- priv->xstats.tx_clean++;
+-
+ tx_q->xsk_frames_done = 0;
+
+ entry = tx_q->dirty_tx;
+@@ -2580,8 +2585,7 @@ static int stmmac_tx_clean(struct stmmac_priv *priv, int budget, u32 queue)
+ else
+ p = tx_q->dma_tx + entry;
+
+- status = stmmac_tx_status(priv, &priv->dev->stats,
+- &priv->xstats, p, priv->ioaddr);
++ status = stmmac_tx_status(priv, &priv->xstats, p, priv->ioaddr);
+ /* Check if the descriptor is owned by the DMA */
+ if (unlikely(status & tx_dma_own))
+ break;
+@@ -2597,13 +2601,11 @@ static int stmmac_tx_clean(struct stmmac_priv *priv, int budget, u32 queue)
+ if (likely(!(status & tx_not_ls))) {
+ /* ... verify the status error condition */
+ if (unlikely(status & tx_err)) {
+- priv->dev->stats.tx_errors++;
++ tx_errors++;
+ if (unlikely(status & tx_err_bump_tc))
+ stmmac_bump_dma_threshold(priv, queue);
+ } else {
+- priv->dev->stats.tx_packets++;
+- priv->xstats.tx_pkt_n++;
+- priv->xstats.txq_stats[queue].tx_pkt_n++;
++ tx_packets++;
+ }
+ if (skb)
+ stmmac_get_tx_hwtstamp(priv, p, skb);
+@@ -2705,6 +2707,14 @@ static int stmmac_tx_clean(struct stmmac_priv *priv, int budget, u32 queue)
+ if (tx_q->dirty_tx != tx_q->cur_tx)
+ stmmac_tx_timer_arm(priv, queue);
+
++ flags = u64_stats_update_begin_irqsave(&tx_q->txq_stats.syncp);
++ tx_q->txq_stats.tx_packets += tx_packets;
++ tx_q->txq_stats.tx_pkt_n += tx_packets;
++ tx_q->txq_stats.tx_clean++;
++ u64_stats_update_end_irqrestore(&tx_q->txq_stats.syncp, flags);
++
++ priv->xstats.tx_errors += tx_errors;
++
+ __netif_tx_unlock_bh(netdev_get_tx_queue(priv->dev, queue));
+
+ /* Combine decisions from TX clean and XSK TX */
+@@ -2732,7 +2742,7 @@ static void stmmac_tx_err(struct stmmac_priv *priv, u32 chan)
+ tx_q->dma_tx_phy, chan);
+ stmmac_start_tx_dma(priv, chan);
+
+- priv->dev->stats.tx_errors++;
++ priv->xstats.tx_errors++;
+ netif_tx_wake_queue(netdev_get_tx_queue(priv->dev, chan));
+ }
+
+@@ -4112,6 +4122,7 @@ static netdev_tx_t stmmac_tso_xmit(struct sk_buff *skb, struct net_device *dev)
+ struct stmmac_tx_queue *tx_q;
+ bool has_vlan, set_ic;
+ u8 proto_hdr_len, hdr;
++ unsigned long flags;
+ u32 pay_len, mss;
+ dma_addr_t des;
+ int i;
+@@ -4260,7 +4271,6 @@ static netdev_tx_t stmmac_tso_xmit(struct sk_buff *skb, struct net_device *dev)
+
+ tx_q->tx_count_frames = 0;
+ stmmac_set_tx_ic(priv, desc);
+- priv->xstats.tx_set_ic_bit++;
+ }
+
+ /* We've used all descriptors we need for this skb, however,
+@@ -4276,9 +4286,13 @@ static netdev_tx_t stmmac_tso_xmit(struct sk_buff *skb, struct net_device *dev)
+ netif_tx_stop_queue(netdev_get_tx_queue(priv->dev, queue));
+ }
+
+- dev->stats.tx_bytes += skb->len;
+- priv->xstats.tx_tso_frames++;
+- priv->xstats.tx_tso_nfrags += nfrags;
++ flags = u64_stats_update_begin_irqsave(&tx_q->txq_stats.syncp);
++ tx_q->txq_stats.tx_bytes += skb->len;
++ tx_q->txq_stats.tx_tso_frames++;
++ tx_q->txq_stats.tx_tso_nfrags += nfrags;
++ if (set_ic)
++ tx_q->txq_stats.tx_set_ic_bit++;
++ u64_stats_update_end_irqrestore(&tx_q->txq_stats.syncp, flags);
+
+ if (priv->sarc_type)
+ stmmac_set_desc_sarc(priv, first, priv->sarc_type);
+@@ -4328,7 +4342,7 @@ static netdev_tx_t stmmac_tso_xmit(struct sk_buff *skb, struct net_device *dev)
+ dma_map_err:
+ dev_err(priv->device, "Tx dma map failed\n");
+ dev_kfree_skb(skb);
+- priv->dev->stats.tx_dropped++;
++ priv->xstats.tx_dropped++;
+ return NETDEV_TX_OK;
+ }
+
+@@ -4354,6 +4368,7 @@ static netdev_tx_t stmmac_xmit(struct sk_buff *skb, struct net_device *dev)
+ struct stmmac_tx_queue *tx_q;
+ bool has_vlan, set_ic;
+ int entry, first_tx;
++ unsigned long flags;
+ dma_addr_t des;
+
+ tx_q = &priv->dma_conf.tx_queue[queue];
+@@ -4482,7 +4497,6 @@ static netdev_tx_t stmmac_xmit(struct sk_buff *skb, struct net_device *dev)
+
+ tx_q->tx_count_frames = 0;
+ stmmac_set_tx_ic(priv, desc);
+- priv->xstats.tx_set_ic_bit++;
+ }
+
+ /* We've used all descriptors we need for this skb, however,
+@@ -4509,7 +4523,11 @@ static netdev_tx_t stmmac_xmit(struct sk_buff *skb, struct net_device *dev)
+ netif_tx_stop_queue(netdev_get_tx_queue(priv->dev, queue));
+ }
+
+- dev->stats.tx_bytes += skb->len;
++ flags = u64_stats_update_begin_irqsave(&tx_q->txq_stats.syncp);
++ tx_q->txq_stats.tx_bytes += skb->len;
++ if (set_ic)
++ tx_q->txq_stats.tx_set_ic_bit++;
++ u64_stats_update_end_irqrestore(&tx_q->txq_stats.syncp, flags);
+
+ if (priv->sarc_type)
+ stmmac_set_desc_sarc(priv, first, priv->sarc_type);
+@@ -4571,7 +4589,7 @@ static netdev_tx_t stmmac_xmit(struct sk_buff *skb, struct net_device *dev)
+ dma_map_err:
+ netdev_err(priv->dev, "Tx DMA map failed\n");
+ dev_kfree_skb(skb);
+- priv->dev->stats.tx_dropped++;
++ priv->xstats.tx_dropped++;
+ return NETDEV_TX_OK;
+ }
+
+@@ -4772,9 +4790,12 @@ static int stmmac_xdp_xmit_xdpf(struct stmmac_priv *priv, int queue,
+ set_ic = false;
+
+ if (set_ic) {
++ unsigned long flags;
+ tx_q->tx_count_frames = 0;
+ stmmac_set_tx_ic(priv, tx_desc);
+- priv->xstats.tx_set_ic_bit++;
++ flags = u64_stats_update_begin_irqsave(&tx_q->txq_stats.syncp);
++ tx_q->txq_stats.tx_set_ic_bit++;
++ u64_stats_update_end_irqrestore(&tx_q->txq_stats.syncp, flags);
+ }
+
+ stmmac_enable_dma_transmission(priv, priv->ioaddr);
+@@ -4919,16 +4940,18 @@ static void stmmac_dispatch_skb_zc(struct stmmac_priv *priv, u32 queue,
+ struct dma_desc *p, struct dma_desc *np,
+ struct xdp_buff *xdp)
+ {
++ struct stmmac_rx_queue *rx_q = &priv->dma_conf.rx_queue[queue];
+ struct stmmac_channel *ch = &priv->channel[queue];
+ unsigned int len = xdp->data_end - xdp->data;
+ enum pkt_hash_types hash_type;
+ int coe = priv->hw->rx_csum;
++ unsigned long flags;
+ struct sk_buff *skb;
+ u32 hash;
+
+ skb = stmmac_construct_skb_zc(ch, xdp);
+ if (!skb) {
+- priv->dev->stats.rx_dropped++;
++ priv->xstats.rx_dropped++;
+ return;
+ }
+
+@@ -4947,8 +4970,10 @@ static void stmmac_dispatch_skb_zc(struct stmmac_priv *priv, u32 queue,
+ skb_record_rx_queue(skb, queue);
+ napi_gro_receive(&ch->rxtx_napi, skb);
+
+- priv->dev->stats.rx_packets++;
+- priv->dev->stats.rx_bytes += len;
++ flags = u64_stats_update_begin_irqsave(&rx_q->rxq_stats.syncp);
++ rx_q->rxq_stats.rx_pkt_n++;
++ rx_q->rxq_stats.rx_bytes += len;
++ u64_stats_update_end_irqrestore(&rx_q->rxq_stats.syncp, flags);
+ }
+
+ static bool stmmac_rx_refill_zc(struct stmmac_priv *priv, u32 queue, u32 budget)
+@@ -5025,9 +5050,11 @@ static int stmmac_rx_zc(struct stmmac_priv *priv, int limit, u32 queue)
+ unsigned int count = 0, error = 0, len = 0;
+ int dirty = stmmac_rx_dirty(priv, queue);
+ unsigned int next_entry = rx_q->cur_rx;
++ u32 rx_errors = 0, rx_dropped = 0;
+ unsigned int desc_size;
+ struct bpf_prog *prog;
+ bool failure = false;
++ unsigned long flags;
+ int xdp_status = 0;
+ int status = 0;
+
+@@ -5083,8 +5110,7 @@ static int stmmac_rx_zc(struct stmmac_priv *priv, int limit, u32 queue)
+ p = rx_q->dma_rx + entry;
+
+ /* read the status of the incoming frame */
+- status = stmmac_rx_status(priv, &priv->dev->stats,
+- &priv->xstats, p);
++ status = stmmac_rx_status(priv, &priv->xstats, p);
+ /* check if managed by the DMA otherwise go ahead */
+ if (unlikely(status & dma_own))
+ break;
+@@ -5106,8 +5132,7 @@ static int stmmac_rx_zc(struct stmmac_priv *priv, int limit, u32 queue)
+ break;
+
+ if (priv->extend_desc)
+- stmmac_rx_extended_status(priv, &priv->dev->stats,
+- &priv->xstats,
++ stmmac_rx_extended_status(priv, &priv->xstats,
+ rx_q->dma_erx + entry);
+ if (unlikely(status == discard_frame)) {
+ xsk_buff_free(buf->xdp);
+@@ -5115,7 +5140,7 @@ static int stmmac_rx_zc(struct stmmac_priv *priv, int limit, u32 queue)
+ dirty++;
+ error = 1;
+ if (!priv->hwts_rx_en)
+- priv->dev->stats.rx_errors++;
++ rx_errors++;
+ }
+
+ if (unlikely(error && (status & rx_not_ls)))
+@@ -5163,7 +5188,7 @@ static int stmmac_rx_zc(struct stmmac_priv *priv, int limit, u32 queue)
+ break;
+ case STMMAC_XDP_CONSUMED:
+ xsk_buff_free(buf->xdp);
+- priv->dev->stats.rx_dropped++;
++ rx_dropped++;
+ break;
+ case STMMAC_XDP_TX:
+ case STMMAC_XDP_REDIRECT:
+@@ -5184,8 +5209,12 @@ static int stmmac_rx_zc(struct stmmac_priv *priv, int limit, u32 queue)
+
+ stmmac_finalize_xdp_rx(priv, xdp_status);
+
+- priv->xstats.rx_pkt_n += count;
+- priv->xstats.rxq_stats[queue].rx_pkt_n += count;
++ flags = u64_stats_update_begin_irqsave(&rx_q->rxq_stats.syncp);
++ rx_q->rxq_stats.rx_pkt_n += count;
++ u64_stats_update_end_irqrestore(&rx_q->rxq_stats.syncp, flags);
++
++ priv->xstats.rx_dropped += rx_dropped;
++ priv->xstats.rx_errors += rx_errors;
+
+ if (xsk_uses_need_wakeup(rx_q->xsk_pool)) {
+ if (failure || stmmac_rx_dirty(priv, queue) > 0)
+@@ -5209,6 +5238,7 @@ static int stmmac_rx_zc(struct stmmac_priv *priv, int limit, u32 queue)
+ */
+ static int stmmac_rx(struct stmmac_priv *priv, int limit, u32 queue)
+ {
++ u32 rx_errors = 0, rx_dropped = 0, rx_bytes = 0, rx_packets = 0;
+ struct stmmac_rx_queue *rx_q = &priv->dma_conf.rx_queue[queue];
+ struct stmmac_channel *ch = &priv->channel[queue];
+ unsigned int count = 0, error = 0, len = 0;
+@@ -5218,6 +5248,7 @@ static int stmmac_rx(struct stmmac_priv *priv, int limit, u32 queue)
+ unsigned int desc_size;
+ struct sk_buff *skb = NULL;
+ struct stmmac_xdp_buff ctx;
++ unsigned long flags;
+ int xdp_status = 0;
+ int buf_sz;
+
+@@ -5273,8 +5304,7 @@ static int stmmac_rx(struct stmmac_priv *priv, int limit, u32 queue)
+ p = rx_q->dma_rx + entry;
+
+ /* read the status of the incoming frame */
+- status = stmmac_rx_status(priv, &priv->dev->stats,
+- &priv->xstats, p);
++ status = stmmac_rx_status(priv, &priv->xstats, p);
+ /* check if managed by the DMA otherwise go ahead */
+ if (unlikely(status & dma_own))
+ break;
+@@ -5291,14 +5321,13 @@ static int stmmac_rx(struct stmmac_priv *priv, int limit, u32 queue)
+ prefetch(np);
+
+ if (priv->extend_desc)
+- stmmac_rx_extended_status(priv, &priv->dev->stats,
+- &priv->xstats, rx_q->dma_erx + entry);
++ stmmac_rx_extended_status(priv, &priv->xstats, rx_q->dma_erx + entry);
+ if (unlikely(status == discard_frame)) {
+ page_pool_recycle_direct(rx_q->page_pool, buf->page);
+ buf->page = NULL;
+ error = 1;
+ if (!priv->hwts_rx_en)
+- priv->dev->stats.rx_errors++;
++ rx_errors++;
+ }
+
+ if (unlikely(error && (status & rx_not_ls)))
+@@ -5366,7 +5395,7 @@ static int stmmac_rx(struct stmmac_priv *priv, int limit, u32 queue)
+ virt_to_head_page(ctx.xdp.data),
+ sync_len, true);
+ buf->page = NULL;
+- priv->dev->stats.rx_dropped++;
++ rx_dropped++;
+
+ /* Clear skb as it was set as
+ * status by XDP program.
+@@ -5395,7 +5424,7 @@ static int stmmac_rx(struct stmmac_priv *priv, int limit, u32 queue)
+
+ skb = napi_alloc_skb(&ch->rx_napi, buf1_len);
+ if (!skb) {
+- priv->dev->stats.rx_dropped++;
++ rx_dropped++;
+ count++;
+ goto drain_data;
+ }
+@@ -5455,8 +5484,8 @@ static int stmmac_rx(struct stmmac_priv *priv, int limit, u32 queue)
+ napi_gro_receive(&ch->rx_napi, skb);
+ skb = NULL;
+
+- priv->dev->stats.rx_packets++;
+- priv->dev->stats.rx_bytes += len;
++ rx_packets++;
++ rx_bytes += len;
+ count++;
+ }
+
+@@ -5471,8 +5500,14 @@ static int stmmac_rx(struct stmmac_priv *priv, int limit, u32 queue)
+
+ stmmac_rx_refill(priv, queue);
+
+- priv->xstats.rx_pkt_n += count;
+- priv->xstats.rxq_stats[queue].rx_pkt_n += count;
++ flags = u64_stats_update_begin_irqsave(&rx_q->rxq_stats.syncp);
++ rx_q->rxq_stats.rx_packets += rx_packets;
++ rx_q->rxq_stats.rx_bytes += rx_bytes;
++ rx_q->rxq_stats.rx_pkt_n += count;
++ u64_stats_update_end_irqrestore(&rx_q->rxq_stats.syncp, flags);
++
++ priv->xstats.rx_dropped += rx_dropped;
++ priv->xstats.rx_errors += rx_errors;
+
+ return count;
+ }
+@@ -5482,10 +5517,15 @@ static int stmmac_napi_poll_rx(struct napi_struct *napi, int budget)
+ struct stmmac_channel *ch =
+ container_of(napi, struct stmmac_channel, rx_napi);
+ struct stmmac_priv *priv = ch->priv_data;
++ struct stmmac_rx_queue *rx_q;
+ u32 chan = ch->index;
++ unsigned long flags;
+ int work_done;
+
+- priv->xstats.napi_poll++;
++ rx_q = &priv->dma_conf.rx_queue[chan];
++ flags = u64_stats_update_begin_irqsave(&rx_q->rxq_stats.syncp);
++ rx_q->rxq_stats.napi_poll++;
++ u64_stats_update_end_irqrestore(&rx_q->rxq_stats.syncp, flags);
+
+ work_done = stmmac_rx(priv, budget, chan);
+ if (work_done < budget && napi_complete_done(napi, work_done)) {
+@@ -5504,10 +5544,15 @@ static int stmmac_napi_poll_tx(struct napi_struct *napi, int budget)
+ struct stmmac_channel *ch =
+ container_of(napi, struct stmmac_channel, tx_napi);
+ struct stmmac_priv *priv = ch->priv_data;
++ struct stmmac_tx_queue *tx_q;
+ u32 chan = ch->index;
++ unsigned long flags;
+ int work_done;
+
+- priv->xstats.napi_poll++;
++ tx_q = &priv->dma_conf.tx_queue[chan];
++ flags = u64_stats_update_begin_irqsave(&tx_q->txq_stats.syncp);
++ tx_q->txq_stats.napi_poll++;
++ u64_stats_update_end_irqrestore(&tx_q->txq_stats.syncp, flags);
+
+ work_done = stmmac_tx_clean(priv, budget, chan);
+ work_done = min(work_done, budget);
+@@ -5529,9 +5574,20 @@ static int stmmac_napi_poll_rxtx(struct napi_struct *napi, int budget)
+ container_of(napi, struct stmmac_channel, rxtx_napi);
+ struct stmmac_priv *priv = ch->priv_data;
+ int rx_done, tx_done, rxtx_done;
++ struct stmmac_rx_queue *rx_q;
++ struct stmmac_tx_queue *tx_q;
+ u32 chan = ch->index;
++ unsigned long flags;
++
++ rx_q = &priv->dma_conf.rx_queue[chan];
++ flags = u64_stats_update_begin_irqsave(&rx_q->rxq_stats.syncp);
++ rx_q->rxq_stats.napi_poll++;
++ u64_stats_update_end_irqrestore(&rx_q->rxq_stats.syncp, flags);
+
+- priv->xstats.napi_poll++;
++ tx_q = &priv->dma_conf.tx_queue[chan];
++ flags = u64_stats_update_begin_irqsave(&tx_q->txq_stats.syncp);
++ tx_q->txq_stats.napi_poll++;
++ u64_stats_update_end_irqrestore(&tx_q->txq_stats.syncp, flags);
+
+ tx_done = stmmac_tx_clean(priv, budget, chan);
+ tx_done = min(tx_done, budget);
+@@ -6790,6 +6846,56 @@ int stmmac_xsk_wakeup(struct net_device *dev, u32 queue, u32 flags)
+ return 0;
+ }
+
++static void stmmac_get_stats64(struct net_device *dev, struct rtnl_link_stats64 *stats)
++{
++ struct stmmac_priv *priv = netdev_priv(dev);
++ u32 tx_cnt = priv->plat->tx_queues_to_use;
++ u32 rx_cnt = priv->plat->rx_queues_to_use;
++ unsigned int start;
++ int q;
++
++ for (q = 0; q < tx_cnt; q++) {
++ struct stmmac_txq_stats *txq_stats = &priv->dma_conf.tx_queue[q].txq_stats;
++ u64 tx_packets;
++ u64 tx_bytes;
++
++ do {
++ start = u64_stats_fetch_begin(&txq_stats->syncp);
++ tx_packets = txq_stats->tx_packets;
++ tx_bytes = txq_stats->tx_bytes;
++ } while (u64_stats_fetch_retry(&txq_stats->syncp, start));
++
++ stats->tx_packets += tx_packets;
++ stats->tx_bytes += tx_bytes;
++ }
++
++ for (q = 0; q < rx_cnt; q++) {
++ struct stmmac_rxq_stats *rxq_stats = &priv->dma_conf.rx_queue[q].rxq_stats;
++ u64 rx_packets;
++ u64 rx_bytes;
++
++ do {
++ start = u64_stats_fetch_begin(&rxq_stats->syncp);
++ rx_packets = rxq_stats->rx_packets;
++ rx_bytes = rxq_stats->rx_bytes;
++ } while (u64_stats_fetch_retry(&rxq_stats->syncp, start));
++
++ stats->rx_packets += rx_packets;
++ stats->rx_bytes += rx_bytes;
++ }
++
++ stats->rx_dropped = priv->xstats.rx_dropped;
++ stats->rx_errors = priv->xstats.rx_errors;
++ stats->tx_dropped = priv->xstats.tx_dropped;
++ stats->tx_errors = priv->xstats.tx_errors;
++ stats->tx_carrier_errors = priv->xstats.tx_losscarrier + priv->xstats.tx_carrier;
++ stats->collisions = priv->xstats.tx_collision + priv->xstats.rx_collision;
++ stats->rx_length_errors = priv->xstats.rx_length;
++ stats->rx_crc_errors = priv->xstats.rx_crc_errors;
++ stats->rx_over_errors = priv->xstats.rx_overflow_cntr;
++ stats->rx_missed_errors = priv->xstats.rx_missed_cntr;
++}
++
+ static const struct net_device_ops stmmac_netdev_ops = {
+ .ndo_open = stmmac_open,
+ .ndo_start_xmit = stmmac_xmit,
+@@ -6800,6 +6906,7 @@ static const struct net_device_ops stmmac_netdev_ops = {
+ .ndo_set_rx_mode = stmmac_set_rx_mode,
+ .ndo_tx_timeout = stmmac_tx_timeout,
+ .ndo_eth_ioctl = stmmac_ioctl,
++ .ndo_get_stats64 = stmmac_get_stats64,
+ .ndo_setup_tc = stmmac_setup_tc,
+ .ndo_select_queue = stmmac_select_queue,
+ #ifdef CONFIG_NET_POLL_CONTROLLER
+@@ -7162,6 +7269,11 @@ int stmmac_dvr_probe(struct device *device,
+ priv->device = device;
+ priv->dev = ndev;
+
++ for (i = 0; i < MTL_MAX_RX_QUEUES; i++)
++ u64_stats_init(&priv->dma_conf.rx_queue[i].rxq_stats.syncp);
++ for (i = 0; i < MTL_MAX_TX_QUEUES; i++)
++ u64_stats_init(&priv->dma_conf.tx_queue[i].txq_stats.syncp);
++
+ stmmac_set_ethtool_ops(ndev);
+ priv->pause = pause;
+ priv->plat = plat_dat;
+--
+2.40.1
+
--- /dev/null
+From 8678c1ca9368c023232df7a3ff1a32ef29e4f693 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 28 Jul 2023 17:48:13 -0700
+Subject: net: Use sockaddr_storage for getsockopt(SO_PEERNAME).
+
+From: Kuniyuki Iwashima <kuniyu@amazon.com>
+
+[ Upstream commit 8936bf53a091ad6a34b480c22002f1cb2422ab38 ]
+
+Commit df8fc4e934c1 ("kbuild: Enable -fstrict-flex-arrays=3") started
+applying strict rules to standard string functions.
+
+It does not work well with conventional socket code around each protocol-
+specific sockaddr_XXX struct, which is cast from sockaddr_storage and has
+a bigger size than fortified functions expect. See these commits:
+
+ commit 06d4c8a80836 ("af_unix: Fix fortify_panic() in unix_bind_bsd().")
+ commit ecb4534b6a1c ("af_unix: Terminate sun_path when bind()ing pathname socket.")
+ commit a0ade8404c3b ("af_packet: Fix warning of fortified memcpy() in packet_getname().")
+
+We must cast the protocol-specific address back to sockaddr_storage
+to call such functions.
+
+However, in the case of getsockaddr(SO_PEERNAME), the rationale is a bit
+unclear as the buffer is defined by char[128] which is the same size as
+sockaddr_storage.
+
+Let's use sockaddr_storage explicitly.
+
+Signed-off-by: Kuniyuki Iwashima <kuniyu@amazon.com>
+Reviewed-by: Eric Dumazet <edumazet@google.com>
+Reviewed-by: Willem de Bruijn <willemb@google.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/core/sock.c | 6 +++---
+ 1 file changed, 3 insertions(+), 3 deletions(-)
+
+diff --git a/net/core/sock.c b/net/core/sock.c
+index 29c6cb030818b..eef27812013a4 100644
+--- a/net/core/sock.c
++++ b/net/core/sock.c
+@@ -1824,14 +1824,14 @@ int sk_getsockopt(struct sock *sk, int level, int optname,
+
+ case SO_PEERNAME:
+ {
+- char address[128];
++ struct sockaddr_storage address;
+
+- lv = sock->ops->getname(sock, (struct sockaddr *)address, 2);
++ lv = sock->ops->getname(sock, (struct sockaddr *)&address, 2);
+ if (lv < 0)
+ return -ENOTCONN;
+ if (lv < len)
+ return -EINVAL;
+- if (copy_to_sockptr(optval, address, len))
++ if (copy_to_sockptr(optval, &address, len))
+ return -EFAULT;
+ goto lenout;
+ }
+--
+2.40.1
+
--- /dev/null
+From 733f36435ce5ad1638c2f39ae16a938c1fce993e Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 9 Aug 2023 15:45:03 +0800
+Subject: netfilter: ebtables: fix fortify warnings in size_entry_mwt()
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: GONG, Ruiqi <gongruiqi1@huawei.com>
+
+[ Upstream commit a7ed3465daa240bdf01a5420f64336fee879c09d ]
+
+When compiling with gcc 13 and CONFIG_FORTIFY_SOURCE=y, the following
+warning appears:
+
+In function ‘fortify_memcpy_chk’,
+ inlined from ‘size_entry_mwt’ at net/bridge/netfilter/ebtables.c:2118:2:
+./include/linux/fortify-string.h:592:25: error: call to ‘__read_overflow2_field’
+declared with attribute warning: detected read beyond size of field (2nd parameter);
+maybe use struct_group()? [-Werror=attribute-warning]
+ 592 | __read_overflow2_field(q_size_field, size);
+ | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+The compiler is complaining:
+
+memcpy(&offsets[1], &entry->watchers_offset,
+ sizeof(offsets) - sizeof(offsets[0]));
+
+where memcpy reads beyong &entry->watchers_offset to copy
+{watchers,target,next}_offset altogether into offsets[]. Silence the
+warning by wrapping these three up via struct_group().
+
+Signed-off-by: GONG, Ruiqi <gongruiqi1@huawei.com>
+Reviewed-by: Gustavo A. R. Silva <gustavoars@kernel.org>
+Reviewed-by: Kees Cook <keescook@chromium.org>
+Signed-off-by: Florian Westphal <fw@strlen.de>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ include/uapi/linux/netfilter_bridge/ebtables.h | 14 ++++++++------
+ net/bridge/netfilter/ebtables.c | 3 +--
+ 2 files changed, 9 insertions(+), 8 deletions(-)
+
+diff --git a/include/uapi/linux/netfilter_bridge/ebtables.h b/include/uapi/linux/netfilter_bridge/ebtables.h
+index a494cf43a7552..b0caad82b6937 100644
+--- a/include/uapi/linux/netfilter_bridge/ebtables.h
++++ b/include/uapi/linux/netfilter_bridge/ebtables.h
+@@ -182,12 +182,14 @@ struct ebt_entry {
+ unsigned char sourcemsk[ETH_ALEN];
+ unsigned char destmac[ETH_ALEN];
+ unsigned char destmsk[ETH_ALEN];
+- /* sizeof ebt_entry + matches */
+- unsigned int watchers_offset;
+- /* sizeof ebt_entry + matches + watchers */
+- unsigned int target_offset;
+- /* sizeof ebt_entry + matches + watchers + target */
+- unsigned int next_offset;
++ __struct_group(/* no tag */, offsets, /* no attrs */,
++ /* sizeof ebt_entry + matches */
++ unsigned int watchers_offset;
++ /* sizeof ebt_entry + matches + watchers */
++ unsigned int target_offset;
++ /* sizeof ebt_entry + matches + watchers + target */
++ unsigned int next_offset;
++ );
+ unsigned char elems[0] __attribute__ ((aligned (__alignof__(struct ebt_replace))));
+ };
+
+diff --git a/net/bridge/netfilter/ebtables.c b/net/bridge/netfilter/ebtables.c
+index 757ec46fc45a0..aa23479b20b2a 100644
+--- a/net/bridge/netfilter/ebtables.c
++++ b/net/bridge/netfilter/ebtables.c
+@@ -2115,8 +2115,7 @@ static int size_entry_mwt(const struct ebt_entry *entry, const unsigned char *ba
+ return ret;
+
+ offsets[0] = sizeof(struct ebt_entry); /* matches come first */
+- memcpy(&offsets[1], &entry->watchers_offset,
+- sizeof(offsets) - sizeof(offsets[0]));
++ memcpy(&offsets[1], &entry->offsets, sizeof(entry->offsets));
+
+ if (state->buf_kern_start) {
+ buf_start = state->buf_kern_start + state->buf_kern_offset;
+--
+2.40.1
+
--- /dev/null
+From 0b5fa4a10e349e3cd05d0db3c9cd18de5ec49011 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 11 Aug 2023 07:22:26 +0000
+Subject: netlink: convert nlk->flags to atomic flags
+
+From: Eric Dumazet <edumazet@google.com>
+
+[ Upstream commit 8fe08d70a2b61b35a0a1235c78cf321e7528351f ]
+
+sk_diag_put_flags(), netlink_setsockopt(), netlink_getsockopt()
+and others use nlk->flags without correct locking.
+
+Use set_bit(), clear_bit(), test_bit(), assign_bit() to remove
+data-races.
+
+Reported-by: syzbot <syzkaller@googlegroups.com>
+Signed-off-by: Eric Dumazet <edumazet@google.com>
+Reviewed-by: Simon Horman <horms@kernel.org>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/netlink/af_netlink.c | 90 ++++++++++++++--------------------------
+ net/netlink/af_netlink.h | 22 ++++++----
+ net/netlink/diag.c | 10 ++---
+ 3 files changed, 48 insertions(+), 74 deletions(-)
+
+diff --git a/net/netlink/af_netlink.c b/net/netlink/af_netlink.c
+index 3836318737483..20082171f24a3 100644
+--- a/net/netlink/af_netlink.c
++++ b/net/netlink/af_netlink.c
+@@ -84,7 +84,7 @@ struct listeners {
+
+ static inline int netlink_is_kernel(struct sock *sk)
+ {
+- return nlk_sk(sk)->flags & NETLINK_F_KERNEL_SOCKET;
++ return nlk_test_bit(KERNEL_SOCKET, sk);
+ }
+
+ struct netlink_table *nl_table __read_mostly;
+@@ -349,9 +349,7 @@ static void netlink_deliver_tap_kernel(struct sock *dst, struct sock *src,
+
+ static void netlink_overrun(struct sock *sk)
+ {
+- struct netlink_sock *nlk = nlk_sk(sk);
+-
+- if (!(nlk->flags & NETLINK_F_RECV_NO_ENOBUFS)) {
++ if (!nlk_test_bit(RECV_NO_ENOBUFS, sk)) {
+ if (!test_and_set_bit(NETLINK_S_CONGESTED,
+ &nlk_sk(sk)->state)) {
+ sk->sk_err = ENOBUFS;
+@@ -1402,9 +1400,7 @@ EXPORT_SYMBOL_GPL(netlink_has_listeners);
+
+ bool netlink_strict_get_check(struct sk_buff *skb)
+ {
+- const struct netlink_sock *nlk = nlk_sk(NETLINK_CB(skb).sk);
+-
+- return nlk->flags & NETLINK_F_STRICT_CHK;
++ return nlk_test_bit(STRICT_CHK, NETLINK_CB(skb).sk);
+ }
+ EXPORT_SYMBOL_GPL(netlink_strict_get_check);
+
+@@ -1448,7 +1444,7 @@ static void do_one_broadcast(struct sock *sk,
+ return;
+
+ if (!net_eq(sock_net(sk), p->net)) {
+- if (!(nlk->flags & NETLINK_F_LISTEN_ALL_NSID))
++ if (!nlk_test_bit(LISTEN_ALL_NSID, sk))
+ return;
+
+ if (!peernet_has_id(sock_net(sk), p->net))
+@@ -1481,7 +1477,7 @@ static void do_one_broadcast(struct sock *sk,
+ netlink_overrun(sk);
+ /* Clone failed. Notify ALL listeners. */
+ p->failure = 1;
+- if (nlk->flags & NETLINK_F_BROADCAST_SEND_ERROR)
++ if (nlk_test_bit(BROADCAST_SEND_ERROR, sk))
+ p->delivery_failure = 1;
+ goto out;
+ }
+@@ -1496,7 +1492,7 @@ static void do_one_broadcast(struct sock *sk,
+ val = netlink_broadcast_deliver(sk, p->skb2);
+ if (val < 0) {
+ netlink_overrun(sk);
+- if (nlk->flags & NETLINK_F_BROADCAST_SEND_ERROR)
++ if (nlk_test_bit(BROADCAST_SEND_ERROR, sk))
+ p->delivery_failure = 1;
+ } else {
+ p->congested |= val;
+@@ -1576,7 +1572,7 @@ static int do_one_set_err(struct sock *sk, struct netlink_set_err_data *p)
+ !test_bit(p->group - 1, nlk->groups))
+ goto out;
+
+- if (p->code == ENOBUFS && nlk->flags & NETLINK_F_RECV_NO_ENOBUFS) {
++ if (p->code == ENOBUFS && nlk_test_bit(RECV_NO_ENOBUFS, sk)) {
+ ret = 1;
+ goto out;
+ }
+@@ -1643,7 +1639,7 @@ static int netlink_setsockopt(struct socket *sock, int level, int optname,
+ struct sock *sk = sock->sk;
+ struct netlink_sock *nlk = nlk_sk(sk);
+ unsigned int val = 0;
+- int err;
++ int nr = -1;
+
+ if (level != SOL_NETLINK)
+ return -ENOPROTOOPT;
+@@ -1654,14 +1650,12 @@ static int netlink_setsockopt(struct socket *sock, int level, int optname,
+
+ switch (optname) {
+ case NETLINK_PKTINFO:
+- if (val)
+- nlk->flags |= NETLINK_F_RECV_PKTINFO;
+- else
+- nlk->flags &= ~NETLINK_F_RECV_PKTINFO;
+- err = 0;
++ nr = NETLINK_F_RECV_PKTINFO;
+ break;
+ case NETLINK_ADD_MEMBERSHIP:
+ case NETLINK_DROP_MEMBERSHIP: {
++ int err;
++
+ if (!netlink_allowed(sock, NL_CFG_F_NONROOT_RECV))
+ return -EPERM;
+ err = netlink_realloc_groups(sk);
+@@ -1681,61 +1675,38 @@ static int netlink_setsockopt(struct socket *sock, int level, int optname,
+ if (optname == NETLINK_DROP_MEMBERSHIP && nlk->netlink_unbind)
+ nlk->netlink_unbind(sock_net(sk), val);
+
+- err = 0;
+ break;
+ }
+ case NETLINK_BROADCAST_ERROR:
+- if (val)
+- nlk->flags |= NETLINK_F_BROADCAST_SEND_ERROR;
+- else
+- nlk->flags &= ~NETLINK_F_BROADCAST_SEND_ERROR;
+- err = 0;
++ nr = NETLINK_F_BROADCAST_SEND_ERROR;
+ break;
+ case NETLINK_NO_ENOBUFS:
++ assign_bit(NETLINK_F_RECV_NO_ENOBUFS, &nlk->flags, val);
+ if (val) {
+- nlk->flags |= NETLINK_F_RECV_NO_ENOBUFS;
+ clear_bit(NETLINK_S_CONGESTED, &nlk->state);
+ wake_up_interruptible(&nlk->wait);
+- } else {
+- nlk->flags &= ~NETLINK_F_RECV_NO_ENOBUFS;
+ }
+- err = 0;
+ break;
+ case NETLINK_LISTEN_ALL_NSID:
+ if (!ns_capable(sock_net(sk)->user_ns, CAP_NET_BROADCAST))
+ return -EPERM;
+-
+- if (val)
+- nlk->flags |= NETLINK_F_LISTEN_ALL_NSID;
+- else
+- nlk->flags &= ~NETLINK_F_LISTEN_ALL_NSID;
+- err = 0;
++ nr = NETLINK_F_LISTEN_ALL_NSID;
+ break;
+ case NETLINK_CAP_ACK:
+- if (val)
+- nlk->flags |= NETLINK_F_CAP_ACK;
+- else
+- nlk->flags &= ~NETLINK_F_CAP_ACK;
+- err = 0;
++ nr = NETLINK_F_CAP_ACK;
+ break;
+ case NETLINK_EXT_ACK:
+- if (val)
+- nlk->flags |= NETLINK_F_EXT_ACK;
+- else
+- nlk->flags &= ~NETLINK_F_EXT_ACK;
+- err = 0;
++ nr = NETLINK_F_EXT_ACK;
+ break;
+ case NETLINK_GET_STRICT_CHK:
+- if (val)
+- nlk->flags |= NETLINK_F_STRICT_CHK;
+- else
+- nlk->flags &= ~NETLINK_F_STRICT_CHK;
+- err = 0;
++ nr = NETLINK_F_STRICT_CHK;
+ break;
+ default:
+- err = -ENOPROTOOPT;
++ return -ENOPROTOOPT;
+ }
+- return err;
++ if (nr >= 0)
++ assign_bit(nr, &nlk->flags, val);
++ return 0;
+ }
+
+ static int netlink_getsockopt(struct socket *sock, int level, int optname,
+@@ -1802,7 +1773,7 @@ static int netlink_getsockopt(struct socket *sock, int level, int optname,
+ return -EINVAL;
+
+ len = sizeof(int);
+- val = nlk->flags & flag ? 1 : 0;
++ val = test_bit(flag, &nlk->flags);
+
+ if (put_user(len, optlen) ||
+ copy_to_user(optval, &val, len))
+@@ -1979,9 +1950,9 @@ static int netlink_recvmsg(struct socket *sock, struct msghdr *msg, size_t len,
+ msg->msg_namelen = sizeof(*addr);
+ }
+
+- if (nlk->flags & NETLINK_F_RECV_PKTINFO)
++ if (nlk_test_bit(RECV_PKTINFO, sk))
+ netlink_cmsg_recv_pktinfo(msg, skb);
+- if (nlk->flags & NETLINK_F_LISTEN_ALL_NSID)
++ if (nlk_test_bit(LISTEN_ALL_NSID, sk))
+ netlink_cmsg_listen_all_nsid(sk, msg, skb);
+
+ memset(&scm, 0, sizeof(scm));
+@@ -2058,7 +2029,7 @@ __netlink_kernel_create(struct net *net, int unit, struct module *module,
+ goto out_sock_release;
+
+ nlk = nlk_sk(sk);
+- nlk->flags |= NETLINK_F_KERNEL_SOCKET;
++ set_bit(NETLINK_F_KERNEL_SOCKET, &nlk->flags);
+
+ netlink_table_grab();
+ if (!nl_table[unit].registered) {
+@@ -2192,7 +2163,7 @@ static int netlink_dump_done(struct netlink_sock *nlk, struct sk_buff *skb,
+ nl_dump_check_consistent(cb, nlh);
+ memcpy(nlmsg_data(nlh), &nlk->dump_done_errno, sizeof(nlk->dump_done_errno));
+
+- if (extack->_msg && nlk->flags & NETLINK_F_EXT_ACK) {
++ if (extack->_msg && test_bit(NETLINK_F_EXT_ACK, &nlk->flags)) {
+ nlh->nlmsg_flags |= NLM_F_ACK_TLVS;
+ if (!nla_put_string(skb, NLMSGERR_ATTR_MSG, extack->_msg))
+ nlmsg_end(skb, nlh);
+@@ -2321,8 +2292,8 @@ int __netlink_dump_start(struct sock *ssk, struct sk_buff *skb,
+ const struct nlmsghdr *nlh,
+ struct netlink_dump_control *control)
+ {
+- struct netlink_sock *nlk, *nlk2;
+ struct netlink_callback *cb;
++ struct netlink_sock *nlk;
+ struct sock *sk;
+ int ret;
+
+@@ -2357,8 +2328,7 @@ int __netlink_dump_start(struct sock *ssk, struct sk_buff *skb,
+ cb->min_dump_alloc = control->min_dump_alloc;
+ cb->skb = skb;
+
+- nlk2 = nlk_sk(NETLINK_CB(skb).sk);
+- cb->strict_check = !!(nlk2->flags & NETLINK_F_STRICT_CHK);
++ cb->strict_check = nlk_test_bit(STRICT_CHK, NETLINK_CB(skb).sk);
+
+ if (control->start) {
+ cb->extack = control->extack;
+@@ -2402,7 +2372,7 @@ netlink_ack_tlv_len(struct netlink_sock *nlk, int err,
+ {
+ size_t tlvlen;
+
+- if (!extack || !(nlk->flags & NETLINK_F_EXT_ACK))
++ if (!extack || !test_bit(NETLINK_F_EXT_ACK, &nlk->flags))
+ return 0;
+
+ tlvlen = 0;
+@@ -2474,7 +2444,7 @@ void netlink_ack(struct sk_buff *in_skb, struct nlmsghdr *nlh, int err,
+ * requests to cap the error message, and get extra error data if
+ * requested.
+ */
+- if (err && !(nlk->flags & NETLINK_F_CAP_ACK))
++ if (err && !test_bit(NETLINK_F_CAP_ACK, &nlk->flags))
+ payload += nlmsg_len(nlh);
+ else
+ flags |= NLM_F_CAPPED;
+diff --git a/net/netlink/af_netlink.h b/net/netlink/af_netlink.h
+index 90a3198a9b7f7..3dbd38aef50a4 100644
+--- a/net/netlink/af_netlink.h
++++ b/net/netlink/af_netlink.h
+@@ -8,14 +8,16 @@
+ #include <net/sock.h>
+
+ /* flags */
+-#define NETLINK_F_KERNEL_SOCKET 0x1
+-#define NETLINK_F_RECV_PKTINFO 0x2
+-#define NETLINK_F_BROADCAST_SEND_ERROR 0x4
+-#define NETLINK_F_RECV_NO_ENOBUFS 0x8
+-#define NETLINK_F_LISTEN_ALL_NSID 0x10
+-#define NETLINK_F_CAP_ACK 0x20
+-#define NETLINK_F_EXT_ACK 0x40
+-#define NETLINK_F_STRICT_CHK 0x80
++enum {
++ NETLINK_F_KERNEL_SOCKET,
++ NETLINK_F_RECV_PKTINFO,
++ NETLINK_F_BROADCAST_SEND_ERROR,
++ NETLINK_F_RECV_NO_ENOBUFS,
++ NETLINK_F_LISTEN_ALL_NSID,
++ NETLINK_F_CAP_ACK,
++ NETLINK_F_EXT_ACK,
++ NETLINK_F_STRICT_CHK,
++};
+
+ #define NLGRPSZ(x) (ALIGN(x, sizeof(unsigned long) * 8) / 8)
+ #define NLGRPLONGS(x) (NLGRPSZ(x)/sizeof(unsigned long))
+@@ -23,10 +25,10 @@
+ struct netlink_sock {
+ /* struct sock has to be the first member of netlink_sock */
+ struct sock sk;
++ unsigned long flags;
+ u32 portid;
+ u32 dst_portid;
+ u32 dst_group;
+- u32 flags;
+ u32 subscriptions;
+ u32 ngroups;
+ unsigned long *groups;
+@@ -54,6 +56,8 @@ static inline struct netlink_sock *nlk_sk(struct sock *sk)
+ return container_of(sk, struct netlink_sock, sk);
+ }
+
++#define nlk_test_bit(nr, sk) test_bit(NETLINK_F_##nr, &nlk_sk(sk)->flags)
++
+ struct netlink_table {
+ struct rhashtable hash;
+ struct hlist_head mc_list;
+diff --git a/net/netlink/diag.c b/net/netlink/diag.c
+index e4f21b1067bcc..9c4f231be2757 100644
+--- a/net/netlink/diag.c
++++ b/net/netlink/diag.c
+@@ -27,15 +27,15 @@ static int sk_diag_put_flags(struct sock *sk, struct sk_buff *skb)
+
+ if (nlk->cb_running)
+ flags |= NDIAG_FLAG_CB_RUNNING;
+- if (nlk->flags & NETLINK_F_RECV_PKTINFO)
++ if (nlk_test_bit(RECV_PKTINFO, sk))
+ flags |= NDIAG_FLAG_PKTINFO;
+- if (nlk->flags & NETLINK_F_BROADCAST_SEND_ERROR)
++ if (nlk_test_bit(BROADCAST_SEND_ERROR, sk))
+ flags |= NDIAG_FLAG_BROADCAST_ERROR;
+- if (nlk->flags & NETLINK_F_RECV_NO_ENOBUFS)
++ if (nlk_test_bit(RECV_NO_ENOBUFS, sk))
+ flags |= NDIAG_FLAG_NO_ENOBUFS;
+- if (nlk->flags & NETLINK_F_LISTEN_ALL_NSID)
++ if (nlk_test_bit(LISTEN_ALL_NSID, sk))
+ flags |= NDIAG_FLAG_LISTEN_ALL_NSID;
+- if (nlk->flags & NETLINK_F_CAP_ACK)
++ if (nlk_test_bit(CAP_ACK, sk))
+ flags |= NDIAG_FLAG_CAP_ACK;
+
+ return nla_put_u32(skb, NETLINK_DIAG_FLAGS, flags);
+--
+2.40.1
+
--- /dev/null
+From f04f081f064034112bd7c8b7618ec1c5eedd97f8 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 9 Aug 2023 15:56:45 +0530
+Subject: nvmet-tcp: pass iov_len instead of sg->length to bvec_set_page()
+
+From: Varun Prakash <varun@chelsio.com>
+
+[ Upstream commit 1f0bbf28940cf5edad90ab57b62aa8197bf5e836 ]
+
+iov_len is the valid data length, so pass iov_len instead of sg->length to
+bvec_set_page().
+
+Fixes: 5bfaba275ae6 ("nvmet-tcp: don't map pages which can't come from HIGHMEM")
+Signed-off-by: Rakshana Sridhar <rakshanas@chelsio.com>
+Signed-off-by: Varun Prakash <varun@chelsio.com>
+Reviewed-by: Sagi Grimberg <sagi@grimberg.me>
+Reviewed-by: Christoph Hellwig <hch@lst.de>
+Signed-off-by: Keith Busch <kbusch@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/nvme/target/tcp.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/drivers/nvme/target/tcp.c b/drivers/nvme/target/tcp.c
+index 868aa4de2e4c4..cd92d7ddf5ed1 100644
+--- a/drivers/nvme/target/tcp.c
++++ b/drivers/nvme/target/tcp.c
+@@ -348,7 +348,7 @@ static void nvmet_tcp_build_pdu_iovec(struct nvmet_tcp_cmd *cmd)
+ while (length) {
+ u32 iov_len = min_t(u32, length, sg->length - sg_offset);
+
+- bvec_set_page(iov, sg_page(sg), sg->length,
++ bvec_set_page(iov, sg_page(sg), iov_len,
+ sg->offset + sg_offset);
+
+ length -= iov_len;
+--
+2.40.1
+
--- /dev/null
+From 35d7124bab0d893fe5a0e8b376a6295210db397c Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 15 Sep 2023 09:55:39 +0200
+Subject: panic: Reenable preemption in WARN slowpath
+
+From: Lukas Wunner <lukas@wunner.de>
+
+[ Upstream commit cccd32816506cbac3a4c65d9dff51b3125ef1a03 ]
+
+Commit:
+
+ 5a5d7e9badd2 ("cpuidle: lib/bug: Disable rcu_is_watching() during WARN/BUG")
+
+amended warn_slowpath_fmt() to disable preemption until the WARN splat
+has been emitted.
+
+However the commit neglected to reenable preemption in the !fmt codepath,
+i.e. when a WARN splat is emitted without additional format string.
+
+One consequence is that users may see more splats than intended. E.g. a
+WARN splat emitted in a work item results in at least two extra splats:
+
+ BUG: workqueue leaked lock or atomic
+ (emitted by process_one_work())
+
+ BUG: scheduling while atomic
+ (emitted by worker_thread() -> schedule())
+
+Ironically the point of the commit was to *avoid* extra splats. ;)
+
+Fix it.
+
+Fixes: 5a5d7e9badd2 ("cpuidle: lib/bug: Disable rcu_is_watching() during WARN/BUG")
+Signed-off-by: Lukas Wunner <lukas@wunner.de>
+Signed-off-by: Ingo Molnar <mingo@kernel.org>
+Cc: Linus Torvalds <torvalds@linux-foundation.org>
+Cc: Thomas Gleixner <tglx@linutronix.de>
+Cc: Paul E. McKenney <paulmck@kernel.org>
+Link: https://lore.kernel.org/r/3ec48fde01e4ee6505f77908ba351bad200ae3d1.1694763684.git.lukas@wunner.de
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ kernel/panic.c | 1 +
+ 1 file changed, 1 insertion(+)
+
+diff --git a/kernel/panic.c b/kernel/panic.c
+index 10effe40a3fa6..ea1c5fcb2d191 100644
+--- a/kernel/panic.c
++++ b/kernel/panic.c
+@@ -697,6 +697,7 @@ void warn_slowpath_fmt(const char *file, int line, unsigned taint,
+ if (!fmt) {
+ __warn(file, line, __builtin_return_address(0), taint,
+ NULL, NULL);
++ warn_rcu_exit(rcu);
+ return;
+ }
+
+--
+2.40.1
+
--- /dev/null
+From 2ac0b1629babc6906ee0563344971d9bbf717ec4 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 31 Jul 2023 12:55:01 +0100
+Subject: PCI: dwc: Provide deinit callback for i.MX
+
+From: Mark Brown <broonie@kernel.org>
+
+[ Upstream commit fc8b24c28bec19fc0621d108b9ee81ddfdedb25a ]
+
+The i.MX integration for the DesignWare PCI controller has a _host_exit()
+operation which undoes everything that the _host_init() operation does but
+does not wire this up as the host_deinit callback for the core, or call it
+in any path other than suspend. This means that if we ever unwind the
+initial probe of the device, for example because it fails, the regulator
+core complains that the regulators for the device were left enabled:
+
+imx6q-pcie 33800000.pcie: iATU: unroll T, 4 ob, 4 ib, align 64K, limit 16G
+imx6q-pcie 33800000.pcie: Phy link never came up
+imx6q-pcie 33800000.pcie: Phy link never came up
+imx6q-pcie: probe of 33800000.pcie failed with error -110
+------------[ cut here ]------------
+WARNING: CPU: 2 PID: 46 at drivers/regulator/core.c:2396 _regulator_put+0x110/0x128
+
+Wire up the callback so that the core can clean up after itself.
+
+Link: https://lore.kernel.org/r/20230731-pci-imx-regulator-cleanup-v2-1-fc8fa5c9893d@kernel.org
+Tested-by: Fabio Estevam <festevam@gmail.com>
+Signed-off-by: Mark Brown <broonie@kernel.org>
+Signed-off-by: Lorenzo Pieralisi <lpieralisi@kernel.org>
+Reviewed-by: Richard Zhu <hongxing.zhu@nxp.com>
+Acked-by: Manivannan Sadhasivam <manivannan.sadhasivam@linaro.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/pci/controller/dwc/pci-imx6.c | 1 +
+ 1 file changed, 1 insertion(+)
+
+diff --git a/drivers/pci/controller/dwc/pci-imx6.c b/drivers/pci/controller/dwc/pci-imx6.c
+index 27aaa2a6bf391..a18c20085e940 100644
+--- a/drivers/pci/controller/dwc/pci-imx6.c
++++ b/drivers/pci/controller/dwc/pci-imx6.c
+@@ -1040,6 +1040,7 @@ static void imx6_pcie_host_exit(struct dw_pcie_rp *pp)
+
+ static const struct dw_pcie_host_ops imx6_pcie_host_ops = {
+ .host_init = imx6_pcie_host_init,
++ .host_deinit = imx6_pcie_host_exit,
+ };
+
+ static const struct dw_pcie_ops dw_pcie_ops = {
+--
+2.40.1
+
--- /dev/null
+From 9b4e8bef06c9c1ca9f7c2ace5be3a84ffdb7c164 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 7 Aug 2023 05:56:21 +0000
+Subject: PCI: fu740: Set the number of MSI vectors
+
+From: Yong-Xuan Wang <yongxuan.wang@sifive.com>
+
+[ Upstream commit 551a60e1225e71fff8efd9390204c505b0870e0f ]
+
+The iMSI-RX module of the DW PCIe controller provides multiple sets of
+MSI_CTRL_INT_i_* registers, and each set is capable of handling 32 MSI
+interrupts. However, the fu740 PCIe controller driver only enabled one set
+of MSI_CTRL_INT_i_* registers, as the total number of supported interrupts
+was not specified.
+
+Set the supported number of MSI vectors to enable all the MSI_CTRL_INT_i_*
+registers on the fu740 PCIe core, allowing the system to fully utilize the
+available MSI interrupts.
+
+Link: https://lore.kernel.org/r/20230807055621.2431-1-yongxuan.wang@sifive.com
+Signed-off-by: Yong-Xuan Wang <yongxuan.wang@sifive.com>
+Signed-off-by: Lorenzo Pieralisi <lpieralisi@kernel.org>
+Reviewed-by: Serge Semin <fancer.lancer@gmail.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/pci/controller/dwc/pcie-fu740.c | 1 +
+ 1 file changed, 1 insertion(+)
+
+diff --git a/drivers/pci/controller/dwc/pcie-fu740.c b/drivers/pci/controller/dwc/pcie-fu740.c
+index 0c90583c078bf..1e9b44b8bba48 100644
+--- a/drivers/pci/controller/dwc/pcie-fu740.c
++++ b/drivers/pci/controller/dwc/pcie-fu740.c
+@@ -299,6 +299,7 @@ static int fu740_pcie_probe(struct platform_device *pdev)
+ pci->dev = dev;
+ pci->ops = &dw_pcie_ops;
+ pci->pp.ops = &fu740_pcie_host_ops;
++ pci->pp.num_vectors = MAX_MSI_IRQS;
+
+ /* SiFive specific region: mgmt */
+ afp->mgmt_base = devm_platform_ioremap_resource_byname(pdev, "mgmt");
+--
+2.40.1
+
--- /dev/null
+From 337cbbca1309cf319efcb19aa03af7589e2b0506 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 10 Aug 2023 17:50:29 -0400
+Subject: PCI: vmd: Disable bridge window for domain reset
+
+From: Nirmal Patel <nirmal.patel@linux.intel.com>
+
+[ Upstream commit f73eedc90bf73d48e8368e6b0b4ad76a7fffaef7 ]
+
+During domain reset process vmd_domain_reset() clears PCI
+configuration space of VMD root ports. But certain platform
+has observed following errors and failed to boot.
+ ...
+ DMAR: VT-d detected Invalidation Queue Error: Reason f
+ DMAR: VT-d detected Invalidation Time-out Error: SID ffff
+ DMAR: VT-d detected Invalidation Completion Error: SID ffff
+ DMAR: QI HEAD: UNKNOWN qw0 = 0x0, qw1 = 0x0
+ DMAR: QI PRIOR: UNKNOWN qw0 = 0x0, qw1 = 0x0
+ DMAR: Invalidation Time-out Error (ITE) cleared
+
+The root cause is that memset_io() clears prefetchable memory base/limit
+registers and prefetchable base/limit 32 bits registers sequentially.
+This seems to be enabling prefetchable memory if the device disabled
+prefetchable memory originally.
+
+Here is an example (before memset_io()):
+
+ PCI configuration space for 10000:00:00.0:
+ 86 80 30 20 06 00 10 00 04 00 04 06 00 00 01 00
+ 00 00 00 00 00 00 00 00 00 01 01 00 00 00 00 20
+ 00 00 00 00 01 00 01 00 ff ff ff ff 75 05 00 00
+ ...
+
+So, prefetchable memory is ffffffff00000000-575000fffff, which is
+disabled. When memset_io() clears prefetchable base 32 bits register,
+the prefetchable memory becomes 0000000000000000-575000fffff, which is
+enabled and incorrect.
+
+Here is the quote from section 7.5.1.3.9 of PCI Express Base 6.0 spec:
+
+ The Prefetchable Memory Limit register must be programmed to a smaller
+ value than the Prefetchable Memory Base register if there is no
+ prefetchable memory on the secondary side of the bridge.
+
+This is believed to be the reason for the failure and in addition the
+sequence of operation in vmd_domain_reset() is not following the PCIe
+specs.
+
+Disable the bridge window by executing a sequence of operations
+borrowed from pci_disable_bridge_window() and pci_setup_bridge_io(),
+that comply with the PCI specifications.
+
+Link: https://lore.kernel.org/r/20230810215029.1177379-1-nirmal.patel@linux.intel.com
+Signed-off-by: Nirmal Patel <nirmal.patel@linux.intel.com>
+Signed-off-by: Lorenzo Pieralisi <lpieralisi@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/pci/controller/vmd.c | 19 +++++++++++++++++--
+ 1 file changed, 17 insertions(+), 2 deletions(-)
+
+diff --git a/drivers/pci/controller/vmd.c b/drivers/pci/controller/vmd.c
+index e718a816d4814..ad56df98b8e63 100644
+--- a/drivers/pci/controller/vmd.c
++++ b/drivers/pci/controller/vmd.c
+@@ -541,8 +541,23 @@ static void vmd_domain_reset(struct vmd_dev *vmd)
+ PCI_CLASS_BRIDGE_PCI))
+ continue;
+
+- memset_io(base + PCI_IO_BASE, 0,
+- PCI_ROM_ADDRESS1 - PCI_IO_BASE);
++ /*
++ * Temporarily disable the I/O range before updating
++ * PCI_IO_BASE.
++ */
++ writel(0x0000ffff, base + PCI_IO_BASE_UPPER16);
++ /* Update lower 16 bits of I/O base/limit */
++ writew(0x00f0, base + PCI_IO_BASE);
++ /* Update upper 16 bits of I/O base/limit */
++ writel(0, base + PCI_IO_BASE_UPPER16);
++
++ /* MMIO Base/Limit */
++ writel(0x0000fff0, base + PCI_MEMORY_BASE);
++
++ /* Prefetchable MMIO Base/Limit */
++ writel(0, base + PCI_PREF_LIMIT_UPPER32);
++ writel(0x0000fff0, base + PCI_PREF_MEMORY_BASE);
++ writel(0xffffffff, base + PCI_PREF_BASE_UPPER32);
+ }
+ }
+ }
+--
+2.40.1
+
--- /dev/null
+From 72baa53549bd042f2209d838f5b6024969b07c07 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 11 Aug 2023 09:54:37 +0800
+Subject: perf/imx_ddr: speed up overflow frequency of cycle
+
+From: Xu Yang <xu.yang_2@nxp.com>
+
+[ Upstream commit e89ecd8368860bf05437eabd07d292c316221cfc ]
+
+For i.MX8MP, we cannot ensure that cycle counter overflow occurs at least
+4 times as often as other events. Due to byte counters will count for any
+event configured, it will overflow more often. And if byte counters
+overflow that related counters would stop since they share the
+COUNTER_CNTL. We can speed up cycle counter overflow frequency by setting
+counter parameter (CP) field of cycle counter. In this way, we can avoid
+stop counting byte counters when interrupt didn't come and the byte
+counters can be fetched or updated from each cycle counter overflow
+interrupt.
+
+Because we initialize CP filed to shorten counter0 overflow time, the cycle
+counter will start couting from a fixed/base value each time. We need to
+remove the base from the result too. Therefore, we could get precise result
+from cycle counter.
+
+Signed-off-by: Xu Yang <xu.yang_2@nxp.com>
+Reviewed-by: Frank Li <Frank.Li@nxp.com>
+Link: https://lore.kernel.org/r/20230811015438.1999307-1-xu.yang_2@nxp.com
+Signed-off-by: Will Deacon <will@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/perf/fsl_imx8_ddr_perf.c | 21 +++++++++++++++++++++
+ 1 file changed, 21 insertions(+)
+
+diff --git a/drivers/perf/fsl_imx8_ddr_perf.c b/drivers/perf/fsl_imx8_ddr_perf.c
+index c684aab407f86..e78b30521be25 100644
+--- a/drivers/perf/fsl_imx8_ddr_perf.c
++++ b/drivers/perf/fsl_imx8_ddr_perf.c
+@@ -28,6 +28,8 @@
+ #define CNTL_CLEAR_MASK 0xFFFFFFFD
+ #define CNTL_OVER_MASK 0xFFFFFFFE
+
++#define CNTL_CP_SHIFT 16
++#define CNTL_CP_MASK (0xFF << CNTL_CP_SHIFT)
+ #define CNTL_CSV_SHIFT 24
+ #define CNTL_CSV_MASK (0xFFU << CNTL_CSV_SHIFT)
+
+@@ -35,6 +37,8 @@
+ #define EVENT_CYCLES_COUNTER 0
+ #define NUM_COUNTERS 4
+
++/* For removing bias if cycle counter CNTL.CP is set to 0xf0 */
++#define CYCLES_COUNTER_MASK 0x0FFFFFFF
+ #define AXI_MASKING_REVERT 0xffff0000 /* AXI_MASKING(MSB 16bits) + AXI_ID(LSB 16bits) */
+
+ #define to_ddr_pmu(p) container_of(p, struct ddr_pmu, pmu)
+@@ -428,6 +432,17 @@ static void ddr_perf_counter_enable(struct ddr_pmu *pmu, int config,
+ writel(0, pmu->base + reg);
+ val = CNTL_EN | CNTL_CLEAR;
+ val |= FIELD_PREP(CNTL_CSV_MASK, config);
++
++ /*
++ * On i.MX8MP we need to bias the cycle counter to overflow more often.
++ * We do this by initializing bits [23:16] of the counter value via the
++ * COUNTER_CTRL Counter Parameter (CP) field.
++ */
++ if (pmu->devtype_data->quirks & DDR_CAP_AXI_ID_FILTER_ENHANCED) {
++ if (counter == EVENT_CYCLES_COUNTER)
++ val |= FIELD_PREP(CNTL_CP_MASK, 0xf0);
++ }
++
+ writel(val, pmu->base + reg);
+ } else {
+ /* Disable counter */
+@@ -467,6 +482,12 @@ static void ddr_perf_event_update(struct perf_event *event)
+ int ret;
+
+ new_raw_count = ddr_perf_read_counter(pmu, counter);
++ /* Remove the bias applied in ddr_perf_counter_enable(). */
++ if (pmu->devtype_data->quirks & DDR_CAP_AXI_ID_FILTER_ENHANCED) {
++ if (counter == EVENT_CYCLES_COUNTER)
++ new_raw_count &= CYCLES_COUNTER_MASK;
++ }
++
+ local64_add(new_raw_count, &event->count);
+
+ /*
+--
+2.40.1
+
--- /dev/null
+From 781b6d82d38d8aa676d5ddf4e27cc0587d05c220 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 14 Aug 2023 20:40:12 +0800
+Subject: perf/smmuv3: Enable HiSilicon Erratum 162001900 quirk for HIP08/09
+
+From: Yicong Yang <yangyicong@hisilicon.com>
+
+[ Upstream commit 0242737dc4eb9f6e9a5ea594b3f93efa0b12f28d ]
+
+Some HiSilicon SMMU PMCG suffers the erratum 162001900 that the PMU
+disable control sometimes fail to disable the counters. This will lead
+to error or inaccurate data since before we enable the counters the
+counter's still counting for the event used in last perf session.
+
+This patch tries to fix this by hardening the global disable process.
+Before disable the PMU, writing an invalid event type (0xffff) to
+focibly stop the counters. Correspondingly restore each events on
+pmu::pmu_enable().
+
+Signed-off-by: Yicong Yang <yangyicong@hisilicon.com>
+Link: https://lore.kernel.org/r/20230814124012.58013-1-yangyicong@huawei.com
+Signed-off-by: Will Deacon <will@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ Documentation/arch/arm64/silicon-errata.rst | 3 ++
+ drivers/acpi/arm64/iort.c | 5 ++-
+ drivers/perf/arm_smmuv3_pmu.c | 46 ++++++++++++++++++++-
+ include/linux/acpi_iort.h | 1 +
+ 4 files changed, 53 insertions(+), 2 deletions(-)
+
+diff --git a/Documentation/arch/arm64/silicon-errata.rst b/Documentation/arch/arm64/silicon-errata.rst
+index bedd3a1d7b423..0ac452333eb4f 100644
+--- a/Documentation/arch/arm64/silicon-errata.rst
++++ b/Documentation/arch/arm64/silicon-errata.rst
+@@ -198,6 +198,9 @@ stable kernels.
+ +----------------+-----------------+-----------------+-----------------------------+
+ | Hisilicon | Hip08 SMMU PMCG | #162001800 | N/A |
+ +----------------+-----------------+-----------------+-----------------------------+
++| Hisilicon | Hip08 SMMU PMCG | #162001900 | N/A |
++| | Hip09 SMMU PMCG | | |
+++----------------+-----------------+-----------------+-----------------------------+
+ +----------------+-----------------+-----------------+-----------------------------+
+ | Qualcomm Tech. | Kryo/Falkor v1 | E1003 | QCOM_FALKOR_ERRATUM_1003 |
+ +----------------+-----------------+-----------------+-----------------------------+
+diff --git a/drivers/acpi/arm64/iort.c b/drivers/acpi/arm64/iort.c
+index 56d887323ae52..6496ff5a6ba20 100644
+--- a/drivers/acpi/arm64/iort.c
++++ b/drivers/acpi/arm64/iort.c
+@@ -1708,7 +1708,10 @@ static void __init arm_smmu_v3_pmcg_init_resources(struct resource *res,
+ static struct acpi_platform_list pmcg_plat_info[] __initdata = {
+ /* HiSilicon Hip08 Platform */
+ {"HISI ", "HIP08 ", 0, ACPI_SIG_IORT, greater_than_or_equal,
+- "Erratum #162001800", IORT_SMMU_V3_PMCG_HISI_HIP08},
++ "Erratum #162001800, Erratum #162001900", IORT_SMMU_V3_PMCG_HISI_HIP08},
++ /* HiSilicon Hip09 Platform */
++ {"HISI ", "HIP09 ", 0, ACPI_SIG_IORT, greater_than_or_equal,
++ "Erratum #162001900", IORT_SMMU_V3_PMCG_HISI_HIP09},
+ { }
+ };
+
+diff --git a/drivers/perf/arm_smmuv3_pmu.c b/drivers/perf/arm_smmuv3_pmu.c
+index 25a269d431e45..0e17c57ddb876 100644
+--- a/drivers/perf/arm_smmuv3_pmu.c
++++ b/drivers/perf/arm_smmuv3_pmu.c
+@@ -115,6 +115,7 @@
+ #define SMMU_PMCG_PA_SHIFT 12
+
+ #define SMMU_PMCG_EVCNTR_RDONLY BIT(0)
++#define SMMU_PMCG_HARDEN_DISABLE BIT(1)
+
+ static int cpuhp_state_num;
+
+@@ -159,6 +160,20 @@ static inline void smmu_pmu_enable(struct pmu *pmu)
+ writel(SMMU_PMCG_CR_ENABLE, smmu_pmu->reg_base + SMMU_PMCG_CR);
+ }
+
++static int smmu_pmu_apply_event_filter(struct smmu_pmu *smmu_pmu,
++ struct perf_event *event, int idx);
++
++static inline void smmu_pmu_enable_quirk_hip08_09(struct pmu *pmu)
++{
++ struct smmu_pmu *smmu_pmu = to_smmu_pmu(pmu);
++ unsigned int idx;
++
++ for_each_set_bit(idx, smmu_pmu->used_counters, smmu_pmu->num_counters)
++ smmu_pmu_apply_event_filter(smmu_pmu, smmu_pmu->events[idx], idx);
++
++ smmu_pmu_enable(pmu);
++}
++
+ static inline void smmu_pmu_disable(struct pmu *pmu)
+ {
+ struct smmu_pmu *smmu_pmu = to_smmu_pmu(pmu);
+@@ -167,6 +182,22 @@ static inline void smmu_pmu_disable(struct pmu *pmu)
+ writel(0, smmu_pmu->reg_base + SMMU_PMCG_IRQ_CTRL);
+ }
+
++static inline void smmu_pmu_disable_quirk_hip08_09(struct pmu *pmu)
++{
++ struct smmu_pmu *smmu_pmu = to_smmu_pmu(pmu);
++ unsigned int idx;
++
++ /*
++ * The global disable of PMU sometimes fail to stop the counting.
++ * Harden this by writing an invalid event type to each used counter
++ * to forcibly stop counting.
++ */
++ for_each_set_bit(idx, smmu_pmu->used_counters, smmu_pmu->num_counters)
++ writel(0xffff, smmu_pmu->reg_base + SMMU_PMCG_EVTYPER(idx));
++
++ smmu_pmu_disable(pmu);
++}
++
+ static inline void smmu_pmu_counter_set_value(struct smmu_pmu *smmu_pmu,
+ u32 idx, u64 value)
+ {
+@@ -765,7 +796,10 @@ static void smmu_pmu_get_acpi_options(struct smmu_pmu *smmu_pmu)
+ switch (model) {
+ case IORT_SMMU_V3_PMCG_HISI_HIP08:
+ /* HiSilicon Erratum 162001800 */
+- smmu_pmu->options |= SMMU_PMCG_EVCNTR_RDONLY;
++ smmu_pmu->options |= SMMU_PMCG_EVCNTR_RDONLY | SMMU_PMCG_HARDEN_DISABLE;
++ break;
++ case IORT_SMMU_V3_PMCG_HISI_HIP09:
++ smmu_pmu->options |= SMMU_PMCG_HARDEN_DISABLE;
+ break;
+ }
+
+@@ -890,6 +924,16 @@ static int smmu_pmu_probe(struct platform_device *pdev)
+ if (!dev->of_node)
+ smmu_pmu_get_acpi_options(smmu_pmu);
+
++ /*
++ * For platforms suffer this quirk, the PMU disable sometimes fails to
++ * stop the counters. This will leads to inaccurate or error counting.
++ * Forcibly disable the counters with these quirk handler.
++ */
++ if (smmu_pmu->options & SMMU_PMCG_HARDEN_DISABLE) {
++ smmu_pmu->pmu.pmu_enable = smmu_pmu_enable_quirk_hip08_09;
++ smmu_pmu->pmu.pmu_disable = smmu_pmu_disable_quirk_hip08_09;
++ }
++
+ /* Pick one CPU to be the preferred one to use */
+ smmu_pmu->on_cpu = raw_smp_processor_id();
+ WARN_ON(irq_set_affinity(smmu_pmu->irq, cpumask_of(smmu_pmu->on_cpu)));
+diff --git a/include/linux/acpi_iort.h b/include/linux/acpi_iort.h
+index ee7cb6aaff718..1cb65592c95dd 100644
+--- a/include/linux/acpi_iort.h
++++ b/include/linux/acpi_iort.h
+@@ -21,6 +21,7 @@
+ */
+ #define IORT_SMMU_V3_PMCG_GENERIC 0x00000000 /* Generic SMMUv3 PMCG */
+ #define IORT_SMMU_V3_PMCG_HISI_HIP08 0x00000001 /* HiSilicon HIP08 PMCG */
++#define IORT_SMMU_V3_PMCG_HISI_HIP09 0x00000002 /* HiSilicon HIP09 PMCG */
+
+ int iort_register_domain_token(int trans_id, phys_addr_t base,
+ struct fwnode_handle *fw_node);
+--
+2.40.1
+
--- /dev/null
+From 421b4b968ee5f038f65df467765b3cd796731065 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 2 Aug 2023 17:58:48 +0000
+Subject: platform/chrome: cros_ec_lpc: Remove EC panic shutdown timeout
+
+From: Rob Barnes <robbarnes@google.com>
+
+[ Upstream commit f2d4dced9a584612b25adb559c1350243d2bb544 ]
+
+Remove the 1 second timeout applied to hw_protection_shutdown after an
+EC panic. On some platforms this 1 second timeout is insufficient to
+allow the filesystem to fully sync. Independently the EC will force a
+full system reset after a short period. So this backup timeout is
+unnecessary.
+
+Signed-off-by: Rob Barnes <robbarnes@google.com>
+Reviewed-by: Guenter Roeck <groeck@chromium.org>
+Link: https://lore.kernel.org/r/20230802175847.1.Ie9fc53b6a1f4c6661c5376286a50e0cf51b3e961@changeid
+Signed-off-by: Tzung-Bi Shih <tzungbi@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/platform/chrome/cros_ec_lpc.c | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/drivers/platform/chrome/cros_ec_lpc.c b/drivers/platform/chrome/cros_ec_lpc.c
+index 500a61b093e47..356572452898d 100644
+--- a/drivers/platform/chrome/cros_ec_lpc.c
++++ b/drivers/platform/chrome/cros_ec_lpc.c
+@@ -327,8 +327,8 @@ static void cros_ec_lpc_acpi_notify(acpi_handle device, u32 value, void *data)
+ dev_emerg(ec_dev->dev, "CrOS EC Panic Reported. Shutdown is imminent!");
+ blocking_notifier_call_chain(&ec_dev->panic_notifier, 0, ec_dev);
+ kobject_uevent_env(&ec_dev->dev->kobj, KOBJ_CHANGE, (char **)env);
+- /* Begin orderly shutdown. Force shutdown after 1 second. */
+- hw_protection_shutdown("CrOS EC Panic", 1000);
++ /* Begin orderly shutdown. EC will force reset after a short period. */
++ hw_protection_shutdown("CrOS EC Panic", -1);
+ /* Do not query for other events after a panic is reported */
+ return;
+ }
+--
+2.40.1
+
--- /dev/null
+From 2750b0f1d2bc30185cc1c6d1a6ade999dc0190e2 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 6 Sep 2023 12:18:52 +0800
+Subject: PM: hibernate: Fix the exclusive get block device in test_resume mode
+
+From: Chen Yu <yu.c.chen@intel.com>
+
+[ Upstream commit 148b6f4cc3920e563094540fe1a12d00d3bbccae ]
+
+Commit 5904de0d735b ("PM: hibernate: Do not get block device exclusively
+in test_resume mode") fixes a hibernation issue under test_resume mode.
+That commit is supposed to open the block device in non-exclusive mode
+when in test_resume. However the code does the opposite, which is against
+its description.
+
+In summary, the swap device is only opened exclusively by swsusp_check()
+with its corresponding *close(), and must be in non test_resume mode.
+This is to avoid the race condition that different processes scribble the
+device at the same time. All the other cases should use non-exclusive mode.
+
+Fix it by really disabling exclusive mode under test_resume.
+
+Fixes: 5904de0d735b ("PM: hibernate: Do not get block device exclusively in test_resume mode")
+Closes: https://lore.kernel.org/lkml/000000000000761f5f0603324129@google.com/
+Reported-by: Pengfei Xu <pengfei.xu@intel.com>
+Signed-off-by: Chen Yu <yu.c.chen@intel.com>
+Tested-by: Chenzhou Feng <chenzhoux.feng@intel.com>
+Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ kernel/power/hibernate.c | 12 ++++++------
+ 1 file changed, 6 insertions(+), 6 deletions(-)
+
+diff --git a/kernel/power/hibernate.c b/kernel/power/hibernate.c
+index 2b4a946a6ff5c..8d35b9f9aaa3f 100644
+--- a/kernel/power/hibernate.c
++++ b/kernel/power/hibernate.c
+@@ -786,9 +786,9 @@ int hibernate(void)
+ unlock_device_hotplug();
+ if (snapshot_test) {
+ pm_pr_dbg("Checking hibernation image\n");
+- error = swsusp_check(snapshot_test);
++ error = swsusp_check(false);
+ if (!error)
+- error = load_image_and_restore(snapshot_test);
++ error = load_image_and_restore(false);
+ }
+ thaw_processes();
+
+@@ -945,14 +945,14 @@ static int software_resume(void)
+ pm_pr_dbg("Looking for hibernation image.\n");
+
+ mutex_lock(&system_transition_mutex);
+- error = swsusp_check(false);
++ error = swsusp_check(true);
+ if (error)
+ goto Unlock;
+
+ /* The snapshot device should not be opened while we're running */
+ if (!hibernate_acquire()) {
+ error = -EBUSY;
+- swsusp_close(false);
++ swsusp_close(true);
+ goto Unlock;
+ }
+
+@@ -973,7 +973,7 @@ static int software_resume(void)
+ goto Close_Finish;
+ }
+
+- error = load_image_and_restore(false);
++ error = load_image_and_restore(true);
+ thaw_processes();
+ Finish:
+ pm_notifier_call_chain(PM_POST_RESTORE);
+@@ -987,7 +987,7 @@ static int software_resume(void)
+ pm_pr_dbg("Hibernation image not present or could not be loaded.\n");
+ return error;
+ Close_Finish:
+- swsusp_close(false);
++ swsusp_close(true);
+ goto Finish;
+ }
+
+--
+2.40.1
+
--- /dev/null
+From 304692699edacc1c2a8f47908b7312a876e1cf9c Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 10 Nov 2022 09:19:29 +0800
+Subject: powerpc/pseries: fix possible memory leak in ibmebus_bus_init()
+
+From: ruanjinjie <ruanjinjie@huawei.com>
+
+[ Upstream commit afda85b963c12947e298ad85d757e333aa40fd74 ]
+
+If device_register() returns error in ibmebus_bus_init(), name of kobject
+which is allocated in dev_set_name() called in device_add() is leaked.
+
+As comment of device_add() says, it should call put_device() to drop
+the reference count that was set in device_initialize() when it fails,
+so the name can be freed in kobject_cleanup().
+
+Signed-off-by: ruanjinjie <ruanjinjie@huawei.com>
+Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
+Link: https://msgid.link/20221110011929.3709774-1-ruanjinjie@huawei.com
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ arch/powerpc/platforms/pseries/ibmebus.c | 1 +
+ 1 file changed, 1 insertion(+)
+
+diff --git a/arch/powerpc/platforms/pseries/ibmebus.c b/arch/powerpc/platforms/pseries/ibmebus.c
+index 44703f13985bf..969cb9fc960f8 100644
+--- a/arch/powerpc/platforms/pseries/ibmebus.c
++++ b/arch/powerpc/platforms/pseries/ibmebus.c
+@@ -460,6 +460,7 @@ static int __init ibmebus_bus_init(void)
+ if (err) {
+ printk(KERN_WARNING "%s: device_register returned %i\n",
+ __func__, err);
++ put_device(&ibmebus_bus_device);
+ bus_unregister(&ibmebus_bus_type);
+
+ return err;
+--
+2.40.1
+
--- /dev/null
+From a2103cfe353b3db0dec0519b1722bfd31e177dc1 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 17 Jul 2023 21:52:05 +0206
+Subject: printk: Consolidate console deferred printing
+
+From: John Ogness <john.ogness@linutronix.de>
+
+[ Upstream commit 696ffaf50e1f8dbc66223ff614473f945f5fb8d8 ]
+
+Printing to consoles can be deferred for several reasons:
+
+- explicitly with printk_deferred()
+- printk() in NMI context
+- recursive printk() calls
+
+The current implementation is not consistent. For printk_deferred(),
+irq work is scheduled twice. For NMI und recursive, panic CPU
+suppression and caller delays are not properly enforced.
+
+Correct these inconsistencies by consolidating the deferred printing
+code so that vprintk_deferred() is the top-level function for
+deferred printing and vprintk_emit() will perform whichever irq_work
+queueing is appropriate.
+
+Also add kerneldoc for wake_up_klogd() and defer_console_output() to
+clarify their differences and appropriate usage.
+
+Signed-off-by: John Ogness <john.ogness@linutronix.de>
+Reviewed-by: Sergey Senozhatsky <senozhatsky@chromium.org>
+Reviewed-by: Petr Mladek <pmladek@suse.com>
+Signed-off-by: Petr Mladek <pmladek@suse.com>
+Link: https://lore.kernel.org/r/20230717194607.145135-6-john.ogness@linutronix.de
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ kernel/printk/printk.c | 35 ++++++++++++++++++++++++++++-------
+ kernel/printk/printk_safe.c | 9 ++-------
+ 2 files changed, 30 insertions(+), 14 deletions(-)
+
+diff --git a/kernel/printk/printk.c b/kernel/printk/printk.c
+index 88770561c4350..d5e29fad84234 100644
+--- a/kernel/printk/printk.c
++++ b/kernel/printk/printk.c
+@@ -2308,7 +2308,11 @@ asmlinkage int vprintk_emit(int facility, int level,
+ preempt_enable();
+ }
+
+- wake_up_klogd();
++ if (in_sched)
++ defer_console_output();
++ else
++ wake_up_klogd();
++
+ return printed_len;
+ }
+ EXPORT_SYMBOL(vprintk_emit);
+@@ -3843,11 +3847,33 @@ static void __wake_up_klogd(int val)
+ preempt_enable();
+ }
+
++/**
++ * wake_up_klogd - Wake kernel logging daemon
++ *
++ * Use this function when new records have been added to the ringbuffer
++ * and the console printing of those records has already occurred or is
++ * known to be handled by some other context. This function will only
++ * wake the logging daemon.
++ *
++ * Context: Any context.
++ */
+ void wake_up_klogd(void)
+ {
+ __wake_up_klogd(PRINTK_PENDING_WAKEUP);
+ }
+
++/**
++ * defer_console_output - Wake kernel logging daemon and trigger
++ * console printing in a deferred context
++ *
++ * Use this function when new records have been added to the ringbuffer,
++ * this context is responsible for console printing those records, but
++ * the current context is not allowed to perform the console printing.
++ * Trigger an irq_work context to perform the console printing. This
++ * function also wakes the logging daemon.
++ *
++ * Context: Any context.
++ */
+ void defer_console_output(void)
+ {
+ /*
+@@ -3864,12 +3890,7 @@ void printk_trigger_flush(void)
+
+ int vprintk_deferred(const char *fmt, va_list args)
+ {
+- int r;
+-
+- r = vprintk_emit(0, LOGLEVEL_SCHED, NULL, fmt, args);
+- defer_console_output();
+-
+- return r;
++ return vprintk_emit(0, LOGLEVEL_SCHED, NULL, fmt, args);
+ }
+
+ int _printk_deferred(const char *fmt, ...)
+diff --git a/kernel/printk/printk_safe.c b/kernel/printk/printk_safe.c
+index ef0f9a2044da1..6d10927a07d83 100644
+--- a/kernel/printk/printk_safe.c
++++ b/kernel/printk/printk_safe.c
+@@ -38,13 +38,8 @@ asmlinkage int vprintk(const char *fmt, va_list args)
+ * Use the main logbuf even in NMI. But avoid calling console
+ * drivers that might have their own locks.
+ */
+- if (this_cpu_read(printk_context) || in_nmi()) {
+- int len;
+-
+- len = vprintk_store(0, LOGLEVEL_DEFAULT, NULL, fmt, args);
+- defer_console_output();
+- return len;
+- }
++ if (this_cpu_read(printk_context) || in_nmi())
++ return vprintk_deferred(fmt, args);
+
+ /* No obstacles. */
+ return vprintk_default(fmt, args);
+--
+2.40.1
+
--- /dev/null
+From db1b38358ec5d28707b80f56b35362d520760a06 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 17 Jul 2023 21:52:04 +0206
+Subject: printk: Do not take console lock for console_flush_on_panic()
+
+From: John Ogness <john.ogness@linutronix.de>
+
+[ Upstream commit eacb04ff3c5b8662a65f380ae450250698448cff ]
+
+Currently console_flush_on_panic() will attempt to acquire the
+console lock when flushing the buffer on panic. If it fails to
+acquire the lock, it continues anyway because this is the last
+chance to get any pending records printed.
+
+The reason why the console lock was attempted at all was to
+prevent any other CPUs from acquiring the console lock for
+printing while the panic CPU was printing. But as of the
+previous commit, non-panic CPUs will no longer attempt to
+acquire the console lock in a panic situation. Therefore it is
+no longer strictly necessary for a panic CPU to acquire the
+console lock.
+
+Avoiding taking the console lock when flushing in panic has
+the additional benefit of avoiding possible deadlocks due to
+semaphore usage in NMI context (semaphores are not NMI-safe)
+and avoiding possible deadlocks if another CPU accesses the
+semaphore and is stopped while holding one of the semaphore's
+internal spinlocks.
+
+Signed-off-by: John Ogness <john.ogness@linutronix.de>
+Reviewed-by: Sergey Senozhatsky <senozhatsky@chromium.org>
+Reviewed-by: Petr Mladek <pmladek@suse.com>
+Signed-off-by: Petr Mladek <pmladek@suse.com>
+Link: https://lore.kernel.org/r/20230717194607.145135-5-john.ogness@linutronix.de
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ kernel/printk/printk.c | 28 +++++++++++++++++++---------
+ 1 file changed, 19 insertions(+), 9 deletions(-)
+
+diff --git a/kernel/printk/printk.c b/kernel/printk/printk.c
+index 591c11888200d..88770561c4350 100644
+--- a/kernel/printk/printk.c
++++ b/kernel/printk/printk.c
+@@ -3120,14 +3120,24 @@ void console_unblank(void)
+ */
+ void console_flush_on_panic(enum con_flush_mode mode)
+ {
++ bool handover;
++ u64 next_seq;
++
+ /*
+- * If someone else is holding the console lock, trylock will fail
+- * and may_schedule may be set. Ignore and proceed to unlock so
+- * that messages are flushed out. As this can be called from any
+- * context and we don't want to get preempted while flushing,
+- * ensure may_schedule is cleared.
++ * Ignore the console lock and flush out the messages. Attempting a
++ * trylock would not be useful because:
++ *
++ * - if it is contended, it must be ignored anyway
++ * - console_lock() and console_trylock() block and fail
++ * respectively in panic for non-panic CPUs
++ * - semaphores are not NMI-safe
++ */
++
++ /*
++ * If another context is holding the console lock,
++ * @console_may_schedule might be set. Clear it so that
++ * this context does not call cond_resched() while flushing.
+ */
+- console_trylock();
+ console_may_schedule = 0;
+
+ if (mode == CONSOLE_REPLAY_ALL) {
+@@ -3140,15 +3150,15 @@ void console_flush_on_panic(enum con_flush_mode mode)
+ cookie = console_srcu_read_lock();
+ for_each_console_srcu(c) {
+ /*
+- * If the above console_trylock() failed, this is an
+- * unsynchronized assignment. But in that case, the
++ * This is an unsynchronized assignment, but the
+ * kernel is in "hope and pray" mode anyway.
+ */
+ c->seq = seq;
+ }
+ console_srcu_read_unlock(cookie);
+ }
+- console_unlock();
++
++ console_flush_all(false, &next_seq, &handover);
+ }
+
+ /*
+--
+2.40.1
+
--- /dev/null
+From f237a5fc598b7ff2d6376a32d787b89377349332 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 17 Jul 2023 21:52:03 +0206
+Subject: printk: Keep non-panic-CPUs out of console lock
+
+From: John Ogness <john.ogness@linutronix.de>
+
+[ Upstream commit 51a1d258e50e03a0216bf42b6af9ff34ec402ac1 ]
+
+When in a panic situation, non-panic CPUs should avoid holding the
+console lock so as not to contend with the panic CPU. This is already
+implemented with abandon_console_lock_in_panic(), which is checked
+after each printed line. However, non-panic CPUs should also avoid
+trying to acquire the console lock during a panic.
+
+Modify console_trylock() to fail and console_lock() to block() when
+called from a non-panic CPU during a panic.
+
+Signed-off-by: John Ogness <john.ogness@linutronix.de>
+Reviewed-by: Sergey Senozhatsky <senozhatsky@chromium.org>
+Reviewed-by: Petr Mladek <pmladek@suse.com>
+Signed-off-by: Petr Mladek <pmladek@suse.com>
+Link: https://lore.kernel.org/r/20230717194607.145135-4-john.ogness@linutronix.de
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ kernel/printk/printk.c | 45 ++++++++++++++++++++++++------------------
+ 1 file changed, 26 insertions(+), 19 deletions(-)
+
+diff --git a/kernel/printk/printk.c b/kernel/printk/printk.c
+index 7d3f30eb35862..591c11888200d 100644
+--- a/kernel/printk/printk.c
++++ b/kernel/printk/printk.c
+@@ -2585,6 +2585,25 @@ static int console_cpu_notify(unsigned int cpu)
+ return 0;
+ }
+
++/*
++ * Return true when this CPU should unlock console_sem without pushing all
++ * messages to the console. This reduces the chance that the console is
++ * locked when the panic CPU tries to use it.
++ */
++static bool abandon_console_lock_in_panic(void)
++{
++ if (!panic_in_progress())
++ return false;
++
++ /*
++ * We can use raw_smp_processor_id() here because it is impossible for
++ * the task to be migrated to the panic_cpu, or away from it. If
++ * panic_cpu has already been set, and we're not currently executing on
++ * that CPU, then we never will be.
++ */
++ return atomic_read(&panic_cpu) != raw_smp_processor_id();
++}
++
+ /**
+ * console_lock - block the console subsystem from printing
+ *
+@@ -2597,6 +2616,10 @@ void console_lock(void)
+ {
+ might_sleep();
+
++ /* On panic, the console_lock must be left to the panic cpu. */
++ while (abandon_console_lock_in_panic())
++ msleep(1000);
++
+ down_console_sem();
+ if (console_suspended)
+ return;
+@@ -2615,6 +2638,9 @@ EXPORT_SYMBOL(console_lock);
+ */
+ int console_trylock(void)
+ {
++ /* On panic, the console_lock must be left to the panic cpu. */
++ if (abandon_console_lock_in_panic())
++ return 0;
+ if (down_trylock_console_sem())
+ return 0;
+ if (console_suspended) {
+@@ -2633,25 +2659,6 @@ int is_console_locked(void)
+ }
+ EXPORT_SYMBOL(is_console_locked);
+
+-/*
+- * Return true when this CPU should unlock console_sem without pushing all
+- * messages to the console. This reduces the chance that the console is
+- * locked when the panic CPU tries to use it.
+- */
+-static bool abandon_console_lock_in_panic(void)
+-{
+- if (!panic_in_progress())
+- return false;
+-
+- /*
+- * We can use raw_smp_processor_id() here because it is impossible for
+- * the task to be migrated to the panic_cpu, or away from it. If
+- * panic_cpu has already been set, and we're not currently executing on
+- * that CPU, then we never will be.
+- */
+- return atomic_read(&panic_cpu) != raw_smp_processor_id();
+-}
+-
+ /*
+ * Check if the given console is currently capable and allowed to print
+ * records.
+--
+2.40.1
+
--- /dev/null
+From 2c4830d767254f7e42841303c7c91dbea51f2da9 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 17 Jul 2023 21:52:02 +0206
+Subject: printk: Reduce console_unblank() usage in unsafe scenarios
+
+From: John Ogness <john.ogness@linutronix.de>
+
+[ Upstream commit 7b23a66db55ed0a55b020e913f0d6f6d52a1ad2c ]
+
+A semaphore is not NMI-safe, even when using down_trylock(). Both
+down_trylock() and up() are using internal spinlocks and up()
+might even call wake_up_process().
+
+In the panic() code path it gets even worse because the internal
+spinlocks of the semaphore may have been taken by a CPU that has
+been stopped.
+
+To reduce the risk of deadlocks caused by the console semaphore in
+the panic path, make the following changes:
+
+- First check if any consoles have implemented the unblank()
+ callback. If not, then there is no reason to take the console
+ semaphore anyway. (This check is also useful for the non-panic
+ path since the locking/unlocking of the console lock can be
+ quite expensive due to console printing.)
+
+- If the panic path is in NMI context, bail out without attempting
+ to take the console semaphore or calling any unblank() callbacks.
+ Bailing out is acceptable because console_unblank() would already
+ bail out if the console semaphore is contended. The alternative of
+ ignoring the console semaphore and calling the unblank() callbacks
+ anyway is a bad idea because these callbacks are also not NMI-safe.
+
+If consoles with unblank() callbacks exist and console_unblank() is
+called from a non-NMI panic context, it will still attempt a
+down_trylock(). This could still result in a deadlock if one of the
+stopped CPUs is holding the semaphore internal spinlock. But this
+is a risk that the kernel has been (and continues to be) willing
+to take.
+
+Signed-off-by: John Ogness <john.ogness@linutronix.de>
+Reviewed-by: Sergey Senozhatsky <senozhatsky@chromium.org>
+Reviewed-by: Petr Mladek <pmladek@suse.com>
+Signed-off-by: Petr Mladek <pmladek@suse.com>
+Link: https://lore.kernel.org/r/20230717194607.145135-3-john.ogness@linutronix.de
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ kernel/printk/printk.c | 28 ++++++++++++++++++++++++++++
+ 1 file changed, 28 insertions(+)
+
+diff --git a/kernel/printk/printk.c b/kernel/printk/printk.c
+index 357a4d18f6387..7d3f30eb35862 100644
+--- a/kernel/printk/printk.c
++++ b/kernel/printk/printk.c
+@@ -3045,9 +3045,27 @@ EXPORT_SYMBOL(console_conditional_schedule);
+
+ void console_unblank(void)
+ {
++ bool found_unblank = false;
+ struct console *c;
+ int cookie;
+
++ /*
++ * First check if there are any consoles implementing the unblank()
++ * callback. If not, there is no reason to continue and take the
++ * console lock, which in particular can be dangerous if
++ * @oops_in_progress is set.
++ */
++ cookie = console_srcu_read_lock();
++ for_each_console_srcu(c) {
++ if ((console_srcu_read_flags(c) & CON_ENABLED) && c->unblank) {
++ found_unblank = true;
++ break;
++ }
++ }
++ console_srcu_read_unlock(cookie);
++ if (!found_unblank)
++ return;
++
+ /*
+ * Stop console printing because the unblank() callback may
+ * assume the console is not within its write() callback.
+@@ -3056,6 +3074,16 @@ void console_unblank(void)
+ * In that case, attempt a trylock as best-effort.
+ */
+ if (oops_in_progress) {
++ /* Semaphores are not NMI-safe. */
++ if (in_nmi())
++ return;
++
++ /*
++ * Attempting to trylock the console lock can deadlock
++ * if another CPU was stopped while modifying the
++ * semaphore. "Hope and pray" that this is not the
++ * current situation.
++ */
+ if (down_trylock_console_sem() != 0)
+ return;
+ } else
+--
+2.40.1
+
--- /dev/null
+From e0733272398ba3fb0554624d185834193787a23f Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 17 Jul 2023 21:52:07 +0206
+Subject: printk: Rename abandon_console_lock_in_panic() to
+ other_cpu_in_panic()
+
+From: John Ogness <john.ogness@linutronix.de>
+
+[ Upstream commit 132a90d1527fedba2d95085c951ccf00dbbebe41 ]
+
+Currently abandon_console_lock_in_panic() is only used to determine if
+the current CPU should immediately release the console lock because
+another CPU is in panic. However, later this function will be used by
+the CPU to immediately release other resources in this situation.
+
+Rename the function to other_cpu_in_panic(), which is a better
+description and does not assume it is related to the console lock.
+
+Signed-off-by: John Ogness <john.ogness@linutronix.de>
+Reviewed-by: Sergey Senozhatsky <senozhatsky@chromium.org>
+Reviewed-by: Petr Mladek <pmladek@suse.com>
+Signed-off-by: Petr Mladek <pmladek@suse.com>
+Link: https://lore.kernel.org/r/20230717194607.145135-8-john.ogness@linutronix.de
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ kernel/printk/internal.h | 2 ++
+ kernel/printk/printk.c | 15 ++++++++-------
+ 2 files changed, 10 insertions(+), 7 deletions(-)
+
+diff --git a/kernel/printk/internal.h b/kernel/printk/internal.h
+index 2a17704136f1d..7d4979d5c3ce6 100644
+--- a/kernel/printk/internal.h
++++ b/kernel/printk/internal.h
+@@ -103,3 +103,5 @@ struct printk_message {
+ u64 seq;
+ unsigned long dropped;
+ };
++
++bool other_cpu_in_panic(void);
+diff --git a/kernel/printk/printk.c b/kernel/printk/printk.c
+index d5e29fad84234..08a9419046b65 100644
+--- a/kernel/printk/printk.c
++++ b/kernel/printk/printk.c
+@@ -2590,11 +2590,12 @@ static int console_cpu_notify(unsigned int cpu)
+ }
+
+ /*
+- * Return true when this CPU should unlock console_sem without pushing all
+- * messages to the console. This reduces the chance that the console is
+- * locked when the panic CPU tries to use it.
++ * Return true if a panic is in progress on a remote CPU.
++ *
++ * On true, the local CPU should immediately release any printing resources
++ * that may be needed by the panic CPU.
+ */
+-static bool abandon_console_lock_in_panic(void)
++bool other_cpu_in_panic(void)
+ {
+ if (!panic_in_progress())
+ return false;
+@@ -2621,7 +2622,7 @@ void console_lock(void)
+ might_sleep();
+
+ /* On panic, the console_lock must be left to the panic cpu. */
+- while (abandon_console_lock_in_panic())
++ while (other_cpu_in_panic())
+ msleep(1000);
+
+ down_console_sem();
+@@ -2643,7 +2644,7 @@ EXPORT_SYMBOL(console_lock);
+ int console_trylock(void)
+ {
+ /* On panic, the console_lock must be left to the panic cpu. */
+- if (abandon_console_lock_in_panic())
++ if (other_cpu_in_panic())
+ return 0;
+ if (down_trylock_console_sem())
+ return 0;
+@@ -2959,7 +2960,7 @@ static bool console_flush_all(bool do_cond_resched, u64 *next_seq, bool *handove
+ any_progress = true;
+
+ /* Allow panic_cpu to take over the consoles safely. */
+- if (abandon_console_lock_in_panic())
++ if (other_cpu_in_panic())
+ goto abandon;
+
+ if (do_cond_resched)
+--
+2.40.1
+
--- /dev/null
+From 54d05d1c09eec3c64dddd55ba9c59e432e3df95f Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 16 Jun 2023 15:39:26 +0800
+Subject: rcuscale: Move rcu_scale_writer() schedule_timeout_uninterruptible()
+ to _idle()
+
+From: Zqiang <qiang.zhang1211@gmail.com>
+
+[ Upstream commit e60c122a1614b4f65b29a7bef9d83b9fd30e937a ]
+
+The rcuscale.holdoff module parameter can be used to delay the start
+of rcu_scale_writer() kthread. However, the hung-task timeout will
+trigger when the timeout specified by rcuscale.holdoff is greater than
+hung_task_timeout_secs:
+
+runqemu kvm nographic slirp qemuparams="-smp 4 -m 2048M"
+bootparams="rcuscale.shutdown=0 rcuscale.holdoff=300"
+
+[ 247.071753] INFO: task rcu_scale_write:59 blocked for more than 122 seconds.
+[ 247.072529] Not tainted 6.4.0-rc1-00134-gb9ed6de8d4ff #7
+[ 247.073400] "echo 0 > /proc/sys/kernel/hung_task_timeout_secs" disables this message.
+[ 247.074331] task:rcu_scale_write state:D stack:30144 pid:59 ppid:2 flags:0x00004000
+[ 247.075346] Call Trace:
+[ 247.075660] <TASK>
+[ 247.075965] __schedule+0x635/0x1280
+[ 247.076448] ? __pfx___schedule+0x10/0x10
+[ 247.076967] ? schedule_timeout+0x2dc/0x4d0
+[ 247.077471] ? __pfx_lock_release+0x10/0x10
+[ 247.078018] ? enqueue_timer+0xe2/0x220
+[ 247.078522] schedule+0x84/0x120
+[ 247.078957] schedule_timeout+0x2e1/0x4d0
+[ 247.079447] ? __pfx_schedule_timeout+0x10/0x10
+[ 247.080032] ? __pfx_rcu_scale_writer+0x10/0x10
+[ 247.080591] ? __pfx_process_timeout+0x10/0x10
+[ 247.081163] ? __pfx_sched_set_fifo_low+0x10/0x10
+[ 247.081760] ? __pfx_rcu_scale_writer+0x10/0x10
+[ 247.082287] rcu_scale_writer+0x6b1/0x7f0
+[ 247.082773] ? mark_held_locks+0x29/0xa0
+[ 247.083252] ? __pfx_rcu_scale_writer+0x10/0x10
+[ 247.083865] ? __pfx_rcu_scale_writer+0x10/0x10
+[ 247.084412] kthread+0x179/0x1c0
+[ 247.084759] ? __pfx_kthread+0x10/0x10
+[ 247.085098] ret_from_fork+0x2c/0x50
+[ 247.085433] </TASK>
+
+This commit therefore replaces schedule_timeout_uninterruptible() with
+schedule_timeout_idle().
+
+Signed-off-by: Zqiang <qiang.zhang1211@gmail.com>
+Signed-off-by: Paul E. McKenney <paulmck@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ kernel/rcu/rcuscale.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/kernel/rcu/rcuscale.c b/kernel/rcu/rcuscale.c
+index d1221731c7cfd..35aab6cbba583 100644
+--- a/kernel/rcu/rcuscale.c
++++ b/kernel/rcu/rcuscale.c
+@@ -424,7 +424,7 @@ rcu_scale_writer(void *arg)
+ sched_set_fifo_low(current);
+
+ if (holdoff)
+- schedule_timeout_uninterruptible(holdoff * HZ);
++ schedule_timeout_idle(holdoff * HZ);
+
+ /*
+ * Wait until rcu_end_inkernel_boot() is called for normal GP tests
+--
+2.40.1
+
--- /dev/null
+From 431054e59d25a9f16b85e925de89370c738ac94a Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 22 Aug 2023 14:17:21 +0200
+Subject: Revert "wifi: mac80211_hwsim: check the return value of nla_put_u32"
+
+From: Johannes Berg <johannes.berg@intel.com>
+
+[ Upstream commit 1b78dd34560e9962f8e917fe4adde6f2ab0eb89f ]
+
+This reverts commit b970ac68e0c4 ("wifi: mac80211_hwsim: check the
+return value of nla_put_u32") since it introduced a memory leak in
+the error path, which seems worse than sending an incomplete skb,
+and the put can't fail anyway since the SKB was just allocated.
+
+Signed-off-by: Johannes Berg <johannes.berg@intel.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/wireless/virtual/mac80211_hwsim.c | 5 ++---
+ 1 file changed, 2 insertions(+), 3 deletions(-)
+
+diff --git a/drivers/net/wireless/virtual/mac80211_hwsim.c b/drivers/net/wireless/virtual/mac80211_hwsim.c
+index dd516cec41973..23307c8baea21 100644
+--- a/drivers/net/wireless/virtual/mac80211_hwsim.c
++++ b/drivers/net/wireless/virtual/mac80211_hwsim.c
+@@ -582,9 +582,8 @@ static int mac80211_hwsim_vendor_cmd_test(struct wiphy *wiphy,
+ */
+
+ /* Add vendor data */
+- err = nla_put_u32(skb, QCA_WLAN_VENDOR_ATTR_TEST, val + 1);
+- if (err)
+- return err;
++ nla_put_u32(skb, QCA_WLAN_VENDOR_ATTR_TEST, val + 1);
++
+ /* Send the event - this will call nla_nest_end() */
+ cfg80211_vendor_event(skb, GFP_KERNEL);
+ }
+--
+2.40.1
+
--- /dev/null
+From f3a721f8d050c391aec90297e1160583866d3b8b Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 6 Sep 2023 17:58:17 +0800
+Subject: riscv: kexec: Align the kexeced kernel entry
+
+From: Song Shuai <songshuaishuai@tinylab.org>
+
+[ Upstream commit 1bfb2b618d52e59a4ef1896b46c4698ad2be66b7 ]
+
+The current riscv boot protocol requires 2MB alignment for RV64
+and 4MB alignment for RV32.
+
+In KEXEC_FILE path, the elf_find_pbase() function should align
+the kexeced kernel entry according to the requirement, otherwise
+the kexeced kernel would silently BUG at the setup_vm().
+
+Fixes: 8acea455fafa ("RISC-V: Support for kexec_file on panic")
+Signed-off-by: Song Shuai <songshuaishuai@tinylab.org>
+Link: https://lore.kernel.org/r/20230906095817.364390-1-songshuaishuai@tinylab.org
+Signed-off-by: Palmer Dabbelt <palmer@rivosinc.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ arch/riscv/kernel/elf_kexec.c | 8 +++++++-
+ 1 file changed, 7 insertions(+), 1 deletion(-)
+
+diff --git a/arch/riscv/kernel/elf_kexec.c b/arch/riscv/kernel/elf_kexec.c
+index c08bb5c3b3857..b3b96ff46d193 100644
+--- a/arch/riscv/kernel/elf_kexec.c
++++ b/arch/riscv/kernel/elf_kexec.c
+@@ -98,7 +98,13 @@ static int elf_find_pbase(struct kimage *image, unsigned long kernel_len,
+ kbuf.image = image;
+ kbuf.buf_min = lowest_paddr;
+ kbuf.buf_max = ULONG_MAX;
+- kbuf.buf_align = PAGE_SIZE;
++
++ /*
++ * Current riscv boot protocol requires 2MB alignment for
++ * RV64 and 4MB alignment for RV32
++ *
++ */
++ kbuf.buf_align = PMD_SIZE;
+ kbuf.mem = KEXEC_BUF_MEM_UNKNOWN;
+ kbuf.memsz = ALIGN(kernel_len, PAGE_SIZE);
+ kbuf.top_down = false;
+--
+2.40.1
+
--- /dev/null
+From 1433000ff520b2e2411103591369e6afcbda459b Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 6 Jul 2023 12:28:17 +0200
+Subject: s390/boot: cleanup number of page table levels setup
+
+From: Alexander Gordeev <agordeev@linux.ibm.com>
+
+[ Upstream commit 8ddccc8a7d06f7ea4d8579970c95609d1b1de77b ]
+
+The separate vmalloc area size check against _REGION2_SIZE
+is needed in case user provided insanely large value using
+vmalloc= kernel command line parameter. That could lead to
+overflow and selecting 3 page table levels instead of 4.
+
+Use size_add() for the overflow check and get rid of the
+extra vmalloc area check.
+
+With the current values of CONFIG_MAX_PHYSMEM_BITS and
+PAGES_PER_SECTION the sum of maximal possible size of
+identity mapping and vmemmap area (derived from these
+macros) plus modules area size MODULES_LEN can not
+overflow. Thus, that sum is used as first addend while
+vmalloc area size is second addend for size_add().
+
+Suggested-by: Heiko Carstens <hca@linux.ibm.com>
+Acked-by: Heiko Carstens <hca@linux.ibm.com>
+Signed-off-by: Alexander Gordeev <agordeev@linux.ibm.com>
+Signed-off-by: Heiko Carstens <hca@linux.ibm.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ arch/s390/boot/startup.c | 9 ++++-----
+ 1 file changed, 4 insertions(+), 5 deletions(-)
+
+diff --git a/arch/s390/boot/startup.c b/arch/s390/boot/startup.c
+index 64bd7ac3e35d1..f8d0550e5d2af 100644
+--- a/arch/s390/boot/startup.c
++++ b/arch/s390/boot/startup.c
+@@ -176,6 +176,7 @@ static unsigned long setup_kernel_memory_layout(void)
+ unsigned long asce_limit;
+ unsigned long rte_size;
+ unsigned long pages;
++ unsigned long vsize;
+ unsigned long vmax;
+
+ pages = ident_map_size / PAGE_SIZE;
+@@ -183,11 +184,9 @@ static unsigned long setup_kernel_memory_layout(void)
+ vmemmap_size = SECTION_ALIGN_UP(pages) * sizeof(struct page);
+
+ /* choose kernel address space layout: 4 or 3 levels. */
+- vmemmap_start = round_up(ident_map_size, _REGION3_SIZE);
+- if (IS_ENABLED(CONFIG_KASAN) ||
+- vmalloc_size > _REGION2_SIZE ||
+- vmemmap_start + vmemmap_size + vmalloc_size + MODULES_LEN >
+- _REGION2_SIZE) {
++ vsize = round_up(ident_map_size, _REGION3_SIZE) + vmemmap_size + MODULES_LEN;
++ vsize = size_add(vsize, vmalloc_size);
++ if (IS_ENABLED(CONFIG_KASAN) || (vsize > _REGION2_SIZE)) {
+ asce_limit = _REGION1_SIZE;
+ rte_size = _REGION2_SIZE;
+ } else {
+--
+2.40.1
+
--- /dev/null
+From 6ab63f0c5a10d7d362d09a97120c021ddd4e8cb0 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 25 Jul 2023 10:25:36 +0200
+Subject: samples/hw_breakpoint: fix building without module unloading
+
+From: Arnd Bergmann <arnd@arndb.de>
+
+[ Upstream commit b9080468caeddc58a91edd1c3a7d212ea82b0d1d ]
+
+__symbol_put() is really meant as an internal helper and is not available
+when module unloading is disabled, unlike the previously used symbol_put():
+
+samples/hw_breakpoint/data_breakpoint.c: In function 'hw_break_module_exit':
+samples/hw_breakpoint/data_breakpoint.c:73:9: error: implicit declaration of function '__symbol_put'; did you mean '__symbol_get'? [-Werror=implicit-function-declaration]
+
+The hw_break_module_exit() function is not actually used when module
+unloading is disabled, but it still causes the build failure for an
+undefined identifier. Enclose this one call in an appropriate #ifdef to
+clarify what the requirement is. Leaving out the entire exit function
+would also work but feels less clar in this case.
+
+Fixes: 910e230d5f1bb ("samples/hw_breakpoint: Fix kernel BUG 'invalid opcode: 0000'")
+Fixes: d8a84d33a4954 ("samples/hw_breakpoint: drop use of kallsyms_lookup_name()")
+Signed-off-by: Arnd Bergmann <arnd@arndb.de>
+Reviewed-by: Petr Mladek <pmladek@suse.com>
+Signed-off-by: Luis Chamberlain <mcgrof@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ samples/hw_breakpoint/data_breakpoint.c | 2 ++
+ 1 file changed, 2 insertions(+)
+
+diff --git a/samples/hw_breakpoint/data_breakpoint.c b/samples/hw_breakpoint/data_breakpoint.c
+index 9debd128b2ab8..b99322f188e59 100644
+--- a/samples/hw_breakpoint/data_breakpoint.c
++++ b/samples/hw_breakpoint/data_breakpoint.c
+@@ -70,7 +70,9 @@ static int __init hw_break_module_init(void)
+ static void __exit hw_break_module_exit(void)
+ {
+ unregister_wide_hw_breakpoint(sample_hbp);
++#ifdef CONFIG_MODULE_UNLOAD
+ __symbol_put(ksym_name);
++#endif
+ printk(KERN_INFO "HW Breakpoint for %s write uninstalled\n", ksym_name);
+ }
+
+--
+2.40.1
+
--- /dev/null
+From d0694ef523e8b25720156bf2d051e2f1aac11600 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sun, 16 Apr 2023 23:05:17 +0800
+Subject: samples/hw_breakpoint: Fix kernel BUG 'invalid opcode: 0000'
+
+From: Rong Tao <rongtao@cestc.cn>
+
+[ Upstream commit 910e230d5f1bb72c54532e94fbb1705095c7bab6 ]
+
+Macro symbol_put() is defined as __symbol_put(__stringify(x))
+
+ ksym_name = "jiffies"
+ symbol_put(ksym_name)
+
+will be resolved as
+
+ __symbol_put("ksym_name")
+
+which is clearly wrong. So symbol_put must be replaced with __symbol_put.
+
+When we uninstall hw_breakpoint.ko (rmmod), a kernel bug occurs with the
+following error:
+
+[11381.854152] kernel BUG at kernel/module/main.c:779!
+[11381.854159] invalid opcode: 0000 [#2] PREEMPT SMP PTI
+[11381.854163] CPU: 8 PID: 59623 Comm: rmmod Tainted: G D OE 6.2.9-200.fc37.x86_64 #1
+[11381.854167] Hardware name: To Be Filled By O.E.M. To Be Filled By O.E.M./B360M-HDV, BIOS P3.20 10/23/2018
+[11381.854169] RIP: 0010:__symbol_put+0xa2/0xb0
+[11381.854175] Code: 00 e8 92 d2 f7 ff 65 8b 05 c3 2f e6 78 85 c0 74 1b 48 8b 44 24 30 65 48 2b 04 25 28 00 00 00 75 12 48 83 c4 38 c3 cc cc cc cc <0f> 0b 0f 1f 44 00 00 eb de e8 c0 df d8 00 90 90 90 90 90 90 90 90
+[11381.854178] RSP: 0018:ffffad8ec6ae7dd0 EFLAGS: 00010246
+[11381.854181] RAX: 0000000000000000 RBX: ffffffffc1fd1240 RCX: 000000000000000c
+[11381.854184] RDX: 000000000000006b RSI: ffffffffc02bf7c7 RDI: ffffffffc1fd001c
+[11381.854186] RBP: 000055a38b76e7c8 R08: ffffffff871ccfe0 R09: 0000000000000000
+[11381.854188] R10: 0000000000000000 R11: 0000000000000000 R12: 0000000000000000
+[11381.854190] R13: 0000000000000000 R14: 0000000000000000 R15: 0000000000000000
+[11381.854192] FS: 00007fbf7c62c740(0000) GS:ffff8c5badc00000(0000) knlGS:0000000000000000
+[11381.854195] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
+[11381.854197] CR2: 000055a38b7793f8 CR3: 0000000363e1e001 CR4: 00000000003726e0
+[11381.854200] DR0: ffffffffb3407980 DR1: 0000000000000000 DR2: 0000000000000000
+[11381.854202] DR3: 0000000000000000 DR6: 00000000ffff0ff0 DR7: 0000000000000400
+[11381.854204] Call Trace:
+[11381.854207] <TASK>
+[11381.854212] s_module_exit+0xc/0xff0 [symbol_getput]
+[11381.854219] __do_sys_delete_module.constprop.0+0x198/0x2f0
+[11381.854225] do_syscall_64+0x58/0x80
+[11381.854231] ? exit_to_user_mode_prepare+0x180/0x1f0
+[11381.854237] ? syscall_exit_to_user_mode+0x17/0x40
+[11381.854241] ? do_syscall_64+0x67/0x80
+[11381.854245] ? syscall_exit_to_user_mode+0x17/0x40
+[11381.854248] ? do_syscall_64+0x67/0x80
+[11381.854252] ? exc_page_fault+0x70/0x170
+[11381.854256] entry_SYSCALL_64_after_hwframe+0x72/0xdc
+
+Signed-off-by: Rong Tao <rongtao@cestc.cn>
+Reviewed-by: Petr Mladek <pmladek@suse.com>
+Signed-off-by: Luis Chamberlain <mcgrof@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ samples/hw_breakpoint/data_breakpoint.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/samples/hw_breakpoint/data_breakpoint.c b/samples/hw_breakpoint/data_breakpoint.c
+index 418c46fe5ffc3..9debd128b2ab8 100644
+--- a/samples/hw_breakpoint/data_breakpoint.c
++++ b/samples/hw_breakpoint/data_breakpoint.c
+@@ -70,7 +70,7 @@ static int __init hw_break_module_init(void)
+ static void __exit hw_break_module_exit(void)
+ {
+ unregister_wide_hw_breakpoint(sample_hbp);
+- symbol_put(ksym_name);
++ __symbol_put(ksym_name);
+ printk(KERN_INFO "HW Breakpoint for %s write uninstalled\n", ksym_name);
+ }
+
+--
+2.40.1
+
--- /dev/null
+From 6a7aad339ae004003f8a3665493477c18b05ae45 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 15 May 2023 19:00:10 -0700
+Subject: scftorture: Forgive memory-allocation failure if KASAN
+
+From: Paul E. McKenney <paulmck@kernel.org>
+
+[ Upstream commit 013608cd0812bdb21fc26d39ed8fdd2fc76e8b9b ]
+
+Kernels built with CONFIG_KASAN=y quarantine newly freed memory in order
+to better detect use-after-free errors. However, this can exhaust memory
+more quickly in allocator-heavy tests, which can result in spurious
+scftorture failure. This commit therefore forgives memory-allocation
+failure in kernels built with CONFIG_KASAN=y, but continues counting
+the errors for use in detailed test-result analyses.
+
+Signed-off-by: Paul E. McKenney <paulmck@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ kernel/scftorture.c | 6 ++++--
+ 1 file changed, 4 insertions(+), 2 deletions(-)
+
+diff --git a/kernel/scftorture.c b/kernel/scftorture.c
+index 5d113aa59e773..83c33ba0ca7e0 100644
+--- a/kernel/scftorture.c
++++ b/kernel/scftorture.c
+@@ -171,7 +171,8 @@ static void scf_torture_stats_print(void)
+ scfs.n_all_wait += scf_stats_p[i].n_all_wait;
+ }
+ if (atomic_read(&n_errs) || atomic_read(&n_mb_in_errs) ||
+- atomic_read(&n_mb_out_errs) || atomic_read(&n_alloc_errs))
++ atomic_read(&n_mb_out_errs) ||
++ (!IS_ENABLED(CONFIG_KASAN) && atomic_read(&n_alloc_errs)))
+ bangstr = "!!! ";
+ pr_alert("%s %sscf_invoked_count %s: %lld resched: %lld single: %lld/%lld single_ofl: %lld/%lld single_rpc: %lld single_rpc_ofl: %lld many: %lld/%lld all: %lld/%lld ",
+ SCFTORT_FLAG, bangstr, isdone ? "VER" : "ver", invoked_count, scfs.n_resched,
+@@ -323,7 +324,8 @@ static void scftorture_invoke_one(struct scf_statistics *scfp, struct torture_ra
+ preempt_disable();
+ if (scfsp->scfs_prim == SCF_PRIM_SINGLE || scfsp->scfs_wait) {
+ scfcp = kmalloc(sizeof(*scfcp), GFP_ATOMIC);
+- if (WARN_ON_ONCE(!scfcp)) {
++ if (!scfcp) {
++ WARN_ON_ONCE(!IS_ENABLED(CONFIG_KASAN));
+ atomic_inc(&n_alloc_errs);
+ } else {
+ scfcp->scfc_cpu = -1;
+--
+2.40.1
+
--- /dev/null
+From 2187bc313549c1073deb3830fb7e7874e8677da1 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 12 Jul 2023 11:05:18 -0700
+Subject: scsi: lpfc: Abort outstanding ELS cmds when mailbox timeout error is
+ detected
+
+From: Justin Tee <justin.tee@broadcom.com>
+
+[ Upstream commit 089ea22e374aa20043e72243c47b5867d5419d38 ]
+
+A mailbox timeout error usually indicates something has gone wrong, and a
+follow up reset of the HBA is a typical recovery mechanism. Introduce a
+MBX_TMO_ERR flag to detect such cases and have lpfc_els_flush_cmd abort ELS
+commands if the MBX_TMO_ERR flag condition was set. This ensures all of
+the registered SGL resources meant for ELS traffic are not leaked after an
+HBA reset.
+
+Signed-off-by: Justin Tee <justin.tee@broadcom.com>
+Link: https://lore.kernel.org/r/20230712180522.112722-9-justintee8345@gmail.com
+Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/scsi/lpfc/lpfc.h | 1 +
+ drivers/scsi/lpfc/lpfc_els.c | 25 ++++++++++++++++++-------
+ drivers/scsi/lpfc/lpfc_init.c | 20 +++++++++++++++++---
+ drivers/scsi/lpfc/lpfc_sli.c | 8 +++++++-
+ 4 files changed, 43 insertions(+), 11 deletions(-)
+
+diff --git a/drivers/scsi/lpfc/lpfc.h b/drivers/scsi/lpfc/lpfc.h
+index 9a89636843693..e8d7eeeb21856 100644
+--- a/drivers/scsi/lpfc/lpfc.h
++++ b/drivers/scsi/lpfc/lpfc.h
+@@ -872,6 +872,7 @@ enum lpfc_irq_chann_mode {
+ enum lpfc_hba_bit_flags {
+ FABRIC_COMANDS_BLOCKED,
+ HBA_PCI_ERR,
++ MBX_TMO_ERR,
+ };
+
+ struct lpfc_hba {
+diff --git a/drivers/scsi/lpfc/lpfc_els.c b/drivers/scsi/lpfc/lpfc_els.c
+index 2bad9954c355f..6f6ef5235ee3b 100644
+--- a/drivers/scsi/lpfc/lpfc_els.c
++++ b/drivers/scsi/lpfc/lpfc_els.c
+@@ -9588,11 +9588,13 @@ void
+ lpfc_els_flush_cmd(struct lpfc_vport *vport)
+ {
+ LIST_HEAD(abort_list);
++ LIST_HEAD(cancel_list);
+ struct lpfc_hba *phba = vport->phba;
+ struct lpfc_sli_ring *pring;
+ struct lpfc_iocbq *tmp_iocb, *piocb;
+ u32 ulp_command;
+ unsigned long iflags = 0;
++ bool mbx_tmo_err;
+
+ lpfc_fabric_abort_vport(vport);
+
+@@ -9614,15 +9616,16 @@ lpfc_els_flush_cmd(struct lpfc_vport *vport)
+ if (phba->sli_rev == LPFC_SLI_REV4)
+ spin_lock(&pring->ring_lock);
+
++ mbx_tmo_err = test_bit(MBX_TMO_ERR, &phba->bit_flags);
+ /* First we need to issue aborts to outstanding cmds on txcmpl */
+ list_for_each_entry_safe(piocb, tmp_iocb, &pring->txcmplq, list) {
+- if (piocb->cmd_flag & LPFC_IO_LIBDFC)
++ if (piocb->cmd_flag & LPFC_IO_LIBDFC && !mbx_tmo_err)
+ continue;
+
+ if (piocb->vport != vport)
+ continue;
+
+- if (piocb->cmd_flag & LPFC_DRIVER_ABORTED)
++ if (piocb->cmd_flag & LPFC_DRIVER_ABORTED && !mbx_tmo_err)
+ continue;
+
+ /* On the ELS ring we can have ELS_REQUESTs or
+@@ -9641,8 +9644,8 @@ lpfc_els_flush_cmd(struct lpfc_vport *vport)
+ */
+ if (phba->link_state == LPFC_LINK_DOWN)
+ piocb->cmd_cmpl = lpfc_cmpl_els_link_down;
+- }
+- if (ulp_command == CMD_GEN_REQUEST64_CR)
++ } else if (ulp_command == CMD_GEN_REQUEST64_CR ||
++ mbx_tmo_err)
+ list_add_tail(&piocb->dlist, &abort_list);
+ }
+
+@@ -9654,11 +9657,19 @@ lpfc_els_flush_cmd(struct lpfc_vport *vport)
+ list_for_each_entry_safe(piocb, tmp_iocb, &abort_list, dlist) {
+ spin_lock_irqsave(&phba->hbalock, iflags);
+ list_del_init(&piocb->dlist);
+- lpfc_sli_issue_abort_iotag(phba, pring, piocb, NULL);
++ if (mbx_tmo_err)
++ list_move_tail(&piocb->list, &cancel_list);
++ else
++ lpfc_sli_issue_abort_iotag(phba, pring, piocb, NULL);
++
+ spin_unlock_irqrestore(&phba->hbalock, iflags);
+ }
+- /* Make sure HBA is alive */
+- lpfc_issue_hb_tmo(phba);
++ if (!list_empty(&cancel_list))
++ lpfc_sli_cancel_iocbs(phba, &cancel_list, IOSTAT_LOCAL_REJECT,
++ IOERR_SLI_ABORTED);
++ else
++ /* Make sure HBA is alive */
++ lpfc_issue_hb_tmo(phba);
+
+ if (!list_empty(&abort_list))
+ lpfc_printf_vlog(vport, KERN_ERR, LOG_TRACE_EVENT,
+diff --git a/drivers/scsi/lpfc/lpfc_init.c b/drivers/scsi/lpfc/lpfc_init.c
+index 3221a934066bb..ce9e4cdd6004c 100644
+--- a/drivers/scsi/lpfc/lpfc_init.c
++++ b/drivers/scsi/lpfc/lpfc_init.c
+@@ -7550,6 +7550,8 @@ lpfc_disable_pci_dev(struct lpfc_hba *phba)
+ void
+ lpfc_reset_hba(struct lpfc_hba *phba)
+ {
++ int rc = 0;
++
+ /* If resets are disabled then set error state and return. */
+ if (!phba->cfg_enable_hba_reset) {
+ phba->link_state = LPFC_HBA_ERROR;
+@@ -7560,13 +7562,25 @@ lpfc_reset_hba(struct lpfc_hba *phba)
+ if (phba->sli.sli_flag & LPFC_SLI_ACTIVE) {
+ lpfc_offline_prep(phba, LPFC_MBX_WAIT);
+ } else {
++ if (test_bit(MBX_TMO_ERR, &phba->bit_flags)) {
++ /* Perform a PCI function reset to start from clean */
++ rc = lpfc_pci_function_reset(phba);
++ lpfc_els_flush_all_cmd(phba);
++ }
+ lpfc_offline_prep(phba, LPFC_MBX_NO_WAIT);
+ lpfc_sli_flush_io_rings(phba);
+ }
+ lpfc_offline(phba);
+- lpfc_sli_brdrestart(phba);
+- lpfc_online(phba);
+- lpfc_unblock_mgmt_io(phba);
++ clear_bit(MBX_TMO_ERR, &phba->bit_flags);
++ if (unlikely(rc)) {
++ lpfc_printf_log(phba, KERN_ERR, LOG_SLI,
++ "8888 PCI function reset failed rc %x\n",
++ rc);
++ } else {
++ lpfc_sli_brdrestart(phba);
++ lpfc_online(phba);
++ lpfc_unblock_mgmt_io(phba);
++ }
+ }
+
+ /**
+diff --git a/drivers/scsi/lpfc/lpfc_sli.c b/drivers/scsi/lpfc/lpfc_sli.c
+index 58d10f8f75a78..4dfadf254a727 100644
+--- a/drivers/scsi/lpfc/lpfc_sli.c
++++ b/drivers/scsi/lpfc/lpfc_sli.c
+@@ -3935,6 +3935,8 @@ void lpfc_poll_eratt(struct timer_list *t)
+ uint64_t sli_intr, cnt;
+
+ phba = from_timer(phba, t, eratt_poll);
++ if (!(phba->hba_flag & HBA_SETUP))
++ return;
+
+ /* Here we will also keep track of interrupts per sec of the hba */
+ sli_intr = phba->sli.slistat.sli_intr;
+@@ -7693,7 +7695,9 @@ lpfc_sli4_repost_sgl_list(struct lpfc_hba *phba,
+ spin_unlock_irq(&phba->hbalock);
+ } else {
+ lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
+- "3161 Failure to post sgl to port.\n");
++ "3161 Failure to post sgl to port,status %x "
++ "blkcnt %d totalcnt %d postcnt %d\n",
++ status, block_cnt, total_cnt, post_cnt);
+ return -EIO;
+ }
+
+@@ -8478,6 +8482,7 @@ lpfc_sli4_hba_setup(struct lpfc_hba *phba)
+ spin_unlock_irq(&phba->hbalock);
+ }
+ }
++ phba->hba_flag &= ~HBA_SETUP;
+
+ lpfc_sli4_dip(phba);
+
+@@ -9282,6 +9287,7 @@ lpfc_mbox_timeout_handler(struct lpfc_hba *phba)
+ * would get IOCB_ERROR from lpfc_sli_issue_iocb, allowing
+ * it to fail all outstanding SCSI IO.
+ */
++ set_bit(MBX_TMO_ERR, &phba->bit_flags);
+ spin_lock_irq(&phba->pport->work_port_lock);
+ phba->pport->work_port_events &= ~WORKER_MBOX_TMO;
+ spin_unlock_irq(&phba->pport->work_port_lock);
+--
+2.40.1
+
--- /dev/null
+From 2d9a9d4edb3f6718aa424da11c619550542c9889 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 6 Sep 2023 11:08:09 +0800
+Subject: scsi: lpfc: Fix the NULL vs IS_ERR() bug for debugfs_create_file()
+
+From: Jinjie Ruan <ruanjinjie@huawei.com>
+
+[ Upstream commit 7dcc683db3639eadd11bf0d59a09088a43de5e22 ]
+
+Since debugfs_create_file() returns ERR_PTR and never NULL, use IS_ERR() to
+check the return value.
+
+Fixes: 2fcbc569b9f5 ("scsi: lpfc: Make debugfs ktime stats generic for NVME and SCSI")
+Fixes: 4c47efc140fa ("scsi: lpfc: Move SCSI and NVME Stats to hardware queue structures")
+Fixes: 6a828b0f6192 ("scsi: lpfc: Support non-uniform allocation of MSIX vectors to hardware queues")
+Fixes: 95bfc6d8ad86 ("scsi: lpfc: Make FW logging dynamically configurable")
+Fixes: 9f77870870d8 ("scsi: lpfc: Add debugfs support for cm framework buffers")
+Fixes: c490850a0947 ("scsi: lpfc: Adapt partitioned XRI lists to efficient sharing")
+Signed-off-by: Jinjie Ruan <ruanjinjie@huawei.com>
+Link: https://lore.kernel.org/r/20230906030809.2847970-1-ruanjinjie@huawei.com
+Reviewed-by: Justin Tee <justin.tee@broadcom.com>
+Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/scsi/lpfc/lpfc_debugfs.c | 14 +++++++-------
+ 1 file changed, 7 insertions(+), 7 deletions(-)
+
+diff --git a/drivers/scsi/lpfc/lpfc_debugfs.c b/drivers/scsi/lpfc/lpfc_debugfs.c
+index 7f9b221e7c34a..ea9b42225e629 100644
+--- a/drivers/scsi/lpfc/lpfc_debugfs.c
++++ b/drivers/scsi/lpfc/lpfc_debugfs.c
+@@ -6073,7 +6073,7 @@ lpfc_debugfs_initialize(struct lpfc_vport *vport)
+ phba->hba_debugfs_root,
+ phba,
+ &lpfc_debugfs_op_multixripools);
+- if (!phba->debug_multixri_pools) {
++ if (IS_ERR(phba->debug_multixri_pools)) {
+ lpfc_printf_vlog(vport, KERN_ERR, LOG_INIT,
+ "0527 Cannot create debugfs multixripools\n");
+ goto debug_failed;
+@@ -6085,7 +6085,7 @@ lpfc_debugfs_initialize(struct lpfc_vport *vport)
+ debugfs_create_file(name, S_IFREG | 0644,
+ phba->hba_debugfs_root,
+ phba, &lpfc_cgn_buffer_op);
+- if (!phba->debug_cgn_buffer) {
++ if (IS_ERR(phba->debug_cgn_buffer)) {
+ lpfc_printf_vlog(vport, KERN_ERR, LOG_INIT,
+ "6527 Cannot create debugfs "
+ "cgn_buffer\n");
+@@ -6098,7 +6098,7 @@ lpfc_debugfs_initialize(struct lpfc_vport *vport)
+ debugfs_create_file(name, S_IFREG | 0644,
+ phba->hba_debugfs_root,
+ phba, &lpfc_rx_monitor_op);
+- if (!phba->debug_rx_monitor) {
++ if (IS_ERR(phba->debug_rx_monitor)) {
+ lpfc_printf_vlog(vport, KERN_ERR, LOG_INIT,
+ "6528 Cannot create debugfs "
+ "rx_monitor\n");
+@@ -6111,7 +6111,7 @@ lpfc_debugfs_initialize(struct lpfc_vport *vport)
+ debugfs_create_file(name, 0644,
+ phba->hba_debugfs_root,
+ phba, &lpfc_debugfs_ras_log);
+- if (!phba->debug_ras_log) {
++ if (IS_ERR(phba->debug_ras_log)) {
+ lpfc_printf_vlog(vport, KERN_ERR, LOG_INIT,
+ "6148 Cannot create debugfs"
+ " ras_log\n");
+@@ -6132,7 +6132,7 @@ lpfc_debugfs_initialize(struct lpfc_vport *vport)
+ debugfs_create_file(name, S_IFREG | 0644,
+ phba->hba_debugfs_root,
+ phba, &lpfc_debugfs_op_lockstat);
+- if (!phba->debug_lockstat) {
++ if (IS_ERR(phba->debug_lockstat)) {
+ lpfc_printf_vlog(vport, KERN_ERR, LOG_INIT,
+ "4610 Can't create debugfs lockstat\n");
+ goto debug_failed;
+@@ -6358,7 +6358,7 @@ lpfc_debugfs_initialize(struct lpfc_vport *vport)
+ debugfs_create_file(name, 0644,
+ vport->vport_debugfs_root,
+ vport, &lpfc_debugfs_op_scsistat);
+- if (!vport->debug_scsistat) {
++ if (IS_ERR(vport->debug_scsistat)) {
+ lpfc_printf_vlog(vport, KERN_ERR, LOG_INIT,
+ "4611 Cannot create debugfs scsistat\n");
+ goto debug_failed;
+@@ -6369,7 +6369,7 @@ lpfc_debugfs_initialize(struct lpfc_vport *vport)
+ debugfs_create_file(name, 0644,
+ vport->vport_debugfs_root,
+ vport, &lpfc_debugfs_op_ioktime);
+- if (!vport->debug_ioktime) {
++ if (IS_ERR(vport->debug_ioktime)) {
+ lpfc_printf_vlog(vport, KERN_ERR, LOG_INIT,
+ "0815 Cannot create debugfs ioktime\n");
+ goto debug_failed;
+--
+2.40.1
+
--- /dev/null
+From 9f0205633022384a4bbf6775d1395d311b28f4ac Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 31 Aug 2023 22:09:29 +0800
+Subject: scsi: qla2xxx: Fix NULL vs IS_ERR() bug for debugfs_create_dir()
+
+From: Jinjie Ruan <ruanjinjie@huawei.com>
+
+[ Upstream commit d0b0822e32dbae80bbcb3cc86f34d28539d913df ]
+
+Since both debugfs_create_dir() and debugfs_create_file() return ERR_PTR
+and never NULL, use IS_ERR() instead of checking for NULL.
+
+Fixes: 1e98fb0f9208 ("scsi: qla2xxx: Setup debugfs entries for remote ports")
+Signed-off-by: Jinjie Ruan <ruanjinjie@huawei.com>
+Link: https://lore.kernel.org/r/20230831140930.3166359-1-ruanjinjie@huawei.com
+Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/scsi/qla2xxx/qla_dfs.c | 6 +++---
+ 1 file changed, 3 insertions(+), 3 deletions(-)
+
+diff --git a/drivers/scsi/qla2xxx/qla_dfs.c b/drivers/scsi/qla2xxx/qla_dfs.c
+index f060e593685de..a7a364760b800 100644
+--- a/drivers/scsi/qla2xxx/qla_dfs.c
++++ b/drivers/scsi/qla2xxx/qla_dfs.c
+@@ -116,7 +116,7 @@ qla2x00_dfs_create_rport(scsi_qla_host_t *vha, struct fc_port *fp)
+
+ sprintf(wwn, "pn-%016llx", wwn_to_u64(fp->port_name));
+ fp->dfs_rport_dir = debugfs_create_dir(wwn, vha->dfs_rport_root);
+- if (!fp->dfs_rport_dir)
++ if (IS_ERR(fp->dfs_rport_dir))
+ return;
+ if (NVME_TARGET(vha->hw, fp))
+ debugfs_create_file("dev_loss_tmo", 0600, fp->dfs_rport_dir,
+@@ -708,14 +708,14 @@ qla2x00_dfs_setup(scsi_qla_host_t *vha)
+ if (IS_QLA27XX(ha) || IS_QLA83XX(ha) || IS_QLA28XX(ha)) {
+ ha->tgt.dfs_naqp = debugfs_create_file("naqp",
+ 0400, ha->dfs_dir, vha, &dfs_naqp_ops);
+- if (!ha->tgt.dfs_naqp) {
++ if (IS_ERR(ha->tgt.dfs_naqp)) {
+ ql_log(ql_log_warn, vha, 0xd011,
+ "Unable to create debugFS naqp node.\n");
+ goto out;
+ }
+ }
+ vha->dfs_rport_root = debugfs_create_dir("rports", ha->dfs_dir);
+- if (!vha->dfs_rport_root) {
++ if (IS_ERR(vha->dfs_rport_root)) {
+ ql_log(ql_log_warn, vha, 0xd012,
+ "Unable to create debugFS rports node.\n");
+ goto out;
+--
+2.40.1
+
--- /dev/null
+From 3fb20f5d58c67804613e5be3f859b43ca86c60f4 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 31 Aug 2023 20:34:59 +0200
+Subject: scsi: target: core: Fix target_cmd_counter leak
+
+From: David Disseldorp <ddiss@suse.de>
+
+[ Upstream commit d14e3e553e05cb763964c991fe6acb0a6a1c6f9c ]
+
+The target_cmd_counter struct allocated via target_alloc_cmd_counter() is
+never freed, resulting in leaks across various transport types, e.g.:
+
+ unreferenced object 0xffff88801f920120 (size 96):
+ comm "sh", pid 102, jiffies 4294892535 (age 713.412s)
+ hex dump (first 32 bytes):
+ 07 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
+ 00 00 00 00 00 00 00 00 38 01 92 1f 80 88 ff ff ........8.......
+ backtrace:
+ [<00000000e58a6252>] kmalloc_trace+0x11/0x20
+ [<0000000043af4b2f>] target_alloc_cmd_counter+0x17/0x90 [target_core_mod]
+ [<000000007da2dfa7>] target_setup_session+0x2d/0x140 [target_core_mod]
+ [<0000000068feef86>] tcm_loop_tpg_nexus_store+0x19b/0x350 [tcm_loop]
+ [<000000006a80e021>] configfs_write_iter+0xb1/0x120
+ [<00000000e9f4d860>] vfs_write+0x2e4/0x3c0
+ [<000000008143433b>] ksys_write+0x80/0xb0
+ [<00000000a7df29b2>] do_syscall_64+0x42/0x90
+ [<0000000053f45fb8>] entry_SYSCALL_64_after_hwframe+0x6e/0xd8
+
+Free the structure alongside the corresponding iscsit_conn / se_sess
+parent.
+
+Signed-off-by: David Disseldorp <ddiss@suse.de>
+Link: https://lore.kernel.org/r/20230831183459.6938-1-ddiss@suse.de
+Fixes: becd9be6069e ("scsi: target: Move sess cmd counter to new struct")
+Reviewed-by: Mike Christie <michael.christie@oracle.com>
+Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/target/target_core_transport.c | 1 +
+ 1 file changed, 1 insertion(+)
+
+diff --git a/drivers/target/target_core_transport.c b/drivers/target/target_core_transport.c
+index 687adc9e086ca..0686882bcbda3 100644
+--- a/drivers/target/target_core_transport.c
++++ b/drivers/target/target_core_transport.c
+@@ -264,6 +264,7 @@ void target_free_cmd_counter(struct target_cmd_counter *cmd_cnt)
+ percpu_ref_put(&cmd_cnt->refcnt);
+
+ percpu_ref_exit(&cmd_cnt->refcnt);
++ kfree(cmd_cnt);
+ }
+ EXPORT_SYMBOL_GPL(target_free_cmd_counter);
+
+--
+2.40.1
+
--- /dev/null
+From 57ba3e34f49f8c3b0ff1ba194aa0f5c037344c4d Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sat, 22 Jul 2023 18:26:37 +0300
+Subject: scsi: target: iscsi: Fix buffer overflow in
+ lio_target_nacl_info_show()
+
+From: Konstantin Shelekhin <k.shelekhin@yadro.com>
+
+[ Upstream commit 801f287c93ff95582b0a2d2163f12870a2f076d4 ]
+
+The function lio_target_nacl_info_show() uses sprintf() in a loop to print
+details for every iSCSI connection in a session without checking for the
+buffer length. With enough iSCSI connections it's possible to overflow the
+buffer provided by configfs and corrupt the memory.
+
+This patch replaces sprintf() with sysfs_emit_at() that checks for buffer
+boundries.
+
+Signed-off-by: Konstantin Shelekhin <k.shelekhin@yadro.com>
+Link: https://lore.kernel.org/r/20230722152657.168859-2-k.shelekhin@yadro.com
+Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/target/iscsi/iscsi_target_configfs.c | 54 ++++++++++----------
+ 1 file changed, 27 insertions(+), 27 deletions(-)
+
+diff --git a/drivers/target/iscsi/iscsi_target_configfs.c b/drivers/target/iscsi/iscsi_target_configfs.c
+index 5d0f51822414e..c142a67dc7cc2 100644
+--- a/drivers/target/iscsi/iscsi_target_configfs.c
++++ b/drivers/target/iscsi/iscsi_target_configfs.c
+@@ -533,102 +533,102 @@ static ssize_t lio_target_nacl_info_show(struct config_item *item, char *page)
+ spin_lock_bh(&se_nacl->nacl_sess_lock);
+ se_sess = se_nacl->nacl_sess;
+ if (!se_sess) {
+- rb += sprintf(page+rb, "No active iSCSI Session for Initiator"
++ rb += sysfs_emit_at(page, rb, "No active iSCSI Session for Initiator"
+ " Endpoint: %s\n", se_nacl->initiatorname);
+ } else {
+ sess = se_sess->fabric_sess_ptr;
+
+- rb += sprintf(page+rb, "InitiatorName: %s\n",
++ rb += sysfs_emit_at(page, rb, "InitiatorName: %s\n",
+ sess->sess_ops->InitiatorName);
+- rb += sprintf(page+rb, "InitiatorAlias: %s\n",
++ rb += sysfs_emit_at(page, rb, "InitiatorAlias: %s\n",
+ sess->sess_ops->InitiatorAlias);
+
+- rb += sprintf(page+rb,
++ rb += sysfs_emit_at(page, rb,
+ "LIO Session ID: %u ISID: 0x%6ph TSIH: %hu ",
+ sess->sid, sess->isid, sess->tsih);
+- rb += sprintf(page+rb, "SessionType: %s\n",
++ rb += sysfs_emit_at(page, rb, "SessionType: %s\n",
+ (sess->sess_ops->SessionType) ?
+ "Discovery" : "Normal");
+- rb += sprintf(page+rb, "Session State: ");
++ rb += sysfs_emit_at(page, rb, "Session State: ");
+ switch (sess->session_state) {
+ case TARG_SESS_STATE_FREE:
+- rb += sprintf(page+rb, "TARG_SESS_FREE\n");
++ rb += sysfs_emit_at(page, rb, "TARG_SESS_FREE\n");
+ break;
+ case TARG_SESS_STATE_ACTIVE:
+- rb += sprintf(page+rb, "TARG_SESS_STATE_ACTIVE\n");
++ rb += sysfs_emit_at(page, rb, "TARG_SESS_STATE_ACTIVE\n");
+ break;
+ case TARG_SESS_STATE_LOGGED_IN:
+- rb += sprintf(page+rb, "TARG_SESS_STATE_LOGGED_IN\n");
++ rb += sysfs_emit_at(page, rb, "TARG_SESS_STATE_LOGGED_IN\n");
+ break;
+ case TARG_SESS_STATE_FAILED:
+- rb += sprintf(page+rb, "TARG_SESS_STATE_FAILED\n");
++ rb += sysfs_emit_at(page, rb, "TARG_SESS_STATE_FAILED\n");
+ break;
+ case TARG_SESS_STATE_IN_CONTINUE:
+- rb += sprintf(page+rb, "TARG_SESS_STATE_IN_CONTINUE\n");
++ rb += sysfs_emit_at(page, rb, "TARG_SESS_STATE_IN_CONTINUE\n");
+ break;
+ default:
+- rb += sprintf(page+rb, "ERROR: Unknown Session"
++ rb += sysfs_emit_at(page, rb, "ERROR: Unknown Session"
+ " State!\n");
+ break;
+ }
+
+- rb += sprintf(page+rb, "---------------------[iSCSI Session"
++ rb += sysfs_emit_at(page, rb, "---------------------[iSCSI Session"
+ " Values]-----------------------\n");
+- rb += sprintf(page+rb, " CmdSN/WR : CmdSN/WC : ExpCmdSN"
++ rb += sysfs_emit_at(page, rb, " CmdSN/WR : CmdSN/WC : ExpCmdSN"
+ " : MaxCmdSN : ITT : TTT\n");
+ max_cmd_sn = (u32) atomic_read(&sess->max_cmd_sn);
+- rb += sprintf(page+rb, " 0x%08x 0x%08x 0x%08x 0x%08x"
++ rb += sysfs_emit_at(page, rb, " 0x%08x 0x%08x 0x%08x 0x%08x"
+ " 0x%08x 0x%08x\n",
+ sess->cmdsn_window,
+ (max_cmd_sn - sess->exp_cmd_sn) + 1,
+ sess->exp_cmd_sn, max_cmd_sn,
+ sess->init_task_tag, sess->targ_xfer_tag);
+- rb += sprintf(page+rb, "----------------------[iSCSI"
++ rb += sysfs_emit_at(page, rb, "----------------------[iSCSI"
+ " Connections]-------------------------\n");
+
+ spin_lock(&sess->conn_lock);
+ list_for_each_entry(conn, &sess->sess_conn_list, conn_list) {
+- rb += sprintf(page+rb, "CID: %hu Connection"
++ rb += sysfs_emit_at(page, rb, "CID: %hu Connection"
+ " State: ", conn->cid);
+ switch (conn->conn_state) {
+ case TARG_CONN_STATE_FREE:
+- rb += sprintf(page+rb,
++ rb += sysfs_emit_at(page, rb,
+ "TARG_CONN_STATE_FREE\n");
+ break;
+ case TARG_CONN_STATE_XPT_UP:
+- rb += sprintf(page+rb,
++ rb += sysfs_emit_at(page, rb,
+ "TARG_CONN_STATE_XPT_UP\n");
+ break;
+ case TARG_CONN_STATE_IN_LOGIN:
+- rb += sprintf(page+rb,
++ rb += sysfs_emit_at(page, rb,
+ "TARG_CONN_STATE_IN_LOGIN\n");
+ break;
+ case TARG_CONN_STATE_LOGGED_IN:
+- rb += sprintf(page+rb,
++ rb += sysfs_emit_at(page, rb,
+ "TARG_CONN_STATE_LOGGED_IN\n");
+ break;
+ case TARG_CONN_STATE_IN_LOGOUT:
+- rb += sprintf(page+rb,
++ rb += sysfs_emit_at(page, rb,
+ "TARG_CONN_STATE_IN_LOGOUT\n");
+ break;
+ case TARG_CONN_STATE_LOGOUT_REQUESTED:
+- rb += sprintf(page+rb,
++ rb += sysfs_emit_at(page, rb,
+ "TARG_CONN_STATE_LOGOUT_REQUESTED\n");
+ break;
+ case TARG_CONN_STATE_CLEANUP_WAIT:
+- rb += sprintf(page+rb,
++ rb += sysfs_emit_at(page, rb,
+ "TARG_CONN_STATE_CLEANUP_WAIT\n");
+ break;
+ default:
+- rb += sprintf(page+rb,
++ rb += sysfs_emit_at(page, rb,
+ "ERROR: Unknown Connection State!\n");
+ break;
+ }
+
+- rb += sprintf(page+rb, " Address %pISc %s", &conn->login_sockaddr,
++ rb += sysfs_emit_at(page, rb, " Address %pISc %s", &conn->login_sockaddr,
+ (conn->network_transport == ISCSI_TCP) ?
+ "TCP" : "SCTP");
+- rb += sprintf(page+rb, " StatSN: 0x%08x\n",
++ rb += sysfs_emit_at(page, rb, " StatSN: 0x%08x\n",
+ conn->stat_sn);
+ }
+ spin_unlock(&sess->conn_lock);
+--
+2.40.1
+
--- /dev/null
+From 4c21f60f069e19e2bc7cea87f9e40c4c7846fd1a Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sat, 8 Jul 2023 02:32:05 +0800
+Subject: selftests/nolibc: fix up kernel parameters support
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Zhangjin Wu <falcon@tinylab.org>
+
+[ Upstream commit c388c9920da2679f62bec48d00ca9e80e9d0a364 ]
+
+kernel parameters allow pass two types of strings, one type is like
+'noapic', another type is like 'panic=5', the first type is passed as
+arguments of the init program, the second type is passed as environment
+variables of the init program.
+
+when users pass kernel parameters like this:
+
+ noapic NOLIBC_TEST=syscall
+
+our nolibc-test program will use the test setting from argv[1] and
+ignore the one from NOLIBC_TEST environment variable, and at last, it
+will print the following line and ignore the whole test setting.
+
+ Ignoring unknown test name 'noapic'
+
+reversing the parsing order does solve the above issue:
+
+ test = getenv("NOLIBC_TEST");
+ if (test)
+ test = argv[1];
+
+but it still doesn't work with such kernel parameters (without
+NOLIBC_TEST environment variable):
+
+ noapic FOO=bar
+
+To support all of the potential kernel parameters, let's verify the test
+setting from both of argv[1] and NOLIBC_TEST environment variable.
+
+Reviewed-by: Thomas Weißschuh <linux@weissschuh.net>
+Signed-off-by: Zhangjin Wu <falcon@tinylab.org>
+Signed-off-by: Willy Tarreau <w@1wt.eu>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ tools/testing/selftests/nolibc/nolibc-test.c | 33 ++++++++++++++++++--
+ 1 file changed, 31 insertions(+), 2 deletions(-)
+
+diff --git a/tools/testing/selftests/nolibc/nolibc-test.c b/tools/testing/selftests/nolibc/nolibc-test.c
+index 486334981e601..55628a25df0a3 100644
+--- a/tools/testing/selftests/nolibc/nolibc-test.c
++++ b/tools/testing/selftests/nolibc/nolibc-test.c
+@@ -939,6 +939,35 @@ static const struct test test_names[] = {
+ { 0 }
+ };
+
++int is_setting_valid(char *test)
++{
++ int idx, len, test_len, valid = 0;
++ char delimiter;
++
++ if (!test)
++ return valid;
++
++ test_len = strlen(test);
++
++ for (idx = 0; test_names[idx].name; idx++) {
++ len = strlen(test_names[idx].name);
++ if (test_len < len)
++ continue;
++
++ if (strncmp(test, test_names[idx].name, len) != 0)
++ continue;
++
++ delimiter = test[len];
++ if (delimiter != ':' && delimiter != ',' && delimiter != '\0')
++ continue;
++
++ valid = 1;
++ break;
++ }
++
++ return valid;
++}
++
+ int main(int argc, char **argv, char **envp)
+ {
+ int min = 0;
+@@ -964,10 +993,10 @@ int main(int argc, char **argv, char **envp)
+ * syscall:5-15[:.*],stdlib:8-10
+ */
+ test = argv[1];
+- if (!test)
++ if (!is_setting_valid(test))
+ test = getenv("NOLIBC_TEST");
+
+- if (test) {
++ if (is_setting_valid(test)) {
+ char *comma, *colon, *dash, *value;
+
+ do {
+--
+2.40.1
+
--- /dev/null
+From a3989fb1685f3d178bc255e9303e651ddabc332b Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 3 Aug 2023 09:28:56 +0200
+Subject: selftests/nolibc: prevent out of bounds access in expect_vfprintf
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Thomas Weißschuh <linux@weissschuh.net>
+
+[ Upstream commit 9c5e490093e83e165022e0311bd7df5aa06cc860 ]
+
+If read() fails and returns -1 (or returns garbage for some other
+reason) buf would be accessed out of bounds.
+Only use the return value of read() after it has been validated.
+
+Signed-off-by: Thomas Weißschuh <linux@weissschuh.net>
+Signed-off-by: Willy Tarreau <w@1wt.eu>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ tools/testing/selftests/nolibc/nolibc-test.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/tools/testing/selftests/nolibc/nolibc-test.c b/tools/testing/selftests/nolibc/nolibc-test.c
+index 55628a25df0a3..8e7750e2eb97c 100644
+--- a/tools/testing/selftests/nolibc/nolibc-test.c
++++ b/tools/testing/selftests/nolibc/nolibc-test.c
+@@ -769,7 +769,6 @@ static int expect_vfprintf(int llen, size_t c, const char *expected, const char
+ lseek(fd, 0, SEEK_SET);
+
+ r = read(fd, buf, sizeof(buf) - 1);
+- buf[r] = '\0';
+
+ fclose(memfile);
+
+@@ -779,6 +778,7 @@ static int expect_vfprintf(int llen, size_t c, const char *expected, const char
+ return 1;
+ }
+
++ buf[r] = '\0';
+ llen += printf(" \"%s\" = \"%s\"", expected, buf);
+ ret = strncmp(expected, buf, c);
+
+--
+2.40.1
+
--- /dev/null
+From 5d4aabb99b46d389364bd8693b0bbc08a801898a Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 12 Sep 2023 10:10:39 +0900
+Subject: selftests: tracing: Fix to unmount tracefs for recovering environment
+
+From: Masami Hiramatsu (Google) <mhiramat@kernel.org>
+
+[ Upstream commit 7e021da80f48582171029714f8a487347f29dddb ]
+
+Fix to unmount the tracefs if the ftracetest mounted it for recovering
+system environment. If the tracefs is already mounted, this does nothing.
+
+Suggested-by: Mark Brown <broonie@kernel.org>
+Link: https://lore.kernel.org/all/29fce076-746c-4650-8358-b4e0fa215cf7@sirena.org.uk/
+Fixes: cbd965bde74c ("ftrace/selftests: Return the skip code when tracing directory not configured in kernel")
+Signed-off-by: Masami Hiramatsu (Google) <mhiramat@kernel.org>
+Reviewed-by: Steven Rostedt (Google) <rostedt@goodmis.org>
+Reviewed-by: Mark Brown <broonie@kernel.org>
+Signed-off-by: Shuah Khan <skhan@linuxfoundation.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ tools/testing/selftests/ftrace/ftracetest | 8 ++++++++
+ 1 file changed, 8 insertions(+)
+
+diff --git a/tools/testing/selftests/ftrace/ftracetest b/tools/testing/selftests/ftrace/ftracetest
+index cb5f18c06593d..d68264a5f3f03 100755
+--- a/tools/testing/selftests/ftrace/ftracetest
++++ b/tools/testing/selftests/ftrace/ftracetest
+@@ -31,6 +31,9 @@ err_ret=1
+ # kselftest skip code is 4
+ err_skip=4
+
++# umount required
++UMOUNT_DIR=""
++
+ # cgroup RT scheduling prevents chrt commands from succeeding, which
+ # induces failures in test wakeup tests. Disable for the duration of
+ # the tests.
+@@ -45,6 +48,9 @@ setup() {
+
+ cleanup() {
+ echo $sched_rt_runtime_orig > $sched_rt_runtime
++ if [ -n "${UMOUNT_DIR}" ]; then
++ umount ${UMOUNT_DIR} ||:
++ fi
+ }
+
+ errexit() { # message
+@@ -160,11 +166,13 @@ if [ -z "$TRACING_DIR" ]; then
+ mount -t tracefs nodev /sys/kernel/tracing ||
+ errexit "Failed to mount /sys/kernel/tracing"
+ TRACING_DIR="/sys/kernel/tracing"
++ UMOUNT_DIR=${TRACING_DIR}
+ # If debugfs exists, then so does /sys/kernel/debug
+ elif [ -d "/sys/kernel/debug" ]; then
+ mount -t debugfs nodev /sys/kernel/debug ||
+ errexit "Failed to mount /sys/kernel/debug"
+ TRACING_DIR="/sys/kernel/debug/tracing"
++ UMOUNT_DIR=${TRACING_DIR}
+ else
+ err_ret=$err_skip
+ errexit "debugfs and tracefs are not configured in this kernel"
+--
+2.40.1
+
--- /dev/null
+From 272efdde02cb231ef30d291cc97c413a200381d0 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 3 Aug 2023 15:56:42 +0200
+Subject: serial: cpm_uart: Avoid suspicious locking
+
+From: Christophe Leroy <christophe.leroy@csgroup.eu>
+
+[ Upstream commit 36ef11d311f405e55ad8e848c19b212ff71ef536 ]
+
+ CHECK drivers/tty/serial/cpm_uart/cpm_uart_core.c
+drivers/tty/serial/cpm_uart/cpm_uart_core.c:1271:39: warning: context imbalance in 'cpm_uart_console_write' - unexpected unlock
+
+Allthough 'nolock' is not expected to change, sparse find the following
+form suspicious:
+
+ if (unlikely(nolock)) {
+ local_irq_save(flags);
+ } else {
+ spin_lock_irqsave(&pinfo->port.lock, flags);
+ }
+
+ cpm_uart_early_write(pinfo, s, count, true);
+
+ if (unlikely(nolock)) {
+ local_irq_restore(flags);
+ } else {
+ spin_unlock_irqrestore(&pinfo->port.lock, flags);
+ }
+
+Rewrite it a more obvious form:
+
+ if (unlikely(oops_in_progress)) {
+ local_irq_save(flags);
+ cpm_uart_early_write(pinfo, s, count, true);
+ local_irq_restore(flags);
+ } else {
+ spin_lock_irqsave(&pinfo->port.lock, flags);
+ cpm_uart_early_write(pinfo, s, count, true);
+ spin_unlock_irqrestore(&pinfo->port.lock, flags);
+ }
+
+Signed-off-by: Christophe Leroy <christophe.leroy@csgroup.eu>
+Link: https://lore.kernel.org/r/f7da5cdc9287960185829cfef681a7d8614efa1f.1691068700.git.christophe.leroy@csgroup.eu
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/tty/serial/cpm_uart/cpm_uart_core.c | 13 ++++---------
+ 1 file changed, 4 insertions(+), 9 deletions(-)
+
+diff --git a/drivers/tty/serial/cpm_uart/cpm_uart_core.c b/drivers/tty/serial/cpm_uart/cpm_uart_core.c
+index 66afa9bea6bfe..71366a4cea22c 100644
+--- a/drivers/tty/serial/cpm_uart/cpm_uart_core.c
++++ b/drivers/tty/serial/cpm_uart/cpm_uart_core.c
+@@ -1255,19 +1255,14 @@ static void cpm_uart_console_write(struct console *co, const char *s,
+ {
+ struct uart_cpm_port *pinfo = &cpm_uart_ports[co->index];
+ unsigned long flags;
+- int nolock = oops_in_progress;
+
+- if (unlikely(nolock)) {
++ if (unlikely(oops_in_progress)) {
+ local_irq_save(flags);
+- } else {
+- spin_lock_irqsave(&pinfo->port.lock, flags);
+- }
+-
+- cpm_uart_early_write(pinfo, s, count, true);
+-
+- if (unlikely(nolock)) {
++ cpm_uart_early_write(pinfo, s, count, true);
+ local_irq_restore(flags);
+ } else {
++ spin_lock_irqsave(&pinfo->port.lock, flags);
++ cpm_uart_early_write(pinfo, s, count, true);
+ spin_unlock_irqrestore(&pinfo->port.lock, flags);
+ }
+ }
+--
+2.40.1
+
--- /dev/null
+iomap-fix-possible-overflow-condition-in-iomap_write.patch
+autofs-fix-memory-leak-of-waitqueues-in-autofs_catat.patch
+btrfs-handle-errors-properly-in-update_inline_extent.patch
+btrfs-output-extra-debug-info-if-we-failed-to-find-a.patch
+locks-fix-kasan-use-after-free-in-trace_event_raw_ev.patch
+acpica-add-aml_no_operand_resolve-flag-to-timer.patch
+kernel-fork-beware-of-__put_task_struct-calling-cont.patch
+rcuscale-move-rcu_scale_writer-schedule_timeout_unin.patch
+scftorture-forgive-memory-allocation-failure-if-kasa.patch
+acpi-video-add-backlight-native-dmi-quirk-for-lenovo.patch
+platform-chrome-cros_ec_lpc-remove-ec-panic-shutdown.patch
+x86-amd_nb-add-pci-ids-for-amd-family-1ah-based-mode.patch
+perf-smmuv3-enable-hisilicon-erratum-162001900-quirk.patch
+s390-boot-cleanup-number-of-page-table-levels-setup.patch
+kselftest-arm64-fix-a-memleak-in-zt_regs_run.patch
+perf-imx_ddr-speed-up-overflow-frequency-of-cycle.patch
+acpi-video-add-backlight-native-dmi-quirk-for-apple-.patch
+hw_breakpoint-fix-single-stepping-when-using-bpf_ove.patch
+acpi-x86-s2idle-catch-multiple-acpi_type_package-obj.patch
+selftests-nolibc-fix-up-kernel-parameters-support.patch
+selftests-nolibc-prevent-out-of-bounds-access-in-exp.patch
+spi-sun6i-add-quirk-for-dual-and-quad-spi-modes-supp.patch
+devlink-remove-reload-failed-checks-in-params-get-se.patch
+crypto-lrw-xts-replace-strlcpy-with-strscpy.patch
+net-stmmac-use-per-queue-64-bit-statistics-where-nec.patch
+ice-don-t-tx-before-switchdev-is-fully-configured.patch
+wifi-ath9k-fix-fortify-warnings.patch
+wifi-ath9k-fix-printk-specifier.patch
+wifi-rtw88-delete-timer-and-free-skb-queue-when-unlo.patch
+wifi-mwifiex-fix-fortify-warning.patch
+mt76-mt7921-don-t-assume-adequate-headroom-for-sdio-.patch
+wifi-wil6210-fix-fortify-warnings.patch
+can-sun4i_can-add-acceptance-register-quirk.patch
+can-sun4i_can-add-support-for-the-allwinner-d1.patch
+net-use-sockaddr_storage-for-getsockopt-so_peername.patch
+wifi-ath12k-fix-a-null-pointer-dereference-in-ath12k.patch
+wifi-ath12k-avoid-array-overflow-of-hw-mode-for-pref.patch
+net-ipv4-return-the-real-errno-instead-of-einval.patch
+crypto-lib-mpi-avoid-null-pointer-deref-in-mpi_cmp_u.patch
+bluetooth-btusb-add-device-0489-e0f5-as-mt7922-devic.patch
+bluetooth-btusb-add-a-new-vid-pid-0489-e0f6-for-mt79.patch
+bluetooth-btusb-add-new-vid-pid-0489-e102-for-mt7922.patch
+bluetooth-btusb-add-new-vid-pid-04ca-3804-for-mt7922.patch
+bluetooth-fix-hci_suspend_sync-crash.patch
+bluetooth-btusb-add-support-for-another-mediatek-792.patch
+netlink-convert-nlk-flags-to-atomic-flags.patch
+tpm_tis-resend-command-to-recover-from-data-transfer.patch
+mmc-sdhci-esdhc-imx-improve-esdhc_flag_err010450.patch
+alx-fix-oob-read-compiler-warning.patch
+wifi-iwlwifi-pcie-avoid-a-warning-in-case-prepare-ca.patch
+wifi-mac80211-check-s1g-action-frame-size.patch
+netfilter-ebtables-fix-fortify-warnings-in-size_entr.patch
+wifi-cfg80211-reject-auth-assoc-to-ap-with-our-addre.patch
+wifi-cfg80211-ocb-don-t-leave-if-not-joined.patch
+wifi-mac80211-check-for-station-first-in-client-prob.patch
+wifi-mac80211_hwsim-drop-short-frames.patch
+revert-wifi-mac80211_hwsim-check-the-return-value-of.patch
+libbpf-free-btf_vmlinux-when-closing-bpf_object.patch
+wifi-ath12k-fix-memory-leak-in-rx_desc-and-tx_desc.patch
+wifi-ath12k-add-check-max-message-length-while-scann.patch
+fix-nomenclature-for-usb-and-pci-wireless-devices.patch
+bpf-consider-non-owning-refs-trusted.patch
+bpf-consider-non-owning-refs-to-refcounted-nodes-rcu.patch
+drm-bridge-tc358762-instruct-dsi-host-to-generate-hs.patch
+drm-edid-add-quirk-for-osvr-hdk-2.0.patch
+drm-bridge-samsung-dsim-drain-command-transfer-fifo-.patch
+arm64-dts-qcom-sm6125-pdx201-correct-ramoops-pmsg-si.patch
+arm64-dts-qcom-sm6125-sprout-correct-ramoops-pmsg-si.patch
+arm64-dts-qcom-sm6350-correct-ramoops-pmsg-size.patch
+arm64-dts-qcom-sm8150-kumano-correct-ramoops-pmsg-si.patch
+arm64-dts-qcom-sm8250-edo-correct-ramoops-pmsg-size.patch
+drm-amdgpu-increase-soft-ih-ring-size.patch
+drm-amd-display-add-stream-overhead-in-bw-calculatio.patch
+samples-hw_breakpoint-fix-kernel-bug-invalid-opcode-.patch
+drm-amdgpu-update-ring-scheduler-info-as-needed.patch
+drm-amd-display-fix-underflow-issue-on-175hz-timing.patch
+asoc-sof-topology-simplify-code-to-prevent-static-an.patch
+asoc-intel-sof_sdw-update-bt-offload-config-for-soun.patch
+alsa-hda-intel-dsp-cfg-add-lunarlake-support.patch
+drm-amd-display-use-dtbclk-as-refclk-instead-of-dpre.patch
+drm-amd-display-blocking-invalid-420-modes-on-hdmi-t.patch
+drm-amd-display-blocking-invalid-420-modes-on-hdmi-t.patch-12335
+drm-amd-display-use-max-memclk-variable-when-setting.patch
+drm-msm-adreno-use-quirk-identify-hw_apriv.patch
+drm-msm-adreno-use-quirk-to-identify-cached-coherent.patch
+drm-exynos-fix-a-possible-null-pointer-dereference-d.patch
+io_uring-annotate-the-struct-io_kiocb-slab-for-appro.patch
+drm-mediatek-dp-change-logging-to-dev-for-mtk_dp_aux.patch
+bus-ti-sysc-configure-uart-quirks-for-k3-soc.patch
+arm64-dts-qcom-sc8280xp-x13s-add-camera-activity-led.patch
+md-raid1-fix-potential-oob-in-raid1_remove_disk.patch
+ext2-fix-datatype-of-block-number-in-ext2_xattr_set2.patch
+blk-mq-fix-tags-leak-when-shrink-nr_hw_queues.patch
+asoc-sof-amd-clear-panic-mask-status-when-panic-occu.patch
+x86-bring-back-rep-movsq-for-user-access-on-cpus-wit.patch
+fs-jfs-prevent-double-free-in-dbunmount-after-failed.patch
+jfs-fix-invalid-free-of-jfs_ip-ipimap-i_imap-in-diun.patch
+ext4-add-two-helper-functions-extent_logical_end-and.patch
+ext4-avoid-overlapping-preallocations-due-to-overflo.patch
+pci-dwc-provide-deinit-callback-for-i.mx.patch
+arm-9317-1-kexec-make-smp-stop-calls-asynchronous.patch
+powerpc-pseries-fix-possible-memory-leak-in-ibmebus_.patch
+pci-vmd-disable-bridge-window-for-domain-reset.patch
+pci-fu740-set-the-number-of-msi-vectors.patch
+media-mdp3-fix-resource-leaks-in-of_find_device_by_n.patch
+media-dvb-usb-v2-af9035-fix-null-ptr-deref-in-af9035.patch
+media-dw2102-fix-null-ptr-deref-in-dw2102_i2c_transf.patch
+media-af9005-fix-null-ptr-deref-in-af9005_i2c_xfer.patch
+media-anysee-fix-null-ptr-deref-in-anysee_master_xfe.patch
+media-az6007-fix-null-ptr-deref-in-az6007_i2c_xfer.patch
+media-dvb-usb-v2-gl861-fix-null-ptr-deref-in-gl861_i.patch
+scsi-lpfc-abort-outstanding-els-cmds-when-mailbox-ti.patch
+media-tuners-qt1010-replace-bug_on-with-a-regular-er.patch
+media-pci-cx23885-replace-bug-with-error-return.patch
+usb-cdns3-put-the-cdns-set-active-part-outside-the-s.patch
+usb-typec-intel_pmc_mux-add-new-acpi-id-for-lunar-la.patch
+usb-gadget-fsl_qe_udc-validate-endpoint-index-for-ch.patch
+tools-iio-iio_generic_buffer-fix-some-integer-type-a.patch
+scsi-target-iscsi-fix-buffer-overflow-in-lio_target_.patch
+serial-cpm_uart-avoid-suspicious-locking.patch
+misc-open-dice-make-open_dice-depend-on-has_iomem.patch
+usb-dwc3-dwc3-octeon-verify-clock-divider.patch
+usb-ehci-add-workaround-for-chipidea-portsc.pec-bug.patch
+usb-chipidea-add-workaround-for-chipidea-pec-bug.patch
+media-pci-ipu3-cio2-initialise-timing-struct-to-avoi.patch
+kobject-add-sanity-check-for-kset-kobj.ktype-in-kset.patch
+interconnect-fix-locking-for-runpm-vs-reclaim.patch
+usb-typec-qcom-pmic-typec-register-drm_bridge.patch
+printk-reduce-console_unblank-usage-in-unsafe-scenar.patch
+printk-keep-non-panic-cpus-out-of-console-lock.patch
+printk-do-not-take-console-lock-for-console_flush_on.patch
+printk-consolidate-console-deferred-printing.patch
+printk-rename-abandon_console_lock_in_panic-to-other.patch
+ext4-fix-bug-in-ext4_mb_new_inode_pa-due-to-overflow.patch
+btrfs-introduce-struct-to-consolidate-extent-buffer-.patch
+btrfs-zoned-introduce-block-group-context-to-btrfs_e.patch
+btrfs-zoned-return-int-from-btrfs_check_meta_write_p.patch
+btrfs-zoned-defer-advancing-meta-write-pointer.patch
+btrfs-zoned-activate-metadata-block-group-on-write-t.patch
+mtd-spi-nor-spansion-use-clpef-as-an-alternative-to-.patch
+mtd-spi-nor-spansion-preserve-cfr2v-7-when-writing-m.patch
+btrfs-add-a-helper-to-read-the-superblock-metadata_u.patch
+btrfs-compare-the-correct-fsid-metadata_uuid-in-btrf.patch
+nvmet-tcp-pass-iov_len-instead-of-sg-length-to-bvec_.patch
+drm-gm12u320-fix-the-timeout-usage-for-usb_bulk_msg.patch
+scsi-qla2xxx-fix-null-vs-is_err-bug-for-debugfs_crea.patch
+md-don-t-dereference-mddev-after-export_rdev.patch
+md-fix-warning-for-holder-mismatch-from-export_rdev.patch
+efi-unaccepted-use-acpi-reclaim-memory-for-unaccepte.patch
+efivarfs-fix-statfs-on-efivarfs.patch
+pm-hibernate-fix-the-exclusive-get-block-device-in-t.patch
+selftests-tracing-fix-to-unmount-tracefs-for-recover.patch
+x86-ibt-suppress-spurious-endbr.patch
+x86-ibt-avoid-duplicate-endbr-in-__put_user_nocheck.patch
+riscv-kexec-align-the-kexeced-kernel-entry.patch
+x86-sched-restore-the-sd_asym_packing-flag-in-the-di.patch
+scsi-target-core-fix-target_cmd_counter-leak.patch
+scsi-lpfc-fix-the-null-vs-is_err-bug-for-debugfs_cre.patch
+panic-reenable-preemption-in-warn-slowpath.patch
+ata-libata-remove-references-to-non-existing-error_h.patch
+ata-libata-core-fetch-sense-data-for-successful-comm.patch
+x86-boot-compressed-reserve-more-memory-for-page-tab.patch
+x86-purgatory-remove-lto-flags.patch
+samples-hw_breakpoint-fix-building-without-module-un.patch
+blk-mq-fix-tags-uaf-when-shrinking-q-nr_hw_queues.patch
+md-raid1-fix-error-iso-c90-forbids-mixed-declaration.patch
--- /dev/null
+From 4644734b897324ef4c9a73b90d83c4b9b41b33bb Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sat, 24 Jun 2023 16:16:22 +0300
+Subject: spi: sun6i: add quirk for dual and quad SPI modes support
+
+From: Maksim Kiselev <bigunclemax@gmail.com>
+
+[ Upstream commit 0605d9fb411f3337482976842a3901d6c125d298 ]
+
+New Allwinner's SPI controllers can support dual and quad SPI modes.
+To enable one of these modes, we should set the corresponding bit in
+the SUN6I_BURST_CTL_CNT_REG register. DRM (28 bits) for dual mode and
+Quad_EN (29 bits) for quad transmission.
+
+Signed-off-by: Maksim Kiselev <bigunclemax@gmail.com>
+Link: https://lore.kernel.org/r/20230624131632.2972546-2-bigunclemax@gmail.com
+Signed-off-by: Mark Brown <broonie@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/spi/spi-sun6i.c | 29 +++++++++++++++++++++++++----
+ 1 file changed, 25 insertions(+), 4 deletions(-)
+
+diff --git a/drivers/spi/spi-sun6i.c b/drivers/spi/spi-sun6i.c
+index 30d541612253e..cec2747235abf 100644
+--- a/drivers/spi/spi-sun6i.c
++++ b/drivers/spi/spi-sun6i.c
+@@ -83,6 +83,9 @@
+ #define SUN6I_XMIT_CNT_REG 0x34
+
+ #define SUN6I_BURST_CTL_CNT_REG 0x38
++#define SUN6I_BURST_CTL_CNT_STC_MASK GENMASK(23, 0)
++#define SUN6I_BURST_CTL_CNT_DRM BIT(28)
++#define SUN6I_BURST_CTL_CNT_QUAD_EN BIT(29)
+
+ #define SUN6I_TXDATA_REG 0x200
+ #define SUN6I_RXDATA_REG 0x300
+@@ -90,6 +93,7 @@
+ struct sun6i_spi_cfg {
+ unsigned long fifo_depth;
+ bool has_clk_ctl;
++ u32 mode_bits;
+ };
+
+ struct sun6i_spi {
+@@ -266,7 +270,7 @@ static int sun6i_spi_transfer_one(struct spi_master *master,
+ unsigned int div, div_cdr1, div_cdr2, timeout;
+ unsigned int start, end, tx_time;
+ unsigned int trig_level;
+- unsigned int tx_len = 0, rx_len = 0;
++ unsigned int tx_len = 0, rx_len = 0, nbits = 0;
+ bool use_dma;
+ int ret = 0;
+ u32 reg;
+@@ -418,13 +422,29 @@ static int sun6i_spi_transfer_one(struct spi_master *master,
+ sun6i_spi_write(sspi, SUN6I_GBL_CTL_REG, reg);
+
+ /* Setup the transfer now... */
+- if (sspi->tx_buf)
++ if (sspi->tx_buf) {
+ tx_len = tfr->len;
++ nbits = tfr->tx_nbits;
++ } else if (tfr->rx_buf) {
++ nbits = tfr->rx_nbits;
++ }
++
++ switch (nbits) {
++ case SPI_NBITS_DUAL:
++ reg = SUN6I_BURST_CTL_CNT_DRM;
++ break;
++ case SPI_NBITS_QUAD:
++ reg = SUN6I_BURST_CTL_CNT_QUAD_EN;
++ break;
++ case SPI_NBITS_SINGLE:
++ default:
++ reg = FIELD_PREP(SUN6I_BURST_CTL_CNT_STC_MASK, tx_len);
++ }
+
+ /* Setup the counters */
++ sun6i_spi_write(sspi, SUN6I_BURST_CTL_CNT_REG, reg);
+ sun6i_spi_write(sspi, SUN6I_BURST_CNT_REG, tfr->len);
+ sun6i_spi_write(sspi, SUN6I_XMIT_CNT_REG, tx_len);
+- sun6i_spi_write(sspi, SUN6I_BURST_CTL_CNT_REG, tx_len);
+
+ if (!use_dma) {
+ /* Fill the TX FIFO */
+@@ -623,7 +643,8 @@ static int sun6i_spi_probe(struct platform_device *pdev)
+ master->set_cs = sun6i_spi_set_cs;
+ master->transfer_one = sun6i_spi_transfer_one;
+ master->num_chipselect = 4;
+- master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH | SPI_LSB_FIRST;
++ master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH | SPI_LSB_FIRST |
++ sspi->cfg->mode_bits;
+ master->bits_per_word_mask = SPI_BPW_MASK(8);
+ master->dev.of_node = pdev->dev.of_node;
+ master->auto_runtime_pm = true;
+--
+2.40.1
+
--- /dev/null
+From ee6d5c7e36ccb6bc23f4381b41a21d933504bc3b Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 25 Jul 2023 09:24:07 +0000
+Subject: tools: iio: iio_generic_buffer: Fix some integer type and calculation
+
+From: Chenyuan Mi <michenyuan@huawei.com>
+
+[ Upstream commit 49d736313d0975ddeb156f4f59801da833f78b30 ]
+
+In function size_from_channelarray(), the return value 'bytes' is defined
+as int type. However, the calcution of 'bytes' in this function is designed
+to use the unsigned int type. So it is necessary to change 'bytes' type to
+unsigned int to avoid integer overflow.
+
+The size_from_channelarray() is called in main() function, its return value
+is directly multipled by 'buf_len' and then used as the malloc() parameter.
+The 'buf_len' is completely controllable by user, thus a multiplication
+overflow may occur here. This could allocate an unexpected small area.
+
+Signed-off-by: Chenyuan Mi <michenyuan@huawei.com>
+Link: https://lore.kernel.org/r/20230725092407.62545-1-michenyuan@huawei.com
+Signed-off-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ tools/iio/iio_generic_buffer.c | 17 +++++++++++++----
+ 1 file changed, 13 insertions(+), 4 deletions(-)
+
+diff --git a/tools/iio/iio_generic_buffer.c b/tools/iio/iio_generic_buffer.c
+index f8deae4e26a15..44bbf80f0cfdd 100644
+--- a/tools/iio/iio_generic_buffer.c
++++ b/tools/iio/iio_generic_buffer.c
+@@ -51,9 +51,9 @@ enum autochan {
+ * Has the side effect of filling the channels[i].location values used
+ * in processing the buffer output.
+ **/
+-static int size_from_channelarray(struct iio_channel_info *channels, int num_channels)
++static unsigned int size_from_channelarray(struct iio_channel_info *channels, int num_channels)
+ {
+- int bytes = 0;
++ unsigned int bytes = 0;
+ int i = 0;
+
+ while (i < num_channels) {
+@@ -348,7 +348,7 @@ int main(int argc, char **argv)
+ ssize_t read_size;
+ int dev_num = -1, trig_num = -1;
+ char *buffer_access = NULL;
+- int scan_size;
++ unsigned int scan_size;
+ int noevents = 0;
+ int notrigger = 0;
+ char *dummy;
+@@ -674,7 +674,16 @@ int main(int argc, char **argv)
+ }
+
+ scan_size = size_from_channelarray(channels, num_channels);
+- data = malloc(scan_size * buf_len);
++
++ size_t total_buf_len = scan_size * buf_len;
++
++ if (scan_size > 0 && total_buf_len / scan_size != buf_len) {
++ ret = -EFAULT;
++ perror("Integer overflow happened when calculate scan_size * buf_len");
++ goto error;
++ }
++
++ data = malloc(total_buf_len);
+ if (!data) {
+ ret = -ENOMEM;
+ goto error;
+--
+2.40.1
+
--- /dev/null
+From 08b9f8fe19af7f3a6cc7d0d930745a8918bcca90 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 13 Jun 2023 20:02:59 +0200
+Subject: tpm_tis: Resend command to recover from data transfer errors
+
+From: Alexander Steffen <Alexander.Steffen@infineon.com>
+
+[ Upstream commit 280db21e153d8810ce3b93640c63ae922bcb9e8e ]
+
+Similar to the transmission of TPM responses, also the transmission of TPM
+commands may become corrupted. Instead of aborting when detecting such
+issues, try resending the command again.
+
+Signed-off-by: Alexander Steffen <Alexander.Steffen@infineon.com>
+Reviewed-by: Jarkko Sakkinen <jarkko@kernel.org>
+Signed-off-by: Jarkko Sakkinen <jarkko@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/char/tpm/tpm_tis_core.c | 13 ++++++++++---
+ 1 file changed, 10 insertions(+), 3 deletions(-)
+
+diff --git a/drivers/char/tpm/tpm_tis_core.c b/drivers/char/tpm/tpm_tis_core.c
+index b95963095729a..f4c4c027b062d 100644
+--- a/drivers/char/tpm/tpm_tis_core.c
++++ b/drivers/char/tpm/tpm_tis_core.c
+@@ -512,10 +512,17 @@ static int tpm_tis_send_main(struct tpm_chip *chip, const u8 *buf, size_t len)
+ int rc;
+ u32 ordinal;
+ unsigned long dur;
++ unsigned int try;
+
+- rc = tpm_tis_send_data(chip, buf, len);
+- if (rc < 0)
+- return rc;
++ for (try = 0; try < TPM_RETRY; try++) {
++ rc = tpm_tis_send_data(chip, buf, len);
++ if (rc >= 0)
++ /* Data transfer done successfully */
++ break;
++ else if (rc != -EIO)
++ /* Data transfer failed, not recoverable */
++ return rc;
++ }
+
+ rc = tpm_tis_verify_crc(priv, len, buf);
+ if (rc < 0) {
+--
+2.40.1
+
--- /dev/null
+From 7530cd38b37f333d155564308e174038f9b91e1e Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 16 Jun 2023 10:19:51 +0800
+Subject: usb: cdns3: Put the cdns set active part outside the spin lock
+
+From: Xiaolei Wang <xiaolei.wang@windriver.com>
+
+[ Upstream commit 2319b9c87fe243327285f2fefd7374ffd75a65fc ]
+
+The device may be scheduled during the resume process,
+so this cannot appear in atomic operations. Since
+pm_runtime_set_active will resume suppliers, put set
+active outside the spin lock, which is only used to
+protect the struct cdns data structure, otherwise the
+kernel will report the following warning:
+
+ BUG: sleeping function called from invalid context at drivers/base/power/runtime.c:1163
+ in_atomic(): 1, irqs_disabled(): 0, non_block: 0, pid: 651, name: sh
+ preempt_count: 1, expected: 0
+ RCU nest depth: 0, expected: 0
+ CPU: 0 PID: 651 Comm: sh Tainted: G WC 6.1.20 #1
+ Hardware name: Freescale i.MX8QM MEK (DT)
+ Call trace:
+ dump_backtrace.part.0+0xe0/0xf0
+ show_stack+0x18/0x30
+ dump_stack_lvl+0x64/0x80
+ dump_stack+0x1c/0x38
+ __might_resched+0x1fc/0x240
+ __might_sleep+0x68/0xc0
+ __pm_runtime_resume+0x9c/0xe0
+ rpm_get_suppliers+0x68/0x1b0
+ __pm_runtime_set_status+0x298/0x560
+ cdns_resume+0xb0/0x1c0
+ cdns3_controller_resume.isra.0+0x1e0/0x250
+ cdns3_plat_resume+0x28/0x40
+
+Signed-off-by: Xiaolei Wang <xiaolei.wang@windriver.com>
+Acked-by: Peter Chen <peter.chen@kernel.org>
+Link: https://lore.kernel.org/r/20230616021952.1025854-1-xiaolei.wang@windriver.com
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/usb/cdns3/cdns3-plat.c | 3 ++-
+ drivers/usb/cdns3/cdnsp-pci.c | 3 ++-
+ drivers/usb/cdns3/core.c | 15 +++++++++++----
+ drivers/usb/cdns3/core.h | 7 +++++--
+ 4 files changed, 20 insertions(+), 8 deletions(-)
+
+diff --git a/drivers/usb/cdns3/cdns3-plat.c b/drivers/usb/cdns3/cdns3-plat.c
+index 884e2301237f4..1168dbeed2ce0 100644
+--- a/drivers/usb/cdns3/cdns3-plat.c
++++ b/drivers/usb/cdns3/cdns3-plat.c
+@@ -255,9 +255,10 @@ static int cdns3_controller_resume(struct device *dev, pm_message_t msg)
+ cdns3_set_platform_suspend(cdns->dev, false, false);
+
+ spin_lock_irqsave(&cdns->lock, flags);
+- cdns_resume(cdns, !PMSG_IS_AUTO(msg));
++ cdns_resume(cdns);
+ cdns->in_lpm = false;
+ spin_unlock_irqrestore(&cdns->lock, flags);
++ cdns_set_active(cdns, !PMSG_IS_AUTO(msg));
+ if (cdns->wakeup_pending) {
+ cdns->wakeup_pending = false;
+ enable_irq(cdns->wakeup_irq);
+diff --git a/drivers/usb/cdns3/cdnsp-pci.c b/drivers/usb/cdns3/cdnsp-pci.c
+index 7b151f5af3ccb..0725668ffea4c 100644
+--- a/drivers/usb/cdns3/cdnsp-pci.c
++++ b/drivers/usb/cdns3/cdnsp-pci.c
+@@ -208,8 +208,9 @@ static int __maybe_unused cdnsp_pci_resume(struct device *dev)
+ int ret;
+
+ spin_lock_irqsave(&cdns->lock, flags);
+- ret = cdns_resume(cdns, 1);
++ ret = cdns_resume(cdns);
+ spin_unlock_irqrestore(&cdns->lock, flags);
++ cdns_set_active(cdns, 1);
+
+ return ret;
+ }
+diff --git a/drivers/usb/cdns3/core.c b/drivers/usb/cdns3/core.c
+index dbcdf3b24b477..7b20d2d5c262e 100644
+--- a/drivers/usb/cdns3/core.c
++++ b/drivers/usb/cdns3/core.c
+@@ -522,9 +522,8 @@ int cdns_suspend(struct cdns *cdns)
+ }
+ EXPORT_SYMBOL_GPL(cdns_suspend);
+
+-int cdns_resume(struct cdns *cdns, u8 set_active)
++int cdns_resume(struct cdns *cdns)
+ {
+- struct device *dev = cdns->dev;
+ enum usb_role real_role;
+ bool role_changed = false;
+ int ret = 0;
+@@ -556,15 +555,23 @@ int cdns_resume(struct cdns *cdns, u8 set_active)
+ if (cdns->roles[cdns->role]->resume)
+ cdns->roles[cdns->role]->resume(cdns, cdns_power_is_lost(cdns));
+
++ return 0;
++}
++EXPORT_SYMBOL_GPL(cdns_resume);
++
++void cdns_set_active(struct cdns *cdns, u8 set_active)
++{
++ struct device *dev = cdns->dev;
++
+ if (set_active) {
+ pm_runtime_disable(dev);
+ pm_runtime_set_active(dev);
+ pm_runtime_enable(dev);
+ }
+
+- return 0;
++ return;
+ }
+-EXPORT_SYMBOL_GPL(cdns_resume);
++EXPORT_SYMBOL_GPL(cdns_set_active);
+ #endif /* CONFIG_PM_SLEEP */
+
+ MODULE_AUTHOR("Peter Chen <peter.chen@nxp.com>");
+diff --git a/drivers/usb/cdns3/core.h b/drivers/usb/cdns3/core.h
+index 2d332a788871e..4a4dbc2c15615 100644
+--- a/drivers/usb/cdns3/core.h
++++ b/drivers/usb/cdns3/core.h
+@@ -125,10 +125,13 @@ int cdns_init(struct cdns *cdns);
+ int cdns_remove(struct cdns *cdns);
+
+ #ifdef CONFIG_PM_SLEEP
+-int cdns_resume(struct cdns *cdns, u8 set_active);
++int cdns_resume(struct cdns *cdns);
+ int cdns_suspend(struct cdns *cdns);
++void cdns_set_active(struct cdns *cdns, u8 set_active);
+ #else /* CONFIG_PM_SLEEP */
+-static inline int cdns_resume(struct cdns *cdns, u8 set_active)
++static inline int cdns_resume(struct cdns *cdns)
++{ return 0; }
++static inline int cdns_set_active(struct cdns *cdns, u8 set_active)
+ { return 0; }
+ static inline int cdns_suspend(struct cdns *cdns)
+ { return 0; }
+--
+2.40.1
+
--- /dev/null
+From fd22c29a6aceaa005f02937a140584046887c4c0 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 9 Aug 2023 10:44:32 +0800
+Subject: usb: chipidea: add workaround for chipidea PEC bug
+
+From: Xu Yang <xu.yang_2@nxp.com>
+
+[ Upstream commit 12e6ac69cc7e7d3367599ae26a92a0f9a18bc728 ]
+
+Some NXP processors using ChipIdea USB IP have a bug when frame babble is
+detected.
+
+Issue description:
+In USB camera test, our controller is host in HS mode. In ISOC IN, when
+device sends data across the micro frame, it causes the babble in host
+controller. This will clear the PE bit. In spec, it also requires to set
+the PEC bit and then set the PCI bit. Without the PCI interrupt, the
+software does not know the PE is cleared.
+
+This will add a flag CI_HDRC_HAS_PORTSC_PEC_MISSED to some impacted
+platform datas. And the ehci host driver will assert PEC by SW when
+specific conditions are satisfied.
+
+Signed-off-by: Xu Yang <xu.yang_2@nxp.com>
+Link: https://lore.kernel.org/r/20230809024432.535160-2-xu.yang_2@nxp.com
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/usb/chipidea/ci.h | 1 +
+ drivers/usb/chipidea/ci_hdrc_imx.c | 4 +++-
+ drivers/usb/chipidea/core.c | 2 ++
+ drivers/usb/chipidea/host.c | 1 +
+ include/linux/usb/chipidea.h | 1 +
+ 5 files changed, 8 insertions(+), 1 deletion(-)
+
+diff --git a/drivers/usb/chipidea/ci.h b/drivers/usb/chipidea/ci.h
+index f210b7489fd5b..78cfbe621272c 100644
+--- a/drivers/usb/chipidea/ci.h
++++ b/drivers/usb/chipidea/ci.h
+@@ -257,6 +257,7 @@ struct ci_hdrc {
+ bool id_event;
+ bool b_sess_valid_event;
+ bool imx28_write_fix;
++ bool has_portsc_pec_bug;
+ bool supports_runtime_pm;
+ bool in_lpm;
+ bool wakeup_int;
+diff --git a/drivers/usb/chipidea/ci_hdrc_imx.c b/drivers/usb/chipidea/ci_hdrc_imx.c
+index 873539f9a2c0a..a96d8af935382 100644
+--- a/drivers/usb/chipidea/ci_hdrc_imx.c
++++ b/drivers/usb/chipidea/ci_hdrc_imx.c
+@@ -67,11 +67,13 @@ static const struct ci_hdrc_imx_platform_flag imx7d_usb_data = {
+
+ static const struct ci_hdrc_imx_platform_flag imx7ulp_usb_data = {
+ .flags = CI_HDRC_SUPPORTS_RUNTIME_PM |
++ CI_HDRC_HAS_PORTSC_PEC_MISSED |
+ CI_HDRC_PMQOS,
+ };
+
+ static const struct ci_hdrc_imx_platform_flag imx8ulp_usb_data = {
+- .flags = CI_HDRC_SUPPORTS_RUNTIME_PM,
++ .flags = CI_HDRC_SUPPORTS_RUNTIME_PM |
++ CI_HDRC_HAS_PORTSC_PEC_MISSED,
+ };
+
+ static const struct of_device_id ci_hdrc_imx_dt_ids[] = {
+diff --git a/drivers/usb/chipidea/core.c b/drivers/usb/chipidea/core.c
+index 51994d655b821..500286a4576b5 100644
+--- a/drivers/usb/chipidea/core.c
++++ b/drivers/usb/chipidea/core.c
+@@ -1045,6 +1045,8 @@ static int ci_hdrc_probe(struct platform_device *pdev)
+ CI_HDRC_IMX28_WRITE_FIX);
+ ci->supports_runtime_pm = !!(ci->platdata->flags &
+ CI_HDRC_SUPPORTS_RUNTIME_PM);
++ ci->has_portsc_pec_bug = !!(ci->platdata->flags &
++ CI_HDRC_HAS_PORTSC_PEC_MISSED);
+ platform_set_drvdata(pdev, ci);
+
+ ret = hw_device_init(ci, base);
+diff --git a/drivers/usb/chipidea/host.c b/drivers/usb/chipidea/host.c
+index ebe7400243b12..08af26b762a2d 100644
+--- a/drivers/usb/chipidea/host.c
++++ b/drivers/usb/chipidea/host.c
+@@ -151,6 +151,7 @@ static int host_start(struct ci_hdrc *ci)
+ ehci->has_hostpc = ci->hw_bank.lpm;
+ ehci->has_tdi_phy_lpm = ci->hw_bank.lpm;
+ ehci->imx28_write_fix = ci->imx28_write_fix;
++ ehci->has_ci_pec_bug = ci->has_portsc_pec_bug;
+
+ priv = (struct ehci_ci_priv *)ehci->priv;
+ priv->reg_vbus = NULL;
+diff --git a/include/linux/usb/chipidea.h b/include/linux/usb/chipidea.h
+index ee38835ed77cc..0b4f2d5faa080 100644
+--- a/include/linux/usb/chipidea.h
++++ b/include/linux/usb/chipidea.h
+@@ -63,6 +63,7 @@ struct ci_hdrc_platform_data {
+ #define CI_HDRC_IMX_IS_HSIC BIT(14)
+ #define CI_HDRC_PMQOS BIT(15)
+ #define CI_HDRC_PHY_VBUS_CONTROL BIT(16)
++#define CI_HDRC_HAS_PORTSC_PEC_MISSED BIT(17)
+ enum usb_dr_mode dr_mode;
+ #define CI_HDRC_CONTROLLER_RESET_EVENT 0
+ #define CI_HDRC_CONTROLLER_STOPPED_EVENT 1
+--
+2.40.1
+
--- /dev/null
+From c151f6712e0b82f9f120a8da356633024f4459e0 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 8 Aug 2023 11:37:50 +0200
+Subject: usb: dwc3: dwc3-octeon: Verify clock divider
+
+From: Ladislav Michl <ladis@linux-mips.org>
+
+[ Upstream commit fb57f829beefd4b3746f1b23d51e80ed5d4bb87b ]
+
+Although valid USB clock divider will be calculated for all valid
+Octeon core frequencies, make code formally correct limiting
+divider not to be greater that 7 so it fits into H_CLKDIV_SEL
+field.
+
+Signed-off-by: Ladislav Michl <ladis@linux-mips.org>
+Reported-by: Linux Kernel Functional Testing <lkft@linaro.org>
+Closes: https://qa-reports.linaro.org/lkft/linux-next-master/build/next-20230808/testrun/18882876/suite/build/test/gcc-8-cavium_octeon_defconfig/log
+Acked-by: Thinh Nguyen <Thinh.Nguyen@synopsys.com>
+Link: https://lore.kernel.org/r/ZNIM7tlBNdHFzXZG@lenoch
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ arch/mips/cavium-octeon/octeon-usb.c | 8 ++++++--
+ 1 file changed, 6 insertions(+), 2 deletions(-)
+
+diff --git a/arch/mips/cavium-octeon/octeon-usb.c b/arch/mips/cavium-octeon/octeon-usb.c
+index 2add435ad0387..165e032d08647 100644
+--- a/arch/mips/cavium-octeon/octeon-usb.c
++++ b/arch/mips/cavium-octeon/octeon-usb.c
+@@ -243,11 +243,11 @@ static int dwc3_octeon_get_divider(void)
+ while (div < ARRAY_SIZE(clk_div)) {
+ uint64_t rate = octeon_get_io_clock_rate() / clk_div[div];
+ if (rate <= 300000000 && rate >= 150000000)
+- break;
++ return div;
+ div++;
+ }
+
+- return div;
++ return -EINVAL;
+ }
+
+ static int dwc3_octeon_config_power(struct device *dev, void __iomem *base)
+@@ -374,6 +374,10 @@ static int dwc3_octeon_clocks_start(struct device *dev, void __iomem *base)
+
+ /* Step 4b: Select controller clock frequency. */
+ div = dwc3_octeon_get_divider();
++ if (div < 0) {
++ dev_err(dev, "clock divider invalid\n");
++ return div;
++ }
+ val = dwc3_octeon_readq(uctl_ctl_reg);
+ val &= ~USBDRD_UCTL_CTL_H_CLKDIV_SEL;
+ val |= FIELD_PREP(USBDRD_UCTL_CTL_H_CLKDIV_SEL, div);
+--
+2.40.1
+
--- /dev/null
+From db01f2024c550498aea86c5d5948d105331e151d Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 9 Aug 2023 10:44:31 +0800
+Subject: usb: ehci: add workaround for chipidea PORTSC.PEC bug
+
+From: Xu Yang <xu.yang_2@nxp.com>
+
+[ Upstream commit dda4b60ed70bd670eefda081f70c0cb20bbeb1fa ]
+
+Some NXP processor using chipidea IP has a bug when frame babble is
+detected.
+
+As per 4.15.1.1.1 Serial Bus Babble:
+ A babble condition also exists if IN transaction is in progress at
+High-speed SOF2 point. This is called frame babble. The host controller
+must disable the port to which the frame babble is detected.
+
+The USB controller has disabled the port (PE cleared) and has asserted
+USBERRINT when frame babble is detected, but PEC is not asserted.
+Therefore, the SW isn't aware that port has been disabled. Then the
+SW keeps sending packets to this port, but all of the transfers will
+fail.
+
+This workaround will firstly assert PCD by SW when USBERRINT is detected
+and then judge whether port change has really occurred or not by polling
+roothub status. Because the PEC doesn't get asserted in our case, this
+patch will also assert it by SW when specific conditions are satisfied.
+
+Signed-off-by: Xu Yang <xu.yang_2@nxp.com>
+Acked-by: Peter Chen <peter.chen@kernel.org>
+Link: https://lore.kernel.org/r/20230809024432.535160-1-xu.yang_2@nxp.com
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/usb/host/ehci-hcd.c | 8 ++++++--
+ drivers/usb/host/ehci-hub.c | 10 +++++++++-
+ drivers/usb/host/ehci.h | 10 ++++++++++
+ 3 files changed, 25 insertions(+), 3 deletions(-)
+
+diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c
+index a1930db0da1c3..802bfafb1012b 100644
+--- a/drivers/usb/host/ehci-hcd.c
++++ b/drivers/usb/host/ehci-hcd.c
+@@ -755,10 +755,14 @@ static irqreturn_t ehci_irq (struct usb_hcd *hcd)
+
+ /* normal [4.15.1.2] or error [4.15.1.1] completion */
+ if (likely ((status & (STS_INT|STS_ERR)) != 0)) {
+- if (likely ((status & STS_ERR) == 0))
++ if (likely ((status & STS_ERR) == 0)) {
+ INCR(ehci->stats.normal);
+- else
++ } else {
++ /* Force to check port status */
++ if (ehci->has_ci_pec_bug)
++ status |= STS_PCD;
+ INCR(ehci->stats.error);
++ }
+ bh = 1;
+ }
+
+diff --git a/drivers/usb/host/ehci-hub.c b/drivers/usb/host/ehci-hub.c
+index efe30e3be22f7..1aee392e84927 100644
+--- a/drivers/usb/host/ehci-hub.c
++++ b/drivers/usb/host/ehci-hub.c
+@@ -674,7 +674,8 @@ ehci_hub_status_data (struct usb_hcd *hcd, char *buf)
+
+ if ((temp & mask) != 0 || test_bit(i, &ehci->port_c_suspend)
+ || (ehci->reset_done[i] && time_after_eq(
+- jiffies, ehci->reset_done[i]))) {
++ jiffies, ehci->reset_done[i]))
++ || ehci_has_ci_pec_bug(ehci, temp)) {
+ if (i < 7)
+ buf [0] |= 1 << (i + 1);
+ else
+@@ -875,6 +876,13 @@ int ehci_hub_control(
+ if (temp & PORT_PEC)
+ status |= USB_PORT_STAT_C_ENABLE << 16;
+
++ if (ehci_has_ci_pec_bug(ehci, temp)) {
++ status |= USB_PORT_STAT_C_ENABLE << 16;
++ ehci_info(ehci,
++ "PE is cleared by HW port:%d PORTSC:%08x\n",
++ wIndex + 1, temp);
++ }
++
+ if ((temp & PORT_OCC) && (!ignore_oc && !ehci->spurious_oc)){
+ status |= USB_PORT_STAT_C_OVERCURRENT << 16;
+
+diff --git a/drivers/usb/host/ehci.h b/drivers/usb/host/ehci.h
+index c5c7f87825493..1441e34007961 100644
+--- a/drivers/usb/host/ehci.h
++++ b/drivers/usb/host/ehci.h
+@@ -207,6 +207,7 @@ struct ehci_hcd { /* one per controller */
+ unsigned has_fsl_port_bug:1; /* FreeScale */
+ unsigned has_fsl_hs_errata:1; /* Freescale HS quirk */
+ unsigned has_fsl_susp_errata:1; /* NXP SUSP quirk */
++ unsigned has_ci_pec_bug:1; /* ChipIdea PEC bug */
+ unsigned big_endian_mmio:1;
+ unsigned big_endian_desc:1;
+ unsigned big_endian_capbase:1;
+@@ -707,6 +708,15 @@ ehci_port_speed(struct ehci_hcd *ehci, unsigned int portsc)
+ */
+ #define ehci_has_fsl_susp_errata(e) ((e)->has_fsl_susp_errata)
+
++/*
++ * Some Freescale/NXP processors using ChipIdea IP have a bug in which
++ * disabling the port (PE is cleared) does not cause PEC to be asserted
++ * when frame babble is detected.
++ */
++#define ehci_has_ci_pec_bug(e, portsc) \
++ ((e)->has_ci_pec_bug && ((e)->command & CMD_PSE) \
++ && !(portsc & PORT_PEC) && !(portsc & PORT_PE))
++
+ /*
+ * While most USB host controllers implement their registers in
+ * little-endian format, a minority (celleb companion chip) implement
+--
+2.40.1
+
--- /dev/null
+From 251c693d6b5e96f5cf78bb657d62de06a268d908 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 28 Jun 2023 16:15:11 +0800
+Subject: usb: gadget: fsl_qe_udc: validate endpoint index for ch9 udc
+
+From: Ma Ke <make_ruc2021@163.com>
+
+[ Upstream commit ce9daa2efc0872a9a68ea51dc8000df05893ef2e ]
+
+We should verify the bound of the array to assure that host
+may not manipulate the index to point past endpoint array.
+
+Signed-off-by: Ma Ke <make_ruc2021@163.com>
+Acked-by: Li Yang <leoyang.li@nxp.com>
+Link: https://lore.kernel.org/r/20230628081511.186850-1-make_ruc2021@163.com
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/usb/gadget/udc/fsl_qe_udc.c | 2 ++
+ 1 file changed, 2 insertions(+)
+
+diff --git a/drivers/usb/gadget/udc/fsl_qe_udc.c b/drivers/usb/gadget/udc/fsl_qe_udc.c
+index 9c5dc1c1a68ea..4aae86b47edfc 100644
+--- a/drivers/usb/gadget/udc/fsl_qe_udc.c
++++ b/drivers/usb/gadget/udc/fsl_qe_udc.c
+@@ -1959,6 +1959,8 @@ static void ch9getstatus(struct qe_udc *udc, u8 request_type, u16 value,
+ } else if ((request_type & USB_RECIP_MASK) == USB_RECIP_ENDPOINT) {
+ /* Get endpoint status */
+ int pipe = index & USB_ENDPOINT_NUMBER_MASK;
++ if (pipe >= USB_MAX_ENDPOINTS)
++ goto stall;
+ struct qe_ep *target_ep = &udc->eps[pipe];
+ u16 usep;
+
+--
+2.40.1
+
--- /dev/null
+From 0fb2fe8692397b97c94ea4e6b285d9f8e72a5682 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 4 Jul 2023 13:35:09 +0530
+Subject: usb: typec: intel_pmc_mux: Add new ACPI ID for Lunar Lake IOM device
+
+From: Madhu M <madhu.m@intel.com>
+
+[ Upstream commit e032368e8cb15ab1f11b92f078caa9bae995b8fe ]
+
+Intel Lunar Lake IOM has a different IOM port status offset and size
+than Intel MTL.
+
+Intel Lunar Lake is the first platform to extend IOM port status
+from 32bit to 64bit by adding DDI port number into IOM port status.
+
+Added IOM_PORT_STATUS_REGS macro for using platform specific IOM port
+status offset and size.
+
+Reviewed-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
+Acked-by: Heikki Krogerus <heikki.krogerus@linux.intel.com>
+Signed-off-by: Madhu M <madhu.m@intel.com>
+Link: https://lore.kernel.org/r/20230704080509.14251-1-madhu.m@intel.com
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/usb/typec/mux/intel_pmc_mux.c | 25 ++++++++++++++++++++-----
+ 1 file changed, 20 insertions(+), 5 deletions(-)
+
+diff --git a/drivers/usb/typec/mux/intel_pmc_mux.c b/drivers/usb/typec/mux/intel_pmc_mux.c
+index 5e8edf3881c0d..61a88f68b458c 100644
+--- a/drivers/usb/typec/mux/intel_pmc_mux.c
++++ b/drivers/usb/typec/mux/intel_pmc_mux.c
+@@ -117,6 +117,16 @@ enum {
+ IOM_PORT_STATUS_DHPD_HPD_STATUS_SHIFT) & \
+ IOM_PORT_STATUS_DHPD_HPD_STATUS_ASSERT)
+
++/* IOM port status register */
++#define IOM_PORT_STATUS_REGS(_offset_, _size_) ((_offset_) | (_size_))
++#define IOM_PORT_STATUS_REGS_SZ_MASK BIT(0)
++#define IOM_PORT_STATUS_REGS_SZ_4 0
++#define IOM_PORT_STATUS_REGS_SZ_8 1
++#define IOM_PORT_STATUS_REGS_OFFSET(_d_) \
++ ((_d_) & ~IOM_PORT_STATUS_REGS_SZ_MASK)
++#define IOM_PORT_STATUS_REGS_SIZE(_d_) \
++ (4 << ((_d_) & IOM_PORT_STATUS_REGS_SZ_MASK))
++
+ struct pmc_usb;
+
+ struct pmc_usb_port {
+@@ -145,6 +155,7 @@ struct pmc_usb {
+ struct acpi_device *iom_adev;
+ void __iomem *iom_base;
+ u32 iom_port_status_offset;
++ u8 iom_port_status_size;
+
+ struct dentry *dentry;
+ };
+@@ -160,7 +171,7 @@ static void update_port_status(struct pmc_usb_port *port)
+
+ port->iom_status = readl(port->pmc->iom_base +
+ port->pmc->iom_port_status_offset +
+- port_num * sizeof(u32));
++ port_num * port->pmc->iom_port_status_size);
+ }
+
+ static int sbu_orientation(struct pmc_usb_port *port)
+@@ -589,13 +600,16 @@ static int pmc_usb_register_port(struct pmc_usb *pmc, int index,
+ /* IOM ACPI IDs and IOM_PORT_STATUS_OFFSET */
+ static const struct acpi_device_id iom_acpi_ids[] = {
+ /* TigerLake */
+- { "INTC1072", 0x560, },
++ { "INTC1072", IOM_PORT_STATUS_REGS(0x560, IOM_PORT_STATUS_REGS_SZ_4) },
+
+ /* AlderLake */
+- { "INTC1079", 0x160, },
++ { "INTC1079", IOM_PORT_STATUS_REGS(0x160, IOM_PORT_STATUS_REGS_SZ_4) },
+
+ /* Meteor Lake */
+- { "INTC107A", 0x160, },
++ { "INTC107A", IOM_PORT_STATUS_REGS(0x160, IOM_PORT_STATUS_REGS_SZ_4) },
++
++ /* Lunar Lake */
++ { "INTC10EA", IOM_PORT_STATUS_REGS(0x150, IOM_PORT_STATUS_REGS_SZ_8) },
+ {}
+ };
+
+@@ -615,7 +629,8 @@ static int pmc_usb_probe_iom(struct pmc_usb *pmc)
+ if (!adev)
+ return -ENODEV;
+
+- pmc->iom_port_status_offset = (u32)dev_id->driver_data;
++ pmc->iom_port_status_offset = IOM_PORT_STATUS_REGS_OFFSET(dev_id->driver_data);
++ pmc->iom_port_status_size = IOM_PORT_STATUS_REGS_SIZE(dev_id->driver_data);
+
+ INIT_LIST_HEAD(&resource_list);
+ ret = acpi_dev_get_memory_resources(adev, &resource_list);
+--
+2.40.1
+
--- /dev/null
+From bd7f8ea50c3c99cd27b9f1a041071552dbb1a901 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 17 Aug 2023 18:08:24 +0300
+Subject: usb: typec: qcom-pmic-typec: register drm_bridge
+
+From: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
+
+[ Upstream commit 4b3cd783808bb327d931bbb1324d6c367443b721 ]
+
+The current approach to handling DP on bridge-enabled platforms requires
+a chain of DP bridges up to the USB-C connector. Register a last DRM
+bridge for such chain.
+
+Acked-by: Bryan O'Donoghue <bryan.odonoghue@linaro.org>
+Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
+Link: https://lore.kernel.org/r/20230817150824.14371-3-dmitry.baryshkov@linaro.org
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/usb/typec/tcpm/Kconfig | 1 +
+ drivers/usb/typec/tcpm/qcom/qcom_pmic_typec.c | 37 +++++++++++++++++++
+ 2 files changed, 38 insertions(+)
+
+diff --git a/drivers/usb/typec/tcpm/Kconfig b/drivers/usb/typec/tcpm/Kconfig
+index 5d393f520fc2f..0b2993fef564b 100644
+--- a/drivers/usb/typec/tcpm/Kconfig
++++ b/drivers/usb/typec/tcpm/Kconfig
+@@ -79,6 +79,7 @@ config TYPEC_WCOVE
+ config TYPEC_QCOM_PMIC
+ tristate "Qualcomm PMIC USB Type-C Port Controller Manager driver"
+ depends on ARCH_QCOM || COMPILE_TEST
++ depends on DRM || DRM=n
+ help
+ A Type-C port and Power Delivery driver which aggregates two
+ discrete pieces of silicon in the PM8150b PMIC block: the
+diff --git a/drivers/usb/typec/tcpm/qcom/qcom_pmic_typec.c b/drivers/usb/typec/tcpm/qcom/qcom_pmic_typec.c
+index 9b467a346114e..273b4811b4ac8 100644
+--- a/drivers/usb/typec/tcpm/qcom/qcom_pmic_typec.c
++++ b/drivers/usb/typec/tcpm/qcom/qcom_pmic_typec.c
+@@ -17,6 +17,9 @@
+ #include <linux/usb/role.h>
+ #include <linux/usb/tcpm.h>
+ #include <linux/usb/typec_mux.h>
++
++#include <drm/drm_bridge.h>
++
+ #include "qcom_pmic_typec_pdphy.h"
+ #include "qcom_pmic_typec_port.h"
+
+@@ -33,6 +36,7 @@ struct pmic_typec {
+ struct pmic_typec_port *pmic_typec_port;
+ bool vbus_enabled;
+ struct mutex lock; /* VBUS state serialization */
++ struct drm_bridge bridge;
+ };
+
+ #define tcpc_to_tcpm(_tcpc_) container_of(_tcpc_, struct pmic_typec, tcpc)
+@@ -146,6 +150,35 @@ static int qcom_pmic_typec_init(struct tcpc_dev *tcpc)
+ return 0;
+ }
+
++#if IS_ENABLED(CONFIG_DRM)
++static int qcom_pmic_typec_attach(struct drm_bridge *bridge,
++ enum drm_bridge_attach_flags flags)
++{
++ return flags & DRM_BRIDGE_ATTACH_NO_CONNECTOR ? 0 : -EINVAL;
++}
++
++static const struct drm_bridge_funcs qcom_pmic_typec_bridge_funcs = {
++ .attach = qcom_pmic_typec_attach,
++};
++
++static int qcom_pmic_typec_init_drm(struct pmic_typec *tcpm)
++{
++ tcpm->bridge.funcs = &qcom_pmic_typec_bridge_funcs;
++#ifdef CONFIG_OF
++ tcpm->bridge.of_node = of_get_child_by_name(tcpm->dev->of_node, "connector");
++#endif
++ tcpm->bridge.ops = DRM_BRIDGE_OP_HPD;
++ tcpm->bridge.type = DRM_MODE_CONNECTOR_DisplayPort;
++
++ return devm_drm_bridge_add(tcpm->dev, &tcpm->bridge);
++}
++#else
++static int qcom_pmic_typec_init_drm(struct pmic_typec *tcpm)
++{
++ return 0;
++}
++#endif
++
+ static int qcom_pmic_typec_probe(struct platform_device *pdev)
+ {
+ struct pmic_typec *tcpm;
+@@ -208,6 +241,10 @@ static int qcom_pmic_typec_probe(struct platform_device *pdev)
+ mutex_init(&tcpm->lock);
+ platform_set_drvdata(pdev, tcpm);
+
++ ret = qcom_pmic_typec_init_drm(tcpm);
++ if (ret)
++ return ret;
++
+ tcpm->tcpc.fwnode = device_get_named_child_node(tcpm->dev, "connector");
+ if (!tcpm->tcpc.fwnode)
+ return -EINVAL;
+--
+2.40.1
+
--- /dev/null
+From ae409df4868f312ba06c50f648de1026482f6658 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 9 Aug 2023 04:16:57 -0400
+Subject: wifi: ath12k: add check max message length while scanning with
+ extraie
+
+From: Wen Gong <quic_wgong@quicinc.com>
+
+[ Upstream commit 2f5124e86ae74b7ba24c9ae2644107b750cbf38f ]
+
+Currently the extraie length is directly used to allocate skb buffer. When
+the length of skb is greater than the max message length which firmware
+supports, error will happen in firmware side.
+
+Hence add check for the skb length and drop extraie when overflow and
+print a message.
+
+Tested-on: WCN7850 hw2.0 PCI WLAN.HMT.1.0-03427-QCAHMTSWPL_V1.0_V2.0_SILICONZ-1.15378.4
+
+Signed-off-by: Wen Gong <quic_wgong@quicinc.com>
+Reviewed-by: Jeff Johnson <quic_jjohnson@quicinc.com>
+Signed-off-by: Kalle Valo <quic_kvalo@quicinc.com>
+Link: https://lore.kernel.org/r/20230809081657.13858-1-quic_wgong@quicinc.com
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/wireless/ath/ath12k/wmi.c | 20 +++++++++++++-------
+ 1 file changed, 13 insertions(+), 7 deletions(-)
+
+diff --git a/drivers/net/wireless/ath/ath12k/wmi.c b/drivers/net/wireless/ath/ath12k/wmi.c
+index 4f378f06e946e..eebc5a65ce3b4 100644
+--- a/drivers/net/wireless/ath/ath12k/wmi.c
++++ b/drivers/net/wireless/ath/ath12k/wmi.c
+@@ -2162,12 +2162,6 @@ int ath12k_wmi_send_scan_start_cmd(struct ath12k *ar,
+ if (arg->num_bssid)
+ len += sizeof(*bssid) * arg->num_bssid;
+
+- len += TLV_HDR_SIZE;
+- if (arg->extraie.len)
+- extraie_len_with_pad =
+- roundup(arg->extraie.len, sizeof(u32));
+- len += extraie_len_with_pad;
+-
+ if (arg->num_hint_bssid)
+ len += TLV_HDR_SIZE +
+ arg->num_hint_bssid * sizeof(*hint_bssid);
+@@ -2176,6 +2170,18 @@ int ath12k_wmi_send_scan_start_cmd(struct ath12k *ar,
+ len += TLV_HDR_SIZE +
+ arg->num_hint_s_ssid * sizeof(*s_ssid);
+
++ len += TLV_HDR_SIZE;
++ if (arg->extraie.len)
++ extraie_len_with_pad =
++ roundup(arg->extraie.len, sizeof(u32));
++ if (extraie_len_with_pad <= (wmi->wmi_ab->max_msg_len[ar->pdev_idx] - len)) {
++ len += extraie_len_with_pad;
++ } else {
++ ath12k_warn(ar->ab, "discard large size %d bytes extraie for scan start\n",
++ arg->extraie.len);
++ extraie_len_with_pad = 0;
++ }
++
+ skb = ath12k_wmi_alloc_skb(wmi->wmi_ab, len);
+ if (!skb)
+ return -ENOMEM;
+@@ -2265,7 +2271,7 @@ int ath12k_wmi_send_scan_start_cmd(struct ath12k *ar,
+ tlv->header = ath12k_wmi_tlv_hdr(WMI_TAG_ARRAY_BYTE, len);
+ ptr += TLV_HDR_SIZE;
+
+- if (arg->extraie.len)
++ if (extraie_len_with_pad)
+ memcpy(ptr, arg->extraie.ptr,
+ arg->extraie.len);
+
+--
+2.40.1
+
--- /dev/null
+From 24367c49d9dc0f7e6f89bec54df2672b10a8f9d5 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 14 Jul 2023 03:24:05 -0400
+Subject: wifi: ath12k: avoid array overflow of hw mode for preferred_hw_mode
+
+From: Wen Gong <quic_wgong@quicinc.com>
+
+[ Upstream commit 1e9b1363e2de1552ee4e3d74ac8bb43a194f1cb4 ]
+
+Currently ath12k define WMI_HOST_HW_MODE_DBS_OR_SBS=5 as max hw mode
+for enum wmi_host_hw_mode_config_type, it is also same for the array
+ath12k_hw_mode_pri_map.
+
+When tested with new version firmware/board data which support new
+hw mode eMLSR mode with hw mode value 8, it leads overflow usage for
+array ath12k_hw_mode_pri_map in function ath12k_wmi_hw_mode_caps(),
+and then lead preferred_hw_mode changed to 8, and finally function
+ath12k_pull_mac_phy_cap_svc_ready_ext() select the capability of hw
+mode 8, but the capability of eMLSR mode report from firmware does
+not support 2.4 GHz band for WCN7850, so finally 2.4 GHz band is
+disabled.
+
+Skip the hw mode which exceeds WMI_HOST_HW_MODE_MAX in function
+ath12k_wmi_hw_mode_caps() helps to avoid array overflow, then the 2.4
+GHz band will not be disabled.
+
+This is to keep compatibility with newer version firmware/board data
+files, this change is still needed after ath12k add eMLSR hw mode 8 in
+array ath12k_hw_mode_pri_map and enum wmi_host_hw_mode_config_type,
+because more hw mode maybe added in next firmware/board data version
+e.g hw mode 9, then it will also lead new array overflow without this
+change.
+
+Tested-on: WCN7850 hw2.0 PCI WLAN.HMT.1.0-03427-QCAHMTSWPL_V1.0_V2.0_SILICONZ-1.15378.4
+
+Signed-off-by: Wen Gong <quic_wgong@quicinc.com>
+Signed-off-by: Kalle Valo <quic_kvalo@quicinc.com>
+Link: https://lore.kernel.org/r/20230714072405.28705-1-quic_wgong@quicinc.com
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/wireless/ath/ath12k/wmi.c | 4 ++++
+ 1 file changed, 4 insertions(+)
+
+diff --git a/drivers/net/wireless/ath/ath12k/wmi.c b/drivers/net/wireless/ath/ath12k/wmi.c
+index 4928e4e916603..4f378f06e946e 100644
+--- a/drivers/net/wireless/ath/ath12k/wmi.c
++++ b/drivers/net/wireless/ath/ath12k/wmi.c
+@@ -3704,6 +3704,10 @@ static int ath12k_wmi_hw_mode_caps(struct ath12k_base *soc,
+ for (i = 0 ; i < svc_rdy_ext->n_hw_mode_caps; i++) {
+ hw_mode_caps = &svc_rdy_ext->hw_mode_caps[i];
+ mode = le32_to_cpu(hw_mode_caps->hw_mode_id);
++
++ if (mode >= WMI_HOST_HW_MODE_MAX)
++ continue;
++
+ pref = soc->wmi_ab.preferred_hw_mode;
+
+ if (ath12k_hw_mode_pri_map[mode] < ath12k_hw_mode_pri_map[pref]) {
+--
+2.40.1
+
--- /dev/null
+From cff630f8b0eb8208b2a9ae0cad76d96868161c56 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 26 Jul 2023 05:26:25 -0400
+Subject: wifi: ath12k: Fix a NULL pointer dereference in
+ ath12k_mac_op_hw_scan()
+
+From: Wen Gong <quic_wgong@quicinc.com>
+
+[ Upstream commit 8ad314da54c6dd223a6b6cc85019160aa842f659 ]
+
+In ath12k_mac_op_hw_scan(), the return value of kzalloc() is directly
+used in memcpy(), which may lead to a NULL pointer dereference on
+failure of kzalloc().
+
+Fix this bug by adding a check of arg.extraie.ptr.
+
+Tested-on: WCN7850 hw2.0 PCI WLAN.HMT.1.0-03427-QCAHMTSWPL_V1.0_V2.0_SILICONZ-1.15378.4
+
+Signed-off-by: Wen Gong <quic_wgong@quicinc.com>
+Signed-off-by: Kalle Valo <quic_kvalo@quicinc.com>
+Link: https://lore.kernel.org/r/20230726092625.3350-1-quic_wgong@quicinc.com
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/wireless/ath/ath12k/mac.c | 7 +++++--
+ 1 file changed, 5 insertions(+), 2 deletions(-)
+
+diff --git a/drivers/net/wireless/ath/ath12k/mac.c b/drivers/net/wireless/ath/ath12k/mac.c
+index 45d88e35fc2eb..d165b24094ad5 100644
+--- a/drivers/net/wireless/ath/ath12k/mac.c
++++ b/drivers/net/wireless/ath/ath12k/mac.c
+@@ -2755,9 +2755,12 @@ static int ath12k_mac_op_hw_scan(struct ieee80211_hw *hw,
+ arg.scan_id = ATH12K_SCAN_ID;
+
+ if (req->ie_len) {
++ arg.extraie.ptr = kmemdup(req->ie, req->ie_len, GFP_KERNEL);
++ if (!arg.extraie.ptr) {
++ ret = -ENOMEM;
++ goto exit;
++ }
+ arg.extraie.len = req->ie_len;
+- arg.extraie.ptr = kzalloc(req->ie_len, GFP_KERNEL);
+- memcpy(arg.extraie.ptr, req->ie, req->ie_len);
+ }
+
+ if (req->n_ssids) {
+--
+2.40.1
+
--- /dev/null
+From 89224cd238fb6f54b8c9e1849fcaf10ed4fb5225 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 22 Aug 2023 16:42:23 +0300
+Subject: wifi: ath12k: Fix memory leak in rx_desc and tx_desc
+
+From: Rajat Soni <quic_rajson@quicinc.com>
+
+[ Upstream commit afb522b36e76acaa9f8fc06d0a9742d841c47c16 ]
+
+Currently when ath12k_dp_cc_desc_init() is called we allocate
+memory to rx_descs and tx_descs. In ath12k_dp_cc_cleanup(), during
+descriptor cleanup rx_descs and tx_descs memory is not freed.
+
+This is cause of memory leak. These allocated memory should be
+freed in ath12k_dp_cc_cleanup.
+
+In ath12k_dp_cc_desc_init(), we can save base address of rx_descs
+and tx_descs. In ath12k_dp_cc_cleanup(), we can free rx_descs and
+tx_descs memory using their base address.
+
+Tested-on: QCN9274 hw2.0 PCI WLAN.WBE.1.0.1-00029-QCAHKSWPL_SILICONZ-1
+
+Signed-off-by: Rajat Soni <quic_rajson@quicinc.com>
+Signed-off-by: Kalle Valo <quic_kvalo@quicinc.com>
+Link: https://lore.kernel.org/r/20230718053510.30894-1-quic_rajson@quicinc.com
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/wireless/ath/ath12k/dp.c | 30 +++++++++++++++++++++++++++-
+ drivers/net/wireless/ath/ath12k/dp.h | 2 ++
+ 2 files changed, 31 insertions(+), 1 deletion(-)
+
+diff --git a/drivers/net/wireless/ath/ath12k/dp.c b/drivers/net/wireless/ath/ath12k/dp.c
+index ae1645d0f42a2..f933896f2a68d 100644
+--- a/drivers/net/wireless/ath/ath12k/dp.c
++++ b/drivers/net/wireless/ath/ath12k/dp.c
+@@ -1129,6 +1129,7 @@ static void ath12k_dp_cc_cleanup(struct ath12k_base *ab)
+ struct ath12k_dp *dp = &ab->dp;
+ struct sk_buff *skb;
+ int i;
++ u32 pool_id, tx_spt_page;
+
+ if (!dp->spt_info)
+ return;
+@@ -1148,6 +1149,14 @@ static void ath12k_dp_cc_cleanup(struct ath12k_base *ab)
+ dev_kfree_skb_any(skb);
+ }
+
++ for (i = 0; i < ATH12K_NUM_RX_SPT_PAGES; i++) {
++ if (!dp->spt_info->rxbaddr[i])
++ continue;
++
++ kfree(dp->spt_info->rxbaddr[i]);
++ dp->spt_info->rxbaddr[i] = NULL;
++ }
++
+ spin_unlock_bh(&dp->rx_desc_lock);
+
+ /* TX Descriptor cleanup */
+@@ -1170,6 +1179,21 @@ static void ath12k_dp_cc_cleanup(struct ath12k_base *ab)
+ spin_unlock_bh(&dp->tx_desc_lock[i]);
+ }
+
++ for (pool_id = 0; pool_id < ATH12K_HW_MAX_QUEUES; pool_id++) {
++ spin_lock_bh(&dp->tx_desc_lock[pool_id]);
++
++ for (i = 0; i < ATH12K_TX_SPT_PAGES_PER_POOL; i++) {
++ tx_spt_page = i + pool_id * ATH12K_TX_SPT_PAGES_PER_POOL;
++ if (!dp->spt_info->txbaddr[tx_spt_page])
++ continue;
++
++ kfree(dp->spt_info->txbaddr[tx_spt_page]);
++ dp->spt_info->txbaddr[tx_spt_page] = NULL;
++ }
++
++ spin_unlock_bh(&dp->tx_desc_lock[pool_id]);
++ }
++
+ /* unmap SPT pages */
+ for (i = 0; i < dp->num_spt_pages; i++) {
+ if (!dp->spt_info[i].vaddr)
+@@ -1343,6 +1367,8 @@ static int ath12k_dp_cc_desc_init(struct ath12k_base *ab)
+ return -ENOMEM;
+ }
+
++ dp->spt_info->rxbaddr[i] = &rx_descs[0];
++
+ for (j = 0; j < ATH12K_MAX_SPT_ENTRIES; j++) {
+ rx_descs[j].cookie = ath12k_dp_cc_cookie_gen(i, j);
+ rx_descs[j].magic = ATH12K_DP_RX_DESC_MAGIC;
+@@ -1368,8 +1394,10 @@ static int ath12k_dp_cc_desc_init(struct ath12k_base *ab)
+ return -ENOMEM;
+ }
+
++ tx_spt_page = i + pool_id * ATH12K_TX_SPT_PAGES_PER_POOL;
++ dp->spt_info->txbaddr[tx_spt_page] = &tx_descs[0];
++
+ for (j = 0; j < ATH12K_MAX_SPT_ENTRIES; j++) {
+- tx_spt_page = i + pool_id * ATH12K_TX_SPT_PAGES_PER_POOL;
+ ppt_idx = ATH12K_NUM_RX_SPT_PAGES + tx_spt_page;
+ tx_descs[j].desc_id = ath12k_dp_cc_cookie_gen(ppt_idx, j);
+ tx_descs[j].pool_id = pool_id;
+diff --git a/drivers/net/wireless/ath/ath12k/dp.h b/drivers/net/wireless/ath/ath12k/dp.h
+index 7c5dafce5a68d..9aeda0321cd75 100644
+--- a/drivers/net/wireless/ath/ath12k/dp.h
++++ b/drivers/net/wireless/ath/ath12k/dp.h
+@@ -289,6 +289,8 @@ struct ath12k_tx_desc_info {
+ struct ath12k_spt_info {
+ dma_addr_t paddr;
+ u64 *vaddr;
++ struct ath12k_rx_desc_info *rxbaddr[ATH12K_NUM_RX_SPT_PAGES];
++ struct ath12k_tx_desc_info *txbaddr[ATH12K_NUM_TX_SPT_PAGES];
+ };
+
+ struct ath12k_reo_queue_ref {
+--
+2.40.1
+
--- /dev/null
+From 8f1b9a2e9e5b3a20703319de84e8f52b31e198aa Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 24 Jul 2023 13:11:07 +0300
+Subject: wifi: ath9k: fix fortify warnings
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Dmitry Antipov <dmantipov@yandex.ru>
+
+[ Upstream commit 810e41cebb6c6e394f2068f839e1a3fc745a5dcc ]
+
+When compiling with gcc 13.1 and CONFIG_FORTIFY_SOURCE=y,
+I've noticed the following:
+
+In function ‘fortify_memcpy_chk’,
+ inlined from ‘ath_tx_complete_aggr’ at drivers/net/wireless/ath/ath9k/xmit.c:556:4,
+ inlined from ‘ath_tx_process_buffer’ at drivers/net/wireless/ath/ath9k/xmit.c:773:3:
+./include/linux/fortify-string.h:529:25: warning: call to ‘__read_overflow2_field’
+declared with attribute warning: detected read beyond size of field (2nd parameter);
+maybe use struct_group()? [-Wattribute-warning]
+ 529 | __read_overflow2_field(q_size_field, size);
+ | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+In function ‘fortify_memcpy_chk’,
+ inlined from ‘ath_tx_count_frames’ at drivers/net/wireless/ath/ath9k/xmit.c:473:3,
+ inlined from ‘ath_tx_complete_aggr’ at drivers/net/wireless/ath/ath9k/xmit.c:572:2,
+ inlined from ‘ath_tx_process_buffer’ at drivers/net/wireless/ath/ath9k/xmit.c:773:3:
+./include/linux/fortify-string.h:529:25: warning: call to ‘__read_overflow2_field’
+declared with attribute warning: detected read beyond size of field (2nd parameter);
+maybe use struct_group()? [-Wattribute-warning]
+ 529 | __read_overflow2_field(q_size_field, size);
+ | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+In both cases, the compiler complains on:
+
+memcpy(ba, &ts->ba_low, WME_BA_BMP_SIZE >> 3);
+
+which is the legal way to copy both 'ba_low' and following 'ba_high'
+members of 'struct ath_tx_status' at once (that is, issue one 8-byte
+'memcpy()' for two 4-byte fields). Since the fortification logic seems
+interprets this trick as an attempt to overread 4-byte 'ba_low', silence
+relevant warnings by using the convenient 'struct_group()' quirk.
+
+Suggested-by: Johannes Berg <johannes@sipsolutions.net>
+Signed-off-by: Dmitry Antipov <dmantipov@yandex.ru>
+Acked-by: Toke Høiland-Jørgensen <toke@toke.dk>
+Signed-off-by: Kalle Valo <quic_kvalo@quicinc.com>
+Link: https://lore.kernel.org/r/20230620080855.396851-2-dmantipov@yandex.ru
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/wireless/ath/ath9k/mac.h | 6 ++++--
+ drivers/net/wireless/ath/ath9k/xmit.c | 4 ++--
+ 2 files changed, 6 insertions(+), 4 deletions(-)
+
+diff --git a/drivers/net/wireless/ath/ath9k/mac.h b/drivers/net/wireless/ath/ath9k/mac.h
+index af44b33814ddc..f03d792732da7 100644
+--- a/drivers/net/wireless/ath/ath9k/mac.h
++++ b/drivers/net/wireless/ath/ath9k/mac.h
+@@ -115,8 +115,10 @@ struct ath_tx_status {
+ u8 qid;
+ u16 desc_id;
+ u8 tid;
+- u32 ba_low;
+- u32 ba_high;
++ struct_group(ba,
++ u32 ba_low;
++ u32 ba_high;
++ );
+ u32 evm0;
+ u32 evm1;
+ u32 evm2;
+diff --git a/drivers/net/wireless/ath/ath9k/xmit.c b/drivers/net/wireless/ath/ath9k/xmit.c
+index f6f2ab7a63ffc..42058368e6373 100644
+--- a/drivers/net/wireless/ath/ath9k/xmit.c
++++ b/drivers/net/wireless/ath/ath9k/xmit.c
+@@ -468,7 +468,7 @@ static void ath_tx_count_frames(struct ath_softc *sc, struct ath_buf *bf,
+ isaggr = bf_isaggr(bf);
+ if (isaggr) {
+ seq_st = ts->ts_seqnum;
+- memcpy(ba, &ts->ba_low, WME_BA_BMP_SIZE >> 3);
++ memcpy(ba, &ts->ba, WME_BA_BMP_SIZE >> 3);
+ }
+
+ while (bf) {
+@@ -551,7 +551,7 @@ static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq,
+ if (isaggr && txok) {
+ if (ts->ts_flags & ATH9K_TX_BA) {
+ seq_st = ts->ts_seqnum;
+- memcpy(ba, &ts->ba_low, WME_BA_BMP_SIZE >> 3);
++ memcpy(ba, &ts->ba, WME_BA_BMP_SIZE >> 3);
+ } else {
+ /*
+ * AR5416 can become deaf/mute when BA
+--
+2.40.1
+
--- /dev/null
+From e3e20f1ab24fe7ef989193b82cfdeb1741196298 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sun, 23 Jul 2023 12:04:02 +0800
+Subject: wifi: ath9k: fix printk specifier
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Dongliang Mu <dzm91@hust.edu.cn>
+
+[ Upstream commit 061115fbfb2ce5870c9a004d68dc63138c07c782 ]
+
+Smatch reports:
+
+ath_pci_probe() warn: argument 4 to %lx specifier is cast from pointer
+ath_ahb_probe() warn: argument 4 to %lx specifier is cast from pointer
+
+Fix it by modifying %lx to %p in the printk format string.
+
+Note that with this change, the pointer address will be printed as a
+hashed value by default. This is appropriate because the kernel
+should not leak kernel pointers to user space in an informational
+message. If someone wants to see the real address for debugging
+purposes, this can be achieved with the no_hash_pointers kernel option.
+
+Signed-off-by: Dongliang Mu <dzm91@hust.edu.cn>
+Acked-by: Toke Høiland-Jørgensen <toke@toke.dk>
+Signed-off-by: Kalle Valo <quic_kvalo@quicinc.com>
+Link: https://lore.kernel.org/r/20230723040403.296723-1-dzm91@hust.edu.cn
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/wireless/ath/ath9k/ahb.c | 4 ++--
+ drivers/net/wireless/ath/ath9k/pci.c | 4 ++--
+ 2 files changed, 4 insertions(+), 4 deletions(-)
+
+diff --git a/drivers/net/wireless/ath/ath9k/ahb.c b/drivers/net/wireless/ath/ath9k/ahb.c
+index 9cd12b20b18d8..9bfaadfa6c009 100644
+--- a/drivers/net/wireless/ath/ath9k/ahb.c
++++ b/drivers/net/wireless/ath/ath9k/ahb.c
+@@ -132,8 +132,8 @@ static int ath_ahb_probe(struct platform_device *pdev)
+
+ ah = sc->sc_ah;
+ ath9k_hw_name(ah, hw_name, sizeof(hw_name));
+- wiphy_info(hw->wiphy, "%s mem=0x%lx, irq=%d\n",
+- hw_name, (unsigned long)mem, irq);
++ wiphy_info(hw->wiphy, "%s mem=0x%p, irq=%d\n",
++ hw_name, mem, irq);
+
+ return 0;
+
+diff --git a/drivers/net/wireless/ath/ath9k/pci.c b/drivers/net/wireless/ath/ath9k/pci.c
+index a09f9d223f3de..0633589b85c23 100644
+--- a/drivers/net/wireless/ath/ath9k/pci.c
++++ b/drivers/net/wireless/ath/ath9k/pci.c
+@@ -988,8 +988,8 @@ static int ath_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id)
+ sc->sc_ah->msi_reg = 0;
+
+ ath9k_hw_name(sc->sc_ah, hw_name, sizeof(hw_name));
+- wiphy_info(hw->wiphy, "%s mem=0x%lx, irq=%d\n",
+- hw_name, (unsigned long)sc->mem, pdev->irq);
++ wiphy_info(hw->wiphy, "%s mem=0x%p, irq=%d\n",
++ hw_name, sc->mem, pdev->irq);
+
+ return 0;
+
+--
+2.40.1
+
--- /dev/null
+From da23de484fdcc386620940a6227cda54c6266b5d Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 15 Aug 2023 18:32:03 +0200
+Subject: wifi: cfg80211: ocb: don't leave if not joined
+
+From: Johannes Berg <johannes.berg@intel.com>
+
+[ Upstream commit abc76cf552e13cfa88a204b362a86b0e08e95228 ]
+
+If there's no OCB state, don't ask the driver/mac80211 to
+leave, since that's just confusing. Since set/clear the
+chandef state, that's a simple check.
+
+Reported-by: syzbot+09d1cd2f71e6dd3bfd2c@syzkaller.appspotmail.com
+Signed-off-by: Johannes Berg <johannes.berg@intel.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/wireless/ocb.c | 3 +++
+ 1 file changed, 3 insertions(+)
+
+diff --git a/net/wireless/ocb.c b/net/wireless/ocb.c
+index 27a1732264f95..29afaf3da54f3 100644
+--- a/net/wireless/ocb.c
++++ b/net/wireless/ocb.c
+@@ -68,6 +68,9 @@ int __cfg80211_leave_ocb(struct cfg80211_registered_device *rdev,
+ if (!rdev->ops->leave_ocb)
+ return -EOPNOTSUPP;
+
++ if (!wdev->u.ocb.chandef.chan)
++ return -ENOTCONN;
++
+ err = rdev_leave_ocb(rdev, dev);
+ if (!err)
+ memset(&wdev->u.ocb.chandef, 0, sizeof(wdev->u.ocb.chandef));
+--
+2.40.1
+
--- /dev/null
+From f3fce875eacacae0d406c2bc8c83e87b23f5d855 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 15 Aug 2023 18:09:00 +0200
+Subject: wifi: cfg80211: reject auth/assoc to AP with our address
+
+From: Johannes Berg <johannes.berg@intel.com>
+
+[ Upstream commit 5d4e04bf3a0f098bd9033de3a5291810fa14c7a6 ]
+
+If the AP uses our own address as its MLD address or BSSID, then
+clearly something's wrong. Reject such connections so we don't
+try and fail later.
+
+Reported-by: syzbot+2676771ed06a6df166ad@syzkaller.appspotmail.com
+Signed-off-by: Johannes Berg <johannes.berg@intel.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/wireless/mlme.c | 13 +++++++++++++
+ 1 file changed, 13 insertions(+)
+
+diff --git a/net/wireless/mlme.c b/net/wireless/mlme.c
+index ac059cefbeb39..775cac4d61006 100644
+--- a/net/wireless/mlme.c
++++ b/net/wireless/mlme.c
+@@ -281,6 +281,11 @@ int cfg80211_mlme_auth(struct cfg80211_registered_device *rdev,
+ ether_addr_equal(req->bss->bssid, wdev->u.client.connected_addr))
+ return -EALREADY;
+
++ if (ether_addr_equal(req->bss->bssid, dev->dev_addr) ||
++ (req->link_id >= 0 &&
++ ether_addr_equal(req->ap_mld_addr, dev->dev_addr)))
++ return -EINVAL;
++
+ return rdev_auth(rdev, dev, req);
+ }
+
+@@ -335,6 +340,9 @@ int cfg80211_mlme_assoc(struct cfg80211_registered_device *rdev,
+ if (req->links[i].bss == req->links[j].bss)
+ return -EINVAL;
+ }
++
++ if (ether_addr_equal(req->links[i].bss->bssid, dev->dev_addr))
++ return -EINVAL;
+ }
+
+ if (wdev->connected &&
+@@ -342,6 +350,11 @@ int cfg80211_mlme_assoc(struct cfg80211_registered_device *rdev,
+ !ether_addr_equal(wdev->u.client.connected_addr, req->prev_bssid)))
+ return -EALREADY;
+
++ if ((req->bss && ether_addr_equal(req->bss->bssid, dev->dev_addr)) ||
++ (req->link_id >= 0 &&
++ ether_addr_equal(req->ap_mld_addr, dev->dev_addr)))
++ return -EINVAL;
++
+ cfg80211_oper_and_ht_capa(&req->ht_capa_mask,
+ rdev->wiphy.ht_capa_mod_mask);
+ cfg80211_oper_and_vht_capa(&req->vht_capa_mask,
+--
+2.40.1
+
--- /dev/null
+From 482475fe2d37a43a2dab551a5d5c70222e78f683 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 22 Aug 2023 10:33:15 +0300
+Subject: wifi: iwlwifi: pcie: avoid a warning in case prepare card failed
+
+From: Avraham Stern <avraham.stern@intel.com>
+
+[ Upstream commit 057381ddac0593c6e4ca8f58732830d8542b9c4e ]
+
+In case CSME holds the NIC and SAP connection is already established,
+iwl_pcie_prepare_card_hw() during iwl_pci_probe() will fail
+(which is fine since CSME will release the nic later when asked with
+a SAP message). In this case tring to grab nic access to read the
+crf ids will fail with a warning.
+Avoid the warning by only trying to read the crf ids in case prepare
+card succeeded.
+
+Signed-off-by: Avraham Stern <avraham.stern@intel.com>
+Signed-off-by: Gregory Greenman <gregory.greenman@intel.com>
+Link: https://lore.kernel.org/r/20230822103048.9b026fa7b97e.I12bea7e6eef54eeeaf916b68d71583e92ff310fd@changeid
+Signed-off-by: Johannes Berg <johannes.berg@intel.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/wireless/intel/iwlwifi/pcie/drv.c | 11 +----------
+ 1 file changed, 1 insertion(+), 10 deletions(-)
+
+diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/drv.c b/drivers/net/wireless/intel/iwlwifi/pcie/drv.c
+index 73c1fb3c0c5ec..bc83d2ba55c67 100644
+--- a/drivers/net/wireless/intel/iwlwifi/pcie/drv.c
++++ b/drivers/net/wireless/intel/iwlwifi/pcie/drv.c
+@@ -1132,12 +1132,6 @@ static int get_crf_id(struct iwl_trans *iwl_trans)
+ else
+ sd_reg_ver_addr = SD_REG_VER;
+
+- if (!iwl_trans_grab_nic_access(iwl_trans)) {
+- IWL_ERR(iwl_trans, "Failed to grab nic access before reading crf id\n");
+- ret = -EIO;
+- goto out;
+- }
+-
+ /* Enable access to peripheral registers */
+ val = iwl_read_umac_prph_no_grab(iwl_trans, WFPM_CTRL_REG);
+ val |= ENABLE_WFPM;
+@@ -1157,9 +1151,6 @@ static int get_crf_id(struct iwl_trans *iwl_trans)
+ iwl_trans->hw_crf_id, iwl_trans->hw_cnv_id,
+ iwl_trans->hw_wfpm_id);
+
+- iwl_trans_release_nic_access(iwl_trans);
+-
+-out:
+ return ret;
+ }
+
+@@ -1351,6 +1342,7 @@ static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
+ if (ret)
+ goto out_free_trans;
+ if (iwl_trans_grab_nic_access(iwl_trans)) {
++ get_crf_id(iwl_trans);
+ /* all good */
+ iwl_trans_release_nic_access(iwl_trans);
+ } else {
+@@ -1360,7 +1352,6 @@ static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
+ }
+
+ iwl_trans->hw_rf_id = iwl_read32(iwl_trans, CSR_HW_RF_ID);
+- get_crf_id(iwl_trans);
+
+ /*
+ * The RF_ID is set to zero in blank OTP so read version to
+--
+2.40.1
+
--- /dev/null
+From 8a8c62d5a8d5a05a40e143438726004b01b4d9d2 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 15 Aug 2023 18:41:32 +0200
+Subject: wifi: mac80211: check for station first in client probe
+
+From: Johannes Berg <johannes.berg@intel.com>
+
+[ Upstream commit 67dfa589aa8806c7959cbca2f4613b8d41c75a06 ]
+
+When probing a client, first check if we have it, and then
+check for the channel context, otherwise you can trigger
+the warning there easily by probing when the AP isn't even
+started yet. Since a client existing means the AP is also
+operating, we can then keep the warning.
+
+Also simplify the moved code a bit.
+
+Reported-by: syzbot+999fac712d84878a7379@syzkaller.appspotmail.com
+Signed-off-by: Johannes Berg <johannes.berg@intel.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/mac80211/cfg.c | 15 ++++++++-------
+ 1 file changed, 8 insertions(+), 7 deletions(-)
+
+diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c
+index d354b32a20f8f..45e7a5d9c7d94 100644
+--- a/net/mac80211/cfg.c
++++ b/net/mac80211/cfg.c
+@@ -4133,19 +4133,20 @@ static int ieee80211_probe_client(struct wiphy *wiphy, struct net_device *dev,
+ mutex_lock(&local->mtx);
+
+ rcu_read_lock();
++ sta = sta_info_get_bss(sdata, peer);
++ if (!sta) {
++ ret = -ENOLINK;
++ goto unlock;
++ }
++
++ qos = sta->sta.wme;
++
+ chanctx_conf = rcu_dereference(sdata->vif.bss_conf.chanctx_conf);
+ if (WARN_ON(!chanctx_conf)) {
+ ret = -EINVAL;
+ goto unlock;
+ }
+ band = chanctx_conf->def.chan->band;
+- sta = sta_info_get_bss(sdata, peer);
+- if (sta) {
+- qos = sta->sta.wme;
+- } else {
+- ret = -ENOLINK;
+- goto unlock;
+- }
+
+ if (qos) {
+ fc = cpu_to_le16(IEEE80211_FTYPE_DATA |
+--
+2.40.1
+
--- /dev/null
+From 7f7f4659ca96cef28a401bf2d2046a8b87af4da5 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 15 Aug 2023 17:51:05 +0200
+Subject: wifi: mac80211: check S1G action frame size
+
+From: Johannes Berg <johannes.berg@intel.com>
+
+[ Upstream commit 19e4a47ee74718a22e963e8a647c8c3bfe8bb05c ]
+
+Before checking the action code, check that it even
+exists in the frame.
+
+Reported-by: syzbot+be9c824e6f269d608288@syzkaller.appspotmail.com
+Signed-off-by: Johannes Berg <johannes.berg@intel.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/mac80211/rx.c | 4 ++++
+ 1 file changed, 4 insertions(+)
+
+diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c
+index 0af2599c17e8d..e751cda5eef69 100644
+--- a/net/mac80211/rx.c
++++ b/net/mac80211/rx.c
+@@ -3734,6 +3734,10 @@ ieee80211_rx_h_action(struct ieee80211_rx_data *rx)
+ break;
+ goto queue;
+ case WLAN_CATEGORY_S1G:
++ if (len < offsetofend(typeof(*mgmt),
++ u.action.u.s1g.action_code))
++ break;
++
+ switch (mgmt->u.action.u.s1g.action_code) {
+ case WLAN_S1G_TWT_SETUP:
+ case WLAN_S1G_TWT_TEARDOWN:
+--
+2.40.1
+
--- /dev/null
+From a0887212b95d8db71a244327cef38cf4dcb79d93 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 15 Aug 2023 21:28:01 +0200
+Subject: wifi: mac80211_hwsim: drop short frames
+
+From: Johannes Berg <johannes.berg@intel.com>
+
+[ Upstream commit fba360a047d5eeeb9d4b7c3a9b1c8308980ce9a6 ]
+
+While technically some control frames like ACK are shorter and
+end after Address 1, such frames shouldn't be forwarded through
+wmediumd or similar userspace, so require the full 3-address
+header to avoid accessing invalid memory if shorter frames are
+passed in.
+
+Reported-by: syzbot+b2645b5bf1512b81fa22@syzkaller.appspotmail.com
+Reviewed-by: Jeff Johnson <quic_jjohnson@quicinc.com>
+Signed-off-by: Johannes Berg <johannes.berg@intel.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/wireless/virtual/mac80211_hwsim.c | 7 ++++---
+ 1 file changed, 4 insertions(+), 3 deletions(-)
+
+diff --git a/drivers/net/wireless/virtual/mac80211_hwsim.c b/drivers/net/wireless/virtual/mac80211_hwsim.c
+index f446fd0e8cd0d..dd516cec41973 100644
+--- a/drivers/net/wireless/virtual/mac80211_hwsim.c
++++ b/drivers/net/wireless/virtual/mac80211_hwsim.c
+@@ -5626,14 +5626,15 @@ static int hwsim_cloned_frame_received_nl(struct sk_buff *skb_2,
+ frame_data_len = nla_len(info->attrs[HWSIM_ATTR_FRAME]);
+ frame_data = (void *)nla_data(info->attrs[HWSIM_ATTR_FRAME]);
+
++ if (frame_data_len < sizeof(struct ieee80211_hdr_3addr) ||
++ frame_data_len > IEEE80211_MAX_DATA_LEN)
++ goto err;
++
+ /* Allocate new skb here */
+ skb = alloc_skb(frame_data_len, GFP_KERNEL);
+ if (skb == NULL)
+ goto err;
+
+- if (frame_data_len > IEEE80211_MAX_DATA_LEN)
+- goto err;
+-
+ /* Copy the data */
+ skb_put_data(skb, frame_data, frame_data_len);
+
+--
+2.40.1
+
--- /dev/null
+From 35b4a45ebb534c963be720ff8be8c5cd238e0604 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 29 Jun 2023 11:51:01 +0300
+Subject: wifi: mwifiex: fix fortify warning
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Dmitry Antipov <dmantipov@yandex.ru>
+
+[ Upstream commit dcce94b80a954a8968ff29fafcfb066d6197fa9a ]
+
+When compiling with gcc 13.1 and CONFIG_FORTIFY_SOURCE=y,
+I've noticed the following:
+
+In function ‘fortify_memcpy_chk’,
+ inlined from ‘mwifiex_construct_tdls_action_frame’ at drivers/net/wireless/marvell/mwifiex/tdls.c:765:3,
+ inlined from ‘mwifiex_send_tdls_action_frame’ at drivers/net/wireless/marvell/mwifiex/tdls.c:856:6:
+./include/linux/fortify-string.h:529:25: warning: call to ‘__read_overflow2_field’
+declared with attribute warning: detected read beyond size of field (2nd parameter);
+maybe use struct_group()? [-Wattribute-warning]
+ 529 | __read_overflow2_field(q_size_field, size);
+ | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+The compiler actually complains on:
+
+memmove(pos + ETH_ALEN, &mgmt->u.action.category,
+ sizeof(mgmt->u.action.u.tdls_discover_resp));
+
+and it happens because the fortification logic interprets this
+as an attempt to overread 1-byte 'u.action.category' member of
+'struct ieee80211_mgmt'. To silence this warning, it's enough
+to pass an address of 'u.action' itself instead of an address
+of its first member.
+
+This also fixes an improper usage of 'sizeof()'. Since 'skb' is
+extended with 'sizeof(mgmt->u.action.u.tdls_discover_resp) + 1'
+bytes (where 1 is actually 'sizeof(mgmt->u.action.category)'),
+I assume that the same number of bytes should be copied.
+
+Suggested-by: Brian Norris <briannorris@chromium.org>
+Signed-off-by: Dmitry Antipov <dmantipov@yandex.ru>
+Reviewed-by: Brian Norris <briannorris@chromium.org>
+Signed-off-by: Kalle Valo <kvalo@kernel.org>
+Link: https://lore.kernel.org/r/20230629085115.180499-2-dmantipov@yandex.ru
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/wireless/marvell/mwifiex/tdls.c | 9 ++++++---
+ 1 file changed, 6 insertions(+), 3 deletions(-)
+
+diff --git a/drivers/net/wireless/marvell/mwifiex/tdls.c b/drivers/net/wireless/marvell/mwifiex/tdls.c
+index 97bb87c3676bb..6c60621b6cccb 100644
+--- a/drivers/net/wireless/marvell/mwifiex/tdls.c
++++ b/drivers/net/wireless/marvell/mwifiex/tdls.c
+@@ -735,6 +735,7 @@ mwifiex_construct_tdls_action_frame(struct mwifiex_private *priv,
+ int ret;
+ u16 capab;
+ struct ieee80211_ht_cap *ht_cap;
++ unsigned int extra;
+ u8 radio, *pos;
+
+ capab = priv->curr_bss_params.bss_descriptor.cap_info_bitmap;
+@@ -753,7 +754,10 @@ mwifiex_construct_tdls_action_frame(struct mwifiex_private *priv,
+
+ switch (action_code) {
+ case WLAN_PUB_ACTION_TDLS_DISCOVER_RES:
+- skb_put(skb, sizeof(mgmt->u.action.u.tdls_discover_resp) + 1);
++ /* See the layout of 'struct ieee80211_mgmt'. */
++ extra = sizeof(mgmt->u.action.u.tdls_discover_resp) +
++ sizeof(mgmt->u.action.category);
++ skb_put(skb, extra);
+ mgmt->u.action.category = WLAN_CATEGORY_PUBLIC;
+ mgmt->u.action.u.tdls_discover_resp.action_code =
+ WLAN_PUB_ACTION_TDLS_DISCOVER_RES;
+@@ -762,8 +766,7 @@ mwifiex_construct_tdls_action_frame(struct mwifiex_private *priv,
+ mgmt->u.action.u.tdls_discover_resp.capability =
+ cpu_to_le16(capab);
+ /* move back for addr4 */
+- memmove(pos + ETH_ALEN, &mgmt->u.action.category,
+- sizeof(mgmt->u.action.u.tdls_discover_resp));
++ memmove(pos + ETH_ALEN, &mgmt->u.action, extra);
+ /* init address 4 */
+ eth_broadcast_addr(pos);
+
+--
+2.40.1
+
--- /dev/null
+From 737b7dd1f54acbfd8c49fcecaf4d1b4786ff663b Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 28 Jun 2023 10:23:15 +0300
+Subject: wifi: rtw88: delete timer and free skb queue when unloading
+
+From: Dmitry Antipov <dmantipov@yandex.ru>
+
+[ Upstream commit 634fcbcaa4062db39aeb5ac6ed1bc1feb8dd5216 ]
+
+Fix possible crash and memory leak on driver unload by deleting
+TX purge timer and freeing C2H queue in 'rtw_core_deinit()',
+shrink critical section in the latter by freeing COEX queue
+out of TX report lock scope.
+
+Reviewed-by: Ping-Ke Shih <pkshih@realtek.com>
+Signed-off-by: Dmitry Antipov <dmantipov@yandex.ru>
+Signed-off-by: Kalle Valo <kvalo@kernel.org>
+Link: https://lore.kernel.org/r/20230628072327.167196-1-dmantipov@yandex.ru
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/wireless/realtek/rtw88/main.c | 4 +++-
+ 1 file changed, 3 insertions(+), 1 deletion(-)
+
+diff --git a/drivers/net/wireless/realtek/rtw88/main.c b/drivers/net/wireless/realtek/rtw88/main.c
+index c853e2f2d448f..c2ddb4d382af5 100644
+--- a/drivers/net/wireless/realtek/rtw88/main.c
++++ b/drivers/net/wireless/realtek/rtw88/main.c
+@@ -2183,10 +2183,12 @@ void rtw_core_deinit(struct rtw_dev *rtwdev)
+ release_firmware(wow_fw->firmware);
+
+ destroy_workqueue(rtwdev->tx_wq);
++ timer_delete_sync(&rtwdev->tx_report.purge_timer);
+ spin_lock_irqsave(&rtwdev->tx_report.q_lock, flags);
+ skb_queue_purge(&rtwdev->tx_report.queue);
+- skb_queue_purge(&rtwdev->coex.queue);
+ spin_unlock_irqrestore(&rtwdev->tx_report.q_lock, flags);
++ skb_queue_purge(&rtwdev->coex.queue);
++ skb_queue_purge(&rtwdev->c2h_queue);
+
+ list_for_each_entry_safe(rsvd_pkt, tmp, &rtwdev->rsvd_page_list,
+ build_list) {
+--
+2.40.1
+
--- /dev/null
+From 21f2efbca8041458beb0daac19b6aea1ff0bbcb4 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 21 Jun 2023 12:36:55 +0300
+Subject: wifi: wil6210: fix fortify warnings
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Dmitry Antipov <dmantipov@yandex.ru>
+
+[ Upstream commit 1ad8237e971630c66a1a6194491e0837b64d00e0 ]
+
+When compiling with gcc 13.1 and CONFIG_FORTIFY_SOURCE=y,
+I've noticed the following:
+
+In function ‘fortify_memcpy_chk’,
+ inlined from ‘wil_rx_crypto_check_edma’ at drivers/net/wireless/ath/wil6210/txrx_edma.c:566:2:
+./include/linux/fortify-string.h:529:25: warning: call to ‘__read_overflow2_field’
+declared with attribute warning: detected read beyond size of field (2nd parameter);
+maybe use struct_group()? [-Wattribute-warning]
+ 529 | __read_overflow2_field(q_size_field, size);
+ | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+where the compiler complains on:
+
+const u8 *pn;
+...
+pn = (u8 *)&st->ext.pn_15_0;
+...
+memcpy(cc->pn, pn, IEEE80211_GCMP_PN_LEN);
+
+and:
+
+In function ‘fortify_memcpy_chk’,
+ inlined from ‘wil_rx_crypto_check’ at drivers/net/wireless/ath/wil6210/txrx.c:684:2:
+./include/linux/fortify-string.h:529:25: warning: call to ‘__read_overflow2_field’
+declared with attribute warning: detected read beyond size of field (2nd parameter);
+maybe use struct_group()? [-Wattribute-warning]
+ 529 | __read_overflow2_field(q_size_field, size);
+ | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+where the compiler complains on:
+
+const u8 *pn = (u8 *)&d->mac.pn_15_0;
+...
+memcpy(cc->pn, pn, IEEE80211_GCMP_PN_LEN);
+
+In both cases, the fortification logic interprets 'memcpy()' as 6-byte
+overread of 2-byte field 'pn_15_0' of 'struct wil_rx_status_extension'
+and 'pn_15_0' of 'struct vring_rx_mac', respectively. To silence
+these warnings, last two fields of the aforementioned structures
+are grouped using 'struct_group_attr(pn, __packed' quirk.
+
+Signed-off-by: Dmitry Antipov <dmantipov@yandex.ru>
+Signed-off-by: Kalle Valo <quic_kvalo@quicinc.com>
+Link: https://lore.kernel.org/r/20230621093711.80118-1-dmantipov@yandex.ru
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/wireless/ath/wil6210/txrx.c | 2 +-
+ drivers/net/wireless/ath/wil6210/txrx.h | 6 ++++--
+ drivers/net/wireless/ath/wil6210/txrx_edma.c | 2 +-
+ drivers/net/wireless/ath/wil6210/txrx_edma.h | 6 ++++--
+ 4 files changed, 10 insertions(+), 6 deletions(-)
+
+diff --git a/drivers/net/wireless/ath/wil6210/txrx.c b/drivers/net/wireless/ath/wil6210/txrx.c
+index 237cbd5c5060b..f29ac6de71399 100644
+--- a/drivers/net/wireless/ath/wil6210/txrx.c
++++ b/drivers/net/wireless/ath/wil6210/txrx.c
+@@ -666,7 +666,7 @@ static int wil_rx_crypto_check(struct wil6210_priv *wil, struct sk_buff *skb)
+ struct wil_tid_crypto_rx *c = mc ? &s->group_crypto_rx :
+ &s->tid_crypto_rx[tid];
+ struct wil_tid_crypto_rx_single *cc = &c->key_id[key_id];
+- const u8 *pn = (u8 *)&d->mac.pn_15_0;
++ const u8 *pn = (u8 *)&d->mac.pn;
+
+ if (!cc->key_set) {
+ wil_err_ratelimited(wil,
+diff --git a/drivers/net/wireless/ath/wil6210/txrx.h b/drivers/net/wireless/ath/wil6210/txrx.h
+index 1ae1bec1b97f1..689f68d89a440 100644
+--- a/drivers/net/wireless/ath/wil6210/txrx.h
++++ b/drivers/net/wireless/ath/wil6210/txrx.h
+@@ -343,8 +343,10 @@ struct vring_rx_mac {
+ u32 d0;
+ u32 d1;
+ u16 w4;
+- u16 pn_15_0;
+- u32 pn_47_16;
++ struct_group_attr(pn, __packed,
++ u16 pn_15_0;
++ u32 pn_47_16;
++ );
+ } __packed;
+
+ /* Rx descriptor - DMA part
+diff --git a/drivers/net/wireless/ath/wil6210/txrx_edma.c b/drivers/net/wireless/ath/wil6210/txrx_edma.c
+index 201c8c35e0c9e..1ba1f21ebea26 100644
+--- a/drivers/net/wireless/ath/wil6210/txrx_edma.c
++++ b/drivers/net/wireless/ath/wil6210/txrx_edma.c
+@@ -548,7 +548,7 @@ static int wil_rx_crypto_check_edma(struct wil6210_priv *wil,
+ s = &wil->sta[cid];
+ c = mc ? &s->group_crypto_rx : &s->tid_crypto_rx[tid];
+ cc = &c->key_id[key_id];
+- pn = (u8 *)&st->ext.pn_15_0;
++ pn = (u8 *)&st->ext.pn;
+
+ if (!cc->key_set) {
+ wil_err_ratelimited(wil,
+diff --git a/drivers/net/wireless/ath/wil6210/txrx_edma.h b/drivers/net/wireless/ath/wil6210/txrx_edma.h
+index c736f7413a35f..ee90e225bb050 100644
+--- a/drivers/net/wireless/ath/wil6210/txrx_edma.h
++++ b/drivers/net/wireless/ath/wil6210/txrx_edma.h
+@@ -330,8 +330,10 @@ struct wil_rx_status_extension {
+ u32 d0;
+ u32 d1;
+ __le16 seq_num; /* only lower 12 bits */
+- u16 pn_15_0;
+- u32 pn_47_16;
++ struct_group_attr(pn, __packed,
++ u16 pn_15_0;
++ u32 pn_47_16;
++ );
+ } __packed;
+
+ struct wil_rx_status_extended {
+--
+2.40.1
+
--- /dev/null
+From 62267dfba8f2fd09e19c2dc1cc61379f5de6c2c3 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 8 Aug 2023 22:52:42 -0500
+Subject: x86/amd_nb: Add PCI IDs for AMD Family 1Ah-based models
+
+From: Avadhut Naik <Avadhut.Naik@amd.com>
+
+[ Upstream commit c64016609b6f66b753b5f37929a191477fa584c0 ]
+
+Add new PCI Device IDs required to support AMD's new Family 1Ah-based
+models 00h-1Fh, 20h and 40h-4Fh.
+
+ [ bp: Zap a useless sentence. ]
+
+Co-developed-by: Mario Limonciello <mario.limonciello@amd.com>
+Signed-off-by: Mario Limonciello <mario.limonciello@amd.com>
+Signed-off-by: Avadhut Naik <Avadhut.Naik@amd.com>
+Signed-off-by: Borislav Petkov (AMD) <bp@alien8.de>
+Link: https://lore.kernel.org/r/20230809035244.2722455-2-avadhut.naik@amd.com
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ arch/x86/kernel/amd_nb.c | 8 ++++++++
+ include/linux/pci_ids.h | 2 ++
+ 2 files changed, 10 insertions(+)
+
+diff --git a/arch/x86/kernel/amd_nb.c b/arch/x86/kernel/amd_nb.c
+index 035a3db5330b0..356de955e78dd 100644
+--- a/arch/x86/kernel/amd_nb.c
++++ b/arch/x86/kernel/amd_nb.c
+@@ -24,6 +24,8 @@
+ #define PCI_DEVICE_ID_AMD_19H_M40H_ROOT 0x14b5
+ #define PCI_DEVICE_ID_AMD_19H_M60H_ROOT 0x14d8
+ #define PCI_DEVICE_ID_AMD_19H_M70H_ROOT 0x14e8
++#define PCI_DEVICE_ID_AMD_1AH_M00H_ROOT 0x153a
++#define PCI_DEVICE_ID_AMD_1AH_M20H_ROOT 0x1507
+ #define PCI_DEVICE_ID_AMD_MI200_ROOT 0x14bb
+
+ #define PCI_DEVICE_ID_AMD_17H_DF_F4 0x1464
+@@ -39,6 +41,7 @@
+ #define PCI_DEVICE_ID_AMD_19H_M60H_DF_F4 0x14e4
+ #define PCI_DEVICE_ID_AMD_19H_M70H_DF_F4 0x14f4
+ #define PCI_DEVICE_ID_AMD_19H_M78H_DF_F4 0x12fc
++#define PCI_DEVICE_ID_AMD_1AH_M00H_DF_F4 0x12c4
+ #define PCI_DEVICE_ID_AMD_MI200_DF_F4 0x14d4
+
+ /* Protect the PCI config register pairs used for SMN. */
+@@ -56,6 +59,8 @@ static const struct pci_device_id amd_root_ids[] = {
+ { PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_19H_M40H_ROOT) },
+ { PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_19H_M60H_ROOT) },
+ { PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_19H_M70H_ROOT) },
++ { PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_1AH_M00H_ROOT) },
++ { PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_1AH_M20H_ROOT) },
+ { PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_MI200_ROOT) },
+ {}
+ };
+@@ -85,6 +90,8 @@ static const struct pci_device_id amd_nb_misc_ids[] = {
+ { PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_19H_M60H_DF_F3) },
+ { PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_19H_M70H_DF_F3) },
+ { PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_19H_M78H_DF_F3) },
++ { PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_1AH_M00H_DF_F3) },
++ { PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_1AH_M20H_DF_F3) },
+ { PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_MI200_DF_F3) },
+ {}
+ };
+@@ -106,6 +113,7 @@ static const struct pci_device_id amd_nb_link_ids[] = {
+ { PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_19H_M40H_DF_F4) },
+ { PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_19H_M50H_DF_F4) },
+ { PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_CNB17H_F4) },
++ { PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_1AH_M00H_DF_F4) },
+ { PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_MI200_DF_F4) },
+ {}
+ };
+diff --git a/include/linux/pci_ids.h b/include/linux/pci_ids.h
+index 2dc75df1437fb..8f9a459e16718 100644
+--- a/include/linux/pci_ids.h
++++ b/include/linux/pci_ids.h
+@@ -576,6 +576,8 @@
+ #define PCI_DEVICE_ID_AMD_19H_M60H_DF_F3 0x14e3
+ #define PCI_DEVICE_ID_AMD_19H_M70H_DF_F3 0x14f3
+ #define PCI_DEVICE_ID_AMD_19H_M78H_DF_F3 0x12fb
++#define PCI_DEVICE_ID_AMD_1AH_M00H_DF_F3 0x12c3
++#define PCI_DEVICE_ID_AMD_1AH_M20H_DF_F3 0x16fb
+ #define PCI_DEVICE_ID_AMD_MI200_DF_F3 0x14d3
+ #define PCI_DEVICE_ID_AMD_CNB17H_F3 0x1703
+ #define PCI_DEVICE_ID_AMD_LANCE 0x2000
+--
+2.40.1
+
--- /dev/null
+From 5b8bba4dc3e5f5487fbd315502e7c6d606fa24ee Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 15 Sep 2023 10:02:21 +0300
+Subject: x86/boot/compressed: Reserve more memory for page tables
+
+From: Kirill A. Shutemov <kirill.shutemov@linux.intel.com>
+
+[ Upstream commit f530ee95b72e77b09c141c4b1a4b94d1199ffbd9 ]
+
+The decompressor has a hard limit on the number of page tables it can
+allocate. This limit is defined at compile-time and will cause boot
+failure if it is reached.
+
+The kernel is very strict and calculates the limit precisely for the
+worst-case scenario based on the current configuration. However, it is
+easy to forget to adjust the limit when a new use-case arises. The
+worst-case scenario is rarely encountered during sanity checks.
+
+In the case of enabling 5-level paging, a use-case was overlooked. The
+limit needs to be increased by one to accommodate the additional level.
+This oversight went unnoticed until Aaron attempted to run the kernel
+via kexec with 5-level paging and unaccepted memory enabled.
+
+Update wost-case calculations to include 5-level paging.
+
+To address this issue, let's allocate some extra space for page tables.
+128K should be sufficient for any use-case. The logic can be simplified
+by using a single value for all kernel configurations.
+
+[ Also add a warning, should this memory run low - by Dave Hansen. ]
+
+Fixes: 34bbb0009f3b ("x86/boot/compressed: Enable 5-level paging during decompression stage")
+Reported-by: Aaron Lu <aaron.lu@intel.com>
+Signed-off-by: Kirill A. Shutemov <kirill.shutemov@linux.intel.com>
+Signed-off-by: Ingo Molnar <mingo@kernel.org>
+Link: https://lore.kernel.org/r/20230915070221.10266-1-kirill.shutemov@linux.intel.com
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ arch/x86/boot/compressed/ident_map_64.c | 8 +++++
+ arch/x86/include/asm/boot.h | 45 +++++++++++++++++--------
+ 2 files changed, 39 insertions(+), 14 deletions(-)
+
+diff --git a/arch/x86/boot/compressed/ident_map_64.c b/arch/x86/boot/compressed/ident_map_64.c
+index bcc956c17872b..08f93b0401bbd 100644
+--- a/arch/x86/boot/compressed/ident_map_64.c
++++ b/arch/x86/boot/compressed/ident_map_64.c
+@@ -59,6 +59,14 @@ static void *alloc_pgt_page(void *context)
+ return NULL;
+ }
+
++ /* Consumed more tables than expected? */
++ if (pages->pgt_buf_offset == BOOT_PGT_SIZE_WARN) {
++ debug_putstr("pgt_buf running low in " __FILE__ "\n");
++ debug_putstr("Need to raise BOOT_PGT_SIZE?\n");
++ debug_putaddr(pages->pgt_buf_offset);
++ debug_putaddr(pages->pgt_buf_size);
++ }
++
+ entry = pages->pgt_buf + pages->pgt_buf_offset;
+ pages->pgt_buf_offset += PAGE_SIZE;
+
+diff --git a/arch/x86/include/asm/boot.h b/arch/x86/include/asm/boot.h
+index 9191280d9ea31..215d37f7dde8a 100644
+--- a/arch/x86/include/asm/boot.h
++++ b/arch/x86/include/asm/boot.h
+@@ -40,23 +40,40 @@
+ #ifdef CONFIG_X86_64
+ # define BOOT_STACK_SIZE 0x4000
+
++/*
++ * Used by decompressor's startup_32() to allocate page tables for identity
++ * mapping of the 4G of RAM in 4-level paging mode:
++ * - 1 level4 table;
++ * - 1 level3 table;
++ * - 4 level2 table that maps everything with 2M pages;
++ *
++ * The additional level5 table needed for 5-level paging is allocated from
++ * trampoline_32bit memory.
++ */
+ # define BOOT_INIT_PGT_SIZE (6*4096)
+-# ifdef CONFIG_RANDOMIZE_BASE
++
+ /*
+- * Assuming all cross the 512GB boundary:
+- * 1 page for level4
+- * (2+2)*4 pages for kernel, param, cmd_line, and randomized kernel
+- * 2 pages for first 2M (video RAM: CONFIG_X86_VERBOSE_BOOTUP).
+- * Total is 19 pages.
++ * Total number of page tables kernel_add_identity_map() can allocate,
++ * including page tables consumed by startup_32().
++ *
++ * Worst-case scenario:
++ * - 5-level paging needs 1 level5 table;
++ * - KASLR needs to map kernel, boot_params, cmdline and randomized kernel,
++ * assuming all of them cross 256T boundary:
++ * + 4*2 level4 table;
++ * + 4*2 level3 table;
++ * + 4*2 level2 table;
++ * - X86_VERBOSE_BOOTUP needs to map the first 2M (video RAM):
++ * + 1 level4 table;
++ * + 1 level3 table;
++ * + 1 level2 table;
++ * Total: 28 tables
++ *
++ * Add 4 spare table in case decompressor touches anything beyond what is
++ * accounted above. Warn if it happens.
+ */
+-# ifdef CONFIG_X86_VERBOSE_BOOTUP
+-# define BOOT_PGT_SIZE (19*4096)
+-# else /* !CONFIG_X86_VERBOSE_BOOTUP */
+-# define BOOT_PGT_SIZE (17*4096)
+-# endif
+-# else /* !CONFIG_RANDOMIZE_BASE */
+-# define BOOT_PGT_SIZE BOOT_INIT_PGT_SIZE
+-# endif
++# define BOOT_PGT_SIZE_WARN (28*4096)
++# define BOOT_PGT_SIZE (32*4096)
+
+ #else /* !CONFIG_X86_64 */
+ # define BOOT_STACK_SIZE 0x1000
+--
+2.40.1
+
--- /dev/null
+From a0dbcc380f71bc780c75cd497608850941f98d41 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 30 Aug 2023 16:03:15 +0200
+Subject: x86: bring back rep movsq for user access on CPUs without ERMS
+
+From: Mateusz Guzik <mjguzik@gmail.com>
+
+[ Upstream commit ca96b162bfd21a5d55e3cd6099e4ee357a0eeb68 ]
+
+Intel CPUs ship with ERMS for over a decade, but this is not true for
+AMD. In particular one reasonably recent uarch (EPYC 7R13) does not
+have it (or at least the bit is inactive when running on the Amazon EC2
+cloud -- I found rather conflicting information about AMD CPUs vs the
+extension).
+
+Hand-rolled mov loops executing in this case are quite pessimal compared
+to rep movsq for bigger sizes. While the upper limit depends on uarch,
+everyone is well south of 1KB AFAICS and sizes bigger than that are
+common.
+
+While technically ancient CPUs may be suffering from rep usage, gcc has
+been emitting it for years all over kernel code, so I don't think this
+is a legitimate concern.
+
+Sample result from read1_processes from will-it-scale (4KB reads/s):
+
+ before: 1507021
+ after: 1721828 (+14%)
+
+Note that the cutoff point for rep usage is set to 64 bytes, which is
+way too conservative but I'm sticking to what was done in 47ee3f1dd93b
+("x86: re-introduce support for ERMS copies for user space accesses").
+That is to say *some* copies will now go slower, which is fixable but
+beyond the scope of this patch.
+
+Signed-off-by: Mateusz Guzik <mjguzik@gmail.com>
+Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ arch/x86/include/asm/uaccess_64.h | 2 +-
+ arch/x86/lib/copy_user_64.S | 57 +++++++------------------------
+ 2 files changed, 14 insertions(+), 45 deletions(-)
+
+diff --git a/arch/x86/include/asm/uaccess_64.h b/arch/x86/include/asm/uaccess_64.h
+index 81b826d3b7530..f2c02e4469ccc 100644
+--- a/arch/x86/include/asm/uaccess_64.h
++++ b/arch/x86/include/asm/uaccess_64.h
+@@ -116,7 +116,7 @@ copy_user_generic(void *to, const void *from, unsigned long len)
+ "2:\n"
+ _ASM_EXTABLE_UA(1b, 2b)
+ :"+c" (len), "+D" (to), "+S" (from), ASM_CALL_CONSTRAINT
+- : : "memory", "rax", "r8", "r9", "r10", "r11");
++ : : "memory", "rax");
+ clac();
+ return len;
+ }
+diff --git a/arch/x86/lib/copy_user_64.S b/arch/x86/lib/copy_user_64.S
+index 01c5de4c279b8..0a81aafed7f88 100644
+--- a/arch/x86/lib/copy_user_64.S
++++ b/arch/x86/lib/copy_user_64.S
+@@ -27,7 +27,7 @@
+ * NOTE! The calling convention is very intentionally the same as
+ * for 'rep movs', so that we can rewrite the function call with
+ * just a plain 'rep movs' on machines that have FSRM. But to make
+- * it simpler for us, we can clobber rsi/rdi and rax/r8-r11 freely.
++ * it simpler for us, we can clobber rsi/rdi and rax freely.
+ */
+ SYM_FUNC_START(rep_movs_alternative)
+ cmpq $64,%rcx
+@@ -68,55 +68,24 @@ SYM_FUNC_START(rep_movs_alternative)
+ _ASM_EXTABLE_UA( 3b, .Lcopy_user_tail)
+
+ .Llarge:
+-0: ALTERNATIVE "jmp .Lunrolled", "rep movsb", X86_FEATURE_ERMS
++0: ALTERNATIVE "jmp .Llarge_movsq", "rep movsb", X86_FEATURE_ERMS
+ 1: RET
+
+- _ASM_EXTABLE_UA( 0b, 1b)
++ _ASM_EXTABLE_UA( 0b, 1b)
+
+- .p2align 4
+-.Lunrolled:
+-10: movq (%rsi),%r8
+-11: movq 8(%rsi),%r9
+-12: movq 16(%rsi),%r10
+-13: movq 24(%rsi),%r11
+-14: movq %r8,(%rdi)
+-15: movq %r9,8(%rdi)
+-16: movq %r10,16(%rdi)
+-17: movq %r11,24(%rdi)
+-20: movq 32(%rsi),%r8
+-21: movq 40(%rsi),%r9
+-22: movq 48(%rsi),%r10
+-23: movq 56(%rsi),%r11
+-24: movq %r8,32(%rdi)
+-25: movq %r9,40(%rdi)
+-26: movq %r10,48(%rdi)
+-27: movq %r11,56(%rdi)
+- addq $64,%rsi
+- addq $64,%rdi
+- subq $64,%rcx
+- cmpq $64,%rcx
+- jae .Lunrolled
+- cmpl $8,%ecx
+- jae .Lword
++.Llarge_movsq:
++ movq %rcx,%rax
++ shrq $3,%rcx
++ andl $7,%eax
++0: rep movsq
++ movl %eax,%ecx
+ testl %ecx,%ecx
+ jne .Lcopy_user_tail
+ RET
+
+- _ASM_EXTABLE_UA(10b, .Lcopy_user_tail)
+- _ASM_EXTABLE_UA(11b, .Lcopy_user_tail)
+- _ASM_EXTABLE_UA(12b, .Lcopy_user_tail)
+- _ASM_EXTABLE_UA(13b, .Lcopy_user_tail)
+- _ASM_EXTABLE_UA(14b, .Lcopy_user_tail)
+- _ASM_EXTABLE_UA(15b, .Lcopy_user_tail)
+- _ASM_EXTABLE_UA(16b, .Lcopy_user_tail)
+- _ASM_EXTABLE_UA(17b, .Lcopy_user_tail)
+- _ASM_EXTABLE_UA(20b, .Lcopy_user_tail)
+- _ASM_EXTABLE_UA(21b, .Lcopy_user_tail)
+- _ASM_EXTABLE_UA(22b, .Lcopy_user_tail)
+- _ASM_EXTABLE_UA(23b, .Lcopy_user_tail)
+- _ASM_EXTABLE_UA(24b, .Lcopy_user_tail)
+- _ASM_EXTABLE_UA(25b, .Lcopy_user_tail)
+- _ASM_EXTABLE_UA(26b, .Lcopy_user_tail)
+- _ASM_EXTABLE_UA(27b, .Lcopy_user_tail)
++1: leaq (%rax,%rcx,8),%rcx
++ jmp .Lcopy_user_tail
++
++ _ASM_EXTABLE_UA( 0b, 1b)
+ SYM_FUNC_END(rep_movs_alternative)
+ EXPORT_SYMBOL(rep_movs_alternative)
+--
+2.40.1
+
--- /dev/null
+From 7d2238c090feb2c330f6af0df0506538e4b488e1 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 2 Aug 2023 12:55:47 +0200
+Subject: x86/ibt: Avoid duplicate ENDBR in __put_user_nocheck*()
+
+From: Peter Zijlstra <peterz@infradead.org>
+
+[ Upstream commit 7575e5a35267983dcbeb1e0d3a49d21ae3cf0b82 ]
+
+Commit cb855971d717 ("x86/putuser: Provide room for padding") changed
+__put_user_nocheck_*() into proper functions but failed to note that
+SYM_FUNC_START() already provides ENDBR, rendering the explicit ENDBR
+superfluous.
+
+Fixes: cb855971d717 ("x86/putuser: Provide room for padding")
+Reported-by: David Kaplan <David.Kaplan@amd.com>
+Reviewed-by: Andrew Cooper <andrew.cooper3@citrix.com>
+Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
+Signed-off-by: Ingo Molnar <mingo@kernel.org>
+Link: https://lore.kernel.org/r/20230802110323.086971726@infradead.org
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ arch/x86/lib/putuser.S | 4 ----
+ 1 file changed, 4 deletions(-)
+
+diff --git a/arch/x86/lib/putuser.S b/arch/x86/lib/putuser.S
+index 1451e0c4ae22a..235bbda6fc823 100644
+--- a/arch/x86/lib/putuser.S
++++ b/arch/x86/lib/putuser.S
+@@ -56,7 +56,6 @@ SYM_FUNC_END(__put_user_1)
+ EXPORT_SYMBOL(__put_user_1)
+
+ SYM_FUNC_START(__put_user_nocheck_1)
+- ENDBR
+ ASM_STAC
+ 2: movb %al,(%_ASM_CX)
+ xor %ecx,%ecx
+@@ -76,7 +75,6 @@ SYM_FUNC_END(__put_user_2)
+ EXPORT_SYMBOL(__put_user_2)
+
+ SYM_FUNC_START(__put_user_nocheck_2)
+- ENDBR
+ ASM_STAC
+ 4: movw %ax,(%_ASM_CX)
+ xor %ecx,%ecx
+@@ -96,7 +94,6 @@ SYM_FUNC_END(__put_user_4)
+ EXPORT_SYMBOL(__put_user_4)
+
+ SYM_FUNC_START(__put_user_nocheck_4)
+- ENDBR
+ ASM_STAC
+ 6: movl %eax,(%_ASM_CX)
+ xor %ecx,%ecx
+@@ -119,7 +116,6 @@ SYM_FUNC_END(__put_user_8)
+ EXPORT_SYMBOL(__put_user_8)
+
+ SYM_FUNC_START(__put_user_nocheck_8)
+- ENDBR
+ ASM_STAC
+ 9: mov %_ASM_AX,(%_ASM_CX)
+ #ifdef CONFIG_X86_32
+--
+2.40.1
+
--- /dev/null
+From a60926a3232694d9a0d1ec9e2a8542febfde6377 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 2 Aug 2023 12:55:46 +0200
+Subject: x86/ibt: Suppress spurious ENDBR
+
+From: Peter Zijlstra <peterz@infradead.org>
+
+[ Upstream commit 25e73b7e3f72a25aa30cbb2eecb49036e0acf066 ]
+
+It was reported that under certain circumstances GCC emits ENDBR
+instructions for _THIS_IP_ usage. Specifically, when it appears at the
+start of a basic block -- but not elsewhere.
+
+Since _THIS_IP_ is never used for control flow, these ENDBR
+instructions are completely superfluous. Override the _THIS_IP_
+definition for x86_64 to avoid this.
+
+Less ENDBR instructions is better.
+
+Fixes: 156ff4a544ae ("x86/ibt: Base IBT bits")
+Reported-by: David Kaplan <David.Kaplan@amd.com>
+Reviewed-by: Andrew Cooper <andrew.cooper3@citrix.com>
+Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
+Signed-off-by: Ingo Molnar <mingo@kernel.org>
+Link: https://lore.kernel.org/r/20230802110323.016197440@infradead.org
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ arch/x86/include/asm/linkage.h | 8 ++++++++
+ include/linux/instruction_pointer.h | 5 +++++
+ 2 files changed, 13 insertions(+)
+
+diff --git a/arch/x86/include/asm/linkage.h b/arch/x86/include/asm/linkage.h
+index 97a3de7892d3f..5ff49fd67732e 100644
+--- a/arch/x86/include/asm/linkage.h
++++ b/arch/x86/include/asm/linkage.h
+@@ -8,6 +8,14 @@
+ #undef notrace
+ #define notrace __attribute__((no_instrument_function))
+
++#ifdef CONFIG_64BIT
++/*
++ * The generic version tends to create spurious ENDBR instructions under
++ * certain conditions.
++ */
++#define _THIS_IP_ ({ unsigned long __here; asm ("lea 0(%%rip), %0" : "=r" (__here)); __here; })
++#endif
++
+ #ifdef CONFIG_X86_32
+ #define asmlinkage CPP_ASMLINKAGE __attribute__((regparm(0)))
+ #endif /* CONFIG_X86_32 */
+diff --git a/include/linux/instruction_pointer.h b/include/linux/instruction_pointer.h
+index cda1f706eaeb1..aa0b3ffea9353 100644
+--- a/include/linux/instruction_pointer.h
++++ b/include/linux/instruction_pointer.h
+@@ -2,7 +2,12 @@
+ #ifndef _LINUX_INSTRUCTION_POINTER_H
+ #define _LINUX_INSTRUCTION_POINTER_H
+
++#include <asm/linkage.h>
++
+ #define _RET_IP_ (unsigned long)__builtin_return_address(0)
++
++#ifndef _THIS_IP_
+ #define _THIS_IP_ ({ __label__ __here; __here: (unsigned long)&&__here; })
++#endif
+
+ #endif /* _LINUX_INSTRUCTION_POINTER_H */
+--
+2.40.1
+
--- /dev/null
+From b9c6c5360df5c9632ed07e9fd54b981d9900bd84 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 14 Sep 2023 10:01:38 -0700
+Subject: x86/purgatory: Remove LTO flags
+
+From: Song Liu <song@kernel.org>
+
+[ Upstream commit 75b2f7e4c9e0fd750a5a27ca9736d1daa7a3762a ]
+
+-flto* implies -ffunction-sections. With LTO enabled, ld.lld generates
+multiple .text sections for purgatory.ro:
+
+ $ readelf -S purgatory.ro | grep " .text"
+ [ 1] .text PROGBITS 0000000000000000 00000040
+ [ 7] .text.purgatory PROGBITS 0000000000000000 000020e0
+ [ 9] .text.warn PROGBITS 0000000000000000 000021c0
+ [13] .text.sha256_upda PROGBITS 0000000000000000 000022f0
+ [15] .text.sha224_upda PROGBITS 0000000000000000 00002be0
+ [17] .text.sha256_fina PROGBITS 0000000000000000 00002bf0
+ [19] .text.sha224_fina PROGBITS 0000000000000000 00002cc0
+
+This causes WARNING from kexec_purgatory_setup_sechdrs():
+
+ WARNING: CPU: 26 PID: 110894 at kernel/kexec_file.c:919
+ kexec_load_purgatory+0x37f/0x390
+
+Fix this by disabling LTO for purgatory.
+
+[ AFAICT, x86 is the only arch that supports LTO and purgatory. ]
+
+We could also fix this with an explicit linker script to rejoin .text.*
+sections back into .text. However, given the benefit of LTOing purgatory
+is small, simply disable the production of more .text.* sections for now.
+
+Fixes: b33fff07e3e3 ("x86, build: allow LTO to be selected")
+Signed-off-by: Song Liu <song@kernel.org>
+Signed-off-by: Ingo Molnar <mingo@kernel.org>
+Reviewed-by: Nick Desaulniers <ndesaulniers@google.com>
+Reviewed-by: Sami Tolvanen <samitolvanen@google.com>
+Link: https://lore.kernel.org/r/20230914170138.995606-1-song@kernel.org
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ arch/x86/purgatory/Makefile | 4 ++++
+ 1 file changed, 4 insertions(+)
+
+diff --git a/arch/x86/purgatory/Makefile b/arch/x86/purgatory/Makefile
+index c2a29be35c01b..08aa0f25f12a0 100644
+--- a/arch/x86/purgatory/Makefile
++++ b/arch/x86/purgatory/Makefile
+@@ -19,6 +19,10 @@ CFLAGS_sha256.o := -D__DISABLE_EXPORTS -D__NO_FORTIFY
+ # optimization flags.
+ KBUILD_CFLAGS := $(filter-out -fprofile-sample-use=% -fprofile-use=%,$(KBUILD_CFLAGS))
+
++# When LTO is enabled, llvm emits many text sections, which is not supported
++# by kexec. Remove -flto=* flags.
++KBUILD_CFLAGS := $(filter-out $(CC_FLAGS_LTO),$(KBUILD_CFLAGS))
++
+ # When linking purgatory.ro with -r unresolved symbols are not checked,
+ # also link a purgatory.chk binary without -r to check for unresolved symbols.
+ PURGATORY_LDFLAGS := -e purgatory_start -z nodefaultlib
+--
+2.40.1
+
--- /dev/null
+From 9f54b64afe19c51fe0c08de919d7e227a26365d9 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 14 Aug 2023 20:57:47 -0700
+Subject: x86/sched: Restore the SD_ASYM_PACKING flag in the DIE domain
+
+From: Ricardo Neri <ricardo.neri-calderon@linux.intel.com>
+
+[ Upstream commit 108af4b4bd3813610701379a58538e3339b162e4 ]
+
+Commit 8f2d6c41e5a6 ("x86/sched: Rewrite topology setup") dropped the
+SD_ASYM_PACKING flag in the DIE domain added in commit 044f0e27dec6
+("x86/sched: Add the SD_ASYM_PACKING flag to the die domain of hybrid
+processors"). Restore it on hybrid processors.
+
+The die-level domain does not depend on any build configuration and now
+x86_sched_itmt_flags() is always needed. Remove the build dependency on
+CONFIG_SCHED_[SMT|CLUSTER|MC].
+
+Fixes: 8f2d6c41e5a6 ("x86/sched: Rewrite topology setup")
+Signed-off-by: Ricardo Neri <ricardo.neri-calderon@linux.intel.com>
+Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
+Signed-off-by: Ingo Molnar <mingo@kernel.org>
+Reviewed-by: Chen Yu <yu.c.chen@intel.com>
+Tested-by: Caleb Callaway <caleb.callaway@intel.com>
+Link: https://lkml.kernel.org/r/20230815035747.11529-1-ricardo.neri-calderon@linux.intel.com
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ arch/x86/kernel/smpboot.c | 12 +++++++++---
+ 1 file changed, 9 insertions(+), 3 deletions(-)
+
+diff --git a/arch/x86/kernel/smpboot.c b/arch/x86/kernel/smpboot.c
+index 7d82f0bd449c7..747b83a373a2d 100644
+--- a/arch/x86/kernel/smpboot.c
++++ b/arch/x86/kernel/smpboot.c
+@@ -587,7 +587,6 @@ static bool match_llc(struct cpuinfo_x86 *c, struct cpuinfo_x86 *o)
+ }
+
+
+-#if defined(CONFIG_SCHED_SMT) || defined(CONFIG_SCHED_CLUSTER) || defined(CONFIG_SCHED_MC)
+ static inline int x86_sched_itmt_flags(void)
+ {
+ return sysctl_sched_itmt_enabled ? SD_ASYM_PACKING : 0;
+@@ -611,7 +610,14 @@ static int x86_cluster_flags(void)
+ return cpu_cluster_flags() | x86_sched_itmt_flags();
+ }
+ #endif
+-#endif
++
++static int x86_die_flags(void)
++{
++ if (cpu_feature_enabled(X86_FEATURE_HYBRID_CPU))
++ return x86_sched_itmt_flags();
++
++ return 0;
++}
+
+ /*
+ * Set if a package/die has multiple NUMA nodes inside.
+@@ -653,7 +659,7 @@ static void __init build_sched_topology(void)
+ */
+ if (!x86_has_numa_in_package) {
+ x86_topology[i++] = (struct sched_domain_topology_level){
+- cpu_cpu_mask, SD_INIT_NAME(DIE)
++ cpu_cpu_mask, x86_die_flags, SD_INIT_NAME(DIE)
+ };
+ }
+
+--
+2.40.1
+