diff options
author | 2024-07-25 08:08:09 -0400 | |
---|---|---|
committer | 2024-07-25 08:08:09 -0400 | |
commit | 23c525cf347a41a5a069e3a19cc1c1e92a254571 (patch) | |
tree | a4f8a1dd38001ee709ba5a0f1862c6f6b5fd741f | |
parent | Linux patch 6.9.10 (diff) | |
download | linux-patches-23c525cf347a41a5a069e3a19cc1c1e92a254571.tar.gz linux-patches-23c525cf347a41a5a069e3a19cc1c1e92a254571.tar.bz2 linux-patches-23c525cf347a41a5a069e3a19cc1c1e92a254571.zip |
Linux patch 6.9.116.9-12
Signed-off-by: Mike Pagano <mpagano@gentoo.org>
-rw-r--r-- | 0000_README | 4 | ||||
-rw-r--r-- | 1010_linux-6.9.11.patch | 6453 |
2 files changed, 6457 insertions, 0 deletions
diff --git a/0000_README b/0000_README index e8d9065b..dd499825 100644 --- a/0000_README +++ b/0000_README @@ -83,6 +83,10 @@ Patch: 1009_linux-6.9.10.patch From: https://www.kernel.org Desc: Linux 6.9.10 +Patch: 1010_linux-6.9.11.patch +From: https://www.kernel.org +Desc: Linux 6.9.11 + Patch: 1510_fs-enable-link-security-restrictions-by-default.patch From: http://sources.debian.net/src/linux/3.16.7-ckt4-3/debian/patches/debian/fs-enable-link-security-restrictions-by-default.patch Desc: Enable link security restrictions by default. diff --git a/1010_linux-6.9.11.patch b/1010_linux-6.9.11.patch new file mode 100644 index 00000000..aa466b72 --- /dev/null +++ b/1010_linux-6.9.11.patch @@ -0,0 +1,6453 @@ +diff --git a/Documentation/cdrom/cdrom-standard.rst b/Documentation/cdrom/cdrom-standard.rst +index 7964fe134277b..6c1303cff159e 100644 +--- a/Documentation/cdrom/cdrom-standard.rst ++++ b/Documentation/cdrom/cdrom-standard.rst +@@ -217,7 +217,7 @@ current *struct* is:: + int (*media_changed)(struct cdrom_device_info *, int); + int (*tray_move)(struct cdrom_device_info *, int); + int (*lock_door)(struct cdrom_device_info *, int); +- int (*select_speed)(struct cdrom_device_info *, int); ++ int (*select_speed)(struct cdrom_device_info *, unsigned long); + int (*get_last_session) (struct cdrom_device_info *, + struct cdrom_multisession *); + int (*get_mcn)(struct cdrom_device_info *, struct cdrom_mcn *); +@@ -396,7 +396,7 @@ action need be taken, and the return value should be 0. + + :: + +- int select_speed(struct cdrom_device_info *cdi, int speed) ++ int select_speed(struct cdrom_device_info *cdi, unsigned long speed) + + Some CD-ROM drives are capable of changing their head-speed. There + are several reasons for changing the speed of a CD-ROM drive. Badly +diff --git a/Makefile b/Makefile +index 5471f554f95ec..46457f645921e 100644 +--- a/Makefile ++++ b/Makefile +@@ -1,7 +1,7 @@ + # SPDX-License-Identifier: GPL-2.0 + VERSION = 6 + PATCHLEVEL = 9 +-SUBLEVEL = 10 ++SUBLEVEL = 11 + EXTRAVERSION = + NAME = Hurr durr I'ma ninja sloth + +diff --git a/arch/arm64/kernel/armv8_deprecated.c b/arch/arm64/kernel/armv8_deprecated.c +index dd6ce86d4332b..b776e7424fe91 100644 +--- a/arch/arm64/kernel/armv8_deprecated.c ++++ b/arch/arm64/kernel/armv8_deprecated.c +@@ -462,6 +462,9 @@ static int run_all_insn_set_hw_mode(unsigned int cpu) + for (int i = 0; i < ARRAY_SIZE(insn_emulations); i++) { + struct insn_emulation *insn = insn_emulations[i]; + bool enable = READ_ONCE(insn->current_mode) == INSN_HW; ++ if (insn->status == INSN_UNAVAILABLE) ++ continue; ++ + if (insn->set_hw_mode && insn->set_hw_mode(enable)) { + pr_warn("CPU[%u] cannot support the emulation of %s", + cpu, insn->name); +diff --git a/arch/loongarch/boot/dts/loongson-2k0500-ref.dts b/arch/loongarch/boot/dts/loongson-2k0500-ref.dts +index 8aefb0c126722..a34734a6c3ce8 100644 +--- a/arch/loongarch/boot/dts/loongson-2k0500-ref.dts ++++ b/arch/loongarch/boot/dts/loongson-2k0500-ref.dts +@@ -44,14 +44,14 @@ linux,cma { + &gmac0 { + status = "okay"; + +- phy-mode = "rgmii"; ++ phy-mode = "rgmii-id"; + bus_id = <0x0>; + }; + + &gmac1 { + status = "okay"; + +- phy-mode = "rgmii"; ++ phy-mode = "rgmii-id"; + bus_id = <0x1>; + }; + +diff --git a/arch/loongarch/boot/dts/loongson-2k1000-ref.dts b/arch/loongarch/boot/dts/loongson-2k1000-ref.dts +index ed4d324340411..aaf41b565805a 100644 +--- a/arch/loongarch/boot/dts/loongson-2k1000-ref.dts ++++ b/arch/loongarch/boot/dts/loongson-2k1000-ref.dts +@@ -43,7 +43,7 @@ linux,cma { + &gmac0 { + status = "okay"; + +- phy-mode = "rgmii"; ++ phy-mode = "rgmii-id"; + phy-handle = <&phy0>; + mdio { + compatible = "snps,dwmac-mdio"; +@@ -58,7 +58,7 @@ phy0: ethernet-phy@0 { + &gmac1 { + status = "okay"; + +- phy-mode = "rgmii"; ++ phy-mode = "rgmii-id"; + phy-handle = <&phy1>; + mdio { + compatible = "snps,dwmac-mdio"; +diff --git a/arch/loongarch/boot/dts/loongson-2k2000-ref.dts b/arch/loongarch/boot/dts/loongson-2k2000-ref.dts +index 74b99bd234cc3..ea9e6985d0e9f 100644 +--- a/arch/loongarch/boot/dts/loongson-2k2000-ref.dts ++++ b/arch/loongarch/boot/dts/loongson-2k2000-ref.dts +@@ -92,7 +92,7 @@ phy1: ethernet-phy@1 { + &gmac2 { + status = "okay"; + +- phy-mode = "rgmii"; ++ phy-mode = "rgmii-id"; + phy-handle = <&phy2>; + mdio { + compatible = "snps,dwmac-mdio"; +diff --git a/arch/mips/kernel/syscalls/syscall_o32.tbl b/arch/mips/kernel/syscalls/syscall_o32.tbl +index 0352c07c608e9..fe76282a353f5 100644 +--- a/arch/mips/kernel/syscalls/syscall_o32.tbl ++++ b/arch/mips/kernel/syscalls/syscall_o32.tbl +@@ -27,7 +27,7 @@ + 17 o32 break sys_ni_syscall + # 18 was sys_stat + 18 o32 unused18 sys_ni_syscall +-19 o32 lseek sys_lseek ++19 o32 lseek sys_lseek compat_sys_lseek + 20 o32 getpid sys_getpid + 21 o32 mount sys_mount + 22 o32 umount sys_oldumount +diff --git a/arch/powerpc/kernel/eeh_pe.c b/arch/powerpc/kernel/eeh_pe.c +index e0ce812796241..7d1b50599dd6c 100644 +--- a/arch/powerpc/kernel/eeh_pe.c ++++ b/arch/powerpc/kernel/eeh_pe.c +@@ -849,6 +849,7 @@ struct pci_bus *eeh_pe_bus_get(struct eeh_pe *pe) + { + struct eeh_dev *edev; + struct pci_dev *pdev; ++ struct pci_bus *bus = NULL; + + if (pe->type & EEH_PE_PHB) + return pe->phb->bus; +@@ -859,9 +860,11 @@ struct pci_bus *eeh_pe_bus_get(struct eeh_pe *pe) + + /* Retrieve the parent PCI bus of first (top) PCI device */ + edev = list_first_entry_or_null(&pe->edevs, struct eeh_dev, entry); ++ pci_lock_rescan_remove(); + pdev = eeh_dev_to_pci_dev(edev); + if (pdev) +- return pdev->bus; ++ bus = pdev->bus; ++ pci_unlock_rescan_remove(); + +- return NULL; ++ return bus; + } +diff --git a/arch/powerpc/kvm/book3s_64_vio.c b/arch/powerpc/kvm/book3s_64_vio.c +index b569ebaa590e2..3ff3de9a52acf 100644 +--- a/arch/powerpc/kvm/book3s_64_vio.c ++++ b/arch/powerpc/kvm/book3s_64_vio.c +@@ -130,14 +130,16 @@ long kvm_spapr_tce_attach_iommu_group(struct kvm *kvm, int tablefd, + } + rcu_read_unlock(); + +- fdput(f); +- +- if (!found) ++ if (!found) { ++ fdput(f); + return -EINVAL; ++ } + + table_group = iommu_group_get_iommudata(grp); +- if (WARN_ON(!table_group)) ++ if (WARN_ON(!table_group)) { ++ fdput(f); + return -EFAULT; ++ } + + for (i = 0; i < IOMMU_TABLE_GROUP_MAX_TABLES; ++i) { + struct iommu_table *tbltmp = table_group->tables[i]; +@@ -158,8 +160,10 @@ long kvm_spapr_tce_attach_iommu_group(struct kvm *kvm, int tablefd, + break; + } + } +- if (!tbl) ++ if (!tbl) { ++ fdput(f); + return -EINVAL; ++ } + + rcu_read_lock(); + list_for_each_entry_rcu(stit, &stt->iommu_tables, next) { +@@ -170,6 +174,7 @@ long kvm_spapr_tce_attach_iommu_group(struct kvm *kvm, int tablefd, + /* stit is being destroyed */ + iommu_tce_table_put(tbl); + rcu_read_unlock(); ++ fdput(f); + return -ENOTTY; + } + /* +@@ -177,6 +182,7 @@ long kvm_spapr_tce_attach_iommu_group(struct kvm *kvm, int tablefd, + * its KVM reference counter and can return. + */ + rcu_read_unlock(); ++ fdput(f); + return 0; + } + rcu_read_unlock(); +@@ -184,6 +190,7 @@ long kvm_spapr_tce_attach_iommu_group(struct kvm *kvm, int tablefd, + stit = kzalloc(sizeof(*stit), GFP_KERNEL); + if (!stit) { + iommu_tce_table_put(tbl); ++ fdput(f); + return -ENOMEM; + } + +@@ -192,6 +199,7 @@ long kvm_spapr_tce_attach_iommu_group(struct kvm *kvm, int tablefd, + + list_add_rcu(&stit->next, &stt->iommu_tables); + ++ fdput(f); + return 0; + } + +diff --git a/arch/powerpc/platforms/pseries/setup.c b/arch/powerpc/platforms/pseries/setup.c +index b44de0f0822f0..b10a253252387 100644 +--- a/arch/powerpc/platforms/pseries/setup.c ++++ b/arch/powerpc/platforms/pseries/setup.c +@@ -343,8 +343,8 @@ static int alloc_dispatch_log_kmem_cache(void) + { + void (*ctor)(void *) = get_dtl_cache_ctor(); + +- dtl_cache = kmem_cache_create("dtl", DISPATCH_LOG_BYTES, +- DISPATCH_LOG_BYTES, 0, ctor); ++ dtl_cache = kmem_cache_create_usercopy("dtl", DISPATCH_LOG_BYTES, ++ DISPATCH_LOG_BYTES, 0, 0, DISPATCH_LOG_BYTES, ctor); + if (!dtl_cache) { + pr_warn("Failed to create dispatch trace log buffer cache\n"); + pr_warn("Stolen time statistics will be unreliable\n"); +diff --git a/arch/riscv/kernel/stacktrace.c b/arch/riscv/kernel/stacktrace.c +index 0d3f00eb0baee..10e311b2759d3 100644 +--- a/arch/riscv/kernel/stacktrace.c ++++ b/arch/riscv/kernel/stacktrace.c +@@ -32,6 +32,7 @@ void notrace walk_stackframe(struct task_struct *task, struct pt_regs *regs, + bool (*fn)(void *, unsigned long), void *arg) + { + unsigned long fp, sp, pc; ++ int graph_idx = 0; + int level = 0; + + if (regs) { +@@ -68,7 +69,7 @@ void notrace walk_stackframe(struct task_struct *task, struct pt_regs *regs, + pc = regs->ra; + } else { + fp = frame->fp; +- pc = ftrace_graph_ret_addr(current, NULL, frame->ra, ++ pc = ftrace_graph_ret_addr(current, &graph_idx, frame->ra, + &frame->ra); + if (pc == (unsigned long)ret_from_exception) { + if (unlikely(!__kernel_text_address(pc) || !fn(arg, pc))) +diff --git a/drivers/acpi/ac.c b/drivers/acpi/ac.c +index 2d4a35e6dd18d..09a87fa222c78 100644 +--- a/drivers/acpi/ac.c ++++ b/drivers/acpi/ac.c +@@ -145,7 +145,7 @@ static void acpi_ac_notify(acpi_handle handle, u32 event, void *data) + dev_name(&adev->dev), event, + (u32) ac->state); + acpi_notifier_call_chain(adev, event, (u32) ac->state); +- kobject_uevent(&ac->charger->dev.kobj, KOBJ_CHANGE); ++ power_supply_changed(ac->charger); + } + } + +@@ -268,7 +268,7 @@ static int acpi_ac_resume(struct device *dev) + if (acpi_ac_get_state(ac)) + return 0; + if (old_state != ac->state) +- kobject_uevent(&ac->charger->dev.kobj, KOBJ_CHANGE); ++ power_supply_changed(ac->charger); + + return 0; + } +diff --git a/drivers/acpi/ec.c b/drivers/acpi/ec.c +index 1cec29ab64ce8..299ec653388ce 100644 +--- a/drivers/acpi/ec.c ++++ b/drivers/acpi/ec.c +@@ -1333,10 +1333,13 @@ acpi_ec_space_handler(u32 function, acpi_physical_address address, + if (ec->busy_polling || bits > 8) + acpi_ec_burst_enable(ec); + +- for (i = 0; i < bytes; ++i, ++address, ++value) ++ for (i = 0; i < bytes; ++i, ++address, ++value) { + result = (function == ACPI_READ) ? + acpi_ec_read(ec, address, value) : + acpi_ec_write(ec, address, *value); ++ if (result < 0) ++ break; ++ } + + if (ec->busy_polling || bits > 8) + acpi_ec_burst_disable(ec); +@@ -1348,8 +1351,10 @@ acpi_ec_space_handler(u32 function, acpi_physical_address address, + return AE_NOT_FOUND; + case -ETIME: + return AE_TIME; +- default: ++ case 0: + return AE_OK; ++ default: ++ return AE_ERROR; + } + } + +diff --git a/drivers/acpi/sbs.c b/drivers/acpi/sbs.c +index 94e3c000df2e1..dc8164b182dcc 100644 +--- a/drivers/acpi/sbs.c ++++ b/drivers/acpi/sbs.c +@@ -610,7 +610,7 @@ static void acpi_sbs_callback(void *context) + if (sbs->charger_exists) { + acpi_ac_get_present(sbs); + if (sbs->charger_present != saved_charger_state) +- kobject_uevent(&sbs->charger->dev.kobj, KOBJ_CHANGE); ++ power_supply_changed(sbs->charger); + } + + if (sbs->manager_present) { +@@ -622,7 +622,7 @@ static void acpi_sbs_callback(void *context) + acpi_battery_read(bat); + if (saved_battery_state == bat->present) + continue; +- kobject_uevent(&bat->bat->dev.kobj, KOBJ_CHANGE); ++ power_supply_changed(bat->bat); + } + } + } +diff --git a/drivers/block/loop.c b/drivers/block/loop.c +index 28a95fd366fea..95a468eaa7013 100644 +--- a/drivers/block/loop.c ++++ b/drivers/block/loop.c +@@ -302,6 +302,21 @@ static int lo_read_simple(struct loop_device *lo, struct request *rq, + return 0; + } + ++static void loop_clear_limits(struct loop_device *lo, int mode) ++{ ++ struct queue_limits lim = queue_limits_start_update(lo->lo_queue); ++ ++ if (mode & FALLOC_FL_ZERO_RANGE) ++ lim.max_write_zeroes_sectors = 0; ++ ++ if (mode & FALLOC_FL_PUNCH_HOLE) { ++ lim.max_hw_discard_sectors = 0; ++ lim.discard_granularity = 0; ++ } ++ ++ queue_limits_commit_update(lo->lo_queue, &lim); ++} ++ + static int lo_fallocate(struct loop_device *lo, struct request *rq, loff_t pos, + int mode) + { +@@ -320,6 +335,14 @@ static int lo_fallocate(struct loop_device *lo, struct request *rq, loff_t pos, + ret = file->f_op->fallocate(file, mode, pos, blk_rq_bytes(rq)); + if (unlikely(ret && ret != -EINVAL && ret != -EOPNOTSUPP)) + return -EIO; ++ ++ /* ++ * We initially configure the limits in a hope that fallocate is ++ * supported and clear them here if that turns out not to be true. ++ */ ++ if (unlikely(ret == -EOPNOTSUPP)) ++ loop_clear_limits(lo, mode); ++ + return ret; + } + +diff --git a/drivers/block/null_blk/main.c b/drivers/block/null_blk/main.c +index 620679a0ac381..26e2c22a87e1c 100644 +--- a/drivers/block/null_blk/main.c ++++ b/drivers/block/null_blk/main.c +@@ -1810,8 +1810,8 @@ static int null_validate_conf(struct nullb_device *dev) + dev->queue_mode = NULL_Q_MQ; + } + +- dev->blocksize = round_down(dev->blocksize, 512); +- dev->blocksize = clamp_t(unsigned int, dev->blocksize, 512, 4096); ++ if (blk_validate_block_size(dev->blocksize)) ++ return -EINVAL; + + if (dev->use_per_node_hctx) { + if (dev->submit_queues != nr_online_nodes) +diff --git a/drivers/bluetooth/btnxpuart.c b/drivers/bluetooth/btnxpuart.c +index 9d0c7e278114b..9bfa9a6ad56c8 100644 +--- a/drivers/bluetooth/btnxpuart.c ++++ b/drivers/bluetooth/btnxpuart.c +@@ -281,7 +281,7 @@ static u8 crc8_table[CRC8_TABLE_SIZE]; + + /* Default configurations */ + #define DEFAULT_H2C_WAKEUP_MODE WAKEUP_METHOD_BREAK +-#define DEFAULT_PS_MODE PS_MODE_DISABLE ++#define DEFAULT_PS_MODE PS_MODE_ENABLE + #define FW_INIT_BAUDRATE HCI_NXP_PRI_BAUDRATE + + static struct sk_buff *nxp_drv_send_cmd(struct hci_dev *hdev, u16 opcode, +diff --git a/drivers/clk/qcom/apss-ipq-pll.c b/drivers/clk/qcom/apss-ipq-pll.c +index d7ab5bd5d4b41..e12bb9abf6b6a 100644 +--- a/drivers/clk/qcom/apss-ipq-pll.c ++++ b/drivers/clk/qcom/apss-ipq-pll.c +@@ -100,7 +100,6 @@ static struct clk_alpha_pll ipq_pll_stromer_plus = { + static const struct alpha_pll_config ipq5018_pll_config = { + .l = 0x2a, + .config_ctl_val = 0x4001075b, +- .config_ctl_hi_val = 0x304, + .main_output_mask = BIT(0), + .aux_output_mask = BIT(1), + .early_output_mask = BIT(3), +@@ -114,7 +113,6 @@ static const struct alpha_pll_config ipq5018_pll_config = { + static const struct alpha_pll_config ipq5332_pll_config = { + .l = 0x2d, + .config_ctl_val = 0x4001075b, +- .config_ctl_hi_val = 0x304, + .main_output_mask = BIT(0), + .aux_output_mask = BIT(1), + .early_output_mask = BIT(3), +diff --git a/drivers/firmware/efi/libstub/zboot.lds b/drivers/firmware/efi/libstub/zboot.lds +index ac8c0ef851581..af2c82f7bd902 100644 +--- a/drivers/firmware/efi/libstub/zboot.lds ++++ b/drivers/firmware/efi/libstub/zboot.lds +@@ -41,6 +41,7 @@ SECTIONS + } + + /DISCARD/ : { ++ *(.discard .discard.*) + *(.modinfo .init.modinfo) + } + } +diff --git a/drivers/gpio/gpio-pca953x.c b/drivers/gpio/gpio-pca953x.c +index 00ffa168e4056..f2f40393e3695 100644 +--- a/drivers/gpio/gpio-pca953x.c ++++ b/drivers/gpio/gpio-pca953x.c +@@ -758,6 +758,8 @@ static void pca953x_irq_bus_sync_unlock(struct irq_data *d) + int level; + + if (chip->driver_data & PCA_PCAL) { ++ guard(mutex)(&chip->i2c_lock); ++ + /* Enable latch on interrupt-enabled inputs */ + pca953x_write_regs(chip, PCAL953X_IN_LATCH, chip->irq_mask); + +diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v9_4_3.c b/drivers/gpu/drm/amd/amdgpu/gfx_v9_4_3.c +index d89d6829f1df4..b10fdd8b54144 100644 +--- a/drivers/gpu/drm/amd/amdgpu/gfx_v9_4_3.c ++++ b/drivers/gpu/drm/amd/amdgpu/gfx_v9_4_3.c +@@ -4187,9 +4187,10 @@ static u32 gfx_v9_4_3_get_cu_active_bitmap(struct amdgpu_device *adev, int xcc_i + static int gfx_v9_4_3_get_cu_info(struct amdgpu_device *adev, + struct amdgpu_cu_info *cu_info) + { +- int i, j, k, counter, xcc_id, active_cu_number = 0; +- u32 mask, bitmap, ao_bitmap, ao_cu_mask = 0; ++ int i, j, k, prev_counter, counter, xcc_id, active_cu_number = 0; ++ u32 mask, bitmap, ao_bitmap, ao_cu_mask = 0, tmp; + unsigned disable_masks[4 * 4]; ++ bool is_symmetric_cus; + + if (!adev || !cu_info) + return -EINVAL; +@@ -4207,6 +4208,7 @@ static int gfx_v9_4_3_get_cu_info(struct amdgpu_device *adev, + + mutex_lock(&adev->grbm_idx_mutex); + for (xcc_id = 0; xcc_id < NUM_XCC(adev->gfx.xcc_mask); xcc_id++) { ++ is_symmetric_cus = true; + for (i = 0; i < adev->gfx.config.max_shader_engines; i++) { + for (j = 0; j < adev->gfx.config.max_sh_per_se; j++) { + mask = 1; +@@ -4234,6 +4236,15 @@ static int gfx_v9_4_3_get_cu_info(struct amdgpu_device *adev, + ao_cu_mask |= (ao_bitmap << (i * 16 + j * 8)); + cu_info->ao_cu_bitmap[i][j] = ao_bitmap; + } ++ if (i && is_symmetric_cus && prev_counter != counter) ++ is_symmetric_cus = false; ++ prev_counter = counter; ++ } ++ if (is_symmetric_cus) { ++ tmp = RREG32_SOC15(GC, GET_INST(GC, xcc_id), regCP_CPC_DEBUG); ++ tmp = REG_SET_FIELD(tmp, CP_CPC_DEBUG, CPC_HARVESTING_RELAUNCH_DISABLE, 1); ++ tmp = REG_SET_FIELD(tmp, CP_CPC_DEBUG, CPC_HARVESTING_DISPATCH_DISABLE, 1); ++ WREG32_SOC15(GC, GET_INST(GC, xcc_id), regCP_CPC_DEBUG, tmp); + } + gfx_v9_4_3_xcc_select_se_sh(adev, 0xffffffff, 0xffffffff, 0xffffffff, + xcc_id); +diff --git a/drivers/gpu/drm/amd/amdgpu/psp_v14_0.c b/drivers/gpu/drm/amd/amdgpu/psp_v14_0.c +index 78a95f8f370be..238abd98072ad 100644 +--- a/drivers/gpu/drm/amd/amdgpu/psp_v14_0.c ++++ b/drivers/gpu/drm/amd/amdgpu/psp_v14_0.c +@@ -32,7 +32,9 @@ + #include "mp/mp_14_0_2_sh_mask.h" + + MODULE_FIRMWARE("amdgpu/psp_14_0_2_sos.bin"); ++MODULE_FIRMWARE("amdgpu/psp_14_0_2_ta.bin"); + MODULE_FIRMWARE("amdgpu/psp_14_0_3_sos.bin"); ++MODULE_FIRMWARE("amdgpu/psp_14_0_3_ta.bin"); + + /* For large FW files the time to complete can be very long */ + #define USBC_PD_POLLING_LIMIT_S 240 +@@ -64,6 +66,9 @@ static int psp_v14_0_init_microcode(struct psp_context *psp) + case IP_VERSION(14, 0, 2): + case IP_VERSION(14, 0, 3): + err = psp_init_sos_microcode(psp, ucode_prefix); ++ if (err) ++ return err; ++ err = psp_init_ta_microcode(psp, ucode_prefix); + if (err) + return err; + break; +diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +index 2152e40ee1c27..c29d271579ad3 100644 +--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c ++++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +@@ -11161,6 +11161,49 @@ static bool parse_edid_cea(struct amdgpu_dm_connector *aconnector, + return ret; + } + ++static void parse_edid_displayid_vrr(struct drm_connector *connector, ++ struct edid *edid) ++{ ++ u8 *edid_ext = NULL; ++ int i; ++ int j = 0; ++ u16 min_vfreq; ++ u16 max_vfreq; ++ ++ if (edid == NULL || edid->extensions == 0) ++ return; ++ ++ /* Find DisplayID extension */ ++ for (i = 0; i < edid->extensions; i++) { ++ edid_ext = (void *)(edid + (i + 1)); ++ if (edid_ext[0] == DISPLAYID_EXT) ++ break; ++ } ++ ++ if (edid_ext == NULL) ++ return; ++ ++ while (j < EDID_LENGTH) { ++ /* Get dynamic video timing range from DisplayID if available */ ++ if (EDID_LENGTH - j > 13 && edid_ext[j] == 0x25 && ++ (edid_ext[j+1] & 0xFE) == 0 && (edid_ext[j+2] == 9)) { ++ min_vfreq = edid_ext[j+9]; ++ if (edid_ext[j+1] & 7) ++ max_vfreq = edid_ext[j+10] + ((edid_ext[j+11] & 3) << 8); ++ else ++ max_vfreq = edid_ext[j+10]; ++ ++ if (max_vfreq && min_vfreq) { ++ connector->display_info.monitor_range.max_vfreq = max_vfreq; ++ connector->display_info.monitor_range.min_vfreq = min_vfreq; ++ ++ return; ++ } ++ } ++ j++; ++ } ++} ++ + static int parse_amd_vsdb(struct amdgpu_dm_connector *aconnector, + struct edid *edid, struct amdgpu_hdmi_vsdb_info *vsdb_info) + { +@@ -11282,6 +11325,11 @@ void amdgpu_dm_update_freesync_caps(struct drm_connector *connector, + if (!adev->dm.freesync_module) + goto update; + ++ /* Some eDP panels only have the refresh rate range info in DisplayID */ ++ if ((connector->display_info.monitor_range.min_vfreq == 0 || ++ connector->display_info.monitor_range.max_vfreq == 0)) ++ parse_edid_displayid_vrr(connector, edid); ++ + if (edid && (sink->sink_signal == SIGNAL_TYPE_DISPLAY_PORT || + sink->sink_signal == SIGNAL_TYPE_EDP)) { + bool edid_check_required = false; +@@ -11289,9 +11337,11 @@ void amdgpu_dm_update_freesync_caps(struct drm_connector *connector, + if (is_dp_capable_without_timing_msa(adev->dm.dc, + amdgpu_dm_connector)) { + if (edid->features & DRM_EDID_FEATURE_CONTINUOUS_FREQ) { +- freesync_capable = true; + amdgpu_dm_connector->min_vfreq = connector->display_info.monitor_range.min_vfreq; + amdgpu_dm_connector->max_vfreq = connector->display_info.monitor_range.max_vfreq; ++ if (amdgpu_dm_connector->max_vfreq - ++ amdgpu_dm_connector->min_vfreq > 10) ++ freesync_capable = true; + } else { + edid_check_required = edid->version > 1 || + (edid->version == 1 && +diff --git a/drivers/gpu/drm/amd/display/dc/dml/dcn32/display_mode_vba_32.c b/drivers/gpu/drm/amd/display/dc/dml/dcn32/display_mode_vba_32.c +index 6c84b0fa40f44..0782a34689a00 100644 +--- a/drivers/gpu/drm/amd/display/dc/dml/dcn32/display_mode_vba_32.c ++++ b/drivers/gpu/drm/amd/display/dc/dml/dcn32/display_mode_vba_32.c +@@ -3364,6 +3364,9 @@ void dml32_ModeSupportAndSystemConfigurationFull(struct display_mode_lib *mode_l + &mode_lib->vba.UrgentBurstFactorLumaPre[k], + &mode_lib->vba.UrgentBurstFactorChromaPre[k], + &mode_lib->vba.NotUrgentLatencyHidingPre[k]); ++ ++ v->cursor_bw_pre[k] = mode_lib->vba.NumberOfCursors[k] * mode_lib->vba.CursorWidth[k][0] * mode_lib->vba.CursorBPP[k][0] / ++ 8.0 / (mode_lib->vba.HTotal[k] / mode_lib->vba.PixelClock[k]) * v->VRatioPreY[i][j][k]; + } + + { +diff --git a/drivers/gpu/drm/amd/display/dc/dml/dcn35/dcn35_fpu.c b/drivers/gpu/drm/amd/display/dc/dml/dcn35/dcn35_fpu.c +index 53e40d3c48d4b..6716696df7719 100644 +--- a/drivers/gpu/drm/amd/display/dc/dml/dcn35/dcn35_fpu.c ++++ b/drivers/gpu/drm/amd/display/dc/dml/dcn35/dcn35_fpu.c +@@ -177,7 +177,7 @@ struct _vcs_dpi_soc_bounding_box_st dcn3_5_soc = { + .urgent_latency_pixel_data_only_us = 4.0, + .urgent_latency_pixel_mixed_with_vm_data_us = 4.0, + .urgent_latency_vm_data_only_us = 4.0, +- .dram_clock_change_latency_us = 11.72, ++ .dram_clock_change_latency_us = 34.0, + .urgent_out_of_order_return_per_channel_pixel_only_bytes = 4096, + .urgent_out_of_order_return_per_channel_pixel_and_vm_bytes = 4096, + .urgent_out_of_order_return_per_channel_vm_only_bytes = 4096, +diff --git a/drivers/gpu/drm/amd/display/dc/dml/dcn351/dcn351_fpu.c b/drivers/gpu/drm/amd/display/dc/dml/dcn351/dcn351_fpu.c +index b3ffab77cf889..40ca38dd1b23e 100644 +--- a/drivers/gpu/drm/amd/display/dc/dml/dcn351/dcn351_fpu.c ++++ b/drivers/gpu/drm/amd/display/dc/dml/dcn351/dcn351_fpu.c +@@ -215,7 +215,7 @@ struct _vcs_dpi_soc_bounding_box_st dcn3_51_soc = { + .urgent_latency_pixel_data_only_us = 4.0, + .urgent_latency_pixel_mixed_with_vm_data_us = 4.0, + .urgent_latency_vm_data_only_us = 4.0, +- .dram_clock_change_latency_us = 11.72, ++ .dram_clock_change_latency_us = 34, + .urgent_out_of_order_return_per_channel_pixel_only_bytes = 4096, + .urgent_out_of_order_return_per_channel_pixel_and_vm_bytes = 4096, + .urgent_out_of_order_return_per_channel_vm_only_bytes = 4096, +diff --git a/drivers/gpu/drm/amd/display/dc/dml2/dml2_translation_helper.c b/drivers/gpu/drm/amd/display/dc/dml2/dml2_translation_helper.c +index a20f28a5d2e7b..3af759dca6ebf 100644 +--- a/drivers/gpu/drm/amd/display/dc/dml2/dml2_translation_helper.c ++++ b/drivers/gpu/drm/amd/display/dc/dml2/dml2_translation_helper.c +@@ -233,6 +233,7 @@ void dml2_init_socbb_params(struct dml2_context *dml2, const struct dc *in_dc, s + out->round_trip_ping_latency_dcfclk_cycles = 106; + out->smn_latency_us = 2; + out->dispclk_dppclk_vco_speed_mhz = 3600; ++ out->pct_ideal_dram_bw_after_urgent_pixel_only = 65.0; + break; + + } +diff --git a/drivers/gpu/drm/amd/display/dc/dml2/dml2_utils.c b/drivers/gpu/drm/amd/display/dc/dml2/dml2_utils.c +index b72ed3e78df05..bb4e812248aec 100644 +--- a/drivers/gpu/drm/amd/display/dc/dml2/dml2_utils.c ++++ b/drivers/gpu/drm/amd/display/dc/dml2/dml2_utils.c +@@ -294,7 +294,7 @@ void dml2_calculate_rq_and_dlg_params(const struct dc *dc, struct dc_state *cont + context->bw_ctx.bw.dcn.clk.dcfclk_deep_sleep_khz = (unsigned int)in_ctx->v20.dml_core_ctx.mp.DCFCLKDeepSleep * 1000; + context->bw_ctx.bw.dcn.clk.dppclk_khz = 0; + +- if (in_ctx->v20.dml_core_ctx.ms.support.FCLKChangeSupport[in_ctx->v20.scratch.mode_support_params.out_lowest_state_idx] == dml_fclock_change_unsupported) ++ if (in_ctx->v20.dml_core_ctx.ms.support.FCLKChangeSupport[0] == dml_fclock_change_unsupported) + context->bw_ctx.bw.dcn.clk.fclk_p_state_change_support = false; + else + context->bw_ctx.bw.dcn.clk.fclk_p_state_change_support = true; +diff --git a/drivers/gpu/drm/amd/include/pptable.h b/drivers/gpu/drm/amd/include/pptable.h +index 2e8e6c9875f6c..f83ace2d7ec30 100644 +--- a/drivers/gpu/drm/amd/include/pptable.h ++++ b/drivers/gpu/drm/amd/include/pptable.h +@@ -477,31 +477,30 @@ typedef struct _ATOM_PPLIB_STATE_V2 + } ATOM_PPLIB_STATE_V2; + + typedef struct _StateArray{ +- //how many states we have +- UCHAR ucNumEntries; +- +- ATOM_PPLIB_STATE_V2 states[1]; ++ //how many states we have ++ UCHAR ucNumEntries; ++ ++ ATOM_PPLIB_STATE_V2 states[] /* __counted_by(ucNumEntries) */; + }StateArray; + + + typedef struct _ClockInfoArray{ +- //how many clock levels we have +- UCHAR ucNumEntries; +- +- //sizeof(ATOM_PPLIB_CLOCK_INFO) +- UCHAR ucEntrySize; +- +- UCHAR clockInfo[]; ++ //how many clock levels we have ++ UCHAR ucNumEntries; ++ ++ //sizeof(ATOM_PPLIB_CLOCK_INFO) ++ UCHAR ucEntrySize; ++ ++ UCHAR clockInfo[]; + }ClockInfoArray; + + typedef struct _NonClockInfoArray{ ++ //how many non-clock levels we have. normally should be same as number of states ++ UCHAR ucNumEntries; ++ //sizeof(ATOM_PPLIB_NONCLOCK_INFO) ++ UCHAR ucEntrySize; + +- //how many non-clock levels we have. normally should be same as number of states +- UCHAR ucNumEntries; +- //sizeof(ATOM_PPLIB_NONCLOCK_INFO) +- UCHAR ucEntrySize; +- +- ATOM_PPLIB_NONCLOCK_INFO nonClockInfo[]; ++ ATOM_PPLIB_NONCLOCK_INFO nonClockInfo[] __counted_by(ucNumEntries); + }NonClockInfoArray; + + typedef struct _ATOM_PPLIB_Clock_Voltage_Dependency_Record +@@ -513,8 +512,10 @@ typedef struct _ATOM_PPLIB_Clock_Voltage_Dependency_Record + + typedef struct _ATOM_PPLIB_Clock_Voltage_Dependency_Table + { +- UCHAR ucNumEntries; // Number of entries. +- ATOM_PPLIB_Clock_Voltage_Dependency_Record entries[1]; // Dynamically allocate entries. ++ // Number of entries. ++ UCHAR ucNumEntries; ++ // Dynamically allocate entries. ++ ATOM_PPLIB_Clock_Voltage_Dependency_Record entries[] __counted_by(ucNumEntries); + }ATOM_PPLIB_Clock_Voltage_Dependency_Table; + + typedef struct _ATOM_PPLIB_Clock_Voltage_Limit_Record +@@ -529,8 +530,10 @@ typedef struct _ATOM_PPLIB_Clock_Voltage_Limit_Record + + typedef struct _ATOM_PPLIB_Clock_Voltage_Limit_Table + { +- UCHAR ucNumEntries; // Number of entries. +- ATOM_PPLIB_Clock_Voltage_Limit_Record entries[1]; // Dynamically allocate entries. ++ // Number of entries. ++ UCHAR ucNumEntries; ++ // Dynamically allocate entries. ++ ATOM_PPLIB_Clock_Voltage_Limit_Record entries[] __counted_by(ucNumEntries); + }ATOM_PPLIB_Clock_Voltage_Limit_Table; + + union _ATOM_PPLIB_CAC_Leakage_Record +@@ -553,8 +556,10 @@ typedef union _ATOM_PPLIB_CAC_Leakage_Record ATOM_PPLIB_CAC_Leakage_Record; + + typedef struct _ATOM_PPLIB_CAC_Leakage_Table + { +- UCHAR ucNumEntries; // Number of entries. +- ATOM_PPLIB_CAC_Leakage_Record entries[1]; // Dynamically allocate entries. ++ // Number of entries. ++ UCHAR ucNumEntries; ++ // Dynamically allocate entries. ++ ATOM_PPLIB_CAC_Leakage_Record entries[] __counted_by(ucNumEntries); + }ATOM_PPLIB_CAC_Leakage_Table; + + typedef struct _ATOM_PPLIB_PhaseSheddingLimits_Record +@@ -568,8 +573,10 @@ typedef struct _ATOM_PPLIB_PhaseSheddingLimits_Record + + typedef struct _ATOM_PPLIB_PhaseSheddingLimits_Table + { +- UCHAR ucNumEntries; // Number of entries. +- ATOM_PPLIB_PhaseSheddingLimits_Record entries[1]; // Dynamically allocate entries. ++ // Number of entries. ++ UCHAR ucNumEntries; ++ // Dynamically allocate entries. ++ ATOM_PPLIB_PhaseSheddingLimits_Record entries[] __counted_by(ucNumEntries); + }ATOM_PPLIB_PhaseSheddingLimits_Table; + + typedef struct _VCEClockInfo{ +@@ -580,8 +587,8 @@ typedef struct _VCEClockInfo{ + }VCEClockInfo; + + typedef struct _VCEClockInfoArray{ +- UCHAR ucNumEntries; +- VCEClockInfo entries[1]; ++ UCHAR ucNumEntries; ++ VCEClockInfo entries[] __counted_by(ucNumEntries); + }VCEClockInfoArray; + + typedef struct _ATOM_PPLIB_VCE_Clock_Voltage_Limit_Record +@@ -592,8 +599,8 @@ typedef struct _ATOM_PPLIB_VCE_Clock_Voltage_Limit_Record + + typedef struct _ATOM_PPLIB_VCE_Clock_Voltage_Limit_Table + { +- UCHAR numEntries; +- ATOM_PPLIB_VCE_Clock_Voltage_Limit_Record entries[1]; ++ UCHAR numEntries; ++ ATOM_PPLIB_VCE_Clock_Voltage_Limit_Record entries[] __counted_by(numEntries); + }ATOM_PPLIB_VCE_Clock_Voltage_Limit_Table; + + typedef struct _ATOM_PPLIB_VCE_State_Record +@@ -604,8 +611,8 @@ typedef struct _ATOM_PPLIB_VCE_State_Record + + typedef struct _ATOM_PPLIB_VCE_State_Table + { +- UCHAR numEntries; +- ATOM_PPLIB_VCE_State_Record entries[1]; ++ UCHAR numEntries; ++ ATOM_PPLIB_VCE_State_Record entries[] __counted_by(numEntries); + }ATOM_PPLIB_VCE_State_Table; + + +@@ -626,8 +633,8 @@ typedef struct _UVDClockInfo{ + }UVDClockInfo; + + typedef struct _UVDClockInfoArray{ +- UCHAR ucNumEntries; +- UVDClockInfo entries[1]; ++ UCHAR ucNumEntries; ++ UVDClockInfo entries[] __counted_by(ucNumEntries); + }UVDClockInfoArray; + + typedef struct _ATOM_PPLIB_UVD_Clock_Voltage_Limit_Record +@@ -638,8 +645,8 @@ typedef struct _ATOM_PPLIB_UVD_Clock_Voltage_Limit_Record + + typedef struct _ATOM_PPLIB_UVD_Clock_Voltage_Limit_Table + { +- UCHAR numEntries; +- ATOM_PPLIB_UVD_Clock_Voltage_Limit_Record entries[1]; ++ UCHAR numEntries; ++ ATOM_PPLIB_UVD_Clock_Voltage_Limit_Record entries[] __counted_by(numEntries); + }ATOM_PPLIB_UVD_Clock_Voltage_Limit_Table; + + typedef struct _ATOM_PPLIB_UVD_Table +@@ -657,8 +664,8 @@ typedef struct _ATOM_PPLIB_SAMClk_Voltage_Limit_Record + }ATOM_PPLIB_SAMClk_Voltage_Limit_Record; + + typedef struct _ATOM_PPLIB_SAMClk_Voltage_Limit_Table{ +- UCHAR numEntries; +- ATOM_PPLIB_SAMClk_Voltage_Limit_Record entries[]; ++ UCHAR numEntries; ++ ATOM_PPLIB_SAMClk_Voltage_Limit_Record entries[] __counted_by(numEntries); + }ATOM_PPLIB_SAMClk_Voltage_Limit_Table; + + typedef struct _ATOM_PPLIB_SAMU_Table +@@ -675,8 +682,8 @@ typedef struct _ATOM_PPLIB_ACPClk_Voltage_Limit_Record + }ATOM_PPLIB_ACPClk_Voltage_Limit_Record; + + typedef struct _ATOM_PPLIB_ACPClk_Voltage_Limit_Table{ +- UCHAR numEntries; +- ATOM_PPLIB_ACPClk_Voltage_Limit_Record entries[1]; ++ UCHAR numEntries; ++ ATOM_PPLIB_ACPClk_Voltage_Limit_Record entries[] __counted_by(numEntries); + }ATOM_PPLIB_ACPClk_Voltage_Limit_Table; + + typedef struct _ATOM_PPLIB_ACP_Table +@@ -743,9 +750,9 @@ typedef struct ATOM_PPLIB_VQ_Budgeting_Record{ + } ATOM_PPLIB_VQ_Budgeting_Record; + + typedef struct ATOM_PPLIB_VQ_Budgeting_Table { +- UCHAR revid; +- UCHAR numEntries; +- ATOM_PPLIB_VQ_Budgeting_Record entries[1]; ++ UCHAR revid; ++ UCHAR numEntries; ++ ATOM_PPLIB_VQ_Budgeting_Record entries[] __counted_by(numEntries); + } ATOM_PPLIB_VQ_Budgeting_Table; + + #pragma pack() +diff --git a/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c b/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c +index 65333141b1c1b..5a2247018229c 100644 +--- a/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c ++++ b/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c +@@ -323,6 +323,18 @@ static int smu_dpm_set_umsch_mm_enable(struct smu_context *smu, + return ret; + } + ++static int smu_set_mall_enable(struct smu_context *smu) ++{ ++ int ret = 0; ++ ++ if (!smu->ppt_funcs->set_mall_enable) ++ return 0; ++ ++ ret = smu->ppt_funcs->set_mall_enable(smu); ++ ++ return ret; ++} ++ + /** + * smu_dpm_set_power_gate - power gate/ungate the specific IP block + * +@@ -1785,6 +1797,7 @@ static int smu_hw_init(void *handle) + smu_dpm_set_jpeg_enable(smu, true); + smu_dpm_set_vpe_enable(smu, true); + smu_dpm_set_umsch_mm_enable(smu, true); ++ smu_set_mall_enable(smu); + smu_set_gfx_cgpg(smu, true); + } + +diff --git a/drivers/gpu/drm/amd/pm/swsmu/inc/amdgpu_smu.h b/drivers/gpu/drm/amd/pm/swsmu/inc/amdgpu_smu.h +index 1fa81575788c5..8667e8c9d7e7c 100644 +--- a/drivers/gpu/drm/amd/pm/swsmu/inc/amdgpu_smu.h ++++ b/drivers/gpu/drm/amd/pm/swsmu/inc/amdgpu_smu.h +@@ -1391,6 +1391,11 @@ struct pptable_funcs { + */ + int (*dpm_set_umsch_mm_enable)(struct smu_context *smu, bool enable); + ++ /** ++ * @set_mall_enable: Init MALL power gating control. ++ */ ++ int (*set_mall_enable)(struct smu_context *smu); ++ + /** + * @notify_rlc_state: Notify RLC power state to SMU. + */ +diff --git a/drivers/gpu/drm/amd/pm/swsmu/inc/pmfw_if/smu_v14_0_0_ppsmc.h b/drivers/gpu/drm/amd/pm/swsmu/inc/pmfw_if/smu_v14_0_0_ppsmc.h +index c4dc5881d8df0..e7f5ef49049f9 100644 +--- a/drivers/gpu/drm/amd/pm/swsmu/inc/pmfw_if/smu_v14_0_0_ppsmc.h ++++ b/drivers/gpu/drm/amd/pm/swsmu/inc/pmfw_if/smu_v14_0_0_ppsmc.h +@@ -106,8 +106,8 @@ + #define PPSMC_MSG_DisableLSdma 0x35 ///< Disable LSDMA + #define PPSMC_MSG_SetSoftMaxVpe 0x36 ///< + #define PPSMC_MSG_SetSoftMinVpe 0x37 ///< +-#define PPSMC_MSG_AllocMALLCache 0x38 ///< Allocating MALL Cache +-#define PPSMC_MSG_ReleaseMALLCache 0x39 ///< Releasing MALL Cache ++#define PPSMC_MSG_MALLPowerController 0x38 ///< Set MALL control ++#define PPSMC_MSG_MALLPowerState 0x39 ///< Enter/Exit MALL PG + #define PPSMC_Message_Count 0x3A ///< Total number of PPSMC messages + /** @}*/ + +diff --git a/drivers/gpu/drm/amd/pm/swsmu/inc/smu_types.h b/drivers/gpu/drm/amd/pm/swsmu/inc/smu_types.h +index af427cc7dbb84..4a7404856b960 100644 +--- a/drivers/gpu/drm/amd/pm/swsmu/inc/smu_types.h ++++ b/drivers/gpu/drm/amd/pm/swsmu/inc/smu_types.h +@@ -272,7 +272,9 @@ + __SMU_DUMMY_MAP(SetSoftMinVpe), \ + __SMU_DUMMY_MAP(GetMetricsVersion), \ + __SMU_DUMMY_MAP(EnableUCLKShadow), \ +- __SMU_DUMMY_MAP(RmaDueToBadPageThreshold), ++ __SMU_DUMMY_MAP(RmaDueToBadPageThreshold), \ ++ __SMU_DUMMY_MAP(MALLPowerController), \ ++ __SMU_DUMMY_MAP(MALLPowerState), + + #undef __SMU_DUMMY_MAP + #define __SMU_DUMMY_MAP(type) SMU_MSG_##type +diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu14/smu_v14_0_0_ppt.c b/drivers/gpu/drm/amd/pm/swsmu/smu14/smu_v14_0_0_ppt.c +index 63399c00cc28f..20f3861b5eeac 100644 +--- a/drivers/gpu/drm/amd/pm/swsmu/smu14/smu_v14_0_0_ppt.c ++++ b/drivers/gpu/drm/amd/pm/swsmu/smu14/smu_v14_0_0_ppt.c +@@ -52,6 +52,19 @@ + #define mmMP1_SMN_C2PMSG_90 0x029a + #define mmMP1_SMN_C2PMSG_90_BASE_IDX 0 + ++/* MALLPowerController message arguments (Defines for the Cache mode control) */ ++#define SMU_MALL_PMFW_CONTROL 0 ++#define SMU_MALL_DRIVER_CONTROL 1 ++ ++/* ++ * MALLPowerState message arguments ++ * (Defines for the Allocate/Release Cache mode if in driver mode) ++ */ ++#define SMU_MALL_EXIT_PG 0 ++#define SMU_MALL_ENTER_PG 1 ++ ++#define SMU_MALL_PG_CONFIG_DEFAULT SMU_MALL_PG_CONFIG_DRIVER_CONTROL_ALWAYS_ON ++ + #define FEATURE_MASK(feature) (1ULL << feature) + #define SMC_DPM_FEATURE ( \ + FEATURE_MASK(FEATURE_CCLK_DPM_BIT) | \ +@@ -66,6 +79,12 @@ + FEATURE_MASK(FEATURE_GFX_DPM_BIT) | \ + FEATURE_MASK(FEATURE_VPE_DPM_BIT)) + ++enum smu_mall_pg_config { ++ SMU_MALL_PG_CONFIG_PMFW_CONTROL = 0, ++ SMU_MALL_PG_CONFIG_DRIVER_CONTROL_ALWAYS_ON = 1, ++ SMU_MALL_PG_CONFIG_DRIVER_CONTROL_ALWAYS_OFF = 2, ++}; ++ + static struct cmn2asic_msg_mapping smu_v14_0_0_message_map[SMU_MSG_MAX_COUNT] = { + MSG_MAP(TestMessage, PPSMC_MSG_TestMessage, 1), + MSG_MAP(GetSmuVersion, PPSMC_MSG_GetPmfwVersion, 1), +@@ -113,6 +132,8 @@ static struct cmn2asic_msg_mapping smu_v14_0_0_message_map[SMU_MSG_MAX_COUNT] = + MSG_MAP(PowerDownUmsch, PPSMC_MSG_PowerDownUmsch, 1), + MSG_MAP(SetSoftMaxVpe, PPSMC_MSG_SetSoftMaxVpe, 1), + MSG_MAP(SetSoftMinVpe, PPSMC_MSG_SetSoftMinVpe, 1), ++ MSG_MAP(MALLPowerController, PPSMC_MSG_MALLPowerController, 1), ++ MSG_MAP(MALLPowerState, PPSMC_MSG_MALLPowerState, 1), + }; + + static struct cmn2asic_mapping smu_v14_0_0_feature_mask_map[SMU_FEATURE_COUNT] = { +@@ -1417,6 +1438,57 @@ static int smu_v14_0_common_get_dpm_table(struct smu_context *smu, struct dpm_cl + return 0; + } + ++static int smu_v14_0_1_init_mall_power_gating(struct smu_context *smu, enum smu_mall_pg_config pg_config) ++{ ++ struct amdgpu_device *adev = smu->adev; ++ int ret = 0; ++ ++ if (pg_config == SMU_MALL_PG_CONFIG_PMFW_CONTROL) { ++ ret = smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_MALLPowerController, ++ SMU_MALL_PMFW_CONTROL, NULL); ++ if (ret) { ++ dev_err(adev->dev, "Init MALL PMFW CONTROL Failure\n"); ++ return ret; ++ } ++ } else { ++ ret = smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_MALLPowerController, ++ SMU_MALL_DRIVER_CONTROL, NULL); ++ if (ret) { ++ dev_err(adev->dev, "Init MALL Driver CONTROL Failure\n"); ++ return ret; ++ } ++ ++ if (pg_config == SMU_MALL_PG_CONFIG_DRIVER_CONTROL_ALWAYS_ON) { ++ ret = smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_MALLPowerState, ++ SMU_MALL_EXIT_PG, NULL); ++ if (ret) { ++ dev_err(adev->dev, "EXIT MALL PG Failure\n"); ++ return ret; ++ } ++ } else if (pg_config == SMU_MALL_PG_CONFIG_DRIVER_CONTROL_ALWAYS_OFF) { ++ ret = smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_MALLPowerState, ++ SMU_MALL_ENTER_PG, NULL); ++ if (ret) { ++ dev_err(adev->dev, "Enter MALL PG Failure\n"); ++ return ret; ++ } ++ } ++ } ++ ++ return ret; ++} ++ ++static int smu_v14_0_common_set_mall_enable(struct smu_context *smu) ++{ ++ enum smu_mall_pg_config pg_config = SMU_MALL_PG_CONFIG_DEFAULT; ++ int ret = 0; ++ ++ if (amdgpu_ip_version(smu->adev, MP1_HWIP, 0) == IP_VERSION(14, 0, 1)) ++ ret = smu_v14_0_1_init_mall_power_gating(smu, pg_config); ++ ++ return ret; ++} ++ + static const struct pptable_funcs smu_v14_0_0_ppt_funcs = { + .check_fw_status = smu_v14_0_check_fw_status, + .check_fw_version = smu_v14_0_check_fw_version, +@@ -1448,6 +1520,7 @@ static const struct pptable_funcs smu_v14_0_0_ppt_funcs = { + .dpm_set_vpe_enable = smu_v14_0_0_set_vpe_enable, + .dpm_set_umsch_mm_enable = smu_v14_0_0_set_umsch_mm_enable, + .get_dpm_clock_table = smu_v14_0_common_get_dpm_table, ++ .set_mall_enable = smu_v14_0_common_set_mall_enable, + }; + + static void smu_v14_0_0_set_smu_mailbox_registers(struct smu_context *smu) +diff --git a/drivers/gpu/drm/drm_panel_orientation_quirks.c b/drivers/gpu/drm/drm_panel_orientation_quirks.c +index 426bbee2d9f5e..5db52d6c5c35c 100644 +--- a/drivers/gpu/drm/drm_panel_orientation_quirks.c ++++ b/drivers/gpu/drm/drm_panel_orientation_quirks.c +@@ -202,6 +202,12 @@ static const struct dmi_system_id orientation_data[] = { + DMI_MATCH(DMI_BOARD_NAME, "NEXT"), + }, + .driver_data = (void *)&lcd800x1280_rightside_up, ++ }, { /* AYA NEO KUN */ ++ .matches = { ++ DMI_EXACT_MATCH(DMI_BOARD_VENDOR, "AYANEO"), ++ DMI_MATCH(DMI_BOARD_NAME, "KUN"), ++ }, ++ .driver_data = (void *)&lcd1600x2560_rightside_up, + }, { /* Chuwi HiBook (CWI514) */ + .matches = { + DMI_MATCH(DMI_BOARD_VENDOR, "Hampoo"), +diff --git a/drivers/gpu/drm/exynos/exynos_dp.c b/drivers/gpu/drm/exynos/exynos_dp.c +index f48c4343f4690..3e6d4c6aa877e 100644 +--- a/drivers/gpu/drm/exynos/exynos_dp.c ++++ b/drivers/gpu/drm/exynos/exynos_dp.c +@@ -285,7 +285,6 @@ struct platform_driver dp_driver = { + .remove_new = exynos_dp_remove, + .driver = { + .name = "exynos-dp", +- .owner = THIS_MODULE, + .pm = pm_ptr(&exynos_dp_pm_ops), + .of_match_table = exynos_dp_match, + }, +diff --git a/drivers/gpu/drm/mediatek/mtk_drm_drv.c b/drivers/gpu/drm/mediatek/mtk_drm_drv.c +index 74832c2130921..0b570e194079a 100644 +--- a/drivers/gpu/drm/mediatek/mtk_drm_drv.c ++++ b/drivers/gpu/drm/mediatek/mtk_drm_drv.c +@@ -950,6 +950,13 @@ static void mtk_drm_remove(struct platform_device *pdev) + of_node_put(private->comp_node[i]); + } + ++static void mtk_drm_shutdown(struct platform_device *pdev) ++{ ++ struct mtk_drm_private *private = platform_get_drvdata(pdev); ++ ++ drm_atomic_helper_shutdown(private->drm); ++} ++ + static int mtk_drm_sys_prepare(struct device *dev) + { + struct mtk_drm_private *private = dev_get_drvdata(dev); +@@ -981,6 +988,7 @@ static const struct dev_pm_ops mtk_drm_pm_ops = { + static struct platform_driver mtk_drm_platform_driver = { + .probe = mtk_drm_probe, + .remove_new = mtk_drm_remove, ++ .shutdown = mtk_drm_shutdown, + .driver = { + .name = "mediatek-drm", + .pm = &mtk_drm_pm_ops, +diff --git a/drivers/gpu/drm/radeon/radeon_gem.c b/drivers/gpu/drm/radeon/radeon_gem.c +index 3fec3acdaf284..27225d1fe8d2e 100644 +--- a/drivers/gpu/drm/radeon/radeon_gem.c ++++ b/drivers/gpu/drm/radeon/radeon_gem.c +@@ -641,7 +641,7 @@ static void radeon_gem_va_update_vm(struct radeon_device *rdev, + if (r) + goto error_unlock; + +- if (bo_va->it.start) ++ if (bo_va->it.start && bo_va->bo) + r = radeon_vm_bo_update(rdev, bo_va, bo_va->bo->tbo.resource); + + error_unlock: +diff --git a/drivers/gpu/drm/renesas/shmobile/shmob_drm_drv.c b/drivers/gpu/drm/renesas/shmobile/shmob_drm_drv.c +index e83c3e52251de..0250d5f00bf10 100644 +--- a/drivers/gpu/drm/renesas/shmobile/shmob_drm_drv.c ++++ b/drivers/gpu/drm/renesas/shmobile/shmob_drm_drv.c +@@ -171,6 +171,13 @@ static void shmob_drm_remove(struct platform_device *pdev) + drm_kms_helper_poll_fini(ddev); + } + ++static void shmob_drm_shutdown(struct platform_device *pdev) ++{ ++ struct shmob_drm_device *sdev = platform_get_drvdata(pdev); ++ ++ drm_atomic_helper_shutdown(&sdev->ddev); ++} ++ + static int shmob_drm_probe(struct platform_device *pdev) + { + struct shmob_drm_platform_data *pdata = pdev->dev.platform_data; +@@ -273,6 +280,7 @@ static const struct of_device_id shmob_drm_of_table[] __maybe_unused = { + static struct platform_driver shmob_drm_platform_driver = { + .probe = shmob_drm_probe, + .remove_new = shmob_drm_remove, ++ .shutdown = shmob_drm_shutdown, + .driver = { + .name = "shmob-drm", + .of_match_table = of_match_ptr(shmob_drm_of_table), +diff --git a/drivers/gpu/drm/vmwgfx/Kconfig b/drivers/gpu/drm/vmwgfx/Kconfig +index faddae3d6ac2e..6f1ac940cbae7 100644 +--- a/drivers/gpu/drm/vmwgfx/Kconfig ++++ b/drivers/gpu/drm/vmwgfx/Kconfig +@@ -2,7 +2,7 @@ + config DRM_VMWGFX + tristate "DRM driver for VMware Virtual GPU" + depends on DRM && PCI && MMU +- depends on X86 || ARM64 ++ depends on (X86 && HYPERVISOR_GUEST) || ARM64 + select DRM_TTM + select DRM_TTM_HELPER + select MAPPING_DIRTY_HELPERS +diff --git a/drivers/hid/hid-debug.c b/drivers/hid/hid-debug.c +index 7dd83ec74f8a9..5302bfd527d86 100644 +--- a/drivers/hid/hid-debug.c ++++ b/drivers/hid/hid-debug.c +@@ -974,6 +974,8 @@ static const char *keys[KEY_MAX + 1] = { + [KEY_CAMERA_ACCESS_ENABLE] = "CameraAccessEnable", + [KEY_CAMERA_ACCESS_DISABLE] = "CameraAccessDisable", + [KEY_CAMERA_ACCESS_TOGGLE] = "CameraAccessToggle", ++ [KEY_ACCESSIBILITY] = "Accessibility", ++ [KEY_DO_NOT_DISTURB] = "DoNotDisturb", + [KEY_DICTATE] = "Dictate", + [KEY_MICMUTE] = "MicrophoneMute", + [KEY_BRIGHTNESS_MIN] = "BrightnessMin", +diff --git a/drivers/hid/hid-ids.h b/drivers/hid/hid-ids.h +index 68b0f39deaa9a..8eb073dea3593 100644 +--- a/drivers/hid/hid-ids.h ++++ b/drivers/hid/hid-ids.h +@@ -421,6 +421,8 @@ + #define I2C_DEVICE_ID_HP_SPECTRE_X360_13_AW0020NG 0x29DF + #define I2C_DEVICE_ID_ASUS_TP420IA_TOUCHSCREEN 0x2BC8 + #define I2C_DEVICE_ID_ASUS_GV301RA_TOUCHSCREEN 0x2C82 ++#define I2C_DEVICE_ID_ASUS_UX3402_TOUCHSCREEN 0x2F2C ++#define I2C_DEVICE_ID_ASUS_UX6404_TOUCHSCREEN 0x4116 + #define USB_DEVICE_ID_ASUS_UX550VE_TOUCHSCREEN 0x2544 + #define USB_DEVICE_ID_ASUS_UX550_TOUCHSCREEN 0x2706 + #define I2C_DEVICE_ID_SURFACE_GO_TOUCHSCREEN 0x261A +diff --git a/drivers/hid/hid-input.c b/drivers/hid/hid-input.c +index e03d300d2bac4..c9094a4f281e9 100644 +--- a/drivers/hid/hid-input.c ++++ b/drivers/hid/hid-input.c +@@ -377,6 +377,10 @@ static const struct hid_device_id hid_battery_quirks[] = { + HID_BATTERY_QUIRK_IGNORE }, + { HID_I2C_DEVICE(USB_VENDOR_ID_ELAN, I2C_DEVICE_ID_ASUS_GV301RA_TOUCHSCREEN), + HID_BATTERY_QUIRK_IGNORE }, ++ { HID_I2C_DEVICE(USB_VENDOR_ID_ELAN, I2C_DEVICE_ID_ASUS_UX3402_TOUCHSCREEN), ++ HID_BATTERY_QUIRK_IGNORE }, ++ { HID_I2C_DEVICE(USB_VENDOR_ID_ELAN, I2C_DEVICE_ID_ASUS_UX6404_TOUCHSCREEN), ++ HID_BATTERY_QUIRK_IGNORE }, + { HID_USB_DEVICE(USB_VENDOR_ID_ELAN, USB_DEVICE_ID_ASUS_UX550_TOUCHSCREEN), + HID_BATTERY_QUIRK_IGNORE }, + { HID_USB_DEVICE(USB_VENDOR_ID_ELAN, USB_DEVICE_ID_ASUS_UX550VE_TOUCHSCREEN), +@@ -833,9 +837,18 @@ static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_fiel + break; + } + ++ if ((usage->hid & 0xf0) == 0x90) { /* SystemControl*/ ++ switch (usage->hid & 0xf) { ++ case 0xb: map_key_clear(KEY_DO_NOT_DISTURB); break; ++ default: goto ignore; ++ } ++ break; ++ } ++ + if ((usage->hid & 0xf0) == 0xa0) { /* SystemControl */ + switch (usage->hid & 0xf) { + case 0x9: map_key_clear(KEY_MICMUTE); break; ++ case 0xa: map_key_clear(KEY_ACCESSIBILITY); break; + default: goto ignore; + } + break; +diff --git a/drivers/input/joystick/xpad.c b/drivers/input/joystick/xpad.c +index 6fadaddb2b908..3a5af0909233a 100644 +--- a/drivers/input/joystick/xpad.c ++++ b/drivers/input/joystick/xpad.c +@@ -209,6 +209,7 @@ static const struct xpad_device { + { 0x0738, 0xf738, "Super SFIV FightStick TE S", 0, XTYPE_XBOX360 }, + { 0x07ff, 0xffff, "Mad Catz GamePad", 0, XTYPE_XBOX360 }, + { 0x0b05, 0x1a38, "ASUS ROG RAIKIRI", 0, XTYPE_XBOXONE }, ++ { 0x0b05, 0x1abb, "ASUS ROG RAIKIRI PRO", 0, XTYPE_XBOXONE }, + { 0x0c12, 0x0005, "Intec wireless", 0, XTYPE_XBOX }, + { 0x0c12, 0x8801, "Nyko Xbox Controller", 0, XTYPE_XBOX }, + { 0x0c12, 0x8802, "Zeroplus Xbox Controller", 0, XTYPE_XBOX }, +diff --git a/drivers/input/mouse/elantech.c b/drivers/input/mouse/elantech.c +index 4e38229404b4b..b4723ea395eb9 100644 +--- a/drivers/input/mouse/elantech.c ++++ b/drivers/input/mouse/elantech.c +@@ -1476,16 +1476,47 @@ static void elantech_disconnect(struct psmouse *psmouse) + psmouse->private = NULL; + } + ++/* ++ * Some hw_version 4 models fail to properly activate absolute mode on ++ * resume without going through disable/enable cycle. ++ */ ++static const struct dmi_system_id elantech_needs_reenable[] = { ++#if defined(CONFIG_DMI) && defined(CONFIG_X86) ++ { ++ /* Lenovo N24 */ ++ .matches = { ++ DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), ++ DMI_MATCH(DMI_PRODUCT_NAME, "81AF"), ++ }, ++ }, ++#endif ++ { } ++}; ++ + /* + * Put the touchpad back into absolute mode when reconnecting + */ + static int elantech_reconnect(struct psmouse *psmouse) + { ++ int err; ++ + psmouse_reset(psmouse); + + if (elantech_detect(psmouse, 0)) + return -1; + ++ if (dmi_check_system(elantech_needs_reenable)) { ++ err = ps2_command(&psmouse->ps2dev, NULL, PSMOUSE_CMD_DISABLE); ++ if (err) ++ psmouse_warn(psmouse, "failed to deactivate mouse on %s: %d\n", ++ psmouse->ps2dev.serio->phys, err); ++ ++ err = ps2_command(&psmouse->ps2dev, NULL, PSMOUSE_CMD_ENABLE); ++ if (err) ++ psmouse_warn(psmouse, "failed to reactivate mouse on %s: %d\n", ++ psmouse->ps2dev.serio->phys, err); ++ } ++ + if (elantech_set_absolute_mode(psmouse)) { + psmouse_err(psmouse, + "failed to put touchpad back into absolute mode.\n"); +diff --git a/drivers/input/serio/i8042-acpipnpio.h b/drivers/input/serio/i8042-acpipnpio.h +index dfc6c581873b7..5b50475ec4140 100644 +--- a/drivers/input/serio/i8042-acpipnpio.h ++++ b/drivers/input/serio/i8042-acpipnpio.h +@@ -76,7 +76,7 @@ static inline void i8042_write_command(int val) + #define SERIO_QUIRK_PROBE_DEFER BIT(5) + #define SERIO_QUIRK_RESET_ALWAYS BIT(6) + #define SERIO_QUIRK_RESET_NEVER BIT(7) +-#define SERIO_QUIRK_DIECT BIT(8) ++#define SERIO_QUIRK_DIRECT BIT(8) + #define SERIO_QUIRK_DUMBKBD BIT(9) + #define SERIO_QUIRK_NOLOOP BIT(10) + #define SERIO_QUIRK_NOTIMEOUT BIT(11) +@@ -1332,6 +1332,20 @@ static const struct dmi_system_id i8042_dmi_quirk_table[] __initconst = { + .driver_data = (void *)(SERIO_QUIRK_NOMUX | SERIO_QUIRK_RESET_ALWAYS | + SERIO_QUIRK_NOLOOP | SERIO_QUIRK_NOPNP) + }, ++ { ++ /* ++ * The Ayaneo Kun is a handheld device where some the buttons ++ * are handled by an AT keyboard. The keyboard is usually ++ * detected as raw, but sometimes, usually after a cold boot, ++ * it is detected as translated. Make sure that the keyboard ++ * is always in raw mode. ++ */ ++ .matches = { ++ DMI_EXACT_MATCH(DMI_BOARD_VENDOR, "AYANEO"), ++ DMI_MATCH(DMI_BOARD_NAME, "KUN"), ++ }, ++ .driver_data = (void *)(SERIO_QUIRK_DIRECT) ++ }, + { } + }; + +@@ -1655,7 +1669,7 @@ static void __init i8042_check_quirks(void) + if (quirks & SERIO_QUIRK_RESET_NEVER) + i8042_reset = I8042_RESET_NEVER; + } +- if (quirks & SERIO_QUIRK_DIECT) ++ if (quirks & SERIO_QUIRK_DIRECT) + i8042_direct = true; + if (quirks & SERIO_QUIRK_DUMBKBD) + i8042_dumbkbd = true; +diff --git a/drivers/input/touchscreen/ads7846.c b/drivers/input/touchscreen/ads7846.c +index d2bbb436a77df..4d13db13b9e57 100644 +--- a/drivers/input/touchscreen/ads7846.c ++++ b/drivers/input/touchscreen/ads7846.c +@@ -1111,6 +1111,16 @@ static const struct of_device_id ads7846_dt_ids[] = { + }; + MODULE_DEVICE_TABLE(of, ads7846_dt_ids); + ++static const struct spi_device_id ads7846_spi_ids[] = { ++ { "tsc2046", 7846 }, ++ { "ads7843", 7843 }, ++ { "ads7845", 7845 }, ++ { "ads7846", 7846 }, ++ { "ads7873", 7873 }, ++ { }, ++}; ++MODULE_DEVICE_TABLE(spi, ads7846_spi_ids); ++ + static const struct ads7846_platform_data *ads7846_get_props(struct device *dev) + { + struct ads7846_platform_data *pdata; +@@ -1386,10 +1396,10 @@ static struct spi_driver ads7846_driver = { + }, + .probe = ads7846_probe, + .remove = ads7846_remove, ++ .id_table = ads7846_spi_ids, + }; + + module_spi_driver(ads7846_driver); + + MODULE_DESCRIPTION("ADS7846 TouchScreen Driver"); + MODULE_LICENSE("GPL"); +-MODULE_ALIAS("spi:ads7846"); +diff --git a/drivers/input/touchscreen/silead.c b/drivers/input/touchscreen/silead.c +index 62f562ad50263..050fa9ca4ec94 100644 +--- a/drivers/input/touchscreen/silead.c ++++ b/drivers/input/touchscreen/silead.c +@@ -71,7 +71,6 @@ struct silead_ts_data { + struct regulator_bulk_data regulators[2]; + char fw_name[64]; + struct touchscreen_properties prop; +- u32 max_fingers; + u32 chip_id; + struct input_mt_pos pos[SILEAD_MAX_FINGERS]; + int slots[SILEAD_MAX_FINGERS]; +@@ -136,7 +135,7 @@ static int silead_ts_request_input_dev(struct silead_ts_data *data) + touchscreen_parse_properties(data->input, true, &data->prop); + silead_apply_efi_fw_min_max(data); + +- input_mt_init_slots(data->input, data->max_fingers, ++ input_mt_init_slots(data->input, SILEAD_MAX_FINGERS, + INPUT_MT_DIRECT | INPUT_MT_DROP_UNUSED | + INPUT_MT_TRACK); + +@@ -256,10 +255,10 @@ static void silead_ts_read_data(struct i2c_client *client) + return; + } + +- if (buf[0] > data->max_fingers) { ++ if (buf[0] > SILEAD_MAX_FINGERS) { + dev_warn(dev, "More touches reported then supported %d > %d\n", +- buf[0], data->max_fingers); +- buf[0] = data->max_fingers; ++ buf[0], SILEAD_MAX_FINGERS); ++ buf[0] = SILEAD_MAX_FINGERS; + } + + if (silead_ts_handle_pen_data(data, buf)) +@@ -315,7 +314,6 @@ static void silead_ts_read_data(struct i2c_client *client) + + static int silead_ts_init(struct i2c_client *client) + { +- struct silead_ts_data *data = i2c_get_clientdata(client); + int error; + + error = i2c_smbus_write_byte_data(client, SILEAD_REG_RESET, +@@ -325,7 +323,7 @@ static int silead_ts_init(struct i2c_client *client) + usleep_range(SILEAD_CMD_SLEEP_MIN, SILEAD_CMD_SLEEP_MAX); + + error = i2c_smbus_write_byte_data(client, SILEAD_REG_TOUCH_NR, +- data->max_fingers); ++ SILEAD_MAX_FINGERS); + if (error) + goto i2c_write_err; + usleep_range(SILEAD_CMD_SLEEP_MIN, SILEAD_CMD_SLEEP_MAX); +@@ -591,13 +589,6 @@ static void silead_ts_read_props(struct i2c_client *client) + const char *str; + int error; + +- error = device_property_read_u32(dev, "silead,max-fingers", +- &data->max_fingers); +- if (error) { +- dev_dbg(dev, "Max fingers read error %d\n", error); +- data->max_fingers = 5; /* Most devices handle up-to 5 fingers */ +- } +- + error = device_property_read_string(dev, "firmware-name", &str); + if (!error) + snprintf(data->fw_name, sizeof(data->fw_name), +diff --git a/drivers/misc/mei/main.c b/drivers/misc/mei/main.c +index 79e6f3c1341fe..40c3fe26f76df 100644 +--- a/drivers/misc/mei/main.c ++++ b/drivers/misc/mei/main.c +@@ -329,7 +329,7 @@ static ssize_t mei_write(struct file *file, const char __user *ubuf, + } + + if (!mei_cl_is_connected(cl)) { +- cl_err(dev, cl, "is not connected"); ++ cl_dbg(dev, cl, "is not connected"); + rets = -ENODEV; + goto out; + } +diff --git a/drivers/net/can/usb/kvaser_usb/kvaser_usb_core.c b/drivers/net/can/usb/kvaser_usb/kvaser_usb_core.c +index ffc3e93292501..024169461cad0 100644 +--- a/drivers/net/can/usb/kvaser_usb/kvaser_usb_core.c ++++ b/drivers/net/can/usb/kvaser_usb/kvaser_usb_core.c +@@ -295,7 +295,7 @@ int kvaser_usb_send_cmd_async(struct kvaser_usb_net_priv *priv, void *cmd, + } + usb_free_urb(urb); + +- return 0; ++ return err; + } + + int kvaser_usb_can_rx_over_error(struct net_device *netdev) +diff --git a/drivers/net/ethernet/ibm/ibmvnic.c b/drivers/net/ethernet/ibm/ibmvnic.c +index 722bb724361c2..664baedfe7d13 100644 +--- a/drivers/net/ethernet/ibm/ibmvnic.c ++++ b/drivers/net/ethernet/ibm/ibmvnic.c +@@ -2478,6 +2478,18 @@ static netdev_tx_t ibmvnic_xmit(struct sk_buff *skb, struct net_device *netdev) + (tx_pool->consumer_index + 1) % tx_pool->num_buffers; + + tx_buff = &tx_pool->tx_buff[bufidx]; ++ ++ /* Sanity checks on our free map to make sure it points to an index ++ * that is not being occupied by another skb. If skb memory is ++ * not freed then we see congestion control kick in and halt tx. ++ */ ++ if (unlikely(tx_buff->skb)) { ++ dev_warn_ratelimited(dev, "TX free map points to untracked skb (%s %d idx=%d)\n", ++ skb_is_gso(skb) ? "tso_pool" : "tx_pool", ++ queue_num, bufidx); ++ dev_kfree_skb_any(tx_buff->skb); ++ } ++ + tx_buff->skb = skb; + tx_buff->index = bufidx; + tx_buff->pool_index = queue_num; +diff --git a/drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c b/drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c +index cebc79a710ec2..6340e5e61a7da 100644 +--- a/drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c ++++ b/drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c +@@ -6906,6 +6906,7 @@ static int mvpp2_port_probe(struct platform_device *pdev, + /* 9704 == 9728 - 20 and rounding to 8 */ + dev->max_mtu = MVPP2_BM_JUMBO_PKT_SIZE; + device_set_node(&dev->dev, port_fwnode); ++ dev->dev_port = port->id; + + port->pcs_gmac.ops = &mvpp2_phylink_gmac_pcs_ops; + port->pcs_gmac.neg_mode = true; +diff --git a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_common.c b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_common.c +index a85ac039d779b..87d5776e3b88e 100644 +--- a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_common.c ++++ b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_common.c +@@ -648,14 +648,14 @@ int otx2_txschq_config(struct otx2_nic *pfvf, int lvl, int prio, bool txschq_for + } else if (lvl == NIX_TXSCH_LVL_TL4) { + parent = schq_list[NIX_TXSCH_LVL_TL3][prio]; + req->reg[0] = NIX_AF_TL4X_PARENT(schq); +- req->regval[0] = parent << 16; ++ req->regval[0] = (u64)parent << 16; + req->num_regs++; + req->reg[1] = NIX_AF_TL4X_SCHEDULE(schq); + req->regval[1] = dwrr_val; + } else if (lvl == NIX_TXSCH_LVL_TL3) { + parent = schq_list[NIX_TXSCH_LVL_TL2][prio]; + req->reg[0] = NIX_AF_TL3X_PARENT(schq); +- req->regval[0] = parent << 16; ++ req->regval[0] = (u64)parent << 16; + req->num_regs++; + req->reg[1] = NIX_AF_TL3X_SCHEDULE(schq); + req->regval[1] = dwrr_val; +@@ -670,11 +670,11 @@ int otx2_txschq_config(struct otx2_nic *pfvf, int lvl, int prio, bool txschq_for + } else if (lvl == NIX_TXSCH_LVL_TL2) { + parent = schq_list[NIX_TXSCH_LVL_TL1][prio]; + req->reg[0] = NIX_AF_TL2X_PARENT(schq); +- req->regval[0] = parent << 16; ++ req->regval[0] = (u64)parent << 16; + + req->num_regs++; + req->reg[1] = NIX_AF_TL2X_SCHEDULE(schq); +- req->regval[1] = TXSCH_TL1_DFLT_RR_PRIO << 24 | dwrr_val; ++ req->regval[1] = (u64)hw->txschq_aggr_lvl_rr_prio << 24 | dwrr_val; + + if (lvl == hw->txschq_link_cfg_lvl) { + req->num_regs++; +@@ -698,7 +698,7 @@ int otx2_txschq_config(struct otx2_nic *pfvf, int lvl, int prio, bool txschq_for + + req->num_regs++; + req->reg[1] = NIX_AF_TL1X_TOPOLOGY(schq); +- req->regval[1] = (TXSCH_TL1_DFLT_RR_PRIO << 1); ++ req->regval[1] = hw->txschq_aggr_lvl_rr_prio << 1; + + req->num_regs++; + req->reg[2] = NIX_AF_TL1X_CIR(schq); +diff --git a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_reg.h b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_reg.h +index 45a32e4b49d1c..e3aee6e362151 100644 +--- a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_reg.h ++++ b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_reg.h +@@ -139,33 +139,34 @@ + #define NIX_LF_CINTX_ENA_W1C(a) (NIX_LFBASE | 0xD50 | (a) << 12) + + /* NIX AF transmit scheduler registers */ +-#define NIX_AF_SMQX_CFG(a) (0x700 | (a) << 16) +-#define NIX_AF_TL1X_SCHEDULE(a) (0xC00 | (a) << 16) +-#define NIX_AF_TL1X_CIR(a) (0xC20 | (a) << 16) +-#define NIX_AF_TL1X_TOPOLOGY(a) (0xC80 | (a) << 16) +-#define NIX_AF_TL2X_PARENT(a) (0xE88 | (a) << 16) +-#define NIX_AF_TL2X_SCHEDULE(a) (0xE00 | (a) << 16) +-#define NIX_AF_TL2X_TOPOLOGY(a) (0xE80 | (a) << 16) +-#define NIX_AF_TL2X_CIR(a) (0xE20 | (a) << 16) +-#define NIX_AF_TL2X_PIR(a) (0xE30 | (a) << 16) +-#define NIX_AF_TL3X_PARENT(a) (0x1088 | (a) << 16) +-#define NIX_AF_TL3X_SCHEDULE(a) (0x1000 | (a) << 16) +-#define NIX_AF_TL3X_SHAPE(a) (0x1010 | (a) << 16) +-#define NIX_AF_TL3X_CIR(a) (0x1020 | (a) << 16) +-#define NIX_AF_TL3X_PIR(a) (0x1030 | (a) << 16) +-#define NIX_AF_TL3X_TOPOLOGY(a) (0x1080 | (a) << 16) +-#define NIX_AF_TL4X_PARENT(a) (0x1288 | (a) << 16) +-#define NIX_AF_TL4X_SCHEDULE(a) (0x1200 | (a) << 16) +-#define NIX_AF_TL4X_SHAPE(a) (0x1210 | (a) << 16) +-#define NIX_AF_TL4X_CIR(a) (0x1220 | (a) << 16) +-#define NIX_AF_TL4X_PIR(a) (0x1230 | (a) << 16) +-#define NIX_AF_TL4X_TOPOLOGY(a) (0x1280 | (a) << 16) +-#define NIX_AF_MDQX_SCHEDULE(a) (0x1400 | (a) << 16) +-#define NIX_AF_MDQX_SHAPE(a) (0x1410 | (a) << 16) +-#define NIX_AF_MDQX_CIR(a) (0x1420 | (a) << 16) +-#define NIX_AF_MDQX_PIR(a) (0x1430 | (a) << 16) +-#define NIX_AF_MDQX_PARENT(a) (0x1480 | (a) << 16) +-#define NIX_AF_TL3_TL2X_LINKX_CFG(a, b) (0x1700 | (a) << 16 | (b) << 3) ++#define NIX_AF_SMQX_CFG(a) (0x700 | (u64)(a) << 16) ++#define NIX_AF_TL4X_SDP_LINK_CFG(a) (0xB10 | (u64)(a) << 16) ++#define NIX_AF_TL1X_SCHEDULE(a) (0xC00 | (u64)(a) << 16) ++#define NIX_AF_TL1X_CIR(a) (0xC20 | (u64)(a) << 16) ++#define NIX_AF_TL1X_TOPOLOGY(a) (0xC80 | (u64)(a) << 16) ++#define NIX_AF_TL2X_PARENT(a) (0xE88 | (u64)(a) << 16) ++#define NIX_AF_TL2X_SCHEDULE(a) (0xE00 | (u64)(a) << 16) ++#define NIX_AF_TL2X_TOPOLOGY(a) (0xE80 | (u64)(a) << 16) ++#define NIX_AF_TL2X_CIR(a) (0xE20 | (u64)(a) << 16) ++#define NIX_AF_TL2X_PIR(a) (0xE30 | (u64)(a) << 16) ++#define NIX_AF_TL3X_PARENT(a) (0x1088 | (u64)(a) << 16) ++#define NIX_AF_TL3X_SCHEDULE(a) (0x1000 | (u64)(a) << 16) ++#define NIX_AF_TL3X_SHAPE(a) (0x1010 | (u64)(a) << 16) ++#define NIX_AF_TL3X_CIR(a) (0x1020 | (u64)(a) << 16) ++#define NIX_AF_TL3X_PIR(a) (0x1030 | (u64)(a) << 16) ++#define NIX_AF_TL3X_TOPOLOGY(a) (0x1080 | (u64)(a) << 16) ++#define NIX_AF_TL4X_PARENT(a) (0x1288 | (u64)(a) << 16) ++#define NIX_AF_TL4X_SCHEDULE(a) (0x1200 | (u64)(a) << 16) ++#define NIX_AF_TL4X_SHAPE(a) (0x1210 | (u64)(a) << 16) ++#define NIX_AF_TL4X_CIR(a) (0x1220 | (u64)(a) << 16) ++#define NIX_AF_TL4X_PIR(a) (0x1230 | (u64)(a) << 16) ++#define NIX_AF_TL4X_TOPOLOGY(a) (0x1280 | (u64)(a) << 16) ++#define NIX_AF_MDQX_SCHEDULE(a) (0x1400 | (u64)(a) << 16) ++#define NIX_AF_MDQX_SHAPE(a) (0x1410 | (u64)(a) << 16) ++#define NIX_AF_MDQX_CIR(a) (0x1420 | (u64)(a) << 16) ++#define NIX_AF_MDQX_PIR(a) (0x1430 | (u64)(a) << 16) ++#define NIX_AF_MDQX_PARENT(a) (0x1480 | (u64)(a) << 16) ++#define NIX_AF_TL3_TL2X_LINKX_CFG(a, b) (0x1700 | (u64)(a) << 16 | (b) << 3) + + /* LMT LF registers */ + #define LMT_LFBASE BIT_ULL(RVU_FUNC_BLKADDR_SHIFT) +diff --git a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_txrx.c b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_txrx.c +index 04a49b9b545f3..0ca9f2ffd932d 100644 +--- a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_txrx.c ++++ b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_txrx.c +@@ -510,7 +510,7 @@ static int otx2_tx_napi_handler(struct otx2_nic *pfvf, + + static void otx2_adjust_adaptive_coalese(struct otx2_nic *pfvf, struct otx2_cq_poll *cq_poll) + { +- struct dim_sample dim_sample; ++ struct dim_sample dim_sample = { 0 }; + u64 rx_frames, rx_bytes; + u64 tx_frames, tx_bytes; + +diff --git a/drivers/net/ethernet/marvell/octeontx2/nic/qos.c b/drivers/net/ethernet/marvell/octeontx2/nic/qos.c +index 6cddb4da85b71..4995a2d54d7d0 100644 +--- a/drivers/net/ethernet/marvell/octeontx2/nic/qos.c ++++ b/drivers/net/ethernet/marvell/octeontx2/nic/qos.c +@@ -153,7 +153,6 @@ static void __otx2_qos_txschq_cfg(struct otx2_nic *pfvf, + num_regs++; + + otx2_config_sched_shaping(pfvf, node, cfg, &num_regs); +- + } else if (level == NIX_TXSCH_LVL_TL4) { + otx2_config_sched_shaping(pfvf, node, cfg, &num_regs); + } else if (level == NIX_TXSCH_LVL_TL3) { +@@ -176,7 +175,7 @@ static void __otx2_qos_txschq_cfg(struct otx2_nic *pfvf, + /* check if node is root */ + if (node->qid == OTX2_QOS_QID_INNER && !node->parent) { + cfg->reg[num_regs] = NIX_AF_TL2X_SCHEDULE(node->schq); +- cfg->regval[num_regs] = TXSCH_TL1_DFLT_RR_PRIO << 24 | ++ cfg->regval[num_regs] = (u64)hw->txschq_aggr_lvl_rr_prio << 24 | + mtu_to_dwrr_weight(pfvf, + pfvf->tx_max_pktlen); + num_regs++; +diff --git a/drivers/net/usb/qmi_wwan.c b/drivers/net/usb/qmi_wwan.c +index a5469cf5cf670..befbca01bfe37 100644 +--- a/drivers/net/usb/qmi_wwan.c ++++ b/drivers/net/usb/qmi_wwan.c +@@ -1380,6 +1380,8 @@ static const struct usb_device_id products[] = { + {QMI_QUIRK_SET_DTR(0x1bc7, 0x1260, 2)}, /* Telit LE910Cx */ + {QMI_QUIRK_SET_DTR(0x1bc7, 0x1261, 2)}, /* Telit LE910Cx */ + {QMI_QUIRK_SET_DTR(0x1bc7, 0x1900, 1)}, /* Telit LN940 series */ ++ {QMI_QUIRK_SET_DTR(0x1bc7, 0x3000, 0)}, /* Telit FN912 series */ ++ {QMI_QUIRK_SET_DTR(0x1bc7, 0x3001, 0)}, /* Telit FN912 series */ + {QMI_FIXED_INTF(0x1c9e, 0x9801, 3)}, /* Telewell TW-3G HSPA+ */ + {QMI_FIXED_INTF(0x1c9e, 0x9803, 4)}, /* Telewell TW-3G HSPA+ */ + {QMI_FIXED_INTF(0x1c9e, 0x9b01, 3)}, /* XS Stick W100-2 from 4G Systems */ +diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/d3.c b/drivers/net/wireless/intel/iwlwifi/mvm/d3.c +index 52518a47554e7..6f16b5b33f0c0 100644 +--- a/drivers/net/wireless/intel/iwlwifi/mvm/d3.c ++++ b/drivers/net/wireless/intel/iwlwifi/mvm/d3.c +@@ -595,6 +595,12 @@ static void iwl_mvm_wowlan_gtk_type_iter(struct ieee80211_hw *hw, + void *_data) + { + struct wowlan_key_gtk_type_iter *data = _data; ++ __le32 *cipher = NULL; ++ ++ if (key->keyidx == 4 || key->keyidx == 5) ++ cipher = &data->kek_kck_cmd->igtk_cipher; ++ if (key->keyidx == 6 || key->keyidx == 7) ++ cipher = &data->kek_kck_cmd->bigtk_cipher; + + switch (key->cipher) { + default: +@@ -606,10 +612,13 @@ static void iwl_mvm_wowlan_gtk_type_iter(struct ieee80211_hw *hw, + return; + case WLAN_CIPHER_SUITE_BIP_GMAC_256: + case WLAN_CIPHER_SUITE_BIP_GMAC_128: +- data->kek_kck_cmd->igtk_cipher = cpu_to_le32(STA_KEY_FLG_GCMP); ++ if (cipher) ++ *cipher = cpu_to_le32(STA_KEY_FLG_GCMP); + return; + case WLAN_CIPHER_SUITE_AES_CMAC: +- data->kek_kck_cmd->igtk_cipher = cpu_to_le32(STA_KEY_FLG_CCM); ++ case WLAN_CIPHER_SUITE_BIP_CMAC_256: ++ if (cipher) ++ *cipher = cpu_to_le32(STA_KEY_FLG_CCM); + return; + case WLAN_CIPHER_SUITE_CCMP: + if (!sta) +@@ -2182,7 +2191,8 @@ static bool iwl_mvm_setup_connection_keep(struct iwl_mvm *mvm, + + out: + if (iwl_fw_lookup_notif_ver(mvm->fw, LONG_GROUP, +- WOWLAN_GET_STATUSES, 0) < 10) { ++ WOWLAN_GET_STATUSES, ++ IWL_FW_CMD_VER_UNKNOWN) < 10) { + mvmvif->seqno_valid = true; + /* +0x10 because the set API expects next-to-use, not last-used */ + mvmvif->seqno = status->non_qos_seq_ctr + 0x10; +diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c b/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c +index 5f6b16d3fc8a3..81bc0878a61cc 100644 +--- a/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c ++++ b/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c +@@ -651,7 +651,7 @@ int iwl_mvm_mac_setup_register(struct iwl_mvm *mvm) + hw->wiphy->features |= NL80211_FEATURE_WFA_TPC_IE_IN_PROBES; + + if (iwl_fw_lookup_cmd_ver(mvm->fw, WOWLAN_KEK_KCK_MATERIAL, +- IWL_FW_CMD_VER_UNKNOWN) == 3) ++ IWL_FW_CMD_VER_UNKNOWN) >= 3) + hw->wiphy->flags |= WIPHY_FLAG_SUPPORTS_EXT_KEK_KCK; + + if (fw_has_api(&mvm->fw->ucode_capa, +@@ -1115,6 +1115,39 @@ static void iwl_mvm_cleanup_iterator(void *data, u8 *mac, + RCU_INIT_POINTER(mvmvif->deflink.probe_resp_data, NULL); + } + ++static void iwl_mvm_cleanup_sta_iterator(void *data, struct ieee80211_sta *sta) ++{ ++ struct iwl_mvm *mvm = data; ++ struct iwl_mvm_sta *mvm_sta; ++ struct ieee80211_vif *vif; ++ int link_id; ++ ++ mvm_sta = iwl_mvm_sta_from_mac80211(sta); ++ vif = mvm_sta->vif; ++ ++ if (!sta->valid_links) ++ return; ++ ++ for (link_id = 0; link_id < ARRAY_SIZE((sta)->link); link_id++) { ++ struct iwl_mvm_link_sta *mvm_link_sta; ++ ++ mvm_link_sta = ++ rcu_dereference_check(mvm_sta->link[link_id], ++ lockdep_is_held(&mvm->mutex)); ++ if (mvm_link_sta && !(vif->active_links & BIT(link_id))) { ++ /* ++ * We have a link STA but the link is inactive in ++ * mac80211. This will happen if we failed to ++ * deactivate the link but mac80211 roll back the ++ * deactivation of the link. ++ * Delete the stale data to avoid issues later on. ++ */ ++ iwl_mvm_mld_free_sta_link(mvm, mvm_sta, mvm_link_sta, ++ link_id, false); ++ } ++ } ++} ++ + static void iwl_mvm_restart_cleanup(struct iwl_mvm *mvm) + { + iwl_mvm_stop_device(mvm); +@@ -1137,6 +1170,10 @@ static void iwl_mvm_restart_cleanup(struct iwl_mvm *mvm) + */ + ieee80211_iterate_interfaces(mvm->hw, 0, iwl_mvm_cleanup_iterator, mvm); + ++ /* cleanup stations as links may be gone after restart */ ++ ieee80211_iterate_stations_atomic(mvm->hw, ++ iwl_mvm_cleanup_sta_iterator, mvm); ++ + mvm->p2p_device_vif = NULL; + + iwl_mvm_reset_phy_ctxts(mvm); +@@ -6127,7 +6164,7 @@ void iwl_mvm_sync_rx_queues_internal(struct iwl_mvm *mvm, + .len[0] = sizeof(cmd), + .data[1] = data, + .len[1] = size, +- .flags = sync ? 0 : CMD_ASYNC, ++ .flags = CMD_SEND_IN_RFKILL | (sync ? 0 : CMD_ASYNC), + }; + int ret; + +@@ -6152,11 +6189,9 @@ void iwl_mvm_sync_rx_queues_internal(struct iwl_mvm *mvm, + if (sync) { + lockdep_assert_held(&mvm->mutex); + ret = wait_event_timeout(mvm->rx_sync_waitq, +- READ_ONCE(mvm->queue_sync_state) == 0 || +- iwl_mvm_is_radio_hw_killed(mvm), ++ READ_ONCE(mvm->queue_sync_state) == 0, + SYNC_RX_QUEUE_TIMEOUT); +- WARN_ONCE(!ret && !iwl_mvm_is_radio_hw_killed(mvm), +- "queue sync: failed to sync, state is 0x%lx, cookie %d\n", ++ WARN_ONCE(!ret, "queue sync: failed to sync, state is 0x%lx, cookie %d\n", + mvm->queue_sync_state, + mvm->queue_sync_cookie); + } +diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mld-sta.c b/drivers/net/wireless/intel/iwlwifi/mvm/mld-sta.c +index 36dc291d98dd6..dbe668db7ce37 100644 +--- a/drivers/net/wireless/intel/iwlwifi/mvm/mld-sta.c ++++ b/drivers/net/wireless/intel/iwlwifi/mvm/mld-sta.c +@@ -515,11 +515,11 @@ static int iwl_mvm_mld_cfg_sta(struct iwl_mvm *mvm, struct ieee80211_sta *sta, + return iwl_mvm_mld_send_sta_cmd(mvm, &cmd); + } + +-static void iwl_mvm_mld_free_sta_link(struct iwl_mvm *mvm, +- struct iwl_mvm_sta *mvm_sta, +- struct iwl_mvm_link_sta *mvm_sta_link, +- unsigned int link_id, +- bool is_in_fw) ++void iwl_mvm_mld_free_sta_link(struct iwl_mvm *mvm, ++ struct iwl_mvm_sta *mvm_sta, ++ struct iwl_mvm_link_sta *mvm_sta_link, ++ unsigned int link_id, ++ bool is_in_fw) + { + RCU_INIT_POINTER(mvm->fw_id_to_mac_id[mvm_sta_link->sta_id], + is_in_fw ? ERR_PTR(-EINVAL) : NULL); +@@ -1012,7 +1012,8 @@ static int iwl_mvm_mld_update_sta_baids(struct iwl_mvm *mvm, + + cmd.modify.tid = cpu_to_le32(data->tid); + +- ret = iwl_mvm_send_cmd_pdu(mvm, cmd_id, 0, sizeof(cmd), &cmd); ++ ret = iwl_mvm_send_cmd_pdu(mvm, cmd_id, CMD_SEND_IN_RFKILL, ++ sizeof(cmd), &cmd); + data->sta_mask = new_sta_mask; + if (ret) + return ret; +diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/ops.c b/drivers/net/wireless/intel/iwlwifi/mvm/ops.c +index a93981cb9714f..7f5685a4838cb 100644 +--- a/drivers/net/wireless/intel/iwlwifi/mvm/ops.c ++++ b/drivers/net/wireless/intel/iwlwifi/mvm/ops.c +@@ -1854,12 +1854,10 @@ static bool iwl_mvm_set_hw_rfkill_state(struct iwl_op_mode *op_mode, bool state) + bool rfkill_safe_init_done = READ_ONCE(mvm->rfkill_safe_init_done); + bool unified = iwl_mvm_has_unified_ucode(mvm); + +- if (state) { ++ if (state) + set_bit(IWL_MVM_STATUS_HW_RFKILL, &mvm->status); +- wake_up(&mvm->rx_sync_waitq); +- } else { ++ else + clear_bit(IWL_MVM_STATUS_HW_RFKILL, &mvm->status); +- } + + iwl_mvm_set_rfkill_state(mvm); + +diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/scan.c b/drivers/net/wireless/intel/iwlwifi/mvm/scan.c +index 525d8efcc1475..aa5fa6c657c02 100644 +--- a/drivers/net/wireless/intel/iwlwifi/mvm/scan.c ++++ b/drivers/net/wireless/intel/iwlwifi/mvm/scan.c +@@ -1717,7 +1717,10 @@ iwl_mvm_umac_scan_fill_6g_chan_list(struct iwl_mvm *mvm, + break; + } + +- if (k == idex_b && idex_b < SCAN_BSSID_MAX_SIZE) { ++ if (k == idex_b && idex_b < SCAN_BSSID_MAX_SIZE && ++ !WARN_ONCE(!is_valid_ether_addr(scan_6ghz_params[j].bssid), ++ "scan: invalid BSSID at index %u, index_b=%u\n", ++ j, idex_b)) { + memcpy(&pp->bssid_array[idex_b++], + scan_6ghz_params[j].bssid, ETH_ALEN); + } +@@ -3251,10 +3254,11 @@ static int iwl_mvm_umac_scan_abort(struct iwl_mvm *mvm, int type) + + ret = iwl_mvm_send_cmd_pdu(mvm, + WIDE_ID(IWL_ALWAYS_LONG_GROUP, SCAN_ABORT_UMAC), +- 0, sizeof(cmd), &cmd); ++ CMD_SEND_IN_RFKILL, sizeof(cmd), &cmd); + if (!ret) + mvm->scan_uid_status[uid] = type << IWL_MVM_SCAN_STOPPING_SHIFT; + ++ IWL_DEBUG_SCAN(mvm, "Scan abort: ret=%d\n", ret); + return ret; + } + +diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/sta.c b/drivers/net/wireless/intel/iwlwifi/mvm/sta.c +index 491c449fd4316..908d0bc474da6 100644 +--- a/drivers/net/wireless/intel/iwlwifi/mvm/sta.c ++++ b/drivers/net/wireless/intel/iwlwifi/mvm/sta.c +@@ -2836,7 +2836,12 @@ static int iwl_mvm_fw_baid_op_cmd(struct iwl_mvm *mvm, + .action = start ? cpu_to_le32(IWL_RX_BAID_ACTION_ADD) : + cpu_to_le32(IWL_RX_BAID_ACTION_REMOVE), + }; +- u32 cmd_id = WIDE_ID(DATA_PATH_GROUP, RX_BAID_ALLOCATION_CONFIG_CMD); ++ struct iwl_host_cmd hcmd = { ++ .id = WIDE_ID(DATA_PATH_GROUP, RX_BAID_ALLOCATION_CONFIG_CMD), ++ .flags = CMD_SEND_IN_RFKILL, ++ .len[0] = sizeof(cmd), ++ .data[0] = &cmd, ++ }; + int ret; + + BUILD_BUG_ON(sizeof(struct iwl_rx_baid_cfg_resp) != sizeof(baid)); +@@ -2848,7 +2853,7 @@ static int iwl_mvm_fw_baid_op_cmd(struct iwl_mvm *mvm, + cmd.alloc.ssn = cpu_to_le16(ssn); + cmd.alloc.win_size = cpu_to_le16(buf_size); + baid = -EIO; +- } else if (iwl_fw_lookup_cmd_ver(mvm->fw, cmd_id, 1) == 1) { ++ } else if (iwl_fw_lookup_cmd_ver(mvm->fw, hcmd.id, 1) == 1) { + cmd.remove_v1.baid = cpu_to_le32(baid); + BUILD_BUG_ON(sizeof(cmd.remove_v1) > sizeof(cmd.remove)); + } else { +@@ -2857,8 +2862,7 @@ static int iwl_mvm_fw_baid_op_cmd(struct iwl_mvm *mvm, + cmd.remove.tid = cpu_to_le32(tid); + } + +- ret = iwl_mvm_send_cmd_pdu_status(mvm, cmd_id, sizeof(cmd), +- &cmd, &baid); ++ ret = iwl_mvm_send_cmd_status(mvm, &hcmd, &baid); + if (ret) + return ret; + +diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/sta.h b/drivers/net/wireless/intel/iwlwifi/mvm/sta.h +index b3450569864eb..7dd8f7f4b4492 100644 +--- a/drivers/net/wireless/intel/iwlwifi/mvm/sta.h ++++ b/drivers/net/wireless/intel/iwlwifi/mvm/sta.h +@@ -638,6 +638,11 @@ int iwl_mvm_mld_update_sta(struct iwl_mvm *mvm, struct ieee80211_vif *vif, + struct ieee80211_sta *sta); + int iwl_mvm_mld_rm_sta(struct iwl_mvm *mvm, struct ieee80211_vif *vif, + struct ieee80211_sta *sta); ++void iwl_mvm_mld_free_sta_link(struct iwl_mvm *mvm, ++ struct iwl_mvm_sta *mvm_sta, ++ struct iwl_mvm_link_sta *mvm_sta_link, ++ unsigned int link_id, ++ bool is_in_fw); + int iwl_mvm_mld_rm_sta_id(struct iwl_mvm *mvm, u8 sta_id); + int iwl_mvm_mld_update_sta_links(struct iwl_mvm *mvm, + struct ieee80211_vif *vif, +diff --git a/drivers/nvme/host/core.c b/drivers/nvme/host/core.c +index d513fd27589df..36f30594b671f 100644 +--- a/drivers/nvme/host/core.c ++++ b/drivers/nvme/host/core.c +@@ -998,6 +998,7 @@ void nvme_cleanup_cmd(struct request *req) + clear_bit_unlock(0, &ctrl->discard_page_busy); + else + kfree(bvec_virt(&req->special_vec)); ++ req->rq_flags &= ~RQF_SPECIAL_PAYLOAD; + } + } + EXPORT_SYMBOL_GPL(nvme_cleanup_cmd); +diff --git a/drivers/nvme/host/fabrics.c b/drivers/nvme/host/fabrics.c +index 1f0ea1f32d22f..f6416f8553f03 100644 +--- a/drivers/nvme/host/fabrics.c ++++ b/drivers/nvme/host/fabrics.c +@@ -180,7 +180,7 @@ int nvmf_reg_read32(struct nvme_ctrl *ctrl, u32 off, u32 *val) + cmd.prop_get.offset = cpu_to_le32(off); + + ret = __nvme_submit_sync_cmd(ctrl->fabrics_q, &cmd, &res, NULL, 0, +- NVME_QID_ANY, 0); ++ NVME_QID_ANY, NVME_SUBMIT_RESERVED); + + if (ret >= 0) + *val = le64_to_cpu(res.u64); +@@ -226,7 +226,7 @@ int nvmf_reg_read64(struct nvme_ctrl *ctrl, u32 off, u64 *val) + cmd.prop_get.offset = cpu_to_le32(off); + + ret = __nvme_submit_sync_cmd(ctrl->fabrics_q, &cmd, &res, NULL, 0, +- NVME_QID_ANY, 0); ++ NVME_QID_ANY, NVME_SUBMIT_RESERVED); + + if (ret >= 0) + *val = le64_to_cpu(res.u64); +@@ -271,7 +271,7 @@ int nvmf_reg_write32(struct nvme_ctrl *ctrl, u32 off, u32 val) + cmd.prop_set.value = cpu_to_le64(val); + + ret = __nvme_submit_sync_cmd(ctrl->fabrics_q, &cmd, NULL, NULL, 0, +- NVME_QID_ANY, 0); ++ NVME_QID_ANY, NVME_SUBMIT_RESERVED); + if (unlikely(ret)) + dev_err(ctrl->device, + "Property Set error: %d, offset %#x\n", +diff --git a/drivers/nvme/host/nvme.h b/drivers/nvme/host/nvme.h +index d7bcc6d51e84e..3f2b0d41e4819 100644 +--- a/drivers/nvme/host/nvme.h ++++ b/drivers/nvme/host/nvme.h +@@ -503,7 +503,7 @@ static inline bool nvme_ns_head_multipath(struct nvme_ns_head *head) + enum nvme_ns_features { + NVME_NS_EXT_LBAS = 1 << 0, /* support extended LBA format */ + NVME_NS_METADATA_SUPPORTED = 1 << 1, /* support getting generated md */ +- NVME_NS_DEAC, /* DEAC bit in Write Zeores supported */ ++ NVME_NS_DEAC = 1 << 2, /* DEAC bit in Write Zeores supported */ + }; + + struct nvme_ns { +diff --git a/drivers/nvme/target/core.c b/drivers/nvme/target/core.c +index 06f0c587f3437..4ff460ba28263 100644 +--- a/drivers/nvme/target/core.c ++++ b/drivers/nvme/target/core.c +@@ -957,6 +957,7 @@ bool nvmet_req_init(struct nvmet_req *req, struct nvmet_cq *cq, + req->metadata_sg_cnt = 0; + req->transfer_len = 0; + req->metadata_len = 0; ++ req->cqe->result.u64 = 0; + req->cqe->status = 0; + req->cqe->sq_head = 0; + req->ns = NULL; +diff --git a/drivers/nvme/target/fabrics-cmd-auth.c b/drivers/nvme/target/fabrics-cmd-auth.c +index eb7785be0ca77..ee76491e8b12c 100644 +--- a/drivers/nvme/target/fabrics-cmd-auth.c ++++ b/drivers/nvme/target/fabrics-cmd-auth.c +@@ -332,7 +332,6 @@ void nvmet_execute_auth_send(struct nvmet_req *req) + pr_debug("%s: ctrl %d qid %d nvme status %x error loc %d\n", + __func__, ctrl->cntlid, req->sq->qid, + status, req->error_loc); +- req->cqe->result.u64 = 0; + if (req->sq->dhchap_step != NVME_AUTH_DHCHAP_MESSAGE_SUCCESS2 && + req->sq->dhchap_step != NVME_AUTH_DHCHAP_MESSAGE_FAILURE2) { + unsigned long auth_expire_secs = ctrl->kato ? ctrl->kato : 120; +@@ -515,8 +514,6 @@ void nvmet_execute_auth_receive(struct nvmet_req *req) + status = nvmet_copy_to_sgl(req, 0, d, al); + kfree(d); + done: +- req->cqe->result.u64 = 0; +- + if (req->sq->dhchap_step == NVME_AUTH_DHCHAP_MESSAGE_SUCCESS2) + nvmet_auth_sq_free(req->sq); + else if (req->sq->dhchap_step == NVME_AUTH_DHCHAP_MESSAGE_FAILURE1) { +diff --git a/drivers/nvme/target/fabrics-cmd.c b/drivers/nvme/target/fabrics-cmd.c +index b23f4cf840bd5..f6714453b8bb3 100644 +--- a/drivers/nvme/target/fabrics-cmd.c ++++ b/drivers/nvme/target/fabrics-cmd.c +@@ -226,9 +226,6 @@ static void nvmet_execute_admin_connect(struct nvmet_req *req) + if (status) + goto out; + +- /* zero out initial completion result, assign values as needed */ +- req->cqe->result.u32 = 0; +- + if (c->recfmt != 0) { + pr_warn("invalid connect version (%d).\n", + le16_to_cpu(c->recfmt)); +@@ -304,9 +301,6 @@ static void nvmet_execute_io_connect(struct nvmet_req *req) + if (status) + goto out; + +- /* zero out initial completion result, assign values as needed */ +- req->cqe->result.u32 = 0; +- + if (c->recfmt != 0) { + pr_warn("invalid connect version (%d).\n", + le16_to_cpu(c->recfmt)); +diff --git a/drivers/of/irq.c b/drivers/of/irq.c +index 174900072c18c..c94203ce65bb3 100644 +--- a/drivers/of/irq.c ++++ b/drivers/of/irq.c +@@ -25,6 +25,8 @@ + #include <linux/string.h> + #include <linux/slab.h> + ++#include "of_private.h" ++ + /** + * irq_of_parse_and_map - Parse and map an interrupt into linux virq space + * @dev: Device node of the device whose interrupt is to be mapped +@@ -79,7 +81,8 @@ EXPORT_SYMBOL_GPL(of_irq_find_parent); + /* + * These interrupt controllers abuse interrupt-map for unspeakable + * reasons and rely on the core code to *ignore* it (the drivers do +- * their own parsing of the property). ++ * their own parsing of the property). The PAsemi entry covers a ++ * non-sensical interrupt-map that is better left ignored. + * + * If you think of adding to the list for something *new*, think + * again. There is a high chance that you will be sent back to the +@@ -93,9 +96,61 @@ static const char * const of_irq_imap_abusers[] = { + "fsl,ls1043a-extirq", + "fsl,ls1088a-extirq", + "renesas,rza1-irqc", ++ "pasemi,rootbus", + NULL, + }; + ++const __be32 *of_irq_parse_imap_parent(const __be32 *imap, int len, struct of_phandle_args *out_irq) ++{ ++ u32 intsize, addrsize; ++ struct device_node *np; ++ ++ /* Get the interrupt parent */ ++ if (of_irq_workarounds & OF_IMAP_NO_PHANDLE) ++ np = of_node_get(of_irq_dflt_pic); ++ else ++ np = of_find_node_by_phandle(be32_to_cpup(imap)); ++ imap++; ++ ++ /* Check if not found */ ++ if (!np) { ++ pr_debug(" -> imap parent not found !\n"); ++ return NULL; ++ } ++ ++ /* Get #interrupt-cells and #address-cells of new parent */ ++ if (of_property_read_u32(np, "#interrupt-cells", ++ &intsize)) { ++ pr_debug(" -> parent lacks #interrupt-cells!\n"); ++ of_node_put(np); ++ return NULL; ++ } ++ if (of_property_read_u32(np, "#address-cells", ++ &addrsize)) ++ addrsize = 0; ++ ++ pr_debug(" -> intsize=%d, addrsize=%d\n", ++ intsize, addrsize); ++ ++ /* Check for malformed properties */ ++ if (WARN_ON(addrsize + intsize > MAX_PHANDLE_ARGS) ++ || (len < (addrsize + intsize))) { ++ of_node_put(np); ++ return NULL; ++ } ++ ++ pr_debug(" -> imaplen=%d\n", len); ++ ++ imap += addrsize + intsize; ++ ++ out_irq->np = np; ++ for (int i = 0; i < intsize; i++) ++ out_irq->args[i] = be32_to_cpup(imap - intsize + i); ++ out_irq->args_count = intsize; ++ ++ return imap; ++} ++ + /** + * of_irq_parse_raw - Low level interrupt tree parsing + * @addr: address specifier (start of "reg" property of the device) in be32 format +@@ -112,12 +167,12 @@ static const char * const of_irq_imap_abusers[] = { + */ + int of_irq_parse_raw(const __be32 *addr, struct of_phandle_args *out_irq) + { +- struct device_node *ipar, *tnode, *old = NULL, *newpar = NULL; ++ struct device_node *ipar, *tnode, *old = NULL; + __be32 initial_match_array[MAX_PHANDLE_ARGS]; + const __be32 *match_array = initial_match_array; +- const __be32 *tmp, *imap, *imask, dummy_imask[] = { [0 ... MAX_PHANDLE_ARGS] = cpu_to_be32(~0) }; +- u32 intsize = 1, addrsize, newintsize = 0, newaddrsize = 0; +- int imaplen, match, i, rc = -EINVAL; ++ const __be32 *tmp, dummy_imask[] = { [0 ... MAX_PHANDLE_ARGS] = cpu_to_be32(~0) }; ++ u32 intsize = 1, addrsize; ++ int i, rc = -EINVAL; + + #ifdef DEBUG + of_print_phandle_args("of_irq_parse_raw: ", out_irq); +@@ -176,6 +231,9 @@ int of_irq_parse_raw(const __be32 *addr, struct of_phandle_args *out_irq) + + /* Now start the actual "proper" walk of the interrupt tree */ + while (ipar != NULL) { ++ int imaplen, match; ++ const __be32 *imap, *oldimap, *imask; ++ struct device_node *newpar; + /* + * Now check if cursor is an interrupt-controller and + * if it is then we are done, unless there is an +@@ -216,7 +274,7 @@ int of_irq_parse_raw(const __be32 *addr, struct of_phandle_args *out_irq) + + /* Parse interrupt-map */ + match = 0; +- while (imaplen > (addrsize + intsize + 1) && !match) { ++ while (imaplen > (addrsize + intsize + 1)) { + /* Compare specifiers */ + match = 1; + for (i = 0; i < (addrsize + intsize); i++, imaplen--) +@@ -224,74 +282,31 @@ int of_irq_parse_raw(const __be32 *addr, struct of_phandle_args *out_irq) + + pr_debug(" -> match=%d (imaplen=%d)\n", match, imaplen); + +- /* Get the interrupt parent */ +- if (of_irq_workarounds & OF_IMAP_NO_PHANDLE) +- newpar = of_node_get(of_irq_dflt_pic); +- else +- newpar = of_find_node_by_phandle(be32_to_cpup(imap)); +- imap++; +- --imaplen; +- +- /* Check if not found */ +- if (newpar == NULL) { +- pr_debug(" -> imap parent not found !\n"); ++ oldimap = imap; ++ imap = of_irq_parse_imap_parent(oldimap, imaplen, out_irq); ++ if (!imap) + goto fail; +- } +- +- if (!of_device_is_available(newpar)) +- match = 0; +- +- /* Get #interrupt-cells and #address-cells of new +- * parent +- */ +- if (of_property_read_u32(newpar, "#interrupt-cells", +- &newintsize)) { +- pr_debug(" -> parent lacks #interrupt-cells!\n"); +- goto fail; +- } +- if (of_property_read_u32(newpar, "#address-cells", +- &newaddrsize)) +- newaddrsize = 0; + +- pr_debug(" -> newintsize=%d, newaddrsize=%d\n", +- newintsize, newaddrsize); +- +- /* Check for malformed properties */ +- if (WARN_ON(newaddrsize + newintsize > MAX_PHANDLE_ARGS) +- || (imaplen < (newaddrsize + newintsize))) { +- rc = -EFAULT; +- goto fail; +- } +- +- imap += newaddrsize + newintsize; +- imaplen -= newaddrsize + newintsize; ++ match &= of_device_is_available(out_irq->np); ++ if (match) ++ break; + ++ of_node_put(out_irq->np); ++ imaplen -= imap - oldimap; + pr_debug(" -> imaplen=%d\n", imaplen); + } +- if (!match) { +- if (intc) { +- /* +- * The PASEMI Nemo is a known offender, so +- * let's only warn for anyone else. +- */ +- WARN(!IS_ENABLED(CONFIG_PPC_PASEMI), +- "%pOF interrupt-map failed, using interrupt-controller\n", +- ipar); +- return 0; +- } +- ++ if (!match) + goto fail; +- } + + /* + * Successfully parsed an interrupt-map translation; copy new + * interrupt specifier into the out_irq structure + */ +- match_array = imap - newaddrsize - newintsize; +- for (i = 0; i < newintsize; i++) +- out_irq->args[i] = be32_to_cpup(imap - newintsize + i); +- out_irq->args_count = intsize = newintsize; +- addrsize = newaddrsize; ++ match_array = oldimap + 1; ++ ++ newpar = out_irq->np; ++ intsize = out_irq->args_count; ++ addrsize = (imap - match_array) - intsize; + + if (ipar == newpar) { + pr_debug("%pOF interrupt-map entry to self\n", ipar); +@@ -300,7 +315,6 @@ int of_irq_parse_raw(const __be32 *addr, struct of_phandle_args *out_irq) + + skiplevel: + /* Iterate again with new parent */ +- out_irq->np = newpar; + pr_debug(" -> new parent: %pOF\n", newpar); + of_node_put(ipar); + ipar = newpar; +@@ -310,7 +324,6 @@ int of_irq_parse_raw(const __be32 *addr, struct of_phandle_args *out_irq) + + fail: + of_node_put(ipar); +- of_node_put(newpar); + + return rc; + } +diff --git a/drivers/of/of_private.h b/drivers/of/of_private.h +index 485483524b7f1..b0609de49c7c4 100644 +--- a/drivers/of/of_private.h ++++ b/drivers/of/of_private.h +@@ -158,6 +158,9 @@ extern void __of_sysfs_remove_bin_file(struct device_node *np, + extern int of_bus_n_addr_cells(struct device_node *np); + extern int of_bus_n_size_cells(struct device_node *np); + ++const __be32 *of_irq_parse_imap_parent(const __be32 *imap, int len, ++ struct of_phandle_args *out_irq); ++ + struct bus_dma_region; + #if defined(CONFIG_OF_ADDRESS) && defined(CONFIG_HAS_DMA) + int of_dma_get_range(struct device_node *np, +diff --git a/drivers/parport/parport_amiga.c b/drivers/parport/parport_amiga.c +index e6dc857aac3fe..e06c7b2aac5c4 100644 +--- a/drivers/parport/parport_amiga.c ++++ b/drivers/parport/parport_amiga.c +@@ -229,7 +229,13 @@ static void __exit amiga_parallel_remove(struct platform_device *pdev) + parport_put_port(port); + } + +-static struct platform_driver amiga_parallel_driver = { ++/* ++ * amiga_parallel_remove() lives in .exit.text. For drivers registered via ++ * module_platform_driver_probe() this is ok because they cannot get unbound at ++ * runtime. So mark the driver struct with __refdata to prevent modpost ++ * triggering a section mismatch warning. ++ */ ++static struct platform_driver amiga_parallel_driver __refdata = { + .remove_new = __exit_p(amiga_parallel_remove), + .driver = { + .name = "amiga-parallel", +diff --git a/drivers/perf/riscv_pmu_sbi.c b/drivers/perf/riscv_pmu_sbi.c +index 3e44d2fb8bf81..6d3fdf3a688dd 100644 +--- a/drivers/perf/riscv_pmu_sbi.c ++++ b/drivers/perf/riscv_pmu_sbi.c +@@ -634,7 +634,7 @@ static inline void pmu_sbi_stop_all(struct riscv_pmu *pmu) + * which may include counters that are not enabled yet. + */ + sbi_ecall(SBI_EXT_PMU, SBI_EXT_PMU_COUNTER_STOP, +- 0, pmu->cmask, 0, 0, 0, 0); ++ 0, pmu->cmask, SBI_PMU_STOP_FLAG_RESET, 0, 0, 0); + } + + static inline void pmu_sbi_stop_hw_ctrs(struct riscv_pmu *pmu) +diff --git a/drivers/platform/mellanox/nvsw-sn2201.c b/drivers/platform/mellanox/nvsw-sn2201.c +index 3ef655591424c..abe7be602f846 100644 +--- a/drivers/platform/mellanox/nvsw-sn2201.c ++++ b/drivers/platform/mellanox/nvsw-sn2201.c +@@ -1198,6 +1198,7 @@ static int nvsw_sn2201_config_pre_init(struct nvsw_sn2201 *nvsw_sn2201) + static int nvsw_sn2201_probe(struct platform_device *pdev) + { + struct nvsw_sn2201 *nvsw_sn2201; ++ int ret; + + nvsw_sn2201 = devm_kzalloc(&pdev->dev, sizeof(*nvsw_sn2201), GFP_KERNEL); + if (!nvsw_sn2201) +@@ -1205,8 +1206,10 @@ static int nvsw_sn2201_probe(struct platform_device *pdev) + + nvsw_sn2201->dev = &pdev->dev; + platform_set_drvdata(pdev, nvsw_sn2201); +- platform_device_add_resources(pdev, nvsw_sn2201_lpc_io_resources, ++ ret = platform_device_add_resources(pdev, nvsw_sn2201_lpc_io_resources, + ARRAY_SIZE(nvsw_sn2201_lpc_io_resources)); ++ if (ret) ++ return ret; + + nvsw_sn2201->main_mux_deferred_nr = NVSW_SN2201_MAIN_MUX_DEFER_NR; + nvsw_sn2201->main_mux_devs = nvsw_sn2201_main_mux_brdinfo; +diff --git a/drivers/platform/x86/amd/hsmp.c b/drivers/platform/x86/amd/hsmp.c +index 1927be901108e..272d32a95e216 100644 +--- a/drivers/platform/x86/amd/hsmp.c ++++ b/drivers/platform/x86/amd/hsmp.c +@@ -907,16 +907,44 @@ static int hsmp_plat_dev_register(void) + return ret; + } + ++/* ++ * This check is only needed for backward compatibility of previous platforms. ++ * All new platforms are expected to support ACPI based probing. ++ */ ++static bool legacy_hsmp_support(void) ++{ ++ if (boot_cpu_data.x86_vendor != X86_VENDOR_AMD) ++ return false; ++ ++ switch (boot_cpu_data.x86) { ++ case 0x19: ++ switch (boot_cpu_data.x86_model) { ++ case 0x00 ... 0x1F: ++ case 0x30 ... 0x3F: ++ case 0x90 ... 0x9F: ++ case 0xA0 ... 0xAF: ++ return true; ++ default: ++ return false; ++ } ++ case 0x1A: ++ switch (boot_cpu_data.x86_model) { ++ case 0x00 ... 0x1F: ++ return true; ++ default: ++ return false; ++ } ++ default: ++ return false; ++ } ++ ++ return false; ++} ++ + static int __init hsmp_plt_init(void) + { + int ret = -ENODEV; + +- if (boot_cpu_data.x86_vendor != X86_VENDOR_AMD || boot_cpu_data.x86 < 0x19) { +- pr_err("HSMP is not supported on Family:%x model:%x\n", +- boot_cpu_data.x86, boot_cpu_data.x86_model); +- return ret; +- } +- + /* + * amd_nb_num() returns number of SMN/DF interfaces present in the system + * if we have N SMN/DF interfaces that ideally means N sockets +@@ -930,7 +958,15 @@ static int __init hsmp_plt_init(void) + return ret; + + if (!plat_dev.is_acpi_device) { +- ret = hsmp_plat_dev_register(); ++ if (legacy_hsmp_support()) { ++ /* Not ACPI device, but supports HSMP, register a plat_dev */ ++ ret = hsmp_plat_dev_register(); ++ } else { ++ /* Not ACPI, Does not support HSMP */ ++ pr_info("HSMP is not supported on Family:%x model:%x\n", ++ boot_cpu_data.x86, boot_cpu_data.x86_model); ++ ret = -ENODEV; ++ } + if (ret) + platform_driver_unregister(&amd_hsmp_driver); + } +diff --git a/drivers/platform/x86/lg-laptop.c b/drivers/platform/x86/lg-laptop.c +index e714ee6298dda..78c48a1f9c68a 100644 +--- a/drivers/platform/x86/lg-laptop.c ++++ b/drivers/platform/x86/lg-laptop.c +@@ -39,8 +39,6 @@ MODULE_LICENSE("GPL"); + #define WMI_METHOD_WMBB "2B4F501A-BD3C-4394-8DCF-00A7D2BC8210" + #define WMI_EVENT_GUID WMI_EVENT_GUID0 + +-#define WMAB_METHOD "\\XINI.WMAB" +-#define WMBB_METHOD "\\XINI.WMBB" + #define SB_GGOV_METHOD "\\_SB.GGOV" + #define GOV_TLED 0x2020008 + #define WM_GET 1 +@@ -74,7 +72,7 @@ static u32 inited; + + static int battery_limit_use_wmbb; + static struct led_classdev kbd_backlight; +-static enum led_brightness get_kbd_backlight_level(void); ++static enum led_brightness get_kbd_backlight_level(struct device *dev); + + static const struct key_entry wmi_keymap[] = { + {KE_KEY, 0x70, {KEY_F15} }, /* LG control panel (F1) */ +@@ -84,7 +82,6 @@ static const struct key_entry wmi_keymap[] = { + * this key both sends an event and + * changes backlight level. + */ +- {KE_KEY, 0x80, {KEY_RFKILL} }, + {KE_END, 0} + }; + +@@ -128,11 +125,10 @@ static int ggov(u32 arg0) + return res; + } + +-static union acpi_object *lg_wmab(u32 method, u32 arg1, u32 arg2) ++static union acpi_object *lg_wmab(struct device *dev, u32 method, u32 arg1, u32 arg2) + { + union acpi_object args[3]; + acpi_status status; +- acpi_handle handle; + struct acpi_object_list arg; + struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL }; + +@@ -143,29 +139,22 @@ static union acpi_object *lg_wmab(u32 method, u32 arg1, u32 arg2) + args[2].type = ACPI_TYPE_INTEGER; + args[2].integer.value = arg2; + +- status = acpi_get_handle(NULL, (acpi_string) WMAB_METHOD, &handle); +- if (ACPI_FAILURE(status)) { +- pr_err("Cannot get handle"); +- return NULL; +- } +- + arg.count = 3; + arg.pointer = args; + +- status = acpi_evaluate_object(handle, NULL, &arg, &buffer); ++ status = acpi_evaluate_object(ACPI_HANDLE(dev), "WMAB", &arg, &buffer); + if (ACPI_FAILURE(status)) { +- acpi_handle_err(handle, "WMAB: call failed.\n"); ++ dev_err(dev, "WMAB: call failed.\n"); + return NULL; + } + + return buffer.pointer; + } + +-static union acpi_object *lg_wmbb(u32 method_id, u32 arg1, u32 arg2) ++static union acpi_object *lg_wmbb(struct device *dev, u32 method_id, u32 arg1, u32 arg2) + { + union acpi_object args[3]; + acpi_status status; +- acpi_handle handle; + struct acpi_object_list arg; + struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL }; + u8 buf[32]; +@@ -181,18 +170,12 @@ static union acpi_object *lg_wmbb(u32 method_id, u32 arg1, u32 arg2) + args[2].buffer.length = 32; + args[2].buffer.pointer = buf; + +- status = acpi_get_handle(NULL, (acpi_string)WMBB_METHOD, &handle); +- if (ACPI_FAILURE(status)) { +- pr_err("Cannot get handle"); +- return NULL; +- } +- + arg.count = 3; + arg.pointer = args; + +- status = acpi_evaluate_object(handle, NULL, &arg, &buffer); ++ status = acpi_evaluate_object(ACPI_HANDLE(dev), "WMBB", &arg, &buffer); + if (ACPI_FAILURE(status)) { +- acpi_handle_err(handle, "WMAB: call failed.\n"); ++ dev_err(dev, "WMBB: call failed.\n"); + return NULL; + } + +@@ -223,7 +206,7 @@ static void wmi_notify(u32 value, void *context) + + if (eventcode == 0x10000000) { + led_classdev_notify_brightness_hw_changed( +- &kbd_backlight, get_kbd_backlight_level()); ++ &kbd_backlight, get_kbd_backlight_level(kbd_backlight.dev->parent)); + } else { + key = sparse_keymap_entry_from_scancode( + wmi_input_dev, eventcode); +@@ -272,14 +255,7 @@ static void wmi_input_setup(void) + + static void acpi_notify(struct acpi_device *device, u32 event) + { +- struct key_entry *key; +- + acpi_handle_debug(device->handle, "notify: %d\n", event); +- if (inited & INIT_SPARSE_KEYMAP) { +- key = sparse_keymap_entry_from_scancode(wmi_input_dev, 0x80); +- if (key && key->type == KE_KEY) +- sparse_keymap_report_entry(wmi_input_dev, key, 1, true); +- } + } + + static ssize_t fan_mode_store(struct device *dev, +@@ -295,7 +271,7 @@ static ssize_t fan_mode_store(struct device *dev, + if (ret) + return ret; + +- r = lg_wmab(WM_FAN_MODE, WM_GET, 0); ++ r = lg_wmab(dev, WM_FAN_MODE, WM_GET, 0); + if (!r) + return -EIO; + +@@ -306,9 +282,9 @@ static ssize_t fan_mode_store(struct device *dev, + + m = r->integer.value; + kfree(r); +- r = lg_wmab(WM_FAN_MODE, WM_SET, (m & 0xffffff0f) | (value << 4)); ++ r = lg_wmab(dev, WM_FAN_MODE, WM_SET, (m & 0xffffff0f) | (value << 4)); + kfree(r); +- r = lg_wmab(WM_FAN_MODE, WM_SET, (m & 0xfffffff0) | value); ++ r = lg_wmab(dev, WM_FAN_MODE, WM_SET, (m & 0xfffffff0) | value); + kfree(r); + + return count; +@@ -320,7 +296,7 @@ static ssize_t fan_mode_show(struct device *dev, + unsigned int status; + union acpi_object *r; + +- r = lg_wmab(WM_FAN_MODE, WM_GET, 0); ++ r = lg_wmab(dev, WM_FAN_MODE, WM_GET, 0); + if (!r) + return -EIO; + +@@ -347,7 +323,7 @@ static ssize_t usb_charge_store(struct device *dev, + if (ret) + return ret; + +- r = lg_wmbb(WMBB_USB_CHARGE, WM_SET, value); ++ r = lg_wmbb(dev, WMBB_USB_CHARGE, WM_SET, value); + if (!r) + return -EIO; + +@@ -361,7 +337,7 @@ static ssize_t usb_charge_show(struct device *dev, + unsigned int status; + union acpi_object *r; + +- r = lg_wmbb(WMBB_USB_CHARGE, WM_GET, 0); ++ r = lg_wmbb(dev, WMBB_USB_CHARGE, WM_GET, 0); + if (!r) + return -EIO; + +@@ -389,7 +365,7 @@ static ssize_t reader_mode_store(struct device *dev, + if (ret) + return ret; + +- r = lg_wmab(WM_READER_MODE, WM_SET, value); ++ r = lg_wmab(dev, WM_READER_MODE, WM_SET, value); + if (!r) + return -EIO; + +@@ -403,7 +379,7 @@ static ssize_t reader_mode_show(struct device *dev, + unsigned int status; + union acpi_object *r; + +- r = lg_wmab(WM_READER_MODE, WM_GET, 0); ++ r = lg_wmab(dev, WM_READER_MODE, WM_GET, 0); + if (!r) + return -EIO; + +@@ -431,7 +407,7 @@ static ssize_t fn_lock_store(struct device *dev, + if (ret) + return ret; + +- r = lg_wmab(WM_FN_LOCK, WM_SET, value); ++ r = lg_wmab(dev, WM_FN_LOCK, WM_SET, value); + if (!r) + return -EIO; + +@@ -445,7 +421,7 @@ static ssize_t fn_lock_show(struct device *dev, + unsigned int status; + union acpi_object *r; + +- r = lg_wmab(WM_FN_LOCK, WM_GET, 0); ++ r = lg_wmab(dev, WM_FN_LOCK, WM_GET, 0); + if (!r) + return -EIO; + +@@ -475,9 +451,9 @@ static ssize_t charge_control_end_threshold_store(struct device *dev, + union acpi_object *r; + + if (battery_limit_use_wmbb) +- r = lg_wmbb(WMBB_BATT_LIMIT, WM_SET, value); ++ r = lg_wmbb(&pf_device->dev, WMBB_BATT_LIMIT, WM_SET, value); + else +- r = lg_wmab(WM_BATT_LIMIT, WM_SET, value); ++ r = lg_wmab(&pf_device->dev, WM_BATT_LIMIT, WM_SET, value); + if (!r) + return -EIO; + +@@ -496,7 +472,7 @@ static ssize_t charge_control_end_threshold_show(struct device *device, + union acpi_object *r; + + if (battery_limit_use_wmbb) { +- r = lg_wmbb(WMBB_BATT_LIMIT, WM_GET, 0); ++ r = lg_wmbb(&pf_device->dev, WMBB_BATT_LIMIT, WM_GET, 0); + if (!r) + return -EIO; + +@@ -507,7 +483,7 @@ static ssize_t charge_control_end_threshold_show(struct device *device, + + status = r->buffer.pointer[0x10]; + } else { +- r = lg_wmab(WM_BATT_LIMIT, WM_GET, 0); ++ r = lg_wmab(&pf_device->dev, WM_BATT_LIMIT, WM_GET, 0); + if (!r) + return -EIO; + +@@ -586,7 +562,7 @@ static void tpad_led_set(struct led_classdev *cdev, + { + union acpi_object *r; + +- r = lg_wmab(WM_TLED, WM_SET, brightness > LED_OFF); ++ r = lg_wmab(cdev->dev->parent, WM_TLED, WM_SET, brightness > LED_OFF); + kfree(r); + } + +@@ -608,16 +584,16 @@ static void kbd_backlight_set(struct led_classdev *cdev, + val = 0; + if (brightness >= LED_FULL) + val = 0x24; +- r = lg_wmab(WM_KEY_LIGHT, WM_SET, val); ++ r = lg_wmab(cdev->dev->parent, WM_KEY_LIGHT, WM_SET, val); + kfree(r); + } + +-static enum led_brightness get_kbd_backlight_level(void) ++static enum led_brightness get_kbd_backlight_level(struct device *dev) + { + union acpi_object *r; + int val; + +- r = lg_wmab(WM_KEY_LIGHT, WM_GET, 0); ++ r = lg_wmab(dev, WM_KEY_LIGHT, WM_GET, 0); + + if (!r) + return LED_OFF; +@@ -645,7 +621,7 @@ static enum led_brightness get_kbd_backlight_level(void) + + static enum led_brightness kbd_backlight_get(struct led_classdev *cdev) + { +- return get_kbd_backlight_level(); ++ return get_kbd_backlight_level(cdev->dev->parent); + } + + static LED_DEVICE(kbd_backlight, 255, LED_BRIGHT_HW_CHANGED); +@@ -672,6 +648,11 @@ static struct platform_driver pf_driver = { + + static int acpi_add(struct acpi_device *device) + { ++ struct platform_device_info pdev_info = { ++ .fwnode = acpi_fwnode_handle(device), ++ .name = PLATFORM_NAME, ++ .id = PLATFORM_DEVID_NONE, ++ }; + int ret; + const char *product; + int year = 2017; +@@ -683,9 +664,7 @@ static int acpi_add(struct acpi_device *device) + if (ret) + return ret; + +- pf_device = platform_device_register_simple(PLATFORM_NAME, +- PLATFORM_DEVID_NONE, +- NULL, 0); ++ pf_device = platform_device_register_full(&pdev_info); + if (IS_ERR(pf_device)) { + ret = PTR_ERR(pf_device); + pf_device = NULL; +@@ -776,7 +755,7 @@ static void acpi_remove(struct acpi_device *device) + } + + static const struct acpi_device_id device_ids[] = { +- {"LGEX0815", 0}, ++ {"LGEX0820", 0}, + {"", 0} + }; + MODULE_DEVICE_TABLE(acpi, device_ids); +diff --git a/drivers/platform/x86/wireless-hotkey.c b/drivers/platform/x86/wireless-hotkey.c +index 4422863f47bbe..01feb6e6787f2 100644 +--- a/drivers/platform/x86/wireless-hotkey.c ++++ b/drivers/platform/x86/wireless-hotkey.c +@@ -19,6 +19,7 @@ MODULE_AUTHOR("Alex Hung"); + MODULE_ALIAS("acpi*:HPQ6001:*"); + MODULE_ALIAS("acpi*:WSTADEF:*"); + MODULE_ALIAS("acpi*:AMDI0051:*"); ++MODULE_ALIAS("acpi*:LGEX0815:*"); + + struct wl_button { + struct input_dev *input_dev; +@@ -29,6 +30,7 @@ static const struct acpi_device_id wl_ids[] = { + {"HPQ6001", 0}, + {"WSTADEF", 0}, + {"AMDI0051", 0}, ++ {"LGEX0815", 0}, + {"", 0}, + }; + +diff --git a/drivers/pnp/base.h b/drivers/pnp/base.h +index e74a0f6a31572..4e80273dfb1ec 100644 +--- a/drivers/pnp/base.h ++++ b/drivers/pnp/base.h +@@ -6,6 +6,7 @@ + + extern struct mutex pnp_lock; + extern const struct attribute_group *pnp_dev_groups[]; ++extern const struct bus_type pnp_bus_type; + + int pnp_register_protocol(struct pnp_protocol *protocol); + void pnp_unregister_protocol(struct pnp_protocol *protocol); +diff --git a/drivers/s390/char/sclp.c b/drivers/s390/char/sclp.c +index d53ee34d398f6..fbe29cabcbb83 100644 +--- a/drivers/s390/char/sclp.c ++++ b/drivers/s390/char/sclp.c +@@ -1293,6 +1293,7 @@ sclp_init(void) + fail_unregister_reboot_notifier: + unregister_reboot_notifier(&sclp_reboot_notifier); + fail_init_state_uninitialized: ++ list_del(&sclp_state_change_event.list); + sclp_init_state = sclp_init_state_uninitialized; + free_page((unsigned long) sclp_read_sccb); + free_page((unsigned long) sclp_init_sccb); +diff --git a/drivers/scsi/device_handler/scsi_dh_alua.c b/drivers/scsi/device_handler/scsi_dh_alua.c +index a226dc1b65d71..4eb0837298d4d 100644 +--- a/drivers/scsi/device_handler/scsi_dh_alua.c ++++ b/drivers/scsi/device_handler/scsi_dh_alua.c +@@ -414,28 +414,40 @@ static char print_alua_state(unsigned char state) + } + } + +-static enum scsi_disposition alua_check_sense(struct scsi_device *sdev, +- struct scsi_sense_hdr *sense_hdr) ++static void alua_handle_state_transition(struct scsi_device *sdev) + { + struct alua_dh_data *h = sdev->handler_data; + struct alua_port_group *pg; + ++ rcu_read_lock(); ++ pg = rcu_dereference(h->pg); ++ if (pg) ++ pg->state = SCSI_ACCESS_STATE_TRANSITIONING; ++ rcu_read_unlock(); ++ alua_check(sdev, false); ++} ++ ++static enum scsi_disposition alua_check_sense(struct scsi_device *sdev, ++ struct scsi_sense_hdr *sense_hdr) ++{ + switch (sense_hdr->sense_key) { + case NOT_READY: + if (sense_hdr->asc == 0x04 && sense_hdr->ascq == 0x0a) { + /* + * LUN Not Accessible - ALUA state transition + */ +- rcu_read_lock(); +- pg = rcu_dereference(h->pg); +- if (pg) +- pg->state = SCSI_ACCESS_STATE_TRANSITIONING; +- rcu_read_unlock(); +- alua_check(sdev, false); ++ alua_handle_state_transition(sdev); + return NEEDS_RETRY; + } + break; + case UNIT_ATTENTION: ++ if (sense_hdr->asc == 0x04 && sense_hdr->ascq == 0x0a) { ++ /* ++ * LUN Not Accessible - ALUA state transition ++ */ ++ alua_handle_state_transition(sdev); ++ return NEEDS_RETRY; ++ } + if (sense_hdr->asc == 0x29 && sense_hdr->ascq == 0x00) { + /* + * Power On, Reset, or Bus Device Reset. +@@ -502,7 +514,8 @@ static int alua_tur(struct scsi_device *sdev) + + retval = scsi_test_unit_ready(sdev, ALUA_FAILOVER_TIMEOUT * HZ, + ALUA_FAILOVER_RETRIES, &sense_hdr); +- if (sense_hdr.sense_key == NOT_READY && ++ if ((sense_hdr.sense_key == NOT_READY || ++ sense_hdr.sense_key == UNIT_ATTENTION) && + sense_hdr.asc == 0x04 && sense_hdr.ascq == 0x0a) + return SCSI_DH_RETRY; + else if (retval) +diff --git a/drivers/scsi/libsas/sas_internal.h b/drivers/scsi/libsas/sas_internal.h +index 3804aef165adb..164086c5824ec 100644 +--- a/drivers/scsi/libsas/sas_internal.h ++++ b/drivers/scsi/libsas/sas_internal.h +@@ -145,6 +145,20 @@ static inline void sas_fail_probe(struct domain_device *dev, const char *func, i + func, dev->parent ? "exp-attached" : + "direct-attached", + SAS_ADDR(dev->sas_addr), err); ++ ++ /* ++ * If the device probe failed, the expander phy attached address ++ * needs to be reset so that the phy will not be treated as flutter ++ * in the next revalidation ++ */ ++ if (dev->parent && !dev_is_expander(dev->dev_type)) { ++ struct sas_phy *phy = dev->phy; ++ struct domain_device *parent = dev->parent; ++ struct ex_phy *ex_phy = &parent->ex_dev.ex_phy[phy->number]; ++ ++ memset(ex_phy->attached_sas_addr, 0, SAS_ADDR_SIZE); ++ } ++ + sas_unregister_dev(dev->port, dev); + } + +diff --git a/drivers/scsi/qedf/qedf.h b/drivers/scsi/qedf/qedf.h +index 5058e01b65a27..98afdfe636003 100644 +--- a/drivers/scsi/qedf/qedf.h ++++ b/drivers/scsi/qedf/qedf.h +@@ -363,6 +363,7 @@ struct qedf_ctx { + #define QEDF_IN_RECOVERY 5 + #define QEDF_DBG_STOP_IO 6 + #define QEDF_PROBING 8 ++#define QEDF_STAG_IN_PROGRESS 9 + unsigned long flags; /* Miscellaneous state flags */ + int fipvlan_retries; + u8 num_queues; +diff --git a/drivers/scsi/qedf/qedf_main.c b/drivers/scsi/qedf/qedf_main.c +index a58353b7b4e8b..b97a8712d3f66 100644 +--- a/drivers/scsi/qedf/qedf_main.c ++++ b/drivers/scsi/qedf/qedf_main.c +@@ -318,11 +318,18 @@ static struct fc_seq *qedf_elsct_send(struct fc_lport *lport, u32 did, + */ + if (resp == fc_lport_flogi_resp) { + qedf->flogi_cnt++; ++ qedf->flogi_pending++; ++ ++ if (test_bit(QEDF_UNLOADING, &qedf->flags)) { ++ QEDF_ERR(&qedf->dbg_ctx, "Driver unloading\n"); ++ qedf->flogi_pending = 0; ++ } ++ + if (qedf->flogi_pending >= QEDF_FLOGI_RETRY_CNT) { + schedule_delayed_work(&qedf->stag_work, 2); + return NULL; + } +- qedf->flogi_pending++; ++ + return fc_elsct_send(lport, did, fp, op, qedf_flogi_resp, + arg, timeout); + } +@@ -912,13 +919,14 @@ void qedf_ctx_soft_reset(struct fc_lport *lport) + struct qedf_ctx *qedf; + struct qed_link_output if_link; + ++ qedf = lport_priv(lport); ++ + if (lport->vport) { ++ clear_bit(QEDF_STAG_IN_PROGRESS, &qedf->flags); + printk_ratelimited("Cannot issue host reset on NPIV port.\n"); + return; + } + +- qedf = lport_priv(lport); +- + qedf->flogi_pending = 0; + /* For host reset, essentially do a soft link up/down */ + atomic_set(&qedf->link_state, QEDF_LINK_DOWN); +@@ -938,6 +946,7 @@ void qedf_ctx_soft_reset(struct fc_lport *lport) + if (!if_link.link_up) { + QEDF_INFO(&qedf->dbg_ctx, QEDF_LOG_DISC, + "Physical link is not up.\n"); ++ clear_bit(QEDF_STAG_IN_PROGRESS, &qedf->flags); + return; + } + /* Flush and wait to make sure link down is processed */ +@@ -950,6 +959,7 @@ void qedf_ctx_soft_reset(struct fc_lport *lport) + "Queue link up work.\n"); + queue_delayed_work(qedf->link_update_wq, &qedf->link_update, + 0); ++ clear_bit(QEDF_STAG_IN_PROGRESS, &qedf->flags); + } + + /* Reset the host by gracefully logging out and then logging back in */ +@@ -3463,6 +3473,7 @@ static int __qedf_probe(struct pci_dev *pdev, int mode) + } + + /* Start the Slowpath-process */ ++ memset(&slowpath_params, 0, sizeof(struct qed_slowpath_params)); + slowpath_params.int_mode = QED_INT_MODE_MSIX; + slowpath_params.drv_major = QEDF_DRIVER_MAJOR_VER; + slowpath_params.drv_minor = QEDF_DRIVER_MINOR_VER; +@@ -3721,6 +3732,7 @@ static void __qedf_remove(struct pci_dev *pdev, int mode) + { + struct qedf_ctx *qedf; + int rc; ++ int cnt = 0; + + if (!pdev) { + QEDF_ERR(NULL, "pdev is NULL.\n"); +@@ -3738,6 +3750,17 @@ static void __qedf_remove(struct pci_dev *pdev, int mode) + return; + } + ++stag_in_prog: ++ if (test_bit(QEDF_STAG_IN_PROGRESS, &qedf->flags)) { ++ QEDF_ERR(&qedf->dbg_ctx, "Stag in progress, cnt=%d.\n", cnt); ++ cnt++; ++ ++ if (cnt < 5) { ++ msleep(500); ++ goto stag_in_prog; ++ } ++ } ++ + if (mode != QEDF_MODE_RECOVERY) + set_bit(QEDF_UNLOADING, &qedf->flags); + +@@ -3997,6 +4020,24 @@ void qedf_stag_change_work(struct work_struct *work) + struct qedf_ctx *qedf = + container_of(work, struct qedf_ctx, stag_work.work); + ++ if (!qedf) { ++ QEDF_ERR(&qedf->dbg_ctx, "qedf is NULL"); ++ return; ++ } ++ ++ if (test_bit(QEDF_IN_RECOVERY, &qedf->flags)) { ++ QEDF_ERR(&qedf->dbg_ctx, ++ "Already is in recovery, hence not calling software context reset.\n"); ++ return; ++ } ++ ++ if (test_bit(QEDF_UNLOADING, &qedf->flags)) { ++ QEDF_ERR(&qedf->dbg_ctx, "Driver unloading\n"); ++ return; ++ } ++ ++ set_bit(QEDF_STAG_IN_PROGRESS, &qedf->flags); ++ + printk_ratelimited("[%s]:[%s:%d]:%d: Performing software context reset.", + dev_name(&qedf->pdev->dev), __func__, __LINE__, + qedf->dbg_ctx.host_no); +diff --git a/drivers/scsi/sr.h b/drivers/scsi/sr.h +index 1175f2e213b56..dc899277b3a44 100644 +--- a/drivers/scsi/sr.h ++++ b/drivers/scsi/sr.h +@@ -65,7 +65,7 @@ int sr_disk_status(struct cdrom_device_info *); + int sr_get_last_session(struct cdrom_device_info *, struct cdrom_multisession *); + int sr_get_mcn(struct cdrom_device_info *, struct cdrom_mcn *); + int sr_reset(struct cdrom_device_info *); +-int sr_select_speed(struct cdrom_device_info *cdi, int speed); ++int sr_select_speed(struct cdrom_device_info *cdi, unsigned long speed); + int sr_audio_ioctl(struct cdrom_device_info *, unsigned int, void *); + + int sr_is_xa(Scsi_CD *); +diff --git a/drivers/scsi/sr_ioctl.c b/drivers/scsi/sr_ioctl.c +index 5b0b35e60e61f..a0d2556a27bba 100644 +--- a/drivers/scsi/sr_ioctl.c ++++ b/drivers/scsi/sr_ioctl.c +@@ -425,11 +425,14 @@ int sr_reset(struct cdrom_device_info *cdi) + return 0; + } + +-int sr_select_speed(struct cdrom_device_info *cdi, int speed) ++int sr_select_speed(struct cdrom_device_info *cdi, unsigned long speed) + { + Scsi_CD *cd = cdi->handle; + struct packet_command cgc; + ++ /* avoid exceeding the max speed or overflowing integer bounds */ ++ speed = clamp(0, speed, 0xffff / 177); ++ + if (speed == 0) + speed = 0xffff; /* set to max */ + else +diff --git a/drivers/spi/spi-davinci.c b/drivers/spi/spi-davinci.c +index be3998104bfbb..f7e8b5efa50e5 100644 +--- a/drivers/spi/spi-davinci.c ++++ b/drivers/spi/spi-davinci.c +@@ -984,6 +984,9 @@ static int davinci_spi_probe(struct platform_device *pdev) + return ret; + + free_dma: ++ /* This bit needs to be cleared to disable dpsi->clk */ ++ clear_io_bits(dspi->base + SPIGCR1, SPIGCR1_POWERDOWN_MASK); ++ + if (dspi->dma_rx) { + dma_release_channel(dspi->dma_rx); + dma_release_channel(dspi->dma_tx); +@@ -1013,6 +1016,9 @@ static void davinci_spi_remove(struct platform_device *pdev) + + spi_bitbang_stop(&dspi->bitbang); + ++ /* This bit needs to be cleared to disable dpsi->clk */ ++ clear_io_bits(dspi->base + SPIGCR1, SPIGCR1_POWERDOWN_MASK); ++ + if (dspi->dma_rx) { + dma_release_channel(dspi->dma_rx); + dma_release_channel(dspi->dma_tx); +diff --git a/drivers/spi/spi-imx.c b/drivers/spi/spi-imx.c +index 09b6c1b45f1a1..09c676e50fe0e 100644 +--- a/drivers/spi/spi-imx.c ++++ b/drivers/spi/spi-imx.c +@@ -1050,7 +1050,7 @@ static struct spi_imx_devtype_data imx35_cspi_devtype_data = { + .rx_available = mx31_rx_available, + .reset = mx31_reset, + .fifo_size = 8, +- .has_dmamode = true, ++ .has_dmamode = false, + .dynamic_burst = false, + .has_targetmode = false, + .devtype = IMX35_CSPI, +diff --git a/drivers/spi/spi-mux.c b/drivers/spi/spi-mux.c +index 031b5795d1060..a8bb07b38ec64 100644 +--- a/drivers/spi/spi-mux.c ++++ b/drivers/spi/spi-mux.c +@@ -156,6 +156,7 @@ static int spi_mux_probe(struct spi_device *spi) + /* supported modes are the same as our parent's */ + ctlr->mode_bits = spi->controller->mode_bits; + ctlr->flags = spi->controller->flags; ++ ctlr->bits_per_word_mask = spi->controller->bits_per_word_mask; + ctlr->transfer_one_message = spi_mux_transfer_one_message; + ctlr->setup = spi_mux_setup; + ctlr->num_chipselect = mux_control_states(priv->mux); +diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c +index 9304fd03bf764..fcc39523d6857 100644 +--- a/drivers/spi/spi.c ++++ b/drivers/spi/spi.c +@@ -4152,7 +4152,8 @@ static int __spi_validate(struct spi_device *spi, struct spi_message *message) + return -EINVAL; + if (xfer->tx_nbits != SPI_NBITS_SINGLE && + xfer->tx_nbits != SPI_NBITS_DUAL && +- xfer->tx_nbits != SPI_NBITS_QUAD) ++ xfer->tx_nbits != SPI_NBITS_QUAD && ++ xfer->tx_nbits != SPI_NBITS_OCTAL) + return -EINVAL; + if ((xfer->tx_nbits == SPI_NBITS_DUAL) && + !(spi->mode & (SPI_TX_DUAL | SPI_TX_QUAD))) +@@ -4167,7 +4168,8 @@ static int __spi_validate(struct spi_device *spi, struct spi_message *message) + return -EINVAL; + if (xfer->rx_nbits != SPI_NBITS_SINGLE && + xfer->rx_nbits != SPI_NBITS_DUAL && +- xfer->rx_nbits != SPI_NBITS_QUAD) ++ xfer->rx_nbits != SPI_NBITS_QUAD && ++ xfer->rx_nbits != SPI_NBITS_OCTAL) + return -EINVAL; + if ((xfer->rx_nbits == SPI_NBITS_DUAL) && + !(spi->mode & (SPI_RX_DUAL | SPI_RX_QUAD))) +diff --git a/drivers/tee/optee/ffa_abi.c b/drivers/tee/optee/ffa_abi.c +index ecb5eb079408e..c5a3e25c55dab 100644 +--- a/drivers/tee/optee/ffa_abi.c ++++ b/drivers/tee/optee/ffa_abi.c +@@ -660,7 +660,9 @@ static bool optee_ffa_api_is_compatbile(struct ffa_device *ffa_dev, + const struct ffa_ops *ops) + { + const struct ffa_msg_ops *msg_ops = ops->msg_ops; +- struct ffa_send_direct_data data = { OPTEE_FFA_GET_API_VERSION }; ++ struct ffa_send_direct_data data = { ++ .data0 = OPTEE_FFA_GET_API_VERSION, ++ }; + int rc; + + msg_ops->mode_32bit_set(ffa_dev); +@@ -677,7 +679,9 @@ static bool optee_ffa_api_is_compatbile(struct ffa_device *ffa_dev, + return false; + } + +- data = (struct ffa_send_direct_data){ OPTEE_FFA_GET_OS_VERSION }; ++ data = (struct ffa_send_direct_data){ ++ .data0 = OPTEE_FFA_GET_OS_VERSION, ++ }; + rc = msg_ops->sync_send_receive(ffa_dev, &data); + if (rc) { + pr_err("Unexpected error %d\n", rc); +@@ -698,7 +702,9 @@ static bool optee_ffa_exchange_caps(struct ffa_device *ffa_dev, + unsigned int *rpc_param_count, + unsigned int *max_notif_value) + { +- struct ffa_send_direct_data data = { OPTEE_FFA_EXCHANGE_CAPABILITIES }; ++ struct ffa_send_direct_data data = { ++ .data0 = OPTEE_FFA_EXCHANGE_CAPABILITIES, ++ }; + int rc; + + rc = ops->msg_ops->sync_send_receive(ffa_dev, &data); +diff --git a/drivers/vfio/device_cdev.c b/drivers/vfio/device_cdev.c +index e75da0a70d1f8..bb1817bd4ff31 100644 +--- a/drivers/vfio/device_cdev.c ++++ b/drivers/vfio/device_cdev.c +@@ -39,6 +39,13 @@ int vfio_device_fops_cdev_open(struct inode *inode, struct file *filep) + + filep->private_data = df; + ++ /* ++ * Use the pseudo fs inode on the device to link all mmaps ++ * to the same address space, allowing us to unmap all vmas ++ * associated to this device using unmap_mapping_range(). ++ */ ++ filep->f_mapping = device->inode->i_mapping; ++ + return 0; + + err_put_registration: +diff --git a/drivers/vfio/group.c b/drivers/vfio/group.c +index 610a429c61912..ded364588d297 100644 +--- a/drivers/vfio/group.c ++++ b/drivers/vfio/group.c +@@ -286,6 +286,13 @@ static struct file *vfio_device_open_file(struct vfio_device *device) + */ + filep->f_mode |= (FMODE_PREAD | FMODE_PWRITE); + ++ /* ++ * Use the pseudo fs inode on the device to link all mmaps ++ * to the same address space, allowing us to unmap all vmas ++ * associated to this device using unmap_mapping_range(). ++ */ ++ filep->f_mapping = device->inode->i_mapping; ++ + if (device->group->type == VFIO_NO_IOMMU) + dev_warn(device->dev, "vfio-noiommu device opened by user " + "(%s:%d)\n", current->comm, task_pid_nr(current)); +diff --git a/drivers/vfio/pci/vfio_pci_core.c b/drivers/vfio/pci/vfio_pci_core.c +index ea36d2139590f..680b15ca4fcea 100644 +--- a/drivers/vfio/pci/vfio_pci_core.c ++++ b/drivers/vfio/pci/vfio_pci_core.c +@@ -1607,100 +1607,20 @@ ssize_t vfio_pci_core_write(struct vfio_device *core_vdev, const char __user *bu + } + EXPORT_SYMBOL_GPL(vfio_pci_core_write); + +-/* Return 1 on zap and vma_lock acquired, 0 on contention (only with @try) */ +-static int vfio_pci_zap_and_vma_lock(struct vfio_pci_core_device *vdev, bool try) ++static void vfio_pci_zap_bars(struct vfio_pci_core_device *vdev) + { +- struct vfio_pci_mmap_vma *mmap_vma, *tmp; ++ struct vfio_device *core_vdev = &vdev->vdev; ++ loff_t start = VFIO_PCI_INDEX_TO_OFFSET(VFIO_PCI_BAR0_REGION_INDEX); ++ loff_t end = VFIO_PCI_INDEX_TO_OFFSET(VFIO_PCI_ROM_REGION_INDEX); ++ loff_t len = end - start; + +- /* +- * Lock ordering: +- * vma_lock is nested under mmap_lock for vm_ops callback paths. +- * The memory_lock semaphore is used by both code paths calling +- * into this function to zap vmas and the vm_ops.fault callback +- * to protect the memory enable state of the device. +- * +- * When zapping vmas we need to maintain the mmap_lock => vma_lock +- * ordering, which requires using vma_lock to walk vma_list to +- * acquire an mm, then dropping vma_lock to get the mmap_lock and +- * reacquiring vma_lock. This logic is derived from similar +- * requirements in uverbs_user_mmap_disassociate(). +- * +- * mmap_lock must always be the top-level lock when it is taken. +- * Therefore we can only hold the memory_lock write lock when +- * vma_list is empty, as we'd need to take mmap_lock to clear +- * entries. vma_list can only be guaranteed empty when holding +- * vma_lock, thus memory_lock is nested under vma_lock. +- * +- * This enables the vm_ops.fault callback to acquire vma_lock, +- * followed by memory_lock read lock, while already holding +- * mmap_lock without risk of deadlock. +- */ +- while (1) { +- struct mm_struct *mm = NULL; +- +- if (try) { +- if (!mutex_trylock(&vdev->vma_lock)) +- return 0; +- } else { +- mutex_lock(&vdev->vma_lock); +- } +- while (!list_empty(&vdev->vma_list)) { +- mmap_vma = list_first_entry(&vdev->vma_list, +- struct vfio_pci_mmap_vma, +- vma_next); +- mm = mmap_vma->vma->vm_mm; +- if (mmget_not_zero(mm)) +- break; +- +- list_del(&mmap_vma->vma_next); +- kfree(mmap_vma); +- mm = NULL; +- } +- if (!mm) +- return 1; +- mutex_unlock(&vdev->vma_lock); +- +- if (try) { +- if (!mmap_read_trylock(mm)) { +- mmput(mm); +- return 0; +- } +- } else { +- mmap_read_lock(mm); +- } +- if (try) { +- if (!mutex_trylock(&vdev->vma_lock)) { +- mmap_read_unlock(mm); +- mmput(mm); +- return 0; +- } +- } else { +- mutex_lock(&vdev->vma_lock); +- } +- list_for_each_entry_safe(mmap_vma, tmp, +- &vdev->vma_list, vma_next) { +- struct vm_area_struct *vma = mmap_vma->vma; +- +- if (vma->vm_mm != mm) +- continue; +- +- list_del(&mmap_vma->vma_next); +- kfree(mmap_vma); +- +- zap_vma_ptes(vma, vma->vm_start, +- vma->vm_end - vma->vm_start); +- } +- mutex_unlock(&vdev->vma_lock); +- mmap_read_unlock(mm); +- mmput(mm); +- } ++ unmap_mapping_range(core_vdev->inode->i_mapping, start, len, true); + } + + void vfio_pci_zap_and_down_write_memory_lock(struct vfio_pci_core_device *vdev) + { +- vfio_pci_zap_and_vma_lock(vdev, false); + down_write(&vdev->memory_lock); +- mutex_unlock(&vdev->vma_lock); ++ vfio_pci_zap_bars(vdev); + } + + u16 vfio_pci_memory_lock_and_enable(struct vfio_pci_core_device *vdev) +@@ -1722,99 +1642,56 @@ void vfio_pci_memory_unlock_and_restore(struct vfio_pci_core_device *vdev, u16 c + up_write(&vdev->memory_lock); + } + +-/* Caller holds vma_lock */ +-static int __vfio_pci_add_vma(struct vfio_pci_core_device *vdev, +- struct vm_area_struct *vma) +-{ +- struct vfio_pci_mmap_vma *mmap_vma; +- +- mmap_vma = kmalloc(sizeof(*mmap_vma), GFP_KERNEL_ACCOUNT); +- if (!mmap_vma) +- return -ENOMEM; +- +- mmap_vma->vma = vma; +- list_add(&mmap_vma->vma_next, &vdev->vma_list); +- +- return 0; +-} +- +-/* +- * Zap mmaps on open so that we can fault them in on access and therefore +- * our vma_list only tracks mappings accessed since last zap. +- */ +-static void vfio_pci_mmap_open(struct vm_area_struct *vma) +-{ +- zap_vma_ptes(vma, vma->vm_start, vma->vm_end - vma->vm_start); +-} +- +-static void vfio_pci_mmap_close(struct vm_area_struct *vma) ++static unsigned long vma_to_pfn(struct vm_area_struct *vma) + { + struct vfio_pci_core_device *vdev = vma->vm_private_data; +- struct vfio_pci_mmap_vma *mmap_vma; ++ int index = vma->vm_pgoff >> (VFIO_PCI_OFFSET_SHIFT - PAGE_SHIFT); ++ u64 pgoff; + +- mutex_lock(&vdev->vma_lock); +- list_for_each_entry(mmap_vma, &vdev->vma_list, vma_next) { +- if (mmap_vma->vma == vma) { +- list_del(&mmap_vma->vma_next); +- kfree(mmap_vma); +- break; +- } +- } +- mutex_unlock(&vdev->vma_lock); ++ pgoff = vma->vm_pgoff & ++ ((1U << (VFIO_PCI_OFFSET_SHIFT - PAGE_SHIFT)) - 1); ++ ++ return (pci_resource_start(vdev->pdev, index) >> PAGE_SHIFT) + pgoff; + } + + static vm_fault_t vfio_pci_mmap_fault(struct vm_fault *vmf) + { + struct vm_area_struct *vma = vmf->vma; + struct vfio_pci_core_device *vdev = vma->vm_private_data; +- struct vfio_pci_mmap_vma *mmap_vma; +- vm_fault_t ret = VM_FAULT_NOPAGE; ++ unsigned long pfn, pgoff = vmf->pgoff - vma->vm_pgoff; ++ unsigned long addr = vma->vm_start; ++ vm_fault_t ret = VM_FAULT_SIGBUS; ++ ++ pfn = vma_to_pfn(vma); + +- mutex_lock(&vdev->vma_lock); + down_read(&vdev->memory_lock); + +- /* +- * Memory region cannot be accessed if the low power feature is engaged +- * or memory access is disabled. +- */ +- if (vdev->pm_runtime_engaged || !__vfio_pci_memory_enabled(vdev)) { +- ret = VM_FAULT_SIGBUS; +- goto up_out; +- } ++ if (vdev->pm_runtime_engaged || !__vfio_pci_memory_enabled(vdev)) ++ goto out_unlock; ++ ++ ret = vmf_insert_pfn(vma, vmf->address, pfn + pgoff); ++ if (ret & VM_FAULT_ERROR) ++ goto out_unlock; + + /* +- * We populate the whole vma on fault, so we need to test whether +- * the vma has already been mapped, such as for concurrent faults +- * to the same vma. io_remap_pfn_range() will trigger a BUG_ON if +- * we ask it to fill the same range again. ++ * Pre-fault the remainder of the vma, abort further insertions and ++ * supress error if fault is encountered during pre-fault. + */ +- list_for_each_entry(mmap_vma, &vdev->vma_list, vma_next) { +- if (mmap_vma->vma == vma) +- goto up_out; +- } +- +- if (io_remap_pfn_range(vma, vma->vm_start, vma->vm_pgoff, +- vma->vm_end - vma->vm_start, +- vma->vm_page_prot)) { +- ret = VM_FAULT_SIGBUS; +- zap_vma_ptes(vma, vma->vm_start, vma->vm_end - vma->vm_start); +- goto up_out; +- } ++ for (; addr < vma->vm_end; addr += PAGE_SIZE, pfn++) { ++ if (addr == vmf->address) ++ continue; + +- if (__vfio_pci_add_vma(vdev, vma)) { +- ret = VM_FAULT_OOM; +- zap_vma_ptes(vma, vma->vm_start, vma->vm_end - vma->vm_start); ++ if (vmf_insert_pfn(vma, addr, pfn) & VM_FAULT_ERROR) ++ break; + } + +-up_out: ++out_unlock: + up_read(&vdev->memory_lock); +- mutex_unlock(&vdev->vma_lock); ++ + return ret; + } + + static const struct vm_operations_struct vfio_pci_mmap_ops = { +- .open = vfio_pci_mmap_open, +- .close = vfio_pci_mmap_close, + .fault = vfio_pci_mmap_fault, + }; + +@@ -1877,11 +1754,12 @@ int vfio_pci_core_mmap(struct vfio_device *core_vdev, struct vm_area_struct *vma + + vma->vm_private_data = vdev; + vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot); +- vma->vm_pgoff = (pci_resource_start(pdev, index) >> PAGE_SHIFT) + pgoff; ++ vma->vm_page_prot = pgprot_decrypted(vma->vm_page_prot); + + /* +- * See remap_pfn_range(), called from vfio_pci_fault() but we can't +- * change vm_flags within the fault handler. Set them now. ++ * Set vm_flags now, they should not be changed in the fault handler. ++ * We want the same flags and page protection (decrypted above) as ++ * io_remap_pfn_range() would set. + * + * VM_ALLOW_ANY_UNCACHED: The VMA flag is implemented for ARM64, + * allowing KVM stage 2 device mapping attributes to use Normal-NC +@@ -2199,8 +2077,6 @@ int vfio_pci_core_init_dev(struct vfio_device *core_vdev) + mutex_init(&vdev->ioeventfds_lock); + INIT_LIST_HEAD(&vdev->dummy_resources_list); + INIT_LIST_HEAD(&vdev->ioeventfds_list); +- mutex_init(&vdev->vma_lock); +- INIT_LIST_HEAD(&vdev->vma_list); + INIT_LIST_HEAD(&vdev->sriov_pfs_item); + init_rwsem(&vdev->memory_lock); + xa_init(&vdev->ctx); +@@ -2216,7 +2092,6 @@ void vfio_pci_core_release_dev(struct vfio_device *core_vdev) + + mutex_destroy(&vdev->igate); + mutex_destroy(&vdev->ioeventfds_lock); +- mutex_destroy(&vdev->vma_lock); + kfree(vdev->region); + kfree(vdev->pm_save); + } +@@ -2494,26 +2369,15 @@ static int vfio_pci_dev_set_pm_runtime_get(struct vfio_device_set *dev_set) + return ret; + } + +-/* +- * We need to get memory_lock for each device, but devices can share mmap_lock, +- * therefore we need to zap and hold the vma_lock for each device, and only then +- * get each memory_lock. +- */ + static int vfio_pci_dev_set_hot_reset(struct vfio_device_set *dev_set, + struct vfio_pci_group_info *groups, + struct iommufd_ctx *iommufd_ctx) + { +- struct vfio_pci_core_device *cur_mem; +- struct vfio_pci_core_device *cur_vma; +- struct vfio_pci_core_device *cur; ++ struct vfio_pci_core_device *vdev; + struct pci_dev *pdev; +- bool is_mem = true; + int ret; + + mutex_lock(&dev_set->lock); +- cur_mem = list_first_entry(&dev_set->device_list, +- struct vfio_pci_core_device, +- vdev.dev_set_list); + + pdev = vfio_pci_dev_set_resettable(dev_set); + if (!pdev) { +@@ -2530,7 +2394,7 @@ static int vfio_pci_dev_set_hot_reset(struct vfio_device_set *dev_set, + if (ret) + goto err_unlock; + +- list_for_each_entry(cur_vma, &dev_set->device_list, vdev.dev_set_list) { ++ list_for_each_entry(vdev, &dev_set->device_list, vdev.dev_set_list) { + bool owned; + + /* +@@ -2554,38 +2418,38 @@ static int vfio_pci_dev_set_hot_reset(struct vfio_device_set *dev_set, + * Otherwise, reset is not allowed. + */ + if (iommufd_ctx) { +- int devid = vfio_iommufd_get_dev_id(&cur_vma->vdev, ++ int devid = vfio_iommufd_get_dev_id(&vdev->vdev, + iommufd_ctx); + + owned = (devid > 0 || devid == -ENOENT); + } else { +- owned = vfio_dev_in_groups(&cur_vma->vdev, groups); ++ owned = vfio_dev_in_groups(&vdev->vdev, groups); + } + + if (!owned) { + ret = -EINVAL; +- goto err_undo; ++ break; + } + + /* +- * Locking multiple devices is prone to deadlock, runaway and +- * unwind if we hit contention. ++ * Take the memory write lock for each device and zap BAR ++ * mappings to prevent the user accessing the device while in ++ * reset. Locking multiple devices is prone to deadlock, ++ * runaway and unwind if we hit contention. + */ +- if (!vfio_pci_zap_and_vma_lock(cur_vma, true)) { ++ if (!down_write_trylock(&vdev->memory_lock)) { + ret = -EBUSY; +- goto err_undo; ++ break; + } ++ ++ vfio_pci_zap_bars(vdev); + } +- cur_vma = NULL; + +- list_for_each_entry(cur_mem, &dev_set->device_list, vdev.dev_set_list) { +- if (!down_write_trylock(&cur_mem->memory_lock)) { +- ret = -EBUSY; +- goto err_undo; +- } +- mutex_unlock(&cur_mem->vma_lock); ++ if (!list_entry_is_head(vdev, ++ &dev_set->device_list, vdev.dev_set_list)) { ++ vdev = list_prev_entry(vdev, vdev.dev_set_list); ++ goto err_undo; + } +- cur_mem = NULL; + + /* + * The pci_reset_bus() will reset all the devices in the bus. +@@ -2596,25 +2460,22 @@ static int vfio_pci_dev_set_hot_reset(struct vfio_device_set *dev_set, + * cause the PCI config space reset without restoring the original + * state (saved locally in 'vdev->pm_save'). + */ +- list_for_each_entry(cur, &dev_set->device_list, vdev.dev_set_list) +- vfio_pci_set_power_state(cur, PCI_D0); ++ list_for_each_entry(vdev, &dev_set->device_list, vdev.dev_set_list) ++ vfio_pci_set_power_state(vdev, PCI_D0); + + ret = pci_reset_bus(pdev); + ++ vdev = list_last_entry(&dev_set->device_list, ++ struct vfio_pci_core_device, vdev.dev_set_list); ++ + err_undo: +- list_for_each_entry(cur, &dev_set->device_list, vdev.dev_set_list) { +- if (cur == cur_mem) +- is_mem = false; +- if (cur == cur_vma) +- break; +- if (is_mem) +- up_write(&cur->memory_lock); +- else +- mutex_unlock(&cur->vma_lock); +- } ++ list_for_each_entry_from_reverse(vdev, &dev_set->device_list, ++ vdev.dev_set_list) ++ up_write(&vdev->memory_lock); ++ ++ list_for_each_entry(vdev, &dev_set->device_list, vdev.dev_set_list) ++ pm_runtime_put(&vdev->pdev->dev); + +- list_for_each_entry(cur, &dev_set->device_list, vdev.dev_set_list) +- pm_runtime_put(&cur->pdev->dev); + err_unlock: + mutex_unlock(&dev_set->lock); + return ret; +diff --git a/drivers/vfio/vfio_main.c b/drivers/vfio/vfio_main.c +index e97d796a54fba..a5a62d9d963f7 100644 +--- a/drivers/vfio/vfio_main.c ++++ b/drivers/vfio/vfio_main.c +@@ -22,8 +22,10 @@ + #include <linux/list.h> + #include <linux/miscdevice.h> + #include <linux/module.h> ++#include <linux/mount.h> + #include <linux/mutex.h> + #include <linux/pci.h> ++#include <linux/pseudo_fs.h> + #include <linux/rwsem.h> + #include <linux/sched.h> + #include <linux/slab.h> +@@ -43,9 +45,13 @@ + #define DRIVER_AUTHOR "Alex Williamson <alex.williamson@redhat.com>" + #define DRIVER_DESC "VFIO - User Level meta-driver" + ++#define VFIO_MAGIC 0x5646494f /* "VFIO" */ ++ + static struct vfio { + struct class *device_class; + struct ida device_ida; ++ struct vfsmount *vfs_mount; ++ int fs_count; + } vfio; + + #ifdef CONFIG_VFIO_NOIOMMU +@@ -186,6 +192,8 @@ static void vfio_device_release(struct device *dev) + if (device->ops->release) + device->ops->release(device); + ++ iput(device->inode); ++ simple_release_fs(&vfio.vfs_mount, &vfio.fs_count); + kvfree(device); + } + +@@ -228,6 +236,34 @@ struct vfio_device *_vfio_alloc_device(size_t size, struct device *dev, + } + EXPORT_SYMBOL_GPL(_vfio_alloc_device); + ++static int vfio_fs_init_fs_context(struct fs_context *fc) ++{ ++ return init_pseudo(fc, VFIO_MAGIC) ? 0 : -ENOMEM; ++} ++ ++static struct file_system_type vfio_fs_type = { ++ .name = "vfio", ++ .owner = THIS_MODULE, ++ .init_fs_context = vfio_fs_init_fs_context, ++ .kill_sb = kill_anon_super, ++}; ++ ++static struct inode *vfio_fs_inode_new(void) ++{ ++ struct inode *inode; ++ int ret; ++ ++ ret = simple_pin_fs(&vfio_fs_type, &vfio.vfs_mount, &vfio.fs_count); ++ if (ret) ++ return ERR_PTR(ret); ++ ++ inode = alloc_anon_inode(vfio.vfs_mount->mnt_sb); ++ if (IS_ERR(inode)) ++ simple_release_fs(&vfio.vfs_mount, &vfio.fs_count); ++ ++ return inode; ++} ++ + /* + * Initialize a vfio_device so it can be registered to vfio core. + */ +@@ -246,6 +282,11 @@ static int vfio_init_device(struct vfio_device *device, struct device *dev, + init_completion(&device->comp); + device->dev = dev; + device->ops = ops; ++ device->inode = vfio_fs_inode_new(); ++ if (IS_ERR(device->inode)) { ++ ret = PTR_ERR(device->inode); ++ goto out_inode; ++ } + + if (ops->init) { + ret = ops->init(device); +@@ -260,6 +301,9 @@ static int vfio_init_device(struct vfio_device *device, struct device *dev, + return 0; + + out_uninit: ++ iput(device->inode); ++ simple_release_fs(&vfio.vfs_mount, &vfio.fs_count); ++out_inode: + vfio_release_device_set(device); + ida_free(&vfio.device_ida, device->index); + return ret; +diff --git a/fs/btrfs/btrfs_inode.h b/fs/btrfs/btrfs_inode.h +index 100020ca4658e..787ca2892d7a6 100644 +--- a/fs/btrfs/btrfs_inode.h ++++ b/fs/btrfs/btrfs_inode.h +@@ -89,6 +89,16 @@ enum { + BTRFS_INODE_FREE_SPACE_INODE, + /* Set when there are no capabilities in XATTs for the inode. */ + BTRFS_INODE_NO_CAP_XATTR, ++ /* ++ * Set if an error happened when doing a COW write before submitting a ++ * bio or during writeback. Used for both buffered writes and direct IO ++ * writes. This is to signal a fast fsync that it has to wait for ++ * ordered extents to complete and therefore not log extent maps that ++ * point to unwritten extents (when an ordered extent completes and it ++ * has the BTRFS_ORDERED_IOERR flag set, it drops extent maps in its ++ * range). ++ */ ++ BTRFS_INODE_COW_WRITE_ERROR, + }; + + /* in memory btrfs inode */ +diff --git a/fs/btrfs/file.c b/fs/btrfs/file.c +index f9d76072398da..97f6133b6eee8 100644 +--- a/fs/btrfs/file.c ++++ b/fs/btrfs/file.c +@@ -1875,6 +1875,7 @@ int btrfs_sync_file(struct file *file, loff_t start, loff_t end, int datasync) + */ + if (full_sync || btrfs_is_zoned(fs_info)) { + ret = btrfs_wait_ordered_range(inode, start, len); ++ clear_bit(BTRFS_INODE_COW_WRITE_ERROR, &BTRFS_I(inode)->runtime_flags); + } else { + /* + * Get our ordered extents as soon as possible to avoid doing +@@ -1884,6 +1885,21 @@ int btrfs_sync_file(struct file *file, loff_t start, loff_t end, int datasync) + btrfs_get_ordered_extents_for_logging(BTRFS_I(inode), + &ctx.ordered_extents); + ret = filemap_fdatawait_range(inode->i_mapping, start, end); ++ if (ret) ++ goto out_release_extents; ++ ++ /* ++ * Check and clear the BTRFS_INODE_COW_WRITE_ERROR now after ++ * starting and waiting for writeback, because for buffered IO ++ * it may have been set during the end IO callback ++ * (end_bbio_data_write() -> btrfs_finish_ordered_extent()) in ++ * case an error happened and we need to wait for ordered ++ * extents to complete so that any extent maps that point to ++ * unwritten locations are dropped and we don't log them. ++ */ ++ if (test_and_clear_bit(BTRFS_INODE_COW_WRITE_ERROR, ++ &BTRFS_I(inode)->runtime_flags)) ++ ret = btrfs_wait_ordered_range(inode, start, len); + } + + if (ret) +diff --git a/fs/btrfs/ordered-data.c b/fs/btrfs/ordered-data.c +index c2a42bcde98e0..7dbf4162c75a5 100644 +--- a/fs/btrfs/ordered-data.c ++++ b/fs/btrfs/ordered-data.c +@@ -382,6 +382,37 @@ bool btrfs_finish_ordered_extent(struct btrfs_ordered_extent *ordered, + ret = can_finish_ordered_extent(ordered, page, file_offset, len, uptodate); + spin_unlock_irqrestore(&inode->ordered_tree_lock, flags); + ++ /* ++ * If this is a COW write it means we created new extent maps for the ++ * range and they point to unwritten locations if we got an error either ++ * before submitting a bio or during IO. ++ * ++ * We have marked the ordered extent with BTRFS_ORDERED_IOERR, and we ++ * are queuing its completion below. During completion, at ++ * btrfs_finish_one_ordered(), we will drop the extent maps for the ++ * unwritten extents. ++ * ++ * However because completion runs in a work queue we can end up having ++ * a fast fsync running before that. In the case of direct IO, once we ++ * unlock the inode the fsync might start, and we queue the completion ++ * before unlocking the inode. In the case of buffered IO when writeback ++ * finishes (end_bbio_data_write()) we queue the completion, so if the ++ * writeback was triggered by a fast fsync, the fsync might start ++ * logging before ordered extent completion runs in the work queue. ++ * ++ * The fast fsync will log file extent items based on the extent maps it ++ * finds, so if by the time it collects extent maps the ordered extent ++ * completion didn't happen yet, it will log file extent items that ++ * point to unwritten extents, resulting in a corruption if a crash ++ * happens and the log tree is replayed. Note that a fast fsync does not ++ * wait for completion of ordered extents in order to reduce latency. ++ * ++ * Set a flag in the inode so that the next fast fsync will wait for ++ * ordered extents to complete before starting to log. ++ */ ++ if (!uptodate && !test_bit(BTRFS_ORDERED_NOCOW, &ordered->flags)) ++ set_bit(BTRFS_INODE_COW_WRITE_ERROR, &inode->runtime_flags); ++ + if (ret) + btrfs_queue_ordered_fn(ordered); + return ret; +diff --git a/fs/btrfs/qgroup.c b/fs/btrfs/qgroup.c +index 4caa078d972a3..9af2afb417308 100644 +--- a/fs/btrfs/qgroup.c ++++ b/fs/btrfs/qgroup.c +@@ -1351,7 +1351,7 @@ static int flush_reservations(struct btrfs_fs_info *fs_info) + + int btrfs_quota_disable(struct btrfs_fs_info *fs_info) + { +- struct btrfs_root *quota_root; ++ struct btrfs_root *quota_root = NULL; + struct btrfs_trans_handle *trans = NULL; + int ret = 0; + +@@ -1449,9 +1449,9 @@ int btrfs_quota_disable(struct btrfs_fs_info *fs_info) + btrfs_free_tree_block(trans, btrfs_root_id(quota_root), + quota_root->node, 0, 1); + +- btrfs_put_root(quota_root); + + out: ++ btrfs_put_root(quota_root); + mutex_unlock(&fs_info->qgroup_ioctl_lock); + if (ret && trans) + btrfs_end_transaction(trans); +diff --git a/fs/btrfs/ref-verify.c b/fs/btrfs/ref-verify.c +index 8c4fc98ca9ce7..aa7ddc09c55fa 100644 +--- a/fs/btrfs/ref-verify.c ++++ b/fs/btrfs/ref-verify.c +@@ -441,7 +441,8 @@ static int process_extent_item(struct btrfs_fs_info *fs_info, + u32 item_size = btrfs_item_size(leaf, slot); + unsigned long end, ptr; + u64 offset, flags, count; +- int type, ret; ++ int type; ++ int ret = 0; + + ei = btrfs_item_ptr(leaf, slot, struct btrfs_extent_item); + flags = btrfs_extent_flags(leaf, ei); +@@ -486,7 +487,11 @@ static int process_extent_item(struct btrfs_fs_info *fs_info, + key->objectid, key->offset); + break; + case BTRFS_EXTENT_OWNER_REF_KEY: +- WARN_ON(!btrfs_fs_incompat(fs_info, SIMPLE_QUOTA)); ++ if (!btrfs_fs_incompat(fs_info, SIMPLE_QUOTA)) { ++ btrfs_err(fs_info, ++ "found extent owner ref without simple quotas enabled"); ++ ret = -EINVAL; ++ } + break; + default: + btrfs_err(fs_info, "invalid key type in iref"); +diff --git a/fs/btrfs/scrub.c b/fs/btrfs/scrub.c +index afd6932f5e895..d7caa3732f074 100644 +--- a/fs/btrfs/scrub.c ++++ b/fs/btrfs/scrub.c +@@ -1688,20 +1688,24 @@ static void scrub_submit_extent_sector_read(struct scrub_ctx *sctx, + (i << fs_info->sectorsize_bits); + int err; + +- bbio = btrfs_bio_alloc(stripe->nr_sectors, REQ_OP_READ, +- fs_info, scrub_read_endio, stripe); +- bbio->bio.bi_iter.bi_sector = logical >> SECTOR_SHIFT; +- + io_stripe.is_scrub = true; ++ stripe_len = (nr_sectors - i) << fs_info->sectorsize_bits; ++ /* ++ * For RST cases, we need to manually split the bbio to ++ * follow the RST boundary. ++ */ + err = btrfs_map_block(fs_info, BTRFS_MAP_READ, logical, +- &stripe_len, &bioc, &io_stripe, +- &mirror); ++ &stripe_len, &bioc, &io_stripe, &mirror); + btrfs_put_bioc(bioc); +- if (err) { +- btrfs_bio_end_io(bbio, +- errno_to_blk_status(err)); +- return; ++ if (err < 0) { ++ set_bit(i, &stripe->io_error_bitmap); ++ set_bit(i, &stripe->error_bitmap); ++ continue; + } ++ ++ bbio = btrfs_bio_alloc(stripe->nr_sectors, REQ_OP_READ, ++ fs_info, scrub_read_endio, stripe); ++ bbio->bio.bi_iter.bi_sector = logical >> SECTOR_SHIFT; + } + + __bio_add_page(&bbio->bio, page, fs_info->sectorsize, pgoff); +diff --git a/fs/cachefiles/cache.c b/fs/cachefiles/cache.c +index f449f7340aad0..9fb06dc165202 100644 +--- a/fs/cachefiles/cache.c ++++ b/fs/cachefiles/cache.c +@@ -8,6 +8,7 @@ + #include <linux/slab.h> + #include <linux/statfs.h> + #include <linux/namei.h> ++#include <trace/events/fscache.h> + #include "internal.h" + + /* +@@ -312,19 +313,59 @@ static void cachefiles_withdraw_objects(struct cachefiles_cache *cache) + } + + /* +- * Withdraw volumes. ++ * Withdraw fscache volumes. ++ */ ++static void cachefiles_withdraw_fscache_volumes(struct cachefiles_cache *cache) ++{ ++ struct list_head *cur; ++ struct cachefiles_volume *volume; ++ struct fscache_volume *vcookie; ++ ++ _enter(""); ++retry: ++ spin_lock(&cache->object_list_lock); ++ list_for_each(cur, &cache->volumes) { ++ volume = list_entry(cur, struct cachefiles_volume, cache_link); ++ ++ if (atomic_read(&volume->vcookie->n_accesses) == 0) ++ continue; ++ ++ vcookie = fscache_try_get_volume(volume->vcookie, ++ fscache_volume_get_withdraw); ++ if (vcookie) { ++ spin_unlock(&cache->object_list_lock); ++ fscache_withdraw_volume(vcookie); ++ fscache_put_volume(vcookie, fscache_volume_put_withdraw); ++ goto retry; ++ } ++ } ++ spin_unlock(&cache->object_list_lock); ++ ++ _leave(""); ++} ++ ++/* ++ * Withdraw cachefiles volumes. + */ + static void cachefiles_withdraw_volumes(struct cachefiles_cache *cache) + { + _enter(""); + + for (;;) { ++ struct fscache_volume *vcookie = NULL; + struct cachefiles_volume *volume = NULL; + + spin_lock(&cache->object_list_lock); + if (!list_empty(&cache->volumes)) { + volume = list_first_entry(&cache->volumes, + struct cachefiles_volume, cache_link); ++ vcookie = fscache_try_get_volume(volume->vcookie, ++ fscache_volume_get_withdraw); ++ if (!vcookie) { ++ spin_unlock(&cache->object_list_lock); ++ cpu_relax(); ++ continue; ++ } + list_del_init(&volume->cache_link); + } + spin_unlock(&cache->object_list_lock); +@@ -332,6 +373,7 @@ static void cachefiles_withdraw_volumes(struct cachefiles_cache *cache) + break; + + cachefiles_withdraw_volume(volume); ++ fscache_put_volume(vcookie, fscache_volume_put_withdraw); + } + + _leave(""); +@@ -371,6 +413,7 @@ void cachefiles_withdraw_cache(struct cachefiles_cache *cache) + pr_info("File cache on %s unregistering\n", fscache->name); + + fscache_withdraw_cache(fscache); ++ cachefiles_withdraw_fscache_volumes(cache); + + /* we now have to destroy all the active objects pertaining to this + * cache - which we do by passing them off to thread pool to be +diff --git a/fs/cachefiles/ondemand.c b/fs/cachefiles/ondemand.c +index 7e4874f60de10..d0059d36cbd51 100644 +--- a/fs/cachefiles/ondemand.c ++++ b/fs/cachefiles/ondemand.c +@@ -97,12 +97,12 @@ static loff_t cachefiles_ondemand_fd_llseek(struct file *filp, loff_t pos, + } + + static long cachefiles_ondemand_fd_ioctl(struct file *filp, unsigned int ioctl, +- unsigned long arg) ++ unsigned long id) + { + struct cachefiles_object *object = filp->private_data; + struct cachefiles_cache *cache = object->volume->cache; + struct cachefiles_req *req; +- unsigned long id; ++ XA_STATE(xas, &cache->reqs, id); + + if (ioctl != CACHEFILES_IOC_READ_COMPLETE) + return -EINVAL; +@@ -110,10 +110,15 @@ static long cachefiles_ondemand_fd_ioctl(struct file *filp, unsigned int ioctl, + if (!test_bit(CACHEFILES_ONDEMAND_MODE, &cache->flags)) + return -EOPNOTSUPP; + +- id = arg; +- req = xa_erase(&cache->reqs, id); +- if (!req) ++ xa_lock(&cache->reqs); ++ req = xas_load(&xas); ++ if (!req || req->msg.opcode != CACHEFILES_OP_READ || ++ req->object != object) { ++ xa_unlock(&cache->reqs); + return -EINVAL; ++ } ++ xas_store(&xas, NULL); ++ xa_unlock(&cache->reqs); + + trace_cachefiles_ondemand_cread(object, id); + complete(&req->done); +@@ -142,6 +147,7 @@ int cachefiles_ondemand_copen(struct cachefiles_cache *cache, char *args) + unsigned long id; + long size; + int ret; ++ XA_STATE(xas, &cache->reqs, 0); + + if (!test_bit(CACHEFILES_ONDEMAND_MODE, &cache->flags)) + return -EOPNOTSUPP; +@@ -165,10 +171,18 @@ int cachefiles_ondemand_copen(struct cachefiles_cache *cache, char *args) + if (ret) + return ret; + +- req = xa_erase(&cache->reqs, id); +- if (!req) ++ xa_lock(&cache->reqs); ++ xas.xa_index = id; ++ req = xas_load(&xas); ++ if (!req || req->msg.opcode != CACHEFILES_OP_OPEN || ++ !req->object->ondemand->ondemand_id) { ++ xa_unlock(&cache->reqs); + return -EINVAL; ++ } ++ xas_store(&xas, NULL); ++ xa_unlock(&cache->reqs); + ++ info = req->object->ondemand; + /* fail OPEN request if copen format is invalid */ + ret = kstrtol(psize, 0, &size); + if (ret) { +@@ -188,7 +202,6 @@ int cachefiles_ondemand_copen(struct cachefiles_cache *cache, char *args) + goto out; + } + +- info = req->object->ondemand; + spin_lock(&info->lock); + /* + * The anonymous fd was closed before copen ? Fail the request. +@@ -228,6 +241,11 @@ int cachefiles_ondemand_copen(struct cachefiles_cache *cache, char *args) + wake_up_all(&cache->daemon_pollwq); + + out: ++ spin_lock(&info->lock); ++ /* Need to set object close to avoid reopen status continuing */ ++ if (info->ondemand_id == CACHEFILES_ONDEMAND_ID_CLOSED) ++ cachefiles_ondemand_set_object_close(req->object); ++ spin_unlock(&info->lock); + complete(&req->done); + return ret; + } +@@ -362,6 +380,20 @@ static struct cachefiles_req *cachefiles_ondemand_select_req(struct xa_state *xa + return NULL; + } + ++static inline bool cachefiles_ondemand_finish_req(struct cachefiles_req *req, ++ struct xa_state *xas, int err) ++{ ++ if (unlikely(!xas || !req)) ++ return false; ++ ++ if (xa_cmpxchg(xas->xa, xas->xa_index, req, NULL, 0) != req) ++ return false; ++ ++ req->error = err; ++ complete(&req->done); ++ return true; ++} ++ + ssize_t cachefiles_ondemand_daemon_read(struct cachefiles_cache *cache, + char __user *_buffer, size_t buflen) + { +@@ -425,16 +457,8 @@ ssize_t cachefiles_ondemand_daemon_read(struct cachefiles_cache *cache, + out: + cachefiles_put_object(req->object, cachefiles_obj_put_read_req); + /* Remove error request and CLOSE request has no reply */ +- if (ret || msg->opcode == CACHEFILES_OP_CLOSE) { +- xas_reset(&xas); +- xas_lock(&xas); +- if (xas_load(&xas) == req) { +- req->error = ret; +- complete(&req->done); +- xas_store(&xas, NULL); +- } +- xas_unlock(&xas); +- } ++ if (ret || msg->opcode == CACHEFILES_OP_CLOSE) ++ cachefiles_ondemand_finish_req(req, &xas, ret); + cachefiles_req_put(req); + return ret ? ret : n; + } +@@ -539,8 +563,18 @@ static int cachefiles_ondemand_send_req(struct cachefiles_object *object, + goto out; + + wake_up_all(&cache->daemon_pollwq); +- wait_for_completion(&req->done); +- ret = req->error; ++wait: ++ ret = wait_for_completion_killable(&req->done); ++ if (!ret) { ++ ret = req->error; ++ } else { ++ ret = -EINTR; ++ if (!cachefiles_ondemand_finish_req(req, &xas, ret)) { ++ /* Someone will complete it soon. */ ++ cpu_relax(); ++ goto wait; ++ } ++ } + cachefiles_req_put(req); + return ret; + out: +diff --git a/fs/cachefiles/volume.c b/fs/cachefiles/volume.c +index 89df0ba8ba5e7..781aac4ef274b 100644 +--- a/fs/cachefiles/volume.c ++++ b/fs/cachefiles/volume.c +@@ -133,7 +133,6 @@ void cachefiles_free_volume(struct fscache_volume *vcookie) + + void cachefiles_withdraw_volume(struct cachefiles_volume *volume) + { +- fscache_withdraw_volume(volume->vcookie); + cachefiles_set_volume_xattr(volume); + __cachefiles_free_volume(volume); + } +diff --git a/fs/dcache.c b/fs/dcache.c +index 66515fbc9dd70..4c144519aa709 100644 +--- a/fs/dcache.c ++++ b/fs/dcache.c +@@ -3035,28 +3035,25 @@ EXPORT_SYMBOL(d_splice_alias); + + bool is_subdir(struct dentry *new_dentry, struct dentry *old_dentry) + { +- bool result; ++ bool subdir; + unsigned seq; + + if (new_dentry == old_dentry) + return true; + +- do { +- /* for restarting inner loop in case of seq retry */ +- seq = read_seqbegin(&rename_lock); +- /* +- * Need rcu_readlock to protect against the d_parent trashing +- * due to d_move +- */ +- rcu_read_lock(); +- if (d_ancestor(old_dentry, new_dentry)) +- result = true; +- else +- result = false; +- rcu_read_unlock(); +- } while (read_seqretry(&rename_lock, seq)); +- +- return result; ++ /* Access d_parent under rcu as d_move() may change it. */ ++ rcu_read_lock(); ++ seq = read_seqbegin(&rename_lock); ++ subdir = d_ancestor(old_dentry, new_dentry); ++ /* Try lockless once... */ ++ if (read_seqretry(&rename_lock, seq)) { ++ /* ...else acquire lock for progress even on deep chains. */ ++ read_seqlock_excl(&rename_lock); ++ subdir = d_ancestor(old_dentry, new_dentry); ++ read_sequnlock_excl(&rename_lock); ++ } ++ rcu_read_unlock(); ++ return subdir; + } + EXPORT_SYMBOL(is_subdir); + +diff --git a/fs/erofs/zmap.c b/fs/erofs/zmap.c +index e313c936351d5..6bd435a565f61 100644 +--- a/fs/erofs/zmap.c ++++ b/fs/erofs/zmap.c +@@ -723,6 +723,8 @@ int z_erofs_map_blocks_iter(struct inode *inode, struct erofs_map_blocks *map, + + err = z_erofs_do_map_blocks(inode, map, flags); + out: ++ if (err) ++ map->m_llen = 0; + trace_z_erofs_map_blocks_iter_exit(inode, map, flags, err); + return err; + } +diff --git a/fs/file.c b/fs/file.c +index 3b683b9101d84..005841dd35977 100644 +--- a/fs/file.c ++++ b/fs/file.c +@@ -481,12 +481,12 @@ struct files_struct init_files = { + + static unsigned int find_next_fd(struct fdtable *fdt, unsigned int start) + { +- unsigned int maxfd = fdt->max_fds; ++ unsigned int maxfd = fdt->max_fds; /* always multiple of BITS_PER_LONG */ + unsigned int maxbit = maxfd / BITS_PER_LONG; + unsigned int bitbit = start / BITS_PER_LONG; + + bitbit = find_next_zero_bit(fdt->full_fds_bits, maxbit, bitbit) * BITS_PER_LONG; +- if (bitbit > maxfd) ++ if (bitbit >= maxfd) + return maxfd; + if (bitbit > start) + start = bitbit; +diff --git a/fs/hfsplus/xattr.c b/fs/hfsplus/xattr.c +index 9c9ff6b8c6f7e..858029b1c1735 100644 +--- a/fs/hfsplus/xattr.c ++++ b/fs/hfsplus/xattr.c +@@ -698,7 +698,7 @@ ssize_t hfsplus_listxattr(struct dentry *dentry, char *buffer, size_t size) + return err; + } + +- strbuf = kmalloc(NLS_MAX_CHARSET_SIZE * HFSPLUS_ATTR_MAX_STRLEN + ++ strbuf = kzalloc(NLS_MAX_CHARSET_SIZE * HFSPLUS_ATTR_MAX_STRLEN + + XATTR_MAC_OSX_PREFIX_LEN + 1, GFP_KERNEL); + if (!strbuf) { + res = -ENOMEM; +diff --git a/fs/iomap/buffered-io.c b/fs/iomap/buffered-io.c +index 4ac6c8c403c26..248e615270ff7 100644 +--- a/fs/iomap/buffered-io.c ++++ b/fs/iomap/buffered-io.c +@@ -241,6 +241,7 @@ static void iomap_adjust_read_range(struct inode *inode, struct folio *folio, + unsigned block_size = (1 << block_bits); + size_t poff = offset_in_folio(folio, *pos); + size_t plen = min_t(loff_t, folio_size(folio) - poff, length); ++ size_t orig_plen = plen; + unsigned first = poff >> block_bits; + unsigned last = (poff + plen - 1) >> block_bits; + +@@ -277,7 +278,7 @@ static void iomap_adjust_read_range(struct inode *inode, struct folio *folio, + * handle both halves separately so that we properly zero data in the + * page cache for blocks that are entirely outside of i_size. + */ +- if (orig_pos <= isize && orig_pos + length > isize) { ++ if (orig_pos <= isize && orig_pos + orig_plen > isize) { + unsigned end = offset_in_folio(folio, isize - 1) >> block_bits; + + if (first <= end && last > end) +diff --git a/fs/netfs/buffered_write.c b/fs/netfs/buffered_write.c +index d2ce0849bb53d..e6066ddbb3acf 100644 +--- a/fs/netfs/buffered_write.c ++++ b/fs/netfs/buffered_write.c +@@ -811,7 +811,7 @@ static void netfs_extend_writeback(struct address_space *mapping, + break; + } + +- if (!folio_try_get_rcu(folio)) { ++ if (!folio_try_get(folio)) { + xas_reset(xas); + continue; + } +@@ -1028,7 +1028,7 @@ static ssize_t netfs_writepages_begin(struct address_space *mapping, + if (!folio) + break; + +- if (!folio_try_get_rcu(folio)) { ++ if (!folio_try_get(folio)) { + xas_reset(xas); + continue; + } +diff --git a/fs/netfs/fscache_volume.c b/fs/netfs/fscache_volume.c +index cdf991bdd9def..cb75c07b5281a 100644 +--- a/fs/netfs/fscache_volume.c ++++ b/fs/netfs/fscache_volume.c +@@ -27,6 +27,19 @@ struct fscache_volume *fscache_get_volume(struct fscache_volume *volume, + return volume; + } + ++struct fscache_volume *fscache_try_get_volume(struct fscache_volume *volume, ++ enum fscache_volume_trace where) ++{ ++ int ref; ++ ++ if (!__refcount_inc_not_zero(&volume->ref, &ref)) ++ return NULL; ++ ++ trace_fscache_volume(volume->debug_id, ref + 1, where); ++ return volume; ++} ++EXPORT_SYMBOL(fscache_try_get_volume); ++ + static void fscache_see_volume(struct fscache_volume *volume, + enum fscache_volume_trace where) + { +@@ -420,6 +433,7 @@ void fscache_put_volume(struct fscache_volume *volume, + fscache_free_volume(volume); + } + } ++EXPORT_SYMBOL(fscache_put_volume); + + /* + * Relinquish a volume representation cookie. +diff --git a/fs/netfs/internal.h b/fs/netfs/internal.h +index ec7045d24400d..edf9b2a180caa 100644 +--- a/fs/netfs/internal.h ++++ b/fs/netfs/internal.h +@@ -326,8 +326,6 @@ extern const struct seq_operations fscache_volumes_seq_ops; + + struct fscache_volume *fscache_get_volume(struct fscache_volume *volume, + enum fscache_volume_trace where); +-void fscache_put_volume(struct fscache_volume *volume, +- enum fscache_volume_trace where); + bool fscache_begin_volume_access(struct fscache_volume *volume, + struct fscache_cookie *cookie, + enum fscache_access_trace why); +diff --git a/fs/nfs/dir.c b/fs/nfs/dir.c +index bdd6cb33a3708..375c08fdcf2f3 100644 +--- a/fs/nfs/dir.c ++++ b/fs/nfs/dir.c +@@ -1625,7 +1625,16 @@ nfs_lookup_revalidate_done(struct inode *dir, struct dentry *dentry, + switch (error) { + case 1: + break; +- case 0: ++ case -ETIMEDOUT: ++ if (inode && (IS_ROOT(dentry) || ++ NFS_SERVER(inode)->flags & NFS_MOUNT_SOFTREVAL)) ++ error = 1; ++ break; ++ case -ESTALE: ++ case -ENOENT: ++ error = 0; ++ fallthrough; ++ default: + /* + * We can't d_drop the root of a disconnected tree: + * its d_hash is on the s_anon list and d_drop() would hide +@@ -1680,18 +1689,8 @@ static int nfs_lookup_revalidate_dentry(struct inode *dir, + + dir_verifier = nfs_save_change_attribute(dir); + ret = NFS_PROTO(dir)->lookup(dir, dentry, fhandle, fattr); +- if (ret < 0) { +- switch (ret) { +- case -ESTALE: +- case -ENOENT: +- ret = 0; +- break; +- case -ETIMEDOUT: +- if (NFS_SERVER(inode)->flags & NFS_MOUNT_SOFTREVAL) +- ret = 1; +- } ++ if (ret < 0) + goto out; +- } + + /* Request help from readdirplus */ + nfs_lookup_advise_force_readdirplus(dir, flags); +@@ -1735,7 +1734,7 @@ nfs_do_lookup_revalidate(struct inode *dir, struct dentry *dentry, + unsigned int flags) + { + struct inode *inode; +- int error; ++ int error = 0; + + nfs_inc_stats(dir, NFSIOS_DENTRYREVALIDATE); + inode = d_inode(dentry); +@@ -1780,7 +1779,7 @@ nfs_do_lookup_revalidate(struct inode *dir, struct dentry *dentry, + out_bad: + if (flags & LOOKUP_RCU) + return -ECHILD; +- return nfs_lookup_revalidate_done(dir, dentry, inode, 0); ++ return nfs_lookup_revalidate_done(dir, dentry, inode, error); + } + + static int +diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c +index 3a816c4a6d5e2..a691fa10b3e95 100644 +--- a/fs/nfs/nfs4proc.c ++++ b/fs/nfs/nfs4proc.c +@@ -6289,6 +6289,7 @@ nfs4_set_security_label(struct inode *inode, const void *buf, size_t buflen) + if (status == 0) + nfs_setsecurity(inode, fattr); + ++ nfs_free_fattr(fattr); + return status; + } + #endif /* CONFIG_NFS_V4_SECURITY_LABEL */ +diff --git a/fs/nfs/pagelist.c b/fs/nfs/pagelist.c +index 6efb5068c116e..040b6b79c75e5 100644 +--- a/fs/nfs/pagelist.c ++++ b/fs/nfs/pagelist.c +@@ -1545,6 +1545,11 @@ void nfs_pageio_cond_complete(struct nfs_pageio_descriptor *desc, pgoff_t index) + continue; + } else if (index == prev->wb_index + 1) + continue; ++ /* ++ * We will submit more requests after these. Indicate ++ * this to the underlying layers. ++ */ ++ desc->pg_moreio = 1; + nfs_pageio_complete(desc); + break; + } +diff --git a/fs/nfs/symlink.c b/fs/nfs/symlink.c +index 0e27a2e4e68b8..13818129d268f 100644 +--- a/fs/nfs/symlink.c ++++ b/fs/nfs/symlink.c +@@ -41,7 +41,7 @@ static int nfs_symlink_filler(struct file *file, struct folio *folio) + error: + folio_set_error(folio); + folio_unlock(folio); +- return -EIO; ++ return error; + } + + static const char *nfs_get_link(struct dentry *dentry, +diff --git a/fs/smb/client/cifsfs.c b/fs/smb/client/cifsfs.c +index d8ede68260007..612e3398b221e 100644 +--- a/fs/smb/client/cifsfs.c ++++ b/fs/smb/client/cifsfs.c +@@ -1409,7 +1409,7 @@ ssize_t cifs_file_copychunk_range(unsigned int xid, + target_tcon = tlink_tcon(smb_file_target->tlink); + + if (src_tcon->ses != target_tcon->ses) { +- cifs_dbg(VFS, "source and target of copy not on same server\n"); ++ cifs_dbg(FYI, "source and target of copy not on same server\n"); + goto out; + } + +diff --git a/fs/smb/client/file.c b/fs/smb/client/file.c +index 9be37d0fe724e..4784fece4d994 100644 +--- a/fs/smb/client/file.c ++++ b/fs/smb/client/file.c +@@ -2753,7 +2753,7 @@ static void cifs_extend_writeback(struct address_space *mapping, + break; + } + +- if (!folio_try_get_rcu(folio)) { ++ if (!folio_try_get(folio)) { + xas_reset(xas); + continue; + } +@@ -2989,7 +2989,7 @@ static ssize_t cifs_writepages_begin(struct address_space *mapping, + if (!folio) + break; + +- if (!folio_try_get_rcu(folio)) { ++ if (!folio_try_get(folio)) { + xas_reset(xas); + continue; + } +diff --git a/fs/smb/common/smb2pdu.h b/fs/smb/common/smb2pdu.h +index 202ff91281560..694d2b4a4ad99 100644 +--- a/fs/smb/common/smb2pdu.h ++++ b/fs/smb/common/smb2pdu.h +@@ -917,6 +917,40 @@ struct smb2_query_directory_rsp { + __u8 Buffer[]; + } __packed; + ++/* DeviceType Flags */ ++#define FILE_DEVICE_CD_ROM 0x00000002 ++#define FILE_DEVICE_CD_ROM_FILE_SYSTEM 0x00000003 ++#define FILE_DEVICE_DFS 0x00000006 ++#define FILE_DEVICE_DISK 0x00000007 ++#define FILE_DEVICE_DISK_FILE_SYSTEM 0x00000008 ++#define FILE_DEVICE_FILE_SYSTEM 0x00000009 ++#define FILE_DEVICE_NAMED_PIPE 0x00000011 ++#define FILE_DEVICE_NETWORK 0x00000012 ++#define FILE_DEVICE_NETWORK_FILE_SYSTEM 0x00000014 ++#define FILE_DEVICE_NULL 0x00000015 ++#define FILE_DEVICE_PARALLEL_PORT 0x00000016 ++#define FILE_DEVICE_PRINTER 0x00000018 ++#define FILE_DEVICE_SERIAL_PORT 0x0000001b ++#define FILE_DEVICE_STREAMS 0x0000001e ++#define FILE_DEVICE_TAPE 0x0000001f ++#define FILE_DEVICE_TAPE_FILE_SYSTEM 0x00000020 ++#define FILE_DEVICE_VIRTUAL_DISK 0x00000024 ++#define FILE_DEVICE_NETWORK_REDIRECTOR 0x00000028 ++ ++/* Device Characteristics */ ++#define FILE_REMOVABLE_MEDIA 0x00000001 ++#define FILE_READ_ONLY_DEVICE 0x00000002 ++#define FILE_FLOPPY_DISKETTE 0x00000004 ++#define FILE_WRITE_ONCE_MEDIA 0x00000008 ++#define FILE_REMOTE_DEVICE 0x00000010 ++#define FILE_DEVICE_IS_MOUNTED 0x00000020 ++#define FILE_VIRTUAL_VOLUME 0x00000040 ++#define FILE_DEVICE_SECURE_OPEN 0x00000100 ++#define FILE_CHARACTERISTIC_TS_DEVICE 0x00001000 ++#define FILE_CHARACTERISTIC_WEBDAV_DEVICE 0x00002000 ++#define FILE_PORTABLE_DEVICE 0x00004000 ++#define FILE_DEVICE_ALLOW_APPCONTAINER_TRAVERSAL 0x00020000 ++ + /* + * Maximum number of iovs we need for a set-info request. + * The largest one is rename/hardlink +diff --git a/fs/smb/server/smb2pdu.c b/fs/smb/server/smb2pdu.c +index 7d26fdcebbf98..840c71c66b30b 100644 +--- a/fs/smb/server/smb2pdu.c ++++ b/fs/smb/server/smb2pdu.c +@@ -5323,8 +5323,13 @@ static int smb2_get_info_filesystem(struct ksmbd_work *work, + + info = (struct filesystem_device_info *)rsp->Buffer; + +- info->DeviceType = cpu_to_le32(stfs.f_type); +- info->DeviceCharacteristics = cpu_to_le32(0x00000020); ++ info->DeviceType = cpu_to_le32(FILE_DEVICE_DISK); ++ info->DeviceCharacteristics = ++ cpu_to_le32(FILE_DEVICE_IS_MOUNTED); ++ if (!test_tree_conn_flag(work->tcon, ++ KSMBD_TREE_CONN_FLAG_WRITABLE)) ++ info->DeviceCharacteristics |= ++ cpu_to_le32(FILE_READ_ONLY_DEVICE); + rsp->OutputBufferLength = cpu_to_le32(8); + break; + } +diff --git a/include/linux/cdrom.h b/include/linux/cdrom.h +index 98c6fd0b39b63..fdfb61ccf55ae 100644 +--- a/include/linux/cdrom.h ++++ b/include/linux/cdrom.h +@@ -77,7 +77,7 @@ struct cdrom_device_ops { + unsigned int clearing, int slot); + int (*tray_move) (struct cdrom_device_info *, int); + int (*lock_door) (struct cdrom_device_info *, int); +- int (*select_speed) (struct cdrom_device_info *, int); ++ int (*select_speed) (struct cdrom_device_info *, unsigned long); + int (*get_last_session) (struct cdrom_device_info *, + struct cdrom_multisession *); + int (*get_mcn) (struct cdrom_device_info *, +diff --git a/include/linux/fscache-cache.h b/include/linux/fscache-cache.h +index bdf7f3eddf0a2..4c91a019972b6 100644 +--- a/include/linux/fscache-cache.h ++++ b/include/linux/fscache-cache.h +@@ -19,6 +19,7 @@ + enum fscache_cache_trace; + enum fscache_cookie_trace; + enum fscache_access_trace; ++enum fscache_volume_trace; + + enum fscache_cache_state { + FSCACHE_CACHE_IS_NOT_PRESENT, /* No cache is present for this name */ +@@ -97,6 +98,11 @@ extern void fscache_withdraw_cookie(struct fscache_cookie *cookie); + + extern void fscache_io_error(struct fscache_cache *cache); + ++extern struct fscache_volume * ++fscache_try_get_volume(struct fscache_volume *volume, ++ enum fscache_volume_trace where); ++extern void fscache_put_volume(struct fscache_volume *volume, ++ enum fscache_volume_trace where); + extern void fscache_end_volume_access(struct fscache_volume *volume, + struct fscache_cookie *cookie, + enum fscache_access_trace why); +diff --git a/include/linux/page_ref.h b/include/linux/page_ref.h +index d7c2d33baa7f8..fdd2a75adb037 100644 +--- a/include/linux/page_ref.h ++++ b/include/linux/page_ref.h +@@ -263,54 +263,9 @@ static inline bool folio_try_get(struct folio *folio) + return folio_ref_add_unless(folio, 1, 0); + } + +-static inline bool folio_ref_try_add_rcu(struct folio *folio, int count) +-{ +-#ifdef CONFIG_TINY_RCU +- /* +- * The caller guarantees the folio will not be freed from interrupt +- * context, so (on !SMP) we only need preemption to be disabled +- * and TINY_RCU does that for us. +- */ +-# ifdef CONFIG_PREEMPT_COUNT +- VM_BUG_ON(!in_atomic() && !irqs_disabled()); +-# endif +- VM_BUG_ON_FOLIO(folio_ref_count(folio) == 0, folio); +- folio_ref_add(folio, count); +-#else +- if (unlikely(!folio_ref_add_unless(folio, count, 0))) { +- /* Either the folio has been freed, or will be freed. */ +- return false; +- } +-#endif +- return true; +-} +- +-/** +- * folio_try_get_rcu - Attempt to increase the refcount on a folio. +- * @folio: The folio. +- * +- * This is a version of folio_try_get() optimised for non-SMP kernels. +- * If you are still holding the rcu_read_lock() after looking up the +- * page and know that the page cannot have its refcount decreased to +- * zero in interrupt context, you can use this instead of folio_try_get(). +- * +- * Example users include get_user_pages_fast() (as pages are not unmapped +- * from interrupt context) and the page cache lookups (as pages are not +- * truncated from interrupt context). We also know that pages are not +- * frozen in interrupt context for the purposes of splitting or migration. +- * +- * You can also use this function if you're holding a lock that prevents +- * pages being frozen & removed; eg the i_pages lock for the page cache +- * or the mmap_lock or page table lock for page tables. In this case, +- * it will always succeed, and you could have used a plain folio_get(), +- * but it's sometimes more convenient to have a common function called +- * from both locked and RCU-protected contexts. +- * +- * Return: True if the reference count was successfully incremented. +- */ +-static inline bool folio_try_get_rcu(struct folio *folio) ++static inline bool folio_ref_try_add(struct folio *folio, int count) + { +- return folio_ref_try_add_rcu(folio, 1); ++ return folio_ref_add_unless(folio, count, 0); + } + + static inline int page_ref_freeze(struct page *page, int count) +diff --git a/include/linux/pnp.h b/include/linux/pnp.h +index ddbe7c3ca4ce2..314892a6de8a0 100644 +--- a/include/linux/pnp.h ++++ b/include/linux/pnp.h +@@ -435,8 +435,6 @@ struct pnp_protocol { + #define protocol_for_each_dev(protocol, dev) \ + list_for_each_entry(dev, &(protocol)->devices, protocol_list) + +-extern const struct bus_type pnp_bus_type; +- + #if defined(CONFIG_PNP) + + /* device management */ +diff --git a/include/linux/spi/spi.h b/include/linux/spi/spi.h +index 64a4deb18dd00..afe6631da1bc6 100644 +--- a/include/linux/spi/spi.h ++++ b/include/linux/spi/spi.h +@@ -1089,12 +1089,13 @@ struct spi_transfer { + unsigned dummy_data:1; + unsigned cs_off:1; + unsigned cs_change:1; +- unsigned tx_nbits:3; +- unsigned rx_nbits:3; ++ unsigned tx_nbits:4; ++ unsigned rx_nbits:4; + unsigned timestamped:1; + #define SPI_NBITS_SINGLE 0x01 /* 1-bit transfer */ + #define SPI_NBITS_DUAL 0x02 /* 2-bit transfer */ + #define SPI_NBITS_QUAD 0x04 /* 4-bit transfer */ ++#define SPI_NBITS_OCTAL 0x08 /* 8-bit transfer */ + u8 bits_per_word; + struct spi_delay delay; + struct spi_delay cs_change_delay; +diff --git a/include/linux/vfio.h b/include/linux/vfio.h +index 8b1a298204091..000a6cab2d318 100644 +--- a/include/linux/vfio.h ++++ b/include/linux/vfio.h +@@ -64,6 +64,7 @@ struct vfio_device { + struct completion comp; + struct iommufd_access *iommufd_access; + void (*put_kvm)(struct kvm *kvm); ++ struct inode *inode; + #if IS_ENABLED(CONFIG_IOMMUFD) + struct iommufd_device *iommufd_device; + u8 iommufd_attached:1; +diff --git a/include/linux/vfio_pci_core.h b/include/linux/vfio_pci_core.h +index a2c8b8bba7119..f87067438ed48 100644 +--- a/include/linux/vfio_pci_core.h ++++ b/include/linux/vfio_pci_core.h +@@ -93,8 +93,6 @@ struct vfio_pci_core_device { + struct list_head sriov_pfs_item; + struct vfio_pci_core_device *sriov_pf_core_dev; + struct notifier_block nb; +- struct mutex vma_lock; +- struct list_head vma_list; + struct rw_semaphore memory_lock; + }; + +diff --git a/include/net/bluetooth/hci_sync.h b/include/net/bluetooth/hci_sync.h +index 6a9d063e9f472..534c3386e714f 100644 +--- a/include/net/bluetooth/hci_sync.h ++++ b/include/net/bluetooth/hci_sync.h +@@ -38,6 +38,8 @@ int __hci_cmd_sync_status(struct hci_dev *hdev, u16 opcode, u32 plen, + int __hci_cmd_sync_status_sk(struct hci_dev *hdev, u16 opcode, u32 plen, + const void *param, u8 event, u32 timeout, + struct sock *sk); ++int hci_cmd_sync_status(struct hci_dev *hdev, u16 opcode, u32 plen, ++ const void *param, u32 timeout); + + void hci_cmd_sync_init(struct hci_dev *hdev); + void hci_cmd_sync_clear(struct hci_dev *hdev); +diff --git a/include/sound/dmaengine_pcm.h b/include/sound/dmaengine_pcm.h +index d70c55f17df7c..94dbb23580f2f 100644 +--- a/include/sound/dmaengine_pcm.h ++++ b/include/sound/dmaengine_pcm.h +@@ -36,6 +36,7 @@ snd_pcm_uframes_t snd_dmaengine_pcm_pointer_no_residue(struct snd_pcm_substream + int snd_dmaengine_pcm_open(struct snd_pcm_substream *substream, + struct dma_chan *chan); + int snd_dmaengine_pcm_close(struct snd_pcm_substream *substream); ++int snd_dmaengine_pcm_sync_stop(struct snd_pcm_substream *substream); + + int snd_dmaengine_pcm_open_request_chan(struct snd_pcm_substream *substream, + dma_filter_fn filter_fn, void *filter_data); +diff --git a/include/trace/events/fscache.h b/include/trace/events/fscache.h +index a6190aa1b4060..f1a73aa83fbbf 100644 +--- a/include/trace/events/fscache.h ++++ b/include/trace/events/fscache.h +@@ -35,12 +35,14 @@ enum fscache_volume_trace { + fscache_volume_get_cookie, + fscache_volume_get_create_work, + fscache_volume_get_hash_collision, ++ fscache_volume_get_withdraw, + fscache_volume_free, + fscache_volume_new_acquire, + fscache_volume_put_cookie, + fscache_volume_put_create_work, + fscache_volume_put_hash_collision, + fscache_volume_put_relinquish, ++ fscache_volume_put_withdraw, + fscache_volume_see_create_work, + fscache_volume_see_hash_wake, + fscache_volume_wait_create_work, +@@ -120,12 +122,14 @@ enum fscache_access_trace { + EM(fscache_volume_get_cookie, "GET cook ") \ + EM(fscache_volume_get_create_work, "GET creat") \ + EM(fscache_volume_get_hash_collision, "GET hcoll") \ ++ EM(fscache_volume_get_withdraw, "GET withd") \ + EM(fscache_volume_free, "FREE ") \ + EM(fscache_volume_new_acquire, "NEW acq ") \ + EM(fscache_volume_put_cookie, "PUT cook ") \ + EM(fscache_volume_put_create_work, "PUT creat") \ + EM(fscache_volume_put_hash_collision, "PUT hcoll") \ + EM(fscache_volume_put_relinquish, "PUT relnq") \ ++ EM(fscache_volume_put_withdraw, "PUT withd") \ + EM(fscache_volume_see_create_work, "SEE creat") \ + EM(fscache_volume_see_hash_wake, "SEE hwake") \ + E_(fscache_volume_wait_create_work, "WAIT crea") +diff --git a/include/uapi/linux/input-event-codes.h b/include/uapi/linux/input-event-codes.h +index 03edf2ccdf6c8..a4206723f5033 100644 +--- a/include/uapi/linux/input-event-codes.h ++++ b/include/uapi/linux/input-event-codes.h +@@ -618,6 +618,8 @@ + #define KEY_CAMERA_ACCESS_ENABLE 0x24b /* Enables programmatic access to camera devices. (HUTRR72) */ + #define KEY_CAMERA_ACCESS_DISABLE 0x24c /* Disables programmatic access to camera devices. (HUTRR72) */ + #define KEY_CAMERA_ACCESS_TOGGLE 0x24d /* Toggles the current state of the camera access control. (HUTRR72) */ ++#define KEY_ACCESSIBILITY 0x24e /* Toggles the system bound accessibility UI/command (HUTRR116) */ ++#define KEY_DO_NOT_DISTURB 0x24f /* Toggles the system-wide "Do Not Disturb" control (HUTRR94)*/ + + #define KEY_BRIGHTNESS_MIN 0x250 /* Set Brightness to Minimum */ + #define KEY_BRIGHTNESS_MAX 0x251 /* Set Brightness to Maximum */ +diff --git a/io_uring/register.c b/io_uring/register.c +index 99c37775f974c..1ae8491e35abb 100644 +--- a/io_uring/register.c ++++ b/io_uring/register.c +@@ -355,8 +355,10 @@ static __cold int io_register_iowq_max_workers(struct io_ring_ctx *ctx, + } + + if (sqd) { ++ mutex_unlock(&ctx->uring_lock); + mutex_unlock(&sqd->lock); + io_put_sq_data(sqd); ++ mutex_lock(&ctx->uring_lock); + } + + if (copy_to_user(arg, new_count, sizeof(new_count))) +@@ -381,8 +383,10 @@ static __cold int io_register_iowq_max_workers(struct io_ring_ctx *ctx, + return 0; + err: + if (sqd) { ++ mutex_unlock(&ctx->uring_lock); + mutex_unlock(&sqd->lock); + io_put_sq_data(sqd); ++ mutex_lock(&ctx->uring_lock); + } + return ret; + } +diff --git a/kernel/workqueue.c b/kernel/workqueue.c +index d2dbe099286b9..7634fc32ee05a 100644 +--- a/kernel/workqueue.c ++++ b/kernel/workqueue.c +@@ -124,6 +124,7 @@ enum wq_internal_consts { + HIGHPRI_NICE_LEVEL = MIN_NICE, + + WQ_NAME_LEN = 32, ++ WORKER_ID_LEN = 10 + WQ_NAME_LEN, /* "kworker/R-" + WQ_NAME_LEN */ + }; + + /* +@@ -2778,6 +2779,26 @@ static void worker_detach_from_pool(struct worker *worker) + complete(detach_completion); + } + ++static int format_worker_id(char *buf, size_t size, struct worker *worker, ++ struct worker_pool *pool) ++{ ++ if (worker->rescue_wq) ++ return scnprintf(buf, size, "kworker/R-%s", ++ worker->rescue_wq->name); ++ ++ if (pool) { ++ if (pool->cpu >= 0) ++ return scnprintf(buf, size, "kworker/%d:%d%s", ++ pool->cpu, worker->id, ++ pool->attrs->nice < 0 ? "H" : ""); ++ else ++ return scnprintf(buf, size, "kworker/u%d:%d", ++ pool->id, worker->id); ++ } else { ++ return scnprintf(buf, size, "kworker/dying"); ++ } ++} ++ + /** + * create_worker - create a new workqueue worker + * @pool: pool the new worker will belong to +@@ -2794,7 +2815,6 @@ static struct worker *create_worker(struct worker_pool *pool) + { + struct worker *worker; + int id; +- char id_buf[23]; + + /* ID is needed to determine kthread name */ + id = ida_alloc(&pool->worker_ida, GFP_KERNEL); +@@ -2813,17 +2833,14 @@ static struct worker *create_worker(struct worker_pool *pool) + worker->id = id; + + if (!(pool->flags & POOL_BH)) { +- if (pool->cpu >= 0) +- snprintf(id_buf, sizeof(id_buf), "%d:%d%s", pool->cpu, id, +- pool->attrs->nice < 0 ? "H" : ""); +- else +- snprintf(id_buf, sizeof(id_buf), "u%d:%d", pool->id, id); ++ char id_buf[WORKER_ID_LEN]; + ++ format_worker_id(id_buf, sizeof(id_buf), worker, pool); + worker->task = kthread_create_on_node(worker_thread, worker, +- pool->node, "kworker/%s", id_buf); ++ pool->node, "%s", id_buf); + if (IS_ERR(worker->task)) { + if (PTR_ERR(worker->task) == -EINTR) { +- pr_err("workqueue: Interrupted when creating a worker thread \"kworker/%s\"\n", ++ pr_err("workqueue: Interrupted when creating a worker thread \"%s\"\n", + id_buf); + } else { + pr_err_once("workqueue: Failed to create a worker thread: %pe", +@@ -3386,7 +3403,6 @@ static int worker_thread(void *__worker) + raw_spin_unlock_irq(&pool->lock); + set_pf_worker(false); + +- set_task_comm(worker->task, "kworker/dying"); + ida_free(&pool->worker_ida, worker->id); + worker_detach_from_pool(worker); + WARN_ON_ONCE(!list_empty(&worker->entry)); +@@ -5430,6 +5446,7 @@ static int wq_clamp_max_active(int max_active, unsigned int flags, + static int init_rescuer(struct workqueue_struct *wq) + { + struct worker *rescuer; ++ char id_buf[WORKER_ID_LEN]; + int ret; + + if (!(wq->flags & WQ_MEM_RECLAIM)) +@@ -5443,7 +5460,9 @@ static int init_rescuer(struct workqueue_struct *wq) + } + + rescuer->rescue_wq = wq; +- rescuer->task = kthread_create(rescuer_thread, rescuer, "kworker/R-%s", wq->name); ++ format_worker_id(id_buf, sizeof(id_buf), rescuer, NULL); ++ ++ rescuer->task = kthread_create(rescuer_thread, rescuer, "%s", id_buf); + if (IS_ERR(rescuer->task)) { + ret = PTR_ERR(rescuer->task); + pr_err("workqueue: Failed to create a rescuer kthread for wq \"%s\": %pe", +@@ -6272,19 +6291,15 @@ void show_freezable_workqueues(void) + /* used to show worker information through /proc/PID/{comm,stat,status} */ + void wq_worker_comm(char *buf, size_t size, struct task_struct *task) + { +- int off; +- +- /* always show the actual comm */ +- off = strscpy(buf, task->comm, size); +- if (off < 0) +- return; +- + /* stabilize PF_WQ_WORKER and worker pool association */ + mutex_lock(&wq_pool_attach_mutex); + + if (task->flags & PF_WQ_WORKER) { + struct worker *worker = kthread_data(task); + struct worker_pool *pool = worker->pool; ++ int off; ++ ++ off = format_worker_id(buf, size, worker, pool); + + if (pool) { + raw_spin_lock_irq(&pool->lock); +@@ -6303,6 +6318,8 @@ void wq_worker_comm(char *buf, size_t size, struct task_struct *task) + } + raw_spin_unlock_irq(&pool->lock); + } ++ } else { ++ strscpy(buf, task->comm, size); + } + + mutex_unlock(&wq_pool_attach_mutex); +diff --git a/lib/Kconfig b/lib/Kconfig +index 4557bb8a52565..c98e11c7330ec 100644 +--- a/lib/Kconfig ++++ b/lib/Kconfig +@@ -539,13 +539,7 @@ config CPUMASK_OFFSTACK + stack overflow. + + config FORCE_NR_CPUS +- bool "Set number of CPUs at compile time" +- depends on SMP && EXPERT && !COMPILE_TEST +- help +- Say Yes if you have NR_CPUS set to an actual number of possible +- CPUs in your system, not to a default value. This forces the core +- code to rely on compile-time value and optimize kernel routines +- better. ++ def_bool !SMP + + config CPU_RMAP + bool +diff --git a/lib/closure.c b/lib/closure.c +index c16540552d61b..99380d9b4aa94 100644 +--- a/lib/closure.c ++++ b/lib/closure.c +@@ -17,12 +17,18 @@ static inline void closure_put_after_sub(struct closure *cl, int flags) + { + int r = flags & CLOSURE_REMAINING_MASK; + +- BUG_ON(flags & CLOSURE_GUARD_MASK); +- BUG_ON(!r && (flags & ~CLOSURE_DESTRUCTOR)); ++ if (WARN(flags & CLOSURE_GUARD_MASK, ++ "closure has guard bits set: %x (%u)", ++ flags & CLOSURE_GUARD_MASK, (unsigned) __fls(r))) ++ r &= ~CLOSURE_GUARD_MASK; + + if (!r) { + smp_acquire__after_ctrl_dep(); + ++ WARN(flags & ~CLOSURE_DESTRUCTOR, ++ "closure ref hit 0 with incorrect flags set: %x (%u)", ++ flags & ~CLOSURE_DESTRUCTOR, (unsigned) __fls(flags)); ++ + cl->closure_get_happened = false; + + if (cl->fn && !(flags & CLOSURE_DESTRUCTOR)) { +diff --git a/mm/filemap.c b/mm/filemap.c +index 41bf94f7dbd1b..196f70166537b 100644 +--- a/mm/filemap.c ++++ b/mm/filemap.c +@@ -1823,7 +1823,7 @@ void *filemap_get_entry(struct address_space *mapping, pgoff_t index) + if (!folio || xa_is_value(folio)) + goto out; + +- if (!folio_try_get_rcu(folio)) ++ if (!folio_try_get(folio)) + goto repeat; + + if (unlikely(folio != xas_reload(&xas))) { +@@ -1977,7 +1977,7 @@ static inline struct folio *find_get_entry(struct xa_state *xas, pgoff_t max, + if (!folio || xa_is_value(folio)) + return folio; + +- if (!folio_try_get_rcu(folio)) ++ if (!folio_try_get(folio)) + goto reset; + + if (unlikely(folio != xas_reload(xas))) { +@@ -2157,7 +2157,7 @@ unsigned filemap_get_folios_contig(struct address_space *mapping, + if (xa_is_value(folio)) + goto update_start; + +- if (!folio_try_get_rcu(folio)) ++ if (!folio_try_get(folio)) + goto retry; + + if (unlikely(folio != xas_reload(&xas))) +@@ -2289,7 +2289,7 @@ static void filemap_get_read_batch(struct address_space *mapping, + break; + if (xa_is_sibling(folio)) + break; +- if (!folio_try_get_rcu(folio)) ++ if (!folio_try_get(folio)) + goto retry; + + if (unlikely(folio != xas_reload(&xas))) +@@ -3449,7 +3449,7 @@ static struct folio *next_uptodate_folio(struct xa_state *xas, + continue; + if (folio_test_locked(folio)) + continue; +- if (!folio_try_get_rcu(folio)) ++ if (!folio_try_get(folio)) + continue; + /* Has the page moved or been split? */ + if (unlikely(folio != xas_reload(xas))) +diff --git a/mm/gup.c b/mm/gup.c +index 1611e73b1121b..ec8570d25a6c9 100644 +--- a/mm/gup.c ++++ b/mm/gup.c +@@ -76,7 +76,7 @@ static inline struct folio *try_get_folio(struct page *page, int refs) + folio = page_folio(page); + if (WARN_ON_ONCE(folio_ref_count(folio) < 0)) + return NULL; +- if (unlikely(!folio_ref_try_add_rcu(folio, refs))) ++ if (unlikely(!folio_ref_try_add(folio, refs))) + return NULL; + + /* +diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c +index 24f6b6a5c7721..2647458843c59 100644 +--- a/net/bluetooth/hci_core.c ++++ b/net/bluetooth/hci_core.c +@@ -63,50 +63,6 @@ DEFINE_MUTEX(hci_cb_list_lock); + /* HCI ID Numbering */ + static DEFINE_IDA(hci_index_ida); + +-static int hci_scan_req(struct hci_request *req, unsigned long opt) +-{ +- __u8 scan = opt; +- +- BT_DBG("%s %x", req->hdev->name, scan); +- +- /* Inquiry and Page scans */ +- hci_req_add(req, HCI_OP_WRITE_SCAN_ENABLE, 1, &scan); +- return 0; +-} +- +-static int hci_auth_req(struct hci_request *req, unsigned long opt) +-{ +- __u8 auth = opt; +- +- BT_DBG("%s %x", req->hdev->name, auth); +- +- /* Authentication */ +- hci_req_add(req, HCI_OP_WRITE_AUTH_ENABLE, 1, &auth); +- return 0; +-} +- +-static int hci_encrypt_req(struct hci_request *req, unsigned long opt) +-{ +- __u8 encrypt = opt; +- +- BT_DBG("%s %x", req->hdev->name, encrypt); +- +- /* Encryption */ +- hci_req_add(req, HCI_OP_WRITE_ENCRYPT_MODE, 1, &encrypt); +- return 0; +-} +- +-static int hci_linkpol_req(struct hci_request *req, unsigned long opt) +-{ +- __le16 policy = cpu_to_le16(opt); +- +- BT_DBG("%s %x", req->hdev->name, policy); +- +- /* Default link policy */ +- hci_req_add(req, HCI_OP_WRITE_DEF_LINK_POLICY, 2, &policy); +- return 0; +-} +- + /* Get HCI device by index. + * Device is held on return. */ + struct hci_dev *hci_dev_get(int index) +@@ -728,6 +684,7 @@ int hci_dev_cmd(unsigned int cmd, void __user *arg) + { + struct hci_dev *hdev; + struct hci_dev_req dr; ++ __le16 policy; + int err = 0; + + if (copy_from_user(&dr, arg, sizeof(dr))) +@@ -754,8 +711,8 @@ int hci_dev_cmd(unsigned int cmd, void __user *arg) + + switch (cmd) { + case HCISETAUTH: +- err = hci_req_sync(hdev, hci_auth_req, dr.dev_opt, +- HCI_INIT_TIMEOUT, NULL); ++ err = __hci_cmd_sync_status(hdev, HCI_OP_WRITE_AUTH_ENABLE, ++ 1, &dr.dev_opt, HCI_CMD_TIMEOUT); + break; + + case HCISETENCRYPT: +@@ -766,19 +723,23 @@ int hci_dev_cmd(unsigned int cmd, void __user *arg) + + if (!test_bit(HCI_AUTH, &hdev->flags)) { + /* Auth must be enabled first */ +- err = hci_req_sync(hdev, hci_auth_req, dr.dev_opt, +- HCI_INIT_TIMEOUT, NULL); ++ err = __hci_cmd_sync_status(hdev, ++ HCI_OP_WRITE_AUTH_ENABLE, ++ 1, &dr.dev_opt, ++ HCI_CMD_TIMEOUT); + if (err) + break; + } + +- err = hci_req_sync(hdev, hci_encrypt_req, dr.dev_opt, +- HCI_INIT_TIMEOUT, NULL); ++ err = __hci_cmd_sync_status(hdev, HCI_OP_WRITE_ENCRYPT_MODE, ++ 1, &dr.dev_opt, ++ HCI_CMD_TIMEOUT); + break; + + case HCISETSCAN: +- err = hci_req_sync(hdev, hci_scan_req, dr.dev_opt, +- HCI_INIT_TIMEOUT, NULL); ++ err = __hci_cmd_sync_status(hdev, HCI_OP_WRITE_SCAN_ENABLE, ++ 1, &dr.dev_opt, ++ HCI_CMD_TIMEOUT); + + /* Ensure that the connectable and discoverable states + * get correctly modified as this was a non-mgmt change. +@@ -788,8 +749,11 @@ int hci_dev_cmd(unsigned int cmd, void __user *arg) + break; + + case HCISETLINKPOL: +- err = hci_req_sync(hdev, hci_linkpol_req, dr.dev_opt, +- HCI_INIT_TIMEOUT, NULL); ++ policy = cpu_to_le16(dr.dev_opt); ++ ++ err = __hci_cmd_sync_status(hdev, HCI_OP_WRITE_DEF_LINK_POLICY, ++ 2, &policy, ++ HCI_CMD_TIMEOUT); + break; + + case HCISETLINKMODE: +@@ -2744,7 +2708,11 @@ void hci_unregister_dev(struct hci_dev *hdev) + list_del(&hdev->list); + write_unlock(&hci_dev_list_lock); + ++ cancel_work_sync(&hdev->rx_work); ++ cancel_work_sync(&hdev->cmd_work); ++ cancel_work_sync(&hdev->tx_work); + cancel_work_sync(&hdev->power_on); ++ cancel_work_sync(&hdev->error_reset); + + hci_cmd_sync_clear(hdev); + +diff --git a/net/bluetooth/hci_sync.c b/net/bluetooth/hci_sync.c +index 7bfa6b59ba87e..51f754b6e838b 100644 +--- a/net/bluetooth/hci_sync.c ++++ b/net/bluetooth/hci_sync.c +@@ -280,6 +280,19 @@ int __hci_cmd_sync_status(struct hci_dev *hdev, u16 opcode, u32 plen, + } + EXPORT_SYMBOL(__hci_cmd_sync_status); + ++int hci_cmd_sync_status(struct hci_dev *hdev, u16 opcode, u32 plen, ++ const void *param, u32 timeout) ++{ ++ int err; ++ ++ hci_req_sync_lock(hdev); ++ err = __hci_cmd_sync_status(hdev, opcode, plen, param, timeout); ++ hci_req_sync_unlock(hdev); ++ ++ return err; ++} ++EXPORT_SYMBOL(hci_cmd_sync_status); ++ + static void hci_cmd_sync_work(struct work_struct *work) + { + struct hci_dev *hdev = container_of(work, struct hci_dev, cmd_sync_work); +diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c +index 9394a158d1b1a..b8ff522589cd9 100644 +--- a/net/bluetooth/l2cap_core.c ++++ b/net/bluetooth/l2cap_core.c +@@ -6762,6 +6762,8 @@ static void l2cap_conless_channel(struct l2cap_conn *conn, __le16 psm, + + BT_DBG("chan %p, len %d", chan, skb->len); + ++ l2cap_chan_lock(chan); ++ + if (chan->state != BT_BOUND && chan->state != BT_CONNECTED) + goto drop; + +@@ -6778,6 +6780,7 @@ static void l2cap_conless_channel(struct l2cap_conn *conn, __le16 psm, + } + + drop: ++ l2cap_chan_unlock(chan); + l2cap_chan_put(chan); + free_skb: + kfree_skb(skb); +diff --git a/net/bluetooth/l2cap_sock.c b/net/bluetooth/l2cap_sock.c +index 8645461d45e81..1bc79887a7947 100644 +--- a/net/bluetooth/l2cap_sock.c ++++ b/net/bluetooth/l2cap_sock.c +@@ -1239,6 +1239,10 @@ static void l2cap_sock_kill(struct sock *sk) + + BT_DBG("sk %p state %s", sk, state_to_string(sk->sk_state)); + ++ /* Sock is dead, so set chan data to NULL, avoid other task use invalid ++ * sock pointer. ++ */ ++ l2cap_pi(sk)->chan->data = NULL; + /* Kill poor orphan */ + + l2cap_chan_put(l2cap_pi(sk)->chan); +@@ -1481,12 +1485,16 @@ static struct l2cap_chan *l2cap_sock_new_connection_cb(struct l2cap_chan *chan) + + static int l2cap_sock_recv_cb(struct l2cap_chan *chan, struct sk_buff *skb) + { +- struct sock *sk = chan->data; +- struct l2cap_pinfo *pi = l2cap_pi(sk); ++ struct sock *sk; ++ struct l2cap_pinfo *pi; + int err; + +- lock_sock(sk); ++ sk = chan->data; ++ if (!sk) ++ return -ENXIO; + ++ pi = l2cap_pi(sk); ++ lock_sock(sk); + if (chan->mode == L2CAP_MODE_ERTM && !list_empty(&pi->rx_busy)) { + err = -ENOMEM; + goto done; +diff --git a/net/ipv6/ila/ila_lwt.c b/net/ipv6/ila/ila_lwt.c +index 0601bad798221..ff7e734e335b0 100644 +--- a/net/ipv6/ila/ila_lwt.c ++++ b/net/ipv6/ila/ila_lwt.c +@@ -58,7 +58,9 @@ static int ila_output(struct net *net, struct sock *sk, struct sk_buff *skb) + return orig_dst->lwtstate->orig_output(net, sk, skb); + } + ++ local_bh_disable(); + dst = dst_cache_get(&ilwt->dst_cache); ++ local_bh_enable(); + if (unlikely(!dst)) { + struct ipv6hdr *ip6h = ipv6_hdr(skb); + struct flowi6 fl6; +@@ -86,8 +88,11 @@ static int ila_output(struct net *net, struct sock *sk, struct sk_buff *skb) + goto drop; + } + +- if (ilwt->connected) ++ if (ilwt->connected) { ++ local_bh_disable(); + dst_cache_set_ip6(&ilwt->dst_cache, dst, &fl6.saddr); ++ local_bh_enable(); ++ } + } + + skb_dst_set(skb, dst); +diff --git a/net/ipv6/rpl_iptunnel.c b/net/ipv6/rpl_iptunnel.c +index a013b92cbb860..2c83b7586422d 100644 +--- a/net/ipv6/rpl_iptunnel.c ++++ b/net/ipv6/rpl_iptunnel.c +@@ -212,9 +212,9 @@ static int rpl_output(struct net *net, struct sock *sk, struct sk_buff *skb) + if (unlikely(err)) + goto drop; + +- preempt_disable(); ++ local_bh_disable(); + dst = dst_cache_get(&rlwt->cache); +- preempt_enable(); ++ local_bh_enable(); + + if (unlikely(!dst)) { + struct ipv6hdr *hdr = ipv6_hdr(skb); +@@ -234,9 +234,9 @@ static int rpl_output(struct net *net, struct sock *sk, struct sk_buff *skb) + goto drop; + } + +- preempt_disable(); ++ local_bh_disable(); + dst_cache_set_ip6(&rlwt->cache, dst, &fl6.saddr); +- preempt_enable(); ++ local_bh_enable(); + } + + skb_dst_drop(skb); +@@ -268,23 +268,21 @@ static int rpl_input(struct sk_buff *skb) + return err; + } + +- preempt_disable(); ++ local_bh_disable(); + dst = dst_cache_get(&rlwt->cache); +- preempt_enable(); + + if (!dst) { + ip6_route_input(skb); + dst = skb_dst(skb); + if (!dst->error) { +- preempt_disable(); + dst_cache_set_ip6(&rlwt->cache, dst, + &ipv6_hdr(skb)->saddr); +- preempt_enable(); + } + } else { + skb_dst_drop(skb); + skb_dst_set(skb, dst); + } ++ local_bh_enable(); + + err = skb_cow_head(skb, LL_RESERVED_SPACE(dst->dev)); + if (unlikely(err)) +diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c +index 51dc2d9dd6b84..d0feadfdb46e1 100644 +--- a/net/mac80211/cfg.c ++++ b/net/mac80211/cfg.c +@@ -2954,8 +2954,9 @@ static int ieee80211_set_mcast_rate(struct wiphy *wiphy, struct net_device *dev, + memcpy(sdata->vif.bss_conf.mcast_rate, rate, + sizeof(int) * NUM_NL80211_BANDS); + +- ieee80211_link_info_change_notify(sdata, &sdata->deflink, +- BSS_CHANGED_MCAST_RATE); ++ if (ieee80211_sdata_running(sdata)) ++ ieee80211_link_info_change_notify(sdata, &sdata->deflink, ++ BSS_CHANGED_MCAST_RATE); + + return 0; + } +diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h +index 70c67c860e995..48bf62e92e02e 100644 +--- a/net/mac80211/ieee80211_i.h ++++ b/net/mac80211/ieee80211_i.h +@@ -1841,6 +1841,8 @@ void ieee80211_link_info_change_notify(struct ieee80211_sub_if_data *sdata, + void ieee80211_configure_filter(struct ieee80211_local *local); + u64 ieee80211_reset_erp_info(struct ieee80211_sub_if_data *sdata); + ++void ieee80211_handle_queued_frames(struct ieee80211_local *local); ++ + u64 ieee80211_mgmt_tx_cookie(struct ieee80211_local *local); + int ieee80211_attach_ack_skb(struct ieee80211_local *local, struct sk_buff *skb, + u64 *cookie, gfp_t gfp); +diff --git a/net/mac80211/main.c b/net/mac80211/main.c +index 4eaea0a9975b4..0965ad11ec747 100644 +--- a/net/mac80211/main.c ++++ b/net/mac80211/main.c +@@ -423,9 +423,9 @@ u64 ieee80211_reset_erp_info(struct ieee80211_sub_if_data *sdata) + BSS_CHANGED_ERP_SLOT; + } + +-static void ieee80211_tasklet_handler(struct tasklet_struct *t) ++/* context: requires softirqs disabled */ ++void ieee80211_handle_queued_frames(struct ieee80211_local *local) + { +- struct ieee80211_local *local = from_tasklet(local, t, tasklet); + struct sk_buff *skb; + + while ((skb = skb_dequeue(&local->skb_queue)) || +@@ -450,6 +450,13 @@ static void ieee80211_tasklet_handler(struct tasklet_struct *t) + } + } + ++static void ieee80211_tasklet_handler(struct tasklet_struct *t) ++{ ++ struct ieee80211_local *local = from_tasklet(local, t, tasklet); ++ ++ ieee80211_handle_queued_frames(local); ++} ++ + static void ieee80211_restart_work(struct work_struct *work) + { + struct ieee80211_local *local = +diff --git a/net/mac80211/mesh.c b/net/mac80211/mesh.c +index cbc9b5e40cb35..6d4510221c98e 100644 +--- a/net/mac80211/mesh.c ++++ b/net/mac80211/mesh.c +@@ -1776,6 +1776,7 @@ void ieee80211_mesh_init_sdata(struct ieee80211_sub_if_data *sdata) + ifmsh->last_preq = jiffies; + ifmsh->next_perr = jiffies; + ifmsh->csa_role = IEEE80211_MESH_CSA_ROLE_NONE; ++ ifmsh->nonpeer_pm = NL80211_MESH_POWER_ACTIVE; + /* Allocate all mesh structures when creating the first mesh interface. */ + if (!mesh_allocated) + ieee80211s_init(); +diff --git a/net/mac80211/scan.c b/net/mac80211/scan.c +index 3da1c5c450358..b5f2df61c7f67 100644 +--- a/net/mac80211/scan.c ++++ b/net/mac80211/scan.c +@@ -358,7 +358,8 @@ static bool ieee80211_prep_hw_scan(struct ieee80211_sub_if_data *sdata) + struct cfg80211_scan_request *req; + struct cfg80211_chan_def chandef; + u8 bands_used = 0; +- int i, ielen, n_chans; ++ int i, ielen; ++ u32 *n_chans; + u32 flags = 0; + + req = rcu_dereference_protected(local->scan_req, +@@ -368,34 +369,34 @@ static bool ieee80211_prep_hw_scan(struct ieee80211_sub_if_data *sdata) + return false; + + if (ieee80211_hw_check(&local->hw, SINGLE_SCAN_ON_ALL_BANDS)) { ++ local->hw_scan_req->req.n_channels = req->n_channels; ++ + for (i = 0; i < req->n_channels; i++) { + local->hw_scan_req->req.channels[i] = req->channels[i]; + bands_used |= BIT(req->channels[i]->band); + } +- +- n_chans = req->n_channels; + } else { + do { + if (local->hw_scan_band == NUM_NL80211_BANDS) + return false; + +- n_chans = 0; ++ n_chans = &local->hw_scan_req->req.n_channels; ++ *n_chans = 0; + + for (i = 0; i < req->n_channels; i++) { + if (req->channels[i]->band != + local->hw_scan_band) + continue; +- local->hw_scan_req->req.channels[n_chans] = ++ local->hw_scan_req->req.channels[(*n_chans)++] = + req->channels[i]; +- n_chans++; ++ + bands_used |= BIT(req->channels[i]->band); + } + + local->hw_scan_band++; +- } while (!n_chans); ++ } while (!*n_chans); + } + +- local->hw_scan_req->req.n_channels = n_chans; + ieee80211_prepare_scan_chandef(&chandef); + + if (req->flags & NL80211_SCAN_FLAG_MIN_PREQ_CONTENT) +@@ -744,15 +745,21 @@ static int __ieee80211_start_scan(struct ieee80211_sub_if_data *sdata, + local->hw_scan_ies_bufsize *= n_bands; + } + +- local->hw_scan_req = kmalloc( +- sizeof(*local->hw_scan_req) + +- req->n_channels * sizeof(req->channels[0]) + +- local->hw_scan_ies_bufsize, GFP_KERNEL); ++ local->hw_scan_req = kmalloc(struct_size(local->hw_scan_req, ++ req.channels, ++ req->n_channels) + ++ local->hw_scan_ies_bufsize, ++ GFP_KERNEL); + if (!local->hw_scan_req) + return -ENOMEM; + + local->hw_scan_req->req.ssids = req->ssids; + local->hw_scan_req->req.n_ssids = req->n_ssids; ++ /* None of the channels are actually set ++ * up but let UBSAN know the boundaries. ++ */ ++ local->hw_scan_req->req.n_channels = req->n_channels; ++ + ies = (u8 *)local->hw_scan_req + + sizeof(*local->hw_scan_req) + + req->n_channels * sizeof(req->channels[0]); +diff --git a/net/mac80211/util.c b/net/mac80211/util.c +index 0da5f6082d159..cd4573723999e 100644 +--- a/net/mac80211/util.c ++++ b/net/mac80211/util.c +@@ -1567,6 +1567,10 @@ u32 ieee80211_sta_get_rates(struct ieee80211_sub_if_data *sdata, + + void ieee80211_stop_device(struct ieee80211_local *local) + { ++ local_bh_disable(); ++ ieee80211_handle_queued_frames(local); ++ local_bh_enable(); ++ + ieee80211_led_radio(local, false); + ieee80211_mod_tpt_led_trig(local, 0, IEEE80211_TPT_LEDTRIG_FL_RADIO); + +diff --git a/net/mac802154/tx.c b/net/mac802154/tx.c +index 2a6f1ed763c9b..6fbed5bb5c3e0 100644 +--- a/net/mac802154/tx.c ++++ b/net/mac802154/tx.c +@@ -34,8 +34,8 @@ void ieee802154_xmit_sync_worker(struct work_struct *work) + if (res) + goto err_tx; + +- dev->stats.tx_packets++; +- dev->stats.tx_bytes += skb->len; ++ DEV_STATS_INC(dev, tx_packets); ++ DEV_STATS_ADD(dev, tx_bytes, skb->len); + + ieee802154_xmit_complete(&local->hw, skb, false); + +@@ -90,8 +90,8 @@ ieee802154_tx(struct ieee802154_local *local, struct sk_buff *skb) + if (ret) + goto err_wake_netif_queue; + +- dev->stats.tx_packets++; +- dev->stats.tx_bytes += len; ++ DEV_STATS_INC(dev, tx_packets); ++ DEV_STATS_ADD(dev, tx_bytes, len); + } else { + local->tx_skb = skb; + queue_work(local->workqueue, &local->sync_tx_work); +diff --git a/net/wireless/rdev-ops.h b/net/wireless/rdev-ops.h +index 43897a5269b6a..755af47b88b91 100644 +--- a/net/wireless/rdev-ops.h ++++ b/net/wireless/rdev-ops.h +@@ -2,7 +2,7 @@ + /* + * Portions of this file + * Copyright(c) 2016-2017 Intel Deutschland GmbH +- * Copyright (C) 2018, 2021-2023 Intel Corporation ++ * Copyright (C) 2018, 2021-2024 Intel Corporation + */ + #ifndef __CFG80211_RDEV_OPS + #define __CFG80211_RDEV_OPS +@@ -458,6 +458,10 @@ static inline int rdev_scan(struct cfg80211_registered_device *rdev, + struct cfg80211_scan_request *request) + { + int ret; ++ ++ if (WARN_ON_ONCE(!request->n_ssids && request->ssids)) ++ return -EINVAL; ++ + trace_rdev_scan(&rdev->wiphy, request); + ret = rdev->ops->scan(&rdev->wiphy, request); + trace_rdev_return_int(&rdev->wiphy, ret); +diff --git a/net/wireless/scan.c b/net/wireless/scan.c +index ecea8c08e2701..fba5e98bf493a 100644 +--- a/net/wireless/scan.c ++++ b/net/wireless/scan.c +@@ -812,6 +812,7 @@ static int cfg80211_scan_6ghz(struct cfg80211_registered_device *rdev) + LIST_HEAD(coloc_ap_list); + bool need_scan_psc = true; + const struct ieee80211_sband_iftype_data *iftd; ++ size_t size, offs_ssids, offs_6ghz_params, offs_ies; + + rdev_req->scan_6ghz = true; + +@@ -877,10 +878,15 @@ static int cfg80211_scan_6ghz(struct cfg80211_registered_device *rdev) + spin_unlock_bh(&rdev->bss_lock); + } + +- request = kzalloc(struct_size(request, channels, n_channels) + +- sizeof(*request->scan_6ghz_params) * count + +- sizeof(*request->ssids) * rdev_req->n_ssids, +- GFP_KERNEL); ++ size = struct_size(request, channels, n_channels); ++ offs_ssids = size; ++ size += sizeof(*request->ssids) * rdev_req->n_ssids; ++ offs_6ghz_params = size; ++ size += sizeof(*request->scan_6ghz_params) * count; ++ offs_ies = size; ++ size += rdev_req->ie_len; ++ ++ request = kzalloc(size, GFP_KERNEL); + if (!request) { + cfg80211_free_coloc_ap_list(&coloc_ap_list); + return -ENOMEM; +@@ -888,8 +894,26 @@ static int cfg80211_scan_6ghz(struct cfg80211_registered_device *rdev) + + *request = *rdev_req; + request->n_channels = 0; +- request->scan_6ghz_params = +- (void *)&request->channels[n_channels]; ++ request->n_6ghz_params = 0; ++ if (rdev_req->n_ssids) { ++ /* ++ * Add the ssids from the parent scan request to the new ++ * scan request, so the driver would be able to use them ++ * in its probe requests to discover hidden APs on PSC ++ * channels. ++ */ ++ request->ssids = (void *)request + offs_ssids; ++ memcpy(request->ssids, rdev_req->ssids, ++ sizeof(*request->ssids) * request->n_ssids); ++ } ++ request->scan_6ghz_params = (void *)request + offs_6ghz_params; ++ ++ if (rdev_req->ie_len) { ++ void *ie = (void *)request + offs_ies; ++ ++ memcpy(ie, rdev_req->ie, rdev_req->ie_len); ++ request->ie = ie; ++ } + + /* + * PSC channels should not be scanned in case of direct scan with 1 SSID +@@ -978,17 +1002,8 @@ static int cfg80211_scan_6ghz(struct cfg80211_registered_device *rdev) + + if (request->n_channels) { + struct cfg80211_scan_request *old = rdev->int_scan_req; +- rdev->int_scan_req = request; + +- /* +- * Add the ssids from the parent scan request to the new scan +- * request, so the driver would be able to use them in its +- * probe requests to discover hidden APs on PSC channels. +- */ +- request->ssids = (void *)&request->channels[request->n_channels]; +- request->n_ssids = rdev_req->n_ssids; +- memcpy(request->ssids, rdev_req->ssids, sizeof(*request->ssids) * +- request->n_ssids); ++ rdev->int_scan_req = request; + + /* + * If this scan follows a previous scan, save the scan start +@@ -3396,10 +3411,14 @@ int cfg80211_wext_siwscan(struct net_device *dev, + wiphy = &rdev->wiphy; + + /* Determine number of channels, needed to allocate creq */ +- if (wreq && wreq->num_channels) ++ if (wreq && wreq->num_channels) { ++ /* Passed from userspace so should be checked */ ++ if (unlikely(wreq->num_channels > IW_MAX_FREQUENCIES)) ++ return -EINVAL; + n_channels = wreq->num_channels; +- else ++ } else { + n_channels = ieee80211_get_num_supported_channels(wiphy); ++ } + + creq = kzalloc(sizeof(*creq) + sizeof(struct cfg80211_ssid) + + n_channels * sizeof(void *), +@@ -3473,8 +3492,10 @@ int cfg80211_wext_siwscan(struct net_device *dev, + memcpy(creq->ssids[0].ssid, wreq->essid, wreq->essid_len); + creq->ssids[0].ssid_len = wreq->essid_len; + } +- if (wreq->scan_type == IW_SCAN_TYPE_PASSIVE) ++ if (wreq->scan_type == IW_SCAN_TYPE_PASSIVE) { ++ creq->ssids = NULL; + creq->n_ssids = 0; ++ } + } + + for (i = 0; i < NUM_NL80211_BANDS; i++) +diff --git a/scripts/kconfig/expr.c b/scripts/kconfig/expr.c +index a290de36307ba..7866167552177 100644 +--- a/scripts/kconfig/expr.c ++++ b/scripts/kconfig/expr.c +@@ -396,35 +396,6 @@ static struct expr *expr_eliminate_yn(struct expr *e) + return e; + } + +-/* +- * bool FOO!=n => FOO +- */ +-struct expr *expr_trans_bool(struct expr *e) +-{ +- if (!e) +- return NULL; +- switch (e->type) { +- case E_AND: +- case E_OR: +- case E_NOT: +- e->left.expr = expr_trans_bool(e->left.expr); +- e->right.expr = expr_trans_bool(e->right.expr); +- break; +- case E_UNEQUAL: +- // FOO!=n -> FOO +- if (e->left.sym->type == S_TRISTATE) { +- if (e->right.sym == &symbol_no) { +- e->type = E_SYMBOL; +- e->right.sym = NULL; +- } +- } +- break; +- default: +- ; +- } +- return e; +-} +- + /* + * e1 || e2 -> ? + */ +diff --git a/scripts/kconfig/expr.h b/scripts/kconfig/expr.h +index 0158f5eac4542..f015883519b39 100644 +--- a/scripts/kconfig/expr.h ++++ b/scripts/kconfig/expr.h +@@ -288,7 +288,6 @@ void expr_free(struct expr *e); + void expr_eliminate_eq(struct expr **ep1, struct expr **ep2); + int expr_eq(struct expr *e1, struct expr *e2); + tristate expr_calc_value(struct expr *e); +-struct expr *expr_trans_bool(struct expr *e); + struct expr *expr_eliminate_dups(struct expr *e); + struct expr *expr_transform(struct expr *e); + int expr_contains_symbol(struct expr *dep, struct symbol *sym); +diff --git a/scripts/kconfig/gconf.c b/scripts/kconfig/gconf.c +index 9709aca3a30fe..9e52c7360e55b 100644 +--- a/scripts/kconfig/gconf.c ++++ b/scripts/kconfig/gconf.c +@@ -1478,7 +1478,6 @@ int main(int ac, char *av[]) + + conf_parse(name); + fixup_rootmenu(&rootmenu); +- conf_read(NULL); + + /* Load the interface and connect signals */ + init_main_window(glade_file); +@@ -1486,6 +1485,8 @@ int main(int ac, char *av[]) + init_left_tree(); + init_right_tree(); + ++ conf_read(NULL); ++ + switch (view_mode) { + case SINGLE_VIEW: + display_tree_part(); +diff --git a/scripts/kconfig/menu.c b/scripts/kconfig/menu.c +index 3b822cd110f47..8b48a80e7e168 100644 +--- a/scripts/kconfig/menu.c ++++ b/scripts/kconfig/menu.c +@@ -379,8 +379,6 @@ static void _menu_finalize(struct menu *parent, bool inside_choice) + dep = expr_transform(dep); + dep = expr_alloc_and(expr_copy(basedep), dep); + dep = expr_eliminate_dups(dep); +- if (menu->sym && menu->sym->type != S_TRISTATE) +- dep = expr_trans_bool(dep); + prop->visible.expr = dep; + + /* +diff --git a/sound/core/pcm_dmaengine.c b/sound/core/pcm_dmaengine.c +index 494ec0c207fad..e299e8634751f 100644 +--- a/sound/core/pcm_dmaengine.c ++++ b/sound/core/pcm_dmaengine.c +@@ -349,6 +349,16 @@ int snd_dmaengine_pcm_open_request_chan(struct snd_pcm_substream *substream, + } + EXPORT_SYMBOL_GPL(snd_dmaengine_pcm_open_request_chan); + ++int snd_dmaengine_pcm_sync_stop(struct snd_pcm_substream *substream) ++{ ++ struct dmaengine_pcm_runtime_data *prtd = substream_to_prtd(substream); ++ ++ dmaengine_synchronize(prtd->dma_chan); ++ ++ return 0; ++} ++EXPORT_SYMBOL_GPL(snd_dmaengine_pcm_sync_stop); ++ + /** + * snd_dmaengine_pcm_close - Close a dmaengine based PCM substream + * @substream: PCM substream +@@ -358,6 +368,12 @@ EXPORT_SYMBOL_GPL(snd_dmaengine_pcm_open_request_chan); + int snd_dmaengine_pcm_close(struct snd_pcm_substream *substream) + { + struct dmaengine_pcm_runtime_data *prtd = substream_to_prtd(substream); ++ struct dma_tx_state state; ++ enum dma_status status; ++ ++ status = dmaengine_tx_status(prtd->dma_chan, prtd->cookie, &state); ++ if (status == DMA_PAUSED) ++ dmaengine_terminate_async(prtd->dma_chan); + + dmaengine_synchronize(prtd->dma_chan); + kfree(prtd); +@@ -378,6 +394,12 @@ EXPORT_SYMBOL_GPL(snd_dmaengine_pcm_close); + int snd_dmaengine_pcm_close_release_chan(struct snd_pcm_substream *substream) + { + struct dmaengine_pcm_runtime_data *prtd = substream_to_prtd(substream); ++ struct dma_tx_state state; ++ enum dma_status status; ++ ++ status = dmaengine_tx_status(prtd->dma_chan, prtd->cookie, &state); ++ if (status == DMA_PAUSED) ++ dmaengine_terminate_async(prtd->dma_chan); + + dmaengine_synchronize(prtd->dma_chan); + dma_release_channel(prtd->dma_chan); +diff --git a/sound/core/pcm_native.c b/sound/core/pcm_native.c +index 0b76e76823d28..353ecd960a1f5 100644 +--- a/sound/core/pcm_native.c ++++ b/sound/core/pcm_native.c +@@ -1775,6 +1775,8 @@ static int snd_pcm_pre_resume(struct snd_pcm_substream *substream, + snd_pcm_state_t state) + { + struct snd_pcm_runtime *runtime = substream->runtime; ++ if (runtime->state != SNDRV_PCM_STATE_SUSPENDED) ++ return -EBADFD; + if (!(runtime->info & SNDRV_PCM_INFO_RESUME)) + return -ENOSYS; + runtime->trigger_master = substream; +diff --git a/sound/pci/hda/Kconfig b/sound/pci/hda/Kconfig +index f806636242ee9..b6869fe019f29 100644 +--- a/sound/pci/hda/Kconfig ++++ b/sound/pci/hda/Kconfig +@@ -160,6 +160,7 @@ config SND_HDA_SCODEC_CS35L56_I2C + depends on ACPI || COMPILE_TEST + depends on SND_SOC + select FW_CS_DSP ++ imply SERIAL_MULTI_INSTANTIATE + select SND_HDA_GENERIC + select SND_SOC_CS35L56_SHARED + select SND_HDA_SCODEC_CS35L56 +@@ -176,6 +177,7 @@ config SND_HDA_SCODEC_CS35L56_SPI + depends on ACPI || COMPILE_TEST + depends on SND_SOC + select FW_CS_DSP ++ imply SERIAL_MULTI_INSTANTIATE + select SND_HDA_GENERIC + select SND_SOC_CS35L56_SHARED + select SND_HDA_SCODEC_CS35L56 +diff --git a/sound/pci/hda/cs35l41_hda_property.c b/sound/pci/hda/cs35l41_hda_property.c +index 4f5e581cdd5ff..16cf62f06d2ca 100644 +--- a/sound/pci/hda/cs35l41_hda_property.c ++++ b/sound/pci/hda/cs35l41_hda_property.c +@@ -118,6 +118,10 @@ static const struct cs35l41_config cs35l41_config_table[] = { + { "17AA38B5", 2, EXTERNAL, { CS35L41_LEFT, CS35L41_RIGHT, 0, 0 }, 0, 1, -1, 0, 0, 0 }, + { "17AA38B6", 2, EXTERNAL, { CS35L41_LEFT, CS35L41_RIGHT, 0, 0 }, 0, 1, -1, 0, 0, 0 }, + { "17AA38B7", 2, EXTERNAL, { CS35L41_LEFT, CS35L41_RIGHT, 0, 0 }, 0, 1, -1, 0, 0, 0 }, ++ { "17AA38C7", 4, INTERNAL, { CS35L41_RIGHT, CS35L41_LEFT, CS35L41_RIGHT, CS35L41_LEFT }, 0, 2, -1, 1000, 4500, 24 }, ++ { "17AA38C8", 4, INTERNAL, { CS35L41_RIGHT, CS35L41_LEFT, CS35L41_RIGHT, CS35L41_LEFT }, 0, 2, -1, 1000, 4500, 24 }, ++ { "17AA38F9", 2, EXTERNAL, { CS35L41_RIGHT, CS35L41_LEFT, 0, 0 }, 0, 2, -1, 0, 0, 0 }, ++ { "17AA38FA", 2, EXTERNAL, { CS35L41_RIGHT, CS35L41_LEFT, 0, 0 }, 0, 2, -1, 0, 0, 0 }, + {} + }; + +@@ -509,6 +513,10 @@ static const struct cs35l41_prop_model cs35l41_prop_model_table[] = { + { "CSC3551", "17AA38B5", generic_dsd_config }, + { "CSC3551", "17AA38B6", generic_dsd_config }, + { "CSC3551", "17AA38B7", generic_dsd_config }, ++ { "CSC3551", "17AA38C7", generic_dsd_config }, ++ { "CSC3551", "17AA38C8", generic_dsd_config }, ++ { "CSC3551", "17AA38F9", generic_dsd_config }, ++ { "CSC3551", "17AA38FA", generic_dsd_config }, + {} + }; + +diff --git a/sound/pci/hda/cs35l56_hda.c b/sound/pci/hda/cs35l56_hda.c +index 6b77c38a0e155..e134ede6c5aa5 100644 +--- a/sound/pci/hda/cs35l56_hda.c ++++ b/sound/pci/hda/cs35l56_hda.c +@@ -735,6 +735,8 @@ static void cs35l56_hda_unbind(struct device *dev, struct device *master, void * + if (comps[cs35l56->index].dev == dev) + memset(&comps[cs35l56->index], 0, sizeof(*comps)); + ++ cs35l56->codec = NULL; ++ + dev_dbg(cs35l56->base.dev, "Unbound\n"); + } + +@@ -840,6 +842,9 @@ static int cs35l56_hda_system_resume(struct device *dev) + + cs35l56->suspended = false; + ++ if (!cs35l56->codec) ++ return 0; ++ + ret = cs35l56_is_fw_reload_needed(&cs35l56->base); + dev_dbg(cs35l56->base.dev, "fw_reload_needed: %d\n", ret); + if (ret > 0) { +diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c +index 98f580e273e48..8a52ed9aa465c 100644 +--- a/sound/pci/hda/patch_realtek.c ++++ b/sound/pci/hda/patch_realtek.c +@@ -585,10 +585,14 @@ static void alc_shutup_pins(struct hda_codec *codec) + switch (codec->core.vendor_id) { + case 0x10ec0236: + case 0x10ec0256: ++ case 0x10ec0257: + case 0x19e58326: + case 0x10ec0283: ++ case 0x10ec0285: + case 0x10ec0286: ++ case 0x10ec0287: + case 0x10ec0288: ++ case 0x10ec0295: + case 0x10ec0298: + alc_headset_mic_no_shutup(codec); + break; +@@ -10035,6 +10039,7 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = { + SND_PCI_QUIRK(0x103c, 0x8788, "HP OMEN 15", ALC285_FIXUP_HP_MUTE_LED), + SND_PCI_QUIRK(0x103c, 0x87b7, "HP Laptop 14-fq0xxx", ALC236_FIXUP_HP_MUTE_LED_COEFBIT2), + SND_PCI_QUIRK(0x103c, 0x87c8, "HP", ALC287_FIXUP_HP_GPIO_LED), ++ SND_PCI_QUIRK(0x103c, 0x87d3, "HP Laptop 15-gw0xxx", ALC236_FIXUP_HP_MUTE_LED_COEFBIT2), + SND_PCI_QUIRK(0x103c, 0x87e5, "HP ProBook 440 G8 Notebook PC", ALC236_FIXUP_HP_GPIO_LED), + SND_PCI_QUIRK(0x103c, 0x87e7, "HP ProBook 450 G8 Notebook PC", ALC236_FIXUP_HP_GPIO_LED), + SND_PCI_QUIRK(0x103c, 0x87f1, "HP ProBook 630 G8 Notebook PC", ALC236_FIXUP_HP_GPIO_LED), +@@ -10538,10 +10543,14 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = { + SND_PCI_QUIRK(0x17aa, 0x38be, "Yoga S980-14.5 proX YC Dual", ALC287_FIXUP_TAS2781_I2C), + SND_PCI_QUIRK(0x17aa, 0x38bf, "Yoga S980-14.5 proX LX Dual", ALC287_FIXUP_TAS2781_I2C), + SND_PCI_QUIRK(0x17aa, 0x38c3, "Y980 DUAL", ALC287_FIXUP_TAS2781_I2C), ++ SND_PCI_QUIRK(0x17aa, 0x38c7, "Thinkbook 13x Gen 4", ALC287_FIXUP_CS35L41_I2C_4), ++ SND_PCI_QUIRK(0x17aa, 0x38c8, "Thinkbook 13x Gen 4", ALC287_FIXUP_CS35L41_I2C_4), + SND_PCI_QUIRK(0x17aa, 0x38cb, "Y790 YG DUAL", ALC287_FIXUP_TAS2781_I2C), + SND_PCI_QUIRK(0x17aa, 0x38cd, "Y790 VECO DUAL", ALC287_FIXUP_TAS2781_I2C), + SND_PCI_QUIRK(0x17aa, 0x38d2, "Lenovo Yoga 9 14IMH9", ALC287_FIXUP_YOGA9_14IMH9_BASS_SPK_PIN), + SND_PCI_QUIRK(0x17aa, 0x38d7, "Lenovo Yoga 9 14IMH9", ALC287_FIXUP_YOGA9_14IMH9_BASS_SPK_PIN), ++ SND_PCI_QUIRK(0x17aa, 0x38f9, "Thinkbook 16P Gen5", ALC287_FIXUP_CS35L41_I2C_2), ++ SND_PCI_QUIRK(0x17aa, 0x38fa, "Thinkbook 16P Gen5", ALC287_FIXUP_CS35L41_I2C_2), + SND_PCI_QUIRK(0x17aa, 0x3902, "Lenovo E50-80", ALC269_FIXUP_DMIC_THINKPAD_ACPI), + SND_PCI_QUIRK(0x17aa, 0x3977, "IdeaPad S210", ALC283_FIXUP_INT_MIC), + SND_PCI_QUIRK(0x17aa, 0x3978, "Lenovo B50-70", ALC269_FIXUP_DMIC_THINKPAD_ACPI), +diff --git a/sound/soc/amd/yc/acp6x-mach.c b/sound/soc/amd/yc/acp6x-mach.c +index 1760b5d42460a..4e3a8ce690a45 100644 +--- a/sound/soc/amd/yc/acp6x-mach.c ++++ b/sound/soc/amd/yc/acp6x-mach.c +@@ -283,6 +283,13 @@ static const struct dmi_system_id yc_acp_quirk_table[] = { + DMI_MATCH(DMI_PRODUCT_NAME, "M5402RA"), + } + }, ++ { ++ .driver_data = &acp6x_card, ++ .matches = { ++ DMI_MATCH(DMI_BOARD_VENDOR, "ASUSTeK COMPUTER INC."), ++ DMI_MATCH(DMI_PRODUCT_NAME, "M5602RA"), ++ } ++ }, + { + .driver_data = &acp6x_card, + .matches = { +diff --git a/sound/soc/codecs/cs35l56-shared.c b/sound/soc/codecs/cs35l56-shared.c +index fd02b621da52c..d29878af2a80d 100644 +--- a/sound/soc/codecs/cs35l56-shared.c ++++ b/sound/soc/codecs/cs35l56-shared.c +@@ -214,6 +214,10 @@ static const struct reg_sequence cs35l56_asp1_defaults[] = { + REG_SEQ0(CS35L56_ASP1_FRAME_CONTROL5, 0x00020100), + REG_SEQ0(CS35L56_ASP1_DATA_CONTROL1, 0x00000018), + REG_SEQ0(CS35L56_ASP1_DATA_CONTROL5, 0x00000018), ++ REG_SEQ0(CS35L56_ASP1TX1_INPUT, 0x00000000), ++ REG_SEQ0(CS35L56_ASP1TX2_INPUT, 0x00000000), ++ REG_SEQ0(CS35L56_ASP1TX3_INPUT, 0x00000000), ++ REG_SEQ0(CS35L56_ASP1TX4_INPUT, 0x00000000), + }; + + /* +diff --git a/sound/soc/codecs/es8326.c b/sound/soc/codecs/es8326.c +index 17bd6b5160772..8b2328d5d0c74 100644 +--- a/sound/soc/codecs/es8326.c ++++ b/sound/soc/codecs/es8326.c +@@ -865,12 +865,16 @@ static void es8326_jack_detect_handler(struct work_struct *work) + * set auto-check mode, then restart jack_detect_work after 400ms. + * Don't report jack status. + */ +- regmap_write(es8326->regmap, ES8326_INT_SOURCE, +- (ES8326_INT_SRC_PIN9 | ES8326_INT_SRC_BUTTON)); ++ regmap_write(es8326->regmap, ES8326_INT_SOURCE, 0x00); + regmap_update_bits(es8326->regmap, ES8326_HPDET_TYPE, 0x03, 0x01); ++ regmap_update_bits(es8326->regmap, ES8326_HPDET_TYPE, 0x10, 0x00); + es8326_enable_micbias(es8326->component); + usleep_range(50000, 70000); + regmap_update_bits(es8326->regmap, ES8326_HPDET_TYPE, 0x03, 0x00); ++ regmap_update_bits(es8326->regmap, ES8326_HPDET_TYPE, 0x10, 0x10); ++ usleep_range(50000, 70000); ++ regmap_write(es8326->regmap, ES8326_INT_SOURCE, ++ (ES8326_INT_SRC_PIN9 | ES8326_INT_SRC_BUTTON)); + regmap_write(es8326->regmap, ES8326_SYS_BIAS, 0x1f); + regmap_update_bits(es8326->regmap, ES8326_HP_DRIVER_REF, 0x0f, 0x08); + queue_delayed_work(system_wq, &es8326->jack_detect_work, +diff --git a/sound/soc/codecs/rt722-sdca-sdw.c b/sound/soc/codecs/rt722-sdca-sdw.c +index 65d584c1886e8..543a3fa1f5d3c 100644 +--- a/sound/soc/codecs/rt722-sdca-sdw.c ++++ b/sound/soc/codecs/rt722-sdca-sdw.c +@@ -68,6 +68,7 @@ static bool rt722_sdca_mbq_readable_register(struct device *dev, unsigned int re + case 0x200007f: + case 0x2000082 ... 0x200008e: + case 0x2000090 ... 0x2000094: ++ case 0x3110000: + case 0x5300000 ... 0x5300002: + case 0x5400002: + case 0x5600000 ... 0x5600007: +@@ -125,6 +126,7 @@ static bool rt722_sdca_mbq_volatile_register(struct device *dev, unsigned int re + case 0x2000067: + case 0x2000084: + case 0x2000086: ++ case 0x3110000: + return true; + default: + return false; +@@ -350,7 +352,7 @@ static int rt722_sdca_interrupt_callback(struct sdw_slave *slave, + + if (status->sdca_cascade && !rt722->disable_irq) + mod_delayed_work(system_power_efficient_wq, +- &rt722->jack_detect_work, msecs_to_jiffies(30)); ++ &rt722->jack_detect_work, msecs_to_jiffies(280)); + + mutex_unlock(&rt722->disable_irq_lock); + +diff --git a/sound/soc/intel/avs/topology.c b/sound/soc/intel/avs/topology.c +index 42b42903ae9de..691d16ce95a0f 100644 +--- a/sound/soc/intel/avs/topology.c ++++ b/sound/soc/intel/avs/topology.c +@@ -1545,8 +1545,8 @@ static int avs_route_load(struct snd_soc_component *comp, int index, + { + struct snd_soc_acpi_mach *mach = dev_get_platdata(comp->card->dev); + size_t len = SNDRV_CTL_ELEM_ID_NAME_MAXLEN; +- char buf[SNDRV_CTL_ELEM_ID_NAME_MAXLEN]; + int ssp_port, tdm_slot; ++ char *buf; + + /* See parse_link_formatted_string() for dynamic naming when(s). */ + if (!avs_mach_singular_ssp(mach)) +@@ -1557,13 +1557,24 @@ static int avs_route_load(struct snd_soc_component *comp, int index, + return 0; + tdm_slot = avs_mach_ssp_tdm(mach, ssp_port); + ++ buf = devm_kzalloc(comp->card->dev, len, GFP_KERNEL); ++ if (!buf) ++ return -ENOMEM; + avs_ssp_sprint(buf, len, route->source, ssp_port, tdm_slot); +- strscpy((char *)route->source, buf, len); ++ route->source = buf; ++ ++ buf = devm_kzalloc(comp->card->dev, len, GFP_KERNEL); ++ if (!buf) ++ return -ENOMEM; + avs_ssp_sprint(buf, len, route->sink, ssp_port, tdm_slot); +- strscpy((char *)route->sink, buf, len); ++ route->sink = buf; ++ + if (route->control) { ++ buf = devm_kzalloc(comp->card->dev, len, GFP_KERNEL); ++ if (!buf) ++ return -ENOMEM; + avs_ssp_sprint(buf, len, route->control, ssp_port, tdm_slot); +- strscpy((char *)route->control, buf, len); ++ route->control = buf; + } + + return 0; +diff --git a/sound/soc/intel/boards/bytcr_rt5640.c b/sound/soc/intel/boards/bytcr_rt5640.c +index b41a1147f1c34..a64d1989e28a5 100644 +--- a/sound/soc/intel/boards/bytcr_rt5640.c ++++ b/sound/soc/intel/boards/bytcr_rt5640.c +@@ -610,6 +610,17 @@ static const struct dmi_system_id byt_rt5640_quirk_table[] = { + BYT_RT5640_SSP0_AIF1 | + BYT_RT5640_MCLK_EN), + }, ++ { ++ .matches = { ++ DMI_EXACT_MATCH(DMI_SYS_VENDOR, "ARCHOS"), ++ DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "ARCHOS 101 CESIUM"), ++ }, ++ .driver_data = (void *)(BYTCR_INPUT_DEFAULTS | ++ BYT_RT5640_JD_NOT_INV | ++ BYT_RT5640_DIFF_MIC | ++ BYT_RT5640_SSP0_AIF1 | ++ BYT_RT5640_MCLK_EN), ++ }, + { + .matches = { + DMI_EXACT_MATCH(DMI_SYS_VENDOR, "ARCHOS"), +diff --git a/sound/soc/soc-generic-dmaengine-pcm.c b/sound/soc/soc-generic-dmaengine-pcm.c +index 092ca09f36319..7fa75b55c65e2 100644 +--- a/sound/soc/soc-generic-dmaengine-pcm.c ++++ b/sound/soc/soc-generic-dmaengine-pcm.c +@@ -318,6 +318,12 @@ static int dmaengine_copy(struct snd_soc_component *component, + return 0; + } + ++static int dmaengine_pcm_sync_stop(struct snd_soc_component *component, ++ struct snd_pcm_substream *substream) ++{ ++ return snd_dmaengine_pcm_sync_stop(substream); ++} ++ + static const struct snd_soc_component_driver dmaengine_pcm_component = { + .name = SND_DMAENGINE_PCM_DRV_NAME, + .probe_order = SND_SOC_COMP_ORDER_LATE, +@@ -327,6 +333,7 @@ static const struct snd_soc_component_driver dmaengine_pcm_component = { + .trigger = dmaengine_pcm_trigger, + .pointer = dmaengine_pcm_pointer, + .pcm_construct = dmaengine_pcm_new, ++ .sync_stop = dmaengine_pcm_sync_stop, + }; + + static const struct snd_soc_component_driver dmaengine_pcm_component_process = { +@@ -339,6 +346,7 @@ static const struct snd_soc_component_driver dmaengine_pcm_component_process = { + .pointer = dmaengine_pcm_pointer, + .copy = dmaengine_copy, + .pcm_construct = dmaengine_pcm_new, ++ .sync_stop = dmaengine_pcm_sync_stop, + }; + + static const char * const dmaengine_pcm_dma_channel_names[] = { +diff --git a/sound/soc/soc-topology.c b/sound/soc/soc-topology.c +index ba4890991f0d7..ce22613bf9690 100644 +--- a/sound/soc/soc-topology.c ++++ b/sound/soc/soc-topology.c +@@ -1060,15 +1060,28 @@ static int soc_tplg_dapm_graph_elems_load(struct soc_tplg *tplg, + break; + } + +- route->source = elem->source; +- route->sink = elem->sink; ++ route->source = devm_kmemdup(tplg->dev, elem->source, ++ min(strlen(elem->source), ++ SNDRV_CTL_ELEM_ID_NAME_MAXLEN), ++ GFP_KERNEL); ++ route->sink = devm_kmemdup(tplg->dev, elem->sink, ++ min(strlen(elem->sink), SNDRV_CTL_ELEM_ID_NAME_MAXLEN), ++ GFP_KERNEL); ++ if (!route->source || !route->sink) { ++ ret = -ENOMEM; ++ break; ++ } + +- /* set to NULL atm for tplg users */ +- route->connected = NULL; +- if (strnlen(elem->control, SNDRV_CTL_ELEM_ID_NAME_MAXLEN) == 0) +- route->control = NULL; +- else +- route->control = elem->control; ++ if (strnlen(elem->control, SNDRV_CTL_ELEM_ID_NAME_MAXLEN) != 0) { ++ route->control = devm_kmemdup(tplg->dev, elem->control, ++ min(strlen(elem->control), ++ SNDRV_CTL_ELEM_ID_NAME_MAXLEN), ++ GFP_KERNEL); ++ if (!route->control) { ++ ret = -ENOMEM; ++ break; ++ } ++ } + + /* add route dobj to dobj_list */ + route->dobj.type = SND_SOC_DOBJ_GRAPH; +diff --git a/sound/soc/sof/intel/hda-pcm.c b/sound/soc/sof/intel/hda-pcm.c +index d7b446f3f973e..8b5fbbc777bd4 100644 +--- a/sound/soc/sof/intel/hda-pcm.c ++++ b/sound/soc/sof/intel/hda-pcm.c +@@ -254,6 +254,12 @@ int hda_dsp_pcm_open(struct snd_sof_dev *sdev, + snd_pcm_hw_constraint_integer(substream->runtime, + SNDRV_PCM_HW_PARAM_PERIODS); + ++ /* Limit the maximum number of periods to not exceed the BDL entries count */ ++ if (runtime->hw.periods_max > HDA_DSP_MAX_BDL_ENTRIES) ++ snd_pcm_hw_constraint_minmax(runtime, SNDRV_PCM_HW_PARAM_PERIODS, ++ runtime->hw.periods_min, ++ HDA_DSP_MAX_BDL_ENTRIES); ++ + /* Only S16 and S32 supported by HDA hardware when used without DSP */ + if (sdev->dspless_mode_selected) + snd_pcm_hw_constraint_mask64(substream->runtime, SNDRV_PCM_HW_PARAM_FORMAT, +diff --git a/sound/soc/sof/sof-audio.c b/sound/soc/sof/sof-audio.c +index e693dcb475e4d..d1a7d867f6a3a 100644 +--- a/sound/soc/sof/sof-audio.c ++++ b/sound/soc/sof/sof-audio.c +@@ -485,7 +485,7 @@ sof_prepare_widgets_in_path(struct snd_sof_dev *sdev, struct snd_soc_dapm_widget + if (ret < 0) { + /* unprepare the source widget */ + if (widget_ops[widget->id].ipc_unprepare && +- swidget && swidget->prepared) { ++ swidget && swidget->prepared && swidget->use_count == 0) { + widget_ops[widget->id].ipc_unprepare(swidget); + swidget->prepared = false; + } +diff --git a/sound/soc/ti/davinci-mcasp.c b/sound/soc/ti/davinci-mcasp.c +index 1e760c3155213..2b1ed91a736c9 100644 +--- a/sound/soc/ti/davinci-mcasp.c ++++ b/sound/soc/ti/davinci-mcasp.c +@@ -1472,10 +1472,11 @@ static int davinci_mcasp_hw_rule_min_periodsize( + { + struct snd_interval *period_size = hw_param_interval(params, + SNDRV_PCM_HW_PARAM_PERIOD_SIZE); ++ u8 numevt = *((u8 *)rule->private); + struct snd_interval frames; + + snd_interval_any(&frames); +- frames.min = 64; ++ frames.min = numevt; + frames.integer = 1; + + return snd_interval_refine(period_size, &frames); +@@ -1490,6 +1491,7 @@ static int davinci_mcasp_startup(struct snd_pcm_substream *substream, + u32 max_channels = 0; + int i, dir, ret; + int tdm_slots = mcasp->tdm_slots; ++ u8 *numevt; + + /* Do not allow more then one stream per direction */ + if (mcasp->substreams[substream->stream]) +@@ -1589,9 +1591,12 @@ static int davinci_mcasp_startup(struct snd_pcm_substream *substream, + return ret; + } + ++ numevt = (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) ? ++ &mcasp->txnumevt : ++ &mcasp->rxnumevt; + snd_pcm_hw_rule_add(substream->runtime, 0, + SNDRV_PCM_HW_PARAM_PERIOD_SIZE, +- davinci_mcasp_hw_rule_min_periodsize, NULL, ++ davinci_mcasp_hw_rule_min_periodsize, numevt, + SNDRV_PCM_HW_PARAM_PERIOD_SIZE, -1); + + return 0; +diff --git a/sound/soc/ti/omap-hdmi.c b/sound/soc/ti/omap-hdmi.c +index 4513b527ab970..ad8925b6481ca 100644 +--- a/sound/soc/ti/omap-hdmi.c ++++ b/sound/soc/ti/omap-hdmi.c +@@ -354,11 +354,7 @@ static int omap_hdmi_audio_probe(struct platform_device *pdev) + if (!card) + return -ENOMEM; + +- card->name = devm_kasprintf(dev, GFP_KERNEL, +- "HDMI %s", dev_name(ad->dssdev)); +- if (!card->name) +- return -ENOMEM; +- ++ card->name = "HDMI"; + card->owner = THIS_MODULE; + card->dai_link = + devm_kzalloc(dev, sizeof(*(card->dai_link)), GFP_KERNEL); +diff --git a/tools/power/cpupower/utils/helpers/amd.c b/tools/power/cpupower/utils/helpers/amd.c +index c519cc89c97f4..0a56e22240fc8 100644 +--- a/tools/power/cpupower/utils/helpers/amd.c ++++ b/tools/power/cpupower/utils/helpers/amd.c +@@ -41,6 +41,16 @@ union core_pstate { + unsigned res1:31; + unsigned en:1; + } pstatedef; ++ /* since fam 1Ah: */ ++ struct { ++ unsigned fid:12; ++ unsigned res1:2; ++ unsigned vid:8; ++ unsigned iddval:8; ++ unsigned idddiv:2; ++ unsigned res2:31; ++ unsigned en:1; ++ } pstatedef2; + unsigned long long val; + }; + +@@ -48,6 +58,10 @@ static int get_did(union core_pstate pstate) + { + int t; + ++ /* Fam 1Ah onward do not use did */ ++ if (cpupower_cpu_info.family >= 0x1A) ++ return 0; ++ + if (cpupower_cpu_info.caps & CPUPOWER_CAP_AMD_PSTATEDEF) + t = pstate.pstatedef.did; + else if (cpupower_cpu_info.family == 0x12) +@@ -61,12 +75,18 @@ static int get_did(union core_pstate pstate) + static int get_cof(union core_pstate pstate) + { + int t; +- int fid, did, cof; ++ int fid, did, cof = 0; + + did = get_did(pstate); + if (cpupower_cpu_info.caps & CPUPOWER_CAP_AMD_PSTATEDEF) { +- fid = pstate.pstatedef.fid; +- cof = 200 * fid / did; ++ if (cpupower_cpu_info.family >= 0x1A) { ++ fid = pstate.pstatedef2.fid; ++ if (fid > 0x0f) ++ cof = (fid * 5); ++ } else { ++ fid = pstate.pstatedef.fid; ++ cof = 200 * fid / did; ++ } + } else { + t = 0x10; + fid = pstate.pstate.fid; +diff --git a/tools/testing/selftests/bpf/config b/tools/testing/selftests/bpf/config +index 01f241ea2c67b..dec9fd7ebba7f 100644 +--- a/tools/testing/selftests/bpf/config ++++ b/tools/testing/selftests/bpf/config +@@ -53,9 +53,12 @@ CONFIG_MPLS=y + CONFIG_MPLS_IPTUNNEL=y + CONFIG_MPLS_ROUTING=y + CONFIG_MPTCP=y ++CONFIG_NET_ACT_SKBMOD=y ++CONFIG_NET_CLS=y + CONFIG_NET_CLS_ACT=y + CONFIG_NET_CLS_BPF=y + CONFIG_NET_CLS_FLOWER=y ++CONFIG_NET_CLS_MATCHALL=y + CONFIG_NET_FOU=y + CONFIG_NET_FOU_IP_TUNNELS=y + CONFIG_NET_IPGRE=y +diff --git a/tools/testing/selftests/bpf/prog_tests/tc_links.c b/tools/testing/selftests/bpf/prog_tests/tc_links.c +index bc98411446855..1af9ec1149aab 100644 +--- a/tools/testing/selftests/bpf/prog_tests/tc_links.c ++++ b/tools/testing/selftests/bpf/prog_tests/tc_links.c +@@ -9,6 +9,8 @@ + #define ping_cmd "ping -q -c1 -w1 127.0.0.1 > /dev/null" + + #include "test_tc_link.skel.h" ++ ++#include "netlink_helpers.h" + #include "tc_helpers.h" + + void serial_test_tc_links_basic(void) +@@ -1787,6 +1789,65 @@ void serial_test_tc_links_ingress(void) + test_tc_links_ingress(BPF_TCX_INGRESS, false, false); + } + ++struct qdisc_req { ++ struct nlmsghdr n; ++ struct tcmsg t; ++ char buf[1024]; ++}; ++ ++static int qdisc_replace(int ifindex, const char *kind, bool block) ++{ ++ struct rtnl_handle rth = { .fd = -1 }; ++ struct qdisc_req req; ++ int err; ++ ++ err = rtnl_open(&rth, 0); ++ if (!ASSERT_OK(err, "open_rtnetlink")) ++ return err; ++ ++ memset(&req, 0, sizeof(req)); ++ req.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct tcmsg)); ++ req.n.nlmsg_flags = NLM_F_CREATE | NLM_F_REPLACE | NLM_F_REQUEST; ++ req.n.nlmsg_type = RTM_NEWQDISC; ++ req.t.tcm_family = AF_UNSPEC; ++ req.t.tcm_ifindex = ifindex; ++ req.t.tcm_parent = 0xfffffff1; ++ ++ addattr_l(&req.n, sizeof(req), TCA_KIND, kind, strlen(kind) + 1); ++ if (block) ++ addattr32(&req.n, sizeof(req), TCA_INGRESS_BLOCK, 1); ++ ++ err = rtnl_talk(&rth, &req.n, NULL); ++ ASSERT_OK(err, "talk_rtnetlink"); ++ rtnl_close(&rth); ++ return err; ++} ++ ++void serial_test_tc_links_dev_chain0(void) ++{ ++ int err, ifindex; ++ ++ ASSERT_OK(system("ip link add dev foo type veth peer name bar"), "add veth"); ++ ifindex = if_nametoindex("foo"); ++ ASSERT_NEQ(ifindex, 0, "non_zero_ifindex"); ++ err = qdisc_replace(ifindex, "ingress", true); ++ if (!ASSERT_OK(err, "attaching ingress")) ++ goto cleanup; ++ ASSERT_OK(system("tc filter add block 1 matchall action skbmod swap mac"), "add block"); ++ err = qdisc_replace(ifindex, "clsact", false); ++ if (!ASSERT_OK(err, "attaching clsact")) ++ goto cleanup; ++ /* Heuristic: kern_sync_rcu() alone does not work; a wait-time of ~5s ++ * triggered the issue without the fix reliably 100% of the time. ++ */ ++ sleep(5); ++ ASSERT_OK(system("tc filter add dev foo ingress matchall action skbmod swap mac"), "add filter"); ++cleanup: ++ ASSERT_OK(system("ip link del dev foo"), "del veth"); ++ ASSERT_EQ(if_nametoindex("foo"), 0, "foo removed"); ++ ASSERT_EQ(if_nametoindex("bar"), 0, "bar removed"); ++} ++ + static void test_tc_links_dev_mixed(int target) + { + LIBBPF_OPTS(bpf_tc_opts, tc_opts, .handle = 1, .priority = 1); +diff --git a/tools/testing/selftests/cachestat/test_cachestat.c b/tools/testing/selftests/cachestat/test_cachestat.c +index b171fd53b004e..632ab44737ec3 100644 +--- a/tools/testing/selftests/cachestat/test_cachestat.c ++++ b/tools/testing/selftests/cachestat/test_cachestat.c +@@ -1,5 +1,6 @@ + // SPDX-License-Identifier: GPL-2.0 + #define _GNU_SOURCE ++#define __SANE_USERSPACE_TYPES__ // Use ll64 + + #include <stdio.h> + #include <stdbool.h> +diff --git a/tools/testing/selftests/filesystems/overlayfs/dev_in_maps.c b/tools/testing/selftests/filesystems/overlayfs/dev_in_maps.c +index 759f86e7d263e..2862aae58b79a 100644 +--- a/tools/testing/selftests/filesystems/overlayfs/dev_in_maps.c ++++ b/tools/testing/selftests/filesystems/overlayfs/dev_in_maps.c +@@ -1,5 +1,6 @@ + // SPDX-License-Identifier: GPL-2.0 + #define _GNU_SOURCE ++#define __SANE_USERSPACE_TYPES__ // Use ll64 + + #include <inttypes.h> + #include <unistd.h> +diff --git a/tools/testing/selftests/futex/functional/Makefile b/tools/testing/selftests/futex/functional/Makefile +index a392d0917b4e5..994fa3468f170 100644 +--- a/tools/testing/selftests/futex/functional/Makefile ++++ b/tools/testing/selftests/futex/functional/Makefile +@@ -1,6 +1,6 @@ + # SPDX-License-Identifier: GPL-2.0 + INCLUDES := -I../include -I../../ $(KHDR_INCLUDES) +-CFLAGS := $(CFLAGS) -g -O2 -Wall -D_GNU_SOURCE -pthread $(INCLUDES) $(KHDR_INCLUDES) ++CFLAGS := $(CFLAGS) -g -O2 -Wall -D_GNU_SOURCE= -pthread $(INCLUDES) $(KHDR_INCLUDES) + LDLIBS := -lpthread -lrt + + LOCAL_HDRS := \ +diff --git a/tools/testing/selftests/net/openvswitch/ovs-dpctl.py b/tools/testing/selftests/net/openvswitch/ovs-dpctl.py +index 5e0e539a323d5..8b120718768ec 100644 +--- a/tools/testing/selftests/net/openvswitch/ovs-dpctl.py ++++ b/tools/testing/selftests/net/openvswitch/ovs-dpctl.py +@@ -531,7 +531,7 @@ class ovsactions(nla): + for flat_act in parse_flat_map: + if parse_starts_block(actstr, flat_act[0], False): + actstr = actstr[len(flat_act[0]):] +- self["attrs"].append([flat_act[1]]) ++ self["attrs"].append([flat_act[1], True]) + actstr = actstr[strspn(actstr, ", ") :] + parsed = True + +diff --git a/tools/testing/selftests/openat2/openat2_test.c b/tools/testing/selftests/openat2/openat2_test.c +index 9024754530b23..5790ab446527f 100644 +--- a/tools/testing/selftests/openat2/openat2_test.c ++++ b/tools/testing/selftests/openat2/openat2_test.c +@@ -5,6 +5,7 @@ + */ + + #define _GNU_SOURCE ++#define __SANE_USERSPACE_TYPES__ // Use ll64 + #include <fcntl.h> + #include <sched.h> + #include <sys/stat.h> +diff --git a/tools/testing/selftests/timens/exec.c b/tools/testing/selftests/timens/exec.c +index e40dc5be2f668..d12ff955de0d8 100644 +--- a/tools/testing/selftests/timens/exec.c ++++ b/tools/testing/selftests/timens/exec.c +@@ -30,7 +30,7 @@ int main(int argc, char *argv[]) + + for (i = 0; i < 2; i++) { + _gettime(CLOCK_MONOTONIC, &tst, i); +- if (abs(tst.tv_sec - now.tv_sec) > 5) ++ if (labs(tst.tv_sec - now.tv_sec) > 5) + return pr_fail("%ld %ld\n", now.tv_sec, tst.tv_sec); + } + return 0; +@@ -50,7 +50,7 @@ int main(int argc, char *argv[]) + + for (i = 0; i < 2; i++) { + _gettime(CLOCK_MONOTONIC, &tst, i); +- if (abs(tst.tv_sec - now.tv_sec) > 5) ++ if (labs(tst.tv_sec - now.tv_sec) > 5) + return pr_fail("%ld %ld\n", + now.tv_sec, tst.tv_sec); + } +@@ -70,7 +70,7 @@ int main(int argc, char *argv[]) + /* Check that a child process is in the new timens. */ + for (i = 0; i < 2; i++) { + _gettime(CLOCK_MONOTONIC, &tst, i); +- if (abs(tst.tv_sec - now.tv_sec - OFFSET) > 5) ++ if (labs(tst.tv_sec - now.tv_sec - OFFSET) > 5) + return pr_fail("%ld %ld\n", + now.tv_sec + OFFSET, tst.tv_sec); + } +diff --git a/tools/testing/selftests/timens/timer.c b/tools/testing/selftests/timens/timer.c +index 5e7f0051bd7be..5b939f59dfa4d 100644 +--- a/tools/testing/selftests/timens/timer.c ++++ b/tools/testing/selftests/timens/timer.c +@@ -56,7 +56,7 @@ int run_test(int clockid, struct timespec now) + return pr_perror("timerfd_gettime"); + + elapsed = new_value.it_value.tv_sec; +- if (abs(elapsed - 3600) > 60) { ++ if (llabs(elapsed - 3600) > 60) { + ksft_test_result_fail("clockid: %d elapsed: %lld\n", + clockid, elapsed); + return 1; +diff --git a/tools/testing/selftests/timens/timerfd.c b/tools/testing/selftests/timens/timerfd.c +index 9edd43d6b2c13..a4196bbd6e33f 100644 +--- a/tools/testing/selftests/timens/timerfd.c ++++ b/tools/testing/selftests/timens/timerfd.c +@@ -61,7 +61,7 @@ int run_test(int clockid, struct timespec now) + return pr_perror("timerfd_gettime(%d)", clockid); + + elapsed = new_value.it_value.tv_sec; +- if (abs(elapsed - 3600) > 60) { ++ if (llabs(elapsed - 3600) > 60) { + ksft_test_result_fail("clockid: %d elapsed: %lld\n", + clockid, elapsed); + return 1; +diff --git a/tools/testing/selftests/timens/vfork_exec.c b/tools/testing/selftests/timens/vfork_exec.c +index beb7614941fb1..5b8907bf451dd 100644 +--- a/tools/testing/selftests/timens/vfork_exec.c ++++ b/tools/testing/selftests/timens/vfork_exec.c +@@ -32,7 +32,7 @@ static void *tcheck(void *_args) + + for (i = 0; i < 2; i++) { + _gettime(CLOCK_MONOTONIC, &tst, i); +- if (abs(tst.tv_sec - now->tv_sec) > 5) { ++ if (labs(tst.tv_sec - now->tv_sec) > 5) { + pr_fail("%s: in-thread: unexpected value: %ld (%ld)\n", + args->tst_name, tst.tv_sec, now->tv_sec); + return (void *)1UL; +@@ -64,7 +64,7 @@ static int check(char *tst_name, struct timespec *now) + + for (i = 0; i < 2; i++) { + _gettime(CLOCK_MONOTONIC, &tst, i); +- if (abs(tst.tv_sec - now->tv_sec) > 5) ++ if (labs(tst.tv_sec - now->tv_sec) > 5) + return pr_fail("%s: unexpected value: %ld (%ld)\n", + tst_name, tst.tv_sec, now->tv_sec); + } +diff --git a/tools/testing/selftests/vDSO/parse_vdso.c b/tools/testing/selftests/vDSO/parse_vdso.c +index 413f75620a35b..4ae417372e9eb 100644 +--- a/tools/testing/selftests/vDSO/parse_vdso.c ++++ b/tools/testing/selftests/vDSO/parse_vdso.c +@@ -55,14 +55,20 @@ static struct vdso_info + ELF(Verdef) *verdef; + } vdso_info; + +-/* Straight from the ELF specification. */ +-static unsigned long elf_hash(const unsigned char *name) ++/* ++ * Straight from the ELF specification...and then tweaked slightly, in order to ++ * avoid a few clang warnings. ++ */ ++static unsigned long elf_hash(const char *name) + { + unsigned long h = 0, g; +- while (*name) ++ const unsigned char *uch_name = (const unsigned char *)name; ++ ++ while (*uch_name) + { +- h = (h << 4) + *name++; +- if (g = h & 0xf0000000) ++ h = (h << 4) + *uch_name++; ++ g = h & 0xf0000000; ++ if (g) + h ^= g >> 24; + h &= ~g; + } +diff --git a/tools/testing/selftests/vDSO/vdso_standalone_test_x86.c b/tools/testing/selftests/vDSO/vdso_standalone_test_x86.c +index 8a44ff973ee17..27f6fdf119691 100644 +--- a/tools/testing/selftests/vDSO/vdso_standalone_test_x86.c ++++ b/tools/testing/selftests/vDSO/vdso_standalone_test_x86.c +@@ -18,7 +18,7 @@ + + #include "parse_vdso.h" + +-/* We need a libc functions... */ ++/* We need some libc functions... */ + int strcmp(const char *a, const char *b) + { + /* This implementation is buggy: it never returns -1. */ +@@ -34,6 +34,20 @@ int strcmp(const char *a, const char *b) + return 0; + } + ++/* ++ * The clang build needs this, although gcc does not. ++ * Stolen from lib/string.c. ++ */ ++void *memcpy(void *dest, const void *src, size_t count) ++{ ++ char *tmp = dest; ++ const char *s = src; ++ ++ while (count--) ++ *tmp++ = *s++; ++ return dest; ++} ++ + /* ...and two syscalls. This is x86-specific. */ + static inline long x86_syscall3(long nr, long a0, long a1, long a2) + { +@@ -70,7 +84,7 @@ void to_base10(char *lastdig, time_t n) + } + } + +-__attribute__((externally_visible)) void c_main(void **stack) ++void c_main(void **stack) + { + /* Parse the stack */ + long argc = (long)*stack; |