]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
6.1-stable patches master
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Mon, 16 Feb 2026 10:36:29 +0000 (11:36 +0100)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Mon, 16 Feb 2026 10:36:29 +0000 (11:36 +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
cacheinfo-decrement-refcount-in-cache_setup_of_node.patch
cacheinfo-remove-of_node_put-for-fw_token.patch
net-sfp-fix-quirk-for-ubiquiti-u-fiber-instant-sfp-module.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
smb-client-set-correct-id-uid-and-cruid-for-multiuser-automounts.patch

15 files changed:
queue-6.1/btrfs-fix-racy-bitfield-write-in-btrfs_clear_space_info_full.patch [new file with mode: 0644]
queue-6.1/bus-fsl-mc-fix-use-after-free-in-driver_override_show.patch [new file with mode: 0644]
queue-6.1/bus-fsl-mc-replace-snprintf-and-sprintf-with-sysfs_emit-in-sysfs-show-functions.patch [new file with mode: 0644]
queue-6.1/cacheinfo-decrement-refcount-in-cache_setup_of_node.patch [new file with mode: 0644]
queue-6.1/cacheinfo-remove-of_node_put-for-fw_token.patch [new file with mode: 0644]
queue-6.1/net-sfp-fix-quirk-for-ubiquiti-u-fiber-instant-sfp-module.patch [new file with mode: 0644]
queue-6.1/pci-endpoint-automatically-create-a-function-specific-attributes-group.patch [new file with mode: 0644]
queue-6.1/pci-endpoint-avoid-creating-sub-groups-asynchronously.patch [new file with mode: 0644]
queue-6.1/pci-endpoint-remove-unused-field-in-struct-pci_epf_group.patch [new file with mode: 0644]
queue-6.1/scsi-qla2xxx-fix-bsg_done-causing-double-free.patch [new file with mode: 0644]
queue-6.1/scsi-qla2xxx-free-sp-in-error-path-to-fix-system-crash.patch [new file with mode: 0644]
queue-6.1/scsi-qla2xxx-reduce-fabric-scan-duplicate-code.patch [new file with mode: 0644]
queue-6.1/scsi-qla2xxx-remove-dead-code-gnn-id.patch [new file with mode: 0644]
queue-6.1/series
queue-6.1/smb-client-set-correct-id-uid-and-cruid-for-multiuser-automounts.patch [new file with mode: 0644]

diff --git a/queue-6.1/btrfs-fix-racy-bitfield-write-in-btrfs_clear_space_info_full.patch b/queue-6.1/btrfs-fix-racy-bitfield-write-in-btrfs_clear_space_info_full.patch
new file mode 100644 (file)
index 0000000..b0f23bc
--- /dev/null
@@ -0,0 +1,250 @@
+From 38e818718c5e04961eea0fa8feff3f100ce40408 Mon Sep 17 00:00:00 2001
+From: Boris Burkov <boris@bur.io>
+Date: Wed, 1 Oct 2025 17:20:22 -0700
+Subject: btrfs: fix racy bitfield write in btrfs_clear_space_info_full()
+
+From: Boris Burkov <boris@bur.io>
+
+commit 38e818718c5e04961eea0fa8feff3f100ce40408 upstream.
+
+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")
+  in v6.16 which is 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  |   22 +++++++++++-----------
+ fs/btrfs/space-info.h  |    6 +++---
+ 3 files changed, 17 insertions(+), 17 deletions(-)
+
+--- a/fs/btrfs/block-group.c
++++ b/fs/btrfs/block-group.c
+@@ -3924,7 +3924,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);
+               }
+@@ -3973,7 +3973,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 {
+@@ -3983,7 +3983,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
+@@ -179,7 +179,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;
+ }
+ /*
+@@ -360,7 +360,7 @@ void btrfs_add_bg_to_space_info(struct b
+       found->bytes_readonly += block_group->bytes_super;
+       btrfs_space_info_update_bytes_zone_unusable(info, found, block_group->zone_unusable);
+       if (block_group->length > 0)
+-              found->full = 0;
++              found->full = false;
+       btrfs_try_granting_tickets(info, found);
+       spin_unlock(&found->lock);
+@@ -1116,7 +1116,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;
+       }
+@@ -1128,7 +1128,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;
+               }
+@@ -1171,7 +1171,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;
+@@ -1333,7 +1333,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;
+       }
+@@ -1344,7 +1344,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;
+               }
+@@ -1361,7 +1361,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;
+               }
+@@ -1378,7 +1378,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;
+                       }
+@@ -1394,7 +1394,7 @@ static void btrfs_async_reclaim_data_spa
+ aborted_fs:
+       maybe_fail_all_tickets(fs_info, space_info);
+-      space_info->flush = 0;
++      space_info->flush = false;
+       spin_unlock(&space_info->lock);
+ }
+@@ -1719,7 +1719,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
+@@ -109,11 +109,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-6.1/bus-fsl-mc-fix-use-after-free-in-driver_override_show.patch b/queue-6.1/bus-fsl-mc-fix-use-after-free-in-driver_override_show.patch
new file mode 100644 (file)
index 0000000..c466b5f
--- /dev/null
@@ -0,0 +1,50 @@
+From stable+bounces-216275-greg=kroah.com@vger.kernel.org Fri Feb 13 17:45:14 2026
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 13 Feb 2026 11:45:08 -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: <20260213164508.3564699-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
+@@ -201,8 +201,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-6.1/bus-fsl-mc-replace-snprintf-and-sprintf-with-sysfs_emit-in-sysfs-show-functions.patch b/queue-6.1/bus-fsl-mc-replace-snprintf-and-sprintf-with-sysfs_emit-in-sysfs-show-functions.patch
new file mode 100644 (file)
index 0000000..da6f870
--- /dev/null
@@ -0,0 +1,48 @@
+From stable+bounces-216274-greg=kroah.com@vger.kernel.org Fri Feb 13 17:45:13 2026
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 13 Feb 2026 11:45:07 -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: <20260213164508.3564699-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
+@@ -175,8 +175,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);
+@@ -202,7 +202,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-6.1/cacheinfo-decrement-refcount-in-cache_setup_of_node.patch b/queue-6.1/cacheinfo-decrement-refcount-in-cache_setup_of_node.patch
new file mode 100644 (file)
index 0000000..11501cb
--- /dev/null
@@ -0,0 +1,66 @@
+From florian.fainelli@broadcom.com Fri Feb 13 18:57:04 2026
+From: Florian Fainelli <florian.fainelli@broadcom.com>
+Date: Fri, 13 Feb 2026 09:56:59 -0800
+Subject: cacheinfo: Decrement refcount in cache_setup_of_node()
+To: stable@vger.kernel.org
+Cc: Pierre Gondois <pierre.gondois@arm.com>, Sudeep Holla <sudeep.holla@arm.com>, Greg Kroah-Hartman <gregkh@linuxfoundation.org>, Florian Fainelli <florian.fainelli@broadcom.com>, "Rafael J. Wysocki" <rafael@kernel.org>, linux-kernel@vger.kernel.org (open list)
+Message-ID: <20260213175700.1964980-2-florian.fainelli@broadcom.com>
+
+From: Pierre Gondois <pierre.gondois@arm.com>
+
+commit 3da72e18371c41a6f6f96b594854b178168c7757 upstream
+
+Refcounts to DT nodes are only incremented in the function
+and never decremented. Decrease the refcounts when necessary.
+
+Signed-off-by: Pierre Gondois <pierre.gondois@arm.com>
+Reviewed-by: Sudeep Holla <sudeep.holla@arm.com>
+Link: https://lore.kernel.org/r/20221026185954.991547-1-pierre.gondois@arm.com
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Signed-off-by: Florian Fainelli <florian.fainelli@broadcom.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/base/cacheinfo.c |   17 +++++++++++------
+ 1 file changed, 11 insertions(+), 6 deletions(-)
+
+--- a/drivers/base/cacheinfo.c
++++ b/drivers/base/cacheinfo.c
+@@ -195,7 +195,7 @@ static void cache_of_set_props(struct ca
+ static int cache_setup_of_node(unsigned int cpu)
+ {
+-      struct device_node *np;
++      struct device_node *np, *prev;
+       struct cacheinfo *this_leaf;
+       unsigned int index = 0;
+@@ -205,19 +205,24 @@ static int cache_setup_of_node(unsigned
+               return -ENOENT;
+       }
++      prev = np;
++
+       while (index < cache_leaves(cpu)) {
+               this_leaf = per_cpu_cacheinfo_idx(cpu, index);
+-              if (this_leaf->level != 1)
++              if (this_leaf->level != 1) {
+                       np = of_find_next_cache_node(np);
+-              else
+-                      np = of_node_get(np);/* cpu node itself */
+-              if (!np)
+-                      break;
++                      of_node_put(prev);
++                      prev = np;
++                      if (!np)
++                              break;
++              }
+               cache_of_set_props(this_leaf, np);
+               this_leaf->fw_token = np;
+               index++;
+       }
++      of_node_put(np);
++
+       if (index != cache_leaves(cpu)) /* not all OF nodes populated */
+               return -ENOENT;
diff --git a/queue-6.1/cacheinfo-remove-of_node_put-for-fw_token.patch b/queue-6.1/cacheinfo-remove-of_node_put-for-fw_token.patch
new file mode 100644 (file)
index 0000000..f687b44
--- /dev/null
@@ -0,0 +1,79 @@
+From florian.fainelli@broadcom.com Fri Feb 13 18:57:05 2026
+From: Florian Fainelli <florian.fainelli@broadcom.com>
+Date: Fri, 13 Feb 2026 09:57:00 -0800
+Subject: cacheinfo: Remove of_node_put() for fw_token
+To: stable@vger.kernel.org
+Cc: Pierre Gondois <pierre.gondois@arm.com>, Geert Uytterhoeven <geert@linux-m68k.org>, Marek Szyprowski <m.szyprowski@samsung.com>, Geert Uytterhoeven <geert+renesas@glider.be>, Sudeep Holla <sudeep.holla@arm.com>, Greg Kroah-Hartman <gregkh@linuxfoundation.org>, Florian Fainelli <florian.fainelli@broadcom.com>, "Rafael J. Wysocki" <rafael@kernel.org>, linux-kernel@vger.kernel.org (open list)
+Message-ID: <20260213175700.1964980-3-florian.fainelli@broadcom.com>
+
+From: Pierre Gondois <pierre.gondois@arm.com>
+
+commit 2613cc29c5723881ca603b1a3b50f0107010d5d6 upstream
+
+fw_token is used for DT/ACPI systems to identify CPUs sharing caches.
+For DT based systems, fw_token is set to a pointer to a DT node.
+
+commit 3da72e18371c ("cacheinfo: Decrement refcount in
+cache_setup_of_node()")
+doesn't increment the refcount of fw_token anymore in
+cache_setup_of_node(). fw_token is indeed used as a token and not
+as a (struct device_node*), so no reference to fw_token should be
+kept.
+
+However, [1] is triggered when hotplugging a CPU multiple times
+since cache_shared_cpu_map_remove() decrements the refcount to
+fw_token at each CPU unplugging, eventually reaching 0.
+
+Remove of_node_put() for fw_token in cache_shared_cpu_map_remove().
+
+[1]
+------------[ cut here ]------------
+refcount_t: saturated; leaking memory.
+WARNING: CPU: 4 PID: 32 at lib/refcount.c:22 refcount_warn_saturate (lib/refcount.c:22 (discriminator 3))
+Modules linked in:
+CPU: 4 PID: 32 Comm: cpuhp/4 Tainted: G        W          6.1.0-rc1-14091-g9fdf2ca7b9c8 #76
+Hardware name: ARM LTD ARM Juno Development Platform/ARM Juno Development Platform, BIOS EDK II Oct 31 2022
+pstate: 600000c5 (nZCv daIF -PAN -UAO -TCO -DIT -SSBS BTYPE=--)
+pc : refcount_warn_saturate (lib/refcount.c:22 (discriminator 3))
+lr : refcount_warn_saturate (lib/refcount.c:22 (discriminator 3))
+[...]
+Call trace:
+[...]
+of_node_release (drivers/of/dynamic.c:335)
+kobject_put (lib/kobject.c:677 lib/kobject.c:704 ./include/linux/kref.h:65 lib/kobject.c:721)
+of_node_put (drivers/of/dynamic.c:49)
+free_cache_attributes.part.0 (drivers/base/cacheinfo.c:712)
+cacheinfo_cpu_pre_down (drivers/base/cacheinfo.c:718)
+cpuhp_invoke_callback (kernel/cpu.c:247 (discriminator 4))
+cpuhp_thread_fun (kernel/cpu.c:785)
+smpboot_thread_fn (kernel/smpboot.c:164 (discriminator 3))
+kthread (kernel/kthread.c:376)
+ret_from_fork (arch/arm64/kernel/entry.S:861)
+---[ end trace 0000000000000000 ]---
+
+Fixes: 3da72e18371c ("cacheinfo: Decrement refcount in cache_setup_of_node()")
+Reported-by: Geert Uytterhoeven <geert@linux-m68k.org>
+Reported-by: Marek Szyprowski <m.szyprowski@samsung.com>
+Tested-by: Geert Uytterhoeven <geert+renesas@glider.be>
+Tested-by: Sudeep Holla <sudeep.holla@arm.com>
+Reviewed-by: Sudeep Holla <sudeep.holla@arm.com>
+Signed-off-by: Pierre Gondois <pierre.gondois@arm.com>
+Link: https://lore.kernel.org/r/20221116094958.2141072-1-pierre.gondois@arm.com
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Signed-off-by: Florian Fainelli <florian.fainelli@broadcom.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/base/cacheinfo.c |    2 --
+ 1 file changed, 2 deletions(-)
+
+--- a/drivers/base/cacheinfo.c
++++ b/drivers/base/cacheinfo.c
+@@ -409,8 +409,6 @@ static void cache_shared_cpu_map_remove(
+                               }
+                       }
+               }
+-              if (of_have_populated_dt())
+-                      of_node_put(this_leaf->fw_token);
+       }
+       /* cpu is no longer populated in the shared map */
diff --git a/queue-6.1/net-sfp-fix-quirk-for-ubiquiti-u-fiber-instant-sfp-module.patch b/queue-6.1/net-sfp-fix-quirk-for-ubiquiti-u-fiber-instant-sfp-module.patch
new file mode 100644 (file)
index 0000000..df229a3
--- /dev/null
@@ -0,0 +1,50 @@
+From adcbadfd8e05d3558c9cfaa783f17c645181165f Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Marek=20Beh=C3=BAn?= <kabel@kernel.org>
+Date: Thu, 29 Jan 2026 09:22:27 +0100
+Subject: net: sfp: Fix quirk for Ubiquiti U-Fiber Instant SFP module
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Marek Behún <kabel@kernel.org>
+
+commit adcbadfd8e05d3558c9cfaa783f17c645181165f upstream.
+
+Commit fd580c9830316eda ("net: sfp: augment SFP parsing with
+phy_interface_t bitmap") did not add augumentation for the interface
+bitmap in the quirk for Ubiquiti U-Fiber Instant.
+
+The subsequent commit f81fa96d8a6c7a77 ("net: phylink: use
+phy_interface_t bitmaps for optical modules") then changed phylink code
+for selection of SFP interface: instead of using link mode bitmap, the
+interface bitmap is used, and the fastest interface mode supported by
+both SFP module and MAC is chosen.
+
+Since the interface bitmap contains also modes faster than 1000base-x,
+this caused a regression wherein this module stopped working
+out-of-the-box.
+
+Fix this.
+
+Fixes: fd580c9830316eda ("net: sfp: augment SFP parsing with phy_interface_t bitmap")
+Signed-off-by: Marek Behún <kabel@kernel.org>
+Reviewed-by: Maxime Chevallier <maxime.chevallier@bootlin.com>
+Reviewed-by: Russell King (Oracle) <rmk+kernel@armlinux.org.uk>
+Link: https://patch.msgid.link/20260129082227.17443-1-kabel@kernel.org
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/net/phy/sfp.c |    2 ++
+ 1 file changed, 2 insertions(+)
+
+--- a/drivers/net/phy/sfp.c
++++ b/drivers/net/phy/sfp.c
+@@ -376,6 +376,8 @@ static void sfp_quirk_ubnt_uf_instant(co
+        */
+       linkmode_zero(modes);
+       linkmode_set_bit(ETHTOOL_LINK_MODE_1000baseX_Full_BIT, modes);
++      phy_interface_zero(interfaces);
++      __set_bit(PHY_INTERFACE_MODE_1000BASEX, interfaces);
+ }
+ #define SFP_QUIRK(_v, _p, _m, _f) \
diff --git a/queue-6.1/pci-endpoint-automatically-create-a-function-specific-attributes-group.patch b/queue-6.1/pci-endpoint-automatically-create-a-function-specific-attributes-group.patch
new file mode 100644 (file)
index 0000000..8b383b8
--- /dev/null
@@ -0,0 +1,265 @@
+From stable+bounces-216463-greg=kroah.com@vger.kernel.org Sat Feb 14 03:23:22 2026
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 13 Feb 2026 21:23:13 -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: <20260214022316.4103092-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 ++----
+ Documentation/PCI/endpoint/pci-vntb-howto.rst |   13 +++-----
+ drivers/pci/endpoint/pci-ep-cfs.c             |   42 ++++++++++++--------------
+ 3 files changed, 29 insertions(+), 37 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/Documentation/PCI/endpoint/pci-vntb-howto.rst
++++ b/Documentation/PCI/endpoint/pci-vntb-howto.rst
+@@ -84,13 +84,10 @@ commands can be used::
+       # echo 0x1957 > functions/pci_epf_vntb/func1/vendorid
+       # echo 0x0809 > functions/pci_epf_vntb/func1/deviceid
+-In order to configure NTB specific attributes, a new sub-directory to func1
+-should be created::
+-
+-      # mkdir functions/pci_epf_vntb/func1/pci_epf_vntb.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_vntb/func1/pci_epf_vntb.0/
+       db_count    mw1         mw2         mw3         mw4         num_mws
+@@ -103,7 +100,7 @@ A sample configuration for NTB function
+       # echo 1 > functions/pci_epf_vntb/func1/pci_epf_vntb.0/num_mws
+       # echo 0x100000 > functions/pci_epf_vntb/func1/pci_epf_vntb.0/mw1
+-A sample configuration for virtual NTB driver for virutal PCI bus::
++A sample configuration for virtual NTB driver for virtual PCI bus::
+       # echo 0x1957 > functions/pci_epf_vntb/func1/pci_epf_vntb.0/vntb_vid
+       # echo 0x080A > functions/pci_epf_vntb/func1/pci_epf_vntb.0/vntb_pid
+--- 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;
+@@ -502,34 +503,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;
+@@ -547,6 +543,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-6.1/pci-endpoint-avoid-creating-sub-groups-asynchronously.patch b/queue-6.1/pci-endpoint-avoid-creating-sub-groups-asynchronously.patch
new file mode 100644 (file)
index 0000000..3dcd0d5
--- /dev/null
@@ -0,0 +1,103 @@
+From stable+bounces-216465-greg=kroah.com@vger.kernel.org Sat Feb 14 03:23:23 2026
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 13 Feb 2026 21:23:15 -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: <20260214022316.4103092-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;
+ }
+@@ -522,15 +521,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");
+@@ -589,9 +586,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-6.1/pci-endpoint-remove-unused-field-in-struct-pci_epf_group.patch b/queue-6.1/pci-endpoint-remove-unused-field-in-struct-pci_epf_group.patch
new file mode 100644 (file)
index 0000000..8dc2304
--- /dev/null
@@ -0,0 +1,43 @@
+From stable+bounces-216464-greg=kroah.com@vger.kernel.org Sat Feb 14 03:23:23 2026
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 13 Feb 2026 21:23:14 -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: <20260214022316.4103092-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-6.1/scsi-qla2xxx-fix-bsg_done-causing-double-free.patch b/queue-6.1/scsi-qla2xxx-fix-bsg_done-causing-double-free.patch
new file mode 100644 (file)
index 0000000..dbad4d7
--- /dev/null
@@ -0,0 +1,135 @@
+From stable+bounces-216460-greg=kroah.com@vger.kernel.org Sat Feb 14 02:49:24 2026
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 13 Feb 2026 20:49:14 -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: <20260214014914.3893755-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 |   28 +++++++++++++++++-----------
+ 1 file changed, 17 insertions(+), 11 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;
+ }
+@@ -2612,8 +2613,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;
+ }
+@@ -2702,8 +2704,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:
+@@ -2802,8 +2805,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);
+@@ -2864,8 +2868,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;
+ }
+@@ -3240,7 +3245,8 @@ int qla2x00_mailbox_passthru(struct bsg_
+       bsg_job->reply_len = sizeof(*bsg_job->reply);
+       bsg_reply->result = DID_OK << 16;
+-      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(req_data);
diff --git a/queue-6.1/scsi-qla2xxx-free-sp-in-error-path-to-fix-system-crash.patch b/queue-6.1/scsi-qla2xxx-free-sp-in-error-path-to-fix-system-crash.patch
new file mode 100644 (file)
index 0000000..3e5aa79
--- /dev/null
@@ -0,0 +1,87 @@
+From stable+bounces-216251-greg=kroah.com@vger.kernel.org Fri Feb 13 16:43:48 2026
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 13 Feb 2026 10:43:32 -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: <20260213154332.3544750-3-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
+@@ -3919,8 +3919,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-6.1/scsi-qla2xxx-reduce-fabric-scan-duplicate-code.patch b/queue-6.1/scsi-qla2xxx-reduce-fabric-scan-duplicate-code.patch
new file mode 100644 (file)
index 0000000..8b9fb3e
--- /dev/null
@@ -0,0 +1,716 @@
+From stable+bounces-216250-greg=kroah.com@vger.kernel.org Fri Feb 13 16:44:06 2026
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 13 Feb 2026 10:43:31 -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: <20260213154332.3544750-2-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
+@@ -3273,11 +3273,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;
+@@ -3503,9 +3512,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
+@@ -736,9 +736,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
+@@ -3488,7 +3488,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;
+@@ -3700,14 +3700,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;
+@@ -3717,37 +3714,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;
+@@ -3766,85 +3741,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) {
+@@ -3868,8 +3841,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);
+@@ -3894,28 +3866,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) {
+@@ -3926,127 +3900,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)
+@@ -4055,22 +3918,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) {
+@@ -4086,7 +3948,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;
+@@ -4094,7 +3956,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) *
+@@ -4106,7 +3967,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;
+@@ -4126,35 +3987,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) {
+@@ -4187,7 +4108,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);
+@@ -4198,6 +4119,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
+@@ -6444,10 +6444,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
+@@ -5522,15 +5522,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-6.1/scsi-qla2xxx-remove-dead-code-gnn-id.patch b/queue-6.1/scsi-qla2xxx-remove-dead-code-gnn-id.patch
new file mode 100644 (file)
index 0000000..d8641bc
--- /dev/null
@@ -0,0 +1,214 @@
+From stable+bounces-216249-greg=kroah.com@vger.kernel.org Fri Feb 13 16:44:02 2026
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 13 Feb 2026 10:43:30 -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: <20260213154332.3544750-1-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
+@@ -2499,7 +2499,6 @@ struct ct_sns_desc {
+ enum discovery_state {
+       DSC_DELETED,
+-      DSC_GNN_ID,
+       DSC_GNL,
+       DSC_LOGIN_PEND,
+       DSC_LOGIN_FAILED,
+@@ -2712,7 +2711,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",
+@@ -3508,7 +3506,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
+@@ -739,9 +739,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
+@@ -4216,116 +4216,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
+@@ -1723,12 +1723,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
+@@ -5532,9 +5532,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;
index a3644ad845e6e228c419e6d870a51b5a1dcc15c0..7b05e373fa9063fe85601ec7b260ec1eb7fd1225 100644 (file)
@@ -13,3 +13,17 @@ scsi-qla2xxx-allow-recovery-for-tape-devices.patch
 scsi-qla2xxx-delay-module-unload-while-fabric-scan-in-progress.patch
 scsi-qla2xxx-query-fw-again-before-proceeding-with-login.patch
 gpio-omap-do-not-register-driver-in-probe.patch
+btrfs-fix-racy-bitfield-write-in-btrfs_clear_space_info_full.patch
+net-sfp-fix-quirk-for-ubiquiti-u-fiber-instant-sfp-module.patch
+smb-client-set-correct-id-uid-and-cruid-for-multiuser-automounts.patch
+scsi-qla2xxx-fix-bsg_done-causing-double-free.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
+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-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
+cacheinfo-decrement-refcount-in-cache_setup_of_node.patch
+cacheinfo-remove-of_node_put-for-fw_token.patch
diff --git a/queue-6.1/smb-client-set-correct-id-uid-and-cruid-for-multiuser-automounts.patch b/queue-6.1/smb-client-set-correct-id-uid-and-cruid-for-multiuser-automounts.patch
new file mode 100644 (file)
index 0000000..c2197f8
--- /dev/null
@@ -0,0 +1,61 @@
+From 4508ec17357094e2075f334948393ddedbb75157 Mon Sep 17 00:00:00 2001
+From: Paulo Alcantara <pc@manguebit.com>
+Date: Sun, 11 Feb 2024 20:19:30 -0300
+Subject: smb: client: set correct id, uid and cruid for multiuser automounts
+
+From: Paulo Alcantara <pc@manguebit.com>
+
+commit 4508ec17357094e2075f334948393ddedbb75157 upstream.
+
+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/smb/client/cifs_dfs_ref.c |   16 ++++++++++++++++
+ 1 file changed, 16 insertions(+)
+
+--- a/fs/smb/client/cifs_dfs_ref.c
++++ b/fs/smb/client/cifs_dfs_ref.c
+@@ -283,6 +283,21 @@ out:
+       return rc;
+ }
++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
+  */
+@@ -333,6 +348,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);