diff -druNp --no-dereference linux-libre-5.4.5-gnu/arch/arm/boot/dts/s3c6410-mini6410.dts linux-libre-5.4.6-gnu/arch/arm/boot/dts/s3c6410-mini6410.dts
--- linux-libre-5.4.5-gnu/arch/arm/boot/dts/s3c6410-mini6410.dts	2019-12-18 10:09:17.000000000 -0500
+++ linux-libre-5.4.6-gnu/arch/arm/boot/dts/s3c6410-mini6410.dts	2019-12-21 05:05:23.000000000 -0500
@@ -165,6 +165,10 @@
 	};
 };
 
+&clocks {
+	clocks = <&fin_pll>;
+};
+
 &sdhci0 {
 	pinctrl-names = "default";
 	pinctrl-0 = <&sd0_clk>, <&sd0_cmd>, <&sd0_cd>, <&sd0_bus4>;
diff -druNp --no-dereference linux-libre-5.4.5-gnu/arch/arm/boot/dts/s3c6410-smdk6410.dts linux-libre-5.4.6-gnu/arch/arm/boot/dts/s3c6410-smdk6410.dts
--- linux-libre-5.4.5-gnu/arch/arm/boot/dts/s3c6410-smdk6410.dts	2019-12-18 10:09:17.000000000 -0500
+++ linux-libre-5.4.6-gnu/arch/arm/boot/dts/s3c6410-smdk6410.dts	2019-12-21 05:05:23.000000000 -0500
@@ -69,6 +69,10 @@
 	};
 };
 
+&clocks {
+	clocks = <&fin_pll>;
+};
+
 &sdhci0 {
 	pinctrl-names = "default";
 	pinctrl-0 = <&sd0_clk>, <&sd0_cmd>, <&sd0_cd>, <&sd0_bus4>;
diff -druNp --no-dereference linux-libre-5.4.5-gnu/arch/arm/mach-tegra/reset-handler.S linux-libre-5.4.6-gnu/arch/arm/mach-tegra/reset-handler.S
--- linux-libre-5.4.5-gnu/arch/arm/mach-tegra/reset-handler.S	2019-12-18 10:09:17.000000000 -0500
+++ linux-libre-5.4.6-gnu/arch/arm/mach-tegra/reset-handler.S	2019-12-21 05:05:23.000000000 -0500
@@ -44,16 +44,16 @@ ENTRY(tegra_resume)
 	cmp	r6, #TEGRA20
 	beq	1f				@ Yes
 	/* Clear the flow controller flags for this CPU. */
-	cpu_to_csr_reg r1, r0
+	cpu_to_csr_reg r3, r0
 	mov32	r2, TEGRA_FLOW_CTRL_BASE
-	ldr	r1, [r2, r1]
+	ldr	r1, [r2, r3]
 	/* Clear event & intr flag */
 	orr	r1, r1, \
 		#FLOW_CTRL_CSR_INTR_FLAG | FLOW_CTRL_CSR_EVENT_FLAG
 	movw	r0, #0x3FFD	@ enable, cluster_switch, immed, bitmaps
 				@ & ext flags for CPU power mgnt
 	bic	r1, r1, r0
-	str	r1, [r2]
+	str	r1, [r2, r3]
 1:
 
 	mov32	r9, 0xc09
diff -druNp --no-dereference linux-libre-5.4.5-gnu/arch/xtensa/include/asm/syscall.h linux-libre-5.4.6-gnu/arch/xtensa/include/asm/syscall.h
--- linux-libre-5.4.5-gnu/arch/xtensa/include/asm/syscall.h	2019-12-18 10:09:17.000000000 -0500
+++ linux-libre-5.4.6-gnu/arch/xtensa/include/asm/syscall.h	2019-12-21 05:05:23.000000000 -0500
@@ -51,7 +51,7 @@ static inline void syscall_set_return_va
 					    struct pt_regs *regs,
 					    int error, long val)
 {
-	regs->areg[0] = (long) error ? error : val;
+	regs->areg[2] = (long) error ? error : val;
 }
 
 #define SYSCALL_MAX_ARGS 6
