commit:     4994f7a6a964771e4edb483163c052550960d29a
Author:     Arisu Tachibana <alicef <AT> gentoo <DOT> org>
AuthorDate: Fri Feb 20 02:26:46 2026 +0000
Commit:     Arisu Tachibana <alicef <AT> gentoo <DOT> org>
CommitDate: Fri Feb 20 02:26:46 2026 +0000
URL:        https://gitweb.gentoo.org/proj/linux-patches.git/commit/?id=4994f7a6

Linux patch 5.15.201

Signed-off-by: Arisu Tachibana <alicef <AT> gentoo.org>

 0000_README               |    4 +
 1200_linux-5.15.201.patch | 2222 +++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 2226 insertions(+)

diff --git a/0000_README b/0000_README
index 5c7ccef8..67e70c4e 100644
--- a/0000_README
+++ b/0000_README
@@ -843,6 +843,10 @@ Patch:  1199_linux-5.15.200.patch
 From:   https://www.kernel.org
 Desc:   Linux 5.15.200
 
+Patch:  1200_linux-5.15.201.patch
+From:   https://www.kernel.org
+Desc:   Linux 5.15.201
+
 Patch:  1500_XATTR_USER_PREFIX.patch
 From:   https://bugs.gentoo.org/show_bug.cgi?id=470644
 Desc:   Support for namespace user.pax.* on tmpfs.

