summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMike Pagano <mpagano@gentoo.org>2024-03-01 08:08:58 -0500
committerMike Pagano <mpagano@gentoo.org>2024-03-01 08:08:58 -0500
commitc8d7c31185ba6c4c2569107bc4858dda52ebacfa (patch)
tree9787da676e52aa854e37779c5f07e1250a95a2ec
parentTemporary remove broken cpu opt patch (diff)
downloadlinux-patches-c8d7c31185ba6c4c2569107bc4858dda52ebacfa.tar.gz
linux-patches-c8d7c31185ba6c4c2569107bc4858dda52ebacfa.tar.bz2
linux-patches-c8d7c31185ba6c4c2569107bc4858dda52ebacfa.zip
Linux patch 5.10.2115.10-222
Signed-off-by: Mike Pagano <mpagano@gentoo.org>
-rw-r--r--0000_README4
-rw-r--r--1210_linux-5.10.211.patch7770
2 files changed, 7774 insertions, 0 deletions
diff --git a/0000_README b/0000_README
index 9f0368c8..bcc82e6d 100644
--- a/0000_README
+++ b/0000_README
@@ -883,6 +883,10 @@ Patch: 1209_linux-5.10.210.patch
From: https://www.kernel.org
Desc: Linux 5.10.210
+Patch: 1210_linux-5.10.211.patch
+From: https://www.kernel.org
+Desc: Linux 5.10.211
+
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/1210_linux-5.10.211.patch b/1210_linux-5.10.211.patch
new file mode 100644
index 00000000..bef3b1db
--- /dev/null
+++ b/1210_linux-5.10.211.patch
@@ -0,0 +1,7770 @@
+diff --git a/Makefile b/Makefile
+index 6e9ee164b9dfd..dc55a86e0f7df 100644
+--- a/Makefile
++++ b/Makefile
+@@ -1,7 +1,7 @@
+ # SPDX-License-Identifier: GPL-2.0
+ VERSION = 5
+ PATCHLEVEL = 10
+-SUBLEVEL = 210
++SUBLEVEL = 211
+ EXTRAVERSION =
+ NAME = Dare mighty things
+
+diff --git a/arch/arm/boot/dts/bcm47189-luxul-xap-1440.dts b/arch/arm/boot/dts/bcm47189-luxul-xap-1440.dts
+index 00e688b45d981..5901160919dcd 100644
+--- a/arch/arm/boot/dts/bcm47189-luxul-xap-1440.dts
++++ b/arch/arm/boot/dts/bcm47189-luxul-xap-1440.dts
+@@ -26,7 +26,6 @@ leds {
+ wlan {
+ label = "bcm53xx:blue:wlan";
+ gpios = <&chipcommon 10 GPIO_ACTIVE_LOW>;
+- linux,default-trigger = "default-off";
+ };
+
+ system {
+diff --git a/arch/arm/boot/dts/bcm47189-luxul-xap-810.dts b/arch/arm/boot/dts/bcm47189-luxul-xap-810.dts
+index 78c80a5d3f4fa..8e7483272d47d 100644
+--- a/arch/arm/boot/dts/bcm47189-luxul-xap-810.dts
++++ b/arch/arm/boot/dts/bcm47189-luxul-xap-810.dts
+@@ -26,7 +26,6 @@ leds {
+ 5ghz {
+ label = "bcm53xx:blue:5ghz";
+ gpios = <&chipcommon 11 GPIO_ACTIVE_HIGH>;
+- linux,default-trigger = "default-off";
+ };
+
+ system {
+@@ -42,7 +41,6 @@ pcie0_leds {
+ 2ghz {
+ label = "bcm53xx:blue:2ghz";
+ gpios = <&pcie0_chipcommon 3 GPIO_ACTIVE_HIGH>;
+- linux,default-trigger = "default-off";
+ };
+ };
+
+diff --git a/arch/arm/boot/dts/imx6sx.dtsi b/arch/arm/boot/dts/imx6sx.dtsi
+index 08332f70a8dc2..51491b7418e40 100644
+--- a/arch/arm/boot/dts/imx6sx.dtsi
++++ b/arch/arm/boot/dts/imx6sx.dtsi
+@@ -981,6 +981,8 @@ usdhc1: mmc@2190000 {
+ <&clks IMX6SX_CLK_USDHC1>;
+ clock-names = "ipg", "ahb", "per";
+ bus-width = <4>;
++ fsl,tuning-start-tap = <20>;
++ fsl,tuning-step= <2>;
+ status = "disabled";
+ };
+
+@@ -993,6 +995,8 @@ usdhc2: mmc@2194000 {
+ <&clks IMX6SX_CLK_USDHC2>;
+ clock-names = "ipg", "ahb", "per";
+ bus-width = <4>;
++ fsl,tuning-start-tap = <20>;
++ fsl,tuning-step= <2>;
+ status = "disabled";
+ };
+
+@@ -1005,6 +1009,8 @@ usdhc3: mmc@2198000 {
+ <&clks IMX6SX_CLK_USDHC3>;
+ clock-names = "ipg", "ahb", "per";
+ bus-width = <4>;
++ fsl,tuning-start-tap = <20>;
++ fsl,tuning-step= <2>;
+ status = "disabled";
+ };
+
+diff --git a/arch/arm/mach-ep93xx/core.c b/arch/arm/mach-ep93xx/core.c
+index 6fb19a393fd2e..c06ae33dc53ec 100644
+--- a/arch/arm/mach-ep93xx/core.c
++++ b/arch/arm/mach-ep93xx/core.c
+@@ -337,6 +337,7 @@ static struct gpiod_lookup_table ep93xx_i2c_gpiod_table = {
+ GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN),
+ GPIO_LOOKUP_IDX("G", 0, NULL, 1,
+ GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN),
++ { }
+ },
+ };
+
+diff --git a/arch/arm64/boot/dts/rockchip/px30.dtsi b/arch/arm64/boot/dts/rockchip/px30.dtsi
+index 0d6761074b11a..f241e7c318bcd 100644
+--- a/arch/arm64/boot/dts/rockchip/px30.dtsi
++++ b/arch/arm64/boot/dts/rockchip/px30.dtsi
+@@ -577,6 +577,7 @@ spi0: spi@ff1d0000 {
+ clock-names = "spiclk", "apb_pclk";
+ dmas = <&dmac 12>, <&dmac 13>;
+ dma-names = "tx", "rx";
++ num-cs = <2>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&spi0_clk &spi0_csn &spi0_miso &spi0_mosi>;
+ #address-cells = <1>;
+@@ -592,6 +593,7 @@ spi1: spi@ff1d8000 {
+ clock-names = "spiclk", "apb_pclk";
+ dmas = <&dmac 14>, <&dmac 15>;
+ dma-names = "tx", "rx";
++ num-cs = <2>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&spi1_clk &spi1_csn0 &spi1_csn1 &spi1_miso &spi1_mosi>;
+ #address-cells = <1>;
+diff --git a/arch/arm64/kvm/vgic/vgic-its.c b/arch/arm64/kvm/vgic/vgic-its.c
+index 62f261b8eb62f..93c0365cdd7b7 100644
+--- a/arch/arm64/kvm/vgic/vgic-its.c
++++ b/arch/arm64/kvm/vgic/vgic-its.c
+@@ -462,6 +462,9 @@ static int its_sync_lpi_pending_table(struct kvm_vcpu *vcpu)
+ }
+
+ irq = vgic_get_irq(vcpu->kvm, NULL, intids[i]);
++ if (!irq)
++ continue;
++
+ raw_spin_lock_irqsave(&irq->irq_lock, flags);
+ irq->pending_latch = pendmask & (1U << bit_nr);
+ vgic_queue_irq_unlock(vcpu->kvm, irq, flags);
+@@ -1374,6 +1377,8 @@ static int vgic_its_cmd_handle_movall(struct kvm *kvm, struct vgic_its *its,
+
+ for (i = 0; i < irq_count; i++) {
+ irq = vgic_get_irq(kvm, NULL, intids[i]);
++ if (!irq)
++ continue;
+
+ update_affinity(irq, vcpu2);
+
+diff --git a/arch/powerpc/kernel/hw_breakpoint.c b/arch/powerpc/kernel/hw_breakpoint.c
+index 6e5bed50c3578..ca3374c6f3749 100644
+--- a/arch/powerpc/kernel/hw_breakpoint.c
++++ b/arch/powerpc/kernel/hw_breakpoint.c
+@@ -504,6 +504,11 @@ static bool is_larx_stcx_instr(int type)
+ return type == LARX || type == STCX;
+ }
+
++static bool is_octword_vsx_instr(int type, int size)
++{
++ return ((type == LOAD_VSX || type == STORE_VSX) && size == 32);
++}
++
+ /*
+ * We've failed in reliably handling the hw-breakpoint. Unregister
+ * it and throw a warning message to let the user know about it.
+@@ -554,6 +559,63 @@ static bool stepping_handler(struct pt_regs *regs, struct perf_event **bp,
+ return true;
+ }
+
++static void handle_p10dd1_spurious_exception(struct arch_hw_breakpoint **info,
++ int *hit, unsigned long ea)
++{
++ int i;
++ unsigned long hw_end_addr;
++
++ /*
++ * Handle spurious exception only when any bp_per_reg is set.
++ * Otherwise this might be created by xmon and not actually a
++ * spurious exception.
++ */
++ for (i = 0; i < nr_wp_slots(); i++) {
++ if (!info[i])
++ continue;
++
++ hw_end_addr = ALIGN(info[i]->address + info[i]->len, HW_BREAKPOINT_SIZE);
++
++ /*
++ * Ending address of DAWR range is less than starting
++ * address of op.
++ */
++ if ((hw_end_addr - 1) >= ea)
++ continue;
++
++ /*
++ * Those addresses need to be in the same or in two
++ * consecutive 512B blocks;
++ */
++ if (((hw_end_addr - 1) >> 10) != (ea >> 10))
++ continue;
++
++ /*
++ * 'op address + 64B' generates an address that has a
++ * carry into bit 52 (crosses 2K boundary).
++ */
++ if ((ea & 0x800) == ((ea + 64) & 0x800))
++ continue;
++
++ break;
++ }
++
++ if (i == nr_wp_slots())
++ return;
++
++ for (i = 0; i < nr_wp_slots(); i++) {
++ if (info[i]) {
++ hit[i] = 1;
++ info[i]->type |= HW_BRK_TYPE_EXTRANEOUS_IRQ;
++ }
++ }
++}
++
++/*
++ * Handle a DABR or DAWR exception.
++ *
++ * Called in atomic context.
++ */
+ int hw_breakpoint_handler(struct die_args *args)
+ {
+ bool err = false;
+@@ -612,8 +674,14 @@ int hw_breakpoint_handler(struct die_args *args)
+ goto reset;
+
+ if (!nr_hit) {
+- rc = NOTIFY_DONE;
+- goto out;
++ /* Workaround for Power10 DD1 */
++ if (!IS_ENABLED(CONFIG_PPC_8xx) && mfspr(SPRN_PVR) == 0x800100 &&
++ is_octword_vsx_instr(type, size)) {
++ handle_p10dd1_spurious_exception(info, hit, ea);
++ } else {
++ rc = NOTIFY_DONE;
++ goto out;
++ }
+ }
+
+ /*
+@@ -674,6 +742,8 @@ NOKPROBE_SYMBOL(hw_breakpoint_handler);
+
+ /*
+ * Handle single-step exceptions following a DABR hit.
++ *
++ * Called in atomic context.
+ */
+ static int single_step_dabr_instruction(struct die_args *args)
+ {
+@@ -731,6 +801,8 @@ NOKPROBE_SYMBOL(single_step_dabr_instruction);
+
+ /*
+ * Handle debug exception notifications.
++ *
++ * Called in atomic context.
+ */
+ int hw_breakpoint_exceptions_notify(
+ struct notifier_block *unused, unsigned long val, void *data)
+diff --git a/arch/s390/pci/pci.c b/arch/s390/pci/pci.c
+index 74799439b2598..beecc36c30276 100644
+--- a/arch/s390/pci/pci.c
++++ b/arch/s390/pci/pci.c
+@@ -225,7 +225,7 @@ resource_size_t pcibios_align_resource(void *data, const struct resource *res,
+ /* combine single writes by using store-block insn */
+ void __iowrite64_copy(void __iomem *to, const void *from, size_t count)
+ {
+- zpci_memcpy_toio(to, from, count);
++ zpci_memcpy_toio(to, from, count * 8);
+ }
+
+ static void __iomem *__ioremap(phys_addr_t addr, size_t size, pgprot_t prot)
+diff --git a/arch/x86/include/asm/cpu_entry_area.h b/arch/x86/include/asm/cpu_entry_area.h
+index dd5ea1bdf04c5..75efc4c6f0766 100644
+--- a/arch/x86/include/asm/cpu_entry_area.h
++++ b/arch/x86/include/asm/cpu_entry_area.h
+@@ -143,7 +143,7 @@ extern void cea_set_pte(void *cea_vaddr, phys_addr_t pa, pgprot_t flags);
+
+ extern struct cpu_entry_area *get_cpu_entry_area(int cpu);
+
+-static inline struct entry_stack *cpu_entry_stack(int cpu)
++static __always_inline struct entry_stack *cpu_entry_stack(int cpu)
+ {
+ return &get_cpu_entry_area(cpu)->entry_stack_page.stack;
+ }
+diff --git a/arch/x86/include/asm/nospec-branch.h b/arch/x86/include/asm/nospec-branch.h
+index 7b4782249a925..7711ba5342a1a 100644
+--- a/arch/x86/include/asm/nospec-branch.h
++++ b/arch/x86/include/asm/nospec-branch.h
+@@ -207,6 +207,8 @@ extern void srso_alias_untrain_ret(void);
+ extern void entry_untrain_ret(void);
+ extern void entry_ibpb(void);
+
++extern void (*x86_return_thunk)(void);
++
+ #ifdef CONFIG_RETPOLINE
+
+ typedef u8 retpoline_thunk_t[RETPOLINE_THUNK_SIZE];
+diff --git a/arch/x86/include/asm/text-patching.h b/arch/x86/include/asm/text-patching.h
+index b7421780e4e92..c6015b4074614 100644
+--- a/arch/x86/include/asm/text-patching.h
++++ b/arch/x86/include/asm/text-patching.h
+@@ -96,24 +96,40 @@ union text_poke_insn {
+ };
+
+ static __always_inline
+-void *text_gen_insn(u8 opcode, const void *addr, const void *dest)
++void __text_gen_insn(void *buf, u8 opcode, const void *addr, const void *dest, int size)
+ {
+- static union text_poke_insn insn; /* per instance */
+- int size = text_opcode_size(opcode);
++ union text_poke_insn *insn = buf;
++
++ BUG_ON(size < text_opcode_size(opcode));
++
++ /*
++ * Hide the addresses to avoid the compiler folding in constants when
++ * referencing code, these can mess up annotations like
++ * ANNOTATE_NOENDBR.
++ */
++ OPTIMIZER_HIDE_VAR(insn);
++ OPTIMIZER_HIDE_VAR(addr);
++ OPTIMIZER_HIDE_VAR(dest);
+
+- insn.opcode = opcode;
++ insn->opcode = opcode;
+
+ if (size > 1) {
+- insn.disp = (long)dest - (long)(addr + size);
++ insn->disp = (long)dest - (long)(addr + size);
+ if (size == 2) {
+ /*
+- * Ensure that for JMP9 the displacement
++ * Ensure that for JMP8 the displacement
+ * actually fits the signed byte.
+ */
+- BUG_ON((insn.disp >> 31) != (insn.disp >> 7));
++ BUG_ON((insn->disp >> 31) != (insn->disp >> 7));
+ }
+ }
++}
+
++static __always_inline
++void *text_gen_insn(u8 opcode, const void *addr, const void *dest)
++{
++ static union text_poke_insn insn; /* per instance */
++ __text_gen_insn(&insn, opcode, addr, dest, text_opcode_size(opcode));
+ return &insn.text;
+ }
+
+diff --git a/arch/x86/include/asm/uaccess.h b/arch/x86/include/asm/uaccess.h
+index bf2561a5eb581..3616fd4ba3953 100644
+--- a/arch/x86/include/asm/uaccess.h
++++ b/arch/x86/include/asm/uaccess.h
+@@ -414,6 +414,103 @@ do { \
+
+ #endif // CONFIG_CC_ASM_GOTO_OUTPUT
+
++#ifdef CONFIG_CC_HAS_ASM_GOTO_TIED_OUTPUT
++#define __try_cmpxchg_user_asm(itype, ltype, _ptr, _pold, _new, label) ({ \
++ bool success; \
++ __typeof__(_ptr) _old = (__typeof__(_ptr))(_pold); \
++ __typeof__(*(_ptr)) __old = *_old; \
++ __typeof__(*(_ptr)) __new = (_new); \
++ asm_volatile_goto("\n" \
++ "1: " LOCK_PREFIX "cmpxchg"itype" %[new], %[ptr]\n"\
++ _ASM_EXTABLE_UA(1b, %l[label]) \
++ : CC_OUT(z) (success), \
++ [ptr] "+m" (*_ptr), \
++ [old] "+a" (__old) \
++ : [new] ltype (__new) \
++ : "memory" \
++ : label); \
++ if (unlikely(!success)) \
++ *_old = __old; \
++ likely(success); })
++
++#ifdef CONFIG_X86_32
++#define __try_cmpxchg64_user_asm(_ptr, _pold, _new, label) ({ \
++ bool success; \
++ __typeof__(_ptr) _old = (__typeof__(_ptr))(_pold); \
++ __typeof__(*(_ptr)) __old = *_old; \
++ __typeof__(*(_ptr)) __new = (_new); \
++ asm_volatile_goto("\n" \
++ "1: " LOCK_PREFIX "cmpxchg8b %[ptr]\n" \
++ _ASM_EXTABLE_UA(1b, %l[label]) \
++ : CC_OUT(z) (success), \
++ "+A" (__old), \
++ [ptr] "+m" (*_ptr) \
++ : "b" ((u32)__new), \
++ "c" ((u32)((u64)__new >> 32)) \
++ : "memory" \
++ : label); \
++ if (unlikely(!success)) \
++ *_old = __old; \
++ likely(success); })
++#endif // CONFIG_X86_32
++#else // !CONFIG_CC_HAS_ASM_GOTO_TIED_OUTPUT
++#define __try_cmpxchg_user_asm(itype, ltype, _ptr, _pold, _new, label) ({ \
++ int __err = 0; \
++ bool success; \
++ __typeof__(_ptr) _old = (__typeof__(_ptr))(_pold); \
++ __typeof__(*(_ptr)) __old = *_old; \
++ __typeof__(*(_ptr)) __new = (_new); \
++ asm volatile("\n" \
++ "1: " LOCK_PREFIX "cmpxchg"itype" %[new], %[ptr]\n"\
++ CC_SET(z) \
++ "2:\n" \
++ _ASM_EXTABLE_TYPE_REG(1b, 2b, EX_TYPE_EFAULT_REG, \
++ %[errout]) \
++ : CC_OUT(z) (success), \
++ [errout] "+r" (__err), \
++ [ptr] "+m" (*_ptr), \
++ [old] "+a" (__old) \
++ : [new] ltype (__new) \
++ : "memory"); \
++ if (unlikely(__err)) \
++ goto label; \
++ if (unlikely(!success)) \
++ *_old = __old; \
++ likely(success); })
++
++#ifdef CONFIG_X86_32
++/*
++ * Unlike the normal CMPXCHG, hardcode ECX for both success/fail and error.
++ * There are only six GPRs available and four (EAX, EBX, ECX, and EDX) are
++ * hardcoded by CMPXCHG8B, leaving only ESI and EDI. If the compiler uses
++ * both ESI and EDI for the memory operand, compilation will fail if the error
++ * is an input+output as there will be no register available for input.
++ */
++#define __try_cmpxchg64_user_asm(_ptr, _pold, _new, label) ({ \
++ int __result; \
++ __typeof__(_ptr) _old = (__typeof__(_ptr))(_pold); \
++ __typeof__(*(_ptr)) __old = *_old; \
++ __typeof__(*(_ptr)) __new = (_new); \
++ asm volatile("\n" \
++ "1: " LOCK_PREFIX "cmpxchg8b %[ptr]\n" \
++ "mov $0, %%ecx\n\t" \
++ "setz %%cl\n" \
++ "2:\n" \
++ _ASM_EXTABLE_TYPE_REG(1b, 2b, EX_TYPE_EFAULT_REG, %%ecx) \
++ : [result]"=c" (__result), \
++ "+A" (__old), \
++ [ptr] "+m" (*_ptr) \
++ : "b" ((u32)__new), \
++ "c" ((u32)((u64)__new >> 32)) \
++ : "memory", "cc"); \
++ if (unlikely(__result < 0)) \
++ goto label; \
++ if (unlikely(!__result)) \
++ *_old = __old; \
++ likely(__result); })
++#endif // CONFIG_X86_32
++#endif // CONFIG_CC_HAS_ASM_GOTO_TIED_OUTPUT
++
+ /* FIXME: this hack is definitely wrong -AK */
+ struct __large_struct { unsigned long buf[100]; };
+ #define __m(x) (*(struct __large_struct __user *)(x))
+@@ -506,6 +603,51 @@ do { \
+ } while (0)
+ #endif // CONFIG_CC_HAS_ASM_GOTO_OUTPUT
+
++extern void __try_cmpxchg_user_wrong_size(void);
++
++#ifndef CONFIG_X86_32
++#define __try_cmpxchg64_user_asm(_ptr, _oldp, _nval, _label) \
++ __try_cmpxchg_user_asm("q", "r", (_ptr), (_oldp), (_nval), _label)
++#endif
++
++/*
++ * Force the pointer to u<size> to match the size expected by the asm helper.
++ * clang/LLVM compiles all cases and only discards the unused paths after
++ * processing errors, which breaks i386 if the pointer is an 8-byte value.
++ */
++#define unsafe_try_cmpxchg_user(_ptr, _oldp, _nval, _label) ({ \
++ bool __ret; \
++ __chk_user_ptr(_ptr); \
++ switch (sizeof(*(_ptr))) { \
++ case 1: __ret = __try_cmpxchg_user_asm("b", "q", \
++ (__force u8 *)(_ptr), (_oldp), \
++ (_nval), _label); \
++ break; \
++ case 2: __ret = __try_cmpxchg_user_asm("w", "r", \
++ (__force u16 *)(_ptr), (_oldp), \
++ (_nval), _label); \
++ break; \
++ case 4: __ret = __try_cmpxchg_user_asm("l", "r", \
++ (__force u32 *)(_ptr), (_oldp), \
++ (_nval), _label); \
++ break; \
++ case 8: __ret = __try_cmpxchg64_user_asm((__force u64 *)(_ptr), (_oldp),\
++ (_nval), _label); \
++ break; \
++ default: __try_cmpxchg_user_wrong_size(); \
++ } \
++ __ret; })
++
++/* "Returns" 0 on success, 1 on failure, -EFAULT if the access faults. */
++#define __try_cmpxchg_user(_ptr, _oldp, _nval, _label) ({ \
++ int __ret = -EFAULT; \
++ __uaccess_begin_nospec(); \
++ __ret = !unsafe_try_cmpxchg_user(_ptr, _oldp, _nval, _label); \
++_label: \
++ __uaccess_end(); \
++ __ret; \
++ })
++
+ /*
+ * We want the unsafe accessors to always be inlined and use
+ * the error labels - thus the macro games.
+diff --git a/arch/x86/kernel/alternative.c b/arch/x86/kernel/alternative.c
+index 9e0a3daa838c2..9ceef8515c031 100644
+--- a/arch/x86/kernel/alternative.c
++++ b/arch/x86/kernel/alternative.c
+@@ -676,6 +676,7 @@ void __init_or_module noinline apply_retpolines(s32 *start, s32 *end)
+ }
+
+ #ifdef CONFIG_RETHUNK
++
+ /*
+ * Rewrite the compiler generated return thunk tail-calls.
+ *
+@@ -691,14 +692,18 @@ static int patch_return(void *addr, struct insn *insn, u8 *bytes)
+ {
+ int i = 0;
+
+- if (cpu_feature_enabled(X86_FEATURE_RETHUNK))
+- return -1;
++ if (cpu_feature_enabled(X86_FEATURE_RETHUNK)) {
++ if (x86_return_thunk == __x86_return_thunk)
++ return -1;
+
+- bytes[i++] = RET_INSN_OPCODE;
++ i = JMP32_INSN_SIZE;
++ __text_gen_insn(bytes, JMP32_INSN_OPCODE, addr, x86_return_thunk, i);
++ } else {
++ bytes[i++] = RET_INSN_OPCODE;
++ }
+
+ for (; i < insn->length;)
+ bytes[i++] = INT3_INSN_OPCODE;
+-
+ return i;
+ }
+
+diff --git a/arch/x86/kernel/ftrace.c b/arch/x86/kernel/ftrace.c
+index 6d546f4426ac3..46447877b5941 100644
+--- a/arch/x86/kernel/ftrace.c
++++ b/arch/x86/kernel/ftrace.c
+@@ -367,10 +367,8 @@ create_trampoline(struct ftrace_ops *ops, unsigned int *tramp_size)
+ goto fail;
+
+ ip = trampoline + size;
+-
+- /* The trampoline ends with ret(q) */
+ if (cpu_feature_enabled(X86_FEATURE_RETHUNK))
+- memcpy(ip, text_gen_insn(JMP32_INSN_OPCODE, ip, &__x86_return_thunk), JMP32_INSN_SIZE);
++ __text_gen_insn(ip, JMP32_INSN_OPCODE, ip, x86_return_thunk, JMP32_INSN_SIZE);
+ else
+ memcpy(ip, retq, sizeof(retq));
+
+diff --git a/arch/x86/kernel/paravirt.c b/arch/x86/kernel/paravirt.c
+index e21937680d1f2..5bea8d93883a2 100644
+--- a/arch/x86/kernel/paravirt.c
++++ b/arch/x86/kernel/paravirt.c
+@@ -55,28 +55,16 @@ void __init default_banner(void)
+ static const unsigned char ud2a[] = { 0x0f, 0x0b };
+
+ struct branch {
+- unsigned char opcode;
+- u32 delta;
++ unsigned char opcode;
++ u32 delta;
+ } __attribute__((packed));
+
+ static unsigned paravirt_patch_call(void *insn_buff, const void *target,
+ unsigned long addr, unsigned len)
+ {
+- const int call_len = 5;
+- struct branch *b = insn_buff;
+- unsigned long delta = (unsigned long)target - (addr+call_len);
+-
+- if (len < call_len) {
+- pr_warn("paravirt: Failed to patch indirect CALL at %ps\n", (void *)addr);
+- /* Kernel might not be viable if patching fails, bail out: */
+- BUG_ON(1);
+- }
+-
+- b->opcode = 0xe8; /* call */
+- b->delta = delta;
+- BUILD_BUG_ON(sizeof(*b) != call_len);
+-
+- return call_len;
++ __text_gen_insn(insn_buff, CALL_INSN_OPCODE,
++ (void *)addr, target, CALL_INSN_SIZE);
++ return CALL_INSN_SIZE;
+ }
+
+ #ifdef CONFIG_PARAVIRT_XXL
+diff --git a/arch/x86/kernel/static_call.c b/arch/x86/kernel/static_call.c
+index 759b986b7f033..273e9b77b7302 100644
+--- a/arch/x86/kernel/static_call.c
++++ b/arch/x86/kernel/static_call.c
+@@ -41,7 +41,7 @@ static void __ref __static_call_transform(void *insn, enum insn_type type,
+
+ case RET:
+ if (cpu_feature_enabled(X86_FEATURE_RETHUNK))
+- code = text_gen_insn(JMP32_INSN_OPCODE, insn, &__x86_return_thunk);
++ code = text_gen_insn(JMP32_INSN_OPCODE, insn, x86_return_thunk);
+ else
+ code = &retinsn;
+ break;
+diff --git a/arch/x86/net/bpf_jit_comp.c b/arch/x86/net/bpf_jit_comp.c
+index 8e3c3d8916dd2..d7d592c092983 100644
+--- a/arch/x86/net/bpf_jit_comp.c
++++ b/arch/x86/net/bpf_jit_comp.c
+@@ -405,7 +405,7 @@ static void emit_return(u8 **pprog, u8 *ip)
+ int cnt = 0;
+
+ if (cpu_feature_enabled(X86_FEATURE_RETHUNK)) {
+- emit_jump(&prog, &__x86_return_thunk, ip);
++ emit_jump(&prog, x86_return_thunk, ip);
+ } else {
+ EMIT1(0xC3); /* ret */
+ if (IS_ENABLED(CONFIG_SLS))
+diff --git a/drivers/ata/ahci.c b/drivers/ata/ahci.c
+index 4297a8d69dbf7..6f7f8e41404dc 100644
+--- a/drivers/ata/ahci.c
++++ b/drivers/ata/ahci.c
+@@ -49,6 +49,7 @@ enum {
+ enum board_ids {
+ /* board IDs by feature in alphabetical order */
+ board_ahci,
++ board_ahci_43bit_dma,
+ board_ahci_ign_iferr,
+ board_ahci_low_power,
+ board_ahci_no_debounce_delay,
+@@ -129,6 +130,13 @@ static const struct ata_port_info ahci_port_info[] = {
+ .udma_mask = ATA_UDMA6,
+ .port_ops = &ahci_ops,
+ },
++ [board_ahci_43bit_dma] = {
++ AHCI_HFLAGS (AHCI_HFLAG_43BIT_ONLY),
++ .flags = AHCI_FLAG_COMMON,
++ .pio_mask = ATA_PIO4,
++ .udma_mask = ATA_UDMA6,
++ .port_ops = &ahci_ops,
++ },
+ [board_ahci_ign_iferr] = {
+ AHCI_HFLAGS (AHCI_HFLAG_IGN_IRQ_IF_ERR),
+ .flags = AHCI_FLAG_COMMON,
+@@ -594,11 +602,11 @@ static const struct pci_device_id ahci_pci_tbl[] = {
+ { PCI_VDEVICE(PROMISE, 0x3f20), board_ahci }, /* PDC42819 */
+ { PCI_VDEVICE(PROMISE, 0x3781), board_ahci }, /* FastTrak TX8660 ahci-mode */
+
+- /* Asmedia */
++ /* ASMedia */
+ { PCI_VDEVICE(ASMEDIA, 0x0601), board_ahci }, /* ASM1060 */
+ { PCI_VDEVICE(ASMEDIA, 0x0602), board_ahci }, /* ASM1060 */
+- { PCI_VDEVICE(ASMEDIA, 0x0611), board_ahci }, /* ASM1061 */
+- { PCI_VDEVICE(ASMEDIA, 0x0612), board_ahci }, /* ASM1062 */
++ { PCI_VDEVICE(ASMEDIA, 0x0611), board_ahci_43bit_dma }, /* ASM1061 */
++ { PCI_VDEVICE(ASMEDIA, 0x0612), board_ahci_43bit_dma }, /* ASM1061/1062 */
+ { PCI_VDEVICE(ASMEDIA, 0x0621), board_ahci }, /* ASM1061R */
+ { PCI_VDEVICE(ASMEDIA, 0x0622), board_ahci }, /* ASM1062R */
+
+@@ -654,6 +662,11 @@ MODULE_PARM_DESC(mobile_lpm_policy, "Default LPM policy for mobile chipsets");
+ static void ahci_pci_save_initial_config(struct pci_dev *pdev,
+ struct ahci_host_priv *hpriv)
+ {
++ if (pdev->vendor == PCI_VENDOR_ID_ASMEDIA && pdev->device == 0x1166) {
++ dev_info(&pdev->dev, "ASM1166 has only six ports\n");
++ hpriv->saved_port_map = 0x3f;
++ }
++
+ if (pdev->vendor == PCI_VENDOR_ID_JMICRON && pdev->device == 0x2361) {
+ dev_info(&pdev->dev, "JMB361 has only one port\n");
+ hpriv->force_port_map = 1;
+@@ -946,11 +959,20 @@ static int ahci_pci_device_resume(struct device *dev)
+
+ #endif /* CONFIG_PM */
+
+-static int ahci_configure_dma_masks(struct pci_dev *pdev, int using_dac)
++static int ahci_configure_dma_masks(struct pci_dev *pdev,
++ struct ahci_host_priv *hpriv)
+ {
+- const int dma_bits = using_dac ? 64 : 32;
++ int dma_bits;
+ int rc;
+
++ if (hpriv->cap & HOST_CAP_64) {
++ dma_bits = 64;
++ if (hpriv->flags & AHCI_HFLAG_43BIT_ONLY)
++ dma_bits = 43;
++ } else {
++ dma_bits = 32;
++ }
++
+ /*
+ * If the device fixup already set the dma_mask to some non-standard
+ * value, don't extend it here. This happens on STA2X11, for example.
+@@ -1928,7 +1950,7 @@ static int ahci_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
+ ahci_gtf_filter_workaround(host);
+
+ /* initialize adapter */
+- rc = ahci_configure_dma_masks(pdev, hpriv->cap & HOST_CAP_64);
++ rc = ahci_configure_dma_masks(pdev, hpriv);
+ if (rc)
+ return rc;
+
+diff --git a/drivers/ata/ahci.h b/drivers/ata/ahci.h
+index 7cc6feb17e972..b8db2b0d74146 100644
+--- a/drivers/ata/ahci.h
++++ b/drivers/ata/ahci.h
+@@ -244,6 +244,7 @@ enum {
+ AHCI_HFLAG_IGN_NOTSUPP_POWER_ON = BIT(27), /* ignore -EOPNOTSUPP
+ from phy_power_on() */
+ AHCI_HFLAG_NO_SXS = BIT(28), /* SXS not supported */
++ AHCI_HFLAG_43BIT_ONLY = BIT(29), /* 43bit DMA addr limit */
+
+ /* ap->flags bits */
+
+diff --git a/drivers/block/ataflop.c b/drivers/block/ataflop.c
+index 3e881fdb06e0a..224450c90e459 100644
+--- a/drivers/block/ataflop.c
++++ b/drivers/block/ataflop.c
+@@ -456,10 +456,20 @@ static DEFINE_TIMER(fd_timer, check_change);
+
+ static void fd_end_request_cur(blk_status_t err)
+ {
++ DPRINT(("fd_end_request_cur(), bytes %d of %d\n",
++ blk_rq_cur_bytes(fd_request),
++ blk_rq_bytes(fd_request)));
++
+ if (!blk_update_request(fd_request, err,
+ blk_rq_cur_bytes(fd_request))) {
++ DPRINT(("calling __blk_mq_end_request()\n"));
+ __blk_mq_end_request(fd_request, err);
+ fd_request = NULL;
++ } else {
++ /* requeue rest of request */
++ DPRINT(("calling blk_mq_requeue_request()\n"));
++ blk_mq_requeue_request(fd_request, true);
++ fd_request = NULL;
+ }
+ }
+
+@@ -653,9 +663,6 @@ static inline void copy_buffer(void *from, void *to)
+ *p2++ = *p1++;
+ }
+
+-
+-
+-
+ /* General Interrupt Handling */
+
+ static void (*FloppyIRQHandler)( int status ) = NULL;
+@@ -700,12 +707,21 @@ static void fd_error( void )
+ if (fd_request->error_count >= MAX_ERRORS) {
+ printk(KERN_ERR "fd%d: too many errors.\n", SelectedDrive );
+ fd_end_request_cur(BLK_STS_IOERR);
++ finish_fdc();
++ return;
+ }
+ else if (fd_request->error_count == RECALIBRATE_ERRORS) {
+ printk(KERN_WARNING "fd%d: recalibrating\n", SelectedDrive );
+ if (SelectedDrive != -1)
+ SUD.track = -1;
+ }
++ /* need to re-run request to recalibrate */
++ atari_disable_irq( IRQ_MFP_FDC );
++
++ setup_req_params( SelectedDrive );
++ do_fd_action( SelectedDrive );
++
++ atari_enable_irq( IRQ_MFP_FDC );
+ }
+
+
+@@ -740,6 +756,7 @@ static int do_format(int drive, int type, struct atari_format_descr *desc)
+ if (type) {
+ if (--type >= NUM_DISK_MINORS ||
+ minor2disktype[type].drive_types > DriveType) {
++ finish_fdc();
+ ret = -EINVAL;
+ goto out;
+ }
+@@ -748,6 +765,7 @@ static int do_format(int drive, int type, struct atari_format_descr *desc)
+ }
+
+ if (!UDT || desc->track >= UDT->blocks/UDT->spt/2 || desc->head >= 2) {
++ finish_fdc();
+ ret = -EINVAL;
+ goto out;
+ }
+@@ -788,6 +806,7 @@ static int do_format(int drive, int type, struct atari_format_descr *desc)
+
+ wait_for_completion(&format_wait);
+
++ finish_fdc();
+ ret = FormatError ? -EIO : 0;
+ out:
+ blk_mq_unquiesce_queue(q);
+@@ -822,6 +841,7 @@ static void do_fd_action( int drive )
+ else {
+ /* all sectors finished */
+ fd_end_request_cur(BLK_STS_OK);
++ finish_fdc();
+ return;
+ }
+ }
+@@ -1226,6 +1246,7 @@ static void fd_rwsec_done1(int status)
+ else {
+ /* all sectors finished */
+ fd_end_request_cur(BLK_STS_OK);
++ finish_fdc();
+ }
+ return;
+
+@@ -1347,7 +1368,7 @@ static void fd_times_out(struct timer_list *unused)
+
+ static void finish_fdc( void )
+ {
+- if (!NeedSeek) {
++ if (!NeedSeek || !stdma_is_locked_by(floppy_irq)) {
+ finish_fdc_done( 0 );
+ }
+ else {
+@@ -1382,7 +1403,8 @@ static void finish_fdc_done( int dummy )
+ start_motor_off_timer();
+
+ local_irq_save(flags);
+- stdma_release();
++ if (stdma_is_locked_by(floppy_irq))
++ stdma_release();
+ local_irq_restore(flags);
+
+ DPRINT(("finish_fdc() finished\n"));
+@@ -1472,15 +1494,6 @@ static void setup_req_params( int drive )
+ ReqTrack, ReqSector, (unsigned long)ReqData ));
+ }
+
+-static void ataflop_commit_rqs(struct blk_mq_hw_ctx *hctx)
+-{
+- spin_lock_irq(&ataflop_lock);
+- atari_disable_irq(IRQ_MFP_FDC);
+- finish_fdc();
+- atari_enable_irq(IRQ_MFP_FDC);
+- spin_unlock_irq(&ataflop_lock);
+-}
+-
+ static blk_status_t ataflop_queue_rq(struct blk_mq_hw_ctx *hctx,
+ const struct blk_mq_queue_data *bd)
+ {
+@@ -1488,6 +1501,10 @@ static blk_status_t ataflop_queue_rq(struct blk_mq_hw_ctx *hctx,
+ int drive = floppy - unit;
+ int type = floppy->type;
+
++ DPRINT(("Queue request: drive %d type %d sectors %d of %d last %d\n",
++ drive, type, blk_rq_cur_sectors(bd->rq),
++ blk_rq_sectors(bd->rq), bd->last));
++
+ spin_lock_irq(&ataflop_lock);
+ if (fd_request) {
+ spin_unlock_irq(&ataflop_lock);
+@@ -1508,6 +1525,7 @@ static blk_status_t ataflop_queue_rq(struct blk_mq_hw_ctx *hctx,
+ /* drive not connected */
+ printk(KERN_ERR "Unknown Device: fd%d\n", drive );
+ fd_end_request_cur(BLK_STS_IOERR);
++ stdma_release();
+ goto out;
+ }
+
+@@ -1524,11 +1542,13 @@ static blk_status_t ataflop_queue_rq(struct blk_mq_hw_ctx *hctx,
+ if (--type >= NUM_DISK_MINORS) {
+ printk(KERN_WARNING "fd%d: invalid disk format", drive );
+ fd_end_request_cur(BLK_STS_IOERR);
++ stdma_release();
+ goto out;
+ }
+ if (minor2disktype[type].drive_types > DriveType) {
+ printk(KERN_WARNING "fd%d: unsupported disk format", drive );
+ fd_end_request_cur(BLK_STS_IOERR);
++ stdma_release();
+ goto out;
+ }
+ type = minor2disktype[type].index;
+@@ -1547,8 +1567,6 @@ static blk_status_t ataflop_queue_rq(struct blk_mq_hw_ctx *hctx,
+ setup_req_params( drive );
+ do_fd_action( drive );
+
+- if (bd->last)
+- finish_fdc();
+ atari_enable_irq( IRQ_MFP_FDC );
+
+ out:
+@@ -1631,6 +1649,7 @@ static int fd_locked_ioctl(struct block_device *bdev, fmode_t mode,
+ /* what if type > 0 here? Overwrite specified entry ? */
+ if (type) {
+ /* refuse to re-set a predefined type for now */
++ finish_fdc();
+ return -EINVAL;
+ }
+
+@@ -1698,8 +1717,10 @@ static int fd_locked_ioctl(struct block_device *bdev, fmode_t mode,
+
+ /* sanity check */
+ if (setprm.track != dtp->blocks/dtp->spt/2 ||
+- setprm.head != 2)
++ setprm.head != 2) {
++ finish_fdc();
+ return -EINVAL;
++ }
+
+ UDT = dtp;
+ set_capacity(floppy->disk, UDT->blocks);
+@@ -1959,7 +1980,6 @@ static const struct block_device_operations floppy_fops = {
+
+ static const struct blk_mq_ops ataflop_mq_ops = {
+ .queue_rq = ataflop_queue_rq,
+- .commit_rqs = ataflop_commit_rqs,
+ };
+
+ static struct kobject *floppy_find(dev_t dev, int *part, void *data)
+diff --git a/drivers/block/virtio_blk.c b/drivers/block/virtio_blk.c
+index 9b54eec9b17eb..7eae3f3732336 100644
+--- a/drivers/block/virtio_blk.c
++++ b/drivers/block/virtio_blk.c
+@@ -952,14 +952,15 @@ static int virtblk_freeze(struct virtio_device *vdev)
+ {
+ struct virtio_blk *vblk = vdev->priv;
+
++ /* Ensure no requests in virtqueues before deleting vqs. */
++ blk_mq_freeze_queue(vblk->disk->queue);
++
+ /* Ensure we don't receive any more interrupts */
+ vdev->config->reset(vdev);
+
+ /* Make sure no work handler is accessing the device. */
+ flush_work(&vblk->config_work);
+
+- blk_mq_quiesce_queue(vblk->disk->queue);
+-
+ vdev->config->del_vqs(vdev);
+ kfree(vblk->vqs);
+
+@@ -977,7 +978,7 @@ static int virtblk_restore(struct virtio_device *vdev)
+
+ virtio_device_ready(vdev);
+
+- blk_mq_unquiesce_queue(vblk->disk->queue);
++ blk_mq_unfreeze_queue(vblk->disk->queue);
+ return 0;
+ }
+ #endif
+diff --git a/drivers/dma/fsl-qdma.c b/drivers/dma/fsl-qdma.c
+index 69385f32e2756..f383f219ed008 100644
+--- a/drivers/dma/fsl-qdma.c
++++ b/drivers/dma/fsl-qdma.c
+@@ -805,7 +805,7 @@ fsl_qdma_irq_init(struct platform_device *pdev,
+ int i;
+ int cpu;
+ int ret;
+- char irq_name[20];
++ char irq_name[32];
+
+ fsl_qdma->error_irq =
+ platform_get_irq_byname(pdev, "qdma-error");
+diff --git a/drivers/dma/sh/shdma.h b/drivers/dma/sh/shdma.h
+index 9c121a4b33ad8..f97d80343aea4 100644
+--- a/drivers/dma/sh/shdma.h
++++ b/drivers/dma/sh/shdma.h
+@@ -25,7 +25,7 @@ struct sh_dmae_chan {
+ const struct sh_dmae_slave_config *config; /* Slave DMA configuration */
+ int xmit_shift; /* log_2(bytes_per_xfer) */
+ void __iomem *base;
+- char dev_id[16]; /* unique name per DMAC of channel */
++ char dev_id[32]; /* unique name per DMAC of channel */
+ int pm_error;
+ dma_addr_t slave_addr;
+ };
+diff --git a/drivers/dma/ti/edma.c b/drivers/dma/ti/edma.c
+index a1adc8d91fd8d..69292d4a0c441 100644
+--- a/drivers/dma/ti/edma.c
++++ b/drivers/dma/ti/edma.c
+@@ -2462,6 +2462,11 @@ static int edma_probe(struct platform_device *pdev)
+ if (irq > 0) {
+ irq_name = devm_kasprintf(dev, GFP_KERNEL, "%s_ccint",
+ dev_name(dev));
++ if (!irq_name) {
++ ret = -ENOMEM;
++ goto err_disable_pm;
++ }
++
+ ret = devm_request_irq(dev, irq, dma_irq_handler, 0, irq_name,
+ ecc);
+ if (ret) {
+@@ -2478,6 +2483,11 @@ static int edma_probe(struct platform_device *pdev)
+ if (irq > 0) {
+ irq_name = devm_kasprintf(dev, GFP_KERNEL, "%s_ccerrint",
+ dev_name(dev));
++ if (!irq_name) {
++ ret = -ENOMEM;
++ goto err_disable_pm;
++ }
++
+ ret = devm_request_irq(dev, irq, dma_ccerr_handler, 0, irq_name,
+ ecc);
+ if (ret) {
+diff --git a/drivers/firewire/core-card.c b/drivers/firewire/core-card.c
+index f3b3953cac834..be195ba834632 100644
+--- a/drivers/firewire/core-card.c
++++ b/drivers/firewire/core-card.c
+@@ -429,7 +429,23 @@ static void bm_work(struct work_struct *work)
+ */
+ card->bm_generation = generation;
+
+- if (root_device == NULL) {
++ if (card->gap_count == 0) {
++ /*
++ * If self IDs have inconsistent gap counts, do a
++ * bus reset ASAP. The config rom read might never
++ * complete, so don't wait for it. However, still
++ * send a PHY configuration packet prior to the
++ * bus reset. The PHY configuration packet might
++ * fail, but 1394-2008 8.4.5.2 explicitly permits
++ * it in this case, so it should be safe to try.
++ */
++ new_root_id = local_id;
++ /*
++ * We must always send a bus reset if the gap count
++ * is inconsistent, so bypass the 5-reset limit.
++ */
++ card->bm_retries = 0;
++ } else if (root_device == NULL) {
+ /*
+ * Either link_on is false, or we failed to read the
+ * config rom. In either case, pick another root.
+diff --git a/drivers/firmware/efi/arm-runtime.c b/drivers/firmware/efi/arm-runtime.c
+index 3359ae2adf24b..9054c2852580d 100644
+--- a/drivers/firmware/efi/arm-runtime.c
++++ b/drivers/firmware/efi/arm-runtime.c
+@@ -107,7 +107,7 @@ static int __init arm_enable_runtime_services(void)
+ efi_memory_desc_t *md;
+
+ for_each_efi_memory_desc(md) {
+- int md_size = md->num_pages << EFI_PAGE_SHIFT;
++ u64 md_size = md->num_pages << EFI_PAGE_SHIFT;
+ struct resource *res;
+
+ if (!(md->attribute & EFI_MEMORY_SP))
+diff --git a/drivers/firmware/efi/efi-init.c b/drivers/firmware/efi/efi-init.c
+index f55a92ff12c0f..86da3c7a5036a 100644
+--- a/drivers/firmware/efi/efi-init.c
++++ b/drivers/firmware/efi/efi-init.c
+@@ -141,15 +141,6 @@ static __init int is_usable_memory(efi_memory_desc_t *md)
+ case EFI_BOOT_SERVICES_DATA:
+ case EFI_CONVENTIONAL_MEMORY:
+ case EFI_PERSISTENT_MEMORY:
+- /*
+- * Special purpose memory is 'soft reserved', which means it
+- * is set aside initially, but can be hotplugged back in or
+- * be assigned to the dax driver after boot.
+- */
+- if (efi_soft_reserve_enabled() &&
+- (md->attribute & EFI_MEMORY_SP))
+- return false;
+-
+ /*
+ * According to the spec, these regions are no longer reserved
+ * after calling ExitBootServices(). However, we can only use
+@@ -194,6 +185,16 @@ static __init void reserve_regions(void)
+ size = npages << PAGE_SHIFT;
+
+ if (is_memory(md)) {
++ /*
++ * Special purpose memory is 'soft reserved', which
++ * means it is set aside initially. Don't add a memblock
++ * for it now so that it can be hotplugged back in or
++ * be assigned to the dax driver after boot.
++ */
++ if (efi_soft_reserve_enabled() &&
++ (md->attribute & EFI_MEMORY_SP))
++ continue;
++
+ early_init_dt_add_memory_arch(paddr, size);
+
+ if (!is_usable_memory(md))
+diff --git a/drivers/firmware/efi/riscv-runtime.c b/drivers/firmware/efi/riscv-runtime.c
+index d28e715d2bcc8..6711e64eb0b16 100644
+--- a/drivers/firmware/efi/riscv-runtime.c
++++ b/drivers/firmware/efi/riscv-runtime.c
+@@ -85,7 +85,7 @@ static int __init riscv_enable_runtime_services(void)
+ efi_memory_desc_t *md;
+
+ for_each_efi_memory_desc(md) {
+- int md_size = md->num_pages << EFI_PAGE_SHIFT;
++ u64 md_size = md->num_pages << EFI_PAGE_SHIFT;
+ struct resource *res;
+
+ if (!(md->attribute & EFI_MEMORY_SP))
+diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
+index 54d6b4128721e..3578e3b3536e3 100644
+--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
++++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
+@@ -1456,6 +1456,7 @@ static int dm_sw_fini(void *handle)
+
+ if (adev->dm.dmub_srv) {
+ dmub_srv_destroy(adev->dm.dmub_srv);
++ kfree(adev->dm.dmub_srv);
+ adev->dm.dmub_srv = NULL;
+ }
+
+diff --git a/drivers/gpu/drm/drm_syncobj.c b/drivers/gpu/drm/drm_syncobj.c
+index 738e60139db90..6ce446cc88780 100644
+--- a/drivers/gpu/drm/drm_syncobj.c
++++ b/drivers/gpu/drm/drm_syncobj.c
+@@ -387,6 +387,15 @@ int drm_syncobj_find_fence(struct drm_file *file_private,
+ if (!syncobj)
+ return -ENOENT;
+
++ /* Waiting for userspace with locks help is illegal cause that can
++ * trivial deadlock with page faults for example. Make lockdep complain
++ * about it early on.
++ */
++ if (flags & DRM_SYNCOBJ_WAIT_FLAGS_WAIT_FOR_SUBMIT) {
++ might_sleep();
++ lockdep_assert_none_held_once();
++ }
++
+ *fence = drm_syncobj_fence_get(syncobj);
+
+ if (*fence) {
+@@ -951,6 +960,10 @@ static signed long drm_syncobj_array_wait_timeout(struct drm_syncobj **syncobjs,
+ uint64_t *points;
+ uint32_t signaled_count, i;
+
++ if (flags & (DRM_SYNCOBJ_WAIT_FLAGS_WAIT_FOR_SUBMIT |
++ DRM_SYNCOBJ_WAIT_FLAGS_WAIT_AVAILABLE))
++ lockdep_assert_none_held_once();
++
+ points = kmalloc_array(count, sizeof(*points), GFP_KERNEL);
+ if (points == NULL)
+ return -ENOMEM;
+@@ -1017,7 +1030,8 @@ static signed long drm_syncobj_array_wait_timeout(struct drm_syncobj **syncobjs,
+ * fallthough and try a 0 timeout wait!
+ */
+
+- if (flags & DRM_SYNCOBJ_WAIT_FLAGS_WAIT_FOR_SUBMIT) {
++ if (flags & (DRM_SYNCOBJ_WAIT_FLAGS_WAIT_FOR_SUBMIT |
++ DRM_SYNCOBJ_WAIT_FLAGS_WAIT_AVAILABLE)) {
+ for (i = 0; i < count; ++i)
+ drm_syncobj_fence_add_wait(syncobjs[i], &entries[i]);
+ }
+diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/bios/shadow.c b/drivers/gpu/drm/nouveau/nvkm/subdev/bios/shadow.c
+index 4b571cc6bc70f..6597def18627e 100644
+--- a/drivers/gpu/drm/nouveau/nvkm/subdev/bios/shadow.c
++++ b/drivers/gpu/drm/nouveau/nvkm/subdev/bios/shadow.c
+@@ -154,11 +154,17 @@ shadow_fw_init(struct nvkm_bios *bios, const char *name)
+ return (void *)fw;
+ }
+
++static void
++shadow_fw_release(void *fw)
++{
++ release_firmware(fw);
++}
++
+ static const struct nvbios_source
+ shadow_fw = {
+ .name = "firmware",
+ .init = shadow_fw_init,
+- .fini = (void(*)(void *))release_firmware,
++ .fini = shadow_fw_release,
+ .read = shadow_fw_read,
+ .rw = false,
+ };
+diff --git a/drivers/hwmon/coretemp.c b/drivers/hwmon/coretemp.c
+index d67d972d18aa2..cbe2f874b5e2f 100644
+--- a/drivers/hwmon/coretemp.c
++++ b/drivers/hwmon/coretemp.c
+@@ -40,7 +40,7 @@ MODULE_PARM_DESC(tjmax, "TjMax value in degrees Celsius");
+
+ #define PKG_SYSFS_ATTR_NO 1 /* Sysfs attribute for package temp */
+ #define BASE_SYSFS_ATTR_NO 2 /* Sysfs Base attr no for coretemp */
+-#define NUM_REAL_CORES 128 /* Number of Real cores per cpu */
++#define NUM_REAL_CORES 512 /* Number of Real cores per cpu */
+ #define CORETEMP_NAME_LENGTH 28 /* String Length of attrs */
+ #define MAX_CORE_ATTRS 4 /* Maximum no of basic attrs */
+ #define TOTAL_ATTRS (MAX_CORE_ATTRS + 1)
+diff --git a/drivers/infiniband/hw/bnxt_re/ib_verbs.c b/drivers/infiniband/hw/bnxt_re/ib_verbs.c
+index 2a973a1390a4a..a0d7777acb6d4 100644
+--- a/drivers/infiniband/hw/bnxt_re/ib_verbs.c
++++ b/drivers/infiniband/hw/bnxt_re/ib_verbs.c
+@@ -1711,7 +1711,7 @@ int bnxt_re_modify_srq(struct ib_srq *ib_srq, struct ib_srq_attr *srq_attr,
+ switch (srq_attr_mask) {
+ case IB_SRQ_MAX_WR:
+ /* SRQ resize is not supported */
+- break;
++ return -EINVAL;
+ case IB_SRQ_LIMIT:
+ /* Change the SRQ threshold */
+ if (srq_attr->srq_limit > srq->qplib_srq.max_wqe)
+@@ -1726,13 +1726,12 @@ int bnxt_re_modify_srq(struct ib_srq *ib_srq, struct ib_srq_attr *srq_attr,
+ /* On success, update the shadow */
+ srq->srq_limit = srq_attr->srq_limit;
+ /* No need to Build and send response back to udata */
+- break;
++ return 0;
+ default:
+ ibdev_err(&rdev->ibdev,
+ "Unsupported srq_attr_mask 0x%x", srq_attr_mask);
+ return -EINVAL;
+ }
+- return 0;
+ }
+
+ int bnxt_re_query_srq(struct ib_srq *ib_srq, struct ib_srq_attr *srq_attr)
+diff --git a/drivers/infiniband/hw/hfi1/pio.c b/drivers/infiniband/hw/hfi1/pio.c
+index 60eb3a64518f3..969004258692b 100644
+--- a/drivers/infiniband/hw/hfi1/pio.c
++++ b/drivers/infiniband/hw/hfi1/pio.c
+@@ -2131,7 +2131,7 @@ int init_credit_return(struct hfi1_devdata *dd)
+ "Unable to allocate credit return DMA range for NUMA %d\n",
+ i);
+ ret = -ENOMEM;
+- goto done;
++ goto free_cr_base;
+ }
+ }
+ set_dev_node(&dd->pcidev->dev, dd->node);
+@@ -2139,6 +2139,10 @@ int init_credit_return(struct hfi1_devdata *dd)
+ ret = 0;
+ done:
+ return ret;
++
++free_cr_base:
++ free_credit_return(dd);
++ goto done;
+ }
+
+ void free_credit_return(struct hfi1_devdata *dd)
+diff --git a/drivers/infiniband/hw/hfi1/sdma.c b/drivers/infiniband/hw/hfi1/sdma.c
+index 2dc97de434a5e..68a8557e9a7c4 100644
+--- a/drivers/infiniband/hw/hfi1/sdma.c
++++ b/drivers/infiniband/hw/hfi1/sdma.c
+@@ -3200,7 +3200,7 @@ int _pad_sdma_tx_descs(struct hfi1_devdata *dd, struct sdma_txreq *tx)
+ {
+ int rval = 0;
+
+- if ((unlikely(tx->num_desc + 1 == tx->desc_limit))) {
++ if ((unlikely(tx->num_desc == tx->desc_limit))) {
+ rval = _extend_sdma_tx_descs(dd, tx);
+ if (rval) {
+ __sdma_txclean(dd, tx);
+diff --git a/drivers/infiniband/hw/qedr/verbs.c b/drivers/infiniband/hw/qedr/verbs.c
+index 3543b9af10b7a..d382ac21159c2 100644
+--- a/drivers/infiniband/hw/qedr/verbs.c
++++ b/drivers/infiniband/hw/qedr/verbs.c
+@@ -1865,8 +1865,17 @@ static int qedr_create_user_qp(struct qedr_dev *dev,
+ /* RQ - read access only (0) */
+ rc = qedr_init_user_queue(udata, dev, &qp->urq, ureq.rq_addr,
+ ureq.rq_len, true, 0, alloc_and_init);
+- if (rc)
++ if (rc) {
++ ib_umem_release(qp->usq.umem);
++ qp->usq.umem = NULL;
++ if (rdma_protocol_roce(&dev->ibdev, 1)) {
++ qedr_free_pbl(dev, &qp->usq.pbl_info,
++ qp->usq.pbl_tbl);
++ } else {
++ kfree(qp->usq.pbl_tbl);
++ }
+ return rc;
++ }
+ }
+
+ memset(&in_params, 0, sizeof(in_params));
+diff --git a/drivers/infiniband/ulp/srpt/ib_srpt.c b/drivers/infiniband/ulp/srpt/ib_srpt.c
+index 983f59c87b79f..41abf9cf11c67 100644
+--- a/drivers/infiniband/ulp/srpt/ib_srpt.c
++++ b/drivers/infiniband/ulp/srpt/ib_srpt.c
+@@ -79,12 +79,16 @@ module_param(srpt_srq_size, int, 0444);
+ MODULE_PARM_DESC(srpt_srq_size,
+ "Shared receive queue (SRQ) size.");
+
++static int srpt_set_u64_x(const char *buffer, const struct kernel_param *kp)
++{
++ return kstrtou64(buffer, 16, (u64 *)kp->arg);
++}
+ static int srpt_get_u64_x(char *buffer, const struct kernel_param *kp)
+ {
+ return sprintf(buffer, "0x%016llx\n", *(u64 *)kp->arg);
+ }
+-module_param_call(srpt_service_guid, NULL, srpt_get_u64_x, &srpt_service_guid,
+- 0444);
++module_param_call(srpt_service_guid, srpt_set_u64_x, srpt_get_u64_x,
++ &srpt_service_guid, 0444);
+ MODULE_PARM_DESC(srpt_service_guid,
+ "Using this value for ioc_guid, id_ext, and cm_listen_id instead of using the node_guid of the first HCA.");
+
+@@ -210,10 +214,12 @@ static const char *get_ch_state_name(enum rdma_ch_state s)
+ /**
+ * srpt_qp_event - QP event callback function
+ * @event: Description of the event that occurred.
+- * @ch: SRPT RDMA channel.
++ * @ptr: SRPT RDMA channel.
+ */
+-static void srpt_qp_event(struct ib_event *event, struct srpt_rdma_ch *ch)
++static void srpt_qp_event(struct ib_event *event, void *ptr)
+ {
++ struct srpt_rdma_ch *ch = ptr;
++
+ pr_debug("QP event %d on ch=%p sess_name=%s-%d state=%s\n",
+ event->event, ch, ch->sess_name, ch->qp->qp_num,
+ get_ch_state_name(ch->state));
+@@ -1803,8 +1809,7 @@ static int srpt_create_ch_ib(struct srpt_rdma_ch *ch)
+ ch->cq_size = ch->rq_size + sq_size;
+
+ qp_init->qp_context = (void *)ch;
+- qp_init->event_handler
+- = (void(*)(struct ib_event *, void*))srpt_qp_event;
++ qp_init->event_handler = srpt_qp_event;
+ qp_init->send_cq = ch->cq;
+ qp_init->recv_cq = ch->cq;
+ qp_init->sq_sig_type = IB_SIGNAL_REQ_WR;
+diff --git a/drivers/input/serio/i8042-acpipnpio.h b/drivers/input/serio/i8042-acpipnpio.h
+index cd21c92a6b2cd..6804970d8f51a 100644
+--- a/drivers/input/serio/i8042-acpipnpio.h
++++ b/drivers/input/serio/i8042-acpipnpio.h
+@@ -625,6 +625,14 @@ static const struct dmi_system_id i8042_dmi_quirk_table[] __initconst = {
+ },
+ .driver_data = (void *)(SERIO_QUIRK_NOAUX)
+ },
++ {
++ /* Fujitsu Lifebook U728 */
++ .matches = {
++ DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU"),
++ DMI_MATCH(DMI_PRODUCT_NAME, "LIFEBOOK U728"),
++ },
++ .driver_data = (void *)(SERIO_QUIRK_NOAUX)
++ },
+ {
+ /* Gigabyte M912 */
+ .matches = {
+diff --git a/drivers/irqchip/irq-mips-gic.c b/drivers/irqchip/irq-mips-gic.c
+index fc25b900cef71..7888e3c08df40 100644
+--- a/drivers/irqchip/irq-mips-gic.c
++++ b/drivers/irqchip/irq-mips-gic.c
+@@ -398,6 +398,8 @@ static void gic_all_vpes_irq_cpu_online(void)
+ unsigned int intr = local_intrs[i];
+ struct gic_all_vpes_chip_data *cd;
+
++ if (!gic_local_irq_is_routable(intr))
++ continue;
+ cd = &gic_all_vpes_chip_data[intr];
+ write_gic_vl_map(mips_gic_vx_map_reg(intr), cd->map);
+ if (cd->mask)
+diff --git a/drivers/md/dm-crypt.c b/drivers/md/dm-crypt.c
+index 5d772f322a245..5edcdcee91c23 100644
+--- a/drivers/md/dm-crypt.c
++++ b/drivers/md/dm-crypt.c
+@@ -2064,6 +2064,12 @@ static void kcryptd_crypt_write_convert(struct dm_crypt_io *io)
+ io->ctx.bio_out = clone;
+ io->ctx.iter_out = clone->bi_iter;
+
++ if (crypt_integrity_aead(cc)) {
++ bio_copy_data(clone, io->base_bio);
++ io->ctx.bio_in = clone;
++ io->ctx.iter_in = clone->bi_iter;
++ }
++
+ sector += bio_sectors(clone);
+
+ crypt_inc_pending(io);
+diff --git a/drivers/media/pci/ttpci/av7110_av.c b/drivers/media/pci/ttpci/av7110_av.c
+index ea9f7d0058a21..e201d5a56bc65 100644
+--- a/drivers/media/pci/ttpci/av7110_av.c
++++ b/drivers/media/pci/ttpci/av7110_av.c
+@@ -822,10 +822,10 @@ static int write_ts_to_decoder(struct av7110 *av7110, int type, const u8 *buf, s
+ av7110_ipack_flush(ipack);
+
+ if (buf[3] & ADAPT_FIELD) {
++ if (buf[4] > len - 1 - 4)
++ return 0;
+ len -= buf[4] + 1;
+ buf += buf[4] + 1;
+- if (!len)
+- return 0;
+ }
+
+ av7110_ipack_instant_repack(buf + 4, len - 4, ipack);
+diff --git a/drivers/mtd/nand/spi/macronix.c b/drivers/mtd/nand/spi/macronix.c
+index cd7a9cacc3fbf..8bd3f6bf9b103 100644
+--- a/drivers/mtd/nand/spi/macronix.c
++++ b/drivers/mtd/nand/spi/macronix.c
+@@ -119,6 +119,26 @@ static const struct spinand_info macronix_spinand_table[] = {
+ &update_cache_variants),
+ SPINAND_HAS_QE_BIT,
+ SPINAND_ECCINFO(&mx35lfxge4ab_ooblayout, NULL)),
++ SPINAND_INFO("MX35LF2GE4AD",
++ SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0x26),
++ NAND_MEMORG(1, 2048, 64, 64, 2048, 40, 1, 1, 1),
++ NAND_ECCREQ(8, 512),
++ SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
++ &write_cache_variants,
++ &update_cache_variants),
++ 0,
++ SPINAND_ECCINFO(&mx35lfxge4ab_ooblayout,
++ mx35lf1ge4ab_ecc_get_status)),
++ SPINAND_INFO("MX35LF4GE4AD",
++ SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0x37),
++ NAND_MEMORG(1, 4096, 128, 64, 2048, 40, 1, 1, 1),
++ NAND_ECCREQ(8, 512),
++ SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
++ &write_cache_variants,
++ &update_cache_variants),
++ 0,
++ SPINAND_ECCINFO(&mx35lfxge4ab_ooblayout,
++ mx35lf1ge4ab_ecc_get_status)),
+ SPINAND_INFO("MX31LF1GE4BC",
+ SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0x1e),
+ NAND_MEMORG(1, 2048, 64, 64, 1024, 20, 1, 1, 1),
+diff --git a/drivers/net/ethernet/microchip/lan743x_ethtool.c b/drivers/net/ethernet/microchip/lan743x_ethtool.c
+index dcde496da7fb4..c5de8f46cdd35 100644
+--- a/drivers/net/ethernet/microchip/lan743x_ethtool.c
++++ b/drivers/net/ethernet/microchip/lan743x_ethtool.c
+@@ -780,7 +780,9 @@ static void lan743x_ethtool_get_wol(struct net_device *netdev,
+
+ wol->supported = 0;
+ wol->wolopts = 0;
+- phy_ethtool_get_wol(netdev->phydev, wol);
++
++ if (netdev->phydev)
++ phy_ethtool_get_wol(netdev->phydev, wol);
+
+ wol->supported |= WAKE_BCAST | WAKE_UCAST | WAKE_MCAST |
+ WAKE_MAGIC | WAKE_PHY | WAKE_ARP;
+@@ -809,9 +811,8 @@ static int lan743x_ethtool_set_wol(struct net_device *netdev,
+
+ device_set_wakeup_enable(&adapter->pdev->dev, (bool)wol->wolopts);
+
+- phy_ethtool_set_wol(netdev->phydev, wol);
+-
+- return 0;
++ return netdev->phydev ? phy_ethtool_set_wol(netdev->phydev, wol)
++ : -ENETDOWN;
+ }
+ #endif /* CONFIG_PM */
+
+diff --git a/drivers/net/gtp.c b/drivers/net/gtp.c
+index ed247cba22916..9534f58368ccb 100644
+--- a/drivers/net/gtp.c
++++ b/drivers/net/gtp.c
+@@ -1410,20 +1410,20 @@ static int __init gtp_init(void)
+ if (err < 0)
+ goto error_out;
+
+- err = genl_register_family(&gtp_genl_family);
++ err = register_pernet_subsys(&gtp_net_ops);
+ if (err < 0)
+ goto unreg_rtnl_link;
+
+- err = register_pernet_subsys(&gtp_net_ops);
++ err = genl_register_family(&gtp_genl_family);
+ if (err < 0)
+- goto unreg_genl_family;
++ goto unreg_pernet_subsys;
+
+ pr_info("GTP module loaded (pdp ctx size %zd bytes)\n",
+ sizeof(struct pdp_ctx));
+ return 0;
+
+-unreg_genl_family:
+- genl_unregister_family(&gtp_genl_family);
++unreg_pernet_subsys:
++ unregister_pernet_subsys(&gtp_net_ops);
+ unreg_rtnl_link:
+ rtnl_link_unregister(&gtp_link_ops);
+ error_out:
+diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c b/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c
+index d2c6fdb702732..08008b0c0637c 100644
+--- a/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c
++++ b/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c
+@@ -5155,8 +5155,7 @@ void iwl_mvm_sync_rx_queues_internal(struct iwl_mvm *mvm,
+
+ if (notif->sync) {
+ notif->cookie = mvm->queue_sync_cookie;
+- atomic_set(&mvm->queue_sync_counter,
+- mvm->trans->num_rx_queues);
++ mvm->queue_sync_state = (1 << mvm->trans->num_rx_queues) - 1;
+ }
+
+ ret = iwl_mvm_notify_rx_queue(mvm, qmask, (u8 *)notif,
+@@ -5169,16 +5168,19 @@ void iwl_mvm_sync_rx_queues_internal(struct iwl_mvm *mvm,
+ if (notif->sync) {
+ lockdep_assert_held(&mvm->mutex);
+ ret = wait_event_timeout(mvm->rx_sync_waitq,
+- atomic_read(&mvm->queue_sync_counter) == 0 ||
++ READ_ONCE(mvm->queue_sync_state) == 0 ||
+ iwl_mvm_is_radio_killed(mvm),
+ HZ);
+- WARN_ON_ONCE(!ret && !iwl_mvm_is_radio_killed(mvm));
++ WARN_ONCE(!ret && !iwl_mvm_is_radio_killed(mvm),
++ "queue sync: failed to sync, state is 0x%lx\n",
++ mvm->queue_sync_state);
+ }
+
+ out:
+- atomic_set(&mvm->queue_sync_counter, 0);
+- if (notif->sync)
++ if (notif->sync) {
++ mvm->queue_sync_state = 0;
+ mvm->queue_sync_cookie++;
++ }
+ }
+
+ static void iwl_mvm_sync_rx_queues(struct ieee80211_hw *hw)
+diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h b/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h
+index 64f5a4cb3d3ac..8b779c3a92d43 100644
+--- a/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h
++++ b/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h
+@@ -842,7 +842,7 @@ struct iwl_mvm {
+ unsigned long status;
+
+ u32 queue_sync_cookie;
+- atomic_t queue_sync_counter;
++ unsigned long queue_sync_state;
+ /*
+ * for beacon filtering -
+ * currently only one interface can be supported
+diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/ops.c b/drivers/net/wireless/intel/iwlwifi/mvm/ops.c
+index 5b173f21e87bf..3548eb57f1f30 100644
+--- a/drivers/net/wireless/intel/iwlwifi/mvm/ops.c
++++ b/drivers/net/wireless/intel/iwlwifi/mvm/ops.c
+@@ -725,7 +725,7 @@ iwl_op_mode_mvm_start(struct iwl_trans *trans, const struct iwl_cfg *cfg,
+
+ init_waitqueue_head(&mvm->rx_sync_waitq);
+
+- atomic_set(&mvm->queue_sync_counter, 0);
++ mvm->queue_sync_state = 0;
+
+ SET_IEEE80211_DEV(mvm->hw, mvm->trans->dev);
+
+diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/rxmq.c b/drivers/net/wireless/intel/iwlwifi/mvm/rxmq.c
+index 86b3fb321dfdd..e2a39e8b98d07 100644
+--- a/drivers/net/wireless/intel/iwlwifi/mvm/rxmq.c
++++ b/drivers/net/wireless/intel/iwlwifi/mvm/rxmq.c
+@@ -853,9 +853,13 @@ void iwl_mvm_rx_queue_notif(struct iwl_mvm *mvm, struct napi_struct *napi,
+ WARN_ONCE(1, "Invalid identifier %d", internal_notif->type);
+ }
+
+- if (internal_notif->sync &&
+- !atomic_dec_return(&mvm->queue_sync_counter))
+- wake_up(&mvm->rx_sync_waitq);
++ if (internal_notif->sync) {
++ WARN_ONCE(!test_and_clear_bit(queue, &mvm->queue_sync_state),
++ "queue sync: queue %d responded a second time!\n",
++ queue);
++ if (READ_ONCE(mvm->queue_sync_state) == 0)
++ wake_up(&mvm->rx_sync_waitq);
++ }
+ }
+
+ static void iwl_mvm_oldsn_workaround(struct iwl_mvm *mvm,
+diff --git a/drivers/nvme/host/fc.c b/drivers/nvme/host/fc.c
+index 906cab35afe7a..8e05239073ef2 100644
+--- a/drivers/nvme/host/fc.c
++++ b/drivers/nvme/host/fc.c
+@@ -220,11 +220,6 @@ static LIST_HEAD(nvme_fc_lport_list);
+ static DEFINE_IDA(nvme_fc_local_port_cnt);
+ static DEFINE_IDA(nvme_fc_ctrl_cnt);
+
+-static struct workqueue_struct *nvme_fc_wq;
+-
+-static bool nvme_fc_waiting_to_unload;
+-static DECLARE_COMPLETION(nvme_fc_unload_proceed);
+-
+ /*
+ * These items are short-term. They will eventually be moved into
+ * a generic FC class. See comments in module init.
+@@ -254,8 +249,6 @@ nvme_fc_free_lport(struct kref *ref)
+ /* remove from transport list */
+ spin_lock_irqsave(&nvme_fc_lock, flags);
+ list_del(&lport->port_list);
+- if (nvme_fc_waiting_to_unload && list_empty(&nvme_fc_lport_list))
+- complete(&nvme_fc_unload_proceed);
+ spin_unlock_irqrestore(&nvme_fc_lock, flags);
+
+ ida_simple_remove(&nvme_fc_local_port_cnt, lport->localport.port_num);
+@@ -3823,10 +3816,6 @@ static int __init nvme_fc_init_module(void)
+ {
+ int ret;
+
+- nvme_fc_wq = alloc_workqueue("nvme_fc_wq", WQ_MEM_RECLAIM, 0);
+- if (!nvme_fc_wq)
+- return -ENOMEM;
+-
+ /*
+ * NOTE:
+ * It is expected that in the future the kernel will combine
+@@ -3844,7 +3833,7 @@ static int __init nvme_fc_init_module(void)
+ ret = class_register(&fc_class);
+ if (ret) {
+ pr_err("couldn't register class fc\n");
+- goto out_destroy_wq;
++ return ret;
+ }
+
+ /*
+@@ -3868,8 +3857,6 @@ static int __init nvme_fc_init_module(void)
+ device_destroy(&fc_class, MKDEV(0, 0));
+ out_destroy_class:
+ class_unregister(&fc_class);
+-out_destroy_wq:
+- destroy_workqueue(nvme_fc_wq);
+
+ return ret;
+ }
+@@ -3889,45 +3876,23 @@ nvme_fc_delete_controllers(struct nvme_fc_rport *rport)
+ spin_unlock(&rport->lock);
+ }
+
+-static void
+-nvme_fc_cleanup_for_unload(void)
++static void __exit nvme_fc_exit_module(void)
+ {
+ struct nvme_fc_lport *lport;
+ struct nvme_fc_rport *rport;
+-
+- list_for_each_entry(lport, &nvme_fc_lport_list, port_list) {
+- list_for_each_entry(rport, &lport->endp_list, endp_list) {
+- nvme_fc_delete_controllers(rport);
+- }
+- }
+-}
+-
+-static void __exit nvme_fc_exit_module(void)
+-{
+ unsigned long flags;
+- bool need_cleanup = false;
+
+ spin_lock_irqsave(&nvme_fc_lock, flags);
+- nvme_fc_waiting_to_unload = true;
+- if (!list_empty(&nvme_fc_lport_list)) {
+- need_cleanup = true;
+- nvme_fc_cleanup_for_unload();
+- }
++ list_for_each_entry(lport, &nvme_fc_lport_list, port_list)
++ list_for_each_entry(rport, &lport->endp_list, endp_list)
++ nvme_fc_delete_controllers(rport);
+ spin_unlock_irqrestore(&nvme_fc_lock, flags);
+- if (need_cleanup) {
+- pr_info("%s: waiting for ctlr deletes\n", __func__);
+- wait_for_completion(&nvme_fc_unload_proceed);
+- pr_info("%s: ctrl deletes complete\n", __func__);
+- }
++ flush_workqueue(nvme_delete_wq);
+
+ nvmf_unregister_transport(&nvme_fc_transport);
+
+- ida_destroy(&nvme_fc_local_port_cnt);
+- ida_destroy(&nvme_fc_ctrl_cnt);
+-
+ device_destroy(&fc_class, MKDEV(0, 0));
+ class_unregister(&fc_class);
+- destroy_workqueue(nvme_fc_wq);
+ }
+
+ module_init(nvme_fc_init_module);
+diff --git a/drivers/nvme/target/fc.c b/drivers/nvme/target/fc.c
+index 46fc44ce86712..846fb41da6430 100644
+--- a/drivers/nvme/target/fc.c
++++ b/drivers/nvme/target/fc.c
+@@ -357,7 +357,7 @@ __nvmet_fc_finish_ls_req(struct nvmet_fc_ls_req_op *lsop)
+
+ if (!lsop->req_queued) {
+ spin_unlock_irqrestore(&tgtport->lock, flags);
+- return;
++ goto out_puttgtport;
+ }
+
+ list_del(&lsop->lsreq_list);
+@@ -370,6 +370,7 @@ __nvmet_fc_finish_ls_req(struct nvmet_fc_ls_req_op *lsop)
+ (lsreq->rqstlen + lsreq->rsplen),
+ DMA_BIDIRECTIONAL);
+
++out_puttgtport:
+ nvmet_fc_tgtport_put(tgtport);
+ }
+
+@@ -1101,6 +1102,9 @@ nvmet_fc_alloc_target_assoc(struct nvmet_fc_tgtport *tgtport, void *hosthandle)
+ int idx;
+ bool needrandom = true;
+
++ if (!tgtport->pe)
++ return NULL;
++
+ assoc = kzalloc(sizeof(*assoc), GFP_KERNEL);
+ if (!assoc)
+ return NULL;
+@@ -2528,8 +2532,9 @@ nvmet_fc_handle_fcp_rqst(struct nvmet_fc_tgtport *tgtport,
+
+ fod->req.cmd = &fod->cmdiubuf.sqe;
+ fod->req.cqe = &fod->rspiubuf.cqe;
+- if (tgtport->pe)
+- fod->req.port = tgtport->pe->port;
++ if (!tgtport->pe)
++ goto transport_error;
++ fod->req.port = tgtport->pe->port;
+
+ /* clear any response payload */
+ memset(&fod->rspiubuf, 0, sizeof(fod->rspiubuf));
+diff --git a/drivers/nvme/target/fcloop.c b/drivers/nvme/target/fcloop.c
+index 80a208fb34f52..f2c5136bf2b82 100644
+--- a/drivers/nvme/target/fcloop.c
++++ b/drivers/nvme/target/fcloop.c
+@@ -358,7 +358,7 @@ fcloop_h2t_ls_req(struct nvme_fc_local_port *localport,
+ if (!rport->targetport) {
+ tls_req->status = -ECONNREFUSED;
+ spin_lock(&rport->lock);
+- list_add_tail(&rport->ls_list, &tls_req->ls_list);
++ list_add_tail(&tls_req->ls_list, &rport->ls_list);
+ spin_unlock(&rport->lock);
+ schedule_work(&rport->ls_work);
+ return ret;
+@@ -391,7 +391,7 @@ fcloop_h2t_xmt_ls_rsp(struct nvmet_fc_target_port *targetport,
+ if (remoteport) {
+ rport = remoteport->private;
+ spin_lock(&rport->lock);
+- list_add_tail(&rport->ls_list, &tls_req->ls_list);
++ list_add_tail(&tls_req->ls_list, &rport->ls_list);
+ spin_unlock(&rport->lock);
+ schedule_work(&rport->ls_work);
+ }
+@@ -446,7 +446,7 @@ fcloop_t2h_ls_req(struct nvmet_fc_target_port *targetport, void *hosthandle,
+ if (!tport->remoteport) {
+ tls_req->status = -ECONNREFUSED;
+ spin_lock(&tport->lock);
+- list_add_tail(&tport->ls_list, &tls_req->ls_list);
++ list_add_tail(&tls_req->ls_list, &tport->ls_list);
+ spin_unlock(&tport->lock);
+ schedule_work(&tport->ls_work);
+ return ret;
+diff --git a/drivers/nvme/target/tcp.c b/drivers/nvme/target/tcp.c
+index 116ae6fd35e2d..d70a2fa4ba45f 100644
+--- a/drivers/nvme/target/tcp.c
++++ b/drivers/nvme/target/tcp.c
+@@ -1852,6 +1852,7 @@ static void __exit nvmet_tcp_exit(void)
+ flush_scheduled_work();
+
+ destroy_workqueue(nvmet_tcp_wq);
++ ida_destroy(&nvmet_tcp_queue_ida);
+ }
+
+ module_init(nvmet_tcp_init);
+diff --git a/drivers/pci/msi.c b/drivers/pci/msi.c
+index 3da69b26e6743..27377f2f9e84b 100644
+--- a/drivers/pci/msi.c
++++ b/drivers/pci/msi.c
+@@ -1409,7 +1409,7 @@ static irq_hw_number_t pci_msi_domain_calc_hwirq(struct msi_desc *desc)
+
+ return (irq_hw_number_t)desc->msi_attrib.entry_nr |
+ pci_dev_id(dev) << 11 |
+- (pci_domain_nr(dev->bus) & 0xFFFFFFFF) << 27;
++ ((irq_hw_number_t)(pci_domain_nr(dev->bus) & 0xFFFFFFFF)) << 27;
+ }
+
+ static inline bool pci_msi_desc_is_multi_msi(struct msi_desc *desc)
+diff --git a/drivers/platform/x86/intel-vbtn.c b/drivers/platform/x86/intel-vbtn.c
+index a90c32d072da3..9c8a6722f115e 100644
+--- a/drivers/platform/x86/intel-vbtn.c
++++ b/drivers/platform/x86/intel-vbtn.c
+@@ -230,6 +230,12 @@ static const struct dmi_system_id dmi_switches_allow_list[] = {
+ DMI_MATCH(DMI_PRODUCT_NAME, "Inspiron 7352"),
+ },
+ },
++ {
++ .matches = {
++ DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"),
++ DMI_MATCH(DMI_PRODUCT_NAME, "HP Pavilion 13 x360 PC"),
++ },
++ },
+ {} /* Array terminator */
+ };
+
+diff --git a/drivers/regulator/pwm-regulator.c b/drivers/regulator/pwm-regulator.c
+index 7629476d94aeb..f4d9d9455dea6 100644
+--- a/drivers/regulator/pwm-regulator.c
++++ b/drivers/regulator/pwm-regulator.c
+@@ -158,6 +158,9 @@ static int pwm_regulator_get_voltage(struct regulator_dev *rdev)
+ pwm_get_state(drvdata->pwm, &pstate);
+
+ voltage = pwm_get_relative_duty_cycle(&pstate, duty_unit);
++ if (voltage < min(max_uV_duty, min_uV_duty) ||
++ voltage > max(max_uV_duty, min_uV_duty))
++ return -ENOTRECOVERABLE;
+
+ /*
+ * The dutycycle for min_uV might be greater than the one for max_uV.
+diff --git a/drivers/s390/cio/device_ops.c b/drivers/s390/cio/device_ops.c
+index c533d1dadc6bb..a5dba3829769c 100644
+--- a/drivers/s390/cio/device_ops.c
++++ b/drivers/s390/cio/device_ops.c
+@@ -202,7 +202,8 @@ int ccw_device_start_timeout_key(struct ccw_device *cdev, struct ccw1 *cpa,
+ return -EINVAL;
+ if (cdev->private->state == DEV_STATE_NOT_OPER)
+ return -ENODEV;
+- if (cdev->private->state == DEV_STATE_VERIFY) {
++ if (cdev->private->state == DEV_STATE_VERIFY ||
++ cdev->private->flags.doverify) {
+ /* Remember to fake irb when finished. */
+ if (!cdev->private->flags.fake_irb) {
+ cdev->private->flags.fake_irb = FAKE_CMD_IRB;
+@@ -214,8 +215,7 @@ int ccw_device_start_timeout_key(struct ccw_device *cdev, struct ccw1 *cpa,
+ }
+ if (cdev->private->state != DEV_STATE_ONLINE ||
+ ((sch->schib.scsw.cmd.stctl & SCSW_STCTL_PRIM_STATUS) &&
+- !(sch->schib.scsw.cmd.stctl & SCSW_STCTL_SEC_STATUS)) ||
+- cdev->private->flags.doverify)
++ !(sch->schib.scsw.cmd.stctl & SCSW_STCTL_SEC_STATUS)))
+ return -EBUSY;
+ ret = cio_set_options (sch, flags);
+ if (ret)
+diff --git a/drivers/scsi/Kconfig b/drivers/scsi/Kconfig
+index 6524e1fe54d2e..f59c9002468cc 100644
+--- a/drivers/scsi/Kconfig
++++ b/drivers/scsi/Kconfig
+@@ -1289,7 +1289,7 @@ source "drivers/scsi/arm/Kconfig"
+
+ config JAZZ_ESP
+ bool "MIPS JAZZ FAS216 SCSI support"
+- depends on MACH_JAZZ && SCSI
++ depends on MACH_JAZZ && SCSI=y
+ select SCSI_SPI_ATTRS
+ help
+ This is the driver for the onboard SCSI host adapter of MIPS Magnum
+diff --git a/drivers/scsi/lpfc/lpfc_scsi.c b/drivers/scsi/lpfc/lpfc_scsi.c
+index 983eeb0e3d07e..b4b87e5d8b291 100644
+--- a/drivers/scsi/lpfc/lpfc_scsi.c
++++ b/drivers/scsi/lpfc/lpfc_scsi.c
+@@ -1944,7 +1944,7 @@ lpfc_bg_setup_bpl_prot(struct lpfc_hba *phba, struct scsi_cmnd *sc,
+ *
+ * Returns the number of SGEs added to the SGL.
+ **/
+-static int
++static uint32_t
+ lpfc_bg_setup_sgl(struct lpfc_hba *phba, struct scsi_cmnd *sc,
+ struct sli4_sge *sgl, int datasegcnt,
+ struct lpfc_io_buf *lpfc_cmd)
+@@ -1952,8 +1952,8 @@ lpfc_bg_setup_sgl(struct lpfc_hba *phba, struct scsi_cmnd *sc,
+ struct scatterlist *sgde = NULL; /* s/g data entry */
+ struct sli4_sge_diseed *diseed = NULL;
+ dma_addr_t physaddr;
+- int i = 0, num_sge = 0, status;
+- uint32_t reftag;
++ int i = 0, status;
++ uint32_t reftag, num_sge = 0;
+ uint8_t txop, rxop;
+ #ifdef CONFIG_SCSI_LPFC_DEBUG_FS
+ uint32_t rc;
+@@ -2124,7 +2124,7 @@ lpfc_bg_setup_sgl(struct lpfc_hba *phba, struct scsi_cmnd *sc,
+ *
+ * Returns the number of SGEs added to the SGL.
+ **/
+-static int
++static uint32_t
+ lpfc_bg_setup_sgl_prot(struct lpfc_hba *phba, struct scsi_cmnd *sc,
+ struct sli4_sge *sgl, int datacnt, int protcnt,
+ struct lpfc_io_buf *lpfc_cmd)
+@@ -2148,8 +2148,8 @@ lpfc_bg_setup_sgl_prot(struct lpfc_hba *phba, struct scsi_cmnd *sc,
+ uint32_t rc;
+ #endif
+ uint32_t checking = 1;
+- uint32_t dma_offset = 0;
+- int num_sge = 0, j = 2;
++ uint32_t dma_offset = 0, num_sge = 0;
++ int j = 2;
+ struct sli4_hybrid_sgl *sgl_xtra = NULL;
+
+ sgpe = scsi_prot_sglist(sc);
+diff --git a/drivers/soc/renesas/r8a77980-sysc.c b/drivers/soc/renesas/r8a77980-sysc.c
+index 39ca84a67daad..621e411fc9991 100644
+--- a/drivers/soc/renesas/r8a77980-sysc.c
++++ b/drivers/soc/renesas/r8a77980-sysc.c
+@@ -25,7 +25,8 @@ static const struct rcar_sysc_area r8a77980_areas[] __initconst = {
+ PD_CPU_NOCR },
+ { "ca53-cpu3", 0x200, 3, R8A77980_PD_CA53_CPU3, R8A77980_PD_CA53_SCU,
+ PD_CPU_NOCR },
+- { "cr7", 0x240, 0, R8A77980_PD_CR7, R8A77980_PD_ALWAYS_ON },
++ { "cr7", 0x240, 0, R8A77980_PD_CR7, R8A77980_PD_ALWAYS_ON,
++ PD_CPU_NOCR },
+ { "a3ir", 0x180, 0, R8A77980_PD_A3IR, R8A77980_PD_ALWAYS_ON },
+ { "a2ir0", 0x400, 0, R8A77980_PD_A2IR0, R8A77980_PD_A3IR },
+ { "a2ir1", 0x400, 1, R8A77980_PD_A2IR1, R8A77980_PD_A3IR },
+diff --git a/drivers/spi/spi-hisi-sfc-v3xx.c b/drivers/spi/spi-hisi-sfc-v3xx.c
+index 4650b483a33d3..e0c3ad73c576d 100644
+--- a/drivers/spi/spi-hisi-sfc-v3xx.c
++++ b/drivers/spi/spi-hisi-sfc-v3xx.c
+@@ -365,6 +365,11 @@ static const struct spi_controller_mem_ops hisi_sfc_v3xx_mem_ops = {
+ static irqreturn_t hisi_sfc_v3xx_isr(int irq, void *data)
+ {
+ struct hisi_sfc_v3xx_host *host = data;
++ u32 reg;
++
++ reg = readl(host->regbase + HISI_SFC_V3XX_INT_STAT);
++ if (!reg)
++ return IRQ_NONE;
+
+ hisi_sfc_v3xx_disable_int(host);
+
+diff --git a/drivers/spi/spi-sh-msiof.c b/drivers/spi/spi-sh-msiof.c
+index 35d30378256f6..12fd02f92e37b 100644
+--- a/drivers/spi/spi-sh-msiof.c
++++ b/drivers/spi/spi-sh-msiof.c
+@@ -137,14 +137,14 @@ struct sh_msiof_spi_priv {
+
+ /* SIFCTR */
+ #define SIFCTR_TFWM_MASK GENMASK(31, 29) /* Transmit FIFO Watermark */
+-#define SIFCTR_TFWM_64 (0 << 29) /* Transfer Request when 64 empty stages */
+-#define SIFCTR_TFWM_32 (1 << 29) /* Transfer Request when 32 empty stages */
+-#define SIFCTR_TFWM_24 (2 << 29) /* Transfer Request when 24 empty stages */
+-#define SIFCTR_TFWM_16 (3 << 29) /* Transfer Request when 16 empty stages */
+-#define SIFCTR_TFWM_12 (4 << 29) /* Transfer Request when 12 empty stages */
+-#define SIFCTR_TFWM_8 (5 << 29) /* Transfer Request when 8 empty stages */
+-#define SIFCTR_TFWM_4 (6 << 29) /* Transfer Request when 4 empty stages */
+-#define SIFCTR_TFWM_1 (7 << 29) /* Transfer Request when 1 empty stage */
++#define SIFCTR_TFWM_64 (0UL << 29) /* Transfer Request when 64 empty stages */
++#define SIFCTR_TFWM_32 (1UL << 29) /* Transfer Request when 32 empty stages */
++#define SIFCTR_TFWM_24 (2UL << 29) /* Transfer Request when 24 empty stages */
++#define SIFCTR_TFWM_16 (3UL << 29) /* Transfer Request when 16 empty stages */
++#define SIFCTR_TFWM_12 (4UL << 29) /* Transfer Request when 12 empty stages */
++#define SIFCTR_TFWM_8 (5UL << 29) /* Transfer Request when 8 empty stages */
++#define SIFCTR_TFWM_4 (6UL << 29) /* Transfer Request when 4 empty stages */
++#define SIFCTR_TFWM_1 (7UL << 29) /* Transfer Request when 1 empty stage */
+ #define SIFCTR_TFUA_MASK GENMASK(26, 20) /* Transmit FIFO Usable Area */
+ #define SIFCTR_TFUA_SHIFT 20
+ #define SIFCTR_TFUA(i) ((i) << SIFCTR_TFUA_SHIFT)
+diff --git a/drivers/target/target_core_device.c b/drivers/target/target_core_device.c
+index 9aeedcff7d02e..daa4d06ce2336 100644
+--- a/drivers/target/target_core_device.c
++++ b/drivers/target/target_core_device.c
+@@ -150,7 +150,6 @@ int transport_lookup_tmr_lun(struct se_cmd *se_cmd)
+ struct se_session *se_sess = se_cmd->se_sess;
+ struct se_node_acl *nacl = se_sess->se_node_acl;
+ struct se_tmr_req *se_tmr = se_cmd->se_tmr_req;
+- unsigned long flags;
+
+ rcu_read_lock();
+ deve = target_nacl_find_deve(nacl, se_cmd->orig_fe_lun);
+@@ -181,10 +180,6 @@ int transport_lookup_tmr_lun(struct se_cmd *se_cmd)
+ se_cmd->se_dev = rcu_dereference_raw(se_lun->lun_se_dev);
+ se_tmr->tmr_dev = rcu_dereference_raw(se_lun->lun_se_dev);
+
+- spin_lock_irqsave(&se_tmr->tmr_dev->se_tmr_lock, flags);
+- list_add_tail(&se_tmr->tmr_list, &se_tmr->tmr_dev->dev_tmr_list);
+- spin_unlock_irqrestore(&se_tmr->tmr_dev->se_tmr_lock, flags);
+-
+ return 0;
+ }
+ EXPORT_SYMBOL(transport_lookup_tmr_lun);
+diff --git a/drivers/target/target_core_transport.c b/drivers/target/target_core_transport.c
+index 2e97937f005ff..8d294b658592c 100644
+--- a/drivers/target/target_core_transport.c
++++ b/drivers/target/target_core_transport.c
+@@ -3436,6 +3436,10 @@ int transport_generic_handle_tmr(
+ unsigned long flags;
+ bool aborted = false;
+
++ spin_lock_irqsave(&cmd->se_dev->se_tmr_lock, flags);
++ list_add_tail(&cmd->se_tmr_req->tmr_list, &cmd->se_dev->dev_tmr_list);
++ spin_unlock_irqrestore(&cmd->se_dev->se_tmr_lock, flags);
++
+ spin_lock_irqsave(&cmd->t_state_lock, flags);
+ if (cmd->transport_state & CMD_T_ABORTED) {
+ aborted = true;
+diff --git a/drivers/tty/hvc/hvc_xen.c b/drivers/tty/hvc/hvc_xen.c
+index cf0fb650a9247..4886cad0fde61 100644
+--- a/drivers/tty/hvc/hvc_xen.c
++++ b/drivers/tty/hvc/hvc_xen.c
+@@ -43,6 +43,7 @@ struct xencons_info {
+ int irq;
+ int vtermno;
+ grant_ref_t gntref;
++ spinlock_t ring_lock;
+ };
+
+ static LIST_HEAD(xenconsoles);
+@@ -89,12 +90,15 @@ static int __write_console(struct xencons_info *xencons,
+ XENCONS_RING_IDX cons, prod;
+ struct xencons_interface *intf = xencons->intf;
+ int sent = 0;
++ unsigned long flags;
+
++ spin_lock_irqsave(&xencons->ring_lock, flags);
+ cons = intf->out_cons;
+ prod = intf->out_prod;
+ mb(); /* update queue values before going on */
+
+ if ((prod - cons) > sizeof(intf->out)) {
++ spin_unlock_irqrestore(&xencons->ring_lock, flags);
+ pr_err_once("xencons: Illegal ring page indices");
+ return -EINVAL;
+ }
+@@ -104,6 +108,7 @@ static int __write_console(struct xencons_info *xencons,
+
+ wmb(); /* write ring before updating pointer */
+ intf->out_prod = prod;
++ spin_unlock_irqrestore(&xencons->ring_lock, flags);
+
+ if (sent)
+ notify_daemon(xencons);
+@@ -146,16 +151,19 @@ static int domU_read_console(uint32_t vtermno, char *buf, int len)
+ int recv = 0;
+ struct xencons_info *xencons = vtermno_to_xencons(vtermno);
+ unsigned int eoiflag = 0;
++ unsigned long flags;
+
+ if (xencons == NULL)
+ return -EINVAL;
+ intf = xencons->intf;
+
++ spin_lock_irqsave(&xencons->ring_lock, flags);
+ cons = intf->in_cons;
+ prod = intf->in_prod;
+ mb(); /* get pointers before reading ring */
+
+ if ((prod - cons) > sizeof(intf->in)) {
++ spin_unlock_irqrestore(&xencons->ring_lock, flags);
+ pr_err_once("xencons: Illegal ring page indices");
+ return -EINVAL;
+ }
+@@ -179,10 +187,13 @@ static int domU_read_console(uint32_t vtermno, char *buf, int len)
+ xencons->out_cons = intf->out_cons;
+ xencons->out_cons_same = 0;
+ }
++ if (!recv && xencons->out_cons_same++ > 1) {
++ eoiflag = XEN_EOI_FLAG_SPURIOUS;
++ }
++ spin_unlock_irqrestore(&xencons->ring_lock, flags);
++
+ if (recv) {
+ notify_daemon(xencons);
+- } else if (xencons->out_cons_same++ > 1) {
+- eoiflag = XEN_EOI_FLAG_SPURIOUS;
+ }
+
+ xen_irq_lateeoi(xencons->irq, eoiflag);
+@@ -239,6 +250,7 @@ static int xen_hvm_console_init(void)
+ info = kzalloc(sizeof(struct xencons_info), GFP_KERNEL);
+ if (!info)
+ return -ENOMEM;
++ spin_lock_init(&info->ring_lock);
+ } else if (info->intf != NULL) {
+ /* already configured */
+ return 0;
+@@ -275,6 +287,7 @@ static int xen_hvm_console_init(void)
+
+ static int xencons_info_pv_init(struct xencons_info *info, int vtermno)
+ {
++ spin_lock_init(&info->ring_lock);
+ info->evtchn = xen_start_info->console.domU.evtchn;
+ /* GFN == MFN for PV guest */
+ info->intf = gfn_to_virt(xen_start_info->console.domU.mfn);
+@@ -325,6 +338,7 @@ static int xen_initial_domain_console_init(void)
+ info = kzalloc(sizeof(struct xencons_info), GFP_KERNEL);
+ if (!info)
+ return -ENOMEM;
++ spin_lock_init(&info->ring_lock);
+ }
+
+ info->irq = bind_virq_to_irq(VIRQ_CONSOLE, 0, false);
+@@ -485,6 +499,7 @@ static int xencons_probe(struct xenbus_device *dev,
+ info = kzalloc(sizeof(struct xencons_info), GFP_KERNEL);
+ if (!info)
+ return -ENOMEM;
++ spin_lock_init(&info->ring_lock);
+ dev_set_drvdata(&dev->dev, info);
+ info->xbdev = dev;
+ info->vtermno = xenbus_devid_to_vtermno(devid);
+diff --git a/drivers/usb/cdns3/gadget.c b/drivers/usb/cdns3/gadget.c
+index 8a1f0a636848b..eeea892248b5d 100644
+--- a/drivers/usb/cdns3/gadget.c
++++ b/drivers/usb/cdns3/gadget.c
+@@ -837,7 +837,11 @@ void cdns3_gadget_giveback(struct cdns3_endpoint *priv_ep,
+ return;
+ }
+
+- if (request->complete) {
++ /*
++ * zlp request is appended by driver, needn't call usb_gadget_giveback_request() to notify
++ * gadget composite driver.
++ */
++ if (request->complete && request->buf != priv_dev->zlp_buf) {
+ spin_unlock(&priv_dev->lock);
+ usb_gadget_giveback_request(&priv_ep->endpoint,
+ request);
+@@ -2538,11 +2542,11 @@ static int cdns3_gadget_ep_disable(struct usb_ep *ep)
+
+ while (!list_empty(&priv_ep->wa2_descmiss_req_list)) {
+ priv_req = cdns3_next_priv_request(&priv_ep->wa2_descmiss_req_list);
++ list_del_init(&priv_req->list);
+
+ kfree(priv_req->request.buf);
+ cdns3_gadget_ep_free_request(&priv_ep->endpoint,
+ &priv_req->request);
+- list_del_init(&priv_req->list);
+ --priv_ep->wa2_counter;
+ }
+
+diff --git a/drivers/usb/gadget/function/f_ncm.c b/drivers/usb/gadget/function/f_ncm.c
+index d42cd1d036bdf..8fac7a67db76f 100644
+--- a/drivers/usb/gadget/function/f_ncm.c
++++ b/drivers/usb/gadget/function/f_ncm.c
+@@ -1349,7 +1349,15 @@ static int ncm_unwrap_ntb(struct gether *port,
+ "Parsed NTB with %d frames\n", dgram_counter);
+
+ to_process -= block_len;
+- if (to_process != 0) {
++
++ /*
++ * Windows NCM driver avoids USB ZLPs by adding a 1-byte
++ * zero pad as needed.
++ */
++ if (to_process == 1 &&
++ (*(unsigned char *)(ntb_ptr + block_len) == 0x00)) {
++ to_process--;
++ } else if (to_process > 0) {
+ ntb_ptr = (unsigned char *)(ntb_ptr + block_len);
+ goto parse_ntb;
+ }
+diff --git a/drivers/usb/roles/class.c b/drivers/usb/roles/class.c
+index 5cc20275335d1..e1dff4a44fd25 100644
+--- a/drivers/usb/roles/class.c
++++ b/drivers/usb/roles/class.c
+@@ -19,7 +19,9 @@ static struct class *role_class;
+ struct usb_role_switch {
+ struct device dev;
+ struct mutex lock; /* device lock*/
++ struct module *module; /* the module this device depends on */
+ enum usb_role role;
++ bool registered;
+
+ /* From descriptor */
+ struct device *usb2_port;
+@@ -46,6 +48,9 @@ int usb_role_switch_set_role(struct usb_role_switch *sw, enum usb_role role)
+ if (IS_ERR_OR_NULL(sw))
+ return 0;
+
++ if (!sw->registered)
++ return -EOPNOTSUPP;
++
+ mutex_lock(&sw->lock);
+
+ ret = sw->set(sw, role);
+@@ -71,7 +76,7 @@ enum usb_role usb_role_switch_get_role(struct usb_role_switch *sw)
+ {
+ enum usb_role role;
+
+- if (IS_ERR_OR_NULL(sw))
++ if (IS_ERR_OR_NULL(sw) || !sw->registered)
+ return USB_ROLE_NONE;
+
+ mutex_lock(&sw->lock);
+@@ -133,7 +138,7 @@ struct usb_role_switch *usb_role_switch_get(struct device *dev)
+ usb_role_switch_match);
+
+ if (!IS_ERR_OR_NULL(sw))
+- WARN_ON(!try_module_get(sw->dev.parent->driver->owner));
++ WARN_ON(!try_module_get(sw->module));
+
+ return sw;
+ }
+@@ -155,7 +160,7 @@ struct usb_role_switch *fwnode_usb_role_switch_get(struct fwnode_handle *fwnode)
+ sw = fwnode_connection_find_match(fwnode, "usb-role-switch",
+ NULL, usb_role_switch_match);
+ if (!IS_ERR_OR_NULL(sw))
+- WARN_ON(!try_module_get(sw->dev.parent->driver->owner));
++ WARN_ON(!try_module_get(sw->module));
+
+ return sw;
+ }
+@@ -170,7 +175,7 @@ EXPORT_SYMBOL_GPL(fwnode_usb_role_switch_get);
+ void usb_role_switch_put(struct usb_role_switch *sw)
+ {
+ if (!IS_ERR_OR_NULL(sw)) {
+- module_put(sw->dev.parent->driver->owner);
++ module_put(sw->module);
+ put_device(&sw->dev);
+ }
+ }
+@@ -187,15 +192,18 @@ struct usb_role_switch *
+ usb_role_switch_find_by_fwnode(const struct fwnode_handle *fwnode)
+ {
+ struct device *dev;
++ struct usb_role_switch *sw = NULL;
+
+ if (!fwnode)
+ return NULL;
+
+ dev = class_find_device_by_fwnode(role_class, fwnode);
+- if (dev)
+- WARN_ON(!try_module_get(dev->parent->driver->owner));
++ if (dev) {
++ sw = to_role_switch(dev);
++ WARN_ON(!try_module_get(sw->module));
++ }
+
+- return dev ? to_role_switch(dev) : NULL;
++ return sw;
+ }
+ EXPORT_SYMBOL_GPL(usb_role_switch_find_by_fwnode);
+
+@@ -328,6 +336,7 @@ usb_role_switch_register(struct device *parent,
+ sw->set = desc->set;
+ sw->get = desc->get;
+
++ sw->module = parent->driver->owner;
+ sw->dev.parent = parent;
+ sw->dev.fwnode = desc->fwnode;
+ sw->dev.class = role_class;
+@@ -342,6 +351,8 @@ usb_role_switch_register(struct device *parent,
+ return ERR_PTR(ret);
+ }
+
++ sw->registered = true;
++
+ /* TODO: Symlinks for the host port and the device controller. */
+
+ return sw;
+@@ -356,8 +367,10 @@ EXPORT_SYMBOL_GPL(usb_role_switch_register);
+ */
+ void usb_role_switch_unregister(struct usb_role_switch *sw)
+ {
+- if (!IS_ERR_OR_NULL(sw))
++ if (!IS_ERR_OR_NULL(sw)) {
++ sw->registered = false;
+ device_unregister(&sw->dev);
++ }
+ }
+ EXPORT_SYMBOL_GPL(usb_role_switch_unregister);
+
+diff --git a/drivers/video/fbdev/savage/savagefb_driver.c b/drivers/video/fbdev/savage/savagefb_driver.c
+index 0ac750cc5ea13..94ebd8af50cf7 100644
+--- a/drivers/video/fbdev/savage/savagefb_driver.c
++++ b/drivers/video/fbdev/savage/savagefb_driver.c
+@@ -868,6 +868,9 @@ static int savagefb_check_var(struct fb_var_screeninfo *var,
+
+ DBG("savagefb_check_var");
+
++ if (!var->pixclock)
++ return -EINVAL;
++
+ var->transp.offset = 0;
+ var->transp.length = 0;
+ switch (var->bits_per_pixel) {
+diff --git a/drivers/video/fbdev/sis/sis_main.c b/drivers/video/fbdev/sis/sis_main.c
+index 03c736f6f3d08..e540cb0c51726 100644
+--- a/drivers/video/fbdev/sis/sis_main.c
++++ b/drivers/video/fbdev/sis/sis_main.c
+@@ -1474,6 +1474,8 @@ sisfb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
+
+ vtotal = var->upper_margin + var->lower_margin + var->vsync_len;
+
++ if (!var->pixclock)
++ return -EINVAL;
+ pixclock = var->pixclock;
+
+ if((var->vmode & FB_VMODE_MASK) == FB_VMODE_NONINTERLACED) {
+diff --git a/fs/afs/volume.c b/fs/afs/volume.c
+index f84194b791d3e..fb19c69284ab2 100644
+--- a/fs/afs/volume.c
++++ b/fs/afs/volume.c
+@@ -302,7 +302,7 @@ static int afs_update_volume_status(struct afs_volume *volume, struct key *key)
+ {
+ struct afs_server_list *new, *old, *discard;
+ struct afs_vldb_entry *vldb;
+- char idbuf[16];
++ char idbuf[24];
+ int ret, idsz;
+
+ _enter("");
+@@ -310,7 +310,7 @@ static int afs_update_volume_status(struct afs_volume *volume, struct key *key)
+ /* We look up an ID by passing it as a decimal string in the
+ * operation's name parameter.
+ */
+- idsz = sprintf(idbuf, "%llu", volume->vid);
++ idsz = snprintf(idbuf, sizeof(idbuf), "%llu", volume->vid);
+
+ vldb = afs_vl_lookup_vldb(volume->cell, key, idbuf, idsz);
+ if (IS_ERR(vldb)) {
+diff --git a/fs/aio.c b/fs/aio.c
+index 5934ea84b4993..900ed5207540e 100644
+--- a/fs/aio.c
++++ b/fs/aio.c
+@@ -569,6 +569,13 @@ void kiocb_set_cancel_fn(struct kiocb *iocb, kiocb_cancel_fn *cancel)
+ struct kioctx *ctx = req->ki_ctx;
+ unsigned long flags;
+
++ /*
++ * kiocb didn't come from aio or is neither a read nor a write, hence
++ * ignore it.
++ */
++ if (!(iocb->ki_flags & IOCB_AIO_RW))
++ return;
++
+ if (WARN_ON_ONCE(!list_empty(&req->ki_list)))
+ return;
+
+@@ -1454,7 +1461,7 @@ static int aio_prep_rw(struct kiocb *req, const struct iocb *iocb)
+ req->ki_complete = aio_complete_rw;
+ req->private = NULL;
+ req->ki_pos = iocb->aio_offset;
+- req->ki_flags = iocb_flags(req->ki_filp);
++ req->ki_flags = iocb_flags(req->ki_filp) | IOCB_AIO_RW;
+ if (iocb->aio_flags & IOCB_FLAG_RESFD)
+ req->ki_flags |= IOCB_EVENTFD;
+ req->ki_hint = ki_hint_validate(file_write_hint(req->ki_filp));
+diff --git a/fs/btrfs/ctree.h b/fs/btrfs/ctree.h
+index 67831868ef0de..3ddb09f2b1685 100644
+--- a/fs/btrfs/ctree.h
++++ b/fs/btrfs/ctree.h
+@@ -2879,7 +2879,7 @@ struct btrfs_dir_item *
+ btrfs_lookup_dir_index_item(struct btrfs_trans_handle *trans,
+ struct btrfs_root *root,
+ struct btrfs_path *path, u64 dir,
+- u64 objectid, const char *name, int name_len,
++ u64 index, const char *name, int name_len,
+ int mod);
+ struct btrfs_dir_item *
+ btrfs_search_dir_index_item(struct btrfs_root *root,
+diff --git a/fs/btrfs/dir-item.c b/fs/btrfs/dir-item.c
+index 863367c2c6205..98c6faa8ce15b 100644
+--- a/fs/btrfs/dir-item.c
++++ b/fs/btrfs/dir-item.c
+@@ -171,10 +171,40 @@ int btrfs_insert_dir_item(struct btrfs_trans_handle *trans, const char *name,
+ return 0;
+ }
+
++static struct btrfs_dir_item *btrfs_lookup_match_dir(
++ struct btrfs_trans_handle *trans,
++ struct btrfs_root *root, struct btrfs_path *path,
++ struct btrfs_key *key, const char *name,
++ int name_len, int mod)
++{
++ const int ins_len = (mod < 0 ? -1 : 0);
++ const int cow = (mod != 0);
++ int ret;
++
++ ret = btrfs_search_slot(trans, root, key, path, ins_len, cow);
++ if (ret < 0)
++ return ERR_PTR(ret);
++ if (ret > 0)
++ return ERR_PTR(-ENOENT);
++
++ return btrfs_match_dir_item_name(root->fs_info, path, name, name_len);
++}
++
+ /*
+- * lookup a directory item based on name. 'dir' is the objectid
+- * we're searching in, and 'mod' tells us if you plan on deleting the
+- * item (use mod < 0) or changing the options (use mod > 0)
++ * Lookup for a directory item by name.
++ *
++ * @trans: The transaction handle to use. Can be NULL if @mod is 0.
++ * @root: The root of the target tree.
++ * @path: Path to use for the search.
++ * @dir: The inode number (objectid) of the directory.
++ * @name: The name associated to the directory entry we are looking for.
++ * @name_len: The length of the name.
++ * @mod: Used to indicate if the tree search is meant for a read only
++ * lookup, for a modification lookup or for a deletion lookup, so
++ * its value should be 0, 1 or -1, respectively.
++ *
++ * Returns: NULL if the dir item does not exists, an error pointer if an error
++ * happened, or a pointer to a dir item if a dir item exists for the given name.
+ */
+ struct btrfs_dir_item *btrfs_lookup_dir_item(struct btrfs_trans_handle *trans,
+ struct btrfs_root *root,
+@@ -182,23 +212,18 @@ struct btrfs_dir_item *btrfs_lookup_dir_item(struct btrfs_trans_handle *trans,
+ const char *name, int name_len,
+ int mod)
+ {
+- int ret;
+ struct btrfs_key key;
+- int ins_len = mod < 0 ? -1 : 0;
+- int cow = mod != 0;
++ struct btrfs_dir_item *di;
+
+ key.objectid = dir;
+ key.type = BTRFS_DIR_ITEM_KEY;
+-
+ key.offset = btrfs_name_hash(name, name_len);
+
+- ret = btrfs_search_slot(trans, root, &key, path, ins_len, cow);
+- if (ret < 0)
+- return ERR_PTR(ret);
+- if (ret > 0)
++ di = btrfs_lookup_match_dir(trans, root, path, &key, name, name_len, mod);
++ if (IS_ERR(di) && PTR_ERR(di) == -ENOENT)
+ return NULL;
+
+- return btrfs_match_dir_item_name(root->fs_info, path, name, name_len);
++ return di;
+ }
+
+ int btrfs_check_dir_item_collision(struct btrfs_root *root, u64 dir,
+@@ -212,7 +237,6 @@ int btrfs_check_dir_item_collision(struct btrfs_root *root, u64 dir,
+ int slot;
+ struct btrfs_path *path;
+
+-
+ path = btrfs_alloc_path();
+ if (!path)
+ return -ENOMEM;
+@@ -221,20 +245,20 @@ int btrfs_check_dir_item_collision(struct btrfs_root *root, u64 dir,
+ key.type = BTRFS_DIR_ITEM_KEY;
+ key.offset = btrfs_name_hash(name, name_len);
+
+- ret = btrfs_search_slot(NULL, root, &key, path, 0, 0);
+-
+- /* return back any errors */
+- if (ret < 0)
+- goto out;
++ di = btrfs_lookup_match_dir(NULL, root, path, &key, name, name_len, 0);
++ if (IS_ERR(di)) {
++ ret = PTR_ERR(di);
++ /* Nothing found, we're safe */
++ if (ret == -ENOENT) {
++ ret = 0;
++ goto out;
++ }
+
+- /* nothing found, we're safe */
+- if (ret > 0) {
+- ret = 0;
+- goto out;
++ if (ret < 0)
++ goto out;
+ }
+
+ /* we found an item, look for our name in the item */
+- di = btrfs_match_dir_item_name(root->fs_info, path, name, name_len);
+ if (di) {
+ /* our exact name was found */
+ ret = -EEXIST;
+@@ -261,35 +285,42 @@ int btrfs_check_dir_item_collision(struct btrfs_root *root, u64 dir,
+ }
+
+ /*
+- * lookup a directory item based on index. 'dir' is the objectid
+- * we're searching in, and 'mod' tells us if you plan on deleting the
+- * item (use mod < 0) or changing the options (use mod > 0)
++ * Lookup for a directory index item by name and index number.
++ *
++ * @trans: The transaction handle to use. Can be NULL if @mod is 0.
++ * @root: The root of the target tree.
++ * @path: Path to use for the search.
++ * @dir: The inode number (objectid) of the directory.
++ * @index: The index number.
++ * @name: The name associated to the directory entry we are looking for.
++ * @name_len: The length of the name.
++ * @mod: Used to indicate if the tree search is meant for a read only
++ * lookup, for a modification lookup or for a deletion lookup, so
++ * its value should be 0, 1 or -1, respectively.
+ *
+- * The name is used to make sure the index really points to the name you were
+- * looking for.
++ * Returns: NULL if the dir index item does not exists, an error pointer if an
++ * error happened, or a pointer to a dir item if the dir index item exists and
++ * matches the criteria (name and index number).
+ */
+ struct btrfs_dir_item *
+ btrfs_lookup_dir_index_item(struct btrfs_trans_handle *trans,
+ struct btrfs_root *root,
+ struct btrfs_path *path, u64 dir,
+- u64 objectid, const char *name, int name_len,
++ u64 index, const char *name, int name_len,
+ int mod)
+ {
+- int ret;
++ struct btrfs_dir_item *di;
+ struct btrfs_key key;
+- int ins_len = mod < 0 ? -1 : 0;
+- int cow = mod != 0;
+
+ key.objectid = dir;
+ key.type = BTRFS_DIR_INDEX_KEY;
+- key.offset = objectid;
++ key.offset = index;
+
+- ret = btrfs_search_slot(trans, root, &key, path, ins_len, cow);
+- if (ret < 0)
+- return ERR_PTR(ret);
+- if (ret > 0)
+- return ERR_PTR(-ENOENT);
+- return btrfs_match_dir_item_name(root->fs_info, path, name, name_len);
++ di = btrfs_lookup_match_dir(trans, root, path, &key, name, name_len, mod);
++ if (di == ERR_PTR(-ENOENT))
++ return NULL;
++
++ return di;
+ }
+
+ struct btrfs_dir_item *
+@@ -346,21 +377,18 @@ struct btrfs_dir_item *btrfs_lookup_xattr(struct btrfs_trans_handle *trans,
+ const char *name, u16 name_len,
+ int mod)
+ {
+- int ret;
+ struct btrfs_key key;
+- int ins_len = mod < 0 ? -1 : 0;
+- int cow = mod != 0;
++ struct btrfs_dir_item *di;
+
+ key.objectid = dir;
+ key.type = BTRFS_XATTR_ITEM_KEY;
+ key.offset = btrfs_name_hash(name, name_len);
+- ret = btrfs_search_slot(trans, root, &key, path, ins_len, cow);
+- if (ret < 0)
+- return ERR_PTR(ret);
+- if (ret > 0)
++
++ di = btrfs_lookup_match_dir(trans, root, path, &key, name, name_len, mod);
++ if (IS_ERR(di) && PTR_ERR(di) == -ENOENT)
+ return NULL;
+
+- return btrfs_match_dir_item_name(root->fs_info, path, name, name_len);
++ return di;
+ }
+
+ /*
+diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c
+index 250b6064876de..591caac2bf814 100644
+--- a/fs/btrfs/inode.c
++++ b/fs/btrfs/inode.c
+@@ -8968,8 +8968,6 @@ static int btrfs_rename_exchange(struct inode *old_dir,
+ /* force full log commit if subvolume involved. */
+ btrfs_set_log_full_commit(trans);
+ } else {
+- btrfs_pin_log_trans(root);
+- root_log_pinned = true;
+ ret = btrfs_insert_inode_ref(trans, dest,
+ new_dentry->d_name.name,
+ new_dentry->d_name.len,
+@@ -8986,8 +8984,6 @@ static int btrfs_rename_exchange(struct inode *old_dir,
+ /* force full log commit if subvolume involved. */
+ btrfs_set_log_full_commit(trans);
+ } else {
+- btrfs_pin_log_trans(dest);
+- dest_log_pinned = true;
+ ret = btrfs_insert_inode_ref(trans, root,
+ old_dentry->d_name.name,
+ old_dentry->d_name.len,
+@@ -9018,6 +9014,29 @@ static int btrfs_rename_exchange(struct inode *old_dir,
+ BTRFS_I(new_inode), 1);
+ }
+
++ /*
++ * Now pin the logs of the roots. We do it to ensure that no other task
++ * can sync the logs while we are in progress with the rename, because
++ * that could result in an inconsistency in case any of the inodes that
++ * are part of this rename operation were logged before.
++ *
++ * We pin the logs even if at this precise moment none of the inodes was
++ * logged before. This is because right after we checked for that, some
++ * other task fsyncing some other inode not involved with this rename
++ * operation could log that one of our inodes exists.
++ *
++ * We don't need to pin the logs before the above calls to
++ * btrfs_insert_inode_ref(), since those don't ever need to change a log.
++ */
++ if (old_ino != BTRFS_FIRST_FREE_OBJECTID) {
++ btrfs_pin_log_trans(root);
++ root_log_pinned = true;
++ }
++ if (new_ino != BTRFS_FIRST_FREE_OBJECTID) {
++ btrfs_pin_log_trans(dest);
++ dest_log_pinned = true;
++ }
++
+ /* src is a subvolume */
+ if (old_ino == BTRFS_FIRST_FREE_OBJECTID) {
+ ret = btrfs_unlink_subvol(trans, old_dir, old_dentry);
+@@ -9267,8 +9286,6 @@ static int btrfs_rename(struct inode *old_dir, struct dentry *old_dentry,
+ /* force full log commit if subvolume involved. */
+ btrfs_set_log_full_commit(trans);
+ } else {
+- btrfs_pin_log_trans(root);
+- log_pinned = true;
+ ret = btrfs_insert_inode_ref(trans, dest,
+ new_dentry->d_name.name,
+ new_dentry->d_name.len,
+@@ -9292,6 +9309,25 @@ static int btrfs_rename(struct inode *old_dir, struct dentry *old_dentry,
+ if (unlikely(old_ino == BTRFS_FIRST_FREE_OBJECTID)) {
+ ret = btrfs_unlink_subvol(trans, old_dir, old_dentry);
+ } else {
++ /*
++ * Now pin the log. We do it to ensure that no other task can
++ * sync the log while we are in progress with the rename, as
++ * that could result in an inconsistency in case any of the
++ * inodes that are part of this rename operation were logged
++ * before.
++ *
++ * We pin the log even if at this precise moment none of the
++ * inodes was logged before. This is because right after we
++ * checked for that, some other task fsyncing some other inode
++ * not involved with this rename operation could log that one of
++ * our inodes exists.
++ *
++ * We don't need to pin the logs before the above call to
++ * btrfs_insert_inode_ref(), since that does not need to change
++ * a log.
++ */
++ btrfs_pin_log_trans(root);
++ log_pinned = true;
+ ret = __btrfs_unlink_inode(trans, root, BTRFS_I(old_dir),
+ BTRFS_I(d_inode(old_dentry)),
+ old_dentry->d_name.name,
+diff --git a/fs/btrfs/tree-checker.c b/fs/btrfs/tree-checker.c
+index c0eda3816f685..5b952f69bc1f6 100644
+--- a/fs/btrfs/tree-checker.c
++++ b/fs/btrfs/tree-checker.c
+@@ -1189,7 +1189,8 @@ static void extent_err(const struct extent_buffer *eb, int slot,
+ }
+
+ static int check_extent_item(struct extent_buffer *leaf,
+- struct btrfs_key *key, int slot)
++ struct btrfs_key *key, int slot,
++ struct btrfs_key *prev_key)
+ {
+ struct btrfs_fs_info *fs_info = leaf->fs_info;
+ struct btrfs_extent_item *ei;
+@@ -1400,6 +1401,26 @@ static int check_extent_item(struct extent_buffer *leaf,
+ total_refs, inline_refs);
+ return -EUCLEAN;
+ }
++
++ if ((prev_key->type == BTRFS_EXTENT_ITEM_KEY) ||
++ (prev_key->type == BTRFS_METADATA_ITEM_KEY)) {
++ u64 prev_end = prev_key->objectid;
++
++ if (prev_key->type == BTRFS_METADATA_ITEM_KEY)
++ prev_end += fs_info->nodesize;
++ else
++ prev_end += prev_key->offset;
++
++ if (unlikely(prev_end > key->objectid)) {
++ extent_err(leaf, slot,
++ "previous extent [%llu %u %llu] overlaps current extent [%llu %u %llu]",
++ prev_key->objectid, prev_key->type,
++ prev_key->offset, key->objectid, key->type,
++ key->offset);
++ return -EUCLEAN;
++ }
++ }
++
+ return 0;
+ }
+
+@@ -1568,7 +1589,7 @@ static int check_leaf_item(struct extent_buffer *leaf,
+ break;
+ case BTRFS_EXTENT_ITEM_KEY:
+ case BTRFS_METADATA_ITEM_KEY:
+- ret = check_extent_item(leaf, key, slot);
++ ret = check_extent_item(leaf, key, slot, prev_key);
+ break;
+ case BTRFS_TREE_BLOCK_REF_KEY:
+ case BTRFS_SHARED_DATA_REF_KEY:
+diff --git a/fs/btrfs/tree-log.c b/fs/btrfs/tree-log.c
+index 10a0913ffb492..34e9eb5010cda 100644
+--- a/fs/btrfs/tree-log.c
++++ b/fs/btrfs/tree-log.c
+@@ -912,8 +912,7 @@ static noinline int inode_in_dir(struct btrfs_root *root,
+ di = btrfs_lookup_dir_index_item(NULL, root, path, dirid,
+ index, name, name_len, 0);
+ if (IS_ERR(di)) {
+- if (PTR_ERR(di) != -ENOENT)
+- ret = PTR_ERR(di);
++ ret = PTR_ERR(di);
+ goto out;
+ } else if (di) {
+ btrfs_dir_item_key_to_cpu(path->nodes[0], di, &location);
+@@ -1149,8 +1148,7 @@ static inline int __add_inode_ref(struct btrfs_trans_handle *trans,
+ di = btrfs_lookup_dir_index_item(trans, root, path, btrfs_ino(dir),
+ ref_index, name, namelen, 0);
+ if (IS_ERR(di)) {
+- if (PTR_ERR(di) != -ENOENT)
+- return PTR_ERR(di);
++ return PTR_ERR(di);
+ } else if (di) {
+ ret = drop_one_dir_item(trans, root, path, dir, di);
+ if (ret)
+@@ -1976,9 +1974,6 @@ static noinline int replay_one_name(struct btrfs_trans_handle *trans,
+ goto out;
+ }
+
+- if (dst_di == ERR_PTR(-ENOENT))
+- dst_di = NULL;
+-
+ if (IS_ERR(dst_di)) {
+ ret = PTR_ERR(dst_di);
+ goto out;
+@@ -2286,7 +2281,7 @@ static noinline int check_item_in_log(struct btrfs_trans_handle *trans,
+ dir_key->offset,
+ name, name_len, 0);
+ }
+- if (!log_di || log_di == ERR_PTR(-ENOENT)) {
++ if (!log_di) {
+ btrfs_dir_item_key_to_cpu(eb, di, &location);
+ btrfs_release_path(path);
+ btrfs_release_path(log_path);
+@@ -3495,8 +3490,7 @@ int btrfs_del_dir_entries_in_log(struct btrfs_trans_handle *trans,
+ if (err == -ENOSPC) {
+ btrfs_set_log_full_commit(trans);
+ err = 0;
+- } else if (err < 0 && err != -ENOENT) {
+- /* ENOENT can be returned if the entry hasn't been fsynced yet */
++ } else if (err < 0) {
+ btrfs_abort_transaction(trans, err);
+ }
+
+diff --git a/fs/cifs/smb2ops.c b/fs/cifs/smb2ops.c
+index 84850a55c8b7e..b2a7238a34221 100644
+--- a/fs/cifs/smb2ops.c
++++ b/fs/cifs/smb2ops.c
+@@ -82,6 +82,7 @@ smb2_add_credits(struct TCP_Server_Info *server,
+ *val = 65000; /* Don't get near 64K credits, avoid srv bugs */
+ pr_warn_once("server overflowed SMB3 credits\n");
+ }
++ WARN_ON_ONCE(server->in_flight == 0);
+ server->in_flight--;
+ if (server->in_flight == 0 && (optype & CIFS_OP_MASK) != CIFS_NEG_OP)
+ rc = change_conf(server);
+@@ -818,10 +819,12 @@ int open_shroot(unsigned int xid, struct cifs_tcon *tcon,
+ if (o_rsp->OplockLevel == SMB2_OPLOCK_LEVEL_LEASE) {
+ kref_get(&tcon->crfid.refcount);
+ tcon->crfid.has_lease = true;
+- smb2_parse_contexts(server, o_rsp,
++ rc = smb2_parse_contexts(server, rsp_iov,
+ &oparms.fid->epoch,
+ oparms.fid->lease_key, &oplock,
+ NULL, NULL);
++ if (rc)
++ goto oshr_exit;
+ } else
+ goto oshr_exit;
+
+@@ -4892,6 +4895,7 @@ receive_encrypted_standard(struct TCP_Server_Info *server,
+ struct smb2_sync_hdr *shdr;
+ unsigned int pdu_length = server->pdu_size;
+ unsigned int buf_size;
++ unsigned int next_cmd;
+ struct mid_q_entry *mid_entry;
+ int next_is_large;
+ char *next_buffer = NULL;
+@@ -4920,14 +4924,15 @@ receive_encrypted_standard(struct TCP_Server_Info *server,
+ next_is_large = server->large_buf;
+ one_more:
+ shdr = (struct smb2_sync_hdr *)buf;
+- if (shdr->NextCommand) {
++ next_cmd = le32_to_cpu(shdr->NextCommand);
++ if (next_cmd) {
++ if (WARN_ON_ONCE(next_cmd > pdu_length))
++ return -1;
+ if (next_is_large)
+ next_buffer = (char *)cifs_buf_get();
+ else
+ next_buffer = (char *)cifs_small_buf_get();
+- memcpy(next_buffer,
+- buf + le32_to_cpu(shdr->NextCommand),
+- pdu_length - le32_to_cpu(shdr->NextCommand));
++ memcpy(next_buffer, buf + next_cmd, pdu_length - next_cmd);
+ }
+
+ mid_entry = smb2_find_mid(server, buf);
+@@ -4951,8 +4956,8 @@ receive_encrypted_standard(struct TCP_Server_Info *server,
+ else
+ ret = cifs_handle_standard(server, mid_entry);
+
+- if (ret == 0 && shdr->NextCommand) {
+- pdu_length -= le32_to_cpu(shdr->NextCommand);
++ if (ret == 0 && next_cmd) {
++ pdu_length -= next_cmd;
+ server->large_buf = next_is_large;
+ if (next_is_large)
+ server->bigbuf = buf = next_buffer;
+diff --git a/fs/cifs/smb2pdu.c b/fs/cifs/smb2pdu.c
+index 4aec01841f0f2..aa3211d8cce3b 100644
+--- a/fs/cifs/smb2pdu.c
++++ b/fs/cifs/smb2pdu.c
+@@ -1991,17 +1991,18 @@ parse_posix_ctxt(struct create_context *cc, struct smb2_file_all_info *info,
+ posix->nlink, posix->mode, posix->reparse_tag);
+ }
+
+-void
+-smb2_parse_contexts(struct TCP_Server_Info *server,
+- struct smb2_create_rsp *rsp,
+- unsigned int *epoch, char *lease_key, __u8 *oplock,
+- struct smb2_file_all_info *buf,
+- struct create_posix_rsp *posix)
++int smb2_parse_contexts(struct TCP_Server_Info *server,
++ struct kvec *rsp_iov,
++ unsigned int *epoch,
++ char *lease_key, __u8 *oplock,
++ struct smb2_file_all_info *buf,
++ struct create_posix_rsp *posix)
+ {
+- char *data_offset;
++ struct smb2_create_rsp *rsp = rsp_iov->iov_base;
+ struct create_context *cc;
+- unsigned int next;
+- unsigned int remaining;
++ size_t rem, off, len;
++ size_t doff, dlen;
++ size_t noff, nlen;
+ char *name;
+ static const char smb3_create_tag_posix[] = {
+ 0x93, 0xAD, 0x25, 0x50, 0x9C,
+@@ -2010,45 +2011,63 @@ smb2_parse_contexts(struct TCP_Server_Info *server,
+ };
+
+ *oplock = 0;
+- data_offset = (char *)rsp + le32_to_cpu(rsp->CreateContextsOffset);
+- remaining = le32_to_cpu(rsp->CreateContextsLength);
+- cc = (struct create_context *)data_offset;
++
++ off = le32_to_cpu(rsp->CreateContextsOffset);
++ rem = le32_to_cpu(rsp->CreateContextsLength);
++ if (check_add_overflow(off, rem, &len) || len > rsp_iov->iov_len)
++ return -EINVAL;
++ cc = (struct create_context *)((u8 *)rsp + off);
+
+ /* Initialize inode number to 0 in case no valid data in qfid context */
+ if (buf)
+ buf->IndexNumber = 0;
+
+- while (remaining >= sizeof(struct create_context)) {
+- name = le16_to_cpu(cc->NameOffset) + (char *)cc;
+- if (le16_to_cpu(cc->NameLength) == 4 &&
+- strncmp(name, SMB2_CREATE_REQUEST_LEASE, 4) == 0)
+- *oplock = server->ops->parse_lease_buf(cc, epoch,
+- lease_key);
+- else if (buf && (le16_to_cpu(cc->NameLength) == 4) &&
+- strncmp(name, SMB2_CREATE_QUERY_ON_DISK_ID, 4) == 0)
+- parse_query_id_ctxt(cc, buf);
+- else if ((le16_to_cpu(cc->NameLength) == 16)) {
+- if (posix &&
+- memcmp(name, smb3_create_tag_posix, 16) == 0)
++ while (rem >= sizeof(*cc)) {
++ doff = le16_to_cpu(cc->DataOffset);
++ dlen = le32_to_cpu(cc->DataLength);
++ if (check_add_overflow(doff, dlen, &len) || len > rem)
++ return -EINVAL;
++
++ noff = le16_to_cpu(cc->NameOffset);
++ nlen = le16_to_cpu(cc->NameLength);
++ if (noff + nlen > doff)
++ return -EINVAL;
++
++ name = (char *)cc + noff;
++ switch (nlen) {
++ case 4:
++ if (!strncmp(name, SMB2_CREATE_REQUEST_LEASE, 4)) {
++ *oplock = server->ops->parse_lease_buf(cc, epoch,
++ lease_key);
++ } else if (buf &&
++ !strncmp(name, SMB2_CREATE_QUERY_ON_DISK_ID, 4)) {
++ parse_query_id_ctxt(cc, buf);
++ }
++ break;
++ case 16:
++ if (posix && !memcmp(name, smb3_create_tag_posix, 16))
+ parse_posix_ctxt(cc, buf, posix);
++ break;
++ default:
++ cifs_dbg(FYI, "%s: unhandled context (nlen=%zu dlen=%zu)\n",
++ __func__, nlen, dlen);
++ if (IS_ENABLED(CONFIG_CIFS_DEBUG2))
++ cifs_dump_mem("context data: ", cc, dlen);
++ break;
+ }
+- /* else {
+- cifs_dbg(FYI, "Context not matched with len %d\n",
+- le16_to_cpu(cc->NameLength));
+- cifs_dump_mem("Cctxt name: ", name, 4);
+- } */
+-
+- next = le32_to_cpu(cc->Next);
+- if (!next)
++
++ off = le32_to_cpu(cc->Next);
++ if (!off)
+ break;
+- remaining -= next;
+- cc = (struct create_context *)((char *)cc + next);
++ if (check_sub_overflow(rem, off, &rem))
++ return -EINVAL;
++ cc = (struct create_context *)((u8 *)cc + off);
+ }
+
+ if (rsp->OplockLevel != SMB2_OPLOCK_LEVEL_LEASE)
+ *oplock = rsp->OplockLevel;
+
+- return;
++ return 0;
+ }
+
+ static int
+@@ -2915,8 +2934,8 @@ SMB2_open(const unsigned int xid, struct cifs_open_parms *oparms, __le16 *path,
+ }
+
+
+- smb2_parse_contexts(server, rsp, &oparms->fid->epoch,
+- oparms->fid->lease_key, oplock, buf, posix);
++ rc = smb2_parse_contexts(server, &rsp_iov, &oparms->fid->epoch,
++ oparms->fid->lease_key, oplock, buf, posix);
+ creat_exit:
+ SMB2_open_free(&rqst);
+ free_rsp_buf(resp_buftype, rsp);
+diff --git a/fs/cifs/smb2proto.h b/fs/cifs/smb2proto.h
+index ed2b4fb012a41..3184a5efcdba5 100644
+--- a/fs/cifs/smb2proto.h
++++ b/fs/cifs/smb2proto.h
+@@ -270,11 +270,13 @@ extern int smb3_validate_negotiate(const unsigned int, struct cifs_tcon *);
+
+ extern enum securityEnum smb2_select_sectype(struct TCP_Server_Info *,
+ enum securityEnum);
+-extern void smb2_parse_contexts(struct TCP_Server_Info *server,
+- struct smb2_create_rsp *rsp,
+- unsigned int *epoch, char *lease_key,
+- __u8 *oplock, struct smb2_file_all_info *buf,
+- struct create_posix_rsp *posix);
++int smb2_parse_contexts(struct TCP_Server_Info *server,
++ struct kvec *rsp_iov,
++ unsigned int *epoch,
++ char *lease_key, __u8 *oplock,
++ struct smb2_file_all_info *buf,
++ struct create_posix_rsp *posix);
++
+ extern int smb3_encryption_required(const struct cifs_tcon *tcon);
+ extern int smb2_validate_iov(unsigned int offset, unsigned int buffer_length,
+ struct kvec *iov, unsigned int min_buf_size);
+diff --git a/fs/erofs/decompressor.c b/fs/erofs/decompressor.c
+index f921580b56cbc..36693924db182 100644
+--- a/fs/erofs/decompressor.c
++++ b/fs/erofs/decompressor.c
+@@ -24,7 +24,8 @@ struct z_erofs_decompressor {
+ */
+ int (*prepare_destpages)(struct z_erofs_decompress_req *rq,
+ struct list_head *pagepool);
+- int (*decompress)(struct z_erofs_decompress_req *rq, u8 *out);
++ int (*decompress)(struct z_erofs_decompress_req *rq, u8 *out,
++ u8 *obase);
+ char *name;
+ };
+
+@@ -114,10 +115,13 @@ static void *generic_copy_inplace_data(struct z_erofs_decompress_req *rq,
+ return tmp;
+ }
+
+-static int z_erofs_lz4_decompress(struct z_erofs_decompress_req *rq, u8 *out)
++static int z_erofs_lz4_decompress(struct z_erofs_decompress_req *rq, u8 *out,
++ u8 *obase)
+ {
++ const uint nrpages_out = PAGE_ALIGN(rq->pageofs_out +
++ rq->outputsize) >> PAGE_SHIFT;
+ unsigned int inputmargin, inlen;
+- u8 *src;
++ u8 *src, *src2;
+ bool copied, support_0padding;
+ int ret;
+
+@@ -125,6 +129,7 @@ static int z_erofs_lz4_decompress(struct z_erofs_decompress_req *rq, u8 *out)
+ return -EOPNOTSUPP;
+
+ src = kmap_atomic(*rq->in);
++ src2 = src;
+ inputmargin = 0;
+ support_0padding = false;
+
+@@ -148,16 +153,15 @@ static int z_erofs_lz4_decompress(struct z_erofs_decompress_req *rq, u8 *out)
+ if (rq->inplace_io) {
+ const uint oend = (rq->pageofs_out +
+ rq->outputsize) & ~PAGE_MASK;
+- const uint nr = PAGE_ALIGN(rq->pageofs_out +
+- rq->outputsize) >> PAGE_SHIFT;
+-
+ if (rq->partial_decoding || !support_0padding ||
+- rq->out[nr - 1] != rq->in[0] ||
++ rq->out[nrpages_out - 1] != rq->in[0] ||
+ rq->inputsize - oend <
+ LZ4_DECOMPRESS_INPLACE_MARGIN(inlen)) {
+ src = generic_copy_inplace_data(rq, src, inputmargin);
+ inputmargin = 0;
+ copied = true;
++ } else {
++ src = obase + ((nrpages_out - 1) << PAGE_SHIFT);
+ }
+ }
+
+@@ -187,7 +191,7 @@ static int z_erofs_lz4_decompress(struct z_erofs_decompress_req *rq, u8 *out)
+ if (copied)
+ erofs_put_pcpubuf(src);
+ else
+- kunmap_atomic(src);
++ kunmap_atomic(src2);
+ return ret;
+ }
+
+@@ -257,7 +261,7 @@ static int z_erofs_decompress_generic(struct z_erofs_decompress_req *rq,
+ return PTR_ERR(dst);
+
+ rq->inplace_io = false;
+- ret = alg->decompress(rq, dst);
++ ret = alg->decompress(rq, dst, NULL);
+ if (!ret)
+ copy_from_pcpubuf(rq->out, dst, rq->pageofs_out,
+ rq->outputsize);
+@@ -291,7 +295,7 @@ static int z_erofs_decompress_generic(struct z_erofs_decompress_req *rq,
+ dst_maptype = 2;
+
+ dstmap_out:
+- ret = alg->decompress(rq, dst + rq->pageofs_out);
++ ret = alg->decompress(rq, dst + rq->pageofs_out, dst);
+
+ if (!dst_maptype)
+ kunmap_atomic(dst);
+diff --git a/fs/ext4/extents.c b/fs/ext4/extents.c
+index 193b13630ac1e..68aa8760cb465 100644
+--- a/fs/ext4/extents.c
++++ b/fs/ext4/extents.c
+@@ -2222,7 +2222,7 @@ static int ext4_fill_es_cache_info(struct inode *inode,
+
+
+ /*
+- * ext4_ext_determine_hole - determine hole around given block
++ * ext4_ext_find_hole - find hole around given block according to the given path
+ * @inode: inode we lookup in
+ * @path: path in extent tree to @lblk
+ * @lblk: pointer to logical block around which we want to determine hole
+@@ -2234,9 +2234,9 @@ static int ext4_fill_es_cache_info(struct inode *inode,
+ * The function returns the length of a hole starting at @lblk. We update @lblk
+ * to the beginning of the hole if we managed to find it.
+ */
+-static ext4_lblk_t ext4_ext_determine_hole(struct inode *inode,
+- struct ext4_ext_path *path,
+- ext4_lblk_t *lblk)
++static ext4_lblk_t ext4_ext_find_hole(struct inode *inode,
++ struct ext4_ext_path *path,
++ ext4_lblk_t *lblk)
+ {
+ int depth = ext_depth(inode);
+ struct ext4_extent *ex;
+@@ -2263,30 +2263,6 @@ static ext4_lblk_t ext4_ext_determine_hole(struct inode *inode,
+ return len;
+ }
+
+-/*
+- * ext4_ext_put_gap_in_cache:
+- * calculate boundaries of the gap that the requested block fits into
+- * and cache this gap
+- */
+-static void
+-ext4_ext_put_gap_in_cache(struct inode *inode, ext4_lblk_t hole_start,
+- ext4_lblk_t hole_len)
+-{
+- struct extent_status es;
+-
+- ext4_es_find_extent_range(inode, &ext4_es_is_delayed, hole_start,
+- hole_start + hole_len - 1, &es);
+- if (es.es_len) {
+- /* There's delayed extent containing lblock? */
+- if (es.es_lblk <= hole_start)
+- return;
+- hole_len = min(es.es_lblk - hole_start, hole_len);
+- }
+- ext_debug(inode, " -> %u:%u\n", hole_start, hole_len);
+- ext4_es_insert_extent(inode, hole_start, hole_len, ~0,
+- EXTENT_STATUS_HOLE);
+-}
+-
+ /*
+ * ext4_ext_rm_idx:
+ * removes index from the index block.
+@@ -4058,6 +4034,69 @@ static int get_implied_cluster_alloc(struct super_block *sb,
+ return 0;
+ }
+
++/*
++ * Determine hole length around the given logical block, first try to
++ * locate and expand the hole from the given @path, and then adjust it
++ * if it's partially or completely converted to delayed extents, insert
++ * it into the extent cache tree if it's indeed a hole, finally return
++ * the length of the determined extent.
++ */
++static ext4_lblk_t ext4_ext_determine_insert_hole(struct inode *inode,
++ struct ext4_ext_path *path,
++ ext4_lblk_t lblk)
++{
++ ext4_lblk_t hole_start, len;
++ struct extent_status es;
++
++ hole_start = lblk;
++ len = ext4_ext_find_hole(inode, path, &hole_start);
++again:
++ ext4_es_find_extent_range(inode, &ext4_es_is_delayed, hole_start,
++ hole_start + len - 1, &es);
++ if (!es.es_len)
++ goto insert_hole;
++
++ /*
++ * There's a delalloc extent in the hole, handle it if the delalloc
++ * extent is in front of, behind and straddle the queried range.
++ */
++ if (lblk >= es.es_lblk + es.es_len) {
++ /*
++ * The delalloc extent is in front of the queried range,
++ * find again from the queried start block.
++ */
++ len -= lblk - hole_start;
++ hole_start = lblk;
++ goto again;
++ } else if (in_range(lblk, es.es_lblk, es.es_len)) {
++ /*
++ * The delalloc extent containing lblk, it must have been
++ * added after ext4_map_blocks() checked the extent status
++ * tree, adjust the length to the delalloc extent's after
++ * lblk.
++ */
++ len = es.es_lblk + es.es_len - lblk;
++ return len;
++ } else {
++ /*
++ * The delalloc extent is partially or completely behind
++ * the queried range, update hole length until the
++ * beginning of the delalloc extent.
++ */
++ len = min(es.es_lblk - hole_start, len);
++ }
++
++insert_hole:
++ /* Put just found gap into cache to speed up subsequent requests */
++ ext_debug(inode, " -> %u:%u\n", hole_start, len);
++ ext4_es_insert_extent(inode, hole_start, len, ~0, EXTENT_STATUS_HOLE);
++
++ /* Update hole_len to reflect hole size after lblk */
++ if (hole_start != lblk)
++ len -= lblk - hole_start;
++
++ return len;
++}
+
+ /*
+ * Block allocation/map/preallocation routine for extents based files
+@@ -4175,22 +4214,12 @@ int ext4_ext_map_blocks(handle_t *handle, struct inode *inode,
+ * we couldn't try to create block if create flag is zero
+ */
+ if ((flags & EXT4_GET_BLOCKS_CREATE) == 0) {
+- ext4_lblk_t hole_start, hole_len;
++ ext4_lblk_t len;
+
+- hole_start = map->m_lblk;
+- hole_len = ext4_ext_determine_hole(inode, path, &hole_start);
+- /*
+- * put just found gap into cache to speed up
+- * subsequent requests
+- */
+- ext4_ext_put_gap_in_cache(inode, hole_start, hole_len);
++ len = ext4_ext_determine_insert_hole(inode, path, map->m_lblk);
+
+- /* Update hole_len to reflect hole size after map->m_lblk */
+- if (hole_start != map->m_lblk)
+- hole_len -= map->m_lblk - hole_start;
+ map->m_pblk = 0;
+- map->m_len = min_t(unsigned int, map->m_len, hole_len);
+-
++ map->m_len = min_t(unsigned int, map->m_len, len);
+ goto out;
+ }
+
+diff --git a/fs/ext4/mballoc.c b/fs/ext4/mballoc.c
+index 9bec75847b856..d66ba6f6a8115 100644
+--- a/fs/ext4/mballoc.c
++++ b/fs/ext4/mballoc.c
+@@ -823,6 +823,24 @@ void ext4_mb_generate_buddy(struct super_block *sb,
+ atomic64_add(period, &sbi->s_mb_generation_time);
+ }
+
++static void mb_regenerate_buddy(struct ext4_buddy *e4b)
++{
++ int count;
++ int order = 1;
++ void *buddy;
++
++ while ((buddy = mb_find_buddy(e4b, order++, &count)))
++ ext4_set_bits(buddy, 0, count);
++
++ e4b->bd_info->bb_fragments = 0;
++ memset(e4b->bd_info->bb_counters, 0,
++ sizeof(*e4b->bd_info->bb_counters) *
++ (e4b->bd_sb->s_blocksize_bits + 2));
++
++ ext4_mb_generate_buddy(e4b->bd_sb, e4b->bd_buddy,
++ e4b->bd_bitmap, e4b->bd_group, e4b->bd_info);
++}
++
+ /* The buddy information is attached the buddy cache inode
+ * for convenience. The information regarding each group
+ * is loaded via ext4_mb_load_buddy. The information involve
+@@ -1505,6 +1523,8 @@ static void mb_free_blocks(struct inode *inode, struct ext4_buddy *e4b,
+ ext4_mark_group_bitmap_corrupted(
+ sb, e4b->bd_group,
+ EXT4_GROUP_INFO_BBITMAP_CORRUPT);
++ } else {
++ mb_regenerate_buddy(e4b);
+ }
+ goto done;
+ }
+@@ -1854,6 +1874,9 @@ int ext4_mb_try_best_found(struct ext4_allocation_context *ac,
+ return err;
+
+ ext4_lock_group(ac->ac_sb, group);
++ if (unlikely(EXT4_MB_GRP_BBITMAP_CORRUPT(e4b->bd_info)))
++ goto out;
++
+ max = mb_find_extent(e4b, ex.fe_start, ex.fe_len, &ex);
+
+ if (max > 0) {
+@@ -1861,6 +1884,7 @@ int ext4_mb_try_best_found(struct ext4_allocation_context *ac,
+ ext4_mb_use_best_found(ac, e4b);
+ }
+
++out:
+ ext4_unlock_group(ac->ac_sb, group);
+ ext4_mb_unload_buddy(e4b);
+
+@@ -1889,12 +1913,10 @@ int ext4_mb_find_by_goal(struct ext4_allocation_context *ac,
+ if (err)
+ return err;
+
+- if (unlikely(EXT4_MB_GRP_BBITMAP_CORRUPT(e4b->bd_info))) {
+- ext4_mb_unload_buddy(e4b);
+- return 0;
+- }
+-
+ ext4_lock_group(ac->ac_sb, group);
++ if (unlikely(EXT4_MB_GRP_BBITMAP_CORRUPT(e4b->bd_info)))
++ goto out;
++
+ max = mb_find_extent(e4b, ac->ac_g_ex.fe_start,
+ ac->ac_g_ex.fe_len, &ex);
+ ex.fe_logical = 0xDEADFA11; /* debug value */
+@@ -1927,6 +1949,7 @@ int ext4_mb_find_by_goal(struct ext4_allocation_context *ac,
+ ac->ac_b_ex = ex;
+ ext4_mb_use_best_found(ac, e4b);
+ }
++out:
+ ext4_unlock_group(ac->ac_sb, group);
+ ext4_mb_unload_buddy(e4b);
+
+diff --git a/fs/jbd2/checkpoint.c b/fs/jbd2/checkpoint.c
+index 472932b9e6bca..7898983c9fba0 100644
+--- a/fs/jbd2/checkpoint.c
++++ b/fs/jbd2/checkpoint.c
+@@ -57,28 +57,6 @@ static inline void __buffer_unlink(struct journal_head *jh)
+ }
+ }
+
+-/*
+- * Move a buffer from the checkpoint list to the checkpoint io list
+- *
+- * Called with j_list_lock held
+- */
+-static inline void __buffer_relink_io(struct journal_head *jh)
+-{
+- transaction_t *transaction = jh->b_cp_transaction;
+-
+- __buffer_unlink_first(jh);
+-
+- if (!transaction->t_checkpoint_io_list) {
+- jh->b_cpnext = jh->b_cpprev = jh;
+- } else {
+- jh->b_cpnext = transaction->t_checkpoint_io_list;
+- jh->b_cpprev = transaction->t_checkpoint_io_list->b_cpprev;
+- jh->b_cpprev->b_cpnext = jh;
+- jh->b_cpnext->b_cpprev = jh;
+- }
+- transaction->t_checkpoint_io_list = jh;
+-}
+-
+ /*
+ * Try to release a checkpointed buffer from its transaction.
+ * Returns 1 if we released it and 2 if we also released the
+@@ -91,8 +69,7 @@ static int __try_to_free_cp_buf(struct journal_head *jh)
+ int ret = 0;
+ struct buffer_head *bh = jh2bh(jh);
+
+- if (jh->b_transaction == NULL && !buffer_locked(bh) &&
+- !buffer_dirty(bh) && !buffer_write_io_error(bh)) {
++ if (!jh->b_transaction && !buffer_locked(bh) && !buffer_dirty(bh)) {
+ JBUFFER_TRACE(jh, "remove from checkpoint list");
+ ret = __jbd2_journal_remove_checkpoint(jh) + 1;
+ }
+@@ -191,6 +168,7 @@ __flush_batch(journal_t *journal, int *batch_count)
+ struct buffer_head *bh = journal->j_chkpt_bhs[i];
+ BUFFER_TRACE(bh, "brelse");
+ __brelse(bh);
++ journal->j_chkpt_bhs[i] = NULL;
+ }
+ *batch_count = 0;
+ }
+@@ -228,7 +206,6 @@ int jbd2_log_do_checkpoint(journal_t *journal)
+ * OK, we need to start writing disk blocks. Take one transaction
+ * and write it.
+ */
+- result = 0;
+ spin_lock(&journal->j_list_lock);
+ if (!journal->j_checkpoint_transactions)
+ goto out;
+@@ -251,15 +228,6 @@ int jbd2_log_do_checkpoint(journal_t *journal)
+ jh = transaction->t_checkpoint_list;
+ bh = jh2bh(jh);
+
+- if (buffer_locked(bh)) {
+- get_bh(bh);
+- spin_unlock(&journal->j_list_lock);
+- wait_on_buffer(bh);
+- /* the journal_head may have gone by now */
+- BUFFER_TRACE(bh, "brelse");
+- __brelse(bh);
+- goto retry;
+- }
+ if (jh->b_transaction != NULL) {
+ transaction_t *t = jh->b_transaction;
+ tid_t tid = t->t_tid;
+@@ -294,32 +262,50 @@ int jbd2_log_do_checkpoint(journal_t *journal)
+ spin_lock(&journal->j_list_lock);
+ goto restart;
+ }
+- if (!buffer_dirty(bh)) {
+- if (unlikely(buffer_write_io_error(bh)) && !result)
+- result = -EIO;
++ if (!trylock_buffer(bh)) {
++ /*
++ * The buffer is locked, it may be writing back, or
++ * flushing out in the last couple of cycles, or
++ * re-adding into a new transaction, need to check
++ * it again until it's unlocked.
++ */
++ get_bh(bh);
++ spin_unlock(&journal->j_list_lock);
++ wait_on_buffer(bh);
++ /* the journal_head may have gone by now */
++ BUFFER_TRACE(bh, "brelse");
++ __brelse(bh);
++ goto retry;
++ } else if (!buffer_dirty(bh)) {
++ unlock_buffer(bh);
+ BUFFER_TRACE(bh, "remove from checkpoint");
+- if (__jbd2_journal_remove_checkpoint(jh))
+- /* The transaction was released; we're done */
++ /*
++ * If the transaction was released or the checkpoint
++ * list was empty, we're done.
++ */
++ if (__jbd2_journal_remove_checkpoint(jh) ||
++ !transaction->t_checkpoint_list)
+ goto out;
+- continue;
++ } else {
++ unlock_buffer(bh);
++ /*
++ * We are about to write the buffer, it could be
++ * raced by some other transaction shrink or buffer
++ * re-log logic once we release the j_list_lock,
++ * leave it on the checkpoint list and check status
++ * again to make sure it's clean.
++ */
++ BUFFER_TRACE(bh, "queue");
++ get_bh(bh);
++ J_ASSERT_BH(bh, !buffer_jwrite(bh));
++ journal->j_chkpt_bhs[batch_count++] = bh;
++ transaction->t_chp_stats.cs_written++;
++ transaction->t_checkpoint_list = jh->b_cpnext;
+ }
+- /*
+- * Important: we are about to write the buffer, and
+- * possibly block, while still holding the journal
+- * lock. We cannot afford to let the transaction
+- * logic start messing around with this buffer before
+- * we write it to disk, as that would break
+- * recoverability.
+- */
+- BUFFER_TRACE(bh, "queue");
+- get_bh(bh);
+- J_ASSERT_BH(bh, !buffer_jwrite(bh));
+- journal->j_chkpt_bhs[batch_count++] = bh;
+- __buffer_relink_io(jh);
+- transaction->t_chp_stats.cs_written++;
++
+ if ((batch_count == JBD2_NR_BATCH) ||
+- need_resched() ||
+- spin_needbreak(&journal->j_list_lock))
++ need_resched() || spin_needbreak(&journal->j_list_lock) ||
++ jh2bh(transaction->t_checkpoint_list) == journal->j_chkpt_bhs[0])
+ goto unlock_and_flush;
+ }
+
+@@ -333,46 +319,9 @@ int jbd2_log_do_checkpoint(journal_t *journal)
+ goto restart;
+ }
+
+- /*
+- * Now we issued all of the transaction's buffers, let's deal
+- * with the buffers that are out for I/O.
+- */
+-restart2:
+- /* Did somebody clean up the transaction in the meanwhile? */
+- if (journal->j_checkpoint_transactions != transaction ||
+- transaction->t_tid != this_tid)
+- goto out;
+-
+- while (transaction->t_checkpoint_io_list) {
+- jh = transaction->t_checkpoint_io_list;
+- bh = jh2bh(jh);
+- if (buffer_locked(bh)) {
+- get_bh(bh);
+- spin_unlock(&journal->j_list_lock);
+- wait_on_buffer(bh);
+- /* the journal_head may have gone by now */
+- BUFFER_TRACE(bh, "brelse");
+- __brelse(bh);
+- spin_lock(&journal->j_list_lock);
+- goto restart2;
+- }
+- if (unlikely(buffer_write_io_error(bh)) && !result)
+- result = -EIO;
+-
+- /*
+- * Now in whatever state the buffer currently is, we
+- * know that it has been written out and so we can
+- * drop it from the list
+- */
+- if (__jbd2_journal_remove_checkpoint(jh))
+- break;
+- }
+ out:
+ spin_unlock(&journal->j_list_lock);
+- if (result < 0)
+- jbd2_journal_abort(journal, result);
+- else
+- result = jbd2_cleanup_journal_tail(journal);
++ result = jbd2_cleanup_journal_tail(journal);
+
+ return (result < 0) ? result : 0;
+ }
+diff --git a/fs/zonefs/super.c b/fs/zonefs/super.c
+index b9522eee1257a..f9ecade9ea65b 100644
+--- a/fs/zonefs/super.c
++++ b/fs/zonefs/super.c
+@@ -319,16 +319,18 @@ static loff_t zonefs_check_zone_condition(struct inode *inode,
+ }
+ }
+
+-struct zonefs_ioerr_data {
+- struct inode *inode;
+- bool write;
+-};
+-
+ static int zonefs_io_error_cb(struct blk_zone *zone, unsigned int idx,
+ void *data)
+ {
+- struct zonefs_ioerr_data *err = data;
+- struct inode *inode = err->inode;
++ struct blk_zone *z = data;
++
++ *z = *zone;
++ return 0;
++}
++
++static void zonefs_handle_io_error(struct inode *inode, struct blk_zone *zone,
++ bool write)
++{
+ struct zonefs_inode_info *zi = ZONEFS_I(inode);
+ struct super_block *sb = inode->i_sb;
+ struct zonefs_sb_info *sbi = ZONEFS_SB(sb);
+@@ -344,8 +346,8 @@ static int zonefs_io_error_cb(struct blk_zone *zone, unsigned int idx,
+ isize = i_size_read(inode);
+ if (zone->cond != BLK_ZONE_COND_OFFLINE &&
+ zone->cond != BLK_ZONE_COND_READONLY &&
+- !err->write && isize == data_size)
+- return 0;
++ !write && isize == data_size)
++ return;
+
+ /*
+ * At this point, we detected either a bad zone or an inconsistency
+@@ -366,8 +368,9 @@ static int zonefs_io_error_cb(struct blk_zone *zone, unsigned int idx,
+ * In all cases, warn about inode size inconsistency and handle the
+ * IO error according to the zone condition and to the mount options.
+ */
+- if (zi->i_ztype == ZONEFS_ZTYPE_SEQ && isize != data_size)
+- zonefs_warn(sb, "inode %lu: invalid size %lld (should be %lld)\n",
++ if (isize != data_size)
++ zonefs_warn(sb,
++ "inode %lu: invalid size %lld (should be %lld)\n",
+ inode->i_ino, isize, data_size);
+
+ /*
+@@ -427,8 +430,6 @@ static int zonefs_io_error_cb(struct blk_zone *zone, unsigned int idx,
+ zonefs_update_stats(inode, data_size);
+ zonefs_i_size_write(inode, data_size);
+ zi->i_wpoffset = data_size;
+-
+- return 0;
+ }
+
+ /*
+@@ -442,23 +443,25 @@ static void __zonefs_io_error(struct inode *inode, bool write)
+ {
+ struct zonefs_inode_info *zi = ZONEFS_I(inode);
+ struct super_block *sb = inode->i_sb;
+- struct zonefs_sb_info *sbi = ZONEFS_SB(sb);
+ unsigned int noio_flag;
+- unsigned int nr_zones = 1;
+- struct zonefs_ioerr_data err = {
+- .inode = inode,
+- .write = write,
+- };
++ struct blk_zone zone;
+ int ret;
+
+ /*
+- * The only files that have more than one zone are conventional zone
+- * files with aggregated conventional zones, for which the inode zone
+- * size is always larger than the device zone size.
++ * Conventional zone have no write pointer and cannot become read-only
++ * or offline. So simply fake a report for a single or aggregated zone
++ * and let zonefs_handle_io_error() correct the zone inode information
++ * according to the mount options.
+ */
+- if (zi->i_zone_size > bdev_zone_sectors(sb->s_bdev))
+- nr_zones = zi->i_zone_size >>
+- (sbi->s_zone_sectors_shift + SECTOR_SHIFT);
++ if (zi->i_ztype != ZONEFS_ZTYPE_SEQ) {
++ zone.start = zi->i_zsector;
++ zone.len = zi->i_max_size >> SECTOR_SHIFT;
++ zone.wp = zone.start + zone.len;
++ zone.type = BLK_ZONE_TYPE_CONVENTIONAL;
++ zone.cond = BLK_ZONE_COND_NOT_WP;
++ zone.capacity = zone.len;
++ goto handle_io_error;
++ }
+
+ /*
+ * Memory allocations in blkdev_report_zones() can trigger a memory
+@@ -469,12 +472,19 @@ static void __zonefs_io_error(struct inode *inode, bool write)
+ * the GFP_NOIO context avoids both problems.
+ */
+ noio_flag = memalloc_noio_save();
+- ret = blkdev_report_zones(sb->s_bdev, zi->i_zsector, nr_zones,
+- zonefs_io_error_cb, &err);
+- if (ret != nr_zones)
++ ret = blkdev_report_zones(sb->s_bdev, zi->i_zsector, 1,
++ zonefs_io_error_cb, &zone);
++ memalloc_noio_restore(noio_flag);
++ if (ret != 1) {
+ zonefs_err(sb, "Get inode %lu zone information failed %d\n",
+ inode->i_ino, ret);
+- memalloc_noio_restore(noio_flag);
++ zonefs_warn(sb, "remounting filesystem read-only\n");
++ sb->s_flags |= SB_RDONLY;
++ return;
++ }
++
++handle_io_error:
++ zonefs_handle_io_error(inode, &zone, write);
+ }
+
+ static void zonefs_io_error(struct inode *inode, bool write)
+diff --git a/include/linux/fs.h b/include/linux/fs.h
+index 82316863c71fd..6de70634e5471 100644
+--- a/include/linux/fs.h
++++ b/include/linux/fs.h
+@@ -316,6 +316,8 @@ enum rw_hint {
+ /* iocb->ki_waitq is valid */
+ #define IOCB_WAITQ (1 << 19)
+ #define IOCB_NOIO (1 << 20)
++/* kiocb is a read or write operation submitted by fs/aio.c. */
++#define IOCB_AIO_RW (1 << 23)
+
+ struct kiocb {
+ struct file *ki_filp;
+diff --git a/include/linux/lockdep.h b/include/linux/lockdep.h
+index 2c2586312b447..3eca9f91b9a56 100644
+--- a/include/linux/lockdep.h
++++ b/include/linux/lockdep.h
+@@ -321,6 +321,10 @@ extern void lock_unpin_lock(struct lockdep_map *lock, struct pin_cookie);
+ WARN_ON_ONCE(debug_locks && !lockdep_is_held(l)); \
+ } while (0)
+
++#define lockdep_assert_none_held_once() do { \
++ WARN_ON_ONCE(debug_locks && current->lockdep_depth); \
++ } while (0)
++
+ #define lockdep_recursing(tsk) ((tsk)->lockdep_recursion)
+
+ #define lockdep_pin_lock(l) lock_pin_lock(&(l)->dep_map)
+@@ -394,6 +398,7 @@ static inline void lockdep_unregister_key(struct lock_class_key *key)
+ #define lockdep_assert_held_write(l) do { (void)(l); } while (0)
+ #define lockdep_assert_held_read(l) do { (void)(l); } while (0)
+ #define lockdep_assert_held_once(l) do { (void)(l); } while (0)
++#define lockdep_assert_none_held_once() do { } while (0)
+
+ #define lockdep_recursing(tsk) (0)
+
+diff --git a/include/linux/sched/task_stack.h b/include/linux/sched/task_stack.h
+index f24575942dabe..879a5c8f930b6 100644
+--- a/include/linux/sched/task_stack.h
++++ b/include/linux/sched/task_stack.h
+@@ -16,7 +16,7 @@
+ * try_get_task_stack() instead. task_stack_page will return a pointer
+ * that could get freed out from under you.
+ */
+-static inline void *task_stack_page(const struct task_struct *task)
++static __always_inline void *task_stack_page(const struct task_struct *task)
+ {
+ return task->stack;
+ }
+diff --git a/include/linux/socket.h b/include/linux/socket.h
+index c3b35d18bcd30..daf51fef5a8d1 100644
+--- a/include/linux/socket.h
++++ b/include/linux/socket.h
+@@ -31,7 +31,10 @@ typedef __kernel_sa_family_t sa_family_t;
+
+ struct sockaddr {
+ sa_family_t sa_family; /* address family, AF_xxx */
+- char sa_data[14]; /* 14 bytes of protocol address */
++ union {
++ char sa_data_min[14]; /* Minimum 14 bytes of protocol address */
++ DECLARE_FLEX_ARRAY(char, sa_data);
++ };
+ };
+
+ struct linger {
+diff --git a/include/net/tcp.h b/include/net/tcp.h
+index 5c03dc6d0f792..d6e4b6f7d6ce0 100644
+--- a/include/net/tcp.h
++++ b/include/net/tcp.h
+@@ -2224,7 +2224,7 @@ struct tcp_ulp_ops {
+ /* cleanup ulp */
+ void (*release)(struct sock *sk);
+ /* diagnostic */
+- int (*get_info)(const struct sock *sk, struct sk_buff *skb);
++ int (*get_info)(struct sock *sk, struct sk_buff *skb);
+ size_t (*get_info_size)(const struct sock *sk);
+ /* clone ulp */
+ void (*clone)(const struct request_sock *req, struct sock *newsk,
+diff --git a/kernel/sched/rt.c b/kernel/sched/rt.c
+index f690f901b6cc7..1289991c970e1 100644
+--- a/kernel/sched/rt.c
++++ b/kernel/sched/rt.c
+@@ -8,7 +8,7 @@
+ #include "pelt.h"
+
+ int sched_rr_timeslice = RR_TIMESLICE;
+-int sysctl_sched_rr_timeslice = (MSEC_PER_SEC / HZ) * RR_TIMESLICE;
++int sysctl_sched_rr_timeslice = (MSEC_PER_SEC * RR_TIMESLICE) / HZ;
+ /* More than 4 hours if BW_SHIFT equals 20. */
+ static const u64 max_rt_runtime = MAX_BW;
+
+@@ -2727,9 +2727,6 @@ static int sched_rt_global_constraints(void)
+
+ static int sched_rt_global_validate(void)
+ {
+- if (sysctl_sched_rt_period <= 0)
+- return -EINVAL;
+-
+ if ((sysctl_sched_rt_runtime != RUNTIME_INF) &&
+ ((sysctl_sched_rt_runtime > sysctl_sched_rt_period) ||
+ ((u64)sysctl_sched_rt_runtime *
+@@ -2760,7 +2757,7 @@ int sched_rt_handler(struct ctl_table *table, int write, void *buffer,
+ old_period = sysctl_sched_rt_period;
+ old_runtime = sysctl_sched_rt_runtime;
+
+- ret = proc_dointvec(table, write, buffer, lenp, ppos);
++ ret = proc_dointvec_minmax(table, write, buffer, lenp, ppos);
+
+ if (!ret && write) {
+ ret = sched_rt_global_validate();
+@@ -2804,6 +2801,9 @@ int sched_rr_handler(struct ctl_table *table, int write, void *buffer,
+ sched_rr_timeslice =
+ sysctl_sched_rr_timeslice <= 0 ? RR_TIMESLICE :
+ msecs_to_jiffies(sysctl_sched_rr_timeslice);
++
++ if (sysctl_sched_rr_timeslice <= 0)
++ sysctl_sched_rr_timeslice = jiffies_to_msecs(RR_TIMESLICE);
+ }
+ mutex_unlock(&mutex);
+
+diff --git a/kernel/seccomp.c b/kernel/seccomp.c
+index 305f0eca163ed..0b0331346e4be 100644
+--- a/kernel/seccomp.c
++++ b/kernel/seccomp.c
+@@ -29,6 +29,9 @@
+ #include <linux/syscalls.h>
+ #include <linux/sysctl.h>
+
++/* Not exposed in headers: strictly internal use only. */
++#define SECCOMP_MODE_DEAD (SECCOMP_MODE_FILTER + 1)
++
+ #ifdef CONFIG_HAVE_ARCH_SECCOMP_FILTER
+ #include <asm/syscall.h>
+ #endif
+@@ -795,6 +798,7 @@ static void __secure_computing_strict(int this_syscall)
+ #ifdef SECCOMP_DEBUG
+ dump_stack();
+ #endif
++ current->seccomp.mode = SECCOMP_MODE_DEAD;
+ seccomp_log(this_syscall, SIGKILL, SECCOMP_RET_KILL_THREAD, true);
+ do_exit(SIGKILL);
+ }
+@@ -1023,6 +1027,7 @@ static int __seccomp_filter(int this_syscall, const struct seccomp_data *sd,
+ case SECCOMP_RET_KILL_THREAD:
+ case SECCOMP_RET_KILL_PROCESS:
+ default:
++ current->seccomp.mode = SECCOMP_MODE_DEAD;
+ seccomp_log(this_syscall, SIGSYS, action, true);
+ /* Dump core only if this is the last remaining thread. */
+ if (action != SECCOMP_RET_KILL_THREAD ||
+@@ -1075,6 +1080,11 @@ int __secure_computing(const struct seccomp_data *sd)
+ return 0;
+ case SECCOMP_MODE_FILTER:
+ return __seccomp_filter(this_syscall, sd, false);
++ /* Surviving SECCOMP_RET_KILL_* must be proactively impossible. */
++ case SECCOMP_MODE_DEAD:
++ WARN_ON_ONCE(1);
++ do_exit(SIGKILL);
++ return -1;
+ default:
+ BUG();
+ }
+diff --git a/kernel/sysctl.c b/kernel/sysctl.c
+index a45f0dd10b9a3..99a19190196e0 100644
+--- a/kernel/sysctl.c
++++ b/kernel/sysctl.c
+@@ -1859,6 +1859,8 @@ static struct ctl_table kern_table[] = {
+ .maxlen = sizeof(unsigned int),
+ .mode = 0644,
+ .proc_handler = sched_rt_handler,
++ .extra1 = SYSCTL_ONE,
++ .extra2 = SYSCTL_INT_MAX,
+ },
+ {
+ .procname = "sched_rt_runtime_us",
+@@ -1866,6 +1868,8 @@ static struct ctl_table kern_table[] = {
+ .maxlen = sizeof(int),
+ .mode = 0644,
+ .proc_handler = sched_rt_handler,
++ .extra1 = SYSCTL_NEG_ONE,
++ .extra2 = SYSCTL_INT_MAX,
+ },
+ {
+ .procname = "sched_deadline_period_max_us",
+diff --git a/mm/userfaultfd.c b/mm/userfaultfd.c
+index 078d95cd32c53..c28ff36f5b311 100644
+--- a/mm/userfaultfd.c
++++ b/mm/userfaultfd.c
+@@ -209,6 +209,7 @@ static __always_inline ssize_t __mcopy_atomic_hugetlb(struct mm_struct *dst_mm,
+ unsigned long dst_start,
+ unsigned long src_start,
+ unsigned long len,
++ bool *mmap_changing,
+ bool zeropage)
+ {
+ int vm_alloc_shared = dst_vma->vm_flags & VM_SHARED;
+@@ -329,6 +330,15 @@ static __always_inline ssize_t __mcopy_atomic_hugetlb(struct mm_struct *dst_mm,
+ goto out;
+ }
+ mmap_read_lock(dst_mm);
++ /*
++ * If memory mappings are changing because of non-cooperative
++ * operation (e.g. mremap) running in parallel, bail out and
++ * request the user to retry later
++ */
++ if (mmap_changing && READ_ONCE(*mmap_changing)) {
++ err = -EAGAIN;
++ break;
++ }
+
+ dst_vma = NULL;
+ goto retry;
+@@ -410,6 +420,7 @@ extern ssize_t __mcopy_atomic_hugetlb(struct mm_struct *dst_mm,
+ unsigned long dst_start,
+ unsigned long src_start,
+ unsigned long len,
++ bool *mmap_changing,
+ bool zeropage);
+ #endif /* CONFIG_HUGETLB_PAGE */
+
+@@ -529,7 +540,8 @@ static __always_inline ssize_t __mcopy_atomic(struct mm_struct *dst_mm,
+ */
+ if (is_vm_hugetlb_page(dst_vma))
+ return __mcopy_atomic_hugetlb(dst_mm, dst_vma, dst_start,
+- src_start, len, zeropage);
++ src_start, len, mmap_changing,
++ zeropage);
+
+ if (!vma_is_anonymous(dst_vma) && !vma_is_shmem(dst_vma))
+ goto out_unlock;
+diff --git a/net/core/dev.c b/net/core/dev.c
+index fc881d60a9dcc..0619d2253aa24 100644
+--- a/net/core/dev.c
++++ b/net/core/dev.c
+@@ -8787,7 +8787,7 @@ EXPORT_SYMBOL(dev_set_mac_address_user);
+
+ int dev_get_mac_address(struct sockaddr *sa, struct net *net, char *dev_name)
+ {
+- size_t size = sizeof(sa->sa_data);
++ size_t size = sizeof(sa->sa_data_min);
+ struct net_device *dev;
+ int ret = 0;
+
+diff --git a/net/core/dev_ioctl.c b/net/core/dev_ioctl.c
+index 993420da29307..60e815a71909a 100644
+--- a/net/core/dev_ioctl.c
++++ b/net/core/dev_ioctl.c
+@@ -245,7 +245,7 @@ static int dev_ifsioc(struct net *net, struct ifreq *ifr, unsigned int cmd)
+ if (ifr->ifr_hwaddr.sa_family != dev->type)
+ return -EINVAL;
+ memcpy(dev->broadcast, ifr->ifr_hwaddr.sa_data,
+- min(sizeof(ifr->ifr_hwaddr.sa_data),
++ min(sizeof(ifr->ifr_hwaddr.sa_data_min),
+ (size_t)dev->addr_len));
+ call_netdevice_notifiers(NETDEV_CHANGEADDR, dev);
+ return 0;
+diff --git a/net/hsr/hsr_framereg.c b/net/hsr/hsr_framereg.c
+index afc97d65cf2d8..87fc86aade5c9 100644
+--- a/net/hsr/hsr_framereg.c
++++ b/net/hsr/hsr_framereg.c
+@@ -327,9 +327,12 @@ void hsr_handle_sup_frame(struct hsr_frame_info *frame)
+ node_real->addr_B_port = port_rcv->type;
+
+ spin_lock_bh(&hsr->list_lock);
+- list_del_rcu(&node_curr->mac_list);
++ if (!node_curr->removed) {
++ list_del_rcu(&node_curr->mac_list);
++ node_curr->removed = true;
++ kfree_rcu(node_curr, rcu_head);
++ }
+ spin_unlock_bh(&hsr->list_lock);
+- kfree_rcu(node_curr, rcu_head);
+
+ done:
+ /* PRP uses v0 header */
+@@ -506,9 +509,12 @@ void hsr_prune_nodes(struct timer_list *t)
+ if (time_is_before_jiffies(timestamp +
+ msecs_to_jiffies(HSR_NODE_FORGET_TIME))) {
+ hsr_nl_nodedown(hsr, node->macaddress_A);
+- list_del_rcu(&node->mac_list);
+- /* Note that we need to free this entry later: */
+- kfree_rcu(node, rcu_head);
++ if (!node->removed) {
++ list_del_rcu(&node->mac_list);
++ node->removed = true;
++ /* Note that we need to free this entry later: */
++ kfree_rcu(node, rcu_head);
++ }
+ }
+ }
+ spin_unlock_bh(&hsr->list_lock);
+diff --git a/net/hsr/hsr_framereg.h b/net/hsr/hsr_framereg.h
+index 5a771cb3f0325..48990166e4c4e 100644
+--- a/net/hsr/hsr_framereg.h
++++ b/net/hsr/hsr_framereg.h
+@@ -82,6 +82,7 @@ struct hsr_node {
+ bool san_a;
+ bool san_b;
+ u16 seq_out[HSR_PT_PORTS];
++ bool removed;
+ struct rcu_head rcu_head;
+ };
+
+diff --git a/net/ipv4/arp.c b/net/ipv4/arp.c
+index 83a47998c4b18..8ae9bd6f91c19 100644
+--- a/net/ipv4/arp.c
++++ b/net/ipv4/arp.c
+@@ -1104,7 +1104,8 @@ static int arp_req_get(struct arpreq *r, struct net_device *dev)
+ if (neigh) {
+ if (!(neigh->nud_state & NUD_NOARP)) {
+ read_lock_bh(&neigh->lock);
+- memcpy(r->arp_ha.sa_data, neigh->ha, dev->addr_len);
++ memcpy(r->arp_ha.sa_data, neigh->ha,
++ min(dev->addr_len, (unsigned char)sizeof(r->arp_ha.sa_data_min)));
+ r->arp_flags = arp_state_to_flags(neigh);
+ read_unlock_bh(&neigh->lock);
+ r->arp_ha.sa_family = dev->type;
+diff --git a/net/ipv4/devinet.c b/net/ipv4/devinet.c
+index da1ca8081c035..9ac7d47d27b81 100644
+--- a/net/ipv4/devinet.c
++++ b/net/ipv4/devinet.c
+@@ -1798,6 +1798,21 @@ static int in_dev_dump_addr(struct in_device *in_dev, struct sk_buff *skb,
+ return err;
+ }
+
++/* Combine dev_addr_genid and dev_base_seq to detect changes.
++ */
++static u32 inet_base_seq(const struct net *net)
++{
++ u32 res = atomic_read(&net->ipv4.dev_addr_genid) +
++ net->dev_base_seq;
++
++ /* Must not return 0 (see nl_dump_check_consistent()).
++ * Chose a value far away from 0.
++ */
++ if (!res)
++ res = 0x80000000;
++ return res;
++}
++
+ static int inet_dump_ifaddr(struct sk_buff *skb, struct netlink_callback *cb)
+ {
+ const struct nlmsghdr *nlh = cb->nlh;
+@@ -1849,8 +1864,7 @@ static int inet_dump_ifaddr(struct sk_buff *skb, struct netlink_callback *cb)
+ idx = 0;
+ head = &tgt_net->dev_index_head[h];
+ rcu_read_lock();
+- cb->seq = atomic_read(&tgt_net->ipv4.dev_addr_genid) ^
+- tgt_net->dev_base_seq;
++ cb->seq = inet_base_seq(tgt_net);
+ hlist_for_each_entry_rcu(dev, head, index_hlist) {
+ if (idx < s_idx)
+ goto cont;
+@@ -2249,8 +2263,7 @@ static int inet_netconf_dump_devconf(struct sk_buff *skb,
+ idx = 0;
+ head = &net->dev_index_head[h];
+ rcu_read_lock();
+- cb->seq = atomic_read(&net->ipv4.dev_addr_genid) ^
+- net->dev_base_seq;
++ cb->seq = inet_base_seq(net);
+ hlist_for_each_entry_rcu(dev, head, index_hlist) {
+ if (idx < s_idx)
+ goto cont;
+diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c
+index 79787a1f5ab34..150c2f71ec89f 100644
+--- a/net/ipv6/addrconf.c
++++ b/net/ipv6/addrconf.c
+@@ -698,6 +698,22 @@ static int inet6_netconf_get_devconf(struct sk_buff *in_skb,
+ return err;
+ }
+
++/* Combine dev_addr_genid and dev_base_seq to detect changes.
++ */
++static u32 inet6_base_seq(const struct net *net)
++{
++ u32 res = atomic_read(&net->ipv6.dev_addr_genid) +
++ net->dev_base_seq;
++
++ /* Must not return 0 (see nl_dump_check_consistent()).
++ * Chose a value far away from 0.
++ */
++ if (!res)
++ res = 0x80000000;
++ return res;
++}
++
++
+ static int inet6_netconf_dump_devconf(struct sk_buff *skb,
+ struct netlink_callback *cb)
+ {
+@@ -731,8 +747,7 @@ static int inet6_netconf_dump_devconf(struct sk_buff *skb,
+ idx = 0;
+ head = &net->dev_index_head[h];
+ rcu_read_lock();
+- cb->seq = atomic_read(&net->ipv6.dev_addr_genid) ^
+- net->dev_base_seq;
++ cb->seq = inet6_base_seq(net);
+ hlist_for_each_entry_rcu(dev, head, index_hlist) {
+ if (idx < s_idx)
+ goto cont;
+@@ -5288,7 +5303,7 @@ static int inet6_dump_addr(struct sk_buff *skb, struct netlink_callback *cb,
+ }
+
+ rcu_read_lock();
+- cb->seq = atomic_read(&tgt_net->ipv6.dev_addr_genid) ^ tgt_net->dev_base_seq;
++ cb->seq = inet6_base_seq(tgt_net);
+ for (h = s_h; h < NETDEV_HASHENTRIES; h++, s_idx = 0) {
+ idx = 0;
+ head = &tgt_net->dev_index_head[h];
+diff --git a/net/ipv6/seg6.c b/net/ipv6/seg6.c
+index 2278c0234c497..a8439fded12dc 100644
+--- a/net/ipv6/seg6.c
++++ b/net/ipv6/seg6.c
+@@ -451,22 +451,24 @@ int __init seg6_init(void)
+ {
+ int err;
+
+- err = genl_register_family(&seg6_genl_family);
++ err = register_pernet_subsys(&ip6_segments_ops);
+ if (err)
+ goto out;
+
+- err = register_pernet_subsys(&ip6_segments_ops);
++ err = genl_register_family(&seg6_genl_family);
+ if (err)
+- goto out_unregister_genl;
++ goto out_unregister_pernet;
+
+ #ifdef CONFIG_IPV6_SEG6_LWTUNNEL
+ err = seg6_iptunnel_init();
+ if (err)
+- goto out_unregister_pernet;
++ goto out_unregister_genl;
+
+ err = seg6_local_init();
+- if (err)
+- goto out_unregister_pernet;
++ if (err) {
++ seg6_iptunnel_exit();
++ goto out_unregister_genl;
++ }
+ #endif
+
+ #ifdef CONFIG_IPV6_SEG6_HMAC
+@@ -487,11 +489,11 @@ int __init seg6_init(void)
+ #endif
+ #endif
+ #ifdef CONFIG_IPV6_SEG6_LWTUNNEL
+-out_unregister_pernet:
+- unregister_pernet_subsys(&ip6_segments_ops);
+-#endif
+ out_unregister_genl:
+ genl_unregister_family(&seg6_genl_family);
++#endif
++out_unregister_pernet:
++ unregister_pernet_subsys(&ip6_segments_ops);
+ goto out;
+ }
+
+diff --git a/net/l2tp/l2tp_ip6.c b/net/l2tp/l2tp_ip6.c
+index 9746c624a5503..eb3d81bcce6d2 100644
+--- a/net/l2tp/l2tp_ip6.c
++++ b/net/l2tp/l2tp_ip6.c
+@@ -628,7 +628,7 @@ static int l2tp_ip6_sendmsg(struct sock *sk, struct msghdr *msg, size_t len)
+
+ back_from_confirm:
+ lock_sock(sk);
+- ulen = len + skb_queue_empty(&sk->sk_write_queue) ? transhdrlen : 0;
++ ulen = len + (skb_queue_empty(&sk->sk_write_queue) ? transhdrlen : 0);
+ err = ip6_append_data(sk, ip_generic_getfrag, msg,
+ ulen, transhdrlen, &ipc6,
+ &fl6, (struct rt6_info *)dst,
+diff --git a/net/mac80211/sta_info.c b/net/mac80211/sta_info.c
+index 2e84360990f0c..44bd03c6b8473 100644
+--- a/net/mac80211/sta_info.c
++++ b/net/mac80211/sta_info.c
+@@ -700,6 +700,8 @@ static int sta_info_insert_finish(struct sta_info *sta) __acquires(RCU)
+ if (ieee80211_vif_is_mesh(&sdata->vif))
+ mesh_accept_plinks_update(sdata);
+
++ ieee80211_check_fast_xmit(sta);
++
+ return 0;
+ out_remove:
+ sta_info_hash_del(local, sta);
+diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c
+index 55abc06214c4d..0d6d12fc3c07e 100644
+--- a/net/mac80211/tx.c
++++ b/net/mac80211/tx.c
+@@ -2959,7 +2959,7 @@ void ieee80211_check_fast_xmit(struct sta_info *sta)
+ sdata->vif.type == NL80211_IFTYPE_STATION)
+ goto out;
+
+- if (!test_sta_flag(sta, WLAN_STA_AUTHORIZED))
++ if (!test_sta_flag(sta, WLAN_STA_AUTHORIZED) || !sta->uploaded)
+ goto out;
+
+ if (test_sta_flag(sta, WLAN_STA_PS_STA) ||
+diff --git a/net/mptcp/diag.c b/net/mptcp/diag.c
+index a536586742f28..e57c5f47f0351 100644
+--- a/net/mptcp/diag.c
++++ b/net/mptcp/diag.c
+@@ -13,17 +13,19 @@
+ #include <uapi/linux/mptcp.h>
+ #include "protocol.h"
+
+-static int subflow_get_info(const struct sock *sk, struct sk_buff *skb)
++static int subflow_get_info(struct sock *sk, struct sk_buff *skb)
+ {
+ struct mptcp_subflow_context *sf;
+ struct nlattr *start;
+ u32 flags = 0;
++ bool slow;
+ int err;
+
+ start = nla_nest_start_noflag(skb, INET_ULP_INFO_MPTCP);
+ if (!start)
+ return -EMSGSIZE;
+
++ slow = lock_sock_fast(sk);
+ rcu_read_lock();
+ sf = rcu_dereference(inet_csk(sk)->icsk_ulp_data);
+ if (!sf) {
+@@ -69,11 +71,13 @@ static int subflow_get_info(const struct sock *sk, struct sk_buff *skb)
+ }
+
+ rcu_read_unlock();
++ unlock_sock_fast(sk, slow);
+ nla_nest_end(skb, start);
+ return 0;
+
+ nla_failure:
+ rcu_read_unlock();
++ unlock_sock_fast(sk, slow);
+ nla_nest_cancel(skb, start);
+ return err;
+ }
+diff --git a/net/netfilter/nf_conntrack_proto_sctp.c b/net/netfilter/nf_conntrack_proto_sctp.c
+index e7545bcca805e..6b2a215b27862 100644
+--- a/net/netfilter/nf_conntrack_proto_sctp.c
++++ b/net/netfilter/nf_conntrack_proto_sctp.c
+@@ -299,7 +299,7 @@ sctp_new(struct nf_conn *ct, const struct sk_buff *skb,
+ pr_debug("Setting vtag %x for secondary conntrack\n",
+ sh->vtag);
+ ct->proto.sctp.vtag[IP_CT_DIR_ORIGINAL] = sh->vtag;
+- } else {
++ } else if (sch->type == SCTP_CID_SHUTDOWN_ACK) {
+ /* If it is a shutdown ack OOTB packet, we expect a return
+ shutdown complete, otherwise an ABORT Sec 8.4 (5) and (8) */
+ pr_debug("Setting vtag %x for new conn OOTB\n",
+diff --git a/net/netfilter/nf_tables_api.c b/net/netfilter/nf_tables_api.c
+index f586e8b3c6cfa..73b0a6925304c 100644
+--- a/net/netfilter/nf_tables_api.c
++++ b/net/netfilter/nf_tables_api.c
+@@ -1132,6 +1132,7 @@ static int nf_tables_updtable(struct nft_ctx *ctx)
+ return 0;
+
+ err_register_hooks:
++ ctx->table->flags |= NFT_TABLE_F_DORMANT;
+ nft_trans_destroy(trans);
+ return ret;
+ }
+diff --git a/net/packet/af_packet.c b/net/packet/af_packet.c
+index b292d58fdcc4c..6cc054dd53b6e 100644
+--- a/net/packet/af_packet.c
++++ b/net/packet/af_packet.c
+@@ -1871,7 +1871,7 @@ static int packet_rcv_spkt(struct sk_buff *skb, struct net_device *dev,
+ */
+
+ spkt->spkt_family = dev->type;
+- strlcpy(spkt->spkt_device, dev->name, sizeof(spkt->spkt_device));
++ strscpy(spkt->spkt_device, dev->name, sizeof(spkt->spkt_device));
+ spkt->spkt_protocol = skb->protocol;
+
+ /*
+@@ -3252,7 +3252,7 @@ static int packet_bind_spkt(struct socket *sock, struct sockaddr *uaddr,
+ int addr_len)
+ {
+ struct sock *sk = sock->sk;
+- char name[sizeof(uaddr->sa_data) + 1];
++ char name[sizeof(uaddr->sa_data_min) + 1];
+
+ /*
+ * Check legality
+@@ -3263,8 +3263,8 @@ static int packet_bind_spkt(struct socket *sock, struct sockaddr *uaddr,
+ /* uaddr->sa_data comes from the userspace, it's not guaranteed to be
+ * zero-terminated.
+ */
+- memcpy(name, uaddr->sa_data, sizeof(uaddr->sa_data));
+- name[sizeof(uaddr->sa_data)] = 0;
++ memcpy(name, uaddr->sa_data, sizeof(uaddr->sa_data_min));
++ name[sizeof(uaddr->sa_data_min)] = 0;
+
+ return packet_do_bind(sk, name, 0, 0);
+ }
+@@ -3536,11 +3536,11 @@ static int packet_getname_spkt(struct socket *sock, struct sockaddr *uaddr,
+ return -EOPNOTSUPP;
+
+ uaddr->sa_family = AF_PACKET;
+- memset(uaddr->sa_data, 0, sizeof(uaddr->sa_data));
++ memset(uaddr->sa_data, 0, sizeof(uaddr->sa_data_min));
+ rcu_read_lock();
+ dev = dev_get_by_index_rcu(sock_net(sk), READ_ONCE(pkt_sk(sk)->ifindex));
+ if (dev)
+- strlcpy(uaddr->sa_data, dev->name, sizeof(uaddr->sa_data));
++ strscpy(uaddr->sa_data, dev->name, sizeof(uaddr->sa_data_min));
+ rcu_read_unlock();
+
+ return sizeof(*uaddr);
+diff --git a/net/sched/Kconfig b/net/sched/Kconfig
+index 2046c16b29f09..e5f7675e587b8 100644
+--- a/net/sched/Kconfig
++++ b/net/sched/Kconfig
+@@ -45,23 +45,6 @@ if NET_SCHED
+
+ comment "Queueing/Scheduling"
+
+-config NET_SCH_CBQ
+- tristate "Class Based Queueing (CBQ)"
+- help
+- Say Y here if you want to use the Class-Based Queueing (CBQ) packet
+- scheduling algorithm. This algorithm classifies the waiting packets
+- into a tree-like hierarchy of classes; the leaves of this tree are
+- in turn scheduled by separate algorithms.
+-
+- See the top of <file:net/sched/sch_cbq.c> for more details.
+-
+- CBQ is a commonly used scheduler, so if you're unsure, you should
+- say Y here. Then say Y to all the queueing algorithms below that you
+- want to use as leaf disciplines.
+-
+- To compile this code as a module, choose M here: the
+- module will be called sch_cbq.
+-
+ config NET_SCH_HTB
+ tristate "Hierarchical Token Bucket (HTB)"
+ help
+@@ -85,20 +68,6 @@ config NET_SCH_HFSC
+ To compile this code as a module, choose M here: the
+ module will be called sch_hfsc.
+
+-config NET_SCH_ATM
+- tristate "ATM Virtual Circuits (ATM)"
+- depends on ATM
+- help
+- Say Y here if you want to use the ATM pseudo-scheduler. This
+- provides a framework for invoking classifiers, which in turn
+- select classes of this queuing discipline. Each class maps
+- the flow(s) it is handling to a given virtual circuit.
+-
+- See the top of <file:net/sched/sch_atm.c> for more details.
+-
+- To compile this code as a module, choose M here: the
+- module will be called sch_atm.
+-
+ config NET_SCH_PRIO
+ tristate "Multi Band Priority Queueing (PRIO)"
+ help
+@@ -217,17 +186,6 @@ config NET_SCH_GRED
+ To compile this code as a module, choose M here: the
+ module will be called sch_gred.
+
+-config NET_SCH_DSMARK
+- tristate "Differentiated Services marker (DSMARK)"
+- help
+- Say Y if you want to schedule packets according to the
+- Differentiated Services architecture proposed in RFC 2475.
+- Technical information on this method, with pointers to associated
+- RFCs, is available at <http://www.gta.ufrj.br/diffserv/>.
+-
+- To compile this code as a module, choose M here: the
+- module will be called sch_dsmark.
+-
+ config NET_SCH_NETEM
+ tristate "Network emulator (NETEM)"
+ help
+diff --git a/net/sched/Makefile b/net/sched/Makefile
+index df2bcd785f7d1..1b8d0fc6614c2 100644
+--- a/net/sched/Makefile
++++ b/net/sched/Makefile
+@@ -32,20 +32,17 @@ obj-$(CONFIG_NET_ACT_TUNNEL_KEY)+= act_tunnel_key.o
+ obj-$(CONFIG_NET_ACT_CT) += act_ct.o
+ obj-$(CONFIG_NET_ACT_GATE) += act_gate.o
+ obj-$(CONFIG_NET_SCH_FIFO) += sch_fifo.o
+-obj-$(CONFIG_NET_SCH_CBQ) += sch_cbq.o
+ obj-$(CONFIG_NET_SCH_HTB) += sch_htb.o
+ obj-$(CONFIG_NET_SCH_HFSC) += sch_hfsc.o
+ obj-$(CONFIG_NET_SCH_RED) += sch_red.o
+ obj-$(CONFIG_NET_SCH_GRED) += sch_gred.o
+ obj-$(CONFIG_NET_SCH_INGRESS) += sch_ingress.o
+-obj-$(CONFIG_NET_SCH_DSMARK) += sch_dsmark.o
+ obj-$(CONFIG_NET_SCH_SFB) += sch_sfb.o
+ obj-$(CONFIG_NET_SCH_SFQ) += sch_sfq.o
+ obj-$(CONFIG_NET_SCH_TBF) += sch_tbf.o
+ obj-$(CONFIG_NET_SCH_TEQL) += sch_teql.o
+ obj-$(CONFIG_NET_SCH_PRIO) += sch_prio.o
+ obj-$(CONFIG_NET_SCH_MULTIQ) += sch_multiq.o
+-obj-$(CONFIG_NET_SCH_ATM) += sch_atm.o
+ obj-$(CONFIG_NET_SCH_NETEM) += sch_netem.o
+ obj-$(CONFIG_NET_SCH_DRR) += sch_drr.o
+ obj-$(CONFIG_NET_SCH_PLUG) += sch_plug.o
+diff --git a/net/sched/sch_atm.c b/net/sched/sch_atm.c
+deleted file mode 100644
+index 95967ce1f370a..0000000000000
+--- a/net/sched/sch_atm.c
++++ /dev/null
+@@ -1,709 +0,0 @@
+-// SPDX-License-Identifier: GPL-2.0-only
+-/* net/sched/sch_atm.c - ATM VC selection "queueing discipline" */
+-
+-/* Written 1998-2000 by Werner Almesberger, EPFL ICA */
+-
+-#include <linux/module.h>
+-#include <linux/slab.h>
+-#include <linux/init.h>
+-#include <linux/interrupt.h>
+-#include <linux/string.h>
+-#include <linux/errno.h>
+-#include <linux/skbuff.h>
+-#include <linux/atmdev.h>
+-#include <linux/atmclip.h>
+-#include <linux/rtnetlink.h>
+-#include <linux/file.h> /* for fput */
+-#include <net/netlink.h>
+-#include <net/pkt_sched.h>
+-#include <net/pkt_cls.h>
+-
+-/*
+- * The ATM queuing discipline provides a framework for invoking classifiers
+- * (aka "filters"), which in turn select classes of this queuing discipline.
+- * Each class maps the flow(s) it is handling to a given VC. Multiple classes
+- * may share the same VC.
+- *
+- * When creating a class, VCs are specified by passing the number of the open
+- * socket descriptor by which the calling process references the VC. The kernel
+- * keeps the VC open at least until all classes using it are removed.
+- *
+- * In this file, most functions are named atm_tc_* to avoid confusion with all
+- * the atm_* in net/atm. This naming convention differs from what's used in the
+- * rest of net/sched.
+- *
+- * Known bugs:
+- * - sometimes messes up the IP stack
+- * - any manipulations besides the few operations described in the README, are
+- * untested and likely to crash the system
+- * - should lock the flow while there is data in the queue (?)
+- */
+-
+-#define VCC2FLOW(vcc) ((struct atm_flow_data *) ((vcc)->user_back))
+-
+-struct atm_flow_data {
+- struct Qdisc_class_common common;
+- struct Qdisc *q; /* FIFO, TBF, etc. */
+- struct tcf_proto __rcu *filter_list;
+- struct tcf_block *block;
+- struct atm_vcc *vcc; /* VCC; NULL if VCC is closed */
+- void (*old_pop)(struct atm_vcc *vcc,
+- struct sk_buff *skb); /* chaining */
+- struct atm_qdisc_data *parent; /* parent qdisc */
+- struct socket *sock; /* for closing */
+- int ref; /* reference count */
+- struct gnet_stats_basic_packed bstats;
+- struct gnet_stats_queue qstats;
+- struct list_head list;
+- struct atm_flow_data *excess; /* flow for excess traffic;
+- NULL to set CLP instead */
+- int hdr_len;
+- unsigned char hdr[]; /* header data; MUST BE LAST */
+-};
+-
+-struct atm_qdisc_data {
+- struct atm_flow_data link; /* unclassified skbs go here */
+- struct list_head flows; /* NB: "link" is also on this
+- list */
+- struct tasklet_struct task; /* dequeue tasklet */
+-};
+-
+-/* ------------------------- Class/flow operations ------------------------- */
+-
+-static inline struct atm_flow_data *lookup_flow(struct Qdisc *sch, u32 classid)
+-{
+- struct atm_qdisc_data *p = qdisc_priv(sch);
+- struct atm_flow_data *flow;
+-
+- list_for_each_entry(flow, &p->flows, list) {
+- if (flow->common.classid == classid)
+- return flow;
+- }
+- return NULL;
+-}
+-
+-static int atm_tc_graft(struct Qdisc *sch, unsigned long arg,
+- struct Qdisc *new, struct Qdisc **old,
+- struct netlink_ext_ack *extack)
+-{
+- struct atm_qdisc_data *p = qdisc_priv(sch);
+- struct atm_flow_data *flow = (struct atm_flow_data *)arg;
+-
+- pr_debug("atm_tc_graft(sch %p,[qdisc %p],flow %p,new %p,old %p)\n",
+- sch, p, flow, new, old);
+- if (list_empty(&flow->list))
+- return -EINVAL;
+- if (!new)
+- new = &noop_qdisc;
+- *old = flow->q;
+- flow->q = new;
+- if (*old)
+- qdisc_reset(*old);
+- return 0;
+-}
+-
+-static struct Qdisc *atm_tc_leaf(struct Qdisc *sch, unsigned long cl)
+-{
+- struct atm_flow_data *flow = (struct atm_flow_data *)cl;
+-
+- pr_debug("atm_tc_leaf(sch %p,flow %p)\n", sch, flow);
+- return flow ? flow->q : NULL;
+-}
+-
+-static unsigned long atm_tc_find(struct Qdisc *sch, u32 classid)
+-{
+- struct atm_qdisc_data *p __maybe_unused = qdisc_priv(sch);
+- struct atm_flow_data *flow;
+-
+- pr_debug("%s(sch %p,[qdisc %p],classid %x)\n", __func__, sch, p, classid);
+- flow = lookup_flow(sch, classid);
+- pr_debug("%s: flow %p\n", __func__, flow);
+- return (unsigned long)flow;
+-}
+-
+-static unsigned long atm_tc_bind_filter(struct Qdisc *sch,
+- unsigned long parent, u32 classid)
+-{
+- struct atm_qdisc_data *p __maybe_unused = qdisc_priv(sch);
+- struct atm_flow_data *flow;
+-
+- pr_debug("%s(sch %p,[qdisc %p],classid %x)\n", __func__, sch, p, classid);
+- flow = lookup_flow(sch, classid);
+- if (flow)
+- flow->ref++;
+- pr_debug("%s: flow %p\n", __func__, flow);
+- return (unsigned long)flow;
+-}
+-
+-/*
+- * atm_tc_put handles all destructions, including the ones that are explicitly
+- * requested (atm_tc_destroy, etc.). The assumption here is that we never drop
+- * anything that still seems to be in use.
+- */
+-static void atm_tc_put(struct Qdisc *sch, unsigned long cl)
+-{
+- struct atm_qdisc_data *p = qdisc_priv(sch);
+- struct atm_flow_data *flow = (struct atm_flow_data *)cl;
+-
+- pr_debug("atm_tc_put(sch %p,[qdisc %p],flow %p)\n", sch, p, flow);
+- if (--flow->ref)
+- return;
+- pr_debug("atm_tc_put: destroying\n");
+- list_del_init(&flow->list);
+- pr_debug("atm_tc_put: qdisc %p\n", flow->q);
+- qdisc_put(flow->q);
+- tcf_block_put(flow->block);
+- if (flow->sock) {
+- pr_debug("atm_tc_put: f_count %ld\n",
+- file_count(flow->sock->file));
+- flow->vcc->pop = flow->old_pop;
+- sockfd_put(flow->sock);
+- }
+- if (flow->excess)
+- atm_tc_put(sch, (unsigned long)flow->excess);
+- if (flow != &p->link)
+- kfree(flow);
+- /*
+- * If flow == &p->link, the qdisc no longer works at this point and
+- * needs to be removed. (By the caller of atm_tc_put.)
+- */
+-}
+-
+-static void sch_atm_pop(struct atm_vcc *vcc, struct sk_buff *skb)
+-{
+- struct atm_qdisc_data *p = VCC2FLOW(vcc)->parent;
+-
+- pr_debug("sch_atm_pop(vcc %p,skb %p,[qdisc %p])\n", vcc, skb, p);
+- VCC2FLOW(vcc)->old_pop(vcc, skb);
+- tasklet_schedule(&p->task);
+-}
+-
+-static const u8 llc_oui_ip[] = {
+- 0xaa, /* DSAP: non-ISO */
+- 0xaa, /* SSAP: non-ISO */
+- 0x03, /* Ctrl: Unnumbered Information Command PDU */
+- 0x00, /* OUI: EtherType */
+- 0x00, 0x00,
+- 0x08, 0x00
+-}; /* Ethertype IP (0800) */
+-
+-static const struct nla_policy atm_policy[TCA_ATM_MAX + 1] = {
+- [TCA_ATM_FD] = { .type = NLA_U32 },
+- [TCA_ATM_EXCESS] = { .type = NLA_U32 },
+-};
+-
+-static int atm_tc_change(struct Qdisc *sch, u32 classid, u32 parent,
+- struct nlattr **tca, unsigned long *arg,
+- struct netlink_ext_ack *extack)
+-{
+- struct atm_qdisc_data *p = qdisc_priv(sch);
+- struct atm_flow_data *flow = (struct atm_flow_data *)*arg;
+- struct atm_flow_data *excess = NULL;
+- struct nlattr *opt = tca[TCA_OPTIONS];
+- struct nlattr *tb[TCA_ATM_MAX + 1];
+- struct socket *sock;
+- int fd, error, hdr_len;
+- void *hdr;
+-
+- pr_debug("atm_tc_change(sch %p,[qdisc %p],classid %x,parent %x,"
+- "flow %p,opt %p)\n", sch, p, classid, parent, flow, opt);
+- /*
+- * The concept of parents doesn't apply for this qdisc.
+- */
+- if (parent && parent != TC_H_ROOT && parent != sch->handle)
+- return -EINVAL;
+- /*
+- * ATM classes cannot be changed. In order to change properties of the
+- * ATM connection, that socket needs to be modified directly (via the
+- * native ATM API. In order to send a flow to a different VC, the old
+- * class needs to be removed and a new one added. (This may be changed
+- * later.)
+- */
+- if (flow)
+- return -EBUSY;
+- if (opt == NULL)
+- return -EINVAL;
+-
+- error = nla_parse_nested_deprecated(tb, TCA_ATM_MAX, opt, atm_policy,
+- NULL);
+- if (error < 0)
+- return error;
+-
+- if (!tb[TCA_ATM_FD])
+- return -EINVAL;
+- fd = nla_get_u32(tb[TCA_ATM_FD]);
+- pr_debug("atm_tc_change: fd %d\n", fd);
+- if (tb[TCA_ATM_HDR]) {
+- hdr_len = nla_len(tb[TCA_ATM_HDR]);
+- hdr = nla_data(tb[TCA_ATM_HDR]);
+- } else {
+- hdr_len = RFC1483LLC_LEN;
+- hdr = NULL; /* default LLC/SNAP for IP */
+- }
+- if (!tb[TCA_ATM_EXCESS])
+- excess = NULL;
+- else {
+- excess = (struct atm_flow_data *)
+- atm_tc_find(sch, nla_get_u32(tb[TCA_ATM_EXCESS]));
+- if (!excess)
+- return -ENOENT;
+- }
+- pr_debug("atm_tc_change: type %d, payload %d, hdr_len %d\n",
+- opt->nla_type, nla_len(opt), hdr_len);
+- sock = sockfd_lookup(fd, &error);
+- if (!sock)
+- return error; /* f_count++ */
+- pr_debug("atm_tc_change: f_count %ld\n", file_count(sock->file));
+- if (sock->ops->family != PF_ATMSVC && sock->ops->family != PF_ATMPVC) {
+- error = -EPROTOTYPE;
+- goto err_out;
+- }
+- /* @@@ should check if the socket is really operational or we'll crash
+- on vcc->send */
+- if (classid) {
+- if (TC_H_MAJ(classid ^ sch->handle)) {
+- pr_debug("atm_tc_change: classid mismatch\n");
+- error = -EINVAL;
+- goto err_out;
+- }
+- } else {
+- int i;
+- unsigned long cl;
+-
+- for (i = 1; i < 0x8000; i++) {
+- classid = TC_H_MAKE(sch->handle, 0x8000 | i);
+- cl = atm_tc_find(sch, classid);
+- if (!cl)
+- break;
+- }
+- }
+- pr_debug("atm_tc_change: new id %x\n", classid);
+- flow = kzalloc(sizeof(struct atm_flow_data) + hdr_len, GFP_KERNEL);
+- pr_debug("atm_tc_change: flow %p\n", flow);
+- if (!flow) {
+- error = -ENOBUFS;
+- goto err_out;
+- }
+-
+- error = tcf_block_get(&flow->block, &flow->filter_list, sch,
+- extack);
+- if (error) {
+- kfree(flow);
+- goto err_out;
+- }
+-
+- flow->q = qdisc_create_dflt(sch->dev_queue, &pfifo_qdisc_ops, classid,
+- extack);
+- if (!flow->q)
+- flow->q = &noop_qdisc;
+- pr_debug("atm_tc_change: qdisc %p\n", flow->q);
+- flow->sock = sock;
+- flow->vcc = ATM_SD(sock); /* speedup */
+- flow->vcc->user_back = flow;
+- pr_debug("atm_tc_change: vcc %p\n", flow->vcc);
+- flow->old_pop = flow->vcc->pop;
+- flow->parent = p;
+- flow->vcc->pop = sch_atm_pop;
+- flow->common.classid = classid;
+- flow->ref = 1;
+- flow->excess = excess;
+- list_add(&flow->list, &p->link.list);
+- flow->hdr_len = hdr_len;
+- if (hdr)
+- memcpy(flow->hdr, hdr, hdr_len);
+- else
+- memcpy(flow->hdr, llc_oui_ip, sizeof(llc_oui_ip));
+- *arg = (unsigned long)flow;
+- return 0;
+-err_out:
+- sockfd_put(sock);
+- return error;
+-}
+-
+-static int atm_tc_delete(struct Qdisc *sch, unsigned long arg)
+-{
+- struct atm_qdisc_data *p = qdisc_priv(sch);
+- struct atm_flow_data *flow = (struct atm_flow_data *)arg;
+-
+- pr_debug("atm_tc_delete(sch %p,[qdisc %p],flow %p)\n", sch, p, flow);
+- if (list_empty(&flow->list))
+- return -EINVAL;
+- if (rcu_access_pointer(flow->filter_list) || flow == &p->link)
+- return -EBUSY;
+- /*
+- * Reference count must be 2: one for "keepalive" (set at class
+- * creation), and one for the reference held when calling delete.
+- */
+- if (flow->ref < 2) {
+- pr_err("atm_tc_delete: flow->ref == %d\n", flow->ref);
+- return -EINVAL;
+- }
+- if (flow->ref > 2)
+- return -EBUSY; /* catch references via excess, etc. */
+- atm_tc_put(sch, arg);
+- return 0;
+-}
+-
+-static void atm_tc_walk(struct Qdisc *sch, struct qdisc_walker *walker)
+-{
+- struct atm_qdisc_data *p = qdisc_priv(sch);
+- struct atm_flow_data *flow;
+-
+- pr_debug("atm_tc_walk(sch %p,[qdisc %p],walker %p)\n", sch, p, walker);
+- if (walker->stop)
+- return;
+- list_for_each_entry(flow, &p->flows, list) {
+- if (walker->count >= walker->skip &&
+- walker->fn(sch, (unsigned long)flow, walker) < 0) {
+- walker->stop = 1;
+- break;
+- }
+- walker->count++;
+- }
+-}
+-
+-static struct tcf_block *atm_tc_tcf_block(struct Qdisc *sch, unsigned long cl,
+- struct netlink_ext_ack *extack)
+-{
+- struct atm_qdisc_data *p = qdisc_priv(sch);
+- struct atm_flow_data *flow = (struct atm_flow_data *)cl;
+-
+- pr_debug("atm_tc_find_tcf(sch %p,[qdisc %p],flow %p)\n", sch, p, flow);
+- return flow ? flow->block : p->link.block;
+-}
+-
+-/* --------------------------- Qdisc operations ---------------------------- */
+-
+-static int atm_tc_enqueue(struct sk_buff *skb, struct Qdisc *sch,
+- struct sk_buff **to_free)
+-{
+- struct atm_qdisc_data *p = qdisc_priv(sch);
+- struct atm_flow_data *flow;
+- struct tcf_result res;
+- int result;
+- int ret = NET_XMIT_SUCCESS | __NET_XMIT_BYPASS;
+-
+- pr_debug("atm_tc_enqueue(skb %p,sch %p,[qdisc %p])\n", skb, sch, p);
+- result = TC_ACT_OK; /* be nice to gcc */
+- flow = NULL;
+- if (TC_H_MAJ(skb->priority) != sch->handle ||
+- !(flow = (struct atm_flow_data *)atm_tc_find(sch, skb->priority))) {
+- struct tcf_proto *fl;
+-
+- list_for_each_entry(flow, &p->flows, list) {
+- fl = rcu_dereference_bh(flow->filter_list);
+- if (fl) {
+- result = tcf_classify(skb, fl, &res, true);
+- if (result < 0)
+- continue;
+- if (result == TC_ACT_SHOT)
+- goto done;
+-
+- flow = (struct atm_flow_data *)res.class;
+- if (!flow)
+- flow = lookup_flow(sch, res.classid);
+- goto drop;
+- }
+- }
+- flow = NULL;
+-done:
+- ;
+- }
+- if (!flow) {
+- flow = &p->link;
+- } else {
+- if (flow->vcc)
+- ATM_SKB(skb)->atm_options = flow->vcc->atm_options;
+- /*@@@ looks good ... but it's not supposed to work :-) */
+-#ifdef CONFIG_NET_CLS_ACT
+- switch (result) {
+- case TC_ACT_QUEUED:
+- case TC_ACT_STOLEN:
+- case TC_ACT_TRAP:
+- __qdisc_drop(skb, to_free);
+- return NET_XMIT_SUCCESS | __NET_XMIT_STOLEN;
+- case TC_ACT_SHOT:
+- __qdisc_drop(skb, to_free);
+- goto drop;
+- case TC_ACT_RECLASSIFY:
+- if (flow->excess)
+- flow = flow->excess;
+- else
+- ATM_SKB(skb)->atm_options |= ATM_ATMOPT_CLP;
+- break;
+- }
+-#endif
+- }
+-
+- ret = qdisc_enqueue(skb, flow->q, to_free);
+- if (ret != NET_XMIT_SUCCESS) {
+-drop: __maybe_unused
+- if (net_xmit_drop_count(ret)) {
+- qdisc_qstats_drop(sch);
+- if (flow)
+- flow->qstats.drops++;
+- }
+- return ret;
+- }
+- /*
+- * Okay, this may seem weird. We pretend we've dropped the packet if
+- * it goes via ATM. The reason for this is that the outer qdisc
+- * expects to be able to q->dequeue the packet later on if we return
+- * success at this place. Also, sch->q.qdisc needs to reflect whether
+- * there is a packet egligible for dequeuing or not. Note that the
+- * statistics of the outer qdisc are necessarily wrong because of all
+- * this. There's currently no correct solution for this.
+- */
+- if (flow == &p->link) {
+- sch->q.qlen++;
+- return NET_XMIT_SUCCESS;
+- }
+- tasklet_schedule(&p->task);
+- return NET_XMIT_SUCCESS | __NET_XMIT_BYPASS;
+-}
+-
+-/*
+- * Dequeue packets and send them over ATM. Note that we quite deliberately
+- * avoid checking net_device's flow control here, simply because sch_atm
+- * uses its own channels, which have nothing to do with any CLIP/LANE/or
+- * non-ATM interfaces.
+- */
+-
+-static void sch_atm_dequeue(unsigned long data)
+-{
+- struct Qdisc *sch = (struct Qdisc *)data;
+- struct atm_qdisc_data *p = qdisc_priv(sch);
+- struct atm_flow_data *flow;
+- struct sk_buff *skb;
+-
+- pr_debug("sch_atm_dequeue(sch %p,[qdisc %p])\n", sch, p);
+- list_for_each_entry(flow, &p->flows, list) {
+- if (flow == &p->link)
+- continue;
+- /*
+- * If traffic is properly shaped, this won't generate nasty
+- * little bursts. Otherwise, it may ... (but that's okay)
+- */
+- while ((skb = flow->q->ops->peek(flow->q))) {
+- if (!atm_may_send(flow->vcc, skb->truesize))
+- break;
+-
+- skb = qdisc_dequeue_peeked(flow->q);
+- if (unlikely(!skb))
+- break;
+-
+- qdisc_bstats_update(sch, skb);
+- bstats_update(&flow->bstats, skb);
+- pr_debug("atm_tc_dequeue: sending on class %p\n", flow);
+- /* remove any LL header somebody else has attached */
+- skb_pull(skb, skb_network_offset(skb));
+- if (skb_headroom(skb) < flow->hdr_len) {
+- struct sk_buff *new;
+-
+- new = skb_realloc_headroom(skb, flow->hdr_len);
+- dev_kfree_skb(skb);
+- if (!new)
+- continue;
+- skb = new;
+- }
+- pr_debug("sch_atm_dequeue: ip %p, data %p\n",
+- skb_network_header(skb), skb->data);
+- ATM_SKB(skb)->vcc = flow->vcc;
+- memcpy(skb_push(skb, flow->hdr_len), flow->hdr,
+- flow->hdr_len);
+- refcount_add(skb->truesize,
+- &sk_atm(flow->vcc)->sk_wmem_alloc);
+- /* atm.atm_options are already set by atm_tc_enqueue */
+- flow->vcc->send(flow->vcc, skb);
+- }
+- }
+-}
+-
+-static struct sk_buff *atm_tc_dequeue(struct Qdisc *sch)
+-{
+- struct atm_qdisc_data *p = qdisc_priv(sch);
+- struct sk_buff *skb;
+-
+- pr_debug("atm_tc_dequeue(sch %p,[qdisc %p])\n", sch, p);
+- tasklet_schedule(&p->task);
+- skb = qdisc_dequeue_peeked(p->link.q);
+- if (skb)
+- sch->q.qlen--;
+- return skb;
+-}
+-
+-static struct sk_buff *atm_tc_peek(struct Qdisc *sch)
+-{
+- struct atm_qdisc_data *p = qdisc_priv(sch);
+-
+- pr_debug("atm_tc_peek(sch %p,[qdisc %p])\n", sch, p);
+-
+- return p->link.q->ops->peek(p->link.q);
+-}
+-
+-static int atm_tc_init(struct Qdisc *sch, struct nlattr *opt,
+- struct netlink_ext_ack *extack)
+-{
+- struct atm_qdisc_data *p = qdisc_priv(sch);
+- int err;
+-
+- pr_debug("atm_tc_init(sch %p,[qdisc %p],opt %p)\n", sch, p, opt);
+- INIT_LIST_HEAD(&p->flows);
+- INIT_LIST_HEAD(&p->link.list);
+- list_add(&p->link.list, &p->flows);
+- p->link.q = qdisc_create_dflt(sch->dev_queue,
+- &pfifo_qdisc_ops, sch->handle, extack);
+- if (!p->link.q)
+- p->link.q = &noop_qdisc;
+- pr_debug("atm_tc_init: link (%p) qdisc %p\n", &p->link, p->link.q);
+- p->link.vcc = NULL;
+- p->link.sock = NULL;
+- p->link.common.classid = sch->handle;
+- p->link.ref = 1;
+-
+- err = tcf_block_get(&p->link.block, &p->link.filter_list, sch,
+- extack);
+- if (err)
+- return err;
+-
+- tasklet_init(&p->task, sch_atm_dequeue, (unsigned long)sch);
+- return 0;
+-}
+-
+-static void atm_tc_reset(struct Qdisc *sch)
+-{
+- struct atm_qdisc_data *p = qdisc_priv(sch);
+- struct atm_flow_data *flow;
+-
+- pr_debug("atm_tc_reset(sch %p,[qdisc %p])\n", sch, p);
+- list_for_each_entry(flow, &p->flows, list)
+- qdisc_reset(flow->q);
+-}
+-
+-static void atm_tc_destroy(struct Qdisc *sch)
+-{
+- struct atm_qdisc_data *p = qdisc_priv(sch);
+- struct atm_flow_data *flow, *tmp;
+-
+- pr_debug("atm_tc_destroy(sch %p,[qdisc %p])\n", sch, p);
+- list_for_each_entry(flow, &p->flows, list) {
+- tcf_block_put(flow->block);
+- flow->block = NULL;
+- }
+-
+- list_for_each_entry_safe(flow, tmp, &p->flows, list) {
+- if (flow->ref > 1)
+- pr_err("atm_destroy: %p->ref = %d\n", flow, flow->ref);
+- atm_tc_put(sch, (unsigned long)flow);
+- }
+- tasklet_kill(&p->task);
+-}
+-
+-static int atm_tc_dump_class(struct Qdisc *sch, unsigned long cl,
+- struct sk_buff *skb, struct tcmsg *tcm)
+-{
+- struct atm_qdisc_data *p = qdisc_priv(sch);
+- struct atm_flow_data *flow = (struct atm_flow_data *)cl;
+- struct nlattr *nest;
+-
+- pr_debug("atm_tc_dump_class(sch %p,[qdisc %p],flow %p,skb %p,tcm %p)\n",
+- sch, p, flow, skb, tcm);
+- if (list_empty(&flow->list))
+- return -EINVAL;
+- tcm->tcm_handle = flow->common.classid;
+- tcm->tcm_info = flow->q->handle;
+-
+- nest = nla_nest_start_noflag(skb, TCA_OPTIONS);
+- if (nest == NULL)
+- goto nla_put_failure;
+-
+- if (nla_put(skb, TCA_ATM_HDR, flow->hdr_len, flow->hdr))
+- goto nla_put_failure;
+- if (flow->vcc) {
+- struct sockaddr_atmpvc pvc;
+- int state;
+-
+- memset(&pvc, 0, sizeof(pvc));
+- pvc.sap_family = AF_ATMPVC;
+- pvc.sap_addr.itf = flow->vcc->dev ? flow->vcc->dev->number : -1;
+- pvc.sap_addr.vpi = flow->vcc->vpi;
+- pvc.sap_addr.vci = flow->vcc->vci;
+- if (nla_put(skb, TCA_ATM_ADDR, sizeof(pvc), &pvc))
+- goto nla_put_failure;
+- state = ATM_VF2VS(flow->vcc->flags);
+- if (nla_put_u32(skb, TCA_ATM_STATE, state))
+- goto nla_put_failure;
+- }
+- if (flow->excess) {
+- if (nla_put_u32(skb, TCA_ATM_EXCESS, flow->common.classid))
+- goto nla_put_failure;
+- } else {
+- if (nla_put_u32(skb, TCA_ATM_EXCESS, 0))
+- goto nla_put_failure;
+- }
+- return nla_nest_end(skb, nest);
+-
+-nla_put_failure:
+- nla_nest_cancel(skb, nest);
+- return -1;
+-}
+-static int
+-atm_tc_dump_class_stats(struct Qdisc *sch, unsigned long arg,
+- struct gnet_dump *d)
+-{
+- struct atm_flow_data *flow = (struct atm_flow_data *)arg;
+-
+- if (gnet_stats_copy_basic(qdisc_root_sleeping_running(sch),
+- d, NULL, &flow->bstats) < 0 ||
+- gnet_stats_copy_queue(d, NULL, &flow->qstats, flow->q->q.qlen) < 0)
+- return -1;
+-
+- return 0;
+-}
+-
+-static int atm_tc_dump(struct Qdisc *sch, struct sk_buff *skb)
+-{
+- return 0;
+-}
+-
+-static const struct Qdisc_class_ops atm_class_ops = {
+- .graft = atm_tc_graft,
+- .leaf = atm_tc_leaf,
+- .find = atm_tc_find,
+- .change = atm_tc_change,
+- .delete = atm_tc_delete,
+- .walk = atm_tc_walk,
+- .tcf_block = atm_tc_tcf_block,
+- .bind_tcf = atm_tc_bind_filter,
+- .unbind_tcf = atm_tc_put,
+- .dump = atm_tc_dump_class,
+- .dump_stats = atm_tc_dump_class_stats,
+-};
+-
+-static struct Qdisc_ops atm_qdisc_ops __read_mostly = {
+- .cl_ops = &atm_class_ops,
+- .id = "atm",
+- .priv_size = sizeof(struct atm_qdisc_data),
+- .enqueue = atm_tc_enqueue,
+- .dequeue = atm_tc_dequeue,
+- .peek = atm_tc_peek,
+- .init = atm_tc_init,
+- .reset = atm_tc_reset,
+- .destroy = atm_tc_destroy,
+- .dump = atm_tc_dump,
+- .owner = THIS_MODULE,
+-};
+-
+-static int __init atm_init(void)
+-{
+- return register_qdisc(&atm_qdisc_ops);
+-}
+-
+-static void __exit atm_exit(void)
+-{
+- unregister_qdisc(&atm_qdisc_ops);
+-}
+-
+-module_init(atm_init)
+-module_exit(atm_exit)
+-MODULE_LICENSE("GPL");
+diff --git a/net/sched/sch_cbq.c b/net/sched/sch_cbq.c
+deleted file mode 100644
+index 3da5eb313c246..0000000000000
+--- a/net/sched/sch_cbq.c
++++ /dev/null
+@@ -1,1816 +0,0 @@
+-// SPDX-License-Identifier: GPL-2.0-or-later
+-/*
+- * net/sched/sch_cbq.c Class-Based Queueing discipline.
+- *
+- * Authors: Alexey Kuznetsov, <kuznet@ms2.inr.ac.ru>
+- */
+-
+-#include <linux/module.h>
+-#include <linux/slab.h>
+-#include <linux/types.h>
+-#include <linux/kernel.h>
+-#include <linux/string.h>
+-#include <linux/errno.h>
+-#include <linux/skbuff.h>
+-#include <net/netlink.h>
+-#include <net/pkt_sched.h>
+-#include <net/pkt_cls.h>
+-
+-
+-/* Class-Based Queueing (CBQ) algorithm.
+- =======================================
+-
+- Sources: [1] Sally Floyd and Van Jacobson, "Link-sharing and Resource
+- Management Models for Packet Networks",
+- IEEE/ACM Transactions on Networking, Vol.3, No.4, 1995
+-
+- [2] Sally Floyd, "Notes on CBQ and Guaranteed Service", 1995
+-
+- [3] Sally Floyd, "Notes on Class-Based Queueing: Setting
+- Parameters", 1996
+-
+- [4] Sally Floyd and Michael Speer, "Experimental Results
+- for Class-Based Queueing", 1998, not published.
+-
+- -----------------------------------------------------------------------
+-
+- Algorithm skeleton was taken from NS simulator cbq.cc.
+- If someone wants to check this code against the LBL version,
+- he should take into account that ONLY the skeleton was borrowed,
+- the implementation is different. Particularly:
+-
+- --- The WRR algorithm is different. Our version looks more
+- reasonable (I hope) and works when quanta are allowed to be
+- less than MTU, which is always the case when real time classes
+- have small rates. Note, that the statement of [3] is
+- incomplete, delay may actually be estimated even if class
+- per-round allotment is less than MTU. Namely, if per-round
+- allotment is W*r_i, and r_1+...+r_k = r < 1
+-
+- delay_i <= ([MTU/(W*r_i)]*W*r + W*r + k*MTU)/B
+-
+- In the worst case we have IntServ estimate with D = W*r+k*MTU
+- and C = MTU*r. The proof (if correct at all) is trivial.
+-
+-
+- --- It seems that cbq-2.0 is not very accurate. At least, I cannot
+- interpret some places, which look like wrong translations
+- from NS. Anyone is advised to find these differences
+- and explain to me, why I am wrong 8).
+-
+- --- Linux has no EOI event, so that we cannot estimate true class
+- idle time. Workaround is to consider the next dequeue event
+- as sign that previous packet is finished. This is wrong because of
+- internal device queueing, but on a permanently loaded link it is true.
+- Moreover, combined with clock integrator, this scheme looks
+- very close to an ideal solution. */
+-
+-struct cbq_sched_data;
+-
+-
+-struct cbq_class {
+- struct Qdisc_class_common common;
+- struct cbq_class *next_alive; /* next class with backlog in this priority band */
+-
+-/* Parameters */
+- unsigned char priority; /* class priority */
+- unsigned char priority2; /* priority to be used after overlimit */
+- unsigned char ewma_log; /* time constant for idle time calculation */
+-
+- u32 defmap;
+-
+- /* Link-sharing scheduler parameters */
+- long maxidle; /* Class parameters: see below. */
+- long offtime;
+- long minidle;
+- u32 avpkt;
+- struct qdisc_rate_table *R_tab;
+-
+- /* General scheduler (WRR) parameters */
+- long allot;
+- long quantum; /* Allotment per WRR round */
+- long weight; /* Relative allotment: see below */
+-
+- struct Qdisc *qdisc; /* Ptr to CBQ discipline */
+- struct cbq_class *split; /* Ptr to split node */
+- struct cbq_class *share; /* Ptr to LS parent in the class tree */
+- struct cbq_class *tparent; /* Ptr to tree parent in the class tree */
+- struct cbq_class *borrow; /* NULL if class is bandwidth limited;
+- parent otherwise */
+- struct cbq_class *sibling; /* Sibling chain */
+- struct cbq_class *children; /* Pointer to children chain */
+-
+- struct Qdisc *q; /* Elementary queueing discipline */
+-
+-
+-/* Variables */
+- unsigned char cpriority; /* Effective priority */
+- unsigned char delayed;
+- unsigned char level; /* level of the class in hierarchy:
+- 0 for leaf classes, and maximal
+- level of children + 1 for nodes.
+- */
+-
+- psched_time_t last; /* Last end of service */
+- psched_time_t undertime;
+- long avgidle;
+- long deficit; /* Saved deficit for WRR */
+- psched_time_t penalized;
+- struct gnet_stats_basic_packed bstats;
+- struct gnet_stats_queue qstats;
+- struct net_rate_estimator __rcu *rate_est;
+- struct tc_cbq_xstats xstats;
+-
+- struct tcf_proto __rcu *filter_list;
+- struct tcf_block *block;
+-
+- int filters;
+-
+- struct cbq_class *defaults[TC_PRIO_MAX + 1];
+-};
+-
+-struct cbq_sched_data {
+- struct Qdisc_class_hash clhash; /* Hash table of all classes */
+- int nclasses[TC_CBQ_MAXPRIO + 1];
+- unsigned int quanta[TC_CBQ_MAXPRIO + 1];
+-
+- struct cbq_class link;
+-
+- unsigned int activemask;
+- struct cbq_class *active[TC_CBQ_MAXPRIO + 1]; /* List of all classes
+- with backlog */
+-
+-#ifdef CONFIG_NET_CLS_ACT
+- struct cbq_class *rx_class;
+-#endif
+- struct cbq_class *tx_class;
+- struct cbq_class *tx_borrowed;
+- int tx_len;
+- psched_time_t now; /* Cached timestamp */
+- unsigned int pmask;
+-
+- struct hrtimer delay_timer;
+- struct qdisc_watchdog watchdog; /* Watchdog timer,
+- started when CBQ has
+- backlog, but cannot
+- transmit just now */
+- psched_tdiff_t wd_expires;
+- int toplevel;
+- u32 hgenerator;
+-};
+-
+-
+-#define L2T(cl, len) qdisc_l2t((cl)->R_tab, len)
+-
+-static inline struct cbq_class *
+-cbq_class_lookup(struct cbq_sched_data *q, u32 classid)
+-{
+- struct Qdisc_class_common *clc;
+-
+- clc = qdisc_class_find(&q->clhash, classid);
+- if (clc == NULL)
+- return NULL;
+- return container_of(clc, struct cbq_class, common);
+-}
+-
+-#ifdef CONFIG_NET_CLS_ACT
+-
+-static struct cbq_class *
+-cbq_reclassify(struct sk_buff *skb, struct cbq_class *this)
+-{
+- struct cbq_class *cl;
+-
+- for (cl = this->tparent; cl; cl = cl->tparent) {
+- struct cbq_class *new = cl->defaults[TC_PRIO_BESTEFFORT];
+-
+- if (new != NULL && new != this)
+- return new;
+- }
+- return NULL;
+-}
+-
+-#endif
+-
+-/* Classify packet. The procedure is pretty complicated, but
+- * it allows us to combine link sharing and priority scheduling
+- * transparently.
+- *
+- * Namely, you can put link sharing rules (f.e. route based) at root of CBQ,
+- * so that it resolves to split nodes. Then packets are classified
+- * by logical priority, or a more specific classifier may be attached
+- * to the split node.
+- */
+-
+-static struct cbq_class *
+-cbq_classify(struct sk_buff *skb, struct Qdisc *sch, int *qerr)
+-{
+- struct cbq_sched_data *q = qdisc_priv(sch);
+- struct cbq_class *head = &q->link;
+- struct cbq_class **defmap;
+- struct cbq_class *cl = NULL;
+- u32 prio = skb->priority;
+- struct tcf_proto *fl;
+- struct tcf_result res;
+-
+- /*
+- * Step 1. If skb->priority points to one of our classes, use it.
+- */
+- if (TC_H_MAJ(prio ^ sch->handle) == 0 &&
+- (cl = cbq_class_lookup(q, prio)) != NULL)
+- return cl;
+-
+- *qerr = NET_XMIT_SUCCESS | __NET_XMIT_BYPASS;
+- for (;;) {
+- int result = 0;
+- defmap = head->defaults;
+-
+- fl = rcu_dereference_bh(head->filter_list);
+- /*
+- * Step 2+n. Apply classifier.
+- */
+- result = tcf_classify(skb, fl, &res, true);
+- if (!fl || result < 0)
+- goto fallback;
+- if (result == TC_ACT_SHOT)
+- return NULL;
+-
+- cl = (void *)res.class;
+- if (!cl) {
+- if (TC_H_MAJ(res.classid))
+- cl = cbq_class_lookup(q, res.classid);
+- else if ((cl = defmap[res.classid & TC_PRIO_MAX]) == NULL)
+- cl = defmap[TC_PRIO_BESTEFFORT];
+-
+- if (cl == NULL)
+- goto fallback;
+- }
+- if (cl->level >= head->level)
+- goto fallback;
+-#ifdef CONFIG_NET_CLS_ACT
+- switch (result) {
+- case TC_ACT_QUEUED:
+- case TC_ACT_STOLEN:
+- case TC_ACT_TRAP:
+- *qerr = NET_XMIT_SUCCESS | __NET_XMIT_STOLEN;
+- fallthrough;
+- case TC_ACT_RECLASSIFY:
+- return cbq_reclassify(skb, cl);
+- }
+-#endif
+- if (cl->level == 0)
+- return cl;
+-
+- /*
+- * Step 3+n. If classifier selected a link sharing class,
+- * apply agency specific classifier.
+- * Repeat this procdure until we hit a leaf node.
+- */
+- head = cl;
+- }
+-
+-fallback:
+- cl = head;
+-
+- /*
+- * Step 4. No success...
+- */
+- if (TC_H_MAJ(prio) == 0 &&
+- !(cl = head->defaults[prio & TC_PRIO_MAX]) &&
+- !(cl = head->defaults[TC_PRIO_BESTEFFORT]))
+- return head;
+-
+- return cl;
+-}
+-
+-/*
+- * A packet has just been enqueued on the empty class.
+- * cbq_activate_class adds it to the tail of active class list
+- * of its priority band.
+- */
+-
+-static inline void cbq_activate_class(struct cbq_class *cl)
+-{
+- struct cbq_sched_data *q = qdisc_priv(cl->qdisc);
+- int prio = cl->cpriority;
+- struct cbq_class *cl_tail;
+-
+- cl_tail = q->active[prio];
+- q->active[prio] = cl;
+-
+- if (cl_tail != NULL) {
+- cl->next_alive = cl_tail->next_alive;
+- cl_tail->next_alive = cl;
+- } else {
+- cl->next_alive = cl;
+- q->activemask |= (1<<prio);
+- }
+-}
+-
+-/*
+- * Unlink class from active chain.
+- * Note that this same procedure is done directly in cbq_dequeue*
+- * during round-robin procedure.
+- */
+-
+-static void cbq_deactivate_class(struct cbq_class *this)
+-{
+- struct cbq_sched_data *q = qdisc_priv(this->qdisc);
+- int prio = this->cpriority;
+- struct cbq_class *cl;
+- struct cbq_class *cl_prev = q->active[prio];
+-
+- do {
+- cl = cl_prev->next_alive;
+- if (cl == this) {
+- cl_prev->next_alive = cl->next_alive;
+- cl->next_alive = NULL;
+-
+- if (cl == q->active[prio]) {
+- q->active[prio] = cl_prev;
+- if (cl == q->active[prio]) {
+- q->active[prio] = NULL;
+- q->activemask &= ~(1<<prio);
+- return;
+- }
+- }
+- return;
+- }
+- } while ((cl_prev = cl) != q->active[prio]);
+-}
+-
+-static void
+-cbq_mark_toplevel(struct cbq_sched_data *q, struct cbq_class *cl)
+-{
+- int toplevel = q->toplevel;
+-
+- if (toplevel > cl->level) {
+- psched_time_t now = psched_get_time();
+-
+- do {
+- if (cl->undertime < now) {
+- q->toplevel = cl->level;
+- return;
+- }
+- } while ((cl = cl->borrow) != NULL && toplevel > cl->level);
+- }
+-}
+-
+-static int
+-cbq_enqueue(struct sk_buff *skb, struct Qdisc *sch,
+- struct sk_buff **to_free)
+-{
+- struct cbq_sched_data *q = qdisc_priv(sch);
+- int ret;
+- struct cbq_class *cl = cbq_classify(skb, sch, &ret);
+-
+-#ifdef CONFIG_NET_CLS_ACT
+- q->rx_class = cl;
+-#endif
+- if (cl == NULL) {
+- if (ret & __NET_XMIT_BYPASS)
+- qdisc_qstats_drop(sch);
+- __qdisc_drop(skb, to_free);
+- return ret;
+- }
+-
+- ret = qdisc_enqueue(skb, cl->q, to_free);
+- if (ret == NET_XMIT_SUCCESS) {
+- sch->q.qlen++;
+- cbq_mark_toplevel(q, cl);
+- if (!cl->next_alive)
+- cbq_activate_class(cl);
+- return ret;
+- }
+-
+- if (net_xmit_drop_count(ret)) {
+- qdisc_qstats_drop(sch);
+- cbq_mark_toplevel(q, cl);
+- cl->qstats.drops++;
+- }
+- return ret;
+-}
+-
+-/* Overlimit action: penalize leaf class by adding offtime */
+-static void cbq_overlimit(struct cbq_class *cl)
+-{
+- struct cbq_sched_data *q = qdisc_priv(cl->qdisc);
+- psched_tdiff_t delay = cl->undertime - q->now;
+-
+- if (!cl->delayed) {
+- delay += cl->offtime;
+-
+- /*
+- * Class goes to sleep, so that it will have no
+- * chance to work avgidle. Let's forgive it 8)
+- *
+- * BTW cbq-2.0 has a crap in this
+- * place, apparently they forgot to shift it by cl->ewma_log.
+- */
+- if (cl->avgidle < 0)
+- delay -= (-cl->avgidle) - ((-cl->avgidle) >> cl->ewma_log);
+- if (cl->avgidle < cl->minidle)
+- cl->avgidle = cl->minidle;
+- if (delay <= 0)
+- delay = 1;
+- cl->undertime = q->now + delay;
+-
+- cl->xstats.overactions++;
+- cl->delayed = 1;
+- }
+- if (q->wd_expires == 0 || q->wd_expires > delay)
+- q->wd_expires = delay;
+-
+- /* Dirty work! We must schedule wakeups based on
+- * real available rate, rather than leaf rate,
+- * which may be tiny (even zero).
+- */
+- if (q->toplevel == TC_CBQ_MAXLEVEL) {
+- struct cbq_class *b;
+- psched_tdiff_t base_delay = q->wd_expires;
+-
+- for (b = cl->borrow; b; b = b->borrow) {
+- delay = b->undertime - q->now;
+- if (delay < base_delay) {
+- if (delay <= 0)
+- delay = 1;
+- base_delay = delay;
+- }
+- }
+-
+- q->wd_expires = base_delay;
+- }
+-}
+-
+-static psched_tdiff_t cbq_undelay_prio(struct cbq_sched_data *q, int prio,
+- psched_time_t now)
+-{
+- struct cbq_class *cl;
+- struct cbq_class *cl_prev = q->active[prio];
+- psched_time_t sched = now;
+-
+- if (cl_prev == NULL)
+- return 0;
+-
+- do {
+- cl = cl_prev->next_alive;
+- if (now - cl->penalized > 0) {
+- cl_prev->next_alive = cl->next_alive;
+- cl->next_alive = NULL;
+- cl->cpriority = cl->priority;
+- cl->delayed = 0;
+- cbq_activate_class(cl);
+-
+- if (cl == q->active[prio]) {
+- q->active[prio] = cl_prev;
+- if (cl == q->active[prio]) {
+- q->active[prio] = NULL;
+- return 0;
+- }
+- }
+-
+- cl = cl_prev->next_alive;
+- } else if (sched - cl->penalized > 0)
+- sched = cl->penalized;
+- } while ((cl_prev = cl) != q->active[prio]);
+-
+- return sched - now;
+-}
+-
+-static enum hrtimer_restart cbq_undelay(struct hrtimer *timer)
+-{
+- struct cbq_sched_data *q = container_of(timer, struct cbq_sched_data,
+- delay_timer);
+- struct Qdisc *sch = q->watchdog.qdisc;
+- psched_time_t now;
+- psched_tdiff_t delay = 0;
+- unsigned int pmask;
+-
+- now = psched_get_time();
+-
+- pmask = q->pmask;
+- q->pmask = 0;
+-
+- while (pmask) {
+- int prio = ffz(~pmask);
+- psched_tdiff_t tmp;
+-
+- pmask &= ~(1<<prio);
+-
+- tmp = cbq_undelay_prio(q, prio, now);
+- if (tmp > 0) {
+- q->pmask |= 1<<prio;
+- if (tmp < delay || delay == 0)
+- delay = tmp;
+- }
+- }
+-
+- if (delay) {
+- ktime_t time;
+-
+- time = 0;
+- time = ktime_add_ns(time, PSCHED_TICKS2NS(now + delay));
+- hrtimer_start(&q->delay_timer, time, HRTIMER_MODE_ABS_PINNED);
+- }
+-
+- __netif_schedule(qdisc_root(sch));
+- return HRTIMER_NORESTART;
+-}
+-
+-/*
+- * It is mission critical procedure.
+- *
+- * We "regenerate" toplevel cutoff, if transmitting class
+- * has backlog and it is not regulated. It is not part of
+- * original CBQ description, but looks more reasonable.
+- * Probably, it is wrong. This question needs further investigation.
+- */
+-
+-static inline void
+-cbq_update_toplevel(struct cbq_sched_data *q, struct cbq_class *cl,
+- struct cbq_class *borrowed)
+-{
+- if (cl && q->toplevel >= borrowed->level) {
+- if (cl->q->q.qlen > 1) {
+- do {
+- if (borrowed->undertime == PSCHED_PASTPERFECT) {
+- q->toplevel = borrowed->level;
+- return;
+- }
+- } while ((borrowed = borrowed->borrow) != NULL);
+- }
+-#if 0
+- /* It is not necessary now. Uncommenting it
+- will save CPU cycles, but decrease fairness.
+- */
+- q->toplevel = TC_CBQ_MAXLEVEL;
+-#endif
+- }
+-}
+-
+-static void
+-cbq_update(struct cbq_sched_data *q)
+-{
+- struct cbq_class *this = q->tx_class;
+- struct cbq_class *cl = this;
+- int len = q->tx_len;
+- psched_time_t now;
+-
+- q->tx_class = NULL;
+- /* Time integrator. We calculate EOS time
+- * by adding expected packet transmission time.
+- */
+- now = q->now + L2T(&q->link, len);
+-
+- for ( ; cl; cl = cl->share) {
+- long avgidle = cl->avgidle;
+- long idle;
+-
+- cl->bstats.packets++;
+- cl->bstats.bytes += len;
+-
+- /*
+- * (now - last) is total time between packet right edges.
+- * (last_pktlen/rate) is "virtual" busy time, so that
+- *
+- * idle = (now - last) - last_pktlen/rate
+- */
+-
+- idle = now - cl->last;
+- if ((unsigned long)idle > 128*1024*1024) {
+- avgidle = cl->maxidle;
+- } else {
+- idle -= L2T(cl, len);
+-
+- /* true_avgidle := (1-W)*true_avgidle + W*idle,
+- * where W=2^{-ewma_log}. But cl->avgidle is scaled:
+- * cl->avgidle == true_avgidle/W,
+- * hence:
+- */
+- avgidle += idle - (avgidle>>cl->ewma_log);
+- }
+-
+- if (avgidle <= 0) {
+- /* Overlimit or at-limit */
+-
+- if (avgidle < cl->minidle)
+- avgidle = cl->minidle;
+-
+- cl->avgidle = avgidle;
+-
+- /* Calculate expected time, when this class
+- * will be allowed to send.
+- * It will occur, when:
+- * (1-W)*true_avgidle + W*delay = 0, i.e.
+- * idle = (1/W - 1)*(-true_avgidle)
+- * or
+- * idle = (1 - W)*(-cl->avgidle);
+- */
+- idle = (-avgidle) - ((-avgidle) >> cl->ewma_log);
+-
+- /*
+- * That is not all.
+- * To maintain the rate allocated to the class,
+- * we add to undertime virtual clock,
+- * necessary to complete transmitted packet.
+- * (len/phys_bandwidth has been already passed
+- * to the moment of cbq_update)
+- */
+-
+- idle -= L2T(&q->link, len);
+- idle += L2T(cl, len);
+-
+- cl->undertime = now + idle;
+- } else {
+- /* Underlimit */
+-
+- cl->undertime = PSCHED_PASTPERFECT;
+- if (avgidle > cl->maxidle)
+- cl->avgidle = cl->maxidle;
+- else
+- cl->avgidle = avgidle;
+- }
+- if ((s64)(now - cl->last) > 0)
+- cl->last = now;
+- }
+-
+- cbq_update_toplevel(q, this, q->tx_borrowed);
+-}
+-
+-static inline struct cbq_class *
+-cbq_under_limit(struct cbq_class *cl)
+-{
+- struct cbq_sched_data *q = qdisc_priv(cl->qdisc);
+- struct cbq_class *this_cl = cl;
+-
+- if (cl->tparent == NULL)
+- return cl;
+-
+- if (cl->undertime == PSCHED_PASTPERFECT || q->now >= cl->undertime) {
+- cl->delayed = 0;
+- return cl;
+- }
+-
+- do {
+- /* It is very suspicious place. Now overlimit
+- * action is generated for not bounded classes
+- * only if link is completely congested.
+- * Though it is in agree with ancestor-only paradigm,
+- * it looks very stupid. Particularly,
+- * it means that this chunk of code will either
+- * never be called or result in strong amplification
+- * of burstiness. Dangerous, silly, and, however,
+- * no another solution exists.
+- */
+- cl = cl->borrow;
+- if (!cl) {
+- this_cl->qstats.overlimits++;
+- cbq_overlimit(this_cl);
+- return NULL;
+- }
+- if (cl->level > q->toplevel)
+- return NULL;
+- } while (cl->undertime != PSCHED_PASTPERFECT && q->now < cl->undertime);
+-
+- cl->delayed = 0;
+- return cl;
+-}
+-
+-static inline struct sk_buff *
+-cbq_dequeue_prio(struct Qdisc *sch, int prio)
+-{
+- struct cbq_sched_data *q = qdisc_priv(sch);
+- struct cbq_class *cl_tail, *cl_prev, *cl;
+- struct sk_buff *skb;
+- int deficit;
+-
+- cl_tail = cl_prev = q->active[prio];
+- cl = cl_prev->next_alive;
+-
+- do {
+- deficit = 0;
+-
+- /* Start round */
+- do {
+- struct cbq_class *borrow = cl;
+-
+- if (cl->q->q.qlen &&
+- (borrow = cbq_under_limit(cl)) == NULL)
+- goto skip_class;
+-
+- if (cl->deficit <= 0) {
+- /* Class exhausted its allotment per
+- * this round. Switch to the next one.
+- */
+- deficit = 1;
+- cl->deficit += cl->quantum;
+- goto next_class;
+- }
+-
+- skb = cl->q->dequeue(cl->q);
+-
+- /* Class did not give us any skb :-(
+- * It could occur even if cl->q->q.qlen != 0
+- * f.e. if cl->q == "tbf"
+- */
+- if (skb == NULL)
+- goto skip_class;
+-
+- cl->deficit -= qdisc_pkt_len(skb);
+- q->tx_class = cl;
+- q->tx_borrowed = borrow;
+- if (borrow != cl) {
+-#ifndef CBQ_XSTATS_BORROWS_BYTES
+- borrow->xstats.borrows++;
+- cl->xstats.borrows++;
+-#else
+- borrow->xstats.borrows += qdisc_pkt_len(skb);
+- cl->xstats.borrows += qdisc_pkt_len(skb);
+-#endif
+- }
+- q->tx_len = qdisc_pkt_len(skb);
+-
+- if (cl->deficit <= 0) {
+- q->active[prio] = cl;
+- cl = cl->next_alive;
+- cl->deficit += cl->quantum;
+- }
+- return skb;
+-
+-skip_class:
+- if (cl->q->q.qlen == 0 || prio != cl->cpriority) {
+- /* Class is empty or penalized.
+- * Unlink it from active chain.
+- */
+- cl_prev->next_alive = cl->next_alive;
+- cl->next_alive = NULL;
+-
+- /* Did cl_tail point to it? */
+- if (cl == cl_tail) {
+- /* Repair it! */
+- cl_tail = cl_prev;
+-
+- /* Was it the last class in this band? */
+- if (cl == cl_tail) {
+- /* Kill the band! */
+- q->active[prio] = NULL;
+- q->activemask &= ~(1<<prio);
+- if (cl->q->q.qlen)
+- cbq_activate_class(cl);
+- return NULL;
+- }
+-
+- q->active[prio] = cl_tail;
+- }
+- if (cl->q->q.qlen)
+- cbq_activate_class(cl);
+-
+- cl = cl_prev;
+- }
+-
+-next_class:
+- cl_prev = cl;
+- cl = cl->next_alive;
+- } while (cl_prev != cl_tail);
+- } while (deficit);
+-
+- q->active[prio] = cl_prev;
+-
+- return NULL;
+-}
+-
+-static inline struct sk_buff *
+-cbq_dequeue_1(struct Qdisc *sch)
+-{
+- struct cbq_sched_data *q = qdisc_priv(sch);
+- struct sk_buff *skb;
+- unsigned int activemask;
+-
+- activemask = q->activemask & 0xFF;
+- while (activemask) {
+- int prio = ffz(~activemask);
+- activemask &= ~(1<<prio);
+- skb = cbq_dequeue_prio(sch, prio);
+- if (skb)
+- return skb;
+- }
+- return NULL;
+-}
+-
+-static struct sk_buff *
+-cbq_dequeue(struct Qdisc *sch)
+-{
+- struct sk_buff *skb;
+- struct cbq_sched_data *q = qdisc_priv(sch);
+- psched_time_t now;
+-
+- now = psched_get_time();
+-
+- if (q->tx_class)
+- cbq_update(q);
+-
+- q->now = now;
+-
+- for (;;) {
+- q->wd_expires = 0;
+-
+- skb = cbq_dequeue_1(sch);
+- if (skb) {
+- qdisc_bstats_update(sch, skb);
+- sch->q.qlen--;
+- return skb;
+- }
+-
+- /* All the classes are overlimit.
+- *
+- * It is possible, if:
+- *
+- * 1. Scheduler is empty.
+- * 2. Toplevel cutoff inhibited borrowing.
+- * 3. Root class is overlimit.
+- *
+- * Reset 2d and 3d conditions and retry.
+- *
+- * Note, that NS and cbq-2.0 are buggy, peeking
+- * an arbitrary class is appropriate for ancestor-only
+- * sharing, but not for toplevel algorithm.
+- *
+- * Our version is better, but slower, because it requires
+- * two passes, but it is unavoidable with top-level sharing.
+- */
+-
+- if (q->toplevel == TC_CBQ_MAXLEVEL &&
+- q->link.undertime == PSCHED_PASTPERFECT)
+- break;
+-
+- q->toplevel = TC_CBQ_MAXLEVEL;
+- q->link.undertime = PSCHED_PASTPERFECT;
+- }
+-
+- /* No packets in scheduler or nobody wants to give them to us :-(
+- * Sigh... start watchdog timer in the last case.
+- */
+-
+- if (sch->q.qlen) {
+- qdisc_qstats_overlimit(sch);
+- if (q->wd_expires)
+- qdisc_watchdog_schedule(&q->watchdog,
+- now + q->wd_expires);
+- }
+- return NULL;
+-}
+-
+-/* CBQ class maintanance routines */
+-
+-static void cbq_adjust_levels(struct cbq_class *this)
+-{
+- if (this == NULL)
+- return;
+-
+- do {
+- int level = 0;
+- struct cbq_class *cl;
+-
+- cl = this->children;
+- if (cl) {
+- do {
+- if (cl->level > level)
+- level = cl->level;
+- } while ((cl = cl->sibling) != this->children);
+- }
+- this->level = level + 1;
+- } while ((this = this->tparent) != NULL);
+-}
+-
+-static void cbq_normalize_quanta(struct cbq_sched_data *q, int prio)
+-{
+- struct cbq_class *cl;
+- unsigned int h;
+-
+- if (q->quanta[prio] == 0)
+- return;
+-
+- for (h = 0; h < q->clhash.hashsize; h++) {
+- hlist_for_each_entry(cl, &q->clhash.hash[h], common.hnode) {
+- /* BUGGGG... Beware! This expression suffer of
+- * arithmetic overflows!
+- */
+- if (cl->priority == prio) {
+- cl->quantum = (cl->weight*cl->allot*q->nclasses[prio])/
+- q->quanta[prio];
+- }
+- if (cl->quantum <= 0 ||
+- cl->quantum > 32*qdisc_dev(cl->qdisc)->mtu) {
+- pr_warn("CBQ: class %08x has bad quantum==%ld, repaired.\n",
+- cl->common.classid, cl->quantum);
+- cl->quantum = qdisc_dev(cl->qdisc)->mtu/2 + 1;
+- }
+- }
+- }
+-}
+-
+-static void cbq_sync_defmap(struct cbq_class *cl)
+-{
+- struct cbq_sched_data *q = qdisc_priv(cl->qdisc);
+- struct cbq_class *split = cl->split;
+- unsigned int h;
+- int i;
+-
+- if (split == NULL)
+- return;
+-
+- for (i = 0; i <= TC_PRIO_MAX; i++) {
+- if (split->defaults[i] == cl && !(cl->defmap & (1<<i)))
+- split->defaults[i] = NULL;
+- }
+-
+- for (i = 0; i <= TC_PRIO_MAX; i++) {
+- int level = split->level;
+-
+- if (split->defaults[i])
+- continue;
+-
+- for (h = 0; h < q->clhash.hashsize; h++) {
+- struct cbq_class *c;
+-
+- hlist_for_each_entry(c, &q->clhash.hash[h],
+- common.hnode) {
+- if (c->split == split && c->level < level &&
+- c->defmap & (1<<i)) {
+- split->defaults[i] = c;
+- level = c->level;
+- }
+- }
+- }
+- }
+-}
+-
+-static void cbq_change_defmap(struct cbq_class *cl, u32 splitid, u32 def, u32 mask)
+-{
+- struct cbq_class *split = NULL;
+-
+- if (splitid == 0) {
+- split = cl->split;
+- if (!split)
+- return;
+- splitid = split->common.classid;
+- }
+-
+- if (split == NULL || split->common.classid != splitid) {
+- for (split = cl->tparent; split; split = split->tparent)
+- if (split->common.classid == splitid)
+- break;
+- }
+-
+- if (split == NULL)
+- return;
+-
+- if (cl->split != split) {
+- cl->defmap = 0;
+- cbq_sync_defmap(cl);
+- cl->split = split;
+- cl->defmap = def & mask;
+- } else
+- cl->defmap = (cl->defmap & ~mask) | (def & mask);
+-
+- cbq_sync_defmap(cl);
+-}
+-
+-static void cbq_unlink_class(struct cbq_class *this)
+-{
+- struct cbq_class *cl, **clp;
+- struct cbq_sched_data *q = qdisc_priv(this->qdisc);
+-
+- qdisc_class_hash_remove(&q->clhash, &this->common);
+-
+- if (this->tparent) {
+- clp = &this->sibling;
+- cl = *clp;
+- do {
+- if (cl == this) {
+- *clp = cl->sibling;
+- break;
+- }
+- clp = &cl->sibling;
+- } while ((cl = *clp) != this->sibling);
+-
+- if (this->tparent->children == this) {
+- this->tparent->children = this->sibling;
+- if (this->sibling == this)
+- this->tparent->children = NULL;
+- }
+- } else {
+- WARN_ON(this->sibling != this);
+- }
+-}
+-
+-static void cbq_link_class(struct cbq_class *this)
+-{
+- struct cbq_sched_data *q = qdisc_priv(this->qdisc);
+- struct cbq_class *parent = this->tparent;
+-
+- this->sibling = this;
+- qdisc_class_hash_insert(&q->clhash, &this->common);
+-
+- if (parent == NULL)
+- return;
+-
+- if (parent->children == NULL) {
+- parent->children = this;
+- } else {
+- this->sibling = parent->children->sibling;
+- parent->children->sibling = this;
+- }
+-}
+-
+-static void
+-cbq_reset(struct Qdisc *sch)
+-{
+- struct cbq_sched_data *q = qdisc_priv(sch);
+- struct cbq_class *cl;
+- int prio;
+- unsigned int h;
+-
+- q->activemask = 0;
+- q->pmask = 0;
+- q->tx_class = NULL;
+- q->tx_borrowed = NULL;
+- qdisc_watchdog_cancel(&q->watchdog);
+- hrtimer_cancel(&q->delay_timer);
+- q->toplevel = TC_CBQ_MAXLEVEL;
+- q->now = psched_get_time();
+-
+- for (prio = 0; prio <= TC_CBQ_MAXPRIO; prio++)
+- q->active[prio] = NULL;
+-
+- for (h = 0; h < q->clhash.hashsize; h++) {
+- hlist_for_each_entry(cl, &q->clhash.hash[h], common.hnode) {
+- qdisc_reset(cl->q);
+-
+- cl->next_alive = NULL;
+- cl->undertime = PSCHED_PASTPERFECT;
+- cl->avgidle = cl->maxidle;
+- cl->deficit = cl->quantum;
+- cl->cpriority = cl->priority;
+- }
+- }
+-}
+-
+-
+-static int cbq_set_lss(struct cbq_class *cl, struct tc_cbq_lssopt *lss)
+-{
+- if (lss->change & TCF_CBQ_LSS_FLAGS) {
+- cl->share = (lss->flags & TCF_CBQ_LSS_ISOLATED) ? NULL : cl->tparent;
+- cl->borrow = (lss->flags & TCF_CBQ_LSS_BOUNDED) ? NULL : cl->tparent;
+- }
+- if (lss->change & TCF_CBQ_LSS_EWMA)
+- cl->ewma_log = lss->ewma_log;
+- if (lss->change & TCF_CBQ_LSS_AVPKT)
+- cl->avpkt = lss->avpkt;
+- if (lss->change & TCF_CBQ_LSS_MINIDLE)
+- cl->minidle = -(long)lss->minidle;
+- if (lss->change & TCF_CBQ_LSS_MAXIDLE) {
+- cl->maxidle = lss->maxidle;
+- cl->avgidle = lss->maxidle;
+- }
+- if (lss->change & TCF_CBQ_LSS_OFFTIME)
+- cl->offtime = lss->offtime;
+- return 0;
+-}
+-
+-static void cbq_rmprio(struct cbq_sched_data *q, struct cbq_class *cl)
+-{
+- q->nclasses[cl->priority]--;
+- q->quanta[cl->priority] -= cl->weight;
+- cbq_normalize_quanta(q, cl->priority);
+-}
+-
+-static void cbq_addprio(struct cbq_sched_data *q, struct cbq_class *cl)
+-{
+- q->nclasses[cl->priority]++;
+- q->quanta[cl->priority] += cl->weight;
+- cbq_normalize_quanta(q, cl->priority);
+-}
+-
+-static int cbq_set_wrr(struct cbq_class *cl, struct tc_cbq_wrropt *wrr)
+-{
+- struct cbq_sched_data *q = qdisc_priv(cl->qdisc);
+-
+- if (wrr->allot)
+- cl->allot = wrr->allot;
+- if (wrr->weight)
+- cl->weight = wrr->weight;
+- if (wrr->priority) {
+- cl->priority = wrr->priority - 1;
+- cl->cpriority = cl->priority;
+- if (cl->priority >= cl->priority2)
+- cl->priority2 = TC_CBQ_MAXPRIO - 1;
+- }
+-
+- cbq_addprio(q, cl);
+- return 0;
+-}
+-
+-static int cbq_set_fopt(struct cbq_class *cl, struct tc_cbq_fopt *fopt)
+-{
+- cbq_change_defmap(cl, fopt->split, fopt->defmap, fopt->defchange);
+- return 0;
+-}
+-
+-static const struct nla_policy cbq_policy[TCA_CBQ_MAX + 1] = {
+- [TCA_CBQ_LSSOPT] = { .len = sizeof(struct tc_cbq_lssopt) },
+- [TCA_CBQ_WRROPT] = { .len = sizeof(struct tc_cbq_wrropt) },
+- [TCA_CBQ_FOPT] = { .len = sizeof(struct tc_cbq_fopt) },
+- [TCA_CBQ_OVL_STRATEGY] = { .len = sizeof(struct tc_cbq_ovl) },
+- [TCA_CBQ_RATE] = { .len = sizeof(struct tc_ratespec) },
+- [TCA_CBQ_RTAB] = { .type = NLA_BINARY, .len = TC_RTAB_SIZE },
+- [TCA_CBQ_POLICE] = { .len = sizeof(struct tc_cbq_police) },
+-};
+-
+-static int cbq_opt_parse(struct nlattr *tb[TCA_CBQ_MAX + 1],
+- struct nlattr *opt,
+- struct netlink_ext_ack *extack)
+-{
+- int err;
+-
+- if (!opt) {
+- NL_SET_ERR_MSG(extack, "CBQ options are required for this operation");
+- return -EINVAL;
+- }
+-
+- err = nla_parse_nested_deprecated(tb, TCA_CBQ_MAX, opt,
+- cbq_policy, extack);
+- if (err < 0)
+- return err;
+-
+- if (tb[TCA_CBQ_WRROPT]) {
+- const struct tc_cbq_wrropt *wrr = nla_data(tb[TCA_CBQ_WRROPT]);
+-
+- if (wrr->priority > TC_CBQ_MAXPRIO) {
+- NL_SET_ERR_MSG(extack, "priority is bigger than TC_CBQ_MAXPRIO");
+- err = -EINVAL;
+- }
+- }
+- return err;
+-}
+-
+-static int cbq_init(struct Qdisc *sch, struct nlattr *opt,
+- struct netlink_ext_ack *extack)
+-{
+- struct cbq_sched_data *q = qdisc_priv(sch);
+- struct nlattr *tb[TCA_CBQ_MAX + 1];
+- struct tc_ratespec *r;
+- int err;
+-
+- qdisc_watchdog_init(&q->watchdog, sch);
+- hrtimer_init(&q->delay_timer, CLOCK_MONOTONIC, HRTIMER_MODE_ABS_PINNED);
+- q->delay_timer.function = cbq_undelay;
+-
+- err = cbq_opt_parse(tb, opt, extack);
+- if (err < 0)
+- return err;
+-
+- if (!tb[TCA_CBQ_RTAB] || !tb[TCA_CBQ_RATE]) {
+- NL_SET_ERR_MSG(extack, "Rate specification missing or incomplete");
+- return -EINVAL;
+- }
+-
+- r = nla_data(tb[TCA_CBQ_RATE]);
+-
+- q->link.R_tab = qdisc_get_rtab(r, tb[TCA_CBQ_RTAB], extack);
+- if (!q->link.R_tab)
+- return -EINVAL;
+-
+- err = tcf_block_get(&q->link.block, &q->link.filter_list, sch, extack);
+- if (err)
+- goto put_rtab;
+-
+- err = qdisc_class_hash_init(&q->clhash);
+- if (err < 0)
+- goto put_block;
+-
+- q->link.sibling = &q->link;
+- q->link.common.classid = sch->handle;
+- q->link.qdisc = sch;
+- q->link.q = qdisc_create_dflt(sch->dev_queue, &pfifo_qdisc_ops,
+- sch->handle, NULL);
+- if (!q->link.q)
+- q->link.q = &noop_qdisc;
+- else
+- qdisc_hash_add(q->link.q, true);
+-
+- q->link.priority = TC_CBQ_MAXPRIO - 1;
+- q->link.priority2 = TC_CBQ_MAXPRIO - 1;
+- q->link.cpriority = TC_CBQ_MAXPRIO - 1;
+- q->link.allot = psched_mtu(qdisc_dev(sch));
+- q->link.quantum = q->link.allot;
+- q->link.weight = q->link.R_tab->rate.rate;
+-
+- q->link.ewma_log = TC_CBQ_DEF_EWMA;
+- q->link.avpkt = q->link.allot/2;
+- q->link.minidle = -0x7FFFFFFF;
+-
+- q->toplevel = TC_CBQ_MAXLEVEL;
+- q->now = psched_get_time();
+-
+- cbq_link_class(&q->link);
+-
+- if (tb[TCA_CBQ_LSSOPT])
+- cbq_set_lss(&q->link, nla_data(tb[TCA_CBQ_LSSOPT]));
+-
+- cbq_addprio(q, &q->link);
+- return 0;
+-
+-put_block:
+- tcf_block_put(q->link.block);
+-
+-put_rtab:
+- qdisc_put_rtab(q->link.R_tab);
+- return err;
+-}
+-
+-static int cbq_dump_rate(struct sk_buff *skb, struct cbq_class *cl)
+-{
+- unsigned char *b = skb_tail_pointer(skb);
+-
+- if (nla_put(skb, TCA_CBQ_RATE, sizeof(cl->R_tab->rate), &cl->R_tab->rate))
+- goto nla_put_failure;
+- return skb->len;
+-
+-nla_put_failure:
+- nlmsg_trim(skb, b);
+- return -1;
+-}
+-
+-static int cbq_dump_lss(struct sk_buff *skb, struct cbq_class *cl)
+-{
+- unsigned char *b = skb_tail_pointer(skb);
+- struct tc_cbq_lssopt opt;
+-
+- opt.flags = 0;
+- if (cl->borrow == NULL)
+- opt.flags |= TCF_CBQ_LSS_BOUNDED;
+- if (cl->share == NULL)
+- opt.flags |= TCF_CBQ_LSS_ISOLATED;
+- opt.ewma_log = cl->ewma_log;
+- opt.level = cl->level;
+- opt.avpkt = cl->avpkt;
+- opt.maxidle = cl->maxidle;
+- opt.minidle = (u32)(-cl->minidle);
+- opt.offtime = cl->offtime;
+- opt.change = ~0;
+- if (nla_put(skb, TCA_CBQ_LSSOPT, sizeof(opt), &opt))
+- goto nla_put_failure;
+- return skb->len;
+-
+-nla_put_failure:
+- nlmsg_trim(skb, b);
+- return -1;
+-}
+-
+-static int cbq_dump_wrr(struct sk_buff *skb, struct cbq_class *cl)
+-{
+- unsigned char *b = skb_tail_pointer(skb);
+- struct tc_cbq_wrropt opt;
+-
+- memset(&opt, 0, sizeof(opt));
+- opt.flags = 0;
+- opt.allot = cl->allot;
+- opt.priority = cl->priority + 1;
+- opt.cpriority = cl->cpriority + 1;
+- opt.weight = cl->weight;
+- if (nla_put(skb, TCA_CBQ_WRROPT, sizeof(opt), &opt))
+- goto nla_put_failure;
+- return skb->len;
+-
+-nla_put_failure:
+- nlmsg_trim(skb, b);
+- return -1;
+-}
+-
+-static int cbq_dump_fopt(struct sk_buff *skb, struct cbq_class *cl)
+-{
+- unsigned char *b = skb_tail_pointer(skb);
+- struct tc_cbq_fopt opt;
+-
+- if (cl->split || cl->defmap) {
+- opt.split = cl->split ? cl->split->common.classid : 0;
+- opt.defmap = cl->defmap;
+- opt.defchange = ~0;
+- if (nla_put(skb, TCA_CBQ_FOPT, sizeof(opt), &opt))
+- goto nla_put_failure;
+- }
+- return skb->len;
+-
+-nla_put_failure:
+- nlmsg_trim(skb, b);
+- return -1;
+-}
+-
+-static int cbq_dump_attr(struct sk_buff *skb, struct cbq_class *cl)
+-{
+- if (cbq_dump_lss(skb, cl) < 0 ||
+- cbq_dump_rate(skb, cl) < 0 ||
+- cbq_dump_wrr(skb, cl) < 0 ||
+- cbq_dump_fopt(skb, cl) < 0)
+- return -1;
+- return 0;
+-}
+-
+-static int cbq_dump(struct Qdisc *sch, struct sk_buff *skb)
+-{
+- struct cbq_sched_data *q = qdisc_priv(sch);
+- struct nlattr *nest;
+-
+- nest = nla_nest_start_noflag(skb, TCA_OPTIONS);
+- if (nest == NULL)
+- goto nla_put_failure;
+- if (cbq_dump_attr(skb, &q->link) < 0)
+- goto nla_put_failure;
+- return nla_nest_end(skb, nest);
+-
+-nla_put_failure:
+- nla_nest_cancel(skb, nest);
+- return -1;
+-}
+-
+-static int
+-cbq_dump_stats(struct Qdisc *sch, struct gnet_dump *d)
+-{
+- struct cbq_sched_data *q = qdisc_priv(sch);
+-
+- q->link.xstats.avgidle = q->link.avgidle;
+- return gnet_stats_copy_app(d, &q->link.xstats, sizeof(q->link.xstats));
+-}
+-
+-static int
+-cbq_dump_class(struct Qdisc *sch, unsigned long arg,
+- struct sk_buff *skb, struct tcmsg *tcm)
+-{
+- struct cbq_class *cl = (struct cbq_class *)arg;
+- struct nlattr *nest;
+-
+- if (cl->tparent)
+- tcm->tcm_parent = cl->tparent->common.classid;
+- else
+- tcm->tcm_parent = TC_H_ROOT;
+- tcm->tcm_handle = cl->common.classid;
+- tcm->tcm_info = cl->q->handle;
+-
+- nest = nla_nest_start_noflag(skb, TCA_OPTIONS);
+- if (nest == NULL)
+- goto nla_put_failure;
+- if (cbq_dump_attr(skb, cl) < 0)
+- goto nla_put_failure;
+- return nla_nest_end(skb, nest);
+-
+-nla_put_failure:
+- nla_nest_cancel(skb, nest);
+- return -1;
+-}
+-
+-static int
+-cbq_dump_class_stats(struct Qdisc *sch, unsigned long arg,
+- struct gnet_dump *d)
+-{
+- struct cbq_sched_data *q = qdisc_priv(sch);
+- struct cbq_class *cl = (struct cbq_class *)arg;
+- __u32 qlen;
+-
+- cl->xstats.avgidle = cl->avgidle;
+- cl->xstats.undertime = 0;
+- qdisc_qstats_qlen_backlog(cl->q, &qlen, &cl->qstats.backlog);
+-
+- if (cl->undertime != PSCHED_PASTPERFECT)
+- cl->xstats.undertime = cl->undertime - q->now;
+-
+- if (gnet_stats_copy_basic(qdisc_root_sleeping_running(sch),
+- d, NULL, &cl->bstats) < 0 ||
+- gnet_stats_copy_rate_est(d, &cl->rate_est) < 0 ||
+- gnet_stats_copy_queue(d, NULL, &cl->qstats, qlen) < 0)
+- return -1;
+-
+- return gnet_stats_copy_app(d, &cl->xstats, sizeof(cl->xstats));
+-}
+-
+-static int cbq_graft(struct Qdisc *sch, unsigned long arg, struct Qdisc *new,
+- struct Qdisc **old, struct netlink_ext_ack *extack)
+-{
+- struct cbq_class *cl = (struct cbq_class *)arg;
+-
+- if (new == NULL) {
+- new = qdisc_create_dflt(sch->dev_queue, &pfifo_qdisc_ops,
+- cl->common.classid, extack);
+- if (new == NULL)
+- return -ENOBUFS;
+- }
+-
+- *old = qdisc_replace(sch, new, &cl->q);
+- return 0;
+-}
+-
+-static struct Qdisc *cbq_leaf(struct Qdisc *sch, unsigned long arg)
+-{
+- struct cbq_class *cl = (struct cbq_class *)arg;
+-
+- return cl->q;
+-}
+-
+-static void cbq_qlen_notify(struct Qdisc *sch, unsigned long arg)
+-{
+- struct cbq_class *cl = (struct cbq_class *)arg;
+-
+- cbq_deactivate_class(cl);
+-}
+-
+-static unsigned long cbq_find(struct Qdisc *sch, u32 classid)
+-{
+- struct cbq_sched_data *q = qdisc_priv(sch);
+-
+- return (unsigned long)cbq_class_lookup(q, classid);
+-}
+-
+-static void cbq_destroy_class(struct Qdisc *sch, struct cbq_class *cl)
+-{
+- struct cbq_sched_data *q = qdisc_priv(sch);
+-
+- WARN_ON(cl->filters);
+-
+- tcf_block_put(cl->block);
+- qdisc_put(cl->q);
+- qdisc_put_rtab(cl->R_tab);
+- gen_kill_estimator(&cl->rate_est);
+- if (cl != &q->link)
+- kfree(cl);
+-}
+-
+-static void cbq_destroy(struct Qdisc *sch)
+-{
+- struct cbq_sched_data *q = qdisc_priv(sch);
+- struct hlist_node *next;
+- struct cbq_class *cl;
+- unsigned int h;
+-
+-#ifdef CONFIG_NET_CLS_ACT
+- q->rx_class = NULL;
+-#endif
+- /*
+- * Filters must be destroyed first because we don't destroy the
+- * classes from root to leafs which means that filters can still
+- * be bound to classes which have been destroyed already. --TGR '04
+- */
+- for (h = 0; h < q->clhash.hashsize; h++) {
+- hlist_for_each_entry(cl, &q->clhash.hash[h], common.hnode) {
+- tcf_block_put(cl->block);
+- cl->block = NULL;
+- }
+- }
+- for (h = 0; h < q->clhash.hashsize; h++) {
+- hlist_for_each_entry_safe(cl, next, &q->clhash.hash[h],
+- common.hnode)
+- cbq_destroy_class(sch, cl);
+- }
+- qdisc_class_hash_destroy(&q->clhash);
+-}
+-
+-static int
+-cbq_change_class(struct Qdisc *sch, u32 classid, u32 parentid, struct nlattr **tca,
+- unsigned long *arg, struct netlink_ext_ack *extack)
+-{
+- int err;
+- struct cbq_sched_data *q = qdisc_priv(sch);
+- struct cbq_class *cl = (struct cbq_class *)*arg;
+- struct nlattr *opt = tca[TCA_OPTIONS];
+- struct nlattr *tb[TCA_CBQ_MAX + 1];
+- struct cbq_class *parent;
+- struct qdisc_rate_table *rtab = NULL;
+-
+- err = cbq_opt_parse(tb, opt, extack);
+- if (err < 0)
+- return err;
+-
+- if (tb[TCA_CBQ_OVL_STRATEGY] || tb[TCA_CBQ_POLICE]) {
+- NL_SET_ERR_MSG(extack, "Neither overlimit strategy nor policing attributes can be used for changing class params");
+- return -EOPNOTSUPP;
+- }
+-
+- if (cl) {
+- /* Check parent */
+- if (parentid) {
+- if (cl->tparent &&
+- cl->tparent->common.classid != parentid) {
+- NL_SET_ERR_MSG(extack, "Invalid parent id");
+- return -EINVAL;
+- }
+- if (!cl->tparent && parentid != TC_H_ROOT) {
+- NL_SET_ERR_MSG(extack, "Parent must be root");
+- return -EINVAL;
+- }
+- }
+-
+- if (tb[TCA_CBQ_RATE]) {
+- rtab = qdisc_get_rtab(nla_data(tb[TCA_CBQ_RATE]),
+- tb[TCA_CBQ_RTAB], extack);
+- if (rtab == NULL)
+- return -EINVAL;
+- }
+-
+- if (tca[TCA_RATE]) {
+- err = gen_replace_estimator(&cl->bstats, NULL,
+- &cl->rate_est,
+- NULL,
+- qdisc_root_sleeping_running(sch),
+- tca[TCA_RATE]);
+- if (err) {
+- NL_SET_ERR_MSG(extack, "Failed to replace specified rate estimator");
+- qdisc_put_rtab(rtab);
+- return err;
+- }
+- }
+-
+- /* Change class parameters */
+- sch_tree_lock(sch);
+-
+- if (cl->next_alive != NULL)
+- cbq_deactivate_class(cl);
+-
+- if (rtab) {
+- qdisc_put_rtab(cl->R_tab);
+- cl->R_tab = rtab;
+- }
+-
+- if (tb[TCA_CBQ_LSSOPT])
+- cbq_set_lss(cl, nla_data(tb[TCA_CBQ_LSSOPT]));
+-
+- if (tb[TCA_CBQ_WRROPT]) {
+- cbq_rmprio(q, cl);
+- cbq_set_wrr(cl, nla_data(tb[TCA_CBQ_WRROPT]));
+- }
+-
+- if (tb[TCA_CBQ_FOPT])
+- cbq_set_fopt(cl, nla_data(tb[TCA_CBQ_FOPT]));
+-
+- if (cl->q->q.qlen)
+- cbq_activate_class(cl);
+-
+- sch_tree_unlock(sch);
+-
+- return 0;
+- }
+-
+- if (parentid == TC_H_ROOT)
+- return -EINVAL;
+-
+- if (!tb[TCA_CBQ_WRROPT] || !tb[TCA_CBQ_RATE] || !tb[TCA_CBQ_LSSOPT]) {
+- NL_SET_ERR_MSG(extack, "One of the following attributes MUST be specified: WRR, rate or link sharing");
+- return -EINVAL;
+- }
+-
+- rtab = qdisc_get_rtab(nla_data(tb[TCA_CBQ_RATE]), tb[TCA_CBQ_RTAB],
+- extack);
+- if (rtab == NULL)
+- return -EINVAL;
+-
+- if (classid) {
+- err = -EINVAL;
+- if (TC_H_MAJ(classid ^ sch->handle) ||
+- cbq_class_lookup(q, classid)) {
+- NL_SET_ERR_MSG(extack, "Specified class not found");
+- goto failure;
+- }
+- } else {
+- int i;
+- classid = TC_H_MAKE(sch->handle, 0x8000);
+-
+- for (i = 0; i < 0x8000; i++) {
+- if (++q->hgenerator >= 0x8000)
+- q->hgenerator = 1;
+- if (cbq_class_lookup(q, classid|q->hgenerator) == NULL)
+- break;
+- }
+- err = -ENOSR;
+- if (i >= 0x8000) {
+- NL_SET_ERR_MSG(extack, "Unable to generate classid");
+- goto failure;
+- }
+- classid = classid|q->hgenerator;
+- }
+-
+- parent = &q->link;
+- if (parentid) {
+- parent = cbq_class_lookup(q, parentid);
+- err = -EINVAL;
+- if (!parent) {
+- NL_SET_ERR_MSG(extack, "Failed to find parentid");
+- goto failure;
+- }
+- }
+-
+- err = -ENOBUFS;
+- cl = kzalloc(sizeof(*cl), GFP_KERNEL);
+- if (cl == NULL)
+- goto failure;
+-
+- err = tcf_block_get(&cl->block, &cl->filter_list, sch, extack);
+- if (err) {
+- kfree(cl);
+- goto failure;
+- }
+-
+- if (tca[TCA_RATE]) {
+- err = gen_new_estimator(&cl->bstats, NULL, &cl->rate_est,
+- NULL,
+- qdisc_root_sleeping_running(sch),
+- tca[TCA_RATE]);
+- if (err) {
+- NL_SET_ERR_MSG(extack, "Couldn't create new estimator");
+- tcf_block_put(cl->block);
+- kfree(cl);
+- goto failure;
+- }
+- }
+-
+- cl->R_tab = rtab;
+- rtab = NULL;
+- cl->q = qdisc_create_dflt(sch->dev_queue, &pfifo_qdisc_ops, classid,
+- NULL);
+- if (!cl->q)
+- cl->q = &noop_qdisc;
+- else
+- qdisc_hash_add(cl->q, true);
+-
+- cl->common.classid = classid;
+- cl->tparent = parent;
+- cl->qdisc = sch;
+- cl->allot = parent->allot;
+- cl->quantum = cl->allot;
+- cl->weight = cl->R_tab->rate.rate;
+-
+- sch_tree_lock(sch);
+- cbq_link_class(cl);
+- cl->borrow = cl->tparent;
+- if (cl->tparent != &q->link)
+- cl->share = cl->tparent;
+- cbq_adjust_levels(parent);
+- cl->minidle = -0x7FFFFFFF;
+- cbq_set_lss(cl, nla_data(tb[TCA_CBQ_LSSOPT]));
+- cbq_set_wrr(cl, nla_data(tb[TCA_CBQ_WRROPT]));
+- if (cl->ewma_log == 0)
+- cl->ewma_log = q->link.ewma_log;
+- if (cl->maxidle == 0)
+- cl->maxidle = q->link.maxidle;
+- if (cl->avpkt == 0)
+- cl->avpkt = q->link.avpkt;
+- if (tb[TCA_CBQ_FOPT])
+- cbq_set_fopt(cl, nla_data(tb[TCA_CBQ_FOPT]));
+- sch_tree_unlock(sch);
+-
+- qdisc_class_hash_grow(sch, &q->clhash);
+-
+- *arg = (unsigned long)cl;
+- return 0;
+-
+-failure:
+- qdisc_put_rtab(rtab);
+- return err;
+-}
+-
+-static int cbq_delete(struct Qdisc *sch, unsigned long arg)
+-{
+- struct cbq_sched_data *q = qdisc_priv(sch);
+- struct cbq_class *cl = (struct cbq_class *)arg;
+-
+- if (cl->filters || cl->children || cl == &q->link)
+- return -EBUSY;
+-
+- sch_tree_lock(sch);
+-
+- qdisc_purge_queue(cl->q);
+-
+- if (cl->next_alive)
+- cbq_deactivate_class(cl);
+-
+- if (q->tx_borrowed == cl)
+- q->tx_borrowed = q->tx_class;
+- if (q->tx_class == cl) {
+- q->tx_class = NULL;
+- q->tx_borrowed = NULL;
+- }
+-#ifdef CONFIG_NET_CLS_ACT
+- if (q->rx_class == cl)
+- q->rx_class = NULL;
+-#endif
+-
+- cbq_unlink_class(cl);
+- cbq_adjust_levels(cl->tparent);
+- cl->defmap = 0;
+- cbq_sync_defmap(cl);
+-
+- cbq_rmprio(q, cl);
+- sch_tree_unlock(sch);
+-
+- cbq_destroy_class(sch, cl);
+- return 0;
+-}
+-
+-static struct tcf_block *cbq_tcf_block(struct Qdisc *sch, unsigned long arg,
+- struct netlink_ext_ack *extack)
+-{
+- struct cbq_sched_data *q = qdisc_priv(sch);
+- struct cbq_class *cl = (struct cbq_class *)arg;
+-
+- if (cl == NULL)
+- cl = &q->link;
+-
+- return cl->block;
+-}
+-
+-static unsigned long cbq_bind_filter(struct Qdisc *sch, unsigned long parent,
+- u32 classid)
+-{
+- struct cbq_sched_data *q = qdisc_priv(sch);
+- struct cbq_class *p = (struct cbq_class *)parent;
+- struct cbq_class *cl = cbq_class_lookup(q, classid);
+-
+- if (cl) {
+- if (p && p->level <= cl->level)
+- return 0;
+- cl->filters++;
+- return (unsigned long)cl;
+- }
+- return 0;
+-}
+-
+-static void cbq_unbind_filter(struct Qdisc *sch, unsigned long arg)
+-{
+- struct cbq_class *cl = (struct cbq_class *)arg;
+-
+- cl->filters--;
+-}
+-
+-static void cbq_walk(struct Qdisc *sch, struct qdisc_walker *arg)
+-{
+- struct cbq_sched_data *q = qdisc_priv(sch);
+- struct cbq_class *cl;
+- unsigned int h;
+-
+- if (arg->stop)
+- return;
+-
+- for (h = 0; h < q->clhash.hashsize; h++) {
+- hlist_for_each_entry(cl, &q->clhash.hash[h], common.hnode) {
+- if (arg->count < arg->skip) {
+- arg->count++;
+- continue;
+- }
+- if (arg->fn(sch, (unsigned long)cl, arg) < 0) {
+- arg->stop = 1;
+- return;
+- }
+- arg->count++;
+- }
+- }
+-}
+-
+-static const struct Qdisc_class_ops cbq_class_ops = {
+- .graft = cbq_graft,
+- .leaf = cbq_leaf,
+- .qlen_notify = cbq_qlen_notify,
+- .find = cbq_find,
+- .change = cbq_change_class,
+- .delete = cbq_delete,
+- .walk = cbq_walk,
+- .tcf_block = cbq_tcf_block,
+- .bind_tcf = cbq_bind_filter,
+- .unbind_tcf = cbq_unbind_filter,
+- .dump = cbq_dump_class,
+- .dump_stats = cbq_dump_class_stats,
+-};
+-
+-static struct Qdisc_ops cbq_qdisc_ops __read_mostly = {
+- .next = NULL,
+- .cl_ops = &cbq_class_ops,
+- .id = "cbq",
+- .priv_size = sizeof(struct cbq_sched_data),
+- .enqueue = cbq_enqueue,
+- .dequeue = cbq_dequeue,
+- .peek = qdisc_peek_dequeued,
+- .init = cbq_init,
+- .reset = cbq_reset,
+- .destroy = cbq_destroy,
+- .change = NULL,
+- .dump = cbq_dump,
+- .dump_stats = cbq_dump_stats,
+- .owner = THIS_MODULE,
+-};
+-
+-static int __init cbq_module_init(void)
+-{
+- return register_qdisc(&cbq_qdisc_ops);
+-}
+-static void __exit cbq_module_exit(void)
+-{
+- unregister_qdisc(&cbq_qdisc_ops);
+-}
+-module_init(cbq_module_init)
+-module_exit(cbq_module_exit)
+-MODULE_LICENSE("GPL");
+diff --git a/net/sched/sch_dsmark.c b/net/sched/sch_dsmark.c
+deleted file mode 100644
+index a75bc7f80cd7e..0000000000000
+--- a/net/sched/sch_dsmark.c
++++ /dev/null
+@@ -1,521 +0,0 @@
+-// SPDX-License-Identifier: GPL-2.0-only
+-/* net/sched/sch_dsmark.c - Differentiated Services field marker */
+-
+-/* Written 1998-2000 by Werner Almesberger, EPFL ICA */
+-
+-
+-#include <linux/module.h>
+-#include <linux/init.h>
+-#include <linux/slab.h>
+-#include <linux/types.h>
+-#include <linux/string.h>
+-#include <linux/errno.h>
+-#include <linux/skbuff.h>
+-#include <linux/rtnetlink.h>
+-#include <linux/bitops.h>
+-#include <net/pkt_sched.h>
+-#include <net/pkt_cls.h>
+-#include <net/dsfield.h>
+-#include <net/inet_ecn.h>
+-#include <asm/byteorder.h>
+-
+-/*
+- * classid class marking
+- * ------- ----- -------
+- * n/a 0 n/a
+- * x:0 1 use entry [0]
+- * ... ... ...
+- * x:y y>0 y+1 use entry [y]
+- * ... ... ...
+- * x:indices-1 indices use entry [indices-1]
+- * ... ... ...
+- * x:y y+1 use entry [y & (indices-1)]
+- * ... ... ...
+- * 0xffff 0x10000 use entry [indices-1]
+- */
+-
+-
+-#define NO_DEFAULT_INDEX (1 << 16)
+-
+-struct mask_value {
+- u8 mask;
+- u8 value;
+-};
+-
+-struct dsmark_qdisc_data {
+- struct Qdisc *q;
+- struct tcf_proto __rcu *filter_list;
+- struct tcf_block *block;
+- struct mask_value *mv;
+- u16 indices;
+- u8 set_tc_index;
+- u32 default_index; /* index range is 0...0xffff */
+-#define DSMARK_EMBEDDED_SZ 16
+- struct mask_value embedded[DSMARK_EMBEDDED_SZ];
+-};
+-
+-static inline int dsmark_valid_index(struct dsmark_qdisc_data *p, u16 index)
+-{
+- return index <= p->indices && index > 0;
+-}
+-
+-/* ------------------------- Class/flow operations ------------------------- */
+-
+-static int dsmark_graft(struct Qdisc *sch, unsigned long arg,
+- struct Qdisc *new, struct Qdisc **old,
+- struct netlink_ext_ack *extack)
+-{
+- struct dsmark_qdisc_data *p = qdisc_priv(sch);
+-
+- pr_debug("%s(sch %p,[qdisc %p],new %p,old %p)\n",
+- __func__, sch, p, new, old);
+-
+- if (new == NULL) {
+- new = qdisc_create_dflt(sch->dev_queue, &pfifo_qdisc_ops,
+- sch->handle, NULL);
+- if (new == NULL)
+- new = &noop_qdisc;
+- }
+-
+- *old = qdisc_replace(sch, new, &p->q);
+- return 0;
+-}
+-
+-static struct Qdisc *dsmark_leaf(struct Qdisc *sch, unsigned long arg)
+-{
+- struct dsmark_qdisc_data *p = qdisc_priv(sch);
+- return p->q;
+-}
+-
+-static unsigned long dsmark_find(struct Qdisc *sch, u32 classid)
+-{
+- return TC_H_MIN(classid) + 1;
+-}
+-
+-static unsigned long dsmark_bind_filter(struct Qdisc *sch,
+- unsigned long parent, u32 classid)
+-{
+- pr_debug("%s(sch %p,[qdisc %p],classid %x)\n",
+- __func__, sch, qdisc_priv(sch), classid);
+-
+- return dsmark_find(sch, classid);
+-}
+-
+-static void dsmark_unbind_filter(struct Qdisc *sch, unsigned long cl)
+-{
+-}
+-
+-static const struct nla_policy dsmark_policy[TCA_DSMARK_MAX + 1] = {
+- [TCA_DSMARK_INDICES] = { .type = NLA_U16 },
+- [TCA_DSMARK_DEFAULT_INDEX] = { .type = NLA_U16 },
+- [TCA_DSMARK_SET_TC_INDEX] = { .type = NLA_FLAG },
+- [TCA_DSMARK_MASK] = { .type = NLA_U8 },
+- [TCA_DSMARK_VALUE] = { .type = NLA_U8 },
+-};
+-
+-static int dsmark_change(struct Qdisc *sch, u32 classid, u32 parent,
+- struct nlattr **tca, unsigned long *arg,
+- struct netlink_ext_ack *extack)
+-{
+- struct dsmark_qdisc_data *p = qdisc_priv(sch);
+- struct nlattr *opt = tca[TCA_OPTIONS];
+- struct nlattr *tb[TCA_DSMARK_MAX + 1];
+- int err = -EINVAL;
+-
+- pr_debug("%s(sch %p,[qdisc %p],classid %x,parent %x), arg 0x%lx\n",
+- __func__, sch, p, classid, parent, *arg);
+-
+- if (!dsmark_valid_index(p, *arg)) {
+- err = -ENOENT;
+- goto errout;
+- }
+-
+- if (!opt)
+- goto errout;
+-
+- err = nla_parse_nested_deprecated(tb, TCA_DSMARK_MAX, opt,
+- dsmark_policy, NULL);
+- if (err < 0)
+- goto errout;
+-
+- if (tb[TCA_DSMARK_VALUE])
+- p->mv[*arg - 1].value = nla_get_u8(tb[TCA_DSMARK_VALUE]);
+-
+- if (tb[TCA_DSMARK_MASK])
+- p->mv[*arg - 1].mask = nla_get_u8(tb[TCA_DSMARK_MASK]);
+-
+- err = 0;
+-
+-errout:
+- return err;
+-}
+-
+-static int dsmark_delete(struct Qdisc *sch, unsigned long arg)
+-{
+- struct dsmark_qdisc_data *p = qdisc_priv(sch);
+-
+- if (!dsmark_valid_index(p, arg))
+- return -EINVAL;
+-
+- p->mv[arg - 1].mask = 0xff;
+- p->mv[arg - 1].value = 0;
+-
+- return 0;
+-}
+-
+-static void dsmark_walk(struct Qdisc *sch, struct qdisc_walker *walker)
+-{
+- struct dsmark_qdisc_data *p = qdisc_priv(sch);
+- int i;
+-
+- pr_debug("%s(sch %p,[qdisc %p],walker %p)\n",
+- __func__, sch, p, walker);
+-
+- if (walker->stop)
+- return;
+-
+- for (i = 0; i < p->indices; i++) {
+- if (p->mv[i].mask == 0xff && !p->mv[i].value)
+- goto ignore;
+- if (walker->count >= walker->skip) {
+- if (walker->fn(sch, i + 1, walker) < 0) {
+- walker->stop = 1;
+- break;
+- }
+- }
+-ignore:
+- walker->count++;
+- }
+-}
+-
+-static struct tcf_block *dsmark_tcf_block(struct Qdisc *sch, unsigned long cl,
+- struct netlink_ext_ack *extack)
+-{
+- struct dsmark_qdisc_data *p = qdisc_priv(sch);
+-
+- return p->block;
+-}
+-
+-/* --------------------------- Qdisc operations ---------------------------- */
+-
+-static int dsmark_enqueue(struct sk_buff *skb, struct Qdisc *sch,
+- struct sk_buff **to_free)
+-{
+- unsigned int len = qdisc_pkt_len(skb);
+- struct dsmark_qdisc_data *p = qdisc_priv(sch);
+- int err;
+-
+- pr_debug("%s(skb %p,sch %p,[qdisc %p])\n", __func__, skb, sch, p);
+-
+- if (p->set_tc_index) {
+- int wlen = skb_network_offset(skb);
+-
+- switch (skb_protocol(skb, true)) {
+- case htons(ETH_P_IP):
+- wlen += sizeof(struct iphdr);
+- if (!pskb_may_pull(skb, wlen) ||
+- skb_try_make_writable(skb, wlen))
+- goto drop;
+-
+- skb->tc_index = ipv4_get_dsfield(ip_hdr(skb))
+- & ~INET_ECN_MASK;
+- break;
+-
+- case htons(ETH_P_IPV6):
+- wlen += sizeof(struct ipv6hdr);
+- if (!pskb_may_pull(skb, wlen) ||
+- skb_try_make_writable(skb, wlen))
+- goto drop;
+-
+- skb->tc_index = ipv6_get_dsfield(ipv6_hdr(skb))
+- & ~INET_ECN_MASK;
+- break;
+- default:
+- skb->tc_index = 0;
+- break;
+- }
+- }
+-
+- if (TC_H_MAJ(skb->priority) == sch->handle)
+- skb->tc_index = TC_H_MIN(skb->priority);
+- else {
+- struct tcf_result res;
+- struct tcf_proto *fl = rcu_dereference_bh(p->filter_list);
+- int result = tcf_classify(skb, fl, &res, false);
+-
+- pr_debug("result %d class 0x%04x\n", result, res.classid);
+-
+- switch (result) {
+-#ifdef CONFIG_NET_CLS_ACT
+- case TC_ACT_QUEUED:
+- case TC_ACT_STOLEN:
+- case TC_ACT_TRAP:
+- __qdisc_drop(skb, to_free);
+- return NET_XMIT_SUCCESS | __NET_XMIT_STOLEN;
+-
+- case TC_ACT_SHOT:
+- goto drop;
+-#endif
+- case TC_ACT_OK:
+- skb->tc_index = TC_H_MIN(res.classid);
+- break;
+-
+- default:
+- if (p->default_index != NO_DEFAULT_INDEX)
+- skb->tc_index = p->default_index;
+- break;
+- }
+- }
+-
+- err = qdisc_enqueue(skb, p->q, to_free);
+- if (err != NET_XMIT_SUCCESS) {
+- if (net_xmit_drop_count(err))
+- qdisc_qstats_drop(sch);
+- return err;
+- }
+-
+- sch->qstats.backlog += len;
+- sch->q.qlen++;
+-
+- return NET_XMIT_SUCCESS;
+-
+-drop:
+- qdisc_drop(skb, sch, to_free);
+- return NET_XMIT_SUCCESS | __NET_XMIT_BYPASS;
+-}
+-
+-static struct sk_buff *dsmark_dequeue(struct Qdisc *sch)
+-{
+- struct dsmark_qdisc_data *p = qdisc_priv(sch);
+- struct sk_buff *skb;
+- u32 index;
+-
+- pr_debug("%s(sch %p,[qdisc %p])\n", __func__, sch, p);
+-
+- skb = qdisc_dequeue_peeked(p->q);
+- if (skb == NULL)
+- return NULL;
+-
+- qdisc_bstats_update(sch, skb);
+- qdisc_qstats_backlog_dec(sch, skb);
+- sch->q.qlen--;
+-
+- index = skb->tc_index & (p->indices - 1);
+- pr_debug("index %d->%d\n", skb->tc_index, index);
+-
+- switch (skb_protocol(skb, true)) {
+- case htons(ETH_P_IP):
+- ipv4_change_dsfield(ip_hdr(skb), p->mv[index].mask,
+- p->mv[index].value);
+- break;
+- case htons(ETH_P_IPV6):
+- ipv6_change_dsfield(ipv6_hdr(skb), p->mv[index].mask,
+- p->mv[index].value);
+- break;
+- default:
+- /*
+- * Only complain if a change was actually attempted.
+- * This way, we can send non-IP traffic through dsmark
+- * and don't need yet another qdisc as a bypass.
+- */
+- if (p->mv[index].mask != 0xff || p->mv[index].value)
+- pr_warn("%s: unsupported protocol %d\n",
+- __func__, ntohs(skb_protocol(skb, true)));
+- break;
+- }
+-
+- return skb;
+-}
+-
+-static struct sk_buff *dsmark_peek(struct Qdisc *sch)
+-{
+- struct dsmark_qdisc_data *p = qdisc_priv(sch);
+-
+- pr_debug("%s(sch %p,[qdisc %p])\n", __func__, sch, p);
+-
+- return p->q->ops->peek(p->q);
+-}
+-
+-static int dsmark_init(struct Qdisc *sch, struct nlattr *opt,
+- struct netlink_ext_ack *extack)
+-{
+- struct dsmark_qdisc_data *p = qdisc_priv(sch);
+- struct nlattr *tb[TCA_DSMARK_MAX + 1];
+- int err = -EINVAL;
+- u32 default_index = NO_DEFAULT_INDEX;
+- u16 indices;
+- int i;
+-
+- pr_debug("%s(sch %p,[qdisc %p],opt %p)\n", __func__, sch, p, opt);
+-
+- if (!opt)
+- goto errout;
+-
+- err = tcf_block_get(&p->block, &p->filter_list, sch, extack);
+- if (err)
+- return err;
+-
+- err = nla_parse_nested_deprecated(tb, TCA_DSMARK_MAX, opt,
+- dsmark_policy, NULL);
+- if (err < 0)
+- goto errout;
+-
+- err = -EINVAL;
+- if (!tb[TCA_DSMARK_INDICES])
+- goto errout;
+- indices = nla_get_u16(tb[TCA_DSMARK_INDICES]);
+-
+- if (hweight32(indices) != 1)
+- goto errout;
+-
+- if (tb[TCA_DSMARK_DEFAULT_INDEX])
+- default_index = nla_get_u16(tb[TCA_DSMARK_DEFAULT_INDEX]);
+-
+- if (indices <= DSMARK_EMBEDDED_SZ)
+- p->mv = p->embedded;
+- else
+- p->mv = kmalloc_array(indices, sizeof(*p->mv), GFP_KERNEL);
+- if (!p->mv) {
+- err = -ENOMEM;
+- goto errout;
+- }
+- for (i = 0; i < indices; i++) {
+- p->mv[i].mask = 0xff;
+- p->mv[i].value = 0;
+- }
+- p->indices = indices;
+- p->default_index = default_index;
+- p->set_tc_index = nla_get_flag(tb[TCA_DSMARK_SET_TC_INDEX]);
+-
+- p->q = qdisc_create_dflt(sch->dev_queue, &pfifo_qdisc_ops, sch->handle,
+- NULL);
+- if (p->q == NULL)
+- p->q = &noop_qdisc;
+- else
+- qdisc_hash_add(p->q, true);
+-
+- pr_debug("%s: qdisc %p\n", __func__, p->q);
+-
+- err = 0;
+-errout:
+- return err;
+-}
+-
+-static void dsmark_reset(struct Qdisc *sch)
+-{
+- struct dsmark_qdisc_data *p = qdisc_priv(sch);
+-
+- pr_debug("%s(sch %p,[qdisc %p])\n", __func__, sch, p);
+- if (p->q)
+- qdisc_reset(p->q);
+-}
+-
+-static void dsmark_destroy(struct Qdisc *sch)
+-{
+- struct dsmark_qdisc_data *p = qdisc_priv(sch);
+-
+- pr_debug("%s(sch %p,[qdisc %p])\n", __func__, sch, p);
+-
+- tcf_block_put(p->block);
+- qdisc_put(p->q);
+- if (p->mv != p->embedded)
+- kfree(p->mv);
+-}
+-
+-static int dsmark_dump_class(struct Qdisc *sch, unsigned long cl,
+- struct sk_buff *skb, struct tcmsg *tcm)
+-{
+- struct dsmark_qdisc_data *p = qdisc_priv(sch);
+- struct nlattr *opts = NULL;
+-
+- pr_debug("%s(sch %p,[qdisc %p],class %ld\n", __func__, sch, p, cl);
+-
+- if (!dsmark_valid_index(p, cl))
+- return -EINVAL;
+-
+- tcm->tcm_handle = TC_H_MAKE(TC_H_MAJ(sch->handle), cl - 1);
+- tcm->tcm_info = p->q->handle;
+-
+- opts = nla_nest_start_noflag(skb, TCA_OPTIONS);
+- if (opts == NULL)
+- goto nla_put_failure;
+- if (nla_put_u8(skb, TCA_DSMARK_MASK, p->mv[cl - 1].mask) ||
+- nla_put_u8(skb, TCA_DSMARK_VALUE, p->mv[cl - 1].value))
+- goto nla_put_failure;
+-
+- return nla_nest_end(skb, opts);
+-
+-nla_put_failure:
+- nla_nest_cancel(skb, opts);
+- return -EMSGSIZE;
+-}
+-
+-static int dsmark_dump(struct Qdisc *sch, struct sk_buff *skb)
+-{
+- struct dsmark_qdisc_data *p = qdisc_priv(sch);
+- struct nlattr *opts = NULL;
+-
+- opts = nla_nest_start_noflag(skb, TCA_OPTIONS);
+- if (opts == NULL)
+- goto nla_put_failure;
+- if (nla_put_u16(skb, TCA_DSMARK_INDICES, p->indices))
+- goto nla_put_failure;
+-
+- if (p->default_index != NO_DEFAULT_INDEX &&
+- nla_put_u16(skb, TCA_DSMARK_DEFAULT_INDEX, p->default_index))
+- goto nla_put_failure;
+-
+- if (p->set_tc_index &&
+- nla_put_flag(skb, TCA_DSMARK_SET_TC_INDEX))
+- goto nla_put_failure;
+-
+- return nla_nest_end(skb, opts);
+-
+-nla_put_failure:
+- nla_nest_cancel(skb, opts);
+- return -EMSGSIZE;
+-}
+-
+-static const struct Qdisc_class_ops dsmark_class_ops = {
+- .graft = dsmark_graft,
+- .leaf = dsmark_leaf,
+- .find = dsmark_find,
+- .change = dsmark_change,
+- .delete = dsmark_delete,
+- .walk = dsmark_walk,
+- .tcf_block = dsmark_tcf_block,
+- .bind_tcf = dsmark_bind_filter,
+- .unbind_tcf = dsmark_unbind_filter,
+- .dump = dsmark_dump_class,
+-};
+-
+-static struct Qdisc_ops dsmark_qdisc_ops __read_mostly = {
+- .next = NULL,
+- .cl_ops = &dsmark_class_ops,
+- .id = "dsmark",
+- .priv_size = sizeof(struct dsmark_qdisc_data),
+- .enqueue = dsmark_enqueue,
+- .dequeue = dsmark_dequeue,
+- .peek = dsmark_peek,
+- .init = dsmark_init,
+- .reset = dsmark_reset,
+- .destroy = dsmark_destroy,
+- .change = NULL,
+- .dump = dsmark_dump,
+- .owner = THIS_MODULE,
+-};
+-
+-static int __init dsmark_module_init(void)
+-{
+- return register_qdisc(&dsmark_qdisc_ops);
+-}
+-
+-static void __exit dsmark_module_exit(void)
+-{
+- unregister_qdisc(&dsmark_qdisc_ops);
+-}
+-
+-module_init(dsmark_module_init)
+-module_exit(dsmark_module_exit)
+-
+-MODULE_LICENSE("GPL");
+diff --git a/net/tls/tls_main.c b/net/tls/tls_main.c
+index 7ee3c8b03a39e..2bbacd9b97e56 100644
+--- a/net/tls/tls_main.c
++++ b/net/tls/tls_main.c
+@@ -800,7 +800,7 @@ static void tls_update(struct sock *sk, struct proto *p,
+ }
+ }
+
+-static int tls_get_info(const struct sock *sk, struct sk_buff *skb)
++static int tls_get_info(struct sock *sk, struct sk_buff *skb)
+ {
+ u16 version, cipher_type;
+ struct tls_context *ctx;
+diff --git a/net/tls/tls_sw.c b/net/tls/tls_sw.c
+index dd980438f201f..46f1c19f7c60b 100644
+--- a/net/tls/tls_sw.c
++++ b/net/tls/tls_sw.c
+@@ -1754,6 +1754,7 @@ int tls_sw_recvmsg(struct sock *sk,
+ struct tls_sw_context_rx *ctx = tls_sw_ctx_rx(tls_ctx);
+ struct tls_prot_info *prot = &tls_ctx->prot_info;
+ struct sk_psock *psock;
++ int num_async, pending;
+ unsigned char control = 0;
+ ssize_t decrypted = 0;
+ struct strp_msg *rxm;
+@@ -1766,8 +1767,6 @@ int tls_sw_recvmsg(struct sock *sk,
+ bool is_kvec = iov_iter_is_kvec(&msg->msg_iter);
+ bool is_peek = flags & MSG_PEEK;
+ bool bpf_strp_enabled;
+- int num_async = 0;
+- int pending;
+
+ flags |= nonblock;
+
+@@ -1784,17 +1783,18 @@ int tls_sw_recvmsg(struct sock *sk,
+ if (err < 0) {
+ tls_err_abort(sk, err);
+ goto end;
+- } else {
+- copied = err;
+ }
+
+- if (len <= copied)
+- goto recv_end;
++ copied = err;
++ if (len <= copied || (copied && control != TLS_RECORD_TYPE_DATA))
++ goto end;
+
+ target = sock_rcvlowat(sk, flags & MSG_WAITALL, len);
+ len = len - copied;
+ timeo = sock_rcvtimeo(sk, flags & MSG_DONTWAIT);
+
++ decrypted = 0;
++ num_async = 0;
+ while (len && (decrypted + copied < target || ctx->recv_pkt)) {
+ bool retain_skb = false;
+ bool zc = false;
+diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
+index 0ac829c8f1888..279f4977e2eed 100644
+--- a/net/wireless/nl80211.c
++++ b/net/wireless/nl80211.c
+@@ -3595,6 +3595,7 @@ static int nl80211_dump_interface(struct sk_buff *skb, struct netlink_callback *
+ if_idx++;
+ }
+
++ if_start = 0;
+ wp_idx++;
+ }
+ out:
+diff --git a/scripts/bpf_helpers_doc.py b/scripts/bpf_helpers_doc.py
+index 31484377b8b11..806240dda6090 100755
+--- a/scripts/bpf_helpers_doc.py
++++ b/scripts/bpf_helpers_doc.py
+@@ -284,7 +284,7 @@ eBPF programs can have an associated license, passed along with the bytecode
+ instructions to the kernel when the programs are loaded. The format for that
+ string is identical to the one in use for kernel modules (Dual licenses, such
+ as "Dual BSD/GPL", may be used). Some helper functions are only accessible to
+-programs that are compatible with the GNU Privacy License (GPL).
++programs that are compatible with the GNU General Public License (GNU GPL).
+
+ In order to use such helpers, the eBPF program must be loaded with the correct
+ license string passed (via **attr**) to the **bpf**\ () system call, and this
+diff --git a/sound/soc/fsl/fsl_micfil.c b/sound/soc/fsl/fsl_micfil.c
+index 97f83c63e7652..826829e3ff7a2 100644
+--- a/sound/soc/fsl/fsl_micfil.c
++++ b/sound/soc/fsl/fsl_micfil.c
+@@ -756,18 +756,23 @@ static int fsl_micfil_probe(struct platform_device *pdev)
+
+ pm_runtime_enable(&pdev->dev);
+
++ /*
++ * Register platform component before registering cpu dai for there
++ * is not defer probe for platform component in snd_soc_add_pcm_runtime().
++ */
++ ret = devm_snd_dmaengine_pcm_register(&pdev->dev, NULL, 0);
++ if (ret) {
++ dev_err(&pdev->dev, "failed to pcm register\n");
++ return ret;
++ }
++
+ ret = devm_snd_soc_register_component(&pdev->dev, &fsl_micfil_component,
+ &fsl_micfil_dai, 1);
+ if (ret) {
+ dev_err(&pdev->dev, "failed to register component %s\n",
+ fsl_micfil_component.name);
+- return ret;
+ }
+
+- ret = devm_snd_dmaengine_pcm_register(&pdev->dev, NULL, 0);
+- if (ret)
+- dev_err(&pdev->dev, "failed to pcm register\n");
+-
+ return ret;
+ }
+
+diff --git a/sound/soc/intel/boards/bytcht_es8316.c b/sound/soc/intel/boards/bytcht_es8316.c
+index 81269ed5a2aaa..03b9cdbd3170f 100644
+--- a/sound/soc/intel/boards/bytcht_es8316.c
++++ b/sound/soc/intel/boards/bytcht_es8316.c
+@@ -37,6 +37,7 @@ struct byt_cht_es8316_private {
+ struct clk *mclk;
+ struct snd_soc_jack jack;
+ struct gpio_desc *speaker_en_gpio;
++ struct device *codec_dev;
+ bool speaker_en;
+ };
+
+@@ -549,9 +550,10 @@ static int snd_byt_cht_es8316_mc_probe(struct platform_device *pdev)
+ }
+
+ /* get speaker enable GPIO */
+- codec_dev = bus_find_device_by_name(&i2c_bus_type, NULL, codec_name);
++ codec_dev = acpi_get_first_physical_node(adev);
+ if (!codec_dev)
+ return -EPROBE_DEFER;
++ priv->codec_dev = get_device(codec_dev);
+
+ if (quirk & BYT_CHT_ES8316_JD_INVERTED)
+ props[cnt++] = PROPERTY_ENTRY_BOOL("everest,jack-detect-inverted");
+@@ -569,7 +571,6 @@ static int snd_byt_cht_es8316_mc_probe(struct platform_device *pdev)
+ gpiod_get_index(codec_dev, "speaker-enable", 0,
+ /* see comment in byt_cht_es8316_resume */
+ GPIOD_OUT_LOW | GPIOD_FLAGS_BIT_NONEXCLUSIVE);
+- put_device(codec_dev);
+
+ if (IS_ERR(priv->speaker_en_gpio)) {
+ ret = PTR_ERR(priv->speaker_en_gpio);
+@@ -581,7 +582,7 @@ static int snd_byt_cht_es8316_mc_probe(struct platform_device *pdev)
+ dev_err(dev, "get speaker GPIO failed: %d\n", ret);
+ fallthrough;
+ case -EPROBE_DEFER:
+- return ret;
++ goto err_put_codec;
+ }
+ }
+
+@@ -604,10 +605,14 @@ static int snd_byt_cht_es8316_mc_probe(struct platform_device *pdev)
+ if (ret) {
+ gpiod_put(priv->speaker_en_gpio);
+ dev_err(dev, "snd_soc_register_card failed: %d\n", ret);
+- return ret;
++ goto err_put_codec;
+ }
+ platform_set_drvdata(pdev, &byt_cht_es8316_card);
+ return 0;
++
++err_put_codec:
++ put_device(priv->codec_dev);
++ return ret;
+ }
+
+ static int snd_byt_cht_es8316_mc_remove(struct platform_device *pdev)
+@@ -616,6 +621,7 @@ static int snd_byt_cht_es8316_mc_remove(struct platform_device *pdev)
+ struct byt_cht_es8316_private *priv = snd_soc_card_get_drvdata(card);
+
+ gpiod_put(priv->speaker_en_gpio);
++ put_device(priv->codec_dev);
+ return 0;
+ }
+
+diff --git a/sound/soc/intel/boards/bytcr_rt5640.c b/sound/soc/intel/boards/bytcr_rt5640.c
+index 9a5ab96f917d3..f5b1b3b876980 100644
+--- a/sound/soc/intel/boards/bytcr_rt5640.c
++++ b/sound/soc/intel/boards/bytcr_rt5640.c
+@@ -86,6 +86,7 @@ enum {
+ struct byt_rt5640_private {
+ struct snd_soc_jack jack;
+ struct clk *mclk;
++ struct device *codec_dev;
+ };
+ static bool is_bytcr;
+
+@@ -941,15 +942,11 @@ static const struct dmi_system_id byt_rt5640_quirk_table[] = {
+ * Note this MUST be called before snd_soc_register_card(), so that the props
+ * are in place before the codec component driver's probe function parses them.
+ */
+-static int byt_rt5640_add_codec_device_props(const char *i2c_dev_name)
++static int byt_rt5640_add_codec_device_props(struct device *i2c_dev,
++ struct byt_rt5640_private *priv)
+ {
+ struct property_entry props[MAX_NO_PROPS] = {};
+- struct device *i2c_dev;
+- int ret, cnt = 0;
+-
+- i2c_dev = bus_find_device_by_name(&i2c_bus_type, NULL, i2c_dev_name);
+- if (!i2c_dev)
+- return -EPROBE_DEFER;
++ int cnt = 0;
+
+ switch (BYT_RT5640_MAP(byt_rt5640_quirk)) {
+ case BYT_RT5640_DMIC1_MAP:
+@@ -989,10 +986,7 @@ static int byt_rt5640_add_codec_device_props(const char *i2c_dev_name)
+ if (byt_rt5640_quirk & BYT_RT5640_JD_NOT_INV)
+ props[cnt++] = PROPERTY_ENTRY_BOOL("realtek,jack-detect-not-inverted");
+
+- ret = device_add_properties(i2c_dev, props);
+- put_device(i2c_dev);
+-
+- return ret;
++ return device_add_properties(i2c_dev, props);
+ }
+
+ static int byt_rt5640_init(struct snd_soc_pcm_runtime *runtime)
+@@ -1324,6 +1318,7 @@ static int snd_byt_rt5640_mc_probe(struct platform_device *pdev)
+ struct snd_soc_acpi_mach *mach;
+ const char *platform_name;
+ struct acpi_device *adev;
++ struct device *codec_dev;
+ int ret_val = 0;
+ int dai_index = 0;
+ int i, cfg_spk;
+@@ -1430,10 +1425,15 @@ static int snd_byt_rt5640_mc_probe(struct platform_device *pdev)
+ byt_rt5640_quirk = quirk_override;
+ }
+
++ codec_dev = acpi_get_first_physical_node(adev);
++ if (!codec_dev)
++ return -EPROBE_DEFER;
++ priv->codec_dev = get_device(codec_dev);
++
+ /* Must be called before register_card, also see declaration comment. */
+- ret_val = byt_rt5640_add_codec_device_props(byt_rt5640_codec_name);
++ ret_val = byt_rt5640_add_codec_device_props(codec_dev, priv);
+ if (ret_val)
+- return ret_val;
++ goto err;
+
+ log_quirks(&pdev->dev);
+
+@@ -1460,7 +1460,7 @@ static int snd_byt_rt5640_mc_probe(struct platform_device *pdev)
+ * for all other errors, including -EPROBE_DEFER
+ */
+ if (ret_val != -ENOENT)
+- return ret_val;
++ goto err;
+ byt_rt5640_quirk &= ~BYT_RT5640_MCLK_EN;
+ }
+ }
+@@ -1493,17 +1493,30 @@ static int snd_byt_rt5640_mc_probe(struct platform_device *pdev)
+ ret_val = snd_soc_fixup_dai_links_platform_name(&byt_rt5640_card,
+ platform_name);
+ if (ret_val)
+- return ret_val;
++ goto err;
+
+ ret_val = devm_snd_soc_register_card(&pdev->dev, &byt_rt5640_card);
+
+ if (ret_val) {
+ dev_err(&pdev->dev, "devm_snd_soc_register_card failed %d\n",
+ ret_val);
+- return ret_val;
++ goto err;
+ }
+ platform_set_drvdata(pdev, &byt_rt5640_card);
+ return ret_val;
++
++err:
++ put_device(priv->codec_dev);
++ return ret_val;
++}
++
++static int snd_byt_rt5640_mc_remove(struct platform_device *pdev)
++{
++ struct snd_soc_card *card = platform_get_drvdata(pdev);
++ struct byt_rt5640_private *priv = snd_soc_card_get_drvdata(card);
++
++ put_device(priv->codec_dev);
++ return 0;
+ }
+
+ static struct platform_driver snd_byt_rt5640_mc_driver = {
+@@ -1514,6 +1527,7 @@ static struct platform_driver snd_byt_rt5640_mc_driver = {
+ #endif
+ },
+ .probe = snd_byt_rt5640_mc_probe,
++ .remove = snd_byt_rt5640_mc_remove,
+ };
+
+ module_platform_driver(snd_byt_rt5640_mc_driver);
+diff --git a/sound/soc/intel/boards/bytcr_rt5651.c b/sound/soc/intel/boards/bytcr_rt5651.c
+index bf8b87d45cb0a..a8289f74463e9 100644
+--- a/sound/soc/intel/boards/bytcr_rt5651.c
++++ b/sound/soc/intel/boards/bytcr_rt5651.c
+@@ -85,6 +85,7 @@ struct byt_rt5651_private {
+ struct gpio_desc *ext_amp_gpio;
+ struct gpio_desc *hp_detect;
+ struct snd_soc_jack jack;
++ struct device *codec_dev;
+ };
+
+ static const struct acpi_gpio_mapping *byt_rt5651_gpios;
+@@ -918,17 +919,17 @@ static int snd_byt_rt5651_mc_probe(struct platform_device *pdev)
+ if (adev) {
+ snprintf(byt_rt5651_codec_name, sizeof(byt_rt5651_codec_name),
+ "i2c-%s", acpi_dev_name(adev));
+- put_device(&adev->dev);
+ byt_rt5651_dais[dai_index].codecs->name = byt_rt5651_codec_name;
+ } else {
+ dev_err(&pdev->dev, "Error cannot find '%s' dev\n", mach->id);
+ return -ENODEV;
+ }
+
+- codec_dev = bus_find_device_by_name(&i2c_bus_type, NULL,
+- byt_rt5651_codec_name);
++ codec_dev = acpi_get_first_physical_node(adev);
++ acpi_dev_put(adev);
+ if (!codec_dev)
+ return -EPROBE_DEFER;
++ priv->codec_dev = get_device(codec_dev);
+
+ /*
+ * swap SSP0 if bytcr is detected
+@@ -997,10 +998,8 @@ static int snd_byt_rt5651_mc_probe(struct platform_device *pdev)
+
+ /* Must be called before register_card, also see declaration comment. */
+ ret_val = byt_rt5651_add_codec_device_props(codec_dev);
+- if (ret_val) {
+- put_device(codec_dev);
+- return ret_val;
+- }
++ if (ret_val)
++ goto err;
+
+ /* Cherry Trail devices use an external amplifier enable gpio */
+ if (soc_intel_is_cht() && !byt_rt5651_gpios)
+@@ -1024,8 +1023,7 @@ static int snd_byt_rt5651_mc_probe(struct platform_device *pdev)
+ ret_val);
+ fallthrough;
+ case -EPROBE_DEFER:
+- put_device(codec_dev);
+- return ret_val;
++ goto err;
+ }
+ }
+ priv->hp_detect = devm_fwnode_gpiod_get(&pdev->dev,
+@@ -1044,14 +1042,11 @@ static int snd_byt_rt5651_mc_probe(struct platform_device *pdev)
+ ret_val);
+ fallthrough;
+ case -EPROBE_DEFER:
+- put_device(codec_dev);
+- return ret_val;
++ goto err;
+ }
+ }
+ }
+
+- put_device(codec_dev);
+-
+ log_quirks(&pdev->dev);
+
+ if ((byt_rt5651_quirk & BYT_RT5651_SSP2_AIF2) ||
+@@ -1075,7 +1070,7 @@ static int snd_byt_rt5651_mc_probe(struct platform_device *pdev)
+ * for all other errors, including -EPROBE_DEFER
+ */
+ if (ret_val != -ENOENT)
+- return ret_val;
++ goto err;
+ byt_rt5651_quirk &= ~BYT_RT5651_MCLK_EN;
+ }
+ }
+@@ -1104,17 +1099,30 @@ static int snd_byt_rt5651_mc_probe(struct platform_device *pdev)
+ ret_val = snd_soc_fixup_dai_links_platform_name(&byt_rt5651_card,
+ platform_name);
+ if (ret_val)
+- return ret_val;
++ goto err;
+
+ ret_val = devm_snd_soc_register_card(&pdev->dev, &byt_rt5651_card);
+
+ if (ret_val) {
+ dev_err(&pdev->dev, "devm_snd_soc_register_card failed %d\n",
+ ret_val);
+- return ret_val;
++ goto err;
+ }
+ platform_set_drvdata(pdev, &byt_rt5651_card);
+ return ret_val;
++
++err:
++ put_device(priv->codec_dev);
++ return ret_val;
++}
++
++static int snd_byt_rt5651_mc_remove(struct platform_device *pdev)
++{
++ struct snd_soc_card *card = platform_get_drvdata(pdev);
++ struct byt_rt5651_private *priv = snd_soc_card_get_drvdata(card);
++
++ put_device(priv->codec_dev);
++ return 0;
+ }
+
+ static struct platform_driver snd_byt_rt5651_mc_driver = {
+@@ -1125,6 +1133,7 @@ static struct platform_driver snd_byt_rt5651_mc_driver = {
+ #endif
+ },
+ .probe = snd_byt_rt5651_mc_probe,
++ .remove = snd_byt_rt5651_mc_remove,
+ };
+
+ module_platform_driver(snd_byt_rt5651_mc_driver);
+diff --git a/sound/soc/sunxi/sun4i-spdif.c b/sound/soc/sunxi/sun4i-spdif.c
+index 228485fe07342..6dcad1aa25037 100644
+--- a/sound/soc/sunxi/sun4i-spdif.c
++++ b/sound/soc/sunxi/sun4i-spdif.c
+@@ -464,6 +464,11 @@ static const struct of_device_id sun4i_spdif_of_match[] = {
+ .compatible = "allwinner,sun50i-h6-spdif",
+ .data = &sun50i_h6_spdif_quirks,
+ },
++ {
++ .compatible = "allwinner,sun50i-h616-spdif",
++ /* Essentially the same as the H6, but without RX */
++ .data = &sun50i_h6_spdif_quirks,
++ },
+ { /* sentinel */ }
+ };
+ MODULE_DEVICE_TABLE(of, sun4i_spdif_of_match);