]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
Fixes for 6.6
authorSasha Levin <sashal@kernel.org>
Tue, 20 Aug 2024 11:58:50 +0000 (07:58 -0400)
committerSasha Levin <sashal@kernel.org>
Tue, 20 Aug 2024 11:58:50 +0000 (07:58 -0400)
Signed-off-by: Sasha Levin <sashal@kernel.org>
58 files changed:
queue-6.6/accel-habanalabs-export-dma-buf-only-if-size-offset-.patch [new file with mode: 0644]
queue-6.6/accel-habanalabs-fix-bug-in-timestamp-interrupt-hand.patch [new file with mode: 0644]
queue-6.6/accel-habanalabs-gaudi2-unsecure-tpc-count-registers.patch [new file with mode: 0644]
queue-6.6/arm64-fix-kasan-random-tag-seed-initialization.patch [new file with mode: 0644]
queue-6.6/asoc-cs35l45-checks-index-of-cs35l45_irqs.patch [new file with mode: 0644]
queue-6.6/asoc-sof-intel-hda-dsp-make-sure-that-no-irq-handler.patch [new file with mode: 0644]
queue-6.6/binfmt_misc-cleanup-on-filesystem-umount.patch [new file with mode: 0644]
queue-6.6/block-fix-lockdep-warning-in-blk_mq_mark_tag_wait.patch [new file with mode: 0644]
queue-6.6/cgroup-avoid-extra-dereference-in-css_populate_dir.patch [new file with mode: 0644]
queue-6.6/clk-visconti-add-bounds-checking-coverage-for-struct.patch [new file with mode: 0644]
queue-6.6/cpu-smt-enable-smt-only-if-a-core-is-online.patch [new file with mode: 0644]
queue-6.6/drm-amd-amdgpu-imu_v11_0-increase-buffer-size-to-ens.patch [new file with mode: 0644]
queue-6.6/drm-amd-display-validate-hw_points_num-before-using-.patch [new file with mode: 0644]
queue-6.6/drm-amd-pm-fix-error-flow-in-sensor-fetching.patch [new file with mode: 0644]
queue-6.6/drm-amdgpu-access-rlc_spm_mc_cntl-through-mmio-in-sr.patch [new file with mode: 0644]
queue-6.6/drm-amdkfd-move-dma-unmapping-after-tlb-flush.patch [new file with mode: 0644]
queue-6.6/drm-bridge-tc358768-attempt-to-fix-dsi-horizontal-ti.patch [new file with mode: 0644]
queue-6.6/drm-tegra-zero-initialize-iosys_map.patch [new file with mode: 0644]
queue-6.6/gfs2-setattr_chown-add-missing-initialization.patch [new file with mode: 0644]
queue-6.6/hwmon-ltc2992-avoid-division-by-zero.patch [new file with mode: 0644]
queue-6.6/i2c-riic-avoid-potential-division-by-zero.patch [new file with mode: 0644]
queue-6.6/i3c-mipi-i3c-hci-do-not-unmap-region-not-mapped-for-.patch [new file with mode: 0644]
queue-6.6/i3c-mipi-i3c-hci-remove-bug-when-ring-abort-request-.patch [new file with mode: 0644]
queue-6.6/ib-hfi1-fix-potential-deadlock-on-irq_src_lock-and-d.patch [new file with mode: 0644]
queue-6.6/iommu-arm-smmu-qcom-add-sdm670-mdss-compatible.patch [new file with mode: 0644]
queue-6.6/md-raid5-cache-use-read_once-write_once-for-conf-log.patch [new file with mode: 0644]
queue-6.6/media-qcom-venus-fix-incorrect-return-value.patch [new file with mode: 0644]
queue-6.6/media-radio-isa-use-dev_name-to-fill-in-bus_info.patch [new file with mode: 0644]
queue-6.6/media-s5p-mfc-fix-potential-deadlock-on-condlock.patch [new file with mode: 0644]
queue-6.6/net-ethernet-mtk_wed-check-update_wo_rx_stats-in-mtk.patch [new file with mode: 0644]
queue-6.6/platform-x86-intel-ifs-validate-image-size.patch [new file with mode: 0644]
queue-6.6/powerpc-topology-check-if-a-core-is-online.patch [new file with mode: 0644]
queue-6.6/rcu-dump-memory-object-info-if-callback-function-is-.patch [new file with mode: 0644]
queue-6.6/rcu-eliminate-rcu_gp_slow_unregister-false-positive.patch [new file with mode: 0644]
queue-6.6/rdma-rtrs-fix-the-problem-of-variable-not-initialize.patch [new file with mode: 0644]
queue-6.6/rust-fix-the-default-format-for-config_-rustc-bindge.patch [new file with mode: 0644]
queue-6.6/rust-suppress-error-messages-from-config_-rustc-bind.patch [new file with mode: 0644]
queue-6.6/rust-work-around-bindgen-0.69.0-issue.patch [new file with mode: 0644]
queue-6.6/s390-smp-mcck-fix-early-ipi-handling.patch [new file with mode: 0644]
queue-6.6/sched-topology-handle-numa_no_node-in-sched_numa_fin.patch [new file with mode: 0644]
queue-6.6/scsi-spi-fix-sshdr-use.patch [new file with mode: 0644]
queue-6.6/series
queue-6.6/ssb-fix-division-by-zero-issue-in-ssb_calc_clock_rat.patch [new file with mode: 0644]
queue-6.6/staging-iio-resolver-ad2s1210-fix-use-before-initial.patch [new file with mode: 0644]
queue-6.6/staging-ks7010-disable-bh-on-tx_dev_lock.patch [new file with mode: 0644]
queue-6.6/usb-gadget-uvc-cleanup-request-when-not-in-correct-s.patch [new file with mode: 0644]
queue-6.6/wifi-ath11k-fix-ath11k_mac_op_remain_on_channel-stac.patch [new file with mode: 0644]
queue-6.6/wifi-ath12k-fix-warn_on-during-ath12k_mac_update_vif.patch [new file with mode: 0644]
queue-6.6/wifi-cfg80211-check-wiphy-mutex-is-held-for-wdev-mut.patch [new file with mode: 0644]
queue-6.6/wifi-cw1200-avoid-processing-an-invalid-tim-ie.patch [new file with mode: 0644]
queue-6.6/wifi-iwlwifi-abort-scan-when-rfkill-on-but-device-en.patch [new file with mode: 0644]
queue-6.6/wifi-iwlwifi-check-for-kmemdup-return-value-in-iwl_p.patch [new file with mode: 0644]
queue-6.6/wifi-iwlwifi-fw-fix-debugfs-command-sending.patch [new file with mode: 0644]
queue-6.6/wifi-iwlwifi-mvm-fix-recovery-flow-in-csa.patch [new file with mode: 0644]
queue-6.6/wifi-mac80211-fix-ba-session-teardown-race.patch [new file with mode: 0644]
queue-6.6/wifi-mac80211-flush-sta-queues-on-unauthorization.patch [new file with mode: 0644]
queue-6.6/wifi-mac80211-lock-wiphy-in-ip-address-notifier.patch [new file with mode: 0644]
queue-6.6/wifi-mt76-fix-race-condition-related-to-checking-tx-.patch [new file with mode: 0644]