diff --git a/1200_linux-5.15.201.patch b/1200_linux-5.15.201.patch
new file mode 100644
index 00000000..377853e1
--- /dev/null
+++ b/1200_linux-5.15.201.patch
@@ -0,0 +1,2222 @@
+diff --git a/Documentation/PCI/endpoint/pci-ntb-howto.rst 
b/Documentation/PCI/endpoint/pci-ntb-howto.rst
+index 1884bf29caba4b..4261e7157ef1ca 100644
+--- 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
+diff --git a/Makefile b/Makefile
+index 1af1fb3f126354..5e3d4c453ed7ef 100644
+--- a/Makefile
++++ b/Makefile
+@@ -1,7 +1,7 @@
+ # SPDX-License-Identifier: GPL-2.0
+ VERSION = 5
+ PATCHLEVEL = 15
+-SUBLEVEL = 200
++SUBLEVEL = 201
+ EXTRAVERSION =
+ NAME = Trick or Treat
+ 
+diff --git a/drivers/bus/fsl-mc/fsl-mc-bus.c b/drivers/bus/fsl-mc/fsl-mc-bus.c
+index 40d5249ec55c91..dc35de3e4379e6 100644
+--- a/drivers/bus/fsl-mc/fsl-mc-bus.c
++++ b/drivers/bus/fsl-mc/fsl-mc-bus.c
+@@ -156,8 +156,8 @@ static ssize_t modalias_show(struct device *dev, struct 
device_attribute *attr,
+ {
+       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);
+ 
+@@ -199,8 +199,12 @@ static ssize_t driver_override_show(struct device *dev,
+                                   struct device_attribute *attr, char *buf)
+ {
+       struct fsl_mc_device *mc_dev = to_fsl_mc_device(dev);
++      ssize_t len;
+ 
+-      return snprintf(buf, PAGE_SIZE, "%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/drivers/crypto/marvell/octeontx/otx_cptpf_ucode.c 
b/drivers/crypto/marvell/octeontx/otx_cptpf_ucode.c
+index a765eefb18c2fa..ad5f4a1677b300 100644
+--- a/drivers/crypto/marvell/octeontx/otx_cptpf_ucode.c
++++ b/drivers/crypto/marvell/octeontx/otx_cptpf_ucode.c
+@@ -1337,7 +1337,7 @@ static ssize_t ucode_load_store(struct device *dev,
+       int del_grp_idx = -1;
+       int ucode_idx = 0;
+ 
+-      if (strlen(buf) > OTX_CPT_UCODE_NAME_LENGTH)
++      if (count >= OTX_CPT_UCODE_NAME_LENGTH)
+               return -EINVAL;
+ 
+       eng_grps = container_of(attr, struct otx_cpt_eng_grps, ucode_load_attr);
+diff --git a/drivers/crypto/omap-crypto.c b/drivers/crypto/omap-crypto.c
+index a4cc6bf146ec09..0345c9383d5097 100644
+--- a/drivers/crypto/omap-crypto.c
++++ b/drivers/crypto/omap-crypto.c
+@@ -21,7 +21,7 @@ static int omap_crypto_copy_sg_lists(int total, int bs,
+       struct scatterlist *tmp;
+ 
+       if (!(flags & OMAP_CRYPTO_FORCE_SINGLE_ENTRY)) {
+-              new_sg = kmalloc_array(n, sizeof(*sg), GFP_KERNEL);
++              new_sg = kmalloc_array(n, sizeof(*new_sg), GFP_KERNEL);
+               if (!new_sg)
+                       return -ENOMEM;
+ 
+diff --git a/drivers/crypto/virtio/virtio_crypto_algs.c 
b/drivers/crypto/virtio/virtio_crypto_algs.c
+index 8b577e4aa39fac..3106e40d482e5c 100644
+--- a/drivers/crypto/virtio/virtio_crypto_algs.c
++++ b/drivers/crypto/virtio/virtio_crypto_algs.c
+@@ -569,8 +569,6 @@ int virtio_crypto_skcipher_crypt_req(
+       if (ret < 0)
+               return ret;
+ 
+-      virtqueue_kick(data_vq->vq);
+-
+       return 0;
+ }
+ 
+diff --git a/drivers/crypto/virtio/virtio_crypto_core.c 
b/drivers/crypto/virtio/virtio_crypto_core.c
+index f1eff8f752cd58..321f16c0c69a34 100644
+--- a/drivers/crypto/virtio/virtio_crypto_core.c
++++ b/drivers/crypto/virtio/virtio_crypto_core.c
+@@ -27,15 +27,20 @@ static void virtcrypto_done_task(unsigned long data)
+       struct data_queue *data_vq = (struct data_queue *)data;
+       struct virtqueue *vq = data_vq->vq;
+       struct virtio_crypto_request *vc_req;
++      unsigned long flags;
+       unsigned int len;
+ 
++      spin_lock_irqsave(&data_vq->lock, flags);
+       do {
+               virtqueue_disable_cb(vq);
+               while ((vc_req = virtqueue_get_buf(vq, &len)) != NULL) {
++                      spin_unlock_irqrestore(&data_vq->lock, flags);
+                       if (vc_req->alg_cb)
+                               vc_req->alg_cb(vc_req, len);
++                      spin_lock_irqsave(&data_vq->lock, flags);
+               }
+       } while (!virtqueue_enable_cb(vq));
++      spin_unlock_irqrestore(&data_vq->lock, flags);
+ }
+ 
+ static void virtcrypto_dataq_callback(struct virtqueue *vq)
+diff --git a/drivers/gpio/gpio-omap.c b/drivers/gpio/gpio-omap.c
+index 415e8df89d6fe0..171e2150c36265 100644
+--- a/drivers/gpio/gpio-omap.c
++++ b/drivers/gpio/gpio-omap.c
+@@ -762,10 +762,13 @@ static struct platform_device omap_mpuio_device = {
+ 
+ static inline void omap_mpuio_init(struct gpio_bank *bank)
+ {
+-      platform_set_drvdata(&omap_mpuio_device, bank);
++      static bool registered;
+ 
+-      if (platform_driver_register(&omap_mpuio_driver) == 0)
+-              (void) platform_device_register(&omap_mpuio_device);
++      platform_set_drvdata(&omap_mpuio_device, bank);
++      if (!registered) {
++              (void)platform_device_register(&omap_mpuio_device);
++              registered = true;
++      }
+ }
+ 
+ /*---------------------------------------------------------------------*/
+@@ -1574,13 +1577,24 @@ static struct platform_driver omap_gpio_driver = {
+  */
+ static int __init omap_gpio_drv_reg(void)
+ {
+-      return platform_driver_register(&omap_gpio_driver);
++      int ret;
++
++      ret = platform_driver_register(&omap_mpuio_driver);
++      if (ret)
++              return ret;
++
++      ret = platform_driver_register(&omap_gpio_driver);
++      if (ret)
++              platform_driver_unregister(&omap_mpuio_driver);
++
++      return ret;
+ }
+ postcore_initcall(omap_gpio_drv_reg);
+ 
+ static void __exit omap_gpio_exit(void)
+ {
+       platform_driver_unregister(&omap_gpio_driver);
++      platform_driver_unregister(&omap_mpuio_driver);
+ }
+ module_exit(omap_gpio_exit);
+ 
+diff --git a/drivers/gpio/gpio-sprd.c b/drivers/gpio/gpio-sprd.c
+index 9dd9dabb579e2d..b2b28c6877f2f0 100644
+--- a/drivers/gpio/gpio-sprd.c
++++ b/drivers/gpio/gpio-sprd.c
+@@ -35,7 +35,7 @@
+ struct sprd_gpio {
+       struct gpio_chip chip;
+       void __iomem *base;
+-      spinlock_t lock;
++      raw_spinlock_t lock;
+       int irq;
+ };
+ 
+@@ -54,7 +54,7 @@ static void sprd_gpio_update(struct gpio_chip *chip, 
unsigned int offset,
+       unsigned long flags;
+       u32 tmp;
+ 
+-      spin_lock_irqsave(&sprd_gpio->lock, flags);
++      raw_spin_lock_irqsave(&sprd_gpio->lock, flags);
+       tmp = readl_relaxed(base + reg);
+ 
+       if (val)
+@@ -63,7 +63,7 @@ static void sprd_gpio_update(struct gpio_chip *chip, 
unsigned int offset,
+               tmp &= ~BIT(SPRD_GPIO_BIT(offset));
+ 
+       writel_relaxed(tmp, base + reg);
+-      spin_unlock_irqrestore(&sprd_gpio->lock, flags);
++      raw_spin_unlock_irqrestore(&sprd_gpio->lock, flags);
+ }
+ 
+ static int sprd_gpio_read(struct gpio_chip *chip, unsigned int offset, u16 
reg)
+@@ -231,7 +231,7 @@ static int sprd_gpio_probe(struct platform_device *pdev)
+       if (IS_ERR(sprd_gpio->base))
+               return PTR_ERR(sprd_gpio->base);
+ 
+-      spin_lock_init(&sprd_gpio->lock);
++      raw_spin_lock_init(&sprd_gpio->lock);
+ 
+       sprd_gpio->chip.label = dev_name(&pdev->dev);
+       sprd_gpio->chip.ngpio = SPRD_GPIO_NR;
+diff --git a/drivers/gpio/gpiolib-acpi.c b/drivers/gpio/gpiolib-acpi.c
+index 3e4fd028a82da0..0e6a2200a5febb 100644
+--- a/drivers/gpio/gpiolib-acpi.c
++++ b/drivers/gpio/gpiolib-acpi.c
+@@ -1369,6 +1369,7 @@ static int acpi_gpio_package_count(const union 
acpi_object *obj)
+       while (element < end) {
+               switch (element->type) {
+               case ACPI_TYPE_LOCAL_REFERENCE:
++              case ACPI_TYPE_STRING:
+                       element += 3;
+                       fallthrough;
+               case ACPI_TYPE_INTEGER:
+diff --git a/drivers/gpu/drm/tegra/hdmi.c b/drivers/gpu/drm/tegra/hdmi.c
+index e5d2a402602887..fe700dfaaa4ce8 100644
+--- a/drivers/gpu/drm/tegra/hdmi.c
++++ b/drivers/gpu/drm/tegra/hdmi.c
+@@ -635,7 +635,7 @@ static void tegra_hdmi_write_infopack(struct tegra_hdmi 
*hdmi, const void *data,
+ {
+       const u8 *ptr = data;
+       unsigned long offset;
+-      size_t i, j;
++      size_t i;
+       u32 value;
+ 
+       switch (ptr[0]) {
+@@ -668,7 +668,7 @@ static void tegra_hdmi_write_infopack(struct tegra_hdmi 
*hdmi, const void *data,
+        * - subpack_low: bytes 0 - 3
+        * - subpack_high: bytes 4 - 6 (with byte 7 padded to 0x00)
+        */
+-      for (i = 3, j = 0; i < size; i += 7, j += 8) {
++      for (i = 3; i < size; i += 7) {
+               size_t rem = size - i, num = min_t(size_t, rem, 4);
+ 
+               value = tegra_hdmi_subpack(&ptr[i], num);
+diff --git a/drivers/gpu/drm/tegra/sor.c b/drivers/gpu/drm/tegra/sor.c
+index f2f76a0897a802..31e1f9ec9fead0 100644
+--- a/drivers/gpu/drm/tegra/sor.c
++++ b/drivers/gpu/drm/tegra/sor.c
+@@ -1860,7 +1860,7 @@ static void tegra_sor_hdmi_write_infopack(struct 
tegra_sor *sor,
+ {
+       const u8 *ptr = data;
+       unsigned long offset;
+-      size_t i, j;
++      size_t i;
+       u32 value;
+ 
+       switch (ptr[0]) {
+@@ -1893,7 +1893,7 @@ static void tegra_sor_hdmi_write_infopack(struct 
tegra_sor *sor,
+        * - subpack_low: bytes 0 - 3
+        * - subpack_high: bytes 4 - 6 (with byte 7 padded to 0x00)
+        */
+-      for (i = 3, j = 0; i < size; i += 7, j += 8) {
++      for (i = 3; i < size; i += 7) {
+               size_t rem = size - i, num = min_t(size_t, rem, 4);
+ 
+               value = tegra_sor_hdmi_subpack(&ptr[i], num);
+diff --git a/drivers/net/wireguard/device.c b/drivers/net/wireguard/device.c
+index 7bf1ec4ccaa980..e5e344af342371 100644
+--- a/drivers/net/wireguard/device.c
++++ b/drivers/net/wireguard/device.c
+@@ -352,7 +352,6 @@ static int wg_newlink(struct net *src_net, struct 
net_device *dev,
+       if (ret < 0)
+               goto err_free_handshake_queue;
+ 
+-      dev_set_threaded(dev, true);
+       ret = register_netdevice(dev);
+       if (ret < 0)
+               goto err_uninit_ratelimiter;
+diff --git a/drivers/pci/endpoint/pci-ep-cfs.c 
b/drivers/pci/endpoint/pci-ep-cfs.c
+index 149de77b2a423d..38140500704910 100644
+--- 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;
+ }
+@@ -514,40 +513,33 @@ static struct configfs_item_operations pci_epf_ops = {
+       .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_epf_cfs_work(struct work_struct *work)
++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_add_default_group(group, &epf_group->group);
++}
++
++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");
+@@ -559,6 +551,8 @@ static void pci_epf_cfs_work(struct 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,
+@@ -604,9 +598,7 @@ static struct config_group *pci_epf_make(struct 
config_group *group,
+ 
+       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/drivers/platform/x86/classmate-laptop.c 
b/drivers/platform/x86/classmate-laptop.c
+index 9309ab5792cbc3..ac02b22154d62a 100644
+--- a/drivers/platform/x86/classmate-laptop.c
++++ b/drivers/platform/x86/classmate-laptop.c
+@@ -208,7 +208,12 @@ static ssize_t cmpc_accel_sensitivity_show_v4(struct 
device *dev,
+ 
+       acpi = to_acpi_device(dev);
+       inputdev = dev_get_drvdata(&acpi->dev);
++      if (!inputdev)
++              return -ENXIO;
++
+       accel = dev_get_drvdata(&inputdev->dev);
++      if (!accel)
++              return -ENXIO;
+ 
+       return sprintf(buf, "%d\n", accel->sensitivity);
+ }
+@@ -225,7 +230,12 @@ static ssize_t cmpc_accel_sensitivity_store_v4(struct 
device *dev,
+ 
+       acpi = to_acpi_device(dev);
+       inputdev = dev_get_drvdata(&acpi->dev);
++      if (!inputdev)
++              return -ENXIO;
++
+       accel = dev_get_drvdata(&inputdev->dev);
++      if (!accel)
++              return -ENXIO;
+ 
+       r = kstrtoul(buf, 0, &sensitivity);
+       if (r)
+@@ -257,7 +267,12 @@ static ssize_t cmpc_accel_g_select_show_v4(struct device 
*dev,
+ 
+       acpi = to_acpi_device(dev);
+       inputdev = dev_get_drvdata(&acpi->dev);
++      if (!inputdev)
++              return -ENXIO;
++
+       accel = dev_get_drvdata(&inputdev->dev);
++      if (!accel)
++              return -ENXIO;
+ 
+       return sprintf(buf, "%d\n", accel->g_select);
+ }
+@@ -274,7 +289,12 @@ static ssize_t cmpc_accel_g_select_store_v4(struct device 
*dev,
+ 
+       acpi = to_acpi_device(dev);
+       inputdev = dev_get_drvdata(&acpi->dev);
++      if (!inputdev)
++              return -ENXIO;
++
+       accel = dev_get_drvdata(&inputdev->dev);
++      if (!accel)
++              return -ENXIO;
+ 
+       r = kstrtoul(buf, 0, &g_select);
+       if (r)
+@@ -303,6 +323,8 @@ static int cmpc_accel_open_v4(struct input_dev *input)
+ 
+       acpi = to_acpi_device(input->dev.parent);
+       accel = dev_get_drvdata(&input->dev);
++      if (!accel)
++              return -ENXIO;
+ 
+       cmpc_accel_set_sensitivity_v4(acpi->handle, accel->sensitivity);
+       cmpc_accel_set_g_select_v4(acpi->handle, accel->g_select);
+@@ -551,7 +573,12 @@ static ssize_t cmpc_accel_sensitivity_show(struct device 
*dev,
+ 
+       acpi = to_acpi_device(dev);
+       inputdev = dev_get_drvdata(&acpi->dev);
++      if (!inputdev)
++              return -ENXIO;
++
+       accel = dev_get_drvdata(&inputdev->dev);
++      if (!accel)
++              return -ENXIO;
+ 
+       return sprintf(buf, "%d\n", accel->sensitivity);
+ }
+@@ -568,7 +595,12 @@ static ssize_t cmpc_accel_sensitivity_store(struct device 
*dev,
+ 
+       acpi = to_acpi_device(dev);
+       inputdev = dev_get_drvdata(&acpi->dev);
++      if (!inputdev)
++              return -ENXIO;
++
+       accel = dev_get_drvdata(&inputdev->dev);
++      if (!accel)
++              return -ENXIO;
+ 
+       r = kstrtoul(buf, 0, &sensitivity);
+       if (r)
+diff --git a/drivers/platform/x86/panasonic-laptop.c 
b/drivers/platform/x86/panasonic-laptop.c
+index e412a550f09831..418cd4d7812614 100644
+--- a/drivers/platform/x86/panasonic-laptop.c
++++ b/drivers/platform/x86/panasonic-laptop.c
+@@ -1073,7 +1073,7 @@ static int acpi_pcc_hotkey_add(struct acpi_device 
*device)
+                       -1, NULL, 0);
+               if (IS_ERR(pcc->platform)) {
+                       result = PTR_ERR(pcc->platform);
+-                      goto out_backlight;
++                      goto out_sysfs;
+               }
+               result = device_create_file(&pcc->platform->dev,
+                       &dev_attr_cdpower);
+@@ -1089,6 +1089,8 @@ static int acpi_pcc_hotkey_add(struct acpi_device 
*device)
+ 
+ out_platform:
+       platform_device_unregister(pcc->platform);
++out_sysfs:
++      sysfs_remove_group(&device->dev.kobj, &pcc_attr_group);
+ out_backlight:
+       backlight_device_unregister(pcc->backlight);
+ out_input:
+diff --git a/drivers/scsi/qla2xxx/qla_bsg.c b/drivers/scsi/qla2xxx/qla_bsg.c
+index 02e4b9fc9deea7..23779a1f0cee9c 100644
+--- a/drivers/scsi/qla2xxx/qla_bsg.c
++++ b/drivers/scsi/qla2xxx/qla_bsg.c
+@@ -1546,8 +1546,9 @@ qla2x00_update_optrom(struct bsg_job *bsg_job)
+       ha->optrom_buffer = NULL;
+       ha->optrom_state = QLA_SWAITING;
+       mutex_unlock(&ha->optrom_mutex);
+-      bsg_job_done(bsg_job, bsg_reply->result,
+-                     bsg_reply->reply_payload_rcv_len);
++      if (!rval)
++              bsg_job_done(bsg_job, bsg_reply->result,
++                           bsg_reply->reply_payload_rcv_len);
+       return rval;
+ }
+ 
+@@ -2525,8 +2526,9 @@ qla2x00_manage_host_stats(struct bsg_job *bsg_job)
+                                   sizeof(struct ql_vnd_mng_host_stats_resp));
+ 
+       bsg_reply->result = DID_OK;
+-      bsg_job_done(bsg_job, bsg_reply->result,
+-                   bsg_reply->reply_payload_rcv_len);
++      if (!ret)
++              bsg_job_done(bsg_job, bsg_reply->result,
++                           bsg_reply->reply_payload_rcv_len);
+ 
+       return ret;
+ }
+@@ -2615,8 +2617,9 @@ qla2x00_get_host_stats(struct bsg_job *bsg_job)
+                                                              
bsg_job->reply_payload.sg_cnt,
+                                                              data, 
response_len);
+       bsg_reply->result = DID_OK;
+-      bsg_job_done(bsg_job, bsg_reply->result,
+-                   bsg_reply->reply_payload_rcv_len);
++      if (!ret)
++              bsg_job_done(bsg_job, bsg_reply->result,
++                           bsg_reply->reply_payload_rcv_len);
+ 
+       kfree(data);
+ host_stat_out:
+@@ -2715,8 +2718,9 @@ reply:
+                                   bsg_job->reply_payload.sg_cnt, data,
+                                   response_len);
+       bsg_reply->result = DID_OK;
+-      bsg_job_done(bsg_job, bsg_reply->result,
+-                   bsg_reply->reply_payload_rcv_len);
++      if (!ret)
++              bsg_job_done(bsg_job, bsg_reply->result,
++                           bsg_reply->reply_payload_rcv_len);
+ 
+ tgt_stat_out:
+       kfree(data);
+@@ -2777,8 +2781,9 @@ qla2x00_manage_host_port(struct bsg_job *bsg_job)
+                                   bsg_job->reply_payload.sg_cnt, &rsp_data,
+                                   sizeof(struct ql_vnd_mng_host_port_resp));
+       bsg_reply->result = DID_OK;
+-      bsg_job_done(bsg_job, bsg_reply->result,
+-                   bsg_reply->reply_payload_rcv_len);
++      if (!ret)
++              bsg_job_done(bsg_job, bsg_reply->result,
++                           bsg_reply->reply_payload_rcv_len);
+ 
+       return ret;
+ }
+diff --git a/drivers/scsi/qla2xxx/qla_def.h b/drivers/scsi/qla2xxx/qla_def.h
+index 02a2fd1b150a93..fde74fb8ce1b61 100644
+--- a/drivers/scsi/qla2xxx/qla_def.h
++++ b/drivers/scsi/qla2xxx/qla_def.h
+@@ -2488,7 +2488,6 @@ struct ct_sns_desc {
+ 
+ enum discovery_state {
+       DSC_DELETED,
+-      DSC_GNN_ID,
+       DSC_GNL,
+       DSC_LOGIN_PEND,
+       DSC_LOGIN_FAILED,
+@@ -2689,25 +2688,27 @@ struct event_arg {
+ /*
+  * Fibre channel port/lun states.
+  */
+-#define FCS_UNCONFIGURED      1
+-#define FCS_DEVICE_DEAD               2
+-#define FCS_DEVICE_LOST               3
+-#define FCS_ONLINE            4
++enum {
++      FCS_UNKNOWN,
++      FCS_UNCONFIGURED,
++      FCS_DEVICE_DEAD,
++      FCS_DEVICE_LOST,
++      FCS_ONLINE,
++};
+ 
+ extern const char *const port_state_str[5];
+ 
+-static const char * const port_dstate_str[] = {
+-      "DELETED",
+-      "GNN_ID",
+-      "GNL",
+-      "LOGIN_PEND",
+-      "LOGIN_FAILED",
+-      "GPDB",
+-      "UPD_FCPORT",
+-      "LOGIN_COMPLETE",
+-      "ADISC",
+-      "DELETE_PEND",
+-      "LOGIN_AUTH_PEND",
++static const char *const port_dstate_str[] = {
++      [DSC_DELETED]           = "DELETED",
++      [DSC_GNL]               = "GNL",
++      [DSC_LOGIN_PEND]        = "LOGIN_PEND",
++      [DSC_LOGIN_FAILED]      = "LOGIN_FAILED",
++      [DSC_GPDB]              = "GPDB",
++      [DSC_UPD_FCPORT]        = "UPD_FCPORT",
++      [DSC_LOGIN_COMPLETE]    = "LOGIN_COMPLETE",
++      [DSC_ADISC]             = "ADISC",
++      [DSC_DELETE_PEND]       = "DELETE_PEND",
++      [DSC_LOGIN_AUTH_PEND]   = "LOGIN_AUTH_PEND",
+ };
+ 
+ /*
+@@ -3261,11 +3262,20 @@ struct fab_scan_rp {
+       u8 node_name[8];
+ };
+ 
++enum scan_step {
++      FAB_SCAN_START,
++      FAB_SCAN_GPNFT_FCP,
++      FAB_SCAN_GNNFT_FCP,
++      FAB_SCAN_GPNFT_NVME,
++      FAB_SCAN_GNNFT_NVME,
++};
++
+ struct fab_scan {
+       struct fab_scan_rp *l;
+       u32 size;
+       u32 rscn_gen_start;
+       u32 rscn_gen_end;
++      enum scan_step step;
+       u16 scan_retry;
+ #define MAX_SCAN_RETRIES 5
+       enum scan_flags_t scan_flags;
+@@ -3491,10 +3501,8 @@ enum qla_work_type {
+       QLA_EVT_RELOGIN,
+       QLA_EVT_ASYNC_PRLO,
+       QLA_EVT_ASYNC_PRLO_DONE,
+-      QLA_EVT_GPNFT,
+-      QLA_EVT_GPNFT_DONE,
+-      QLA_EVT_GNNFT_DONE,
+-      QLA_EVT_GNNID,
++      QLA_EVT_SCAN_CMD,
++      QLA_EVT_SCAN_FINISH,
+       QLA_EVT_GFPNID,
+       QLA_EVT_SP_RETRY,
+       QLA_EVT_IIDMA,
+diff --git a/drivers/scsi/qla2xxx/qla_gbl.h b/drivers/scsi/qla2xxx/qla_gbl.h
+index e8c66cc4b71b49..323f0eee3a19a2 100644
+--- a/drivers/scsi/qla2xxx/qla_gbl.h
++++ b/drivers/scsi/qla2xxx/qla_gbl.h
+@@ -727,12 +727,9 @@ void qla24xx_handle_gpsc_event(scsi_qla_host_t *, struct 
event_arg *);
+ 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 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 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 *);
+diff --git a/drivers/scsi/qla2xxx/qla_gs.c b/drivers/scsi/qla2xxx/qla_gs.c
+index d0c3710b5cdf64..07dc489e1c61d8 100644
+--- a/drivers/scsi/qla2xxx/qla_gs.c
++++ b/drivers/scsi/qla2xxx/qla_gs.c
+@@ -3487,7 +3487,7 @@ static bool qla_ok_to_clear_rscn(scsi_qla_host_t *vha, 
fc_port_t *fcport)
+       return true;
+ }
+ 
+-void qla24xx_async_gnnft_done(scsi_qla_host_t *vha, srb_t *sp)
++void qla_fab_scan_finish(scsi_qla_host_t *vha, srb_t *sp)
+ {
+       fc_port_t *fcport;
+       u32 i, rc;
+@@ -3702,14 +3702,11 @@ out:
+       }
+ }
+ 
+-static int qla2x00_post_gnnft_gpnft_done_work(struct scsi_qla_host *vha,
++static int qla2x00_post_next_scan_work(struct scsi_qla_host *vha,
+     srb_t *sp, int cmd)
+ {
+       struct qla_work_evt *e;
+ 
+-      if (cmd != QLA_EVT_GPNFT_DONE && cmd != QLA_EVT_GNNFT_DONE)
+-              return QLA_PARAMETER_ERROR;
+-
+       e = qla2x00_alloc_work(vha, cmd);
+       if (!e)
+               return QLA_FUNCTION_FAILED;
+@@ -3719,37 +3716,15 @@ static int qla2x00_post_gnnft_gpnft_done_work(struct 
scsi_qla_host *vha,
+       return qla2x00_post_work(vha, e);
+ }
+ 
+-static int qla2x00_post_nvme_gpnft_work(struct scsi_qla_host *vha,
+-    srb_t *sp, int cmd)
+-{
+-      struct qla_work_evt *e;
+-
+-      if (cmd != QLA_EVT_GPNFT)
+-              return QLA_PARAMETER_ERROR;
+-
+-      e = qla2x00_alloc_work(vha, cmd);
+-      if (!e)
+-              return QLA_FUNCTION_FAILED;
+-
+-      e->u.gpnft.fc4_type = FC4_TYPE_NVME;
+-      e->u.gpnft.sp = sp;
+-
+-      return qla2x00_post_work(vha, e);
+-}
+-
+ static void qla2x00_find_free_fcp_nvme_slot(struct scsi_qla_host *vha,
+       struct srb *sp)
+ {
+       struct qla_hw_data *ha = vha->hw;
+       int num_fibre_dev = ha->max_fibre_devices;
+-      struct ct_sns_req *ct_req =
+-              (struct ct_sns_req *)sp->u.iocb_cmd.u.ctarg.req;
+       struct ct_sns_gpnft_rsp *ct_rsp =
+               (struct ct_sns_gpnft_rsp *)sp->u.iocb_cmd.u.ctarg.rsp;
+       struct ct_sns_gpn_ft_data *d;
+       struct fab_scan_rp *rp;
+-      u16 cmd = be16_to_cpu(ct_req->command);
+-      u8 fc4_type = sp->gen2;
+       int i, j, k;
+       port_id_t id;
+       u8 found;
+@@ -3768,85 +3743,83 @@ static void qla2x00_find_free_fcp_nvme_slot(struct 
scsi_qla_host *vha,
+               if (id.b24 == 0 || wwn == 0)
+                       continue;
+ 
+-              if (fc4_type == FC4_TYPE_FCP_SCSI) {
+-                      if (cmd == GPN_FT_CMD) {
+-                              rp = &vha->scan.l[j];
+-                              rp->id = id;
+-                              memcpy(rp->port_name, d->port_name, 8);
+-                              j++;
+-                              rp->fc4type = FS_FC4TYPE_FCP;
+-                      } else {
+-                              for (k = 0; k < num_fibre_dev; k++) {
+-                                      rp = &vha->scan.l[k];
+-                                      if (id.b24 == rp->id.b24) {
+-                                              memcpy(rp->node_name,
+-                                                  d->port_name, 8);
+-                                              break;
+-                                      }
++              ql_dbg(ql_dbg_disc + ql_dbg_verbose, vha, 0x2025,
++                     "%s %06x %8ph \n",
++                     __func__, id.b24, d->port_name);
++
++              switch (vha->scan.step) {
++              case FAB_SCAN_GPNFT_FCP:
++                      rp = &vha->scan.l[j];
++                      rp->id = id;
++                      memcpy(rp->port_name, d->port_name, 8);
++                      j++;
++                      rp->fc4type = FS_FC4TYPE_FCP;
++                      break;
++              case FAB_SCAN_GNNFT_FCP:
++                      for (k = 0; k < num_fibre_dev; k++) {
++                              rp = &vha->scan.l[k];
++                              if (id.b24 == rp->id.b24) {
++                                      memcpy(rp->node_name,
++                                          d->port_name, 8);
++                                      break;
+                               }
+                       }
+-              } else {
+-                      /* Search if the fibre device supports FC4_TYPE_NVME */
+-                      if (cmd == GPN_FT_CMD) {
+-                              found = 0;
++                      break;
++              case FAB_SCAN_GPNFT_NVME:
++                      found = 0;
+ 
+-                              for (k = 0; k < num_fibre_dev; k++) {
+-                                      rp = &vha->scan.l[k];
+-                                      if (!memcmp(rp->port_name,
+-                                          d->port_name, 8)) {
+-                                              /*
+-                                               * Supports FC-NVMe & FCP
+-                                               */
+-                                              rp->fc4type |= FS_FC4TYPE_NVME;
+-                                              found = 1;
+-                                              break;
+-                                      }
++                      for (k = 0; k < num_fibre_dev; k++) {
++                              rp = &vha->scan.l[k];
++                              if (!memcmp(rp->port_name, d->port_name, 8)) {
++                                      /*
++                                       * Supports FC-NVMe & FCP
++                                       */
++                                      rp->fc4type |= FS_FC4TYPE_NVME;
++                                      found = 1;
++                                      break;
+                               }
++                      }
+ 
+-                              /* We found new FC-NVMe only port */
+-                              if (!found) {
+-                                      for (k = 0; k < num_fibre_dev; k++) {
+-                                              rp = &vha->scan.l[k];
+-                                              if (wwn_to_u64(rp->port_name)) {
+-                                                      continue;
+-                                              } else {
+-                                                      rp->id = id;
+-                                                      memcpy(rp->port_name,
+-                                                          d->port_name, 8);
+-                                                      rp->fc4type =
+-                                                          FS_FC4TYPE_NVME;
+-                                                      break;
+-                                              }
+-                                      }
+-                              }
+-                      } else {
++                      /* We found new FC-NVMe only port */
++                      if (!found) {
+                               for (k = 0; k < num_fibre_dev; k++) {
+                                       rp = &vha->scan.l[k];
+-                                      if (id.b24 == rp->id.b24) {
+-                                              memcpy(rp->node_name,
+-                                                  d->port_name, 8);
++                                      if (wwn_to_u64(rp->port_name)) {
++                                              continue;
++                                      } else {
++                                              rp->id = id;
++                                              memcpy(rp->port_name, 
d->port_name, 8);
++                                              rp->fc4type = FS_FC4TYPE_NVME;
+                                               break;
+                                       }
+                               }
+                       }
++                      break;
++              case FAB_SCAN_GNNFT_NVME:
++                      for (k = 0; k < num_fibre_dev; k++) {
++                              rp = &vha->scan.l[k];
++                              if (id.b24 == rp->id.b24) {
++                                      memcpy(rp->node_name, d->port_name, 8);
++                                      break;
++                              }
++                      }
++                      break;
++              default:
++                      break;
+               }
+       }
+ }
+ 
+-static void qla2x00_async_gpnft_gnnft_sp_done(srb_t *sp, int res)
++static void qla_async_scan_sp_done(srb_t *sp, int res)
+ {
+       struct scsi_qla_host *vha = sp->vha;
+-      struct ct_sns_req *ct_req =
+-              (struct ct_sns_req *)sp->u.iocb_cmd.u.ctarg.req;
+-      u16 cmd = be16_to_cpu(ct_req->command);
+-      u8 fc4_type = sp->gen2;
+       unsigned long flags;
+       int rc;
+ 
+       /* gen2 field is holding the fc4type */
+-      ql_dbg(ql_dbg_disc, vha, 0xffff,
+-          "Async done-%s res %x FC4Type %x\n",
+-          sp->name, res, sp->gen2);
++      ql_dbg(ql_dbg_disc, vha, 0x2026,
++          "Async done-%s res %x step %x\n",
++          sp->name, res, vha->scan.step);
+ 
+       sp->rc = res;
+       if (res) {
+@@ -3870,8 +3843,7 @@ static void qla2x00_async_gpnft_gnnft_sp_done(srb_t *sp, 
int res)
+                * sp for GNNFT_DONE work. This will allow all
+                * the resource to get freed up.
+                */
+-              rc = qla2x00_post_gnnft_gpnft_done_work(vha, sp,
+-                  QLA_EVT_GNNFT_DONE);
++              rc = qla2x00_post_next_scan_work(vha, sp, QLA_EVT_SCAN_FINISH);
+               if (rc) {
+                       /* Cleanup here to prevent memory leak */
+                       qla24xx_sp_unmap(vha, sp);
+@@ -3896,28 +3868,30 @@ static void qla2x00_async_gpnft_gnnft_sp_done(srb_t 
*sp, int res)
+ 
+       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);
++      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;
+-      }
++      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);
+ 
+-      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);
++              break;
++      case  FAB_SCAN_GNNFT_NVME:
++              rc = qla2x00_post_next_scan_work(vha, sp, QLA_EVT_SCAN_FINISH);
++              break;
++      default:
++              /* should not be here */
++              WARN_ON(1);
++              rc = QLA_FUNCTION_FAILED;
++              break;
+       }
+ 
+       if (rc) {
+@@ -3928,127 +3902,16 @@ static void qla2x00_async_gpnft_gnnft_sp_done(srb_t 
*sp, int res)
+       }
+ }
+ 
+-/*
+- * Get WWNN list for fc4_type
+- *
+- * It is assumed the same SRB is re-used from GPNFT to avoid
+- * mem free & re-alloc
+- */
+-static int qla24xx_async_gnnft(scsi_qla_host_t *vha, struct srb *sp,
+-    u8 fc4_type)
+-{
+-      int rval = QLA_FUNCTION_FAILED;
+-      struct ct_sns_req *ct_req;
+-      struct ct_sns_pkt *ct_sns;
+-      unsigned long flags;
+-
+-      if (!vha->flags.online) {
+-              spin_lock_irqsave(&vha->work_lock, flags);
+-              vha->scan.scan_flags &= ~SF_SCANNING;
+-              spin_unlock_irqrestore(&vha->work_lock, flags);
+-              goto done_free_sp;
+-      }
+-
+-      if (!sp->u.iocb_cmd.u.ctarg.req || !sp->u.iocb_cmd.u.ctarg.rsp) {
+-              ql_log(ql_log_warn, vha, 0xffff,
+-                  "%s: req %p rsp %p are not setup\n",
+-                  __func__, sp->u.iocb_cmd.u.ctarg.req,
+-                  sp->u.iocb_cmd.u.ctarg.rsp);
+-              spin_lock_irqsave(&vha->work_lock, flags);
+-              vha->scan.scan_flags &= ~SF_SCANNING;
+-              spin_unlock_irqrestore(&vha->work_lock, flags);
+-              WARN_ON(1);
+-              set_bit(LOCAL_LOOP_UPDATE, &vha->dpc_flags);
+-              set_bit(LOOP_RESYNC_NEEDED, &vha->dpc_flags);
+-              goto done_free_sp;
+-      }
+-
+-      ql_dbg(ql_dbg_disc, vha, 0xfffff,
+-          "%s: FC4Type %x, CT-PASSTHRU %s command ctarg rsp size %d, ctarg 
req size %d\n",
+-          __func__, fc4_type, sp->name, sp->u.iocb_cmd.u.ctarg.rsp_size,
+-           sp->u.iocb_cmd.u.ctarg.req_size);
+-
+-      sp->type = SRB_CT_PTHRU_CMD;
+-      sp->name = "gnnft";
+-      sp->gen1 = vha->hw->base_qpair->chip_reset;
+-      sp->gen2 = fc4_type;
+-      qla2x00_init_async_sp(sp, qla2x00_get_async_timeout(vha) + 2,
+-                            qla2x00_async_gpnft_gnnft_sp_done);
+-
+-      memset(sp->u.iocb_cmd.u.ctarg.rsp, 0, sp->u.iocb_cmd.u.ctarg.rsp_size);
+-      memset(sp->u.iocb_cmd.u.ctarg.req, 0, sp->u.iocb_cmd.u.ctarg.req_size);
+-
+-      ct_sns = (struct ct_sns_pkt *)sp->u.iocb_cmd.u.ctarg.req;
+-      /* CT_IU preamble  */
+-      ct_req = qla2x00_prep_ct_req(ct_sns, GNN_FT_CMD,
+-          sp->u.iocb_cmd.u.ctarg.rsp_size);
+-
+-      /* GPN_FT req */
+-      ct_req->req.gpn_ft.port_type = fc4_type;
+-
+-      sp->u.iocb_cmd.u.ctarg.req_size = GNN_FT_REQ_SIZE;
+-      sp->u.iocb_cmd.u.ctarg.nport_handle = NPH_SNS;
+-
+-      ql_dbg(ql_dbg_disc, vha, 0xffff,
+-          "Async-%s hdl=%x FC4Type %x.\n", sp->name,
+-          sp->handle, ct_req->req.gpn_ft.port_type);
+-
+-      rval = qla2x00_start_sp(sp);
+-      if (rval != QLA_SUCCESS) {
+-              goto done_free_sp;
+-      }
+-
+-      return rval;
+-
+-done_free_sp:
+-      if (sp->u.iocb_cmd.u.ctarg.req) {
+-              dma_free_coherent(&vha->hw->pdev->dev,
+-                  sp->u.iocb_cmd.u.ctarg.req_allocated_size,
+-                  sp->u.iocb_cmd.u.ctarg.req,
+-                  sp->u.iocb_cmd.u.ctarg.req_dma);
+-              sp->u.iocb_cmd.u.ctarg.req = NULL;
+-      }
+-      if (sp->u.iocb_cmd.u.ctarg.rsp) {
+-              dma_free_coherent(&vha->hw->pdev->dev,
+-                  sp->u.iocb_cmd.u.ctarg.rsp_allocated_size,
+-                  sp->u.iocb_cmd.u.ctarg.rsp,
+-                  sp->u.iocb_cmd.u.ctarg.rsp_dma);
+-              sp->u.iocb_cmd.u.ctarg.rsp = NULL;
+-      }
+-      /* ref: INIT */
+-      kref_put(&sp->cmd_kref, qla2x00_sp_release);
+-
+-      spin_lock_irqsave(&vha->work_lock, flags);
+-      vha->scan.scan_flags &= ~SF_SCANNING;
+-      if (vha->scan.scan_flags == 0) {
+-              ql_dbg(ql_dbg_disc, vha, 0xffff,
+-                  "%s: schedule\n", __func__);
+-              vha->scan.scan_flags |= SF_QUEUED;
+-              schedule_delayed_work(&vha->scan.scan_work, 5);
+-      }
+-      spin_unlock_irqrestore(&vha->work_lock, flags);
+-
+-
+-      return rval;
+-} /* GNNFT */
+-
+-void qla24xx_async_gpnft_done(scsi_qla_host_t *vha, srb_t *sp)
+-{
+-      ql_dbg(ql_dbg_disc + ql_dbg_verbose, vha, 0xffff,
+-          "%s enter\n", __func__);
+-      qla24xx_async_gnnft(vha, sp, sp->gen2);
+-}
+-
+ /* Get WWPN list for certain fc4_type */
+-int qla24xx_async_gpnft(scsi_qla_host_t *vha, u8 fc4_type, srb_t *sp)
++int qla_fab_async_scan(scsi_qla_host_t *vha, srb_t *sp)
+ {
+       int rval = QLA_FUNCTION_FAILED;
+       struct ct_sns_req       *ct_req;
+       struct ct_sns_pkt *ct_sns;
+-      u32 rspsz;
++      u32 rspsz = 0;
+       unsigned long flags;
+ 
+-      ql_dbg(ql_dbg_disc + ql_dbg_verbose, vha, 0xffff,
++      ql_dbg(ql_dbg_disc + ql_dbg_verbose, vha, 0x200c,
+           "%s enter\n", __func__);
+ 
+       if (!vha->flags.online)
+@@ -4057,22 +3920,21 @@ int qla24xx_async_gpnft(scsi_qla_host_t *vha, u8 
fc4_type, srb_t *sp)
+       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,
+-                  "%s: scan active\n", __func__);
+-              return rval;
++              ql_dbg(ql_dbg_disc + ql_dbg_verbose, vha, 0x2012,
++                  "%s: scan active for sp:%p\n", __func__, sp);
++              goto done_free_sp;
+       }
+       vha->scan.scan_flags |= SF_SCANNING;
++      if (!sp)
++              vha->scan.step = FAB_SCAN_START;
++
+       spin_unlock_irqrestore(&vha->work_lock, flags);
+ 
+-      if (fc4_type == FC4_TYPE_FCP_SCSI) {
+-              ql_dbg(ql_dbg_disc + ql_dbg_verbose, vha, 0xffff,
++      switch (vha->scan.step) {
++      case FAB_SCAN_START:
++              ql_dbg(ql_dbg_disc + ql_dbg_verbose, vha, 0x2018,
+                   "%s: Performing FCP Scan\n", __func__);
+ 
+-              if (sp) {
+-                      /* ref: INIT */
+-                      kref_put(&sp->cmd_kref, qla2x00_sp_release);
+-              }
+-
+               /* ref: INIT */
+               sp = qla2x00_get_sp(vha, NULL, GFP_KERNEL);
+               if (!sp) {
+@@ -4088,7 +3950,7 @@ int qla24xx_async_gpnft(scsi_qla_host_t *vha, u8 
fc4_type, srb_t *sp)
+                                                               GFP_KERNEL);
+               sp->u.iocb_cmd.u.ctarg.req_allocated_size = sizeof(struct 
ct_sns_pkt);
+               if (!sp->u.iocb_cmd.u.ctarg.req) {
+-                      ql_log(ql_log_warn, vha, 0xffff,
++                      ql_log(ql_log_warn, vha, 0x201a,
+                           "Failed to allocate ct_sns request.\n");
+                       spin_lock_irqsave(&vha->work_lock, flags);
+                       vha->scan.scan_flags &= ~SF_SCANNING;
+@@ -4096,7 +3958,6 @@ int qla24xx_async_gpnft(scsi_qla_host_t *vha, u8 
fc4_type, srb_t *sp)
+                       qla2x00_rel_sp(sp);
+                       return rval;
+               }
+-              sp->u.iocb_cmd.u.ctarg.req_size = GPN_FT_REQ_SIZE;
+ 
+               rspsz = sizeof(struct ct_sns_gpnft_rsp) +
+                       ((vha->hw->max_fibre_devices - 1) *
+@@ -4108,7 +3969,7 @@ int qla24xx_async_gpnft(scsi_qla_host_t *vha, u8 
fc4_type, srb_t *sp)
+                                                               GFP_KERNEL);
+               sp->u.iocb_cmd.u.ctarg.rsp_allocated_size = rspsz;
+               if (!sp->u.iocb_cmd.u.ctarg.rsp) {
+-                      ql_log(ql_log_warn, vha, 0xffff,
++                      ql_log(ql_log_warn, vha, 0x201b,
+                           "Failed to allocate ct_sns request.\n");
+                       spin_lock_irqsave(&vha->work_lock, flags);
+                       vha->scan.scan_flags &= ~SF_SCANNING;
+@@ -4128,35 +3989,95 @@ int qla24xx_async_gpnft(scsi_qla_host_t *vha, u8 
fc4_type, srb_t *sp)
+                   "%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) {
+@@ -4166,28 +4087,30 @@ int qla24xx_async_gpnft(scsi_qla_host_t *vha, u8 
fc4_type, srb_t *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;
+-      }
++      if (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);
++              /* 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 + 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 +4121,15 @@ done_free_sp:
+       return rval;
+ }
+ 
++void qla_fab_scan_start(struct scsi_qla_host *vha)
++{
++      int rval;
++
++      rval = qla_fab_async_scan(vha, NULL);
++      if (rval)
++              set_bit(LOOP_RESYNC_NEEDED, &vha->dpc_flags);
++}
++
+ void qla_scan_work_fn(struct work_struct *work)
+ {
+       struct fab_scan *s = container_of(to_delayed_work(work),
+@@ -4216,116 +4148,6 @@ void qla_scan_work_fn(struct work_struct *work)
+       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)
+ {
+diff --git a/drivers/scsi/qla2xxx/qla_init.c b/drivers/scsi/qla2xxx/qla_init.c
+index 5f3593680c9532..177b71fae2f89a 100644
+--- a/drivers/scsi/qla2xxx/qla_init.c
++++ b/drivers/scsi/qla2xxx/qla_init.c
+@@ -1725,12 +1725,7 @@ int qla24xx_fcport_handle_login(struct scsi_qla_host 
*vha, fc_port_t *fcport)
+                       }
+                       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);
+@@ -2473,8 +2468,23 @@ qla24xx_handle_plogi_done_event(struct scsi_qla_host 
*vha, struct event_arg *ea)
+           ea->sp->gen1, fcport->rscn_gen,
+           ea->data[0], ea->data[1], ea->iop[0], ea->iop[1]);
+ 
+-      if ((fcport->fw_login_state == DSC_LS_PLOGI_PEND) ||
+-          (fcport->fw_login_state == DSC_LS_PRLI_PEND)) {
++      if (fcport->fw_login_state == DSC_LS_PLOGI_PEND) {
++              ql_dbg(ql_dbg_disc, vha, 0x20ea,
++                  "%s %d %8phC Remote is trying to login\n",
++                  __func__, __LINE__, fcport->port_name);
++              /*
++               * If we get here, there is port thats already logged in,
++               * but it's state has not moved ahead. Recheck with FW on
++               * what state it is in and proceed ahead
++               */
++              if (!N2N_TOPO(vha->hw)) {
++                      fcport->fw_login_state = DSC_LS_PRLI_COMP;
++                      qla24xx_post_gpdb_work(vha, fcport, 0);
++              }
++              return;
++      }
++
++      if (fcport->fw_login_state == DSC_LS_PRLI_PEND) {
+               ql_dbg(ql_dbg_disc, vha, 0x20ea,
+                   "%s %d %8phC Remote is trying to login\n",
+                   __func__, __LINE__, fcport->port_name);
+@@ -6447,10 +6457,7 @@ qla2x00_configure_fabric(scsi_qla_host_t *vha)
+               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;
+diff --git a/drivers/scsi/qla2xxx/qla_isr.c b/drivers/scsi/qla2xxx/qla_isr.c
+index 1459ae380389a0..7dcd2c8577db03 100644
+--- a/drivers/scsi/qla2xxx/qla_isr.c
++++ b/drivers/scsi/qla2xxx/qla_isr.c
+@@ -49,11 +49,11 @@ qla27xx_process_purex_fpin(struct scsi_qla_host *vha, 
struct purex_item *item)
+ }
+ 
+ const char *const port_state_str[] = {
+-      "Unknown",
+-      "UNCONFIGURED",
+-      "DEAD",
+-      "LOST",
+-      "ONLINE"
++      [FCS_UNKNOWN]           = "Unknown",
++      [FCS_UNCONFIGURED]      = "UNCONFIGURED",
++      [FCS_DEVICE_DEAD]       = "DEAD",
++      [FCS_DEVICE_LOST]       = "LOST",
++      [FCS_ONLINE]            = "ONLINE"
+ };
+ 
+ static void
+@@ -1524,13 +1524,28 @@ skip_rio:
+ 
+                       /* Port logout */
+                       fcport = qla2x00_find_fcport_by_loopid(vha, mb[1]);
+-                      if (!fcport)
++                      if (!fcport) {
++                              ql_dbg(ql_dbg_async, vha, 0x5011,
++                                      "Could not find fcport:%04x %04x 
%04x\n",
++                                      mb[1], mb[2], mb[3]);
+                               break;
+-                      if (atomic_read(&fcport->state) != FCS_ONLINE)
++                      }
++
++                      if (atomic_read(&fcport->state) != FCS_ONLINE) {
++                              ql_dbg(ql_dbg_async, vha, 0x5012,
++                                      "Port state is not online State:0x%x 
\n",
++                                      atomic_read(&fcport->state));
++                              ql_dbg(ql_dbg_async, vha, 0x5012,
++                                      "Scheduling session for deletion \n");
++                              fcport->logout_on_delete = 0;
++                              qlt_schedule_sess_for_deletion(fcport);
+                               break;
++                      }
++
+                       ql_dbg(ql_dbg_async, vha, 0x508a,
+                           "Marking port lost loopid=%04x portid=%06x.\n",
+                           fcport->loop_id, fcport->d_id.b24);
++
+                       if (qla_ini_mode_enabled(vha)) {
+                               fcport->logout_on_delete = 0;
+                               qlt_schedule_sess_for_deletion(fcport);
+diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c
+index 2b6b5eb66bc7ec..fe53cb84c97ea0 100644
+--- a/drivers/scsi/qla2xxx/qla_os.c
++++ b/drivers/scsi/qla2xxx/qla_os.c
+@@ -1216,7 +1216,8 @@ qla2x00_wait_for_hba_ready(scsi_qla_host_t *vha)
+       while ((qla2x00_reset_active(vha) || ha->dpc_active ||
+               ha->flags.mbox_busy) ||
+              test_bit(FX00_RESET_RECOVERY, &vha->dpc_flags) ||
+-             test_bit(FX00_TARGET_SCAN, &vha->dpc_flags)) {
++             test_bit(FX00_TARGET_SCAN, &vha->dpc_flags) ||
++             (vha->scan.scan_flags & SF_SCANNING)) {
+               if (test_bit(UNLOADING, &base_vha->dpc_flags))
+                       break;
+               msleep(1000);
+@@ -5489,18 +5490,11 @@ qla2x00_do_work(struct scsi_qla_host *vha)
+                       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);
+-                      break;
+-              case QLA_EVT_GNNID:
+-                      qla24xx_async_gnnid(vha, e->u.fcport.fcport);
++              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/drivers/usb/serial/option.c b/drivers/usb/serial/option.c
+index 506a26c12e1ae8..12be1ed6a56c1e 100644
+--- a/drivers/usb/serial/option.c
++++ b/drivers/usb/serial/option.c
+@@ -1401,12 +1401,16 @@ static const struct usb_device_id option_ids[] = {
+         .driver_info = NCTRL(0) | RSVD(1) },
+       { USB_DEVICE_INTERFACE_CLASS(TELIT_VENDOR_ID, 0x10a0, 0xff),    /* 
Telit FN20C04 (rmnet) */
+         .driver_info = RSVD(0) | NCTRL(3) },
++      { USB_DEVICE_INTERFACE_CLASS(TELIT_VENDOR_ID, 0x10a1, 0xff),    /* 
Telit FN20C04 (RNDIS) */
++        .driver_info = NCTRL(4) },
+       { USB_DEVICE_INTERFACE_CLASS(TELIT_VENDOR_ID, 0x10a2, 0xff),    /* 
Telit FN920C04 (MBIM) */
+         .driver_info = NCTRL(4) },
+       { USB_DEVICE_INTERFACE_CLASS(TELIT_VENDOR_ID, 0x10a3, 0xff),    /* 
Telit FN920C04 (ECM) */
+         .driver_info = NCTRL(4) },
+       { USB_DEVICE_INTERFACE_CLASS(TELIT_VENDOR_ID, 0x10a4, 0xff),    /* 
Telit FN20C04 (rmnet) */
+         .driver_info = RSVD(0) | NCTRL(3) },
++      { USB_DEVICE_INTERFACE_CLASS(TELIT_VENDOR_ID, 0x10a6, 0xff),    /* 
Telit FN920C04 (RNDIS) */
++        .driver_info = NCTRL(4) },
+       { USB_DEVICE_INTERFACE_CLASS(TELIT_VENDOR_ID, 0x10a7, 0xff),    /* 
Telit FN920C04 (MBIM) */
+         .driver_info = NCTRL(4) },
+       { USB_DEVICE_INTERFACE_CLASS(TELIT_VENDOR_ID, 0x10a8, 0xff),    /* 
Telit FN920C04 (ECM) */
+@@ -1415,6 +1419,8 @@ static const struct usb_device_id option_ids[] = {
+         .driver_info = RSVD(0) | NCTRL(2) | RSVD(3) | RSVD(4) },
+       { USB_DEVICE_INTERFACE_CLASS(TELIT_VENDOR_ID, 0x10aa, 0xff),    /* 
Telit FN920C04 (MBIM) */
+         .driver_info = NCTRL(3) | RSVD(4) | RSVD(5) },
++      { USB_DEVICE_INTERFACE_CLASS(TELIT_VENDOR_ID, 0x10ab, 0xff),    /* 
Telit FN920C04 (RNDIS) */
++        .driver_info = NCTRL(3) | RSVD(4) | RSVD(5) },
+       { USB_DEVICE_AND_INTERFACE_INFO(TELIT_VENDOR_ID, 0x10b0, 0xff, 0xff, 
0x30),     /* Telit FE990B (rmnet) */
+         .driver_info = NCTRL(5) },
+       { USB_DEVICE_AND_INTERFACE_INFO(TELIT_VENDOR_ID, 0x10b0, 0xff, 0xff, 
0x40) },
+diff --git a/drivers/video/fbdev/riva/riva_hw.c 
b/drivers/video/fbdev/riva/riva_hw.c
+index 8b829b7200642f..f292079566cfca 100644
+--- a/drivers/video/fbdev/riva/riva_hw.c
++++ b/drivers/video/fbdev/riva/riva_hw.c
+@@ -436,6 +436,9 @@ static char nv3_arb(nv3_fifo_info * res_info, 
nv3_sim_state * state,  nv3_arb_in
+     vmisses = 2;
+     eburst_size = state->memory_width * 1;
+     mburst_size = 32;
++    if (!state->mclk_khz)
++      return (0);
++
+     gns = 1000000 * (gmisses*state->mem_page_miss + 
state->mem_latency)/state->mclk_khz;
+     ainfo->by_gfacc = gns*ainfo->gdrain_rate/1000000;
+     ainfo->wcmocc = 0;
+diff --git a/drivers/video/fbdev/smscufx.c b/drivers/video/fbdev/smscufx.c
+index 14e4e106d26bc6..071448eba24650 100644
+--- a/drivers/video/fbdev/smscufx.c
++++ b/drivers/video/fbdev/smscufx.c
+@@ -986,7 +986,6 @@ static int ufx_ops_ioctl(struct fb_info *info, unsigned 
int cmd,
+                        unsigned long arg)
+ {
+       struct ufx_data *dev = info->par;
+-      struct dloarea *area = NULL;
+ 
+       if (!atomic_read(&dev->usb_active))
+               return 0;
+@@ -1001,6 +1000,10 @@ static int ufx_ops_ioctl(struct fb_info *info, unsigned 
int cmd,
+ 
+       /* TODO: Help propose a standard fb.h ioctl to report mmap damage */
+       if (cmd == UFX_IOCTL_REPORT_DAMAGE) {
++              struct dloarea *area __free(kfree) = kmalloc(sizeof(*area), 
GFP_KERNEL);
++              if (!area)
++                      return -ENOMEM;
++
+               /* If we have a damage-aware client, turn fb_defio "off"
+                * To avoid perf imact of unnecessary page fault handling.
+                * Done by resetting the delay for this fb_info to a very
+@@ -1010,7 +1013,8 @@ static int ufx_ops_ioctl(struct fb_info *info, unsigned 
int cmd,
+               if (info->fbdefio)
+                       info->fbdefio->delay = UFX_DEFIO_WRITE_DISABLE;
+ 
+-              area = (struct dloarea *)arg;
++              if (copy_from_user(area, (u8 __user *)arg, sizeof(*area)))
++                      return -EFAULT;
+ 
+               if (area->x < 0)
+                       area->x = 0;
+diff --git a/fs/btrfs/block-group.c b/fs/btrfs/block-group.c
+index 614917cac0e7e2..4bc7a5e63b86d9 100644
+--- a/fs/btrfs/block-group.c
++++ b/fs/btrfs/block-group.c
+@@ -3699,7 +3699,7 @@ int btrfs_chunk_alloc(struct btrfs_trans_handle *trans, 
u64 flags,
+                       mutex_unlock(&fs_info->chunk_mutex);
+               } else {
+                       /* Proceed with allocation */
+-                      space_info->chunk_alloc = 1;
++                      space_info->chunk_alloc = true;
+                       wait_for_alloc = false;
+                       spin_unlock(&space_info->lock);
+               }
+@@ -3735,7 +3735,7 @@ int btrfs_chunk_alloc(struct btrfs_trans_handle *trans, 
u64 flags,
+       spin_lock(&space_info->lock);
+       if (ret < 0) {
+               if (ret == -ENOSPC)
+-                      space_info->full = 1;
++                      space_info->full = true;
+               else
+                       goto out;
+       } else {
+@@ -3745,7 +3745,7 @@ int btrfs_chunk_alloc(struct btrfs_trans_handle *trans, 
u64 flags,
+ 
+       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);
+ 
+diff --git a/fs/btrfs/space-info.c b/fs/btrfs/space-info.c
+index 5ed66a794e577a..9482f34ebf8457 100644
+--- a/fs/btrfs/space-info.c
++++ b/fs/btrfs/space-info.c
+@@ -178,7 +178,7 @@ void btrfs_clear_space_info_full(struct btrfs_fs_info 
*info)
+       struct btrfs_space_info *found;
+ 
+       list_for_each_entry(found, head, list)
+-              found->full = 0;
++              found->full = false;
+ }
+ 
+ static int create_space_info(struct btrfs_fs_info *info, u64 flags)
+@@ -271,7 +271,7 @@ void btrfs_update_space_info(struct btrfs_fs_info *info, 
u64 flags,
+       found->bytes_readonly += bytes_readonly;
+       found->bytes_zone_unusable += bytes_zone_unusable;
+       if (total_bytes > 0)
+-              found->full = 0;
++              found->full = false;
+       btrfs_try_granting_tickets(info, found);
+       spin_unlock(&found->lock);
+       *space_info = found;
+@@ -941,7 +941,7 @@ static void btrfs_async_reclaim_metadata_space(struct 
work_struct *work)
+       spin_lock(&space_info->lock);
+       to_reclaim = btrfs_calc_reclaim_metadata_size(fs_info, space_info);
+       if (!to_reclaim) {
+-              space_info->flush = 0;
++              space_info->flush = false;
+               spin_unlock(&space_info->lock);
+               return;
+       }
+@@ -953,7 +953,7 @@ static void btrfs_async_reclaim_metadata_space(struct 
work_struct *work)
+               flush_space(fs_info, space_info, to_reclaim, flush_state, 
false);
+               spin_lock(&space_info->lock);
+               if (list_empty(&space_info->tickets)) {
+-                      space_info->flush = 0;
++                      space_info->flush = false;
+                       spin_unlock(&space_info->lock);
+                       return;
+               }
+@@ -996,7 +996,7 @@ static void btrfs_async_reclaim_metadata_space(struct 
work_struct *work)
+                                       flush_state = FLUSH_DELAYED_ITEMS_NR;
+                                       commit_cycles--;
+                               } else {
+-                                      space_info->flush = 0;
++                                      space_info->flush = false;
+                               }
+                       } else {
+                               flush_state = FLUSH_DELAYED_ITEMS_NR;
+@@ -1158,7 +1158,7 @@ static void btrfs_async_reclaim_data_space(struct 
work_struct *work)
+ 
+       spin_lock(&space_info->lock);
+       if (list_empty(&space_info->tickets)) {
+-              space_info->flush = 0;
++              space_info->flush = false;
+               spin_unlock(&space_info->lock);
+               return;
+       }
+@@ -1169,7 +1169,7 @@ static void btrfs_async_reclaim_data_space(struct 
work_struct *work)
+               flush_space(fs_info, space_info, U64_MAX, ALLOC_CHUNK_FORCE, 
false);
+               spin_lock(&space_info->lock);
+               if (list_empty(&space_info->tickets)) {
+-                      space_info->flush = 0;
++                      space_info->flush = false;
+                       spin_unlock(&space_info->lock);
+                       return;
+               }
+@@ -1182,7 +1182,7 @@ static void btrfs_async_reclaim_data_space(struct 
work_struct *work)
+                           data_flush_states[flush_state], false);
+               spin_lock(&space_info->lock);
+               if (list_empty(&space_info->tickets)) {
+-                      space_info->flush = 0;
++                      space_info->flush = false;
+                       spin_unlock(&space_info->lock);
+                       return;
+               }
+@@ -1199,7 +1199,7 @@ static void btrfs_async_reclaim_data_space(struct 
work_struct *work)
+                               if (maybe_fail_all_tickets(fs_info, space_info))
+                                       flush_state = 0;
+                               else
+-                                      space_info->flush = 0;
++                                      space_info->flush = false;
+                       } else {
+                               flush_state = 0;
+                       }
+@@ -1510,7 +1510,7 @@ static int __reserve_bytes(struct btrfs_fs_info *fs_info,
+                                */
+                               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,
+diff --git a/fs/btrfs/space-info.h b/fs/btrfs/space-info.h
+index cb5056472e798d..9359de73250dbb 100644
+--- a/fs/btrfs/space-info.h
++++ b/fs/btrfs/space-info.h
+@@ -28,11 +28,11 @@ struct btrfs_space_info {
+                                  flushing. The value is >> clamp, so turns
+                                  out to be a 2^clamp divisor. */
+ 
+-      unsigned int full:1;    /* indicates that we cannot allocate any more
++      bool full;              /* indicates that we cannot allocate any more
+                                  chunks for this space */
+-      unsigned int chunk_alloc:1;     /* set if we are allocating a chunk */
++      bool chunk_alloc;       /* set if we are allocating a chunk */
+ 
+-      unsigned int flush:1;           /* set if we are trying to make space */
++      bool flush;             /* set if we are trying to make space */
+ 
+       unsigned int force_alloc;       /* set if we need to force a chunk
+                                          alloc for this space */
+diff --git a/fs/cifs/cifs_dfs_ref.c b/fs/cifs/cifs_dfs_ref.c
+index 020e71fe1454ed..2c6dee3f097b80 100644
+--- a/fs/cifs/cifs_dfs_ref.c
++++ b/fs/cifs/cifs_dfs_ref.c
+@@ -258,6 +258,21 @@ compose_mount_options_err:
+       goto compose_mount_options_out;
+ }
+ 
++static void fs_context_set_ids(struct smb3_fs_context *ctx)
++{
++      kuid_t uid = current_fsuid();
++      kgid_t gid = current_fsgid();
++
++      if (ctx->multiuser) {
++              if (!ctx->uid_specified)
++                      ctx->linux_uid = uid;
++              if (!ctx->gid_specified)
++                      ctx->linux_gid = gid;
++      }
++      if (!ctx->cruid_specified)
++              ctx->cred_uid = uid;
++}
++
+ /*
+  * Create a vfsmount that we can automount
+  */
+@@ -309,6 +324,7 @@ static struct vfsmount *cifs_dfs_do_automount(struct path 
*path)
+       tmp.source = full_path;
+       tmp.UNC = tmp.prepath = NULL;
+ 
++      fs_context_set_ids(&tmp);
+       rc = smb3_fs_context_dup(ctx, &tmp);
+       if (rc) {
+               mnt = ERR_PTR(rc);
+diff --git a/fs/f2fs/data.c b/fs/f2fs/data.c
+index 6798efda7d0d33..887e286d2c3290 100644
+--- a/fs/f2fs/data.c
++++ b/fs/f2fs/data.c
+@@ -341,14 +341,20 @@ static void f2fs_write_end_io(struct bio *bio)
+                                       page->index != nid_of_node(page));
+ 
+               dec_page_count(sbi, type);
++
++              /*
++               * we should access sbi before end_page_writeback() to
++               * avoid racing w/ kill_f2fs_super()
++               */
++              if (type == F2FS_WB_CP_DATA && !get_pages(sbi, type) &&
++                              wq_has_sleeper(&sbi->cp_wait))
++                      wake_up(&sbi->cp_wait);
++
+               if (f2fs_in_warm_node_list(sbi, page))
+                       f2fs_del_fsync_node_entry(sbi, page);
+               clear_page_private_gcing(page);
+               end_page_writeback(page);
+       }
+-      if (!get_pages(sbi, F2FS_WB_CP_DATA) &&
+-                              wq_has_sleeper(&sbi->cp_wait))
+-              wake_up(&sbi->cp_wait);
+ 
+       bio_put(bio);
+ }
+diff --git a/fs/f2fs/sysfs.c b/fs/f2fs/sysfs.c
+index 30ff2c08772660..cb13d47725432c 100644
+--- a/fs/f2fs/sysfs.c
++++ b/fs/f2fs/sysfs.c
+@@ -48,6 +48,7 @@ struct f2fs_attr {
+                        const char *, size_t);
+       int struct_type;
+       int offset;
++      int size;
+       int id;
+ };
+ 
+@@ -249,11 +250,30 @@ static ssize_t main_blkaddr_show(struct f2fs_attr *a,
+                       (unsigned long long)MAIN_BLKADDR(sbi));
+ }
+ 
++static ssize_t __sbi_show_value(struct f2fs_attr *a,
++              struct f2fs_sb_info *sbi, char *buf,
++              unsigned char *value)
++{
++      switch (a->size) {
++      case 1:
++              return sysfs_emit(buf, "%u\n", *(u8 *)value);
++      case 2:
++              return sysfs_emit(buf, "%u\n", *(u16 *)value);
++      case 4:
++              return sysfs_emit(buf, "%u\n", *(u32 *)value);
++      case 8:
++              return sysfs_emit(buf, "%llu\n", *(u64 *)value);
++      default:
++              f2fs_bug_on(sbi, 1);
++              return sysfs_emit(buf,
++                              "show sysfs node value with wrong type\n");
++      }
++}
++
+ static ssize_t f2fs_sbi_show(struct f2fs_attr *a,
+                       struct f2fs_sb_info *sbi, char *buf)
+ {
+       unsigned char *ptr = NULL;
+-      unsigned int *ui;
+ 
+       ptr = __struct_ptr(sbi, a->struct_type);
+       if (!ptr)
+@@ -316,9 +336,30 @@ static ssize_t f2fs_sbi_show(struct f2fs_attr *a,
+                       sbi->gc_reclaimed_segs[sbi->gc_segment_mode]);
+       }
+ 
+-      ui = (unsigned int *)(ptr + a->offset);
++      return __sbi_show_value(a, sbi, buf, ptr + a->offset);
++}
+ 
+-      return sprintf(buf, "%u\n", *ui);
++static void __sbi_store_value(struct f2fs_attr *a,
++                      struct f2fs_sb_info *sbi,
++                      unsigned char *ui, unsigned long value)
++{
++      switch (a->size) {
++      case 1:
++              *(u8 *)ui = value;
++              break;
++      case 2:
++              *(u16 *)ui = value;
++              break;
++      case 4:
++              *(u32 *)ui = value;
++              break;
++      case 8:
++              *(u64 *)ui = value;
++              break;
++      default:
++              f2fs_bug_on(sbi, 1);
++              f2fs_err(sbi, "store sysfs node value with wrong type");
++      }
+ }
+ 
+ static ssize_t __sbi_store(struct f2fs_attr *a,
+@@ -559,7 +600,7 @@ out:
+               return count;
+       }
+ 
+-      *ui = (unsigned int)t;
++      __sbi_store_value(a, sbi, ptr + a->offset, t);
+ 
+       return count;
+ }
+@@ -655,19 +696,28 @@ static struct f2fs_attr f2fs_attr_sb_##_name = {         
\
+       .id     = F2FS_FEATURE_##_feat,                         \
+ }
+ 
+-#define F2FS_ATTR_OFFSET(_struct_type, _name, _mode, _show, _store, _offset) \
++#define F2FS_ATTR_OFFSET(_struct_type, _name, _mode, _show, _store, _offset, 
_size) \
+ static struct f2fs_attr f2fs_attr_##_name = {                 \
+       .attr = {.name = __stringify(_name), .mode = _mode },   \
+       .show   = _show,                                        \
+       .store  = _store,                                       \
+       .struct_type = _struct_type,                            \
+-      .offset = _offset                                       \
++      .offset = _offset,                                      \
++      .size = _size                                           \
+ }
+ 
++#define F2FS_RO_ATTR(struct_type, struct_name, name, elname)  \
++      F2FS_ATTR_OFFSET(struct_type, name, 0444,               \
++              f2fs_sbi_show, NULL,                            \
++              offsetof(struct struct_name, elname),           \
++              sizeof_field(struct struct_name, elname))
++
++
+ #define F2FS_RW_ATTR(struct_type, struct_name, name, elname)  \
+       F2FS_ATTR_OFFSET(struct_type, name, 0644,               \
+               f2fs_sbi_show, f2fs_sbi_store,                  \
+-              offsetof(struct struct_name, elname))
++              offsetof(struct struct_name, elname),           \
++              sizeof_field(struct struct_name, elname))
+ 
+ #define F2FS_GENERAL_RO_ATTR(name) \
+ static struct f2fs_attr f2fs_attr_##name = __ATTR(name, 0444, name##_show, 
NULL)
+@@ -678,6 +728,7 @@ static struct f2fs_attr f2fs_attr_##_name = {              
        \
+       .show = f2fs_sbi_show,                                  \
+       .struct_type = _struct_type,                            \
+       .offset = offsetof(struct _struct_name, _elname),       \
++      .size = sizeof_field(struct _struct_name, _elname),     \
+ }
+ 
+ F2FS_RW_ATTR(GC_THREAD, f2fs_gc_kthread, gc_urgent_sleep_time,
+diff --git a/fs/ksmbd/transport_tcp.c b/fs/ksmbd/transport_tcp.c
+index 176295137045a8..7ef201b7ddb57b 100644
+--- a/fs/ksmbd/transport_tcp.c
++++ b/fs/ksmbd/transport_tcp.c
+@@ -41,6 +41,7 @@ static struct ksmbd_transport_ops ksmbd_tcp_transport_ops;
+ 
+ static void tcp_stop_kthread(struct task_struct *kthread);
+ static struct interface *alloc_iface(char *ifname);
++static void ksmbd_tcp_disconnect(struct ksmbd_transport *t);
+ 
+ #define KSMBD_TRANS(t)        (&(t)->transport)
+ #define TCP_TRANS(t)  ((struct tcp_transport *)container_of(t, \
+@@ -207,7 +208,7 @@ static int ksmbd_tcp_new_connection(struct socket 
*client_sk)
+       if (IS_ERR(handler)) {
+               pr_err("cannot start conn thread\n");
+               rc = PTR_ERR(handler);
+-              free_transport(t);
++              ksmbd_tcp_disconnect(KSMBD_TRANS(t));
+       }
+       return rc;
+ 
+diff --git a/fs/nilfs2/sufile.c b/fs/nilfs2/sufile.c
+index 23b4b8863e7f96..69b8baf86632b4 100644
+--- a/fs/nilfs2/sufile.c
++++ b/fs/nilfs2/sufile.c
+@@ -1091,6 +1091,9 @@ int nilfs_sufile_trim_fs(struct inode *sufile, struct 
fstrim_range *range)
+       else
+               end_block = start_block + len - 1;
+ 
++      if (end_block < nilfs->ns_first_data_block)
++              goto out;
++
+       segnum = nilfs_get_segnum_of_block(nilfs, start_block);
+       segnum_end = nilfs_get_segnum_of_block(nilfs, end_block);
+ 
+@@ -1188,6 +1191,7 @@ int nilfs_sufile_trim_fs(struct inode *sufile, struct 
fstrim_range *range)
+ out_sem:
+       up_read(&NILFS_MDT(sufile)->mi_sem);
+ 
++out:
+       range->len = ndiscarded << nilfs->ns_blocksize_bits;
+       return ret;
+ }
+diff --git a/fs/romfs/super.c b/fs/romfs/super.c
+index 259f684d9236e7..6f31e720c9561f 100644
+--- a/fs/romfs/super.c
++++ b/fs/romfs/super.c
+@@ -467,7 +467,10 @@ static int romfs_fill_super(struct super_block *sb, 
struct fs_context *fc)
+ 
+ #ifdef CONFIG_BLOCK
+       if (!sb->s_mtd) {
+-              sb_set_blocksize(sb, ROMBSIZE);
++              if (!sb_set_blocksize(sb, ROMBSIZE)) {
++                      errorf(fc, "romfs: unable to set blocksize\n");
++                      return -EINVAL;
++              }
+       } else {
+               sb->s_blocksize = ROMBSIZE;
+               sb->s_blocksize_bits = blksize_bits(ROMBSIZE);
+diff --git a/net/dsa/dsa2.c b/net/dsa/dsa2.c
+index bf384b30ec0a83..a6b6bcffc69cea 100644
+--- a/net/dsa/dsa2.c
++++ b/net/dsa/dsa2.c
+@@ -1079,6 +1079,16 @@ static void dsa_tree_teardown_lags(struct 
dsa_switch_tree *dst)
+       kfree(dst->lags);
+ }
+ 
++static void dsa_tree_teardown_routing_table(struct dsa_switch_tree *dst)
++{
++      struct dsa_link *dl, *next;
++
++      list_for_each_entry_safe(dl, next, &dst->rtable, list) {
++              list_del(&dl->list);
++              kfree(dl);
++      }
++}
++
+ static int dsa_tree_setup(struct dsa_switch_tree *dst)
+ {
+       bool complete;
+@@ -1096,7 +1106,7 @@ static int dsa_tree_setup(struct dsa_switch_tree *dst)
+ 
+       err = dsa_tree_setup_cpu_ports(dst);
+       if (err)
+-              return err;
++              goto teardown_rtable;
+ 
+       err = dsa_tree_setup_switches(dst);
+       if (err)
+@@ -1123,14 +1133,14 @@ teardown_switches:
+       dsa_tree_teardown_switches(dst);
+ teardown_cpu_ports:
+       dsa_tree_teardown_cpu_ports(dst);
++teardown_rtable:
++      dsa_tree_teardown_routing_table(dst);
+ 
+       return err;
+ }
+ 
+ static void dsa_tree_teardown(struct dsa_switch_tree *dst)
+ {
+-      struct dsa_link *dl, *next;
+-
+       if (!dst->setup)
+               return;
+ 
+@@ -1144,10 +1154,7 @@ static void dsa_tree_teardown(struct dsa_switch_tree 
*dst)
+ 
+       dsa_tree_teardown_cpu_ports(dst);
+ 
+-      list_for_each_entry_safe(dl, next, &dst->rtable, list) {
+-              list_del(&dl->list);
+-              kfree(dl);
+-      }
++      dsa_tree_teardown_routing_table(dst);
+ 
+       pr_info("DSA: tree %d torn down\n", dst->index);
+ 
+diff --git a/net/mptcp/pm_netlink.c b/net/mptcp/pm_netlink.c
+index e396adefea0266..1c8aabce33a6a7 100644
+--- a/net/mptcp/pm_netlink.c
++++ b/net/mptcp/pm_netlink.c
+@@ -1656,16 +1656,26 @@ static void __reset_counters(struct pm_nl_pernet 
*pernet)
+ static int mptcp_nl_cmd_flush_addrs(struct sk_buff *skb, struct genl_info 
*info)
+ {
+       struct pm_nl_pernet *pernet = genl_info_pm_nl(info);
+-      LIST_HEAD(free_list);
++      struct list_head free_list;
+ 
+       spin_lock_bh(&pernet->lock);
+-      list_splice_init(&pernet->local_addr_list, &free_list);
++      free_list = pernet->local_addr_list;
++      INIT_LIST_HEAD_RCU(&pernet->local_addr_list);
+       __reset_counters(pernet);
+       pernet->next_id = 1;
+       bitmap_zero(pernet->id_bitmap, MAX_ADDR_ID + 1);
+       spin_unlock_bh(&pernet->lock);
+-      mptcp_nl_remove_addrs_list(sock_net(skb->sk), &free_list);
++
++      if (free_list.next == &pernet->local_addr_list)
++              return 0;
++
+       synchronize_rcu();
++
++      /* Adjust the pointers to free_list instead of pernet->local_addr_list 
*/
++      free_list.prev->next = &free_list;
++      free_list.next->prev = &free_list;
++
++      mptcp_nl_remove_addrs_list(sock_net(skb->sk), &free_list);
+       __flush_addrs(&free_list);
+       return 0;
+ }
+diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c
+index 839a7e957d42a0..72d9ea5171bbd6 100644
+--- a/sound/pci/hda/patch_realtek.c
++++ b/sound/pci/hda/patch_realtek.c
+@@ -10133,6 +10133,10 @@ static const struct snd_hda_pin_quirk 
alc269_pin_fixup_tbl[] = {
+               {0x12, 0x90a60140},
+               {0x19, 0x04a11030},
+               {0x21, 0x04211020}),
++      SND_HDA_PIN_QUIRK(0x10ec0274, 0x1d05, "TongFang", 
ALC274_FIXUP_HP_HEADSET_MIC,
++              {0x17, 0x90170110},
++              {0x19, 0x03a11030},
++              {0x21, 0x03211020}),
+       SND_HDA_PIN_QUIRK(0x10ec0282, 0x1025, "Acer", 
ALC282_FIXUP_ACER_DISABLE_LINEOUT,
+               ALC282_STANDARD_PINS,
+               {0x12, 0x90a609c0},
+diff --git a/sound/soc/fsl/fsl_xcvr.c b/sound/soc/fsl/fsl_xcvr.c
+index ae5960b2b6a951..c4deb09c9a9bca 100644
+--- a/sound/soc/fsl/fsl_xcvr.c
++++ b/sound/soc/fsl/fsl_xcvr.c
+@@ -203,10 +203,13 @@ static int fsl_xcvr_mode_put(struct snd_kcontrol 
*kcontrol,
+ 
+       xcvr->mode = snd_soc_enum_item_to_val(e, item[0]);
+ 
++      down_read(&card->snd_card->controls_rwsem);
+       fsl_xcvr_activate_ctl(dai, fsl_xcvr_arc_mode_kctl.name,
+                             (xcvr->mode == FSL_XCVR_MODE_ARC));
+       fsl_xcvr_activate_ctl(dai, fsl_xcvr_earc_capds_kctl.name,
+                             (xcvr->mode == FSL_XCVR_MODE_EARC));
++      up_read(&card->snd_card->controls_rwsem);
++
+       /* Allow playback for SPDIF only */
+       rtd = snd_soc_get_pcm_runtime(card, card->dai_link);
+       rtd->pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream_count =
+diff --git a/tools/testing/selftests/net/mptcp/pm_netlink.sh 
b/tools/testing/selftests/net/mptcp/pm_netlink.sh
+index 68e05bd3526ead..e3ab2f5ef30478 100755
+--- a/tools/testing/selftests/net/mptcp/pm_netlink.sh
++++ b/tools/testing/selftests/net/mptcp/pm_netlink.sh
+@@ -124,6 +124,10 @@ id 8 flags signal 10.0.1.8" "id limit"
+ ip netns exec $ns1 ./pm_nl_ctl flush
+ check "ip netns exec $ns1 ./pm_nl_ctl dump" "" "flush addrs"
+ 
++ip netns exec $ns1 ./pm_nl_ctl add 10.0.1.1 flags unknown
++check "ip netns exec $ns1 ./pm_nl_ctl dump" "id 1 flags  10.0.1.1" "ignore 
unknown flags"
++ip netns exec $ns1 ./pm_nl_ctl flush
++
+ ip netns exec $ns1 ./pm_nl_ctl limits 9 1
+ check "ip netns exec $ns1 ./pm_nl_ctl limits" "$default_limits" "rcv addrs 
above hard limit"
+ 
+diff --git a/tools/testing/selftests/net/mptcp/pm_nl_ctl.c 
b/tools/testing/selftests/net/mptcp/pm_nl_ctl.c
+index 354784512748a4..e50075be0e4dc3 100644
+--- a/tools/testing/selftests/net/mptcp/pm_nl_ctl.c
++++ b/tools/testing/selftests/net/mptcp/pm_nl_ctl.c
+@@ -22,6 +22,8 @@
+ #define MPTCP_PM_NAME         "mptcp_pm"
+ #endif
+ 
++#define MPTCP_PM_ADDR_FLAG_UNKNOWN _BITUL(7)
++
+ static void syntax(char *argv[])
+ {
+       fprintf(stderr, "%s add|get|set|del|flush|dump|accept [<args>]\n", 
argv[0]);
+@@ -238,6 +240,8 @@ int add_addr(int fd, int pm_family, int argc, char *argv[])
+                                       flags |= MPTCP_PM_ADDR_FLAG_BACKUP;
+                               else if (!strcmp(tok, "fullmesh"))
+                                       flags |= MPTCP_PM_ADDR_FLAG_FULLMESH;
++                              else if (!strcmp(tok, "unknown"))
++                                      flags |= MPTCP_PM_ADDR_FLAG_UNKNOWN;
+                               else
+                                       error(1, errno,
+                                             "unknown flag %s", argv[arg]);
+@@ -436,6 +440,13 @@ static void print_addr(struct rtattr *attrs, int len)
+                                       printf(",");
+                       }
+ 
++                      if (flags & MPTCP_PM_ADDR_FLAG_UNKNOWN) {
++                              printf("unknown");
++                              flags &= ~MPTCP_PM_ADDR_FLAG_UNKNOWN;
++                              if (flags)
++                                      printf(",");
++                      }
++
+                       /* bump unknown flags, if any */
+                       if (flags)
+                               printf("0x%x", flags);

Reply via email to