]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
5.15-stable patches
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Tue, 17 Feb 2026 12:45:29 +0000 (13:45 +0100)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Tue, 17 Feb 2026 12:45:29 +0000 (13:45 +0100)
added patches:
btrfs-fix-racy-bitfield-write-in-btrfs_clear_space_info_full.patch
bus-fsl-mc-fix-use-after-free-in-driver_override_show.patch
bus-fsl-mc-replace-snprintf-and-sprintf-with-sysfs_emit-in-sysfs-show-functions.patch
crypto-virtio-remove-duplicated-virtqueue_kick-in-virtio_crypto_skcipher_crypt_req.patch
mptcp-fix-race-in-mptcp_pm_nl_flush_addrs_doit.patch
net-dsa-free-routing-table-on-probe-failure.patch
pci-endpoint-automatically-create-a-function-specific-attributes-group.patch
pci-endpoint-avoid-creating-sub-groups-asynchronously.patch
pci-endpoint-remove-unused-field-in-struct-pci_epf_group.patch
scsi-qla2xxx-fix-bsg_done-causing-double-free.patch
scsi-qla2xxx-free-sp-in-error-path-to-fix-system-crash.patch
scsi-qla2xxx-reduce-fabric-scan-duplicate-code.patch
scsi-qla2xxx-remove-dead-code-gnn-id.patch
scsi-qla2xxx-use-named-initializers-for-port_state_str.patch
selftests-mptcp-pm-ensure-unknown-flags-are-ignored.patch
smb-client-set-correct-id-uid-and-cruid-for-multiuser-automounts.patch
smb-server-fix-leak-of-active_num_conn-in-ksmbd_tcp_new_connection.patch

18 files changed:
queue-5.15/btrfs-fix-racy-bitfield-write-in-btrfs_clear_space_info_full.patch [new file with mode: 0644]
queue-5.15/bus-fsl-mc-fix-use-after-free-in-driver_override_show.patch [new file with mode: 0644]
queue-5.15/bus-fsl-mc-replace-snprintf-and-sprintf-with-sysfs_emit-in-sysfs-show-functions.patch [new file with mode: 0644]
queue-5.15/crypto-virtio-remove-duplicated-virtqueue_kick-in-virtio_crypto_skcipher_crypt_req.patch [new file with mode: 0644]
queue-5.15/mptcp-fix-race-in-mptcp_pm_nl_flush_addrs_doit.patch [new file with mode: 0644]
queue-5.15/net-dsa-free-routing-table-on-probe-failure.patch [new file with mode: 0644]
queue-5.15/pci-endpoint-automatically-create-a-function-specific-attributes-group.patch [new file with mode: 0644]
queue-5.15/pci-endpoint-avoid-creating-sub-groups-asynchronously.patch [new file with mode: 0644]
queue-5.15/pci-endpoint-remove-unused-field-in-struct-pci_epf_group.patch [new file with mode: 0644]
queue-5.15/scsi-qla2xxx-fix-bsg_done-causing-double-free.patch [new file with mode: 0644]
queue-5.15/scsi-qla2xxx-free-sp-in-error-path-to-fix-system-crash.patch [new file with mode: 0644]
queue-5.15/scsi-qla2xxx-reduce-fabric-scan-duplicate-code.patch [new file with mode: 0644]
queue-5.15/scsi-qla2xxx-remove-dead-code-gnn-id.patch [new file with mode: 0644]
queue-5.15/scsi-qla2xxx-use-named-initializers-for-port_state_str.patch [new file with mode: 0644]
queue-5.15/selftests-mptcp-pm-ensure-unknown-flags-are-ignored.patch [new file with mode: 0644]
queue-5.15/series
queue-5.15/smb-client-set-correct-id-uid-and-cruid-for-multiuser-automounts.patch [new file with mode: 0644]
queue-5.15/smb-server-fix-leak-of-active_num_conn-in-ksmbd_tcp_new_connection.patch [new file with mode: 0644]

