diff -druNp --no-dereference linux-libre-5.2-rc7-gnu/arch/arm/boot/dts/armada-xp-98dx3236.dtsi linux-libre-5.2-gnu/arch/arm/boot/dts/armada-xp-98dx3236.dtsi
--- linux-libre-5.2-rc7-gnu/arch/arm/boot/dts/armada-xp-98dx3236.dtsi	2019-06-29 23:25:36.000000000 -0400
+++ linux-libre-5.2-gnu/arch/arm/boot/dts/armada-xp-98dx3236.dtsi	2019-07-07 18:41:56.000000000 -0400
@@ -336,3 +336,11 @@
 	status = "disabled";
 };
 
+&uart0 {
+	compatible = "marvell,armada-38x-uart";
+};
+
+&uart1 {
+	compatible = "marvell,armada-38x-uart";
+};
+
diff -druNp --no-dereference linux-libre-5.2-rc7-gnu/arch/arm/mach-davinci/board-da830-evm.c linux-libre-5.2-gnu/arch/arm/mach-davinci/board-da830-evm.c
--- linux-libre-5.2-rc7-gnu/arch/arm/mach-davinci/board-da830-evm.c	2019-06-29 23:25:36.000000000 -0400
+++ linux-libre-5.2-gnu/arch/arm/mach-davinci/board-da830-evm.c	2019-07-07 18:41:56.000000000 -0400
@@ -61,6 +61,9 @@ static struct regulator_consumer_supply
 static struct regulator_init_data da830_evm_usb_vbus_data = {
 	.consumer_supplies	= da830_evm_usb_supplies,
 	.num_consumer_supplies	= ARRAY_SIZE(da830_evm_usb_supplies),
+	.constraints    = {
+		.valid_ops_mask = REGULATOR_CHANGE_STATUS,
+	},
 };
 
 static struct fixed_voltage_config da830_evm_usb_vbus = {
@@ -88,7 +91,7 @@ static struct gpiod_lookup_table da830_e
 static struct gpiod_lookup_table da830_evm_usb_vbus_gpio_lookup = {
 	.dev_id		= "reg-fixed-voltage.0",
 	.table = {
-		GPIO_LOOKUP("davinci_gpio", ON_BD_USB_DRV, "vbus", 0),
+		GPIO_LOOKUP("davinci_gpio", ON_BD_USB_DRV, NULL, 0),
 		{ }
 	},
 };
diff -druNp --no-dereference linux-libre-5.2-rc7-gnu/arch/arm/mach-davinci/board-omapl138-hawk.c linux-libre-5.2-gnu/arch/arm/mach-davinci/board-omapl138-hawk.c
--- linux-libre-5.2-rc7-gnu/arch/arm/mach-davinci/board-omapl138-hawk.c	2019-06-29 23:25:36.000000000 -0400
+++ linux-libre-5.2-gnu/arch/arm/mach-davinci/board-omapl138-hawk.c	2019-07-07 18:41:56.000000000 -0400
@@ -306,6 +306,9 @@ static struct regulator_consumer_supply
 static struct regulator_init_data hawk_usb_vbus_data = {
 	.consumer_supplies	= hawk_usb_supplies,
 	.num_consumer_supplies	= ARRAY_SIZE(hawk_usb_supplies),
+	.constraints    = {
+		.valid_ops_mask = REGULATOR_CHANGE_STATUS,
+	},
 };
 
 static struct fixed_voltage_config hawk_usb_vbus = {
diff -druNp --no-dereference linux-libre-5.2-rc7-gnu/arch/arm64/kernel/image.h linux-libre-5.2-gnu/arch/arm64/kernel/image.h
--- linux-libre-5.2-rc7-gnu/arch/arm64/kernel/image.h	2019-06-29 23:25:36.000000000 -0400
+++ linux-libre-5.2-gnu/arch/arm64/kernel/image.h	2019-07-07 18:41:56.000000000 -0400
@@ -67,7 +67,11 @@
 
 #ifdef CONFIG_EFI
 
-__efistub_stext_offset = stext - _text;
+/*
+ * Use ABSOLUTE() to avoid ld.lld treating this as a relative symbol:
+ * https://github.com/ClangBuiltLinux/linux/issues/561
+ */
+__efistub_stext_offset = ABSOLUTE(stext - _text);
 
 /*
  * The EFI stub has its own symbol namespace prefixed by __efistub_, to
diff -druNp --no-dereference linux-libre-5.2-rc7-gnu/arch/arm64/kernel/module.c linux-libre-5.2-gnu/arch/arm64/kernel/module.c
--- linux-libre-5.2-rc7-gnu/arch/arm64/kernel/module.c	2019-06-29 23:25:36.000000000 -0400
+++ linux-libre-5.2-gnu/arch/arm64/kernel/module.c	2019-07-07 18:41:56.000000000 -0400
@@ -21,6 +21,7 @@
 
 void *module_alloc(unsigned long size)
 {
+	u64 module_alloc_end = module_alloc_base + MODULES_VSIZE;
 	gfp_t gfp_mask = GFP_KERNEL;
 	void *p;
 
@@ -28,9 +29,12 @@ void *module_alloc(unsigned long size)
 	if (IS_ENABLED(CONFIG_ARM64_MODULE_PLTS))
 		gfp_mask |= __GFP_NOWARN;
 
+	if (IS_ENABLED(CONFIG_KASAN))
+		/* don't exceed the static module region - see below */
+		module_alloc_end = MODULES_END;
+
 	p = __vmalloc_node_range(size, MODULE_ALIGN, module_alloc_base,
-				module_alloc_base + MODULES_VSIZE,
-				gfp_mask, PAGE_KERNEL_EXEC, 0,
+				module_alloc_end, gfp_mask, PAGE_KERNEL_EXEC, 0,
 				NUMA_NO_NODE, __builtin_return_address(0));
 
 	if (!p && IS_ENABLED(CONFIG_ARM64_MODULE_PLTS) &&
diff -druNp --no-dereference linux-libre-5.2-rc7-gnu/arch/arm64/kvm/guest.c linux-libre-5.2-gnu/arch/arm64/kvm/guest.c
--- linux-libre-5.2-rc7-gnu/arch/arm64/kvm/guest.c	2019-06-29 23:25:36.000000000 -0400
+++ linux-libre-5.2-gnu/arch/arm64/kvm/guest.c	2019-07-07 18:41:56.000000000 -0400
@@ -208,7 +208,7 @@ out:
 
 #define vq_word(vq) (((vq) - SVE_VQ_MIN) / 64)
 #define vq_mask(vq) ((u64)1 << ((vq) - SVE_VQ_MIN) % 64)
-#define vq_present(vqs, vq) ((vqs)[vq_word(vq)] & vq_mask(vq))
+#define vq_present(vqs, vq) (!!((vqs)[vq_word(vq)] & vq_mask(vq)))
 
 static int get_sve_vls(struct kvm_vcpu *vcpu, const struct kvm_one_reg *reg)
 {
diff -druNp --no-dereference linux-libre-5.2-rc7-gnu/arch/mips/boot/compressed/calc_vmlinuz_load_addr.c linux-libre-5.2-gnu/arch/mips/boot/compressed/calc_vmlinuz_load_addr.c
--- linux-libre-5.2-rc7-gnu/arch/mips/boot/compressed/calc_vmlinuz_load_addr.c	2019-06-29 23:25:36.000000000 -0400
+++ linux-libre-5.2-gnu/arch/mips/boot/compressed/calc_vmlinuz_load_addr.c	2019-07-07 18:41:56.000000000 -0400
@@ -9,7 +9,7 @@
 #include <stdint.h>
 #include <stdio.h>
 #include <stdlib.h>
-#include "../../../../include/linux/sizes.h"
+#include <linux/sizes.h>
 
 int main(int argc, char *argv[])
 {
diff -druNp --no-dereference linux-libre-5.2-rc7-gnu/arch/mips/boot/compressed/Makefile linux-libre-5.2-gnu/arch/mips/boot/compressed/Makefile
--- linux-libre-5.2-rc7-gnu/arch/mips/boot/compressed/Makefile	2019-06-29 23:25:36.000000000 -0400
+++ linux-libre-5.2-gnu/arch/mips/boot/compressed/Makefile	2019-07-07 18:41:56.000000000 -0400
@@ -78,6 +78,8 @@ OBJCOPYFLAGS_piggy.o := --add-section=.i
 $(obj)/piggy.o: $(obj)/dummy.o $(obj)/vmlinux.bin.z FORCE
 	$(call if_changed,objcopy)
 
+HOSTCFLAGS_calc_vmlinuz_load_addr.o += $(LINUXINCLUDE)
+
 # Calculate the load address of the compressed kernel image
 hostprogs-y := calc_vmlinuz_load_addr
 
diff -druNp --no-dereference linux-libre-5.2-rc7-gnu/arch/mips/include/asm/mach-ath79/ar933x_uart.h linux-libre-5.2-gnu/arch/mips/include/asm/mach-ath79/ar933x_uart.h
--- linux-libre-5.2-rc7-gnu/arch/mips/include/asm/mach-ath79/ar933x_uart.h	2019-06-29 23:25:36.000000000 -0400
+++ linux-libre-5.2-gnu/arch/mips/include/asm/mach-ath79/ar933x_uart.h	2019-07-07 18:41:56.000000000 -0400
@@ -24,8 +24,8 @@
 #define AR933X_UART_CS_PARITY_S		0
 #define AR933X_UART_CS_PARITY_M		0x3
 #define	  AR933X_UART_CS_PARITY_NONE	0
-#define	  AR933X_UART_CS_PARITY_ODD	1
-#define	  AR933X_UART_CS_PARITY_EVEN	2
+#define	  AR933X_UART_CS_PARITY_ODD	2
+#define	  AR933X_UART_CS_PARITY_EVEN	3
 #define AR933X_UART_CS_IF_MODE_S	2
 #define AR933X_UART_CS_IF_MODE_M	0x3
 #define	  AR933X_UART_CS_IF_MODE_NONE	0
diff -druNp --no-dereference linux-libre-5.2-rc7-gnu/arch/mips/Makefile linux-libre-5.2-gnu/arch/mips/Makefile
--- linux-libre-5.2-rc7-gnu/arch/mips/Makefile	2019-06-29 23:25:36.000000000 -0400
+++ linux-libre-5.2-gnu/arch/mips/Makefile	2019-07-07 18:41:56.000000000 -0400
@@ -17,6 +17,7 @@ archscripts: scripts_basic
 	$(Q)$(MAKE) $(build)=arch/mips/boot/tools relocs
 
 KBUILD_DEFCONFIG := 32r2el_defconfig
+KBUILD_DTBS      := dtbs
 
 #
 # Select the object file format to substitute into the linker script.
@@ -384,7 +385,7 @@ quiet_cmd_64 = OBJCOPY $@
 vmlinux.64: vmlinux
 	$(call cmd,64)
 
-all:	$(all-y)
+all:	$(all-y) $(KBUILD_DTBS)
 
 # boot
 $(boot-y): $(vmlinux-32) FORCE
diff -druNp --no-dereference linux-libre-5.2-rc7-gnu/arch/mips/mm/mmap.c linux-libre-5.2-gnu/arch/mips/mm/mmap.c
--- linux-libre-5.2-rc7-gnu/arch/mips/mm/mmap.c	2019-06-29 23:25:36.000000000 -0400
+++ linux-libre-5.2-gnu/arch/mips/mm/mmap.c	2019-07-07 18:41:56.000000000 -0400
@@ -203,7 +203,7 @@ unsigned long arch_randomize_brk(struct
 
 bool __virt_addr_valid(const volatile void *kaddr)
 {
-	unsigned long vaddr = (unsigned long)vaddr;
+	unsigned long vaddr = (unsigned long)kaddr;
 
 	if ((vaddr < PAGE_OFFSET) || (vaddr >= MAP_BASE))
 		return false;
diff -druNp --no-dereference linux-libre-5.2-rc7-gnu/arch/mips/mm/tlbex.c linux-libre-5.2-gnu/arch/mips/mm/tlbex.c
--- linux-libre-5.2-rc7-gnu/arch/mips/mm/tlbex.c	2019-06-29 23:25:36.000000000 -0400
+++ linux-libre-5.2-gnu/arch/mips/mm/tlbex.c	2019-07-07 18:41:56.000000000 -0400
@@ -391,6 +391,7 @@ static struct work_registers build_get_w
 static void build_restore_work_registers(u32 **p)
 {
 	if (scratch_reg >= 0) {
+		uasm_i_ehb(p);
 		UASM_i_MFC0(p, 1, c0_kscratch(), scratch_reg);
 		return;
 	}
@@ -668,10 +669,12 @@ static void build_restore_pagemask(u32 *
 			uasm_i_mtc0(p, 0, C0_PAGEMASK);
 			uasm_il_b(p, r, lid);
 		}
-		if (scratch_reg >= 0)
+		if (scratch_reg >= 0) {
+			uasm_i_ehb(p);
 			UASM_i_MFC0(p, 1, c0_kscratch(), scratch_reg);
-		else
+		} else {
 			UASM_i_LW(p, 1, scratchpad_offset(0), 0);
+		}
 	} else {
 		/* Reset default page size */
 		if (PM_DEFAULT_MASK >> 16) {
@@ -938,10 +941,12 @@ build_get_pgd_vmalloc64(u32 **p, struct
 		uasm_i_jr(p, ptr);
 
 		if (mode == refill_scratch) {
-			if (scratch_reg >= 0)
+			if (scratch_reg >= 0) {
+				uasm_i_ehb(p);
 				UASM_i_MFC0(p, 1, c0_kscratch(), scratch_reg);
-			else
+			} else {
 				UASM_i_LW(p, 1, scratchpad_offset(0), 0);
+			}
 		} else {
 			uasm_i_nop(p);
 		}
@@ -1258,6 +1263,7 @@ build_fast_tlb_refill_handler (u32 **p,
 	UASM_i_MTC0(p, odd, C0_ENTRYLO1); /* load it */
 
 	if (c0_scratch_reg >= 0) {
+		uasm_i_ehb(p);
 		UASM_i_MFC0(p, scratch, c0_kscratch(), c0_scratch_reg);
 		build_tlb_write_entry(p, l, r, tlb_random);
 		uasm_l_leave(l, *p);
@@ -1603,15 +1609,17 @@ static void build_setup_pgd(void)
 		uasm_i_dinsm(&p, a0, 0, 29, 64 - 29);
 		uasm_l_tlbl_goaround1(&l, p);
 		UASM_i_SLL(&p, a0, a0, 11);
-		uasm_i_jr(&p, 31);
 		UASM_i_MTC0(&p, a0, C0_CONTEXT);
+		uasm_i_jr(&p, 31);
+		uasm_i_ehb(&p);
 	} else {
 		/* PGD in c0_KScratch */
-		uasm_i_jr(&p, 31);
 		if (cpu_has_ldpte)
 			UASM_i_MTC0(&p, a0, C0_PWBASE);
 		else
 			UASM_i_MTC0(&p, a0, c0_kscratch(), pgd_reg);
+		uasm_i_jr(&p, 31);
+		uasm_i_ehb(&p);
 	}
 #else
 #ifdef CONFIG_SMP
@@ -1625,13 +1633,16 @@ static void build_setup_pgd(void)
 	UASM_i_LA_mostly(&p, a2, pgdc);
 	UASM_i_SW(&p, a0, uasm_rel_lo(pgdc), a2);
 #endif /* SMP */
-	uasm_i_jr(&p, 31);
 
 	/* if pgd_reg is allocated, save PGD also to scratch register */
-	if (pgd_reg != -1)
+	if (pgd_reg != -1) {
 		UASM_i_MTC0(&p, a0, c0_kscratch(), pgd_reg);
-	else
+		uasm_i_jr(&p, 31);
+		uasm_i_ehb(&p);
+	} else {
+		uasm_i_jr(&p, 31);
 		uasm_i_nop(&p);
+	}
 #endif
 	if (p >= (u32 *)tlbmiss_handler_setup_pgd_end)
 		panic("tlbmiss_handler_setup_pgd space exceeded");
diff -druNp --no-dereference linux-libre-5.2-rc7-gnu/arch/x86/kernel/ftrace.c linux-libre-5.2-gnu/arch/x86/kernel/ftrace.c
--- linux-libre-5.2-rc7-gnu/arch/x86/kernel/ftrace.c	2019-06-29 23:25:36.000000000 -0400
+++ linux-libre-5.2-gnu/arch/x86/kernel/ftrace.c	2019-07-07 18:41:56.000000000 -0400
@@ -22,6 +22,7 @@
 #include <linux/init.h>
 #include <linux/list.h>
 #include <linux/module.h>
+#include <linux/memory.h>
 
 #include <trace/syscall.h>
 
@@ -34,16 +35,25 @@
 #ifdef CONFIG_DYNAMIC_FTRACE
 
 int ftrace_arch_code_modify_prepare(void)
+    __acquires(&text_mutex)
 {
+	/*
+	 * Need to grab text_mutex to prevent a race from module loading
+	 * and live kernel patching from changing the text permissions while
+	 * ftrace has it set to "read/write".
+	 */
+	mutex_lock(&text_mutex);
 	set_kernel_text_rw();
 	set_all_modules_text_rw();
 	return 0;
 }
 
 int ftrace_arch_code_modify_post_process(void)
+    __releases(&text_mutex)
 {
 	set_all_modules_text_ro();
 	set_kernel_text_ro();
+	mutex_unlock(&text_mutex);
 	return 0;
 }
 
diff -druNp --no-dereference linux-libre-5.2-rc7-gnu/arch/x86/kvm/lapic.c linux-libre-5.2-gnu/arch/x86/kvm/lapic.c
--- linux-libre-5.2-rc7-gnu/arch/x86/kvm/lapic.c	2019-06-29 23:25:36.000000000 -0400
+++ linux-libre-5.2-gnu/arch/x86/kvm/lapic.c	2019-07-07 18:41:56.000000000 -0400
@@ -2339,7 +2339,7 @@ int kvm_apic_has_interrupt(struct kvm_vc
 	struct kvm_lapic *apic = vcpu->arch.apic;
 	u32 ppr;
 
-	if (!apic_enabled(apic))
+	if (!kvm_apic_hw_enabled(apic))
 		return -1;
 
 	__apic_update_ppr(apic, &ppr);
diff -druNp --no-dereference linux-libre-5.2-rc7-gnu/arch/x86/kvm/vmx/nested.c linux-libre-5.2-gnu/arch/x86/kvm/vmx/nested.c
--- linux-libre-5.2-rc7-gnu/arch/x86/kvm/vmx/nested.c	2019-06-29 23:25:36.000000000 -0400
+++ linux-libre-5.2-gnu/arch/x86/kvm/vmx/nested.c	2019-07-07 18:41:56.000000000 -0400
@@ -5240,9 +5240,6 @@ static int vmx_get_nested_state(struct k
 	vmx = to_vmx(vcpu);
 	vmcs12 = get_vmcs12(vcpu);
 
-	if (nested_vmx_allowed(vcpu) && vmx->nested.enlightened_vmcs_enabled)
-		kvm_state.flags |= KVM_STATE_NESTED_EVMCS;
-
 	if (nested_vmx_allowed(vcpu) &&
 	    (vmx->nested.vmxon || vmx->nested.smm.vmxon)) {
 		kvm_state.hdr.vmx.vmxon_pa = vmx->nested.vmxon_ptr;
@@ -5251,6 +5248,9 @@ static int vmx_get_nested_state(struct k
 		if (vmx_has_valid_vmcs12(vcpu)) {
 			kvm_state.size += sizeof(user_vmx_nested_state->vmcs12);
 
+			if (vmx->nested.hv_evmcs)
+				kvm_state.flags |= KVM_STATE_NESTED_EVMCS;
+
 			if (is_guest_mode(vcpu) &&
 			    nested_cpu_has_shadow_vmcs(vmcs12) &&
 			    vmcs12->vmcs_link_pointer != -1ull)
@@ -5350,6 +5350,15 @@ static int vmx_set_nested_state(struct k
 		if (kvm_state->hdr.vmx.vmcs12_pa != -1ull)
 			return -EINVAL;
 
+		/*
+		 * KVM_STATE_NESTED_EVMCS used to signal that KVM should
+		 * enable eVMCS capability on vCPU. However, since then
+		 * code was changed such that flag signals vmcs12 should
+		 * be copied into eVMCS in guest memory.
+		 *
+		 * To preserve backwards compatability, allow user
+		 * to set this flag even when there is no VMXON region.
+		 */
 		if (kvm_state->flags & ~KVM_STATE_NESTED_EVMCS)
 			return -EINVAL;
 	} else {
@@ -5358,7 +5367,7 @@ static int vmx_set_nested_state(struct k
 
 		if (!page_address_valid(vcpu, kvm_state->hdr.vmx.vmxon_pa))
 			return -EINVAL;
-    	}
+	}
 
 	if ((kvm_state->hdr.vmx.smm.flags & KVM_STATE_NESTED_SMM_GUEST_MODE) &&
 	    (kvm_state->flags & KVM_STATE_NESTED_GUEST_MODE))
@@ -5373,20 +5382,21 @@ static int vmx_set_nested_state(struct k
 	 * nor can VMLAUNCH/VMRESUME be pending.  Outside SMM, SMM flags
 	 * must be zero.
 	 */
-	if (is_smm(vcpu) ? kvm_state->flags : kvm_state->hdr.vmx.smm.flags)
+	if (is_smm(vcpu) ?
+		(kvm_state->flags &
+		 (KVM_STATE_NESTED_GUEST_MODE | KVM_STATE_NESTED_RUN_PENDING))
+		: kvm_state->hdr.vmx.smm.flags)
 		return -EINVAL;
 
 	if ((kvm_state->hdr.vmx.smm.flags & KVM_STATE_NESTED_SMM_GUEST_MODE) &&
 	    !(kvm_state->hdr.vmx.smm.flags & KVM_STATE_NESTED_SMM_VMXON))
 		return -EINVAL;
 
-	vmx_leave_nested(vcpu);
-	if (kvm_state->flags & KVM_STATE_NESTED_EVMCS) {
-		if (!nested_vmx_allowed(vcpu))
+	if ((kvm_state->flags & KVM_STATE_NESTED_EVMCS) &&
+		(!nested_vmx_allowed(vcpu) || !vmx->nested.enlightened_vmcs_enabled))
 			return -EINVAL;
 
-		nested_enable_evmcs(vcpu, NULL);
-	}
+	vmx_leave_nested(vcpu);
 
 	if (kvm_state->hdr.vmx.vmxon_pa == -1ull)
 		return 0;
diff -druNp --no-dereference linux-libre-5.2-rc7-gnu/arch/x86/kvm/x86.c linux-libre-5.2-gnu/arch/x86/kvm/x86.c
--- linux-libre-5.2-rc7-gnu/arch/x86/kvm/x86.c	2019-06-29 23:25:36.000000000 -0400
+++ linux-libre-5.2-gnu/arch/x86/kvm/x86.c	2019-07-07 18:41:56.000000000 -0400
@@ -1554,7 +1554,7 @@ static int set_tsc_khz(struct kvm_vcpu *
 			vcpu->arch.tsc_always_catchup = 1;
 			return 0;
 		} else {
-			WARN(1, "user requested TSC rate below hardware speed\n");
+			pr_warn_ratelimited("user requested TSC rate below hardware speed\n");
 			return -1;
 		}
 	}
@@ -1564,8 +1564,8 @@ static int set_tsc_khz(struct kvm_vcpu *
 				user_tsc_khz, tsc_khz);
 
 	if (ratio == 0 || ratio >= kvm_max_tsc_scaling_ratio) {
-		WARN_ONCE(1, "Invalid TSC scaling ratio - virtual-tsc-khz=%u\n",
-			  user_tsc_khz);
+		pr_warn_ratelimited("Invalid TSC scaling ratio - virtual-tsc-khz=%u\n",
+			            user_tsc_khz);
 		return -1;
 	}
 
diff -druNp --no-dereference linux-libre-5.2-rc7-gnu/block/blk-mq-debugfs.c linux-libre-5.2-gnu/block/blk-mq-debugfs.c
--- linux-libre-5.2-rc7-gnu/block/blk-mq-debugfs.c	2019-06-29 23:25:36.000000000 -0400
+++ linux-libre-5.2-gnu/block/blk-mq-debugfs.c	2019-07-07 18:41:56.000000000 -0400
@@ -934,6 +934,13 @@ void blk_mq_debugfs_register_sched(struc
 {
 	struct elevator_type *e = q->elevator->type;
 
+	/*
+	 * If the parent directory has not been created yet, return, we will be
+	 * called again later on and the directory/files will be created then.
+	 */
+	if (!q->debugfs_dir)
+		return;
+
 	if (!e->queue_debugfs_attrs)
 		return;
 
diff -druNp --no-dereference linux-libre-5.2-rc7-gnu/crypto/cryptd.c linux-libre-5.2-gnu/crypto/cryptd.c
--- linux-libre-5.2-rc7-gnu/crypto/cryptd.c	2019-06-29 23:25:36.000000000 -0400
+++ linux-libre-5.2-gnu/crypto/cryptd.c	2019-07-07 18:41:56.000000000 -0400
@@ -388,6 +388,7 @@ static void cryptd_skcipher_free(struct
 	struct skcipherd_instance_ctx *ctx = skcipher_instance_ctx(inst);
 
 	crypto_drop_skcipher(&ctx->spawn);
+	kfree(inst);
 }
 
 static int cryptd_create_skcipher(struct crypto_template *tmpl,
diff -druNp --no-dereference linux-libre-5.2-rc7-gnu/crypto/crypto_user_base.c linux-libre-5.2-gnu/crypto/crypto_user_base.c
--- linux-libre-5.2-rc7-gnu/crypto/crypto_user_base.c	2019-06-29 23:25:36.000000000 -0400
+++ linux-libre-5.2-gnu/crypto/crypto_user_base.c	2019-07-07 18:41:56.000000000 -0400
@@ -44,6 +44,9 @@ struct crypto_alg *crypto_alg_match(stru
 	list_for_each_entry(q, &crypto_alg_list, cra_list) {
 		int match = 0;
 
+		if (crypto_is_larval(q))
+			continue;
+
 		if ((q->cra_flags ^ p->cru_type) & p->cru_mask)
 			continue;
 
diff -druNp --no-dereference linux-libre-5.2-rc7-gnu/drivers/dma/dma-jz4780.c linux-libre-5.2-gnu/drivers/dma/dma-jz4780.c
--- linux-libre-5.2-rc7-gnu/drivers/dma/dma-jz4780.c	2019-06-29 23:25:36.000000000 -0400
+++ linux-libre-5.2-gnu/drivers/dma/dma-jz4780.c	2019-07-07 18:41:56.000000000 -0400
@@ -718,12 +718,13 @@ static irqreturn_t jz4780_dma_irq_handle
 {
 	struct jz4780_dma_dev *jzdma = data;
 	unsigned int nb_channels = jzdma->soc_data->nb_channels;
-	uint32_t pending, dmac;
+	unsigned long pending;
+	uint32_t dmac;
 	int i;
 
 	pending = jz4780_dma_ctrl_readl(jzdma, JZ_DMA_REG_DIRQP);
 
-	for_each_set_bit(i, (unsigned long *)&pending, nb_channels) {
+	for_each_set_bit(i, &pending, nb_channels) {
 		if (jz4780_dma_chan_irq(jzdma, &jzdma->chan[i]))
 			pending &= ~BIT(i);
 	}
diff -druNp --no-dereference linux-libre-5.2-rc7-gnu/drivers/dma/imx-sdma.c linux-libre-5.2-gnu/drivers/dma/imx-sdma.c
--- linux-libre-5.2-rc7-gnu/drivers/dma/imx-sdma.c	2019-07-02 02:04:16.000000000 -0400
+++ linux-libre-5.2-gnu/drivers/dma/imx-sdma.c	2019-07-07 20:43:18.000000000 -0400
@@ -703,7 +703,7 @@ static int sdma_load_script(struct sdma_
 	spin_lock_irqsave(&sdma->channel_0_lock, flags);
 
 	bd0->mode.command = C0_SETPM;
-	bd0->mode.status = BD_DONE | BD_INTR | BD_WRAP | BD_EXTD;
+	bd0->mode.status = BD_DONE | BD_WRAP | BD_EXTD;
 	bd0->mode.count = size / 2;
 	bd0->buffer_addr = buf_phys;
 	bd0->ext_buffer_addr = address;
@@ -1025,7 +1025,7 @@ static int sdma_load_context(struct sdma
 	context->gReg[7] = sdmac->watermark_level;
 
 	bd0->mode.command = C0_SETDM;
-	bd0->mode.status = BD_DONE | BD_INTR | BD_WRAP | BD_EXTD;
+	bd0->mode.status = BD_DONE | BD_WRAP | BD_EXTD;
 	bd0->mode.count = sizeof(*context) / 4;
 	bd0->buffer_addr = sdma->context_phys;
 	bd0->ext_buffer_addr = 2048 + (sizeof(*context) / 4) * channel;
@@ -2096,27 +2096,6 @@ static int sdma_probe(struct platform_de
 	if (pdata && pdata->script_addrs)
 		sdma_add_scripts(sdma, pdata->script_addrs);
 
-	if (pdata) {
-		ret = sdma_get_firmware(sdma, pdata->fw_name);
-		if (ret)
-			dev_warn(&pdev->dev, "failed to get firmware from platform data\n");
-	} else {
-		/*
-		 * Because that device tree does not encode ROM script address,
-		 * the RAM script in firmware is mandatory for device tree
-		 * probe, otherwise it fails.
-		 */
-		ret = of_property_read_string(np, "fsl,sdma-ram-script-name",
-					      &fw_name);
-		if (ret)
-			dev_warn(&pdev->dev, "failed to get firmware name\n");
-		else {
-			ret = sdma_get_firmware(sdma, fw_name);
-			if (ret)
-				dev_warn(&pdev->dev, "failed to get firmware from device tree\n");
-		}
-	}
-
 	sdma->dma_device.dev = &pdev->dev;
 
 	sdma->dma_device.device_alloc_chan_resources = sdma_alloc_chan_resources;
@@ -2161,6 +2140,33 @@ static int sdma_probe(struct platform_de
 		of_node_put(spba_bus);
 	}
 
+	/*
+	 * Kick off firmware loading as the very last step:
+	 * attempt to load firmware only if we're not on the error path, because
+	 * the firmware callback requires a fully functional and allocated sdma
+	 * instance.
+	 */
+	if (pdata) {
+		ret = sdma_get_firmware(sdma, pdata->fw_name);
+		if (ret)
+			dev_warn(&pdev->dev, "failed to get firmware from platform data\n");
+	} else {
+		/*
+		 * Because that device tree does not encode ROM script address,
+		 * the RAM script in firmware is mandatory for device tree
+		 * probe, otherwise it fails.
+		 */
+		ret = of_property_read_string(np, "fsl,sdma-ram-script-name",
+					      &fw_name);
+		if (ret) {
+			dev_warn(&pdev->dev, "failed to get firmware name\n");
+		} else {
+			ret = sdma_get_firmware(sdma, fw_name);
+			if (ret)
+				dev_warn(&pdev->dev, "failed to get firmware from device tree\n");
+		}
+	}
+
 	return 0;
 
 err_register:
diff -druNp --no-dereference linux-libre-5.2-rc7-gnu/drivers/dma/qcom/bam_dma.c linux-libre-5.2-gnu/drivers/dma/qcom/bam_dma.c
--- linux-libre-5.2-rc7-gnu/drivers/dma/qcom/bam_dma.c	2019-06-29 23:25:36.000000000 -0400
+++ linux-libre-5.2-gnu/drivers/dma/qcom/bam_dma.c	2019-07-07 18:41:56.000000000 -0400
@@ -799,6 +799,9 @@ static u32 process_channel_irqs(struct b
 		/* Number of bytes available to read */
 		avail = CIRC_CNT(offset, bchan->head, MAX_DESCRIPTORS + 1);
 
+		if (offset < bchan->head)
+			avail--;
+
 		list_for_each_entry_safe(async_desc, tmp,
 					 &bchan->desc_list, desc_node) {
 			/* Not enough data to read */
diff -druNp --no-dereference linux-libre-5.2-rc7-gnu/drivers/gpio/gpiolib-of.c linux-libre-5.2-gnu/drivers/gpio/gpiolib-of.c
--- linux-libre-5.2-rc7-gnu/drivers/gpio/gpiolib-of.c	2019-06-29 23:25:36.000000000 -0400
+++ linux-libre-5.2-gnu/drivers/gpio/gpiolib-of.c	2019-07-07 18:41:56.000000000 -0400
@@ -118,8 +118,15 @@ static void of_gpio_flags_quirks(struct
 	 * Legacy handling of SPI active high chip select. If we have a
 	 * property named "cs-gpios" we need to inspect the child node
 	 * to determine if the flags should have inverted semantics.
+	 *
+	 * This does not apply to an SPI device named "spi-gpio", because
+	 * these have traditionally obtained their own GPIOs by parsing
+	 * the device tree directly and did not respect any "spi-cs-high"
+	 * property on the SPI bus children.
 	 */
-	if (IS_ENABLED(CONFIG_SPI_MASTER) && !strcmp(propname, "cs-gpios") &&
+	if (IS_ENABLED(CONFIG_SPI_MASTER) &&
+	    !strcmp(propname, "cs-gpios") &&
+	    !of_device_is_compatible(np, "spi-gpio") &&
 	    of_property_read_bool(np, "cs-gpios")) {
 		struct device_node *child;
 		u32 cs;
diff -druNp --no-dereference linux-libre-5.2-rc7-gnu/drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c linux-libre-5.2-gnu/drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c
--- linux-libre-5.2-rc7-gnu/drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c	2019-07-02 02:01:17.000000000 -0400
+++ linux-libre-5.2-gnu/drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c	2019-07-07 20:40:23.000000000 -0400
@@ -1917,25 +1917,6 @@ static void gfx_v9_0_constants_init(stru
 	mutex_unlock(&adev->srbm_mutex);
 
 	gfx_v9_0_init_compute_vmid(adev);
-
-	mutex_lock(&adev->grbm_idx_mutex);
-	/*
-	 * making sure that the following register writes will be broadcasted
-	 * to all the shaders
-	 */
-	gfx_v9_0_select_se_sh(adev, 0xffffffff, 0xffffffff, 0xffffffff);
-
-	WREG32_SOC15(GC, 0, mmPA_SC_FIFO_SIZE,
-		   (adev->gfx.config.sc_prim_fifo_size_frontend <<
-			PA_SC_FIFO_SIZE__SC_FRONTEND_PRIM_FIFO_SIZE__SHIFT) |
-		   (adev->gfx.config.sc_prim_fifo_size_backend <<
-			PA_SC_FIFO_SIZE__SC_BACKEND_PRIM_FIFO_SIZE__SHIFT) |
-		   (adev->gfx.config.sc_hiz_tile_fifo_size <<
-			PA_SC_FIFO_SIZE__SC_HIZ_TILE_FIFO_SIZE__SHIFT) |
-		   (adev->gfx.config.sc_earlyz_tile_fifo_size <<
-			PA_SC_FIFO_SIZE__SC_EARLYZ_TILE_FIFO_SIZE__SHIFT));
-	mutex_unlock(&adev->grbm_idx_mutex);
-
 }
 
 static void gfx_v9_0_wait_for_rlc_serdes(struct amdgpu_device *adev)
diff -druNp --no-dereference linux-libre-5.2-rc7-gnu/drivers/gpu/drm/amd/powerplay/hwmgr/hwmgr.c linux-libre-5.2-gnu/drivers/gpu/drm/amd/powerplay/hwmgr/hwmgr.c
--- linux-libre-5.2-rc7-gnu/drivers/gpu/drm/amd/powerplay/hwmgr/hwmgr.c	2019-06-29 23:25:36.000000000 -0400
+++ linux-libre-5.2-gnu/drivers/gpu/drm/amd/powerplay/hwmgr/hwmgr.c	2019-07-07 18:41:56.000000000 -0400
@@ -326,7 +326,7 @@ int hwmgr_resume(struct pp_hwmgr *hwmgr)
 	if (ret)
 		return ret;
 
-	ret = psm_adjust_power_state_dynamic(hwmgr, true, NULL);
+	ret = psm_adjust_power_state_dynamic(hwmgr, false, NULL);
 
 	return ret;
 }
diff -druNp --no-dereference linux-libre-5.2-rc7-gnu/drivers/gpu/drm/amd/powerplay/hwmgr/process_pptables_v1_0.c linux-libre-5.2-gnu/drivers/gpu/drm/amd/powerplay/hwmgr/process_pptables_v1_0.c
--- linux-libre-5.2-rc7-gnu/drivers/gpu/drm/amd/powerplay/hwmgr/process_pptables_v1_0.c	2019-06-29 23:25:36.000000000 -0400
+++ linux-libre-5.2-gnu/drivers/gpu/drm/amd/powerplay/hwmgr/process_pptables_v1_0.c	2019-07-07 18:41:56.000000000 -0400
@@ -916,8 +916,10 @@ static int init_thermal_controller(
 			PHM_PlatformCaps_ThermalController
 		  );
 
-	if (0 == powerplay_table->usFanTableOffset)
+	if (0 == powerplay_table->usFanTableOffset) {
+		hwmgr->thermal_controller.use_hw_fan_control = 1;
 		return 0;
+	}
 
 	fan_table = (const PPTable_Generic_SubTable_Header *)
 		(((unsigned long)powerplay_table) +
diff -druNp --no-dereference linux-libre-5.2-rc7-gnu/drivers/gpu/drm/amd/powerplay/inc/hwmgr.h linux-libre-5.2-gnu/drivers/gpu/drm/amd/powerplay/inc/hwmgr.h
--- linux-libre-5.2-rc7-gnu/drivers/gpu/drm/amd/powerplay/inc/hwmgr.h	2019-06-29 23:25:36.000000000 -0400
+++ linux-libre-5.2-gnu/drivers/gpu/drm/amd/powerplay/inc/hwmgr.h	2019-07-07 18:41:56.000000000 -0400
@@ -694,6 +694,7 @@ struct pp_thermal_controller_info {
 	uint8_t ucType;
 	uint8_t ucI2cLine;
 	uint8_t ucI2cAddress;
+	uint8_t use_hw_fan_control;
 	struct pp_fan_info fanInfo;
 	struct pp_advance_fan_control_parameters advanceFanControlParameters;
 };
diff -druNp --no-dereference linux-libre-5.2-rc7-gnu/drivers/gpu/drm/amd/powerplay/smumgr/polaris10_smumgr.c linux-libre-5.2-gnu/drivers/gpu/drm/amd/powerplay/smumgr/polaris10_smumgr.c
--- linux-libre-5.2-rc7-gnu/drivers/gpu/drm/amd/powerplay/smumgr/polaris10_smumgr.c	2019-06-29 23:25:36.000000000 -0400
+++ linux-libre-5.2-gnu/drivers/gpu/drm/amd/powerplay/smumgr/polaris10_smumgr.c	2019-07-07 18:41:56.000000000 -0400
@@ -2092,6 +2092,10 @@ static int polaris10_thermal_setup_fan_t
 		return 0;
 	}
 
+	/* use hardware fan control */
+	if (hwmgr->thermal_controller.use_hw_fan_control)
+		return 0;
+
 	tmp64 = hwmgr->thermal_controller.advanceFanControlParameters.
 			usPWMMin * duty100;
 	do_div(tmp64, 10000);
diff -druNp --no-dereference linux-libre-5.2-rc7-gnu/drivers/gpu/drm/etnaviv/etnaviv_gpu.c linux-libre-5.2-gnu/drivers/gpu/drm/etnaviv/etnaviv_gpu.c
--- linux-libre-5.2-rc7-gnu/drivers/gpu/drm/etnaviv/etnaviv_gpu.c	2019-06-29 23:25:36.000000000 -0400
+++ linux-libre-5.2-gnu/drivers/gpu/drm/etnaviv/etnaviv_gpu.c	2019-07-07 18:41:56.000000000 -0400
@@ -760,7 +760,7 @@ int etnaviv_gpu_init(struct etnaviv_gpu
 	if (IS_ERR(gpu->cmdbuf_suballoc)) {
 		dev_err(gpu->dev, "Failed to create cmdbuf suballocator\n");
 		ret = PTR_ERR(gpu->cmdbuf_suballoc);
-		goto fail;
+		goto destroy_iommu;
 	}
 
 	/* Create buffer: */
@@ -768,7 +768,7 @@ int etnaviv_gpu_init(struct etnaviv_gpu
 				  PAGE_SIZE);
 	if (ret) {
 		dev_err(gpu->dev, "could not create command buffer\n");
-		goto destroy_iommu;
+		goto destroy_suballoc;
 	}
 
 	if (gpu->mmu->version == ETNAVIV_IOMMU_V1 &&
@@ -800,6 +800,9 @@ int etnaviv_gpu_init(struct etnaviv_gpu
 free_buffer:
 	etnaviv_cmdbuf_free(&gpu->buffer);
 	gpu->buffer.suballoc = NULL;
+destroy_suballoc:
+	etnaviv_cmdbuf_suballoc_destroy(gpu->cmdbuf_suballoc);
+	gpu->cmdbuf_suballoc = NULL;
 destroy_iommu:
 	etnaviv_iommu_destroy(gpu->mmu);
 	gpu->mmu = NULL;
diff -druNp --no-dereference linux-libre-5.2-rc7-gnu/drivers/gpu/drm/i915/intel_ringbuffer.c linux-libre-5.2-gnu/drivers/gpu/drm/i915/intel_ringbuffer.c
--- linux-libre-5.2-rc7-gnu/drivers/gpu/drm/i915/intel_ringbuffer.c	2019-06-29 23:25:36.000000000 -0400
+++ linux-libre-5.2-gnu/drivers/gpu/drm/i915/intel_ringbuffer.c	2019-07-07 18:41:56.000000000 -0400
@@ -1888,12 +1888,12 @@ static int ring_request_alloc(struct i91
 	 */
 	request->reserved_space += LEGACY_REQUEST_SIZE;
 
-	ret = switch_context(request);
+	/* Unconditionally invalidate GPU caches and TLBs. */
+	ret = request->engine->emit_flush(request, EMIT_INVALIDATE);
 	if (ret)
 		return ret;
 
-	/* Unconditionally invalidate GPU caches and TLBs. */
-	ret = request->engine->emit_flush(request, EMIT_INVALIDATE);
+	ret = switch_context(request);
 	if (ret)
 		return ret;
 
diff -druNp --no-dereference linux-libre-5.2-rc7-gnu/drivers/gpu/drm/imx/ipuv3-crtc.c linux-libre-5.2-gnu/drivers/gpu/drm/imx/ipuv3-crtc.c
--- linux-libre-5.2-rc7-gnu/drivers/gpu/drm/imx/ipuv3-crtc.c	2019-06-29 23:25:36.000000000 -0400
+++ linux-libre-5.2-gnu/drivers/gpu/drm/imx/ipuv3-crtc.c	2019-07-07 18:41:56.000000000 -0400
@@ -91,14 +91,14 @@ static void ipu_crtc_atomic_disable(stru
 	ipu_dc_disable(ipu);
 	ipu_prg_disable(ipu);
 
+	drm_crtc_vblank_off(crtc);
+
 	spin_lock_irq(&crtc->dev->event_lock);
-	if (crtc->state->event) {
+	if (crtc->state->event && !crtc->state->active) {
 		drm_crtc_send_vblank_event(crtc, crtc->state->event);
 		crtc->state->event = NULL;
 	}
 	spin_unlock_irq(&crtc->dev->event_lock);
-
-	drm_crtc_vblank_off(crtc);
 }
 
 static void imx_drm_crtc_reset(struct drm_crtc *crtc)
diff -druNp --no-dereference linux-libre-5.2-rc7-gnu/drivers/gpu/drm/panfrost/panfrost_drv.c linux-libre-5.2-gnu/drivers/gpu/drm/panfrost/panfrost_drv.c
--- linux-libre-5.2-rc7-gnu/drivers/gpu/drm/panfrost/panfrost_drv.c	2019-06-29 23:25:36.000000000 -0400
+++ linux-libre-5.2-gnu/drivers/gpu/drm/panfrost/panfrost_drv.c	2019-07-07 18:41:56.000000000 -0400
@@ -63,7 +63,7 @@ static int panfrost_ioctl_create_bo(stru
 	return 0;
 
 err_free:
-	drm_gem_object_put_unlocked(&shmem->base);
+	drm_gem_handle_delete(file, args->handle);
 	return ret;
 }
 
diff -druNp --no-dereference linux-libre-5.2-rc7-gnu/drivers/gpu/drm/virtio/virtgpu_vq.c linux-libre-5.2-gnu/drivers/gpu/drm/virtio/virtgpu_vq.c
--- linux-libre-5.2-rc7-gnu/drivers/gpu/drm/virtio/virtgpu_vq.c	2019-06-29 23:25:36.000000000 -0400
+++ linux-libre-5.2-gnu/drivers/gpu/drm/virtio/virtgpu_vq.c	2019-07-07 18:41:56.000000000 -0400
@@ -619,11 +619,11 @@ static void virtio_gpu_cmd_get_edid_cb(s
 	output = vgdev->outputs + scanout;
 
 	new_edid = drm_do_get_edid(&output->conn, virtio_get_edid_block, resp);
+	drm_connector_update_edid_property(&output->conn, new_edid);
 
 	spin_lock(&vgdev->display_info_lock);
 	old_edid = output->edid;
 	output->edid = new_edid;
-	drm_connector_update_edid_property(&output->conn, output->edid);
 	spin_unlock(&vgdev->display_info_lock);
 
 	kfree(old_edid);
diff -druNp --no-dereference linux-libre-5.2-rc7-gnu/drivers/mtd/nand/raw/ingenic/ingenic_ecc.c linux-libre-5.2-gnu/drivers/mtd/nand/raw/ingenic/ingenic_ecc.c
--- linux-libre-5.2-rc7-gnu/drivers/mtd/nand/raw/ingenic/ingenic_ecc.c	2019-06-29 23:25:36.000000000 -0400
+++ linux-libre-5.2-gnu/drivers/mtd/nand/raw/ingenic/ingenic_ecc.c	2019-07-07 18:41:56.000000000 -0400
@@ -30,7 +30,6 @@ int ingenic_ecc_calculate(struct ingenic
 {
 	return ecc->ops->calculate(ecc, params, buf, ecc_code);
 }
-EXPORT_SYMBOL(ingenic_ecc_calculate);
 
 /**
  * ingenic_ecc_correct() - detect and correct bit errors
@@ -51,7 +50,6 @@ int ingenic_ecc_correct(struct ingenic_e
 {
 	return ecc->ops->correct(ecc, params, buf, ecc_code);
 }
-EXPORT_SYMBOL(ingenic_ecc_correct);
 
 /**
  * ingenic_ecc_get() - get the ECC controller device
@@ -111,7 +109,6 @@ struct ingenic_ecc *of_ingenic_ecc_get(s
 	}
 	return ecc;
 }
-EXPORT_SYMBOL(of_ingenic_ecc_get);
 
 /**
  * ingenic_ecc_release() - release the ECC controller device
@@ -122,7 +119,6 @@ void ingenic_ecc_release(struct ingenic_
 	clk_disable_unprepare(ecc->clk);
 	put_device(ecc->dev);
 }
-EXPORT_SYMBOL(ingenic_ecc_release);
 
 int ingenic_ecc_probe(struct platform_device *pdev)
 {
@@ -159,8 +155,3 @@ int ingenic_ecc_probe(struct platform_de
 	return 0;
 }
 EXPORT_SYMBOL(ingenic_ecc_probe);
-
-MODULE_AUTHOR("Alex Smith <alex@alex-smith.me.uk>");
-MODULE_AUTHOR("Harvey Hunt <harveyhuntnexus@gmail.com>");
-MODULE_DESCRIPTION("Ingenic ECC common driver");
-MODULE_LICENSE("GPL v2");
diff -druNp --no-dereference linux-libre-5.2-rc7-gnu/drivers/mtd/nand/raw/ingenic/ingenic_nand.c linux-libre-5.2-gnu/drivers/mtd/nand/raw/ingenic/ingenic_nand.c
--- linux-libre-5.2-rc7-gnu/drivers/mtd/nand/raw/ingenic/ingenic_nand.c	2019-06-29 23:25:36.000000000 -0400
+++ linux-libre-5.2-gnu/drivers/mtd/nand/raw/ingenic/ingenic_nand.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,530 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/*
- * Ingenic JZ47xx NAND driver
- *
- * Copyright (c) 2015 Imagination Technologies
- * Author: Alex Smith <alex.smith@imgtec.com>
- */
-
-#include <linux/delay.h>
-#include <linux/init.h>
-#include <linux/io.h>
-#include <linux/list.h>
-#include <linux/module.h>
-#include <linux/of.h>
-#include <linux/of_address.h>
-#include <linux/of_device.h>
-#include <linux/gpio/consumer.h>
-#include <linux/platform_device.h>
-#include <linux/slab.h>
-#include <linux/mtd/mtd.h>
-#include <linux/mtd/rawnand.h>
-#include <linux/mtd/partitions.h>
-
-#include <linux/jz4780-nemc.h>
-
-#include "ingenic_ecc.h"
-
-#define DRV_NAME	"ingenic-nand"
-
-/* Command delay when there is no R/B pin. */
-#define RB_DELAY_US	100
-
-struct jz_soc_info {
-	unsigned long data_offset;
-	unsigned long addr_offset;
-	unsigned long cmd_offset;
-	const struct mtd_ooblayout_ops *oob_layout;
-};
-
-struct ingenic_nand_cs {
-	unsigned int bank;
-	void __iomem *base;
-};
-
-struct ingenic_nfc {
-	struct device *dev;
-	struct ingenic_ecc *ecc;
-	const struct jz_soc_info *soc_info;
-	struct nand_controller controller;
-	unsigned int num_banks;
-	struct list_head chips;
-	int selected;
-	struct ingenic_nand_cs cs[];
-};
-
-struct ingenic_nand {
-	struct nand_chip chip;
-	struct list_head chip_list;
-
-	struct gpio_desc *busy_gpio;
-	struct gpio_desc *wp_gpio;
-	unsigned int reading: 1;
-};
-
-static inline struct ingenic_nand *to_ingenic_nand(struct mtd_info *mtd)
-{
-	return container_of(mtd_to_nand(mtd), struct ingenic_nand, chip);
-}
-
-static inline struct ingenic_nfc *to_ingenic_nfc(struct nand_controller *ctrl)
-{
-	return container_of(ctrl, struct ingenic_nfc, controller);
-}
-
-static int qi_lb60_ooblayout_ecc(struct mtd_info *mtd, int section,
-				 struct mtd_oob_region *oobregion)
-{
-	struct nand_chip *chip = mtd_to_nand(mtd);
-	struct nand_ecc_ctrl *ecc = &chip->ecc;
-
-	if (section || !ecc->total)
-		return -ERANGE;
-
-	oobregion->length = ecc->total;
-	oobregion->offset = 12;
-
-	return 0;
-}
-
-static int qi_lb60_ooblayout_free(struct mtd_info *mtd, int section,
-				  struct mtd_oob_region *oobregion)
-{
-	struct nand_chip *chip = mtd_to_nand(mtd);
-	struct nand_ecc_ctrl *ecc = &chip->ecc;
-
-	if (section)
-		return -ERANGE;
-
-	oobregion->length = mtd->oobsize - ecc->total - 12;
-	oobregion->offset = 12 + ecc->total;
-
-	return 0;
-}
-
-const struct mtd_ooblayout_ops qi_lb60_ooblayout_ops = {
-	.ecc = qi_lb60_ooblayout_ecc,
-	.free = qi_lb60_ooblayout_free,
-};
-
-static int jz4725b_ooblayout_ecc(struct mtd_info *mtd, int section,
-				 struct mtd_oob_region *oobregion)
-{
-	struct nand_chip *chip = mtd_to_nand(mtd);
-	struct nand_ecc_ctrl *ecc = &chip->ecc;
-
-	if (section || !ecc->total)
-		return -ERANGE;
-
-	oobregion->length = ecc->total;
-	oobregion->offset = 3;
-
-	return 0;
-}
-
-static int jz4725b_ooblayout_free(struct mtd_info *mtd, int section,
-				  struct mtd_oob_region *oobregion)
-{
-	struct nand_chip *chip = mtd_to_nand(mtd);
-	struct nand_ecc_ctrl *ecc = &chip->ecc;
-
-	if (section)
-		return -ERANGE;
-
-	oobregion->length = mtd->oobsize - ecc->total - 3;
-	oobregion->offset = 3 + ecc->total;
-
-	return 0;
-}
-
-static const struct mtd_ooblayout_ops jz4725b_ooblayout_ops = {
-	.ecc = jz4725b_ooblayout_ecc,
-	.free = jz4725b_ooblayout_free,
-};
-
-static void ingenic_nand_select_chip(struct nand_chip *chip, int chipnr)
-{
-	struct ingenic_nand *nand = to_ingenic_nand(nand_to_mtd(chip));
-	struct ingenic_nfc *nfc = to_ingenic_nfc(nand->chip.controller);
-	struct ingenic_nand_cs *cs;
-
-	/* Ensure the currently selected chip is deasserted. */
-	if (chipnr == -1 && nfc->selected >= 0) {
-		cs = &nfc->cs[nfc->selected];
-		jz4780_nemc_assert(nfc->dev, cs->bank, false);
-	}
-
-	nfc->selected = chipnr;
-}
-
-static void ingenic_nand_cmd_ctrl(struct nand_chip *chip, int cmd,
-				  unsigned int ctrl)
-{
-	struct ingenic_nand *nand = to_ingenic_nand(nand_to_mtd(chip));
-	struct ingenic_nfc *nfc = to_ingenic_nfc(nand->chip.controller);
-	struct ingenic_nand_cs *cs;
-
-	if (WARN_ON(nfc->selected < 0))
-		return;
-
-	cs = &nfc->cs[nfc->selected];
-
-	jz4780_nemc_assert(nfc->dev, cs->bank, ctrl & NAND_NCE);
-
-	if (cmd == NAND_CMD_NONE)
-		return;
-
-	if (ctrl & NAND_ALE)
-		writeb(cmd, cs->base + nfc->soc_info->addr_offset);
-	else if (ctrl & NAND_CLE)
-		writeb(cmd, cs->base + nfc->soc_info->cmd_offset);
-}
-
-static int ingenic_nand_dev_ready(struct nand_chip *chip)
-{
-	struct ingenic_nand *nand = to_ingenic_nand(nand_to_mtd(chip));
-
-	return !gpiod_get_value_cansleep(nand->busy_gpio);
-}
-
-static void ingenic_nand_ecc_hwctl(struct nand_chip *chip, int mode)
-{
-	struct ingenic_nand *nand = to_ingenic_nand(nand_to_mtd(chip));
-
-	nand->reading = (mode == NAND_ECC_READ);
-}
-
-static int ingenic_nand_ecc_calculate(struct nand_chip *chip, const u8 *dat,
-				      u8 *ecc_code)
-{
-	struct ingenic_nand *nand = to_ingenic_nand(nand_to_mtd(chip));
-	struct ingenic_nfc *nfc = to_ingenic_nfc(nand->chip.controller);
-	struct ingenic_ecc_params params;
-
-	/*
-	 * Don't need to generate the ECC when reading, the ECC engine does it
-	 * for us as part of decoding/correction.
-	 */
-	if (nand->reading)
-		return 0;
-
-	params.size = nand->chip.ecc.size;
-	params.bytes = nand->chip.ecc.bytes;
-	params.strength = nand->chip.ecc.strength;
-
-	return ingenic_ecc_calculate(nfc->ecc, &params, dat, ecc_code);
-}
-
-static int ingenic_nand_ecc_correct(struct nand_chip *chip, u8 *dat,
-				    u8 *read_ecc, u8 *calc_ecc)
-{
-	struct ingenic_nand *nand = to_ingenic_nand(nand_to_mtd(chip));
-	struct ingenic_nfc *nfc = to_ingenic_nfc(nand->chip.controller);
-	struct ingenic_ecc_params params;
-
-	params.size = nand->chip.ecc.size;
-	params.bytes = nand->chip.ecc.bytes;
-	params.strength = nand->chip.ecc.strength;
-
-	return ingenic_ecc_correct(nfc->ecc, &params, dat, read_ecc);
-}
-
-static int ingenic_nand_attach_chip(struct nand_chip *chip)
-{
-	struct mtd_info *mtd = nand_to_mtd(chip);
-	struct ingenic_nfc *nfc = to_ingenic_nfc(chip->controller);
-	int eccbytes;
-
-	if (chip->ecc.strength == 4) {
-		/* JZ4740 uses 9 bytes of ECC to correct maximum 4 errors */
-		chip->ecc.bytes = 9;
-	} else {
-		chip->ecc.bytes = fls((1 + 8) * chip->ecc.size)	*
-				  (chip->ecc.strength / 8);
-	}
-
-	switch (chip->ecc.mode) {
-	case NAND_ECC_HW:
-		if (!nfc->ecc) {
-			dev_err(nfc->dev, "HW ECC selected, but ECC controller not found\n");
-			return -ENODEV;
-		}
-
-		chip->ecc.hwctl = ingenic_nand_ecc_hwctl;
-		chip->ecc.calculate = ingenic_nand_ecc_calculate;
-		chip->ecc.correct = ingenic_nand_ecc_correct;
-		/* fall through */
-	case NAND_ECC_SOFT:
-		dev_info(nfc->dev, "using %s (strength %d, size %d, bytes %d)\n",
-			 (nfc->ecc) ? "hardware ECC" : "software ECC",
-			 chip->ecc.strength, chip->ecc.size, chip->ecc.bytes);
-		break;
-	case NAND_ECC_NONE:
-		dev_info(nfc->dev, "not using ECC\n");
-		break;
-	default:
-		dev_err(nfc->dev, "ECC mode %d not supported\n",
-			chip->ecc.mode);
-		return -EINVAL;
-	}
-
-	/* The NAND core will generate the ECC layout for SW ECC */
-	if (chip->ecc.mode != NAND_ECC_HW)
-		return 0;
-
-	/* Generate ECC layout. ECC codes are right aligned in the OOB area. */
-	eccbytes = mtd->writesize / chip->ecc.size * chip->ecc.bytes;
-
-	if (eccbytes > mtd->oobsize - 2) {
-		dev_err(nfc->dev,
-			"invalid ECC config: required %d ECC bytes, but only %d are available",
-			eccbytes, mtd->oobsize - 2);
-		return -EINVAL;
-	}
-
-	/*
-	 * The generic layout for BBT markers will most likely overlap with our
-	 * ECC bytes in the OOB, so move the BBT markers outside the OOB area.
-	 */
-	if (chip->bbt_options & NAND_BBT_USE_FLASH)
-		chip->bbt_options |= NAND_BBT_NO_OOB;
-
-	/* For legacy reasons we use a different layout on the qi,lb60 board. */
-	if (of_machine_is_compatible("qi,lb60"))
-		mtd_set_ooblayout(mtd, &qi_lb60_ooblayout_ops);
-	else
-		mtd_set_ooblayout(mtd, nfc->soc_info->oob_layout);
-
-	return 0;
-}
-
-static const struct nand_controller_ops ingenic_nand_controller_ops = {
-	.attach_chip = ingenic_nand_attach_chip,
-};
-
-static int ingenic_nand_init_chip(struct platform_device *pdev,
-				  struct ingenic_nfc *nfc,
-				  struct device_node *np,
-				  unsigned int chipnr)
-{
-	struct device *dev = &pdev->dev;
-	struct ingenic_nand *nand;
-	struct ingenic_nand_cs *cs;
-	struct resource *res;
-	struct nand_chip *chip;
-	struct mtd_info *mtd;
-	const __be32 *reg;
-	int ret = 0;
-
-	cs = &nfc->cs[chipnr];
-
-	reg = of_get_property(np, "reg", NULL);
-	if (!reg)
-		return -EINVAL;
-
-	cs->bank = be32_to_cpu(*reg);
-
-	jz4780_nemc_set_type(nfc->dev, cs->bank, JZ4780_NEMC_BANK_NAND);
-
-	res = platform_get_resource(pdev, IORESOURCE_MEM, chipnr);
-	cs->base = devm_ioremap_resource(dev, res);
-	if (IS_ERR(cs->base))
-		return PTR_ERR(cs->base);
-
-	nand = devm_kzalloc(dev, sizeof(*nand), GFP_KERNEL);
-	if (!nand)
-		return -ENOMEM;
-
-	nand->busy_gpio = devm_gpiod_get_optional(dev, "rb", GPIOD_IN);
-
-	if (IS_ERR(nand->busy_gpio)) {
-		ret = PTR_ERR(nand->busy_gpio);
-		dev_err(dev, "failed to request busy GPIO: %d\n", ret);
-		return ret;
-	} else if (nand->busy_gpio) {
-		nand->chip.legacy.dev_ready = ingenic_nand_dev_ready;
-	}
-
-	nand->wp_gpio = devm_gpiod_get_optional(dev, "wp", GPIOD_OUT_LOW);
-
-	if (IS_ERR(nand->wp_gpio)) {
-		ret = PTR_ERR(nand->wp_gpio);
-		dev_err(dev, "failed to request WP GPIO: %d\n", ret);
-		return ret;
-	}
-
-	chip = &nand->chip;
-	mtd = nand_to_mtd(chip);
-	mtd->name = devm_kasprintf(dev, GFP_KERNEL, "%s.%d", dev_name(dev),
-				   cs->bank);
-	if (!mtd->name)
-		return -ENOMEM;
-	mtd->dev.parent = dev;
-
-	chip->legacy.IO_ADDR_R = cs->base + nfc->soc_info->data_offset;
-	chip->legacy.IO_ADDR_W = cs->base + nfc->soc_info->data_offset;
-	chip->legacy.chip_delay = RB_DELAY_US;
-	chip->options = NAND_NO_SUBPAGE_WRITE;
-	chip->legacy.select_chip = ingenic_nand_select_chip;
-	chip->legacy.cmd_ctrl = ingenic_nand_cmd_ctrl;
-	chip->ecc.mode = NAND_ECC_HW;
-	chip->controller = &nfc->controller;
-	nand_set_flash_node(chip, np);
-
-	chip->controller->ops = &ingenic_nand_controller_ops;
-	ret = nand_scan(chip, 1);
-	if (ret)
-		return ret;
-
-	ret = mtd_device_register(mtd, NULL, 0);
-	if (ret) {
-		nand_release(chip);
-		return ret;
-	}
-
-	list_add_tail(&nand->chip_list, &nfc->chips);
-
-	return 0;
-}
-
-static void ingenic_nand_cleanup_chips(struct ingenic_nfc *nfc)
-{
-	struct ingenic_nand *chip;
-
-	while (!list_empty(&nfc->chips)) {
-		chip = list_first_entry(&nfc->chips,
-					struct ingenic_nand, chip_list);
-		nand_release(&chip->chip);
-		list_del(&chip->chip_list);
-	}
-}
-
-static int ingenic_nand_init_chips(struct ingenic_nfc *nfc,
-				   struct platform_device *pdev)
-{
-	struct device *dev = &pdev->dev;
-	struct device_node *np;
-	int i = 0;
-	int ret;
-	int num_chips = of_get_child_count(dev->of_node);
-
-	if (num_chips > nfc->num_banks) {
-		dev_err(dev, "found %d chips but only %d banks\n",
-			num_chips, nfc->num_banks);
-		return -EINVAL;
-	}
-
-	for_each_child_of_node(dev->of_node, np) {
-		ret = ingenic_nand_init_chip(pdev, nfc, np, i);
-		if (ret) {
-			ingenic_nand_cleanup_chips(nfc);
-			return ret;
-		}
-
-		i++;
-	}
-
-	return 0;
-}
-
-static int ingenic_nand_probe(struct platform_device *pdev)
-{
-	struct device *dev = &pdev->dev;
-	unsigned int num_banks;
-	struct ingenic_nfc *nfc;
-	int ret;
-
-	num_banks = jz4780_nemc_num_banks(dev);
-	if (num_banks == 0) {
-		dev_err(dev, "no banks found\n");
-		return -ENODEV;
-	}
-
-	nfc = devm_kzalloc(dev, struct_size(nfc, cs, num_banks), GFP_KERNEL);
-	if (!nfc)
-		return -ENOMEM;
-
-	nfc->soc_info = device_get_match_data(dev);
-	if (!nfc->soc_info)
-		return -EINVAL;
-
-	/*
-	 * Check for ECC HW before we call nand_scan_ident, to prevent us from
-	 * having to call it again if the ECC driver returns -EPROBE_DEFER.
-	 */
-	nfc->ecc = of_ingenic_ecc_get(dev->of_node);
-	if (IS_ERR(nfc->ecc))
-		return PTR_ERR(nfc->ecc);
-
-	nfc->dev = dev;
-	nfc->num_banks = num_banks;
-
-	nand_controller_init(&nfc->controller);
-	INIT_LIST_HEAD(&nfc->chips);
-
-	ret = ingenic_nand_init_chips(nfc, pdev);
-	if (ret) {
-		if (nfc->ecc)
-			ingenic_ecc_release(nfc->ecc);
-		return ret;
-	}
-
-	platform_set_drvdata(pdev, nfc);
-	return 0;
-}
-
-static int ingenic_nand_remove(struct platform_device *pdev)
-{
-	struct ingenic_nfc *nfc = platform_get_drvdata(pdev);
-
-	if (nfc->ecc)
-		ingenic_ecc_release(nfc->ecc);
-
-	ingenic_nand_cleanup_chips(nfc);
-
-	return 0;
-}
-
-static const struct jz_soc_info jz4740_soc_info = {
-	.data_offset = 0x00000000,
-	.cmd_offset = 0x00008000,
-	.addr_offset = 0x00010000,
-	.oob_layout = &nand_ooblayout_lp_ops,
-};
-
-static const struct jz_soc_info jz4725b_soc_info = {
-	.data_offset = 0x00000000,
-	.cmd_offset = 0x00008000,
-	.addr_offset = 0x00010000,
-	.oob_layout = &jz4725b_ooblayout_ops,
-};
-
-static const struct jz_soc_info jz4780_soc_info = {
-	.data_offset = 0x00000000,
-	.cmd_offset = 0x00400000,
-	.addr_offset = 0x00800000,
-	.oob_layout = &nand_ooblayout_lp_ops,
-};
-
-static const struct of_device_id ingenic_nand_dt_match[] = {
-	{ .compatible = "ingenic,jz4740-nand", .data = &jz4740_soc_info },
-	{ .compatible = "ingenic,jz4725b-nand", .data = &jz4725b_soc_info },
-	{ .compatible = "ingenic,jz4780-nand", .data = &jz4780_soc_info },
-	{},
-};
-MODULE_DEVICE_TABLE(of, ingenic_nand_dt_match);
-
-static struct platform_driver ingenic_nand_driver = {
-	.probe		= ingenic_nand_probe,
-	.remove		= ingenic_nand_remove,
-	.driver	= {
-		.name	= DRV_NAME,
-		.of_match_table = of_match_ptr(ingenic_nand_dt_match),
-	},
-};
-module_platform_driver(ingenic_nand_driver);
-
-MODULE_AUTHOR("Alex Smith <alex@alex-smith.me.uk>");
-MODULE_AUTHOR("Harvey Hunt <harveyhuntnexus@gmail.com>");
-MODULE_DESCRIPTION("Ingenic JZ47xx NAND driver");
-MODULE_LICENSE("GPL v2");
diff -druNp --no-dereference linux-libre-5.2-rc7-gnu/drivers/mtd/nand/raw/ingenic/ingenic_nand_drv.c linux-libre-5.2-gnu/drivers/mtd/nand/raw/ingenic/ingenic_nand_drv.c
--- linux-libre-5.2-rc7-gnu/drivers/mtd/nand/raw/ingenic/ingenic_nand_drv.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-5.2-gnu/drivers/mtd/nand/raw/ingenic/ingenic_nand_drv.c	2019-07-07 18:41:56.000000000 -0400
@@ -0,0 +1,530 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Ingenic JZ47xx NAND driver
+ *
+ * Copyright (c) 2015 Imagination Technologies
+ * Author: Alex Smith <alex.smith@imgtec.com>
+ */
+
+#include <linux/delay.h>
+#include <linux/init.h>
+#include <linux/io.h>
+#include <linux/list.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/of_device.h>
+#include <linux/gpio/consumer.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+#include <linux/mtd/mtd.h>
+#include <linux/mtd/rawnand.h>
+#include <linux/mtd/partitions.h>
+
+#include <linux/jz4780-nemc.h>
+
+#include "ingenic_ecc.h"
+
+#define DRV_NAME	"ingenic-nand"
+
+/* Command delay when there is no R/B pin. */
+#define RB_DELAY_US	100
+
+struct jz_soc_info {
+	unsigned long data_offset;
+	unsigned long addr_offset;
+	unsigned long cmd_offset;
+	const struct mtd_ooblayout_ops *oob_layout;
+};
+
+struct ingenic_nand_cs {
+	unsigned int bank;
+	void __iomem *base;
+};
+
+struct ingenic_nfc {
+	struct device *dev;
+	struct ingenic_ecc *ecc;
+	const struct jz_soc_info *soc_info;
+	struct nand_controller controller;
+	unsigned int num_banks;
+	struct list_head chips;
+	int selected;
+	struct ingenic_nand_cs cs[];
+};
+
+struct ingenic_nand {
+	struct nand_chip chip;
+	struct list_head chip_list;
+
+	struct gpio_desc *busy_gpio;
+	struct gpio_desc *wp_gpio;
+	unsigned int reading: 1;
+};
+
+static inline struct ingenic_nand *to_ingenic_nand(struct mtd_info *mtd)
+{
+	return container_of(mtd_to_nand(mtd), struct ingenic_nand, chip);
+}
+
+static inline struct ingenic_nfc *to_ingenic_nfc(struct nand_controller *ctrl)
+{
+	return container_of(ctrl, struct ingenic_nfc, controller);
+}
+
+static int qi_lb60_ooblayout_ecc(struct mtd_info *mtd, int section,
+				 struct mtd_oob_region *oobregion)
+{
+	struct nand_chip *chip = mtd_to_nand(mtd);
+	struct nand_ecc_ctrl *ecc = &chip->ecc;
+
+	if (section || !ecc->total)
+		return -ERANGE;
+
+	oobregion->length = ecc->total;
+	oobregion->offset = 12;
+
+	return 0;
+}
+
+static int qi_lb60_ooblayout_free(struct mtd_info *mtd, int section,
+				  struct mtd_oob_region *oobregion)
+{
+	struct nand_chip *chip = mtd_to_nand(mtd);
+	struct nand_ecc_ctrl *ecc = &chip->ecc;
+
+	if (section)
+		return -ERANGE;
+
+	oobregion->length = mtd->oobsize - ecc->total - 12;
+	oobregion->offset = 12 + ecc->total;
+
+	return 0;
+}
+
+const struct mtd_ooblayout_ops qi_lb60_ooblayout_ops = {
+	.ecc = qi_lb60_ooblayout_ecc,
+	.free = qi_lb60_ooblayout_free,
+};
+
+static int jz4725b_ooblayout_ecc(struct mtd_info *mtd, int section,
+				 struct mtd_oob_region *oobregion)
+{
+	struct nand_chip *chip = mtd_to_nand(mtd);
+	struct nand_ecc_ctrl *ecc = &chip->ecc;
+
+	if (section || !ecc->total)
+		return -ERANGE;
+
+	oobregion->length = ecc->total;
+	oobregion->offset = 3;
+
+	return 0;
+}
+
+static int jz4725b_ooblayout_free(struct mtd_info *mtd, int section,
+				  struct mtd_oob_region *oobregion)
+{
+	struct nand_chip *chip = mtd_to_nand(mtd);
+	struct nand_ecc_ctrl *ecc = &chip->ecc;
+
+	if (section)
+		return -ERANGE;
+
+	oobregion->length = mtd->oobsize - ecc->total - 3;
+	oobregion->offset = 3 + ecc->total;
+
+	return 0;
+}
+
+static const struct mtd_ooblayout_ops jz4725b_ooblayout_ops = {
+	.ecc = jz4725b_ooblayout_ecc,
+	.free = jz4725b_ooblayout_free,
+};
+
+static void ingenic_nand_select_chip(struct nand_chip *chip, int chipnr)
+{
+	struct ingenic_nand *nand = to_ingenic_nand(nand_to_mtd(chip));
+	struct ingenic_nfc *nfc = to_ingenic_nfc(nand->chip.controller);
+	struct ingenic_nand_cs *cs;
+
+	/* Ensure the currently selected chip is deasserted. */
+	if (chipnr == -1 && nfc->selected >= 0) {
+		cs = &nfc->cs[nfc->selected];
+		jz4780_nemc_assert(nfc->dev, cs->bank, false);
+	}
+
+	nfc->selected = chipnr;
+}
+
+static void ingenic_nand_cmd_ctrl(struct nand_chip *chip, int cmd,
+				  unsigned int ctrl)
+{
+	struct ingenic_nand *nand = to_ingenic_nand(nand_to_mtd(chip));
+	struct ingenic_nfc *nfc = to_ingenic_nfc(nand->chip.controller);
+	struct ingenic_nand_cs *cs;
+
+	if (WARN_ON(nfc->selected < 0))
+		return;
+
+	cs = &nfc->cs[nfc->selected];
+
+	jz4780_nemc_assert(nfc->dev, cs->bank, ctrl & NAND_NCE);
+
+	if (cmd == NAND_CMD_NONE)
+		return;
+
+	if (ctrl & NAND_ALE)
+		writeb(cmd, cs->base + nfc->soc_info->addr_offset);
+	else if (ctrl & NAND_CLE)
+		writeb(cmd, cs->base + nfc->soc_info->cmd_offset);
+}
+
+static int ingenic_nand_dev_ready(struct nand_chip *chip)
+{
+	struct ingenic_nand *nand = to_ingenic_nand(nand_to_mtd(chip));
+
+	return !gpiod_get_value_cansleep(nand->busy_gpio);
+}
+
+static void ingenic_nand_ecc_hwctl(struct nand_chip *chip, int mode)
+{
+	struct ingenic_nand *nand = to_ingenic_nand(nand_to_mtd(chip));
+
+	nand->reading = (mode == NAND_ECC_READ);
+}
+
+static int ingenic_nand_ecc_calculate(struct nand_chip *chip, const u8 *dat,
+				      u8 *ecc_code)
+{
+	struct ingenic_nand *nand = to_ingenic_nand(nand_to_mtd(chip));
+	struct ingenic_nfc *nfc = to_ingenic_nfc(nand->chip.controller);
+	struct ingenic_ecc_params params;
+
+	/*
+	 * Don't need to generate the ECC when reading, the ECC engine does it
+	 * for us as part of decoding/correction.
+	 */
+	if (nand->reading)
+		return 0;
+
+	params.size = nand->chip.ecc.size;
+	params.bytes = nand->chip.ecc.bytes;
+	params.strength = nand->chip.ecc.strength;
+
+	return ingenic_ecc_calculate(nfc->ecc, &params, dat, ecc_code);
+}
+
+static int ingenic_nand_ecc_correct(struct nand_chip *chip, u8 *dat,
+				    u8 *read_ecc, u8 *calc_ecc)
+{
+	struct ingenic_nand *nand = to_ingenic_nand(nand_to_mtd(chip));
+	struct ingenic_nfc *nfc = to_ingenic_nfc(nand->chip.controller);
+	struct ingenic_ecc_params params;
+
+	params.size = nand->chip.ecc.size;
+	params.bytes = nand->chip.ecc.bytes;
+	params.strength = nand->chip.ecc.strength;
+
+	return ingenic_ecc_correct(nfc->ecc, &params, dat, read_ecc);
+}
+
+static int ingenic_nand_attach_chip(struct nand_chip *chip)
+{
+	struct mtd_info *mtd = nand_to_mtd(chip);
+	struct ingenic_nfc *nfc = to_ingenic_nfc(chip->controller);
+	int eccbytes;
+
+	if (chip->ecc.strength == 4) {
+		/* JZ4740 uses 9 bytes of ECC to correct maximum 4 errors */
+		chip->ecc.bytes = 9;
+	} else {
+		chip->ecc.bytes = fls((1 + 8) * chip->ecc.size)	*
+				  (chip->ecc.strength / 8);
+	}
+
+	switch (chip->ecc.mode) {
+	case NAND_ECC_HW:
+		if (!nfc->ecc) {
+			dev_err(nfc->dev, "HW ECC selected, but ECC controller not found\n");
+			return -ENODEV;
+		}
+
+		chip->ecc.hwctl = ingenic_nand_ecc_hwctl;
+		chip->ecc.calculate = ingenic_nand_ecc_calculate;
+		chip->ecc.correct = ingenic_nand_ecc_correct;
+		/* fall through */
+	case NAND_ECC_SOFT:
+		dev_info(nfc->dev, "using %s (strength %d, size %d, bytes %d)\n",
+			 (nfc->ecc) ? "hardware ECC" : "software ECC",
+			 chip->ecc.strength, chip->ecc.size, chip->ecc.bytes);
+		break;
+	case NAND_ECC_NONE:
+		dev_info(nfc->dev, "not using ECC\n");
+		break;
+	default:
+		dev_err(nfc->dev, "ECC mode %d not supported\n",
+			chip->ecc.mode);
+		return -EINVAL;
+	}
+
+	/* The NAND core will generate the ECC layout for SW ECC */
+	if (chip->ecc.mode != NAND_ECC_HW)
+		return 0;
+
+	/* Generate ECC layout. ECC codes are right aligned in the OOB area. */
+	eccbytes = mtd->writesize / chip->ecc.size * chip->ecc.bytes;
+
+	if (eccbytes > mtd->oobsize - 2) {
+		dev_err(nfc->dev,
+			"invalid ECC config: required %d ECC bytes, but only %d are available",
+			eccbytes, mtd->oobsize - 2);
+		return -EINVAL;
+	}
+
+	/*
+	 * The generic layout for BBT markers will most likely overlap with our
+	 * ECC bytes in the OOB, so move the BBT markers outside the OOB area.
+	 */
+	if (chip->bbt_options & NAND_BBT_USE_FLASH)
+		chip->bbt_options |= NAND_BBT_NO_OOB;
+
+	/* For legacy reasons we use a different layout on the qi,lb60 board. */
+	if (of_machine_is_compatible("qi,lb60"))
+		mtd_set_ooblayout(mtd, &qi_lb60_ooblayout_ops);
+	else
+		mtd_set_ooblayout(mtd, nfc->soc_info->oob_layout);
+
+	return 0;
+}
+
+static const struct nand_controller_ops ingenic_nand_controller_ops = {
+	.attach_chip = ingenic_nand_attach_chip,
+};
+
+static int ingenic_nand_init_chip(struct platform_device *pdev,
+				  struct ingenic_nfc *nfc,
+				  struct device_node *np,
+				  unsigned int chipnr)
+{
+	struct device *dev = &pdev->dev;
+	struct ingenic_nand *nand;
+	struct ingenic_nand_cs *cs;
+	struct resource *res;
+	struct nand_chip *chip;
+	struct mtd_info *mtd;
+	const __be32 *reg;
+	int ret = 0;
+
+	cs = &nfc->cs[chipnr];
+
+	reg = of_get_property(np, "reg", NULL);
+	if (!reg)
+		return -EINVAL;
+
+	cs->bank = be32_to_cpu(*reg);
+
+	jz4780_nemc_set_type(nfc->dev, cs->bank, JZ4780_NEMC_BANK_NAND);
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, chipnr);
+	cs->base = devm_ioremap_resource(dev, res);
+	if (IS_ERR(cs->base))
+		return PTR_ERR(cs->base);
+
+	nand = devm_kzalloc(dev, sizeof(*nand), GFP_KERNEL);
+	if (!nand)
+		return -ENOMEM;
+
+	nand->busy_gpio = devm_gpiod_get_optional(dev, "rb", GPIOD_IN);
+
+	if (IS_ERR(nand->busy_gpio)) {
+		ret = PTR_ERR(nand->busy_gpio);
+		dev_err(dev, "failed to request busy GPIO: %d\n", ret);
+		return ret;
+	} else if (nand->busy_gpio) {
+		nand->chip.legacy.dev_ready = ingenic_nand_dev_ready;
+	}
+
+	nand->wp_gpio = devm_gpiod_get_optional(dev, "wp", GPIOD_OUT_LOW);
+
+	if (IS_ERR(nand->wp_gpio)) {
+		ret = PTR_ERR(nand->wp_gpio);
+		dev_err(dev, "failed to request WP GPIO: %d\n", ret);
+		return ret;
+	}
+
+	chip = &nand->chip;
+	mtd = nand_to_mtd(chip);
+	mtd->name = devm_kasprintf(dev, GFP_KERNEL, "%s.%d", dev_name(dev),
+				   cs->bank);
+	if (!mtd->name)
+		return -ENOMEM;
+	mtd->dev.parent = dev;
+
+	chip->legacy.IO_ADDR_R = cs->base + nfc->soc_info->data_offset;
+	chip->legacy.IO_ADDR_W = cs->base + nfc->soc_info->data_offset;
+	chip->legacy.chip_delay = RB_DELAY_US;
+	chip->options = NAND_NO_SUBPAGE_WRITE;
+	chip->legacy.select_chip = ingenic_nand_select_chip;
+	chip->legacy.cmd_ctrl = ingenic_nand_cmd_ctrl;
+	chip->ecc.mode = NAND_ECC_HW;
+	chip->controller = &nfc->controller;
+	nand_set_flash_node(chip, np);
+
+	chip->controller->ops = &ingenic_nand_controller_ops;
+	ret = nand_scan(chip, 1);
+	if (ret)
+		return ret;
+
+	ret = mtd_device_register(mtd, NULL, 0);
+	if (ret) {
+		nand_release(chip);
+		return ret;
+	}
+
+	list_add_tail(&nand->chip_list, &nfc->chips);
+
+	return 0;
+}
+
+static void ingenic_nand_cleanup_chips(struct ingenic_nfc *nfc)
+{
+	struct ingenic_nand *chip;
+
+	while (!list_empty(&nfc->chips)) {
+		chip = list_first_entry(&nfc->chips,
+					struct ingenic_nand, chip_list);
+		nand_release(&chip->chip);
+		list_del(&chip->chip_list);
+	}
+}
+
+static int ingenic_nand_init_chips(struct ingenic_nfc *nfc,
+				   struct platform_device *pdev)
+{
+	struct device *dev = &pdev->dev;
+	struct device_node *np;
+	int i = 0;
+	int ret;
+	int num_chips = of_get_child_count(dev->of_node);
+
+	if (num_chips > nfc->num_banks) {
+		dev_err(dev, "found %d chips but only %d banks\n",
+			num_chips, nfc->num_banks);
+		return -EINVAL;
+	}
+
+	for_each_child_of_node(dev->of_node, np) {
+		ret = ingenic_nand_init_chip(pdev, nfc, np, i);
+		if (ret) {
+			ingenic_nand_cleanup_chips(nfc);
+			return ret;
+		}
+
+		i++;
+	}
+
+	return 0;
+}
+
+static int ingenic_nand_probe(struct platform_device *pdev)
+{
+	struct device *dev = &pdev->dev;
+	unsigned int num_banks;
+	struct ingenic_nfc *nfc;
+	int ret;
+
+	num_banks = jz4780_nemc_num_banks(dev);
+	if (num_banks == 0) {
+		dev_err(dev, "no banks found\n");
+		return -ENODEV;
+	}
+
+	nfc = devm_kzalloc(dev, struct_size(nfc, cs, num_banks), GFP_KERNEL);
+	if (!nfc)
+		return -ENOMEM;
+
+	nfc->soc_info = device_get_match_data(dev);
+	if (!nfc->soc_info)
+		return -EINVAL;
+
+	/*
+	 * Check for ECC HW before we call nand_scan_ident, to prevent us from
+	 * having to call it again if the ECC driver returns -EPROBE_DEFER.
+	 */
+	nfc->ecc = of_ingenic_ecc_get(dev->of_node);
+	if (IS_ERR(nfc->ecc))
+		return PTR_ERR(nfc->ecc);
+
+	nfc->dev = dev;
+	nfc->num_banks = num_banks;
+
+	nand_controller_init(&nfc->controller);
+	INIT_LIST_HEAD(&nfc->chips);
+
+	ret = ingenic_nand_init_chips(nfc, pdev);
+	if (ret) {
+		if (nfc->ecc)
+			ingenic_ecc_release(nfc->ecc);
+		return ret;
+	}
+
+	platform_set_drvdata(pdev, nfc);
+	return 0;
+}
+
+static int ingenic_nand_remove(struct platform_device *pdev)
+{
+	struct ingenic_nfc *nfc = platform_get_drvdata(pdev);
+
+	if (nfc->ecc)
+		ingenic_ecc_release(nfc->ecc);
+
+	ingenic_nand_cleanup_chips(nfc);
+
+	return 0;
+}
+
+static const struct jz_soc_info jz4740_soc_info = {
+	.data_offset = 0x00000000,
+	.cmd_offset = 0x00008000,
+	.addr_offset = 0x00010000,
+	.oob_layout = &nand_ooblayout_lp_ops,
+};
+
+static const struct jz_soc_info jz4725b_soc_info = {
+	.data_offset = 0x00000000,
+	.cmd_offset = 0x00008000,
+	.addr_offset = 0x00010000,
+	.oob_layout = &jz4725b_ooblayout_ops,
+};
+
+static const struct jz_soc_info jz4780_soc_info = {
+	.data_offset = 0x00000000,
+	.cmd_offset = 0x00400000,
+	.addr_offset = 0x00800000,
+	.oob_layout = &nand_ooblayout_lp_ops,
+};
+
+static const struct of_device_id ingenic_nand_dt_match[] = {
+	{ .compatible = "ingenic,jz4740-nand", .data = &jz4740_soc_info },
+	{ .compatible = "ingenic,jz4725b-nand", .data = &jz4725b_soc_info },
+	{ .compatible = "ingenic,jz4780-nand", .data = &jz4780_soc_info },
+	{},
+};
+MODULE_DEVICE_TABLE(of, ingenic_nand_dt_match);
+
+static struct platform_driver ingenic_nand_driver = {
+	.probe		= ingenic_nand_probe,
+	.remove		= ingenic_nand_remove,
+	.driver	= {
+		.name	= DRV_NAME,
+		.of_match_table = of_match_ptr(ingenic_nand_dt_match),
+	},
+};
+module_platform_driver(ingenic_nand_driver);
+
+MODULE_AUTHOR("Alex Smith <alex@alex-smith.me.uk>");
+MODULE_AUTHOR("Harvey Hunt <harveyhuntnexus@gmail.com>");
+MODULE_DESCRIPTION("Ingenic JZ47xx NAND driver");
+MODULE_LICENSE("GPL v2");
diff -druNp --no-dereference linux-libre-5.2-rc7-gnu/drivers/mtd/nand/raw/ingenic/Kconfig linux-libre-5.2-gnu/drivers/mtd/nand/raw/ingenic/Kconfig
--- linux-libre-5.2-rc7-gnu/drivers/mtd/nand/raw/ingenic/Kconfig	2019-06-29 23:25:36.000000000 -0400
+++ linux-libre-5.2-gnu/drivers/mtd/nand/raw/ingenic/Kconfig	2019-07-07 18:41:56.000000000 -0400
@@ -16,7 +16,7 @@ config MTD_NAND_JZ4780
 if MTD_NAND_JZ4780
 
 config MTD_NAND_INGENIC_ECC
-	tristate
+	bool
 
 config MTD_NAND_JZ4740_ECC
 	tristate "Hardware BCH support for JZ4740 SoC"
diff -druNp --no-dereference linux-libre-5.2-rc7-gnu/drivers/mtd/nand/raw/ingenic/Makefile linux-libre-5.2-gnu/drivers/mtd/nand/raw/ingenic/Makefile
--- linux-libre-5.2-rc7-gnu/drivers/mtd/nand/raw/ingenic/Makefile	2019-06-29 23:25:36.000000000 -0400
+++ linux-libre-5.2-gnu/drivers/mtd/nand/raw/ingenic/Makefile	2019-07-07 18:41:56.000000000 -0400
@@ -2,7 +2,9 @@
 obj-$(CONFIG_MTD_NAND_JZ4740) += jz4740_nand.o
 obj-$(CONFIG_MTD_NAND_JZ4780) += ingenic_nand.o
 
-obj-$(CONFIG_MTD_NAND_INGENIC_ECC) += ingenic_ecc.o
+ingenic_nand-y += ingenic_nand_drv.o
+ingenic_nand-$(CONFIG_MTD_NAND_INGENIC_ECC) += ingenic_ecc.o
+
 obj-$(CONFIG_MTD_NAND_JZ4740_ECC) += jz4740_ecc.o
 obj-$(CONFIG_MTD_NAND_JZ4725B_BCH) += jz4725b_bch.o
 obj-$(CONFIG_MTD_NAND_JZ4780_BCH) += jz4780_bch.o
diff -druNp --no-dereference linux-libre-5.2-rc7-gnu/drivers/mtd/nand/raw/sunxi_nand.c linux-libre-5.2-gnu/drivers/mtd/nand/raw/sunxi_nand.c
--- linux-libre-5.2-rc7-gnu/drivers/mtd/nand/raw/sunxi_nand.c	2019-06-29 23:25:36.000000000 -0400
+++ linux-libre-5.2-gnu/drivers/mtd/nand/raw/sunxi_nand.c	2019-07-07 18:41:56.000000000 -0400
@@ -51,6 +51,7 @@
 #define NFC_REG_USER_DATA(x)	(0x0050 + ((x) * 4))
 #define NFC_REG_SPARE_AREA	0x00A0
 #define NFC_REG_PAT_ID		0x00A4
+#define NFC_REG_MDMA_CNT	0x00C4
 #define NFC_RAM0_BASE		0x0400
 #define NFC_RAM1_BASE		0x0800
 
@@ -69,6 +70,7 @@
 #define NFC_PAGE_SHIFT(x)	(((x) < 10 ? 0 : (x) - 10) << 8)
 #define NFC_SAM			BIT(12)
 #define NFC_RAM_METHOD		BIT(14)
+#define NFC_DMA_TYPE_NORMAL	BIT(15)
 #define NFC_DEBUG_CTL		BIT(31)
 
 /* define bit use in NFC_ST */
@@ -205,14 +207,13 @@ static inline struct sunxi_nand_chip *to
  * NAND Controller capabilities structure: stores NAND controller capabilities
  * for distinction between compatible strings.
  *
- * @sram_through_ahb:	On A23, we choose to access the internal RAM through AHB
- *                      instead of MBUS (less configuration). A10, A10s, A13 and
- *                      A20 use the MBUS but no extra configuration is needed.
+ * @extra_mbus_conf:	Contrary to A10, A10s and A13, accessing internal RAM
+ *			through MBUS on A23/A33 needs extra configuration.
  * @reg_io_data:	I/O data register
  * @dma_maxburst:	DMA maxburst
  */
 struct sunxi_nfc_caps {
-	bool sram_through_ahb;
+	bool extra_mbus_conf;
 	unsigned int reg_io_data;
 	unsigned int dma_maxburst;
 };
@@ -368,28 +369,12 @@ static int sunxi_nfc_dma_op_prepare(stru
 		goto err_unmap_buf;
 	}
 
-	/*
-	 * On A23, we suppose the "internal RAM" (p.12 of the NFC user manual)
-	 * refers to the NAND controller's internal SRAM. This memory is mapped
-	 * and so is accessible from the AHB. It seems that it can also be
-	 * accessed by the MBUS. MBUS accesses are mandatory when using the
-	 * internal DMA instead of the external DMA engine.
-	 *
-	 * During DMA I/O operation, either we access this memory from the AHB
-	 * by clearing the NFC_RAM_METHOD bit, or we set the bit and use the
-	 * MBUS. In this case, we should also configure the MBUS DMA length
-	 * NFC_REG_MDMA_CNT(0xC4) to be chunksize * nchunks. NAND I/O over MBUS
-	 * are also limited to 32kiB pages.
-	 */
-	if (nfc->caps->sram_through_ahb)
-		writel(readl(nfc->regs + NFC_REG_CTL) & ~NFC_RAM_METHOD,
-		       nfc->regs + NFC_REG_CTL);
-	else
-		writel(readl(nfc->regs + NFC_REG_CTL) | NFC_RAM_METHOD,
-		       nfc->regs + NFC_REG_CTL);
-
+	writel(readl(nfc->regs + NFC_REG_CTL) | NFC_RAM_METHOD,
+	       nfc->regs + NFC_REG_CTL);
 	writel(nchunks, nfc->regs + NFC_REG_SECTOR_NUM);
 	writel(chunksize, nfc->regs + NFC_REG_CNT);
+	if (nfc->caps->extra_mbus_conf)
+		writel(chunksize * nchunks, nfc->regs + NFC_REG_MDMA_CNT);
 
 	dmat = dmaengine_submit(dmad);
 
@@ -2151,6 +2136,11 @@ static int sunxi_nfc_probe(struct platfo
 		dmac_cfg.src_maxburst = nfc->caps->dma_maxburst;
 		dmac_cfg.dst_maxburst = nfc->caps->dma_maxburst;
 		dmaengine_slave_config(nfc->dmac, &dmac_cfg);
+
+		if (nfc->caps->extra_mbus_conf)
+			writel(readl(nfc->regs + NFC_REG_CTL) |
+			       NFC_DMA_TYPE_NORMAL, nfc->regs + NFC_REG_CTL);
+
 	} else {
 		dev_warn(dev, "failed to request rxtx DMA channel\n");
 	}
@@ -2200,7 +2190,7 @@ static const struct sunxi_nfc_caps sunxi
 };
 
 static const struct sunxi_nfc_caps sunxi_nfc_a23_caps = {
-	.sram_through_ahb = true,
+	.extra_mbus_conf = true,
 	.reg_io_data = NFC_REG_A23_IO_DATA,
 	.dma_maxburst = 8,
 };
diff -druNp --no-dereference linux-libre-5.2-rc7-gnu/drivers/mtd/nand/spi/gigadevice.c linux-libre-5.2-gnu/drivers/mtd/nand/spi/gigadevice.c
--- linux-libre-5.2-rc7-gnu/drivers/mtd/nand/spi/gigadevice.c	2019-06-29 23:25:36.000000000 -0400
+++ linux-libre-5.2-gnu/drivers/mtd/nand/spi/gigadevice.c	2019-07-07 18:41:56.000000000 -0400
@@ -180,7 +180,7 @@ static const struct spinand_info gigadev
 		     SPINAND_ECCINFO(&gd5fxgq4xa_ooblayout,
 				     gd5fxgq4xa_ecc_get_status)),
 	SPINAND_INFO("GD5F4GQ4xA", 0xF4,
-		     NAND_MEMORG(1, 2048, 64, 64, 4096, 40, 1, 1, 1),
+		     NAND_MEMORG(1, 2048, 64, 64, 4096, 80, 1, 1, 1),
 		     NAND_ECCREQ(8, 512),
 		     SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
 					      &write_cache_variants,
diff -druNp --no-dereference linux-libre-5.2-rc7-gnu/drivers/mtd/nand/spi/macronix.c linux-libre-5.2-gnu/drivers/mtd/nand/spi/macronix.c
--- linux-libre-5.2-rc7-gnu/drivers/mtd/nand/spi/macronix.c	2019-06-29 23:25:36.000000000 -0400
+++ linux-libre-5.2-gnu/drivers/mtd/nand/spi/macronix.c	2019-07-07 18:41:56.000000000 -0400
@@ -100,7 +100,7 @@ static int mx35lf1ge4ab_ecc_get_status(s
 
 static const struct spinand_info macronix_spinand_table[] = {
 	SPINAND_INFO("MX35LF1GE4AB", 0x12,
-		     NAND_MEMORG(1, 2048, 64, 64, 1024, 40, 1, 1, 1),
+		     NAND_MEMORG(1, 2048, 64, 64, 1024, 20, 1, 1, 1),
 		     NAND_ECCREQ(4, 512),
 		     SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
 					      &write_cache_variants,
@@ -109,7 +109,7 @@ static const struct spinand_info macroni
 		     SPINAND_ECCINFO(&mx35lfxge4ab_ooblayout,
 				     mx35lf1ge4ab_ecc_get_status)),
 	SPINAND_INFO("MX35LF2GE4AB", 0x22,
-		     NAND_MEMORG(1, 2048, 64, 64, 2048, 20, 2, 1, 1),
+		     NAND_MEMORG(1, 2048, 64, 64, 2048, 40, 2, 1, 1),
 		     NAND_ECCREQ(4, 512),
 		     SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
 					      &write_cache_variants,
diff -druNp --no-dereference linux-libre-5.2-rc7-gnu/drivers/soc/Makefile linux-libre-5.2-gnu/drivers/soc/Makefile
--- linux-libre-5.2-rc7-gnu/drivers/soc/Makefile	2019-06-29 23:25:36.000000000 -0400
+++ linux-libre-5.2-gnu/drivers/soc/Makefile	2019-07-07 18:41:56.000000000 -0400
@@ -22,7 +22,7 @@ obj-$(CONFIG_ARCH_ROCKCHIP)	+= rockchip/
 obj-$(CONFIG_SOC_SAMSUNG)	+= samsung/
 obj-y				+= sunxi/
 obj-$(CONFIG_ARCH_TEGRA)	+= tegra/
-obj-$(CONFIG_SOC_TI)		+= ti/
+obj-y				+= ti/
 obj-$(CONFIG_ARCH_U8500)	+= ux500/
 obj-$(CONFIG_PLAT_VERSATILE)	+= versatile/
 obj-y				+= xilinx/
diff -druNp --no-dereference linux-libre-5.2-rc7-gnu/drivers/soc/ti/Kconfig linux-libre-5.2-gnu/drivers/soc/ti/Kconfig
--- linux-libre-5.2-rc7-gnu/drivers/soc/ti/Kconfig	2019-06-29 23:25:36.000000000 -0400
+++ linux-libre-5.2-gnu/drivers/soc/ti/Kconfig	2019-07-07 18:41:56.000000000 -0400
@@ -75,10 +75,10 @@ config TI_SCI_PM_DOMAINS
 	  called ti_sci_pm_domains. Note this is needed early in boot before
 	  rootfs may be available.
 
+endif # SOC_TI
+
 config TI_SCI_INTA_MSI_DOMAIN
 	bool
 	select GENERIC_MSI_IRQ_DOMAIN
 	help
 	  Driver to enable Interrupt Aggregator specific MSI Domain.
-
-endif # SOC_TI
diff -druNp --no-dereference linux-libre-5.2-rc7-gnu/drivers/target/iscsi/iscsi_target_auth.c linux-libre-5.2-gnu/drivers/target/iscsi/iscsi_target_auth.c
--- linux-libre-5.2-rc7-gnu/drivers/target/iscsi/iscsi_target_auth.c	2019-06-29 23:25:36.000000000 -0400
+++ linux-libre-5.2-gnu/drivers/target/iscsi/iscsi_target_auth.c	2019-07-07 18:41:56.000000000 -0400
@@ -81,6 +81,12 @@ out:
 	return CHAP_DIGEST_UNKNOWN;
 }
 
+static void chap_close(struct iscsi_conn *conn)
+{
+	kfree(conn->auth_protocol);
+	conn->auth_protocol = NULL;
+}
+
 static struct iscsi_chap *chap_server_open(
 	struct iscsi_conn *conn,
 	struct iscsi_node_auth *auth,
@@ -118,7 +124,7 @@ static struct iscsi_chap *chap_server_op
 	case CHAP_DIGEST_UNKNOWN:
 	default:
 		pr_err("Unsupported CHAP_A value\n");
-		kfree(conn->auth_protocol);
+		chap_close(conn);
 		return NULL;
 	}
 
@@ -133,19 +139,13 @@ static struct iscsi_chap *chap_server_op
 	 * Generate Challenge.
 	 */
 	if (chap_gen_challenge(conn, 1, aic_str, aic_len) < 0) {
-		kfree(conn->auth_protocol);
+		chap_close(conn);
 		return NULL;
 	}
 
 	return chap;
 }
 
-static void chap_close(struct iscsi_conn *conn)
-{
-	kfree(conn->auth_protocol);
-	conn->auth_protocol = NULL;
-}
-
 static int chap_server_compute_md5(
 	struct iscsi_conn *conn,
 	struct iscsi_node_auth *auth,
diff -druNp --no-dereference linux-libre-5.2-rc7-gnu/drivers/target/target_core_iblock.c linux-libre-5.2-gnu/drivers/target/target_core_iblock.c
--- linux-libre-5.2-rc7-gnu/drivers/target/target_core_iblock.c	2019-06-29 23:25:36.000000000 -0400
+++ linux-libre-5.2-gnu/drivers/target/target_core_iblock.c	2019-07-07 18:41:56.000000000 -0400
@@ -502,7 +502,7 @@ iblock_execute_write_same(struct se_cmd
 
 		/* Always in 512 byte units for Linux/Block */
 		block_lba += sg->length >> SECTOR_SHIFT;
-		sectors -= 1;
+		sectors -= sg->length >> SECTOR_SHIFT;
 	}
 
 	iblock_submit_bios(&list);
diff -druNp --no-dereference linux-libre-5.2-rc7-gnu/fs/cifs/smb2ops.c linux-libre-5.2-gnu/fs/cifs/smb2ops.c
--- linux-libre-5.2-rc7-gnu/fs/cifs/smb2ops.c	2019-06-29 23:25:36.000000000 -0400
+++ linux-libre-5.2-gnu/fs/cifs/smb2ops.c	2019-07-07 18:41:56.000000000 -0400
@@ -2372,6 +2372,41 @@ smb2_get_dfs_refer(const unsigned int xi
 	kfree(dfs_rsp);
 	return rc;
 }
+
+static int
+parse_reparse_symlink(struct reparse_symlink_data_buffer *symlink_buf,
+		      u32 plen, char **target_path,
+		      struct cifs_sb_info *cifs_sb)
+{
+	unsigned int sub_len;
+	unsigned int sub_offset;
+
+	/* We only handle Symbolic Link : MS-FSCC 2.1.2.4 */
+	if (le32_to_cpu(symlink_buf->ReparseTag) != IO_REPARSE_TAG_SYMLINK) {
+		cifs_dbg(VFS, "srv returned invalid symlink buffer\n");
+		return -EIO;
+	}
+
+	sub_offset = le16_to_cpu(symlink_buf->SubstituteNameOffset);
+	sub_len = le16_to_cpu(symlink_buf->SubstituteNameLength);
+	if (sub_offset + 20 > plen ||
+	    sub_offset + sub_len + 20 > plen) {
+		cifs_dbg(VFS, "srv returned malformed symlink buffer\n");
+		return -EIO;
+	}
+
+	*target_path = cifs_strndup_from_utf16(
+				symlink_buf->PathBuffer + sub_offset,
+				sub_len, true, cifs_sb->local_nls);
+	if (!(*target_path))
+		return -ENOMEM;
+
+	convert_delimiter(*target_path, '/');
+	cifs_dbg(FYI, "%s: target path: %s\n", __func__, *target_path);
+
+	return 0;
+}
+
 #define SMB2_SYMLINK_STRUCT_SIZE \
 	(sizeof(struct smb2_err_rsp) - 1 + sizeof(struct smb2_symlink_err_rsp))
 
@@ -2401,11 +2436,13 @@ smb2_query_symlink(const unsigned int xi
 	struct kvec close_iov[1];
 	struct smb2_create_rsp *create_rsp;
 	struct smb2_ioctl_rsp *ioctl_rsp;
-	char *ioctl_buf;
+	struct reparse_data_buffer *reparse_buf;
 	u32 plen;
 
 	cifs_dbg(FYI, "%s: path: %s\n", __func__, full_path);
 
+	*target_path = NULL;
+
 	if (smb3_encryption_required(tcon))
 		flags |= CIFS_TRANSFORM_REQ;
 
@@ -2483,17 +2520,36 @@ smb2_query_symlink(const unsigned int xi
 	if ((rc == 0) && (is_reparse_point)) {
 		/* See MS-FSCC 2.3.23 */
 
-		ioctl_buf = (char *)ioctl_rsp + le32_to_cpu(ioctl_rsp->OutputOffset);
+		reparse_buf = (struct reparse_data_buffer *)
+			((char *)ioctl_rsp +
+			 le32_to_cpu(ioctl_rsp->OutputOffset));
 		plen = le32_to_cpu(ioctl_rsp->OutputCount);
 
 		if (plen + le32_to_cpu(ioctl_rsp->OutputOffset) >
 		    rsp_iov[1].iov_len) {
-			cifs_dbg(VFS, "srv returned invalid ioctl length: %d\n", plen);
+			cifs_dbg(VFS, "srv returned invalid ioctl len: %d\n",
+				 plen);
 			rc = -EIO;
 			goto querty_exit;
 		}
 
-		/* Do stuff with ioctl_buf/plen */
+		if (plen < 8) {
+			cifs_dbg(VFS, "reparse buffer is too small. Must be "
+				 "at least 8 bytes but was %d\n", plen);
+			rc = -EIO;
+			goto querty_exit;
+		}
+
+		if (plen < le16_to_cpu(reparse_buf->ReparseDataLength) + 8) {
+			cifs_dbg(VFS, "srv returned invalid reparse buf "
+				 "length: %d\n", plen);
+			rc = -EIO;
+			goto querty_exit;
+		}
+
+		rc = parse_reparse_symlink(
+			(struct reparse_symlink_data_buffer *)reparse_buf,
+			plen, target_path, cifs_sb);
 		goto querty_exit;
 	}
 
diff -druNp --no-dereference linux-libre-5.2-rc7-gnu/fs/cifs/smb2pdu.h linux-libre-5.2-gnu/fs/cifs/smb2pdu.h
--- linux-libre-5.2-rc7-gnu/fs/cifs/smb2pdu.h	2019-06-29 23:25:36.000000000 -0400
+++ linux-libre-5.2-gnu/fs/cifs/smb2pdu.h	2019-07-07 18:41:56.000000000 -0400
@@ -914,7 +914,19 @@ struct reparse_mount_point_data_buffer {
 	__u8	PathBuffer[0]; /* Variable Length */
 } __packed;
 
-/* See MS-FSCC 2.1.2.4 and cifspdu.h for struct reparse_symlink_data */
+#define SYMLINK_FLAG_RELATIVE 0x00000001
+
+struct reparse_symlink_data_buffer {
+	__le32	ReparseTag;
+	__le16	ReparseDataLength;
+	__u16	Reserved;
+	__le16	SubstituteNameOffset;
+	__le16	SubstituteNameLength;
+	__le16	PrintNameOffset;
+	__le16	PrintNameLength;
+	__le32	Flags;
+	__u8	PathBuffer[0]; /* Variable Length */
+} __packed;
 
 /* See MS-FSCC 2.1.2.6 and cifspdu.h for struct reparse_posix_data */
 
diff -druNp --no-dereference linux-libre-5.2-rc7-gnu/fs/dax.c linux-libre-5.2-gnu/fs/dax.c
--- linux-libre-5.2-rc7-gnu/fs/dax.c	2019-06-29 23:25:36.000000000 -0400
+++ linux-libre-5.2-gnu/fs/dax.c	2019-07-07 18:41:56.000000000 -0400
@@ -720,12 +720,11 @@ static void *dax_insert_entry(struct xa_
 
 	xas_reset(xas);
 	xas_lock_irq(xas);
-	if (dax_entry_size(entry) != dax_entry_size(new_entry)) {
+	if (dax_is_zero_entry(entry) || dax_is_empty_entry(entry)) {
+		void *old;
+
 		dax_disassociate_entry(entry, mapping, false);
 		dax_associate_entry(new_entry, mapping, vmf->vma, vmf->address);
-	}
-
-	if (dax_is_zero_entry(entry) || dax_is_empty_entry(entry)) {
 		/*
 		 * Only swap our new entry into the page cache if the current
 		 * entry is a zero page or an empty entry.  If a normal PTE or
@@ -734,7 +733,7 @@ static void *dax_insert_entry(struct xa_
 		 * existing entry is a PMD, we will just leave the PMD in the
 		 * tree and dirty it if necessary.
 		 */
-		void *old = dax_lock_entry(xas, new_entry);
+		old = dax_lock_entry(xas, new_entry);
 		WARN_ON_ONCE(old != xa_mk_value(xa_to_value(entry) |
 					DAX_LOCKED));
 		entry = new_entry;
diff -druNp --no-dereference linux-libre-5.2-rc7-gnu/fs/Kconfig linux-libre-5.2-gnu/fs/Kconfig
--- linux-libre-5.2-rc7-gnu/fs/Kconfig	2019-06-29 23:25:36.000000000 -0400
+++ linux-libre-5.2-gnu/fs/Kconfig	2019-07-07 18:41:56.000000000 -0400
@@ -11,7 +11,6 @@ config DCACHE_WORD_ACCESS
 
 config VALIDATE_FS_PARSER
 	bool "Validate filesystem parameter description"
-	default y
 	help
 	  Enable this to perform validation of the parameter description for a
 	  filesystem when it is registered.
diff -druNp --no-dereference linux-libre-5.2-rc7-gnu/fs/namespace.c linux-libre-5.2-gnu/fs/namespace.c
--- linux-libre-5.2-rc7-gnu/fs/namespace.c	2019-06-29 23:25:36.000000000 -0400
+++ linux-libre-5.2-gnu/fs/namespace.c	2019-07-07 18:41:56.000000000 -0400
@@ -2596,11 +2596,12 @@ static int do_move_mount(struct path *ol
 	if (!check_mnt(p))
 		goto out;
 
-	/* The thing moved should be either ours or completely unattached. */
-	if (attached && !check_mnt(old))
+	/* The thing moved must be mounted... */
+	if (!is_mounted(&old->mnt))
 		goto out;
 
-	if (!attached && !(ns && is_anon_ns(ns)))
+	/* ... and either ours or the root of anon namespace */
+	if (!(attached ? check_mnt(old) : is_anon_ns(ns)))
 		goto out;
 
 	if (old->mnt.mnt_flags & MNT_LOCKED)
diff -druNp --no-dereference linux-libre-5.2-rc7-gnu/fs/nfsd/nfs4state.c linux-libre-5.2-gnu/fs/nfsd/nfs4state.c
--- linux-libre-5.2-rc7-gnu/fs/nfsd/nfs4state.c	2019-06-29 23:25:36.000000000 -0400
+++ linux-libre-5.2-gnu/fs/nfsd/nfs4state.c	2019-07-07 18:41:56.000000000 -0400
@@ -1563,7 +1563,7 @@ static u32 nfsd4_get_drc_mem(struct nfsd
 	 * Never use more than a third of the remaining memory,
 	 * unless it's the only way to give this client a slot:
 	 */
-	avail = clamp_t(int, avail, slotsize, total_avail/3);
+	avail = clamp_t(unsigned long, avail, slotsize, total_avail/3);
 	num = min_t(int, num, avail / slotsize);
 	nfsd_drc_mem_used += num * slotsize;
 	spin_unlock(&nfsd_drc_lock);
diff -druNp --no-dereference linux-libre-5.2-rc7-gnu/fs/userfaultfd.c linux-libre-5.2-gnu/fs/userfaultfd.c
--- linux-libre-5.2-rc7-gnu/fs/userfaultfd.c	2019-06-29 23:25:36.000000000 -0400
+++ linux-libre-5.2-gnu/fs/userfaultfd.c	2019-07-07 18:41:56.000000000 -0400
@@ -40,6 +40,16 @@ enum userfaultfd_state {
 /*
  * Start with fault_pending_wqh and fault_wqh so they're more likely
  * to be in the same cacheline.
+ *
+ * Locking order:
+ *	fd_wqh.lock
+ *		fault_pending_wqh.lock
+ *			fault_wqh.lock
+ *		event_wqh.lock
+ *
+ * To avoid deadlocks, IRQs must be disabled when taking any of the above locks,
+ * since fd_wqh.lock is taken by aio_poll() while it's holding a lock that's
+ * also taken in IRQ context.
  */
 struct userfaultfd_ctx {
 	/* waitqueue head for the pending (i.e. not read) userfaults */
@@ -458,7 +468,7 @@ vm_fault_t handle_userfault(struct vm_fa
 	blocking_state = return_to_userland ? TASK_INTERRUPTIBLE :
 			 TASK_KILLABLE;
 
-	spin_lock(&ctx->fault_pending_wqh.lock);
+	spin_lock_irq(&ctx->fault_pending_wqh.lock);
 	/*
 	 * After the __add_wait_queue the uwq is visible to userland
 	 * through poll/read().
@@ -470,7 +480,7 @@ vm_fault_t handle_userfault(struct vm_fa
 	 * __add_wait_queue.
 	 */
 	set_current_state(blocking_state);
-	spin_unlock(&ctx->fault_pending_wqh.lock);
+	spin_unlock_irq(&ctx->fault_pending_wqh.lock);
 
 	if (!is_vm_hugetlb_page(vmf->vma))
 		must_wait = userfaultfd_must_wait(ctx, vmf->address, vmf->flags,
@@ -552,13 +562,13 @@ vm_fault_t handle_userfault(struct vm_fa
 	 * kernel stack can be released after the list_del_init.
 	 */
 	if (!list_empty_careful(&uwq.wq.entry)) {
-		spin_lock(&ctx->fault_pending_wqh.lock);
+		spin_lock_irq(&ctx->fault_pending_wqh.lock);
 		/*
 		 * No need of list_del_init(), the uwq on the stack
 		 * will be freed shortly anyway.
 		 */
 		list_del(&uwq.wq.entry);
-		spin_unlock(&ctx->fault_pending_wqh.lock);
+		spin_unlock_irq(&ctx->fault_pending_wqh.lock);
 	}
 
 	/*
@@ -583,7 +593,7 @@ static void userfaultfd_event_wait_compl
 	init_waitqueue_entry(&ewq->wq, current);
 	release_new_ctx = NULL;
 
-	spin_lock(&ctx->event_wqh.lock);
+	spin_lock_irq(&ctx->event_wqh.lock);
 	/*
 	 * After the __add_wait_queue the uwq is visible to userland
 	 * through poll/read().
@@ -613,15 +623,15 @@ static void userfaultfd_event_wait_compl
 			break;
 		}
 
-		spin_unlock(&ctx->event_wqh.lock);
+		spin_unlock_irq(&ctx->event_wqh.lock);
 
 		wake_up_poll(&ctx->fd_wqh, EPOLLIN);
 		schedule();
 
-		spin_lock(&ctx->event_wqh.lock);
+		spin_lock_irq(&ctx->event_wqh.lock);
 	}
 	__set_current_state(TASK_RUNNING);
-	spin_unlock(&ctx->event_wqh.lock);
+	spin_unlock_irq(&ctx->event_wqh.lock);
 
 	if (release_new_ctx) {
 		struct vm_area_struct *vma;
@@ -918,10 +928,10 @@ wakeup:
 	 * the last page faults that may have been already waiting on
 	 * the fault_*wqh.
 	 */
-	spin_lock(&ctx->fault_pending_wqh.lock);
+	spin_lock_irq(&ctx->fault_pending_wqh.lock);
 	__wake_up_locked_key(&ctx->fault_pending_wqh, TASK_NORMAL, &range);
 	__wake_up(&ctx->fault_wqh, TASK_NORMAL, 1, &range);
-	spin_unlock(&ctx->fault_pending_wqh.lock);
+	spin_unlock_irq(&ctx->fault_pending_wqh.lock);
 
 	/* Flush pending events that may still wait on event_wqh */
 	wake_up_all(&ctx->event_wqh);
@@ -1134,7 +1144,7 @@ static ssize_t userfaultfd_ctx_read(stru
 
 	if (!ret && msg->event == UFFD_EVENT_FORK) {
 		ret = resolve_userfault_fork(ctx, fork_nctx, msg);
-		spin_lock(&ctx->event_wqh.lock);
+		spin_lock_irq(&ctx->event_wqh.lock);
 		if (!list_empty(&fork_event)) {
 			/*
 			 * The fork thread didn't abort, so we can
@@ -1180,7 +1190,7 @@ static ssize_t userfaultfd_ctx_read(stru
 			if (ret)
 				userfaultfd_ctx_put(fork_nctx);
 		}
-		spin_unlock(&ctx->event_wqh.lock);
+		spin_unlock_irq(&ctx->event_wqh.lock);
 	}
 
 	return ret;
@@ -1219,14 +1229,14 @@ static ssize_t userfaultfd_read(struct f
 static void __wake_userfault(struct userfaultfd_ctx *ctx,
 			     struct userfaultfd_wake_range *range)
 {
-	spin_lock(&ctx->fault_pending_wqh.lock);
+	spin_lock_irq(&ctx->fault_pending_wqh.lock);
 	/* wake all in the range and autoremove */
 	if (waitqueue_active(&ctx->fault_pending_wqh))
 		__wake_up_locked_key(&ctx->fault_pending_wqh, TASK_NORMAL,
 				     range);
 	if (waitqueue_active(&ctx->fault_wqh))
 		__wake_up(&ctx->fault_wqh, TASK_NORMAL, 1, range);
-	spin_unlock(&ctx->fault_pending_wqh.lock);
+	spin_unlock_irq(&ctx->fault_pending_wqh.lock);
 }
 
 static __always_inline void wake_userfault(struct userfaultfd_ctx *ctx,
@@ -1881,7 +1891,7 @@ static void userfaultfd_show_fdinfo(stru
 	wait_queue_entry_t *wq;
 	unsigned long pending = 0, total = 0;
 
-	spin_lock(&ctx->fault_pending_wqh.lock);
+	spin_lock_irq(&ctx->fault_pending_wqh.lock);
 	list_for_each_entry(wq, &ctx->fault_pending_wqh.head, entry) {
 		pending++;
 		total++;
@@ -1889,7 +1899,7 @@ static void userfaultfd_show_fdinfo(stru
 	list_for_each_entry(wq, &ctx->fault_wqh.head, entry) {
 		total++;
 	}
-	spin_unlock(&ctx->fault_pending_wqh.lock);
+	spin_unlock_irq(&ctx->fault_pending_wqh.lock);
 
 	/*
 	 * If more protocols will be added, there will be all shown
diff -druNp --no-dereference linux-libre-5.2-rc7-gnu/include/linux/device.h linux-libre-5.2-gnu/include/linux/device.h
--- linux-libre-5.2-rc7-gnu/include/linux/device.h	2019-06-29 23:25:36.000000000 -0400
+++ linux-libre-5.2-gnu/include/linux/device.h	2019-07-07 18:41:56.000000000 -0400
@@ -704,7 +704,8 @@ extern unsigned long devm_get_free_pages
 					 gfp_t gfp_mask, unsigned int order);
 extern void devm_free_pages(struct device *dev, unsigned long addr);
 
-void __iomem *devm_ioremap_resource(struct device *dev, struct resource *res);
+void __iomem *devm_ioremap_resource(struct device *dev,
+				    const struct resource *res);
 
 void __iomem *devm_of_iomap(struct device *dev,
 			    struct device_node *node, int index,
diff -druNp --no-dereference linux-libre-5.2-rc7-gnu/include/linux/pagemap.h linux-libre-5.2-gnu/include/linux/pagemap.h
--- linux-libre-5.2-rc7-gnu/include/linux/pagemap.h	2019-06-29 23:25:36.000000000 -0400
+++ linux-libre-5.2-gnu/include/linux/pagemap.h	2019-07-07 18:41:56.000000000 -0400
@@ -333,19 +333,6 @@ static inline struct page *grab_cache_pa
 			mapping_gfp_mask(mapping));
 }
 
-static inline struct page *find_subpage(struct page *page, pgoff_t offset)
-{
-	unsigned long mask;
-
-	if (PageHuge(page))
-		return page;
-
-	VM_BUG_ON_PAGE(PageTail(page), page);
-
-	mask = (1UL << compound_order(page)) - 1;
-	return page + (offset & mask);
-}
-
 struct page *find_get_entry(struct address_space *mapping, pgoff_t offset);
 struct page *find_lock_entry(struct address_space *mapping, pgoff_t offset);
 unsigned find_get_entries(struct address_space *mapping, pgoff_t start,
diff -druNp --no-dereference linux-libre-5.2-rc7-gnu/kernel/fork.c linux-libre-5.2-gnu/kernel/fork.c
--- linux-libre-5.2-rc7-gnu/kernel/fork.c	2019-06-29 23:25:36.000000000 -0400
+++ linux-libre-5.2-gnu/kernel/fork.c	2019-07-07 18:41:56.000000000 -0400
@@ -2036,6 +2036,7 @@ static __latent_entropy struct task_stru
 					      O_RDWR | O_CLOEXEC);
 		if (IS_ERR(pidfile)) {
 			put_unused_fd(pidfd);
+			retval = PTR_ERR(pidfile);
 			goto bad_fork_free_pid;
 		}
 		get_pid(pid);	/* held by pidfile now */
diff -druNp --no-dereference linux-libre-5.2-rc7-gnu/kernel/ptrace.c linux-libre-5.2-gnu/kernel/ptrace.c
--- linux-libre-5.2-rc7-gnu/kernel/ptrace.c	2019-06-29 23:25:36.000000000 -0400
+++ linux-libre-5.2-gnu/kernel/ptrace.c	2019-07-07 18:41:56.000000000 -0400
@@ -79,9 +79,7 @@ void __ptrace_link(struct task_struct *c
  */
 static void ptrace_link(struct task_struct *child, struct task_struct *new_parent)
 {
-	rcu_read_lock();
-	__ptrace_link(child, new_parent, __task_cred(new_parent));
-	rcu_read_unlock();
+	__ptrace_link(child, new_parent, current_cred());
 }
 
 /**
diff -druNp --no-dereference linux-libre-5.2-rc7-gnu/kernel/trace/ftrace.c linux-libre-5.2-gnu/kernel/trace/ftrace.c
--- linux-libre-5.2-rc7-gnu/kernel/trace/ftrace.c	2019-06-29 23:25:36.000000000 -0400
+++ linux-libre-5.2-gnu/kernel/trace/ftrace.c	2019-07-07 18:41:56.000000000 -0400
@@ -34,7 +34,6 @@
 #include <linux/hash.h>
 #include <linux/rcupdate.h>
 #include <linux/kprobes.h>
-#include <linux/memory.h>
 
 #include <trace/events/sched.h>
 
@@ -2611,12 +2610,10 @@ static void ftrace_run_update_code(int c
 {
 	int ret;
 
-	mutex_lock(&text_mutex);
-
 	ret = ftrace_arch_code_modify_prepare();
 	FTRACE_WARN_ON(ret);
 	if (ret)
-		goto out_unlock;
+		return;
 
 	/*
 	 * By default we use stop_machine() to modify the code.
@@ -2628,9 +2625,6 @@ static void ftrace_run_update_code(int c
 
 	ret = ftrace_arch_code_modify_post_process();
 	FTRACE_WARN_ON(ret);
-
-out_unlock:
-	mutex_unlock(&text_mutex);
 }
 
 static void ftrace_run_modify_code(struct ftrace_ops *ops, int command,
@@ -5784,7 +5778,6 @@ void ftrace_module_enable(struct module
 	struct ftrace_page *pg;
 
 	mutex_lock(&ftrace_lock);
-	mutex_lock(&text_mutex);
 
 	if (ftrace_disabled)
 		goto out_unlock;
@@ -5846,7 +5839,6 @@ void ftrace_module_enable(struct module
 		ftrace_arch_code_modify_post_process();
 
  out_unlock:
-	mutex_unlock(&text_mutex);
 	mutex_unlock(&ftrace_lock);
 
 	process_cached_mods(mod->name);
diff -druNp --no-dereference linux-libre-5.2-rc7-gnu/kernel/trace/trace.c linux-libre-5.2-gnu/kernel/trace/trace.c
--- linux-libre-5.2-rc7-gnu/kernel/trace/trace.c	2019-06-29 23:25:36.000000000 -0400
+++ linux-libre-5.2-gnu/kernel/trace/trace.c	2019-07-07 18:41:56.000000000 -0400
@@ -6719,11 +6719,13 @@ tracing_snapshot_write(struct file *filp
 			break;
 		}
 #endif
-		if (!tr->allocated_snapshot) {
+		if (tr->allocated_snapshot)
+			ret = resize_buffer_duplicate_size(&tr->max_buffer,
+					&tr->trace_buffer, iter->cpu_file);
+		else
 			ret = tracing_alloc_snapshot_instance(tr);
-			if (ret < 0)
-				break;
-		}
+		if (ret < 0)
+			break;
 		local_irq_disable();
 		/* Now, we're going to swap */
 		if (iter->cpu_file == RING_BUFFER_ALL_CPUS)
@@ -7126,12 +7128,24 @@ static ssize_t tracing_err_log_write(str
 	return count;
 }
 
+static int tracing_err_log_release(struct inode *inode, struct file *file)
+{
+	struct trace_array *tr = inode->i_private;
+
+	trace_array_put(tr);
+
+	if (file->f_mode & FMODE_READ)
+		seq_release(inode, file);
+
+	return 0;
+}
+
 static const struct file_operations tracing_err_log_fops = {
 	.open           = tracing_err_log_open,
 	.write		= tracing_err_log_write,
 	.read           = seq_read,
 	.llseek         = seq_lseek,
-	.release	= tracing_release_generic_tr,
+	.release        = tracing_err_log_release,
 };
 
 static int tracing_buffers_open(struct inode *inode, struct file *filp)
diff -druNp --no-dereference linux-libre-5.2-rc7-gnu/lib/devres.c linux-libre-5.2-gnu/lib/devres.c
--- linux-libre-5.2-rc7-gnu/lib/devres.c	2019-06-29 23:25:36.000000000 -0400
+++ linux-libre-5.2-gnu/lib/devres.c	2019-07-07 18:41:56.000000000 -0400
@@ -131,7 +131,8 @@ EXPORT_SYMBOL(devm_iounmap);
  *	if (IS_ERR(base))
  *		return PTR_ERR(base);
  */
-void __iomem *devm_ioremap_resource(struct device *dev, struct resource *res)
+void __iomem *devm_ioremap_resource(struct device *dev,
+				    const struct resource *res)
 {
 	resource_size_t size;
 	void __iomem *dest_ptr;
diff -druNp --no-dereference linux-libre-5.2-rc7-gnu/lib/mpi/mpi-pow.c linux-libre-5.2-gnu/lib/mpi/mpi-pow.c
--- linux-libre-5.2-rc7-gnu/lib/mpi/mpi-pow.c	2019-06-29 23:25:36.000000000 -0400
+++ linux-libre-5.2-gnu/lib/mpi/mpi-pow.c	2019-07-07 18:41:56.000000000 -0400
@@ -24,6 +24,7 @@
 int mpi_powm(MPI res, MPI base, MPI exp, MPI mod)
 {
 	mpi_ptr_t mp_marker = NULL, bp_marker = NULL, ep_marker = NULL;
+	struct karatsuba_ctx karactx = {};
 	mpi_ptr_t xp_marker = NULL;
 	mpi_ptr_t tspace = NULL;
 	mpi_ptr_t rp, ep, mp, bp;
@@ -150,13 +151,11 @@ int mpi_powm(MPI res, MPI base, MPI exp,
 		int c;
 		mpi_limb_t e;
 		mpi_limb_t carry_limb;
-		struct karatsuba_ctx karactx;
 
 		xp = xp_marker = mpi_alloc_limb_space(2 * (msize + 1));
 		if (!xp)
 			goto enomem;
 
-		memset(&karactx, 0, sizeof karactx);
 		negative_result = (ep[0] & 1) && base->sign;
 
 		i = esize - 1;
@@ -281,8 +280,6 @@ int mpi_powm(MPI res, MPI base, MPI exp,
 		if (mod_shift_cnt)
 			mpihelp_rshift(rp, rp, rsize, mod_shift_cnt);
 		MPN_NORMALIZE(rp, rsize);
-
-		mpihelp_release_karatsuba_ctx(&karactx);
 	}
 
 	if (negative_result && rsize) {
@@ -299,6 +296,7 @@ int mpi_powm(MPI res, MPI base, MPI exp,
 leave:
 	rc = 0;
 enomem:
+	mpihelp_release_karatsuba_ctx(&karactx);
 	if (assign_rp)
 		mpi_assign_limb_space(res, rp, size);
 	if (mp_marker)
diff -druNp --no-dereference linux-libre-5.2-rc7-gnu/MAINTAINERS linux-libre-5.2-gnu/MAINTAINERS
--- linux-libre-5.2-rc7-gnu/MAINTAINERS	2019-06-29 23:25:36.000000000 -0400
+++ linux-libre-5.2-gnu/MAINTAINERS	2019-07-07 18:41:56.000000000 -0400
@@ -7810,7 +7810,7 @@ INGENIC JZ4780 NAND DRIVER
 M:	Harvey Hunt <harveyhuntnexus@gmail.com>
 L:	linux-mtd@lists.infradead.org
 S:	Maintained
-F:	drivers/mtd/nand/raw/jz4780_*
+F:	drivers/mtd/nand/raw/ingenic/
 
 INOTIFY
 M:	Jan Kara <jack@suse.cz>
@@ -15503,6 +15503,7 @@ F:	drivers/dma/tegra*
 
 TEGRA I2C DRIVER
 M:	Laxman Dewangan <ldewangan@nvidia.com>
+R:	Dmitry Osipenko <digetx@gmail.com>
 S:	Supported
 F:	drivers/i2c/busses/i2c-tegra.c
 
diff -druNp --no-dereference linux-libre-5.2-rc7-gnu/Makefile linux-libre-5.2-gnu/Makefile
--- linux-libre-5.2-rc7-gnu/Makefile	2019-07-02 01:58:45.000000000 -0400
+++ linux-libre-5.2-gnu/Makefile	2019-07-07 20:37:31.000000000 -0400
@@ -2,7 +2,7 @@
 VERSION = 5
 PATCHLEVEL = 2
 SUBLEVEL = 0
-EXTRAVERSION = -rc7-gnu
+EXTRAVERSION = -gnu
 NAME = Bobtail Squid
 
 # *DOCUMENTATION*
diff -druNp --no-dereference linux-libre-5.2-rc7-gnu/mm/filemap.c linux-libre-5.2-gnu/mm/filemap.c
--- linux-libre-5.2-rc7-gnu/mm/filemap.c	2019-06-29 23:25:36.000000000 -0400
+++ linux-libre-5.2-gnu/mm/filemap.c	2019-07-07 18:41:56.000000000 -0400
@@ -281,11 +281,11 @@ EXPORT_SYMBOL(delete_from_page_cache);
  * @pvec: pagevec with pages to delete
  *
  * The function walks over mapping->i_pages and removes pages passed in @pvec
- * from the mapping. The function expects @pvec to be sorted by page index
- * and is optimised for it to be dense.
+ * from the mapping. The function expects @pvec to be sorted by page index.
  * It tolerates holes in @pvec (mapping entries at those indices are not
  * modified). The function expects only THP head pages to be present in the
- * @pvec.
+ * @pvec and takes care to delete all corresponding tail pages from the
+ * mapping as well.
  *
  * The function expects the i_pages lock to be held.
  */
@@ -294,44 +294,40 @@ static void page_cache_delete_batch(stru
 {
 	XA_STATE(xas, &mapping->i_pages, pvec->pages[0]->index);
 	int total_pages = 0;
-	int i = 0;
+	int i = 0, tail_pages = 0;
 	struct page *page;
 
 	mapping_set_update(&xas, mapping);
 	xas_for_each(&xas, page, ULONG_MAX) {
-		if (i >= pagevec_count(pvec))
+		if (i >= pagevec_count(pvec) && !tail_pages)
 			break;
-
-		/* A swap/dax/shadow entry got inserted? Skip it. */
 		if (xa_is_value(page))
 			continue;
-		/*
-		 * A page got inserted in our range? Skip it. We have our
-		 * pages locked so they are protected from being removed.
-		 * If we see a page whose index is higher than ours, it
-		 * means our page has been removed, which shouldn't be
-		 * possible because we're holding the PageLock.
-		 */
-		if (page != pvec->pages[i]) {
-			VM_BUG_ON_PAGE(page->index > pvec->pages[i]->index,
-					page);
-			continue;
-		}
-
-		WARN_ON_ONCE(!PageLocked(page));
-
-		if (page->index == xas.xa_index)
+		if (!tail_pages) {
+			/*
+			 * Some page got inserted in our range? Skip it. We
+			 * have our pages locked so they are protected from
+			 * being removed.
+			 */
+			if (page != pvec->pages[i]) {
+				VM_BUG_ON_PAGE(page->index >
+						pvec->pages[i]->index, page);
+				continue;
+			}
+			WARN_ON_ONCE(!PageLocked(page));
+			if (PageTransHuge(page) && !PageHuge(page))
+				tail_pages = HPAGE_PMD_NR - 1;
 			page->mapping = NULL;
-		/* Leave page->index set: truncation lookup relies on it */
-
-		/*
-		 * Move to the next page in the vector if this is a regular
-		 * page or the index is of the last sub-page of this compound
-		 * page.
-		 */
-		if (page->index + (1UL << compound_order(page)) - 1 ==
-				xas.xa_index)
+			/*
+			 * Leave page->index set: truncation lookup relies
+			 * upon it
+			 */
 			i++;
+		} else {
+			VM_BUG_ON_PAGE(page->index + HPAGE_PMD_NR - tail_pages
+					!= pvec->pages[i]->index, page);
+			tail_pages--;
+		}
 		xas_store(&xas, NULL);
 		total_pages++;
 	}
@@ -1498,7 +1494,7 @@ EXPORT_SYMBOL(page_cache_prev_miss);
 struct page *find_get_entry(struct address_space *mapping, pgoff_t offset)
 {
 	XA_STATE(xas, &mapping->i_pages, offset);
-	struct page *page;
+	struct page *head, *page;
 
 	rcu_read_lock();
 repeat:
@@ -1513,19 +1509,25 @@ repeat:
 	if (!page || xa_is_value(page))
 		goto out;
 
-	if (!page_cache_get_speculative(page))
+	head = compound_head(page);
+	if (!page_cache_get_speculative(head))
 		goto repeat;
 
+	/* The page was split under us? */
+	if (compound_head(page) != head) {
+		put_page(head);
+		goto repeat;
+	}
+
 	/*
-	 * Has the page moved or been split?
+	 * Has the page moved?
 	 * This is part of the lockless pagecache protocol. See
 	 * include/linux/pagemap.h for details.
 	 */
 	if (unlikely(page != xas_reload(&xas))) {
-		put_page(page);
+		put_page(head);
 		goto repeat;
 	}
-	page = find_subpage(page, offset);
 out:
 	rcu_read_unlock();
 
@@ -1707,6 +1709,7 @@ unsigned find_get_entries(struct address
 
 	rcu_read_lock();
 	xas_for_each(&xas, page, ULONG_MAX) {
+		struct page *head;
 		if (xas_retry(&xas, page))
 			continue;
 		/*
@@ -1717,13 +1720,17 @@ unsigned find_get_entries(struct address
 		if (xa_is_value(page))
 			goto export;
 
-		if (!page_cache_get_speculative(page))
+		head = compound_head(page);
+		if (!page_cache_get_speculative(head))
 			goto retry;
 
-		/* Has the page moved or been split? */
+		/* The page was split under us? */
+		if (compound_head(page) != head)
+			goto put_page;
+
+		/* Has the page moved? */
 		if (unlikely(page != xas_reload(&xas)))
 			goto put_page;
-		page = find_subpage(page, xas.xa_index);
 
 export:
 		indices[ret] = xas.xa_index;
@@ -1732,7 +1739,7 @@ export:
 			break;
 		continue;
 put_page:
-		put_page(page);
+		put_page(head);
 retry:
 		xas_reset(&xas);
 	}
@@ -1774,27 +1781,33 @@ unsigned find_get_pages_range(struct add
 
 	rcu_read_lock();
 	xas_for_each(&xas, page, end) {
+		struct page *head;
 		if (xas_retry(&xas, page))
 			continue;
 		/* Skip over shadow, swap and DAX entries */
 		if (xa_is_value(page))
 			continue;
 
-		if (!page_cache_get_speculative(page))
+		head = compound_head(page);
+		if (!page_cache_get_speculative(head))
 			goto retry;
 
-		/* Has the page moved or been split? */
+		/* The page was split under us? */
+		if (compound_head(page) != head)
+			goto put_page;
+
+		/* Has the page moved? */
 		if (unlikely(page != xas_reload(&xas)))
 			goto put_page;
 
-		pages[ret] = find_subpage(page, xas.xa_index);
+		pages[ret] = page;
 		if (++ret == nr_pages) {
 			*start = xas.xa_index + 1;
 			goto out;
 		}
 		continue;
 put_page:
-		put_page(page);
+		put_page(head);
 retry:
 		xas_reset(&xas);
 	}
@@ -1839,6 +1852,7 @@ unsigned find_get_pages_contig(struct ad
 
 	rcu_read_lock();
 	for (page = xas_load(&xas); page; page = xas_next(&xas)) {
+		struct page *head;
 		if (xas_retry(&xas, page))
 			continue;
 		/*
@@ -1848,19 +1862,24 @@ unsigned find_get_pages_contig(struct ad
 		if (xa_is_value(page))
 			break;
 
-		if (!page_cache_get_speculative(page))
+		head = compound_head(page);
+		if (!page_cache_get_speculative(head))
 			goto retry;
 
-		/* Has the page moved or been split? */
+		/* The page was split under us? */
+		if (compound_head(page) != head)
+			goto put_page;
+
+		/* Has the page moved? */
 		if (unlikely(page != xas_reload(&xas)))
 			goto put_page;
 
-		pages[ret] = find_subpage(page, xas.xa_index);
+		pages[ret] = page;
 		if (++ret == nr_pages)
 			break;
 		continue;
 put_page:
-		put_page(page);
+		put_page(head);
 retry:
 		xas_reset(&xas);
 	}
@@ -1896,6 +1915,7 @@ unsigned find_get_pages_range_tag(struct
 
 	rcu_read_lock();
 	xas_for_each_marked(&xas, page, end, tag) {
+		struct page *head;
 		if (xas_retry(&xas, page))
 			continue;
 		/*
@@ -1906,21 +1926,26 @@ unsigned find_get_pages_range_tag(struct
 		if (xa_is_value(page))
 			continue;
 
-		if (!page_cache_get_speculative(page))
+		head = compound_head(page);
+		if (!page_cache_get_speculative(head))
 			goto retry;
 
-		/* Has the page moved or been split? */
+		/* The page was split under us? */
+		if (compound_head(page) != head)
+			goto put_page;
+
+		/* Has the page moved? */
 		if (unlikely(page != xas_reload(&xas)))
 			goto put_page;
 
-		pages[ret] = find_subpage(page, xas.xa_index);
+		pages[ret] = page;
 		if (++ret == nr_pages) {
 			*index = xas.xa_index + 1;
 			goto out;
 		}
 		continue;
 put_page:
-		put_page(page);
+		put_page(head);
 retry:
 		xas_reset(&xas);
 	}
@@ -2603,7 +2628,7 @@ void filemap_map_pages(struct vm_fault *
 	pgoff_t last_pgoff = start_pgoff;
 	unsigned long max_idx;
 	XA_STATE(xas, &mapping->i_pages, start_pgoff);
-	struct page *page;
+	struct page *head, *page;
 
 	rcu_read_lock();
 	xas_for_each(&xas, page, end_pgoff) {
@@ -2612,19 +2637,24 @@ void filemap_map_pages(struct vm_fault *
 		if (xa_is_value(page))
 			goto next;
 
+		head = compound_head(page);
+
 		/*
 		 * Check for a locked page first, as a speculative
 		 * reference may adversely influence page migration.
 		 */
-		if (PageLocked(page))
+		if (PageLocked(head))
 			goto next;
-		if (!page_cache_get_speculative(page))
+		if (!page_cache_get_speculative(head))
 			goto next;
 
-		/* Has the page moved or been split? */
+		/* The page was split under us? */
+		if (compound_head(page) != head)
+			goto skip;
+
+		/* Has the page moved? */
 		if (unlikely(page != xas_reload(&xas)))
 			goto skip;
-		page = find_subpage(page, xas.xa_index);
 
 		if (!PageUptodate(page) ||
 				PageReadahead(page) ||
diff -druNp --no-dereference linux-libre-5.2-rc7-gnu/mm/huge_memory.c linux-libre-5.2-gnu/mm/huge_memory.c
--- linux-libre-5.2-rc7-gnu/mm/huge_memory.c	2019-06-29 23:25:36.000000000 -0400
+++ linux-libre-5.2-gnu/mm/huge_memory.c	2019-07-07 18:41:56.000000000 -0400
@@ -2496,9 +2496,6 @@ static void __split_huge_page(struct pag
 			if (IS_ENABLED(CONFIG_SHMEM) && PageSwapBacked(head))
 				shmem_uncharge(head->mapping->host, 1);
 			put_page(head + i);
-		} else if (!PageAnon(page)) {
-			__xa_store(&head->mapping->i_pages, head[i].index,
-					head + i, 0);
 		}
 	}
 
diff -druNp --no-dereference linux-libre-5.2-rc7-gnu/mm/khugepaged.c linux-libre-5.2-gnu/mm/khugepaged.c
--- linux-libre-5.2-rc7-gnu/mm/khugepaged.c	2019-06-29 23:25:36.000000000 -0400
+++ linux-libre-5.2-gnu/mm/khugepaged.c	2019-07-07 18:41:56.000000000 -0400
@@ -1378,7 +1378,7 @@ static void collapse_shmem(struct mm_str
 				result = SCAN_FAIL;
 				goto xa_locked;
 			}
-			xas_store(&xas, new_page);
+			xas_store(&xas, new_page + (index % HPAGE_PMD_NR));
 			nr_none++;
 			continue;
 		}
@@ -1454,7 +1454,7 @@ static void collapse_shmem(struct mm_str
 		list_add_tail(&page->lru, &pagelist);
 
 		/* Finally, replace with the new page. */
-		xas_store(&xas, new_page);
+		xas_store(&xas, new_page + (index % HPAGE_PMD_NR));
 		continue;
 out_unlock:
 		unlock_page(page);
diff -druNp --no-dereference linux-libre-5.2-rc7-gnu/mm/memfd.c linux-libre-5.2-gnu/mm/memfd.c
--- linux-libre-5.2-rc7-gnu/mm/memfd.c	2019-06-29 23:25:36.000000000 -0400
+++ linux-libre-5.2-gnu/mm/memfd.c	2019-07-07 18:41:56.000000000 -0400
@@ -39,7 +39,6 @@ static void memfd_tag_pins(struct xa_sta
 	xas_for_each(xas, page, ULONG_MAX) {
 		if (xa_is_value(page))
 			continue;
-		page = find_subpage(page, xas->xa_index);
 		if (page_count(page) - page_mapcount(page) > 1)
 			xas_set_mark(xas, MEMFD_TAG_PINNED);
 
@@ -89,7 +88,6 @@ static int memfd_wait_for_pins(struct ad
 			bool clear = true;
 			if (xa_is_value(page))
 				continue;
-			page = find_subpage(page, xas.xa_index);
 			if (page_count(page) - page_mapcount(page) != 1) {
 				/*
 				 * On the last scan, we clean up all those tags
diff -druNp --no-dereference linux-libre-5.2-rc7-gnu/mm/migrate.c linux-libre-5.2-gnu/mm/migrate.c
--- linux-libre-5.2-rc7-gnu/mm/migrate.c	2019-06-29 23:25:36.000000000 -0400
+++ linux-libre-5.2-gnu/mm/migrate.c	2019-07-07 18:41:56.000000000 -0400
@@ -463,7 +463,7 @@ int migrate_page_move_mapping(struct add
 
 		for (i = 1; i < HPAGE_PMD_NR; i++) {
 			xas_next(&xas);
-			xas_store(&xas, newpage);
+			xas_store(&xas, newpage + i);
 		}
 	}
 
diff -druNp --no-dereference linux-libre-5.2-rc7-gnu/mm/page_alloc.c linux-libre-5.2-gnu/mm/page_alloc.c
--- linux-libre-5.2-rc7-gnu/mm/page_alloc.c	2019-06-29 23:25:36.000000000 -0400
+++ linux-libre-5.2-gnu/mm/page_alloc.c	2019-07-07 18:41:56.000000000 -0400
@@ -1826,7 +1826,8 @@ deferred_grow_zone(struct zone *zone, un
 						 first_deferred_pfn)) {
 		pgdat->first_deferred_pfn = ULONG_MAX;
 		pgdat_resize_unlock(pgdat, &flags);
-		return true;
+		/* Retry only once. */
+		return first_deferred_pfn != ULONG_MAX;
 	}
 
 	/*
diff -druNp --no-dereference linux-libre-5.2-rc7-gnu/mm/page_io.c linux-libre-5.2-gnu/mm/page_io.c
--- linux-libre-5.2-rc7-gnu/mm/page_io.c	2019-06-29 23:25:36.000000000 -0400
+++ linux-libre-5.2-gnu/mm/page_io.c	2019-07-07 18:41:56.000000000 -0400
@@ -137,8 +137,10 @@ out:
 	unlock_page(page);
 	WRITE_ONCE(bio->bi_private, NULL);
 	bio_put(bio);
-	blk_wake_io_task(waiter);
-	put_task_struct(waiter);
+	if (waiter) {
+		blk_wake_io_task(waiter);
+		put_task_struct(waiter);
+	}
 }
 
 int generic_swapfile_activate(struct swap_info_struct *sis,
@@ -395,11 +397,12 @@ int swap_readpage(struct page *page, boo
 	 * Keep this task valid during swap readpage because the oom killer may
 	 * attempt to access it in the page fault retry time check.
 	 */
-	get_task_struct(current);
-	bio->bi_private = current;
 	bio_set_op_attrs(bio, REQ_OP_READ, 0);
-	if (synchronous)
+	if (synchronous) {
 		bio->bi_opf |= REQ_HIPRI;
+		get_task_struct(current);
+		bio->bi_private = current;
+	}
 	count_vm_event(PSWPIN);
 	bio_get(bio);
 	qc = submit_bio(bio);
diff -druNp --no-dereference linux-libre-5.2-rc7-gnu/mm/shmem.c linux-libre-5.2-gnu/mm/shmem.c
--- linux-libre-5.2-rc7-gnu/mm/shmem.c	2019-06-29 23:25:36.000000000 -0400
+++ linux-libre-5.2-gnu/mm/shmem.c	2019-07-07 18:41:56.000000000 -0400
@@ -614,7 +614,7 @@ static int shmem_add_to_page_cache(struc
 		if (xas_error(&xas))
 			goto unlock;
 next:
-		xas_store(&xas, page);
+		xas_store(&xas, page + i);
 		if (++i < nr) {
 			xas_next(&xas);
 			goto next;
diff -druNp --no-dereference linux-libre-5.2-rc7-gnu/mm/swap_state.c linux-libre-5.2-gnu/mm/swap_state.c
--- linux-libre-5.2-rc7-gnu/mm/swap_state.c	2019-06-29 23:25:36.000000000 -0400
+++ linux-libre-5.2-gnu/mm/swap_state.c	2019-07-07 18:41:56.000000000 -0400
@@ -132,7 +132,7 @@ int add_to_swap_cache(struct page *page,
 		for (i = 0; i < nr; i++) {
 			VM_BUG_ON_PAGE(xas.xa_index != idx + i, page);
 			set_page_private(page + i, entry.val + i);
-			xas_store(&xas, page);
+			xas_store(&xas, page + i);
 			xas_next(&xas);
 		}
 		address_space->nrpages += nr;
@@ -167,7 +167,7 @@ void __delete_from_swap_cache(struct pag
 
 	for (i = 0; i < nr; i++) {
 		void *entry = xas_store(&xas, NULL);
-		VM_BUG_ON_PAGE(entry != page, entry);
+		VM_BUG_ON_PAGE(entry != page + i, entry);
 		set_page_private(page + i, 0);
 		xas_next(&xas);
 	}
diff -druNp --no-dereference linux-libre-5.2-rc7-gnu/mm/vmscan.c linux-libre-5.2-gnu/mm/vmscan.c
--- linux-libre-5.2-rc7-gnu/mm/vmscan.c	2019-06-29 23:25:36.000000000 -0400
+++ linux-libre-5.2-gnu/mm/vmscan.c	2019-07-07 18:41:56.000000000 -0400
@@ -3644,19 +3644,18 @@ out:
 }
 
 /*
- * pgdat->kswapd_classzone_idx is the highest zone index that a recent
- * allocation request woke kswapd for. When kswapd has not woken recently,
- * the value is MAX_NR_ZONES which is not a valid index. This compares a
- * given classzone and returns it or the highest classzone index kswapd
- * was recently woke for.
+ * The pgdat->kswapd_classzone_idx is used to pass the highest zone index to be
+ * reclaimed by kswapd from the waker. If the value is MAX_NR_ZONES which is not
+ * a valid index then either kswapd runs for first time or kswapd couldn't sleep
+ * after previous reclaim attempt (node is still unbalanced). In that case
+ * return the zone index of the previous kswapd reclaim cycle.
  */
 static enum zone_type kswapd_classzone_idx(pg_data_t *pgdat,
-					   enum zone_type classzone_idx)
+					   enum zone_type prev_classzone_idx)
 {
 	if (pgdat->kswapd_classzone_idx == MAX_NR_ZONES)
-		return classzone_idx;
-
-	return max(pgdat->kswapd_classzone_idx, classzone_idx);
+		return prev_classzone_idx;
+	return pgdat->kswapd_classzone_idx;
 }
 
 static void kswapd_try_to_sleep(pg_data_t *pgdat, int alloc_order, int reclaim_order,
@@ -3797,7 +3796,7 @@ kswapd_try_sleep:
 
 		/* Read the new order and classzone_idx */
 		alloc_order = reclaim_order = pgdat->kswapd_order;
-		classzone_idx = kswapd_classzone_idx(pgdat, 0);
+		classzone_idx = kswapd_classzone_idx(pgdat, classzone_idx);
 		pgdat->kswapd_order = 0;
 		pgdat->kswapd_classzone_idx = MAX_NR_ZONES;
 
@@ -3851,8 +3850,12 @@ void wakeup_kswapd(struct zone *zone, gf
 	if (!cpuset_zone_allowed(zone, gfp_flags))
 		return;
 	pgdat = zone->zone_pgdat;
-	pgdat->kswapd_classzone_idx = kswapd_classzone_idx(pgdat,
-							   classzone_idx);
+
+	if (pgdat->kswapd_classzone_idx == MAX_NR_ZONES)
+		pgdat->kswapd_classzone_idx = classzone_idx;
+	else
+		pgdat->kswapd_classzone_idx = max(pgdat->kswapd_classzone_idx,
+						  classzone_idx);
 	pgdat->kswapd_order = max(pgdat->kswapd_order, order);
 	if (!waitqueue_active(&pgdat->kswapd_wait))
 		return;
diff -druNp --no-dereference linux-libre-5.2-rc7-gnu/net/bluetooth/l2cap_core.c linux-libre-5.2-gnu/net/bluetooth/l2cap_core.c
--- linux-libre-5.2-rc7-gnu/net/bluetooth/l2cap_core.c	2019-06-29 23:25:36.000000000 -0400
+++ linux-libre-5.2-gnu/net/bluetooth/l2cap_core.c	2019-07-07 18:41:56.000000000 -0400
@@ -1353,7 +1353,7 @@ static bool l2cap_check_enc_key_size(str
 	 * actually encrypted before enforcing a key size.
 	 */
 	return (!test_bit(HCI_CONN_ENCRYPT, &hcon->flags) ||
-		hcon->enc_key_size > HCI_MIN_ENC_KEY_SIZE);
+		hcon->enc_key_size >= HCI_MIN_ENC_KEY_SIZE);
 }
 
 static void l2cap_do_start(struct l2cap_chan *chan)
diff -druNp --no-dereference linux-libre-5.2-rc7-gnu/net/sunrpc/xprtrdma/svc_rdma_transport.c linux-libre-5.2-gnu/net/sunrpc/xprtrdma/svc_rdma_transport.c
--- linux-libre-5.2-rc7-gnu/net/sunrpc/xprtrdma/svc_rdma_transport.c	2019-06-29 23:25:36.000000000 -0400
+++ linux-libre-5.2-gnu/net/sunrpc/xprtrdma/svc_rdma_transport.c	2019-07-07 18:41:56.000000000 -0400
@@ -211,9 +211,14 @@ static void handle_connect_req(struct rd
 	/* Save client advertised inbound read limit for use later in accept. */
 	newxprt->sc_ord = param->initiator_depth;
 
-	/* Set the local and remote addresses in the transport */
 	sa = (struct sockaddr *)&newxprt->sc_cm_id->route.addr.dst_addr;
 	svc_xprt_set_remote(&newxprt->sc_xprt, sa, svc_addr_len(sa));
+	/* The remote port is arbitrary and not under the control of the
+	 * client ULP. Set it to a fixed value so that the DRC continues
+	 * to be effective after a reconnect.
+	 */
+	rpc_set_port((struct sockaddr *)&newxprt->sc_xprt.xpt_remote, 0);
+
 	sa = (struct sockaddr *)&newxprt->sc_cm_id->route.addr.src_addr;
 	svc_xprt_set_local(&newxprt->sc_xprt, sa, svc_addr_len(sa));
 
diff -druNp --no-dereference linux-libre-5.2-rc7-gnu/sound/core/seq/oss/seq_oss_ioctl.c linux-libre-5.2-gnu/sound/core/seq/oss/seq_oss_ioctl.c
--- linux-libre-5.2-rc7-gnu/sound/core/seq/oss/seq_oss_ioctl.c	2019-06-29 23:25:36.000000000 -0400
+++ linux-libre-5.2-gnu/sound/core/seq/oss/seq_oss_ioctl.c	2019-07-07 18:41:56.000000000 -0400
@@ -49,7 +49,7 @@ static int snd_seq_oss_oob_user(struct s
 	if (copy_from_user(ev, arg, 8))
 		return -EFAULT;
 	memset(&tmpev, 0, sizeof(tmpev));
-	snd_seq_oss_fill_addr(dp, &tmpev, dp->addr.port, dp->addr.client);
+	snd_seq_oss_fill_addr(dp, &tmpev, dp->addr.client, dp->addr.port);
 	tmpev.time.tick = 0;
 	if (! snd_seq_oss_process_event(dp, (union evrec *)ev, &tmpev)) {
 		snd_seq_oss_dispatch(dp, &tmpev, 0, 0);
diff -druNp --no-dereference linux-libre-5.2-rc7-gnu/sound/core/seq/oss/seq_oss_rw.c linux-libre-5.2-gnu/sound/core/seq/oss/seq_oss_rw.c
--- linux-libre-5.2-rc7-gnu/sound/core/seq/oss/seq_oss_rw.c	2019-06-29 23:25:36.000000000 -0400
+++ linux-libre-5.2-gnu/sound/core/seq/oss/seq_oss_rw.c	2019-07-07 18:41:56.000000000 -0400
@@ -161,7 +161,7 @@ insert_queue(struct seq_oss_devinfo *dp,
 	memset(&event, 0, sizeof(event));
 	/* set dummy -- to be sure */
 	event.type = SNDRV_SEQ_EVENT_NOTEOFF;
-	snd_seq_oss_fill_addr(dp, &event, dp->addr.port, dp->addr.client);
+	snd_seq_oss_fill_addr(dp, &event, dp->addr.client, dp->addr.port);
 
 	if (snd_seq_oss_process_event(dp, rec, &event))
 		return 0; /* invalid event - no need to insert queue */
diff -druNp --no-dereference linux-libre-5.2-rc7-gnu/sound/firewire/amdtp-am824.c linux-libre-5.2-gnu/sound/firewire/amdtp-am824.c
--- linux-libre-5.2-rc7-gnu/sound/firewire/amdtp-am824.c	2019-06-29 23:25:36.000000000 -0400
+++ linux-libre-5.2-gnu/sound/firewire/amdtp-am824.c	2019-07-07 18:41:56.000000000 -0400
@@ -320,7 +320,7 @@ static void read_midi_messages(struct am
 	u8 *b;
 
 	for (f = 0; f < frames; f++) {
-		port = (s->data_block_counter + f) % 8;
+		port = (8 - s->tx_first_dbc + s->data_block_counter + f) % 8;
 		b = (u8 *)&buffer[p->midi_position];
 
 		len = b[0] - 0x80;
diff -druNp --no-dereference linux-libre-5.2-rc7-gnu/sound/hda/hdac_device.c linux-libre-5.2-gnu/sound/hda/hdac_device.c
--- linux-libre-5.2-rc7-gnu/sound/hda/hdac_device.c	2019-06-29 23:25:36.000000000 -0400
+++ linux-libre-5.2-gnu/sound/hda/hdac_device.c	2019-07-07 18:41:56.000000000 -0400
@@ -400,27 +400,33 @@ static void setup_fg_nodes(struct hdac_d
 int snd_hdac_refresh_widgets(struct hdac_device *codec, bool sysfs)
 {
 	hda_nid_t start_nid;
-	int nums, err;
+	int nums, err = 0;
 
+	/*
+	 * Serialize against multiple threads trying to update the sysfs
+	 * widgets array.
+	 */
+	mutex_lock(&codec->widget_lock);
 	nums = snd_hdac_get_sub_nodes(codec, codec->afg, &start_nid);
 	if (!start_nid || nums <= 0 || nums >= 0xff) {
 		dev_err(&codec->dev, "cannot read sub nodes for FG 0x%02x\n",
 			codec->afg);
-		return -EINVAL;
+		err = -EINVAL;
+		goto unlock;
 	}
 
 	if (sysfs) {
-		mutex_lock(&codec->widget_lock);
 		err = hda_widget_sysfs_reinit(codec, start_nid, nums);
-		mutex_unlock(&codec->widget_lock);
 		if (err < 0)
-			return err;
+			goto unlock;
 	}
 
 	codec->num_nodes = nums;
 	codec->start_nid = start_nid;
 	codec->end_nid = start_nid + nums;
-	return 0;
+unlock:
+	mutex_unlock(&codec->widget_lock);
+	return err;
 }
 EXPORT_SYMBOL_GPL(snd_hdac_refresh_widgets);
 
diff -druNp --no-dereference linux-libre-5.2-rc7-gnu/sound/pci/hda/patch_realtek.c linux-libre-5.2-gnu/sound/pci/hda/patch_realtek.c
--- linux-libre-5.2-rc7-gnu/sound/pci/hda/patch_realtek.c	2019-06-29 23:25:36.000000000 -0400
+++ linux-libre-5.2-gnu/sound/pci/hda/patch_realtek.c	2019-07-07 18:41:56.000000000 -0400
@@ -2448,9 +2448,10 @@ static const struct snd_pci_quirk alc882
 	SND_PCI_QUIRK(0x1558, 0x9501, "Clevo P950HR", ALC1220_FIXUP_CLEVO_P950),
 	SND_PCI_QUIRK(0x1558, 0x95e1, "Clevo P95xER", ALC1220_FIXUP_CLEVO_P950),
 	SND_PCI_QUIRK(0x1558, 0x95e2, "Clevo P950ER", ALC1220_FIXUP_CLEVO_P950),
-	SND_PCI_QUIRK(0x1558, 0x96e1, "System76 Oryx Pro (oryp5)", ALC1220_FIXUP_CLEVO_PB51ED_PINS),
-	SND_PCI_QUIRK(0x1558, 0x97e1, "System76 Oryx Pro (oryp5)", ALC1220_FIXUP_CLEVO_PB51ED_PINS),
-	SND_PCI_QUIRK(0x1558, 0x65d1, "Tuxedo Book XC1509", ALC1220_FIXUP_CLEVO_PB51ED_PINS),
+	SND_PCI_QUIRK(0x1558, 0x96e1, "Clevo P960[ER][CDFN]-K", ALC1220_FIXUP_CLEVO_P950),
+	SND_PCI_QUIRK(0x1558, 0x97e1, "Clevo P970[ER][CDFN]", ALC1220_FIXUP_CLEVO_P950),
+	SND_PCI_QUIRK(0x1558, 0x65d1, "Clevo PB51[ER][CDF]", ALC1220_FIXUP_CLEVO_PB51ED_PINS),
+	SND_PCI_QUIRK(0x1558, 0x67d1, "Clevo PB71[ER][CDF]", ALC1220_FIXUP_CLEVO_PB51ED_PINS),
 	SND_PCI_QUIRK_VENDOR(0x1558, "Clevo laptop", ALC882_FIXUP_EAPD),
 	SND_PCI_QUIRK(0x161f, 0x2054, "Medion laptop", ALC883_FIXUP_EAPD),
 	SND_PCI_QUIRK(0x17aa, 0x3a0d, "Lenovo Y530", ALC882_FIXUP_LENOVO_Y530),
@@ -7074,6 +7075,7 @@ static const struct snd_pci_quirk alc269
 	SND_PCI_QUIRK(0x17aa, 0x30bb, "ThinkCentre AIO", ALC233_FIXUP_LENOVO_LINE2_MIC_HOTKEY),
 	SND_PCI_QUIRK(0x17aa, 0x30e2, "ThinkCentre AIO", ALC233_FIXUP_LENOVO_LINE2_MIC_HOTKEY),
 	SND_PCI_QUIRK(0x17aa, 0x310c, "ThinkCentre Station", ALC294_FIXUP_LENOVO_MIC_LOCATION),
+	SND_PCI_QUIRK(0x17aa, 0x3111, "ThinkCentre Station", ALC294_FIXUP_LENOVO_MIC_LOCATION),
 	SND_PCI_QUIRK(0x17aa, 0x312a, "ThinkCentre Station", ALC294_FIXUP_LENOVO_MIC_LOCATION),
 	SND_PCI_QUIRK(0x17aa, 0x312f, "ThinkCentre Station", ALC294_FIXUP_LENOVO_MIC_LOCATION),
 	SND_PCI_QUIRK(0x17aa, 0x313c, "ThinkCentre Station", ALC294_FIXUP_LENOVO_MIC_LOCATION),
diff -druNp --no-dereference linux-libre-5.2-rc7-gnu/sound/usb/line6/pcm.c linux-libre-5.2-gnu/sound/usb/line6/pcm.c
--- linux-libre-5.2-rc7-gnu/sound/usb/line6/pcm.c	2019-06-29 23:25:36.000000000 -0400
+++ linux-libre-5.2-gnu/sound/usb/line6/pcm.c	2019-07-07 18:41:56.000000000 -0400
@@ -556,6 +556,11 @@ int line6_init_pcm(struct usb_line6 *lin
 	line6pcm->max_packet_size_out =
 		usb_maxpacket(line6->usbdev,
 			usb_sndisocpipe(line6->usbdev, ep_write), 1);
+	if (!line6pcm->max_packet_size_in || !line6pcm->max_packet_size_out) {
+		dev_err(line6pcm->line6->ifcdev,
+			"cannot get proper max packet size\n");
+		return -EINVAL;
+	}
 
 	spin_lock_init(&line6pcm->out.lock);
 	spin_lock_init(&line6pcm->in.lock);
diff -druNp --no-dereference linux-libre-5.2-rc7-gnu/sound/usb/mixer_quirks.c linux-libre-5.2-gnu/sound/usb/mixer_quirks.c
--- linux-libre-5.2-rc7-gnu/sound/usb/mixer_quirks.c	2019-06-29 23:25:36.000000000 -0400
+++ linux-libre-5.2-gnu/sound/usb/mixer_quirks.c	2019-07-07 18:41:56.000000000 -0400
@@ -741,7 +741,7 @@ static int snd_ni_control_init_val(struc
 		return err;
 	}
 
-	kctl->private_value |= (value << 24);
+	kctl->private_value |= ((unsigned int)value << 24);
 	return 0;
 }
 
@@ -902,7 +902,7 @@ static int snd_ftu_eff_switch_init(struc
 	if (err < 0)
 		return err;
 
-	kctl->private_value |= value[0] << 24;
+	kctl->private_value |= (unsigned int)value[0] << 24;
 	return 0;
 }
 
diff -druNp --no-dereference linux-libre-5.2-rc7-gnu/tools/testing/selftests/kvm/x86_64/evmcs_test.c linux-libre-5.2-gnu/tools/testing/selftests/kvm/x86_64/evmcs_test.c
--- linux-libre-5.2-rc7-gnu/tools/testing/selftests/kvm/x86_64/evmcs_test.c	2019-06-29 23:25:36.000000000 -0400
+++ linux-libre-5.2-gnu/tools/testing/selftests/kvm/x86_64/evmcs_test.c	2019-07-07 18:41:56.000000000 -0400
@@ -146,6 +146,7 @@ int main(int argc, char *argv[])
 		kvm_vm_restart(vm, O_RDWR);
 		vm_vcpu_add(vm, VCPU_ID, 0, 0);
 		vcpu_set_cpuid(vm, VCPU_ID, kvm_get_supported_cpuid());
+		vcpu_ioctl(vm, VCPU_ID, KVM_ENABLE_CAP, &enable_evmcs_cap);
 		vcpu_load_state(vm, VCPU_ID, state);
 		run = vcpu_state(vm, VCPU_ID);
 		free(state);