diff -druNp --no-dereference linux-libre-5.4.5-gnu/arch/xtensa/mm/kasan_init.c linux-libre-5.4.6-gnu/arch/xtensa/mm/kasan_init.c
--- linux-libre-5.4.5-gnu/arch/xtensa/mm/kasan_init.c	2019-12-18 10:09:17.000000000 -0500
+++ linux-libre-5.4.6-gnu/arch/xtensa/mm/kasan_init.c	2019-12-21 05:05:23.000000000 -0500
@@ -56,7 +56,9 @@ static void __init populate(void *start,
 
 		for (k = 0; k < PTRS_PER_PTE; ++k, ++j) {
 			phys_addr_t phys =
-				memblock_phys_alloc(PAGE_SIZE, PAGE_SIZE);
+				memblock_phys_alloc_range(PAGE_SIZE, PAGE_SIZE,
+							  0,
+							  MEMBLOCK_ALLOC_ANYWHERE);
 
 			if (!phys)
 				panic("Failed to allocate page table page\n");
diff -druNp --no-dereference linux-libre-5.4.5-gnu/arch/xtensa/mm/tlb.c linux-libre-5.4.6-gnu/arch/xtensa/mm/tlb.c
--- linux-libre-5.4.5-gnu/arch/xtensa/mm/tlb.c	2019-12-18 10:09:17.000000000 -0500
+++ linux-libre-5.4.6-gnu/arch/xtensa/mm/tlb.c	2019-12-21 05:05:23.000000000 -0500
@@ -216,6 +216,8 @@ static int check_tlb_entry(unsigned w, u
 	unsigned tlbidx = w | (e << PAGE_SHIFT);
 	unsigned r0 = dtlb ?
 		read_dtlb_virtual(tlbidx) : read_itlb_virtual(tlbidx);
+	unsigned r1 = dtlb ?
+		read_dtlb_translation(tlbidx) : read_itlb_translation(tlbidx);
 	unsigned vpn = (r0 & PAGE_MASK) | (e << PAGE_SHIFT);
 	unsigned pte = get_pte_for_vaddr(vpn);
 	unsigned mm_asid = (get_rasid_register() >> 8) & ASID_MASK;
@@ -231,8 +233,6 @@ static int check_tlb_entry(unsigned w, u
 	}
 
 	if (tlb_asid == mm_asid) {
-		unsigned r1 = dtlb ? read_dtlb_translation(tlbidx) :
-			read_itlb_translation(tlbidx);
 		if ((pte ^ r1) & PAGE_MASK) {
 			pr_err("%cTLB: way: %u, entry: %u, mapping: %08x->%08x, PTE: %08x\n",
 					dtlb ? 'D' : 'I', w, e, r0, r1, pte);
diff -druNp --no-dereference linux-libre-5.4.5-gnu/block/bio.c linux-libre-5.4.6-gnu/block/bio.c
--- linux-libre-5.4.5-gnu/block/bio.c	2019-12-18 10:09:17.000000000 -0500
+++ linux-libre-5.4.6-gnu/block/bio.c	2019-12-21 05:05:23.000000000 -0500
@@ -751,10 +751,12 @@ bool __bio_try_merge_page(struct bio *bi
 	if (WARN_ON_ONCE(bio_flagged(bio, BIO_CLONED)))
 		return false;
 
-	if (bio->bi_vcnt > 0 && !bio_full(bio, len)) {
+	if (bio->bi_vcnt > 0) {
 		struct bio_vec *bv = &bio->bi_io_vec[bio->bi_vcnt - 1];
 
 		if (page_is_mergeable(bv, page, len, off, same_page)) {
+			if (bio->bi_iter.bi_size > UINT_MAX - len)
+				return false;
 			bv->bv_len += len;
 			bio->bi_iter.bi_size += len;
 			return true;
diff -druNp --no-dereference linux-libre-5.4.5-gnu/drivers/dma-buf/sync_file.c linux-libre-5.4.6-gnu/drivers/dma-buf/sync_file.c
--- linux-libre-5.4.5-gnu/drivers/dma-buf/sync_file.c	2019-12-18 10:09:17.000000000 -0500
+++ linux-libre-5.4.6-gnu/drivers/dma-buf/sync_file.c	2019-12-21 05:05:23.000000000 -0500
@@ -221,7 +221,7 @@ static struct sync_file *sync_file_merge
 	a_fences = get_fences(a, &a_num_fences);
 	b_fences = get_fences(b, &b_num_fences);
 	if (a_num_fences > INT_MAX - b_num_fences)
-		return NULL;
+		goto err;
 
 	num_fences = a_num_fences + b_num_fences;
 
diff -druNp --no-dereference linux-libre-5.4.5-gnu/drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.h linux-libre-5.4.6-gnu/drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.h
--- linux-libre-5.4.5-gnu/drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.h	2019-12-18 10:09:17.000000000 -0500
+++ linux-libre-5.4.6-gnu/drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.h	2019-12-21 05:05:23.000000000 -0500
@@ -77,6 +77,7 @@ struct amdgpu_gmc_fault {
 struct amdgpu_vmhub {
 	uint32_t	ctx0_ptb_addr_lo32;
 	uint32_t	ctx0_ptb_addr_hi32;
+	uint32_t	vm_inv_eng0_sem;
 	uint32_t	vm_inv_eng0_req;
 	uint32_t	vm_inv_eng0_ack;
 	uint32_t	vm_context0_cntl;
diff -druNp --no-dereference linux-libre-5.4.5-gnu/drivers/gpu/drm/amd/amdgpu/gfxhub_v1_0.c linux-libre-5.4.6-gnu/drivers/gpu/drm/amd/amdgpu/gfxhub_v1_0.c
--- linux-libre-5.4.5-gnu/drivers/gpu/drm/amd/amdgpu/gfxhub_v1_0.c	2019-12-18 10:09:17.000000000 -0500
+++ linux-libre-5.4.6-gnu/drivers/gpu/drm/amd/amdgpu/gfxhub_v1_0.c	2019-12-21 05:05:23.000000000 -0500
@@ -365,6 +365,8 @@ void gfxhub_v1_0_init(struct amdgpu_devi
 	hub->ctx0_ptb_addr_hi32 =
 		SOC15_REG_OFFSET(GC, 0,
 				 mmVM_CONTEXT0_PAGE_TABLE_BASE_ADDR_HI32);
+	hub->vm_inv_eng0_sem =
+		SOC15_REG_OFFSET(GC, 0, mmVM_INVALIDATE_ENG0_SEM);
 	hub->vm_inv_eng0_req =
 		SOC15_REG_OFFSET(GC, 0, mmVM_INVALIDATE_ENG0_REQ);
 	hub->vm_inv_eng0_ack =
diff -druNp --no-dereference linux-libre-5.4.5-gnu/drivers/gpu/drm/amd/amdgpu/gfxhub_v2_0.c linux-libre-5.4.6-gnu/drivers/gpu/drm/amd/amdgpu/gfxhub_v2_0.c
--- linux-libre-5.4.5-gnu/drivers/gpu/drm/amd/amdgpu/gfxhub_v2_0.c	2019-12-18 10:09:17.000000000 -0500
+++ linux-libre-5.4.6-gnu/drivers/gpu/drm/amd/amdgpu/gfxhub_v2_0.c	2019-12-21 05:05:23.000000000 -0500
@@ -350,6 +350,8 @@ void gfxhub_v2_0_init(struct amdgpu_devi
 	hub->ctx0_ptb_addr_hi32 =
 		SOC15_REG_OFFSET(GC, 0,
 				 mmGCVM_CONTEXT0_PAGE_TABLE_BASE_ADDR_HI32);
+	hub->vm_inv_eng0_sem =
+		SOC15_REG_OFFSET(GC, 0, mmGCVM_INVALIDATE_ENG0_SEM);
 	hub->vm_inv_eng0_req =
 		SOC15_REG_OFFSET(GC, 0, mmGCVM_INVALIDATE_ENG0_REQ);
 	hub->vm_inv_eng0_ack =
diff -druNp --no-dereference linux-libre-5.4.5-gnu/drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c linux-libre-5.4.6-gnu/drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c
--- linux-libre-5.4.5-gnu/drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c	2019-12-18 13:18:36.000000000 -0500
+++ linux-libre-5.4.6-gnu/drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c	2019-12-21 21:53:17.000000000 -0500
@@ -1761,27 +1761,52 @@ static void gfx_v10_0_enable_gui_idle_in
 	WREG32_SOC15(GC, 0, mmCP_INT_CNTL_RING0, tmp);
 }
 
-static void gfx_v10_0_init_csb(struct amdgpu_device *adev)
+static int gfx_v10_0_init_csb(struct amdgpu_device *adev)
 {
+	int r;
+
+	if (adev->in_gpu_reset) {
+		r = amdgpu_bo_reserve(adev->gfx.rlc.clear_state_obj, false);
+		if (r)
+			return r;
+
+		r = amdgpu_bo_kmap(adev->gfx.rlc.clear_state_obj,
+				   (void **)&adev->gfx.rlc.cs_ptr);
+		if (!r) {
+			adev->gfx.rlc.funcs->get_csb_buffer(adev,
+					adev->gfx.rlc.cs_ptr);
+			amdgpu_bo_kunmap(adev->gfx.rlc.clear_state_obj);
+		}
+
+		amdgpu_bo_unreserve(adev->gfx.rlc.clear_state_obj);
+		if (r)
+			return r;
+	}
+
 	/* csib */
 	WREG32_SOC15(GC, 0, mmRLC_CSIB_ADDR_HI,
 		     adev->gfx.rlc.clear_state_gpu_addr >> 32);
 	WREG32_SOC15(GC, 0, mmRLC_CSIB_ADDR_LO,
 		     adev->gfx.rlc.clear_state_gpu_addr & 0xfffffffc);
 	WREG32_SOC15(GC, 0, mmRLC_CSIB_LENGTH, adev->gfx.rlc.clear_state_size);
+
+	return 0;
 }
 
-static void gfx_v10_0_init_pg(struct amdgpu_device *adev)
+static int gfx_v10_0_init_pg(struct amdgpu_device *adev)
 {
 	int i;
+	int r;
 
-	gfx_v10_0_init_csb(adev);
+	r = gfx_v10_0_init_csb(adev);
+	if (r)
+		return r;
 
 	for (i = 0; i < adev->num_vmhubs; i++)
 		amdgpu_gmc_flush_gpu_tlb(adev, 0, i, 0);
 
 	/* TODO: init power gating */
-	return;
+	return 0;
 }
 
 void gfx_v10_0_rlc_stop(struct amdgpu_device *adev)
@@ -1883,7 +1908,10 @@ static int gfx_v10_0_rlc_resume(struct a
 		r = gfx_v10_0_wait_for_rlc_autoload_complete(adev);
 		if (r)
 			return r;
-		gfx_v10_0_init_pg(adev);
+
+		r = gfx_v10_0_init_pg(adev);
+		if (r)
+			return r;
 
 		/* enable RLC SRM */
 		gfx_v10_0_rlc_enable_srm(adev);
@@ -1909,7 +1937,10 @@ static int gfx_v10_0_rlc_resume(struct a
 				return r;
 		}
 
-		gfx_v10_0_init_pg(adev);
+		r = gfx_v10_0_init_pg(adev);
+		if (r)
+			return r;
+
 		adev->gfx.rlc.funcs->start(adev);
 
 		if (adev->firmware.load_type == AMDGPU_FW_LOAD_RLC_BACKDOOR_AUTO) {
@@ -2376,7 +2407,7 @@ static int gfx_v10_0_wait_for_rlc_autolo
 	return 0;
 }
 
-static void gfx_v10_0_cp_gfx_enable(struct amdgpu_device *adev, bool enable)
+static int gfx_v10_0_cp_gfx_enable(struct amdgpu_device *adev, bool enable)
 {
 	int i;
 	u32 tmp = RREG32_SOC15(GC, 0, mmCP_ME_CNTL);
@@ -2389,7 +2420,17 @@ static void gfx_v10_0_cp_gfx_enable(stru
 			adev->gfx.gfx_ring[i].sched.ready = false;
 	}
 	WREG32_SOC15(GC, 0, mmCP_ME_CNTL, tmp);
-	udelay(50);
+
+	for (i = 0; i < adev->usec_timeout; i++) {
+		if (RREG32_SOC15(GC, 0, mmCP_STAT) == 0)
+			break;
+		udelay(1);
+	}
+
+	if (i >= adev->usec_timeout)
+		DRM_ERROR("failed to %s cp gfx\n", enable ? "unhalt" : "halt");
+
+	return 0;
 }
 
 static int gfx_v10_0_cp_gfx_load_pfp_microcode(struct amdgpu_device *adev)
diff -druNp --no-dereference linux-libre-5.4.5-gnu/drivers/gpu/drm/amd/amdgpu/gmc_v10_0.c linux-libre-5.4.6-gnu/drivers/gpu/drm/amd/amdgpu/gmc_v10_0.c
--- linux-libre-5.4.5-gnu/drivers/gpu/drm/amd/amdgpu/gmc_v10_0.c	2019-12-18 10:09:17.000000000 -0500
+++ linux-libre-5.4.6-gnu/drivers/gpu/drm/amd/amdgpu/gmc_v10_0.c	2019-12-21 05:05:23.000000000 -0500
@@ -235,6 +235,29 @@ static void gmc_v10_0_flush_vm_hub(struc
 	const unsigned eng = 17;
 	unsigned int i;
 
+	spin_lock(&adev->gmc.invalidate_lock);
+	/*
+	 * It may lose gpuvm invalidate acknowldege state across power-gating
+	 * off cycle, add semaphore acquire before invalidation and semaphore
+	 * release after invalidation to avoid entering power gated state
+	 * to WA the Issue
+	 */
+
+	/* TODO: It needs to continue working on debugging with semaphore for GFXHUB as well. */
+	if (vmhub == AMDGPU_MMHUB_0 ||
+	    vmhub == AMDGPU_MMHUB_1) {
+		for (i = 0; i < adev->usec_timeout; i++) {
+			/* a read return value of 1 means semaphore acuqire */
+			tmp = RREG32_NO_KIQ(hub->vm_inv_eng0_sem + eng);
+			if (tmp & 0x1)
+				break;
+			udelay(1);
+		}
+
+		if (i >= adev->usec_timeout)
+			DRM_ERROR("Timeout waiting for sem acquire in VM flush!\n");
+	}
+
 	WREG32_NO_KIQ(hub->vm_inv_eng0_req + eng, tmp);
 
 	/*
@@ -254,6 +277,17 @@ static void gmc_v10_0_flush_vm_hub(struc
 		udelay(1);
 	}
 
+	/* TODO: It needs to continue working on debugging with semaphore for GFXHUB as well. */
+	if (vmhub == AMDGPU_MMHUB_0 ||
+	    vmhub == AMDGPU_MMHUB_1)
+		/*
+		 * add semaphore release after invalidation,
+		 * write with 0 means semaphore release
+		 */
+		WREG32_NO_KIQ(hub->vm_inv_eng0_sem + eng, 0);
+
+	spin_unlock(&adev->gmc.invalidate_lock);
+
 	if (i < adev->usec_timeout)
 		return;
 
@@ -338,6 +372,20 @@ static uint64_t gmc_v10_0_emit_flush_gpu
 	uint32_t req = gmc_v10_0_get_invalidate_req(vmid, 0);
 	unsigned eng = ring->vm_inv_eng;
 
+	/*
+	 * It may lose gpuvm invalidate acknowldege state across power-gating
+	 * off cycle, add semaphore acquire before invalidation and semaphore
+	 * release after invalidation to avoid entering power gated state
+	 * to WA the Issue
+	 */
+
+	/* TODO: It needs to continue working on debugging with semaphore for GFXHUB as well. */
+	if (ring->funcs->vmhub == AMDGPU_MMHUB_0 ||
+	    ring->funcs->vmhub == AMDGPU_MMHUB_1)
+		/* a read return value of 1 means semaphore acuqire */
+		amdgpu_ring_emit_reg_wait(ring,
+					  hub->vm_inv_eng0_sem + eng, 0x1, 0x1);
+
 	amdgpu_ring_emit_wreg(ring, hub->ctx0_ptb_addr_lo32 + (2 * vmid),
 			      lower_32_bits(pd_addr));
 
@@ -348,6 +396,15 @@ static uint64_t gmc_v10_0_emit_flush_gpu
 					    hub->vm_inv_eng0_ack + eng,
 					    req, 1 << vmid);
 
+	/* TODO: It needs to continue working on debugging with semaphore for GFXHUB as well. */
+	if (ring->funcs->vmhub == AMDGPU_MMHUB_0 ||
+	    ring->funcs->vmhub == AMDGPU_MMHUB_1)
+		/*
+		 * add semaphore release after invalidation,
+		 * write with 0 means semaphore release
+		 */
+		amdgpu_ring_emit_wreg(ring, hub->vm_inv_eng0_sem + eng, 0);
+
 	return pd_addr;
 }
 
diff -druNp --no-dereference linux-libre-5.4.5-gnu/drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c linux-libre-5.4.6-gnu/drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c
--- linux-libre-5.4.5-gnu/drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c	2019-12-18 10:09:17.000000000 -0500
+++ linux-libre-5.4.6-gnu/drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c	2019-12-21 05:05:23.000000000 -0500
@@ -448,6 +448,24 @@ static uint32_t gmc_v9_0_get_invalidate_
 	return req;
 }
 
+/**
+ * gmc_v9_0_use_invalidate_semaphore - judge whether to use semaphore
+ *
+ * @adev: amdgpu_device pointer
+ * @vmhub: vmhub type
+ *
+ */
+static bool gmc_v9_0_use_invalidate_semaphore(struct amdgpu_device *adev,
+				       uint32_t vmhub)
+{
+	return ((vmhub == AMDGPU_MMHUB_0 ||
+		 vmhub == AMDGPU_MMHUB_1) &&
+		(!amdgpu_sriov_vf(adev)) &&
+		(!(adev->asic_type == CHIP_RAVEN &&
+		   adev->rev_id < 0x8 &&
+		   adev->pdev->device == 0x15d8)));
+}
+
 /*
  * GART
  * VMID 0 is the physical GPU addresses as used by the kernel.
@@ -467,6 +485,7 @@ static uint32_t gmc_v9_0_get_invalidate_
 static void gmc_v9_0_flush_gpu_tlb(struct amdgpu_device *adev, uint32_t vmid,
 					uint32_t vmhub, uint32_t flush_type)
 {
+	bool use_semaphore = gmc_v9_0_use_invalidate_semaphore(adev, vmhub);
 	const unsigned eng = 17;
 	u32 j, tmp;
 	struct amdgpu_vmhub *hub;
@@ -491,6 +510,28 @@ static void gmc_v9_0_flush_gpu_tlb(struc
 	}
 
 	spin_lock(&adev->gmc.invalidate_lock);
+
+	/*
+	 * It may lose gpuvm invalidate acknowldege state across power-gating
+	 * off cycle, add semaphore acquire before invalidation and semaphore
+	 * release after invalidation to avoid entering power gated state
+	 * to WA the Issue
+	 */
+
+	/* TODO: It needs to continue working on debugging with semaphore for GFXHUB as well. */
+	if (use_semaphore) {
+		for (j = 0; j < adev->usec_timeout; j++) {
+			/* a read return value of 1 means semaphore acuqire */
+			tmp = RREG32_NO_KIQ(hub->vm_inv_eng0_sem + eng);
+			if (tmp & 0x1)
+				break;
+			udelay(1);
+		}
+
+		if (j >= adev->usec_timeout)
+			DRM_ERROR("Timeout waiting for sem acquire in VM flush!\n");
+	}
+
 	WREG32_NO_KIQ(hub->vm_inv_eng0_req + eng, tmp);
 
 	/*
@@ -506,7 +547,17 @@ static void gmc_v9_0_flush_gpu_tlb(struc
 			break;
 		udelay(1);
 	}
+
+	/* TODO: It needs to continue working on debugging with semaphore for GFXHUB as well. */
+	if (use_semaphore)
+		/*
+		 * add semaphore release after invalidation,
+		 * write with 0 means semaphore release
+		 */
+		WREG32_NO_KIQ(hub->vm_inv_eng0_sem + eng, 0);
+
 	spin_unlock(&adev->gmc.invalidate_lock);
+
 	if (j < adev->usec_timeout)
 		return;
 
@@ -516,11 +567,25 @@ static void gmc_v9_0_flush_gpu_tlb(struc
 static uint64_t gmc_v9_0_emit_flush_gpu_tlb(struct amdgpu_ring *ring,
 					    unsigned vmid, uint64_t pd_addr)
 {
+	bool use_semaphore = gmc_v9_0_use_invalidate_semaphore(ring->adev, ring->funcs->vmhub);
 	struct amdgpu_device *adev = ring->adev;
 	struct amdgpu_vmhub *hub = &adev->vmhub[ring->funcs->vmhub];
 	uint32_t req = gmc_v9_0_get_invalidate_req(vmid, 0);
 	unsigned eng = ring->vm_inv_eng;
 
+	/*
+	 * It may lose gpuvm invalidate acknowldege state across power-gating
+	 * off cycle, add semaphore acquire before invalidation and semaphore
+	 * release after invalidation to avoid entering power gated state
+	 * to WA the Issue
+	 */
+
+	/* TODO: It needs to continue working on debugging with semaphore for GFXHUB as well. */
+	if (use_semaphore)
+		/* a read return value of 1 means semaphore acuqire */
+		amdgpu_ring_emit_reg_wait(ring,
+					  hub->vm_inv_eng0_sem + eng, 0x1, 0x1);
+
 	amdgpu_ring_emit_wreg(ring, hub->ctx0_ptb_addr_lo32 + (2 * vmid),
 			      lower_32_bits(pd_addr));
 
@@ -531,6 +596,14 @@ static uint64_t gmc_v9_0_emit_flush_gpu_
 					    hub->vm_inv_eng0_ack + eng,
 					    req, 1 << vmid);
 
+	/* TODO: It needs to continue working on debugging with semaphore for GFXHUB as well. */
+	if (use_semaphore)
+		/*
+		 * add semaphore release after invalidation,
+		 * write with 0 means semaphore release
+		 */
+		amdgpu_ring_emit_wreg(ring, hub->vm_inv_eng0_sem + eng, 0);
+
 	return pd_addr;
 }
 
diff -druNp --no-dereference linux-libre-5.4.5-gnu/drivers/gpu/drm/amd/amdgpu/mmhub_v1_0.c linux-libre-5.4.6-gnu/drivers/gpu/drm/amd/amdgpu/mmhub_v1_0.c
--- linux-libre-5.4.5-gnu/drivers/gpu/drm/amd/amdgpu/mmhub_v1_0.c	2019-12-18 10:09:17.000000000 -0500
+++ linux-libre-5.4.6-gnu/drivers/gpu/drm/amd/amdgpu/mmhub_v1_0.c	2019-12-21 05:05:23.000000000 -0500
@@ -418,6 +418,8 @@ void mmhub_v1_0_init(struct amdgpu_devic
 	hub->ctx0_ptb_addr_hi32 =
 		SOC15_REG_OFFSET(MMHUB, 0,
 				 mmVM_CONTEXT0_PAGE_TABLE_BASE_ADDR_HI32);
+	hub->vm_inv_eng0_sem =
+		SOC15_REG_OFFSET(MMHUB, 0, mmVM_INVALIDATE_ENG0_SEM);
 	hub->vm_inv_eng0_req =
 		SOC15_REG_OFFSET(MMHUB, 0, mmVM_INVALIDATE_ENG0_REQ);
 	hub->vm_inv_eng0_ack =
diff -druNp --no-dereference linux-libre-5.4.5-gnu/drivers/gpu/drm/amd/amdgpu/mmhub_v2_0.c linux-libre-5.4.6-gnu/drivers/gpu/drm/amd/amdgpu/mmhub_v2_0.c
--- linux-libre-5.4.5-gnu/drivers/gpu/drm/amd/amdgpu/mmhub_v2_0.c	2019-12-18 10:09:17.000000000 -0500
+++ linux-libre-5.4.6-gnu/drivers/gpu/drm/amd/amdgpu/mmhub_v2_0.c	2019-12-21 05:05:23.000000000 -0500
@@ -341,6 +341,8 @@ void mmhub_v2_0_init(struct amdgpu_devic
 	hub->ctx0_ptb_addr_hi32 =
 		SOC15_REG_OFFSET(MMHUB, 0,
 				 mmMMVM_CONTEXT0_PAGE_TABLE_BASE_ADDR_HI32);
+	hub->vm_inv_eng0_sem =
+		SOC15_REG_OFFSET(MMHUB, 0, mmMMVM_INVALIDATE_ENG0_SEM);
 	hub->vm_inv_eng0_req =
 		SOC15_REG_OFFSET(MMHUB, 0, mmMMVM_INVALIDATE_ENG0_REQ);
 	hub->vm_inv_eng0_ack =
diff -druNp --no-dereference linux-libre-5.4.5-gnu/drivers/gpu/drm/amd/amdgpu/mmhub_v9_4.c linux-libre-5.4.6-gnu/drivers/gpu/drm/amd/amdgpu/mmhub_v9_4.c
--- linux-libre-5.4.5-gnu/drivers/gpu/drm/amd/amdgpu/mmhub_v9_4.c	2019-12-18 10:09:17.000000000 -0500
+++ linux-libre-5.4.6-gnu/drivers/gpu/drm/amd/amdgpu/mmhub_v9_4.c	2019-12-21 05:05:23.000000000 -0500
@@ -502,6 +502,10 @@ void mmhub_v9_4_init(struct amdgpu_devic
 			SOC15_REG_OFFSET(MMHUB, 0,
 			    mmVML2VC0_VM_CONTEXT0_PAGE_TABLE_BASE_ADDR_HI32) +
 			    i * MMHUB_INSTANCE_REGISTER_OFFSET;
+		hub[i]->vm_inv_eng0_sem =
+			SOC15_REG_OFFSET(MMHUB, 0,
+					 mmVML2VC0_VM_INVALIDATE_ENG0_SEM) +
+					 i * MMHUB_INSTANCE_REGISTER_OFFSET;
 		hub[i]->vm_inv_eng0_req =
 			SOC15_REG_OFFSET(MMHUB, 0,
 					 mmVML2VC0_VM_INVALIDATE_ENG0_REQ) +
diff -druNp --no-dereference linux-libre-5.4.5-gnu/drivers/gpu/drm/amd/amdgpu/soc15.h linux-libre-5.4.6-gnu/drivers/gpu/drm/amd/amdgpu/soc15.h
--- linux-libre-5.4.5-gnu/drivers/gpu/drm/amd/amdgpu/soc15.h	2019-12-18 10:09:17.000000000 -0500
+++ linux-libre-5.4.6-gnu/drivers/gpu/drm/amd/amdgpu/soc15.h	2019-12-21 05:05:23.000000000 -0500
@@ -28,8 +28,8 @@
 #include "nbio_v7_0.h"
 #include "nbio_v7_4.h"
 
-#define SOC15_FLUSH_GPU_TLB_NUM_WREG		4
-#define SOC15_FLUSH_GPU_TLB_NUM_REG_WAIT	1
+#define SOC15_FLUSH_GPU_TLB_NUM_WREG		6
+#define SOC15_FLUSH_GPU_TLB_NUM_REG_WAIT	3
 
 extern const struct amd_ip_funcs soc15_common_ip_funcs;
 
diff -druNp --no-dereference linux-libre-5.4.5-gnu/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_pp_smu.c linux-libre-5.4.6-gnu/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_pp_smu.c
--- linux-libre-5.4.5-gnu/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_pp_smu.c	2019-12-18 10:09:17.000000000 -0500
+++ linux-libre-5.4.6-gnu/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_pp_smu.c	2019-12-21 05:05:23.000000000 -0500
@@ -342,7 +342,8 @@ bool dm_pp_get_clock_levels_by_type(
 	if (adev->powerplay.pp_funcs && adev->powerplay.pp_funcs->get_clock_by_type) {
 		if (adev->powerplay.pp_funcs->get_clock_by_type(pp_handle,
 			dc_to_pp_clock_type(clk_type), &pp_clks)) {
-		/* Error in pplib. Provide default values. */
+			/* Error in pplib. Provide default values. */
+			get_default_clock_levels(clk_type, dc_clks);
 			return true;
 		}
 	} else if (adev->smu.funcs && adev->smu.funcs->get_clock_by_type) {
diff -druNp --no-dereference linux-libre-5.4.5-gnu/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hwseq.c linux-libre-5.4.6-gnu/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hwseq.c
--- linux-libre-5.4.5-gnu/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hwseq.c	2019-12-18 10:09:17.000000000 -0500
+++ linux-libre-5.4.6-gnu/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hwseq.c	2019-12-21 05:05:23.000000000 -0500
@@ -1103,6 +1103,25 @@ void dcn20_pipe_control_lock(
 	if (pipe->plane_state != NULL)
 		flip_immediate = pipe->plane_state->flip_immediate;
 
+	if (flip_immediate && lock) {
+		const int TIMEOUT_FOR_FLIP_PENDING = 100000;
+		int i;
+
+		for (i = 0; i < TIMEOUT_FOR_FLIP_PENDING; ++i) {
+			if (!pipe->plane_res.hubp->funcs->hubp_is_flip_pending(pipe->plane_res.hubp))
+				break;
+			udelay(1);
+		}
+
+		if (pipe->bottom_pipe != NULL) {
+			for (i = 0; i < TIMEOUT_FOR_FLIP_PENDING; ++i) {
+				if (!pipe->bottom_pipe->plane_res.hubp->funcs->hubp_is_flip_pending(pipe->bottom_pipe->plane_res.hubp))
+					break;
+				udelay(1);
+			}
+		}
+	}
+
 	/* In flip immediate and pipe splitting case, we need to use GSL
 	 * for synchronization. Only do setup on locking and on flip type change.
 	 */
diff -druNp --no-dereference linux-libre-5.4.5-gnu/drivers/gpu/drm/drm_dp_mst_topology.c linux-libre-5.4.6-gnu/drivers/gpu/drm/drm_dp_mst_topology.c
--- linux-libre-5.4.5-gnu/drivers/gpu/drm/drm_dp_mst_topology.c	2019-12-18 10:09:17.000000000 -0500
+++ linux-libre-5.4.6-gnu/drivers/gpu/drm/drm_dp_mst_topology.c	2019-12-21 05:05:23.000000000 -0500
@@ -2465,9 +2465,11 @@ int drm_dp_update_payload_part1(struct d
 			drm_dp_mst_topology_put_port(port);
 	}
 
-	for (i = 0; i < mgr->max_payloads; i++) {
-		if (mgr->payloads[i].payload_state != DP_PAYLOAD_DELETE_LOCAL)
+	for (i = 0; i < mgr->max_payloads; /* do nothing */) {
+		if (mgr->payloads[i].payload_state != DP_PAYLOAD_DELETE_LOCAL) {
+			i++;
 			continue;
+		}
 
 		DRM_DEBUG_KMS("removing payload %d\n", i);
 		for (j = i; j < mgr->max_payloads - 1; j++) {
diff -druNp --no-dereference linux-libre-5.4.5-gnu/drivers/gpu/drm/i915/display/intel_fbc.c linux-libre-5.4.6-gnu/drivers/gpu/drm/i915/display/intel_fbc.c
--- linux-libre-5.4.5-gnu/drivers/gpu/drm/i915/display/intel_fbc.c	2019-12-18 10:09:17.000000000 -0500
+++ linux-libre-5.4.6-gnu/drivers/gpu/drm/i915/display/intel_fbc.c	2019-12-21 05:05:23.000000000 -0500
@@ -1284,7 +1284,7 @@ static int intel_sanitize_fbc_option(str
 		return 0;
 
 	/* https://bugs.freedesktop.org/show_bug.cgi?id=108085 */
-	if (IS_GEMINILAKE(dev_priv))
+	if (INTEL_GEN(dev_priv) >= 10 || IS_GEMINILAKE(dev_priv))
 		return 0;
 
 	if (IS_BROADWELL(dev_priv) || INTEL_GEN(dev_priv) >= 9)
diff -druNp --no-dereference linux-libre-5.4.5-gnu/drivers/gpu/drm/i915/gvt/cmd_parser.c linux-libre-5.4.6-gnu/drivers/gpu/drm/i915/gvt/cmd_parser.c
--- linux-libre-5.4.5-gnu/drivers/gpu/drm/i915/gvt/cmd_parser.c	2019-12-18 10:09:17.000000000 -0500
+++ linux-libre-5.4.6-gnu/drivers/gpu/drm/i915/gvt/cmd_parser.c	2019-12-21 05:05:23.000000000 -0500
@@ -1597,9 +1597,9 @@ static int cmd_handler_mi_op_2f(struct p
 	if (!(cmd_val(s, 0) & (1 << 22)))
 		return ret;
 
-	/* check if QWORD */
-	if (DWORD_FIELD(0, 20, 19) == 1)
-		valid_len += 8;
+	/* check inline data */
+	if (cmd_val(s, 0) & BIT(18))
+		valid_len = CMD_LEN(9);
 	ret = gvt_check_valid_cmd_length(cmd_length(s),
 			valid_len);
 	if (ret)
diff -druNp --no-dereference linux-libre-5.4.5-gnu/drivers/gpu/drm/meson/meson_venc_cvbs.c linux-libre-5.4.6-gnu/drivers/gpu/drm/meson/meson_venc_cvbs.c
--- linux-libre-5.4.5-gnu/drivers/gpu/drm/meson/meson_venc_cvbs.c	2019-12-18 10:09:17.000000000 -0500
+++ linux-libre-5.4.6-gnu/drivers/gpu/drm/meson/meson_venc_cvbs.c	2019-12-21 05:05:23.000000000 -0500
@@ -64,6 +64,25 @@ struct meson_cvbs_mode meson_cvbs_modes[
 	},
 };
 
+static const struct meson_cvbs_mode *
+meson_cvbs_get_mode(const struct drm_display_mode *req_mode)
+{
+	int i;
+
+	for (i = 0; i < MESON_CVBS_MODES_COUNT; ++i) {
+		struct meson_cvbs_mode *meson_mode = &meson_cvbs_modes[i];
+
+		if (drm_mode_match(req_mode, &meson_mode->mode,
+				   DRM_MODE_MATCH_TIMINGS |
+				   DRM_MODE_MATCH_CLOCK |
+				   DRM_MODE_MATCH_FLAGS |
+				   DRM_MODE_MATCH_3D_FLAGS))
+			return meson_mode;
+	}
+
+	return NULL;
+}
+
 /* Connector */
 
 static void meson_cvbs_connector_destroy(struct drm_connector *connector)
@@ -136,14 +155,8 @@ static int meson_venc_cvbs_encoder_atomi
 					struct drm_crtc_state *crtc_state,
 					struct drm_connector_state *conn_state)
 {
-	int i;
-
-	for (i = 0; i < MESON_CVBS_MODES_COUNT; ++i) {
-		struct meson_cvbs_mode *meson_mode = &meson_cvbs_modes[i];
-
-		if (drm_mode_equal(&crtc_state->mode, &meson_mode->mode))
-			return 0;
-	}
+	if (meson_cvbs_get_mode(&crtc_state->mode))
+		return 0;
 
 	return -EINVAL;
 }
@@ -191,24 +204,17 @@ static void meson_venc_cvbs_encoder_mode
 				   struct drm_display_mode *mode,
 				   struct drm_display_mode *adjusted_mode)
 {
+	const struct meson_cvbs_mode *meson_mode = meson_cvbs_get_mode(mode);
 	struct meson_venc_cvbs *meson_venc_cvbs =
 					encoder_to_meson_venc_cvbs(encoder);
 	struct meson_drm *priv = meson_venc_cvbs->priv;
-	int i;
-
-	for (i = 0; i < MESON_CVBS_MODES_COUNT; ++i) {
-		struct meson_cvbs_mode *meson_mode = &meson_cvbs_modes[i];
 
-		if (drm_mode_equal(mode, &meson_mode->mode)) {
-			meson_venci_cvbs_mode_set(priv,
-						  meson_mode->enci);
+	if (meson_mode) {
+		meson_venci_cvbs_mode_set(priv, meson_mode->enci);
 
-			/* Setup 27MHz vclk2 for ENCI and VDAC */
-			meson_vclk_setup(priv, MESON_VCLK_TARGET_CVBS,
-					 MESON_VCLK_CVBS, MESON_VCLK_CVBS,
-					 MESON_VCLK_CVBS, true);
-			break;
-		}
+		/* Setup 27MHz vclk2 for ENCI and VDAC */
+		meson_vclk_setup(priv, MESON_VCLK_TARGET_CVBS, MESON_VCLK_CVBS,
+				 MESON_VCLK_CVBS, MESON_VCLK_CVBS, true);
 	}
 }
 
diff -druNp --no-dereference linux-libre-5.4.5-gnu/drivers/gpu/drm/mgag200/mgag200_drv.c linux-libre-5.4.6-gnu/drivers/gpu/drm/mgag200/mgag200_drv.c
--- linux-libre-5.4.5-gnu/drivers/gpu/drm/mgag200/mgag200_drv.c	2019-12-18 10:09:17.000000000 -0500
+++ linux-libre-5.4.6-gnu/drivers/gpu/drm/mgag200/mgag200_drv.c	2019-12-21 05:05:23.000000000 -0500
@@ -30,7 +30,8 @@ module_param_named(modeset, mgag200_mode
 static struct drm_driver driver;
 
 static const struct pci_device_id pciidlist[] = {
-	{ PCI_VENDOR_ID_MATROX, 0x522, PCI_ANY_ID, PCI_ANY_ID, 0, 0, G200_SE_A },
+	{ PCI_VENDOR_ID_MATROX, 0x522, PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+		G200_SE_A | MGAG200_FLAG_HW_BUG_NO_STARTADD},
 	{ PCI_VENDOR_ID_MATROX, 0x524, PCI_ANY_ID, PCI_ANY_ID, 0, 0, G200_SE_B },
 	{ PCI_VENDOR_ID_MATROX, 0x530, PCI_ANY_ID, PCI_ANY_ID, 0, 0, G200_EV },
 	{ PCI_VENDOR_ID_MATROX, 0x532, PCI_ANY_ID, PCI_ANY_ID, 0, 0, G200_WB },
@@ -63,6 +64,35 @@ static const struct file_operations mgag
 	DRM_VRAM_MM_FILE_OPERATIONS
 };
 
+static bool mgag200_pin_bo_at_0(const struct mga_device *mdev)
+{
+	return mdev->flags & MGAG200_FLAG_HW_BUG_NO_STARTADD;
+}
+
+int mgag200_driver_dumb_create(struct drm_file *file,
+			       struct drm_device *dev,
+			       struct drm_mode_create_dumb *args)
+{
+	struct mga_device *mdev = dev->dev_private;
+	unsigned long pg_align;
+
+	if (WARN_ONCE(!dev->vram_mm, "VRAM MM not initialized"))
+		return -EINVAL;
+
+	pg_align = 0ul;
+
+	/*
+	 * Aligning scanout buffers to the size of the video ram forces
+	 * placement at offset 0. Works around a bug where HW does not
+	 * respect 'startadd' field.
+	 */
+	if (mgag200_pin_bo_at_0(mdev))
+		pg_align = PFN_UP(mdev->mc.vram_size);
+
+	return drm_gem_vram_fill_create_dumb(file, dev, &dev->vram_mm->bdev,
+					     pg_align, false, args);
+}
+
 static struct drm_driver driver = {
 	.driver_features = DRIVER_GEM | DRIVER_MODESET,
 	.load = mgag200_driver_load,
@@ -74,7 +104,9 @@ static struct drm_driver driver = {
 	.major = DRIVER_MAJOR,
 	.minor = DRIVER_MINOR,
 	.patchlevel = DRIVER_PATCHLEVEL,
-	DRM_GEM_VRAM_DRIVER
+	.dumb_create = mgag200_driver_dumb_create,
+	.dumb_map_offset = drm_gem_vram_driver_dumb_mmap_offset,
+	.gem_prime_mmap = drm_gem_prime_mmap,
 };
 
 static struct pci_driver mgag200_pci_driver = {
diff -druNp --no-dereference linux-libre-5.4.5-gnu/drivers/gpu/drm/mgag200/mgag200_drv.h linux-libre-5.4.6-gnu/drivers/gpu/drm/mgag200/mgag200_drv.h
--- linux-libre-5.4.5-gnu/drivers/gpu/drm/mgag200/mgag200_drv.h	2019-12-18 10:09:17.000000000 -0500
+++ linux-libre-5.4.6-gnu/drivers/gpu/drm/mgag200/mgag200_drv.h	2019-12-21 05:05:23.000000000 -0500
@@ -159,6 +159,12 @@ enum mga_type {
 	G200_EW3,
 };
 
+/* HW does not handle 'startadd' field correct. */
+#define MGAG200_FLAG_HW_BUG_NO_STARTADD	(1ul << 8)
+
+#define MGAG200_TYPE_MASK	(0x000000ff)
+#define MGAG200_FLAG_MASK	(0x00ffff00)
+
 #define IS_G200_SE(mdev) (mdev->type == G200_SE_A || mdev->type == G200_SE_B)
 
 struct mga_device {
@@ -188,6 +194,18 @@ struct mga_device {
 	u32 unique_rev_id;
 };
 
+static inline enum mga_type
+mgag200_type_from_driver_data(kernel_ulong_t driver_data)
+{
+	return (enum mga_type)(driver_data & MGAG200_TYPE_MASK);
+}
+
+static inline unsigned long
+mgag200_flags_from_driver_data(kernel_ulong_t driver_data)
+{
+	return driver_data & MGAG200_FLAG_MASK;
+}
+
 				/* mgag200_mode.c */
 int mgag200_modeset_init(struct mga_device *mdev);
 void mgag200_modeset_fini(struct mga_device *mdev);
diff -druNp --no-dereference linux-libre-5.4.5-gnu/drivers/gpu/drm/mgag200/mgag200_main.c linux-libre-5.4.6-gnu/drivers/gpu/drm/mgag200/mgag200_main.c
--- linux-libre-5.4.5-gnu/drivers/gpu/drm/mgag200/mgag200_main.c	2019-12-18 10:09:17.000000000 -0500
+++ linux-libre-5.4.6-gnu/drivers/gpu/drm/mgag200/mgag200_main.c	2019-12-21 05:05:23.000000000 -0500
@@ -94,7 +94,8 @@ static int mgag200_device_init(struct dr
 	struct mga_device *mdev = dev->dev_private;
 	int ret, option;
 
-	mdev->type = flags;
+	mdev->flags = mgag200_flags_from_driver_data(flags);
+	mdev->type = mgag200_type_from_driver_data(flags);
 
 	/* Hardcode the number of CRTCs to 1 */
 	mdev->num_crtc = 1;
diff -druNp --no-dereference linux-libre-5.4.5-gnu/drivers/gpu/drm/nouveau/dispnv50/atom.h linux-libre-5.4.6-gnu/drivers/gpu/drm/nouveau/dispnv50/atom.h
--- linux-libre-5.4.5-gnu/drivers/gpu/drm/nouveau/dispnv50/atom.h	2019-12-18 10:09:17.000000000 -0500
+++ linux-libre-5.4.6-gnu/drivers/gpu/drm/nouveau/dispnv50/atom.h	2019-12-21 05:05:23.000000000 -0500
@@ -114,6 +114,7 @@ struct nv50_head_atom {
 		u8 nhsync:1;
 		u8 nvsync:1;
 		u8 depth:4;
+		u8 bpc;
 	} or;
 
 	/* Currently only used for MST */
diff -druNp --no-dereference linux-libre-5.4.5-gnu/drivers/gpu/drm/nouveau/dispnv50/disp.c linux-libre-5.4.6-gnu/drivers/gpu/drm/nouveau/dispnv50/disp.c
--- linux-libre-5.4.5-gnu/drivers/gpu/drm/nouveau/dispnv50/disp.c	2019-12-18 10:09:17.000000000 -0500
+++ linux-libre-5.4.6-gnu/drivers/gpu/drm/nouveau/dispnv50/disp.c	2019-12-21 05:05:23.000000000 -0500
@@ -353,10 +353,20 @@ nv50_outp_atomic_check(struct drm_encode
 		       struct drm_crtc_state *crtc_state,
 		       struct drm_connector_state *conn_state)
 {
-	struct nouveau_connector *nv_connector =
-		nouveau_connector(conn_state->connector);
-	return nv50_outp_atomic_check_view(encoder, crtc_state, conn_state,
-					   nv_connector->native_mode);
+	struct drm_connector *connector = conn_state->connector;
+	struct nouveau_connector *nv_connector = nouveau_connector(connector);
+	struct nv50_head_atom *asyh = nv50_head_atom(crtc_state);
+	int ret;
+
+	ret = nv50_outp_atomic_check_view(encoder, crtc_state, conn_state,
+					  nv_connector->native_mode);
+	if (ret)
+		return ret;
+
+	if (crtc_state->mode_changed || crtc_state->connectors_changed)
+		asyh->or.bpc = connector->display_info.bpc;
+
+	return 0;
 }
 
 /******************************************************************************
@@ -770,32 +780,54 @@ nv50_msto_atomic_check(struct drm_encode
 	struct nv50_mstm *mstm = mstc->mstm;
 	struct nv50_head_atom *asyh = nv50_head_atom(crtc_state);
 	int slots;
+	int ret;
+
+	ret = nv50_outp_atomic_check_view(encoder, crtc_state, conn_state,
+					  mstc->native);
+	if (ret)
+		return ret;
+
+	if (!crtc_state->mode_changed && !crtc_state->connectors_changed)
+		return 0;
+
+	/*
+	 * When restoring duplicated states, we need to make sure that the bw
+	 * remains the same and avoid recalculating it, as the connector's bpc
+	 * may have changed after the state was duplicated
+	 */
+	if (!state->duplicated) {
+		const int clock = crtc_state->adjusted_mode.clock;
 
-	if (crtc_state->mode_changed || crtc_state->connectors_changed) {
 		/*
-		 * When restoring duplicated states, we need to make sure that
-		 * the bw remains the same and avoid recalculating it, as the
-		 * connector's bpc may have changed after the state was
-		 * duplicated
+		 * XXX: Since we don't use HDR in userspace quite yet, limit
+		 * the bpc to 8 to save bandwidth on the topology. In the
+		 * future, we'll want to properly fix this by dynamically
+		 * selecting the highest possible bpc that would fit in the
+		 * topology
 		 */
-		if (!state->duplicated) {
-			const int bpp = connector->display_info.bpc * 3;
-			const int clock = crtc_state->adjusted_mode.clock;
+		asyh->or.bpc = min(connector->display_info.bpc, 8U);
+		asyh->dp.pbn = drm_dp_calc_pbn_mode(clock, asyh->or.bpc * 3);
+	}
 
-			asyh->dp.pbn = drm_dp_calc_pbn_mode(clock, bpp);
-		}
+	slots = drm_dp_atomic_find_vcpi_slots(state, &mstm->mgr, mstc->port,
+					      asyh->dp.pbn);
+	if (slots < 0)
+		return slots;
 
-		slots = drm_dp_atomic_find_vcpi_slots(state, &mstm->mgr,
-						      mstc->port,
-						      asyh->dp.pbn);
-		if (slots < 0)
-			return slots;
+	asyh->dp.tu = slots;
 
-		asyh->dp.tu = slots;
-	}
+	return 0;
+}
 
-	return nv50_outp_atomic_check_view(encoder, crtc_state, conn_state,
-					   mstc->native);
+static u8
+nv50_dp_bpc_to_depth(unsigned int bpc)
+{
+	switch (bpc) {
+	case  6: return 0x2;
+	case  8: return 0x5;
+	case 10: /* fall-through */
+	default: return 0x6;
+	}
 }
 
 static void
@@ -808,7 +840,7 @@ nv50_msto_enable(struct drm_encoder *enc
 	struct nv50_mstm *mstm = NULL;
 	struct drm_connector *connector;
 	struct drm_connector_list_iter conn_iter;
-	u8 proto, depth;
+	u8 proto;
 	bool r;
 
 	drm_connector_list_iter_begin(encoder->dev, &conn_iter);
@@ -837,14 +869,8 @@ nv50_msto_enable(struct drm_encoder *enc
 	else
 		proto = 0x9;
 
-	switch (mstc->connector.display_info.bpc) {
-	case  6: depth = 0x2; break;
-	case  8: depth = 0x5; break;
-	case 10:
-	default: depth = 0x6; break;
-	}
-
-	mstm->outp->update(mstm->outp, head->base.index, armh, proto, depth);
+	mstm->outp->update(mstm->outp, head->base.index, armh, proto,
+			   nv50_dp_bpc_to_depth(armh->or.bpc));
 
 	msto->head = head;
 	msto->mstc = mstc;
@@ -1498,20 +1524,14 @@ nv50_sor_enable(struct drm_encoder *enco
 					lvds.lvds.script |= 0x0200;
 			}
 
-			if (nv_connector->base.display_info.bpc == 8)
+			if (asyh->or.bpc == 8)
 				lvds.lvds.script |= 0x0200;
 		}
 
 		nvif_mthd(&disp->disp->object, 0, &lvds, sizeof(lvds));
 		break;
 	case DCB_OUTPUT_DP:
-		if (nv_connector->base.display_info.bpc == 6)
-			depth = 0x2;
-		else
-		if (nv_connector->base.display_info.bpc == 8)
-			depth = 0x5;
-		else
-			depth = 0x6;
+		depth = nv50_dp_bpc_to_depth(asyh->or.bpc);
 
 		if (nv_encoder->link & 1)
 			proto = 0x8;
@@ -1662,7 +1682,7 @@ nv50_pior_enable(struct drm_encoder *enc
 	nv50_outp_acquire(nv_encoder);
 
 	nv_connector = nouveau_encoder_connector_get(nv_encoder);
-	switch (nv_connector->base.display_info.bpc) {
+	switch (asyh->or.bpc) {
 	case 10: asyh->or.depth = 0x6; break;
 	case  8: asyh->or.depth = 0x5; break;
 	case  6: asyh->or.depth = 0x2; break;
diff -druNp --no-dereference linux-libre-5.4.5-gnu/drivers/gpu/drm/nouveau/dispnv50/head.c linux-libre-5.4.6-gnu/drivers/gpu/drm/nouveau/dispnv50/head.c
--- linux-libre-5.4.5-gnu/drivers/gpu/drm/nouveau/dispnv50/head.c	2019-12-18 10:09:17.000000000 -0500
+++ linux-libre-5.4.6-gnu/drivers/gpu/drm/nouveau/dispnv50/head.c	2019-12-21 05:05:23.000000000 -0500
@@ -81,18 +81,17 @@ nv50_head_atomic_check_dither(struct nv5
 			      struct nv50_head_atom *asyh,
 			      struct nouveau_conn_atom *asyc)
 {
-	struct drm_connector *connector = asyc->state.connector;
 	u32 mode = 0x00;
 
 	if (asyc->dither.mode == DITHERING_MODE_AUTO) {
-		if (asyh->base.depth > connector->display_info.bpc * 3)
+		if (asyh->base.depth > asyh->or.bpc * 3)
 			mode = DITHERING_MODE_DYNAMIC2X2;
 	} else {
 		mode = asyc->dither.mode;
 	}
 
 	if (asyc->dither.depth == DITHERING_DEPTH_AUTO) {
-		if (connector->display_info.bpc >= 8)
+		if (asyh->or.bpc >= 8)
 			mode |= DITHERING_DEPTH_8BPC;
 	} else {
 		mode |= asyc->dither.depth;
diff -druNp --no-dereference linux-libre-5.4.5-gnu/drivers/gpu/drm/panfrost/panfrost_drv.c linux-libre-5.4.6-gnu/drivers/gpu/drm/panfrost/panfrost_drv.c
--- linux-libre-5.4.5-gnu/drivers/gpu/drm/panfrost/panfrost_drv.c	2019-12-18 10:09:17.000000000 -0500
+++ linux-libre-5.4.6-gnu/drivers/gpu/drm/panfrost/panfrost_drv.c	2019-12-21 05:05:23.000000000 -0500
@@ -303,14 +303,17 @@ static int panfrost_ioctl_mmap_bo(struct
 	}
 
 	/* Don't allow mmapping of heap objects as pages are not pinned. */
-	if (to_panfrost_bo(gem_obj)->is_heap)
-		return -EINVAL;
+	if (to_panfrost_bo(gem_obj)->is_heap) {
+		ret = -EINVAL;
+		goto out;
+	}
 
 	ret = drm_gem_create_mmap_offset(gem_obj);
 	if (ret == 0)
 		args->offset = drm_vma_node_offset_addr(&gem_obj->vma_node);
-	drm_gem_object_put_unlocked(gem_obj);
 
+out:
+	drm_gem_object_put_unlocked(gem_obj);
 	return ret;
 }
 
@@ -347,20 +350,19 @@ static int panfrost_ioctl_madvise(struct
 		return -ENOENT;
 	}
 
+	mutex_lock(&pfdev->shrinker_lock);
 	args->retained = drm_gem_shmem_madvise(gem_obj, args->madv);
 
 	if (args->retained) {
 		struct panfrost_gem_object *bo = to_panfrost_bo(gem_obj);
 
-		mutex_lock(&pfdev->shrinker_lock);
-
 		if (args->madv == PANFROST_MADV_DONTNEED)
-			list_add_tail(&bo->base.madv_list, &pfdev->shrinker_list);
+			list_add_tail(&bo->base.madv_list,
+				      &pfdev->shrinker_list);
 		else if (args->madv == PANFROST_MADV_WILLNEED)
 			list_del_init(&bo->base.madv_list);
-
-		mutex_unlock(&pfdev->shrinker_lock);
 	}
+	mutex_unlock(&pfdev->shrinker_lock);
 
 	drm_gem_object_put_unlocked(gem_obj);
 	return 0;
diff -druNp --no-dereference linux-libre-5.4.5-gnu/drivers/gpu/drm/panfrost/panfrost_gem.c linux-libre-5.4.6-gnu/drivers/gpu/drm/panfrost/panfrost_gem.c
--- linux-libre-5.4.5-gnu/drivers/gpu/drm/panfrost/panfrost_gem.c	2019-12-18 10:09:17.000000000 -0500
+++ linux-libre-5.4.6-gnu/drivers/gpu/drm/panfrost/panfrost_gem.c	2019-12-21 05:05:23.000000000 -0500
@@ -19,6 +19,16 @@ static void panfrost_gem_free_object(str
 	struct panfrost_gem_object *bo = to_panfrost_bo(obj);
 	struct panfrost_device *pfdev = obj->dev->dev_private;
 
+	/*
+	 * Make sure the BO is no longer inserted in the shrinker list before
+	 * taking care of the destruction itself. If we don't do that we have a
+	 * race condition between this function and what's done in
+	 * panfrost_gem_shrinker_scan().
+	 */
+	mutex_lock(&pfdev->shrinker_lock);
+	list_del_init(&bo->base.madv_list);
+	mutex_unlock(&pfdev->shrinker_lock);
+
 	if (bo->sgts) {
 		int i;
 		int n_sgt = bo->base.base.size / SZ_2M;
@@ -33,11 +43,6 @@ static void panfrost_gem_free_object(str
 		kfree(bo->sgts);
 	}
 
-	mutex_lock(&pfdev->shrinker_lock);
-	if (!list_empty(&bo->base.madv_list))
-		list_del(&bo->base.madv_list);
-	mutex_unlock(&pfdev->shrinker_lock);
-
 	drm_gem_shmem_free_object(obj);
 }
 
diff -druNp --no-dereference linux-libre-5.4.5-gnu/drivers/gpu/drm/radeon/r100.c linux-libre-5.4.6-gnu/drivers/gpu/drm/radeon/r100.c
--- linux-libre-5.4.5-gnu/drivers/gpu/drm/radeon/r100.c	2019-12-18 13:21:00.000000000 -0500
+++ linux-libre-5.4.6-gnu/drivers/gpu/drm/radeon/r100.c	2019-12-21 21:56:04.000000000 -0500
@@ -1820,8 +1820,8 @@ static int r100_packet0_check(struct rad
 			track->textures[i].use_pitch = 1;
 		} else {
 			track->textures[i].use_pitch = 0;
-			track->textures[i].width = 1 << ((idx_value >> RADEON_TXFORMAT_WIDTH_SHIFT) & RADEON_TXFORMAT_WIDTH_MASK);
-			track->textures[i].height = 1 << ((idx_value >> RADEON_TXFORMAT_HEIGHT_SHIFT) & RADEON_TXFORMAT_HEIGHT_MASK);
+			track->textures[i].width = 1 << ((idx_value & RADEON_TXFORMAT_WIDTH_MASK) >> RADEON_TXFORMAT_WIDTH_SHIFT);
+			track->textures[i].height = 1 << ((idx_value & RADEON_TXFORMAT_HEIGHT_MASK) >> RADEON_TXFORMAT_HEIGHT_SHIFT);
 		}
 		if (idx_value & RADEON_TXFORMAT_CUBIC_MAP_ENABLE)
 			track->textures[i].tex_coord_type = 2;
diff -druNp --no-dereference linux-libre-5.4.5-gnu/drivers/gpu/drm/radeon/r200.c linux-libre-5.4.6-gnu/drivers/gpu/drm/radeon/r200.c
--- linux-libre-5.4.5-gnu/drivers/gpu/drm/radeon/r200.c	2019-12-18 10:09:17.000000000 -0500
+++ linux-libre-5.4.6-gnu/drivers/gpu/drm/radeon/r200.c	2019-12-21 05:05:23.000000000 -0500
@@ -476,8 +476,8 @@ int r200_packet0_check(struct radeon_cs_
 			track->textures[i].use_pitch = 1;
 		} else {
 			track->textures[i].use_pitch = 0;
-			track->textures[i].width = 1 << ((idx_value >> RADEON_TXFORMAT_WIDTH_SHIFT) & RADEON_TXFORMAT_WIDTH_MASK);
-			track->textures[i].height = 1 << ((idx_value >> RADEON_TXFORMAT_HEIGHT_SHIFT) & RADEON_TXFORMAT_HEIGHT_MASK);
+			track->textures[i].width = 1 << ((idx_value & RADEON_TXFORMAT_WIDTH_MASK) >> RADEON_TXFORMAT_WIDTH_SHIFT);
+			track->textures[i].height = 1 << ((idx_value & RADEON_TXFORMAT_HEIGHT_MASK) >> RADEON_TXFORMAT_HEIGHT_SHIFT);
 		}
 		if (idx_value & R200_TXFORMAT_LOOKUP_DISABLE)
 			track->textures[i].lookup_disable = true;
diff -druNp --no-dereference linux-libre-5.4.5-gnu/drivers/md/dm-clone-metadata.c linux-libre-5.4.6-gnu/drivers/md/dm-clone-metadata.c
--- linux-libre-5.4.5-gnu/drivers/md/dm-clone-metadata.c	2019-12-18 10:09:17.000000000 -0500
+++ linux-libre-5.4.6-gnu/drivers/md/dm-clone-metadata.c	2019-12-21 05:05:23.000000000 -0500
@@ -67,23 +67,34 @@ struct superblock_disk {
  * To save constantly doing look ups on disk we keep an in core copy of the
  * on-disk bitmap, the region_map.
  *
- * To further reduce metadata I/O overhead we use a second bitmap, the dmap
- * (dirty bitmap), which tracks the dirty words, i.e. longs, of the region_map.
+ * In order to track which regions are hydrated during a metadata transaction,
+ * we use a second set of bitmaps, the dmap (dirty bitmap), which includes two
+ * bitmaps, namely dirty_regions and dirty_words. The dirty_regions bitmap
+ * tracks the regions that got hydrated during the current metadata
+ * transaction. The dirty_words bitmap tracks the dirty words, i.e. longs, of
+ * the dirty_regions bitmap.
+ *
+ * This allows us to precisely track the regions that were hydrated during the
+ * current metadata transaction and update the metadata accordingly, when we
+ * commit the current transaction. This is important because dm-clone should
+ * only commit the metadata of regions that were properly flushed to the
+ * destination device beforehand. Otherwise, in case of a crash, we could end
+ * up with a corrupted dm-clone device.
  *
  * When a region finishes hydrating dm-clone calls
  * dm_clone_set_region_hydrated(), or for discard requests
  * dm_clone_cond_set_range(), which sets the corresponding bits in region_map
  * and dmap.
  *
- * During a metadata commit we scan the dmap for dirty region_map words (longs)
- * and update accordingly the on-disk metadata. Thus, we don't have to flush to
- * disk the whole region_map. We can just flush the dirty region_map words.
+ * During a metadata commit we scan dmap->dirty_words and dmap->dirty_regions
+ * and update the on-disk metadata accordingly. Thus, we don't have to flush to
+ * disk the whole region_map. We can just flush the dirty region_map bits.
  *
- * We use a dirty bitmap, which is smaller than the original region_map, to
- * reduce the amount of memory accesses during a metadata commit. As dm-bitset
- * accesses the on-disk bitmap in 64-bit word granularity, there is no
- * significant benefit in tracking the dirty region_map bits with a smaller
- * granularity.
+ * We use the helper dmap->dirty_words bitmap, which is smaller than the
+ * original region_map, to reduce the amount of memory accesses during a
+ * metadata commit. Moreover, as dm-bitset also accesses the on-disk bitmap in
+ * 64-bit word granularity, the dirty_words bitmap helps us avoid useless disk
+ * accesses.
  *
  * We could update directly the on-disk bitmap, when dm-clone calls either
  * dm_clone_set_region_hydrated() or dm_clone_cond_set_range(), buts this
@@ -92,12 +103,13 @@ struct superblock_disk {
  * e.g., in a hooked overwrite bio's completion routine, and further reduce the
  * I/O completion latency.
  *
- * We maintain two dirty bitmaps. During a metadata commit we atomically swap
- * the currently used dmap with the unused one. This allows the metadata update
- * functions to run concurrently with an ongoing commit.
+ * We maintain two dirty bitmap sets. During a metadata commit we atomically
+ * swap the currently used dmap with the unused one. This allows the metadata
+ * update functions to run concurrently with an ongoing commit.
  */
 struct dirty_map {
 	unsigned long *dirty_words;
+	unsigned long *dirty_regions;
 	unsigned int changed;
 };
 
@@ -115,6 +127,9 @@ struct dm_clone_metadata {
 	struct dirty_map dmap[2];
 	struct dirty_map *current_dmap;
 
+	/* Protected by lock */
+	struct dirty_map *committing_dmap;
+
 	/*
 	 * In core copy of the on-disk bitmap to save constantly doing look ups
 	 * on disk.
@@ -461,34 +476,53 @@ static size_t bitmap_size(unsigned long
 	return BITS_TO_LONGS(nr_bits) * sizeof(long);
 }
 
-static int dirty_map_init(struct dm_clone_metadata *cmd)
+static int __dirty_map_init(struct dirty_map *dmap, unsigned long nr_words,
+			    unsigned long nr_regions)
 {
-	cmd->dmap[0].changed = 0;
-	cmd->dmap[0].dirty_words = kvzalloc(bitmap_size(cmd->nr_words), GFP_KERNEL);
+	dmap->changed = 0;
 
-	if (!cmd->dmap[0].dirty_words) {
-		DMERR("Failed to allocate dirty bitmap");
+	dmap->dirty_words = kvzalloc(bitmap_size(nr_words), GFP_KERNEL);
+	if (!dmap->dirty_words)
+		return -ENOMEM;
+
+	dmap->dirty_regions = kvzalloc(bitmap_size(nr_regions), GFP_KERNEL);
+	if (!dmap->dirty_regions) {
+		kvfree(dmap->dirty_words);
 		return -ENOMEM;
 	}
 
-	cmd->dmap[1].changed = 0;
-	cmd->dmap[1].dirty_words = kvzalloc(bitmap_size(cmd->nr_words), GFP_KERNEL);
+	return 0;
+}
 
-	if (!cmd->dmap[1].dirty_words) {
+static void __dirty_map_exit(struct dirty_map *dmap)
+{
+	kvfree(dmap->dirty_words);
+	kvfree(dmap->dirty_regions);
+}
+
+static int dirty_map_init(struct dm_clone_metadata *cmd)
+{
+	if (__dirty_map_init(&cmd->dmap[0], cmd->nr_words, cmd->nr_regions)) {
 		DMERR("Failed to allocate dirty bitmap");
-		kvfree(cmd->dmap[0].dirty_words);
+		return -ENOMEM;
+	}
+
+	if (__dirty_map_init(&cmd->dmap[1], cmd->nr_words, cmd->nr_regions)) {
+		DMERR("Failed to allocate dirty bitmap");
+		__dirty_map_exit(&cmd->dmap[0]);
 		return -ENOMEM;
 	}
 
 	cmd->current_dmap = &cmd->dmap[0];
+	cmd->committing_dmap = NULL;
 
 	return 0;
 }
 
 static void dirty_map_exit(struct dm_clone_metadata *cmd)
 {
-	kvfree(cmd->dmap[0].dirty_words);
-	kvfree(cmd->dmap[1].dirty_words);
+	__dirty_map_exit(&cmd->dmap[0]);
+	__dirty_map_exit(&cmd->dmap[1]);
 }
 
 static int __load_bitset_in_core(struct dm_clone_metadata *cmd)
@@ -633,21 +667,23 @@ unsigned long dm_clone_find_next_unhydra
 	return find_next_zero_bit(cmd->region_map, cmd->nr_regions, start);
 }
 
-static int __update_metadata_word(struct dm_clone_metadata *cmd, unsigned long word)
+static int __update_metadata_word(struct dm_clone_metadata *cmd,
+				  unsigned long *dirty_regions,
+				  unsigned long word)
 {
 	int r;
 	unsigned long index = word * BITS_PER_LONG;
 	unsigned long max_index = min(cmd->nr_regions, (word + 1) * BITS_PER_LONG);
 
 	while (index < max_index) {
-		if (test_bit(index, cmd->region_map)) {
+		if (test_bit(index, dirty_regions)) {
 			r = dm_bitset_set_bit(&cmd->bitset_info, cmd->bitset_root,
 					      index, &cmd->bitset_root);
-
 			if (r) {
 				DMERR("dm_bitset_set_bit failed");
 				return r;
 			}
+			__clear_bit(index, dirty_regions);
 		}
 		index++;
 	}
@@ -721,7 +757,7 @@ static int __flush_dmap(struct dm_clone_
 		if (word == cmd->nr_words)
 			break;
 
-		r = __update_metadata_word(cmd, word);
+		r = __update_metadata_word(cmd, dmap->dirty_regions, word);
 
 		if (r)
 			return r;
@@ -743,16 +779,18 @@ static int __flush_dmap(struct dm_clone_
 	return 0;
 }
 
-int dm_clone_metadata_commit(struct dm_clone_metadata *cmd)
+int dm_clone_metadata_pre_commit(struct dm_clone_metadata *cmd)
 {
-	int r = -EPERM;
+	int r = 0;
 	unsigned long flags;
 	struct dirty_map *dmap, *next_dmap;
 
 	down_write(&cmd->lock);
 
-	if (cmd->fail_io || dm_bm_is_read_only(cmd->bm))
+	if (cmd->fail_io || dm_bm_is_read_only(cmd->bm)) {
+		r = -EPERM;
 		goto out;
+	}
 
 	/* Get current dirty bitmap */
 	dmap = cmd->current_dmap;
@@ -764,7 +802,7 @@ int dm_clone_metadata_commit(struct dm_c
 	 * The last commit failed, so we don't have a clean dirty-bitmap to
 	 * use.
 	 */
-	if (WARN_ON(next_dmap->changed)) {
+	if (WARN_ON(next_dmap->changed || cmd->committing_dmap)) {
 		r = -EINVAL;
 		goto out;
 	}
@@ -774,11 +812,33 @@ int dm_clone_metadata_commit(struct dm_c
 	cmd->current_dmap = next_dmap;
 	spin_unlock_irqrestore(&cmd->bitmap_lock, flags);
 
-	/*
-	 * No one is accessing the old dirty bitmap anymore, so we can flush
-	 * it.
-	 */
-	r = __flush_dmap(cmd, dmap);
+	/* Set old dirty bitmap as currently committing */
+	cmd->committing_dmap = dmap;
+out:
+	up_write(&cmd->lock);
+
+	return r;
+}
+
+int dm_clone_metadata_commit(struct dm_clone_metadata *cmd)
+{
+	int r = -EPERM;
+
+	down_write(&cmd->lock);
+
+	if (cmd->fail_io || dm_bm_is_read_only(cmd->bm))
+		goto out;
+
+	if (WARN_ON(!cmd->committing_dmap)) {
+		r = -EINVAL;
+		goto out;
+	}
+
+	r = __flush_dmap(cmd, cmd->committing_dmap);
+	if (!r) {
+		/* Clear committing dmap */
+		cmd->committing_dmap = NULL;
+	}
 out:
 	up_write(&cmd->lock);
 
@@ -803,6 +863,7 @@ int dm_clone_set_region_hydrated(struct
 	dmap = cmd->current_dmap;
 
 	__set_bit(word, dmap->dirty_words);
+	__set_bit(region_nr, dmap->dirty_regions);
 	__set_bit(region_nr, cmd->region_map);
 	dmap->changed = 1;
 
@@ -831,6 +892,7 @@ int dm_clone_cond_set_range(struct dm_cl
 		if (!test_bit(region_nr, cmd->region_map)) {
 			word = region_nr / BITS_PER_LONG;
 			__set_bit(word, dmap->dirty_words);
+			__set_bit(region_nr, dmap->dirty_regions);
 			__set_bit(region_nr, cmd->region_map);
 			dmap->changed = 1;
 		}
diff -druNp --no-dereference linux-libre-5.4.5-gnu/drivers/md/dm-clone-metadata.h linux-libre-5.4.6-gnu/drivers/md/dm-clone-metadata.h
--- linux-libre-5.4.5-gnu/drivers/md/dm-clone-metadata.h	2019-12-18 10:09:17.000000000 -0500
+++ linux-libre-5.4.6-gnu/drivers/md/dm-clone-metadata.h	2019-12-21 05:05:23.000000000 -0500
@@ -73,7 +73,23 @@ void dm_clone_metadata_close(struct dm_c
 
 /*
  * Commit dm-clone metadata to disk.
+ *
+ * We use a two phase commit:
+ *
+ * 1. dm_clone_metadata_pre_commit(): Prepare the current transaction for
+ *    committing. After this is called, all subsequent metadata updates, done
+ *    through either dm_clone_set_region_hydrated() or
+ *    dm_clone_cond_set_range(), will be part of the **next** transaction.
+ *
+ * 2. dm_clone_metadata_commit(): Actually commit the current transaction to
+ *    disk and start a new transaction.
+ *
+ * This allows dm-clone to flush the destination device after step (1) to
+ * ensure that all freshly hydrated regions, for which we are updating the
+ * metadata, are properly written to non-volatile storage and won't be lost in
+ * case of a crash.
  */
+int dm_clone_metadata_pre_commit(struct dm_clone_metadata *cmd);
 int dm_clone_metadata_commit(struct dm_clone_metadata *cmd);
 
 /*
@@ -110,6 +126,7 @@ int dm_clone_metadata_abort(struct dm_cl
  * Switches metadata to a read only mode. Once read-only mode has been entered
  * the following functions will return -EPERM:
  *
+ *   dm_clone_metadata_pre_commit()
  *   dm_clone_metadata_commit()
  *   dm_clone_set_region_hydrated()
  *   dm_clone_cond_set_range()
diff -druNp --no-dereference linux-libre-5.4.5-gnu/drivers/md/dm-clone-target.c linux-libre-5.4.6-gnu/drivers/md/dm-clone-target.c
--- linux-libre-5.4.5-gnu/drivers/md/dm-clone-target.c	2019-12-18 10:09:17.000000000 -0500
+++ linux-libre-5.4.6-gnu/drivers/md/dm-clone-target.c	2019-12-21 05:05:23.000000000 -0500
@@ -86,6 +86,12 @@ struct clone {
 
 	struct dm_clone_metadata *cmd;
 
+	/*
+	 * bio used to flush the destination device, before committing the
+	 * metadata.
+	 */
+	struct bio flush_bio;
+
 	/* Region hydration hash table */
 	struct hash_table_bucket *ht;
 
@@ -1106,10 +1112,13 @@ static bool need_commit_due_to_time(stru
 /*
  * A non-zero return indicates read-only or fail mode.
  */
-static int commit_metadata(struct clone *clone)
+static int commit_metadata(struct clone *clone, bool *dest_dev_flushed)
 {
 	int r = 0;
 
+	if (dest_dev_flushed)
+		*dest_dev_flushed = false;
+
 	mutex_lock(&clone->commit_lock);
 
 	if (!dm_clone_changed_this_transaction(clone->cmd))
@@ -1120,8 +1129,26 @@ static int commit_metadata(struct clone
 		goto out;
 	}
 
-	r = dm_clone_metadata_commit(clone->cmd);
+	r = dm_clone_metadata_pre_commit(clone->cmd);
+	if (unlikely(r)) {
+		__metadata_operation_failed(clone, "dm_clone_metadata_pre_commit", r);
+		goto out;
+	}
+
+	bio_reset(&clone->flush_bio);
+	bio_set_dev(&clone->flush_bio, clone->dest_dev->bdev);
+	clone->flush_bio.bi_opf = REQ_OP_WRITE | REQ_PREFLUSH;
 
+	r = submit_bio_wait(&clone->flush_bio);
+	if (unlikely(r)) {
+		__metadata_operation_failed(clone, "flush destination device", r);
+		goto out;
+	}
+
+	if (dest_dev_flushed)
+		*dest_dev_flushed = true;
+
+	r = dm_clone_metadata_commit(clone->cmd);
 	if (unlikely(r)) {
 		__metadata_operation_failed(clone, "dm_clone_metadata_commit", r);
 		goto out;
@@ -1194,6 +1221,7 @@ static void process_deferred_flush_bios(
 {
 	struct bio *bio;
 	unsigned long flags;
+	bool dest_dev_flushed;
 	struct bio_list bios = BIO_EMPTY_LIST;
 	struct bio_list bio_completions = BIO_EMPTY_LIST;
 
@@ -1213,7 +1241,7 @@ static void process_deferred_flush_bios(
 	    !(dm_clone_changed_this_transaction(clone->cmd) && need_commit_due_to_time(clone)))
 		return;
 
-	if (commit_metadata(clone)) {
+	if (commit_metadata(clone, &dest_dev_flushed)) {
 		bio_list_merge(&bios, &bio_completions);
 
 		while ((bio = bio_list_pop(&bios)))
@@ -1227,8 +1255,17 @@ static void process_deferred_flush_bios(
 	while ((bio = bio_list_pop(&bio_completions)))
 		bio_endio(bio);
 
-	while ((bio = bio_list_pop(&bios)))
-		generic_make_request(bio);
+	while ((bio = bio_list_pop(&bios))) {
+		if ((bio->bi_opf & REQ_PREFLUSH) && dest_dev_flushed) {
+			/* We just flushed the destination device as part of
+			 * the metadata commit, so there is no reason to send
+			 * another flush.
+			 */
+			bio_endio(bio);
+		} else {
+			generic_make_request(bio);
+		}
+	}
 }
 
 static void do_worker(struct work_struct *work)
@@ -1400,7 +1437,7 @@ static void clone_status(struct dm_targe
 
 		/* Commit to ensure statistics aren't out-of-date */
 		if (!(status_flags & DM_STATUS_NOFLUSH_FLAG) && !dm_suspended(ti))
-			(void) commit_metadata(clone);
+			(void) commit_metadata(clone, NULL);
 
 		r = dm_clone_get_free_metadata_block_count(clone->cmd, &nr_free_metadata_blocks);
 
@@ -1834,6 +1871,7 @@ static int clone_ctr(struct dm_target *t
 	bio_list_init(&clone->deferred_flush_completions);
 	clone->hydration_offset = 0;
 	atomic_set(&clone->hydrations_in_flight, 0);
+	bio_init(&clone->flush_bio, NULL, 0);
 
 	clone->wq = alloc_workqueue("dm-" DM_MSG_PREFIX, WQ_MEM_RECLAIM, 0);
 	if (!clone->wq) {
@@ -1907,6 +1945,7 @@ static void clone_dtr(struct dm_target *
 	struct clone *clone = ti->private;
 
 	mutex_destroy(&clone->commit_lock);
+	bio_uninit(&clone->flush_bio);
 
 	for (i = 0; i < clone->nr_ctr_args; i++)
 		kfree(clone->ctr_args[i]);
@@ -1961,7 +2000,7 @@ static void clone_postsuspend(struct dm_
 	wait_event(clone->hydration_stopped, !atomic_read(&clone->hydrations_in_flight));
 	flush_workqueue(clone->wq);
 
-	(void) commit_metadata(clone);
+	(void) commit_metadata(clone, NULL);
 }
 
 static void clone_resume(struct dm_target *ti)
diff -druNp --no-dereference linux-libre-5.4.5-gnu/drivers/md/dm-mpath.c linux-libre-5.4.6-gnu/drivers/md/dm-mpath.c
--- linux-libre-5.4.5-gnu/drivers/md/dm-mpath.c	2019-12-18 10:09:17.000000000 -0500
+++ linux-libre-5.4.6-gnu/drivers/md/dm-mpath.c	2019-12-21 05:05:23.000000000 -0500
@@ -599,45 +599,10 @@ static struct pgpath *__map_bio(struct m
 	return pgpath;
 }
 
-static struct pgpath *__map_bio_fast(struct multipath *m, struct bio *bio)
-{
-	struct pgpath *pgpath;
-	unsigned long flags;
-
-	/* Do we need to select a new pgpath? */
-	/*
-	 * FIXME: currently only switching path if no path (due to failure, etc)
-	 * - which negates the point of using a path selector
-	 */
-	pgpath = READ_ONCE(m->current_pgpath);
-	if (!pgpath)
-		pgpath = choose_pgpath(m, bio->bi_iter.bi_size);
-
-	if (!pgpath) {
-		if (test_bit(MPATHF_QUEUE_IF_NO_PATH, &m->flags)) {
-			/* Queue for the daemon to resubmit */
-			spin_lock_irqsave(&m->lock, flags);
-			bio_list_add(&m->queued_bios, bio);
-			spin_unlock_irqrestore(&m->lock, flags);
-			queue_work(kmultipathd, &m->process_queued_bios);
-
-			return ERR_PTR(-EAGAIN);
-		}
-		return NULL;
-	}
-
-	return pgpath;
-}
-
 static int __multipath_map_bio(struct multipath *m, struct bio *bio,
 			       struct dm_mpath_io *mpio)
 {
-	struct pgpath *pgpath;
-
-	if (!m->hw_handler_name)
-		pgpath = __map_bio_fast(m, bio);
-	else
-		pgpath = __map_bio(m, bio);
+	struct pgpath *pgpath = __map_bio(m, bio);
 
 	if (IS_ERR(pgpath))
 		return DM_MAPIO_SUBMITTED;
diff -druNp --no-dereference linux-libre-5.4.5-gnu/drivers/md/dm-thin.c linux-libre-5.4.6-gnu/drivers/md/dm-thin.c
--- linux-libre-5.4.5-gnu/drivers/md/dm-thin.c	2019-12-18 10:09:17.000000000 -0500
+++ linux-libre-5.4.6-gnu/drivers/md/dm-thin.c	2019-12-21 05:05:23.000000000 -0500
@@ -328,6 +328,7 @@ struct pool_c {
 	dm_block_t low_water_blocks;
 	struct pool_features requested_pf; /* Features requested during table load */
 	struct pool_features adjusted_pf;  /* Features used after adjusting for constituent devices */
+	struct bio flush_bio;
 };
 
 /*
@@ -2392,8 +2393,16 @@ static void process_deferred_bios(struct
 	while ((bio = bio_list_pop(&bio_completions)))
 		bio_endio(bio);
 
-	while ((bio = bio_list_pop(&bios)))
-		generic_make_request(bio);
+	while ((bio = bio_list_pop(&bios))) {
+		/*
+		 * The data device was flushed as part of metadata commit,
+		 * so complete redundant flushes immediately.
+		 */
+		if (bio->bi_opf & REQ_PREFLUSH)
+			bio_endio(bio);
+		else
+			generic_make_request(bio);
+	}
 }
 
 static void do_worker(struct work_struct *ws)
@@ -3127,6 +3136,7 @@ static void pool_dtr(struct dm_target *t
 	__pool_dec(pt->pool);
 	dm_put_device(ti, pt->metadata_dev);
 	dm_put_device(ti, pt->data_dev);
+	bio_uninit(&pt->flush_bio);
 	kfree(pt);
 
 	mutex_unlock(&dm_thin_pool_table.mutex);
@@ -3192,6 +3202,29 @@ static void metadata_low_callback(void *
 	dm_table_event(pool->ti->table);
 }
 
+/*
+ * We need to flush the data device **before** committing the metadata.
+ *
+ * This ensures that the data blocks of any newly inserted mappings are
+ * properly written to non-volatile storage and won't be lost in case of a
+ * crash.
+ *
+ * Failure to do so can result in data corruption in the case of internal or
+ * external snapshots and in the case of newly provisioned blocks, when block
+ * zeroing is enabled.
+ */
+static int metadata_pre_commit_callback(void *context)
+{
+	struct pool_c *pt = context;
+	struct bio *flush_bio = &pt->flush_bio;
+
+	bio_reset(flush_bio);
+	bio_set_dev(flush_bio, pt->data_dev->bdev);
+	flush_bio->bi_opf = REQ_OP_WRITE | REQ_PREFLUSH;
+
+	return submit_bio_wait(flush_bio);
+}
+
 static sector_t get_dev_size(struct block_device *bdev)
 {
 	return i_size_read(bdev->bd_inode) >> SECTOR_SHIFT;
@@ -3360,6 +3393,7 @@ static int pool_ctr(struct dm_target *ti
 	pt->data_dev = data_dev;
 	pt->low_water_blocks = low_water_blocks;
 	pt->adjusted_pf = pt->requested_pf = pf;
+	bio_init(&pt->flush_bio, NULL, 0);
 	ti->num_flush_bios = 1;
 
 	/*
@@ -3386,6 +3420,10 @@ static int pool_ctr(struct dm_target *ti
 	if (r)
 		goto out_flags_changed;
 
+	dm_pool_register_pre_commit_callback(pt->pool->pmd,
+					     metadata_pre_commit_callback,
+					     pt);
+
 	pt->callbacks.congested_fn = pool_is_congested;
 	dm_table_add_target_callbacks(ti->table, &pt->callbacks);
 
diff -druNp --no-dereference linux-libre-5.4.5-gnu/drivers/md/dm-thin-metadata.c linux-libre-5.4.6-gnu/drivers/md/dm-thin-metadata.c
--- linux-libre-5.4.5-gnu/drivers/md/dm-thin-metadata.c	2019-12-18 10:09:17.000000000 -0500
+++ linux-libre-5.4.6-gnu/drivers/md/dm-thin-metadata.c	2019-12-21 05:05:23.000000000 -0500
@@ -189,6 +189,15 @@ struct dm_pool_metadata {
 	sector_t data_block_size;
 
 	/*
+	 * Pre-commit callback.
+	 *
+	 * This allows the thin provisioning target to run a callback before
+	 * the metadata are committed.
+	 */
+	dm_pool_pre_commit_fn pre_commit_fn;
+	void *pre_commit_context;
+
+	/*
 	 * We reserve a section of the metadata for commit overhead.
 	 * All reported space does *not* include this.
 	 */
@@ -826,6 +835,14 @@ static int __commit_transaction(struct d
 	if (unlikely(!pmd->in_service))
 		return 0;
 
+	if (pmd->pre_commit_fn) {
+		r = pmd->pre_commit_fn(pmd->pre_commit_context);
+		if (r < 0) {
+			DMERR("pre-commit callback failed");
+			return r;
+		}
+	}
+
 	r = __write_changed_details(pmd);
 	if (r < 0)
 		return r;
@@ -892,6 +909,8 @@ struct dm_pool_metadata *dm_pool_metadat
 	pmd->in_service = false;
 	pmd->bdev = bdev;
 	pmd->data_block_size = data_block_size;
+	pmd->pre_commit_fn = NULL;
+	pmd->pre_commit_context = NULL;
 
 	r = __create_persistent_data_objects(pmd, format_device);
 	if (r) {
@@ -2044,6 +2063,16 @@ int dm_pool_register_metadata_threshold(
 	return r;
 }
 
+void dm_pool_register_pre_commit_callback(struct dm_pool_metadata *pmd,
+					  dm_pool_pre_commit_fn fn,
+					  void *context)
+{
+	pmd_write_lock_in_core(pmd);
+	pmd->pre_commit_fn = fn;
+	pmd->pre_commit_context = context;
+	pmd_write_unlock(pmd);
+}
+
 int dm_pool_metadata_set_needs_check(struct dm_pool_metadata *pmd)
 {
 	int r = -EINVAL;
diff -druNp --no-dereference linux-libre-5.4.5-gnu/drivers/md/dm-thin-metadata.h linux-libre-5.4.6-gnu/drivers/md/dm-thin-metadata.h
--- linux-libre-5.4.5-gnu/drivers/md/dm-thin-metadata.h	2019-12-18 10:09:17.000000000 -0500
+++ linux-libre-5.4.6-gnu/drivers/md/dm-thin-metadata.h	2019-12-21 05:05:23.000000000 -0500
@@ -230,6 +230,13 @@ bool dm_pool_metadata_needs_check(struct
  */
 void dm_pool_issue_prefetches(struct dm_pool_metadata *pmd);
 
+/* Pre-commit callback */
+typedef int (*dm_pool_pre_commit_fn)(void *context);
+
+void dm_pool_register_pre_commit_callback(struct dm_pool_metadata *pmd,
+					  dm_pool_pre_commit_fn fn,
+					  void *context);
+
 /*----------------------------------------------------------------*/
 
 #endif
diff -druNp --no-dereference linux-libre-5.4.5-gnu/drivers/md/persistent-data/dm-btree-remove.c linux-libre-5.4.6-gnu/drivers/md/persistent-data/dm-btree-remove.c
--- linux-libre-5.4.5-gnu/drivers/md/persistent-data/dm-btree-remove.c	2019-12-18 10:09:17.000000000 -0500
+++ linux-libre-5.4.6-gnu/drivers/md/persistent-data/dm-btree-remove.c	2019-12-21 05:05:23.000000000 -0500
@@ -203,7 +203,13 @@ static void __rebalance2(struct dm_btree
 	struct btree_node *right = r->n;
 	uint32_t nr_left = le32_to_cpu(left->header.nr_entries);
 	uint32_t nr_right = le32_to_cpu(right->header.nr_entries);
-	unsigned threshold = 2 * merge_threshold(left) + 1;
+	/*
+	 * Ensure the number of entries in each child will be greater
+	 * than or equal to (max_entries / 3 + 1), so no matter which
+	 * child is used for removal, the number will still be not
+	 * less than (max_entries / 3).
+	 */
+	unsigned int threshold = 2 * (merge_threshold(left) + 1);
 
 	if (nr_left + nr_right < threshold) {
 		/*
diff -druNp --no-dereference linux-libre-5.4.5-gnu/drivers/mmc/core/block.c linux-libre-5.4.6-gnu/drivers/mmc/core/block.c
--- linux-libre-5.4.5-gnu/drivers/mmc/core/block.c	2019-12-18 10:09:17.000000000 -0500
+++ linux-libre-5.4.6-gnu/drivers/mmc/core/block.c	2019-12-21 05:05:23.000000000 -0500
@@ -408,38 +408,6 @@ static int mmc_blk_ioctl_copy_to_user(st
 	return 0;
 }
 
-static int ioctl_rpmb_card_status_poll(struct mmc_card *card, u32 *status,
-				       u32 retries_max)
-{
-	int err;
-	u32 retry_count = 0;
-
-	if (!status || !retries_max)
-		return -EINVAL;
-
-	do {
-		err = __mmc_send_status(card, status, 5);
-		if (err)
-			break;
-
-		if (!R1_STATUS(*status) &&
-				(R1_CURRENT_STATE(*status) != R1_STATE_PRG))
-			break; /* RPMB programming operation complete */
-
-		/*
-		 * Rechedule to give the MMC device a chance to continue
-		 * processing the previous command without being polled too
-		 * frequently.
-		 */
-		usleep_range(1000, 5000);
-	} while (++retry_count < retries_max);
-
-	if (retry_count == retries_max)
-		err = -EPERM;
-
-	return err;
-}
-
 static int ioctl_do_sanitize(struct mmc_card *card)
 {
 	int err;
@@ -468,6 +436,58 @@ out:
 	return err;
 }
 
+static inline bool mmc_blk_in_tran_state(u32 status)
+{
+	/*
+	 * Some cards mishandle the status bits, so make sure to check both the
+	 * busy indication and the card state.
+	 */
+	return status & R1_READY_FOR_DATA &&
+	       (R1_CURRENT_STATE(status) == R1_STATE_TRAN);
+}
+
+static int card_busy_detect(struct mmc_card *card, unsigned int timeout_ms,
+			    u32 *resp_errs)
+{
+	unsigned long timeout = jiffies + msecs_to_jiffies(timeout_ms);
+	int err = 0;
+	u32 status;
+
+	do {
+		bool done = time_after(jiffies, timeout);
+
+		err = __mmc_send_status(card, &status, 5);
+		if (err) {
+			dev_err(mmc_dev(card->host),
+				"error %d requesting status\n", err);
+			return err;
+		}
+
+		/* Accumulate any response error bits seen */
+		if (resp_errs)
+			*resp_errs |= status;
+
+		/*
+		 * Timeout if the device never becomes ready for data and never
+		 * leaves the program state.
+		 */
+		if (done) {
+			dev_err(mmc_dev(card->host),
+				"Card stuck in wrong state! %s status: %#x\n",
+				 __func__, status);
+			return -ETIMEDOUT;
+		}
+
+		/*
+		 * Some cards mishandle the status bits,
+		 * so make sure to check both the busy
+		 * indication and the card state.
+		 */
+	} while (!mmc_blk_in_tran_state(status));
+
+	return err;
+}
+
 static int __mmc_blk_ioctl_cmd(struct mmc_card *card, struct mmc_blk_data *md,
 			       struct mmc_blk_ioc_data *idata)
 {
@@ -477,7 +497,6 @@ static int __mmc_blk_ioctl_cmd(struct mm
 	struct scatterlist sg;
 	int err;
 	unsigned int target_part;
-	u32 status = 0;
 
 	if (!card || !md || !idata)
 		return -EINVAL;
@@ -611,16 +630,12 @@ static int __mmc_blk_ioctl_cmd(struct mm
 
 	memcpy(&(idata->ic.response), cmd.resp, sizeof(cmd.resp));
 
-	if (idata->rpmb) {
+	if (idata->rpmb || (cmd.flags & MMC_RSP_R1B)) {
 		/*
-		 * Ensure RPMB command has completed by polling CMD13
+		 * Ensure RPMB/R1B command has completed by polling CMD13
 		 * "Send Status".
 		 */
-		err = ioctl_rpmb_card_status_poll(card, &status, 5);
-		if (err)
-			dev_err(mmc_dev(card->host),
-					"%s: Card Status=0x%08X, error %d\n",
-					__func__, status, err);
+		err = card_busy_detect(card, MMC_BLK_TIMEOUT_MS, NULL);
 	}
 
 	return err;
@@ -970,58 +985,6 @@ static unsigned int mmc_blk_data_timeout
 	return ms;
 }
 
-static inline bool mmc_blk_in_tran_state(u32 status)
-{
-	/*
-	 * Some cards mishandle the status bits, so make sure to check both the
-	 * busy indication and the card state.
-	 */
-	return status & R1_READY_FOR_DATA &&
-	       (R1_CURRENT_STATE(status) == R1_STATE_TRAN);
-}
-
-static int card_busy_detect(struct mmc_card *card, unsigned int timeout_ms,
-			    struct request *req, u32 *resp_errs)
-{
-	unsigned long timeout = jiffies + msecs_to_jiffies(timeout_ms);
-	int err = 0;
-	u32 status;
-
-	do {
-		bool done = time_after(jiffies, timeout);
-
-		err = __mmc_send_status(card, &status, 5);
-		if (err) {
-			pr_err("%s: error %d requesting status\n",
-			       req->rq_disk->disk_name, err);
-			return err;
-		}
-
-		/* Accumulate any response error bits seen */
-		if (resp_errs)
-			*resp_errs |= status;
-
-		/*
-		 * Timeout if the device never becomes ready for data and never
-		 * leaves the program state.
-		 */
-		if (done) {
-			pr_err("%s: Card stuck in wrong state! %s %s status: %#x\n",
-				mmc_hostname(card->host),
-				req->rq_disk->disk_name, __func__, status);
-			return -ETIMEDOUT;
-		}
-
-		/*
-		 * Some cards mishandle the status bits,
-		 * so make sure to check both the busy
-		 * indication and the card state.
-		 */
-	} while (!mmc_blk_in_tran_state(status));
-
-	return err;
-}
-
 static int mmc_blk_reset(struct mmc_blk_data *md, struct mmc_host *host,
 			 int type)
 {
@@ -1671,7 +1634,7 @@ static int mmc_blk_fix_state(struct mmc_
 
 	mmc_blk_send_stop(card, timeout);
 
-	err = card_busy_detect(card, timeout, req, NULL);
+	err = card_busy_detect(card, timeout, NULL);
 
 	mmc_retune_release(card->host);
 
@@ -1895,7 +1858,7 @@ static int mmc_blk_card_busy(struct mmc_
 	if (mmc_host_is_spi(card->host) || rq_data_dir(req) == READ)
 		return 0;
 
-	err = card_busy_detect(card, MMC_BLK_TIMEOUT_MS, req, &status);
+	err = card_busy_detect(card, MMC_BLK_TIMEOUT_MS, &status);
 
 	/*
 	 * Do not assume data transferred correctly if there are any error bits
diff -druNp --no-dereference linux-libre-5.4.5-gnu/drivers/mmc/core/core.c linux-libre-5.4.6-gnu/drivers/mmc/core/core.c
--- linux-libre-5.4.5-gnu/drivers/mmc/core/core.c	2019-12-18 10:09:17.000000000 -0500
+++ linux-libre-5.4.6-gnu/drivers/mmc/core/core.c	2019-12-21 05:05:23.000000000 -0500
@@ -1469,8 +1469,7 @@ void mmc_detach_bus(struct mmc_host *hos
 	mmc_bus_put(host);
 }
 
-static void _mmc_detect_change(struct mmc_host *host, unsigned long delay,
-				bool cd_irq)
+void _mmc_detect_change(struct mmc_host *host, unsigned long delay, bool cd_irq)
 {
 	/*
 	 * If the device is configured as wakeup, we prevent a new sleep for
@@ -2129,7 +2128,7 @@ int mmc_hw_reset(struct mmc_host *host)
 	ret = host->bus_ops->hw_reset(host);
 	mmc_bus_put(host);
 
-	if (ret)
+	if (ret < 0)
 		pr_warn("%s: tried to HW reset card, got error %d\n",
 			mmc_hostname(host), ret);
 
@@ -2297,11 +2296,8 @@ void mmc_rescan(struct work_struct *work
 
 	mmc_bus_get(host);
 
-	/*
-	 * if there is a _removable_ card registered, check whether it is
-	 * still present
-	 */
-	if (host->bus_ops && !host->bus_dead && mmc_card_is_removable(host))
+	/* Verify a registered card to be functional, else remove it. */
+	if (host->bus_ops && !host->bus_dead)
 		host->bus_ops->detect(host);
 
 	host->detect_change = 0;
diff -druNp --no-dereference linux-libre-5.4.5-gnu/drivers/mmc/core/core.h linux-libre-5.4.6-gnu/drivers/mmc/core/core.h
--- linux-libre-5.4.5-gnu/drivers/mmc/core/core.h	2019-12-18 10:09:17.000000000 -0500
+++ linux-libre-5.4.6-gnu/drivers/mmc/core/core.h	2019-12-21 05:05:23.000000000 -0500
@@ -70,6 +70,8 @@ void mmc_rescan(struct work_struct *work
 void mmc_start_host(struct mmc_host *host);
 void mmc_stop_host(struct mmc_host *host);
 
+void _mmc_detect_change(struct mmc_host *host, unsigned long delay,
+			bool cd_irq);
 int _mmc_detect_card_removed(struct mmc_host *host);
 int mmc_detect_card_removed(struct mmc_host *host);
 
diff -druNp --no-dereference linux-libre-5.4.5-gnu/drivers/mmc/core/sdio_bus.c linux-libre-5.4.6-gnu/drivers/mmc/core/sdio_bus.c
--- linux-libre-5.4.5-gnu/drivers/mmc/core/sdio_bus.c	2019-12-18 10:09:17.000000000 -0500
+++ linux-libre-5.4.6-gnu/drivers/mmc/core/sdio_bus.c	2019-12-21 05:05:23.000000000 -0500
@@ -138,6 +138,8 @@ static int sdio_bus_probe(struct device
 	if (ret)
 		return ret;
 
+	atomic_inc(&func->card->sdio_funcs_probed);
+
 	/* Unbound SDIO functions are always suspended.
 	 * During probe, the function is set active and the usage count
 	 * is incremented.  If the driver supports runtime PM,
@@ -153,7 +155,10 @@ static int sdio_bus_probe(struct device
 	/* Set the default block size so the driver is sure it's something
 	 * sensible. */
 	sdio_claim_host(func);
-	ret = sdio_set_block_size(func, 0);
+	if (mmc_card_removed(func->card))
+		ret = -ENOMEDIUM;
+	else
+		ret = sdio_set_block_size(func, 0);
 	sdio_release_host(func);
 	if (ret)
 		goto disable_runtimepm;
@@ -165,6 +170,7 @@ static int sdio_bus_probe(struct device
 	return 0;
 
 disable_runtimepm:
+	atomic_dec(&func->card->sdio_funcs_probed);
 	if (func->card->host->caps & MMC_CAP_POWER_OFF_CARD)
 		pm_runtime_put_noidle(dev);
 	dev_pm_domain_detach(dev, false);
@@ -181,6 +187,7 @@ static int sdio_bus_remove(struct device
 		pm_runtime_get_sync(dev);
 
 	drv->remove(func);
+	atomic_dec(&func->card->sdio_funcs_probed);
 
 	if (func->irq_handler) {
 		pr_warn("WARNING: driver %s did not remove its interrupt handler!\n",
diff -druNp --no-dereference linux-libre-5.4.5-gnu/drivers/mmc/core/sdio.c linux-libre-5.4.6-gnu/drivers/mmc/core/sdio.c
--- linux-libre-5.4.5-gnu/drivers/mmc/core/sdio.c	2019-12-18 10:09:17.000000000 -0500
+++ linux-libre-5.4.6-gnu/drivers/mmc/core/sdio.c	2019-12-21 05:05:23.000000000 -0500
@@ -1048,9 +1048,35 @@ static int mmc_sdio_runtime_resume(struc
 	return ret;
 }
 
+/*
+ * SDIO HW reset
+ *
+ * Returns 0 if the HW reset was executed synchronously, returns 1 if the HW
+ * reset was asynchronously scheduled, else a negative error code.
+ */
 static int mmc_sdio_hw_reset(struct mmc_host *host)
 {
-	mmc_power_cycle(host, host->card->ocr);
+	struct mmc_card *card = host->card;
+
+	/*
+	 * In case the card is shared among multiple func drivers, reset the
+	 * card through a rescan work. In this way it will be removed and
+	 * re-detected, thus all func drivers becomes informed about it.
+	 */
+	if (atomic_read(&card->sdio_funcs_probed) > 1) {
+		if (mmc_card_removed(card))
+			return 1;
+		host->rescan_entered = 0;
+		mmc_card_set_removed(card);
+		_mmc_detect_change(host, 0, false);
+		return 1;
+	}
+
+	/*
+	 * A single func driver has been probed, then let's skip the heavy
+	 * hotplug dance above and execute the reset immediately.
+	 */
+	mmc_power_cycle(host, card->ocr);
 	return mmc_sdio_reinit_card(host);
 }
 
diff -druNp --no-dereference linux-libre-5.4.5-gnu/drivers/pci/controller/pcie-rcar.c linux-libre-5.4.6-gnu/drivers/pci/controller/pcie-rcar.c
--- linux-libre-5.4.5-gnu/drivers/pci/controller/pcie-rcar.c	2019-12-18 10:09:17.000000000 -0500
+++ linux-libre-5.4.6-gnu/drivers/pci/controller/pcie-rcar.c	2019-12-21 05:05:23.000000000 -0500
@@ -93,8 +93,11 @@
 #define  LINK_SPEED_2_5GTS	(1 << 16)
 #define  LINK_SPEED_5_0GTS	(2 << 16)
 #define MACCTLR			0x011058
+#define  MACCTLR_NFTS_MASK	GENMASK(23, 16)	/* The name is from SH7786 */
 #define  SPEED_CHANGE		BIT(24)
 #define  SCRAMBLE_DISABLE	BIT(27)
+#define  LTSMDIS		BIT(31)
+#define  MACCTLR_INIT_VAL	(LTSMDIS | MACCTLR_NFTS_MASK)
 #define PMSR			0x01105c
 #define MACS2R			0x011078
 #define MACCGSPSETR		0x011084
@@ -615,6 +618,8 @@ static int rcar_pcie_hw_init(struct rcar
 	if (IS_ENABLED(CONFIG_PCI_MSI))
 		rcar_pci_write_reg(pcie, 0x801f0000, PCIEMSITXR);
 
+	rcar_pci_write_reg(pcie, MACCTLR_INIT_VAL, MACCTLR);
+
 	/* Finish initialization - establish a PCI Express link */
 	rcar_pci_write_reg(pcie, CFINIT, PCIETCTLR);
 
@@ -1237,6 +1242,7 @@ static int rcar_pcie_resume_noirq(struct
 		return 0;
 
 	/* Re-establish the PCIe link */
+	rcar_pci_write_reg(pcie, MACCTLR_INIT_VAL, MACCTLR);
 	rcar_pci_write_reg(pcie, CFINIT, PCIETCTLR);
 	return rcar_pcie_wait_for_dl(pcie);
 }
diff -druNp --no-dereference linux-libre-5.4.5-gnu/drivers/pci/hotplug/pciehp_ctrl.c linux-libre-5.4.6-gnu/drivers/pci/hotplug/pciehp_ctrl.c
--- linux-libre-5.4.5-gnu/drivers/pci/hotplug/pciehp_ctrl.c	2019-12-18 10:09:17.000000000 -0500
+++ linux-libre-5.4.6-gnu/drivers/pci/hotplug/pciehp_ctrl.c	2019-12-21 05:05:23.000000000 -0500
@@ -375,7 +375,8 @@ int pciehp_sysfs_enable_slot(struct hotp
 		ctrl->request_result = -ENODEV;
 		pciehp_request(ctrl, PCI_EXP_SLTSTA_PDC);
 		wait_event(ctrl->requester,
-			   !atomic_read(&ctrl->pending_events));
+			   !atomic_read(&ctrl->pending_events) &&
+			   !ctrl->ist_running);
 		return ctrl->request_result;
 	case POWERON_STATE:
 		ctrl_info(ctrl, "Slot(%s): Already in powering on state\n",
@@ -408,7 +409,8 @@ int pciehp_sysfs_disable_slot(struct hot
 		mutex_unlock(&ctrl->state_lock);
 		pciehp_request(ctrl, DISABLE_SLOT);
 		wait_event(ctrl->requester,
-			   !atomic_read(&ctrl->pending_events));
+			   !atomic_read(&ctrl->pending_events) &&
+			   !ctrl->ist_running);
 		return ctrl->request_result;
 	case POWEROFF_STATE:
 		ctrl_info(ctrl, "Slot(%s): Already in powering off state\n",
diff -druNp --no-dereference linux-libre-5.4.5-gnu/drivers/pci/hotplug/pciehp.h linux-libre-5.4.6-gnu/drivers/pci/hotplug/pciehp.h
--- linux-libre-5.4.5-gnu/drivers/pci/hotplug/pciehp.h	2019-12-18 10:09:17.000000000 -0500
+++ linux-libre-5.4.6-gnu/drivers/pci/hotplug/pciehp.h	2019-12-21 05:05:23.000000000 -0500
@@ -72,6 +72,7 @@ extern int pciehp_poll_time;
  * @reset_lock: prevents access to the Data Link Layer Link Active bit in the
  *	Link Status register and to the Presence Detect State bit in the Slot
  *	Status register during a slot reset which may cause them to flap
+ * @ist_running: flag to keep user request waiting while IRQ thread is running
  * @request_result: result of last user request submitted to the IRQ thread
  * @requester: wait queue to wake up on completion of user request,
  *	used for synchronous slot enable/disable request via sysfs
@@ -101,6 +102,7 @@ struct controller {
 
 	struct hotplug_slot hotplug_slot;	/* hotplug core interface */
 	struct rw_semaphore reset_lock;
+	unsigned int ist_running;
 	int request_result;
 	wait_queue_head_t requester;
 };
diff -druNp --no-dereference linux-libre-5.4.5-gnu/drivers/pci/hotplug/pciehp_hpc.c linux-libre-5.4.6-gnu/drivers/pci/hotplug/pciehp_hpc.c
--- linux-libre-5.4.5-gnu/drivers/pci/hotplug/pciehp_hpc.c	2019-12-18 10:09:17.000000000 -0500
+++ linux-libre-5.4.6-gnu/drivers/pci/hotplug/pciehp_hpc.c	2019-12-21 05:05:23.000000000 -0500
@@ -583,6 +583,7 @@ static irqreturn_t pciehp_ist(int irq, v
 	irqreturn_t ret;
 	u32 events;
 
+	ctrl->ist_running = true;
 	pci_config_pm_runtime_get(pdev);
 
 	/* rerun pciehp_isr() if the port was inaccessible on interrupt */
@@ -629,6 +630,7 @@ static irqreturn_t pciehp_ist(int irq, v
 	up_read(&ctrl->reset_lock);
 
 	pci_config_pm_runtime_put(pdev);
+	ctrl->ist_running = false;
 	wake_up(&ctrl->requester);
 	return IRQ_HANDLED;
 }
diff -druNp --no-dereference linux-libre-5.4.5-gnu/drivers/pci/msi.c linux-libre-5.4.6-gnu/drivers/pci/msi.c
--- linux-libre-5.4.5-gnu/drivers/pci/msi.c	2019-12-18 10:09:17.000000000 -0500
+++ linux-libre-5.4.6-gnu/drivers/pci/msi.c	2019-12-21 05:05:23.000000000 -0500
@@ -213,12 +213,13 @@ u32 __pci_msix_desc_mask_irq(struct msi_
 
 	if (pci_msi_ignore_mask)
 		return 0;
+
 	desc_addr = pci_msix_desc_addr(desc);
 	if (!desc_addr)
 		return 0;
 
 	mask_bits &= ~PCI_MSIX_ENTRY_CTRL_MASKBIT;
-	if (flag)
+	if (flag & PCI_MSIX_ENTRY_CTRL_MASKBIT)
 		mask_bits |= PCI_MSIX_ENTRY_CTRL_MASKBIT;
 
 	writel(mask_bits, desc_addr + PCI_MSIX_ENTRY_VECTOR_CTRL);
diff -druNp --no-dereference linux-libre-5.4.5-gnu/drivers/pci/pci-driver.c linux-libre-5.4.6-gnu/drivers/pci/pci-driver.c
--- linux-libre-5.4.5-gnu/drivers/pci/pci-driver.c	2019-12-18 10:09:17.000000000 -0500
+++ linux-libre-5.4.6-gnu/drivers/pci/pci-driver.c	2019-12-21 05:05:23.000000000 -0500
@@ -1076,17 +1076,22 @@ static int pci_pm_thaw_noirq(struct devi
 			return error;
 	}
 
-	if (pci_has_legacy_pm_support(pci_dev))
-		return pci_legacy_resume_early(dev);
-
 	/*
-	 * pci_restore_state() requires the device to be in D0 (because of MSI
-	 * restoration among other things), so force it into D0 in case the
-	 * driver's "freeze" callbacks put it into a low-power state directly.
+	 * Both the legacy ->resume_early() and the new pm->thaw_noirq()
+	 * callbacks assume the device has been returned to D0 and its
+	 * config state has been restored.
+	 *
+	 * In addition, pci_restore_state() restores MSI-X state in MMIO
+	 * space, which requires the device to be in D0, so return it to D0
+	 * in case the driver's "freeze" callbacks put it into a low-power
+	 * state.
 	 */
 	pci_set_power_state(pci_dev, PCI_D0);
 	pci_restore_state(pci_dev);
 
+	if (pci_has_legacy_pm_support(pci_dev))
+		return pci_legacy_resume_early(dev);
+
 	if (drv && drv->pm && drv->pm->thaw_noirq)
 		error = drv->pm->thaw_noirq(dev);
 
diff -druNp --no-dereference linux-libre-5.4.5-gnu/drivers/pci/probe.c linux-libre-5.4.6-gnu/drivers/pci/probe.c
--- linux-libre-5.4.5-gnu/drivers/pci/probe.c	2019-12-18 10:09:17.000000000 -0500
+++ linux-libre-5.4.6-gnu/drivers/pci/probe.c	2019-12-21 05:05:23.000000000 -0500
@@ -1089,14 +1089,15 @@ static unsigned int pci_scan_child_bus_e
  * @sec: updated with secondary bus number from EA
  * @sub: updated with subordinate bus number from EA
  *
- * If @dev is a bridge with EA capability, update @sec and @sub with
- * fixed bus numbers from the capability and return true.  Otherwise,
- * return false.
+ * If @dev is a bridge with EA capability that specifies valid secondary
+ * and subordinate bus numbers, return true with the bus numbers in @sec
+ * and @sub.  Otherwise return false.
  */
 static bool pci_ea_fixed_busnrs(struct pci_dev *dev, u8 *sec, u8 *sub)
 {
 	int ea, offset;
 	u32 dw;
+	u8 ea_sec, ea_sub;
 
 	if (dev->hdr_type != PCI_HEADER_TYPE_BRIDGE)
 		return false;
@@ -1108,8 +1109,13 @@ static bool pci_ea_fixed_busnrs(struct p
 
 	offset = ea + PCI_EA_FIRST_ENT;
 	pci_read_config_dword(dev, offset, &dw);
-	*sec =  dw & PCI_EA_SEC_BUS_MASK;
-	*sub = (dw & PCI_EA_SUB_BUS_MASK) >> PCI_EA_SUB_BUS_SHIFT;
+	ea_sec =  dw & PCI_EA_SEC_BUS_MASK;
+	ea_sub = (dw & PCI_EA_SUB_BUS_MASK) >> PCI_EA_SUB_BUS_SHIFT;
+	if (ea_sec  == 0 || ea_sub < ea_sec)
+		return false;
+
+	*sec = ea_sec;
+	*sub = ea_sub;
 	return true;
 }
 
diff -druNp --no-dereference linux-libre-5.4.5-gnu/drivers/pci/quirks.c linux-libre-5.4.6-gnu/drivers/pci/quirks.c
--- linux-libre-5.4.5-gnu/drivers/pci/quirks.c	2019-12-18 10:09:17.000000000 -0500
+++ linux-libre-5.4.6-gnu/drivers/pci/quirks.c	2019-12-21 05:05:23.000000000 -0500
@@ -4313,15 +4313,21 @@ static int pci_quirk_amd_sb_acs(struct p
 
 static bool pci_quirk_cavium_acs_match(struct pci_dev *dev)
 {
+	if (!pci_is_pcie(dev) || pci_pcie_type(dev) != PCI_EXP_TYPE_ROOT_PORT)
+		return false;
+
+	switch (dev->device) {
 	/*
-	 * Effectively selects all downstream ports for whole ThunderX 1
-	 * family by 0xf800 mask (which represents 8 SoCs), while the lower
-	 * bits of device ID are used to indicate which subdevice is used
-	 * within the SoC.
+	 * Effectively selects all downstream ports for whole ThunderX1
+	 * (which represents 8 SoCs).
 	 */
-	return (pci_is_pcie(dev) &&
-		(pci_pcie_type(dev) == PCI_EXP_TYPE_ROOT_PORT) &&
-		((dev->device & 0xf800) == 0xa000));
+	case 0xa000 ... 0xa7ff: /* ThunderX1 */
+	case 0xaf84:  /* ThunderX2 */
+	case 0xb884:  /* ThunderX3 */
+		return true;
+	default:
+		return false;
+	}
 }
 
 static int pci_quirk_cavium_acs(struct pci_dev *dev, u16 acs_flags)
@@ -4706,7 +4712,7 @@ int pci_dev_specific_acs_enabled(struct
 #define INTEL_BSPR_REG_BPPD  (1 << 9)
 
 /* Upstream Peer Decode Configuration Register */
-#define INTEL_UPDCR_REG 0x1114
+#define INTEL_UPDCR_REG 0x1014
 /* 5:0 Peer Decode Enable bits */
 #define INTEL_UPDCR_REG_MASK 0x3f
 
diff -druNp --no-dereference linux-libre-5.4.5-gnu/drivers/pci/switch/switchtec.c linux-libre-5.4.6-gnu/drivers/pci/switch/switchtec.c
--- linux-libre-5.4.5-gnu/drivers/pci/switch/switchtec.c	2019-12-18 10:09:17.000000000 -0500
+++ linux-libre-5.4.6-gnu/drivers/pci/switch/switchtec.c	2019-12-21 05:05:23.000000000 -0500
@@ -675,7 +675,7 @@ static int ioctl_event_summary(struct sw
 		return -ENOMEM;
 
 	s->global = ioread32(&stdev->mmio_sw_event->global_summary);
-	s->part_bitmap = ioread32(&stdev->mmio_sw_event->part_event_bitmap);
+	s->part_bitmap = ioread64(&stdev->mmio_sw_event->part_event_bitmap);
 	s->local_part = ioread32(&stdev->mmio_part_cfg->part_event_summary);
 
 	for (i = 0; i < stdev->partition_count; i++) {
diff -druNp --no-dereference linux-libre-5.4.5-gnu/drivers/rpmsg/qcom_glink_native.c linux-libre-5.4.6-gnu/drivers/rpmsg/qcom_glink_native.c
--- linux-libre-5.4.5-gnu/drivers/rpmsg/qcom_glink_native.c	2019-12-18 10:09:17.000000000 -0500
+++ linux-libre-5.4.6-gnu/drivers/rpmsg/qcom_glink_native.c	2019-12-21 05:05:23.000000000 -0500
@@ -241,10 +241,31 @@ static void qcom_glink_channel_release(s
 {
 	struct glink_channel *channel = container_of(ref, struct glink_channel,
 						     refcount);
+	struct glink_core_rx_intent *intent;
+	struct glink_core_rx_intent *tmp;
 	unsigned long flags;
+	int iid;
+
+	/* cancel pending rx_done work */
+	cancel_work_sync(&channel->intent_work);
 
 	spin_lock_irqsave(&channel->intent_lock, flags);
+	/* Free all non-reuse intents pending rx_done work */
+	list_for_each_entry_safe(intent, tmp, &channel->done_intents, node) {
+		if (!intent->reuse) {
+			kfree(intent->data);
+			kfree(intent);
+		}
+	}
+
+	idr_for_each_entry(&channel->liids, tmp, iid) {
+		kfree(tmp->data);
+		kfree(tmp);
+	}
 	idr_destroy(&channel->liids);
+
+	idr_for_each_entry(&channel->riids, tmp, iid)
+		kfree(tmp);
 	idr_destroy(&channel->riids);
 	spin_unlock_irqrestore(&channel->intent_lock, flags);
 
@@ -1094,13 +1115,12 @@ static int qcom_glink_create_remote(stru
 close_link:
 	/*
 	 * Send a close request to "undo" our open-ack. The close-ack will
-	 * release the last reference.
+	 * release qcom_glink_send_open_req() reference and the last reference
+	 * will be relesed after receiving remote_close or transport unregister
+	 * by calling qcom_glink_native_remove().
 	 */
 	qcom_glink_send_close_req(glink, channel);
 
-	/* Release qcom_glink_send_open_req() reference */
-	kref_put(&channel->refcount, qcom_glink_channel_release);
-
 	return ret;
 }
 
@@ -1415,15 +1435,13 @@ static int qcom_glink_rx_open(struct qco
 
 		ret = rpmsg_register_device(rpdev);
 		if (ret)
-			goto free_rpdev;
+			goto rcid_remove;
 
 		channel->rpdev = rpdev;
 	}
 
 	return 0;
 
-free_rpdev:
-	kfree(rpdev);
 rcid_remove:
 	spin_lock_irqsave(&glink->idr_lock, flags);
 	idr_remove(&glink->rcids, channel->rcid);
@@ -1544,6 +1562,18 @@ static void qcom_glink_work(struct work_
 	}
 }
 
+static void qcom_glink_cancel_rx_work(struct qcom_glink *glink)
+{
+	struct glink_defer_cmd *dcmd;
+	struct glink_defer_cmd *tmp;
+
+	/* cancel any pending deferred rx_work */
+	cancel_work_sync(&glink->rx_work);
+
+	list_for_each_entry_safe(dcmd, tmp, &glink->rx_queue, node)
+		kfree(dcmd);
+}
+
 struct qcom_glink *qcom_glink_native_probe(struct device *dev,
 					   unsigned long features,
 					   struct qcom_glink_pipe *rx,
@@ -1619,23 +1649,24 @@ void qcom_glink_native_remove(struct qco
 	struct glink_channel *channel;
 	int cid;
 	int ret;
-	unsigned long flags;
 
 	disable_irq(glink->irq);
-	cancel_work_sync(&glink->rx_work);
+	qcom_glink_cancel_rx_work(glink);
 
 	ret = device_for_each_child(glink->dev, NULL, qcom_glink_remove_device);
 	if (ret)
 		dev_warn(glink->dev, "Can't remove GLINK devices: %d\n", ret);
 
-	spin_lock_irqsave(&glink->idr_lock, flags);
 	/* Release any defunct local channels, waiting for close-ack */
 	idr_for_each_entry(&glink->lcids, channel, cid)
 		kref_put(&channel->refcount, qcom_glink_channel_release);
 
+	/* Release any defunct local channels, waiting for close-req */
+	idr_for_each_entry(&glink->rcids, channel, cid)
+		kref_put(&channel->refcount, qcom_glink_channel_release);
+
 	idr_destroy(&glink->lcids);
 	idr_destroy(&glink->rcids);
-	spin_unlock_irqrestore(&glink->idr_lock, flags);
 	mbox_free_channel(glink->mbox_chan);
 }
 EXPORT_SYMBOL_GPL(qcom_glink_native_remove);
diff -druNp --no-dereference linux-libre-5.4.5-gnu/drivers/rpmsg/qcom_glink_smem.c linux-libre-5.4.6-gnu/drivers/rpmsg/qcom_glink_smem.c
--- linux-libre-5.4.5-gnu/drivers/rpmsg/qcom_glink_smem.c	2019-12-18 10:09:17.000000000 -0500
+++ linux-libre-5.4.6-gnu/drivers/rpmsg/qcom_glink_smem.c	2019-12-21 05:05:23.000000000 -0500
@@ -105,7 +105,7 @@ static void glink_smem_rx_advance(struct
 	tail = le32_to_cpu(*pipe->tail);
 
 	tail += count;
-	if (tail > pipe->native.length)
+	if (tail >= pipe->native.length)
 		tail -= pipe->native.length;
 
 	*pipe->tail = cpu_to_le32(tail);
diff -druNp --no-dereference linux-libre-5.4.5-gnu/drivers/scsi/libiscsi.c linux-libre-5.4.6-gnu/drivers/scsi/libiscsi.c
--- linux-libre-5.4.5-gnu/drivers/scsi/libiscsi.c	2019-12-18 10:09:17.000000000 -0500
+++ linux-libre-5.4.6-gnu/drivers/scsi/libiscsi.c	2019-12-21 05:05:23.000000000 -0500
@@ -1945,7 +1945,7 @@ enum blk_eh_timer_return iscsi_eh_cmd_ti
 
 	ISCSI_DBG_EH(session, "scsi cmd %p timedout\n", sc);
 
-	spin_lock(&session->frwd_lock);
+	spin_lock_bh(&session->frwd_lock);
 	task = (struct iscsi_task *)sc->SCp.ptr;
 	if (!task) {
 		/*
@@ -2072,7 +2072,7 @@ enum blk_eh_timer_return iscsi_eh_cmd_ti
 done:
 	if (task)
 		task->last_timeout = jiffies;
-	spin_unlock(&session->frwd_lock);
+	spin_unlock_bh(&session->frwd_lock);
 	ISCSI_DBG_EH(session, "return %s\n", rc == BLK_EH_RESET_TIMER ?
 		     "timer reset" : "shutdown or nh");
 	return rc;
diff -druNp --no-dereference linux-libre-5.4.5-gnu/drivers/scsi/qla2xxx/qla_attr.c linux-libre-5.4.6-gnu/drivers/scsi/qla2xxx/qla_attr.c
--- linux-libre-5.4.5-gnu/drivers/scsi/qla2xxx/qla_attr.c	2019-12-18 10:09:17.000000000 -0500
+++ linux-libre-5.4.6-gnu/drivers/scsi/qla2xxx/qla_attr.c	2019-12-21 05:05:23.000000000 -0500
@@ -176,6 +176,7 @@ qla2x00_sysfs_read_nvram(struct file *fi
 
 	faddr = ha->flt_region_nvram;
 	if (IS_QLA28XX(ha)) {
+		qla28xx_get_aux_images(vha, &active_regions);
 		if (active_regions.aux.vpd_nvram == QLA27XX_SECONDARY_IMAGE)
 			faddr = ha->flt_region_nvram_sec;
 	}
diff -druNp --no-dereference linux-libre-5.4.5-gnu/drivers/scsi/qla2xxx/qla_bsg.c linux-libre-5.4.6-gnu/drivers/scsi/qla2xxx/qla_bsg.c
--- linux-libre-5.4.5-gnu/drivers/scsi/qla2xxx/qla_bsg.c	2019-12-18 10:09:17.000000000 -0500
+++ linux-libre-5.4.6-gnu/drivers/scsi/qla2xxx/qla_bsg.c	2019-12-21 05:05:23.000000000 -0500
@@ -2399,7 +2399,7 @@ qla2x00_get_flash_image_status(struct bs
 	struct qla_active_regions regions = { };
 	struct active_regions active_regions = { };
 
-	qla28xx_get_aux_images(vha, &active_regions);
+	qla27xx_get_active_image(vha, &active_regions);
 	regions.global_image = active_regions.global;
 
 	if (IS_QLA28XX(ha)) {
diff -druNp --no-dereference linux-libre-5.4.5-gnu/drivers/scsi/qla2xxx/qla_fw.h linux-libre-5.4.6-gnu/drivers/scsi/qla2xxx/qla_fw.h
--- linux-libre-5.4.5-gnu/drivers/scsi/qla2xxx/qla_fw.h	2019-12-18 10:09:17.000000000 -0500
+++ linux-libre-5.4.6-gnu/drivers/scsi/qla2xxx/qla_fw.h	2019-12-21 05:05:23.000000000 -0500
@@ -1523,6 +1523,10 @@ struct qla_flt_header {
 #define FLT_REG_NVRAM_SEC_28XX_1	0x10F
 #define FLT_REG_NVRAM_SEC_28XX_2	0x111
 #define FLT_REG_NVRAM_SEC_28XX_3	0x113
+#define FLT_REG_MPI_PRI_28XX		0xD3
+#define FLT_REG_MPI_SEC_28XX		0xF0
+#define FLT_REG_PEP_PRI_28XX		0xD1
+#define FLT_REG_PEP_SEC_28XX		0xF1
 
 struct qla_flt_region {
 	uint16_t code;
diff -druNp --no-dereference linux-libre-5.4.5-gnu/drivers/scsi/qla2xxx/qla_init.c linux-libre-5.4.6-gnu/drivers/scsi/qla2xxx/qla_init.c
--- linux-libre-5.4.5-gnu/drivers/scsi/qla2xxx/qla_init.c	2019-12-18 10:09:17.000000000 -0500
+++ linux-libre-5.4.6-gnu/drivers/scsi/qla2xxx/qla_init.c	2019-12-21 05:05:23.000000000 -0500
@@ -534,6 +534,7 @@ static int qla_post_els_plogi_work(struc
 
 	e->u.fcport.fcport = fcport;
 	fcport->flags |= FCF_ASYNC_ACTIVE;
+	fcport->disc_state = DSC_LOGIN_PEND;
 	return qla2x00_post_work(vha, e);
 }
 
@@ -4847,6 +4848,7 @@ qla2x00_alloc_fcport(scsi_qla_host_t *vh
 	}
 
 	INIT_WORK(&fcport->del_work, qla24xx_delete_sess_fn);
+	INIT_WORK(&fcport->free_work, qlt_free_session_done);
 	INIT_WORK(&fcport->reg_work, qla_register_fcport_fn);
 	INIT_LIST_HEAD(&fcport->gnl_entry);
 	INIT_LIST_HEAD(&fcport->list);
diff -druNp --no-dereference linux-libre-5.4.5-gnu/drivers/scsi/qla2xxx/qla_sup.c linux-libre-5.4.6-gnu/drivers/scsi/qla2xxx/qla_sup.c
--- linux-libre-5.4.5-gnu/drivers/scsi/qla2xxx/qla_sup.c	2019-12-18 10:09:17.000000000 -0500
+++ linux-libre-5.4.6-gnu/drivers/scsi/qla2xxx/qla_sup.c	2019-12-21 05:05:23.000000000 -0500
@@ -847,15 +847,15 @@ qla2xxx_get_flt_info(scsi_qla_host_t *vh
 				ha->flt_region_img_status_pri = start;
 			break;
 		case FLT_REG_IMG_SEC_27XX:
-			if (IS_QLA27XX(ha) && !IS_QLA28XX(ha))
+			if (IS_QLA27XX(ha) || IS_QLA28XX(ha))
 				ha->flt_region_img_status_sec = start;
 			break;
 		case FLT_REG_FW_SEC_27XX:
-			if (IS_QLA27XX(ha) && !IS_QLA28XX(ha))
+			if (IS_QLA27XX(ha) || IS_QLA28XX(ha))
 				ha->flt_region_fw_sec = start;
 			break;
 		case FLT_REG_BOOTLOAD_SEC_27XX:
-			if (IS_QLA27XX(ha) && !IS_QLA28XX(ha))
+			if (IS_QLA27XX(ha) || IS_QLA28XX(ha))
 				ha->flt_region_boot_sec = start;
 			break;
 		case FLT_REG_AUX_IMG_PRI_28XX:
@@ -2725,8 +2725,11 @@ qla28xx_write_flash_data(scsi_qla_host_t
 		ql_log(ql_log_warn + ql_dbg_verbose, vha, 0xffff,
 		    "Region %x is secure\n", region.code);
 
-		if (region.code == FLT_REG_FW ||
-		    region.code == FLT_REG_FW_SEC_27XX) {
+		switch (region.code) {
+		case FLT_REG_FW:
+		case FLT_REG_FW_SEC_27XX:
+		case FLT_REG_MPI_PRI_28XX:
+		case FLT_REG_MPI_SEC_28XX:
 			fw_array = dwptr;
 
 			/* 1st fw array */
@@ -2757,9 +2760,23 @@ qla28xx_write_flash_data(scsi_qla_host_t
 				buf_size_without_sfub += risc_size;
 				fw_array += risc_size;
 			}
-		} else {
-			ql_log(ql_log_warn + ql_dbg_verbose, vha, 0xffff,
-			    "Secure region %x not supported\n",
+			break;
+
+		case FLT_REG_PEP_PRI_28XX:
+		case FLT_REG_PEP_SEC_28XX:
+			fw_array = dwptr;
+
+			/* 1st fw array */
+			risc_size = be32_to_cpu(fw_array[3]);
+			risc_attr = be32_to_cpu(fw_array[9]);
+
+			buf_size_without_sfub = risc_size;
+			fw_array += risc_size;
+			break;
+
+		default:
+			ql_log(ql_log_warn + ql_dbg_verbose, vha,
+			    0xffff, "Secure region %x not supported\n",
 			    region.code);
 			rval = QLA_COMMAND_ERROR;
 			goto done;
@@ -2880,7 +2897,7 @@ qla28xx_write_flash_data(scsi_qla_host_t
 			    "Sending Secure Flash MB Cmd\n");
 			rval = qla28xx_secure_flash_update(vha, 0, region.code,
 				buf_size_without_sfub, sfub_dma,
-				sizeof(struct secure_flash_update_block));
+				sizeof(struct secure_flash_update_block) >> 2);
 			if (rval != QLA_SUCCESS) {
 				ql_log(ql_log_warn, vha, 0xffff,
 				    "Secure Flash MB Cmd failed %x.", rval);
diff -druNp --no-dereference linux-libre-5.4.5-gnu/drivers/scsi/qla2xxx/qla_target.c linux-libre-5.4.6-gnu/drivers/scsi/qla2xxx/qla_target.c
--- linux-libre-5.4.5-gnu/drivers/scsi/qla2xxx/qla_target.c	2019-12-18 10:09:17.000000000 -0500
+++ linux-libre-5.4.6-gnu/drivers/scsi/qla2xxx/qla_target.c	2019-12-21 05:05:23.000000000 -0500
@@ -1160,7 +1160,6 @@ void qlt_unreg_sess(struct fc_port *sess
 	sess->last_rscn_gen = sess->rscn_gen;
 	sess->last_login_gen = sess->login_gen;
 
-	INIT_WORK(&sess->free_work, qlt_free_session_done);
 	queue_work(sess->vha->hw->wq, &sess->free_work);
 }
 EXPORT_SYMBOL(qlt_unreg_sess);
diff -druNp --no-dereference linux-libre-5.4.5-gnu/drivers/scsi/qla2xxx/tcm_qla2xxx.c linux-libre-5.4.6-gnu/drivers/scsi/qla2xxx/tcm_qla2xxx.c
--- linux-libre-5.4.5-gnu/drivers/scsi/qla2xxx/tcm_qla2xxx.c	2019-12-18 10:09:17.000000000 -0500
+++ linux-libre-5.4.6-gnu/drivers/scsi/qla2xxx/tcm_qla2xxx.c	2019-12-21 05:05:23.000000000 -0500
@@ -246,6 +246,8 @@ static void tcm_qla2xxx_complete_mcmd(st
  */
 static void tcm_qla2xxx_free_mcmd(struct qla_tgt_mgmt_cmd *mcmd)
 {
+	if (!mcmd)
+		return;
 	INIT_WORK(&mcmd->free_work, tcm_qla2xxx_complete_mcmd);
 	queue_work(tcm_qla2xxx_free_wq, &mcmd->free_work);
 }
diff -druNp --no-dereference linux-libre-5.4.5-gnu/drivers/scsi/ufs/cdns-pltfrm.c linux-libre-5.4.6-gnu/drivers/scsi/ufs/cdns-pltfrm.c
--- linux-libre-5.4.5-gnu/drivers/scsi/ufs/cdns-pltfrm.c	2019-12-18 10:09:17.000000000 -0500
+++ linux-libre-5.4.6-gnu/drivers/scsi/ufs/cdns-pltfrm.c	2019-12-21 05:05:23.000000000 -0500
@@ -99,6 +99,12 @@ static int cdns_ufs_link_startup_notify(
 	 */
 	ufshcd_dme_set(hba, UIC_ARG_MIB(PA_LOCAL_TX_LCC_ENABLE), 0);
 
+	/*
+	 * Disabling Autohibern8 feature in cadence UFS
+	 * to mask unexpected interrupt trigger.
+	 */
+	hba->ahit = 0;
+
 	return 0;
 }
 
diff -druNp --no-dereference linux-libre-5.4.5-gnu/drivers/usb/core/hcd.c linux-libre-5.4.6-gnu/drivers/usb/core/hcd.c
--- linux-libre-5.4.5-gnu/drivers/usb/core/hcd.c	2019-12-18 10:09:17.000000000 -0500
+++ linux-libre-5.4.6-gnu/drivers/usb/core/hcd.c	2019-12-21 05:05:23.000000000 -0500
@@ -1409,7 +1409,17 @@ int usb_hcd_map_urb_for_dma(struct usb_h
 	if (usb_endpoint_xfer_control(&urb->ep->desc)) {
 		if (hcd->self.uses_pio_for_control)
 			return ret;
-		if (hcd_uses_dma(hcd)) {
+		if (hcd->localmem_pool) {
+			ret = hcd_alloc_coherent(
+					urb->dev->bus, mem_flags,
+					&urb->setup_dma,
+					(void **)&urb->setup_packet,
+					sizeof(struct usb_ctrlrequest),
+					DMA_TO_DEVICE);
+			if (ret)
+				return ret;
+			urb->transfer_flags |= URB_SETUP_MAP_LOCAL;
+		} else if (hcd_uses_dma(hcd)) {
 			if (is_vmalloc_addr(urb->setup_packet)) {
 				WARN_ONCE(1, "setup packet is not dma capable\n");
 				return -EAGAIN;
@@ -1427,23 +1437,22 @@ int usb_hcd_map_urb_for_dma(struct usb_h
 						urb->setup_dma))
 				return -EAGAIN;
 			urb->transfer_flags |= URB_SETUP_MAP_SINGLE;
-		} else if (hcd->localmem_pool) {
-			ret = hcd_alloc_coherent(
-					urb->dev->bus, mem_flags,
-					&urb->setup_dma,
-					(void **)&urb->setup_packet,
-					sizeof(struct usb_ctrlrequest),
-					DMA_TO_DEVICE);
-			if (ret)
-				return ret;
-			urb->transfer_flags |= URB_SETUP_MAP_LOCAL;
 		}
 	}
 
 	dir = usb_urb_dir_in(urb) ? DMA_FROM_DEVICE : DMA_TO_DEVICE;
 	if (urb->transfer_buffer_length != 0
 	    && !(urb->transfer_flags & URB_NO_TRANSFER_DMA_MAP)) {
-		if (hcd_uses_dma(hcd)) {
+		if (hcd->localmem_pool) {
+			ret = hcd_alloc_coherent(
+					urb->dev->bus, mem_flags,
+					&urb->transfer_dma,
+					&urb->transfer_buffer,
+					urb->transfer_buffer_length,
+					dir);
+			if (ret == 0)
+				urb->transfer_flags |= URB_MAP_LOCAL;
+		} else if (hcd_uses_dma(hcd)) {
 			if (urb->num_sgs) {
 				int n;
 
@@ -1497,15 +1506,6 @@ int usb_hcd_map_urb_for_dma(struct usb_h
 				else
 					urb->transfer_flags |= URB_DMA_MAP_SINGLE;
 			}
-		} else if (hcd->localmem_pool) {
-			ret = hcd_alloc_coherent(
-					urb->dev->bus, mem_flags,
-					&urb->transfer_dma,
-					&urb->transfer_buffer,
-					urb->transfer_buffer_length,
-					dir);
-			if (ret == 0)
-				urb->transfer_flags |= URB_MAP_LOCAL;
 		}
 		if (ret && (urb->transfer_flags & (URB_SETUP_MAP_SINGLE |
 				URB_SETUP_MAP_LOCAL)))
diff -druNp --no-dereference linux-libre-5.4.5-gnu/drivers/usb/storage/scsiglue.c linux-libre-5.4.6-gnu/drivers/usb/storage/scsiglue.c
--- linux-libre-5.4.5-gnu/drivers/usb/storage/scsiglue.c	2019-12-18 10:09:17.000000000 -0500
+++ linux-libre-5.4.6-gnu/drivers/usb/storage/scsiglue.c	2019-12-21 05:05:23.000000000 -0500
@@ -135,7 +135,8 @@ static int slave_configure(struct scsi_d
 	 * For such controllers we need to make sure the block layer sets
 	 * up bounce buffers in addressable memory.
 	 */
-	if (!hcd_uses_dma(bus_to_hcd(us->pusb_dev->bus)))
+	if (!hcd_uses_dma(bus_to_hcd(us->pusb_dev->bus)) ||
+			(bus_to_hcd(us->pusb_dev->bus)->localmem_pool != NULL))
 		blk_queue_bounce_limit(sdev->request_queue, BLK_BOUNCE_HIGH);
 
 	/*
diff -druNp --no-dereference linux-libre-5.4.5-gnu/drivers/vfio/pci/vfio_pci_intrs.c linux-libre-5.4.6-gnu/drivers/vfio/pci/vfio_pci_intrs.c
--- linux-libre-5.4.5-gnu/drivers/vfio/pci/vfio_pci_intrs.c	2019-12-18 10:09:17.000000000 -0500
+++ linux-libre-5.4.6-gnu/drivers/vfio/pci/vfio_pci_intrs.c	2019-12-21 05:05:23.000000000 -0500
@@ -294,8 +294,8 @@ static int vfio_msi_set_vector_signal(st
 	irq = pci_irq_vector(pdev, vector);
 
 	if (vdev->ctx[vector].trigger) {
-		free_irq(irq, vdev->ctx[vector].trigger);
 		irq_bypass_unregister_producer(&vdev->ctx[vector].producer);
+		free_irq(irq, vdev->ctx[vector].trigger);
 		kfree(vdev->ctx[vector].name);
 		eventfd_ctx_put(vdev->ctx[vector].trigger);
 		vdev->ctx[vector].trigger = NULL;
diff -druNp --no-dereference linux-libre-5.4.5-gnu/fs/cifs/cifs_debug.c linux-libre-5.4.6-gnu/fs/cifs/cifs_debug.c
--- linux-libre-5.4.5-gnu/fs/cifs/cifs_debug.c	2019-12-18 10:09:17.000000000 -0500
+++ linux-libre-5.4.6-gnu/fs/cifs/cifs_debug.c	2019-12-21 05:05:23.000000000 -0500
@@ -256,6 +256,11 @@ static int cifs_debug_data_proc_show(str
 		if (!server->rdma)
 			goto skip_rdma;
 
+		if (!server->smbd_conn) {
+			seq_printf(m, "\nSMBDirect transport not available");
+			goto skip_rdma;
+		}
+
 		seq_printf(m, "\nSMBDirect (in hex) protocol version: %x "
 			"transport status: %x",
 			server->smbd_conn->protocol,
diff -druNp --no-dereference linux-libre-5.4.5-gnu/fs/cifs/cifsglob.h linux-libre-5.4.6-gnu/fs/cifs/cifsglob.h
--- linux-libre-5.4.5-gnu/fs/cifs/cifsglob.h	2019-12-18 10:09:17.000000000 -0500
+++ linux-libre-5.4.6-gnu/fs/cifs/cifsglob.h	2019-12-21 05:05:23.000000000 -0500
@@ -1524,6 +1524,7 @@ struct mid_q_entry {
 	struct TCP_Server_Info *server;	/* server corresponding to this mid */
 	__u64 mid;		/* multiplex id */
 	__u16 credits;		/* number of credits consumed by this mid */
+	__u16 credits_received;	/* number of credits from the response */
 	__u32 pid;		/* process id */
 	__u32 sequence_number;  /* for CIFS signing */
 	unsigned long when_alloc;  /* when mid was created */
diff -druNp --no-dereference linux-libre-5.4.5-gnu/fs/cifs/connect.c linux-libre-5.4.6-gnu/fs/cifs/connect.c
--- linux-libre-5.4.5-gnu/fs/cifs/connect.c	2019-12-18 10:09:17.000000000 -0500
+++ linux-libre-5.4.6-gnu/fs/cifs/connect.c	2019-12-21 05:05:23.000000000 -0500
@@ -905,6 +905,20 @@ dequeue_mid(struct mid_q_entry *mid, boo
 	spin_unlock(&GlobalMid_Lock);
 }
 
+static unsigned int
+smb2_get_credits_from_hdr(char *buffer, struct TCP_Server_Info *server)
+{
+	struct smb2_sync_hdr *shdr = (struct smb2_sync_hdr *)buffer;
+
+	/*
+	 * SMB1 does not use credits.
+	 */
+	if (server->vals->header_preamble_size)
+		return 0;
+
+	return le16_to_cpu(shdr->CreditRequest);
+}
+
 static void
 handle_mid(struct mid_q_entry *mid, struct TCP_Server_Info *server,
 	   char *buf, int malformed)
@@ -912,6 +926,7 @@ handle_mid(struct mid_q_entry *mid, stru
 	if (server->ops->check_trans2 &&
 	    server->ops->check_trans2(mid, server, buf, malformed))
 		return;
+	mid->credits_received = smb2_get_credits_from_hdr(buf, server);
 	mid->resp_buf = buf;
 	mid->large_buf = server->large_buf;
 	/* Was previous buf put in mpx struct for multi-rsp? */
@@ -1222,12 +1237,6 @@ next_pdu:
 		for (i = 0; i < num_mids; i++) {
 			if (mids[i] != NULL) {
 				mids[i]->resp_buf_size = server->pdu_size;
-				if ((mids[i]->mid_flags & MID_WAIT_CANCELLED) &&
-				    mids[i]->mid_state == MID_RESPONSE_RECEIVED &&
-				    server->ops->handle_cancelled_mid)
-					server->ops->handle_cancelled_mid(
-							mids[i]->resp_buf,
-							server);
 
 				if (!mids[i]->multiRsp || mids[i]->multiEnd)
 					mids[i]->callback(mids[i]);
@@ -4700,6 +4709,17 @@ static int is_path_remote(struct cifs_sb
 }
 
 #ifdef CONFIG_CIFS_DFS_UPCALL
+static inline void set_root_tcon(struct cifs_sb_info *cifs_sb,
+				 struct cifs_tcon *tcon,
+				 struct cifs_tcon **root)
+{
+	spin_lock(&cifs_tcp_ses_lock);
+	tcon->tc_count++;
+	tcon->remap = cifs_remap(cifs_sb);
+	spin_unlock(&cifs_tcp_ses_lock);
+	*root = tcon;
+}
+
 int cifs_mount(struct cifs_sb_info *cifs_sb, struct smb_vol *vol)
 {
 	int rc = 0;
@@ -4801,18 +4821,10 @@ int cifs_mount(struct cifs_sb_info *cifs
 	/* Cache out resolved root server */
 	(void)dfs_cache_find(xid, ses, cifs_sb->local_nls, cifs_remap(cifs_sb),
 			     root_path + 1, NULL, NULL);
-	/*
-	 * Save root tcon for additional DFS requests to update or create a new
-	 * DFS cache entry, or even perform DFS failover.
-	 */
-	spin_lock(&cifs_tcp_ses_lock);
-	tcon->tc_count++;
-	tcon->dfs_path = root_path;
+	kfree(root_path);
 	root_path = NULL;
-	tcon->remap = cifs_remap(cifs_sb);
-	spin_unlock(&cifs_tcp_ses_lock);
 
-	root_tcon = tcon;
+	set_root_tcon(cifs_sb, tcon, &root_tcon);
 
 	for (count = 1; ;) {
 		if (!rc && tcon) {
@@ -4849,6 +4861,15 @@ int cifs_mount(struct cifs_sb_info *cifs
 			mount_put_conns(cifs_sb, xid, server, ses, tcon);
 			rc = mount_get_conns(vol, cifs_sb, &xid, &server, &ses,
 					     &tcon);
+			/*
+			 * Ensure that DFS referrals go through new root server.
+			 */
+			if (!rc && tcon &&
+			    (tcon->share_flags & (SHI1005_FLAGS_DFS |
+						  SHI1005_FLAGS_DFS_ROOT))) {
+				cifs_put_tcon(root_tcon);
+				set_root_tcon(cifs_sb, tcon, &root_tcon);
+			}
 		}
 		if (rc) {
 			if (rc == -EACCES || rc == -EOPNOTSUPP)
diff -druNp --no-dereference linux-libre-5.4.5-gnu/fs/cifs/file.c linux-libre-5.4.6-gnu/fs/cifs/file.c
--- linux-libre-5.4.5-gnu/fs/cifs/file.c	2019-12-18 10:09:17.000000000 -0500
+++ linux-libre-5.4.6-gnu/fs/cifs/file.c	2019-12-21 05:05:23.000000000 -0500
@@ -729,6 +729,13 @@ cifs_reopen_file(struct cifsFileInfo *cf
 	if (backup_cred(cifs_sb))
 		create_options |= CREATE_OPEN_BACKUP_INTENT;
 
+	/* O_SYNC also has bit for O_DSYNC so following check picks up either */
+	if (cfile->f_flags & O_SYNC)
+		create_options |= CREATE_WRITE_THROUGH;
+
+	if (cfile->f_flags & O_DIRECT)
+		create_options |= CREATE_NO_BUFFER;
+
 	if (server->ops->get_lease_key)
 		server->ops->get_lease_key(inode, &cfile->fid);
 
diff -druNp --no-dereference linux-libre-5.4.5-gnu/fs/cifs/smb2misc.c linux-libre-5.4.6-gnu/fs/cifs/smb2misc.c
--- linux-libre-5.4.5-gnu/fs/cifs/smb2misc.c	2019-12-18 10:09:17.000000000 -0500
+++ linux-libre-5.4.6-gnu/fs/cifs/smb2misc.c	2019-12-21 05:05:23.000000000 -0500
@@ -743,36 +743,67 @@ smb2_cancelled_close_fid(struct work_str
 	kfree(cancelled);
 }
 
+/* Caller should already has an extra reference to @tcon */
+static int
+__smb2_handle_cancelled_close(struct cifs_tcon *tcon, __u64 persistent_fid,
+			      __u64 volatile_fid)
+{
+	struct close_cancelled_open *cancelled;
+
+	cancelled = kzalloc(sizeof(*cancelled), GFP_KERNEL);
+	if (!cancelled)
+		return -ENOMEM;
+
+	cancelled->fid.persistent_fid = persistent_fid;
+	cancelled->fid.volatile_fid = volatile_fid;
+	cancelled->tcon = tcon;
+	INIT_WORK(&cancelled->work, smb2_cancelled_close_fid);
+	WARN_ON(queue_work(cifsiod_wq, &cancelled->work) == false);
+
+	return 0;
+}
+
+int
+smb2_handle_cancelled_close(struct cifs_tcon *tcon, __u64 persistent_fid,
+			    __u64 volatile_fid)
+{
+	int rc;
+
+	cifs_dbg(FYI, "%s: tc_count=%d\n", __func__, tcon->tc_count);
+	spin_lock(&cifs_tcp_ses_lock);
+	tcon->tc_count++;
+	spin_unlock(&cifs_tcp_ses_lock);
+
+	rc = __smb2_handle_cancelled_close(tcon, persistent_fid, volatile_fid);
+	if (rc)
+		cifs_put_tcon(tcon);
+
+	return rc;
+}
+
 int
 smb2_handle_cancelled_mid(char *buffer, struct TCP_Server_Info *server)
 {
 	struct smb2_sync_hdr *sync_hdr = (struct smb2_sync_hdr *)buffer;
 	struct smb2_create_rsp *rsp = (struct smb2_create_rsp *)buffer;
 	struct cifs_tcon *tcon;
-	struct close_cancelled_open *cancelled;
+	int rc;
 
 	if (sync_hdr->Command != SMB2_CREATE ||
 	    sync_hdr->Status != STATUS_SUCCESS)
 		return 0;
 
-	cancelled = kzalloc(sizeof(*cancelled), GFP_KERNEL);
-	if (!cancelled)
-		return -ENOMEM;
-
 	tcon = smb2_find_smb_tcon(server, sync_hdr->SessionId,
 				  sync_hdr->TreeId);
-	if (!tcon) {
-		kfree(cancelled);
+	if (!tcon)
 		return -ENOENT;
-	}
 
-	cancelled->fid.persistent_fid = rsp->PersistentFileId;
-	cancelled->fid.volatile_fid = rsp->VolatileFileId;
-	cancelled->tcon = tcon;
-	INIT_WORK(&cancelled->work, smb2_cancelled_close_fid);
-	queue_work(cifsiod_wq, &cancelled->work);
+	rc = __smb2_handle_cancelled_close(tcon, rsp->PersistentFileId,
+					   rsp->VolatileFileId);
+	if (rc)
+		cifs_put_tcon(tcon);
 
-	return 0;
+	return rc;
 }
 
 /**
diff -druNp --no-dereference linux-libre-5.4.5-gnu/fs/cifs/smb2ops.c linux-libre-5.4.6-gnu/fs/cifs/smb2ops.c
--- linux-libre-5.4.5-gnu/fs/cifs/smb2ops.c	2019-12-18 10:09:17.000000000 -0500
+++ linux-libre-5.4.6-gnu/fs/cifs/smb2ops.c	2019-12-21 05:05:23.000000000 -0500
@@ -151,13 +151,7 @@ smb2_get_credits_field(struct TCP_Server
 static unsigned int
 smb2_get_credits(struct mid_q_entry *mid)
 {
-	struct smb2_sync_hdr *shdr = (struct smb2_sync_hdr *)mid->resp_buf;
-
-	if (mid->mid_state == MID_RESPONSE_RECEIVED
-	    || mid->mid_state == MID_RESPONSE_MALFORMED)
-		return le16_to_cpu(shdr->CreditRequest);
-
-	return 0;
+	return mid->credits_received;
 }
 
 static int
diff -druNp --no-dereference linux-libre-5.4.5-gnu/fs/cifs/smb2pdu.c linux-libre-5.4.6-gnu/fs/cifs/smb2pdu.c
--- linux-libre-5.4.5-gnu/fs/cifs/smb2pdu.c	2019-12-18 10:09:17.000000000 -0500
+++ linux-libre-5.4.6-gnu/fs/cifs/smb2pdu.c	2019-12-21 05:05:23.000000000 -0500
@@ -2972,7 +2972,21 @@ int
 SMB2_close(const unsigned int xid, struct cifs_tcon *tcon,
 	   u64 persistent_fid, u64 volatile_fid)
 {
-	return SMB2_close_flags(xid, tcon, persistent_fid, volatile_fid, 0);
+	int rc;
+	int tmp_rc;
+
+	rc = SMB2_close_flags(xid, tcon, persistent_fid, volatile_fid, 0);
+
+	/* retry close in a worker thread if this one is interrupted */
+	if (rc == -EINTR) {
+		tmp_rc = smb2_handle_cancelled_close(tcon, persistent_fid,
+						     volatile_fid);
+		if (tmp_rc)
+			cifs_dbg(VFS, "handle cancelled close fid 0x%llx returned error %d\n",
+				 persistent_fid, tmp_rc);
+	}
+
+	return rc;
 }
 
 int
diff -druNp --no-dereference linux-libre-5.4.5-gnu/fs/cifs/smb2proto.h linux-libre-5.4.6-gnu/fs/cifs/smb2proto.h
--- linux-libre-5.4.5-gnu/fs/cifs/smb2proto.h	2019-12-18 10:09:17.000000000 -0500
+++ linux-libre-5.4.6-gnu/fs/cifs/smb2proto.h	2019-12-21 05:05:23.000000000 -0500
@@ -212,6 +212,9 @@ extern int SMB2_set_compression(const un
 extern int SMB2_oplock_break(const unsigned int xid, struct cifs_tcon *tcon,
 			     const u64 persistent_fid, const u64 volatile_fid,
 			     const __u8 oplock_level);
+extern int smb2_handle_cancelled_close(struct cifs_tcon *tcon,
+				       __u64 persistent_fid,
+				       __u64 volatile_fid);
 extern int smb2_handle_cancelled_mid(char *buffer,
 					struct TCP_Server_Info *server);
 void smb2_cancelled_close_fid(struct work_struct *work);
diff -druNp --no-dereference linux-libre-5.4.5-gnu/fs/cifs/smbdirect.c linux-libre-5.4.6-gnu/fs/cifs/smbdirect.c
--- linux-libre-5.4.5-gnu/fs/cifs/smbdirect.c	2019-12-18 10:09:17.000000000 -0500
+++ linux-libre-5.4.6-gnu/fs/cifs/smbdirect.c	2019-12-21 05:05:23.000000000 -0500
@@ -1069,7 +1069,7 @@ static int smbd_post_send_data(
 
 	if (n_vec > SMBDIRECT_MAX_SGE) {
 		cifs_dbg(VFS, "Can't fit data to SGL, n_vec=%d\n", n_vec);
-		return -ENOMEM;
+		return -EINVAL;
 	}
 
 	sg_init_table(sgl, n_vec);
@@ -1476,6 +1476,7 @@ void smbd_destroy(struct TCP_Server_Info
 	info->transport_status = SMBD_DESTROYED;
 
 	destroy_workqueue(info->workqueue);
+	log_rdma_event(INFO,  "rdma session destroyed\n");
 	kfree(info);
 }
 
@@ -1505,8 +1506,9 @@ create_conn:
 	log_rdma_event(INFO, "creating rdma session\n");
 	server->smbd_conn = smbd_get_connection(
 		server, (struct sockaddr *) &server->dstaddr);
-	log_rdma_event(INFO, "created rdma session info=%p\n",
-		server->smbd_conn);
+
+	if (server->smbd_conn)
+		cifs_dbg(VFS, "RDMA transport re-established\n");
 
 	return server->smbd_conn ? 0 : -ENOENT;
 }
@@ -1970,7 +1972,7 @@ read_rfc1002_done:
 
 	if (info->transport_status != SMBD_CONNECTED) {
 		log_read(ERR, "disconnected\n");
-		return 0;
+		return -ECONNABORTED;
 	}
 
 	goto again;
@@ -2269,12 +2271,7 @@ static void smbd_mr_recovery_work(struct
 	int rc;
 
 	list_for_each_entry(smbdirect_mr, &info->mr_list, list) {
-		if (smbdirect_mr->state == MR_INVALIDATED)
-			ib_dma_unmap_sg(
-				info->id->device, smbdirect_mr->sgl,
-				smbdirect_mr->sgl_count,
-				smbdirect_mr->dir);
-		else if (smbdirect_mr->state == MR_ERROR) {
+		if (smbdirect_mr->state == MR_ERROR) {
 
 			/* recover this MR entry */
 			rc = ib_dereg_mr(smbdirect_mr->mr);
@@ -2602,11 +2599,20 @@ int smbd_deregister_mr(struct smbd_mr *s
 		 */
 		smbdirect_mr->state = MR_INVALIDATED;
 
-	/*
-	 * Schedule the work to do MR recovery for future I/Os
-	 * MR recovery is slow and we don't want it to block the current I/O
-	 */
-	queue_work(info->workqueue, &info->mr_recovery_work);
+	if (smbdirect_mr->state == MR_INVALIDATED) {
+		ib_dma_unmap_sg(
+			info->id->device, smbdirect_mr->sgl,
+			smbdirect_mr->sgl_count,
+			smbdirect_mr->dir);
+		smbdirect_mr->state = MR_READY;
+		if (atomic_inc_return(&info->mr_ready_count) == 1)
+			wake_up_interruptible(&info->wait_mr);
+	} else
+		/*
+		 * Schedule the work to do MR recovery for future I/Os MR
+		 * recovery is slow and don't want it to block current I/O
+		 */
+		queue_work(info->workqueue, &info->mr_recovery_work);
 
 done:
 	if (atomic_dec_and_test(&info->mr_used_count))
diff -druNp --no-dereference linux-libre-5.4.5-gnu/fs/cifs/transport.c linux-libre-5.4.6-gnu/fs/cifs/transport.c
--- linux-libre-5.4.5-gnu/fs/cifs/transport.c	2019-12-18 10:09:17.000000000 -0500
+++ linux-libre-5.4.6-gnu/fs/cifs/transport.c	2019-12-21 05:05:23.000000000 -0500
@@ -93,8 +93,14 @@ static void _cifs_mid_q_entry_release(st
 	__u16 smb_cmd = le16_to_cpu(midEntry->command);
 	unsigned long now;
 	unsigned long roundtrip_time;
-	struct TCP_Server_Info *server = midEntry->server;
 #endif
+	struct TCP_Server_Info *server = midEntry->server;
+
+	if (midEntry->resp_buf && (midEntry->mid_flags & MID_WAIT_CANCELLED) &&
+	    midEntry->mid_state == MID_RESPONSE_RECEIVED &&
+	    server->ops->handle_cancelled_mid)
+		server->ops->handle_cancelled_mid(midEntry->resp_buf, server);
+
 	midEntry->mid_state = MID_FREE;
 	atomic_dec(&midCount);
 	if (midEntry->large_buf)
@@ -319,8 +325,11 @@ __smb_send_rqst(struct TCP_Server_Info *
 	int val = 1;
 	__be32 rfc1002_marker;
 
-	if (cifs_rdma_enabled(server) && server->smbd_conn) {
-		rc = smbd_send(server, num_rqst, rqst);
+	if (cifs_rdma_enabled(server)) {
+		/* return -EAGAIN when connecting or reconnecting */
+		rc = -EAGAIN;
+		if (server->smbd_conn)
+			rc = smbd_send(server, num_rqst, rqst);
 		goto smbd_done;
 	}
 
@@ -1119,8 +1128,8 @@ compound_send_recv(const unsigned int xi
 				 midQ[i]->mid, le16_to_cpu(midQ[i]->command));
 			send_cancel(server, &rqst[i], midQ[i]);
 			spin_lock(&GlobalMid_Lock);
+			midQ[i]->mid_flags |= MID_WAIT_CANCELLED;
 			if (midQ[i]->mid_state == MID_REQUEST_SUBMITTED) {
-				midQ[i]->mid_flags |= MID_WAIT_CANCELLED;
 				midQ[i]->callback = cifs_cancelled_callback;
 				cancelled_mid[i] = true;
 				credits[i].value = 0;
diff -druNp --no-dereference linux-libre-5.4.5-gnu/fs/gfs2/file.c linux-libre-5.4.6-gnu/fs/gfs2/file.c
--- linux-libre-5.4.5-gnu/fs/gfs2/file.c	2019-12-18 10:09:17.000000000 -0500
+++ linux-libre-5.4.6-gnu/fs/gfs2/file.c	2019-12-21 05:05:23.000000000 -0500
@@ -381,27 +381,28 @@ static void gfs2_size_hint(struct file *
 /**
  * gfs2_allocate_page_backing - Allocate blocks for a write fault
  * @page: The (locked) page to allocate backing for
+ * @length: Size of the allocation
  *
  * We try to allocate all the blocks required for the page in one go.  This
  * might fail for various reasons, so we keep trying until all the blocks to
  * back this page are allocated.  If some of the blocks are already allocated,
  * that is ok too.
  */
-static int gfs2_allocate_page_backing(struct page *page)
+static int gfs2_allocate_page_backing(struct page *page, unsigned int length)
 {
 	u64 pos = page_offset(page);
-	u64 size = PAGE_SIZE;
 
 	do {
 		struct iomap iomap = { };
 
-		if (gfs2_iomap_get_alloc(page->mapping->host, pos, 1, &iomap))
+		if (gfs2_iomap_get_alloc(page->mapping->host, pos, length, &iomap))
 			return -EIO;
 
-		iomap.length = min(iomap.length, size);
-		size -= iomap.length;
+		if (length < iomap.length)
+			iomap.length = length;
+		length -= iomap.length;
 		pos += iomap.length;
-	} while (size > 0);
+	} while (length > 0);
 
 	return 0;
 }
@@ -501,7 +502,7 @@ static vm_fault_t gfs2_page_mkwrite(stru
 	if (gfs2_is_stuffed(ip))
 		ret = gfs2_unstuff_dinode(ip, page);
 	if (ret == 0)
-		ret = gfs2_allocate_page_backing(page);
+		ret = gfs2_allocate_page_backing(page, PAGE_SIZE);
 
 out_trans_end:
 	if (ret)
diff -druNp --no-dereference linux-libre-5.4.5-gnu/fs/gfs2/log.c linux-libre-5.4.6-gnu/fs/gfs2/log.c
--- linux-libre-5.4.5-gnu/fs/gfs2/log.c	2019-12-18 10:09:17.000000000 -0500
+++ linux-libre-5.4.6-gnu/fs/gfs2/log.c	2019-12-21 05:05:23.000000000 -0500
@@ -609,6 +609,14 @@ void gfs2_add_revoke(struct gfs2_sbd *sd
 	list_add(&bd->bd_list, &sdp->sd_log_revokes);
 }
 
+void gfs2_glock_remove_revoke(struct gfs2_glock *gl)
+{
+	if (atomic_dec_return(&gl->gl_revokes) == 0) {
+		clear_bit(GLF_LFLUSH, &gl->gl_flags);
+		gfs2_glock_queue_put(gl);
+	}
+}
+
 void gfs2_write_revokes(struct gfs2_sbd *sdp)
 {
 	struct gfs2_trans *tr;
diff -druNp --no-dereference linux-libre-5.4.5-gnu/fs/gfs2/log.h linux-libre-5.4.6-gnu/fs/gfs2/log.h
--- linux-libre-5.4.5-gnu/fs/gfs2/log.h	2019-12-18 10:09:17.000000000 -0500
+++ linux-libre-5.4.6-gnu/fs/gfs2/log.h	2019-12-21 05:05:23.000000000 -0500
@@ -77,6 +77,7 @@ extern void gfs2_ail1_flush(struct gfs2_
 extern void gfs2_log_shutdown(struct gfs2_sbd *sdp);
 extern int gfs2_logd(void *data);
 extern void gfs2_add_revoke(struct gfs2_sbd *sdp, struct gfs2_bufdata *bd);
+extern void gfs2_glock_remove_revoke(struct gfs2_glock *gl);
 extern void gfs2_write_revokes(struct gfs2_sbd *sdp);
 
 #endif /* __LOG_DOT_H__ */
diff -druNp --no-dereference linux-libre-5.4.5-gnu/fs/gfs2/lops.c linux-libre-5.4.6-gnu/fs/gfs2/lops.c
--- linux-libre-5.4.5-gnu/fs/gfs2/lops.c	2019-12-18 10:09:17.000000000 -0500
+++ linux-libre-5.4.6-gnu/fs/gfs2/lops.c	2019-12-21 05:05:23.000000000 -0500
@@ -882,10 +882,7 @@ static void revoke_lo_after_commit(struc
 		bd = list_entry(head->next, struct gfs2_bufdata, bd_list);
 		list_del_init(&bd->bd_list);
 		gl = bd->bd_gl;
-		if (atomic_dec_return(&gl->gl_revokes) == 0) {
-			clear_bit(GLF_LFLUSH, &gl->gl_flags);
-			gfs2_glock_queue_put(gl);
-		}
+		gfs2_glock_remove_revoke(gl);
 		kmem_cache_free(gfs2_bufdata_cachep, bd);
 	}
 }
diff -druNp --no-dereference linux-libre-5.4.5-gnu/fs/gfs2/trans.c linux-libre-5.4.6-gnu/fs/gfs2/trans.c
--- linux-libre-5.4.5-gnu/fs/gfs2/trans.c	2019-12-18 10:09:17.000000000 -0500
+++ linux-libre-5.4.6-gnu/fs/gfs2/trans.c	2019-12-21 05:05:23.000000000 -0500
@@ -262,6 +262,8 @@ void gfs2_trans_remove_revoke(struct gfs
 			list_del_init(&bd->bd_list);
 			gfs2_assert_withdraw(sdp, sdp->sd_log_num_revoke);
 			sdp->sd_log_num_revoke--;
+			if (bd->bd_gl)
+				gfs2_glock_remove_revoke(bd->bd_gl);
 			kmem_cache_free(gfs2_bufdata_cachep, bd);
 			tr->tr_num_revoke--;
 			if (--n == 0)
diff -druNp --no-dereference linux-libre-5.4.5-gnu/include/linux/mmc/card.h linux-libre-5.4.6-gnu/include/linux/mmc/card.h
--- linux-libre-5.4.5-gnu/include/linux/mmc/card.h	2019-12-18 10:09:17.000000000 -0500
+++ linux-libre-5.4.6-gnu/include/linux/mmc/card.h	2019-12-21 05:05:23.000000000 -0500
@@ -291,6 +291,7 @@ struct mmc_card {
 	struct sd_switch_caps	sw_caps;	/* switch (CMD6) caps */
 
 	unsigned int		sdio_funcs;	/* number of SDIO functions */
+	atomic_t		sdio_funcs_probed; /* number of probed SDIO funcs */
 	struct sdio_cccr	cccr;		/* common card info */
 	struct sdio_cis		cis;		/* common tuple info */
 	struct sdio_func	*sdio_func[SDIO_MAX_FUNCS]; /* SDIO functions (devices) */
diff -druNp --no-dereference linux-libre-5.4.5-gnu/include/linux/pm_qos.h linux-libre-5.4.6-gnu/include/linux/pm_qos.h
--- linux-libre-5.4.5-gnu/include/linux/pm_qos.h	2019-12-18 10:09:17.000000000 -0500
+++ linux-libre-5.4.6-gnu/include/linux/pm_qos.h	2019-12-21 05:05:23.000000000 -0500
@@ -256,7 +256,7 @@ static inline s32 dev_pm_qos_raw_resume_
 #endif
 
 #define FREQ_QOS_MIN_DEFAULT_VALUE	0
-#define FREQ_QOS_MAX_DEFAULT_VALUE	(-1)
+#define FREQ_QOS_MAX_DEFAULT_VALUE	S32_MAX
 
 enum freq_qos_req_type {
 	FREQ_QOS_MIN = 1,
diff -druNp --no-dereference linux-libre-5.4.5-gnu/Makefile linux-libre-5.4.6-gnu/Makefile
--- linux-libre-5.4.5-gnu/Makefile	2019-12-18 13:16:02.000000000 -0500
+++ linux-libre-5.4.6-gnu/Makefile	2019-12-21 21:50:28.000000000 -0500
@@ -1,7 +1,7 @@
 # SPDX-License-Identifier: GPL-2.0
 VERSION = 5
 PATCHLEVEL = 4
-SUBLEVEL = 5
+SUBLEVEL = 6
 EXTRAVERSION = -gnu
 NAME = Kleptomaniac Octopus
 
diff -druNp --no-dereference linux-libre-5.4.5-gnu/sound/hda/hdac_stream.c linux-libre-5.4.6-gnu/sound/hda/hdac_stream.c
--- linux-libre-5.4.5-gnu/sound/hda/hdac_stream.c	2019-12-18 10:09:17.000000000 -0500
+++ linux-libre-5.4.6-gnu/sound/hda/hdac_stream.c	2019-12-21 05:05:23.000000000 -0500
@@ -120,10 +120,8 @@ void snd_hdac_stream_clear(struct hdac_s
 	snd_hdac_stream_updateb(azx_dev, SD_CTL,
 				SD_CTL_DMA_START | SD_INT_MASK, 0);
 	snd_hdac_stream_writeb(azx_dev, SD_STS, SD_INT_MASK); /* to be sure */
-	if (azx_dev->stripe) {
+	if (azx_dev->stripe)
 		snd_hdac_stream_updateb(azx_dev, SD_CTL_3B, SD_CTL_STRIPE_MASK, 0);
-		azx_dev->stripe = 0;
-	}
 	azx_dev->running = false;
 }
 EXPORT_SYMBOL_GPL(snd_hdac_stream_clear);
diff -druNp --no-dereference linux-libre-5.4.5-gnu/sound/pci/hda/patch_hdmi.c linux-libre-5.4.6-gnu/sound/pci/hda/patch_hdmi.c
--- linux-libre-5.4.5-gnu/sound/pci/hda/patch_hdmi.c	2019-12-18 10:09:17.000000000 -0500
+++ linux-libre-5.4.6-gnu/sound/pci/hda/patch_hdmi.c	2019-12-21 05:05:23.000000000 -0500
@@ -1983,6 +1983,8 @@ static int hdmi_pcm_close(struct hda_pcm
 		per_cvt->assigned = 0;
 		hinfo->nid = 0;
 
+		azx_stream(get_azx_dev(substream))->stripe = 0;
+
 		mutex_lock(&spec->pcm_lock);
 		snd_hda_spdif_ctls_unassign(codec, pcm_idx);
 		clear_bit(pcm_idx, &spec->pcm_in_use);
