--- /dev/null
+From stable+bounces-215606-greg=kroah.com@vger.kernel.org Tue Feb 10 07:56:56 2026
+From: Rahul Sharma <black.hawk@163.com>
+Date: Tue, 10 Feb 2026 14:55:04 +0800
+Subject: btrfs: fix racy bitfield write in btrfs_clear_space_info_full()
+To: gregkh@linuxfoundation.org, stable@vger.kernel.org
+Cc: linux-kernel@vger.kernel.org, Boris Burkov <boris@bur.io>, Qu Wenruo <wqu@suse.com>, David Sterba <dsterba@suse.com>, Rahul Sharma <black.hawk@163.com>
+Message-ID: <20260210065504.562467-1-black.hawk@163.com>
+
+From: Boris Burkov <boris@bur.io>
+
+[ Upstream commit 38e818718c5e04961eea0fa8feff3f100ce40408 ]
+
+>From the memory-barriers.txt document regarding memory barrier ordering
+guarantees:
+
+ (*) These guarantees do not apply to bitfields, because compilers often
+ generate code to modify these using non-atomic read-modify-write
+ sequences. Do not attempt to use bitfields to synchronize parallel
+ algorithms.
+
+ (*) Even in cases where bitfields are protected by locks, all fields
+ in a given bitfield must be protected by one lock. If two fields
+ in a given bitfield are protected by different locks, the compiler's
+ non-atomic read-modify-write sequences can cause an update to one
+ field to corrupt the value of an adjacent field.
+
+btrfs_space_info has a bitfield sharing an underlying word consisting of
+the fields full, chunk_alloc, and flush:
+
+struct btrfs_space_info {
+ struct btrfs_fs_info * fs_info; /* 0 8 */
+ struct btrfs_space_info * parent; /* 8 8 */
+ ...
+ int clamp; /* 172 4 */
+ unsigned int full:1; /* 176: 0 4 */
+ unsigned int chunk_alloc:1; /* 176: 1 4 */
+ unsigned int flush:1; /* 176: 2 4 */
+ ...
+
+Therefore, to be safe from parallel read-modify-writes losing a write to
+one of the bitfield members protected by a lock, all writes to all the
+bitfields must use the lock. They almost universally do, except for
+btrfs_clear_space_info_full() which iterates over the space_infos and
+writes out found->full = 0 without a lock.
+
+Imagine that we have one thread completing a transaction in which we
+finished deleting a block_group and are thus calling
+btrfs_clear_space_info_full() while simultaneously the data reclaim
+ticket infrastructure is running do_async_reclaim_data_space():
+
+ T1 T2
+btrfs_commit_transaction
+ btrfs_clear_space_info_full
+ data_sinfo->full = 0
+ READ: full:0, chunk_alloc:0, flush:1
+ do_async_reclaim_data_space(data_sinfo)
+ spin_lock(&space_info->lock);
+ if(list_empty(tickets))
+ space_info->flush = 0;
+ READ: full: 0, chunk_alloc:0, flush:1
+ MOD/WRITE: full: 0, chunk_alloc:0, flush:0
+ spin_unlock(&space_info->lock);
+ return;
+ MOD/WRITE: full:0, chunk_alloc:0, flush:1
+
+and now data_sinfo->flush is 1 but the reclaim worker has exited. This
+breaks the invariant that flush is 0 iff there is no work queued or
+running. Once this invariant is violated, future allocations that go
+into __reserve_bytes() will add tickets to space_info->tickets but will
+see space_info->flush is set to 1 and not queue the work. After this,
+they will block forever on the resulting ticket, as it is now impossible
+to kick the worker again.
+
+I also confirmed by looking at the assembly of the affected kernel that
+it is doing RMW operations. For example, to set the flush (3rd) bit to 0,
+the assembly is:
+ andb $0xfb,0x60(%rbx)
+and similarly for setting the full (1st) bit to 0:
+ andb $0xfe,-0x20(%rax)
+
+So I think this is really a bug on practical systems. I have observed
+a number of systems in this exact state, but am currently unable to
+reproduce it.
+
+Rather than leaving this footgun lying around for the future, take
+advantage of the fact that there is room in the struct anyway, and that
+it is already quite large and simply change the three bitfield members to
+bools. This avoids writes to space_info->full having any effect on
+writes to space_info->flush, regardless of locking.
+
+Fixes: 957780eb2788 ("Btrfs: introduce ticketed enospc infrastructure")
+Reviewed-by: Qu Wenruo <wqu@suse.com>
+Signed-off-by: Boris Burkov <boris@bur.io>
+Reviewed-by: David Sterba <dsterba@suse.com>
+Signed-off-by: David Sterba <dsterba@suse.com>
+[ The context change is due to the commit cc0517fe779f
+("btrfs: tweak extent/chunk allocation for space_info sub-space")
+and the commit 45a59513b4b2
+("btrfs: add support for reclaiming from sub-space space_info")
+in v6.16 which are irrelevant to the logic of this patch. ]
+Signed-off-by: Rahul Sharma <black.hawk@163.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ fs/btrfs/block-group.c | 6 +++---
+ fs/btrfs/space-info.c | 20 ++++++++++----------
+ fs/btrfs/space-info.h | 6 +++---
+ 3 files changed, 16 insertions(+), 16 deletions(-)
+
+--- a/fs/btrfs/block-group.c
++++ b/fs/btrfs/block-group.c
+@@ -3699,7 +3699,7 @@ int btrfs_chunk_alloc(struct btrfs_trans
+ mutex_unlock(&fs_info->chunk_mutex);
+ } else {
+ /* Proceed with allocation */
+- space_info->chunk_alloc = 1;
++ space_info->chunk_alloc = true;
+ wait_for_alloc = false;
+ spin_unlock(&space_info->lock);
+ }
+@@ -3735,7 +3735,7 @@ int btrfs_chunk_alloc(struct btrfs_trans
+ spin_lock(&space_info->lock);
+ if (ret < 0) {
+ if (ret == -ENOSPC)
+- space_info->full = 1;
++ space_info->full = true;
+ else
+ goto out;
+ } else {
+@@ -3745,7 +3745,7 @@ int btrfs_chunk_alloc(struct btrfs_trans
+
+ space_info->force_alloc = CHUNK_ALLOC_NO_FORCE;
+ out:
+- space_info->chunk_alloc = 0;
++ space_info->chunk_alloc = false;
+ spin_unlock(&space_info->lock);
+ mutex_unlock(&fs_info->chunk_mutex);
+
+--- a/fs/btrfs/space-info.c
++++ b/fs/btrfs/space-info.c
+@@ -178,7 +178,7 @@ void btrfs_clear_space_info_full(struct
+ struct btrfs_space_info *found;
+
+ list_for_each_entry(found, head, list)
+- found->full = 0;
++ found->full = false;
+ }
+
+ static int create_space_info(struct btrfs_fs_info *info, u64 flags)
+@@ -271,7 +271,7 @@ void btrfs_update_space_info(struct btrf
+ found->bytes_readonly += bytes_readonly;
+ found->bytes_zone_unusable += bytes_zone_unusable;
+ if (total_bytes > 0)
+- found->full = 0;
++ found->full = false;
+ btrfs_try_granting_tickets(info, found);
+ spin_unlock(&found->lock);
+ *space_info = found;
+@@ -941,7 +941,7 @@ static void btrfs_async_reclaim_metadata
+ spin_lock(&space_info->lock);
+ to_reclaim = btrfs_calc_reclaim_metadata_size(fs_info, space_info);
+ if (!to_reclaim) {
+- space_info->flush = 0;
++ space_info->flush = false;
+ spin_unlock(&space_info->lock);
+ return;
+ }
+@@ -953,7 +953,7 @@ static void btrfs_async_reclaim_metadata
+ flush_space(fs_info, space_info, to_reclaim, flush_state, false);
+ spin_lock(&space_info->lock);
+ if (list_empty(&space_info->tickets)) {
+- space_info->flush = 0;
++ space_info->flush = false;
+ spin_unlock(&space_info->lock);
+ return;
+ }
+@@ -996,7 +996,7 @@ static void btrfs_async_reclaim_metadata
+ flush_state = FLUSH_DELAYED_ITEMS_NR;
+ commit_cycles--;
+ } else {
+- space_info->flush = 0;
++ space_info->flush = false;
+ }
+ } else {
+ flush_state = FLUSH_DELAYED_ITEMS_NR;
+@@ -1158,7 +1158,7 @@ static void btrfs_async_reclaim_data_spa
+
+ spin_lock(&space_info->lock);
+ if (list_empty(&space_info->tickets)) {
+- space_info->flush = 0;
++ space_info->flush = false;
+ spin_unlock(&space_info->lock);
+ return;
+ }
+@@ -1169,7 +1169,7 @@ static void btrfs_async_reclaim_data_spa
+ flush_space(fs_info, space_info, U64_MAX, ALLOC_CHUNK_FORCE, false);
+ spin_lock(&space_info->lock);
+ if (list_empty(&space_info->tickets)) {
+- space_info->flush = 0;
++ space_info->flush = false;
+ spin_unlock(&space_info->lock);
+ return;
+ }
+@@ -1182,7 +1182,7 @@ static void btrfs_async_reclaim_data_spa
+ data_flush_states[flush_state], false);
+ spin_lock(&space_info->lock);
+ if (list_empty(&space_info->tickets)) {
+- space_info->flush = 0;
++ space_info->flush = false;
+ spin_unlock(&space_info->lock);
+ return;
+ }
+@@ -1199,7 +1199,7 @@ static void btrfs_async_reclaim_data_spa
+ if (maybe_fail_all_tickets(fs_info, space_info))
+ flush_state = 0;
+ else
+- space_info->flush = 0;
++ space_info->flush = false;
+ } else {
+ flush_state = 0;
+ }
+@@ -1510,7 +1510,7 @@ static int __reserve_bytes(struct btrfs_
+ */
+ maybe_clamp_preempt(fs_info, space_info);
+
+- space_info->flush = 1;
++ space_info->flush = true;
+ trace_btrfs_trigger_flush(fs_info,
+ space_info->flags,
+ orig_bytes, flush,
+--- a/fs/btrfs/space-info.h
++++ b/fs/btrfs/space-info.h
+@@ -28,11 +28,11 @@ struct btrfs_space_info {
+ flushing. The value is >> clamp, so turns
+ out to be a 2^clamp divisor. */
+
+- unsigned int full:1; /* indicates that we cannot allocate any more
++ bool full; /* indicates that we cannot allocate any more
+ chunks for this space */
+- unsigned int chunk_alloc:1; /* set if we are allocating a chunk */
++ bool chunk_alloc; /* set if we are allocating a chunk */
+
+- unsigned int flush:1; /* set if we are trying to make space */
++ bool flush; /* set if we are trying to make space */
+
+ unsigned int force_alloc; /* set if we need to force a chunk
+ alloc for this space */
--- /dev/null
+From stable+bounces-216316-greg=kroah.com@vger.kernel.org Sat Feb 14 01:54:34 2026
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 13 Feb 2026 19:54:27 -0500
+Subject: bus: fsl-mc: fix use-after-free in driver_override_show()
+To: stable@vger.kernel.org
+Cc: Gui-Dong Han <hanguidong02@gmail.com>, Ioana Ciornei <ioana.ciornei@nxp.com>, "Christophe Leroy (CS GROUP)" <chleroy@kernel.org>, Sasha Levin <sashal@kernel.org>
+Message-ID: <20260214005427.3653008-2-sashal@kernel.org>
+
+From: Gui-Dong Han <hanguidong02@gmail.com>
+
+[ Upstream commit 148891e95014b5dc5878acefa57f1940c281c431 ]
+
+The driver_override_show() function reads the driver_override string
+without holding the device_lock. However, driver_override_store() uses
+driver_set_override(), which modifies and frees the string while holding
+the device_lock.
+
+This can result in a concurrent use-after-free if the string is freed
+by the store function while being read by the show function.
+
+Fix this by holding the device_lock around the read operation.
+
+Fixes: 1f86a00c1159 ("bus/fsl-mc: add support for 'driver_override' in the mc-bus")
+Cc: stable@vger.kernel.org
+Signed-off-by: Gui-Dong Han <hanguidong02@gmail.com>
+Reviewed-by: Ioana Ciornei <ioana.ciornei@nxp.com>
+Link: https://lore.kernel.org/r/20251202174438.12658-1-hanguidong02@gmail.com
+Signed-off-by: Christophe Leroy (CS GROUP) <chleroy@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/bus/fsl-mc/fsl-mc-bus.c | 6 +++++-
+ 1 file changed, 5 insertions(+), 1 deletion(-)
+
+--- a/drivers/bus/fsl-mc/fsl-mc-bus.c
++++ b/drivers/bus/fsl-mc/fsl-mc-bus.c
+@@ -199,8 +199,12 @@ static ssize_t driver_override_show(stru
+ struct device_attribute *attr, char *buf)
+ {
+ struct fsl_mc_device *mc_dev = to_fsl_mc_device(dev);
++ ssize_t len;
+
+- return sysfs_emit(buf, "%s\n", mc_dev->driver_override);
++ device_lock(dev);
++ len = sysfs_emit(buf, "%s\n", mc_dev->driver_override);
++ device_unlock(dev);
++ return len;
+ }
+ static DEVICE_ATTR_RW(driver_override);
+
--- /dev/null
+From stable+bounces-216315-greg=kroah.com@vger.kernel.org Sat Feb 14 01:54:32 2026
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 13 Feb 2026 19:54:26 -0500
+Subject: bus: fsl-mc: Replace snprintf and sprintf with sysfs_emit in sysfs show functions
+To: stable@vger.kernel.org
+Cc: Chelsy Ratnawat <chelsyratnawat2001@gmail.com>, Ioana Ciornei <ioana.ciornei@nxp.com>, Christophe Leroy <christophe.leroy@csgroup.eu>, Sasha Levin <sashal@kernel.org>
+Message-ID: <20260214005427.3653008-1-sashal@kernel.org>
+
+From: Chelsy Ratnawat <chelsyratnawat2001@gmail.com>
+
+[ Upstream commit a50522c805a6c575c80f41b04706e084d814e116 ]
+
+Use sysfs_emit() instead of snprintf()/sprintf() when writing
+to sysfs buffers, as recommended by the kernel documentation.
+
+Signed-off-by: Chelsy Ratnawat <chelsyratnawat2001@gmail.com>
+Acked-by: Ioana Ciornei <ioana.ciornei@nxp.com>
+Link: https://lore.kernel.org/r/20250822124339.1739290-1-chelsyratnawat2001@gmail.com
+Signed-off-by: Christophe Leroy <christophe.leroy@csgroup.eu>
+Stable-dep-of: 148891e95014 ("bus: fsl-mc: fix use-after-free in driver_override_show()")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/bus/fsl-mc/fsl-mc-bus.c | 6 +++---
+ 1 file changed, 3 insertions(+), 3 deletions(-)
+
+--- a/drivers/bus/fsl-mc/fsl-mc-bus.c
++++ b/drivers/bus/fsl-mc/fsl-mc-bus.c
+@@ -156,8 +156,8 @@ static ssize_t modalias_show(struct devi
+ {
+ struct fsl_mc_device *mc_dev = to_fsl_mc_device(dev);
+
+- return sprintf(buf, "fsl-mc:v%08Xd%s\n", mc_dev->obj_desc.vendor,
+- mc_dev->obj_desc.type);
++ return sysfs_emit(buf, "fsl-mc:v%08Xd%s\n", mc_dev->obj_desc.vendor,
++ mc_dev->obj_desc.type);
+ }
+ static DEVICE_ATTR_RO(modalias);
+
+@@ -200,7 +200,7 @@ static ssize_t driver_override_show(stru
+ {
+ struct fsl_mc_device *mc_dev = to_fsl_mc_device(dev);
+
+- return snprintf(buf, PAGE_SIZE, "%s\n", mc_dev->driver_override);
++ return sysfs_emit(buf, "%s\n", mc_dev->driver_override);
+ }
+ static DEVICE_ATTR_RW(driver_override);
+
--- /dev/null
+From stable+bounces-216235-greg=kroah.com@vger.kernel.org Fri Feb 13 15:13:37 2026
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 13 Feb 2026 09:10:48 -0500
+Subject: crypto: virtio - Remove duplicated virtqueue_kick in virtio_crypto_skcipher_crypt_req
+To: stable@vger.kernel.org
+Cc: Bibo Mao <maobibo@loongson.cn>, Jason Wang <jasowang@redhat.com>, "Michael S. Tsirkin" <mst@redhat.com>, Herbert Xu <herbert@gondor.apana.org.au>, Sasha Levin <sashal@kernel.org>
+Message-ID: <20260213141048.3504475-1-sashal@kernel.org>
+
+From: Bibo Mao <maobibo@loongson.cn>
+
+[ Upstream commit 14f86a1155cca1176abf55987b2fce7f7fcb2455 ]
+
+With function virtio_crypto_skcipher_crypt_req(), there is already
+virtqueue_kick() call with spinlock held in function
+__virtio_crypto_skcipher_do_req(). Remove duplicated virtqueue_kick()
+function call here.
+
+Fixes: d79b5d0bbf2e ("crypto: virtio - support crypto engine framework")
+Cc: stable@vger.kernel.org
+Signed-off-by: Bibo Mao <maobibo@loongson.cn>
+Acked-by: Jason Wang <jasowang@redhat.com>
+Acked-by: Michael S. Tsirkin <mst@redhat.com>
+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/virtio/virtio_crypto_algs.c | 2 --
+ 1 file changed, 2 deletions(-)
+
+--- a/drivers/crypto/virtio/virtio_crypto_algs.c
++++ b/drivers/crypto/virtio/virtio_crypto_algs.c
+@@ -569,8 +569,6 @@ int virtio_crypto_skcipher_crypt_req(
+ if (ret < 0)
+ return ret;
+
+- virtqueue_kick(data_vq->vq);
+-
+ return 0;
+ }
+
--- /dev/null
+From stable+bounces-215984-greg=kroah.com@vger.kernel.org Thu Feb 12 18:42:13 2026
+From: "Matthieu Baerts (NGI0)" <matttbe@kernel.org>
+Date: Thu, 12 Feb 2026 18:41:47 +0100
+Subject: mptcp: fix race in mptcp_pm_nl_flush_addrs_doit()
+To: stable@vger.kernel.org, gregkh@linuxfoundation.org
+Cc: MPTCP Upstream <mptcp@lists.linux.dev>, Eric Dumazet <edumazet@google.com>, syzbot+5498a510ff9de39d37da@syzkaller.appspotmail.com, Eulgyu Kim <eulgyukim@snu.ac.kr>, Mat Martineau <martineau@kernel.org>, "Matthieu Baerts (NGI0)" <matttbe@kernel.org>, Jakub Kicinski <kuba@kernel.org>
+Message-ID: <20260212174146.1841030-2-matttbe@kernel.org>
+
+From: Eric Dumazet <edumazet@google.com>
+
+commit e2a9eeb69f7d4ca4cf4c70463af77664fdb6ab1d upstream.
+
+syzbot and Eulgyu Kim reported crashes in mptcp_pm_nl_get_local_id()
+and/or mptcp_pm_nl_is_backup()
+
+Root cause is list_splice_init() in mptcp_pm_nl_flush_addrs_doit()
+which is not RCU ready.
+
+list_splice_init_rcu() can not be called here while holding pernet->lock
+spinlock.
+
+Many thanks to Eulgyu Kim for providing a repro and testing our patches.
+
+Fixes: 141694df6573 ("mptcp: remove address when netlink flushes addrs")
+Signed-off-by: Eric Dumazet <edumazet@google.com>
+Reported-by: syzbot+5498a510ff9de39d37da@syzkaller.appspotmail.com
+Closes: https://lore.kernel.org/all/6970a46d.a00a0220.3ad28e.5cf0.GAE@google.com/T/
+Reported-by: Eulgyu Kim <eulgyukim@snu.ac.kr>
+Closes: https://github.com/multipath-tcp/mptcp_net-next/issues/611
+Reviewed-by: Mat Martineau <martineau@kernel.org>
+Signed-off-by: Matthieu Baerts (NGI0) <matttbe@kernel.org>
+Link: https://patch.msgid.link/20260124-net-mptcp-race_nl_flush_addrs-v3-1-b2dc1b613e9d@kernel.org
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+[ Conflicts because the code has been moved from pm_netlink.c to
+ pm_kernel.c later on in commit 8617e85e04bd ("mptcp: pm: split
+ in-kernel PM specific code"). The same modifications can be applied
+ in pm_netlink.c with one exception, because 'pernet->local_addr_list'
+ has been renamed to 'pernet->endp_list' in commit 35e71e43a56d
+ ("mptcp: pm: in-kernel: rename 'local_addr_list' to 'endp_list'"). The
+ previous name is then still being used in this version.
+ Also, another conflict is caused by commit 7bcf4d8022f9 ("mptcp: pm:
+ rename helpers linked to 'flush'") which is not in this version:
+ mptcp_nl_remove_addrs_list() has been renamed to
+ mptcp_nl_flush_addrs_list(). The previous name has then been kept. ]
+Signed-off-by: Matthieu Baerts (NGI0) <matttbe@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ net/mptcp/pm_netlink.c | 16 +++++++++++++---
+ 1 file changed, 13 insertions(+), 3 deletions(-)
+
+--- a/net/mptcp/pm_netlink.c
++++ b/net/mptcp/pm_netlink.c
+@@ -1656,16 +1656,26 @@ static void __reset_counters(struct pm_n
+ static int mptcp_nl_cmd_flush_addrs(struct sk_buff *skb, struct genl_info *info)
+ {
+ struct pm_nl_pernet *pernet = genl_info_pm_nl(info);
+- LIST_HEAD(free_list);
++ struct list_head free_list;
+
+ spin_lock_bh(&pernet->lock);
+- list_splice_init(&pernet->local_addr_list, &free_list);
++ free_list = pernet->local_addr_list;
++ INIT_LIST_HEAD_RCU(&pernet->local_addr_list);
+ __reset_counters(pernet);
+ pernet->next_id = 1;
+ bitmap_zero(pernet->id_bitmap, MAX_ADDR_ID + 1);
+ spin_unlock_bh(&pernet->lock);
+- mptcp_nl_remove_addrs_list(sock_net(skb->sk), &free_list);
++
++ if (free_list.next == &pernet->local_addr_list)
++ return 0;
++
+ synchronize_rcu();
++
++ /* Adjust the pointers to free_list instead of pernet->local_addr_list */
++ free_list.prev->next = &free_list;
++ free_list.next->prev = &free_list;
++
++ mptcp_nl_remove_addrs_list(sock_net(skb->sk), &free_list);
+ __flush_addrs(&free_list);
+ return 0;
+ }
--- /dev/null
+From lanbincn@139.com Thu Feb 12 11:52:47 2026
+From: Bin Lan <lanbincn@139.com>
+Date: Thu, 12 Feb 2026 10:52:36 +0000
+Subject: net: dsa: free routing table on probe failure
+To: stable@vger.kernel.org, gregkh@linuxfoundation.org
+Cc: Vladimir Oltean <vladimir.oltean@nxp.com>, Jakub Kicinski <kuba@kernel.org>, Bin Lan <lanbincn@139.com>
+Message-ID: <20260212105236.4180-1-lanbincn@139.com>
+
+From: Vladimir Oltean <vladimir.oltean@nxp.com>
+
+[ Upstream commit 8bf108d7161ffc6880ad13a0cc109de3cf631727 ]
+
+If complete = true in dsa_tree_setup(), it means that we are the last
+switch of the tree which is successfully probing, and we should be
+setting up all switches from our probe path.
+
+After "complete" becomes true, dsa_tree_setup_cpu_ports() or any
+subsequent function may fail. If that happens, the entire tree setup is
+in limbo: the first N-1 switches have successfully finished probing
+(doing nothing but having allocated persistent memory in the tree's
+dst->ports, and maybe dst->rtable), and switch N failed to probe, ending
+the tree setup process before anything is tangible from the user's PoV.
+
+If switch N fails to probe, its memory (ports) will be freed and removed
+from dst->ports. However, the dst->rtable elements pointing to its ports,
+as created by dsa_link_touch(), will remain there, and will lead to
+use-after-free if dereferenced.
+
+If dsa_tree_setup_switches() returns -EPROBE_DEFER, which is entirely
+possible because that is where ds->ops->setup() is, we get a kasan
+report like this:
+
+==================================================================
+BUG: KASAN: slab-use-after-free in mv88e6xxx_setup_upstream_port+0x240/0x568
+Read of size 8 at addr ffff000004f56020 by task kworker/u8:3/42
+
+Call trace:
+ __asan_report_load8_noabort+0x20/0x30
+ mv88e6xxx_setup_upstream_port+0x240/0x568
+ mv88e6xxx_setup+0xebc/0x1eb0
+ dsa_register_switch+0x1af4/0x2ae0
+ mv88e6xxx_register_switch+0x1b8/0x2a8
+ mv88e6xxx_probe+0xc4c/0xf60
+ mdio_probe+0x78/0xb8
+ really_probe+0x2b8/0x5a8
+ __driver_probe_device+0x164/0x298
+ driver_probe_device+0x78/0x258
+ __device_attach_driver+0x274/0x350
+
+Allocated by task 42:
+ __kasan_kmalloc+0x84/0xa0
+ __kmalloc_cache_noprof+0x298/0x490
+ dsa_switch_touch_ports+0x174/0x3d8
+ dsa_register_switch+0x800/0x2ae0
+ mv88e6xxx_register_switch+0x1b8/0x2a8
+ mv88e6xxx_probe+0xc4c/0xf60
+ mdio_probe+0x78/0xb8
+ really_probe+0x2b8/0x5a8
+ __driver_probe_device+0x164/0x298
+ driver_probe_device+0x78/0x258
+ __device_attach_driver+0x274/0x350
+
+Freed by task 42:
+ __kasan_slab_free+0x48/0x68
+ kfree+0x138/0x418
+ dsa_register_switch+0x2694/0x2ae0
+ mv88e6xxx_register_switch+0x1b8/0x2a8
+ mv88e6xxx_probe+0xc4c/0xf60
+ mdio_probe+0x78/0xb8
+ really_probe+0x2b8/0x5a8
+ __driver_probe_device+0x164/0x298
+ driver_probe_device+0x78/0x258
+ __device_attach_driver+0x274/0x350
+
+The simplest way to fix the bug is to delete the routing table in its
+entirety. dsa_tree_setup_routing_table() has no problem in regenerating
+it even if we deleted links between ports other than those of switch N,
+because dsa_link_touch() first checks whether the port pair already
+exists in dst->rtable, allocating if not.
+
+The deletion of the routing table in its entirety already exists in
+dsa_tree_teardown(), so refactor that into a function that can also be
+called from the tree setup error path.
+
+In my analysis of the commit to blame, it is the one which added
+dsa_link elements to dst->rtable. Prior to that, each switch had its own
+ds->rtable which is freed when the switch fails to probe. But the tree
+is potentially persistent memory.
+
+Fixes: c5f51765a1f6 ("net: dsa: list DSA links in the fabric")
+Signed-off-by: Vladimir Oltean <vladimir.oltean@nxp.com>
+Link: https://patch.msgid.link/20250414213001.2957964-1-vladimir.oltean@nxp.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+[ Backport the fix to net/dsa/dsa2.c in v5.15.y for dsa2.c was
+renamed back into dsa.c by commit
+47d2ce03dcfb ("net: dsa: rename dsa2.c back into dsa.c and create its header")
+since v6.2. ]
+Signed-off-by: Bin Lan <lanbincn@139.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ net/dsa/dsa2.c | 21 ++++++++++++++-------
+ 1 file changed, 14 insertions(+), 7 deletions(-)
+
+--- a/net/dsa/dsa2.c
++++ b/net/dsa/dsa2.c
+@@ -1079,6 +1079,16 @@ static void dsa_tree_teardown_lags(struc
+ kfree(dst->lags);
+ }
+
++static void dsa_tree_teardown_routing_table(struct dsa_switch_tree *dst)
++{
++ struct dsa_link *dl, *next;
++
++ list_for_each_entry_safe(dl, next, &dst->rtable, list) {
++ list_del(&dl->list);
++ kfree(dl);
++ }
++}
++
+ static int dsa_tree_setup(struct dsa_switch_tree *dst)
+ {
+ bool complete;
+@@ -1096,7 +1106,7 @@ static int dsa_tree_setup(struct dsa_swi
+
+ err = dsa_tree_setup_cpu_ports(dst);
+ if (err)
+- return err;
++ goto teardown_rtable;
+
+ err = dsa_tree_setup_switches(dst);
+ if (err)
+@@ -1123,14 +1133,14 @@ teardown_switches:
+ dsa_tree_teardown_switches(dst);
+ teardown_cpu_ports:
+ dsa_tree_teardown_cpu_ports(dst);
++teardown_rtable:
++ dsa_tree_teardown_routing_table(dst);
+
+ return err;
+ }
+
+ static void dsa_tree_teardown(struct dsa_switch_tree *dst)
+ {
+- struct dsa_link *dl, *next;
+-
+ if (!dst->setup)
+ return;
+
+@@ -1144,10 +1154,7 @@ static void dsa_tree_teardown(struct dsa
+
+ dsa_tree_teardown_cpu_ports(dst);
+
+- list_for_each_entry_safe(dl, next, &dst->rtable, list) {
+- list_del(&dl->list);
+- kfree(dl);
+- }
++ dsa_tree_teardown_routing_table(dst);
+
+ pr_info("DSA: tree %d torn down\n", dst->index);
+
--- /dev/null
+From stable+bounces-216477-greg=kroah.com@vger.kernel.org Sat Feb 14 14:03:01 2026
+From: Sasha Levin <sashal@kernel.org>
+Date: Sat, 14 Feb 2026 08:02:52 -0500
+Subject: PCI: endpoint: Automatically create a function specific attributes group
+To: stable@vger.kernel.org
+Cc: Damien Le Moal <dlemoal@kernel.org>, Lorenzo Pieralisi <lpieralisi@kernel.org>, Bjorn Helgaas <bhelgaas@google.com>, Manivannan Sadhasivam <mani@kernel.org>, Sasha Levin <sashal@kernel.org>
+Message-ID: <20260214130254.345213-1-sashal@kernel.org>
+
+From: Damien Le Moal <dlemoal@kernel.org>
+
+[ Upstream commit 70b3740f2c1941e2006d61539131b70d20cba9a6 ]
+
+A PCI endpoint function driver can define function specific attributes
+under its function configfs directory using the add_cfs() endpoint driver
+operation. This is done by tying up the mkdir operation for the function
+configfs directory to a call to the add_cfs() operation. However, there
+are no checks preventing the user from repeatedly creating function
+specific attribute directories with different names, resulting in the same
+endpoint specific attributes group being added multiple times, which also
+result in an invalid reference counting for the attribute groups. E.g.,
+using the pci-epf-ntb function driver as an example, the user creates the
+function as follows:
+
+ $ modprobe pci-epf-ntb
+ $ cd /sys/kernel/config/pci_ep/functions/pci_epf_ntb
+ $ mkdir func0
+ $ tree func0
+ func0/
+ |-- baseclass_code
+ |-- cache_line_size
+ |-- ...
+ `-- vendorid
+
+ $ mkdir func0/attrs
+ $ tree func0
+ func0/
+ |-- attrs
+ | |-- db_count
+ | |-- mw1
+ | |-- mw2
+ | |-- mw3
+ | |-- mw4
+ | |-- num_mws
+ | `-- spad_count
+ |-- baseclass_code
+ |-- cache_line_size
+ |-- ...
+ `-- vendorid
+
+At this point, the function can be started by linking the EP controller.
+However, if the user mistakenly creates again a directory:
+
+ $ mkdir func0/attrs2
+ $ tree func0
+ func0/
+ |-- attrs
+ | |-- db_count
+ | |-- mw1
+ | |-- mw2
+ | |-- mw3
+ | |-- mw4
+ | |-- num_mws
+ | `-- spad_count
+ |-- attrs2
+ | |-- db_count
+ | |-- mw1
+ | |-- mw2
+ | |-- mw3
+ | |-- mw4
+ | |-- num_mws
+ | `-- spad_count
+ |-- baseclass_code
+ |-- cache_line_size
+ |-- ...
+ `-- vendorid
+
+The endpoint function specific attributes are duplicated and cause a crash
+when the endpoint function device is torn down:
+
+ refcount_t: addition on 0; use-after-free.
+ WARNING: CPU: 2 PID: 834 at lib/refcount.c:25 refcount_warn_saturate+0xc8/0x144
+ CPU: 2 PID: 834 Comm: rmdir Not tainted 6.3.0-rc1 #1
+ Hardware name: Pine64 RockPro64 v2.1 (DT)
+ pstate: 60000005 (nZCv daif -PAN -UAO -TCO -DIT -SSBS BTYPE=--)
+ ...
+ Call trace:
+ refcount_warn_saturate+0xc8/0x144
+ config_item_get+0x7c/0x80
+ configfs_rmdir+0x17c/0x30c
+ vfs_rmdir+0x8c/0x204
+ do_rmdir+0x158/0x184
+ __arm64_sys_unlinkat+0x64/0x80
+ invoke_syscall+0x48/0x114
+ ...
+
+Fix this by modifying pci_epf_cfs_work() to execute the new function
+pci_ep_cfs_add_type_group() which itself calls pci_epf_type_add_cfs() to
+obtain the function specific attribute group and the group name (directory
+name) from the endpoint function driver. If the function driver defines an
+attribute group, pci_ep_cfs_add_type_group() then proceeds to register this
+group using configfs_register_group(), thus automatically exposing the
+function type specific configfs attributes to the user. E.g.:
+
+ $ modprobe pci-epf-ntb
+ $ cd /sys/kernel/config/pci_ep/functions/pci_epf_ntb
+ $ mkdir func0
+ $ tree func0
+ func0/
+ |-- baseclass_code
+ |-- cache_line_size
+ |-- ...
+ |-- pci_epf_ntb.0
+ | |-- db_count
+ | |-- mw1
+ | |-- mw2
+ | |-- mw3
+ | |-- mw4
+ | |-- num_mws
+ | `-- spad_count
+ |-- primary
+ |-- ...
+ `-- vendorid
+
+With this change, there is no need for the user to create or delete
+directories in the endpoint function attributes directory. The
+pci_epf_type_group_ops group operations are thus removed.
+
+Also update the documentation for the pci-epf-ntb and pci-epf-vntb function
+drivers to reflect this change, removing the explanations showing the need
+to manually create the sub-directory for the function specific attributes.
+
+Link: https://lore.kernel.org/r/20230415023542.77601-2-dlemoal@kernel.org
+Signed-off-by: Damien Le Moal <dlemoal@kernel.org>
+Signed-off-by: Lorenzo Pieralisi <lpieralisi@kernel.org>
+Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>
+Reviewed-by: Manivannan Sadhasivam <mani@kernel.org>
+Stable-dep-of: 7c5c7d06bd1f ("PCI: endpoint: Avoid creating sub-groups asynchronously")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ Documentation/PCI/endpoint/pci-ntb-howto.rst | 11 ++-----
+ drivers/pci/endpoint/pci-ep-cfs.c | 42 ++++++++++++---------------
+ 2 files changed, 24 insertions(+), 29 deletions(-)
+
+--- a/Documentation/PCI/endpoint/pci-ntb-howto.rst
++++ b/Documentation/PCI/endpoint/pci-ntb-howto.rst
+@@ -88,13 +88,10 @@ commands can be used::
+ # echo 0x104c > functions/pci_epf_ntb/func1/vendorid
+ # echo 0xb00d > functions/pci_epf_ntb/func1/deviceid
+
+-In order to configure NTB specific attributes, a new sub-directory to func1
+-should be created::
+-
+- # mkdir functions/pci_epf_ntb/func1/pci_epf_ntb.0/
+-
+-The NTB function driver will populate this directory with various attributes
+-that can be configured by the user::
++The PCI endpoint framework also automatically creates a sub-directory in the
++function attribute directory. This sub-directory has the same name as the name
++of the function device and is populated with the following NTB specific
++attributes that can be configured by the user::
+
+ # ls functions/pci_epf_ntb/func1/pci_epf_ntb.0/
+ db_count mw1 mw2 mw3 mw4 num_mws
+--- a/drivers/pci/endpoint/pci-ep-cfs.c
++++ b/drivers/pci/endpoint/pci-ep-cfs.c
+@@ -23,6 +23,7 @@ struct pci_epf_group {
+ struct config_group group;
+ struct config_group primary_epc_group;
+ struct config_group secondary_epc_group;
++ struct config_group *type_group;
+ struct delayed_work cfs_work;
+ struct pci_epf *epf;
+ int index;
+@@ -514,34 +515,29 @@ static struct configfs_item_operations p
+ .release = pci_epf_release,
+ };
+
+-static struct config_group *pci_epf_type_make(struct config_group *group,
+- const char *name)
+-{
+- struct pci_epf_group *epf_group = to_pci_epf_group(&group->cg_item);
+- struct config_group *epf_type_group;
+-
+- epf_type_group = pci_epf_type_add_cfs(epf_group->epf, group);
+- return epf_type_group;
+-}
+-
+-static void pci_epf_type_drop(struct config_group *group,
+- struct config_item *item)
+-{
+- config_item_put(item);
+-}
+-
+-static struct configfs_group_operations pci_epf_type_group_ops = {
+- .make_group = &pci_epf_type_make,
+- .drop_item = &pci_epf_type_drop,
+-};
+-
+ static const struct config_item_type pci_epf_type = {
+- .ct_group_ops = &pci_epf_type_group_ops,
+ .ct_item_ops = &pci_epf_ops,
+ .ct_attrs = pci_epf_attrs,
+ .ct_owner = THIS_MODULE,
+ };
+
++static void pci_ep_cfs_add_type_group(struct pci_epf_group *epf_group)
++{
++ struct config_group *group;
++
++ group = pci_epf_type_add_cfs(epf_group->epf, &epf_group->group);
++ if (!group)
++ return;
++
++ if (IS_ERR(group)) {
++ dev_err(&epf_group->epf->dev,
++ "failed to create epf type specific attributes\n");
++ return;
++ }
++
++ configfs_register_group(&epf_group->group, group);
++}
++
+ static void pci_epf_cfs_work(struct work_struct *work)
+ {
+ struct pci_epf_group *epf_group;
+@@ -559,6 +555,8 @@ static void pci_epf_cfs_work(struct work
+ pr_err("failed to create 'secondary' EPC interface\n");
+ return;
+ }
++
++ pci_ep_cfs_add_type_group(epf_group);
+ }
+
+ static struct config_group *pci_epf_make(struct config_group *group,
--- /dev/null
+From stable+bounces-216479-greg=kroah.com@vger.kernel.org Sat Feb 14 14:03:04 2026
+From: Sasha Levin <sashal@kernel.org>
+Date: Sat, 14 Feb 2026 08:02:54 -0500
+Subject: PCI: endpoint: Avoid creating sub-groups asynchronously
+To: stable@vger.kernel.org
+Cc: Liu Song <liu.song13@zte.com.cn>, Manivannan Sadhasivam <mani@kernel.org>, Bjorn Helgaas <bhelgaas@google.com>, stable@kernel.org, Sasha Levin <sashal@kernel.org>
+Message-ID: <20260214130254.345213-3-sashal@kernel.org>
+
+From: Liu Song <liu.song13@zte.com.cn>
+
+[ Upstream commit 7c5c7d06bd1f86d2c3ebe62be903a4ba42db4d2c ]
+
+The asynchronous creation of sub-groups by a delayed work could lead to a
+NULL pointer dereference when the driver directory is removed before the
+work completes.
+
+The crash can be easily reproduced with the following commands:
+
+ # cd /sys/kernel/config/pci_ep/functions/pci_epf_test
+ # for i in {1..20}; do mkdir test && rmdir test; done
+
+ BUG: kernel NULL pointer dereference, address: 0000000000000088
+ ...
+ Call Trace:
+ configfs_register_group+0x3d/0x190
+ pci_epf_cfs_work+0x41/0x110
+ process_one_work+0x18f/0x350
+ worker_thread+0x25a/0x3a0
+
+Fix this issue by using configfs_add_default_group() API which does not
+have the deadlock problem as configfs_register_group() and does not require
+the delayed work handler.
+
+Fixes: e85a2d783762 ("PCI: endpoint: Add support in configfs to associate two EPCs with EPF")
+Signed-off-by: Liu Song <liu.song13@zte.com.cn>
+[mani: slightly reworded the description and added stable list]
+Signed-off-by: Manivannan Sadhasivam <mani@kernel.org>
+Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>
+Cc: stable@kernel.org
+Link: https://patch.msgid.link/20250710143845409gLM6JdlwPhlHG9iX3F6jK@zte.com.cn
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/pci/endpoint/pci-ep-cfs.c | 15 +++++----------
+ 1 file changed, 5 insertions(+), 10 deletions(-)
+
+--- a/drivers/pci/endpoint/pci-ep-cfs.c
++++ b/drivers/pci/endpoint/pci-ep-cfs.c
+@@ -23,7 +23,6 @@ struct pci_epf_group {
+ struct config_group group;
+ struct config_group primary_epc_group;
+ struct config_group secondary_epc_group;
+- struct delayed_work cfs_work;
+ struct pci_epf *epf;
+ int index;
+ };
+@@ -100,7 +99,7 @@ static struct config_group
+ secondary_epc_group = &epf_group->secondary_epc_group;
+ config_group_init_type_name(secondary_epc_group, "secondary",
+ &pci_secondary_epc_type);
+- configfs_register_group(&epf_group->group, secondary_epc_group);
++ configfs_add_default_group(secondary_epc_group, &epf_group->group);
+
+ return secondary_epc_group;
+ }
+@@ -160,7 +159,7 @@ static struct config_group
+
+ config_group_init_type_name(primary_epc_group, "primary",
+ &pci_primary_epc_type);
+- configfs_register_group(&epf_group->group, primary_epc_group);
++ configfs_add_default_group(primary_epc_group, &epf_group->group);
+
+ return primary_epc_group;
+ }
+@@ -534,15 +533,13 @@ static void pci_ep_cfs_add_type_group(st
+ return;
+ }
+
+- configfs_register_group(&epf_group->group, group);
++ configfs_add_default_group(group, &epf_group->group);
+ }
+
+-static void pci_epf_cfs_work(struct work_struct *work)
++static void pci_epf_cfs_add_sub_groups(struct pci_epf_group *epf_group)
+ {
+- struct pci_epf_group *epf_group;
+ struct config_group *group;
+
+- epf_group = container_of(work, struct pci_epf_group, cfs_work.work);
+ group = pci_ep_cfs_add_primary_group(epf_group);
+ if (IS_ERR(group)) {
+ pr_err("failed to create 'primary' EPC interface\n");
+@@ -601,9 +598,7 @@ static struct config_group *pci_epf_make
+
+ kfree(epf_name);
+
+- INIT_DELAYED_WORK(&epf_group->cfs_work, pci_epf_cfs_work);
+- queue_delayed_work(system_wq, &epf_group->cfs_work,
+- msecs_to_jiffies(1));
++ pci_epf_cfs_add_sub_groups(epf_group);
+
+ return &epf_group->group;
+
--- /dev/null
+From stable+bounces-216478-greg=kroah.com@vger.kernel.org Sat Feb 14 14:03:03 2026
+From: Sasha Levin <sashal@kernel.org>
+Date: Sat, 14 Feb 2026 08:02:53 -0500
+Subject: PCI: endpoint: Remove unused field in struct pci_epf_group
+To: stable@vger.kernel.org
+Cc: "Christophe JAILLET" <christophe.jaillet@wanadoo.fr>, "Krzysztof Wilczyński" <kwilczynski@kernel.org>, "Bjorn Helgaas" <bhelgaas@google.com>, "Sasha Levin" <sashal@kernel.org>
+Message-ID: <20260214130254.345213-2-sashal@kernel.org>
+
+From: Christophe JAILLET <christophe.jaillet@wanadoo.fr>
+
+[ Upstream commit 328e4dffbeecc0f2cc5a149dee6c11a0577c9671 ]
+
+In "struct pci_epf_group", the 'type_group' field is unused.
+
+This was added, but already unused, by commit 70b3740f2c19 ("PCI: endpoint:
+Automatically create a function specific attributes group").
+
+Thus, remove it.
+
+Found with cppcheck, unusedStructMember.
+
+[kwilczynski: commit log]
+Link: https://lore.kernel.org/linux-pci/6507d44b6c60a19af35a605e2d58050be8872ab6.1712341008.git.christophe.jaillet@wanadoo.fr
+Signed-off-by: Christophe JAILLET <christophe.jaillet@wanadoo.fr>
+Signed-off-by: Krzysztof Wilczyński <kwilczynski@kernel.org>
+Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>
+Stable-dep-of: 7c5c7d06bd1f ("PCI: endpoint: Avoid creating sub-groups asynchronously")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/pci/endpoint/pci-ep-cfs.c | 1 -
+ 1 file changed, 1 deletion(-)
+
+--- a/drivers/pci/endpoint/pci-ep-cfs.c
++++ b/drivers/pci/endpoint/pci-ep-cfs.c
+@@ -23,7 +23,6 @@ struct pci_epf_group {
+ struct config_group group;
+ struct config_group primary_epc_group;
+ struct config_group secondary_epc_group;
+- struct config_group *type_group;
+ struct delayed_work cfs_work;
+ struct pci_epf *epf;
+ int index;
--- /dev/null
+From stable+bounces-216476-greg=kroah.com@vger.kernel.org Sat Feb 14 14:02:42 2026
+From: Sasha Levin <sashal@kernel.org>
+Date: Sat, 14 Feb 2026 08:02:35 -0500
+Subject: scsi: qla2xxx: Fix bsg_done() causing double free
+To: stable@vger.kernel.org
+Cc: Anil Gurumurthy <agurumurthy@marvell.com>, Nilesh Javali <njavali@marvell.com>, Himanshu Madhani <hmadhani2024@gmail.com>, "Martin K. Petersen" <martin.petersen@oracle.com>, Sasha Levin <sashal@kernel.org>
+Message-ID: <20260214130235.343904-1-sashal@kernel.org>
+
+From: Anil Gurumurthy <agurumurthy@marvell.com>
+
+[ Upstream commit c2c68225b1456f4d0d393b5a8778d51bb0d5b1d0 ]
+
+Kernel panic observed on system,
+
+[5353358.825191] BUG: unable to handle page fault for address: ff5f5e897b024000
+[5353358.825194] #PF: supervisor write access in kernel mode
+[5353358.825195] #PF: error_code(0x0002) - not-present page
+[5353358.825196] PGD 100006067 P4D 0
+[5353358.825198] Oops: 0002 [#1] PREEMPT SMP NOPTI
+[5353358.825200] CPU: 5 PID: 2132085 Comm: qlafwupdate.sub Kdump: loaded Tainted: G W L ------- --- 5.14.0-503.34.1.el9_5.x86_64 #1
+[5353358.825203] Hardware name: HPE ProLiant DL360 Gen11/ProLiant DL360 Gen11, BIOS 2.44 01/17/2025
+[5353358.825204] RIP: 0010:memcpy_erms+0x6/0x10
+[5353358.825211] RSP: 0018:ff591da8f4f6b710 EFLAGS: 00010246
+[5353358.825212] RAX: ff5f5e897b024000 RBX: 0000000000007090 RCX: 0000000000001000
+[5353358.825213] RDX: 0000000000001000 RSI: ff591da8f4fed090 RDI: ff5f5e897b024000
+[5353358.825214] RBP: 0000000000010000 R08: ff5f5e897b024000 R09: 0000000000000000
+[5353358.825215] R10: ff46cf8c40517000 R11: 0000000000000001 R12: 0000000000008090
+[5353358.825216] R13: ff591da8f4f6b720 R14: 0000000000001000 R15: 0000000000000000
+[5353358.825218] FS: 00007f1e88d47740(0000) GS:ff46cf935f940000(0000) knlGS:0000000000000000
+[5353358.825219] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
+[5353358.825220] CR2: ff5f5e897b024000 CR3: 0000000231532004 CR4: 0000000000771ef0
+[5353358.825221] PKRU: 55555554
+[5353358.825222] Call Trace:
+[5353358.825223] <TASK>
+[5353358.825224] ? show_trace_log_lvl+0x1c4/0x2df
+[5353358.825229] ? show_trace_log_lvl+0x1c4/0x2df
+[5353358.825232] ? sg_copy_buffer+0xc8/0x110
+[5353358.825236] ? __die_body.cold+0x8/0xd
+[5353358.825238] ? page_fault_oops+0x134/0x170
+[5353358.825242] ? kernelmode_fixup_or_oops+0x84/0x110
+[5353358.825244] ? exc_page_fault+0xa8/0x150
+[5353358.825247] ? asm_exc_page_fault+0x22/0x30
+[5353358.825252] ? memcpy_erms+0x6/0x10
+[5353358.825253] sg_copy_buffer+0xc8/0x110
+[5353358.825259] qla2x00_process_vendor_specific+0x652/0x1320 [qla2xxx]
+[5353358.825317] qla24xx_bsg_request+0x1b2/0x2d0 [qla2xxx]
+
+Most routines in qla_bsg.c call bsg_done() only for success cases.
+However a few invoke it for failure case as well leading to a double
+free. Validate before calling bsg_done().
+
+Cc: stable@vger.kernel.org
+Signed-off-by: Anil Gurumurthy <agurumurthy@marvell.com>
+Signed-off-by: Nilesh Javali <njavali@marvell.com>
+Reviewed-by: Himanshu Madhani <hmadhani2024@gmail.com>
+Link: https://patch.msgid.link/20251210101604.431868-12-njavali@marvell.com
+Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/scsi/qla2xxx/qla_bsg.c | 25 +++++++++++++++----------
+ 1 file changed, 15 insertions(+), 10 deletions(-)
+
+--- a/drivers/scsi/qla2xxx/qla_bsg.c
++++ b/drivers/scsi/qla2xxx/qla_bsg.c
+@@ -1546,8 +1546,9 @@ qla2x00_update_optrom(struct bsg_job *bs
+ ha->optrom_buffer = NULL;
+ ha->optrom_state = QLA_SWAITING;
+ mutex_unlock(&ha->optrom_mutex);
+- bsg_job_done(bsg_job, bsg_reply->result,
+- bsg_reply->reply_payload_rcv_len);
++ if (!rval)
++ bsg_job_done(bsg_job, bsg_reply->result,
++ bsg_reply->reply_payload_rcv_len);
+ return rval;
+ }
+
+@@ -2525,8 +2526,9 @@ qla2x00_manage_host_stats(struct bsg_job
+ sizeof(struct ql_vnd_mng_host_stats_resp));
+
+ bsg_reply->result = DID_OK;
+- bsg_job_done(bsg_job, bsg_reply->result,
+- bsg_reply->reply_payload_rcv_len);
++ if (!ret)
++ bsg_job_done(bsg_job, bsg_reply->result,
++ bsg_reply->reply_payload_rcv_len);
+
+ return ret;
+ }
+@@ -2615,8 +2617,9 @@ qla2x00_get_host_stats(struct bsg_job *b
+ bsg_job->reply_payload.sg_cnt,
+ data, response_len);
+ bsg_reply->result = DID_OK;
+- bsg_job_done(bsg_job, bsg_reply->result,
+- bsg_reply->reply_payload_rcv_len);
++ if (!ret)
++ bsg_job_done(bsg_job, bsg_reply->result,
++ bsg_reply->reply_payload_rcv_len);
+
+ kfree(data);
+ host_stat_out:
+@@ -2715,8 +2718,9 @@ reply:
+ bsg_job->reply_payload.sg_cnt, data,
+ response_len);
+ bsg_reply->result = DID_OK;
+- bsg_job_done(bsg_job, bsg_reply->result,
+- bsg_reply->reply_payload_rcv_len);
++ if (!ret)
++ bsg_job_done(bsg_job, bsg_reply->result,
++ bsg_reply->reply_payload_rcv_len);
+
+ tgt_stat_out:
+ kfree(data);
+@@ -2777,8 +2781,9 @@ qla2x00_manage_host_port(struct bsg_job
+ bsg_job->reply_payload.sg_cnt, &rsp_data,
+ sizeof(struct ql_vnd_mng_host_port_resp));
+ bsg_reply->result = DID_OK;
+- bsg_job_done(bsg_job, bsg_reply->result,
+- bsg_reply->reply_payload_rcv_len);
++ if (!ret)
++ bsg_job_done(bsg_job, bsg_reply->result,
++ bsg_reply->reply_payload_rcv_len);
+
+ return ret;
+ }
--- /dev/null
+From stable+bounces-216273-greg=kroah.com@vger.kernel.org Fri Feb 13 17:47:07 2026
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 13 Feb 2026 11:45:03 -0500
+Subject: scsi: qla2xxx: Free sp in error path to fix system crash
+To: stable@vger.kernel.org
+Cc: Anil Gurumurthy <agurumurthy@marvell.com>, Nilesh Javali <njavali@marvell.com>, Himanshu Madhani <hmadhani2024@gmail.com>, "Martin K. Petersen" <martin.petersen@oracle.com>, Sasha Levin <sashal@kernel.org>
+Message-ID: <20260213164503.3564614-4-sashal@kernel.org>
+
+From: Anil Gurumurthy <agurumurthy@marvell.com>
+
+[ Upstream commit 7adbd2b7809066c75f0433e5e2a8e114b429f30f ]
+
+System crash seen during load/unload test in a loop,
+
+[61110.449331] qla2xxx [0000:27:00.0]-0042:0: Disabled MSI-X.
+[61110.467494] =============================================================================
+[61110.467498] BUG qla2xxx_srbs (Tainted: G OE -------- --- ): Objects remaining in qla2xxx_srbs on __kmem_cache_shutdown()
+[61110.467501] -----------------------------------------------------------------------------
+
+[61110.467502] Slab 0x000000000ffc8162 objects=51 used=1 fp=0x00000000e25d3d85 flags=0x57ffffc0010200(slab|head|node=1|zone=2|lastcpupid=0x1fffff)
+[61110.467509] CPU: 53 PID: 455206 Comm: rmmod Kdump: loaded Tainted: G OE -------- --- 5.14.0-284.11.1.el9_2.x86_64 #1
+[61110.467513] Hardware name: HPE ProLiant DL385 Gen10 Plus v2/ProLiant DL385 Gen10 Plus v2, BIOS A42 08/17/2023
+[61110.467515] Call Trace:
+[61110.467516] <TASK>
+[61110.467519] dump_stack_lvl+0x34/0x48
+[61110.467526] slab_err.cold+0x53/0x67
+[61110.467534] __kmem_cache_shutdown+0x16e/0x320
+[61110.467540] kmem_cache_destroy+0x51/0x160
+[61110.467544] qla2x00_module_exit+0x93/0x99 [qla2xxx]
+[61110.467607] ? __do_sys_delete_module.constprop.0+0x178/0x280
+[61110.467613] ? syscall_trace_enter.constprop.0+0x145/0x1d0
+[61110.467616] ? do_syscall_64+0x5c/0x90
+[61110.467619] ? exc_page_fault+0x62/0x150
+[61110.467622] ? entry_SYSCALL_64_after_hwframe+0x63/0xcd
+[61110.467626] </TASK>
+[61110.467627] Disabling lock debugging due to kernel taint
+[61110.467635] Object 0x0000000026f7e6e6 @offset=16000
+[61110.467639] ------------[ cut here ]------------
+[61110.467639] kmem_cache_destroy qla2xxx_srbs: Slab cache still has objects when called from qla2x00_module_exit+0x93/0x99 [qla2xxx]
+[61110.467659] WARNING: CPU: 53 PID: 455206 at mm/slab_common.c:520 kmem_cache_destroy+0x14d/0x160
+[61110.467718] CPU: 53 PID: 455206 Comm: rmmod Kdump: loaded Tainted: G B OE -------- --- 5.14.0-284.11.1.el9_2.x86_64 #1
+[61110.467720] Hardware name: HPE ProLiant DL385 Gen10 Plus v2/ProLiant DL385 Gen10 Plus v2, BIOS A42 08/17/2023
+[61110.467721] RIP: 0010:kmem_cache_destroy+0x14d/0x160
+[61110.467724] Code: 99 7d 07 00 48 89 ef e8 e1 6a 07 00 eb b3 48 8b 55 60 48 8b 4c 24 20 48 c7 c6 70 fc 66 90 48 c7 c7 f8 ef a1 90 e8 e1 ed 7c 00 <0f> 0b eb 93 c3 cc cc cc cc 66 2e 0f 1f 84 00 00 00 00 00 55 48 89
+[61110.467725] RSP: 0018:ffffa304e489fe80 EFLAGS: 00010282
+[61110.467727] RAX: 0000000000000000 RBX: ffffffffc0d9a860 RCX: 0000000000000027
+[61110.467729] RDX: ffff8fd5ff9598a8 RSI: 0000000000000001 RDI: ffff8fd5ff9598a0
+[61110.467730] RBP: ffff8fb6aaf78700 R08: 0000000000000000 R09: 0000000100d863b7
+[61110.467731] R10: ffffa304e489fd20 R11: ffffffff913bef48 R12: 0000000040002000
+[61110.467731] R13: 0000000000000000 R14: 0000000000000000 R15: 0000000000000000
+[61110.467733] FS: 00007f64c89fb740(0000) GS:ffff8fd5ff940000(0000) knlGS:0000000000000000
+[61110.467734] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
+[61110.467735] CR2: 00007f0f02bfe000 CR3: 00000020ad6dc005 CR4: 0000000000770ee0
+[61110.467736] PKRU: 55555554
+[61110.467737] Call Trace:
+[61110.467738] <TASK>
+[61110.467739] qla2x00_module_exit+0x93/0x99 [qla2xxx]
+[61110.467755] ? __do_sys_delete_module.constprop.0+0x178/0x280
+
+Free sp in the error path to fix the crash.
+
+Fixes: f352eeb75419 ("scsi: qla2xxx: Add ability to use GPNFT/GNNFT for RSCN handling")
+Cc: stable@vger.kernel.org
+Signed-off-by: Anil Gurumurthy <agurumurthy@marvell.com>
+Signed-off-by: Nilesh Javali <njavali@marvell.com>
+Reviewed-by: Himanshu Madhani <hmadhani2024@gmail.com>
+Link: https://patch.msgid.link/20251210101604.431868-9-njavali@marvell.com
+Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/scsi/qla2xxx/qla_gs.c | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+--- a/drivers/scsi/qla2xxx/qla_gs.c
++++ b/drivers/scsi/qla2xxx/qla_gs.c
+@@ -3921,8 +3921,8 @@ int qla_fab_async_scan(scsi_qla_host_t *
+ if (vha->scan.scan_flags & SF_SCANNING) {
+ spin_unlock_irqrestore(&vha->work_lock, flags);
+ ql_dbg(ql_dbg_disc + ql_dbg_verbose, vha, 0x2012,
+- "%s: scan active\n", __func__);
+- return rval;
++ "%s: scan active for sp:%p\n", __func__, sp);
++ goto done_free_sp;
+ }
+ vha->scan.scan_flags |= SF_SCANNING;
+ if (!sp)
--- /dev/null
+From stable+bounces-216271-greg=kroah.com@vger.kernel.org Fri Feb 13 17:45:10 2026
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 13 Feb 2026 11:45:02 -0500
+Subject: scsi: qla2xxx: Reduce fabric scan duplicate code
+To: stable@vger.kernel.org
+Cc: Quinn Tran <qutran@marvell.com>, Nilesh Javali <njavali@marvell.com>, Himanshu Madhani <himanshu.madhani@oracle.com>, "Martin K. Petersen" <martin.petersen@oracle.com>, Sasha Levin <sashal@kernel.org>
+Message-ID: <20260213164503.3564614-3-sashal@kernel.org>
+
+From: Quinn Tran <qutran@marvell.com>
+
+[ Upstream commit beafd692461443e0fb1d61aa56886bf85ef6f5e4 ]
+
+For fabric scan, current code uses switch scan opcode and flags as the
+method to iterate through different commands to carry out the process.
+This makes it hard to read. This patch convert those opcode and flags into
+steps. In addition, this help reduce some duplicate code.
+
+Consolidate routines that handle GPNFT & GNNFT.
+
+Cc: stable@vger.kernel.org
+Signed-off-by: Quinn Tran <qutran@marvell.com>
+Signed-off-by: Nilesh Javali <njavali@marvell.com>
+Link: https://lore.kernel.org/r/20240710171057.35066-10-njavali@marvell.com
+Reviewed-by: Himanshu Madhani <himanshu.madhani@oracle.com>
+Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
+Stable-dep-of: 7adbd2b78090 ("scsi: qla2xxx: Free sp in error path to fix system crash")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/scsi/qla2xxx/qla_def.h | 14 +
+ drivers/scsi/qla2xxx/qla_gbl.h | 6
+ drivers/scsi/qla2xxx/qla_gs.c | 432 ++++++++++++++++------------------------
+ drivers/scsi/qla2xxx/qla_init.c | 5
+ drivers/scsi/qla2xxx/qla_os.c | 12 -
+ 5 files changed, 200 insertions(+), 269 deletions(-)
+
+--- a/drivers/scsi/qla2xxx/qla_def.h
++++ b/drivers/scsi/qla2xxx/qla_def.h
+@@ -3262,11 +3262,20 @@ struct fab_scan_rp {
+ u8 node_name[8];
+ };
+
++enum scan_step {
++ FAB_SCAN_START,
++ FAB_SCAN_GPNFT_FCP,
++ FAB_SCAN_GNNFT_FCP,
++ FAB_SCAN_GPNFT_NVME,
++ FAB_SCAN_GNNFT_NVME,
++};
++
+ struct fab_scan {
+ struct fab_scan_rp *l;
+ u32 size;
+ u32 rscn_gen_start;
+ u32 rscn_gen_end;
++ enum scan_step step;
+ u16 scan_retry;
+ #define MAX_SCAN_RETRIES 5
+ enum scan_flags_t scan_flags;
+@@ -3492,9 +3501,8 @@ enum qla_work_type {
+ QLA_EVT_RELOGIN,
+ QLA_EVT_ASYNC_PRLO,
+ QLA_EVT_ASYNC_PRLO_DONE,
+- QLA_EVT_GPNFT,
+- QLA_EVT_GPNFT_DONE,
+- QLA_EVT_GNNFT_DONE,
++ QLA_EVT_SCAN_CMD,
++ QLA_EVT_SCAN_FINISH,
+ QLA_EVT_GFPNID,
+ QLA_EVT_SP_RETRY,
+ QLA_EVT_IIDMA,
+--- a/drivers/scsi/qla2xxx/qla_gbl.h
++++ b/drivers/scsi/qla2xxx/qla_gbl.h
+@@ -727,9 +727,9 @@ void qla24xx_handle_gpsc_event(scsi_qla_
+ int qla2x00_mgmt_svr_login(scsi_qla_host_t *);
+ void qla24xx_handle_gffid_event(scsi_qla_host_t *vha, struct event_arg *ea);
+ int qla24xx_async_gffid(scsi_qla_host_t *vha, fc_port_t *fcport, bool);
+-int qla24xx_async_gpnft(scsi_qla_host_t *, u8, srb_t *);
+-void qla24xx_async_gpnft_done(scsi_qla_host_t *, srb_t *);
+-void qla24xx_async_gnnft_done(scsi_qla_host_t *, srb_t *);
++int qla_fab_async_scan(scsi_qla_host_t *, srb_t *);
++void qla_fab_scan_start(struct scsi_qla_host *);
++void qla_fab_scan_finish(scsi_qla_host_t *, srb_t *);
+ int qla24xx_post_gfpnid_work(struct scsi_qla_host *, fc_port_t *);
+ int qla24xx_async_gfpnid(scsi_qla_host_t *, fc_port_t *);
+ void qla24xx_handle_gfpnid_event(scsi_qla_host_t *, struct event_arg *);
+--- a/drivers/scsi/qla2xxx/qla_gs.c
++++ b/drivers/scsi/qla2xxx/qla_gs.c
+@@ -3487,7 +3487,7 @@ static bool qla_ok_to_clear_rscn(scsi_ql
+ return true;
+ }
+
+-void qla24xx_async_gnnft_done(scsi_qla_host_t *vha, srb_t *sp)
++void qla_fab_scan_finish(scsi_qla_host_t *vha, srb_t *sp)
+ {
+ fc_port_t *fcport;
+ u32 i, rc;
+@@ -3702,14 +3702,11 @@ out:
+ }
+ }
+
+-static int qla2x00_post_gnnft_gpnft_done_work(struct scsi_qla_host *vha,
++static int qla2x00_post_next_scan_work(struct scsi_qla_host *vha,
+ srb_t *sp, int cmd)
+ {
+ struct qla_work_evt *e;
+
+- if (cmd != QLA_EVT_GPNFT_DONE && cmd != QLA_EVT_GNNFT_DONE)
+- return QLA_PARAMETER_ERROR;
+-
+ e = qla2x00_alloc_work(vha, cmd);
+ if (!e)
+ return QLA_FUNCTION_FAILED;
+@@ -3719,37 +3716,15 @@ static int qla2x00_post_gnnft_gpnft_done
+ return qla2x00_post_work(vha, e);
+ }
+
+-static int qla2x00_post_nvme_gpnft_work(struct scsi_qla_host *vha,
+- srb_t *sp, int cmd)
+-{
+- struct qla_work_evt *e;
+-
+- if (cmd != QLA_EVT_GPNFT)
+- return QLA_PARAMETER_ERROR;
+-
+- e = qla2x00_alloc_work(vha, cmd);
+- if (!e)
+- return QLA_FUNCTION_FAILED;
+-
+- e->u.gpnft.fc4_type = FC4_TYPE_NVME;
+- e->u.gpnft.sp = sp;
+-
+- return qla2x00_post_work(vha, e);
+-}
+-
+ static void qla2x00_find_free_fcp_nvme_slot(struct scsi_qla_host *vha,
+ struct srb *sp)
+ {
+ struct qla_hw_data *ha = vha->hw;
+ int num_fibre_dev = ha->max_fibre_devices;
+- struct ct_sns_req *ct_req =
+- (struct ct_sns_req *)sp->u.iocb_cmd.u.ctarg.req;
+ struct ct_sns_gpnft_rsp *ct_rsp =
+ (struct ct_sns_gpnft_rsp *)sp->u.iocb_cmd.u.ctarg.rsp;
+ struct ct_sns_gpn_ft_data *d;
+ struct fab_scan_rp *rp;
+- u16 cmd = be16_to_cpu(ct_req->command);
+- u8 fc4_type = sp->gen2;
+ int i, j, k;
+ port_id_t id;
+ u8 found;
+@@ -3768,85 +3743,83 @@ static void qla2x00_find_free_fcp_nvme_s
+ if (id.b24 == 0 || wwn == 0)
+ continue;
+
+- if (fc4_type == FC4_TYPE_FCP_SCSI) {
+- if (cmd == GPN_FT_CMD) {
+- rp = &vha->scan.l[j];
+- rp->id = id;
+- memcpy(rp->port_name, d->port_name, 8);
+- j++;
+- rp->fc4type = FS_FC4TYPE_FCP;
+- } else {
+- for (k = 0; k < num_fibre_dev; k++) {
+- rp = &vha->scan.l[k];
+- if (id.b24 == rp->id.b24) {
+- memcpy(rp->node_name,
+- d->port_name, 8);
+- break;
+- }
++ ql_dbg(ql_dbg_disc + ql_dbg_verbose, vha, 0x2025,
++ "%s %06x %8ph \n",
++ __func__, id.b24, d->port_name);
++
++ switch (vha->scan.step) {
++ case FAB_SCAN_GPNFT_FCP:
++ rp = &vha->scan.l[j];
++ rp->id = id;
++ memcpy(rp->port_name, d->port_name, 8);
++ j++;
++ rp->fc4type = FS_FC4TYPE_FCP;
++ break;
++ case FAB_SCAN_GNNFT_FCP:
++ for (k = 0; k < num_fibre_dev; k++) {
++ rp = &vha->scan.l[k];
++ if (id.b24 == rp->id.b24) {
++ memcpy(rp->node_name,
++ d->port_name, 8);
++ break;
+ }
+ }
+- } else {
+- /* Search if the fibre device supports FC4_TYPE_NVME */
+- if (cmd == GPN_FT_CMD) {
+- found = 0;
++ break;
++ case FAB_SCAN_GPNFT_NVME:
++ found = 0;
+
+- for (k = 0; k < num_fibre_dev; k++) {
+- rp = &vha->scan.l[k];
+- if (!memcmp(rp->port_name,
+- d->port_name, 8)) {
+- /*
+- * Supports FC-NVMe & FCP
+- */
+- rp->fc4type |= FS_FC4TYPE_NVME;
+- found = 1;
+- break;
+- }
++ for (k = 0; k < num_fibre_dev; k++) {
++ rp = &vha->scan.l[k];
++ if (!memcmp(rp->port_name, d->port_name, 8)) {
++ /*
++ * Supports FC-NVMe & FCP
++ */
++ rp->fc4type |= FS_FC4TYPE_NVME;
++ found = 1;
++ break;
+ }
++ }
+
+- /* We found new FC-NVMe only port */
+- if (!found) {
+- for (k = 0; k < num_fibre_dev; k++) {
+- rp = &vha->scan.l[k];
+- if (wwn_to_u64(rp->port_name)) {
+- continue;
+- } else {
+- rp->id = id;
+- memcpy(rp->port_name,
+- d->port_name, 8);
+- rp->fc4type =
+- FS_FC4TYPE_NVME;
+- break;
+- }
+- }
+- }
+- } else {
++ /* We found new FC-NVMe only port */
++ if (!found) {
+ for (k = 0; k < num_fibre_dev; k++) {
+ rp = &vha->scan.l[k];
+- if (id.b24 == rp->id.b24) {
+- memcpy(rp->node_name,
+- d->port_name, 8);
++ if (wwn_to_u64(rp->port_name)) {
++ continue;
++ } else {
++ rp->id = id;
++ memcpy(rp->port_name, d->port_name, 8);
++ rp->fc4type = FS_FC4TYPE_NVME;
+ break;
+ }
+ }
+ }
++ break;
++ case FAB_SCAN_GNNFT_NVME:
++ for (k = 0; k < num_fibre_dev; k++) {
++ rp = &vha->scan.l[k];
++ if (id.b24 == rp->id.b24) {
++ memcpy(rp->node_name, d->port_name, 8);
++ break;
++ }
++ }
++ break;
++ default:
++ break;
+ }
+ }
+ }
+
+-static void qla2x00_async_gpnft_gnnft_sp_done(srb_t *sp, int res)
++static void qla_async_scan_sp_done(srb_t *sp, int res)
+ {
+ struct scsi_qla_host *vha = sp->vha;
+- struct ct_sns_req *ct_req =
+- (struct ct_sns_req *)sp->u.iocb_cmd.u.ctarg.req;
+- u16 cmd = be16_to_cpu(ct_req->command);
+- u8 fc4_type = sp->gen2;
+ unsigned long flags;
+ int rc;
+
+ /* gen2 field is holding the fc4type */
+- ql_dbg(ql_dbg_disc, vha, 0xffff,
+- "Async done-%s res %x FC4Type %x\n",
+- sp->name, res, sp->gen2);
++ ql_dbg(ql_dbg_disc, vha, 0x2026,
++ "Async done-%s res %x step %x\n",
++ sp->name, res, vha->scan.step);
+
+ sp->rc = res;
+ if (res) {
+@@ -3870,8 +3843,7 @@ static void qla2x00_async_gpnft_gnnft_sp
+ * sp for GNNFT_DONE work. This will allow all
+ * the resource to get freed up.
+ */
+- rc = qla2x00_post_gnnft_gpnft_done_work(vha, sp,
+- QLA_EVT_GNNFT_DONE);
++ rc = qla2x00_post_next_scan_work(vha, sp, QLA_EVT_SCAN_FINISH);
+ if (rc) {
+ /* Cleanup here to prevent memory leak */
+ qla24xx_sp_unmap(vha, sp);
+@@ -3896,28 +3868,30 @@ static void qla2x00_async_gpnft_gnnft_sp
+
+ qla2x00_find_free_fcp_nvme_slot(vha, sp);
+
+- if ((fc4_type == FC4_TYPE_FCP_SCSI) && vha->flags.nvme_enabled &&
+- cmd == GNN_FT_CMD) {
+- spin_lock_irqsave(&vha->work_lock, flags);
+- vha->scan.scan_flags &= ~SF_SCANNING;
+- spin_unlock_irqrestore(&vha->work_lock, flags);
+-
+- sp->rc = res;
+- rc = qla2x00_post_nvme_gpnft_work(vha, sp, QLA_EVT_GPNFT);
+- if (rc) {
+- qla24xx_sp_unmap(vha, sp);
+- set_bit(LOCAL_LOOP_UPDATE, &vha->dpc_flags);
+- set_bit(LOOP_RESYNC_NEEDED, &vha->dpc_flags);
+- }
+- return;
+- }
++ spin_lock_irqsave(&vha->work_lock, flags);
++ vha->scan.scan_flags &= ~SF_SCANNING;
++ spin_unlock_irqrestore(&vha->work_lock, flags);
+
+- if (cmd == GPN_FT_CMD) {
+- rc = qla2x00_post_gnnft_gpnft_done_work(vha, sp,
+- QLA_EVT_GPNFT_DONE);
+- } else {
+- rc = qla2x00_post_gnnft_gpnft_done_work(vha, sp,
+- QLA_EVT_GNNFT_DONE);
++ switch (vha->scan.step) {
++ case FAB_SCAN_GPNFT_FCP:
++ case FAB_SCAN_GPNFT_NVME:
++ rc = qla2x00_post_next_scan_work(vha, sp, QLA_EVT_SCAN_CMD);
++ break;
++ case FAB_SCAN_GNNFT_FCP:
++ if (vha->flags.nvme_enabled)
++ rc = qla2x00_post_next_scan_work(vha, sp, QLA_EVT_SCAN_CMD);
++ else
++ rc = qla2x00_post_next_scan_work(vha, sp, QLA_EVT_SCAN_FINISH);
++
++ break;
++ case FAB_SCAN_GNNFT_NVME:
++ rc = qla2x00_post_next_scan_work(vha, sp, QLA_EVT_SCAN_FINISH);
++ break;
++ default:
++ /* should not be here */
++ WARN_ON(1);
++ rc = QLA_FUNCTION_FAILED;
++ break;
+ }
+
+ if (rc) {
+@@ -3928,127 +3902,16 @@ static void qla2x00_async_gpnft_gnnft_sp
+ }
+ }
+
+-/*
+- * Get WWNN list for fc4_type
+- *
+- * It is assumed the same SRB is re-used from GPNFT to avoid
+- * mem free & re-alloc
+- */
+-static int qla24xx_async_gnnft(scsi_qla_host_t *vha, struct srb *sp,
+- u8 fc4_type)
+-{
+- int rval = QLA_FUNCTION_FAILED;
+- struct ct_sns_req *ct_req;
+- struct ct_sns_pkt *ct_sns;
+- unsigned long flags;
+-
+- if (!vha->flags.online) {
+- spin_lock_irqsave(&vha->work_lock, flags);
+- vha->scan.scan_flags &= ~SF_SCANNING;
+- spin_unlock_irqrestore(&vha->work_lock, flags);
+- goto done_free_sp;
+- }
+-
+- if (!sp->u.iocb_cmd.u.ctarg.req || !sp->u.iocb_cmd.u.ctarg.rsp) {
+- ql_log(ql_log_warn, vha, 0xffff,
+- "%s: req %p rsp %p are not setup\n",
+- __func__, sp->u.iocb_cmd.u.ctarg.req,
+- sp->u.iocb_cmd.u.ctarg.rsp);
+- spin_lock_irqsave(&vha->work_lock, flags);
+- vha->scan.scan_flags &= ~SF_SCANNING;
+- spin_unlock_irqrestore(&vha->work_lock, flags);
+- WARN_ON(1);
+- set_bit(LOCAL_LOOP_UPDATE, &vha->dpc_flags);
+- set_bit(LOOP_RESYNC_NEEDED, &vha->dpc_flags);
+- goto done_free_sp;
+- }
+-
+- ql_dbg(ql_dbg_disc, vha, 0xfffff,
+- "%s: FC4Type %x, CT-PASSTHRU %s command ctarg rsp size %d, ctarg req size %d\n",
+- __func__, fc4_type, sp->name, sp->u.iocb_cmd.u.ctarg.rsp_size,
+- sp->u.iocb_cmd.u.ctarg.req_size);
+-
+- sp->type = SRB_CT_PTHRU_CMD;
+- sp->name = "gnnft";
+- sp->gen1 = vha->hw->base_qpair->chip_reset;
+- sp->gen2 = fc4_type;
+- qla2x00_init_async_sp(sp, qla2x00_get_async_timeout(vha) + 2,
+- qla2x00_async_gpnft_gnnft_sp_done);
+-
+- memset(sp->u.iocb_cmd.u.ctarg.rsp, 0, sp->u.iocb_cmd.u.ctarg.rsp_size);
+- memset(sp->u.iocb_cmd.u.ctarg.req, 0, sp->u.iocb_cmd.u.ctarg.req_size);
+-
+- ct_sns = (struct ct_sns_pkt *)sp->u.iocb_cmd.u.ctarg.req;
+- /* CT_IU preamble */
+- ct_req = qla2x00_prep_ct_req(ct_sns, GNN_FT_CMD,
+- sp->u.iocb_cmd.u.ctarg.rsp_size);
+-
+- /* GPN_FT req */
+- ct_req->req.gpn_ft.port_type = fc4_type;
+-
+- sp->u.iocb_cmd.u.ctarg.req_size = GNN_FT_REQ_SIZE;
+- sp->u.iocb_cmd.u.ctarg.nport_handle = NPH_SNS;
+-
+- ql_dbg(ql_dbg_disc, vha, 0xffff,
+- "Async-%s hdl=%x FC4Type %x.\n", sp->name,
+- sp->handle, ct_req->req.gpn_ft.port_type);
+-
+- rval = qla2x00_start_sp(sp);
+- if (rval != QLA_SUCCESS) {
+- goto done_free_sp;
+- }
+-
+- return rval;
+-
+-done_free_sp:
+- if (sp->u.iocb_cmd.u.ctarg.req) {
+- dma_free_coherent(&vha->hw->pdev->dev,
+- sp->u.iocb_cmd.u.ctarg.req_allocated_size,
+- sp->u.iocb_cmd.u.ctarg.req,
+- sp->u.iocb_cmd.u.ctarg.req_dma);
+- sp->u.iocb_cmd.u.ctarg.req = NULL;
+- }
+- if (sp->u.iocb_cmd.u.ctarg.rsp) {
+- dma_free_coherent(&vha->hw->pdev->dev,
+- sp->u.iocb_cmd.u.ctarg.rsp_allocated_size,
+- sp->u.iocb_cmd.u.ctarg.rsp,
+- sp->u.iocb_cmd.u.ctarg.rsp_dma);
+- sp->u.iocb_cmd.u.ctarg.rsp = NULL;
+- }
+- /* ref: INIT */
+- kref_put(&sp->cmd_kref, qla2x00_sp_release);
+-
+- spin_lock_irqsave(&vha->work_lock, flags);
+- vha->scan.scan_flags &= ~SF_SCANNING;
+- if (vha->scan.scan_flags == 0) {
+- ql_dbg(ql_dbg_disc, vha, 0xffff,
+- "%s: schedule\n", __func__);
+- vha->scan.scan_flags |= SF_QUEUED;
+- schedule_delayed_work(&vha->scan.scan_work, 5);
+- }
+- spin_unlock_irqrestore(&vha->work_lock, flags);
+-
+-
+- return rval;
+-} /* GNNFT */
+-
+-void qla24xx_async_gpnft_done(scsi_qla_host_t *vha, srb_t *sp)
+-{
+- ql_dbg(ql_dbg_disc + ql_dbg_verbose, vha, 0xffff,
+- "%s enter\n", __func__);
+- qla24xx_async_gnnft(vha, sp, sp->gen2);
+-}
+-
+ /* Get WWPN list for certain fc4_type */
+-int qla24xx_async_gpnft(scsi_qla_host_t *vha, u8 fc4_type, srb_t *sp)
++int qla_fab_async_scan(scsi_qla_host_t *vha, srb_t *sp)
+ {
+ int rval = QLA_FUNCTION_FAILED;
+ struct ct_sns_req *ct_req;
+ struct ct_sns_pkt *ct_sns;
+- u32 rspsz;
++ u32 rspsz = 0;
+ unsigned long flags;
+
+- ql_dbg(ql_dbg_disc + ql_dbg_verbose, vha, 0xffff,
++ ql_dbg(ql_dbg_disc + ql_dbg_verbose, vha, 0x200c,
+ "%s enter\n", __func__);
+
+ if (!vha->flags.online)
+@@ -4057,22 +3920,21 @@ int qla24xx_async_gpnft(scsi_qla_host_t
+ spin_lock_irqsave(&vha->work_lock, flags);
+ if (vha->scan.scan_flags & SF_SCANNING) {
+ spin_unlock_irqrestore(&vha->work_lock, flags);
+- ql_dbg(ql_dbg_disc + ql_dbg_verbose, vha, 0xffff,
++ ql_dbg(ql_dbg_disc + ql_dbg_verbose, vha, 0x2012,
+ "%s: scan active\n", __func__);
+ return rval;
+ }
+ vha->scan.scan_flags |= SF_SCANNING;
++ if (!sp)
++ vha->scan.step = FAB_SCAN_START;
++
+ spin_unlock_irqrestore(&vha->work_lock, flags);
+
+- if (fc4_type == FC4_TYPE_FCP_SCSI) {
+- ql_dbg(ql_dbg_disc + ql_dbg_verbose, vha, 0xffff,
++ switch (vha->scan.step) {
++ case FAB_SCAN_START:
++ ql_dbg(ql_dbg_disc + ql_dbg_verbose, vha, 0x2018,
+ "%s: Performing FCP Scan\n", __func__);
+
+- if (sp) {
+- /* ref: INIT */
+- kref_put(&sp->cmd_kref, qla2x00_sp_release);
+- }
+-
+ /* ref: INIT */
+ sp = qla2x00_get_sp(vha, NULL, GFP_KERNEL);
+ if (!sp) {
+@@ -4088,7 +3950,7 @@ int qla24xx_async_gpnft(scsi_qla_host_t
+ GFP_KERNEL);
+ sp->u.iocb_cmd.u.ctarg.req_allocated_size = sizeof(struct ct_sns_pkt);
+ if (!sp->u.iocb_cmd.u.ctarg.req) {
+- ql_log(ql_log_warn, vha, 0xffff,
++ ql_log(ql_log_warn, vha, 0x201a,
+ "Failed to allocate ct_sns request.\n");
+ spin_lock_irqsave(&vha->work_lock, flags);
+ vha->scan.scan_flags &= ~SF_SCANNING;
+@@ -4096,7 +3958,6 @@ int qla24xx_async_gpnft(scsi_qla_host_t
+ qla2x00_rel_sp(sp);
+ return rval;
+ }
+- sp->u.iocb_cmd.u.ctarg.req_size = GPN_FT_REQ_SIZE;
+
+ rspsz = sizeof(struct ct_sns_gpnft_rsp) +
+ ((vha->hw->max_fibre_devices - 1) *
+@@ -4108,7 +3969,7 @@ int qla24xx_async_gpnft(scsi_qla_host_t
+ GFP_KERNEL);
+ sp->u.iocb_cmd.u.ctarg.rsp_allocated_size = rspsz;
+ if (!sp->u.iocb_cmd.u.ctarg.rsp) {
+- ql_log(ql_log_warn, vha, 0xffff,
++ ql_log(ql_log_warn, vha, 0x201b,
+ "Failed to allocate ct_sns request.\n");
+ spin_lock_irqsave(&vha->work_lock, flags);
+ vha->scan.scan_flags &= ~SF_SCANNING;
+@@ -4128,35 +3989,95 @@ int qla24xx_async_gpnft(scsi_qla_host_t
+ "%s scan list size %d\n", __func__, vha->scan.size);
+
+ memset(vha->scan.l, 0, vha->scan.size);
+- } else if (!sp) {
+- ql_dbg(ql_dbg_disc, vha, 0xffff,
+- "NVME scan did not provide SP\n");
++
++ vha->scan.step = FAB_SCAN_GPNFT_FCP;
++ break;
++ case FAB_SCAN_GPNFT_FCP:
++ vha->scan.step = FAB_SCAN_GNNFT_FCP;
++ break;
++ case FAB_SCAN_GNNFT_FCP:
++ vha->scan.step = FAB_SCAN_GPNFT_NVME;
++ break;
++ case FAB_SCAN_GPNFT_NVME:
++ vha->scan.step = FAB_SCAN_GNNFT_NVME;
++ break;
++ case FAB_SCAN_GNNFT_NVME:
++ default:
++ /* should not be here */
++ WARN_ON(1);
++ goto done_free_sp;
++ }
++
++ if (!sp) {
++ ql_dbg(ql_dbg_disc, vha, 0x201c,
++ "scan did not provide SP\n");
+ return rval;
+ }
++ if (!sp->u.iocb_cmd.u.ctarg.req || !sp->u.iocb_cmd.u.ctarg.rsp) {
++ ql_log(ql_log_warn, vha, 0x201d,
++ "%s: req %p rsp %p are not setup\n",
++ __func__, sp->u.iocb_cmd.u.ctarg.req,
++ sp->u.iocb_cmd.u.ctarg.rsp);
++ spin_lock_irqsave(&vha->work_lock, flags);
++ vha->scan.scan_flags &= ~SF_SCANNING;
++ spin_unlock_irqrestore(&vha->work_lock, flags);
++ WARN_ON(1);
++ set_bit(LOCAL_LOOP_UPDATE, &vha->dpc_flags);
++ set_bit(LOOP_RESYNC_NEEDED, &vha->dpc_flags);
++ goto done_free_sp;
++ }
++
++ rspsz = sp->u.iocb_cmd.u.ctarg.rsp_size;
++ memset(sp->u.iocb_cmd.u.ctarg.req, 0, sp->u.iocb_cmd.u.ctarg.req_size);
++ memset(sp->u.iocb_cmd.u.ctarg.rsp, 0, sp->u.iocb_cmd.u.ctarg.rsp_size);
++
+
+ sp->type = SRB_CT_PTHRU_CMD;
+- sp->name = "gpnft";
+ sp->gen1 = vha->hw->base_qpair->chip_reset;
+- sp->gen2 = fc4_type;
+ qla2x00_init_async_sp(sp, qla2x00_get_async_timeout(vha) + 2,
+- qla2x00_async_gpnft_gnnft_sp_done);
+-
+- rspsz = sp->u.iocb_cmd.u.ctarg.rsp_size;
+- memset(sp->u.iocb_cmd.u.ctarg.rsp, 0, sp->u.iocb_cmd.u.ctarg.rsp_size);
+- memset(sp->u.iocb_cmd.u.ctarg.req, 0, sp->u.iocb_cmd.u.ctarg.req_size);
++ qla_async_scan_sp_done);
+
+ ct_sns = (struct ct_sns_pkt *)sp->u.iocb_cmd.u.ctarg.req;
+- /* CT_IU preamble */
+- ct_req = qla2x00_prep_ct_req(ct_sns, GPN_FT_CMD, rspsz);
+
+- /* GPN_FT req */
+- ct_req->req.gpn_ft.port_type = fc4_type;
++ /* CT_IU preamble */
++ switch (vha->scan.step) {
++ case FAB_SCAN_GPNFT_FCP:
++ sp->name = "gpnft";
++ ct_req = qla2x00_prep_ct_req(ct_sns, GPN_FT_CMD, rspsz);
++ ct_req->req.gpn_ft.port_type = FC4_TYPE_FCP_SCSI;
++ sp->u.iocb_cmd.u.ctarg.req_size = GPN_FT_REQ_SIZE;
++ break;
++ case FAB_SCAN_GNNFT_FCP:
++ sp->name = "gnnft";
++ ct_req = qla2x00_prep_ct_req(ct_sns, GNN_FT_CMD, rspsz);
++ ct_req->req.gpn_ft.port_type = FC4_TYPE_FCP_SCSI;
++ sp->u.iocb_cmd.u.ctarg.req_size = GNN_FT_REQ_SIZE;
++ break;
++ case FAB_SCAN_GPNFT_NVME:
++ sp->name = "gpnft";
++ ct_req = qla2x00_prep_ct_req(ct_sns, GPN_FT_CMD, rspsz);
++ ct_req->req.gpn_ft.port_type = FC4_TYPE_NVME;
++ sp->u.iocb_cmd.u.ctarg.req_size = GPN_FT_REQ_SIZE;
++ break;
++ case FAB_SCAN_GNNFT_NVME:
++ sp->name = "gnnft";
++ ct_req = qla2x00_prep_ct_req(ct_sns, GNN_FT_CMD, rspsz);
++ ct_req->req.gpn_ft.port_type = FC4_TYPE_NVME;
++ sp->u.iocb_cmd.u.ctarg.req_size = GNN_FT_REQ_SIZE;
++ break;
++ default:
++ /* should not be here */
++ WARN_ON(1);
++ goto done_free_sp;
++ }
+
+ sp->u.iocb_cmd.u.ctarg.nport_handle = NPH_SNS;
+
+- ql_dbg(ql_dbg_disc, vha, 0xffff,
+- "Async-%s hdl=%x FC4Type %x.\n", sp->name,
+- sp->handle, ct_req->req.gpn_ft.port_type);
++ ql_dbg(ql_dbg_disc, vha, 0x2003,
++ "%s: step %d, rsp size %d, req size %d hdl %x %s FC4TYPE %x \n",
++ __func__, vha->scan.step, sp->u.iocb_cmd.u.ctarg.rsp_size,
++ sp->u.iocb_cmd.u.ctarg.req_size, sp->handle, sp->name,
++ ct_req->req.gpn_ft.port_type);
+
+ rval = qla2x00_start_sp(sp);
+ if (rval != QLA_SUCCESS) {
+@@ -4189,7 +4110,7 @@ done_free_sp:
+ spin_lock_irqsave(&vha->work_lock, flags);
+ vha->scan.scan_flags &= ~SF_SCANNING;
+ if (vha->scan.scan_flags == 0) {
+- ql_dbg(ql_dbg_disc + ql_dbg_verbose, vha, 0xffff,
++ ql_dbg(ql_dbg_disc + ql_dbg_verbose, vha, 0x2007,
+ "%s: Scan scheduled.\n", __func__);
+ vha->scan.scan_flags |= SF_QUEUED;
+ schedule_delayed_work(&vha->scan.scan_work, 5);
+@@ -4200,6 +4121,15 @@ done_free_sp:
+ return rval;
+ }
+
++void qla_fab_scan_start(struct scsi_qla_host *vha)
++{
++ int rval;
++
++ rval = qla_fab_async_scan(vha, NULL);
++ if (rval)
++ set_bit(LOOP_RESYNC_NEEDED, &vha->dpc_flags);
++}
++
+ void qla_scan_work_fn(struct work_struct *work)
+ {
+ struct fab_scan *s = container_of(to_delayed_work(work),
+--- a/drivers/scsi/qla2xxx/qla_init.c
++++ b/drivers/scsi/qla2xxx/qla_init.c
+@@ -6457,10 +6457,7 @@ qla2x00_configure_fabric(scsi_qla_host_t
+ if (USE_ASYNC_SCAN(ha)) {
+ /* start of scan begins here */
+ vha->scan.rscn_gen_end = atomic_read(&vha->rscn_gen);
+- rval = qla24xx_async_gpnft(vha, FC4_TYPE_FCP_SCSI,
+- NULL);
+- if (rval)
+- set_bit(LOOP_RESYNC_NEEDED, &vha->dpc_flags);
++ qla_fab_scan_start(vha);
+ } else {
+ list_for_each_entry(fcport, &vha->vp_fcports, list)
+ fcport->scan_state = QLA_FCPORT_SCAN;
+--- a/drivers/scsi/qla2xxx/qla_os.c
++++ b/drivers/scsi/qla2xxx/qla_os.c
+@@ -5490,15 +5490,11 @@ qla2x00_do_work(struct scsi_qla_host *vh
+ qla2x00_async_prlo_done(vha, e->u.logio.fcport,
+ e->u.logio.data);
+ break;
+- case QLA_EVT_GPNFT:
+- qla24xx_async_gpnft(vha, e->u.gpnft.fc4_type,
+- e->u.gpnft.sp);
++ case QLA_EVT_SCAN_CMD:
++ qla_fab_async_scan(vha, e->u.iosb.sp);
+ break;
+- case QLA_EVT_GPNFT_DONE:
+- qla24xx_async_gpnft_done(vha, e->u.iosb.sp);
+- break;
+- case QLA_EVT_GNNFT_DONE:
+- qla24xx_async_gnnft_done(vha, e->u.iosb.sp);
++ case QLA_EVT_SCAN_FINISH:
++ qla_fab_scan_finish(vha, e->u.iosb.sp);
+ break;
+ case QLA_EVT_GFPNID:
+ qla24xx_async_gfpnid(vha, e->u.fcport.fcport);
--- /dev/null
+From stable+bounces-216270-greg=kroah.com@vger.kernel.org Fri Feb 13 17:46:56 2026
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 13 Feb 2026 11:45:01 -0500
+Subject: scsi: qla2xxx: Remove dead code (GNN ID)
+To: stable@vger.kernel.org
+Cc: Quinn Tran <qutran@marvell.com>, Nilesh Javali <njavali@marvell.com>, Himanshu Madhani <himanshu.madhani@oracle.com>, "Martin K. Petersen" <martin.petersen@oracle.com>, Sasha Levin <sashal@kernel.org>
+Message-ID: <20260213164503.3564614-2-sashal@kernel.org>
+
+From: Quinn Tran <qutran@marvell.com>
+
+[ Upstream commit 87f6dafd50fb6d7214c32596a11b983138b09123 ]
+
+Remove stale/unused code (GNN ID).
+
+Signed-off-by: Quinn Tran <qutran@marvell.com>
+Signed-off-by: Nilesh Javali <njavali@marvell.com>
+Reviewed-by: Himanshu Madhani <himanshu.madhani@oracle.com>
+Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
+Stable-dep-of: 7adbd2b78090 ("scsi: qla2xxx: Free sp in error path to fix system crash")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/scsi/qla2xxx/qla_def.h | 3 -
+ drivers/scsi/qla2xxx/qla_gbl.h | 3 -
+ drivers/scsi/qla2xxx/qla_gs.c | 110 ----------------------------------------
+ drivers/scsi/qla2xxx/qla_init.c | 7 --
+ drivers/scsi/qla2xxx/qla_os.c | 3 -
+ 5 files changed, 1 insertion(+), 125 deletions(-)
+
+--- a/drivers/scsi/qla2xxx/qla_def.h
++++ b/drivers/scsi/qla2xxx/qla_def.h
+@@ -2488,7 +2488,6 @@ struct ct_sns_desc {
+
+ enum discovery_state {
+ DSC_DELETED,
+- DSC_GNN_ID,
+ DSC_GNL,
+ DSC_LOGIN_PEND,
+ DSC_LOGIN_FAILED,
+@@ -2701,7 +2700,6 @@ extern const char *const port_state_str[
+
+ static const char *const port_dstate_str[] = {
+ [DSC_DELETED] = "DELETED",
+- [DSC_GNN_ID] = "GNN_ID",
+ [DSC_GNL] = "GNL",
+ [DSC_LOGIN_PEND] = "LOGIN_PEND",
+ [DSC_LOGIN_FAILED] = "LOGIN_FAILED",
+@@ -3497,7 +3495,6 @@ enum qla_work_type {
+ QLA_EVT_GPNFT,
+ QLA_EVT_GPNFT_DONE,
+ QLA_EVT_GNNFT_DONE,
+- QLA_EVT_GNNID,
+ QLA_EVT_GFPNID,
+ QLA_EVT_SP_RETRY,
+ QLA_EVT_IIDMA,
+--- a/drivers/scsi/qla2xxx/qla_gbl.h
++++ b/drivers/scsi/qla2xxx/qla_gbl.h
+@@ -730,9 +730,6 @@ int qla24xx_async_gffid(scsi_qla_host_t
+ int qla24xx_async_gpnft(scsi_qla_host_t *, u8, srb_t *);
+ void qla24xx_async_gpnft_done(scsi_qla_host_t *, srb_t *);
+ void qla24xx_async_gnnft_done(scsi_qla_host_t *, srb_t *);
+-int qla24xx_async_gnnid(scsi_qla_host_t *, fc_port_t *);
+-void qla24xx_handle_gnnid_event(scsi_qla_host_t *, struct event_arg *);
+-int qla24xx_post_gnnid_work(struct scsi_qla_host *, fc_port_t *);
+ int qla24xx_post_gfpnid_work(struct scsi_qla_host *, fc_port_t *);
+ int qla24xx_async_gfpnid(scsi_qla_host_t *, fc_port_t *);
+ void qla24xx_handle_gfpnid_event(scsi_qla_host_t *, struct event_arg *);
+--- a/drivers/scsi/qla2xxx/qla_gs.c
++++ b/drivers/scsi/qla2xxx/qla_gs.c
+@@ -4218,116 +4218,6 @@ void qla_scan_work_fn(struct work_struct
+ spin_unlock_irqrestore(&vha->work_lock, flags);
+ }
+
+-/* GNN_ID */
+-void qla24xx_handle_gnnid_event(scsi_qla_host_t *vha, struct event_arg *ea)
+-{
+- qla24xx_post_gnl_work(vha, ea->fcport);
+-}
+-
+-static void qla2x00_async_gnnid_sp_done(srb_t *sp, int res)
+-{
+- struct scsi_qla_host *vha = sp->vha;
+- fc_port_t *fcport = sp->fcport;
+- u8 *node_name = fcport->ct_desc.ct_sns->p.rsp.rsp.gnn_id.node_name;
+- struct event_arg ea;
+- u64 wwnn;
+-
+- fcport->flags &= ~FCF_ASYNC_SENT;
+- wwnn = wwn_to_u64(node_name);
+- if (wwnn)
+- memcpy(fcport->node_name, node_name, WWN_SIZE);
+-
+- memset(&ea, 0, sizeof(ea));
+- ea.fcport = fcport;
+- ea.sp = sp;
+- ea.rc = res;
+-
+- ql_dbg(ql_dbg_disc, vha, 0x204f,
+- "Async done-%s res %x, WWPN %8phC %8phC\n",
+- sp->name, res, fcport->port_name, fcport->node_name);
+-
+- qla24xx_handle_gnnid_event(vha, &ea);
+-
+- /* ref: INIT */
+- kref_put(&sp->cmd_kref, qla2x00_sp_release);
+-}
+-
+-int qla24xx_async_gnnid(scsi_qla_host_t *vha, fc_port_t *fcport)
+-{
+- int rval = QLA_FUNCTION_FAILED;
+- struct ct_sns_req *ct_req;
+- srb_t *sp;
+-
+- if (!vha->flags.online || (fcport->flags & FCF_ASYNC_SENT))
+- return rval;
+-
+- qla2x00_set_fcport_disc_state(fcport, DSC_GNN_ID);
+- /* ref: INIT */
+- sp = qla2x00_get_sp(vha, fcport, GFP_ATOMIC);
+- if (!sp)
+- goto done;
+-
+- fcport->flags |= FCF_ASYNC_SENT;
+- sp->type = SRB_CT_PTHRU_CMD;
+- sp->name = "gnnid";
+- sp->gen1 = fcport->rscn_gen;
+- sp->gen2 = fcport->login_gen;
+- qla2x00_init_async_sp(sp, qla2x00_get_async_timeout(vha) + 2,
+- qla2x00_async_gnnid_sp_done);
+-
+- /* CT_IU preamble */
+- ct_req = qla2x00_prep_ct_req(fcport->ct_desc.ct_sns, GNN_ID_CMD,
+- GNN_ID_RSP_SIZE);
+-
+- /* GNN_ID req */
+- ct_req->req.port_id.port_id = port_id_to_be_id(fcport->d_id);
+-
+-
+- /* req & rsp use the same buffer */
+- sp->u.iocb_cmd.u.ctarg.req = fcport->ct_desc.ct_sns;
+- sp->u.iocb_cmd.u.ctarg.req_dma = fcport->ct_desc.ct_sns_dma;
+- sp->u.iocb_cmd.u.ctarg.rsp = fcport->ct_desc.ct_sns;
+- sp->u.iocb_cmd.u.ctarg.rsp_dma = fcport->ct_desc.ct_sns_dma;
+- sp->u.iocb_cmd.u.ctarg.req_size = GNN_ID_REQ_SIZE;
+- sp->u.iocb_cmd.u.ctarg.rsp_size = GNN_ID_RSP_SIZE;
+- sp->u.iocb_cmd.u.ctarg.nport_handle = NPH_SNS;
+-
+- ql_dbg(ql_dbg_disc, vha, 0xffff,
+- "Async-%s - %8phC hdl=%x loopid=%x portid %06x.\n",
+- sp->name, fcport->port_name,
+- sp->handle, fcport->loop_id, fcport->d_id.b24);
+-
+- rval = qla2x00_start_sp(sp);
+- if (rval != QLA_SUCCESS)
+- goto done_free_sp;
+- return rval;
+-
+-done_free_sp:
+- /* ref: INIT */
+- kref_put(&sp->cmd_kref, qla2x00_sp_release);
+- fcport->flags &= ~FCF_ASYNC_SENT;
+-done:
+- return rval;
+-}
+-
+-int qla24xx_post_gnnid_work(struct scsi_qla_host *vha, fc_port_t *fcport)
+-{
+- struct qla_work_evt *e;
+- int ls;
+-
+- ls = atomic_read(&vha->loop_state);
+- if (((ls != LOOP_READY) && (ls != LOOP_UP)) ||
+- test_bit(UNLOADING, &vha->dpc_flags))
+- return 0;
+-
+- e = qla2x00_alloc_work(vha, QLA_EVT_GNNID);
+- if (!e)
+- return QLA_FUNCTION_FAILED;
+-
+- e->u.fcport.fcport = fcport;
+- return qla2x00_post_work(vha, e);
+-}
+-
+ /* GPFN_ID */
+ void qla24xx_handle_gfpnid_event(scsi_qla_host_t *vha, struct event_arg *ea)
+ {
+--- a/drivers/scsi/qla2xxx/qla_init.c
++++ b/drivers/scsi/qla2xxx/qla_init.c
+@@ -1725,12 +1725,7 @@ int qla24xx_fcport_handle_login(struct s
+ }
+ break;
+ default:
+- if (wwn == 0) {
+- ql_dbg(ql_dbg_disc, vha, 0xffff,
+- "%s %d %8phC post GNNID\n",
+- __func__, __LINE__, fcport->port_name);
+- qla24xx_post_gnnid_work(vha, fcport);
+- } else if (fcport->loop_id == FC_NO_LOOP_ID) {
++ if (fcport->loop_id == FC_NO_LOOP_ID) {
+ ql_dbg(ql_dbg_disc, vha, 0x20bd,
+ "%s %d %8phC post gnl\n",
+ __func__, __LINE__, fcport->port_name);
+--- a/drivers/scsi/qla2xxx/qla_os.c
++++ b/drivers/scsi/qla2xxx/qla_os.c
+@@ -5500,9 +5500,6 @@ qla2x00_do_work(struct scsi_qla_host *vh
+ case QLA_EVT_GNNFT_DONE:
+ qla24xx_async_gnnft_done(vha, e->u.iosb.sp);
+ break;
+- case QLA_EVT_GNNID:
+- qla24xx_async_gnnid(vha, e->u.fcport.fcport);
+- break;
+ case QLA_EVT_GFPNID:
+ qla24xx_async_gfpnid(vha, e->u.fcport.fcport);
+ break;
--- /dev/null
+From stable+bounces-216269-greg=kroah.com@vger.kernel.org Fri Feb 13 17:45:10 2026
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 13 Feb 2026 11:45:00 -0500
+Subject: scsi: qla2xxx: Use named initializers for port_[d]state_str
+To: stable@vger.kernel.org
+Cc: Gleb Chesnokov <Chesnokov.G@raidix.com>, Himanshu Madhani <himanshu.madhani@oracle.com>, "Martin K. Petersen" <martin.petersen@oracle.com>, Sasha Levin <sashal@kernel.org>
+Message-ID: <20260213164503.3564614-1-sashal@kernel.org>
+
+From: Gleb Chesnokov <Chesnokov.G@raidix.com>
+
+[ Upstream commit 6e0e85d39e528da2915a2da261195f81bfde6915 ]
+
+Make port_state_str and port_dstate_str a little more readable and
+maintainable by using named initializers.
+
+Also convert FCS_* macros into an enum.
+
+Link: https://lore.kernel.org/r/AS8PR10MB495215841EB25C16DBC0CB409D349@AS8PR10MB4952.EURPRD10.PROD.OUTLOOK.COM
+Reviewed-by: Himanshu Madhani <himanshu.madhani@oracle.com>
+Signed-off-by: Gleb Chesnokov <Chesnokov.G@raidix.com>
+Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
+Stable-dep-of: 7adbd2b78090 ("scsi: qla2xxx: Free sp in error path to fix system crash")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/scsi/qla2xxx/qla_def.h | 35 +++++++++++++++++++----------------
+ drivers/scsi/qla2xxx/qla_isr.c | 10 +++++-----
+ 2 files changed, 24 insertions(+), 21 deletions(-)
+
+--- a/drivers/scsi/qla2xxx/qla_def.h
++++ b/drivers/scsi/qla2xxx/qla_def.h
+@@ -2689,25 +2689,28 @@ struct event_arg {
+ /*
+ * Fibre channel port/lun states.
+ */
+-#define FCS_UNCONFIGURED 1
+-#define FCS_DEVICE_DEAD 2
+-#define FCS_DEVICE_LOST 3
+-#define FCS_ONLINE 4
++enum {
++ FCS_UNKNOWN,
++ FCS_UNCONFIGURED,
++ FCS_DEVICE_DEAD,
++ FCS_DEVICE_LOST,
++ FCS_ONLINE,
++};
+
+ extern const char *const port_state_str[5];
+
+-static const char * const port_dstate_str[] = {
+- "DELETED",
+- "GNN_ID",
+- "GNL",
+- "LOGIN_PEND",
+- "LOGIN_FAILED",
+- "GPDB",
+- "UPD_FCPORT",
+- "LOGIN_COMPLETE",
+- "ADISC",
+- "DELETE_PEND",
+- "LOGIN_AUTH_PEND",
++static const char *const port_dstate_str[] = {
++ [DSC_DELETED] = "DELETED",
++ [DSC_GNN_ID] = "GNN_ID",
++ [DSC_GNL] = "GNL",
++ [DSC_LOGIN_PEND] = "LOGIN_PEND",
++ [DSC_LOGIN_FAILED] = "LOGIN_FAILED",
++ [DSC_GPDB] = "GPDB",
++ [DSC_UPD_FCPORT] = "UPD_FCPORT",
++ [DSC_LOGIN_COMPLETE] = "LOGIN_COMPLETE",
++ [DSC_ADISC] = "ADISC",
++ [DSC_DELETE_PEND] = "DELETE_PEND",
++ [DSC_LOGIN_AUTH_PEND] = "LOGIN_AUTH_PEND",
+ };
+
+ /*
+--- a/drivers/scsi/qla2xxx/qla_isr.c
++++ b/drivers/scsi/qla2xxx/qla_isr.c
+@@ -49,11 +49,11 @@ qla27xx_process_purex_fpin(struct scsi_q
+ }
+
+ const char *const port_state_str[] = {
+- "Unknown",
+- "UNCONFIGURED",
+- "DEAD",
+- "LOST",
+- "ONLINE"
++ [FCS_UNKNOWN] = "Unknown",
++ [FCS_UNCONFIGURED] = "UNCONFIGURED",
++ [FCS_DEVICE_DEAD] = "DEAD",
++ [FCS_DEVICE_LOST] = "LOST",
++ [FCS_ONLINE] = "ONLINE"
+ };
+
+ static void
--- /dev/null
+From matttbe@kernel.org Thu Feb 12 12:04:04 2026
+From: "Matthieu Baerts (NGI0)" <matttbe@kernel.org>
+Date: Thu, 12 Feb 2026 12:03:45 +0100
+Subject: selftests: mptcp: pm: ensure unknown flags are ignored
+To: stable@vger.kernel.org, gregkh@linuxfoundation.org
+Cc: MPTCP Upstream <mptcp@lists.linux.dev>, "Matthieu Baerts (NGI0)" <matttbe@kernel.org>, Mat Martineau <martineau@kernel.org>, Jakub Kicinski <kuba@kernel.org>
+Message-ID: <20260212110344.781836-2-matttbe@kernel.org>
+
+From: "Matthieu Baerts (NGI0)" <matttbe@kernel.org>
+
+commit 29f4801e9c8dfd12bdcb33b61a6ac479c7162bd7 upstream.
+
+This validates the previous commit: the userspace can set unknown flags
+-- the 7th bit is currently unused -- without errors, but only the
+supported ones are printed in the endpoints dumps.
+
+The 'Fixes' tag here below is the same as the one from the previous
+commit: this patch here is not fixing anything wrong in the selftests,
+but it validates the previous fix for an issue introduced by this commit
+ID.
+
+Fixes: 01cacb00b35c ("mptcp: add netlink-based PM")
+Cc: stable@vger.kernel.org
+Reviewed-by: Mat Martineau <martineau@kernel.org>
+Signed-off-by: Matthieu Baerts (NGI0) <matttbe@kernel.org>
+Link: https://patch.msgid.link/20251205-net-mptcp-misc-fixes-6-19-rc1-v1-2-9e4781a6c1b8@kernel.org
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+[ Conflicts in pm_netlink.sh, because some refactoring have been done
+ later on: commit 0d16ed0c2e74 ("selftests: mptcp: add
+ {get,format}_endpoint(s) helpers") and commit c99d57d0007a
+ ("selftests: mptcp: use pm_nl endpoint ops") are not in this version.
+ The same operation can still be done at the same place, without using
+ the new helpers.
+ Also, commit 1dc88d241f92 ("selftests: mptcp: pm_nl_ctl: always look
+ for errors") is not in this version, and create a conflict in the
+ context which is not related to the modification here.
+ Conflicts in pm_nl_ctl.c, because commit 69c6ce7b6eca ("selftests:
+ mptcp: add implicit endpoint test case") is not in this version, and
+ caused a conflict in the context which is not related to the
+ modification here. ]
+Signed-off-by: Matthieu Baerts (NGI0) <matttbe@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ tools/testing/selftests/net/mptcp/pm_netlink.sh | 4 ++++
+ tools/testing/selftests/net/mptcp/pm_nl_ctl.c | 11 +++++++++++
+ 2 files changed, 15 insertions(+)
+
+--- a/tools/testing/selftests/net/mptcp/pm_netlink.sh
++++ b/tools/testing/selftests/net/mptcp/pm_netlink.sh
+@@ -124,6 +124,10 @@ id 8 flags signal 10.0.1.8" "id limit"
+ ip netns exec $ns1 ./pm_nl_ctl flush
+ check "ip netns exec $ns1 ./pm_nl_ctl dump" "" "flush addrs"
+
++ip netns exec $ns1 ./pm_nl_ctl add 10.0.1.1 flags unknown
++check "ip netns exec $ns1 ./pm_nl_ctl dump" "id 1 flags 10.0.1.1" "ignore unknown flags"
++ip netns exec $ns1 ./pm_nl_ctl flush
++
+ ip netns exec $ns1 ./pm_nl_ctl limits 9 1
+ check "ip netns exec $ns1 ./pm_nl_ctl limits" "$default_limits" "rcv addrs above hard limit"
+
+--- a/tools/testing/selftests/net/mptcp/pm_nl_ctl.c
++++ b/tools/testing/selftests/net/mptcp/pm_nl_ctl.c
+@@ -22,6 +22,8 @@
+ #define MPTCP_PM_NAME "mptcp_pm"
+ #endif
+
++#define MPTCP_PM_ADDR_FLAG_UNKNOWN _BITUL(7)
++
+ static void syntax(char *argv[])
+ {
+ fprintf(stderr, "%s add|get|set|del|flush|dump|accept [<args>]\n", argv[0]);
+@@ -238,6 +240,8 @@ int add_addr(int fd, int pm_family, int
+ flags |= MPTCP_PM_ADDR_FLAG_BACKUP;
+ else if (!strcmp(tok, "fullmesh"))
+ flags |= MPTCP_PM_ADDR_FLAG_FULLMESH;
++ else if (!strcmp(tok, "unknown"))
++ flags |= MPTCP_PM_ADDR_FLAG_UNKNOWN;
+ else
+ error(1, errno,
+ "unknown flag %s", argv[arg]);
+@@ -435,6 +439,13 @@ static void print_addr(struct rtattr *at
+ if (flags)
+ printf(",");
+ }
++
++ if (flags & MPTCP_PM_ADDR_FLAG_UNKNOWN) {
++ printf("unknown");
++ flags &= ~MPTCP_PM_ADDR_FLAG_UNKNOWN;
++ if (flags)
++ printf(",");
++ }
+
+ /* bump unknown flags, if any */
+ if (flags)
asoc-fsl_xcvr-fix-missing-lock-in-fsl_xcvr_mode_put.patch
gpiolib-acpi-fix-gpio-count-with-string-references.patch
revert-wireguard-device-enable-threaded-napi.patch
+btrfs-fix-racy-bitfield-write-in-btrfs_clear_space_info_full.patch
+smb-client-set-correct-id-uid-and-cruid-for-multiuser-automounts.patch
+net-dsa-free-routing-table-on-probe-failure.patch
+selftests-mptcp-pm-ensure-unknown-flags-are-ignored.patch
+mptcp-fix-race-in-mptcp_pm_nl_flush_addrs_doit.patch
+crypto-virtio-remove-duplicated-virtqueue_kick-in-virtio_crypto_skcipher_crypt_req.patch
+smb-server-fix-leak-of-active_num_conn-in-ksmbd_tcp_new_connection.patch
+bus-fsl-mc-replace-snprintf-and-sprintf-with-sysfs_emit-in-sysfs-show-functions.patch
+bus-fsl-mc-fix-use-after-free-in-driver_override_show.patch
+scsi-qla2xxx-fix-bsg_done-causing-double-free.patch
+scsi-qla2xxx-use-named-initializers-for-port_state_str.patch
+scsi-qla2xxx-remove-dead-code-gnn-id.patch
+scsi-qla2xxx-reduce-fabric-scan-duplicate-code.patch
+scsi-qla2xxx-free-sp-in-error-path-to-fix-system-crash.patch
+pci-endpoint-automatically-create-a-function-specific-attributes-group.patch
+pci-endpoint-remove-unused-field-in-struct-pci_epf_group.patch
+pci-endpoint-avoid-creating-sub-groups-asynchronously.patch
--- /dev/null
+From stable+bounces-215924-greg=kroah.com@vger.kernel.org Thu Feb 12 09:51:18 2026
+From: Rahul Sharma <black.hawk@163.com>
+Date: Thu, 12 Feb 2026 16:50:30 +0800
+Subject: smb: client: set correct id, uid and cruid for multiuser automounts
+To: gregkh@linuxfoundation.org, stable@vger.kernel.org
+Cc: linux-kernel@vger.kernel.org, Paulo Alcantara <pc@manguebit.com>, Shane Nehring <snehring@iastate.edu>, Steve French <stfrench@microsoft.com>, Rahul Sharma <black.hawk@163.com>
+Message-ID: <20260212085030.372707-1-black.hawk@163.com>
+
+From: Paulo Alcantara <pc@manguebit.com>
+
+[ Upstream commit 4508ec17357094e2075f334948393ddedbb75157 ]
+
+When uid, gid and cruid are not specified, we need to dynamically
+set them into the filesystem context used for automounting otherwise
+they'll end up reusing the values from the parent mount.
+
+Fixes: 9fd29a5bae6e ("cifs: use fs_context for automounts")
+Reported-by: Shane Nehring <snehring@iastate.edu>
+Closes: https://bugzilla.redhat.com/show_bug.cgi?id=2259257
+Cc: stable@vger.kernel.org # 6.2+
+Signed-off-by: Paulo Alcantara (Red Hat) <pc@manguebit.com>
+Signed-off-by: Steve French <stfrench@microsoft.com>
+[ The context change is due to the commit 561f82a3a24c
+("smb: client: rename cifs_dfs_ref.c to namespace.c") and the commit
+0a049935e47e ("smb: client: get rid of dfs naming in automount code")
+in v6.6 which are irrelevant to the logic of this patch. ]
+Signed-off-by: Rahul Sharma <black.hawk@163.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ fs/cifs/cifs_dfs_ref.c | 16 ++++++++++++++++
+ 1 file changed, 16 insertions(+)
+
+--- a/fs/cifs/cifs_dfs_ref.c
++++ b/fs/cifs/cifs_dfs_ref.c
+@@ -258,6 +258,21 @@ compose_mount_options_err:
+ goto compose_mount_options_out;
+ }
+
++static void fs_context_set_ids(struct smb3_fs_context *ctx)
++{
++ kuid_t uid = current_fsuid();
++ kgid_t gid = current_fsgid();
++
++ if (ctx->multiuser) {
++ if (!ctx->uid_specified)
++ ctx->linux_uid = uid;
++ if (!ctx->gid_specified)
++ ctx->linux_gid = gid;
++ }
++ if (!ctx->cruid_specified)
++ ctx->cred_uid = uid;
++}
++
+ /*
+ * Create a vfsmount that we can automount
+ */
+@@ -309,6 +324,7 @@ static struct vfsmount *cifs_dfs_do_auto
+ tmp.source = full_path;
+ tmp.UNC = tmp.prepath = NULL;
+
++ fs_context_set_ids(&tmp);
+ rc = smb3_fs_context_dup(ctx, &tmp);
+ if (rc) {
+ mnt = ERR_PTR(rc);
--- /dev/null
+From stable+bounces-216246-greg=kroah.com@vger.kernel.org Fri Feb 13 16:09:01 2026
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 13 Feb 2026 10:08:55 -0500
+Subject: smb: server: fix leak of active_num_conn in ksmbd_tcp_new_connection()
+To: stable@vger.kernel.org
+Cc: Henrique Carvalho <henrique.carvalho@suse.com>, Namjae Jeon <linkinjeon@kernel.org>, Steve French <stfrench@microsoft.com>, Sasha Levin <sashal@kernel.org>
+Message-ID: <20260213150855.3532387-1-sashal@kernel.org>
+
+From: Henrique Carvalho <henrique.carvalho@suse.com>
+
+[ Upstream commit 77ffbcac4e569566d0092d5f22627dfc0896b553 ]
+
+On kthread_run() failure in ksmbd_tcp_new_connection(), the transport is
+freed via free_transport(), which does not decrement active_num_conn,
+leaking this counter.
+
+Replace free_transport() with ksmbd_tcp_disconnect().
+
+Fixes: 0d0d4680db22e ("ksmbd: add max connections parameter")
+Cc: stable@vger.kernel.org
+Signed-off-by: Henrique Carvalho <henrique.carvalho@suse.com>
+Acked-by: Namjae Jeon <linkinjeon@kernel.org>
+Signed-off-by: Steve French <stfrench@microsoft.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ fs/ksmbd/transport_tcp.c | 3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+--- a/fs/ksmbd/transport_tcp.c
++++ b/fs/ksmbd/transport_tcp.c
+@@ -41,6 +41,7 @@ static struct ksmbd_transport_ops ksmbd_
+
+ static void tcp_stop_kthread(struct task_struct *kthread);
+ static struct interface *alloc_iface(char *ifname);
++static void ksmbd_tcp_disconnect(struct ksmbd_transport *t);
+
+ #define KSMBD_TRANS(t) (&(t)->transport)
+ #define TCP_TRANS(t) ((struct tcp_transport *)container_of(t, \
+@@ -207,7 +208,7 @@ static int ksmbd_tcp_new_connection(stru
+ if (IS_ERR(handler)) {
+ pr_err("cannot start conn thread\n");
+ rc = PTR_ERR(handler);
+- free_transport(t);
++ ksmbd_tcp_disconnect(KSMBD_TRANS(t));
+ }
+ return rc;
+