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

Linux patch 6.1.164

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

 0000_README              |    4 +
 1163_linux-6.1.164.patch | 3088 ++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 3092 insertions(+)

diff --git a/0000_README b/0000_README
index 1ea26aae..4a99e821 100644
--- a/0000_README
+++ b/0000_README
@@ -695,6 +695,10 @@ Patch:  1162_linux-6.1.163.patch
 From:   https://www.kernel.org
 Desc:   Linux 6.1.163
 
+Patch:  1163_linux-6.1.164.patch
+From:   https://www.kernel.org
+Desc:   Linux 6.1.164
+
 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/1163_linux-6.1.164.patch b/1163_linux-6.1.164.patch
new file mode 100644
index 00000000..798a517a
--- /dev/null
+++ b/1163_linux-6.1.164.patch
@@ -0,0 +1,3088 @@
+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/Documentation/PCI/endpoint/pci-vntb-howto.rst 
b/Documentation/PCI/endpoint/pci-vntb-howto.rst
+index 4ab8e4a26d4bed..70d3bc90893f33 100644
+--- 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 is given below::
+       # 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
+diff --git a/Makefile b/Makefile
+index f52d3b8656d4f6..eca6fda4347731 100644
+--- a/Makefile
++++ b/Makefile
+@@ -1,7 +1,7 @@
+ # SPDX-License-Identifier: GPL-2.0
+ VERSION = 6
+ PATCHLEVEL = 1
+-SUBLEVEL = 163
++SUBLEVEL = 164
+ EXTRAVERSION =
+ NAME = Curry Ramen
+ 
+diff --git a/drivers/acpi/apei/ghes.c b/drivers/acpi/apei/ghes.c
+index 03344c27322201..9fb86d0c4ff059 100644
+--- a/drivers/acpi/apei/ghes.c
++++ b/drivers/acpi/apei/ghes.c
+@@ -684,6 +684,16 @@ static bool ghes_do_proc(struct ghes *ghes,
+               }
+       }
+ 
++      /*
++       * If no memory failure work is queued for abnormal synchronous
++       * errors, do a force kill.
++       */
++      if (sync && !queued) {
++              pr_err(GHES_PFX "%s:%d: synchronous unrecoverable error 
(SIGBUS)\n",
++                      current->comm, task_pid_nr(current));
++              force_sig(SIGBUS);
++      }
++
+       return queued;
+ }
+ 
+diff --git a/drivers/base/cacheinfo.c b/drivers/base/cacheinfo.c
+index 9e11d42b0d644e..f41effceea7c3e 100644
+--- a/drivers/base/cacheinfo.c
++++ b/drivers/base/cacheinfo.c
+@@ -195,7 +195,7 @@ static void cache_of_set_props(struct cacheinfo *this_leaf,
+ 
+ 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 int cpu)
+               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;
+ 
+@@ -404,8 +409,6 @@ static void cache_shared_cpu_map_remove(unsigned int cpu)
+                               }
+                       }
+               }
+-              if (of_have_populated_dt())
+-                      of_node_put(this_leaf->fw_token);
+       }
+ 
+       /* cpu is no longer populated in the shared map */
+diff --git a/drivers/bus/fsl-mc/fsl-mc-bus.c b/drivers/bus/fsl-mc/fsl-mc-bus.c
+index 8ae7e7bfc62489..8311da43c3d562 100644
+--- 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 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);
+ 
+@@ -201,8 +201,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/clk/mediatek/clk-mtk.c b/drivers/clk/mediatek/clk-mtk.c
+index 7b1ad73309b1a9..c2ca3d7576c22a 100644
+--- a/drivers/clk/mediatek/clk-mtk.c
++++ b/drivers/clk/mediatek/clk-mtk.c
+@@ -505,8 +505,10 @@ int mtk_clk_simple_probe(struct platform_device *pdev)
+       num_clks += mcd->num_mux_clks;
+ 
+       clk_data = mtk_alloc_clk_data(num_clks);
+-      if (!clk_data)
+-              return -ENOMEM;
++      if (!clk_data) {
++              r = -ENOMEM;
++              goto free_base;
++      }
+ 
+       if (mcd->fixed_clks) {
+               r = mtk_clk_register_fixed_clks(mcd->fixed_clks,
+@@ -594,6 +596,7 @@ unregister_fixed_clks:
+                                             mcd->num_fixed_clks, clk_data);
+ free_data:
+       mtk_free_clk_data(clk_data);
++free_base:
+       if (mcd->shared_io && base)
+               iounmap(base);
+ 
+diff --git a/drivers/crypto/marvell/octeontx/otx_cptpf_ucode.c 
b/drivers/crypto/marvell/octeontx/otx_cptpf_ucode.c
+index df9c2b8747e6dd..b65330bbaf45a5 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_core.c 
b/drivers/crypto/virtio/virtio_crypto_core.c
+index 56dc0935c774a3..d185e8b3bba1d6 100644
+--- a/drivers/crypto/virtio/virtio_crypto_core.c
++++ b/drivers/crypto/virtio/virtio_crypto_core.c
+@@ -77,15 +77,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/crypto/virtio/virtio_crypto_skcipher_algs.c 
b/drivers/crypto/virtio/virtio_crypto_skcipher_algs.c
+index e5876286828b8e..f7b8715b507443 100644
+--- a/drivers/crypto/virtio/virtio_crypto_skcipher_algs.c
++++ b/drivers/crypto/virtio/virtio_crypto_skcipher_algs.c
+@@ -556,8 +556,6 @@ int virtio_crypto_skcipher_crypt_req(
+       if (ret < 0)
+               return ret;
+ 
+-      virtqueue_kick(data_vq->vq);
+-
+       return 0;
+ }
+ 
+diff --git a/drivers/gpio/gpio-omap.c b/drivers/gpio/gpio-omap.c
+index 80ddc43fd875b7..7f19af08f91c60 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;
++      }
+ }
+ 
+ /*---------------------------------------------------------------------*/
+@@ -1572,13 +1575,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 9bff63990eee43..2da626905798b1 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 11338f47d884d4..48c9935bedffbd 100644
+--- a/drivers/gpio/gpiolib-acpi.c
++++ b/drivers/gpio/gpiolib-acpi.c
+@@ -1383,6 +1383,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 c66764c0bd2509..47f794a367ba19 100644
+--- a/drivers/gpu/drm/tegra/hdmi.c
++++ b/drivers/gpu/drm/tegra/hdmi.c
+@@ -654,7 +654,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]) {
+@@ -687,7 +687,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 77723d5f1d3fd2..ce8e299b6afb69 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/bareudp.c b/drivers/net/bareudp.c
+index 54767154de265c..cfbc0240126ef0 100644
+--- a/drivers/net/bareudp.c
++++ b/drivers/net/bareudp.c
+@@ -319,7 +319,7 @@ static int bareudp_xmit_skb(struct sk_buff *skb, struct 
net_device *dev,
+       __be32 saddr;
+       int err;
+ 
+-      if (!skb_vlan_inet_prepare(skb, skb->protocol != htons(ETH_P_TEB)))
++      if (skb_vlan_inet_prepare(skb, skb->protocol != htons(ETH_P_TEB)))
+               return -EINVAL;
+ 
+       if (!sock)
+@@ -385,7 +385,7 @@ static int bareudp6_xmit_skb(struct sk_buff *skb, struct 
net_device *dev,
+       __be16 sport;
+       int err;
+ 
+-      if (!skb_vlan_inet_prepare(skb, skb->protocol != htons(ETH_P_TEB)))
++      if (skb_vlan_inet_prepare(skb, skb->protocol != htons(ETH_P_TEB)))
+               return -EINVAL;
+ 
+       if (!sock)
+diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c 
b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
+index b8b3ef09ea998a..b5de07b84f77bc 100644
+--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
++++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
+@@ -3518,7 +3518,6 @@ static int stmmac_request_irq_multi_msi(struct 
net_device *dev)
+ {
+       struct stmmac_priv *priv = netdev_priv(dev);
+       enum request_irq_err irq_err;
+-      cpumask_t cpu_mask;
+       int irq_idx = 0;
+       char *int_name;
+       int ret;
+@@ -3630,9 +3629,8 @@ static int stmmac_request_irq_multi_msi(struct 
net_device *dev)
+                       irq_idx = i;
+                       goto irq_error;
+               }
+-              cpumask_clear(&cpu_mask);
+-              cpumask_set_cpu(i % num_online_cpus(), &cpu_mask);
+-              irq_set_affinity_hint(priv->rx_irq[i], &cpu_mask);
++              irq_set_affinity_hint(priv->rx_irq[i],
++                                    cpumask_of(i % num_online_cpus()));
+       }
+ 
+       /* Request Tx MSI irq */
+@@ -3655,9 +3653,8 @@ static int stmmac_request_irq_multi_msi(struct 
net_device *dev)
+                       irq_idx = i;
+                       goto irq_error;
+               }
+-              cpumask_clear(&cpu_mask);
+-              cpumask_set_cpu(i % num_online_cpus(), &cpu_mask);
+-              irq_set_affinity_hint(priv->tx_irq[i], &cpu_mask);
++              irq_set_affinity_hint(priv->tx_irq[i],
++                                    cpumask_of(i % num_online_cpus()));
+       }
+ 
+       return 0;
+diff --git a/drivers/net/geneve.c b/drivers/net/geneve.c
+index b31441fc99fc4a..6234a3c711c53b 100644
+--- a/drivers/net/geneve.c
++++ b/drivers/net/geneve.c
+@@ -932,7 +932,7 @@ static int geneve_xmit_skb(struct sk_buff *skb, struct 
net_device *dev,
+       __be16 sport;
+       int err;
+ 
+-      if (!skb_vlan_inet_prepare(skb, inner_proto_inherit))
++      if (skb_vlan_inet_prepare(skb, inner_proto_inherit))
+               return -EINVAL;
+ 
+       sport = udp_flow_src_port(geneve->net, skb, 1, USHRT_MAX, true);
+@@ -1031,7 +1031,7 @@ static int geneve6_xmit_skb(struct sk_buff *skb, struct 
net_device *dev,
+       __be16 sport;
+       int err;
+ 
+-      if (!skb_vlan_inet_prepare(skb, inner_proto_inherit))
++      if (skb_vlan_inet_prepare(skb, inner_proto_inherit))
+               return -EINVAL;
+ 
+       sport = udp_flow_src_port(geneve->net, skb, 1, USHRT_MAX, true);
+diff --git a/drivers/net/phy/sfp.c b/drivers/net/phy/sfp.c
+index 0666a39dc48591..5cc3d53bbf666d 100644
+--- a/drivers/net/phy/sfp.c
++++ b/drivers/net/phy/sfp.c
+@@ -376,6 +376,8 @@ static void sfp_quirk_ubnt_uf_instant(const struct 
sfp_eeprom_id *id,
+        */
+       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/drivers/net/wireguard/device.c b/drivers/net/wireguard/device.c
+index 531332e169df83..895a621c9e267c 100644
+--- a/drivers/net/wireguard/device.c
++++ b/drivers/net/wireguard/device.c
+@@ -368,7 +368,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 6f7253d420dbf9..9fb35cf0233163 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;
+ }
+@@ -502,40 +501,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");
+@@ -547,6 +539,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,
+@@ -592,9 +586,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 e9bee5f6ec8d05..99cbacd0cbba47 100644
+--- a/drivers/platform/x86/panasonic-laptop.c
++++ b/drivers/platform/x86/panasonic-laptop.c
+@@ -1077,7 +1077,7 @@ static int acpi_pcc_hotkey_add(struct acpi_device 
*device)
+                       PLATFORM_DEVID_NONE, 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);
+@@ -1093,6 +1093,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 10431a67d202bb..f43969ed87bf9e 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;
+ }
+ 
+@@ -2612,8 +2613,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;
+ }
+@@ -2702,8 +2704,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:
+@@ -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)
+                                   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_job *bsg_job)
+ 
+       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/drivers/scsi/qla2xxx/qla_def.h b/drivers/scsi/qla2xxx/qla_def.h
+index c0d8714d6f7663..e68f843be0867e 100644
+--- 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[5];
+ 
+ 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",
+@@ -3275,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;
+@@ -3505,10 +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_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 f654877ed083e8..64cce557cbeb39 100644
+--- a/drivers/scsi/qla2xxx/qla_gbl.h
++++ b/drivers/scsi/qla2xxx/qla_gbl.h
+@@ -736,12 +736,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 9c707d677f648d..0698265f4717de 100644
+--- 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_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;
+@@ -3653,9 +3653,6 @@ login_logout:
+                           atomic_read(&fcport->state) == FCS_ONLINE) ||
+                               do_delete) {
+                               if (fcport->loop_id != FC_NO_LOOP_ID) {
+-                                      if (fcport->flags & FCF_FCP2_DEVICE)
+-                                              continue;
+-
+                                       ql_log(ql_log_warn, vha, 0x20f0,
+                                              "%s %d %8phC post del sess\n",
+                                              __func__, __LINE__,
+@@ -3703,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;
+@@ -3720,37 +3714,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;
+@@ -3769,85 +3741,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) {
+@@ -3871,8 +3841,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);
+@@ -3897,28 +3866,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) {
+@@ -3929,127 +3900,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)
+@@ -4058,22 +3918,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) {
+@@ -4089,7 +3948,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;
+@@ -4097,7 +3956,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) *
+@@ -4109,7 +3967,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;
+@@ -4129,35 +3987,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) {
+@@ -4167,28 +4085,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);
+@@ -4199,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),
+@@ -4217,116 +4146,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 d2243f809616df..d4f9857cbd449e 100644
+--- a/drivers/scsi/qla2xxx/qla_init.c
++++ b/drivers/scsi/qla2xxx/qla_init.c
+@@ -1723,12 +1723,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);
+@@ -1860,15 +1855,6 @@ void qla2x00_handle_rscn(scsi_qla_host_t *vha, struct 
event_arg *ea)
+       case RSCN_PORT_ADDR:
+               fcport = qla2x00_find_fcport_by_nportid(vha, &ea->id, 1);
+               if (fcport) {
+-                      if (ql2xfc2target &&
+-                          fcport->flags & FCF_FCP2_DEVICE &&
+-                          atomic_read(&fcport->state) == FCS_ONLINE) {
+-                              ql_dbg(ql_dbg_disc, vha, 0x2115,
+-                                     "Delaying session delete for FCP2 
portid=%06x %8phC ",
+-                                      fcport->d_id.b24, fcport->port_name);
+-                              return;
+-                      }
+-
+                       if (vha->hw->flags.edif_enabled && DBELL_ACTIVE(vha)) {
+                               /*
+                                * On ipsec start by remote port, Target port
+@@ -2472,8 +2458,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);
+@@ -6443,10 +6444,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 b5421614c8573d..f11de5d1ecbf76 100644
+--- a/drivers/scsi/qla2xxx/qla_isr.c
++++ b/drivers/scsi/qla2xxx/qla_isr.c
+@@ -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 6f399640996823..a373c90dfe6df3 100644
+--- a/drivers/scsi/qla2xxx/qla_os.c
++++ b/drivers/scsi/qla2xxx/qla_os.c
+@@ -1189,7 +1189,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);
+@@ -5521,18 +5522,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 2ad6e98ce10d5c..1bbffec21b7276 100644
+--- a/drivers/video/fbdev/smscufx.c
++++ b/drivers/video/fbdev/smscufx.c
+@@ -988,7 +988,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;
+@@ -1003,6 +1002,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
+@@ -1012,7 +1015,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 2338d42b8f4e68..880288d7358e6c 100644
+--- a/fs/btrfs/block-group.c
++++ b/fs/btrfs/block-group.c
+@@ -3924,7 +3924,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);
+               }
+@@ -3973,7 +3973,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 {
+@@ -3983,7 +3983,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 230e086ddee8e6..2f23bbcbd2316b 100644
+--- a/fs/btrfs/space-info.c
++++ b/fs/btrfs/space-info.c
+@@ -179,7 +179,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;
+ }
+ 
+ /*
+@@ -360,7 +360,7 @@ void btrfs_add_bg_to_space_info(struct btrfs_fs_info *info,
+       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_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;
+       }
+@@ -1128,7 +1128,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;
+               }
+@@ -1171,7 +1171,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;
+@@ -1333,7 +1333,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;
+       }
+@@ -1344,7 +1344,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;
+               }
+@@ -1361,7 +1361,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;
+               }
+@@ -1378,7 +1378,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;
+                       }
+@@ -1394,7 +1394,7 @@ static void btrfs_async_reclaim_data_space(struct 
work_struct *work)
+ 
+ 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_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 dc69138f3de172..7aebb6c4132c6b 100644
+--- 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/fs/f2fs/data.c b/fs/f2fs/data.c
+index 3bf3b24e38d23a..0e13b01db06aa1 100644
+--- a/fs/f2fs/data.c
++++ b/fs/f2fs/data.c
+@@ -358,14 +358,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/node.c b/fs/f2fs/node.c
+index ec84bb7c31bfd2..2555787c79bbe5 100644
+--- a/fs/f2fs/node.c
++++ b/fs/f2fs/node.c
+@@ -1665,8 +1665,13 @@ static int __write_node_page(struct page *page, bool 
atomic, bool *submitted,
+               goto redirty_out;
+       }
+ 
+-      if (atomic && !test_opt(sbi, NOBARRIER) && !f2fs_sb_has_blkzoned(sbi))
+-              fio.op_flags |= REQ_PREFLUSH | REQ_FUA;
++      if (atomic) {
++              if (!test_opt(sbi, NOBARRIER) && !f2fs_sb_has_blkzoned(sbi))
++                      fio.op_flags |= REQ_PREFLUSH | REQ_FUA;
++              if (IS_INODE(page))
++                      set_dentry_mark(page,
++                              f2fs_need_dentry_mark(sbi, ino_of_node(page)));
++      }
+ 
+       /* should add to global list before clearing PAGECACHE status */
+       if (f2fs_in_warm_node_list(sbi, page)) {
+@@ -1821,8 +1826,9 @@ continue_unlock:
+                                       if (is_inode_flag_set(inode,
+                                                               FI_DIRTY_INODE))
+                                               f2fs_update_inode(inode, page);
+-                                      set_dentry_mark(page,
+-                                              f2fs_need_dentry_mark(sbi, 
ino));
++                                      if (!atomic)
++                                              set_dentry_mark(page,
++                                                      
f2fs_need_dentry_mark(sbi, ino));
+                               }
+                               /* may be written by other thread */
+                               if (!PageDirty(page))
+diff --git a/fs/f2fs/sysfs.c b/fs/f2fs/sysfs.c
+index 06d5791afe90e1..4e643abbd891a6 100644
+--- a/fs/f2fs/sysfs.c
++++ b/fs/f2fs/sysfs.c
+@@ -58,6 +58,7 @@ struct f2fs_attr {
+                        const char *, size_t);
+       int struct_type;
+       int offset;
++      int size;
+       int id;
+ };
+ 
+@@ -273,11 +274,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)
+@@ -360,9 +380,30 @@ static ssize_t f2fs_sbi_show(struct f2fs_attr *a,
+       if (!strcmp(a->attr.name, "revoked_atomic_block"))
+               return sysfs_emit(buf, "%llu\n", sbi->revoked_atomic_block);
+ 
+-      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,
+@@ -655,7 +696,7 @@ out:
+               return count;
+       }
+ 
+-      *ui = (unsigned int)t;
++      __sbi_store_value(a, sbi, ptr + a->offset, t);
+ 
+       return count;
+ }
+@@ -751,24 +792,27 @@ 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))
++              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)
+@@ -779,6 +823,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/nfsd/nfsctl.c b/fs/nfsd/nfsctl.c
+index ba2eaf3744efa4..cc0dea883fbdb2 100644
+--- a/fs/nfsd/nfsctl.c
++++ b/fs/nfsd/nfsctl.c
+@@ -1460,17 +1460,24 @@ static __net_init int nfsd_init_net(struct net *net)
+       retval = nfsd_stat_counters_init(nn);
+       if (retval)
+               goto out_repcache_error;
++
+       memset(&nn->nfsd_svcstats, 0, sizeof(nn->nfsd_svcstats));
+       nn->nfsd_svcstats.program = &nfsd_program;
++      if (!nfsd_proc_stat_init(net)) {
++              retval = -ENOMEM;
++              goto out_proc_error;
++      }
++
+       nn->nfsd_versions = NULL;
+       nn->nfsd4_minorversions = NULL;
+       nfsd4_init_leases_net(nn);
+       get_random_bytes(&nn->siphash_key, sizeof(nn->siphash_key));
+       seqlock_init(&nn->writeverf_lock);
+-      nfsd_proc_stat_init(net);
+ 
+       return 0;
+ 
++out_proc_error:
++      nfsd_stat_counters_destroy(nn);
+ out_repcache_error:
+       nfsd_idmap_shutdown(net);
+ out_idmap_error:
+diff --git a/fs/nfsd/stats.c b/fs/nfsd/stats.c
+index 36f1373bbe3f05..336878cf3b0738 100644
+--- a/fs/nfsd/stats.c
++++ b/fs/nfsd/stats.c
+@@ -113,11 +113,11 @@ void nfsd_stat_counters_destroy(struct nfsd_net *nn)
+       nfsd_percpu_counters_destroy(nn->counter, NFSD_STATS_COUNTERS_NUM);
+ }
+ 
+-void nfsd_proc_stat_init(struct net *net)
++struct proc_dir_entry *nfsd_proc_stat_init(struct net *net)
+ {
+       struct nfsd_net *nn = net_generic(net, nfsd_net_id);
+ 
+-      svc_proc_register(net, &nn->nfsd_svcstats, &nfsd_proc_ops);
++      return svc_proc_register(net, &nn->nfsd_svcstats, &nfsd_proc_ops);
+ }
+ 
+ void nfsd_proc_stat_shutdown(struct net *net)
+diff --git a/fs/nfsd/stats.h b/fs/nfsd/stats.h
+index 14525e854cbac3..b9329285bc1d79 100644
+--- a/fs/nfsd/stats.h
++++ b/fs/nfsd/stats.h
+@@ -15,7 +15,7 @@ void nfsd_percpu_counters_reset(struct percpu_counter 
*counters, int num);
+ void nfsd_percpu_counters_destroy(struct percpu_counter *counters, int num);
+ int nfsd_stat_counters_init(struct nfsd_net *nn);
+ void nfsd_stat_counters_destroy(struct nfsd_net *nn);
+-void nfsd_proc_stat_init(struct net *net);
++struct proc_dir_entry *nfsd_proc_stat_init(struct net *net);
+ void nfsd_proc_stat_shutdown(struct net *net);
+ 
+ static inline void nfsd_stats_rc_hits_inc(struct nfsd_net *nn)
+diff --git a/fs/nilfs2/sufile.c b/fs/nilfs2/sufile.c
+index 58ca7c936393c4..aa39cdce59930b 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 c59b230d55b435..3bc993634321a5 100644
+--- a/fs/romfs/super.c
++++ b/fs/romfs/super.c
+@@ -468,7 +468,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/fs/smb/client/cached_dir.h b/fs/smb/client/cached_dir.h
+index dad31f0b7ffb7f..467570ad788879 100644
+--- a/fs/smb/client/cached_dir.h
++++ b/fs/smb/client/cached_dir.h
+@@ -34,10 +34,10 @@ struct cached_fid {
+       struct list_head entry;
+       struct cached_fids *cfids;
+       const char *path;
+-      bool has_lease:1;
+-      bool is_open:1;
+-      bool on_list:1;
+-      bool file_all_info_is_valid:1;
++      bool has_lease;
++      bool is_open;
++      bool on_list;
++      bool file_all_info_is_valid;
+       unsigned long time; /* jiffies of when lease was taken */
+       struct kref refcount;
+       struct cifs_fid fid;
+diff --git a/fs/smb/client/cifs_dfs_ref.c b/fs/smb/client/cifs_dfs_ref.c
+index 876f9a43a99db9..d8a20283de0df9 100644
+--- 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_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/smb/server/server.c b/fs/smb/server/server.c
+index 27d8d6c6fdacd9..fe797e8fe9419e 100644
+--- a/fs/smb/server/server.c
++++ b/fs/smb/server/server.c
+@@ -126,21 +126,21 @@ static int __process_request(struct ksmbd_work *work, 
struct ksmbd_conn *conn,
+ andx_again:
+       if (command >= conn->max_cmds) {
+               conn->ops->set_rsp_status(work, STATUS_INVALID_PARAMETER);
+-              return SERVER_HANDLER_CONTINUE;
++              return SERVER_HANDLER_ABORT;
+       }
+ 
+       cmds = &conn->cmds[command];
+       if (!cmds->proc) {
+               ksmbd_debug(SMB, "*** not implemented yet cmd = %x\n", command);
+               conn->ops->set_rsp_status(work, STATUS_NOT_IMPLEMENTED);
+-              return SERVER_HANDLER_CONTINUE;
++              return SERVER_HANDLER_ABORT;
+       }
+ 
+       if (work->sess && conn->ops->is_sign_req(work, command)) {
+               ret = conn->ops->check_sign_req(work);
+               if (!ret) {
+                       conn->ops->set_rsp_status(work, STATUS_ACCESS_DENIED);
+-                      return SERVER_HANDLER_CONTINUE;
++                      return SERVER_HANDLER_ABORT;
+               }
+       }
+ 
+diff --git a/fs/smb/server/smb2pdu.c b/fs/smb/server/smb2pdu.c
+index 14d46c52ee7484..2b16bd48824992 100644
+--- a/fs/smb/server/smb2pdu.c
++++ b/fs/smb/server/smb2pdu.c
+@@ -5739,15 +5739,13 @@ static int set_file_basic_info(struct ksmbd_file *fp,
+               attrs.ia_valid |= (ATTR_ATIME | ATTR_ATIME_SET);
+       }
+ 
+-      attrs.ia_valid |= ATTR_CTIME;
+       if (file_info->ChangeTime)
+-              attrs.ia_ctime = ksmbd_NTtimeToUnix(file_info->ChangeTime);
+-      else
+-              attrs.ia_ctime = inode->i_ctime;
++              inode_set_ctime_to_ts(inode,
++                              ksmbd_NTtimeToUnix(file_info->ChangeTime));
+ 
+       if (file_info->LastWriteTime) {
+               attrs.ia_mtime = ksmbd_NTtimeToUnix(file_info->LastWriteTime);
+-              attrs.ia_valid |= (ATTR_MTIME | ATTR_MTIME_SET);
++              attrs.ia_valid |= (ATTR_MTIME | ATTR_MTIME_SET | ATTR_CTIME);
+       }
+ 
+       if (file_info->Attributes) {
+@@ -5789,8 +5787,6 @@ static int set_file_basic_info(struct ksmbd_file *fp,
+                       return -EACCES;
+ 
+               inode_lock(inode);
+-              inode->i_ctime = attrs.ia_ctime;
+-              attrs.ia_valid &= ~ATTR_CTIME;
+               rc = notify_change(user_ns, dentry, &attrs, NULL);
+               inode_unlock(inode);
+       }
+diff --git a/fs/smb/server/transport_tcp.c b/fs/smb/server/transport_tcp.c
+index 34707dc46db4a4..8a1a61d22dac1b 100644
+--- a/fs/smb/server/transport_tcp.c
++++ b/fs/smb/server/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, \
+@@ -215,7 +216,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/include/net/ip_tunnels.h b/include/net/ip_tunnels.h
+index e93db837412b20..c649192ddbacfb 100644
+--- a/include/net/ip_tunnels.h
++++ b/include/net/ip_tunnels.h
+@@ -354,11 +354,12 @@ static inline bool pskb_inet_may_pull(struct sk_buff 
*skb)
+ 
+ /* Variant of pskb_inet_may_pull().
+  */
+-static inline bool skb_vlan_inet_prepare(struct sk_buff *skb,
+-                                       bool inner_proto_inherit)
++static inline enum skb_drop_reason
++skb_vlan_inet_prepare(struct sk_buff *skb, bool inner_proto_inherit)
+ {
+       int nhlen = 0, maclen = inner_proto_inherit ? 0 : ETH_HLEN;
+       __be16 type = skb->protocol;
++      enum skb_drop_reason reason;
+ 
+       /* Essentially this is skb_protocol(skb, true)
+        * And we get MAC len.
+@@ -379,11 +380,13 @@ static inline bool skb_vlan_inet_prepare(struct sk_buff 
*skb,
+       /* For ETH_P_IPV6/ETH_P_IP we make sure to pull
+        * a base network header in skb->head.
+        */
+-      if (!pskb_may_pull(skb, maclen + nhlen))
+-              return false;
++      reason = pskb_may_pull_reason(skb, maclen + nhlen);
++      if (reason)
++              return reason;
+ 
+       skb_set_network_header(skb, maclen);
+-      return true;
++
++      return SKB_NOT_DROPPED_YET;
+ }
+ 
+ static inline int ip_encap_hlen(struct ip_tunnel_encap *e)
+diff --git a/include/net/xdp_sock.h b/include/net/xdp_sock.h
+index 3057e1a4a11c63..b8001d24106a57 100644
+--- a/include/net/xdp_sock.h
++++ b/include/net/xdp_sock.h
+@@ -59,8 +59,6 @@ struct xdp_sock {
+ 
+       struct xsk_queue *tx ____cacheline_aligned_in_smp;
+       struct list_head tx_list;
+-      /* Protects generic receive. */
+-      spinlock_t rx_lock;
+ 
+       /* Statistics */
+       u64 rx_dropped;
+diff --git a/include/net/xsk_buff_pool.h b/include/net/xsk_buff_pool.h
+index 996eaf1ef1a1d1..e436363c219229 100644
+--- a/include/net/xsk_buff_pool.h
++++ b/include/net/xsk_buff_pool.h
+@@ -48,6 +48,8 @@ struct xsk_buff_pool {
+       refcount_t users;
+       struct xdp_umem *umem;
+       struct work_struct work;
++      /* Protects generic receive in shared and non-shared umem mode. */
++      spinlock_t rx_lock;
+       struct list_head free_list;
+       u32 heads_cnt;
+       u16 queue_id;
+diff --git a/kernel/cgroup/cpuset.c b/kernel/cgroup/cpuset.c
+index d56433c8e970bb..ecc5ebbcf99172 100644
+--- a/kernel/cgroup/cpuset.c
++++ b/kernel/cgroup/cpuset.c
+@@ -509,7 +509,7 @@ static inline bool partition_is_populated(struct cpuset 
*cs,
+           cs->attach_in_progress)
+               return true;
+       if (!excluded_child && !cs->nr_subparts_cpus)
+-              return cgroup_is_populated(cs->css.cgroup);
++              return cpuset_is_populated(cs);
+ 
+       rcu_read_lock();
+       cpuset_for_each_descendant_pre(cp, pos_css, cs) {
+diff --git a/net/devlink/leftover.c b/net/devlink/leftover.c
+index f1c6bd727a8399..1ea84c5ffa9f1a 100644
+--- a/net/devlink/leftover.c
++++ b/net/devlink/leftover.c
+@@ -10274,13 +10274,15 @@ void devl_rate_nodes_destroy(struct devlink *devlink)
+               if (!devlink_rate->parent)
+                       continue;
+ 
+-              refcount_dec(&devlink_rate->parent->refcnt);
+               if (devlink_rate_is_leaf(devlink_rate))
+                       ops->rate_leaf_parent_set(devlink_rate, NULL, 
devlink_rate->priv,
+                                                 NULL, NULL);
+               else if (devlink_rate_is_node(devlink_rate))
+                       ops->rate_node_parent_set(devlink_rate, NULL, 
devlink_rate->priv,
+                                                 NULL, NULL);
++
++              refcount_dec(&devlink_rate->parent->refcnt);
++              devlink_rate->parent = NULL;
+       }
+       list_for_each_entry_safe(devlink_rate, tmp, &devlink->rate_list, list) {
+               if (devlink_rate_is_node(devlink_rate)) {
+diff --git a/net/dsa/dsa2.c b/net/dsa/dsa2.c
+index 98f86487917554..668699d7b0b713 100644
+--- a/net/dsa/dsa2.c
++++ b/net/dsa/dsa2.c
+@@ -1148,6 +1148,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;
+@@ -1165,7 +1175,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)
+@@ -1197,14 +1207,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;
+ 
+@@ -1218,10 +1228,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 cc58536bbf2625..293ec3448f52c2 100644
+--- a/net/mptcp/pm_netlink.c
++++ b/net/mptcp/pm_netlink.c
+@@ -1855,16 +1855,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, MPTCP_PM_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/net/mptcp/protocol.c b/net/mptcp/protocol.c
+index 2d107a1f2ef946..5274b19a5dbd76 100644
+--- a/net/mptcp/protocol.c
++++ b/net/mptcp/protocol.c
+@@ -1666,7 +1666,7 @@ void __mptcp_push_pending(struct sock *sk, unsigned int 
flags)
+       struct mptcp_sendmsg_info info = {
+                               .flags = flags,
+       };
+-      bool do_check_data_fin = false;
++      bool copied = false;
+       struct mptcp_data_frag *dfrag;
+       int len;
+ 
+@@ -1703,7 +1703,7 @@ void __mptcp_push_pending(struct sock *sk, unsigned int 
flags)
+                               goto out;
+                       }
+ 
+-                      do_check_data_fin = true;
++                      copied = true;
+                       info.sent += ret;
+                       len -= ret;
+ 
+@@ -1717,11 +1717,14 @@ void __mptcp_push_pending(struct sock *sk, unsigned 
int flags)
+               mptcp_push_release(ssk, &info);
+ 
+ out:
+-      /* ensure the rtx timer is running */
+-      if (!mptcp_rtx_timer_pending(sk))
+-              mptcp_reset_rtx_timer(sk);
+-      if (do_check_data_fin)
++      /* Avoid scheduling the rtx timer if no data has been pushed; the timer
++       * will be updated on positive acks by __mptcp_cleanup_una().
++       */
++      if (copied) {
++              if (!mptcp_rtx_timer_pending(sk))
++                      mptcp_reset_rtx_timer(sk);
+               mptcp_check_send_data_fin(sk);
++      }
+ }
+ 
+ static void __mptcp_subflow_push_pending(struct sock *sk, struct sock *ssk, 
bool first)
+@@ -2453,10 +2456,10 @@ bool __mptcp_retransmit_pending_data(struct sock *sk)
+  */
+ static void __mptcp_subflow_disconnect(struct sock *ssk,
+                                      struct mptcp_subflow_context *subflow,
+-                                     unsigned int flags)
++                                     bool fastclosing)
+ {
+       if (((1 << ssk->sk_state) & (TCPF_CLOSE | TCPF_LISTEN)) ||
+-          subflow->send_fastclose) {
++          fastclosing) {
+               /* The MPTCP code never wait on the subflow sockets, TCP-level
+                * disconnect should never fail
+                */
+@@ -2508,7 +2511,7 @@ static void __mptcp_close_ssk(struct sock *sk, struct 
sock *ssk,
+ 
+       need_push = (flags & MPTCP_CF_PUSH) && 
__mptcp_retransmit_pending_data(sk);
+       if (!dispose_it) {
+-              __mptcp_subflow_disconnect(ssk, subflow, flags);
++              __mptcp_subflow_disconnect(ssk, subflow, msk->fastclosing);
+               if (msk->subflow && ssk == msk->subflow->sk)
+                       msk->subflow->state = SS_UNCONNECTED;
+               release_sock(ssk);
+@@ -2799,6 +2802,8 @@ static void mptcp_do_fastclose(struct sock *sk)
+       struct mptcp_subflow_context *subflow, *tmp;
+       struct mptcp_sock *msk = mptcp_sk(sk);
+ 
++      msk->fastclosing = 1;
++
+       /* Explicitly send the fastclose reset as need */
+       if (__mptcp_check_fallback(msk))
+               return;
+@@ -3287,6 +3292,7 @@ static int mptcp_disconnect(struct sock *sk, int flags)
+       WRITE_ONCE(msk->csum_enabled, mptcp_is_checksum_enabled(sock_net(sk)));
+       mptcp_pm_data_reset(msk);
+       mptcp_ca_reset(sk);
++      msk->fastclosing = 0;
+ 
+       WRITE_ONCE(sk->sk_shutdown, 0);
+       sk_error_report(sk);
+diff --git a/net/mptcp/protocol.h b/net/mptcp/protocol.h
+index 6575712c789e48..dd5070d57d740f 100644
+--- a/net/mptcp/protocol.h
++++ b/net/mptcp/protocol.h
+@@ -289,7 +289,8 @@ struct mptcp_sock {
+                       nodelay:1,
+                       fastopening:1,
+                       in_accept_queue:1,
+-                      free_first:1;
++                      free_first:1,
++                      fastclosing:1;
+       int             keepalive_cnt;
+       int             keepalive_idle;
+       int             keepalive_intvl;
+diff --git a/net/wireless/reg.c b/net/wireless/reg.c
+index 34a6bc43119bc1..85a982a1e9f991 100644
+--- a/net/wireless/reg.c
++++ b/net/wireless/reg.c
+@@ -4241,6 +4241,9 @@ EXPORT_SYMBOL(regulatory_pre_cac_allowed);
+ static void cfg80211_check_and_end_cac(struct cfg80211_registered_device 
*rdev)
+ {
+       struct wireless_dev *wdev;
++
++      wiphy_lock(&rdev->wiphy);
++
+       /* If we finished CAC or received radar, we should end any
+        * CAC running on the same channels.
+        * the check !cfg80211_chandef_dfs_usable contain 2 options:
+@@ -4264,6 +4267,8 @@ static void cfg80211_check_and_end_cac(struct 
cfg80211_registered_device *rdev)
+               if (!cfg80211_chandef_dfs_usable(&rdev->wiphy, chandef))
+                       rdev_end_cac(rdev, wdev->netdev);
+       }
++
++      wiphy_unlock(&rdev->wiphy);
+ }
+ 
+ void regulatory_propagate_dfs_state(struct wiphy *wiphy,
+diff --git a/net/xdp/xsk.c b/net/xdp/xsk.c
+index e3bdfc517424d2..e55e153377c827 100644
+--- a/net/xdp/xsk.c
++++ b/net/xdp/xsk.c
+@@ -237,13 +237,14 @@ int xsk_generic_rcv(struct xdp_sock *xs, struct xdp_buff 
*xdp)
+ {
+       int err;
+ 
+-      spin_lock_bh(&xs->rx_lock);
+       err = xsk_rcv_check(xs, xdp);
+       if (!err) {
++              spin_lock_bh(&xs->pool->rx_lock);
+               err = __xsk_rcv(xs, xdp);
+               xsk_flush(xs);
++              spin_unlock_bh(&xs->pool->rx_lock);
+       }
+-      spin_unlock_bh(&xs->rx_lock);
++
+       return err;
+ }
+ 
+@@ -1448,7 +1449,6 @@ static int xsk_create(struct net *net, struct socket 
*sock, int protocol,
+       xs = xdp_sk(sk);
+       xs->state = XSK_READY;
+       mutex_init(&xs->mutex);
+-      spin_lock_init(&xs->rx_lock);
+ 
+       INIT_LIST_HEAD(&xs->map_list);
+       spin_lock_init(&xs->map_list_lock);
+diff --git a/net/xdp/xsk_buff_pool.c b/net/xdp/xsk_buff_pool.c
+index 21d5fdba47c493..b2004a8bf67fcc 100644
+--- a/net/xdp/xsk_buff_pool.c
++++ b/net/xdp/xsk_buff_pool.c
+@@ -85,6 +85,7 @@ struct xsk_buff_pool *xp_create_and_assign_umem(struct 
xdp_sock *xs,
+               XDP_PACKET_HEADROOM;
+       pool->umem = umem;
+       pool->addrs = umem->addrs;
++      spin_lock_init(&pool->rx_lock);
+       INIT_LIST_HEAD(&pool->free_list);
+       INIT_LIST_HEAD(&pool->xsk_tx_list);
+       spin_lock_init(&pool->xsk_tx_list_lock);
+diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c
+index b45e5b268a65bc..89410d40561d71 100644
+--- a/sound/pci/hda/patch_realtek.c
++++ b/sound/pci/hda/patch_realtek.c
+@@ -10454,6 +10454,7 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = 
{
+       SND_PCI_QUIRK(0x1ee7, 0x2078, "HONOR BRB-X M1010", 
ALC2XX_FIXUP_HEADSET_MIC),
+       SND_PCI_QUIRK(0x1f66, 0x0105, "Ayaneo Portable Game Player", 
ALC287_FIXUP_CS35L41_I2C_2),
+       SND_PCI_QUIRK(0x2014, 0x800a, "Positivo ARN50", 
ALC269_FIXUP_LIMIT_INT_MIC_BOOST),
++      SND_PCI_QUIRK(0x2039, 0x0001, "Inspur S14-G1", 
ALC295_FIXUP_CHROME_BOOK),
+       SND_PCI_QUIRK(0x2782, 0x0214, "VAIO VJFE-CL", 
ALC269_FIXUP_LIMIT_INT_MIC_BOOST),
+       SND_PCI_QUIRK(0x2782, 0x0228, "Infinix ZERO BOOK 13", 
ALC269VB_FIXUP_INFINIX_ZERO_BOOK_13),
+       SND_PCI_QUIRK(0x2782, 0x0232, "CHUWI CoreBook XPro", 
ALC269VB_FIXUP_CHUWI_COREBOOK_XPRO),
+@@ -10906,6 +10907,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/amd/yc/acp6x-mach.c b/sound/soc/amd/yc/acp6x-mach.c
+index 6bbbcf77fc5254..43f7f64015b253 100644
+--- a/sound/soc/amd/yc/acp6x-mach.c
++++ b/sound/soc/amd/yc/acp6x-mach.c
+@@ -451,6 +451,13 @@ static const struct dmi_system_id yc_acp_quirk_table[] = {
+                       DMI_MATCH(DMI_PRODUCT_NAME, "15NBC1011"),
+               }
+       },
++      {
++              .driver_data = &acp6x_card,
++              .matches = {
++                      DMI_MATCH(DMI_BOARD_VENDOR, "ASUSTeK COMPUTER INC."),
++                      DMI_MATCH(DMI_PRODUCT_NAME, "ASUS EXPERTBOOK 
PM1503CDA"),
++              }
++      },
+       {
+               .driver_data = &acp6x_card,
+               .matches = {
+diff --git a/sound/soc/codecs/cs35l45.c b/sound/soc/codecs/cs35l45.c
+index d15b3b77c7eb09..29aed074438662 100644
+--- a/sound/soc/codecs/cs35l45.c
++++ b/sound/soc/codecs/cs35l45.c
+@@ -131,7 +131,7 @@ static const struct snd_soc_dapm_widget 
cs35l45_dapm_widgets[] = {
+       SND_SOC_DAPM_AIF_OUT("ASP_TX2", NULL, 1, CS35L45_ASP_ENABLES1, 
CS35L45_ASP_TX2_EN_SHIFT, 0),
+       SND_SOC_DAPM_AIF_OUT("ASP_TX3", NULL, 2, CS35L45_ASP_ENABLES1, 
CS35L45_ASP_TX3_EN_SHIFT, 0),
+       SND_SOC_DAPM_AIF_OUT("ASP_TX4", NULL, 3, CS35L45_ASP_ENABLES1, 
CS35L45_ASP_TX4_EN_SHIFT, 0),
+-      SND_SOC_DAPM_AIF_OUT("ASP_TX5", NULL, 3, CS35L45_ASP_ENABLES1, 
CS35L45_ASP_TX5_EN_SHIFT, 0),
++      SND_SOC_DAPM_AIF_OUT("ASP_TX5", NULL, 4, CS35L45_ASP_ENABLES1, 
CS35L45_ASP_TX5_EN_SHIFT, 0),
+ 
+       SND_SOC_DAPM_MUX("ASP_TX1 Source", SND_SOC_NOPM, 0, 0, 
&cs35l45_asp_muxes[0]),
+       SND_SOC_DAPM_MUX("ASP_TX2 Source", SND_SOC_NOPM, 0, 0, 
&cs35l45_asp_muxes[1]),
+diff --git a/sound/soc/fsl/fsl_xcvr.c b/sound/soc/fsl/fsl_xcvr.c
+index 5b61b93772d648..e6c0e6609cbe02 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/sound/soc/intel/boards/sof_es8336.c 
b/sound/soc/intel/boards/sof_es8336.c
+index 41dab5dcf79a35..1c71c23f347e70 100644
+--- a/sound/soc/intel/boards/sof_es8336.c
++++ b/sound/soc/intel/boards/sof_es8336.c
+@@ -332,6 +332,15 @@ static int sof_es8336_quirk_cb(const struct dmi_system_id 
*id)
+  * if the topology file is modified as well.
+  */
+ static const struct dmi_system_id sof_es8336_quirk_table[] = {
++      {
++              .callback = sof_es8336_quirk_cb,
++              .matches = {
++                      DMI_MATCH(DMI_SYS_VENDOR, "HUAWEI"),
++                      DMI_MATCH(DMI_PRODUCT_NAME, "BOD-WXX9"),
++              },
++              .driver_data = (void *)(SOF_ES8336_HEADPHONE_GPIO |
++                                      SOF_ES8336_ENABLE_DMIC)
++      },
+       {
+               .callback = sof_es8336_quirk_cb,
+               .matches = {
+diff --git a/tools/testing/selftests/net/mptcp/mptcp_join.sh 
b/tools/testing/selftests/net/mptcp/mptcp_join.sh
+index 9f73297b69da7d..5a40e09e8374cf 100755
+--- a/tools/testing/selftests/net/mptcp/mptcp_join.sh
++++ b/tools/testing/selftests/net/mptcp/mptcp_join.sh
+@@ -2181,17 +2181,16 @@ signal_address_tests()
+               # the peer could possibly miss some addr notification, allow 
retransmission
+               ip netns exec $ns1 sysctl -q net.mptcp.add_addr_timeout=1
+               run_tests $ns1 $ns2 10.0.1.1 0 0 0 slow
++              chk_join_nr 3 3 3
+ 
+               # It is not directly linked to the commit introducing this
+               # symbol but for the parent one which is linked anyway.
+-              if ! mptcp_lib_kallsyms_has "mptcp_pm_subflow_check_next$"; then
+-                      chk_join_nr 3 3 2
+-                      chk_add_nr 4 4
+-              else
+-                      chk_join_nr 3 3 3
++              if mptcp_lib_kallsyms_has "mptcp_pm_subflow_check_next$"; then
+                       # the server will not signal the address terminating
+                       # the MPC subflow
+                       chk_add_nr 3 3
++              else
++                      chk_add_nr 4 4
+               fi
+       fi
+ }
+@@ -3183,32 +3182,101 @@ fail_tests()
+       fi
+ }
+ 
+-# $1: ns ; $2: event type ; $3: count
++# get the value of keyword $1 in the line marked by keyword $2
++get_info_value() {
++      grep "${2}" 2>/dev/null |
++              sed -n 's/.*\('"${1}"':\)\([0-9a-f:.]*\).*$/\2/p;q'
++              # the ';q' at the end limits to the first matched entry.
++}
++
++# $1: info name ; $2: evts_ns ; [$3: event type; [$4: addr]]
++evts_get_info() {
++      grep "${4:-}" "${2}" 2>/dev/null |
++              get_info_value "${1}" "^type:${3:-1},"
++}
++
++# $1: ns ; $2: addr ; $3: id
++userspace_pm_add_sf()
++{
++      local evts=$evts_ns1
++      local tk da dp
++
++      [ "$1" == "$ns2" ] && evts=$evts_ns2
++      tk=$(evts_get_info token "$evts")
++      da=$(evts_get_info daddr4 "$evts")
++      dp=$(evts_get_info dport "$evts")
++
++      ip netns exec $1 ./pm_nl_ctl csf lip $2 lid $3 \
++                              rip $da rport $dp token $tk
++      sleep 1
++}
++
++# $1: ns ; $2: event type ; $3: count ; [ $4: attr ; $5: attr count ]
+ chk_evt_nr()
+ {
+       local ns=${1}
+       local evt_name="${2}"
+       local exp="${3}"
++      local attr="${4}"
++      local attr_exp="${5}"
+ 
+       local evts="${evts_ns1}"
+       local evt="${!evt_name}"
++      local attr_name
+       local count
+ 
++      if [ -n "${attr}" ]; then
++              attr_name=", ${attr}: ${attr_exp}"
++      fi
++
+       evt_name="${evt_name:16}" # without MPTCP_LIB_EVENT_
+       [ "${ns}" == "ns2" ] && evts="${evts_ns2}"
+ 
+-      printf "%-${nr_blank}s %s" " " "event ${ns} ${evt_name} (${exp})"
++      printf "%-${nr_blank}s %s" " " "event ${ns} ${evt_name} 
(${exp}${attr_name})"
+ 
+       count=$(grep -cw "type:${evt}" "${evts}")
+       if [ "${count}" != "${exp}" ]; then
+               echo "[fail] got $count events, expected $exp"
+               fail_test
+               dump_stats
++              cat "${evts}"
++              return
++      elif [ -z "${attr}" ]; then
++              echo "[ ok ]"
++              return
++      fi
++
++      count=$(grep -w "type:${evt}" "${evts}" | grep -c ",${attr}:")
++      if [ "${count}" != "${attr_exp}" ]; then
++              echo "[fail] got ${count} event attributes, expected 
${attr_exp}"
++              fail_test
++              dump_stats
++              grep -w "type:${evt}" "${evts}"
+       else
+               echo "[ ok ]"
+       fi
+ }
+ 
++# $1: ns ; $2: event type ; $3: expected count
++wait_event()
++{
++      local ns="${1}"
++      local evt_name="${2}"
++      local exp="${3}"
++
++      local evt="${!evt_name}"
++      local evts="${evts_ns1}"
++      local count
++
++      [ "${ns}" == "ns2" ] && evts="${evts_ns2}"
++
++      for _ in $(seq 100); do
++              count=$(grep -cw "type:${evt}" "${evts}")
++              [ "${count}" -ge "${exp}" ] && break
++              sleep 0.1
++      done
++}
++
+ userspace_tests()
+ {
+       # userspace pm type prevents add_addr
+@@ -3302,6 +3370,35 @@ userspace_tests()
+               chk_join_nr 1 1 1
+               chk_rm_nr 0 1
+       fi
++
++      # userspace pm no duplicated spurious close events after an error
++      if reset_with_events "userspace pm no dup close events after error" &&
++         continue_if mptcp_lib_has_file '/proc/sys/net/mptcp/pm_type'; then
++              set_userspace_pm $ns2
++              pm_nl_set_limits $ns1 0 2
++              run_tests $ns1 $ns2 10.0.1.1 128 0 0 slow 2>/dev/null &
++              local tests_pid=$!
++              wait_event ns2 MPTCP_LIB_EVENT_ESTABLISHED 1
++              userspace_pm_add_sf $ns2 10.0.3.2 20
++              chk_subflow_nr needtitle "new subflow" 2
++
++              # force quick loss
++              ip netns exec $ns2 sysctl -q net.ipv4.tcp_syn_retries=1
++              if ip netns exec "${ns1}" ${iptables} -A INPUT -s "10.0.1.2" \
++                    -p tcp --tcp-option 30 -j REJECT --reject-with tcp-reset 
&&
++                 ip netns exec "${ns2}" ${iptables} -A INPUT -d "10.0.1.2" \
++                    -p tcp --tcp-option 30 -j REJECT --reject-with tcp-reset; 
then
++                      wait_event ns2 MPTCP_LIB_EVENT_SUB_CLOSED 1
++                      wait_event ns1 MPTCP_LIB_EVENT_SUB_CLOSED 1
++                      chk_subflow_nr "" "after reject" 1
++                      userspace_pm_add_sf $ns2 10.0.1.2 0
++                      wait_event ns2 MPTCP_LIB_EVENT_SUB_CLOSED 2
++                      chk_evt_nr ns2 MPTCP_LIB_EVENT_SUB_CLOSED 2 error 2
++              fi
++              kill_wait "${tests_pid}"
++              kill_events_pids
++              kill_tests_wait
++      fi
+ }
+ 
+ endpoint_tests()
+diff --git a/tools/testing/selftests/net/mptcp/pm_netlink.sh 
b/tools/testing/selftests/net/mptcp/pm_netlink.sh
+index 1b0ed849c61747..4dfb6b93d9cbf9 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 17e5b7ec53b67c..5feecb3463a1a9 100644
+--- a/tools/testing/selftests/net/mptcp/pm_nl_ctl.c
++++ b/tools/testing/selftests/net/mptcp/pm_nl_ctl.c
+@@ -29,6 +29,8 @@
+ #define IPPROTO_MPTCP 262
+ #endif
+ 
++#define MPTCP_PM_ADDR_FLAG_UNKNOWN _BITUL(7)
++
+ static void syntax(char *argv[])
+ {
+       fprintf(stderr, "%s 
add|ann|rem|csf|dsf|get|set|del|flush|dump|events|listen|accept [<args>]\n", 
argv[0]);
+@@ -814,6 +816,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]);
+@@ -1019,6 +1023,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