From: Greg Kroah-Hartman Date: Fri, 15 May 2026 09:30:57 +0000 (+0200) Subject: 6.12-stable patches X-Git-Tag: v5.10.256~7 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=377167beeb309103a57d86fc78f5a9857b61d822;p=thirdparty%2Fkernel%2Fstable-queue.git 6.12-stable patches added patches: alsa-core-serialize-deferred-fasync-state-checks.patch alsa-hda-cs35l56-propagate-asp-tx-source-control-errors.patch alsa-misc-use-guard-for-spin-locks.patch alsa-seq-fix-ump-group-16-filtering.patch alsa-seq-notify-client-and-port-info-changes.patch block-cleanup-blkdev_report_zones.patch block-fix-zone-write-plug-removal.patch block-reorganize-struct-blk_zone_wplug.patch bluetooth-hci_conn-fix-potential-uaf-in-create_big_sync.patch fbcon-avoid-oob-font-access-if-console-rotation-fails.patch mm-hugetlb_cma-round-up-per_node-before-logging-it.patch rust-pin-init-fix-incorrect-accessor-reference-lifetime.patch spi-tegra114-fix-controller-deregistration.patch spi-tegra20-sflash-fix-controller-deregistration.patch spi-uniphier-fix-controller-deregistration.patch spi-uniphier-simplify-clock-handling-with-devm_clk_get_enabled.patch spi-zynq-qspi-fix-controller-deregistration.patch spi-zynq-qspi-simplify-clock-handling-with-devm_clk_get_enabled.patch tracefs-fix-default-permissions-not-being-applied-on-initial-mount.patch usb-dwc3-move-guid-programming-after-phy-initialization.patch usb-typec-tcpm-reset-internal-port-states-on-soft-reset-ams.patch --- diff --git a/queue-6.12/alsa-core-serialize-deferred-fasync-state-checks.patch b/queue-6.12/alsa-core-serialize-deferred-fasync-state-checks.patch new file mode 100644 index 0000000000..6d341558de --- /dev/null +++ b/queue-6.12/alsa-core-serialize-deferred-fasync-state-checks.patch @@ -0,0 +1,64 @@ +From stable+bounces-246870-greg=kroah.com@vger.kernel.org Wed May 13 16:58:47 2026 +From: Sasha Levin +Date: Wed, 13 May 2026 09:53:39 -0400 +Subject: ALSA: core: Serialize deferred fasync state checks +To: stable@vger.kernel.org +Cc: "Cássio Gabriel" , "Takashi Iwai" , "Sasha Levin" +Message-ID: <20260513135339.3740733-2-sashal@kernel.org> + +From: Cássio Gabriel + +[ Upstream commit 5337213381df578058e2e41da93cbd0e4639935f ] + +snd_fasync_helper() updates fasync->on under snd_fasync_lock, and +snd_fasync_work_fn() now also evaluates fasync->on under the same +lock. snd_kill_fasync() still tests the flag before taking the lock, +leaving an unsynchronized read against FASYNC enable/disable updates. + +Move the enabled-state check into the locked section. + +Also clear fasync->on under snd_fasync_lock in snd_fasync_free() +before unlinking the pending entry. Together with the locked sender-side +check, this publishes teardown before flushing the deferred work and +prevents a racing sender from requeueing the entry after free has +started. + +Fixes: ef34a0ae7a26 ("ALSA: core: Add async signal helpers") +Fixes: 8146cd333d23 ("ALSA: core: Fix potential data race at fasync handling") +Cc: stable@vger.kernel.org +Signed-off-by: Cássio Gabriel +Link: https://patch.msgid.link/20260506-alsa-core-fasync-on-lock-v1-1-ea48c77d6ca4@gmail.com +Signed-off-by: Takashi Iwai +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + sound/core/misc.c | 8 ++++++-- + 1 file changed, 6 insertions(+), 2 deletions(-) + +--- a/sound/core/misc.c ++++ b/sound/core/misc.c +@@ -148,9 +148,11 @@ EXPORT_SYMBOL_GPL(snd_fasync_helper); + + void snd_kill_fasync(struct snd_fasync *fasync, int signal, int poll) + { +- if (!fasync || !fasync->on) ++ if (!fasync) + return; + guard(spinlock_irqsave)(&snd_fasync_lock); ++ if (!fasync->on) ++ return; + fasync->signal = signal; + fasync->poll = poll; + list_move(&fasync->list, &snd_fasync_list); +@@ -163,8 +165,10 @@ void snd_fasync_free(struct snd_fasync * + if (!fasync) + return; + +- scoped_guard(spinlock_irq, &snd_fasync_lock) ++ scoped_guard(spinlock_irq, &snd_fasync_lock) { ++ fasync->on = 0; + list_del_init(&fasync->list); ++ } + + flush_work(&snd_fasync_work); + kfree(fasync); diff --git a/queue-6.12/alsa-hda-cs35l56-propagate-asp-tx-source-control-errors.patch b/queue-6.12/alsa-hda-cs35l56-propagate-asp-tx-source-control-errors.patch new file mode 100644 index 0000000000..cb18953209 --- /dev/null +++ b/queue-6.12/alsa-hda-cs35l56-propagate-asp-tx-source-control-errors.patch @@ -0,0 +1,79 @@ +From stable+bounces-246851-greg=kroah.com@vger.kernel.org Wed May 13 15:35:25 2026 +From: Sasha Levin +Date: Wed, 13 May 2026 09:11:11 -0400 +Subject: ALSA: hda: cs35l56: Propagate ASP TX source control errors +To: stable@vger.kernel.org +Cc: "Cássio Gabriel" , "Richard Fitzgerald" , "Takashi Iwai" , "Sasha Levin" +Message-ID: <20260513131111.3723022-1-sashal@kernel.org> + +From: Cássio Gabriel + +[ Upstream commit 0faacc0841d66f3cf51989c10a83f3a82d52ff2c ] + +cs35l56_hda_mixer_get() ignores regmap_read() and +cs35l56_hda_mixer_put() ignores regmap_update_bits_check(). + +This makes the ASP TX source controls report success when a regmap +access fails. The write path returns no change instead of an error, +and the read path continues after a failed read instead of aborting +the control callback. + +Propagate the regmap errors, matching the posture and volume controls +in this driver. + +Fixes: 73cfbfa9caea ("ALSA: hda/cs35l56: Add driver for Cirrus Logic CS35L56 amplifier") +Cc: stable@vger.kernel.org +Signed-off-by: Cássio Gabriel +Reviewed-by: Richard Fitzgerald +Signed-off-by: Takashi Iwai +Link: https://patch.msgid.link/20260423-alsa-cs35l56-asp-tx-source-errors-v1-1-17ea7c62ec31@gmail.com +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + sound/pci/hda/cs35l56_hda.c | 19 ++++++++++++++----- + 1 file changed, 14 insertions(+), 5 deletions(-) + +--- a/sound/pci/hda/cs35l56_hda.c ++++ b/sound/pci/hda/cs35l56_hda.c +@@ -182,11 +182,15 @@ static int cs35l56_hda_mixer_get(struct + { + struct cs35l56_hda *cs35l56 = snd_kcontrol_chip(kcontrol); + unsigned int reg_val; +- int i; ++ int i, ret; + + cs35l56_hda_wait_dsp_ready(cs35l56); + +- regmap_read(cs35l56->base.regmap, kcontrol->private_value, ®_val); ++ ret = regmap_read(cs35l56->base.regmap, kcontrol->private_value, ++ ®_val); ++ if (ret) ++ return ret; ++ + reg_val &= CS35L56_ASP_TXn_SRC_MASK; + + for (i = 0; i < CS35L56_NUM_INPUT_SRC; ++i) { +@@ -205,15 +209,20 @@ static int cs35l56_hda_mixer_put(struct + struct cs35l56_hda *cs35l56 = snd_kcontrol_chip(kcontrol); + unsigned int item = ucontrol->value.enumerated.item[0]; + bool changed; ++ int ret; + + if (item >= CS35L56_NUM_INPUT_SRC) + return -EINVAL; + + cs35l56_hda_wait_dsp_ready(cs35l56); + +- regmap_update_bits_check(cs35l56->base.regmap, kcontrol->private_value, +- CS35L56_INPUT_MASK, cs35l56_tx_input_values[item], +- &changed); ++ ret = regmap_update_bits_check(cs35l56->base.regmap, ++ kcontrol->private_value, ++ CS35L56_INPUT_MASK, ++ cs35l56_tx_input_values[item], ++ &changed); ++ if (ret) ++ return ret; + + return changed; + } diff --git a/queue-6.12/alsa-misc-use-guard-for-spin-locks.patch b/queue-6.12/alsa-misc-use-guard-for-spin-locks.patch new file mode 100644 index 0000000000..b3e0954a74 --- /dev/null +++ b/queue-6.12/alsa-misc-use-guard-for-spin-locks.patch @@ -0,0 +1,73 @@ +From stable+bounces-246869-greg=kroah.com@vger.kernel.org Wed May 13 16:10:28 2026 +From: Sasha Levin +Date: Wed, 13 May 2026 09:53:38 -0400 +Subject: ALSA: misc: Use guard() for spin locks +To: stable@vger.kernel.org +Cc: Takashi Iwai , Sasha Levin +Message-ID: <20260513135339.3740733-1-sashal@kernel.org> + +From: Takashi Iwai + +[ Upstream commit b8e1684163ae52db90f428965bd9aaff7205c02e ] + +Clean up the code using guard() for spin locks. + +Merely code refactoring, and no behavior change. + +Signed-off-by: Takashi Iwai +Link: https://patch.msgid.link/20250829151335.7342-20-tiwai@suse.de +Stable-dep-of: 5337213381df ("ALSA: core: Serialize deferred fasync state checks") +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + sound/core/misc.c | 25 ++++++++++--------------- + 1 file changed, 10 insertions(+), 15 deletions(-) + +--- a/sound/core/misc.c ++++ b/sound/core/misc.c +@@ -131,35 +131,30 @@ int snd_fasync_helper(int fd, struct fil + INIT_LIST_HEAD(&fasync->list); + } + +- spin_lock_irq(&snd_fasync_lock); +- if (*fasyncp) { +- kfree(fasync); +- fasync = *fasyncp; +- } else { +- if (!fasync) { +- spin_unlock_irq(&snd_fasync_lock); +- return 0; ++ scoped_guard(spinlock_irq, &snd_fasync_lock) { ++ if (*fasyncp) { ++ kfree(fasync); ++ fasync = *fasyncp; ++ } else { ++ if (!fasync) ++ return 0; ++ *fasyncp = fasync; + } +- *fasyncp = fasync; ++ fasync->on = on; + } +- fasync->on = on; +- spin_unlock_irq(&snd_fasync_lock); + return fasync_helper(fd, file, on, &fasync->fasync); + } + EXPORT_SYMBOL_GPL(snd_fasync_helper); + + void snd_kill_fasync(struct snd_fasync *fasync, int signal, int poll) + { +- unsigned long flags; +- + if (!fasync || !fasync->on) + return; +- spin_lock_irqsave(&snd_fasync_lock, flags); ++ guard(spinlock_irqsave)(&snd_fasync_lock); + fasync->signal = signal; + fasync->poll = poll; + list_move(&fasync->list, &snd_fasync_list); + schedule_work(&snd_fasync_work); +- spin_unlock_irqrestore(&snd_fasync_lock, flags); + } + EXPORT_SYMBOL_GPL(snd_kill_fasync); + diff --git a/queue-6.12/alsa-seq-fix-ump-group-16-filtering.patch b/queue-6.12/alsa-seq-fix-ump-group-16-filtering.patch new file mode 100644 index 0000000000..798239a907 --- /dev/null +++ b/queue-6.12/alsa-seq-fix-ump-group-16-filtering.patch @@ -0,0 +1,79 @@ +From stable+bounces-246876-greg=kroah.com@vger.kernel.org Wed May 13 16:24:31 2026 +From: Sasha Levin +Date: Wed, 13 May 2026 10:09:32 -0400 +Subject: ALSA: seq: Fix UMP group 16 filtering +To: stable@vger.kernel.org +Cc: "Cássio Gabriel" , "Takashi Iwai" , "Sasha Levin" +Message-ID: <20260513140932.3747146-2-sashal@kernel.org> + +From: Cássio Gabriel + +[ Upstream commit 92429ca999db99febced82f23362a71b2ba4c1d8 ] + +The sequencer UAPI defines group_filter as an unsigned int bitmap. +Bit 0 filters groupless messages and bits 1-16 filter UMP groups 1-16. + +The internal snd_seq_client storage is only unsigned short, so bit 16 +is truncated when userspace sets the filter. The same truncation affects +the automatic UMP client filter used to avoid delivery to inactive +groups, so events for group 16 cannot be filtered. + +Store the internal bitmap as unsigned int and keep both userspace-provided +and automatically generated values limited to the defined UAPI bits. + +Fixes: d2b706077792 ("ALSA: seq: Add UMP group filter") +Cc: stable@vger.kernel.org +Signed-off-by: Cássio Gabriel +Link: https://patch.msgid.link/20260506-alsa-seq-ump-group16-filter-v1-1-b75160bf6993@gmail.com +Signed-off-by: Takashi Iwai +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + sound/core/seq/seq_clientmgr.c | 2 +- + sound/core/seq/seq_clientmgr.h | 5 ++++- + sound/core/seq/seq_ump_client.c | 2 +- + 3 files changed, 6 insertions(+), 3 deletions(-) + +--- a/sound/core/seq/seq_clientmgr.c ++++ b/sound/core/seq/seq_clientmgr.c +@@ -1328,7 +1328,7 @@ static int snd_seq_ioctl_set_client_info + if (client->user_pversion >= SNDRV_PROTOCOL_VERSION(1, 0, 3)) + client->midi_version = client_info->midi_version; + memcpy(client->event_filter, client_info->event_filter, 32); +- client->group_filter = client_info->group_filter; ++ client->group_filter = client_info->group_filter & SND_SEQ_GROUP_FILTER_MASK; + + /* notify the change */ + snd_seq_system_client_ev_client_change(client->number); +--- a/sound/core/seq/seq_clientmgr.h ++++ b/sound/core/seq/seq_clientmgr.h +@@ -14,6 +14,9 @@ + + /* client manager */ + ++#define SND_SEQ_GROUP_FILTER_MASK GENMASK(SNDRV_UMP_MAX_GROUPS, 0) ++#define SND_SEQ_GROUP_FILTER_GROUPS GENMASK(SNDRV_UMP_MAX_GROUPS, 1) ++ + struct snd_seq_user_client { + struct file *file; /* file struct of client */ + /* ... */ +@@ -40,7 +43,7 @@ struct snd_seq_client { + int number; /* client number */ + unsigned int filter; /* filter flags */ + DECLARE_BITMAP(event_filter, 256); +- unsigned short group_filter; ++ unsigned int group_filter; + snd_use_lock_t use_lock; + int event_lost; + /* ports */ +--- a/sound/core/seq/seq_ump_client.c ++++ b/sound/core/seq/seq_ump_client.c +@@ -369,7 +369,7 @@ static void setup_client_group_filter(st + cptr = snd_seq_kernel_client_get(client->seq_client); + if (!cptr) + return; +- filter = ~(1U << 0); /* always allow groupless messages */ ++ filter = SND_SEQ_GROUP_FILTER_GROUPS; /* always allow groupless messages */ + for (p = 0; p < SNDRV_UMP_MAX_GROUPS; p++) { + if (client->ump->groups[p].active) + filter &= ~(1U << (p + 1)); diff --git a/queue-6.12/alsa-seq-notify-client-and-port-info-changes.patch b/queue-6.12/alsa-seq-notify-client-and-port-info-changes.patch new file mode 100644 index 0000000000..90ab0377db --- /dev/null +++ b/queue-6.12/alsa-seq-notify-client-and-port-info-changes.patch @@ -0,0 +1,69 @@ +From stable+bounces-246875-greg=kroah.com@vger.kernel.org Wed May 13 17:14:01 2026 +From: Sasha Levin +Date: Wed, 13 May 2026 10:09:31 -0400 +Subject: ALSA: seq: Notify client and port info changes +To: stable@vger.kernel.org +Cc: Takashi Iwai , Mark Lentczner , Sasha Levin +Message-ID: <20260513140932.3747146-1-sashal@kernel.org> + +From: Takashi Iwai + +[ Upstream commit b8e49e24cdba27a0810a0988e810e2c68f2033cb ] + +It was supposed to be notified when a sequencer client info and a port +info has changed (via SNDRV_SEQ_EVENT_CLIENT_CHANGE and +SNDRV_SEQ_EVENT_PORT_CHANGE event, respectively), and there are +already helper functions. But those aren't really sent from the +driver so far, except for the recent support of UMP, simply due to the +lack of implementations. + +This patch adds the missing notifications at updating the client and +the port info. The formerly added notification for UMP is dropped +because it's handled now in the port info side. + +Reported-by: Mark Lentczner +Link: https://lore.kernel.org/CAPnksqRok7xGa4bxq9WWimVV=28-7_j628OmrWLS=S0=hzaTHQ@mail.gmail.com +Link: https://patch.msgid.link/20241128074734.32165-1-tiwai@suse.de +Signed-off-by: Takashi Iwai +Stable-dep-of: 92429ca999db ("ALSA: seq: Fix UMP group 16 filtering") +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + sound/core/seq/seq_clientmgr.c | 7 +++++++ + sound/core/seq/seq_ump_client.c | 2 -- + 2 files changed, 7 insertions(+), 2 deletions(-) + +--- a/sound/core/seq/seq_clientmgr.c ++++ b/sound/core/seq/seq_clientmgr.c +@@ -1329,6 +1329,10 @@ static int snd_seq_ioctl_set_client_info + client->midi_version = client_info->midi_version; + memcpy(client->event_filter, client_info->event_filter, 32); + client->group_filter = client_info->group_filter; ++ ++ /* notify the change */ ++ snd_seq_system_client_ev_client_change(client->number); ++ + return 0; + } + +@@ -1452,6 +1456,9 @@ static int snd_seq_ioctl_set_port_info(s + if (port) { + snd_seq_set_port_info(port, info); + snd_seq_port_unlock(port); ++ /* notify the change */ ++ snd_seq_system_client_ev_port_change(info->addr.client, ++ info->addr.port); + } + return 0; + } +--- a/sound/core/seq/seq_ump_client.c ++++ b/sound/core/seq/seq_ump_client.c +@@ -272,8 +272,6 @@ static void update_port_infos(struct seq + new); + if (err < 0) + continue; +- /* notify to system port */ +- snd_seq_system_client_ev_port_change(client->seq_client, i); + } + } + diff --git a/queue-6.12/block-cleanup-blkdev_report_zones.patch b/queue-6.12/block-cleanup-blkdev_report_zones.patch new file mode 100644 index 0000000000..a7be6c35c5 --- /dev/null +++ b/queue-6.12/block-cleanup-blkdev_report_zones.patch @@ -0,0 +1,49 @@ +From stable+bounces-247263-greg=kroah.com@vger.kernel.org Thu May 14 19:58:45 2026 +From: Sasha Levin +Date: Thu, 14 May 2026 13:58:35 -0400 +Subject: block: cleanup blkdev_report_zones() +To: stable@vger.kernel.org +Cc: Damien Le Moal , Christoph Hellwig , Bart Van Assche , Hannes Reinecke , Johannes Thumshirn , Chaitanya Kulkarni , "Martin K. Petersen" , Jens Axboe , Sasha Levin +Message-ID: <20260514175837.526481-1-sashal@kernel.org> + +From: Damien Le Moal + +[ Upstream commit e8ecb21f081fe0cab33dc20cbe65ccbbfe615c15 ] + +The variable capacity is used only in one place and so can be removed +and get_capacity(disk) used directly instead. + +Signed-off-by: Damien Le Moal +Reviewed-by: Christoph Hellwig +Reviewed-by: Bart Van Assche +Reviewed-by: Hannes Reinecke +Reviewed-by: Johannes Thumshirn +Reviewed-by: Chaitanya Kulkarni +Reviewed-by: Martin K. Petersen +Signed-off-by: Jens Axboe +Stable-dep-of: b7d4ffb51037 ("block: fix zone write plug removal") +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + block/blk-zoned.c | 3 +-- + 1 file changed, 1 insertion(+), 2 deletions(-) + +--- a/block/blk-zoned.c ++++ b/block/blk-zoned.c +@@ -163,7 +163,6 @@ int blkdev_report_zones(struct block_dev + unsigned int nr_zones, report_zones_cb cb, void *data) + { + struct gendisk *disk = bdev->bd_disk; +- sector_t capacity = get_capacity(disk); + struct disk_report_zones_cb_args args = { + .disk = disk, + .user_cb = cb, +@@ -173,7 +172,7 @@ int blkdev_report_zones(struct block_dev + if (!bdev_is_zoned(bdev) || WARN_ON_ONCE(!disk->fops->report_zones)) + return -EOPNOTSUPP; + +- if (!nr_zones || sector >= capacity) ++ if (!nr_zones || sector >= get_capacity(disk)) + return 0; + + return disk->fops->report_zones(disk, sector, nr_zones, diff --git a/queue-6.12/block-fix-zone-write-plug-removal.patch b/queue-6.12/block-fix-zone-write-plug-removal.patch new file mode 100644 index 0000000000..862ba3e5ec --- /dev/null +++ b/queue-6.12/block-fix-zone-write-plug-removal.patch @@ -0,0 +1,292 @@ +From stable+bounces-247265-greg=kroah.com@vger.kernel.org Thu May 14 19:58:49 2026 +From: Sasha Levin +Date: Thu, 14 May 2026 13:58:37 -0400 +Subject: block: fix zone write plug removal +To: stable@vger.kernel.org +Cc: Damien Le Moal , Christoph Hellwig , Johannes Thumshirn , Jens Axboe , Sasha Levin +Message-ID: <20260514175837.526481-3-sashal@kernel.org> + +From: Damien Le Moal + +[ Upstream commit b7d4ffb510373cc6ecf16022dd0e510a023034fb ] + +Commit 7b295187287e ("block: Do not remove zone write plugs still in +use") modified disk_should_remove_zone_wplug() to add a check on the +reference count of a zone write plug to prevent removing zone write +plugs from a disk hash table when the plugs are still being referenced +by BIOs or requests in-flight. However, this check does not take into +account that a BIO completion may happen right after its submission by +a zone write plug BIO work, and before the zone write plug BIO work +releases the zone write plug reference count. This situation leads to +disk_should_remove_zone_wplug() returning false as in this case the zone +write plug reference count is at least equal to 3. If the BIO that +completes in such manner transitioned the zone to the FULL condition, +the zone write plug for the FULL zone will remain in the disk hash +table. + +Furthermore, relying on a particular value of a zone write plug +reference count to set the BLK_ZONE_WPLUG_UNHASHED flag is fragile as +reading the atomic reference count and doing a comparison with some +value is not overall atomic at all. + +Address these issues by reworking the reference counting of zone write +plugs so that removing plugs from a disk hash table can be done +directly from disk_put_zone_wplug() when the last reference on a plug +is dropped. + +To do so, replace the function disk_remove_zone_wplug() with +disk_mark_zone_wplug_dead(). This new function sets the zone write plug +flag BLK_ZONE_WPLUG_DEAD (which replaces BLK_ZONE_WPLUG_UNHASHED) and +drops the initial reference on the zone write plug taken when the plug +was added to the disk hash table. This function is called either for +zones that are empty or full, or directly in the case of a forced plug +removal (e.g. when the disk hash table is being destroyed on disk +removal). With this change, disk_should_remove_zone_wplug() is also +removed. + +disk_put_zone_wplug() is modified to call the function +disk_free_zone_wplug() to remove a zone write plug from a disk hash +table and free the plug structure (with a call_rcu()), when the last +reference on a zone write plug is dropped. disk_free_zone_wplug() +always checks that the BLK_ZONE_WPLUG_DEAD flag is set. + +In order to avoid having multiple zone write plugs for the same zone in +the disk hash table, disk_get_and_lock_zone_wplug() checked for the +BLK_ZONE_WPLUG_UNHASHED flag. This check is removed and a check for +the new BLK_ZONE_WPLUG_DEAD flag is added to +blk_zone_wplug_handle_write(). With this change, we continue preventing +adding multiple zone write plugs for the same zone and at the same time +re-inforce checks on the user behavior by failing new incoming write +BIOs targeting a zone that is marked as dead. This case can happen only +if the user erroneously issues write BIOs to zones that are full, or to +zones that are currently being reset or finished. + +Fixes: 7b295187287e ("block: Do not remove zone write plugs still in use") +Cc: stable@vger.kernel.org +Signed-off-by: Damien Le Moal +Reviewed-by: Christoph Hellwig +Reviewed-by: Johannes Thumshirn +Signed-off-by: Jens Axboe +[ dropped blk_zone_set_cond() and disk_zone_wplug_update_cond() calls due to missing zones_cond tracking prereq ] +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + block/blk-zoned.c | 145 ++++++++++++++++++++---------------------------------- + 1 file changed, 56 insertions(+), 89 deletions(-) + +--- a/block/blk-zoned.c ++++ b/block/blk-zoned.c +@@ -85,17 +85,17 @@ static inline unsigned int disk_zone_wpl + * being executed or the zone write plug bio list is not empty. + * - 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 +- * dropped. This flag is set when a zone is reset, finished or become full, +- * to prevent new references to the zone write plug to be taken for +- * newly incoming BIOs. A zone write plug flagged with this flag will be +- * freed once all remaining references from BIOs or functions are dropped. ++ * - BLK_ZONE_WPLUG_DEAD: Indicates that the zone write plug will be ++ * removed from the disk hash table of zone write plugs when the last ++ * reference on the zone write plug is dropped. If set, this flag also ++ * indicates that the initial extra reference on the zone write plug was ++ * dropped, meaning that the reference count indicates the current number of ++ * active users (code context or BIOs and requests in flight). This flag is ++ * set when a zone is reset, finished or becomes full. + */ + #define BLK_ZONE_WPLUG_PLUGGED (1U << 0) + #define BLK_ZONE_WPLUG_NEED_WP_UPDATE (1U << 1) +-#define BLK_ZONE_WPLUG_UNHASHED (1U << 2) ++#define BLK_ZONE_WPLUG_DEAD (1U << 2) + + /** + * blk_zone_cond_str - Return string XXX in BLK_ZONE_COND_XXX. +@@ -479,65 +479,42 @@ static void disk_free_zone_wplug_rcu(str + mempool_free(zwplug, zwplug->disk->zone_wplugs_pool); + } + +-static inline void disk_put_zone_wplug(struct blk_zone_wplug *zwplug) ++static void disk_free_zone_wplug(struct blk_zone_wplug *zwplug) + { +- if (refcount_dec_and_test(&zwplug->ref)) { +- WARN_ON_ONCE(!bio_list_empty(&zwplug->bio_list)); +- 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); +- } +-} +- +-static inline bool disk_should_remove_zone_wplug(struct gendisk *disk, +- struct blk_zone_wplug *zwplug) +-{ +- /* If the zone write plug was already removed, we are done. */ +- if (zwplug->flags & BLK_ZONE_WPLUG_UNHASHED) +- return false; ++ struct gendisk *disk = zwplug->disk; ++ unsigned long flags; + +- /* If the zone write plug is still plugged, it cannot be removed. */ +- if (zwplug->flags & BLK_ZONE_WPLUG_PLUGGED) +- return false; ++ WARN_ON_ONCE(!(zwplug->flags & BLK_ZONE_WPLUG_DEAD)); ++ WARN_ON_ONCE(zwplug->flags & BLK_ZONE_WPLUG_PLUGGED); ++ WARN_ON_ONCE(!bio_list_empty(&zwplug->bio_list)); + +- /* +- * Completions of BIOs with blk_zone_write_plug_bio_endio() may +- * happen after handling a request completion with +- * blk_zone_write_plug_finish_request() (e.g. with split BIOs +- * that are chained). In such case, disk_zone_wplug_unplug_bio() +- * should not attempt to remove the zone write plug until all BIO +- * completions are seen. Check by looking at the zone write plug +- * reference count, which is 2 when the plug is unused (one reference +- * taken when the plug was allocated and another reference taken by the +- * caller context). +- */ +- if (refcount_read(&zwplug->ref) > 2) +- return false; ++ spin_lock_irqsave(&disk->zone_wplugs_lock, flags); ++ hlist_del_init_rcu(&zwplug->node); ++ atomic_dec(&disk->nr_zone_wplugs); ++ spin_unlock_irqrestore(&disk->zone_wplugs_lock, flags); + +- /* We can remove zone write plugs for zones that are empty or full. */ +- return !zwplug->wp_offset || disk_zone_wplug_is_full(disk, zwplug); ++ call_rcu(&zwplug->rcu_head, disk_free_zone_wplug_rcu); + } + +-static void disk_remove_zone_wplug(struct gendisk *disk, +- struct blk_zone_wplug *zwplug) ++static inline void disk_put_zone_wplug(struct blk_zone_wplug *zwplug) + { +- unsigned long flags; ++ if (refcount_dec_and_test(&zwplug->ref)) ++ disk_free_zone_wplug(zwplug); ++} + +- /* If the zone write plug was already removed, we have nothing to do. */ +- if (zwplug->flags & BLK_ZONE_WPLUG_UNHASHED) +- return; ++/* ++ * Flag the zone write plug as dead and drop the initial reference we got when ++ * the zone write plug was added to the hash table. The zone write plug will be ++ * unhashed when its last reference is dropped. ++ */ ++static void disk_mark_zone_wplug_dead(struct blk_zone_wplug *zwplug) ++{ ++ lockdep_assert_held(&zwplug->lock); + +- /* +- * Mark the zone write plug as unhashed and drop the extra reference we +- * took when the plug was inserted in the hash table. +- */ +- zwplug->flags |= BLK_ZONE_WPLUG_UNHASHED; +- spin_lock_irqsave(&disk->zone_wplugs_lock, flags); +- hlist_del_init_rcu(&zwplug->node); +- atomic_dec(&disk->nr_zone_wplugs); +- spin_unlock_irqrestore(&disk->zone_wplugs_lock, flags); +- disk_put_zone_wplug(zwplug); ++ if (!(zwplug->flags & BLK_ZONE_WPLUG_DEAD)) { ++ zwplug->flags |= BLK_ZONE_WPLUG_DEAD; ++ disk_put_zone_wplug(zwplug); ++ } + } + + static void blk_zone_wplug_bio_work(struct work_struct *work); +@@ -557,18 +534,7 @@ static struct blk_zone_wplug *disk_get_a + again: + zwplug = disk_get_zone_wplug(disk, sector); + if (zwplug) { +- /* +- * Check that a BIO completion or a zone reset or finish +- * operation has not already removed the zone write plug from +- * the hash table and dropped its reference count. In such case, +- * we need to get a new plug so start over from the beginning. +- */ + spin_lock_irqsave(&zwplug->lock, *flags); +- if (zwplug->flags & BLK_ZONE_WPLUG_UNHASHED) { +- spin_unlock_irqrestore(&zwplug->lock, *flags); +- disk_put_zone_wplug(zwplug); +- goto again; +- } + return zwplug; + } + +@@ -654,14 +620,8 @@ static void disk_zone_wplug_set_wp_offse + zwplug->flags &= ~BLK_ZONE_WPLUG_NEED_WP_UPDATE; + zwplug->wp_offset = wp_offset; + disk_zone_wplug_abort(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); ++ if (!zwplug->wp_offset || disk_zone_wplug_is_full(disk, zwplug)) ++ disk_mark_zone_wplug_dead(zwplug); + } + + static unsigned int blk_zone_wp_offset(struct blk_zone *zone) +@@ -1076,6 +1036,19 @@ static bool blk_zone_wplug_handle_write( + return true; + } + ++ /* ++ * If we got a zone write plug marked as dead, then the user is issuing ++ * writes to a full zone, or without synchronizing with zone reset or ++ * zone finish operations. In such case, fail the BIO to signal this ++ * invalid usage. ++ */ ++ if (zwplug->flags & BLK_ZONE_WPLUG_DEAD) { ++ spin_unlock_irqrestore(&zwplug->lock, flags); ++ disk_put_zone_wplug(zwplug); ++ bio_io_error(bio); ++ return true; ++ } ++ + /* Indicate that this BIO is being handled using zone write plugging. */ + bio_set_flag(bio, BIO_ZONE_WRITE_PLUGGING); + +@@ -1144,7 +1117,7 @@ static void blk_zone_wplug_handle_native + disk->disk_name, zwplug->zone_no); + disk_zone_wplug_abort(zwplug); + } +- disk_remove_zone_wplug(disk, zwplug); ++ disk_mark_zone_wplug_dead(zwplug); + spin_unlock_irqrestore(&zwplug->lock, flags); + + disk_put_zone_wplug(zwplug); +@@ -1249,14 +1222,8 @@ static void disk_zone_wplug_unplug_bio(s + } + + zwplug->flags &= ~BLK_ZONE_WPLUG_PLUGGED; +- +- /* +- * If the zone is full (it was fully written or finished, or empty +- * (it was reset), remove its zone write plug from the hash table. +- */ +- if (disk_should_remove_zone_wplug(disk, zwplug)) +- disk_remove_zone_wplug(disk, zwplug); +- ++ if (!zwplug->wp_offset || disk_zone_wplug_is_full(disk, zwplug)) ++ disk_mark_zone_wplug_dead(zwplug); + spin_unlock_irqrestore(&zwplug->lock, flags); + } + +@@ -1450,9 +1417,9 @@ 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); +- refcount_inc(&zwplug->ref); +- disk_remove_zone_wplug(disk, zwplug); +- disk_put_zone_wplug(zwplug); ++ spin_lock_irq(&zwplug->lock); ++ disk_mark_zone_wplug_dead(zwplug); ++ spin_unlock_irq(&zwplug->lock); + } + } + diff --git a/queue-6.12/block-reorganize-struct-blk_zone_wplug.patch b/queue-6.12/block-reorganize-struct-blk_zone_wplug.patch new file mode 100644 index 0000000000..0cff612180 --- /dev/null +++ b/queue-6.12/block-reorganize-struct-blk_zone_wplug.patch @@ -0,0 +1,80 @@ +From stable+bounces-247264-greg=kroah.com@vger.kernel.org Thu May 14 19:58:47 2026 +From: Sasha Levin +Date: Thu, 14 May 2026 13:58:36 -0400 +Subject: block: reorganize struct blk_zone_wplug +To: stable@vger.kernel.org +Cc: Damien Le Moal , Christoph Hellwig , Bart Van Assche , Johannes Thumshirn , Chaitanya Kulkarni , Hannes Reinecke , "Martin K. Petersen" , Jens Axboe , Sasha Levin +Message-ID: <20260514175837.526481-2-sashal@kernel.org> + +From: Damien Le Moal + +[ Upstream commit ca1a897fb266c4b23b5ecb99fe787ed18559057d ] + +Reorganize the fields of struct blk_zone_wplug to remove a hole after +the wp_offset field and avoid having the bio_work structure split +between 2 cache lines. + +No functional changes. + +Signed-off-by: Damien Le Moal +Reviewed-by: Christoph Hellwig +Reviewed-by: Bart Van Assche +Reviewed-by: Johannes Thumshirn +Reviewed-by: Chaitanya Kulkarni +Reviewed-by: Hannes Reinecke +Reviewed-by: Martin K. Petersen +Signed-off-by: Jens Axboe +Stable-dep-of: b7d4ffb51037 ("block: fix zone write plug removal") +Signed-off-by: Sasha Levin +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 +@@ -41,6 +41,11 @@ static const char *const zone_cond_name[ + /* + * Per-zone write plug. + * @node: hlist_node structure for managing the plug using a hash table. ++ * @bio_list: The list of BIOs that are currently plugged. ++ * @bio_work: Work struct to handle issuing of plugged BIOs ++ * @rcu_head: RCU head to free zone write plugs with an RCU grace period. ++ * @disk: The gendisk the plug belongs to. ++ * @lock: Spinlock to atomically manipulate the plug. + * @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 +@@ -50,27 +55,22 @@ static const char *const zone_cond_name[ + * reference is dropped whenever the zone of the zone write plug is reset, + * finished and when the zone becomes full (last write BIO to the zone + * completes). +- * @lock: Spinlock to atomically manipulate the plug. + * @flags: Flags indicating the plug state. + * @zone_no: The number of the zone the plug is managing. + * @wp_offset: The zone write pointer location relative to the start of the zone + * as a number of 512B sectors. +- * @bio_list: The list of BIOs that are currently plugged. +- * @bio_work: Work struct to handle issuing of plugged BIOs +- * @rcu_head: RCU head to free zone write plugs with an RCU grace period. +- * @disk: The gendisk the plug belongs to. + */ + struct blk_zone_wplug { + struct hlist_node node; +- refcount_t ref; +- spinlock_t lock; +- unsigned int flags; +- unsigned int zone_no; +- unsigned int wp_offset; + struct bio_list bio_list; + struct work_struct bio_work; + struct rcu_head rcu_head; + struct gendisk *disk; ++ spinlock_t lock; ++ refcount_t ref; ++ unsigned int flags; ++ unsigned int zone_no; ++ unsigned int wp_offset; + }; + + static inline unsigned int disk_zone_wplugs_hash_size(struct gendisk *disk) diff --git a/queue-6.12/bluetooth-hci_conn-fix-potential-uaf-in-create_big_sync.patch b/queue-6.12/bluetooth-hci_conn-fix-potential-uaf-in-create_big_sync.patch new file mode 100644 index 0000000000..87ed3534d0 --- /dev/null +++ b/queue-6.12/bluetooth-hci_conn-fix-potential-uaf-in-create_big_sync.patch @@ -0,0 +1,96 @@ +From stable+bounces-246962-greg=kroah.com@vger.kernel.org Wed May 13 19:41:35 2026 +From: Sasha Levin +Date: Wed, 13 May 2026 13:16:14 -0400 +Subject: Bluetooth: hci_conn: fix potential UAF in create_big_sync +To: stable@vger.kernel.org +Cc: David Carlier , Luiz Augusto von Dentz , Sasha Levin +Message-ID: <20260513171614.3877718-1-sashal@kernel.org> + +From: David Carlier + +[ Upstream commit 0beddb0c380bed5f5b8e61ddbe14635bb73d0b41 ] + +Add hci_conn_valid() check in create_big_sync() to detect stale +connections before proceeding with BIG creation. Handle the +resulting -ECANCELED in create_big_complete() and re-validate the +connection under hci_dev_lock() before dereferencing, matching the +pattern used by create_le_conn_complete() and create_pa_complete(). + +Keep the hci_conn object alive across the async boundary by taking +a reference via hci_conn_get() when queueing create_big_sync(), and +dropping it in the completion callback. The refcount and the lock +are complementary: the refcount keeps the object allocated, while +hci_dev_lock() serializes hci_conn_hash_del()'s list_del_rcu() on +hdev->conn_hash, as required by hci_conn_del(). + +hci_conn_put() is called outside hci_dev_unlock() so the final put +(which resolves to kfree() via bt_link_release) does not run under +hdev->lock, though the release path would be safe either way. + +Without this, create_big_complete() would unconditionally +dereference the conn pointer on error, causing a use-after-free +via hci_connect_cfm() and hci_conn_del(). + +Fixes: eca0ae4aea66 ("Bluetooth: Add initial implementation of BIS connections") +Cc: stable@vger.kernel.org +Co-developed-by: Luiz Augusto von Dentz +Signed-off-by: Luiz Augusto von Dentz +Signed-off-by: David Carlier +Signed-off-by: Luiz Augusto von Dentz +[ kept stable's `qos->bcast.out.phy == 0x02` context line instead of upstream's renamed `qos->bcast.out.phys == BIT(1)` ] +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + net/bluetooth/hci_conn.c | 19 ++++++++++++++++++- + 1 file changed, 18 insertions(+), 1 deletion(-) + +--- a/net/bluetooth/hci_conn.c ++++ b/net/bluetooth/hci_conn.c +@@ -2051,6 +2051,9 @@ static int create_big_sync(struct hci_de + u32 flags = 0; + int err; + ++ if (!hci_conn_valid(hdev, conn)) ++ return -ECANCELED; ++ + if (qos->bcast.out.phy == 0x02) + flags |= MGMT_ADV_FLAG_SEC_2M; + +@@ -2125,11 +2128,24 @@ static void create_big_complete(struct h + + bt_dev_dbg(hdev, "conn %p", conn); + ++ if (err == -ECANCELED) ++ goto done; ++ ++ hci_dev_lock(hdev); ++ ++ if (!hci_conn_valid(hdev, conn)) ++ goto unlock; ++ + if (err) { + bt_dev_err(hdev, "Unable to create BIG: %d", err); + hci_connect_cfm(conn, err); + hci_conn_del(conn); + } ++ ++unlock: ++ hci_dev_unlock(hdev); ++done: ++ hci_conn_put(conn); + } + + struct hci_conn *hci_bind_bis(struct hci_dev *hdev, bdaddr_t *dst, +@@ -2230,10 +2246,11 @@ struct hci_conn *hci_connect_bis(struct + BT_BOUND, &data); + + /* Queue start periodic advertising and create BIG */ +- err = hci_cmd_sync_queue(hdev, create_big_sync, conn, ++ err = hci_cmd_sync_queue(hdev, create_big_sync, hci_conn_get(conn), + create_big_complete); + if (err < 0) { + hci_conn_drop(conn); ++ hci_conn_put(conn); + return ERR_PTR(err); + } + diff --git a/queue-6.12/fbcon-avoid-oob-font-access-if-console-rotation-fails.patch b/queue-6.12/fbcon-avoid-oob-font-access-if-console-rotation-fails.patch new file mode 100644 index 0000000000..811054d0a8 --- /dev/null +++ b/queue-6.12/fbcon-avoid-oob-font-access-if-console-rotation-fails.patch @@ -0,0 +1,56 @@ +From stable+bounces-247284-greg=kroah.com@vger.kernel.org Thu May 14 21:27:39 2026 +From: Sasha Levin +Date: Thu, 14 May 2026 15:26:19 -0400 +Subject: fbcon: Avoid OOB font access if console rotation fails +To: stable@vger.kernel.org +Cc: Thomas Zimmermann , Helge Deller , Sasha Levin +Message-ID: <20260514192619.1259876-1-sashal@kernel.org> + +From: Thomas Zimmermann + +[ Upstream commit e4ef723d8975a2694cc90733a6b888a5e2841842 ] + +Clear the font buffer if the reallocation during console rotation fails +in fbcon_rotate_font(). The putcs implementations for the rotated buffer +will return early in this case. See [1] for an example. + +Currently, fbcon_rotate_font() keeps the old buffer, which is too small +for the rotated font. Printing to the rotated console with a high-enough +character code will overflow the font buffer. + +v2: +- fix typos in commit message + +Signed-off-by: Thomas Zimmermann +Fixes: 6cc50e1c5b57 ("[PATCH] fbcon: Console Rotation - Add support to rotate font bitmap") +Cc: stable@vger.kernel.org # v2.6.15+ +Link: https://elixir.bootlin.com/linux/v6.19/source/drivers/video/fbdev/core/fbcon_ccw.c#L144 # [1] +Signed-off-by: Helge Deller +[ renamed `par` to `ops` to match the 6.12 local pointer name ] +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + drivers/video/fbdev/core/fbcon_rotate.c | 5 ++++- + 1 file changed, 4 insertions(+), 1 deletion(-) + +--- a/drivers/video/fbdev/core/fbcon_rotate.c ++++ b/drivers/video/fbdev/core/fbcon_rotate.c +@@ -46,6 +46,10 @@ static int fbcon_rotate_font(struct fb_i + info->fbops->fb_sync(info); + + if (ops->fd_size < d_cellsize * len) { ++ kfree(ops->fontbuffer); ++ ops->fontbuffer = NULL; ++ ops->fd_size = 0; ++ + dst = kmalloc_array(len, d_cellsize, GFP_KERNEL); + + if (dst == NULL) { +@@ -54,7 +58,6 @@ static int fbcon_rotate_font(struct fb_i + } + + ops->fd_size = d_cellsize * len; +- kfree(ops->fontbuffer); + ops->fontbuffer = dst; + } + diff --git a/queue-6.12/mm-hugetlb_cma-round-up-per_node-before-logging-it.patch b/queue-6.12/mm-hugetlb_cma-round-up-per_node-before-logging-it.patch new file mode 100644 index 0000000000..94dbbd3510 --- /dev/null +++ b/queue-6.12/mm-hugetlb_cma-round-up-per_node-before-logging-it.patch @@ -0,0 +1,79 @@ +From stable+bounces-247194-greg=kroah.com@vger.kernel.org Thu May 14 14:41:52 2026 +From: Sasha Levin +Date: Thu, 14 May 2026 08:41:03 -0400 +Subject: mm/hugetlb_cma: round up per_node before logging it +To: stable@vger.kernel.org +Cc: Sang-Heon Jeon , Muchun Song , David Hildenbrand , Oscar Salvador , Andrew Morton , Sasha Levin +Message-ID: <20260514124103.211726-1-sashal@kernel.org> + +From: Sang-Heon Jeon + +[ Upstream commit 8f5ce56b76303c55b78a87af996e2e0f8535f979 ] + +When the user requests a total hugetlb CMA size without per-node +specification, hugetlb_cma_reserve() computes per_node from +hugetlb_cma_size and the number of nodes that have memory + + per_node = DIV_ROUND_UP(hugetlb_cma_size, + nodes_weight(hugetlb_bootmem_nodes)); + +The reservation loop later computes + + size = round_up(min(per_node, hugetlb_cma_size - reserved), + PAGE_SIZE << order); + +So the actually reserved per_node size is multiple of (PAGE_SIZE << +order), but the logged per_node is not rounded up, so it may be smaller +than the actual reserved size. + +For example, as the existing comment describes, if a 3 GB area is +requested on a machine with 4 NUMA nodes that have memory, 1 GB is +allocated on the first three nodes, but the printed log is + + hugetlb_cma: reserve 3072 MiB, up to 768 MiB per node + +Round per_node up to (PAGE_SIZE << order) before logging so that the +printed log always matches the actual reserved size. No functional change +to the actual reservation size, as the following case analysis shows + +1. remaining (hugetlb_cma_size - reserved) >= rounded per_node + - AS-IS: min() picks unrounded per_node; + round_up() returns rounded per_node + - TO-BE: min() picks rounded per_node; + round_up() returns rounded per_node (no-op) +2. remaining < unrounded per_node + - AS-IS: min() picks remaining; + round_up() returns round_up(remaining) + - TO-BE: min() picks remaining; + round_up() returns round_up(remaining) +3. unrounded per_node <= remaining < rounded per_node + - AS-IS: min() picks unrounded per_node; + round_up() returns rounded per_node + - TO-BE: min() picks remaining; + round_up() returns round_up(remaining) equals rounded per_node + +Link: https://lore.kernel.org/20260422143353.852257-1-ekffu200098@gmail.com +Fixes: cf11e85fc08c ("mm: hugetlb: optionally allocate gigantic hugepages using cma") # 5.7 +Signed-off-by: Sang-Heon Jeon +Reviewed-by: Muchun Song +Cc: David Hildenbrand +Cc: Oscar Salvador +Cc: +Signed-off-by: Andrew Morton +[ applied the single-line addition to mm/hugetlb.c since mm/hugetlb_cma.c didn't exist yet in 6.12 ] +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + mm/hugetlb.c | 1 + + 1 file changed, 1 insertion(+) + +--- a/mm/hugetlb.c ++++ b/mm/hugetlb.c +@@ -7689,6 +7689,7 @@ void __init hugetlb_cma_reserve(int orde + * let's allocate 1 GB on first three nodes and ignore the last one. + */ + per_node = DIV_ROUND_UP(hugetlb_cma_size, nr_online_nodes); ++ per_node = round_up(per_node, PAGE_SIZE << order); + pr_info("hugetlb_cma: reserve %lu MiB, up to %lu MiB per node\n", + hugetlb_cma_size / SZ_1M, per_node / SZ_1M); + } diff --git a/queue-6.12/rust-pin-init-fix-incorrect-accessor-reference-lifetime.patch b/queue-6.12/rust-pin-init-fix-incorrect-accessor-reference-lifetime.patch new file mode 100644 index 0000000000..0fa4ce119e --- /dev/null +++ b/queue-6.12/rust-pin-init-fix-incorrect-accessor-reference-lifetime.patch @@ -0,0 +1,269 @@ +From gary@garyguo.net Wed May 13 15:26:20 2026 +From: Gary Guo +Date: Wed, 13 May 2026 14:25:36 +0100 +Subject: rust: pin-init: fix incorrect accessor reference lifetime +To: gregkh@linuxfoundation.org, ojeda@kernel.org +Cc: stable@vger.kernel.org, Gary Guo +Message-ID: <20260513132535.3822518-2-gary@garyguo.net> + +From: Gary Guo + +commit 68bf102226cf2199dc609b67c1e847cad4de4b57 upstream + +When a field has been initialized, `init!`/`pin_init!` create a reference +or pinned reference to the field so it can be accessed later during the +initialization of other fields. However, the reference it created is +incorrectly `&'static` rather than just the scope of the initializer. + +This means that you can do + + init!(Foo { + a: 1, + _: { + let b: &'static u32 = a; + } + }) + +which is unsound. + +This is caused by `&mut (*$slot).$ident`, which actually allows arbitrary +lifetime, so this is effectively `'static`. + +Fix it by adding `let_binding` method on `DropGuard` to shorten lifetime. +This results in exactly what we want for these accessors. The safety and +invariant comments of `DropGuard` have been reworked; instead of reasoning +about what caller can do with the guard, express it in a way that the +ownership is transferred to the guard and `forget` takes it back, so the +unsafe operations within the `DropGuard` can be more easily justified. + +Assisted-by: Claude:claude-3-opus +Signed-off-by: Gary Guo +Signed-off-by: Greg Kroah-Hartman +--- + rust/kernel/init/__internal.rs | 28 ++++++++---- + rust/kernel/init/macros.rs | 91 ++++++++++++++++++++++++----------------- + 2 files changed, 73 insertions(+), 46 deletions(-) + +--- a/rust/kernel/init/__internal.rs ++++ b/rust/kernel/init/__internal.rs +@@ -189,32 +189,42 @@ impl StackInit { + /// When a value of this type is dropped, it drops a `T`. + /// + /// Can be forgotten to prevent the drop. ++/// ++/// # Invariants ++/// ++/// - `ptr` is valid and properly aligned. ++/// - `*ptr` is initialized and owned by this guard. + pub struct DropGuard { + ptr: *mut T, + } + + impl DropGuard { +- /// Creates a new [`DropGuard`]. It will [`ptr::drop_in_place`] `ptr` when it gets dropped. ++ /// Creates a drop guard and transfer the ownership of the pointer content. + /// +- /// # Safety ++ /// The ownership is only relinquished if the guard is forgotten via [`core::mem::forget`]. + /// +- /// `ptr` must be a valid pointer. ++ /// # Safety + /// +- /// It is the callers responsibility that `self` will only get dropped if the pointee of `ptr`: +- /// - has not been dropped, +- /// - is not accessible by any other means, +- /// - will not be dropped by any other means. ++ /// - `ptr` is valid and properly aligned. ++ /// - `*ptr` is initialized, and the ownership is transferred to this guard. + #[inline] + pub unsafe fn new(ptr: *mut T) -> Self { ++ // INVARIANT: By safety requirement. + Self { ptr } + } ++ ++ /// Create a let binding for accessor use. ++ #[inline] ++ pub fn let_binding(&mut self) -> &mut T { ++ // SAFETY: Per type invariant. ++ unsafe { &mut *self.ptr } ++ } + } + + impl Drop for DropGuard { + #[inline] + fn drop(&mut self) { +- // SAFETY: A `DropGuard` can only be constructed using the unsafe `new` function +- // ensuring that this operation is safe. ++ // SAFETY: `self.ptr` is valid, properly aligned and `*self.ptr` is owned by this guard. + unsafe { ptr::drop_in_place(self.ptr) } + } + } +--- a/rust/kernel/init/macros.rs ++++ b/rust/kernel/init/macros.rs +@@ -1232,27 +1232,33 @@ macro_rules! __init_internal { + // return when an error/panic occurs. + // We also use the `data` to require the correct trait (`Init` or `PinInit`) for `$field`. + unsafe { $data.$field(::core::ptr::addr_of_mut!((*$slot).$field), init)? }; +- // NOTE: the field accessor ensures that the initialized field is properly aligned. ++ // NOTE: this ensures that the initialized field is properly aligned. + // Unaligned fields will cause the compiler to emit E0793. We do not support + // unaligned fields since `Init::__init` requires an aligned pointer; the call to + // `ptr::write` below has the same requirement. +- #[allow(unused_variables, unused_assignments)] +- // SAFETY: +- // - the project function does the correct field projection, +- // - the field has been initialized, +- // - the reference is only valid until the end of the initializer. +- let $field = $crate::macros::paste!(unsafe { $data.[< __project_ $field >](&mut (*$slot).$field) }); ++ // SAFETY: the field has been initialized. ++ let _ = unsafe { &mut (*$slot).$field }; + + // Create the drop guard: + // + // We rely on macro hygiene to make it impossible for users to access this local variable. + // We use `paste!` to create new hygiene for `$field`. + ::kernel::macros::paste! { +- // SAFETY: We forget the guard later when initialization has succeeded. +- let [< __ $field _guard >] = unsafe { ++ // SAFETY: ++ // - `addr_of_mut!((*$slot).$field)` is valid. ++ // - `(*$slot).$field` has been initialized above. ++ // - We only need the ownership to the pointee back when initialization has ++ // succeeded, where we `forget` the guard. ++ let mut [< __ $field _guard >] = unsafe { + $crate::init::__internal::DropGuard::new(::core::ptr::addr_of_mut!((*$slot).$field)) + }; + ++ // NOTE: The reference is derived from the guard so that it only lives as long as ++ // the guard does and cannot escape the scope. ++ #[allow(unused_variables, unused_assignments)] ++ // SAFETY: the project function does the correct field projection. ++ let $field = unsafe { $data.[< __project_ $field >]([< __ $field _guard >].let_binding()) }; ++ + $crate::__init_internal!(init_slot($use_data): + @data($data), + @slot($slot), +@@ -1275,27 +1281,30 @@ macro_rules! __init_internal { + // return when an error/panic occurs. + unsafe { $crate::init::Init::__init(init, ::core::ptr::addr_of_mut!((*$slot).$field))? }; + +- // NOTE: the field accessor ensures that the initialized field is properly aligned. ++ // NOTE: this ensures that the initialized field is properly aligned. + // Unaligned fields will cause the compiler to emit E0793. We do not support + // unaligned fields since `Init::__init` requires an aligned pointer; the call to + // `ptr::write` below has the same requirement. +- #[allow(unused_variables, unused_assignments)] +- // SAFETY: +- // - the field is not structurally pinned, since the line above must compile, +- // - the field has been initialized, +- // - the reference is only valid until the end of the initializer. +- let $field = unsafe { &mut (*$slot).$field }; ++ // SAFETY: the field has been initialized. ++ let _ = unsafe { &mut (*$slot).$field }; + + // Create the drop guard: + // + // We rely on macro hygiene to make it impossible for users to access this local variable. + // We use `paste!` to create new hygiene for `$field`. + ::kernel::macros::paste! { +- // SAFETY: We forget the guard later when initialization has succeeded. +- let [< __ $field _guard >] = unsafe { ++ // SAFETY: ++ // - `addr_of_mut!((*$slot).$field)` is valid. ++ // - `(*$slot).$field` has been initialized above. ++ // - We only need the ownership to the pointee back when initialization has ++ // succeeded, where we `forget` the guard. ++ let mut [< __ $field _guard >] = unsafe { + $crate::init::__internal::DropGuard::new(::core::ptr::addr_of_mut!((*$slot).$field)) + }; + ++ #[allow(unused_variables, unused_assignments)] ++ let $field = [< __ $field _guard >].let_binding(); ++ + $crate::__init_internal!(init_slot(): + @data($data), + @slot($slot), +@@ -1319,28 +1328,30 @@ macro_rules! __init_internal { + unsafe { ::core::ptr::write(::core::ptr::addr_of_mut!((*$slot).$field), $field) }; + } + +- // NOTE: the field accessor ensures that the initialized field is properly aligned. ++ // NOTE: this ensures that the initialized field is properly aligned. + // Unaligned fields will cause the compiler to emit E0793. We do not support + // unaligned fields since `Init::__init` requires an aligned pointer; the call to + // `ptr::write` below has the same requirement. +- #[allow(unused_variables, unused_assignments)] +- // SAFETY: +- // - the field is not structurally pinned, since no `use_data` was required to create this +- // initializer, +- // - the field has been initialized, +- // - the reference is only valid until the end of the initializer. +- let $field = unsafe { &mut (*$slot).$field }; ++ // SAFETY: the field has been initialized. ++ let _ = unsafe { &mut (*$slot).$field }; + + // Create the drop guard: + // + // We rely on macro hygiene to make it impossible for users to access this local variable. + // We use `paste!` to create new hygiene for `$field`. + ::kernel::macros::paste! { +- // SAFETY: We forget the guard later when initialization has succeeded. +- let [< __ $field _guard >] = unsafe { ++ // SAFETY: ++ // - `addr_of_mut!((*$slot).$field)` is valid. ++ // - `(*$slot).$field` has been initialized above. ++ // - We only need the ownership to the pointee back when initialization has ++ // succeeded, where we `forget` the guard. ++ let mut [< __ $field _guard >] = unsafe { + $crate::init::__internal::DropGuard::new(::core::ptr::addr_of_mut!((*$slot).$field)) + }; + ++ #[allow(unused_variables, unused_assignments)] ++ let $field = [< __ $field _guard >].let_binding(); ++ + $crate::__init_internal!(init_slot(): + @data($data), + @slot($slot), +@@ -1363,27 +1374,33 @@ macro_rules! __init_internal { + // SAFETY: The memory at `slot` is uninitialized. + unsafe { ::core::ptr::write(::core::ptr::addr_of_mut!((*$slot).$field), $field) }; + } +- // NOTE: the field accessor ensures that the initialized field is properly aligned. ++ // NOTE: this ensures that the initialized field is properly aligned. + // Unaligned fields will cause the compiler to emit E0793. We do not support + // unaligned fields since `Init::__init` requires an aligned pointer; the call to + // `ptr::write` below has the same requirement. +- #[allow(unused_variables, unused_assignments)] +- // SAFETY: +- // - the project function does the correct field projection, +- // - the field has been initialized, +- // - the reference is only valid until the end of the initializer. +- let $field = $crate::macros::paste!(unsafe { $data.[< __project_ $field >](&mut (*$slot).$field) }); ++ // SAFETY: the field has been initialized. ++ let _ = unsafe { &mut (*$slot).$field }; + + // Create the drop guard: + // + // We rely on macro hygiene to make it impossible for users to access this local variable. + // We use `paste!` to create new hygiene for `$field`. + $crate::macros::paste! { +- // SAFETY: We forget the guard later when initialization has succeeded. +- let [< __ $field _guard >] = unsafe { ++ // SAFETY: ++ // - `addr_of_mut!((*$slot).$field)` is valid. ++ // - `(*$slot).$field` has been initialized above. ++ // - We only need the ownership to the pointee back when initialization has ++ // succeeded, where we `forget` the guard. ++ let mut [< __ $field _guard >] = unsafe { + $crate::init::__internal::DropGuard::new(::core::ptr::addr_of_mut!((*$slot).$field)) + }; + ++ // NOTE: The reference is derived from the guard so that it only lives as long as ++ // the guard does and cannot escape the scope. ++ #[allow(unused_variables, unused_assignments)] ++ // SAFETY: the project function does the correct field projection. ++ let $field = unsafe { $data.[< __project_ $field >]([< __ $field _guard >].let_binding()) }; ++ + $crate::__init_internal!(init_slot($use_data): + @data($data), + @slot($slot), diff --git a/queue-6.12/series b/queue-6.12/series index 12615b93cf..ee798e98e0 100644 --- a/queue-6.12/series +++ b/queue-6.12/series @@ -100,3 +100,24 @@ batman-adv-bla-prevent-use-after-free-when-deleting-claims.patch batman-adv-bla-only-purge-non-released-claims.patch batman-adv-bla-put-backbone-reference-on-failed-claim-hash-insert.patch sched_ext-use-hk_type_domain_boot-to-detect-isolcpus-domain-isolation.patch +usb-typec-tcpm-reset-internal-port-states-on-soft-reset-ams.patch +usb-dwc3-move-guid-programming-after-phy-initialization.patch +alsa-hda-cs35l56-propagate-asp-tx-source-control-errors.patch +alsa-misc-use-guard-for-spin-locks.patch +alsa-core-serialize-deferred-fasync-state-checks.patch +alsa-seq-notify-client-and-port-info-changes.patch +alsa-seq-fix-ump-group-16-filtering.patch +bluetooth-hci_conn-fix-potential-uaf-in-create_big_sync.patch +spi-zynq-qspi-simplify-clock-handling-with-devm_clk_get_enabled.patch +spi-zynq-qspi-fix-controller-deregistration.patch +spi-tegra20-sflash-fix-controller-deregistration.patch +spi-tegra114-fix-controller-deregistration.patch +spi-uniphier-simplify-clock-handling-with-devm_clk_get_enabled.patch +spi-uniphier-fix-controller-deregistration.patch +mm-hugetlb_cma-round-up-per_node-before-logging-it.patch +block-cleanup-blkdev_report_zones.patch +block-reorganize-struct-blk_zone_wplug.patch +block-fix-zone-write-plug-removal.patch +tracefs-fix-default-permissions-not-being-applied-on-initial-mount.patch +fbcon-avoid-oob-font-access-if-console-rotation-fails.patch +rust-pin-init-fix-incorrect-accessor-reference-lifetime.patch diff --git a/queue-6.12/spi-tegra114-fix-controller-deregistration.patch b/queue-6.12/spi-tegra114-fix-controller-deregistration.patch new file mode 100644 index 0000000000..87174bae56 --- /dev/null +++ b/queue-6.12/spi-tegra114-fix-controller-deregistration.patch @@ -0,0 +1,59 @@ +From stable+bounces-247097-greg=kroah.com@vger.kernel.org Thu May 14 06:14:21 2026 +From: Sasha Levin +Date: Thu, 14 May 2026 00:14:15 -0400 +Subject: spi: tegra114: fix controller deregistration +To: stable@vger.kernel.org +Cc: Johan Hovold , Jingoo Han , Mark Brown , Sasha Levin +Message-ID: <20260514041415.4189700-1-sashal@kernel.org> + +From: Johan Hovold + +[ Upstream commit 9c9c27ff2058142d8f800de3186d6864184958de ] + +Make sure to deregister the controller before disabling underlying +resources like clocks during driver unbind. + +Fixes: 5c8096439600 ("spi: tegra114: use devm_spi_register_master()") +Cc: stable@vger.kernel.org # 3.13 +Cc: Jingoo Han +Signed-off-by: Johan Hovold +Link: https://patch.msgid.link/20260410081757.503099-22-johan@kernel.org +Signed-off-by: Mark Brown +[ kept `host->dev.of_node = pdev->dev.of_node;` context line above the `spi_register_controller()` conversion ] +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + drivers/spi/spi-tegra114.c | 8 +++++++- + 1 file changed, 7 insertions(+), 1 deletion(-) + +--- a/drivers/spi/spi-tegra114.c ++++ b/drivers/spi/spi-tegra114.c +@@ -1416,7 +1416,7 @@ static int tegra_spi_probe(struct platfo + } + + host->dev.of_node = pdev->dev.of_node; +- ret = devm_spi_register_controller(&pdev->dev, host); ++ ret = spi_register_controller(host); + if (ret < 0) { + dev_err(&pdev->dev, "can not register to host err %d\n", ret); + goto exit_free_irq; +@@ -1442,6 +1442,10 @@ static void tegra_spi_remove(struct plat + struct spi_controller *host = platform_get_drvdata(pdev); + struct tegra_spi_data *tspi = spi_controller_get_devdata(host); + ++ spi_controller_get(host); ++ ++ spi_unregister_controller(host); ++ + free_irq(tspi->irq, tspi); + + if (tspi->tx_dma_chan) +@@ -1453,6 +1457,8 @@ static void tegra_spi_remove(struct plat + pm_runtime_disable(&pdev->dev); + if (!pm_runtime_status_suspended(&pdev->dev)) + tegra_spi_runtime_suspend(&pdev->dev); ++ ++ spi_controller_put(host); + } + + #ifdef CONFIG_PM_SLEEP diff --git a/queue-6.12/spi-tegra20-sflash-fix-controller-deregistration.patch b/queue-6.12/spi-tegra20-sflash-fix-controller-deregistration.patch new file mode 100644 index 0000000000..365b20707a --- /dev/null +++ b/queue-6.12/spi-tegra20-sflash-fix-controller-deregistration.patch @@ -0,0 +1,57 @@ +From stable+bounces-247102-greg=kroah.com@vger.kernel.org Thu May 14 06:36:31 2026 +From: Sasha Levin +Date: Thu, 14 May 2026 00:36:25 -0400 +Subject: spi: tegra20-sflash: fix controller deregistration +To: stable@vger.kernel.org +Cc: Johan Hovold , Jingoo Han , Mark Brown , Sasha Levin +Message-ID: <20260514043625.10766-1-sashal@kernel.org> + +From: Johan Hovold + +[ Upstream commit ad7310e983327f939dd6c4e801eab13238992572 ] + +Make sure to deregister the controller before disabling underlying +resources like clocks during driver unbind. + +Fixes: f12f7318c44a ("spi: tegra20-sflash: use devm_spi_register_master()") +Cc: stable@vger.kernel.org # 3.13 +Cc: Jingoo Han +Signed-off-by: Johan Hovold +Link: https://patch.msgid.link/20260410081757.503099-23-johan@kernel.org +Signed-off-by: Mark Brown +[ kept the redundant `host->dev.of_node = pdev->dev.of_node;` line above the registration call ] +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + drivers/spi/spi-tegra20-sflash.c | 8 +++++++- + 1 file changed, 7 insertions(+), 1 deletion(-) + +--- a/drivers/spi/spi-tegra20-sflash.c ++++ b/drivers/spi/spi-tegra20-sflash.c +@@ -506,7 +506,7 @@ static int tegra_sflash_probe(struct pla + pm_runtime_put(&pdev->dev); + + host->dev.of_node = pdev->dev.of_node; +- ret = devm_spi_register_controller(&pdev->dev, host); ++ ret = spi_register_controller(host); + if (ret < 0) { + dev_err(&pdev->dev, "can not register to host err %d\n", ret); + goto exit_pm_disable; +@@ -529,11 +529,17 @@ static void tegra_sflash_remove(struct p + struct spi_controller *host = platform_get_drvdata(pdev); + struct tegra_sflash_data *tsd = spi_controller_get_devdata(host); + ++ spi_controller_get(host); ++ ++ spi_unregister_controller(host); ++ + free_irq(tsd->irq, tsd); + + pm_runtime_disable(&pdev->dev); + if (!pm_runtime_status_suspended(&pdev->dev)) + tegra_sflash_runtime_suspend(&pdev->dev); ++ ++ spi_controller_put(host); + } + + #ifdef CONFIG_PM_SLEEP diff --git a/queue-6.12/spi-uniphier-fix-controller-deregistration.patch b/queue-6.12/spi-uniphier-fix-controller-deregistration.patch new file mode 100644 index 0000000000..9d49632344 --- /dev/null +++ b/queue-6.12/spi-uniphier-fix-controller-deregistration.patch @@ -0,0 +1,59 @@ +From stable+bounces-247116-greg=kroah.com@vger.kernel.org Thu May 14 07:20:55 2026 +From: Sasha Levin +Date: Thu, 14 May 2026 01:20:15 -0400 +Subject: spi: uniphier: fix controller deregistration +To: stable@vger.kernel.org +Cc: Johan Hovold , Keiji Hayashibara , Mark Brown , Sasha Levin +Message-ID: <20260514052015.40231-2-sashal@kernel.org> + +From: Johan Hovold + +[ Upstream commit 0245435f777264ac45945ed2f325dd095a41d1af ] + +Make sure to deregister the controller before releasing underlying +resources like DMA during driver unbind. + +Note that clocks were also disabled before the recent commit +fdca270f8f87 ("spi: uniphier: Simplify clock handling with +devm_clk_get_enabled()"). + +Fixes: 5ba155a4d4cc ("spi: add SPI controller driver for UniPhier SoC") +Cc: stable@vger.kernel.org # 4.19 +Cc: Keiji Hayashibara +Signed-off-by: Johan Hovold +Link: https://patch.msgid.link/20260410081757.503099-25-johan@kernel.org +Signed-off-by: Mark Brown +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + drivers/spi/spi-uniphier.c | 8 +++++++- + 1 file changed, 7 insertions(+), 1 deletion(-) + +--- a/drivers/spi/spi-uniphier.c ++++ b/drivers/spi/spi-uniphier.c +@@ -747,7 +747,7 @@ static int uniphier_spi_probe(struct pla + + host->max_dma_len = min(dma_tx_burst, dma_rx_burst); + +- ret = devm_spi_register_controller(&pdev->dev, host); ++ ret = spi_register_controller(host); + if (ret) + goto out_release_dma; + +@@ -772,10 +772,16 @@ static void uniphier_spi_remove(struct p + { + struct spi_controller *host = platform_get_drvdata(pdev); + ++ spi_controller_get(host); ++ ++ spi_unregister_controller(host); ++ + if (host->dma_tx) + dma_release_channel(host->dma_tx); + if (host->dma_rx) + dma_release_channel(host->dma_rx); ++ ++ spi_controller_put(host); + } + + static const struct of_device_id uniphier_spi_match[] = { diff --git a/queue-6.12/spi-uniphier-simplify-clock-handling-with-devm_clk_get_enabled.patch b/queue-6.12/spi-uniphier-simplify-clock-handling-with-devm_clk_get_enabled.patch new file mode 100644 index 0000000000..37e2dc000f --- /dev/null +++ b/queue-6.12/spi-uniphier-simplify-clock-handling-with-devm_clk_get_enabled.patch @@ -0,0 +1,99 @@ +From stable+bounces-247115-greg=kroah.com@vger.kernel.org Thu May 14 07:20:52 2026 +From: Sasha Levin +Date: Thu, 14 May 2026 01:20:14 -0400 +Subject: spi: uniphier: Simplify clock handling with devm_clk_get_enabled() +To: stable@vger.kernel.org +Cc: Pei Xiao , Kunihiko Hayashi , Mark Brown , Sasha Levin +Message-ID: <20260514052015.40231-1-sashal@kernel.org> + +From: Pei Xiao + +[ Upstream commit fdca270f8f87cae2eb5b619234b9dd11a863ce6b ] + +Replace devm_clk_get() followed by clk_prepare_enable() with +devm_clk_get_enabled() for the clock. This removes the need for +explicit clock enable and disable calls, as the managed API automatically +handles clock disabling on device removal or probe failure. + +Remove the now-unnecessary clk_disable_unprepare() calls from the probe +error path and the remove callback. Adjust error labels accordingly. + +Signed-off-by: Pei Xiao +Reviewed-by: Kunihiko Hayashi +Link: https://patch.msgid.link/b2deeefd4ef1a4bce71116aabfcb7e81400f6d37.1775546948.git.xiaopei01@kylinos.cn +Signed-off-by: Mark Brown +Stable-dep-of: 0245435f7772 ("spi: uniphier: fix controller deregistration") +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + drivers/spi/spi-uniphier.c | 18 ++++-------------- + 1 file changed, 4 insertions(+), 14 deletions(-) + +--- a/drivers/spi/spi-uniphier.c ++++ b/drivers/spi/spi-uniphier.c +@@ -666,28 +666,24 @@ static int uniphier_spi_probe(struct pla + } + priv->base_dma_addr = res->start; + +- priv->clk = devm_clk_get(&pdev->dev, NULL); ++ priv->clk = devm_clk_get_enabled(&pdev->dev, NULL); + if (IS_ERR(priv->clk)) { + dev_err(&pdev->dev, "failed to get clock\n"); + ret = PTR_ERR(priv->clk); + goto out_host_put; + } + +- ret = clk_prepare_enable(priv->clk); +- if (ret) +- goto out_host_put; +- + irq = platform_get_irq(pdev, 0); + if (irq < 0) { + ret = irq; +- goto out_disable_clk; ++ goto out_host_put; + } + + ret = devm_request_irq(&pdev->dev, irq, uniphier_spi_handler, + 0, "uniphier-spi", priv); + if (ret) { + dev_err(&pdev->dev, "failed to request IRQ\n"); +- goto out_disable_clk; ++ goto out_host_put; + } + + init_completion(&priv->xfer_done); +@@ -717,7 +713,7 @@ static int uniphier_spi_probe(struct pla + if (IS_ERR_OR_NULL(host->dma_tx)) { + if (PTR_ERR(host->dma_tx) == -EPROBE_DEFER) { + ret = -EPROBE_DEFER; +- goto out_disable_clk; ++ goto out_host_put; + } + host->dma_tx = NULL; + dma_tx_burst = INT_MAX; +@@ -767,9 +763,6 @@ out_release_dma: + host->dma_tx = NULL; + } + +-out_disable_clk: +- clk_disable_unprepare(priv->clk); +- + out_host_put: + spi_controller_put(host); + return ret; +@@ -778,14 +771,11 @@ out_host_put: + static void uniphier_spi_remove(struct platform_device *pdev) + { + struct spi_controller *host = platform_get_drvdata(pdev); +- struct uniphier_spi_priv *priv = spi_controller_get_devdata(host); + + if (host->dma_tx) + dma_release_channel(host->dma_tx); + if (host->dma_rx) + dma_release_channel(host->dma_rx); +- +- clk_disable_unprepare(priv->clk); + } + + static const struct of_device_id uniphier_spi_match[] = { diff --git a/queue-6.12/spi-zynq-qspi-fix-controller-deregistration.patch b/queue-6.12/spi-zynq-qspi-fix-controller-deregistration.patch new file mode 100644 index 0000000000..eaa8ea0604 --- /dev/null +++ b/queue-6.12/spi-zynq-qspi-fix-controller-deregistration.patch @@ -0,0 +1,73 @@ +From stable+bounces-247008-greg=kroah.com@vger.kernel.org Wed May 13 20:28:32 2026 +From: Sasha Levin +Date: Wed, 13 May 2026 14:20:21 -0400 +Subject: spi: zynq-qspi: fix controller deregistration +To: stable@vger.kernel.org +Cc: Johan Hovold , Naga Sureshkumar Relli , Mark Brown , Sasha Levin +Message-ID: <20260513182021.3918405-2-sashal@kernel.org> + +From: Johan Hovold + +[ Upstream commit c9c012706c9fa8ca6d129a9161caf92ab625a3fd ] + +Make sure to deregister the controller before disabling it during driver +unbind. + +Note that clocks were also disabled before the recent commit +1f8fd9490e31 ("spi: zynq-qspi: Simplify clock handling with +devm_clk_get_enabled()"). + +Fixes: 67dca5e580f1 ("spi: spi-mem: Add support for Zynq QSPI controller") +Cc: stable@vger.kernel.org # 5.2: 8eb2fd00f65a +Cc: stable@vger.kernel.org # 5.2 +Cc: Naga Sureshkumar Relli +Signed-off-by: Johan Hovold +Link: https://patch.msgid.link/20260410081757.503099-27-johan@kernel.org +Signed-off-by: Mark Brown +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + drivers/spi/spi-zynq-qspi.c | 15 +++++++++++---- + 1 file changed, 11 insertions(+), 4 deletions(-) + +--- a/drivers/spi/spi-zynq-qspi.c ++++ b/drivers/spi/spi-zynq-qspi.c +@@ -641,7 +641,7 @@ static int zynq_qspi_probe(struct platfo + + xqspi = spi_controller_get_devdata(ctlr); + xqspi->dev = dev; +- platform_set_drvdata(pdev, xqspi); ++ platform_set_drvdata(pdev, ctlr); + xqspi->regs = devm_platform_ioremap_resource(pdev, 0); + if (IS_ERR(xqspi->regs)) { + ret = PTR_ERR(xqspi->regs); +@@ -699,9 +699,9 @@ static int zynq_qspi_probe(struct platfo + /* QSPI controller initializations */ + zynq_qspi_init_hw(xqspi, ctlr->num_chipselect); + +- ret = devm_spi_register_controller(&pdev->dev, ctlr); ++ ret = spi_register_controller(ctlr); + if (ret) { +- dev_err(&pdev->dev, "devm_spi_register_controller failed\n"); ++ dev_err(&pdev->dev, "failed to register controller\n"); + goto remove_ctlr; + } + +@@ -725,9 +725,16 @@ remove_ctlr: + */ + static void zynq_qspi_remove(struct platform_device *pdev) + { +- struct zynq_qspi *xqspi = platform_get_drvdata(pdev); ++ struct spi_controller *ctlr = platform_get_drvdata(pdev); ++ struct zynq_qspi *xqspi = spi_controller_get_devdata(ctlr); ++ ++ spi_controller_get(ctlr); ++ ++ spi_unregister_controller(ctlr); + + zynq_qspi_write(xqspi, ZYNQ_QSPI_ENABLE_OFFSET, 0); ++ ++ spi_controller_put(ctlr); + } + + static const struct of_device_id zynq_qspi_of_match[] = { diff --git a/queue-6.12/spi-zynq-qspi-simplify-clock-handling-with-devm_clk_get_enabled.patch b/queue-6.12/spi-zynq-qspi-simplify-clock-handling-with-devm_clk_get_enabled.patch new file mode 100644 index 0000000000..bdc067824b --- /dev/null +++ b/queue-6.12/spi-zynq-qspi-simplify-clock-handling-with-devm_clk_get_enabled.patch @@ -0,0 +1,142 @@ +From stable+bounces-247007-greg=kroah.com@vger.kernel.org Wed May 13 20:21:02 2026 +From: Sasha Levin +Date: Wed, 13 May 2026 14:20:20 -0400 +Subject: spi: zynq-qspi: Simplify clock handling with devm_clk_get_enabled() +To: stable@vger.kernel.org +Cc: Pei Xiao , Michal Simek , Mark Brown , Sasha Levin +Message-ID: <20260513182021.3918405-1-sashal@kernel.org> + +From: Pei Xiao + +[ Upstream commit 1f8fd9490e3184e9a2394df2e682901a1d57ce71 ] + +Replace devm_clk_get() followed by clk_prepare_enable() with +devm_clk_get_enabled() for both "pclk" and "ref_clk". This removes +the need for explicit clock enable and disable calls, as the managed +API automatically disables the clocks on device removal or probe +failure. + +Remove the now-unnecessary clk_disable_unprepare() calls from the +probe error paths and the remove callback. Simplify error handling +by jumping directly to the remove_ctlr label. + +Signed-off-by: Pei Xiao +Acked-by: Michal Simek +Link: https://patch.msgid.link/24043625f89376da36feca2408f990a85be7ab36.1775555500.git.xiaopei01@kylinos.cn +Signed-off-by: Mark Brown +Stable-dep-of: c9c012706c9f ("spi: zynq-qspi: fix controller deregistration") +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + drivers/spi/spi-zynq-qspi.c | 42 ++++++------------------------------------ + 1 file changed, 6 insertions(+), 36 deletions(-) + +--- a/drivers/spi/spi-zynq-qspi.c ++++ b/drivers/spi/spi-zynq-qspi.c +@@ -379,21 +379,10 @@ static int zynq_qspi_setup_op(struct spi + { + struct spi_controller *ctlr = spi->controller; + struct zynq_qspi *qspi = spi_controller_get_devdata(ctlr); +- int ret; + + if (ctlr->busy) + return -EBUSY; + +- ret = clk_enable(qspi->refclk); +- if (ret) +- return ret; +- +- ret = clk_enable(qspi->pclk); +- if (ret) { +- clk_disable(qspi->refclk); +- return ret; +- } +- + zynq_qspi_write(qspi, ZYNQ_QSPI_ENABLE_OFFSET, + ZYNQ_QSPI_ENABLE_ENABLE_MASK); + +@@ -659,7 +648,7 @@ static int zynq_qspi_probe(struct platfo + goto remove_ctlr; + } + +- xqspi->pclk = devm_clk_get(&pdev->dev, "pclk"); ++ xqspi->pclk = devm_clk_get_enabled(&pdev->dev, "pclk"); + if (IS_ERR(xqspi->pclk)) { + dev_err(&pdev->dev, "pclk clock not found.\n"); + ret = PTR_ERR(xqspi->pclk); +@@ -668,36 +657,24 @@ static int zynq_qspi_probe(struct platfo + + init_completion(&xqspi->data_completion); + +- xqspi->refclk = devm_clk_get(&pdev->dev, "ref_clk"); ++ xqspi->refclk = devm_clk_get_enabled(&pdev->dev, "ref_clk"); + if (IS_ERR(xqspi->refclk)) { + dev_err(&pdev->dev, "ref_clk clock not found.\n"); + ret = PTR_ERR(xqspi->refclk); + goto remove_ctlr; + } + +- ret = clk_prepare_enable(xqspi->pclk); +- if (ret) { +- dev_err(&pdev->dev, "Unable to enable APB clock.\n"); +- goto remove_ctlr; +- } +- +- ret = clk_prepare_enable(xqspi->refclk); +- if (ret) { +- dev_err(&pdev->dev, "Unable to enable device clock.\n"); +- goto clk_dis_pclk; +- } +- + xqspi->irq = platform_get_irq(pdev, 0); + if (xqspi->irq < 0) { + ret = xqspi->irq; +- goto clk_dis_all; ++ goto remove_ctlr; + } + ret = devm_request_irq(&pdev->dev, xqspi->irq, zynq_qspi_irq, + 0, pdev->name, xqspi); + if (ret != 0) { + ret = -ENXIO; + dev_err(&pdev->dev, "request_irq failed\n"); +- goto clk_dis_all; ++ goto remove_ctlr; + } + + ret = of_property_read_u32(np, "num-cs", +@@ -707,7 +684,7 @@ static int zynq_qspi_probe(struct platfo + } else if (num_cs > ZYNQ_QSPI_MAX_NUM_CS) { + ret = -EINVAL; + dev_err(&pdev->dev, "only 2 chip selects are available\n"); +- goto clk_dis_all; ++ goto remove_ctlr; + } else { + ctlr->num_chipselect = num_cs; + } +@@ -725,15 +702,11 @@ static int zynq_qspi_probe(struct platfo + ret = devm_spi_register_controller(&pdev->dev, ctlr); + if (ret) { + dev_err(&pdev->dev, "devm_spi_register_controller failed\n"); +- goto clk_dis_all; ++ goto remove_ctlr; + } + + return ret; + +-clk_dis_all: +- clk_disable_unprepare(xqspi->refclk); +-clk_dis_pclk: +- clk_disable_unprepare(xqspi->pclk); + remove_ctlr: + spi_controller_put(ctlr); + +@@ -755,9 +728,6 @@ static void zynq_qspi_remove(struct plat + struct zynq_qspi *xqspi = platform_get_drvdata(pdev); + + zynq_qspi_write(xqspi, ZYNQ_QSPI_ENABLE_OFFSET, 0); +- +- clk_disable_unprepare(xqspi->refclk); +- clk_disable_unprepare(xqspi->pclk); + } + + static const struct of_device_id zynq_qspi_of_match[] = { diff --git a/queue-6.12/tracefs-fix-default-permissions-not-being-applied-on-initial-mount.patch b/queue-6.12/tracefs-fix-default-permissions-not-being-applied-on-initial-mount.patch new file mode 100644 index 0000000000..d221c8ac19 --- /dev/null +++ b/queue-6.12/tracefs-fix-default-permissions-not-being-applied-on-initial-mount.patch @@ -0,0 +1,56 @@ +From stable+bounces-247285-greg=kroah.com@vger.kernel.org Thu May 14 21:26:47 2026 +From: Sasha Levin +Date: Thu, 14 May 2026 15:26:38 -0400 +Subject: tracefs: Fix default permissions not being applied on initial mount +To: stable@vger.kernel.org +Cc: David Carlier , "Steven Rostedt (Google)" , Sasha Levin +Message-ID: <20260514192638.1262074-1-sashal@kernel.org> + +From: David Carlier + +[ Upstream commit e8368d1f4bedbb0cce4cfe33a1d2664bb0fd4f27 ] + +Commit e4d32142d1de ("tracing: Fix tracefs mount options") moved the +option application from tracefs_fill_super() to tracefs_reconfigure() +called from tracefs_get_tree(). This fixed mount options being ignored +on user-space mounts when the superblock already exists, but introduced +a regression for the initial kernel-internal mount. + +On the first mount (via simple_pin_fs during init), sget_fc() transfers +fc->s_fs_info to sb->s_fs_info and sets fc->s_fs_info to NULL. When +tracefs_get_tree() then calls tracefs_reconfigure(), it sees a NULL +fc->s_fs_info and returns early without applying any options. The root +inode keeps mode 0755 from simple_fill_super() instead of the intended +TRACEFS_DEFAULT_MODE (0700). + +Furthermore, even on subsequent user-space mounts without an explicit +mode= option, tracefs_apply_options(sb, true) gates the mode behind +fsi->opts & BIT(Opt_mode), which is unset for the defaults. So the +mode is never corrected unless the user explicitly passes mode=0700. + +Restore the tracefs_apply_options(sb, false) call in tracefs_fill_super() +to apply default permissions on initial superblock creation, matching +what debugfs does in debugfs_fill_super(). + +Cc: stable@vger.kernel.org +Fixes: e4d32142d1de ("tracing: Fix tracefs mount options") +Link: https://patch.msgid.link/20260404134747.98867-1-devnexen@gmail.com +Signed-off-by: David Carlier +Signed-off-by: Steven Rostedt (Google) +[ kept 6.12's `sb->s_d_op = &tracefs_dentry_operations;` instead of upstream's `set_default_d_op()` ] +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + fs/tracefs/inode.c | 1 + + 1 file changed, 1 insertion(+) + +--- a/fs/tracefs/inode.c ++++ b/fs/tracefs/inode.c +@@ -493,6 +493,7 @@ static int tracefs_fill_super(struct sup + return err; + + sb->s_op = &tracefs_super_operations; ++ tracefs_apply_options(sb, false); + sb->s_d_op = &tracefs_dentry_operations; + + return 0; diff --git a/queue-6.12/usb-dwc3-move-guid-programming-after-phy-initialization.patch b/queue-6.12/usb-dwc3-move-guid-programming-after-phy-initialization.patch new file mode 100644 index 0000000000..537375a81b --- /dev/null +++ b/queue-6.12/usb-dwc3-move-guid-programming-after-phy-initialization.patch @@ -0,0 +1,63 @@ +From sashal@kernel.org Wed May 13 14:49:03 2026 +From: Sasha Levin +Date: Wed, 13 May 2026 08:49:00 -0400 +Subject: usb: dwc3: Move GUID programming after PHY initialization +To: stable@vger.kernel.org +Cc: Selvarasu Ganesan , stable , Pritam Manohar Sutar , Thinh Nguyen , Greg Kroah-Hartman , Sasha Levin +Message-ID: <20260513124900.3713317-1-sashal@kernel.org> + +From: Selvarasu Ganesan + +[ Upstream commit aad35f9c926ec220b0742af1ada45666ae667956 ] + +The Linux Version Code is currently written to the GUID register before +PHY initialization. Certain PHY implementations (such as Synopsys eUSB +PHY performing link_sw_reset) clear the GUID register to its default +value during initialization, causing the kernel version information to +be lost. + +Move the GUID register programming to occur after PHY initialization +completes to ensure the Linux version information persists. + +Fixes: fa0ea13e9f1c ("usb: dwc3: core: write LINUX_VERSION_CODE to our GUID register") +Cc: stable +Reported-by: Pritam Manohar Sutar +Signed-off-by: Selvarasu Ganesan +Acked-by: Thinh Nguyen +Link: https://patch.msgid.link/20260417063314.2359-1-selvarasu.g@samsung.com +Signed-off-by: Greg Kroah-Hartman +[ adapted dwc3_writel(dwc, ...) to dwc3_writel(dwc->regs, ...) ] +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + drivers/usb/dwc3/core.c | 12 ++++++------ + 1 file changed, 6 insertions(+), 6 deletions(-) + +--- a/drivers/usb/dwc3/core.c ++++ b/drivers/usb/dwc3/core.c +@@ -1336,12 +1336,6 @@ static int dwc3_core_init(struct dwc3 *d + + hw_mode = DWC3_GHWPARAMS0_MODE(dwc->hwparams.hwparams0); + +- /* +- * Write Linux Version Code to our GUID register so it's easy to figure +- * out which kernel version a bug was found. +- */ +- dwc3_writel(dwc->regs, DWC3_GUID, LINUX_VERSION_CODE); +- + ret = dwc3_phy_setup(dwc); + if (ret) + return ret; +@@ -1373,6 +1367,12 @@ static int dwc3_core_init(struct dwc3 *d + if (ret) + goto err_exit_phy; + ++ /* ++ * Write Linux Version Code to our GUID register so it's easy to figure ++ * out which kernel version a bug was found. ++ */ ++ dwc3_writel(dwc->regs, DWC3_GUID, LINUX_VERSION_CODE); ++ + dwc3_core_setup_global_control(dwc); + dwc3_core_num_eps(dwc); + diff --git a/queue-6.12/usb-typec-tcpm-reset-internal-port-states-on-soft-reset-ams.patch b/queue-6.12/usb-typec-tcpm-reset-internal-port-states-on-soft-reset-ams.patch new file mode 100644 index 0000000000..5187c0c145 --- /dev/null +++ b/queue-6.12/usb-typec-tcpm-reset-internal-port-states-on-soft-reset-ams.patch @@ -0,0 +1,84 @@ +From 2909f0d4994fb4306bf116df5ccee797791fce2c Mon Sep 17 00:00:00 2001 +From: Amit Sunil Dhamne +Date: Tue, 14 Apr 2026 00:58:32 +0000 +Subject: usb: typec: tcpm: reset internal port states on soft reset AMS + +From: Amit Sunil Dhamne + +commit 2909f0d4994fb4306bf116df5ccee797791fce2c upstream. + +Reset internal port states (such as vdm_sm_running and +explicit_contract) on soft reset AMS as the port needs to negotiate a +new contract. The consequence of leaving the states in as-is cond are as +follows: + * port is in SRC power role and an explicit contract is negotiated + with the port partner (in sink role) + * port partner sends a Soft Reset AMS while VDM State Machine is + running + * port accepts the Soft Reset request and the port advertises src caps + * port partner sends a Request message but since the explicit_contract + and vdm_sm_running are true from previous negotiation, the port ends + up sending Soft Reset instead of Accept msg. + +Stub Log: +[ 203.653942] AMS DISCOVER_IDENTITY start +[ 203.653947] PD TX, header: 0x176f +[ 203.655901] PD TX complete, status: 0 +[ 203.657470] PD RX, header: 0x124f [1] +[ 203.657477] Rx VDM cmd 0xff008081 type 2 cmd 1 len 1 +[ 203.657482] AMS DISCOVER_IDENTITY finished +[ 203.657484] cc:=4 +[ 204.155698] PD RX, header: 0x144f [1] +[ 204.155718] Rx VDM cmd 0xeeee8001 type 0 cmd 1 len 1 +[ 204.155741] PD TX, header: 0x196f +[ 204.157622] PD TX complete, status: 0 +[ 204.160060] PD RX, header: 0x4d [1] +[ 204.160066] state change SRC_READY -> SOFT_RESET [rev2 SOFT_RESET_AMS] +[ 204.160076] PD TX, header: 0x163 +[ 204.162486] PD TX complete, status: 0 +[ 204.162832] AMS SOFT_RESET_AMS finished +[ 204.162840] cc:=4 +[ 204.162891] AMS POWER_NEGOTIATION start +[ 204.162896] state change SOFT_RESET -> AMS_START [rev2 POWER_NEGOTIATION] +[ 204.162908] state change AMS_START -> SRC_SEND_CAPABILITIES [rev2 POWER_NEGOTIATION] +[ 204.162913] PD TX, header: 0x1361 +[ 204.165529] PD TX complete, status: 0 +[ 204.165571] pending state change SRC_SEND_CAPABILITIES -> SRC_SEND_CAPABILITIES_TIMEOUT @ 60 ms [rev2 POWER_NEGOTIATION] +[ 204.166996] PD RX, header: 0x1242 [1] +[ 204.167009] state change SRC_SEND_CAPABILITIES -> SRC_SOFT_RESET_WAIT_SNK_TX [rev2 POWER_NEGOTIATION] +[ 204.167019] AMS POWER_NEGOTIATION finished +[ 204.167020] cc:=4 +[ 204.167083] AMS SOFT_RESET_AMS start +[ 204.167086] state change SRC_SOFT_RESET_WAIT_SNK_TX -> SOFT_RESET_SEND [rev2 SOFT_RESET_AMS] +[ 204.167092] PD TX, header: 0x16d +[ 204.168824] PD TX complete, status: 0 +[ 204.168854] pending state change SOFT_RESET_SEND -> HARD_RESET_SEND @ 60 ms [rev2 SOFT_RESET_AMS] +[ 204.171876] PD RX, header: 0x43 [1] +[ 204.171879] AMS SOFT_RESET_AMS finished + +This causes COMMON.PROC.PD.11.2 check failure for +TEST.PD.VDM.SRC.2_Rev2Src test on the PD compliance tester. + +Signed-off-by: Amit Sunil Dhamne +Fixes: 8d3a0578ad1a ("usb: typec: tcpm: Respond Wait if VDM state machine is running") +Fixes: f0690a25a140 ("staging: typec: USB Type-C Port Manager (tcpm)") +Cc: stable +Reviewed-by: Badhri Jagan Sridharan +Acked-by: Heikki Krogerus +Link: https://patch.msgid.link/20260414-fix-soft-reset-v1-1-01d7cb9764e2@google.com +Signed-off-by: Greg Kroah-Hartman +--- + drivers/usb/typec/tcpm/tcpm.c | 2 ++ + 1 file changed, 2 insertions(+) + +--- a/drivers/usb/typec/tcpm/tcpm.c ++++ b/drivers/usb/typec/tcpm/tcpm.c +@@ -5407,6 +5407,8 @@ static void run_state_machine(struct tcp + usb_power_delivery_unregister_capabilities(port->partner_source_caps); + port->partner_source_caps = NULL; + tcpm_pd_send_control(port, PD_CTRL_ACCEPT, TCPC_TX_SOP); ++ port->vdm_sm_running = false; ++ port->explicit_contract = false; + tcpm_ams_finish(port); + if (port->pwr_role == TYPEC_SOURCE) { + port->upcoming_state = SRC_SEND_CAPABILITIES;