diff options
author | Mike Pagano <mpagano@gentoo.org> | 2021-12-14 07:12:03 -0500 |
---|---|---|
committer | Mike Pagano <mpagano@gentoo.org> | 2021-12-14 07:12:03 -0500 |
commit | 7bc0d05e4d1b0680ef4e6889c40344b985aeacfc (patch) | |
tree | 076c0577be7eddadcb867ac4a573d96dc3fed572 | |
parent | Linux 5.10.84 (diff) | |
download | linux-patches-7bc0d05e4d1b0680ef4e6889c40344b985aeacfc.tar.gz linux-patches-7bc0d05e4d1b0680ef4e6889c40344b985aeacfc.tar.bz2 linux-patches-7bc0d05e4d1b0680ef4e6889c40344b985aeacfc.zip |
Linux patch 5.10.85
Signed-off-by: Mike Pagano <mpagano@gentoo.org>
-rw-r--r-- | 0000_README | 4 | ||||
-rw-r--r-- | 1084_linux-5.10.85.patch | 6226 |
2 files changed, 6230 insertions, 0 deletions
diff --git a/0000_README b/0000_README index 19b3a8b7..9b6b1174 100644 --- a/0000_README +++ b/0000_README @@ -379,6 +379,10 @@ Patch: 1083_linux-5.10.84.patch From: http://www.kernel.org Desc: Linux 5.10.84 +Patch: 1084_linux-5.10.85.patch +From: http://www.kernel.org +Desc: Linux 5.10.85 + Patch: 1500_XATTR_USER_PREFIX.patch From: https://bugs.gentoo.org/show_bug.cgi?id=470644 Desc: Support for namespace user.pax.* on tmpfs. diff --git a/1084_linux-5.10.85.patch b/1084_linux-5.10.85.patch new file mode 100644 index 00000000..80c28595 --- /dev/null +++ b/1084_linux-5.10.85.patch @@ -0,0 +1,6226 @@ +diff --git a/Documentation/devicetree/bindings/net/ethernet-phy.yaml b/Documentation/devicetree/bindings/net/ethernet-phy.yaml +index 6dd72faebd896..a054accc20bd4 100644 +--- a/Documentation/devicetree/bindings/net/ethernet-phy.yaml ++++ b/Documentation/devicetree/bindings/net/ethernet-phy.yaml +@@ -91,6 +91,14 @@ properties: + compensate for the board being designed with the lanes + swapped. + ++ enet-phy-lane-no-swap: ++ $ref: /schemas/types.yaml#/definitions/flag ++ description: ++ If set, indicates that PHY will disable swap of the ++ TX/RX lanes. This property allows the PHY to work correcly after ++ e.g. wrong bootstrap configuration caused by issues in PCB ++ layout design. ++ + eee-broken-100tx: + $ref: /schemas/types.yaml#definitions/flag + description: +diff --git a/Documentation/kbuild/gcc-plugins.rst b/Documentation/kbuild/gcc-plugins.rst +index 4b1c10f88e304..3349966f213dc 100644 +--- a/Documentation/kbuild/gcc-plugins.rst ++++ b/Documentation/kbuild/gcc-plugins.rst +@@ -11,16 +11,13 @@ compiler [1]_. They are useful for runtime instrumentation and static analysis. + We can analyse, change and add further code during compilation via + callbacks [2]_, GIMPLE [3]_, IPA [4]_ and RTL passes [5]_. + +-The GCC plugin infrastructure of the kernel supports all gcc versions from +-4.5 to 6.0, building out-of-tree modules, cross-compilation and building in a +-separate directory. +-Plugin source files have to be compilable by both a C and a C++ compiler as well +-because gcc versions 4.5 and 4.6 are compiled by a C compiler, +-gcc-4.7 can be compiled by a C or a C++ compiler, +-and versions 4.8+ can only be compiled by a C++ compiler. ++The GCC plugin infrastructure of the kernel supports building out-of-tree ++modules, cross-compilation and building in a separate directory. ++Plugin source files have to be compilable by a C++ compiler. + +-Currently the GCC plugin infrastructure supports only the x86, arm, arm64 and +-powerpc architectures. ++Currently the GCC plugin infrastructure supports only some architectures. ++Grep "select HAVE_GCC_PLUGINS" to find out which architectures support ++GCC plugins. + + This infrastructure was ported from grsecurity [6]_ and PaX [7]_. + +@@ -47,20 +44,13 @@ Files + This is a compatibility header for GCC plugins. + It should be always included instead of individual gcc headers. + +-**$(src)/scripts/gcc-plugin.sh** +- +- This script checks the availability of the included headers in +- gcc-common.h and chooses the proper host compiler to build the plugins +- (gcc-4.7 can be built by either gcc or g++). +- + **$(src)/scripts/gcc-plugins/gcc-generate-gimple-pass.h, + $(src)/scripts/gcc-plugins/gcc-generate-ipa-pass.h, + $(src)/scripts/gcc-plugins/gcc-generate-simple_ipa-pass.h, + $(src)/scripts/gcc-plugins/gcc-generate-rtl-pass.h** + + These headers automatically generate the registration structures for +- GIMPLE, SIMPLE_IPA, IPA and RTL passes. They support all gcc versions +- from 4.5 to 6.0. ++ GIMPLE, SIMPLE_IPA, IPA and RTL passes. + They should be preferred to creating the structures by hand. + + +@@ -68,21 +58,25 @@ Usage + ===== + + You must install the gcc plugin headers for your gcc version, +-e.g., on Ubuntu for gcc-4.9:: ++e.g., on Ubuntu for gcc-10:: + +- apt-get install gcc-4.9-plugin-dev ++ apt-get install gcc-10-plugin-dev + + Or on Fedora:: + + dnf install gcc-plugin-devel + +-Enable a GCC plugin based feature in the kernel config:: ++Enable the GCC plugin infrastructure and some plugin(s) you want to use ++in the kernel config:: + +- CONFIG_GCC_PLUGIN_CYC_COMPLEXITY = y ++ CONFIG_GCC_PLUGINS=y ++ CONFIG_GCC_PLUGIN_CYC_COMPLEXITY=y ++ CONFIG_GCC_PLUGIN_LATENT_ENTROPY=y ++ ... + +-To compile only the plugin(s):: ++To compile the minimum tool set including the plugin(s):: + +- make gcc-plugins ++ make scripts + + or just run the kernel make and compile the whole kernel with + the cyclomatic complexity GCC plugin. +@@ -91,7 +85,8 @@ the cyclomatic complexity GCC plugin. + 4. How to add a new GCC plugin + ============================== + +-The GCC plugins are in $(src)/scripts/gcc-plugins/. You can use a file or a directory +-here. It must be added to $(src)/scripts/gcc-plugins/Makefile, +-$(src)/scripts/Makefile.gcc-plugins and $(src)/arch/Kconfig. ++The GCC plugins are in scripts/gcc-plugins/. You need to put plugin source files ++right under scripts/gcc-plugins/. Creating subdirectories is not supported. ++It must be added to scripts/gcc-plugins/Makefile, scripts/Makefile.gcc-plugins ++and a relevant Kconfig file. + See the cyc_complexity_plugin.c (CONFIG_GCC_PLUGIN_CYC_COMPLEXITY) GCC plugin. +diff --git a/Documentation/locking/locktypes.rst b/Documentation/locking/locktypes.rst +index ddada4a537493..4fd7b70fcde19 100644 +--- a/Documentation/locking/locktypes.rst ++++ b/Documentation/locking/locktypes.rst +@@ -439,11 +439,9 @@ preemption. The following substitution works on both kernels:: + spin_lock(&p->lock); + p->count += this_cpu_read(var2); + +-On a non-PREEMPT_RT kernel migrate_disable() maps to preempt_disable() +-which makes the above code fully equivalent. On a PREEMPT_RT kernel + migrate_disable() ensures that the task is pinned on the current CPU which + in turn guarantees that the per-CPU access to var1 and var2 are staying on +-the same CPU. ++the same CPU while the task remains preemptible. + + The migrate_disable() substitution is not valid for the following + scenario:: +@@ -456,9 +454,8 @@ scenario:: + p = this_cpu_ptr(&var1); + p->val = func2(); + +-While correct on a non-PREEMPT_RT kernel, this breaks on PREEMPT_RT because +-here migrate_disable() does not protect against reentrancy from a +-preempting task. A correct substitution for this case is:: ++This breaks because migrate_disable() does not protect against reentrancy from ++a preempting task. A correct substitution for this case is:: + + func() + { +diff --git a/MAINTAINERS b/MAINTAINERS +index 4fef10dd29753..c64c9354c287f 100644 +--- a/MAINTAINERS ++++ b/MAINTAINERS +@@ -7310,7 +7310,6 @@ L: linux-hardening@vger.kernel.org + S: Maintained + F: Documentation/kbuild/gcc-plugins.rst + F: scripts/Makefile.gcc-plugins +-F: scripts/gcc-plugin.sh + F: scripts/gcc-plugins/ + + GCOV BASED KERNEL PROFILING +diff --git a/Makefile b/Makefile +index cce1e5dac06fb..8de80228df3f6 100644 +--- a/Makefile ++++ b/Makefile +@@ -1,7 +1,7 @@ + # SPDX-License-Identifier: GPL-2.0 + VERSION = 5 + PATCHLEVEL = 10 +-SUBLEVEL = 84 ++SUBLEVEL = 85 + EXTRAVERSION = + NAME = Dare mighty things + +diff --git a/arch/csky/kernel/traps.c b/arch/csky/kernel/traps.c +index 959a917c989d8..22721468a04b2 100644 +--- a/arch/csky/kernel/traps.c ++++ b/arch/csky/kernel/traps.c +@@ -211,7 +211,7 @@ asmlinkage void do_trap_illinsn(struct pt_regs *regs) + + asmlinkage void do_trap_fpe(struct pt_regs *regs) + { +-#ifdef CONFIG_CPU_HAS_FP ++#ifdef CONFIG_CPU_HAS_FPU + return fpu_fpe(regs); + #else + do_trap_error(regs, SIGILL, ILL_ILLOPC, regs->pc, +@@ -221,7 +221,7 @@ asmlinkage void do_trap_fpe(struct pt_regs *regs) + + asmlinkage void do_trap_priv(struct pt_regs *regs) + { +-#ifdef CONFIG_CPU_HAS_FP ++#ifdef CONFIG_CPU_HAS_FPU + if (user_mode(regs) && fpu_libc_helper(regs)) + return; + #endif +diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig +index a853ed7240eef..fb873a7bb65c8 100644 +--- a/arch/x86/Kconfig ++++ b/arch/x86/Kconfig +@@ -1939,6 +1939,7 @@ config EFI + depends on ACPI + select UCS2_STRING + select EFI_RUNTIME_WRAPPERS ++ select ARCH_USE_MEMREMAP_PROT + help + This enables the kernel to use EFI runtime services that are + available (such as the EFI variable services). +diff --git a/arch/x86/include/asm/kvm_host.h b/arch/x86/include/asm/kvm_host.h +index b1cd8334db11a..e8fb4b0394af2 100644 +--- a/arch/x86/include/asm/kvm_host.h ++++ b/arch/x86/include/asm/kvm_host.h +@@ -85,7 +85,7 @@ + KVM_ARCH_REQ_FLAGS(25, KVM_REQUEST_WAIT | KVM_REQUEST_NO_WAKEUP) + #define KVM_REQ_TLB_FLUSH_CURRENT KVM_ARCH_REQ(26) + #define KVM_REQ_TLB_FLUSH_GUEST \ +- KVM_ARCH_REQ_FLAGS(27, KVM_REQUEST_NO_WAKEUP) ++ KVM_ARCH_REQ_FLAGS(27, KVM_REQUEST_WAIT | KVM_REQUEST_NO_WAKEUP) + #define KVM_REQ_APF_READY KVM_ARCH_REQ(28) + #define KVM_REQ_MSR_FILTER_CHANGED KVM_ARCH_REQ(29) + +diff --git a/arch/x86/platform/efi/quirks.c b/arch/x86/platform/efi/quirks.c +index 5a40fe411ebda..c1eec019dcee6 100644 +--- a/arch/x86/platform/efi/quirks.c ++++ b/arch/x86/platform/efi/quirks.c +@@ -277,7 +277,8 @@ void __init efi_arch_mem_reserve(phys_addr_t addr, u64 size) + return; + } + +- new = early_memremap(data.phys_map, data.size); ++ new = early_memremap_prot(data.phys_map, data.size, ++ pgprot_val(pgprot_encrypted(FIXMAP_PAGE_NORMAL))); + if (!new) { + pr_err("Failed to map new boot services memmap\n"); + return; +diff --git a/block/ioprio.c b/block/ioprio.c +index 84da6c71b2ccb..c8878647de400 100644 +--- a/block/ioprio.c ++++ b/block/ioprio.c +@@ -214,6 +214,7 @@ SYSCALL_DEFINE2(ioprio_get, int, which, int, who) + pgrp = task_pgrp(current); + else + pgrp = find_vpid(who); ++ read_lock(&tasklist_lock); + do_each_pid_thread(pgrp, PIDTYPE_PGID, p) { + tmpio = get_task_ioprio(p); + if (tmpio < 0) +@@ -223,6 +224,8 @@ SYSCALL_DEFINE2(ioprio_get, int, which, int, who) + else + ret = ioprio_best(ret, tmpio); + } while_each_pid_thread(pgrp, PIDTYPE_PGID, p); ++ read_unlock(&tasklist_lock); ++ + break; + case IOPRIO_WHO_USER: + uid = make_kuid(current_user_ns(), who); +diff --git a/drivers/android/binder.c b/drivers/android/binder.c +index a1255971e50ce..80e2bbb36422e 100644 +--- a/drivers/android/binder.c ++++ b/drivers/android/binder.c +@@ -4784,23 +4784,20 @@ static int binder_thread_release(struct binder_proc *proc, + __release(&t->lock); + + /* +- * If this thread used poll, make sure we remove the waitqueue +- * from any epoll data structures holding it with POLLFREE. +- * waitqueue_active() is safe to use here because we're holding +- * the inner lock. ++ * If this thread used poll, make sure we remove the waitqueue from any ++ * poll data structures holding it. + */ +- if ((thread->looper & BINDER_LOOPER_STATE_POLL) && +- waitqueue_active(&thread->wait)) { +- wake_up_poll(&thread->wait, EPOLLHUP | POLLFREE); +- } ++ if (thread->looper & BINDER_LOOPER_STATE_POLL) ++ wake_up_pollfree(&thread->wait); + + binder_inner_proc_unlock(thread->proc); + + /* +- * This is needed to avoid races between wake_up_poll() above and +- * and ep_remove_waitqueue() called for other reasons (eg the epoll file +- * descriptor being closed); ep_remove_waitqueue() holds an RCU read +- * lock, so we can be sure it's done after calling synchronize_rcu(). ++ * This is needed to avoid races between wake_up_pollfree() above and ++ * someone else removing the last entry from the queue for other reasons ++ * (e.g. ep_remove_wait_queue() being called due to an epoll file ++ * descriptor being closed). Such other users hold an RCU read lock, so ++ * we can be sure they're done after we call synchronize_rcu(). + */ + if (thread->looper & BINDER_LOOPER_STATE_POLL) + synchronize_rcu(); +diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c +index 8acf99b88b21e..1f54f82d22d61 100644 +--- a/drivers/ata/libata-core.c ++++ b/drivers/ata/libata-core.c +@@ -3831,6 +3831,8 @@ static const struct ata_blacklist_entry ata_device_blacklist [] = { + { "VRFDFC22048UCHC-TE*", NULL, ATA_HORKAGE_NODMA }, + /* Odd clown on sil3726/4726 PMPs */ + { "Config Disk", NULL, ATA_HORKAGE_DISABLE }, ++ /* Similar story with ASMedia 1092 */ ++ { "ASMT109x- Config", NULL, ATA_HORKAGE_DISABLE }, + + /* Weird ATAPI devices */ + { "TORiSAN DVD-ROM DRD-N216", NULL, ATA_HORKAGE_MAX_SEC_128 }, +diff --git a/drivers/clk/imx/clk-imx8qxp-lpcg.c b/drivers/clk/imx/clk-imx8qxp-lpcg.c +index e947a70054acd..522c03a12b693 100644 +--- a/drivers/clk/imx/clk-imx8qxp-lpcg.c ++++ b/drivers/clk/imx/clk-imx8qxp-lpcg.c +@@ -231,7 +231,7 @@ static struct platform_driver imx8qxp_lpcg_clk_driver = { + .probe = imx8qxp_lpcg_clk_probe, + }; + +-builtin_platform_driver(imx8qxp_lpcg_clk_driver); ++module_platform_driver(imx8qxp_lpcg_clk_driver); + + MODULE_AUTHOR("Aisheng Dong <aisheng.dong@nxp.com>"); + MODULE_DESCRIPTION("NXP i.MX8QXP LPCG clock driver"); +diff --git a/drivers/clk/imx/clk-imx8qxp.c b/drivers/clk/imx/clk-imx8qxp.c +index d650ca33cdc80..8c14e0bbe1a24 100644 +--- a/drivers/clk/imx/clk-imx8qxp.c ++++ b/drivers/clk/imx/clk-imx8qxp.c +@@ -151,7 +151,7 @@ static struct platform_driver imx8qxp_clk_driver = { + }, + .probe = imx8qxp_clk_probe, + }; +-builtin_platform_driver(imx8qxp_clk_driver); ++module_platform_driver(imx8qxp_clk_driver); + + MODULE_AUTHOR("Aisheng Dong <aisheng.dong@nxp.com>"); + MODULE_DESCRIPTION("NXP i.MX8QXP clock driver"); +diff --git a/drivers/clk/qcom/clk-regmap-mux.c b/drivers/clk/qcom/clk-regmap-mux.c +index b2d00b4519634..45d9cca28064f 100644 +--- a/drivers/clk/qcom/clk-regmap-mux.c ++++ b/drivers/clk/qcom/clk-regmap-mux.c +@@ -28,7 +28,7 @@ static u8 mux_get_parent(struct clk_hw *hw) + val &= mask; + + if (mux->parent_map) +- return qcom_find_src_index(hw, mux->parent_map, val); ++ return qcom_find_cfg_index(hw, mux->parent_map, val); + + return val; + } +diff --git a/drivers/clk/qcom/common.c b/drivers/clk/qcom/common.c +index 60d2a78d13950..2af04fc4abfa9 100644 +--- a/drivers/clk/qcom/common.c ++++ b/drivers/clk/qcom/common.c +@@ -69,6 +69,18 @@ int qcom_find_src_index(struct clk_hw *hw, const struct parent_map *map, u8 src) + } + EXPORT_SYMBOL_GPL(qcom_find_src_index); + ++int qcom_find_cfg_index(struct clk_hw *hw, const struct parent_map *map, u8 cfg) ++{ ++ int i, num_parents = clk_hw_get_num_parents(hw); ++ ++ for (i = 0; i < num_parents; i++) ++ if (cfg == map[i].cfg) ++ return i; ++ ++ return -ENOENT; ++} ++EXPORT_SYMBOL_GPL(qcom_find_cfg_index); ++ + struct regmap * + qcom_cc_map(struct platform_device *pdev, const struct qcom_cc_desc *desc) + { +diff --git a/drivers/clk/qcom/common.h b/drivers/clk/qcom/common.h +index bb39a7e106d8a..9c8f7b798d9fc 100644 +--- a/drivers/clk/qcom/common.h ++++ b/drivers/clk/qcom/common.h +@@ -49,6 +49,8 @@ extern void + qcom_pll_set_fsm_mode(struct regmap *m, u32 reg, u8 bias_count, u8 lock_count); + extern int qcom_find_src_index(struct clk_hw *hw, const struct parent_map *map, + u8 src); ++extern int qcom_find_cfg_index(struct clk_hw *hw, const struct parent_map *map, ++ u8 cfg); + + extern int qcom_cc_register_board_clk(struct device *dev, const char *path, + const char *name, unsigned long rate); +diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.c +index 0544460653b95..fb6230c62daad 100644 +--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.c ++++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.c +@@ -47,12 +47,8 @@ int amdgpu_amdkfd_init(void) + amdgpu_amdkfd_total_mem_size = si.totalram - si.totalhigh; + amdgpu_amdkfd_total_mem_size *= si.mem_unit; + +-#ifdef CONFIG_HSA_AMD + ret = kgd2kfd_init(); + amdgpu_amdkfd_gpuvm_init_mem_limits(); +-#else +- ret = -ENOENT; +-#endif + kfd_initialized = !ret; + + return ret; +@@ -194,6 +190,16 @@ void amdgpu_amdkfd_suspend(struct amdgpu_device *adev, bool run_pm) + kgd2kfd_suspend(adev->kfd.dev, run_pm); + } + ++int amdgpu_amdkfd_resume_iommu(struct amdgpu_device *adev) ++{ ++ int r = 0; ++ ++ if (adev->kfd.dev) ++ r = kgd2kfd_resume_iommu(adev->kfd.dev); ++ ++ return r; ++} ++ + int amdgpu_amdkfd_resume(struct amdgpu_device *adev, bool run_pm) + { + int r = 0; +@@ -695,86 +701,3 @@ bool amdgpu_amdkfd_have_atomics_support(struct kgd_dev *kgd) + + return adev->have_atomics_support; + } +- +-#ifndef CONFIG_HSA_AMD +-bool amdkfd_fence_check_mm(struct dma_fence *f, struct mm_struct *mm) +-{ +- return false; +-} +- +-void amdgpu_amdkfd_unreserve_memory_limit(struct amdgpu_bo *bo) +-{ +-} +- +-int amdgpu_amdkfd_remove_fence_on_pt_pd_bos(struct amdgpu_bo *bo) +-{ +- return 0; +-} +- +-void amdgpu_amdkfd_gpuvm_destroy_cb(struct amdgpu_device *adev, +- struct amdgpu_vm *vm) +-{ +-} +- +-struct amdgpu_amdkfd_fence *to_amdgpu_amdkfd_fence(struct dma_fence *f) +-{ +- return NULL; +-} +- +-int amdgpu_amdkfd_evict_userptr(struct kgd_mem *mem, struct mm_struct *mm) +-{ +- return 0; +-} +- +-struct kfd_dev *kgd2kfd_probe(struct kgd_dev *kgd, struct pci_dev *pdev, +- unsigned int asic_type, bool vf) +-{ +- return NULL; +-} +- +-bool kgd2kfd_device_init(struct kfd_dev *kfd, +- struct drm_device *ddev, +- const struct kgd2kfd_shared_resources *gpu_resources) +-{ +- return false; +-} +- +-void kgd2kfd_device_exit(struct kfd_dev *kfd) +-{ +-} +- +-void kgd2kfd_exit(void) +-{ +-} +- +-void kgd2kfd_suspend(struct kfd_dev *kfd, bool run_pm) +-{ +-} +- +-int kgd2kfd_resume(struct kfd_dev *kfd, bool run_pm) +-{ +- return 0; +-} +- +-int kgd2kfd_pre_reset(struct kfd_dev *kfd) +-{ +- return 0; +-} +- +-int kgd2kfd_post_reset(struct kfd_dev *kfd) +-{ +- return 0; +-} +- +-void kgd2kfd_interrupt(struct kfd_dev *kfd, const void *ih_ring_entry) +-{ +-} +- +-void kgd2kfd_set_sram_ecc_flag(struct kfd_dev *kfd) +-{ +-} +- +-void kgd2kfd_smi_event_throttle(struct kfd_dev *kfd, uint32_t throttle_bitmask) +-{ +-} +-#endif +diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.h +index ea391ca7f2f1c..32e385f287cb6 100644 +--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.h ++++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.h +@@ -94,11 +94,6 @@ enum kgd_engine_type { + KGD_ENGINE_MAX + }; + +-struct amdgpu_amdkfd_fence *amdgpu_amdkfd_fence_create(u64 context, +- struct mm_struct *mm); +-bool amdkfd_fence_check_mm(struct dma_fence *f, struct mm_struct *mm); +-struct amdgpu_amdkfd_fence *to_amdgpu_amdkfd_fence(struct dma_fence *f); +-int amdgpu_amdkfd_remove_fence_on_pt_pd_bos(struct amdgpu_bo *bo); + + struct amdkfd_process_info { + /* List head of all VMs that belong to a KFD process */ +@@ -126,14 +121,13 @@ int amdgpu_amdkfd_init(void); + void amdgpu_amdkfd_fini(void); + + void amdgpu_amdkfd_suspend(struct amdgpu_device *adev, bool run_pm); ++int amdgpu_amdkfd_resume_iommu(struct amdgpu_device *adev); + int amdgpu_amdkfd_resume(struct amdgpu_device *adev, bool run_pm); + void amdgpu_amdkfd_interrupt(struct amdgpu_device *adev, + const void *ih_ring_entry); + void amdgpu_amdkfd_device_probe(struct amdgpu_device *adev); + void amdgpu_amdkfd_device_init(struct amdgpu_device *adev); + void amdgpu_amdkfd_device_fini(struct amdgpu_device *adev); +- +-int amdgpu_amdkfd_evict_userptr(struct kgd_mem *mem, struct mm_struct *mm); + int amdgpu_amdkfd_submit_ib(struct kgd_dev *kgd, enum kgd_engine_type engine, + uint32_t vmid, uint64_t gpu_addr, + uint32_t *ib_cmd, uint32_t ib_len); +@@ -153,6 +147,38 @@ void amdgpu_amdkfd_gpu_reset(struct kgd_dev *kgd); + int amdgpu_queue_mask_bit_to_set_resource_bit(struct amdgpu_device *adev, + int queue_bit); + ++struct amdgpu_amdkfd_fence *amdgpu_amdkfd_fence_create(u64 context, ++ struct mm_struct *mm); ++#if IS_ENABLED(CONFIG_HSA_AMD) ++bool amdkfd_fence_check_mm(struct dma_fence *f, struct mm_struct *mm); ++struct amdgpu_amdkfd_fence *to_amdgpu_amdkfd_fence(struct dma_fence *f); ++int amdgpu_amdkfd_remove_fence_on_pt_pd_bos(struct amdgpu_bo *bo); ++int amdgpu_amdkfd_evict_userptr(struct kgd_mem *mem, struct mm_struct *mm); ++#else ++static inline ++bool amdkfd_fence_check_mm(struct dma_fence *f, struct mm_struct *mm) ++{ ++ return false; ++} ++ ++static inline ++struct amdgpu_amdkfd_fence *to_amdgpu_amdkfd_fence(struct dma_fence *f) ++{ ++ return NULL; ++} ++ ++static inline ++int amdgpu_amdkfd_remove_fence_on_pt_pd_bos(struct amdgpu_bo *bo) ++{ ++ return 0; ++} ++ ++static inline ++int amdgpu_amdkfd_evict_userptr(struct kgd_mem *mem, struct mm_struct *mm) ++{ ++ return 0; ++} ++#endif + /* Shared API */ + int amdgpu_amdkfd_alloc_gtt_mem(struct kgd_dev *kgd, size_t size, + void **mem_obj, uint64_t *gpu_addr, +@@ -215,8 +241,6 @@ int amdgpu_amdkfd_gpuvm_acquire_process_vm(struct kgd_dev *kgd, + struct file *filp, u32 pasid, + void **vm, void **process_info, + struct dma_fence **ef); +-void amdgpu_amdkfd_gpuvm_destroy_cb(struct amdgpu_device *adev, +- struct amdgpu_vm *vm); + void amdgpu_amdkfd_gpuvm_destroy_process_vm(struct kgd_dev *kgd, void *vm); + void amdgpu_amdkfd_gpuvm_release_process_vm(struct kgd_dev *kgd, void *vm); + uint64_t amdgpu_amdkfd_gpuvm_get_process_page_dir(void *vm); +@@ -236,23 +260,43 @@ int amdgpu_amdkfd_gpuvm_map_gtt_bo_to_kernel(struct kgd_dev *kgd, + struct kgd_mem *mem, void **kptr, uint64_t *size); + int amdgpu_amdkfd_gpuvm_restore_process_bos(void *process_info, + struct dma_fence **ef); +- + int amdgpu_amdkfd_gpuvm_get_vm_fault_info(struct kgd_dev *kgd, + struct kfd_vm_fault_info *info); +- + int amdgpu_amdkfd_gpuvm_import_dmabuf(struct kgd_dev *kgd, + struct dma_buf *dmabuf, + uint64_t va, void *vm, + struct kgd_mem **mem, uint64_t *size, + uint64_t *mmap_offset); +- +-void amdgpu_amdkfd_gpuvm_init_mem_limits(void); +-void amdgpu_amdkfd_unreserve_memory_limit(struct amdgpu_bo *bo); +- + int amdgpu_amdkfd_get_tile_config(struct kgd_dev *kgd, + struct tile_config *config); ++#if IS_ENABLED(CONFIG_HSA_AMD) ++void amdgpu_amdkfd_gpuvm_init_mem_limits(void); ++void amdgpu_amdkfd_gpuvm_destroy_cb(struct amdgpu_device *adev, ++ struct amdgpu_vm *vm); ++void amdgpu_amdkfd_unreserve_memory_limit(struct amdgpu_bo *bo); ++#else ++static inline ++void amdgpu_amdkfd_gpuvm_init_mem_limits(void) ++{ ++} + ++static inline ++void amdgpu_amdkfd_gpuvm_destroy_cb(struct amdgpu_device *adev, ++ struct amdgpu_vm *vm) ++{ ++} ++ ++static inline ++void amdgpu_amdkfd_unreserve_memory_limit(struct amdgpu_bo *bo) ++{ ++} ++#endif + /* KGD2KFD callbacks */ ++int kgd2kfd_quiesce_mm(struct mm_struct *mm); ++int kgd2kfd_resume_mm(struct mm_struct *mm); ++int kgd2kfd_schedule_evict_and_restore_process(struct mm_struct *mm, ++ struct dma_fence *fence); ++#if IS_ENABLED(CONFIG_HSA_AMD) + int kgd2kfd_init(void); + void kgd2kfd_exit(void); + struct kfd_dev *kgd2kfd_probe(struct kgd_dev *kgd, struct pci_dev *pdev, +@@ -262,15 +306,78 @@ bool kgd2kfd_device_init(struct kfd_dev *kfd, + const struct kgd2kfd_shared_resources *gpu_resources); + void kgd2kfd_device_exit(struct kfd_dev *kfd); + void kgd2kfd_suspend(struct kfd_dev *kfd, bool run_pm); ++int kgd2kfd_resume_iommu(struct kfd_dev *kfd); + int kgd2kfd_resume(struct kfd_dev *kfd, bool run_pm); + int kgd2kfd_pre_reset(struct kfd_dev *kfd); + int kgd2kfd_post_reset(struct kfd_dev *kfd); + void kgd2kfd_interrupt(struct kfd_dev *kfd, const void *ih_ring_entry); +-int kgd2kfd_quiesce_mm(struct mm_struct *mm); +-int kgd2kfd_resume_mm(struct mm_struct *mm); +-int kgd2kfd_schedule_evict_and_restore_process(struct mm_struct *mm, +- struct dma_fence *fence); + void kgd2kfd_set_sram_ecc_flag(struct kfd_dev *kfd); + void kgd2kfd_smi_event_throttle(struct kfd_dev *kfd, uint32_t throttle_bitmask); ++#else ++static inline int kgd2kfd_init(void) ++{ ++ return -ENOENT; ++} + ++static inline void kgd2kfd_exit(void) ++{ ++} ++ ++static inline ++struct kfd_dev *kgd2kfd_probe(struct kgd_dev *kgd, struct pci_dev *pdev, ++ unsigned int asic_type, bool vf) ++{ ++ return NULL; ++} ++ ++static inline ++bool kgd2kfd_device_init(struct kfd_dev *kfd, struct drm_device *ddev, ++ const struct kgd2kfd_shared_resources *gpu_resources) ++{ ++ return false; ++} ++ ++static inline void kgd2kfd_device_exit(struct kfd_dev *kfd) ++{ ++} ++ ++static inline void kgd2kfd_suspend(struct kfd_dev *kfd, bool run_pm) ++{ ++} ++ ++static int __maybe_unused kgd2kfd_resume_iommu(struct kfd_dev *kfd) ++{ ++ return 0; ++} ++ ++static inline int kgd2kfd_resume(struct kfd_dev *kfd, bool run_pm) ++{ ++ return 0; ++} ++ ++static inline int kgd2kfd_pre_reset(struct kfd_dev *kfd) ++{ ++ return 0; ++} ++ ++static inline int kgd2kfd_post_reset(struct kfd_dev *kfd) ++{ ++ return 0; ++} ++ ++static inline ++void kgd2kfd_interrupt(struct kfd_dev *kfd, const void *ih_ring_entry) ++{ ++} ++ ++static inline ++void kgd2kfd_set_sram_ecc_flag(struct kfd_dev *kfd) ++{ ++} ++ ++static inline ++void kgd2kfd_smi_event_throttle(struct kfd_dev *kfd, uint32_t throttle_bitmask) ++{ ++} ++#endif + #endif /* AMDGPU_AMDKFD_H_INCLUDED */ +diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c +index 97723f2b5ece7..f262c4e7a48a2 100644 +--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c ++++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c +@@ -2913,6 +2913,10 @@ static int amdgpu_device_ip_resume(struct amdgpu_device *adev) + { + int r; + ++ r = amdgpu_amdkfd_resume_iommu(adev); ++ if (r) ++ return r; ++ + r = amdgpu_device_ip_resume_phase1(adev); + if (r) + return r; +@@ -4296,6 +4300,10 @@ static int amdgpu_do_asic_reset(struct amdgpu_hive_info *hive, + + if (!r) { + dev_info(tmp_adev->dev, "GPU reset succeeded, trying to resume\n"); ++ r = amdgpu_amdkfd_resume_iommu(tmp_adev); ++ if (r) ++ goto out; ++ + r = amdgpu_device_ip_resume_phase1(tmp_adev); + if (r) + goto out; +diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_device.c b/drivers/gpu/drm/amd/amdkfd/kfd_device.c +index 5751bddc9cadd..84313135c2eae 100644 +--- a/drivers/gpu/drm/amd/amdkfd/kfd_device.c ++++ b/drivers/gpu/drm/amd/amdkfd/kfd_device.c +@@ -751,6 +751,9 @@ bool kgd2kfd_device_init(struct kfd_dev *kfd, + + kfd_cwsr_init(kfd); + ++ if(kgd2kfd_resume_iommu(kfd)) ++ goto device_iommu_error; ++ + if (kfd_resume(kfd)) + goto kfd_resume_error; + +@@ -896,17 +899,21 @@ int kgd2kfd_resume(struct kfd_dev *kfd, bool run_pm) + return ret; + } + +-static int kfd_resume(struct kfd_dev *kfd) ++int kgd2kfd_resume_iommu(struct kfd_dev *kfd) + { + int err = 0; + + err = kfd_iommu_resume(kfd); +- if (err) { ++ if (err) + dev_err(kfd_device, + "Failed to resume IOMMU for device %x:%x\n", + kfd->pdev->vendor, kfd->pdev->device); +- return err; +- } ++ return err; ++} ++ ++static int kfd_resume(struct kfd_dev *kfd) ++{ ++ int err = 0; + + err = kfd->dqm->ops.start(kfd->dqm); + if (err) { +diff --git a/drivers/gpu/drm/drm_syncobj.c b/drivers/gpu/drm/drm_syncobj.c +index 3491460498491..993898a2c7791 100644 +--- a/drivers/gpu/drm/drm_syncobj.c ++++ b/drivers/gpu/drm/drm_syncobj.c +@@ -391,8 +391,17 @@ int drm_syncobj_find_fence(struct drm_file *file_private, + + if (*fence) { + ret = dma_fence_chain_find_seqno(fence, point); +- if (!ret) ++ if (!ret) { ++ /* If the requested seqno is already signaled ++ * drm_syncobj_find_fence may return a NULL ++ * fence. To make sure the recipient gets ++ * signalled, use a new fence instead. ++ */ ++ if (!*fence) ++ *fence = dma_fence_get_stub(); ++ + goto out; ++ } + dma_fence_put(*fence); + } else { + ret = -EINVAL; +diff --git a/drivers/hid/Kconfig b/drivers/hid/Kconfig +index 54bc563a8dff1..f8ad3b2be0bfb 100644 +--- a/drivers/hid/Kconfig ++++ b/drivers/hid/Kconfig +@@ -207,14 +207,14 @@ config HID_CHERRY + + config HID_CHICONY + tristate "Chicony devices" +- depends on HID ++ depends on USB_HID + default !EXPERT + help + Support for Chicony Tactical pad and special keys on Chicony keyboards. + + config HID_CORSAIR + tristate "Corsair devices" +- depends on HID && USB && LEDS_CLASS ++ depends on USB_HID && LEDS_CLASS + help + Support for Corsair devices that are not fully compliant with the + HID standard. +@@ -245,7 +245,7 @@ config HID_MACALLY + + config HID_PRODIKEYS + tristate "Prodikeys PC-MIDI Keyboard support" +- depends on HID && SND ++ depends on USB_HID && SND + select SND_RAWMIDI + help + Support for Prodikeys PC-MIDI Keyboard device support. +@@ -541,7 +541,7 @@ config HID_LENOVO + + config HID_LOGITECH + tristate "Logitech devices" +- depends on HID ++ depends on USB_HID + depends on LEDS_CLASS + default !EXPERT + help +@@ -889,7 +889,7 @@ config HID_SAITEK + + config HID_SAMSUNG + tristate "Samsung InfraRed remote control or keyboards" +- depends on HID ++ depends on USB_HID + help + Support for Samsung InfraRed remote control or keyboards. + +diff --git a/drivers/hid/hid-asus.c b/drivers/hid/hid-asus.c +index c183caf89d492..f85c6e3309a09 100644 +--- a/drivers/hid/hid-asus.c ++++ b/drivers/hid/hid-asus.c +@@ -918,8 +918,7 @@ static int asus_probe(struct hid_device *hdev, const struct hid_device_id *id) + if (drvdata->quirks & QUIRK_IS_MULTITOUCH) + drvdata->tp = &asus_i2c_tp; + +- if ((drvdata->quirks & QUIRK_T100_KEYBOARD) && +- hid_is_using_ll_driver(hdev, &usb_hid_driver)) { ++ if ((drvdata->quirks & QUIRK_T100_KEYBOARD) && hid_is_usb(hdev)) { + struct usb_interface *intf = to_usb_interface(hdev->dev.parent); + + if (intf->altsetting->desc.bInterfaceNumber == T100_TPAD_INTF) { +@@ -947,8 +946,7 @@ static int asus_probe(struct hid_device *hdev, const struct hid_device_id *id) + drvdata->tp = &asus_t100chi_tp; + } + +- if ((drvdata->quirks & QUIRK_MEDION_E1239T) && +- hid_is_using_ll_driver(hdev, &usb_hid_driver)) { ++ if ((drvdata->quirks & QUIRK_MEDION_E1239T) && hid_is_usb(hdev)) { + struct usb_host_interface *alt = + to_usb_interface(hdev->dev.parent)->altsetting; + +diff --git a/drivers/hid/hid-bigbenff.c b/drivers/hid/hid-bigbenff.c +index db6da21ade063..74ad8bf98bfd5 100644 +--- a/drivers/hid/hid-bigbenff.c ++++ b/drivers/hid/hid-bigbenff.c +@@ -191,7 +191,7 @@ static void bigben_worker(struct work_struct *work) + struct bigben_device, worker); + struct hid_field *report_field = bigben->report->field[0]; + +- if (bigben->removed) ++ if (bigben->removed || !report_field) + return; + + if (bigben->work_led) { +diff --git a/drivers/hid/hid-chicony.c b/drivers/hid/hid-chicony.c +index 3f0ed6a952234..e19e2b5973396 100644 +--- a/drivers/hid/hid-chicony.c ++++ b/drivers/hid/hid-chicony.c +@@ -58,8 +58,12 @@ static int ch_input_mapping(struct hid_device *hdev, struct hid_input *hi, + static __u8 *ch_switch12_report_fixup(struct hid_device *hdev, __u8 *rdesc, + unsigned int *rsize) + { +- struct usb_interface *intf = to_usb_interface(hdev->dev.parent); +- ++ struct usb_interface *intf; ++ ++ if (!hid_is_usb(hdev)) ++ return rdesc; ++ ++ intf = to_usb_interface(hdev->dev.parent); + if (intf->cur_altsetting->desc.bInterfaceNumber == 1) { + /* Change usage maximum and logical maximum from 0x7fff to + * 0x2fff, so they don't exceed HID_MAX_USAGES */ +diff --git a/drivers/hid/hid-corsair.c b/drivers/hid/hid-corsair.c +index 902a60e249ed2..8c895c820b672 100644 +--- a/drivers/hid/hid-corsair.c ++++ b/drivers/hid/hid-corsair.c +@@ -553,7 +553,12 @@ static int corsair_probe(struct hid_device *dev, const struct hid_device_id *id) + int ret; + unsigned long quirks = id->driver_data; + struct corsair_drvdata *drvdata; +- struct usb_interface *usbif = to_usb_interface(dev->dev.parent); ++ struct usb_interface *usbif; ++ ++ if (!hid_is_usb(dev)) ++ return -EINVAL; ++ ++ usbif = to_usb_interface(dev->dev.parent); + + drvdata = devm_kzalloc(&dev->dev, sizeof(struct corsair_drvdata), + GFP_KERNEL); +diff --git a/drivers/hid/hid-elan.c b/drivers/hid/hid-elan.c +index dae193749d443..0e8f424025fea 100644 +--- a/drivers/hid/hid-elan.c ++++ b/drivers/hid/hid-elan.c +@@ -50,7 +50,7 @@ struct elan_drvdata { + + static int is_not_elan_touchpad(struct hid_device *hdev) + { +- if (hdev->bus == BUS_USB) { ++ if (hid_is_usb(hdev)) { + struct usb_interface *intf = to_usb_interface(hdev->dev.parent); + + return (intf->altsetting->desc.bInterfaceNumber != +diff --git a/drivers/hid/hid-elo.c b/drivers/hid/hid-elo.c +index 0d22713a38742..2876cb6a7dcab 100644 +--- a/drivers/hid/hid-elo.c ++++ b/drivers/hid/hid-elo.c +@@ -229,6 +229,9 @@ static int elo_probe(struct hid_device *hdev, const struct hid_device_id *id) + struct elo_priv *priv; + int ret; + ++ if (!hid_is_usb(hdev)) ++ return -EINVAL; ++ + priv = kzalloc(sizeof(*priv), GFP_KERNEL); + if (!priv) + return -ENOMEM; +diff --git a/drivers/hid/hid-google-hammer.c b/drivers/hid/hid-google-hammer.c +index 2a176f77b32e9..0476301983964 100644 +--- a/drivers/hid/hid-google-hammer.c ++++ b/drivers/hid/hid-google-hammer.c +@@ -528,6 +528,8 @@ static void hammer_remove(struct hid_device *hdev) + static const struct hid_device_id hammer_devices[] = { + { HID_DEVICE(BUS_USB, HID_GROUP_GENERIC, + USB_VENDOR_ID_GOOGLE, USB_DEVICE_ID_GOOGLE_DON) }, ++ { HID_DEVICE(BUS_USB, HID_GROUP_GENERIC, ++ USB_VENDOR_ID_GOOGLE, USB_DEVICE_ID_GOOGLE_EEL) }, + { HID_DEVICE(BUS_USB, HID_GROUP_GENERIC, + USB_VENDOR_ID_GOOGLE, USB_DEVICE_ID_GOOGLE_HAMMER) }, + { HID_DEVICE(BUS_USB, HID_GROUP_GENERIC, +diff --git a/drivers/hid/hid-holtek-kbd.c b/drivers/hid/hid-holtek-kbd.c +index 0a38e8e9bc783..403506b9697e7 100644 +--- a/drivers/hid/hid-holtek-kbd.c ++++ b/drivers/hid/hid-holtek-kbd.c +@@ -140,12 +140,17 @@ static int holtek_kbd_input_event(struct input_dev *dev, unsigned int type, + static int holtek_kbd_probe(struct hid_device *hdev, + const struct hid_device_id *id) + { +- struct usb_interface *intf = to_usb_interface(hdev->dev.parent); +- int ret = hid_parse(hdev); ++ struct usb_interface *intf; ++ int ret; ++ ++ if (!hid_is_usb(hdev)) ++ return -EINVAL; + ++ ret = hid_parse(hdev); + if (!ret) + ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT); + ++ intf = to_usb_interface(hdev->dev.parent); + if (!ret && intf->cur_altsetting->desc.bInterfaceNumber == 1) { + struct hid_input *hidinput; + list_for_each_entry(hidinput, &hdev->inputs, list) { +diff --git a/drivers/hid/hid-holtek-mouse.c b/drivers/hid/hid-holtek-mouse.c +index 195b735b001d0..b7172c48ef9f0 100644 +--- a/drivers/hid/hid-holtek-mouse.c ++++ b/drivers/hid/hid-holtek-mouse.c +@@ -62,6 +62,14 @@ static __u8 *holtek_mouse_report_fixup(struct hid_device *hdev, __u8 *rdesc, + return rdesc; + } + ++static int holtek_mouse_probe(struct hid_device *hdev, ++ const struct hid_device_id *id) ++{ ++ if (!hid_is_usb(hdev)) ++ return -EINVAL; ++ return 0; ++} ++ + static const struct hid_device_id holtek_mouse_devices[] = { + { HID_USB_DEVICE(USB_VENDOR_ID_HOLTEK_ALT, + USB_DEVICE_ID_HOLTEK_ALT_MOUSE_A067) }, +@@ -83,6 +91,7 @@ static struct hid_driver holtek_mouse_driver = { + .name = "holtek_mouse", + .id_table = holtek_mouse_devices, + .report_fixup = holtek_mouse_report_fixup, ++ .probe = holtek_mouse_probe, + }; + + module_hid_driver(holtek_mouse_driver); +diff --git a/drivers/hid/hid-ids.h b/drivers/hid/hid-ids.h +index 136b58a91c04c..370ec4402ebe3 100644 +--- a/drivers/hid/hid-ids.h ++++ b/drivers/hid/hid-ids.h +@@ -488,6 +488,7 @@ + #define USB_DEVICE_ID_GOOGLE_MAGNEMITE 0x503d + #define USB_DEVICE_ID_GOOGLE_MOONBALL 0x5044 + #define USB_DEVICE_ID_GOOGLE_DON 0x5050 ++#define USB_DEVICE_ID_GOOGLE_EEL 0x5057 + + #define USB_VENDOR_ID_GOTOP 0x08f2 + #define USB_DEVICE_ID_SUPER_Q2 0x007f +@@ -865,6 +866,7 @@ + #define USB_DEVICE_ID_MS_TOUCH_COVER_2 0x07a7 + #define USB_DEVICE_ID_MS_TYPE_COVER_2 0x07a9 + #define USB_DEVICE_ID_MS_POWER_COVER 0x07da ++#define USB_DEVICE_ID_MS_SURFACE3_COVER 0x07de + #define USB_DEVICE_ID_MS_XBOX_ONE_S_CONTROLLER 0x02fd + #define USB_DEVICE_ID_MS_PIXART_MOUSE 0x00cb + #define USB_DEVICE_ID_8BITDO_SN30_PRO_PLUS 0x02e0 +diff --git a/drivers/hid/hid-lg.c b/drivers/hid/hid-lg.c +index 0dc7cdfc56f77..2c7e7c089bf99 100644 +--- a/drivers/hid/hid-lg.c ++++ b/drivers/hid/hid-lg.c +@@ -769,12 +769,18 @@ static int lg_raw_event(struct hid_device *hdev, struct hid_report *report, + + static int lg_probe(struct hid_device *hdev, const struct hid_device_id *id) + { +- struct usb_interface *iface = to_usb_interface(hdev->dev.parent); +- __u8 iface_num = iface->cur_altsetting->desc.bInterfaceNumber; ++ struct usb_interface *iface; ++ __u8 iface_num; + unsigned int connect_mask = HID_CONNECT_DEFAULT; + struct lg_drv_data *drv_data; + int ret; + ++ if (!hid_is_usb(hdev)) ++ return -EINVAL; ++ ++ iface = to_usb_interface(hdev->dev.parent); ++ iface_num = iface->cur_altsetting->desc.bInterfaceNumber; ++ + /* G29 only work with the 1st interface */ + if ((hdev->product == USB_DEVICE_ID_LOGITECH_G29_WHEEL) && + (iface_num != 0)) { +diff --git a/drivers/hid/hid-logitech-dj.c b/drivers/hid/hid-logitech-dj.c +index 271bd8d243395..a311b0a33eba7 100644 +--- a/drivers/hid/hid-logitech-dj.c ++++ b/drivers/hid/hid-logitech-dj.c +@@ -1693,7 +1693,7 @@ static int logi_dj_probe(struct hid_device *hdev, + case recvr_type_27mhz: no_dj_interfaces = 2; break; + case recvr_type_bluetooth: no_dj_interfaces = 2; break; + } +- if (hid_is_using_ll_driver(hdev, &usb_hid_driver)) { ++ if (hid_is_usb(hdev)) { + intf = to_usb_interface(hdev->dev.parent); + if (intf && intf->altsetting->desc.bInterfaceNumber >= + no_dj_interfaces) { +diff --git a/drivers/hid/hid-prodikeys.c b/drivers/hid/hid-prodikeys.c +index 2666af02d5c1a..e4e9471d0f1e9 100644 +--- a/drivers/hid/hid-prodikeys.c ++++ b/drivers/hid/hid-prodikeys.c +@@ -798,12 +798,18 @@ static int pk_raw_event(struct hid_device *hdev, struct hid_report *report, + static int pk_probe(struct hid_device *hdev, const struct hid_device_id *id) + { + int ret; +- struct usb_interface *intf = to_usb_interface(hdev->dev.parent); +- unsigned short ifnum = intf->cur_altsetting->desc.bInterfaceNumber; ++ struct usb_interface *intf; ++ unsigned short ifnum; + unsigned long quirks = id->driver_data; + struct pk_device *pk; + struct pcmidi_snd *pm = NULL; + ++ if (!hid_is_usb(hdev)) ++ return -EINVAL; ++ ++ intf = to_usb_interface(hdev->dev.parent); ++ ifnum = intf->cur_altsetting->desc.bInterfaceNumber; ++ + pk = kzalloc(sizeof(*pk), GFP_KERNEL); + if (pk == NULL) { + hid_err(hdev, "can't alloc descriptor\n"); +diff --git a/drivers/hid/hid-quirks.c b/drivers/hid/hid-quirks.c +index be53c723c729d..84a30202e3dbe 100644 +--- a/drivers/hid/hid-quirks.c ++++ b/drivers/hid/hid-quirks.c +@@ -124,6 +124,7 @@ static const struct hid_device_id hid_quirks[] = { + { HID_USB_DEVICE(USB_VENDOR_ID_MCS, USB_DEVICE_ID_MCS_GAMEPADBLOCK), HID_QUIRK_MULTI_INPUT }, + { HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_PIXART_MOUSE), HID_QUIRK_ALWAYS_POLL }, + { HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_POWER_COVER), HID_QUIRK_NO_INIT_REPORTS }, ++ { HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_SURFACE3_COVER), HID_QUIRK_NO_INIT_REPORTS }, + { HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_SURFACE_PRO_2), HID_QUIRK_NO_INIT_REPORTS }, + { HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_TOUCH_COVER_2), HID_QUIRK_NO_INIT_REPORTS }, + { HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_TYPE_COVER_2), HID_QUIRK_NO_INIT_REPORTS }, +diff --git a/drivers/hid/hid-roccat-arvo.c b/drivers/hid/hid-roccat-arvo.c +index ffcd444ae2ba6..4b18e1a4fc7ac 100644 +--- a/drivers/hid/hid-roccat-arvo.c ++++ b/drivers/hid/hid-roccat-arvo.c +@@ -344,6 +344,9 @@ static int arvo_probe(struct hid_device *hdev, + { + int retval; + ++ if (!hid_is_usb(hdev)) ++ return -EINVAL; ++ + retval = hid_parse(hdev); + if (retval) { + hid_err(hdev, "parse failed\n"); +diff --git a/drivers/hid/hid-roccat-isku.c b/drivers/hid/hid-roccat-isku.c +index ce5f22519956a..e95d59cd8d075 100644 +--- a/drivers/hid/hid-roccat-isku.c ++++ b/drivers/hid/hid-roccat-isku.c +@@ -324,6 +324,9 @@ static int isku_probe(struct hid_device *hdev, + { + int retval; + ++ if (!hid_is_usb(hdev)) ++ return -EINVAL; ++ + retval = hid_parse(hdev); + if (retval) { + hid_err(hdev, "parse failed\n"); +diff --git a/drivers/hid/hid-roccat-kone.c b/drivers/hid/hid-roccat-kone.c +index 1ca64481145ee..e8522eacf7973 100644 +--- a/drivers/hid/hid-roccat-kone.c ++++ b/drivers/hid/hid-roccat-kone.c +@@ -749,6 +749,9 @@ static int kone_probe(struct hid_device *hdev, const struct hid_device_id *id) + { + int retval; + ++ if (!hid_is_usb(hdev)) ++ return -EINVAL; ++ + retval = hid_parse(hdev); + if (retval) { + hid_err(hdev, "parse failed\n"); +diff --git a/drivers/hid/hid-roccat-koneplus.c b/drivers/hid/hid-roccat-koneplus.c +index 0316edf8c5bb4..1896c69ea512f 100644 +--- a/drivers/hid/hid-roccat-koneplus.c ++++ b/drivers/hid/hid-roccat-koneplus.c +@@ -431,6 +431,9 @@ static int koneplus_probe(struct hid_device *hdev, + { + int retval; + ++ if (!hid_is_usb(hdev)) ++ return -EINVAL; ++ + retval = hid_parse(hdev); + if (retval) { + hid_err(hdev, "parse failed\n"); +diff --git a/drivers/hid/hid-roccat-konepure.c b/drivers/hid/hid-roccat-konepure.c +index 5248b3c7cf785..cf8eeb33a1257 100644 +--- a/drivers/hid/hid-roccat-konepure.c ++++ b/drivers/hid/hid-roccat-konepure.c +@@ -133,6 +133,9 @@ static int konepure_probe(struct hid_device *hdev, + { + int retval; + ++ if (!hid_is_usb(hdev)) ++ return -EINVAL; ++ + retval = hid_parse(hdev); + if (retval) { + hid_err(hdev, "parse failed\n"); +diff --git a/drivers/hid/hid-roccat-kovaplus.c b/drivers/hid/hid-roccat-kovaplus.c +index 9600128815705..6fb9b9563769d 100644 +--- a/drivers/hid/hid-roccat-kovaplus.c ++++ b/drivers/hid/hid-roccat-kovaplus.c +@@ -501,6 +501,9 @@ static int kovaplus_probe(struct hid_device *hdev, + { + int retval; + ++ if (!hid_is_usb(hdev)) ++ return -EINVAL; ++ + retval = hid_parse(hdev); + if (retval) { + hid_err(hdev, "parse failed\n"); +diff --git a/drivers/hid/hid-roccat-lua.c b/drivers/hid/hid-roccat-lua.c +index 4a88a76d5c622..d5ddf0d68346b 100644 +--- a/drivers/hid/hid-roccat-lua.c ++++ b/drivers/hid/hid-roccat-lua.c +@@ -160,6 +160,9 @@ static int lua_probe(struct hid_device *hdev, + { + int retval; + ++ if (!hid_is_usb(hdev)) ++ return -EINVAL; ++ + retval = hid_parse(hdev); + if (retval) { + hid_err(hdev, "parse failed\n"); +diff --git a/drivers/hid/hid-roccat-pyra.c b/drivers/hid/hid-roccat-pyra.c +index 989927defe8db..4fcc8e7d276f2 100644 +--- a/drivers/hid/hid-roccat-pyra.c ++++ b/drivers/hid/hid-roccat-pyra.c +@@ -449,6 +449,9 @@ static int pyra_probe(struct hid_device *hdev, const struct hid_device_id *id) + { + int retval; + ++ if (!hid_is_usb(hdev)) ++ return -EINVAL; ++ + retval = hid_parse(hdev); + if (retval) { + hid_err(hdev, "parse failed\n"); +diff --git a/drivers/hid/hid-roccat-ryos.c b/drivers/hid/hid-roccat-ryos.c +index 3956a6c9c5217..5bf1971a2b14d 100644 +--- a/drivers/hid/hid-roccat-ryos.c ++++ b/drivers/hid/hid-roccat-ryos.c +@@ -141,6 +141,9 @@ static int ryos_probe(struct hid_device *hdev, + { + int retval; + ++ if (!hid_is_usb(hdev)) ++ return -EINVAL; ++ + retval = hid_parse(hdev); + if (retval) { + hid_err(hdev, "parse failed\n"); +diff --git a/drivers/hid/hid-roccat-savu.c b/drivers/hid/hid-roccat-savu.c +index 818701f7a0281..a784bb4ee6512 100644 +--- a/drivers/hid/hid-roccat-savu.c ++++ b/drivers/hid/hid-roccat-savu.c +@@ -113,6 +113,9 @@ static int savu_probe(struct hid_device *hdev, + { + int retval; + ++ if (!hid_is_usb(hdev)) ++ return -EINVAL; ++ + retval = hid_parse(hdev); + if (retval) { + hid_err(hdev, "parse failed\n"); +diff --git a/drivers/hid/hid-samsung.c b/drivers/hid/hid-samsung.c +index 2e1c31156eca0..cf5992e970940 100644 +--- a/drivers/hid/hid-samsung.c ++++ b/drivers/hid/hid-samsung.c +@@ -152,6 +152,9 @@ static int samsung_probe(struct hid_device *hdev, + int ret; + unsigned int cmask = HID_CONNECT_DEFAULT; + ++ if (!hid_is_usb(hdev)) ++ return -EINVAL; ++ + ret = hid_parse(hdev); + if (ret) { + hid_err(hdev, "parse failed\n"); +diff --git a/drivers/hid/hid-u2fzero.c b/drivers/hid/hid-u2fzero.c +index 67ae2b18e33ac..ac3fd870673d2 100644 +--- a/drivers/hid/hid-u2fzero.c ++++ b/drivers/hid/hid-u2fzero.c +@@ -290,7 +290,7 @@ static int u2fzero_probe(struct hid_device *hdev, + unsigned int minor; + int ret; + +- if (!hid_is_using_ll_driver(hdev, &usb_hid_driver)) ++ if (!hid_is_usb(hdev)) + return -EINVAL; + + dev = devm_kzalloc(&hdev->dev, sizeof(*dev), GFP_KERNEL); +diff --git a/drivers/hid/hid-uclogic-core.c b/drivers/hid/hid-uclogic-core.c +index 8e9c9e646cb7d..4edb241957040 100644 +--- a/drivers/hid/hid-uclogic-core.c ++++ b/drivers/hid/hid-uclogic-core.c +@@ -164,6 +164,9 @@ static int uclogic_probe(struct hid_device *hdev, + struct uclogic_drvdata *drvdata = NULL; + bool params_initialized = false; + ++ if (!hid_is_usb(hdev)) ++ return -EINVAL; ++ + /* + * libinput requires the pad interface to be on a different node + * than the pen, so use QUIRK_MULTI_INPUT for all tablets. +diff --git a/drivers/hid/hid-uclogic-params.c b/drivers/hid/hid-uclogic-params.c +index d26d8cd98efcf..dd05bed4ca53a 100644 +--- a/drivers/hid/hid-uclogic-params.c ++++ b/drivers/hid/hid-uclogic-params.c +@@ -841,8 +841,7 @@ int uclogic_params_init(struct uclogic_params *params, + struct uclogic_params p = {0, }; + + /* Check arguments */ +- if (params == NULL || hdev == NULL || +- !hid_is_using_ll_driver(hdev, &usb_hid_driver)) { ++ if (params == NULL || hdev == NULL || !hid_is_usb(hdev)) { + rc = -EINVAL; + goto cleanup; + } +diff --git a/drivers/hid/wacom_sys.c b/drivers/hid/wacom_sys.c +index 73dafa60080f1..329bb1a46f90e 100644 +--- a/drivers/hid/wacom_sys.c ++++ b/drivers/hid/wacom_sys.c +@@ -726,7 +726,7 @@ static void wacom_retrieve_hid_descriptor(struct hid_device *hdev, + * Skip the query for this type and modify defaults based on + * interface number. + */ +- if (features->type == WIRELESS) { ++ if (features->type == WIRELESS && intf) { + if (intf->cur_altsetting->desc.bInterfaceNumber == 0) + features->device_type = WACOM_DEVICETYPE_WL_MONITOR; + else +@@ -2217,7 +2217,7 @@ static void wacom_update_name(struct wacom *wacom, const char *suffix) + if ((features->type == HID_GENERIC) && !strcmp("Wacom HID", features->name)) { + char *product_name = wacom->hdev->name; + +- if (hid_is_using_ll_driver(wacom->hdev, &usb_hid_driver)) { ++ if (hid_is_usb(wacom->hdev)) { + struct usb_interface *intf = to_usb_interface(wacom->hdev->dev.parent); + struct usb_device *dev = interface_to_usbdev(intf); + product_name = dev->product; +@@ -2448,6 +2448,9 @@ static void wacom_wireless_work(struct work_struct *work) + + wacom_destroy_battery(wacom); + ++ if (!usbdev) ++ return; ++ + /* Stylus interface */ + hdev1 = usb_get_intfdata(usbdev->config->interface[1]); + wacom1 = hid_get_drvdata(hdev1); +@@ -2727,8 +2730,6 @@ static void wacom_mode_change_work(struct work_struct *work) + static int wacom_probe(struct hid_device *hdev, + const struct hid_device_id *id) + { +- struct usb_interface *intf = to_usb_interface(hdev->dev.parent); +- struct usb_device *dev = interface_to_usbdev(intf); + struct wacom *wacom; + struct wacom_wac *wacom_wac; + struct wacom_features *features; +@@ -2763,8 +2764,14 @@ static int wacom_probe(struct hid_device *hdev, + wacom_wac->hid_data.inputmode = -1; + wacom_wac->mode_report = -1; + +- wacom->usbdev = dev; +- wacom->intf = intf; ++ if (hid_is_usb(hdev)) { ++ struct usb_interface *intf = to_usb_interface(hdev->dev.parent); ++ struct usb_device *dev = interface_to_usbdev(intf); ++ ++ wacom->usbdev = dev; ++ wacom->intf = intf; ++ } ++ + mutex_init(&wacom->lock); + INIT_DELAYED_WORK(&wacom->init_work, wacom_init_work); + INIT_WORK(&wacom->wireless_work, wacom_wireless_work); +diff --git a/drivers/iio/accel/kxcjk-1013.c b/drivers/iio/accel/kxcjk-1013.c +index c99e90469a245..2eaf85b6e39f4 100644 +--- a/drivers/iio/accel/kxcjk-1013.c ++++ b/drivers/iio/accel/kxcjk-1013.c +@@ -1435,8 +1435,7 @@ static int kxcjk1013_probe(struct i2c_client *client, + return 0; + + err_buffer_cleanup: +- if (data->dready_trig) +- iio_triggered_buffer_cleanup(indio_dev); ++ iio_triggered_buffer_cleanup(indio_dev); + err_trigger_unregister: + if (data->dready_trig) + iio_trigger_unregister(data->dready_trig); +@@ -1459,8 +1458,8 @@ static int kxcjk1013_remove(struct i2c_client *client) + pm_runtime_set_suspended(&client->dev); + pm_runtime_put_noidle(&client->dev); + ++ iio_triggered_buffer_cleanup(indio_dev); + if (data->dready_trig) { +- iio_triggered_buffer_cleanup(indio_dev); + iio_trigger_unregister(data->dready_trig); + iio_trigger_unregister(data->motion_trig); + } +diff --git a/drivers/iio/accel/kxsd9.c b/drivers/iio/accel/kxsd9.c +index 0e18b92e20992..a51568ba8b7d2 100644 +--- a/drivers/iio/accel/kxsd9.c ++++ b/drivers/iio/accel/kxsd9.c +@@ -224,14 +224,14 @@ static irqreturn_t kxsd9_trigger_handler(int irq, void *p) + hw_values.chan, + sizeof(hw_values.chan)); + if (ret) { +- dev_err(st->dev, +- "error reading data\n"); +- return ret; ++ dev_err(st->dev, "error reading data: %d\n", ret); ++ goto out; + } + + iio_push_to_buffers_with_timestamp(indio_dev, + &hw_values, + iio_get_time_ns(indio_dev)); ++out: + iio_trigger_notify_done(indio_dev->trig); + + return IRQ_HANDLED; +diff --git a/drivers/iio/accel/mma8452.c b/drivers/iio/accel/mma8452.c +index bf1d2c8afdbd7..a7208704d31c9 100644 +--- a/drivers/iio/accel/mma8452.c ++++ b/drivers/iio/accel/mma8452.c +@@ -1473,7 +1473,7 @@ static int mma8452_trigger_setup(struct iio_dev *indio_dev) + if (ret) + return ret; + +- indio_dev->trig = trig; ++ indio_dev->trig = iio_trigger_get(trig); + + return 0; + } +diff --git a/drivers/iio/adc/ad7768-1.c b/drivers/iio/adc/ad7768-1.c +index c7e15c45140ad..4afa50e5c058a 100644 +--- a/drivers/iio/adc/ad7768-1.c ++++ b/drivers/iio/adc/ad7768-1.c +@@ -470,8 +470,8 @@ static irqreturn_t ad7768_trigger_handler(int irq, void *p) + iio_push_to_buffers_with_timestamp(indio_dev, &st->data.scan, + iio_get_time_ns(indio_dev)); + +- iio_trigger_notify_done(indio_dev->trig); + err_unlock: ++ iio_trigger_notify_done(indio_dev->trig); + mutex_unlock(&st->lock); + + return IRQ_HANDLED; +diff --git a/drivers/iio/adc/at91-sama5d2_adc.c b/drivers/iio/adc/at91-sama5d2_adc.c +index b8139c435a4b0..4ede7e766765e 100644 +--- a/drivers/iio/adc/at91-sama5d2_adc.c ++++ b/drivers/iio/adc/at91-sama5d2_adc.c +@@ -1401,7 +1401,8 @@ static int at91_adc_read_info_raw(struct iio_dev *indio_dev, + *val = st->conversion_value; + ret = at91_adc_adjust_val_osr(st, val); + if (chan->scan_type.sign == 's') +- *val = sign_extend32(*val, 11); ++ *val = sign_extend32(*val, ++ chan->scan_type.realbits - 1); + st->conversion_done = false; + } + +diff --git a/drivers/iio/adc/axp20x_adc.c b/drivers/iio/adc/axp20x_adc.c +index 3e0c0233b4315..df99f1365c398 100644 +--- a/drivers/iio/adc/axp20x_adc.c ++++ b/drivers/iio/adc/axp20x_adc.c +@@ -251,19 +251,8 @@ static int axp22x_adc_raw(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan, int *val) + { + struct axp20x_adc_iio *info = iio_priv(indio_dev); +- int size; + +- /* +- * N.B.: Unlike the Chinese datasheets tell, the charging current is +- * stored on 12 bits, not 13 bits. Only discharging current is on 13 +- * bits. +- */ +- if (chan->type == IIO_CURRENT && chan->channel == AXP22X_BATT_DISCHRG_I) +- size = 13; +- else +- size = 12; +- +- *val = axp20x_read_variable_width(info->regmap, chan->address, size); ++ *val = axp20x_read_variable_width(info->regmap, chan->address, 12); + if (*val < 0) + return *val; + +@@ -386,9 +375,8 @@ static int axp22x_adc_scale(struct iio_chan_spec const *chan, int *val, + return IIO_VAL_INT_PLUS_MICRO; + + case IIO_CURRENT: +- *val = 0; +- *val2 = 500000; +- return IIO_VAL_INT_PLUS_MICRO; ++ *val = 1; ++ return IIO_VAL_INT; + + case IIO_TEMP: + *val = 100; +diff --git a/drivers/iio/adc/dln2-adc.c b/drivers/iio/adc/dln2-adc.c +index 0d53ef18e0459..58b3f6065db0d 100644 +--- a/drivers/iio/adc/dln2-adc.c ++++ b/drivers/iio/adc/dln2-adc.c +@@ -248,7 +248,6 @@ static int dln2_adc_set_chan_period(struct dln2_adc *dln2, + static int dln2_adc_read(struct dln2_adc *dln2, unsigned int channel) + { + int ret, i; +- struct iio_dev *indio_dev = platform_get_drvdata(dln2->pdev); + u16 conflict; + __le16 value; + int olen = sizeof(value); +@@ -257,13 +256,9 @@ static int dln2_adc_read(struct dln2_adc *dln2, unsigned int channel) + .chan = channel, + }; + +- ret = iio_device_claim_direct_mode(indio_dev); +- if (ret < 0) +- return ret; +- + ret = dln2_adc_set_chan_enabled(dln2, channel, true); + if (ret < 0) +- goto release_direct; ++ return ret; + + ret = dln2_adc_set_port_enabled(dln2, true, &conflict); + if (ret < 0) { +@@ -300,8 +295,6 @@ disable_port: + dln2_adc_set_port_enabled(dln2, false, NULL); + disable_chan: + dln2_adc_set_chan_enabled(dln2, channel, false); +-release_direct: +- iio_device_release_direct_mode(indio_dev); + + return ret; + } +@@ -337,10 +330,16 @@ static int dln2_adc_read_raw(struct iio_dev *indio_dev, + + switch (mask) { + case IIO_CHAN_INFO_RAW: ++ ret = iio_device_claim_direct_mode(indio_dev); ++ if (ret < 0) ++ return ret; ++ + mutex_lock(&dln2->mutex); + ret = dln2_adc_read(dln2, chan->channel); + mutex_unlock(&dln2->mutex); + ++ iio_device_release_direct_mode(indio_dev); ++ + if (ret < 0) + return ret; + +@@ -655,7 +654,11 @@ static int dln2_adc_probe(struct platform_device *pdev) + return -ENOMEM; + } + iio_trigger_set_drvdata(dln2->trig, dln2); +- devm_iio_trigger_register(dev, dln2->trig); ++ ret = devm_iio_trigger_register(dev, dln2->trig); ++ if (ret) { ++ dev_err(dev, "failed to register trigger: %d\n", ret); ++ return ret; ++ } + iio_trigger_set_immutable(indio_dev, dln2->trig); + + ret = devm_iio_triggered_buffer_setup(dev, indio_dev, NULL, +diff --git a/drivers/iio/adc/stm32-adc.c b/drivers/iio/adc/stm32-adc.c +index 16c02c30dec75..9939dee017433 100644 +--- a/drivers/iio/adc/stm32-adc.c ++++ b/drivers/iio/adc/stm32-adc.c +@@ -979,6 +979,7 @@ static void stm32h7_adc_unprepare(struct iio_dev *indio_dev) + { + struct stm32_adc *adc = iio_priv(indio_dev); + ++ stm32_adc_writel(adc, STM32H7_ADC_PCSEL, 0); + stm32h7_adc_disable(indio_dev); + stm32h7_adc_enter_pwr_down(adc); + } +diff --git a/drivers/iio/gyro/adxrs290.c b/drivers/iio/gyro/adxrs290.c +index ca6fc234076ee..c7f9963391558 100644 +--- a/drivers/iio/gyro/adxrs290.c ++++ b/drivers/iio/gyro/adxrs290.c +@@ -7,6 +7,7 @@ + */ + + #include <linux/bitfield.h> ++#include <linux/bitops.h> + #include <linux/delay.h> + #include <linux/device.h> + #include <linux/kernel.h> +@@ -124,7 +125,7 @@ static int adxrs290_get_rate_data(struct iio_dev *indio_dev, const u8 cmd, int * + goto err_unlock; + } + +- *val = temp; ++ *val = sign_extend32(temp, 15); + + err_unlock: + mutex_unlock(&st->lock); +@@ -146,7 +147,7 @@ static int adxrs290_get_temp_data(struct iio_dev *indio_dev, int *val) + } + + /* extract lower 12 bits temperature reading */ +- *val = temp & 0x0FFF; ++ *val = sign_extend32(temp, 11); + + err_unlock: + mutex_unlock(&st->lock); +diff --git a/drivers/iio/gyro/itg3200_buffer.c b/drivers/iio/gyro/itg3200_buffer.c +index 1c3c1bd53374a..98b3f021f0bec 100644 +--- a/drivers/iio/gyro/itg3200_buffer.c ++++ b/drivers/iio/gyro/itg3200_buffer.c +@@ -61,9 +61,9 @@ static irqreturn_t itg3200_trigger_handler(int irq, void *p) + + iio_push_to_buffers_with_timestamp(indio_dev, &scan, pf->timestamp); + ++error_ret: + iio_trigger_notify_done(indio_dev->trig); + +-error_ret: + return IRQ_HANDLED; + } + +diff --git a/drivers/iio/industrialio-trigger.c b/drivers/iio/industrialio-trigger.c +index 583bb51f65a75..6bcc562d7857b 100644 +--- a/drivers/iio/industrialio-trigger.c ++++ b/drivers/iio/industrialio-trigger.c +@@ -550,7 +550,6 @@ struct iio_trigger *viio_trigger_alloc(const char *fmt, va_list vargs) + irq_modify_status(trig->subirq_base + i, + IRQ_NOREQUEST | IRQ_NOAUTOEN, IRQ_NOPROBE); + } +- get_device(&trig->dev); + + return trig; + +diff --git a/drivers/iio/light/ltr501.c b/drivers/iio/light/ltr501.c +index 74ed2d88a3ed3..379236a806fac 100644 +--- a/drivers/iio/light/ltr501.c ++++ b/drivers/iio/light/ltr501.c +@@ -1273,7 +1273,7 @@ static irqreturn_t ltr501_trigger_handler(int irq, void *p) + ret = regmap_bulk_read(data->regmap, LTR501_ALS_DATA1, + als_buf, sizeof(als_buf)); + if (ret < 0) +- return ret; ++ goto done; + if (test_bit(0, indio_dev->active_scan_mask)) + scan.channels[j++] = le16_to_cpu(als_buf[1]); + if (test_bit(1, indio_dev->active_scan_mask)) +diff --git a/drivers/iio/light/stk3310.c b/drivers/iio/light/stk3310.c +index a2827d03ab0fb..6654573a887c9 100644 +--- a/drivers/iio/light/stk3310.c ++++ b/drivers/iio/light/stk3310.c +@@ -546,9 +546,8 @@ static irqreturn_t stk3310_irq_event_handler(int irq, void *private) + mutex_lock(&data->lock); + ret = regmap_field_read(data->reg_flag_nf, &dir); + if (ret < 0) { +- dev_err(&data->client->dev, "register read failed\n"); +- mutex_unlock(&data->lock); +- return ret; ++ dev_err(&data->client->dev, "register read failed: %d\n", ret); ++ goto out; + } + event = IIO_UNMOD_EVENT_CODE(IIO_PROXIMITY, 1, + IIO_EV_TYPE_THRESH, +@@ -560,6 +559,7 @@ static irqreturn_t stk3310_irq_event_handler(int irq, void *private) + ret = regmap_field_write(data->reg_flag_psint, 0); + if (ret < 0) + dev_err(&data->client->dev, "failed to reset interrupts\n"); ++out: + mutex_unlock(&data->lock); + + return IRQ_HANDLED; +diff --git a/drivers/iio/trigger/stm32-timer-trigger.c b/drivers/iio/trigger/stm32-timer-trigger.c +index 3aa9e8bba005f..e38671b41df74 100644 +--- a/drivers/iio/trigger/stm32-timer-trigger.c ++++ b/drivers/iio/trigger/stm32-timer-trigger.c +@@ -912,6 +912,6 @@ static struct platform_driver stm32_timer_trigger_driver = { + }; + module_platform_driver(stm32_timer_trigger_driver); + +-MODULE_ALIAS("platform: stm32-timer-trigger"); ++MODULE_ALIAS("platform:stm32-timer-trigger"); + MODULE_DESCRIPTION("STMicroelectronics STM32 Timer Trigger driver"); + MODULE_LICENSE("GPL v2"); +diff --git a/drivers/infiniband/hw/hfi1/chip.c b/drivers/infiniband/hw/hfi1/chip.c +index c87b94ea29397..88476a1a601a4 100644 +--- a/drivers/infiniband/hw/hfi1/chip.c ++++ b/drivers/infiniband/hw/hfi1/chip.c +@@ -8456,6 +8456,8 @@ static void receive_interrupt_common(struct hfi1_ctxtdata *rcd) + */ + static void __hfi1_rcd_eoi_intr(struct hfi1_ctxtdata *rcd) + { ++ if (!rcd->rcvhdrq) ++ return; + clear_recv_intr(rcd); + if (check_packet_present(rcd)) + force_recv_intr(rcd); +diff --git a/drivers/infiniband/hw/hfi1/driver.c b/drivers/infiniband/hw/hfi1/driver.c +index a40701a6e1b64..808571855ed15 100644 +--- a/drivers/infiniband/hw/hfi1/driver.c ++++ b/drivers/infiniband/hw/hfi1/driver.c +@@ -1053,6 +1053,8 @@ int handle_receive_interrupt(struct hfi1_ctxtdata *rcd, int thread) + struct hfi1_packet packet; + int skip_pkt = 0; + ++ if (!rcd->rcvhdrq) ++ return RCV_PKT_OK; + /* Control context will always use the slow path interrupt handler */ + needset = (rcd->ctxt == HFI1_CTRL_CTXT) ? 0 : 1; + +diff --git a/drivers/infiniband/hw/hfi1/init.c b/drivers/infiniband/hw/hfi1/init.c +index b6e453e9ba236..fa2cd76747ff4 100644 +--- a/drivers/infiniband/hw/hfi1/init.c ++++ b/drivers/infiniband/hw/hfi1/init.c +@@ -154,7 +154,6 @@ static int hfi1_create_kctxt(struct hfi1_devdata *dd, + rcd->fast_handler = get_dma_rtail_setting(rcd) ? + handle_receive_interrupt_dma_rtail : + handle_receive_interrupt_nodma_rtail; +- rcd->slow_handler = handle_receive_interrupt; + + hfi1_set_seq_cnt(rcd, 1); + +@@ -375,6 +374,8 @@ int hfi1_create_ctxtdata(struct hfi1_pportdata *ppd, int numa, + rcd->numa_id = numa; + rcd->rcv_array_groups = dd->rcv_entries.ngroups; + rcd->rhf_rcv_function_map = normal_rhf_rcv_functions; ++ rcd->slow_handler = handle_receive_interrupt; ++ rcd->do_interrupt = rcd->slow_handler; + rcd->msix_intr = CCE_NUM_MSIX_VECTORS; + + mutex_init(&rcd->exp_mutex); +@@ -915,18 +916,6 @@ int hfi1_init(struct hfi1_devdata *dd, int reinit) + if (ret) + goto done; + +- /* allocate dummy tail memory for all receive contexts */ +- dd->rcvhdrtail_dummy_kvaddr = dma_alloc_coherent(&dd->pcidev->dev, +- sizeof(u64), +- &dd->rcvhdrtail_dummy_dma, +- GFP_KERNEL); +- +- if (!dd->rcvhdrtail_dummy_kvaddr) { +- dd_dev_err(dd, "cannot allocate dummy tail memory\n"); +- ret = -ENOMEM; +- goto done; +- } +- + /* dd->rcd can be NULL if early initialization failed */ + for (i = 0; dd->rcd && i < dd->first_dyn_alloc_ctxt; ++i) { + /* +@@ -939,8 +928,6 @@ int hfi1_init(struct hfi1_devdata *dd, int reinit) + if (!rcd) + continue; + +- rcd->do_interrupt = &handle_receive_interrupt; +- + lastfail = hfi1_create_rcvhdrq(dd, rcd); + if (!lastfail) + lastfail = hfi1_setup_eagerbufs(rcd); +@@ -1161,7 +1148,7 @@ void hfi1_free_ctxtdata(struct hfi1_devdata *dd, struct hfi1_ctxtdata *rcd) + rcd->egrbufs.rcvtids = NULL; + + for (e = 0; e < rcd->egrbufs.alloced; e++) { +- if (rcd->egrbufs.buffers[e].dma) ++ if (rcd->egrbufs.buffers[e].addr) + dma_free_coherent(&dd->pcidev->dev, + rcd->egrbufs.buffers[e].len, + rcd->egrbufs.buffers[e].addr, +@@ -1242,6 +1229,11 @@ void hfi1_free_devdata(struct hfi1_devdata *dd) + dd->tx_opstats = NULL; + kfree(dd->comp_vect); + dd->comp_vect = NULL; ++ if (dd->rcvhdrtail_dummy_kvaddr) ++ dma_free_coherent(&dd->pcidev->dev, sizeof(u64), ++ (void *)dd->rcvhdrtail_dummy_kvaddr, ++ dd->rcvhdrtail_dummy_dma); ++ dd->rcvhdrtail_dummy_kvaddr = NULL; + sdma_clean(dd, dd->num_sdma); + rvt_dealloc_device(&dd->verbs_dev.rdi); + } +@@ -1339,6 +1331,15 @@ static struct hfi1_devdata *hfi1_alloc_devdata(struct pci_dev *pdev, + goto bail; + } + ++ /* allocate dummy tail memory for all receive contexts */ ++ dd->rcvhdrtail_dummy_kvaddr = ++ dma_alloc_coherent(&dd->pcidev->dev, sizeof(u64), ++ &dd->rcvhdrtail_dummy_dma, GFP_KERNEL); ++ if (!dd->rcvhdrtail_dummy_kvaddr) { ++ ret = -ENOMEM; ++ goto bail; ++ } ++ + atomic_set(&dd->ipoib_rsm_usr_num, 0); + return dd; + +@@ -1546,13 +1547,6 @@ static void cleanup_device_data(struct hfi1_devdata *dd) + + free_credit_return(dd); + +- if (dd->rcvhdrtail_dummy_kvaddr) { +- dma_free_coherent(&dd->pcidev->dev, sizeof(u64), +- (void *)dd->rcvhdrtail_dummy_kvaddr, +- dd->rcvhdrtail_dummy_dma); +- dd->rcvhdrtail_dummy_kvaddr = NULL; +- } +- + /* + * Free any resources still in use (usually just kernel contexts) + * at unload; we do for ctxtcnt, because that's what we allocate. +diff --git a/drivers/infiniband/hw/hfi1/sdma.c b/drivers/infiniband/hw/hfi1/sdma.c +index ac6f87137b637..0b73dc7847aae 100644 +--- a/drivers/infiniband/hw/hfi1/sdma.c ++++ b/drivers/infiniband/hw/hfi1/sdma.c +@@ -880,8 +880,8 @@ struct sdma_engine *sdma_select_user_engine(struct hfi1_devdata *dd, + if (current->nr_cpus_allowed != 1) + goto out; + +- cpu_id = smp_processor_id(); + rcu_read_lock(); ++ cpu_id = smp_processor_id(); + rht_node = rhashtable_lookup(dd->sdma_rht, &cpu_id, + sdma_rht_params); + +diff --git a/drivers/infiniband/hw/hns/hns_roce_hw_v2.c b/drivers/infiniband/hw/hns/hns_roce_hw_v2.c +index c29ba8ee51e29..abe882ec1bae7 100644 +--- a/drivers/infiniband/hw/hns/hns_roce_hw_v2.c ++++ b/drivers/infiniband/hw/hns/hns_roce_hw_v2.c +@@ -33,6 +33,7 @@ + #include <linux/acpi.h> + #include <linux/etherdevice.h> + #include <linux/interrupt.h> ++#include <linux/iopoll.h> + #include <linux/kernel.h> + #include <linux/types.h> + #include <net/addrconf.h> +@@ -964,9 +965,14 @@ static int hns_roce_v2_cmd_hw_resetting(struct hns_roce_dev *hr_dev, + unsigned long instance_stage, + unsigned long reset_stage) + { ++#define HW_RESET_TIMEOUT_US 1000000 ++#define HW_RESET_SLEEP_US 1000 ++ + struct hns_roce_v2_priv *priv = hr_dev->priv; + struct hnae3_handle *handle = priv->handle; + const struct hnae3_ae_ops *ops = handle->ae_algo->ops; ++ unsigned long val; ++ int ret; + + /* When hardware reset is detected, we should stop sending mailbox&cmq& + * doorbell to hardware. If now in .init_instance() function, we should +@@ -978,7 +984,11 @@ static int hns_roce_v2_cmd_hw_resetting(struct hns_roce_dev *hr_dev, + * again. + */ + hr_dev->dis_db = true; +- if (!ops->get_hw_reset_stat(handle)) ++ ++ ret = read_poll_timeout(ops->ae_dev_reset_cnt, val, ++ val > hr_dev->reset_cnt, HW_RESET_SLEEP_US, ++ HW_RESET_TIMEOUT_US, false, handle); ++ if (!ret) + hr_dev->is_reset = true; + + if (!hr_dev->is_reset || reset_stage == HNS_ROCE_STATE_RST_INIT || +@@ -6342,10 +6352,8 @@ static int hns_roce_hw_v2_reset_notify_down(struct hnae3_handle *handle) + if (!hr_dev) + return 0; + +- hr_dev->is_reset = true; + hr_dev->active = false; + hr_dev->dis_db = true; +- + hr_dev->state = HNS_ROCE_DEVICE_STATE_RST_DOWN; + + return 0; +diff --git a/drivers/irqchip/irq-armada-370-xp.c b/drivers/irqchip/irq-armada-370-xp.c +index d7eb2e93db8f5..84f2741aaac6a 100644 +--- a/drivers/irqchip/irq-armada-370-xp.c ++++ b/drivers/irqchip/irq-armada-370-xp.c +@@ -232,16 +232,12 @@ static int armada_370_xp_msi_alloc(struct irq_domain *domain, unsigned int virq, + int hwirq, i; + + mutex_lock(&msi_used_lock); ++ hwirq = bitmap_find_free_region(msi_used, PCI_MSI_DOORBELL_NR, ++ order_base_2(nr_irqs)); ++ mutex_unlock(&msi_used_lock); + +- hwirq = bitmap_find_next_zero_area(msi_used, PCI_MSI_DOORBELL_NR, +- 0, nr_irqs, 0); +- if (hwirq >= PCI_MSI_DOORBELL_NR) { +- mutex_unlock(&msi_used_lock); ++ if (hwirq < 0) + return -ENOSPC; +- } +- +- bitmap_set(msi_used, hwirq, nr_irqs); +- mutex_unlock(&msi_used_lock); + + for (i = 0; i < nr_irqs; i++) { + irq_domain_set_info(domain, virq + i, hwirq + i, +@@ -250,7 +246,7 @@ static int armada_370_xp_msi_alloc(struct irq_domain *domain, unsigned int virq, + NULL, NULL); + } + +- return hwirq; ++ return 0; + } + + static void armada_370_xp_msi_free(struct irq_domain *domain, +@@ -259,7 +255,7 @@ static void armada_370_xp_msi_free(struct irq_domain *domain, + struct irq_data *d = irq_domain_get_irq_data(domain, virq); + + mutex_lock(&msi_used_lock); +- bitmap_clear(msi_used, d->hwirq, nr_irqs); ++ bitmap_release_region(msi_used, d->hwirq, order_base_2(nr_irqs)); + mutex_unlock(&msi_used_lock); + } + +diff --git a/drivers/irqchip/irq-aspeed-scu-ic.c b/drivers/irqchip/irq-aspeed-scu-ic.c +index c90a3346b9857..0f0aac7cc1140 100644 +--- a/drivers/irqchip/irq-aspeed-scu-ic.c ++++ b/drivers/irqchip/irq-aspeed-scu-ic.c +@@ -78,8 +78,8 @@ static void aspeed_scu_ic_irq_handler(struct irq_desc *desc) + bit - scu_ic->irq_shift); + generic_handle_irq(irq); + +- regmap_update_bits(scu_ic->scu, scu_ic->reg, mask, +- BIT(bit + ASPEED_SCU_IC_STATUS_SHIFT)); ++ regmap_write_bits(scu_ic->scu, scu_ic->reg, mask, ++ BIT(bit + ASPEED_SCU_IC_STATUS_SHIFT)); + } + + chained_irq_exit(chip, desc); +diff --git a/drivers/irqchip/irq-gic-v3-its.c b/drivers/irqchip/irq-gic-v3-its.c +index 95e0b82b6c661..42b295337bafb 100644 +--- a/drivers/irqchip/irq-gic-v3-its.c ++++ b/drivers/irqchip/irq-gic-v3-its.c +@@ -742,7 +742,7 @@ static struct its_collection *its_build_invall_cmd(struct its_node *its, + + its_fixup_cmd(cmd); + +- return NULL; ++ return desc->its_invall_cmd.col; + } + + static struct its_vpe *its_build_vinvall_cmd(struct its_node *its, +diff --git a/drivers/irqchip/irq-nvic.c b/drivers/irqchip/irq-nvic.c +index f747e2209ea99..21cb31ff2bbf2 100644 +--- a/drivers/irqchip/irq-nvic.c ++++ b/drivers/irqchip/irq-nvic.c +@@ -26,7 +26,7 @@ + + #define NVIC_ISER 0x000 + #define NVIC_ICER 0x080 +-#define NVIC_IPR 0x300 ++#define NVIC_IPR 0x400 + + #define NVIC_MAX_BANKS 16 + /* +diff --git a/drivers/md/md.c b/drivers/md/md.c +index 7871e7dcd4836..2069b16b50eca 100644 +--- a/drivers/md/md.c ++++ b/drivers/md/md.c +@@ -2252,6 +2252,7 @@ super_1_rdev_size_change(struct md_rdev *rdev, sector_t num_sectors) + + if (!num_sectors || num_sectors > max_sectors) + num_sectors = max_sectors; ++ rdev->sb_start = sb_start; + } + sb = page_address(rdev->sb_page); + sb->data_size = cpu_to_le64(num_sectors); +diff --git a/drivers/misc/fastrpc.c b/drivers/misc/fastrpc.c +index a9c9d86eef4bc..ef49ac8d91019 100644 +--- a/drivers/misc/fastrpc.c ++++ b/drivers/misc/fastrpc.c +@@ -717,16 +717,18 @@ static int fastrpc_get_meta_size(struct fastrpc_invoke_ctx *ctx) + static u64 fastrpc_get_payload_size(struct fastrpc_invoke_ctx *ctx, int metalen) + { + u64 size = 0; +- int i; ++ int oix; + + size = ALIGN(metalen, FASTRPC_ALIGN); +- for (i = 0; i < ctx->nscalars; i++) { ++ for (oix = 0; oix < ctx->nbufs; oix++) { ++ int i = ctx->olaps[oix].raix; ++ + if (ctx->args[i].fd == 0 || ctx->args[i].fd == -1) { + +- if (ctx->olaps[i].offset == 0) ++ if (ctx->olaps[oix].offset == 0) + size = ALIGN(size, FASTRPC_ALIGN); + +- size += (ctx->olaps[i].mend - ctx->olaps[i].mstart); ++ size += (ctx->olaps[oix].mend - ctx->olaps[oix].mstart); + } + } + +diff --git a/drivers/mmc/host/renesas_sdhi_core.c b/drivers/mmc/host/renesas_sdhi_core.c +index addaaf2810e26..782879d46ff48 100644 +--- a/drivers/mmc/host/renesas_sdhi_core.c ++++ b/drivers/mmc/host/renesas_sdhi_core.c +@@ -660,7 +660,7 @@ static int renesas_sdhi_execute_tuning(struct mmc_host *mmc, u32 opcode) + + /* Issue CMD19 twice for each tap */ + for (i = 0; i < 2 * priv->tap_num; i++) { +- int cmd_error; ++ int cmd_error = 0; + + /* Set sampling clock position */ + sd_scc_write32(host, priv, SH_MOBILE_SDHI_SCC_TAPSET, i % priv->tap_num); +diff --git a/drivers/mtd/nand/raw/fsmc_nand.c b/drivers/mtd/nand/raw/fsmc_nand.c +index ce05dd4088e9d..663ff5300ad99 100644 +--- a/drivers/mtd/nand/raw/fsmc_nand.c ++++ b/drivers/mtd/nand/raw/fsmc_nand.c +@@ -15,6 +15,7 @@ + + #include <linux/clk.h> + #include <linux/completion.h> ++#include <linux/delay.h> + #include <linux/dmaengine.h> + #include <linux/dma-direction.h> + #include <linux/dma-mapping.h> +@@ -93,6 +94,14 @@ + + #define FSMC_BUSY_WAIT_TIMEOUT (1 * HZ) + ++/* ++ * According to SPEAr300 Reference Manual (RM0082) ++ * TOUDEL = 7ns (Output delay from the flip-flops to the board) ++ * TINDEL = 5ns (Input delay from the board to the flipflop) ++ */ ++#define TOUTDEL 7000 ++#define TINDEL 5000 ++ + struct fsmc_nand_timings { + u8 tclr; + u8 tar; +@@ -277,7 +286,7 @@ static int fsmc_calc_timings(struct fsmc_nand_data *host, + { + unsigned long hclk = clk_get_rate(host->clk); + unsigned long hclkn = NSEC_PER_SEC / hclk; +- u32 thiz, thold, twait, tset; ++ u32 thiz, thold, twait, tset, twait_min; + + if (sdrt->tRC_min < 30000) + return -EOPNOTSUPP; +@@ -309,13 +318,6 @@ static int fsmc_calc_timings(struct fsmc_nand_data *host, + else if (tims->thold > FSMC_THOLD_MASK) + tims->thold = FSMC_THOLD_MASK; + +- twait = max(sdrt->tRP_min, sdrt->tWP_min); +- tims->twait = DIV_ROUND_UP(twait / 1000, hclkn) - 1; +- if (tims->twait == 0) +- tims->twait = 1; +- else if (tims->twait > FSMC_TWAIT_MASK) +- tims->twait = FSMC_TWAIT_MASK; +- + tset = max(sdrt->tCS_min - sdrt->tWP_min, + sdrt->tCEA_max - sdrt->tREA_max); + tims->tset = DIV_ROUND_UP(tset / 1000, hclkn) - 1; +@@ -324,6 +326,21 @@ static int fsmc_calc_timings(struct fsmc_nand_data *host, + else if (tims->tset > FSMC_TSET_MASK) + tims->tset = FSMC_TSET_MASK; + ++ /* ++ * According to SPEAr300 Reference Manual (RM0082) which gives more ++ * information related to FSMSC timings than the SPEAr600 one (RM0305), ++ * twait >= tCEA - (tset * TCLK) + TOUTDEL + TINDEL ++ */ ++ twait_min = sdrt->tCEA_max - ((tims->tset + 1) * hclkn * 1000) ++ + TOUTDEL + TINDEL; ++ twait = max3(sdrt->tRP_min, sdrt->tWP_min, twait_min); ++ ++ tims->twait = DIV_ROUND_UP(twait / 1000, hclkn) - 1; ++ if (tims->twait == 0) ++ tims->twait = 1; ++ else if (tims->twait > FSMC_TWAIT_MASK) ++ tims->twait = FSMC_TWAIT_MASK; ++ + return 0; + } + +@@ -653,6 +670,9 @@ static int fsmc_exec_op(struct nand_chip *chip, const struct nand_operation *op, + instr->ctx.waitrdy.timeout_ms); + break; + } ++ ++ if (instr->delay_ns) ++ ndelay(instr->delay_ns); + } + + return ret; +diff --git a/drivers/net/bonding/bond_alb.c b/drivers/net/bonding/bond_alb.c +index c3091e00dd5fb..0436aef9c9ef5 100644 +--- a/drivers/net/bonding/bond_alb.c ++++ b/drivers/net/bonding/bond_alb.c +@@ -1531,14 +1531,14 @@ void bond_alb_monitor(struct work_struct *work) + struct slave *slave; + + if (!bond_has_slaves(bond)) { +- bond_info->tx_rebalance_counter = 0; ++ atomic_set(&bond_info->tx_rebalance_counter, 0); + bond_info->lp_counter = 0; + goto re_arm; + } + + rcu_read_lock(); + +- bond_info->tx_rebalance_counter++; ++ atomic_inc(&bond_info->tx_rebalance_counter); + bond_info->lp_counter++; + + /* send learning packets */ +@@ -1560,7 +1560,7 @@ void bond_alb_monitor(struct work_struct *work) + } + + /* rebalance tx traffic */ +- if (bond_info->tx_rebalance_counter >= BOND_TLB_REBALANCE_TICKS) { ++ if (atomic_read(&bond_info->tx_rebalance_counter) >= BOND_TLB_REBALANCE_TICKS) { + bond_for_each_slave_rcu(bond, slave, iter) { + tlb_clear_slave(bond, slave, 1); + if (slave == rcu_access_pointer(bond->curr_active_slave)) { +@@ -1570,7 +1570,7 @@ void bond_alb_monitor(struct work_struct *work) + bond_info->unbalanced_load = 0; + } + } +- bond_info->tx_rebalance_counter = 0; ++ atomic_set(&bond_info->tx_rebalance_counter, 0); + } + + if (bond_info->rlb_enabled) { +@@ -1640,7 +1640,8 @@ int bond_alb_init_slave(struct bonding *bond, struct slave *slave) + tlb_init_slave(slave); + + /* order a rebalance ASAP */ +- bond->alb_info.tx_rebalance_counter = BOND_TLB_REBALANCE_TICKS; ++ atomic_set(&bond->alb_info.tx_rebalance_counter, ++ BOND_TLB_REBALANCE_TICKS); + + if (bond->alb_info.rlb_enabled) + bond->alb_info.rlb_rebalance = 1; +@@ -1677,7 +1678,8 @@ void bond_alb_handle_link_change(struct bonding *bond, struct slave *slave, char + rlb_clear_slave(bond, slave); + } else if (link == BOND_LINK_UP) { + /* order a rebalance ASAP */ +- bond_info->tx_rebalance_counter = BOND_TLB_REBALANCE_TICKS; ++ atomic_set(&bond_info->tx_rebalance_counter, ++ BOND_TLB_REBALANCE_TICKS); + if (bond->alb_info.rlb_enabled) { + bond->alb_info.rlb_rebalance = 1; + /* If the updelay module parameter is smaller than the +diff --git a/drivers/net/can/kvaser_pciefd.c b/drivers/net/can/kvaser_pciefd.c +index 99323c273aa56..9d7445f6ef143 100644 +--- a/drivers/net/can/kvaser_pciefd.c ++++ b/drivers/net/can/kvaser_pciefd.c +@@ -248,6 +248,9 @@ MODULE_DESCRIPTION("CAN driver for Kvaser CAN/PCIe devices"); + #define KVASER_PCIEFD_SPACK_EWLR BIT(23) + #define KVASER_PCIEFD_SPACK_EPLR BIT(24) + ++/* Kvaser KCAN_EPACK second word */ ++#define KVASER_PCIEFD_EPACK_DIR_TX BIT(0) ++ + struct kvaser_pciefd; + + struct kvaser_pciefd_can { +@@ -1285,7 +1288,10 @@ static int kvaser_pciefd_rx_error_frame(struct kvaser_pciefd_can *can, + + can->err_rep_cnt++; + can->can.can_stats.bus_error++; +- stats->rx_errors++; ++ if (p->header[1] & KVASER_PCIEFD_EPACK_DIR_TX) ++ stats->tx_errors++; ++ else ++ stats->rx_errors++; + + can->bec.txerr = bec.txerr; + can->bec.rxerr = bec.rxerr; +diff --git a/drivers/net/can/m_can/m_can.c b/drivers/net/can/m_can/m_can.c +index 62bcef4bb95fd..19a7e4adb9338 100644 +--- a/drivers/net/can/m_can/m_can.c ++++ b/drivers/net/can/m_can/m_can.c +@@ -207,15 +207,15 @@ enum m_can_reg { + + /* Interrupts for version 3.0.x */ + #define IR_ERR_LEC_30X (IR_STE | IR_FOE | IR_ACKE | IR_BE | IR_CRCE) +-#define IR_ERR_BUS_30X (IR_ERR_LEC_30X | IR_WDI | IR_ELO | IR_BEU | \ +- IR_BEC | IR_TOO | IR_MRAF | IR_TSW | IR_TEFL | \ +- IR_RF1L | IR_RF0L) ++#define IR_ERR_BUS_30X (IR_ERR_LEC_30X | IR_WDI | IR_BEU | IR_BEC | \ ++ IR_TOO | IR_MRAF | IR_TSW | IR_TEFL | IR_RF1L | \ ++ IR_RF0L) + #define IR_ERR_ALL_30X (IR_ERR_STATE | IR_ERR_BUS_30X) + /* Interrupts for version >= 3.1.x */ + #define IR_ERR_LEC_31X (IR_PED | IR_PEA) +-#define IR_ERR_BUS_31X (IR_ERR_LEC_31X | IR_WDI | IR_ELO | IR_BEU | \ +- IR_BEC | IR_TOO | IR_MRAF | IR_TSW | IR_TEFL | \ +- IR_RF1L | IR_RF0L) ++#define IR_ERR_BUS_31X (IR_ERR_LEC_31X | IR_WDI | IR_BEU | IR_BEC | \ ++ IR_TOO | IR_MRAF | IR_TSW | IR_TEFL | IR_RF1L | \ ++ IR_RF0L) + #define IR_ERR_ALL_31X (IR_ERR_STATE | IR_ERR_BUS_31X) + + /* Interrupt Line Select (ILS) */ +@@ -752,8 +752,6 @@ static void m_can_handle_other_err(struct net_device *dev, u32 irqstatus) + { + if (irqstatus & IR_WDI) + netdev_err(dev, "Message RAM Watchdog event due to missing READY\n"); +- if (irqstatus & IR_ELO) +- netdev_err(dev, "Error Logging Overflow\n"); + if (irqstatus & IR_BEU) + netdev_err(dev, "Bit Error Uncorrected\n"); + if (irqstatus & IR_BEC) +diff --git a/drivers/net/can/pch_can.c b/drivers/net/can/pch_can.c +index 5c180d2f3c3c1..79d9abdcc65aa 100644 +--- a/drivers/net/can/pch_can.c ++++ b/drivers/net/can/pch_can.c +@@ -692,11 +692,11 @@ static int pch_can_rx_normal(struct net_device *ndev, u32 obj_num, int quota) + cf->data[i + 1] = data_reg >> 8; + } + +- netif_receive_skb(skb); + rcv_pkts++; + stats->rx_packets++; + quota--; + stats->rx_bytes += cf->can_dlc; ++ netif_receive_skb(skb); + + pch_fifo_thresh(priv, obj_num); + obj_num++; +diff --git a/drivers/net/can/sja1000/ems_pcmcia.c b/drivers/net/can/sja1000/ems_pcmcia.c +index 770304eaef950..80b30768d9c6c 100644 +--- a/drivers/net/can/sja1000/ems_pcmcia.c ++++ b/drivers/net/can/sja1000/ems_pcmcia.c +@@ -235,7 +235,12 @@ static int ems_pcmcia_add_card(struct pcmcia_device *pdev, unsigned long base) + free_sja1000dev(dev); + } + +- err = request_irq(dev->irq, &ems_pcmcia_interrupt, IRQF_SHARED, ++ if (!card->channels) { ++ err = -ENODEV; ++ goto failure_cleanup; ++ } ++ ++ err = request_irq(pdev->irq, &ems_pcmcia_interrupt, IRQF_SHARED, + DRV_NAME, card); + if (!err) + return 0; +diff --git a/drivers/net/can/usb/kvaser_usb/kvaser_usb_leaf.c b/drivers/net/can/usb/kvaser_usb/kvaser_usb_leaf.c +index 1b9957f12459a..8b5d1add899a6 100644 +--- a/drivers/net/can/usb/kvaser_usb/kvaser_usb_leaf.c ++++ b/drivers/net/can/usb/kvaser_usb/kvaser_usb_leaf.c +@@ -28,10 +28,6 @@ + + #include "kvaser_usb.h" + +-/* Forward declaration */ +-static const struct kvaser_usb_dev_cfg kvaser_usb_leaf_dev_cfg; +- +-#define CAN_USB_CLOCK 8000000 + #define MAX_USBCAN_NET_DEVICES 2 + + /* Command header size */ +@@ -80,6 +76,12 @@ static const struct kvaser_usb_dev_cfg kvaser_usb_leaf_dev_cfg; + + #define CMD_LEAF_LOG_MESSAGE 106 + ++/* Leaf frequency options */ ++#define KVASER_USB_LEAF_SWOPTION_FREQ_MASK 0x60 ++#define KVASER_USB_LEAF_SWOPTION_FREQ_16_MHZ_CLK 0 ++#define KVASER_USB_LEAF_SWOPTION_FREQ_32_MHZ_CLK BIT(5) ++#define KVASER_USB_LEAF_SWOPTION_FREQ_24_MHZ_CLK BIT(6) ++ + /* error factors */ + #define M16C_EF_ACKE BIT(0) + #define M16C_EF_CRCE BIT(1) +@@ -340,6 +342,50 @@ struct kvaser_usb_err_summary { + }; + }; + ++static const struct can_bittiming_const kvaser_usb_leaf_bittiming_const = { ++ .name = "kvaser_usb", ++ .tseg1_min = KVASER_USB_TSEG1_MIN, ++ .tseg1_max = KVASER_USB_TSEG1_MAX, ++ .tseg2_min = KVASER_USB_TSEG2_MIN, ++ .tseg2_max = KVASER_USB_TSEG2_MAX, ++ .sjw_max = KVASER_USB_SJW_MAX, ++ .brp_min = KVASER_USB_BRP_MIN, ++ .brp_max = KVASER_USB_BRP_MAX, ++ .brp_inc = KVASER_USB_BRP_INC, ++}; ++ ++static const struct kvaser_usb_dev_cfg kvaser_usb_leaf_dev_cfg_8mhz = { ++ .clock = { ++ .freq = 8000000, ++ }, ++ .timestamp_freq = 1, ++ .bittiming_const = &kvaser_usb_leaf_bittiming_const, ++}; ++ ++static const struct kvaser_usb_dev_cfg kvaser_usb_leaf_dev_cfg_16mhz = { ++ .clock = { ++ .freq = 16000000, ++ }, ++ .timestamp_freq = 1, ++ .bittiming_const = &kvaser_usb_leaf_bittiming_const, ++}; ++ ++static const struct kvaser_usb_dev_cfg kvaser_usb_leaf_dev_cfg_24mhz = { ++ .clock = { ++ .freq = 24000000, ++ }, ++ .timestamp_freq = 1, ++ .bittiming_const = &kvaser_usb_leaf_bittiming_const, ++}; ++ ++static const struct kvaser_usb_dev_cfg kvaser_usb_leaf_dev_cfg_32mhz = { ++ .clock = { ++ .freq = 32000000, ++ }, ++ .timestamp_freq = 1, ++ .bittiming_const = &kvaser_usb_leaf_bittiming_const, ++}; ++ + static void * + kvaser_usb_leaf_frame_to_cmd(const struct kvaser_usb_net_priv *priv, + const struct sk_buff *skb, int *frame_len, +@@ -471,6 +517,27 @@ static int kvaser_usb_leaf_send_simple_cmd(const struct kvaser_usb *dev, + return rc; + } + ++static void kvaser_usb_leaf_get_software_info_leaf(struct kvaser_usb *dev, ++ const struct leaf_cmd_softinfo *softinfo) ++{ ++ u32 sw_options = le32_to_cpu(softinfo->sw_options); ++ ++ dev->fw_version = le32_to_cpu(softinfo->fw_version); ++ dev->max_tx_urbs = le16_to_cpu(softinfo->max_outstanding_tx); ++ ++ switch (sw_options & KVASER_USB_LEAF_SWOPTION_FREQ_MASK) { ++ case KVASER_USB_LEAF_SWOPTION_FREQ_16_MHZ_CLK: ++ dev->cfg = &kvaser_usb_leaf_dev_cfg_16mhz; ++ break; ++ case KVASER_USB_LEAF_SWOPTION_FREQ_24_MHZ_CLK: ++ dev->cfg = &kvaser_usb_leaf_dev_cfg_24mhz; ++ break; ++ case KVASER_USB_LEAF_SWOPTION_FREQ_32_MHZ_CLK: ++ dev->cfg = &kvaser_usb_leaf_dev_cfg_32mhz; ++ break; ++ } ++} ++ + static int kvaser_usb_leaf_get_software_info_inner(struct kvaser_usb *dev) + { + struct kvaser_cmd cmd; +@@ -486,14 +553,13 @@ static int kvaser_usb_leaf_get_software_info_inner(struct kvaser_usb *dev) + + switch (dev->card_data.leaf.family) { + case KVASER_LEAF: +- dev->fw_version = le32_to_cpu(cmd.u.leaf.softinfo.fw_version); +- dev->max_tx_urbs = +- le16_to_cpu(cmd.u.leaf.softinfo.max_outstanding_tx); ++ kvaser_usb_leaf_get_software_info_leaf(dev, &cmd.u.leaf.softinfo); + break; + case KVASER_USBCAN: + dev->fw_version = le32_to_cpu(cmd.u.usbcan.softinfo.fw_version); + dev->max_tx_urbs = + le16_to_cpu(cmd.u.usbcan.softinfo.max_outstanding_tx); ++ dev->cfg = &kvaser_usb_leaf_dev_cfg_8mhz; + break; + } + +@@ -1225,24 +1291,11 @@ static int kvaser_usb_leaf_init_card(struct kvaser_usb *dev) + { + struct kvaser_usb_dev_card_data *card_data = &dev->card_data; + +- dev->cfg = &kvaser_usb_leaf_dev_cfg; + card_data->ctrlmode_supported |= CAN_CTRLMODE_3_SAMPLES; + + return 0; + } + +-static const struct can_bittiming_const kvaser_usb_leaf_bittiming_const = { +- .name = "kvaser_usb", +- .tseg1_min = KVASER_USB_TSEG1_MIN, +- .tseg1_max = KVASER_USB_TSEG1_MAX, +- .tseg2_min = KVASER_USB_TSEG2_MIN, +- .tseg2_max = KVASER_USB_TSEG2_MAX, +- .sjw_max = KVASER_USB_SJW_MAX, +- .brp_min = KVASER_USB_BRP_MIN, +- .brp_max = KVASER_USB_BRP_MAX, +- .brp_inc = KVASER_USB_BRP_INC, +-}; +- + static int kvaser_usb_leaf_set_bittiming(struct net_device *netdev) + { + struct kvaser_usb_net_priv *priv = netdev_priv(netdev); +@@ -1348,11 +1401,3 @@ const struct kvaser_usb_dev_ops kvaser_usb_leaf_dev_ops = { + .dev_read_bulk_callback = kvaser_usb_leaf_read_bulk_callback, + .dev_frame_to_cmd = kvaser_usb_leaf_frame_to_cmd, + }; +- +-static const struct kvaser_usb_dev_cfg kvaser_usb_leaf_dev_cfg = { +- .clock = { +- .freq = CAN_USB_CLOCK, +- }, +- .timestamp_freq = 1, +- .bittiming_const = &kvaser_usb_leaf_bittiming_const, +-}; +diff --git a/drivers/net/ethernet/altera/altera_tse_main.c b/drivers/net/ethernet/altera/altera_tse_main.c +index 907125abef2c1..a7d8d45e0e941 100644 +--- a/drivers/net/ethernet/altera/altera_tse_main.c ++++ b/drivers/net/ethernet/altera/altera_tse_main.c +@@ -1431,16 +1431,19 @@ static int altera_tse_probe(struct platform_device *pdev) + priv->rxdescmem_busaddr = dma_res->start; + + } else { ++ ret = -ENODEV; + goto err_free_netdev; + } + +- if (!dma_set_mask(priv->device, DMA_BIT_MASK(priv->dmaops->dmamask))) ++ if (!dma_set_mask(priv->device, DMA_BIT_MASK(priv->dmaops->dmamask))) { + dma_set_coherent_mask(priv->device, + DMA_BIT_MASK(priv->dmaops->dmamask)); +- else if (!dma_set_mask(priv->device, DMA_BIT_MASK(32))) ++ } else if (!dma_set_mask(priv->device, DMA_BIT_MASK(32))) { + dma_set_coherent_mask(priv->device, DMA_BIT_MASK(32)); +- else ++ } else { ++ ret = -EIO; + goto err_free_netdev; ++ } + + /* MAC address space */ + ret = request_and_map(pdev, "control_port", &control_port, +diff --git a/drivers/net/ethernet/freescale/fec.h b/drivers/net/ethernet/freescale/fec.h +index c527f4ee1d3ae..6ea98af63b341 100644 +--- a/drivers/net/ethernet/freescale/fec.h ++++ b/drivers/net/ethernet/freescale/fec.h +@@ -373,6 +373,9 @@ struct bufdesc_ex { + #define FEC_ENET_WAKEUP ((uint)0x00020000) /* Wakeup request */ + #define FEC_ENET_TXF (FEC_ENET_TXF_0 | FEC_ENET_TXF_1 | FEC_ENET_TXF_2) + #define FEC_ENET_RXF (FEC_ENET_RXF_0 | FEC_ENET_RXF_1 | FEC_ENET_RXF_2) ++#define FEC_ENET_RXF_GET(X) (((X) == 0) ? FEC_ENET_RXF_0 : \ ++ (((X) == 1) ? FEC_ENET_RXF_1 : \ ++ FEC_ENET_RXF_2)) + #define FEC_ENET_TS_AVAIL ((uint)0x00010000) + #define FEC_ENET_TS_TIMER ((uint)0x00008000) + +diff --git a/drivers/net/ethernet/freescale/fec_main.c b/drivers/net/ethernet/freescale/fec_main.c +index 94eb838a01760..166bc3f3b34cc 100644 +--- a/drivers/net/ethernet/freescale/fec_main.c ++++ b/drivers/net/ethernet/freescale/fec_main.c +@@ -1439,7 +1439,7 @@ fec_enet_rx_queue(struct net_device *ndev, int budget, u16 queue_id) + break; + pkt_received++; + +- writel(FEC_ENET_RXF, fep->hwp + FEC_IEVENT); ++ writel(FEC_ENET_RXF_GET(queue_id), fep->hwp + FEC_IEVENT); + + /* Check for errors. */ + status ^= BD_ENET_RX_LAST; +diff --git a/drivers/net/ethernet/intel/i40e/i40e_debugfs.c b/drivers/net/ethernet/intel/i40e/i40e_debugfs.c +index d627b59ad4465..714b578b2b49c 100644 +--- a/drivers/net/ethernet/intel/i40e/i40e_debugfs.c ++++ b/drivers/net/ethernet/intel/i40e/i40e_debugfs.c +@@ -553,6 +553,14 @@ static void i40e_dbg_dump_desc(int cnt, int vsi_seid, int ring_id, int desc_n, + dev_info(&pf->pdev->dev, "vsi %d not found\n", vsi_seid); + return; + } ++ if (vsi->type != I40E_VSI_MAIN && ++ vsi->type != I40E_VSI_FDIR && ++ vsi->type != I40E_VSI_VMDQ2) { ++ dev_info(&pf->pdev->dev, ++ "vsi %d type %d descriptor rings not available\n", ++ vsi_seid, vsi->type); ++ return; ++ } + if (type == RING_TYPE_XDP && !i40e_enabled_xdp_vsi(vsi)) { + dev_info(&pf->pdev->dev, "XDP not enabled on VSI %d\n", vsi_seid); + return; +diff --git a/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c b/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c +index 41c0a103119c1..5a58edba4adfc 100644 +--- a/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c ++++ b/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c +@@ -1895,6 +1895,32 @@ static int i40e_vc_send_resp_to_vf(struct i40e_vf *vf, + return i40e_vc_send_msg_to_vf(vf, opcode, retval, NULL, 0); + } + ++/** ++ * i40e_sync_vf_state ++ * @vf: pointer to the VF info ++ * @state: VF state ++ * ++ * Called from a VF message to synchronize the service with a potential ++ * VF reset state ++ **/ ++static bool i40e_sync_vf_state(struct i40e_vf *vf, enum i40e_vf_states state) ++{ ++ int i; ++ ++ /* When handling some messages, it needs VF state to be set. ++ * It is possible that this flag is cleared during VF reset, ++ * so there is a need to wait until the end of the reset to ++ * handle the request message correctly. ++ */ ++ for (i = 0; i < I40E_VF_STATE_WAIT_COUNT; i++) { ++ if (test_bit(state, &vf->vf_states)) ++ return true; ++ usleep_range(10000, 20000); ++ } ++ ++ return test_bit(state, &vf->vf_states); ++} ++ + /** + * i40e_vc_get_version_msg + * @vf: pointer to the VF info +@@ -1955,7 +1981,7 @@ static int i40e_vc_get_vf_resources_msg(struct i40e_vf *vf, u8 *msg) + size_t len = 0; + int ret; + +- if (!test_bit(I40E_VF_STATE_INIT, &vf->vf_states)) { ++ if (!i40e_sync_vf_state(vf, I40E_VF_STATE_INIT)) { + aq_ret = I40E_ERR_PARAM; + goto err; + } +@@ -2077,7 +2103,7 @@ static int i40e_vc_config_promiscuous_mode_msg(struct i40e_vf *vf, u8 *msg) + bool allmulti = false; + bool alluni = false; + +- if (!test_bit(I40E_VF_STATE_ACTIVE, &vf->vf_states)) { ++ if (!i40e_sync_vf_state(vf, I40E_VF_STATE_ACTIVE)) { + aq_ret = I40E_ERR_PARAM; + goto err_out; + } +@@ -2165,7 +2191,7 @@ static int i40e_vc_config_queues_msg(struct i40e_vf *vf, u8 *msg) + struct i40e_vsi *vsi; + u16 num_qps_all = 0; + +- if (!test_bit(I40E_VF_STATE_ACTIVE, &vf->vf_states)) { ++ if (!i40e_sync_vf_state(vf, I40E_VF_STATE_ACTIVE)) { + aq_ret = I40E_ERR_PARAM; + goto error_param; + } +@@ -2314,7 +2340,7 @@ static int i40e_vc_config_irq_map_msg(struct i40e_vf *vf, u8 *msg) + i40e_status aq_ret = 0; + int i; + +- if (!test_bit(I40E_VF_STATE_ACTIVE, &vf->vf_states)) { ++ if (!i40e_sync_vf_state(vf, I40E_VF_STATE_ACTIVE)) { + aq_ret = I40E_ERR_PARAM; + goto error_param; + } +@@ -2486,7 +2512,7 @@ static int i40e_vc_disable_queues_msg(struct i40e_vf *vf, u8 *msg) + struct i40e_pf *pf = vf->pf; + i40e_status aq_ret = 0; + +- if (!test_bit(I40E_VF_STATE_ACTIVE, &vf->vf_states)) { ++ if (!i40e_sync_vf_state(vf, I40E_VF_STATE_ACTIVE)) { + aq_ret = I40E_ERR_PARAM; + goto error_param; + } +@@ -2536,7 +2562,7 @@ static int i40e_vc_request_queues_msg(struct i40e_vf *vf, u8 *msg) + u8 cur_pairs = vf->num_queue_pairs; + struct i40e_pf *pf = vf->pf; + +- if (!test_bit(I40E_VF_STATE_ACTIVE, &vf->vf_states)) ++ if (!i40e_sync_vf_state(vf, I40E_VF_STATE_ACTIVE)) + return -EINVAL; + + if (req_pairs > I40E_MAX_VF_QUEUES) { +@@ -2581,7 +2607,7 @@ static int i40e_vc_get_stats_msg(struct i40e_vf *vf, u8 *msg) + + memset(&stats, 0, sizeof(struct i40e_eth_stats)); + +- if (!test_bit(I40E_VF_STATE_ACTIVE, &vf->vf_states)) { ++ if (!i40e_sync_vf_state(vf, I40E_VF_STATE_ACTIVE)) { + aq_ret = I40E_ERR_PARAM; + goto error_param; + } +@@ -2698,7 +2724,7 @@ static int i40e_vc_add_mac_addr_msg(struct i40e_vf *vf, u8 *msg) + i40e_status ret = 0; + int i; + +- if (!test_bit(I40E_VF_STATE_ACTIVE, &vf->vf_states) || ++ if (!i40e_sync_vf_state(vf, I40E_VF_STATE_ACTIVE) || + !i40e_vc_isvalid_vsi_id(vf, al->vsi_id)) { + ret = I40E_ERR_PARAM; + goto error_param; +@@ -2770,7 +2796,7 @@ static int i40e_vc_del_mac_addr_msg(struct i40e_vf *vf, u8 *msg) + i40e_status ret = 0; + int i; + +- if (!test_bit(I40E_VF_STATE_ACTIVE, &vf->vf_states) || ++ if (!i40e_sync_vf_state(vf, I40E_VF_STATE_ACTIVE) || + !i40e_vc_isvalid_vsi_id(vf, al->vsi_id)) { + ret = I40E_ERR_PARAM; + goto error_param; +@@ -2914,7 +2940,7 @@ static int i40e_vc_remove_vlan_msg(struct i40e_vf *vf, u8 *msg) + i40e_status aq_ret = 0; + int i; + +- if (!test_bit(I40E_VF_STATE_ACTIVE, &vf->vf_states) || ++ if (!i40e_sync_vf_state(vf, I40E_VF_STATE_ACTIVE) || + !i40e_vc_isvalid_vsi_id(vf, vfl->vsi_id)) { + aq_ret = I40E_ERR_PARAM; + goto error_param; +@@ -3034,9 +3060,9 @@ static int i40e_vc_config_rss_key(struct i40e_vf *vf, u8 *msg) + struct i40e_vsi *vsi = NULL; + i40e_status aq_ret = 0; + +- if (!test_bit(I40E_VF_STATE_ACTIVE, &vf->vf_states) || ++ if (!i40e_sync_vf_state(vf, I40E_VF_STATE_ACTIVE) || + !i40e_vc_isvalid_vsi_id(vf, vrk->vsi_id) || +- (vrk->key_len != I40E_HKEY_ARRAY_SIZE)) { ++ vrk->key_len != I40E_HKEY_ARRAY_SIZE) { + aq_ret = I40E_ERR_PARAM; + goto err; + } +@@ -3065,9 +3091,9 @@ static int i40e_vc_config_rss_lut(struct i40e_vf *vf, u8 *msg) + i40e_status aq_ret = 0; + u16 i; + +- if (!test_bit(I40E_VF_STATE_ACTIVE, &vf->vf_states) || ++ if (!i40e_sync_vf_state(vf, I40E_VF_STATE_ACTIVE) || + !i40e_vc_isvalid_vsi_id(vf, vrl->vsi_id) || +- (vrl->lut_entries != I40E_VF_HLUT_ARRAY_SIZE)) { ++ vrl->lut_entries != I40E_VF_HLUT_ARRAY_SIZE) { + aq_ret = I40E_ERR_PARAM; + goto err; + } +@@ -3100,7 +3126,7 @@ static int i40e_vc_get_rss_hena(struct i40e_vf *vf, u8 *msg) + i40e_status aq_ret = 0; + int len = 0; + +- if (!test_bit(I40E_VF_STATE_ACTIVE, &vf->vf_states)) { ++ if (!i40e_sync_vf_state(vf, I40E_VF_STATE_ACTIVE)) { + aq_ret = I40E_ERR_PARAM; + goto err; + } +@@ -3136,7 +3162,7 @@ static int i40e_vc_set_rss_hena(struct i40e_vf *vf, u8 *msg) + struct i40e_hw *hw = &pf->hw; + i40e_status aq_ret = 0; + +- if (!test_bit(I40E_VF_STATE_ACTIVE, &vf->vf_states)) { ++ if (!i40e_sync_vf_state(vf, I40E_VF_STATE_ACTIVE)) { + aq_ret = I40E_ERR_PARAM; + goto err; + } +@@ -3161,7 +3187,7 @@ static int i40e_vc_enable_vlan_stripping(struct i40e_vf *vf, u8 *msg) + i40e_status aq_ret = 0; + struct i40e_vsi *vsi; + +- if (!test_bit(I40E_VF_STATE_ACTIVE, &vf->vf_states)) { ++ if (!i40e_sync_vf_state(vf, I40E_VF_STATE_ACTIVE)) { + aq_ret = I40E_ERR_PARAM; + goto err; + } +@@ -3187,7 +3213,7 @@ static int i40e_vc_disable_vlan_stripping(struct i40e_vf *vf, u8 *msg) + i40e_status aq_ret = 0; + struct i40e_vsi *vsi; + +- if (!test_bit(I40E_VF_STATE_ACTIVE, &vf->vf_states)) { ++ if (!i40e_sync_vf_state(vf, I40E_VF_STATE_ACTIVE)) { + aq_ret = I40E_ERR_PARAM; + goto err; + } +@@ -3414,7 +3440,7 @@ static int i40e_vc_del_cloud_filter(struct i40e_vf *vf, u8 *msg) + i40e_status aq_ret = 0; + int i, ret; + +- if (!test_bit(I40E_VF_STATE_ACTIVE, &vf->vf_states)) { ++ if (!i40e_sync_vf_state(vf, I40E_VF_STATE_ACTIVE)) { + aq_ret = I40E_ERR_PARAM; + goto err; + } +@@ -3545,7 +3571,7 @@ static int i40e_vc_add_cloud_filter(struct i40e_vf *vf, u8 *msg) + i40e_status aq_ret = 0; + int i, ret; + +- if (!test_bit(I40E_VF_STATE_ACTIVE, &vf->vf_states)) { ++ if (!i40e_sync_vf_state(vf, I40E_VF_STATE_ACTIVE)) { + aq_ret = I40E_ERR_PARAM; + goto err_out; + } +@@ -3654,7 +3680,7 @@ static int i40e_vc_add_qch_msg(struct i40e_vf *vf, u8 *msg) + i40e_status aq_ret = 0; + u64 speed = 0; + +- if (!test_bit(I40E_VF_STATE_ACTIVE, &vf->vf_states)) { ++ if (!i40e_sync_vf_state(vf, I40E_VF_STATE_ACTIVE)) { + aq_ret = I40E_ERR_PARAM; + goto err; + } +@@ -3761,11 +3787,6 @@ static int i40e_vc_add_qch_msg(struct i40e_vf *vf, u8 *msg) + + /* set this flag only after making sure all inputs are sane */ + vf->adq_enabled = true; +- /* num_req_queues is set when user changes number of queues via ethtool +- * and this causes issue for default VSI(which depends on this variable) +- * when ADq is enabled, hence reset it. +- */ +- vf->num_req_queues = 0; + + /* reset the VF in order to allocate resources */ + i40e_vc_reset_vf(vf, true); +@@ -3788,7 +3809,7 @@ static int i40e_vc_del_qch_msg(struct i40e_vf *vf, u8 *msg) + struct i40e_pf *pf = vf->pf; + i40e_status aq_ret = 0; + +- if (!test_bit(I40E_VF_STATE_ACTIVE, &vf->vf_states)) { ++ if (!i40e_sync_vf_state(vf, I40E_VF_STATE_ACTIVE)) { + aq_ret = I40E_ERR_PARAM; + goto err; + } +diff --git a/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.h b/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.h +index 091e32c1bb46f..49575a640a84c 100644 +--- a/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.h ++++ b/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.h +@@ -18,6 +18,8 @@ + + #define I40E_MAX_VF_PROMISC_FLAGS 3 + ++#define I40E_VF_STATE_WAIT_COUNT 20 ++ + /* Various queue ctrls */ + enum i40e_queue_ctrl { + I40E_QUEUE_CTRL_UNKNOWN = 0, +diff --git a/drivers/net/ethernet/intel/iavf/iavf_ethtool.c b/drivers/net/ethernet/intel/iavf/iavf_ethtool.c +index 90f5ec982d513..4680a2fe6d3cc 100644 +--- a/drivers/net/ethernet/intel/iavf/iavf_ethtool.c ++++ b/drivers/net/ethernet/intel/iavf/iavf_ethtool.c +@@ -612,23 +612,44 @@ static int iavf_set_ringparam(struct net_device *netdev, + if ((ring->rx_mini_pending) || (ring->rx_jumbo_pending)) + return -EINVAL; + +- new_tx_count = clamp_t(u32, ring->tx_pending, +- IAVF_MIN_TXD, +- IAVF_MAX_TXD); +- new_tx_count = ALIGN(new_tx_count, IAVF_REQ_DESCRIPTOR_MULTIPLE); ++ if (ring->tx_pending > IAVF_MAX_TXD || ++ ring->tx_pending < IAVF_MIN_TXD || ++ ring->rx_pending > IAVF_MAX_RXD || ++ ring->rx_pending < IAVF_MIN_RXD) { ++ netdev_err(netdev, "Descriptors requested (Tx: %d / Rx: %d) out of range [%d-%d] (increment %d)\n", ++ ring->tx_pending, ring->rx_pending, IAVF_MIN_TXD, ++ IAVF_MAX_RXD, IAVF_REQ_DESCRIPTOR_MULTIPLE); ++ return -EINVAL; ++ } + +- new_rx_count = clamp_t(u32, ring->rx_pending, +- IAVF_MIN_RXD, +- IAVF_MAX_RXD); +- new_rx_count = ALIGN(new_rx_count, IAVF_REQ_DESCRIPTOR_MULTIPLE); ++ new_tx_count = ALIGN(ring->tx_pending, IAVF_REQ_DESCRIPTOR_MULTIPLE); ++ if (new_tx_count != ring->tx_pending) ++ netdev_info(netdev, "Requested Tx descriptor count rounded up to %d\n", ++ new_tx_count); ++ ++ new_rx_count = ALIGN(ring->rx_pending, IAVF_REQ_DESCRIPTOR_MULTIPLE); ++ if (new_rx_count != ring->rx_pending) ++ netdev_info(netdev, "Requested Rx descriptor count rounded up to %d\n", ++ new_rx_count); + + /* if nothing to do return success */ + if ((new_tx_count == adapter->tx_desc_count) && +- (new_rx_count == adapter->rx_desc_count)) ++ (new_rx_count == adapter->rx_desc_count)) { ++ netdev_dbg(netdev, "Nothing to change, descriptor count is same as requested\n"); + return 0; ++ } + +- adapter->tx_desc_count = new_tx_count; +- adapter->rx_desc_count = new_rx_count; ++ if (new_tx_count != adapter->tx_desc_count) { ++ netdev_dbg(netdev, "Changing Tx descriptor count from %d to %d\n", ++ adapter->tx_desc_count, new_tx_count); ++ adapter->tx_desc_count = new_tx_count; ++ } ++ ++ if (new_rx_count != adapter->rx_desc_count) { ++ netdev_dbg(netdev, "Changing Rx descriptor count from %d to %d\n", ++ adapter->rx_desc_count, new_rx_count); ++ adapter->rx_desc_count = new_rx_count; ++ } + + if (netif_running(netdev)) { + adapter->flags |= IAVF_FLAG_RESET_NEEDED; +diff --git a/drivers/net/ethernet/intel/iavf/iavf_main.c b/drivers/net/ethernet/intel/iavf/iavf_main.c +index 643679cad8657..7aa49d4eaa87c 100644 +--- a/drivers/net/ethernet/intel/iavf/iavf_main.c ++++ b/drivers/net/ethernet/intel/iavf/iavf_main.c +@@ -2139,6 +2139,7 @@ static void iavf_reset_task(struct work_struct *work) + } + + pci_set_master(adapter->pdev); ++ pci_restore_msi_state(adapter->pdev); + + if (i == IAVF_RESET_WAIT_COMPLETE_COUNT) { + dev_err(&adapter->pdev->dev, "Reset never finished (%x)\n", +diff --git a/drivers/net/ethernet/intel/ice/ice_main.c b/drivers/net/ethernet/intel/ice/ice_main.c +index 746a5bd178d3b..4c7d1720113a0 100644 +--- a/drivers/net/ethernet/intel/ice/ice_main.c ++++ b/drivers/net/ethernet/intel/ice/ice_main.c +@@ -5267,6 +5267,9 @@ static int ice_up_complete(struct ice_vsi *vsi) + netif_carrier_on(vsi->netdev); + } + ++ /* clear this now, and the first stats read will be used as baseline */ ++ vsi->stat_offsets_loaded = false; ++ + ice_service_task_schedule(pf); + + return 0; +diff --git a/drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c b/drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c +index f39841b0a248c..542cd6f2c9bd4 100644 +--- a/drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c ++++ b/drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c +@@ -2607,11 +2607,11 @@ static int mvpp2_rxq_init(struct mvpp2_port *port, + mvpp2_rxq_status_update(port, rxq->id, 0, rxq->size); + + if (priv->percpu_pools) { +- err = xdp_rxq_info_reg(&rxq->xdp_rxq_short, port->dev, rxq->id); ++ err = xdp_rxq_info_reg(&rxq->xdp_rxq_short, port->dev, rxq->logic_rxq); + if (err < 0) + goto err_free_dma; + +- err = xdp_rxq_info_reg(&rxq->xdp_rxq_long, port->dev, rxq->id); ++ err = xdp_rxq_info_reg(&rxq->xdp_rxq_long, port->dev, rxq->logic_rxq); + if (err < 0) + goto err_unregister_rxq_short; + +diff --git a/drivers/net/ethernet/netronome/nfp/nfpcore/nfp_cppcore.c b/drivers/net/ethernet/netronome/nfp/nfpcore/nfp_cppcore.c +index 94994a939277b..6ef48eb3a77d4 100644 +--- a/drivers/net/ethernet/netronome/nfp/nfpcore/nfp_cppcore.c ++++ b/drivers/net/ethernet/netronome/nfp/nfpcore/nfp_cppcore.c +@@ -803,8 +803,10 @@ int nfp_cpp_area_cache_add(struct nfp_cpp *cpp, size_t size) + return -ENOMEM; + + cache = kzalloc(sizeof(*cache), GFP_KERNEL); +- if (!cache) ++ if (!cache) { ++ nfp_cpp_area_free(area); + return -ENOMEM; ++ } + + cache->id = 0; + cache->addr = 0; +diff --git a/drivers/net/ethernet/qlogic/qede/qede_fp.c b/drivers/net/ethernet/qlogic/qede/qede_fp.c +index ca0ee29a57b50..21c906200e791 100644 +--- a/drivers/net/ethernet/qlogic/qede/qede_fp.c ++++ b/drivers/net/ethernet/qlogic/qede/qede_fp.c +@@ -1659,6 +1659,13 @@ netdev_tx_t qede_start_xmit(struct sk_buff *skb, struct net_device *ndev) + data_split = true; + } + } else { ++ if (unlikely(skb->len > ETH_TX_MAX_NON_LSO_PKT_LEN)) { ++ DP_ERR(edev, "Unexpected non LSO skb length = 0x%x\n", skb->len); ++ qede_free_failed_tx_pkt(txq, first_bd, 0, false); ++ qede_update_tx_producer(txq); ++ return NETDEV_TX_OK; ++ } ++ + val |= ((skb->len & ETH_TX_DATA_1ST_BD_PKT_LEN_MASK) << + ETH_TX_DATA_1ST_BD_PKT_LEN_SHIFT); + } +diff --git a/drivers/net/ethernet/qlogic/qla3xxx.c b/drivers/net/ethernet/qlogic/qla3xxx.c +index c7923e22a4c42..c9f32fc50254f 100644 +--- a/drivers/net/ethernet/qlogic/qla3xxx.c ++++ b/drivers/net/ethernet/qlogic/qla3xxx.c +@@ -3494,20 +3494,19 @@ static int ql_adapter_up(struct ql3_adapter *qdev) + + spin_lock_irqsave(&qdev->hw_lock, hw_flags); + +- err = ql_wait_for_drvr_lock(qdev); +- if (err) { +- err = ql_adapter_initialize(qdev); +- if (err) { +- netdev_err(ndev, "Unable to initialize adapter\n"); +- goto err_init; +- } +- netdev_err(ndev, "Releasing driver lock\n"); +- ql_sem_unlock(qdev, QL_DRVR_SEM_MASK); +- } else { ++ if (!ql_wait_for_drvr_lock(qdev)) { + netdev_err(ndev, "Could not acquire driver lock\n"); ++ err = -ENODEV; + goto err_lock; + } + ++ err = ql_adapter_initialize(qdev); ++ if (err) { ++ netdev_err(ndev, "Unable to initialize adapter\n"); ++ goto err_init; ++ } ++ ql_sem_unlock(qdev, QL_DRVR_SEM_MASK); ++ + spin_unlock_irqrestore(&qdev->hw_lock, hw_flags); + + set_bit(QL_ADAPTER_UP, &qdev->flags); +diff --git a/drivers/net/usb/cdc_ncm.c b/drivers/net/usb/cdc_ncm.c +index 04c4f1570bc8c..eaaa5aee58251 100644 +--- a/drivers/net/usb/cdc_ncm.c ++++ b/drivers/net/usb/cdc_ncm.c +@@ -181,6 +181,8 @@ static u32 cdc_ncm_check_tx_max(struct usbnet *dev, u32 new_tx) + min = ctx->max_datagram_size + ctx->max_ndp_size + sizeof(struct usb_cdc_ncm_nth32); + + max = min_t(u32, CDC_NCM_NTB_MAX_SIZE_TX, le32_to_cpu(ctx->ncm_parm.dwNtbOutMaxSize)); ++ if (max == 0) ++ max = CDC_NCM_NTB_MAX_SIZE_TX; /* dwNtbOutMaxSize not set */ + + /* some devices set dwNtbOutMaxSize too low for the above default */ + min = min(min, max); +diff --git a/drivers/net/vrf.c b/drivers/net/vrf.c +index 570e1d11ddc7a..8ab0b5a8dfeff 100644 +--- a/drivers/net/vrf.c ++++ b/drivers/net/vrf.c +@@ -771,8 +771,6 @@ static struct sk_buff *vrf_ip6_out_direct(struct net_device *vrf_dev, + + skb->dev = vrf_dev; + +- vrf_nf_set_untracked(skb); +- + err = nf_hook(NFPROTO_IPV6, NF_INET_LOCAL_OUT, net, sk, + skb, NULL, vrf_dev, vrf_ip6_out_direct_finish); + +@@ -793,6 +791,8 @@ static struct sk_buff *vrf_ip6_out(struct net_device *vrf_dev, + if (rt6_need_strict(&ipv6_hdr(skb)->daddr)) + return skb; + ++ vrf_nf_set_untracked(skb); ++ + if (qdisc_tx_is_default(vrf_dev) || + IP6CB(skb)->flags & IP6SKB_XFRM_TRANSFORMED) + return vrf_ip6_out_direct(vrf_dev, sk, skb); +@@ -1008,8 +1008,6 @@ static struct sk_buff *vrf_ip_out_direct(struct net_device *vrf_dev, + + skb->dev = vrf_dev; + +- vrf_nf_set_untracked(skb); +- + err = nf_hook(NFPROTO_IPV4, NF_INET_LOCAL_OUT, net, sk, + skb, NULL, vrf_dev, vrf_ip_out_direct_finish); + +@@ -1031,6 +1029,8 @@ static struct sk_buff *vrf_ip_out(struct net_device *vrf_dev, + ipv4_is_lbcast(ip_hdr(skb)->daddr)) + return skb; + ++ vrf_nf_set_untracked(skb); ++ + if (qdisc_tx_is_default(vrf_dev) || + IPCB(skb)->flags & IPSKB_XFRM_TRANSFORMED) + return vrf_ip_out_direct(vrf_dev, sk, skb); +diff --git a/drivers/pci/controller/pci-aardvark.c b/drivers/pci/controller/pci-aardvark.c +index 604b294bb15c9..0f6a6685ab5b5 100644 +--- a/drivers/pci/controller/pci-aardvark.c ++++ b/drivers/pci/controller/pci-aardvark.c +@@ -31,7 +31,6 @@ + #define PCIE_CORE_DEV_ID_REG 0x0 + #define PCIE_CORE_CMD_STATUS_REG 0x4 + #define PCIE_CORE_DEV_REV_REG 0x8 +-#define PCIE_CORE_EXP_ROM_BAR_REG 0x30 + #define PCIE_CORE_PCIEXP_CAP 0xc0 + #define PCIE_CORE_ERR_CAPCTL_REG 0x118 + #define PCIE_CORE_ERR_CAPCTL_ECRC_CHK_TX BIT(5) +@@ -781,10 +780,6 @@ advk_pci_bridge_emul_base_conf_read(struct pci_bridge_emul *bridge, + *value = advk_readl(pcie, PCIE_CORE_CMD_STATUS_REG); + return PCI_BRIDGE_EMUL_HANDLED; + +- case PCI_ROM_ADDRESS1: +- *value = advk_readl(pcie, PCIE_CORE_EXP_ROM_BAR_REG); +- return PCI_BRIDGE_EMUL_HANDLED; +- + case PCI_INTERRUPT_LINE: { + /* + * From the whole 32bit register we support reading from HW only +@@ -817,10 +812,6 @@ advk_pci_bridge_emul_base_conf_write(struct pci_bridge_emul *bridge, + advk_writel(pcie, new, PCIE_CORE_CMD_STATUS_REG); + break; + +- case PCI_ROM_ADDRESS1: +- advk_writel(pcie, new, PCIE_CORE_EXP_ROM_BAR_REG); +- break; +- + case PCI_INTERRUPT_LINE: + if (mask & (PCI_BRIDGE_CTL_BUS_RESET << 16)) { + u32 val = advk_readl(pcie, PCIE_CORE_CTRL1_REG); +diff --git a/drivers/scsi/pm8001/pm8001_init.c b/drivers/scsi/pm8001/pm8001_init.c +index 13b8ddec61894..01eb2ade20709 100644 +--- a/drivers/scsi/pm8001/pm8001_init.c ++++ b/drivers/scsi/pm8001/pm8001_init.c +@@ -280,12 +280,12 @@ static int pm8001_alloc(struct pm8001_hba_info *pm8001_ha, + if (rc) { + pm8001_dbg(pm8001_ha, FAIL, + "pm8001_setup_irq failed [ret: %d]\n", rc); +- goto err_out_shost; ++ goto err_out; + } + /* Request Interrupt */ + rc = pm8001_request_irq(pm8001_ha); + if (rc) +- goto err_out_shost; ++ goto err_out; + + count = pm8001_ha->max_q_num; + /* Queues are chosen based on the number of cores/msix availability */ +@@ -419,8 +419,6 @@ static int pm8001_alloc(struct pm8001_hba_info *pm8001_ha, + pm8001_tag_init(pm8001_ha); + return 0; + +-err_out_shost: +- scsi_remove_host(pm8001_ha->shost); + err_out_nodev: + for (i = 0; i < pm8001_ha->max_memcnt; i++) { + if (pm8001_ha->memoryMap.region[i].virt_ptr != NULL) { +diff --git a/drivers/scsi/qla2xxx/qla_dbg.c b/drivers/scsi/qla2xxx/qla_dbg.c +index 3a20bf8ce5ab9..00b4d033b07a9 100644 +--- a/drivers/scsi/qla2xxx/qla_dbg.c ++++ b/drivers/scsi/qla2xxx/qla_dbg.c +@@ -2477,6 +2477,9 @@ ql_dbg(uint level, scsi_qla_host_t *vha, uint id, const char *fmt, ...) + struct va_format vaf; + char pbuf[64]; + ++ if (!ql_mask_match(level) && !trace_ql_dbg_log_enabled()) ++ return; ++ + va_start(va, fmt); + + vaf.fmt = fmt; +diff --git a/drivers/scsi/scsi_debug.c b/drivers/scsi/scsi_debug.c +index 1a3f5adc68849..9188191433439 100644 +--- a/drivers/scsi/scsi_debug.c ++++ b/drivers/scsi/scsi_debug.c +@@ -4313,7 +4313,7 @@ static int resp_report_zones(struct scsi_cmnd *scp, + rep_max_zones = min((alloc_len - 64) >> ilog2(RZONES_DESC_HD), + max_zones); + +- arr = kcalloc(RZONES_DESC_HD, alloc_len, GFP_ATOMIC); ++ arr = kzalloc(alloc_len, GFP_ATOMIC); + if (!arr) { + mk_sense_buffer(scp, ILLEGAL_REQUEST, INSUFF_RES_ASC, + INSUFF_RES_ASCQ); +diff --git a/drivers/usb/core/config.c b/drivers/usb/core/config.c +index 562a730befdac..39f1eca60a714 100644 +--- a/drivers/usb/core/config.c ++++ b/drivers/usb/core/config.c +@@ -406,7 +406,7 @@ static int usb_parse_endpoint(struct device *ddev, int cfgno, + * the USB-2 spec requires such endpoints to have wMaxPacketSize = 0 + * (see the end of section 5.6.3), so don't warn about them. + */ +- maxp = usb_endpoint_maxp(&endpoint->desc); ++ maxp = le16_to_cpu(endpoint->desc.wMaxPacketSize); + if (maxp == 0 && !(usb_endpoint_xfer_isoc(d) && asnum == 0)) { + dev_warn(ddev, "config %d interface %d altsetting %d endpoint 0x%X has invalid wMaxPacketSize 0\n", + cfgno, inum, asnum, d->bEndpointAddress); +@@ -422,9 +422,9 @@ static int usb_parse_endpoint(struct device *ddev, int cfgno, + maxpacket_maxes = full_speed_maxpacket_maxes; + break; + case USB_SPEED_HIGH: +- /* Bits 12..11 are allowed only for HS periodic endpoints */ ++ /* Multiple-transactions bits are allowed only for HS periodic endpoints */ + if (usb_endpoint_xfer_int(d) || usb_endpoint_xfer_isoc(d)) { +- i = maxp & (BIT(12) | BIT(11)); ++ i = maxp & USB_EP_MAXP_MULT_MASK; + maxp &= ~i; + } + fallthrough; +diff --git a/drivers/usb/gadget/composite.c b/drivers/usb/gadget/composite.c +index 3ffa939678d77..426132988512d 100644 +--- a/drivers/usb/gadget/composite.c ++++ b/drivers/usb/gadget/composite.c +@@ -1648,6 +1648,18 @@ composite_setup(struct usb_gadget *gadget, const struct usb_ctrlrequest *ctrl) + struct usb_function *f = NULL; + u8 endp; + ++ if (w_length > USB_COMP_EP0_BUFSIZ) { ++ if (ctrl->bRequestType == USB_DIR_OUT) { ++ goto done; ++ } else { ++ /* Cast away the const, we are going to overwrite on purpose. */ ++ __le16 *temp = (__le16 *)&ctrl->wLength; ++ ++ *temp = cpu_to_le16(USB_COMP_EP0_BUFSIZ); ++ w_length = USB_COMP_EP0_BUFSIZ; ++ } ++ } ++ + /* partial re-init of the response message; the function or the + * gadget might need to intercept e.g. a control-OUT completion + * when we delegate to it. +@@ -2161,7 +2173,7 @@ int composite_dev_prepare(struct usb_composite_driver *composite, + if (!cdev->req) + return -ENOMEM; + +- cdev->req->buf = kmalloc(USB_COMP_EP0_BUFSIZ, GFP_KERNEL); ++ cdev->req->buf = kzalloc(USB_COMP_EP0_BUFSIZ, GFP_KERNEL); + if (!cdev->req->buf) + goto fail; + +diff --git a/drivers/usb/gadget/function/uvc.h b/drivers/usb/gadget/function/uvc.h +index 23ee25383c1f7..893aaa70f81a4 100644 +--- a/drivers/usb/gadget/function/uvc.h ++++ b/drivers/usb/gadget/function/uvc.h +@@ -117,6 +117,7 @@ struct uvc_device { + enum uvc_state state; + struct usb_function func; + struct uvc_video video; ++ bool func_connected; + + /* Descriptors */ + struct { +@@ -147,6 +148,7 @@ static inline struct uvc_device *to_uvc(struct usb_function *f) + struct uvc_file_handle { + struct v4l2_fh vfh; + struct uvc_video *device; ++ bool is_uvc_app_handle; + }; + + #define to_uvc_file_handle(handle) \ +diff --git a/drivers/usb/gadget/function/uvc_v4l2.c b/drivers/usb/gadget/function/uvc_v4l2.c +index 4ca89eab61590..197c26f7aec63 100644 +--- a/drivers/usb/gadget/function/uvc_v4l2.c ++++ b/drivers/usb/gadget/function/uvc_v4l2.c +@@ -227,17 +227,55 @@ static int + uvc_v4l2_subscribe_event(struct v4l2_fh *fh, + const struct v4l2_event_subscription *sub) + { ++ struct uvc_device *uvc = video_get_drvdata(fh->vdev); ++ struct uvc_file_handle *handle = to_uvc_file_handle(fh); ++ int ret; ++ + if (sub->type < UVC_EVENT_FIRST || sub->type > UVC_EVENT_LAST) + return -EINVAL; + +- return v4l2_event_subscribe(fh, sub, 2, NULL); ++ if (sub->type == UVC_EVENT_SETUP && uvc->func_connected) ++ return -EBUSY; ++ ++ ret = v4l2_event_subscribe(fh, sub, 2, NULL); ++ if (ret < 0) ++ return ret; ++ ++ if (sub->type == UVC_EVENT_SETUP) { ++ uvc->func_connected = true; ++ handle->is_uvc_app_handle = true; ++ uvc_function_connect(uvc); ++ } ++ ++ return 0; ++} ++ ++static void uvc_v4l2_disable(struct uvc_device *uvc) ++{ ++ uvc->func_connected = false; ++ uvc_function_disconnect(uvc); ++ uvcg_video_enable(&uvc->video, 0); ++ uvcg_free_buffers(&uvc->video.queue); + } + + static int + uvc_v4l2_unsubscribe_event(struct v4l2_fh *fh, + const struct v4l2_event_subscription *sub) + { +- return v4l2_event_unsubscribe(fh, sub); ++ struct uvc_device *uvc = video_get_drvdata(fh->vdev); ++ struct uvc_file_handle *handle = to_uvc_file_handle(fh); ++ int ret; ++ ++ ret = v4l2_event_unsubscribe(fh, sub); ++ if (ret < 0) ++ return ret; ++ ++ if (sub->type == UVC_EVENT_SETUP && handle->is_uvc_app_handle) { ++ uvc_v4l2_disable(uvc); ++ handle->is_uvc_app_handle = false; ++ } ++ ++ return 0; + } + + static long +@@ -292,7 +330,6 @@ uvc_v4l2_open(struct file *file) + handle->device = &uvc->video; + file->private_data = &handle->vfh; + +- uvc_function_connect(uvc); + return 0; + } + +@@ -304,11 +341,9 @@ uvc_v4l2_release(struct file *file) + struct uvc_file_handle *handle = to_uvc_file_handle(file->private_data); + struct uvc_video *video = handle->device; + +- uvc_function_disconnect(uvc); +- + mutex_lock(&video->mutex); +- uvcg_video_enable(video, 0); +- uvcg_free_buffers(&video->queue); ++ if (handle->is_uvc_app_handle) ++ uvc_v4l2_disable(uvc); + mutex_unlock(&video->mutex); + + file->private_data = NULL; +diff --git a/drivers/usb/gadget/legacy/dbgp.c b/drivers/usb/gadget/legacy/dbgp.c +index e1d566c9918ae..355bc7dab9d5f 100644 +--- a/drivers/usb/gadget/legacy/dbgp.c ++++ b/drivers/usb/gadget/legacy/dbgp.c +@@ -137,7 +137,7 @@ static int dbgp_enable_ep_req(struct usb_ep *ep) + goto fail_1; + } + +- req->buf = kmalloc(DBGP_REQ_LEN, GFP_KERNEL); ++ req->buf = kzalloc(DBGP_REQ_LEN, GFP_KERNEL); + if (!req->buf) { + err = -ENOMEM; + stp = 2; +@@ -345,6 +345,19 @@ static int dbgp_setup(struct usb_gadget *gadget, + void *data = NULL; + u16 len = 0; + ++ if (length > DBGP_REQ_LEN) { ++ if (ctrl->bRequestType == USB_DIR_OUT) { ++ return err; ++ } else { ++ /* Cast away the const, we are going to overwrite on purpose. */ ++ __le16 *temp = (__le16 *)&ctrl->wLength; ++ ++ *temp = cpu_to_le16(DBGP_REQ_LEN); ++ length = DBGP_REQ_LEN; ++ } ++ } ++ ++ + if (request == USB_REQ_GET_DESCRIPTOR) { + switch (value>>8) { + case USB_DT_DEVICE: +diff --git a/drivers/usb/gadget/legacy/inode.c b/drivers/usb/gadget/legacy/inode.c +index 71e7d10dd76b9..04b9c4f5f129d 100644 +--- a/drivers/usb/gadget/legacy/inode.c ++++ b/drivers/usb/gadget/legacy/inode.c +@@ -110,6 +110,8 @@ enum ep0_state { + /* enough for the whole queue: most events invalidate others */ + #define N_EVENT 5 + ++#define RBUF_SIZE 256 ++ + struct dev_data { + spinlock_t lock; + refcount_t count; +@@ -144,7 +146,7 @@ struct dev_data { + struct dentry *dentry; + + /* except this scratch i/o buffer for ep0 */ +- u8 rbuf [256]; ++ u8 rbuf[RBUF_SIZE]; + }; + + static inline void get_dev (struct dev_data *data) +@@ -1333,6 +1335,18 @@ gadgetfs_setup (struct usb_gadget *gadget, const struct usb_ctrlrequest *ctrl) + u16 w_value = le16_to_cpu(ctrl->wValue); + u16 w_length = le16_to_cpu(ctrl->wLength); + ++ if (w_length > RBUF_SIZE) { ++ if (ctrl->bRequestType == USB_DIR_OUT) { ++ return value; ++ } else { ++ /* Cast away the const, we are going to overwrite on purpose. */ ++ __le16 *temp = (__le16 *)&ctrl->wLength; ++ ++ *temp = cpu_to_le16(RBUF_SIZE); ++ w_length = RBUF_SIZE; ++ } ++ } ++ + spin_lock (&dev->lock); + dev->setup_abort = 0; + if (dev->state == STATE_DEV_UNCONNECTED) { +diff --git a/drivers/usb/host/xhci-hub.c b/drivers/usb/host/xhci-hub.c +index 41d5a46c1dc1a..71b018e9a5735 100644 +--- a/drivers/usb/host/xhci-hub.c ++++ b/drivers/usb/host/xhci-hub.c +@@ -631,6 +631,7 @@ static int xhci_enter_test_mode(struct xhci_hcd *xhci, + continue; + + retval = xhci_disable_slot(xhci, i); ++ xhci_free_virt_device(xhci, i); + if (retval) + xhci_err(xhci, "Failed to disable slot %d, %d. Enter test mode anyway\n", + i, retval); +diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c +index 667a37f509828..76389c0dda8bc 100644 +--- a/drivers/usb/host/xhci-ring.c ++++ b/drivers/usb/host/xhci-ring.c +@@ -1298,7 +1298,6 @@ static void xhci_handle_cmd_disable_slot(struct xhci_hcd *xhci, int slot_id) + if (xhci->quirks & XHCI_EP_LIMIT_QUIRK) + /* Delete default control endpoint resources */ + xhci_free_device_endpoint_resources(xhci, virt_dev, true); +- xhci_free_virt_device(xhci, slot_id); + } + + static void xhci_handle_cmd_config_ep(struct xhci_hcd *xhci, int slot_id, +diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c +index bf42ba3e4415a..325eb1609f8c5 100644 +--- a/drivers/usb/host/xhci.c ++++ b/drivers/usb/host/xhci.c +@@ -3893,7 +3893,6 @@ static void xhci_free_dev(struct usb_hcd *hcd, struct usb_device *udev) + struct xhci_slot_ctx *slot_ctx; + int i, ret; + +-#ifndef CONFIG_USB_DEFAULT_PERSIST + /* + * We called pm_runtime_get_noresume when the device was attached. + * Decrement the counter here to allow controller to runtime suspend +@@ -3901,7 +3900,6 @@ static void xhci_free_dev(struct usb_hcd *hcd, struct usb_device *udev) + */ + if (xhci->quirks & XHCI_RESET_ON_RESUME) + pm_runtime_put_noidle(hcd->self.controller); +-#endif + + ret = xhci_check_args(hcd, udev, NULL, 0, true, __func__); + /* If the host is halted due to driver unload, we still need to free the +@@ -3920,9 +3918,8 @@ static void xhci_free_dev(struct usb_hcd *hcd, struct usb_device *udev) + del_timer_sync(&virt_dev->eps[i].stop_cmd_timer); + } + virt_dev->udev = NULL; +- ret = xhci_disable_slot(xhci, udev->slot_id); +- if (ret) +- xhci_free_virt_device(xhci, udev->slot_id); ++ xhci_disable_slot(xhci, udev->slot_id); ++ xhci_free_virt_device(xhci, udev->slot_id); + } + + int xhci_disable_slot(struct xhci_hcd *xhci, u32 slot_id) +@@ -3932,7 +3929,7 @@ int xhci_disable_slot(struct xhci_hcd *xhci, u32 slot_id) + u32 state; + int ret = 0; + +- command = xhci_alloc_command(xhci, false, GFP_KERNEL); ++ command = xhci_alloc_command(xhci, true, GFP_KERNEL); + if (!command) + return -ENOMEM; + +@@ -3957,6 +3954,15 @@ int xhci_disable_slot(struct xhci_hcd *xhci, u32 slot_id) + } + xhci_ring_cmd_db(xhci); + spin_unlock_irqrestore(&xhci->lock, flags); ++ ++ wait_for_completion(command->completion); ++ ++ if (command->status != COMP_SUCCESS) ++ xhci_warn(xhci, "Unsuccessful disable slot %u command, status %d\n", ++ slot_id, command->status); ++ ++ xhci_free_command(xhci, command); ++ + return ret; + } + +@@ -4053,23 +4059,20 @@ int xhci_alloc_dev(struct usb_hcd *hcd, struct usb_device *udev) + + xhci_debugfs_create_slot(xhci, slot_id); + +-#ifndef CONFIG_USB_DEFAULT_PERSIST + /* + * If resetting upon resume, we can't put the controller into runtime + * suspend if there is a device attached. + */ + if (xhci->quirks & XHCI_RESET_ON_RESUME) + pm_runtime_get_noresume(hcd->self.controller); +-#endif + + /* Is this a LS or FS device under a HS hub? */ + /* Hub or peripherial? */ + return 1; + + disable_slot: +- ret = xhci_disable_slot(xhci, udev->slot_id); +- if (ret) +- xhci_free_virt_device(xhci, udev->slot_id); ++ xhci_disable_slot(xhci, udev->slot_id); ++ xhci_free_virt_device(xhci, udev->slot_id); + + return 0; + } +@@ -4199,6 +4202,7 @@ static int xhci_setup_device(struct usb_hcd *hcd, struct usb_device *udev, + + mutex_unlock(&xhci->mutex); + ret = xhci_disable_slot(xhci, udev->slot_id); ++ xhci_free_virt_device(xhci, udev->slot_id); + if (!ret) + xhci_alloc_dev(hcd, udev); + kfree(command->completion); +diff --git a/fs/aio.c b/fs/aio.c +index 6a21d8919409c..2a9dfa58ec3ab 100644 +--- a/fs/aio.c ++++ b/fs/aio.c +@@ -182,8 +182,9 @@ struct poll_iocb { + struct file *file; + struct wait_queue_head *head; + __poll_t events; +- bool done; + bool cancelled; ++ bool work_scheduled; ++ bool work_need_resched; + struct wait_queue_entry wait; + struct work_struct work; + }; +@@ -1621,6 +1622,51 @@ static void aio_poll_put_work(struct work_struct *work) + iocb_put(iocb); + } + ++/* ++ * Safely lock the waitqueue which the request is on, synchronizing with the ++ * case where the ->poll() provider decides to free its waitqueue early. ++ * ++ * Returns true on success, meaning that req->head->lock was locked, req->wait ++ * is on req->head, and an RCU read lock was taken. Returns false if the ++ * request was already removed from its waitqueue (which might no longer exist). ++ */ ++static bool poll_iocb_lock_wq(struct poll_iocb *req) ++{ ++ wait_queue_head_t *head; ++ ++ /* ++ * While we hold the waitqueue lock and the waitqueue is nonempty, ++ * wake_up_pollfree() will wait for us. However, taking the waitqueue ++ * lock in the first place can race with the waitqueue being freed. ++ * ++ * We solve this as eventpoll does: by taking advantage of the fact that ++ * all users of wake_up_pollfree() will RCU-delay the actual free. If ++ * we enter rcu_read_lock() and see that the pointer to the queue is ++ * non-NULL, we can then lock it without the memory being freed out from ++ * under us, then check whether the request is still on the queue. ++ * ++ * Keep holding rcu_read_lock() as long as we hold the queue lock, in ++ * case the caller deletes the entry from the queue, leaving it empty. ++ * In that case, only RCU prevents the queue memory from being freed. ++ */ ++ rcu_read_lock(); ++ head = smp_load_acquire(&req->head); ++ if (head) { ++ spin_lock(&head->lock); ++ if (!list_empty(&req->wait.entry)) ++ return true; ++ spin_unlock(&head->lock); ++ } ++ rcu_read_unlock(); ++ return false; ++} ++ ++static void poll_iocb_unlock_wq(struct poll_iocb *req) ++{ ++ spin_unlock(&req->head->lock); ++ rcu_read_unlock(); ++} ++ + static void aio_poll_complete_work(struct work_struct *work) + { + struct poll_iocb *req = container_of(work, struct poll_iocb, work); +@@ -1640,14 +1686,27 @@ static void aio_poll_complete_work(struct work_struct *work) + * avoid further branches in the fast path. + */ + spin_lock_irq(&ctx->ctx_lock); +- if (!mask && !READ_ONCE(req->cancelled)) { +- add_wait_queue(req->head, &req->wait); +- spin_unlock_irq(&ctx->ctx_lock); +- return; +- } ++ if (poll_iocb_lock_wq(req)) { ++ if (!mask && !READ_ONCE(req->cancelled)) { ++ /* ++ * The request isn't actually ready to be completed yet. ++ * Reschedule completion if another wakeup came in. ++ */ ++ if (req->work_need_resched) { ++ schedule_work(&req->work); ++ req->work_need_resched = false; ++ } else { ++ req->work_scheduled = false; ++ } ++ poll_iocb_unlock_wq(req); ++ spin_unlock_irq(&ctx->ctx_lock); ++ return; ++ } ++ list_del_init(&req->wait.entry); ++ poll_iocb_unlock_wq(req); ++ } /* else, POLLFREE has freed the waitqueue, so we must complete */ + list_del_init(&iocb->ki_list); + iocb->ki_res.res = mangle_poll(mask); +- req->done = true; + spin_unlock_irq(&ctx->ctx_lock); + + iocb_put(iocb); +@@ -1659,13 +1718,14 @@ static int aio_poll_cancel(struct kiocb *iocb) + struct aio_kiocb *aiocb = container_of(iocb, struct aio_kiocb, rw); + struct poll_iocb *req = &aiocb->poll; + +- spin_lock(&req->head->lock); +- WRITE_ONCE(req->cancelled, true); +- if (!list_empty(&req->wait.entry)) { +- list_del_init(&req->wait.entry); +- schedule_work(&aiocb->poll.work); +- } +- spin_unlock(&req->head->lock); ++ if (poll_iocb_lock_wq(req)) { ++ WRITE_ONCE(req->cancelled, true); ++ if (!req->work_scheduled) { ++ schedule_work(&aiocb->poll.work); ++ req->work_scheduled = true; ++ } ++ poll_iocb_unlock_wq(req); ++ } /* else, the request was force-cancelled by POLLFREE already */ + + return 0; + } +@@ -1682,20 +1742,26 @@ static int aio_poll_wake(struct wait_queue_entry *wait, unsigned mode, int sync, + if (mask && !(mask & req->events)) + return 0; + +- list_del_init(&req->wait.entry); +- +- if (mask && spin_trylock_irqsave(&iocb->ki_ctx->ctx_lock, flags)) { ++ /* ++ * Complete the request inline if possible. This requires that three ++ * conditions be met: ++ * 1. An event mask must have been passed. If a plain wakeup was done ++ * instead, then mask == 0 and we have to call vfs_poll() to get ++ * the events, so inline completion isn't possible. ++ * 2. The completion work must not have already been scheduled. ++ * 3. ctx_lock must not be busy. We have to use trylock because we ++ * already hold the waitqueue lock, so this inverts the normal ++ * locking order. Use irqsave/irqrestore because not all ++ * filesystems (e.g. fuse) call this function with IRQs disabled, ++ * yet IRQs have to be disabled before ctx_lock is obtained. ++ */ ++ if (mask && !req->work_scheduled && ++ spin_trylock_irqsave(&iocb->ki_ctx->ctx_lock, flags)) { + struct kioctx *ctx = iocb->ki_ctx; + +- /* +- * Try to complete the iocb inline if we can. Use +- * irqsave/irqrestore because not all filesystems (e.g. fuse) +- * call this function with IRQs disabled and because IRQs +- * have to be disabled before ctx_lock is obtained. +- */ ++ list_del_init(&req->wait.entry); + list_del(&iocb->ki_list); + iocb->ki_res.res = mangle_poll(mask); +- req->done = true; + if (iocb->ki_eventfd && eventfd_signal_count()) { + iocb = NULL; + INIT_WORK(&req->work, aio_poll_put_work); +@@ -1705,7 +1771,43 @@ static int aio_poll_wake(struct wait_queue_entry *wait, unsigned mode, int sync, + if (iocb) + iocb_put(iocb); + } else { +- schedule_work(&req->work); ++ /* ++ * Schedule the completion work if needed. If it was already ++ * scheduled, record that another wakeup came in. ++ * ++ * Don't remove the request from the waitqueue here, as it might ++ * not actually be complete yet (we won't know until vfs_poll() ++ * is called), and we must not miss any wakeups. POLLFREE is an ++ * exception to this; see below. ++ */ ++ if (req->work_scheduled) { ++ req->work_need_resched = true; ++ } else { ++ schedule_work(&req->work); ++ req->work_scheduled = true; ++ } ++ ++ /* ++ * If the waitqueue is being freed early but we can't complete ++ * the request inline, we have to tear down the request as best ++ * we can. That means immediately removing the request from its ++ * waitqueue and preventing all further accesses to the ++ * waitqueue via the request. We also need to schedule the ++ * completion work (done above). Also mark the request as ++ * cancelled, to potentially skip an unneeded call to ->poll(). ++ */ ++ if (mask & POLLFREE) { ++ WRITE_ONCE(req->cancelled, true); ++ list_del_init(&req->wait.entry); ++ ++ /* ++ * Careful: this *must* be the last step, since as soon ++ * as req->head is NULL'ed out, the request can be ++ * completed and freed, since aio_poll_complete_work() ++ * will no longer need to take the waitqueue lock. ++ */ ++ smp_store_release(&req->head, NULL); ++ } + } + return 1; + } +@@ -1713,6 +1815,7 @@ static int aio_poll_wake(struct wait_queue_entry *wait, unsigned mode, int sync, + struct aio_poll_table { + struct poll_table_struct pt; + struct aio_kiocb *iocb; ++ bool queued; + int error; + }; + +@@ -1723,11 +1826,12 @@ aio_poll_queue_proc(struct file *file, struct wait_queue_head *head, + struct aio_poll_table *pt = container_of(p, struct aio_poll_table, pt); + + /* multiple wait queues per file are not supported */ +- if (unlikely(pt->iocb->poll.head)) { ++ if (unlikely(pt->queued)) { + pt->error = -EINVAL; + return; + } + ++ pt->queued = true; + pt->error = 0; + pt->iocb->poll.head = head; + add_wait_queue(head, &pt->iocb->poll.wait); +@@ -1752,12 +1856,14 @@ static int aio_poll(struct aio_kiocb *aiocb, const struct iocb *iocb) + req->events = demangle_poll(iocb->aio_buf) | EPOLLERR | EPOLLHUP; + + req->head = NULL; +- req->done = false; + req->cancelled = false; ++ req->work_scheduled = false; ++ req->work_need_resched = false; + + apt.pt._qproc = aio_poll_queue_proc; + apt.pt._key = req->events; + apt.iocb = aiocb; ++ apt.queued = false; + apt.error = -EINVAL; /* same as no support for IOCB_CMD_POLL */ + + /* initialized the list so that we can do list_empty checks */ +@@ -1766,23 +1872,35 @@ static int aio_poll(struct aio_kiocb *aiocb, const struct iocb *iocb) + + mask = vfs_poll(req->file, &apt.pt) & req->events; + spin_lock_irq(&ctx->ctx_lock); +- if (likely(req->head)) { +- spin_lock(&req->head->lock); +- if (unlikely(list_empty(&req->wait.entry))) { +- if (apt.error) ++ if (likely(apt.queued)) { ++ bool on_queue = poll_iocb_lock_wq(req); ++ ++ if (!on_queue || req->work_scheduled) { ++ /* ++ * aio_poll_wake() already either scheduled the async ++ * completion work, or completed the request inline. ++ */ ++ if (apt.error) /* unsupported case: multiple queues */ + cancel = true; + apt.error = 0; + mask = 0; + } + if (mask || apt.error) { ++ /* Steal to complete synchronously. */ + list_del_init(&req->wait.entry); + } else if (cancel) { ++ /* Cancel if possible (may be too late though). */ + WRITE_ONCE(req->cancelled, true); +- } else if (!req->done) { /* actually waiting for an event */ ++ } else if (on_queue) { ++ /* ++ * Actually waiting for an event, so add the request to ++ * active_reqs so that it can be cancelled if needed. ++ */ + list_add_tail(&aiocb->ki_list, &ctx->active_reqs); + aiocb->ki_cancel = aio_poll_cancel; + } +- spin_unlock(&req->head->lock); ++ if (on_queue) ++ poll_iocb_unlock_wq(req); + } + if (mask) { /* no async, we'd stolen it */ + aiocb->ki_res.res = mangle_poll(mask); +diff --git a/fs/btrfs/extent_io.c b/fs/btrfs/extent_io.c +index 81e98a457130f..5fc65a780f83b 100644 +--- a/fs/btrfs/extent_io.c ++++ b/fs/btrfs/extent_io.c +@@ -3769,6 +3769,12 @@ static void set_btree_ioerr(struct page *page) + if (test_and_set_bit(EXTENT_BUFFER_WRITE_ERR, &eb->bflags)) + return; + ++ /* ++ * A read may stumble upon this buffer later, make sure that it gets an ++ * error and knows there was an error. ++ */ ++ clear_bit(EXTENT_BUFFER_UPTODATE, &eb->bflags); ++ + /* + * If we error out, we should add back the dirty_metadata_bytes + * to make it consistent. +diff --git a/fs/btrfs/root-tree.c b/fs/btrfs/root-tree.c +index 702dc5441f039..db37a37996497 100644 +--- a/fs/btrfs/root-tree.c ++++ b/fs/btrfs/root-tree.c +@@ -336,7 +336,8 @@ int btrfs_del_root_ref(struct btrfs_trans_handle *trans, u64 root_id, + key.offset = ref_id; + again: + ret = btrfs_search_slot(trans, tree_root, &key, path, -1, 1); +- BUG_ON(ret < 0); ++ if (ret < 0) ++ goto out; + if (ret == 0) { + leaf = path->nodes[0]; + ref = btrfs_item_ptr(leaf, path->slots[0], +diff --git a/fs/nfsd/nfs4recover.c b/fs/nfsd/nfs4recover.c +index 186fa2c2c6ba6..f9b730c43192d 100644 +--- a/fs/nfsd/nfs4recover.c ++++ b/fs/nfsd/nfs4recover.c +@@ -2156,6 +2156,7 @@ static struct notifier_block nfsd4_cld_block = { + int + register_cld_notifier(void) + { ++ WARN_ON(!nfsd_net_id); + return rpc_pipefs_notifier_register(&nfsd4_cld_block); + } + +diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c +index 1cdf7e0a5c22d..210147960c52e 100644 +--- a/fs/nfsd/nfs4state.c ++++ b/fs/nfsd/nfs4state.c +@@ -1089,6 +1089,11 @@ hash_delegation_locked(struct nfs4_delegation *dp, struct nfs4_file *fp) + return 0; + } + ++static bool delegation_hashed(struct nfs4_delegation *dp) ++{ ++ return !(list_empty(&dp->dl_perfile)); ++} ++ + static bool + unhash_delegation_locked(struct nfs4_delegation *dp) + { +@@ -1096,7 +1101,7 @@ unhash_delegation_locked(struct nfs4_delegation *dp) + + lockdep_assert_held(&state_lock); + +- if (list_empty(&dp->dl_perfile)) ++ if (!delegation_hashed(dp)) + return false; + + dp->dl_stid.sc_type = NFS4_CLOSED_DELEG_STID; +@@ -4512,7 +4517,7 @@ static void nfsd4_cb_recall_prepare(struct nfsd4_callback *cb) + * queued for a lease break. Don't queue it again. + */ + spin_lock(&state_lock); +- if (dp->dl_time == 0) { ++ if (delegation_hashed(dp) && dp->dl_time == 0) { + dp->dl_time = ktime_get_boottime_seconds(); + list_add_tail(&dp->dl_recall_lru, &nn->del_recall_lru); + } +diff --git a/fs/nfsd/nfsctl.c b/fs/nfsd/nfsctl.c +index 21c4ffda5f943..a8f954bbde4f5 100644 +--- a/fs/nfsd/nfsctl.c ++++ b/fs/nfsd/nfsctl.c +@@ -1525,12 +1525,9 @@ static int __init init_nfsd(void) + int retval; + printk(KERN_INFO "Installing knfsd (copyright (C) 1996 okir@monad.swb.de).\n"); + +- retval = register_cld_notifier(); +- if (retval) +- return retval; + retval = nfsd4_init_slabs(); + if (retval) +- goto out_unregister_notifier; ++ return retval; + retval = nfsd4_init_pnfs(); + if (retval) + goto out_free_slabs; +@@ -1547,9 +1544,14 @@ static int __init init_nfsd(void) + goto out_free_exports; + retval = register_pernet_subsys(&nfsd_net_ops); + if (retval < 0) ++ goto out_free_filesystem; ++ retval = register_cld_notifier(); ++ if (retval) + goto out_free_all; + return 0; + out_free_all: ++ unregister_pernet_subsys(&nfsd_net_ops); ++out_free_filesystem: + unregister_filesystem(&nfsd_fs_type); + out_free_exports: + remove_proc_entry("fs/nfs/exports", NULL); +@@ -1562,13 +1564,12 @@ out_free_stat: + nfsd4_exit_pnfs(); + out_free_slabs: + nfsd4_free_slabs(); +-out_unregister_notifier: +- unregister_cld_notifier(); + return retval; + } + + static void __exit exit_nfsd(void) + { ++ unregister_cld_notifier(); + unregister_pernet_subsys(&nfsd_net_ops); + nfsd_drc_slab_free(); + remove_proc_entry("fs/nfs/exports", NULL); +@@ -1578,7 +1579,6 @@ static void __exit exit_nfsd(void) + nfsd4_free_slabs(); + nfsd4_exit_pnfs(); + unregister_filesystem(&nfsd_fs_type); +- unregister_cld_notifier(); + } + + MODULE_AUTHOR("Olaf Kirch <okir@monad.swb.de>"); +diff --git a/fs/signalfd.c b/fs/signalfd.c +index 456046e158737..b94fb5f81797a 100644 +--- a/fs/signalfd.c ++++ b/fs/signalfd.c +@@ -35,17 +35,7 @@ + + void signalfd_cleanup(struct sighand_struct *sighand) + { +- wait_queue_head_t *wqh = &sighand->signalfd_wqh; +- /* +- * The lockless check can race with remove_wait_queue() in progress, +- * but in this case its caller should run under rcu_read_lock() and +- * sighand_cachep is SLAB_TYPESAFE_BY_RCU, we can safely return. +- */ +- if (likely(!waitqueue_active(wqh))) +- return; +- +- /* wait_queue_entry_t->func(POLLFREE) should do remove_wait_queue() */ +- wake_up_poll(wqh, EPOLLHUP | POLLFREE); ++ wake_up_pollfree(&sighand->signalfd_wqh); + } + + struct signalfd_ctx { +diff --git a/fs/tracefs/inode.c b/fs/tracefs/inode.c +index bf58ae6f984fe..ade05887070dd 100644 +--- a/fs/tracefs/inode.c ++++ b/fs/tracefs/inode.c +@@ -159,6 +159,77 @@ struct tracefs_fs_info { + struct tracefs_mount_opts mount_opts; + }; + ++static void change_gid(struct dentry *dentry, kgid_t gid) ++{ ++ if (!dentry->d_inode) ++ return; ++ dentry->d_inode->i_gid = gid; ++} ++ ++/* ++ * Taken from d_walk, but without he need for handling renames. ++ * Nothing can be renamed while walking the list, as tracefs ++ * does not support renames. This is only called when mounting ++ * or remounting the file system, to set all the files to ++ * the given gid. ++ */ ++static void set_gid(struct dentry *parent, kgid_t gid) ++{ ++ struct dentry *this_parent; ++ struct list_head *next; ++ ++ this_parent = parent; ++ spin_lock(&this_parent->d_lock); ++ ++ change_gid(this_parent, gid); ++repeat: ++ next = this_parent->d_subdirs.next; ++resume: ++ while (next != &this_parent->d_subdirs) { ++ struct list_head *tmp = next; ++ struct dentry *dentry = list_entry(tmp, struct dentry, d_child); ++ next = tmp->next; ++ ++ spin_lock_nested(&dentry->d_lock, DENTRY_D_LOCK_NESTED); ++ ++ change_gid(dentry, gid); ++ ++ if (!list_empty(&dentry->d_subdirs)) { ++ spin_unlock(&this_parent->d_lock); ++ spin_release(&dentry->d_lock.dep_map, _RET_IP_); ++ this_parent = dentry; ++ spin_acquire(&this_parent->d_lock.dep_map, 0, 1, _RET_IP_); ++ goto repeat; ++ } ++ spin_unlock(&dentry->d_lock); ++ } ++ /* ++ * All done at this level ... ascend and resume the search. ++ */ ++ rcu_read_lock(); ++ascend: ++ if (this_parent != parent) { ++ struct dentry *child = this_parent; ++ this_parent = child->d_parent; ++ ++ spin_unlock(&child->d_lock); ++ spin_lock(&this_parent->d_lock); ++ ++ /* go into the first sibling still alive */ ++ do { ++ next = child->d_child.next; ++ if (next == &this_parent->d_subdirs) ++ goto ascend; ++ child = list_entry(next, struct dentry, d_child); ++ } while (unlikely(child->d_flags & DCACHE_DENTRY_KILLED)); ++ rcu_read_unlock(); ++ goto resume; ++ } ++ rcu_read_unlock(); ++ spin_unlock(&this_parent->d_lock); ++ return; ++} ++ + static int tracefs_parse_options(char *data, struct tracefs_mount_opts *opts) + { + substring_t args[MAX_OPT_ARGS]; +@@ -191,6 +262,7 @@ static int tracefs_parse_options(char *data, struct tracefs_mount_opts *opts) + if (!gid_valid(gid)) + return -EINVAL; + opts->gid = gid; ++ set_gid(tracefs_mount->mnt_root, gid); + break; + case Opt_mode: + if (match_octal(&args[0], &option)) +@@ -412,6 +484,8 @@ struct dentry *tracefs_create_file(const char *name, umode_t mode, + inode->i_mode = mode; + inode->i_fop = fops ? fops : &tracefs_file_operations; + inode->i_private = data; ++ inode->i_uid = d_inode(dentry->d_parent)->i_uid; ++ inode->i_gid = d_inode(dentry->d_parent)->i_gid; + d_instantiate(dentry, inode); + fsnotify_create(dentry->d_parent->d_inode, dentry); + return end_creating(dentry); +@@ -434,6 +508,8 @@ static struct dentry *__create_dir(const char *name, struct dentry *parent, + inode->i_mode = S_IFDIR | S_IRWXU | S_IRUSR| S_IRGRP | S_IXUSR | S_IXGRP; + inode->i_op = ops; + inode->i_fop = &simple_dir_operations; ++ inode->i_uid = d_inode(dentry->d_parent)->i_uid; ++ inode->i_gid = d_inode(dentry->d_parent)->i_gid; + + /* directory inodes start off with i_nlink == 2 (for "." entry) */ + inc_nlink(inode); +diff --git a/include/linux/bpf.h b/include/linux/bpf.h +index 474a0d852614f..e6ddf5a3beaf8 100644 +--- a/include/linux/bpf.h ++++ b/include/linux/bpf.h +@@ -666,6 +666,7 @@ int bpf_trampoline_unlink_prog(struct bpf_prog *prog, struct bpf_trampoline *tr) + struct bpf_trampoline *bpf_trampoline_get(u64 key, + struct bpf_attach_target_info *tgt_info); + void bpf_trampoline_put(struct bpf_trampoline *tr); ++int arch_prepare_bpf_dispatcher(void *image, s64 *funcs, int num_funcs); + #define BPF_DISPATCHER_INIT(_name) { \ + .mutex = __MUTEX_INITIALIZER(_name.mutex), \ + .func = &_name##_func, \ +diff --git a/include/linux/hid.h b/include/linux/hid.h +index 6ed2a97eb55f1..fc56d53cc68bf 100644 +--- a/include/linux/hid.h ++++ b/include/linux/hid.h +@@ -833,6 +833,11 @@ static inline bool hid_is_using_ll_driver(struct hid_device *hdev, + return hdev->ll_driver == driver; + } + ++static inline bool hid_is_usb(struct hid_device *hdev) ++{ ++ return hid_is_using_ll_driver(hdev, &usb_hid_driver); ++} ++ + #define PM_HINT_FULLON 1<<5 + #define PM_HINT_NORMAL 1<<1 + +diff --git a/include/linux/pm_runtime.h b/include/linux/pm_runtime.h +index 6c08a085367bf..161acd4ede448 100644 +--- a/include/linux/pm_runtime.h ++++ b/include/linux/pm_runtime.h +@@ -127,7 +127,7 @@ static inline bool pm_runtime_suspended(struct device *dev) + * pm_runtime_active - Check whether or not a device is runtime-active. + * @dev: Target device. + * +- * Return %true if runtime PM is enabled for @dev and its runtime PM status is ++ * Return %true if runtime PM is disabled for @dev or its runtime PM status is + * %RPM_ACTIVE, or %false otherwise. + * + * Note that the return value of this function can only be trusted if it is +diff --git a/include/linux/wait.h b/include/linux/wait.h +index f8b0704968a1e..9b8b0833100a0 100644 +--- a/include/linux/wait.h ++++ b/include/linux/wait.h +@@ -207,6 +207,7 @@ void __wake_up_sync_key(struct wait_queue_head *wq_head, unsigned int mode, void + void __wake_up_locked_sync_key(struct wait_queue_head *wq_head, unsigned int mode, void *key); + void __wake_up_locked(struct wait_queue_head *wq_head, unsigned int mode, int nr); + void __wake_up_sync(struct wait_queue_head *wq_head, unsigned int mode); ++void __wake_up_pollfree(struct wait_queue_head *wq_head); + + #define wake_up(x) __wake_up(x, TASK_NORMAL, 1, NULL) + #define wake_up_nr(x, nr) __wake_up(x, TASK_NORMAL, nr, NULL) +@@ -235,6 +236,31 @@ void __wake_up_sync(struct wait_queue_head *wq_head, unsigned int mode); + #define wake_up_interruptible_sync_poll_locked(x, m) \ + __wake_up_locked_sync_key((x), TASK_INTERRUPTIBLE, poll_to_key(m)) + ++/** ++ * wake_up_pollfree - signal that a polled waitqueue is going away ++ * @wq_head: the wait queue head ++ * ++ * In the very rare cases where a ->poll() implementation uses a waitqueue whose ++ * lifetime is tied to a task rather than to the 'struct file' being polled, ++ * this function must be called before the waitqueue is freed so that ++ * non-blocking polls (e.g. epoll) are notified that the queue is going away. ++ * ++ * The caller must also RCU-delay the freeing of the wait_queue_head, e.g. via ++ * an explicit synchronize_rcu() or call_rcu(), or via SLAB_TYPESAFE_BY_RCU. ++ */ ++static inline void wake_up_pollfree(struct wait_queue_head *wq_head) ++{ ++ /* ++ * For performance reasons, we don't always take the queue lock here. ++ * Therefore, we might race with someone removing the last entry from ++ * the queue, and proceed while they still hold the queue lock. ++ * However, rcu_read_lock() is required to be held in such cases, so we ++ * can safely proceed with an RCU-delayed free. ++ */ ++ if (waitqueue_active(wq_head)) ++ __wake_up_pollfree(wq_head); ++} ++ + #define ___wait_cond_timeout(condition) \ + ({ \ + bool __cond = (condition); \ +diff --git a/include/net/bond_alb.h b/include/net/bond_alb.h +index f6af76c87a6c3..191c36afa1f4a 100644 +--- a/include/net/bond_alb.h ++++ b/include/net/bond_alb.h +@@ -126,7 +126,7 @@ struct tlb_slave_info { + struct alb_bond_info { + struct tlb_client_info *tx_hashtbl; /* Dynamically allocated */ + u32 unbalanced_load; +- int tx_rebalance_counter; ++ atomic_t tx_rebalance_counter; + int lp_counter; + /* -------- rlb parameters -------- */ + int rlb_enabled; +diff --git a/include/net/netfilter/nf_conntrack.h b/include/net/netfilter/nf_conntrack.h +index 439379ca9ffac..5cf23a23f3c44 100644 +--- a/include/net/netfilter/nf_conntrack.h ++++ b/include/net/netfilter/nf_conntrack.h +@@ -262,14 +262,14 @@ static inline bool nf_is_loopback_packet(const struct sk_buff *skb) + /* jiffies until ct expires, 0 if already expired */ + static inline unsigned long nf_ct_expires(const struct nf_conn *ct) + { +- s32 timeout = ct->timeout - nfct_time_stamp; ++ s32 timeout = READ_ONCE(ct->timeout) - nfct_time_stamp; + + return timeout > 0 ? timeout : 0; + } + + static inline bool nf_ct_is_expired(const struct nf_conn *ct) + { +- return (__s32)(ct->timeout - nfct_time_stamp) <= 0; ++ return (__s32)(READ_ONCE(ct->timeout) - nfct_time_stamp) <= 0; + } + + /* use after obtaining a reference count */ +@@ -288,7 +288,7 @@ static inline bool nf_ct_should_gc(const struct nf_conn *ct) + static inline void nf_ct_offload_timeout(struct nf_conn *ct) + { + if (nf_ct_expires(ct) < NF_CT_DAY / 2) +- ct->timeout = nfct_time_stamp + NF_CT_DAY; ++ WRITE_ONCE(ct->timeout, nfct_time_stamp + NF_CT_DAY); + } + + struct kernel_param; +diff --git a/include/uapi/asm-generic/poll.h b/include/uapi/asm-generic/poll.h +index 41b509f410bf9..f9c520ce4bf4e 100644 +--- a/include/uapi/asm-generic/poll.h ++++ b/include/uapi/asm-generic/poll.h +@@ -29,7 +29,7 @@ + #define POLLRDHUP 0x2000 + #endif + +-#define POLLFREE (__force __poll_t)0x4000 /* currently only for epoll */ ++#define POLLFREE (__force __poll_t)0x4000 + + #define POLL_BUSY_LOOP (__force __poll_t)0x8000 + +diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c +index 5a2b28e6816ee..95ab3f243acde 100644 +--- a/kernel/bpf/verifier.c ++++ b/kernel/bpf/verifier.c +@@ -7240,7 +7240,7 @@ static void find_good_pkt_pointers(struct bpf_verifier_state *vstate, + + new_range = dst_reg->off; + if (range_right_open) +- new_range--; ++ new_range++; + + /* Examples for register markings: + * +diff --git a/kernel/sched/wait.c b/kernel/sched/wait.c +index 21005b980a6b7..a55642aa3f68b 100644 +--- a/kernel/sched/wait.c ++++ b/kernel/sched/wait.c +@@ -223,6 +223,13 @@ void __wake_up_sync(struct wait_queue_head *wq_head, unsigned int mode) + } + EXPORT_SYMBOL_GPL(__wake_up_sync); /* For internal use only */ + ++void __wake_up_pollfree(struct wait_queue_head *wq_head) ++{ ++ __wake_up(wq_head, TASK_NORMAL, 0, poll_to_key(EPOLLHUP | POLLFREE)); ++ /* POLLFREE must have cleared the queue. */ ++ WARN_ON_ONCE(waitqueue_active(wq_head)); ++} ++ + /* + * Note: we use "set_current_state()" _after_ the wait-queue add, + * because we need a memory barrier there on SMP, so that any +diff --git a/mm/backing-dev.c b/mm/backing-dev.c +index 408d5051d05b3..ca770a783a9f9 100644 +--- a/mm/backing-dev.c ++++ b/mm/backing-dev.c +@@ -872,6 +872,13 @@ void bdi_unregister(struct backing_dev_info *bdi) + wb_shutdown(&bdi->wb); + cgwb_bdi_unregister(bdi); + ++ /* ++ * If this BDI's min ratio has been set, use bdi_set_min_ratio() to ++ * update the global bdi_min_ratio. ++ */ ++ if (bdi->min_ratio) ++ bdi_set_min_ratio(bdi, 0); ++ + if (bdi->dev) { + bdi_debug_unregister(bdi); + device_unregister(bdi->dev); +diff --git a/net/core/devlink.c b/net/core/devlink.c +index 96cf4bc1f9585..442b67c044a9f 100644 +--- a/net/core/devlink.c ++++ b/net/core/devlink.c +@@ -3265,14 +3265,6 @@ static int devlink_nl_cmd_reload(struct sk_buff *skb, struct genl_info *info) + return err; + } + +- if (info->attrs[DEVLINK_ATTR_NETNS_PID] || +- info->attrs[DEVLINK_ATTR_NETNS_FD] || +- info->attrs[DEVLINK_ATTR_NETNS_ID]) { +- dest_net = devlink_netns_get(skb, info); +- if (IS_ERR(dest_net)) +- return PTR_ERR(dest_net); +- } +- + if (info->attrs[DEVLINK_ATTR_RELOAD_ACTION]) + action = nla_get_u8(info->attrs[DEVLINK_ATTR_RELOAD_ACTION]); + else +@@ -3315,6 +3307,14 @@ static int devlink_nl_cmd_reload(struct sk_buff *skb, struct genl_info *info) + return -EINVAL; + } + } ++ if (info->attrs[DEVLINK_ATTR_NETNS_PID] || ++ info->attrs[DEVLINK_ATTR_NETNS_FD] || ++ info->attrs[DEVLINK_ATTR_NETNS_ID]) { ++ dest_net = devlink_netns_get(skb, info); ++ if (IS_ERR(dest_net)) ++ return PTR_ERR(dest_net); ++ } ++ + err = devlink_reload(devlink, dest_net, action, limit, &actions_performed, info->extack); + + if (dest_net) +diff --git a/net/core/neighbour.c b/net/core/neighbour.c +index 8eec7667aa761..52a1c8725337b 100644 +--- a/net/core/neighbour.c ++++ b/net/core/neighbour.c +@@ -734,11 +734,10 @@ struct pneigh_entry * pneigh_lookup(struct neigh_table *tbl, + + ASSERT_RTNL(); + +- n = kmalloc(sizeof(*n) + key_len, GFP_KERNEL); ++ n = kzalloc(sizeof(*n) + key_len, GFP_KERNEL); + if (!n) + goto out; + +- n->protocol = 0; + write_pnet(&n->net, net); + memcpy(n->key, pkey, key_len); + n->dev = dev; +diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c +index 655f0d8a13d36..86ed2afbee302 100644 +--- a/net/ipv4/udp.c ++++ b/net/ipv4/udp.c +@@ -899,7 +899,7 @@ static int udp_send_skb(struct sk_buff *skb, struct flowi4 *fl4, + kfree_skb(skb); + return -EINVAL; + } +- if (skb->len > cork->gso_size * UDP_MAX_SEGMENTS) { ++ if (datalen > cork->gso_size * UDP_MAX_SEGMENTS) { + kfree_skb(skb); + return -EINVAL; + } +diff --git a/net/ipv6/seg6_iptunnel.c b/net/ipv6/seg6_iptunnel.c +index 897fa59c47de7..4d4399c5c5ea9 100644 +--- a/net/ipv6/seg6_iptunnel.c ++++ b/net/ipv6/seg6_iptunnel.c +@@ -160,6 +160,14 @@ int seg6_do_srh_encap(struct sk_buff *skb, struct ipv6_sr_hdr *osrh, int proto) + hdr->hop_limit = ip6_dst_hoplimit(skb_dst(skb)); + + memset(IP6CB(skb), 0, sizeof(*IP6CB(skb))); ++ ++ /* the control block has been erased, so we have to set the ++ * iif once again. ++ * We read the receiving interface index directly from the ++ * skb->skb_iif as it is done in the IPv4 receiving path (i.e.: ++ * ip_rcv_core(...)). ++ */ ++ IP6CB(skb)->iif = skb->skb_iif; + } + + hdr->nexthdr = NEXTHDR_ROUTING; +diff --git a/net/netfilter/nf_conntrack_core.c b/net/netfilter/nf_conntrack_core.c +index 6a66e99459351..f4cf26b606f92 100644 +--- a/net/netfilter/nf_conntrack_core.c ++++ b/net/netfilter/nf_conntrack_core.c +@@ -660,7 +660,7 @@ bool nf_ct_delete(struct nf_conn *ct, u32 portid, int report) + + tstamp = nf_conn_tstamp_find(ct); + if (tstamp) { +- s32 timeout = ct->timeout - nfct_time_stamp; ++ s32 timeout = READ_ONCE(ct->timeout) - nfct_time_stamp; + + tstamp->stop = ktime_get_real_ns(); + if (timeout < 0) +@@ -980,7 +980,7 @@ static int nf_ct_resolve_clash_harder(struct sk_buff *skb, u32 repl_idx) + } + + /* We want the clashing entry to go away real soon: 1 second timeout. */ +- loser_ct->timeout = nfct_time_stamp + HZ; ++ WRITE_ONCE(loser_ct->timeout, nfct_time_stamp + HZ); + + /* IPS_NAT_CLASH removes the entry automatically on the first + * reply. Also prevents UDP tracker from moving the entry to +@@ -1487,7 +1487,7 @@ __nf_conntrack_alloc(struct net *net, + /* save hash for reusing when confirming */ + *(unsigned long *)(&ct->tuplehash[IP_CT_DIR_REPLY].hnnode.pprev) = hash; + ct->status = 0; +- ct->timeout = 0; ++ WRITE_ONCE(ct->timeout, 0); + write_pnet(&ct->ct_net, net); + memset(&ct->__nfct_init_offset, 0, + offsetof(struct nf_conn, proto) - +diff --git a/net/netfilter/nf_conntrack_netlink.c b/net/netfilter/nf_conntrack_netlink.c +index 60a1a666e797a..c6bcc28ae3387 100644 +--- a/net/netfilter/nf_conntrack_netlink.c ++++ b/net/netfilter/nf_conntrack_netlink.c +@@ -1971,7 +1971,7 @@ static int ctnetlink_change_timeout(struct nf_conn *ct, + + if (timeout > INT_MAX) + timeout = INT_MAX; +- ct->timeout = nfct_time_stamp + (u32)timeout; ++ WRITE_ONCE(ct->timeout, nfct_time_stamp + (u32)timeout); + + if (test_bit(IPS_DYING_BIT, &ct->status)) + return -ETIME; +diff --git a/net/netfilter/nf_flow_table_core.c b/net/netfilter/nf_flow_table_core.c +index f4029fc2c8846..d091d51b5e19f 100644 +--- a/net/netfilter/nf_flow_table_core.c ++++ b/net/netfilter/nf_flow_table_core.c +@@ -151,8 +151,8 @@ static void flow_offload_fixup_ct_timeout(struct nf_conn *ct) + else + return; + +- if (nf_flow_timeout_delta(ct->timeout) > (__s32)timeout) +- ct->timeout = nfct_time_stamp + timeout; ++ if (nf_flow_timeout_delta(READ_ONCE(ct->timeout)) > (__s32)timeout) ++ WRITE_ONCE(ct->timeout, nfct_time_stamp + timeout); + } + + static void flow_offload_fixup_ct_state(struct nf_conn *ct) +diff --git a/net/netfilter/nft_set_pipapo_avx2.c b/net/netfilter/nft_set_pipapo_avx2.c +index eabdb8d552eef..10332178da8c5 100644 +--- a/net/netfilter/nft_set_pipapo_avx2.c ++++ b/net/netfilter/nft_set_pipapo_avx2.c +@@ -887,7 +887,7 @@ static int nft_pipapo_avx2_lookup_8b_6(unsigned long *map, unsigned long *fill, + NFT_PIPAPO_AVX2_BUCKET_LOAD8(4, lt, 4, pkt[4], bsize); + + NFT_PIPAPO_AVX2_AND(5, 0, 1); +- NFT_PIPAPO_AVX2_BUCKET_LOAD8(6, lt, 6, pkt[5], bsize); ++ NFT_PIPAPO_AVX2_BUCKET_LOAD8(6, lt, 5, pkt[5], bsize); + NFT_PIPAPO_AVX2_AND(7, 2, 3); + + /* Stall */ +diff --git a/net/nfc/netlink.c b/net/nfc/netlink.c +index bec7847f8eaac..0767404636c14 100644 +--- a/net/nfc/netlink.c ++++ b/net/nfc/netlink.c +@@ -1392,8 +1392,10 @@ static int nfc_genl_dump_ses_done(struct netlink_callback *cb) + { + struct class_dev_iter *iter = (struct class_dev_iter *) cb->args[0]; + +- nfc_device_iter_exit(iter); +- kfree(iter); ++ if (iter) { ++ nfc_device_iter_exit(iter); ++ kfree(iter); ++ } + + return 0; + } +diff --git a/net/sched/sch_fq_pie.c b/net/sched/sch_fq_pie.c +index cac684952edc5..c70802785518f 100644 +--- a/net/sched/sch_fq_pie.c ++++ b/net/sched/sch_fq_pie.c +@@ -531,6 +531,7 @@ static void fq_pie_destroy(struct Qdisc *sch) + struct fq_pie_sched_data *q = qdisc_priv(sch); + + tcf_block_put(q->block); ++ q->p_params.tupdate = 0; + del_timer_sync(&q->adapt_timer); + kvfree(q->flows); + } +diff --git a/scripts/dummy-tools/gcc b/scripts/dummy-tools/gcc +index 11c9f045ee4b9..0d0589cf8184e 100755 +--- a/scripts/dummy-tools/gcc ++++ b/scripts/dummy-tools/gcc +@@ -75,16 +75,12 @@ if arg_contain -S "$@"; then + fi + fi + +-# For scripts/gcc-plugin.sh ++# To set GCC_PLUGINS + if arg_contain -print-file-name=plugin "$@"; then + plugin_dir=$(mktemp -d) + +- sed -n 's/.*#include "\(.*\)"/\1/p' $(dirname $0)/../gcc-plugins/gcc-common.h | +- while read header +- do +- mkdir -p $plugin_dir/include/$(dirname $header) +- touch $plugin_dir/include/$header +- done ++ mkdir -p $plugin_dir/include ++ touch $plugin_dir/include/plugin-version.h + + echo $plugin_dir + exit 0 +diff --git a/scripts/gcc-plugin.sh b/scripts/gcc-plugin.sh +deleted file mode 100755 +index b79fd0bea8384..0000000000000 +--- a/scripts/gcc-plugin.sh ++++ /dev/null +@@ -1,19 +0,0 @@ +-#!/bin/sh +-# SPDX-License-Identifier: GPL-2.0 +- +-set -e +- +-srctree=$(dirname "$0") +- +-gccplugins_dir=$($* -print-file-name=plugin) +- +-# we need a c++ compiler that supports the designated initializer GNU extension +-$HOSTCC -c -x c++ -std=gnu++98 - -fsyntax-only -I $srctree/gcc-plugins -I $gccplugins_dir/include 2>/dev/null <<EOF +-#include "gcc-common.h" +-class test { +-public: +- int test; +-} test = { +- .test = 1 +-}; +-EOF +diff --git a/scripts/gcc-plugins/Kconfig b/scripts/gcc-plugins/Kconfig +index ae19fb0243b9b..ab9eb4cbe33a6 100644 +--- a/scripts/gcc-plugins/Kconfig ++++ b/scripts/gcc-plugins/Kconfig +@@ -9,7 +9,7 @@ menuconfig GCC_PLUGINS + bool "GCC plugins" + depends on HAVE_GCC_PLUGINS + depends on CC_IS_GCC +- depends on $(success,$(srctree)/scripts/gcc-plugin.sh $(CC)) ++ depends on $(success,test -e $(shell,$(CC) -print-file-name=plugin)/include/plugin-version.h) + default y + help + GCC plugins are loadable modules that provide extra features to the +diff --git a/scripts/gcc-plugins/Makefile b/scripts/gcc-plugins/Makefile +index d66949bfeba45..b5487cce69e8e 100644 +--- a/scripts/gcc-plugins/Makefile ++++ b/scripts/gcc-plugins/Makefile +@@ -22,9 +22,9 @@ always-y += $(GCC_PLUGIN) + GCC_PLUGINS_DIR = $(shell $(CC) -print-file-name=plugin) + + plugin_cxxflags = -Wp,-MMD,$(depfile) $(KBUILD_HOSTCXXFLAGS) -fPIC \ +- -I $(GCC_PLUGINS_DIR)/include -I $(obj) -std=gnu++98 \ ++ -I $(GCC_PLUGINS_DIR)/include -I $(obj) -std=gnu++11 \ + -fno-rtti -fno-exceptions -fasynchronous-unwind-tables \ +- -ggdb -Wno-narrowing -Wno-unused-variable -Wno-c++11-compat \ ++ -ggdb -Wno-narrowing -Wno-unused-variable \ + -Wno-format-diag + + plugin_ldflags = -shared +diff --git a/sound/core/control_compat.c b/sound/core/control_compat.c +index 1d708aab9c98e..97467f6a32a13 100644 +--- a/sound/core/control_compat.c ++++ b/sound/core/control_compat.c +@@ -264,6 +264,7 @@ static int copy_ctl_value_to_user(void __user *userdata, + struct snd_ctl_elem_value *data, + int type, int count) + { ++ struct snd_ctl_elem_value32 __user *data32 = userdata; + int i, size; + + if (type == SNDRV_CTL_ELEM_TYPE_BOOLEAN || +@@ -280,6 +281,8 @@ static int copy_ctl_value_to_user(void __user *userdata, + if (copy_to_user(valuep, data->value.bytes.data, size)) + return -EFAULT; + } ++ if (copy_to_user(&data32->id, &data->id, sizeof(data32->id))) ++ return -EFAULT; + return 0; + } + +diff --git a/sound/core/oss/pcm_oss.c b/sound/core/oss/pcm_oss.c +index 142fc751a8477..77727a69c3c4e 100644 +--- a/sound/core/oss/pcm_oss.c ++++ b/sound/core/oss/pcm_oss.c +@@ -147,7 +147,7 @@ snd_pcm_hw_param_value_min(const struct snd_pcm_hw_params *params, + * + * Return the maximum value for field PAR. + */ +-static unsigned int ++static int + snd_pcm_hw_param_value_max(const struct snd_pcm_hw_params *params, + snd_pcm_hw_param_t var, int *dir) + { +@@ -682,18 +682,24 @@ static int snd_pcm_oss_period_size(struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *oss_params, + struct snd_pcm_hw_params *slave_params) + { +- size_t s; +- size_t oss_buffer_size, oss_period_size, oss_periods; +- size_t min_period_size, max_period_size; ++ ssize_t s; ++ ssize_t oss_buffer_size; ++ ssize_t oss_period_size, oss_periods; ++ ssize_t min_period_size, max_period_size; + struct snd_pcm_runtime *runtime = substream->runtime; + size_t oss_frame_size; + + oss_frame_size = snd_pcm_format_physical_width(params_format(oss_params)) * + params_channels(oss_params) / 8; + ++ oss_buffer_size = snd_pcm_hw_param_value_max(slave_params, ++ SNDRV_PCM_HW_PARAM_BUFFER_SIZE, ++ NULL); ++ if (oss_buffer_size <= 0) ++ return -EINVAL; + oss_buffer_size = snd_pcm_plug_client_size(substream, +- snd_pcm_hw_param_value_max(slave_params, SNDRV_PCM_HW_PARAM_BUFFER_SIZE, NULL)) * oss_frame_size; +- if (!oss_buffer_size) ++ oss_buffer_size * oss_frame_size); ++ if (oss_buffer_size <= 0) + return -EINVAL; + oss_buffer_size = rounddown_pow_of_two(oss_buffer_size); + if (atomic_read(&substream->mmap_count)) { +@@ -730,7 +736,7 @@ static int snd_pcm_oss_period_size(struct snd_pcm_substream *substream, + + min_period_size = snd_pcm_plug_client_size(substream, + snd_pcm_hw_param_value_min(slave_params, SNDRV_PCM_HW_PARAM_PERIOD_SIZE, NULL)); +- if (min_period_size) { ++ if (min_period_size > 0) { + min_period_size *= oss_frame_size; + min_period_size = roundup_pow_of_two(min_period_size); + if (oss_period_size < min_period_size) +@@ -739,7 +745,7 @@ static int snd_pcm_oss_period_size(struct snd_pcm_substream *substream, + + max_period_size = snd_pcm_plug_client_size(substream, + snd_pcm_hw_param_value_max(slave_params, SNDRV_PCM_HW_PARAM_PERIOD_SIZE, NULL)); +- if (max_period_size) { ++ if (max_period_size > 0) { + max_period_size *= oss_frame_size; + max_period_size = rounddown_pow_of_two(max_period_size); + if (oss_period_size > max_period_size) +@@ -752,7 +758,7 @@ static int snd_pcm_oss_period_size(struct snd_pcm_substream *substream, + oss_periods = substream->oss.setup.periods; + + s = snd_pcm_hw_param_value_max(slave_params, SNDRV_PCM_HW_PARAM_PERIODS, NULL); +- if (runtime->oss.maxfrags && s > runtime->oss.maxfrags) ++ if (s > 0 && runtime->oss.maxfrags && s > runtime->oss.maxfrags) + s = runtime->oss.maxfrags; + if (oss_periods > s) + oss_periods = s; +@@ -878,8 +884,15 @@ static int snd_pcm_oss_change_params_locked(struct snd_pcm_substream *substream) + err = -EINVAL; + goto failure; + } +- choose_rate(substream, sparams, runtime->oss.rate); +- snd_pcm_hw_param_near(substream, sparams, SNDRV_PCM_HW_PARAM_CHANNELS, runtime->oss.channels, NULL); ++ ++ err = choose_rate(substream, sparams, runtime->oss.rate); ++ if (err < 0) ++ goto failure; ++ err = snd_pcm_hw_param_near(substream, sparams, ++ SNDRV_PCM_HW_PARAM_CHANNELS, ++ runtime->oss.channels, NULL); ++ if (err < 0) ++ goto failure; + + format = snd_pcm_oss_format_from(runtime->oss.format); + +@@ -1947,7 +1960,7 @@ static int snd_pcm_oss_set_fragment1(struct snd_pcm_substream *substream, unsign + if (runtime->oss.subdivision || runtime->oss.fragshift) + return -EINVAL; + fragshift = val & 0xffff; +- if (fragshift >= 31) ++ if (fragshift >= 25) /* should be large enough */ + return -EINVAL; + runtime->oss.fragshift = fragshift; + runtime->oss.maxfrags = (val >> 16) & 0xffff; +diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c +index b980fa617229e..bed2a93001635 100644 +--- a/sound/pci/hda/patch_realtek.c ++++ b/sound/pci/hda/patch_realtek.c +@@ -6449,22 +6449,26 @@ static void alc287_fixup_legion_15imhg05_speakers(struct hda_codec *codec, + /* for alc285_fixup_ideapad_s740_coef() */ + #include "ideapad_s740_helper.c" + +-static void alc256_fixup_tongfang_reset_persistent_settings(struct hda_codec *codec, +- const struct hda_fixup *fix, +- int action) ++static const struct coef_fw alc256_fixup_set_coef_defaults_coefs[] = { ++ WRITE_COEF(0x10, 0x0020), WRITE_COEF(0x24, 0x0000), ++ WRITE_COEF(0x26, 0x0000), WRITE_COEF(0x29, 0x3000), ++ WRITE_COEF(0x37, 0xfe05), WRITE_COEF(0x45, 0x5089), ++ {} ++}; ++ ++static void alc256_fixup_set_coef_defaults(struct hda_codec *codec, ++ const struct hda_fixup *fix, ++ int action) + { + /* +- * A certain other OS sets these coeffs to different values. On at least one TongFang +- * barebone these settings might survive even a cold reboot. So to restore a clean slate the +- * values are explicitly reset to default here. Without this, the external microphone is +- * always in a plugged-in state, while the internal microphone is always in an unplugged +- * state, breaking the ability to use the internal microphone. +- */ +- alc_write_coef_idx(codec, 0x24, 0x0000); +- alc_write_coef_idx(codec, 0x26, 0x0000); +- alc_write_coef_idx(codec, 0x29, 0x3000); +- alc_write_coef_idx(codec, 0x37, 0xfe05); +- alc_write_coef_idx(codec, 0x45, 0x5089); ++ * A certain other OS sets these coeffs to different values. On at least ++ * one TongFang barebone these settings might survive even a cold ++ * reboot. So to restore a clean slate the values are explicitly reset ++ * to default here. Without this, the external microphone is always in a ++ * plugged-in state, while the internal microphone is always in an ++ * unplugged state, breaking the ability to use the internal microphone. ++ */ ++ alc_process_coef_fw(codec, alc256_fixup_set_coef_defaults_coefs); + } + + static const struct coef_fw alc233_fixup_no_audio_jack_coefs[] = { +@@ -6704,7 +6708,7 @@ enum { + ALC287_FIXUP_LEGION_15IMHG05_AUTOMUTE, + ALC287_FIXUP_YOGA7_14ITL_SPEAKERS, + ALC287_FIXUP_13S_GEN2_SPEAKERS, +- ALC256_FIXUP_TONGFANG_RESET_PERSISTENT_SETTINGS, ++ ALC256_FIXUP_SET_COEF_DEFAULTS, + ALC256_FIXUP_SYSTEM76_MIC_NO_PRESENCE, + ALC233_FIXUP_NO_AUDIO_JACK, + }; +@@ -8404,9 +8408,9 @@ static const struct hda_fixup alc269_fixups[] = { + .chained = true, + .chain_id = ALC269_FIXUP_HEADSET_MODE, + }, +- [ALC256_FIXUP_TONGFANG_RESET_PERSISTENT_SETTINGS] = { ++ [ALC256_FIXUP_SET_COEF_DEFAULTS] = { + .type = HDA_FIXUP_FUNC, +- .v.func = alc256_fixup_tongfang_reset_persistent_settings, ++ .v.func = alc256_fixup_set_coef_defaults, + }, + [ALC245_FIXUP_HP_GPIO_LED] = { + .type = HDA_FIXUP_FUNC, +@@ -8866,7 +8870,7 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = { + SND_PCI_QUIRK(0x1b7d, 0xa831, "Ordissimo EVE2 ", ALC269VB_FIXUP_ORDISSIMO_EVE2), /* Also known as Malata PC-B1303 */ + SND_PCI_QUIRK(0x1c06, 0x2013, "Lemote A1802", ALC269_FIXUP_LEMOTE_A1802), + SND_PCI_QUIRK(0x1c06, 0x2015, "Lemote A190X", ALC269_FIXUP_LEMOTE_A190X), +- SND_PCI_QUIRK(0x1d05, 0x1132, "TongFang PHxTxX1", ALC256_FIXUP_TONGFANG_RESET_PERSISTENT_SETTINGS), ++ SND_PCI_QUIRK(0x1d05, 0x1132, "TongFang PHxTxX1", ALC256_FIXUP_SET_COEF_DEFAULTS), + SND_PCI_QUIRK(0x1d72, 0x1602, "RedmiBook", ALC255_FIXUP_XIAOMI_HEADSET_MIC), + SND_PCI_QUIRK(0x1d72, 0x1701, "XiaomiNotebook Pro", ALC298_FIXUP_DELL1_MIC_NO_PRESENCE), + SND_PCI_QUIRK(0x1d72, 0x1901, "RedmiBook 14", ALC256_FIXUP_ASUS_HEADSET_MIC), +@@ -10163,6 +10167,27 @@ static void alc671_fixup_hp_headset_mic2(struct hda_codec *codec, + } + } + ++static void alc897_hp_automute_hook(struct hda_codec *codec, ++ struct hda_jack_callback *jack) ++{ ++ struct alc_spec *spec = codec->spec; ++ int vref; ++ ++ snd_hda_gen_hp_automute(codec, jack); ++ vref = spec->gen.hp_jack_present ? (PIN_HP | AC_PINCTL_VREF_100) : PIN_HP; ++ snd_hda_codec_write(codec, 0x1b, 0, AC_VERB_SET_PIN_WIDGET_CONTROL, ++ vref); ++} ++ ++static void alc897_fixup_lenovo_headset_mic(struct hda_codec *codec, ++ const struct hda_fixup *fix, int action) ++{ ++ struct alc_spec *spec = codec->spec; ++ if (action == HDA_FIXUP_ACT_PRE_PROBE) { ++ spec->gen.hp_automute_hook = alc897_hp_automute_hook; ++ } ++} ++ + static const struct coef_fw alc668_coefs[] = { + WRITE_COEF(0x01, 0xbebe), WRITE_COEF(0x02, 0xaaaa), WRITE_COEF(0x03, 0x0), + WRITE_COEF(0x04, 0x0180), WRITE_COEF(0x06, 0x0), WRITE_COEF(0x07, 0x0f80), +@@ -10243,6 +10268,8 @@ enum { + ALC668_FIXUP_ASUS_NO_HEADSET_MIC, + ALC668_FIXUP_HEADSET_MIC, + ALC668_FIXUP_MIC_DET_COEF, ++ ALC897_FIXUP_LENOVO_HEADSET_MIC, ++ ALC897_FIXUP_HEADSET_MIC_PIN, + }; + + static const struct hda_fixup alc662_fixups[] = { +@@ -10649,6 +10676,19 @@ static const struct hda_fixup alc662_fixups[] = { + {} + }, + }, ++ [ALC897_FIXUP_LENOVO_HEADSET_MIC] = { ++ .type = HDA_FIXUP_FUNC, ++ .v.func = alc897_fixup_lenovo_headset_mic, ++ }, ++ [ALC897_FIXUP_HEADSET_MIC_PIN] = { ++ .type = HDA_FIXUP_PINS, ++ .v.pins = (const struct hda_pintbl[]) { ++ { 0x1a, 0x03a11050 }, ++ { } ++ }, ++ .chained = true, ++ .chain_id = ALC897_FIXUP_LENOVO_HEADSET_MIC ++ }, + }; + + static const struct snd_pci_quirk alc662_fixup_tbl[] = { +@@ -10693,6 +10733,10 @@ static const struct snd_pci_quirk alc662_fixup_tbl[] = { + SND_PCI_QUIRK(0x144d, 0xc051, "Samsung R720", ALC662_FIXUP_IDEAPAD), + SND_PCI_QUIRK(0x14cd, 0x5003, "USI", ALC662_FIXUP_USI_HEADSET_MODE), + SND_PCI_QUIRK(0x17aa, 0x1036, "Lenovo P520", ALC662_FIXUP_LENOVO_MULTI_CODECS), ++ SND_PCI_QUIRK(0x17aa, 0x32ca, "Lenovo ThinkCentre M80", ALC897_FIXUP_HEADSET_MIC_PIN), ++ SND_PCI_QUIRK(0x17aa, 0x32cb, "Lenovo ThinkCentre M70", ALC897_FIXUP_HEADSET_MIC_PIN), ++ SND_PCI_QUIRK(0x17aa, 0x32cf, "Lenovo ThinkCentre M950", ALC897_FIXUP_HEADSET_MIC_PIN), ++ SND_PCI_QUIRK(0x17aa, 0x32f7, "Lenovo ThinkCentre M90", ALC897_FIXUP_HEADSET_MIC_PIN), + SND_PCI_QUIRK(0x17aa, 0x38af, "Lenovo Ideapad Y550P", ALC662_FIXUP_IDEAPAD), + SND_PCI_QUIRK(0x17aa, 0x3a0d, "Lenovo Ideapad Y550", ALC662_FIXUP_IDEAPAD), + SND_PCI_QUIRK(0x1849, 0x5892, "ASRock B150M", ALC892_FIXUP_ASROCK_MOBO), +diff --git a/sound/soc/codecs/rt5682.c b/sound/soc/codecs/rt5682.c +index 0486b14697994..41827cdf26a39 100644 +--- a/sound/soc/codecs/rt5682.c ++++ b/sound/soc/codecs/rt5682.c +@@ -2797,6 +2797,8 @@ static int rt5682_register_dai_clks(struct snd_soc_component *component) + + for (i = 0; i < RT5682_DAI_NUM_CLKS; ++i) { + struct clk_init_data init = { }; ++ struct clk_parent_data parent_data; ++ const struct clk_hw *parent; + + dai_clk_hw = &rt5682->dai_clks_hw[i]; + +@@ -2804,17 +2806,17 @@ static int rt5682_register_dai_clks(struct snd_soc_component *component) + case RT5682_DAI_WCLK_IDX: + /* Make MCLK the parent of WCLK */ + if (rt5682->mclk) { +- init.parent_data = &(struct clk_parent_data){ ++ parent_data = (struct clk_parent_data){ + .fw_name = "mclk", + }; ++ init.parent_data = &parent_data; + init.num_parents = 1; + } + break; + case RT5682_DAI_BCLK_IDX: + /* Make WCLK the parent of BCLK */ +- init.parent_hws = &(const struct clk_hw *){ +- &rt5682->dai_clks_hw[RT5682_DAI_WCLK_IDX] +- }; ++ parent = &rt5682->dai_clks_hw[RT5682_DAI_WCLK_IDX]; ++ init.parent_hws = &parent; + init.num_parents = 1; + break; + default: +diff --git a/sound/soc/codecs/wcd934x.c b/sound/soc/codecs/wcd934x.c +index 699b59cd389c0..01df3f4e045a9 100644 +--- a/sound/soc/codecs/wcd934x.c ++++ b/sound/soc/codecs/wcd934x.c +@@ -2470,6 +2470,9 @@ static int wcd934x_compander_set(struct snd_kcontrol *kc, + int value = ucontrol->value.integer.value[0]; + int sel; + ++ if (wcd->comp_enabled[comp] == value) ++ return 0; ++ + wcd->comp_enabled[comp] = value; + sel = value ? WCD934X_HPH_GAIN_SRC_SEL_COMPANDER : + WCD934X_HPH_GAIN_SRC_SEL_REGISTER; +@@ -2493,10 +2496,10 @@ static int wcd934x_compander_set(struct snd_kcontrol *kc, + case COMPANDER_8: + break; + default: +- break; ++ return 0; + } + +- return 0; ++ return 1; + } + + static int wcd934x_rx_hph_mode_get(struct snd_kcontrol *kc, +@@ -2540,6 +2543,31 @@ static int slim_rx_mux_get(struct snd_kcontrol *kc, + return 0; + } + ++static int slim_rx_mux_to_dai_id(int mux) ++{ ++ int aif_id; ++ ++ switch (mux) { ++ case 1: ++ aif_id = AIF1_PB; ++ break; ++ case 2: ++ aif_id = AIF2_PB; ++ break; ++ case 3: ++ aif_id = AIF3_PB; ++ break; ++ case 4: ++ aif_id = AIF4_PB; ++ break; ++ default: ++ aif_id = -1; ++ break; ++ } ++ ++ return aif_id; ++} ++ + static int slim_rx_mux_put(struct snd_kcontrol *kc, + struct snd_ctl_elem_value *ucontrol) + { +@@ -2547,43 +2575,59 @@ static int slim_rx_mux_put(struct snd_kcontrol *kc, + struct wcd934x_codec *wcd = dev_get_drvdata(w->dapm->dev); + struct soc_enum *e = (struct soc_enum *)kc->private_value; + struct snd_soc_dapm_update *update = NULL; ++ struct wcd934x_slim_ch *ch, *c; + u32 port_id = w->shift; ++ bool found = false; ++ int mux_idx; ++ int prev_mux_idx = wcd->rx_port_value[port_id]; ++ int aif_id; + +- if (wcd->rx_port_value[port_id] == ucontrol->value.enumerated.item[0]) +- return 0; ++ mux_idx = ucontrol->value.enumerated.item[0]; + +- wcd->rx_port_value[port_id] = ucontrol->value.enumerated.item[0]; ++ if (mux_idx == prev_mux_idx) ++ return 0; + +- switch (wcd->rx_port_value[port_id]) { ++ switch(mux_idx) { + case 0: +- list_del_init(&wcd->rx_chs[port_id].list); +- break; +- case 1: +- list_add_tail(&wcd->rx_chs[port_id].list, +- &wcd->dai[AIF1_PB].slim_ch_list); +- break; +- case 2: +- list_add_tail(&wcd->rx_chs[port_id].list, +- &wcd->dai[AIF2_PB].slim_ch_list); +- break; +- case 3: +- list_add_tail(&wcd->rx_chs[port_id].list, +- &wcd->dai[AIF3_PB].slim_ch_list); ++ aif_id = slim_rx_mux_to_dai_id(prev_mux_idx); ++ if (aif_id < 0) ++ return 0; ++ ++ list_for_each_entry_safe(ch, c, &wcd->dai[aif_id].slim_ch_list, list) { ++ if (ch->port == port_id + WCD934X_RX_START) { ++ found = true; ++ list_del_init(&ch->list); ++ break; ++ } ++ } ++ if (!found) ++ return 0; ++ + break; +- case 4: +- list_add_tail(&wcd->rx_chs[port_id].list, +- &wcd->dai[AIF4_PB].slim_ch_list); ++ case 1 ... 4: ++ aif_id = slim_rx_mux_to_dai_id(mux_idx); ++ if (aif_id < 0) ++ return 0; ++ ++ if (list_empty(&wcd->rx_chs[port_id].list)) { ++ list_add_tail(&wcd->rx_chs[port_id].list, ++ &wcd->dai[aif_id].slim_ch_list); ++ } else { ++ dev_err(wcd->dev ,"SLIM_RX%d PORT is busy\n", port_id); ++ return 0; ++ } + break; ++ + default: +- dev_err(wcd->dev, "Unknown AIF %d\n", +- wcd->rx_port_value[port_id]); ++ dev_err(wcd->dev, "Unknown AIF %d\n", mux_idx); + goto err; + } + ++ wcd->rx_port_value[port_id] = mux_idx; + snd_soc_dapm_mux_update_power(w->dapm, kc, wcd->rx_port_value[port_id], + e, update); + +- return 0; ++ return 1; + err: + return -EINVAL; + } +@@ -3029,6 +3073,7 @@ static int slim_tx_mixer_put(struct snd_kcontrol *kc, + struct soc_mixer_control *mixer = + (struct soc_mixer_control *)kc->private_value; + int enable = ucontrol->value.integer.value[0]; ++ struct wcd934x_slim_ch *ch, *c; + int dai_id = widget->shift; + int port_id = mixer->shift; + +@@ -3036,17 +3081,32 @@ static int slim_tx_mixer_put(struct snd_kcontrol *kc, + if (enable == wcd->tx_port_value[port_id]) + return 0; + +- wcd->tx_port_value[port_id] = enable; +- +- if (enable) +- list_add_tail(&wcd->tx_chs[port_id].list, +- &wcd->dai[dai_id].slim_ch_list); +- else +- list_del_init(&wcd->tx_chs[port_id].list); ++ if (enable) { ++ if (list_empty(&wcd->tx_chs[port_id].list)) { ++ list_add_tail(&wcd->tx_chs[port_id].list, ++ &wcd->dai[dai_id].slim_ch_list); ++ } else { ++ dev_err(wcd->dev ,"SLIM_TX%d PORT is busy\n", port_id); ++ return 0; ++ } ++ } else { ++ bool found = false; ++ ++ list_for_each_entry_safe(ch, c, &wcd->dai[dai_id].slim_ch_list, list) { ++ if (ch->port == port_id) { ++ found = true; ++ list_del_init(&wcd->tx_chs[port_id].list); ++ break; ++ } ++ } ++ if (!found) ++ return 0; ++ } + ++ wcd->tx_port_value[port_id] = enable; + snd_soc_dapm_mixer_update_power(widget->dapm, kc, enable, update); + +- return 0; ++ return 1; + } + + static const struct snd_kcontrol_new aif1_slim_cap_mixer[] = { +diff --git a/sound/soc/codecs/wsa881x.c b/sound/soc/codecs/wsa881x.c +index db87e07b11c94..601525c77bbaf 100644 +--- a/sound/soc/codecs/wsa881x.c ++++ b/sound/soc/codecs/wsa881x.c +@@ -772,7 +772,8 @@ static int wsa881x_put_pa_gain(struct snd_kcontrol *kc, + + usleep_range(1000, 1010); + } +- return 0; ++ ++ return 1; + } + + static int wsa881x_get_port(struct snd_kcontrol *kcontrol, +@@ -816,15 +817,22 @@ static int wsa881x_set_port(struct snd_kcontrol *kcontrol, + (struct soc_mixer_control *)kcontrol->private_value; + int portidx = mixer->reg; + +- if (ucontrol->value.integer.value[0]) ++ if (ucontrol->value.integer.value[0]) { ++ if (data->port_enable[portidx]) ++ return 0; ++ + data->port_enable[portidx] = true; +- else ++ } else { ++ if (!data->port_enable[portidx]) ++ return 0; ++ + data->port_enable[portidx] = false; ++ } + + if (portidx == WSA881X_PORT_BOOST) /* Boost Switch */ + wsa881x_boost_ctrl(comp, data->port_enable[portidx]); + +- return 0; ++ return 1; + } + + static const char * const smart_boost_lvl_text[] = { +diff --git a/sound/soc/qcom/qdsp6/q6routing.c b/sound/soc/qcom/qdsp6/q6routing.c +index 934b3f282bccd..2026fa5902927 100644 +--- a/sound/soc/qcom/qdsp6/q6routing.c ++++ b/sound/soc/qcom/qdsp6/q6routing.c +@@ -488,14 +488,16 @@ static int msm_routing_put_audio_mixer(struct snd_kcontrol *kcontrol, + struct session_data *session = &data->sessions[session_id]; + + if (ucontrol->value.integer.value[0]) { ++ if (session->port_id == be_id) ++ return 0; ++ + session->port_id = be_id; + snd_soc_dapm_mixer_update_power(dapm, kcontrol, 1, update); + } else { +- if (session->port_id == be_id) { +- session->port_id = -1; ++ if (session->port_id == -1 || session->port_id != be_id) + return 0; +- } + ++ session->port_id = -1; + snd_soc_dapm_mixer_update_power(dapm, kcontrol, 0, update); + } + +diff --git a/tools/build/Makefile.feature b/tools/build/Makefile.feature +index 97cbfb31b7625..e1d2c255669e6 100644 +--- a/tools/build/Makefile.feature ++++ b/tools/build/Makefile.feature +@@ -49,7 +49,6 @@ FEATURE_TESTS_BASIC := \ + numa_num_possible_cpus \ + libperl \ + libpython \ +- libpython-version \ + libslang \ + libslang-include-subdir \ + libcrypto \ +diff --git a/tools/build/feature/Makefile b/tools/build/feature/Makefile +index 89ba522e377dc..22ea350dab588 100644 +--- a/tools/build/feature/Makefile ++++ b/tools/build/feature/Makefile +@@ -31,7 +31,6 @@ FILES= \ + test-numa_num_possible_cpus.bin \ + test-libperl.bin \ + test-libpython.bin \ +- test-libpython-version.bin \ + test-libslang.bin \ + test-libslang-include-subdir.bin \ + test-libcrypto.bin \ +@@ -220,9 +219,6 @@ $(OUTPUT)test-libperl.bin: + $(OUTPUT)test-libpython.bin: + $(BUILD) $(FLAGS_PYTHON_EMBED) + +-$(OUTPUT)test-libpython-version.bin: +- $(BUILD) +- + $(OUTPUT)test-libbfd.bin: + $(BUILD) -DPACKAGE='"perf"' -lbfd -ldl + +diff --git a/tools/build/feature/test-all.c b/tools/build/feature/test-all.c +index 464873883396e..09517ff2fad56 100644 +--- a/tools/build/feature/test-all.c ++++ b/tools/build/feature/test-all.c +@@ -14,10 +14,6 @@ + # include "test-libpython.c" + #undef main + +-#define main main_test_libpython_version +-# include "test-libpython-version.c" +-#undef main +- + #define main main_test_libperl + # include "test-libperl.c" + #undef main +@@ -181,7 +177,6 @@ + int main(int argc, char *argv[]) + { + main_test_libpython(); +- main_test_libpython_version(); + main_test_libperl(); + main_test_hello(); + main_test_libelf(); +diff --git a/tools/build/feature/test-libpython-version.c b/tools/build/feature/test-libpython-version.c +deleted file mode 100644 +index 47714b942d4d3..0000000000000 +--- a/tools/build/feature/test-libpython-version.c ++++ /dev/null +@@ -1,11 +0,0 @@ +-// SPDX-License-Identifier: GPL-2.0 +-#include <Python.h> +- +-#if PY_VERSION_HEX >= 0x03000000 +- #error +-#endif +- +-int main(void) +-{ +- return 0; +-} +diff --git a/tools/perf/Makefile.config b/tools/perf/Makefile.config +index 014b959575cae..68408a5ecfed2 100644 +--- a/tools/perf/Makefile.config ++++ b/tools/perf/Makefile.config +@@ -259,8 +259,6 @@ endif + + FEATURE_CHECK_CFLAGS-libpython := $(PYTHON_EMBED_CCOPTS) + FEATURE_CHECK_LDFLAGS-libpython := $(PYTHON_EMBED_LDOPTS) +-FEATURE_CHECK_CFLAGS-libpython-version := $(PYTHON_EMBED_CCOPTS) +-FEATURE_CHECK_LDFLAGS-libpython-version := $(PYTHON_EMBED_LDOPTS) + + FEATURE_CHECK_LDFLAGS-libaio = -lrt + +diff --git a/tools/perf/util/smt.c b/tools/perf/util/smt.c +index 20bacd5972ade..34f1b1b1176c7 100644 +--- a/tools/perf/util/smt.c ++++ b/tools/perf/util/smt.c +@@ -15,7 +15,7 @@ int smt_on(void) + if (cached) + return cached_result; + +- if (sysfs__read_int("devices/system/cpu/smt/active", &cached_result) > 0) ++ if (sysfs__read_int("devices/system/cpu/smt/active", &cached_result) >= 0) + goto done; + + ncpu = sysconf(_SC_NPROCESSORS_CONF); +diff --git a/tools/testing/selftests/bpf/verifier/xdp_direct_packet_access.c b/tools/testing/selftests/bpf/verifier/xdp_direct_packet_access.c +index bfb97383e6b5a..b4ec228eb95d0 100644 +--- a/tools/testing/selftests/bpf/verifier/xdp_direct_packet_access.c ++++ b/tools/testing/selftests/bpf/verifier/xdp_direct_packet_access.c +@@ -35,7 +35,7 @@ + .prog_type = BPF_PROG_TYPE_XDP, + }, + { +- "XDP pkt read, pkt_data' > pkt_end, good access", ++ "XDP pkt read, pkt_data' > pkt_end, corner case, good access", + .insns = { + BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_1, offsetof(struct xdp_md, data)), + BPF_LDX_MEM(BPF_W, BPF_REG_3, BPF_REG_1, +@@ -87,6 +87,41 @@ + .prog_type = BPF_PROG_TYPE_XDP, + .flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS, + }, ++{ ++ "XDP pkt read, pkt_data' > pkt_end, corner case +1, good access", ++ .insns = { ++ BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_1, offsetof(struct xdp_md, data)), ++ BPF_LDX_MEM(BPF_W, BPF_REG_3, BPF_REG_1, ++ offsetof(struct xdp_md, data_end)), ++ BPF_MOV64_REG(BPF_REG_1, BPF_REG_2), ++ BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, 9), ++ BPF_JMP_REG(BPF_JGT, BPF_REG_1, BPF_REG_3, 1), ++ BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_1, -9), ++ BPF_MOV64_IMM(BPF_REG_0, 0), ++ BPF_EXIT_INSN(), ++ }, ++ .result = ACCEPT, ++ .prog_type = BPF_PROG_TYPE_XDP, ++ .flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS, ++}, ++{ ++ "XDP pkt read, pkt_data' > pkt_end, corner case -1, bad access", ++ .insns = { ++ BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_1, offsetof(struct xdp_md, data)), ++ BPF_LDX_MEM(BPF_W, BPF_REG_3, BPF_REG_1, ++ offsetof(struct xdp_md, data_end)), ++ BPF_MOV64_REG(BPF_REG_1, BPF_REG_2), ++ BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, 7), ++ BPF_JMP_REG(BPF_JGT, BPF_REG_1, BPF_REG_3, 1), ++ BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_1, -7), ++ BPF_MOV64_IMM(BPF_REG_0, 0), ++ BPF_EXIT_INSN(), ++ }, ++ .errstr = "R1 offset is outside of the packet", ++ .result = REJECT, ++ .prog_type = BPF_PROG_TYPE_XDP, ++ .flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS, ++}, + { + "XDP pkt read, pkt_end > pkt_data', good access", + .insns = { +@@ -106,16 +141,16 @@ + .flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS, + }, + { +- "XDP pkt read, pkt_end > pkt_data', bad access 1", ++ "XDP pkt read, pkt_end > pkt_data', corner case -1, bad access", + .insns = { + BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_1, offsetof(struct xdp_md, data)), + BPF_LDX_MEM(BPF_W, BPF_REG_3, BPF_REG_1, + offsetof(struct xdp_md, data_end)), + BPF_MOV64_REG(BPF_REG_1, BPF_REG_2), +- BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, 8), ++ BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, 6), + BPF_JMP_REG(BPF_JGT, BPF_REG_3, BPF_REG_1, 1), + BPF_JMP_IMM(BPF_JA, 0, 0, 1), +- BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_1, -8), ++ BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_1, -6), + BPF_MOV64_IMM(BPF_REG_0, 0), + BPF_EXIT_INSN(), + }, +@@ -142,6 +177,42 @@ + .prog_type = BPF_PROG_TYPE_XDP, + .flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS, + }, ++{ ++ "XDP pkt read, pkt_end > pkt_data', corner case, good access", ++ .insns = { ++ BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_1, offsetof(struct xdp_md, data)), ++ BPF_LDX_MEM(BPF_W, BPF_REG_3, BPF_REG_1, ++ offsetof(struct xdp_md, data_end)), ++ BPF_MOV64_REG(BPF_REG_1, BPF_REG_2), ++ BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, 7), ++ BPF_JMP_REG(BPF_JGT, BPF_REG_3, BPF_REG_1, 1), ++ BPF_JMP_IMM(BPF_JA, 0, 0, 1), ++ BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_1, -7), ++ BPF_MOV64_IMM(BPF_REG_0, 0), ++ BPF_EXIT_INSN(), ++ }, ++ .result = ACCEPT, ++ .prog_type = BPF_PROG_TYPE_XDP, ++ .flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS, ++}, ++{ ++ "XDP pkt read, pkt_end > pkt_data', corner case +1, good access", ++ .insns = { ++ BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_1, offsetof(struct xdp_md, data)), ++ BPF_LDX_MEM(BPF_W, BPF_REG_3, BPF_REG_1, ++ offsetof(struct xdp_md, data_end)), ++ BPF_MOV64_REG(BPF_REG_1, BPF_REG_2), ++ BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, 8), ++ BPF_JMP_REG(BPF_JGT, BPF_REG_3, BPF_REG_1, 1), ++ BPF_JMP_IMM(BPF_JA, 0, 0, 1), ++ BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_1, -8), ++ BPF_MOV64_IMM(BPF_REG_0, 0), ++ BPF_EXIT_INSN(), ++ }, ++ .result = ACCEPT, ++ .prog_type = BPF_PROG_TYPE_XDP, ++ .flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS, ++}, + { + "XDP pkt read, pkt_data' < pkt_end, good access", + .insns = { +@@ -161,16 +232,16 @@ + .flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS, + }, + { +- "XDP pkt read, pkt_data' < pkt_end, bad access 1", ++ "XDP pkt read, pkt_data' < pkt_end, corner case -1, bad access", + .insns = { + BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_1, offsetof(struct xdp_md, data)), + BPF_LDX_MEM(BPF_W, BPF_REG_3, BPF_REG_1, + offsetof(struct xdp_md, data_end)), + BPF_MOV64_REG(BPF_REG_1, BPF_REG_2), +- BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, 8), ++ BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, 6), + BPF_JMP_REG(BPF_JLT, BPF_REG_1, BPF_REG_3, 1), + BPF_JMP_IMM(BPF_JA, 0, 0, 1), +- BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_1, -8), ++ BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_1, -6), + BPF_MOV64_IMM(BPF_REG_0, 0), + BPF_EXIT_INSN(), + }, +@@ -198,7 +269,43 @@ + .flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS, + }, + { +- "XDP pkt read, pkt_end < pkt_data', good access", ++ "XDP pkt read, pkt_data' < pkt_end, corner case, good access", ++ .insns = { ++ BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_1, offsetof(struct xdp_md, data)), ++ BPF_LDX_MEM(BPF_W, BPF_REG_3, BPF_REG_1, ++ offsetof(struct xdp_md, data_end)), ++ BPF_MOV64_REG(BPF_REG_1, BPF_REG_2), ++ BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, 7), ++ BPF_JMP_REG(BPF_JLT, BPF_REG_1, BPF_REG_3, 1), ++ BPF_JMP_IMM(BPF_JA, 0, 0, 1), ++ BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_1, -7), ++ BPF_MOV64_IMM(BPF_REG_0, 0), ++ BPF_EXIT_INSN(), ++ }, ++ .result = ACCEPT, ++ .prog_type = BPF_PROG_TYPE_XDP, ++ .flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS, ++}, ++{ ++ "XDP pkt read, pkt_data' < pkt_end, corner case +1, good access", ++ .insns = { ++ BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_1, offsetof(struct xdp_md, data)), ++ BPF_LDX_MEM(BPF_W, BPF_REG_3, BPF_REG_1, ++ offsetof(struct xdp_md, data_end)), ++ BPF_MOV64_REG(BPF_REG_1, BPF_REG_2), ++ BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, 8), ++ BPF_JMP_REG(BPF_JLT, BPF_REG_1, BPF_REG_3, 1), ++ BPF_JMP_IMM(BPF_JA, 0, 0, 1), ++ BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_1, -8), ++ BPF_MOV64_IMM(BPF_REG_0, 0), ++ BPF_EXIT_INSN(), ++ }, ++ .result = ACCEPT, ++ .prog_type = BPF_PROG_TYPE_XDP, ++ .flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS, ++}, ++{ ++ "XDP pkt read, pkt_end < pkt_data', corner case, good access", + .insns = { + BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_1, offsetof(struct xdp_md, data)), + BPF_LDX_MEM(BPF_W, BPF_REG_3, BPF_REG_1, +@@ -250,6 +357,41 @@ + .prog_type = BPF_PROG_TYPE_XDP, + .flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS, + }, ++{ ++ "XDP pkt read, pkt_end < pkt_data', corner case +1, good access", ++ .insns = { ++ BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_1, offsetof(struct xdp_md, data)), ++ BPF_LDX_MEM(BPF_W, BPF_REG_3, BPF_REG_1, ++ offsetof(struct xdp_md, data_end)), ++ BPF_MOV64_REG(BPF_REG_1, BPF_REG_2), ++ BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, 9), ++ BPF_JMP_REG(BPF_JLT, BPF_REG_3, BPF_REG_1, 1), ++ BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_1, -9), ++ BPF_MOV64_IMM(BPF_REG_0, 0), ++ BPF_EXIT_INSN(), ++ }, ++ .result = ACCEPT, ++ .prog_type = BPF_PROG_TYPE_XDP, ++ .flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS, ++}, ++{ ++ "XDP pkt read, pkt_end < pkt_data', corner case -1, bad access", ++ .insns = { ++ BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_1, offsetof(struct xdp_md, data)), ++ BPF_LDX_MEM(BPF_W, BPF_REG_3, BPF_REG_1, ++ offsetof(struct xdp_md, data_end)), ++ BPF_MOV64_REG(BPF_REG_1, BPF_REG_2), ++ BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, 7), ++ BPF_JMP_REG(BPF_JLT, BPF_REG_3, BPF_REG_1, 1), ++ BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_1, -7), ++ BPF_MOV64_IMM(BPF_REG_0, 0), ++ BPF_EXIT_INSN(), ++ }, ++ .errstr = "R1 offset is outside of the packet", ++ .result = REJECT, ++ .prog_type = BPF_PROG_TYPE_XDP, ++ .flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS, ++}, + { + "XDP pkt read, pkt_data' >= pkt_end, good access", + .insns = { +@@ -268,15 +410,15 @@ + .flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS, + }, + { +- "XDP pkt read, pkt_data' >= pkt_end, bad access 1", ++ "XDP pkt read, pkt_data' >= pkt_end, corner case -1, bad access", + .insns = { + BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_1, offsetof(struct xdp_md, data)), + BPF_LDX_MEM(BPF_W, BPF_REG_3, BPF_REG_1, + offsetof(struct xdp_md, data_end)), + BPF_MOV64_REG(BPF_REG_1, BPF_REG_2), +- BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, 8), ++ BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, 6), + BPF_JMP_REG(BPF_JGE, BPF_REG_1, BPF_REG_3, 1), +- BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_1, -8), ++ BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_1, -6), + BPF_MOV64_IMM(BPF_REG_0, 0), + BPF_EXIT_INSN(), + }, +@@ -304,7 +446,41 @@ + .flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS, + }, + { +- "XDP pkt read, pkt_end >= pkt_data', good access", ++ "XDP pkt read, pkt_data' >= pkt_end, corner case, good access", ++ .insns = { ++ BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_1, offsetof(struct xdp_md, data)), ++ BPF_LDX_MEM(BPF_W, BPF_REG_3, BPF_REG_1, ++ offsetof(struct xdp_md, data_end)), ++ BPF_MOV64_REG(BPF_REG_1, BPF_REG_2), ++ BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, 7), ++ BPF_JMP_REG(BPF_JGE, BPF_REG_1, BPF_REG_3, 1), ++ BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_1, -7), ++ BPF_MOV64_IMM(BPF_REG_0, 0), ++ BPF_EXIT_INSN(), ++ }, ++ .result = ACCEPT, ++ .prog_type = BPF_PROG_TYPE_XDP, ++ .flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS, ++}, ++{ ++ "XDP pkt read, pkt_data' >= pkt_end, corner case +1, good access", ++ .insns = { ++ BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_1, offsetof(struct xdp_md, data)), ++ BPF_LDX_MEM(BPF_W, BPF_REG_3, BPF_REG_1, ++ offsetof(struct xdp_md, data_end)), ++ BPF_MOV64_REG(BPF_REG_1, BPF_REG_2), ++ BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, 8), ++ BPF_JMP_REG(BPF_JGE, BPF_REG_1, BPF_REG_3, 1), ++ BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_1, -8), ++ BPF_MOV64_IMM(BPF_REG_0, 0), ++ BPF_EXIT_INSN(), ++ }, ++ .result = ACCEPT, ++ .prog_type = BPF_PROG_TYPE_XDP, ++ .flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS, ++}, ++{ ++ "XDP pkt read, pkt_end >= pkt_data', corner case, good access", + .insns = { + BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_1, offsetof(struct xdp_md, data)), + BPF_LDX_MEM(BPF_W, BPF_REG_3, BPF_REG_1, +@@ -359,7 +535,44 @@ + .flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS, + }, + { +- "XDP pkt read, pkt_data' <= pkt_end, good access", ++ "XDP pkt read, pkt_end >= pkt_data', corner case +1, good access", ++ .insns = { ++ BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_1, offsetof(struct xdp_md, data)), ++ BPF_LDX_MEM(BPF_W, BPF_REG_3, BPF_REG_1, ++ offsetof(struct xdp_md, data_end)), ++ BPF_MOV64_REG(BPF_REG_1, BPF_REG_2), ++ BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, 9), ++ BPF_JMP_REG(BPF_JGE, BPF_REG_3, BPF_REG_1, 1), ++ BPF_JMP_IMM(BPF_JA, 0, 0, 1), ++ BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_1, -9), ++ BPF_MOV64_IMM(BPF_REG_0, 0), ++ BPF_EXIT_INSN(), ++ }, ++ .result = ACCEPT, ++ .prog_type = BPF_PROG_TYPE_XDP, ++ .flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS, ++}, ++{ ++ "XDP pkt read, pkt_end >= pkt_data', corner case -1, bad access", ++ .insns = { ++ BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_1, offsetof(struct xdp_md, data)), ++ BPF_LDX_MEM(BPF_W, BPF_REG_3, BPF_REG_1, ++ offsetof(struct xdp_md, data_end)), ++ BPF_MOV64_REG(BPF_REG_1, BPF_REG_2), ++ BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, 7), ++ BPF_JMP_REG(BPF_JGE, BPF_REG_3, BPF_REG_1, 1), ++ BPF_JMP_IMM(BPF_JA, 0, 0, 1), ++ BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_1, -7), ++ BPF_MOV64_IMM(BPF_REG_0, 0), ++ BPF_EXIT_INSN(), ++ }, ++ .errstr = "R1 offset is outside of the packet", ++ .result = REJECT, ++ .prog_type = BPF_PROG_TYPE_XDP, ++ .flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS, ++}, ++{ ++ "XDP pkt read, pkt_data' <= pkt_end, corner case, good access", + .insns = { + BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_1, offsetof(struct xdp_md, data)), + BPF_LDX_MEM(BPF_W, BPF_REG_3, BPF_REG_1, +@@ -413,6 +626,43 @@ + .prog_type = BPF_PROG_TYPE_XDP, + .flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS, + }, ++{ ++ "XDP pkt read, pkt_data' <= pkt_end, corner case +1, good access", ++ .insns = { ++ BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_1, offsetof(struct xdp_md, data)), ++ BPF_LDX_MEM(BPF_W, BPF_REG_3, BPF_REG_1, ++ offsetof(struct xdp_md, data_end)), ++ BPF_MOV64_REG(BPF_REG_1, BPF_REG_2), ++ BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, 9), ++ BPF_JMP_REG(BPF_JLE, BPF_REG_1, BPF_REG_3, 1), ++ BPF_JMP_IMM(BPF_JA, 0, 0, 1), ++ BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_1, -9), ++ BPF_MOV64_IMM(BPF_REG_0, 0), ++ BPF_EXIT_INSN(), ++ }, ++ .result = ACCEPT, ++ .prog_type = BPF_PROG_TYPE_XDP, ++ .flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS, ++}, ++{ ++ "XDP pkt read, pkt_data' <= pkt_end, corner case -1, bad access", ++ .insns = { ++ BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_1, offsetof(struct xdp_md, data)), ++ BPF_LDX_MEM(BPF_W, BPF_REG_3, BPF_REG_1, ++ offsetof(struct xdp_md, data_end)), ++ BPF_MOV64_REG(BPF_REG_1, BPF_REG_2), ++ BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, 7), ++ BPF_JMP_REG(BPF_JLE, BPF_REG_1, BPF_REG_3, 1), ++ BPF_JMP_IMM(BPF_JA, 0, 0, 1), ++ BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_1, -7), ++ BPF_MOV64_IMM(BPF_REG_0, 0), ++ BPF_EXIT_INSN(), ++ }, ++ .errstr = "R1 offset is outside of the packet", ++ .result = REJECT, ++ .prog_type = BPF_PROG_TYPE_XDP, ++ .flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS, ++}, + { + "XDP pkt read, pkt_end <= pkt_data', good access", + .insns = { +@@ -431,15 +681,15 @@ + .flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS, + }, + { +- "XDP pkt read, pkt_end <= pkt_data', bad access 1", ++ "XDP pkt read, pkt_end <= pkt_data', corner case -1, bad access", + .insns = { + BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_1, offsetof(struct xdp_md, data)), + BPF_LDX_MEM(BPF_W, BPF_REG_3, BPF_REG_1, + offsetof(struct xdp_md, data_end)), + BPF_MOV64_REG(BPF_REG_1, BPF_REG_2), +- BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, 8), ++ BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, 6), + BPF_JMP_REG(BPF_JLE, BPF_REG_3, BPF_REG_1, 1), +- BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_1, -8), ++ BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_1, -6), + BPF_MOV64_IMM(BPF_REG_0, 0), + BPF_EXIT_INSN(), + }, +@@ -467,7 +717,41 @@ + .flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS, + }, + { +- "XDP pkt read, pkt_meta' > pkt_data, good access", ++ "XDP pkt read, pkt_end <= pkt_data', corner case, good access", ++ .insns = { ++ BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_1, offsetof(struct xdp_md, data)), ++ BPF_LDX_MEM(BPF_W, BPF_REG_3, BPF_REG_1, ++ offsetof(struct xdp_md, data_end)), ++ BPF_MOV64_REG(BPF_REG_1, BPF_REG_2), ++ BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, 7), ++ BPF_JMP_REG(BPF_JLE, BPF_REG_3, BPF_REG_1, 1), ++ BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_1, -7), ++ BPF_MOV64_IMM(BPF_REG_0, 0), ++ BPF_EXIT_INSN(), ++ }, ++ .result = ACCEPT, ++ .prog_type = BPF_PROG_TYPE_XDP, ++ .flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS, ++}, ++{ ++ "XDP pkt read, pkt_end <= pkt_data', corner case +1, good access", ++ .insns = { ++ BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_1, offsetof(struct xdp_md, data)), ++ BPF_LDX_MEM(BPF_W, BPF_REG_3, BPF_REG_1, ++ offsetof(struct xdp_md, data_end)), ++ BPF_MOV64_REG(BPF_REG_1, BPF_REG_2), ++ BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, 8), ++ BPF_JMP_REG(BPF_JLE, BPF_REG_3, BPF_REG_1, 1), ++ BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_1, -8), ++ BPF_MOV64_IMM(BPF_REG_0, 0), ++ BPF_EXIT_INSN(), ++ }, ++ .result = ACCEPT, ++ .prog_type = BPF_PROG_TYPE_XDP, ++ .flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS, ++}, ++{ ++ "XDP pkt read, pkt_meta' > pkt_data, corner case, good access", + .insns = { + BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_1, + offsetof(struct xdp_md, data_meta)), +@@ -519,6 +803,41 @@ + .prog_type = BPF_PROG_TYPE_XDP, + .flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS, + }, ++{ ++ "XDP pkt read, pkt_meta' > pkt_data, corner case +1, good access", ++ .insns = { ++ BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_1, ++ offsetof(struct xdp_md, data_meta)), ++ BPF_LDX_MEM(BPF_W, BPF_REG_3, BPF_REG_1, offsetof(struct xdp_md, data)), ++ BPF_MOV64_REG(BPF_REG_1, BPF_REG_2), ++ BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, 9), ++ BPF_JMP_REG(BPF_JGT, BPF_REG_1, BPF_REG_3, 1), ++ BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_1, -9), ++ BPF_MOV64_IMM(BPF_REG_0, 0), ++ BPF_EXIT_INSN(), ++ }, ++ .result = ACCEPT, ++ .prog_type = BPF_PROG_TYPE_XDP, ++ .flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS, ++}, ++{ ++ "XDP pkt read, pkt_meta' > pkt_data, corner case -1, bad access", ++ .insns = { ++ BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_1, ++ offsetof(struct xdp_md, data_meta)), ++ BPF_LDX_MEM(BPF_W, BPF_REG_3, BPF_REG_1, offsetof(struct xdp_md, data)), ++ BPF_MOV64_REG(BPF_REG_1, BPF_REG_2), ++ BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, 7), ++ BPF_JMP_REG(BPF_JGT, BPF_REG_1, BPF_REG_3, 1), ++ BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_1, -7), ++ BPF_MOV64_IMM(BPF_REG_0, 0), ++ BPF_EXIT_INSN(), ++ }, ++ .errstr = "R1 offset is outside of the packet", ++ .result = REJECT, ++ .prog_type = BPF_PROG_TYPE_XDP, ++ .flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS, ++}, + { + "XDP pkt read, pkt_data > pkt_meta', good access", + .insns = { +@@ -538,16 +857,16 @@ + .flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS, + }, + { +- "XDP pkt read, pkt_data > pkt_meta', bad access 1", ++ "XDP pkt read, pkt_data > pkt_meta', corner case -1, bad access", + .insns = { + BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_1, + offsetof(struct xdp_md, data_meta)), + BPF_LDX_MEM(BPF_W, BPF_REG_3, BPF_REG_1, offsetof(struct xdp_md, data)), + BPF_MOV64_REG(BPF_REG_1, BPF_REG_2), +- BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, 8), ++ BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, 6), + BPF_JMP_REG(BPF_JGT, BPF_REG_3, BPF_REG_1, 1), + BPF_JMP_IMM(BPF_JA, 0, 0, 1), +- BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_1, -8), ++ BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_1, -6), + BPF_MOV64_IMM(BPF_REG_0, 0), + BPF_EXIT_INSN(), + }, +@@ -574,6 +893,42 @@ + .prog_type = BPF_PROG_TYPE_XDP, + .flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS, + }, ++{ ++ "XDP pkt read, pkt_data > pkt_meta', corner case, good access", ++ .insns = { ++ BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_1, ++ offsetof(struct xdp_md, data_meta)), ++ BPF_LDX_MEM(BPF_W, BPF_REG_3, BPF_REG_1, offsetof(struct xdp_md, data)), ++ BPF_MOV64_REG(BPF_REG_1, BPF_REG_2), ++ BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, 7), ++ BPF_JMP_REG(BPF_JGT, BPF_REG_3, BPF_REG_1, 1), ++ BPF_JMP_IMM(BPF_JA, 0, 0, 1), ++ BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_1, -7), ++ BPF_MOV64_IMM(BPF_REG_0, 0), ++ BPF_EXIT_INSN(), ++ }, ++ .result = ACCEPT, ++ .prog_type = BPF_PROG_TYPE_XDP, ++ .flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS, ++}, ++{ ++ "XDP pkt read, pkt_data > pkt_meta', corner case +1, good access", ++ .insns = { ++ BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_1, ++ offsetof(struct xdp_md, data_meta)), ++ BPF_LDX_MEM(BPF_W, BPF_REG_3, BPF_REG_1, offsetof(struct xdp_md, data)), ++ BPF_MOV64_REG(BPF_REG_1, BPF_REG_2), ++ BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, 8), ++ BPF_JMP_REG(BPF_JGT, BPF_REG_3, BPF_REG_1, 1), ++ BPF_JMP_IMM(BPF_JA, 0, 0, 1), ++ BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_1, -8), ++ BPF_MOV64_IMM(BPF_REG_0, 0), ++ BPF_EXIT_INSN(), ++ }, ++ .result = ACCEPT, ++ .prog_type = BPF_PROG_TYPE_XDP, ++ .flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS, ++}, + { + "XDP pkt read, pkt_meta' < pkt_data, good access", + .insns = { +@@ -593,16 +948,16 @@ + .flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS, + }, + { +- "XDP pkt read, pkt_meta' < pkt_data, bad access 1", ++ "XDP pkt read, pkt_meta' < pkt_data, corner case -1, bad access", + .insns = { + BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_1, + offsetof(struct xdp_md, data_meta)), + BPF_LDX_MEM(BPF_W, BPF_REG_3, BPF_REG_1, offsetof(struct xdp_md, data)), + BPF_MOV64_REG(BPF_REG_1, BPF_REG_2), +- BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, 8), ++ BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, 6), + BPF_JMP_REG(BPF_JLT, BPF_REG_1, BPF_REG_3, 1), + BPF_JMP_IMM(BPF_JA, 0, 0, 1), +- BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_1, -8), ++ BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_1, -6), + BPF_MOV64_IMM(BPF_REG_0, 0), + BPF_EXIT_INSN(), + }, +@@ -630,7 +985,43 @@ + .flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS, + }, + { +- "XDP pkt read, pkt_data < pkt_meta', good access", ++ "XDP pkt read, pkt_meta' < pkt_data, corner case, good access", ++ .insns = { ++ BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_1, ++ offsetof(struct xdp_md, data_meta)), ++ BPF_LDX_MEM(BPF_W, BPF_REG_3, BPF_REG_1, offsetof(struct xdp_md, data)), ++ BPF_MOV64_REG(BPF_REG_1, BPF_REG_2), ++ BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, 7), ++ BPF_JMP_REG(BPF_JLT, BPF_REG_1, BPF_REG_3, 1), ++ BPF_JMP_IMM(BPF_JA, 0, 0, 1), ++ BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_1, -7), ++ BPF_MOV64_IMM(BPF_REG_0, 0), ++ BPF_EXIT_INSN(), ++ }, ++ .result = ACCEPT, ++ .prog_type = BPF_PROG_TYPE_XDP, ++ .flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS, ++}, ++{ ++ "XDP pkt read, pkt_meta' < pkt_data, corner case +1, good access", ++ .insns = { ++ BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_1, ++ offsetof(struct xdp_md, data_meta)), ++ BPF_LDX_MEM(BPF_W, BPF_REG_3, BPF_REG_1, offsetof(struct xdp_md, data)), ++ BPF_MOV64_REG(BPF_REG_1, BPF_REG_2), ++ BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, 8), ++ BPF_JMP_REG(BPF_JLT, BPF_REG_1, BPF_REG_3, 1), ++ BPF_JMP_IMM(BPF_JA, 0, 0, 1), ++ BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_1, -8), ++ BPF_MOV64_IMM(BPF_REG_0, 0), ++ BPF_EXIT_INSN(), ++ }, ++ .result = ACCEPT, ++ .prog_type = BPF_PROG_TYPE_XDP, ++ .flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS, ++}, ++{ ++ "XDP pkt read, pkt_data < pkt_meta', corner case, good access", + .insns = { + BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_1, + offsetof(struct xdp_md, data_meta)), +@@ -682,6 +1073,41 @@ + .prog_type = BPF_PROG_TYPE_XDP, + .flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS, + }, ++{ ++ "XDP pkt read, pkt_data < pkt_meta', corner case +1, good access", ++ .insns = { ++ BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_1, ++ offsetof(struct xdp_md, data_meta)), ++ BPF_LDX_MEM(BPF_W, BPF_REG_3, BPF_REG_1, offsetof(struct xdp_md, data)), ++ BPF_MOV64_REG(BPF_REG_1, BPF_REG_2), ++ BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, 9), ++ BPF_JMP_REG(BPF_JLT, BPF_REG_3, BPF_REG_1, 1), ++ BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_1, -9), ++ BPF_MOV64_IMM(BPF_REG_0, 0), ++ BPF_EXIT_INSN(), ++ }, ++ .result = ACCEPT, ++ .prog_type = BPF_PROG_TYPE_XDP, ++ .flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS, ++}, ++{ ++ "XDP pkt read, pkt_data < pkt_meta', corner case -1, bad access", ++ .insns = { ++ BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_1, ++ offsetof(struct xdp_md, data_meta)), ++ BPF_LDX_MEM(BPF_W, BPF_REG_3, BPF_REG_1, offsetof(struct xdp_md, data)), ++ BPF_MOV64_REG(BPF_REG_1, BPF_REG_2), ++ BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, 7), ++ BPF_JMP_REG(BPF_JLT, BPF_REG_3, BPF_REG_1, 1), ++ BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_1, -7), ++ BPF_MOV64_IMM(BPF_REG_0, 0), ++ BPF_EXIT_INSN(), ++ }, ++ .errstr = "R1 offset is outside of the packet", ++ .result = REJECT, ++ .prog_type = BPF_PROG_TYPE_XDP, ++ .flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS, ++}, + { + "XDP pkt read, pkt_meta' >= pkt_data, good access", + .insns = { +@@ -700,15 +1126,15 @@ + .flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS, + }, + { +- "XDP pkt read, pkt_meta' >= pkt_data, bad access 1", ++ "XDP pkt read, pkt_meta' >= pkt_data, corner case -1, bad access", + .insns = { + BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_1, + offsetof(struct xdp_md, data_meta)), + BPF_LDX_MEM(BPF_W, BPF_REG_3, BPF_REG_1, offsetof(struct xdp_md, data)), + BPF_MOV64_REG(BPF_REG_1, BPF_REG_2), +- BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, 8), ++ BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, 6), + BPF_JMP_REG(BPF_JGE, BPF_REG_1, BPF_REG_3, 1), +- BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_1, -8), ++ BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_1, -6), + BPF_MOV64_IMM(BPF_REG_0, 0), + BPF_EXIT_INSN(), + }, +@@ -736,7 +1162,41 @@ + .flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS, + }, + { +- "XDP pkt read, pkt_data >= pkt_meta', good access", ++ "XDP pkt read, pkt_meta' >= pkt_data, corner case, good access", ++ .insns = { ++ BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_1, ++ offsetof(struct xdp_md, data_meta)), ++ BPF_LDX_MEM(BPF_W, BPF_REG_3, BPF_REG_1, offsetof(struct xdp_md, data)), ++ BPF_MOV64_REG(BPF_REG_1, BPF_REG_2), ++ BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, 7), ++ BPF_JMP_REG(BPF_JGE, BPF_REG_1, BPF_REG_3, 1), ++ BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_1, -7), ++ BPF_MOV64_IMM(BPF_REG_0, 0), ++ BPF_EXIT_INSN(), ++ }, ++ .result = ACCEPT, ++ .prog_type = BPF_PROG_TYPE_XDP, ++ .flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS, ++}, ++{ ++ "XDP pkt read, pkt_meta' >= pkt_data, corner case +1, good access", ++ .insns = { ++ BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_1, ++ offsetof(struct xdp_md, data_meta)), ++ BPF_LDX_MEM(BPF_W, BPF_REG_3, BPF_REG_1, offsetof(struct xdp_md, data)), ++ BPF_MOV64_REG(BPF_REG_1, BPF_REG_2), ++ BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, 8), ++ BPF_JMP_REG(BPF_JGE, BPF_REG_1, BPF_REG_3, 1), ++ BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_1, -8), ++ BPF_MOV64_IMM(BPF_REG_0, 0), ++ BPF_EXIT_INSN(), ++ }, ++ .result = ACCEPT, ++ .prog_type = BPF_PROG_TYPE_XDP, ++ .flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS, ++}, ++{ ++ "XDP pkt read, pkt_data >= pkt_meta', corner case, good access", + .insns = { + BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_1, + offsetof(struct xdp_md, data_meta)), +@@ -791,7 +1251,44 @@ + .flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS, + }, + { +- "XDP pkt read, pkt_meta' <= pkt_data, good access", ++ "XDP pkt read, pkt_data >= pkt_meta', corner case +1, good access", ++ .insns = { ++ BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_1, ++ offsetof(struct xdp_md, data_meta)), ++ BPF_LDX_MEM(BPF_W, BPF_REG_3, BPF_REG_1, offsetof(struct xdp_md, data)), ++ BPF_MOV64_REG(BPF_REG_1, BPF_REG_2), ++ BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, 9), ++ BPF_JMP_REG(BPF_JGE, BPF_REG_3, BPF_REG_1, 1), ++ BPF_JMP_IMM(BPF_JA, 0, 0, 1), ++ BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_1, -9), ++ BPF_MOV64_IMM(BPF_REG_0, 0), ++ BPF_EXIT_INSN(), ++ }, ++ .result = ACCEPT, ++ .prog_type = BPF_PROG_TYPE_XDP, ++ .flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS, ++}, ++{ ++ "XDP pkt read, pkt_data >= pkt_meta', corner case -1, bad access", ++ .insns = { ++ BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_1, ++ offsetof(struct xdp_md, data_meta)), ++ BPF_LDX_MEM(BPF_W, BPF_REG_3, BPF_REG_1, offsetof(struct xdp_md, data)), ++ BPF_MOV64_REG(BPF_REG_1, BPF_REG_2), ++ BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, 7), ++ BPF_JMP_REG(BPF_JGE, BPF_REG_3, BPF_REG_1, 1), ++ BPF_JMP_IMM(BPF_JA, 0, 0, 1), ++ BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_1, -7), ++ BPF_MOV64_IMM(BPF_REG_0, 0), ++ BPF_EXIT_INSN(), ++ }, ++ .errstr = "R1 offset is outside of the packet", ++ .result = REJECT, ++ .prog_type = BPF_PROG_TYPE_XDP, ++ .flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS, ++}, ++{ ++ "XDP pkt read, pkt_meta' <= pkt_data, corner case, good access", + .insns = { + BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_1, + offsetof(struct xdp_md, data_meta)), +@@ -845,6 +1342,43 @@ + .prog_type = BPF_PROG_TYPE_XDP, + .flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS, + }, ++{ ++ "XDP pkt read, pkt_meta' <= pkt_data, corner case +1, good access", ++ .insns = { ++ BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_1, ++ offsetof(struct xdp_md, data_meta)), ++ BPF_LDX_MEM(BPF_W, BPF_REG_3, BPF_REG_1, offsetof(struct xdp_md, data)), ++ BPF_MOV64_REG(BPF_REG_1, BPF_REG_2), ++ BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, 9), ++ BPF_JMP_REG(BPF_JLE, BPF_REG_1, BPF_REG_3, 1), ++ BPF_JMP_IMM(BPF_JA, 0, 0, 1), ++ BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_1, -9), ++ BPF_MOV64_IMM(BPF_REG_0, 0), ++ BPF_EXIT_INSN(), ++ }, ++ .result = ACCEPT, ++ .prog_type = BPF_PROG_TYPE_XDP, ++ .flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS, ++}, ++{ ++ "XDP pkt read, pkt_meta' <= pkt_data, corner case -1, bad access", ++ .insns = { ++ BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_1, ++ offsetof(struct xdp_md, data_meta)), ++ BPF_LDX_MEM(BPF_W, BPF_REG_3, BPF_REG_1, offsetof(struct xdp_md, data)), ++ BPF_MOV64_REG(BPF_REG_1, BPF_REG_2), ++ BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, 7), ++ BPF_JMP_REG(BPF_JLE, BPF_REG_1, BPF_REG_3, 1), ++ BPF_JMP_IMM(BPF_JA, 0, 0, 1), ++ BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_1, -7), ++ BPF_MOV64_IMM(BPF_REG_0, 0), ++ BPF_EXIT_INSN(), ++ }, ++ .errstr = "R1 offset is outside of the packet", ++ .result = REJECT, ++ .prog_type = BPF_PROG_TYPE_XDP, ++ .flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS, ++}, + { + "XDP pkt read, pkt_data <= pkt_meta', good access", + .insns = { +@@ -863,15 +1397,15 @@ + .flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS, + }, + { +- "XDP pkt read, pkt_data <= pkt_meta', bad access 1", ++ "XDP pkt read, pkt_data <= pkt_meta', corner case -1, bad access", + .insns = { + BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_1, + offsetof(struct xdp_md, data_meta)), + BPF_LDX_MEM(BPF_W, BPF_REG_3, BPF_REG_1, offsetof(struct xdp_md, data)), + BPF_MOV64_REG(BPF_REG_1, BPF_REG_2), +- BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, 8), ++ BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, 6), + BPF_JMP_REG(BPF_JLE, BPF_REG_3, BPF_REG_1, 1), +- BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_1, -8), ++ BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_1, -6), + BPF_MOV64_IMM(BPF_REG_0, 0), + BPF_EXIT_INSN(), + }, +@@ -898,3 +1432,37 @@ + .prog_type = BPF_PROG_TYPE_XDP, + .flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS, + }, ++{ ++ "XDP pkt read, pkt_data <= pkt_meta', corner case, good access", ++ .insns = { ++ BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_1, ++ offsetof(struct xdp_md, data_meta)), ++ BPF_LDX_MEM(BPF_W, BPF_REG_3, BPF_REG_1, offsetof(struct xdp_md, data)), ++ BPF_MOV64_REG(BPF_REG_1, BPF_REG_2), ++ BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, 7), ++ BPF_JMP_REG(BPF_JLE, BPF_REG_3, BPF_REG_1, 1), ++ BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_1, -7), ++ BPF_MOV64_IMM(BPF_REG_0, 0), ++ BPF_EXIT_INSN(), ++ }, ++ .result = ACCEPT, ++ .prog_type = BPF_PROG_TYPE_XDP, ++ .flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS, ++}, ++{ ++ "XDP pkt read, pkt_data <= pkt_meta', corner case +1, good access", ++ .insns = { ++ BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_1, ++ offsetof(struct xdp_md, data_meta)), ++ BPF_LDX_MEM(BPF_W, BPF_REG_3, BPF_REG_1, offsetof(struct xdp_md, data)), ++ BPF_MOV64_REG(BPF_REG_1, BPF_REG_2), ++ BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, 8), ++ BPF_JMP_REG(BPF_JLE, BPF_REG_3, BPF_REG_1, 1), ++ BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_1, -8), ++ BPF_MOV64_IMM(BPF_REG_0, 0), ++ BPF_EXIT_INSN(), ++ }, ++ .result = ACCEPT, ++ .prog_type = BPF_PROG_TYPE_XDP, ++ .flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS, ++}, +diff --git a/tools/testing/selftests/net/fib_tests.sh b/tools/testing/selftests/net/fib_tests.sh +index 6fad54c7ecb4a..a7f53c2a9580a 100755 +--- a/tools/testing/selftests/net/fib_tests.sh ++++ b/tools/testing/selftests/net/fib_tests.sh +@@ -444,24 +444,63 @@ fib_rp_filter_test() + setup + + set -e ++ ip netns add ns2 ++ ip netns set ns2 auto ++ ++ ip -netns ns2 link set dev lo up ++ ++ $IP link add name veth1 type veth peer name veth2 ++ $IP link set dev veth2 netns ns2 ++ $IP address add 192.0.2.1/24 dev veth1 ++ ip -netns ns2 address add 192.0.2.1/24 dev veth2 ++ $IP link set dev veth1 up ++ ip -netns ns2 link set dev veth2 up ++ + $IP link set dev lo address 52:54:00:6a:c7:5e +- $IP link set dummy0 address 52:54:00:6a:c7:5e +- $IP link add dummy1 type dummy +- $IP link set dummy1 address 52:54:00:6a:c7:5e +- $IP link set dev dummy1 up ++ $IP link set dev veth1 address 52:54:00:6a:c7:5e ++ ip -netns ns2 link set dev lo address 52:54:00:6a:c7:5e ++ ip -netns ns2 link set dev veth2 address 52:54:00:6a:c7:5e ++ ++ # 1. (ns2) redirect lo's egress to veth2's egress ++ ip netns exec ns2 tc qdisc add dev lo parent root handle 1: fq_codel ++ ip netns exec ns2 tc filter add dev lo parent 1: protocol arp basic \ ++ action mirred egress redirect dev veth2 ++ ip netns exec ns2 tc filter add dev lo parent 1: protocol ip basic \ ++ action mirred egress redirect dev veth2 ++ ++ # 2. (ns1) redirect veth1's ingress to lo's ingress ++ $NS_EXEC tc qdisc add dev veth1 ingress ++ $NS_EXEC tc filter add dev veth1 ingress protocol arp basic \ ++ action mirred ingress redirect dev lo ++ $NS_EXEC tc filter add dev veth1 ingress protocol ip basic \ ++ action mirred ingress redirect dev lo ++ ++ # 3. (ns1) redirect lo's egress to veth1's egress ++ $NS_EXEC tc qdisc add dev lo parent root handle 1: fq_codel ++ $NS_EXEC tc filter add dev lo parent 1: protocol arp basic \ ++ action mirred egress redirect dev veth1 ++ $NS_EXEC tc filter add dev lo parent 1: protocol ip basic \ ++ action mirred egress redirect dev veth1 ++ ++ # 4. (ns2) redirect veth2's ingress to lo's ingress ++ ip netns exec ns2 tc qdisc add dev veth2 ingress ++ ip netns exec ns2 tc filter add dev veth2 ingress protocol arp basic \ ++ action mirred ingress redirect dev lo ++ ip netns exec ns2 tc filter add dev veth2 ingress protocol ip basic \ ++ action mirred ingress redirect dev lo ++ + $NS_EXEC sysctl -qw net.ipv4.conf.all.rp_filter=1 + $NS_EXEC sysctl -qw net.ipv4.conf.all.accept_local=1 + $NS_EXEC sysctl -qw net.ipv4.conf.all.route_localnet=1 +- +- $NS_EXEC tc qd add dev dummy1 parent root handle 1: fq_codel +- $NS_EXEC tc filter add dev dummy1 parent 1: protocol arp basic action mirred egress redirect dev lo +- $NS_EXEC tc filter add dev dummy1 parent 1: protocol ip basic action mirred egress redirect dev lo ++ ip netns exec ns2 sysctl -qw net.ipv4.conf.all.rp_filter=1 ++ ip netns exec ns2 sysctl -qw net.ipv4.conf.all.accept_local=1 ++ ip netns exec ns2 sysctl -qw net.ipv4.conf.all.route_localnet=1 + set +e + +- run_cmd "ip netns exec ns1 ping -I dummy1 -w1 -c1 198.51.100.1" ++ run_cmd "ip netns exec ns2 ping -w1 -c1 192.0.2.1" + log_test $? 0 "rp_filter passes local packets" + +- run_cmd "ip netns exec ns1 ping -I dummy1 -w1 -c1 127.0.0.1" ++ run_cmd "ip netns exec ns2 ping -w1 -c1 127.0.0.1" + log_test $? 0 "rp_filter passes loopback packets" + + cleanup +diff --git a/tools/testing/selftests/netfilter/Makefile b/tools/testing/selftests/netfilter/Makefile +index a374e10ef5065..a56cfc4f2f3fa 100644 +--- a/tools/testing/selftests/netfilter/Makefile ++++ b/tools/testing/selftests/netfilter/Makefile +@@ -4,7 +4,8 @@ + TEST_PROGS := nft_trans_stress.sh nft_nat.sh bridge_brouter.sh \ + conntrack_icmp_related.sh nft_flowtable.sh ipvs.sh \ + nft_concat_range.sh nft_conntrack_helper.sh \ +- nft_queue.sh nft_meta.sh ++ nft_queue.sh nft_meta.sh \ ++ conntrack_vrf.sh + + LDLIBS = -lmnl + TEST_GEN_FILES = nf-queue +diff --git a/tools/testing/selftests/netfilter/conntrack_vrf.sh b/tools/testing/selftests/netfilter/conntrack_vrf.sh +new file mode 100644 +index 0000000000000..8b5ea92345882 +--- /dev/null ++++ b/tools/testing/selftests/netfilter/conntrack_vrf.sh +@@ -0,0 +1,241 @@ ++#!/bin/sh ++ ++# This script demonstrates interaction of conntrack and vrf. ++# The vrf driver calls the netfilter hooks again, with oif/iif ++# pointing at the VRF device. ++# ++# For ingress, this means first iteration has iifname of lower/real ++# device. In this script, thats veth0. ++# Second iteration is iifname set to vrf device, tvrf in this script. ++# ++# For egress, this is reversed: first iteration has the vrf device, ++# second iteration is done with the lower/real/veth0 device. ++# ++# test_ct_zone_in demonstrates unexpected change of nftables ++# behavior # caused by commit 09e856d54bda5f28 "vrf: Reset skb conntrack ++# connection on VRF rcv" ++# ++# It was possible to assign conntrack zone to a packet (or mark it for ++# `notracking`) in the prerouting chain before conntrack, based on real iif. ++# ++# After the change, the zone assignment is lost and the zone is assigned based ++# on the VRF master interface (in case such a rule exists). ++# assignment is lost. Instead, assignment based on the `iif` matching ++# Thus it is impossible to distinguish packets based on the original ++# interface. ++# ++# test_masquerade_vrf and test_masquerade_veth0 demonstrate the problem ++# that was supposed to be fixed by the commit mentioned above to make sure ++# that any fix to test case 1 won't break masquerade again. ++ ++ksft_skip=4 ++ ++IP0=172.30.30.1 ++IP1=172.30.30.2 ++PFXL=30 ++ret=0 ++ ++sfx=$(mktemp -u "XXXXXXXX") ++ns0="ns0-$sfx" ++ns1="ns1-$sfx" ++ ++cleanup() ++{ ++ ip netns pids $ns0 | xargs kill 2>/dev/null ++ ip netns pids $ns1 | xargs kill 2>/dev/null ++ ++ ip netns del $ns0 $ns1 ++} ++ ++nft --version > /dev/null 2>&1 ++if [ $? -ne 0 ];then ++ echo "SKIP: Could not run test without nft tool" ++ exit $ksft_skip ++fi ++ ++ip -Version > /dev/null 2>&1 ++if [ $? -ne 0 ];then ++ echo "SKIP: Could not run test without ip tool" ++ exit $ksft_skip ++fi ++ ++ip netns add "$ns0" ++if [ $? -ne 0 ];then ++ echo "SKIP: Could not create net namespace $ns0" ++ exit $ksft_skip ++fi ++ip netns add "$ns1" ++ ++trap cleanup EXIT ++ ++ip netns exec $ns0 sysctl -q -w net.ipv4.conf.default.rp_filter=0 ++ip netns exec $ns0 sysctl -q -w net.ipv4.conf.all.rp_filter=0 ++ip netns exec $ns0 sysctl -q -w net.ipv4.conf.all.rp_filter=0 ++ ++ip link add veth0 netns "$ns0" type veth peer name veth0 netns "$ns1" > /dev/null 2>&1 ++if [ $? -ne 0 ];then ++ echo "SKIP: Could not add veth device" ++ exit $ksft_skip ++fi ++ ++ip -net $ns0 li add tvrf type vrf table 9876 ++if [ $? -ne 0 ];then ++ echo "SKIP: Could not add vrf device" ++ exit $ksft_skip ++fi ++ ++ip -net $ns0 li set lo up ++ ++ip -net $ns0 li set veth0 master tvrf ++ip -net $ns0 li set tvrf up ++ip -net $ns0 li set veth0 up ++ip -net $ns1 li set veth0 up ++ ++ip -net $ns0 addr add $IP0/$PFXL dev veth0 ++ip -net $ns1 addr add $IP1/$PFXL dev veth0 ++ ++ip netns exec $ns1 iperf3 -s > /dev/null 2>&1& ++if [ $? -ne 0 ];then ++ echo "SKIP: Could not start iperf3" ++ exit $ksft_skip ++fi ++ ++# test vrf ingress handling. ++# The incoming connection should be placed in conntrack zone 1, ++# as decided by the first iteration of the ruleset. ++test_ct_zone_in() ++{ ++ip netns exec $ns0 nft -f - <<EOF ++table testct { ++ chain rawpre { ++ type filter hook prerouting priority raw; ++ ++ iif { veth0, tvrf } counter meta nftrace set 1 ++ iif veth0 counter ct zone set 1 counter return ++ iif tvrf counter ct zone set 2 counter return ++ ip protocol icmp counter ++ notrack counter ++ } ++ ++ chain rawout { ++ type filter hook output priority raw; ++ ++ oif veth0 counter ct zone set 1 counter return ++ oif tvrf counter ct zone set 2 counter return ++ notrack counter ++ } ++} ++EOF ++ ip netns exec $ns1 ping -W 1 -c 1 -I veth0 $IP0 > /dev/null ++ ++ # should be in zone 1, not zone 2 ++ count=$(ip netns exec $ns0 conntrack -L -s $IP1 -d $IP0 -p icmp --zone 1 2>/dev/null | wc -l) ++ if [ $count -eq 1 ]; then ++ echo "PASS: entry found in conntrack zone 1" ++ else ++ echo "FAIL: entry not found in conntrack zone 1" ++ count=$(ip netns exec $ns0 conntrack -L -s $IP1 -d $IP0 -p icmp --zone 2 2> /dev/null | wc -l) ++ if [ $count -eq 1 ]; then ++ echo "FAIL: entry found in zone 2 instead" ++ else ++ echo "FAIL: entry not in zone 1 or 2, dumping table" ++ ip netns exec $ns0 conntrack -L ++ ip netns exec $ns0 nft list ruleset ++ fi ++ fi ++} ++ ++# add masq rule that gets evaluated w. outif set to vrf device. ++# This tests the first iteration of the packet through conntrack, ++# oifname is the vrf device. ++test_masquerade_vrf() ++{ ++ local qdisc=$1 ++ ++ if [ "$qdisc" != "default" ]; then ++ tc -net $ns0 qdisc add dev tvrf root $qdisc ++ fi ++ ++ ip netns exec $ns0 conntrack -F 2>/dev/null ++ ++ip netns exec $ns0 nft -f - <<EOF ++flush ruleset ++table ip nat { ++ chain rawout { ++ type filter hook output priority raw; ++ ++ oif tvrf ct state untracked counter ++ } ++ chain postrouting2 { ++ type filter hook postrouting priority mangle; ++ ++ oif tvrf ct state untracked counter ++ } ++ chain postrouting { ++ type nat hook postrouting priority 0; ++ # NB: masquerade should always be combined with 'oif(name) bla', ++ # lack of this is intentional here, we want to exercise double-snat. ++ ip saddr 172.30.30.0/30 counter masquerade random ++ } ++} ++EOF ++ ip netns exec $ns0 ip vrf exec tvrf iperf3 -t 1 -c $IP1 >/dev/null ++ if [ $? -ne 0 ]; then ++ echo "FAIL: iperf3 connect failure with masquerade + sport rewrite on vrf device" ++ ret=1 ++ return ++ fi ++ ++ # must also check that nat table was evaluated on second (lower device) iteration. ++ ip netns exec $ns0 nft list table ip nat |grep -q 'counter packets 2' && ++ ip netns exec $ns0 nft list table ip nat |grep -q 'untracked counter packets [1-9]' ++ if [ $? -eq 0 ]; then ++ echo "PASS: iperf3 connect with masquerade + sport rewrite on vrf device ($qdisc qdisc)" ++ else ++ echo "FAIL: vrf rules have unexpected counter value" ++ ret=1 ++ fi ++ ++ if [ "$qdisc" != "default" ]; then ++ tc -net $ns0 qdisc del dev tvrf root ++ fi ++} ++ ++# add masq rule that gets evaluated w. outif set to veth device. ++# This tests the 2nd iteration of the packet through conntrack, ++# oifname is the lower device (veth0 in this case). ++test_masquerade_veth() ++{ ++ ip netns exec $ns0 conntrack -F 2>/dev/null ++ip netns exec $ns0 nft -f - <<EOF ++flush ruleset ++table ip nat { ++ chain postrouting { ++ type nat hook postrouting priority 0; ++ meta oif veth0 ip saddr 172.30.30.0/30 counter masquerade random ++ } ++} ++EOF ++ ip netns exec $ns0 ip vrf exec tvrf iperf3 -t 1 -c $IP1 > /dev/null ++ if [ $? -ne 0 ]; then ++ echo "FAIL: iperf3 connect failure with masquerade + sport rewrite on veth device" ++ ret=1 ++ return ++ fi ++ ++ # must also check that nat table was evaluated on second (lower device) iteration. ++ ip netns exec $ns0 nft list table ip nat |grep -q 'counter packets 2' ++ if [ $? -eq 0 ]; then ++ echo "PASS: iperf3 connect with masquerade + sport rewrite on veth device" ++ else ++ echo "FAIL: vrf masq rule has unexpected counter value" ++ ret=1 ++ fi ++} ++ ++test_ct_zone_in ++test_masquerade_vrf "default" ++test_masquerade_vrf "pfifo" ++test_masquerade_veth ++ ++exit $ret |