diff --git a/queue-5.15/btrfs-fix-racy-bitfield-write-in-btrfs_clear_space_info_full.patch b/queue-5.15/btrfs-fix-racy-bitfield-write-in-btrfs_clear_space_info_full.patch
new file mode 100644 (file)
index 0000000..cf590b0
--- /dev/null
@@ -0,0 +1,246 @@
+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 */
diff --git a/queue-5.15/bus-fsl-mc-fix-use-after-free-in-driver_override_show.patch b/queue-5.15/bus-fsl-mc-fix-use-after-free-in-driver_override_show.patch
new file mode 100644 (file)
index 0000000..ff716ad
--- /dev/null
@@ -0,0 +1,50 @@
+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);
diff --git a/queue-5.15/bus-fsl-mc-replace-snprintf-and-sprintf-with-sysfs_emit-in-sysfs-show-functions.patch b/queue-5.15/bus-fsl-mc-replace-snprintf-and-sprintf-with-sysfs_emit-in-sysfs-show-functions.patch
new file mode 100644 (file)
index 0000000..cbb7cb2
--- /dev/null
@@ -0,0 +1,48 @@
+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);
diff --git a/queue-5.15/crypto-virtio-remove-duplicated-virtqueue_kick-in-virtio_crypto_skcipher_crypt_req.patch b/queue-5.15/crypto-virtio-remove-duplicated-virtqueue_kick-in-virtio_crypto_skcipher_crypt_req.patch
new file mode 100644 (file)
index 0000000..1f11b62
--- /dev/null
@@ -0,0 +1,40 @@
+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;
+ }
diff --git a/queue-5.15/mptcp-fix-race-in-mptcp_pm_nl_flush_addrs_doit.patch b/queue-5.15/mptcp-fix-race-in-mptcp_pm_nl_flush_addrs_doit.patch
new file mode 100644 (file)
index 0000000..82086be
--- /dev/null
@@ -0,0 +1,82 @@
+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;
+ }
diff --git a/queue-5.15/net-dsa-free-routing-table-on-probe-failure.patch b/queue-5.15/net-dsa-free-routing-table-on-probe-failure.patch
new file mode 100644 (file)
index 0000000..3f4da2a
--- /dev/null
@@ -0,0 +1,160 @@
+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);
diff --git a/queue-5.15/pci-endpoint-automatically-create-a-function-specific-attributes-group.patch b/queue-5.15/pci-endpoint-automatically-create-a-function-specific-attributes-group.patch
new file mode 100644 (file)
index 0000000..9aded88
--- /dev/null
@@ -0,0 +1,235 @@
+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,
diff --git a/queue-5.15/pci-endpoint-avoid-creating-sub-groups-asynchronously.patch b/queue-5.15/pci-endpoint-avoid-creating-sub-groups-asynchronously.patch
new file mode 100644 (file)
index 0000000..c930bf5
--- /dev/null
@@ -0,0 +1,103 @@
+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;
diff --git a/queue-5.15/pci-endpoint-remove-unused-field-in-struct-pci_epf_group.patch b/queue-5.15/pci-endpoint-remove-unused-field-in-struct-pci_epf_group.patch
new file mode 100644 (file)
index 0000000..6370bef
--- /dev/null
@@ -0,0 +1,43 @@
+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;
diff --git a/queue-5.15/scsi-qla2xxx-fix-bsg_done-causing-double-free.patch b/queue-5.15/scsi-qla2xxx-fix-bsg_done-causing-double-free.patch
new file mode 100644 (file)
index 0000000..4ec1d1c
--- /dev/null
@@ -0,0 +1,125 @@
+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;
+ }
diff --git a/queue-5.15/scsi-qla2xxx-free-sp-in-error-path-to-fix-system-crash.patch b/queue-5.15/scsi-qla2xxx-free-sp-in-error-path-to-fix-system-crash.patch
new file mode 100644 (file)
index 0000000..b5690a1
--- /dev/null
@@ -0,0 +1,87 @@
+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)
diff --git a/queue-5.15/scsi-qla2xxx-reduce-fabric-scan-duplicate-code.patch b/queue-5.15/scsi-qla2xxx-reduce-fabric-scan-duplicate-code.patch
new file mode 100644 (file)
index 0000000..a28100a
--- /dev/null
@@ -0,0 +1,716 @@
+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);
diff --git a/queue-5.15/scsi-qla2xxx-remove-dead-code-gnn-id.patch b/queue-5.15/scsi-qla2xxx-remove-dead-code-gnn-id.patch
new file mode 100644 (file)
index 0000000..6c402db
--- /dev/null
@@ -0,0 +1,214 @@
+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;
diff --git a/queue-5.15/scsi-qla2xxx-use-named-initializers-for-port_state_str.patch b/queue-5.15/scsi-qla2xxx-use-named-initializers-for-port_state_str.patch
new file mode 100644 (file)
index 0000000..5396e99
--- /dev/null
@@ -0,0 +1,95 @@
+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
diff --git a/queue-5.15/selftests-mptcp-pm-ensure-unknown-flags-are-ignored.patch b/queue-5.15/selftests-mptcp-pm-ensure-unknown-flags-are-ignored.patch
new file mode 100644 (file)
index 0000000..cc5e77a
--- /dev/null
@@ -0,0 +1,94 @@
+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)
index 2d0f4a5a21a4501634d9ca4703583a020168d5e4..5b3a0fc4fca1068a08e476427d281af0222a6d35 100644 (file)
@@ -15,3 +15,20 @@ platform-x86-panasonic-laptop-fix-sysfs-group-leak-i.patch
 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
diff --git a/queue-5.15/smb-client-set-correct-id-uid-and-cruid-for-multiuser-automounts.patch b/queue-5.15/smb-client-set-correct-id-uid-and-cruid-for-multiuser-automounts.patch
new file mode 100644 (file)
index 0000000..c7b30d1
--- /dev/null
@@ -0,0 +1,64 @@
+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);
diff --git a/queue-5.15/smb-server-fix-leak-of-active_num_conn-in-ksmbd_tcp_new_connection.patch b/queue-5.15/smb-server-fix-leak-of-active_num_conn-in-ksmbd_tcp_new_connection.patch
new file mode 100644 (file)
index 0000000..fe1e93b
--- /dev/null
@@ -0,0 +1,48 @@
+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;