--- /dev/null
+From stable+bounces-246879-greg=kroah.com@vger.kernel.org Wed May 13 17:15:06 2026
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 13 May 2026 10:10:25 -0400
+Subject: ALSA: core: Serialize deferred fasync state checks
+To: stable@vger.kernel.org
+Cc: "Cássio Gabriel" <cassiogabrielcontato@gmail.com>, "Takashi Iwai" <tiwai@suse.de>, "Sasha Levin" <sashal@kernel.org>
+Message-ID: <20260513141025.3748103-3-sashal@kernel.org>
+
+From: Cássio Gabriel <cassiogabrielcontato@gmail.com>
+
+[ 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 <cassiogabrielcontato@gmail.com>
+Link: https://patch.msgid.link/20260506-alsa-core-fasync-on-lock-v1-1-ea48c77d6ca4@gmail.com
+Signed-off-by: Takashi Iwai <tiwai@suse.de>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ sound/core/misc.c | 8 ++++++--
+ 1 file changed, 6 insertions(+), 2 deletions(-)
+
+--- a/sound/core/misc.c
++++ b/sound/core/misc.c
+@@ -219,9 +219,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);
+@@ -234,8 +236,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);
--- /dev/null
+From stable+bounces-246871-greg=kroah.com@vger.kernel.org Wed May 13 16:09:46 2026
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 13 May 2026 09:53:59 -0400
+Subject: ALSA: hda: cs35l56: Propagate ASP TX source control errors
+To: stable@vger.kernel.org
+Cc: "Cássio Gabriel" <cassiogabrielcontato@gmail.com>, "Richard Fitzgerald" <rf@opensource.cirrus.com>, "Takashi Iwai" <tiwai@suse.de>, "Sasha Levin" <sashal@kernel.org>
+Message-ID: <20260513135359.3741836-1-sashal@kernel.org>
+
+From: Cássio Gabriel <cassiogabrielcontato@gmail.com>
+
+[ 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 <cassiogabrielcontato@gmail.com>
+Reviewed-by: Richard Fitzgerald <rf@opensource.cirrus.com>
+Signed-off-by: Takashi Iwai <tiwai@suse.de>
+Link: https://patch.msgid.link/20260423-alsa-cs35l56-asp-tx-source-errors-v1-1-17ea7c62ec31@gmail.com
+[ adjusted path to sound/pci/hda/ and dropped cs35l56_hda_wait_dsp_ready() context ]
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ 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
+@@ -176,9 +176,13 @@ static int cs35l56_hda_mixer_get(struct
+ {
+ struct cs35l56_hda *cs35l56 = snd_kcontrol_chip(kcontrol);
+ unsigned int reg_val;
+- int i;
++ int i, ret;
++
++ ret = regmap_read(cs35l56->base.regmap, kcontrol->private_value,
++ ®_val);
++ if (ret)
++ return ret;
+
+- regmap_read(cs35l56->base.regmap, kcontrol->private_value, ®_val);
+ reg_val &= CS35L56_ASP_TXn_SRC_MASK;
+
+ for (i = 0; i < CS35L56_NUM_INPUT_SRC; ++i) {
+@@ -197,13 +201,18 @@ 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;
+
+- 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;
+ }
--- /dev/null
+From stable+bounces-246877-greg=kroah.com@vger.kernel.org Wed May 13 16:24:43 2026
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 13 May 2026 10:10:23 -0400
+Subject: ALSA: misc: Use guard() for spin locks
+To: stable@vger.kernel.org
+Cc: Takashi Iwai <tiwai@suse.de>, Sasha Levin <sashal@kernel.org>
+Message-ID: <20260513141025.3748103-1-sashal@kernel.org>
+
+From: Takashi Iwai <tiwai@suse.de>
+
+[ Upstream commit b8e1684163ae52db90f428965bd9aaff7205c02e ]
+
+Clean up the code using guard() for spin locks.
+
+Merely code refactoring, and no behavior change.
+
+Signed-off-by: Takashi Iwai <tiwai@suse.de>
+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 <sashal@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ sound/core/misc.c | 25 ++++++++++---------------
+ 1 file changed, 10 insertions(+), 15 deletions(-)
+
+--- a/sound/core/misc.c
++++ b/sound/core/misc.c
+@@ -202,35 +202,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);
+
--- /dev/null
+From stable+bounces-246886-greg=kroah.com@vger.kernel.org Wed May 13 16:39:59 2026
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 13 May 2026 10:34:30 -0400
+Subject: ALSA: seq: Fix UMP group 16 filtering
+To: stable@vger.kernel.org
+Cc: "Cássio Gabriel" <cassiogabrielcontato@gmail.com>, "Takashi Iwai" <tiwai@suse.de>, "Sasha Levin" <sashal@kernel.org>
+Message-ID: <20260513143430.3755036-2-sashal@kernel.org>
+
+From: Cássio Gabriel <cassiogabrielcontato@gmail.com>
+
+[ 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 <cassiogabrielcontato@gmail.com>
+Link: https://patch.msgid.link/20260506-alsa-seq-ump-group16-filter-v1-1-b75160bf6993@gmail.com
+Signed-off-by: Takashi Iwai <tiwai@suse.de>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ 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
+@@ -1333,7 +1333,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
+@@ -370,7 +370,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));
--- /dev/null
+From stable+bounces-246885-greg=kroah.com@vger.kernel.org Wed May 13 16:41:06 2026
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 13 May 2026 10:34:29 -0400
+Subject: ALSA: seq: Notify client and port info changes
+To: stable@vger.kernel.org
+Cc: Takashi Iwai <tiwai@suse.de>, Mark Lentczner <mark@glyphic.com>, Sasha Levin <sashal@kernel.org>
+Message-ID: <20260513143430.3755036-1-sashal@kernel.org>
+
+From: Takashi Iwai <tiwai@suse.de>
+
+[ 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 <mark@glyphic.com>
+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 <tiwai@suse.de>
+Stable-dep-of: 92429ca999db ("ALSA: seq: Fix UMP group 16 filtering")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ 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
+@@ -1334,6 +1334,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;
+ }
+
+@@ -1457,6 +1461,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
+@@ -273,8 +273,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);
+ }
+ }
+
--- /dev/null
+From stable+bounces-246967-greg=kroah.com@vger.kernel.org Wed May 13 19:49:43 2026
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 13 May 2026 13:31:46 -0400
+Subject: Bluetooth: hci_conn: fix potential UAF in create_big_sync
+To: stable@vger.kernel.org
+Cc: David Carlier <devnexen@gmail.com>, Luiz Augusto von Dentz <luiz.von.dentz@intel.com>, Sasha Levin <sashal@kernel.org>
+Message-ID: <20260513173146.3885958-1-sashal@kernel.org>
+
+From: David Carlier <devnexen@gmail.com>
+
+[ 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 <luiz.von.dentz@intel.com>
+Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
+Signed-off-by: David Carlier <devnexen@gmail.com>
+Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
+[ 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 <sashal@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ 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
+@@ -2014,6 +2014,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);
+ }
+
--- /dev/null
+From stable+bounces-245016-greg=kroah.com@vger.kernel.org Sun May 10 15:15:17 2026
+From: Sasha Levin <sashal@kernel.org>
+Date: Sun, 10 May 2026 09:15:08 -0400
+Subject: crypto: caam - guard HMAC key hex dumps in hash_digest_key
+To: stable@vger.kernel.org
+Cc: Thorsten Blum <thorsten.blum@linux.dev>, Herbert Xu <herbert@gondor.apana.org.au>, Sasha Levin <sashal@kernel.org>
+Message-ID: <20260510131508.4113857-2-sashal@kernel.org>
+
+From: Thorsten Blum <thorsten.blum@linux.dev>
+
+[ Upstream commit 177730a273b18e195263ed953853273e901b5064 ]
+
+Use print_hex_dump_devel() for dumping sensitive HMAC key bytes in
+hash_digest_key() to avoid leaking secrets at runtime when
+CONFIG_DYNAMIC_DEBUG is enabled.
+
+Fixes: 045e36780f11 ("crypto: caam - ahash hmac support")
+Fixes: 3f16f6c9d632 ("crypto: caam/qi2 - add support for ahash algorithms")
+Cc: stable@vger.kernel.org
+Signed-off-by: Thorsten Blum <thorsten.blum@linux.dev>
+Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/crypto/caam/caamalg_qi2.c | 4 ++--
+ drivers/crypto/caam/caamhash.c | 4 ++--
+ 2 files changed, 4 insertions(+), 4 deletions(-)
+
+--- a/drivers/crypto/caam/caamalg_qi2.c
++++ b/drivers/crypto/caam/caamalg_qi2.c
+@@ -3268,7 +3268,7 @@ static int hash_digest_key(struct caam_h
+ dpaa2_fl_set_addr(out_fle, key_dma);
+ dpaa2_fl_set_len(out_fle, digestsize);
+
+- print_hex_dump_debug("key_in@" __stringify(__LINE__)": ",
++ print_hex_dump_devel("key_in@" __stringify(__LINE__)": ",
+ DUMP_PREFIX_ADDRESS, 16, 4, key, *keylen, 1);
+ print_hex_dump_debug("shdesc@" __stringify(__LINE__)": ",
+ DUMP_PREFIX_ADDRESS, 16, 4, desc, desc_bytes(desc),
+@@ -3288,7 +3288,7 @@ static int hash_digest_key(struct caam_h
+ /* in progress */
+ wait_for_completion(&result.completion);
+ ret = result.err;
+- print_hex_dump_debug("digested key@" __stringify(__LINE__)": ",
++ print_hex_dump_devel("digested key@" __stringify(__LINE__)": ",
+ DUMP_PREFIX_ADDRESS, 16, 4, key,
+ digestsize, 1);
+ }
+--- a/drivers/crypto/caam/caamhash.c
++++ b/drivers/crypto/caam/caamhash.c
+@@ -393,7 +393,7 @@ static int hash_digest_key(struct caam_h
+ append_seq_store(desc, digestsize, LDST_CLASS_2_CCB |
+ LDST_SRCDST_BYTE_CONTEXT);
+
+- print_hex_dump_debug("key_in@"__stringify(__LINE__)": ",
++ print_hex_dump_devel("key_in@"__stringify(__LINE__)": ",
+ DUMP_PREFIX_ADDRESS, 16, 4, key, *keylen, 1);
+ print_hex_dump_debug("jobdesc@"__stringify(__LINE__)": ",
+ DUMP_PREFIX_ADDRESS, 16, 4, desc, desc_bytes(desc),
+@@ -408,7 +408,7 @@ static int hash_digest_key(struct caam_h
+ wait_for_completion(&result.completion);
+ ret = result.err;
+
+- print_hex_dump_debug("digested key@"__stringify(__LINE__)": ",
++ print_hex_dump_devel("digested key@"__stringify(__LINE__)": ",
+ DUMP_PREFIX_ADDRESS, 16, 4, key,
+ digestsize, 1);
+ }
--- /dev/null
+From stable+bounces-244898-greg=kroah.com@vger.kernel.org Sat May 9 05:31:56 2026
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 8 May 2026 23:31:48 -0400
+Subject: crypto: nx - Avoid -Wflex-array-member-not-at-end warning
+To: stable@vger.kernel.org
+Cc: "Gustavo A. R. Silva" <gustavoars@kernel.org>, Herbert Xu <herbert@gondor.apana.org.au>, Sasha Levin <sashal@kernel.org>
+Message-ID: <20260509033150.3082044-1-sashal@kernel.org>
+
+From: "Gustavo A. R. Silva" <gustavoars@kernel.org>
+
+[ Upstream commit 1e6b251ce1759392666856908113dd5d7cea044d ]
+
+-Wflex-array-member-not-at-end is coming in GCC-14, and we are getting
+ready to enable it globally. So, we are deprecating flexible-array
+members in the middle of another structure.
+
+There is currently an object (`header`) in `struct nx842_crypto_ctx`
+that contains a flexible structure (`struct nx842_crypto_header`):
+
+struct nx842_crypto_ctx {
+ ...
+ struct nx842_crypto_header header;
+ struct nx842_crypto_header_group group[NX842_CRYPTO_GROUP_MAX];
+ ...
+};
+
+So, in order to avoid ending up with a flexible-array member in the
+middle of another struct, we use the `struct_group_tagged()` helper to
+separate the flexible array from the rest of the members in the flexible
+structure:
+
+struct nx842_crypto_header {
+ struct_group_tagged(nx842_crypto_header_hdr, hdr,
+
+ ... the rest of the members
+
+ );
+ struct nx842_crypto_header_group group[];
+} __packed;
+
+With the change described above, we can now declare an object of the
+type of the tagged struct, without embedding the flexible array in the
+middle of another struct:
+
+struct nx842_crypto_ctx {
+ ...
+ struct nx842_crypto_header_hdr header;
+ struct nx842_crypto_header_group group[NX842_CRYPTO_GROUP_MAX];
+ ...
+ } __packed;
+
+We also use `container_of()` whenever we need to retrieve a pointer to
+the flexible structure, through which we can access the flexible
+array if needed.
+
+So, with these changes, fix the following warning:
+
+In file included from drivers/crypto/nx/nx-842.c:55:
+drivers/crypto/nx/nx-842.h:174:36: warning: structure containing a flexible array member is not at the end of another structure [-Wflex-array-member-not-at-end]
+ 174 | struct nx842_crypto_header header;
+ | ^~~~~~
+
+Signed-off-by: Gustavo A. R. Silva <gustavoars@kernel.org>
+Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
+Stable-dep-of: adb3faf2db1a ("crypto: nx - fix bounce buffer leaks in nx842_crypto_{alloc,free}_ctx")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/crypto/nx/nx-842.c | 6 ++++--
+ drivers/crypto/nx/nx-842.h | 10 ++++++----
+ 2 files changed, 10 insertions(+), 6 deletions(-)
+
+--- a/drivers/crypto/nx/nx-842.c
++++ b/drivers/crypto/nx/nx-842.c
+@@ -251,7 +251,9 @@ int nx842_crypto_compress(struct crypto_
+ u8 *dst, unsigned int *dlen)
+ {
+ struct nx842_crypto_ctx *ctx = crypto_tfm_ctx(tfm);
+- struct nx842_crypto_header *hdr = &ctx->header;
++ struct nx842_crypto_header *hdr =
++ container_of(&ctx->header,
++ struct nx842_crypto_header, hdr);
+ struct nx842_crypto_param p;
+ struct nx842_constraints c = *ctx->driver->constraints;
+ unsigned int groups, hdrsize, h;
+@@ -490,7 +492,7 @@ int nx842_crypto_decompress(struct crypt
+ }
+
+ memcpy(&ctx->header, src, hdr_len);
+- hdr = &ctx->header;
++ hdr = container_of(&ctx->header, struct nx842_crypto_header, hdr);
+
+ for (n = 0; n < hdr->groups; n++) {
+ /* ignore applies to last group */
+--- a/drivers/crypto/nx/nx-842.h
++++ b/drivers/crypto/nx/nx-842.h
+@@ -157,9 +157,11 @@ struct nx842_crypto_header_group {
+ } __packed;
+
+ struct nx842_crypto_header {
+- __be16 magic; /* NX842_CRYPTO_MAGIC */
+- __be16 ignore; /* decompressed end bytes to ignore */
+- u8 groups; /* total groups in this header */
++ struct_group_tagged(nx842_crypto_header_hdr, hdr,
++ __be16 magic; /* NX842_CRYPTO_MAGIC */
++ __be16 ignore; /* decompressed end bytes to ignore */
++ u8 groups; /* total groups in this header */
++ );
+ struct nx842_crypto_header_group group[];
+ } __packed;
+
+@@ -171,7 +173,7 @@ struct nx842_crypto_ctx {
+ u8 *wmem;
+ u8 *sbounce, *dbounce;
+
+- struct nx842_crypto_header header;
++ struct nx842_crypto_header_hdr header;
+ struct nx842_crypto_header_group group[NX842_CRYPTO_GROUP_MAX];
+
+ struct nx842_driver *driver;
--- /dev/null
+From stable+bounces-244900-greg=kroah.com@vger.kernel.org Sat May 9 05:31:58 2026
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 8 May 2026 23:31:50 -0400
+Subject: crypto: nx - fix bounce buffer leaks in nx842_crypto_{alloc,free}_ctx
+To: stable@vger.kernel.org
+Cc: Thorsten Blum <thorsten.blum@linux.dev>, Herbert Xu <herbert@gondor.apana.org.au>, Sasha Levin <sashal@kernel.org>
+Message-ID: <20260509033150.3082044-3-sashal@kernel.org>
+
+From: Thorsten Blum <thorsten.blum@linux.dev>
+
+[ Upstream commit adb3faf2db1a66d0f015b44ac909a32dfc7f2f9c ]
+
+The bounce buffers are allocated with __get_free_pages() using
+BOUNCE_BUFFER_ORDER (order 2 = 4 pages), but both the allocation error
+path and nx842_crypto_free_ctx() release the buffers with free_page().
+Use free_pages() with the matching order instead.
+
+Fixes: ed70b479c2c0 ("crypto: nx - add hardware 842 crypto comp alg")
+Cc: stable@vger.kernel.org
+Signed-off-by: Thorsten Blum <thorsten.blum@linux.dev>
+Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/crypto/nx/nx-842.c | 8 ++++----
+ 1 file changed, 4 insertions(+), 4 deletions(-)
+
+--- a/drivers/crypto/nx/nx-842.c
++++ b/drivers/crypto/nx/nx-842.c
+@@ -116,8 +116,8 @@ void *nx842_crypto_alloc_ctx(struct nx84
+ ctx->dbounce = (u8 *)__get_free_pages(GFP_KERNEL, BOUNCE_BUFFER_ORDER);
+ if (!ctx->wmem || !ctx->sbounce || !ctx->dbounce) {
+ kfree(ctx->wmem);
+- free_page((unsigned long)ctx->sbounce);
+- free_page((unsigned long)ctx->dbounce);
++ free_pages((unsigned long)ctx->sbounce, BOUNCE_BUFFER_ORDER);
++ free_pages((unsigned long)ctx->dbounce, BOUNCE_BUFFER_ORDER);
+ kfree(ctx);
+ return ERR_PTR(-ENOMEM);
+ }
+@@ -131,8 +131,8 @@ void nx842_crypto_free_ctx(void *p)
+ struct nx842_crypto_ctx *ctx = p;
+
+ kfree(ctx->wmem);
+- free_page((unsigned long)ctx->sbounce);
+- free_page((unsigned long)ctx->dbounce);
++ free_pages((unsigned long)ctx->sbounce, BOUNCE_BUFFER_ORDER);
++ free_pages((unsigned long)ctx->dbounce, BOUNCE_BUFFER_ORDER);
+ }
+ EXPORT_SYMBOL_GPL(nx842_crypto_free_ctx);
+
--- /dev/null
+From stable+bounces-244899-greg=kroah.com@vger.kernel.org Sat May 9 05:31:59 2026
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 8 May 2026 23:31:49 -0400
+Subject: crypto: nx - Migrate to scomp API
+To: stable@vger.kernel.org
+Cc: Ard Biesheuvel <ardb@kernel.org>, Herbert Xu <herbert@gondor.apana.org.au>, Sasha Levin <sashal@kernel.org>
+Message-ID: <20260509033150.3082044-2-sashal@kernel.org>
+
+From: Ard Biesheuvel <ardb@kernel.org>
+
+[ Upstream commit 980b5705f4e73f567e405cd18337cc32fd51cf79 ]
+
+The only remaining user of 842 compression has been migrated to the
+acomp compression API, and so the NX hardware driver has to follow suit,
+given that no users of the obsolete 'comp' API remain, and it is going
+to be removed.
+
+So migrate the NX driver code to scomp. These will be wrapped and
+exposed as acomp implementation via the crypto subsystem's
+acomp-to-scomp adaptation layer.
+
+Signed-off-by: Ard Biesheuvel <ardb@kernel.org>
+Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
+Stable-dep-of: adb3faf2db1a ("crypto: nx - fix bounce buffer leaks in nx842_crypto_{alloc,free}_ctx")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/crypto/nx/nx-842.c | 33 +++++++++++++++++++--------------
+ drivers/crypto/nx/nx-842.h | 15 ++++++++-------
+ drivers/crypto/nx/nx-common-powernv.c | 31 +++++++++++++++----------------
+ drivers/crypto/nx/nx-common-pseries.c | 33 ++++++++++++++++-----------------
+ 4 files changed, 58 insertions(+), 54 deletions(-)
+
+--- a/drivers/crypto/nx/nx-842.c
++++ b/drivers/crypto/nx/nx-842.c
+@@ -101,9 +101,13 @@ static int update_param(struct nx842_cry
+ return 0;
+ }
+
+-int nx842_crypto_init(struct crypto_tfm *tfm, struct nx842_driver *driver)
++void *nx842_crypto_alloc_ctx(struct nx842_driver *driver)
+ {
+- struct nx842_crypto_ctx *ctx = crypto_tfm_ctx(tfm);
++ struct nx842_crypto_ctx *ctx;
++
++ ctx = kzalloc(sizeof(*ctx), GFP_KERNEL);
++ if (!ctx)
++ return ERR_PTR(-ENOMEM);
+
+ spin_lock_init(&ctx->lock);
+ ctx->driver = driver;
+@@ -114,22 +118,23 @@ int nx842_crypto_init(struct crypto_tfm
+ kfree(ctx->wmem);
+ free_page((unsigned long)ctx->sbounce);
+ free_page((unsigned long)ctx->dbounce);
+- return -ENOMEM;
++ kfree(ctx);
++ return ERR_PTR(-ENOMEM);
+ }
+
+- return 0;
++ return ctx;
+ }
+-EXPORT_SYMBOL_GPL(nx842_crypto_init);
++EXPORT_SYMBOL_GPL(nx842_crypto_alloc_ctx);
+
+-void nx842_crypto_exit(struct crypto_tfm *tfm)
++void nx842_crypto_free_ctx(void *p)
+ {
+- struct nx842_crypto_ctx *ctx = crypto_tfm_ctx(tfm);
++ struct nx842_crypto_ctx *ctx = p;
+
+ kfree(ctx->wmem);
+ free_page((unsigned long)ctx->sbounce);
+ free_page((unsigned long)ctx->dbounce);
+ }
+-EXPORT_SYMBOL_GPL(nx842_crypto_exit);
++EXPORT_SYMBOL_GPL(nx842_crypto_free_ctx);
+
+ static void check_constraints(struct nx842_constraints *c)
+ {
+@@ -246,11 +251,11 @@ nospc:
+ return update_param(p, slen, dskip + dlen);
+ }
+
+-int nx842_crypto_compress(struct crypto_tfm *tfm,
++int nx842_crypto_compress(struct crypto_scomp *tfm,
+ const u8 *src, unsigned int slen,
+- u8 *dst, unsigned int *dlen)
++ u8 *dst, unsigned int *dlen, void *pctx)
+ {
+- struct nx842_crypto_ctx *ctx = crypto_tfm_ctx(tfm);
++ struct nx842_crypto_ctx *ctx = pctx;
+ struct nx842_crypto_header *hdr =
+ container_of(&ctx->header,
+ struct nx842_crypto_header, hdr);
+@@ -431,11 +436,11 @@ usesw:
+ return update_param(p, slen + padding, dlen);
+ }
+
+-int nx842_crypto_decompress(struct crypto_tfm *tfm,
++int nx842_crypto_decompress(struct crypto_scomp *tfm,
+ const u8 *src, unsigned int slen,
+- u8 *dst, unsigned int *dlen)
++ u8 *dst, unsigned int *dlen, void *pctx)
+ {
+- struct nx842_crypto_ctx *ctx = crypto_tfm_ctx(tfm);
++ struct nx842_crypto_ctx *ctx = pctx;
+ struct nx842_crypto_header *hdr;
+ struct nx842_crypto_param p;
+ struct nx842_constraints c = *ctx->driver->constraints;
+--- a/drivers/crypto/nx/nx-842.h
++++ b/drivers/crypto/nx/nx-842.h
+@@ -3,7 +3,6 @@
+ #ifndef __NX_842_H__
+ #define __NX_842_H__
+
+-#include <crypto/algapi.h>
+ #include <linux/kernel.h>
+ #include <linux/init.h>
+ #include <linux/module.h>
+@@ -101,6 +100,8 @@
+ #define LEN_ON_SIZE(pa, size) ((size) - ((pa) & ((size) - 1)))
+ #define LEN_ON_PAGE(pa) LEN_ON_SIZE(pa, PAGE_SIZE)
+
++struct crypto_scomp;
++
+ static inline unsigned long nx842_get_pa(void *addr)
+ {
+ if (!is_vmalloc_addr(addr))
+@@ -179,13 +180,13 @@ struct nx842_crypto_ctx {
+ struct nx842_driver *driver;
+ };
+
+-int nx842_crypto_init(struct crypto_tfm *tfm, struct nx842_driver *driver);
+-void nx842_crypto_exit(struct crypto_tfm *tfm);
+-int nx842_crypto_compress(struct crypto_tfm *tfm,
++void *nx842_crypto_alloc_ctx(struct nx842_driver *driver);
++void nx842_crypto_free_ctx(void *ctx);
++int nx842_crypto_compress(struct crypto_scomp *tfm,
+ const u8 *src, unsigned int slen,
+- u8 *dst, unsigned int *dlen);
+-int nx842_crypto_decompress(struct crypto_tfm *tfm,
++ u8 *dst, unsigned int *dlen, void *ctx);
++int nx842_crypto_decompress(struct crypto_scomp *tfm,
+ const u8 *src, unsigned int slen,
+- u8 *dst, unsigned int *dlen);
++ u8 *dst, unsigned int *dlen, void *ctx);
+
+ #endif /* __NX_842_H__ */
+--- a/drivers/crypto/nx/nx-common-powernv.c
++++ b/drivers/crypto/nx/nx-common-powernv.c
+@@ -9,6 +9,7 @@
+
+ #include "nx-842.h"
+
++#include <crypto/internal/scompress.h>
+ #include <linux/timer.h>
+
+ #include <asm/prom.h>
+@@ -1031,23 +1032,21 @@ static struct nx842_driver nx842_powernv
+ .decompress = nx842_powernv_decompress,
+ };
+
+-static int nx842_powernv_crypto_init(struct crypto_tfm *tfm)
++static void *nx842_powernv_crypto_alloc_ctx(void)
+ {
+- return nx842_crypto_init(tfm, &nx842_powernv_driver);
++ return nx842_crypto_alloc_ctx(&nx842_powernv_driver);
+ }
+
+-static struct crypto_alg nx842_powernv_alg = {
+- .cra_name = "842",
+- .cra_driver_name = "842-nx",
+- .cra_priority = 300,
+- .cra_flags = CRYPTO_ALG_TYPE_COMPRESS,
+- .cra_ctxsize = sizeof(struct nx842_crypto_ctx),
+- .cra_module = THIS_MODULE,
+- .cra_init = nx842_powernv_crypto_init,
+- .cra_exit = nx842_crypto_exit,
+- .cra_u = { .compress = {
+- .coa_compress = nx842_crypto_compress,
+- .coa_decompress = nx842_crypto_decompress } }
++static struct scomp_alg nx842_powernv_alg = {
++ .base.cra_name = "842",
++ .base.cra_driver_name = "842-nx",
++ .base.cra_priority = 300,
++ .base.cra_module = THIS_MODULE,
++
++ .alloc_ctx = nx842_powernv_crypto_alloc_ctx,
++ .free_ctx = nx842_crypto_free_ctx,
++ .compress = nx842_crypto_compress,
++ .decompress = nx842_crypto_decompress,
+ };
+
+ static __init int nx_compress_powernv_init(void)
+@@ -1107,7 +1106,7 @@ static __init int nx_compress_powernv_in
+ nx842_powernv_exec = nx842_exec_vas;
+ }
+
+- ret = crypto_register_alg(&nx842_powernv_alg);
++ ret = crypto_register_scomp(&nx842_powernv_alg);
+ if (ret) {
+ nx_delete_coprocs();
+ return ret;
+@@ -1128,7 +1127,7 @@ static void __exit nx_compress_powernv_e
+ if (!nx842_ct)
+ vas_unregister_api_powernv();
+
+- crypto_unregister_alg(&nx842_powernv_alg);
++ crypto_unregister_scomp(&nx842_powernv_alg);
+
+ nx_delete_coprocs();
+ }
+--- a/drivers/crypto/nx/nx-common-pseries.c
++++ b/drivers/crypto/nx/nx-common-pseries.c
+@@ -11,6 +11,7 @@
+ #include <asm/vio.h>
+ #include <asm/hvcall.h>
+ #include <asm/vas.h>
++#include <crypto/internal/scompress.h>
+
+ #include "nx-842.h"
+ #include "nx_csbcpb.h" /* struct nx_csbcpb */
+@@ -1008,23 +1009,21 @@ static struct nx842_driver nx842_pseries
+ .decompress = nx842_pseries_decompress,
+ };
+
+-static int nx842_pseries_crypto_init(struct crypto_tfm *tfm)
++static void *nx842_pseries_crypto_alloc_ctx(void)
+ {
+- return nx842_crypto_init(tfm, &nx842_pseries_driver);
++ return nx842_crypto_alloc_ctx(&nx842_pseries_driver);
+ }
+
+-static struct crypto_alg nx842_pseries_alg = {
+- .cra_name = "842",
+- .cra_driver_name = "842-nx",
+- .cra_priority = 300,
+- .cra_flags = CRYPTO_ALG_TYPE_COMPRESS,
+- .cra_ctxsize = sizeof(struct nx842_crypto_ctx),
+- .cra_module = THIS_MODULE,
+- .cra_init = nx842_pseries_crypto_init,
+- .cra_exit = nx842_crypto_exit,
+- .cra_u = { .compress = {
+- .coa_compress = nx842_crypto_compress,
+- .coa_decompress = nx842_crypto_decompress } }
++static struct scomp_alg nx842_pseries_alg = {
++ .base.cra_name = "842",
++ .base.cra_driver_name = "842-nx",
++ .base.cra_priority = 300,
++ .base.cra_module = THIS_MODULE,
++
++ .alloc_ctx = nx842_pseries_crypto_alloc_ctx,
++ .free_ctx = nx842_crypto_free_ctx,
++ .compress = nx842_crypto_compress,
++ .decompress = nx842_crypto_decompress,
+ };
+
+ static int nx842_probe(struct vio_dev *viodev,
+@@ -1072,7 +1071,7 @@ static int nx842_probe(struct vio_dev *v
+ if (ret)
+ goto error;
+
+- ret = crypto_register_alg(&nx842_pseries_alg);
++ ret = crypto_register_scomp(&nx842_pseries_alg);
+ if (ret) {
+ dev_err(&viodev->dev, "could not register comp alg: %d\n", ret);
+ goto error;
+@@ -1120,7 +1119,7 @@ static void nx842_remove(struct vio_dev
+ if (caps_feat)
+ sysfs_remove_group(&viodev->dev.kobj, &nxcop_caps_attr_group);
+
+- crypto_unregister_alg(&nx842_pseries_alg);
++ crypto_unregister_scomp(&nx842_pseries_alg);
+
+ spin_lock_irqsave(&devdata_mutex, flags);
+ old_devdata = rcu_dereference_check(devdata,
+@@ -1252,7 +1251,7 @@ static void __exit nx842_pseries_exit(vo
+
+ vas_unregister_api_pseries();
+
+- crypto_unregister_alg(&nx842_pseries_alg);
++ crypto_unregister_scomp(&nx842_pseries_alg);
+
+ spin_lock_irqsave(&devdata_mutex, flags);
+ old_devdata = rcu_dereference_check(devdata,
--- /dev/null
+From stable+bounces-244910-greg=kroah.com@vger.kernel.org Sat May 9 05:54:40 2026
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 8 May 2026 23:54:21 -0400
+Subject: erofs: fix unsigned underflow in z_erofs_lz4_handle_overlap()
+To: stable@vger.kernel.org
+Cc: Junrui Luo <moonafterrain@outlook.com>, Yuhao Jiang <danisjiang@gmail.com>, Gao Xiang <hsiangkao@linux.alibaba.com>, Sasha Levin <sashal@kernel.org>
+Message-ID: <20260509035421.3122562-1-sashal@kernel.org>
+
+From: Junrui Luo <moonafterrain@outlook.com>
+
+[ Upstream commit 21e161de2dc660b1bb70ef5b156ab8e6e1cca3ab ]
+
+Some crafted images can have illegal (!partial_decoding &&
+m_llen < m_plen) extents, and the LZ4 inplace decompression path
+can be wrongly hit, but it cannot handle (outpages < inpages)
+properly: "outpages - inpages" wraps to a large value and
+the subsequent rq->out[] access reads past the decompressed_pages
+array.
+
+However, such crafted cases can correctly result in a corruption
+report in the normal LZ4 non-inplace path.
+
+Let's add an additional check to fix this for backporting.
+
+Reproducible image (base64-encoded gzipped blob):
+
+H4sIAJGR12kCA+3SPUoDQRgG4MkmkkZk8QRbRFIIi9hbpEjrHQI5ghfwCN5BLCzTGtLbBI+g
+dilSJo1CnIm7GEXFxhT6PDDwfrs73/ywIQD/1ePD4r7Ou6ETsrq4mu7XcWfj++Pb58nJU/9i
+PNtbjhan04/9GtX4qVYc814WDqt6FaX5s+ZwXXeq52lndT6IuVvlblytLMvh4Gzwaf90nsvz
+2DF/21+20T/ldgp5s1jXRaN4t/8izsy/OUB6e/Qa79r+JwAAAAAAAL52vQVuGQAAAP6+my1w
+ywAAAAAAAADwu14ATsEYtgBQAAA=
+
+$ mount -t erofs -o cache_strategy=disabled foo.erofs /mnt
+$ dd if=/mnt/data of=/dev/null bs=4096 count=1
+
+Fixes: 598162d05080 ("erofs: support decompress big pcluster for lz4 backend")
+Reported-by: Yuhao Jiang <danisjiang@gmail.com>
+Cc: stable@vger.kernel.org
+Signed-off-by: Junrui Luo <moonafterrain@outlook.com>
+Reviewed-by: Gao Xiang <hsiangkao@linux.alibaba.com>
+Signed-off-by: Gao Xiang <hsiangkao@linux.alibaba.com>
+[ inverted condition to early-out `goto docopy` form and used `ctx->inpages`/`ctx->outpages` instead of `rq->` ]
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ fs/erofs/decompressor.c | 1 +
+ 1 file changed, 1 insertion(+)
+
+--- a/fs/erofs/decompressor.c
++++ b/fs/erofs/decompressor.c
+@@ -133,6 +133,7 @@ static void *z_erofs_lz4_handle_overlap(
+ if (rq->inplace_io) {
+ omargin = PAGE_ALIGN(ctx->oend) - ctx->oend;
+ if (rq->partial_decoding || !may_inplace ||
++ ctx->outpages < ctx->inpages ||
+ omargin < LZ4_DECOMPRESS_INPLACE_MARGIN(rq->inputsize))
+ goto docopy;
+
--- /dev/null
+From stable+bounces-247304-greg=kroah.com@vger.kernel.org Fri May 15 03:30:44 2026
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 14 May 2026 21:26:17 -0400
+Subject: fbcon: Avoid OOB font access if console rotation fails
+To: stable@vger.kernel.org
+Cc: Thomas Zimmermann <tzimmermann@suse.de>, Helge Deller <deller@gmx.de>, Sasha Levin <sashal@kernel.org>
+Message-ID: <20260515012617.2652194-1-sashal@kernel.org>
+
+From: Thomas Zimmermann <tzimmermann@suse.de>
+
+[ 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 <tzimmermann@suse.de>
+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 <deller@gmx.de>
+[ renamed `par` to `ops` to match the 6.12 local pointer name ]
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ 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;
+ }
+
--- /dev/null
+From stable+bounces-247201-greg=kroah.com@vger.kernel.org Thu May 14 15:07:38 2026
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 14 May 2026 09:06:35 -0400
+Subject: mm/hugetlb_cma: round up per_node before logging it
+To: stable@vger.kernel.org
+Cc: Sang-Heon Jeon <ekffu200098@gmail.com>, Muchun Song <muchun.song@linux.dev>, David Hildenbrand <david@kernel.org>, Oscar Salvador <osalvador@suse.de>, Andrew Morton <akpm@linux-foundation.org>, Sasha Levin <sashal@kernel.org>
+Message-ID: <20260514130635.228150-1-sashal@kernel.org>
+
+From: Sang-Heon Jeon <ekffu200098@gmail.com>
+
+[ 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 <ekffu200098@gmail.com>
+Reviewed-by: Muchun Song <muchun.song@linux.dev>
+Cc: David Hildenbrand <david@kernel.org>
+Cc: Oscar Salvador <osalvador@suse.de>
+Cc: <stable@vger.kernel.org>
+Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
+[ 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 <sashal@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ mm/hugetlb.c | 1 +
+ 1 file changed, 1 insertion(+)
+
+--- a/mm/hugetlb.c
++++ b/mm/hugetlb.c
+@@ -7493,6 +7493,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);
+ }
--- /dev/null
+From stable+bounces-246943-greg=kroah.com@vger.kernel.org Wed May 13 18:49:24 2026
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 13 May 2026 12:46:33 -0400
+Subject: net: ipv4: stop checking crypto_ahash_alignmask
+To: stable@vger.kernel.org
+Cc: Eric Biggers <ebiggers@google.com>, Herbert Xu <herbert@gondor.apana.org.au>, Sasha Levin <sashal@kernel.org>
+Message-ID: <20260513164635.3816490-1-sashal@kernel.org>
+
+From: Eric Biggers <ebiggers@google.com>
+
+[ Upstream commit e77f5dd701381cef35b9ea8b6dea6e62c8a7f9f3 ]
+
+Now that the alignmask for ahash and shash algorithms is always 0,
+crypto_ahash_alignmask() always returns 0 and will be removed. In
+preparation for this, stop checking crypto_ahash_alignmask() in ah4.c.
+
+Signed-off-by: Eric Biggers <ebiggers@google.com>
+Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
+Stable-dep-of: ec54093e6a8f ("xfrm: ah: account for ESN high bits in async callbacks")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ net/ipv4/ah4.c | 17 +++++++----------
+ 1 file changed, 7 insertions(+), 10 deletions(-)
+
+--- a/net/ipv4/ah4.c
++++ b/net/ipv4/ah4.c
+@@ -27,9 +27,7 @@ static void *ah_alloc_tmp(struct crypto_
+ {
+ unsigned int len;
+
+- len = size + crypto_ahash_digestsize(ahash) +
+- (crypto_ahash_alignmask(ahash) &
+- ~(crypto_tfm_ctx_alignment() - 1));
++ len = size + crypto_ahash_digestsize(ahash);
+
+ len = ALIGN(len, crypto_tfm_ctx_alignment());
+
+@@ -46,10 +44,9 @@ static inline u8 *ah_tmp_auth(void *tmp,
+ return tmp + offset;
+ }
+
+-static inline u8 *ah_tmp_icv(struct crypto_ahash *ahash, void *tmp,
+- unsigned int offset)
++static inline u8 *ah_tmp_icv(void *tmp, unsigned int offset)
+ {
+- return PTR_ALIGN((u8 *)tmp + offset, crypto_ahash_alignmask(ahash) + 1);
++ return tmp + offset;
+ }
+
+ static inline struct ahash_request *ah_tmp_req(struct crypto_ahash *ahash,
+@@ -129,7 +126,7 @@ static void ah_output_done(void *data, i
+ int ihl = ip_hdrlen(skb);
+
+ iph = AH_SKB_CB(skb)->tmp;
+- icv = ah_tmp_icv(ahp->ahash, iph, ihl);
++ icv = ah_tmp_icv(iph, ihl);
+ memcpy(ah->auth_data, icv, ahp->icv_trunc_len);
+
+ top_iph->tos = iph->tos;
+@@ -182,7 +179,7 @@ static int ah_output(struct xfrm_state *
+ if (!iph)
+ goto out;
+ seqhi = (__be32 *)((char *)iph + ihl);
+- icv = ah_tmp_icv(ahash, seqhi, seqhi_len);
++ icv = ah_tmp_icv(seqhi, seqhi_len);
+ req = ah_tmp_req(ahash, icv);
+ sg = ah_req_sg(ahash, req);
+ seqhisg = sg + nfrags;
+@@ -279,7 +276,7 @@ static void ah_input_done(void *data, in
+
+ work_iph = AH_SKB_CB(skb)->tmp;
+ auth_data = ah_tmp_auth(work_iph, ihl);
+- icv = ah_tmp_icv(ahp->ahash, auth_data, ahp->icv_trunc_len);
++ icv = ah_tmp_icv(auth_data, ahp->icv_trunc_len);
+
+ err = crypto_memneq(icv, auth_data, ahp->icv_trunc_len) ? -EBADMSG : 0;
+ if (err)
+@@ -374,7 +371,7 @@ static int ah_input(struct xfrm_state *x
+
+ seqhi = (__be32 *)((char *)work_iph + ihl);
+ auth_data = ah_tmp_auth(seqhi, seqhi_len);
+- icv = ah_tmp_icv(ahash, auth_data, ahp->icv_trunc_len);
++ icv = ah_tmp_icv(auth_data, ahp->icv_trunc_len);
+ req = ah_tmp_req(ahash, icv);
+ sg = ah_req_sg(ahash, req);
+ seqhisg = sg + nfrags;
--- /dev/null
+From stable+bounces-246944-greg=kroah.com@vger.kernel.org Wed May 13 18:49:27 2026
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 13 May 2026 12:46:34 -0400
+Subject: net: ipv6: stop checking crypto_ahash_alignmask
+To: stable@vger.kernel.org
+Cc: Eric Biggers <ebiggers@google.com>, Herbert Xu <herbert@gondor.apana.org.au>, Sasha Levin <sashal@kernel.org>
+Message-ID: <20260513164635.3816490-2-sashal@kernel.org>
+
+From: Eric Biggers <ebiggers@google.com>
+
+[ Upstream commit 0a6bfaa0e695facb072f2fedfb55df37c4483b50 ]
+
+Now that the alignmask for ahash and shash algorithms is always 0,
+crypto_ahash_alignmask() always returns 0 and will be removed. In
+preparation for this, stop checking crypto_ahash_alignmask() in ah6.c.
+
+Signed-off-by: Eric Biggers <ebiggers@google.com>
+Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
+Stable-dep-of: ec54093e6a8f ("xfrm: ah: account for ESN high bits in async callbacks")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ net/ipv6/ah6.c | 17 +++++++----------
+ 1 file changed, 7 insertions(+), 10 deletions(-)
+
+--- a/net/ipv6/ah6.c
++++ b/net/ipv6/ah6.c
+@@ -79,9 +79,7 @@ static void *ah_alloc_tmp(struct crypto_
+ {
+ unsigned int len;
+
+- len = size + crypto_ahash_digestsize(ahash) +
+- (crypto_ahash_alignmask(ahash) &
+- ~(crypto_tfm_ctx_alignment() - 1));
++ len = size + crypto_ahash_digestsize(ahash);
+
+ len = ALIGN(len, crypto_tfm_ctx_alignment());
+
+@@ -103,10 +101,9 @@ static inline u8 *ah_tmp_auth(u8 *tmp, u
+ return tmp + offset;
+ }
+
+-static inline u8 *ah_tmp_icv(struct crypto_ahash *ahash, void *tmp,
+- unsigned int offset)
++static inline u8 *ah_tmp_icv(void *tmp, unsigned int offset)
+ {
+- return PTR_ALIGN((u8 *)tmp + offset, crypto_ahash_alignmask(ahash) + 1);
++ return tmp + offset;
+ }
+
+ static inline struct ahash_request *ah_tmp_req(struct crypto_ahash *ahash,
+@@ -327,7 +324,7 @@ static void ah6_output_done(void *data,
+
+ iph_base = AH_SKB_CB(skb)->tmp;
+ iph_ext = ah_tmp_ext(iph_base);
+- icv = ah_tmp_icv(ahp->ahash, iph_ext, extlen);
++ icv = ah_tmp_icv(iph_ext, extlen);
+
+ memcpy(ah->auth_data, icv, ahp->icv_trunc_len);
+ memcpy(top_iph, iph_base, IPV6HDR_BASELEN);
+@@ -384,7 +381,7 @@ static int ah6_output(struct xfrm_state
+
+ iph_ext = ah_tmp_ext(iph_base);
+ seqhi = (__be32 *)((char *)iph_ext + extlen);
+- icv = ah_tmp_icv(ahash, seqhi, seqhi_len);
++ icv = ah_tmp_icv(seqhi, seqhi_len);
+ req = ah_tmp_req(ahash, icv);
+ sg = ah_req_sg(ahash, req);
+ seqhisg = sg + nfrags;
+@@ -480,7 +477,7 @@ static void ah6_input_done(void *data, i
+
+ work_iph = AH_SKB_CB(skb)->tmp;
+ auth_data = ah_tmp_auth(work_iph, hdr_len);
+- icv = ah_tmp_icv(ahp->ahash, auth_data, ahp->icv_trunc_len);
++ icv = ah_tmp_icv(auth_data, ahp->icv_trunc_len);
+
+ err = crypto_memneq(icv, auth_data, ahp->icv_trunc_len) ? -EBADMSG : 0;
+ if (err)
+@@ -588,7 +585,7 @@ static int ah6_input(struct xfrm_state *
+
+ auth_data = ah_tmp_auth((u8 *)work_iph, hdr_len);
+ seqhi = (__be32 *)(auth_data + ahp->icv_trunc_len);
+- icv = ah_tmp_icv(ahash, seqhi, seqhi_len);
++ icv = ah_tmp_icv(seqhi, seqhi_len);
+ req = ah_tmp_req(ahash, icv);
+ sg = ah_req_sg(ahash, req);
+ seqhisg = sg + nfrags;
--- /dev/null
+From stable+bounces-245032-greg=kroah.com@vger.kernel.org Sun May 10 17:10:25 2026
+From: Sasha Levin <sashal@kernel.org>
+Date: Sun, 10 May 2026 11:10:17 -0400
+Subject: net: stmmac: avoid shadowing global buf_sz
+To: stable@vger.kernel.org
+Cc: "Russell King (Oracle)" <rmk+kernel@armlinux.org.uk>, Furong Xu <0x1207@gmail.com>, Jakub Kicinski <kuba@kernel.org>, Sasha Levin <sashal@kernel.org>
+Message-ID: <20260510151019.38468-1-sashal@kernel.org>
+
+From: "Russell King (Oracle)" <rmk+kernel@armlinux.org.uk>
+
+[ Upstream commit 876cfb20e8892143c0c967b3657074f9131f9b5f ]
+
+stmmac_rx() declares a local variable named "buf_sz" but there is also
+a global variable for a module parameter which is called the same. To
+avoid confusion, rename the local variable.
+
+Signed-off-by: Russell King (Oracle) <rmk+kernel@armlinux.org.uk>
+Reviewed-by: Furong Xu <0x1207@gmail.com>
+Link: https://patch.msgid.link/E1tpswi-005U6C-Py@rmk-PC.armlinux.org.uk
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Stable-dep-of: 0bb05e6adfa9 ("net: stmmac: Prevent NULL deref when RX memory exhausted")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/net/ethernet/stmicro/stmmac/stmmac_main.c | 6 +++---
+ 1 file changed, 3 insertions(+), 3 deletions(-)
+
+--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
++++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
+@@ -5279,10 +5279,10 @@ static int stmmac_rx(struct stmmac_priv
+ struct sk_buff *skb = NULL;
+ struct stmmac_xdp_buff ctx;
+ int xdp_status = 0;
+- int buf_sz;
++ int bufsz;
+
+ dma_dir = page_pool_get_dma_dir(rx_q->page_pool);
+- buf_sz = DIV_ROUND_UP(priv->dma_conf.dma_buf_sz, PAGE_SIZE) * PAGE_SIZE;
++ bufsz = DIV_ROUND_UP(priv->dma_conf.dma_buf_sz, PAGE_SIZE) * PAGE_SIZE;
+ limit = min(priv->dma_conf.dma_rx_size - 1, (unsigned int)limit);
+
+ if (netif_msg_rx_status(priv)) {
+@@ -5397,7 +5397,7 @@ read_again:
+ dma_sync_single_for_cpu(priv->device, buf->addr,
+ buf1_len, dma_dir);
+
+- xdp_init_buff(&ctx.xdp, buf_sz, &rx_q->xdp_rxq);
++ xdp_init_buff(&ctx.xdp, bufsz, &rx_q->xdp_rxq);
+ xdp_prepare_buff(&ctx.xdp, page_address(buf->page),
+ buf->page_offset, buf1_len, true);
+
--- /dev/null
+From stable+bounces-245034-greg=kroah.com@vger.kernel.org Sun May 10 17:10:28 2026
+From: Sasha Levin <sashal@kernel.org>
+Date: Sun, 10 May 2026 11:10:19 -0400
+Subject: net: stmmac: Prevent NULL deref when RX memory exhausted
+To: stable@vger.kernel.org
+Cc: Sam Edwards <cfsworks@gmail.com>, Russell King <linux@armlinux.org.uk>, Sam Edwards <CFSworks@gmail.com>, Paolo Abeni <pabeni@redhat.com>, Sasha Levin <sashal@kernel.org>
+Message-ID: <20260510151019.38468-3-sashal@kernel.org>
+
+From: Sam Edwards <cfsworks@gmail.com>
+
+[ Upstream commit 0bb05e6adfa99a2ea1fee1125cc0953409f83ed8 ]
+
+The CPU receives frames from the MAC through conventional DMA: the CPU
+allocates buffers for the MAC, then the MAC fills them and returns
+ownership to the CPU. For each hardware RX queue, the CPU and MAC
+coordinate through a shared ring array of DMA descriptors: one
+descriptor per DMA buffer. Each descriptor includes the buffer's
+physical address and a status flag ("OWN") indicating which side owns
+the buffer: OWN=0 for CPU, OWN=1 for MAC. The CPU is only allowed to set
+the flag and the MAC is only allowed to clear it, and both must move
+through the ring in sequence: thus the ring is used for both
+"submissions" and "completions."
+
+In the stmmac driver, stmmac_rx() bookmarks its position in the ring
+with the `cur_rx` index. The main receive loop in that function checks
+for rx_descs[cur_rx].own=0, gives the corresponding buffer to the
+network stack (NULLing the pointer), and increments `cur_rx` modulo the
+ring size. After the loop exits, stmmac_rx_refill(), which bookmarks its
+position with `dirty_rx`, allocates fresh buffers and rearms the
+descriptors (setting OWN=1). If it fails any allocation, it simply stops
+early (leaving OWN=0) and will retry where it left off when next called.
+
+This means descriptors have a three-stage lifecycle (terms my own):
+- `empty` (OWN=1, buffer valid)
+- `full` (OWN=0, buffer valid and populated)
+- `dirty` (OWN=0, buffer NULL)
+
+But because stmmac_rx() only checks OWN, it confuses `full`/`dirty`. In
+the past (see 'Fixes:'), there was a bug where the loop could cycle
+`cur_rx` all the way back to the first descriptor it dirtied, resulting
+in a NULL dereference when mistaken for `full`. The aforementioned
+commit resolved that *specific* failure by capping the loop's iteration
+limit at `dma_rx_size - 1`, but this is only a partial fix: if the
+previous stmmac_rx_refill() didn't complete, then there are leftover
+`dirty` descriptors that the loop might encounter without needing to
+cycle fully around. The current code therefore panics (see 'Closes:')
+when stmmac_rx_refill() is memory-starved long enough for `cur_rx` to
+catch up to `dirty_rx`.
+
+Fix this by explicitly checking, before advancing `cur_rx`, if the next
+entry is dirty; exit the loop if so. This prevents processing of the
+final, used descriptor until stmmac_rx_refill() succeeds, but
+fully prevents the `cur_rx == dirty_rx` ambiguity as the previous bugfix
+intended: so remove the clamp as well. Since stmmac_rx_zc() is a
+copy-paste-and-tweak of stmmac_rx() and the code structure is identical,
+any fix to stmmac_rx() will also need a corresponding fix for
+stmmac_rx_zc(). Therefore, apply the same check there.
+
+In stmmac_rx() (not stmmac_rx_zc()), a related bug remains: after the
+MAC sets OWN=0 on the final descriptor, it will be unable to send any
+further DMA-complete IRQs until it's given more `empty` descriptors.
+Currently, the driver simply *hopes* that the next stmmac_rx_refill()
+succeeds, risking an indefinite stall of the receive process if not. But
+this is not a regression, so it can be addressed in a future change.
+
+Fixes: b6cb4541853c7 ("net: stmmac: avoid rx queue overrun")
+Closes: https://bugzilla.kernel.org/show_bug.cgi?id=221010
+Cc: stable@vger.kernel.org
+Suggested-by: Russell King <linux@armlinux.org.uk>
+Signed-off-by: Sam Edwards <CFSworks@gmail.com>
+Link: https://patch.msgid.link/20260422044503.5349-1-CFSworks@gmail.com
+Signed-off-by: Paolo Abeni <pabeni@redhat.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/net/ethernet/stmicro/stmmac/stmmac_main.c | 19 ++++++++++++-------
+ 1 file changed, 12 insertions(+), 7 deletions(-)
+
+--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
++++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
+@@ -5143,9 +5143,12 @@ read_again:
+ break;
+
+ /* Prefetch the next RX descriptor */
+- rx_q->cur_rx = STMMAC_NEXT_ENTRY(rx_q->cur_rx,
+- priv->dma_conf.dma_rx_size);
+- next_entry = rx_q->cur_rx;
++ next_entry = STMMAC_NEXT_ENTRY(rx_q->cur_rx,
++ priv->dma_conf.dma_rx_size);
++ if (unlikely(next_entry == rx_q->dirty_rx))
++ break;
++
++ rx_q->cur_rx = next_entry;
+
+ if (priv->extend_desc)
+ np = (struct dma_desc *)(rx_q->dma_erx + next_entry);
+@@ -5283,7 +5286,6 @@ static int stmmac_rx(struct stmmac_priv
+
+ dma_dir = page_pool_get_dma_dir(rx_q->page_pool);
+ bufsz = DIV_ROUND_UP(priv->dma_conf.dma_buf_sz, PAGE_SIZE) * PAGE_SIZE;
+- limit = min(priv->dma_conf.dma_rx_size - 1, (unsigned int)limit);
+
+ if (netif_msg_rx_status(priv)) {
+ void *rx_head;
+@@ -5339,9 +5341,12 @@ read_again:
+ if (unlikely(status & dma_own))
+ break;
+
+- rx_q->cur_rx = STMMAC_NEXT_ENTRY(rx_q->cur_rx,
+- priv->dma_conf.dma_rx_size);
+- next_entry = rx_q->cur_rx;
++ next_entry = STMMAC_NEXT_ENTRY(rx_q->cur_rx,
++ priv->dma_conf.dma_rx_size);
++ if (unlikely(next_entry == rx_q->dirty_rx))
++ break;
++
++ rx_q->cur_rx = next_entry;
+
+ if (priv->extend_desc)
+ np = (struct dma_desc *)(rx_q->dma_erx + next_entry);
--- /dev/null
+From stable+bounces-245033-greg=kroah.com@vger.kernel.org Sun May 10 17:10:27 2026
+From: Sasha Levin <sashal@kernel.org>
+Date: Sun, 10 May 2026 11:10:18 -0400
+Subject: net: stmmac: rename STMMAC_GET_ENTRY() -> STMMAC_NEXT_ENTRY()
+To: stable@vger.kernel.org
+Cc: "Russell King (Oracle)" <rmk+kernel@armlinux.org.uk>, Jakub Kicinski <kuba@kernel.org>, Sasha Levin <sashal@kernel.org>
+Message-ID: <20260510151019.38468-2-sashal@kernel.org>
+
+From: "Russell King (Oracle)" <rmk+kernel@armlinux.org.uk>
+
+[ Upstream commit 6b4286e0550814cdc4b897f881ec1fa8b0313227 ]
+
+STMMAC_GET_ENTRY() doesn't describe what this macro is doing - it is
+incrementing the provided index for the circular array of descriptors.
+Replace "GET" with "NEXT" as this better describes the action here.
+
+Signed-off-by: Russell King (Oracle) <rmk+kernel@armlinux.org.uk>
+Link: https://patch.msgid.link/E1w2vba-0000000DbWo-1oL5@rmk-PC.armlinux.org.uk
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Stable-dep-of: 0bb05e6adfa9 ("net: stmmac: Prevent NULL deref when RX memory exhausted")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/net/ethernet/stmicro/stmmac/chain_mode.c | 2 -
+ drivers/net/ethernet/stmicro/stmmac/common.h | 2 -
+ drivers/net/ethernet/stmicro/stmmac/ring_mode.c | 2 -
+ drivers/net/ethernet/stmicro/stmmac/stmmac_main.c | 26 +++++++++++-----------
+ 4 files changed, 16 insertions(+), 16 deletions(-)
+
+--- a/drivers/net/ethernet/stmicro/stmmac/chain_mode.c
++++ b/drivers/net/ethernet/stmicro/stmmac/chain_mode.c
+@@ -47,7 +47,7 @@ static int jumbo_frm(struct stmmac_tx_qu
+
+ while (len != 0) {
+ tx_q->tx_skbuff[entry] = NULL;
+- entry = STMMAC_GET_ENTRY(entry, priv->dma_conf.dma_tx_size);
++ entry = STMMAC_NEXT_ENTRY(entry, priv->dma_conf.dma_tx_size);
+ desc = tx_q->dma_tx + entry;
+
+ if (len > bmax) {
+--- a/drivers/net/ethernet/stmicro/stmmac/common.h
++++ b/drivers/net/ethernet/stmicro/stmmac/common.h
+@@ -54,7 +54,7 @@
+ #define DMA_MIN_RX_SIZE 64
+ #define DMA_MAX_RX_SIZE 1024
+ #define DMA_DEFAULT_RX_SIZE 512
+-#define STMMAC_GET_ENTRY(x, size) ((x + 1) & (size - 1))
++#define STMMAC_NEXT_ENTRY(x, size) ((x + 1) & (size - 1))
+
+ #undef FRAME_FILTER_DEBUG
+ /* #define FRAME_FILTER_DEBUG */
+--- a/drivers/net/ethernet/stmicro/stmmac/ring_mode.c
++++ b/drivers/net/ethernet/stmicro/stmmac/ring_mode.c
+@@ -51,7 +51,7 @@ static int jumbo_frm(struct stmmac_tx_qu
+ stmmac_prepare_tx_desc(priv, desc, 1, bmax, csum,
+ STMMAC_RING_MODE, 0, false, skb->len);
+ tx_q->tx_skbuff[entry] = NULL;
+- entry = STMMAC_GET_ENTRY(entry, priv->dma_conf.dma_tx_size);
++ entry = STMMAC_NEXT_ENTRY(entry, priv->dma_conf.dma_tx_size);
+
+ if (priv->extend_desc)
+ desc = (struct dma_desc *)(tx_q->dma_etx + entry);
+--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
++++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
+@@ -2503,7 +2503,7 @@ static bool stmmac_xdp_xmit_zc(struct st
+
+ stmmac_enable_dma_transmission(priv, priv->ioaddr);
+
+- tx_q->cur_tx = STMMAC_GET_ENTRY(tx_q->cur_tx, priv->dma_conf.dma_tx_size);
++ tx_q->cur_tx = STMMAC_NEXT_ENTRY(tx_q->cur_tx, priv->dma_conf.dma_tx_size);
+ entry = tx_q->cur_tx;
+ }
+ u64_stats_update_begin(&txq_stats->napi_syncp);
+@@ -2659,7 +2659,7 @@ static int stmmac_tx_clean(struct stmmac
+
+ stmmac_release_tx_desc(priv, p, priv->mode);
+
+- entry = STMMAC_GET_ENTRY(entry, priv->dma_conf.dma_tx_size);
++ entry = STMMAC_NEXT_ENTRY(entry, priv->dma_conf.dma_tx_size);
+ }
+ tx_q->dirty_tx = entry;
+
+@@ -3973,7 +3973,7 @@ static bool stmmac_vlan_insert(struct st
+ return false;
+
+ stmmac_set_tx_owner(priv, p);
+- tx_q->cur_tx = STMMAC_GET_ENTRY(tx_q->cur_tx, priv->dma_conf.dma_tx_size);
++ tx_q->cur_tx = STMMAC_NEXT_ENTRY(tx_q->cur_tx, priv->dma_conf.dma_tx_size);
+ return true;
+ }
+
+@@ -4001,7 +4001,7 @@ static void stmmac_tso_allocator(struct
+ while (tmp_len > 0) {
+ dma_addr_t curr_addr;
+
+- tx_q->cur_tx = STMMAC_GET_ENTRY(tx_q->cur_tx,
++ tx_q->cur_tx = STMMAC_NEXT_ENTRY(tx_q->cur_tx,
+ priv->dma_conf.dma_tx_size);
+ WARN_ON(tx_q->tx_skbuff[tx_q->cur_tx]);
+
+@@ -4133,7 +4133,7 @@ static netdev_tx_t stmmac_tso_xmit(struc
+
+ stmmac_set_mss(priv, mss_desc, mss);
+ tx_q->mss = mss;
+- tx_q->cur_tx = STMMAC_GET_ENTRY(tx_q->cur_tx,
++ tx_q->cur_tx = STMMAC_NEXT_ENTRY(tx_q->cur_tx,
+ priv->dma_conf.dma_tx_size);
+ WARN_ON(tx_q->tx_skbuff[tx_q->cur_tx]);
+ }
+@@ -4258,7 +4258,7 @@ static netdev_tx_t stmmac_tso_xmit(struc
+ * ndo_start_xmit will fill this descriptor the next time it's
+ * called and stmmac_tx_clean may clean up to this descriptor.
+ */
+- tx_q->cur_tx = STMMAC_GET_ENTRY(tx_q->cur_tx, priv->dma_conf.dma_tx_size);
++ tx_q->cur_tx = STMMAC_NEXT_ENTRY(tx_q->cur_tx, priv->dma_conf.dma_tx_size);
+
+ if (unlikely(stmmac_tx_avail(priv, queue) <= (MAX_SKB_FRAGS + 1))) {
+ netif_dbg(priv, hw, priv->dev, "%s: stop transmitted packets\n",
+@@ -4451,7 +4451,7 @@ static netdev_tx_t stmmac_xmit(struct sk
+ int len = skb_frag_size(frag);
+ bool last_segment = (i == (nfrags - 1));
+
+- entry = STMMAC_GET_ENTRY(entry, priv->dma_conf.dma_tx_size);
++ entry = STMMAC_NEXT_ENTRY(entry, priv->dma_conf.dma_tx_size);
+ WARN_ON(tx_q->tx_skbuff[entry]);
+
+ if (likely(priv->extend_desc))
+@@ -4521,7 +4521,7 @@ static netdev_tx_t stmmac_xmit(struct sk
+ * ndo_start_xmit will fill this descriptor the next time it's
+ * called and stmmac_tx_clean may clean up to this descriptor.
+ */
+- entry = STMMAC_GET_ENTRY(entry, priv->dma_conf.dma_tx_size);
++ entry = STMMAC_NEXT_ENTRY(entry, priv->dma_conf.dma_tx_size);
+ tx_q->cur_tx = entry;
+
+ if (netif_msg_pktdata(priv)) {
+@@ -4691,7 +4691,7 @@ static inline void stmmac_rx_refill(stru
+ dma_wmb();
+ stmmac_set_rx_owner(priv, p, use_rx_wd);
+
+- entry = STMMAC_GET_ENTRY(entry, priv->dma_conf.dma_rx_size);
++ entry = STMMAC_NEXT_ENTRY(entry, priv->dma_conf.dma_rx_size);
+ }
+ rx_q->dirty_rx = entry;
+ rx_q->rx_tail_addr = rx_q->dma_rx_phy +
+@@ -4818,7 +4818,7 @@ static int stmmac_xdp_xmit_xdpf(struct s
+
+ stmmac_enable_dma_transmission(priv, priv->ioaddr);
+
+- entry = STMMAC_GET_ENTRY(entry, priv->dma_conf.dma_tx_size);
++ entry = STMMAC_NEXT_ENTRY(entry, priv->dma_conf.dma_tx_size);
+ tx_q->cur_tx = entry;
+
+ return STMMAC_XDP_TX;
+@@ -5048,7 +5048,7 @@ static bool stmmac_rx_refill_zc(struct s
+ dma_wmb();
+ stmmac_set_rx_owner(priv, rx_desc, use_rx_wd);
+
+- entry = STMMAC_GET_ENTRY(entry, priv->dma_conf.dma_rx_size);
++ entry = STMMAC_NEXT_ENTRY(entry, priv->dma_conf.dma_rx_size);
+ }
+
+ if (rx_desc) {
+@@ -5143,7 +5143,7 @@ read_again:
+ break;
+
+ /* Prefetch the next RX descriptor */
+- rx_q->cur_rx = STMMAC_GET_ENTRY(rx_q->cur_rx,
++ rx_q->cur_rx = STMMAC_NEXT_ENTRY(rx_q->cur_rx,
+ priv->dma_conf.dma_rx_size);
+ next_entry = rx_q->cur_rx;
+
+@@ -5339,7 +5339,7 @@ read_again:
+ if (unlikely(status & dma_own))
+ break;
+
+- rx_q->cur_rx = STMMAC_GET_ENTRY(rx_q->cur_rx,
++ rx_q->cur_rx = STMMAC_NEXT_ENTRY(rx_q->cur_rx,
+ priv->dma_conf.dma_rx_size);
+ next_entry = rx_q->cur_rx;
+
--- /dev/null
+From stable+bounces-245015-greg=kroah.com@vger.kernel.org Sun May 10 15:15:16 2026
+From: Sasha Levin <sashal@kernel.org>
+Date: Sun, 10 May 2026 09:15:07 -0400
+Subject: printk: add print_hex_dump_devel()
+To: stable@vger.kernel.org
+Cc: Thorsten Blum <thorsten.blum@linux.dev>, Herbert Xu <herbert@gondor.apana.org.au>, John Ogness <john.ogness@linutronix.de>, Sasha Levin <sashal@kernel.org>
+Message-ID: <20260510131508.4113857-1-sashal@kernel.org>
+
+From: Thorsten Blum <thorsten.blum@linux.dev>
+
+[ Upstream commit d134feeb5df33fbf77f482f52a366a44642dba09 ]
+
+Add print_hex_dump_devel() as the hex dump equivalent of pr_devel(),
+which emits output only when DEBUG is enabled, but keeps call sites
+compiled otherwise.
+
+Suggested-by: Herbert Xu <herbert@gondor.apana.org.au>
+Signed-off-by: Thorsten Blum <thorsten.blum@linux.dev>
+Reviewed-by: John Ogness <john.ogness@linutronix.de>
+Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
+Stable-dep-of: 177730a273b1 ("crypto: caam - guard HMAC key hex dumps in hash_digest_key")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ include/linux/printk.h | 13 +++++++++++++
+ 1 file changed, 13 insertions(+)
+
+--- a/include/linux/printk.h
++++ b/include/linux/printk.h
+@@ -745,6 +745,19 @@ static inline void print_hex_dump_debug(
+ }
+ #endif
+
++#if defined(DEBUG)
++#define print_hex_dump_devel(prefix_str, prefix_type, rowsize, \
++ groupsize, buf, len, ascii) \
++ print_hex_dump(KERN_DEBUG, prefix_str, prefix_type, rowsize, \
++ groupsize, buf, len, ascii)
++#else
++static inline void print_hex_dump_devel(const char *prefix_str, int prefix_type,
++ int rowsize, int groupsize,
++ const void *buf, size_t len, bool ascii)
++{
++}
++#endif
++
+ /**
+ * print_hex_dump_bytes - shorthand form of print_hex_dump() with default params
+ * @prefix_str: string to prefix each line with;
--- /dev/null
+From stable+bounces-242797-greg=kroah.com@vger.kernel.org Sun May 3 16:33:27 2026
+From: Sasha Levin <sashal@kernel.org>
+Date: Sun, 3 May 2026 10:33:17 -0400
+Subject: rxrpc: Fix conn-level packet handling to unshare RESPONSE packets
+To: stable@vger.kernel.org
+Cc: David Howells <dhowells@redhat.com>, Marc Dionne <marc.dionne@auristor.com>, Jeffrey Altman <jaltman@auristor.com>, Simon Horman <horms@kernel.org>, linux-afs@lists.infradead.org, stable@kernel.org, Jakub Kicinski <kuba@kernel.org>, Sasha Levin <sashal@kernel.org>
+Message-ID: <20260503143317.1089945-1-sashal@kernel.org>
+
+From: David Howells <dhowells@redhat.com>
+
+[ Upstream commit 24481a7f573305706054c59e275371f8d0fe919f ]
+
+The security operations that verify the RESPONSE packets decrypt bits of it
+in place - however, the sk_buff may be shared with a packet sniffer, which
+would lead to the sniffer seeing an apparently corrupt packet (actually
+decrypted).
+
+Fix this by handing a copy of the packet off to the specific security
+handler if the packet was cloned.
+
+Fixes: 17926a79320a ("[AF_RXRPC]: Provide secure RxRPC sockets for use by userspace and kernel both")
+Closes: https://sashiko.dev/#/patchset/20260408121252.2249051-1-dhowells%40redhat.com
+Signed-off-by: David Howells <dhowells@redhat.com>
+cc: Marc Dionne <marc.dionne@auristor.com>
+cc: Jeffrey Altman <jaltman@auristor.com>
+cc: Simon Horman <horms@kernel.org>
+cc: linux-afs@lists.infradead.org
+cc: stable@kernel.org
+Link: https://patch.msgid.link/20260422161438.2593376-5-dhowells@redhat.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ net/rxrpc/conn_event.c | 29 ++++++++++++++++++++++++++++-
+ 1 file changed, 28 insertions(+), 1 deletion(-)
+
+--- a/net/rxrpc/conn_event.c
++++ b/net/rxrpc/conn_event.c
+@@ -226,6 +226,33 @@ static void rxrpc_call_is_secure(struct
+ rxrpc_notify_socket(call);
+ }
+
++static int rxrpc_verify_response(struct rxrpc_connection *conn,
++ struct sk_buff *skb)
++{
++ int ret;
++
++ if (skb_cloned(skb)) {
++ /* Copy the packet if shared so that we can do in-place
++ * decryption.
++ */
++ struct sk_buff *nskb = skb_copy(skb, GFP_NOFS);
++
++ if (nskb) {
++ rxrpc_new_skb(nskb, rxrpc_skb_new_unshared);
++ ret = conn->security->verify_response(conn, nskb);
++ rxrpc_free_skb(nskb, rxrpc_skb_put_response_copy);
++ } else {
++ /* OOM - Drop the packet. */
++ rxrpc_see_skb(skb, rxrpc_skb_see_unshare_nomem);
++ ret = -ENOMEM;
++ }
++ } else {
++ ret = conn->security->verify_response(conn, skb);
++ }
++
++ return ret;
++}
++
+ /*
+ * connection-level Rx packet processor
+ */
+@@ -253,7 +280,7 @@ static int rxrpc_process_event(struct rx
+ }
+ spin_unlock(&conn->state_lock);
+
+- ret = conn->security->verify_response(conn, skb);
++ ret = rxrpc_verify_response(conn, skb);
+ if (ret < 0)
+ return ret;
+
hfsplus-fix-held-lock-freed-on-hfsplus_fill_super.patch
wifi-rtl8xxxu-fix-potential-use-of-uninitialized-value.patch
ksmbd-reset-rcount-per-connection-in-ksmbd_conn_wait_idle_sess_id.patch
+crypto-nx-avoid-wflex-array-member-not-at-end-warning.patch
+crypto-nx-migrate-to-scomp-api.patch
+crypto-nx-fix-bounce-buffer-leaks-in-nx842_crypto_-alloc-free-_ctx.patch
+erofs-fix-unsigned-underflow-in-z_erofs_lz4_handle_overlap.patch
+printk-add-print_hex_dump_devel.patch
+crypto-caam-guard-hmac-key-hex-dumps-in-hash_digest_key.patch
+net-stmmac-avoid-shadowing-global-buf_sz.patch
+net-stmmac-rename-stmmac_get_entry-stmmac_next_entry.patch
+net-stmmac-prevent-null-deref-when-rx-memory-exhausted.patch
+tracepoint-balance-regfunc-on-func_add-failure-in-tracepoint_add_func.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
+net-ipv4-stop-checking-crypto_ahash_alignmask.patch
+net-ipv6-stop-checking-crypto_ahash_alignmask.patch
+xfrm-ah-account-for-esn-high-bits-in-async-callbacks.patch
+xfrm-defensively-unhash-xfrm_state-lists-in-__xfrm_state_delete.patch
+bluetooth-hci_conn-fix-potential-uaf-in-create_big_sync.patch
+spi-synquacer-switch-to-use-modern-name.patch
+spi-syncuacer-fix-controller-deregistration.patch
+spi-sun4i-switch-to-use-modern-name.patch
+spi-sun4i-fix-controller-deregistration.patch
+spi-spi-ti-qspi-convert-to-platform-remove-callback-returning-void.patch
+spi-spi-ti-qspi-switch-to-use-modern-name.patch
+spi-ti-qspi-fix-controller-deregistration.patch
+spi-zynq-qspi-switch-to-use-modern-name.patch
+spi-zynq-qspi-simplify-clock-handling-with-devm_clk_get_enabled.patch
+spi-zynq-qspi-fix-controller-deregistration.patch
+spi-sun6i-switch-to-use-modern-name.patch
+spi-sun6i-fix-controller-deregistration.patch
+spi-tegra114-fix-controller-deregistration.patch
+spi-tegra20-sflash-fix-controller-deregistration.patch
+spi-uniphier-switch-to-use-modern-name.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
+spi-microchip-core-qspi-use-helper-function-devm_clk_get_enabled.patch
+spi-microchip-core-qspi-fix-controller-deregistration.patch
+fbcon-avoid-oob-font-access-if-console-rotation-fails.patch
+rxrpc-fix-conn-level-packet-handling-to-unshare-response-packets.patch
--- /dev/null
+From stable+bounces-247275-greg=kroah.com@vger.kernel.org Thu May 14 20:33:45 2026
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 14 May 2026 14:33:36 -0400
+Subject: spi: microchip-core-qspi: fix controller deregistration
+To: stable@vger.kernel.org
+Cc: Johan Hovold <johan@kernel.org>, Naga Sureshkumar Relli <nagasuresh.relli@microchip.com>, Conor Dooley <conor.dooley@microchip.com>, Mark Brown <broonie@kernel.org>, Sasha Levin <sashal@kernel.org>
+Message-ID: <20260514183336.771790-2-sashal@kernel.org>
+
+From: Johan Hovold <johan@kernel.org>
+
+[ Upstream commit e6464140d439f2d42f072eb422a5b1fec470c5a6 ]
+
+Make sure to deregister the controller before disabling underlying
+resources like interrupts during driver unbind.
+
+Fixes: 8596124c4c1b ("spi: microchip-core-qspi: Add support for microchip fpga qspi controllers")
+Cc: stable@vger.kernel.org # 6.1
+Cc: Naga Sureshkumar Relli <nagasuresh.relli@microchip.com>
+Signed-off-by: Johan Hovold <johan@kernel.org>
+Acked-by: Conor Dooley <conor.dooley@microchip.com>
+Link: https://patch.msgid.link/20260409120419.388546-19-johan@kernel.org
+Signed-off-by: Mark Brown <broonie@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/spi/spi-microchip-core-qspi.c | 12 ++++++++----
+ 1 file changed, 8 insertions(+), 4 deletions(-)
+
+--- a/drivers/spi/spi-microchip-core-qspi.c
++++ b/drivers/spi/spi-microchip-core-qspi.c
+@@ -512,7 +512,7 @@ static int mchp_coreqspi_probe(struct pl
+ "unable to allocate master for QSPI controller\n");
+
+ qspi = spi_controller_get_devdata(ctlr);
+- platform_set_drvdata(pdev, qspi);
++ platform_set_drvdata(pdev, ctlr);
+
+ qspi->regs = devm_platform_ioremap_resource(pdev, 0);
+ if (IS_ERR(qspi->regs))
+@@ -545,7 +545,7 @@ static int mchp_coreqspi_probe(struct pl
+ SPI_TX_DUAL | SPI_TX_QUAD;
+ ctlr->dev.of_node = np;
+
+- ret = devm_spi_register_controller(&pdev->dev, ctlr);
++ ret = spi_register_controller(ctlr);
+ if (ret)
+ return dev_err_probe(&pdev->dev, ret,
+ "spi_register_controller failed\n");
+@@ -555,9 +555,13 @@ static int mchp_coreqspi_probe(struct pl
+
+ static void mchp_coreqspi_remove(struct platform_device *pdev)
+ {
+- struct mchp_coreqspi *qspi = platform_get_drvdata(pdev);
+- u32 control = readl_relaxed(qspi->regs + REG_CONTROL);
++ struct spi_controller *ctlr = platform_get_drvdata(pdev);
++ struct mchp_coreqspi *qspi = spi_controller_get_devdata(ctlr);
++ u32 control;
+
++ spi_unregister_controller(ctlr);
++
++ control = readl_relaxed(qspi->regs + REG_CONTROL);
+ mchp_coreqspi_disable_ints(qspi);
+ control &= ~CONTROL_ENABLE;
+ writel_relaxed(control, qspi->regs + REG_CONTROL);
--- /dev/null
+From stable+bounces-247274-greg=kroah.com@vger.kernel.org Thu May 14 20:33:42 2026
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 14 May 2026 14:33:35 -0400
+Subject: spi: microchip-core-qspi: Use helper function devm_clk_get_enabled()
+To: stable@vger.kernel.org
+Cc: Li Zetao <lizetao1@huawei.com>, Jonathan Cameron <Jonathan.Cameron@huawei.com>, Mark Brown <broonie@kernel.org>, Sasha Levin <sashal@kernel.org>
+Message-ID: <20260514183336.771790-1-sashal@kernel.org>
+
+From: Li Zetao <lizetao1@huawei.com>
+
+[ Upstream commit e922f3fff21445117e9196bd8e940ad8e15ca8c7 ]
+
+Since commit 7ef9651e9792 ("clk: Provide new devm_clk helpers for prepared
+and enabled clocks"), devm_clk_get() and clk_prepare_enable() can now be
+replaced by devm_clk_get_enabled() when driver enables (and possibly
+prepares) the clocks for the whole lifetime of the device. Moreover, it is
+no longer necessary to unprepare and disable the clocks explicitly.
+
+Reviewed-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
+Signed-off-by: Li Zetao <lizetao1@huawei.com>
+Link: https://lore.kernel.org/r/20230823133938.1359106-18-lizetao1@huawei.com
+Signed-off-by: Mark Brown <broonie@kernel.org>
+Stable-dep-of: e6464140d439 ("spi: microchip-core-qspi: fix controller deregistration")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/spi/spi-microchip-core-qspi.c | 29 +++++++----------------------
+ 1 file changed, 7 insertions(+), 22 deletions(-)
+
+--- a/drivers/spi/spi-microchip-core-qspi.c
++++ b/drivers/spi/spi-microchip-core-qspi.c
+@@ -519,30 +519,23 @@ static int mchp_coreqspi_probe(struct pl
+ return dev_err_probe(&pdev->dev, PTR_ERR(qspi->regs),
+ "failed to map registers\n");
+
+- qspi->clk = devm_clk_get(&pdev->dev, NULL);
++ qspi->clk = devm_clk_get_enabled(&pdev->dev, NULL);
+ if (IS_ERR(qspi->clk))
+ return dev_err_probe(&pdev->dev, PTR_ERR(qspi->clk),
+ "could not get clock\n");
+
+- ret = clk_prepare_enable(qspi->clk);
+- if (ret)
+- return dev_err_probe(&pdev->dev, ret,
+- "failed to enable clock\n");
+-
+ init_completion(&qspi->data_completion);
+ mutex_init(&qspi->op_lock);
+
+ qspi->irq = platform_get_irq(pdev, 0);
+- if (qspi->irq < 0) {
+- ret = qspi->irq;
+- goto out;
+- }
++ if (qspi->irq < 0)
++ return qspi->irq;
+
+ ret = devm_request_irq(&pdev->dev, qspi->irq, mchp_coreqspi_isr,
+ IRQF_SHARED, pdev->name, qspi);
+ if (ret) {
+ dev_err(&pdev->dev, "request_irq failed %d\n", ret);
+- goto out;
++ return ret;
+ }
+
+ ctlr->bits_per_word_mask = SPI_BPW_MASK(8);
+@@ -553,18 +546,11 @@ static int mchp_coreqspi_probe(struct pl
+ ctlr->dev.of_node = np;
+
+ ret = devm_spi_register_controller(&pdev->dev, ctlr);
+- if (ret) {
+- dev_err_probe(&pdev->dev, ret,
+- "spi_register_controller failed\n");
+- goto out;
+- }
++ if (ret)
++ return dev_err_probe(&pdev->dev, ret,
++ "spi_register_controller failed\n");
+
+ return 0;
+-
+-out:
+- clk_disable_unprepare(qspi->clk);
+-
+- return ret;
+ }
+
+ static void mchp_coreqspi_remove(struct platform_device *pdev)
+@@ -575,7 +561,6 @@ static void mchp_coreqspi_remove(struct
+ mchp_coreqspi_disable_ints(qspi);
+ control &= ~CONTROL_ENABLE;
+ writel_relaxed(control, qspi->regs + REG_CONTROL);
+- clk_disable_unprepare(qspi->clk);
+ }
+
+ static const struct of_device_id mchp_coreqspi_of_match[] = {
--- /dev/null
+From stable+bounces-246995-greg=kroah.com@vger.kernel.org Wed May 13 20:11:11 2026
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 13 May 2026 14:08:40 -0400
+Subject: spi: spi-ti-qspi: Convert to platform remove callback returning void
+To: stable@vger.kernel.org
+Cc: "Uwe Kleine-König" <u.kleine-koenig@pengutronix.de>, "Mark Brown" <broonie@kernel.org>, "Sasha Levin" <sashal@kernel.org>
+Message-ID: <20260513180842.3912849-1-sashal@kernel.org>
+
+From: Uwe Kleine-König <u.kleine-koenig@pengutronix.de>
+
+[ Upstream commit 2f2802d1a59d79a3d00cb429841db502c2bbc3df ]
+
+The .remove() callback for a platform driver returns an int which makes
+many driver authors wrongly assume it's possible to do error handling by
+returning an error code. However the value returned is ignored (apart
+from emitting a warning) and this typically results in resource leaks.
+
+To improve here there is a quest to make the remove callback return
+void. In the first step of this quest all drivers are converted to
+.remove_new(), which already returns void. Eventually after all drivers
+are converted, .remove_new() will be renamed to .remove().
+
+Add an error message to the error path that returned an error before to
+replace the core's error message with more information. Apart from the
+different wording of the error message, this patch doesn't introduce a
+semantic difference.
+
+Signed-off-by: Uwe Kleine-König <u.kleine-koenig@pengutronix.de>
+Link: https://lore.kernel.org/r/20231105172649.3738556-2-u.kleine-koenig@pengutronix.de
+Signed-off-by: Mark Brown <broonie@kernel.org>
+Stable-dep-of: 0c18a1bacbb1 ("spi: ti-qspi: fix controller deregistration")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/spi/spi-ti-qspi.c | 13 +++++++------
+ 1 file changed, 7 insertions(+), 6 deletions(-)
+
+--- a/drivers/spi/spi-ti-qspi.c
++++ b/drivers/spi/spi-ti-qspi.c
+@@ -907,21 +907,22 @@ free_master:
+ return ret;
+ }
+
+-static int ti_qspi_remove(struct platform_device *pdev)
++static void ti_qspi_remove(struct platform_device *pdev)
+ {
+ struct ti_qspi *qspi = platform_get_drvdata(pdev);
+ int rc;
+
+ rc = spi_master_suspend(qspi->master);
+- if (rc)
+- return rc;
++ if (rc) {
++ dev_alert(&pdev->dev, "spi_master_suspend() failed (%pe)\n",
++ ERR_PTR(rc));
++ return;
++ }
+
+ pm_runtime_put_sync(&pdev->dev);
+ pm_runtime_disable(&pdev->dev);
+
+ ti_qspi_dma_cleanup(qspi);
+-
+- return 0;
+ }
+
+ static const struct dev_pm_ops ti_qspi_pm_ops = {
+@@ -930,7 +931,7 @@ static const struct dev_pm_ops ti_qspi_p
+
+ static struct platform_driver ti_qspi_driver = {
+ .probe = ti_qspi_probe,
+- .remove = ti_qspi_remove,
++ .remove_new = ti_qspi_remove,
+ .driver = {
+ .name = "ti-qspi",
+ .pm = &ti_qspi_pm_ops,
--- /dev/null
+From stable+bounces-246996-greg=kroah.com@vger.kernel.org Wed May 13 20:15:40 2026
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 13 May 2026 14:08:41 -0400
+Subject: spi: spi-ti-qspi: switch to use modern name
+To: stable@vger.kernel.org
+Cc: Yang Yingliang <yangyingliang@huawei.com>, Mark Brown <broonie@kernel.org>, Sasha Levin <sashal@kernel.org>
+Message-ID: <20260513180842.3912849-2-sashal@kernel.org>
+
+From: Yang Yingliang <yangyingliang@huawei.com>
+
+[ Upstream commit 9d93c8d97b4cdb5edddb4c5530881c90eecb7e44 ]
+
+Change legacy name master to modern name host or controller.
+
+No functional changed.
+
+Signed-off-by: Yang Yingliang <yangyingliang@huawei.com>
+Link: https://msgid.link/r/20231128093031.3707034-16-yangyingliang@huawei.com
+Signed-off-by: Mark Brown <broonie@kernel.org>
+Stable-dep-of: 0c18a1bacbb1 ("spi: ti-qspi: fix controller deregistration")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/spi/spi-ti-qspi.c | 88 +++++++++++++++++++++++-----------------------
+ 1 file changed, 44 insertions(+), 44 deletions(-)
+
+--- a/drivers/spi/spi-ti-qspi.c
++++ b/drivers/spi/spi-ti-qspi.c
+@@ -40,7 +40,7 @@ struct ti_qspi {
+ /* list synchronization */
+ struct mutex list_lock;
+
+- struct spi_master *master;
++ struct spi_controller *host;
+ void __iomem *base;
+ void __iomem *mmap_base;
+ size_t mmap_size;
+@@ -137,20 +137,20 @@ static inline void ti_qspi_write(struct
+
+ static int ti_qspi_setup(struct spi_device *spi)
+ {
+- struct ti_qspi *qspi = spi_master_get_devdata(spi->master);
++ struct ti_qspi *qspi = spi_controller_get_devdata(spi->controller);
+ int ret;
+
+- if (spi->master->busy) {
+- dev_dbg(qspi->dev, "master busy doing other transfers\n");
++ if (spi->controller->busy) {
++ dev_dbg(qspi->dev, "host busy doing other transfers\n");
+ return -EBUSY;
+ }
+
+- if (!qspi->master->max_speed_hz) {
++ if (!qspi->host->max_speed_hz) {
+ dev_err(qspi->dev, "spi max frequency not defined\n");
+ return -EINVAL;
+ }
+
+- spi->max_speed_hz = min(spi->max_speed_hz, qspi->master->max_speed_hz);
++ spi->max_speed_hz = min(spi->max_speed_hz, qspi->host->max_speed_hz);
+
+ ret = pm_runtime_resume_and_get(qspi->dev);
+ if (ret < 0) {
+@@ -526,7 +526,7 @@ static int ti_qspi_dma_xfer_sg(struct ti
+
+ static void ti_qspi_enable_memory_map(struct spi_device *spi)
+ {
+- struct ti_qspi *qspi = spi_master_get_devdata(spi->master);
++ struct ti_qspi *qspi = spi_controller_get_devdata(spi->controller);
+
+ ti_qspi_write(qspi, MM_SWITCH, QSPI_SPI_SWITCH_REG);
+ if (qspi->ctrl_base) {
+@@ -540,7 +540,7 @@ static void ti_qspi_enable_memory_map(st
+
+ static void ti_qspi_disable_memory_map(struct spi_device *spi)
+ {
+- struct ti_qspi *qspi = spi_master_get_devdata(spi->master);
++ struct ti_qspi *qspi = spi_controller_get_devdata(spi->controller);
+
+ ti_qspi_write(qspi, 0, QSPI_SPI_SWITCH_REG);
+ if (qspi->ctrl_base)
+@@ -554,7 +554,7 @@ static void ti_qspi_setup_mmap_read(stru
+ u8 data_nbits, u8 addr_width,
+ u8 dummy_bytes)
+ {
+- struct ti_qspi *qspi = spi_master_get_devdata(spi->master);
++ struct ti_qspi *qspi = spi_controller_get_devdata(spi->controller);
+ u32 memval = opcode;
+
+ switch (data_nbits) {
+@@ -576,7 +576,7 @@ static void ti_qspi_setup_mmap_read(stru
+
+ static int ti_qspi_adjust_op_size(struct spi_mem *mem, struct spi_mem_op *op)
+ {
+- struct ti_qspi *qspi = spi_controller_get_devdata(mem->spi->master);
++ struct ti_qspi *qspi = spi_controller_get_devdata(mem->spi->controller);
+ size_t max_len;
+
+ if (op->data.dir == SPI_MEM_DATA_IN) {
+@@ -606,7 +606,7 @@ static int ti_qspi_adjust_op_size(struct
+ static int ti_qspi_exec_mem_op(struct spi_mem *mem,
+ const struct spi_mem_op *op)
+ {
+- struct ti_qspi *qspi = spi_master_get_devdata(mem->spi->master);
++ struct ti_qspi *qspi = spi_controller_get_devdata(mem->spi->controller);
+ u32 from = 0;
+ int ret = 0;
+
+@@ -633,10 +633,10 @@ static int ti_qspi_exec_mem_op(struct sp
+ struct sg_table sgt;
+
+ if (virt_addr_valid(op->data.buf.in) &&
+- !spi_controller_dma_map_mem_op_data(mem->spi->master, op,
++ !spi_controller_dma_map_mem_op_data(mem->spi->controller, op,
+ &sgt)) {
+ ret = ti_qspi_dma_xfer_sg(qspi, sgt, from);
+- spi_controller_dma_unmap_mem_op_data(mem->spi->master,
++ spi_controller_dma_unmap_mem_op_data(mem->spi->controller,
+ op, &sgt);
+ } else {
+ ret = ti_qspi_dma_bounce_buffer(qspi, from,
+@@ -658,10 +658,10 @@ static const struct spi_controller_mem_o
+ .adjust_op_size = ti_qspi_adjust_op_size,
+ };
+
+-static int ti_qspi_start_transfer_one(struct spi_master *master,
++static int ti_qspi_start_transfer_one(struct spi_controller *host,
+ struct spi_message *m)
+ {
+- struct ti_qspi *qspi = spi_master_get_devdata(master);
++ struct ti_qspi *qspi = spi_controller_get_devdata(host);
+ struct spi_device *spi = m->spi;
+ struct spi_transfer *t;
+ int status = 0, ret;
+@@ -720,7 +720,7 @@ static int ti_qspi_start_transfer_one(st
+
+ ti_qspi_write(qspi, qspi->cmd | QSPI_INVAL, QSPI_SPI_CMD_REG);
+ m->status = status;
+- spi_finalize_current_message(master);
++ spi_finalize_current_message(host);
+
+ return status;
+ }
+@@ -756,33 +756,33 @@ MODULE_DEVICE_TABLE(of, ti_qspi_match);
+ static int ti_qspi_probe(struct platform_device *pdev)
+ {
+ struct ti_qspi *qspi;
+- struct spi_master *master;
++ struct spi_controller *host;
+ struct resource *r, *res_mmap;
+ struct device_node *np = pdev->dev.of_node;
+ u32 max_freq;
+ int ret = 0, num_cs, irq;
+ dma_cap_mask_t mask;
+
+- master = spi_alloc_master(&pdev->dev, sizeof(*qspi));
+- if (!master)
++ host = spi_alloc_host(&pdev->dev, sizeof(*qspi));
++ if (!host)
+ return -ENOMEM;
+
+- master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_RX_DUAL | SPI_RX_QUAD;
++ host->mode_bits = SPI_CPOL | SPI_CPHA | SPI_RX_DUAL | SPI_RX_QUAD;
+
+- master->flags = SPI_CONTROLLER_HALF_DUPLEX;
+- master->setup = ti_qspi_setup;
+- master->auto_runtime_pm = true;
+- master->transfer_one_message = ti_qspi_start_transfer_one;
+- master->dev.of_node = pdev->dev.of_node;
+- master->bits_per_word_mask = SPI_BPW_MASK(32) | SPI_BPW_MASK(16) |
+- SPI_BPW_MASK(8);
+- master->mem_ops = &ti_qspi_mem_ops;
++ host->flags = SPI_CONTROLLER_HALF_DUPLEX;
++ host->setup = ti_qspi_setup;
++ host->auto_runtime_pm = true;
++ host->transfer_one_message = ti_qspi_start_transfer_one;
++ host->dev.of_node = pdev->dev.of_node;
++ host->bits_per_word_mask = SPI_BPW_MASK(32) | SPI_BPW_MASK(16) |
++ SPI_BPW_MASK(8);
++ host->mem_ops = &ti_qspi_mem_ops;
+
+ if (!of_property_read_u32(np, "num-cs", &num_cs))
+- master->num_chipselect = num_cs;
++ host->num_chipselect = num_cs;
+
+- qspi = spi_master_get_devdata(master);
+- qspi->master = master;
++ qspi = spi_controller_get_devdata(host);
++ qspi->host = host;
+ qspi->dev = &pdev->dev;
+ platform_set_drvdata(pdev, qspi);
+
+@@ -792,7 +792,7 @@ static int ti_qspi_probe(struct platform
+ if (r == NULL) {
+ dev_err(&pdev->dev, "missing platform data\n");
+ ret = -ENODEV;
+- goto free_master;
++ goto free_host;
+ }
+ }
+
+@@ -812,7 +812,7 @@ static int ti_qspi_probe(struct platform
+ irq = platform_get_irq(pdev, 0);
+ if (irq < 0) {
+ ret = irq;
+- goto free_master;
++ goto free_host;
+ }
+
+ mutex_init(&qspi->list_lock);
+@@ -820,7 +820,7 @@ static int ti_qspi_probe(struct platform
+ qspi->base = devm_ioremap_resource(&pdev->dev, r);
+ if (IS_ERR(qspi->base)) {
+ ret = PTR_ERR(qspi->base);
+- goto free_master;
++ goto free_host;
+ }
+
+
+@@ -830,7 +830,7 @@ static int ti_qspi_probe(struct platform
+ "syscon-chipselects");
+ if (IS_ERR(qspi->ctrl_base)) {
+ ret = PTR_ERR(qspi->ctrl_base);
+- goto free_master;
++ goto free_host;
+ }
+ ret = of_property_read_u32_index(np,
+ "syscon-chipselects",
+@@ -838,7 +838,7 @@ static int ti_qspi_probe(struct platform
+ if (ret) {
+ dev_err(&pdev->dev,
+ "couldn't get ctrl_mod reg index\n");
+- goto free_master;
++ goto free_host;
+ }
+ }
+
+@@ -853,7 +853,7 @@ static int ti_qspi_probe(struct platform
+ pm_runtime_enable(&pdev->dev);
+
+ if (!of_property_read_u32(np, "spi-max-frequency", &max_freq))
+- master->max_speed_hz = max_freq;
++ host->max_speed_hz = max_freq;
+
+ dma_cap_zero(mask);
+ dma_cap_set(DMA_MEMCPY, mask);
+@@ -876,7 +876,7 @@ static int ti_qspi_probe(struct platform
+ dma_release_channel(qspi->rx_chan);
+ goto no_dma;
+ }
+- master->dma_rx = qspi->rx_chan;
++ host->dma_rx = qspi->rx_chan;
+ init_completion(&qspi->transfer_complete);
+ if (res_mmap)
+ qspi->mmap_phys_base = (dma_addr_t)res_mmap->start;
+@@ -889,21 +889,21 @@ no_dma:
+ "mmap failed with error %ld using PIO mode\n",
+ PTR_ERR(qspi->mmap_base));
+ qspi->mmap_base = NULL;
+- master->mem_ops = NULL;
++ host->mem_ops = NULL;
+ }
+ }
+ qspi->mmap_enabled = false;
+ qspi->current_cs = -1;
+
+- ret = devm_spi_register_master(&pdev->dev, master);
++ ret = devm_spi_register_controller(&pdev->dev, host);
+ if (!ret)
+ return 0;
+
+ ti_qspi_dma_cleanup(qspi);
+
+ pm_runtime_disable(&pdev->dev);
+-free_master:
+- spi_master_put(master);
++free_host:
++ spi_controller_put(host);
+ return ret;
+ }
+
+@@ -912,9 +912,9 @@ static void ti_qspi_remove(struct platfo
+ struct ti_qspi *qspi = platform_get_drvdata(pdev);
+ int rc;
+
+- rc = spi_master_suspend(qspi->master);
++ rc = spi_controller_suspend(qspi->host);
+ if (rc) {
+- dev_alert(&pdev->dev, "spi_master_suspend() failed (%pe)\n",
++ dev_alert(&pdev->dev, "spi_controller_suspend() failed (%pe)\n",
+ ERR_PTR(rc));
+ return;
+ }
--- /dev/null
+From stable+bounces-246971-greg=kroah.com@vger.kernel.org Wed May 13 19:32:40 2026
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 13 May 2026 13:32:02 -0400
+Subject: spi: sun4i: fix controller deregistration
+To: stable@vger.kernel.org
+Cc: Johan Hovold <johan@kernel.org>, Maxime Ripard <mripard@kernel.org>, Mark Brown <broonie@kernel.org>, Sasha Levin <sashal@kernel.org>
+Message-ID: <20260513173202.3886782-2-sashal@kernel.org>
+
+From: Johan Hovold <johan@kernel.org>
+
+[ Upstream commit 42108a2f03e0fdeabe9d02d085bdb058baa1189f ]
+
+Make sure to deregister the controller before disabling underlying
+resources like clocks during driver unbind.
+
+Fixes: b5f6517948cc ("spi: sunxi: Add Allwinner A10 SPI controller driver")
+Cc: stable@vger.kernel.org # 3.15
+Cc: Maxime Ripard <mripard@kernel.org>
+Signed-off-by: Johan Hovold <johan@kernel.org>
+Link: https://patch.msgid.link/20260410081757.503099-19-johan@kernel.org
+Signed-off-by: Mark Brown <broonie@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/spi/spi-sun4i.c | 10 +++++++++-
+ 1 file changed, 9 insertions(+), 1 deletion(-)
+
+--- a/drivers/spi/spi-sun4i.c
++++ b/drivers/spi/spi-sun4i.c
+@@ -503,7 +503,7 @@ static int sun4i_spi_probe(struct platfo
+ pm_runtime_enable(&pdev->dev);
+ pm_runtime_idle(&pdev->dev);
+
+- ret = devm_spi_register_controller(&pdev->dev, host);
++ ret = spi_register_controller(host);
+ if (ret) {
+ dev_err(&pdev->dev, "cannot register SPI host\n");
+ goto err_pm_disable;
+@@ -521,7 +521,15 @@ err_free_host:
+
+ static void sun4i_spi_remove(struct platform_device *pdev)
+ {
++ struct spi_controller *host = platform_get_drvdata(pdev);
++
++ spi_controller_get(host);
++
++ spi_unregister_controller(host);
++
+ pm_runtime_force_suspend(&pdev->dev);
++
++ spi_controller_put(host);
+ }
+
+ static const struct of_device_id sun4i_spi_match[] = {
--- /dev/null
+From stable+bounces-246970-greg=kroah.com@vger.kernel.org Wed May 13 19:32:37 2026
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 13 May 2026 13:32:01 -0400
+Subject: spi: sun4i: switch to use modern name
+To: stable@vger.kernel.org
+Cc: Yang Yingliang <yangyingliang@huawei.com>, Mark Brown <broonie@kernel.org>, Sasha Levin <sashal@kernel.org>
+Message-ID: <20260513173202.3886782-1-sashal@kernel.org>
+
+From: Yang Yingliang <yangyingliang@huawei.com>
+
+[ Upstream commit 6d232cc8a7e59af0c083319827541966a68817a0 ]
+
+Change legacy name master to modern name host or controller.
+
+No functional changed.
+
+Signed-off-by: Yang Yingliang <yangyingliang@huawei.com>
+Link: https://msgid.link/r/20231128093031.3707034-7-yangyingliang@huawei.com
+Signed-off-by: Mark Brown <broonie@kernel.org>
+Stable-dep-of: 42108a2f03e0 ("spi: sun4i: fix controller deregistration")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/spi/spi-sun4i.c | 72 ++++++++++++++++++++++++------------------------
+ 1 file changed, 36 insertions(+), 36 deletions(-)
+
+--- a/drivers/spi/spi-sun4i.c
++++ b/drivers/spi/spi-sun4i.c
+@@ -75,7 +75,7 @@
+ #define SUN4I_FIFO_STA_TF_CNT_BITS 16
+
+ struct sun4i_spi {
+- struct spi_master *master;
++ struct spi_controller *host;
+ void __iomem *base_addr;
+ struct clk *hclk;
+ struct clk *mclk;
+@@ -161,7 +161,7 @@ static inline void sun4i_spi_fill_fifo(s
+
+ static void sun4i_spi_set_cs(struct spi_device *spi, bool enable)
+ {
+- struct sun4i_spi *sspi = spi_master_get_devdata(spi->master);
++ struct sun4i_spi *sspi = spi_controller_get_devdata(spi->controller);
+ u32 reg;
+
+ reg = sun4i_spi_read(sspi, SUN4I_CTL_REG);
+@@ -201,11 +201,11 @@ static size_t sun4i_spi_max_transfer_siz
+ return SUN4I_MAX_XFER_SIZE - 1;
+ }
+
+-static int sun4i_spi_transfer_one(struct spi_master *master,
++static int sun4i_spi_transfer_one(struct spi_controller *host,
+ struct spi_device *spi,
+ struct spi_transfer *tfr)
+ {
+- struct sun4i_spi *sspi = spi_master_get_devdata(master);
++ struct sun4i_spi *sspi = spi_controller_get_devdata(host);
+ unsigned int mclk_rate, div, timeout;
+ unsigned int start, end, tx_time;
+ unsigned int tx_len = 0;
+@@ -334,7 +334,7 @@ static int sun4i_spi_transfer_one(struct
+ msecs_to_jiffies(tx_time));
+ end = jiffies;
+ if (!timeout) {
+- dev_warn(&master->dev,
++ dev_warn(&host->dev,
+ "%s: timeout transferring %u bytes@%iHz for %i(%i)ms",
+ dev_name(&spi->dev), tfr->len, tfr->speed_hz,
+ jiffies_to_msecs(end - start), tx_time);
+@@ -389,8 +389,8 @@ static irqreturn_t sun4i_spi_handler(int
+
+ static int sun4i_spi_runtime_resume(struct device *dev)
+ {
+- struct spi_master *master = dev_get_drvdata(dev);
+- struct sun4i_spi *sspi = spi_master_get_devdata(master);
++ struct spi_controller *host = dev_get_drvdata(dev);
++ struct sun4i_spi *sspi = spi_controller_get_devdata(host);
+ int ret;
+
+ ret = clk_prepare_enable(sspi->hclk);
+@@ -418,8 +418,8 @@ out:
+
+ static int sun4i_spi_runtime_suspend(struct device *dev)
+ {
+- struct spi_master *master = dev_get_drvdata(dev);
+- struct sun4i_spi *sspi = spi_master_get_devdata(master);
++ struct spi_controller *host = dev_get_drvdata(dev);
++ struct sun4i_spi *sspi = spi_controller_get_devdata(host);
+
+ clk_disable_unprepare(sspi->mclk);
+ clk_disable_unprepare(sspi->hclk);
+@@ -429,62 +429,62 @@ static int sun4i_spi_runtime_suspend(str
+
+ static int sun4i_spi_probe(struct platform_device *pdev)
+ {
+- struct spi_master *master;
++ struct spi_controller *host;
+ struct sun4i_spi *sspi;
+ int ret = 0, irq;
+
+- master = spi_alloc_master(&pdev->dev, sizeof(struct sun4i_spi));
+- if (!master) {
+- dev_err(&pdev->dev, "Unable to allocate SPI Master\n");
++ host = spi_alloc_host(&pdev->dev, sizeof(struct sun4i_spi));
++ if (!host) {
++ dev_err(&pdev->dev, "Unable to allocate SPI Host\n");
+ return -ENOMEM;
+ }
+
+- platform_set_drvdata(pdev, master);
+- sspi = spi_master_get_devdata(master);
++ platform_set_drvdata(pdev, host);
++ sspi = spi_controller_get_devdata(host);
+
+ sspi->base_addr = devm_platform_ioremap_resource(pdev, 0);
+ if (IS_ERR(sspi->base_addr)) {
+ ret = PTR_ERR(sspi->base_addr);
+- goto err_free_master;
++ goto err_free_host;
+ }
+
+ irq = platform_get_irq(pdev, 0);
+ if (irq < 0) {
+ ret = -ENXIO;
+- goto err_free_master;
++ goto err_free_host;
+ }
+
+ ret = devm_request_irq(&pdev->dev, irq, sun4i_spi_handler,
+ 0, "sun4i-spi", sspi);
+ if (ret) {
+ dev_err(&pdev->dev, "Cannot request IRQ\n");
+- goto err_free_master;
++ goto err_free_host;
+ }
+
+- sspi->master = master;
+- master->max_speed_hz = 100 * 1000 * 1000;
+- master->min_speed_hz = 3 * 1000;
+- master->set_cs = sun4i_spi_set_cs;
+- master->transfer_one = sun4i_spi_transfer_one;
+- master->num_chipselect = 4;
+- master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH | SPI_LSB_FIRST;
+- master->bits_per_word_mask = SPI_BPW_MASK(8);
+- master->dev.of_node = pdev->dev.of_node;
+- master->auto_runtime_pm = true;
+- master->max_transfer_size = sun4i_spi_max_transfer_size;
++ sspi->host = host;
++ host->max_speed_hz = 100 * 1000 * 1000;
++ host->min_speed_hz = 3 * 1000;
++ host->set_cs = sun4i_spi_set_cs;
++ host->transfer_one = sun4i_spi_transfer_one;
++ host->num_chipselect = 4;
++ host->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH | SPI_LSB_FIRST;
++ host->bits_per_word_mask = SPI_BPW_MASK(8);
++ host->dev.of_node = pdev->dev.of_node;
++ host->auto_runtime_pm = true;
++ host->max_transfer_size = sun4i_spi_max_transfer_size;
+
+ sspi->hclk = devm_clk_get(&pdev->dev, "ahb");
+ if (IS_ERR(sspi->hclk)) {
+ dev_err(&pdev->dev, "Unable to acquire AHB clock\n");
+ ret = PTR_ERR(sspi->hclk);
+- goto err_free_master;
++ goto err_free_host;
+ }
+
+ sspi->mclk = devm_clk_get(&pdev->dev, "mod");
+ if (IS_ERR(sspi->mclk)) {
+ dev_err(&pdev->dev, "Unable to acquire module clock\n");
+ ret = PTR_ERR(sspi->mclk);
+- goto err_free_master;
++ goto err_free_host;
+ }
+
+ init_completion(&sspi->done);
+@@ -496,16 +496,16 @@ static int sun4i_spi_probe(struct platfo
+ ret = sun4i_spi_runtime_resume(&pdev->dev);
+ if (ret) {
+ dev_err(&pdev->dev, "Couldn't resume the device\n");
+- goto err_free_master;
++ goto err_free_host;
+ }
+
+ pm_runtime_set_active(&pdev->dev);
+ pm_runtime_enable(&pdev->dev);
+ pm_runtime_idle(&pdev->dev);
+
+- ret = devm_spi_register_master(&pdev->dev, master);
++ ret = devm_spi_register_controller(&pdev->dev, host);
+ if (ret) {
+- dev_err(&pdev->dev, "cannot register SPI master\n");
++ dev_err(&pdev->dev, "cannot register SPI host\n");
+ goto err_pm_disable;
+ }
+
+@@ -514,8 +514,8 @@ static int sun4i_spi_probe(struct platfo
+ err_pm_disable:
+ pm_runtime_disable(&pdev->dev);
+ sun4i_spi_runtime_suspend(&pdev->dev);
+-err_free_master:
+- spi_master_put(master);
++err_free_host:
++ spi_controller_put(host);
+ return ret;
+ }
+
--- /dev/null
+From stable+bounces-247048-greg=kroah.com@vger.kernel.org Thu May 14 01:06:27 2026
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 13 May 2026 19:05:13 -0400
+Subject: spi: sun6i: fix controller deregistration
+To: stable@vger.kernel.org
+Cc: Johan Hovold <johan@kernel.org>, Maxime Ripard <mripard@kernel.org>, Mark Brown <broonie@kernel.org>, Sasha Levin <sashal@kernel.org>
+Message-ID: <20260513230513.4027915-2-sashal@kernel.org>
+
+From: Johan Hovold <johan@kernel.org>
+
+[ Upstream commit d874a1c33aee0d88fb4ba2f8aeadaa9f1965209a ]
+
+Make sure to deregister the controller before disabling underlying
+resources like clocks during driver unbind.
+
+Fixes: 3558fe900e8a ("spi: sunxi: Add Allwinner A31 SPI controller driver")
+Cc: stable@vger.kernel.org # 3.15
+Cc: Maxime Ripard <mripard@kernel.org>
+Signed-off-by: Johan Hovold <johan@kernel.org>
+Link: https://patch.msgid.link/20260410081757.503099-20-johan@kernel.org
+Signed-off-by: Mark Brown <broonie@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/spi/spi-sun6i.c | 8 +++++++-
+ 1 file changed, 7 insertions(+), 1 deletion(-)
+
+--- a/drivers/spi/spi-sun6i.c
++++ b/drivers/spi/spi-sun6i.c
+@@ -742,7 +742,7 @@ static int sun6i_spi_probe(struct platfo
+ pm_runtime_set_active(&pdev->dev);
+ pm_runtime_enable(&pdev->dev);
+
+- ret = devm_spi_register_controller(&pdev->dev, host);
++ ret = spi_register_controller(host);
+ if (ret) {
+ dev_err(&pdev->dev, "cannot register SPI host\n");
+ goto err_pm_disable;
+@@ -768,12 +768,18 @@ static void sun6i_spi_remove(struct plat
+ {
+ struct spi_controller *host = platform_get_drvdata(pdev);
+
++ spi_controller_get(host);
++
++ spi_unregister_controller(host);
++
+ pm_runtime_force_suspend(&pdev->dev);
+
+ 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 sun6i_spi_cfg sun6i_a31_spi_cfg = {
--- /dev/null
+From stable+bounces-247047-greg=kroah.com@vger.kernel.org Thu May 14 01:06:20 2026
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 13 May 2026 19:05:12 -0400
+Subject: spi: sun6i: switch to use modern name
+To: stable@vger.kernel.org
+Cc: Yang Yingliang <yangyingliang@huawei.com>, Mark Brown <broonie@kernel.org>, Sasha Levin <sashal@kernel.org>
+Message-ID: <20260513230513.4027915-1-sashal@kernel.org>
+
+From: Yang Yingliang <yangyingliang@huawei.com>
+
+[ Upstream commit 9f55bb79893a9dc75982372bee1307bdce48976b ]
+
+Change legacy name master to modern name host or controller.
+
+No functional changed.
+
+Signed-off-by: Yang Yingliang <yangyingliang@huawei.com>
+Link: https://msgid.link/r/20231128093031.3707034-8-yangyingliang@huawei.com
+Signed-off-by: Mark Brown <broonie@kernel.org>
+Stable-dep-of: d874a1c33aee ("spi: sun6i: fix controller deregistration")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/spi/spi-sun6i.c | 148 ++++++++++++++++++++++++------------------------
+ 1 file changed, 74 insertions(+), 74 deletions(-)
+
+--- a/drivers/spi/spi-sun6i.c
++++ b/drivers/spi/spi-sun6i.c
+@@ -97,7 +97,7 @@ struct sun6i_spi_cfg {
+ };
+
+ struct sun6i_spi {
+- struct spi_master *master;
++ struct spi_controller *host;
+ void __iomem *base_addr;
+ dma_addr_t dma_addr_rx;
+ dma_addr_t dma_addr_tx;
+@@ -181,7 +181,7 @@ static inline void sun6i_spi_fill_fifo(s
+
+ static void sun6i_spi_set_cs(struct spi_device *spi, bool enable)
+ {
+- struct sun6i_spi *sspi = spi_master_get_devdata(spi->master);
++ struct sun6i_spi *sspi = spi_controller_get_devdata(spi->controller);
+ u32 reg;
+
+ reg = sun6i_spi_read(sspi, SUN6I_TFR_CTL_REG);
+@@ -212,7 +212,7 @@ static int sun6i_spi_prepare_dma(struct
+ struct spi_transfer *tfr)
+ {
+ struct dma_async_tx_descriptor *rxdesc, *txdesc;
+- struct spi_master *master = sspi->master;
++ struct spi_controller *host = sspi->host;
+
+ rxdesc = NULL;
+ if (tfr->rx_buf) {
+@@ -223,9 +223,9 @@ static int sun6i_spi_prepare_dma(struct
+ .src_maxburst = 8,
+ };
+
+- dmaengine_slave_config(master->dma_rx, &rxconf);
++ dmaengine_slave_config(host->dma_rx, &rxconf);
+
+- rxdesc = dmaengine_prep_slave_sg(master->dma_rx,
++ rxdesc = dmaengine_prep_slave_sg(host->dma_rx,
+ tfr->rx_sg.sgl,
+ tfr->rx_sg.nents,
+ DMA_DEV_TO_MEM,
+@@ -245,38 +245,38 @@ static int sun6i_spi_prepare_dma(struct
+ .dst_maxburst = 8,
+ };
+
+- dmaengine_slave_config(master->dma_tx, &txconf);
++ dmaengine_slave_config(host->dma_tx, &txconf);
+
+- txdesc = dmaengine_prep_slave_sg(master->dma_tx,
++ txdesc = dmaengine_prep_slave_sg(host->dma_tx,
+ tfr->tx_sg.sgl,
+ tfr->tx_sg.nents,
+ DMA_MEM_TO_DEV,
+ DMA_PREP_INTERRUPT);
+ if (!txdesc) {
+ if (rxdesc)
+- dmaengine_terminate_sync(master->dma_rx);
++ dmaengine_terminate_sync(host->dma_rx);
+ return -EINVAL;
+ }
+ }
+
+ if (tfr->rx_buf) {
+ dmaengine_submit(rxdesc);
+- dma_async_issue_pending(master->dma_rx);
++ dma_async_issue_pending(host->dma_rx);
+ }
+
+ if (tfr->tx_buf) {
+ dmaengine_submit(txdesc);
+- dma_async_issue_pending(master->dma_tx);
++ dma_async_issue_pending(host->dma_tx);
+ }
+
+ return 0;
+ }
+
+-static int sun6i_spi_transfer_one(struct spi_master *master,
++static int sun6i_spi_transfer_one(struct spi_controller *host,
+ struct spi_device *spi,
+ struct spi_transfer *tfr)
+ {
+- struct sun6i_spi *sspi = spi_master_get_devdata(master);
++ struct sun6i_spi *sspi = spi_controller_get_devdata(host);
+ unsigned int div, div_cdr1, div_cdr2, timeout;
+ unsigned int start, end, tx_time;
+ unsigned int trig_level;
+@@ -293,7 +293,7 @@ static int sun6i_spi_transfer_one(struct
+ sspi->tx_buf = tfr->tx_buf;
+ sspi->rx_buf = tfr->rx_buf;
+ sspi->len = tfr->len;
+- use_dma = master->can_dma ? master->can_dma(master, spi, tfr) : false;
++ use_dma = host->can_dma ? host->can_dma(host, spi, tfr) : false;
+
+ /* Clear pending interrupts */
+ sun6i_spi_write(sspi, SUN6I_INT_STA_REG, ~0);
+@@ -463,7 +463,7 @@ static int sun6i_spi_transfer_one(struct
+ } else {
+ ret = sun6i_spi_prepare_dma(sspi, tfr);
+ if (ret) {
+- dev_warn(&master->dev,
++ dev_warn(&host->dev,
+ "%s: prepare DMA failed, ret=%d",
+ dev_name(&spi->dev), ret);
+ return ret;
+@@ -486,7 +486,7 @@ static int sun6i_spi_transfer_one(struct
+ reg = sun6i_spi_read(sspi, SUN6I_TFR_CTL_REG);
+ sun6i_spi_write(sspi, SUN6I_TFR_CTL_REG, reg | SUN6I_TFR_CTL_XCH);
+
+- tx_time = spi_controller_xfer_timeout(master, tfr);
++ tx_time = spi_controller_xfer_timeout(host, tfr);
+ start = jiffies;
+ timeout = wait_for_completion_timeout(&sspi->done,
+ msecs_to_jiffies(tx_time));
+@@ -502,13 +502,13 @@ static int sun6i_spi_transfer_one(struct
+ timeout = wait_for_completion_timeout(&sspi->dma_rx_done,
+ timeout);
+ if (!timeout)
+- dev_warn(&master->dev, "RX DMA timeout\n");
++ dev_warn(&host->dev, "RX DMA timeout\n");
+ }
+ }
+
+ end = jiffies;
+ if (!timeout) {
+- dev_warn(&master->dev,
++ dev_warn(&host->dev,
+ "%s: timeout transferring %u bytes@%iHz for %i(%i)ms",
+ dev_name(&spi->dev), tfr->len, tfr->speed_hz,
+ jiffies_to_msecs(end - start), tx_time);
+@@ -518,8 +518,8 @@ static int sun6i_spi_transfer_one(struct
+ sun6i_spi_write(sspi, SUN6I_INT_CTL_REG, 0);
+
+ if (ret && use_dma) {
+- dmaengine_terminate_sync(master->dma_rx);
+- dmaengine_terminate_sync(master->dma_tx);
++ dmaengine_terminate_sync(host->dma_rx);
++ dmaengine_terminate_sync(host->dma_tx);
+ }
+
+ return ret;
+@@ -564,8 +564,8 @@ static irqreturn_t sun6i_spi_handler(int
+
+ static int sun6i_spi_runtime_resume(struct device *dev)
+ {
+- struct spi_master *master = dev_get_drvdata(dev);
+- struct sun6i_spi *sspi = spi_master_get_devdata(master);
++ struct spi_controller *host = dev_get_drvdata(dev);
++ struct sun6i_spi *sspi = spi_controller_get_devdata(host);
+ int ret;
+
+ ret = clk_prepare_enable(sspi->hclk);
+@@ -601,8 +601,8 @@ out:
+
+ static int sun6i_spi_runtime_suspend(struct device *dev)
+ {
+- struct spi_master *master = dev_get_drvdata(dev);
+- struct sun6i_spi *sspi = spi_master_get_devdata(master);
++ struct spi_controller *host = dev_get_drvdata(dev);
++ struct sun6i_spi *sspi = spi_controller_get_devdata(host);
+
+ reset_control_assert(sspi->rstc);
+ clk_disable_unprepare(sspi->mclk);
+@@ -611,11 +611,11 @@ static int sun6i_spi_runtime_suspend(str
+ return 0;
+ }
+
+-static bool sun6i_spi_can_dma(struct spi_master *master,
++static bool sun6i_spi_can_dma(struct spi_controller *host,
+ struct spi_device *spi,
+ struct spi_transfer *xfer)
+ {
+- struct sun6i_spi *sspi = spi_master_get_devdata(master);
++ struct sun6i_spi *sspi = spi_controller_get_devdata(host);
+
+ /*
+ * If the number of spi words to transfer is less or equal than
+@@ -627,67 +627,67 @@ static bool sun6i_spi_can_dma(struct spi
+
+ static int sun6i_spi_probe(struct platform_device *pdev)
+ {
+- struct spi_master *master;
++ struct spi_controller *host;
+ struct sun6i_spi *sspi;
+ struct resource *mem;
+ int ret = 0, irq;
+
+- master = spi_alloc_master(&pdev->dev, sizeof(struct sun6i_spi));
+- if (!master) {
+- dev_err(&pdev->dev, "Unable to allocate SPI Master\n");
++ host = spi_alloc_host(&pdev->dev, sizeof(struct sun6i_spi));
++ if (!host) {
++ dev_err(&pdev->dev, "Unable to allocate SPI Host\n");
+ return -ENOMEM;
+ }
+
+- platform_set_drvdata(pdev, master);
+- sspi = spi_master_get_devdata(master);
++ platform_set_drvdata(pdev, host);
++ sspi = spi_controller_get_devdata(host);
+
+ sspi->base_addr = devm_platform_get_and_ioremap_resource(pdev, 0, &mem);
+ if (IS_ERR(sspi->base_addr)) {
+ ret = PTR_ERR(sspi->base_addr);
+- goto err_free_master;
++ goto err_free_host;
+ }
+
+ irq = platform_get_irq(pdev, 0);
+ if (irq < 0) {
+ ret = -ENXIO;
+- goto err_free_master;
++ goto err_free_host;
+ }
+
+ ret = devm_request_irq(&pdev->dev, irq, sun6i_spi_handler,
+ 0, "sun6i-spi", sspi);
+ if (ret) {
+ dev_err(&pdev->dev, "Cannot request IRQ\n");
+- goto err_free_master;
++ goto err_free_host;
+ }
+
+- sspi->master = master;
++ sspi->host = host;
+ sspi->cfg = of_device_get_match_data(&pdev->dev);
+
+- master->max_speed_hz = 100 * 1000 * 1000;
+- master->min_speed_hz = 3 * 1000;
+- master->use_gpio_descriptors = true;
+- master->set_cs = sun6i_spi_set_cs;
+- master->transfer_one = sun6i_spi_transfer_one;
+- master->num_chipselect = 4;
+- master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH | SPI_LSB_FIRST |
+- sspi->cfg->mode_bits;
+- master->bits_per_word_mask = SPI_BPW_MASK(8);
+- master->dev.of_node = pdev->dev.of_node;
+- master->auto_runtime_pm = true;
+- master->max_transfer_size = sun6i_spi_max_transfer_size;
++ host->max_speed_hz = 100 * 1000 * 1000;
++ host->min_speed_hz = 3 * 1000;
++ host->use_gpio_descriptors = true;
++ host->set_cs = sun6i_spi_set_cs;
++ host->transfer_one = sun6i_spi_transfer_one;
++ host->num_chipselect = 4;
++ host->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH | SPI_LSB_FIRST |
++ sspi->cfg->mode_bits;
++ host->bits_per_word_mask = SPI_BPW_MASK(8);
++ host->dev.of_node = pdev->dev.of_node;
++ host->auto_runtime_pm = true;
++ host->max_transfer_size = sun6i_spi_max_transfer_size;
+
+ sspi->hclk = devm_clk_get(&pdev->dev, "ahb");
+ if (IS_ERR(sspi->hclk)) {
+ dev_err(&pdev->dev, "Unable to acquire AHB clock\n");
+ ret = PTR_ERR(sspi->hclk);
+- goto err_free_master;
++ goto err_free_host;
+ }
+
+ sspi->mclk = devm_clk_get(&pdev->dev, "mod");
+ if (IS_ERR(sspi->mclk)) {
+ dev_err(&pdev->dev, "Unable to acquire module clock\n");
+ ret = PTR_ERR(sspi->mclk);
+- goto err_free_master;
++ goto err_free_host;
+ }
+
+ init_completion(&sspi->done);
+@@ -697,34 +697,34 @@ static int sun6i_spi_probe(struct platfo
+ if (IS_ERR(sspi->rstc)) {
+ dev_err(&pdev->dev, "Couldn't get reset controller\n");
+ ret = PTR_ERR(sspi->rstc);
+- goto err_free_master;
++ goto err_free_host;
+ }
+
+- master->dma_tx = dma_request_chan(&pdev->dev, "tx");
+- if (IS_ERR(master->dma_tx)) {
++ host->dma_tx = dma_request_chan(&pdev->dev, "tx");
++ if (IS_ERR(host->dma_tx)) {
+ /* Check tx to see if we need defer probing driver */
+- if (PTR_ERR(master->dma_tx) == -EPROBE_DEFER) {
++ if (PTR_ERR(host->dma_tx) == -EPROBE_DEFER) {
+ ret = -EPROBE_DEFER;
+- goto err_free_master;
++ goto err_free_host;
+ }
+ dev_warn(&pdev->dev, "Failed to request TX DMA channel\n");
+- master->dma_tx = NULL;
++ host->dma_tx = NULL;
+ }
+
+- master->dma_rx = dma_request_chan(&pdev->dev, "rx");
+- if (IS_ERR(master->dma_rx)) {
+- if (PTR_ERR(master->dma_rx) == -EPROBE_DEFER) {
++ host->dma_rx = dma_request_chan(&pdev->dev, "rx");
++ if (IS_ERR(host->dma_rx)) {
++ if (PTR_ERR(host->dma_rx) == -EPROBE_DEFER) {
+ ret = -EPROBE_DEFER;
+ goto err_free_dma_tx;
+ }
+ dev_warn(&pdev->dev, "Failed to request RX DMA channel\n");
+- master->dma_rx = NULL;
++ host->dma_rx = NULL;
+ }
+
+- if (master->dma_tx && master->dma_rx) {
++ if (host->dma_tx && host->dma_rx) {
+ sspi->dma_addr_tx = mem->start + SUN6I_TXDATA_REG;
+ sspi->dma_addr_rx = mem->start + SUN6I_RXDATA_REG;
+- master->can_dma = sun6i_spi_can_dma;
++ host->can_dma = sun6i_spi_can_dma;
+ }
+
+ /*
+@@ -742,9 +742,9 @@ static int sun6i_spi_probe(struct platfo
+ pm_runtime_set_active(&pdev->dev);
+ pm_runtime_enable(&pdev->dev);
+
+- ret = devm_spi_register_master(&pdev->dev, master);
++ ret = devm_spi_register_controller(&pdev->dev, host);
+ if (ret) {
+- dev_err(&pdev->dev, "cannot register SPI master\n");
++ dev_err(&pdev->dev, "cannot register SPI host\n");
+ goto err_pm_disable;
+ }
+
+@@ -754,26 +754,26 @@ err_pm_disable:
+ pm_runtime_disable(&pdev->dev);
+ sun6i_spi_runtime_suspend(&pdev->dev);
+ err_free_dma_rx:
+- if (master->dma_rx)
+- dma_release_channel(master->dma_rx);
++ if (host->dma_rx)
++ dma_release_channel(host->dma_rx);
+ err_free_dma_tx:
+- if (master->dma_tx)
+- dma_release_channel(master->dma_tx);
+-err_free_master:
+- spi_master_put(master);
++ if (host->dma_tx)
++ dma_release_channel(host->dma_tx);
++err_free_host:
++ spi_controller_put(host);
+ return ret;
+ }
+
+ static void sun6i_spi_remove(struct platform_device *pdev)
+ {
+- struct spi_master *master = platform_get_drvdata(pdev);
++ struct spi_controller *host = platform_get_drvdata(pdev);
+
+ pm_runtime_force_suspend(&pdev->dev);
+
+- if (master->dma_tx)
+- dma_release_channel(master->dma_tx);
+- if (master->dma_rx)
+- dma_release_channel(master->dma_rx);
++ if (host->dma_tx)
++ dma_release_channel(host->dma_tx);
++ if (host->dma_rx)
++ dma_release_channel(host->dma_rx);
+ }
+
+ static const struct sun6i_spi_cfg sun6i_a31_spi_cfg = {
--- /dev/null
+From stable+bounces-246969-greg=kroah.com@vger.kernel.org Wed May 13 19:42:05 2026
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 13 May 2026 13:31:54 -0400
+Subject: spi: syncuacer: fix controller deregistration
+To: stable@vger.kernel.org
+Cc: Johan Hovold <johan@kernel.org>, Masahisa Kojima <masahisa.kojima@linaro.org>, Mark Brown <broonie@kernel.org>, Sasha Levin <sashal@kernel.org>
+Message-ID: <20260513173154.3886494-2-sashal@kernel.org>
+
+From: Johan Hovold <johan@kernel.org>
+
+[ Upstream commit 75d849c3452e9611de031db45b3149ba9a99035f ]
+
+Make sure to deregister the controller before disabling underlying
+resources like clocks during driver unbind.
+
+Fixes: b0823ee35cf9 ("spi: Add spi driver for Socionext SynQuacer platform")
+Cc: stable@vger.kernel.org # 5.3
+Cc: Masahisa Kojima <masahisa.kojima@linaro.org>
+Signed-off-by: Johan Hovold <johan@kernel.org>
+Link: https://patch.msgid.link/20260410081757.503099-21-johan@kernel.org
+Signed-off-by: Mark Brown <broonie@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/spi/spi-synquacer.c | 8 +++++++-
+ 1 file changed, 7 insertions(+), 1 deletion(-)
+
+--- a/drivers/spi/spi-synquacer.c
++++ b/drivers/spi/spi-synquacer.c
+@@ -719,7 +719,7 @@ static int synquacer_spi_probe(struct pl
+ pm_runtime_set_active(sspi->dev);
+ pm_runtime_enable(sspi->dev);
+
+- ret = devm_spi_register_controller(sspi->dev, host);
++ ret = spi_register_controller(host);
+ if (ret)
+ goto disable_pm;
+
+@@ -740,9 +740,15 @@ static void synquacer_spi_remove(struct
+ struct spi_controller *host = platform_get_drvdata(pdev);
+ struct synquacer_spi *sspi = spi_controller_get_devdata(host);
+
++ spi_controller_get(host);
++
++ spi_unregister_controller(host);
++
+ pm_runtime_disable(sspi->dev);
+
+ clk_disable_unprepare(sspi->clk);
++
++ spi_controller_put(host);
+ }
+
+ static int __maybe_unused synquacer_spi_suspend(struct device *dev)
--- /dev/null
+From stable+bounces-246968-greg=kroah.com@vger.kernel.org Wed May 13 19:32:28 2026
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 13 May 2026 13:31:53 -0400
+Subject: spi: synquacer: switch to use modern name
+To: stable@vger.kernel.org
+Cc: Yang Yingliang <yangyingliang@huawei.com>, Mark Brown <broonie@kernel.org>, Sasha Levin <sashal@kernel.org>
+Message-ID: <20260513173154.3886494-1-sashal@kernel.org>
+
+From: Yang Yingliang <yangyingliang@huawei.com>
+
+[ Upstream commit 3524d1b727a66712f02f92807219a3650e5cf910 ]
+
+Change legacy name master to modern name host or controller.
+
+No functional changed.
+
+Signed-off-by: Yang Yingliang <yangyingliang@huawei.com>
+Link: https://msgid.link/r/20231128093031.3707034-10-yangyingliang@huawei.com
+Signed-off-by: Mark Brown <broonie@kernel.org>
+Stable-dep-of: 75d849c3452e ("spi: syncuacer: fix controller deregistration")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/spi/spi-synquacer.c | 84 ++++++++++++++++++++++----------------------
+ 1 file changed, 42 insertions(+), 42 deletions(-)
+
+--- a/drivers/spi/spi-synquacer.c
++++ b/drivers/spi/spi-synquacer.c
+@@ -225,11 +225,11 @@ static int write_fifo(struct synquacer_s
+ return 0;
+ }
+
+-static int synquacer_spi_config(struct spi_master *master,
++static int synquacer_spi_config(struct spi_controller *host,
+ struct spi_device *spi,
+ struct spi_transfer *xfer)
+ {
+- struct synquacer_spi *sspi = spi_master_get_devdata(master);
++ struct synquacer_spi *sspi = spi_controller_get_devdata(host);
+ unsigned int speed, mode, bpw, cs, bus_width, transfer_mode;
+ u32 rate, val, div;
+
+@@ -263,7 +263,7 @@ static int synquacer_spi_config(struct s
+ }
+
+ sspi->transfer_mode = transfer_mode;
+- rate = master->max_speed_hz;
++ rate = host->max_speed_hz;
+
+ div = DIV_ROUND_UP(rate, speed);
+ if (div > 254) {
+@@ -350,11 +350,11 @@ static int synquacer_spi_config(struct s
+ return 0;
+ }
+
+-static int synquacer_spi_transfer_one(struct spi_master *master,
++static int synquacer_spi_transfer_one(struct spi_controller *host,
+ struct spi_device *spi,
+ struct spi_transfer *xfer)
+ {
+- struct synquacer_spi *sspi = spi_master_get_devdata(master);
++ struct synquacer_spi *sspi = spi_controller_get_devdata(host);
+ int ret;
+ int status = 0;
+ u32 words;
+@@ -378,7 +378,7 @@ static int synquacer_spi_transfer_one(st
+ if (bpw == 8 && !(xfer->len % 4) && !(spi->mode & SPI_LSB_FIRST))
+ xfer->bits_per_word = 32;
+
+- ret = synquacer_spi_config(master, spi, xfer);
++ ret = synquacer_spi_config(host, spi, xfer);
+
+ /* restore */
+ xfer->bits_per_word = bpw;
+@@ -482,7 +482,7 @@ static int synquacer_spi_transfer_one(st
+
+ static void synquacer_spi_set_cs(struct spi_device *spi, bool enable)
+ {
+- struct synquacer_spi *sspi = spi_master_get_devdata(spi->master);
++ struct synquacer_spi *sspi = spi_controller_get_devdata(spi->controller);
+ u32 val;
+
+ val = readl(sspi->regs + SYNQUACER_HSSPI_REG_DMSTART);
+@@ -517,11 +517,11 @@ static int synquacer_spi_wait_status_upd
+ return -EBUSY;
+ }
+
+-static int synquacer_spi_enable(struct spi_master *master)
++static int synquacer_spi_enable(struct spi_controller *host)
+ {
+ u32 val;
+ int status;
+- struct synquacer_spi *sspi = spi_master_get_devdata(master);
++ struct synquacer_spi *sspi = spi_controller_get_devdata(host);
+
+ /* Disable module */
+ writel(0, sspi->regs + SYNQUACER_HSSPI_REG_MCTRL);
+@@ -601,18 +601,18 @@ static irqreturn_t sq_spi_tx_handler(int
+ static int synquacer_spi_probe(struct platform_device *pdev)
+ {
+ struct device_node *np = pdev->dev.of_node;
+- struct spi_master *master;
++ struct spi_controller *host;
+ struct synquacer_spi *sspi;
+ int ret;
+ int rx_irq, tx_irq;
+
+- master = spi_alloc_master(&pdev->dev, sizeof(*sspi));
+- if (!master)
++ host = spi_alloc_host(&pdev->dev, sizeof(*sspi));
++ if (!host)
+ return -ENOMEM;
+
+- platform_set_drvdata(pdev, master);
++ platform_set_drvdata(pdev, host);
+
+- sspi = spi_master_get_devdata(master);
++ sspi = spi_controller_get_devdata(host);
+ sspi->dev = &pdev->dev;
+
+ init_completion(&sspi->transfer_done);
+@@ -625,7 +625,7 @@ static int synquacer_spi_probe(struct pl
+
+ sspi->clk_src_type = SYNQUACER_HSSPI_CLOCK_SRC_IHCLK; /* Default */
+ device_property_read_u32(&pdev->dev, "socionext,ihclk-rate",
+- &master->max_speed_hz); /* for ACPI */
++ &host->max_speed_hz); /* for ACPI */
+
+ if (dev_of_node(&pdev->dev)) {
+ if (device_property_match_string(&pdev->dev,
+@@ -655,21 +655,21 @@ static int synquacer_spi_probe(struct pl
+ goto put_spi;
+ }
+
+- master->max_speed_hz = clk_get_rate(sspi->clk);
++ host->max_speed_hz = clk_get_rate(sspi->clk);
+ }
+
+- if (!master->max_speed_hz) {
++ if (!host->max_speed_hz) {
+ dev_err(&pdev->dev, "missing clock source\n");
+ ret = -EINVAL;
+ goto disable_clk;
+ }
+- master->min_speed_hz = master->max_speed_hz / 254;
++ host->min_speed_hz = host->max_speed_hz / 254;
+
+ sspi->aces = device_property_read_bool(&pdev->dev,
+ "socionext,set-aces");
+ sspi->rtm = device_property_read_bool(&pdev->dev, "socionext,use-rtm");
+
+- master->num_chipselect = SYNQUACER_HSSPI_NUM_CHIP_SELECT;
++ host->num_chipselect = SYNQUACER_HSSPI_NUM_CHIP_SELECT;
+
+ rx_irq = platform_get_irq(pdev, 0);
+ if (rx_irq <= 0) {
+@@ -699,27 +699,27 @@ static int synquacer_spi_probe(struct pl
+ goto disable_clk;
+ }
+
+- master->dev.of_node = np;
+- master->dev.fwnode = pdev->dev.fwnode;
+- master->auto_runtime_pm = true;
+- master->bus_num = pdev->id;
+-
+- master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_TX_DUAL | SPI_RX_DUAL |
+- SPI_TX_QUAD | SPI_RX_QUAD;
+- master->bits_per_word_mask = SPI_BPW_MASK(32) | SPI_BPW_MASK(24) |
+- SPI_BPW_MASK(16) | SPI_BPW_MASK(8);
++ host->dev.of_node = np;
++ host->dev.fwnode = pdev->dev.fwnode;
++ host->auto_runtime_pm = true;
++ host->bus_num = pdev->id;
++
++ host->mode_bits = SPI_CPOL | SPI_CPHA | SPI_TX_DUAL | SPI_RX_DUAL |
++ SPI_TX_QUAD | SPI_RX_QUAD;
++ host->bits_per_word_mask = SPI_BPW_MASK(32) | SPI_BPW_MASK(24) |
++ SPI_BPW_MASK(16) | SPI_BPW_MASK(8);
+
+- master->set_cs = synquacer_spi_set_cs;
+- master->transfer_one = synquacer_spi_transfer_one;
++ host->set_cs = synquacer_spi_set_cs;
++ host->transfer_one = synquacer_spi_transfer_one;
+
+- ret = synquacer_spi_enable(master);
++ ret = synquacer_spi_enable(host);
+ if (ret)
+ goto disable_clk;
+
+ pm_runtime_set_active(sspi->dev);
+ pm_runtime_enable(sspi->dev);
+
+- ret = devm_spi_register_master(sspi->dev, master);
++ ret = devm_spi_register_controller(sspi->dev, host);
+ if (ret)
+ goto disable_pm;
+
+@@ -730,15 +730,15 @@ disable_pm:
+ disable_clk:
+ clk_disable_unprepare(sspi->clk);
+ put_spi:
+- spi_master_put(master);
++ spi_controller_put(host);
+
+ return ret;
+ }
+
+ static void synquacer_spi_remove(struct platform_device *pdev)
+ {
+- struct spi_master *master = platform_get_drvdata(pdev);
+- struct synquacer_spi *sspi = spi_master_get_devdata(master);
++ struct spi_controller *host = platform_get_drvdata(pdev);
++ struct synquacer_spi *sspi = spi_controller_get_devdata(host);
+
+ pm_runtime_disable(sspi->dev);
+
+@@ -747,11 +747,11 @@ static void synquacer_spi_remove(struct
+
+ static int __maybe_unused synquacer_spi_suspend(struct device *dev)
+ {
+- struct spi_master *master = dev_get_drvdata(dev);
+- struct synquacer_spi *sspi = spi_master_get_devdata(master);
++ struct spi_controller *host = dev_get_drvdata(dev);
++ struct synquacer_spi *sspi = spi_controller_get_devdata(host);
+ int ret;
+
+- ret = spi_master_suspend(master);
++ ret = spi_controller_suspend(host);
+ if (ret)
+ return ret;
+
+@@ -763,8 +763,8 @@ static int __maybe_unused synquacer_spi_
+
+ static int __maybe_unused synquacer_spi_resume(struct device *dev)
+ {
+- struct spi_master *master = dev_get_drvdata(dev);
+- struct synquacer_spi *sspi = spi_master_get_devdata(master);
++ struct spi_controller *host = dev_get_drvdata(dev);
++ struct synquacer_spi *sspi = spi_controller_get_devdata(host);
+ int ret;
+
+ if (!pm_runtime_suspended(dev)) {
+@@ -778,7 +778,7 @@ static int __maybe_unused synquacer_spi_
+ return ret;
+ }
+
+- ret = synquacer_spi_enable(master);
++ ret = synquacer_spi_enable(host);
+ if (ret) {
+ clk_disable_unprepare(sspi->clk);
+ dev_err(dev, "failed to enable spi (%d)\n", ret);
+@@ -786,7 +786,7 @@ static int __maybe_unused synquacer_spi_
+ }
+ }
+
+- ret = spi_master_resume(master);
++ ret = spi_controller_resume(host);
+ if (ret < 0)
+ clk_disable_unprepare(sspi->clk);
+
--- /dev/null
+From stable+bounces-247112-greg=kroah.com@vger.kernel.org Thu May 14 06:59:29 2026
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 14 May 2026 00:59:22 -0400
+Subject: spi: tegra114: fix controller deregistration
+To: stable@vger.kernel.org
+Cc: Johan Hovold <johan@kernel.org>, Jingoo Han <jg1.han@samsung.com>, Mark Brown <broonie@kernel.org>, Sasha Levin <sashal@kernel.org>
+Message-ID: <20260514045922.25250-1-sashal@kernel.org>
+
+From: Johan Hovold <johan@kernel.org>
+
+[ 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 <jg1.han@samsung.com>
+Signed-off-by: Johan Hovold <johan@kernel.org>
+Link: https://patch.msgid.link/20260410081757.503099-22-johan@kernel.org
+Signed-off-by: Mark Brown <broonie@kernel.org>
+[ renamed spi_controller/host API calls to spi_master/master equivalents ]
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ 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
+ }
+
+ master->dev.of_node = pdev->dev.of_node;
+- ret = devm_spi_register_master(&pdev->dev, master);
++ ret = spi_register_master(master);
+ if (ret < 0) {
+ dev_err(&pdev->dev, "can not register to master err %d\n", ret);
+ goto exit_free_irq;
+@@ -1442,6 +1442,10 @@ static void tegra_spi_remove(struct plat
+ struct spi_master *master = platform_get_drvdata(pdev);
+ struct tegra_spi_data *tspi = spi_master_get_devdata(master);
+
++ spi_master_get(master);
++
++ spi_unregister_master(master);
++
+ 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_master_put(master);
+ }
+
+ #ifdef CONFIG_PM_SLEEP
--- /dev/null
+From stable+bounces-247113-greg=kroah.com@vger.kernel.org Thu May 14 06:59:42 2026
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 14 May 2026 00:59:34 -0400
+Subject: spi: tegra20-sflash: fix controller deregistration
+To: stable@vger.kernel.org
+Cc: Johan Hovold <johan@kernel.org>, Jingoo Han <jg1.han@samsung.com>, Mark Brown <broonie@kernel.org>, Sasha Levin <sashal@kernel.org>
+Message-ID: <20260514045934.26261-1-sashal@kernel.org>
+
+From: Johan Hovold <johan@kernel.org>
+
+[ 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 <jg1.han@samsung.com>
+Signed-off-by: Johan Hovold <johan@kernel.org>
+Link: https://patch.msgid.link/20260410081757.503099-23-johan@kernel.org
+Signed-off-by: Mark Brown <broonie@kernel.org>
+[ translated spi_controller/host API to legacy spi_master/master naming and dropped devm-managed registration ]
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ 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);
+
+ master->dev.of_node = pdev->dev.of_node;
+- ret = devm_spi_register_master(&pdev->dev, master);
++ ret = spi_register_master(master);
+ if (ret < 0) {
+ dev_err(&pdev->dev, "can not register to master err %d\n", ret);
+ goto exit_pm_disable;
+@@ -529,11 +529,17 @@ static void tegra_sflash_remove(struct p
+ struct spi_master *master = platform_get_drvdata(pdev);
+ struct tegra_sflash_data *tsd = spi_master_get_devdata(master);
+
++ spi_master_get(master);
++
++ spi_unregister_master(master);
++
+ free_irq(tsd->irq, tsd);
+
+ pm_runtime_disable(&pdev->dev);
+ if (!pm_runtime_status_suspended(&pdev->dev))
+ tegra_sflash_runtime_suspend(&pdev->dev);
++
++ spi_master_put(master);
+ }
+
+ #ifdef CONFIG_PM_SLEEP
--- /dev/null
+From stable+bounces-246997-greg=kroah.com@vger.kernel.org Wed May 13 20:10:45 2026
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 13 May 2026 14:08:42 -0400
+Subject: spi: ti-qspi: fix controller deregistration
+To: stable@vger.kernel.org
+Cc: Johan Hovold <johan@kernel.org>, Sebastian Andrzej Siewior <bigeasy@linutronix.de>, Mark Brown <broonie@kernel.org>, Sasha Levin <sashal@kernel.org>
+Message-ID: <20260513180842.3912849-3-sashal@kernel.org>
+
+From: Johan Hovold <johan@kernel.org>
+
+[ Upstream commit 0c18a1bacbb1d8b8aa34d3d004a2cb8226c8b1ea ]
+
+Make sure to deregister the controller before disabling underlying
+resources like clocks during driver unbind.
+
+Note that the controller is suspended before disabling and releasing
+resources since commit 3ac066e2227c ("spi: spi-ti-qspi: Suspend the
+queue before removing the device") which avoids issues like unclocked
+accesses but prevents SPI device drivers from doing I/O during
+deregistration.
+
+Fixes: 3b3a80019ff1 ("spi: ti-qspi: one only one interrupt handler")
+Cc: stable@vger.kernel.org # 3.13
+Cc: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
+Signed-off-by: Johan Hovold <johan@kernel.org>
+Link: https://patch.msgid.link/20260410081757.503099-24-johan@kernel.org
+Signed-off-by: Mark Brown <broonie@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/spi/spi-ti-qspi.c | 14 ++++++--------
+ 1 file changed, 6 insertions(+), 8 deletions(-)
+
+--- a/drivers/spi/spi-ti-qspi.c
++++ b/drivers/spi/spi-ti-qspi.c
+@@ -895,7 +895,7 @@ no_dma:
+ qspi->mmap_enabled = false;
+ qspi->current_cs = -1;
+
+- ret = devm_spi_register_controller(&pdev->dev, host);
++ ret = spi_register_controller(host);
+ if (!ret)
+ return 0;
+
+@@ -910,19 +910,17 @@ free_host:
+ static void ti_qspi_remove(struct platform_device *pdev)
+ {
+ struct ti_qspi *qspi = platform_get_drvdata(pdev);
+- int rc;
+
+- rc = spi_controller_suspend(qspi->host);
+- if (rc) {
+- dev_alert(&pdev->dev, "spi_controller_suspend() failed (%pe)\n",
+- ERR_PTR(rc));
+- return;
+- }
++ spi_controller_get(qspi->host);
++
++ spi_unregister_controller(qspi->host);
+
+ pm_runtime_put_sync(&pdev->dev);
+ pm_runtime_disable(&pdev->dev);
+
+ ti_qspi_dma_cleanup(qspi);
++
++ spi_controller_put(qspi->host);
+ }
+
+ static const struct dev_pm_ops ti_qspi_pm_ops = {
--- /dev/null
+From stable+bounces-247177-greg=kroah.com@vger.kernel.org Thu May 14 13:46:41 2026
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 14 May 2026 07:46:35 -0400
+Subject: spi: uniphier: fix controller deregistration
+To: stable@vger.kernel.org
+Cc: Johan Hovold <johan@kernel.org>, Keiji Hayashibara <hayashibara.keiji@socionext.com>, Mark Brown <broonie@kernel.org>, Sasha Levin <sashal@kernel.org>
+Message-ID: <20260514114635.181243-3-sashal@kernel.org>
+
+From: Johan Hovold <johan@kernel.org>
+
+[ 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 <hayashibara.keiji@socionext.com>
+Signed-off-by: Johan Hovold <johan@kernel.org>
+Link: https://patch.msgid.link/20260410081757.503099-25-johan@kernel.org
+Signed-off-by: Mark Brown <broonie@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ 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[] = {
--- /dev/null
+From stable+bounces-247176-greg=kroah.com@vger.kernel.org Thu May 14 13:46:42 2026
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 14 May 2026 07:46:34 -0400
+Subject: spi: uniphier: Simplify clock handling with devm_clk_get_enabled()
+To: stable@vger.kernel.org
+Cc: Pei Xiao <xiaopei01@kylinos.cn>, Kunihiko Hayashi <hayashi.kunihiko@socionext.com>, Mark Brown <broonie@kernel.org>, Sasha Levin <sashal@kernel.org>
+Message-ID: <20260514114635.181243-2-sashal@kernel.org>
+
+From: Pei Xiao <xiaopei01@kylinos.cn>
+
+[ 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 <xiaopei01@kylinos.cn>
+Reviewed-by: Kunihiko Hayashi <hayashi.kunihiko@socionext.com>
+Link: https://patch.msgid.link/b2deeefd4ef1a4bce71116aabfcb7e81400f6d37.1775546948.git.xiaopei01@kylinos.cn
+Signed-off-by: Mark Brown <broonie@kernel.org>
+Stable-dep-of: 0245435f7772 ("spi: uniphier: fix controller deregistration")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ 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[] = {
--- /dev/null
+From stable+bounces-247175-greg=kroah.com@vger.kernel.org Thu May 14 13:46:42 2026
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 14 May 2026 07:46:33 -0400
+Subject: spi: uniphier: switch to use modern name
+To: stable@vger.kernel.org
+Cc: Yang Yingliang <yangyingliang@huawei.com>, Mark Brown <broonie@kernel.org>, Sasha Levin <sashal@kernel.org>
+Message-ID: <20260514114635.181243-1-sashal@kernel.org>
+
+From: Yang Yingliang <yangyingliang@huawei.com>
+
+[ Upstream commit 4c2ee0991013ca8a32bb093a017d460204790112 ]
+
+Change legacy name master to modern name host or controller.
+
+No functional changed.
+
+Signed-off-by: Yang Yingliang <yangyingliang@huawei.com>
+Link: https://msgid.link/r/20231128093031.3707034-19-yangyingliang@huawei.com
+Signed-off-by: Mark Brown <broonie@kernel.org>
+Stable-dep-of: 0245435f7772 ("spi: uniphier: fix controller deregistration")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/spi/spi-uniphier.c | 198 ++++++++++++++++++++++-----------------------
+ 1 file changed, 99 insertions(+), 99 deletions(-)
+
+--- a/drivers/spi/spi-uniphier.c
++++ b/drivers/spi/spi-uniphier.c
+@@ -26,7 +26,7 @@ struct uniphier_spi_priv {
+ void __iomem *base;
+ dma_addr_t base_dma_addr;
+ struct clk *clk;
+- struct spi_master *master;
++ struct spi_controller *host;
+ struct completion xfer_done;
+
+ int error;
+@@ -127,7 +127,7 @@ static inline void uniphier_spi_irq_disa
+
+ static void uniphier_spi_set_mode(struct spi_device *spi)
+ {
+- struct uniphier_spi_priv *priv = spi_master_get_devdata(spi->master);
++ struct uniphier_spi_priv *priv = spi_controller_get_devdata(spi->controller);
+ u32 val1, val2;
+
+ /*
+@@ -180,7 +180,7 @@ static void uniphier_spi_set_mode(struct
+
+ static void uniphier_spi_set_transfer_size(struct spi_device *spi, int size)
+ {
+- struct uniphier_spi_priv *priv = spi_master_get_devdata(spi->master);
++ struct uniphier_spi_priv *priv = spi_controller_get_devdata(spi->controller);
+ u32 val;
+
+ val = readl(priv->base + SSI_TXWDS);
+@@ -198,7 +198,7 @@ static void uniphier_spi_set_transfer_si
+ static void uniphier_spi_set_baudrate(struct spi_device *spi,
+ unsigned int speed)
+ {
+- struct uniphier_spi_priv *priv = spi_master_get_devdata(spi->master);
++ struct uniphier_spi_priv *priv = spi_controller_get_devdata(spi->controller);
+ u32 val, ckdiv;
+
+ /*
+@@ -217,7 +217,7 @@ static void uniphier_spi_set_baudrate(st
+ static void uniphier_spi_setup_transfer(struct spi_device *spi,
+ struct spi_transfer *t)
+ {
+- struct uniphier_spi_priv *priv = spi_master_get_devdata(spi->master);
++ struct uniphier_spi_priv *priv = spi_controller_get_devdata(spi->controller);
+ u32 val;
+
+ priv->error = 0;
+@@ -333,7 +333,7 @@ static void uniphier_spi_fill_tx_fifo(st
+
+ static void uniphier_spi_set_cs(struct spi_device *spi, bool enable)
+ {
+- struct uniphier_spi_priv *priv = spi_master_get_devdata(spi->master);
++ struct uniphier_spi_priv *priv = spi_controller_get_devdata(spi->controller);
+ u32 val;
+
+ val = readl(priv->base + SSI_FPS);
+@@ -346,16 +346,16 @@ static void uniphier_spi_set_cs(struct s
+ writel(val, priv->base + SSI_FPS);
+ }
+
+-static bool uniphier_spi_can_dma(struct spi_master *master,
++static bool uniphier_spi_can_dma(struct spi_controller *host,
+ struct spi_device *spi,
+ struct spi_transfer *t)
+ {
+- struct uniphier_spi_priv *priv = spi_master_get_devdata(master);
++ struct uniphier_spi_priv *priv = spi_controller_get_devdata(host);
+ unsigned int bpw = bytes_per_word(priv->bits_per_word);
+
+- if ((!master->dma_tx && !master->dma_rx)
+- || (!master->dma_tx && t->tx_buf)
+- || (!master->dma_rx && t->rx_buf))
++ if ((!host->dma_tx && !host->dma_rx)
++ || (!host->dma_tx && t->tx_buf)
++ || (!host->dma_rx && t->rx_buf))
+ return false;
+
+ return DIV_ROUND_UP(t->len, bpw) > SSI_FIFO_DEPTH;
+@@ -363,33 +363,33 @@ static bool uniphier_spi_can_dma(struct
+
+ static void uniphier_spi_dma_rxcb(void *data)
+ {
+- struct spi_master *master = data;
+- struct uniphier_spi_priv *priv = spi_master_get_devdata(master);
++ struct spi_controller *host = data;
++ struct uniphier_spi_priv *priv = spi_controller_get_devdata(host);
+ int state = atomic_fetch_andnot(SSI_DMA_RX_BUSY, &priv->dma_busy);
+
+ uniphier_spi_irq_disable(priv, SSI_IE_RXRE);
+
+ if (!(state & SSI_DMA_TX_BUSY))
+- spi_finalize_current_transfer(master);
++ spi_finalize_current_transfer(host);
+ }
+
+ static void uniphier_spi_dma_txcb(void *data)
+ {
+- struct spi_master *master = data;
+- struct uniphier_spi_priv *priv = spi_master_get_devdata(master);
++ struct spi_controller *host = data;
++ struct uniphier_spi_priv *priv = spi_controller_get_devdata(host);
+ int state = atomic_fetch_andnot(SSI_DMA_TX_BUSY, &priv->dma_busy);
+
+ uniphier_spi_irq_disable(priv, SSI_IE_TXRE);
+
+ if (!(state & SSI_DMA_RX_BUSY))
+- spi_finalize_current_transfer(master);
++ spi_finalize_current_transfer(host);
+ }
+
+-static int uniphier_spi_transfer_one_dma(struct spi_master *master,
++static int uniphier_spi_transfer_one_dma(struct spi_controller *host,
+ struct spi_device *spi,
+ struct spi_transfer *t)
+ {
+- struct uniphier_spi_priv *priv = spi_master_get_devdata(master);
++ struct uniphier_spi_priv *priv = spi_controller_get_devdata(host);
+ struct dma_async_tx_descriptor *rxdesc = NULL, *txdesc = NULL;
+ int buswidth;
+
+@@ -412,23 +412,23 @@ static int uniphier_spi_transfer_one_dma
+ .src_maxburst = SSI_FIFO_BURST_NUM,
+ };
+
+- dmaengine_slave_config(master->dma_rx, &rxconf);
++ dmaengine_slave_config(host->dma_rx, &rxconf);
+
+ rxdesc = dmaengine_prep_slave_sg(
+- master->dma_rx,
++ host->dma_rx,
+ t->rx_sg.sgl, t->rx_sg.nents,
+ DMA_DEV_TO_MEM, DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
+ if (!rxdesc)
+ goto out_err_prep;
+
+ rxdesc->callback = uniphier_spi_dma_rxcb;
+- rxdesc->callback_param = master;
++ rxdesc->callback_param = host;
+
+ uniphier_spi_irq_enable(priv, SSI_IE_RXRE);
+ atomic_or(SSI_DMA_RX_BUSY, &priv->dma_busy);
+
+ dmaengine_submit(rxdesc);
+- dma_async_issue_pending(master->dma_rx);
++ dma_async_issue_pending(host->dma_rx);
+ }
+
+ if (priv->tx_buf) {
+@@ -439,23 +439,23 @@ static int uniphier_spi_transfer_one_dma
+ .dst_maxburst = SSI_FIFO_BURST_NUM,
+ };
+
+- dmaengine_slave_config(master->dma_tx, &txconf);
++ dmaengine_slave_config(host->dma_tx, &txconf);
+
+ txdesc = dmaengine_prep_slave_sg(
+- master->dma_tx,
++ host->dma_tx,
+ t->tx_sg.sgl, t->tx_sg.nents,
+ DMA_MEM_TO_DEV, DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
+ if (!txdesc)
+ goto out_err_prep;
+
+ txdesc->callback = uniphier_spi_dma_txcb;
+- txdesc->callback_param = master;
++ txdesc->callback_param = host;
+
+ uniphier_spi_irq_enable(priv, SSI_IE_TXRE);
+ atomic_or(SSI_DMA_TX_BUSY, &priv->dma_busy);
+
+ dmaengine_submit(txdesc);
+- dma_async_issue_pending(master->dma_tx);
++ dma_async_issue_pending(host->dma_tx);
+ }
+
+ /* signal that we need to wait for completion */
+@@ -463,17 +463,17 @@ static int uniphier_spi_transfer_one_dma
+
+ out_err_prep:
+ if (rxdesc)
+- dmaengine_terminate_sync(master->dma_rx);
++ dmaengine_terminate_sync(host->dma_rx);
+
+ return -EINVAL;
+ }
+
+-static int uniphier_spi_transfer_one_irq(struct spi_master *master,
++static int uniphier_spi_transfer_one_irq(struct spi_controller *host,
+ struct spi_device *spi,
+ struct spi_transfer *t)
+ {
+- struct uniphier_spi_priv *priv = spi_master_get_devdata(master);
+- struct device *dev = master->dev.parent;
++ struct uniphier_spi_priv *priv = spi_controller_get_devdata(host);
++ struct device *dev = host->dev.parent;
+ unsigned long time_left;
+
+ reinit_completion(&priv->xfer_done);
+@@ -495,11 +495,11 @@ static int uniphier_spi_transfer_one_irq
+ return priv->error;
+ }
+
+-static int uniphier_spi_transfer_one_poll(struct spi_master *master,
++static int uniphier_spi_transfer_one_poll(struct spi_controller *host,
+ struct spi_device *spi,
+ struct spi_transfer *t)
+ {
+- struct uniphier_spi_priv *priv = spi_master_get_devdata(master);
++ struct uniphier_spi_priv *priv = spi_controller_get_devdata(host);
+ int loop = SSI_POLL_TIMEOUT_US * 10;
+
+ while (priv->tx_bytes) {
+@@ -520,14 +520,14 @@ static int uniphier_spi_transfer_one_pol
+ return 0;
+
+ irq_transfer:
+- return uniphier_spi_transfer_one_irq(master, spi, t);
++ return uniphier_spi_transfer_one_irq(host, spi, t);
+ }
+
+-static int uniphier_spi_transfer_one(struct spi_master *master,
++static int uniphier_spi_transfer_one(struct spi_controller *host,
+ struct spi_device *spi,
+ struct spi_transfer *t)
+ {
+- struct uniphier_spi_priv *priv = spi_master_get_devdata(master);
++ struct uniphier_spi_priv *priv = spi_controller_get_devdata(host);
+ unsigned long threshold;
+ bool use_dma;
+
+@@ -537,9 +537,9 @@ static int uniphier_spi_transfer_one(str
+
+ uniphier_spi_setup_transfer(spi, t);
+
+- use_dma = master->can_dma ? master->can_dma(master, spi, t) : false;
++ use_dma = host->can_dma ? host->can_dma(host, spi, t) : false;
+ if (use_dma)
+- return uniphier_spi_transfer_one_dma(master, spi, t);
++ return uniphier_spi_transfer_one_dma(host, spi, t);
+
+ /*
+ * If the transfer operation will take longer than
+@@ -548,33 +548,33 @@ static int uniphier_spi_transfer_one(str
+ threshold = DIV_ROUND_UP(SSI_POLL_TIMEOUT_US * priv->speed_hz,
+ USEC_PER_SEC * BITS_PER_BYTE);
+ if (t->len > threshold)
+- return uniphier_spi_transfer_one_irq(master, spi, t);
++ return uniphier_spi_transfer_one_irq(host, spi, t);
+ else
+- return uniphier_spi_transfer_one_poll(master, spi, t);
++ return uniphier_spi_transfer_one_poll(host, spi, t);
+ }
+
+-static int uniphier_spi_prepare_transfer_hardware(struct spi_master *master)
++static int uniphier_spi_prepare_transfer_hardware(struct spi_controller *host)
+ {
+- struct uniphier_spi_priv *priv = spi_master_get_devdata(master);
++ struct uniphier_spi_priv *priv = spi_controller_get_devdata(host);
+
+ writel(SSI_CTL_EN, priv->base + SSI_CTL);
+
+ return 0;
+ }
+
+-static int uniphier_spi_unprepare_transfer_hardware(struct spi_master *master)
++static int uniphier_spi_unprepare_transfer_hardware(struct spi_controller *host)
+ {
+- struct uniphier_spi_priv *priv = spi_master_get_devdata(master);
++ struct uniphier_spi_priv *priv = spi_controller_get_devdata(host);
+
+ writel(0, priv->base + SSI_CTL);
+
+ return 0;
+ }
+
+-static void uniphier_spi_handle_err(struct spi_master *master,
++static void uniphier_spi_handle_err(struct spi_controller *host,
+ struct spi_message *msg)
+ {
+- struct uniphier_spi_priv *priv = spi_master_get_devdata(master);
++ struct uniphier_spi_priv *priv = spi_controller_get_devdata(host);
+ u32 val;
+
+ /* stop running spi transfer */
+@@ -587,12 +587,12 @@ static void uniphier_spi_handle_err(stru
+ uniphier_spi_irq_disable(priv, SSI_IE_ALL_MASK);
+
+ if (atomic_read(&priv->dma_busy) & SSI_DMA_TX_BUSY) {
+- dmaengine_terminate_async(master->dma_tx);
++ dmaengine_terminate_async(host->dma_tx);
+ atomic_andnot(SSI_DMA_TX_BUSY, &priv->dma_busy);
+ }
+
+ if (atomic_read(&priv->dma_busy) & SSI_DMA_RX_BUSY) {
+- dmaengine_terminate_async(master->dma_rx);
++ dmaengine_terminate_async(host->dma_rx);
+ atomic_andnot(SSI_DMA_RX_BUSY, &priv->dma_busy);
+ }
+ }
+@@ -641,7 +641,7 @@ done:
+ static int uniphier_spi_probe(struct platform_device *pdev)
+ {
+ struct uniphier_spi_priv *priv;
+- struct spi_master *master;
++ struct spi_controller *host;
+ struct resource *res;
+ struct dma_slave_caps caps;
+ u32 dma_tx_burst = 0, dma_rx_burst = 0;
+@@ -649,20 +649,20 @@ static int uniphier_spi_probe(struct pla
+ int irq;
+ int ret;
+
+- master = spi_alloc_master(&pdev->dev, sizeof(*priv));
+- if (!master)
++ host = spi_alloc_host(&pdev->dev, sizeof(*priv));
++ if (!host)
+ return -ENOMEM;
+
+- platform_set_drvdata(pdev, master);
++ platform_set_drvdata(pdev, host);
+
+- priv = spi_master_get_devdata(master);
+- priv->master = master;
++ priv = spi_controller_get_devdata(host);
++ priv->host = host;
+ priv->is_save_param = false;
+
+ priv->base = devm_platform_get_and_ioremap_resource(pdev, 0, &res);
+ if (IS_ERR(priv->base)) {
+ ret = PTR_ERR(priv->base);
+- goto out_master_put;
++ goto out_host_put;
+ }
+ priv->base_dma_addr = res->start;
+
+@@ -670,12 +670,12 @@ static int uniphier_spi_probe(struct pla
+ if (IS_ERR(priv->clk)) {
+ dev_err(&pdev->dev, "failed to get clock\n");
+ ret = PTR_ERR(priv->clk);
+- goto out_master_put;
++ goto out_host_put;
+ }
+
+ ret = clk_prepare_enable(priv->clk);
+ if (ret)
+- goto out_master_put;
++ goto out_host_put;
+
+ irq = platform_get_irq(pdev, 0);
+ if (irq < 0) {
+@@ -694,35 +694,35 @@ static int uniphier_spi_probe(struct pla
+
+ clk_rate = clk_get_rate(priv->clk);
+
+- master->max_speed_hz = DIV_ROUND_UP(clk_rate, SSI_MIN_CLK_DIVIDER);
+- master->min_speed_hz = DIV_ROUND_UP(clk_rate, SSI_MAX_CLK_DIVIDER);
+- master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH | SPI_LSB_FIRST;
+- master->dev.of_node = pdev->dev.of_node;
+- master->bus_num = pdev->id;
+- master->bits_per_word_mask = SPI_BPW_RANGE_MASK(1, 32);
+-
+- master->set_cs = uniphier_spi_set_cs;
+- master->transfer_one = uniphier_spi_transfer_one;
+- master->prepare_transfer_hardware
++ host->max_speed_hz = DIV_ROUND_UP(clk_rate, SSI_MIN_CLK_DIVIDER);
++ host->min_speed_hz = DIV_ROUND_UP(clk_rate, SSI_MAX_CLK_DIVIDER);
++ host->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH | SPI_LSB_FIRST;
++ host->dev.of_node = pdev->dev.of_node;
++ host->bus_num = pdev->id;
++ host->bits_per_word_mask = SPI_BPW_RANGE_MASK(1, 32);
++
++ host->set_cs = uniphier_spi_set_cs;
++ host->transfer_one = uniphier_spi_transfer_one;
++ host->prepare_transfer_hardware
+ = uniphier_spi_prepare_transfer_hardware;
+- master->unprepare_transfer_hardware
++ host->unprepare_transfer_hardware
+ = uniphier_spi_unprepare_transfer_hardware;
+- master->handle_err = uniphier_spi_handle_err;
+- master->can_dma = uniphier_spi_can_dma;
++ host->handle_err = uniphier_spi_handle_err;
++ host->can_dma = uniphier_spi_can_dma;
+
+- master->num_chipselect = 1;
+- master->flags = SPI_CONTROLLER_MUST_RX | SPI_CONTROLLER_MUST_TX;
++ host->num_chipselect = 1;
++ host->flags = SPI_CONTROLLER_MUST_RX | SPI_CONTROLLER_MUST_TX;
+
+- master->dma_tx = dma_request_chan(&pdev->dev, "tx");
+- if (IS_ERR_OR_NULL(master->dma_tx)) {
+- if (PTR_ERR(master->dma_tx) == -EPROBE_DEFER) {
++ host->dma_tx = dma_request_chan(&pdev->dev, "tx");
++ if (IS_ERR_OR_NULL(host->dma_tx)) {
++ if (PTR_ERR(host->dma_tx) == -EPROBE_DEFER) {
+ ret = -EPROBE_DEFER;
+ goto out_disable_clk;
+ }
+- master->dma_tx = NULL;
++ host->dma_tx = NULL;
+ dma_tx_burst = INT_MAX;
+ } else {
+- ret = dma_get_slave_caps(master->dma_tx, &caps);
++ ret = dma_get_slave_caps(host->dma_tx, &caps);
+ if (ret) {
+ dev_err(&pdev->dev, "failed to get TX DMA capacities: %d\n",
+ ret);
+@@ -731,16 +731,16 @@ static int uniphier_spi_probe(struct pla
+ dma_tx_burst = caps.max_burst;
+ }
+
+- master->dma_rx = dma_request_chan(&pdev->dev, "rx");
+- if (IS_ERR_OR_NULL(master->dma_rx)) {
+- if (PTR_ERR(master->dma_rx) == -EPROBE_DEFER) {
++ host->dma_rx = dma_request_chan(&pdev->dev, "rx");
++ if (IS_ERR_OR_NULL(host->dma_rx)) {
++ if (PTR_ERR(host->dma_rx) == -EPROBE_DEFER) {
+ ret = -EPROBE_DEFER;
+ goto out_release_dma;
+ }
+- master->dma_rx = NULL;
++ host->dma_rx = NULL;
+ dma_rx_burst = INT_MAX;
+ } else {
+- ret = dma_get_slave_caps(master->dma_rx, &caps);
++ ret = dma_get_slave_caps(host->dma_rx, &caps);
+ if (ret) {
+ dev_err(&pdev->dev, "failed to get RX DMA capacities: %d\n",
+ ret);
+@@ -749,41 +749,41 @@ static int uniphier_spi_probe(struct pla
+ dma_rx_burst = caps.max_burst;
+ }
+
+- master->max_dma_len = min(dma_tx_burst, dma_rx_burst);
++ host->max_dma_len = min(dma_tx_burst, dma_rx_burst);
+
+- ret = devm_spi_register_master(&pdev->dev, master);
++ ret = devm_spi_register_controller(&pdev->dev, host);
+ if (ret)
+ goto out_release_dma;
+
+ return 0;
+
+ out_release_dma:
+- if (!IS_ERR_OR_NULL(master->dma_rx)) {
+- dma_release_channel(master->dma_rx);
+- master->dma_rx = NULL;
+- }
+- if (!IS_ERR_OR_NULL(master->dma_tx)) {
+- dma_release_channel(master->dma_tx);
+- master->dma_tx = NULL;
++ if (!IS_ERR_OR_NULL(host->dma_rx)) {
++ dma_release_channel(host->dma_rx);
++ host->dma_rx = NULL;
++ }
++ if (!IS_ERR_OR_NULL(host->dma_tx)) {
++ dma_release_channel(host->dma_tx);
++ host->dma_tx = NULL;
+ }
+
+ out_disable_clk:
+ clk_disable_unprepare(priv->clk);
+
+-out_master_put:
+- spi_master_put(master);
++out_host_put:
++ spi_controller_put(host);
+ return ret;
+ }
+
+ static void uniphier_spi_remove(struct platform_device *pdev)
+ {
+- struct spi_master *master = platform_get_drvdata(pdev);
+- struct uniphier_spi_priv *priv = spi_master_get_devdata(master);
++ struct spi_controller *host = platform_get_drvdata(pdev);
++ struct uniphier_spi_priv *priv = spi_controller_get_devdata(host);
+
+- if (master->dma_tx)
+- dma_release_channel(master->dma_tx);
+- if (master->dma_rx)
+- dma_release_channel(master->dma_rx);
++ 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);
+ }
--- /dev/null
+From stable+bounces-247015-greg=kroah.com@vger.kernel.org Wed May 13 20:40:59 2026
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 13 May 2026 14:33:48 -0400
+Subject: spi: zynq-qspi: fix controller deregistration
+To: stable@vger.kernel.org
+Cc: Johan Hovold <johan@kernel.org>, Naga Sureshkumar Relli <naga.sureshkumar.relli@xilinx.com>, Mark Brown <broonie@kernel.org>, Sasha Levin <sashal@kernel.org>
+Message-ID: <20260513183348.3927281-3-sashal@kernel.org>
+
+From: Johan Hovold <johan@kernel.org>
+
+[ 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 <naga.sureshkumar.relli@xilinx.com>
+Signed-off-by: Johan Hovold <johan@kernel.org>
+Link: https://patch.msgid.link/20260410081757.503099-27-johan@kernel.org
+Signed-off-by: Mark Brown <broonie@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ 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[] = {
--- /dev/null
+From stable+bounces-247014-greg=kroah.com@vger.kernel.org Wed May 13 20:41:03 2026
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 13 May 2026 14:33:47 -0400
+Subject: spi: zynq-qspi: Simplify clock handling with devm_clk_get_enabled()
+To: stable@vger.kernel.org
+Cc: Pei Xiao <xiaopei01@kylinos.cn>, Michal Simek <michal.simek@amd.com>, Mark Brown <broonie@kernel.org>, Sasha Levin <sashal@kernel.org>
+Message-ID: <20260513183348.3927281-2-sashal@kernel.org>
+
+From: Pei Xiao <xiaopei01@kylinos.cn>
+
+[ 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 <xiaopei01@kylinos.cn>
+Acked-by: Michal Simek <michal.simek@amd.com>
+Link: https://patch.msgid.link/24043625f89376da36feca2408f990a85be7ab36.1775555500.git.xiaopei01@kylinos.cn
+Signed-off-by: Mark Brown <broonie@kernel.org>
+Stable-dep-of: c9c012706c9f ("spi: zynq-qspi: fix controller deregistration")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ 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[] = {
--- /dev/null
+From stable+bounces-247013-greg=kroah.com@vger.kernel.org Wed May 13 20:39:57 2026
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 13 May 2026 14:33:46 -0400
+Subject: spi: zynq-qspi: switch to use modern name
+To: stable@vger.kernel.org
+Cc: Yang Yingliang <yangyingliang@huawei.com>, Mark Brown <broonie@kernel.org>, Sasha Levin <sashal@kernel.org>
+Message-ID: <20260513183348.3927281-1-sashal@kernel.org>
+
+From: Yang Yingliang <yangyingliang@huawei.com>
+
+[ Upstream commit 178ebb0c505b0a35edb4fb2a0e23a1f29e1db14d ]
+
+Change legacy name master/slave to modern name host/target or controller.
+
+No functional changed.
+
+Signed-off-by: Yang Yingliang <yangyingliang@huawei.com>
+Link: https://msgid.link/r/20231128093031.3707034-24-yangyingliang@huawei.com
+Signed-off-by: Mark Brown <broonie@kernel.org>
+Stable-dep-of: c9c012706c9f ("spi: zynq-qspi: fix controller deregistration")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/spi/spi-zynq-qspi.c | 28 ++++++++++++++--------------
+ 1 file changed, 14 insertions(+), 14 deletions(-)
+
+--- a/drivers/spi/spi-zynq-qspi.c
++++ b/drivers/spi/spi-zynq-qspi.c
+@@ -54,10 +54,10 @@
+ #define ZYNQ_QSPI_CONFIG_MSTREN_MASK BIT(0) /* Master Mode */
+
+ /*
+- * QSPI Configuration Register - Baud rate and slave select
++ * QSPI Configuration Register - Baud rate and target select
+ *
+ * These are the values used in the calculation of baud rate divisor and
+- * setting the slave select.
++ * setting the target select.
+ */
+ #define ZYNQ_QSPI_CONFIG_BAUD_DIV_MAX GENMASK(2, 0) /* Baud rate maximum */
+ #define ZYNQ_QSPI_CONFIG_BAUD_DIV_SHIFT 3 /* Baud rate divisor shift */
+@@ -164,14 +164,14 @@ static inline void zynq_qspi_write(struc
+ *
+ * The default settings of the QSPI controller's configurable parameters on
+ * reset are
+- * - Master mode
++ * - Host mode
+ * - Baud rate divisor is set to 2
+ * - Tx threshold set to 1l Rx threshold set to 32
+ * - Flash memory interface mode enabled
+ * - Size of the word to be transferred as 8 bit
+ * This function performs the following actions
+ * - Disable and clear all the interrupts
+- * - Enable manual slave select
++ * - Enable manual target select
+ * - Enable manual start
+ * - Deselect all the chip select lines
+ * - Set the size of the word to be transferred as 32 bit
+@@ -289,7 +289,7 @@ static void zynq_qspi_txfifo_op(struct z
+ */
+ static void zynq_qspi_chipselect(struct spi_device *spi, bool assert)
+ {
+- struct spi_controller *ctlr = spi->master;
++ struct spi_controller *ctlr = spi->controller;
+ struct zynq_qspi *xqspi = spi_controller_get_devdata(ctlr);
+ u32 config_reg;
+
+@@ -377,7 +377,7 @@ static int zynq_qspi_config_op(struct zy
+ */
+ static int zynq_qspi_setup_op(struct spi_device *spi)
+ {
+- struct spi_controller *ctlr = spi->master;
++ struct spi_controller *ctlr = spi->controller;
+ struct zynq_qspi *qspi = spi_controller_get_devdata(ctlr);
+ int ret;
+
+@@ -534,7 +534,7 @@ static irqreturn_t zynq_qspi_irq(int irq
+ static int zynq_qspi_exec_mem_op(struct spi_mem *mem,
+ const struct spi_mem_op *op)
+ {
+- struct zynq_qspi *xqspi = spi_controller_get_devdata(mem->spi->master);
++ struct zynq_qspi *xqspi = spi_controller_get_devdata(mem->spi->controller);
+ int err = 0, i;
+ u8 *tmpbuf;
+
+@@ -646,7 +646,7 @@ static int zynq_qspi_probe(struct platfo
+ struct zynq_qspi *xqspi;
+ u32 num_cs;
+
+- ctlr = spi_alloc_master(&pdev->dev, sizeof(*xqspi));
++ ctlr = spi_alloc_host(&pdev->dev, sizeof(*xqspi));
+ if (!ctlr)
+ return -ENOMEM;
+
+@@ -656,14 +656,14 @@ static int zynq_qspi_probe(struct platfo
+ xqspi->regs = devm_platform_ioremap_resource(pdev, 0);
+ if (IS_ERR(xqspi->regs)) {
+ ret = PTR_ERR(xqspi->regs);
+- goto remove_master;
++ goto remove_ctlr;
+ }
+
+ xqspi->pclk = devm_clk_get(&pdev->dev, "pclk");
+ if (IS_ERR(xqspi->pclk)) {
+ dev_err(&pdev->dev, "pclk clock not found.\n");
+ ret = PTR_ERR(xqspi->pclk);
+- goto remove_master;
++ goto remove_ctlr;
+ }
+
+ init_completion(&xqspi->data_completion);
+@@ -672,13 +672,13 @@ static int zynq_qspi_probe(struct platfo
+ if (IS_ERR(xqspi->refclk)) {
+ dev_err(&pdev->dev, "ref_clk clock not found.\n");
+ ret = PTR_ERR(xqspi->refclk);
+- goto remove_master;
++ goto remove_ctlr;
+ }
+
+ ret = clk_prepare_enable(xqspi->pclk);
+ if (ret) {
+ dev_err(&pdev->dev, "Unable to enable APB clock.\n");
+- goto remove_master;
++ goto remove_ctlr;
+ }
+
+ ret = clk_prepare_enable(xqspi->refclk);
+@@ -724,7 +724,7 @@ static int zynq_qspi_probe(struct platfo
+
+ ret = devm_spi_register_controller(&pdev->dev, ctlr);
+ if (ret) {
+- dev_err(&pdev->dev, "spi_register_master failed\n");
++ dev_err(&pdev->dev, "devm_spi_register_controller failed\n");
+ goto clk_dis_all;
+ }
+
+@@ -734,7 +734,7 @@ clk_dis_all:
+ clk_disable_unprepare(xqspi->refclk);
+ clk_dis_pclk:
+ clk_disable_unprepare(xqspi->pclk);
+-remove_master:
++remove_ctlr:
+ spi_controller_put(ctlr);
+
+ return ret;
--- /dev/null
+From stable+bounces-245065-greg=kroah.com@vger.kernel.org Sun May 10 22:00:00 2026
+From: Sasha Levin <sashal@kernel.org>
+Date: Sun, 10 May 2026 15:59:53 -0400
+Subject: tracepoint: balance regfunc() on func_add() failure in tracepoint_add_func()
+To: stable@vger.kernel.org
+Cc: David Carlier <devnexen@gmail.com>, Masami Hiramatsu <mhiramat@kernel.org>, Mathieu Desnoyers <mathieu.desnoyers@efficios.com>, "Steven Rostedt (Google)" <rostedt@goodmis.org>, Sasha Levin <sashal@kernel.org>
+Message-ID: <20260510195953.593373-1-sashal@kernel.org>
+
+From: David Carlier <devnexen@gmail.com>
+
+[ Upstream commit fad217e16fded7f3c09f8637b0f6a224d58b5f2e ]
+
+When a tracepoint goes through the 0 -> 1 transition, tracepoint_add_func()
+invokes the subsystem's ext->regfunc() before attempting to install the
+new probe via func_add(). If func_add() then fails (for example, when
+allocate_probes() cannot allocate a new probe array under memory pressure
+and returns -ENOMEM), the function returns the error without calling the
+matching ext->unregfunc(), leaving the side effects of regfunc() behind
+with no installed probe to justify them.
+
+For syscall tracepoints this is particularly unpleasant: syscall_regfunc()
+bumps sys_tracepoint_refcount and sets SYSCALL_TRACEPOINT on every task.
+After a leaked failure, the refcount is stuck at a non-zero value with no
+consumer, and every task continues paying the syscall trace entry/exit
+overhead until reboot. Other subsystems providing regfunc()/unregfunc()
+pairs exhibit similarly scoped persistent state.
+
+Mirror the existing 1 -> 0 cleanup and call ext->unregfunc() in the
+func_add() error path, gated on the same condition used there so the
+unwind is symmetric with the registration.
+
+Fixes: 8cf868affdc4 ("tracing: Have the reg function allow to fail")
+Cc: stable@vger.kernel.org
+Cc: Masami Hiramatsu <mhiramat@kernel.org>
+Cc: Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
+Link: https://patch.msgid.link/20260413190601.21993-1-devnexen@gmail.com
+Signed-off-by: David Carlier <devnexen@gmail.com>
+Signed-off-by: Steven Rostedt (Google) <rostedt@goodmis.org>
+[ changed `tp->ext->unregfunc` to `tp->unregfunc` to match older struct layout ]
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ kernel/tracepoint.c | 2 ++
+ 1 file changed, 2 insertions(+)
+
+--- a/kernel/tracepoint.c
++++ b/kernel/tracepoint.c
+@@ -337,6 +337,8 @@ static int tracepoint_add_func(struct tr
+ lockdep_is_held(&tracepoints_mutex));
+ old = func_add(&tp_funcs, func, prio);
+ if (IS_ERR(old)) {
++ if (tp->unregfunc && !static_key_enabled(&tp->key))
++ tp->unregfunc();
+ WARN_ON_ONCE(warn && PTR_ERR(old) != -ENOMEM);
+ return PTR_ERR(old);
+ }
--- /dev/null
+From stable+bounces-246945-greg=kroah.com@vger.kernel.org Wed May 13 19:18:18 2026
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 13 May 2026 12:46:35 -0400
+Subject: xfrm: ah: account for ESN high bits in async callbacks
+To: stable@vger.kernel.org
+Cc: Michael Bommarito <michael.bommarito@gmail.com>, Steffen Klassert <steffen.klassert@secunet.com>, Sasha Levin <sashal@kernel.org>
+Message-ID: <20260513164635.3816490-3-sashal@kernel.org>
+
+From: Michael Bommarito <michael.bommarito@gmail.com>
+
+[ Upstream commit ec54093e6a8f87e800bb6aa15eb7fc1e33faa524 ]
+
+AH allocates its temporary auth/ICV layout differently when ESN is enabled:
+the async ahash setup appends a 4-byte seqhi slot before the ICV or
+auth_data area, but the async completion callbacks still reconstruct the
+temporary layout as if seqhi were absent.
+
+With an async AH implementation selected, that makes AH copy or compare
+the wrong bytes on both the IPv4 and IPv6 paths. In UML repro on IPv4 AH
+with ESN and forced async hmac(sha1), ping fails with 100% packet loss,
+and the callback logs show the pre-fix drift:
+
+ ah4 output_done: esn=1 err=0 icv_off=20 expected_off=24
+ ah4 input_done: esn=1 auth_off=20 expected_auth_off=24 icv_off=32 expected_icv_off=36
+
+Reconstruct the callback-side layout the same way the setup path built it
+by skipping the ESN seqhi slot before locating the saved auth_data or ICV.
+Per RFC 4302, the ESN high-order 32 bits participate in the AH ICV
+computation, so the async callbacks must account for the seqhi slot.
+
+Post-fix, the same IPv4 AH+ESN+forced-async-hmac(sha1) UML repro shows
+the corrected offset (ah4 output_done: esn=1 err=0 icv_off=24
+expected_off=24) and ping succeeds; net/ipv4/ah4.o and net/ipv6/ah6.o
+build clean at W=1. IPv6 AH+ESN was not exercised at runtime, and the
+change has not been tested against a real async hardware AH engine.
+
+Fixes: d4d573d0334d ("{IPv4,xfrm} Add ESN support for AH egress part")
+Fixes: d8b2a8600b0e ("{IPv4,xfrm} Add ESN support for AH ingress part")
+Fixes: 26dd70c3fad3 ("{IPv6,xfrm} Add ESN support for AH egress part")
+Fixes: 8d6da6f32557 ("{IPv6,xfrm} Add ESN support for AH ingress part")
+Cc: stable@vger.kernel.org
+Assisted-by: Codex:gpt-5-4
+Assisted-by: Claude:claude-opus-4-7
+Signed-off-by: Michael Bommarito <michael.bommarito@gmail.com>
+Signed-off-by: Steffen Klassert <steffen.klassert@secunet.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ net/ipv4/ah4.c | 14 ++++++++++++--
+ net/ipv6/ah6.c | 14 ++++++++++++--
+ 2 files changed, 24 insertions(+), 4 deletions(-)
+
+--- a/net/ipv4/ah4.c
++++ b/net/ipv4/ah4.c
+@@ -124,9 +124,14 @@ static void ah_output_done(void *data, i
+ struct iphdr *top_iph = ip_hdr(skb);
+ struct ip_auth_hdr *ah = ip_auth_hdr(skb);
+ int ihl = ip_hdrlen(skb);
++ int seqhi_len = 0;
++ __be32 *seqhi;
+
++ if (x->props.flags & XFRM_STATE_ESN)
++ seqhi_len = sizeof(*seqhi);
+ iph = AH_SKB_CB(skb)->tmp;
+- icv = ah_tmp_icv(iph, ihl);
++ seqhi = (__be32 *)((char *)iph + ihl);
++ icv = ah_tmp_icv(seqhi, seqhi_len);
+ memcpy(ah->auth_data, icv, ahp->icv_trunc_len);
+
+ top_iph->tos = iph->tos;
+@@ -270,12 +275,17 @@ static void ah_input_done(void *data, in
+ struct ip_auth_hdr *ah = ip_auth_hdr(skb);
+ int ihl = ip_hdrlen(skb);
+ int ah_hlen = (ah->hdrlen + 2) << 2;
++ int seqhi_len = 0;
++ __be32 *seqhi;
+
+ if (err)
+ goto out;
+
++ if (x->props.flags & XFRM_STATE_ESN)
++ seqhi_len = sizeof(*seqhi);
+ work_iph = AH_SKB_CB(skb)->tmp;
+- auth_data = ah_tmp_auth(work_iph, ihl);
++ seqhi = (__be32 *)((char *)work_iph + ihl);
++ auth_data = ah_tmp_auth(seqhi, seqhi_len);
+ icv = ah_tmp_icv(auth_data, ahp->icv_trunc_len);
+
+ err = crypto_memneq(icv, auth_data, ahp->icv_trunc_len) ? -EBADMSG : 0;
+--- a/net/ipv6/ah6.c
++++ b/net/ipv6/ah6.c
+@@ -317,14 +317,19 @@ static void ah6_output_done(void *data,
+ struct ipv6hdr *top_iph = ipv6_hdr(skb);
+ struct ip_auth_hdr *ah = ip_auth_hdr(skb);
+ struct tmp_ext *iph_ext;
++ int seqhi_len = 0;
++ __be32 *seqhi;
+
+ extlen = skb_network_header_len(skb) - sizeof(struct ipv6hdr);
+ if (extlen)
+ extlen += sizeof(*iph_ext);
+
++ if (x->props.flags & XFRM_STATE_ESN)
++ seqhi_len = sizeof(*seqhi);
+ iph_base = AH_SKB_CB(skb)->tmp;
+ iph_ext = ah_tmp_ext(iph_base);
+- icv = ah_tmp_icv(iph_ext, extlen);
++ seqhi = (__be32 *)((char *)iph_ext + extlen);
++ icv = ah_tmp_icv(seqhi, seqhi_len);
+
+ memcpy(ah->auth_data, icv, ahp->icv_trunc_len);
+ memcpy(top_iph, iph_base, IPV6HDR_BASELEN);
+@@ -471,13 +476,18 @@ static void ah6_input_done(void *data, i
+ struct ip_auth_hdr *ah = ip_auth_hdr(skb);
+ int hdr_len = skb_network_header_len(skb);
+ int ah_hlen = ipv6_authlen(ah);
++ int seqhi_len = 0;
++ __be32 *seqhi;
+
+ if (err)
+ goto out;
+
++ if (x->props.flags & XFRM_STATE_ESN)
++ seqhi_len = sizeof(*seqhi);
+ work_iph = AH_SKB_CB(skb)->tmp;
+ auth_data = ah_tmp_auth(work_iph, hdr_len);
+- icv = ah_tmp_icv(auth_data, ahp->icv_trunc_len);
++ seqhi = (__be32 *)(auth_data + ahp->icv_trunc_len);
++ icv = ah_tmp_icv(seqhi, seqhi_len);
+
+ err = crypto_memneq(icv, auth_data, ahp->icv_trunc_len) ? -EBADMSG : 0;
+ if (err)
--- /dev/null
+From stable+bounces-246964-greg=kroah.com@vger.kernel.org Wed May 13 19:16:52 2026
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 13 May 2026 13:16:28 -0400
+Subject: xfrm: defensively unhash xfrm_state lists in __xfrm_state_delete
+To: stable@vger.kernel.org
+Cc: Michal Kosiorek <mkosiorek121@gmail.com>, Steffen Klassert <steffen.klassert@secunet.com>, Sasha Levin <sashal@kernel.org>
+Message-ID: <20260513171628.3878131-1-sashal@kernel.org>
+
+From: Michal Kosiorek <mkosiorek121@gmail.com>
+
+[ Upstream commit 14acf9652e5690de3c7486c6db5fb8dafd0a32a3 ]
+
+KASAN reproduces a slab-use-after-free in __xfrm_state_delete()'s
+hlist_del_rcu calls under syzkaller load on linux-6.12.y stable
+(reproduced on 6.12.47, also reachable via the same code path on
+torvalds/master and on the ipsec tree). Nine unique signatures cluster
+in the xfrm_state lifecycle, the load-bearing one being:
+
+ BUG: KASAN: slab-use-after-free in __hlist_del include/linux/list.h:990 [inline]
+ BUG: KASAN: slab-use-after-free in hlist_del_rcu include/linux/rculist.h:516 [inline]
+ BUG: KASAN: slab-use-after-free in __xfrm_state_delete net/xfrm/xfrm_state.c
+ Write of size 8 at addr ffff8881198bcb70 by task kworker/u8:9/435
+
+ Workqueue: netns cleanup_net
+ Call Trace:
+ __hlist_del / hlist_del_rcu
+ __xfrm_state_delete
+ xfrm_state_delete
+ xfrm_state_flush
+ xfrm_state_fini
+ ops_exit_list
+ cleanup_net
+
+The other observed signatures hit the same slab object from
+__xfrm_state_lookup, xfrm_alloc_spi, __xfrm_state_insert and an OOB
+write variant of __xfrm_state_delete, all on the byseq/byspi
+hash chains.
+
+__xfrm_state_delete() guards its byseq and byspi unhashes with
+value-based predicates:
+
+ if (x->km.seq)
+ hlist_del_rcu(&x->byseq);
+ if (x->id.spi)
+ hlist_del_rcu(&x->byspi);
+
+while everywhere else in the file (e.g. state_cache, state_cache_input)
+the safer hlist_unhashed() check is used. xfrm_alloc_spi() sets
+x->id.spi = newspi inside xfrm_state_lock and then immediately inserts
+into byspi, but a path that observes x->id.spi != 0 outside of
+xfrm_state_lock can still skip-or-hit the byspi unhash inconsistently
+with whether x is actually on the list. The same holds for x->km.seq
+versus byseq, and the bydst/bysrc unhashes have no predicate at all,
+so a second __xfrm_state_delete() on the same object writes through
+LIST_POISON pprev.
+
+The defensive change here:
+
+ - Use hlist_del_init_rcu() instead of hlist_del_rcu() on bydst,
+ bysrc, byseq and byspi so a second deletion is a no-op rather
+ than a write through LIST_POISON pprev. The byseq/byspi nodes
+ are already initialised in xfrm_state_alloc().
+ - Test hlist_unhashed() rather than the value predicate for
+ byseq/byspi, so the unhash decision tracks list state rather than
+ mutable scalar fields.
+
+Empirical verification: applied this patch on top of v6.12.47, rebuilt,
+and re-ran the same syzkaller harness for 1h16m on a previously-crashy
+configuration that produced ~100 hits each of slab-use-after-free
+Read in xfrm_alloc_spi / Read in __xfrm_state_lookup / Write in
+__xfrm_state_delete. After the patch, 7.1M execs across 32 VMs at
+~1550 exec/sec produced zero xfrm_state UAF/OOB hits. /proc/slabinfo
+confirms the xfrm_state slab is actively allocated and freed during
+the run (~143 KiB resident), so the fuzzer is still exercising those
+code paths -- they just no longer crash.
+
+Reproduction:
+
+ - Linux 6.12.47 x86_64 + KASAN_GENERIC + KASAN_INLINE + KCOV
+ - syzkaller @ 746545b8b1e4c3a128db8652b340d3df90ce61db
+ - 32 QEMU/KVM VMs x 2 vCPU on AWS c5.metal bare metal
+ - 9 unique signatures collected in ~9h, all within xfrm_state
+ lifecycle
+
+Fixes: fe9f1d8779cb ("xfrm: add state hashtable keyed by seq")
+Fixes: 7b4dc3600e48 ("[XFRM]: Do not add a state whose SPI is zero to the SPI hash.")
+Reported-by: Michal Kosiorek <mkosiorek121@gmail.com>
+Tested-by: Michal Kosiorek <mkosiorek121@gmail.com>
+Cc: stable@vger.kernel.org
+Signed-off-by: Michal Kosiorek <mkosiorek121@gmail.com>
+Signed-off-by: Steffen Klassert <steffen.klassert@secunet.com>
+[ dropped state_cache/state_cache_input unhash hunks and xfrm_nat_keepalive_state_updated() call ]
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ net/xfrm/xfrm_state.c | 12 ++++++------
+ 1 file changed, 6 insertions(+), 6 deletions(-)
+
+--- a/net/xfrm/xfrm_state.c
++++ b/net/xfrm/xfrm_state.c
+@@ -752,12 +752,12 @@ int __xfrm_state_delete(struct xfrm_stat
+ x->km.state = XFRM_STATE_DEAD;
+ spin_lock(&net->xfrm.xfrm_state_lock);
+ list_del(&x->km.all);
+- hlist_del_rcu(&x->bydst);
+- hlist_del_rcu(&x->bysrc);
+- if (x->km.seq)
+- hlist_del_rcu(&x->byseq);
+- if (x->id.spi)
+- hlist_del_rcu(&x->byspi);
++ hlist_del_init_rcu(&x->bydst);
++ hlist_del_init_rcu(&x->bysrc);
++ if (!hlist_unhashed(&x->byseq))
++ hlist_del_init_rcu(&x->byseq);
++ if (!hlist_unhashed(&x->byspi))
++ hlist_del_init_rcu(&x->byspi);
+ net->xfrm.state_num--;
+ spin_unlock(&net->xfrm.xfrm_state_lock);
+