diff --git a/queue-6.6/accel-habanalabs-export-dma-buf-only-if-size-offset-.patch b/queue-6.6/accel-habanalabs-export-dma-buf-only-if-size-offset-.patch
new file mode 100644 (file)
index 0000000..62ccc53
--- /dev/null
@@ -0,0 +1,68 @@
+From 7940430fa2fc161167b7d9e7a940a16af007885a Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 9 Aug 2023 16:14:49 +0300
+Subject: accel/habanalabs: export dma-buf only if size/offset multiples of
+ PAGE_SIZE
+
+From: Tomer Tayar <ttayar@habana.ai>
+
+[ Upstream commit 0b75cb5b240fddf181c284d415ee77ef61b418d6 ]
+
+It is currently allowed for a user to export dma-buf with size and
+offset that are not multiples of PAGE_SIZE.
+The exported memory is mapped for the importer device, and there it will
+be rounded to PAGE_SIZE, leading to actually exporting more than the
+user intended to.
+To make the user be aware of it, accept only size and offset which are
+multiple of PAGE_SIZE.
+
+Signed-off-by: Tomer Tayar <ttayar@habana.ai>
+Reviewed-by: Oded Gabbay <ogabbay@kernel.org>
+Signed-off-by: Oded Gabbay <ogabbay@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/accel/habanalabs/common/memory.c | 15 +++++++++++----
+ 1 file changed, 11 insertions(+), 4 deletions(-)
+
+diff --git a/drivers/accel/habanalabs/common/memory.c b/drivers/accel/habanalabs/common/memory.c
+index 4fc72a07d2f59..5b7d9a351133f 100644
+--- a/drivers/accel/habanalabs/common/memory.c
++++ b/drivers/accel/habanalabs/common/memory.c
+@@ -1878,16 +1878,16 @@ static int export_dmabuf(struct hl_ctx *ctx,
+ static int validate_export_params_common(struct hl_device *hdev, u64 device_addr, u64 size)
+ {
+-      if (!IS_ALIGNED(device_addr, PAGE_SIZE)) {
++      if (!PAGE_ALIGNED(device_addr)) {
+               dev_dbg(hdev->dev,
+-                      "exported device memory address 0x%llx should be aligned to 0x%lx\n",
++                      "exported device memory address 0x%llx should be aligned to PAGE_SIZE 0x%lx\n",
+                       device_addr, PAGE_SIZE);
+               return -EINVAL;
+       }
+-      if (size < PAGE_SIZE) {
++      if (!size || !PAGE_ALIGNED(size)) {
+               dev_dbg(hdev->dev,
+-                      "exported device memory size %llu should be equal to or greater than %lu\n",
++                      "exported device memory size %llu should be a multiple of PAGE_SIZE %lu\n",
+                       size, PAGE_SIZE);
+               return -EINVAL;
+       }
+@@ -1938,6 +1938,13 @@ static int validate_export_params(struct hl_device *hdev, u64 device_addr, u64 s
+       if (rc)
+               return rc;
++      if (!PAGE_ALIGNED(offset)) {
++              dev_dbg(hdev->dev,
++                      "exported device memory offset %llu should be a multiple of PAGE_SIZE %lu\n",
++                      offset, PAGE_SIZE);
++              return -EINVAL;
++      }
++
+       if ((offset + size) > phys_pg_pack->total_size) {
+               dev_dbg(hdev->dev, "offset %#llx and size %#llx exceed total map size %#llx\n",
+                               offset, size, phys_pg_pack->total_size);
+-- 
+2.43.0
+
diff --git a/queue-6.6/accel-habanalabs-fix-bug-in-timestamp-interrupt-hand.patch b/queue-6.6/accel-habanalabs-fix-bug-in-timestamp-interrupt-hand.patch
new file mode 100644 (file)
index 0000000..46f415e
--- /dev/null
@@ -0,0 +1,43 @@
+From b3fcb94cc8c93be4ad31dbde998ca7b00947ff3e Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 24 Aug 2023 15:45:21 +0300
+Subject: accel/habanalabs: fix bug in timestamp interrupt handling
+
+From: farah kassabri <fkassabri@habana.ai>
+
+[ Upstream commit 0165994c215f321e2d055368f89b424756e340eb ]
+
+There is a potential race between user thread seeking to re-use
+a timestamp record with new interrupt id, while this record is still
+in the middle of interrupt handling and it is about to be freed.
+Imagine the driver set the record in_use to 0 and only then fill the
+free_node information. This might lead to unpleasant scenario where
+the new registration thread detects the record as free to use, and
+change the cq buff address. That will cause the free_node to get
+the wrong buffer address to put refcount to.
+
+Signed-off-by: farah kassabri <fkassabri@habana.ai>
+Reviewed-by: Oded Gabbay <ogabbay@kernel.org>
+Signed-off-by: Oded Gabbay <ogabbay@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/accel/habanalabs/common/irq.c | 3 +++
+ 1 file changed, 3 insertions(+)
+
+diff --git a/drivers/accel/habanalabs/common/irq.c b/drivers/accel/habanalabs/common/irq.c
+index b1010d206c2ef..813315cea4a7b 100644
+--- a/drivers/accel/habanalabs/common/irq.c
++++ b/drivers/accel/habanalabs/common/irq.c
+@@ -271,6 +271,9 @@ static int handle_registration_node(struct hl_device *hdev, struct hl_user_pendi
+       free_node->cq_cb = pend->ts_reg_info.cq_cb;
+       list_add(&free_node->free_objects_node, *free_list);
++      /* Mark TS record as free */
++      pend->ts_reg_info.in_use = false;
++
+       return 0;
+ }
+-- 
+2.43.0
+
diff --git a/queue-6.6/accel-habanalabs-gaudi2-unsecure-tpc-count-registers.patch b/queue-6.6/accel-habanalabs-gaudi2-unsecure-tpc-count-registers.patch
new file mode 100644 (file)
index 0000000..b4f852d
--- /dev/null
@@ -0,0 +1,34 @@
+From 09706282fca2ee0b7fcde5783f0830246254febf Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 28 Jun 2023 14:40:46 +0300
+Subject: accel/habanalabs/gaudi2: unsecure tpc count registers
+
+From: Ofir Bitton <obitton@habana.ai>
+
+[ Upstream commit 1e3a78270b4ec1c8c177eb310c08128d52137a69 ]
+
+As TPC kernels now must use those registers we unsecure them.
+
+Signed-off-by: Ofir Bitton <obitton@habana.ai>
+Reviewed-by: Oded Gabbay <ogabbay@kernel.org>
+Signed-off-by: Oded Gabbay <ogabbay@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/accel/habanalabs/gaudi2/gaudi2_security.c | 1 +
+ 1 file changed, 1 insertion(+)
+
+diff --git a/drivers/accel/habanalabs/gaudi2/gaudi2_security.c b/drivers/accel/habanalabs/gaudi2/gaudi2_security.c
+index 2742b1f801eb2..908710524dc9e 100644
+--- a/drivers/accel/habanalabs/gaudi2/gaudi2_security.c
++++ b/drivers/accel/habanalabs/gaudi2/gaudi2_security.c
+@@ -1601,6 +1601,7 @@ static const u32 gaudi2_pb_dcr0_tpc0_unsecured_regs[] = {
+       mmDCORE0_TPC0_CFG_KERNEL_SRF_30,
+       mmDCORE0_TPC0_CFG_KERNEL_SRF_31,
+       mmDCORE0_TPC0_CFG_TPC_SB_L0CD,
++      mmDCORE0_TPC0_CFG_TPC_COUNT,
+       mmDCORE0_TPC0_CFG_TPC_ID,
+       mmDCORE0_TPC0_CFG_QM_KERNEL_ID_INC,
+       mmDCORE0_TPC0_CFG_QM_TID_BASE_SIZE_HIGH_DIM_0,
+-- 
+2.43.0
+
diff --git a/queue-6.6/arm64-fix-kasan-random-tag-seed-initialization.patch b/queue-6.6/arm64-fix-kasan-random-tag-seed-initialization.patch
new file mode 100644 (file)
index 0000000..c0d79bb
--- /dev/null
@@ -0,0 +1,57 @@
+From 204fb524b13759bb3eeabba8c80f6b018d87a3d3 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 14 Aug 2024 02:09:53 -0700
+Subject: arm64: Fix KASAN random tag seed initialization
+
+From: Samuel Holland <samuel.holland@sifive.com>
+
+[ Upstream commit f75c235565f90c4a17b125e47f1c68ef6b8c2bce ]
+
+Currently, kasan_init_sw_tags() is called before setup_per_cpu_areas(),
+so per_cpu(prng_state, cpu) accesses the same address regardless of the
+value of "cpu", and the same seed value gets copied to the percpu area
+for every CPU. Fix this by moving the call to smp_prepare_boot_cpu(),
+which is the first architecture hook after setup_per_cpu_areas().
+
+Fixes: 3c9e3aa11094 ("kasan: add tag related helper functions")
+Fixes: 3f41b6093823 ("kasan: fix random seed generation for tag-based mode")
+Signed-off-by: Samuel Holland <samuel.holland@sifive.com>
+Reviewed-by: Andrey Konovalov <andreyknvl@gmail.com>
+Link: https://lore.kernel.org/r/20240814091005.969756-1-samuel.holland@sifive.com
+Signed-off-by: Catalin Marinas <catalin.marinas@arm.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ arch/arm64/kernel/setup.c | 3 ---
+ arch/arm64/kernel/smp.c   | 2 ++
+ 2 files changed, 2 insertions(+), 3 deletions(-)
+
+diff --git a/arch/arm64/kernel/setup.c b/arch/arm64/kernel/setup.c
+index 417a8a86b2db5..c583d1f335f8c 100644
+--- a/arch/arm64/kernel/setup.c
++++ b/arch/arm64/kernel/setup.c
+@@ -371,9 +371,6 @@ void __init __no_sanitize_address setup_arch(char **cmdline_p)
+       smp_init_cpus();
+       smp_build_mpidr_hash();
+-      /* Init percpu seeds for random tags after cpus are set up. */
+-      kasan_init_sw_tags();
+-
+ #ifdef CONFIG_ARM64_SW_TTBR0_PAN
+       /*
+        * Make sure init_thread_info.ttbr0 always generates translation
+diff --git a/arch/arm64/kernel/smp.c b/arch/arm64/kernel/smp.c
+index 960b98b43506d..14365ef842440 100644
+--- a/arch/arm64/kernel/smp.c
++++ b/arch/arm64/kernel/smp.c
+@@ -459,6 +459,8 @@ void __init smp_prepare_boot_cpu(void)
+               init_gic_priority_masking();
+       kasan_init_hw_tags();
++      /* Init percpu seeds for random tags after cpus are set up. */
++      kasan_init_sw_tags();
+ }
+ /*
+-- 
+2.43.0
+
diff --git a/queue-6.6/asoc-cs35l45-checks-index-of-cs35l45_irqs.patch b/queue-6.6/asoc-cs35l45-checks-index-of-cs35l45_irqs.patch
new file mode 100644 (file)
index 0000000..228442e
--- /dev/null
@@ -0,0 +1,42 @@
+From accc8a70f10f91b3349c0b9b2a5d410b08daf15d Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 31 Aug 2023 11:20:39 -0500
+Subject: ASoC: cs35l45: Checks index of cs35l45_irqs[]
+
+From: Ricardo Rivera-Matos <rriveram@opensource.cirrus.com>
+
+[ Upstream commit 44f37b6ce041c838cb2f49f08998c41f1ab3b08c ]
+
+Checks the index computed by the virq offset before printing the
+error condition in cs35l45_spk_safe_err() handler.
+
+Signed-off-by: Ricardo Rivera-Matos <rriveram@opensource.cirrus.com>
+Signed-off-by: Vlad Karpovich <vkarpovi@opensource.cirrus.com>
+Acked-by: Ricardo Rivera-Matos <rriveram@opensource.cirrus.com>
+Acked-by: Charles Keepax <ckeepax@opensource.cirrus.com>
+Link: https://lore.kernel.org/r/20230831162042.471801-1-vkarpovi@opensource.cirrus.com
+Signed-off-by: Mark Brown <broonie@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ sound/soc/codecs/cs35l45.c | 5 ++++-
+ 1 file changed, 4 insertions(+), 1 deletion(-)
+
+diff --git a/sound/soc/codecs/cs35l45.c b/sound/soc/codecs/cs35l45.c
+index 9b9fc2d491089..7e439c778c6b4 100644
+--- a/sound/soc/codecs/cs35l45.c
++++ b/sound/soc/codecs/cs35l45.c
+@@ -1067,7 +1067,10 @@ static irqreturn_t cs35l45_spk_safe_err(int irq, void *data)
+       i = irq - regmap_irq_get_virq(cs35l45->irq_data, 0);
+-      dev_err(cs35l45->dev, "%s condition detected!\n", cs35l45_irqs[i].name);
++      if (i < 0 || i >= ARRAY_SIZE(cs35l45_irqs))
++              dev_err(cs35l45->dev, "Unspecified global error condition (%d) detected!\n", irq);
++      else
++              dev_err(cs35l45->dev, "%s condition detected!\n", cs35l45_irqs[i].name);
+       return IRQ_HANDLED;
+ }
+-- 
+2.43.0
+
diff --git a/queue-6.6/asoc-sof-intel-hda-dsp-make-sure-that-no-irq-handler.patch b/queue-6.6/asoc-sof-intel-hda-dsp-make-sure-that-no-irq-handler.patch
new file mode 100644 (file)
index 0000000..13fcf9e
--- /dev/null
@@ -0,0 +1,53 @@
+From e3f3231a3e2c63a589706153a55eb7257658738f Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 12 Oct 2023 15:18:48 -0400
+Subject: ASoC: SOF: Intel: hda-dsp: Make sure that no irq handler is pending
+ before suspend
+
+From: Peter Ujfalusi <peter.ujfalusi@linux.intel.com>
+
+[ Upstream commit 576a0b71b5b479008dacb3047a346625040f5ac6 ]
+
+In the existing IPC support, the reply to each IPC message is handled in
+an IRQ thread. The assumption is that the IRQ thread is scheduled without
+significant delays.
+
+On an experimental (iow, buggy) kernel, the IRQ thread dealing with the
+reply to the last IPC message before powering-down the DSP can be delayed
+by several seconds. The IRQ thread will proceed with register accesses
+after the DSP is powered-down which results in a kernel crash.
+
+While the bug which causes the delay is not in the audio stack, we must
+handle such cases with defensive programming to avoid such crashes.
+
+Call synchronize_irq() before proceeding to power down the DSP to make
+sure that no irq thread is pending execution.
+
+Closes: https://github.com/thesofproject/linux/issues/4608
+Reviewed-by: Guennadi Liakhovetski <guennadi.liakhovetski@linux.intel.com>
+Signed-off-by: Peter Ujfalusi <peter.ujfalusi@linux.intel.com>
+Signed-off-by: Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>
+Link: https://lore.kernel.org/r/20231012191850.147140-3-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/intel/hda-dsp.c | 3 +++
+ 1 file changed, 3 insertions(+)
+
+diff --git a/sound/soc/sof/intel/hda-dsp.c b/sound/soc/sof/intel/hda-dsp.c
+index e80a2a5ec56a1..1506982a56c30 100644
+--- a/sound/soc/sof/intel/hda-dsp.c
++++ b/sound/soc/sof/intel/hda-dsp.c
+@@ -709,6 +709,9 @@ static int hda_suspend(struct snd_sof_dev *sdev, bool runtime_suspend)
+       if (ret < 0)
+               return ret;
++      /* make sure that no irq handler is pending before shutdown */
++      synchronize_irq(sdev->ipc_irq);
++
+       hda_codec_jack_wake_enable(sdev, runtime_suspend);
+       /* power down all hda links */
+-- 
+2.43.0
+
diff --git a/queue-6.6/binfmt_misc-cleanup-on-filesystem-umount.patch b/queue-6.6/binfmt_misc-cleanup-on-filesystem-umount.patch
new file mode 100644 (file)
index 0000000..d455f98
--- /dev/null
@@ -0,0 +1,442 @@
+From d701ec81d96ea4f6b265ad6ab664584837c1039b Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 28 Oct 2021 12:31:13 +0200
+Subject: binfmt_misc: cleanup on filesystem umount
+
+From: Christian Brauner <christian.brauner@ubuntu.com>
+
+[ Upstream commit 1c5976ef0f7ad76319df748ccb99a4c7ba2ba464 ]
+
+Currently, registering a new binary type pins the binfmt_misc
+filesystem. Specifically, this means that as long as there is at least
+one binary type registered the binfmt_misc filesystem survives all
+umounts, i.e. the superblock is not destroyed. Meaning that a umount
+followed by another mount will end up with the same superblock and the
+same binary type handlers. This is a behavior we tend to discourage for
+any new filesystems (apart from a few special filesystems such as e.g.
+configfs or debugfs). A umount operation without the filesystem being
+pinned - by e.g. someone holding a file descriptor to an open file -
+should usually result in the destruction of the superblock and all
+associated resources. This makes introspection easier and leads to
+clearly defined, simple and clean semantics. An administrator can rely
+on the fact that a umount will guarantee a clean slate making it
+possible to reinitialize a filesystem. Right now all binary types would
+need to be explicitly deleted before that can happen.
+
+This allows us to remove the heavy-handed calls to simple_pin_fs() and
+simple_release_fs() when creating and deleting binary types. This in
+turn allows us to replace the current brittle pinning mechanism abusing
+dget() which has caused a range of bugs judging from prior fixes in [2]
+and [3]. The additional dget() in load_misc_binary() pins the dentry but
+only does so for the sake to prevent ->evict_inode() from freeing the
+node when a user removes the binary type and kill_node() is run. Which
+would mean ->interpreter and ->interp_file would be freed causing a UAF.
+
+This isn't really nicely documented nor is it very clean because it
+relies on simple_pin_fs() pinning the filesystem as long as at least one
+binary type exists. Otherwise it would cause load_misc_binary() to hold
+on to a dentry belonging to a superblock that has been shutdown.
+Replace that implicit pinning with a clean and simple per-node refcount
+and get rid of the ugly dget() pinning. A similar mechanism exists for
+e.g. binderfs (cf. [4]). All the cleanup work can now be done in
+->evict_inode().
+
+In a follow-up patch we will make it possible to use binfmt_misc in
+sandboxes. We will use the cleaner semantics where a umount for the
+filesystem will cause the superblock and all resources to be
+deallocated. In preparation for this apply the same semantics to the
+initial binfmt_misc mount. Note, that this is a user-visible change and
+as such a uapi change but one that we can reasonably risk. We've
+discussed this in earlier versions of this patchset (cf. [1]).
+
+The main user and provider of binfmt_misc is systemd. Systemd provides
+binfmt_misc via autofs since it is configurable as a kernel module and
+is used by a few exotic packages and users. As such a binfmt_misc mount
+is triggered when /proc/sys/fs/binfmt_misc is accessed and is only
+provided on demand. Other autofs on demand filesystems include EFI ESP
+which systemd umounts if the mountpoint stays idle for a certain amount
+of time. This doesn't apply to the binfmt_misc autofs mount which isn't
+touched once it is mounted meaning this change can't accidently wipe
+binary type handlers without someone having explicitly unmounted
+binfmt_misc. After speaking to systemd folks they don't expect this
+change to affect them.
+
+In line with our general policy, if we see a regression for systemd or
+other users with this change we will switch back to the old behavior for
+the initial binfmt_misc mount and have binary types pin the filesystem
+again. But while we touch this code let's take the chance and let's
+improve on the status quo.
+
+[1]: https://lore.kernel.org/r/20191216091220.465626-2-laurent@vivier.eu
+[2]: commit 43a4f2619038 ("exec: binfmt_misc: fix race between load_misc_binary() and kill_node()"
+[3]: commit 83f918274e4b ("exec: binfmt_misc: shift filp_close(interp_file) from kill_node() to bm_evict_inode()")
+[4]: commit f0fe2c0f050d ("binder: prevent UAF for binderfs devices II")
+
+Link: https://lore.kernel.org/r/20211028103114.2849140-1-brauner@kernel.org (v1)
+Cc: Sargun Dhillon <sargun@sargun.me>
+Cc: Serge Hallyn <serge@hallyn.com>
+Cc: Jann Horn <jannh@google.com>
+Cc: Henning Schild <henning.schild@siemens.com>
+Cc: Andrei Vagin <avagin@gmail.com>
+Cc: Al Viro <viro@zeniv.linux.org.uk>
+Cc: Laurent Vivier <laurent@vivier.eu>
+Cc: linux-fsdevel@vger.kernel.org
+Acked-by: Serge Hallyn <serge@hallyn.com>
+Signed-off-by: Christian Brauner <christian.brauner@ubuntu.com>
+Signed-off-by: Christian Brauner <brauner@kernel.org>
+Signed-off-by: Kees Cook <keescook@chromium.org>
+---
+/* v2 */
+- Christian Brauner <christian.brauner@ubuntu.com>:
+  - Add more comments that explain what's going on.
+  - Rename functions while changing them to better reflect what they are
+    doing to make the code easier to understand.
+  - In the first version when a specific binary type handler was removed
+    either through a write to the entry's file or all binary type
+    handlers were removed by a write to the binfmt_misc mount's status
+    file all cleanup work happened during inode eviction.
+    That includes removal of the relevant entries from entry list. While
+    that works fine I disliked that model after thinking about it for a
+    bit. Because it means that there was a window were someone has
+    already removed a or all binary handlers but they could still be
+    safely reached from load_misc_binary() when it has managed to take
+    the read_lock() on the entries list while inode eviction was already
+    happening. Again, that perfectly benign but it's cleaner to remove
+    the binary handler from the list immediately meaning that ones the
+    write to then entry's file or the binfmt_misc status file returns
+    the binary type cannot be executed anymore. That gives stronger
+    guarantees to the user.
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ fs/binfmt_misc.c | 216 ++++++++++++++++++++++++++++++++++++-----------
+ 1 file changed, 168 insertions(+), 48 deletions(-)
+
+diff --git a/fs/binfmt_misc.c b/fs/binfmt_misc.c
+index e0108d17b085c..cf5ed5cd4102d 100644
+--- a/fs/binfmt_misc.c
++++ b/fs/binfmt_misc.c
+@@ -60,12 +60,11 @@ typedef struct {
+       char *name;
+       struct dentry *dentry;
+       struct file *interp_file;
++      refcount_t users;               /* sync removal with load_misc_binary() */
+ } Node;
+ static DEFINE_RWLOCK(entries_lock);
+ static struct file_system_type bm_fs_type;
+-static struct vfsmount *bm_mnt;
+-static int entry_count;
+ /*
+  * Max length of the register string.  Determined by:
+@@ -82,19 +81,23 @@ static int entry_count;
+  */
+ #define MAX_REGISTER_LENGTH 1920
+-/*
+- * Check if we support the binfmt
+- * if we do, return the node, else NULL
+- * locking is done in load_misc_binary
++/**
++ * search_binfmt_handler - search for a binary handler for @bprm
++ * @misc: handle to binfmt_misc instance
++ * @bprm: binary for which we are looking for a handler
++ *
++ * Search for a binary type handler for @bprm in the list of registered binary
++ * type handlers.
++ *
++ * Return: binary type list entry on success, NULL on failure
+  */
+-static Node *check_file(struct linux_binprm *bprm)
++static Node *search_binfmt_handler(struct linux_binprm *bprm)
+ {
+       char *p = strrchr(bprm->interp, '.');
+-      struct list_head *l;
++      Node *e;
+       /* Walk all the registered handlers. */
+-      list_for_each(l, &entries) {
+-              Node *e = list_entry(l, Node, list);
++      list_for_each_entry(e, &entries, list) {
+               char *s;
+               int j;
+@@ -123,9 +126,49 @@ static Node *check_file(struct linux_binprm *bprm)
+               if (j == e->size)
+                       return e;
+       }
++
+       return NULL;
+ }
++/**
++ * get_binfmt_handler - try to find a binary type handler
++ * @misc: handle to binfmt_misc instance
++ * @bprm: binary for which we are looking for a handler
++ *
++ * Try to find a binfmt handler for the binary type. If one is found take a
++ * reference to protect against removal via bm_{entry,status}_write().
++ *
++ * Return: binary type list entry on success, NULL on failure
++ */
++static Node *get_binfmt_handler(struct linux_binprm *bprm)
++{
++      Node *e;
++
++      read_lock(&entries_lock);
++      e = search_binfmt_handler(bprm);
++      if (e)
++              refcount_inc(&e->users);
++      read_unlock(&entries_lock);
++      return e;
++}
++
++/**
++ * put_binfmt_handler - put binary handler node
++ * @e: node to put
++ *
++ * Free node syncing with load_misc_binary() and defer final free to
++ * load_misc_binary() in case it is using the binary type handler we were
++ * requested to remove.
++ */
++static void put_binfmt_handler(Node *e)
++{
++      if (refcount_dec_and_test(&e->users)) {
++              if (e->flags & MISC_FMT_OPEN_FILE)
++                      filp_close(e->interp_file, NULL);
++              kfree(e);
++      }
++}
++
+ /*
+  * the loader itself
+  */
+@@ -139,12 +182,7 @@ static int load_misc_binary(struct linux_binprm *bprm)
+       if (!enabled)
+               return retval;
+-      /* to keep locking time low, we copy the interpreter string */
+-      read_lock(&entries_lock);
+-      fmt = check_file(bprm);
+-      if (fmt)
+-              dget(fmt->dentry);
+-      read_unlock(&entries_lock);
++      fmt = get_binfmt_handler(bprm);
+       if (!fmt)
+               return retval;
+@@ -198,7 +236,16 @@ static int load_misc_binary(struct linux_binprm *bprm)
+       retval = 0;
+ ret:
+-      dput(fmt->dentry);
++
++      /*
++       * If we actually put the node here all concurrent calls to
++       * load_misc_binary() will have finished. We also know
++       * that for the refcount to be zero ->evict_inode() must have removed
++       * the node to be deleted from the list. All that is left for us is to
++       * close and free.
++       */
++      put_binfmt_handler(fmt);
++
+       return retval;
+ }
+@@ -552,30 +599,90 @@ static struct inode *bm_get_inode(struct super_block *sb, int mode)
+       return inode;
+ }
++/**
++ * bm_evict_inode - cleanup data associated with @inode
++ * @inode: inode to which the data is attached
++ *
++ * Cleanup the binary type handler data associated with @inode if a binary type
++ * entry is removed or the filesystem is unmounted and the super block is
++ * shutdown.
++ *
++ * If the ->evict call was not caused by a super block shutdown but by a write
++ * to remove the entry or all entries via bm_{entry,status}_write() the entry
++ * will have already been removed from the list. We keep the list_empty() check
++ * to make that explicit.
++*/
+ static void bm_evict_inode(struct inode *inode)
+ {
+       Node *e = inode->i_private;
+-      if (e && e->flags & MISC_FMT_OPEN_FILE)
+-              filp_close(e->interp_file, NULL);
+-
+       clear_inode(inode);
+-      kfree(e);
++
++      if (e) {
++              write_lock(&entries_lock);
++              if (!list_empty(&e->list))
++                      list_del_init(&e->list);
++              write_unlock(&entries_lock);
++              put_binfmt_handler(e);
++      }
+ }
+-static void kill_node(Node *e)
++/**
++ * unlink_binfmt_dentry - remove the dentry for the binary type handler
++ * @dentry: dentry associated with the binary type handler
++ *
++ * Do the actual filesystem work to remove a dentry for a registered binary
++ * type handler. Since binfmt_misc only allows simple files to be created
++ * directly under the root dentry of the filesystem we ensure that we are
++ * indeed passed a dentry directly beneath the root dentry, that the inode
++ * associated with the root dentry is locked, and that it is a regular file we
++ * are asked to remove.
++ */
++static void unlink_binfmt_dentry(struct dentry *dentry)
+ {
+-      struct dentry *dentry;
++      struct dentry *parent = dentry->d_parent;
++      struct inode *inode, *parent_inode;
++
++      /* All entries are immediate descendants of the root dentry. */
++      if (WARN_ON_ONCE(dentry->d_sb->s_root != parent))
++              return;
++      /* We only expect to be called on regular files. */
++      inode = d_inode(dentry);
++      if (WARN_ON_ONCE(!S_ISREG(inode->i_mode)))
++              return;
++
++      /* The parent inode must be locked. */
++      parent_inode = d_inode(parent);
++      if (WARN_ON_ONCE(!inode_is_locked(parent_inode)))
++              return;
++
++      if (simple_positive(dentry)) {
++              dget(dentry);
++              simple_unlink(parent_inode, dentry);
++              d_delete(dentry);
++              dput(dentry);
++      }
++}
++
++/**
++ * remove_binfmt_handler - remove a binary type handler
++ * @misc: handle to binfmt_misc instance
++ * @e: binary type handler to remove
++ *
++ * Remove a binary type handler from the list of binary type handlers and
++ * remove its associated dentry. This is called from
++ * binfmt_{entry,status}_write(). In the future, we might want to think about
++ * adding a proper ->unlink() method to binfmt_misc instead of forcing caller's
++ * to use writes to files in order to delete binary type handlers. But it has
++ * worked for so long that it's not a pressing issue.
++ */
++static void remove_binfmt_handler(Node *e)
++{
+       write_lock(&entries_lock);
+       list_del_init(&e->list);
+       write_unlock(&entries_lock);
+-
+-      dentry = e->dentry;
+-      drop_nlink(d_inode(dentry));
+-      d_drop(dentry);
+-      dput(dentry);
+-      simple_release_fs(&bm_mnt, &entry_count);
++      unlink_binfmt_dentry(e->dentry);
+ }
+ /* /<entry> */
+@@ -602,8 +709,8 @@ bm_entry_read(struct file *file, char __user *buf, size_t nbytes, loff_t *ppos)
+ static ssize_t bm_entry_write(struct file *file, const char __user *buffer,
+                               size_t count, loff_t *ppos)
+ {
+-      struct dentry *root;
+-      Node *e = file_inode(file)->i_private;
++      struct inode *inode = file_inode(file);
++      Node *e = inode->i_private;
+       int res = parse_command(buffer, count);
+       switch (res) {
+@@ -617,13 +724,22 @@ static ssize_t bm_entry_write(struct file *file, const char __user *buffer,
+               break;
+       case 3:
+               /* Delete this handler. */
+-              root = file_inode(file)->i_sb->s_root;
+-              inode_lock(d_inode(root));
++              inode = d_inode(inode->i_sb->s_root);
++              inode_lock(inode);
++              /*
++               * In order to add new element or remove elements from the list
++               * via bm_{entry,register,status}_write() inode_lock() on the
++               * root inode must be held.
++               * The lock is exclusive ensuring that the list can't be
++               * modified. Only load_misc_binary() can access but does so
++               * read-only. So we only need to take the write lock when we
++               * actually remove the entry from the list.
++               */
+               if (!list_empty(&e->list))
+-                      kill_node(e);
++                      remove_binfmt_handler(e);
+-              inode_unlock(d_inode(root));
++              inode_unlock(inode);
+               break;
+       default:
+               return res;
+@@ -682,13 +798,7 @@ static ssize_t bm_register_write(struct file *file, const char __user *buffer,
+       if (!inode)
+               goto out2;
+-      err = simple_pin_fs(&bm_fs_type, &bm_mnt, &entry_count);
+-      if (err) {
+-              iput(inode);
+-              inode = NULL;
+-              goto out2;
+-      }
+-
++      refcount_set(&e->users, 1);
+       e->dentry = dget(dentry);
+       inode->i_private = e;
+       inode->i_fop = &bm_entry_operations;
+@@ -732,7 +842,8 @@ static ssize_t bm_status_write(struct file *file, const char __user *buffer,
+               size_t count, loff_t *ppos)
+ {
+       int res = parse_command(buffer, count);
+-      struct dentry *root;
++      Node *e, *next;
++      struct inode *inode;
+       switch (res) {
+       case 1:
+@@ -745,13 +856,22 @@ static ssize_t bm_status_write(struct file *file, const char __user *buffer,
+               break;
+       case 3:
+               /* Delete all handlers. */
+-              root = file_inode(file)->i_sb->s_root;
+-              inode_lock(d_inode(root));
++              inode = d_inode(file_inode(file)->i_sb->s_root);
++              inode_lock(inode);
+-              while (!list_empty(&entries))
+-                      kill_node(list_first_entry(&entries, Node, list));
++              /*
++               * In order to add new element or remove elements from the list
++               * via bm_{entry,register,status}_write() inode_lock() on the
++               * root inode must be held.
++               * The lock is exclusive ensuring that the list can't be
++               * modified. Only load_misc_binary() can access but does so
++               * read-only. So we only need to take the write lock when we
++               * actually remove the entry from the list.
++               */
++              list_for_each_entry_safe(e, next, &entries, list)
++                      remove_binfmt_handler(e);
+-              inode_unlock(d_inode(root));
++              inode_unlock(inode);
+               break;
+       default:
+               return res;
+-- 
+2.43.0
+
diff --git a/queue-6.6/block-fix-lockdep-warning-in-blk_mq_mark_tag_wait.patch b/queue-6.6/block-fix-lockdep-warning-in-blk_mq_mark_tag_wait.patch
new file mode 100644 (file)
index 0000000..6e54ae2
--- /dev/null
@@ -0,0 +1,211 @@
+From 7c6f0b3661ad4b7e3ee698df636b41123f69d784 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 15 Aug 2024 10:47:36 +0800
+Subject: block: Fix lockdep warning in blk_mq_mark_tag_wait
+
+From: Li Lingfeng <lilingfeng3@huawei.com>
+
+[ Upstream commit b313a8c835516bdda85025500be866ac8a74e022 ]
+
+Lockdep reported a warning in Linux version 6.6:
+
+[  414.344659] ================================
+[  414.345155] WARNING: inconsistent lock state
+[  414.345658] 6.6.0-07439-gba2303cacfda #6 Not tainted
+[  414.346221] --------------------------------
+[  414.346712] inconsistent {IN-SOFTIRQ-W} -> {SOFTIRQ-ON-W} usage.
+[  414.347545] kworker/u10:3/1152 [HC0[0]:SC0[0]:HE0:SE1] takes:
+[  414.349245] ffff88810edd1098 (&sbq->ws[i].wait){+.?.}-{2:2}, at: blk_mq_dispatch_rq_list+0x131c/0x1ee0
+[  414.351204] {IN-SOFTIRQ-W} state was registered at:
+[  414.351751]   lock_acquire+0x18d/0x460
+[  414.352218]   _raw_spin_lock_irqsave+0x39/0x60
+[  414.352769]   __wake_up_common_lock+0x22/0x60
+[  414.353289]   sbitmap_queue_wake_up+0x375/0x4f0
+[  414.353829]   sbitmap_queue_clear+0xdd/0x270
+[  414.354338]   blk_mq_put_tag+0xdf/0x170
+[  414.354807]   __blk_mq_free_request+0x381/0x4d0
+[  414.355335]   blk_mq_free_request+0x28b/0x3e0
+[  414.355847]   __blk_mq_end_request+0x242/0xc30
+[  414.356367]   scsi_end_request+0x2c1/0x830
+[  414.345155] WARNING: inconsistent lock state
+[  414.345658] 6.6.0-07439-gba2303cacfda #6 Not tainted
+[  414.346221] --------------------------------
+[  414.346712] inconsistent {IN-SOFTIRQ-W} -> {SOFTIRQ-ON-W} usage.
+[  414.347545] kworker/u10:3/1152 [HC0[0]:SC0[0]:HE0:SE1] takes:
+[  414.349245] ffff88810edd1098 (&sbq->ws[i].wait){+.?.}-{2:2}, at: blk_mq_dispatch_rq_list+0x131c/0x1ee0
+[  414.351204] {IN-SOFTIRQ-W} state was registered at:
+[  414.351751]   lock_acquire+0x18d/0x460
+[  414.352218]   _raw_spin_lock_irqsave+0x39/0x60
+[  414.352769]   __wake_up_common_lock+0x22/0x60
+[  414.353289]   sbitmap_queue_wake_up+0x375/0x4f0
+[  414.353829]   sbitmap_queue_clear+0xdd/0x270
+[  414.354338]   blk_mq_put_tag+0xdf/0x170
+[  414.354807]   __blk_mq_free_request+0x381/0x4d0
+[  414.355335]   blk_mq_free_request+0x28b/0x3e0
+[  414.355847]   __blk_mq_end_request+0x242/0xc30
+[  414.356367]   scsi_end_request+0x2c1/0x830
+[  414.356863]   scsi_io_completion+0x177/0x1610
+[  414.357379]   scsi_complete+0x12f/0x260
+[  414.357856]   blk_complete_reqs+0xba/0xf0
+[  414.358338]   __do_softirq+0x1b0/0x7a2
+[  414.358796]   irq_exit_rcu+0x14b/0x1a0
+[  414.359262]   sysvec_call_function_single+0xaf/0xc0
+[  414.359828]   asm_sysvec_call_function_single+0x1a/0x20
+[  414.360426]   default_idle+0x1e/0x30
+[  414.360873]   default_idle_call+0x9b/0x1f0
+[  414.361390]   do_idle+0x2d2/0x3e0
+[  414.361819]   cpu_startup_entry+0x55/0x60
+[  414.362314]   start_secondary+0x235/0x2b0
+[  414.362809]   secondary_startup_64_no_verify+0x18f/0x19b
+[  414.363413] irq event stamp: 428794
+[  414.363825] hardirqs last  enabled at (428793): [<ffffffff816bfd1c>] ktime_get+0x1dc/0x200
+[  414.364694] hardirqs last disabled at (428794): [<ffffffff85470177>] _raw_spin_lock_irq+0x47/0x50
+[  414.365629] softirqs last  enabled at (428444): [<ffffffff85474780>] __do_softirq+0x540/0x7a2
+[  414.366522] softirqs last disabled at (428419): [<ffffffff813f65ab>] irq_exit_rcu+0x14b/0x1a0
+[  414.367425]
+               other info that might help us debug this:
+[  414.368194]  Possible unsafe locking scenario:
+[  414.368900]        CPU0
+[  414.369225]        ----
+[  414.369548]   lock(&sbq->ws[i].wait);
+[  414.370000]   <Interrupt>
+[  414.370342]     lock(&sbq->ws[i].wait);
+[  414.370802]
+                *** DEADLOCK ***
+[  414.371569] 5 locks held by kworker/u10:3/1152:
+[  414.372088]  #0: ffff88810130e938 ((wq_completion)writeback){+.+.}-{0:0}, at: process_scheduled_works+0x357/0x13f0
+[  414.373180]  #1: ffff88810201fdb8 ((work_completion)(&(&wb->dwork)->work)){+.+.}-{0:0}, at: process_scheduled_works+0x3a3/0x13f0
+[  414.374384]  #2: ffffffff86ffbdc0 (rcu_read_lock){....}-{1:2}, at: blk_mq_run_hw_queue+0x637/0xa00
+[  414.375342]  #3: ffff88810edd1098 (&sbq->ws[i].wait){+.?.}-{2:2}, at: blk_mq_dispatch_rq_list+0x131c/0x1ee0
+[  414.376377]  #4: ffff888106205a08 (&hctx->dispatch_wait_lock){+.-.}-{2:2}, at: blk_mq_dispatch_rq_list+0x1337/0x1ee0
+[  414.378607]
+               stack backtrace:
+[  414.379177] CPU: 0 PID: 1152 Comm: kworker/u10:3 Not tainted 6.6.0-07439-gba2303cacfda #6
+[  414.380032] Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS rel-1.14.0-0-g155821a1990b-prebuilt.qemu.org 04/01/2014
+[  414.381177] Workqueue: writeback wb_workfn (flush-253:0)
+[  414.381805] Call Trace:
+[  414.382136]  <TASK>
+[  414.382429]  dump_stack_lvl+0x91/0xf0
+[  414.382884]  mark_lock_irq+0xb3b/0x1260
+[  414.383367]  ? __pfx_mark_lock_irq+0x10/0x10
+[  414.383889]  ? stack_trace_save+0x8e/0xc0
+[  414.384373]  ? __pfx_stack_trace_save+0x10/0x10
+[  414.384903]  ? graph_lock+0xcf/0x410
+[  414.385350]  ? save_trace+0x3d/0xc70
+[  414.385808]  mark_lock.part.20+0x56d/0xa90
+[  414.386317]  mark_held_locks+0xb0/0x110
+[  414.386791]  ? __pfx_do_raw_spin_lock+0x10/0x10
+[  414.387320]  lockdep_hardirqs_on_prepare+0x297/0x3f0
+[  414.387901]  ? _raw_spin_unlock_irq+0x28/0x50
+[  414.388422]  trace_hardirqs_on+0x58/0x100
+[  414.388917]  _raw_spin_unlock_irq+0x28/0x50
+[  414.389422]  __blk_mq_tag_busy+0x1d6/0x2a0
+[  414.389920]  __blk_mq_get_driver_tag+0x761/0x9f0
+[  414.390899]  blk_mq_dispatch_rq_list+0x1780/0x1ee0
+[  414.391473]  ? __pfx_blk_mq_dispatch_rq_list+0x10/0x10
+[  414.392070]  ? sbitmap_get+0x2b8/0x450
+[  414.392533]  ? __blk_mq_get_driver_tag+0x210/0x9f0
+[  414.393095]  __blk_mq_sched_dispatch_requests+0xd99/0x1690
+[  414.393730]  ? elv_attempt_insert_merge+0x1b1/0x420
+[  414.394302]  ? __pfx___blk_mq_sched_dispatch_requests+0x10/0x10
+[  414.394970]  ? lock_acquire+0x18d/0x460
+[  414.395456]  ? blk_mq_run_hw_queue+0x637/0xa00
+[  414.395986]  ? __pfx_lock_acquire+0x10/0x10
+[  414.396499]  blk_mq_sched_dispatch_requests+0x109/0x190
+[  414.397100]  blk_mq_run_hw_queue+0x66e/0xa00
+[  414.397616]  blk_mq_flush_plug_list.part.17+0x614/0x2030
+[  414.398244]  ? __pfx_blk_mq_flush_plug_list.part.17+0x10/0x10
+[  414.398897]  ? writeback_sb_inodes+0x241/0xcc0
+[  414.399429]  blk_mq_flush_plug_list+0x65/0x80
+[  414.399957]  __blk_flush_plug+0x2f1/0x530
+[  414.400458]  ? __pfx___blk_flush_plug+0x10/0x10
+[  414.400999]  blk_finish_plug+0x59/0xa0
+[  414.401467]  wb_writeback+0x7cc/0x920
+[  414.401935]  ? __pfx_wb_writeback+0x10/0x10
+[  414.402442]  ? mark_held_locks+0xb0/0x110
+[  414.402931]  ? __pfx_do_raw_spin_lock+0x10/0x10
+[  414.403462]  ? lockdep_hardirqs_on_prepare+0x297/0x3f0
+[  414.404062]  wb_workfn+0x2b3/0xcf0
+[  414.404500]  ? __pfx_wb_workfn+0x10/0x10
+[  414.404989]  process_scheduled_works+0x432/0x13f0
+[  414.405546]  ? __pfx_process_scheduled_works+0x10/0x10
+[  414.406139]  ? do_raw_spin_lock+0x101/0x2a0
+[  414.406641]  ? assign_work+0x19b/0x240
+[  414.407106]  ? lock_is_held_type+0x9d/0x110
+[  414.407604]  worker_thread+0x6f2/0x1160
+[  414.408075]  ? __kthread_parkme+0x62/0x210
+[  414.408572]  ? lockdep_hardirqs_on_prepare+0x297/0x3f0
+[  414.409168]  ? __kthread_parkme+0x13c/0x210
+[  414.409678]  ? __pfx_worker_thread+0x10/0x10
+[  414.410191]  kthread+0x33c/0x440
+[  414.410602]  ? __pfx_kthread+0x10/0x10
+[  414.411068]  ret_from_fork+0x4d/0x80
+[  414.411526]  ? __pfx_kthread+0x10/0x10
+[  414.411993]  ret_from_fork_asm+0x1b/0x30
+[  414.412489]  </TASK>
+
+When interrupt is turned on while a lock holding by spin_lock_irq it
+throws a warning because of potential deadlock.
+
+blk_mq_prep_dispatch_rq
+ blk_mq_get_driver_tag
+  __blk_mq_get_driver_tag
+   __blk_mq_alloc_driver_tag
+    blk_mq_tag_busy -> tag is already busy
+    // failed to get driver tag
+ blk_mq_mark_tag_wait
+  spin_lock_irq(&wq->lock) -> lock A (&sbq->ws[i].wait)
+  __add_wait_queue(wq, wait) -> wait queue active
+  blk_mq_get_driver_tag
+  __blk_mq_tag_busy
+-> 1) tag must be idle, which means there can't be inflight IO
+   spin_lock_irq(&tags->lock) -> lock B (hctx->tags)
+   spin_unlock_irq(&tags->lock) -> unlock B, turn on interrupt accidentally
+-> 2) context must be preempt by IO interrupt to trigger deadlock.
+
+As shown above, the deadlock is not possible in theory, but the warning
+still need to be fixed.
+
+Fix it by using spin_lock_irqsave to get lockB instead of spin_lock_irq.
+
+Fixes: 4f1731df60f9 ("blk-mq: fix potential io hang by wrong 'wake_batch'")
+Signed-off-by: Li Lingfeng <lilingfeng3@huawei.com>
+Reviewed-by: Ming Lei <ming.lei@redhat.com>
+Reviewed-by: Yu Kuai <yukuai3@huawei.com>
+Reviewed-by: Bart Van Assche <bvanassche@acm.org>
+Link: https://lore.kernel.org/r/20240815024736.2040971-1-lilingfeng@huaweicloud.com
+Signed-off-by: Jens Axboe <axboe@kernel.dk>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ block/blk-mq-tag.c | 5 +++--
+ 1 file changed, 3 insertions(+), 2 deletions(-)
+
+diff --git a/block/blk-mq-tag.c b/block/blk-mq-tag.c
+index cc57e2dd9a0bb..2cafcf11ee8be 100644
+--- a/block/blk-mq-tag.c
++++ b/block/blk-mq-tag.c
+@@ -38,6 +38,7 @@ static void blk_mq_update_wake_batch(struct blk_mq_tags *tags,
+ void __blk_mq_tag_busy(struct blk_mq_hw_ctx *hctx)
+ {
+       unsigned int users;
++      unsigned long flags;
+       struct blk_mq_tags *tags = hctx->tags;
+       /*
+@@ -56,11 +57,11 @@ void __blk_mq_tag_busy(struct blk_mq_hw_ctx *hctx)
+                       return;
+       }
+-      spin_lock_irq(&tags->lock);
++      spin_lock_irqsave(&tags->lock, flags);
+       users = tags->active_queues + 1;
+       WRITE_ONCE(tags->active_queues, users);
+       blk_mq_update_wake_batch(tags, users);
+-      spin_unlock_irq(&tags->lock);
++      spin_unlock_irqrestore(&tags->lock, flags);
+ }
+ /*
+-- 
+2.43.0
+
diff --git a/queue-6.6/cgroup-avoid-extra-dereference-in-css_populate_dir.patch b/queue-6.6/cgroup-avoid-extra-dereference-in-css_populate_dir.patch
new file mode 100644 (file)
index 0000000..df690d9
--- /dev/null
@@ -0,0 +1,44 @@
+From 3aa0e54c9babd05ff40331602f7bddbf4139daf2 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 12 Sep 2023 12:34:35 +0530
+Subject: cgroup: Avoid extra dereference in css_populate_dir()
+
+From: Kamalesh Babulal <kamalesh.babulal@oracle.com>
+
+[ Upstream commit d24f05987ce8bf61e62d86fedbe47523dc5c3393 ]
+
+Use css directly instead of dereferencing it from &cgroup->self, while
+adding the cgroup v2 cft base and psi files in css_populate_dir(). Both
+points to the same css, when css->ss is NULL, this avoids extra deferences
+and makes code consistent in usage across the function.
+
+Signed-off-by: Kamalesh Babulal <kamalesh.babulal@oracle.com>
+Signed-off-by: Tejun Heo <tj@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ kernel/cgroup/cgroup.c | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/kernel/cgroup/cgroup.c b/kernel/cgroup/cgroup.c
+index d872fff901073..5eca6281d1aa6 100644
+--- a/kernel/cgroup/cgroup.c
++++ b/kernel/cgroup/cgroup.c
+@@ -1728,13 +1728,13 @@ static int css_populate_dir(struct cgroup_subsys_state *css)
+       if (!css->ss) {
+               if (cgroup_on_dfl(cgrp)) {
+-                      ret = cgroup_addrm_files(&cgrp->self, cgrp,
++                      ret = cgroup_addrm_files(css, cgrp,
+                                                cgroup_base_files, true);
+                       if (ret < 0)
+                               return ret;
+                       if (cgroup_psi_enabled()) {
+-                              ret = cgroup_addrm_files(&cgrp->self, cgrp,
++                              ret = cgroup_addrm_files(css, cgrp,
+                                                        cgroup_psi_files, true);
+                               if (ret < 0)
+                                       return ret;
+-- 
+2.43.0
+
diff --git a/queue-6.6/clk-visconti-add-bounds-checking-coverage-for-struct.patch b/queue-6.6/clk-visconti-add-bounds-checking-coverage-for-struct.patch
new file mode 100644 (file)
index 0000000..1d76775
--- /dev/null
@@ -0,0 +1,80 @@
+From db365cdc9787cdc829e1ae15ca3218ca535b8c6f Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 16 Oct 2023 16:06:16 -0600
+Subject: clk: visconti: Add bounds-checking coverage for struct
+ visconti_pll_provider
+
+From: Gustavo A. R. Silva <gustavoars@kernel.org>
+
+[ Upstream commit 397d887c1601a71e8a8abdb6beea67d58f0472d3 ]
+
+In order to gain the bounds-checking coverage that __counted_by provides
+to flexible-array members at run-time via CONFIG_UBSAN_BOUNDS (for array
+indexing) and CONFIG_FORTIFY_SOURCE (for strcpy/memcpy-family functions),
+we must make sure that the counter member, in this particular case `num`,
+is updated before the first access to the flex-array member, in this
+particular case array `hws`. See below:
+
+commit f316cdff8d67 ("clk: Annotate struct clk_hw_onecell_data with
+__counted_by") introduced `__counted_by` for `struct clk_hw_onecell_data`
+together with changes to relocate some of assignments of counter `num`
+before `hws` is accessed:
+
+include/linux/clk-provider.h:
+1380 struct clk_hw_onecell_data {
+1381         unsigned int num;
+1382         struct clk_hw *hws[] __counted_by(num);
+1383 };
+
+However, this structure is used as a member in other structs, in this
+case in `struct visconti_pll_provider`:
+
+drivers/clk/visconti/pll.h:
+ 16 struct visconti_pll_provider {
+ 17         void __iomem *reg_base;
+ 18         struct device_node *node;
+ 19
+ 20         /* Must be last */
+ 21         struct clk_hw_onecell_data clk_data;
+ 22 };
+
+Hence, we need to move the assignments to `ctx->clk_data.num` after
+allocation for `struct visconti_pll_provider` and before accessing the
+flexible array `ctx->clk_data.hws`. And, as assignments for all members
+in `struct visconti_pll_provider` are originally adjacent to each other,
+relocate all assignments together, so we don't split up
+`ctx->clk_data.hws = nr_plls` from the rest. :)
+
+Reviewed-by: Kees Cook <keescook@chromium.org>
+Acked-by: Nobuhiro Iwamatsu <nobuhiro1.iwamatsu@toshiba.co.jp>
+Signed-off-by: Gustavo A. R. Silva <gustavoars@kernel.org>
+Link: https://lore.kernel.org/r/e3189f3e40e8723b6d794fb2260e2e9ab6b960bd.1697492890.git.gustavoars@kernel.org
+Signed-off-by: Stephen Boyd <sboyd@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/clk/visconti/pll.c | 6 +++---
+ 1 file changed, 3 insertions(+), 3 deletions(-)
+
+diff --git a/drivers/clk/visconti/pll.c b/drivers/clk/visconti/pll.c
+index 1f3234f226674..e9cd80e085dc3 100644
+--- a/drivers/clk/visconti/pll.c
++++ b/drivers/clk/visconti/pll.c
+@@ -329,12 +329,12 @@ struct visconti_pll_provider * __init visconti_init_pll(struct device_node *np,
+       if (!ctx)
+               return ERR_PTR(-ENOMEM);
+-      for (i = 0; i < nr_plls; ++i)
+-              ctx->clk_data.hws[i] = ERR_PTR(-ENOENT);
+-
+       ctx->node = np;
+       ctx->reg_base = base;
+       ctx->clk_data.num = nr_plls;
++      for (i = 0; i < nr_plls; ++i)
++              ctx->clk_data.hws[i] = ERR_PTR(-ENOENT);
++
+       return ctx;
+ }
+-- 
+2.43.0
+
diff --git a/queue-6.6/cpu-smt-enable-smt-only-if-a-core-is-online.patch b/queue-6.6/cpu-smt-enable-smt-only-if-a-core-is-online.patch
new file mode 100644 (file)
index 0000000..2aa4155
--- /dev/null
@@ -0,0 +1,88 @@
+From 9fddf7eae19817ddfe881f54bfc8bf18202034bb Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 31 Jul 2024 08:31:12 +0530
+Subject: cpu/SMT: Enable SMT only if a core is online
+
+From: Nysal Jan K.A <nysal@linux.ibm.com>
+
+[ Upstream commit 6c17ea1f3eaa330d445ac14a9428402ce4e3055e ]
+
+If a core is offline then enabling SMT should not online CPUs of
+this core. By enabling SMT, what is intended is either changing the SMT
+value from "off" to "on" or setting the SMT level (threads per core) from a
+lower to higher value.
+
+On PowerPC the ppc64_cpu utility can be used, among other things, to
+perform the following functions:
+
+ppc64_cpu --cores-on                # Get the number of online cores
+ppc64_cpu --cores-on=X              # Put exactly X cores online
+ppc64_cpu --offline-cores=X[,Y,...] # Put specified cores offline
+ppc64_cpu --smt={on|off|value}      # Enable, disable or change SMT level
+
+If the user has decided to offline certain cores, enabling SMT should
+not online CPUs in those cores. This patch fixes the issue and changes
+the behaviour as described, by introducing an arch specific function
+topology_is_core_online(). It is currently implemented only for PowerPC.
+
+Fixes: 73c58e7e1412 ("powerpc: Add HOTPLUG_SMT support")
+Reported-by: Tyrel Datwyler <tyreld@linux.ibm.com>
+Closes: https://groups.google.com/g/powerpc-utils-devel/c/wrwVzAAnRlI/m/5KJSoqP4BAAJ
+Signed-off-by: Nysal Jan K.A <nysal@linux.ibm.com>
+Reviewed-by: Shrikanth Hegde <sshegde@linux.ibm.com>
+Reviewed-by: Thomas Gleixner <tglx@linutronix.de>
+Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
+Link: https://msgid.link/20240731030126.956210-2-nysal@linux.ibm.com
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ Documentation/ABI/testing/sysfs-devices-system-cpu |  3 ++-
+ kernel/cpu.c                                       | 12 +++++++++++-
+ 2 files changed, 13 insertions(+), 2 deletions(-)
+
+diff --git a/Documentation/ABI/testing/sysfs-devices-system-cpu b/Documentation/ABI/testing/sysfs-devices-system-cpu
+index 34b6f6ab47422..657bdee28d845 100644
+--- a/Documentation/ABI/testing/sysfs-devices-system-cpu
++++ b/Documentation/ABI/testing/sysfs-devices-system-cpu
+@@ -565,7 +565,8 @@ Description:       Control Symmetric Multi Threading (SMT)
+                        ================ =========================================
+                        If control status is "forceoff" or "notsupported" writes
+-                       are rejected.
++                       are rejected. Note that enabling SMT on PowerPC skips
++                       offline cores.
+ What:         /sys/devices/system/cpu/cpuX/power/energy_perf_bias
+ Date:         March 2019
+diff --git a/kernel/cpu.c b/kernel/cpu.c
+index 874bfb952e6e8..0c72b94ed076a 100644
+--- a/kernel/cpu.c
++++ b/kernel/cpu.c
+@@ -2728,6 +2728,16 @@ int cpuhp_smt_disable(enum cpuhp_smt_control ctrlval)
+       return ret;
+ }
++/**
++ * Check if the core a CPU belongs to is online
++ */
++#if !defined(topology_is_core_online)
++static inline bool topology_is_core_online(unsigned int cpu)
++{
++      return true;
++}
++#endif
++
+ int cpuhp_smt_enable(void)
+ {
+       int cpu, ret = 0;
+@@ -2738,7 +2748,7 @@ int cpuhp_smt_enable(void)
+               /* Skip online CPUs and CPUs on offline nodes */
+               if (cpu_online(cpu) || !node_online(cpu_to_node(cpu)))
+                       continue;
+-              if (!cpu_smt_thread_allowed(cpu))
++              if (!cpu_smt_thread_allowed(cpu) || !topology_is_core_online(cpu))
+                       continue;
+               ret = _cpu_up(cpu, 0, CPUHP_ONLINE);
+               if (ret)
+-- 
+2.43.0
+
diff --git a/queue-6.6/drm-amd-amdgpu-imu_v11_0-increase-buffer-size-to-ens.patch b/queue-6.6/drm-amd-amdgpu-imu_v11_0-increase-buffer-size-to-ens.patch
new file mode 100644 (file)
index 0000000..f25818f
--- /dev/null
@@ -0,0 +1,42 @@
+From ef28c788bc05b6bd71a2cd0d1ee53559605c2056 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 24 Aug 2023 08:37:05 +0100
+Subject: drm/amd/amdgpu/imu_v11_0: Increase buffer size to ensure all possible
+ values can be stored
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Lee Jones <lee@kernel.org>
+
+[ Upstream commit a728342ae4ec2a7fdab0038b11427579424f133e ]
+
+Fixes the following W=1 kernel build warning(s):
+
+ drivers/gpu/drm/amd/amdgpu/imu_v11_0.c: In function â€˜imu_v11_0_init_microcode’:
+ drivers/gpu/drm/amd/amdgpu/imu_v11_0.c:52:54: warning: â€˜_imu.bin’ directive output may be truncated writing 8 bytes into a region of size between 4 and 33 [-Wformat-truncation=]
+ drivers/gpu/drm/amd/amdgpu/imu_v11_0.c:52:9: note: â€˜snprintf’ output between 16 and 45 bytes into a destination of size 40
+
+Signed-off-by: Lee Jones <lee@kernel.org>
+Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/gpu/drm/amd/amdgpu/imu_v11_0.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/drivers/gpu/drm/amd/amdgpu/imu_v11_0.c b/drivers/gpu/drm/amd/amdgpu/imu_v11_0.c
+index 4ab90c7852c3e..ca123ff553477 100644
+--- a/drivers/gpu/drm/amd/amdgpu/imu_v11_0.c
++++ b/drivers/gpu/drm/amd/amdgpu/imu_v11_0.c
+@@ -39,7 +39,7 @@ MODULE_FIRMWARE("amdgpu/gc_11_0_4_imu.bin");
+ static int imu_v11_0_init_microcode(struct amdgpu_device *adev)
+ {
+-      char fw_name[40];
++      char fw_name[45];
+       char ucode_prefix[30];
+       int err;
+       const struct imu_firmware_header_v1_0 *imu_hdr;
+-- 
+2.43.0
+
diff --git a/queue-6.6/drm-amd-display-validate-hw_points_num-before-using-.patch b/queue-6.6/drm-amd-display-validate-hw_points_num-before-using-.patch
new file mode 100644 (file)
index 0000000..543e08d
--- /dev/null
@@ -0,0 +1,42 @@
+From 691bca2638abd8a97ecbd4867c31fd748f257777 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 10 Jul 2023 18:23:58 -0600
+Subject: drm/amd/display: Validate hw_points_num before using it
+
+From: Alex Hung <alex.hung@amd.com>
+
+[ Upstream commit 58c3b3341cea4f75dc8c003b89f8a6dd8ec55e50 ]
+
+[WHAT]
+hw_points_num is 0 before ogam LUT is programmed; however, function
+"dwb3_program_ogam_pwl" assumes hw_points_num is always greater than 0,
+i.e. substracting it by 1 as an array index.
+
+[HOW]
+Check hw_points_num is not equal to 0 before using it.
+
+Reviewed-by: Harry Wentland <harry.wentland@amd.com>
+Signed-off-by: Alex Hung <alex.hung@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/dcn30/dcn30_dwb_cm.c | 3 +++
+ 1 file changed, 3 insertions(+)
+
+diff --git a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_dwb_cm.c b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_dwb_cm.c
+index 701c7d8bc038a..03a50c32fcfe1 100644
+--- a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_dwb_cm.c
++++ b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_dwb_cm.c
+@@ -243,6 +243,9 @@ static bool dwb3_program_ogam_lut(
+               return false;
+       }
++      if (params->hw_points_num == 0)
++              return false;
++
+       REG_SET(DWB_OGAM_CONTROL, 0, DWB_OGAM_MODE, 2);
+       current_mode = dwb3_get_ogam_current(dwbc30);
+-- 
+2.43.0
+
diff --git a/queue-6.6/drm-amd-pm-fix-error-flow-in-sensor-fetching.patch b/queue-6.6/drm-amd-pm-fix-error-flow-in-sensor-fetching.patch
new file mode 100644 (file)
index 0000000..df2f026
--- /dev/null
@@ -0,0 +1,69 @@
+From faf89220d243dd36ca4bf8f0e622a96bf28621ad Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 18 Aug 2023 12:21:32 -0400
+Subject: drm/amd/pm: fix error flow in sensor fetching
+
+From: Alex Deucher <alexander.deucher@amd.com>
+
+[ Upstream commit a5600853167aeba5cade81f184a382a0d1b14641 ]
+
+Sensor fetching functions should return an signed int to
+handle errors properly.
+
+Reviewed-by: Srinivasan Shanmugam <srinivasan.shanmugam@amd.com>
+Reported-by: Jiapeng Chong <jiapeng.chong@linux.alibaba.com>
+Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/gpu/drm/amd/pm/amdgpu_pm.c | 14 +++++++-------
+ 1 file changed, 7 insertions(+), 7 deletions(-)
+
+diff --git a/drivers/gpu/drm/amd/pm/amdgpu_pm.c b/drivers/gpu/drm/amd/pm/amdgpu_pm.c
+index 7372eae0b0ef8..babb73147adfb 100644
+--- a/drivers/gpu/drm/amd/pm/amdgpu_pm.c
++++ b/drivers/gpu/drm/amd/pm/amdgpu_pm.c
+@@ -1471,9 +1471,9 @@ static ssize_t amdgpu_set_pp_power_profile_mode(struct device *dev,
+       return -EINVAL;
+ }
+-static unsigned int amdgpu_hwmon_get_sensor_generic(struct amdgpu_device *adev,
+-                                                  enum amd_pp_sensors sensor,
+-                                                  void *query)
++static int amdgpu_hwmon_get_sensor_generic(struct amdgpu_device *adev,
++                                         enum amd_pp_sensors sensor,
++                                         void *query)
+ {
+       int r, size = sizeof(uint32_t);
+@@ -2787,8 +2787,8 @@ static ssize_t amdgpu_hwmon_show_vddnb_label(struct device *dev,
+       return sysfs_emit(buf, "vddnb\n");
+ }
+-static unsigned int amdgpu_hwmon_get_power(struct device *dev,
+-                                         enum amd_pp_sensors sensor)
++static int amdgpu_hwmon_get_power(struct device *dev,
++                                enum amd_pp_sensors sensor)
+ {
+       struct amdgpu_device *adev = dev_get_drvdata(dev);
+       unsigned int uw;
+@@ -2809,7 +2809,7 @@ static ssize_t amdgpu_hwmon_show_power_avg(struct device *dev,
+                                          struct device_attribute *attr,
+                                          char *buf)
+ {
+-      unsigned int val;
++      int val;
+       val = amdgpu_hwmon_get_power(dev, AMDGPU_PP_SENSOR_GPU_AVG_POWER);
+       if (val < 0)
+@@ -2822,7 +2822,7 @@ static ssize_t amdgpu_hwmon_show_power_input(struct device *dev,
+                                            struct device_attribute *attr,
+                                            char *buf)
+ {
+-      unsigned int val;
++      int val;
+       val = amdgpu_hwmon_get_power(dev, AMDGPU_PP_SENSOR_GPU_INPUT_POWER);
+       if (val < 0)
+-- 
+2.43.0
+
diff --git a/queue-6.6/drm-amdgpu-access-rlc_spm_mc_cntl-through-mmio-in-sr.patch b/queue-6.6/drm-amdgpu-access-rlc_spm_mc_cntl-through-mmio-in-sr.patch
new file mode 100644 (file)
index 0000000..9769416
--- /dev/null
@@ -0,0 +1,87 @@
+From 2ff3d3a224a13708fca6f0dad110a67c660b8b9a Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 28 Aug 2023 14:18:52 +0800
+Subject: drm/amdgpu: access RLC_SPM_MC_CNTL through MMIO in SRIOV runtime
+
+From: ZhenGuo Yin <zhenguo.yin@amd.com>
+
+[ Upstream commit 9f05cfc78c6880e06940ea78fbc43f6392710f17 ]
+
+Register RLC_SPM_MC_CNTL is not blocked by L1 policy, VF can
+directly access it through MMIO during SRIOV runtime.
+
+v2: use SOC15 interface to access registers
+
+Acked-by: Alex Deucher <alexander.deucher@amd.com>
+Signed-off-by: ZhenGuo Yin <zhenguo.yin@amd.com>
+Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c | 13 +++----------
+ drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c | 13 +++----------
+ 2 files changed, 6 insertions(+), 20 deletions(-)
+
+diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c b/drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c
+index 3560a3f2c848e..cd594b92c6129 100644
+--- a/drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c
++++ b/drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c
+@@ -7892,22 +7892,15 @@ static int gfx_v10_0_update_gfx_clock_gating(struct amdgpu_device *adev,
+ static void gfx_v10_0_update_spm_vmid_internal(struct amdgpu_device *adev,
+                                              unsigned int vmid)
+ {
+-      u32 reg, data;
++      u32 data;
+       /* not for *_SOC15 */
+-      reg = SOC15_REG_OFFSET(GC, 0, mmRLC_SPM_MC_CNTL);
+-      if (amdgpu_sriov_is_pp_one_vf(adev))
+-              data = RREG32_NO_KIQ(reg);
+-      else
+-              data = RREG32_SOC15(GC, 0, mmRLC_SPM_MC_CNTL);
++      data = RREG32_SOC15_NO_KIQ(GC, 0, mmRLC_SPM_MC_CNTL);
+       data &= ~RLC_SPM_MC_CNTL__RLC_SPM_VMID_MASK;
+       data |= (vmid & RLC_SPM_MC_CNTL__RLC_SPM_VMID_MASK) << RLC_SPM_MC_CNTL__RLC_SPM_VMID__SHIFT;
+-      if (amdgpu_sriov_is_pp_one_vf(adev))
+-              WREG32_SOC15_NO_KIQ(GC, 0, mmRLC_SPM_MC_CNTL, data);
+-      else
+-              WREG32_SOC15(GC, 0, mmRLC_SPM_MC_CNTL, data);
++      WREG32_SOC15_NO_KIQ(GC, 0, mmRLC_SPM_MC_CNTL, data);
+ }
+ static void gfx_v10_0_update_spm_vmid(struct amdgpu_device *adev, unsigned int vmid)
+diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c b/drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c
+index daab4c7a073ac..c81e98f0d17ff 100644
+--- a/drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c
++++ b/drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c
+@@ -4961,23 +4961,16 @@ static int gfx_v11_0_update_gfx_clock_gating(struct amdgpu_device *adev,
+ static void gfx_v11_0_update_spm_vmid(struct amdgpu_device *adev, unsigned vmid)
+ {
+-      u32 reg, data;
++      u32 data;
+       amdgpu_gfx_off_ctrl(adev, false);
+-      reg = SOC15_REG_OFFSET(GC, 0, regRLC_SPM_MC_CNTL);
+-      if (amdgpu_sriov_is_pp_one_vf(adev))
+-              data = RREG32_NO_KIQ(reg);
+-      else
+-              data = RREG32(reg);
++      data = RREG32_SOC15_NO_KIQ(GC, 0, regRLC_SPM_MC_CNTL);
+       data &= ~RLC_SPM_MC_CNTL__RLC_SPM_VMID_MASK;
+       data |= (vmid & RLC_SPM_MC_CNTL__RLC_SPM_VMID_MASK) << RLC_SPM_MC_CNTL__RLC_SPM_VMID__SHIFT;
+-      if (amdgpu_sriov_is_pp_one_vf(adev))
+-              WREG32_SOC15_NO_KIQ(GC, 0, regRLC_SPM_MC_CNTL, data);
+-      else
+-              WREG32_SOC15(GC, 0, regRLC_SPM_MC_CNTL, data);
++      WREG32_SOC15_NO_KIQ(GC, 0, regRLC_SPM_MC_CNTL, data);
+       amdgpu_gfx_off_ctrl(adev, true);
+ }
+-- 
+2.43.0
+
diff --git a/queue-6.6/drm-amdkfd-move-dma-unmapping-after-tlb-flush.patch b/queue-6.6/drm-amdkfd-move-dma-unmapping-after-tlb-flush.patch
new file mode 100644 (file)
index 0000000..20c0490
--- /dev/null
@@ -0,0 +1,144 @@
+From 23f8ef0f6e5deee5814fda6ec2e2ee4c2f19a384 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 11 Sep 2023 14:44:22 -0400
+Subject: drm/amdkfd: Move dma unmapping after TLB flush
+
+From: Philip Yang <Philip.Yang@amd.com>
+
+[ Upstream commit 101b8104307eac734f2dfa4d3511430b0b631c73 ]
+
+Otherwise GPU may access the stale mapping and generate IOMMU
+IO_PAGE_FAULT.
+
+Move this to inside p->mutex to prevent multiple threads mapping and
+unmapping concurrently race condition.
+
+After kfd_mem_dmaunmap_attachment is removed from unmap_bo_from_gpuvm,
+kfd_mem_dmaunmap_attachment is called if failed to map to GPUs, and
+before free the mem attachment in case failed to unmap from GPUs.
+
+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_amdkfd.h    |  1 +
+ .../gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c  | 26 ++++++++++++++++---
+ drivers/gpu/drm/amd/amdkfd/kfd_chardev.c      | 20 ++++++++------
+ 3 files changed, 35 insertions(+), 12 deletions(-)
+
+diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.h
+index 2fe9860725bd9..5e4fb33b97351 100644
+--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.h
++++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.h
+@@ -303,6 +303,7 @@ int amdgpu_amdkfd_gpuvm_map_memory_to_gpu(struct amdgpu_device *adev,
+                                         struct kgd_mem *mem, void *drm_priv);
+ int amdgpu_amdkfd_gpuvm_unmap_memory_from_gpu(
+               struct amdgpu_device *adev, struct kgd_mem *mem, void *drm_priv);
++void amdgpu_amdkfd_gpuvm_dmaunmap_mem(struct kgd_mem *mem, void *drm_priv);
+ int amdgpu_amdkfd_gpuvm_sync_memory(
+               struct amdgpu_device *adev, struct kgd_mem *mem, bool intr);
+ int amdgpu_amdkfd_gpuvm_map_gtt_bo_to_kernel(struct kgd_mem *mem,
+diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c
+index 62c1dc9510a41..c2d1d57a6c668 100644
+--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c
++++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c
+@@ -733,7 +733,7 @@ kfd_mem_dmaunmap_sg_bo(struct kgd_mem *mem,
+       enum dma_data_direction dir;
+       if (unlikely(!ttm->sg)) {
+-              pr_err("SG Table of BO is UNEXPECTEDLY NULL");
++              pr_debug("SG Table of BO is NULL");
+               return;
+       }
+@@ -1202,8 +1202,6 @@ static void unmap_bo_from_gpuvm(struct kgd_mem *mem,
+       amdgpu_vm_clear_freed(adev, vm, &bo_va->last_pt_update);
+       amdgpu_sync_fence(sync, bo_va->last_pt_update);
+-
+-      kfd_mem_dmaunmap_attachment(mem, entry);
+ }
+ static int update_gpuvm_pte(struct kgd_mem *mem,
+@@ -1258,6 +1256,7 @@ static int map_bo_to_gpuvm(struct kgd_mem *mem,
+ update_gpuvm_pte_failed:
+       unmap_bo_from_gpuvm(mem, entry, sync);
++      kfd_mem_dmaunmap_attachment(mem, entry);
+       return ret;
+ }
+@@ -1862,8 +1861,10 @@ int amdgpu_amdkfd_gpuvm_free_memory_of_gpu(
+               mem->va + bo_size * (1 + mem->aql_queue));
+       /* Remove from VM internal data structures */
+-      list_for_each_entry_safe(entry, tmp, &mem->attachments, list)
++      list_for_each_entry_safe(entry, tmp, &mem->attachments, list) {
++              kfd_mem_dmaunmap_attachment(mem, entry);
+               kfd_mem_detach(entry);
++      }
+       ret = unreserve_bo_and_vms(&ctx, false, false);
+@@ -2037,6 +2038,23 @@ int amdgpu_amdkfd_gpuvm_map_memory_to_gpu(
+       return ret;
+ }
++void amdgpu_amdkfd_gpuvm_dmaunmap_mem(struct kgd_mem *mem, void *drm_priv)
++{
++      struct kfd_mem_attachment *entry;
++      struct amdgpu_vm *vm;
++
++      vm = drm_priv_to_vm(drm_priv);
++
++      mutex_lock(&mem->lock);
++
++      list_for_each_entry(entry, &mem->attachments, list) {
++              if (entry->bo_va->base.vm == vm)
++                      kfd_mem_dmaunmap_attachment(mem, entry);
++      }
++
++      mutex_unlock(&mem->lock);
++}
++
+ int amdgpu_amdkfd_gpuvm_unmap_memory_from_gpu(
+               struct amdgpu_device *adev, struct kgd_mem *mem, void *drm_priv)
+ {
+diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_chardev.c b/drivers/gpu/drm/amd/amdkfd/kfd_chardev.c
+index d33ba4fe9ad5b..045280c2b607c 100644
+--- a/drivers/gpu/drm/amd/amdkfd/kfd_chardev.c
++++ b/drivers/gpu/drm/amd/amdkfd/kfd_chardev.c
+@@ -1432,17 +1432,21 @@ static int kfd_ioctl_unmap_memory_from_gpu(struct file *filep,
+                       goto sync_memory_failed;
+               }
+       }
+-      mutex_unlock(&p->mutex);
+-      if (flush_tlb) {
+-              /* Flush TLBs after waiting for the page table updates to complete */
+-              for (i = 0; i < args->n_devices; i++) {
+-                      peer_pdd = kfd_process_device_data_by_id(p, devices_arr[i]);
+-                      if (WARN_ON_ONCE(!peer_pdd))
+-                              continue;
++      /* Flush TLBs after waiting for the page table updates to complete */
++      for (i = 0; i < args->n_devices; i++) {
++              peer_pdd = kfd_process_device_data_by_id(p, devices_arr[i]);
++              if (WARN_ON_ONCE(!peer_pdd))
++                      continue;
++              if (flush_tlb)
+                       kfd_flush_tlb(peer_pdd, TLB_FLUSH_HEAVYWEIGHT);
+-              }
++
++              /* Remove dma mapping after tlb flush to avoid IO_PAGE_FAULT */
++              amdgpu_amdkfd_gpuvm_dmaunmap_mem(mem, peer_pdd->drm_priv);
+       }
++
++      mutex_unlock(&p->mutex);
++
+       kfree(devices_arr);
+       return 0;
+-- 
+2.43.0
+
diff --git a/queue-6.6/drm-bridge-tc358768-attempt-to-fix-dsi-horizontal-ti.patch b/queue-6.6/drm-bridge-tc358768-attempt-to-fix-dsi-horizontal-ti.patch
new file mode 100644 (file)
index 0000000..ba1e674
--- /dev/null
@@ -0,0 +1,346 @@
+From 9ae2e4069249a445ae063d1fb32017d9331fd747 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 6 Sep 2023 09:50:59 +0300
+Subject: drm/bridge: tc358768: Attempt to fix DSI horizontal timings
+
+From: Tomi Valkeinen <tomi.valkeinen@ideasonboard.com>
+
+[ Upstream commit 9fc75c40faa29df14ba16066be6bdfaea9f39ce4 ]
+
+The DSI horizontal timing calculations done by the driver seem to often
+lead to underflows or overflows, depending on the videomode.
+
+There are two main things the current driver doesn't seem to get right:
+DSI HSW and HFP, and VSDly. However, even following Toshiba's
+documentation it seems we don't always get a working display.
+
+This patch attempts to fix the horizontal timings for DSI event mode, and
+on a system with a DSI->HDMI encoder, a lot of standard HDMI modes now
+seem to work. The work relies on Toshiba's documentation, but also quite
+a bit on empirical testing.
+
+This also adds timing related debug prints to make it easier to improve
+on this later.
+
+The DSI pulse mode has only been tested with a fixed-resolution panel,
+which limits the testing of different modes on DSI pulse mode. However,
+as the VSDly calculation also affects pulse mode, so this might cause a
+regression.
+
+Reviewed-by: Peter Ujfalusi <peter.ujfalusi@gmail.com>
+Tested-by: Marcel Ziswiler <marcel.ziswiler@toradex.com>
+Tested-by: Maxim Schwalm <maxim.schwalm@gmail.com> # Asus TF700T
+Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ideasonboard.com>
+Signed-off-by: Robert Foss <rfoss@kernel.org>
+Link: https://patchwork.freedesktop.org/patch/msgid/20230906-tc358768-v4-12-31725f008a50@ideasonboard.com
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/gpu/drm/bridge/tc358768.c | 213 ++++++++++++++++++++++++++----
+ 1 file changed, 185 insertions(+), 28 deletions(-)
+
+diff --git a/drivers/gpu/drm/bridge/tc358768.c b/drivers/gpu/drm/bridge/tc358768.c
+index 6eed5c4232956..c72d5fbbb0ec4 100644
+--- a/drivers/gpu/drm/bridge/tc358768.c
++++ b/drivers/gpu/drm/bridge/tc358768.c
+@@ -9,6 +9,7 @@
+ #include <linux/gpio/consumer.h>
+ #include <linux/i2c.h>
+ #include <linux/kernel.h>
++#include <linux/math64.h>
+ #include <linux/media-bus-format.h>
+ #include <linux/minmax.h>
+ #include <linux/module.h>
+@@ -157,6 +158,7 @@ struct tc358768_priv {
+       u32 frs;        /* PLL Freqency range for HSCK (post divider) */
+       u32 dsiclk;     /* pll_clk / 2 */
++      u32 pclk;       /* incoming pclk rate */
+ };
+ static inline struct tc358768_priv *dsi_host_to_tc358768(struct mipi_dsi_host
+@@ -380,6 +382,7 @@ static int tc358768_calc_pll(struct tc358768_priv *priv,
+       priv->prd = best_prd;
+       priv->frs = frs;
+       priv->dsiclk = best_pll / 2;
++      priv->pclk = mode->clock * 1000;
+       return 0;
+ }
+@@ -638,6 +641,28 @@ static u32 tc358768_ps_to_ns(u32 ps)
+       return ps / 1000;
+ }
++static u32 tc358768_dpi_to_ns(u32 val, u32 pclk)
++{
++      return (u32)div_u64((u64)val * NANO, pclk);
++}
++
++/* Convert value in DPI pixel clock units to DSI byte count */
++static u32 tc358768_dpi_to_dsi_bytes(struct tc358768_priv *priv, u32 val)
++{
++      u64 m = (u64)val * priv->dsiclk / 4 * priv->dsi_lanes;
++      u64 n = priv->pclk;
++
++      return (u32)div_u64(m + n - 1, n);
++}
++
++static u32 tc358768_dsi_bytes_to_ns(struct tc358768_priv *priv, u32 val)
++{
++      u64 m = (u64)val * NANO;
++      u64 n = priv->dsiclk / 4 * priv->dsi_lanes;
++
++      return (u32)div_u64(m, n);
++}
++
+ static void tc358768_bridge_pre_enable(struct drm_bridge *bridge)
+ {
+       struct tc358768_priv *priv = bridge_to_tc358768(bridge);
+@@ -647,11 +672,19 @@ static void tc358768_bridge_pre_enable(struct drm_bridge *bridge)
+       s32 raw_val;
+       const struct drm_display_mode *mode;
+       u32 hsbyteclk_ps, dsiclk_ps, ui_ps;
+-      u32 dsiclk, hsbyteclk, video_start;
+-      const u32 internal_delay = 40;
++      u32 dsiclk, hsbyteclk;
+       int ret, i;
+       struct videomode vm;
+       struct device *dev = priv->dev;
++      /* In pixelclock units */
++      u32 dpi_htot, dpi_data_start;
++      /* In byte units */
++      u32 dsi_dpi_htot, dsi_dpi_data_start;
++      u32 dsi_hsw, dsi_hbp, dsi_hact, dsi_hfp;
++      const u32 dsi_hss = 4; /* HSS is a short packet (4 bytes) */
++      /* In hsbyteclk units */
++      u32 dsi_vsdly;
++      const u32 internal_dly = 40;
+       if (mode_flags & MIPI_DSI_CLOCK_NON_CONTINUOUS) {
+               dev_warn_once(dev, "Non-continuous mode unimplemented, falling back to continuous\n");
+@@ -686,27 +719,23 @@ static void tc358768_bridge_pre_enable(struct drm_bridge *bridge)
+       case MIPI_DSI_FMT_RGB888:
+               val |= (0x3 << 4);
+               hact = vm.hactive * 3;
+-              video_start = (vm.hsync_len + vm.hback_porch) * 3;
+               data_type = MIPI_DSI_PACKED_PIXEL_STREAM_24;
+               break;
+       case MIPI_DSI_FMT_RGB666:
+               val |= (0x4 << 4);
+               hact = vm.hactive * 3;
+-              video_start = (vm.hsync_len + vm.hback_porch) * 3;
+               data_type = MIPI_DSI_PACKED_PIXEL_STREAM_18;
+               break;
+       case MIPI_DSI_FMT_RGB666_PACKED:
+               val |= (0x4 << 4) | BIT(3);
+               hact = vm.hactive * 18 / 8;
+-              video_start = (vm.hsync_len + vm.hback_porch) * 18 / 8;
+               data_type = MIPI_DSI_PIXEL_STREAM_3BYTE_18;
+               break;
+       case MIPI_DSI_FMT_RGB565:
+               val |= (0x5 << 4);
+               hact = vm.hactive * 2;
+-              video_start = (vm.hsync_len + vm.hback_porch) * 2;
+               data_type = MIPI_DSI_PACKED_PIXEL_STREAM_16;
+               break;
+       default:
+@@ -716,9 +745,152 @@ static void tc358768_bridge_pre_enable(struct drm_bridge *bridge)
+               return;
+       }
++      /*
++       * There are three important things to make TC358768 work correctly,
++       * which are not trivial to manage:
++       *
++       * 1. Keep the DPI line-time and the DSI line-time as close to each
++       *    other as possible.
++       * 2. TC358768 goes to LP mode after each line's active area. The DSI
++       *    HFP period has to be long enough for entering and exiting LP mode.
++       *    But it is not clear how to calculate this.
++       * 3. VSDly (video start delay) has to be long enough to ensure that the
++       *    DSI TX does not start transmitting until we have started receiving
++       *    pixel data from the DPI input. It is not clear how to calculate
++       *    this either.
++       */
++
++      dpi_htot = vm.hactive + vm.hfront_porch + vm.hsync_len + vm.hback_porch;
++      dpi_data_start = vm.hsync_len + vm.hback_porch;
++
++      dev_dbg(dev, "dpi horiz timing (pclk): %u + %u + %u + %u = %u\n",
++              vm.hsync_len, vm.hback_porch, vm.hactive, vm.hfront_porch,
++              dpi_htot);
++
++      dev_dbg(dev, "dpi horiz timing (ns): %u + %u + %u + %u = %u\n",
++              tc358768_dpi_to_ns(vm.hsync_len, vm.pixelclock),
++              tc358768_dpi_to_ns(vm.hback_porch, vm.pixelclock),
++              tc358768_dpi_to_ns(vm.hactive, vm.pixelclock),
++              tc358768_dpi_to_ns(vm.hfront_porch, vm.pixelclock),
++              tc358768_dpi_to_ns(dpi_htot, vm.pixelclock));
++
++      dev_dbg(dev, "dpi data start (ns): %u + %u = %u\n",
++              tc358768_dpi_to_ns(vm.hsync_len, vm.pixelclock),
++              tc358768_dpi_to_ns(vm.hback_porch, vm.pixelclock),
++              tc358768_dpi_to_ns(dpi_data_start, vm.pixelclock));
++
++      dsi_dpi_htot = tc358768_dpi_to_dsi_bytes(priv, dpi_htot);
++      dsi_dpi_data_start = tc358768_dpi_to_dsi_bytes(priv, dpi_data_start);
++
++      if (dsi_dev->mode_flags & MIPI_DSI_MODE_VIDEO_SYNC_PULSE) {
++              dsi_hsw = tc358768_dpi_to_dsi_bytes(priv, vm.hsync_len);
++              dsi_hbp = tc358768_dpi_to_dsi_bytes(priv, vm.hback_porch);
++      } else {
++              /* HBP is included in HSW in event mode */
++              dsi_hbp = 0;
++              dsi_hsw = tc358768_dpi_to_dsi_bytes(priv,
++                                                  vm.hsync_len +
++                                                  vm.hback_porch);
++
++              /*
++               * The pixel packet includes the actual pixel data, and:
++               * DSI packet header = 4 bytes
++               * DCS code = 1 byte
++               * DSI packet footer = 2 bytes
++               */
++              dsi_hact = hact + 4 + 1 + 2;
++
++              dsi_hfp = dsi_dpi_htot - dsi_hact - dsi_hsw - dsi_hss;
++
++              /*
++               * Here we should check if HFP is long enough for entering LP
++               * and exiting LP, but it's not clear how to calculate that.
++               * Instead, this is a naive algorithm that just adjusts the HFP
++               * and HSW so that HFP is (at least) roughly 2/3 of the total
++               * blanking time.
++               */
++              if (dsi_hfp < (dsi_hfp + dsi_hsw + dsi_hss) * 2 / 3) {
++                      u32 old_hfp = dsi_hfp;
++                      u32 old_hsw = dsi_hsw;
++                      u32 tot = dsi_hfp + dsi_hsw + dsi_hss;
++
++                      dsi_hsw = tot / 3;
++
++                      /*
++                       * Seems like sometimes HSW has to be divisible by num-lanes, but
++                       * not always...
++                       */
++                      dsi_hsw = roundup(dsi_hsw, priv->dsi_lanes);
++
++                      dsi_hfp = dsi_dpi_htot - dsi_hact - dsi_hsw - dsi_hss;
++
++                      dev_dbg(dev,
++                              "hfp too short, adjusting dsi hfp and dsi hsw from %u, %u to %u, %u\n",
++                              old_hfp, old_hsw, dsi_hfp, dsi_hsw);
++              }
++
++              dev_dbg(dev,
++                      "dsi horiz timing (bytes): %u, %u + %u + %u + %u = %u\n",
++                      dsi_hss, dsi_hsw, dsi_hbp, dsi_hact, dsi_hfp,
++                      dsi_hss + dsi_hsw + dsi_hbp + dsi_hact + dsi_hfp);
++
++              dev_dbg(dev, "dsi horiz timing (ns): %u + %u + %u + %u + %u = %u\n",
++                      tc358768_dsi_bytes_to_ns(priv, dsi_hss),
++                      tc358768_dsi_bytes_to_ns(priv, dsi_hsw),
++                      tc358768_dsi_bytes_to_ns(priv, dsi_hbp),
++                      tc358768_dsi_bytes_to_ns(priv, dsi_hact),
++                      tc358768_dsi_bytes_to_ns(priv, dsi_hfp),
++                      tc358768_dsi_bytes_to_ns(priv, dsi_hss + dsi_hsw +
++                                               dsi_hbp + dsi_hact + dsi_hfp));
++      }
++
++      /* VSDly calculation */
++
++      /* Start with the HW internal delay */
++      dsi_vsdly = internal_dly;
++
++      /* Convert to byte units as the other variables are in byte units */
++      dsi_vsdly *= priv->dsi_lanes;
++
++      /* Do we need more delay, in addition to the internal? */
++      if (dsi_dpi_data_start > dsi_vsdly + dsi_hss + dsi_hsw + dsi_hbp) {
++              dsi_vsdly = dsi_dpi_data_start - dsi_hss - dsi_hsw - dsi_hbp;
++              dsi_vsdly = roundup(dsi_vsdly, priv->dsi_lanes);
++      }
++
++      dev_dbg(dev, "dsi data start (bytes) %u + %u + %u + %u = %u\n",
++              dsi_vsdly, dsi_hss, dsi_hsw, dsi_hbp,
++              dsi_vsdly + dsi_hss + dsi_hsw + dsi_hbp);
++
++      dev_dbg(dev, "dsi data start (ns) %u + %u + %u + %u = %u\n",
++              tc358768_dsi_bytes_to_ns(priv, dsi_vsdly),
++              tc358768_dsi_bytes_to_ns(priv, dsi_hss),
++              tc358768_dsi_bytes_to_ns(priv, dsi_hsw),
++              tc358768_dsi_bytes_to_ns(priv, dsi_hbp),
++              tc358768_dsi_bytes_to_ns(priv, dsi_vsdly + dsi_hss + dsi_hsw + dsi_hbp));
++
++      /* Convert back to hsbyteclk */
++      dsi_vsdly /= priv->dsi_lanes;
++
++      /*
++       * The docs say that there is an internal delay of 40 cycles.
++       * However, we get underflows if we follow that rule. If we
++       * instead ignore the internal delay, things work. So either
++       * the docs are wrong or the calculations are wrong.
++       *
++       * As a temporary fix, add the internal delay here, to counter
++       * the subtraction when writing the register.
++       */
++      dsi_vsdly += internal_dly;
++
++      /* Clamp to the register max */
++      if (dsi_vsdly - internal_dly > 0x3ff) {
++              dev_warn(dev, "VSDly too high, underflows likely\n");
++              dsi_vsdly = 0x3ff + internal_dly;
++      }
++
+       /* VSDly[9:0] */
+-      video_start = max(video_start, internal_delay + 1) - internal_delay;
+-      tc358768_write(priv, TC358768_VSDLY, video_start);
++      tc358768_write(priv, TC358768_VSDLY, dsi_vsdly - internal_dly);
+       tc358768_write(priv, TC358768_DATAFMT, val);
+       tc358768_write(priv, TC358768_DSITX_DT, data_type);
+@@ -826,18 +998,6 @@ static void tc358768_bridge_pre_enable(struct drm_bridge *bridge)
+               /* vbp */
+               tc358768_write(priv, TC358768_DSI_VBPR, vm.vback_porch);
+-
+-              /* hsw * byteclk * ndl / pclk */
+-              val = (u32)div_u64(vm.hsync_len *
+-                                 (u64)hsbyteclk * priv->dsi_lanes,
+-                                 vm.pixelclock);
+-              tc358768_write(priv, TC358768_DSI_HSW, val);
+-
+-              /* hbp * byteclk * ndl / pclk */
+-              val = (u32)div_u64(vm.hback_porch *
+-                                 (u64)hsbyteclk * priv->dsi_lanes,
+-                                 vm.pixelclock);
+-              tc358768_write(priv, TC358768_DSI_HBPR, val);
+       } else {
+               /* Set event mode */
+               tc358768_write(priv, TC358768_DSI_EVENT, 1);
+@@ -851,16 +1011,13 @@ static void tc358768_bridge_pre_enable(struct drm_bridge *bridge)
+               /* vbp (not used in event mode) */
+               tc358768_write(priv, TC358768_DSI_VBPR, 0);
++      }
+-              /* (hsw + hbp) * byteclk * ndl / pclk */
+-              val = (u32)div_u64((vm.hsync_len + vm.hback_porch) *
+-                                 (u64)hsbyteclk * priv->dsi_lanes,
+-                                 vm.pixelclock);
+-              tc358768_write(priv, TC358768_DSI_HSW, val);
++      /* hsw (bytes) */
++      tc358768_write(priv, TC358768_DSI_HSW, dsi_hsw);
+-              /* hbp (not used in event mode) */
+-              tc358768_write(priv, TC358768_DSI_HBPR, 0);
+-      }
++      /* hbp (bytes) */
++      tc358768_write(priv, TC358768_DSI_HBPR, dsi_hbp);
+       /* hact (bytes) */
+       tc358768_write(priv, TC358768_DSI_HACT, hact);
+-- 
+2.43.0
+
diff --git a/queue-6.6/drm-tegra-zero-initialize-iosys_map.patch b/queue-6.6/drm-tegra-zero-initialize-iosys_map.patch
new file mode 100644 (file)
index 0000000..e4c6e02
--- /dev/null
@@ -0,0 +1,37 @@
+From ba8c441f159b8f1daa587874b95942d5dd3ce016 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 1 Sep 2023 14:59:10 +0300
+Subject: drm/tegra: Zero-initialize iosys_map
+
+From: Mikko Perttunen <mperttunen@nvidia.com>
+
+[ Upstream commit 3868ff006b572cf501a3327832d36c64a9eca86a ]
+
+UBSAN reports an invalid load for bool, as the iosys_map is read
+later without being initialized. Zero-initialize it to avoid this.
+
+Reported-by: Ashish Mhetre <amhetre@nvidia.com>
+Signed-off-by: Mikko Perttunen <mperttunen@nvidia.com>
+Signed-off-by: Thierry Reding <treding@nvidia.com>
+Link: https://patchwork.freedesktop.org/patch/msgid/20230901115910.701518-2-cyndis@kapsi.fi
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/gpu/drm/tegra/gem.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/drivers/gpu/drm/tegra/gem.c b/drivers/gpu/drm/tegra/gem.c
+index a4023163493dc..a825fbbc01af6 100644
+--- a/drivers/gpu/drm/tegra/gem.c
++++ b/drivers/gpu/drm/tegra/gem.c
+@@ -177,7 +177,7 @@ static void tegra_bo_unpin(struct host1x_bo_mapping *map)
+ static void *tegra_bo_mmap(struct host1x_bo *bo)
+ {
+       struct tegra_bo *obj = host1x_to_tegra_bo(bo);
+-      struct iosys_map map;
++      struct iosys_map map = { 0 };
+       int ret;
+       if (obj->vaddr) {
+-- 
+2.43.0
+
diff --git a/queue-6.6/gfs2-setattr_chown-add-missing-initialization.patch b/queue-6.6/gfs2-setattr_chown-add-missing-initialization.patch
new file mode 100644 (file)
index 0000000..42fd479
--- /dev/null
@@ -0,0 +1,34 @@
+From 42923e004fa4cc65026699f747ff2e03e0a3a5c9 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sat, 21 Oct 2023 20:51:13 +0200
+Subject: gfs2: setattr_chown: Add missing initialization
+
+From: Andreas Gruenbacher <agruenba@redhat.com>
+
+[ Upstream commit 2d8d7990619878a848b1d916c2f936d3012ee17d ]
+
+Add a missing initialization of variable ap in setattr_chown().
+Without, chown() may be able to bypass quotas.
+
+Signed-off-by: Andreas Gruenbacher <agruenba@redhat.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ fs/gfs2/inode.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/fs/gfs2/inode.c b/fs/gfs2/inode.c
+index 3de0d8ab42eaf..29085643ad104 100644
+--- a/fs/gfs2/inode.c
++++ b/fs/gfs2/inode.c
+@@ -1929,7 +1929,7 @@ static int setattr_chown(struct inode *inode, struct iattr *attr)
+       kuid_t ouid, nuid;
+       kgid_t ogid, ngid;
+       int error;
+-      struct gfs2_alloc_parms ap;
++      struct gfs2_alloc_parms ap = {};
+       ouid = inode->i_uid;
+       ogid = inode->i_gid;
+-- 
+2.43.0
+
diff --git a/queue-6.6/hwmon-ltc2992-avoid-division-by-zero.patch b/queue-6.6/hwmon-ltc2992-avoid-division-by-zero.patch
new file mode 100644 (file)
index 0000000..06ea81a
--- /dev/null
@@ -0,0 +1,42 @@
+From ce1be53347f679a91d3b7ef97206d1ad20c57118 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 11 Oct 2023 16:57:53 +0300
+Subject: hwmon: (ltc2992) Avoid division by zero
+
+From: Antoniu Miclaus <antoniu.miclaus@analog.com>
+
+[ Upstream commit 10b02902048737f376104bc69e5212466e65a542 ]
+
+Do not allow setting shunt resistor to 0. This results in a division by
+zero when performing current value computations based on input voltages
+and connected resistor values.
+
+Signed-off-by: Antoniu Miclaus <antoniu.miclaus@analog.com>
+Link: https://lore.kernel.org/r/20231011135754.13508-1-antoniu.miclaus@analog.com
+Signed-off-by: Guenter Roeck <linux@roeck-us.net>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/hwmon/ltc2992.c | 6 +++++-
+ 1 file changed, 5 insertions(+), 1 deletion(-)
+
+diff --git a/drivers/hwmon/ltc2992.c b/drivers/hwmon/ltc2992.c
+index 589bcd07ce7f7..001799bc28ed6 100644
+--- a/drivers/hwmon/ltc2992.c
++++ b/drivers/hwmon/ltc2992.c
+@@ -875,8 +875,12 @@ static int ltc2992_parse_dt(struct ltc2992_state *st)
+               }
+               ret = fwnode_property_read_u32(child, "shunt-resistor-micro-ohms", &val);
+-              if (!ret)
++              if (!ret) {
++                      if (!val)
++                              return dev_err_probe(&st->client->dev, -EINVAL,
++                                                   "shunt resistor value cannot be zero\n");
+                       st->r_sense_uohm[addr] = val;
++              }
+       }
+       return 0;
+-- 
+2.43.0
+
diff --git a/queue-6.6/i2c-riic-avoid-potential-division-by-zero.patch b/queue-6.6/i2c-riic-avoid-potential-division-by-zero.patch
new file mode 100644 (file)
index 0000000..e0ac9e9
--- /dev/null
@@ -0,0 +1,35 @@
+From 89165ced7fa0e2d166cbee5eb04c42dbf202dd17 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 6 Sep 2023 22:00:23 +0200
+Subject: i2c: riic: avoid potential division by zero
+
+From: Wolfram Sang <wsa+renesas@sang-engineering.com>
+
+[ Upstream commit 7890fce6201aed46d3576e3d641f9ee5c1f0e16f ]
+
+Value comes from DT, so it could be 0. Unlikely, but could be.
+
+Signed-off-by: Wolfram Sang <wsa+renesas@sang-engineering.com>
+Reviewed-by: Geert Uytterhoeven <geert+renesas@glider.be>
+Signed-off-by: Wolfram Sang <wsa@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/i2c/busses/i2c-riic.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/drivers/i2c/busses/i2c-riic.c b/drivers/i2c/busses/i2c-riic.c
+index f0ee8871d5ae1..e43ff483c56ec 100644
+--- a/drivers/i2c/busses/i2c-riic.c
++++ b/drivers/i2c/busses/i2c-riic.c
+@@ -313,7 +313,7 @@ static int riic_init_hw(struct riic_dev *riic, struct i2c_timings *t)
+        * frequency with only 62 clock ticks max (31 high, 31 low).
+        * Aim for a duty of 60% LOW, 40% HIGH.
+        */
+-      total_ticks = DIV_ROUND_UP(rate, t->bus_freq_hz);
++      total_ticks = DIV_ROUND_UP(rate, t->bus_freq_hz ?: 1);
+       for (cks = 0; cks < 7; cks++) {
+               /*
+-- 
+2.43.0
+
diff --git a/queue-6.6/i3c-mipi-i3c-hci-do-not-unmap-region-not-mapped-for-.patch b/queue-6.6/i3c-mipi-i3c-hci-do-not-unmap-region-not-mapped-for-.patch
new file mode 100644 (file)
index 0000000..bc5a8ab
--- /dev/null
@@ -0,0 +1,41 @@
+From 7568ceee6e3ed471a5f5ca7e486c8cf35aea26d7 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 21 Sep 2023 08:57:01 +0300
+Subject: i3c: mipi-i3c-hci: Do not unmap region not mapped for transfer
+
+From: Jarkko Nikula <jarkko.nikula@linux.intel.com>
+
+[ Upstream commit b8806e0c939f168237593af0056c309bf31022b0 ]
+
+Fix following warning (with CONFIG_DMA_API_DEBUG) which happens with a
+transfer without a data buffer.
+
+       DMA-API: i3c mipi-i3c-hci.0: device driver tries to free DMA memory it has not allocated [device address=0x0000000000000000] [size=0 bytes]
+
+For those transfers the hci_dma_queue_xfer() doesn't create a mapping and
+the DMA address pointer xfer->data_dma is not set.
+
+Signed-off-by: Jarkko Nikula <jarkko.nikula@linux.intel.com>
+Link: https://lore.kernel.org/r/20230921055704.1087277-10-jarkko.nikula@linux.intel.com
+Signed-off-by: Alexandre Belloni <alexandre.belloni@bootlin.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/i3c/master/mipi-i3c-hci/dma.c | 2 ++
+ 1 file changed, 2 insertions(+)
+
+diff --git a/drivers/i3c/master/mipi-i3c-hci/dma.c b/drivers/i3c/master/mipi-i3c-hci/dma.c
+index a28ff177022ce..337c95d43f3f6 100644
+--- a/drivers/i3c/master/mipi-i3c-hci/dma.c
++++ b/drivers/i3c/master/mipi-i3c-hci/dma.c
+@@ -345,6 +345,8 @@ static void hci_dma_unmap_xfer(struct i3c_hci *hci,
+       for (i = 0; i < n; i++) {
+               xfer = xfer_list + i;
++              if (!xfer->data)
++                      continue;
+               dma_unmap_single(&hci->master.dev,
+                                xfer->data_dma, xfer->data_len,
+                                xfer->rnw ? DMA_FROM_DEVICE : DMA_TO_DEVICE);
+-- 
+2.43.0
+
diff --git a/queue-6.6/i3c-mipi-i3c-hci-remove-bug-when-ring-abort-request-.patch b/queue-6.6/i3c-mipi-i3c-hci-remove-bug-when-ring-abort-request-.patch
new file mode 100644 (file)
index 0000000..fa5d0e6
--- /dev/null
@@ -0,0 +1,42 @@
+From 7be7db659f97382df55bc0d5c74deb1cc46e8dc9 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 21 Sep 2023 08:56:57 +0300
+Subject: i3c: mipi-i3c-hci: Remove BUG() when Ring Abort request times out
+
+From: Jarkko Nikula <jarkko.nikula@linux.intel.com>
+
+[ Upstream commit 361acacaf7c706223968c8186f0d3b6e214e7403 ]
+
+Ring Abort request will timeout in case there is an error in the Host
+Controller interrupt delivery or Ring Header configuration. Using BUG()
+makes hard to debug those cases.
+
+Make it less severe and turn BUG() to WARN_ON().
+
+Signed-off-by: Jarkko Nikula <jarkko.nikula@linux.intel.com>
+Link: https://lore.kernel.org/r/20230921055704.1087277-6-jarkko.nikula@linux.intel.com
+Signed-off-by: Alexandre Belloni <alexandre.belloni@bootlin.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/i3c/master/mipi-i3c-hci/dma.c | 3 +--
+ 1 file changed, 1 insertion(+), 2 deletions(-)
+
+diff --git a/drivers/i3c/master/mipi-i3c-hci/dma.c b/drivers/i3c/master/mipi-i3c-hci/dma.c
+index 71b5dbe45c45c..a28ff177022ce 100644
+--- a/drivers/i3c/master/mipi-i3c-hci/dma.c
++++ b/drivers/i3c/master/mipi-i3c-hci/dma.c
+@@ -450,10 +450,9 @@ static bool hci_dma_dequeue_xfer(struct i3c_hci *hci,
+               /*
+                * We're deep in it if ever this condition is ever met.
+                * Hardware might still be writing to memory, etc.
+-               * Better suspend the world than risking silent corruption.
+                */
+               dev_crit(&hci->master.dev, "unable to abort the ring\n");
+-              BUG();
++              WARN_ON(1);
+       }
+       for (i = 0; i < n; i++) {
+-- 
+2.43.0
+
diff --git a/queue-6.6/ib-hfi1-fix-potential-deadlock-on-irq_src_lock-and-d.patch b/queue-6.6/ib-hfi1-fix-potential-deadlock-on-irq_src_lock-and-d.patch
new file mode 100644 (file)
index 0000000..e0be4c5
--- /dev/null
@@ -0,0 +1,77 @@
+From b389d00beaeaddb3b217009f59d71a2e63880694 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 26 Sep 2023 10:11:16 +0000
+Subject: IB/hfi1: Fix potential deadlock on &irq_src_lock and &dd->uctxt_lock
+
+From: Chengfeng Ye <dg573847474@gmail.com>
+
+[ Upstream commit 2f19c4b8395ccb6eb25ccafee883c8cfbe3fc193 ]
+
+handle_receive_interrupt_napi_sp() running inside interrupt handler
+could introduce inverse lock ordering between &dd->irq_src_lock
+and &dd->uctxt_lock, if read_mod_write() is preempted by the isr.
+
+          [CPU0]                                        |          [CPU1]
+hfi1_ipoib_dev_open()                                   |
+--> hfi1_netdev_enable_queues()                         |
+--> enable_queues(rx)                                   |
+--> hfi1_rcvctrl()                                      |
+--> set_intr_bits()                                     |
+--> read_mod_write()                                    |
+--> spin_lock(&dd->irq_src_lock)                        |
+                                                        | hfi1_poll()
+                                                        | --> poll_next()
+                                                        | --> spin_lock_irq(&dd->uctxt_lock)
+                                                        |
+                                                        | --> hfi1_rcvctrl()
+                                                        | --> set_intr_bits()
+                                                        | --> read_mod_write()
+                                                        | --> spin_lock(&dd->irq_src_lock)
+<interrupt>                                             |
+   --> handle_receive_interrupt_napi_sp()               |
+   --> set_all_fastpath()                               |
+   --> hfi1_rcd_get_by_index()                          |
+   --> spin_lock_irqsave(&dd->uctxt_lock)               |
+
+This flaw was found by an experimental static analysis tool I am
+developing for irq-related deadlock.
+
+To prevent the potential deadlock, the patch use spin_lock_irqsave()
+on &dd->irq_src_lock inside read_mod_write() to prevent the possible
+deadlock scenario.
+
+Signed-off-by: Chengfeng Ye <dg573847474@gmail.com>
+Link: https://lore.kernel.org/r/20230926101116.2797-1-dg573847474@gmail.com
+Acked-by: Dennis Dalessandro <dennis.dalessandro@cornelisnetworks.com>
+Signed-off-by: Leon Romanovsky <leon@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/infiniband/hw/hfi1/chip.c | 5 +++--
+ 1 file changed, 3 insertions(+), 2 deletions(-)
+
+diff --git a/drivers/infiniband/hw/hfi1/chip.c b/drivers/infiniband/hw/hfi1/chip.c
+index 0814291a04120..9b542f7c6c115 100644
+--- a/drivers/infiniband/hw/hfi1/chip.c
++++ b/drivers/infiniband/hw/hfi1/chip.c
+@@ -13185,15 +13185,16 @@ static void read_mod_write(struct hfi1_devdata *dd, u16 src, u64 bits,
+ {
+       u64 reg;
+       u16 idx = src / BITS_PER_REGISTER;
++      unsigned long flags;
+-      spin_lock(&dd->irq_src_lock);
++      spin_lock_irqsave(&dd->irq_src_lock, flags);
+       reg = read_csr(dd, CCE_INT_MASK + (8 * idx));
+       if (set)
+               reg |= bits;
+       else
+               reg &= ~bits;
+       write_csr(dd, CCE_INT_MASK + (8 * idx), reg);
+-      spin_unlock(&dd->irq_src_lock);
++      spin_unlock_irqrestore(&dd->irq_src_lock, flags);
+ }
+ /**
+-- 
+2.43.0
+
diff --git a/queue-6.6/iommu-arm-smmu-qcom-add-sdm670-mdss-compatible.patch b/queue-6.6/iommu-arm-smmu-qcom-add-sdm670-mdss-compatible.patch
new file mode 100644 (file)
index 0000000..9da574b
--- /dev/null
@@ -0,0 +1,38 @@
+From 68f06d213c2eba9d7962bca6f668c7025d1ecc86 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 25 Sep 2023 19:42:48 -0400
+Subject: iommu/arm-smmu-qcom: Add SDM670 MDSS compatible
+
+From: Richard Acayan <mailingradian@gmail.com>
+
+[ Upstream commit 270a1470408e44619a55be1079254bf2ba0567fb ]
+
+Add the compatible for the MDSS client on the Snapdragon 670 so it can
+be properly configured by the IOMMU driver.
+
+Otherwise, there is an unhandled context fault.
+
+Signed-off-by: Richard Acayan <mailingradian@gmail.com>
+Reviewed-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
+Link: https://lore.kernel.org/r/20230925234246.900351-3-mailingradian@gmail.com
+Signed-off-by: Will Deacon <will@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/iommu/arm/arm-smmu/arm-smmu-qcom.c | 1 +
+ 1 file changed, 1 insertion(+)
+
+diff --git a/drivers/iommu/arm/arm-smmu/arm-smmu-qcom.c b/drivers/iommu/arm/arm-smmu/arm-smmu-qcom.c
+index 40503376d80cc..6e6cb19c81f59 100644
+--- a/drivers/iommu/arm/arm-smmu/arm-smmu-qcom.c
++++ b/drivers/iommu/arm/arm-smmu/arm-smmu-qcom.c
+@@ -252,6 +252,7 @@ static const struct of_device_id qcom_smmu_client_of_match[] __maybe_unused = {
+       { .compatible = "qcom,sc7280-mss-pil" },
+       { .compatible = "qcom,sc8180x-mdss" },
+       { .compatible = "qcom,sc8280xp-mdss" },
++      { .compatible = "qcom,sdm670-mdss" },
+       { .compatible = "qcom,sdm845-mdss" },
+       { .compatible = "qcom,sdm845-mss-pil" },
+       { .compatible = "qcom,sm6350-mdss" },
+-- 
+2.43.0
+
diff --git a/queue-6.6/md-raid5-cache-use-read_once-write_once-for-conf-log.patch b/queue-6.6/md-raid5-cache-use-read_once-write_once-for-conf-log.patch
new file mode 100644 (file)
index 0000000..77e22a9
--- /dev/null
@@ -0,0 +1,226 @@
+From 4fcc59df505b3ffd57ad13df7abbc4f3439bf3fc Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 10 Oct 2023 23:19:41 +0800
+Subject: md/raid5-cache: use READ_ONCE/WRITE_ONCE for 'conf->log'
+
+From: Yu Kuai <yukuai3@huawei.com>
+
+[ Upstream commit 06a4d0d8c642b5ea654e832b74dca12965356da0 ]
+
+'conf->log' is set with 'reconfig_mutex' grabbed, however, readers are
+not procted, hence protect it with READ_ONCE/WRITE_ONCE to prevent
+reading abnormal values.
+
+Signed-off-by: Yu Kuai <yukuai3@huawei.com>
+Signed-off-by: Song Liu <song@kernel.org>
+Link: https://lore.kernel.org/r/20231010151958.145896-3-yukuai1@huaweicloud.com
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/md/raid5-cache.c | 47 +++++++++++++++++++++-------------------
+ 1 file changed, 25 insertions(+), 22 deletions(-)
+
+diff --git a/drivers/md/raid5-cache.c b/drivers/md/raid5-cache.c
+index 518b7cfa78b9d..889bba60d6ff7 100644
+--- a/drivers/md/raid5-cache.c
++++ b/drivers/md/raid5-cache.c
+@@ -327,8 +327,9 @@ void r5l_wake_reclaim(struct r5l_log *log, sector_t space);
+ void r5c_check_stripe_cache_usage(struct r5conf *conf)
+ {
+       int total_cached;
++      struct r5l_log *log = READ_ONCE(conf->log);
+-      if (!r5c_is_writeback(conf->log))
++      if (!r5c_is_writeback(log))
+               return;
+       total_cached = atomic_read(&conf->r5c_cached_partial_stripes) +
+@@ -344,7 +345,7 @@ void r5c_check_stripe_cache_usage(struct r5conf *conf)
+        */
+       if (total_cached > conf->min_nr_stripes * 1 / 2 ||
+           atomic_read(&conf->empty_inactive_list_nr) > 0)
+-              r5l_wake_reclaim(conf->log, 0);
++              r5l_wake_reclaim(log, 0);
+ }
+ /*
+@@ -353,7 +354,9 @@ void r5c_check_stripe_cache_usage(struct r5conf *conf)
+  */
+ void r5c_check_cached_full_stripe(struct r5conf *conf)
+ {
+-      if (!r5c_is_writeback(conf->log))
++      struct r5l_log *log = READ_ONCE(conf->log);
++
++      if (!r5c_is_writeback(log))
+               return;
+       /*
+@@ -363,7 +366,7 @@ void r5c_check_cached_full_stripe(struct r5conf *conf)
+       if (atomic_read(&conf->r5c_cached_full_stripes) >=
+           min(R5C_FULL_STRIPE_FLUSH_BATCH(conf),
+               conf->chunk_sectors >> RAID5_STRIPE_SHIFT(conf)))
+-              r5l_wake_reclaim(conf->log, 0);
++              r5l_wake_reclaim(log, 0);
+ }
+ /*
+@@ -396,7 +399,7 @@ void r5c_check_cached_full_stripe(struct r5conf *conf)
+  */
+ static sector_t r5c_log_required_to_flush_cache(struct r5conf *conf)
+ {
+-      struct r5l_log *log = conf->log;
++      struct r5l_log *log = READ_ONCE(conf->log);
+       if (!r5c_is_writeback(log))
+               return 0;
+@@ -449,7 +452,7 @@ static inline void r5c_update_log_state(struct r5l_log *log)
+ void r5c_make_stripe_write_out(struct stripe_head *sh)
+ {
+       struct r5conf *conf = sh->raid_conf;
+-      struct r5l_log *log = conf->log;
++      struct r5l_log *log = READ_ONCE(conf->log);
+       BUG_ON(!r5c_is_writeback(log));
+@@ -491,7 +494,7 @@ static void r5c_handle_parity_cached(struct stripe_head *sh)
+  */
+ static void r5c_finish_cache_stripe(struct stripe_head *sh)
+ {
+-      struct r5l_log *log = sh->raid_conf->log;
++      struct r5l_log *log = READ_ONCE(sh->raid_conf->log);
+       if (log->r5c_journal_mode == R5C_JOURNAL_MODE_WRITE_THROUGH) {
+               BUG_ON(test_bit(STRIPE_R5C_CACHING, &sh->state));
+@@ -692,7 +695,7 @@ static void r5c_disable_writeback_async(struct work_struct *work)
+       /* wait superblock change before suspend */
+       wait_event(mddev->sb_wait,
+-                 conf->log == NULL ||
++                 !READ_ONCE(conf->log) ||
+                  (!test_bit(MD_SB_CHANGE_PENDING, &mddev->sb_flags) &&
+                   (locked = mddev_trylock(mddev))));
+       if (locked) {
+@@ -1151,7 +1154,7 @@ static void r5l_run_no_space_stripes(struct r5l_log *log)
+ static sector_t r5c_calculate_new_cp(struct r5conf *conf)
+ {
+       struct stripe_head *sh;
+-      struct r5l_log *log = conf->log;
++      struct r5l_log *log = READ_ONCE(conf->log);
+       sector_t new_cp;
+       unsigned long flags;
+@@ -1159,12 +1162,12 @@ static sector_t r5c_calculate_new_cp(struct r5conf *conf)
+               return log->next_checkpoint;
+       spin_lock_irqsave(&log->stripe_in_journal_lock, flags);
+-      if (list_empty(&conf->log->stripe_in_journal_list)) {
++      if (list_empty(&log->stripe_in_journal_list)) {
+               /* all stripes flushed */
+               spin_unlock_irqrestore(&log->stripe_in_journal_lock, flags);
+               return log->next_checkpoint;
+       }
+-      sh = list_first_entry(&conf->log->stripe_in_journal_list,
++      sh = list_first_entry(&log->stripe_in_journal_list,
+                             struct stripe_head, r5c);
+       new_cp = sh->log_start;
+       spin_unlock_irqrestore(&log->stripe_in_journal_lock, flags);
+@@ -1399,7 +1402,7 @@ void r5c_flush_cache(struct r5conf *conf, int num)
+       struct stripe_head *sh, *next;
+       lockdep_assert_held(&conf->device_lock);
+-      if (!conf->log)
++      if (!READ_ONCE(conf->log))
+               return;
+       count = 0;
+@@ -1420,7 +1423,7 @@ void r5c_flush_cache(struct r5conf *conf, int num)
+ static void r5c_do_reclaim(struct r5conf *conf)
+ {
+-      struct r5l_log *log = conf->log;
++      struct r5l_log *log = READ_ONCE(conf->log);
+       struct stripe_head *sh;
+       int count = 0;
+       unsigned long flags;
+@@ -1549,7 +1552,7 @@ static void r5l_reclaim_thread(struct md_thread *thread)
+ {
+       struct mddev *mddev = thread->mddev;
+       struct r5conf *conf = mddev->private;
+-      struct r5l_log *log = conf->log;
++      struct r5l_log *log = READ_ONCE(conf->log);
+       if (!log)
+               return;
+@@ -1591,7 +1594,7 @@ void r5l_quiesce(struct r5l_log *log, int quiesce)
+ bool r5l_log_disk_error(struct r5conf *conf)
+ {
+-      struct r5l_log *log = conf->log;
++      struct r5l_log *log = READ_ONCE(conf->log);
+       /* don't allow write if journal disk is missing */
+       if (!log)
+@@ -2635,7 +2638,7 @@ int r5c_try_caching_write(struct r5conf *conf,
+                         struct stripe_head_state *s,
+                         int disks)
+ {
+-      struct r5l_log *log = conf->log;
++      struct r5l_log *log = READ_ONCE(conf->log);
+       int i;
+       struct r5dev *dev;
+       int to_cache = 0;
+@@ -2802,7 +2805,7 @@ void r5c_finish_stripe_write_out(struct r5conf *conf,
+                                struct stripe_head *sh,
+                                struct stripe_head_state *s)
+ {
+-      struct r5l_log *log = conf->log;
++      struct r5l_log *log = READ_ONCE(conf->log);
+       int i;
+       int do_wakeup = 0;
+       sector_t tree_index;
+@@ -2941,7 +2944,7 @@ int r5c_cache_data(struct r5l_log *log, struct stripe_head *sh)
+ /* check whether this big stripe is in write back cache. */
+ bool r5c_big_stripe_cached(struct r5conf *conf, sector_t sect)
+ {
+-      struct r5l_log *log = conf->log;
++      struct r5l_log *log = READ_ONCE(conf->log);
+       sector_t tree_index;
+       void *slot;
+@@ -3049,14 +3052,14 @@ int r5l_start(struct r5l_log *log)
+ void r5c_update_on_rdev_error(struct mddev *mddev, struct md_rdev *rdev)
+ {
+       struct r5conf *conf = mddev->private;
+-      struct r5l_log *log = conf->log;
++      struct r5l_log *log = READ_ONCE(conf->log);
+       if (!log)
+               return;
+       if ((raid5_calc_degraded(conf) > 0 ||
+            test_bit(Journal, &rdev->flags)) &&
+-          conf->log->r5c_journal_mode == R5C_JOURNAL_MODE_WRITE_BACK)
++          log->r5c_journal_mode == R5C_JOURNAL_MODE_WRITE_BACK)
+               schedule_work(&log->disable_writeback_work);
+ }
+@@ -3145,7 +3148,7 @@ int r5l_init_log(struct r5conf *conf, struct md_rdev *rdev)
+       spin_lock_init(&log->stripe_in_journal_lock);
+       atomic_set(&log->stripe_in_journal_count, 0);
+-      conf->log = log;
++      WRITE_ONCE(conf->log, log);
+       set_bit(MD_HAS_JOURNAL, &conf->mddev->flags);
+       return 0;
+@@ -3173,7 +3176,7 @@ void r5l_exit_log(struct r5conf *conf)
+        * 'reconfig_mutex' is held by caller, set 'confg->log' to NULL to
+        * ensure disable_writeback_work wakes up and exits.
+        */
+-      conf->log = NULL;
++      WRITE_ONCE(conf->log, NULL);
+       wake_up(&conf->mddev->sb_wait);
+       flush_work(&log->disable_writeback_work);
+-- 
+2.43.0
+
diff --git a/queue-6.6/media-qcom-venus-fix-incorrect-return-value.patch b/queue-6.6/media-qcom-venus-fix-incorrect-return-value.patch
new file mode 100644 (file)
index 0000000..fa6f5cf
--- /dev/null
@@ -0,0 +1,37 @@
+From 5e23129517dc614cffc71a6fbbd33e280d7adaee Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 6 Oct 2023 12:08:47 +0200
+Subject: media: qcom: venus: fix incorrect return value
+
+From: Hans Verkuil <hverkuil-cisco@xs4all.nl>
+
+[ Upstream commit 51b74c09ac8c5862007fc2bf0d465529d06dd446 ]
+
+'pd' can be NULL, and in that case it shouldn't be passed to
+PTR_ERR. Fixes a smatch warning:
+
+drivers/media/platform/qcom/venus/pm_helpers.c:873 vcodec_domains_get() warn: passing zero to 'PTR_ERR'
+
+Signed-off-by: Hans Verkuil <hverkuil-cisco@xs4all.nl>
+Reviewed-by: Bryan O'Donoghue <bryan.odonoghue@linaro.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/media/platform/qcom/venus/pm_helpers.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/drivers/media/platform/qcom/venus/pm_helpers.c b/drivers/media/platform/qcom/venus/pm_helpers.c
+index 48c9084bb4dba..a1b127caa90a7 100644
+--- a/drivers/media/platform/qcom/venus/pm_helpers.c
++++ b/drivers/media/platform/qcom/venus/pm_helpers.c
+@@ -870,7 +870,7 @@ static int vcodec_domains_get(struct venus_core *core)
+               pd = dev_pm_domain_attach_by_name(dev,
+                                                 res->vcodec_pmdomains[i]);
+               if (IS_ERR_OR_NULL(pd))
+-                      return PTR_ERR(pd) ? : -ENODATA;
++                      return pd ? PTR_ERR(pd) : -ENODATA;
+               core->pmdomains[i] = pd;
+       }
+-- 
+2.43.0
+
diff --git a/queue-6.6/media-radio-isa-use-dev_name-to-fill-in-bus_info.patch b/queue-6.6/media-radio-isa-use-dev_name-to-fill-in-bus_info.patch
new file mode 100644 (file)
index 0000000..ea54f84
--- /dev/null
@@ -0,0 +1,41 @@
+From 0a8068a4d3f1ac97b082dac9dc375bf83cb98034 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sat, 23 Sep 2023 17:21:04 +0200
+Subject: media: radio-isa: use dev_name to fill in bus_info
+
+From: Hans Verkuil <hverkuil-cisco@xs4all.nl>
+
+[ Upstream commit 8b7f3cf4eb9a95940eaabad3226caeaa0d9aa59d ]
+
+This fixes this warning:
+
+drivers/media/radio/radio-isa.c: In function 'radio_isa_querycap':
+drivers/media/radio/radio-isa.c:39:57: warning: '%s' directive output may be truncated writing up to 35 bytes into a region of size 28 [-Wformat-truncation=]
+   39 |         snprintf(v->bus_info, sizeof(v->bus_info), "ISA:%s", isa->v4l2_dev.name);
+      |                                                         ^~
+drivers/media/radio/radio-isa.c:39:9: note: 'snprintf' output between 5 and 40 bytes into a destination of size 32
+   39 |         snprintf(v->bus_info, sizeof(v->bus_info), "ISA:%s", isa->v4l2_dev.name);
+      |         ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Signed-off-by: Hans Verkuil <hverkuil-cisco@xs4all.nl>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/media/radio/radio-isa.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/drivers/media/radio/radio-isa.c b/drivers/media/radio/radio-isa.c
+index c591c0851fa28..ad49151f5ff09 100644
+--- a/drivers/media/radio/radio-isa.c
++++ b/drivers/media/radio/radio-isa.c
+@@ -36,7 +36,7 @@ static int radio_isa_querycap(struct file *file, void  *priv,
+       strscpy(v->driver, isa->drv->driver.driver.name, sizeof(v->driver));
+       strscpy(v->card, isa->drv->card, sizeof(v->card));
+-      snprintf(v->bus_info, sizeof(v->bus_info), "ISA:%s", isa->v4l2_dev.name);
++      snprintf(v->bus_info, sizeof(v->bus_info), "ISA:%s", dev_name(isa->v4l2_dev.dev));
+       return 0;
+ }
+-- 
+2.43.0
+
diff --git a/queue-6.6/media-s5p-mfc-fix-potential-deadlock-on-condlock.patch b/queue-6.6/media-s5p-mfc-fix-potential-deadlock-on-condlock.patch
new file mode 100644 (file)
index 0000000..edb42a9
--- /dev/null
@@ -0,0 +1,56 @@
+From 4b2d6a53539fc0b86694b474542230056cd74c5e Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 26 Sep 2023 10:53:30 +0000
+Subject: media: s5p-mfc: Fix potential deadlock on condlock
+
+From: Chengfeng Ye <dg573847474@gmail.com>
+
+[ Upstream commit 04d19e65137e3cd4a5004e624c85c762933d115c ]
+
+As &dev->condlock is acquired under irq context along the following
+call chain from s5p_mfc_irq(), other acquisition of the same lock
+inside process context or softirq context should disable irq avoid double
+lock. enc_post_frame_start() seems to be one such function that execute
+under process context or softirq context.
+
+<deadlock #1>
+
+enc_post_frame_start()
+--> clear_work_bit()
+--> spin_loc(&dev->condlock)
+<interrupt>
+   --> s5p_mfc_irq()
+   --> s5p_mfc_handle_frame()
+   --> clear_work_bit()
+   --> spin_lock(&dev->condlock)
+
+This flaw was found by an experimental static analysis tool I am
+developing for irq-related deadlock.
+
+To prevent the potential deadlock, the patch change clear_work_bit()
+inside enc_post_frame_start() to clear_work_bit_irqsave().
+
+Signed-off-by: Chengfeng Ye <dg573847474@gmail.com>
+Acked-by: Marek Szyprowski <m.szyprowski@samsung.com>
+Signed-off-by: Hans Verkuil <hverkuil-cisco@xs4all.nl>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/media/platform/samsung/s5p-mfc/s5p_mfc_enc.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/drivers/media/platform/samsung/s5p-mfc/s5p_mfc_enc.c b/drivers/media/platform/samsung/s5p-mfc/s5p_mfc_enc.c
+index f62703cebb77c..4b4c129c09e70 100644
+--- a/drivers/media/platform/samsung/s5p-mfc/s5p_mfc_enc.c
++++ b/drivers/media/platform/samsung/s5p-mfc/s5p_mfc_enc.c
+@@ -1297,7 +1297,7 @@ static int enc_post_frame_start(struct s5p_mfc_ctx *ctx)
+       if (ctx->state == MFCINST_FINISHING && ctx->ref_queue_cnt == 0)
+               src_ready = false;
+       if (!src_ready || ctx->dst_queue_cnt == 0)
+-              clear_work_bit(ctx);
++              clear_work_bit_irqsave(ctx);
+       return 0;
+ }
+-- 
+2.43.0
+
diff --git a/queue-6.6/net-ethernet-mtk_wed-check-update_wo_rx_stats-in-mtk.patch b/queue-6.6/net-ethernet-mtk_wed-check-update_wo_rx_stats-in-mtk.patch
new file mode 100644 (file)
index 0000000..1d60576
--- /dev/null
@@ -0,0 +1,39 @@
+From 99d35f460ba70bb0e59796712b3978ecab9a795a Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 12 Sep 2023 10:28:00 +0200
+Subject: net: ethernet: mtk_wed: check update_wo_rx_stats in
+ mtk_wed_update_rx_stats()
+
+From: Lorenzo Bianconi <lorenzo@kernel.org>
+
+[ Upstream commit 486e6ca6b48d68d7fefc99e15cc1865e2210d893 ]
+
+Check if update_wo_rx_stats function pointer is properly set in
+mtk_wed_update_rx_stats routine before accessing it.
+
+Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
+Reviewed-by: Simon Horman <horms@kernel.org>
+Link: https://lore.kernel.org/r/b0d233386e059bccb59f18f69afb79a7806e5ded.1694507226.git.lorenzo@kernel.org
+Signed-off-by: Paolo Abeni <pabeni@redhat.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/ethernet/mediatek/mtk_wed_mcu.c | 3 +++
+ 1 file changed, 3 insertions(+)
+
+diff --git a/drivers/net/ethernet/mediatek/mtk_wed_mcu.c b/drivers/net/ethernet/mediatek/mtk_wed_mcu.c
+index 071ed3dea860d..72bcdaed12a94 100644
+--- a/drivers/net/ethernet/mediatek/mtk_wed_mcu.c
++++ b/drivers/net/ethernet/mediatek/mtk_wed_mcu.c
+@@ -68,6 +68,9 @@ mtk_wed_update_rx_stats(struct mtk_wed_device *wed, struct sk_buff *skb)
+       struct mtk_wed_wo_rx_stats *stats;
+       int i;
++      if (!wed->wlan.update_wo_rx_stats)
++              return;
++
+       if (count * sizeof(*stats) > skb->len - sizeof(u32))
+               return;
+-- 
+2.43.0
+
diff --git a/queue-6.6/platform-x86-intel-ifs-validate-image-size.patch b/queue-6.6/platform-x86-intel-ifs-validate-image-size.patch
new file mode 100644 (file)
index 0000000..6f68c33
--- /dev/null
@@ -0,0 +1,57 @@
+From 16a87a359d58b5a898e493a11d831a488e1a65ee Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 5 Oct 2023 12:51:33 -0700
+Subject: platform/x86/intel/ifs: Validate image size
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Jithu Joseph <jithu.joseph@intel.com>
+
+[ Upstream commit 25a76dbb36dd58ad4df7f6a4dc43061a10b0d817 ]
+
+Perform additional validation prior to loading IFS image.
+
+Error out if the size of the file being loaded doesn't match the size
+specified in the header.
+
+Signed-off-by: Jithu Joseph <jithu.joseph@intel.com>
+Reviewed-by: Tony Luck <tony.luck@intel.com>
+Reviewed-by: Ilpo Järvinen <ilpo.jarvinen@linux.intel.com>
+Tested-by: Pengfei Xu <pengfei.xu@intel.com>
+Link: https://lore.kernel.org/r/20231005195137.3117166-6-jithu.joseph@intel.com
+Signed-off-by: Ilpo Järvinen <ilpo.jarvinen@linux.intel.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/platform/x86/intel/ifs/load.c | 8 ++++++++
+ 1 file changed, 8 insertions(+)
+
+diff --git a/drivers/platform/x86/intel/ifs/load.c b/drivers/platform/x86/intel/ifs/load.c
+index cefd0d886cfd4..ae52de138a6ea 100644
+--- a/drivers/platform/x86/intel/ifs/load.c
++++ b/drivers/platform/x86/intel/ifs/load.c
+@@ -260,6 +260,7 @@ int ifs_load_firmware(struct device *dev)
+ {
+       const struct ifs_test_caps *test = ifs_get_test_caps(dev);
+       struct ifs_data *ifsd = ifs_get_data(dev);
++      unsigned int expected_size;
+       const struct firmware *fw;
+       char scan_path[64];
+       int ret = -EINVAL;
+@@ -274,6 +275,13 @@ int ifs_load_firmware(struct device *dev)
+               goto done;
+       }
++      expected_size = ((struct microcode_header_intel *)fw->data)->totalsize;
++      if (fw->size != expected_size) {
++              dev_err(dev, "File size mismatch (expected %u, actual %zu). Corrupted IFS image.\n",
++                      expected_size, fw->size);
++              return -EINVAL;
++      }
++
+       ret = image_sanity_check(dev, (struct microcode_header_intel *)fw->data);
+       if (ret)
+               goto release;
+-- 
+2.43.0
+
diff --git a/queue-6.6/powerpc-topology-check-if-a-core-is-online.patch b/queue-6.6/powerpc-topology-check-if-a-core-is-online.patch
new file mode 100644 (file)
index 0000000..401fca6
--- /dev/null
@@ -0,0 +1,58 @@
+From 1f8e97f12700f9f4dfaa3b2d1aad7b39609c1890 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 31 Jul 2024 08:31:13 +0530
+Subject: powerpc/topology: Check if a core is online
+
+From: Nysal Jan K.A <nysal@linux.ibm.com>
+
+[ Upstream commit 227bbaabe64b6f9cd98aa051454c1d4a194a8c6a ]
+
+topology_is_core_online() checks if the core a CPU belongs to
+is online. The core is online if at least one of the sibling
+CPUs is online. The first CPU of an online core is also online
+in the common case, so this should be fairly quick.
+
+Fixes: 73c58e7e1412 ("powerpc: Add HOTPLUG_SMT support")
+Signed-off-by: Nysal Jan K.A <nysal@linux.ibm.com>
+Reviewed-by: Shrikanth Hegde <sshegde@linux.ibm.com>
+Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
+Link: https://msgid.link/20240731030126.956210-3-nysal@linux.ibm.com
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ arch/powerpc/include/asm/topology.h | 13 +++++++++++++
+ 1 file changed, 13 insertions(+)
+
+diff --git a/arch/powerpc/include/asm/topology.h b/arch/powerpc/include/asm/topology.h
+index f4e6f2dd04b73..16bacfe8c7a2c 100644
+--- a/arch/powerpc/include/asm/topology.h
++++ b/arch/powerpc/include/asm/topology.h
+@@ -145,6 +145,7 @@ static inline int cpu_to_coregroup_id(int cpu)
+ #ifdef CONFIG_HOTPLUG_SMT
+ #include <linux/cpu_smt.h>
++#include <linux/cpumask.h>
+ #include <asm/cputhreads.h>
+ static inline bool topology_is_primary_thread(unsigned int cpu)
+@@ -156,6 +157,18 @@ static inline bool topology_smt_thread_allowed(unsigned int cpu)
+ {
+       return cpu_thread_in_core(cpu) < cpu_smt_num_threads;
+ }
++
++#define topology_is_core_online topology_is_core_online
++static inline bool topology_is_core_online(unsigned int cpu)
++{
++      int i, first_cpu = cpu_first_thread_sibling(cpu);
++
++      for (i = first_cpu; i < first_cpu + threads_per_core; ++i) {
++              if (cpu_online(i))
++                      return true;
++      }
++      return false;
++}
+ #endif
+ #endif /* __KERNEL__ */
+-- 
+2.43.0
+
diff --git a/queue-6.6/rcu-dump-memory-object-info-if-callback-function-is-.patch b/queue-6.6/rcu-dump-memory-object-info-if-callback-function-is-.patch
new file mode 100644 (file)
index 0000000..bb687ce
--- /dev/null
@@ -0,0 +1,149 @@
+From cfed74fad8a42b9691a37ed7a55943fd09f1941e Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sat, 5 Aug 2023 11:17:26 +0800
+Subject: rcu: Dump memory object info if callback function is invalid
+
+From: Zhen Lei <thunder.leizhen@huawei.com>
+
+[ Upstream commit 2cbc482d325ee58001472c4359b311958c4efdd1 ]
+
+When a structure containing an RCU callback rhp is (incorrectly) freed
+and reallocated after rhp is passed to call_rcu(), it is not unusual for
+rhp->func to be set to NULL. This defeats the debugging prints used by
+__call_rcu_common() in kernels built with CONFIG_DEBUG_OBJECTS_RCU_HEAD=y,
+which expect to identify the offending code using the identity of this
+function.
+
+And in kernels build without CONFIG_DEBUG_OBJECTS_RCU_HEAD=y, things
+are even worse, as can be seen from this splat:
+
+Unable to handle kernel NULL pointer dereference at virtual address 0
+... ...
+PC is at 0x0
+LR is at rcu_do_batch+0x1c0/0x3b8
+... ...
+ (rcu_do_batch) from (rcu_core+0x1d4/0x284)
+ (rcu_core) from (__do_softirq+0x24c/0x344)
+ (__do_softirq) from (__irq_exit_rcu+0x64/0x108)
+ (__irq_exit_rcu) from (irq_exit+0x8/0x10)
+ (irq_exit) from (__handle_domain_irq+0x74/0x9c)
+ (__handle_domain_irq) from (gic_handle_irq+0x8c/0x98)
+ (gic_handle_irq) from (__irq_svc+0x5c/0x94)
+ (__irq_svc) from (arch_cpu_idle+0x20/0x3c)
+ (arch_cpu_idle) from (default_idle_call+0x4c/0x78)
+ (default_idle_call) from (do_idle+0xf8/0x150)
+ (do_idle) from (cpu_startup_entry+0x18/0x20)
+ (cpu_startup_entry) from (0xc01530)
+
+This commit therefore adds calls to mem_dump_obj(rhp) to output some
+information, for example:
+
+  slab kmalloc-256 start ffff410c45019900 pointer offset 0 size 256
+
+This provides the rough size of the memory block and the offset of the
+rcu_head structure, which as least provides at least a few clues to help
+locate the problem. If the problem is reproducible, additional slab
+debugging can be enabled, for example, CONFIG_DEBUG_SLAB=y, which can
+provide significantly more information.
+
+Signed-off-by: Zhen Lei <thunder.leizhen@huawei.com>
+Signed-off-by: Paul E. McKenney <paulmck@kernel.org>
+Signed-off-by: Frederic Weisbecker <frederic@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ kernel/rcu/rcu.h      | 7 +++++++
+ kernel/rcu/srcutiny.c | 1 +
+ kernel/rcu/srcutree.c | 1 +
+ kernel/rcu/tasks.h    | 1 +
+ kernel/rcu/tiny.c     | 1 +
+ kernel/rcu/tree.c     | 1 +
+ 6 files changed, 12 insertions(+)
+
+diff --git a/kernel/rcu/rcu.h b/kernel/rcu/rcu.h
+index 3d1851f82dbb6..de0afabfbd440 100644
+--- a/kernel/rcu/rcu.h
++++ b/kernel/rcu/rcu.h
+@@ -10,6 +10,7 @@
+ #ifndef __LINUX_RCU_H
+ #define __LINUX_RCU_H
++#include <linux/slab.h>
+ #include <trace/events/rcu.h>
+ /*
+@@ -248,6 +249,12 @@ static inline void debug_rcu_head_unqueue(struct rcu_head *head)
+ }
+ #endif        /* #else !CONFIG_DEBUG_OBJECTS_RCU_HEAD */
++static inline void debug_rcu_head_callback(struct rcu_head *rhp)
++{
++      if (unlikely(!rhp->func))
++              kmem_dump_obj(rhp);
++}
++
+ extern int rcu_cpu_stall_suppress_at_boot;
+ static inline bool rcu_stall_is_suppressed_at_boot(void)
+diff --git a/kernel/rcu/srcutiny.c b/kernel/rcu/srcutiny.c
+index 336af24e0fe35..c38e5933a5d69 100644
+--- a/kernel/rcu/srcutiny.c
++++ b/kernel/rcu/srcutiny.c
+@@ -138,6 +138,7 @@ void srcu_drive_gp(struct work_struct *wp)
+       while (lh) {
+               rhp = lh;
+               lh = lh->next;
++              debug_rcu_head_callback(rhp);
+               local_bh_disable();
+               rhp->func(rhp);
+               local_bh_enable();
+diff --git a/kernel/rcu/srcutree.c b/kernel/rcu/srcutree.c
+index 25285893e44e7..2f770a9a2a13a 100644
+--- a/kernel/rcu/srcutree.c
++++ b/kernel/rcu/srcutree.c
+@@ -1735,6 +1735,7 @@ static void srcu_invoke_callbacks(struct work_struct *work)
+       rhp = rcu_cblist_dequeue(&ready_cbs);
+       for (; rhp != NULL; rhp = rcu_cblist_dequeue(&ready_cbs)) {
+               debug_rcu_head_unqueue(rhp);
++              debug_rcu_head_callback(rhp);
+               local_bh_disable();
+               rhp->func(rhp);
+               local_bh_enable();
+diff --git a/kernel/rcu/tasks.h b/kernel/rcu/tasks.h
+index ff8d539ee22be..df81506cf2bde 100644
+--- a/kernel/rcu/tasks.h
++++ b/kernel/rcu/tasks.h
+@@ -538,6 +538,7 @@ static void rcu_tasks_invoke_cbs(struct rcu_tasks *rtp, struct rcu_tasks_percpu
+       raw_spin_unlock_irqrestore_rcu_node(rtpcp, flags);
+       len = rcl.len;
+       for (rhp = rcu_cblist_dequeue(&rcl); rhp; rhp = rcu_cblist_dequeue(&rcl)) {
++              debug_rcu_head_callback(rhp);
+               local_bh_disable();
+               rhp->func(rhp);
+               local_bh_enable();
+diff --git a/kernel/rcu/tiny.c b/kernel/rcu/tiny.c
+index 42f7589e51e09..fec804b790803 100644
+--- a/kernel/rcu/tiny.c
++++ b/kernel/rcu/tiny.c
+@@ -97,6 +97,7 @@ static inline bool rcu_reclaim_tiny(struct rcu_head *head)
+       trace_rcu_invoke_callback("", head);
+       f = head->func;
++      debug_rcu_head_callback(head);
+       WRITE_ONCE(head->func, (rcu_callback_t)0L);
+       f(head);
+       rcu_lock_release(&rcu_callback_map);
+diff --git a/kernel/rcu/tree.c b/kernel/rcu/tree.c
+index 583cc29080764..c7cb465e2e0c7 100644
+--- a/kernel/rcu/tree.c
++++ b/kernel/rcu/tree.c
+@@ -2185,6 +2185,7 @@ static void rcu_do_batch(struct rcu_data *rdp)
+               trace_rcu_invoke_callback(rcu_state.name, rhp);
+               f = rhp->func;
++              debug_rcu_head_callback(rhp);
+               WRITE_ONCE(rhp->func, (rcu_callback_t)0L);
+               f(rhp);
+-- 
+2.43.0
+
diff --git a/queue-6.6/rcu-eliminate-rcu_gp_slow_unregister-false-positive.patch b/queue-6.6/rcu-eliminate-rcu_gp_slow_unregister-false-positive.patch
new file mode 100644 (file)
index 0000000..10a372f
--- /dev/null
@@ -0,0 +1,44 @@
+From a378c239de5df79169fbe1ddbd4e38d21eb9f543 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 18 Aug 2023 08:53:58 -0700
+Subject: rcu: Eliminate rcu_gp_slow_unregister() false positive
+
+From: Paul E. McKenney <paulmck@kernel.org>
+
+[ Upstream commit 0ae9942f03d0d034fdb0a4f44fc99f62a3107987 ]
+
+When using rcutorture as a module, there are a number of conditions that
+can abort the modprobe operation, for example, when attempting to run
+both RCU CPU stall warning tests and forward-progress tests.  This can
+cause rcu_torture_cleanup() to be invoked on the unwind path out of
+rcu_rcu_torture_init(), which will mean that rcu_gp_slow_unregister()
+is invoked without a matching rcu_gp_slow_register().  This will cause
+a splat because rcu_gp_slow_unregister() is passed rcu_fwd_cb_nodelay,
+which does not match a NULL pointer.
+
+This commit therefore forgives a mismatch involving a NULL pointer, thus
+avoiding this false-positive splat.
+
+Signed-off-by: Paul E. McKenney <paulmck@kernel.org>
+Signed-off-by: Frederic Weisbecker <frederic@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ kernel/rcu/tree.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/kernel/rcu/tree.c b/kernel/rcu/tree.c
+index c7cb465e2e0c7..8541084eeba50 100644
+--- a/kernel/rcu/tree.c
++++ b/kernel/rcu/tree.c
+@@ -1298,7 +1298,7 @@ EXPORT_SYMBOL_GPL(rcu_gp_slow_register);
+ /* Unregister a counter, with NULL for not caring which. */
+ void rcu_gp_slow_unregister(atomic_t *rgssp)
+ {
+-      WARN_ON_ONCE(rgssp && rgssp != rcu_gp_slow_suppress);
++      WARN_ON_ONCE(rgssp && rgssp != rcu_gp_slow_suppress && rcu_gp_slow_suppress != NULL);
+       WRITE_ONCE(rcu_gp_slow_suppress, NULL);
+ }
+-- 
+2.43.0
+
diff --git a/queue-6.6/rdma-rtrs-fix-the-problem-of-variable-not-initialize.patch b/queue-6.6/rdma-rtrs-fix-the-problem-of-variable-not-initialize.patch
new file mode 100644 (file)
index 0000000..96f014c
--- /dev/null
@@ -0,0 +1,36 @@
+From d22e06219cb389b4528bfe1530b507f94139e6df Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 19 Sep 2023 10:08:06 +0800
+Subject: RDMA/rtrs: Fix the problem of variable not initialized fully
+
+From: Zhu Yanjun <yanjun.zhu@linux.dev>
+
+[ Upstream commit c5930a1aa08aafe6ffe15b5d28fe875f88f6ac86 ]
+
+No functionality change. The variable which is not initialized fully
+will introduce potential risks.
+
+Signed-off-by: Zhu Yanjun <yanjun.zhu@linux.dev>
+Link: https://lore.kernel.org/r/20230919020806.534183-1-yanjun.zhu@intel.com
+Signed-off-by: Leon Romanovsky <leon@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/infiniband/ulp/rtrs/rtrs.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/drivers/infiniband/ulp/rtrs/rtrs.c b/drivers/infiniband/ulp/rtrs/rtrs.c
+index 3696f367ff515..d80edfffd2e49 100644
+--- a/drivers/infiniband/ulp/rtrs/rtrs.c
++++ b/drivers/infiniband/ulp/rtrs/rtrs.c
+@@ -255,7 +255,7 @@ static int create_cq(struct rtrs_con *con, int cq_vector, int nr_cqe,
+ static int create_qp(struct rtrs_con *con, struct ib_pd *pd,
+                    u32 max_send_wr, u32 max_recv_wr, u32 max_sge)
+ {
+-      struct ib_qp_init_attr init_attr = {NULL};
++      struct ib_qp_init_attr init_attr = {};
+       struct rdma_cm_id *cm_id = con->cm_id;
+       int ret;
+-- 
+2.43.0
+
diff --git a/queue-6.6/rust-fix-the-default-format-for-config_-rustc-bindge.patch b/queue-6.6/rust-fix-the-default-format-for-config_-rustc-bindge.patch
new file mode 100644 (file)
index 0000000..639bfe7
--- /dev/null
@@ -0,0 +1,55 @@
+From 817dfccb5cb3f1aa138f12f3317e2860becd8c71 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sat, 27 Jul 2024 23:03:00 +0900
+Subject: rust: fix the default format for CONFIG_{RUSTC,BINDGEN}_VERSION_TEXT
+
+From: Masahiro Yamada <masahiroy@kernel.org>
+
+[ Upstream commit aacf93e87f0d808ef46e621aa56caea336b4433c ]
+
+Another oddity in these config entries is their default value can fall
+back to 'n', which is a value for bool or tristate symbols.
+
+The '|| echo n' is an incorrect workaround to avoid the syntax error.
+This is not a big deal, as the entry is hidden by 'depends on RUST' in
+situations where '$(RUSTC) --version' or '$(BINDGEN) --version' fails.
+Anyway, it looks odd.
+
+The default of a string type symbol should be a double-quoted string
+literal. Turn it into an empty string when the version command fails.
+
+Fixes: 2f7ab1267dc9 ("Kbuild: add Rust support")
+Signed-off-by: Masahiro Yamada <masahiroy@kernel.org>
+Link: https://lore.kernel.org/r/20240727140302.1806011-2-masahiroy@kernel.org
+[ Rebased on top of v6.11-rc1. - Miguel ]
+Signed-off-by: Miguel Ojeda <ojeda@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ init/Kconfig | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/init/Kconfig b/init/Kconfig
+index b5bcc863bf608..6054ba684c539 100644
+--- a/init/Kconfig
++++ b/init/Kconfig
+@@ -1916,7 +1916,7 @@ config RUST
+ config RUSTC_VERSION_TEXT
+       string
+       depends on RUST
+-      default $(shell,$(RUSTC) --version 2>/dev/null || echo n)
++      default "$(shell,$(RUSTC) --version 2>/dev/null)"
+ config BINDGEN_VERSION_TEXT
+       string
+@@ -1924,7 +1924,7 @@ config BINDGEN_VERSION_TEXT
+       # The dummy parameter `workaround-for-0.69.0` is required to support 0.69.0
+       # (https://github.com/rust-lang/rust-bindgen/pull/2678). It can be removed when
+       # the minimum version is upgraded past that (0.69.1 already fixed the issue).
+-      default $(shell,$(BINDGEN) --version workaround-for-0.69.0 2>/dev/null || echo n)
++      default "$(shell,$(BINDGEN) --version workaround-for-0.69.0 2>/dev/null)"
+ #
+ # Place an empty function call at each tracepoint site. Can be
+-- 
+2.43.0
+
diff --git a/queue-6.6/rust-suppress-error-messages-from-config_-rustc-bind.patch b/queue-6.6/rust-suppress-error-messages-from-config_-rustc-bind.patch
new file mode 100644 (file)
index 0000000..157527b
--- /dev/null
@@ -0,0 +1,79 @@
+From 4b5f5d1e9f90ec4c9b8c26ff9560034ea81332b6 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sat, 27 Jul 2024 23:02:59 +0900
+Subject: rust: suppress error messages from
+ CONFIG_{RUSTC,BINDGEN}_VERSION_TEXT
+
+From: Masahiro Yamada <masahiroy@kernel.org>
+
+[ Upstream commit 5ce86c6c861352c9346ebb5c96ed70cb67414aa3 ]
+
+While this is a somewhat unusual case, I encountered odd error messages
+when I ran Kconfig in a foreign architecture chroot.
+
+  $ make allmodconfig
+  sh: 1: rustc: not found
+  sh: 1: bindgen: not found
+  #
+  # configuration written to .config
+  #
+
+The successful execution of 'command -v rustc' does not necessarily mean
+that 'rustc --version' will succeed.
+
+  $ sh -c 'command -v rustc'
+  /home/masahiro/.cargo/bin/rustc
+  $ sh -c 'rustc --version'
+  sh: 1: rustc: not found
+
+Here, 'rustc' is built for x86, and I ran it in an arm64 system.
+
+The current code:
+
+  command -v $(RUSTC) >/dev/null 2>&1 && $(RUSTC) --version || echo n
+
+can be turned into:
+
+  command -v $(RUSTC) >/dev/null 2>&1 && $(RUSTC) --version 2>/dev/null || echo n
+
+However, I did not understand the necessity of 'command -v $(RUSTC)'.
+
+I simplified it to:
+
+  $(RUSTC) --version 2>/dev/null || echo n
+
+Fixes: 2f7ab1267dc9 ("Kbuild: add Rust support")
+Signed-off-by: Masahiro Yamada <masahiroy@kernel.org>
+Link: https://lore.kernel.org/r/20240727140302.1806011-1-masahiroy@kernel.org
+[ Rebased on top of v6.11-rc1. - Miguel ]
+Signed-off-by: Miguel Ojeda <ojeda@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ init/Kconfig | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/init/Kconfig b/init/Kconfig
+index 777113dceca55..b5bcc863bf608 100644
+--- a/init/Kconfig
++++ b/init/Kconfig
+@@ -1916,7 +1916,7 @@ config RUST
+ config RUSTC_VERSION_TEXT
+       string
+       depends on RUST
+-      default $(shell,command -v $(RUSTC) >/dev/null 2>&1 && $(RUSTC) --version || echo n)
++      default $(shell,$(RUSTC) --version 2>/dev/null || echo n)
+ config BINDGEN_VERSION_TEXT
+       string
+@@ -1924,7 +1924,7 @@ config BINDGEN_VERSION_TEXT
+       # The dummy parameter `workaround-for-0.69.0` is required to support 0.69.0
+       # (https://github.com/rust-lang/rust-bindgen/pull/2678). It can be removed when
+       # the minimum version is upgraded past that (0.69.1 already fixed the issue).
+-      default $(shell,command -v $(BINDGEN) >/dev/null 2>&1 && $(BINDGEN) --version workaround-for-0.69.0 || echo n)
++      default $(shell,$(BINDGEN) --version workaround-for-0.69.0 2>/dev/null || echo n)
+ #
+ # Place an empty function call at each tracepoint site. Can be
+-- 
+2.43.0
+
diff --git a/queue-6.6/rust-work-around-bindgen-0.69.0-issue.patch b/queue-6.6/rust-work-around-bindgen-0.69.0-issue.patch
new file mode 100644 (file)
index 0000000..cf26eac
--- /dev/null
@@ -0,0 +1,72 @@
+From 8fcf06a6c8672d35924718859808435a738aa60a Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 9 Jul 2024 18:06:03 +0200
+Subject: rust: work around `bindgen` 0.69.0 issue
+
+From: Miguel Ojeda <ojeda@kernel.org>
+
+[ Upstream commit 9e98db17837093cb0f4dcfcc3524739d93249c45 ]
+
+`bindgen` 0.69.0 contains a bug: `--version` does not work without
+providing a header [1]:
+
+    error: the following required arguments were not provided:
+      <HEADER>
+
+    Usage: bindgen <FLAGS> <OPTIONS> <HEADER> -- <CLANG_ARGS>...
+
+Thus, in preparation for supporting several `bindgen` versions, work
+around the issue by passing a dummy argument.
+
+Include a comment so that we can remove the workaround in the future.
+
+Link: https://github.com/rust-lang/rust-bindgen/pull/2678 [1]
+Reviewed-by: Finn Behrens <me@kloenk.dev>
+Tested-by: Benno Lossin <benno.lossin@proton.me>
+Tested-by: Andreas Hindborg <a.hindborg@samsung.com>
+Link: https://lore.kernel.org/r/20240709160615.998336-9-ojeda@kernel.org
+Signed-off-by: Miguel Ojeda <ojeda@kernel.org>
+Stable-dep-of: 5ce86c6c8613 ("rust: suppress error messages from CONFIG_{RUSTC,BINDGEN}_VERSION_TEXT")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ init/Kconfig                 | 5 ++++-
+ scripts/rust_is_available.sh | 6 +++++-
+ 2 files changed, 9 insertions(+), 2 deletions(-)
+
+diff --git a/init/Kconfig b/init/Kconfig
+index e173364abd6c0..777113dceca55 100644
+--- a/init/Kconfig
++++ b/init/Kconfig
+@@ -1921,7 +1921,10 @@ config RUSTC_VERSION_TEXT
+ config BINDGEN_VERSION_TEXT
+       string
+       depends on RUST
+-      default $(shell,command -v $(BINDGEN) >/dev/null 2>&1 && $(BINDGEN) --version || echo n)
++      # The dummy parameter `workaround-for-0.69.0` is required to support 0.69.0
++      # (https://github.com/rust-lang/rust-bindgen/pull/2678). It can be removed when
++      # the minimum version is upgraded past that (0.69.1 already fixed the issue).
++      default $(shell,command -v $(BINDGEN) >/dev/null 2>&1 && $(BINDGEN) --version workaround-for-0.69.0 || echo n)
+ #
+ # Place an empty function call at each tracepoint site. Can be
+diff --git a/scripts/rust_is_available.sh b/scripts/rust_is_available.sh
+index 117018946b577..a6fdcf13e0e53 100755
+--- a/scripts/rust_is_available.sh
++++ b/scripts/rust_is_available.sh
+@@ -129,8 +129,12 @@ fi
+ # Check that the Rust bindings generator is suitable.
+ #
+ # Non-stable and distributions' versions may have a version suffix, e.g. `-dev`.
++#
++# The dummy parameter `workaround-for-0.69.0` is required to support 0.69.0
++# (https://github.com/rust-lang/rust-bindgen/pull/2678). It can be removed when
++# the minimum version is upgraded past that (0.69.1 already fixed the issue).
+ rust_bindings_generator_output=$( \
+-      LC_ALL=C "$BINDGEN" --version 2>/dev/null
++      LC_ALL=C "$BINDGEN" --version workaround-for-0.69.0 2>/dev/null
+ ) || rust_bindings_generator_code=$?
+ if [ -n "$rust_bindings_generator_code" ]; then
+       echo >&2 "***"
+-- 
+2.43.0
+
diff --git a/queue-6.6/s390-smp-mcck-fix-early-ipi-handling.patch b/queue-6.6/s390-smp-mcck-fix-early-ipi-handling.patch
new file mode 100644 (file)
index 0000000..407f928
--- /dev/null
@@ -0,0 +1,84 @@
+From ae474616380c8f8423fc6f1467a12fed6fd80e58 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 5 Sep 2023 15:49:37 +0200
+Subject: s390/smp,mcck: fix early IPI handling
+
+From: Heiko Carstens <hca@linux.ibm.com>
+
+[ Upstream commit 4a1725281fc5b0009944b1c0e1d2c1dc311a09ec ]
+
+Both the external call as well as the emergency signal submask bits in
+control register 0 are set before any interrupt handler is registered.
+
+Change the order and first register the interrupt handler and only then
+enable the interrupts by setting the corresponding bits in control
+register 0.
+
+This prevents that the second part of the machine check handler for
+early machine check handling is not executed: the machine check handler
+sends an IPI to the CPU it runs on. If the corresponding interrupts are
+enabled, but no interrupt handler is present, the interrupt is ignored.
+
+Reviewed-by: Sven Schnelle <svens@linux.ibm.com>
+Acked-by: Alexander Gordeev <agordeev@linux.ibm.com>
+Signed-off-by: Heiko Carstens <hca@linux.ibm.com>
+Signed-off-by: Vasily Gorbik <gor@linux.ibm.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ arch/s390/kernel/early.c | 12 +++---------
+ arch/s390/kernel/smp.c   |  4 ++--
+ 2 files changed, 5 insertions(+), 11 deletions(-)
+
+diff --git a/arch/s390/kernel/early.c b/arch/s390/kernel/early.c
+index 442ce0489e1a1..3a54733e4fc65 100644
+--- a/arch/s390/kernel/early.c
++++ b/arch/s390/kernel/early.c
+@@ -258,15 +258,9 @@ static inline void save_vector_registers(void)
+ #endif
+ }
+-static inline void setup_control_registers(void)
++static inline void setup_low_address_protection(void)
+ {
+-      unsigned long reg;
+-
+-      __ctl_store(reg, 0, 0);
+-      reg |= CR0_LOW_ADDRESS_PROTECTION;
+-      reg |= CR0_EMERGENCY_SIGNAL_SUBMASK;
+-      reg |= CR0_EXTERNAL_CALL_SUBMASK;
+-      __ctl_load(reg, 0, 0);
++      __ctl_set_bit(0, 28);
+ }
+ static inline void setup_access_registers(void)
+@@ -314,7 +308,7 @@ void __init startup_init(void)
+       save_vector_registers();
+       setup_topology();
+       sclp_early_detect();
+-      setup_control_registers();
++      setup_low_address_protection();
+       setup_access_registers();
+       lockdep_on();
+ }
+diff --git a/arch/s390/kernel/smp.c b/arch/s390/kernel/smp.c
+index a4edb7ea66ea7..c63be2efd6895 100644
+--- a/arch/s390/kernel/smp.c
++++ b/arch/s390/kernel/smp.c
+@@ -1013,12 +1013,12 @@ void __init smp_fill_possible_mask(void)
+ void __init smp_prepare_cpus(unsigned int max_cpus)
+ {
+-      /* request the 0x1201 emergency signal external interrupt */
+       if (register_external_irq(EXT_IRQ_EMERGENCY_SIG, do_ext_call_interrupt))
+               panic("Couldn't request external interrupt 0x1201");
+-      /* request the 0x1202 external call external interrupt */
++      ctl_set_bit(0, 14);
+       if (register_external_irq(EXT_IRQ_EXTERNAL_CALL, do_ext_call_interrupt))
+               panic("Couldn't request external interrupt 0x1202");
++      ctl_set_bit(0, 13);
+ }
+ void __init smp_prepare_boot_cpu(void)
+-- 
+2.43.0
+
diff --git a/queue-6.6/sched-topology-handle-numa_no_node-in-sched_numa_fin.patch b/queue-6.6/sched-topology-handle-numa_no_node-in-sched_numa_fin.patch
new file mode 100644 (file)
index 0000000..c873325
--- /dev/null
@@ -0,0 +1,58 @@
+From 46461893a791e79387f73e61c9cacd8f250736aa Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sat, 19 Aug 2023 07:12:37 -0700
+Subject: sched/topology: Handle NUMA_NO_NODE in sched_numa_find_nth_cpu()
+
+From: Yury Norov <yury.norov@gmail.com>
+
+[ Upstream commit 9ecea9ae4d3127a09fb5dfcea87f248937a39ff5 ]
+
+sched_numa_find_nth_cpu() doesn't handle NUMA_NO_NODE properly, and
+may crash kernel if passed with it. On the other hand, the only user
+of sched_numa_find_nth_cpu() has to check NUMA_NO_NODE case explicitly.
+
+It would be easier for users if this logic will get moved into
+sched_numa_find_nth_cpu().
+
+Signed-off-by: Yury Norov <yury.norov@gmail.com>
+Signed-off-by: Ingo Molnar <mingo@kernel.org>
+Cc: Mel Gorman <mgorman@suse.de>
+Link: https://lore.kernel.org/r/20230819141239.287290-6-yury.norov@gmail.com
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ kernel/sched/topology.c | 3 +++
+ lib/cpumask.c           | 4 +---
+ 2 files changed, 4 insertions(+), 3 deletions(-)
+
+diff --git a/kernel/sched/topology.c b/kernel/sched/topology.c
+index 8c1e183329d97..3a13cecf17740 100644
+--- a/kernel/sched/topology.c
++++ b/kernel/sched/topology.c
+@@ -2126,6 +2126,9 @@ int sched_numa_find_nth_cpu(const struct cpumask *cpus, int cpu, int node)
+       struct cpumask ***hop_masks;
+       int hop, ret = nr_cpu_ids;
++      if (node == NUMA_NO_NODE)
++              return cpumask_nth_and(cpu, cpus, cpu_online_mask);
++
+       rcu_read_lock();
+       /* CPU-less node entries are uninitialized in sched_domains_numa_masks */
+diff --git a/lib/cpumask.c b/lib/cpumask.c
+index a7fd02b5ae264..34335c1e72653 100644
+--- a/lib/cpumask.c
++++ b/lib/cpumask.c
+@@ -146,9 +146,7 @@ unsigned int cpumask_local_spread(unsigned int i, int node)
+       /* Wrap: we always want a cpu. */
+       i %= num_online_cpus();
+-      cpu = (node == NUMA_NO_NODE) ?
+-              cpumask_nth(i, cpu_online_mask) :
+-              sched_numa_find_nth_cpu(cpu_online_mask, i, node);
++      cpu = sched_numa_find_nth_cpu(cpu_online_mask, i, node);
+       WARN_ON(cpu >= nr_cpu_ids);
+       return cpu;
+-- 
+2.43.0
+
diff --git a/queue-6.6/scsi-spi-fix-sshdr-use.patch b/queue-6.6/scsi-spi-fix-sshdr-use.patch
new file mode 100644 (file)
index 0000000..0ccc5a5
--- /dev/null
@@ -0,0 +1,45 @@
+From 59e3078d5d89dd5e60bbea0950cdee56a54cfb5d Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 4 Oct 2023 16:00:07 -0500
+Subject: scsi: spi: Fix sshdr use
+
+From: Mike Christie <michael.christie@oracle.com>
+
+[ Upstream commit 0b149cee836aa53989ea089af1cb9d90d7c6ac9e ]
+
+If scsi_execute_cmd returns < 0, it doesn't initialize the sshdr, so we
+shouldn't access the sshdr. If it returns 0, then the cmd executed
+successfully, so there is no need to check the sshdr. This has us access
+the sshdr when we get a return value > 0.
+
+Signed-off-by: Mike Christie <michael.christie@oracle.com>
+Link: https://lore.kernel.org/r/20231004210013.5601-7-michael.christie@oracle.com
+Reviewed-by: Christoph Hellwig <hch@lst.de>
+Reviewed-by: John Garry <john.g.garry@oracle.com>
+Reviewed-by: Martin Wilck <mwilck@suse.com>
+Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/scsi/scsi_transport_spi.c | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/drivers/scsi/scsi_transport_spi.c b/drivers/scsi/scsi_transport_spi.c
+index 2442d4d2e3f38..f668c1c0a98f2 100644
+--- a/drivers/scsi/scsi_transport_spi.c
++++ b/drivers/scsi/scsi_transport_spi.c
+@@ -676,10 +676,10 @@ spi_dv_device_echo_buffer(struct scsi_device *sdev, u8 *buffer,
+       for (r = 0; r < retries; r++) {
+               result = spi_execute(sdev, spi_write_buffer, REQ_OP_DRV_OUT,
+                                    buffer, len, &sshdr);
+-              if(result || !scsi_device_online(sdev)) {
++              if (result || !scsi_device_online(sdev)) {
+                       scsi_device_set_state(sdev, SDEV_QUIESCE);
+-                      if (scsi_sense_valid(&sshdr)
++                      if (result > 0 && scsi_sense_valid(&sshdr)
+                           && sshdr.sense_key == ILLEGAL_REQUEST
+                           /* INVALID FIELD IN CDB */
+                           && sshdr.asc == 0x24 && sshdr.ascq == 0x00)
+-- 
+2.43.0
+
index 452fc2bc48eff21b39c9b61fb6ae07d8e5ae4545..c1d31c7abe1c2e03ee550fad273fcf1a88a16d8c 100644 (file)
@@ -80,3 +80,60 @@ net-hns3-use-the-user-s-cfg-after-reset.patch
 net-hns3-fix-a-deadlock-problem-when-config-tc-durin.patch
 gpio-mlxbf3-support-shutdown-function.patch
 alsa-hda-realtek-fix-noise-from-speakers-on-lenovo-i.patch
+drm-amd-pm-fix-error-flow-in-sensor-fetching.patch
+drm-amd-amdgpu-imu_v11_0-increase-buffer-size-to-ens.patch
+drm-amdgpu-access-rlc_spm_mc_cntl-through-mmio-in-sr.patch
+ssb-fix-division-by-zero-issue-in-ssb_calc_clock_rat.patch
+asoc-cs35l45-checks-index-of-cs35l45_irqs.patch
+wifi-mac80211-lock-wiphy-in-ip-address-notifier.patch
+wifi-cfg80211-check-wiphy-mutex-is-held-for-wdev-mut.patch
+wifi-mac80211-fix-ba-session-teardown-race.patch
+wifi-iwlwifi-mvm-fix-recovery-flow-in-csa.patch
+rcu-dump-memory-object-info-if-callback-function-is-.patch
+rcu-eliminate-rcu_gp_slow_unregister-false-positive.patch
+net-ethernet-mtk_wed-check-update_wo_rx_stats-in-mtk.patch
+sched-topology-handle-numa_no_node-in-sched_numa_fin.patch
+wifi-cw1200-avoid-processing-an-invalid-tim-ie.patch
+cgroup-avoid-extra-dereference-in-css_populate_dir.patch
+i2c-riic-avoid-potential-division-by-zero.patch
+rdma-rtrs-fix-the-problem-of-variable-not-initialize.patch
+s390-smp-mcck-fix-early-ipi-handling.patch
+drm-bridge-tc358768-attempt-to-fix-dsi-horizontal-ti.patch
+wifi-ath12k-fix-warn_on-during-ath12k_mac_update_vif.patch
+i3c-mipi-i3c-hci-remove-bug-when-ring-abort-request-.patch
+i3c-mipi-i3c-hci-do-not-unmap-region-not-mapped-for-.patch
+drm-amdkfd-move-dma-unmapping-after-tlb-flush.patch
+media-radio-isa-use-dev_name-to-fill-in-bus_info.patch
+wifi-ath11k-fix-ath11k_mac_op_remain_on_channel-stac.patch
+staging-iio-resolver-ad2s1210-fix-use-before-initial.patch
+wifi-mt76-fix-race-condition-related-to-checking-tx-.patch
+usb-gadget-uvc-cleanup-request-when-not-in-correct-s.patch
+drm-amd-display-validate-hw_points_num-before-using-.patch
+staging-ks7010-disable-bh-on-tx_dev_lock.patch
+platform-x86-intel-ifs-validate-image-size.patch
+media-s5p-mfc-fix-potential-deadlock-on-condlock.patch
+accel-habanalabs-gaudi2-unsecure-tpc-count-registers.patch
+accel-habanalabs-export-dma-buf-only-if-size-offset-.patch
+accel-habanalabs-fix-bug-in-timestamp-interrupt-hand.patch
+md-raid5-cache-use-read_once-write_once-for-conf-log.patch
+binfmt_misc-cleanup-on-filesystem-umount.patch
+drm-tegra-zero-initialize-iosys_map.patch
+media-qcom-venus-fix-incorrect-return-value.patch
+iommu-arm-smmu-qcom-add-sdm670-mdss-compatible.patch
+asoc-sof-intel-hda-dsp-make-sure-that-no-irq-handler.patch
+scsi-spi-fix-sshdr-use.patch
+wifi-mac80211-flush-sta-queues-on-unauthorization.patch
+gfs2-setattr_chown-add-missing-initialization.patch
+wifi-iwlwifi-abort-scan-when-rfkill-on-but-device-en.patch
+wifi-iwlwifi-fw-fix-debugfs-command-sending.patch
+wifi-iwlwifi-check-for-kmemdup-return-value-in-iwl_p.patch
+clk-visconti-add-bounds-checking-coverage-for-struct.patch
+ib-hfi1-fix-potential-deadlock-on-irq_src_lock-and-d.patch
+hwmon-ltc2992-avoid-division-by-zero.patch
+rust-work-around-bindgen-0.69.0-issue.patch
+rust-suppress-error-messages-from-config_-rustc-bind.patch
+rust-fix-the-default-format-for-config_-rustc-bindge.patch
+cpu-smt-enable-smt-only-if-a-core-is-online.patch
+powerpc-topology-check-if-a-core-is-online.patch
+arm64-fix-kasan-random-tag-seed-initialization.patch
+block-fix-lockdep-warning-in-blk_mq_mark_tag_wait.patch
diff --git a/queue-6.6/ssb-fix-division-by-zero-issue-in-ssb_calc_clock_rat.patch b/queue-6.6/ssb-fix-division-by-zero-issue-in-ssb_calc_clock_rat.patch
new file mode 100644 (file)
index 0000000..1b53cbe
--- /dev/null
@@ -0,0 +1,49 @@
+From e3f29eeb31cf28f943dbfb423fe95dfaae91be24 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 5 Sep 2023 02:23:46 +0300
+Subject: ssb: Fix division by zero issue in ssb_calc_clock_rate
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Rand Deeb <rand.sec96@gmail.com>
+
+[ Upstream commit e0b5127fa134fe0284d58877b6b3133939c8b3ce ]
+
+In ssb_calc_clock_rate(), there is a potential issue where the value of
+m1 could be zero due to initialization using clkfactor_f6_resolv(). This
+situation raised concerns about the possibility of a division by zero
+error.
+
+We fixed it by following the suggestions provided by Larry Finger
+<Larry.Finger@lwfinger.net> and Michael Büsch <m@bues.ch>. The fix
+involves returning a value of 1 instead of 0 in clkfactor_f6_resolv().
+This modification ensures the proper functioning of the code and
+eliminates the risk of division by zero errors.
+
+Signed-off-by: Rand Deeb <rand.sec96@gmail.com>
+Acked-by: Larry Finger <Larry.Finger@lwfinger.net>
+Acked-by: Michael Büsch <m@bues.ch>
+Signed-off-by: Kalle Valo <kvalo@kernel.org>
+Link: https://lore.kernel.org/r/20230904232346.34991-1-rand.sec96@gmail.com
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/ssb/main.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/drivers/ssb/main.c b/drivers/ssb/main.c
+index 0c736d51566dc..070a99a4180cc 100644
+--- a/drivers/ssb/main.c
++++ b/drivers/ssb/main.c
+@@ -839,7 +839,7 @@ static u32 clkfactor_f6_resolve(u32 v)
+       case SSB_CHIPCO_CLK_F6_7:
+               return 7;
+       }
+-      return 0;
++      return 1;
+ }
+ /* Calculate the speed the backplane would run at a given set of clockcontrol values */
+-- 
+2.43.0
+
diff --git a/queue-6.6/staging-iio-resolver-ad2s1210-fix-use-before-initial.patch b/queue-6.6/staging-iio-resolver-ad2s1210-fix-use-before-initial.patch
new file mode 100644 (file)
index 0000000..fb5e76f
--- /dev/null
@@ -0,0 +1,49 @@
+From 56b96bd5326aa60db3e4ef02a2d7e4e3f2029510 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 29 Sep 2023 12:23:07 -0500
+Subject: staging: iio: resolver: ad2s1210: fix use before initialization
+
+From: David Lechner <dlechner@baylibre.com>
+
+[ Upstream commit 7fe2d05cee46b1c4d9f1efaeab08cc31a0dfff60 ]
+
+This fixes a use before initialization in ad2s1210_probe(). The
+ad2s1210_setup_gpios() function uses st->sdev but it was being called
+before this field was initialized.
+
+Signed-off-by: David Lechner <dlechner@baylibre.com>
+Link: https://lore.kernel.org/r/20230929-ad2s1210-mainline-v3-2-fa4364281745@baylibre.com
+Signed-off-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/staging/iio/resolver/ad2s1210.c | 7 ++++---
+ 1 file changed, 4 insertions(+), 3 deletions(-)
+
+diff --git a/drivers/staging/iio/resolver/ad2s1210.c b/drivers/staging/iio/resolver/ad2s1210.c
+index 06de5823eb8e3..d38c4674cd6d7 100644
+--- a/drivers/staging/iio/resolver/ad2s1210.c
++++ b/drivers/staging/iio/resolver/ad2s1210.c
+@@ -658,9 +658,6 @@ static int ad2s1210_probe(struct spi_device *spi)
+       if (!indio_dev)
+               return -ENOMEM;
+       st = iio_priv(indio_dev);
+-      ret = ad2s1210_setup_gpios(st);
+-      if (ret < 0)
+-              return ret;
+       spi_set_drvdata(spi, indio_dev);
+@@ -671,6 +668,10 @@ static int ad2s1210_probe(struct spi_device *spi)
+       st->resolution = 12;
+       st->fexcit = AD2S1210_DEF_EXCIT;
++      ret = ad2s1210_setup_gpios(st);
++      if (ret < 0)
++              return ret;
++
+       indio_dev->info = &ad2s1210_info;
+       indio_dev->modes = INDIO_DIRECT_MODE;
+       indio_dev->channels = ad2s1210_channels;
+-- 
+2.43.0
+
diff --git a/queue-6.6/staging-ks7010-disable-bh-on-tx_dev_lock.patch b/queue-6.6/staging-ks7010-disable-bh-on-tx_dev_lock.patch
new file mode 100644 (file)
index 0000000..0b3744d
--- /dev/null
@@ -0,0 +1,51 @@
+From 96a9ef7bb2ca3b69a2bbb15a92b27621b4bc28d8 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 26 Sep 2023 16:13:23 +0000
+Subject: staging: ks7010: disable bh on tx_dev_lock
+
+From: Chengfeng Ye <dg573847474@gmail.com>
+
+[ Upstream commit 058cbee52ccd7be77e373d31a4f14670cfd32018 ]
+
+As &priv->tx_dev.tx_dev_lock is also acquired by xmit callback which
+could be call from timer under softirq context, use spin_lock_bh()
+on it to prevent potential deadlock.
+
+hostif_sme_work()
+--> hostif_sme_set_pmksa()
+--> hostif_mib_set_request()
+--> ks_wlan_hw_tx()
+--> spin_lock(&priv->tx_dev.tx_dev_lock)
+
+ks_wlan_start_xmit()
+--> hostif_data_request()
+--> ks_wlan_hw_tx()
+--> spin_lock(&priv->tx_dev.tx_dev_lock)
+
+Signed-off-by: Chengfeng Ye <dg573847474@gmail.com>
+Link: https://lore.kernel.org/r/20230926161323.41928-1-dg573847474@gmail.com
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/staging/ks7010/ks7010_sdio.c | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/drivers/staging/ks7010/ks7010_sdio.c b/drivers/staging/ks7010/ks7010_sdio.c
+index 9fb118e77a1f0..f1d44e4955fc6 100644
+--- a/drivers/staging/ks7010/ks7010_sdio.c
++++ b/drivers/staging/ks7010/ks7010_sdio.c
+@@ -395,9 +395,9 @@ int ks_wlan_hw_tx(struct ks_wlan_private *priv, void *p, unsigned long size,
+       priv->hostt.buff[priv->hostt.qtail] = le16_to_cpu(hdr->event);
+       priv->hostt.qtail = (priv->hostt.qtail + 1) % SME_EVENT_BUFF_SIZE;
+-      spin_lock(&priv->tx_dev.tx_dev_lock);
++      spin_lock_bh(&priv->tx_dev.tx_dev_lock);
+       result = enqueue_txdev(priv, p, size, complete_handler, skb);
+-      spin_unlock(&priv->tx_dev.tx_dev_lock);
++      spin_unlock_bh(&priv->tx_dev.tx_dev_lock);
+       if (txq_has_space(priv))
+               queue_delayed_work(priv->wq, &priv->rw_dwork, 0);
+-- 
+2.43.0
+
diff --git a/queue-6.6/usb-gadget-uvc-cleanup-request-when-not-in-correct-s.patch b/queue-6.6/usb-gadget-uvc-cleanup-request-when-not-in-correct-s.patch
new file mode 100644 (file)
index 0000000..91f26d0
--- /dev/null
@@ -0,0 +1,45 @@
+From 66b55ee622fc4919a127f4f02a5aa730c13fa67c Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 11 Sep 2023 16:05:29 +0200
+Subject: usb: gadget: uvc: cleanup request when not in correct state
+
+From: Michael Grzeschik <m.grzeschik@pengutronix.de>
+
+[ Upstream commit 52a39f2cf62bb5430ad1f54cd522dbfdab1d71ba ]
+
+The uvc_video_enable function of the uvc-gadget driver is dequeing and
+immediately deallocs all requests on its disable codepath. This is not
+save since the dequeue function is async and does not ensure that the
+requests are left unlinked in the controller driver.
+
+By adding the ep_free_request into the completion path of the requests
+we ensure that the request will be properly deallocated.
+
+Signed-off-by: Michael Grzeschik <m.grzeschik@pengutronix.de>
+Link: https://lore.kernel.org/r/20230911140530.2995138-3-m.grzeschik@pengutronix.de
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/usb/gadget/function/uvc_video.c | 6 ++++++
+ 1 file changed, 6 insertions(+)
+
+diff --git a/drivers/usb/gadget/function/uvc_video.c b/drivers/usb/gadget/function/uvc_video.c
+index 281e75027b344..678ed30ada2b7 100644
+--- a/drivers/usb/gadget/function/uvc_video.c
++++ b/drivers/usb/gadget/function/uvc_video.c
+@@ -259,6 +259,12 @@ uvc_video_complete(struct usb_ep *ep, struct usb_request *req)
+       struct uvc_device *uvc = video->uvc;
+       unsigned long flags;
++      if (uvc->state == UVC_STATE_CONNECTED) {
++              usb_ep_free_request(video->ep, ureq->req);
++              ureq->req = NULL;
++              return;
++      }
++
+       switch (req->status) {
+       case 0:
+               break;
+-- 
+2.43.0
+
diff --git a/queue-6.6/wifi-ath11k-fix-ath11k_mac_op_remain_on_channel-stac.patch b/queue-6.6/wifi-ath11k-fix-ath11k_mac_op_remain_on_channel-stac.patch
new file mode 100644 (file)
index 0000000..d96815d
--- /dev/null
@@ -0,0 +1,106 @@
+From e6656b075d8b57a8b0ce00b5a494a6ca90d625d1 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 26 Sep 2023 07:29:04 +0300
+Subject: wifi: ath11k: fix ath11k_mac_op_remain_on_channel() stack usage
+
+From: Dmitry Antipov <dmantipov@yandex.ru>
+
+[ Upstream commit 4fd15bb705d3faa7e6adab2daba2e3af80d9b6bd ]
+
+When compiling with clang 16.0.6, I've noticed the following:
+
+drivers/net/wireless/ath/ath11k/mac.c:8903:12: warning: stack frame
+size (1032) exceeds limit (1024) in 'ath11k_mac_op_remain_on_channel'
+[-Wframe-larger-than]
+static int ath11k_mac_op_remain_on_channel(struct ieee80211_hw *hw,
+           ^
+68/1032 (6.59%) spills, 964/1032 (93.41%) variables
+
+So switch to kzalloc()'ed instance of 'struct scan_req_params' like
+it's done in 'ath11k_mac_op_hw_scan()'. Compile tested only.
+
+Signed-off-by: Dmitry Antipov <dmantipov@yandex.ru>
+Acked-by: Jeff Johnson <quic_jjohnson@quicinc.com>
+Signed-off-by: Kalle Valo <quic_kvalo@quicinc.com>
+Link: https://lore.kernel.org/r/20230926042906.13725-1-dmantipov@yandex.ru
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/wireless/ath/ath11k/mac.c | 44 +++++++++++++++------------
+ 1 file changed, 25 insertions(+), 19 deletions(-)
+
+diff --git a/drivers/net/wireless/ath/ath11k/mac.c b/drivers/net/wireless/ath/ath11k/mac.c
+index 33f2c189b4d86..4247c0f840a48 100644
+--- a/drivers/net/wireless/ath/ath11k/mac.c
++++ b/drivers/net/wireless/ath/ath11k/mac.c
+@@ -8910,7 +8910,7 @@ static int ath11k_mac_op_remain_on_channel(struct ieee80211_hw *hw,
+ {
+       struct ath11k *ar = hw->priv;
+       struct ath11k_vif *arvif = ath11k_vif_to_arvif(vif);
+-      struct scan_req_params arg;
++      struct scan_req_params *arg;
+       int ret;
+       u32 scan_time_msec;
+@@ -8942,27 +8942,31 @@ static int ath11k_mac_op_remain_on_channel(struct ieee80211_hw *hw,
+       scan_time_msec = ar->hw->wiphy->max_remain_on_channel_duration * 2;
+-      memset(&arg, 0, sizeof(arg));
+-      ath11k_wmi_start_scan_init(ar, &arg);
+-      arg.num_chan = 1;
+-      arg.chan_list = kcalloc(arg.num_chan, sizeof(*arg.chan_list),
+-                              GFP_KERNEL);
+-      if (!arg.chan_list) {
++      arg = kzalloc(sizeof(*arg), GFP_KERNEL);
++      if (!arg) {
+               ret = -ENOMEM;
+               goto exit;
+       }
++      ath11k_wmi_start_scan_init(ar, arg);
++      arg->num_chan = 1;
++      arg->chan_list = kcalloc(arg->num_chan, sizeof(*arg->chan_list),
++                               GFP_KERNEL);
++      if (!arg->chan_list) {
++              ret = -ENOMEM;
++              goto free_arg;
++      }
+-      arg.vdev_id = arvif->vdev_id;
+-      arg.scan_id = ATH11K_SCAN_ID;
+-      arg.chan_list[0] = chan->center_freq;
+-      arg.dwell_time_active = scan_time_msec;
+-      arg.dwell_time_passive = scan_time_msec;
+-      arg.max_scan_time = scan_time_msec;
+-      arg.scan_flags |= WMI_SCAN_FLAG_PASSIVE;
+-      arg.scan_flags |= WMI_SCAN_FILTER_PROBE_REQ;
+-      arg.burst_duration = duration;
+-
+-      ret = ath11k_start_scan(ar, &arg);
++      arg->vdev_id = arvif->vdev_id;
++      arg->scan_id = ATH11K_SCAN_ID;
++      arg->chan_list[0] = chan->center_freq;
++      arg->dwell_time_active = scan_time_msec;
++      arg->dwell_time_passive = scan_time_msec;
++      arg->max_scan_time = scan_time_msec;
++      arg->scan_flags |= WMI_SCAN_FLAG_PASSIVE;
++      arg->scan_flags |= WMI_SCAN_FILTER_PROBE_REQ;
++      arg->burst_duration = duration;
++
++      ret = ath11k_start_scan(ar, arg);
+       if (ret) {
+               ath11k_warn(ar->ab, "failed to start roc scan: %d\n", ret);
+@@ -8988,7 +8992,9 @@ static int ath11k_mac_op_remain_on_channel(struct ieee80211_hw *hw,
+       ret = 0;
+ free_chan_list:
+-      kfree(arg.chan_list);
++      kfree(arg->chan_list);
++free_arg:
++      kfree(arg);
+ exit:
+       mutex_unlock(&ar->conf_mutex);
+       return ret;
+-- 
+2.43.0
+
diff --git a/queue-6.6/wifi-ath12k-fix-warn_on-during-ath12k_mac_update_vif.patch b/queue-6.6/wifi-ath12k-fix-warn_on-during-ath12k_mac_update_vif.patch
new file mode 100644 (file)
index 0000000..340a879
--- /dev/null
@@ -0,0 +1,66 @@
+From d992eb3268825133601ce9bb801d8a958fd1f089 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 5 Sep 2023 16:29:41 +0300
+Subject: wifi: ath12k: fix WARN_ON during ath12k_mac_update_vif_chan
+
+From: Manish Dharanenthiran <quic_mdharane@quicinc.com>
+
+[ Upstream commit 8b8b990fe495e9be057249e1651b59b5ebacf2ef ]
+
+Fix WARN_ON() from ath12k_mac_update_vif_chan() if vdev is not up.
+Since change_chanctx can be called even before vdev_up.
+
+Do vdev stop followed by a vdev start in case of vdev is down.
+
+Tested-on: QCN9274 hw2.0 PCI WLAN.WBE.1.0-02903-QCAHKSWPL_SILICONZ-1
+
+Signed-off-by: Manish Dharanenthiran <quic_mdharane@quicinc.com>
+Signed-off-by: Kalle Valo <quic_kvalo@quicinc.com>
+Link: https://lore.kernel.org/r/20230802085852.19821-2-quic_mdharane@quicinc.com
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/wireless/ath/ath12k/mac.c | 27 +++++++++++++++++++++------
+ 1 file changed, 21 insertions(+), 6 deletions(-)
+
+diff --git a/drivers/net/wireless/ath/ath12k/mac.c b/drivers/net/wireless/ath/ath12k/mac.c
+index 61435e4489b9f..ba6fc27f4a1a1 100644
+--- a/drivers/net/wireless/ath/ath12k/mac.c
++++ b/drivers/net/wireless/ath/ath12k/mac.c
+@@ -6039,13 +6039,28 @@ ath12k_mac_update_vif_chan(struct ath12k *ar,
+               if (WARN_ON(!arvif->is_started))
+                       continue;
+-              if (WARN_ON(!arvif->is_up))
+-                      continue;
++              /* Firmware expect vdev_restart only if vdev is up.
++               * If vdev is down then it expect vdev_stop->vdev_start.
++               */
++              if (arvif->is_up) {
++                      ret = ath12k_mac_vdev_restart(arvif, &vifs[i].new_ctx->def);
++                      if (ret) {
++                              ath12k_warn(ab, "failed to restart vdev %d: %d\n",
++                                          arvif->vdev_id, ret);
++                              continue;
++                      }
++              } else {
++                      ret = ath12k_mac_vdev_stop(arvif);
++                      if (ret) {
++                              ath12k_warn(ab, "failed to stop vdev %d: %d\n",
++                                          arvif->vdev_id, ret);
++                              continue;
++                      }
+-              ret = ath12k_mac_vdev_restart(arvif, &vifs[i].new_ctx->def);
+-              if (ret) {
+-                      ath12k_warn(ab, "failed to restart vdev %d: %d\n",
+-                                  arvif->vdev_id, ret);
++                      ret = ath12k_mac_vdev_start(arvif, &vifs[i].new_ctx->def);
++                      if (ret)
++                              ath12k_warn(ab, "failed to start vdev %d: %d\n",
++                                          arvif->vdev_id, ret);
+                       continue;
+               }
+-- 
+2.43.0
+
diff --git a/queue-6.6/wifi-cfg80211-check-wiphy-mutex-is-held-for-wdev-mut.patch b/queue-6.6/wifi-cfg80211-check-wiphy-mutex-is-held-for-wdev-mut.patch
new file mode 100644 (file)
index 0000000..6163606
--- /dev/null
@@ -0,0 +1,52 @@
+From 1c1e9f152a081e6813e273d2df606473cb960b37 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 28 Aug 2023 13:59:56 +0200
+Subject: wifi: cfg80211: check wiphy mutex is held for wdev mutex
+
+From: Johannes Berg <johannes.berg@intel.com>
+
+[ Upstream commit 1474bc87fe57deac726cc10203f73daa6c3212f7 ]
+
+This might seem pretty pointless rather than changing the locking
+immediately, but it seems safer to run for a while with checks and
+the old locking scheme, and then remove the wdev lock later.
+
+Signed-off-by: Johannes Berg <johannes.berg@intel.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/wireless/core.h | 8 +++++++-
+ 1 file changed, 7 insertions(+), 1 deletion(-)
+
+diff --git a/net/wireless/core.h b/net/wireless/core.h
+index f0a3a23176385..c955be6c6daa4 100644
+--- a/net/wireless/core.h
++++ b/net/wireless/core.h
+@@ -228,6 +228,7 @@ void cfg80211_register_wdev(struct cfg80211_registered_device *rdev,
+ static inline void wdev_lock(struct wireless_dev *wdev)
+       __acquires(wdev)
+ {
++      lockdep_assert_held(&wdev->wiphy->mtx);
+       mutex_lock(&wdev->mtx);
+       __acquire(wdev->mtx);
+ }
+@@ -235,11 +236,16 @@ static inline void wdev_lock(struct wireless_dev *wdev)
+ static inline void wdev_unlock(struct wireless_dev *wdev)
+       __releases(wdev)
+ {
++      lockdep_assert_held(&wdev->wiphy->mtx);
+       __release(wdev->mtx);
+       mutex_unlock(&wdev->mtx);
+ }
+-#define ASSERT_WDEV_LOCK(wdev) lockdep_assert_held(&(wdev)->mtx)
++static inline void ASSERT_WDEV_LOCK(struct wireless_dev *wdev)
++{
++      lockdep_assert_held(&wdev->wiphy->mtx);
++      lockdep_assert_held(&wdev->mtx);
++}
+ static inline bool cfg80211_has_monitors_only(struct cfg80211_registered_device *rdev)
+ {
+-- 
+2.43.0
+
diff --git a/queue-6.6/wifi-cw1200-avoid-processing-an-invalid-tim-ie.patch b/queue-6.6/wifi-cw1200-avoid-processing-an-invalid-tim-ie.patch
new file mode 100644 (file)
index 0000000..e9ea00b
--- /dev/null
@@ -0,0 +1,39 @@
+From bee1fde626b96755ea042ab029debf811863e33f Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 31 Aug 2023 11:22:57 -0700
+Subject: wifi: cw1200: Avoid processing an invalid TIM IE
+
+From: Jeff Johnson <quic_jjohnson@quicinc.com>
+
+[ Upstream commit b7bcea9c27b3d87b54075735c870500123582145 ]
+
+While converting struct ieee80211_tim_ie::virtual_map to be a flexible
+array it was observed that the TIM IE processing in cw1200_rx_cb()
+could potentially process a malformed IE in a manner that could result
+in a buffer over-read. Add logic to verify that the TIM IE length is
+large enough to hold a valid TIM payload before processing it.
+
+Signed-off-by: Jeff Johnson <quic_jjohnson@quicinc.com>
+Signed-off-by: Kalle Valo <kvalo@kernel.org>
+Link: https://lore.kernel.org/r/20230831-ieee80211_tim_ie-v3-1-e10ff584ab5d@quicinc.com
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/wireless/st/cw1200/txrx.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/drivers/net/wireless/st/cw1200/txrx.c b/drivers/net/wireless/st/cw1200/txrx.c
+index 6894b919ff94b..e16e9ae90d204 100644
+--- a/drivers/net/wireless/st/cw1200/txrx.c
++++ b/drivers/net/wireless/st/cw1200/txrx.c
+@@ -1166,7 +1166,7 @@ void cw1200_rx_cb(struct cw1200_common *priv,
+               size_t ies_len = skb->len - (ies - (u8 *)(skb->data));
+               tim_ie = cfg80211_find_ie(WLAN_EID_TIM, ies, ies_len);
+-              if (tim_ie) {
++              if (tim_ie && tim_ie[1] >= sizeof(struct ieee80211_tim_ie)) {
+                       struct ieee80211_tim_ie *tim =
+                               (struct ieee80211_tim_ie *)&tim_ie[2];
+-- 
+2.43.0
+
diff --git a/queue-6.6/wifi-iwlwifi-abort-scan-when-rfkill-on-but-device-en.patch b/queue-6.6/wifi-iwlwifi-abort-scan-when-rfkill-on-but-device-en.patch
new file mode 100644 (file)
index 0000000..4c0d653
--- /dev/null
@@ -0,0 +1,47 @@
+From fc960926fd54f90e706304d76298ba703611e521 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 4 Oct 2023 12:36:28 +0300
+Subject: wifi: iwlwifi: abort scan when rfkill on but device enabled
+
+From: Miri Korenblit <miriam.rachel.korenblit@intel.com>
+
+[ Upstream commit 3c6a0b1f0add72e7f522bc9145222b86d0a7712a ]
+
+In RFKILL we first set the RFKILL bit, then we abort scan
+(if one exists) by waiting for the notification from FW
+and notifying mac80211. And then we stop the device.
+But in case we have a scan ongoing in the period of time between
+rfkill on and before the device is stopped - we will not wait for the
+FW notification because of the iwl_mvm_is_radio_killed() condition,
+and then the scan_status and uid_status are misconfigured,
+(scan_status is cleared but uid_status not)
+and when the notification suddenly arrives (before stopping the device)
+we will get into the assert about scan_status and uid_status mismatch.
+Fix this by waiting for FW notif when rfkill is on but the device isn't
+disabled yet.
+
+Signed-off-by: Miri Korenblit <miriam.rachel.korenblit@intel.com>
+Signed-off-by: Gregory Greenman <gregory.greenman@intel.com>
+Link: https://lore.kernel.org/r/20231004123422.c43b69aa2c77.Icc7b5efb47974d6f499156ff7510b786e177993b@changeid
+Signed-off-by: Johannes Berg <johannes.berg@intel.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/wireless/intel/iwlwifi/mvm/scan.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/scan.c b/drivers/net/wireless/intel/iwlwifi/mvm/scan.c
+index 6ef932e6299da..9ca90c0806c0f 100644
+--- a/drivers/net/wireless/intel/iwlwifi/mvm/scan.c
++++ b/drivers/net/wireless/intel/iwlwifi/mvm/scan.c
+@@ -3413,7 +3413,7 @@ int iwl_mvm_scan_stop(struct iwl_mvm *mvm, int type, bool notify)
+       if (!(mvm->scan_status & type))
+               return 0;
+-      if (iwl_mvm_is_radio_killed(mvm)) {
++      if (!test_bit(STATUS_DEVICE_ENABLED, &mvm->trans->status)) {
+               ret = 0;
+               goto out;
+       }
+-- 
+2.43.0
+
diff --git a/queue-6.6/wifi-iwlwifi-check-for-kmemdup-return-value-in-iwl_p.patch b/queue-6.6/wifi-iwlwifi-check-for-kmemdup-return-value-in-iwl_p.patch
new file mode 100644 (file)
index 0000000..72798e4
--- /dev/null
@@ -0,0 +1,46 @@
+From 66bd0c760760e5454737e67b9fb11089fb9cc85b Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 9 Oct 2023 20:04:49 +0300
+Subject: wifi: iwlwifi: check for kmemdup() return value in
+ iwl_parse_tlv_firmware()
+
+From: Dmitry Antipov <dmantipov@yandex.ru>
+
+[ Upstream commit 3c8aaaa7557b1e33e6ef95a27a5d8a139dcd0874 ]
+
+In 'iwl_parse_tlv_firmware()', check for 'kmemdup()' return value
+when handling IWL_UCODE_TLV_CURRENT_PC and set the number of parsed
+entries only if an allocation was successful (just like it does with
+handling IWL_UCODE_TLV_CMD_VERSIONS above). Compile tested only.
+
+Signed-off-by: Dmitry Antipov <dmantipov@yandex.ru>
+Acked-by: Gregory Greenman <gregory.greenman@intel.com>
+Link: https://lore.kernel.org/r/20231009170453.149905-1-dmantipov@yandex.ru
+Signed-off-by: Johannes Berg <johannes.berg@intel.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/wireless/intel/iwlwifi/iwl-drv.c | 6 ++++--
+ 1 file changed, 4 insertions(+), 2 deletions(-)
+
+diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-drv.c b/drivers/net/wireless/intel/iwlwifi/iwl-drv.c
+index a56593b6135f6..47bea1855e8c8 100644
+--- a/drivers/net/wireless/intel/iwlwifi/iwl-drv.c
++++ b/drivers/net/wireless/intel/iwlwifi/iwl-drv.c
+@@ -1304,10 +1304,12 @@ static int iwl_parse_tlv_firmware(struct iwl_drv *drv,
+               case IWL_UCODE_TLV_CURRENT_PC:
+                       if (tlv_len < sizeof(struct iwl_pc_data))
+                               goto invalid_tlv_len;
+-                      drv->trans->dbg.num_pc =
+-                              tlv_len / sizeof(struct iwl_pc_data);
+                       drv->trans->dbg.pc_data =
+                               kmemdup(tlv_data, tlv_len, GFP_KERNEL);
++                      if (!drv->trans->dbg.pc_data)
++                              return -ENOMEM;
++                      drv->trans->dbg.num_pc =
++                              tlv_len / sizeof(struct iwl_pc_data);
+                       break;
+               default:
+                       IWL_DEBUG_INFO(drv, "unknown TLV: %d\n", tlv_type);
+-- 
+2.43.0
+
diff --git a/queue-6.6/wifi-iwlwifi-fw-fix-debugfs-command-sending.patch b/queue-6.6/wifi-iwlwifi-fw-fix-debugfs-command-sending.patch
new file mode 100644 (file)
index 0000000..d646270
--- /dev/null
@@ -0,0 +1,46 @@
+From 65ec2e9a0fa02c3cae10e408405f2d7725f759e2 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 4 Oct 2023 12:36:32 +0300
+Subject: wifi: iwlwifi: fw: Fix debugfs command sending
+
+From: Mukesh Sisodiya <mukesh.sisodiya@intel.com>
+
+[ Upstream commit 048449fc666d736a1a17d950fde0b5c5c8fd10cc ]
+
+During debugfs command handling transport function is used directly,
+this bypasses the locking used by runtime operation function
+and leads to a kernel warning when two commands are
+sent in parallel.
+
+Fix it by using runtime operations function when sending
+debugfs command.
+
+Signed-off-by: Mukesh Sisodiya <mukesh.sisodiya@intel.com>
+Signed-off-by: Gregory Greenman <gregory.greenman@intel.com>
+Link: https://lore.kernel.org/r/20231004123422.4f80ac90658a.Ia1dfa1195c919f3002fe08db3eefbd2bfa921bbf@changeid
+Signed-off-by: Johannes Berg <johannes.berg@intel.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/wireless/intel/iwlwifi/fw/debugfs.c | 6 +++++-
+ 1 file changed, 5 insertions(+), 1 deletion(-)
+
+diff --git a/drivers/net/wireless/intel/iwlwifi/fw/debugfs.c b/drivers/net/wireless/intel/iwlwifi/fw/debugfs.c
+index 3cdbc6ac7ae5d..3356e36e2af73 100644
+--- a/drivers/net/wireless/intel/iwlwifi/fw/debugfs.c
++++ b/drivers/net/wireless/intel/iwlwifi/fw/debugfs.c
+@@ -141,7 +141,11 @@ static int iwl_dbgfs_enabled_severities_write(struct iwl_fw_runtime *fwrt,
+       event_cfg.enabled_severities = cpu_to_le32(enabled_severities);
+-      ret = iwl_trans_send_cmd(fwrt->trans, &hcmd);
++      if (fwrt->ops && fwrt->ops->send_hcmd)
++              ret = fwrt->ops->send_hcmd(fwrt->ops_ctx, &hcmd);
++      else
++              ret = -EPERM;
++
+       IWL_INFO(fwrt,
+                "sent host event cfg with enabled_severities: %u, ret: %d\n",
+                enabled_severities, ret);
+-- 
+2.43.0
+
diff --git a/queue-6.6/wifi-iwlwifi-mvm-fix-recovery-flow-in-csa.patch b/queue-6.6/wifi-iwlwifi-mvm-fix-recovery-flow-in-csa.patch
new file mode 100644 (file)
index 0000000..7904e58
--- /dev/null
@@ -0,0 +1,57 @@
+From 34e3c1f9646e18f3082990d7731b4404fc787c82 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 13 Sep 2023 14:56:46 +0300
+Subject: wifi: iwlwifi: mvm: fix recovery flow in CSA
+
+From: Emmanuel Grumbach <emmanuel.grumbach@intel.com>
+
+[ Upstream commit 828c79d9feb000acbd9c15bd1ed7e0914473b363 ]
+
+If the firmware crashes in the de-activation / re-activation
+of the link during CSA, we will not have a valid phy_ctxt
+pointer in mvmvif. This is a legit case, but when mac80211
+removes the station to cleanup our state during the
+re-configuration, we need to make sure we clear ap_sta
+otherwise we won't re-add the station after the firmware has
+been restarted. Later on, we'd activate the link, try to send
+a TLC command crash again on ASSERT 3508.
+
+Fix this by properly cleaning up our state.
+
+Signed-off-by: Emmanuel Grumbach <emmanuel.grumbach@intel.com>
+Signed-off-by: Gregory Greenman <gregory.greenman@intel.com>
+Link: https://lore.kernel.org/r/20230913145231.2651e6f6a55a.I4cd50e88ee5c23c1c8dd5b157a800e4b4c96f236@changeid
+Signed-off-by: Johannes Berg <johannes.berg@intel.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c | 7 ++++++-
+ 1 file changed, 6 insertions(+), 1 deletion(-)
+
+diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c b/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c
+index 8f49de1206e03..f973efbbc3795 100644
+--- a/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c
++++ b/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c
+@@ -1035,6 +1035,7 @@ static void iwl_mvm_cleanup_iterator(void *data, u8 *mac,
+       spin_unlock_bh(&mvm->time_event_lock);
+       memset(&mvmvif->bf_data, 0, sizeof(mvmvif->bf_data));
++      mvmvif->ap_sta = NULL;
+       for_each_mvm_vif_valid_link(mvmvif, link_id) {
+               mvmvif->link[link_id]->ap_sta_id = IWL_MVM_INVALID_STA;
+@@ -3934,7 +3935,11 @@ int iwl_mvm_mac_sta_state_common(struct ieee80211_hw *hw,
+       mutex_lock(&mvm->mutex);
+-      /* this would be a mac80211 bug ... but don't crash */
++      /* this would be a mac80211 bug ... but don't crash, unless we had a
++       * firmware crash while we were activating a link, in which case it is
++       * legit to have phy_ctxt = NULL. Don't bother not to WARN if we are in
++       * recovery flow since we spit tons of error messages anyway.
++       */
+       for_each_sta_active_link(vif, sta, link_sta, link_id) {
+               if (WARN_ON_ONCE(!mvmvif->link[link_id]->phy_ctxt)) {
+                       mutex_unlock(&mvm->mutex);
+-- 
+2.43.0
+
diff --git a/queue-6.6/wifi-mac80211-fix-ba-session-teardown-race.patch b/queue-6.6/wifi-mac80211-fix-ba-session-teardown-race.patch
new file mode 100644 (file)
index 0000000..1fc2458
--- /dev/null
@@ -0,0 +1,113 @@
+From 3b091ad48be89ecb73c878647a99c603c8b4cb11 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 29 Aug 2023 20:16:11 +0200
+Subject: wifi: mac80211: fix BA session teardown race
+
+From: Johannes Berg <johannes.berg@intel.com>
+
+[ Upstream commit 05f136220d17839eb7c155f015ace9152f603225 ]
+
+As previously reported by Alexander, whose commit 69403bad97aa
+("wifi: mac80211: sdata can be NULL during AMPDU start") I'm
+reverting as part of this commit, there's a race between station
+destruction and aggregation setup, where the aggregation setup
+can happen while the station is being removed and queue the work
+after ieee80211_sta_tear_down_BA_sessions() has already run in
+__sta_info_destroy_part1(), and thus the worker will run with a
+now freed station. In his case, this manifested in a NULL sdata
+pointer, but really there's no guarantee whatsoever.
+
+The real issue seems to be that it's possible at all to have a
+situation where this occurs - we want to stop the BA sessions
+when doing _part1, but we cannot be sure, and WLAN_STA_BLOCK_BA
+isn't necessarily effective since we don't know that the setup
+isn't concurrently running and already got past the check.
+
+Simply call ieee80211_sta_tear_down_BA_sessions() again in the
+second part of station destruction, since at that point really
+nothing else can hold a reference to the station any more.
+
+Also revert the sdata checks since those are just misleading at
+this point.
+
+Signed-off-by: Johannes Berg <johannes.berg@intel.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/mac80211/agg-tx.c     |  6 +-----
+ net/mac80211/driver-ops.c |  3 ---
+ net/mac80211/sta_info.c   | 14 ++++++++++++++
+ 3 files changed, 15 insertions(+), 8 deletions(-)
+
+diff --git a/net/mac80211/agg-tx.c b/net/mac80211/agg-tx.c
+index b6b7726858815..0a69e47f1c55f 100644
+--- a/net/mac80211/agg-tx.c
++++ b/net/mac80211/agg-tx.c
+@@ -497,7 +497,7 @@ void ieee80211_tx_ba_session_handle_start(struct sta_info *sta, int tid)
+ {
+       struct tid_ampdu_tx *tid_tx;
+       struct ieee80211_local *local = sta->local;
+-      struct ieee80211_sub_if_data *sdata;
++      struct ieee80211_sub_if_data *sdata = sta->sdata;
+       struct ieee80211_ampdu_params params = {
+               .sta = &sta->sta,
+               .action = IEEE80211_AMPDU_TX_START,
+@@ -525,7 +525,6 @@ void ieee80211_tx_ba_session_handle_start(struct sta_info *sta, int tid)
+        */
+       synchronize_net();
+-      sdata = sta->sdata;
+       params.ssn = sta->tid_seq[tid] >> 4;
+       ret = drv_ampdu_action(local, sdata, &params);
+       tid_tx->ssn = params.ssn;
+@@ -539,9 +538,6 @@ void ieee80211_tx_ba_session_handle_start(struct sta_info *sta, int tid)
+                */
+               set_bit(HT_AGG_STATE_DRV_READY, &tid_tx->state);
+       } else if (ret) {
+-              if (!sdata)
+-                      return;
+-
+               ht_dbg(sdata,
+                      "BA request denied - HW unavailable for %pM tid %d\n",
+                      sta->sta.addr, tid);
+diff --git a/net/mac80211/driver-ops.c b/net/mac80211/driver-ops.c
+index f8af0c3d405ae..d6478fd00badf 100644
+--- a/net/mac80211/driver-ops.c
++++ b/net/mac80211/driver-ops.c
+@@ -393,9 +393,6 @@ int drv_ampdu_action(struct ieee80211_local *local,
+       might_sleep();
+-      if (!sdata)
+-              return -EIO;
+-
+       sdata = get_bss_sdata(sdata);
+       if (!check_sdata_in_driver(sdata))
+               return -EIO;
+diff --git a/net/mac80211/sta_info.c b/net/mac80211/sta_info.c
+index 984f8f67492fd..42ba51a9700f2 100644
+--- a/net/mac80211/sta_info.c
++++ b/net/mac80211/sta_info.c
+@@ -1402,6 +1402,20 @@ static void __sta_info_destroy_part2(struct sta_info *sta, bool recalc)
+        *       after _part1 and before _part2!
+        */
++      /*
++       * There's a potential race in _part1 where we set WLAN_STA_BLOCK_BA
++       * but someone might have just gotten past a check, and not yet into
++       * queuing the work/creating the data/etc.
++       *
++       * Do another round of destruction so that the worker is certainly
++       * canceled before we later free the station.
++       *
++       * Since this is after synchronize_rcu()/synchronize_net() we're now
++       * certain that nobody can actually hold a reference to the STA and
++       * be calling e.g. ieee80211_start_tx_ba_session().
++       */
++      ieee80211_sta_tear_down_BA_sessions(sta, AGG_STOP_DESTROY_STA);
++
+       might_sleep();
+       lockdep_assert_held(&local->sta_mtx);
+-- 
+2.43.0
+
diff --git a/queue-6.6/wifi-mac80211-flush-sta-queues-on-unauthorization.patch b/queue-6.6/wifi-mac80211-flush-sta-queues-on-unauthorization.patch
new file mode 100644 (file)
index 0000000..674b57d
--- /dev/null
@@ -0,0 +1,85 @@
+From 989d112acb48b7b77cdbd18184e7ab799c072126 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 28 Sep 2023 17:35:39 +0300
+Subject: wifi: mac80211: flush STA queues on unauthorization
+
+From: Johannes Berg <johannes.berg@intel.com>
+
+[ Upstream commit 06d6af4e1223339bb597b02fa8ad3f979ddb5511 ]
+
+When the station is marked as no longer authorized, we shouldn't
+transmit to it any longer, but in particular we shouldn't be able
+to transmit to it after removing keys, which might lead to frames
+being sent out unencrypted depending on the exact hardware offload
+mechanism. Thus, instead of flushing only on station destruction,
+which covers only some cases, always flush on unauthorization.
+
+Signed-off-by: Johannes Berg <johannes.berg@intel.com>
+Signed-off-by: Gregory Greenman <gregory.greenman@intel.com>
+Link: https://lore.kernel.org/r/20230928172905.d47f528829e7.I96903652c7ee0c5c66891f8b2364383da8e45a1f@changeid
+Signed-off-by: Johannes Berg <johannes.berg@intel.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/mac80211/sta_info.c | 32 ++++++++++++++++++++------------
+ 1 file changed, 20 insertions(+), 12 deletions(-)
+
+diff --git a/net/mac80211/sta_info.c b/net/mac80211/sta_info.c
+index 42ba51a9700f2..5d71e8d084c45 100644
+--- a/net/mac80211/sta_info.c
++++ b/net/mac80211/sta_info.c
+@@ -1284,6 +1284,8 @@ static int _sta_info_move_state(struct sta_info *sta,
+                               enum ieee80211_sta_state new_state,
+                               bool recalc)
+ {
++      struct ieee80211_local *local = sta->local;
++
+       might_sleep();
+       if (sta->sta_state == new_state)
+@@ -1359,6 +1361,24 @@ static int _sta_info_move_state(struct sta_info *sta,
+               } else if (sta->sta_state == IEEE80211_STA_AUTHORIZED) {
+                       ieee80211_vif_dec_num_mcast(sta->sdata);
+                       clear_bit(WLAN_STA_AUTHORIZED, &sta->_flags);
++
++                      /*
++                       * If we have encryption offload, flush (station) queues
++                       * (after ensuring concurrent TX completed) so we won't
++                       * transmit anything later unencrypted if/when keys are
++                       * also removed, which might otherwise happen depending
++                       * on how the hardware offload works.
++                       */
++                      if (local->ops->set_key) {
++                              synchronize_net();
++                              if (local->ops->flush_sta)
++                                      drv_flush_sta(local, sta->sdata, sta);
++                              else
++                                      ieee80211_flush_queues(local,
++                                                             sta->sdata,
++                                                             false);
++                      }
++
+                       ieee80211_clear_fast_xmit(sta);
+                       ieee80211_clear_fast_rx(sta);
+               }
+@@ -1424,18 +1444,6 @@ static void __sta_info_destroy_part2(struct sta_info *sta, bool recalc)
+               WARN_ON_ONCE(ret);
+       }
+-      /* Flush queues before removing keys, as that might remove them
+-       * from hardware, and then depending on the offload method, any
+-       * frames sitting on hardware queues might be sent out without
+-       * any encryption at all.
+-       */
+-      if (local->ops->set_key) {
+-              if (local->ops->flush_sta)
+-                      drv_flush_sta(local, sta->sdata, sta);
+-              else
+-                      ieee80211_flush_queues(local, sta->sdata, false);
+-      }
+-
+       /* now keys can no longer be reached */
+       ieee80211_free_sta_keys(local, sta);
+-- 
+2.43.0
+
diff --git a/queue-6.6/wifi-mac80211-lock-wiphy-in-ip-address-notifier.patch b/queue-6.6/wifi-mac80211-lock-wiphy-in-ip-address-notifier.patch
new file mode 100644 (file)
index 0000000..2fa06fd
--- /dev/null
@@ -0,0 +1,99 @@
+From 2adfa2f3a6f4d4d8981bf119cfe2681271712b6c Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 28 Aug 2023 13:59:41 +0200
+Subject: wifi: mac80211: lock wiphy in IP address notifier
+
+From: Johannes Berg <johannes.berg@intel.com>
+
+[ Upstream commit 730538edc8e0eb14b02708f65100a0deaf43e6cd ]
+
+Lock the wiphy in the IP address notifier as another
+place that should have it locked before calling into
+the driver. This needs a bit of attention since the
+notifier can be called while the wiphy is already
+locked, when we remove an interface. Handle this by
+not running the notifier in this case, and instead
+calling out to the driver directly.
+
+Signed-off-by: Johannes Berg <johannes.berg@intel.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/mac80211/iface.c | 14 ++++++++++++++
+ net/mac80211/main.c  | 22 +++++++++++++++++++++-
+ 2 files changed, 35 insertions(+), 1 deletion(-)
+
+diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c
+index 52b048807feae..a7c39e895b1e5 100644
+--- a/net/mac80211/iface.c
++++ b/net/mac80211/iface.c
+@@ -2315,6 +2315,20 @@ void ieee80211_remove_interfaces(struct ieee80211_local *local)
+       list_for_each_entry_safe(sdata, tmp, &unreg_list, list) {
+               bool netdev = sdata->dev;
++              /*
++               * Remove IP addresses explicitly, since the notifier will
++               * skip the callbacks if wdev->registered is false, since
++               * we can't acquire the wiphy_lock() again there if already
++               * inside this locked section.
++               */
++              sdata_lock(sdata);
++              sdata->vif.cfg.arp_addr_cnt = 0;
++              if (sdata->vif.type == NL80211_IFTYPE_STATION &&
++                  sdata->u.mgd.associated)
++                      ieee80211_vif_cfg_change_notify(sdata,
++                                                      BSS_CHANGED_ARP_FILTER);
++              sdata_unlock(sdata);
++
+               list_del(&sdata->list);
+               cfg80211_unregister_wdev(&sdata->wdev);
+diff --git a/net/mac80211/main.c b/net/mac80211/main.c
+index e0c701c5e5f93..066424e62ff09 100644
+--- a/net/mac80211/main.c
++++ b/net/mac80211/main.c
+@@ -443,7 +443,7 @@ static int ieee80211_ifa_changed(struct notifier_block *nb,
+       if (!wdev)
+               return NOTIFY_DONE;
+-      if (wdev->wiphy != local->hw.wiphy)
++      if (wdev->wiphy != local->hw.wiphy || !wdev->registered)
+               return NOTIFY_DONE;
+       sdata = IEEE80211_DEV_TO_SUB_IF(ndev);
+@@ -458,6 +458,25 @@ static int ieee80211_ifa_changed(struct notifier_block *nb,
+               return NOTIFY_DONE;
+       ifmgd = &sdata->u.mgd;
++
++      /*
++       * The nested here is needed to convince lockdep that this is
++       * all OK. Yes, we lock the wiphy mutex here while we already
++       * hold the notifier rwsem, that's the normal case. And yes,
++       * we also acquire the notifier rwsem again when unregistering
++       * a netdev while we already hold the wiphy mutex, so it does
++       * look like a typical ABBA deadlock.
++       *
++       * However, both of these things happen with the RTNL held
++       * already. Therefore, they can't actually happen, since the
++       * lock orders really are ABC and ACB, which is fine due to
++       * the RTNL (A).
++       *
++       * We still need to prevent recursion, which is accomplished
++       * by the !wdev->registered check above.
++       */
++      mutex_lock_nested(&local->hw.wiphy->mtx, 1);
++      __acquire(&local->hw.wiphy->mtx);
+       sdata_lock(sdata);
+       /* Copy the addresses to the vif config list */
+@@ -476,6 +495,7 @@ static int ieee80211_ifa_changed(struct notifier_block *nb,
+               ieee80211_vif_cfg_change_notify(sdata, BSS_CHANGED_ARP_FILTER);
+       sdata_unlock(sdata);
++      wiphy_unlock(local->hw.wiphy);
+       return NOTIFY_OK;
+ }
+-- 
+2.43.0
+
diff --git a/queue-6.6/wifi-mt76-fix-race-condition-related-to-checking-tx-.patch b/queue-6.6/wifi-mt76-fix-race-condition-related-to-checking-tx-.patch
new file mode 100644 (file)
index 0000000..74300f6
--- /dev/null
@@ -0,0 +1,458 @@
+From c30775cc482b20f7720499215b40d853f7617049 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 29 Aug 2023 10:39:53 +0200
+Subject: wifi: mt76: fix race condition related to checking tx queue fill
+ status
+
+From: Felix Fietkau <nbd@nbd.name>
+
+[ Upstream commit 0335c034e7265d36d956e806f33202c94a8a9860 ]
+
+When drv_tx calls race against local tx scheduling, the queue fill status checks
+can potentially race, leading to dma queue entries being overwritten.
+Fix this by deferring packets from drv_tx calls to the tx worker, in order to
+ensure that all regular queue tx comes from the same context.
+
+Reported-by: Ryder Lee <Ryder.Lee@mediatek.com>
+Signed-off-by: Felix Fietkau <nbd@nbd.name>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/wireless/mediatek/mt76/mac80211.c |  50 +++++++-
+ drivers/net/wireless/mediatek/mt76/mt76.h     |  24 ++--
+ .../net/wireless/mediatek/mt76/mt7603/main.c  |   4 +-
+ .../net/wireless/mediatek/mt76/mt7615/main.c  |   4 +-
+ .../net/wireless/mediatek/mt76/mt76x02_util.c |   4 +-
+ .../net/wireless/mediatek/mt76/mt7915/main.c  |   4 +-
+ .../net/wireless/mediatek/mt76/mt7921/main.c  |   2 +-
+ .../net/wireless/mediatek/mt76/mt792x_core.c  |   2 +-
+ .../net/wireless/mediatek/mt76/mt7996/main.c  |   4 +-
+ drivers/net/wireless/mediatek/mt76/tx.c       | 108 ++++++++++++++----
+ 10 files changed, 155 insertions(+), 51 deletions(-)
+
+diff --git a/drivers/net/wireless/mediatek/mt76/mac80211.c b/drivers/net/wireless/mediatek/mt76/mac80211.c
+index dbab400969202..85bffcf4f6fbf 100644
+--- a/drivers/net/wireless/mediatek/mt76/mac80211.c
++++ b/drivers/net/wireless/mediatek/mt76/mac80211.c
+@@ -415,6 +415,9 @@ mt76_phy_init(struct mt76_phy *phy, struct ieee80211_hw *hw)
+       struct mt76_dev *dev = phy->dev;
+       struct wiphy *wiphy = hw->wiphy;
++      INIT_LIST_HEAD(&phy->tx_list);
++      spin_lock_init(&phy->tx_lock);
++
+       SET_IEEE80211_DEV(hw, dev->dev);
+       SET_IEEE80211_PERM_ADDR(hw, phy->macaddr);
+@@ -688,6 +691,7 @@ int mt76_register_device(struct mt76_dev *dev, bool vht,
+       int ret;
+       dev_set_drvdata(dev->dev, dev);
++      mt76_wcid_init(&dev->global_wcid);
+       ret = mt76_phy_init(phy, hw);
+       if (ret)
+               return ret;
+@@ -743,6 +747,7 @@ void mt76_unregister_device(struct mt76_dev *dev)
+       if (IS_ENABLED(CONFIG_MT76_LEDS))
+               mt76_led_cleanup(&dev->phy);
+       mt76_tx_status_check(dev, true);
++      mt76_wcid_cleanup(dev, &dev->global_wcid);
+       ieee80211_unregister_hw(hw);
+ }
+ EXPORT_SYMBOL_GPL(mt76_unregister_device);
+@@ -1411,7 +1416,7 @@ mt76_sta_add(struct mt76_phy *phy, struct ieee80211_vif *vif,
+       wcid->phy_idx = phy->band_idx;
+       rcu_assign_pointer(dev->wcid[wcid->idx], wcid);
+-      mt76_packet_id_init(wcid);
++      mt76_wcid_init(wcid);
+ out:
+       mutex_unlock(&dev->mutex);
+@@ -1430,7 +1435,7 @@ void __mt76_sta_remove(struct mt76_dev *dev, struct ieee80211_vif *vif,
+       if (dev->drv->sta_remove)
+               dev->drv->sta_remove(dev, vif, sta);
+-      mt76_packet_id_flush(dev, wcid);
++      mt76_wcid_cleanup(dev, wcid);
+       mt76_wcid_mask_clear(dev->wcid_mask, idx);
+       mt76_wcid_mask_clear(dev->wcid_phy_mask, idx);
+@@ -1486,6 +1491,47 @@ void mt76_sta_pre_rcu_remove(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
+ }
+ EXPORT_SYMBOL_GPL(mt76_sta_pre_rcu_remove);
++void mt76_wcid_init(struct mt76_wcid *wcid)
++{
++      INIT_LIST_HEAD(&wcid->tx_list);
++      skb_queue_head_init(&wcid->tx_pending);
++
++      INIT_LIST_HEAD(&wcid->list);
++      idr_init(&wcid->pktid);
++}
++EXPORT_SYMBOL_GPL(mt76_wcid_init);
++
++void mt76_wcid_cleanup(struct mt76_dev *dev, struct mt76_wcid *wcid)
++{
++      struct mt76_phy *phy = dev->phys[wcid->phy_idx];
++      struct ieee80211_hw *hw;
++      struct sk_buff_head list;
++      struct sk_buff *skb;
++
++      mt76_tx_status_lock(dev, &list);
++      mt76_tx_status_skb_get(dev, wcid, -1, &list);
++      mt76_tx_status_unlock(dev, &list);
++
++      idr_destroy(&wcid->pktid);
++
++      spin_lock_bh(&phy->tx_lock);
++
++      if (!list_empty(&wcid->tx_list))
++              list_del_init(&wcid->tx_list);
++
++      spin_lock(&wcid->tx_pending.lock);
++      skb_queue_splice_tail_init(&wcid->tx_pending, &list);
++      spin_unlock(&wcid->tx_pending.lock);
++
++      spin_unlock_bh(&phy->tx_lock);
++
++      while ((skb = __skb_dequeue(&list)) != NULL) {
++              hw = mt76_tx_status_get_hw(dev, skb);
++              ieee80211_free_txskb(hw, skb);
++      }
++}
++EXPORT_SYMBOL_GPL(mt76_wcid_cleanup);
++
+ int mt76_get_txpower(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
+                    int *dbm)
+ {
+diff --git a/drivers/net/wireless/mediatek/mt76/mt76.h b/drivers/net/wireless/mediatek/mt76/mt76.h
+index 7f44736ca26f0..8b620d4fed439 100644
+--- a/drivers/net/wireless/mediatek/mt76/mt76.h
++++ b/drivers/net/wireless/mediatek/mt76/mt76.h
+@@ -334,6 +334,9 @@ struct mt76_wcid {
+       u32 tx_info;
+       bool sw_iv;
++      struct list_head tx_list;
++      struct sk_buff_head tx_pending;
++
+       struct list_head list;
+       struct idr pktid;
+@@ -719,6 +722,8 @@ struct mt76_phy {
+       unsigned long state;
+       u8 band_idx;
++      spinlock_t tx_lock;
++      struct list_head tx_list;
+       struct mt76_queue *q_tx[__MT_TXQ_MAX];
+       struct cfg80211_chan_def chandef;
+@@ -1599,22 +1604,7 @@ mt76_token_put(struct mt76_dev *dev, int token)
+       return txwi;
+ }
+-static inline void mt76_packet_id_init(struct mt76_wcid *wcid)
+-{
+-      INIT_LIST_HEAD(&wcid->list);
+-      idr_init(&wcid->pktid);
+-}
+-
+-static inline void
+-mt76_packet_id_flush(struct mt76_dev *dev, struct mt76_wcid *wcid)
+-{
+-      struct sk_buff_head list;
+-
+-      mt76_tx_status_lock(dev, &list);
+-      mt76_tx_status_skb_get(dev, wcid, -1, &list);
+-      mt76_tx_status_unlock(dev, &list);
+-
+-      idr_destroy(&wcid->pktid);
+-}
++void mt76_wcid_init(struct mt76_wcid *wcid);
++void mt76_wcid_cleanup(struct mt76_dev *dev, struct mt76_wcid *wcid);
+ #endif
+diff --git a/drivers/net/wireless/mediatek/mt76/mt7603/main.c b/drivers/net/wireless/mediatek/mt76/mt7603/main.c
+index c213fd2a5216b..89d738deea62e 100644
+--- a/drivers/net/wireless/mediatek/mt76/mt7603/main.c
++++ b/drivers/net/wireless/mediatek/mt76/mt7603/main.c
+@@ -70,7 +70,7 @@ mt7603_add_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif)
+       mvif->sta.wcid.idx = idx;
+       mvif->sta.wcid.hw_key_idx = -1;
+       mvif->sta.vif = mvif;
+-      mt76_packet_id_init(&mvif->sta.wcid);
++      mt76_wcid_init(&mvif->sta.wcid);
+       eth_broadcast_addr(bc_addr);
+       mt7603_wtbl_init(dev, idx, mvif->idx, bc_addr);
+@@ -110,7 +110,7 @@ mt7603_remove_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif)
+       dev->mt76.vif_mask &= ~BIT_ULL(mvif->idx);
+       mutex_unlock(&dev->mt76.mutex);
+-      mt76_packet_id_flush(&dev->mt76, &mvif->sta.wcid);
++      mt76_wcid_cleanup(&dev->mt76, &mvif->sta.wcid);
+ }
+ void mt7603_init_edcca(struct mt7603_dev *dev)
+diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/main.c b/drivers/net/wireless/mediatek/mt76/mt7615/main.c
+index 200b1752ca77f..dab16b5fc3861 100644
+--- a/drivers/net/wireless/mediatek/mt76/mt7615/main.c
++++ b/drivers/net/wireless/mediatek/mt76/mt7615/main.c
+@@ -226,7 +226,7 @@ static int mt7615_add_interface(struct ieee80211_hw *hw,
+       mvif->sta.wcid.idx = idx;
+       mvif->sta.wcid.phy_idx = mvif->mt76.band_idx;
+       mvif->sta.wcid.hw_key_idx = -1;
+-      mt76_packet_id_init(&mvif->sta.wcid);
++      mt76_wcid_init(&mvif->sta.wcid);
+       mt7615_mac_wtbl_update(dev, idx,
+                              MT_WTBL_UPDATE_ADM_COUNT_CLEAR);
+@@ -279,7 +279,7 @@ static void mt7615_remove_interface(struct ieee80211_hw *hw,
+               list_del_init(&msta->wcid.poll_list);
+       spin_unlock_bh(&dev->mt76.sta_poll_lock);
+-      mt76_packet_id_flush(&dev->mt76, &mvif->sta.wcid);
++      mt76_wcid_cleanup(&dev->mt76, &mvif->sta.wcid);
+ }
+ int mt7615_set_channel(struct mt7615_phy *phy)
+diff --git a/drivers/net/wireless/mediatek/mt76/mt76x02_util.c b/drivers/net/wireless/mediatek/mt76/mt76x02_util.c
+index dcbb5c605dfe6..8a0e8124b8940 100644
+--- a/drivers/net/wireless/mediatek/mt76/mt76x02_util.c
++++ b/drivers/net/wireless/mediatek/mt76/mt76x02_util.c
+@@ -288,7 +288,7 @@ mt76x02_vif_init(struct mt76x02_dev *dev, struct ieee80211_vif *vif,
+       mvif->idx = idx;
+       mvif->group_wcid.idx = MT_VIF_WCID(idx);
+       mvif->group_wcid.hw_key_idx = -1;
+-      mt76_packet_id_init(&mvif->group_wcid);
++      mt76_wcid_init(&mvif->group_wcid);
+       mtxq = (struct mt76_txq *)vif->txq->drv_priv;
+       rcu_assign_pointer(dev->mt76.wcid[MT_VIF_WCID(idx)], &mvif->group_wcid);
+@@ -346,7 +346,7 @@ void mt76x02_remove_interface(struct ieee80211_hw *hw,
+       dev->mt76.vif_mask &= ~BIT_ULL(mvif->idx);
+       rcu_assign_pointer(dev->mt76.wcid[mvif->group_wcid.idx], NULL);
+-      mt76_packet_id_flush(&dev->mt76, &mvif->group_wcid);
++      mt76_wcid_cleanup(&dev->mt76, &mvif->group_wcid);
+ }
+ EXPORT_SYMBOL_GPL(mt76x02_remove_interface);
+diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/main.c b/drivers/net/wireless/mediatek/mt76/mt7915/main.c
+index 3196f56cdf4ab..260fe00d7dc6d 100644
+--- a/drivers/net/wireless/mediatek/mt76/mt7915/main.c
++++ b/drivers/net/wireless/mediatek/mt76/mt7915/main.c
+@@ -253,7 +253,7 @@ static int mt7915_add_interface(struct ieee80211_hw *hw,
+       mvif->sta.wcid.phy_idx = ext_phy;
+       mvif->sta.wcid.hw_key_idx = -1;
+       mvif->sta.wcid.tx_info |= MT_WCID_TX_INFO_SET;
+-      mt76_packet_id_init(&mvif->sta.wcid);
++      mt76_wcid_init(&mvif->sta.wcid);
+       mt7915_mac_wtbl_update(dev, idx,
+                              MT_WTBL_UPDATE_ADM_COUNT_CLEAR);
+@@ -314,7 +314,7 @@ static void mt7915_remove_interface(struct ieee80211_hw *hw,
+               list_del_init(&msta->wcid.poll_list);
+       spin_unlock_bh(&dev->mt76.sta_poll_lock);
+-      mt76_packet_id_flush(&dev->mt76, &msta->wcid);
++      mt76_wcid_cleanup(&dev->mt76, &msta->wcid);
+ }
+ int mt7915_set_channel(struct mt7915_phy *phy)
+diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/main.c b/drivers/net/wireless/mediatek/mt76/mt7921/main.c
+index d8851cb5f400b..6a5c2cae087d0 100644
+--- a/drivers/net/wireless/mediatek/mt76/mt7921/main.c
++++ b/drivers/net/wireless/mediatek/mt76/mt7921/main.c
+@@ -318,7 +318,7 @@ mt7921_add_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif)
+       mvif->sta.wcid.phy_idx = mvif->mt76.band_idx;
+       mvif->sta.wcid.hw_key_idx = -1;
+       mvif->sta.wcid.tx_info |= MT_WCID_TX_INFO_SET;
+-      mt76_packet_id_init(&mvif->sta.wcid);
++      mt76_wcid_init(&mvif->sta.wcid);
+       mt7921_mac_wtbl_update(dev, idx,
+                              MT_WTBL_UPDATE_ADM_COUNT_CLEAR);
+diff --git a/drivers/net/wireless/mediatek/mt76/mt792x_core.c b/drivers/net/wireless/mediatek/mt76/mt792x_core.c
+index 2fb1141e5fa96..66806ed4f942d 100644
+--- a/drivers/net/wireless/mediatek/mt76/mt792x_core.c
++++ b/drivers/net/wireless/mediatek/mt76/mt792x_core.c
+@@ -115,7 +115,7 @@ void mt792x_remove_interface(struct ieee80211_hw *hw,
+               list_del_init(&msta->wcid.poll_list);
+       spin_unlock_bh(&dev->mt76.sta_poll_lock);
+-      mt76_packet_id_flush(&dev->mt76, &msta->wcid);
++      mt76_wcid_cleanup(&dev->mt76, &msta->wcid);
+ }
+ EXPORT_SYMBOL_GPL(mt792x_remove_interface);
+diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/main.c b/drivers/net/wireless/mediatek/mt76/mt7996/main.c
+index 620880e560e00..7fea9f0d409bf 100644
+--- a/drivers/net/wireless/mediatek/mt76/mt7996/main.c
++++ b/drivers/net/wireless/mediatek/mt76/mt7996/main.c
+@@ -207,7 +207,7 @@ static int mt7996_add_interface(struct ieee80211_hw *hw,
+       mvif->sta.wcid.phy_idx = band_idx;
+       mvif->sta.wcid.hw_key_idx = -1;
+       mvif->sta.wcid.tx_info |= MT_WCID_TX_INFO_SET;
+-      mt76_packet_id_init(&mvif->sta.wcid);
++      mt76_wcid_init(&mvif->sta.wcid);
+       mt7996_mac_wtbl_update(dev, idx,
+                              MT_WTBL_UPDATE_ADM_COUNT_CLEAR);
+@@ -268,7 +268,7 @@ static void mt7996_remove_interface(struct ieee80211_hw *hw,
+               list_del_init(&msta->wcid.poll_list);
+       spin_unlock_bh(&dev->mt76.sta_poll_lock);
+-      mt76_packet_id_flush(&dev->mt76, &msta->wcid);
++      mt76_wcid_cleanup(&dev->mt76, &msta->wcid);
+ }
+ int mt7996_set_channel(struct mt7996_phy *phy)
+diff --git a/drivers/net/wireless/mediatek/mt76/tx.c b/drivers/net/wireless/mediatek/mt76/tx.c
+index 6cc26cc6c5178..1809b03292c3d 100644
+--- a/drivers/net/wireless/mediatek/mt76/tx.c
++++ b/drivers/net/wireless/mediatek/mt76/tx.c
+@@ -329,40 +329,32 @@ void
+ mt76_tx(struct mt76_phy *phy, struct ieee80211_sta *sta,
+       struct mt76_wcid *wcid, struct sk_buff *skb)
+ {
+-      struct mt76_dev *dev = phy->dev;
+       struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
+-      struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
+-      struct mt76_queue *q;
+-      int qid = skb_get_queue_mapping(skb);
+       if (mt76_testmode_enabled(phy)) {
+               ieee80211_free_txskb(phy->hw, skb);
+               return;
+       }
+-      if (WARN_ON(qid >= MT_TXQ_PSD)) {
+-              qid = MT_TXQ_BE;
+-              skb_set_queue_mapping(skb, qid);
+-      }
+-
+-      if ((dev->drv->drv_flags & MT_DRV_HW_MGMT_TXQ) &&
+-          !(info->flags & IEEE80211_TX_CTL_HW_80211_ENCAP) &&
+-          !ieee80211_is_data(hdr->frame_control) &&
+-          !ieee80211_is_bufferable_mmpdu(skb)) {
+-              qid = MT_TXQ_PSD;
+-      }
++      if (WARN_ON(skb_get_queue_mapping(skb) >= MT_TXQ_PSD))
++              skb_set_queue_mapping(skb, MT_TXQ_BE);
+       if (wcid && !(wcid->tx_info & MT_WCID_TX_INFO_SET))
+               ieee80211_get_tx_rates(info->control.vif, sta, skb,
+                                      info->control.rates, 1);
+       info->hw_queue |= FIELD_PREP(MT_TX_HW_QUEUE_PHY, phy->band_idx);
+-      q = phy->q_tx[qid];
+-      spin_lock_bh(&q->lock);
+-      __mt76_tx_queue_skb(phy, qid, skb, wcid, sta, NULL);
+-      dev->queue_ops->kick(dev, q);
+-      spin_unlock_bh(&q->lock);
++      spin_lock_bh(&wcid->tx_pending.lock);
++      __skb_queue_tail(&wcid->tx_pending, skb);
++      spin_unlock_bh(&wcid->tx_pending.lock);
++
++      spin_lock_bh(&phy->tx_lock);
++      if (list_empty(&wcid->tx_list))
++              list_add_tail(&wcid->tx_list, &phy->tx_list);
++      spin_unlock_bh(&phy->tx_lock);
++
++      mt76_worker_schedule(&phy->dev->tx_worker);
+ }
+ EXPORT_SYMBOL_GPL(mt76_tx);
+@@ -593,10 +585,86 @@ void mt76_txq_schedule(struct mt76_phy *phy, enum mt76_txq_id qid)
+ }
+ EXPORT_SYMBOL_GPL(mt76_txq_schedule);
++static int
++mt76_txq_schedule_pending_wcid(struct mt76_phy *phy, struct mt76_wcid *wcid)
++{
++      struct mt76_dev *dev = phy->dev;
++      struct ieee80211_sta *sta;
++      struct mt76_queue *q;
++      struct sk_buff *skb;
++      int ret = 0;
++
++      spin_lock(&wcid->tx_pending.lock);
++      while ((skb = skb_peek(&wcid->tx_pending)) != NULL) {
++              struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
++              struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
++              int qid = skb_get_queue_mapping(skb);
++
++              if ((dev->drv->drv_flags & MT_DRV_HW_MGMT_TXQ) &&
++                  !(info->flags & IEEE80211_TX_CTL_HW_80211_ENCAP) &&
++                  !ieee80211_is_data(hdr->frame_control) &&
++                  !ieee80211_is_bufferable_mmpdu(skb))
++                      qid = MT_TXQ_PSD;
++
++              q = phy->q_tx[qid];
++              if (mt76_txq_stopped(q)) {
++                      ret = -1;
++                      break;
++              }
++
++              __skb_unlink(skb, &wcid->tx_pending);
++              spin_unlock(&wcid->tx_pending.lock);
++
++              sta = wcid_to_sta(wcid);
++              spin_lock(&q->lock);
++              __mt76_tx_queue_skb(phy, qid, skb, wcid, sta, NULL);
++              dev->queue_ops->kick(dev, q);
++              spin_unlock(&q->lock);
++
++              spin_lock(&wcid->tx_pending.lock);
++      }
++      spin_unlock(&wcid->tx_pending.lock);
++
++      return ret;
++}
++
++static void mt76_txq_schedule_pending(struct mt76_phy *phy)
++{
++      if (list_empty(&phy->tx_list))
++              return;
++
++      local_bh_disable();
++      rcu_read_lock();
++
++      spin_lock(&phy->tx_lock);
++      while (!list_empty(&phy->tx_list)) {
++              struct mt76_wcid *wcid = NULL;
++              int ret;
++
++              wcid = list_first_entry(&phy->tx_list, struct mt76_wcid, tx_list);
++              list_del_init(&wcid->tx_list);
++
++              spin_unlock(&phy->tx_lock);
++              ret = mt76_txq_schedule_pending_wcid(phy, wcid);
++              spin_lock(&phy->tx_lock);
++
++              if (ret) {
++                      if (list_empty(&wcid->tx_list))
++                              list_add_tail(&wcid->tx_list, &phy->tx_list);
++                      break;
++              }
++      }
++      spin_unlock(&phy->tx_lock);
++
++      rcu_read_unlock();
++      local_bh_enable();
++}
++
+ void mt76_txq_schedule_all(struct mt76_phy *phy)
+ {
+       int i;
++      mt76_txq_schedule_pending(phy);
+       for (i = 0; i <= MT_TXQ_BK; i++)
+               mt76_txq_schedule(phy, i);
+ }
+-- 
+2.43.0
+