]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
6.12-stable patches
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Sun, 15 Dec 2024 07:52:46 +0000 (08:52 +0100)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Sun, 15 Dec 2024 07:52:46 +0000 (08:52 +0100)
added patches:
alsa-hda-realtek-fix-headset-mic-on-acer-nitro-5.patch
alsa-usb-audio-add-implicit-feedback-quirk-for-yamaha-thr5.patch
blk-cgroup-fix-uaf-in-blkcg_unpin_online.patch
block-ignore-req_nowait-for-zone-reset-and-zone-finish-operations.patch
block-prevent-potential-deadlocks-in-zone-write-plug-error-recovery.patch
block-switch-to-using-refcount_t-for-zone-write-plugs.patch
block-use-a-zone-write-plug-bio-work-for-req_nowait-bios.patch
bpf-fix-uaf-via-mismatching-bpf_prog-attachment-rcu-flavors.patch
clk-en7523-fix-wrong-bus-clock-for-en7581.patch
crypto-hisilicon-debugfs-fix-the-struct-pointer-incorrectly-offset-problem.patch
dm-fix-dm-zoned-reclaim-zone-write-pointer-alignment.patch
drm-panic-remove-spurious-empty-line-to-clean-warning.patch
gpio-graniterapids-check-if-gpio-line-can-be-used-for-irqs.patch
gpio-graniterapids-determine-if-gpio-pad-can-be-used-by-driver.patch
gpio-graniterapids-fix-gpio-ack-functionality.patch
gpio-graniterapids-fix-incorrect-bar-assignment.patch
gpio-graniterapids-fix-invalid-gpi_is-register-offset.patch
gpio-graniterapids-fix-invalid-rxevcfg-register-bitmask.patch
gpio-graniterapids-fix-vgpio-driver-crash.patch
gpio-ljca-initialize-num-before-accessing-item-in-ljca_gpio_config.patch
ksmbd-fix-racy-issue-from-session-lookup-and-expire.patch
memcg-slub-fix-sunreclaim-for-post-charged-objects.patch
perf-ftrace-fix-undefined-behavior-in-cmp_profile_data.patch
perf-x86-intel-ds-unconditionally-drain-pebs-ds-when-changing-pebs_data_cfg.patch
riscv-fix-ipis-usage-in-kfence_protect_page.patch
riscv-fix-wrong-usage-of-__pa-on-a-fixmap-address.patch
riscv-mm-do-not-call-pmd-dtor-on-vmemmap-page-table-teardown.patch
sched-deadline-fix-replenish_dl_new_period-dl_server-condition.patch
serial-sh-sci-check-if-tx-data-was-written-to-device-in-.tx_empty.patch
series
spi-rockchip-fix-pm-runtime-count-on-no-op-cs.patch
splice-do-not-checksum-af_unix-sockets.patch
tcp-check-space-before-adding-mptcp-syn-options.patch
usb-core-hcd-only-check-primary-hcd-skip_phy_initialization.patch
usb-host-max3421-hcd-correctly-abort-a-usb-request.patch
usb-misc-onboard_usb_dev-skip-suspend-resume-sequence-for-usb5744-smbus-support.patch
virtio_net-correct-netdev_tx_reset_queue-invocation-point.patch
virtio_net-ensure-netdev_tx_reset_queue-is-called-on-tx-ring-resize.patch
virtio_ring-add-a-func-argument-recycle_done-to-virtqueue_resize.patch

39 files changed:
queue-6.12/alsa-hda-realtek-fix-headset-mic-on-acer-nitro-5.patch [new file with mode: 0644]
queue-6.12/alsa-usb-audio-add-implicit-feedback-quirk-for-yamaha-thr5.patch [new file with mode: 0644]
queue-6.12/blk-cgroup-fix-uaf-in-blkcg_unpin_online.patch [new file with mode: 0644]
queue-6.12/block-ignore-req_nowait-for-zone-reset-and-zone-finish-operations.patch [new file with mode: 0644]
queue-6.12/block-prevent-potential-deadlocks-in-zone-write-plug-error-recovery.patch [new file with mode: 0644]
queue-6.12/block-switch-to-using-refcount_t-for-zone-write-plugs.patch [new file with mode: 0644]
queue-6.12/block-use-a-zone-write-plug-bio-work-for-req_nowait-bios.patch [new file with mode: 0644]
queue-6.12/bpf-fix-uaf-via-mismatching-bpf_prog-attachment-rcu-flavors.patch [new file with mode: 0644]
queue-6.12/clk-en7523-fix-wrong-bus-clock-for-en7581.patch [new file with mode: 0644]
queue-6.12/crypto-hisilicon-debugfs-fix-the-struct-pointer-incorrectly-offset-problem.patch [new file with mode: 0644]
queue-6.12/dm-fix-dm-zoned-reclaim-zone-write-pointer-alignment.patch [new file with mode: 0644]
queue-6.12/drm-panic-remove-spurious-empty-line-to-clean-warning.patch [new file with mode: 0644]
queue-6.12/gpio-graniterapids-check-if-gpio-line-can-be-used-for-irqs.patch [new file with mode: 0644]
queue-6.12/gpio-graniterapids-determine-if-gpio-pad-can-be-used-by-driver.patch [new file with mode: 0644]
queue-6.12/gpio-graniterapids-fix-gpio-ack-functionality.patch [new file with mode: 0644]
queue-6.12/gpio-graniterapids-fix-incorrect-bar-assignment.patch [new file with mode: 0644]
queue-6.12/gpio-graniterapids-fix-invalid-gpi_is-register-offset.patch [new file with mode: 0644]
queue-6.12/gpio-graniterapids-fix-invalid-rxevcfg-register-bitmask.patch [new file with mode: 0644]
queue-6.12/gpio-graniterapids-fix-vgpio-driver-crash.patch [new file with mode: 0644]
queue-6.12/gpio-ljca-initialize-num-before-accessing-item-in-ljca_gpio_config.patch [new file with mode: 0644]
queue-6.12/ksmbd-fix-racy-issue-from-session-lookup-and-expire.patch [new file with mode: 0644]
queue-6.12/memcg-slub-fix-sunreclaim-for-post-charged-objects.patch [new file with mode: 0644]
queue-6.12/perf-ftrace-fix-undefined-behavior-in-cmp_profile_data.patch [new file with mode: 0644]
queue-6.12/perf-x86-intel-ds-unconditionally-drain-pebs-ds-when-changing-pebs_data_cfg.patch [new file with mode: 0644]
queue-6.12/riscv-fix-ipis-usage-in-kfence_protect_page.patch [new file with mode: 0644]
queue-6.12/riscv-fix-wrong-usage-of-__pa-on-a-fixmap-address.patch [new file with mode: 0644]
queue-6.12/riscv-mm-do-not-call-pmd-dtor-on-vmemmap-page-table-teardown.patch [new file with mode: 0644]
queue-6.12/sched-deadline-fix-replenish_dl_new_period-dl_server-condition.patch [new file with mode: 0644]
queue-6.12/serial-sh-sci-check-if-tx-data-was-written-to-device-in-.tx_empty.patch [new file with mode: 0644]
queue-6.12/series [new file with mode: 0644]
queue-6.12/spi-rockchip-fix-pm-runtime-count-on-no-op-cs.patch [new file with mode: 0644]
queue-6.12/splice-do-not-checksum-af_unix-sockets.patch [new file with mode: 0644]
queue-6.12/tcp-check-space-before-adding-mptcp-syn-options.patch [new file with mode: 0644]
queue-6.12/usb-core-hcd-only-check-primary-hcd-skip_phy_initialization.patch [new file with mode: 0644]
queue-6.12/usb-host-max3421-hcd-correctly-abort-a-usb-request.patch [new file with mode: 0644]
queue-6.12/usb-misc-onboard_usb_dev-skip-suspend-resume-sequence-for-usb5744-smbus-support.patch [new file with mode: 0644]
queue-6.12/virtio_net-correct-netdev_tx_reset_queue-invocation-point.patch [new file with mode: 0644]
queue-6.12/virtio_net-ensure-netdev_tx_reset_queue-is-called-on-tx-ring-resize.patch [new file with mode: 0644]
queue-6.12/virtio_ring-add-a-func-argument-recycle_done-to-virtqueue_resize.patch [new file with mode: 0644]

