From: Greg Kroah-Hartman Date: Sun, 15 Dec 2024 07:52:46 +0000 (+0100) Subject: 6.12-stable patches X-Git-Tag: v5.4.288~73 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=2c72dcebe8d5e4fca906e6526e45e983eff0f3a6;p=thirdparty%2Fkernel%2Fstable-queue.git 6.12-stable patches 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 --- 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 index 00000000000..6fbc0450371 --- /dev/null +++ b/queue-6.12/alsa-hda-realtek-fix-headset-mic-on-acer-nitro-5.patch @@ -0,0 +1,31 @@ +From 5a69e3d0a1b0f07e58c353560cfcb1ea20a6f040 Mon Sep 17 00:00:00 2001 +From: Hridesh MG +Date: Thu, 5 Dec 2024 22:48:42 +0530 +Subject: ALSA: hda/realtek: Fix headset mic on Acer Nitro 5 + +From: Hridesh MG + +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 +Cc: +Link: https://patch.msgid.link/20241205171843.7787-1-hridesh699@gmail.com +Signed-off-by: Takashi Iwai +Signed-off-by: Greg Kroah-Hartman +--- + 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 index 00000000000..43f16e50bbf --- /dev/null +++ b/queue-6.12/alsa-usb-audio-add-implicit-feedback-quirk-for-yamaha-thr5.patch @@ -0,0 +1,33 @@ +From 82fdcf9b518b205da040046fbe7747fb3fd18657 Mon Sep 17 00:00:00 2001 +From: Jaakko Salo +Date: Fri, 6 Dec 2024 18:44:48 +0200 +Subject: ALSA: usb-audio: Add implicit feedback quirk for Yamaha THR5 + +From: Jaakko Salo + +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 +Cc: +Link: https://patch.msgid.link/20241206164448.8136-1-jaakkos@gmail.com +Signed-off-by: Takashi Iwai +Signed-off-by: Greg Kroah-Hartman +--- + 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 index 00000000000..2b100c57b74 --- /dev/null +++ b/queue-6.12/blk-cgroup-fix-uaf-in-blkcg_unpin_online.patch @@ -0,0 +1,82 @@ +From 86e6ca55b83c575ab0f2e105cf08f98e58d3d7af Mon Sep 17 00:00:00 2001 +From: Tejun Heo +Date: Fri, 6 Dec 2024 07:59:51 -1000 +Subject: blk-cgroup: Fix UAF in blkcg_unpin_online() + +From: Tejun Heo + +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: + + 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 + + ... + 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 +Reported-by: Abagail ren +Suggested-by: Linus Torvalds +Fixes: 4308a434e5e0 ("blkcg: don't offline parent blkcg first") +Cc: stable@vger.kernel.org # v5.7+ +Signed-off-by: Jens Axboe +Signed-off-by: Greg Kroah-Hartman +--- + 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 index 00000000000..960ba0e5606 --- /dev/null +++ b/queue-6.12/block-ignore-req_nowait-for-zone-reset-and-zone-finish-operations.patch @@ -0,0 +1,47 @@ +From 5eb3317aa5a2ffe4574ab1a12cf9bc9447ca26c0 Mon Sep 17 00:00:00 2001 +From: Damien Le Moal +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 + +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 +Reviewed-by: Christoph Hellwig +Reviewed-by: Martin K. Petersen +Link: https://lore.kernel.org/r/20241209122357.47838-3-dlemoal@kernel.org +Signed-off-by: Jens Axboe +Signed-off-by: Greg Kroah-Hartman +--- + 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 index 00000000000..2814c905a7e --- /dev/null +++ b/queue-6.12/block-prevent-potential-deadlocks-in-zone-write-plug-error-recovery.patch @@ -0,0 +1,638 @@ +From fe0418eb9bd69a19a948b297c8de815e05f3cde1 Mon Sep 17 00:00:00 2001 +From: Damien Le Moal +Date: Mon, 9 Dec 2024 21:23:57 +0900 +Subject: block: Prevent potential deadlocks in zone write plug error recovery + +From: Damien Le Moal + +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 +Reviewed-by: Christoph Hellwig +Reviewed-by: Martin K. Petersen +Link: https://lore.kernel.org/r/20241209122357.47838-5-dlemoal@kernel.org +Signed-off-by: Jens Axboe +Signed-off-by: Greg Kroah-Hartman +--- + 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 index 00000000000..b35eda6c9f6 --- /dev/null +++ b/queue-6.12/block-switch-to-using-refcount_t-for-zone-write-plugs.patch @@ -0,0 +1,115 @@ +From 4122fef16b172f7c1838fcf74340268c86ed96db Mon Sep 17 00:00:00 2001 +From: Damien Le Moal +Date: Thu, 7 Nov 2024 15:54:38 +0900 +Subject: block: Switch to using refcount_t for zone write plugs + +From: Damien Le Moal + +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 +Closes: https://lore.kernel.org/oe-kbuild-all/202411050650.ilIZa8S7-lkp@intel.com/ +Signed-off-by: Damien Le Moal +Reviewed-by: Christoph Hellwig +Link: https://lore.kernel.org/r/20241107065438.236348-1-dlemoal@kernel.org +Signed-off-by: Jens Axboe +Signed-off-by: Greg Kroah-Hartman +--- + 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 + #include + #include +-#include ++#include + #include + + #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 index 00000000000..a5adf440c2f --- /dev/null +++ b/queue-6.12/block-use-a-zone-write-plug-bio-work-for-req_nowait-bios.patch @@ -0,0 +1,166 @@ +From cae005670887cb07ceafc25bb32e221e56286488 Mon Sep 17 00:00:00 2001 +From: Damien Le Moal +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 + +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 +Fixes: dd291d77cc90 ("block: Introduce zone write plugging") +Cc: stable@vger.kernel.org +Signed-off-by: Damien Le Moal +Reviewed-by: Christoph Hellwig +Reviewed-by: Martin K. Petersen +Link: https://lore.kernel.org/r/20241209122357.47838-2-dlemoal@kernel.org +Signed-off-by: Jens Axboe +Signed-off-by: Greg Kroah-Hartman +--- + 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 index 00000000000..670c79ec35c --- /dev/null +++ b/queue-6.12/bpf-fix-uaf-via-mismatching-bpf_prog-attachment-rcu-flavors.patch @@ -0,0 +1,46 @@ +From ef1b808e3b7c98612feceedf985c2fbbeb28f956 Mon Sep 17 00:00:00 2001 +From: Jann Horn +Date: Tue, 10 Dec 2024 17:32:13 +0100 +Subject: bpf: Fix UAF via mismatching bpf_prog/attachment RCU flavors + +From: Jann Horn + +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 +Suggested-by: Alexei Starovoitov +Signed-off-by: Jann Horn +Signed-off-by: Andrii Nakryiko +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 +--- + 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 index 00000000000..2750a715e65 --- /dev/null +++ b/queue-6.12/clk-en7523-fix-wrong-bus-clock-for-en7581.patch @@ -0,0 +1,53 @@ +From 2eb75f86d52565367211c51334d15fe672633085 Mon Sep 17 00:00:00 2001 +From: Christian Marangi +Date: Sat, 16 Nov 2024 11:56:53 +0100 +Subject: clk: en7523: Fix wrong BUS clock for EN7581 + +From: Christian Marangi + +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 +Link: https://lore.kernel.org/r/20241116105710.19748-1-ansuelsmth@gmail.com +Acked-by: Lorenzo Bianconi +Signed-off-by: Stephen Boyd +Signed-off-by: Greg Kroah-Hartman +--- + 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 index 00000000000..93b61cdf54f --- /dev/null +++ b/queue-6.12/crypto-hisilicon-debugfs-fix-the-struct-pointer-incorrectly-offset-problem.patch @@ -0,0 +1,46 @@ +From cd26cd65476711e2c69e0a049c0eeef4b743f5ac Mon Sep 17 00:00:00 2001 +From: Chenghai Huang +Date: Sat, 30 Nov 2024 16:01:31 +0800 +Subject: crypto: hisilicon/debugfs - fix the struct pointer incorrectly offset problem + +From: Chenghai Huang + +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: +Signed-off-by: Chenghai Huang +Signed-off-by: Herbert Xu +Signed-off-by: Greg Kroah-Hartman +--- + 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 index 00000000000..7189d3988f0 --- /dev/null +++ b/queue-6.12/dm-fix-dm-zoned-reclaim-zone-write-pointer-alignment.patch @@ -0,0 +1,264 @@ +From b76b840fd93374240b59825f1ab8e2f5c9907acb Mon Sep 17 00:00:00 2001 +From: Damien Le Moal +Date: Mon, 9 Dec 2024 21:23:56 +0900 +Subject: dm: Fix dm-zoned-reclaim zone write pointer alignment + +From: Damien Le Moal + +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 +Reviewed-by: Christoph Hellwig +Acked-by: Mike Snitzer +Reviewed-by: Martin K. Petersen +Link: https://lore.kernel.org/r/20241209122357.47838-4-dlemoal@kernel.org +Signed-off-by: Jens Axboe +Signed-off-by: Greg Kroah-Hartman +--- + 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 index 00000000000..c8f4721144e --- /dev/null +++ b/queue-6.12/drm-panic-remove-spurious-empty-line-to-clean-warning.patch @@ -0,0 +1,62 @@ +From 4011b351b1b5a953aaa7c6b3915f908b3cc1be96 Mon Sep 17 00:00:00 2001 +From: Miguel Ojeda +Date: Tue, 26 Nov 2024 00:33:32 +0100 +Subject: drm/panic: remove spurious empty line to clean warning + +From: Miguel Ojeda + +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 +Link: https://lore.kernel.org/r/20241125233332.697497-1-ojeda@kernel.org +Signed-off-by: Miguel Ojeda +Signed-off-by: Greg Kroah-Hartman +--- + 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 index 00000000000..abee22fb5c9 --- /dev/null +++ b/queue-6.12/gpio-graniterapids-check-if-gpio-line-can-be-used-for-irqs.patch @@ -0,0 +1,68 @@ +From c0ec4890d6454980c53c3cc164140115c4a671f2 Mon Sep 17 00:00:00 2001 +From: Alan Borzeszkowski +Date: Wed, 4 Dec 2024 09:04:14 +0200 +Subject: gpio: graniterapids: Check if GPIO line can be used for IRQs + +From: Alan Borzeszkowski + +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 +Signed-off-by: Mika Westerberg +Acked-by: Andy Shevchenko +Link: https://lore.kernel.org/r/20241204070415.1034449-7-mika.westerberg@linux.intel.com +Signed-off-by: Bartosz Golaszewski +Signed-off-by: Greg Kroah-Hartman +--- + 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 index 00000000000..e7896976311 --- /dev/null +++ b/queue-6.12/gpio-graniterapids-determine-if-gpio-pad-can-be-used-by-driver.patch @@ -0,0 +1,62 @@ +From 0588504d28dedde6789aec17a6ece6fa8e477725 Mon Sep 17 00:00:00 2001 +From: Alan Borzeszkowski +Date: Wed, 4 Dec 2024 09:04:13 +0200 +Subject: gpio: graniterapids: Determine if GPIO pad can be used by driver + +From: Alan Borzeszkowski + +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 +Signed-off-by: Mika Westerberg +Acked-by: Andy Shevchenko +Link: https://lore.kernel.org/r/20241204070415.1034449-6-mika.westerberg@linux.intel.com +Signed-off-by: Bartosz Golaszewski +Signed-off-by: Greg Kroah-Hartman +--- + 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 index 00000000000..7c42f7e8c7c --- /dev/null +++ b/queue-6.12/gpio-graniterapids-fix-gpio-ack-functionality.patch @@ -0,0 +1,33 @@ +From 0bb18e34abdde7bf58fca8542e2dcf621924ea19 Mon Sep 17 00:00:00 2001 +From: Alan Borzeszkowski +Date: Wed, 4 Dec 2024 09:04:15 +0200 +Subject: gpio: graniterapids: Fix GPIO Ack functionality + +From: Alan Borzeszkowski + +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 +Signed-off-by: Mika Westerberg +Acked-by: Andy Shevchenko +Link: https://lore.kernel.org/r/20241204070415.1034449-8-mika.westerberg@linux.intel.com +Signed-off-by: Bartosz Golaszewski +Signed-off-by: Greg Kroah-Hartman +--- + 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 index 00000000000..5b89d36fe58 --- /dev/null +++ b/queue-6.12/gpio-graniterapids-fix-incorrect-bar-assignment.patch @@ -0,0 +1,88 @@ +From 7382d2f0e802077c36495e325da8d253a15fb441 Mon Sep 17 00:00:00 2001 +From: Alan Borzeszkowski +Date: Wed, 4 Dec 2024 09:04:10 +0200 +Subject: gpio: graniterapids: Fix incorrect BAR assignment + +From: Alan Borzeszkowski + +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 +Signed-off-by: Mika Westerberg +Acked-by: Andy Shevchenko +Link: https://lore.kernel.org/r/20241204070415.1034449-3-mika.westerberg@linux.intel.com +Signed-off-by: Bartosz Golaszewski +Signed-off-by: Greg Kroah-Hartman +--- + 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 index 00000000000..05b3660e6d9 --- /dev/null +++ b/queue-6.12/gpio-graniterapids-fix-invalid-gpi_is-register-offset.patch @@ -0,0 +1,39 @@ +From 0fe329b55231cca489f9bed1db0e778d077fdaf9 Mon Sep 17 00:00:00 2001 +From: Shankar Bandal +Date: Wed, 4 Dec 2024 09:04:11 +0200 +Subject: gpio: graniterapids: Fix invalid GPI_IS register offset + +From: Shankar Bandal + +commit 0fe329b55231cca489f9bed1db0e778d077fdaf9 upstream. + +Update GPI Interrupt Status register offset to correct value. + +Cc: stable@vger.kernel.org +Signed-off-by: Shankar Bandal +Signed-off-by: Alan Borzeszkowski +Signed-off-by: Mika Westerberg +Acked-by: Andy Shevchenko +Link: https://lore.kernel.org/r/20241204070415.1034449-4-mika.westerberg@linux.intel.com +Signed-off-by: Bartosz Golaszewski +Signed-off-by: Greg Kroah-Hartman +--- + 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 index 00000000000..de498e62779 --- /dev/null +++ b/queue-6.12/gpio-graniterapids-fix-invalid-rxevcfg-register-bitmask.patch @@ -0,0 +1,39 @@ +From 15636b00a055474033426b94b6372728b2163a1e Mon Sep 17 00:00:00 2001 +From: Shankar Bandal +Date: Wed, 4 Dec 2024 09:04:12 +0200 +Subject: gpio: graniterapids: Fix invalid RXEVCFG register bitmask + +From: Shankar Bandal + +commit 15636b00a055474033426b94b6372728b2163a1e upstream. + +Correct RX Level/Edge Configuration register (RXEVCFG) bitmask. + +Cc: stable@vger.kernel.org +Signed-off-by: Shankar Bandal +Signed-off-by: Alan Borzeszkowski +Signed-off-by: Mika Westerberg +Acked-by: Andy Shevchenko +Link: https://lore.kernel.org/r/20241204070415.1034449-5-mika.westerberg@linux.intel.com +Signed-off-by: Bartosz Golaszewski +Signed-off-by: Greg Kroah-Hartman +--- + 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 index 00000000000..62ce0e1976d --- /dev/null +++ b/queue-6.12/gpio-graniterapids-fix-vgpio-driver-crash.patch @@ -0,0 +1,56 @@ +From eb9640fd1ce666610b77f5997596e9570a36378f Mon Sep 17 00:00:00 2001 +From: Alan Borzeszkowski +Date: Wed, 4 Dec 2024 09:04:09 +0200 +Subject: gpio: graniterapids: Fix vGPIO driver crash + +From: Alan Borzeszkowski + +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 +Signed-off-by: Mika Westerberg +Acked-by: Andy Shevchenko +Link: https://lore.kernel.org/r/20241204070415.1034449-2-mika.westerberg@linux.intel.com +Signed-off-by: Bartosz Golaszewski +Signed-off-by: Greg Kroah-Hartman +--- + 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 index 00000000000..add2d2af08d --- /dev/null +++ b/queue-6.12/gpio-ljca-initialize-num-before-accessing-item-in-ljca_gpio_config.patch @@ -0,0 +1,42 @@ +From 3396995f9fb6bcbe0004a68118a22f98bab6e2b9 Mon Sep 17 00:00:00 2001 +From: Haoyu Li +Date: Tue, 3 Dec 2024 22:14:51 +0800 +Subject: gpio: ljca: Initialize num before accessing item in ljca_gpio_config + +From: Haoyu Li + +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 +Link: https://lore.kernel.org/stable/20241203141451.342316-1-lihaoyu499%40gmail.com +Signed-off-by: Bartosz Golaszewski +Signed-off-by: Greg Kroah-Hartman +--- + 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 index 00000000000..62843e82cf3 --- /dev/null +++ b/queue-6.12/ksmbd-fix-racy-issue-from-session-lookup-and-expire.patch @@ -0,0 +1,196 @@ +From b95629435b84b9ecc0c765995204a4d8a913ed52 Mon Sep 17 00:00:00 2001 +From: Namjae Jeon +Date: Thu, 5 Dec 2024 21:38:47 +0900 +Subject: ksmbd: fix racy issue from session lookup and expire + +From: Namjae Jeon + +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 +Signed-off-by: Steve French +Signed-off-by: Greg Kroah-Hartman +--- + 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 index 00000000000..a0dcb6b71b0 --- /dev/null +++ b/queue-6.12/memcg-slub-fix-sunreclaim-for-post-charged-objects.patch @@ -0,0 +1,61 @@ +From b7ffecbe198e2dfc44abf92ceb90f46150f7527a Mon Sep 17 00:00:00 2001 +From: Shakeel Butt +Date: Mon, 9 Dec 2024 20:06:57 -0800 +Subject: memcg: slub: fix SUnreclaim for post charged objects + +From: Shakeel Butt + +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 +Cc: +Signed-off-by: Vlastimil Babka +Signed-off-by: Greg Kroah-Hartman +--- + 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 index 00000000000..5ee71e0a6af --- /dev/null +++ b/queue-6.12/perf-ftrace-fix-undefined-behavior-in-cmp_profile_data.patch @@ -0,0 +1,57 @@ +From 246dfe3dc199246bd64635163115f2691623fc53 Mon Sep 17 00:00:00 2001 +From: Kuan-Wei Chiu +Date: Mon, 9 Dec 2024 21:42:26 +0800 +Subject: perf ftrace: Fix undefined behavior in cmp_profile_data() + +From: Kuan-Wei Chiu + +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 +Reviewed-by: Namhyung Kim +Reviewed-by: Arnaldo Carvalho de Melo +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 +Signed-off-by: Greg Kroah-Hartman +--- + 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 index 00000000000..dc55f086fb1 --- /dev/null +++ b/queue-6.12/perf-x86-intel-ds-unconditionally-drain-pebs-ds-when-changing-pebs_data_cfg.patch @@ -0,0 +1,65 @@ +From 9f3de72a0c37005f897d69e4bdd59c25b8898447 Mon Sep 17 00:00:00 2001 +From: Kan Liang +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 + +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 +Signed-off-by: Peter Zijlstra (Intel) +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 +--- + 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 index 00000000000..2757bc27539 --- /dev/null +++ b/queue-6.12/riscv-fix-ipis-usage-in-kfence_protect_page.patch @@ -0,0 +1,81 @@ +From b3431a8bb336cece8adc452437befa7d4534b2fd Mon Sep 17 00:00:00 2001 +From: Alexandre Ghiti +Date: Mon, 9 Dec 2024 08:41:25 +0100 +Subject: riscv: Fix IPIs usage in kfence_protect_page() + +From: Alexandre Ghiti + +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] [] smp_call_function_many_cond+0x452/0x520 +[ 3.458593] [] on_each_cpu_cond_mask+0x1e/0x30 +[ 3.458625] [] __flush_tlb_range+0x118/0x1ca +[ 3.458656] [] flush_tlb_kernel_range+0x1e/0x26 +[ 3.458683] [] kfence_protect+0xc0/0xce +[ 3.458717] [] kfence_guarded_free+0xc6/0x1c0 +[ 3.458742] [] __kfence_free+0x62/0xc6 +[ 3.458764] [] kfree+0x106/0x32c +[ 3.458786] [] detach_buf_split+0x188/0x1a8 +[ 3.458816] [] virtqueue_get_buf_ctx+0xb6/0x1f6 +[ 3.458839] [] virtqueue_get_buf+0xe/0x16 +[ 3.458880] [] virtblk_done+0x5c/0xe2 +[ 3.458908] [] vring_interrupt+0x6a/0x74 +[ 3.458930] [] __handle_irq_event_percpu+0x7c/0xe2 +[ 3.458956] [] handle_irq_event+0x3c/0x86 +[ 3.458978] [] handle_simple_irq+0x9e/0xbe +[ 3.459004] [] generic_handle_domain_irq+0x1c/0x2a +[ 3.459027] [] imsic_handle_irq+0xba/0x120 +[ 3.459056] [] generic_handle_domain_irq+0x1c/0x2a +[ 3.459080] [] riscv_intc_aia_irq+0x24/0x34 +[ 3.459103] [] handle_riscv_irq+0x2e/0x4c +[ 3.459133] [] 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 +Cc: stable@vger.kernel.org +Link: https://lore.kernel.org/r/20241209074125.52322-1-alexghiti@rivosinc.com +Signed-off-by: Palmer Dabbelt +Signed-off-by: Greg Kroah-Hartman +--- + 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 index 00000000000..0b76a446faa --- /dev/null +++ b/queue-6.12/riscv-fix-wrong-usage-of-__pa-on-a-fixmap-address.patch @@ -0,0 +1,33 @@ +From c796e187201242992d6d292bfeff41aadfdf3f29 Mon Sep 17 00:00:00 2001 +From: Alexandre Ghiti +Date: Mon, 9 Dec 2024 08:45:08 +0100 +Subject: riscv: Fix wrong usage of __pa() on a fixmap address + +From: Alexandre Ghiti + +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 +Link: https://lore.kernel.org/r/20241209074508.53037-1-alexghiti@rivosinc.com +Cc: stable@vger.kernel.org +Signed-off-by: Palmer Dabbelt +Signed-off-by: Greg Kroah-Hartman +--- + 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 index 00000000000..d190500ff5e --- /dev/null +++ b/queue-6.12/riscv-mm-do-not-call-pmd-dtor-on-vmemmap-page-table-teardown.patch @@ -0,0 +1,118 @@ +From 21f1b85c8912262adf51707e63614a114425eb10 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Bj=C3=B6rn=20T=C3=B6pel?= +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 + +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 + | [] remove_pgd_mapping+0xbec/0x1070 + | [] vmemmap_free+0x14/0x1e + | [] section_deactivate+0x220/0x452 + | [] sparse_remove_section+0x4a/0x58 + | [] __remove_pages+0x7e/0xba + | [] memunmap_pages+0x2bc/0x3fe + | [] dmirror_device_remove_chunks+0x2ea/0x518 [test_hmm] + | [] hmm_dmirror_exit+0x3e/0x1018 [test_hmm] + | [] __riscv_sys_delete_module+0x15a/0x2a6 + | [] do_trap_ecall_u+0x1f2/0x266 + | [] _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 +Reviewed-by: Alexandre Ghiti +Link: https://lore.kernel.org/r/20241120131203.1859787-1-bjorn@kernel.org +Cc: stable@vger.kernel.org +Signed-off-by: Palmer Dabbelt +Signed-off-by: Greg Kroah-Hartman +--- + 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 index 00000000000..05ba61ef124 --- /dev/null +++ b/queue-6.12/sched-deadline-fix-replenish_dl_new_period-dl_server-condition.patch @@ -0,0 +1,41 @@ +From 22368fe1f9bbf39db2b5b52859589883273e80ce Mon Sep 17 00:00:00 2001 +From: Juri Lelli +Date: Wed, 27 Nov 2024 07:37:40 +0100 +Subject: sched/deadline: Fix replenish_dl_new_period dl_server condition + +From: Juri Lelli + +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 +Signed-off-by: Peter Zijlstra (Intel) +Cc: stable@vger.kernel.org +Link: https://lkml.kernel.org/r/20241127063740.8278-1-juri.lelli@redhat.com +Signed-off-by: Greg Kroah-Hartman +--- + 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 index 00000000000..8e1eb83685f --- /dev/null +++ b/queue-6.12/serial-sh-sci-check-if-tx-data-was-written-to-device-in-.tx_empty.patch @@ -0,0 +1,143 @@ +From 7cc0e0a43a91052477c2921f924a37d9c3891f0c Mon Sep 17 00:00:00 2001 +From: Claudiu Beznea +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 + +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 +Link: https://lore.kernel.org/r/20241125115856.513642-1-claudiu.beznea.uj@bp.renesas.com +Signed-off-by: Greg Kroah-Hartman +--- + 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 index 00000000000..1671f9c33d6 --- /dev/null +++ b/queue-6.12/series @@ -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 index 00000000000..8c1206760a5 --- /dev/null +++ b/queue-6.12/spi-rockchip-fix-pm-runtime-count-on-no-op-cs.patch @@ -0,0 +1,49 @@ +From 0bb394067a792e7119abc9e0b7158ef19381f456 Mon Sep 17 00:00:00 2001 +From: Christian Loehle +Date: Fri, 6 Dec 2024 19:50:55 +0000 +Subject: spi: rockchip: Fix PM runtime count on no-op cs + +From: Christian Loehle + +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 +Link: https://patch.msgid.link/1f2b3af4-2b7a-4ac8-ab95-c80120ebf44c@arm.com +Signed-off-by: Mark Brown +Signed-off-by: Greg Kroah-Hartman +--- + 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 index 00000000000..789f918f08c --- /dev/null +++ b/queue-6.12/splice-do-not-checksum-af_unix-sockets.patch @@ -0,0 +1,44 @@ +From 6bd8614fc2d076fc21b7488c9f279853960964e2 Mon Sep 17 00:00:00 2001 +From: Frederik Deweerdt +Date: Mon, 9 Dec 2024 21:06:48 -0800 +Subject: splice: do not checksum AF_UNIX sockets + +From: Frederik Deweerdt + +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 +Fixes: 2e910b95329c ("net: Add a function to splice pages into an skbuff for MSG_SPLICE_PAGES") +Reviewed-by: Kuniyuki Iwashima +Reviewed-by: Eric Dumazet +Reviewed-by: Joe Damato +Link: https://patch.msgid.link/Z1fMaHkRf8cfubuE@xiberoa +Signed-off-by: Jakub Kicinski +Signed-off-by: Greg Kroah-Hartman +--- + 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 index 00000000000..8c0b2a3d893 --- /dev/null +++ b/queue-6.12/tcp-check-space-before-adding-mptcp-syn-options.patch @@ -0,0 +1,44 @@ +From 06d64ab46f19ac12f59a1d2aa8cd196b2e4edb5b Mon Sep 17 00:00:00 2001 +From: MoYuanhao +Date: Mon, 9 Dec 2024 13:28:14 +0100 +Subject: tcp: check space before adding MPTCP SYN options + +From: MoYuanhao + +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 +Fixes: cec37a6e41aa ("mptcp: Handle MP_CAPABLE options for outgoing connections") +Cc: stable@vger.kernel.org +Acked-by: Matthieu Baerts (NGI0) +[ Matt: Add Fixes, cc Stable, update Description ] +Signed-off-by: Matthieu Baerts (NGI0) +Reviewed-by: Eric Dumazet +Link: https://patch.msgid.link/20241209-net-mptcp-check-space-syn-v1-1-2da992bb6f74@kernel.org +Signed-off-by: Jakub Kicinski +Signed-off-by: Greg Kroah-Hartman +--- + 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 index 00000000000..dd6c5f9e41f --- /dev/null +++ b/queue-6.12/usb-core-hcd-only-check-primary-hcd-skip_phy_initialization.patch @@ -0,0 +1,45 @@ +From d2ec94fbc431cc77ed53d4480bdc856669c2b5aa Mon Sep 17 00:00:00 2001 +From: Xu Yang +Date: Tue, 5 Nov 2024 17:01:20 +0800 +Subject: usb: core: hcd: only check primary hcd skip_phy_initialization + +From: Xu Yang + +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 +Link: https://lore.kernel.org/r/20241105090120.2438366-1-xu.yang_2@nxp.com +Signed-off-by: Greg Kroah-Hartman +--- + 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 index 00000000000..1b70d3037db --- /dev/null +++ b/queue-6.12/usb-host-max3421-hcd-correctly-abort-a-usb-request.patch @@ -0,0 +1,50 @@ +From 0d2ada05227881f3d0722ca2364e3f7a860a301f Mon Sep 17 00:00:00 2001 +From: Mark Tomlinson +Date: Mon, 25 Nov 2024 11:14:30 +1300 +Subject: usb: host: max3421-hcd: Correctly abort a USB request. + +From: Mark Tomlinson + +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 +Signed-off-by: Mark Tomlinson +Link: https://lore.kernel.org/r/20241124221430.1106080-1-mark.tomlinson@alliedtelesis.co.nz +Signed-off-by: Greg Kroah-Hartman +--- + 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 index 00000000000..dd3a97ab3c3 --- /dev/null +++ b/queue-6.12/usb-misc-onboard_usb_dev-skip-suspend-resume-sequence-for-usb5744-smbus-support.patch @@ -0,0 +1,46 @@ +From ce15d6b3d5c3c6f78290066be0f0a4fd89cdeb5b Mon Sep 17 00:00:00 2001 +From: Radhey Shyam Pandey +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 + +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 +Link: https://lore.kernel.org/r/1733165302-1694891-1-git-send-email-radhey.shyam.pandey@amd.com +Signed-off-by: Greg Kroah-Hartman +--- + 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 index 00000000000..d93e8ef0fa1 --- /dev/null +++ b/queue-6.12/virtio_net-correct-netdev_tx_reset_queue-invocation-point.patch @@ -0,0 +1,189 @@ +From 3ddccbefebdbe0c4c72a248676e4d39ac66a8e26 Mon Sep 17 00:00:00 2001 +From: Koichiro Den +Date: Fri, 6 Dec 2024 10:10:42 +0900 +Subject: virtio_net: correct netdev_tx_reset_queue() invocation point + +From: Koichiro Den + +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: + + ? 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 + + + __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 + +[...] + +Fixes: c8bd1f7f3e61 ("virtio_net: add support for Byte Queue Limits") +Cc: # v6.11+ +Signed-off-by: Koichiro Den +Acked-by: Jason Wang +Reviewed-by: Xuan Zhuo +[ pabeni: trimmed possibly troublesome separator ] +Signed-off-by: Paolo Abeni +Signed-off-by: Greg Kroah-Hartman +--- + 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 index 00000000000..558f60d6a19 --- /dev/null +++ b/queue-6.12/virtio_net-ensure-netdev_tx_reset_queue-is-called-on-tx-ring-resize.patch @@ -0,0 +1,60 @@ +From 1480f0f61b675567ca5d0943d6ef2e39172dcafd Mon Sep 17 00:00:00 2001 +From: Koichiro Den +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 + +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: # v6.11+ +Signed-off-by: Koichiro Den +Acked-by: Jason Wang +Reviewed-by: Xuan Zhuo +Signed-off-by: Paolo Abeni +Signed-off-by: Greg Kroah-Hartman +--- + 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 index 00000000000..76d857f0b4d --- /dev/null +++ b/queue-6.12/virtio_ring-add-a-func-argument-recycle_done-to-virtqueue_resize.patch @@ -0,0 +1,87 @@ +From 8d6712c892019b9b9dc5c7039edd3c9d770b510b Mon Sep 17 00:00:00 2001 +From: Koichiro Den +Date: Fri, 6 Dec 2024 10:10:44 +0900 +Subject: virtio_ring: add a func argument 'recycle_done' to virtqueue_resize() + +From: Koichiro Den + +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: # v6.11+ +Signed-off-by: Koichiro Den +Acked-by: Jason Wang +Reviewed-by: Xuan Zhuo +Signed-off-by: Paolo Abeni +Signed-off-by: Greg Kroah-Hartman +--- + 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)); +