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