diff --git a/queue-6.12/alsa-hda-realtek-fix-headset-mic-on-acer-nitro-5.patch b/queue-6.12/alsa-hda-realtek-fix-headset-mic-on-acer-nitro-5.patch
new file mode 100644 (file)
index 0000000..6fbc045
--- /dev/null
@@ -0,0 +1,31 @@
+From 5a69e3d0a1b0f07e58c353560cfcb1ea20a6f040 Mon Sep 17 00:00:00 2001
+From: Hridesh MG <hridesh699@gmail.com>
+Date: Thu, 5 Dec 2024 22:48:42 +0530
+Subject: ALSA: hda/realtek: Fix headset mic on Acer Nitro 5
+
+From: Hridesh MG <hridesh699@gmail.com>
+
+commit 5a69e3d0a1b0f07e58c353560cfcb1ea20a6f040 upstream.
+
+Add a PCI quirk to enable microphone input on the headphone jack on
+the Acer Nitro 5 AN515-58 laptop.
+
+Signed-off-by: Hridesh MG <hridesh699@gmail.com>
+Cc: <stable@vger.kernel.org>
+Link: https://patch.msgid.link/20241205171843.7787-1-hridesh699@gmail.com
+Signed-off-by: Takashi Iwai <tiwai@suse.de>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ sound/pci/hda/patch_realtek.c |    1 +
+ 1 file changed, 1 insertion(+)
+
+--- a/sound/pci/hda/patch_realtek.c
++++ b/sound/pci/hda/patch_realtek.c
+@@ -10127,6 +10127,7 @@ static const struct hda_quirk alc269_fix
+       SND_PCI_QUIRK(0x1025, 0x1430, "Acer TravelMate B311R-31", ALC256_FIXUP_ACER_MIC_NO_PRESENCE),
+       SND_PCI_QUIRK(0x1025, 0x1466, "Acer Aspire A515-56", ALC255_FIXUP_ACER_HEADPHONE_AND_MIC),
+       SND_PCI_QUIRK(0x1025, 0x1534, "Acer Predator PH315-54", ALC255_FIXUP_ACER_MIC_NO_PRESENCE),
++      SND_PCI_QUIRK(0x1025, 0x159c, "Acer Nitro 5 AN515-58", ALC2XX_FIXUP_HEADSET_MIC),
+       SND_PCI_QUIRK(0x1025, 0x169a, "Acer Swift SFG16", ALC256_FIXUP_ACER_SFG16_MICMUTE_LED),
+       SND_PCI_QUIRK(0x1028, 0x0470, "Dell M101z", ALC269_FIXUP_DELL_M101Z),
+       SND_PCI_QUIRK(0x1028, 0x053c, "Dell Latitude E5430", ALC292_FIXUP_DELL_E7X),
diff --git a/queue-6.12/alsa-usb-audio-add-implicit-feedback-quirk-for-yamaha-thr5.patch b/queue-6.12/alsa-usb-audio-add-implicit-feedback-quirk-for-yamaha-thr5.patch
new file mode 100644 (file)
index 0000000..43f16e5
--- /dev/null
@@ -0,0 +1,33 @@
+From 82fdcf9b518b205da040046fbe7747fb3fd18657 Mon Sep 17 00:00:00 2001
+From: Jaakko Salo <jaakkos@gmail.com>
+Date: Fri, 6 Dec 2024 18:44:48 +0200
+Subject: ALSA: usb-audio: Add implicit feedback quirk for Yamaha THR5
+
+From: Jaakko Salo <jaakkos@gmail.com>
+
+commit 82fdcf9b518b205da040046fbe7747fb3fd18657 upstream.
+
+Use implicit feedback from the capture endpoint to fix popping
+sounds during playback.
+
+Link: https://bugzilla.kernel.org/show_bug.cgi?id=219567
+Signed-off-by: Jaakko Salo <jaakkos@gmail.com>
+Cc: <stable@vger.kernel.org>
+Link: https://patch.msgid.link/20241206164448.8136-1-jaakkos@gmail.com
+Signed-off-by: Takashi Iwai <tiwai@suse.de>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ sound/usb/quirks.c |    2 ++
+ 1 file changed, 2 insertions(+)
+
+--- a/sound/usb/quirks.c
++++ b/sound/usb/quirks.c
+@@ -2179,6 +2179,8 @@ static const struct usb_audio_quirk_flag
+                  QUIRK_FLAG_CTL_MSG_DELAY_1M | QUIRK_FLAG_MIC_RES_384),
+       DEVICE_FLG(0x046d, 0x09a4, /* Logitech QuickCam E 3500 */
+                  QUIRK_FLAG_CTL_MSG_DELAY_1M | QUIRK_FLAG_IGNORE_CTL_ERROR),
++      DEVICE_FLG(0x0499, 0x1506, /* Yamaha THR5 */
++                 QUIRK_FLAG_GENERIC_IMPLICIT_FB),
+       DEVICE_FLG(0x0499, 0x1509, /* Steinberg UR22 */
+                  QUIRK_FLAG_GENERIC_IMPLICIT_FB),
+       DEVICE_FLG(0x0499, 0x3108, /* Yamaha YIT-W12TX */
diff --git a/queue-6.12/blk-cgroup-fix-uaf-in-blkcg_unpin_online.patch b/queue-6.12/blk-cgroup-fix-uaf-in-blkcg_unpin_online.patch
new file mode 100644 (file)
index 0000000..2b100c5
--- /dev/null
@@ -0,0 +1,82 @@
+From 86e6ca55b83c575ab0f2e105cf08f98e58d3d7af Mon Sep 17 00:00:00 2001
+From: Tejun Heo <tj@kernel.org>
+Date: Fri, 6 Dec 2024 07:59:51 -1000
+Subject: blk-cgroup: Fix UAF in blkcg_unpin_online()
+
+From: Tejun Heo <tj@kernel.org>
+
+commit 86e6ca55b83c575ab0f2e105cf08f98e58d3d7af upstream.
+
+blkcg_unpin_online() walks up the blkcg hierarchy putting the online pin. To
+walk up, it uses blkcg_parent(blkcg) but it was calling that after
+blkcg_destroy_blkgs(blkcg) which could free the blkcg, leading to the
+following UAF:
+
+  ==================================================================
+  BUG: KASAN: slab-use-after-free in blkcg_unpin_online+0x15a/0x270
+  Read of size 8 at addr ffff8881057678c0 by task kworker/9:1/117
+
+  CPU: 9 UID: 0 PID: 117 Comm: kworker/9:1 Not tainted 6.13.0-rc1-work-00182-gb8f52214c61a-dirty #48
+  Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS unknown 02/02/2022
+  Workqueue: cgwb_release cgwb_release_workfn
+  Call Trace:
+   <TASK>
+   dump_stack_lvl+0x27/0x80
+   print_report+0x151/0x710
+   kasan_report+0xc0/0x100
+   blkcg_unpin_online+0x15a/0x270
+   cgwb_release_workfn+0x194/0x480
+   process_scheduled_works+0x71b/0xe20
+   worker_thread+0x82a/0xbd0
+   kthread+0x242/0x2c0
+   ret_from_fork+0x33/0x70
+   ret_from_fork_asm+0x1a/0x30
+   </TASK>
+  ...
+  Freed by task 1944:
+   kasan_save_track+0x2b/0x70
+   kasan_save_free_info+0x3c/0x50
+   __kasan_slab_free+0x33/0x50
+   kfree+0x10c/0x330
+   css_free_rwork_fn+0xe6/0xb30
+   process_scheduled_works+0x71b/0xe20
+   worker_thread+0x82a/0xbd0
+   kthread+0x242/0x2c0
+   ret_from_fork+0x33/0x70
+   ret_from_fork_asm+0x1a/0x30
+
+Note that the UAF is not easy to trigger as the free path is indirected
+behind a couple RCU grace periods and a work item execution. I could only
+trigger it with artifical msleep() injected in blkcg_unpin_online().
+
+Fix it by reading the parent pointer before destroying the blkcg's blkg's.
+
+Signed-off-by: Tejun Heo <tj@kernel.org>
+Reported-by: Abagail ren <renzezhongucas@gmail.com>
+Suggested-by: Linus Torvalds <torvalds@linuxfoundation.org>
+Fixes: 4308a434e5e0 ("blkcg: don't offline parent blkcg first")
+Cc: stable@vger.kernel.org # v5.7+
+Signed-off-by: Jens Axboe <axboe@kernel.dk>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ block/blk-cgroup.c |    6 +++++-
+ 1 file changed, 5 insertions(+), 1 deletion(-)
+
+--- a/block/blk-cgroup.c
++++ b/block/blk-cgroup.c
+@@ -1324,10 +1324,14 @@ void blkcg_unpin_online(struct cgroup_su
+       struct blkcg *blkcg = css_to_blkcg(blkcg_css);
+       do {
++              struct blkcg *parent;
++
+               if (!refcount_dec_and_test(&blkcg->online_pin))
+                       break;
++
++              parent = blkcg_parent(blkcg);
+               blkcg_destroy_blkgs(blkcg);
+-              blkcg = blkcg_parent(blkcg);
++              blkcg = parent;
+       } while (blkcg);
+ }
diff --git a/queue-6.12/block-ignore-req_nowait-for-zone-reset-and-zone-finish-operations.patch b/queue-6.12/block-ignore-req_nowait-for-zone-reset-and-zone-finish-operations.patch
new file mode 100644 (file)
index 0000000..960ba0e
--- /dev/null
@@ -0,0 +1,47 @@
+From 5eb3317aa5a2ffe4574ab1a12cf9bc9447ca26c0 Mon Sep 17 00:00:00 2001
+From: Damien Le Moal <dlemoal@kernel.org>
+Date: Mon, 9 Dec 2024 21:23:55 +0900
+Subject: block: Ignore REQ_NOWAIT for zone reset and zone finish operations
+
+From: Damien Le Moal <dlemoal@kernel.org>
+
+commit 5eb3317aa5a2ffe4574ab1a12cf9bc9447ca26c0 upstream.
+
+There are currently any issuer of REQ_OP_ZONE_RESET and
+REQ_OP_ZONE_FINISH operations that set REQ_NOWAIT. However, as we cannot
+handle this flag correctly due to the potential request allocation
+failure that may happen in blk_mq_submit_bio() after blk_zone_plug_bio()
+has handled the zone write plug write pointer updates for the targeted
+zones, modify blk_zone_wplug_handle_reset_or_finish() to warn if this
+flag is set and ignore it.
+
+Fixes: dd291d77cc90 ("block: Introduce zone write plugging")
+Cc: stable@vger.kernel.org
+Signed-off-by: Damien Le Moal <dlemoal@kernel.org>
+Reviewed-by: Christoph Hellwig <hch@lst.de>
+Reviewed-by: Martin K. Petersen <martin.petersen@oracle.com>
+Link: https://lore.kernel.org/r/20241209122357.47838-3-dlemoal@kernel.org
+Signed-off-by: Jens Axboe <axboe@kernel.dk>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ block/blk-zoned.c |    9 +++++++++
+ 1 file changed, 9 insertions(+)
+
+--- a/block/blk-zoned.c
++++ b/block/blk-zoned.c
+@@ -704,6 +704,15 @@ static bool blk_zone_wplug_handle_reset_
+       }
+       /*
++       * No-wait reset or finish BIOs do not make much sense as the callers
++       * issue these as blocking operations in most cases. To avoid issues
++       * the BIO execution potentially failing with BLK_STS_AGAIN, warn about
++       * REQ_NOWAIT being set and ignore that flag.
++       */
++      if (WARN_ON_ONCE(bio->bi_opf & REQ_NOWAIT))
++              bio->bi_opf &= ~REQ_NOWAIT;
++
++      /*
+        * If we have a zone write plug, set its write pointer offset to 0
+        * (reset case) or to the zone size (finish case). This will abort all
+        * BIOs plugged for the target zone. It is fine as resetting or
diff --git a/queue-6.12/block-prevent-potential-deadlocks-in-zone-write-plug-error-recovery.patch b/queue-6.12/block-prevent-potential-deadlocks-in-zone-write-plug-error-recovery.patch
new file mode 100644 (file)
index 0000000..2814c90
--- /dev/null
@@ -0,0 +1,638 @@
+From fe0418eb9bd69a19a948b297c8de815e05f3cde1 Mon Sep 17 00:00:00 2001
+From: Damien Le Moal <dlemoal@kernel.org>
+Date: Mon, 9 Dec 2024 21:23:57 +0900
+Subject: block: Prevent potential deadlocks in zone write plug error recovery
+
+From: Damien Le Moal <dlemoal@kernel.org>
+
+commit fe0418eb9bd69a19a948b297c8de815e05f3cde1 upstream.
+
+Zone write plugging for handling writes to zones of a zoned block
+device always execute a zone report whenever a write BIO to a zone
+fails. The intent of this is to ensure that the tracking of a zone write
+pointer is always correct to ensure that the alignment to a zone write
+pointer of write BIOs can be checked on submission and that we can
+always correctly emulate zone append operations using regular write
+BIOs.
+
+However, this error recovery scheme introduces a potential deadlock if a
+device queue freeze is initiated while BIOs are still plugged in a zone
+write plug and one of these write operation fails. In such case, the
+disk zone write plug error recovery work is scheduled and executes a
+report zone. This in turn can result in a request allocation in the
+underlying driver to issue the report zones command to the device. But
+with the device queue freeze already started, this allocation will
+block, preventing the report zone execution and the continuation of the
+processing of the plugged BIOs. As plugged BIOs hold a queue usage
+reference, the queue freeze itself will never complete, resulting in a
+deadlock.
+
+Avoid this problem by completely removing from the zone write plugging
+code the use of report zones operations after a failed write operation,
+instead relying on the device user to either execute a report zones,
+reset the zone, finish the zone, or give up writing to the device (which
+is a fairly common pattern for file systems which degrade to read-only
+after write failures). This is not an unreasonnable requirement as all
+well-behaved applications, FSes and device mapper already use report
+zones to recover from write errors whenever possible by comparing the
+current position of a zone write pointer with what their assumption
+about the position is.
+
+The changes to remove the automatic error recovery are as follows:
+ - Completely remove the error recovery work and its associated
+   resources (zone write plug list head, disk error list, and disk
+   zone_wplugs_work work struct). This also removes the functions
+   disk_zone_wplug_set_error() and disk_zone_wplug_clear_error().
+
+ - Change the BLK_ZONE_WPLUG_ERROR zone write plug flag into
+   BLK_ZONE_WPLUG_NEED_WP_UPDATE. This new flag is set for a zone write
+   plug whenever a write opration targetting the zone of the zone write
+   plug fails. This flag indicates that the zone write pointer offset is
+   not reliable and that it must be updated when the next report zone,
+   reset zone, finish zone or disk revalidation is executed.
+
+ - Modify blk_zone_write_plug_bio_endio() to set the
+   BLK_ZONE_WPLUG_NEED_WP_UPDATE flag for the target zone of a failed
+   write BIO.
+
+ - Modify the function disk_zone_wplug_set_wp_offset() to clear this
+   new flag, thus implementing recovery of a correct write pointer
+   offset with the reset (all) zone and finish zone operations.
+
+ - Modify blkdev_report_zones() to always use the disk_report_zones_cb()
+   callback so that disk_zone_wplug_sync_wp_offset() can be called for
+   any zone marked with the BLK_ZONE_WPLUG_NEED_WP_UPDATE flag.
+   This implements recovery of a correct write pointer offset for zone
+   write plugs marked with BLK_ZONE_WPLUG_NEED_WP_UPDATE and within
+   the range of the report zones operation executed by the user.
+
+ - Modify blk_revalidate_seq_zone() to call
+   disk_zone_wplug_sync_wp_offset() for all sequential write required
+   zones when a zoned block device is revalidated, thus always resolving
+   any inconsistency between the write pointer offset of zone write
+   plugs and the actual write pointer position of sequential zones.
+
+Fixes: dd291d77cc90 ("block: Introduce zone write plugging")
+Cc: stable@vger.kernel.org
+Signed-off-by: Damien Le Moal <dlemoal@kernel.org>
+Reviewed-by: Christoph Hellwig <hch@lst.de>
+Reviewed-by: Martin K. Petersen <martin.petersen@oracle.com>
+Link: https://lore.kernel.org/r/20241209122357.47838-5-dlemoal@kernel.org
+Signed-off-by: Jens Axboe <axboe@kernel.dk>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ block/blk-zoned.c      |  308 +++++++++----------------------------------------
+ include/linux/blkdev.h |    2 
+ 2 files changed, 61 insertions(+), 249 deletions(-)
+
+--- a/block/blk-zoned.c
++++ b/block/blk-zoned.c
+@@ -41,7 +41,6 @@ static const char *const zone_cond_name[
+ /*
+  * Per-zone write plug.
+  * @node: hlist_node structure for managing the plug using a hash table.
+- * @link: To list the plug in the zone write plug error list of the disk.
+  * @ref: Zone write plug reference counter. A zone write plug reference is
+  *       always at least 1 when the plug is hashed in the disk plug hash table.
+  *       The reference is incremented whenever a new BIO needing plugging is
+@@ -63,7 +62,6 @@ static const char *const zone_cond_name[
+  */
+ struct blk_zone_wplug {
+       struct hlist_node       node;
+-      struct list_head        link;
+       refcount_t              ref;
+       spinlock_t              lock;
+       unsigned int            flags;
+@@ -80,8 +78,8 @@ struct blk_zone_wplug {
+  *  - BLK_ZONE_WPLUG_PLUGGED: Indicates that the zone write plug is plugged,
+  *    that is, that write BIOs are being throttled due to a write BIO already
+  *    being executed or the zone write plug bio list is not empty.
+- *  - BLK_ZONE_WPLUG_ERROR: Indicates that a write error happened which will be
+- *    recovered with a report zone to update the zone write pointer offset.
++ *  - BLK_ZONE_WPLUG_NEED_WP_UPDATE: Indicates that we lost track of a zone
++ *    write pointer offset and need to update it.
+  *  - BLK_ZONE_WPLUG_UNHASHED: Indicates that the zone write plug was removed
+  *    from the disk hash table and that the initial reference to the zone
+  *    write plug set when the plug was first added to the hash table has been
+@@ -91,11 +89,9 @@ struct blk_zone_wplug {
+  *    freed once all remaining references from BIOs or functions are dropped.
+  */
+ #define BLK_ZONE_WPLUG_PLUGGED                (1U << 0)
+-#define BLK_ZONE_WPLUG_ERROR          (1U << 1)
++#define BLK_ZONE_WPLUG_NEED_WP_UPDATE (1U << 1)
+ #define BLK_ZONE_WPLUG_UNHASHED               (1U << 2)
+-#define BLK_ZONE_WPLUG_BUSY   (BLK_ZONE_WPLUG_PLUGGED | BLK_ZONE_WPLUG_ERROR)
+-
+ /**
+  * blk_zone_cond_str - Return string XXX in BLK_ZONE_COND_XXX.
+  * @zone_cond: BLK_ZONE_COND_XXX.
+@@ -163,6 +159,11 @@ int blkdev_report_zones(struct block_dev
+ {
+       struct gendisk *disk = bdev->bd_disk;
+       sector_t capacity = get_capacity(disk);
++      struct disk_report_zones_cb_args args = {
++              .disk = disk,
++              .user_cb = cb,
++              .user_data = data,
++      };
+       if (!bdev_is_zoned(bdev) || WARN_ON_ONCE(!disk->fops->report_zones))
+               return -EOPNOTSUPP;
+@@ -170,7 +171,8 @@ int blkdev_report_zones(struct block_dev
+       if (!nr_zones || sector >= capacity)
+               return 0;
+-      return disk->fops->report_zones(disk, sector, nr_zones, cb, data);
++      return disk->fops->report_zones(disk, sector, nr_zones,
++                                      disk_report_zones_cb, &args);
+ }
+ EXPORT_SYMBOL_GPL(blkdev_report_zones);
+@@ -464,7 +466,7 @@ static inline void disk_put_zone_wplug(s
+ {
+       if (refcount_dec_and_test(&zwplug->ref)) {
+               WARN_ON_ONCE(!bio_list_empty(&zwplug->bio_list));
+-              WARN_ON_ONCE(!list_empty(&zwplug->link));
++              WARN_ON_ONCE(zwplug->flags & BLK_ZONE_WPLUG_PLUGGED);
+               WARN_ON_ONCE(!(zwplug->flags & BLK_ZONE_WPLUG_UNHASHED));
+               call_rcu(&zwplug->rcu_head, disk_free_zone_wplug_rcu);
+@@ -478,8 +480,8 @@ static inline bool disk_should_remove_zo
+       if (zwplug->flags & BLK_ZONE_WPLUG_UNHASHED)
+               return false;
+-      /* If the zone write plug is still busy, it cannot be removed. */
+-      if (zwplug->flags & BLK_ZONE_WPLUG_BUSY)
++      /* If the zone write plug is still plugged, it cannot be removed. */
++      if (zwplug->flags & BLK_ZONE_WPLUG_PLUGGED)
+               return false;
+       /*
+@@ -562,7 +564,6 @@ again:
+               return NULL;
+       INIT_HLIST_NODE(&zwplug->node);
+-      INIT_LIST_HEAD(&zwplug->link);
+       refcount_set(&zwplug->ref, 2);
+       spin_lock_init(&zwplug->lock);
+       zwplug->flags = 0;
+@@ -611,124 +612,29 @@ static void disk_zone_wplug_abort(struct
+ }
+ /*
+- * Abort (fail) all plugged BIOs of a zone write plug that are not aligned
+- * with the assumed write pointer location of the zone when the BIO will
+- * be unplugged.
+- */
+-static void disk_zone_wplug_abort_unaligned(struct gendisk *disk,
+-                                          struct blk_zone_wplug *zwplug)
+-{
+-      unsigned int wp_offset = zwplug->wp_offset;
+-      struct bio_list bl = BIO_EMPTY_LIST;
+-      struct bio *bio;
+-
+-      while ((bio = bio_list_pop(&zwplug->bio_list))) {
+-              if (disk_zone_is_full(disk, zwplug->zone_no, wp_offset) ||
+-                  (bio_op(bio) != REQ_OP_ZONE_APPEND &&
+-                   bio_offset_from_zone_start(bio) != wp_offset)) {
+-                      blk_zone_wplug_bio_io_error(zwplug, bio);
+-                      continue;
+-              }
+-
+-              wp_offset += bio_sectors(bio);
+-              bio_list_add(&bl, bio);
+-      }
+-
+-      bio_list_merge(&zwplug->bio_list, &bl);
+-}
+-
+-static inline void disk_zone_wplug_set_error(struct gendisk *disk,
+-                                           struct blk_zone_wplug *zwplug)
+-{
+-      unsigned long flags;
+-
+-      if (zwplug->flags & BLK_ZONE_WPLUG_ERROR)
+-              return;
+-
+-      /*
+-       * At this point, we already have a reference on the zone write plug.
+-       * However, since we are going to add the plug to the disk zone write
+-       * plugs work list, increase its reference count. This reference will
+-       * be dropped in disk_zone_wplugs_work() once the error state is
+-       * handled, or in disk_zone_wplug_clear_error() if the zone is reset or
+-       * finished.
+-       */
+-      zwplug->flags |= BLK_ZONE_WPLUG_ERROR;
+-      refcount_inc(&zwplug->ref);
+-
+-      spin_lock_irqsave(&disk->zone_wplugs_lock, flags);
+-      list_add_tail(&zwplug->link, &disk->zone_wplugs_err_list);
+-      spin_unlock_irqrestore(&disk->zone_wplugs_lock, flags);
+-}
+-
+-static inline void disk_zone_wplug_clear_error(struct gendisk *disk,
+-                                             struct blk_zone_wplug *zwplug)
+-{
+-      unsigned long flags;
+-
+-      if (!(zwplug->flags & BLK_ZONE_WPLUG_ERROR))
+-              return;
+-
+-      /*
+-       * We are racing with the error handling work which drops the reference
+-       * on the zone write plug after handling the error state. So remove the
+-       * plug from the error list and drop its reference count only if the
+-       * error handling has not yet started, that is, if the zone write plug
+-       * is still listed.
+-       */
+-      spin_lock_irqsave(&disk->zone_wplugs_lock, flags);
+-      if (!list_empty(&zwplug->link)) {
+-              list_del_init(&zwplug->link);
+-              zwplug->flags &= ~BLK_ZONE_WPLUG_ERROR;
+-              disk_put_zone_wplug(zwplug);
+-      }
+-      spin_unlock_irqrestore(&disk->zone_wplugs_lock, flags);
+-}
+-
+-/*
+- * Set a zone write plug write pointer offset to either 0 (zone reset case)
+- * or to the zone size (zone finish case). This aborts all plugged BIOs, which
+- * is fine to do as doing a zone reset or zone finish while writes are in-flight
+- * is a mistake from the user which will most likely cause all plugged BIOs to
+- * fail anyway.
++ * Set a zone write plug write pointer offset to the specified value.
++ * This aborts all plugged BIOs, which is fine as this function is called for
++ * a zone reset operation, a zone finish operation or if the zone needs a wp
++ * update from a report zone after a write error.
+  */
+ static void disk_zone_wplug_set_wp_offset(struct gendisk *disk,
+                                         struct blk_zone_wplug *zwplug,
+                                         unsigned int wp_offset)
+ {
+-      unsigned long flags;
+-
+-      spin_lock_irqsave(&zwplug->lock, flags);
+-
+-      /*
+-       * Make sure that a BIO completion or another zone reset or finish
+-       * operation has not already removed the plug from the hash table.
+-       */
+-      if (zwplug->flags & BLK_ZONE_WPLUG_UNHASHED) {
+-              spin_unlock_irqrestore(&zwplug->lock, flags);
+-              return;
+-      }
++      lockdep_assert_held(&zwplug->lock);
+       /* Update the zone write pointer and abort all plugged BIOs. */
++      zwplug->flags &= ~BLK_ZONE_WPLUG_NEED_WP_UPDATE;
+       zwplug->wp_offset = wp_offset;
+       disk_zone_wplug_abort(zwplug);
+       /*
+-       * Updating the write pointer offset puts back the zone
+-       * in a good state. So clear the error flag and decrement the
+-       * error count if we were in error state.
+-       */
+-      disk_zone_wplug_clear_error(disk, zwplug);
+-
+-      /*
+        * The zone write plug now has no BIO plugged: remove it from the
+        * hash table so that it cannot be seen. The plug will be freed
+        * when the last reference is dropped.
+        */
+       if (disk_should_remove_zone_wplug(disk, zwplug))
+               disk_remove_zone_wplug(disk, zwplug);
+-
+-      spin_unlock_irqrestore(&zwplug->lock, flags);
+ }
+ static unsigned int blk_zone_wp_offset(struct blk_zone *zone)
+@@ -765,7 +671,7 @@ static void disk_zone_wplug_sync_wp_offs
+               return;
+       spin_lock_irqsave(&zwplug->lock, flags);
+-      if (zwplug->flags & BLK_ZONE_WPLUG_ERROR)
++      if (zwplug->flags & BLK_ZONE_WPLUG_NEED_WP_UPDATE)
+               disk_zone_wplug_set_wp_offset(disk, zwplug,
+                                             blk_zone_wp_offset(zone));
+       spin_unlock_irqrestore(&zwplug->lock, flags);
+@@ -789,6 +695,7 @@ static bool blk_zone_wplug_handle_reset_
+       struct gendisk *disk = bio->bi_bdev->bd_disk;
+       sector_t sector = bio->bi_iter.bi_sector;
+       struct blk_zone_wplug *zwplug;
++      unsigned long flags;
+       /* Conventional zones cannot be reset nor finished. */
+       if (disk_zone_is_conv(disk, sector)) {
+@@ -805,7 +712,9 @@ static bool blk_zone_wplug_handle_reset_
+        */
+       zwplug = disk_get_zone_wplug(disk, sector);
+       if (zwplug) {
++              spin_lock_irqsave(&zwplug->lock, flags);
+               disk_zone_wplug_set_wp_offset(disk, zwplug, wp_offset);
++              spin_unlock_irqrestore(&zwplug->lock, flags);
+               disk_put_zone_wplug(zwplug);
+       }
+@@ -816,6 +725,7 @@ static bool blk_zone_wplug_handle_reset_
+ {
+       struct gendisk *disk = bio->bi_bdev->bd_disk;
+       struct blk_zone_wplug *zwplug;
++      unsigned long flags;
+       sector_t sector;
+       /*
+@@ -827,7 +737,9 @@ static bool blk_zone_wplug_handle_reset_
+            sector += disk->queue->limits.chunk_sectors) {
+               zwplug = disk_get_zone_wplug(disk, sector);
+               if (zwplug) {
++                      spin_lock_irqsave(&zwplug->lock, flags);
+                       disk_zone_wplug_set_wp_offset(disk, zwplug, 0);
++                      spin_unlock_irqrestore(&zwplug->lock, flags);
+                       disk_put_zone_wplug(zwplug);
+               }
+       }
+@@ -1010,12 +922,22 @@ static bool blk_zone_wplug_prepare_bio(s
+       struct gendisk *disk = bio->bi_bdev->bd_disk;
+       /*
++       * If we lost track of the zone write pointer due to a write error,
++       * the user must either execute a report zones, reset the zone or finish
++       * the to recover a reliable write pointer position. Fail BIOs if the
++       * user did not do that as we cannot handle emulated zone append
++       * otherwise.
++       */
++      if (zwplug->flags & BLK_ZONE_WPLUG_NEED_WP_UPDATE)
++              return false;
++
++      /*
+        * Check that the user is not attempting to write to a full zone.
+        * We know such BIO will fail, and that would potentially overflow our
+        * write pointer offset beyond the end of the zone.
+        */
+       if (disk_zone_wplug_is_full(disk, zwplug))
+-              goto err;
++              return false;
+       if (bio_op(bio) == REQ_OP_ZONE_APPEND) {
+               /*
+@@ -1034,24 +956,18 @@ static bool blk_zone_wplug_prepare_bio(s
+               bio_set_flag(bio, BIO_EMULATES_ZONE_APPEND);
+       } else {
+               /*
+-               * Check for non-sequential writes early because we avoid a
+-               * whole lot of error handling trouble if we don't send it off
+-               * to the driver.
++               * Check for non-sequential writes early as we know that BIOs
++               * with a start sector not unaligned to the zone write pointer
++               * will fail.
+                */
+               if (bio_offset_from_zone_start(bio) != zwplug->wp_offset)
+-                      goto err;
++                      return false;
+       }
+       /* Advance the zone write pointer offset. */
+       zwplug->wp_offset += bio_sectors(bio);
+       return true;
+-
+-err:
+-      /* We detected an invalid write BIO: schedule error recovery. */
+-      disk_zone_wplug_set_error(disk, zwplug);
+-      kblockd_schedule_work(&disk->zone_wplugs_work);
+-      return false;
+ }
+ static bool blk_zone_wplug_handle_write(struct bio *bio, unsigned int nr_segs)
+@@ -1101,20 +1017,20 @@ static bool blk_zone_wplug_handle_write(
+       bio_set_flag(bio, BIO_ZONE_WRITE_PLUGGING);
+       /*
+-       * If the zone is already plugged or has a pending error, add the BIO
+-       * to the plug BIO list. Do the same for REQ_NOWAIT BIOs to ensure that
+-       * we will not see a BLK_STS_AGAIN failure if we let the BIO execute.
++       * If the zone is already plugged, add the BIO to the plug BIO list.
++       * Do the same for REQ_NOWAIT BIOs to ensure that we will not see a
++       * BLK_STS_AGAIN failure if we let the BIO execute.
+        * Otherwise, plug and let the BIO execute.
+        */
+-      if (zwplug->flags & BLK_ZONE_WPLUG_BUSY || (bio->bi_opf & REQ_NOWAIT))
++      if ((zwplug->flags & BLK_ZONE_WPLUG_PLUGGED) ||
++          (bio->bi_opf & REQ_NOWAIT))
+               goto plug;
+-      /*
+-       * If an error is detected when preparing the BIO, add it to the BIO
+-       * list so that error recovery can deal with it.
+-       */
+-      if (!blk_zone_wplug_prepare_bio(zwplug, bio))
+-              goto plug;
++      if (!blk_zone_wplug_prepare_bio(zwplug, bio)) {
++              spin_unlock_irqrestore(&zwplug->lock, flags);
++              bio_io_error(bio);
++              return true;
++      }
+       zwplug->flags |= BLK_ZONE_WPLUG_PLUGGED;
+@@ -1214,16 +1130,6 @@ static void disk_zone_wplug_unplug_bio(s
+       spin_lock_irqsave(&zwplug->lock, flags);
+-      /*
+-       * If we had an error, schedule error recovery. The recovery work
+-       * will restart submission of plugged BIOs.
+-       */
+-      if (zwplug->flags & BLK_ZONE_WPLUG_ERROR) {
+-              spin_unlock_irqrestore(&zwplug->lock, flags);
+-              kblockd_schedule_work(&disk->zone_wplugs_work);
+-              return;
+-      }
+-
+       /* Schedule submission of the next plugged BIO if we have one. */
+       if (!bio_list_empty(&zwplug->bio_list)) {
+               disk_zone_wplug_schedule_bio_work(disk, zwplug);
+@@ -1266,12 +1172,13 @@ void blk_zone_write_plug_bio_endio(struc
+       }
+       /*
+-       * If the BIO failed, mark the plug as having an error to trigger
+-       * recovery.
++       * If the BIO failed, abort all plugged BIOs and mark the plug as
++       * needing a write pointer update.
+        */
+       if (bio->bi_status != BLK_STS_OK) {
+               spin_lock_irqsave(&zwplug->lock, flags);
+-              disk_zone_wplug_set_error(disk, zwplug);
++              disk_zone_wplug_abort(zwplug);
++              zwplug->flags |= BLK_ZONE_WPLUG_NEED_WP_UPDATE;
+               spin_unlock_irqrestore(&zwplug->lock, flags);
+       }
+@@ -1327,6 +1234,7 @@ static void blk_zone_wplug_bio_work(stru
+        */
+       spin_lock_irqsave(&zwplug->lock, flags);
++again:
+       bio = bio_list_pop(&zwplug->bio_list);
+       if (!bio) {
+               zwplug->flags &= ~BLK_ZONE_WPLUG_PLUGGED;
+@@ -1335,10 +1243,8 @@ static void blk_zone_wplug_bio_work(stru
+       }
+       if (!blk_zone_wplug_prepare_bio(zwplug, bio)) {
+-              /* Error recovery will decide what to do with the BIO. */
+-              bio_list_add_head(&zwplug->bio_list, bio);
+-              spin_unlock_irqrestore(&zwplug->lock, flags);
+-              goto put_zwplug;
++              blk_zone_wplug_bio_io_error(zwplug, bio);
++              goto again;
+       }
+       spin_unlock_irqrestore(&zwplug->lock, flags);
+@@ -1360,97 +1266,6 @@ put_zwplug:
+       disk_put_zone_wplug(zwplug);
+ }
+-static int blk_zone_wplug_report_zone_cb(struct blk_zone *zone,
+-                                       unsigned int idx, void *data)
+-{
+-      struct blk_zone *zonep = data;
+-
+-      *zonep = *zone;
+-      return 0;
+-}
+-
+-static void disk_zone_wplug_handle_error(struct gendisk *disk,
+-                                       struct blk_zone_wplug *zwplug)
+-{
+-      sector_t zone_start_sector =
+-              bdev_zone_sectors(disk->part0) * zwplug->zone_no;
+-      unsigned int noio_flag;
+-      struct blk_zone zone;
+-      unsigned long flags;
+-      int ret;
+-
+-      /* Get the current zone information from the device. */
+-      noio_flag = memalloc_noio_save();
+-      ret = disk->fops->report_zones(disk, zone_start_sector, 1,
+-                                     blk_zone_wplug_report_zone_cb, &zone);
+-      memalloc_noio_restore(noio_flag);
+-
+-      spin_lock_irqsave(&zwplug->lock, flags);
+-
+-      /*
+-       * A zone reset or finish may have cleared the error already. In such
+-       * case, do nothing as the report zones may have seen the "old" write
+-       * pointer value before the reset/finish operation completed.
+-       */
+-      if (!(zwplug->flags & BLK_ZONE_WPLUG_ERROR))
+-              goto unlock;
+-
+-      zwplug->flags &= ~BLK_ZONE_WPLUG_ERROR;
+-
+-      if (ret != 1) {
+-              /*
+-               * We failed to get the zone information, meaning that something
+-               * is likely really wrong with the device. Abort all remaining
+-               * plugged BIOs as otherwise we could endup waiting forever on
+-               * plugged BIOs to complete if there is a queue freeze on-going.
+-               */
+-              disk_zone_wplug_abort(zwplug);
+-              goto unplug;
+-      }
+-
+-      /* Update the zone write pointer offset. */
+-      zwplug->wp_offset = blk_zone_wp_offset(&zone);
+-      disk_zone_wplug_abort_unaligned(disk, zwplug);
+-
+-      /* Restart BIO submission if we still have any BIO left. */
+-      if (!bio_list_empty(&zwplug->bio_list)) {
+-              disk_zone_wplug_schedule_bio_work(disk, zwplug);
+-              goto unlock;
+-      }
+-
+-unplug:
+-      zwplug->flags &= ~BLK_ZONE_WPLUG_PLUGGED;
+-      if (disk_should_remove_zone_wplug(disk, zwplug))
+-              disk_remove_zone_wplug(disk, zwplug);
+-
+-unlock:
+-      spin_unlock_irqrestore(&zwplug->lock, flags);
+-}
+-
+-static void disk_zone_wplugs_work(struct work_struct *work)
+-{
+-      struct gendisk *disk =
+-              container_of(work, struct gendisk, zone_wplugs_work);
+-      struct blk_zone_wplug *zwplug;
+-      unsigned long flags;
+-
+-      spin_lock_irqsave(&disk->zone_wplugs_lock, flags);
+-
+-      while (!list_empty(&disk->zone_wplugs_err_list)) {
+-              zwplug = list_first_entry(&disk->zone_wplugs_err_list,
+-                                        struct blk_zone_wplug, link);
+-              list_del_init(&zwplug->link);
+-              spin_unlock_irqrestore(&disk->zone_wplugs_lock, flags);
+-
+-              disk_zone_wplug_handle_error(disk, zwplug);
+-              disk_put_zone_wplug(zwplug);
+-
+-              spin_lock_irqsave(&disk->zone_wplugs_lock, flags);
+-      }
+-
+-      spin_unlock_irqrestore(&disk->zone_wplugs_lock, flags);
+-}
+-
+ static inline unsigned int disk_zone_wplugs_hash_size(struct gendisk *disk)
+ {
+       return 1U << disk->zone_wplugs_hash_bits;
+@@ -1459,8 +1274,6 @@ static inline unsigned int disk_zone_wpl
+ void disk_init_zone_resources(struct gendisk *disk)
+ {
+       spin_lock_init(&disk->zone_wplugs_lock);
+-      INIT_LIST_HEAD(&disk->zone_wplugs_err_list);
+-      INIT_WORK(&disk->zone_wplugs_work, disk_zone_wplugs_work);
+ }
+ /*
+@@ -1559,8 +1372,6 @@ void disk_free_zone_resources(struct gen
+       if (!disk->zone_wplugs_pool)
+               return;
+-      cancel_work_sync(&disk->zone_wplugs_work);
+-
+       if (disk->zone_wplugs_wq) {
+               destroy_workqueue(disk->zone_wplugs_wq);
+               disk->zone_wplugs_wq = NULL;
+@@ -1757,6 +1568,8 @@ static int blk_revalidate_seq_zone(struc
+       if (!disk->zone_wplugs_hash)
+               return 0;
++      disk_zone_wplug_sync_wp_offset(disk, zone);
++
+       wp_offset = blk_zone_wp_offset(zone);
+       if (!wp_offset || wp_offset >= zone->capacity)
+               return 0;
+@@ -1893,6 +1706,7 @@ int blk_revalidate_disk_zones(struct gen
+               memalloc_noio_restore(noio_flag);
+               return ret;
+       }
++
+       ret = disk->fops->report_zones(disk, 0, UINT_MAX,
+                                      blk_revalidate_zone_cb, &args);
+       if (!ret) {
+--- a/include/linux/blkdev.h
++++ b/include/linux/blkdev.h
+@@ -200,8 +200,6 @@ struct gendisk {
+       spinlock_t              zone_wplugs_lock;
+       struct mempool_s        *zone_wplugs_pool;
+       struct hlist_head       *zone_wplugs_hash;
+-      struct list_head        zone_wplugs_err_list;
+-      struct work_struct      zone_wplugs_work;
+       struct workqueue_struct *zone_wplugs_wq;
+ #endif /* CONFIG_BLK_DEV_ZONED */
diff --git a/queue-6.12/block-switch-to-using-refcount_t-for-zone-write-plugs.patch b/queue-6.12/block-switch-to-using-refcount_t-for-zone-write-plugs.patch
new file mode 100644 (file)
index 0000000..b35eda6
--- /dev/null
@@ -0,0 +1,115 @@
+From 4122fef16b172f7c1838fcf74340268c86ed96db Mon Sep 17 00:00:00 2001
+From: Damien Le Moal <dlemoal@kernel.org>
+Date: Thu, 7 Nov 2024 15:54:38 +0900
+Subject: block: Switch to using refcount_t for zone write plugs
+
+From: Damien Le Moal <dlemoal@kernel.org>
+
+commit 4122fef16b172f7c1838fcf74340268c86ed96db upstream.
+
+Replace the raw atomic_t reference counting of zone write plugs with a
+refcount_t.  No functional changes.
+
+Reported-by: kernel test robot <lkp@intel.com>
+Closes: https://lore.kernel.org/oe-kbuild-all/202411050650.ilIZa8S7-lkp@intel.com/
+Signed-off-by: Damien Le Moal <dlemoal@kernel.org>
+Reviewed-by: Christoph Hellwig <hch@lst.de>
+Link: https://lore.kernel.org/r/20241107065438.236348-1-dlemoal@kernel.org
+Signed-off-by: Jens Axboe <axboe@kernel.dk>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ block/blk-zoned.c |   20 ++++++++++----------
+ 1 file changed, 10 insertions(+), 10 deletions(-)
+
+--- a/block/blk-zoned.c
++++ b/block/blk-zoned.c
+@@ -18,7 +18,7 @@
+ #include <linux/vmalloc.h>
+ #include <linux/sched/mm.h>
+ #include <linux/spinlock.h>
+-#include <linux/atomic.h>
++#include <linux/refcount.h>
+ #include <linux/mempool.h>
+ #include "blk.h"
+@@ -64,7 +64,7 @@ static const char *const zone_cond_name[
+ struct blk_zone_wplug {
+       struct hlist_node       node;
+       struct list_head        link;
+-      atomic_t                ref;
++      refcount_t              ref;
+       spinlock_t              lock;
+       unsigned int            flags;
+       unsigned int            zone_no;
+@@ -417,7 +417,7 @@ static struct blk_zone_wplug *disk_get_z
+       hlist_for_each_entry_rcu(zwplug, &disk->zone_wplugs_hash[idx], node) {
+               if (zwplug->zone_no == zno &&
+-                  atomic_inc_not_zero(&zwplug->ref)) {
++                  refcount_inc_not_zero(&zwplug->ref)) {
+                       rcu_read_unlock();
+                       return zwplug;
+               }
+@@ -438,7 +438,7 @@ static void disk_free_zone_wplug_rcu(str
+ static inline void disk_put_zone_wplug(struct blk_zone_wplug *zwplug)
+ {
+-      if (atomic_dec_and_test(&zwplug->ref)) {
++      if (refcount_dec_and_test(&zwplug->ref)) {
+               WARN_ON_ONCE(!bio_list_empty(&zwplug->bio_list));
+               WARN_ON_ONCE(!list_empty(&zwplug->link));
+               WARN_ON_ONCE(!(zwplug->flags & BLK_ZONE_WPLUG_UNHASHED));
+@@ -469,7 +469,7 @@ static inline bool disk_should_remove_zo
+        * taken when the plug was allocated and another reference taken by the
+        * caller context).
+        */
+-      if (atomic_read(&zwplug->ref) > 2)
++      if (refcount_read(&zwplug->ref) > 2)
+               return false;
+       /* We can remove zone write plugs for zones that are empty or full. */
+@@ -539,7 +539,7 @@ again:
+       INIT_HLIST_NODE(&zwplug->node);
+       INIT_LIST_HEAD(&zwplug->link);
+-      atomic_set(&zwplug->ref, 2);
++      refcount_set(&zwplug->ref, 2);
+       spin_lock_init(&zwplug->lock);
+       zwplug->flags = 0;
+       zwplug->zone_no = zno;
+@@ -630,7 +630,7 @@ static inline void disk_zone_wplug_set_e
+        * finished.
+        */
+       zwplug->flags |= BLK_ZONE_WPLUG_ERROR;
+-      atomic_inc(&zwplug->ref);
++      refcount_inc(&zwplug->ref);
+       spin_lock_irqsave(&disk->zone_wplugs_lock, flags);
+       list_add_tail(&zwplug->link, &disk->zone_wplugs_err_list);
+@@ -1105,7 +1105,7 @@ static void disk_zone_wplug_schedule_bio
+        * reference we take here.
+        */
+       WARN_ON_ONCE(!(zwplug->flags & BLK_ZONE_WPLUG_PLUGGED));
+-      atomic_inc(&zwplug->ref);
++      refcount_inc(&zwplug->ref);
+       queue_work(disk->zone_wplugs_wq, &zwplug->bio_work);
+ }
+@@ -1450,7 +1450,7 @@ static void disk_destroy_zone_wplugs_has
+               while (!hlist_empty(&disk->zone_wplugs_hash[i])) {
+                       zwplug = hlist_entry(disk->zone_wplugs_hash[i].first,
+                                            struct blk_zone_wplug, node);
+-                      atomic_inc(&zwplug->ref);
++                      refcount_inc(&zwplug->ref);
+                       disk_remove_zone_wplug(disk, zwplug);
+                       disk_put_zone_wplug(zwplug);
+               }
+@@ -1876,7 +1876,7 @@ int queue_zone_wplugs_show(void *data, s
+                       spin_lock_irqsave(&zwplug->lock, flags);
+                       zwp_zone_no = zwplug->zone_no;
+                       zwp_flags = zwplug->flags;
+-                      zwp_ref = atomic_read(&zwplug->ref);
++                      zwp_ref = refcount_read(&zwplug->ref);
+                       zwp_wp_offset = zwplug->wp_offset;
+                       zwp_bio_list_size = bio_list_size(&zwplug->bio_list);
+                       spin_unlock_irqrestore(&zwplug->lock, flags);
diff --git a/queue-6.12/block-use-a-zone-write-plug-bio-work-for-req_nowait-bios.patch b/queue-6.12/block-use-a-zone-write-plug-bio-work-for-req_nowait-bios.patch
new file mode 100644 (file)
index 0000000..a5adf44
--- /dev/null
@@ -0,0 +1,166 @@
+From cae005670887cb07ceafc25bb32e221e56286488 Mon Sep 17 00:00:00 2001
+From: Damien Le Moal <dlemoal@kernel.org>
+Date: Mon, 9 Dec 2024 21:23:54 +0900
+Subject: block: Use a zone write plug BIO work for REQ_NOWAIT BIOs
+
+From: Damien Le Moal <dlemoal@kernel.org>
+
+commit cae005670887cb07ceafc25bb32e221e56286488 upstream.
+
+For zoned block devices, a write BIO issued to a zone that has no
+on-going writes will be prepared for execution and allowed to execute
+immediately by blk_zone_wplug_handle_write() (called from
+blk_zone_plug_bio()). However, if this BIO specifies REQ_NOWAIT, the
+allocation of a request for its execution in blk_mq_submit_bio() may
+fail after blk_zone_plug_bio() completed, marking the target zone of the
+BIO as plugged. When this BIO is retried later on, it will be blocked as
+the zone write plug of the target zone is in a plugged state without any
+on-going write operation (completion of write operations trigger
+unplugging of the next write BIOs for a zone). This leads to a BIO that
+is stuck in a zone write plug and never completes, which results in
+various issues such as hung tasks.
+
+Avoid this problem by always executing REQ_NOWAIT write BIOs using the
+BIO work of a zone write plug. This ensure that we never block the BIO
+issuer and can thus safely ignore the REQ_NOWAIT flag when executing the
+BIO from the zone write plug BIO work.
+
+Since such BIO may be the first write BIO issued to a zone with no
+on-going write, modify disk_zone_wplug_add_bio() to schedule the zone
+write plug BIO work if the write plug is not already marked with the
+BLK_ZONE_WPLUG_PLUGGED flag. This scheduling is otherwise not necessary
+as the completion of the on-going write for the zone will schedule the
+execution of the next plugged BIOs.
+
+blk_zone_wplug_handle_write() is also fixed to better handle zone write
+plug allocation failures for REQ_NOWAIT BIOs by failing a write BIO
+using bio_wouldblock_error() instead of bio_io_error().
+
+Reported-by: Bart Van Assche <bvanassche@acm.org>
+Fixes: dd291d77cc90 ("block: Introduce zone write plugging")
+Cc: stable@vger.kernel.org
+Signed-off-by: Damien Le Moal <dlemoal@kernel.org>
+Reviewed-by: Christoph Hellwig <hch@lst.de>
+Reviewed-by: Martin K. Petersen <martin.petersen@oracle.com>
+Link: https://lore.kernel.org/r/20241209122357.47838-2-dlemoal@kernel.org
+Signed-off-by: Jens Axboe <axboe@kernel.dk>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ block/blk-zoned.c |   62 ++++++++++++++++++++++++++++++++++++------------------
+ 1 file changed, 42 insertions(+), 20 deletions(-)
+
+--- a/block/blk-zoned.c
++++ b/block/blk-zoned.c
+@@ -759,9 +759,25 @@ static bool blk_zone_wplug_handle_reset_
+       return false;
+ }
+-static inline void blk_zone_wplug_add_bio(struct blk_zone_wplug *zwplug,
+-                                        struct bio *bio, unsigned int nr_segs)
++static void disk_zone_wplug_schedule_bio_work(struct gendisk *disk,
++                                            struct blk_zone_wplug *zwplug)
++{
++      /*
++       * Take a reference on the zone write plug and schedule the submission
++       * of the next plugged BIO. blk_zone_wplug_bio_work() will release the
++       * reference we take here.
++       */
++      WARN_ON_ONCE(!(zwplug->flags & BLK_ZONE_WPLUG_PLUGGED));
++      refcount_inc(&zwplug->ref);
++      queue_work(disk->zone_wplugs_wq, &zwplug->bio_work);
++}
++
++static inline void disk_zone_wplug_add_bio(struct gendisk *disk,
++                              struct blk_zone_wplug *zwplug,
++                              struct bio *bio, unsigned int nr_segs)
+ {
++      bool schedule_bio_work = false;
++
+       /*
+        * Grab an extra reference on the BIO request queue usage counter.
+        * This reference will be reused to submit a request for the BIO for
+@@ -778,6 +794,16 @@ static inline void blk_zone_wplug_add_bi
+       bio_clear_polled(bio);
+       /*
++       * REQ_NOWAIT BIOs are always handled using the zone write plug BIO
++       * work, which can block. So clear the REQ_NOWAIT flag and schedule the
++       * work if this is the first BIO we are plugging.
++       */
++      if (bio->bi_opf & REQ_NOWAIT) {
++              schedule_bio_work = !(zwplug->flags & BLK_ZONE_WPLUG_PLUGGED);
++              bio->bi_opf &= ~REQ_NOWAIT;
++      }
++
++      /*
+        * Reuse the poll cookie field to store the number of segments when
+        * split to the hardware limits.
+        */
+@@ -790,6 +816,11 @@ static inline void blk_zone_wplug_add_bi
+        * at the tail of the list to preserve the sequential write order.
+        */
+       bio_list_add(&zwplug->bio_list, bio);
++
++      zwplug->flags |= BLK_ZONE_WPLUG_PLUGGED;
++
++      if (schedule_bio_work)
++              disk_zone_wplug_schedule_bio_work(disk, zwplug);
+ }
+ /*
+@@ -983,7 +1014,10 @@ static bool blk_zone_wplug_handle_write(
+       zwplug = disk_get_and_lock_zone_wplug(disk, sector, gfp_mask, &flags);
+       if (!zwplug) {
+-              bio_io_error(bio);
++              if (bio->bi_opf & REQ_NOWAIT)
++                      bio_wouldblock_error(bio);
++              else
++                      bio_io_error(bio);
+               return true;
+       }
+@@ -992,9 +1026,11 @@ static bool blk_zone_wplug_handle_write(
+       /*
+        * If the zone is already plugged or has a pending error, add the BIO
+-       * to the plug BIO list. Otherwise, plug and let the BIO execute.
++       * to the plug BIO list. Do the same for REQ_NOWAIT BIOs to ensure that
++       * we will not see a BLK_STS_AGAIN failure if we let the BIO execute.
++       * Otherwise, plug and let the BIO execute.
+        */
+-      if (zwplug->flags & BLK_ZONE_WPLUG_BUSY)
++      if (zwplug->flags & BLK_ZONE_WPLUG_BUSY || (bio->bi_opf & REQ_NOWAIT))
+               goto plug;
+       /*
+@@ -1011,8 +1047,7 @@ static bool blk_zone_wplug_handle_write(
+       return false;
+ plug:
+-      zwplug->flags |= BLK_ZONE_WPLUG_PLUGGED;
+-      blk_zone_wplug_add_bio(zwplug, bio, nr_segs);
++      disk_zone_wplug_add_bio(disk, zwplug, bio, nr_segs);
+       spin_unlock_irqrestore(&zwplug->lock, flags);
+@@ -1096,19 +1131,6 @@ bool blk_zone_plug_bio(struct bio *bio,
+ }
+ EXPORT_SYMBOL_GPL(blk_zone_plug_bio);
+-static void disk_zone_wplug_schedule_bio_work(struct gendisk *disk,
+-                                            struct blk_zone_wplug *zwplug)
+-{
+-      /*
+-       * Take a reference on the zone write plug and schedule the submission
+-       * of the next plugged BIO. blk_zone_wplug_bio_work() will release the
+-       * reference we take here.
+-       */
+-      WARN_ON_ONCE(!(zwplug->flags & BLK_ZONE_WPLUG_PLUGGED));
+-      refcount_inc(&zwplug->ref);
+-      queue_work(disk->zone_wplugs_wq, &zwplug->bio_work);
+-}
+-
+ static void disk_zone_wplug_unplug_bio(struct gendisk *disk,
+                                      struct blk_zone_wplug *zwplug)
+ {
diff --git a/queue-6.12/bpf-fix-uaf-via-mismatching-bpf_prog-attachment-rcu-flavors.patch b/queue-6.12/bpf-fix-uaf-via-mismatching-bpf_prog-attachment-rcu-flavors.patch
new file mode 100644 (file)
index 0000000..670c79e
--- /dev/null
@@ -0,0 +1,46 @@
+From ef1b808e3b7c98612feceedf985c2fbbeb28f956 Mon Sep 17 00:00:00 2001
+From: Jann Horn <jannh@google.com>
+Date: Tue, 10 Dec 2024 17:32:13 +0100
+Subject: bpf: Fix UAF via mismatching bpf_prog/attachment RCU flavors
+
+From: Jann Horn <jannh@google.com>
+
+commit ef1b808e3b7c98612feceedf985c2fbbeb28f956 upstream.
+
+Uprobes always use bpf_prog_run_array_uprobe() under tasks-trace-RCU
+protection. But it is possible to attach a non-sleepable BPF program to a
+uprobe, and non-sleepable BPF programs are freed via normal RCU (see
+__bpf_prog_put_noref()). This leads to UAF of the bpf_prog because a normal
+RCU grace period does not imply a tasks-trace-RCU grace period.
+
+Fix it by explicitly waiting for a tasks-trace-RCU grace period after
+removing the attachment of a bpf_prog to a perf_event.
+
+Fixes: 8c7dcb84e3b7 ("bpf: implement sleepable uprobes by chaining gps")
+Suggested-by: Andrii Nakryiko <andrii@kernel.org>
+Suggested-by: Alexei Starovoitov <ast@kernel.org>
+Signed-off-by: Jann Horn <jannh@google.com>
+Signed-off-by: Andrii Nakryiko <andrii@kernel.org>
+Cc: stable@vger.kernel.org
+Link: https://lore.kernel.org/bpf/20241210-bpf-fix-actual-uprobe-uaf-v1-1-19439849dd44@google.com
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ kernel/trace/bpf_trace.c |    7 +++++++
+ 1 file changed, 7 insertions(+)
+
+--- a/kernel/trace/bpf_trace.c
++++ b/kernel/trace/bpf_trace.c
+@@ -2223,6 +2223,13 @@ void perf_event_detach_bpf_prog(struct p
+               bpf_prog_array_free_sleepable(old_array);
+       }
++      /*
++       * It could be that the bpf_prog is not sleepable (and will be freed
++       * via normal RCU), but is called from a point that supports sleepable
++       * programs and uses tasks-trace-RCU.
++       */
++      synchronize_rcu_tasks_trace();
++
+       bpf_prog_put(event->prog);
+       event->prog = NULL;
diff --git a/queue-6.12/clk-en7523-fix-wrong-bus-clock-for-en7581.patch b/queue-6.12/clk-en7523-fix-wrong-bus-clock-for-en7581.patch
new file mode 100644 (file)
index 0000000..2750a71
--- /dev/null
@@ -0,0 +1,53 @@
+From 2eb75f86d52565367211c51334d15fe672633085 Mon Sep 17 00:00:00 2001
+From: Christian Marangi <ansuelsmth@gmail.com>
+Date: Sat, 16 Nov 2024 11:56:53 +0100
+Subject: clk: en7523: Fix wrong BUS clock for EN7581
+
+From: Christian Marangi <ansuelsmth@gmail.com>
+
+commit 2eb75f86d52565367211c51334d15fe672633085 upstream.
+
+The Documentation for EN7581 had a typo and still referenced the EN7523
+BUS base source frequency. This was in conflict with a different page in
+the Documentration that state that the BUS runs at 300MHz (600MHz source
+with divisor set to 2) and the actual watchdog that tick at half the BUS
+clock (150MHz). This was verified with the watchdog by timing the
+seconds that the system takes to reboot (due too watchdog) and by
+operating on different values of the BUS divisor.
+
+The correct values for source of BUS clock are 600MHz and 540MHz.
+
+This was also confirmed by Airoha.
+
+Cc: stable@vger.kernel.org
+Fixes: 66bc47326ce2 ("clk: en7523: Add EN7581 support")
+Signed-off-by: Christian Marangi <ansuelsmth@gmail.com>
+Link: https://lore.kernel.org/r/20241116105710.19748-1-ansuelsmth@gmail.com
+Acked-by: Lorenzo Bianconi <lorenzo@kernel.org>
+Signed-off-by: Stephen Boyd <sboyd@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/clk/clk-en7523.c |    5 +++--
+ 1 file changed, 3 insertions(+), 2 deletions(-)
+
+--- a/drivers/clk/clk-en7523.c
++++ b/drivers/clk/clk-en7523.c
+@@ -92,6 +92,7 @@ static const u32 slic_base[] = { 1000000
+ static const u32 npu_base[] = { 333000000, 400000000, 500000000 };
+ /* EN7581 */
+ static const u32 emi7581_base[] = { 540000000, 480000000, 400000000, 300000000 };
++static const u32 bus7581_base[] = { 600000000, 540000000 };
+ static const u32 npu7581_base[] = { 800000000, 750000000, 720000000, 600000000 };
+ static const u32 crypto_base[] = { 540000000, 480000000 };
+@@ -227,8 +228,8 @@ static const struct en_clk_desc en7581_b
+               .base_reg = REG_BUS_CLK_DIV_SEL,
+               .base_bits = 1,
+               .base_shift = 8,
+-              .base_values = bus_base,
+-              .n_base_values = ARRAY_SIZE(bus_base),
++              .base_values = bus7581_base,
++              .n_base_values = ARRAY_SIZE(bus7581_base),
+               .div_bits = 3,
+               .div_shift = 0,
diff --git a/queue-6.12/crypto-hisilicon-debugfs-fix-the-struct-pointer-incorrectly-offset-problem.patch b/queue-6.12/crypto-hisilicon-debugfs-fix-the-struct-pointer-incorrectly-offset-problem.patch
new file mode 100644 (file)
index 0000000..93b61cd
--- /dev/null
@@ -0,0 +1,46 @@
+From cd26cd65476711e2c69e0a049c0eeef4b743f5ac Mon Sep 17 00:00:00 2001
+From: Chenghai Huang <huangchenghai2@huawei.com>
+Date: Sat, 30 Nov 2024 16:01:31 +0800
+Subject: crypto: hisilicon/debugfs - fix the struct pointer incorrectly offset problem
+
+From: Chenghai Huang <huangchenghai2@huawei.com>
+
+commit cd26cd65476711e2c69e0a049c0eeef4b743f5ac upstream.
+
+Offset based on (id * size) is wrong for sqc and cqc.
+(*sqc/*cqc + 1) can already offset sizeof(struct(Xqc)) length.
+
+Fixes: 15f112f9cef5 ("crypto: hisilicon/debugfs - mask the unnecessary info from the dump")
+Cc: <stable@vger.kernel.org>
+Signed-off-by: Chenghai Huang <huangchenghai2@huawei.com>
+Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/crypto/hisilicon/debugfs.c | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/drivers/crypto/hisilicon/debugfs.c b/drivers/crypto/hisilicon/debugfs.c
+index 1b9b7bccdeff..45e130b901eb 100644
+--- a/drivers/crypto/hisilicon/debugfs.c
++++ b/drivers/crypto/hisilicon/debugfs.c
+@@ -192,7 +192,7 @@ static int qm_sqc_dump(struct hisi_qm *qm, char *s, char *name)
+       down_read(&qm->qps_lock);
+       if (qm->sqc) {
+-              memcpy(&sqc, qm->sqc + qp_id * sizeof(struct qm_sqc), sizeof(struct qm_sqc));
++              memcpy(&sqc, qm->sqc + qp_id, sizeof(struct qm_sqc));
+               sqc.base_h = cpu_to_le32(QM_XQC_ADDR_MASK);
+               sqc.base_l = cpu_to_le32(QM_XQC_ADDR_MASK);
+               dump_show(qm, &sqc, sizeof(struct qm_sqc), "SOFT SQC");
+@@ -229,7 +229,7 @@ static int qm_cqc_dump(struct hisi_qm *qm, char *s, char *name)
+       down_read(&qm->qps_lock);
+       if (qm->cqc) {
+-              memcpy(&cqc, qm->cqc + qp_id * sizeof(struct qm_cqc), sizeof(struct qm_cqc));
++              memcpy(&cqc, qm->cqc + qp_id, sizeof(struct qm_cqc));
+               cqc.base_h = cpu_to_le32(QM_XQC_ADDR_MASK);
+               cqc.base_l = cpu_to_le32(QM_XQC_ADDR_MASK);
+               dump_show(qm, &cqc, sizeof(struct qm_cqc), "SOFT CQC");
+-- 
+2.47.1
+
diff --git a/queue-6.12/dm-fix-dm-zoned-reclaim-zone-write-pointer-alignment.patch b/queue-6.12/dm-fix-dm-zoned-reclaim-zone-write-pointer-alignment.patch
new file mode 100644 (file)
index 0000000..7189d39
--- /dev/null
@@ -0,0 +1,264 @@
+From b76b840fd93374240b59825f1ab8e2f5c9907acb Mon Sep 17 00:00:00 2001
+From: Damien Le Moal <dlemoal@kernel.org>
+Date: Mon, 9 Dec 2024 21:23:56 +0900
+Subject: dm: Fix dm-zoned-reclaim zone write pointer alignment
+
+From: Damien Le Moal <dlemoal@kernel.org>
+
+commit b76b840fd93374240b59825f1ab8e2f5c9907acb upstream.
+
+The zone reclaim processing of the dm-zoned device mapper uses
+blkdev_issue_zeroout() to align the write pointer of a zone being used
+for reclaiming another zone, to write the valid data blocks from the
+zone being reclaimed at the same position relative to the zone start in
+the reclaim target zone.
+
+The first call to blkdev_issue_zeroout() will try to use hardware
+offload using a REQ_OP_WRITE_ZEROES operation if the device reports a
+non-zero max_write_zeroes_sectors queue limit. If this operation fails
+because of the lack of hardware support, blkdev_issue_zeroout() falls
+back to using a regular write operation with the zero-page as buffer.
+Currently, such REQ_OP_WRITE_ZEROES failure is automatically handled by
+the block layer zone write plugging code which will execute a report
+zones operation to ensure that the write pointer of the target zone of
+the failed operation has not changed and to "rewind" the zone write
+pointer offset of the target zone as it was advanced when the write zero
+operation was submitted. So the REQ_OP_WRITE_ZEROES failure does not
+cause any issue and blkdev_issue_zeroout() works as expected.
+
+However, since the automatic recovery of zone write pointers by the zone
+write plugging code can potentially cause deadlocks with queue freeze
+operations, a different recovery must be implemented in preparation for
+the removal of zone write plugging report zones based recovery.
+
+Do this by introducing the new function blk_zone_issue_zeroout(). This
+function first calls blkdev_issue_zeroout() with the flag
+BLKDEV_ZERO_NOFALLBACK to intercept failures on the first execution
+which attempt to use the device hardware offload with the
+REQ_OP_WRITE_ZEROES operation. If this attempt fails, a report zone
+operation is issued to restore the zone write pointer offset of the
+target zone to the correct position and blkdev_issue_zeroout() is called
+again without the BLKDEV_ZERO_NOFALLBACK flag. The report zones
+operation performing this recovery is implemented using the helper
+function disk_zone_sync_wp_offset() which calls the gendisk report_zones
+file operation with the callback disk_report_zones_cb(). This callback
+updates the target write pointer offset of the target zone using the new
+function disk_zone_wplug_sync_wp_offset().
+
+dmz_reclaim_align_wp() is modified to change its call to
+blkdev_issue_zeroout() to a call to blk_zone_issue_zeroout() without any
+other change needed as the two functions are functionnally equivalent.
+
+Fixes: dd291d77cc90 ("block: Introduce zone write plugging")
+Cc: stable@vger.kernel.org
+Signed-off-by: Damien Le Moal <dlemoal@kernel.org>
+Reviewed-by: Christoph Hellwig <hch@lst.de>
+Acked-by: Mike Snitzer <snitzer@kernel.org>
+Reviewed-by: Martin K. Petersen <martin.petersen@oracle.com>
+Link: https://lore.kernel.org/r/20241209122357.47838-4-dlemoal@kernel.org
+Signed-off-by: Jens Axboe <axboe@kernel.dk>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ block/blk-zoned.c             |  141 +++++++++++++++++++++++++++++++++++-------
+ drivers/md/dm-zoned-reclaim.c |    6 -
+ include/linux/blkdev.h        |    3 
+ 3 files changed, 124 insertions(+), 26 deletions(-)
+
+--- a/block/blk-zoned.c
++++ b/block/blk-zoned.c
+@@ -115,6 +115,30 @@ const char *blk_zone_cond_str(enum blk_z
+ }
+ EXPORT_SYMBOL_GPL(blk_zone_cond_str);
++struct disk_report_zones_cb_args {
++      struct gendisk  *disk;
++      report_zones_cb user_cb;
++      void            *user_data;
++};
++
++static void disk_zone_wplug_sync_wp_offset(struct gendisk *disk,
++                                         struct blk_zone *zone);
++
++static int disk_report_zones_cb(struct blk_zone *zone, unsigned int idx,
++                              void *data)
++{
++      struct disk_report_zones_cb_args *args = data;
++      struct gendisk *disk = args->disk;
++
++      if (disk->zone_wplugs_hash)
++              disk_zone_wplug_sync_wp_offset(disk, zone);
++
++      if (!args->user_cb)
++              return 0;
++
++      return args->user_cb(zone, idx, args->user_data);
++}
++
+ /**
+  * blkdev_report_zones - Get zones information
+  * @bdev:     Target block device
+@@ -707,6 +731,58 @@ static void disk_zone_wplug_set_wp_offse
+       spin_unlock_irqrestore(&zwplug->lock, flags);
+ }
++static unsigned int blk_zone_wp_offset(struct blk_zone *zone)
++{
++      switch (zone->cond) {
++      case BLK_ZONE_COND_IMP_OPEN:
++      case BLK_ZONE_COND_EXP_OPEN:
++      case BLK_ZONE_COND_CLOSED:
++              return zone->wp - zone->start;
++      case BLK_ZONE_COND_FULL:
++              return zone->len;
++      case BLK_ZONE_COND_EMPTY:
++              return 0;
++      case BLK_ZONE_COND_NOT_WP:
++      case BLK_ZONE_COND_OFFLINE:
++      case BLK_ZONE_COND_READONLY:
++      default:
++              /*
++               * Conventional, offline and read-only zones do not have a valid
++               * write pointer.
++               */
++              return UINT_MAX;
++      }
++}
++
++static void disk_zone_wplug_sync_wp_offset(struct gendisk *disk,
++                                         struct blk_zone *zone)
++{
++      struct blk_zone_wplug *zwplug;
++      unsigned long flags;
++
++      zwplug = disk_get_zone_wplug(disk, zone->start);
++      if (!zwplug)
++              return;
++
++      spin_lock_irqsave(&zwplug->lock, flags);
++      if (zwplug->flags & BLK_ZONE_WPLUG_ERROR)
++              disk_zone_wplug_set_wp_offset(disk, zwplug,
++                                            blk_zone_wp_offset(zone));
++      spin_unlock_irqrestore(&zwplug->lock, flags);
++
++      disk_put_zone_wplug(zwplug);
++}
++
++static int disk_zone_sync_wp_offset(struct gendisk *disk, sector_t sector)
++{
++      struct disk_report_zones_cb_args args = {
++              .disk = disk,
++      };
++
++      return disk->fops->report_zones(disk, sector, 1,
++                                      disk_report_zones_cb, &args);
++}
++
+ static bool blk_zone_wplug_handle_reset_or_finish(struct bio *bio,
+                                                 unsigned int wp_offset)
+ {
+@@ -1284,29 +1360,6 @@ put_zwplug:
+       disk_put_zone_wplug(zwplug);
+ }
+-static unsigned int blk_zone_wp_offset(struct blk_zone *zone)
+-{
+-      switch (zone->cond) {
+-      case BLK_ZONE_COND_IMP_OPEN:
+-      case BLK_ZONE_COND_EXP_OPEN:
+-      case BLK_ZONE_COND_CLOSED:
+-              return zone->wp - zone->start;
+-      case BLK_ZONE_COND_FULL:
+-              return zone->len;
+-      case BLK_ZONE_COND_EMPTY:
+-              return 0;
+-      case BLK_ZONE_COND_NOT_WP:
+-      case BLK_ZONE_COND_OFFLINE:
+-      case BLK_ZONE_COND_READONLY:
+-      default:
+-              /*
+-               * Conventional, offline and read-only zones do not have a valid
+-               * write pointer.
+-               */
+-              return UINT_MAX;
+-      }
+-}
+-
+ static int blk_zone_wplug_report_zone_cb(struct blk_zone *zone,
+                                        unsigned int idx, void *data)
+ {
+@@ -1876,6 +1929,48 @@ int blk_revalidate_disk_zones(struct gen
+ }
+ EXPORT_SYMBOL_GPL(blk_revalidate_disk_zones);
++/**
++ * blk_zone_issue_zeroout - zero-fill a block range in a zone
++ * @bdev:     blockdev to write
++ * @sector:   start sector
++ * @nr_sects: number of sectors to write
++ * @gfp_mask: memory allocation flags (for bio_alloc)
++ *
++ * Description:
++ *  Zero-fill a block range in a zone (@sector must be equal to the zone write
++ *  pointer), handling potential errors due to the (initially unknown) lack of
++ *  hardware offload (See blkdev_issue_zeroout()).
++ */
++int blk_zone_issue_zeroout(struct block_device *bdev, sector_t sector,
++                         sector_t nr_sects, gfp_t gfp_mask)
++{
++      int ret;
++
++      if (WARN_ON_ONCE(!bdev_is_zoned(bdev)))
++              return -EIO;
++
++      ret = blkdev_issue_zeroout(bdev, sector, nr_sects, gfp_mask,
++                                 BLKDEV_ZERO_NOFALLBACK);
++      if (ret != -EOPNOTSUPP)
++              return ret;
++
++      /*
++       * The failed call to blkdev_issue_zeroout() advanced the zone write
++       * pointer. Undo this using a report zone to update the zone write
++       * pointer to the correct current value.
++       */
++      ret = disk_zone_sync_wp_offset(bdev->bd_disk, sector);
++      if (ret != 1)
++              return ret < 0 ? ret : -EIO;
++
++      /*
++       * Retry without BLKDEV_ZERO_NOFALLBACK to force the fallback to a
++       * regular write with zero-pages.
++       */
++      return blkdev_issue_zeroout(bdev, sector, nr_sects, gfp_mask, 0);
++}
++EXPORT_SYMBOL_GPL(blk_zone_issue_zeroout);
++
+ #ifdef CONFIG_BLK_DEBUG_FS
+ int queue_zone_wplugs_show(void *data, struct seq_file *m)
+--- a/drivers/md/dm-zoned-reclaim.c
++++ b/drivers/md/dm-zoned-reclaim.c
+@@ -76,9 +76,9 @@ static int dmz_reclaim_align_wp(struct d
+        * pointer and the requested position.
+        */
+       nr_blocks = block - wp_block;
+-      ret = blkdev_issue_zeroout(dev->bdev,
+-                                 dmz_start_sect(zmd, zone) + dmz_blk2sect(wp_block),
+-                                 dmz_blk2sect(nr_blocks), GFP_NOIO, 0);
++      ret = blk_zone_issue_zeroout(dev->bdev,
++                      dmz_start_sect(zmd, zone) + dmz_blk2sect(wp_block),
++                      dmz_blk2sect(nr_blocks), GFP_NOIO);
+       if (ret) {
+               dmz_dev_err(dev,
+                           "Align zone %u wp %llu to %llu (wp+%u) blocks failed %d",
+--- a/include/linux/blkdev.h
++++ b/include/linux/blkdev.h
+@@ -1386,6 +1386,9 @@ static inline bool bdev_is_zone_start(st
+       return bdev_offset_from_zone_start(bdev, sector) == 0;
+ }
++int blk_zone_issue_zeroout(struct block_device *bdev, sector_t sector,
++                         sector_t nr_sects, gfp_t gfp_mask);
++
+ static inline int queue_dma_alignment(const struct request_queue *q)
+ {
+       return q->limits.dma_alignment;
diff --git a/queue-6.12/drm-panic-remove-spurious-empty-line-to-clean-warning.patch b/queue-6.12/drm-panic-remove-spurious-empty-line-to-clean-warning.patch
new file mode 100644 (file)
index 0000000..c8f4721
--- /dev/null
@@ -0,0 +1,62 @@
+From 4011b351b1b5a953aaa7c6b3915f908b3cc1be96 Mon Sep 17 00:00:00 2001
+From: Miguel Ojeda <ojeda@kernel.org>
+Date: Tue, 26 Nov 2024 00:33:32 +0100
+Subject: drm/panic: remove spurious empty line to clean warning
+
+From: Miguel Ojeda <ojeda@kernel.org>
+
+commit 4011b351b1b5a953aaa7c6b3915f908b3cc1be96 upstream.
+
+Clippy in the upcoming Rust 1.83.0 spots a spurious empty line since the
+`clippy::empty_line_after_doc_comments` warning is now enabled by default
+given it is part of the `suspicious` group [1]:
+
+    error: empty line after doc comment
+       --> drivers/gpu/drm/drm_panic_qr.rs:931:1
+        |
+    931 | / /// They must remain valid for the duration of the function call.
+    932 | |
+        | |_
+    933 |   #[no_mangle]
+    934 | / pub unsafe extern "C" fn drm_panic_qr_generate(
+    935 | |     url: *const i8,
+    936 | |     data: *mut u8,
+    937 | |     data_len: usize,
+    ...   |
+    940 | |     tmp_size: usize,
+    941 | | ) -> u8 {
+        | |_______- the comment documents this function
+        |
+        = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#empty_line_after_doc_comments
+        = note: `-D clippy::empty-line-after-doc-comments` implied by `-D warnings`
+        = help: to override `-D warnings` add `#[allow(clippy::empty_line_after_doc_comments)]`
+        = help: if the empty line is unintentional remove it
+
+Thus remove the empty line.
+
+Cc: stable@vger.kernel.org
+Fixes: cb5164ac43d0 ("drm/panic: Add a QR code panic screen")
+Link: https://github.com/rust-lang/rust-clippy/pull/13091 [1]
+Reviewed-by: Jocelyn Falempe <jfalempe@redhat.com>
+Link: https://lore.kernel.org/r/20241125233332.697497-1-ojeda@kernel.org
+Signed-off-by: Miguel Ojeda <ojeda@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/gpu/drm/drm_panic_qr.rs | 1 -
+ 1 file changed, 1 deletion(-)
+
+diff --git a/drivers/gpu/drm/drm_panic_qr.rs b/drivers/gpu/drm/drm_panic_qr.rs
+index 09500cddc009..ef2d490965ba 100644
+--- a/drivers/gpu/drm/drm_panic_qr.rs
++++ b/drivers/gpu/drm/drm_panic_qr.rs
+@@ -929,7 +929,6 @@ impl QrImage<'_> {
+ /// * `tmp` must be valid for reading and writing for `tmp_size` bytes.
+ ///
+ /// They must remain valid for the duration of the function call.
+-
+ #[no_mangle]
+ pub unsafe extern "C" fn drm_panic_qr_generate(
+     url: *const i8,
+-- 
+2.47.1
+
diff --git a/queue-6.12/gpio-graniterapids-check-if-gpio-line-can-be-used-for-irqs.patch b/queue-6.12/gpio-graniterapids-check-if-gpio-line-can-be-used-for-irqs.patch
new file mode 100644 (file)
index 0000000..abee22f
--- /dev/null
@@ -0,0 +1,68 @@
+From c0ec4890d6454980c53c3cc164140115c4a671f2 Mon Sep 17 00:00:00 2001
+From: Alan Borzeszkowski <alan.borzeszkowski@linux.intel.com>
+Date: Wed, 4 Dec 2024 09:04:14 +0200
+Subject: gpio: graniterapids: Check if GPIO line can be used for IRQs
+
+From: Alan Borzeszkowski <alan.borzeszkowski@linux.intel.com>
+
+commit c0ec4890d6454980c53c3cc164140115c4a671f2 upstream.
+
+GPIO line can only be used as interrupt if its INTSEL register is
+programmed by the BIOS.
+
+Cc: stable@vger.kernel.org
+Signed-off-by: Alan Borzeszkowski <alan.borzeszkowski@linux.intel.com>
+Signed-off-by: Mika Westerberg <mika.westerberg@linux.intel.com>
+Acked-by: Andy Shevchenko <andy@kernel.org>
+Link: https://lore.kernel.org/r/20241204070415.1034449-7-mika.westerberg@linux.intel.com
+Signed-off-by: Bartosz Golaszewski <bartosz.golaszewski@linaro.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/gpio/gpio-graniterapids.c | 15 ++++++++++++---
+ 1 file changed, 12 insertions(+), 3 deletions(-)
+
+diff --git a/drivers/gpio/gpio-graniterapids.c b/drivers/gpio/gpio-graniterapids.c
+index b12abe77299c..3a972d460fe2 100644
+--- a/drivers/gpio/gpio-graniterapids.c
++++ b/drivers/gpio/gpio-graniterapids.c
+@@ -39,6 +39,7 @@
+ #define GNR_CFG_DW_HOSTSW_MODE        BIT(27)
+ #define GNR_CFG_DW_RX_MASK    GENMASK(23, 22)
++#define GNR_CFG_DW_INTSEL_MASK        GENMASK(21, 14)
+ #define GNR_CFG_DW_RX_DISABLE FIELD_PREP(GNR_CFG_DW_RX_MASK, 2)
+ #define GNR_CFG_DW_RX_EDGE    FIELD_PREP(GNR_CFG_DW_RX_MASK, 1)
+ #define GNR_CFG_DW_RX_LEVEL   FIELD_PREP(GNR_CFG_DW_RX_MASK, 0)
+@@ -227,10 +228,18 @@ static void gnr_gpio_irq_unmask(struct irq_data *d)
+ static int gnr_gpio_irq_set_type(struct irq_data *d, unsigned int type)
+ {
+       struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
+-      irq_hw_number_t pin = irqd_to_hwirq(d);
+-      u32 mask = GNR_CFG_DW_RX_MASK;
++      struct gnr_gpio *priv = gpiochip_get_data(gc);
++      irq_hw_number_t hwirq = irqd_to_hwirq(d);
++      u32 reg;
+       u32 set;
++      /* Allow interrupts only if Interrupt Select field is non-zero */
++      reg = readl(gnr_gpio_get_padcfg_addr(priv, hwirq));
++      if (!(reg & GNR_CFG_DW_INTSEL_MASK)) {
++              dev_dbg(gc->parent, "GPIO %lu cannot be used as IRQ", hwirq);
++              return -EPERM;
++      }
++
+       /* Falling edge and level low triggers not supported by the GPIO controller */
+       switch (type) {
+       case IRQ_TYPE_NONE:
+@@ -248,7 +257,7 @@ static int gnr_gpio_irq_set_type(struct irq_data *d, unsigned int type)
+               return -EINVAL;
+       }
+-      return gnr_gpio_configure_line(gc, pin, mask, set);
++      return gnr_gpio_configure_line(gc, hwirq, GNR_CFG_DW_RX_MASK, set);
+ }
+ static const struct irq_chip gnr_gpio_irq_chip = {
+-- 
+2.47.1
+
diff --git a/queue-6.12/gpio-graniterapids-determine-if-gpio-pad-can-be-used-by-driver.patch b/queue-6.12/gpio-graniterapids-determine-if-gpio-pad-can-be-used-by-driver.patch
new file mode 100644 (file)
index 0000000..e789697
--- /dev/null
@@ -0,0 +1,62 @@
+From 0588504d28dedde6789aec17a6ece6fa8e477725 Mon Sep 17 00:00:00 2001
+From: Alan Borzeszkowski <alan.borzeszkowski@linux.intel.com>
+Date: Wed, 4 Dec 2024 09:04:13 +0200
+Subject: gpio: graniterapids: Determine if GPIO pad can be used by driver
+
+From: Alan Borzeszkowski <alan.borzeszkowski@linux.intel.com>
+
+commit 0588504d28dedde6789aec17a6ece6fa8e477725 upstream.
+
+Add check of HOSTSW_MODE bit to determine if GPIO pad can be used by the
+driver.
+
+Cc: stable@vger.kernel.org
+Signed-off-by: Alan Borzeszkowski <alan.borzeszkowski@linux.intel.com>
+Signed-off-by: Mika Westerberg <mika.westerberg@linux.intel.com>
+Acked-by: Andy Shevchenko <andy@kernel.org>
+Link: https://lore.kernel.org/r/20241204070415.1034449-6-mika.westerberg@linux.intel.com
+Signed-off-by: Bartosz Golaszewski <bartosz.golaszewski@linaro.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/gpio/gpio-graniterapids.c |   16 ++++++++++++++++
+ 1 file changed, 16 insertions(+)
+
+--- a/drivers/gpio/gpio-graniterapids.c
++++ b/drivers/gpio/gpio-graniterapids.c
+@@ -37,6 +37,7 @@
+ #define GNR_GPI_STATUS_OFFSET 0x14
+ #define GNR_GPI_ENABLE_OFFSET 0x24
++#define GNR_CFG_DW_HOSTSW_MODE        BIT(27)
+ #define GNR_CFG_DW_RX_MASK    GENMASK(23, 22)
+ #define GNR_CFG_DW_RX_DISABLE FIELD_PREP(GNR_CFG_DW_RX_MASK, 2)
+ #define GNR_CFG_DW_RX_EDGE    FIELD_PREP(GNR_CFG_DW_RX_MASK, 1)
+@@ -90,6 +91,20 @@ static int gnr_gpio_configure_line(struc
+       return 0;
+ }
++static int gnr_gpio_request(struct gpio_chip *gc, unsigned int gpio)
++{
++      struct gnr_gpio *priv = gpiochip_get_data(gc);
++      u32 dw;
++
++      dw = readl(gnr_gpio_get_padcfg_addr(priv, gpio));
++      if (!(dw & GNR_CFG_DW_HOSTSW_MODE)) {
++              dev_warn(gc->parent, "GPIO %u is not owned by host", gpio);
++              return -EBUSY;
++      }
++
++      return 0;
++}
++
+ static int gnr_gpio_get(struct gpio_chip *gc, unsigned int gpio)
+ {
+       const struct gnr_gpio *priv = gpiochip_get_data(gc);
+@@ -141,6 +156,7 @@ static int gnr_gpio_direction_output(str
+ static const struct gpio_chip gnr_gpio_chip = {
+       .owner            = THIS_MODULE,
++      .request          = gnr_gpio_request,
+       .get              = gnr_gpio_get,
+       .set              = gnr_gpio_set,
+       .get_direction    = gnr_gpio_get_direction,
diff --git a/queue-6.12/gpio-graniterapids-fix-gpio-ack-functionality.patch b/queue-6.12/gpio-graniterapids-fix-gpio-ack-functionality.patch
new file mode 100644 (file)
index 0000000..7c42f7e
--- /dev/null
@@ -0,0 +1,33 @@
+From 0bb18e34abdde7bf58fca8542e2dcf621924ea19 Mon Sep 17 00:00:00 2001
+From: Alan Borzeszkowski <alan.borzeszkowski@linux.intel.com>
+Date: Wed, 4 Dec 2024 09:04:15 +0200
+Subject: gpio: graniterapids: Fix GPIO Ack functionality
+
+From: Alan Borzeszkowski <alan.borzeszkowski@linux.intel.com>
+
+commit 0bb18e34abdde7bf58fca8542e2dcf621924ea19 upstream.
+
+Interrupt status (GPI_IS) register is cleared by writing 1 to it, not 0.
+
+Cc: stable@vger.kernel.org
+Signed-off-by: Alan Borzeszkowski <alan.borzeszkowski@linux.intel.com>
+Signed-off-by: Mika Westerberg <mika.westerberg@linux.intel.com>
+Acked-by: Andy Shevchenko <andy@kernel.org>
+Link: https://lore.kernel.org/r/20241204070415.1034449-8-mika.westerberg@linux.intel.com
+Signed-off-by: Bartosz Golaszewski <bartosz.golaszewski@linaro.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/gpio/gpio-graniterapids.c |    2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/drivers/gpio/gpio-graniterapids.c
++++ b/drivers/gpio/gpio-graniterapids.c
+@@ -166,7 +166,7 @@ static void gnr_gpio_irq_ack(struct irq_
+       guard(raw_spinlock_irqsave)(&priv->lock);
+       reg = readl(addr);
+-      reg &= ~BIT(bit_idx);
++      reg |= BIT(bit_idx);
+       writel(reg, addr);
+ }
diff --git a/queue-6.12/gpio-graniterapids-fix-incorrect-bar-assignment.patch b/queue-6.12/gpio-graniterapids-fix-incorrect-bar-assignment.patch
new file mode 100644 (file)
index 0000000..5b89d36
--- /dev/null
@@ -0,0 +1,88 @@
+From 7382d2f0e802077c36495e325da8d253a15fb441 Mon Sep 17 00:00:00 2001
+From: Alan Borzeszkowski <alan.borzeszkowski@linux.intel.com>
+Date: Wed, 4 Dec 2024 09:04:10 +0200
+Subject: gpio: graniterapids: Fix incorrect BAR assignment
+
+From: Alan Borzeszkowski <alan.borzeszkowski@linux.intel.com>
+
+commit 7382d2f0e802077c36495e325da8d253a15fb441 upstream.
+
+Base Address of vGPIO MMIO register is provided directly by the BIOS
+instead of using offsets. Update address assignment to reflect this
+change in driver.
+
+Cc: stable@vger.kernel.org
+Signed-off-by: Alan Borzeszkowski <alan.borzeszkowski@linux.intel.com>
+Signed-off-by: Mika Westerberg <mika.westerberg@linux.intel.com>
+Acked-by: Andy Shevchenko <andy@kernel.org>
+Link: https://lore.kernel.org/r/20241204070415.1034449-3-mika.westerberg@linux.intel.com
+Signed-off-by: Bartosz Golaszewski <bartosz.golaszewski@linaro.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/gpio/gpio-graniterapids.c |   13 +++++++++----
+ 1 file changed, 9 insertions(+), 4 deletions(-)
+
+--- a/drivers/gpio/gpio-graniterapids.c
++++ b/drivers/gpio/gpio-graniterapids.c
+@@ -32,7 +32,7 @@
+ #define GNR_PINS_PER_REG 32
+ #define GNR_NUM_REGS DIV_ROUND_UP(GNR_NUM_PINS, GNR_PINS_PER_REG)
+-#define GNR_CFG_BAR           0x00
++#define GNR_CFG_PADBAR                0x00
+ #define GNR_CFG_LOCK_OFFSET   0x04
+ #define GNR_GPI_STATUS_OFFSET 0x20
+ #define GNR_GPI_ENABLE_OFFSET 0x24
+@@ -50,6 +50,7 @@
+  * struct gnr_gpio - Intel Granite Rapids-D vGPIO driver state
+  * @gc: GPIO controller interface
+  * @reg_base: base address of the GPIO registers
++ * @pad_base: base address of the vGPIO pad configuration registers
+  * @ro_bitmap: bitmap of read-only pins
+  * @lock: guard the registers
+  * @pad_backup: backup of the register state for suspend
+@@ -57,6 +58,7 @@
+ struct gnr_gpio {
+       struct gpio_chip gc;
+       void __iomem *reg_base;
++      void __iomem *pad_base;
+       DECLARE_BITMAP(ro_bitmap, GNR_NUM_PINS);
+       raw_spinlock_t lock;
+       u32 pad_backup[];
+@@ -65,7 +67,7 @@ struct gnr_gpio {
+ static void __iomem *gnr_gpio_get_padcfg_addr(const struct gnr_gpio *priv,
+                                             unsigned int gpio)
+ {
+-      return priv->reg_base + gpio * sizeof(u32);
++      return priv->pad_base + gpio * sizeof(u32);
+ }
+ static int gnr_gpio_configure_line(struct gpio_chip *gc, unsigned int gpio,
+@@ -292,6 +294,7 @@ static int gnr_gpio_probe(struct platfor
+       struct gnr_gpio *priv;
+       void __iomem *regs;
+       int irq, ret;
++      u32 offset;
+       priv = devm_kzalloc(dev, struct_size(priv, pad_backup, num_backup_pins), GFP_KERNEL);
+       if (!priv)
+@@ -303,6 +306,10 @@ static int gnr_gpio_probe(struct platfor
+       if (IS_ERR(regs))
+               return PTR_ERR(regs);
++      priv->reg_base = regs;
++      offset = readl(priv->reg_base + GNR_CFG_PADBAR);
++      priv->pad_base = priv->reg_base + offset;
++
+       irq = platform_get_irq(pdev, 0);
+       if (irq < 0)
+               return irq;
+@@ -312,8 +319,6 @@ static int gnr_gpio_probe(struct platfor
+       if (ret)
+               return dev_err_probe(dev, ret, "failed to request interrupt\n");
+-      priv->reg_base = regs + readl(regs + GNR_CFG_BAR);
+-
+       gnr_gpio_init_pin_ro_bits(dev, priv->reg_base + GNR_CFG_LOCK_OFFSET,
+                                 priv->ro_bitmap);
diff --git a/queue-6.12/gpio-graniterapids-fix-invalid-gpi_is-register-offset.patch b/queue-6.12/gpio-graniterapids-fix-invalid-gpi_is-register-offset.patch
new file mode 100644 (file)
index 0000000..05b3660
--- /dev/null
@@ -0,0 +1,39 @@
+From 0fe329b55231cca489f9bed1db0e778d077fdaf9 Mon Sep 17 00:00:00 2001
+From: Shankar Bandal <shankar.bandal@intel.com>
+Date: Wed, 4 Dec 2024 09:04:11 +0200
+Subject: gpio: graniterapids: Fix invalid GPI_IS register offset
+
+From: Shankar Bandal <shankar.bandal@intel.com>
+
+commit 0fe329b55231cca489f9bed1db0e778d077fdaf9 upstream.
+
+Update GPI Interrupt Status register offset to correct value.
+
+Cc: stable@vger.kernel.org
+Signed-off-by: Shankar Bandal <shankar.bandal@intel.com>
+Signed-off-by: Alan Borzeszkowski <alan.borzeszkowski@linux.intel.com>
+Signed-off-by: Mika Westerberg <mika.westerberg@linux.intel.com>
+Acked-by: Andy Shevchenko <andy@kernel.org>
+Link: https://lore.kernel.org/r/20241204070415.1034449-4-mika.westerberg@linux.intel.com
+Signed-off-by: Bartosz Golaszewski <bartosz.golaszewski@linaro.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/gpio/gpio-graniterapids.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/drivers/gpio/gpio-graniterapids.c b/drivers/gpio/gpio-graniterapids.c
+index d2b542b536b6..be907784ccdb 100644
+--- a/drivers/gpio/gpio-graniterapids.c
++++ b/drivers/gpio/gpio-graniterapids.c
+@@ -34,7 +34,7 @@
+ #define GNR_CFG_PADBAR                0x00
+ #define GNR_CFG_LOCK_OFFSET   0x04
+-#define GNR_GPI_STATUS_OFFSET 0x20
++#define GNR_GPI_STATUS_OFFSET 0x14
+ #define GNR_GPI_ENABLE_OFFSET 0x24
+ #define GNR_CFG_DW_RX_MASK    GENMASK(25, 22)
+-- 
+2.47.1
+
diff --git a/queue-6.12/gpio-graniterapids-fix-invalid-rxevcfg-register-bitmask.patch b/queue-6.12/gpio-graniterapids-fix-invalid-rxevcfg-register-bitmask.patch
new file mode 100644 (file)
index 0000000..de498e6
--- /dev/null
@@ -0,0 +1,39 @@
+From 15636b00a055474033426b94b6372728b2163a1e Mon Sep 17 00:00:00 2001
+From: Shankar Bandal <shankar.bandal@intel.com>
+Date: Wed, 4 Dec 2024 09:04:12 +0200
+Subject: gpio: graniterapids: Fix invalid RXEVCFG register bitmask
+
+From: Shankar Bandal <shankar.bandal@intel.com>
+
+commit 15636b00a055474033426b94b6372728b2163a1e upstream.
+
+Correct RX Level/Edge Configuration register (RXEVCFG) bitmask.
+
+Cc: stable@vger.kernel.org
+Signed-off-by: Shankar Bandal <shankar.bandal@intel.com>
+Signed-off-by: Alan Borzeszkowski <alan.borzeszkowski@linux.intel.com>
+Signed-off-by: Mika Westerberg <mika.westerberg@linux.intel.com>
+Acked-by: Andy Shevchenko <andy@kernel.org>
+Link: https://lore.kernel.org/r/20241204070415.1034449-5-mika.westerberg@linux.intel.com
+Signed-off-by: Bartosz Golaszewski <bartosz.golaszewski@linaro.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/gpio/gpio-graniterapids.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/drivers/gpio/gpio-graniterapids.c b/drivers/gpio/gpio-graniterapids.c
+index be907784ccdb..ec2931a65723 100644
+--- a/drivers/gpio/gpio-graniterapids.c
++++ b/drivers/gpio/gpio-graniterapids.c
+@@ -37,7 +37,7 @@
+ #define GNR_GPI_STATUS_OFFSET 0x14
+ #define GNR_GPI_ENABLE_OFFSET 0x24
+-#define GNR_CFG_DW_RX_MASK    GENMASK(25, 22)
++#define GNR_CFG_DW_RX_MASK    GENMASK(23, 22)
+ #define GNR_CFG_DW_RX_DISABLE FIELD_PREP(GNR_CFG_DW_RX_MASK, 2)
+ #define GNR_CFG_DW_RX_EDGE    FIELD_PREP(GNR_CFG_DW_RX_MASK, 1)
+ #define GNR_CFG_DW_RX_LEVEL   FIELD_PREP(GNR_CFG_DW_RX_MASK, 0)
+-- 
+2.47.1
+
diff --git a/queue-6.12/gpio-graniterapids-fix-vgpio-driver-crash.patch b/queue-6.12/gpio-graniterapids-fix-vgpio-driver-crash.patch
new file mode 100644 (file)
index 0000000..62ce0e1
--- /dev/null
@@ -0,0 +1,56 @@
+From eb9640fd1ce666610b77f5997596e9570a36378f Mon Sep 17 00:00:00 2001
+From: Alan Borzeszkowski <alan.borzeszkowski@linux.intel.com>
+Date: Wed, 4 Dec 2024 09:04:09 +0200
+Subject: gpio: graniterapids: Fix vGPIO driver crash
+
+From: Alan Borzeszkowski <alan.borzeszkowski@linux.intel.com>
+
+commit eb9640fd1ce666610b77f5997596e9570a36378f upstream.
+
+Move setting irq_chip.name from probe() function to the initialization
+of "irq_chip" struct in order to fix vGPIO driver crash during bootup.
+
+Crash was caused by unauthorized modification of irq_chip.name field
+where irq_chip struct was initialized as const.
+
+This behavior is a consequence of suboptimal implementation of
+gpio_irq_chip_set_chip(), which should be changed to avoid
+casting away const qualifier.
+
+Crash log:
+BUG: unable to handle page fault for address: ffffffffc0ba81c0
+/#PF: supervisor write access in kernel mode
+/#PF: error_code(0x0003) - permissions violation
+CPU: 33 UID: 0 PID: 1075 Comm: systemd-udevd Not tainted 6.12.0-rc6-00077-g2e1b3cc9d7f7 #1
+Hardware name: Intel Corporation Kaseyville RP/Kaseyville RP, BIOS KVLDCRB1.PGS.0026.D73.2410081258 10/08/2024
+RIP: 0010:gnr_gpio_probe+0x171/0x220 [gpio_graniterapids]
+
+Cc: stable@vger.kernel.org
+Signed-off-by: Alan Borzeszkowski <alan.borzeszkowski@linux.intel.com>
+Signed-off-by: Mika Westerberg <mika.westerberg@linux.intel.com>
+Acked-by: Andy Shevchenko <andy@kernel.org>
+Link: https://lore.kernel.org/r/20241204070415.1034449-2-mika.westerberg@linux.intel.com
+Signed-off-by: Bartosz Golaszewski <bartosz.golaszewski@linaro.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/gpio/gpio-graniterapids.c |    2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/drivers/gpio/gpio-graniterapids.c
++++ b/drivers/gpio/gpio-graniterapids.c
+@@ -234,6 +234,7 @@ static int gnr_gpio_irq_set_type(struct
+ }
+ static const struct irq_chip gnr_gpio_irq_chip = {
++      .name           = "gpio-graniterapids",
+       .irq_ack        = gnr_gpio_irq_ack,
+       .irq_mask       = gnr_gpio_irq_mask,
+       .irq_unmask     = gnr_gpio_irq_unmask,
+@@ -324,7 +325,6 @@ static int gnr_gpio_probe(struct platfor
+       girq = &priv->gc.irq;
+       gpio_irq_chip_set_chip(girq, &gnr_gpio_irq_chip);
+-      girq->chip->name        = dev_name(dev);
+       girq->parent_handler    = NULL;
+       girq->num_parents       = 0;
+       girq->parents           = NULL;
diff --git a/queue-6.12/gpio-ljca-initialize-num-before-accessing-item-in-ljca_gpio_config.patch b/queue-6.12/gpio-ljca-initialize-num-before-accessing-item-in-ljca_gpio_config.patch
new file mode 100644 (file)
index 0000000..add2d2a
--- /dev/null
@@ -0,0 +1,42 @@
+From 3396995f9fb6bcbe0004a68118a22f98bab6e2b9 Mon Sep 17 00:00:00 2001
+From: Haoyu Li <lihaoyu499@gmail.com>
+Date: Tue, 3 Dec 2024 22:14:51 +0800
+Subject: gpio: ljca: Initialize num before accessing item in ljca_gpio_config
+
+From: Haoyu Li <lihaoyu499@gmail.com>
+
+commit 3396995f9fb6bcbe0004a68118a22f98bab6e2b9 upstream.
+
+With the new __counted_by annocation in ljca_gpio_packet, the "num"
+struct member must be set before accessing the "item" array. Failing to
+do so will trigger a runtime warning when enabling CONFIG_UBSAN_BOUNDS
+and CONFIG_FORTIFY_SOURCE.
+
+Fixes: 1034cc423f1b ("gpio: update Intel LJCA USB GPIO driver")
+Cc: stable@vger.kernel.org
+Signed-off-by: Haoyu Li <lihaoyu499@gmail.com>
+Link: https://lore.kernel.org/stable/20241203141451.342316-1-lihaoyu499%40gmail.com
+Signed-off-by: Bartosz Golaszewski <bartosz.golaszewski@linaro.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/gpio/gpio-ljca.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/drivers/gpio/gpio-ljca.c b/drivers/gpio/gpio-ljca.c
+index d67b912d884d..c6c31e6146c7 100644
+--- a/drivers/gpio/gpio-ljca.c
++++ b/drivers/gpio/gpio-ljca.c
+@@ -82,9 +82,9 @@ static int ljca_gpio_config(struct ljca_gpio_dev *ljca_gpio, u8 gpio_id,
+       int ret;
+       mutex_lock(&ljca_gpio->trans_lock);
++      packet->num = 1;
+       packet->item[0].index = gpio_id;
+       packet->item[0].value = config | ljca_gpio->connect_mode[gpio_id];
+-      packet->num = 1;
+       ret = ljca_transfer(ljca_gpio->ljca, LJCA_GPIO_CONFIG, (u8 *)packet,
+                           struct_size(packet, item, packet->num), NULL, 0);
+-- 
+2.47.1
+
diff --git a/queue-6.12/ksmbd-fix-racy-issue-from-session-lookup-and-expire.patch b/queue-6.12/ksmbd-fix-racy-issue-from-session-lookup-and-expire.patch
new file mode 100644 (file)
index 0000000..62843e8
--- /dev/null
@@ -0,0 +1,196 @@
+From b95629435b84b9ecc0c765995204a4d8a913ed52 Mon Sep 17 00:00:00 2001
+From: Namjae Jeon <linkinjeon@kernel.org>
+Date: Thu, 5 Dec 2024 21:38:47 +0900
+Subject: ksmbd: fix racy issue from session lookup and expire
+
+From: Namjae Jeon <linkinjeon@kernel.org>
+
+commit b95629435b84b9ecc0c765995204a4d8a913ed52 upstream.
+
+Increment the session reference count within the lock for lookup to avoid
+racy issue with session expire.
+
+Cc: stable@vger.kernel.org
+Reported-by: zdi-disclosures@trendmicro.com # ZDI-CAN-25737
+Signed-off-by: Namjae Jeon <linkinjeon@kernel.org>
+Signed-off-by: Steve French <stfrench@microsoft.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ fs/smb/server/auth.c              |    2 ++
+ fs/smb/server/mgmt/user_session.c |    6 +++++-
+ fs/smb/server/server.c            |    4 ++--
+ fs/smb/server/smb2pdu.c           |   27 ++++++++++++++-------------
+ 4 files changed, 23 insertions(+), 16 deletions(-)
+
+--- a/fs/smb/server/auth.c
++++ b/fs/smb/server/auth.c
+@@ -1016,6 +1016,8 @@ static int ksmbd_get_encryption_key(stru
+       ses_enc_key = enc ? sess->smb3encryptionkey :
+               sess->smb3decryptionkey;
++      if (enc)
++              ksmbd_user_session_get(sess);
+       memcpy(key, ses_enc_key, SMB3_ENC_DEC_KEY_SIZE);
+       return 0;
+--- a/fs/smb/server/mgmt/user_session.c
++++ b/fs/smb/server/mgmt/user_session.c
+@@ -263,8 +263,10 @@ struct ksmbd_session *ksmbd_session_look
+       down_read(&conn->session_lock);
+       sess = xa_load(&conn->sessions, id);
+-      if (sess)
++      if (sess) {
+               sess->last_active = jiffies;
++              ksmbd_user_session_get(sess);
++      }
+       up_read(&conn->session_lock);
+       return sess;
+ }
+@@ -275,6 +277,8 @@ struct ksmbd_session *ksmbd_session_look
+       down_read(&sessions_table_lock);
+       sess = __session_lookup(id);
++      if (sess)
++              ksmbd_user_session_get(sess);
+       up_read(&sessions_table_lock);
+       return sess;
+--- a/fs/smb/server/server.c
++++ b/fs/smb/server/server.c
+@@ -241,14 +241,14 @@ send:
+       if (work->tcon)
+               ksmbd_tree_connect_put(work->tcon);
+       smb3_preauth_hash_rsp(work);
+-      if (work->sess)
+-              ksmbd_user_session_put(work->sess);
+       if (work->sess && work->sess->enc && work->encrypted &&
+           conn->ops->encrypt_resp) {
+               rc = conn->ops->encrypt_resp(work);
+               if (rc < 0)
+                       conn->ops->set_rsp_status(work, STATUS_DATA_ERROR);
+       }
++      if (work->sess)
++              ksmbd_user_session_put(work->sess);
+       ksmbd_conn_write(work);
+ }
+--- a/fs/smb/server/smb2pdu.c
++++ b/fs/smb/server/smb2pdu.c
+@@ -67,8 +67,10 @@ static inline bool check_session_id(stru
+               return false;
+       sess = ksmbd_session_lookup_all(conn, id);
+-      if (sess)
++      if (sess) {
++              ksmbd_user_session_put(sess);
+               return true;
++      }
+       pr_err("Invalid user session id: %llu\n", id);
+       return false;
+ }
+@@ -605,10 +607,8 @@ int smb2_check_user_session(struct ksmbd
+       /* Check for validity of user session */
+       work->sess = ksmbd_session_lookup_all(conn, sess_id);
+-      if (work->sess) {
+-              ksmbd_user_session_get(work->sess);
++      if (work->sess)
+               return 1;
+-      }
+       ksmbd_debug(SMB, "Invalid user session, Uid %llu\n", sess_id);
+       return -ENOENT;
+ }
+@@ -1701,29 +1701,35 @@ int smb2_sess_setup(struct ksmbd_work *w
+               if (conn->dialect != sess->dialect) {
+                       rc = -EINVAL;
++                      ksmbd_user_session_put(sess);
+                       goto out_err;
+               }
+               if (!(req->hdr.Flags & SMB2_FLAGS_SIGNED)) {
+                       rc = -EINVAL;
++                      ksmbd_user_session_put(sess);
+                       goto out_err;
+               }
+               if (strncmp(conn->ClientGUID, sess->ClientGUID,
+                           SMB2_CLIENT_GUID_SIZE)) {
+                       rc = -ENOENT;
++                      ksmbd_user_session_put(sess);
+                       goto out_err;
+               }
+               if (sess->state == SMB2_SESSION_IN_PROGRESS) {
+                       rc = -EACCES;
++                      ksmbd_user_session_put(sess);
+                       goto out_err;
+               }
+               if (sess->state == SMB2_SESSION_EXPIRED) {
+                       rc = -EFAULT;
++                      ksmbd_user_session_put(sess);
+                       goto out_err;
+               }
++              ksmbd_user_session_put(sess);
+               if (ksmbd_conn_need_reconnect(conn)) {
+                       rc = -EFAULT;
+@@ -1731,7 +1737,8 @@ int smb2_sess_setup(struct ksmbd_work *w
+                       goto out_err;
+               }
+-              if (ksmbd_session_lookup(conn, sess_id)) {
++              sess = ksmbd_session_lookup(conn, sess_id);
++              if (!sess) {
+                       rc = -EACCES;
+                       goto out_err;
+               }
+@@ -1742,7 +1749,6 @@ int smb2_sess_setup(struct ksmbd_work *w
+               }
+               conn->binding = true;
+-              ksmbd_user_session_get(sess);
+       } else if ((conn->dialect < SMB30_PROT_ID ||
+                   server_conf.flags & KSMBD_GLOBAL_FLAG_SMB3_MULTICHANNEL) &&
+                  (req->Flags & SMB2_SESSION_REQ_FLAG_BINDING)) {
+@@ -1769,7 +1775,6 @@ int smb2_sess_setup(struct ksmbd_work *w
+               }
+               conn->binding = false;
+-              ksmbd_user_session_get(sess);
+       }
+       work->sess = sess;
+@@ -2195,9 +2200,9 @@ err_out:
+ int smb2_session_logoff(struct ksmbd_work *work)
+ {
+       struct ksmbd_conn *conn = work->conn;
++      struct ksmbd_session *sess = work->sess;
+       struct smb2_logoff_req *req;
+       struct smb2_logoff_rsp *rsp;
+-      struct ksmbd_session *sess;
+       u64 sess_id;
+       int err;
+@@ -2219,11 +2224,6 @@ int smb2_session_logoff(struct ksmbd_wor
+       ksmbd_close_session_fds(work);
+       ksmbd_conn_wait_idle(conn);
+-      /*
+-       * Re-lookup session to validate if session is deleted
+-       * while waiting request complete
+-       */
+-      sess = ksmbd_session_lookup_all(conn, sess_id);
+       if (ksmbd_tree_conn_session_logoff(sess)) {
+               ksmbd_debug(SMB, "Invalid tid %d\n", req->hdr.Id.SyncId.TreeId);
+               rsp->hdr.Status = STATUS_NETWORK_NAME_DELETED;
+@@ -8962,6 +8962,7 @@ int smb3_decrypt_req(struct ksmbd_work *
+                      le64_to_cpu(tr_hdr->SessionId));
+               return -ECONNABORTED;
+       }
++      ksmbd_user_session_put(sess);
+       iov[0].iov_base = buf;
+       iov[0].iov_len = sizeof(struct smb2_transform_hdr) + 4;
diff --git a/queue-6.12/memcg-slub-fix-sunreclaim-for-post-charged-objects.patch b/queue-6.12/memcg-slub-fix-sunreclaim-for-post-charged-objects.patch
new file mode 100644 (file)
index 0000000..a0dcb6b
--- /dev/null
@@ -0,0 +1,61 @@
+From b7ffecbe198e2dfc44abf92ceb90f46150f7527a Mon Sep 17 00:00:00 2001
+From: Shakeel Butt <shakeel.butt@linux.dev>
+Date: Mon, 9 Dec 2024 20:06:57 -0800
+Subject: memcg: slub: fix SUnreclaim for post charged objects
+
+From: Shakeel Butt <shakeel.butt@linux.dev>
+
+commit b7ffecbe198e2dfc44abf92ceb90f46150f7527a upstream.
+
+Large kmalloc directly allocates from the page allocator and then use
+lruvec_stat_mod_folio() to increment the unreclaimable slab stats for
+global and memcg. However when post memcg charging of slab objects was
+added in commit 9028cdeb38e1 ("memcg: add charging of already allocated
+slab objects"), it missed to correctly handle the unreclaimable slab
+stats for memcg.
+
+One user visisble effect of that bug is that the node level
+unreclaimable slab stat will work correctly but the memcg level stat can
+underflow as kernel correctly handles the free path but the charge path
+missed to increment the memcg level unreclaimable slab stat. Let's fix
+by correctly handle in the post charge code path.
+
+Fixes: 9028cdeb38e1 ("memcg: add charging of already allocated slab objects")
+Signed-off-by: Shakeel Butt <shakeel.butt@linux.dev>
+Cc: <stable@vger.kernel.org>
+Signed-off-by: Vlastimil Babka <vbabka@suse.cz>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ mm/slub.c |   21 ++++++++++++++++++---
+ 1 file changed, 18 insertions(+), 3 deletions(-)
+
+--- a/mm/slub.c
++++ b/mm/slub.c
+@@ -2199,9 +2199,24 @@ bool memcg_slab_post_charge(void *p, gfp
+       folio = virt_to_folio(p);
+       if (!folio_test_slab(folio)) {
+-              return folio_memcg_kmem(folio) ||
+-                      (__memcg_kmem_charge_page(folio_page(folio, 0), flags,
+-                                                folio_order(folio)) == 0);
++              int size;
++
++              if (folio_memcg_kmem(folio))
++                      return true;
++
++              if (__memcg_kmem_charge_page(folio_page(folio, 0), flags,
++                                           folio_order(folio)))
++                      return false;
++
++              /*
++               * This folio has already been accounted in the global stats but
++               * not in the memcg stats. So, subtract from the global and use
++               * the interface which adds to both global and memcg stats.
++               */
++              size = folio_size(folio);
++              node_stat_mod_folio(folio, NR_SLAB_UNRECLAIMABLE_B, -size);
++              lruvec_stat_mod_folio(folio, NR_SLAB_UNRECLAIMABLE_B, size);
++              return true;
+       }
+       slab = folio_slab(folio);
diff --git a/queue-6.12/perf-ftrace-fix-undefined-behavior-in-cmp_profile_data.patch b/queue-6.12/perf-ftrace-fix-undefined-behavior-in-cmp_profile_data.patch
new file mode 100644 (file)
index 0000000..5ee71e0
--- /dev/null
@@ -0,0 +1,57 @@
+From 246dfe3dc199246bd64635163115f2691623fc53 Mon Sep 17 00:00:00 2001
+From: Kuan-Wei Chiu <visitorckw@gmail.com>
+Date: Mon, 9 Dec 2024 21:42:26 +0800
+Subject: perf ftrace: Fix undefined behavior in cmp_profile_data()
+
+From: Kuan-Wei Chiu <visitorckw@gmail.com>
+
+commit 246dfe3dc199246bd64635163115f2691623fc53 upstream.
+
+The comparison function cmp_profile_data() violates the C standard's
+requirements for qsort() comparison functions, which mandate symmetry
+and transitivity:
+
+* Symmetry: If x < y, then y > x.
+* Transitivity: If x < y and y < z, then x < z.
+
+When v1 and v2 are equal, the function incorrectly returns 1, breaking
+symmetry and transitivity. This causes undefined behavior, which can
+lead to memory corruption in certain versions of glibc [1].
+
+Fix the issue by returning 0 when v1 and v2 are equal, ensuring
+compliance with the C standard and preventing undefined behavior.
+
+Link: https://www.qualys.com/2024/01/30/qsort.txt [1]
+Fixes: 0f223813edd0 ("perf ftrace: Add 'profile' command")
+Fixes: 74ae366c37b7 ("perf ftrace profile: Add -s/--sort option")
+Cc: stable@vger.kernel.org
+Signed-off-by: Kuan-Wei Chiu <visitorckw@gmail.com>
+Reviewed-by: Namhyung Kim <namhyung@kernel.org>
+Reviewed-by: Arnaldo Carvalho de Melo <acme@redhat.com>
+Cc: jserv@ccns.ncku.edu.tw
+Cc: chuang@cs.nycu.edu.tw
+Link: https://lore.kernel.org/r/20241209134226.1939163-1-visitorckw@gmail.com
+Signed-off-by: Namhyung Kim <namhyung@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ tools/perf/builtin-ftrace.c | 3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+diff --git a/tools/perf/builtin-ftrace.c b/tools/perf/builtin-ftrace.c
+index 272d3c70810e..a56cf8b0a7d4 100644
+--- a/tools/perf/builtin-ftrace.c
++++ b/tools/perf/builtin-ftrace.c
+@@ -1151,8 +1151,9 @@ static int cmp_profile_data(const void *a, const void *b)
+       if (v1 > v2)
+               return -1;
+-      else
++      if (v1 < v2)
+               return 1;
++      return 0;
+ }
+ static void print_profile_result(struct perf_ftrace *ftrace)
+-- 
+2.47.1
+
diff --git a/queue-6.12/perf-x86-intel-ds-unconditionally-drain-pebs-ds-when-changing-pebs_data_cfg.patch b/queue-6.12/perf-x86-intel-ds-unconditionally-drain-pebs-ds-when-changing-pebs_data_cfg.patch
new file mode 100644 (file)
index 0000000..dc55f08
--- /dev/null
@@ -0,0 +1,65 @@
+From 9f3de72a0c37005f897d69e4bdd59c25b8898447 Mon Sep 17 00:00:00 2001
+From: Kan Liang <kan.liang@linux.intel.com>
+Date: Tue, 19 Nov 2024 05:55:01 -0800
+Subject: perf/x86/intel/ds: Unconditionally drain PEBS DS when changing PEBS_DATA_CFG
+
+From: Kan Liang <kan.liang@linux.intel.com>
+
+commit 9f3de72a0c37005f897d69e4bdd59c25b8898447 upstream.
+
+The PEBS kernel warnings can still be observed with the below case.
+
+when the below commands are running in parallel for a while.
+
+  while true;
+  do
+       perf record --no-buildid -a --intr-regs=AX  \
+                   -e cpu/event=0xd0,umask=0x81/pp \
+                   -c 10003 -o /dev/null ./triad;
+  done &
+
+  while true;
+  do
+       perf record -e 'cpu/mem-loads,ldlat=3/uP' -W -d -- ./dtlb
+  done
+
+The commit b752ea0c28e3 ("perf/x86/intel/ds: Flush PEBS DS when changing
+PEBS_DATA_CFG") intends to flush the entire PEBS buffer before the
+hardware is reprogrammed. However, it fails in the above case.
+
+The first perf command utilizes the large PEBS, while the second perf
+command only utilizes a single PEBS. When the second perf event is
+added, only the n_pebs++. The intel_pmu_pebs_enable() is invoked after
+intel_pmu_pebs_add(). So the cpuc->n_pebs == cpuc->n_large_pebs check in
+the intel_pmu_drain_large_pebs() fails. The PEBS DS is not flushed.
+The new PEBS event should not be taken into account when flushing the
+existing PEBS DS.
+
+The check is unnecessary here. Before the hardware is reprogrammed, all
+the stale records must be drained unconditionally.
+
+For single PEBS or PEBS-vi-pt, the DS must be empty. The drain_pebs()
+can handle the empty case. There is no harm to unconditionally drain the
+PEBS DS.
+
+Fixes: b752ea0c28e3 ("perf/x86/intel/ds: Flush PEBS DS when changing PEBS_DATA_CFG")
+Signed-off-by: Kan Liang <kan.liang@linux.intel.com>
+Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
+Cc: stable@vger.kernel.org
+Link: https://lore.kernel.org/r/20241119135504.1463839-2-kan.liang@linux.intel.com
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ arch/x86/events/intel/ds.c |    2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/arch/x86/events/intel/ds.c
++++ b/arch/x86/events/intel/ds.c
+@@ -1468,7 +1468,7 @@ void intel_pmu_pebs_enable(struct perf_e
+                        * hence we need to drain when changing said
+                        * size.
+                        */
+-                      intel_pmu_drain_large_pebs(cpuc);
++                      intel_pmu_drain_pebs_buffer();
+                       adaptive_pebs_record_size_update();
+                       wrmsrl(MSR_PEBS_DATA_CFG, pebs_data_cfg);
+                       cpuc->active_pebs_data_cfg = pebs_data_cfg;
diff --git a/queue-6.12/riscv-fix-ipis-usage-in-kfence_protect_page.patch b/queue-6.12/riscv-fix-ipis-usage-in-kfence_protect_page.patch
new file mode 100644 (file)
index 0000000..2757bc2
--- /dev/null
@@ -0,0 +1,81 @@
+From b3431a8bb336cece8adc452437befa7d4534b2fd Mon Sep 17 00:00:00 2001
+From: Alexandre Ghiti <alexghiti@rivosinc.com>
+Date: Mon, 9 Dec 2024 08:41:25 +0100
+Subject: riscv: Fix IPIs usage in kfence_protect_page()
+
+From: Alexandre Ghiti <alexghiti@rivosinc.com>
+
+commit b3431a8bb336cece8adc452437befa7d4534b2fd upstream.
+
+flush_tlb_kernel_range() may use IPIs to flush the TLBs of all the
+cores, which triggers the following warning when the irqs are disabled:
+
+[    3.455330] WARNING: CPU: 1 PID: 0 at kernel/smp.c:815 smp_call_function_many_cond+0x452/0x520
+[    3.456647] Modules linked in:
+[    3.457218] CPU: 1 UID: 0 PID: 0 Comm: swapper/1 Not tainted 6.12.0-rc7-00010-g91d3de7240b8 #1
+[    3.457416] Hardware name: QEMU QEMU Virtual Machine, BIOS
+[    3.457633] epc : smp_call_function_many_cond+0x452/0x520
+[    3.457736]  ra : on_each_cpu_cond_mask+0x1e/0x30
+[    3.457786] epc : ffffffff800b669a ra : ffffffff800b67c2 sp : ff2000000000bb50
+[    3.457824]  gp : ffffffff815212b8 tp : ff6000008014f080 t0 : 000000000000003f
+[    3.457859]  t1 : ffffffff815221e0 t2 : 000000000000000f s0 : ff2000000000bc10
+[    3.457920]  s1 : 0000000000000040 a0 : ffffffff815221e0 a1 : 0000000000000001
+[    3.457953]  a2 : 0000000000010000 a3 : 0000000000000003 a4 : 0000000000000000
+[    3.458006]  a5 : 0000000000000000 a6 : ffffffffffffffff a7 : 0000000000000000
+[    3.458042]  s2 : ffffffff815223be s3 : 00fffffffffff000 s4 : ff600001ffe38fc0
+[    3.458076]  s5 : ff600001ff950d00 s6 : 0000000200000120 s7 : 0000000000000001
+[    3.458109]  s8 : 0000000000000001 s9 : ff60000080841ef0 s10: 0000000000000001
+[    3.458141]  s11: ffffffff81524812 t3 : 0000000000000001 t4 : ff60000080092bc0
+[    3.458172]  t5 : 0000000000000000 t6 : ff200000000236d0
+[    3.458203] status: 0000000200000100 badaddr: ffffffff800b669a cause: 0000000000000003
+[    3.458373] [<ffffffff800b669a>] smp_call_function_many_cond+0x452/0x520
+[    3.458593] [<ffffffff800b67c2>] on_each_cpu_cond_mask+0x1e/0x30
+[    3.458625] [<ffffffff8000e4ca>] __flush_tlb_range+0x118/0x1ca
+[    3.458656] [<ffffffff8000e6b2>] flush_tlb_kernel_range+0x1e/0x26
+[    3.458683] [<ffffffff801ea56a>] kfence_protect+0xc0/0xce
+[    3.458717] [<ffffffff801e9456>] kfence_guarded_free+0xc6/0x1c0
+[    3.458742] [<ffffffff801e9d6c>] __kfence_free+0x62/0xc6
+[    3.458764] [<ffffffff801c57d8>] kfree+0x106/0x32c
+[    3.458786] [<ffffffff80588cf2>] detach_buf_split+0x188/0x1a8
+[    3.458816] [<ffffffff8058708c>] virtqueue_get_buf_ctx+0xb6/0x1f6
+[    3.458839] [<ffffffff805871da>] virtqueue_get_buf+0xe/0x16
+[    3.458880] [<ffffffff80613d6a>] virtblk_done+0x5c/0xe2
+[    3.458908] [<ffffffff8058766e>] vring_interrupt+0x6a/0x74
+[    3.458930] [<ffffffff800747d8>] __handle_irq_event_percpu+0x7c/0xe2
+[    3.458956] [<ffffffff800748f0>] handle_irq_event+0x3c/0x86
+[    3.458978] [<ffffffff800786cc>] handle_simple_irq+0x9e/0xbe
+[    3.459004] [<ffffffff80073934>] generic_handle_domain_irq+0x1c/0x2a
+[    3.459027] [<ffffffff804bf87c>] imsic_handle_irq+0xba/0x120
+[    3.459056] [<ffffffff80073934>] generic_handle_domain_irq+0x1c/0x2a
+[    3.459080] [<ffffffff804bdb76>] riscv_intc_aia_irq+0x24/0x34
+[    3.459103] [<ffffffff809d0452>] handle_riscv_irq+0x2e/0x4c
+[    3.459133] [<ffffffff809d923e>] call_on_irq_stack+0x32/0x40
+
+So only flush the local TLB and let the lazy kfence page fault handling
+deal with the faults which could happen when a core has an old protected
+pte version cached in its TLB. That leads to potential inaccuracies which
+can be tolerated when using kfence.
+
+Fixes: 47513f243b45 ("riscv: Enable KFENCE for riscv64")
+Signed-off-by: Alexandre Ghiti <alexghiti@rivosinc.com>
+Cc: stable@vger.kernel.org
+Link: https://lore.kernel.org/r/20241209074125.52322-1-alexghiti@rivosinc.com
+Signed-off-by: Palmer Dabbelt <palmer@rivosinc.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ arch/riscv/include/asm/kfence.h |    4 +++-
+ 1 file changed, 3 insertions(+), 1 deletion(-)
+
+--- a/arch/riscv/include/asm/kfence.h
++++ b/arch/riscv/include/asm/kfence.h
+@@ -22,7 +22,9 @@ static inline bool kfence_protect_page(u
+       else
+               set_pte(pte, __pte(pte_val(ptep_get(pte)) | _PAGE_PRESENT));
+-      flush_tlb_kernel_range(addr, addr + PAGE_SIZE);
++      preempt_disable();
++      local_flush_tlb_kernel_range(addr, addr + PAGE_SIZE);
++      preempt_enable();
+       return true;
+ }
diff --git a/queue-6.12/riscv-fix-wrong-usage-of-__pa-on-a-fixmap-address.patch b/queue-6.12/riscv-fix-wrong-usage-of-__pa-on-a-fixmap-address.patch
new file mode 100644 (file)
index 0000000..0b76a44
--- /dev/null
@@ -0,0 +1,33 @@
+From c796e187201242992d6d292bfeff41aadfdf3f29 Mon Sep 17 00:00:00 2001
+From: Alexandre Ghiti <alexghiti@rivosinc.com>
+Date: Mon, 9 Dec 2024 08:45:08 +0100
+Subject: riscv: Fix wrong usage of __pa() on a fixmap address
+
+From: Alexandre Ghiti <alexghiti@rivosinc.com>
+
+commit c796e187201242992d6d292bfeff41aadfdf3f29 upstream.
+
+riscv uses fixmap addresses to map the dtb so we can't use __pa() which
+is reserved for linear mapping addresses.
+
+Fixes: b2473a359763 ("of/fdt: add dt_phys arg to early_init_dt_scan and early_init_dt_verify")
+Signed-off-by: Alexandre Ghiti <alexghiti@rivosinc.com>
+Link: https://lore.kernel.org/r/20241209074508.53037-1-alexghiti@rivosinc.com
+Cc: stable@vger.kernel.org
+Signed-off-by: Palmer Dabbelt <palmer@rivosinc.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ arch/riscv/kernel/setup.c |    2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/arch/riscv/kernel/setup.c
++++ b/arch/riscv/kernel/setup.c
+@@ -227,7 +227,7 @@ static void __init init_resources(void)
+ static void __init parse_dtb(void)
+ {
+       /* Early scan of device tree from init memory */
+-      if (early_init_dt_scan(dtb_early_va, __pa(dtb_early_va))) {
++      if (early_init_dt_scan(dtb_early_va, dtb_early_pa)) {
+               const char *name = of_flat_dt_get_machine_name();
+               if (name) {
diff --git a/queue-6.12/riscv-mm-do-not-call-pmd-dtor-on-vmemmap-page-table-teardown.patch b/queue-6.12/riscv-mm-do-not-call-pmd-dtor-on-vmemmap-page-table-teardown.patch
new file mode 100644 (file)
index 0000000..d190500
--- /dev/null
@@ -0,0 +1,118 @@
+From 21f1b85c8912262adf51707e63614a114425eb10 Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Bj=C3=B6rn=20T=C3=B6pel?= <bjorn@rivosinc.com>
+Date: Wed, 20 Nov 2024 14:12:02 +0100
+Subject: riscv: mm: Do not call pmd dtor on vmemmap page table teardown
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Björn Töpel <bjorn@rivosinc.com>
+
+commit 21f1b85c8912262adf51707e63614a114425eb10 upstream.
+
+The vmemmap's, which is used for RV64 with SPARSEMEM_VMEMMAP, page
+tables are populated using pmd (page middle directory) hugetables.
+However, the pmd allocation is not using the generic mechanism used by
+the VMA code (e.g. pmd_alloc()), or the RISC-V specific
+create_pgd_mapping()/alloc_pmd_late(). Instead, the vmemmap page table
+code allocates a page, and calls vmemmap_set_pmd(). This results in
+that the pmd ctor is *not* called, nor would it make sense to do so.
+
+Now, when tearing down a vmemmap page table pmd, the cleanup code
+would unconditionally, and incorrectly call the pmd dtor, which
+results in a crash (best case).
+
+This issue was found when running the HMM selftests:
+
+  | tools/testing/selftests/mm# ./test_hmm.sh smoke
+  | ... # when unloading the test_hmm.ko module
+  | page: refcount:1 mapcount:0 mapping:0000000000000000 index:0x0 pfn:0x10915b
+  | flags: 0x1000000000000000(node=0|zone=1)
+  | raw: 1000000000000000 0000000000000000 dead000000000122 0000000000000000
+  | raw: 0000000000000000 0000000000000000 00000001ffffffff 0000000000000000
+  | page dumped because: VM_BUG_ON_PAGE(ptdesc->pmd_huge_pte)
+  | ------------[ cut here ]------------
+  | kernel BUG at include/linux/mm.h:3080!
+  | Kernel BUG [#1]
+  | Modules linked in: test_hmm(-) sch_fq_codel fuse drm drm_panel_orientation_quirks backlight dm_mod
+  | CPU: 1 UID: 0 PID: 514 Comm: modprobe Tainted: G        W          6.12.0-00982-gf2a4f1682d07 #2
+  | Tainted: [W]=WARN
+  | Hardware name: riscv-virtio qemu/qemu, BIOS 2024.10 10/01/2024
+  | epc : remove_pgd_mapping+0xbec/0x1070
+  |  ra : remove_pgd_mapping+0xbec/0x1070
+  | epc : ffffffff80010a68 ra : ffffffff80010a68 sp : ff20000000a73940
+  |  gp : ffffffff827b2d88 tp : ff6000008785da40 t0 : ffffffff80fbce04
+  |  t1 : 0720072007200720 t2 : 706d756420656761 s0 : ff20000000a73a50
+  |  s1 : ff6000008915cff8 a0 : 0000000000000039 a1 : 0000000000000008
+  |  a2 : ff600003fff0de20 a3 : 0000000000000000 a4 : 0000000000000000
+  |  a5 : 0000000000000000 a6 : c0000000ffffefff a7 : ffffffff824469b8
+  |  s2 : ff1c0000022456c0 s3 : ff1ffffffdbfffff s4 : ff6000008915c000
+  |  s5 : ff6000008915c000 s6 : ff6000008915c000 s7 : ff1ffffffdc00000
+  |  s8 : 0000000000000001 s9 : ff1ffffffdc00000 s10: ffffffff819a31f0
+  |  s11: ffffffffffffffff t3 : ffffffff8000c950 t4 : ff60000080244f00
+  |  t5 : ff60000080244000 t6 : ff20000000a73708
+  | status: 0000000200000120 badaddr: ffffffff80010a68 cause: 0000000000000003
+  | [<ffffffff80010a68>] remove_pgd_mapping+0xbec/0x1070
+  | [<ffffffff80fd238e>] vmemmap_free+0x14/0x1e
+  | [<ffffffff8032e698>] section_deactivate+0x220/0x452
+  | [<ffffffff8032ef7e>] sparse_remove_section+0x4a/0x58
+  | [<ffffffff802f8700>] __remove_pages+0x7e/0xba
+  | [<ffffffff803760d8>] memunmap_pages+0x2bc/0x3fe
+  | [<ffffffff02a3ca28>] dmirror_device_remove_chunks+0x2ea/0x518 [test_hmm]
+  | [<ffffffff02a3e026>] hmm_dmirror_exit+0x3e/0x1018 [test_hmm]
+  | [<ffffffff80102c14>] __riscv_sys_delete_module+0x15a/0x2a6
+  | [<ffffffff80fd020c>] do_trap_ecall_u+0x1f2/0x266
+  | [<ffffffff80fde0a2>] _new_vmalloc_restore_context_a0+0xc6/0xd2
+  | Code: bf51 7597 0184 8593 76a5 854a 4097 0029 80e7 2c00 (9002) 7597
+  | ---[ end trace 0000000000000000 ]---
+  | Kernel panic - not syncing: Fatal exception in interrupt
+
+Add a check to avoid calling the pmd dtor, if the calling context is
+vmemmap_free().
+
+Fixes: c75a74f4ba19 ("riscv: mm: Add memory hotplugging support")
+Signed-off-by: Björn Töpel <bjorn@rivosinc.com>
+Reviewed-by: Alexandre Ghiti <alexghiti@rivosinc.com>
+Link: https://lore.kernel.org/r/20241120131203.1859787-1-bjorn@kernel.org
+Cc: stable@vger.kernel.org
+Signed-off-by: Palmer Dabbelt <palmer@rivosinc.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ arch/riscv/mm/init.c | 7 ++++---
+ 1 file changed, 4 insertions(+), 3 deletions(-)
+
+diff --git a/arch/riscv/mm/init.c b/arch/riscv/mm/init.c
+index 0e8c20adcd98..fc53ce748c80 100644
+--- a/arch/riscv/mm/init.c
++++ b/arch/riscv/mm/init.c
+@@ -1566,7 +1566,7 @@ static void __meminit free_pte_table(pte_t *pte_start, pmd_t *pmd)
+       pmd_clear(pmd);
+ }
+-static void __meminit free_pmd_table(pmd_t *pmd_start, pud_t *pud)
++static void __meminit free_pmd_table(pmd_t *pmd_start, pud_t *pud, bool is_vmemmap)
+ {
+       struct page *page = pud_page(*pud);
+       struct ptdesc *ptdesc = page_ptdesc(page);
+@@ -1579,7 +1579,8 @@ static void __meminit free_pmd_table(pmd_t *pmd_start, pud_t *pud)
+                       return;
+       }
+-      pagetable_pmd_dtor(ptdesc);
++      if (!is_vmemmap)
++              pagetable_pmd_dtor(ptdesc);
+       if (PageReserved(page))
+               free_reserved_page(page);
+       else
+@@ -1703,7 +1704,7 @@ static void __meminit remove_pud_mapping(pud_t *pud_base, unsigned long addr, un
+               remove_pmd_mapping(pmd_base, addr, next, is_vmemmap, altmap);
+               if (pgtable_l4_enabled)
+-                      free_pmd_table(pmd_base, pudp);
++                      free_pmd_table(pmd_base, pudp, is_vmemmap);
+       }
+ }
+-- 
+2.47.1
+
diff --git a/queue-6.12/sched-deadline-fix-replenish_dl_new_period-dl_server-condition.patch b/queue-6.12/sched-deadline-fix-replenish_dl_new_period-dl_server-condition.patch
new file mode 100644 (file)
index 0000000..05ba61e
--- /dev/null
@@ -0,0 +1,41 @@
+From 22368fe1f9bbf39db2b5b52859589883273e80ce Mon Sep 17 00:00:00 2001
+From: Juri Lelli <juri.lelli@redhat.com>
+Date: Wed, 27 Nov 2024 07:37:40 +0100
+Subject: sched/deadline: Fix replenish_dl_new_period dl_server condition
+
+From: Juri Lelli <juri.lelli@redhat.com>
+
+commit 22368fe1f9bbf39db2b5b52859589883273e80ce upstream.
+
+The condition in replenish_dl_new_period() that checks if a reservation
+(dl_server) is deferred and is not handling a starvation case is
+obviously wrong.
+
+Fix it.
+
+Fixes: a110a81c52a9 ("sched/deadline: Deferrable dl server")
+Signed-off-by: Juri Lelli <juri.lelli@redhat.com>
+Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
+Cc: stable@vger.kernel.org
+Link: https://lkml.kernel.org/r/20241127063740.8278-1-juri.lelli@redhat.com
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ kernel/sched/deadline.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/kernel/sched/deadline.c b/kernel/sched/deadline.c
+index d9d5a702f1a6..206691d35b7d 100644
+--- a/kernel/sched/deadline.c
++++ b/kernel/sched/deadline.c
+@@ -781,7 +781,7 @@ static inline void replenish_dl_new_period(struct sched_dl_entity *dl_se,
+        * If it is a deferred reservation, and the server
+        * is not handling an starvation case, defer it.
+        */
+-      if (dl_se->dl_defer & !dl_se->dl_defer_running) {
++      if (dl_se->dl_defer && !dl_se->dl_defer_running) {
+               dl_se->dl_throttled = 1;
+               dl_se->dl_defer_armed = 1;
+       }
+-- 
+2.47.1
+
diff --git a/queue-6.12/serial-sh-sci-check-if-tx-data-was-written-to-device-in-.tx_empty.patch b/queue-6.12/serial-sh-sci-check-if-tx-data-was-written-to-device-in-.tx_empty.patch
new file mode 100644 (file)
index 0000000..8e1eb83
--- /dev/null
@@ -0,0 +1,143 @@
+From 7cc0e0a43a91052477c2921f924a37d9c3891f0c Mon Sep 17 00:00:00 2001
+From: Claudiu Beznea <claudiu.beznea.uj@bp.renesas.com>
+Date: Mon, 25 Nov 2024 13:58:56 +0200
+Subject: serial: sh-sci: Check if TX data was written to device in .tx_empty()
+
+From: Claudiu Beznea <claudiu.beznea.uj@bp.renesas.com>
+
+commit 7cc0e0a43a91052477c2921f924a37d9c3891f0c upstream.
+
+On the Renesas RZ/G3S, when doing suspend to RAM, the uart_suspend_port()
+is called. The uart_suspend_port() calls 3 times the
+struct uart_port::ops::tx_empty() before shutting down the port.
+
+According to the documentation, the struct uart_port::ops::tx_empty()
+API tests whether the transmitter FIFO and shifter for the port is
+empty.
+
+The Renesas RZ/G3S SCIFA IP reports the number of data units stored in the
+transmit FIFO through the FDR (FIFO Data Count Register). The data units
+in the FIFOs are written in the shift register and transmitted from there.
+The TEND bit in the Serial Status Register reports if the data was
+transmitted from the shift register.
+
+In the previous code, in the tx_empty() API implemented by the sh-sci
+driver, it is considered that the TX is empty if the hardware reports the
+TEND bit set and the number of data units in the FIFO is zero.
+
+According to the HW manual, the TEND bit has the following meaning:
+
+0: Transmission is in the waiting state or in progress.
+1: Transmission is completed.
+
+It has been noticed that when opening the serial device w/o using it and
+then switch to a power saving mode, the tx_empty() call in the
+uart_port_suspend() function fails, leading to the "Unable to drain
+transmitter" message being printed on the console. This is because the
+TEND=0 if nothing has been transmitted and the FIFOs are empty. As the
+TEND=0 has double meaning (waiting state, in progress) we can't
+determined the scenario described above.
+
+Add a software workaround for this. This sets a variable if any data has
+been sent on the serial console (when using PIO) or if the DMA callback has
+been called (meaning something has been transmitted). In the tx_empty()
+API the status of the DMA transaction is also checked and if it is
+completed or in progress the code falls back in checking the hardware
+registers instead of relying on the software variable.
+
+Fixes: 73a19e4c0301 ("serial: sh-sci: Add DMA support.")
+Cc: stable@vger.kernel.org
+Signed-off-by: Claudiu Beznea <claudiu.beznea.uj@bp.renesas.com>
+Link: https://lore.kernel.org/r/20241125115856.513642-1-claudiu.beznea.uj@bp.renesas.com
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/tty/serial/sh-sci.c |   29 +++++++++++++++++++++++++++++
+ 1 file changed, 29 insertions(+)
+
+--- a/drivers/tty/serial/sh-sci.c
++++ b/drivers/tty/serial/sh-sci.c
+@@ -157,6 +157,7 @@ struct sci_port {
+       bool has_rtscts;
+       bool autorts;
++      bool tx_occurred;
+ };
+ #define SCI_NPORTS CONFIG_SERIAL_SH_SCI_NR_UARTS
+@@ -850,6 +851,7 @@ static void sci_transmit_chars(struct ua
+ {
+       struct tty_port *tport = &port->state->port;
+       unsigned int stopped = uart_tx_stopped(port);
++      struct sci_port *s = to_sci_port(port);
+       unsigned short status;
+       unsigned short ctrl;
+       int count;
+@@ -885,6 +887,7 @@ static void sci_transmit_chars(struct ua
+               }
+               sci_serial_out(port, SCxTDR, c);
++              s->tx_occurred = true;
+               port->icount.tx++;
+       } while (--count > 0);
+@@ -1241,6 +1244,8 @@ static void sci_dma_tx_complete(void *ar
+       if (kfifo_len(&tport->xmit_fifo) < WAKEUP_CHARS)
+               uart_write_wakeup(port);
++      s->tx_occurred = true;
++
+       if (!kfifo_is_empty(&tport->xmit_fifo)) {
+               s->cookie_tx = 0;
+               schedule_work(&s->work_tx);
+@@ -1731,6 +1736,19 @@ static void sci_flush_buffer(struct uart
+               s->cookie_tx = -EINVAL;
+       }
+ }
++
++static void sci_dma_check_tx_occurred(struct sci_port *s)
++{
++      struct dma_tx_state state;
++      enum dma_status status;
++
++      if (!s->chan_tx)
++              return;
++
++      status = dmaengine_tx_status(s->chan_tx, s->cookie_tx, &state);
++      if (status == DMA_COMPLETE || status == DMA_IN_PROGRESS)
++              s->tx_occurred = true;
++}
+ #else /* !CONFIG_SERIAL_SH_SCI_DMA */
+ static inline void sci_request_dma(struct uart_port *port)
+ {
+@@ -1740,6 +1758,10 @@ static inline void sci_free_dma(struct u
+ {
+ }
++static void sci_dma_check_tx_occurred(struct sci_port *s)
++{
++}
++
+ #define sci_flush_buffer      NULL
+ #endif /* !CONFIG_SERIAL_SH_SCI_DMA */
+@@ -2076,6 +2098,12 @@ static unsigned int sci_tx_empty(struct
+ {
+       unsigned short status = sci_serial_in(port, SCxSR);
+       unsigned short in_tx_fifo = sci_txfill(port);
++      struct sci_port *s = to_sci_port(port);
++
++      sci_dma_check_tx_occurred(s);
++
++      if (!s->tx_occurred)
++              return TIOCSER_TEMT;
+       return (status & SCxSR_TEND(port)) && !in_tx_fifo ? TIOCSER_TEMT : 0;
+ }
+@@ -2247,6 +2275,7 @@ static int sci_startup(struct uart_port
+       dev_dbg(port->dev, "%s(%d)\n", __func__, port->line);
++      s->tx_occurred = false;
+       sci_request_dma(port);
+       ret = sci_request_irq(s);
diff --git a/queue-6.12/series b/queue-6.12/series
new file mode 100644 (file)
index 0000000..1671f9c
--- /dev/null
@@ -0,0 +1,38 @@
+usb-misc-onboard_usb_dev-skip-suspend-resume-sequence-for-usb5744-smbus-support.patch
+serial-sh-sci-check-if-tx-data-was-written-to-device-in-.tx_empty.patch
+bpf-fix-uaf-via-mismatching-bpf_prog-attachment-rcu-flavors.patch
+sched-deadline-fix-replenish_dl_new_period-dl_server-condition.patch
+perf-x86-intel-ds-unconditionally-drain-pebs-ds-when-changing-pebs_data_cfg.patch
+clk-en7523-fix-wrong-bus-clock-for-en7581.patch
+ksmbd-fix-racy-issue-from-session-lookup-and-expire.patch
+splice-do-not-checksum-af_unix-sockets.patch
+tcp-check-space-before-adding-mptcp-syn-options.patch
+perf-ftrace-fix-undefined-behavior-in-cmp_profile_data.patch
+virtio_net-correct-netdev_tx_reset_queue-invocation-point.patch
+virtio_ring-add-a-func-argument-recycle_done-to-virtqueue_resize.patch
+virtio_net-ensure-netdev_tx_reset_queue-is-called-on-tx-ring-resize.patch
+riscv-mm-do-not-call-pmd-dtor-on-vmemmap-page-table-teardown.patch
+riscv-fix-wrong-usage-of-__pa-on-a-fixmap-address.patch
+blk-cgroup-fix-uaf-in-blkcg_unpin_online.patch
+block-switch-to-using-refcount_t-for-zone-write-plugs.patch
+block-use-a-zone-write-plug-bio-work-for-req_nowait-bios.patch
+dm-fix-dm-zoned-reclaim-zone-write-pointer-alignment.patch
+block-prevent-potential-deadlocks-in-zone-write-plug-error-recovery.patch
+gpio-graniterapids-fix-gpio-ack-functionality.patch
+memcg-slub-fix-sunreclaim-for-post-charged-objects.patch
+spi-rockchip-fix-pm-runtime-count-on-no-op-cs.patch
+gpio-ljca-initialize-num-before-accessing-item-in-ljca_gpio_config.patch
+alsa-usb-audio-add-implicit-feedback-quirk-for-yamaha-thr5.patch
+alsa-hda-realtek-fix-headset-mic-on-acer-nitro-5.patch
+riscv-fix-ipis-usage-in-kfence_protect_page.patch
+crypto-hisilicon-debugfs-fix-the-struct-pointer-incorrectly-offset-problem.patch
+drm-panic-remove-spurious-empty-line-to-clean-warning.patch
+usb-host-max3421-hcd-correctly-abort-a-usb-request.patch
+block-ignore-req_nowait-for-zone-reset-and-zone-finish-operations.patch
+gpio-graniterapids-fix-vgpio-driver-crash.patch
+gpio-graniterapids-fix-incorrect-bar-assignment.patch
+gpio-graniterapids-fix-invalid-gpi_is-register-offset.patch
+gpio-graniterapids-fix-invalid-rxevcfg-register-bitmask.patch
+gpio-graniterapids-determine-if-gpio-pad-can-be-used-by-driver.patch
+gpio-graniterapids-check-if-gpio-line-can-be-used-for-irqs.patch
+usb-core-hcd-only-check-primary-hcd-skip_phy_initialization.patch
diff --git a/queue-6.12/spi-rockchip-fix-pm-runtime-count-on-no-op-cs.patch b/queue-6.12/spi-rockchip-fix-pm-runtime-count-on-no-op-cs.patch
new file mode 100644 (file)
index 0000000..8c12067
--- /dev/null
@@ -0,0 +1,49 @@
+From 0bb394067a792e7119abc9e0b7158ef19381f456 Mon Sep 17 00:00:00 2001
+From: Christian Loehle <christian.loehle@arm.com>
+Date: Fri, 6 Dec 2024 19:50:55 +0000
+Subject: spi: rockchip: Fix PM runtime count on no-op cs
+
+From: Christian Loehle <christian.loehle@arm.com>
+
+commit 0bb394067a792e7119abc9e0b7158ef19381f456 upstream.
+
+The early bail out that caused an out-of-bounds write was removed with
+commit 5c018e378f91 ("spi: spi-rockchip: Fix out of bounds array
+access")
+Unfortunately that caused the PM runtime count to be unbalanced and
+underflowed on the first call. To fix that reintroduce a no-op check
+by reading the register directly.
+
+Cc: stable@vger.kernel.org
+Fixes: 5c018e378f91 ("spi: spi-rockchip: Fix out of bounds array access")
+Signed-off-by: Christian Loehle <christian.loehle@arm.com>
+Link: https://patch.msgid.link/1f2b3af4-2b7a-4ac8-ab95-c80120ebf44c@arm.com
+Signed-off-by: Mark Brown <broonie@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/spi/spi-rockchip.c |   14 ++++++++++++++
+ 1 file changed, 14 insertions(+)
+
+--- a/drivers/spi/spi-rockchip.c
++++ b/drivers/spi/spi-rockchip.c
+@@ -241,6 +241,20 @@ static void rockchip_spi_set_cs(struct s
+       struct spi_controller *ctlr = spi->controller;
+       struct rockchip_spi *rs = spi_controller_get_devdata(ctlr);
+       bool cs_asserted = spi->mode & SPI_CS_HIGH ? enable : !enable;
++      bool cs_actual;
++
++      /*
++       * SPI subsystem tries to avoid no-op calls that would break the PM
++       * refcount below. It can't however for the first time it is used.
++       * To detect this case we read it here and bail out early for no-ops.
++       */
++      if (spi_get_csgpiod(spi, 0))
++              cs_actual = !!(readl_relaxed(rs->regs + ROCKCHIP_SPI_SER) & 1);
++      else
++              cs_actual = !!(readl_relaxed(rs->regs + ROCKCHIP_SPI_SER) &
++                             BIT(spi_get_chipselect(spi, 0)));
++      if (unlikely(cs_actual == cs_asserted))
++              return;
+       if (cs_asserted) {
+               /* Keep things powered as long as CS is asserted */
diff --git a/queue-6.12/splice-do-not-checksum-af_unix-sockets.patch b/queue-6.12/splice-do-not-checksum-af_unix-sockets.patch
new file mode 100644 (file)
index 0000000..789f918
--- /dev/null
@@ -0,0 +1,44 @@
+From 6bd8614fc2d076fc21b7488c9f279853960964e2 Mon Sep 17 00:00:00 2001
+From: Frederik Deweerdt <deweerdt.lkml@gmail.com>
+Date: Mon, 9 Dec 2024 21:06:48 -0800
+Subject: splice: do not checksum AF_UNIX sockets
+
+From: Frederik Deweerdt <deweerdt.lkml@gmail.com>
+
+commit 6bd8614fc2d076fc21b7488c9f279853960964e2 upstream.
+
+When `skb_splice_from_iter` was introduced, it inadvertently added
+checksumming for AF_UNIX sockets. This resulted in significant
+slowdowns, for example when using sendfile over unix sockets.
+
+Using the test code in [1] in my test setup (2G single core qemu),
+the client receives a 1000M file in:
+- without the patch: 1482ms (+/- 36ms)
+- with the patch: 652.5ms (+/- 22.9ms)
+
+This commit addresses the issue by marking checksumming as unnecessary in
+`unix_stream_sendmsg`
+
+Cc: stable@vger.kernel.org
+Signed-off-by: Frederik Deweerdt <deweerdt.lkml@gmail.com>
+Fixes: 2e910b95329c ("net: Add a function to splice pages into an skbuff for MSG_SPLICE_PAGES")
+Reviewed-by: Kuniyuki Iwashima <kuniyu@amazon.com>
+Reviewed-by: Eric Dumazet <edumazet@google.com>
+Reviewed-by: Joe Damato <jdamato@fastly.com>
+Link: https://patch.msgid.link/Z1fMaHkRf8cfubuE@xiberoa
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ net/unix/af_unix.c |    1 +
+ 1 file changed, 1 insertion(+)
+
+--- a/net/unix/af_unix.c
++++ b/net/unix/af_unix.c
+@@ -2313,6 +2313,7 @@ static int unix_stream_sendmsg(struct so
+               fds_sent = true;
+               if (unlikely(msg->msg_flags & MSG_SPLICE_PAGES)) {
++                      skb->ip_summed = CHECKSUM_UNNECESSARY;
+                       err = skb_splice_from_iter(skb, &msg->msg_iter, size,
+                                                  sk->sk_allocation);
+                       if (err < 0) {
diff --git a/queue-6.12/tcp-check-space-before-adding-mptcp-syn-options.patch b/queue-6.12/tcp-check-space-before-adding-mptcp-syn-options.patch
new file mode 100644 (file)
index 0000000..8c0b2a3
--- /dev/null
@@ -0,0 +1,44 @@
+From 06d64ab46f19ac12f59a1d2aa8cd196b2e4edb5b Mon Sep 17 00:00:00 2001
+From: MoYuanhao <moyuanhao3676@163.com>
+Date: Mon, 9 Dec 2024 13:28:14 +0100
+Subject: tcp: check space before adding MPTCP SYN options
+
+From: MoYuanhao <moyuanhao3676@163.com>
+
+commit 06d64ab46f19ac12f59a1d2aa8cd196b2e4edb5b upstream.
+
+Ensure there is enough space before adding MPTCP options in
+tcp_syn_options().
+
+Without this check, 'remaining' could underflow, and causes issues. If
+there is not enough space, MPTCP should not be used.
+
+Signed-off-by: MoYuanhao <moyuanhao3676@163.com>
+Fixes: cec37a6e41aa ("mptcp: Handle MP_CAPABLE options for outgoing connections")
+Cc: stable@vger.kernel.org
+Acked-by: Matthieu Baerts (NGI0) <matttbe@kernel.org>
+[ Matt: Add Fixes, cc Stable, update Description ]
+Signed-off-by: Matthieu Baerts (NGI0) <matttbe@kernel.org>
+Reviewed-by: Eric Dumazet <edumazet@google.com>
+Link: https://patch.msgid.link/20241209-net-mptcp-check-space-syn-v1-1-2da992bb6f74@kernel.org
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ net/ipv4/tcp_output.c |    6 ++++--
+ 1 file changed, 4 insertions(+), 2 deletions(-)
+
+--- a/net/ipv4/tcp_output.c
++++ b/net/ipv4/tcp_output.c
+@@ -883,8 +883,10 @@ static unsigned int tcp_syn_options(stru
+               unsigned int size;
+               if (mptcp_syn_options(sk, skb, &size, &opts->mptcp)) {
+-                      opts->options |= OPTION_MPTCP;
+-                      remaining -= size;
++                      if (remaining >= size) {
++                              opts->options |= OPTION_MPTCP;
++                              remaining -= size;
++                      }
+               }
+       }
diff --git a/queue-6.12/usb-core-hcd-only-check-primary-hcd-skip_phy_initialization.patch b/queue-6.12/usb-core-hcd-only-check-primary-hcd-skip_phy_initialization.patch
new file mode 100644 (file)
index 0000000..dd6c5f9
--- /dev/null
@@ -0,0 +1,45 @@
+From d2ec94fbc431cc77ed53d4480bdc856669c2b5aa Mon Sep 17 00:00:00 2001
+From: Xu Yang <xu.yang_2@nxp.com>
+Date: Tue, 5 Nov 2024 17:01:20 +0800
+Subject: usb: core: hcd: only check primary hcd skip_phy_initialization
+
+From: Xu Yang <xu.yang_2@nxp.com>
+
+commit d2ec94fbc431cc77ed53d4480bdc856669c2b5aa upstream.
+
+Before commit 53a2d95df836 ("usb: core: add phy notify connect and
+disconnect"), phy initialization will be skipped even when shared hcd
+doesn't set skip_phy_initialization flag. However, the situation is
+changed after the commit. The hcd.c will initialize phy when add shared
+hcd. This behavior is unexpected for some platforms which will handle phy
+initialization by themselves. To avoid the issue, this will only check
+skip_phy_initialization flag of primary hcd since shared hcd normally
+follow primary hcd setting.
+
+Fixes: 53a2d95df836 ("usb: core: add phy notify connect and disconnect")
+Cc: stable@vger.kernel.org
+Signed-off-by: Xu Yang <xu.yang_2@nxp.com>
+Link: https://lore.kernel.org/r/20241105090120.2438366-1-xu.yang_2@nxp.com
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/usb/core/hcd.c |    8 +++++++-
+ 1 file changed, 7 insertions(+), 1 deletion(-)
+
+--- a/drivers/usb/core/hcd.c
++++ b/drivers/usb/core/hcd.c
+@@ -2794,8 +2794,14 @@ int usb_add_hcd(struct usb_hcd *hcd,
+       int retval;
+       struct usb_device *rhdev;
+       struct usb_hcd *shared_hcd;
++      int skip_phy_initialization;
+-      if (!hcd->skip_phy_initialization) {
++      if (usb_hcd_is_primary_hcd(hcd))
++              skip_phy_initialization = hcd->skip_phy_initialization;
++      else
++              skip_phy_initialization = hcd->primary_hcd->skip_phy_initialization;
++
++      if (!skip_phy_initialization) {
+               if (usb_hcd_is_primary_hcd(hcd)) {
+                       hcd->phy_roothub = usb_phy_roothub_alloc(hcd->self.sysdev);
+                       if (IS_ERR(hcd->phy_roothub))
diff --git a/queue-6.12/usb-host-max3421-hcd-correctly-abort-a-usb-request.patch b/queue-6.12/usb-host-max3421-hcd-correctly-abort-a-usb-request.patch
new file mode 100644 (file)
index 0000000..1b70d30
--- /dev/null
@@ -0,0 +1,50 @@
+From 0d2ada05227881f3d0722ca2364e3f7a860a301f Mon Sep 17 00:00:00 2001
+From: Mark Tomlinson <mark.tomlinson@alliedtelesis.co.nz>
+Date: Mon, 25 Nov 2024 11:14:30 +1300
+Subject: usb: host: max3421-hcd: Correctly abort a USB request.
+
+From: Mark Tomlinson <mark.tomlinson@alliedtelesis.co.nz>
+
+commit 0d2ada05227881f3d0722ca2364e3f7a860a301f upstream.
+
+If the current USB request was aborted, the spi thread would not respond
+to any further requests. This is because the "curr_urb" pointer would
+not become NULL, so no further requests would be taken off the queue.
+The solution here is to set the "urb_done" flag, as this will cause the
+correct handling of the URB. Also clear interrupts that should only be
+expected if an URB is in progress.
+
+Fixes: 2d53139f3162 ("Add support for using a MAX3421E chip as a host driver.")
+Cc: stable <stable@kernel.org>
+Signed-off-by: Mark Tomlinson <mark.tomlinson@alliedtelesis.co.nz>
+Link: https://lore.kernel.org/r/20241124221430.1106080-1-mark.tomlinson@alliedtelesis.co.nz
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/usb/host/max3421-hcd.c |   16 +++++++++++-----
+ 1 file changed, 11 insertions(+), 5 deletions(-)
+
+--- a/drivers/usb/host/max3421-hcd.c
++++ b/drivers/usb/host/max3421-hcd.c
+@@ -779,11 +779,17 @@ max3421_check_unlink(struct usb_hcd *hcd
+                               retval = 1;
+                               dev_dbg(&spi->dev, "%s: URB %p unlinked=%d",
+                                       __func__, urb, urb->unlinked);
+-                              usb_hcd_unlink_urb_from_ep(hcd, urb);
+-                              spin_unlock_irqrestore(&max3421_hcd->lock,
+-                                                     flags);
+-                              usb_hcd_giveback_urb(hcd, urb, 0);
+-                              spin_lock_irqsave(&max3421_hcd->lock, flags);
++                              if (urb == max3421_hcd->curr_urb) {
++                                      max3421_hcd->urb_done = 1;
++                                      max3421_hcd->hien &= ~(BIT(MAX3421_HI_HXFRDN_BIT) |
++                                                             BIT(MAX3421_HI_RCVDAV_BIT));
++                              } else {
++                                      usb_hcd_unlink_urb_from_ep(hcd, urb);
++                                      spin_unlock_irqrestore(&max3421_hcd->lock,
++                                                             flags);
++                                      usb_hcd_giveback_urb(hcd, urb, 0);
++                                      spin_lock_irqsave(&max3421_hcd->lock, flags);
++                              }
+                       }
+               }
+       }
diff --git a/queue-6.12/usb-misc-onboard_usb_dev-skip-suspend-resume-sequence-for-usb5744-smbus-support.patch b/queue-6.12/usb-misc-onboard_usb_dev-skip-suspend-resume-sequence-for-usb5744-smbus-support.patch
new file mode 100644 (file)
index 0000000..dd3a97a
--- /dev/null
@@ -0,0 +1,46 @@
+From ce15d6b3d5c3c6f78290066be0f0a4fd89cdeb5b Mon Sep 17 00:00:00 2001
+From: Radhey Shyam Pandey <radhey.shyam.pandey@amd.com>
+Date: Tue, 3 Dec 2024 00:18:22 +0530
+Subject: usb: misc: onboard_usb_dev: skip suspend/resume sequence for USB5744 SMBus support
+
+From: Radhey Shyam Pandey <radhey.shyam.pandey@amd.com>
+
+commit ce15d6b3d5c3c6f78290066be0f0a4fd89cdeb5b upstream.
+
+USB5744 SMBus initialization is done once in probe() and doing it in resume
+is not supported so avoid going into suspend and reset the HUB.
+
+There is a sysfs property 'always_powered_in_suspend' to implement this
+feature but since default state should be set to a working configuration
+so override this property value.
+
+It fixes the suspend/resume testcase on Kria KR260 Robotics Starter Kit.
+
+Fixes: 6782311d04df ("usb: misc: onboard_usb_dev: add Microchip usb5744 SMBus programming support")
+Cc: stable@vger.kernel.org
+Signed-off-by: Radhey Shyam Pandey <radhey.shyam.pandey@amd.com>
+Link: https://lore.kernel.org/r/1733165302-1694891-1-git-send-email-radhey.shyam.pandey@amd.com
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/usb/misc/onboard_usb_dev.c | 4 +++-
+ 1 file changed, 3 insertions(+), 1 deletion(-)
+
+diff --git a/drivers/usb/misc/onboard_usb_dev.c b/drivers/usb/misc/onboard_usb_dev.c
+index 36b11127280f..75ac3c6aa92d 100644
+--- a/drivers/usb/misc/onboard_usb_dev.c
++++ b/drivers/usb/misc/onboard_usb_dev.c
+@@ -407,8 +407,10 @@ static int onboard_dev_probe(struct platform_device *pdev)
+               }
+               if (of_device_is_compatible(pdev->dev.of_node, "usb424,2744") ||
+-                  of_device_is_compatible(pdev->dev.of_node, "usb424,5744"))
++                  of_device_is_compatible(pdev->dev.of_node, "usb424,5744")) {
+                       err = onboard_dev_5744_i2c_init(client);
++                      onboard_dev->always_powered_in_suspend = true;
++              }
+               put_device(&client->dev);
+               if (err < 0)
+-- 
+2.47.1
+
diff --git a/queue-6.12/virtio_net-correct-netdev_tx_reset_queue-invocation-point.patch b/queue-6.12/virtio_net-correct-netdev_tx_reset_queue-invocation-point.patch
new file mode 100644 (file)
index 0000000..d93e8ef
--- /dev/null
@@ -0,0 +1,189 @@
+From 3ddccbefebdbe0c4c72a248676e4d39ac66a8e26 Mon Sep 17 00:00:00 2001
+From: Koichiro Den <koichiro.den@canonical.com>
+Date: Fri, 6 Dec 2024 10:10:42 +0900
+Subject: virtio_net: correct netdev_tx_reset_queue() invocation point
+
+From: Koichiro Den <koichiro.den@canonical.com>
+
+commit 3ddccbefebdbe0c4c72a248676e4d39ac66a8e26 upstream.
+
+When virtnet_close is followed by virtnet_open, some TX completions can
+possibly remain unconsumed, until they are finally processed during the
+first NAPI poll after the netdev_tx_reset_queue(), resulting in a crash
+[1]. Commit b96ed2c97c79 ("virtio_net: move netdev_tx_reset_queue() call
+before RX napi enable") was not sufficient to eliminate all BQL crash
+cases for virtio-net.
+
+This issue can be reproduced with the latest net-next master by running:
+`while :; do ip l set DEV down; ip l set DEV up; done` under heavy network
+TX load from inside the machine.
+
+netdev_tx_reset_queue() can actually be dropped from virtnet_open path;
+the device is not stopped in any case. For BQL core part, it's just like
+traffic nearly ceases to exist for some period. For stall detector added
+to BQL, even if virtnet_close could somehow lead to some TX completions
+delayed for long, followed by virtnet_open, we can just take it as stall
+as mentioned in commit 6025b9135f7a ("net: dqs: add NIC stall detector
+based on BQL"). Note also that users can still reset stall_max via sysfs.
+
+So, drop netdev_tx_reset_queue() from virtnet_enable_queue_pair(). This
+eliminates the BQL crashes. As a result, netdev_tx_reset_queue() is now
+explicitly required in freeze/restore path. This patch adds it to
+immediately after free_unused_bufs(), following the rule of thumb:
+netdev_tx_reset_queue() should follow any SKB freeing not followed by
+netdev_tx_completed_queue(). This seems the most consistent and
+streamlined approach, and now netdev_tx_reset_queue() runs whenever
+free_unused_bufs() is done.
+
+[1]:
+------------[ cut here ]------------
+kernel BUG at lib/dynamic_queue_limits.c:99!
+Oops: invalid opcode: 0000 [#1] PREEMPT SMP NOPTI
+CPU: 7 UID: 0 PID: 1598 Comm: ip Tainted: G    N 6.12.0net-next_main+ #2
+Tainted: [N]=TEST
+Hardware name: QEMU Standard PC (Q35 + ICH9, 2009), \
+BIOS rel-1.16.3-0-ga6ed6b701f0a-prebuilt.qemu.org 04/01/2014
+RIP: 0010:dql_completed+0x26b/0x290
+Code: b7 c2 49 89 e9 44 89 da 89 c6 4c 89 d7 e8 ed 17 47 00 58 65 ff 0d
+4d 27 90 7e 0f 85 fd fe ff ff e8 ea 53 8d ff e9 f3 fe ff ff <0f> 0b 01
+d2 44 89 d1 29 d1 ba 00 00 00 00 0f 48 ca e9 28 ff ff ff
+RSP: 0018:ffffc900002b0d08 EFLAGS: 00010297
+RAX: 0000000000000000 RBX: ffff888102398c80 RCX: 0000000080190009
+RDX: 0000000000000000 RSI: 000000000000006a RDI: 0000000000000000
+RBP: ffff888102398c00 R08: 0000000000000000 R09: 0000000000000000
+R10: 00000000000000ca R11: 0000000000015681 R12: 0000000000000001
+R13: ffffc900002b0d68 R14: ffff88811115e000 R15: ffff8881107aca40
+FS:  00007f41ded69500(0000) GS:ffff888667dc0000(0000)
+knlGS:0000000000000000
+CS:  0010 DS: 0000 ES: 0000 CR0: 0000000080050033
+CR2: 0000556ccc2dc1a0 CR3: 0000000104fd8003 CR4: 0000000000772ef0
+PKRU: 55555554
+Call Trace:
+ <IRQ>
+ ? die+0x32/0x80
+ ? do_trap+0xd9/0x100
+ ? dql_completed+0x26b/0x290
+ ? dql_completed+0x26b/0x290
+ ? do_error_trap+0x6d/0xb0
+ ? dql_completed+0x26b/0x290
+ ? exc_invalid_op+0x4c/0x60
+ ? dql_completed+0x26b/0x290
+ ? asm_exc_invalid_op+0x16/0x20
+ ? dql_completed+0x26b/0x290
+ __free_old_xmit+0xff/0x170 [virtio_net]
+ free_old_xmit+0x54/0xc0 [virtio_net]
+ virtnet_poll+0xf4/0xe30 [virtio_net]
+ ? __update_load_avg_cfs_rq+0x264/0x2d0
+ ? update_curr+0x35/0x260
+ ? reweight_entity+0x1be/0x260
+ __napi_poll.constprop.0+0x28/0x1c0
+ net_rx_action+0x329/0x420
+ ? enqueue_hrtimer+0x35/0x90
+ ? trace_hardirqs_on+0x1d/0x80
+ ? kvm_sched_clock_read+0xd/0x20
+ ? sched_clock+0xc/0x30
+ ? kvm_sched_clock_read+0xd/0x20
+ ? sched_clock+0xc/0x30
+ ? sched_clock_cpu+0xd/0x1a0
+ handle_softirqs+0x138/0x3e0
+ do_softirq.part.0+0x89/0xc0
+ </IRQ>
+ <TASK>
+ __local_bh_enable_ip+0xa7/0xb0
+ virtnet_open+0xc8/0x310 [virtio_net]
+ __dev_open+0xfa/0x1b0
+ __dev_change_flags+0x1de/0x250
+ dev_change_flags+0x22/0x60
+ do_setlink.isra.0+0x2df/0x10b0
+ ? rtnetlink_rcv_msg+0x34f/0x3f0
+ ? netlink_rcv_skb+0x54/0x100
+ ? netlink_unicast+0x23e/0x390
+ ? netlink_sendmsg+0x21e/0x490
+ ? ____sys_sendmsg+0x31b/0x350
+ ? avc_has_perm_noaudit+0x67/0xf0
+ ? cred_has_capability.isra.0+0x75/0x110
+ ? __nla_validate_parse+0x5f/0xee0
+ ? __pfx___probestub_irq_enable+0x3/0x10
+ ? __create_object+0x5e/0x90
+ ? security_capable+0x3b/0x70
+ rtnl_newlink+0x784/0xaf0
+ ? avc_has_perm_noaudit+0x67/0xf0
+ ? cred_has_capability.isra.0+0x75/0x110
+ ? stack_depot_save_flags+0x24/0x6d0
+ ? __pfx_rtnl_newlink+0x10/0x10
+ rtnetlink_rcv_msg+0x34f/0x3f0
+ ? do_syscall_64+0x6c/0x180
+ ? entry_SYSCALL_64_after_hwframe+0x76/0x7e
+ ? __pfx_rtnetlink_rcv_msg+0x10/0x10
+ netlink_rcv_skb+0x54/0x100
+ netlink_unicast+0x23e/0x390
+ netlink_sendmsg+0x21e/0x490
+ ____sys_sendmsg+0x31b/0x350
+ ? copy_msghdr_from_user+0x6d/0xa0
+ ___sys_sendmsg+0x86/0xd0
+ ? __pte_offset_map+0x17/0x160
+ ? preempt_count_add+0x69/0xa0
+ ? __call_rcu_common.constprop.0+0x147/0x610
+ ? preempt_count_add+0x69/0xa0
+ ? preempt_count_add+0x69/0xa0
+ ? _raw_spin_trylock+0x13/0x60
+ ? trace_hardirqs_on+0x1d/0x80
+ __sys_sendmsg+0x66/0xc0
+ do_syscall_64+0x6c/0x180
+ entry_SYSCALL_64_after_hwframe+0x76/0x7e
+RIP: 0033:0x7f41defe5b34
+Code: 15 e1 12 0f 00 f7 d8 64 89 02 b8 ff ff ff ff eb bf 0f 1f 44 00 00
+f3 0f 1e fa 80 3d 35 95 0f 00 00 74 13 b8 2e 00 00 00 0f 05 <48> 3d 00
+f0 ff ff 77 4c c3 0f 1f 00 55 48 89 e5 48 83 ec 20 89 55
+RSP: 002b:00007ffe5336ecc8 EFLAGS: 00000202 ORIG_RAX: 000000000000002e
+RAX: ffffffffffffffda RBX: 0000000000000003 RCX: 00007f41defe5b34
+RDX: 0000000000000000 RSI: 00007ffe5336ed30 RDI: 0000000000000003
+RBP: 00007ffe5336eda0 R08: 0000000000000010 R09: 0000000000000001
+R10: 00007ffe5336f6f9 R11: 0000000000000202 R12: 0000000000000003
+R13: 0000000067452259 R14: 0000556ccc28b040 R15: 0000000000000000
+ </TASK>
+[...]
+
+Fixes: c8bd1f7f3e61 ("virtio_net: add support for Byte Queue Limits")
+Cc: <stable@vger.kernel.org> # v6.11+
+Signed-off-by: Koichiro Den <koichiro.den@canonical.com>
+Acked-by: Jason Wang <jasowang@redhat.com>
+Reviewed-by: Xuan Zhuo <xuanzhuo@linux.alibaba.com>
+[ pabeni: trimmed possibly troublesome separator ]
+Signed-off-by: Paolo Abeni <pabeni@redhat.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/net/virtio_net.c |   10 +++++++++-
+ 1 file changed, 9 insertions(+), 1 deletion(-)
+
+--- a/drivers/net/virtio_net.c
++++ b/drivers/net/virtio_net.c
+@@ -2898,7 +2898,6 @@ static int virtnet_enable_queue_pair(str
+       if (err < 0)
+               goto err_xdp_reg_mem_model;
+-      netdev_tx_reset_queue(netdev_get_tx_queue(vi->dev, qp_index));
+       virtnet_napi_enable(vi->rq[qp_index].vq, &vi->rq[qp_index].napi);
+       virtnet_napi_tx_enable(vi, vi->sq[qp_index].vq, &vi->sq[qp_index].napi);
+@@ -6728,11 +6727,20 @@ free:
+ static void remove_vq_common(struct virtnet_info *vi)
+ {
++      int i;
++
+       virtio_reset_device(vi->vdev);
+       /* Free unused buffers in both send and recv, if any. */
+       free_unused_bufs(vi);
++      /*
++       * Rule of thumb is netdev_tx_reset_queue() should follow any
++       * skb freeing not followed by netdev_tx_completed_queue()
++       */
++      for (i = 0; i < vi->max_queue_pairs; i++)
++              netdev_tx_reset_queue(netdev_get_tx_queue(vi->dev, i));
++
+       free_receive_bufs(vi);
+       free_receive_page_frags(vi);
diff --git a/queue-6.12/virtio_net-ensure-netdev_tx_reset_queue-is-called-on-tx-ring-resize.patch b/queue-6.12/virtio_net-ensure-netdev_tx_reset_queue-is-called-on-tx-ring-resize.patch
new file mode 100644 (file)
index 0000000..558f60d
--- /dev/null
@@ -0,0 +1,60 @@
+From 1480f0f61b675567ca5d0943d6ef2e39172dcafd Mon Sep 17 00:00:00 2001
+From: Koichiro Den <koichiro.den@canonical.com>
+Date: Fri, 6 Dec 2024 10:10:45 +0900
+Subject: virtio_net: ensure netdev_tx_reset_queue is called on tx ring resize
+
+From: Koichiro Den <koichiro.den@canonical.com>
+
+commit 1480f0f61b675567ca5d0943d6ef2e39172dcafd upstream.
+
+virtnet_tx_resize() flushes remaining tx skbs, requiring DQL counters to
+be reset when flushing has actually occurred. Add
+virtnet_sq_free_unused_buf_done() as a callback for virtqueue_reset() to
+handle this.
+
+Fixes: c8bd1f7f3e61 ("virtio_net: add support for Byte Queue Limits")
+Cc: <stable@vger.kernel.org> # v6.11+
+Signed-off-by: Koichiro Den <koichiro.den@canonical.com>
+Acked-by: Jason Wang <jasowang@redhat.com>
+Reviewed-by: Xuan Zhuo <xuanzhuo@linux.alibaba.com>
+Signed-off-by: Paolo Abeni <pabeni@redhat.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/net/virtio_net.c |   12 +++++++++++-
+ 1 file changed, 11 insertions(+), 1 deletion(-)
+
+--- a/drivers/net/virtio_net.c
++++ b/drivers/net/virtio_net.c
+@@ -502,6 +502,7 @@ struct virtio_net_common_hdr {
+ };
+ static void virtnet_sq_free_unused_buf(struct virtqueue *vq, void *buf);
++static void virtnet_sq_free_unused_buf_done(struct virtqueue *vq);
+ static int virtnet_xdp_handler(struct bpf_prog *xdp_prog, struct xdp_buff *xdp,
+                              struct net_device *dev,
+                              unsigned int *xdp_xmit,
+@@ -3228,7 +3229,8 @@ static int virtnet_tx_resize(struct virt
+       virtnet_tx_pause(vi, sq);
+-      err = virtqueue_resize(sq->vq, ring_num, virtnet_sq_free_unused_buf, NULL);
++      err = virtqueue_resize(sq->vq, ring_num, virtnet_sq_free_unused_buf,
++                             virtnet_sq_free_unused_buf_done);
+       if (err)
+               netdev_err(vi->dev, "resize tx fail: tx queue index: %d err: %d\n", qindex, err);
+@@ -5996,6 +5998,14 @@ static void virtnet_sq_free_unused_buf(s
+               xdp_return_frame(ptr_to_xdp(buf));
+ }
++static void virtnet_sq_free_unused_buf_done(struct virtqueue *vq)
++{
++      struct virtnet_info *vi = vq->vdev->priv;
++      int i = vq2txq(vq);
++
++      netdev_tx_reset_queue(netdev_get_tx_queue(vi->dev, i));
++}
++
+ static void free_unused_bufs(struct virtnet_info *vi)
+ {
+       void *buf;
diff --git a/queue-6.12/virtio_ring-add-a-func-argument-recycle_done-to-virtqueue_resize.patch b/queue-6.12/virtio_ring-add-a-func-argument-recycle_done-to-virtqueue_resize.patch
new file mode 100644 (file)
index 0000000..76d857f
--- /dev/null
@@ -0,0 +1,87 @@
+From 8d6712c892019b9b9dc5c7039edd3c9d770b510b Mon Sep 17 00:00:00 2001
+From: Koichiro Den <koichiro.den@canonical.com>
+Date: Fri, 6 Dec 2024 10:10:44 +0900
+Subject: virtio_ring: add a func argument 'recycle_done' to virtqueue_resize()
+
+From: Koichiro Den <koichiro.den@canonical.com>
+
+commit 8d6712c892019b9b9dc5c7039edd3c9d770b510b upstream.
+
+When virtqueue_resize() has actually recycled all unused buffers,
+additional work may be required in some cases. Relying solely on its
+return status is fragile, so introduce a new function argument
+'recycle_done', which is invoked when the recycle really occurs.
+
+Cc: <stable@vger.kernel.org> # v6.11+
+Signed-off-by: Koichiro Den <koichiro.den@canonical.com>
+Acked-by: Jason Wang <jasowang@redhat.com>
+Reviewed-by: Xuan Zhuo <xuanzhuo@linux.alibaba.com>
+Signed-off-by: Paolo Abeni <pabeni@redhat.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/net/virtio_net.c     |    4 ++--
+ drivers/virtio/virtio_ring.c |    6 +++++-
+ include/linux/virtio.h       |    3 ++-
+ 3 files changed, 9 insertions(+), 4 deletions(-)
+
+--- a/drivers/net/virtio_net.c
++++ b/drivers/net/virtio_net.c
+@@ -3165,7 +3165,7 @@ static int virtnet_rx_resize(struct virt
+       virtnet_rx_pause(vi, rq);
+-      err = virtqueue_resize(rq->vq, ring_num, virtnet_rq_unmap_free_buf);
++      err = virtqueue_resize(rq->vq, ring_num, virtnet_rq_unmap_free_buf, NULL);
+       if (err)
+               netdev_err(vi->dev, "resize rx fail: rx queue index: %d err: %d\n", qindex, err);
+@@ -3228,7 +3228,7 @@ static int virtnet_tx_resize(struct virt
+       virtnet_tx_pause(vi, sq);
+-      err = virtqueue_resize(sq->vq, ring_num, virtnet_sq_free_unused_buf);
++      err = virtqueue_resize(sq->vq, ring_num, virtnet_sq_free_unused_buf, NULL);
+       if (err)
+               netdev_err(vi->dev, "resize tx fail: tx queue index: %d err: %d\n", qindex, err);
+--- a/drivers/virtio/virtio_ring.c
++++ b/drivers/virtio/virtio_ring.c
+@@ -2716,6 +2716,7 @@ EXPORT_SYMBOL_GPL(vring_create_virtqueue
+  * @_vq: the struct virtqueue we're talking about.
+  * @num: new ring num
+  * @recycle: callback to recycle unused buffers
++ * @recycle_done: callback to be invoked when recycle for all unused buffers done
+  *
+  * When it is really necessary to create a new vring, it will set the current vq
+  * into the reset state. Then call the passed callback to recycle the buffer
+@@ -2736,7 +2737,8 @@ EXPORT_SYMBOL_GPL(vring_create_virtqueue
+  *
+  */
+ int virtqueue_resize(struct virtqueue *_vq, u32 num,
+-                   void (*recycle)(struct virtqueue *vq, void *buf))
++                   void (*recycle)(struct virtqueue *vq, void *buf),
++                   void (*recycle_done)(struct virtqueue *vq))
+ {
+       struct vring_virtqueue *vq = to_vvq(_vq);
+       int err;
+@@ -2753,6 +2755,8 @@ int virtqueue_resize(struct virtqueue *_
+       err = virtqueue_disable_and_recycle(_vq, recycle);
+       if (err)
+               return err;
++      if (recycle_done)
++              recycle_done(_vq);
+       if (vq->packed_ring)
+               err = virtqueue_resize_packed(_vq, num);
+--- a/include/linux/virtio.h
++++ b/include/linux/virtio.h
+@@ -100,7 +100,8 @@ dma_addr_t virtqueue_get_avail_addr(cons
+ dma_addr_t virtqueue_get_used_addr(const struct virtqueue *vq);
+ int virtqueue_resize(struct virtqueue *vq, u32 num,
+-                   void (*recycle)(struct virtqueue *vq, void *buf));
++                   void (*recycle)(struct virtqueue *vq, void *buf),
++                   void (*recycle_done)(struct virtqueue *vq));
+ int virtqueue_reset(struct virtqueue *vq,
+                   void (*recycle)(struct virtqueue *vq, void *buf));