summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMike Pagano <mpagano@gentoo.org>2023-08-30 11:00:40 -0400
committerMike Pagano <mpagano@gentoo.org>2023-08-30 11:00:40 -0400
commit3cd4ba429f47b781ce5cd8d3e632fd2559a93374 (patch)
treede232da92fec30e529bb4cde6a32f3e6f2018f80
parentLinux patch 4.19.292 (diff)
downloadlinux-patches-3cd4ba429f47b781ce5cd8d3e632fd2559a93374.tar.gz
linux-patches-3cd4ba429f47b781ce5cd8d3e632fd2559a93374.tar.bz2
linux-patches-3cd4ba429f47b781ce5cd8d3e632fd2559a93374.zip
Linux patch 4.19.2924.19-294
Signed-off-by: Mike Pagano <mpagano@gentoo.org>
-rw-r--r--0000_README4
-rw-r--r--1292_linux-4.19.293.patch10805
2 files changed, 10809 insertions, 0 deletions
diff --git a/0000_README b/0000_README
index cff17d32..a211d53c 100644
--- a/0000_README
+++ b/0000_README
@@ -1211,6 +1211,10 @@ Patch: 1291_linux-4.19.292.patch
From: https://www.kernel.org
Desc: Linux 4.19.292
+Patch: 1292_linux-4.19.293.patch
+From: https://www.kernel.org
+Desc: Linux 4.19.293
+
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/1292_linux-4.19.293.patch b/1292_linux-4.19.293.patch
new file mode 100644
index 00000000..3a139a99
--- /dev/null
+++ b/1292_linux-4.19.293.patch
@@ -0,0 +1,10805 @@
+diff --git a/Makefile b/Makefile
+index fcd6a9b173018..5965df0393fd3 100644
+--- a/Makefile
++++ b/Makefile
+@@ -1,7 +1,7 @@
+ # SPDX-License-Identifier: GPL-2.0
+ VERSION = 4
+ PATCHLEVEL = 19
+-SUBLEVEL = 292
++SUBLEVEL = 293
+ EXTRAVERSION =
+ NAME = "People's Front"
+
+diff --git a/arch/mips/include/asm/cpu-features.h b/arch/mips/include/asm/cpu-features.h
+index 4e2ee743088fd..51faee4207454 100644
+--- a/arch/mips/include/asm/cpu-features.h
++++ b/arch/mips/include/asm/cpu-features.h
+@@ -111,7 +111,24 @@
+ #define cpu_has_tx39_cache __opt(MIPS_CPU_TX39_CACHE)
+ #endif
+ #ifndef cpu_has_octeon_cache
+-#define cpu_has_octeon_cache 0
++#define cpu_has_octeon_cache \
++({ \
++ int __res; \
++ \
++ switch (boot_cpu_type()) { \
++ case CPU_CAVIUM_OCTEON: \
++ case CPU_CAVIUM_OCTEON_PLUS: \
++ case CPU_CAVIUM_OCTEON2: \
++ case CPU_CAVIUM_OCTEON3: \
++ __res = 1; \
++ break; \
++ \
++ default: \
++ __res = 0; \
++ } \
++ \
++ __res; \
++})
+ #endif
+ /* Don't override `cpu_has_fpu' to 1 or the "nofpu" option won't work. */
+ #ifndef cpu_has_fpu
+@@ -332,7 +349,7 @@
+ ({ \
+ int __res; \
+ \
+- switch (current_cpu_type()) { \
++ switch (boot_cpu_type()) { \
+ case CPU_M14KC: \
+ case CPU_74K: \
+ case CPU_1074K: \
+diff --git a/arch/mips/include/asm/dec/prom.h b/arch/mips/include/asm/dec/prom.h
+index 09538ff5e9245..6f0405ba27d6d 100644
+--- a/arch/mips/include/asm/dec/prom.h
++++ b/arch/mips/include/asm/dec/prom.h
+@@ -74,7 +74,7 @@ static inline bool prom_is_rex(u32 magic)
+ */
+ typedef struct {
+ int pagesize;
+- unsigned char bitmap[0];
++ unsigned char bitmap[];
+ } memmap;
+
+
+diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig
+index f0e09d5f0bedd..3be56d857d57f 100644
+--- a/arch/powerpc/Kconfig
++++ b/arch/powerpc/Kconfig
+@@ -181,6 +181,7 @@ config PPC
+ select HAVE_ARCH_SECCOMP_FILTER
+ select HAVE_ARCH_TRACEHOOK
+ select HAVE_CBPF_JIT if !PPC64
++ select HAVE_STACKPROTECTOR if $(cc-option,-mstack-protector-guard=tls) && PPC32
+ select HAVE_CONTEXT_TRACKING if PPC64
+ select HAVE_DEBUG_KMEMLEAK
+ select HAVE_DEBUG_STACKOVERFLOW
+diff --git a/arch/powerpc/Kconfig.debug b/arch/powerpc/Kconfig.debug
+index 923b3b794d13f..1f54bb93b5cc7 100644
+--- a/arch/powerpc/Kconfig.debug
++++ b/arch/powerpc/Kconfig.debug
+@@ -368,10 +368,6 @@ config PPC_PTDUMP
+
+ If you are unsure, say N.
+
+-config PPC_HTDUMP
+- def_bool y
+- depends on PPC_PTDUMP && PPC_BOOK3S_64
+-
+ config PPC_FAST_ENDIAN_SWITCH
+ bool "Deprecated fast endian-switch syscall"
+ depends on DEBUG_KERNEL && PPC_BOOK3S_64
+diff --git a/arch/powerpc/Makefile b/arch/powerpc/Makefile
+index b2e0fd8735627..daddada1a3902 100644
+--- a/arch/powerpc/Makefile
++++ b/arch/powerpc/Makefile
+@@ -113,6 +113,9 @@ KBUILD_LDFLAGS += -m elf$(BITS)$(LDEMULATION)
+ KBUILD_ARFLAGS += --target=elf$(BITS)-$(GNUTARGET)
+ endif
+
++cflags-$(CONFIG_STACKPROTECTOR) += -mstack-protector-guard=tls
++cflags-$(CONFIG_STACKPROTECTOR) += -mstack-protector-guard-reg=r2
++
+ LDFLAGS_vmlinux-y := -Bstatic
+ LDFLAGS_vmlinux-$(CONFIG_RELOCATABLE) := -pie
+ LDFLAGS_vmlinux := $(LDFLAGS_vmlinux-y)
+@@ -419,9 +422,12 @@ archclean:
+
+ archprepare: checkbin
+
+-# Use the file '.tmp_gas_check' for binutils tests, as gas won't output
+-# to stdout and these checks are run even on install targets.
+-TOUT := .tmp_gas_check
++ifdef CONFIG_STACKPROTECTOR
++prepare: stack_protector_prepare
++
++stack_protector_prepare: prepare0
++ $(eval KBUILD_CFLAGS += -mstack-protector-guard-offset=$(shell awk '{if ($$2 == "TASK_CANARY") print $$3;}' include/generated/asm-offsets.h))
++endif
+
+ # Check toolchain versions:
+ # - gcc-4.6 is the minimum kernel-wide version so nothing required.
+@@ -433,7 +439,11 @@ checkbin:
+ echo -n '*** Please use a different binutils version.' ; \
+ false ; \
+ fi
+-
+-
+-CLEAN_FILES += $(TOUT)
+-
++ @if test "x${CONFIG_FTRACE_MCOUNT_USE_RECORDMCOUNT}" = "xy" -a \
++ "x${CONFIG_LD_IS_BFD}" = "xy" -a \
++ "${CONFIG_LD_VERSION}" = "23700" ; then \
++ echo -n '*** binutils 2.37 drops unused section symbols, which recordmcount ' ; \
++ echo 'is unable to handle.' ; \
++ echo '*** Please use a different binutils version.' ; \
++ false ; \
++ fi
+diff --git a/arch/powerpc/include/asm/book3s/32/mmu-hash.h b/arch/powerpc/include/asm/book3s/32/mmu-hash.h
+index e38c91388c40f..958b18cecc96a 100644
+--- a/arch/powerpc/include/asm/book3s/32/mmu-hash.h
++++ b/arch/powerpc/include/asm/book3s/32/mmu-hash.h
+@@ -34,14 +34,20 @@
+ #define BAT_PHYS_ADDR(x) ((u32)((x & 0x00000000fffe0000ULL) | \
+ ((x & 0x0000000e00000000ULL) >> 24) | \
+ ((x & 0x0000000100000000ULL) >> 30)))
++#define PHYS_BAT_ADDR(x) (((u64)(x) & 0x00000000fffe0000ULL) | \
++ (((u64)(x) << 24) & 0x0000000e00000000ULL) | \
++ (((u64)(x) << 30) & 0x0000000100000000ULL))
+ #else
+ #define BAT_PHYS_ADDR(x) (x)
++#define PHYS_BAT_ADDR(x) ((x) & 0xfffe0000)
+ #endif
+
+ struct ppc_bat {
+ u32 batu;
+ u32 batl;
+ };
++
++typedef struct page *pgtable_t;
+ #endif /* !__ASSEMBLY__ */
+
+ /*
+diff --git a/arch/powerpc/include/asm/book3s/64/mmu.h b/arch/powerpc/include/asm/book3s/64/mmu.h
+index 9c8c669a6b6a3..488e7ed07e967 100644
+--- a/arch/powerpc/include/asm/book3s/64/mmu.h
++++ b/arch/powerpc/include/asm/book3s/64/mmu.h
+@@ -2,6 +2,8 @@
+ #ifndef _ASM_POWERPC_BOOK3S_64_MMU_H_
+ #define _ASM_POWERPC_BOOK3S_64_MMU_H_
+
++#include <asm/page.h>
++
+ #ifndef __ASSEMBLY__
+ /*
+ * Page size definition
+@@ -24,6 +26,13 @@ struct mmu_psize_def {
+ };
+ extern struct mmu_psize_def mmu_psize_defs[MMU_PAGE_COUNT];
+
++/*
++ * For BOOK3s 64 with 4k and 64K linux page size
++ * we want to use pointers, because the page table
++ * actually store pfn
++ */
++typedef pte_t *pgtable_t;
++
+ #endif /* __ASSEMBLY__ */
+
+ /* 64-bit classic hash table MMU */
+diff --git a/arch/powerpc/include/asm/mmu-40x.h b/arch/powerpc/include/asm/mmu-40x.h
+deleted file mode 100644
+index 74f4edb5916e4..0000000000000
+--- a/arch/powerpc/include/asm/mmu-40x.h
++++ /dev/null
+@@ -1,68 +0,0 @@
+-/* SPDX-License-Identifier: GPL-2.0 */
+-#ifndef _ASM_POWERPC_MMU_40X_H_
+-#define _ASM_POWERPC_MMU_40X_H_
+-
+-/*
+- * PPC40x support
+- */
+-
+-#define PPC40X_TLB_SIZE 64
+-
+-/*
+- * TLB entries are defined by a "high" tag portion and a "low" data
+- * portion. On all architectures, the data portion is 32-bits.
+- *
+- * TLB entries are managed entirely under software control by reading,
+- * writing, and searchoing using the 4xx-specific tlbre, tlbwr, and tlbsx
+- * instructions.
+- */
+-
+-#define TLB_LO 1
+-#define TLB_HI 0
+-
+-#define TLB_DATA TLB_LO
+-#define TLB_TAG TLB_HI
+-
+-/* Tag portion */
+-
+-#define TLB_EPN_MASK 0xFFFFFC00 /* Effective Page Number */
+-#define TLB_PAGESZ_MASK 0x00000380
+-#define TLB_PAGESZ(x) (((x) & 0x7) << 7)
+-#define PAGESZ_1K 0
+-#define PAGESZ_4K 1
+-#define PAGESZ_16K 2
+-#define PAGESZ_64K 3
+-#define PAGESZ_256K 4
+-#define PAGESZ_1M 5
+-#define PAGESZ_4M 6
+-#define PAGESZ_16M 7
+-#define TLB_VALID 0x00000040 /* Entry is valid */
+-
+-/* Data portion */
+-
+-#define TLB_RPN_MASK 0xFFFFFC00 /* Real Page Number */
+-#define TLB_PERM_MASK 0x00000300
+-#define TLB_EX 0x00000200 /* Instruction execution allowed */
+-#define TLB_WR 0x00000100 /* Writes permitted */
+-#define TLB_ZSEL_MASK 0x000000F0
+-#define TLB_ZSEL(x) (((x) & 0xF) << 4)
+-#define TLB_ATTR_MASK 0x0000000F
+-#define TLB_W 0x00000008 /* Caching is write-through */
+-#define TLB_I 0x00000004 /* Caching is inhibited */
+-#define TLB_M 0x00000002 /* Memory is coherent */
+-#define TLB_G 0x00000001 /* Memory is guarded from prefetch */
+-
+-#ifndef __ASSEMBLY__
+-
+-typedef struct {
+- unsigned int id;
+- unsigned int active;
+- unsigned long vdso_base;
+-} mm_context_t;
+-
+-#endif /* !__ASSEMBLY__ */
+-
+-#define mmu_virtual_psize MMU_PAGE_4K
+-#define mmu_linear_psize MMU_PAGE_256M
+-
+-#endif /* _ASM_POWERPC_MMU_40X_H_ */
+diff --git a/arch/powerpc/include/asm/mmu-44x.h b/arch/powerpc/include/asm/mmu-44x.h
+deleted file mode 100644
+index 295b3dbb2698b..0000000000000
+--- a/arch/powerpc/include/asm/mmu-44x.h
++++ /dev/null
+@@ -1,153 +0,0 @@
+-/* SPDX-License-Identifier: GPL-2.0 */
+-#ifndef _ASM_POWERPC_MMU_44X_H_
+-#define _ASM_POWERPC_MMU_44X_H_
+-/*
+- * PPC440 support
+- */
+-
+-#include <asm/asm-const.h>
+-
+-#define PPC44x_MMUCR_TID 0x000000ff
+-#define PPC44x_MMUCR_STS 0x00010000
+-
+-#define PPC44x_TLB_PAGEID 0
+-#define PPC44x_TLB_XLAT 1
+-#define PPC44x_TLB_ATTRIB 2
+-
+-/* Page identification fields */
+-#define PPC44x_TLB_EPN_MASK 0xfffffc00 /* Effective Page Number */
+-#define PPC44x_TLB_VALID 0x00000200 /* Valid flag */
+-#define PPC44x_TLB_TS 0x00000100 /* Translation address space */
+-#define PPC44x_TLB_1K 0x00000000 /* Page sizes */
+-#define PPC44x_TLB_4K 0x00000010
+-#define PPC44x_TLB_16K 0x00000020
+-#define PPC44x_TLB_64K 0x00000030
+-#define PPC44x_TLB_256K 0x00000040
+-#define PPC44x_TLB_1M 0x00000050
+-#define PPC44x_TLB_16M 0x00000070
+-#define PPC44x_TLB_256M 0x00000090
+-
+-/* Translation fields */
+-#define PPC44x_TLB_RPN_MASK 0xfffffc00 /* Real Page Number */
+-#define PPC44x_TLB_ERPN_MASK 0x0000000f
+-
+-/* Storage attribute and access control fields */
+-#define PPC44x_TLB_ATTR_MASK 0x0000ff80
+-#define PPC44x_TLB_U0 0x00008000 /* User 0 */
+-#define PPC44x_TLB_U1 0x00004000 /* User 1 */
+-#define PPC44x_TLB_U2 0x00002000 /* User 2 */
+-#define PPC44x_TLB_U3 0x00001000 /* User 3 */
+-#define PPC44x_TLB_W 0x00000800 /* Caching is write-through */
+-#define PPC44x_TLB_I 0x00000400 /* Caching is inhibited */
+-#define PPC44x_TLB_M 0x00000200 /* Memory is coherent */
+-#define PPC44x_TLB_G 0x00000100 /* Memory is guarded */
+-#define PPC44x_TLB_E 0x00000080 /* Memory is little endian */
+-
+-#define PPC44x_TLB_PERM_MASK 0x0000003f
+-#define PPC44x_TLB_UX 0x00000020 /* User execution */
+-#define PPC44x_TLB_UW 0x00000010 /* User write */
+-#define PPC44x_TLB_UR 0x00000008 /* User read */
+-#define PPC44x_TLB_SX 0x00000004 /* Super execution */
+-#define PPC44x_TLB_SW 0x00000002 /* Super write */
+-#define PPC44x_TLB_SR 0x00000001 /* Super read */
+-
+-/* Number of TLB entries */
+-#define PPC44x_TLB_SIZE 64
+-
+-/* 47x bits */
+-#define PPC47x_MMUCR_TID 0x0000ffff
+-#define PPC47x_MMUCR_STS 0x00010000
+-
+-/* Page identification fields */
+-#define PPC47x_TLB0_EPN_MASK 0xfffff000 /* Effective Page Number */
+-#define PPC47x_TLB0_VALID 0x00000800 /* Valid flag */
+-#define PPC47x_TLB0_TS 0x00000400 /* Translation address space */
+-#define PPC47x_TLB0_4K 0x00000000
+-#define PPC47x_TLB0_16K 0x00000010
+-#define PPC47x_TLB0_64K 0x00000030
+-#define PPC47x_TLB0_1M 0x00000070
+-#define PPC47x_TLB0_16M 0x000000f0
+-#define PPC47x_TLB0_256M 0x000001f0
+-#define PPC47x_TLB0_1G 0x000003f0
+-#define PPC47x_TLB0_BOLTED_R 0x00000008 /* tlbre only */
+-
+-/* Translation fields */
+-#define PPC47x_TLB1_RPN_MASK 0xfffff000 /* Real Page Number */
+-#define PPC47x_TLB1_ERPN_MASK 0x000003ff
+-
+-/* Storage attribute and access control fields */
+-#define PPC47x_TLB2_ATTR_MASK 0x0003ff80
+-#define PPC47x_TLB2_IL1I 0x00020000 /* Memory is guarded */
+-#define PPC47x_TLB2_IL1D 0x00010000 /* Memory is guarded */
+-#define PPC47x_TLB2_U0 0x00008000 /* User 0 */
+-#define PPC47x_TLB2_U1 0x00004000 /* User 1 */
+-#define PPC47x_TLB2_U2 0x00002000 /* User 2 */
+-#define PPC47x_TLB2_U3 0x00001000 /* User 3 */
+-#define PPC47x_TLB2_W 0x00000800 /* Caching is write-through */
+-#define PPC47x_TLB2_I 0x00000400 /* Caching is inhibited */
+-#define PPC47x_TLB2_M 0x00000200 /* Memory is coherent */
+-#define PPC47x_TLB2_G 0x00000100 /* Memory is guarded */
+-#define PPC47x_TLB2_E 0x00000080 /* Memory is little endian */
+-#define PPC47x_TLB2_PERM_MASK 0x0000003f
+-#define PPC47x_TLB2_UX 0x00000020 /* User execution */
+-#define PPC47x_TLB2_UW 0x00000010 /* User write */
+-#define PPC47x_TLB2_UR 0x00000008 /* User read */
+-#define PPC47x_TLB2_SX 0x00000004 /* Super execution */
+-#define PPC47x_TLB2_SW 0x00000002 /* Super write */
+-#define PPC47x_TLB2_SR 0x00000001 /* Super read */
+-#define PPC47x_TLB2_U_RWX (PPC47x_TLB2_UX|PPC47x_TLB2_UW|PPC47x_TLB2_UR)
+-#define PPC47x_TLB2_S_RWX (PPC47x_TLB2_SX|PPC47x_TLB2_SW|PPC47x_TLB2_SR)
+-#define PPC47x_TLB2_S_RW (PPC47x_TLB2_SW | PPC47x_TLB2_SR)
+-#define PPC47x_TLB2_IMG (PPC47x_TLB2_I | PPC47x_TLB2_M | PPC47x_TLB2_G)
+-
+-#ifndef __ASSEMBLY__
+-
+-extern unsigned int tlb_44x_hwater;
+-extern unsigned int tlb_44x_index;
+-
+-typedef struct {
+- unsigned int id;
+- unsigned int active;
+- unsigned long vdso_base;
+-} mm_context_t;
+-
+-#endif /* !__ASSEMBLY__ */
+-
+-#ifndef CONFIG_PPC_EARLY_DEBUG_44x
+-#define PPC44x_EARLY_TLBS 1
+-#else
+-#define PPC44x_EARLY_TLBS 2
+-#define PPC44x_EARLY_DEBUG_VIRTADDR (ASM_CONST(0xf0000000) \
+- | (ASM_CONST(CONFIG_PPC_EARLY_DEBUG_44x_PHYSLOW) & 0xffff))
+-#endif
+-
+-/* Size of the TLBs used for pinning in lowmem */
+-#define PPC_PIN_SIZE (1 << 28) /* 256M */
+-
+-#if defined(CONFIG_PPC_4K_PAGES)
+-#define PPC44x_TLBE_SIZE PPC44x_TLB_4K
+-#define PPC47x_TLBE_SIZE PPC47x_TLB0_4K
+-#define mmu_virtual_psize MMU_PAGE_4K
+-#elif defined(CONFIG_PPC_16K_PAGES)
+-#define PPC44x_TLBE_SIZE PPC44x_TLB_16K
+-#define PPC47x_TLBE_SIZE PPC47x_TLB0_16K
+-#define mmu_virtual_psize MMU_PAGE_16K
+-#elif defined(CONFIG_PPC_64K_PAGES)
+-#define PPC44x_TLBE_SIZE PPC44x_TLB_64K
+-#define PPC47x_TLBE_SIZE PPC47x_TLB0_64K
+-#define mmu_virtual_psize MMU_PAGE_64K
+-#elif defined(CONFIG_PPC_256K_PAGES)
+-#define PPC44x_TLBE_SIZE PPC44x_TLB_256K
+-#define mmu_virtual_psize MMU_PAGE_256K
+-#else
+-#error "Unsupported PAGE_SIZE"
+-#endif
+-
+-#define mmu_linear_psize MMU_PAGE_256M
+-
+-#define PPC44x_PGD_OFF_SHIFT (32 - PGDIR_SHIFT + PGD_T_LOG2)
+-#define PPC44x_PGD_OFF_MASK_BIT (PGDIR_SHIFT - PGD_T_LOG2)
+-#define PPC44x_PTE_ADD_SHIFT (32 - PGDIR_SHIFT + PTE_SHIFT + PTE_T_LOG2)
+-#define PPC44x_PTE_ADD_MASK_BIT (32 - PTE_T_LOG2 - PTE_SHIFT)
+-
+-#endif /* _ASM_POWERPC_MMU_44X_H_ */
+diff --git a/arch/powerpc/include/asm/mmu-8xx.h b/arch/powerpc/include/asm/mmu-8xx.h
+deleted file mode 100644
+index 193f53116c7ae..0000000000000
+--- a/arch/powerpc/include/asm/mmu-8xx.h
++++ /dev/null
+@@ -1,244 +0,0 @@
+-/* SPDX-License-Identifier: GPL-2.0 */
+-#ifndef _ASM_POWERPC_MMU_8XX_H_
+-#define _ASM_POWERPC_MMU_8XX_H_
+-/*
+- * PPC8xx support
+- */
+-
+-/* Control/status registers for the MPC8xx.
+- * A write operation to these registers causes serialized access.
+- * During software tablewalk, the registers used perform mask/shift-add
+- * operations when written/read. A TLB entry is created when the Mx_RPN
+- * is written, and the contents of several registers are used to
+- * create the entry.
+- */
+-#define SPRN_MI_CTR 784 /* Instruction TLB control register */
+-#define MI_GPM 0x80000000 /* Set domain manager mode */
+-#define MI_PPM 0x40000000 /* Set subpage protection */
+-#define MI_CIDEF 0x20000000 /* Set cache inhibit when MMU dis */
+-#define MI_RSV4I 0x08000000 /* Reserve 4 TLB entries */
+-#define MI_PPCS 0x02000000 /* Use MI_RPN prob/priv state */
+-#define MI_IDXMASK 0x00001f00 /* TLB index to be loaded */
+-#define MI_RESETVAL 0x00000000 /* Value of register at reset */
+-
+-/* These are the Ks and Kp from the PowerPC books. For proper operation,
+- * Ks = 0, Kp = 1.
+- */
+-#define SPRN_MI_AP 786
+-#define MI_Ks 0x80000000 /* Should not be set */
+-#define MI_Kp 0x40000000 /* Should always be set */
+-
+-/*
+- * All pages' PP data bits are set to either 001 or 011 by copying _PAGE_EXEC
+- * into bit 21 in the ITLBmiss handler (bit 21 is the middle bit), which means
+- * respectively NA for All or X for Supervisor and no access for User.
+- * Then we use the APG to say whether accesses are according to Page rules or
+- * "all Supervisor" rules (Access to all)
+- * Therefore, we define 2 APG groups. lsb is _PMD_USER
+- * 0 => No user => 01 (all accesses performed according to page definition)
+- * 1 => User => 00 (all accesses performed as supervisor iaw page definition)
+- * We define all 16 groups so that all other bits of APG can take any value
+- */
+-#define MI_APG_INIT 0x44444444
+-
+-/* The effective page number register. When read, contains the information
+- * about the last instruction TLB miss. When MI_RPN is written, bits in
+- * this register are used to create the TLB entry.
+- */
+-#define SPRN_MI_EPN 787
+-#define MI_EPNMASK 0xfffff000 /* Effective page number for entry */
+-#define MI_EVALID 0x00000200 /* Entry is valid */
+-#define MI_ASIDMASK 0x0000000f /* ASID match value */
+- /* Reset value is undefined */
+-
+-/* A "level 1" or "segment" or whatever you want to call it register.
+- * For the instruction TLB, it contains bits that get loaded into the
+- * TLB entry when the MI_RPN is written.
+- */
+-#define SPRN_MI_TWC 789
+-#define MI_APG 0x000001e0 /* Access protection group (0) */
+-#define MI_GUARDED 0x00000010 /* Guarded storage */
+-#define MI_PSMASK 0x0000000c /* Mask of page size bits */
+-#define MI_PS8MEG 0x0000000c /* 8M page size */
+-#define MI_PS512K 0x00000004 /* 512K page size */
+-#define MI_PS4K_16K 0x00000000 /* 4K or 16K page size */
+-#define MI_SVALID 0x00000001 /* Segment entry is valid */
+- /* Reset value is undefined */
+-
+-/* Real page number. Defined by the pte. Writing this register
+- * causes a TLB entry to be created for the instruction TLB, using
+- * additional information from the MI_EPN, and MI_TWC registers.
+- */
+-#define SPRN_MI_RPN 790
+-#define MI_SPS16K 0x00000008 /* Small page size (0 = 4k, 1 = 16k) */
+-
+-/* Define an RPN value for mapping kernel memory to large virtual
+- * pages for boot initialization. This has real page number of 0,
+- * large page size, shared page, cache enabled, and valid.
+- * Also mark all subpages valid and write access.
+- */
+-#define MI_BOOTINIT 0x000001fd
+-
+-#define SPRN_MD_CTR 792 /* Data TLB control register */
+-#define MD_GPM 0x80000000 /* Set domain manager mode */
+-#define MD_PPM 0x40000000 /* Set subpage protection */
+-#define MD_CIDEF 0x20000000 /* Set cache inhibit when MMU dis */
+-#define MD_WTDEF 0x10000000 /* Set writethrough when MMU dis */
+-#define MD_RSV4I 0x08000000 /* Reserve 4 TLB entries */
+-#define MD_TWAM 0x04000000 /* Use 4K page hardware assist */
+-#define MD_PPCS 0x02000000 /* Use MI_RPN prob/priv state */
+-#define MD_IDXMASK 0x00001f00 /* TLB index to be loaded */
+-#define MD_RESETVAL 0x04000000 /* Value of register at reset */
+-
+-#define SPRN_M_CASID 793 /* Address space ID (context) to match */
+-#define MC_ASIDMASK 0x0000000f /* Bits used for ASID value */
+-
+-
+-/* These are the Ks and Kp from the PowerPC books. For proper operation,
+- * Ks = 0, Kp = 1.
+- */
+-#define SPRN_MD_AP 794
+-#define MD_Ks 0x80000000 /* Should not be set */
+-#define MD_Kp 0x40000000 /* Should always be set */
+-
+-/*
+- * All pages' PP data bits are set to either 000 or 011 or 001, which means
+- * respectively RW for Supervisor and no access for User, or RO for
+- * Supervisor and no access for user and NA for ALL.
+- * Then we use the APG to say whether accesses are according to Page rules or
+- * "all Supervisor" rules (Access to all)
+- * Therefore, we define 2 APG groups. lsb is _PMD_USER
+- * 0 => No user => 01 (all accesses performed according to page definition)
+- * 1 => User => 00 (all accesses performed as supervisor iaw page definition)
+- * We define all 16 groups so that all other bits of APG can take any value
+- */
+-#define MD_APG_INIT 0x44444444
+-
+-/* The effective page number register. When read, contains the information
+- * about the last instruction TLB miss. When MD_RPN is written, bits in
+- * this register are used to create the TLB entry.
+- */
+-#define SPRN_MD_EPN 795
+-#define MD_EPNMASK 0xfffff000 /* Effective page number for entry */
+-#define MD_EVALID 0x00000200 /* Entry is valid */
+-#define MD_ASIDMASK 0x0000000f /* ASID match value */
+- /* Reset value is undefined */
+-
+-/* The pointer to the base address of the first level page table.
+- * During a software tablewalk, reading this register provides the address
+- * of the entry associated with MD_EPN.
+- */
+-#define SPRN_M_TWB 796
+-#define M_L1TB 0xfffff000 /* Level 1 table base address */
+-#define M_L1INDX 0x00000ffc /* Level 1 index, when read */
+- /* Reset value is undefined */
+-
+-/* A "level 1" or "segment" or whatever you want to call it register.
+- * For the data TLB, it contains bits that get loaded into the TLB entry
+- * when the MD_RPN is written. It is also provides the hardware assist
+- * for finding the PTE address during software tablewalk.
+- */
+-#define SPRN_MD_TWC 797
+-#define MD_L2TB 0xfffff000 /* Level 2 table base address */
+-#define MD_L2INDX 0xfffffe00 /* Level 2 index (*pte), when read */
+-#define MD_APG 0x000001e0 /* Access protection group (0) */
+-#define MD_GUARDED 0x00000010 /* Guarded storage */
+-#define MD_PSMASK 0x0000000c /* Mask of page size bits */
+-#define MD_PS8MEG 0x0000000c /* 8M page size */
+-#define MD_PS512K 0x00000004 /* 512K page size */
+-#define MD_PS4K_16K 0x00000000 /* 4K or 16K page size */
+-#define MD_WT 0x00000002 /* Use writethrough page attribute */
+-#define MD_SVALID 0x00000001 /* Segment entry is valid */
+- /* Reset value is undefined */
+-
+-
+-/* Real page number. Defined by the pte. Writing this register
+- * causes a TLB entry to be created for the data TLB, using
+- * additional information from the MD_EPN, and MD_TWC registers.
+- */
+-#define SPRN_MD_RPN 798
+-#define MD_SPS16K 0x00000008 /* Small page size (0 = 4k, 1 = 16k) */
+-
+-/* This is a temporary storage register that could be used to save
+- * a processor working register during a tablewalk.
+- */
+-#define SPRN_M_TW 799
+-
+-#ifdef CONFIG_PPC_MM_SLICES
+-#include <asm/nohash/32/slice.h>
+-#define SLICE_ARRAY_SIZE (1 << (32 - SLICE_LOW_SHIFT - 1))
+-#endif
+-
+-#ifndef __ASSEMBLY__
+-struct slice_mask {
+- u64 low_slices;
+- DECLARE_BITMAP(high_slices, 0);
+-};
+-
+-typedef struct {
+- unsigned int id;
+- unsigned int active;
+- unsigned long vdso_base;
+-#ifdef CONFIG_PPC_MM_SLICES
+- u16 user_psize; /* page size index */
+- unsigned char low_slices_psize[SLICE_ARRAY_SIZE];
+- unsigned char high_slices_psize[0];
+- unsigned long slb_addr_limit;
+- struct slice_mask mask_base_psize; /* 4k or 16k */
+-# ifdef CONFIG_HUGETLB_PAGE
+- struct slice_mask mask_512k;
+- struct slice_mask mask_8m;
+-# endif
+-#endif
+-} mm_context_t;
+-
+-#define PHYS_IMMR_BASE (mfspr(SPRN_IMMR) & 0xfff80000)
+-#define VIRT_IMMR_BASE (__fix_to_virt(FIX_IMMR_BASE))
+-
+-/* Page size definitions, common between 32 and 64-bit
+- *
+- * shift : is the "PAGE_SHIFT" value for that page size
+- * penc : is the pte encoding mask
+- *
+- */
+-struct mmu_psize_def {
+- unsigned int shift; /* number of bits */
+- unsigned int enc; /* PTE encoding */
+- unsigned int ind; /* Corresponding indirect page size shift */
+- unsigned int flags;
+-#define MMU_PAGE_SIZE_DIRECT 0x1 /* Supported as a direct size */
+-#define MMU_PAGE_SIZE_INDIRECT 0x2 /* Supported as an indirect size */
+-};
+-
+-extern struct mmu_psize_def mmu_psize_defs[MMU_PAGE_COUNT];
+-
+-static inline int shift_to_mmu_psize(unsigned int shift)
+-{
+- int psize;
+-
+- for (psize = 0; psize < MMU_PAGE_COUNT; ++psize)
+- if (mmu_psize_defs[psize].shift == shift)
+- return psize;
+- return -1;
+-}
+-
+-static inline unsigned int mmu_psize_to_shift(unsigned int mmu_psize)
+-{
+- if (mmu_psize_defs[mmu_psize].shift)
+- return mmu_psize_defs[mmu_psize].shift;
+- BUG();
+-}
+-
+-#endif /* !__ASSEMBLY__ */
+-
+-#if defined(CONFIG_PPC_4K_PAGES)
+-#define mmu_virtual_psize MMU_PAGE_4K
+-#elif defined(CONFIG_PPC_16K_PAGES)
+-#define mmu_virtual_psize MMU_PAGE_16K
+-#else
+-#error "Unsupported PAGE_SIZE"
+-#endif
+-
+-#define mmu_linear_psize MMU_PAGE_8M
+-
+-#endif /* _ASM_POWERPC_MMU_8XX_H_ */
+diff --git a/arch/powerpc/include/asm/mmu-book3e.h b/arch/powerpc/include/asm/mmu-book3e.h
+deleted file mode 100644
+index e20072972e359..0000000000000
+--- a/arch/powerpc/include/asm/mmu-book3e.h
++++ /dev/null
+@@ -1,313 +0,0 @@
+-/* SPDX-License-Identifier: GPL-2.0 */
+-#ifndef _ASM_POWERPC_MMU_BOOK3E_H_
+-#define _ASM_POWERPC_MMU_BOOK3E_H_
+-/*
+- * Freescale Book-E/Book-3e (ISA 2.06+) MMU support
+- */
+-
+-/* Book-3e defined page sizes */
+-#define BOOK3E_PAGESZ_1K 0
+-#define BOOK3E_PAGESZ_2K 1
+-#define BOOK3E_PAGESZ_4K 2
+-#define BOOK3E_PAGESZ_8K 3
+-#define BOOK3E_PAGESZ_16K 4
+-#define BOOK3E_PAGESZ_32K 5
+-#define BOOK3E_PAGESZ_64K 6
+-#define BOOK3E_PAGESZ_128K 7
+-#define BOOK3E_PAGESZ_256K 8
+-#define BOOK3E_PAGESZ_512K 9
+-#define BOOK3E_PAGESZ_1M 10
+-#define BOOK3E_PAGESZ_2M 11
+-#define BOOK3E_PAGESZ_4M 12
+-#define BOOK3E_PAGESZ_8M 13
+-#define BOOK3E_PAGESZ_16M 14
+-#define BOOK3E_PAGESZ_32M 15
+-#define BOOK3E_PAGESZ_64M 16
+-#define BOOK3E_PAGESZ_128M 17
+-#define BOOK3E_PAGESZ_256M 18
+-#define BOOK3E_PAGESZ_512M 19
+-#define BOOK3E_PAGESZ_1GB 20
+-#define BOOK3E_PAGESZ_2GB 21
+-#define BOOK3E_PAGESZ_4GB 22
+-#define BOOK3E_PAGESZ_8GB 23
+-#define BOOK3E_PAGESZ_16GB 24
+-#define BOOK3E_PAGESZ_32GB 25
+-#define BOOK3E_PAGESZ_64GB 26
+-#define BOOK3E_PAGESZ_128GB 27
+-#define BOOK3E_PAGESZ_256GB 28
+-#define BOOK3E_PAGESZ_512GB 29
+-#define BOOK3E_PAGESZ_1TB 30
+-#define BOOK3E_PAGESZ_2TB 31
+-
+-/* MAS registers bit definitions */
+-
+-#define MAS0_TLBSEL_MASK 0x30000000
+-#define MAS0_TLBSEL_SHIFT 28
+-#define MAS0_TLBSEL(x) (((x) << MAS0_TLBSEL_SHIFT) & MAS0_TLBSEL_MASK)
+-#define MAS0_GET_TLBSEL(mas0) (((mas0) & MAS0_TLBSEL_MASK) >> \
+- MAS0_TLBSEL_SHIFT)
+-#define MAS0_ESEL_MASK 0x0FFF0000
+-#define MAS0_ESEL_SHIFT 16
+-#define MAS0_ESEL(x) (((x) << MAS0_ESEL_SHIFT) & MAS0_ESEL_MASK)
+-#define MAS0_NV(x) ((x) & 0x00000FFF)
+-#define MAS0_HES 0x00004000
+-#define MAS0_WQ_ALLWAYS 0x00000000
+-#define MAS0_WQ_COND 0x00001000
+-#define MAS0_WQ_CLR_RSRV 0x00002000
+-
+-#define MAS1_VALID 0x80000000
+-#define MAS1_IPROT 0x40000000
+-#define MAS1_TID(x) (((x) << 16) & 0x3FFF0000)
+-#define MAS1_IND 0x00002000
+-#define MAS1_TS 0x00001000
+-#define MAS1_TSIZE_MASK 0x00000f80
+-#define MAS1_TSIZE_SHIFT 7
+-#define MAS1_TSIZE(x) (((x) << MAS1_TSIZE_SHIFT) & MAS1_TSIZE_MASK)
+-#define MAS1_GET_TSIZE(mas1) (((mas1) & MAS1_TSIZE_MASK) >> MAS1_TSIZE_SHIFT)
+-
+-#define MAS2_EPN (~0xFFFUL)
+-#define MAS2_X0 0x00000040
+-#define MAS2_X1 0x00000020
+-#define MAS2_W 0x00000010
+-#define MAS2_I 0x00000008
+-#define MAS2_M 0x00000004
+-#define MAS2_G 0x00000002
+-#define MAS2_E 0x00000001
+-#define MAS2_WIMGE_MASK 0x0000001f
+-#define MAS2_EPN_MASK(size) (~0 << (size + 10))
+-#define MAS2_VAL(addr, size, flags) ((addr) & MAS2_EPN_MASK(size) | (flags))
+-
+-#define MAS3_RPN 0xFFFFF000
+-#define MAS3_U0 0x00000200
+-#define MAS3_U1 0x00000100
+-#define MAS3_U2 0x00000080
+-#define MAS3_U3 0x00000040
+-#define MAS3_UX 0x00000020
+-#define MAS3_SX 0x00000010
+-#define MAS3_UW 0x00000008
+-#define MAS3_SW 0x00000004
+-#define MAS3_UR 0x00000002
+-#define MAS3_SR 0x00000001
+-#define MAS3_BAP_MASK 0x0000003f
+-#define MAS3_SPSIZE 0x0000003e
+-#define MAS3_SPSIZE_SHIFT 1
+-
+-#define MAS4_TLBSEL_MASK MAS0_TLBSEL_MASK
+-#define MAS4_TLBSELD(x) MAS0_TLBSEL(x)
+-#define MAS4_INDD 0x00008000 /* Default IND */
+-#define MAS4_TSIZED(x) MAS1_TSIZE(x)
+-#define MAS4_X0D 0x00000040
+-#define MAS4_X1D 0x00000020
+-#define MAS4_WD 0x00000010
+-#define MAS4_ID 0x00000008
+-#define MAS4_MD 0x00000004
+-#define MAS4_GD 0x00000002
+-#define MAS4_ED 0x00000001
+-#define MAS4_WIMGED_MASK 0x0000001f /* Default WIMGE */
+-#define MAS4_WIMGED_SHIFT 0
+-#define MAS4_VLED MAS4_X1D /* Default VLE */
+-#define MAS4_ACMD 0x000000c0 /* Default ACM */
+-#define MAS4_ACMD_SHIFT 6
+-#define MAS4_TSIZED_MASK 0x00000f80 /* Default TSIZE */
+-#define MAS4_TSIZED_SHIFT 7
+-
+-#define MAS5_SGS 0x80000000
+-
+-#define MAS6_SPID0 0x3FFF0000
+-#define MAS6_SPID1 0x00007FFE
+-#define MAS6_ISIZE(x) MAS1_TSIZE(x)
+-#define MAS6_SAS 0x00000001
+-#define MAS6_SPID MAS6_SPID0
+-#define MAS6_SIND 0x00000002 /* Indirect page */
+-#define MAS6_SIND_SHIFT 1
+-#define MAS6_SPID_MASK 0x3fff0000
+-#define MAS6_SPID_SHIFT 16
+-#define MAS6_ISIZE_MASK 0x00000f80
+-#define MAS6_ISIZE_SHIFT 7
+-
+-#define MAS7_RPN 0xFFFFFFFF
+-
+-#define MAS8_TGS 0x80000000 /* Guest space */
+-#define MAS8_VF 0x40000000 /* Virtualization Fault */
+-#define MAS8_TLPID 0x000000ff
+-
+-/* Bit definitions for MMUCFG */
+-#define MMUCFG_MAVN 0x00000003 /* MMU Architecture Version Number */
+-#define MMUCFG_MAVN_V1 0x00000000 /* v1.0 */
+-#define MMUCFG_MAVN_V2 0x00000001 /* v2.0 */
+-#define MMUCFG_NTLBS 0x0000000c /* Number of TLBs */
+-#define MMUCFG_PIDSIZE 0x000007c0 /* PID Reg Size */
+-#define MMUCFG_TWC 0x00008000 /* TLB Write Conditional (v2.0) */
+-#define MMUCFG_LRAT 0x00010000 /* LRAT Supported (v2.0) */
+-#define MMUCFG_RASIZE 0x00fe0000 /* Real Addr Size */
+-#define MMUCFG_LPIDSIZE 0x0f000000 /* LPID Reg Size */
+-
+-/* Bit definitions for MMUCSR0 */
+-#define MMUCSR0_TLB1FI 0x00000002 /* TLB1 Flash invalidate */
+-#define MMUCSR0_TLB0FI 0x00000004 /* TLB0 Flash invalidate */
+-#define MMUCSR0_TLB2FI 0x00000040 /* TLB2 Flash invalidate */
+-#define MMUCSR0_TLB3FI 0x00000020 /* TLB3 Flash invalidate */
+-#define MMUCSR0_TLBFI (MMUCSR0_TLB0FI | MMUCSR0_TLB1FI | \
+- MMUCSR0_TLB2FI | MMUCSR0_TLB3FI)
+-#define MMUCSR0_TLB0PS 0x00000780 /* TLB0 Page Size */
+-#define MMUCSR0_TLB1PS 0x00007800 /* TLB1 Page Size */
+-#define MMUCSR0_TLB2PS 0x00078000 /* TLB2 Page Size */
+-#define MMUCSR0_TLB3PS 0x00780000 /* TLB3 Page Size */
+-
+-/* MMUCFG bits */
+-#define MMUCFG_MAVN_NASK 0x00000003
+-#define MMUCFG_MAVN_V1_0 0x00000000
+-#define MMUCFG_MAVN_V2_0 0x00000001
+-#define MMUCFG_NTLB_MASK 0x0000000c
+-#define MMUCFG_NTLB_SHIFT 2
+-#define MMUCFG_PIDSIZE_MASK 0x000007c0
+-#define MMUCFG_PIDSIZE_SHIFT 6
+-#define MMUCFG_TWC 0x00008000
+-#define MMUCFG_LRAT 0x00010000
+-#define MMUCFG_RASIZE_MASK 0x00fe0000
+-#define MMUCFG_RASIZE_SHIFT 17
+-#define MMUCFG_LPIDSIZE_MASK 0x0f000000
+-#define MMUCFG_LPIDSIZE_SHIFT 24
+-
+-/* TLBnCFG encoding */
+-#define TLBnCFG_N_ENTRY 0x00000fff /* number of entries */
+-#define TLBnCFG_HES 0x00002000 /* HW select supported */
+-#define TLBnCFG_IPROT 0x00008000 /* IPROT supported */
+-#define TLBnCFG_GTWE 0x00010000 /* Guest can write */
+-#define TLBnCFG_IND 0x00020000 /* IND entries supported */
+-#define TLBnCFG_PT 0x00040000 /* Can load from page table */
+-#define TLBnCFG_MINSIZE 0x00f00000 /* Minimum Page Size (v1.0) */
+-#define TLBnCFG_MINSIZE_SHIFT 20
+-#define TLBnCFG_MAXSIZE 0x000f0000 /* Maximum Page Size (v1.0) */
+-#define TLBnCFG_MAXSIZE_SHIFT 16
+-#define TLBnCFG_ASSOC 0xff000000 /* Associativity */
+-#define TLBnCFG_ASSOC_SHIFT 24
+-
+-/* TLBnPS encoding */
+-#define TLBnPS_4K 0x00000004
+-#define TLBnPS_8K 0x00000008
+-#define TLBnPS_16K 0x00000010
+-#define TLBnPS_32K 0x00000020
+-#define TLBnPS_64K 0x00000040
+-#define TLBnPS_128K 0x00000080
+-#define TLBnPS_256K 0x00000100
+-#define TLBnPS_512K 0x00000200
+-#define TLBnPS_1M 0x00000400
+-#define TLBnPS_2M 0x00000800
+-#define TLBnPS_4M 0x00001000
+-#define TLBnPS_8M 0x00002000
+-#define TLBnPS_16M 0x00004000
+-#define TLBnPS_32M 0x00008000
+-#define TLBnPS_64M 0x00010000
+-#define TLBnPS_128M 0x00020000
+-#define TLBnPS_256M 0x00040000
+-#define TLBnPS_512M 0x00080000
+-#define TLBnPS_1G 0x00100000
+-#define TLBnPS_2G 0x00200000
+-#define TLBnPS_4G 0x00400000
+-#define TLBnPS_8G 0x00800000
+-#define TLBnPS_16G 0x01000000
+-#define TLBnPS_32G 0x02000000
+-#define TLBnPS_64G 0x04000000
+-#define TLBnPS_128G 0x08000000
+-#define TLBnPS_256G 0x10000000
+-
+-/* tlbilx action encoding */
+-#define TLBILX_T_ALL 0
+-#define TLBILX_T_TID 1
+-#define TLBILX_T_FULLMATCH 3
+-#define TLBILX_T_CLASS0 4
+-#define TLBILX_T_CLASS1 5
+-#define TLBILX_T_CLASS2 6
+-#define TLBILX_T_CLASS3 7
+-
+-#ifndef __ASSEMBLY__
+-#include <asm/bug.h>
+-
+-extern unsigned int tlbcam_index;
+-
+-typedef struct {
+- unsigned int id;
+- unsigned int active;
+- unsigned long vdso_base;
+-} mm_context_t;
+-
+-/* Page size definitions, common between 32 and 64-bit
+- *
+- * shift : is the "PAGE_SHIFT" value for that page size
+- * penc : is the pte encoding mask
+- *
+- */
+-struct mmu_psize_def
+-{
+- unsigned int shift; /* number of bits */
+- unsigned int enc; /* PTE encoding */
+- unsigned int ind; /* Corresponding indirect page size shift */
+- unsigned int flags;
+-#define MMU_PAGE_SIZE_DIRECT 0x1 /* Supported as a direct size */
+-#define MMU_PAGE_SIZE_INDIRECT 0x2 /* Supported as an indirect size */
+-};
+-extern struct mmu_psize_def mmu_psize_defs[MMU_PAGE_COUNT];
+-
+-static inline int shift_to_mmu_psize(unsigned int shift)
+-{
+- int psize;
+-
+- for (psize = 0; psize < MMU_PAGE_COUNT; ++psize)
+- if (mmu_psize_defs[psize].shift == shift)
+- return psize;
+- return -1;
+-}
+-
+-static inline unsigned int mmu_psize_to_shift(unsigned int mmu_psize)
+-{
+- if (mmu_psize_defs[mmu_psize].shift)
+- return mmu_psize_defs[mmu_psize].shift;
+- BUG();
+-}
+-
+-/* The page sizes use the same names as 64-bit hash but are
+- * constants
+- */
+-#if defined(CONFIG_PPC_4K_PAGES)
+-#define mmu_virtual_psize MMU_PAGE_4K
+-#else
+-#error Unsupported page size
+-#endif
+-
+-extern int mmu_linear_psize;
+-extern int mmu_vmemmap_psize;
+-
+-struct tlb_core_data {
+- /*
+- * Per-core spinlock for e6500 TLB handlers (no tlbsrx.)
+- * Must be the first struct element.
+- */
+- u8 lock;
+-
+- /* For software way selection, as on Freescale TLB1 */
+- u8 esel_next, esel_max, esel_first;
+-};
+-
+-#ifdef CONFIG_PPC64
+-extern unsigned long linear_map_top;
+-extern int book3e_htw_mode;
+-
+-#define PPC_HTW_NONE 0
+-#define PPC_HTW_IBM 1
+-#define PPC_HTW_E6500 2
+-
+-/*
+- * 64-bit booke platforms don't load the tlb in the tlb miss handler code.
+- * HUGETLB_NEED_PRELOAD handles this - it causes huge_ptep_set_access_flags to
+- * return 1, indicating that the tlb requires preloading.
+- */
+-#define HUGETLB_NEED_PRELOAD
+-
+-#define mmu_cleanup_all NULL
+-
+-#endif
+-
+-#endif /* !__ASSEMBLY__ */
+-
+-#endif /* _ASM_POWERPC_MMU_BOOK3E_H_ */
+diff --git a/arch/powerpc/include/asm/mmu.h b/arch/powerpc/include/asm/mmu.h
+index 13ea441ac5319..2b396de45e9ec 100644
+--- a/arch/powerpc/include/asm/mmu.h
++++ b/arch/powerpc/include/asm/mmu.h
+@@ -326,18 +326,8 @@ static inline void mmu_early_init_devtree(void) { }
+ #if defined(CONFIG_PPC_STD_MMU_32)
+ /* 32-bit classic hash table MMU */
+ #include <asm/book3s/32/mmu-hash.h>
+-#elif defined(CONFIG_40x)
+-/* 40x-style software loaded TLB */
+-# include <asm/mmu-40x.h>
+-#elif defined(CONFIG_44x)
+-/* 44x-style software loaded TLB */
+-# include <asm/mmu-44x.h>
+-#elif defined(CONFIG_PPC_BOOK3E_MMU)
+-/* Freescale Book-E software loaded TLB or Book-3e (ISA 2.06+) MMU */
+-# include <asm/mmu-book3e.h>
+-#elif defined (CONFIG_PPC_8xx)
+-/* Motorola/Freescale 8xx software loaded TLB */
+-# include <asm/mmu-8xx.h>
++#elif defined(CONFIG_PPC_MMU_NOHASH)
++#include <asm/nohash/mmu.h>
+ #endif
+
+ #endif /* __KERNEL__ */
+diff --git a/arch/powerpc/include/asm/nohash/32/mmu-40x.h b/arch/powerpc/include/asm/nohash/32/mmu-40x.h
+new file mode 100644
+index 0000000000000..74f4edb5916e4
+--- /dev/null
++++ b/arch/powerpc/include/asm/nohash/32/mmu-40x.h
+@@ -0,0 +1,68 @@
++/* SPDX-License-Identifier: GPL-2.0 */
++#ifndef _ASM_POWERPC_MMU_40X_H_
++#define _ASM_POWERPC_MMU_40X_H_
++
++/*
++ * PPC40x support
++ */
++
++#define PPC40X_TLB_SIZE 64
++
++/*
++ * TLB entries are defined by a "high" tag portion and a "low" data
++ * portion. On all architectures, the data portion is 32-bits.
++ *
++ * TLB entries are managed entirely under software control by reading,
++ * writing, and searchoing using the 4xx-specific tlbre, tlbwr, and tlbsx
++ * instructions.
++ */
++
++#define TLB_LO 1
++#define TLB_HI 0
++
++#define TLB_DATA TLB_LO
++#define TLB_TAG TLB_HI
++
++/* Tag portion */
++
++#define TLB_EPN_MASK 0xFFFFFC00 /* Effective Page Number */
++#define TLB_PAGESZ_MASK 0x00000380
++#define TLB_PAGESZ(x) (((x) & 0x7) << 7)
++#define PAGESZ_1K 0
++#define PAGESZ_4K 1
++#define PAGESZ_16K 2
++#define PAGESZ_64K 3
++#define PAGESZ_256K 4
++#define PAGESZ_1M 5
++#define PAGESZ_4M 6
++#define PAGESZ_16M 7
++#define TLB_VALID 0x00000040 /* Entry is valid */
++
++/* Data portion */
++
++#define TLB_RPN_MASK 0xFFFFFC00 /* Real Page Number */
++#define TLB_PERM_MASK 0x00000300
++#define TLB_EX 0x00000200 /* Instruction execution allowed */
++#define TLB_WR 0x00000100 /* Writes permitted */
++#define TLB_ZSEL_MASK 0x000000F0
++#define TLB_ZSEL(x) (((x) & 0xF) << 4)
++#define TLB_ATTR_MASK 0x0000000F
++#define TLB_W 0x00000008 /* Caching is write-through */
++#define TLB_I 0x00000004 /* Caching is inhibited */
++#define TLB_M 0x00000002 /* Memory is coherent */
++#define TLB_G 0x00000001 /* Memory is guarded from prefetch */
++
++#ifndef __ASSEMBLY__
++
++typedef struct {
++ unsigned int id;
++ unsigned int active;
++ unsigned long vdso_base;
++} mm_context_t;
++
++#endif /* !__ASSEMBLY__ */
++
++#define mmu_virtual_psize MMU_PAGE_4K
++#define mmu_linear_psize MMU_PAGE_256M
++
++#endif /* _ASM_POWERPC_MMU_40X_H_ */
+diff --git a/arch/powerpc/include/asm/nohash/32/mmu-44x.h b/arch/powerpc/include/asm/nohash/32/mmu-44x.h
+new file mode 100644
+index 0000000000000..295b3dbb2698b
+--- /dev/null
++++ b/arch/powerpc/include/asm/nohash/32/mmu-44x.h
+@@ -0,0 +1,153 @@
++/* SPDX-License-Identifier: GPL-2.0 */
++#ifndef _ASM_POWERPC_MMU_44X_H_
++#define _ASM_POWERPC_MMU_44X_H_
++/*
++ * PPC440 support
++ */
++
++#include <asm/asm-const.h>
++
++#define PPC44x_MMUCR_TID 0x000000ff
++#define PPC44x_MMUCR_STS 0x00010000
++
++#define PPC44x_TLB_PAGEID 0
++#define PPC44x_TLB_XLAT 1
++#define PPC44x_TLB_ATTRIB 2
++
++/* Page identification fields */
++#define PPC44x_TLB_EPN_MASK 0xfffffc00 /* Effective Page Number */
++#define PPC44x_TLB_VALID 0x00000200 /* Valid flag */
++#define PPC44x_TLB_TS 0x00000100 /* Translation address space */
++#define PPC44x_TLB_1K 0x00000000 /* Page sizes */
++#define PPC44x_TLB_4K 0x00000010
++#define PPC44x_TLB_16K 0x00000020
++#define PPC44x_TLB_64K 0x00000030
++#define PPC44x_TLB_256K 0x00000040
++#define PPC44x_TLB_1M 0x00000050
++#define PPC44x_TLB_16M 0x00000070
++#define PPC44x_TLB_256M 0x00000090
++
++/* Translation fields */
++#define PPC44x_TLB_RPN_MASK 0xfffffc00 /* Real Page Number */
++#define PPC44x_TLB_ERPN_MASK 0x0000000f
++
++/* Storage attribute and access control fields */
++#define PPC44x_TLB_ATTR_MASK 0x0000ff80
++#define PPC44x_TLB_U0 0x00008000 /* User 0 */
++#define PPC44x_TLB_U1 0x00004000 /* User 1 */
++#define PPC44x_TLB_U2 0x00002000 /* User 2 */
++#define PPC44x_TLB_U3 0x00001000 /* User 3 */
++#define PPC44x_TLB_W 0x00000800 /* Caching is write-through */
++#define PPC44x_TLB_I 0x00000400 /* Caching is inhibited */
++#define PPC44x_TLB_M 0x00000200 /* Memory is coherent */
++#define PPC44x_TLB_G 0x00000100 /* Memory is guarded */
++#define PPC44x_TLB_E 0x00000080 /* Memory is little endian */
++
++#define PPC44x_TLB_PERM_MASK 0x0000003f
++#define PPC44x_TLB_UX 0x00000020 /* User execution */
++#define PPC44x_TLB_UW 0x00000010 /* User write */
++#define PPC44x_TLB_UR 0x00000008 /* User read */
++#define PPC44x_TLB_SX 0x00000004 /* Super execution */
++#define PPC44x_TLB_SW 0x00000002 /* Super write */
++#define PPC44x_TLB_SR 0x00000001 /* Super read */
++
++/* Number of TLB entries */
++#define PPC44x_TLB_SIZE 64
++
++/* 47x bits */
++#define PPC47x_MMUCR_TID 0x0000ffff
++#define PPC47x_MMUCR_STS 0x00010000
++
++/* Page identification fields */
++#define PPC47x_TLB0_EPN_MASK 0xfffff000 /* Effective Page Number */
++#define PPC47x_TLB0_VALID 0x00000800 /* Valid flag */
++#define PPC47x_TLB0_TS 0x00000400 /* Translation address space */
++#define PPC47x_TLB0_4K 0x00000000
++#define PPC47x_TLB0_16K 0x00000010
++#define PPC47x_TLB0_64K 0x00000030
++#define PPC47x_TLB0_1M 0x00000070
++#define PPC47x_TLB0_16M 0x000000f0
++#define PPC47x_TLB0_256M 0x000001f0
++#define PPC47x_TLB0_1G 0x000003f0
++#define PPC47x_TLB0_BOLTED_R 0x00000008 /* tlbre only */
++
++/* Translation fields */
++#define PPC47x_TLB1_RPN_MASK 0xfffff000 /* Real Page Number */
++#define PPC47x_TLB1_ERPN_MASK 0x000003ff
++
++/* Storage attribute and access control fields */
++#define PPC47x_TLB2_ATTR_MASK 0x0003ff80
++#define PPC47x_TLB2_IL1I 0x00020000 /* Memory is guarded */
++#define PPC47x_TLB2_IL1D 0x00010000 /* Memory is guarded */
++#define PPC47x_TLB2_U0 0x00008000 /* User 0 */
++#define PPC47x_TLB2_U1 0x00004000 /* User 1 */
++#define PPC47x_TLB2_U2 0x00002000 /* User 2 */
++#define PPC47x_TLB2_U3 0x00001000 /* User 3 */
++#define PPC47x_TLB2_W 0x00000800 /* Caching is write-through */
++#define PPC47x_TLB2_I 0x00000400 /* Caching is inhibited */
++#define PPC47x_TLB2_M 0x00000200 /* Memory is coherent */
++#define PPC47x_TLB2_G 0x00000100 /* Memory is guarded */
++#define PPC47x_TLB2_E 0x00000080 /* Memory is little endian */
++#define PPC47x_TLB2_PERM_MASK 0x0000003f
++#define PPC47x_TLB2_UX 0x00000020 /* User execution */
++#define PPC47x_TLB2_UW 0x00000010 /* User write */
++#define PPC47x_TLB2_UR 0x00000008 /* User read */
++#define PPC47x_TLB2_SX 0x00000004 /* Super execution */
++#define PPC47x_TLB2_SW 0x00000002 /* Super write */
++#define PPC47x_TLB2_SR 0x00000001 /* Super read */
++#define PPC47x_TLB2_U_RWX (PPC47x_TLB2_UX|PPC47x_TLB2_UW|PPC47x_TLB2_UR)
++#define PPC47x_TLB2_S_RWX (PPC47x_TLB2_SX|PPC47x_TLB2_SW|PPC47x_TLB2_SR)
++#define PPC47x_TLB2_S_RW (PPC47x_TLB2_SW | PPC47x_TLB2_SR)
++#define PPC47x_TLB2_IMG (PPC47x_TLB2_I | PPC47x_TLB2_M | PPC47x_TLB2_G)
++
++#ifndef __ASSEMBLY__
++
++extern unsigned int tlb_44x_hwater;
++extern unsigned int tlb_44x_index;
++
++typedef struct {
++ unsigned int id;
++ unsigned int active;
++ unsigned long vdso_base;
++} mm_context_t;
++
++#endif /* !__ASSEMBLY__ */
++
++#ifndef CONFIG_PPC_EARLY_DEBUG_44x
++#define PPC44x_EARLY_TLBS 1
++#else
++#define PPC44x_EARLY_TLBS 2
++#define PPC44x_EARLY_DEBUG_VIRTADDR (ASM_CONST(0xf0000000) \
++ | (ASM_CONST(CONFIG_PPC_EARLY_DEBUG_44x_PHYSLOW) & 0xffff))
++#endif
++
++/* Size of the TLBs used for pinning in lowmem */
++#define PPC_PIN_SIZE (1 << 28) /* 256M */
++
++#if defined(CONFIG_PPC_4K_PAGES)
++#define PPC44x_TLBE_SIZE PPC44x_TLB_4K
++#define PPC47x_TLBE_SIZE PPC47x_TLB0_4K
++#define mmu_virtual_psize MMU_PAGE_4K
++#elif defined(CONFIG_PPC_16K_PAGES)
++#define PPC44x_TLBE_SIZE PPC44x_TLB_16K
++#define PPC47x_TLBE_SIZE PPC47x_TLB0_16K
++#define mmu_virtual_psize MMU_PAGE_16K
++#elif defined(CONFIG_PPC_64K_PAGES)
++#define PPC44x_TLBE_SIZE PPC44x_TLB_64K
++#define PPC47x_TLBE_SIZE PPC47x_TLB0_64K
++#define mmu_virtual_psize MMU_PAGE_64K
++#elif defined(CONFIG_PPC_256K_PAGES)
++#define PPC44x_TLBE_SIZE PPC44x_TLB_256K
++#define mmu_virtual_psize MMU_PAGE_256K
++#else
++#error "Unsupported PAGE_SIZE"
++#endif
++
++#define mmu_linear_psize MMU_PAGE_256M
++
++#define PPC44x_PGD_OFF_SHIFT (32 - PGDIR_SHIFT + PGD_T_LOG2)
++#define PPC44x_PGD_OFF_MASK_BIT (PGDIR_SHIFT - PGD_T_LOG2)
++#define PPC44x_PTE_ADD_SHIFT (32 - PGDIR_SHIFT + PTE_SHIFT + PTE_T_LOG2)
++#define PPC44x_PTE_ADD_MASK_BIT (32 - PTE_T_LOG2 - PTE_SHIFT)
++
++#endif /* _ASM_POWERPC_MMU_44X_H_ */
+diff --git a/arch/powerpc/include/asm/nohash/32/mmu-8xx.h b/arch/powerpc/include/asm/nohash/32/mmu-8xx.h
+new file mode 100644
+index 0000000000000..193f53116c7ae
+--- /dev/null
++++ b/arch/powerpc/include/asm/nohash/32/mmu-8xx.h
+@@ -0,0 +1,244 @@
++/* SPDX-License-Identifier: GPL-2.0 */
++#ifndef _ASM_POWERPC_MMU_8XX_H_
++#define _ASM_POWERPC_MMU_8XX_H_
++/*
++ * PPC8xx support
++ */
++
++/* Control/status registers for the MPC8xx.
++ * A write operation to these registers causes serialized access.
++ * During software tablewalk, the registers used perform mask/shift-add
++ * operations when written/read. A TLB entry is created when the Mx_RPN
++ * is written, and the contents of several registers are used to
++ * create the entry.
++ */
++#define SPRN_MI_CTR 784 /* Instruction TLB control register */
++#define MI_GPM 0x80000000 /* Set domain manager mode */
++#define MI_PPM 0x40000000 /* Set subpage protection */
++#define MI_CIDEF 0x20000000 /* Set cache inhibit when MMU dis */
++#define MI_RSV4I 0x08000000 /* Reserve 4 TLB entries */
++#define MI_PPCS 0x02000000 /* Use MI_RPN prob/priv state */
++#define MI_IDXMASK 0x00001f00 /* TLB index to be loaded */
++#define MI_RESETVAL 0x00000000 /* Value of register at reset */
++
++/* These are the Ks and Kp from the PowerPC books. For proper operation,
++ * Ks = 0, Kp = 1.
++ */
++#define SPRN_MI_AP 786
++#define MI_Ks 0x80000000 /* Should not be set */
++#define MI_Kp 0x40000000 /* Should always be set */
++
++/*
++ * All pages' PP data bits are set to either 001 or 011 by copying _PAGE_EXEC
++ * into bit 21 in the ITLBmiss handler (bit 21 is the middle bit), which means
++ * respectively NA for All or X for Supervisor and no access for User.
++ * Then we use the APG to say whether accesses are according to Page rules or
++ * "all Supervisor" rules (Access to all)
++ * Therefore, we define 2 APG groups. lsb is _PMD_USER
++ * 0 => No user => 01 (all accesses performed according to page definition)
++ * 1 => User => 00 (all accesses performed as supervisor iaw page definition)
++ * We define all 16 groups so that all other bits of APG can take any value
++ */
++#define MI_APG_INIT 0x44444444
++
++/* The effective page number register. When read, contains the information
++ * about the last instruction TLB miss. When MI_RPN is written, bits in
++ * this register are used to create the TLB entry.
++ */
++#define SPRN_MI_EPN 787
++#define MI_EPNMASK 0xfffff000 /* Effective page number for entry */
++#define MI_EVALID 0x00000200 /* Entry is valid */
++#define MI_ASIDMASK 0x0000000f /* ASID match value */
++ /* Reset value is undefined */
++
++/* A "level 1" or "segment" or whatever you want to call it register.
++ * For the instruction TLB, it contains bits that get loaded into the
++ * TLB entry when the MI_RPN is written.
++ */
++#define SPRN_MI_TWC 789
++#define MI_APG 0x000001e0 /* Access protection group (0) */
++#define MI_GUARDED 0x00000010 /* Guarded storage */
++#define MI_PSMASK 0x0000000c /* Mask of page size bits */
++#define MI_PS8MEG 0x0000000c /* 8M page size */
++#define MI_PS512K 0x00000004 /* 512K page size */
++#define MI_PS4K_16K 0x00000000 /* 4K or 16K page size */
++#define MI_SVALID 0x00000001 /* Segment entry is valid */
++ /* Reset value is undefined */
++
++/* Real page number. Defined by the pte. Writing this register
++ * causes a TLB entry to be created for the instruction TLB, using
++ * additional information from the MI_EPN, and MI_TWC registers.
++ */
++#define SPRN_MI_RPN 790
++#define MI_SPS16K 0x00000008 /* Small page size (0 = 4k, 1 = 16k) */
++
++/* Define an RPN value for mapping kernel memory to large virtual
++ * pages for boot initialization. This has real page number of 0,
++ * large page size, shared page, cache enabled, and valid.
++ * Also mark all subpages valid and write access.
++ */
++#define MI_BOOTINIT 0x000001fd
++
++#define SPRN_MD_CTR 792 /* Data TLB control register */
++#define MD_GPM 0x80000000 /* Set domain manager mode */
++#define MD_PPM 0x40000000 /* Set subpage protection */
++#define MD_CIDEF 0x20000000 /* Set cache inhibit when MMU dis */
++#define MD_WTDEF 0x10000000 /* Set writethrough when MMU dis */
++#define MD_RSV4I 0x08000000 /* Reserve 4 TLB entries */
++#define MD_TWAM 0x04000000 /* Use 4K page hardware assist */
++#define MD_PPCS 0x02000000 /* Use MI_RPN prob/priv state */
++#define MD_IDXMASK 0x00001f00 /* TLB index to be loaded */
++#define MD_RESETVAL 0x04000000 /* Value of register at reset */
++
++#define SPRN_M_CASID 793 /* Address space ID (context) to match */
++#define MC_ASIDMASK 0x0000000f /* Bits used for ASID value */
++
++
++/* These are the Ks and Kp from the PowerPC books. For proper operation,
++ * Ks = 0, Kp = 1.
++ */
++#define SPRN_MD_AP 794
++#define MD_Ks 0x80000000 /* Should not be set */
++#define MD_Kp 0x40000000 /* Should always be set */
++
++/*
++ * All pages' PP data bits are set to either 000 or 011 or 001, which means
++ * respectively RW for Supervisor and no access for User, or RO for
++ * Supervisor and no access for user and NA for ALL.
++ * Then we use the APG to say whether accesses are according to Page rules or
++ * "all Supervisor" rules (Access to all)
++ * Therefore, we define 2 APG groups. lsb is _PMD_USER
++ * 0 => No user => 01 (all accesses performed according to page definition)
++ * 1 => User => 00 (all accesses performed as supervisor iaw page definition)
++ * We define all 16 groups so that all other bits of APG can take any value
++ */
++#define MD_APG_INIT 0x44444444
++
++/* The effective page number register. When read, contains the information
++ * about the last instruction TLB miss. When MD_RPN is written, bits in
++ * this register are used to create the TLB entry.
++ */
++#define SPRN_MD_EPN 795
++#define MD_EPNMASK 0xfffff000 /* Effective page number for entry */
++#define MD_EVALID 0x00000200 /* Entry is valid */
++#define MD_ASIDMASK 0x0000000f /* ASID match value */
++ /* Reset value is undefined */
++
++/* The pointer to the base address of the first level page table.
++ * During a software tablewalk, reading this register provides the address
++ * of the entry associated with MD_EPN.
++ */
++#define SPRN_M_TWB 796
++#define M_L1TB 0xfffff000 /* Level 1 table base address */
++#define M_L1INDX 0x00000ffc /* Level 1 index, when read */
++ /* Reset value is undefined */
++
++/* A "level 1" or "segment" or whatever you want to call it register.
++ * For the data TLB, it contains bits that get loaded into the TLB entry
++ * when the MD_RPN is written. It is also provides the hardware assist
++ * for finding the PTE address during software tablewalk.
++ */
++#define SPRN_MD_TWC 797
++#define MD_L2TB 0xfffff000 /* Level 2 table base address */
++#define MD_L2INDX 0xfffffe00 /* Level 2 index (*pte), when read */
++#define MD_APG 0x000001e0 /* Access protection group (0) */
++#define MD_GUARDED 0x00000010 /* Guarded storage */
++#define MD_PSMASK 0x0000000c /* Mask of page size bits */
++#define MD_PS8MEG 0x0000000c /* 8M page size */
++#define MD_PS512K 0x00000004 /* 512K page size */
++#define MD_PS4K_16K 0x00000000 /* 4K or 16K page size */
++#define MD_WT 0x00000002 /* Use writethrough page attribute */
++#define MD_SVALID 0x00000001 /* Segment entry is valid */
++ /* Reset value is undefined */
++
++
++/* Real page number. Defined by the pte. Writing this register
++ * causes a TLB entry to be created for the data TLB, using
++ * additional information from the MD_EPN, and MD_TWC registers.
++ */
++#define SPRN_MD_RPN 798
++#define MD_SPS16K 0x00000008 /* Small page size (0 = 4k, 1 = 16k) */
++
++/* This is a temporary storage register that could be used to save
++ * a processor working register during a tablewalk.
++ */
++#define SPRN_M_TW 799
++
++#ifdef CONFIG_PPC_MM_SLICES
++#include <asm/nohash/32/slice.h>
++#define SLICE_ARRAY_SIZE (1 << (32 - SLICE_LOW_SHIFT - 1))
++#endif
++
++#ifndef __ASSEMBLY__
++struct slice_mask {
++ u64 low_slices;
++ DECLARE_BITMAP(high_slices, 0);
++};
++
++typedef struct {
++ unsigned int id;
++ unsigned int active;
++ unsigned long vdso_base;
++#ifdef CONFIG_PPC_MM_SLICES
++ u16 user_psize; /* page size index */
++ unsigned char low_slices_psize[SLICE_ARRAY_SIZE];
++ unsigned char high_slices_psize[0];
++ unsigned long slb_addr_limit;
++ struct slice_mask mask_base_psize; /* 4k or 16k */
++# ifdef CONFIG_HUGETLB_PAGE
++ struct slice_mask mask_512k;
++ struct slice_mask mask_8m;
++# endif
++#endif
++} mm_context_t;
++
++#define PHYS_IMMR_BASE (mfspr(SPRN_IMMR) & 0xfff80000)
++#define VIRT_IMMR_BASE (__fix_to_virt(FIX_IMMR_BASE))
++
++/* Page size definitions, common between 32 and 64-bit
++ *
++ * shift : is the "PAGE_SHIFT" value for that page size
++ * penc : is the pte encoding mask
++ *
++ */
++struct mmu_psize_def {
++ unsigned int shift; /* number of bits */
++ unsigned int enc; /* PTE encoding */
++ unsigned int ind; /* Corresponding indirect page size shift */
++ unsigned int flags;
++#define MMU_PAGE_SIZE_DIRECT 0x1 /* Supported as a direct size */
++#define MMU_PAGE_SIZE_INDIRECT 0x2 /* Supported as an indirect size */
++};
++
++extern struct mmu_psize_def mmu_psize_defs[MMU_PAGE_COUNT];
++
++static inline int shift_to_mmu_psize(unsigned int shift)
++{
++ int psize;
++
++ for (psize = 0; psize < MMU_PAGE_COUNT; ++psize)
++ if (mmu_psize_defs[psize].shift == shift)
++ return psize;
++ return -1;
++}
++
++static inline unsigned int mmu_psize_to_shift(unsigned int mmu_psize)
++{
++ if (mmu_psize_defs[mmu_psize].shift)
++ return mmu_psize_defs[mmu_psize].shift;
++ BUG();
++}
++
++#endif /* !__ASSEMBLY__ */
++
++#if defined(CONFIG_PPC_4K_PAGES)
++#define mmu_virtual_psize MMU_PAGE_4K
++#elif defined(CONFIG_PPC_16K_PAGES)
++#define mmu_virtual_psize MMU_PAGE_16K
++#else
++#error "Unsupported PAGE_SIZE"
++#endif
++
++#define mmu_linear_psize MMU_PAGE_8M
++
++#endif /* _ASM_POWERPC_MMU_8XX_H_ */
+diff --git a/arch/powerpc/include/asm/nohash/32/mmu.h b/arch/powerpc/include/asm/nohash/32/mmu.h
+new file mode 100644
+index 0000000000000..f61f933a4cd8c
+--- /dev/null
++++ b/arch/powerpc/include/asm/nohash/32/mmu.h
+@@ -0,0 +1,23 @@
++/* SPDX-License-Identifier: GPL-2.0 */
++#ifndef _ASM_POWERPC_NOHASH_32_MMU_H_
++#define _ASM_POWERPC_NOHASH_32_MMU_H_
++
++#if defined(CONFIG_40x)
++/* 40x-style software loaded TLB */
++#include <asm/nohash/32/mmu-40x.h>
++#elif defined(CONFIG_44x)
++/* 44x-style software loaded TLB */
++#include <asm/nohash/32/mmu-44x.h>
++#elif defined(CONFIG_PPC_BOOK3E_MMU)
++/* Freescale Book-E software loaded TLB or Book-3e (ISA 2.06+) MMU */
++#include <asm/nohash/mmu-book3e.h>
++#elif defined (CONFIG_PPC_8xx)
++/* Motorola/Freescale 8xx software loaded TLB */
++#include <asm/nohash/32/mmu-8xx.h>
++#endif
++
++#ifndef __ASSEMBLY__
++typedef struct page *pgtable_t;
++#endif
++
++#endif /* _ASM_POWERPC_NOHASH_32_MMU_H_ */
+diff --git a/arch/powerpc/include/asm/nohash/64/mmu.h b/arch/powerpc/include/asm/nohash/64/mmu.h
+new file mode 100644
+index 0000000000000..e6585480dfc40
+--- /dev/null
++++ b/arch/powerpc/include/asm/nohash/64/mmu.h
+@@ -0,0 +1,12 @@
++/* SPDX-License-Identifier: GPL-2.0 */
++#ifndef _ASM_POWERPC_NOHASH_64_MMU_H_
++#define _ASM_POWERPC_NOHASH_64_MMU_H_
++
++/* Freescale Book-E software loaded TLB or Book-3e (ISA 2.06+) MMU */
++#include <asm/nohash/mmu-book3e.h>
++
++#ifndef __ASSEMBLY__
++typedef struct page *pgtable_t;
++#endif
++
++#endif /* _ASM_POWERPC_NOHASH_64_MMU_H_ */
+diff --git a/arch/powerpc/include/asm/nohash/mmu-book3e.h b/arch/powerpc/include/asm/nohash/mmu-book3e.h
+new file mode 100644
+index 0000000000000..e20072972e359
+--- /dev/null
++++ b/arch/powerpc/include/asm/nohash/mmu-book3e.h
+@@ -0,0 +1,313 @@
++/* SPDX-License-Identifier: GPL-2.0 */
++#ifndef _ASM_POWERPC_MMU_BOOK3E_H_
++#define _ASM_POWERPC_MMU_BOOK3E_H_
++/*
++ * Freescale Book-E/Book-3e (ISA 2.06+) MMU support
++ */
++
++/* Book-3e defined page sizes */
++#define BOOK3E_PAGESZ_1K 0
++#define BOOK3E_PAGESZ_2K 1
++#define BOOK3E_PAGESZ_4K 2
++#define BOOK3E_PAGESZ_8K 3
++#define BOOK3E_PAGESZ_16K 4
++#define BOOK3E_PAGESZ_32K 5
++#define BOOK3E_PAGESZ_64K 6
++#define BOOK3E_PAGESZ_128K 7
++#define BOOK3E_PAGESZ_256K 8
++#define BOOK3E_PAGESZ_512K 9
++#define BOOK3E_PAGESZ_1M 10
++#define BOOK3E_PAGESZ_2M 11
++#define BOOK3E_PAGESZ_4M 12
++#define BOOK3E_PAGESZ_8M 13
++#define BOOK3E_PAGESZ_16M 14
++#define BOOK3E_PAGESZ_32M 15
++#define BOOK3E_PAGESZ_64M 16
++#define BOOK3E_PAGESZ_128M 17
++#define BOOK3E_PAGESZ_256M 18
++#define BOOK3E_PAGESZ_512M 19
++#define BOOK3E_PAGESZ_1GB 20
++#define BOOK3E_PAGESZ_2GB 21
++#define BOOK3E_PAGESZ_4GB 22
++#define BOOK3E_PAGESZ_8GB 23
++#define BOOK3E_PAGESZ_16GB 24
++#define BOOK3E_PAGESZ_32GB 25
++#define BOOK3E_PAGESZ_64GB 26
++#define BOOK3E_PAGESZ_128GB 27
++#define BOOK3E_PAGESZ_256GB 28
++#define BOOK3E_PAGESZ_512GB 29
++#define BOOK3E_PAGESZ_1TB 30
++#define BOOK3E_PAGESZ_2TB 31
++
++/* MAS registers bit definitions */
++
++#define MAS0_TLBSEL_MASK 0x30000000
++#define MAS0_TLBSEL_SHIFT 28
++#define MAS0_TLBSEL(x) (((x) << MAS0_TLBSEL_SHIFT) & MAS0_TLBSEL_MASK)
++#define MAS0_GET_TLBSEL(mas0) (((mas0) & MAS0_TLBSEL_MASK) >> \
++ MAS0_TLBSEL_SHIFT)
++#define MAS0_ESEL_MASK 0x0FFF0000
++#define MAS0_ESEL_SHIFT 16
++#define MAS0_ESEL(x) (((x) << MAS0_ESEL_SHIFT) & MAS0_ESEL_MASK)
++#define MAS0_NV(x) ((x) & 0x00000FFF)
++#define MAS0_HES 0x00004000
++#define MAS0_WQ_ALLWAYS 0x00000000
++#define MAS0_WQ_COND 0x00001000
++#define MAS0_WQ_CLR_RSRV 0x00002000
++
++#define MAS1_VALID 0x80000000
++#define MAS1_IPROT 0x40000000
++#define MAS1_TID(x) (((x) << 16) & 0x3FFF0000)
++#define MAS1_IND 0x00002000
++#define MAS1_TS 0x00001000
++#define MAS1_TSIZE_MASK 0x00000f80
++#define MAS1_TSIZE_SHIFT 7
++#define MAS1_TSIZE(x) (((x) << MAS1_TSIZE_SHIFT) & MAS1_TSIZE_MASK)
++#define MAS1_GET_TSIZE(mas1) (((mas1) & MAS1_TSIZE_MASK) >> MAS1_TSIZE_SHIFT)
++
++#define MAS2_EPN (~0xFFFUL)
++#define MAS2_X0 0x00000040
++#define MAS2_X1 0x00000020
++#define MAS2_W 0x00000010
++#define MAS2_I 0x00000008
++#define MAS2_M 0x00000004
++#define MAS2_G 0x00000002
++#define MAS2_E 0x00000001
++#define MAS2_WIMGE_MASK 0x0000001f
++#define MAS2_EPN_MASK(size) (~0 << (size + 10))
++#define MAS2_VAL(addr, size, flags) ((addr) & MAS2_EPN_MASK(size) | (flags))
++
++#define MAS3_RPN 0xFFFFF000
++#define MAS3_U0 0x00000200
++#define MAS3_U1 0x00000100
++#define MAS3_U2 0x00000080
++#define MAS3_U3 0x00000040
++#define MAS3_UX 0x00000020
++#define MAS3_SX 0x00000010
++#define MAS3_UW 0x00000008
++#define MAS3_SW 0x00000004
++#define MAS3_UR 0x00000002
++#define MAS3_SR 0x00000001
++#define MAS3_BAP_MASK 0x0000003f
++#define MAS3_SPSIZE 0x0000003e
++#define MAS3_SPSIZE_SHIFT 1
++
++#define MAS4_TLBSEL_MASK MAS0_TLBSEL_MASK
++#define MAS4_TLBSELD(x) MAS0_TLBSEL(x)
++#define MAS4_INDD 0x00008000 /* Default IND */
++#define MAS4_TSIZED(x) MAS1_TSIZE(x)
++#define MAS4_X0D 0x00000040
++#define MAS4_X1D 0x00000020
++#define MAS4_WD 0x00000010
++#define MAS4_ID 0x00000008
++#define MAS4_MD 0x00000004
++#define MAS4_GD 0x00000002
++#define MAS4_ED 0x00000001
++#define MAS4_WIMGED_MASK 0x0000001f /* Default WIMGE */
++#define MAS4_WIMGED_SHIFT 0
++#define MAS4_VLED MAS4_X1D /* Default VLE */
++#define MAS4_ACMD 0x000000c0 /* Default ACM */
++#define MAS4_ACMD_SHIFT 6
++#define MAS4_TSIZED_MASK 0x00000f80 /* Default TSIZE */
++#define MAS4_TSIZED_SHIFT 7
++
++#define MAS5_SGS 0x80000000
++
++#define MAS6_SPID0 0x3FFF0000
++#define MAS6_SPID1 0x00007FFE
++#define MAS6_ISIZE(x) MAS1_TSIZE(x)
++#define MAS6_SAS 0x00000001
++#define MAS6_SPID MAS6_SPID0
++#define MAS6_SIND 0x00000002 /* Indirect page */
++#define MAS6_SIND_SHIFT 1
++#define MAS6_SPID_MASK 0x3fff0000
++#define MAS6_SPID_SHIFT 16
++#define MAS6_ISIZE_MASK 0x00000f80
++#define MAS6_ISIZE_SHIFT 7
++
++#define MAS7_RPN 0xFFFFFFFF
++
++#define MAS8_TGS 0x80000000 /* Guest space */
++#define MAS8_VF 0x40000000 /* Virtualization Fault */
++#define MAS8_TLPID 0x000000ff
++
++/* Bit definitions for MMUCFG */
++#define MMUCFG_MAVN 0x00000003 /* MMU Architecture Version Number */
++#define MMUCFG_MAVN_V1 0x00000000 /* v1.0 */
++#define MMUCFG_MAVN_V2 0x00000001 /* v2.0 */
++#define MMUCFG_NTLBS 0x0000000c /* Number of TLBs */
++#define MMUCFG_PIDSIZE 0x000007c0 /* PID Reg Size */
++#define MMUCFG_TWC 0x00008000 /* TLB Write Conditional (v2.0) */
++#define MMUCFG_LRAT 0x00010000 /* LRAT Supported (v2.0) */
++#define MMUCFG_RASIZE 0x00fe0000 /* Real Addr Size */
++#define MMUCFG_LPIDSIZE 0x0f000000 /* LPID Reg Size */
++
++/* Bit definitions for MMUCSR0 */
++#define MMUCSR0_TLB1FI 0x00000002 /* TLB1 Flash invalidate */
++#define MMUCSR0_TLB0FI 0x00000004 /* TLB0 Flash invalidate */
++#define MMUCSR0_TLB2FI 0x00000040 /* TLB2 Flash invalidate */
++#define MMUCSR0_TLB3FI 0x00000020 /* TLB3 Flash invalidate */
++#define MMUCSR0_TLBFI (MMUCSR0_TLB0FI | MMUCSR0_TLB1FI | \
++ MMUCSR0_TLB2FI | MMUCSR0_TLB3FI)
++#define MMUCSR0_TLB0PS 0x00000780 /* TLB0 Page Size */
++#define MMUCSR0_TLB1PS 0x00007800 /* TLB1 Page Size */
++#define MMUCSR0_TLB2PS 0x00078000 /* TLB2 Page Size */
++#define MMUCSR0_TLB3PS 0x00780000 /* TLB3 Page Size */
++
++/* MMUCFG bits */
++#define MMUCFG_MAVN_NASK 0x00000003
++#define MMUCFG_MAVN_V1_0 0x00000000
++#define MMUCFG_MAVN_V2_0 0x00000001
++#define MMUCFG_NTLB_MASK 0x0000000c
++#define MMUCFG_NTLB_SHIFT 2
++#define MMUCFG_PIDSIZE_MASK 0x000007c0
++#define MMUCFG_PIDSIZE_SHIFT 6
++#define MMUCFG_TWC 0x00008000
++#define MMUCFG_LRAT 0x00010000
++#define MMUCFG_RASIZE_MASK 0x00fe0000
++#define MMUCFG_RASIZE_SHIFT 17
++#define MMUCFG_LPIDSIZE_MASK 0x0f000000
++#define MMUCFG_LPIDSIZE_SHIFT 24
++
++/* TLBnCFG encoding */
++#define TLBnCFG_N_ENTRY 0x00000fff /* number of entries */
++#define TLBnCFG_HES 0x00002000 /* HW select supported */
++#define TLBnCFG_IPROT 0x00008000 /* IPROT supported */
++#define TLBnCFG_GTWE 0x00010000 /* Guest can write */
++#define TLBnCFG_IND 0x00020000 /* IND entries supported */
++#define TLBnCFG_PT 0x00040000 /* Can load from page table */
++#define TLBnCFG_MINSIZE 0x00f00000 /* Minimum Page Size (v1.0) */
++#define TLBnCFG_MINSIZE_SHIFT 20
++#define TLBnCFG_MAXSIZE 0x000f0000 /* Maximum Page Size (v1.0) */
++#define TLBnCFG_MAXSIZE_SHIFT 16
++#define TLBnCFG_ASSOC 0xff000000 /* Associativity */
++#define TLBnCFG_ASSOC_SHIFT 24
++
++/* TLBnPS encoding */
++#define TLBnPS_4K 0x00000004
++#define TLBnPS_8K 0x00000008
++#define TLBnPS_16K 0x00000010
++#define TLBnPS_32K 0x00000020
++#define TLBnPS_64K 0x00000040
++#define TLBnPS_128K 0x00000080
++#define TLBnPS_256K 0x00000100
++#define TLBnPS_512K 0x00000200
++#define TLBnPS_1M 0x00000400
++#define TLBnPS_2M 0x00000800
++#define TLBnPS_4M 0x00001000
++#define TLBnPS_8M 0x00002000
++#define TLBnPS_16M 0x00004000
++#define TLBnPS_32M 0x00008000
++#define TLBnPS_64M 0x00010000
++#define TLBnPS_128M 0x00020000
++#define TLBnPS_256M 0x00040000
++#define TLBnPS_512M 0x00080000
++#define TLBnPS_1G 0x00100000
++#define TLBnPS_2G 0x00200000
++#define TLBnPS_4G 0x00400000
++#define TLBnPS_8G 0x00800000
++#define TLBnPS_16G 0x01000000
++#define TLBnPS_32G 0x02000000
++#define TLBnPS_64G 0x04000000
++#define TLBnPS_128G 0x08000000
++#define TLBnPS_256G 0x10000000
++
++/* tlbilx action encoding */
++#define TLBILX_T_ALL 0
++#define TLBILX_T_TID 1
++#define TLBILX_T_FULLMATCH 3
++#define TLBILX_T_CLASS0 4
++#define TLBILX_T_CLASS1 5
++#define TLBILX_T_CLASS2 6
++#define TLBILX_T_CLASS3 7
++
++#ifndef __ASSEMBLY__
++#include <asm/bug.h>
++
++extern unsigned int tlbcam_index;
++
++typedef struct {
++ unsigned int id;
++ unsigned int active;
++ unsigned long vdso_base;
++} mm_context_t;
++
++/* Page size definitions, common between 32 and 64-bit
++ *
++ * shift : is the "PAGE_SHIFT" value for that page size
++ * penc : is the pte encoding mask
++ *
++ */
++struct mmu_psize_def
++{
++ unsigned int shift; /* number of bits */
++ unsigned int enc; /* PTE encoding */
++ unsigned int ind; /* Corresponding indirect page size shift */
++ unsigned int flags;
++#define MMU_PAGE_SIZE_DIRECT 0x1 /* Supported as a direct size */
++#define MMU_PAGE_SIZE_INDIRECT 0x2 /* Supported as an indirect size */
++};
++extern struct mmu_psize_def mmu_psize_defs[MMU_PAGE_COUNT];
++
++static inline int shift_to_mmu_psize(unsigned int shift)
++{
++ int psize;
++
++ for (psize = 0; psize < MMU_PAGE_COUNT; ++psize)
++ if (mmu_psize_defs[psize].shift == shift)
++ return psize;
++ return -1;
++}
++
++static inline unsigned int mmu_psize_to_shift(unsigned int mmu_psize)
++{
++ if (mmu_psize_defs[mmu_psize].shift)
++ return mmu_psize_defs[mmu_psize].shift;
++ BUG();
++}
++
++/* The page sizes use the same names as 64-bit hash but are
++ * constants
++ */
++#if defined(CONFIG_PPC_4K_PAGES)
++#define mmu_virtual_psize MMU_PAGE_4K
++#else
++#error Unsupported page size
++#endif
++
++extern int mmu_linear_psize;
++extern int mmu_vmemmap_psize;
++
++struct tlb_core_data {
++ /*
++ * Per-core spinlock for e6500 TLB handlers (no tlbsrx.)
++ * Must be the first struct element.
++ */
++ u8 lock;
++
++ /* For software way selection, as on Freescale TLB1 */
++ u8 esel_next, esel_max, esel_first;
++};
++
++#ifdef CONFIG_PPC64
++extern unsigned long linear_map_top;
++extern int book3e_htw_mode;
++
++#define PPC_HTW_NONE 0
++#define PPC_HTW_IBM 1
++#define PPC_HTW_E6500 2
++
++/*
++ * 64-bit booke platforms don't load the tlb in the tlb miss handler code.
++ * HUGETLB_NEED_PRELOAD handles this - it causes huge_ptep_set_access_flags to
++ * return 1, indicating that the tlb requires preloading.
++ */
++#define HUGETLB_NEED_PRELOAD
++
++#define mmu_cleanup_all NULL
++
++#endif
++
++#endif /* !__ASSEMBLY__ */
++
++#endif /* _ASM_POWERPC_MMU_BOOK3E_H_ */
+diff --git a/arch/powerpc/include/asm/nohash/mmu.h b/arch/powerpc/include/asm/nohash/mmu.h
+new file mode 100644
+index 0000000000000..a037cb1efb57e
+--- /dev/null
++++ b/arch/powerpc/include/asm/nohash/mmu.h
+@@ -0,0 +1,11 @@
++/* SPDX-License-Identifier: GPL-2.0 */
++#ifndef _ASM_POWERPC_NOHASH_MMU_H_
++#define _ASM_POWERPC_NOHASH_MMU_H_
++
++#ifdef CONFIG_PPC64
++#include <asm/nohash/64/mmu.h>
++#else
++#include <asm/nohash/32/mmu.h>
++#endif
++
++#endif /* _ASM_POWERPC_NOHASH_MMU_H_ */
+diff --git a/arch/powerpc/include/asm/page.h b/arch/powerpc/include/asm/page.h
+index f6a1265face29..ddfb4b965e5bd 100644
+--- a/arch/powerpc/include/asm/page.h
++++ b/arch/powerpc/include/asm/page.h
+@@ -335,20 +335,6 @@ void arch_free_page(struct page *page, int order);
+ #endif
+
+ struct vm_area_struct;
+-#ifdef CONFIG_PPC_BOOK3S_64
+-/*
+- * For BOOK3s 64 with 4k and 64K linux page size
+- * we want to use pointers, because the page table
+- * actually store pfn
+- */
+-typedef pte_t *pgtable_t;
+-#else
+-#if defined(CONFIG_PPC_64K_PAGES) && defined(CONFIG_PPC64)
+-typedef pte_t *pgtable_t;
+-#else
+-typedef struct page *pgtable_t;
+-#endif
+-#endif
+
+ #include <asm-generic/memory_model.h>
+ #endif /* __ASSEMBLY__ */
+diff --git a/arch/powerpc/include/asm/stackprotector.h b/arch/powerpc/include/asm/stackprotector.h
+new file mode 100644
+index 0000000000000..d05d969c98c21
+--- /dev/null
++++ b/arch/powerpc/include/asm/stackprotector.h
+@@ -0,0 +1,34 @@
++/* SPDX-License-Identifier: GPL-2.0 */
++/*
++ * GCC stack protector support.
++ *
++ */
++
++#ifndef _ASM_STACKPROTECTOR_H
++#define _ASM_STACKPROTECTOR_H
++
++#include <linux/random.h>
++#include <linux/version.h>
++#include <asm/reg.h>
++#include <asm/current.h>
++
++/*
++ * Initialize the stackprotector canary value.
++ *
++ * NOTE: this must only be called from functions that never return,
++ * and it must always be inlined.
++ */
++static __always_inline void boot_init_stack_canary(void)
++{
++ unsigned long canary;
++
++ /* Try to get a semi random initial value. */
++ canary = get_random_canary();
++ canary ^= mftb();
++ canary ^= LINUX_VERSION_CODE;
++ canary &= CANARY_MASK;
++
++ current->stack_canary = canary;
++}
++
++#endif /* _ASM_STACKPROTECTOR_H */
+diff --git a/arch/powerpc/kernel/Makefile b/arch/powerpc/kernel/Makefile
+index bf19c5514d6c2..cccea292af683 100644
+--- a/arch/powerpc/kernel/Makefile
++++ b/arch/powerpc/kernel/Makefile
+@@ -21,6 +21,8 @@ CFLAGS_prom_init.o += $(DISABLE_LATENT_ENTROPY_PLUGIN)
+ CFLAGS_btext.o += $(DISABLE_LATENT_ENTROPY_PLUGIN)
+ CFLAGS_prom.o += $(DISABLE_LATENT_ENTROPY_PLUGIN)
+
++CFLAGS_prom_init.o += $(call cc-option, -fno-stack-protector)
++
+ ifdef CONFIG_FUNCTION_TRACER
+ # Do not trace early boot code
+ CFLAGS_REMOVE_cputable.o = $(CC_FLAGS_FTRACE)
+diff --git a/arch/powerpc/kernel/asm-offsets.c b/arch/powerpc/kernel/asm-offsets.c
+index 50400f213bbf2..c2288c73d56d1 100644
+--- a/arch/powerpc/kernel/asm-offsets.c
++++ b/arch/powerpc/kernel/asm-offsets.c
+@@ -79,6 +79,9 @@ int main(void)
+ {
+ OFFSET(THREAD, task_struct, thread);
+ OFFSET(MM, task_struct, mm);
++#ifdef CONFIG_STACKPROTECTOR
++ OFFSET(TASK_CANARY, task_struct, stack_canary);
++#endif
+ OFFSET(MMCONTEXTID, mm_struct, context.id);
+ #ifdef CONFIG_PPC64
+ DEFINE(SIGSEGV, SIGSEGV);
+diff --git a/arch/powerpc/kernel/cpu_setup_fsl_booke.S b/arch/powerpc/kernel/cpu_setup_fsl_booke.S
+index 8d142e5d84cd0..5fbc890d10943 100644
+--- a/arch/powerpc/kernel/cpu_setup_fsl_booke.S
++++ b/arch/powerpc/kernel/cpu_setup_fsl_booke.S
+@@ -17,7 +17,7 @@
+ #include <asm/processor.h>
+ #include <asm/cputable.h>
+ #include <asm/ppc_asm.h>
+-#include <asm/mmu-book3e.h>
++#include <asm/nohash/mmu-book3e.h>
+ #include <asm/asm-offsets.h>
+ #include <asm/mpc85xx.h>
+
+diff --git a/arch/powerpc/kernel/rtas_flash.c b/arch/powerpc/kernel/rtas_flash.c
+index 10fabae2574d5..ddab3488cadbf 100644
+--- a/arch/powerpc/kernel/rtas_flash.c
++++ b/arch/powerpc/kernel/rtas_flash.c
+@@ -714,9 +714,9 @@ static int __init rtas_flash_init(void)
+ if (!rtas_validate_flash_data.buf)
+ return -ENOMEM;
+
+- flash_block_cache = kmem_cache_create("rtas_flash_cache",
+- RTAS_BLK_SIZE, RTAS_BLK_SIZE, 0,
+- NULL);
++ flash_block_cache = kmem_cache_create_usercopy("rtas_flash_cache",
++ RTAS_BLK_SIZE, RTAS_BLK_SIZE,
++ 0, 0, RTAS_BLK_SIZE, NULL);
+ if (!flash_block_cache) {
+ printk(KERN_ERR "%s: failed to create block cache\n",
+ __func__);
+diff --git a/arch/powerpc/kvm/e500.h b/arch/powerpc/kvm/e500.h
+index 94f04fcb373e1..962ee90a0dfea 100644
+--- a/arch/powerpc/kvm/e500.h
++++ b/arch/powerpc/kvm/e500.h
+@@ -20,7 +20,7 @@
+ #define KVM_E500_H
+
+ #include <linux/kvm_host.h>
+-#include <asm/mmu-book3e.h>
++#include <asm/nohash/mmu-book3e.h>
+ #include <asm/tlb.h>
+ #include <asm/cputhreads.h>
+
+diff --git a/arch/powerpc/mm/Makefile b/arch/powerpc/mm/Makefile
+index 3c844bdd16c4e..d4648a1e6e6c1 100644
+--- a/arch/powerpc/mm/Makefile
++++ b/arch/powerpc/mm/Makefile
+@@ -42,13 +42,5 @@ obj-$(CONFIG_NOT_COHERENT_CACHE) += dma-noncoherent.o
+ obj-$(CONFIG_HIGHMEM) += highmem.o
+ obj-$(CONFIG_PPC_COPRO_BASE) += copro_fault.o
+ obj-$(CONFIG_SPAPR_TCE_IOMMU) += mmu_context_iommu.o
+-obj-$(CONFIG_PPC_PTDUMP) += dump_linuxpagetables.o
+-ifdef CONFIG_PPC_PTDUMP
+-obj-$(CONFIG_4xx) += dump_linuxpagetables-generic.o
+-obj-$(CONFIG_PPC_8xx) += dump_linuxpagetables-8xx.o
+-obj-$(CONFIG_PPC_BOOK3E_MMU) += dump_linuxpagetables-generic.o
+-obj-$(CONFIG_PPC_BOOK3S_32) += dump_linuxpagetables-generic.o
+-obj-$(CONFIG_PPC_BOOK3S_64) += dump_linuxpagetables-book3s64.o
+-endif
+-obj-$(CONFIG_PPC_HTDUMP) += dump_hashpagetable.o
++obj-$(CONFIG_PPC_PTDUMP) += ptdump/
+ obj-$(CONFIG_PPC_MEM_KEYS) += pkeys.o
+diff --git a/arch/powerpc/mm/dump_hashpagetable.c b/arch/powerpc/mm/dump_hashpagetable.c
+deleted file mode 100644
+index b430e4e08af69..0000000000000
+--- a/arch/powerpc/mm/dump_hashpagetable.c
++++ /dev/null
+@@ -1,550 +0,0 @@
+-/*
+- * Copyright 2016, Rashmica Gupta, IBM Corp.
+- *
+- * This traverses the kernel virtual memory and dumps the pages that are in
+- * the hash pagetable, along with their flags to
+- * /sys/kernel/debug/kernel_hash_pagetable.
+- *
+- * If radix is enabled then there is no hash page table and so no debugfs file
+- * is generated.
+- *
+- * This program is free software; you can redistribute it and/or
+- * modify it under the terms of the GNU General Public License
+- * as published by the Free Software Foundation; version 2
+- * of the License.
+- */
+-#include <linux/debugfs.h>
+-#include <linux/fs.h>
+-#include <linux/io.h>
+-#include <linux/mm.h>
+-#include <linux/sched.h>
+-#include <linux/seq_file.h>
+-#include <asm/pgtable.h>
+-#include <linux/const.h>
+-#include <asm/page.h>
+-#include <asm/pgalloc.h>
+-#include <asm/plpar_wrappers.h>
+-#include <linux/memblock.h>
+-#include <asm/firmware.h>
+-
+-struct pg_state {
+- struct seq_file *seq;
+- const struct addr_marker *marker;
+- unsigned long start_address;
+- unsigned int level;
+- u64 current_flags;
+-};
+-
+-struct addr_marker {
+- unsigned long start_address;
+- const char *name;
+-};
+-
+-static struct addr_marker address_markers[] = {
+- { 0, "Start of kernel VM" },
+- { 0, "vmalloc() Area" },
+- { 0, "vmalloc() End" },
+- { 0, "isa I/O start" },
+- { 0, "isa I/O end" },
+- { 0, "phb I/O start" },
+- { 0, "phb I/O end" },
+- { 0, "I/O remap start" },
+- { 0, "I/O remap end" },
+- { 0, "vmemmap start" },
+- { -1, NULL },
+-};
+-
+-struct flag_info {
+- u64 mask;
+- u64 val;
+- const char *set;
+- const char *clear;
+- bool is_val;
+- int shift;
+-};
+-
+-static const struct flag_info v_flag_array[] = {
+- {
+- .mask = SLB_VSID_B,
+- .val = SLB_VSID_B_256M,
+- .set = "ssize: 256M",
+- .clear = "ssize: 1T ",
+- }, {
+- .mask = HPTE_V_SECONDARY,
+- .val = HPTE_V_SECONDARY,
+- .set = "secondary",
+- .clear = "primary ",
+- }, {
+- .mask = HPTE_V_VALID,
+- .val = HPTE_V_VALID,
+- .set = "valid ",
+- .clear = "invalid",
+- }, {
+- .mask = HPTE_V_BOLTED,
+- .val = HPTE_V_BOLTED,
+- .set = "bolted",
+- .clear = "",
+- }
+-};
+-
+-static const struct flag_info r_flag_array[] = {
+- {
+- .mask = HPTE_R_PP0 | HPTE_R_PP,
+- .val = PP_RWXX,
+- .set = "prot:RW--",
+- }, {
+- .mask = HPTE_R_PP0 | HPTE_R_PP,
+- .val = PP_RWRX,
+- .set = "prot:RWR-",
+- }, {
+- .mask = HPTE_R_PP0 | HPTE_R_PP,
+- .val = PP_RWRW,
+- .set = "prot:RWRW",
+- }, {
+- .mask = HPTE_R_PP0 | HPTE_R_PP,
+- .val = PP_RXRX,
+- .set = "prot:R-R-",
+- }, {
+- .mask = HPTE_R_PP0 | HPTE_R_PP,
+- .val = PP_RXXX,
+- .set = "prot:R---",
+- }, {
+- .mask = HPTE_R_KEY_HI | HPTE_R_KEY_LO,
+- .val = HPTE_R_KEY_HI | HPTE_R_KEY_LO,
+- .set = "key",
+- .clear = "",
+- .is_val = true,
+- }, {
+- .mask = HPTE_R_R,
+- .val = HPTE_R_R,
+- .set = "ref",
+- .clear = " ",
+- }, {
+- .mask = HPTE_R_C,
+- .val = HPTE_R_C,
+- .set = "changed",
+- .clear = " ",
+- }, {
+- .mask = HPTE_R_N,
+- .val = HPTE_R_N,
+- .set = "no execute",
+- }, {
+- .mask = HPTE_R_WIMG,
+- .val = HPTE_R_W,
+- .set = "writethru",
+- }, {
+- .mask = HPTE_R_WIMG,
+- .val = HPTE_R_I,
+- .set = "no cache",
+- }, {
+- .mask = HPTE_R_WIMG,
+- .val = HPTE_R_G,
+- .set = "guarded",
+- }
+-};
+-
+-static int calculate_pagesize(struct pg_state *st, int ps, char s[])
+-{
+- static const char units[] = "BKMGTPE";
+- const char *unit = units;
+-
+- while (ps > 9 && unit[1]) {
+- ps -= 10;
+- unit++;
+- }
+- seq_printf(st->seq, " %s_ps: %i%c\t", s, 1<<ps, *unit);
+- return ps;
+-}
+-
+-static void dump_flag_info(struct pg_state *st, const struct flag_info
+- *flag, u64 pte, int num)
+-{
+- unsigned int i;
+-
+- for (i = 0; i < num; i++, flag++) {
+- const char *s = NULL;
+- u64 val;
+-
+- /* flag not defined so don't check it */
+- if (flag->mask == 0)
+- continue;
+- /* Some 'flags' are actually values */
+- if (flag->is_val) {
+- val = pte & flag->val;
+- if (flag->shift)
+- val = val >> flag->shift;
+- seq_printf(st->seq, " %s:%llx", flag->set, val);
+- } else {
+- if ((pte & flag->mask) == flag->val)
+- s = flag->set;
+- else
+- s = flag->clear;
+- if (s)
+- seq_printf(st->seq, " %s", s);
+- }
+- }
+-}
+-
+-static void dump_hpte_info(struct pg_state *st, unsigned long ea, u64 v, u64 r,
+- unsigned long rpn, int bps, int aps, unsigned long lp)
+-{
+- int aps_index;
+-
+- while (ea >= st->marker[1].start_address) {
+- st->marker++;
+- seq_printf(st->seq, "---[ %s ]---\n", st->marker->name);
+- }
+- seq_printf(st->seq, "0x%lx:\t", ea);
+- seq_printf(st->seq, "AVPN:%llx\t", HPTE_V_AVPN_VAL(v));
+- dump_flag_info(st, v_flag_array, v, ARRAY_SIZE(v_flag_array));
+- seq_printf(st->seq, " rpn: %lx\t", rpn);
+- dump_flag_info(st, r_flag_array, r, ARRAY_SIZE(r_flag_array));
+-
+- calculate_pagesize(st, bps, "base");
+- aps_index = calculate_pagesize(st, aps, "actual");
+- if (aps_index != 2)
+- seq_printf(st->seq, "LP enc: %lx", lp);
+- seq_putc(st->seq, '\n');
+-}
+-
+-
+-static int native_find(unsigned long ea, int psize, bool primary, u64 *v, u64
+- *r)
+-{
+- struct hash_pte *hptep;
+- unsigned long hash, vsid, vpn, hpte_group, want_v, hpte_v;
+- int i, ssize = mmu_kernel_ssize;
+- unsigned long shift = mmu_psize_defs[psize].shift;
+-
+- /* calculate hash */
+- vsid = get_kernel_vsid(ea, ssize);
+- vpn = hpt_vpn(ea, vsid, ssize);
+- hash = hpt_hash(vpn, shift, ssize);
+- want_v = hpte_encode_avpn(vpn, psize, ssize);
+-
+- /* to check in the secondary hash table, we invert the hash */
+- if (!primary)
+- hash = ~hash;
+- hpte_group = (hash & htab_hash_mask) * HPTES_PER_GROUP;
+- for (i = 0; i < HPTES_PER_GROUP; i++) {
+- hptep = htab_address + hpte_group;
+- hpte_v = be64_to_cpu(hptep->v);
+-
+- if (HPTE_V_COMPARE(hpte_v, want_v) && (hpte_v & HPTE_V_VALID)) {
+- /* HPTE matches */
+- *v = be64_to_cpu(hptep->v);
+- *r = be64_to_cpu(hptep->r);
+- return 0;
+- }
+- ++hpte_group;
+- }
+- return -1;
+-}
+-
+-#ifdef CONFIG_PPC_PSERIES
+-static int pseries_find(unsigned long ea, int psize, bool primary, u64 *v, u64 *r)
+-{
+- struct hash_pte ptes[4];
+- unsigned long vsid, vpn, hash, hpte_group, want_v;
+- int i, j, ssize = mmu_kernel_ssize;
+- long lpar_rc = 0;
+- unsigned long shift = mmu_psize_defs[psize].shift;
+-
+- /* calculate hash */
+- vsid = get_kernel_vsid(ea, ssize);
+- vpn = hpt_vpn(ea, vsid, ssize);
+- hash = hpt_hash(vpn, shift, ssize);
+- want_v = hpte_encode_avpn(vpn, psize, ssize);
+-
+- /* to check in the secondary hash table, we invert the hash */
+- if (!primary)
+- hash = ~hash;
+- hpte_group = (hash & htab_hash_mask) * HPTES_PER_GROUP;
+- /* see if we can find an entry in the hpte with this hash */
+- for (i = 0; i < HPTES_PER_GROUP; i += 4, hpte_group += 4) {
+- lpar_rc = plpar_pte_read_4(0, hpte_group, (void *)ptes);
+-
+- if (lpar_rc != H_SUCCESS)
+- continue;
+- for (j = 0; j < 4; j++) {
+- if (HPTE_V_COMPARE(ptes[j].v, want_v) &&
+- (ptes[j].v & HPTE_V_VALID)) {
+- /* HPTE matches */
+- *v = ptes[j].v;
+- *r = ptes[j].r;
+- return 0;
+- }
+- }
+- }
+- return -1;
+-}
+-#endif
+-
+-static void decode_r(int bps, unsigned long r, unsigned long *rpn, int *aps,
+- unsigned long *lp_bits)
+-{
+- struct mmu_psize_def entry;
+- unsigned long arpn, mask, lp;
+- int penc = -2, idx = 0, shift;
+-
+- /*.
+- * The LP field has 8 bits. Depending on the actual page size, some of
+- * these bits are concatenated with the APRN to get the RPN. The rest
+- * of the bits in the LP field is the LP value and is an encoding for
+- * the base page size and the actual page size.
+- *
+- * - find the mmu entry for our base page size
+- * - go through all page encodings and use the associated mask to
+- * find an encoding that matches our encoding in the LP field.
+- */
+- arpn = (r & HPTE_R_RPN) >> HPTE_R_RPN_SHIFT;
+- lp = arpn & 0xff;
+-
+- entry = mmu_psize_defs[bps];
+- while (idx < MMU_PAGE_COUNT) {
+- penc = entry.penc[idx];
+- if ((penc != -1) && (mmu_psize_defs[idx].shift)) {
+- shift = mmu_psize_defs[idx].shift - HPTE_R_RPN_SHIFT;
+- mask = (0x1 << (shift)) - 1;
+- if ((lp & mask) == penc) {
+- *aps = mmu_psize_to_shift(idx);
+- *lp_bits = lp & mask;
+- *rpn = arpn >> shift;
+- return;
+- }
+- }
+- idx++;
+- }
+-}
+-
+-static int base_hpte_find(unsigned long ea, int psize, bool primary, u64 *v,
+- u64 *r)
+-{
+-#ifdef CONFIG_PPC_PSERIES
+- if (firmware_has_feature(FW_FEATURE_LPAR))
+- return pseries_find(ea, psize, primary, v, r);
+-#endif
+- return native_find(ea, psize, primary, v, r);
+-}
+-
+-static unsigned long hpte_find(struct pg_state *st, unsigned long ea, int psize)
+-{
+- unsigned long slot;
+- u64 v = 0, r = 0;
+- unsigned long rpn, lp_bits;
+- int base_psize = 0, actual_psize = 0;
+-
+- if (ea < PAGE_OFFSET)
+- return -1;
+-
+- /* Look in primary table */
+- slot = base_hpte_find(ea, psize, true, &v, &r);
+-
+- /* Look in secondary table */
+- if (slot == -1)
+- slot = base_hpte_find(ea, psize, false, &v, &r);
+-
+- /* No entry found */
+- if (slot == -1)
+- return -1;
+-
+- /*
+- * We found an entry in the hash page table:
+- * - check that this has the same base page
+- * - find the actual page size
+- * - find the RPN
+- */
+- base_psize = mmu_psize_to_shift(psize);
+-
+- if ((v & HPTE_V_LARGE) == HPTE_V_LARGE) {
+- decode_r(psize, r, &rpn, &actual_psize, &lp_bits);
+- } else {
+- /* 4K actual page size */
+- actual_psize = 12;
+- rpn = (r & HPTE_R_RPN) >> HPTE_R_RPN_SHIFT;
+- /* In this case there are no LP bits */
+- lp_bits = -1;
+- }
+- /*
+- * We didn't find a matching encoding, so the PTE we found isn't for
+- * this address.
+- */
+- if (actual_psize == -1)
+- return -1;
+-
+- dump_hpte_info(st, ea, v, r, rpn, base_psize, actual_psize, lp_bits);
+- return 0;
+-}
+-
+-static void walk_pte(struct pg_state *st, pmd_t *pmd, unsigned long start)
+-{
+- pte_t *pte = pte_offset_kernel(pmd, 0);
+- unsigned long addr, pteval, psize;
+- int i, status;
+-
+- for (i = 0; i < PTRS_PER_PTE; i++, pte++) {
+- addr = start + i * PAGE_SIZE;
+- pteval = pte_val(*pte);
+-
+- if (addr < VMALLOC_END)
+- psize = mmu_vmalloc_psize;
+- else
+- psize = mmu_io_psize;
+-#ifdef CONFIG_PPC_64K_PAGES
+- /* check for secret 4K mappings */
+- if (((pteval & H_PAGE_COMBO) == H_PAGE_COMBO) ||
+- ((pteval & H_PAGE_4K_PFN) == H_PAGE_4K_PFN))
+- psize = mmu_io_psize;
+-#endif
+- /* check for hashpte */
+- status = hpte_find(st, addr, psize);
+-
+- if (((pteval & H_PAGE_HASHPTE) != H_PAGE_HASHPTE)
+- && (status != -1)) {
+- /* found a hpte that is not in the linux page tables */
+- seq_printf(st->seq, "page probably bolted before linux"
+- " pagetables were set: addr:%lx, pteval:%lx\n",
+- addr, pteval);
+- }
+- }
+-}
+-
+-static void walk_pmd(struct pg_state *st, pud_t *pud, unsigned long start)
+-{
+- pmd_t *pmd = pmd_offset(pud, 0);
+- unsigned long addr;
+- unsigned int i;
+-
+- for (i = 0; i < PTRS_PER_PMD; i++, pmd++) {
+- addr = start + i * PMD_SIZE;
+- if (!pmd_none(*pmd))
+- /* pmd exists */
+- walk_pte(st, pmd, addr);
+- }
+-}
+-
+-static void walk_pud(struct pg_state *st, pgd_t *pgd, unsigned long start)
+-{
+- pud_t *pud = pud_offset(pgd, 0);
+- unsigned long addr;
+- unsigned int i;
+-
+- for (i = 0; i < PTRS_PER_PUD; i++, pud++) {
+- addr = start + i * PUD_SIZE;
+- if (!pud_none(*pud))
+- /* pud exists */
+- walk_pmd(st, pud, addr);
+- }
+-}
+-
+-static void walk_pagetables(struct pg_state *st)
+-{
+- pgd_t *pgd = pgd_offset_k(0UL);
+- unsigned int i;
+- unsigned long addr;
+-
+- /*
+- * Traverse the linux pagetable structure and dump pages that are in
+- * the hash pagetable.
+- */
+- for (i = 0; i < PTRS_PER_PGD; i++, pgd++) {
+- addr = KERN_VIRT_START + i * PGDIR_SIZE;
+- if (!pgd_none(*pgd))
+- /* pgd exists */
+- walk_pud(st, pgd, addr);
+- }
+-}
+-
+-
+-static void walk_linearmapping(struct pg_state *st)
+-{
+- unsigned long addr;
+-
+- /*
+- * Traverse the linear mapping section of virtual memory and dump pages
+- * that are in the hash pagetable.
+- */
+- unsigned long psize = 1 << mmu_psize_defs[mmu_linear_psize].shift;
+-
+- for (addr = PAGE_OFFSET; addr < PAGE_OFFSET +
+- memblock_end_of_DRAM(); addr += psize)
+- hpte_find(st, addr, mmu_linear_psize);
+-}
+-
+-static void walk_vmemmap(struct pg_state *st)
+-{
+-#ifdef CONFIG_SPARSEMEM_VMEMMAP
+- struct vmemmap_backing *ptr = vmemmap_list;
+-
+- /*
+- * Traverse the vmemmaped memory and dump pages that are in the hash
+- * pagetable.
+- */
+- while (ptr->list) {
+- hpte_find(st, ptr->virt_addr, mmu_vmemmap_psize);
+- ptr = ptr->list;
+- }
+- seq_puts(st->seq, "---[ vmemmap end ]---\n");
+-#endif
+-}
+-
+-static void populate_markers(void)
+-{
+- address_markers[0].start_address = PAGE_OFFSET;
+- address_markers[1].start_address = VMALLOC_START;
+- address_markers[2].start_address = VMALLOC_END;
+- address_markers[3].start_address = ISA_IO_BASE;
+- address_markers[4].start_address = ISA_IO_END;
+- address_markers[5].start_address = PHB_IO_BASE;
+- address_markers[6].start_address = PHB_IO_END;
+- address_markers[7].start_address = IOREMAP_BASE;
+- address_markers[8].start_address = IOREMAP_END;
+-#ifdef CONFIG_PPC_BOOK3S_64
+- address_markers[9].start_address = H_VMEMMAP_BASE;
+-#else
+- address_markers[9].start_address = VMEMMAP_BASE;
+-#endif
+-}
+-
+-static int ptdump_show(struct seq_file *m, void *v)
+-{
+- struct pg_state st = {
+- .seq = m,
+- .start_address = PAGE_OFFSET,
+- .marker = address_markers,
+- };
+- /*
+- * Traverse the 0xc, 0xd and 0xf areas of the kernel virtual memory and
+- * dump pages that are in the hash pagetable.
+- */
+- walk_linearmapping(&st);
+- walk_pagetables(&st);
+- walk_vmemmap(&st);
+- return 0;
+-}
+-
+-static int ptdump_open(struct inode *inode, struct file *file)
+-{
+- return single_open(file, ptdump_show, NULL);
+-}
+-
+-static const struct file_operations ptdump_fops = {
+- .open = ptdump_open,
+- .read = seq_read,
+- .llseek = seq_lseek,
+- .release = single_release,
+-};
+-
+-static int ptdump_init(void)
+-{
+- struct dentry *debugfs_file;
+-
+- if (!radix_enabled()) {
+- populate_markers();
+- debugfs_file = debugfs_create_file("kernel_hash_pagetable",
+- 0400, NULL, NULL, &ptdump_fops);
+- return debugfs_file ? 0 : -ENOMEM;
+- }
+- return 0;
+-}
+-device_initcall(ptdump_init);
+diff --git a/arch/powerpc/mm/dump_linuxpagetables-8xx.c b/arch/powerpc/mm/dump_linuxpagetables-8xx.c
+deleted file mode 100644
+index 33f52a97975b4..0000000000000
+--- a/arch/powerpc/mm/dump_linuxpagetables-8xx.c
++++ /dev/null
+@@ -1,82 +0,0 @@
+-// SPDX-License-Identifier: GPL-2.0
+-/*
+- * From split of dump_linuxpagetables.c
+- * Copyright 2016, Rashmica Gupta, IBM Corp.
+- *
+- */
+-#include <linux/kernel.h>
+-#include <asm/pgtable.h>
+-
+-#include "dump_linuxpagetables.h"
+-
+-static const struct flag_info flag_array[] = {
+- {
+- .mask = _PAGE_PRIVILEGED,
+- .val = 0,
+- .set = "user",
+- .clear = " ",
+- }, {
+- .mask = _PAGE_RO | _PAGE_NA,
+- .val = 0,
+- .set = "rw",
+- }, {
+- .mask = _PAGE_RO | _PAGE_NA,
+- .val = _PAGE_RO,
+- .set = "r ",
+- }, {
+- .mask = _PAGE_RO | _PAGE_NA,
+- .val = _PAGE_NA,
+- .set = " ",
+- }, {
+- .mask = _PAGE_EXEC,
+- .val = _PAGE_EXEC,
+- .set = " X ",
+- .clear = " ",
+- }, {
+- .mask = _PAGE_PRESENT,
+- .val = _PAGE_PRESENT,
+- .set = "present",
+- .clear = " ",
+- }, {
+- .mask = _PAGE_GUARDED,
+- .val = _PAGE_GUARDED,
+- .set = "guarded",
+- .clear = " ",
+- }, {
+- .mask = _PAGE_DIRTY,
+- .val = _PAGE_DIRTY,
+- .set = "dirty",
+- .clear = " ",
+- }, {
+- .mask = _PAGE_ACCESSED,
+- .val = _PAGE_ACCESSED,
+- .set = "accessed",
+- .clear = " ",
+- }, {
+- .mask = _PAGE_NO_CACHE,
+- .val = _PAGE_NO_CACHE,
+- .set = "no cache",
+- .clear = " ",
+- }, {
+- .mask = _PAGE_SPECIAL,
+- .val = _PAGE_SPECIAL,
+- .set = "special",
+- }
+-};
+-
+-struct pgtable_level pg_level[5] = {
+- {
+- }, { /* pgd */
+- .flag = flag_array,
+- .num = ARRAY_SIZE(flag_array),
+- }, { /* pud */
+- .flag = flag_array,
+- .num = ARRAY_SIZE(flag_array),
+- }, { /* pmd */
+- .flag = flag_array,
+- .num = ARRAY_SIZE(flag_array),
+- }, { /* pte */
+- .flag = flag_array,
+- .num = ARRAY_SIZE(flag_array),
+- },
+-};
+diff --git a/arch/powerpc/mm/dump_linuxpagetables-book3s64.c b/arch/powerpc/mm/dump_linuxpagetables-book3s64.c
+deleted file mode 100644
+index a637e612b2055..0000000000000
+--- a/arch/powerpc/mm/dump_linuxpagetables-book3s64.c
++++ /dev/null
+@@ -1,115 +0,0 @@
+-// SPDX-License-Identifier: GPL-2.0
+-/*
+- * From split of dump_linuxpagetables.c
+- * Copyright 2016, Rashmica Gupta, IBM Corp.
+- *
+- */
+-#include <linux/kernel.h>
+-#include <asm/pgtable.h>
+-
+-#include "dump_linuxpagetables.h"
+-
+-static const struct flag_info flag_array[] = {
+- {
+- .mask = _PAGE_PRIVILEGED,
+- .val = 0,
+- .set = "user",
+- .clear = " ",
+- }, {
+- .mask = _PAGE_READ,
+- .val = _PAGE_READ,
+- .set = "r",
+- .clear = " ",
+- }, {
+- .mask = _PAGE_WRITE,
+- .val = _PAGE_WRITE,
+- .set = "w",
+- .clear = " ",
+- }, {
+- .mask = _PAGE_EXEC,
+- .val = _PAGE_EXEC,
+- .set = " X ",
+- .clear = " ",
+- }, {
+- .mask = _PAGE_PTE,
+- .val = _PAGE_PTE,
+- .set = "pte",
+- .clear = " ",
+- }, {
+- .mask = _PAGE_PRESENT,
+- .val = _PAGE_PRESENT,
+- .set = "present",
+- .clear = " ",
+- }, {
+- .mask = H_PAGE_HASHPTE,
+- .val = H_PAGE_HASHPTE,
+- .set = "hpte",
+- .clear = " ",
+- }, {
+- .mask = _PAGE_DIRTY,
+- .val = _PAGE_DIRTY,
+- .set = "dirty",
+- .clear = " ",
+- }, {
+- .mask = _PAGE_ACCESSED,
+- .val = _PAGE_ACCESSED,
+- .set = "accessed",
+- .clear = " ",
+- }, {
+- .mask = _PAGE_NON_IDEMPOTENT,
+- .val = _PAGE_NON_IDEMPOTENT,
+- .set = "non-idempotent",
+- .clear = " ",
+- }, {
+- .mask = _PAGE_TOLERANT,
+- .val = _PAGE_TOLERANT,
+- .set = "tolerant",
+- .clear = " ",
+- }, {
+- .mask = H_PAGE_BUSY,
+- .val = H_PAGE_BUSY,
+- .set = "busy",
+- }, {
+-#ifdef CONFIG_PPC_64K_PAGES
+- .mask = H_PAGE_COMBO,
+- .val = H_PAGE_COMBO,
+- .set = "combo",
+- }, {
+- .mask = H_PAGE_4K_PFN,
+- .val = H_PAGE_4K_PFN,
+- .set = "4K_pfn",
+- }, {
+-#else /* CONFIG_PPC_64K_PAGES */
+- .mask = H_PAGE_F_GIX,
+- .val = H_PAGE_F_GIX,
+- .set = "f_gix",
+- .is_val = true,
+- .shift = H_PAGE_F_GIX_SHIFT,
+- }, {
+- .mask = H_PAGE_F_SECOND,
+- .val = H_PAGE_F_SECOND,
+- .set = "f_second",
+- }, {
+-#endif /* CONFIG_PPC_64K_PAGES */
+- .mask = _PAGE_SPECIAL,
+- .val = _PAGE_SPECIAL,
+- .set = "special",
+- }
+-};
+-
+-struct pgtable_level pg_level[5] = {
+- {
+- }, { /* pgd */
+- .flag = flag_array,
+- .num = ARRAY_SIZE(flag_array),
+- }, { /* pud */
+- .flag = flag_array,
+- .num = ARRAY_SIZE(flag_array),
+- }, { /* pmd */
+- .flag = flag_array,
+- .num = ARRAY_SIZE(flag_array),
+- }, { /* pte */
+- .flag = flag_array,
+- .num = ARRAY_SIZE(flag_array),
+- },
+-};
+diff --git a/arch/powerpc/mm/dump_linuxpagetables-generic.c b/arch/powerpc/mm/dump_linuxpagetables-generic.c
+deleted file mode 100644
+index fed6923bcb46e..0000000000000
+--- a/arch/powerpc/mm/dump_linuxpagetables-generic.c
++++ /dev/null
+@@ -1,82 +0,0 @@
+-// SPDX-License-Identifier: GPL-2.0
+-/*
+- * From split of dump_linuxpagetables.c
+- * Copyright 2016, Rashmica Gupta, IBM Corp.
+- *
+- */
+-#include <linux/kernel.h>
+-#include <asm/pgtable.h>
+-
+-#include "dump_linuxpagetables.h"
+-
+-static const struct flag_info flag_array[] = {
+- {
+- .mask = _PAGE_USER,
+- .val = _PAGE_USER,
+- .set = "user",
+- .clear = " ",
+- }, {
+- .mask = _PAGE_RW,
+- .val = 0,
+- .set = "r ",
+- .clear = "rw",
+- }, {
+-#ifndef CONFIG_PPC_BOOK3S_32
+- .mask = _PAGE_EXEC,
+- .val = _PAGE_EXEC,
+- .set = " X ",
+- .clear = " ",
+- }, {
+-#endif
+- .mask = _PAGE_PRESENT,
+- .val = _PAGE_PRESENT,
+- .set = "present",
+- .clear = " ",
+- }, {
+- .mask = _PAGE_GUARDED,
+- .val = _PAGE_GUARDED,
+- .set = "guarded",
+- .clear = " ",
+- }, {
+- .mask = _PAGE_DIRTY,
+- .val = _PAGE_DIRTY,
+- .set = "dirty",
+- .clear = " ",
+- }, {
+- .mask = _PAGE_ACCESSED,
+- .val = _PAGE_ACCESSED,
+- .set = "accessed",
+- .clear = " ",
+- }, {
+- .mask = _PAGE_WRITETHRU,
+- .val = _PAGE_WRITETHRU,
+- .set = "write through",
+- .clear = " ",
+- }, {
+- .mask = _PAGE_NO_CACHE,
+- .val = _PAGE_NO_CACHE,
+- .set = "no cache",
+- .clear = " ",
+- }, {
+- .mask = _PAGE_SPECIAL,
+- .val = _PAGE_SPECIAL,
+- .set = "special",
+- }
+-};
+-
+-struct pgtable_level pg_level[5] = {
+- {
+- }, { /* pgd */
+- .flag = flag_array,
+- .num = ARRAY_SIZE(flag_array),
+- }, { /* pud */
+- .flag = flag_array,
+- .num = ARRAY_SIZE(flag_array),
+- }, { /* pmd */
+- .flag = flag_array,
+- .num = ARRAY_SIZE(flag_array),
+- }, { /* pte */
+- .flag = flag_array,
+- .num = ARRAY_SIZE(flag_array),
+- },
+-};
+diff --git a/arch/powerpc/mm/dump_linuxpagetables.c b/arch/powerpc/mm/dump_linuxpagetables.c
+deleted file mode 100644
+index 6aa41669ac1ae..0000000000000
+--- a/arch/powerpc/mm/dump_linuxpagetables.c
++++ /dev/null
+@@ -1,373 +0,0 @@
+-/*
+- * Copyright 2016, Rashmica Gupta, IBM Corp.
+- *
+- * This traverses the kernel pagetables and dumps the
+- * information about the used sections of memory to
+- * /sys/kernel/debug/kernel_pagetables.
+- *
+- * Derived from the arm64 implementation:
+- * Copyright (c) 2014, The Linux Foundation, Laura Abbott.
+- * (C) Copyright 2008 Intel Corporation, Arjan van de Ven.
+- *
+- * This program is free software; you can redistribute it and/or
+- * modify it under the terms of the GNU General Public License
+- * as published by the Free Software Foundation; version 2
+- * of the License.
+- */
+-#include <linux/debugfs.h>
+-#include <linux/fs.h>
+-#include <linux/hugetlb.h>
+-#include <linux/io.h>
+-#include <linux/mm.h>
+-#include <linux/highmem.h>
+-#include <linux/sched.h>
+-#include <linux/seq_file.h>
+-#include <asm/fixmap.h>
+-#include <asm/pgtable.h>
+-#include <linux/const.h>
+-#include <asm/page.h>
+-#include <asm/pgalloc.h>
+-
+-#include "dump_linuxpagetables.h"
+-
+-#ifdef CONFIG_PPC32
+-#define KERN_VIRT_START 0
+-#endif
+-
+-/*
+- * To visualise what is happening,
+- *
+- * - PTRS_PER_P** = how many entries there are in the corresponding P**
+- * - P**_SHIFT = how many bits of the address we use to index into the
+- * corresponding P**
+- * - P**_SIZE is how much memory we can access through the table - not the
+- * size of the table itself.
+- * P**={PGD, PUD, PMD, PTE}
+- *
+- *
+- * Each entry of the PGD points to a PUD. Each entry of a PUD points to a
+- * PMD. Each entry of a PMD points to a PTE. And every PTE entry points to
+- * a page.
+- *
+- * In the case where there are only 3 levels, the PUD is folded into the
+- * PGD: every PUD has only one entry which points to the PMD.
+- *
+- * The page dumper groups page table entries of the same type into a single
+- * description. It uses pg_state to track the range information while
+- * iterating over the PTE entries. When the continuity is broken it then
+- * dumps out a description of the range - ie PTEs that are virtually contiguous
+- * with the same PTE flags are chunked together. This is to make it clear how
+- * different areas of the kernel virtual memory are used.
+- *
+- */
+-struct pg_state {
+- struct seq_file *seq;
+- const struct addr_marker *marker;
+- unsigned long start_address;
+- unsigned long start_pa;
+- unsigned long last_pa;
+- unsigned int level;
+- u64 current_flags;
+-};
+-
+-struct addr_marker {
+- unsigned long start_address;
+- const char *name;
+-};
+-
+-static struct addr_marker address_markers[] = {
+- { 0, "Start of kernel VM" },
+- { 0, "vmalloc() Area" },
+- { 0, "vmalloc() End" },
+-#ifdef CONFIG_PPC64
+- { 0, "isa I/O start" },
+- { 0, "isa I/O end" },
+- { 0, "phb I/O start" },
+- { 0, "phb I/O end" },
+- { 0, "I/O remap start" },
+- { 0, "I/O remap end" },
+- { 0, "vmemmap start" },
+-#else
+- { 0, "Early I/O remap start" },
+- { 0, "Early I/O remap end" },
+-#ifdef CONFIG_NOT_COHERENT_CACHE
+- { 0, "Consistent mem start" },
+- { 0, "Consistent mem end" },
+-#endif
+-#ifdef CONFIG_HIGHMEM
+- { 0, "Highmem PTEs start" },
+- { 0, "Highmem PTEs end" },
+-#endif
+- { 0, "Fixmap start" },
+- { 0, "Fixmap end" },
+-#endif
+- { -1, NULL },
+-};
+-
+-static void dump_flag_info(struct pg_state *st, const struct flag_info
+- *flag, u64 pte, int num)
+-{
+- unsigned int i;
+-
+- for (i = 0; i < num; i++, flag++) {
+- const char *s = NULL;
+- u64 val;
+-
+- /* flag not defined so don't check it */
+- if (flag->mask == 0)
+- continue;
+- /* Some 'flags' are actually values */
+- if (flag->is_val) {
+- val = pte & flag->val;
+- if (flag->shift)
+- val = val >> flag->shift;
+- seq_printf(st->seq, " %s:%llx", flag->set, val);
+- } else {
+- if ((pte & flag->mask) == flag->val)
+- s = flag->set;
+- else
+- s = flag->clear;
+- if (s)
+- seq_printf(st->seq, " %s", s);
+- }
+- st->current_flags &= ~flag->mask;
+- }
+- if (st->current_flags != 0)
+- seq_printf(st->seq, " unknown flags:%llx", st->current_flags);
+-}
+-
+-static void dump_addr(struct pg_state *st, unsigned long addr)
+-{
+- static const char units[] = "KMGTPE";
+- const char *unit = units;
+- unsigned long delta;
+-
+-#ifdef CONFIG_PPC64
+- seq_printf(st->seq, "0x%016lx-0x%016lx ", st->start_address, addr-1);
+- seq_printf(st->seq, "0x%016lx ", st->start_pa);
+-#else
+- seq_printf(st->seq, "0x%08lx-0x%08lx ", st->start_address, addr - 1);
+- seq_printf(st->seq, "0x%08lx ", st->start_pa);
+-#endif
+-
+- delta = (addr - st->start_address) >> 10;
+- /* Work out what appropriate unit to use */
+- while (!(delta & 1023) && unit[1]) {
+- delta >>= 10;
+- unit++;
+- }
+- seq_printf(st->seq, "%9lu%c", delta, *unit);
+-
+-}
+-
+-static void note_page(struct pg_state *st, unsigned long addr,
+- unsigned int level, u64 val)
+-{
+- u64 flag = val & pg_level[level].mask;
+- u64 pa = val & PTE_RPN_MASK;
+-
+- /* At first no level is set */
+- if (!st->level) {
+- st->level = level;
+- st->current_flags = flag;
+- st->start_address = addr;
+- st->start_pa = pa;
+- st->last_pa = pa;
+- seq_printf(st->seq, "---[ %s ]---\n", st->marker->name);
+- /*
+- * Dump the section of virtual memory when:
+- * - the PTE flags from one entry to the next differs.
+- * - we change levels in the tree.
+- * - the address is in a different section of memory and is thus
+- * used for a different purpose, regardless of the flags.
+- * - the pa of this page is not adjacent to the last inspected page
+- */
+- } else if (flag != st->current_flags || level != st->level ||
+- addr >= st->marker[1].start_address ||
+- pa != st->last_pa + PAGE_SIZE) {
+-
+- /* Check the PTE flags */
+- if (st->current_flags) {
+- dump_addr(st, addr);
+-
+- /* Dump all the flags */
+- if (pg_level[st->level].flag)
+- dump_flag_info(st, pg_level[st->level].flag,
+- st->current_flags,
+- pg_level[st->level].num);
+-
+- seq_putc(st->seq, '\n');
+- }
+-
+- /*
+- * Address indicates we have passed the end of the
+- * current section of virtual memory
+- */
+- while (addr >= st->marker[1].start_address) {
+- st->marker++;
+- seq_printf(st->seq, "---[ %s ]---\n", st->marker->name);
+- }
+- st->start_address = addr;
+- st->start_pa = pa;
+- st->last_pa = pa;
+- st->current_flags = flag;
+- st->level = level;
+- } else {
+- st->last_pa = pa;
+- }
+-}
+-
+-static void walk_pte(struct pg_state *st, pmd_t *pmd, unsigned long start)
+-{
+- pte_t *pte = pte_offset_kernel(pmd, 0);
+- unsigned long addr;
+- unsigned int i;
+-
+- for (i = 0; i < PTRS_PER_PTE; i++, pte++) {
+- addr = start + i * PAGE_SIZE;
+- note_page(st, addr, 4, pte_val(*pte));
+-
+- }
+-}
+-
+-static void walk_pmd(struct pg_state *st, pud_t *pud, unsigned long start)
+-{
+- pmd_t *pmd = pmd_offset(pud, 0);
+- unsigned long addr;
+- unsigned int i;
+-
+- for (i = 0; i < PTRS_PER_PMD; i++, pmd++) {
+- addr = start + i * PMD_SIZE;
+- if (!pmd_none(*pmd) && !pmd_huge(*pmd))
+- /* pmd exists */
+- walk_pte(st, pmd, addr);
+- else
+- note_page(st, addr, 3, pmd_val(*pmd));
+- }
+-}
+-
+-static void walk_pud(struct pg_state *st, pgd_t *pgd, unsigned long start)
+-{
+- pud_t *pud = pud_offset(pgd, 0);
+- unsigned long addr;
+- unsigned int i;
+-
+- for (i = 0; i < PTRS_PER_PUD; i++, pud++) {
+- addr = start + i * PUD_SIZE;
+- if (!pud_none(*pud) && !pud_huge(*pud))
+- /* pud exists */
+- walk_pmd(st, pud, addr);
+- else
+- note_page(st, addr, 2, pud_val(*pud));
+- }
+-}
+-
+-static void walk_pagetables(struct pg_state *st)
+-{
+- pgd_t *pgd = pgd_offset_k(0UL);
+- unsigned int i;
+- unsigned long addr;
+-
+- addr = st->start_address;
+-
+- /*
+- * Traverse the linux pagetable structure and dump pages that are in
+- * the hash pagetable.
+- */
+- for (i = 0; i < PTRS_PER_PGD; i++, pgd++, addr += PGDIR_SIZE) {
+- if (!pgd_none(*pgd) && !pgd_huge(*pgd))
+- /* pgd exists */
+- walk_pud(st, pgd, addr);
+- else
+- note_page(st, addr, 1, pgd_val(*pgd));
+- }
+-}
+-
+-static void populate_markers(void)
+-{
+- int i = 0;
+-
+- address_markers[i++].start_address = PAGE_OFFSET;
+- address_markers[i++].start_address = VMALLOC_START;
+- address_markers[i++].start_address = VMALLOC_END;
+-#ifdef CONFIG_PPC64
+- address_markers[i++].start_address = ISA_IO_BASE;
+- address_markers[i++].start_address = ISA_IO_END;
+- address_markers[i++].start_address = PHB_IO_BASE;
+- address_markers[i++].start_address = PHB_IO_END;
+- address_markers[i++].start_address = IOREMAP_BASE;
+- address_markers[i++].start_address = IOREMAP_END;
+-#ifdef CONFIG_PPC_BOOK3S_64
+- address_markers[i++].start_address = H_VMEMMAP_BASE;
+-#else
+- address_markers[i++].start_address = VMEMMAP_BASE;
+-#endif
+-#else /* !CONFIG_PPC64 */
+- address_markers[i++].start_address = ioremap_bot;
+- address_markers[i++].start_address = IOREMAP_TOP;
+-#ifdef CONFIG_NOT_COHERENT_CACHE
+- address_markers[i++].start_address = IOREMAP_TOP;
+- address_markers[i++].start_address = IOREMAP_TOP +
+- CONFIG_CONSISTENT_SIZE;
+-#endif
+-#ifdef CONFIG_HIGHMEM
+- address_markers[i++].start_address = PKMAP_BASE;
+- address_markers[i++].start_address = PKMAP_ADDR(LAST_PKMAP);
+-#endif
+- address_markers[i++].start_address = FIXADDR_START;
+- address_markers[i++].start_address = FIXADDR_TOP;
+-#endif /* CONFIG_PPC64 */
+-}
+-
+-static int ptdump_show(struct seq_file *m, void *v)
+-{
+- struct pg_state st = {
+- .seq = m,
+- .marker = address_markers,
+- };
+-
+- if (radix_enabled())
+- st.start_address = PAGE_OFFSET;
+- else
+- st.start_address = KERN_VIRT_START;
+-
+- /* Traverse kernel page tables */
+- walk_pagetables(&st);
+- note_page(&st, 0, 0, 0);
+- return 0;
+-}
+-
+-
+-static int ptdump_open(struct inode *inode, struct file *file)
+-{
+- return single_open(file, ptdump_show, NULL);
+-}
+-
+-static const struct file_operations ptdump_fops = {
+- .open = ptdump_open,
+- .read = seq_read,
+- .llseek = seq_lseek,
+- .release = single_release,
+-};
+-
+-static void build_pgtable_complete_mask(void)
+-{
+- unsigned int i, j;
+-
+- for (i = 0; i < ARRAY_SIZE(pg_level); i++)
+- if (pg_level[i].flag)
+- for (j = 0; j < pg_level[i].num; j++)
+- pg_level[i].mask |= pg_level[i].flag[j].mask;
+-}
+-
+-static int ptdump_init(void)
+-{
+- struct dentry *debugfs_file;
+-
+- populate_markers();
+- build_pgtable_complete_mask();
+- debugfs_file = debugfs_create_file("kernel_page_tables", 0400, NULL,
+- NULL, &ptdump_fops);
+- return debugfs_file ? 0 : -ENOMEM;
+-}
+-device_initcall(ptdump_init);
+diff --git a/arch/powerpc/mm/dump_linuxpagetables.h b/arch/powerpc/mm/dump_linuxpagetables.h
+deleted file mode 100644
+index 5d513636de73a..0000000000000
+--- a/arch/powerpc/mm/dump_linuxpagetables.h
++++ /dev/null
+@@ -1,19 +0,0 @@
+-/* SPDX-License-Identifier: GPL-2.0 */
+-#include <linux/types.h>
+-
+-struct flag_info {
+- u64 mask;
+- u64 val;
+- const char *set;
+- const char *clear;
+- bool is_val;
+- int shift;
+-};
+-
+-struct pgtable_level {
+- const struct flag_info *flag;
+- size_t num;
+- u64 mask;
+-};
+-
+-extern struct pgtable_level pg_level[5];
+diff --git a/arch/powerpc/mm/pgtable-radix.c b/arch/powerpc/mm/pgtable-radix.c
+index 9ee235fca4278..75cbedaac5d26 100644
+--- a/arch/powerpc/mm/pgtable-radix.c
++++ b/arch/powerpc/mm/pgtable-radix.c
+@@ -1041,8 +1041,8 @@ void radix__ptep_set_access_flags(struct vm_area_struct *vma, pte_t *ptep,
+ pte_t entry, unsigned long address, int psize)
+ {
+ struct mm_struct *mm = vma->vm_mm;
+- unsigned long set = pte_val(entry) & (_PAGE_DIRTY | _PAGE_ACCESSED |
+- _PAGE_RW | _PAGE_EXEC);
++ unsigned long set = pte_val(entry) & (_PAGE_DIRTY | _PAGE_SOFT_DIRTY |
++ _PAGE_ACCESSED | _PAGE_RW | _PAGE_EXEC);
+
+ unsigned long change = pte_val(entry) ^ pte_val(*ptep);
+ /*
+diff --git a/arch/powerpc/mm/ptdump/8xx.c b/arch/powerpc/mm/ptdump/8xx.c
+new file mode 100644
+index 0000000000000..80b4f73f7fdc2
+--- /dev/null
++++ b/arch/powerpc/mm/ptdump/8xx.c
+@@ -0,0 +1,82 @@
++// SPDX-License-Identifier: GPL-2.0
++/*
++ * From split of dump_linuxpagetables.c
++ * Copyright 2016, Rashmica Gupta, IBM Corp.
++ *
++ */
++#include <linux/kernel.h>
++#include <asm/pgtable.h>
++
++#include "ptdump.h"
++
++static const struct flag_info flag_array[] = {
++ {
++ .mask = _PAGE_PRIVILEGED,
++ .val = 0,
++ .set = "user",
++ .clear = " ",
++ }, {
++ .mask = _PAGE_RO | _PAGE_NA,
++ .val = 0,
++ .set = "rw",
++ }, {
++ .mask = _PAGE_RO | _PAGE_NA,
++ .val = _PAGE_RO,
++ .set = "r ",
++ }, {
++ .mask = _PAGE_RO | _PAGE_NA,
++ .val = _PAGE_NA,
++ .set = " ",
++ }, {
++ .mask = _PAGE_EXEC,
++ .val = _PAGE_EXEC,
++ .set = " X ",
++ .clear = " ",
++ }, {
++ .mask = _PAGE_PRESENT,
++ .val = _PAGE_PRESENT,
++ .set = "present",
++ .clear = " ",
++ }, {
++ .mask = _PAGE_GUARDED,
++ .val = _PAGE_GUARDED,
++ .set = "guarded",
++ .clear = " ",
++ }, {
++ .mask = _PAGE_DIRTY,
++ .val = _PAGE_DIRTY,
++ .set = "dirty",
++ .clear = " ",
++ }, {
++ .mask = _PAGE_ACCESSED,
++ .val = _PAGE_ACCESSED,
++ .set = "accessed",
++ .clear = " ",
++ }, {
++ .mask = _PAGE_NO_CACHE,
++ .val = _PAGE_NO_CACHE,
++ .set = "no cache",
++ .clear = " ",
++ }, {
++ .mask = _PAGE_SPECIAL,
++ .val = _PAGE_SPECIAL,
++ .set = "special",
++ }
++};
++
++struct pgtable_level pg_level[5] = {
++ {
++ }, { /* pgd */
++ .flag = flag_array,
++ .num = ARRAY_SIZE(flag_array),
++ }, { /* pud */
++ .flag = flag_array,
++ .num = ARRAY_SIZE(flag_array),
++ }, { /* pmd */
++ .flag = flag_array,
++ .num = ARRAY_SIZE(flag_array),
++ }, { /* pte */
++ .flag = flag_array,
++ .num = ARRAY_SIZE(flag_array),
++ },
++};
+diff --git a/arch/powerpc/mm/ptdump/Makefile b/arch/powerpc/mm/ptdump/Makefile
+new file mode 100644
+index 0000000000000..712762be3cb11
+--- /dev/null
++++ b/arch/powerpc/mm/ptdump/Makefile
+@@ -0,0 +1,9 @@
++# SPDX-License-Identifier: GPL-2.0
++
++obj-y += ptdump.o
++
++obj-$(CONFIG_4xx) += shared.o
++obj-$(CONFIG_PPC_8xx) += 8xx.o
++obj-$(CONFIG_PPC_BOOK3E_MMU) += shared.o
++obj-$(CONFIG_PPC_BOOK3S_32) += shared.o bats.o segment_regs.o
++obj-$(CONFIG_PPC_BOOK3S_64) += book3s64.o hashpagetable.o
+diff --git a/arch/powerpc/mm/ptdump/bats.c b/arch/powerpc/mm/ptdump/bats.c
+new file mode 100644
+index 0000000000000..a0d23e96e841a
+--- /dev/null
++++ b/arch/powerpc/mm/ptdump/bats.c
+@@ -0,0 +1,173 @@
++// SPDX-License-Identifier: GPL-2.0+
++/*
++ * Copyright 2018, Christophe Leroy CS S.I.
++ * <christophe.leroy@c-s.fr>
++ *
++ * This dumps the content of BATS
++ */
++
++#include <asm/debugfs.h>
++#include <asm/pgtable.h>
++#include <asm/cpu_has_feature.h>
++
++static char *pp_601(int k, int pp)
++{
++ if (pp == 0)
++ return k ? "NA" : "RWX";
++ if (pp == 1)
++ return k ? "ROX" : "RWX";
++ if (pp == 2)
++ return k ? "RWX" : "RWX";
++ return k ? "ROX" : "ROX";
++}
++
++static void bat_show_601(struct seq_file *m, int idx, u32 lower, u32 upper)
++{
++ u32 blpi = upper & 0xfffe0000;
++ u32 k = (upper >> 2) & 3;
++ u32 pp = upper & 3;
++ phys_addr_t pbn = PHYS_BAT_ADDR(lower);
++ u32 bsm = lower & 0x3ff;
++ u32 size = (bsm + 1) << 17;
++
++ seq_printf(m, "%d: ", idx);
++ if (!(lower & 0x40)) {
++ seq_puts(m, " -\n");
++ return;
++ }
++
++ seq_printf(m, "0x%08x-0x%08x ", blpi, blpi + size - 1);
++#ifdef CONFIG_PHYS_64BIT
++ seq_printf(m, "0x%016llx ", pbn);
++#else
++ seq_printf(m, "0x%08x ", pbn);
++#endif
++
++ seq_printf(m, "Kernel %s User %s", pp_601(k & 2, pp), pp_601(k & 1, pp));
++
++ if (lower & _PAGE_WRITETHRU)
++ seq_puts(m, "write through ");
++ if (lower & _PAGE_NO_CACHE)
++ seq_puts(m, "no cache ");
++ if (lower & _PAGE_COHERENT)
++ seq_puts(m, "coherent ");
++ seq_puts(m, "\n");
++}
++
++#define BAT_SHOW_601(_m, _n, _l, _u) bat_show_601(_m, _n, mfspr(_l), mfspr(_u))
++
++static int bats_show_601(struct seq_file *m, void *v)
++{
++ seq_puts(m, "---[ Block Address Translation ]---\n");
++
++ BAT_SHOW_601(m, 0, SPRN_IBAT0L, SPRN_IBAT0U);
++ BAT_SHOW_601(m, 1, SPRN_IBAT1L, SPRN_IBAT1U);
++ BAT_SHOW_601(m, 2, SPRN_IBAT2L, SPRN_IBAT2U);
++ BAT_SHOW_601(m, 3, SPRN_IBAT3L, SPRN_IBAT3U);
++
++ return 0;
++}
++
++static void bat_show_603(struct seq_file *m, int idx, u32 lower, u32 upper, bool is_d)
++{
++ u32 bepi = upper & 0xfffe0000;
++ u32 bl = (upper >> 2) & 0x7ff;
++ u32 k = upper & 3;
++ phys_addr_t brpn = PHYS_BAT_ADDR(lower);
++ u32 size = (bl + 1) << 17;
++
++ seq_printf(m, "%d: ", idx);
++ if (k == 0) {
++ seq_puts(m, " -\n");
++ return;
++ }
++
++ seq_printf(m, "0x%08x-0x%08x ", bepi, bepi + size - 1);
++#ifdef CONFIG_PHYS_64BIT
++ seq_printf(m, "0x%016llx ", brpn);
++#else
++ seq_printf(m, "0x%08x ", brpn);
++#endif
++
++ if (k == 1)
++ seq_puts(m, "User ");
++ else if (k == 2)
++ seq_puts(m, "Kernel ");
++ else
++ seq_puts(m, "Kernel/User ");
++
++ if (lower & BPP_RX)
++ seq_puts(m, is_d ? "RO " : "EXEC ");
++ else if (lower & BPP_RW)
++ seq_puts(m, is_d ? "RW " : "EXEC ");
++ else
++ seq_puts(m, is_d ? "NA " : "NX ");
++
++ if (lower & _PAGE_WRITETHRU)
++ seq_puts(m, "write through ");
++ if (lower & _PAGE_NO_CACHE)
++ seq_puts(m, "no cache ");
++ if (lower & _PAGE_COHERENT)
++ seq_puts(m, "coherent ");
++ if (lower & _PAGE_GUARDED)
++ seq_puts(m, "guarded ");
++ seq_puts(m, "\n");
++}
++
++#define BAT_SHOW_603(_m, _n, _l, _u, _d) bat_show_603(_m, _n, mfspr(_l), mfspr(_u), _d)
++
++static int bats_show_603(struct seq_file *m, void *v)
++{
++ seq_puts(m, "---[ Instruction Block Address Translation ]---\n");
++
++ BAT_SHOW_603(m, 0, SPRN_IBAT0L, SPRN_IBAT0U, false);
++ BAT_SHOW_603(m, 1, SPRN_IBAT1L, SPRN_IBAT1U, false);
++ BAT_SHOW_603(m, 2, SPRN_IBAT2L, SPRN_IBAT2U, false);
++ BAT_SHOW_603(m, 3, SPRN_IBAT3L, SPRN_IBAT3U, false);
++ if (mmu_has_feature(MMU_FTR_USE_HIGH_BATS)) {
++ BAT_SHOW_603(m, 4, SPRN_IBAT4L, SPRN_IBAT4U, false);
++ BAT_SHOW_603(m, 5, SPRN_IBAT5L, SPRN_IBAT5U, false);
++ BAT_SHOW_603(m, 6, SPRN_IBAT6L, SPRN_IBAT6U, false);
++ BAT_SHOW_603(m, 7, SPRN_IBAT7L, SPRN_IBAT7U, false);
++ }
++
++ seq_puts(m, "\n---[ Data Block Address Translation ]---\n");
++
++ BAT_SHOW_603(m, 0, SPRN_DBAT0L, SPRN_DBAT0U, true);
++ BAT_SHOW_603(m, 1, SPRN_DBAT1L, SPRN_DBAT1U, true);
++ BAT_SHOW_603(m, 2, SPRN_DBAT2L, SPRN_DBAT2U, true);
++ BAT_SHOW_603(m, 3, SPRN_DBAT3L, SPRN_DBAT3U, true);
++ if (mmu_has_feature(MMU_FTR_USE_HIGH_BATS)) {
++ BAT_SHOW_603(m, 4, SPRN_DBAT4L, SPRN_DBAT4U, true);
++ BAT_SHOW_603(m, 5, SPRN_DBAT5L, SPRN_DBAT5U, true);
++ BAT_SHOW_603(m, 6, SPRN_DBAT6L, SPRN_DBAT6U, true);
++ BAT_SHOW_603(m, 7, SPRN_DBAT7L, SPRN_DBAT7U, true);
++ }
++
++ return 0;
++}
++
++static int bats_open(struct inode *inode, struct file *file)
++{
++ if (cpu_has_feature(CPU_FTR_601))
++ return single_open(file, bats_show_601, NULL);
++
++ return single_open(file, bats_show_603, NULL);
++}
++
++static const struct file_operations bats_fops = {
++ .open = bats_open,
++ .read = seq_read,
++ .llseek = seq_lseek,
++ .release = single_release,
++};
++
++static int __init bats_init(void)
++{
++ struct dentry *debugfs_file;
++
++ debugfs_file = debugfs_create_file("block_address_translation", 0400,
++ powerpc_debugfs_root, NULL, &bats_fops);
++ return debugfs_file ? 0 : -ENOMEM;
++}
++device_initcall(bats_init);
+diff --git a/arch/powerpc/mm/ptdump/book3s64.c b/arch/powerpc/mm/ptdump/book3s64.c
+new file mode 100644
+index 0000000000000..0bce5b85d0112
+--- /dev/null
++++ b/arch/powerpc/mm/ptdump/book3s64.c
+@@ -0,0 +1,115 @@
++// SPDX-License-Identifier: GPL-2.0
++/*
++ * From split of dump_linuxpagetables.c
++ * Copyright 2016, Rashmica Gupta, IBM Corp.
++ *
++ */
++#include <linux/kernel.h>
++#include <asm/pgtable.h>
++
++#include "ptdump.h"
++
++static const struct flag_info flag_array[] = {
++ {
++ .mask = _PAGE_PRIVILEGED,
++ .val = 0,
++ .set = "user",
++ .clear = " ",
++ }, {
++ .mask = _PAGE_READ,
++ .val = _PAGE_READ,
++ .set = "r",
++ .clear = " ",
++ }, {
++ .mask = _PAGE_WRITE,
++ .val = _PAGE_WRITE,
++ .set = "w",
++ .clear = " ",
++ }, {
++ .mask = _PAGE_EXEC,
++ .val = _PAGE_EXEC,
++ .set = " X ",
++ .clear = " ",
++ }, {
++ .mask = _PAGE_PTE,
++ .val = _PAGE_PTE,
++ .set = "pte",
++ .clear = " ",
++ }, {
++ .mask = _PAGE_PRESENT,
++ .val = _PAGE_PRESENT,
++ .set = "present",
++ .clear = " ",
++ }, {
++ .mask = H_PAGE_HASHPTE,
++ .val = H_PAGE_HASHPTE,
++ .set = "hpte",
++ .clear = " ",
++ }, {
++ .mask = _PAGE_DIRTY,
++ .val = _PAGE_DIRTY,
++ .set = "dirty",
++ .clear = " ",
++ }, {
++ .mask = _PAGE_ACCESSED,
++ .val = _PAGE_ACCESSED,
++ .set = "accessed",
++ .clear = " ",
++ }, {
++ .mask = _PAGE_NON_IDEMPOTENT,
++ .val = _PAGE_NON_IDEMPOTENT,
++ .set = "non-idempotent",
++ .clear = " ",
++ }, {
++ .mask = _PAGE_TOLERANT,
++ .val = _PAGE_TOLERANT,
++ .set = "tolerant",
++ .clear = " ",
++ }, {
++ .mask = H_PAGE_BUSY,
++ .val = H_PAGE_BUSY,
++ .set = "busy",
++ }, {
++#ifdef CONFIG_PPC_64K_PAGES
++ .mask = H_PAGE_COMBO,
++ .val = H_PAGE_COMBO,
++ .set = "combo",
++ }, {
++ .mask = H_PAGE_4K_PFN,
++ .val = H_PAGE_4K_PFN,
++ .set = "4K_pfn",
++ }, {
++#else /* CONFIG_PPC_64K_PAGES */
++ .mask = H_PAGE_F_GIX,
++ .val = H_PAGE_F_GIX,
++ .set = "f_gix",
++ .is_val = true,
++ .shift = H_PAGE_F_GIX_SHIFT,
++ }, {
++ .mask = H_PAGE_F_SECOND,
++ .val = H_PAGE_F_SECOND,
++ .set = "f_second",
++ }, {
++#endif /* CONFIG_PPC_64K_PAGES */
++ .mask = _PAGE_SPECIAL,
++ .val = _PAGE_SPECIAL,
++ .set = "special",
++ }
++};
++
++struct pgtable_level pg_level[5] = {
++ {
++ }, { /* pgd */
++ .flag = flag_array,
++ .num = ARRAY_SIZE(flag_array),
++ }, { /* pud */
++ .flag = flag_array,
++ .num = ARRAY_SIZE(flag_array),
++ }, { /* pmd */
++ .flag = flag_array,
++ .num = ARRAY_SIZE(flag_array),
++ }, { /* pte */
++ .flag = flag_array,
++ .num = ARRAY_SIZE(flag_array),
++ },
++};
+diff --git a/arch/powerpc/mm/ptdump/hashpagetable.c b/arch/powerpc/mm/ptdump/hashpagetable.c
+new file mode 100644
+index 0000000000000..b430e4e08af69
+--- /dev/null
++++ b/arch/powerpc/mm/ptdump/hashpagetable.c
+@@ -0,0 +1,550 @@
++/*
++ * Copyright 2016, Rashmica Gupta, IBM Corp.
++ *
++ * This traverses the kernel virtual memory and dumps the pages that are in
++ * the hash pagetable, along with their flags to
++ * /sys/kernel/debug/kernel_hash_pagetable.
++ *
++ * If radix is enabled then there is no hash page table and so no debugfs file
++ * is generated.
++ *
++ * This program is free software; you can redistribute it and/or
++ * modify it under the terms of the GNU General Public License
++ * as published by the Free Software Foundation; version 2
++ * of the License.
++ */
++#include <linux/debugfs.h>
++#include <linux/fs.h>
++#include <linux/io.h>
++#include <linux/mm.h>
++#include <linux/sched.h>
++#include <linux/seq_file.h>
++#include <asm/pgtable.h>
++#include <linux/const.h>
++#include <asm/page.h>
++#include <asm/pgalloc.h>
++#include <asm/plpar_wrappers.h>
++#include <linux/memblock.h>
++#include <asm/firmware.h>
++
++struct pg_state {
++ struct seq_file *seq;
++ const struct addr_marker *marker;
++ unsigned long start_address;
++ unsigned int level;
++ u64 current_flags;
++};
++
++struct addr_marker {
++ unsigned long start_address;
++ const char *name;
++};
++
++static struct addr_marker address_markers[] = {
++ { 0, "Start of kernel VM" },
++ { 0, "vmalloc() Area" },
++ { 0, "vmalloc() End" },
++ { 0, "isa I/O start" },
++ { 0, "isa I/O end" },
++ { 0, "phb I/O start" },
++ { 0, "phb I/O end" },
++ { 0, "I/O remap start" },
++ { 0, "I/O remap end" },
++ { 0, "vmemmap start" },
++ { -1, NULL },
++};
++
++struct flag_info {
++ u64 mask;
++ u64 val;
++ const char *set;
++ const char *clear;
++ bool is_val;
++ int shift;
++};
++
++static const struct flag_info v_flag_array[] = {
++ {
++ .mask = SLB_VSID_B,
++ .val = SLB_VSID_B_256M,
++ .set = "ssize: 256M",
++ .clear = "ssize: 1T ",
++ }, {
++ .mask = HPTE_V_SECONDARY,
++ .val = HPTE_V_SECONDARY,
++ .set = "secondary",
++ .clear = "primary ",
++ }, {
++ .mask = HPTE_V_VALID,
++ .val = HPTE_V_VALID,
++ .set = "valid ",
++ .clear = "invalid",
++ }, {
++ .mask = HPTE_V_BOLTED,
++ .val = HPTE_V_BOLTED,
++ .set = "bolted",
++ .clear = "",
++ }
++};
++
++static const struct flag_info r_flag_array[] = {
++ {
++ .mask = HPTE_R_PP0 | HPTE_R_PP,
++ .val = PP_RWXX,
++ .set = "prot:RW--",
++ }, {
++ .mask = HPTE_R_PP0 | HPTE_R_PP,
++ .val = PP_RWRX,
++ .set = "prot:RWR-",
++ }, {
++ .mask = HPTE_R_PP0 | HPTE_R_PP,
++ .val = PP_RWRW,
++ .set = "prot:RWRW",
++ }, {
++ .mask = HPTE_R_PP0 | HPTE_R_PP,
++ .val = PP_RXRX,
++ .set = "prot:R-R-",
++ }, {
++ .mask = HPTE_R_PP0 | HPTE_R_PP,
++ .val = PP_RXXX,
++ .set = "prot:R---",
++ }, {
++ .mask = HPTE_R_KEY_HI | HPTE_R_KEY_LO,
++ .val = HPTE_R_KEY_HI | HPTE_R_KEY_LO,
++ .set = "key",
++ .clear = "",
++ .is_val = true,
++ }, {
++ .mask = HPTE_R_R,
++ .val = HPTE_R_R,
++ .set = "ref",
++ .clear = " ",
++ }, {
++ .mask = HPTE_R_C,
++ .val = HPTE_R_C,
++ .set = "changed",
++ .clear = " ",
++ }, {
++ .mask = HPTE_R_N,
++ .val = HPTE_R_N,
++ .set = "no execute",
++ }, {
++ .mask = HPTE_R_WIMG,
++ .val = HPTE_R_W,
++ .set = "writethru",
++ }, {
++ .mask = HPTE_R_WIMG,
++ .val = HPTE_R_I,
++ .set = "no cache",
++ }, {
++ .mask = HPTE_R_WIMG,
++ .val = HPTE_R_G,
++ .set = "guarded",
++ }
++};
++
++static int calculate_pagesize(struct pg_state *st, int ps, char s[])
++{
++ static const char units[] = "BKMGTPE";
++ const char *unit = units;
++
++ while (ps > 9 && unit[1]) {
++ ps -= 10;
++ unit++;
++ }
++ seq_printf(st->seq, " %s_ps: %i%c\t", s, 1<<ps, *unit);
++ return ps;
++}
++
++static void dump_flag_info(struct pg_state *st, const struct flag_info
++ *flag, u64 pte, int num)
++{
++ unsigned int i;
++
++ for (i = 0; i < num; i++, flag++) {
++ const char *s = NULL;
++ u64 val;
++
++ /* flag not defined so don't check it */
++ if (flag->mask == 0)
++ continue;
++ /* Some 'flags' are actually values */
++ if (flag->is_val) {
++ val = pte & flag->val;
++ if (flag->shift)
++ val = val >> flag->shift;
++ seq_printf(st->seq, " %s:%llx", flag->set, val);
++ } else {
++ if ((pte & flag->mask) == flag->val)
++ s = flag->set;
++ else
++ s = flag->clear;
++ if (s)
++ seq_printf(st->seq, " %s", s);
++ }
++ }
++}
++
++static void dump_hpte_info(struct pg_state *st, unsigned long ea, u64 v, u64 r,
++ unsigned long rpn, int bps, int aps, unsigned long lp)
++{
++ int aps_index;
++
++ while (ea >= st->marker[1].start_address) {
++ st->marker++;
++ seq_printf(st->seq, "---[ %s ]---\n", st->marker->name);
++ }
++ seq_printf(st->seq, "0x%lx:\t", ea);
++ seq_printf(st->seq, "AVPN:%llx\t", HPTE_V_AVPN_VAL(v));
++ dump_flag_info(st, v_flag_array, v, ARRAY_SIZE(v_flag_array));
++ seq_printf(st->seq, " rpn: %lx\t", rpn);
++ dump_flag_info(st, r_flag_array, r, ARRAY_SIZE(r_flag_array));
++
++ calculate_pagesize(st, bps, "base");
++ aps_index = calculate_pagesize(st, aps, "actual");
++ if (aps_index != 2)
++ seq_printf(st->seq, "LP enc: %lx", lp);
++ seq_putc(st->seq, '\n');
++}
++
++
++static int native_find(unsigned long ea, int psize, bool primary, u64 *v, u64
++ *r)
++{
++ struct hash_pte *hptep;
++ unsigned long hash, vsid, vpn, hpte_group, want_v, hpte_v;
++ int i, ssize = mmu_kernel_ssize;
++ unsigned long shift = mmu_psize_defs[psize].shift;
++
++ /* calculate hash */
++ vsid = get_kernel_vsid(ea, ssize);
++ vpn = hpt_vpn(ea, vsid, ssize);
++ hash = hpt_hash(vpn, shift, ssize);
++ want_v = hpte_encode_avpn(vpn, psize, ssize);
++
++ /* to check in the secondary hash table, we invert the hash */
++ if (!primary)
++ hash = ~hash;
++ hpte_group = (hash & htab_hash_mask) * HPTES_PER_GROUP;
++ for (i = 0; i < HPTES_PER_GROUP; i++) {
++ hptep = htab_address + hpte_group;
++ hpte_v = be64_to_cpu(hptep->v);
++
++ if (HPTE_V_COMPARE(hpte_v, want_v) && (hpte_v & HPTE_V_VALID)) {
++ /* HPTE matches */
++ *v = be64_to_cpu(hptep->v);
++ *r = be64_to_cpu(hptep->r);
++ return 0;
++ }
++ ++hpte_group;
++ }
++ return -1;
++}
++
++#ifdef CONFIG_PPC_PSERIES
++static int pseries_find(unsigned long ea, int psize, bool primary, u64 *v, u64 *r)
++{
++ struct hash_pte ptes[4];
++ unsigned long vsid, vpn, hash, hpte_group, want_v;
++ int i, j, ssize = mmu_kernel_ssize;
++ long lpar_rc = 0;
++ unsigned long shift = mmu_psize_defs[psize].shift;
++
++ /* calculate hash */
++ vsid = get_kernel_vsid(ea, ssize);
++ vpn = hpt_vpn(ea, vsid, ssize);
++ hash = hpt_hash(vpn, shift, ssize);
++ want_v = hpte_encode_avpn(vpn, psize, ssize);
++
++ /* to check in the secondary hash table, we invert the hash */
++ if (!primary)
++ hash = ~hash;
++ hpte_group = (hash & htab_hash_mask) * HPTES_PER_GROUP;
++ /* see if we can find an entry in the hpte with this hash */
++ for (i = 0; i < HPTES_PER_GROUP; i += 4, hpte_group += 4) {
++ lpar_rc = plpar_pte_read_4(0, hpte_group, (void *)ptes);
++
++ if (lpar_rc != H_SUCCESS)
++ continue;
++ for (j = 0; j < 4; j++) {
++ if (HPTE_V_COMPARE(ptes[j].v, want_v) &&
++ (ptes[j].v & HPTE_V_VALID)) {
++ /* HPTE matches */
++ *v = ptes[j].v;
++ *r = ptes[j].r;
++ return 0;
++ }
++ }
++ }
++ return -1;
++}
++#endif
++
++static void decode_r(int bps, unsigned long r, unsigned long *rpn, int *aps,
++ unsigned long *lp_bits)
++{
++ struct mmu_psize_def entry;
++ unsigned long arpn, mask, lp;
++ int penc = -2, idx = 0, shift;
++
++ /*.
++ * The LP field has 8 bits. Depending on the actual page size, some of
++ * these bits are concatenated with the APRN to get the RPN. The rest
++ * of the bits in the LP field is the LP value and is an encoding for
++ * the base page size and the actual page size.
++ *
++ * - find the mmu entry for our base page size
++ * - go through all page encodings and use the associated mask to
++ * find an encoding that matches our encoding in the LP field.
++ */
++ arpn = (r & HPTE_R_RPN) >> HPTE_R_RPN_SHIFT;
++ lp = arpn & 0xff;
++
++ entry = mmu_psize_defs[bps];
++ while (idx < MMU_PAGE_COUNT) {
++ penc = entry.penc[idx];
++ if ((penc != -1) && (mmu_psize_defs[idx].shift)) {
++ shift = mmu_psize_defs[idx].shift - HPTE_R_RPN_SHIFT;
++ mask = (0x1 << (shift)) - 1;
++ if ((lp & mask) == penc) {
++ *aps = mmu_psize_to_shift(idx);
++ *lp_bits = lp & mask;
++ *rpn = arpn >> shift;
++ return;
++ }
++ }
++ idx++;
++ }
++}
++
++static int base_hpte_find(unsigned long ea, int psize, bool primary, u64 *v,
++ u64 *r)
++{
++#ifdef CONFIG_PPC_PSERIES
++ if (firmware_has_feature(FW_FEATURE_LPAR))
++ return pseries_find(ea, psize, primary, v, r);
++#endif
++ return native_find(ea, psize, primary, v, r);
++}
++
++static unsigned long hpte_find(struct pg_state *st, unsigned long ea, int psize)
++{
++ unsigned long slot;
++ u64 v = 0, r = 0;
++ unsigned long rpn, lp_bits;
++ int base_psize = 0, actual_psize = 0;
++
++ if (ea < PAGE_OFFSET)
++ return -1;
++
++ /* Look in primary table */
++ slot = base_hpte_find(ea, psize, true, &v, &r);
++
++ /* Look in secondary table */
++ if (slot == -1)
++ slot = base_hpte_find(ea, psize, false, &v, &r);
++
++ /* No entry found */
++ if (slot == -1)
++ return -1;
++
++ /*
++ * We found an entry in the hash page table:
++ * - check that this has the same base page
++ * - find the actual page size
++ * - find the RPN
++ */
++ base_psize = mmu_psize_to_shift(psize);
++
++ if ((v & HPTE_V_LARGE) == HPTE_V_LARGE) {
++ decode_r(psize, r, &rpn, &actual_psize, &lp_bits);
++ } else {
++ /* 4K actual page size */
++ actual_psize = 12;
++ rpn = (r & HPTE_R_RPN) >> HPTE_R_RPN_SHIFT;
++ /* In this case there are no LP bits */
++ lp_bits = -1;
++ }
++ /*
++ * We didn't find a matching encoding, so the PTE we found isn't for
++ * this address.
++ */
++ if (actual_psize == -1)
++ return -1;
++
++ dump_hpte_info(st, ea, v, r, rpn, base_psize, actual_psize, lp_bits);
++ return 0;
++}
++
++static void walk_pte(struct pg_state *st, pmd_t *pmd, unsigned long start)
++{
++ pte_t *pte = pte_offset_kernel(pmd, 0);
++ unsigned long addr, pteval, psize;
++ int i, status;
++
++ for (i = 0; i < PTRS_PER_PTE; i++, pte++) {
++ addr = start + i * PAGE_SIZE;
++ pteval = pte_val(*pte);
++
++ if (addr < VMALLOC_END)
++ psize = mmu_vmalloc_psize;
++ else
++ psize = mmu_io_psize;
++#ifdef CONFIG_PPC_64K_PAGES
++ /* check for secret 4K mappings */
++ if (((pteval & H_PAGE_COMBO) == H_PAGE_COMBO) ||
++ ((pteval & H_PAGE_4K_PFN) == H_PAGE_4K_PFN))
++ psize = mmu_io_psize;
++#endif
++ /* check for hashpte */
++ status = hpte_find(st, addr, psize);
++
++ if (((pteval & H_PAGE_HASHPTE) != H_PAGE_HASHPTE)
++ && (status != -1)) {
++ /* found a hpte that is not in the linux page tables */
++ seq_printf(st->seq, "page probably bolted before linux"
++ " pagetables were set: addr:%lx, pteval:%lx\n",
++ addr, pteval);
++ }
++ }
++}
++
++static void walk_pmd(struct pg_state *st, pud_t *pud, unsigned long start)
++{
++ pmd_t *pmd = pmd_offset(pud, 0);
++ unsigned long addr;
++ unsigned int i;
++
++ for (i = 0; i < PTRS_PER_PMD; i++, pmd++) {
++ addr = start + i * PMD_SIZE;
++ if (!pmd_none(*pmd))
++ /* pmd exists */
++ walk_pte(st, pmd, addr);
++ }
++}
++
++static void walk_pud(struct pg_state *st, pgd_t *pgd, unsigned long start)
++{
++ pud_t *pud = pud_offset(pgd, 0);
++ unsigned long addr;
++ unsigned int i;
++
++ for (i = 0; i < PTRS_PER_PUD; i++, pud++) {
++ addr = start + i * PUD_SIZE;
++ if (!pud_none(*pud))
++ /* pud exists */
++ walk_pmd(st, pud, addr);
++ }
++}
++
++static void walk_pagetables(struct pg_state *st)
++{
++ pgd_t *pgd = pgd_offset_k(0UL);
++ unsigned int i;
++ unsigned long addr;
++
++ /*
++ * Traverse the linux pagetable structure and dump pages that are in
++ * the hash pagetable.
++ */
++ for (i = 0; i < PTRS_PER_PGD; i++, pgd++) {
++ addr = KERN_VIRT_START + i * PGDIR_SIZE;
++ if (!pgd_none(*pgd))
++ /* pgd exists */
++ walk_pud(st, pgd, addr);
++ }
++}
++
++
++static void walk_linearmapping(struct pg_state *st)
++{
++ unsigned long addr;
++
++ /*
++ * Traverse the linear mapping section of virtual memory and dump pages
++ * that are in the hash pagetable.
++ */
++ unsigned long psize = 1 << mmu_psize_defs[mmu_linear_psize].shift;
++
++ for (addr = PAGE_OFFSET; addr < PAGE_OFFSET +
++ memblock_end_of_DRAM(); addr += psize)
++ hpte_find(st, addr, mmu_linear_psize);
++}
++
++static void walk_vmemmap(struct pg_state *st)
++{
++#ifdef CONFIG_SPARSEMEM_VMEMMAP
++ struct vmemmap_backing *ptr = vmemmap_list;
++
++ /*
++ * Traverse the vmemmaped memory and dump pages that are in the hash
++ * pagetable.
++ */
++ while (ptr->list) {
++ hpte_find(st, ptr->virt_addr, mmu_vmemmap_psize);
++ ptr = ptr->list;
++ }
++ seq_puts(st->seq, "---[ vmemmap end ]---\n");
++#endif
++}
++
++static void populate_markers(void)
++{
++ address_markers[0].start_address = PAGE_OFFSET;
++ address_markers[1].start_address = VMALLOC_START;
++ address_markers[2].start_address = VMALLOC_END;
++ address_markers[3].start_address = ISA_IO_BASE;
++ address_markers[4].start_address = ISA_IO_END;
++ address_markers[5].start_address = PHB_IO_BASE;
++ address_markers[6].start_address = PHB_IO_END;
++ address_markers[7].start_address = IOREMAP_BASE;
++ address_markers[8].start_address = IOREMAP_END;
++#ifdef CONFIG_PPC_BOOK3S_64
++ address_markers[9].start_address = H_VMEMMAP_BASE;
++#else
++ address_markers[9].start_address = VMEMMAP_BASE;
++#endif
++}
++
++static int ptdump_show(struct seq_file *m, void *v)
++{
++ struct pg_state st = {
++ .seq = m,
++ .start_address = PAGE_OFFSET,
++ .marker = address_markers,
++ };
++ /*
++ * Traverse the 0xc, 0xd and 0xf areas of the kernel virtual memory and
++ * dump pages that are in the hash pagetable.
++ */
++ walk_linearmapping(&st);
++ walk_pagetables(&st);
++ walk_vmemmap(&st);
++ return 0;
++}
++
++static int ptdump_open(struct inode *inode, struct file *file)
++{
++ return single_open(file, ptdump_show, NULL);
++}
++
++static const struct file_operations ptdump_fops = {
++ .open = ptdump_open,
++ .read = seq_read,
++ .llseek = seq_lseek,
++ .release = single_release,
++};
++
++static int ptdump_init(void)
++{
++ struct dentry *debugfs_file;
++
++ if (!radix_enabled()) {
++ populate_markers();
++ debugfs_file = debugfs_create_file("kernel_hash_pagetable",
++ 0400, NULL, NULL, &ptdump_fops);
++ return debugfs_file ? 0 : -ENOMEM;
++ }
++ return 0;
++}
++device_initcall(ptdump_init);
+diff --git a/arch/powerpc/mm/ptdump/ptdump.c b/arch/powerpc/mm/ptdump/ptdump.c
+new file mode 100644
+index 0000000000000..76be98988578d
+--- /dev/null
++++ b/arch/powerpc/mm/ptdump/ptdump.c
+@@ -0,0 +1,373 @@
++/*
++ * Copyright 2016, Rashmica Gupta, IBM Corp.
++ *
++ * This traverses the kernel pagetables and dumps the
++ * information about the used sections of memory to
++ * /sys/kernel/debug/kernel_pagetables.
++ *
++ * Derived from the arm64 implementation:
++ * Copyright (c) 2014, The Linux Foundation, Laura Abbott.
++ * (C) Copyright 2008 Intel Corporation, Arjan van de Ven.
++ *
++ * This program is free software; you can redistribute it and/or
++ * modify it under the terms of the GNU General Public License
++ * as published by the Free Software Foundation; version 2
++ * of the License.
++ */
++#include <linux/debugfs.h>
++#include <linux/fs.h>
++#include <linux/hugetlb.h>
++#include <linux/io.h>
++#include <linux/mm.h>
++#include <linux/highmem.h>
++#include <linux/sched.h>
++#include <linux/seq_file.h>
++#include <asm/fixmap.h>
++#include <asm/pgtable.h>
++#include <linux/const.h>
++#include <asm/page.h>
++#include <asm/pgalloc.h>
++
++#include "ptdump.h"
++
++#ifdef CONFIG_PPC32
++#define KERN_VIRT_START 0
++#endif
++
++/*
++ * To visualise what is happening,
++ *
++ * - PTRS_PER_P** = how many entries there are in the corresponding P**
++ * - P**_SHIFT = how many bits of the address we use to index into the
++ * corresponding P**
++ * - P**_SIZE is how much memory we can access through the table - not the
++ * size of the table itself.
++ * P**={PGD, PUD, PMD, PTE}
++ *
++ *
++ * Each entry of the PGD points to a PUD. Each entry of a PUD points to a
++ * PMD. Each entry of a PMD points to a PTE. And every PTE entry points to
++ * a page.
++ *
++ * In the case where there are only 3 levels, the PUD is folded into the
++ * PGD: every PUD has only one entry which points to the PMD.
++ *
++ * The page dumper groups page table entries of the same type into a single
++ * description. It uses pg_state to track the range information while
++ * iterating over the PTE entries. When the continuity is broken it then
++ * dumps out a description of the range - ie PTEs that are virtually contiguous
++ * with the same PTE flags are chunked together. This is to make it clear how
++ * different areas of the kernel virtual memory are used.
++ *
++ */
++struct pg_state {
++ struct seq_file *seq;
++ const struct addr_marker *marker;
++ unsigned long start_address;
++ unsigned long start_pa;
++ unsigned long last_pa;
++ unsigned int level;
++ u64 current_flags;
++};
++
++struct addr_marker {
++ unsigned long start_address;
++ const char *name;
++};
++
++static struct addr_marker address_markers[] = {
++ { 0, "Start of kernel VM" },
++ { 0, "vmalloc() Area" },
++ { 0, "vmalloc() End" },
++#ifdef CONFIG_PPC64
++ { 0, "isa I/O start" },
++ { 0, "isa I/O end" },
++ { 0, "phb I/O start" },
++ { 0, "phb I/O end" },
++ { 0, "I/O remap start" },
++ { 0, "I/O remap end" },
++ { 0, "vmemmap start" },
++#else
++ { 0, "Early I/O remap start" },
++ { 0, "Early I/O remap end" },
++#ifdef CONFIG_NOT_COHERENT_CACHE
++ { 0, "Consistent mem start" },
++ { 0, "Consistent mem end" },
++#endif
++#ifdef CONFIG_HIGHMEM
++ { 0, "Highmem PTEs start" },
++ { 0, "Highmem PTEs end" },
++#endif
++ { 0, "Fixmap start" },
++ { 0, "Fixmap end" },
++#endif
++ { -1, NULL },
++};
++
++static void dump_flag_info(struct pg_state *st, const struct flag_info
++ *flag, u64 pte, int num)
++{
++ unsigned int i;
++
++ for (i = 0; i < num; i++, flag++) {
++ const char *s = NULL;
++ u64 val;
++
++ /* flag not defined so don't check it */
++ if (flag->mask == 0)
++ continue;
++ /* Some 'flags' are actually values */
++ if (flag->is_val) {
++ val = pte & flag->val;
++ if (flag->shift)
++ val = val >> flag->shift;
++ seq_printf(st->seq, " %s:%llx", flag->set, val);
++ } else {
++ if ((pte & flag->mask) == flag->val)
++ s = flag->set;
++ else
++ s = flag->clear;
++ if (s)
++ seq_printf(st->seq, " %s", s);
++ }
++ st->current_flags &= ~flag->mask;
++ }
++ if (st->current_flags != 0)
++ seq_printf(st->seq, " unknown flags:%llx", st->current_flags);
++}
++
++static void dump_addr(struct pg_state *st, unsigned long addr)
++{
++ static const char units[] = "KMGTPE";
++ const char *unit = units;
++ unsigned long delta;
++
++#ifdef CONFIG_PPC64
++ seq_printf(st->seq, "0x%016lx-0x%016lx ", st->start_address, addr-1);
++ seq_printf(st->seq, "0x%016lx ", st->start_pa);
++#else
++ seq_printf(st->seq, "0x%08lx-0x%08lx ", st->start_address, addr - 1);
++ seq_printf(st->seq, "0x%08lx ", st->start_pa);
++#endif
++
++ delta = (addr - st->start_address) >> 10;
++ /* Work out what appropriate unit to use */
++ while (!(delta & 1023) && unit[1]) {
++ delta >>= 10;
++ unit++;
++ }
++ seq_printf(st->seq, "%9lu%c", delta, *unit);
++
++}
++
++static void note_page(struct pg_state *st, unsigned long addr,
++ unsigned int level, u64 val)
++{
++ u64 flag = val & pg_level[level].mask;
++ u64 pa = val & PTE_RPN_MASK;
++
++ /* At first no level is set */
++ if (!st->level) {
++ st->level = level;
++ st->current_flags = flag;
++ st->start_address = addr;
++ st->start_pa = pa;
++ st->last_pa = pa;
++ seq_printf(st->seq, "---[ %s ]---\n", st->marker->name);
++ /*
++ * Dump the section of virtual memory when:
++ * - the PTE flags from one entry to the next differs.
++ * - we change levels in the tree.
++ * - the address is in a different section of memory and is thus
++ * used for a different purpose, regardless of the flags.
++ * - the pa of this page is not adjacent to the last inspected page
++ */
++ } else if (flag != st->current_flags || level != st->level ||
++ addr >= st->marker[1].start_address ||
++ pa != st->last_pa + PAGE_SIZE) {
++
++ /* Check the PTE flags */
++ if (st->current_flags) {
++ dump_addr(st, addr);
++
++ /* Dump all the flags */
++ if (pg_level[st->level].flag)
++ dump_flag_info(st, pg_level[st->level].flag,
++ st->current_flags,
++ pg_level[st->level].num);
++
++ seq_putc(st->seq, '\n');
++ }
++
++ /*
++ * Address indicates we have passed the end of the
++ * current section of virtual memory
++ */
++ while (addr >= st->marker[1].start_address) {
++ st->marker++;
++ seq_printf(st->seq, "---[ %s ]---\n", st->marker->name);
++ }
++ st->start_address = addr;
++ st->start_pa = pa;
++ st->last_pa = pa;
++ st->current_flags = flag;
++ st->level = level;
++ } else {
++ st->last_pa = pa;
++ }
++}
++
++static void walk_pte(struct pg_state *st, pmd_t *pmd, unsigned long start)
++{
++ pte_t *pte = pte_offset_kernel(pmd, 0);
++ unsigned long addr;
++ unsigned int i;
++
++ for (i = 0; i < PTRS_PER_PTE; i++, pte++) {
++ addr = start + i * PAGE_SIZE;
++ note_page(st, addr, 4, pte_val(*pte));
++
++ }
++}
++
++static void walk_pmd(struct pg_state *st, pud_t *pud, unsigned long start)
++{
++ pmd_t *pmd = pmd_offset(pud, 0);
++ unsigned long addr;
++ unsigned int i;
++
++ for (i = 0; i < PTRS_PER_PMD; i++, pmd++) {
++ addr = start + i * PMD_SIZE;
++ if (!pmd_none(*pmd) && !pmd_huge(*pmd))
++ /* pmd exists */
++ walk_pte(st, pmd, addr);
++ else
++ note_page(st, addr, 3, pmd_val(*pmd));
++ }
++}
++
++static void walk_pud(struct pg_state *st, pgd_t *pgd, unsigned long start)
++{
++ pud_t *pud = pud_offset(pgd, 0);
++ unsigned long addr;
++ unsigned int i;
++
++ for (i = 0; i < PTRS_PER_PUD; i++, pud++) {
++ addr = start + i * PUD_SIZE;
++ if (!pud_none(*pud) && !pud_huge(*pud))
++ /* pud exists */
++ walk_pmd(st, pud, addr);
++ else
++ note_page(st, addr, 2, pud_val(*pud));
++ }
++}
++
++static void walk_pagetables(struct pg_state *st)
++{
++ pgd_t *pgd = pgd_offset_k(0UL);
++ unsigned int i;
++ unsigned long addr;
++
++ addr = st->start_address;
++
++ /*
++ * Traverse the linux pagetable structure and dump pages that are in
++ * the hash pagetable.
++ */
++ for (i = 0; i < PTRS_PER_PGD; i++, pgd++, addr += PGDIR_SIZE) {
++ if (!pgd_none(*pgd) && !pgd_huge(*pgd))
++ /* pgd exists */
++ walk_pud(st, pgd, addr);
++ else
++ note_page(st, addr, 1, pgd_val(*pgd));
++ }
++}
++
++static void populate_markers(void)
++{
++ int i = 0;
++
++ address_markers[i++].start_address = PAGE_OFFSET;
++ address_markers[i++].start_address = VMALLOC_START;
++ address_markers[i++].start_address = VMALLOC_END;
++#ifdef CONFIG_PPC64
++ address_markers[i++].start_address = ISA_IO_BASE;
++ address_markers[i++].start_address = ISA_IO_END;
++ address_markers[i++].start_address = PHB_IO_BASE;
++ address_markers[i++].start_address = PHB_IO_END;
++ address_markers[i++].start_address = IOREMAP_BASE;
++ address_markers[i++].start_address = IOREMAP_END;
++#ifdef CONFIG_PPC_BOOK3S_64
++ address_markers[i++].start_address = H_VMEMMAP_BASE;
++#else
++ address_markers[i++].start_address = VMEMMAP_BASE;
++#endif
++#else /* !CONFIG_PPC64 */
++ address_markers[i++].start_address = ioremap_bot;
++ address_markers[i++].start_address = IOREMAP_TOP;
++#ifdef CONFIG_NOT_COHERENT_CACHE
++ address_markers[i++].start_address = IOREMAP_TOP;
++ address_markers[i++].start_address = IOREMAP_TOP +
++ CONFIG_CONSISTENT_SIZE;
++#endif
++#ifdef CONFIG_HIGHMEM
++ address_markers[i++].start_address = PKMAP_BASE;
++ address_markers[i++].start_address = PKMAP_ADDR(LAST_PKMAP);
++#endif
++ address_markers[i++].start_address = FIXADDR_START;
++ address_markers[i++].start_address = FIXADDR_TOP;
++#endif /* CONFIG_PPC64 */
++}
++
++static int ptdump_show(struct seq_file *m, void *v)
++{
++ struct pg_state st = {
++ .seq = m,
++ .marker = address_markers,
++ };
++
++ if (radix_enabled())
++ st.start_address = PAGE_OFFSET;
++ else
++ st.start_address = KERN_VIRT_START;
++
++ /* Traverse kernel page tables */
++ walk_pagetables(&st);
++ note_page(&st, 0, 0, 0);
++ return 0;
++}
++
++
++static int ptdump_open(struct inode *inode, struct file *file)
++{
++ return single_open(file, ptdump_show, NULL);
++}
++
++static const struct file_operations ptdump_fops = {
++ .open = ptdump_open,
++ .read = seq_read,
++ .llseek = seq_lseek,
++ .release = single_release,
++};
++
++static void build_pgtable_complete_mask(void)
++{
++ unsigned int i, j;
++
++ for (i = 0; i < ARRAY_SIZE(pg_level); i++)
++ if (pg_level[i].flag)
++ for (j = 0; j < pg_level[i].num; j++)
++ pg_level[i].mask |= pg_level[i].flag[j].mask;
++}
++
++static int ptdump_init(void)
++{
++ struct dentry *debugfs_file;
++
++ populate_markers();
++ build_pgtable_complete_mask();
++ debugfs_file = debugfs_create_file("kernel_page_tables", 0400, NULL,
++ NULL, &ptdump_fops);
++ return debugfs_file ? 0 : -ENOMEM;
++}
++device_initcall(ptdump_init);
+diff --git a/arch/powerpc/mm/ptdump/ptdump.h b/arch/powerpc/mm/ptdump/ptdump.h
+new file mode 100644
+index 0000000000000..5d513636de73a
+--- /dev/null
++++ b/arch/powerpc/mm/ptdump/ptdump.h
+@@ -0,0 +1,19 @@
++/* SPDX-License-Identifier: GPL-2.0 */
++#include <linux/types.h>
++
++struct flag_info {
++ u64 mask;
++ u64 val;
++ const char *set;
++ const char *clear;
++ bool is_val;
++ int shift;
++};
++
++struct pgtable_level {
++ const struct flag_info *flag;
++ size_t num;
++ u64 mask;
++};
++
++extern struct pgtable_level pg_level[5];
+diff --git a/arch/powerpc/mm/ptdump/segment_regs.c b/arch/powerpc/mm/ptdump/segment_regs.c
+new file mode 100644
+index 0000000000000..501843664bb91
+--- /dev/null
++++ b/arch/powerpc/mm/ptdump/segment_regs.c
+@@ -0,0 +1,64 @@
++// SPDX-License-Identifier: GPL-2.0+
++/*
++ * Copyright 2018, Christophe Leroy CS S.I.
++ * <christophe.leroy@c-s.fr>
++ *
++ * This dumps the content of Segment Registers
++ */
++
++#include <asm/debugfs.h>
++
++static void seg_show(struct seq_file *m, int i)
++{
++ u32 val = mfsrin(i << 28);
++
++ seq_printf(m, "0x%01x0000000-0x%01xfffffff ", i, i);
++ seq_printf(m, "Kern key %d ", (val >> 30) & 1);
++ seq_printf(m, "User key %d ", (val >> 29) & 1);
++ if (val & 0x80000000) {
++ seq_printf(m, "Device 0x%03x", (val >> 20) & 0x1ff);
++ seq_printf(m, "-0x%05x", val & 0xfffff);
++ } else {
++ if (val & 0x10000000)
++ seq_puts(m, "No Exec ");
++ seq_printf(m, "VSID 0x%06x", val & 0xffffff);
++ }
++ seq_puts(m, "\n");
++}
++
++static int sr_show(struct seq_file *m, void *v)
++{
++ int i;
++
++ seq_puts(m, "---[ User Segments ]---\n");
++ for (i = 0; i < TASK_SIZE >> 28; i++)
++ seg_show(m, i);
++
++ seq_puts(m, "\n---[ Kernel Segments ]---\n");
++ for (; i < 16; i++)
++ seg_show(m, i);
++
++ return 0;
++}
++
++static int sr_open(struct inode *inode, struct file *file)
++{
++ return single_open(file, sr_show, NULL);
++}
++
++static const struct file_operations sr_fops = {
++ .open = sr_open,
++ .read = seq_read,
++ .llseek = seq_lseek,
++ .release = single_release,
++};
++
++static int __init sr_init(void)
++{
++ struct dentry *debugfs_file;
++
++ debugfs_file = debugfs_create_file("segment_registers", 0400,
++ powerpc_debugfs_root, NULL, &sr_fops);
++ return debugfs_file ? 0 : -ENOMEM;
++}
++device_initcall(sr_init);
+diff --git a/arch/powerpc/mm/ptdump/shared.c b/arch/powerpc/mm/ptdump/shared.c
+new file mode 100644
+index 0000000000000..1cda3d91c6c26
+--- /dev/null
++++ b/arch/powerpc/mm/ptdump/shared.c
+@@ -0,0 +1,82 @@
++// SPDX-License-Identifier: GPL-2.0
++/*
++ * From split of dump_linuxpagetables.c
++ * Copyright 2016, Rashmica Gupta, IBM Corp.
++ *
++ */
++#include <linux/kernel.h>
++#include <asm/pgtable.h>
++
++#include "ptdump.h"
++
++static const struct flag_info flag_array[] = {
++ {
++ .mask = _PAGE_USER,
++ .val = _PAGE_USER,
++ .set = "user",
++ .clear = " ",
++ }, {
++ .mask = _PAGE_RW,
++ .val = 0,
++ .set = "r ",
++ .clear = "rw",
++ }, {
++#ifndef CONFIG_PPC_BOOK3S_32
++ .mask = _PAGE_EXEC,
++ .val = _PAGE_EXEC,
++ .set = " X ",
++ .clear = " ",
++ }, {
++#endif
++ .mask = _PAGE_PRESENT,
++ .val = _PAGE_PRESENT,
++ .set = "present",
++ .clear = " ",
++ }, {
++ .mask = _PAGE_GUARDED,
++ .val = _PAGE_GUARDED,
++ .set = "guarded",
++ .clear = " ",
++ }, {
++ .mask = _PAGE_DIRTY,
++ .val = _PAGE_DIRTY,
++ .set = "dirty",
++ .clear = " ",
++ }, {
++ .mask = _PAGE_ACCESSED,
++ .val = _PAGE_ACCESSED,
++ .set = "accessed",
++ .clear = " ",
++ }, {
++ .mask = _PAGE_WRITETHRU,
++ .val = _PAGE_WRITETHRU,
++ .set = "write through",
++ .clear = " ",
++ }, {
++ .mask = _PAGE_NO_CACHE,
++ .val = _PAGE_NO_CACHE,
++ .set = "no cache",
++ .clear = " ",
++ }, {
++ .mask = _PAGE_SPECIAL,
++ .val = _PAGE_SPECIAL,
++ .set = "special",
++ }
++};
++
++struct pgtable_level pg_level[5] = {
++ {
++ }, { /* pgd */
++ .flag = flag_array,
++ .num = ARRAY_SIZE(flag_array),
++ }, { /* pud */
++ .flag = flag_array,
++ .num = ARRAY_SIZE(flag_array),
++ }, { /* pmd */
++ .flag = flag_array,
++ .num = ARRAY_SIZE(flag_array),
++ }, { /* pte */
++ .flag = flag_array,
++ .num = ARRAY_SIZE(flag_array),
++ },
++};
+diff --git a/arch/powerpc/platforms/powermac/Makefile b/arch/powerpc/platforms/powermac/Makefile
+index 561a67d65e4d4..923bfb3404333 100644
+--- a/arch/powerpc/platforms/powermac/Makefile
++++ b/arch/powerpc/platforms/powermac/Makefile
+@@ -1,5 +1,6 @@
+ # SPDX-License-Identifier: GPL-2.0
+ CFLAGS_bootx_init.o += -fPIC
++CFLAGS_bootx_init.o += $(call cc-option, -fno-stack-protector)
+
+ ifdef CONFIG_FUNCTION_TRACER
+ # Do not trace early boot code
+diff --git a/arch/x86/kernel/cpu/topology.c b/arch/x86/kernel/cpu/topology.c
+index 71ca064e37948..31fe56a90cbf8 100644
+--- a/arch/x86/kernel/cpu/topology.c
++++ b/arch/x86/kernel/cpu/topology.c
+@@ -44,7 +44,7 @@ int detect_extended_topology_early(struct cpuinfo_x86 *c)
+ * initial apic id, which also represents 32-bit extended x2apic id.
+ */
+ c->initial_apicid = edx;
+- smp_num_siblings = LEVEL_MAX_SIBLINGS(ebx);
++ smp_num_siblings = max_t(int, smp_num_siblings, LEVEL_MAX_SIBLINGS(ebx));
+ #endif
+ return 0;
+ }
+@@ -68,7 +68,8 @@ int detect_extended_topology(struct cpuinfo_x86 *c)
+ * Populate HT related information from sub-leaf level 0.
+ */
+ cpuid_count(0xb, SMT_LEVEL, &eax, &ebx, &ecx, &edx);
+- core_level_siblings = smp_num_siblings = LEVEL_MAX_SIBLINGS(ebx);
++ core_level_siblings = LEVEL_MAX_SIBLINGS(ebx);
++ smp_num_siblings = max_t(int, smp_num_siblings, LEVEL_MAX_SIBLINGS(ebx));
+ core_plus_mask_width = ht_mask_width = BITS_SHIFT_NEXT_LEVEL(eax);
+
+ sub_index = 1;
+diff --git a/arch/x86/kernel/fpu/xstate.c b/arch/x86/kernel/fpu/xstate.c
+index 7d372db8bee11..e33b732ad3376 100644
+--- a/arch/x86/kernel/fpu/xstate.c
++++ b/arch/x86/kernel/fpu/xstate.c
+@@ -811,6 +811,14 @@ void __init fpu__init_system_xstate(void)
+ fpu__init_prepare_fx_sw_frame();
+ setup_init_fpu_buf();
+ setup_xstate_comp();
++
++ /*
++ * CPU capabilities initialization runs before FPU init. So
++ * X86_FEATURE_OSXSAVE is not set. Now that XSAVE is completely
++ * functional, set the feature bit so depending code works.
++ */
++ setup_force_cpu_cap(X86_FEATURE_OSXSAVE);
++
+ print_xstate_offset_size();
+
+ pr_info("x86/fpu: Enabled xstate features 0x%llx, context size is %d bytes, using '%s' format.\n",
+diff --git a/block/partitions/amiga.c b/block/partitions/amiga.c
+index 560936617d9c1..4a4160221183b 100644
+--- a/block/partitions/amiga.c
++++ b/block/partitions/amiga.c
+@@ -32,7 +32,8 @@ int amiga_partition(struct parsed_partitions *state)
+ unsigned char *data;
+ struct RigidDiskBlock *rdb;
+ struct PartitionBlock *pb;
+- int start_sect, nr_sects, blk, part, res = 0;
++ sector_t start_sect, nr_sects;
++ int blk, part, res = 0;
+ int blksize = 1; /* Multiplier for disk block size */
+ int slot = 1;
+ char b[BDEVNAME_SIZE];
+@@ -100,14 +101,14 @@ int amiga_partition(struct parsed_partitions *state)
+
+ /* Tell Kernel about it */
+
+- nr_sects = (be32_to_cpu(pb->pb_Environment[10]) + 1 -
+- be32_to_cpu(pb->pb_Environment[9])) *
++ nr_sects = ((sector_t)be32_to_cpu(pb->pb_Environment[10]) + 1 -
++ be32_to_cpu(pb->pb_Environment[9])) *
+ be32_to_cpu(pb->pb_Environment[3]) *
+ be32_to_cpu(pb->pb_Environment[5]) *
+ blksize;
+ if (!nr_sects)
+ continue;
+- start_sect = be32_to_cpu(pb->pb_Environment[9]) *
++ start_sect = (sector_t)be32_to_cpu(pb->pb_Environment[9]) *
+ be32_to_cpu(pb->pb_Environment[3]) *
+ be32_to_cpu(pb->pb_Environment[5]) *
+ blksize;
+diff --git a/drivers/base/regmap/regmap-i2c.c b/drivers/base/regmap/regmap-i2c.c
+index 056acde5e7d34..4b9d68af090b2 100644
+--- a/drivers/base/regmap/regmap-i2c.c
++++ b/drivers/base/regmap/regmap-i2c.c
+@@ -246,8 +246,8 @@ static int regmap_i2c_smbus_i2c_read(void *context, const void *reg,
+ static struct regmap_bus regmap_i2c_smbus_i2c_block = {
+ .write = regmap_i2c_smbus_i2c_write,
+ .read = regmap_i2c_smbus_i2c_read,
+- .max_raw_read = I2C_SMBUS_BLOCK_MAX,
+- .max_raw_write = I2C_SMBUS_BLOCK_MAX,
++ .max_raw_read = I2C_SMBUS_BLOCK_MAX - 1,
++ .max_raw_write = I2C_SMBUS_BLOCK_MAX - 1,
+ };
+
+ static const struct regmap_bus *regmap_get_i2c_bus(struct i2c_client *i2c,
+diff --git a/drivers/dma-buf/sw_sync.c b/drivers/dma-buf/sw_sync.c
+index 81ba4eb348909..09d369306ee36 100644
+--- a/drivers/dma-buf/sw_sync.c
++++ b/drivers/dma-buf/sw_sync.c
+@@ -200,6 +200,7 @@ static const struct dma_fence_ops timeline_fence_ops = {
+ */
+ static void sync_timeline_signal(struct sync_timeline *obj, unsigned int inc)
+ {
++ LIST_HEAD(signalled);
+ struct sync_pt *pt, *next;
+
+ trace_sync_timeline(obj);
+@@ -212,21 +213,20 @@ static void sync_timeline_signal(struct sync_timeline *obj, unsigned int inc)
+ if (!timeline_fence_signaled(&pt->base))
+ break;
+
+- list_del_init(&pt->link);
++ dma_fence_get(&pt->base);
++
++ list_move_tail(&pt->link, &signalled);
+ rb_erase(&pt->node, &obj->pt_tree);
+
+- /*
+- * A signal callback may release the last reference to this
+- * fence, causing it to be freed. That operation has to be
+- * last to avoid a use after free inside this loop, and must
+- * be after we remove the fence from the timeline in order to
+- * prevent deadlocking on timeline->lock inside
+- * timeline_fence_release().
+- */
+ dma_fence_signal_locked(&pt->base);
+ }
+
+ spin_unlock_irq(&obj->lock);
++
++ list_for_each_entry_safe(pt, next, &signalled, link) {
++ list_del_init(&pt->link);
++ dma_fence_put(&pt->base);
++ }
+ }
+
+ /**
+diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c
+index e667bcf64bc7f..70e446c2acf82 100644
+--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c
++++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c
+@@ -1502,15 +1502,15 @@ static int amdgpu_cs_wait_all_fences(struct amdgpu_device *adev,
+ continue;
+
+ r = dma_fence_wait_timeout(fence, true, timeout);
++ if (r > 0 && fence->error)
++ r = fence->error;
++
+ dma_fence_put(fence);
+ if (r < 0)
+ return r;
+
+ if (r == 0)
+ break;
+-
+- if (fence->error)
+- return fence->error;
+ }
+
+ memset(wait, 0, sizeof(*wait));
+diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c
+index ead221ccb93e0..ddec675ba690a 100644
+--- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c
++++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c
+@@ -2529,7 +2529,9 @@ static void dcn10_wait_for_mpcc_disconnect(
+ if (pipe_ctx->stream_res.opp->mpcc_disconnect_pending[mpcc_inst]) {
+ struct hubp *hubp = get_hubp_by_inst(res_pool, mpcc_inst);
+
+- res_pool->mpc->funcs->wait_for_idle(res_pool->mpc, mpcc_inst);
++ if (pipe_ctx->stream_res.tg &&
++ pipe_ctx->stream_res.tg->funcs->is_tg_enabled(pipe_ctx->stream_res.tg))
++ res_pool->mpc->funcs->wait_for_idle(res_pool->mpc, mpcc_inst);
+ pipe_ctx->stream_res.opp->mpcc_disconnect_pending[mpcc_inst] = false;
+ hubp->funcs->set_blank(hubp, true);
+ /*DC_LOG_ERROR(dc->ctx->logger,
+diff --git a/drivers/gpu/drm/radeon/radeon_cs.c b/drivers/gpu/drm/radeon/radeon_cs.c
+index 1ae31dbc61c64..5e61abb3dce5c 100644
+--- a/drivers/gpu/drm/radeon/radeon_cs.c
++++ b/drivers/gpu/drm/radeon/radeon_cs.c
+@@ -265,7 +265,8 @@ int radeon_cs_parser_init(struct radeon_cs_parser *p, void *data)
+ {
+ struct drm_radeon_cs *cs = data;
+ uint64_t *chunk_array_ptr;
+- unsigned size, i;
++ u64 size;
++ unsigned i;
+ u32 ring = RADEON_CS_RING_GFX;
+ s32 priority = 0;
+
+diff --git a/drivers/hid/hid-ids.h b/drivers/hid/hid-ids.h
+index c0ba8d6f4978f..a9d6f8acf70b5 100644
+--- a/drivers/hid/hid-ids.h
++++ b/drivers/hid/hid-ids.h
+@@ -571,6 +571,7 @@
+ #define USB_DEVICE_ID_UGCI_FIGHTING 0x0030
+
+ #define USB_VENDOR_ID_HP 0x03f0
++#define USB_PRODUCT_ID_HP_ELITE_PRESENTER_MOUSE_464A 0x464a
+ #define USB_PRODUCT_ID_HP_LOGITECH_OEM_USB_OPTICAL_MOUSE_0A4A 0x0a4a
+ #define USB_PRODUCT_ID_HP_LOGITECH_OEM_USB_OPTICAL_MOUSE_0B4A 0x0b4a
+ #define USB_PRODUCT_ID_HP_PIXART_OEM_USB_OPTICAL_MOUSE 0x134a
+diff --git a/drivers/hid/hid-quirks.c b/drivers/hid/hid-quirks.c
+index 8de294aa3184a..a2ab338166e61 100644
+--- a/drivers/hid/hid-quirks.c
++++ b/drivers/hid/hid-quirks.c
+@@ -98,6 +98,7 @@ static const struct hid_device_id hid_quirks[] = {
+ { HID_USB_DEVICE(USB_VENDOR_ID_HOLTEK_ALT, USB_DEVICE_ID_HOLTEK_ALT_KEYBOARD_A096), HID_QUIRK_NO_INIT_REPORTS },
+ { HID_USB_DEVICE(USB_VENDOR_ID_HOLTEK_ALT, USB_DEVICE_ID_HOLTEK_ALT_KEYBOARD_A293), HID_QUIRK_ALWAYS_POLL },
+ { HID_USB_DEVICE(USB_VENDOR_ID_HP, USB_PRODUCT_ID_HP_LOGITECH_OEM_USB_OPTICAL_MOUSE_0A4A), HID_QUIRK_ALWAYS_POLL },
++ { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_HP, USB_PRODUCT_ID_HP_ELITE_PRESENTER_MOUSE_464A), HID_QUIRK_MULTI_INPUT },
+ { HID_USB_DEVICE(USB_VENDOR_ID_HP, USB_PRODUCT_ID_HP_LOGITECH_OEM_USB_OPTICAL_MOUSE_0B4A), HID_QUIRK_ALWAYS_POLL },
+ { HID_USB_DEVICE(USB_VENDOR_ID_HP, USB_PRODUCT_ID_HP_PIXART_OEM_USB_OPTICAL_MOUSE), HID_QUIRK_ALWAYS_POLL },
+ { HID_USB_DEVICE(USB_VENDOR_ID_HP, USB_PRODUCT_ID_HP_PIXART_OEM_USB_OPTICAL_MOUSE_094A), HID_QUIRK_ALWAYS_POLL },
+diff --git a/drivers/iio/Kconfig b/drivers/iio/Kconfig
+index d08aeb41cd078..810e72e4e8b7d 100644
+--- a/drivers/iio/Kconfig
++++ b/drivers/iio/Kconfig
+@@ -70,6 +70,7 @@ config IIO_TRIGGERED_EVENT
+
+ source "drivers/iio/accel/Kconfig"
+ source "drivers/iio/adc/Kconfig"
++source "drivers/iio/addac/Kconfig"
+ source "drivers/iio/afe/Kconfig"
+ source "drivers/iio/amplifiers/Kconfig"
+ source "drivers/iio/chemical/Kconfig"
+diff --git a/drivers/iio/Makefile b/drivers/iio/Makefile
+index cb5993251381e..a60d0cbfe4cd2 100644
+--- a/drivers/iio/Makefile
++++ b/drivers/iio/Makefile
+@@ -15,6 +15,7 @@ obj-$(CONFIG_IIO_TRIGGERED_EVENT) += industrialio-triggered-event.o
+
+ obj-y += accel/
+ obj-y += adc/
++obj-y += addac/
+ obj-y += afe/
+ obj-y += amplifiers/
+ obj-y += buffer/
+diff --git a/drivers/iio/adc/stx104.c b/drivers/iio/adc/stx104.c
+index 0662ca199eb0b..49aeb76212fd0 100644
+--- a/drivers/iio/adc/stx104.c
++++ b/drivers/iio/adc/stx104.c
+@@ -23,7 +23,9 @@
+ #include <linux/kernel.h>
+ #include <linux/module.h>
+ #include <linux/moduleparam.h>
++#include <linux/mutex.h>
+ #include <linux/spinlock.h>
++#include <linux/types.h>
+
+ #define STX104_OUT_CHAN(chan) { \
+ .type = IIO_VOLTAGE, \
+@@ -52,14 +54,38 @@ static unsigned int num_stx104;
+ module_param_hw_array(base, uint, ioport, &num_stx104, 0);
+ MODULE_PARM_DESC(base, "Apex Embedded Systems STX104 base addresses");
+
++/**
++ * struct stx104_reg - device register structure
++ * @ssr_ad: Software Strobe Register and ADC Data
++ * @achan: ADC Channel
++ * @dio: Digital I/O
++ * @dac: DAC Channels
++ * @cir_asr: Clear Interrupts and ADC Status
++ * @acr: ADC Control
++ * @pccr_fsh: Pacer Clock Control and FIFO Status MSB
++ * @acfg: ADC Configuration
++ */
++struct stx104_reg {
++ u16 ssr_ad;
++ u8 achan;
++ u8 dio;
++ u16 dac[2];
++ u8 cir_asr;
++ u8 acr;
++ u8 pccr_fsh;
++ u8 acfg;
++};
++
+ /**
+ * struct stx104_iio - IIO device private data structure
++ * @lock: synchronization lock to prevent I/O race conditions
+ * @chan_out_states: channels' output states
+- * @base: base port address of the IIO device
++ * @reg: I/O address offset for the device registers
+ */
+ struct stx104_iio {
++ struct mutex lock;
+ unsigned int chan_out_states[STX104_NUM_OUT_CHAN];
+- unsigned int base;
++ struct stx104_reg __iomem *reg;
+ };
+
+ /**
+@@ -72,7 +98,7 @@ struct stx104_iio {
+ struct stx104_gpio {
+ struct gpio_chip chip;
+ spinlock_t lock;
+- unsigned int base;
++ u8 __iomem *base;
+ unsigned int out_state;
+ };
+
+@@ -80,6 +106,7 @@ static int stx104_read_raw(struct iio_dev *indio_dev,
+ struct iio_chan_spec const *chan, int *val, int *val2, long mask)
+ {
+ struct stx104_iio *const priv = iio_priv(indio_dev);
++ struct stx104_reg __iomem *const reg = priv->reg;
+ unsigned int adc_config;
+ int adbu;
+ int gain;
+@@ -87,7 +114,7 @@ static int stx104_read_raw(struct iio_dev *indio_dev,
+ switch (mask) {
+ case IIO_CHAN_INFO_HARDWAREGAIN:
+ /* get gain configuration */
+- adc_config = inb(priv->base + 11);
++ adc_config = ioread8(&reg->acfg);
+ gain = adc_config & 0x3;
+
+ *val = 1 << gain;
+@@ -98,25 +125,31 @@ static int stx104_read_raw(struct iio_dev *indio_dev,
+ return IIO_VAL_INT;
+ }
+
++ mutex_lock(&priv->lock);
++
+ /* select ADC channel */
+- outb(chan->channel | (chan->channel << 4), priv->base + 2);
++ iowrite8(chan->channel | (chan->channel << 4), &reg->achan);
++
++ /* trigger ADC sample capture by writing to the 8-bit
++ * Software Strobe Register and wait for completion
++ */
++ iowrite8(0, &reg->ssr_ad);
++ while (ioread8(&reg->cir_asr) & BIT(7));
+
+- /* trigger ADC sample capture and wait for completion */
+- outb(0, priv->base);
+- while (inb(priv->base + 8) & BIT(7));
++ *val = ioread16(&reg->ssr_ad);
+
+- *val = inw(priv->base);
++ mutex_unlock(&priv->lock);
+ return IIO_VAL_INT;
+ case IIO_CHAN_INFO_OFFSET:
+ /* get ADC bipolar/unipolar configuration */
+- adc_config = inb(priv->base + 11);
++ adc_config = ioread8(&reg->acfg);
+ adbu = !(adc_config & BIT(2));
+
+ *val = -32768 * adbu;
+ return IIO_VAL_INT;
+ case IIO_CHAN_INFO_SCALE:
+ /* get ADC bipolar/unipolar and gain configuration */
+- adc_config = inb(priv->base + 11);
++ adc_config = ioread8(&reg->acfg);
+ adbu = !(adc_config & BIT(2));
+ gain = adc_config & 0x3;
+
+@@ -138,16 +171,16 @@ static int stx104_write_raw(struct iio_dev *indio_dev,
+ /* Only four gain states (x1, x2, x4, x8) */
+ switch (val) {
+ case 1:
+- outb(0, priv->base + 11);
++ iowrite8(0, &priv->reg->acfg);
+ break;
+ case 2:
+- outb(1, priv->base + 11);
++ iowrite8(1, &priv->reg->acfg);
+ break;
+ case 4:
+- outb(2, priv->base + 11);
++ iowrite8(2, &priv->reg->acfg);
+ break;
+ case 8:
+- outb(3, priv->base + 11);
++ iowrite8(3, &priv->reg->acfg);
+ break;
+ default:
+ return -EINVAL;
+@@ -160,9 +193,12 @@ static int stx104_write_raw(struct iio_dev *indio_dev,
+ if ((unsigned int)val > 65535)
+ return -EINVAL;
+
++ mutex_lock(&priv->lock);
++
+ priv->chan_out_states[chan->channel] = val;
+- outw(val, priv->base + 4 + 2 * chan->channel);
++ iowrite16(val, &priv->reg->dac[chan->channel]);
+
++ mutex_unlock(&priv->lock);
+ return 0;
+ }
+ return -EINVAL;
+@@ -230,7 +266,7 @@ static int stx104_gpio_get(struct gpio_chip *chip, unsigned int offset)
+ if (offset >= 4)
+ return -EINVAL;
+
+- return !!(inb(stx104gpio->base) & BIT(offset));
++ return !!(ioread8(stx104gpio->base) & BIT(offset));
+ }
+
+ static int stx104_gpio_get_multiple(struct gpio_chip *chip, unsigned long *mask,
+@@ -238,7 +274,7 @@ static int stx104_gpio_get_multiple(struct gpio_chip *chip, unsigned long *mask,
+ {
+ struct stx104_gpio *const stx104gpio = gpiochip_get_data(chip);
+
+- *bits = inb(stx104gpio->base);
++ *bits = ioread8(stx104gpio->base);
+
+ return 0;
+ }
+@@ -260,7 +296,7 @@ static void stx104_gpio_set(struct gpio_chip *chip, unsigned int offset,
+ else
+ stx104gpio->out_state &= ~mask;
+
+- outb(stx104gpio->out_state, stx104gpio->base);
++ iowrite8(stx104gpio->out_state, stx104gpio->base);
+
+ spin_unlock_irqrestore(&stx104gpio->lock, flags);
+ }
+@@ -287,7 +323,7 @@ static void stx104_gpio_set_multiple(struct gpio_chip *chip,
+
+ stx104gpio->out_state &= ~*mask;
+ stx104gpio->out_state |= *mask & *bits;
+- outb(stx104gpio->out_state, stx104gpio->base);
++ iowrite8(stx104gpio->out_state, stx104gpio->base);
+
+ spin_unlock_irqrestore(&stx104gpio->lock, flags);
+ }
+@@ -314,11 +350,16 @@ static int stx104_probe(struct device *dev, unsigned int id)
+ return -EBUSY;
+ }
+
++ priv = iio_priv(indio_dev);
++ priv->reg = devm_ioport_map(dev, base[id], STX104_EXTENT);
++ if (!priv->reg)
++ return -ENOMEM;
++
+ indio_dev->info = &stx104_info;
+ indio_dev->modes = INDIO_DIRECT_MODE;
+
+ /* determine if differential inputs */
+- if (inb(base[id] + 8) & BIT(5)) {
++ if (ioread8(&priv->reg->cir_asr) & BIT(5)) {
+ indio_dev->num_channels = ARRAY_SIZE(stx104_channels_diff);
+ indio_dev->channels = stx104_channels_diff;
+ } else {
+@@ -329,18 +370,17 @@ static int stx104_probe(struct device *dev, unsigned int id)
+ indio_dev->name = dev_name(dev);
+ indio_dev->dev.parent = dev;
+
+- priv = iio_priv(indio_dev);
+- priv->base = base[id];
++ mutex_init(&priv->lock);
+
+ /* configure device for software trigger operation */
+- outb(0, base[id] + 9);
++ iowrite8(0, &priv->reg->acr);
+
+ /* initialize gain setting to x1 */
+- outb(0, base[id] + 11);
++ iowrite8(0, &priv->reg->acfg);
+
+ /* initialize DAC output to 0V */
+- outw(0, base[id] + 4);
+- outw(0, base[id] + 6);
++ iowrite16(0, &priv->reg->dac[0]);
++ iowrite16(0, &priv->reg->dac[1]);
+
+ stx104gpio->chip.label = dev_name(dev);
+ stx104gpio->chip.parent = dev;
+@@ -355,7 +395,7 @@ static int stx104_probe(struct device *dev, unsigned int id)
+ stx104gpio->chip.get_multiple = stx104_gpio_get_multiple;
+ stx104gpio->chip.set = stx104_gpio_set;
+ stx104gpio->chip.set_multiple = stx104_gpio_set_multiple;
+- stx104gpio->base = base[id] + 3;
++ stx104gpio->base = &priv->reg->dio;
+ stx104gpio->out_state = 0x0;
+
+ spin_lock_init(&stx104gpio->lock);
+diff --git a/drivers/iio/addac/Kconfig b/drivers/iio/addac/Kconfig
+new file mode 100644
+index 0000000000000..2e64d7755d5ea
+--- /dev/null
++++ b/drivers/iio/addac/Kconfig
+@@ -0,0 +1,8 @@
++#
++# ADC DAC drivers
++#
++# When adding new entries keep the list in alphabetical order
++
++menu "Analog to digital and digital to analog converters"
++
++endmenu
+diff --git a/drivers/iio/addac/Makefile b/drivers/iio/addac/Makefile
+new file mode 100644
+index 0000000000000..b888b9ee12da0
+--- /dev/null
++++ b/drivers/iio/addac/Makefile
+@@ -0,0 +1,6 @@
++# SPDX-License-Identifier: GPL-2.0
++#
++# Makefile for industrial I/O ADDAC drivers
++#
++
++# When adding new entries keep the list in alphabetical order
+diff --git a/drivers/irqchip/irq-mips-gic.c b/drivers/irqchip/irq-mips-gic.c
+index f3985469c2211..caebafed49bb4 100644
+--- a/drivers/irqchip/irq-mips-gic.c
++++ b/drivers/irqchip/irq-mips-gic.c
+@@ -48,7 +48,7 @@ void __iomem *mips_gic_base;
+
+ DEFINE_PER_CPU_READ_MOSTLY(unsigned long[GIC_MAX_LONGS], pcpu_masks);
+
+-static DEFINE_SPINLOCK(gic_lock);
++static DEFINE_RAW_SPINLOCK(gic_lock);
+ static struct irq_domain *gic_irq_domain;
+ static struct irq_domain *gic_ipi_domain;
+ static int gic_shared_intrs;
+@@ -207,7 +207,7 @@ static int gic_set_type(struct irq_data *d, unsigned int type)
+
+ irq = GIC_HWIRQ_TO_SHARED(d->hwirq);
+
+- spin_lock_irqsave(&gic_lock, flags);
++ raw_spin_lock_irqsave(&gic_lock, flags);
+ switch (type & IRQ_TYPE_SENSE_MASK) {
+ case IRQ_TYPE_EDGE_FALLING:
+ pol = GIC_POL_FALLING_EDGE;
+@@ -247,7 +247,7 @@ static int gic_set_type(struct irq_data *d, unsigned int type)
+ else
+ irq_set_chip_handler_name_locked(d, &gic_level_irq_controller,
+ handle_level_irq, NULL);
+- spin_unlock_irqrestore(&gic_lock, flags);
++ raw_spin_unlock_irqrestore(&gic_lock, flags);
+
+ return 0;
+ }
+@@ -265,7 +265,7 @@ static int gic_set_affinity(struct irq_data *d, const struct cpumask *cpumask,
+ return -EINVAL;
+
+ /* Assumption : cpumask refers to a single CPU */
+- spin_lock_irqsave(&gic_lock, flags);
++ raw_spin_lock_irqsave(&gic_lock, flags);
+
+ /* Re-route this IRQ */
+ write_gic_map_vp(irq, BIT(mips_cm_vp_id(cpu)));
+@@ -276,7 +276,7 @@ static int gic_set_affinity(struct irq_data *d, const struct cpumask *cpumask,
+ set_bit(irq, per_cpu_ptr(pcpu_masks, cpu));
+
+ irq_data_update_effective_affinity(d, cpumask_of(cpu));
+- spin_unlock_irqrestore(&gic_lock, flags);
++ raw_spin_unlock_irqrestore(&gic_lock, flags);
+
+ return IRQ_SET_MASK_OK;
+ }
+@@ -354,12 +354,12 @@ static void gic_mask_local_irq_all_vpes(struct irq_data *d)
+ cd = irq_data_get_irq_chip_data(d);
+ cd->mask = false;
+
+- spin_lock_irqsave(&gic_lock, flags);
++ raw_spin_lock_irqsave(&gic_lock, flags);
+ for_each_online_cpu(cpu) {
+ write_gic_vl_other(mips_cm_vp_id(cpu));
+ write_gic_vo_rmask(BIT(intr));
+ }
+- spin_unlock_irqrestore(&gic_lock, flags);
++ raw_spin_unlock_irqrestore(&gic_lock, flags);
+ }
+
+ static void gic_unmask_local_irq_all_vpes(struct irq_data *d)
+@@ -372,32 +372,45 @@ static void gic_unmask_local_irq_all_vpes(struct irq_data *d)
+ cd = irq_data_get_irq_chip_data(d);
+ cd->mask = true;
+
+- spin_lock_irqsave(&gic_lock, flags);
++ raw_spin_lock_irqsave(&gic_lock, flags);
+ for_each_online_cpu(cpu) {
+ write_gic_vl_other(mips_cm_vp_id(cpu));
+ write_gic_vo_smask(BIT(intr));
+ }
+- spin_unlock_irqrestore(&gic_lock, flags);
++ raw_spin_unlock_irqrestore(&gic_lock, flags);
+ }
+
+-static void gic_all_vpes_irq_cpu_online(struct irq_data *d)
++static void gic_all_vpes_irq_cpu_online(void)
+ {
+- struct gic_all_vpes_chip_data *cd;
+- unsigned int intr;
++ static const unsigned int local_intrs[] = {
++ GIC_LOCAL_INT_TIMER,
++ GIC_LOCAL_INT_PERFCTR,
++ GIC_LOCAL_INT_FDC,
++ };
++ unsigned long flags;
++ int i;
+
+- intr = GIC_HWIRQ_TO_LOCAL(d->hwirq);
+- cd = irq_data_get_irq_chip_data(d);
++ raw_spin_lock_irqsave(&gic_lock, flags);
+
+- write_gic_vl_map(mips_gic_vx_map_reg(intr), cd->map);
+- if (cd->mask)
+- write_gic_vl_smask(BIT(intr));
++ for (i = 0; i < ARRAY_SIZE(local_intrs); i++) {
++ 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)
++ write_gic_vl_smask(BIT(intr));
++ }
++
++ raw_spin_unlock_irqrestore(&gic_lock, flags);
+ }
+
+ static struct irq_chip gic_all_vpes_local_irq_controller = {
+ .name = "MIPS GIC Local",
+ .irq_mask = gic_mask_local_irq_all_vpes,
+ .irq_unmask = gic_unmask_local_irq_all_vpes,
+- .irq_cpu_online = gic_all_vpes_irq_cpu_online,
+ };
+
+ static void __gic_irq_dispatch(void)
+@@ -421,11 +434,11 @@ static int gic_shared_irq_domain_map(struct irq_domain *d, unsigned int virq,
+
+ data = irq_get_irq_data(virq);
+
+- spin_lock_irqsave(&gic_lock, flags);
++ raw_spin_lock_irqsave(&gic_lock, flags);
+ write_gic_map_pin(intr, GIC_MAP_PIN_MAP_TO_PIN | gic_cpu_pin);
+ write_gic_map_vp(intr, BIT(mips_cm_vp_id(cpu)));
+ irq_data_update_effective_affinity(data, cpumask_of(cpu));
+- spin_unlock_irqrestore(&gic_lock, flags);
++ raw_spin_unlock_irqrestore(&gic_lock, flags);
+
+ return 0;
+ }
+@@ -476,6 +489,10 @@ static int gic_irq_domain_map(struct irq_domain *d, unsigned int virq,
+ intr = GIC_HWIRQ_TO_LOCAL(hwirq);
+ map = GIC_MAP_PIN_MAP_TO_PIN | gic_cpu_pin;
+
++ /*
++ * If adding support for more per-cpu interrupts, keep the the
++ * array in gic_all_vpes_irq_cpu_online() in sync.
++ */
+ switch (intr) {
+ case GIC_LOCAL_INT_TIMER:
+ /* CONFIG_MIPS_CMP workaround (see __gic_init) */
+@@ -514,12 +531,12 @@ static int gic_irq_domain_map(struct irq_domain *d, unsigned int virq,
+ if (!gic_local_irq_is_routable(intr))
+ return -EPERM;
+
+- spin_lock_irqsave(&gic_lock, flags);
++ raw_spin_lock_irqsave(&gic_lock, flags);
+ for_each_online_cpu(cpu) {
+ write_gic_vl_other(mips_cm_vp_id(cpu));
+ write_gic_vo_map(mips_gic_vx_map_reg(intr), map);
+ }
+- spin_unlock_irqrestore(&gic_lock, flags);
++ raw_spin_unlock_irqrestore(&gic_lock, flags);
+
+ return 0;
+ }
+@@ -662,8 +679,8 @@ static int gic_cpu_startup(unsigned int cpu)
+ /* Clear all local IRQ masks (ie. disable all local interrupts) */
+ write_gic_vl_rmask(~0);
+
+- /* Invoke irq_cpu_online callbacks to enable desired interrupts */
+- irq_cpu_online();
++ /* Enable desired interrupts */
++ gic_all_vpes_irq_cpu_online();
+
+ return 0;
+ }
+diff --git a/drivers/md/dm-integrity.c b/drivers/md/dm-integrity.c
+index 0a4e440948f0d..234464c1c050e 100644
+--- a/drivers/md/dm-integrity.c
++++ b/drivers/md/dm-integrity.c
+@@ -29,11 +29,11 @@
+ #define DEFAULT_BUFFER_SECTORS 128
+ #define DEFAULT_JOURNAL_WATERMARK 50
+ #define DEFAULT_SYNC_MSEC 10000
+-#define DEFAULT_MAX_JOURNAL_SECTORS 131072
++#define DEFAULT_MAX_JOURNAL_SECTORS (IS_ENABLED(CONFIG_64BIT) ? 131072 : 8192)
+ #define MIN_LOG2_INTERLEAVE_SECTORS 3
+ #define MAX_LOG2_INTERLEAVE_SECTORS 31
+ #define METADATA_WORKQUEUE_MAX_ACTIVE 16
+-#define RECALC_SECTORS 8192
++#define RECALC_SECTORS (IS_ENABLED(CONFIG_64BIT) ? 32768 : 2048)
+ #define RECALC_WRITE_SUPER 16
+
+ /*
+diff --git a/drivers/media/platform/mtk-vcodec/mtk_vcodec_enc.c b/drivers/media/platform/mtk-vcodec/mtk_vcodec_enc.c
+index 6ad408514a998..193a1f800a223 100644
+--- a/drivers/media/platform/mtk-vcodec/mtk_vcodec_enc.c
++++ b/drivers/media/platform/mtk-vcodec/mtk_vcodec_enc.c
+@@ -766,6 +766,8 @@ static int vb2ops_venc_queue_setup(struct vb2_queue *vq,
+ return -EINVAL;
+
+ if (*nplanes) {
++ if (*nplanes != q_data->fmt->num_planes)
++ return -EINVAL;
+ for (i = 0; i < *nplanes; i++)
+ if (sizes[i] < q_data->sizeimage[i])
+ return -EINVAL;
+diff --git a/drivers/media/platform/mtk-vpu/mtk_vpu.c b/drivers/media/platform/mtk-vpu/mtk_vpu.c
+index 9b57fb2857285..46ec1f2699aa7 100644
+--- a/drivers/media/platform/mtk-vpu/mtk_vpu.c
++++ b/drivers/media/platform/mtk-vpu/mtk_vpu.c
+@@ -537,16 +537,18 @@ static int load_requested_vpu(struct mtk_vpu *vpu,
+ int vpu_load_firmware(struct platform_device *pdev)
+ {
+ struct mtk_vpu *vpu;
+- struct device *dev = &pdev->dev;
++ struct device *dev;
+ struct vpu_run *run;
+ const struct firmware *vpu_fw = NULL;
+ int ret;
+
+ if (!pdev) {
+- dev_err(dev, "VPU platform device is invalid\n");
++ pr_err("VPU platform device is invalid\n");
+ return -EINVAL;
+ }
+
++ dev = &pdev->dev;
++
+ vpu = platform_get_drvdata(pdev);
+ run = &vpu->run;
+
+diff --git a/drivers/mmc/core/block.c b/drivers/mmc/core/block.c
+index 88114e576efb3..039058fe6a41a 100644
+--- a/drivers/mmc/core/block.c
++++ b/drivers/mmc/core/block.c
+@@ -1976,15 +1976,16 @@ static void mmc_blk_mq_poll_completion(struct mmc_queue *mq,
+ mmc_blk_urgent_bkops(mq, mqrq);
+ }
+
+-static void mmc_blk_mq_dec_in_flight(struct mmc_queue *mq, struct request *req)
++static void mmc_blk_mq_dec_in_flight(struct mmc_queue *mq,
++ struct request_queue *q,
++ enum mmc_issue_type issue_type)
+ {
+- struct request_queue *q = req->q;
+ unsigned long flags;
+ bool put_card;
+
+ spin_lock_irqsave(q->queue_lock, flags);
+
+- mq->in_flight[mmc_issue_type(mq, req)] -= 1;
++ mq->in_flight[issue_type] -= 1;
+
+ put_card = (mmc_tot_in_flight(mq) == 0);
+
+@@ -1996,9 +1997,11 @@ static void mmc_blk_mq_dec_in_flight(struct mmc_queue *mq, struct request *req)
+
+ static void mmc_blk_mq_post_req(struct mmc_queue *mq, struct request *req)
+ {
++ enum mmc_issue_type issue_type = mmc_issue_type(mq, req);
+ struct mmc_queue_req *mqrq = req_to_mmc_queue_req(req);
+ struct mmc_request *mrq = &mqrq->brq.mrq;
+ struct mmc_host *host = mq->card->host;
++ struct request_queue *q = req->q;
+
+ mmc_post_req(host, mrq, 0);
+
+@@ -2011,7 +2014,7 @@ static void mmc_blk_mq_post_req(struct mmc_queue *mq, struct request *req)
+ else
+ blk_mq_complete_request(req);
+
+- mmc_blk_mq_dec_in_flight(mq, req);
++ mmc_blk_mq_dec_in_flight(mq, q, issue_type);
+ }
+
+ void mmc_blk_mq_recovery(struct mmc_queue *mq)
+diff --git a/drivers/mmc/host/bcm2835.c b/drivers/mmc/host/bcm2835.c
+index 5301302fb5310..2b3ff4be7ae07 100644
+--- a/drivers/mmc/host/bcm2835.c
++++ b/drivers/mmc/host/bcm2835.c
+@@ -1417,9 +1417,8 @@ static int bcm2835_probe(struct platform_device *pdev)
+ host->max_clk = clk_get_rate(clk);
+
+ host->irq = platform_get_irq(pdev, 0);
+- if (host->irq <= 0) {
+- dev_err(dev, "get IRQ failed\n");
+- ret = -EINVAL;
++ if (host->irq < 0) {
++ ret = host->irq;
+ goto err;
+ }
+
+diff --git a/drivers/mmc/host/jz4740_mmc.c b/drivers/mmc/host/jz4740_mmc.c
+index 864338e308e2b..b8fb518c6db01 100644
+--- a/drivers/mmc/host/jz4740_mmc.c
++++ b/drivers/mmc/host/jz4740_mmc.c
+@@ -1060,7 +1060,6 @@ static int jz4740_mmc_probe(struct platform_device* pdev)
+ host->irq = platform_get_irq(pdev, 0);
+ if (host->irq < 0) {
+ ret = host->irq;
+- dev_err(&pdev->dev, "Failed to get platform irq: %d\n", ret);
+ goto err_free_host;
+ }
+
+diff --git a/drivers/mmc/host/meson-gx-mmc.c b/drivers/mmc/host/meson-gx-mmc.c
+index dba98c2886f26..28f07d4100433 100644
+--- a/drivers/mmc/host/meson-gx-mmc.c
++++ b/drivers/mmc/host/meson-gx-mmc.c
+@@ -26,7 +26,6 @@
+ #include <linux/of_device.h>
+ #include <linux/platform_device.h>
+ #include <linux/ioport.h>
+-#include <linux/spinlock.h>
+ #include <linux/dma-mapping.h>
+ #include <linux/mmc/host.h>
+ #include <linux/mmc/mmc.h>
+@@ -159,7 +158,6 @@ struct meson_host {
+ struct mmc_host *mmc;
+ struct mmc_command *cmd;
+
+- spinlock_t lock;
+ void __iomem *regs;
+ struct clk *core_clk;
+ struct clk *mmc_clk;
+@@ -1042,8 +1040,6 @@ static irqreturn_t meson_mmc_irq(int irq, void *dev_id)
+ if (WARN_ON(!host) || WARN_ON(!host->cmd))
+ return IRQ_NONE;
+
+- spin_lock(&host->lock);
+-
+ cmd = host->cmd;
+ data = cmd->data;
+ cmd->error = 0;
+@@ -1071,11 +1067,8 @@ static irqreturn_t meson_mmc_irq(int irq, void *dev_id)
+ if (status & (IRQ_END_OF_CHAIN | IRQ_RESP_STATUS)) {
+ if (data && !cmd->error)
+ data->bytes_xfered = data->blksz * data->blocks;
+- if (meson_mmc_bounce_buf_read(data) ||
+- meson_mmc_get_next_command(cmd))
+- ret = IRQ_WAKE_THREAD;
+- else
+- ret = IRQ_HANDLED;
++
++ return IRQ_WAKE_THREAD;
+ }
+
+ out:
+@@ -1090,10 +1083,6 @@ out:
+ writel(start, host->regs + SD_EMMC_START);
+ }
+
+- if (ret == IRQ_HANDLED)
+- meson_mmc_request_done(host->mmc, cmd->mrq);
+-
+- spin_unlock(&host->lock);
+ return ret;
+ }
+
+@@ -1246,8 +1235,6 @@ static int meson_mmc_probe(struct platform_device *pdev)
+ host->dev = &pdev->dev;
+ dev_set_drvdata(&pdev->dev, host);
+
+- spin_lock_init(&host->lock);
+-
+ /* Get regulators and the supported OCR mask */
+ host->vqmmc_enabled = false;
+ ret = mmc_regulator_get_supply(mmc);
+@@ -1285,7 +1272,6 @@ static int meson_mmc_probe(struct platform_device *pdev)
+
+ host->irq = platform_get_irq(pdev, 0);
+ if (host->irq <= 0) {
+- dev_err(&pdev->dev, "failed to get interrupt resource.\n");
+ ret = -EINVAL;
+ goto free_host;
+ }
+diff --git a/drivers/mmc/host/mxcmmc.c b/drivers/mmc/host/mxcmmc.c
+index 6215feb976e32..a0e8ac9124455 100644
+--- a/drivers/mmc/host/mxcmmc.c
++++ b/drivers/mmc/host/mxcmmc.c
+@@ -1017,10 +1017,8 @@ static int mxcmci_probe(struct platform_device *pdev)
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ irq = platform_get_irq(pdev, 0);
+- if (irq < 0) {
+- dev_err(&pdev->dev, "failed to get IRQ: %d\n", irq);
++ if (irq < 0)
+ return irq;
+- }
+
+ mmc = mmc_alloc_host(sizeof(*host), &pdev->dev);
+ if (!mmc)
+diff --git a/drivers/mmc/host/renesas_sdhi_core.c b/drivers/mmc/host/renesas_sdhi_core.c
+index eabfcb5bbafff..a2c44cc8e2e7c 100644
+--- a/drivers/mmc/host/renesas_sdhi_core.c
++++ b/drivers/mmc/host/renesas_sdhi_core.c
+@@ -155,6 +155,66 @@ static unsigned int renesas_sdhi_clk_update(struct tmio_mmc_host *host,
+ return ret == 0 ? best_freq : clk_get_rate(priv->clk);
+ }
+
++static void renesas_sdhi_clk_start(struct tmio_mmc_host *host)
++{
++ sd_ctrl_write16(host, CTL_SD_CARD_CLK_CTL, CLK_CTL_SCLKEN |
++ sd_ctrl_read16(host, CTL_SD_CARD_CLK_CTL));
++
++ /* HW engineers overrode docs: no sleep needed on R-Car2+ */
++ if (!(host->pdata->flags & TMIO_MMC_MIN_RCAR2))
++ usleep_range(10000, 11000);
++}
++
++static void renesas_sdhi_clk_stop(struct tmio_mmc_host *host)
++{
++ sd_ctrl_write16(host, CTL_SD_CARD_CLK_CTL, ~CLK_CTL_SCLKEN &
++ sd_ctrl_read16(host, CTL_SD_CARD_CLK_CTL));
++
++ /* HW engineers overrode docs: no sleep needed on R-Car2+ */
++ if (!(host->pdata->flags & TMIO_MMC_MIN_RCAR2))
++ usleep_range(10000, 11000);
++}
++
++static void renesas_sdhi_set_clock(struct tmio_mmc_host *host,
++ unsigned int new_clock)
++{
++ u32 clk = 0, clock;
++
++ if (new_clock == 0) {
++ renesas_sdhi_clk_stop(host);
++ return;
++ }
++ /*
++ * Both HS400 and HS200/SD104 set 200MHz, but some devices need to
++ * set 400MHz to distinguish the CPG settings in HS400.
++ */
++ if (host->mmc->ios.timing == MMC_TIMING_MMC_HS400 &&
++ host->pdata->flags & TMIO_MMC_HAVE_4TAP_HS400 &&
++ new_clock == 200000000)
++ new_clock = 400000000;
++
++ clock = renesas_sdhi_clk_update(host, new_clock) / 512;
++
++ for (clk = 0x80000080; new_clock >= (clock << 1); clk >>= 1)
++ clock <<= 1;
++
++ /* 1/1 clock is option */
++ if ((host->pdata->flags & TMIO_MMC_CLK_ACTUAL) && ((clk >> 22) & 0x1)) {
++ if (!(host->mmc->ios.timing == MMC_TIMING_MMC_HS400))
++ clk |= 0xff;
++ else
++ clk &= ~0xff;
++ }
++
++ sd_ctrl_write16(host, CTL_SD_CARD_CLK_CTL, ~CLK_CTL_SCLKEN &
++ sd_ctrl_read16(host, CTL_SD_CARD_CLK_CTL));
++ sd_ctrl_write16(host, CTL_SD_CARD_CLK_CTL, clk & CLK_CTL_DIV_MASK);
++ if (!(host->pdata->flags & TMIO_MMC_MIN_RCAR2))
++ usleep_range(10000, 11000);
++
++ renesas_sdhi_clk_start(host);
++}
++
+ static void renesas_sdhi_clk_disable(struct tmio_mmc_host *host)
+ {
+ struct renesas_sdhi *priv = host_to_priv(host);
+@@ -621,8 +681,8 @@ int renesas_sdhi_probe(struct platform_device *pdev,
+
+ host->write16_hook = renesas_sdhi_write16_hook;
+ host->clk_enable = renesas_sdhi_clk_enable;
+- host->clk_update = renesas_sdhi_clk_update;
+ host->clk_disable = renesas_sdhi_clk_disable;
++ host->set_clock = renesas_sdhi_set_clock;
+ host->multi_io_quirk = renesas_sdhi_multi_io_quirk;
+ host->dma_ops = dma_ops;
+
+diff --git a/drivers/mmc/host/s3cmci.c b/drivers/mmc/host/s3cmci.c
+index f774936043129..ca2239ea6d96d 100644
+--- a/drivers/mmc/host/s3cmci.c
++++ b/drivers/mmc/host/s3cmci.c
+@@ -1661,7 +1661,6 @@ static int s3cmci_probe(struct platform_device *pdev)
+
+ host->irq = platform_get_irq(pdev, 0);
+ if (host->irq <= 0) {
+- dev_err(&pdev->dev, "failed to get interrupt resource.\n");
+ ret = -EINVAL;
+ goto probe_iounmap;
+ }
+diff --git a/drivers/mmc/host/sdhci-msm.c b/drivers/mmc/host/sdhci-msm.c
+index 4970cd40813b2..feede31fab47d 100644
+--- a/drivers/mmc/host/sdhci-msm.c
++++ b/drivers/mmc/host/sdhci-msm.c
+@@ -1914,8 +1914,6 @@ static int sdhci_msm_probe(struct platform_device *pdev)
+ /* Setup IRQ for handling power/voltage tasks with PMIC */
+ msm_host->pwr_irq = platform_get_irq_byname(pdev, "pwr_irq");
+ if (msm_host->pwr_irq < 0) {
+- dev_err(&pdev->dev, "Get pwr_irq failed (%d)\n",
+- msm_host->pwr_irq);
+ ret = msm_host->pwr_irq;
+ goto clk_disable;
+ }
+diff --git a/drivers/mmc/host/sdhci-pltfm.c b/drivers/mmc/host/sdhci-pltfm.c
+index 02bea6159d792..ac380c54bd170 100644
+--- a/drivers/mmc/host/sdhci-pltfm.c
++++ b/drivers/mmc/host/sdhci-pltfm.c
+@@ -131,7 +131,6 @@ struct sdhci_host *sdhci_pltfm_init(struct platform_device *pdev,
+
+ irq = platform_get_irq(pdev, 0);
+ if (irq < 0) {
+- dev_err(&pdev->dev, "failed to get IRQ number\n");
+ ret = irq;
+ goto err;
+ }
+diff --git a/drivers/mmc/host/sdhci-s3c.c b/drivers/mmc/host/sdhci-s3c.c
+index 9ef89d00970e1..936d88a33a675 100644
+--- a/drivers/mmc/host/sdhci-s3c.c
++++ b/drivers/mmc/host/sdhci-s3c.c
+@@ -493,10 +493,8 @@ static int sdhci_s3c_probe(struct platform_device *pdev)
+ }
+
+ irq = platform_get_irq(pdev, 0);
+- if (irq < 0) {
+- dev_err(dev, "no irq specified\n");
++ if (irq < 0)
+ return irq;
+- }
+
+ host = sdhci_alloc_host(dev, sizeof(struct sdhci_s3c));
+ if (IS_ERR(host)) {
+diff --git a/drivers/mmc/host/sdhci_f_sdh30.c b/drivers/mmc/host/sdhci_f_sdh30.c
+index ca9e05440da1d..ee8160d6015ea 100644
+--- a/drivers/mmc/host/sdhci_f_sdh30.c
++++ b/drivers/mmc/host/sdhci_f_sdh30.c
+@@ -122,10 +122,8 @@ static int sdhci_f_sdh30_probe(struct platform_device *pdev)
+ u32 reg = 0;
+
+ irq = platform_get_irq(pdev, 0);
+- if (irq < 0) {
+- dev_err(dev, "%s: no irq specified\n", __func__);
++ if (irq < 0)
+ return irq;
+- }
+
+ host = sdhci_alloc_host(dev, sizeof(struct f_sdhost_priv));
+ if (IS_ERR(host))
+diff --git a/drivers/mmc/host/sunxi-mmc.c b/drivers/mmc/host/sunxi-mmc.c
+index 757eb175611fb..bc3f8a1df10cc 100644
+--- a/drivers/mmc/host/sunxi-mmc.c
++++ b/drivers/mmc/host/sunxi-mmc.c
+@@ -1308,8 +1308,8 @@ static int sunxi_mmc_resource_request(struct sunxi_mmc_host *host,
+ return ret;
+
+ host->irq = platform_get_irq(pdev, 0);
+- if (host->irq <= 0) {
+- ret = -EINVAL;
++ if (host->irq < 0) {
++ ret = host->irq;
+ goto error_disable_mmc;
+ }
+
+diff --git a/drivers/mmc/host/tmio_mmc.c b/drivers/mmc/host/tmio_mmc.c
+index 43a2ea5cff24f..b031a776c12e0 100644
+--- a/drivers/mmc/host/tmio_mmc.c
++++ b/drivers/mmc/host/tmio_mmc.c
+@@ -13,6 +13,7 @@
+ * published by the Free Software Foundation.
+ */
+
++#include <linux/delay.h>
+ #include <linux/device.h>
+ #include <linux/mfd/core.h>
+ #include <linux/mfd/tmio.h>
+@@ -23,6 +24,52 @@
+
+ #include "tmio_mmc.h"
+
++static void tmio_mmc_clk_start(struct tmio_mmc_host *host)
++{
++ sd_ctrl_write16(host, CTL_SD_CARD_CLK_CTL, CLK_CTL_SCLKEN |
++ sd_ctrl_read16(host, CTL_SD_CARD_CLK_CTL));
++
++ usleep_range(10000, 11000);
++ sd_ctrl_write16(host, CTL_CLK_AND_WAIT_CTL, 0x0100);
++ usleep_range(10000, 11000);
++}
++
++static void tmio_mmc_clk_stop(struct tmio_mmc_host *host)
++{
++ sd_ctrl_write16(host, CTL_CLK_AND_WAIT_CTL, 0x0000);
++ usleep_range(10000, 11000);
++
++ sd_ctrl_write16(host, CTL_SD_CARD_CLK_CTL, ~CLK_CTL_SCLKEN &
++ sd_ctrl_read16(host, CTL_SD_CARD_CLK_CTL));
++
++ usleep_range(10000, 11000);
++}
++
++static void tmio_mmc_set_clock(struct tmio_mmc_host *host,
++ unsigned int new_clock)
++{
++ u32 clk = 0, clock;
++
++ if (new_clock == 0) {
++ tmio_mmc_clk_stop(host);
++ return;
++ }
++
++ clock = host->mmc->f_min;
++
++ for (clk = 0x80000080; new_clock >= (clock << 1); clk >>= 1)
++ clock <<= 1;
++
++ host->pdata->set_clk_div(host->pdev, (clk >> 22) & 1);
++
++ sd_ctrl_write16(host, CTL_SD_CARD_CLK_CTL, ~CLK_CTL_SCLKEN &
++ sd_ctrl_read16(host, CTL_SD_CARD_CLK_CTL));
++ sd_ctrl_write16(host, CTL_SD_CARD_CLK_CTL, clk & CLK_CTL_DIV_MASK);
++ usleep_range(10000, 11000);
++
++ tmio_mmc_clk_start(host);
++}
++
+ #ifdef CONFIG_PM_SLEEP
+ static int tmio_mmc_suspend(struct device *dev)
+ {
+@@ -100,6 +147,7 @@ static int tmio_mmc_probe(struct platform_device *pdev)
+
+ /* SD control register space size is 0x200, 0x400 for bus_shift=1 */
+ host->bus_shift = resource_size(res) >> 10;
++ host->set_clock = tmio_mmc_set_clock;
+
+ host->mmc->f_max = pdata->hclk;
+ host->mmc->f_min = pdata->hclk / 512;
+diff --git a/drivers/mmc/host/tmio_mmc.h b/drivers/mmc/host/tmio_mmc.h
+index 7c40a7e1fea1c..358aa258cb159 100644
+--- a/drivers/mmc/host/tmio_mmc.h
++++ b/drivers/mmc/host/tmio_mmc.h
+@@ -133,7 +133,6 @@ struct tmio_mmc_host {
+
+ /* Callbacks for clock / power control */
+ void (*set_pwr)(struct platform_device *host, int state);
+- void (*set_clk_div)(struct platform_device *host, int state);
+
+ /* pio related stuff */
+ struct scatterlist *sg_ptr;
+@@ -170,10 +169,9 @@ struct tmio_mmc_host {
+
+ /* Mandatory callback */
+ int (*clk_enable)(struct tmio_mmc_host *host);
++ void (*set_clock)(struct tmio_mmc_host *host, unsigned int clock);
+
+ /* Optional callbacks */
+- unsigned int (*clk_update)(struct tmio_mmc_host *host,
+- unsigned int new_clock);
+ void (*clk_disable)(struct tmio_mmc_host *host);
+ int (*multi_io_quirk)(struct mmc_card *card,
+ unsigned int direction, int blk_size);
+diff --git a/drivers/mmc/host/tmio_mmc_core.c b/drivers/mmc/host/tmio_mmc_core.c
+index 33c9ca8f14a97..f819757e125e0 100644
+--- a/drivers/mmc/host/tmio_mmc_core.c
++++ b/drivers/mmc/host/tmio_mmc_core.c
+@@ -161,83 +161,6 @@ static void tmio_mmc_enable_sdio_irq(struct mmc_host *mmc, int enable)
+ }
+ }
+
+-static void tmio_mmc_clk_start(struct tmio_mmc_host *host)
+-{
+- sd_ctrl_write16(host, CTL_SD_CARD_CLK_CTL, CLK_CTL_SCLKEN |
+- sd_ctrl_read16(host, CTL_SD_CARD_CLK_CTL));
+-
+- /* HW engineers overrode docs: no sleep needed on R-Car2+ */
+- if (!(host->pdata->flags & TMIO_MMC_MIN_RCAR2))
+- usleep_range(10000, 11000);
+-
+- if (host->pdata->flags & TMIO_MMC_HAVE_HIGH_REG) {
+- sd_ctrl_write16(host, CTL_CLK_AND_WAIT_CTL, 0x0100);
+- usleep_range(10000, 11000);
+- }
+-}
+-
+-static void tmio_mmc_clk_stop(struct tmio_mmc_host *host)
+-{
+- if (host->pdata->flags & TMIO_MMC_HAVE_HIGH_REG) {
+- sd_ctrl_write16(host, CTL_CLK_AND_WAIT_CTL, 0x0000);
+- usleep_range(10000, 11000);
+- }
+-
+- sd_ctrl_write16(host, CTL_SD_CARD_CLK_CTL, ~CLK_CTL_SCLKEN &
+- sd_ctrl_read16(host, CTL_SD_CARD_CLK_CTL));
+-
+- /* HW engineers overrode docs: no sleep needed on R-Car2+ */
+- if (!(host->pdata->flags & TMIO_MMC_MIN_RCAR2))
+- usleep_range(10000, 11000);
+-}
+-
+-static void tmio_mmc_set_clock(struct tmio_mmc_host *host,
+- unsigned int new_clock)
+-{
+- u32 clk = 0, clock;
+-
+- if (new_clock == 0) {
+- tmio_mmc_clk_stop(host);
+- return;
+- }
+- /*
+- * Both HS400 and HS200/SD104 set 200MHz, but some devices need to
+- * set 400MHz to distinguish the CPG settings in HS400.
+- */
+- if (host->mmc->ios.timing == MMC_TIMING_MMC_HS400 &&
+- host->pdata->flags & TMIO_MMC_HAVE_4TAP_HS400 &&
+- new_clock == 200000000)
+- new_clock = 400000000;
+-
+- if (host->clk_update)
+- clock = host->clk_update(host, new_clock) / 512;
+- else
+- clock = host->mmc->f_min;
+-
+- for (clk = 0x80000080; new_clock >= (clock << 1); clk >>= 1)
+- clock <<= 1;
+-
+- /* 1/1 clock is option */
+- if ((host->pdata->flags & TMIO_MMC_CLK_ACTUAL) &&
+- ((clk >> 22) & 0x1)) {
+- if (!(host->mmc->ios.timing == MMC_TIMING_MMC_HS400))
+- clk |= 0xff;
+- else
+- clk &= ~0xff;
+- }
+-
+- if (host->set_clk_div)
+- host->set_clk_div(host->pdev, (clk >> 22) & 1);
+-
+- sd_ctrl_write16(host, CTL_SD_CARD_CLK_CTL, ~CLK_CTL_SCLKEN &
+- sd_ctrl_read16(host, CTL_SD_CARD_CLK_CTL));
+- sd_ctrl_write16(host, CTL_SD_CARD_CLK_CTL, clk & CLK_CTL_DIV_MASK);
+- if (!(host->pdata->flags & TMIO_MMC_MIN_RCAR2))
+- usleep_range(10000, 11000);
+-
+- tmio_mmc_clk_start(host);
+-}
+-
+ static void tmio_mmc_reset(struct tmio_mmc_host *host)
+ {
+ /* FIXME - should we set stop clock reg here */
+@@ -1051,15 +974,15 @@ static void tmio_mmc_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
+ switch (ios->power_mode) {
+ case MMC_POWER_OFF:
+ tmio_mmc_power_off(host);
+- tmio_mmc_clk_stop(host);
++ host->set_clock(host, 0);
+ break;
+ case MMC_POWER_UP:
+ tmio_mmc_power_on(host, ios->vdd);
+- tmio_mmc_set_clock(host, ios->clock);
++ host->set_clock(host, ios->clock);
+ tmio_mmc_set_bus_width(host, ios->bus_width);
+ break;
+ case MMC_POWER_ON:
+- tmio_mmc_set_clock(host, ios->clock);
++ host->set_clock(host, ios->clock);
+ tmio_mmc_set_bus_width(host, ios->bus_width);
+ break;
+ }
+@@ -1245,7 +1168,7 @@ int tmio_mmc_host_probe(struct tmio_mmc_host *_host)
+ int ret;
+
+ /*
+- * Check the sanity of mmc->f_min to prevent tmio_mmc_set_clock() from
++ * Check the sanity of mmc->f_min to prevent host->set_clock() from
+ * looping forever...
+ */
+ if (mmc->f_min == 0)
+@@ -1255,7 +1178,6 @@ int tmio_mmc_host_probe(struct tmio_mmc_host *_host)
+ _host->write16_hook = NULL;
+
+ _host->set_pwr = pdata->set_pwr;
+- _host->set_clk_div = pdata->set_clk_div;
+
+ ret = tmio_mmc_init_ocr(_host);
+ if (ret < 0)
+@@ -1318,7 +1240,7 @@ int tmio_mmc_host_probe(struct tmio_mmc_host *_host)
+ if (pdata->flags & TMIO_MMC_SDIO_IRQ)
+ _host->sdio_irq_mask = TMIO_SDIO_MASK_ALL;
+
+- tmio_mmc_clk_stop(_host);
++ _host->set_clock(_host, 0);
+ tmio_mmc_reset(_host);
+
+ _host->sdcard_irq_mask = sd_ctrl_read16_and_16_as_32(_host, CTL_IRQ_MASK);
+@@ -1402,7 +1324,7 @@ int tmio_mmc_host_runtime_suspend(struct device *dev)
+ tmio_mmc_disable_mmc_irqs(host, TMIO_MASK_ALL);
+
+ if (host->clk_cache)
+- tmio_mmc_clk_stop(host);
++ host->set_clock(host, 0);
+
+ tmio_mmc_clk_disable(host);
+
+@@ -1423,7 +1345,7 @@ int tmio_mmc_host_runtime_resume(struct device *dev)
+ tmio_mmc_clk_enable(host);
+
+ if (host->clk_cache)
+- tmio_mmc_set_clock(host, host->clk_cache);
++ host->set_clock(host, host->clk_cache);
+
+ if (host->native_hotplug)
+ tmio_mmc_enable_mmc_irqs(host,
+diff --git a/drivers/mmc/host/wbsd.c b/drivers/mmc/host/wbsd.c
+index 9b15431d961ce..1df3ea9e5d6f1 100644
+--- a/drivers/mmc/host/wbsd.c
++++ b/drivers/mmc/host/wbsd.c
+@@ -1713,8 +1713,6 @@ static int wbsd_init(struct device *dev, int base, int irq, int dma,
+
+ wbsd_release_resources(host);
+ wbsd_free_mmc(dev);
+-
+- mmc_free_host(mmc);
+ return ret;
+ }
+
+diff --git a/drivers/net/bonding/bond_alb.c b/drivers/net/bonding/bond_alb.c
+index 3fc439d924451..e03f4883858ac 100644
+--- a/drivers/net/bonding/bond_alb.c
++++ b/drivers/net/bonding/bond_alb.c
+@@ -671,10 +671,10 @@ static struct slave *rlb_arp_xmit(struct sk_buff *skb, struct bonding *bond)
+ return NULL;
+ arp = (struct arp_pkt *)skb_network_header(skb);
+
+- /* Don't modify or load balance ARPs that do not originate locally
+- * (e.g.,arrive via a bridge).
++ /* Don't modify or load balance ARPs that do not originate
++ * from the bond itself or a VLAN directly above the bond.
+ */
+- if (!bond_slave_has_mac_rx(bond, arp->mac_src))
++ if (!bond_slave_has_mac_rcu(bond, arp->mac_src))
+ return NULL;
+
+ if (arp->op_code == htons(ARPOP_REPLY)) {
+diff --git a/drivers/net/ethernet/ibm/ibmveth.c b/drivers/net/ethernet/ibm/ibmveth.c
+index 75a1915d95aa8..23997f1c2619f 100644
+--- a/drivers/net/ethernet/ibm/ibmveth.c
++++ b/drivers/net/ethernet/ibm/ibmveth.c
+@@ -209,7 +209,7 @@ static inline void ibmveth_flush_buffer(void *addr, unsigned long length)
+ unsigned long offset;
+
+ for (offset = 0; offset < length; offset += SMP_CACHE_BYTES)
+- asm("dcbfl %0,%1" :: "b" (addr), "r" (offset));
++ asm("dcbf %0,%1,1" :: "b" (addr), "r" (offset));
+ }
+
+ /* replenish the buffers for a pool. note that we don't need to
+diff --git a/drivers/net/ethernet/intel/i40e/i40e_nvm.c b/drivers/net/ethernet/intel/i40e/i40e_nvm.c
+index 0299e5bbb9022..10e9e60f6cf77 100644
+--- a/drivers/net/ethernet/intel/i40e/i40e_nvm.c
++++ b/drivers/net/ethernet/intel/i40e/i40e_nvm.c
+@@ -210,11 +210,11 @@ read_nvm_exit:
+ * @hw: pointer to the HW structure.
+ * @module_pointer: module pointer location in words from the NVM beginning
+ * @offset: offset in words from module start
+- * @words: number of words to write
+- * @data: buffer with words to write to the Shadow RAM
++ * @words: number of words to read
++ * @data: buffer with words to read to the Shadow RAM
+ * @last_command: tells the AdminQ that this is the last command
+ *
+- * Writes a 16 bit words buffer to the Shadow RAM using the admin command.
++ * Reads a 16 bit words buffer to the Shadow RAM using the admin command.
+ **/
+ static i40e_status i40e_read_nvm_aq(struct i40e_hw *hw,
+ u8 module_pointer, u32 offset,
+@@ -234,18 +234,18 @@ static i40e_status i40e_read_nvm_aq(struct i40e_hw *hw,
+ */
+ if ((offset + words) > hw->nvm.sr_size)
+ i40e_debug(hw, I40E_DEBUG_NVM,
+- "NVM write error: offset %d beyond Shadow RAM limit %d\n",
++ "NVM read error: offset %d beyond Shadow RAM limit %d\n",
+ (offset + words), hw->nvm.sr_size);
+ else if (words > I40E_SR_SECTOR_SIZE_IN_WORDS)
+- /* We can write only up to 4KB (one sector), in one AQ write */
++ /* We can read only up to 4KB (one sector), in one AQ write */
+ i40e_debug(hw, I40E_DEBUG_NVM,
+- "NVM write fail error: tried to write %d words, limit is %d.\n",
++ "NVM read fail error: tried to read %d words, limit is %d.\n",
+ words, I40E_SR_SECTOR_SIZE_IN_WORDS);
+ else if (((offset + (words - 1)) / I40E_SR_SECTOR_SIZE_IN_WORDS)
+ != (offset / I40E_SR_SECTOR_SIZE_IN_WORDS))
+- /* A single write cannot spread over two sectors */
++ /* A single read cannot spread over two sectors */
+ i40e_debug(hw, I40E_DEBUG_NVM,
+- "NVM write error: cannot spread over two sectors in a single write offset=%d words=%d\n",
++ "NVM read error: cannot spread over two sectors in a single read offset=%d words=%d\n",
+ offset, words);
+ else
+ ret_code = i40e_aq_read_nvm(hw, module_pointer,
+diff --git a/drivers/net/ethernet/intel/igb/igb_ptp.c b/drivers/net/ethernet/intel/igb/igb_ptp.c
+index 29ced6b74d364..be2e743e65de9 100644
+--- a/drivers/net/ethernet/intel/igb/igb_ptp.c
++++ b/drivers/net/ethernet/intel/igb/igb_ptp.c
+@@ -1181,18 +1181,6 @@ void igb_ptp_init(struct igb_adapter *adapter)
+ return;
+ }
+
+- spin_lock_init(&adapter->tmreg_lock);
+- INIT_WORK(&adapter->ptp_tx_work, igb_ptp_tx_work);
+-
+- if (adapter->ptp_flags & IGB_PTP_OVERFLOW_CHECK)
+- INIT_DELAYED_WORK(&adapter->ptp_overflow_work,
+- igb_ptp_overflow_check);
+-
+- adapter->tstamp_config.rx_filter = HWTSTAMP_FILTER_NONE;
+- adapter->tstamp_config.tx_type = HWTSTAMP_TX_OFF;
+-
+- igb_ptp_reset(adapter);
+-
+ adapter->ptp_clock = ptp_clock_register(&adapter->ptp_caps,
+ &adapter->pdev->dev);
+ if (IS_ERR(adapter->ptp_clock)) {
+@@ -1202,6 +1190,18 @@ void igb_ptp_init(struct igb_adapter *adapter)
+ dev_info(&adapter->pdev->dev, "added PHC on %s\n",
+ adapter->netdev->name);
+ adapter->ptp_flags |= IGB_PTP_ENABLED;
++
++ spin_lock_init(&adapter->tmreg_lock);
++ INIT_WORK(&adapter->ptp_tx_work, igb_ptp_tx_work);
++
++ if (adapter->ptp_flags & IGB_PTP_OVERFLOW_CHECK)
++ INIT_DELAYED_WORK(&adapter->ptp_overflow_work,
++ igb_ptp_overflow_check);
++
++ adapter->tstamp_config.rx_filter = HWTSTAMP_FILTER_NONE;
++ adapter->tstamp_config.tx_type = HWTSTAMP_TX_OFF;
++
++ igb_ptp_reset(adapter);
+ }
+ }
+
+diff --git a/drivers/net/phy/broadcom.c b/drivers/net/phy/broadcom.c
+index 94622d119abce..49fb62d02a76d 100644
+--- a/drivers/net/phy/broadcom.c
++++ b/drivers/net/phy/broadcom.c
+@@ -421,6 +421,17 @@ static int bcm5482_read_status(struct phy_device *phydev)
+ return err;
+ }
+
++static int bcm54810_read_mmd(struct phy_device *phydev, int devnum, u16 regnum)
++{
++ return -EOPNOTSUPP;
++}
++
++static int bcm54810_write_mmd(struct phy_device *phydev, int devnum, u16 regnum,
++ u16 val)
++{
++ return -EOPNOTSUPP;
++}
++
+ static int bcm5481_config_aneg(struct phy_device *phydev)
+ {
+ struct device_node *np = phydev->mdio.dev.of_node;
+@@ -684,6 +695,8 @@ static struct phy_driver broadcom_drivers[] = {
+ .name = "Broadcom BCM54810",
+ .features = PHY_GBIT_FEATURES,
+ .flags = PHY_HAS_INTERRUPT,
++ .read_mmd = bcm54810_read_mmd,
++ .write_mmd = bcm54810_write_mmd,
+ .config_init = bcm54xx_config_init,
+ .config_aneg = bcm5481_config_aneg,
+ .ack_interrupt = bcm_phy_ack_intr,
+diff --git a/drivers/net/team/team.c b/drivers/net/team/team.c
+index d80bc5f59b3fc..8b5e1ec6aabfb 100644
+--- a/drivers/net/team/team.c
++++ b/drivers/net/team/team.c
+@@ -2168,7 +2168,9 @@ static void team_setup(struct net_device *dev)
+
+ dev->hw_features = TEAM_VLAN_FEATURES |
+ NETIF_F_HW_VLAN_CTAG_RX |
+- NETIF_F_HW_VLAN_CTAG_FILTER;
++ NETIF_F_HW_VLAN_CTAG_FILTER |
++ NETIF_F_HW_VLAN_STAG_RX |
++ NETIF_F_HW_VLAN_STAG_FILTER;
+
+ dev->hw_features |= NETIF_F_GSO_ENCAP_ALL | NETIF_F_GSO_UDP_L4;
+ dev->features |= dev->hw_features;
+diff --git a/drivers/net/virtio_net.c b/drivers/net/virtio_net.c
+index 03e0f8060cc2e..331d74f9281b6 100644
+--- a/drivers/net/virtio_net.c
++++ b/drivers/net/virtio_net.c
+@@ -3120,8 +3120,6 @@ static int virtnet_probe(struct virtio_device *vdev)
+ }
+ }
+
+- _virtnet_set_queues(vi, vi->curr_queue_pairs);
+-
+ /* serialize netdev register + virtio_device_ready() with ndo_open() */
+ rtnl_lock();
+
+@@ -3134,6 +3132,8 @@ static int virtnet_probe(struct virtio_device *vdev)
+
+ virtio_device_ready(vdev);
+
++ _virtnet_set_queues(vi, vi->curr_queue_pairs);
++
+ rtnl_unlock();
+
+ err = virtnet_cpu_notif_add(vi);
+diff --git a/drivers/pci/hotplug/acpiphp_glue.c b/drivers/pci/hotplug/acpiphp_glue.c
+index 3d8844e7090a8..72a289d73dfc8 100644
+--- a/drivers/pci/hotplug/acpiphp_glue.c
++++ b/drivers/pci/hotplug/acpiphp_glue.c
+@@ -510,12 +510,15 @@ static void enable_slot(struct acpiphp_slot *slot, bool bridge)
+ if (pass && dev->subordinate) {
+ check_hotplug_bridge(slot, dev);
+ pcibios_resource_survey_bus(dev->subordinate);
+- __pci_bus_size_bridges(dev->subordinate,
+- &add_list);
++ if (pci_is_root_bus(bus))
++ __pci_bus_size_bridges(dev->subordinate, &add_list);
+ }
+ }
+ }
+- __pci_bus_assign_resources(bus, &add_list, NULL);
++ if (pci_is_root_bus(bus))
++ __pci_bus_assign_resources(bus, &add_list, NULL);
++ else
++ pci_assign_unassigned_bridge_resources(bus->self);
+ }
+
+ acpiphp_sanitize_bus(bus);
+diff --git a/drivers/pcmcia/rsrc_nonstatic.c b/drivers/pcmcia/rsrc_nonstatic.c
+index 123420cac6b54..b75b12c2c702d 100644
+--- a/drivers/pcmcia/rsrc_nonstatic.c
++++ b/drivers/pcmcia/rsrc_nonstatic.c
+@@ -1056,6 +1056,8 @@ static void nonstatic_release_resource_db(struct pcmcia_socket *s)
+ q = p->next;
+ kfree(p);
+ }
++
++ kfree(data);
+ }
+
+
+diff --git a/drivers/scsi/raid_class.c b/drivers/scsi/raid_class.c
+index cd0aba0d58b21..cd7912e34dcd6 100644
+--- a/drivers/scsi/raid_class.c
++++ b/drivers/scsi/raid_class.c
+@@ -210,54 +210,6 @@ raid_attr_ro_state(level);
+ raid_attr_ro_fn(resync);
+ raid_attr_ro_state_fn(state);
+
+-static void raid_component_release(struct device *dev)
+-{
+- struct raid_component *rc =
+- container_of(dev, struct raid_component, dev);
+- dev_printk(KERN_ERR, rc->dev.parent, "COMPONENT RELEASE\n");
+- put_device(rc->dev.parent);
+- kfree(rc);
+-}
+-
+-int raid_component_add(struct raid_template *r,struct device *raid_dev,
+- struct device *component_dev)
+-{
+- struct device *cdev =
+- attribute_container_find_class_device(&r->raid_attrs.ac,
+- raid_dev);
+- struct raid_component *rc;
+- struct raid_data *rd = dev_get_drvdata(cdev);
+- int err;
+-
+- rc = kzalloc(sizeof(*rc), GFP_KERNEL);
+- if (!rc)
+- return -ENOMEM;
+-
+- INIT_LIST_HEAD(&rc->node);
+- device_initialize(&rc->dev);
+- rc->dev.release = raid_component_release;
+- rc->dev.parent = get_device(component_dev);
+- rc->num = rd->component_count++;
+-
+- dev_set_name(&rc->dev, "component-%d", rc->num);
+- list_add_tail(&rc->node, &rd->component_list);
+- rc->dev.class = &raid_class.class;
+- err = device_add(&rc->dev);
+- if (err)
+- goto err_out;
+-
+- return 0;
+-
+-err_out:
+- put_device(&rc->dev);
+- list_del(&rc->node);
+- rd->component_count--;
+- put_device(component_dev);
+- kfree(rc);
+- return err;
+-}
+-EXPORT_SYMBOL(raid_component_add);
+-
+ struct raid_template *
+ raid_class_attach(struct raid_function_template *ft)
+ {
+diff --git a/drivers/scsi/snic/snic_disc.c b/drivers/scsi/snic/snic_disc.c
+index 388ba2ebcce52..02b80291c1360 100644
+--- a/drivers/scsi/snic/snic_disc.c
++++ b/drivers/scsi/snic/snic_disc.c
+@@ -316,12 +316,11 @@ snic_tgt_create(struct snic *snic, struct snic_tgt_id *tgtid)
+ "Snic Tgt: device_add, with err = %d\n",
+ ret);
+
+- put_device(&tgt->dev);
+ put_device(&snic->shost->shost_gendev);
+ spin_lock_irqsave(snic->shost->host_lock, flags);
+ list_del(&tgt->list);
+ spin_unlock_irqrestore(snic->shost->host_lock, flags);
+- kfree(tgt);
++ put_device(&tgt->dev);
+ tgt = NULL;
+
+ return tgt;
+diff --git a/drivers/tty/serial/8250/8250_port.c b/drivers/tty/serial/8250/8250_port.c
+index 66de3a59f5779..d3161be35b1b2 100644
+--- a/drivers/tty/serial/8250/8250_port.c
++++ b/drivers/tty/serial/8250/8250_port.c
+@@ -3224,6 +3224,7 @@ void serial8250_init_port(struct uart_8250_port *up)
+ struct uart_port *port = &up->port;
+
+ spin_lock_init(&port->lock);
++ port->pm = NULL;
+ port->ops = &serial8250_pops;
+
+ up->cur_iotype = 0xFF;
+diff --git a/drivers/tty/serial/fsl_lpuart.c b/drivers/tty/serial/fsl_lpuart.c
+index 36321d810d36f..af23d41b98438 100644
+--- a/drivers/tty/serial/fsl_lpuart.c
++++ b/drivers/tty/serial/fsl_lpuart.c
+@@ -2136,6 +2136,8 @@ static int __init lpuart32_imx_early_console_setup(struct earlycon_device *devic
+ OF_EARLYCON_DECLARE(lpuart, "fsl,vf610-lpuart", lpuart_early_console_setup);
+ OF_EARLYCON_DECLARE(lpuart32, "fsl,ls1021a-lpuart", lpuart32_early_console_setup);
+ OF_EARLYCON_DECLARE(lpuart32, "fsl,imx7ulp-lpuart", lpuart32_imx_early_console_setup);
++OF_EARLYCON_DECLARE(lpuart32, "fsl,imx8ulp-lpuart", lpuart32_imx_early_console_setup);
++OF_EARLYCON_DECLARE(lpuart32, "fsl,imx8qxp-lpuart", lpuart32_imx_early_console_setup);
+ EARLYCON_DECLARE(lpuart, lpuart_early_console_setup);
+ EARLYCON_DECLARE(lpuart32, lpuart32_early_console_setup);
+
+diff --git a/drivers/usb/dwc3/dwc3-qcom.c b/drivers/usb/dwc3/dwc3-qcom.c
+index 58e1bc3a77d80..0f090188e265b 100644
+--- a/drivers/usb/dwc3/dwc3-qcom.c
++++ b/drivers/usb/dwc3/dwc3-qcom.c
+@@ -176,55 +176,58 @@ static int dwc3_qcom_register_extcon(struct dwc3_qcom *qcom)
+ /* Only usable in contexts where the role can not change. */
+ static bool dwc3_qcom_is_host(struct dwc3_qcom *qcom)
+ {
+- struct dwc3 *dwc = platform_get_drvdata(qcom->dwc3);
++ struct dwc3 *dwc;
++
++ /*
++ * FIXME: Fix this layering violation.
++ */
++ dwc = platform_get_drvdata(qcom->dwc3);
++
++ /* Core driver may not have probed yet. */
++ if (!dwc)
++ return false;
+
+ return dwc->xhci;
+ }
+
++static void dwc3_qcom_enable_wakeup_irq(int irq)
++{
++ if (!irq)
++ return;
++
++ enable_irq(irq);
++ enable_irq_wake(irq);
++}
++
++static void dwc3_qcom_disable_wakeup_irq(int irq)
++{
++ if (!irq)
++ return;
++
++ disable_irq_wake(irq);
++ disable_irq_nosync(irq);
++}
++
+ static void dwc3_qcom_disable_interrupts(struct dwc3_qcom *qcom)
+ {
+- if (qcom->hs_phy_irq) {
+- disable_irq_wake(qcom->hs_phy_irq);
+- disable_irq_nosync(qcom->hs_phy_irq);
+- }
++ dwc3_qcom_disable_wakeup_irq(qcom->hs_phy_irq);
+
+- if (qcom->dp_hs_phy_irq) {
+- disable_irq_wake(qcom->dp_hs_phy_irq);
+- disable_irq_nosync(qcom->dp_hs_phy_irq);
+- }
++ dwc3_qcom_disable_wakeup_irq(qcom->dp_hs_phy_irq);
+
+- if (qcom->dm_hs_phy_irq) {
+- disable_irq_wake(qcom->dm_hs_phy_irq);
+- disable_irq_nosync(qcom->dm_hs_phy_irq);
+- }
++ dwc3_qcom_disable_wakeup_irq(qcom->dm_hs_phy_irq);
+
+- if (qcom->ss_phy_irq) {
+- disable_irq_wake(qcom->ss_phy_irq);
+- disable_irq_nosync(qcom->ss_phy_irq);
+- }
++ dwc3_qcom_disable_wakeup_irq(qcom->ss_phy_irq);
+ }
+
+ static void dwc3_qcom_enable_interrupts(struct dwc3_qcom *qcom)
+ {
+- if (qcom->hs_phy_irq) {
+- enable_irq(qcom->hs_phy_irq);
+- enable_irq_wake(qcom->hs_phy_irq);
+- }
++ dwc3_qcom_enable_wakeup_irq(qcom->hs_phy_irq);
+
+- if (qcom->dp_hs_phy_irq) {
+- enable_irq(qcom->dp_hs_phy_irq);
+- enable_irq_wake(qcom->dp_hs_phy_irq);
+- }
++ dwc3_qcom_enable_wakeup_irq(qcom->dp_hs_phy_irq);
+
+- if (qcom->dm_hs_phy_irq) {
+- enable_irq(qcom->dm_hs_phy_irq);
+- enable_irq_wake(qcom->dm_hs_phy_irq);
+- }
++ dwc3_qcom_enable_wakeup_irq(qcom->dm_hs_phy_irq);
+
+- if (qcom->ss_phy_irq) {
+- enable_irq(qcom->ss_phy_irq);
+- enable_irq_wake(qcom->ss_phy_irq);
+- }
++ dwc3_qcom_enable_wakeup_irq(qcom->ss_phy_irq);
+ }
+
+ static int dwc3_qcom_suspend(struct dwc3_qcom *qcom)
+diff --git a/drivers/video/fbdev/core/sysimgblt.c b/drivers/video/fbdev/core/sysimgblt.c
+index a4d05b1b17d7d..665ef7a0a2495 100644
+--- a/drivers/video/fbdev/core/sysimgblt.c
++++ b/drivers/video/fbdev/core/sysimgblt.c
+@@ -188,23 +188,29 @@ static void fast_imageblit(const struct fb_image *image, struct fb_info *p,
+ {
+ u32 fgx = fgcolor, bgx = bgcolor, bpp = p->var.bits_per_pixel;
+ u32 ppw = 32/bpp, spitch = (image->width + 7)/8;
+- u32 bit_mask, end_mask, eorx, shift;
+- const char *s = image->data, *src;
++ u32 bit_mask, eorx, shift;
++ const u8 *s = image->data, *src;
+ u32 *dst;
+- const u32 *tab = NULL;
++ const u32 *tab;
++ size_t tablen;
++ u32 colortab[16];
+ int i, j, k;
+
+ switch (bpp) {
+ case 8:
+ tab = fb_be_math(p) ? cfb_tab8_be : cfb_tab8_le;
++ tablen = 16;
+ break;
+ case 16:
+ tab = fb_be_math(p) ? cfb_tab16_be : cfb_tab16_le;
++ tablen = 4;
+ break;
+ case 32:
+- default:
+ tab = cfb_tab32;
++ tablen = 2;
+ break;
++ default:
++ return;
+ }
+
+ for (i = ppw-1; i--; ) {
+@@ -218,20 +224,62 @@ static void fast_imageblit(const struct fb_image *image, struct fb_info *p,
+ eorx = fgx ^ bgx;
+ k = image->width/ppw;
+
++ for (i = 0; i < tablen; ++i)
++ colortab[i] = (tab[i] & eorx) ^ bgx;
++
+ for (i = image->height; i--; ) {
+ dst = dst1;
+ shift = 8;
+ src = s;
+
+- for (j = k; j--; ) {
++ /*
++ * Manually unroll the per-line copying loop for better
++ * performance. This works until we processed the last
++ * completely filled source byte (inclusive).
++ */
++ switch (ppw) {
++ case 4: /* 8 bpp */
++ for (j = k; j >= 2; j -= 2, ++src) {
++ *dst++ = colortab[(*src >> 4) & bit_mask];
++ *dst++ = colortab[(*src >> 0) & bit_mask];
++ }
++ break;
++ case 2: /* 16 bpp */
++ for (j = k; j >= 4; j -= 4, ++src) {
++ *dst++ = colortab[(*src >> 6) & bit_mask];
++ *dst++ = colortab[(*src >> 4) & bit_mask];
++ *dst++ = colortab[(*src >> 2) & bit_mask];
++ *dst++ = colortab[(*src >> 0) & bit_mask];
++ }
++ break;
++ case 1: /* 32 bpp */
++ for (j = k; j >= 8; j -= 8, ++src) {
++ *dst++ = colortab[(*src >> 7) & bit_mask];
++ *dst++ = colortab[(*src >> 6) & bit_mask];
++ *dst++ = colortab[(*src >> 5) & bit_mask];
++ *dst++ = colortab[(*src >> 4) & bit_mask];
++ *dst++ = colortab[(*src >> 3) & bit_mask];
++ *dst++ = colortab[(*src >> 2) & bit_mask];
++ *dst++ = colortab[(*src >> 1) & bit_mask];
++ *dst++ = colortab[(*src >> 0) & bit_mask];
++ }
++ break;
++ }
++
++ /*
++ * For image widths that are not a multiple of 8, there
++ * are trailing pixels left on the current line. Print
++ * them as well.
++ */
++ for (; j--; ) {
+ shift -= ppw;
+- end_mask = tab[(*src >> shift) & bit_mask];
+- *dst++ = (end_mask & eorx) ^ bgx;
++ *dst++ = colortab[(*src >> shift) & bit_mask];
+ if (!shift) {
+ shift = 8;
+- src++;
++ ++src;
+ }
+ }
++
+ dst1 += p->fix.line_length;
+ s += spitch;
+ }
+diff --git a/drivers/video/fbdev/mmp/hw/mmp_ctrl.c b/drivers/video/fbdev/mmp/hw/mmp_ctrl.c
+index fcdbb2df137f8..2277d64310abf 100644
+--- a/drivers/video/fbdev/mmp/hw/mmp_ctrl.c
++++ b/drivers/video/fbdev/mmp/hw/mmp_ctrl.c
+@@ -523,7 +523,9 @@ static int mmphw_probe(struct platform_device *pdev)
+ ret = -ENOENT;
+ goto failed;
+ }
+- clk_prepare_enable(ctrl->clk);
++ ret = clk_prepare_enable(ctrl->clk);
++ if (ret)
++ goto failed;
+
+ /* init global regs */
+ ctrl_set_default(ctrl);
+diff --git a/drivers/virtio/virtio_mmio.c b/drivers/virtio/virtio_mmio.c
+index 17cd682acc22b..07be3a374efbb 100644
+--- a/drivers/virtio/virtio_mmio.c
++++ b/drivers/virtio/virtio_mmio.c
+@@ -536,11 +536,9 @@ static void virtio_mmio_release_dev(struct device *_d)
+ {
+ struct virtio_device *vdev =
+ container_of(_d, struct virtio_device, dev);
+- struct virtio_mmio_device *vm_dev =
+- container_of(vdev, struct virtio_mmio_device, vdev);
+- struct platform_device *pdev = vm_dev->pdev;
++ struct virtio_mmio_device *vm_dev = to_virtio_mmio_device(vdev);
+
+- devm_kfree(&pdev->dev, vm_dev);
++ kfree(vm_dev);
+ }
+
+ /* Platform device */
+@@ -548,19 +546,10 @@ static void virtio_mmio_release_dev(struct device *_d)
+ static int virtio_mmio_probe(struct platform_device *pdev)
+ {
+ struct virtio_mmio_device *vm_dev;
+- struct resource *mem;
+ unsigned long magic;
+ int rc;
+
+- mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+- if (!mem)
+- return -EINVAL;
+-
+- if (!devm_request_mem_region(&pdev->dev, mem->start,
+- resource_size(mem), pdev->name))
+- return -EBUSY;
+-
+- vm_dev = devm_kzalloc(&pdev->dev, sizeof(*vm_dev), GFP_KERNEL);
++ vm_dev = kzalloc(sizeof(*vm_dev), GFP_KERNEL);
+ if (!vm_dev)
+ return -ENOMEM;
+
+@@ -571,9 +560,9 @@ static int virtio_mmio_probe(struct platform_device *pdev)
+ INIT_LIST_HEAD(&vm_dev->virtqueues);
+ spin_lock_init(&vm_dev->lock);
+
+- vm_dev->base = devm_ioremap(&pdev->dev, mem->start, resource_size(mem));
+- if (vm_dev->base == NULL)
+- return -EFAULT;
++ vm_dev->base = devm_platform_ioremap_resource(pdev, 0);
++ if (IS_ERR(vm_dev->base))
++ return PTR_ERR(vm_dev->base);
+
+ /* Check magic value */
+ magic = readl(vm_dev->base + VIRTIO_MMIO_MAGIC_VALUE);
+diff --git a/fs/btrfs/volumes.c b/fs/btrfs/volumes.c
+index 0294f519c29ee..b69d6f7012f44 100644
+--- a/fs/btrfs/volumes.c
++++ b/fs/btrfs/volumes.c
+@@ -4106,8 +4106,7 @@ int btrfs_cancel_balance(struct btrfs_fs_info *fs_info)
+ }
+ }
+
+- BUG_ON(fs_info->balance_ctl ||
+- test_bit(BTRFS_FS_BALANCE_RUNNING, &fs_info->flags));
++ ASSERT(!test_bit(BTRFS_FS_BALANCE_RUNNING, &fs_info->flags));
+ atomic_dec(&fs_info->balance_cancel_req);
+ mutex_unlock(&fs_info->balance_mutex);
+ return 0;
+diff --git a/fs/cifs/file.c b/fs/cifs/file.c
+index 7b482489bd227..0613b86cc3fd0 100644
+--- a/fs/cifs/file.c
++++ b/fs/cifs/file.c
+@@ -3991,9 +3991,9 @@ static int cifs_readpage_worker(struct file *file, struct page *page,
+
+ io_error:
+ kunmap(page);
+- unlock_page(page);
+
+ read_complete:
++ unlock_page(page);
+ return rc;
+ }
+
+diff --git a/fs/dlm/lock.c b/fs/dlm/lock.c
+index d4e204473e76b..0864481d8551c 100644
+--- a/fs/dlm/lock.c
++++ b/fs/dlm/lock.c
+@@ -1858,7 +1858,7 @@ static void del_timeout(struct dlm_lkb *lkb)
+ void dlm_scan_timeout(struct dlm_ls *ls)
+ {
+ struct dlm_rsb *r;
+- struct dlm_lkb *lkb;
++ struct dlm_lkb *lkb = NULL, *iter;
+ int do_cancel, do_warn;
+ s64 wait_us;
+
+@@ -1869,27 +1869,28 @@ void dlm_scan_timeout(struct dlm_ls *ls)
+ do_cancel = 0;
+ do_warn = 0;
+ mutex_lock(&ls->ls_timeout_mutex);
+- list_for_each_entry(lkb, &ls->ls_timeout, lkb_time_list) {
++ list_for_each_entry(iter, &ls->ls_timeout, lkb_time_list) {
+
+ wait_us = ktime_to_us(ktime_sub(ktime_get(),
+- lkb->lkb_timestamp));
++ iter->lkb_timestamp));
+
+- if ((lkb->lkb_exflags & DLM_LKF_TIMEOUT) &&
+- wait_us >= (lkb->lkb_timeout_cs * 10000))
++ if ((iter->lkb_exflags & DLM_LKF_TIMEOUT) &&
++ wait_us >= (iter->lkb_timeout_cs * 10000))
+ do_cancel = 1;
+
+- if ((lkb->lkb_flags & DLM_IFL_WATCH_TIMEWARN) &&
++ if ((iter->lkb_flags & DLM_IFL_WATCH_TIMEWARN) &&
+ wait_us >= dlm_config.ci_timewarn_cs * 10000)
+ do_warn = 1;
+
+ if (!do_cancel && !do_warn)
+ continue;
+- hold_lkb(lkb);
++ hold_lkb(iter);
++ lkb = iter;
+ break;
+ }
+ mutex_unlock(&ls->ls_timeout_mutex);
+
+- if (!do_cancel && !do_warn)
++ if (!lkb)
+ break;
+
+ r = lkb->lkb_resource;
+@@ -5243,21 +5244,18 @@ void dlm_recover_waiters_pre(struct dlm_ls *ls)
+
+ static struct dlm_lkb *find_resend_waiter(struct dlm_ls *ls)
+ {
+- struct dlm_lkb *lkb;
+- int found = 0;
++ struct dlm_lkb *lkb = NULL, *iter;
+
+ mutex_lock(&ls->ls_waiters_mutex);
+- list_for_each_entry(lkb, &ls->ls_waiters, lkb_wait_reply) {
+- if (lkb->lkb_flags & DLM_IFL_RESEND) {
+- hold_lkb(lkb);
+- found = 1;
++ list_for_each_entry(iter, &ls->ls_waiters, lkb_wait_reply) {
++ if (iter->lkb_flags & DLM_IFL_RESEND) {
++ hold_lkb(iter);
++ lkb = iter;
+ break;
+ }
+ }
+ mutex_unlock(&ls->ls_waiters_mutex);
+
+- if (!found)
+- lkb = NULL;
+ return lkb;
+ }
+
+@@ -5916,37 +5914,36 @@ int dlm_user_adopt_orphan(struct dlm_ls *ls, struct dlm_user_args *ua_tmp,
+ int mode, uint32_t flags, void *name, unsigned int namelen,
+ unsigned long timeout_cs, uint32_t *lkid)
+ {
+- struct dlm_lkb *lkb;
++ struct dlm_lkb *lkb = NULL, *iter;
+ struct dlm_user_args *ua;
+ int found_other_mode = 0;
+- int found = 0;
+ int rv = 0;
+
+ mutex_lock(&ls->ls_orphans_mutex);
+- list_for_each_entry(lkb, &ls->ls_orphans, lkb_ownqueue) {
+- if (lkb->lkb_resource->res_length != namelen)
++ list_for_each_entry(iter, &ls->ls_orphans, lkb_ownqueue) {
++ if (iter->lkb_resource->res_length != namelen)
+ continue;
+- if (memcmp(lkb->lkb_resource->res_name, name, namelen))
++ if (memcmp(iter->lkb_resource->res_name, name, namelen))
+ continue;
+- if (lkb->lkb_grmode != mode) {
++ if (iter->lkb_grmode != mode) {
+ found_other_mode = 1;
+ continue;
+ }
+
+- found = 1;
+- list_del_init(&lkb->lkb_ownqueue);
+- lkb->lkb_flags &= ~DLM_IFL_ORPHAN;
+- *lkid = lkb->lkb_id;
++ lkb = iter;
++ list_del_init(&iter->lkb_ownqueue);
++ iter->lkb_flags &= ~DLM_IFL_ORPHAN;
++ *lkid = iter->lkb_id;
+ break;
+ }
+ mutex_unlock(&ls->ls_orphans_mutex);
+
+- if (!found && found_other_mode) {
++ if (!lkb && found_other_mode) {
+ rv = -EAGAIN;
+ goto out;
+ }
+
+- if (!found) {
++ if (!lkb) {
+ rv = -ENOENT;
+ goto out;
+ }
+diff --git a/fs/dlm/plock.c b/fs/dlm/plock.c
+index 9fef426ce6f41..0501821182b1e 100644
+--- a/fs/dlm/plock.c
++++ b/fs/dlm/plock.c
+@@ -83,8 +83,7 @@ static void send_op(struct plock_op *op)
+ abandoned waiter. So, we have to insert the unlock-close when the
+ lock call is interrupted. */
+
+-static void do_unlock_close(struct dlm_ls *ls, u64 number,
+- struct file *file, struct file_lock *fl)
++static void do_unlock_close(const struct dlm_plock_info *info)
+ {
+ struct plock_op *op;
+
+@@ -93,15 +92,12 @@ static void do_unlock_close(struct dlm_ls *ls, u64 number,
+ return;
+
+ op->info.optype = DLM_PLOCK_OP_UNLOCK;
+- op->info.pid = fl->fl_pid;
+- op->info.fsid = ls->ls_global_id;
+- op->info.number = number;
++ op->info.pid = info->pid;
++ op->info.fsid = info->fsid;
++ op->info.number = info->number;
+ op->info.start = 0;
+ op->info.end = OFFSET_MAX;
+- if (fl->fl_lmops && fl->fl_lmops->lm_grant)
+- op->info.owner = (__u64) fl->fl_pid;
+- else
+- op->info.owner = (__u64)(long) fl->fl_owner;
++ op->info.owner = info->owner;
+
+ op->info.flags |= DLM_PLOCK_FL_CLOSE;
+ send_op(op);
+@@ -164,13 +160,14 @@ int dlm_posix_lock(dlm_lockspace_t *lockspace, u64 number, struct file *file,
+
+ rv = wait_event_killable(recv_wq, (op->done != 0));
+ if (rv == -ERESTARTSYS) {
+- log_debug(ls, "%s: wait killed %llx", __func__,
+- (unsigned long long)number);
+ spin_lock(&ops_lock);
+ list_del(&op->list);
+ spin_unlock(&ops_lock);
++ log_debug(ls, "%s: wait interrupted %x %llx pid %d",
++ __func__, ls->ls_global_id,
++ (unsigned long long)number, op->info.pid);
+ dlm_release_plock_op(op);
+- do_unlock_close(ls, number, file, fl);
++ do_unlock_close(&op->info);
+ goto out;
+ }
+
+@@ -411,7 +408,7 @@ static ssize_t dev_read(struct file *file, char __user *u, size_t count,
+ if (op->info.flags & DLM_PLOCK_FL_CLOSE)
+ list_del(&op->list);
+ else
+- list_move(&op->list, &recv_list);
++ list_move_tail(&op->list, &recv_list);
+ memcpy(&info, &op->info, sizeof(info));
+ }
+ spin_unlock(&ops_lock);
+@@ -436,9 +433,9 @@ static ssize_t dev_read(struct file *file, char __user *u, size_t count,
+ static ssize_t dev_write(struct file *file, const char __user *u, size_t count,
+ loff_t *ppos)
+ {
++ struct plock_op *op = NULL, *iter;
+ struct dlm_plock_info info;
+- struct plock_op *op;
+- int found = 0, do_callback = 0;
++ int do_callback = 0;
+
+ if (count != sizeof(info))
+ return -EINVAL;
+@@ -449,31 +446,63 @@ static ssize_t dev_write(struct file *file, const char __user *u, size_t count,
+ if (check_version(&info))
+ return -EINVAL;
+
++ /*
++ * The results for waiting ops (SETLKW) can be returned in any
++ * order, so match all fields to find the op. The results for
++ * non-waiting ops are returned in the order that they were sent
++ * to userspace, so match the result with the first non-waiting op.
++ */
+ spin_lock(&ops_lock);
+- list_for_each_entry(op, &recv_list, list) {
+- if (op->info.fsid == info.fsid &&
+- op->info.number == info.number &&
+- op->info.owner == info.owner) {
+- list_del_init(&op->list);
+- memcpy(&op->info, &info, sizeof(info));
+- if (op->data)
+- do_callback = 1;
+- else
+- op->done = 1;
+- found = 1;
+- break;
++ if (info.wait) {
++ list_for_each_entry(iter, &recv_list, list) {
++ if (iter->info.fsid == info.fsid &&
++ iter->info.number == info.number &&
++ iter->info.owner == info.owner &&
++ iter->info.pid == info.pid &&
++ iter->info.start == info.start &&
++ iter->info.end == info.end &&
++ iter->info.ex == info.ex &&
++ iter->info.wait) {
++ op = iter;
++ break;
++ }
++ }
++ } else {
++ list_for_each_entry(iter, &recv_list, list) {
++ if (!iter->info.wait) {
++ op = iter;
++ break;
++ }
+ }
+ }
++
++ if (op) {
++ /* Sanity check that op and info match. */
++ if (info.wait)
++ WARN_ON(op->info.optype != DLM_PLOCK_OP_LOCK);
++ else
++ WARN_ON(op->info.fsid != info.fsid ||
++ op->info.number != info.number ||
++ op->info.owner != info.owner ||
++ op->info.optype != info.optype);
++
++ list_del_init(&op->list);
++ memcpy(&op->info, &info, sizeof(info));
++ if (op->data)
++ do_callback = 1;
++ else
++ op->done = 1;
++ }
+ spin_unlock(&ops_lock);
+
+- if (found) {
++ if (op) {
+ if (do_callback)
+ dlm_plock_callback(op);
+ else
+ wake_up(&recv_wq);
+ } else
+- log_print("dev_write no op %x %llx", info.fsid,
+- (unsigned long long)info.number);
++ log_print("%s: no op %x %llx", __func__,
++ info.fsid, (unsigned long long)info.number);
+ return count;
+ }
+
+diff --git a/fs/dlm/recover.c b/fs/dlm/recover.c
+index ce2aa54ca2e24..98b710cc9cf30 100644
+--- a/fs/dlm/recover.c
++++ b/fs/dlm/recover.c
+@@ -734,10 +734,9 @@ void dlm_recovered_lock(struct dlm_rsb *r)
+
+ static void recover_lvb(struct dlm_rsb *r)
+ {
+- struct dlm_lkb *lkb, *high_lkb = NULL;
++ struct dlm_lkb *big_lkb = NULL, *iter, *high_lkb = NULL;
+ uint32_t high_seq = 0;
+ int lock_lvb_exists = 0;
+- int big_lock_exists = 0;
+ int lvblen = r->res_ls->ls_lvblen;
+
+ if (!rsb_flag(r, RSB_NEW_MASTER2) &&
+@@ -753,37 +752,37 @@ static void recover_lvb(struct dlm_rsb *r)
+ /* we are the new master, so figure out if VALNOTVALID should
+ be set, and set the rsb lvb from the best lkb available. */
+
+- list_for_each_entry(lkb, &r->res_grantqueue, lkb_statequeue) {
+- if (!(lkb->lkb_exflags & DLM_LKF_VALBLK))
++ list_for_each_entry(iter, &r->res_grantqueue, lkb_statequeue) {
++ if (!(iter->lkb_exflags & DLM_LKF_VALBLK))
+ continue;
+
+ lock_lvb_exists = 1;
+
+- if (lkb->lkb_grmode > DLM_LOCK_CR) {
+- big_lock_exists = 1;
++ if (iter->lkb_grmode > DLM_LOCK_CR) {
++ big_lkb = iter;
+ goto setflag;
+ }
+
+- if (((int)lkb->lkb_lvbseq - (int)high_seq) >= 0) {
+- high_lkb = lkb;
+- high_seq = lkb->lkb_lvbseq;
++ if (((int)iter->lkb_lvbseq - (int)high_seq) >= 0) {
++ high_lkb = iter;
++ high_seq = iter->lkb_lvbseq;
+ }
+ }
+
+- list_for_each_entry(lkb, &r->res_convertqueue, lkb_statequeue) {
+- if (!(lkb->lkb_exflags & DLM_LKF_VALBLK))
++ list_for_each_entry(iter, &r->res_convertqueue, lkb_statequeue) {
++ if (!(iter->lkb_exflags & DLM_LKF_VALBLK))
+ continue;
+
+ lock_lvb_exists = 1;
+
+- if (lkb->lkb_grmode > DLM_LOCK_CR) {
+- big_lock_exists = 1;
++ if (iter->lkb_grmode > DLM_LOCK_CR) {
++ big_lkb = iter;
+ goto setflag;
+ }
+
+- if (((int)lkb->lkb_lvbseq - (int)high_seq) >= 0) {
+- high_lkb = lkb;
+- high_seq = lkb->lkb_lvbseq;
++ if (((int)iter->lkb_lvbseq - (int)high_seq) >= 0) {
++ high_lkb = iter;
++ high_seq = iter->lkb_lvbseq;
+ }
+ }
+
+@@ -792,7 +791,7 @@ static void recover_lvb(struct dlm_rsb *r)
+ goto out;
+
+ /* lvb is invalidated if only NL/CR locks remain */
+- if (!big_lock_exists)
++ if (!big_lkb)
+ rsb_set_flag(r, RSB_VALNOTVALID);
+
+ if (!r->res_lvbptr) {
+@@ -801,9 +800,9 @@ static void recover_lvb(struct dlm_rsb *r)
+ goto out;
+ }
+
+- if (big_lock_exists) {
+- r->res_lvbseq = lkb->lkb_lvbseq;
+- memcpy(r->res_lvbptr, lkb->lkb_lvbptr, lvblen);
++ if (big_lkb) {
++ r->res_lvbseq = big_lkb->lkb_lvbseq;
++ memcpy(r->res_lvbptr, big_lkb->lkb_lvbptr, lvblen);
+ } else if (high_lkb) {
+ r->res_lvbseq = high_lkb->lkb_lvbseq;
+ memcpy(r->res_lvbptr, high_lkb->lkb_lvbptr, lvblen);
+diff --git a/fs/gfs2/super.c b/fs/gfs2/super.c
+index bb0eaa4638e3c..29157f7d9663d 100644
+--- a/fs/gfs2/super.c
++++ b/fs/gfs2/super.c
+@@ -1374,7 +1374,14 @@ static int gfs2_show_options(struct seq_file *s, struct dentry *root)
+ {
+ struct gfs2_sbd *sdp = root->d_sb->s_fs_info;
+ struct gfs2_args *args = &sdp->sd_args;
+- int val;
++ unsigned int logd_secs, statfs_slow, statfs_quantum, quota_quantum;
++
++ spin_lock(&sdp->sd_tune.gt_spin);
++ logd_secs = sdp->sd_tune.gt_logd_secs;
++ quota_quantum = sdp->sd_tune.gt_quota_quantum;
++ statfs_quantum = sdp->sd_tune.gt_statfs_quantum;
++ statfs_slow = sdp->sd_tune.gt_statfs_slow;
++ spin_unlock(&sdp->sd_tune.gt_spin);
+
+ if (is_ancestor(root, sdp->sd_master_dir))
+ seq_puts(s, ",meta");
+@@ -1429,17 +1436,14 @@ static int gfs2_show_options(struct seq_file *s, struct dentry *root)
+ }
+ if (args->ar_discard)
+ seq_puts(s, ",discard");
+- val = sdp->sd_tune.gt_logd_secs;
+- if (val != 30)
+- seq_printf(s, ",commit=%d", val);
+- val = sdp->sd_tune.gt_statfs_quantum;
+- if (val != 30)
+- seq_printf(s, ",statfs_quantum=%d", val);
+- else if (sdp->sd_tune.gt_statfs_slow)
++ if (logd_secs != 30)
++ seq_printf(s, ",commit=%d", logd_secs);
++ if (statfs_quantum != 30)
++ seq_printf(s, ",statfs_quantum=%d", statfs_quantum);
++ else if (statfs_slow)
+ seq_puts(s, ",statfs_quantum=0");
+- val = sdp->sd_tune.gt_quota_quantum;
+- if (val != 60)
+- seq_printf(s, ",quota_quantum=%d", val);
++ if (quota_quantum != 60)
++ seq_printf(s, ",quota_quantum=%d", quota_quantum);
+ if (args->ar_statfs_percent)
+ seq_printf(s, ",statfs_percent=%d", args->ar_statfs_percent);
+ if (args->ar_errors != GFS2_ERRORS_DEFAULT) {
+diff --git a/fs/jfs/jfs_dmap.c b/fs/jfs/jfs_dmap.c
+index 07b9df8938f29..63ad6b1d575a5 100644
+--- a/fs/jfs/jfs_dmap.c
++++ b/fs/jfs/jfs_dmap.c
+@@ -2040,6 +2040,9 @@ dbAllocDmapLev(struct bmap * bmp,
+ if (dbFindLeaf((dmtree_t *) & dp->tree, l2nb, &leafidx))
+ return -ENOSPC;
+
++ if (leafidx < 0)
++ return -EIO;
++
+ /* determine the block number within the file system corresponding
+ * to the leaf at which free space was found.
+ */
+diff --git a/fs/jfs/jfs_txnmgr.c b/fs/jfs/jfs_txnmgr.c
+index 78789c5ed36b0..e10db01f253b8 100644
+--- a/fs/jfs/jfs_txnmgr.c
++++ b/fs/jfs/jfs_txnmgr.c
+@@ -367,6 +367,11 @@ tid_t txBegin(struct super_block *sb, int flag)
+ jfs_info("txBegin: flag = 0x%x", flag);
+ log = JFS_SBI(sb)->log;
+
++ if (!log) {
++ jfs_error(sb, "read-only filesystem\n");
++ return 0;
++ }
++
+ TXN_LOCK();
+
+ INCREMENT(TxStat.txBegin);
+diff --git a/fs/jfs/namei.c b/fs/jfs/namei.c
+index 14528c0ffe635..c2c439acbb780 100644
+--- a/fs/jfs/namei.c
++++ b/fs/jfs/namei.c
+@@ -811,6 +811,11 @@ static int jfs_link(struct dentry *old_dentry,
+ if (rc)
+ goto out;
+
++ if (isReadOnly(ip)) {
++ jfs_error(ip->i_sb, "read-only filesystem\n");
++ return -EROFS;
++ }
++
+ tid = txBegin(ip->i_sb, 0);
+
+ mutex_lock_nested(&JFS_IP(dir)->commit_mutex, COMMIT_MUTEX_PARENT);
+diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c
+index 78191320f8e21..e958181b73618 100644
+--- a/fs/nfsd/nfs4state.c
++++ b/fs/nfsd/nfs4state.c
+@@ -1019,9 +1019,9 @@ static void revoke_delegation(struct nfs4_delegation *dp)
+ WARN_ON(!list_empty(&dp->dl_recall_lru));
+
+ if (clp->cl_minorversion) {
++ spin_lock(&clp->cl_lock);
+ dp->dl_stid.sc_type = NFS4_REVOKED_DELEG_STID;
+ refcount_inc(&dp->dl_stid.sc_count);
+- spin_lock(&clp->cl_lock);
+ list_add(&dp->dl_recall_lru, &clp->cl_revoked);
+ spin_unlock(&clp->cl_lock);
+ }
+@@ -4998,15 +4998,6 @@ static __be32 nfsd4_validate_stateid(struct nfs4_client *cl, stateid_t *stateid)
+ if (ZERO_STATEID(stateid) || ONE_STATEID(stateid) ||
+ CLOSE_STATEID(stateid))
+ return status;
+- /* Client debugging aid. */
+- if (!same_clid(&stateid->si_opaque.so_clid, &cl->cl_clientid)) {
+- char addr_str[INET6_ADDRSTRLEN];
+- rpc_ntop((struct sockaddr *)&cl->cl_addr, addr_str,
+- sizeof(addr_str));
+- pr_warn_ratelimited("NFSD: client %s testing state ID "
+- "with incorrect client ID\n", addr_str);
+- return status;
+- }
+ spin_lock(&cl->cl_lock);
+ s = find_stateid_locked(cl, stateid);
+ if (!s)
+diff --git a/fs/quota/dquot.c b/fs/quota/dquot.c
+index 770a2b1434856..303987d29b9c9 100644
+--- a/fs/quota/dquot.c
++++ b/fs/quota/dquot.c
+@@ -540,7 +540,7 @@ restart:
+ continue;
+ /* Wait for dquot users */
+ if (atomic_read(&dquot->dq_count)) {
+- dqgrab(dquot);
++ atomic_inc(&dquot->dq_count);
+ spin_unlock(&dq_list_lock);
+ /*
+ * Once dqput() wakes us up, we know it's time to free
+@@ -2407,7 +2407,8 @@ int dquot_load_quota_sb(struct super_block *sb, int type, int format_id,
+
+ error = add_dquot_ref(sb, type);
+ if (error)
+- dquot_disable(sb, type, flags);
++ dquot_disable(sb, type,
++ DQUOT_USAGE_ENABLED | DQUOT_LIMITS_ENABLED);
+
+ return error;
+ out_fmt:
+diff --git a/fs/udf/unicode.c b/fs/udf/unicode.c
+index 5fcfa96463ebb..85521d6b02370 100644
+--- a/fs/udf/unicode.c
++++ b/fs/udf/unicode.c
+@@ -247,7 +247,7 @@ static int udf_name_from_CS0(struct super_block *sb,
+ }
+
+ if (translate) {
+- if (str_o_len <= 2 && str_o[0] == '.' &&
++ if (str_o_len > 0 && str_o_len <= 2 && str_o[0] == '.' &&
+ (str_o_len == 1 || str_o[1] == '.'))
+ needsCRC = 1;
+ if (needsCRC) {
+diff --git a/include/linux/clk.h b/include/linux/clk.h
+index 4f750c481b82b..0a2382d3f68c8 100644
+--- a/include/linux/clk.h
++++ b/include/linux/clk.h
+@@ -175,6 +175,39 @@ int clk_get_scaled_duty_cycle(struct clk *clk, unsigned int scale);
+ */
+ bool clk_is_match(const struct clk *p, const struct clk *q);
+
++/**
++ * clk_rate_exclusive_get - get exclusivity over the rate control of a
++ * producer
++ * @clk: clock source
++ *
++ * This function allows drivers to get exclusive control over the rate of a
++ * provider. It prevents any other consumer to execute, even indirectly,
++ * opereation which could alter the rate of the provider or cause glitches
++ *
++ * If exlusivity is claimed more than once on clock, even by the same driver,
++ * the rate effectively gets locked as exclusivity can't be preempted.
++ *
++ * Must not be called from within atomic context.
++ *
++ * Returns success (0) or negative errno.
++ */
++int clk_rate_exclusive_get(struct clk *clk);
++
++/**
++ * clk_rate_exclusive_put - release exclusivity over the rate control of a
++ * producer
++ * @clk: clock source
++ *
++ * This function allows drivers to release the exclusivity it previously got
++ * from clk_rate_exclusive_get()
++ *
++ * The caller must balance the number of clk_rate_exclusive_get() and
++ * clk_rate_exclusive_put() calls.
++ *
++ * Must not be called from within atomic context.
++ */
++void clk_rate_exclusive_put(struct clk *clk);
++
+ #else
+
+ static inline int clk_notifier_register(struct clk *clk,
+@@ -221,6 +254,13 @@ static inline bool clk_is_match(const struct clk *p, const struct clk *q)
+ return p == q;
+ }
+
++static inline int clk_rate_exclusive_get(struct clk *clk)
++{
++ return 0;
++}
++
++static inline void clk_rate_exclusive_put(struct clk *clk) {}
++
+ #endif
+
+ /**
+@@ -364,38 +404,6 @@ struct clk *devm_clk_get(struct device *dev, const char *id);
+ */
+ struct clk *devm_get_clk_from_child(struct device *dev,
+ struct device_node *np, const char *con_id);
+-/**
+- * clk_rate_exclusive_get - get exclusivity over the rate control of a
+- * producer
+- * @clk: clock source
+- *
+- * This function allows drivers to get exclusive control over the rate of a
+- * provider. It prevents any other consumer to execute, even indirectly,
+- * opereation which could alter the rate of the provider or cause glitches
+- *
+- * If exlusivity is claimed more than once on clock, even by the same driver,
+- * the rate effectively gets locked as exclusivity can't be preempted.
+- *
+- * Must not be called from within atomic context.
+- *
+- * Returns success (0) or negative errno.
+- */
+-int clk_rate_exclusive_get(struct clk *clk);
+-
+-/**
+- * clk_rate_exclusive_put - release exclusivity over the rate control of a
+- * producer
+- * @clk: clock source
+- *
+- * This function allows drivers to release the exclusivity it previously got
+- * from clk_rate_exclusive_get()
+- *
+- * The caller must balance the number of clk_rate_exclusive_get() and
+- * clk_rate_exclusive_put() calls.
+- *
+- * Must not be called from within atomic context.
+- */
+-void clk_rate_exclusive_put(struct clk *clk);
+
+ /**
+ * clk_enable - inform the system when the clock source should be running.
+@@ -665,14 +673,6 @@ static inline void clk_bulk_put(int num_clks, struct clk_bulk_data *clks) {}
+
+ static inline void devm_clk_put(struct device *dev, struct clk *clk) {}
+
+-
+-static inline int clk_rate_exclusive_get(struct clk *clk)
+-{
+- return 0;
+-}
+-
+-static inline void clk_rate_exclusive_put(struct clk *clk) {}
+-
+ static inline int clk_enable(struct clk *clk)
+ {
+ return 0;
+diff --git a/include/linux/raid_class.h b/include/linux/raid_class.h
+index ec8655514283e..c868bb927c3d7 100644
+--- a/include/linux/raid_class.h
++++ b/include/linux/raid_class.h
+@@ -78,7 +78,3 @@ DEFINE_RAID_ATTRIBUTE(enum raid_state, state)
+
+ struct raid_template *raid_class_attach(struct raid_function_template *);
+ void raid_class_release(struct raid_template *);
+-
+-int __must_check raid_component_add(struct raid_template *, struct device *,
+- struct device *);
+-
+diff --git a/include/linux/virtio_net.h b/include/linux/virtio_net.h
+index faee73c084d49..d49c1aad24643 100644
+--- a/include/linux/virtio_net.h
++++ b/include/linux/virtio_net.h
+@@ -148,6 +148,10 @@ retry:
+ if (gso_type & SKB_GSO_UDP)
+ nh_off -= thlen;
+
++ /* Kernel has a special handling for GSO_BY_FRAGS. */
++ if (gso_size == GSO_BY_FRAGS)
++ return -EINVAL;
++
+ /* Too small packets are not really GSO ones. */
+ if (skb->len - nh_off > gso_size) {
+ shinfo->gso_size = gso_size;
+diff --git a/include/media/v4l2-mem2mem.h b/include/media/v4l2-mem2mem.h
+index d655720e16a15..62c67e9e190c0 100644
+--- a/include/media/v4l2-mem2mem.h
++++ b/include/media/v4l2-mem2mem.h
+@@ -405,7 +405,14 @@ void v4l2_m2m_buf_queue(struct v4l2_m2m_ctx *m2m_ctx,
+ static inline
+ unsigned int v4l2_m2m_num_src_bufs_ready(struct v4l2_m2m_ctx *m2m_ctx)
+ {
+- return m2m_ctx->out_q_ctx.num_rdy;
++ unsigned int num_buf_rdy;
++ unsigned long flags;
++
++ spin_lock_irqsave(&m2m_ctx->out_q_ctx.rdy_spinlock, flags);
++ num_buf_rdy = m2m_ctx->out_q_ctx.num_rdy;
++ spin_unlock_irqrestore(&m2m_ctx->out_q_ctx.rdy_spinlock, flags);
++
++ return num_buf_rdy;
+ }
+
+ /**
+@@ -417,7 +424,14 @@ unsigned int v4l2_m2m_num_src_bufs_ready(struct v4l2_m2m_ctx *m2m_ctx)
+ static inline
+ unsigned int v4l2_m2m_num_dst_bufs_ready(struct v4l2_m2m_ctx *m2m_ctx)
+ {
+- return m2m_ctx->cap_q_ctx.num_rdy;
++ unsigned int num_buf_rdy;
++ unsigned long flags;
++
++ spin_lock_irqsave(&m2m_ctx->cap_q_ctx.rdy_spinlock, flags);
++ num_buf_rdy = m2m_ctx->cap_q_ctx.num_rdy;
++ spin_unlock_irqrestore(&m2m_ctx->cap_q_ctx.rdy_spinlock, flags);
++
++ return num_buf_rdy;
+ }
+
+ /**
+diff --git a/include/net/bonding.h b/include/net/bonding.h
+index c458f084f7bb9..7d317434e3d13 100644
+--- a/include/net/bonding.h
++++ b/include/net/bonding.h
+@@ -675,37 +675,14 @@ static inline struct slave *bond_slave_has_mac(struct bonding *bond,
+ }
+
+ /* Caller must hold rcu_read_lock() for read */
+-static inline struct slave *bond_slave_has_mac_rcu(struct bonding *bond,
+- const u8 *mac)
++static inline bool bond_slave_has_mac_rcu(struct bonding *bond, const u8 *mac)
+ {
+ struct list_head *iter;
+ struct slave *tmp;
+
+- bond_for_each_slave_rcu(bond, tmp, iter)
+- if (ether_addr_equal_64bits(mac, tmp->dev->dev_addr))
+- return tmp;
+-
+- return NULL;
+-}
+-
+-/* Caller must hold rcu_read_lock() for read */
+-static inline bool bond_slave_has_mac_rx(struct bonding *bond, const u8 *mac)
+-{
+- struct list_head *iter;
+- struct slave *tmp;
+- struct netdev_hw_addr *ha;
+-
+ bond_for_each_slave_rcu(bond, tmp, iter)
+ if (ether_addr_equal_64bits(mac, tmp->dev->dev_addr))
+ return true;
+-
+- if (netdev_uc_empty(bond->dev))
+- return false;
+-
+- netdev_for_each_uc_addr(ha, bond->dev)
+- if (ether_addr_equal_64bits(mac, ha->addr))
+- return true;
+-
+ return false;
+ }
+
+diff --git a/include/net/sock.h b/include/net/sock.h
+index 72739f72e4b90..373e34b46a3c9 100644
+--- a/include/net/sock.h
++++ b/include/net/sock.h
+@@ -1152,6 +1152,7 @@ struct proto {
+ /*
+ * Pressure flag: try to collapse.
+ * Technical note: it is used by multiple contexts non atomically.
++ * Make sure to use READ_ONCE()/WRITE_ONCE() for all reads/writes.
+ * All the __sk_mem_schedule() is of this nature: accounting
+ * is strict, actions are advisory and have some latency.
+ */
+@@ -1265,6 +1266,12 @@ static inline bool sk_has_memory_pressure(const struct sock *sk)
+ return sk->sk_prot->memory_pressure != NULL;
+ }
+
++static inline bool sk_under_global_memory_pressure(const struct sock *sk)
++{
++ return sk->sk_prot->memory_pressure &&
++ !!READ_ONCE(*sk->sk_prot->memory_pressure);
++}
++
+ static inline bool sk_under_memory_pressure(const struct sock *sk)
+ {
+ if (!sk->sk_prot->memory_pressure)
+@@ -1274,7 +1281,7 @@ static inline bool sk_under_memory_pressure(const struct sock *sk)
+ mem_cgroup_under_socket_pressure(sk->sk_memcg))
+ return true;
+
+- return !!*sk->sk_prot->memory_pressure;
++ return !!READ_ONCE(*sk->sk_prot->memory_pressure);
+ }
+
+ static inline long
+@@ -1328,7 +1335,7 @@ proto_memory_pressure(struct proto *prot)
+ {
+ if (!prot->memory_pressure)
+ return false;
+- return !!*prot->memory_pressure;
++ return !!READ_ONCE(*prot->memory_pressure);
+ }
+
+
+diff --git a/kernel/sched/rt.c b/kernel/sched/rt.c
+index 9c6c3572b1312..394c66442cfff 100644
+--- a/kernel/sched/rt.c
++++ b/kernel/sched/rt.c
+@@ -1522,6 +1522,8 @@ static struct sched_rt_entity *pick_next_rt_entity(struct rq *rq,
+ BUG_ON(idx >= MAX_RT_PRIO);
+
+ queue = array->queue + idx;
++ if (SCHED_WARN_ON(list_empty(queue)))
++ return NULL;
+ next = list_entry(queue->next, struct sched_rt_entity, run_list);
+
+ return next;
+@@ -1535,7 +1537,8 @@ static struct task_struct *_pick_next_task_rt(struct rq *rq)
+
+ do {
+ rt_se = pick_next_rt_entity(rq, rt_rq);
+- BUG_ON(!rt_se);
++ if (unlikely(!rt_se))
++ return NULL;
+ rt_rq = group_rt_rq(rt_se);
+ } while (rt_rq);
+
+diff --git a/kernel/trace/trace.c b/kernel/trace/trace.c
+index 9da7b10e56d23..f44c8f1fd3ec5 100644
+--- a/kernel/trace/trace.c
++++ b/kernel/trace/trace.c
+@@ -3277,8 +3277,15 @@ static void *s_start(struct seq_file *m, loff_t *pos)
+ * will point to the same string as current_trace->name.
+ */
+ mutex_lock(&trace_types_lock);
+- if (unlikely(tr->current_trace && iter->trace->name != tr->current_trace->name))
++ if (unlikely(tr->current_trace && iter->trace->name != tr->current_trace->name)) {
++ /* Close iter->trace before switching to the new current tracer */
++ if (iter->trace->close)
++ iter->trace->close(iter);
+ *iter->trace = *tr->current_trace;
++ /* Reopen the new current tracer */
++ if (iter->trace->open)
++ iter->trace->open(iter);
++ }
+ mutex_unlock(&trace_types_lock);
+
+ #ifdef CONFIG_TRACER_MAX_TRACE
+diff --git a/kernel/trace/trace_irqsoff.c b/kernel/trace/trace_irqsoff.c
+index 98ea6d28df15d..0f36bb59970df 100644
+--- a/kernel/trace/trace_irqsoff.c
++++ b/kernel/trace/trace_irqsoff.c
+@@ -222,7 +222,8 @@ static void irqsoff_trace_open(struct trace_iterator *iter)
+ {
+ if (is_graph(iter->tr))
+ graph_trace_open(iter);
+-
++ else
++ iter->private = NULL;
+ }
+
+ static void irqsoff_trace_close(struct trace_iterator *iter)
+diff --git a/kernel/trace/trace_sched_wakeup.c b/kernel/trace/trace_sched_wakeup.c
+index 11f4dbd9526b6..8041bd5e42624 100644
+--- a/kernel/trace/trace_sched_wakeup.c
++++ b/kernel/trace/trace_sched_wakeup.c
+@@ -287,6 +287,8 @@ static void wakeup_trace_open(struct trace_iterator *iter)
+ {
+ if (is_graph(iter->tr))
+ graph_trace_open(iter);
++ else
++ iter->private = NULL;
+ }
+
+ static void wakeup_trace_close(struct trace_iterator *iter)
+diff --git a/lib/clz_ctz.c b/lib/clz_ctz.c
+index 2e11e48446abf..ca0582d33532f 100644
+--- a/lib/clz_ctz.c
++++ b/lib/clz_ctz.c
+@@ -30,36 +30,16 @@ int __weak __clzsi2(int val)
+ }
+ EXPORT_SYMBOL(__clzsi2);
+
+-int __weak __clzdi2(long val);
+-int __weak __ctzdi2(long val);
+-#if BITS_PER_LONG == 32
+-
+-int __weak __clzdi2(long val)
++int __weak __clzdi2(u64 val);
++int __weak __clzdi2(u64 val)
+ {
+- return 32 - fls((int)val);
++ return 64 - fls64(val);
+ }
+ EXPORT_SYMBOL(__clzdi2);
+
+-int __weak __ctzdi2(long val)
++int __weak __ctzdi2(u64 val);
++int __weak __ctzdi2(u64 val)
+ {
+- return __ffs((u32)val);
++ return __ffs64(val);
+ }
+ EXPORT_SYMBOL(__ctzdi2);
+-
+-#elif BITS_PER_LONG == 64
+-
+-int __weak __clzdi2(long val)
+-{
+- return 64 - fls64((u64)val);
+-}
+-EXPORT_SYMBOL(__clzdi2);
+-
+-int __weak __ctzdi2(long val)
+-{
+- return __ffs64((u64)val);
+-}
+-EXPORT_SYMBOL(__ctzdi2);
+-
+-#else
+-#error BITS_PER_LONG not 32 or 64
+-#endif
+diff --git a/lib/mpi/longlong.h b/lib/mpi/longlong.h
+index 6c5229f98c9eb..cac4e5aee7395 100644
+--- a/lib/mpi/longlong.h
++++ b/lib/mpi/longlong.h
+@@ -639,30 +639,12 @@ do { \
+ ************** MIPS *****************
+ ***************************************/
+ #if defined(__mips__) && W_TYPE_SIZE == 32
+-#if (__GNUC__ >= 5) || (__GNUC__ >= 4 && __GNUC_MINOR__ >= 4)
+ #define umul_ppmm(w1, w0, u, v) \
+ do { \
+ UDItype __ll = (UDItype)(u) * (v); \
+ w1 = __ll >> 32; \
+ w0 = __ll; \
+ } while (0)
+-#elif __GNUC__ > 2 || __GNUC_MINOR__ >= 7
+-#define umul_ppmm(w1, w0, u, v) \
+- __asm__ ("multu %2,%3" \
+- : "=l" ((USItype)(w0)), \
+- "=h" ((USItype)(w1)) \
+- : "d" ((USItype)(u)), \
+- "d" ((USItype)(v)))
+-#else
+-#define umul_ppmm(w1, w0, u, v) \
+- __asm__ ("multu %2,%3\n" \
+- "mflo %0\n" \
+- "mfhi %1" \
+- : "=d" ((USItype)(w0)), \
+- "=d" ((USItype)(w1)) \
+- : "d" ((USItype)(u)), \
+- "d" ((USItype)(v)))
+-#endif
+ #define UMUL_TIME 10
+ #define UDIV_TIME 100
+ #endif /* __mips__ */
+@@ -687,7 +669,7 @@ do { \
+ : "d" ((UDItype)(u)), \
+ "d" ((UDItype)(v))); \
+ } while (0)
+-#elif (__GNUC__ >= 5) || (__GNUC__ >= 4 && __GNUC_MINOR__ >= 4)
++#else
+ #define umul_ppmm(w1, w0, u, v) \
+ do { \
+ typedef unsigned int __ll_UTItype __attribute__((mode(TI))); \
+@@ -695,22 +677,6 @@ do { \
+ w1 = __ll >> 64; \
+ w0 = __ll; \
+ } while (0)
+-#elif __GNUC__ > 2 || __GNUC_MINOR__ >= 7
+-#define umul_ppmm(w1, w0, u, v) \
+- __asm__ ("dmultu %2,%3" \
+- : "=l" ((UDItype)(w0)), \
+- "=h" ((UDItype)(w1)) \
+- : "d" ((UDItype)(u)), \
+- "d" ((UDItype)(v)))
+-#else
+-#define umul_ppmm(w1, w0, u, v) \
+- __asm__ ("dmultu %2,%3\n" \
+- "mflo %0\n" \
+- "mfhi %1" \
+- : "=d" ((UDItype)(w0)), \
+- "=d" ((UDItype)(w1)) \
+- : "d" ((UDItype)(u)), \
+- "d" ((UDItype)(v)))
+ #endif
+ #define UMUL_TIME 20
+ #define UDIV_TIME 140
+diff --git a/lib/test_firmware.c b/lib/test_firmware.c
+index b5e779bcfb343..be3baea88b61d 100644
+--- a/lib/test_firmware.c
++++ b/lib/test_firmware.c
+@@ -284,16 +284,26 @@ static ssize_t config_test_show_str(char *dst,
+ return len;
+ }
+
+-static int test_dev_config_update_bool(const char *buf, size_t size,
+- bool *cfg)
++static inline int __test_dev_config_update_bool(const char *buf, size_t size,
++ bool *cfg)
+ {
+ int ret;
+
+- mutex_lock(&test_fw_mutex);
+ if (strtobool(buf, cfg) < 0)
+ ret = -EINVAL;
+ else
+ ret = size;
++
++ return ret;
++}
++
++static int test_dev_config_update_bool(const char *buf, size_t size,
++ bool *cfg)
++{
++ int ret;
++
++ mutex_lock(&test_fw_mutex);
++ ret = __test_dev_config_update_bool(buf, size, cfg);
+ mutex_unlock(&test_fw_mutex);
+
+ return ret;
+@@ -323,7 +333,7 @@ static ssize_t test_dev_config_show_int(char *buf, int cfg)
+ return snprintf(buf, PAGE_SIZE, "%d\n", val);
+ }
+
+-static int test_dev_config_update_u8(const char *buf, size_t size, u8 *cfg)
++static inline int __test_dev_config_update_u8(const char *buf, size_t size, u8 *cfg)
+ {
+ int ret;
+ long new;
+@@ -335,14 +345,23 @@ static int test_dev_config_update_u8(const char *buf, size_t size, u8 *cfg)
+ if (new > U8_MAX)
+ return -EINVAL;
+
+- mutex_lock(&test_fw_mutex);
+ *(u8 *)cfg = new;
+- mutex_unlock(&test_fw_mutex);
+
+ /* Always return full write size even if we didn't consume all */
+ return size;
+ }
+
++static int test_dev_config_update_u8(const char *buf, size_t size, u8 *cfg)
++{
++ int ret;
++
++ mutex_lock(&test_fw_mutex);
++ ret = __test_dev_config_update_u8(buf, size, cfg);
++ mutex_unlock(&test_fw_mutex);
++
++ return ret;
++}
++
+ static ssize_t test_dev_config_show_u8(char *buf, u8 cfg)
+ {
+ u8 val;
+@@ -375,10 +394,10 @@ static ssize_t config_num_requests_store(struct device *dev,
+ mutex_unlock(&test_fw_mutex);
+ goto out;
+ }
+- mutex_unlock(&test_fw_mutex);
+
+- rc = test_dev_config_update_u8(buf, count,
+- &test_fw_config->num_requests);
++ rc = __test_dev_config_update_u8(buf, count,
++ &test_fw_config->num_requests);
++ mutex_unlock(&test_fw_mutex);
+
+ out:
+ return rc;
+diff --git a/net/batman-adv/bat_v_elp.c b/net/batman-adv/bat_v_elp.c
+index af3da6cdfc798..17100d9ceaf0b 100644
+--- a/net/batman-adv/bat_v_elp.c
++++ b/net/batman-adv/bat_v_elp.c
+@@ -513,7 +513,7 @@ int batadv_v_elp_packet_recv(struct sk_buff *skb,
+ struct batadv_priv *bat_priv = netdev_priv(if_incoming->soft_iface);
+ struct batadv_elp_packet *elp_packet;
+ struct batadv_hard_iface *primary_if;
+- struct ethhdr *ethhdr = (struct ethhdr *)skb_mac_header(skb);
++ struct ethhdr *ethhdr;
+ bool res;
+ int ret = NET_RX_DROP;
+
+@@ -521,6 +521,7 @@ int batadv_v_elp_packet_recv(struct sk_buff *skb,
+ if (!res)
+ goto free_skb;
+
++ ethhdr = eth_hdr(skb);
+ if (batadv_is_my_mac(bat_priv, ethhdr->h_source))
+ goto free_skb;
+
+diff --git a/net/batman-adv/bat_v_ogm.c b/net/batman-adv/bat_v_ogm.c
+index 04a620fd13014..5d4232d8d6511 100644
+--- a/net/batman-adv/bat_v_ogm.c
++++ b/net/batman-adv/bat_v_ogm.c
+@@ -119,8 +119,10 @@ static void batadv_v_ogm_send_to_if(struct sk_buff *skb,
+ {
+ struct batadv_priv *bat_priv = netdev_priv(hard_iface->soft_iface);
+
+- if (hard_iface->if_status != BATADV_IF_ACTIVE)
++ if (hard_iface->if_status != BATADV_IF_ACTIVE) {
++ kfree_skb(skb);
+ return;
++ }
+
+ batadv_inc_counter(bat_priv, BATADV_CNT_MGMT_TX);
+ batadv_add_counter(bat_priv, BATADV_CNT_MGMT_TX_BYTES,
+@@ -832,7 +834,7 @@ int batadv_v_ogm_packet_recv(struct sk_buff *skb,
+ {
+ struct batadv_priv *bat_priv = netdev_priv(if_incoming->soft_iface);
+ struct batadv_ogm2_packet *ogm_packet;
+- struct ethhdr *ethhdr = eth_hdr(skb);
++ struct ethhdr *ethhdr;
+ int ogm_offset;
+ u8 *packet_pos;
+ int ret = NET_RX_DROP;
+@@ -846,6 +848,7 @@ int batadv_v_ogm_packet_recv(struct sk_buff *skb,
+ if (!batadv_check_management_packet(skb, if_incoming, BATADV_OGM2_HLEN))
+ goto free_skb;
+
++ ethhdr = eth_hdr(skb);
+ if (batadv_is_my_mac(bat_priv, ethhdr->h_source))
+ goto free_skb;
+
+diff --git a/net/batman-adv/hard-interface.c b/net/batman-adv/hard-interface.c
+index 6d68cdb9dd773..0d5519fcb4388 100644
+--- a/net/batman-adv/hard-interface.c
++++ b/net/batman-adv/hard-interface.c
+@@ -643,7 +643,19 @@ out:
+ */
+ void batadv_update_min_mtu(struct net_device *soft_iface)
+ {
+- soft_iface->mtu = batadv_hardif_min_mtu(soft_iface);
++ struct batadv_priv *bat_priv = netdev_priv(soft_iface);
++ int limit_mtu;
++ int mtu;
++
++ mtu = batadv_hardif_min_mtu(soft_iface);
++
++ if (bat_priv->mtu_set_by_user)
++ limit_mtu = bat_priv->mtu_set_by_user;
++ else
++ limit_mtu = ETH_DATA_LEN;
++
++ mtu = min(mtu, limit_mtu);
++ dev_set_mtu(soft_iface, mtu);
+
+ /* Check if the local translate table should be cleaned up to match a
+ * new (and smaller) MTU.
+diff --git a/net/batman-adv/soft-interface.c b/net/batman-adv/soft-interface.c
+index 1003abb8cc35e..7447dbd305fc1 100644
+--- a/net/batman-adv/soft-interface.c
++++ b/net/batman-adv/soft-interface.c
+@@ -167,11 +167,14 @@ static int batadv_interface_set_mac_addr(struct net_device *dev, void *p)
+
+ static int batadv_interface_change_mtu(struct net_device *dev, int new_mtu)
+ {
++ struct batadv_priv *bat_priv = netdev_priv(dev);
++
+ /* check ranges */
+ if (new_mtu < 68 || new_mtu > batadv_hardif_min_mtu(dev))
+ return -EINVAL;
+
+ dev->mtu = new_mtu;
++ bat_priv->mtu_set_by_user = new_mtu;
+
+ return 0;
+ }
+diff --git a/net/batman-adv/translation-table.c b/net/batman-adv/translation-table.c
+index 6bdb70c93e3fb..c64d58c1b724f 100644
+--- a/net/batman-adv/translation-table.c
++++ b/net/batman-adv/translation-table.c
+@@ -793,7 +793,6 @@ check_roaming:
+ if (roamed_back) {
+ batadv_tt_global_free(bat_priv, tt_global,
+ "Roaming canceled");
+- tt_global = NULL;
+ } else {
+ /* The global entry has to be marked as ROAMING and
+ * has to be kept for consistency purpose
+diff --git a/net/batman-adv/types.h b/net/batman-adv/types.h
+index 37598ae1d3f7a..34c18f72a41ba 100644
+--- a/net/batman-adv/types.h
++++ b/net/batman-adv/types.h
+@@ -1514,6 +1514,12 @@ struct batadv_priv {
+ /** @soft_iface: net device which holds this struct as private data */
+ struct net_device *soft_iface;
+
++ /**
++ * @mtu_set_by_user: MTU was set once by user
++ * protected by rtnl_lock
++ */
++ int mtu_set_by_user;
++
+ /**
+ * @bat_counters: mesh internal traffic statistic counters (see
+ * batadv_counters)
+diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c
+index fcc471f921895..9346fae5d664b 100644
+--- a/net/bluetooth/l2cap_core.c
++++ b/net/bluetooth/l2cap_core.c
+@@ -5705,9 +5705,14 @@ static inline int l2cap_le_command_rej(struct l2cap_conn *conn,
+ if (!chan)
+ goto done;
+
++ chan = l2cap_chan_hold_unless_zero(chan);
++ if (!chan)
++ goto done;
++
+ l2cap_chan_lock(chan);
+ l2cap_chan_del(chan, ECONNREFUSED);
+ l2cap_chan_unlock(chan);
++ l2cap_chan_put(chan);
+
+ done:
+ mutex_unlock(&conn->chan_lock);
+diff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c
+index 79f62517e24a5..794db633f1c90 100644
+--- a/net/core/rtnetlink.c
++++ b/net/core/rtnetlink.c
+@@ -2702,7 +2702,10 @@ static int rtnl_setlink(struct sk_buff *skb, struct nlmsghdr *nlh,
+ ifm = nlmsg_data(nlh);
+ if (ifm->ifi_index > 0)
+ dev = __dev_get_by_index(net, ifm->ifi_index);
+- else if (tb[IFLA_IFNAME])
++ else if (ifm->ifi_index < 0) {
++ NL_SET_ERR_MSG(extack, "ifindex can't be negative");
++ return -EINVAL;
++ } else if (tb[IFLA_IFNAME])
+ dev = __dev_get_by_name(net, ifname);
+ else
+ goto errout;
+diff --git a/net/core/sock.c b/net/core/sock.c
+index 3e6da3694a5a5..4e3ed80a68ceb 100644
+--- a/net/core/sock.c
++++ b/net/core/sock.c
+@@ -2538,7 +2538,7 @@ void __sk_mem_reduce_allocated(struct sock *sk, int amount)
+ if (mem_cgroup_sockets_enabled && sk->sk_memcg)
+ mem_cgroup_uncharge_skmem(sk->sk_memcg, amount);
+
+- if (sk_under_memory_pressure(sk) &&
++ if (sk_under_global_memory_pressure(sk) &&
+ (sk_memory_allocated(sk) < sk_prot_mem_limits(sk, 0)))
+ sk_leave_memory_pressure(sk);
+ }
+diff --git a/net/dccp/proto.c b/net/dccp/proto.c
+index 27de4dc1ff512..c4ea0159ce2e8 100644
+--- a/net/dccp/proto.c
++++ b/net/dccp/proto.c
+@@ -328,11 +328,15 @@ EXPORT_SYMBOL_GPL(dccp_disconnect);
+ __poll_t dccp_poll(struct file *file, struct socket *sock,
+ poll_table *wait)
+ {
+- __poll_t mask;
+ struct sock *sk = sock->sk;
++ __poll_t mask;
++ u8 shutdown;
++ int state;
+
+ sock_poll_wait(file, sock, wait);
+- if (sk->sk_state == DCCP_LISTEN)
++
++ state = inet_sk_state_load(sk);
++ if (state == DCCP_LISTEN)
+ return inet_csk_listen_poll(sk);
+
+ /* Socket is not locked. We are protected from async events
+@@ -341,20 +345,21 @@ __poll_t dccp_poll(struct file *file, struct socket *sock,
+ */
+
+ mask = 0;
+- if (sk->sk_err)
++ if (READ_ONCE(sk->sk_err))
+ mask = EPOLLERR;
++ shutdown = READ_ONCE(sk->sk_shutdown);
+
+- if (sk->sk_shutdown == SHUTDOWN_MASK || sk->sk_state == DCCP_CLOSED)
++ if (shutdown == SHUTDOWN_MASK || state == DCCP_CLOSED)
+ mask |= EPOLLHUP;
+- if (sk->sk_shutdown & RCV_SHUTDOWN)
++ if (shutdown & RCV_SHUTDOWN)
+ mask |= EPOLLIN | EPOLLRDNORM | EPOLLRDHUP;
+
+ /* Connected? */
+- if ((1 << sk->sk_state) & ~(DCCPF_REQUESTING | DCCPF_RESPOND)) {
++ if ((1 << state) & ~(DCCPF_REQUESTING | DCCPF_RESPOND)) {
+ if (atomic_read(&sk->sk_rmem_alloc) > 0)
+ mask |= EPOLLIN | EPOLLRDNORM;
+
+- if (!(sk->sk_shutdown & SEND_SHUTDOWN)) {
++ if (!(shutdown & SEND_SHUTDOWN)) {
+ if (sk_stream_is_writeable(sk)) {
+ mask |= EPOLLOUT | EPOLLWRNORM;
+ } else { /* send SIGIO later */
+@@ -372,7 +377,6 @@ __poll_t dccp_poll(struct file *file, struct socket *sock,
+ }
+ return mask;
+ }
+-
+ EXPORT_SYMBOL_GPL(dccp_poll);
+
+ int dccp_ioctl(struct sock *sk, int cmd, unsigned long arg)
+diff --git a/net/ipv4/ip_vti.c b/net/ipv4/ip_vti.c
+index 15c71b08c2df4..a3536dfe9b16b 100644
+--- a/net/ipv4/ip_vti.c
++++ b/net/ipv4/ip_vti.c
+@@ -319,12 +319,12 @@ static netdev_tx_t vti_tunnel_xmit(struct sk_buff *skb, struct net_device *dev)
+
+ switch (skb->protocol) {
+ case htons(ETH_P_IP):
+- xfrm_decode_session(skb, &fl, AF_INET);
+ memset(IPCB(skb), 0, sizeof(*IPCB(skb)));
++ xfrm_decode_session(skb, &fl, AF_INET);
+ break;
+ case htons(ETH_P_IPV6):
+- xfrm_decode_session(skb, &fl, AF_INET6);
+ memset(IP6CB(skb), 0, sizeof(*IP6CB(skb)));
++ xfrm_decode_session(skb, &fl, AF_INET6);
+ break;
+ default:
+ goto tx_err;
+diff --git a/net/ipv4/tcp_timer.c b/net/ipv4/tcp_timer.c
+index 84069db0423a2..d8d28ba169b4d 100644
+--- a/net/ipv4/tcp_timer.c
++++ b/net/ipv4/tcp_timer.c
+@@ -549,7 +549,9 @@ out_reset_timer:
+ tcp_stream_is_thin(tp) &&
+ icsk->icsk_retransmits <= TCP_THIN_LINEAR_RETRIES) {
+ icsk->icsk_backoff = 0;
+- icsk->icsk_rto = min(__tcp_set_rto(tp), TCP_RTO_MAX);
++ icsk->icsk_rto = clamp(__tcp_set_rto(tp),
++ tcp_rto_min(sk),
++ TCP_RTO_MAX);
+ } else {
+ /* Use normal (exponential) backoff */
+ icsk->icsk_rto = min(icsk->icsk_rto << 1, TCP_RTO_MAX);
+diff --git a/net/ipv6/ip6_vti.c b/net/ipv6/ip6_vti.c
+index 866ce815625e5..a64050e775882 100644
+--- a/net/ipv6/ip6_vti.c
++++ b/net/ipv6/ip6_vti.c
+@@ -562,12 +562,12 @@ vti6_tnl_xmit(struct sk_buff *skb, struct net_device *dev)
+ vti6_addr_conflict(t, ipv6_hdr(skb)))
+ goto tx_err;
+
+- xfrm_decode_session(skb, &fl, AF_INET6);
+ memset(IP6CB(skb), 0, sizeof(*IP6CB(skb)));
++ xfrm_decode_session(skb, &fl, AF_INET6);
+ break;
+ case htons(ETH_P_IP):
+- xfrm_decode_session(skb, &fl, AF_INET);
+ memset(IPCB(skb), 0, sizeof(*IPCB(skb)));
++ xfrm_decode_session(skb, &fl, AF_INET);
+ break;
+ default:
+ goto tx_err;
+diff --git a/net/key/af_key.c b/net/key/af_key.c
+index b8456e2f11673..47ffa69ca6f67 100644
+--- a/net/key/af_key.c
++++ b/net/key/af_key.c
+@@ -1858,9 +1858,9 @@ static int pfkey_dump(struct sock *sk, struct sk_buff *skb, const struct sadb_ms
+ if (ext_hdrs[SADB_X_EXT_FILTER - 1]) {
+ struct sadb_x_filter *xfilter = ext_hdrs[SADB_X_EXT_FILTER - 1];
+
+- if ((xfilter->sadb_x_filter_splen >=
++ if ((xfilter->sadb_x_filter_splen >
+ (sizeof(xfrm_address_t) << 3)) ||
+- (xfilter->sadb_x_filter_dplen >=
++ (xfilter->sadb_x_filter_dplen >
+ (sizeof(xfrm_address_t) << 3))) {
+ mutex_unlock(&pfk->dump_lock);
+ return -EINVAL;
+diff --git a/net/netfilter/ipvs/ip_vs_ctl.c b/net/netfilter/ipvs/ip_vs_ctl.c
+index 3bf8d7f3cdc32..0909f32eabfd1 100644
+--- a/net/netfilter/ipvs/ip_vs_ctl.c
++++ b/net/netfilter/ipvs/ip_vs_ctl.c
+@@ -1656,6 +1656,7 @@ static int ip_vs_zero_all(struct netns_ipvs *ipvs)
+ #ifdef CONFIG_SYSCTL
+
+ static int zero;
++static int one = 1;
+ static int three = 3;
+
+ static int
+@@ -1667,12 +1668,18 @@ proc_do_defense_mode(struct ctl_table *table, int write,
+ int val = *valp;
+ int rc;
+
+- rc = proc_dointvec(table, write, buffer, lenp, ppos);
++ struct ctl_table tmp = {
++ .data = &val,
++ .maxlen = sizeof(int),
++ .mode = table->mode,
++ };
++
++ rc = proc_dointvec(&tmp, write, buffer, lenp, ppos);
+ if (write && (*valp != val)) {
+- if ((*valp < 0) || (*valp > 3)) {
+- /* Restore the correct value */
+- *valp = val;
++ if (val < 0 || val > 3) {
++ rc = -EINVAL;
+ } else {
++ *valp = val;
+ update_defense_level(ipvs);
+ }
+ }
+@@ -1683,37 +1690,27 @@ static int
+ proc_do_sync_threshold(struct ctl_table *table, int write,
+ void __user *buffer, size_t *lenp, loff_t *ppos)
+ {
++ struct netns_ipvs *ipvs = table->extra2;
+ int *valp = table->data;
+ int val[2];
+ int rc;
++ struct ctl_table tmp = {
++ .data = &val,
++ .maxlen = table->maxlen,
++ .mode = table->mode,
++ };
+
+- /* backup the value first */
++ mutex_lock(&ipvs->sync_mutex);
+ memcpy(val, valp, sizeof(val));
+-
+- rc = proc_dointvec(table, write, buffer, lenp, ppos);
+- if (write && (valp[0] < 0 || valp[1] < 0 ||
+- (valp[0] >= valp[1] && valp[1]))) {
+- /* Restore the correct value */
+- memcpy(valp, val, sizeof(val));
+- }
+- return rc;
+-}
+-
+-static int
+-proc_do_sync_mode(struct ctl_table *table, int write,
+- void __user *buffer, size_t *lenp, loff_t *ppos)
+-{
+- int *valp = table->data;
+- int val = *valp;
+- int rc;
+-
+- rc = proc_dointvec(table, write, buffer, lenp, ppos);
+- if (write && (*valp != val)) {
+- if ((*valp < 0) || (*valp > 1)) {
+- /* Restore the correct value */
+- *valp = val;
+- }
++ rc = proc_dointvec(&tmp, write, buffer, lenp, ppos);
++ if (write) {
++ if (val[0] < 0 || val[1] < 0 ||
++ (val[0] >= val[1] && val[1]))
++ rc = -EINVAL;
++ else
++ memcpy(valp, val, sizeof(val));
+ }
++ mutex_unlock(&ipvs->sync_mutex);
+ return rc;
+ }
+
+@@ -1725,12 +1722,18 @@ proc_do_sync_ports(struct ctl_table *table, int write,
+ int val = *valp;
+ int rc;
+
+- rc = proc_dointvec(table, write, buffer, lenp, ppos);
++ struct ctl_table tmp = {
++ .data = &val,
++ .maxlen = sizeof(int),
++ .mode = table->mode,
++ };
++
++ rc = proc_dointvec(&tmp, write, buffer, lenp, ppos);
+ if (write && (*valp != val)) {
+- if (*valp < 1 || !is_power_of_2(*valp)) {
+- /* Restore the correct value */
++ if (val < 1 || !is_power_of_2(val))
++ rc = -EINVAL;
++ else
+ *valp = val;
+- }
+ }
+ return rc;
+ }
+@@ -1790,7 +1793,9 @@ static struct ctl_table vs_vars[] = {
+ .procname = "sync_version",
+ .maxlen = sizeof(int),
+ .mode = 0644,
+- .proc_handler = proc_do_sync_mode,
++ .proc_handler = proc_dointvec_minmax,
++ .extra1 = &zero,
++ .extra2 = &one,
+ },
+ {
+ .procname = "sync_ports",
+@@ -3942,6 +3947,7 @@ static int __net_init ip_vs_control_net_init_sysctl(struct netns_ipvs *ipvs)
+ ipvs->sysctl_sync_threshold[0] = DEFAULT_SYNC_THRESHOLD;
+ ipvs->sysctl_sync_threshold[1] = DEFAULT_SYNC_PERIOD;
+ tbl[idx].data = &ipvs->sysctl_sync_threshold;
++ tbl[idx].extra2 = ipvs;
+ tbl[idx++].maxlen = sizeof(ipvs->sysctl_sync_threshold);
+ ipvs->sysctl_sync_refresh_period = DEFAULT_SYNC_REFRESH_PERIOD;
+ tbl[idx++].data = &ipvs->sysctl_sync_refresh_period;
+diff --git a/net/netfilter/nf_conntrack_proto_sctp.c b/net/netfilter/nf_conntrack_proto_sctp.c
+index cadeb22a48f23..8453e92936ac9 100644
+--- a/net/netfilter/nf_conntrack_proto_sctp.c
++++ b/net/netfilter/nf_conntrack_proto_sctp.c
+@@ -58,8 +58,8 @@ static const unsigned int sctp_timeouts[SCTP_CONNTRACK_MAX] = {
+ [SCTP_CONNTRACK_COOKIE_WAIT] = 3 SECS,
+ [SCTP_CONNTRACK_COOKIE_ECHOED] = 3 SECS,
+ [SCTP_CONNTRACK_ESTABLISHED] = 5 DAYS,
+- [SCTP_CONNTRACK_SHUTDOWN_SENT] = 300 SECS / 1000,
+- [SCTP_CONNTRACK_SHUTDOWN_RECD] = 300 SECS / 1000,
++ [SCTP_CONNTRACK_SHUTDOWN_SENT] = 3 SECS,
++ [SCTP_CONNTRACK_SHUTDOWN_RECD] = 3 SECS,
+ [SCTP_CONNTRACK_SHUTDOWN_ACK_SENT] = 3 SECS,
+ [SCTP_CONNTRACK_HEARTBEAT_SENT] = 30 SECS,
+ [SCTP_CONNTRACK_HEARTBEAT_ACKED] = 210 SECS,
+@@ -119,7 +119,7 @@ static const u8 sctp_conntracks[2][11][SCTP_CONNTRACK_MAX] = {
+ {
+ /* ORIGINAL */
+ /* sNO, sCL, sCW, sCE, sES, sSS, sSR, sSA, sHS, sHA */
+-/* init */ {sCW, sCW, sCW, sCE, sES, sSS, sSR, sSA, sCW, sHA},
++/* init */ {sCW, sCW, sCW, sCE, sES, sCL, sCL, sSA, sCW, sHA},
+ /* init_ack */ {sCL, sCL, sCW, sCE, sES, sSS, sSR, sSA, sCL, sHA},
+ /* abort */ {sCL, sCL, sCL, sCL, sCL, sCL, sCL, sCL, sCL, sCL},
+ /* shutdown */ {sCL, sCL, sCW, sCE, sSS, sSS, sSR, sSA, sCL, sSS},
+diff --git a/net/netfilter/nf_queue.c b/net/netfilter/nf_queue.c
+index 84c59de278822..b3a0385290a15 100644
+--- a/net/netfilter/nf_queue.c
++++ b/net/netfilter/nf_queue.c
+@@ -93,8 +93,6 @@ bool nf_queue_entry_get_refs(struct nf_queue_entry *entry)
+ dev_hold(state->in);
+ if (state->out)
+ dev_hold(state->out);
+- if (state->sk)
+- sock_hold(state->sk);
+ #if IS_ENABLED(CONFIG_BRIDGE_NETFILTER)
+ if (entry->skb->nf_bridge) {
+ struct net_device *physdev;
+diff --git a/net/netfilter/nft_dynset.c b/net/netfilter/nft_dynset.c
+index 651c9784904cb..a4c6aba7da7ee 100644
+--- a/net/netfilter/nft_dynset.c
++++ b/net/netfilter/nft_dynset.c
+@@ -144,6 +144,9 @@ static int nft_dynset_init(const struct nft_ctx *ctx,
+ if (IS_ERR(set))
+ return PTR_ERR(set);
+
++ if (set->flags & NFT_SET_OBJECT)
++ return -EOPNOTSUPP;
++
+ if (set->ops->update == NULL)
+ return -EOPNOTSUPP;
+
+diff --git a/net/sched/sch_api.c b/net/sched/sch_api.c
+index 5a0e71873e24b..8105563593b6f 100644
+--- a/net/sched/sch_api.c
++++ b/net/sched/sch_api.c
+@@ -1438,10 +1438,28 @@ static int tc_get_qdisc(struct sk_buff *skb, struct nlmsghdr *n,
+ return 0;
+ }
+
++static bool req_create_or_replace(struct nlmsghdr *n)
++{
++ return (n->nlmsg_flags & NLM_F_CREATE &&
++ n->nlmsg_flags & NLM_F_REPLACE);
++}
++
++static bool req_create_exclusive(struct nlmsghdr *n)
++{
++ return (n->nlmsg_flags & NLM_F_CREATE &&
++ n->nlmsg_flags & NLM_F_EXCL);
++}
++
++static bool req_change(struct nlmsghdr *n)
++{
++ return (!(n->nlmsg_flags & NLM_F_CREATE) &&
++ !(n->nlmsg_flags & NLM_F_REPLACE) &&
++ !(n->nlmsg_flags & NLM_F_EXCL));
++}
++
+ /*
+ * Create/change qdisc.
+ */
+-
+ static int tc_modify_qdisc(struct sk_buff *skb, struct nlmsghdr *n,
+ struct netlink_ext_ack *extack)
+ {
+@@ -1538,27 +1556,35 @@ replay:
+ *
+ * We know, that some child q is already
+ * attached to this parent and have choice:
+- * either to change it or to create/graft new one.
++ * 1) change it or 2) create/graft new one.
++ * If the requested qdisc kind is different
++ * than the existing one, then we choose graft.
++ * If they are the same then this is "change"
++ * operation - just let it fallthrough..
+ *
+ * 1. We are allowed to create/graft only
+- * if CREATE and REPLACE flags are set.
++ * if the request is explicitly stating
++ * "please create if it doesn't exist".
+ *
+- * 2. If EXCL is set, requestor wanted to say,
+- * that qdisc tcm_handle is not expected
++ * 2. If the request is to exclusive create
++ * then the qdisc tcm_handle is not expected
+ * to exist, so that we choose create/graft too.
+ *
+ * 3. The last case is when no flags are set.
++ * This will happen when for example tc
++ * utility issues a "change" command.
+ * Alas, it is sort of hole in API, we
+ * cannot decide what to do unambiguously.
+- * For now we select create/graft, if
+- * user gave KIND, which does not match existing.
++ * For now we select create/graft.
+ */
+- if ((n->nlmsg_flags & NLM_F_CREATE) &&
+- (n->nlmsg_flags & NLM_F_REPLACE) &&
+- ((n->nlmsg_flags & NLM_F_EXCL) ||
+- (tca[TCA_KIND] &&
+- nla_strcmp(tca[TCA_KIND], q->ops->id))))
+- goto create_n_graft;
++ if (tca[TCA_KIND] &&
++ nla_strcmp(tca[TCA_KIND], q->ops->id)) {
++ if (req_create_or_replace(n) ||
++ req_create_exclusive(n))
++ goto create_n_graft;
++ else if (req_change(n))
++ goto create_n_graft2;
++ }
+ }
+ }
+ } else {
+@@ -1592,6 +1618,7 @@ create_n_graft:
+ NL_SET_ERR_MSG(extack, "Qdisc not found. To create specify NLM_F_CREATE flag");
+ return -ENOENT;
+ }
++create_n_graft2:
+ if (clid == TC_H_INGRESS) {
+ if (dev_ingress_queue(dev)) {
+ q = qdisc_create(dev, dev_ingress_queue(dev), p,
+diff --git a/net/sctp/socket.c b/net/sctp/socket.c
+index baa825751c393..432dccd375064 100644
+--- a/net/sctp/socket.c
++++ b/net/sctp/socket.c
+@@ -112,7 +112,7 @@ struct percpu_counter sctp_sockets_allocated;
+
+ static void sctp_enter_memory_pressure(struct sock *sk)
+ {
+- sctp_memory_pressure = 1;
++ WRITE_ONCE(sctp_memory_pressure, 1);
+ }
+
+
+diff --git a/net/unix/af_unix.c b/net/unix/af_unix.c
+index 8971341c4f8af..402060cf3198c 100644
+--- a/net/unix/af_unix.c
++++ b/net/unix/af_unix.c
+@@ -1984,6 +1984,7 @@ static ssize_t unix_stream_sendpage(struct socket *socket, struct page *page,
+
+ if (false) {
+ alloc_skb:
++ spin_unlock(&other->sk_receive_queue.lock);
+ unix_state_unlock(other);
+ mutex_unlock(&unix_sk(other)->iolock);
+ newskb = sock_alloc_send_pskb(sk, 0, 0, flags & MSG_DONTWAIT,
+@@ -2023,6 +2024,7 @@ alloc_skb:
+ init_scm = false;
+ }
+
++ spin_lock(&other->sk_receive_queue.lock);
+ skb = skb_peek_tail(&other->sk_receive_queue);
+ if (tail && tail == skb) {
+ skb = newskb;
+@@ -2053,14 +2055,11 @@ alloc_skb:
+ refcount_add(size, &sk->sk_wmem_alloc);
+
+ if (newskb) {
+- err = unix_scm_to_skb(&scm, skb, false);
+- if (err)
+- goto err_state_unlock;
+- spin_lock(&other->sk_receive_queue.lock);
++ unix_scm_to_skb(&scm, skb, false);
+ __skb_queue_tail(&other->sk_receive_queue, newskb);
+- spin_unlock(&other->sk_receive_queue.lock);
+ }
+
++ spin_unlock(&other->sk_receive_queue.lock);
+ unix_state_unlock(other);
+ mutex_unlock(&unix_sk(other)->iolock);
+
+diff --git a/net/xfrm/Makefile b/net/xfrm/Makefile
+index fbc4552d17b85..6e5e307f985e4 100644
+--- a/net/xfrm/Makefile
++++ b/net/xfrm/Makefile
+@@ -3,6 +3,8 @@
+ # Makefile for the XFRM subsystem.
+ #
+
++xfrm_interface-$(CONFIG_XFRM_INTERFACE) += xfrm_interface_core.o
++
+ obj-$(CONFIG_XFRM) := xfrm_policy.o xfrm_state.o xfrm_hash.o \
+ xfrm_input.o xfrm_output.o \
+ xfrm_sysctl.o xfrm_replay.o xfrm_device.o
+diff --git a/net/xfrm/xfrm_interface.c b/net/xfrm/xfrm_interface.c
+deleted file mode 100644
+index 3c642328a117c..0000000000000
+--- a/net/xfrm/xfrm_interface.c
++++ /dev/null
+@@ -1,996 +0,0 @@
+-// SPDX-License-Identifier: GPL-2.0
+-/*
+- * XFRM virtual interface
+- *
+- * Copyright (C) 2018 secunet Security Networks AG
+- *
+- * Author:
+- * Steffen Klassert <steffen.klassert@secunet.com>
+- */
+-
+-#include <linux/module.h>
+-#include <linux/capability.h>
+-#include <linux/errno.h>
+-#include <linux/types.h>
+-#include <linux/sockios.h>
+-#include <linux/icmp.h>
+-#include <linux/if.h>
+-#include <linux/in.h>
+-#include <linux/ip.h>
+-#include <linux/net.h>
+-#include <linux/in6.h>
+-#include <linux/netdevice.h>
+-#include <linux/if_link.h>
+-#include <linux/if_arp.h>
+-#include <linux/icmpv6.h>
+-#include <linux/init.h>
+-#include <linux/route.h>
+-#include <linux/rtnetlink.h>
+-#include <linux/netfilter_ipv6.h>
+-#include <linux/slab.h>
+-#include <linux/hash.h>
+-
+-#include <linux/uaccess.h>
+-#include <linux/atomic.h>
+-
+-#include <net/icmp.h>
+-#include <net/ip.h>
+-#include <net/ipv6.h>
+-#include <net/ip6_route.h>
+-#include <net/addrconf.h>
+-#include <net/xfrm.h>
+-#include <net/net_namespace.h>
+-#include <net/netns/generic.h>
+-#include <linux/etherdevice.h>
+-
+-static int xfrmi_dev_init(struct net_device *dev);
+-static void xfrmi_dev_setup(struct net_device *dev);
+-static struct rtnl_link_ops xfrmi_link_ops __read_mostly;
+-static unsigned int xfrmi_net_id __read_mostly;
+-
+-struct xfrmi_net {
+- /* lists for storing interfaces in use */
+- struct xfrm_if __rcu *xfrmi[1];
+-};
+-
+-#define for_each_xfrmi_rcu(start, xi) \
+- for (xi = rcu_dereference(start); xi; xi = rcu_dereference(xi->next))
+-
+-static struct xfrm_if *xfrmi_lookup(struct net *net, struct xfrm_state *x)
+-{
+- struct xfrmi_net *xfrmn = net_generic(net, xfrmi_net_id);
+- struct xfrm_if *xi;
+-
+- for_each_xfrmi_rcu(xfrmn->xfrmi[0], xi) {
+- if (x->if_id == xi->p.if_id &&
+- (xi->dev->flags & IFF_UP))
+- return xi;
+- }
+-
+- return NULL;
+-}
+-
+-static struct xfrm_if *xfrmi_decode_session(struct sk_buff *skb,
+- unsigned short family)
+-{
+- struct xfrmi_net *xfrmn;
+- struct xfrm_if *xi;
+- int ifindex = 0;
+-
+- if (!secpath_exists(skb) || !skb->dev)
+- return NULL;
+-
+- switch (family) {
+- case AF_INET6:
+- ifindex = inet6_sdif(skb);
+- break;
+- case AF_INET:
+- ifindex = inet_sdif(skb);
+- break;
+- }
+- if (!ifindex)
+- ifindex = skb->dev->ifindex;
+-
+- xfrmn = net_generic(xs_net(xfrm_input_state(skb)), xfrmi_net_id);
+-
+- for_each_xfrmi_rcu(xfrmn->xfrmi[0], xi) {
+- if (ifindex == xi->dev->ifindex &&
+- (xi->dev->flags & IFF_UP))
+- return xi;
+- }
+-
+- return NULL;
+-}
+-
+-static void xfrmi_link(struct xfrmi_net *xfrmn, struct xfrm_if *xi)
+-{
+- struct xfrm_if __rcu **xip = &xfrmn->xfrmi[0];
+-
+- rcu_assign_pointer(xi->next , rtnl_dereference(*xip));
+- rcu_assign_pointer(*xip, xi);
+-}
+-
+-static void xfrmi_unlink(struct xfrmi_net *xfrmn, struct xfrm_if *xi)
+-{
+- struct xfrm_if __rcu **xip;
+- struct xfrm_if *iter;
+-
+- for (xip = &xfrmn->xfrmi[0];
+- (iter = rtnl_dereference(*xip)) != NULL;
+- xip = &iter->next) {
+- if (xi == iter) {
+- rcu_assign_pointer(*xip, xi->next);
+- break;
+- }
+- }
+-}
+-
+-static void xfrmi_dev_free(struct net_device *dev)
+-{
+- struct xfrm_if *xi = netdev_priv(dev);
+-
+- gro_cells_destroy(&xi->gro_cells);
+- free_percpu(dev->tstats);
+-}
+-
+-static int xfrmi_create(struct net_device *dev)
+-{
+- struct xfrm_if *xi = netdev_priv(dev);
+- struct net *net = dev_net(dev);
+- struct xfrmi_net *xfrmn = net_generic(net, xfrmi_net_id);
+- int err;
+-
+- dev->rtnl_link_ops = &xfrmi_link_ops;
+- err = register_netdevice(dev);
+- if (err < 0)
+- goto out;
+-
+- dev_hold(dev);
+- xfrmi_link(xfrmn, xi);
+-
+- return 0;
+-
+-out:
+- return err;
+-}
+-
+-static struct xfrm_if *xfrmi_locate(struct net *net, struct xfrm_if_parms *p)
+-{
+- struct xfrm_if __rcu **xip;
+- struct xfrm_if *xi;
+- struct xfrmi_net *xfrmn = net_generic(net, xfrmi_net_id);
+-
+- for (xip = &xfrmn->xfrmi[0];
+- (xi = rtnl_dereference(*xip)) != NULL;
+- xip = &xi->next)
+- if (xi->p.if_id == p->if_id)
+- return xi;
+-
+- return NULL;
+-}
+-
+-static void xfrmi_dev_uninit(struct net_device *dev)
+-{
+- struct xfrm_if *xi = netdev_priv(dev);
+- struct xfrmi_net *xfrmn = net_generic(xi->net, xfrmi_net_id);
+-
+- xfrmi_unlink(xfrmn, xi);
+- dev_put(dev);
+-}
+-
+-static void xfrmi_scrub_packet(struct sk_buff *skb, bool xnet)
+-{
+- skb->tstamp = 0;
+- skb->pkt_type = PACKET_HOST;
+- skb->skb_iif = 0;
+- skb->ignore_df = 0;
+- skb_dst_drop(skb);
+- nf_reset(skb);
+- nf_reset_trace(skb);
+-
+- if (!xnet)
+- return;
+-
+- ipvs_reset(skb);
+- secpath_reset(skb);
+- skb_orphan(skb);
+- skb->mark = 0;
+-}
+-
+-static int xfrmi_rcv_cb(struct sk_buff *skb, int err)
+-{
+- struct pcpu_sw_netstats *tstats;
+- struct xfrm_mode *inner_mode;
+- struct net_device *dev;
+- struct xfrm_state *x;
+- struct xfrm_if *xi;
+- bool xnet;
+-
+- if (err && !skb->sp)
+- return 0;
+-
+- x = xfrm_input_state(skb);
+-
+- xi = xfrmi_lookup(xs_net(x), x);
+- if (!xi)
+- return 1;
+-
+- dev = xi->dev;
+- skb->dev = dev;
+-
+- if (err) {
+- dev->stats.rx_errors++;
+- dev->stats.rx_dropped++;
+-
+- return 0;
+- }
+-
+- xnet = !net_eq(xi->net, dev_net(skb->dev));
+-
+- if (xnet) {
+- inner_mode = x->inner_mode;
+-
+- if (x->sel.family == AF_UNSPEC) {
+- inner_mode = xfrm_ip2inner_mode(x, XFRM_MODE_SKB_CB(skb)->protocol);
+- if (inner_mode == NULL) {
+- XFRM_INC_STATS(dev_net(skb->dev),
+- LINUX_MIB_XFRMINSTATEMODEERROR);
+- return -EINVAL;
+- }
+- }
+-
+- if (!xfrm_policy_check(NULL, XFRM_POLICY_IN, skb,
+- inner_mode->afinfo->family))
+- return -EPERM;
+- }
+-
+- xfrmi_scrub_packet(skb, xnet);
+-
+- tstats = this_cpu_ptr(dev->tstats);
+-
+- u64_stats_update_begin(&tstats->syncp);
+- tstats->rx_packets++;
+- tstats->rx_bytes += skb->len;
+- u64_stats_update_end(&tstats->syncp);
+-
+- return 0;
+-}
+-
+-static int
+-xfrmi_xmit2(struct sk_buff *skb, struct net_device *dev, struct flowi *fl)
+-{
+- struct xfrm_if *xi = netdev_priv(dev);
+- struct net_device_stats *stats = &xi->dev->stats;
+- struct dst_entry *dst = skb_dst(skb);
+- unsigned int length = skb->len;
+- struct net_device *tdev;
+- struct xfrm_state *x;
+- int err = -1;
+- int mtu;
+-
+- dst_hold(dst);
+- dst = xfrm_lookup_with_ifid(xi->net, dst, fl, NULL, 0, xi->p.if_id);
+- if (IS_ERR(dst)) {
+- err = PTR_ERR(dst);
+- dst = NULL;
+- goto tx_err_link_failure;
+- }
+-
+- x = dst->xfrm;
+- if (!x)
+- goto tx_err_link_failure;
+-
+- if (x->if_id != xi->p.if_id)
+- goto tx_err_link_failure;
+-
+- tdev = dst->dev;
+-
+- if (tdev == dev) {
+- stats->collisions++;
+- net_warn_ratelimited("%s: Local routing loop detected!\n",
+- dev->name);
+- goto tx_err_dst_release;
+- }
+-
+- mtu = dst_mtu(dst);
+- if (skb->len > mtu) {
+- skb_dst_update_pmtu_no_confirm(skb, mtu);
+-
+- if (skb->protocol == htons(ETH_P_IPV6)) {
+- if (mtu < IPV6_MIN_MTU)
+- mtu = IPV6_MIN_MTU;
+-
+- if (skb->len > 1280)
+- icmpv6_ndo_send(skb, ICMPV6_PKT_TOOBIG, 0, mtu);
+- else
+- goto xmit;
+- } else {
+- if (!(ip_hdr(skb)->frag_off & htons(IP_DF)))
+- goto xmit;
+- icmp_ndo_send(skb, ICMP_DEST_UNREACH, ICMP_FRAG_NEEDED,
+- htonl(mtu));
+- }
+-
+- dst_release(dst);
+- return -EMSGSIZE;
+- }
+-
+-xmit:
+- xfrmi_scrub_packet(skb, !net_eq(xi->net, dev_net(dev)));
+- skb_dst_set(skb, dst);
+- skb->dev = tdev;
+-
+- err = dst_output(xi->net, skb->sk, skb);
+- if (net_xmit_eval(err) == 0) {
+- struct pcpu_sw_netstats *tstats = this_cpu_ptr(dev->tstats);
+-
+- u64_stats_update_begin(&tstats->syncp);
+- tstats->tx_bytes += length;
+- tstats->tx_packets++;
+- u64_stats_update_end(&tstats->syncp);
+- } else {
+- stats->tx_errors++;
+- stats->tx_aborted_errors++;
+- }
+-
+- return 0;
+-tx_err_link_failure:
+- stats->tx_carrier_errors++;
+- dst_link_failure(skb);
+-tx_err_dst_release:
+- dst_release(dst);
+- return err;
+-}
+-
+-static netdev_tx_t xfrmi_xmit(struct sk_buff *skb, struct net_device *dev)
+-{
+- struct xfrm_if *xi = netdev_priv(dev);
+- struct net_device_stats *stats = &xi->dev->stats;
+- struct dst_entry *dst = skb_dst(skb);
+- struct flowi fl;
+- int ret;
+-
+- memset(&fl, 0, sizeof(fl));
+-
+- switch (skb->protocol) {
+- case htons(ETH_P_IPV6):
+- xfrm_decode_session(skb, &fl, AF_INET6);
+- memset(IP6CB(skb), 0, sizeof(*IP6CB(skb)));
+- if (!dst) {
+- fl.u.ip6.flowi6_oif = dev->ifindex;
+- fl.u.ip6.flowi6_flags |= FLOWI_FLAG_ANYSRC;
+- dst = ip6_route_output(dev_net(dev), NULL, &fl.u.ip6);
+- if (dst->error) {
+- dst_release(dst);
+- stats->tx_carrier_errors++;
+- goto tx_err;
+- }
+- skb_dst_set(skb, dst);
+- }
+- break;
+- case htons(ETH_P_IP):
+- xfrm_decode_session(skb, &fl, AF_INET);
+- memset(IPCB(skb), 0, sizeof(*IPCB(skb)));
+- if (!dst) {
+- struct rtable *rt;
+-
+- fl.u.ip4.flowi4_oif = dev->ifindex;
+- fl.u.ip4.flowi4_flags |= FLOWI_FLAG_ANYSRC;
+- rt = __ip_route_output_key(dev_net(dev), &fl.u.ip4);
+- if (IS_ERR(rt)) {
+- stats->tx_carrier_errors++;
+- goto tx_err;
+- }
+- skb_dst_set(skb, &rt->dst);
+- }
+- break;
+- default:
+- goto tx_err;
+- }
+-
+- fl.flowi_oif = xi->p.link;
+-
+- ret = xfrmi_xmit2(skb, dev, &fl);
+- if (ret < 0)
+- goto tx_err;
+-
+- return NETDEV_TX_OK;
+-
+-tx_err:
+- stats->tx_errors++;
+- stats->tx_dropped++;
+- kfree_skb(skb);
+- return NETDEV_TX_OK;
+-}
+-
+-static int xfrmi4_err(struct sk_buff *skb, u32 info)
+-{
+- const struct iphdr *iph = (const struct iphdr *)skb->data;
+- struct net *net = dev_net(skb->dev);
+- int protocol = iph->protocol;
+- struct ip_comp_hdr *ipch;
+- struct ip_esp_hdr *esph;
+- struct ip_auth_hdr *ah ;
+- struct xfrm_state *x;
+- struct xfrm_if *xi;
+- __be32 spi;
+-
+- switch (protocol) {
+- case IPPROTO_ESP:
+- esph = (struct ip_esp_hdr *)(skb->data+(iph->ihl<<2));
+- spi = esph->spi;
+- break;
+- case IPPROTO_AH:
+- ah = (struct ip_auth_hdr *)(skb->data+(iph->ihl<<2));
+- spi = ah->spi;
+- break;
+- case IPPROTO_COMP:
+- ipch = (struct ip_comp_hdr *)(skb->data+(iph->ihl<<2));
+- spi = htonl(ntohs(ipch->cpi));
+- break;
+- default:
+- return 0;
+- }
+-
+- switch (icmp_hdr(skb)->type) {
+- case ICMP_DEST_UNREACH:
+- if (icmp_hdr(skb)->code != ICMP_FRAG_NEEDED)
+- return 0;
+- case ICMP_REDIRECT:
+- break;
+- default:
+- return 0;
+- }
+-
+- x = xfrm_state_lookup(net, skb->mark, (const xfrm_address_t *)&iph->daddr,
+- spi, protocol, AF_INET);
+- if (!x)
+- return 0;
+-
+- xi = xfrmi_lookup(net, x);
+- if (!xi) {
+- xfrm_state_put(x);
+- return -1;
+- }
+-
+- if (icmp_hdr(skb)->type == ICMP_DEST_UNREACH)
+- ipv4_update_pmtu(skb, net, info, 0, 0, protocol, 0);
+- else
+- ipv4_redirect(skb, net, 0, 0, protocol, 0);
+- xfrm_state_put(x);
+-
+- return 0;
+-}
+-
+-static int xfrmi6_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
+- u8 type, u8 code, int offset, __be32 info)
+-{
+- const struct ipv6hdr *iph = (const struct ipv6hdr *)skb->data;
+- struct net *net = dev_net(skb->dev);
+- int protocol = iph->nexthdr;
+- struct ip_comp_hdr *ipch;
+- struct ip_esp_hdr *esph;
+- struct ip_auth_hdr *ah;
+- struct xfrm_state *x;
+- struct xfrm_if *xi;
+- __be32 spi;
+-
+- switch (protocol) {
+- case IPPROTO_ESP:
+- esph = (struct ip_esp_hdr *)(skb->data + offset);
+- spi = esph->spi;
+- break;
+- case IPPROTO_AH:
+- ah = (struct ip_auth_hdr *)(skb->data + offset);
+- spi = ah->spi;
+- break;
+- case IPPROTO_COMP:
+- ipch = (struct ip_comp_hdr *)(skb->data + offset);
+- spi = htonl(ntohs(ipch->cpi));
+- break;
+- default:
+- return 0;
+- }
+-
+- if (type != ICMPV6_PKT_TOOBIG &&
+- type != NDISC_REDIRECT)
+- return 0;
+-
+- x = xfrm_state_lookup(net, skb->mark, (const xfrm_address_t *)&iph->daddr,
+- spi, protocol, AF_INET6);
+- if (!x)
+- return 0;
+-
+- xi = xfrmi_lookup(net, x);
+- if (!xi) {
+- xfrm_state_put(x);
+- return -1;
+- }
+-
+- if (type == NDISC_REDIRECT)
+- ip6_redirect(skb, net, skb->dev->ifindex, 0,
+- sock_net_uid(net, NULL));
+- else
+- ip6_update_pmtu(skb, net, info, 0, 0, sock_net_uid(net, NULL));
+- xfrm_state_put(x);
+-
+- return 0;
+-}
+-
+-static int xfrmi_change(struct xfrm_if *xi, const struct xfrm_if_parms *p)
+-{
+- if (xi->p.link != p->link)
+- return -EINVAL;
+-
+- xi->p.if_id = p->if_id;
+-
+- return 0;
+-}
+-
+-static int xfrmi_update(struct xfrm_if *xi, struct xfrm_if_parms *p)
+-{
+- struct net *net = xi->net;
+- struct xfrmi_net *xfrmn = net_generic(net, xfrmi_net_id);
+- int err;
+-
+- xfrmi_unlink(xfrmn, xi);
+- synchronize_net();
+- err = xfrmi_change(xi, p);
+- xfrmi_link(xfrmn, xi);
+- netdev_state_change(xi->dev);
+- return err;
+-}
+-
+-static void xfrmi_get_stats64(struct net_device *dev,
+- struct rtnl_link_stats64 *s)
+-{
+- int cpu;
+-
+- if (!dev->tstats)
+- return;
+-
+- for_each_possible_cpu(cpu) {
+- struct pcpu_sw_netstats *stats;
+- struct pcpu_sw_netstats tmp;
+- int start;
+-
+- stats = per_cpu_ptr(dev->tstats, cpu);
+- do {
+- start = u64_stats_fetch_begin_irq(&stats->syncp);
+- tmp.rx_packets = stats->rx_packets;
+- tmp.rx_bytes = stats->rx_bytes;
+- tmp.tx_packets = stats->tx_packets;
+- tmp.tx_bytes = stats->tx_bytes;
+- } while (u64_stats_fetch_retry_irq(&stats->syncp, start));
+-
+- s->rx_packets += tmp.rx_packets;
+- s->rx_bytes += tmp.rx_bytes;
+- s->tx_packets += tmp.tx_packets;
+- s->tx_bytes += tmp.tx_bytes;
+- }
+-
+- s->rx_dropped = dev->stats.rx_dropped;
+- s->tx_dropped = dev->stats.tx_dropped;
+-}
+-
+-static int xfrmi_get_iflink(const struct net_device *dev)
+-{
+- struct xfrm_if *xi = netdev_priv(dev);
+-
+- return xi->p.link;
+-}
+-
+-
+-static const struct net_device_ops xfrmi_netdev_ops = {
+- .ndo_init = xfrmi_dev_init,
+- .ndo_uninit = xfrmi_dev_uninit,
+- .ndo_start_xmit = xfrmi_xmit,
+- .ndo_get_stats64 = xfrmi_get_stats64,
+- .ndo_get_iflink = xfrmi_get_iflink,
+-};
+-
+-static void xfrmi_dev_setup(struct net_device *dev)
+-{
+- dev->netdev_ops = &xfrmi_netdev_ops;
+- dev->type = ARPHRD_NONE;
+- dev->mtu = ETH_DATA_LEN;
+- dev->min_mtu = ETH_MIN_MTU;
+- dev->max_mtu = IP_MAX_MTU;
+- dev->flags = IFF_NOARP;
+- dev->needs_free_netdev = true;
+- dev->priv_destructor = xfrmi_dev_free;
+- netif_keep_dst(dev);
+-
+- eth_broadcast_addr(dev->broadcast);
+-}
+-
+-static int xfrmi_dev_init(struct net_device *dev)
+-{
+- struct xfrm_if *xi = netdev_priv(dev);
+- struct net_device *phydev = __dev_get_by_index(xi->net, xi->p.link);
+- int err;
+-
+- dev->tstats = netdev_alloc_pcpu_stats(struct pcpu_sw_netstats);
+- if (!dev->tstats)
+- return -ENOMEM;
+-
+- err = gro_cells_init(&xi->gro_cells, dev);
+- if (err) {
+- free_percpu(dev->tstats);
+- return err;
+- }
+-
+- dev->features |= NETIF_F_LLTX;
+-
+- if (phydev) {
+- dev->needed_headroom = phydev->needed_headroom;
+- dev->needed_tailroom = phydev->needed_tailroom;
+-
+- if (is_zero_ether_addr(dev->dev_addr))
+- eth_hw_addr_inherit(dev, phydev);
+- if (is_zero_ether_addr(dev->broadcast))
+- memcpy(dev->broadcast, phydev->broadcast,
+- dev->addr_len);
+- } else {
+- eth_hw_addr_random(dev);
+- eth_broadcast_addr(dev->broadcast);
+- }
+-
+- return 0;
+-}
+-
+-static int xfrmi_validate(struct nlattr *tb[], struct nlattr *data[],
+- struct netlink_ext_ack *extack)
+-{
+- return 0;
+-}
+-
+-static void xfrmi_netlink_parms(struct nlattr *data[],
+- struct xfrm_if_parms *parms)
+-{
+- memset(parms, 0, sizeof(*parms));
+-
+- if (!data)
+- return;
+-
+- if (data[IFLA_XFRM_LINK])
+- parms->link = nla_get_u32(data[IFLA_XFRM_LINK]);
+-
+- if (data[IFLA_XFRM_IF_ID])
+- parms->if_id = nla_get_u32(data[IFLA_XFRM_IF_ID]);
+-}
+-
+-static int xfrmi_newlink(struct net *src_net, struct net_device *dev,
+- struct nlattr *tb[], struct nlattr *data[],
+- struct netlink_ext_ack *extack)
+-{
+- struct net *net = dev_net(dev);
+- struct xfrm_if_parms p = {};
+- struct xfrm_if *xi;
+- int err;
+-
+- xfrmi_netlink_parms(data, &p);
+- if (!p.if_id) {
+- NL_SET_ERR_MSG(extack, "if_id must be non zero");
+- return -EINVAL;
+- }
+-
+- xi = xfrmi_locate(net, &p);
+- if (xi)
+- return -EEXIST;
+-
+- xi = netdev_priv(dev);
+- xi->p = p;
+- xi->net = net;
+- xi->dev = dev;
+-
+- err = xfrmi_create(dev);
+- return err;
+-}
+-
+-static void xfrmi_dellink(struct net_device *dev, struct list_head *head)
+-{
+- unregister_netdevice_queue(dev, head);
+-}
+-
+-static int xfrmi_changelink(struct net_device *dev, struct nlattr *tb[],
+- struct nlattr *data[],
+- struct netlink_ext_ack *extack)
+-{
+- struct xfrm_if *xi = netdev_priv(dev);
+- struct net *net = xi->net;
+- struct xfrm_if_parms p = {};
+-
+- xfrmi_netlink_parms(data, &p);
+- if (!p.if_id) {
+- NL_SET_ERR_MSG(extack, "if_id must be non zero");
+- return -EINVAL;
+- }
+-
+- xi = xfrmi_locate(net, &p);
+- if (!xi) {
+- xi = netdev_priv(dev);
+- } else {
+- if (xi->dev != dev)
+- return -EEXIST;
+- }
+-
+- return xfrmi_update(xi, &p);
+-}
+-
+-static size_t xfrmi_get_size(const struct net_device *dev)
+-{
+- return
+- /* IFLA_XFRM_LINK */
+- nla_total_size(4) +
+- /* IFLA_XFRM_IF_ID */
+- nla_total_size(4) +
+- 0;
+-}
+-
+-static int xfrmi_fill_info(struct sk_buff *skb, const struct net_device *dev)
+-{
+- struct xfrm_if *xi = netdev_priv(dev);
+- struct xfrm_if_parms *parm = &xi->p;
+-
+- if (nla_put_u32(skb, IFLA_XFRM_LINK, parm->link) ||
+- nla_put_u32(skb, IFLA_XFRM_IF_ID, parm->if_id))
+- goto nla_put_failure;
+- return 0;
+-
+-nla_put_failure:
+- return -EMSGSIZE;
+-}
+-
+-struct net *xfrmi_get_link_net(const struct net_device *dev)
+-{
+- struct xfrm_if *xi = netdev_priv(dev);
+-
+- return xi->net;
+-}
+-
+-static const struct nla_policy xfrmi_policy[IFLA_XFRM_MAX + 1] = {
+- [IFLA_XFRM_LINK] = { .type = NLA_U32 },
+- [IFLA_XFRM_IF_ID] = { .type = NLA_U32 },
+-};
+-
+-static struct rtnl_link_ops xfrmi_link_ops __read_mostly = {
+- .kind = "xfrm",
+- .maxtype = IFLA_XFRM_MAX,
+- .policy = xfrmi_policy,
+- .priv_size = sizeof(struct xfrm_if),
+- .setup = xfrmi_dev_setup,
+- .validate = xfrmi_validate,
+- .newlink = xfrmi_newlink,
+- .dellink = xfrmi_dellink,
+- .changelink = xfrmi_changelink,
+- .get_size = xfrmi_get_size,
+- .fill_info = xfrmi_fill_info,
+- .get_link_net = xfrmi_get_link_net,
+-};
+-
+-static void __net_exit xfrmi_destroy_interfaces(struct xfrmi_net *xfrmn)
+-{
+- struct xfrm_if *xi;
+- LIST_HEAD(list);
+-
+- xi = rtnl_dereference(xfrmn->xfrmi[0]);
+- if (!xi)
+- return;
+-
+- unregister_netdevice_queue(xi->dev, &list);
+- unregister_netdevice_many(&list);
+-}
+-
+-static int __net_init xfrmi_init_net(struct net *net)
+-{
+- return 0;
+-}
+-
+-static void __net_exit xfrmi_exit_net(struct net *net)
+-{
+- struct xfrmi_net *xfrmn = net_generic(net, xfrmi_net_id);
+-
+- rtnl_lock();
+- xfrmi_destroy_interfaces(xfrmn);
+- rtnl_unlock();
+-}
+-
+-static void __net_exit xfrmi_exit_batch_net(struct list_head *net_exit_list)
+-{
+- struct net *net;
+- LIST_HEAD(list);
+-
+- rtnl_lock();
+- list_for_each_entry(net, net_exit_list, exit_list) {
+- struct xfrmi_net *xfrmn = net_generic(net, xfrmi_net_id);
+- struct xfrm_if __rcu **xip;
+- struct xfrm_if *xi;
+-
+- for (xip = &xfrmn->xfrmi[0];
+- (xi = rtnl_dereference(*xip)) != NULL;
+- xip = &xi->next)
+- unregister_netdevice_queue(xi->dev, &list);
+- }
+- unregister_netdevice_many(&list);
+- rtnl_unlock();
+-}
+-
+-static struct pernet_operations xfrmi_net_ops = {
+- .exit_batch = xfrmi_exit_batch_net,
+- .init = xfrmi_init_net,
+- .exit = xfrmi_exit_net,
+- .id = &xfrmi_net_id,
+- .size = sizeof(struct xfrmi_net),
+-};
+-
+-static struct xfrm6_protocol xfrmi_esp6_protocol __read_mostly = {
+- .handler = xfrm6_rcv,
+- .cb_handler = xfrmi_rcv_cb,
+- .err_handler = xfrmi6_err,
+- .priority = 10,
+-};
+-
+-static struct xfrm6_protocol xfrmi_ah6_protocol __read_mostly = {
+- .handler = xfrm6_rcv,
+- .cb_handler = xfrmi_rcv_cb,
+- .err_handler = xfrmi6_err,
+- .priority = 10,
+-};
+-
+-static struct xfrm6_protocol xfrmi_ipcomp6_protocol __read_mostly = {
+- .handler = xfrm6_rcv,
+- .cb_handler = xfrmi_rcv_cb,
+- .err_handler = xfrmi6_err,
+- .priority = 10,
+-};
+-
+-static struct xfrm4_protocol xfrmi_esp4_protocol __read_mostly = {
+- .handler = xfrm4_rcv,
+- .input_handler = xfrm_input,
+- .cb_handler = xfrmi_rcv_cb,
+- .err_handler = xfrmi4_err,
+- .priority = 10,
+-};
+-
+-static struct xfrm4_protocol xfrmi_ah4_protocol __read_mostly = {
+- .handler = xfrm4_rcv,
+- .input_handler = xfrm_input,
+- .cb_handler = xfrmi_rcv_cb,
+- .err_handler = xfrmi4_err,
+- .priority = 10,
+-};
+-
+-static struct xfrm4_protocol xfrmi_ipcomp4_protocol __read_mostly = {
+- .handler = xfrm4_rcv,
+- .input_handler = xfrm_input,
+- .cb_handler = xfrmi_rcv_cb,
+- .err_handler = xfrmi4_err,
+- .priority = 10,
+-};
+-
+-static int __init xfrmi4_init(void)
+-{
+- int err;
+-
+- err = xfrm4_protocol_register(&xfrmi_esp4_protocol, IPPROTO_ESP);
+- if (err < 0)
+- goto xfrm_proto_esp_failed;
+- err = xfrm4_protocol_register(&xfrmi_ah4_protocol, IPPROTO_AH);
+- if (err < 0)
+- goto xfrm_proto_ah_failed;
+- err = xfrm4_protocol_register(&xfrmi_ipcomp4_protocol, IPPROTO_COMP);
+- if (err < 0)
+- goto xfrm_proto_comp_failed;
+-
+- return 0;
+-
+-xfrm_proto_comp_failed:
+- xfrm4_protocol_deregister(&xfrmi_ah4_protocol, IPPROTO_AH);
+-xfrm_proto_ah_failed:
+- xfrm4_protocol_deregister(&xfrmi_esp4_protocol, IPPROTO_ESP);
+-xfrm_proto_esp_failed:
+- return err;
+-}
+-
+-static void xfrmi4_fini(void)
+-{
+- xfrm4_protocol_deregister(&xfrmi_ipcomp4_protocol, IPPROTO_COMP);
+- xfrm4_protocol_deregister(&xfrmi_ah4_protocol, IPPROTO_AH);
+- xfrm4_protocol_deregister(&xfrmi_esp4_protocol, IPPROTO_ESP);
+-}
+-
+-static int __init xfrmi6_init(void)
+-{
+- int err;
+-
+- err = xfrm6_protocol_register(&xfrmi_esp6_protocol, IPPROTO_ESP);
+- if (err < 0)
+- goto xfrm_proto_esp_failed;
+- err = xfrm6_protocol_register(&xfrmi_ah6_protocol, IPPROTO_AH);
+- if (err < 0)
+- goto xfrm_proto_ah_failed;
+- err = xfrm6_protocol_register(&xfrmi_ipcomp6_protocol, IPPROTO_COMP);
+- if (err < 0)
+- goto xfrm_proto_comp_failed;
+-
+- return 0;
+-
+-xfrm_proto_comp_failed:
+- xfrm6_protocol_deregister(&xfrmi_ah6_protocol, IPPROTO_AH);
+-xfrm_proto_ah_failed:
+- xfrm6_protocol_deregister(&xfrmi_esp6_protocol, IPPROTO_ESP);
+-xfrm_proto_esp_failed:
+- return err;
+-}
+-
+-static void xfrmi6_fini(void)
+-{
+- xfrm6_protocol_deregister(&xfrmi_ipcomp6_protocol, IPPROTO_COMP);
+- xfrm6_protocol_deregister(&xfrmi_ah6_protocol, IPPROTO_AH);
+- xfrm6_protocol_deregister(&xfrmi_esp6_protocol, IPPROTO_ESP);
+-}
+-
+-static const struct xfrm_if_cb xfrm_if_cb = {
+- .decode_session = xfrmi_decode_session,
+-};
+-
+-static int __init xfrmi_init(void)
+-{
+- const char *msg;
+- int err;
+-
+- pr_info("IPsec XFRM device driver\n");
+-
+- msg = "tunnel device";
+- err = register_pernet_device(&xfrmi_net_ops);
+- if (err < 0)
+- goto pernet_dev_failed;
+-
+- msg = "xfrm4 protocols";
+- err = xfrmi4_init();
+- if (err < 0)
+- goto xfrmi4_failed;
+-
+- msg = "xfrm6 protocols";
+- err = xfrmi6_init();
+- if (err < 0)
+- goto xfrmi6_failed;
+-
+-
+- msg = "netlink interface";
+- err = rtnl_link_register(&xfrmi_link_ops);
+- if (err < 0)
+- goto rtnl_link_failed;
+-
+- xfrm_if_register_cb(&xfrm_if_cb);
+-
+- return err;
+-
+-rtnl_link_failed:
+- xfrmi6_fini();
+-xfrmi6_failed:
+- xfrmi4_fini();
+-xfrmi4_failed:
+- unregister_pernet_device(&xfrmi_net_ops);
+-pernet_dev_failed:
+- pr_err("xfrmi init: failed to register %s\n", msg);
+- return err;
+-}
+-
+-static void __exit xfrmi_fini(void)
+-{
+- xfrm_if_unregister_cb();
+- rtnl_link_unregister(&xfrmi_link_ops);
+- xfrmi4_fini();
+- xfrmi6_fini();
+- unregister_pernet_device(&xfrmi_net_ops);
+-}
+-
+-module_init(xfrmi_init);
+-module_exit(xfrmi_fini);
+-MODULE_LICENSE("GPL");
+-MODULE_ALIAS_RTNL_LINK("xfrm");
+-MODULE_ALIAS_NETDEV("xfrm0");
+-MODULE_AUTHOR("Steffen Klassert");
+-MODULE_DESCRIPTION("XFRM virtual interface");
+diff --git a/net/xfrm/xfrm_interface_core.c b/net/xfrm/xfrm_interface_core.c
+new file mode 100644
+index 0000000000000..40081af62b68f
+--- /dev/null
++++ b/net/xfrm/xfrm_interface_core.c
+@@ -0,0 +1,996 @@
++// SPDX-License-Identifier: GPL-2.0
++/*
++ * XFRM virtual interface
++ *
++ * Copyright (C) 2018 secunet Security Networks AG
++ *
++ * Author:
++ * Steffen Klassert <steffen.klassert@secunet.com>
++ */
++
++#include <linux/module.h>
++#include <linux/capability.h>
++#include <linux/errno.h>
++#include <linux/types.h>
++#include <linux/sockios.h>
++#include <linux/icmp.h>
++#include <linux/if.h>
++#include <linux/in.h>
++#include <linux/ip.h>
++#include <linux/net.h>
++#include <linux/in6.h>
++#include <linux/netdevice.h>
++#include <linux/if_link.h>
++#include <linux/if_arp.h>
++#include <linux/icmpv6.h>
++#include <linux/init.h>
++#include <linux/route.h>
++#include <linux/rtnetlink.h>
++#include <linux/netfilter_ipv6.h>
++#include <linux/slab.h>
++#include <linux/hash.h>
++
++#include <linux/uaccess.h>
++#include <linux/atomic.h>
++
++#include <net/icmp.h>
++#include <net/ip.h>
++#include <net/ipv6.h>
++#include <net/ip6_route.h>
++#include <net/addrconf.h>
++#include <net/xfrm.h>
++#include <net/net_namespace.h>
++#include <net/netns/generic.h>
++#include <linux/etherdevice.h>
++
++static int xfrmi_dev_init(struct net_device *dev);
++static void xfrmi_dev_setup(struct net_device *dev);
++static struct rtnl_link_ops xfrmi_link_ops __read_mostly;
++static unsigned int xfrmi_net_id __read_mostly;
++
++struct xfrmi_net {
++ /* lists for storing interfaces in use */
++ struct xfrm_if __rcu *xfrmi[1];
++};
++
++#define for_each_xfrmi_rcu(start, xi) \
++ for (xi = rcu_dereference(start); xi; xi = rcu_dereference(xi->next))
++
++static struct xfrm_if *xfrmi_lookup(struct net *net, struct xfrm_state *x)
++{
++ struct xfrmi_net *xfrmn = net_generic(net, xfrmi_net_id);
++ struct xfrm_if *xi;
++
++ for_each_xfrmi_rcu(xfrmn->xfrmi[0], xi) {
++ if (x->if_id == xi->p.if_id &&
++ (xi->dev->flags & IFF_UP))
++ return xi;
++ }
++
++ return NULL;
++}
++
++static struct xfrm_if *xfrmi_decode_session(struct sk_buff *skb,
++ unsigned short family)
++{
++ struct xfrmi_net *xfrmn;
++ struct xfrm_if *xi;
++ int ifindex = 0;
++
++ if (!secpath_exists(skb) || !skb->dev)
++ return NULL;
++
++ switch (family) {
++ case AF_INET6:
++ ifindex = inet6_sdif(skb);
++ break;
++ case AF_INET:
++ ifindex = inet_sdif(skb);
++ break;
++ }
++ if (!ifindex)
++ ifindex = skb->dev->ifindex;
++
++ xfrmn = net_generic(xs_net(xfrm_input_state(skb)), xfrmi_net_id);
++
++ for_each_xfrmi_rcu(xfrmn->xfrmi[0], xi) {
++ if (ifindex == xi->dev->ifindex &&
++ (xi->dev->flags & IFF_UP))
++ return xi;
++ }
++
++ return NULL;
++}
++
++static void xfrmi_link(struct xfrmi_net *xfrmn, struct xfrm_if *xi)
++{
++ struct xfrm_if __rcu **xip = &xfrmn->xfrmi[0];
++
++ rcu_assign_pointer(xi->next , rtnl_dereference(*xip));
++ rcu_assign_pointer(*xip, xi);
++}
++
++static void xfrmi_unlink(struct xfrmi_net *xfrmn, struct xfrm_if *xi)
++{
++ struct xfrm_if __rcu **xip;
++ struct xfrm_if *iter;
++
++ for (xip = &xfrmn->xfrmi[0];
++ (iter = rtnl_dereference(*xip)) != NULL;
++ xip = &iter->next) {
++ if (xi == iter) {
++ rcu_assign_pointer(*xip, xi->next);
++ break;
++ }
++ }
++}
++
++static void xfrmi_dev_free(struct net_device *dev)
++{
++ struct xfrm_if *xi = netdev_priv(dev);
++
++ gro_cells_destroy(&xi->gro_cells);
++ free_percpu(dev->tstats);
++}
++
++static int xfrmi_create(struct net_device *dev)
++{
++ struct xfrm_if *xi = netdev_priv(dev);
++ struct net *net = dev_net(dev);
++ struct xfrmi_net *xfrmn = net_generic(net, xfrmi_net_id);
++ int err;
++
++ dev->rtnl_link_ops = &xfrmi_link_ops;
++ err = register_netdevice(dev);
++ if (err < 0)
++ goto out;
++
++ dev_hold(dev);
++ xfrmi_link(xfrmn, xi);
++
++ return 0;
++
++out:
++ return err;
++}
++
++static struct xfrm_if *xfrmi_locate(struct net *net, struct xfrm_if_parms *p)
++{
++ struct xfrm_if __rcu **xip;
++ struct xfrm_if *xi;
++ struct xfrmi_net *xfrmn = net_generic(net, xfrmi_net_id);
++
++ for (xip = &xfrmn->xfrmi[0];
++ (xi = rtnl_dereference(*xip)) != NULL;
++ xip = &xi->next)
++ if (xi->p.if_id == p->if_id)
++ return xi;
++
++ return NULL;
++}
++
++static void xfrmi_dev_uninit(struct net_device *dev)
++{
++ struct xfrm_if *xi = netdev_priv(dev);
++ struct xfrmi_net *xfrmn = net_generic(xi->net, xfrmi_net_id);
++
++ xfrmi_unlink(xfrmn, xi);
++ dev_put(dev);
++}
++
++static void xfrmi_scrub_packet(struct sk_buff *skb, bool xnet)
++{
++ skb->tstamp = 0;
++ skb->pkt_type = PACKET_HOST;
++ skb->skb_iif = 0;
++ skb->ignore_df = 0;
++ skb_dst_drop(skb);
++ nf_reset(skb);
++ nf_reset_trace(skb);
++
++ if (!xnet)
++ return;
++
++ ipvs_reset(skb);
++ secpath_reset(skb);
++ skb_orphan(skb);
++ skb->mark = 0;
++}
++
++static int xfrmi_rcv_cb(struct sk_buff *skb, int err)
++{
++ struct pcpu_sw_netstats *tstats;
++ struct xfrm_mode *inner_mode;
++ struct net_device *dev;
++ struct xfrm_state *x;
++ struct xfrm_if *xi;
++ bool xnet;
++
++ if (err && !skb->sp)
++ return 0;
++
++ x = xfrm_input_state(skb);
++
++ xi = xfrmi_lookup(xs_net(x), x);
++ if (!xi)
++ return 1;
++
++ dev = xi->dev;
++ skb->dev = dev;
++
++ if (err) {
++ dev->stats.rx_errors++;
++ dev->stats.rx_dropped++;
++
++ return 0;
++ }
++
++ xnet = !net_eq(xi->net, dev_net(skb->dev));
++
++ if (xnet) {
++ inner_mode = x->inner_mode;
++
++ if (x->sel.family == AF_UNSPEC) {
++ inner_mode = xfrm_ip2inner_mode(x, XFRM_MODE_SKB_CB(skb)->protocol);
++ if (inner_mode == NULL) {
++ XFRM_INC_STATS(dev_net(skb->dev),
++ LINUX_MIB_XFRMINSTATEMODEERROR);
++ return -EINVAL;
++ }
++ }
++
++ if (!xfrm_policy_check(NULL, XFRM_POLICY_IN, skb,
++ inner_mode->afinfo->family))
++ return -EPERM;
++ }
++
++ xfrmi_scrub_packet(skb, xnet);
++
++ tstats = this_cpu_ptr(dev->tstats);
++
++ u64_stats_update_begin(&tstats->syncp);
++ tstats->rx_packets++;
++ tstats->rx_bytes += skb->len;
++ u64_stats_update_end(&tstats->syncp);
++
++ return 0;
++}
++
++static int
++xfrmi_xmit2(struct sk_buff *skb, struct net_device *dev, struct flowi *fl)
++{
++ struct xfrm_if *xi = netdev_priv(dev);
++ struct net_device_stats *stats = &xi->dev->stats;
++ struct dst_entry *dst = skb_dst(skb);
++ unsigned int length = skb->len;
++ struct net_device *tdev;
++ struct xfrm_state *x;
++ int err = -1;
++ int mtu;
++
++ dst_hold(dst);
++ dst = xfrm_lookup_with_ifid(xi->net, dst, fl, NULL, 0, xi->p.if_id);
++ if (IS_ERR(dst)) {
++ err = PTR_ERR(dst);
++ dst = NULL;
++ goto tx_err_link_failure;
++ }
++
++ x = dst->xfrm;
++ if (!x)
++ goto tx_err_link_failure;
++
++ if (x->if_id != xi->p.if_id)
++ goto tx_err_link_failure;
++
++ tdev = dst->dev;
++
++ if (tdev == dev) {
++ stats->collisions++;
++ net_warn_ratelimited("%s: Local routing loop detected!\n",
++ dev->name);
++ goto tx_err_dst_release;
++ }
++
++ mtu = dst_mtu(dst);
++ if (skb->len > mtu) {
++ skb_dst_update_pmtu_no_confirm(skb, mtu);
++
++ if (skb->protocol == htons(ETH_P_IPV6)) {
++ if (mtu < IPV6_MIN_MTU)
++ mtu = IPV6_MIN_MTU;
++
++ if (skb->len > 1280)
++ icmpv6_ndo_send(skb, ICMPV6_PKT_TOOBIG, 0, mtu);
++ else
++ goto xmit;
++ } else {
++ if (!(ip_hdr(skb)->frag_off & htons(IP_DF)))
++ goto xmit;
++ icmp_ndo_send(skb, ICMP_DEST_UNREACH, ICMP_FRAG_NEEDED,
++ htonl(mtu));
++ }
++
++ dst_release(dst);
++ return -EMSGSIZE;
++ }
++
++xmit:
++ xfrmi_scrub_packet(skb, !net_eq(xi->net, dev_net(dev)));
++ skb_dst_set(skb, dst);
++ skb->dev = tdev;
++
++ err = dst_output(xi->net, skb->sk, skb);
++ if (net_xmit_eval(err) == 0) {
++ struct pcpu_sw_netstats *tstats = this_cpu_ptr(dev->tstats);
++
++ u64_stats_update_begin(&tstats->syncp);
++ tstats->tx_bytes += length;
++ tstats->tx_packets++;
++ u64_stats_update_end(&tstats->syncp);
++ } else {
++ stats->tx_errors++;
++ stats->tx_aborted_errors++;
++ }
++
++ return 0;
++tx_err_link_failure:
++ stats->tx_carrier_errors++;
++ dst_link_failure(skb);
++tx_err_dst_release:
++ dst_release(dst);
++ return err;
++}
++
++static netdev_tx_t xfrmi_xmit(struct sk_buff *skb, struct net_device *dev)
++{
++ struct xfrm_if *xi = netdev_priv(dev);
++ struct net_device_stats *stats = &xi->dev->stats;
++ struct dst_entry *dst = skb_dst(skb);
++ struct flowi fl;
++ int ret;
++
++ memset(&fl, 0, sizeof(fl));
++
++ switch (skb->protocol) {
++ case htons(ETH_P_IPV6):
++ memset(IP6CB(skb), 0, sizeof(*IP6CB(skb)));
++ xfrm_decode_session(skb, &fl, AF_INET6);
++ if (!dst) {
++ fl.u.ip6.flowi6_oif = dev->ifindex;
++ fl.u.ip6.flowi6_flags |= FLOWI_FLAG_ANYSRC;
++ dst = ip6_route_output(dev_net(dev), NULL, &fl.u.ip6);
++ if (dst->error) {
++ dst_release(dst);
++ stats->tx_carrier_errors++;
++ goto tx_err;
++ }
++ skb_dst_set(skb, dst);
++ }
++ break;
++ case htons(ETH_P_IP):
++ memset(IPCB(skb), 0, sizeof(*IPCB(skb)));
++ xfrm_decode_session(skb, &fl, AF_INET);
++ if (!dst) {
++ struct rtable *rt;
++
++ fl.u.ip4.flowi4_oif = dev->ifindex;
++ fl.u.ip4.flowi4_flags |= FLOWI_FLAG_ANYSRC;
++ rt = __ip_route_output_key(dev_net(dev), &fl.u.ip4);
++ if (IS_ERR(rt)) {
++ stats->tx_carrier_errors++;
++ goto tx_err;
++ }
++ skb_dst_set(skb, &rt->dst);
++ }
++ break;
++ default:
++ goto tx_err;
++ }
++
++ fl.flowi_oif = xi->p.link;
++
++ ret = xfrmi_xmit2(skb, dev, &fl);
++ if (ret < 0)
++ goto tx_err;
++
++ return NETDEV_TX_OK;
++
++tx_err:
++ stats->tx_errors++;
++ stats->tx_dropped++;
++ kfree_skb(skb);
++ return NETDEV_TX_OK;
++}
++
++static int xfrmi4_err(struct sk_buff *skb, u32 info)
++{
++ const struct iphdr *iph = (const struct iphdr *)skb->data;
++ struct net *net = dev_net(skb->dev);
++ int protocol = iph->protocol;
++ struct ip_comp_hdr *ipch;
++ struct ip_esp_hdr *esph;
++ struct ip_auth_hdr *ah ;
++ struct xfrm_state *x;
++ struct xfrm_if *xi;
++ __be32 spi;
++
++ switch (protocol) {
++ case IPPROTO_ESP:
++ esph = (struct ip_esp_hdr *)(skb->data+(iph->ihl<<2));
++ spi = esph->spi;
++ break;
++ case IPPROTO_AH:
++ ah = (struct ip_auth_hdr *)(skb->data+(iph->ihl<<2));
++ spi = ah->spi;
++ break;
++ case IPPROTO_COMP:
++ ipch = (struct ip_comp_hdr *)(skb->data+(iph->ihl<<2));
++ spi = htonl(ntohs(ipch->cpi));
++ break;
++ default:
++ return 0;
++ }
++
++ switch (icmp_hdr(skb)->type) {
++ case ICMP_DEST_UNREACH:
++ if (icmp_hdr(skb)->code != ICMP_FRAG_NEEDED)
++ return 0;
++ case ICMP_REDIRECT:
++ break;
++ default:
++ return 0;
++ }
++
++ x = xfrm_state_lookup(net, skb->mark, (const xfrm_address_t *)&iph->daddr,
++ spi, protocol, AF_INET);
++ if (!x)
++ return 0;
++
++ xi = xfrmi_lookup(net, x);
++ if (!xi) {
++ xfrm_state_put(x);
++ return -1;
++ }
++
++ if (icmp_hdr(skb)->type == ICMP_DEST_UNREACH)
++ ipv4_update_pmtu(skb, net, info, 0, 0, protocol, 0);
++ else
++ ipv4_redirect(skb, net, 0, 0, protocol, 0);
++ xfrm_state_put(x);
++
++ return 0;
++}
++
++static int xfrmi6_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
++ u8 type, u8 code, int offset, __be32 info)
++{
++ const struct ipv6hdr *iph = (const struct ipv6hdr *)skb->data;
++ struct net *net = dev_net(skb->dev);
++ int protocol = iph->nexthdr;
++ struct ip_comp_hdr *ipch;
++ struct ip_esp_hdr *esph;
++ struct ip_auth_hdr *ah;
++ struct xfrm_state *x;
++ struct xfrm_if *xi;
++ __be32 spi;
++
++ switch (protocol) {
++ case IPPROTO_ESP:
++ esph = (struct ip_esp_hdr *)(skb->data + offset);
++ spi = esph->spi;
++ break;
++ case IPPROTO_AH:
++ ah = (struct ip_auth_hdr *)(skb->data + offset);
++ spi = ah->spi;
++ break;
++ case IPPROTO_COMP:
++ ipch = (struct ip_comp_hdr *)(skb->data + offset);
++ spi = htonl(ntohs(ipch->cpi));
++ break;
++ default:
++ return 0;
++ }
++
++ if (type != ICMPV6_PKT_TOOBIG &&
++ type != NDISC_REDIRECT)
++ return 0;
++
++ x = xfrm_state_lookup(net, skb->mark, (const xfrm_address_t *)&iph->daddr,
++ spi, protocol, AF_INET6);
++ if (!x)
++ return 0;
++
++ xi = xfrmi_lookup(net, x);
++ if (!xi) {
++ xfrm_state_put(x);
++ return -1;
++ }
++
++ if (type == NDISC_REDIRECT)
++ ip6_redirect(skb, net, skb->dev->ifindex, 0,
++ sock_net_uid(net, NULL));
++ else
++ ip6_update_pmtu(skb, net, info, 0, 0, sock_net_uid(net, NULL));
++ xfrm_state_put(x);
++
++ return 0;
++}
++
++static int xfrmi_change(struct xfrm_if *xi, const struct xfrm_if_parms *p)
++{
++ if (xi->p.link != p->link)
++ return -EINVAL;
++
++ xi->p.if_id = p->if_id;
++
++ return 0;
++}
++
++static int xfrmi_update(struct xfrm_if *xi, struct xfrm_if_parms *p)
++{
++ struct net *net = xi->net;
++ struct xfrmi_net *xfrmn = net_generic(net, xfrmi_net_id);
++ int err;
++
++ xfrmi_unlink(xfrmn, xi);
++ synchronize_net();
++ err = xfrmi_change(xi, p);
++ xfrmi_link(xfrmn, xi);
++ netdev_state_change(xi->dev);
++ return err;
++}
++
++static void xfrmi_get_stats64(struct net_device *dev,
++ struct rtnl_link_stats64 *s)
++{
++ int cpu;
++
++ if (!dev->tstats)
++ return;
++
++ for_each_possible_cpu(cpu) {
++ struct pcpu_sw_netstats *stats;
++ struct pcpu_sw_netstats tmp;
++ int start;
++
++ stats = per_cpu_ptr(dev->tstats, cpu);
++ do {
++ start = u64_stats_fetch_begin_irq(&stats->syncp);
++ tmp.rx_packets = stats->rx_packets;
++ tmp.rx_bytes = stats->rx_bytes;
++ tmp.tx_packets = stats->tx_packets;
++ tmp.tx_bytes = stats->tx_bytes;
++ } while (u64_stats_fetch_retry_irq(&stats->syncp, start));
++
++ s->rx_packets += tmp.rx_packets;
++ s->rx_bytes += tmp.rx_bytes;
++ s->tx_packets += tmp.tx_packets;
++ s->tx_bytes += tmp.tx_bytes;
++ }
++
++ s->rx_dropped = dev->stats.rx_dropped;
++ s->tx_dropped = dev->stats.tx_dropped;
++}
++
++static int xfrmi_get_iflink(const struct net_device *dev)
++{
++ struct xfrm_if *xi = netdev_priv(dev);
++
++ return xi->p.link;
++}
++
++
++static const struct net_device_ops xfrmi_netdev_ops = {
++ .ndo_init = xfrmi_dev_init,
++ .ndo_uninit = xfrmi_dev_uninit,
++ .ndo_start_xmit = xfrmi_xmit,
++ .ndo_get_stats64 = xfrmi_get_stats64,
++ .ndo_get_iflink = xfrmi_get_iflink,
++};
++
++static void xfrmi_dev_setup(struct net_device *dev)
++{
++ dev->netdev_ops = &xfrmi_netdev_ops;
++ dev->type = ARPHRD_NONE;
++ dev->mtu = ETH_DATA_LEN;
++ dev->min_mtu = ETH_MIN_MTU;
++ dev->max_mtu = IP_MAX_MTU;
++ dev->flags = IFF_NOARP;
++ dev->needs_free_netdev = true;
++ dev->priv_destructor = xfrmi_dev_free;
++ netif_keep_dst(dev);
++
++ eth_broadcast_addr(dev->broadcast);
++}
++
++static int xfrmi_dev_init(struct net_device *dev)
++{
++ struct xfrm_if *xi = netdev_priv(dev);
++ struct net_device *phydev = __dev_get_by_index(xi->net, xi->p.link);
++ int err;
++
++ dev->tstats = netdev_alloc_pcpu_stats(struct pcpu_sw_netstats);
++ if (!dev->tstats)
++ return -ENOMEM;
++
++ err = gro_cells_init(&xi->gro_cells, dev);
++ if (err) {
++ free_percpu(dev->tstats);
++ return err;
++ }
++
++ dev->features |= NETIF_F_LLTX;
++
++ if (phydev) {
++ dev->needed_headroom = phydev->needed_headroom;
++ dev->needed_tailroom = phydev->needed_tailroom;
++
++ if (is_zero_ether_addr(dev->dev_addr))
++ eth_hw_addr_inherit(dev, phydev);
++ if (is_zero_ether_addr(dev->broadcast))
++ memcpy(dev->broadcast, phydev->broadcast,
++ dev->addr_len);
++ } else {
++ eth_hw_addr_random(dev);
++ eth_broadcast_addr(dev->broadcast);
++ }
++
++ return 0;
++}
++
++static int xfrmi_validate(struct nlattr *tb[], struct nlattr *data[],
++ struct netlink_ext_ack *extack)
++{
++ return 0;
++}
++
++static void xfrmi_netlink_parms(struct nlattr *data[],
++ struct xfrm_if_parms *parms)
++{
++ memset(parms, 0, sizeof(*parms));
++
++ if (!data)
++ return;
++
++ if (data[IFLA_XFRM_LINK])
++ parms->link = nla_get_u32(data[IFLA_XFRM_LINK]);
++
++ if (data[IFLA_XFRM_IF_ID])
++ parms->if_id = nla_get_u32(data[IFLA_XFRM_IF_ID]);
++}
++
++static int xfrmi_newlink(struct net *src_net, struct net_device *dev,
++ struct nlattr *tb[], struct nlattr *data[],
++ struct netlink_ext_ack *extack)
++{
++ struct net *net = dev_net(dev);
++ struct xfrm_if_parms p = {};
++ struct xfrm_if *xi;
++ int err;
++
++ xfrmi_netlink_parms(data, &p);
++ if (!p.if_id) {
++ NL_SET_ERR_MSG(extack, "if_id must be non zero");
++ return -EINVAL;
++ }
++
++ xi = xfrmi_locate(net, &p);
++ if (xi)
++ return -EEXIST;
++
++ xi = netdev_priv(dev);
++ xi->p = p;
++ xi->net = net;
++ xi->dev = dev;
++
++ err = xfrmi_create(dev);
++ return err;
++}
++
++static void xfrmi_dellink(struct net_device *dev, struct list_head *head)
++{
++ unregister_netdevice_queue(dev, head);
++}
++
++static int xfrmi_changelink(struct net_device *dev, struct nlattr *tb[],
++ struct nlattr *data[],
++ struct netlink_ext_ack *extack)
++{
++ struct xfrm_if *xi = netdev_priv(dev);
++ struct net *net = xi->net;
++ struct xfrm_if_parms p = {};
++
++ xfrmi_netlink_parms(data, &p);
++ if (!p.if_id) {
++ NL_SET_ERR_MSG(extack, "if_id must be non zero");
++ return -EINVAL;
++ }
++
++ xi = xfrmi_locate(net, &p);
++ if (!xi) {
++ xi = netdev_priv(dev);
++ } else {
++ if (xi->dev != dev)
++ return -EEXIST;
++ }
++
++ return xfrmi_update(xi, &p);
++}
++
++static size_t xfrmi_get_size(const struct net_device *dev)
++{
++ return
++ /* IFLA_XFRM_LINK */
++ nla_total_size(4) +
++ /* IFLA_XFRM_IF_ID */
++ nla_total_size(4) +
++ 0;
++}
++
++static int xfrmi_fill_info(struct sk_buff *skb, const struct net_device *dev)
++{
++ struct xfrm_if *xi = netdev_priv(dev);
++ struct xfrm_if_parms *parm = &xi->p;
++
++ if (nla_put_u32(skb, IFLA_XFRM_LINK, parm->link) ||
++ nla_put_u32(skb, IFLA_XFRM_IF_ID, parm->if_id))
++ goto nla_put_failure;
++ return 0;
++
++nla_put_failure:
++ return -EMSGSIZE;
++}
++
++struct net *xfrmi_get_link_net(const struct net_device *dev)
++{
++ struct xfrm_if *xi = netdev_priv(dev);
++
++ return xi->net;
++}
++
++static const struct nla_policy xfrmi_policy[IFLA_XFRM_MAX + 1] = {
++ [IFLA_XFRM_LINK] = { .type = NLA_U32 },
++ [IFLA_XFRM_IF_ID] = { .type = NLA_U32 },
++};
++
++static struct rtnl_link_ops xfrmi_link_ops __read_mostly = {
++ .kind = "xfrm",
++ .maxtype = IFLA_XFRM_MAX,
++ .policy = xfrmi_policy,
++ .priv_size = sizeof(struct xfrm_if),
++ .setup = xfrmi_dev_setup,
++ .validate = xfrmi_validate,
++ .newlink = xfrmi_newlink,
++ .dellink = xfrmi_dellink,
++ .changelink = xfrmi_changelink,
++ .get_size = xfrmi_get_size,
++ .fill_info = xfrmi_fill_info,
++ .get_link_net = xfrmi_get_link_net,
++};
++
++static void __net_exit xfrmi_destroy_interfaces(struct xfrmi_net *xfrmn)
++{
++ struct xfrm_if *xi;
++ LIST_HEAD(list);
++
++ xi = rtnl_dereference(xfrmn->xfrmi[0]);
++ if (!xi)
++ return;
++
++ unregister_netdevice_queue(xi->dev, &list);
++ unregister_netdevice_many(&list);
++}
++
++static int __net_init xfrmi_init_net(struct net *net)
++{
++ return 0;
++}
++
++static void __net_exit xfrmi_exit_net(struct net *net)
++{
++ struct xfrmi_net *xfrmn = net_generic(net, xfrmi_net_id);
++
++ rtnl_lock();
++ xfrmi_destroy_interfaces(xfrmn);
++ rtnl_unlock();
++}
++
++static void __net_exit xfrmi_exit_batch_net(struct list_head *net_exit_list)
++{
++ struct net *net;
++ LIST_HEAD(list);
++
++ rtnl_lock();
++ list_for_each_entry(net, net_exit_list, exit_list) {
++ struct xfrmi_net *xfrmn = net_generic(net, xfrmi_net_id);
++ struct xfrm_if __rcu **xip;
++ struct xfrm_if *xi;
++
++ for (xip = &xfrmn->xfrmi[0];
++ (xi = rtnl_dereference(*xip)) != NULL;
++ xip = &xi->next)
++ unregister_netdevice_queue(xi->dev, &list);
++ }
++ unregister_netdevice_many(&list);
++ rtnl_unlock();
++}
++
++static struct pernet_operations xfrmi_net_ops = {
++ .exit_batch = xfrmi_exit_batch_net,
++ .init = xfrmi_init_net,
++ .exit = xfrmi_exit_net,
++ .id = &xfrmi_net_id,
++ .size = sizeof(struct xfrmi_net),
++};
++
++static struct xfrm6_protocol xfrmi_esp6_protocol __read_mostly = {
++ .handler = xfrm6_rcv,
++ .cb_handler = xfrmi_rcv_cb,
++ .err_handler = xfrmi6_err,
++ .priority = 10,
++};
++
++static struct xfrm6_protocol xfrmi_ah6_protocol __read_mostly = {
++ .handler = xfrm6_rcv,
++ .cb_handler = xfrmi_rcv_cb,
++ .err_handler = xfrmi6_err,
++ .priority = 10,
++};
++
++static struct xfrm6_protocol xfrmi_ipcomp6_protocol __read_mostly = {
++ .handler = xfrm6_rcv,
++ .cb_handler = xfrmi_rcv_cb,
++ .err_handler = xfrmi6_err,
++ .priority = 10,
++};
++
++static struct xfrm4_protocol xfrmi_esp4_protocol __read_mostly = {
++ .handler = xfrm4_rcv,
++ .input_handler = xfrm_input,
++ .cb_handler = xfrmi_rcv_cb,
++ .err_handler = xfrmi4_err,
++ .priority = 10,
++};
++
++static struct xfrm4_protocol xfrmi_ah4_protocol __read_mostly = {
++ .handler = xfrm4_rcv,
++ .input_handler = xfrm_input,
++ .cb_handler = xfrmi_rcv_cb,
++ .err_handler = xfrmi4_err,
++ .priority = 10,
++};
++
++static struct xfrm4_protocol xfrmi_ipcomp4_protocol __read_mostly = {
++ .handler = xfrm4_rcv,
++ .input_handler = xfrm_input,
++ .cb_handler = xfrmi_rcv_cb,
++ .err_handler = xfrmi4_err,
++ .priority = 10,
++};
++
++static int __init xfrmi4_init(void)
++{
++ int err;
++
++ err = xfrm4_protocol_register(&xfrmi_esp4_protocol, IPPROTO_ESP);
++ if (err < 0)
++ goto xfrm_proto_esp_failed;
++ err = xfrm4_protocol_register(&xfrmi_ah4_protocol, IPPROTO_AH);
++ if (err < 0)
++ goto xfrm_proto_ah_failed;
++ err = xfrm4_protocol_register(&xfrmi_ipcomp4_protocol, IPPROTO_COMP);
++ if (err < 0)
++ goto xfrm_proto_comp_failed;
++
++ return 0;
++
++xfrm_proto_comp_failed:
++ xfrm4_protocol_deregister(&xfrmi_ah4_protocol, IPPROTO_AH);
++xfrm_proto_ah_failed:
++ xfrm4_protocol_deregister(&xfrmi_esp4_protocol, IPPROTO_ESP);
++xfrm_proto_esp_failed:
++ return err;
++}
++
++static void xfrmi4_fini(void)
++{
++ xfrm4_protocol_deregister(&xfrmi_ipcomp4_protocol, IPPROTO_COMP);
++ xfrm4_protocol_deregister(&xfrmi_ah4_protocol, IPPROTO_AH);
++ xfrm4_protocol_deregister(&xfrmi_esp4_protocol, IPPROTO_ESP);
++}
++
++static int __init xfrmi6_init(void)
++{
++ int err;
++
++ err = xfrm6_protocol_register(&xfrmi_esp6_protocol, IPPROTO_ESP);
++ if (err < 0)
++ goto xfrm_proto_esp_failed;
++ err = xfrm6_protocol_register(&xfrmi_ah6_protocol, IPPROTO_AH);
++ if (err < 0)
++ goto xfrm_proto_ah_failed;
++ err = xfrm6_protocol_register(&xfrmi_ipcomp6_protocol, IPPROTO_COMP);
++ if (err < 0)
++ goto xfrm_proto_comp_failed;
++
++ return 0;
++
++xfrm_proto_comp_failed:
++ xfrm6_protocol_deregister(&xfrmi_ah6_protocol, IPPROTO_AH);
++xfrm_proto_ah_failed:
++ xfrm6_protocol_deregister(&xfrmi_esp6_protocol, IPPROTO_ESP);
++xfrm_proto_esp_failed:
++ return err;
++}
++
++static void xfrmi6_fini(void)
++{
++ xfrm6_protocol_deregister(&xfrmi_ipcomp6_protocol, IPPROTO_COMP);
++ xfrm6_protocol_deregister(&xfrmi_ah6_protocol, IPPROTO_AH);
++ xfrm6_protocol_deregister(&xfrmi_esp6_protocol, IPPROTO_ESP);
++}
++
++static const struct xfrm_if_cb xfrm_if_cb = {
++ .decode_session = xfrmi_decode_session,
++};
++
++static int __init xfrmi_init(void)
++{
++ const char *msg;
++ int err;
++
++ pr_info("IPsec XFRM device driver\n");
++
++ msg = "tunnel device";
++ err = register_pernet_device(&xfrmi_net_ops);
++ if (err < 0)
++ goto pernet_dev_failed;
++
++ msg = "xfrm4 protocols";
++ err = xfrmi4_init();
++ if (err < 0)
++ goto xfrmi4_failed;
++
++ msg = "xfrm6 protocols";
++ err = xfrmi6_init();
++ if (err < 0)
++ goto xfrmi6_failed;
++
++
++ msg = "netlink interface";
++ err = rtnl_link_register(&xfrmi_link_ops);
++ if (err < 0)
++ goto rtnl_link_failed;
++
++ xfrm_if_register_cb(&xfrm_if_cb);
++
++ return err;
++
++rtnl_link_failed:
++ xfrmi6_fini();
++xfrmi6_failed:
++ xfrmi4_fini();
++xfrmi4_failed:
++ unregister_pernet_device(&xfrmi_net_ops);
++pernet_dev_failed:
++ pr_err("xfrmi init: failed to register %s\n", msg);
++ return err;
++}
++
++static void __exit xfrmi_fini(void)
++{
++ xfrm_if_unregister_cb();
++ rtnl_link_unregister(&xfrmi_link_ops);
++ xfrmi4_fini();
++ xfrmi6_fini();
++ unregister_pernet_device(&xfrmi_net_ops);
++}
++
++module_init(xfrmi_init);
++module_exit(xfrmi_fini);
++MODULE_LICENSE("GPL");
++MODULE_ALIAS_RTNL_LINK("xfrm");
++MODULE_ALIAS_NETDEV("xfrm0");
++MODULE_AUTHOR("Steffen Klassert");
++MODULE_DESCRIPTION("XFRM virtual interface");
+diff --git a/net/xfrm/xfrm_user.c b/net/xfrm/xfrm_user.c
+index 94c7ebc26c48e..699e544b4bfd6 100644
+--- a/net/xfrm/xfrm_user.c
++++ b/net/xfrm/xfrm_user.c
+@@ -521,7 +521,7 @@ static void xfrm_update_ae_params(struct xfrm_state *x, struct nlattr **attrs,
+ struct nlattr *et = attrs[XFRMA_ETIMER_THRESH];
+ struct nlattr *rt = attrs[XFRMA_REPLAY_THRESH];
+
+- if (re) {
++ if (re && x->replay_esn && x->preplay_esn) {
+ struct xfrm_replay_state_esn *replay_esn;
+ replay_esn = nla_data(re);
+ memcpy(x->replay_esn, replay_esn,
+@@ -1036,6 +1036,15 @@ static int xfrm_dump_sa(struct sk_buff *skb, struct netlink_callback *cb)
+ sizeof(*filter), GFP_KERNEL);
+ if (filter == NULL)
+ return -ENOMEM;
++
++ /* see addr_match(), (prefix length >> 5) << 2
++ * will be used to compare xfrm_address_t
++ */
++ if (filter->splen > (sizeof(xfrm_address_t) << 3) ||
++ filter->dplen > (sizeof(xfrm_address_t) << 3)) {
++ kfree(filter);
++ return -EINVAL;
++ }
+ }
+
+ if (attrs[XFRMA_PROTO])
+@@ -2573,7 +2582,7 @@ static const struct nla_policy xfrma_policy[XFRMA_MAX+1] = {
+ [XFRMA_ALG_COMP] = { .len = sizeof(struct xfrm_algo) },
+ [XFRMA_ENCAP] = { .len = sizeof(struct xfrm_encap_tmpl) },
+ [XFRMA_TMPL] = { .len = sizeof(struct xfrm_user_tmpl) },
+- [XFRMA_SEC_CTX] = { .len = sizeof(struct xfrm_sec_ctx) },
++ [XFRMA_SEC_CTX] = { .len = sizeof(struct xfrm_user_sec_ctx) },
+ [XFRMA_LTIME_VAL] = { .len = sizeof(struct xfrm_lifetime_cur) },
+ [XFRMA_REPLAY_VAL] = { .len = sizeof(struct xfrm_replay_state) },
+ [XFRMA_REPLAY_THRESH] = { .type = NLA_U32 },
+diff --git a/security/integrity/ima/Kconfig b/security/integrity/ima/Kconfig
+index 3ec45028a8c54..cd32fe3311afe 100644
+--- a/security/integrity/ima/Kconfig
++++ b/security/integrity/ima/Kconfig
+@@ -7,7 +7,7 @@ config IMA
+ select CRYPTO_HMAC
+ select CRYPTO_SHA1
+ select CRYPTO_HASH_INFO
+- select TCG_TPM if HAS_IOMEM && !UML
++ select TCG_TPM if HAS_IOMEM
+ select TCG_TIS if TCG_TPM && X86
+ select TCG_CRB if TCG_TPM && ACPI
+ select TCG_IBMVTPM if TCG_TPM && PPC_PSERIES
+diff --git a/sound/pci/emu10k1/emufx.c b/sound/pci/emu10k1/emufx.c
+index 1f25e6d029d82..84d98c098b744 100644
+--- a/sound/pci/emu10k1/emufx.c
++++ b/sound/pci/emu10k1/emufx.c
+@@ -1550,14 +1550,8 @@ A_OP(icode, &ptr, iMAC0, A_GPR(var), A_GPR(var), A_GPR(vol), A_EXTIN(input))
+ gpr += 2;
+
+ /* Master volume (will be renamed later) */
+- A_OP(icode, &ptr, iMAC0, A_GPR(playback+0+SND_EMU10K1_PLAYBACK_CHANNELS), A_C_00000000, A_GPR(gpr), A_GPR(playback+0+SND_EMU10K1_PLAYBACK_CHANNELS));
+- A_OP(icode, &ptr, iMAC0, A_GPR(playback+1+SND_EMU10K1_PLAYBACK_CHANNELS), A_C_00000000, A_GPR(gpr), A_GPR(playback+1+SND_EMU10K1_PLAYBACK_CHANNELS));
+- A_OP(icode, &ptr, iMAC0, A_GPR(playback+2+SND_EMU10K1_PLAYBACK_CHANNELS), A_C_00000000, A_GPR(gpr), A_GPR(playback+2+SND_EMU10K1_PLAYBACK_CHANNELS));
+- A_OP(icode, &ptr, iMAC0, A_GPR(playback+3+SND_EMU10K1_PLAYBACK_CHANNELS), A_C_00000000, A_GPR(gpr), A_GPR(playback+3+SND_EMU10K1_PLAYBACK_CHANNELS));
+- A_OP(icode, &ptr, iMAC0, A_GPR(playback+4+SND_EMU10K1_PLAYBACK_CHANNELS), A_C_00000000, A_GPR(gpr), A_GPR(playback+4+SND_EMU10K1_PLAYBACK_CHANNELS));
+- A_OP(icode, &ptr, iMAC0, A_GPR(playback+5+SND_EMU10K1_PLAYBACK_CHANNELS), A_C_00000000, A_GPR(gpr), A_GPR(playback+5+SND_EMU10K1_PLAYBACK_CHANNELS));
+- A_OP(icode, &ptr, iMAC0, A_GPR(playback+6+SND_EMU10K1_PLAYBACK_CHANNELS), A_C_00000000, A_GPR(gpr), A_GPR(playback+6+SND_EMU10K1_PLAYBACK_CHANNELS));
+- A_OP(icode, &ptr, iMAC0, A_GPR(playback+7+SND_EMU10K1_PLAYBACK_CHANNELS), A_C_00000000, A_GPR(gpr), A_GPR(playback+7+SND_EMU10K1_PLAYBACK_CHANNELS));
++ for (z = 0; z < 8; z++)
++ A_OP(icode, &ptr, iMAC0, A_GPR(playback+z+SND_EMU10K1_PLAYBACK_CHANNELS), A_C_00000000, A_GPR(gpr), A_GPR(playback+z+SND_EMU10K1_PLAYBACK_CHANNELS));
+ snd_emu10k1_init_mono_control(&controls[nctl++], "Wave Master Playback Volume", gpr, 0);
+ gpr += 2;
+
+@@ -1641,102 +1635,14 @@ A_OP(icode, &ptr, iMAC0, A_GPR(var), A_GPR(var), A_GPR(vol), A_EXTIN(input))
+ dev_dbg(emu->card->dev, "emufx.c: gpr=0x%x, tmp=0x%x\n",
+ gpr, tmp);
+ */
+- /* For the EMU1010: How to get 32bit values from the DSP. High 16bits into L, low 16bits into R. */
+- /* A_P16VIN(0) is delayed by one sample,
+- * so all other A_P16VIN channels will need to also be delayed
+- */
+- /* Left ADC in. 1 of 2 */
+ snd_emu10k1_audigy_dsp_convert_32_to_2x16( icode, &ptr, tmp, bit_shifter16, A_P16VIN(0x0), A_FXBUS2(0) );
+- /* Right ADC in 1 of 2 */
+- gpr_map[gpr++] = 0x00000000;
+- /* Delaying by one sample: instead of copying the input
+- * value A_P16VIN to output A_FXBUS2 as in the first channel,
+- * we use an auxiliary register, delaying the value by one
+- * sample
+- */
+- snd_emu10k1_audigy_dsp_convert_32_to_2x16( icode, &ptr, tmp, bit_shifter16, A_GPR(gpr - 1), A_FXBUS2(2) );
+- A_OP(icode, &ptr, iACC3, A_GPR(gpr - 1), A_P16VIN(0x1), A_C_00000000, A_C_00000000);
+- gpr_map[gpr++] = 0x00000000;
+- snd_emu10k1_audigy_dsp_convert_32_to_2x16( icode, &ptr, tmp, bit_shifter16, A_GPR(gpr - 1), A_FXBUS2(4) );
+- A_OP(icode, &ptr, iACC3, A_GPR(gpr - 1), A_P16VIN(0x2), A_C_00000000, A_C_00000000);
+- gpr_map[gpr++] = 0x00000000;
+- snd_emu10k1_audigy_dsp_convert_32_to_2x16( icode, &ptr, tmp, bit_shifter16, A_GPR(gpr - 1), A_FXBUS2(6) );
+- A_OP(icode, &ptr, iACC3, A_GPR(gpr - 1), A_P16VIN(0x3), A_C_00000000, A_C_00000000);
+- /* For 96kHz mode */
+- /* Left ADC in. 2 of 2 */
+- gpr_map[gpr++] = 0x00000000;
+- snd_emu10k1_audigy_dsp_convert_32_to_2x16( icode, &ptr, tmp, bit_shifter16, A_GPR(gpr - 1), A_FXBUS2(0x8) );
+- A_OP(icode, &ptr, iACC3, A_GPR(gpr - 1), A_P16VIN(0x4), A_C_00000000, A_C_00000000);
+- /* Right ADC in 2 of 2 */
+- gpr_map[gpr++] = 0x00000000;
+- snd_emu10k1_audigy_dsp_convert_32_to_2x16( icode, &ptr, tmp, bit_shifter16, A_GPR(gpr - 1), A_FXBUS2(0xa) );
+- A_OP(icode, &ptr, iACC3, A_GPR(gpr - 1), A_P16VIN(0x5), A_C_00000000, A_C_00000000);
+- gpr_map[gpr++] = 0x00000000;
+- snd_emu10k1_audigy_dsp_convert_32_to_2x16( icode, &ptr, tmp, bit_shifter16, A_GPR(gpr - 1), A_FXBUS2(0xc) );
+- A_OP(icode, &ptr, iACC3, A_GPR(gpr - 1), A_P16VIN(0x6), A_C_00000000, A_C_00000000);
+- gpr_map[gpr++] = 0x00000000;
+- snd_emu10k1_audigy_dsp_convert_32_to_2x16( icode, &ptr, tmp, bit_shifter16, A_GPR(gpr - 1), A_FXBUS2(0xe) );
+- A_OP(icode, &ptr, iACC3, A_GPR(gpr - 1), A_P16VIN(0x7), A_C_00000000, A_C_00000000);
+- /* Pavel Hofman - we still have voices, A_FXBUS2s, and
+- * A_P16VINs available -
+- * let's add 8 more capture channels - total of 16
+- */
+- gpr_map[gpr++] = 0x00000000;
+- snd_emu10k1_audigy_dsp_convert_32_to_2x16(icode, &ptr, tmp,
+- bit_shifter16,
+- A_GPR(gpr - 1),
+- A_FXBUS2(0x10));
+- A_OP(icode, &ptr, iACC3, A_GPR(gpr - 1), A_P16VIN(0x8),
+- A_C_00000000, A_C_00000000);
+- gpr_map[gpr++] = 0x00000000;
+- snd_emu10k1_audigy_dsp_convert_32_to_2x16(icode, &ptr, tmp,
+- bit_shifter16,
+- A_GPR(gpr - 1),
+- A_FXBUS2(0x12));
+- A_OP(icode, &ptr, iACC3, A_GPR(gpr - 1), A_P16VIN(0x9),
+- A_C_00000000, A_C_00000000);
+- gpr_map[gpr++] = 0x00000000;
+- snd_emu10k1_audigy_dsp_convert_32_to_2x16(icode, &ptr, tmp,
+- bit_shifter16,
+- A_GPR(gpr - 1),
+- A_FXBUS2(0x14));
+- A_OP(icode, &ptr, iACC3, A_GPR(gpr - 1), A_P16VIN(0xa),
+- A_C_00000000, A_C_00000000);
+- gpr_map[gpr++] = 0x00000000;
+- snd_emu10k1_audigy_dsp_convert_32_to_2x16(icode, &ptr, tmp,
+- bit_shifter16,
+- A_GPR(gpr - 1),
+- A_FXBUS2(0x16));
+- A_OP(icode, &ptr, iACC3, A_GPR(gpr - 1), A_P16VIN(0xb),
+- A_C_00000000, A_C_00000000);
+- gpr_map[gpr++] = 0x00000000;
+- snd_emu10k1_audigy_dsp_convert_32_to_2x16(icode, &ptr, tmp,
+- bit_shifter16,
+- A_GPR(gpr - 1),
+- A_FXBUS2(0x18));
+- A_OP(icode, &ptr, iACC3, A_GPR(gpr - 1), A_P16VIN(0xc),
+- A_C_00000000, A_C_00000000);
+- gpr_map[gpr++] = 0x00000000;
+- snd_emu10k1_audigy_dsp_convert_32_to_2x16(icode, &ptr, tmp,
+- bit_shifter16,
+- A_GPR(gpr - 1),
+- A_FXBUS2(0x1a));
+- A_OP(icode, &ptr, iACC3, A_GPR(gpr - 1), A_P16VIN(0xd),
+- A_C_00000000, A_C_00000000);
+- gpr_map[gpr++] = 0x00000000;
+- snd_emu10k1_audigy_dsp_convert_32_to_2x16(icode, &ptr, tmp,
+- bit_shifter16,
+- A_GPR(gpr - 1),
+- A_FXBUS2(0x1c));
+- A_OP(icode, &ptr, iACC3, A_GPR(gpr - 1), A_P16VIN(0xe),
+- A_C_00000000, A_C_00000000);
+- gpr_map[gpr++] = 0x00000000;
+- snd_emu10k1_audigy_dsp_convert_32_to_2x16(icode, &ptr, tmp,
+- bit_shifter16,
+- A_GPR(gpr - 1),
+- A_FXBUS2(0x1e));
+- A_OP(icode, &ptr, iACC3, A_GPR(gpr - 1), A_P16VIN(0xf),
+- A_C_00000000, A_C_00000000);
++ /* A_P16VIN(0) is delayed by one sample, so all other A_P16VIN channels
++ * will need to also be delayed; we use an auxiliary register for that. */
++ for (z = 1; z < 0x10; z++) {
++ snd_emu10k1_audigy_dsp_convert_32_to_2x16( icode, &ptr, tmp, bit_shifter16, A_GPR(gpr), A_FXBUS2(z * 2) );
++ A_OP(icode, &ptr, iACC3, A_GPR(gpr), A_P16VIN(z), A_C_00000000, A_C_00000000);
++ gpr_map[gpr++] = 0x00000000;
++ }
+ }
+
+ #if 0
+diff --git a/sound/soc/codecs/rt5665.c b/sound/soc/codecs/rt5665.c
+index 6ba99f5ed3f42..a7ed2a19c3ec2 100644
+--- a/sound/soc/codecs/rt5665.c
++++ b/sound/soc/codecs/rt5665.c
+@@ -4475,6 +4475,8 @@ static void rt5665_remove(struct snd_soc_component *component)
+ struct rt5665_priv *rt5665 = snd_soc_component_get_drvdata(component);
+
+ regmap_write(rt5665->regmap, RT5665_RESET, 0);
++
++ regulator_bulk_disable(ARRAY_SIZE(rt5665->supplies), rt5665->supplies);
+ }
+
+ #ifdef CONFIG_PM
+diff --git a/sound/soc/meson/axg-tdm-formatter.c b/sound/soc/meson/axg-tdm-formatter.c
+index 43e390f9358a4..a195160b68208 100644
+--- a/sound/soc/meson/axg-tdm-formatter.c
++++ b/sound/soc/meson/axg-tdm-formatter.c
+@@ -28,27 +28,32 @@ int axg_tdm_formatter_set_channel_masks(struct regmap *map,
+ struct axg_tdm_stream *ts,
+ unsigned int offset)
+ {
+- unsigned int val, ch = ts->channels;
+- unsigned long mask;
+- int i, j;
++ unsigned int ch = ts->channels;
++ u32 val[AXG_TDM_NUM_LANES];
++ int i, j, k;
++
++ /*
++ * We need to mimick the slot distribution used by the HW to keep the
++ * channel placement consistent regardless of the number of channel
++ * in the stream. This is why the odd algorithm below is used.
++ */
++ memset(val, 0, sizeof(*val) * AXG_TDM_NUM_LANES);
+
+ /*
+ * Distribute the channels of the stream over the available slots
+- * of each TDM lane
++ * of each TDM lane. We need to go over the 32 slots ...
+ */
+- for (i = 0; i < AXG_TDM_NUM_LANES; i++) {
+- val = 0;
+- mask = ts->mask[i];
+-
+- for (j = find_first_bit(&mask, 32);
+- (j < 32) && ch;
+- j = find_next_bit(&mask, 32, j + 1)) {
+- val |= 1 << j;
+- ch -= 1;
++ for (i = 0; (i < 32) && ch; i += 2) {
++ /* ... of all the lanes ... */
++ for (j = 0; j < AXG_TDM_NUM_LANES; j++) {
++ /* ... then distribute the channels in pairs */
++ for (k = 0; k < 2; k++) {
++ if ((BIT(i + k) & ts->mask[j]) && ch) {
++ val[j] |= BIT(i + k);
++ ch -= 1;
++ }
++ }
+ }
+-
+- regmap_write(map, offset, val);
+- offset += regmap_get_reg_stride(map);
+ }
+
+ /*
+@@ -61,6 +66,11 @@ int axg_tdm_formatter_set_channel_masks(struct regmap *map,
+ return -EINVAL;
+ }
+
++ for (i = 0; i < AXG_TDM_NUM_LANES; i++) {
++ regmap_write(map, offset, val[i]);
++ offset += regmap_get_reg_stride(map);
++ }
++
+ return 0;
+ }
+ EXPORT_SYMBOL_GPL(axg_tdm_formatter_set_channel_masks);
+diff --git a/sound/usb/quirks-table.h b/sound/usb/quirks-table.h
+index e72f744bc305d..6c546f520f994 100644
+--- a/sound/usb/quirks-table.h
++++ b/sound/usb/quirks-table.h
+@@ -3677,5 +3677,34 @@ ALC1220_VB_DESKTOP(0x26ce, 0x0a01), /* Asrock TRX40 Creator */
+ }
+ }
+ },
++{
++ /* Advanced modes of the Mythware XA001AU.
++ * For the standard mode, Mythware XA001AU has ID ffad:a001
++ */
++ USB_DEVICE_VENDOR_SPEC(0xffad, 0xa001),
++ .driver_info = (unsigned long) &(const struct snd_usb_audio_quirk) {
++ .vendor_name = "Mythware",
++ .product_name = "XA001AU",
++ .ifnum = QUIRK_ANY_INTERFACE,
++ .type = QUIRK_COMPOSITE,
++ .data = (const struct snd_usb_audio_quirk[]) {
++ {
++ .ifnum = 0,
++ .type = QUIRK_IGNORE_INTERFACE,
++ },
++ {
++ .ifnum = 1,
++ .type = QUIRK_AUDIO_STANDARD_INTERFACE,
++ },
++ {
++ .ifnum = 2,
++ .type = QUIRK_AUDIO_STANDARD_INTERFACE,
++ },
++ {
++ .ifnum = -1
++ }
++ }
++ }
++},
+
+ #undef USB_DEVICE_VENDOR_SPEC
+diff --git a/tools/testing/selftests/net/forwarding/mirror_gre_changes.sh b/tools/testing/selftests/net/forwarding/mirror_gre_changes.sh
+index 135902aa8b114..a372863c9efdb 100755
+--- a/tools/testing/selftests/net/forwarding/mirror_gre_changes.sh
++++ b/tools/testing/selftests/net/forwarding/mirror_gre_changes.sh
+@@ -72,7 +72,8 @@ test_span_gre_ttl()
+
+ RET=0
+
+- mirror_install $swp1 ingress $tundev "matchall $tcflags"
++ mirror_install $swp1 ingress $tundev \
++ "prot ip flower $tcflags ip_prot icmp"
+ tc filter add dev $h3 ingress pref 77 prot $prot \
+ flower ip_ttl 50 action pass
+
+diff --git a/tools/testing/selftests/net/forwarding/tc_flower.sh b/tools/testing/selftests/net/forwarding/tc_flower.sh
+index 20d1077e5a3de..85faef980887a 100755
+--- a/tools/testing/selftests/net/forwarding/tc_flower.sh
++++ b/tools/testing/selftests/net/forwarding/tc_flower.sh
+@@ -48,8 +48,8 @@ match_dst_mac_test()
+ tc_check_packets "dev $h2 ingress" 101 1
+ check_fail $? "Matched on a wrong filter"
+
+- tc_check_packets "dev $h2 ingress" 102 1
+- check_err $? "Did not match on correct filter"
++ tc_check_packets "dev $h2 ingress" 102 0
++ check_fail $? "Did not match on correct filter"
+
+ tc filter del dev $h2 ingress protocol ip pref 1 handle 101 flower
+ tc filter del dev $h2 ingress protocol ip pref 2 handle 102 flower
+@@ -74,8 +74,8 @@ match_src_mac_test()
+ tc_check_packets "dev $h2 ingress" 101 1
+ check_fail $? "Matched on a wrong filter"
+
+- tc_check_packets "dev $h2 ingress" 102 1
+- check_err $? "Did not match on correct filter"
++ tc_check_packets "dev $h2 ingress" 102 0
++ check_fail $? "Did not match on correct filter"
+
+ tc filter del dev $h2 ingress protocol ip pref 1 handle 101 flower
+ tc filter del dev $h2 ingress protocol ip pref 2 handle 102 flower