diff --git linux-libre-7.1.5-gnu/Documentation/admin-guide/cgroup-v2.rst linux-libre-7.1.6-gnu/Documentation/admin-guide/cgroup-v2.rst
index 6efd0095ed995..5cc33d87c3dff 100644
--- linux-libre-7.1.5-gnu/Documentation/admin-guide/cgroup-v2.rst
+++ linux-libre-7.1.6-gnu/Documentation/admin-guide/cgroup-v2.rst
@@ -1570,7 +1570,7 @@ The following nested keys are defined.
 	  sock (npn)
 		Amount of memory used in network transmission buffers
 
-	  vmalloc (npn)
+	  vmalloc
 		Amount of memory used for vmap backed memory.
 
 	  shmem
@@ -1735,7 +1735,7 @@ The following nested keys are defined.
 		Number of pages written from zswap to swap.
 
 	  zswap_incomp
-		Number of incompressible pages currently stored in zswap
+		Amount of memory used by incompressible pages currently stored in zswap
 		without compression. These pages could not be compressed to
 		a size smaller than PAGE_SIZE, so they are stored as-is.
 
diff --git linux-libre-7.1.5-gnu/Documentation/hwmon/max34440.rst linux-libre-7.1.6-gnu/Documentation/hwmon/max34440.rst
index d6d4fbc863d96..e7421f4dbf38f 100644
--- linux-libre-7.1.5-gnu/Documentation/hwmon/max34440.rst
+++ linux-libre-7.1.6-gnu/Documentation/hwmon/max34440.rst
@@ -19,6 +19,14 @@ Supported chips:
 
     Datasheet: -
 
+  * ADI ADPM12250
+
+    Prefixes: 'adpm12250'
+
+    Addresses scanned: -
+
+    Datasheet: -
+
   * Maxim MAX34440
 
     Prefixes: 'max34440'
@@ -87,11 +95,11 @@ This driver supports multiple devices: hardware monitoring for Maxim MAX34440
 PMBus 6-Channel Power-Supply Manager, MAX34441 PMBus 5-Channel Power-Supply
 Manager and Intelligent Fan Controller, and MAX34446 PMBus Power-Supply Data
 Logger; PMBus Voltage Monitor and Sequencers for MAX34451, MAX34460, and
-MAX34461; PMBus DC/DC Power Module ADPM12160, and ADPM12200. The MAX34451
-supports monitoring voltage or current of 12 channels based on GIN pins. The
-MAX34460 supports 12 voltage channels, and the MAX34461 supports 16 voltage
-channels. The ADPM12160, and ADPM12200 also monitors both input and output
-of voltage and current.
+MAX34461; PMBus DC/DC Power Module ADPM12160, ADPM12200, and ADPM12250. The
+MAX34451 supports monitoring voltage or current of 12 channels based on GIN
+pins. The MAX34460 supports 12 voltage channels, and the MAX34461 supports 16
+voltage channels. The ADPM12160, ADPM12200, and ADPM12250 also monitors both
+input and output of voltage and current.
 
 The driver is a client driver to the core PMBus driver. Please see
 Documentation/hwmon/pmbus.rst for details on PMBus client drivers.
@@ -149,7 +157,7 @@ in[1-6]_reset_history	Write any value to reset history.
 .. note::
 
     - MAX34446 only supports in[1-4].
-    - ADPM12160, and ADPM12200 only supports in[1-2]. Label is "vin1"
+    - ADPM12160, ADPM12200, and ADPM12250 only supports in[1-2]. Label is "vin1"
       and "vout1" respectively.
 
 Curr
@@ -172,8 +180,9 @@ curr[1-6]_reset_history	Write any value to reset history.
 
     - in6 and curr6 attributes only exist for MAX34440.
     - MAX34446 only supports curr[1-4].
-    - For ADPM12160, and ADPM12200, curr[1] is "iin1" and curr[2-6]
-      are "iout[1-5]".
+    - For ADPM12160, ADPM12200, and ADPM12250, curr[1] is "iin1"
+    - For ADPM12160, and ADPM12200 curr[2-6] are "iout[1-5]".
+    - For ADPM12250, curr[2-4] are "iout[1-3]".
 
 Power
 ~~~~~
@@ -209,7 +218,7 @@ temp[1-8]_reset_history	Write any value to reset history.
 .. note::
    - temp7 and temp8 attributes only exist for MAX34440.
    - MAX34446 only supports temp[1-3].
-   - ADPM12160, and ADPM12200 only supports temp[1].
+   - ADPM12160, ADPM12200, and ADPM12250 only supports temp[1].
 
 
 .. note::
diff --git linux-libre-7.1.5-gnu/Documentation/netlink/specs/rt-link.yaml linux-libre-7.1.6-gnu/Documentation/netlink/specs/rt-link.yaml
index 644a8bd7b93c3..e656f05268ed2 100644
--- linux-libre-7.1.5-gnu/Documentation/netlink/specs/rt-link.yaml
+++ linux-libre-7.1.6-gnu/Documentation/netlink/specs/rt-link.yaml
@@ -1583,31 +1583,31 @@ attribute-sets:
         type: u32
       -
         name: mode
-        type: flag
+        type: u8
       -
         name: guard
-        type: flag
+        type: u8
       -
         name: protect
-        type: flag
+        type: u8
       -
         name: fast-leave
-        type: flag
+        type: u8
       -
         name: learning
-        type: flag
+        type: u8
       -
         name: unicast-flood
-        type: flag
+        type: u8
       -
         name: proxyarp
-        type: flag
+        type: u8
       -
         name: learning-sync
-        type: flag
+        type: u8
       -
         name: proxyarp-wifi
-        type: flag
+        type: u8
       -
         name: root-id
         type: binary
@@ -1654,34 +1654,34 @@ attribute-sets:
         type: pad
       -
         name: mcast-flood
-        type: flag
+        type: u8
       -
         name: mcast-to-ucast
-        type: flag
+        type: u8
       -
         name: vlan-tunnel
-        type: flag
+        type: u8
       -
         name: bcast-flood
-        type: flag
+        type: u8
       -
         name: group-fwd-mask
         type: u16
       -
         name: neigh-suppress
-        type: flag
+        type: u8
       -
         name: isolated
-        type: flag
+        type: u8
       -
         name: backup-port
         type: u32
       -
         name: mrp-ring-open
-        type: flag
+        type: u8
       -
         name: mrp-in-open
-        type: flag
+        type: u8
       -
         name: mcast-eht-hosts-limit
         type: u32
@@ -1690,10 +1690,10 @@ attribute-sets:
         type: u32
       -
         name: locked
-        type: flag
+        type: u8
       -
         name: mab
-        type: flag
+        type: u8
       -
         name: mcast-n-groups
         type: u32
@@ -1702,7 +1702,7 @@ attribute-sets:
         type: u32
       -
         name: neigh-vlan-suppress
-        type: flag
+        type: u8
       -
         name: backup-nhid
         type: u32
diff --git linux-libre-7.1.5-gnu/Makefile linux-libre-7.1.6-gnu/Makefile
index 8a363dea8d1a5..b935e053d45f9 100644
--- linux-libre-7.1.5-gnu/Makefile
+++ linux-libre-7.1.6-gnu/Makefile
@@ -1,7 +1,7 @@
 # SPDX-License-Identifier: GPL-2.0
 VERSION = 7
 PATCHLEVEL = 1
-SUBLEVEL = 5
+SUBLEVEL = 6
 EXTRAVERSION = -gnu
 NAME = Baby Opossum Posse
 
@@ -473,6 +473,10 @@ KBUILD_USERLDFLAGS := $(USERLDFLAGS)
 
 # These flags apply to all Rust code in the tree, including the kernel and
 # host programs.
+#
+# `-Aclippy::unwrap_or_default`: the lint is buggy [1] and ignores our
+# MSRV. It can trigger depending on the optimization level.
+# [1] https://github.com/rust-lang/rust-clippy/issues/17379
 export rust_common_flags := --edition=2021 \
 			    -Zbinary_dep_depinfo=y \
 			    -Astable_features \
@@ -501,6 +505,7 @@ export rust_common_flags := --edition=2021 \
 			    -Aclippy::uninlined_format_args \
 			    -Wclippy::unnecessary_safety_comment \
 			    -Wclippy::unnecessary_safety_doc \
+			    -Aclippy::unwrap_or_default \
 			    -Wrustdoc::missing_crate_level_docs \
 			    -Wrustdoc::unescaped_backticks
 
diff --git linux-libre-7.1.5-gnu/arch/arm64/boot/dts/nvidia/tegra234.dtsi linux-libre-7.1.6-gnu/arch/arm64/boot/dts/nvidia/tegra234.dtsi
index 18220cdac9f9b..eda23431ed05e 100644
--- linux-libre-7.1.5-gnu/arch/arm64/boot/dts/nvidia/tegra234.dtsi
+++ linux-libre-7.1.6-gnu/arch/arm64/boot/dts/nvidia/tegra234.dtsi
@@ -5339,7 +5339,7 @@
 		#size-cells = <0>;
 
 		cpu0_0: cpu@0 {
-			compatible = "arm,cortex-a78";
+			compatible = "arm,cortex-a78ae";
 			device_type = "cpu";
 			reg = <0x00000>;
 
@@ -5358,7 +5358,7 @@
 		};
 
 		cpu0_1: cpu@100 {
-			compatible = "arm,cortex-a78";
+			compatible = "arm,cortex-a78ae";
 			device_type = "cpu";
 			reg = <0x00100>;
 
@@ -5377,7 +5377,7 @@
 		};
 
 		cpu0_2: cpu@200 {
-			compatible = "arm,cortex-a78";
+			compatible = "arm,cortex-a78ae";
 			device_type = "cpu";
 			reg = <0x00200>;
 
@@ -5396,7 +5396,7 @@
 		};
 
 		cpu0_3: cpu@300 {
-			compatible = "arm,cortex-a78";
+			compatible = "arm,cortex-a78ae";
 			device_type = "cpu";
 			reg = <0x00300>;
 
@@ -5415,7 +5415,7 @@
 		};
 
 		cpu1_0: cpu@10000 {
-			compatible = "arm,cortex-a78";
+			compatible = "arm,cortex-a78ae";
 			device_type = "cpu";
 			reg = <0x10000>;
 
@@ -5434,7 +5434,7 @@
 		};
 
 		cpu1_1: cpu@10100 {
-			compatible = "arm,cortex-a78";
+			compatible = "arm,cortex-a78ae";
 			device_type = "cpu";
 			reg = <0x10100>;
 
@@ -5453,7 +5453,7 @@
 		};
 
 		cpu1_2: cpu@10200 {
-			compatible = "arm,cortex-a78";
+			compatible = "arm,cortex-a78ae";
 			device_type = "cpu";
 			reg = <0x10200>;
 
@@ -5472,7 +5472,7 @@
 		};
 
 		cpu1_3: cpu@10300 {
-			compatible = "arm,cortex-a78";
+			compatible = "arm,cortex-a78ae";
 			device_type = "cpu";
 			reg = <0x10300>;
 
@@ -5491,7 +5491,7 @@
 		};
 
 		cpu2_0: cpu@20000 {
-			compatible = "arm,cortex-a78";
+			compatible = "arm,cortex-a78ae";
 			device_type = "cpu";
 			reg = <0x20000>;
 
@@ -5510,7 +5510,7 @@
 		};
 
 		cpu2_1: cpu@20100 {
-			compatible = "arm,cortex-a78";
+			compatible = "arm,cortex-a78ae";
 			device_type = "cpu";
 			reg = <0x20100>;
 
@@ -5529,7 +5529,7 @@
 		};
 
 		cpu2_2: cpu@20200 {
-			compatible = "arm,cortex-a78";
+			compatible = "arm,cortex-a78ae";
 			device_type = "cpu";
 			reg = <0x20200>;
 
@@ -5548,7 +5548,7 @@
 		};
 
 		cpu2_3: cpu@20300 {
-			compatible = "arm,cortex-a78";
+			compatible = "arm,cortex-a78ae";
 			device_type = "cpu";
 			reg = <0x20300>;
 
diff --git linux-libre-7.1.5-gnu/arch/arm64/boot/dts/nvidia/tegra264.dtsi linux-libre-7.1.6-gnu/arch/arm64/boot/dts/nvidia/tegra264.dtsi
index 2d8e7e37830ff..3dfdd7bb28a91 100644
--- linux-libre-7.1.5-gnu/arch/arm64/boot/dts/nvidia/tegra264.dtsi
+++ linux-libre-7.1.6-gnu/arch/arm64/boot/dts/nvidia/tegra264.dtsi
@@ -3208,7 +3208,7 @@
 		};
 
 		gpcdma: dma-controller@8400000 {
-			compatible = "nvidia,tegra264-gpcdma", "nvidia,tegra186-gpcdma";
+			compatible = "nvidia,tegra264-gpcdma";
 			reg = <0x0 0x08400000 0x0 0x210000>;
 			interrupts = <GIC_SPI 584 IRQ_TYPE_LEVEL_HIGH>,
 				     <GIC_SPI 585 IRQ_TYPE_LEVEL_HIGH>,
diff --git linux-libre-7.1.5-gnu/arch/arm64/include/asm/esr.h linux-libre-7.1.6-gnu/arch/arm64/include/asm/esr.h
index 7e86d400864e0..64e9bd137b603 100644
--- linux-libre-7.1.5-gnu/arch/arm64/include/asm/esr.h
+++ linux-libre-7.1.6-gnu/arch/arm64/include/asm/esr.h
@@ -131,7 +131,7 @@
  * Annoyingly, the negative levels for Address size faults aren't laid out
  * contiguously (or in the desired order)
  */
-#define ESR_ELx_FSC_ADDRSZ_nL(n)	((n) == -1 ? 0x25 : 0x2C)
+#define ESR_ELx_FSC_ADDRSZ_nL(n)	((n) == -1 ? 0x29 : 0x2C)
 #define ESR_ELx_FSC_ADDRSZ_L(n)		((n) < 0 ? ESR_ELx_FSC_ADDRSZ_nL(n) : \
 						   (ESR_ELx_FSC_ADDRSZ + (n)))
 
diff --git linux-libre-7.1.5-gnu/arch/arm64/mm/hugetlbpage.c linux-libre-7.1.6-gnu/arch/arm64/mm/hugetlbpage.c
index 30772a909aea3..8e799c1fe0aa6 100644
--- linux-libre-7.1.5-gnu/arch/arm64/mm/hugetlbpage.c
+++ linux-libre-7.1.6-gnu/arch/arm64/mm/hugetlbpage.c
@@ -87,7 +87,7 @@ static int find_num_contig(struct mm_struct *mm, unsigned long addr,
 	p4dp = p4d_offset(pgdp, addr);
 	pudp = pud_offset(p4dp, addr);
 	pmdp = pmd_offset(pudp, addr);
-	if ((pte_t *)pmdp == ptep) {
+	if ((pte_t *)PTR_ALIGN_DOWN(pmdp, sizeof(*pmdp) * CONT_PMDS) == ptep) {
 		*pgsize = PMD_SIZE;
 		return CONT_PMDS;
 	}
diff --git linux-libre-7.1.5-gnu/arch/arm64/mm/mmu.c linux-libre-7.1.6-gnu/arch/arm64/mm/mmu.c
index fd756390fe925..92fedf4db9278 100644
--- linux-libre-7.1.5-gnu/arch/arm64/mm/mmu.c
+++ linux-libre-7.1.6-gnu/arch/arm64/mm/mmu.c
@@ -2032,12 +2032,13 @@ err:
 	return ret;
 }
 
-void arch_remove_memory(u64 start, u64 size, struct vmem_altmap *altmap)
+void arch_remove_memory(u64 start, u64 size, struct vmem_altmap *altmap,
+			struct dev_pagemap *pgmap)
 {
 	unsigned long start_pfn = start >> PAGE_SHIFT;
 	unsigned long nr_pages = size >> PAGE_SHIFT;
 
-	__remove_pages(start_pfn, nr_pages, altmap);
+	__remove_pages(start_pfn, nr_pages, altmap, pgmap);
 	__remove_pgd_mapping(swapper_pg_dir, __phys_to_virt(start), size);
 }
 
@@ -2201,7 +2202,7 @@ static int prevent_memory_remove_notifier(struct notifier_block *nb,
 		}
 	}
 
-	if (!can_unmap_without_split(pfn, arg->nr_pages))
+	if (!can_unmap_without_split(arg->start_pfn, arg->nr_pages))
 		return NOTIFY_BAD;
 
 	return NOTIFY_OK;
diff --git linux-libre-7.1.5-gnu/arch/loongarch/include/asm/asmmacro.h linux-libre-7.1.6-gnu/arch/loongarch/include/asm/asmmacro.h
index a648be5f723fc..b7423d1ac5684 100644
--- linux-libre-7.1.5-gnu/arch/loongarch/include/asm/asmmacro.h
+++ linux-libre-7.1.6-gnu/arch/loongarch/include/asm/asmmacro.h
@@ -14,7 +14,7 @@
 #ifdef CONFIG_64BIT
 #define TASK_STRUCT_OFFSET 0
 #else
-#define TASK_STRUCT_OFFSET 2000
+#define TASK_STRUCT_OFFSET 2040
 #endif
 
 	.macro	cpu_save_nonscratch thread
diff --git linux-libre-7.1.5-gnu/arch/loongarch/kernel/acpi.c linux-libre-7.1.6-gnu/arch/loongarch/kernel/acpi.c
index 8f650c9ffecde..873e90990771b 100644
--- linux-libre-7.1.5-gnu/arch/loongarch/kernel/acpi.c
+++ linux-libre-7.1.6-gnu/arch/loongarch/kernel/acpi.c
@@ -201,10 +201,12 @@ static void __init acpi_process_madt(void)
 }
 
 int pptt_enabled;
+static int acpi_nr_packages;
+static int acpi_package_ids[MAX_PACKAGES];
 
 int __init parse_acpi_topology(void)
 {
-	int cpu, topology_id;
+	int i, cpu, topology_id;
 
 	for_each_possible_cpu(cpu) {
 		topology_id = find_acpi_cpu_topology(cpu, 0);
@@ -222,6 +224,29 @@ int __init parse_acpi_topology(void)
 
 			cpu_data[cpu].core = topology_id;
 		}
+
+		topology_id = find_acpi_cpu_topology_package(cpu);
+		if (topology_id < 0) {
+			pr_warn("Invalid BIOS PPTT\n");
+			return -ENOENT;
+		}
+
+		for (i = 0; i < acpi_nr_packages; i++)
+			if (acpi_package_ids[i] == topology_id)
+				break;
+
+		if (i == acpi_nr_packages)
+			acpi_package_ids[acpi_nr_packages++] = topology_id;
+
+		cpu_data[cpu].package = topology_id;
+	}
+
+	for_each_possible_cpu(cpu) {
+		for (i = 0; i < acpi_nr_packages; i++)
+			if (cpu_data[cpu].package == acpi_package_ids[i]) {
+				cpu_data[cpu].package = i; /* Canonicalize */
+				break;
+			}
 	}
 
 	pptt_enabled = 1;
diff --git linux-libre-7.1.5-gnu/arch/loongarch/kernel/kgdb.c linux-libre-7.1.6-gnu/arch/loongarch/kernel/kgdb.c
index 17664a6043b1e..e7b59f8a4b05b 100644
--- linux-libre-7.1.5-gnu/arch/loongarch/kernel/kgdb.c
+++ linux-libre-7.1.6-gnu/arch/loongarch/kernel/kgdb.c
@@ -252,7 +252,8 @@ static int kgdb_loongarch_notify(struct notifier_block *self, unsigned long cmd,
 	if (atomic_read(&kgdb_active) != -1)
 		kgdb_nmicallback(smp_processor_id(), regs);
 
-	if (kgdb_handle_exception(args->trapnr, args->signr, cmd, regs))
+	if (kgdb_handle_exception(regs->csr_era == stepped_address ? 0 : args->trapnr,
+				  args->signr, cmd, regs))
 		return NOTIFY_DONE;
 
 	if (atomic_read(&kgdb_setting_breakpoint))
diff --git linux-libre-7.1.5-gnu/arch/loongarch/kernel/machine_kexec.c linux-libre-7.1.6-gnu/arch/loongarch/kernel/machine_kexec.c
index d7fafda1d5417..1883cae93bc31 100644
--- linux-libre-7.1.5-gnu/arch/loongarch/kernel/machine_kexec.c
+++ linux-libre-7.1.6-gnu/arch/loongarch/kernel/machine_kexec.c
@@ -42,6 +42,7 @@ static unsigned long first_ind_entry;
 int machine_kexec_prepare(struct kimage *kimage)
 {
 	int i;
+	char head[8];
 	char *bootloader = "kexec";
 	void *cmdline_ptr = (void *)KEXEC_CMDLINE_ADDR;
 
@@ -59,7 +60,9 @@ int machine_kexec_prepare(struct kimage *kimage)
 	} else {
 		/* Find the command line */
 		for (i = 0; i < kimage->nr_segments; i++) {
-			if (!strncmp(bootloader, (char __user *)kimage->segment[i].buf, strlen(bootloader))) {
+			if (copy_from_user(head, kimage->segment[i].buf, strlen(bootloader)))
+				continue;
+			if (!strncmp(bootloader, head, strlen(bootloader))) {
 				if (!copy_from_user(cmdline_ptr, kimage->segment[i].buf, COMMAND_LINE_SIZE))
 					kimage->arch.cmdline_ptr = (unsigned long)cmdline_ptr;
 				break;
diff --git linux-libre-7.1.5-gnu/arch/loongarch/kernel/rethook_trampoline.S linux-libre-7.1.6-gnu/arch/loongarch/kernel/rethook_trampoline.S
index d4ceb2fa2a5ce..2e009fbea53f2 100644
--- linux-libre-7.1.5-gnu/arch/loongarch/kernel/rethook_trampoline.S
+++ linux-libre-7.1.6-gnu/arch/loongarch/kernel/rethook_trampoline.S
@@ -71,27 +71,27 @@
 	cfi_ld	s7, PT_R30
 	cfi_ld	s8, PT_R31
 	LONG_L  t0, sp, PT_CRMD
-	li.d	t1, 0x7 /* mask bit[1:0] PLV, bit[2] IE */
+	LONG_LI	t1, 0x7 /* mask bit[1:0] PLV, bit[2] IE */
 	csrxchg t0, t1, LOONGARCH_CSR_CRMD
 	.endm
 
 SYM_CODE_START(arch_rethook_trampoline)
 	UNWIND_HINT_UNDEFINED
-	addi.d	sp, sp, -PT_SIZE
+	PTR_ADDI sp, sp, -PT_SIZE
 	save_all_base_regs
 
-	addi.d	t0, sp, PT_SIZE
-	LONG_S	t0, sp, PT_R3
+	PTR_ADDI t0, sp, PT_SIZE
+	LONG_S	 t0, sp, PT_R3
 
-	move a0, sp /* pt_regs */
+	move	 a0, sp /* pt_regs */
 
-	bl arch_rethook_trampoline_callback
+	bl	 arch_rethook_trampoline_callback
 
 	/* use the result as the return-address */
-	move ra, a0
+	move	 ra, a0
 
 	restore_all_base_regs
-	addi.d	sp, sp, PT_SIZE
+	PTR_ADDI sp, sp, PT_SIZE
 
-	jr ra
+	jr	 ra
 SYM_CODE_END(arch_rethook_trampoline)
diff --git linux-libre-7.1.5-gnu/arch/loongarch/kernel/setup.c linux-libre-7.1.6-gnu/arch/loongarch/kernel/setup.c
index bfc6f274e6e28..d37e2439f4f24 100644
--- linux-libre-7.1.5-gnu/arch/loongarch/kernel/setup.c
+++ linux-libre-7.1.6-gnu/arch/loongarch/kernel/setup.c
@@ -602,6 +602,7 @@ void __init setup_arch(char **cmdline_p)
 	memblock_init();
 	pagetable_init();
 	bootcmdline_init(cmdline_p);
+	jump_label_init(); /* Initialise the static keys for early params */
 	parse_early_param();
 	reserve_initrd_mem();
 
@@ -609,8 +610,6 @@ void __init setup_arch(char **cmdline_p)
 	arch_mem_init(cmdline_p);
 
 	resource_init();
-	jump_label_init(); /* Initialise the static keys for paravirtualization */
-
 #ifdef CONFIG_SMP
 	plat_smp_setup();
 	prefill_possible_map();
diff --git linux-libre-7.1.5-gnu/arch/loongarch/kernel/smp.c linux-libre-7.1.6-gnu/arch/loongarch/kernel/smp.c
index b077b2aa1ab37..3d16f8311dce8 100644
--- linux-libre-7.1.5-gnu/arch/loongarch/kernel/smp.c
+++ linux-libre-7.1.6-gnu/arch/loongarch/kernel/smp.c
@@ -425,10 +425,10 @@ void loongson_init_secondary(void)
 	numa_add_cpu(cpu);
 #endif
 	per_cpu(cpu_state, cpu) = CPU_ONLINE;
-	cpu_data[cpu].package =
-		     cpu_logical_map(cpu) / loongson_sysconf.cores_per_package;
 	cpu_data[cpu].core = pptt_enabled ? cpu_data[cpu].core :
 		     cpu_logical_map(cpu) % loongson_sysconf.cores_per_package;
+	cpu_data[cpu].package = pptt_enabled ? cpu_data[cpu].package :
+		     cpu_logical_map(cpu) / loongson_sysconf.cores_per_package;
 	cpu_data[cpu].global_id = cpu_logical_map(cpu);
 }
 
diff --git linux-libre-7.1.5-gnu/arch/loongarch/mm/init.c linux-libre-7.1.6-gnu/arch/loongarch/mm/init.c
index 031b39eb081c5..687980b6e91f0 100644
--- linux-libre-7.1.5-gnu/arch/loongarch/mm/init.c
+++ linux-libre-7.1.6-gnu/arch/loongarch/mm/init.c
@@ -119,12 +119,13 @@ int arch_add_memory(int nid, u64 start, u64 size, struct mhp_params *params)
 	return ret;
 }
 
-void arch_remove_memory(u64 start, u64 size, struct vmem_altmap *altmap)
+void arch_remove_memory(u64 start, u64 size, struct vmem_altmap *altmap,
+			struct dev_pagemap *pgmap)
 {
 	unsigned long start_pfn = start >> PAGE_SHIFT;
 	unsigned long nr_pages = size >> PAGE_SHIFT;
 
-	__remove_pages(start_pfn, nr_pages, altmap);
+	__remove_pages(start_pfn, nr_pages, altmap, pgmap);
 }
 #endif
 
diff --git linux-libre-7.1.5-gnu/arch/loongarch/net/bpf_jit.c linux-libre-7.1.6-gnu/arch/loongarch/net/bpf_jit.c
index e4966c178abc5..4933869b2c11f 100644
--- linux-libre-7.1.5-gnu/arch/loongarch/net/bpf_jit.c
+++ linux-libre-7.1.6-gnu/arch/loongarch/net/bpf_jit.c
@@ -834,7 +834,7 @@ static int build_insn(const struct bpf_insn *insn, struct jit_ctx *ctx, bool ext
 			move_reg(ctx, t1, src);
 			emit_sext_32(ctx, t1, is32);
 			emit_insn(ctx, divd, dst, dst, t1);
-			emit_sext_32(ctx, dst, is32);
+			emit_zext_32(ctx, dst, is32);
 		}
 		break;
 
@@ -851,7 +851,7 @@ static int build_insn(const struct bpf_insn *insn, struct jit_ctx *ctx, bool ext
 			emit_sext_32(ctx, t1, is32);
 			emit_sext_32(ctx, dst, is32);
 			emit_insn(ctx, divd, dst, dst, t1);
-			emit_sext_32(ctx, dst, is32);
+			emit_zext_32(ctx, dst, is32);
 		}
 		break;
 
@@ -869,7 +869,7 @@ static int build_insn(const struct bpf_insn *insn, struct jit_ctx *ctx, bool ext
 			move_reg(ctx, t1, src);
 			emit_sext_32(ctx, t1, is32);
 			emit_insn(ctx, modd, dst, dst, t1);
-			emit_sext_32(ctx, dst, is32);
+			emit_zext_32(ctx, dst, is32);
 		}
 		break;
 
@@ -886,7 +886,7 @@ static int build_insn(const struct bpf_insn *insn, struct jit_ctx *ctx, bool ext
 			emit_sext_32(ctx, t1, is32);
 			emit_sext_32(ctx, dst, is32);
 			emit_insn(ctx, modd, dst, dst, t1);
-			emit_sext_32(ctx, dst, is32);
+			emit_zext_32(ctx, dst, is32);
 		}
 		break;
 
@@ -2347,6 +2347,7 @@ void bpf_jit_free(struct bpf_prog *prog)
 		 */
 		if (jit_data) {
 			bpf_jit_binary_pack_finalize(jit_data->ro_header, jit_data->header);
+			kvfree(jit_data->ctx.offset);
 			kfree(jit_data);
 		}
 		hdr = bpf_jit_binary_pack_hdr(prog);
diff --git linux-libre-7.1.5-gnu/arch/m68k/include/asm/page_mm.h linux-libre-7.1.6-gnu/arch/m68k/include/asm/page_mm.h
index ed782609ca413..0971a0651d490 100644
--- linux-libre-7.1.5-gnu/arch/m68k/include/asm/page_mm.h
+++ linux-libre-7.1.6-gnu/arch/m68k/include/asm/page_mm.h
@@ -55,10 +55,12 @@ static inline void clear_page(void *page)
 #define clear_user_page(addr, vaddr, page)	\
 	do {	clear_page(addr);		\
 		flush_dcache_page(page);	\
+		(void)(vaddr);			\
 	} while (0)
 #define copy_user_page(to, from, vaddr, page)	\
 	do {	copy_page(to, from);		\
 		flush_dcache_page(page);	\
+		(void)(vaddr);			\
 	} while (0)
 
 extern unsigned long m68k_memoffset;
diff --git linux-libre-7.1.5-gnu/arch/powerpc/kernel/time.c linux-libre-7.1.6-gnu/arch/powerpc/kernel/time.c
index b4472288e0d43..11145c40183dd 100644
--- linux-libre-7.1.5-gnu/arch/powerpc/kernel/time.c
+++ linux-libre-7.1.6-gnu/arch/powerpc/kernel/time.c
@@ -376,6 +376,47 @@ void vtime_task_switch(struct task_struct *prev)
 		acct->starttime = acct0->starttime;
 	}
 }
+
+/**
+ * vtime_reset - Fast forward vtime entry clocks
+ *
+ * Called from dynticks idle IRQ entry to fast-forward the clocks to current time
+ * so that the IRQ time is still accounted by vtime while nohz cputime is paused.
+ */
+void vtime_reset(void)
+{
+	struct cpu_accounting_data *acct = get_accounting(current);
+
+	acct->starttime = mftb();
+#ifdef CONFIG_ARCH_HAS_SCALED_CPUTIME
+	acct->startspurr = read_spurr(acct->starttime);
+#endif
+}
+
+#ifdef CONFIG_NO_HZ_COMMON
+/**
+ * vtime_dyntick_start - Inform vtime about entry to idle-dynticks
+ *
+ * Called when idle enters in dyntick mode. The idle cputime that elapsed so far
+ * is accumulated and the tick subsystem takes over the idle cputime accounting.
+ */
+void vtime_dyntick_start(void)
+{
+	vtime_account_idle(current);
+}
+
+/**
+ * vtime_dyntick_stop - Inform vtime about exit from idle-dynticks
+ *
+ * Called when idle exits from dyntick mode. The vtime entry clocks are
+ * fast-forward to current time so that idle accounting restarts elapsing from
+ * now.
+ */
+void vtime_dyntick_stop(void)
+{
+	vtime_reset();
+}
+#endif /* CONFIG_NO_HZ_COMMON */
 #endif /* CONFIG_VIRT_CPU_ACCOUNTING_NATIVE */
 
 void __no_kcsan __delay(unsigned long loops)
@@ -892,6 +933,7 @@ static void __init set_decrementer_max(void)
 static void __init init_decrementer_clockevent(void)
 {
 	register_decrementer_clockevent(smp_processor_id());
+	vtime_reset();
 }
 
 void secondary_cpu_time_init(void)
@@ -907,6 +949,7 @@ void secondary_cpu_time_init(void)
 	/* FIME: Should make unrelated change to move snapshot_timebase
 	 * call here ! */
 	register_decrementer_clockevent(smp_processor_id());
+	vtime_reset();
 }
 
 /*
diff --git linux-libre-7.1.5-gnu/arch/powerpc/mm/mem.c linux-libre-7.1.6-gnu/arch/powerpc/mm/mem.c
index 648d0c5602ec8..4c1afab919963 100644
--- linux-libre-7.1.5-gnu/arch/powerpc/mm/mem.c
+++ linux-libre-7.1.6-gnu/arch/powerpc/mm/mem.c
@@ -158,12 +158,13 @@ int __ref arch_add_memory(int nid, u64 start, u64 size,
 	return rc;
 }
 
-void __ref arch_remove_memory(u64 start, u64 size, struct vmem_altmap *altmap)
+void __ref arch_remove_memory(u64 start, u64 size, struct vmem_altmap *altmap,
+			      struct dev_pagemap *pgmap)
 {
 	unsigned long start_pfn = start >> PAGE_SHIFT;
 	unsigned long nr_pages = size >> PAGE_SHIFT;
 
-	__remove_pages(start_pfn, nr_pages, altmap);
+	__remove_pages(start_pfn, nr_pages, altmap, pgmap);
 	arch_remove_linear_mapping(start, size);
 }
 #endif
diff --git linux-libre-7.1.5-gnu/arch/powerpc/platforms/85xx/common.c linux-libre-7.1.6-gnu/arch/powerpc/platforms/85xx/common.c
index 757811155587d..c11deb2f50ed4 100644
--- linux-libre-7.1.5-gnu/arch/powerpc/platforms/85xx/common.c
+++ linux-libre-7.1.6-gnu/arch/powerpc/platforms/85xx/common.c
@@ -42,6 +42,8 @@ static const struct of_device_id mpc85xx_common_ids[] __initconst = {
 	{ .compatible = "fsl,qoriq-pcie-v2.3", },
 	{ .compatible = "fsl,qoriq-pcie-v2.2", },
 	{ .compatible = "fsl,fman", },
+	/* IFC NAND and NOR controllers */
+	{ .compatible = "fsl,ifc", },
 	{},
 };
 
diff --git linux-libre-7.1.5-gnu/arch/riscv/Kconfig linux-libre-7.1.6-gnu/arch/riscv/Kconfig
index c5754942cf85a..e73f556720c1c 100644
--- linux-libre-7.1.5-gnu/arch/riscv/Kconfig
+++ linux-libre-7.1.6-gnu/arch/riscv/Kconfig
@@ -155,7 +155,7 @@ config RISCV
 	select HAVE_DEBUG_KMEMLEAK
 	select HAVE_DMA_CONTIGUOUS if MMU
 	select HAVE_DYNAMIC_FTRACE if MMU && (CLANG_SUPPORTS_DYNAMIC_FTRACE || GCC_SUPPORTS_DYNAMIC_FTRACE)
-	select FUNCTION_ALIGNMENT_4B if HAVE_DYNAMIC_FTRACE && RISCV_ISA_C
+	select FUNCTION_ALIGNMENT_4B if DYNAMIC_FTRACE && RISCV_ISA_C
 	select HAVE_DYNAMIC_FTRACE_WITH_DIRECT_CALLS if HAVE_DYNAMIC_FTRACE_WITH_CALL_OPS
 	select HAVE_DYNAMIC_FTRACE_WITH_CALL_OPS if (DYNAMIC_FTRACE_WITH_ARGS && !CFI)
 	select HAVE_DYNAMIC_FTRACE_WITH_ARGS if HAVE_DYNAMIC_FTRACE
diff --git linux-libre-7.1.5-gnu/arch/riscv/include/asm/kvm_host.h linux-libre-7.1.6-gnu/arch/riscv/include/asm/kvm_host.h
index 75b0a951c1bc6..97e42645cbabe 100644
--- linux-libre-7.1.5-gnu/arch/riscv/include/asm/kvm_host.h
+++ linux-libre-7.1.6-gnu/arch/riscv/include/asm/kvm_host.h
@@ -207,13 +207,13 @@ struct kvm_vcpu_arch {
 	/*
 	 * VCPU interrupts
 	 *
-	 * We have a lockless approach for tracking pending VCPU interrupts
-	 * implemented using atomic bitops. The irqs_pending bitmap represent
-	 * pending interrupts whereas irqs_pending_mask represent bits changed
-	 * in irqs_pending. Our approach is modeled around multiple producer
-	 * and single consumer problem where the consumer is the VCPU itself.
+	 * The irqs_pending bitmap represents pending interrupts whereas
+	 * irqs_pending_mask represents bits changed in irqs_pending. Updates
+	 * to these bitmaps are serialized so vcpu interrupt sync/flush cannot
+	 * drop a newly injected interrupt while syncing guest-visible HVIP.
 	 */
 #define KVM_RISCV_VCPU_NR_IRQS	64
+	raw_spinlock_t irqs_pending_lock;
 	DECLARE_BITMAP(irqs_pending, KVM_RISCV_VCPU_NR_IRQS);
 	DECLARE_BITMAP(irqs_pending_mask, KVM_RISCV_VCPU_NR_IRQS);
 
diff --git linux-libre-7.1.5-gnu/arch/riscv/kernel/sys_hwprobe.c linux-libre-7.1.6-gnu/arch/riscv/kernel/sys_hwprobe.c
index 1659d31fd288f..caf6762427c87 100644
--- linux-libre-7.1.5-gnu/arch/riscv/kernel/sys_hwprobe.c
+++ linux-libre-7.1.6-gnu/arch/riscv/kernel/sys_hwprobe.c
@@ -450,6 +450,7 @@ static int hwprobe_get_cpus(struct riscv_hwprobe __user *pairs,
 	if (cpusetsize > cpumask_size())
 		cpusetsize = cpumask_size();
 
+	cpumask_clear(&cpus);
 	ret = copy_from_user(&cpus, cpus_user, cpusetsize);
 	if (ret)
 		return -EFAULT;
diff --git linux-libre-7.1.5-gnu/arch/riscv/kvm/aia.c linux-libre-7.1.6-gnu/arch/riscv/kvm/aia.c
index 5ec503288555d..5e92fe14f79ae 100644
--- linux-libre-7.1.5-gnu/arch/riscv/kvm/aia.c
+++ linux-libre-7.1.6-gnu/arch/riscv/kvm/aia.c
@@ -51,12 +51,15 @@ void kvm_riscv_vcpu_aia_flush_interrupts(struct kvm_vcpu *vcpu)
 	struct kvm_vcpu_aia_csr *csr = &vcpu->arch.aia_context.guest_csr;
 	unsigned long mask, val;
 
+	lockdep_assert_held(&vcpu->arch.irqs_pending_lock);
+
 	if (!kvm_riscv_aia_available())
 		return;
 
-	if (READ_ONCE(vcpu->arch.irqs_pending_mask[1])) {
-		mask = xchg_acquire(&vcpu->arch.irqs_pending_mask[1], 0);
-		val = READ_ONCE(vcpu->arch.irqs_pending[1]) & mask;
+	mask = vcpu->arch.irqs_pending_mask[1];
+	if (mask) {
+		vcpu->arch.irqs_pending_mask[1] = 0;
+		val = vcpu->arch.irqs_pending[1] & mask;
 
 		csr->hviph &= ~mask;
 		csr->hviph |= val;
@@ -67,6 +70,8 @@ void kvm_riscv_vcpu_aia_sync_interrupts(struct kvm_vcpu *vcpu)
 {
 	struct kvm_vcpu_aia_csr *csr = &vcpu->arch.aia_context.guest_csr;
 
+	lockdep_assert_held(&vcpu->arch.irqs_pending_lock);
+
 	if (kvm_riscv_aia_available())
 		csr->vsieh = ncsr_read(CSR_VSIEH);
 }
@@ -75,13 +80,22 @@ void kvm_riscv_vcpu_aia_sync_interrupts(struct kvm_vcpu *vcpu)
 bool kvm_riscv_vcpu_aia_has_interrupts(struct kvm_vcpu *vcpu, u64 mask)
 {
 	unsigned long seip;
+#ifdef CONFIG_32BIT
+	unsigned long flags;
+	bool pending;
+#endif
 
 	if (!kvm_riscv_aia_available())
 		return false;
 
 #ifdef CONFIG_32BIT
-	if (READ_ONCE(vcpu->arch.irqs_pending[1]) &
-	    (vcpu->arch.aia_context.guest_csr.vsieh & upper_32_bits(mask)))
+	raw_spin_lock_irqsave(&vcpu->arch.irqs_pending_lock, flags);
+	pending = vcpu->arch.irqs_pending[1] &
+		  (vcpu->arch.aia_context.guest_csr.vsieh &
+		   upper_32_bits(mask));
+	raw_spin_unlock_irqrestore(&vcpu->arch.irqs_pending_lock, flags);
+
+	if (pending)
 		return true;
 #endif
 
@@ -205,6 +219,9 @@ int kvm_riscv_vcpu_aia_set_csr(struct kvm_vcpu *vcpu,
 {
 	struct kvm_vcpu_aia_csr *csr = &vcpu->arch.aia_context.guest_csr;
 	unsigned long regs_max = sizeof(struct kvm_riscv_aia_csr) / sizeof(unsigned long);
+#ifdef CONFIG_32BIT
+	unsigned long flags;
+#endif
 
 	if (!riscv_isa_extension_available(vcpu->arch.isa, SSAIA))
 		return -ENOENT;
@@ -217,8 +234,12 @@ int kvm_riscv_vcpu_aia_set_csr(struct kvm_vcpu *vcpu,
 		((unsigned long *)csr)[reg_num] = val;
 
 #ifdef CONFIG_32BIT
-		if (reg_num == KVM_REG_RISCV_CSR_AIA_REG(siph))
-			WRITE_ONCE(vcpu->arch.irqs_pending_mask[1], 0);
+		if (reg_num == KVM_REG_RISCV_CSR_AIA_REG(siph)) {
+			raw_spin_lock_irqsave(&vcpu->arch.irqs_pending_lock, flags);
+			vcpu->arch.irqs_pending_mask[1] = 0;
+			raw_spin_unlock_irqrestore(&vcpu->arch.irqs_pending_lock,
+						   flags);
+		}
 #endif
 	}
 
diff --git linux-libre-7.1.5-gnu/arch/riscv/kvm/vcpu.c linux-libre-7.1.6-gnu/arch/riscv/kvm/vcpu.c
index a73690eda84b5..61b3029080b1f 100644
--- linux-libre-7.1.5-gnu/arch/riscv/kvm/vcpu.c
+++ linux-libre-7.1.6-gnu/arch/riscv/kvm/vcpu.c
@@ -80,6 +80,7 @@ static void kvm_riscv_vcpu_context_reset(struct kvm_vcpu *vcpu,
 
 static void kvm_riscv_reset_vcpu(struct kvm_vcpu *vcpu, bool kvm_sbi_reset)
 {
+	unsigned long flags;
 	bool loaded;
 
 	/**
@@ -104,8 +105,10 @@ static void kvm_riscv_reset_vcpu(struct kvm_vcpu *vcpu, bool kvm_sbi_reset)
 
 	kvm_riscv_vcpu_aia_reset(vcpu);
 
+	raw_spin_lock_irqsave(&vcpu->arch.irqs_pending_lock, flags);
 	bitmap_zero(vcpu->arch.irqs_pending, KVM_RISCV_VCPU_NR_IRQS);
 	bitmap_zero(vcpu->arch.irqs_pending_mask, KVM_RISCV_VCPU_NR_IRQS);
+	raw_spin_unlock_irqrestore(&vcpu->arch.irqs_pending_lock, flags);
 
 	kvm_riscv_vcpu_pmu_reset(vcpu);
 
@@ -151,6 +154,7 @@ int kvm_arch_vcpu_create(struct kvm_vcpu *vcpu)
 
 	/* Setup VCPU hfence queue */
 	spin_lock_init(&vcpu->arch.hfence_lock);
+	raw_spin_lock_init(&vcpu->arch.irqs_pending_lock);
 
 	spin_lock_init(&vcpu->arch.reset_state.lock);
 
@@ -352,10 +356,14 @@ void kvm_riscv_vcpu_flush_interrupts(struct kvm_vcpu *vcpu)
 {
 	struct kvm_vcpu_csr *csr = &vcpu->arch.guest_csr;
 	unsigned long mask, val;
+	unsigned long flags;
 
-	if (READ_ONCE(vcpu->arch.irqs_pending_mask[0])) {
-		mask = xchg_acquire(&vcpu->arch.irqs_pending_mask[0], 0);
-		val = READ_ONCE(vcpu->arch.irqs_pending[0]) & mask;
+	raw_spin_lock_irqsave(&vcpu->arch.irqs_pending_lock, flags);
+
+	mask = vcpu->arch.irqs_pending_mask[0];
+	if (mask) {
+		vcpu->arch.irqs_pending_mask[0] = 0;
+		val = vcpu->arch.irqs_pending[0] & mask;
 
 		csr->hvip &= ~mask;
 		csr->hvip |= val;
@@ -363,11 +371,14 @@ void kvm_riscv_vcpu_flush_interrupts(struct kvm_vcpu *vcpu)
 
 	/* Flush AIA high interrupts */
 	kvm_riscv_vcpu_aia_flush_interrupts(vcpu);
+
+	raw_spin_unlock_irqrestore(&vcpu->arch.irqs_pending_lock, flags);
 }
 
 void kvm_riscv_vcpu_sync_interrupts(struct kvm_vcpu *vcpu)
 {
 	unsigned long hvip;
+	unsigned long flags;
 	struct kvm_vcpu_arch *v = &vcpu->arch;
 	struct kvm_vcpu_csr *csr = &vcpu->arch.guest_csr;
 
@@ -376,34 +387,41 @@ void kvm_riscv_vcpu_sync_interrupts(struct kvm_vcpu *vcpu)
 
 	/* Sync-up HVIP.VSSIP bit changes does by Guest */
 	hvip = ncsr_read(CSR_HVIP);
+
+	raw_spin_lock_irqsave(&v->irqs_pending_lock, flags);
+
 	if ((csr->hvip ^ hvip) & (1UL << IRQ_VS_SOFT)) {
 		if (hvip & (1UL << IRQ_VS_SOFT)) {
-			if (!test_and_set_bit(IRQ_VS_SOFT,
-					      v->irqs_pending_mask))
-				set_bit(IRQ_VS_SOFT, v->irqs_pending);
+			if (!__test_and_set_bit(IRQ_VS_SOFT,
+						v->irqs_pending_mask))
+				__set_bit(IRQ_VS_SOFT, v->irqs_pending);
 		} else {
-			if (!test_and_set_bit(IRQ_VS_SOFT,
-					      v->irqs_pending_mask))
-				clear_bit(IRQ_VS_SOFT, v->irqs_pending);
+			if (!__test_and_set_bit(IRQ_VS_SOFT,
+						v->irqs_pending_mask))
+				__clear_bit(IRQ_VS_SOFT, v->irqs_pending);
 		}
 	}
 
 	/* Sync up the HVIP.LCOFIP bit changes (only clear) by the guest */
 	if ((csr->hvip ^ hvip) & (1UL << IRQ_PMU_OVF)) {
 		if (!(hvip & (1UL << IRQ_PMU_OVF)) &&
-		    !test_and_set_bit(IRQ_PMU_OVF, v->irqs_pending_mask))
-			clear_bit(IRQ_PMU_OVF, v->irqs_pending);
+		    !__test_and_set_bit(IRQ_PMU_OVF, v->irqs_pending_mask))
+			__clear_bit(IRQ_PMU_OVF, v->irqs_pending);
 	}
 
 	/* Sync-up AIA high interrupts */
 	kvm_riscv_vcpu_aia_sync_interrupts(vcpu);
 
+	raw_spin_unlock_irqrestore(&v->irqs_pending_lock, flags);
+
 	/* Sync-up timer CSRs */
 	kvm_riscv_vcpu_timer_sync(vcpu);
 }
 
 int kvm_riscv_vcpu_set_interrupt(struct kvm_vcpu *vcpu, unsigned int irq)
 {
+	unsigned long flags;
+
 	/*
 	 * We only allow VS-mode software, timer, and external
 	 * interrupts when irq is one of the local interrupts
@@ -416,9 +434,10 @@ int kvm_riscv_vcpu_set_interrupt(struct kvm_vcpu *vcpu, unsigned int irq)
 	    irq != IRQ_PMU_OVF)
 		return -EINVAL;
 
-	set_bit(irq, vcpu->arch.irqs_pending);
-	smp_mb__before_atomic();
-	set_bit(irq, vcpu->arch.irqs_pending_mask);
+	raw_spin_lock_irqsave(&vcpu->arch.irqs_pending_lock, flags);
+	__set_bit(irq, vcpu->arch.irqs_pending);
+	__set_bit(irq, vcpu->arch.irqs_pending_mask);
+	raw_spin_unlock_irqrestore(&vcpu->arch.irqs_pending_lock, flags);
 
 	kvm_vcpu_kick(vcpu);
 
@@ -427,6 +446,8 @@ int kvm_riscv_vcpu_set_interrupt(struct kvm_vcpu *vcpu, unsigned int irq)
 
 int kvm_riscv_vcpu_unset_interrupt(struct kvm_vcpu *vcpu, unsigned int irq)
 {
+	unsigned long flags;
+
 	/*
 	 * We only allow VS-mode software, timer, counter overflow and external
 	 * interrupts when irq is one of the local interrupts
@@ -439,26 +460,33 @@ int kvm_riscv_vcpu_unset_interrupt(struct kvm_vcpu *vcpu, unsigned int irq)
 	    irq != IRQ_PMU_OVF)
 		return -EINVAL;
 
-	clear_bit(irq, vcpu->arch.irqs_pending);
-	smp_mb__before_atomic();
-	set_bit(irq, vcpu->arch.irqs_pending_mask);
+	raw_spin_lock_irqsave(&vcpu->arch.irqs_pending_lock, flags);
+	__clear_bit(irq, vcpu->arch.irqs_pending);
+	__set_bit(irq, vcpu->arch.irqs_pending_mask);
+	raw_spin_unlock_irqrestore(&vcpu->arch.irqs_pending_lock, flags);
 
 	return 0;
 }
 
 bool kvm_riscv_vcpu_has_interrupts(struct kvm_vcpu *vcpu, u64 mask)
 {
+	unsigned long flags;
 	unsigned long ie;
+	bool ret;
 
+	raw_spin_lock_irqsave(&vcpu->arch.irqs_pending_lock, flags);
 	ie = ((vcpu->arch.guest_csr.vsie & VSIP_VALID_MASK)
 		<< VSIP_TO_HVIP_SHIFT) & (unsigned long)mask;
 	ie |= vcpu->arch.guest_csr.vsie & ~IRQ_LOCAL_MASK &
 		(unsigned long)mask;
-	if (READ_ONCE(vcpu->arch.irqs_pending[0]) & ie)
-		return true;
+	ret = vcpu->arch.irqs_pending[0] & ie;
+	raw_spin_unlock_irqrestore(&vcpu->arch.irqs_pending_lock, flags);
 
 	/* Check AIA high interrupts */
-	return kvm_riscv_vcpu_aia_has_interrupts(vcpu, mask);
+	if (!ret)
+		ret = kvm_riscv_vcpu_aia_has_interrupts(vcpu, mask);
+
+	return ret;
 }
 
 void __kvm_riscv_vcpu_power_off(struct kvm_vcpu *vcpu)
diff --git linux-libre-7.1.5-gnu/arch/riscv/kvm/vcpu_onereg.c linux-libre-7.1.6-gnu/arch/riscv/kvm/vcpu_onereg.c
index bb920e8923c93..2031beb9bba6e 100644
--- linux-libre-7.1.5-gnu/arch/riscv/kvm/vcpu_onereg.c
+++ linux-libre-7.1.6-gnu/arch/riscv/kvm/vcpu_onereg.c
@@ -298,6 +298,7 @@ static int kvm_riscv_vcpu_general_set_csr(struct kvm_vcpu *vcpu,
 {
 	struct kvm_vcpu_csr *csr = &vcpu->arch.guest_csr;
 	unsigned long regs_max = sizeof(struct kvm_riscv_csr) / sizeof(unsigned long);
+	unsigned long flags;
 
 	if (reg_num >= regs_max)
 		return -ENOENT;
@@ -311,8 +312,11 @@ static int kvm_riscv_vcpu_general_set_csr(struct kvm_vcpu *vcpu,
 
 	((unsigned long *)csr)[reg_num] = reg_val;
 
-	if (reg_num == KVM_REG_RISCV_CSR_REG(sip))
-		WRITE_ONCE(vcpu->arch.irqs_pending_mask[0], 0);
+	if (reg_num == KVM_REG_RISCV_CSR_REG(sip)) {
+		raw_spin_lock_irqsave(&vcpu->arch.irqs_pending_lock, flags);
+		vcpu->arch.irqs_pending_mask[0] = 0;
+		raw_spin_unlock_irqrestore(&vcpu->arch.irqs_pending_lock, flags);
+	}
 
 	return 0;
 }
diff --git linux-libre-7.1.5-gnu/arch/riscv/mm/init.c linux-libre-7.1.6-gnu/arch/riscv/mm/init.c
index fa8d2f6f554b5..885f1db4e9bfd 100644
--- linux-libre-7.1.5-gnu/arch/riscv/mm/init.c
+++ linux-libre-7.1.6-gnu/arch/riscv/mm/init.c
@@ -1742,9 +1742,10 @@ int __ref arch_add_memory(int nid, u64 start, u64 size, struct mhp_params *param
 	return ret;
 }
 
-void __ref arch_remove_memory(u64 start, u64 size, struct vmem_altmap *altmap)
+void __ref arch_remove_memory(u64 start, u64 size, struct vmem_altmap *altmap,
+			      struct dev_pagemap *pgmap)
 {
-	__remove_pages(start >> PAGE_SHIFT, size >> PAGE_SHIFT, altmap);
+	__remove_pages(start >> PAGE_SHIFT, size >> PAGE_SHIFT, altmap, pgmap);
 	remove_linear_mapping(start, size);
 	flush_tlb_all();
 }
diff --git linux-libre-7.1.5-gnu/arch/s390/kernel/time.c linux-libre-7.1.6-gnu/arch/s390/kernel/time.c
index bd0df61d19077..2b989bebd220a 100644
--- linux-libre-7.1.5-gnu/arch/s390/kernel/time.c
+++ linux-libre-7.1.6-gnu/arch/s390/kernel/time.c
@@ -65,6 +65,7 @@ ATOMIC_NOTIFIER_HEAD(s390_epoch_delta_notifier);
 EXPORT_SYMBOL(s390_epoch_delta_notifier);
 
 unsigned char ptff_function_mask[16];
+EXPORT_SYMBOL(ptff_function_mask);
 
 static unsigned long lpar_offset;
 static unsigned long initial_leap_seconds;
diff --git linux-libre-7.1.5-gnu/arch/s390/lib/csum-partial.c linux-libre-7.1.6-gnu/arch/s390/lib/csum-partial.c
index 458abd9bac702..9d74ceff136c5 100644
--- linux-libre-7.1.5-gnu/arch/s390/lib/csum-partial.c
+++ linux-libre-7.1.6-gnu/arch/s390/lib/csum-partial.c
@@ -23,7 +23,7 @@ static __always_inline __wsum csum_copy(void *dst, const void *src, int len, __w
 	if (!cpu_has_vx()) {
 		if (copy)
 			memcpy(dst, src, len);
-		return cksm(dst, len, sum);
+		return cksm(src, len, sum);
 	}
 	kernel_fpu_begin(&vxstate, KERNEL_VXR_V16V23);
 	fpu_vlvgf(16, (__force u32)sum, 1);
diff --git linux-libre-7.1.5-gnu/arch/s390/mm/init.c linux-libre-7.1.6-gnu/arch/s390/mm/init.c
index 1f72efc2a579f..11a689423440f 100644
--- linux-libre-7.1.5-gnu/arch/s390/mm/init.c
+++ linux-libre-7.1.6-gnu/arch/s390/mm/init.c
@@ -276,12 +276,13 @@ int arch_add_memory(int nid, u64 start, u64 size,
 	return rc;
 }
 
-void arch_remove_memory(u64 start, u64 size, struct vmem_altmap *altmap)
+void arch_remove_memory(u64 start, u64 size, struct vmem_altmap *altmap,
+			struct dev_pagemap *pgmap)
 {
 	unsigned long start_pfn = start >> PAGE_SHIFT;
 	unsigned long nr_pages = size >> PAGE_SHIFT;
 
-	__remove_pages(start_pfn, nr_pages, altmap);
+	__remove_pages(start_pfn, nr_pages, altmap, pgmap);
 	vmem_remove_mapping(start, size);
 }
 #endif /* CONFIG_MEMORY_HOTPLUG */
diff --git linux-libre-7.1.5-gnu/arch/x86/boot/compressed/Makefile linux-libre-7.1.6-gnu/arch/x86/boot/compressed/Makefile
index 07e0e64b9a986..06934f9691d6a 100644
--- linux-libre-7.1.5-gnu/arch/x86/boot/compressed/Makefile
+++ linux-libre-7.1.6-gnu/arch/x86/boot/compressed/Makefile
@@ -27,6 +27,7 @@ targets := vmlinux vmlinux.bin vmlinux.bin.gz vmlinux.bin.bz2 vmlinux.bin.lzma \
 KBUILD_CFLAGS := -m$(BITS) -O2 $(CLANG_FLAGS)
 KBUILD_CFLAGS += $(CC_FLAGS_DIALECT)
 KBUILD_CFLAGS += -fno-strict-aliasing -fPIE
+KBUILD_CFLAGS += -fno-jump-tables
 KBUILD_CFLAGS += -Wundef
 KBUILD_CFLAGS += -DDISABLE_BRANCH_PROFILING
 cflags-$(CONFIG_X86_32) := -march=i386
diff --git linux-libre-7.1.5-gnu/arch/x86/kvm/lapic.c linux-libre-7.1.6-gnu/arch/x86/kvm/lapic.c
index d806abaeda3de..3a0eef95e9058 100644
--- linux-libre-7.1.5-gnu/arch/x86/kvm/lapic.c
+++ linux-libre-7.1.6-gnu/arch/x86/kvm/lapic.c
@@ -2052,7 +2052,7 @@ static void apic_timer_expired(struct kvm_lapic *apic, bool from_timer_fn)
 	if (apic_lvtt_tscdeadline(apic) || ktimer->hv_timer_in_use)
 		ktimer->expired_tscdeadline = ktimer->tscdeadline;
 
-	if (!from_timer_fn && apic->apicv_active) {
+	if (!from_timer_fn && apic->apicv_active && vcpu->wants_to_run) {
 		WARN_ON(kvm_get_running_vcpu() != vcpu);
 		kvm_apic_inject_pending_timer_irqs(apic);
 		return;
diff --git linux-libre-7.1.5-gnu/arch/x86/kvm/mmu/mmu.c linux-libre-7.1.6-gnu/arch/x86/kvm/mmu/mmu.c
index 0c2e35e3ffbdb..34a3127052539 100644
--- linux-libre-7.1.5-gnu/arch/x86/kvm/mmu/mmu.c
+++ linux-libre-7.1.6-gnu/arch/x86/kvm/mmu/mmu.c
@@ -4837,16 +4837,17 @@ static int direct_page_fault(struct kvm_vcpu *vcpu, struct kvm_page_fault *fault
 	if (r != RET_PF_CONTINUE)
 		return r;
 
-	r = RET_PF_RETRY;
 	write_lock(&vcpu->kvm->mmu_lock);
 
-	if (is_page_fault_stale(vcpu, fault))
-		goto out_unlock;
-
 	r = make_mmu_pages_available(vcpu);
 	if (r)
 		goto out_unlock;
 
+	if (is_page_fault_stale(vcpu, fault)) {
+		r = RET_PF_RETRY;
+		goto out_unlock;
+	}
+
 	r = direct_map(vcpu, fault);
 
 out_unlock:
@@ -7501,7 +7502,9 @@ void kvm_mmu_invalidate_mmio_sptes(struct kvm *kvm, u64 gen)
 static void mmu_destroy_caches(void)
 {
 	kmem_cache_destroy(pte_list_desc_cache);
+	pte_list_desc_cache = NULL;
 	kmem_cache_destroy(mmu_page_header_cache);
+	mmu_page_header_cache = NULL;
 }
 
 static void kvm_wake_nx_recovery_thread(struct kvm *kvm)
diff --git linux-libre-7.1.5-gnu/arch/x86/kvm/mmu/paging_tmpl.h linux-libre-7.1.6-gnu/arch/x86/kvm/mmu/paging_tmpl.h
index 901cd2bd40b84..6465de820e70a 100644
--- linux-libre-7.1.5-gnu/arch/x86/kvm/mmu/paging_tmpl.h
+++ linux-libre-7.1.6-gnu/arch/x86/kvm/mmu/paging_tmpl.h
@@ -827,15 +827,17 @@ static int FNAME(page_fault)(struct kvm_vcpu *vcpu, struct kvm_page_fault *fault
 	}
 #endif
 
-	r = RET_PF_RETRY;
 	write_lock(&vcpu->kvm->mmu_lock);
 
-	if (is_page_fault_stale(vcpu, fault))
-		goto out_unlock;
-
 	r = make_mmu_pages_available(vcpu);
 	if (r)
 		goto out_unlock;
+
+	if (is_page_fault_stale(vcpu, fault)) {
+		r = RET_PF_RETRY;
+		goto out_unlock;
+	}
+
 	r = FNAME(fetch)(vcpu, fault, &walker);
 
 out_unlock:
diff --git linux-libre-7.1.5-gnu/arch/x86/kvm/svm/svm.c linux-libre-7.1.6-gnu/arch/x86/kvm/svm/svm.c
index 2544c551e702f..d8eff8f11c5f0 100644
--- linux-libre-7.1.5-gnu/arch/x86/kvm/svm/svm.c
+++ linux-libre-7.1.6-gnu/arch/x86/kvm/svm/svm.c
@@ -566,7 +566,12 @@ static int svm_enable_virtualization_cpu(void)
 		return r;
 
 	sd = per_cpu_ptr(&svm_data, me);
-	sd->asid_generation = 1;
+	/*
+	 * Bump the current asid_generation value to ensure any vCPU that
+	 * previously ran on this CPU sees a stale generation and is forced
+	 * to acquire a new ASID, preventing a latent ASID collision.
+	 */
+	sd->asid_generation++;
 	sd->max_asid = cpuid_ebx(SVM_CPUID_FUNC) - 1;
 	sd->next_asid = sd->max_asid + 1;
 	sd->min_asid = max_sev_asid + 1;
diff --git linux-libre-7.1.5-gnu/arch/x86/kvm/vmx/nested.c linux-libre-7.1.6-gnu/arch/x86/kvm/vmx/nested.c
index 52ab52b0e1ccf..170b0c4d865f1 100644
--- linux-libre-7.1.5-gnu/arch/x86/kvm/vmx/nested.c
+++ linux-libre-7.1.6-gnu/arch/x86/kvm/vmx/nested.c
@@ -336,6 +336,7 @@ static void nested_put_vmcs12_pages(struct kvm_vcpu *vcpu)
 static void free_nested(struct kvm_vcpu *vcpu)
 {
 	struct vcpu_vmx *vmx = to_vmx(vcpu);
+	struct vmcs *shadow_vmcs;
 
 	if (WARN_ON_ONCE(vmx->loaded_vmcs != &vmx->vmcs01))
 		vmx_switch_vmcs(vcpu, &vmx->vmcs01);
@@ -353,9 +354,15 @@ static void free_nested(struct kvm_vcpu *vcpu)
 	vmx->nested.current_vmptr = INVALID_GPA;
 	if (enable_shadow_vmcs) {
 		vmx_disable_shadow_vmcs(vmx);
-		vmcs_clear(vmx->vmcs01.shadow_vmcs);
-		free_vmcs(vmx->vmcs01.shadow_vmcs);
+
+		/*
+		 * Keep the pointer visible until after VMCLEAR, so migration
+		 * can clear an active shadow VMCS on the old CPU.
+		 */
+		shadow_vmcs = vmx->vmcs01.shadow_vmcs;
+		vmcs_clear(shadow_vmcs);
 		vmx->vmcs01.shadow_vmcs = NULL;
+		free_vmcs(shadow_vmcs);
 	}
 	kfree(vmx->nested.cached_vmcs12);
 	vmx->nested.cached_vmcs12 = NULL;
diff --git linux-libre-7.1.5-gnu/arch/x86/mm/init_64.c linux-libre-7.1.6-gnu/arch/x86/mm/init_64.c
index 7e20b22d658b9..d57f29ca23a5a 100644
--- linux-libre-7.1.5-gnu/arch/x86/mm/init_64.c
+++ linux-libre-7.1.6-gnu/arch/x86/mm/init_64.c
@@ -1300,12 +1300,13 @@ kernel_physical_mapping_remove(unsigned long start, unsigned long end)
 	remove_pagetable(start, end, true, NULL);
 }
 
-void __ref arch_remove_memory(u64 start, u64 size, struct vmem_altmap *altmap)
+void __ref arch_remove_memory(u64 start, u64 size, struct vmem_altmap *altmap,
+			      struct dev_pagemap *pgmap)
 {
 	unsigned long start_pfn = start >> PAGE_SHIFT;
 	unsigned long nr_pages = size >> PAGE_SHIFT;
 
-	__remove_pages(start_pfn, nr_pages, altmap);
+	__remove_pages(start_pfn, nr_pages, altmap, pgmap);
 	kernel_physical_mapping_remove(start, start + size);
 }
 #endif /* CONFIG_MEMORY_HOTPLUG */
diff --git linux-libre-7.1.5-gnu/drivers/accel/amdxdna/amdxdna_ctx.c linux-libre-7.1.6-gnu/drivers/accel/amdxdna/amdxdna_ctx.c
index 5315466f137b5..f6fece060dfed 100644
--- linux-libre-7.1.5-gnu/drivers/accel/amdxdna/amdxdna_ctx.c
+++ linux-libre-7.1.6-gnu/drivers/accel/amdxdna/amdxdna_ctx.c
@@ -483,6 +483,7 @@ void amdxdna_sched_job_cleanup(struct amdxdna_sched_job *job)
 	amdxdna_arg_bos_put(job);
 	amdxdna_gem_put_obj(job->cmd_bo);
 	dma_fence_put(job->fence);
+	mmdrop(job->mm);
 }
 
 int amdxdna_cmd_submit(struct amdxdna_client *client,
@@ -549,6 +550,7 @@ int amdxdna_cmd_submit(struct amdxdna_client *client,
 
 	job->hwctx = hwctx;
 	job->mm = current->mm;
+	mmgrab(job->mm);
 
 	job->fence = amdxdna_fence_create(hwctx);
 	if (!job->fence) {
@@ -583,6 +585,8 @@ put_bos:
 cmd_put:
 	amdxdna_gem_put_obj(job->cmd_bo);
 free_job:
+	if (job->mm)
+		mmdrop(job->mm);
 	kfree(job);
 	return ret;
 }
diff --git linux-libre-7.1.5-gnu/drivers/accel/ethosu/ethosu_gem.c linux-libre-7.1.6-gnu/drivers/accel/ethosu/ethosu_gem.c
index 3401883e207fc..d50fed64d4d93 100644
--- linux-libre-7.1.5-gnu/drivers/accel/ethosu/ethosu_gem.c
+++ linux-libre-7.1.6-gnu/drivers/accel/ethosu/ethosu_gem.c
@@ -192,9 +192,17 @@ static u64 dma_length(struct ethosu_validated_cmdstream_info *info,
 	return len;
 }
 
-static u64 feat_matrix_length(struct ethosu_validated_cmdstream_info *info,
+static bool feat_matrix_chained(struct ethosu_device *edev, struct feat_matrix *fm)
+{
+	u32 storage = fm->precision >> 14;
+
+	return !ethosu_is_u65(edev) && storage == 2;
+}
+
+static u64 feat_matrix_length(struct ethosu_device *edev,
+			      struct ethosu_validated_cmdstream_info *info,
 			      struct feat_matrix *fm,
-			      u32 x, u32 y, u32 c)
+			      u32 x, u32 y, u32 c, bool ofm)
 {
 	u32 element_size, storage = fm->precision >> 14;
 	int tile = 0;
@@ -203,6 +211,9 @@ static u64 feat_matrix_length(struct ethosu_validated_cmdstream_info *info,
 	if (fm->region < 0)
 		return U64_MAX;
 
+	if (feat_matrix_chained(edev, fm))
+		return 0;
+
 	switch (storage) {
 	case 0:
 		if (x >= fm->width0 + 1) {
@@ -223,6 +234,8 @@ static u64 feat_matrix_length(struct ethosu_validated_cmdstream_info *info,
 			tile = 1;
 		}
 		break;
+	default:
+		return U64_MAX;
 	}
 	if (fm->base[tile] == U64_MAX)
 		return U64_MAX;
@@ -231,10 +244,11 @@ static u64 feat_matrix_length(struct ethosu_validated_cmdstream_info *info,
 
 	switch ((fm->precision >> 6) & 0x3) { // format
 	case 0: //nhwc:
-		addr += x * fm->stride_x + c;
+		element_size = BIT((fm->precision >> (ofm ? 1 : 2)) & 0x3);
+		addr += x * fm->stride_x + c * element_size;
 		break;
 	case 1: //nhcwb16:
-		element_size = BIT((fm->precision >> 1) & 0x3);
+		element_size = BIT((fm->precision >> (ofm ? 1 : 2)) & 0x3);
 
 		addr += (c / 16) * fm->stride_c + (16 * x + (c & 0xf)) * element_size;
 		break;
@@ -250,6 +264,7 @@ static int calc_sizes(struct drm_device *ddev,
 		      u16 op, struct cmd_state *st,
 		      bool ifm, bool ifm2, bool weight, bool scale)
 {
+	struct ethosu_device *edev = to_ethosu_device(ddev);
 	u64 len;
 
 	if (ifm) {
@@ -267,8 +282,8 @@ static int calc_sizes(struct drm_device *ddev,
 		if (ifm_height < 0 || ifm_width < 0)
 			return -EINVAL;
 
-		len = feat_matrix_length(info, &st->ifm, ifm_width,
-					 ifm_height, st->ifm.depth);
+		len = feat_matrix_length(edev, info, &st->ifm, ifm_width,
+					 ifm_height, st->ifm.depth, false);
 		dev_dbg(ddev->dev, "op %d: IFM:%d:0x%llx-0x%llx\n",
 			op, st->ifm.region, st->ifm.base[0], len);
 		if (len == U64_MAX)
@@ -276,8 +291,8 @@ static int calc_sizes(struct drm_device *ddev,
 	}
 
 	if (ifm2) {
-		len = feat_matrix_length(info, &st->ifm2, st->ifm.depth,
-					 0, st->ofm.depth);
+		len = feat_matrix_length(edev, info, &st->ifm2, st->ifm.depth,
+					 0, st->ofm.depth, false);
 		dev_dbg(ddev->dev, "op %d: IFM2:%d:0x%llx-0x%llx\n",
 			op, st->ifm2.region, st->ifm2.base[0], len);
 		if (len == U64_MAX)
@@ -308,13 +323,14 @@ static int calc_sizes(struct drm_device *ddev,
 			    st->scale[0].base + st->scale[0].length);
 	}
 
-	len = feat_matrix_length(info, &st->ofm, st->ofm.width,
-				 st->ofm.height[2], st->ofm.depth);
+	len = feat_matrix_length(edev, info, &st->ofm, st->ofm.width,
+				 st->ofm.height[2], st->ofm.depth, true);
 	dev_dbg(ddev->dev, "op %d: OFM:%d:0x%llx-0x%llx\n",
 		op, st->ofm.region, st->ofm.base[0], len);
 	if (len == U64_MAX)
 		return -EINVAL;
-	info->output_region[st->ofm.region] = true;
+	if (!feat_matrix_chained(edev, &st->ofm))
+		info->output_region[st->ofm.region] = true;
 
 	return 0;
 }
@@ -324,6 +340,7 @@ static int calc_sizes_elemwise(struct drm_device *ddev,
 			       u16 op, struct cmd_state *st,
 			       bool ifm, bool ifm2)
 {
+	struct ethosu_device *edev = to_ethosu_device(ddev);
 	u32 height, width, depth;
 	u64 len;
 
@@ -332,8 +349,8 @@ static int calc_sizes_elemwise(struct drm_device *ddev,
 		width = st->ifm.broadcast & 0x2 ? 0 : st->ofm.width;
 		depth = st->ifm.broadcast & 0x4 ? 0 : st->ofm.depth;
 
-		len = feat_matrix_length(info, &st->ifm, width,
-					 height, depth);
+		len = feat_matrix_length(edev, info, &st->ifm, width,
+					 height, depth, false);
 		dev_dbg(ddev->dev, "op %d: IFM:%d:0x%llx-0x%llx\n",
 			op, st->ifm.region, st->ifm.base[0], len);
 		if (len == U64_MAX)
@@ -345,21 +362,22 @@ static int calc_sizes_elemwise(struct drm_device *ddev,
 		width = st->ifm2.broadcast & 0x2 ? 0 : st->ofm.width;
 		depth = st->ifm2.broadcast & 0x4 ? 0 : st->ofm.depth;
 
-		len = feat_matrix_length(info, &st->ifm2, width,
-					 height, depth);
+		len = feat_matrix_length(edev, info, &st->ifm2, width,
+					 height, depth, false);
 		dev_dbg(ddev->dev, "op %d: IFM2:%d:0x%llx-0x%llx\n",
 			op, st->ifm2.region, st->ifm2.base[0], len);
 		if (len == U64_MAX)
 			return -EINVAL;
 	}
 
-	len = feat_matrix_length(info, &st->ofm, st->ofm.width,
-				 st->ofm.height[2], st->ofm.depth);
+	len = feat_matrix_length(edev, info, &st->ofm, st->ofm.width,
+				 st->ofm.height[2], st->ofm.depth, true);
 	dev_dbg(ddev->dev, "op %d: OFM:%d:0x%llx-0x%llx\n",
 		op, st->ofm.region, st->ofm.base[0], len);
 	if (len == U64_MAX)
 		return -EINVAL;
-	info->output_region[st->ofm.region] = true;
+	if (!feat_matrix_chained(edev, &st->ofm))
+		info->output_region[st->ofm.region] = true;
 
 	return 0;
 }
diff --git linux-libre-7.1.5-gnu/drivers/accel/ivpu/ivpu_hw_btrs.c linux-libre-7.1.6-gnu/drivers/accel/ivpu/ivpu_hw_btrs.c
index 06e65c5926185..992addabbd3c6 100644
--- linux-libre-7.1.5-gnu/drivers/accel/ivpu/ivpu_hw_btrs.c
+++ linux-libre-7.1.6-gnu/drivers/accel/ivpu/ivpu_hw_btrs.c
@@ -861,7 +861,7 @@ static void diagnose_failure_mtl(struct ivpu_device *vdev)
 
 static void diagnose_failure_lnl(struct ivpu_device *vdev)
 {
-	u32 reg = REGB_RD32(VPU_HW_BTRS_MTL_INTERRUPT_STAT) & BTRS_LNL_IRQ_MASK;
+	u32 reg = REGB_RD32(VPU_HW_BTRS_LNL_INTERRUPT_STAT) & BTRS_LNL_IRQ_MASK;
 
 	if (REG_TEST_FLD(VPU_HW_BTRS_LNL_INTERRUPT_STAT, ATS_ERR, reg)) {
 		ivpu_err(vdev, "ATS_ERR_LOG1 0x%08x ATS_ERR_LOG2 0x%08x\n",
diff --git linux-libre-7.1.5-gnu/drivers/android/binder/thread.rs linux-libre-7.1.6-gnu/drivers/android/binder/thread.rs
index 3b85208139410..bc0ef8927905c 100644
--- linux-libre-7.1.5-gnu/drivers/android/binder/thread.rs
+++ linux-libre-7.1.6-gnu/drivers/android/binder/thread.rs
@@ -1273,14 +1273,14 @@ impl Thread {
                         inner.extended_error =
                             ExtendedError::new(info.debug_id as u32, err.reply, source.to_errno());
                     }
-                }
 
-                pr_warn!(
-                    "{}:{} transaction to {} failed: {err:?}",
-                    info.from_pid,
-                    info.from_tid,
-                    info.to_pid
-                );
+                    pr_warn!(
+                        "{}:{} transaction to {} failed: {err:?}",
+                        info.from_pid,
+                        info.from_tid,
+                        info.to_pid
+                    );
+                }
             }
         }
 
diff --git linux-libre-7.1.5-gnu/drivers/ata/sata_dwc_460ex.c linux-libre-7.1.6-gnu/drivers/ata/sata_dwc_460ex.c
index 64cb544903d88..cf723ef39d7cc 100644
--- linux-libre-7.1.5-gnu/drivers/ata/sata_dwc_460ex.c
+++ linux-libre-7.1.6-gnu/drivers/ata/sata_dwc_460ex.c
@@ -19,7 +19,6 @@
 #include <linux/device.h>
 #include <linux/dmaengine.h>
 #include <linux/of.h>
-#include <linux/of_irq.h>
 #include <linux/platform_device.h>
 #include <linux/phy/phy.h>
 #include <linux/libata.h>
@@ -226,7 +225,6 @@ static int sata_dwc_dma_init_old(struct platform_device *pdev,
 				 struct sata_dwc_device *hsdev)
 {
 	struct device *dev = &pdev->dev;
-	struct device_node *np = dev->of_node;
 
 	hsdev->dma = devm_kzalloc(dev, sizeof(*hsdev->dma), GFP_KERNEL);
 	if (!hsdev->dma)
@@ -236,11 +234,9 @@ static int sata_dwc_dma_init_old(struct platform_device *pdev,
 	hsdev->dma->id = pdev->id;
 
 	/* Get SATA DMA interrupt number */
-	hsdev->dma->irq = irq_of_parse_and_map(np, 1);
-	if (!hsdev->dma->irq) {
-		dev_err(dev, "no SATA DMA irq\n");
-		return -ENODEV;
-	}
+	hsdev->dma->irq = platform_get_irq(pdev, 1);
+	if (hsdev->dma->irq < 0)
+		return hsdev->dma->irq;
 
 	/* Get physical SATA DMA register base address */
 	hsdev->dma->regs = devm_platform_ioremap_resource(pdev, 1);
@@ -398,8 +394,7 @@ static void clear_serror(struct ata_port *ap)
 
 static void clear_interrupt_bit(struct sata_dwc_device *hsdev, u32 bit)
 {
-	sata_dwc_writel(&hsdev->sata_dwc_regs->intpr,
-			sata_dwc_readl(&hsdev->sata_dwc_regs->intpr));
+	sata_dwc_writel(&hsdev->sata_dwc_regs->intpr, bit);
 }
 
 static u32 qcmd_tag_to_mask(u8 tag)
@@ -612,14 +607,9 @@ DRVSTILLBUSY:
 	status = ap->ops->sff_check_status(ap);
 	dev_dbg(ap->dev, "%s ATA status register=0x%x\n", __func__, status);
 
-	tag = 0;
 	while (tag_mask) {
-		while (!(tag_mask & 0x00000001)) {
-			tag++;
-			tag_mask <<= 1;
-		}
-
-		tag_mask &= (~0x00000001);
+		tag = __ffs(tag_mask);
+		tag_mask &= ~(1U << tag);
 		qc = ata_qc_from_tag(ap, tag);
 		if (unlikely(!qc)) {
 			dev_err(ap->dev, "failed to get qc");
@@ -1125,7 +1115,6 @@ static const struct ata_port_info sata_dwc_port_info[] = {
 static int sata_dwc_probe(struct platform_device *ofdev)
 {
 	struct device *dev = &ofdev->dev;
-	struct device_node *np = dev->of_node;
 	struct sata_dwc_device *hsdev;
 	u32 idr, versionr;
 	char *ver = (char *)&versionr;
@@ -1168,18 +1157,13 @@ static int sata_dwc_probe(struct platform_device *ofdev)
 	/* Save dev for later use in dev_xxx() routines */
 	hsdev->dev = dev;
 
-	/* Enable SATA Interrupts */
-	sata_dwc_enable_interrupts(hsdev);
-
 	/* Get SATA interrupt number */
-	irq = irq_of_parse_and_map(np, 0);
-	if (!irq) {
-		dev_err(dev, "no SATA DMA irq\n");
-		return -ENODEV;
-	}
+	irq = platform_get_irq(ofdev, 0);
+	if (irq < 0)
+		return irq;
 
 #ifdef CONFIG_SATA_DWC_OLD_DMA
-	if (!of_property_present(np, "dmas")) {
+	if (!of_property_present(dev->of_node, "dmas")) {
 		err = sata_dwc_dma_init_old(ofdev, hsdev);
 		if (err)
 			return err;
@@ -1203,6 +1187,8 @@ static int sata_dwc_probe(struct platform_device *ofdev)
 	if (err)
 		dev_err(dev, "failed to activate host");
 
+	/* Enable SATA Interrupts */
+	sata_dwc_enable_interrupts(hsdev);
 	return 0;
 
 error_out:
diff --git linux-libre-7.1.5-gnu/drivers/block/rbd.c linux-libre-7.1.6-gnu/drivers/block/rbd.c
index 6c1e7347e6a72..8b9f84398f923 100644
--- linux-libre-7.1.5-gnu/drivers/block/rbd.c
+++ linux-libre-7.1.6-gnu/drivers/block/rbd.c
@@ -1957,9 +1957,14 @@ static int rbd_object_map_update_finish(struct rbd_obj_request *obj_req,
 	bool has_current_state;
 	void *p;
 
-	if (osd_req->r_result)
+	if (osd_req->r_result < 0)
 		return osd_req->r_result;
 
+	/*
+	 * Writes aren't allowed to return a data payload.
+	 */
+	WARN_ON_ONCE(osd_req->r_result > 0);
+
 	/*
 	 * Nothing to do for a snapshot object map.
 	 */
diff --git linux-libre-7.1.5-gnu/drivers/block/ublk_drv.c linux-libre-7.1.6-gnu/drivers/block/ublk_drv.c
index 6c041eaebdb91..802d521a61849 100644
--- linux-libre-7.1.5-gnu/drivers/block/ublk_drv.c
+++ linux-libre-7.1.6-gnu/drivers/block/ublk_drv.c
@@ -19,6 +19,7 @@
 #include <linux/errno.h>
 #include <linux/major.h>
 #include <linux/wait.h>
+#include <linux/wait_bit.h>
 #include <linux/blkdev.h>
 #include <linux/init.h>
 #include <linux/swap.h>
@@ -26,7 +27,6 @@
 #include <linux/compat.h>
 #include <linux/mutex.h>
 #include <linux/writeback.h>
-#include <linux/completion.h>
 #include <linux/highmem.h>
 #include <linux/sysfs.h>
 #include <linux/miscdevice.h>
@@ -327,7 +327,6 @@ struct ublk_device {
 
 	struct ublk_params	params;
 
-	struct completion	completion;
 	u32			nr_queue_ready;
 	bool 			unprivileged_daemons;
 	struct mutex cancel_mutex;
@@ -3058,12 +3057,12 @@ static void ublk_mark_io_ready(struct ublk_device *ub, u16 q_id,
 	if (ublk_dev_ready(ub)) {
 		/*
 		 * All queues ready - clear device-level canceling flag
-		 * and complete the recovery/initialization.
+		 * and wake ublk_dev_ready() waiters.
 		 */
 		mutex_lock(&ub->cancel_mutex);
 		ub->canceling = false;
 		mutex_unlock(&ub->cancel_mutex);
-		complete_all(&ub->completion);
+		wake_up_var(&ub->nr_queue_ready);
 	}
 }
 
@@ -4266,7 +4265,6 @@ static int ublk_init_queues(struct ublk_device *ub)
 			goto fail;
 	}
 
-	init_completion(&ub->completion);
 	return 0;
 
  fail:
@@ -4410,6 +4408,26 @@ static bool ublk_validate_user_pid(struct ublk_device *ub, pid_t ublksrv_pid)
 	return ub->ublksrv_tgid == ublksrv_pid;
 }
 
+/*
+ * Wait until all queues have fetched their I/O commands, and return with
+ * ub->mutex held and readiness guaranteed: then every queue's ->canceling
+ * is cleared. Ready may regress between wakeup and mutex_lock() (F_BATCH
+ * UNPREP, daemon death), so re-check it under the mutex and wait again.
+ */
+static int ublk_wait_dev_ready_and_lock(struct ublk_device *ub)
+{
+	while (true) {
+		if (wait_var_event_interruptible(&ub->nr_queue_ready,
+						 ublk_dev_ready(ub)))
+			return -EINTR;
+
+		mutex_lock(&ub->mutex);
+		if (ublk_dev_ready(ub))
+			return 0;
+		mutex_unlock(&ub->mutex);
+	}
+}
+
 static int ublk_ctrl_start_dev(struct ublk_device *ub,
 		const struct ublksrv_ctrl_cmd *header)
 {
@@ -4492,15 +4510,10 @@ static int ublk_ctrl_start_dev(struct ublk_device *ub,
 		};
 	}
 
-	if (wait_for_completion_interruptible(&ub->completion) != 0)
+	if (ublk_wait_dev_ready_and_lock(ub))
 		return -EINTR;
 
-	if (!ublk_validate_user_pid(ub, ublksrv_pid))
-		return -EINVAL;
-
-	mutex_lock(&ub->mutex);
-	/* device may become not ready in case of F_BATCH */
-	if (!ublk_dev_ready(ub)) {
+	if (!ublk_validate_user_pid(ub, ublksrv_pid)) {
 		ret = -EINVAL;
 		goto out_unlock;
 	}
@@ -5064,7 +5077,6 @@ static int ublk_ctrl_start_recovery(struct ublk_device *ub)
 		goto out_unlock;
 	}
 	pr_devel("%s: start recovery for dev id %d\n", __func__, ub->ub_number);
-	init_completion(&ub->completion);
 	ret = 0;
  out_unlock:
 	mutex_unlock(&ub->mutex);
@@ -5080,16 +5092,17 @@ static int ublk_ctrl_end_recovery(struct ublk_device *ub,
 	pr_devel("%s: Waiting for all FETCH_REQs, dev id %d...\n", __func__,
 		 header->dev_id);
 
-	if (wait_for_completion_interruptible(&ub->completion))
+	if (ublk_wait_dev_ready_and_lock(ub))
 		return -EINTR;
 
 	pr_devel("%s: All FETCH_REQs received, dev id %d\n", __func__,
 		 header->dev_id);
 
-	if (!ublk_validate_user_pid(ub, ublksrv_pid))
-		return -EINVAL;
+	if (!ublk_validate_user_pid(ub, ublksrv_pid)) {
+		ret = -EINVAL;
+		goto out_unlock;
+	}
 
-	mutex_lock(&ub->mutex);
 	if (ublk_nosrv_should_stop_dev(ub))
 		goto out_unlock;
 
diff --git linux-libre-7.1.5-gnu/drivers/bluetooth/btqca.c linux-libre-7.1.6-gnu/drivers/bluetooth/btqca.c
index ef0b20c7422fc..fd2baf29b5437 100644
--- linux-libre-7.1.5-gnu/drivers/bluetooth/btqca.c
+++ linux-libre-7.1.6-gnu/drivers/bluetooth/btqca.c
@@ -413,7 +413,7 @@ static int qca_tlv_check_data(struct hci_dev *hdev,
 
 		idx = 0;
 		data = tlv->data;
-		while (idx < length - sizeof(struct tlv_type_nvm)) {
+		while (idx + sizeof(struct tlv_type_nvm) <= length) {
 			tlv_nvm = (struct tlv_type_nvm *)(data + idx);
 
 			tag_id = le16_to_cpu(tlv_nvm->tag_id);
diff --git linux-libre-7.1.5-gnu/drivers/bluetooth/btusb.c linux-libre-7.1.6-gnu/drivers/bluetooth/btusb.c
index f970c2a7f088b..c6327d07cbaac 100644
--- linux-libre-7.1.5-gnu/drivers/bluetooth/btusb.c
+++ linux-libre-7.1.6-gnu/drivers/bluetooth/btusb.c
@@ -2765,7 +2765,9 @@ static int btusb_setup_realtek(struct hci_dev *hdev)
 
 static int btusb_recv_event_realtek(struct hci_dev *hdev, struct sk_buff *skb)
 {
-	if (skb->data[0] == HCI_VENDOR_PKT && skb->data[2] == RTK_SUB_EVENT_CODE_COREDUMP) {
+	if (skb->len >= HCI_EVENT_HDR_SIZE + 1 &&
+	    skb->data[0] == HCI_VENDOR_PKT &&
+	    skb->data[2] == RTK_SUB_EVENT_CODE_COREDUMP) {
 		struct rtk_dev_coredump_hdr hdr = {
 			.code = RTK_DEVCOREDUMP_CODE_MEMDUMP,
 		};
diff --git linux-libre-7.1.5-gnu/drivers/bluetooth/hci_qca.c linux-libre-7.1.6-gnu/drivers/bluetooth/hci_qca.c
index 2444471956197..bd29d422c2090 100644
--- linux-libre-7.1.5-gnu/drivers/bluetooth/hci_qca.c
+++ linux-libre-7.1.6-gnu/drivers/bluetooth/hci_qca.c
@@ -1088,6 +1088,10 @@ static void qca_controller_memdump(struct work_struct *work)
 			if (!(qca_memdump->ram_dump_size)) {
 				bt_dev_err(hu->hdev, "Rx invalid memdump size");
 				kfree(qca_memdump);
+				qca->qca_memdump = NULL;
+				qca->memdump_state = QCA_MEMDUMP_COLLECTED;
+				clear_and_wake_up_bit(QCA_MEMDUMP_COLLECTION, &qca->flags);
+				clear_bit(QCA_IBS_DISABLED, &qca->flags);
 				kfree_skb(skb);
 				mutex_unlock(&qca->hci_memdump_lock);
 				return;
diff --git linux-libre-7.1.5-gnu/drivers/cdrom/cdrom.c linux-libre-7.1.6-gnu/drivers/cdrom/cdrom.c
index 62934cf4b10de..4f1fd389260f5 100644
--- linux-libre-7.1.5-gnu/drivers/cdrom/cdrom.c
+++ linux-libre-7.1.6-gnu/drivers/cdrom/cdrom.c
@@ -3187,6 +3187,7 @@ static noinline int mmc_ioctl_cdrom_volume(struct cdrom_device_info *cdi,
 
 	/* set volume */
 	cgc->buffer = buffer + offset - 8;
+	cgc->buflen -= offset - 8;
 	memset(cgc->buffer, 0, 8);
 	return cdrom_mode_select(cdi, cgc);
 }
diff --git linux-libre-7.1.5-gnu/drivers/comedi/drivers/comedi_parport.c linux-libre-7.1.6-gnu/drivers/comedi/drivers/comedi_parport.c
index 2604680d86c4a..57ee3f9dfba26 100644
--- linux-libre-7.1.5-gnu/drivers/comedi/drivers/comedi_parport.c
+++ linux-libre-7.1.6-gnu/drivers/comedi/drivers/comedi_parport.c
@@ -211,6 +211,13 @@ static irqreturn_t parport_interrupt(int irq, void *d)
 	unsigned int ctrl;
 	unsigned short val = 0;
 
+	/*
+	 * Check device is fully attached.  Device interrupts should have
+	 * been disabled, but do this in case of bad hardware.
+	 */
+	if (!dev->attached)
+		return IRQ_NONE;
+
 	ctrl = inb(dev->iobase + PARPORT_CTRL_REG);
 	if (!(ctrl & PARPORT_CTRL_IRQ_ENA))
 		return IRQ_NONE;
@@ -233,6 +240,9 @@ static int parport_attach(struct comedi_device *dev,
 	if (ret)
 		return ret;
 
+	outb(0, dev->iobase + PARPORT_DATA_REG);
+	outb(0, dev->iobase + PARPORT_CTRL_REG);
+
 	if (it->options[1]) {
 		ret = request_irq(it->options[1], parport_interrupt, 0,
 				  dev->board_name, dev);
@@ -288,9 +298,6 @@ static int parport_attach(struct comedi_device *dev,
 		s->cancel	= parport_intr_cancel;
 	}
 
-	outb(0, dev->iobase + PARPORT_DATA_REG);
-	outb(0, dev->iobase + PARPORT_CTRL_REG);
-
 	return 0;
 }
 
diff --git linux-libre-7.1.5-gnu/drivers/cpufreq/cpufreq.c linux-libre-7.1.6-gnu/drivers/cpufreq/cpufreq.c
index d41067cd1f1b2..2debe39fc477b 100644
--- linux-libre-7.1.5-gnu/drivers/cpufreq/cpufreq.c
+++ linux-libre-7.1.6-gnu/drivers/cpufreq/cpufreq.c
@@ -2583,6 +2583,9 @@ static void cpufreq_update_pressure(struct cpufreq_policy *policy)
 
 	cpu = cpumask_first(policy->related_cpus);
 	max_freq = arch_scale_freq_ref(cpu);
+	if (!max_freq)
+		max_freq = policy->cpuinfo.max_freq;
+
 	capped_freq = policy->max;
 
 	/*
diff --git linux-libre-7.1.5-gnu/drivers/crypto/tegra/tegra-se-main.c linux-libre-7.1.6-gnu/drivers/crypto/tegra/tegra-se-main.c
index e8d8c3a23d7ad..d2f518ef9a103 100644
--- linux-libre-7.1.5-gnu/drivers/crypto/tegra/tegra-se-main.c
+++ linux-libre-7.1.6-gnu/drivers/crypto/tegra/tegra-se-main.c
@@ -52,7 +52,7 @@ tegra_se_cmdbuf_pin(struct device *dev, struct host1x_bo *bo, enum dma_data_dire
 		return ERR_PTR(-ENOMEM);
 
 	kref_init(&map->ref);
-	map->bo = host1x_bo_get(bo);
+	map->bo = bo;
 	map->direction = direction;
 	map->dev = dev;
 
@@ -93,7 +93,6 @@ static void tegra_se_cmdbuf_unpin(struct host1x_bo_mapping *map)
 	dma_unmap_sgtable(map->dev, map->sgt, map->direction, 0);
 	sg_free_table(map->sgt);
 	kfree(map->sgt);
-	host1x_bo_put(map->bo);
 
 	kfree(map);
 }
diff --git linux-libre-7.1.5-gnu/drivers/dma-buf/udmabuf.c linux-libre-7.1.6-gnu/drivers/dma-buf/udmabuf.c
index 2f94be1df525a..2e7b5d4d11f42 100644
--- linux-libre-7.1.5-gnu/drivers/dma-buf/udmabuf.c
+++ linux-libre-7.1.6-gnu/drivers/dma-buf/udmabuf.c
@@ -247,21 +247,22 @@ static int begin_cpu_udmabuf(struct dma_buf *buf,
 {
 	struct udmabuf *ubuf = buf->priv;
 	struct device *dev = ubuf->device->this_device;
-	int ret = 0;
 
 	if (!ubuf->sg) {
 		ubuf->sg = get_sg_table(dev, buf, direction);
 		if (IS_ERR(ubuf->sg)) {
+			int ret;
+
 			ret = PTR_ERR(ubuf->sg);
 			ubuf->sg = NULL;
+			return ret;
 		} else {
 			ubuf->sg_dir = direction;
 		}
-	} else {
-		dma_sync_sgtable_for_cpu(dev, ubuf->sg, direction);
 	}
 
-	return ret;
+	dma_sync_sgtable_for_cpu(dev, ubuf->sg, direction);
+	return 0;
 }
 
 static int end_cpu_udmabuf(struct dma_buf *buf,
diff --git linux-libre-7.1.5-gnu/drivers/dpll/dpll_netlink.c linux-libre-7.1.6-gnu/drivers/dpll/dpll_netlink.c
index 75e3ae0c16d07..8163521188c06 100644
--- linux-libre-7.1.5-gnu/drivers/dpll/dpll_netlink.c
+++ linux-libre-7.1.6-gnu/drivers/dpll/dpll_netlink.c
@@ -557,6 +557,9 @@ dpll_msg_add_pin_ref_sync(struct sk_buff *msg, struct dpll_pin *pin,
 		if (!dpll_pin_available(ref_sync_pin))
 			continue;
 		ref_sync_pin_priv = dpll_pin_on_dpll_priv(dpll, ref_sync_pin);
+		/* Pin may have been unregistered from this dpll already */
+		if (!ref_sync_pin_priv)
+			continue;
 		if (WARN_ON(!ops->ref_sync_get))
 			return -EOPNOTSUPP;
 		ret = ops->ref_sync_get(pin, pin_priv, ref_sync_pin,
diff --git linux-libre-7.1.5-gnu/drivers/firewire/net.c linux-libre-7.1.6-gnu/drivers/firewire/net.c
index 82b3b6d9ed2df..2a0727935d736 100644
--- linux-libre-7.1.5-gnu/drivers/firewire/net.c
+++ linux-libre-7.1.6-gnu/drivers/firewire/net.c
@@ -298,31 +298,34 @@ static struct fwnet_fragment_info *fwnet_frag_new(
 		if (fi->offset + fi->len == offset) {
 			/* The new fragment can be tacked on to the end */
 			/* Did the new fragment plug a hole? */
-			fi2 = list_entry(fi->fi_link.next,
-					 struct fwnet_fragment_info, fi_link);
-			if (fi->offset + fi->len == fi2->offset) {
-				/* glue fragments together */
-				fi->len += len + fi2->len;
-				list_del(&fi2->fi_link);
-				kfree(fi2);
-			} else {
-				fi->len += len;
+			if (!list_is_last(&fi->fi_link, &pd->fi_list)) {
+				fi2 = list_next_entry(fi, fi_link);
+				if (offset + len == fi2->offset) {
+					/* glue fragments together */
+					fi->len += len + fi2->len;
+					list_del(&fi2->fi_link);
+					kfree(fi2);
+
+					return fi;
+				}
 			}
+			fi->len += len;
 
 			return fi;
 		}
 		if (offset + len == fi->offset) {
 			/* The new fragment can be tacked on to the beginning */
 			/* Did the new fragment plug a hole? */
-			fi2 = list_entry(fi->fi_link.prev,
-					 struct fwnet_fragment_info, fi_link);
-			if (fi2->offset + fi2->len == fi->offset) {
-				/* glue fragments together */
-				fi2->len += fi->len + len;
-				list_del(&fi->fi_link);
-				kfree(fi);
-
-				return fi2;
+			if (!list_is_first(&fi->fi_link, &pd->fi_list)) {
+				fi2 = list_prev_entry(fi, fi_link);
+				if (fi2->offset + fi2->len == offset) {
+					/* glue fragments together */
+					fi2->len += fi->len + len;
+					list_del(&fi->fi_link);
+					kfree(fi);
+
+					return fi2;
+				}
 			}
 			fi->offset = offset;
 			fi->len += len;
diff --git linux-libre-7.1.5-gnu/drivers/firmware/arm_ffa/driver.c linux-libre-7.1.6-gnu/drivers/firmware/arm_ffa/driver.c
index cab32cfdac423..4cbf7537e6242 100644
--- linux-libre-7.1.5-gnu/drivers/firmware/arm_ffa/driver.c
+++ linux-libre-7.1.6-gnu/drivers/firmware/arm_ffa/driver.c
@@ -32,6 +32,7 @@
 #include <linux/interrupt.h>
 #include <linux/io.h>
 #include <linux/kernel.h>
+#include <linux/minmax.h>
 #include <linux/module.h>
 #include <linux/mm.h>
 #include <linux/mutex.h>
@@ -55,7 +56,9 @@
 	(FIELD_PREP(SENDER_ID_MASK, (s)) | FIELD_PREP(RECEIVER_ID_MASK, (r)))
 
 #define RXTX_MAP_MIN_BUFSZ_MASK	GENMASK(1, 0)
-#define RXTX_MAP_MIN_BUFSZ(x)	((x) & RXTX_MAP_MIN_BUFSZ_MASK)
+#define RXTX_MAP_MAX_BUFSZ_MASK	GENMASK(31, 16)
+#define RXTX_MAP_MIN_BUFSZ(x)	(FIELD_GET(RXTX_MAP_MIN_BUFSZ_MASK, (x)))
+#define RXTX_MAP_MAX_BUFSZ(x)	(FIELD_GET(RXTX_MAP_MAX_BUFSZ_MASK, (x)))
 
 #define FFA_MAX_NOTIFICATIONS		64
 
@@ -708,30 +711,39 @@ ffa_setup_and_transmit(u32 func_id, void *buffer, u32 max_fragsize,
 	struct ffa_composite_mem_region *composite;
 	struct ffa_mem_region_addr_range *constituents;
 	struct ffa_mem_region_attributes *ep_mem_access;
-	u32 idx, frag_len, length, buf_sz = 0, num_entries = sg_nents(args->sg);
+	u32 idx, frag_len, length, buf_sz = 0, num_entries = sg_nents(args->sg), ep_offset;
+	u32 emad_end, emad_size = ffa_emad_size_get(drv_info->version);
 
 	mem_region->tag = args->tag;
 	mem_region->flags = args->flags;
 	mem_region->sender_id = drv_info->vm_id;
 	mem_region->attributes = ffa_memory_attributes_get(func_id);
+
+	ffa_mem_region_additional_setup(drv_info->version, mem_region);
 	composite_offset = ffa_mem_desc_offset(buffer, args->nattrs,
 					       drv_info->version);
+	if (composite_offset + sizeof(*composite) > max_fragsize)
+		return -ENXIO;
 
 	for (idx = 0; idx < args->nattrs; idx++) {
-		ep_mem_access = buffer +
-			ffa_mem_desc_offset(buffer, idx, drv_info->version);
+		ep_offset = ffa_mem_desc_offset(buffer, idx, drv_info->version);
+		if (check_add_overflow(ep_offset, emad_size, &emad_end))
+			return -ENXIO;
+
+		if (emad_end > max_fragsize)
+			return -ENXIO;
+
+		ep_mem_access = buffer + ep_offset;
+		memset(ep_mem_access, 0, emad_size);
 		ep_mem_access->receiver = args->attrs[idx].receiver;
 		ep_mem_access->attrs = args->attrs[idx].attrs;
 		ep_mem_access->composite_off = composite_offset;
-		ep_mem_access->flag = 0;
-		ep_mem_access->reserved = 0;
 		ffa_emad_impdef_value_init(drv_info->version,
 					   ep_mem_access->impdef_val,
 					   args->attrs[idx].impdef_val);
 	}
 	mem_region->handle = 0;
 	mem_region->ep_count = args->nattrs;
-	ffa_mem_region_additional_setup(drv_info->version, mem_region);
 
 	composite = buffer + composite_offset;
 	composite->total_pg_cnt = ffa_get_num_pages_sg(args->sg);
@@ -764,7 +776,7 @@ ffa_setup_and_transmit(u32 func_id, void *buffer, u32 max_fragsize,
 			constituents = buffer;
 		}
 
-		if ((void *)constituents - buffer > max_fragsize) {
+		if ((void *)constituents + sizeof(*constituents) - buffer > max_fragsize) {
 			pr_err("Memory Region Fragment > Tx Buffer size\n");
 			return -EFAULT;
 		}
@@ -773,7 +785,7 @@ ffa_setup_and_transmit(u32 func_id, void *buffer, u32 max_fragsize,
 		constituents->pg_cnt = args->sg->length / FFA_PAGE_SIZE;
 		constituents->reserved = 0;
 		constituents++;
-		frag_len += sizeof(struct ffa_mem_region_addr_range);
+		frag_len += sizeof(*constituents);
 	} while ((args->sg = sg_next(args->sg)));
 
 	return ffa_transmit_fragment(func_id, addr, buf_sz, frag_len,
@@ -1134,7 +1146,7 @@ static int ffa_partition_info_get(const char *uuid_str,
 	uuid_t uuid;
 	struct ffa_partition_info *pbuf;
 
-	if (uuid_parse(uuid_str, &uuid)) {
+	if (!uuid_str || uuid_parse(uuid_str, &uuid)) {
 		pr_err("invalid uuid (%s)\n", uuid_str);
 		return -ENODEV;
 	}
@@ -2095,7 +2107,7 @@ static int __init ffa_init(void)
 {
 	int ret;
 	u32 buf_sz;
-	size_t rxtx_bufsz = SZ_4K;
+	size_t rxtx_min_bufsz = SZ_4K, rxtx_max_bufsz = 0, rxtx_bufsz;
 
 	ret = ffa_transport_init(&invoke_ffa_fn);
 	if (ret)
@@ -2118,15 +2130,18 @@ static int __init ffa_init(void)
 	ret = ffa_features(FFA_FN_NATIVE(RXTX_MAP), 0, &buf_sz, NULL);
 	if (!ret) {
 		if (RXTX_MAP_MIN_BUFSZ(buf_sz) == 1)
-			rxtx_bufsz = SZ_64K;
+			rxtx_min_bufsz = SZ_64K;
 		else if (RXTX_MAP_MIN_BUFSZ(buf_sz) == 2)
-			rxtx_bufsz = SZ_16K;
+			rxtx_min_bufsz = SZ_16K;
 		else
-			rxtx_bufsz = SZ_4K;
+			rxtx_min_bufsz = SZ_4K;
+
+		rxtx_max_bufsz = RXTX_MAP_MAX_BUFSZ(buf_sz) * SZ_4K;
+		if (rxtx_max_bufsz != 0 && rxtx_max_bufsz < rxtx_min_bufsz)
+			rxtx_max_bufsz = rxtx_min_bufsz;
 	}
 
-	rxtx_bufsz = PAGE_ALIGN(rxtx_bufsz);
-	drv_info->rxtx_bufsz = rxtx_bufsz;
+	rxtx_bufsz = min_not_zero(PAGE_ALIGN(rxtx_min_bufsz), rxtx_max_bufsz);
 	drv_info->rx_buffer = alloc_pages_exact(rxtx_bufsz, GFP_KERNEL);
 	if (!drv_info->rx_buffer) {
 		ret = -ENOMEM;
@@ -2142,10 +2157,17 @@ static int __init ffa_init(void)
 	ret = ffa_rxtx_map(virt_to_phys(drv_info->tx_buffer),
 			   virt_to_phys(drv_info->rx_buffer),
 			   rxtx_bufsz / FFA_PAGE_SIZE);
+	if (ret == -EINVAL && !rxtx_max_bufsz && rxtx_min_bufsz < rxtx_bufsz) {
+		rxtx_bufsz = rxtx_min_bufsz;
+		ret = ffa_rxtx_map(virt_to_phys(drv_info->tx_buffer),
+				   virt_to_phys(drv_info->rx_buffer),
+				   rxtx_bufsz / FFA_PAGE_SIZE);
+	}
 	if (ret) {
 		pr_err("failed to register FFA RxTx buffers\n");
 		goto free_pages;
 	}
+	drv_info->rxtx_bufsz = rxtx_bufsz;
 
 	mutex_init(&drv_info->rx_lock);
 	mutex_init(&drv_info->tx_lock);
diff --git linux-libre-7.1.5-gnu/drivers/firmware/arm_scmi/notify.c linux-libre-7.1.6-gnu/drivers/firmware/arm_scmi/notify.c
index 40ec184eedaec..0a192cf2deab6 100644
--- linux-libre-7.1.5-gnu/drivers/firmware/arm_scmi/notify.c
+++ linux-libre-7.1.6-gnu/drivers/firmware/arm_scmi/notify.c
@@ -600,9 +600,9 @@ int scmi_notify(const struct scmi_handle *handle, u8 proto_id, u8 evt_id,
 		return -EINVAL;
 	}
 	if (kfifo_avail(&r_evt->proto->equeue.kfifo) < sizeof(eh) + len) {
-		dev_warn(handle->dev,
-			 "queue full, dropping proto_id:%d  evt_id:%d  ts:%lld\n",
-			 proto_id, evt_id, ktime_to_ns(ts));
+		dev_warn_ratelimited(handle->dev,
+				     "queue full, dropping proto_id:%d  evt_id:%d  ts:%lld\n",
+				     proto_id, evt_id, ktime_to_ns(ts));
 		return -ENOMEM;
 	}
 
diff --git linux-libre-7.1.5-gnu/drivers/firmware/stratix10-svc.c linux-libre-7.1.6-gnu/drivers/firmware/stratix10-svc.c
index 39eb78f5905b3..7f73703407ee7 100644
--- linux-libre-7.1.5-gnu/drivers/firmware/stratix10-svc.c
+++ linux-libre-7.1.6-gnu/drivers/firmware/stratix10-svc.c
@@ -1487,8 +1487,9 @@ int stratix10_svc_async_poll(struct stratix10_svc_chan *chan,
 			WARN_ON_ONCE(1);
 		}
 		return 0;
-	} else if (handle->res.a0 == INTEL_SIP_SMC_STATUS_BUSY) {
-		dev_dbg(ctrl->dev, "async message is still in progress\n");
+	} else if (handle->res.a0 == INTEL_SIP_SMC_STATUS_BUSY ||
+		   handle->res.a0 == INTEL_SIP_SMC_STATUS_NO_RESPONSE) {
+		dev_dbg(ctrl->dev, "async message is not ready yet\n");
 		return -EAGAIN;
 	}
 
@@ -1845,14 +1846,16 @@ void *stratix10_svc_allocate_memory(struct stratix10_svc_chan *chan,
 	struct gen_pool *genpool = chan->ctrl->genpool;
 	size_t s = roundup(size, 1 << genpool->min_alloc_order);
 
-	pmem = devm_kzalloc(chan->ctrl->dev, sizeof(*pmem), GFP_KERNEL);
+	pmem = kzalloc_obj(*pmem);
 	if (!pmem)
 		return ERR_PTR(-ENOMEM);
 
 	guard(mutex)(&svc_mem_lock);
 	va = gen_pool_alloc(genpool, s);
-	if (!va)
+	if (!va) {
+		kfree(pmem);
 		return ERR_PTR(-ENOMEM);
+	}
 
 	memset((void *)va, 0, s);
 	pa = gen_pool_virt_to_phys(genpool, va);
@@ -1878,6 +1881,7 @@ EXPORT_SYMBOL_GPL(stratix10_svc_allocate_memory);
 void stratix10_svc_free_memory(struct stratix10_svc_chan *chan, void *kaddr)
 {
 	struct stratix10_svc_data_mem *pmem;
+
 	guard(mutex)(&svc_mem_lock);
 
 	list_for_each_entry(pmem, &svc_data_mem, node)
@@ -1886,10 +1890,9 @@ void stratix10_svc_free_memory(struct stratix10_svc_chan *chan, void *kaddr)
 				       (unsigned long)kaddr, pmem->size);
 			pmem->vaddr = NULL;
 			list_del(&pmem->node);
+			kfree(pmem);
 			return;
 		}
-
-	list_del(&svc_data_mem);
 }
 EXPORT_SYMBOL_GPL(stratix10_svc_free_memory);
 
@@ -2042,12 +2045,12 @@ static void stratix10_svc_drv_remove(struct platform_device *pdev)
 	struct stratix10_svc_controller *ctrl = platform_get_drvdata(pdev);
 	struct stratix10_svc *svc = ctrl->svc;
 
+	platform_device_unregister(svc->stratix10_svc_rsu);
+
 	stratix10_svc_async_exit(ctrl);
 
 	of_platform_depopulate(ctrl->dev);
 
-	platform_device_unregister(svc->stratix10_svc_rsu);
-
 	for (i = 0; i < SVC_NUM_CHANNEL; i++) {
 		if (ctrl->chans[i].task) {
 			kthread_stop(ctrl->chans[i].task);
diff --git linux-libre-7.1.5-gnu/drivers/gpu/drm/amd/amdgpu/amdgpu_acp.c linux-libre-7.1.6-gnu/drivers/gpu/drm/amd/amdgpu/amdgpu_acp.c
index 62807b65f2af8..0365cc2ce34f0 100644
--- linux-libre-7.1.5-gnu/drivers/gpu/drm/amd/amdgpu/amdgpu_acp.c
+++ linux-libre-7.1.6-gnu/drivers/gpu/drm/amd/amdgpu/amdgpu_acp.c
@@ -509,6 +509,7 @@ static int acp_hw_fini(struct amdgpu_ip_block *ip_block)
 	u32 val = 0;
 	u32 count = 0;
 	struct amdgpu_device *adev = ip_block->adev;
+	int ret = 0;
 
 	/* return early if no ACP */
 	if (!adev->acp.acp_genpd) {
@@ -530,7 +531,8 @@ static int acp_hw_fini(struct amdgpu_ip_block *ip_block)
 			break;
 		if (--count == 0) {
 			dev_err(&adev->pdev->dev, "Failed to reset ACP\n");
-			return -ETIMEDOUT;
+			ret = -ETIMEDOUT;
+			goto out;
 		}
 		udelay(100);
 	}
@@ -547,20 +549,23 @@ static int acp_hw_fini(struct amdgpu_ip_block *ip_block)
 			break;
 		if (--count == 0) {
 			dev_err(&adev->pdev->dev, "Failed to reset ACP\n");
-			return -ETIMEDOUT;
+			ret = -ETIMEDOUT;
+			goto out;
 		}
 		udelay(100);
 	}
-
+out:
 	device_for_each_child(adev->acp.parent, NULL,
 			      acp_genpd_remove_device);
 
 	mfd_remove_devices(adev->acp.parent);
 	kfree(adev->acp.acp_res);
+	pm_genpd_remove(&adev->acp.acp_genpd->gpd);
 	kfree(adev->acp.acp_genpd);
+	adev->acp.acp_genpd = NULL;
 	kfree(adev->acp.acp_cell);
 
-	return 0;
+	return ret;
 }
 
 static int acp_suspend(struct amdgpu_ip_block *ip_block)
diff --git linux-libre-7.1.5-gnu/drivers/gpu/drm/amd/amdgpu/amdgpu_bios.c linux-libre-7.1.6-gnu/drivers/gpu/drm/amd/amdgpu/amdgpu_bios.c
index 35d04e69aec09..af88cab07413b 100644
--- linux-libre-7.1.5-gnu/drivers/gpu/drm/amd/amdgpu/amdgpu_bios.c
+++ linux-libre-7.1.6-gnu/drivers/gpu/drm/amd/amdgpu/amdgpu_bios.c
@@ -371,19 +371,59 @@ static bool amdgpu_read_disabled_bios(struct amdgpu_device *adev)
 }
 
 #ifdef CONFIG_ACPI
+/**
+ * amdgpu_acpi_vfct_match() - Check if a VFCT entry matches the device
+ * @adev: AMDGPU device
+ * @vhdr: VFCT image header to check
+ *
+ * VFCT entries contain the PCI bus number as recorded during BIOS POST.
+ * On systems where the kernel renumbers PCI buses (e.g. pci=realloc or
+ * resource conflicts), the runtime bus number may differ from the POST
+ * value.  Match by device identity (vendor + device + function) and use
+ * the bus number as a preference: exact bus match is preferred, but when
+ * the bus numbers disagree we accept the entry if the device identity
+ * matches.
+ *
+ * Returns: 0 on match, -ENODEV on no match
+ */
+static int amdgpu_acpi_vfct_match(struct amdgpu_device *adev,
+				  VFCT_IMAGE_HEADER *vhdr)
+{
+	/* Vendor and device IDs must always match */
+	if (vhdr->VendorID != adev->pdev->vendor ||
+	    vhdr->DeviceID != adev->pdev->device)
+		return -ENODEV;
+
+	if (vhdr->PCIDevice != PCI_SLOT(adev->pdev->devfn) ||
+	    vhdr->PCIFunction != PCI_FUNC(adev->pdev->devfn))
+		return -ENODEV;
+
+	/* Exact bus number match - preferred */
+	if (vhdr->PCIBus == adev->pdev->bus->number)
+		return 0;
+
+	/* Bus mismatch but device identity matches (PCI renumbering case) */
+	dev_notice(adev->dev,
+		   "VFCT bus number mismatch: table %u != runtime %u, matching by device identity (vendor 0x%04x device 0x%04x)\n",
+		   vhdr->PCIBus, adev->pdev->bus->number,
+		   adev->pdev->vendor, adev->pdev->device);
+	return 0;
+}
+
 static bool amdgpu_acpi_vfct_bios(struct amdgpu_device *adev)
 {
 	struct acpi_table_header *hdr;
 	acpi_size tbl_size;
 	UEFI_ACPI_VFCT *vfct;
 	unsigned int offset;
+	bool r = false;
 
 	if (!ACPI_SUCCESS(acpi_get_table("VFCT", 1, &hdr)))
 		return false;
 	tbl_size = hdr->length;
 	if (tbl_size < sizeof(UEFI_ACPI_VFCT)) {
 		dev_info(adev->dev, "ACPI VFCT table present but broken (too short #1),skipping\n");
-		return false;
+		goto out;
 	}
 
 	vfct = (UEFI_ACPI_VFCT *)hdr;
@@ -396,36 +436,36 @@ static bool amdgpu_acpi_vfct_bios(struct amdgpu_device *adev)
 		offset += sizeof(VFCT_IMAGE_HEADER);
 		if (offset > tbl_size) {
 			dev_info(adev->dev, "ACPI VFCT image header truncated,skipping\n");
-			return false;
+			goto out;
 		}
 
 		offset += vhdr->ImageLength;
 		if (offset > tbl_size) {
 			dev_info(adev->dev, "ACPI VFCT image truncated,skipping\n");
-			return false;
+			goto out;
 		}
 
 		if (vhdr->ImageLength &&
-		    vhdr->PCIBus == adev->pdev->bus->number &&
-		    vhdr->PCIDevice == PCI_SLOT(adev->pdev->devfn) &&
-		    vhdr->PCIFunction == PCI_FUNC(adev->pdev->devfn) &&
-		    vhdr->VendorID == adev->pdev->vendor &&
-		    vhdr->DeviceID == adev->pdev->device) {
+		    !amdgpu_acpi_vfct_match(adev, vhdr)) {
 			adev->bios = kmemdup(&vbios->VbiosContent,
 					     vhdr->ImageLength,
 					     GFP_KERNEL);
 
 			if (!check_atom_bios(adev, vhdr->ImageLength)) {
 				amdgpu_bios_release(adev);
-				return false;
+				goto out;
 			}
 			adev->bios_size = vhdr->ImageLength;
-			return true;
+			r = true;
+			goto out;
 		}
 	}
 
 	dev_info(adev->dev, "ACPI VFCT table present but broken (too short #2),skipping\n");
-	return false;
+
+out:
+	acpi_put_table(hdr);
+	return r;
 }
 #else
 static inline bool amdgpu_acpi_vfct_bios(struct amdgpu_device *adev)
diff --git linux-libre-7.1.5-gnu/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c linux-libre-7.1.6-gnu/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c
index 583fd67a2c648..9935869709167 100644
--- linux-libre-7.1.5-gnu/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c
+++ linux-libre-7.1.6-gnu/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c
@@ -252,13 +252,17 @@ static int amdgpu_cs_pass1(struct amdgpu_cs_parser *p,
 				goto free_partial_kdata;
 			break;
 
+		case AMDGPU_CHUNK_ID_CP_GFX_SHADOW:
+			if (size < sizeof(struct drm_amdgpu_cs_chunk_cp_gfx_shadow))
+				goto free_partial_kdata;
+			break;
+
 		case AMDGPU_CHUNK_ID_DEPENDENCIES:
 		case AMDGPU_CHUNK_ID_SYNCOBJ_IN:
 		case AMDGPU_CHUNK_ID_SYNCOBJ_OUT:
 		case AMDGPU_CHUNK_ID_SCHEDULED_DEPENDENCIES:
 		case AMDGPU_CHUNK_ID_SYNCOBJ_TIMELINE_WAIT:
 		case AMDGPU_CHUNK_ID_SYNCOBJ_TIMELINE_SIGNAL:
-		case AMDGPU_CHUNK_ID_CP_GFX_SHADOW:
 			break;
 
 		default:
diff --git linux-libre-7.1.5-gnu/drivers/gpu/drm/amd/amdgpu/amdgpu_ctx.c linux-libre-7.1.6-gnu/drivers/gpu/drm/amd/amdgpu/amdgpu_ctx.c
index 7af86a32c0c5f..ff77126c56443 100644
--- linux-libre-7.1.5-gnu/drivers/gpu/drm/amd/amdgpu/amdgpu_ctx.c
+++ linux-libre-7.1.6-gnu/drivers/gpu/drm/amd/amdgpu/amdgpu_ctx.c
@@ -326,7 +326,6 @@ static int amdgpu_ctx_init(struct amdgpu_ctx_mgr *mgr, int32_t priority,
 			   struct drm_file *filp, struct amdgpu_ctx *ctx)
 {
 	struct amdgpu_fpriv *fpriv = filp->driver_priv;
-	u32 current_stable_pstate;
 	int r;
 
 	r = amdgpu_ctx_priority_permit(filp, priority);
@@ -344,36 +343,21 @@ static int amdgpu_ctx_init(struct amdgpu_ctx_mgr *mgr, int32_t priority,
 	ctx->generation = amdgpu_vm_generation(mgr->adev, &fpriv->vm);
 	ctx->init_priority = priority;
 	ctx->override_priority = AMDGPU_CTX_PRIORITY_UNSET;
-
-	r = amdgpu_ctx_get_stable_pstate(ctx, &current_stable_pstate);
-	if (r)
-		return r;
-
-	if (mgr->adev->pm.stable_pstate_ctx)
-		ctx->stable_pstate = mgr->adev->pm.stable_pstate_ctx->stable_pstate;
-	else
-		ctx->stable_pstate = current_stable_pstate;
+	ctx->stable_pstate = AMDGPU_CTX_STABLE_PSTATE_NONE;
 
 	return 0;
 }
 
-static int amdgpu_ctx_set_stable_pstate(struct amdgpu_ctx *ctx,
-					u32 stable_pstate)
+static int __amdgpu_ctx_set_stable_pstate(struct amdgpu_ctx *ctx,
+					  u32 stable_pstate)
 {
 	struct amdgpu_device *adev = ctx->mgr->adev;
 	enum amd_dpm_forced_level level;
+	struct amdgpu_ctx *current_ctx;
 	u32 current_stable_pstate;
-	int r;
+	int r = 0;
 
-	mutex_lock(&adev->pm.stable_pstate_ctx_lock);
-	if (adev->pm.stable_pstate_ctx && adev->pm.stable_pstate_ctx != ctx) {
-		r = -EBUSY;
-		goto done;
-	}
-
-	r = amdgpu_ctx_get_stable_pstate(ctx, &current_stable_pstate);
-	if (r || (stable_pstate == current_stable_pstate))
-		goto done;
+	lockdep_assert_held(&adev->pm.stable_pstate_ctx_lock);
 
 	switch (stable_pstate) {
 	case AMDGPU_CTX_STABLE_PSTATE_NONE:
@@ -392,17 +376,41 @@ static int amdgpu_ctx_set_stable_pstate(struct amdgpu_ctx *ctx,
 		level = AMD_DPM_FORCED_LEVEL_PROFILE_PEAK;
 		break;
 	default:
-		r = -EINVAL;
-		goto done;
+		return -EINVAL;
 	}
 
+	current_ctx = adev->pm.stable_pstate_ctx;
+	if (current_ctx && current_ctx != ctx)
+		return -EBUSY;
+
+	r = amdgpu_ctx_get_stable_pstate(ctx, &current_stable_pstate);
+	if (r || current_stable_pstate == stable_pstate)
+		return r;
+
 	r = amdgpu_dpm_force_performance_level(adev, level);
+	if (r)
+		return r;
 
-	if (level == AMD_DPM_FORCED_LEVEL_AUTO)
-		adev->pm.stable_pstate_ctx = NULL;
-	else
+	if (!current_ctx) {
 		adev->pm.stable_pstate_ctx = ctx;
-done:
+		/*
+		 * Serialized by context taking ownership for the first time
+		 * while holding adev->pm.stable_pstate_ctx_lock).
+		 */
+		WRITE_ONCE(ctx->stable_pstate, current_stable_pstate);
+	}
+
+	return 0;
+}
+
+static int amdgpu_ctx_set_stable_pstate(struct amdgpu_ctx *ctx,
+					u32 stable_pstate)
+{
+	struct amdgpu_device *adev = ctx->mgr->adev;
+	int r;
+
+	mutex_lock(&adev->pm.stable_pstate_ctx_lock);
+	r = __amdgpu_ctx_set_stable_pstate(ctx, stable_pstate);
 	mutex_unlock(&adev->pm.stable_pstate_ctx_lock);
 
 	return r;
@@ -428,7 +436,12 @@ static void amdgpu_ctx_fini(struct kref *ref)
 	}
 
 	if (drm_dev_enter(adev_to_drm(adev), &idx)) {
-		amdgpu_ctx_set_stable_pstate(ctx, ctx->stable_pstate);
+		mutex_lock(&adev->pm.stable_pstate_ctx_lock);
+		if (adev->pm.stable_pstate_ctx == ctx) {
+			__amdgpu_ctx_set_stable_pstate(ctx, ctx->stable_pstate);
+			adev->pm.stable_pstate_ctx = NULL;
+		}
+		mutex_unlock(&adev->pm.stable_pstate_ctx_lock);
 		drm_dev_exit(idx);
 	}
 
diff --git linux-libre-7.1.5-gnu/drivers/gpu/drm/amd/amdgpu/amdgpu_dev_coredump.c linux-libre-7.1.6-gnu/drivers/gpu/drm/amd/amdgpu/amdgpu_dev_coredump.c
index f89f3a37a45b1..6b5384e5fd716 100644
--- linux-libre-7.1.5-gnu/drivers/gpu/drm/amd/amdgpu/amdgpu_dev_coredump.c
+++ linux-libre-7.1.6-gnu/drivers/gpu/drm/amd/amdgpu/amdgpu_dev_coredump.c
@@ -240,10 +240,14 @@ amdgpu_devcoredump_format(char *buffer, size_t count, struct amdgpu_coredump_inf
 	drm_printf(&p, "kernel: " UTS_RELEASE "\n");
 	drm_printf(&p, "module: " KBUILD_MODNAME "\n");
 	drm_printf(&p, "time: %ptSp\n", &coredump->reset_time);
+	drm_printf(&p, "pasid: %u\n", coredump->pasid);
+	drm_printf(&p, "vmid: %u\n", coredump->vmid);
 
 	if (coredump->reset_task_info.task.pid)
-		drm_printf(&p, "process_name: %s PID: %d\n",
+		drm_printf(&p, "process_name: %s TGID: %d thread: %s PID: %d\n",
 			   coredump->reset_task_info.process_name,
+			   coredump->reset_task_info.tgid,
+			   coredump->reset_task_info.task.comm,
 			   coredump->reset_task_info.task.pid);
 
 	/* SOC Information */
@@ -525,6 +529,7 @@ void amdgpu_coredump(struct amdgpu_device *adev, bool skip_vram_check,
 			amdgpu_vm_put_task_info(ti);
 		}
 		coredump->pasid = job->pasid;
+		coredump->vmid = job->vmid;
 		coredump->num_ibs = job->num_ibs;
 		for (i = 0; i < job->num_ibs; ++i) {
 			coredump->ibs[i].gpu_addr = job->ibs[i].gpu_addr;
diff --git linux-libre-7.1.5-gnu/drivers/gpu/drm/amd/amdgpu/amdgpu_dev_coredump.h linux-libre-7.1.6-gnu/drivers/gpu/drm/amd/amdgpu/amdgpu_dev_coredump.h
index 2371e20fc68bb..63f27337c09ad 100644
--- linux-libre-7.1.5-gnu/drivers/gpu/drm/amd/amdgpu/amdgpu_dev_coredump.h
+++ linux-libre-7.1.6-gnu/drivers/gpu/drm/amd/amdgpu/amdgpu_dev_coredump.h
@@ -63,6 +63,7 @@ struct amdgpu_coredump_info {
 	char				*formatted;
 
 	unsigned int			pasid;
+	unsigned int			vmid;
 	int				num_ibs;
 	struct amdgpu_coredump_ib_info	ibs[] __counted_by(num_ibs);
 };
diff --git linux-libre-7.1.5-gnu/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c linux-libre-7.1.6-gnu/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c
index 979a8ad0d72e4..4fed21108c314 100644
--- linux-libre-7.1.5-gnu/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c
+++ linux-libre-7.1.6-gnu/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c
@@ -1311,6 +1311,15 @@ static bool amdgpu_device_pcie_dynamic_switching_supported(struct amdgpu_device
 
 	if (c->x86_vendor == X86_VENDOR_INTEL)
 		return false;
+
+	/*
+	 * AMD Ryzen Pinnacle Ridge (Zen+, family 0x17 model 0x08) CPUs don't
+	 * support PCIe dynamic speed switching.
+	 * https://gitlab.freedesktop.org/drm/amd/-/work_items/5436
+	 */
+	if (c->x86_vendor == X86_VENDOR_AMD && c->x86 == 0x17 &&
+	    c->x86_model == 0x08)
+		return false;
 #endif
 	return true;
 }
@@ -1321,7 +1330,8 @@ static bool amdgpu_device_aspm_support_quirk(struct amdgpu_device *adev)
 	 * It's unclear if this is a platform-specific or GPU-specific issue.
 	 * Disable ASPM on SI for the time being.
 	 */
-	if (adev->family == AMDGPU_FAMILY_SI)
+	if (adev->family == AMDGPU_FAMILY_SI ||
+		(!(adev->pm.pp_feature & PP_PCIE_DPM_MASK) && adev->family == AMDGPU_FAMILY_VI))
 		return true;
 
 #if IS_ENABLED(CONFIG_X86)
@@ -4152,8 +4162,6 @@ static void amdgpu_device_unmap_mmio(struct amdgpu_device *adev)
 
 	iounmap(adev->rmmio);
 	adev->rmmio = NULL;
-	if (adev->mman.aper_base_kaddr)
-		iounmap(adev->mman.aper_base_kaddr);
 	adev->mman.aper_base_kaddr = NULL;
 
 	/* Memory manager related */
diff --git linux-libre-7.1.5-gnu/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c linux-libre-7.1.6-gnu/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c
index 1120f8225ac02..c08f019366758 100644
--- linux-libre-7.1.5-gnu/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c
+++ linux-libre-7.1.6-gnu/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c
@@ -535,6 +535,7 @@ int amdgpu_gem_userptr_ioctl(struct drm_device *dev, void *data,
 	bo = gem_to_amdgpu_bo(gobj);
 	bo->preferred_domains = AMDGPU_GEM_DOMAIN_GTT;
 	bo->allowed_domains = AMDGPU_GEM_DOMAIN_GTT;
+	bo->parent = amdgpu_bo_ref(fpriv->vm.root.bo);
 	r = amdgpu_ttm_tt_set_userptr(&bo->tbo, args->addr, args->flags);
 	if (r)
 		goto release_object;
@@ -1094,6 +1095,11 @@ int amdgpu_gem_op_ioctl(struct drm_device *dev, void *data,
 		 * If that number is larger than the size of the array, the ioctl must
 		 * be retried.
 		 */
+		if (!bo_va) {
+			r = -ENOENT;
+			goto out_exec;
+		}
+
 		if (args->num_entries > INT_MAX / sizeof(*vm_entries)) {
 			r = -EINVAL;
 			goto out_exec;
diff --git linux-libre-7.1.5-gnu/drivers/gpu/drm/amd/amdgpu/amdgpu_gfx.c linux-libre-7.1.6-gnu/drivers/gpu/drm/amd/amdgpu/amdgpu_gfx.c
index b8ca876694ff8..839bc93a941a0 100644
--- linux-libre-7.1.5-gnu/drivers/gpu/drm/amd/amdgpu/amdgpu_gfx.c
+++ linux-libre-7.1.6-gnu/drivers/gpu/drm/amd/amdgpu/amdgpu_gfx.c
@@ -1646,12 +1646,13 @@ static int amdgpu_gfx_run_cleaner_shader_job(struct amdgpu_ring *ring)
 	struct amdgpu_device *adev = ring->adev;
 	struct drm_gpu_scheduler *sched = &ring->sched;
 	struct drm_sched_entity entity;
+	unsigned int ib_size_dw = 16;
 	static atomic_t counter;
 	struct dma_fence *f;
 	struct amdgpu_job *job;
 	struct amdgpu_ib *ib;
 	void *owner;
-	int i, r;
+	int r;
 
 	/* Initialize the scheduler entity */
 	r = drm_sched_entity_init(&entity, DRM_SCHED_PRIORITY_NORMAL,
@@ -1669,7 +1670,7 @@ static int amdgpu_gfx_run_cleaner_shader_job(struct amdgpu_ring *ring)
 	owner = (void *)(unsigned long)atomic_inc_return(&counter);
 
 	r = amdgpu_job_alloc_with_ib(ring->adev, &entity, owner,
-				     64, 0, &job,
+				     ib_size_dw * sizeof(uint32_t), 0, &job,
 				     AMDGPU_KERNEL_JOB_ID_CLEANER_SHADER);
 	if (r)
 		goto err;
@@ -1679,9 +1680,8 @@ static int amdgpu_gfx_run_cleaner_shader_job(struct amdgpu_ring *ring)
 	job->run_cleaner_shader = true;
 
 	ib = &job->ibs[0];
-	for (i = 0; i <= ring->funcs->align_mask; ++i)
-		ib->ptr[i] = ring->funcs->nop;
-	ib->length_dw = ring->funcs->align_mask + 1;
+	memset32(ib->ptr, ring->funcs->nop, ib_size_dw);
+	ib->length_dw = ib_size_dw;
 
 	f = amdgpu_job_submit(job);
 
diff --git linux-libre-7.1.5-gnu/drivers/gpu/drm/amd/amdgpu/amdgpu_gtt_mgr.c linux-libre-7.1.6-gnu/drivers/gpu/drm/amd/amdgpu/amdgpu_gtt_mgr.c
index d23a91d029aa8..0ea32561c4bca 100644
--- linux-libre-7.1.5-gnu/drivers/gpu/drm/amd/amdgpu/amdgpu_gtt_mgr.c
+++ linux-libre-7.1.6-gnu/drivers/gpu/drm/amd/amdgpu/amdgpu_gtt_mgr.c
@@ -272,7 +272,20 @@ static bool amdgpu_gtt_mgr_intersects(struct ttm_resource_manager *man,
 				      const struct ttm_place *place,
 				      size_t size)
 {
-	return !place->lpfn || amdgpu_gtt_mgr_has_gart_addr(res);
+	const struct drm_mm_node *const node = &to_ttm_range_mgr_node(res)->mm_nodes[0];
+	const u32 num_pages = PFN_UP(size);
+
+	if (!place->lpfn)
+		return true;
+
+	if (!amdgpu_gtt_mgr_has_gart_addr(res))
+		return false;
+
+	if (place->fpfn >= (node->start + num_pages) ||
+	    (place->lpfn && place->lpfn <= node->start))
+		return false;
+
+	return true;
 }
 
 /**
@@ -290,7 +303,20 @@ static bool amdgpu_gtt_mgr_compatible(struct ttm_resource_manager *man,
 				      const struct ttm_place *place,
 				      size_t size)
 {
-	return !place->lpfn || amdgpu_gtt_mgr_has_gart_addr(res);
+	const struct drm_mm_node *const node = &to_ttm_range_mgr_node(res)->mm_nodes[0];
+	const u32 num_pages = PFN_UP(size);
+
+	if (!place->lpfn)
+		return true;
+
+	if (!amdgpu_gtt_mgr_has_gart_addr(res))
+		return false;
+
+	if (node->start < place->fpfn ||
+	    (place->lpfn && (node->start + num_pages) > place->lpfn))
+		return false;
+
+	return true;
 }
 
 /**
diff --git linux-libre-7.1.5-gnu/drivers/gpu/drm/amd/amdgpu/amdgpu_hmm.c linux-libre-7.1.6-gnu/drivers/gpu/drm/amd/amdgpu/amdgpu_hmm.c
index 99bc9ad67d5b8..a7d13e337d846 100644
--- linux-libre-7.1.5-gnu/drivers/gpu/drm/amd/amdgpu/amdgpu_hmm.c
+++ linux-libre-7.1.6-gnu/drivers/gpu/drm/amd/amdgpu/amdgpu_hmm.c
@@ -67,7 +67,6 @@ static bool amdgpu_hmm_invalidate_gfx(struct mmu_interval_notifier *mni,
 {
 	struct amdgpu_bo *bo = container_of(mni, struct amdgpu_bo, notifier);
 	struct amdgpu_device *adev = amdgpu_ttm_adev(bo->tbo.bdev);
-	struct amdgpu_bo *vm_root = bo->vm_bo->vm->root.bo;
 	long r;
 
 	if (!mmu_notifier_range_blockable(range))
@@ -78,7 +77,7 @@ static bool amdgpu_hmm_invalidate_gfx(struct mmu_interval_notifier *mni,
 	mmu_interval_set_seq(mni, cur_seq);
 
 	amdgpu_vm_bo_invalidate(bo, false);
-	r = dma_resv_wait_timeout(vm_root->tbo.base.resv,
+	r = dma_resv_wait_timeout(bo->parent->tbo.base.resv,
 				  DMA_RESV_USAGE_BOOKKEEP, false,
 				  MAX_SCHEDULE_TIMEOUT);
 	mutex_unlock(&adev->notifier_lock);
diff --git linux-libre-7.1.5-gnu/drivers/gpu/drm/amd/amdgpu/amdgpu_mes.h linux-libre-7.1.6-gnu/drivers/gpu/drm/amd/amdgpu/amdgpu_mes.h
index f80e3aca9c78e..ab6e4aa7a34ad 100644
--- linux-libre-7.1.5-gnu/drivers/gpu/drm/amd/amdgpu/amdgpu_mes.h
+++ linux-libre-7.1.6-gnu/drivers/gpu/drm/amd/amdgpu/amdgpu_mes.h
@@ -288,12 +288,14 @@ struct mes_suspend_gang_input {
 	uint64_t	gang_context_addr;
 	uint64_t	suspend_fence_addr;
 	uint32_t	suspend_fence_value;
+	uint32_t	doorbell_offset;
 };
 
 struct mes_resume_gang_input {
 	uint32_t	xcc_id;
 	bool		resume_all_gangs;
 	uint64_t	gang_context_addr;
+	uint32_t	doorbell_offset;
 };
 
 struct mes_reset_queue_input {
diff --git linux-libre-7.1.5-gnu/drivers/gpu/drm/amd/amdgpu/amdgpu_object.c linux-libre-7.1.6-gnu/drivers/gpu/drm/amd/amdgpu/amdgpu_object.c
index b6aabac39b46d..066ac0089e22d 100644
--- linux-libre-7.1.5-gnu/drivers/gpu/drm/amd/amdgpu/amdgpu_object.c
+++ linux-libre-7.1.6-gnu/drivers/gpu/drm/amd/amdgpu/amdgpu_object.c
@@ -276,10 +276,12 @@ int amdgpu_bo_create_reserved(struct amdgpu_device *adev,
 		goto error_free;
 	}
 
-	r = amdgpu_bo_pin(*bo_ptr, domain);
-	if (r) {
-		dev_err(adev->dev, "(%d) kernel bo pin failed\n", r);
-		goto error_unreserve;
+	if (free) {
+		r = amdgpu_bo_pin(*bo_ptr, domain);
+		if (r) {
+			dev_err(adev->dev, "(%d) kernel bo pin failed\n", r);
+			goto error_unreserve;
+		}
 	}
 
 	r = amdgpu_ttm_alloc_gart(&(*bo_ptr)->tbo);
@@ -302,7 +304,8 @@ int amdgpu_bo_create_reserved(struct amdgpu_device *adev,
 	return 0;
 
 error_unpin:
-	amdgpu_bo_unpin(*bo_ptr);
+	if (free)
+		amdgpu_bo_unpin(*bo_ptr);
 error_unreserve:
 	amdgpu_bo_unreserve(*bo_ptr);
 
diff --git linux-libre-7.1.5-gnu/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c linux-libre-7.1.6-gnu/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c
index 3d2e00efc7415..3eae6e620f8d2 100644
--- linux-libre-7.1.5-gnu/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c
+++ linux-libre-7.1.6-gnu/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c
@@ -515,6 +515,15 @@ static int amdgpu_bo_move(struct ttm_buffer_object *bo, bool evict,
 
 	if (new_mem->mem_type == TTM_PL_TT ||
 	    new_mem->mem_type == AMDGPU_PL_PREEMPT) {
+		if (old_mem && (old_mem->mem_type == TTM_PL_TT ||
+				old_mem->mem_type == AMDGPU_PL_PREEMPT)) {
+			r = ttm_bo_wait_ctx(bo, ctx);
+			if (r)
+				return r;
+
+			amdgpu_ttm_backend_unbind(bo->bdev, bo->ttm);
+		}
+
 		r = amdgpu_ttm_backend_bind(bo->bdev, bo->ttm, new_mem);
 		if (r)
 			return r;
@@ -549,6 +558,15 @@ static int amdgpu_bo_move(struct ttm_buffer_object *bo, bool evict,
 		ttm_bo_assign_mem(bo, new_mem);
 		return 0;
 	}
+	if ((old_mem->mem_type == TTM_PL_TT ||
+	     old_mem->mem_type == AMDGPU_PL_PREEMPT) &&
+	    (new_mem->mem_type == TTM_PL_TT ||
+	     new_mem->mem_type == AMDGPU_PL_PREEMPT)) {
+		amdgpu_bo_move_notify(bo, evict, new_mem);
+		ttm_resource_free(bo, &bo->resource);
+		ttm_bo_assign_mem(bo, new_mem);
+		return 0;
+	}
 
 	if (old_mem->mem_type == AMDGPU_PL_GDS ||
 	    old_mem->mem_type == AMDGPU_PL_GWS ||
@@ -2103,18 +2121,23 @@ int amdgpu_ttm_init(struct amdgpu_device *adev)
 	/* Change the size here instead of the init above so only lpfn is affected */
 	amdgpu_ttm_set_buffer_funcs_status(adev, false);
 #ifdef CONFIG_64BIT
-#ifdef CONFIG_X86
-	if (adev->gmc.xgmi.connected_to_cpu)
-		adev->mman.aper_base_kaddr = ioremap_cache(adev->gmc.aper_base,
-				adev->gmc.visible_vram_size);
-
-	else if (adev->gmc.is_app_apu)
+	if (adev->gmc.xgmi.connected_to_cpu) {
+		void *kaddr = devm_memremap(adev->dev, adev->gmc.aper_base,
+					    adev->gmc.visible_vram_size,
+					    MEMREMAP_WB);
+		if (IS_ERR(kaddr))
+			return PTR_ERR(kaddr);
+		adev->mman.aper_base_kaddr = (__force void __iomem *)kaddr;
+	} else if (adev->gmc.is_app_apu) {
 		DRM_DEBUG_DRIVER(
 			"No need to ioremap when real vram size is 0\n");
-	else
-#endif
-		adev->mman.aper_base_kaddr = ioremap_wc(adev->gmc.aper_base,
-				adev->gmc.visible_vram_size);
+	} else {
+		adev->mman.aper_base_kaddr = devm_ioremap_wc(adev->dev,
+							     adev->gmc.aper_base,
+							     adev->gmc.visible_vram_size);
+		if (!adev->mman.aper_base_kaddr)
+			return -ENOMEM;
+	}
 #endif
 
 	amdgpu_ttm_init_vram_resv_regions(adev);
@@ -2231,8 +2254,6 @@ int amdgpu_ttm_init(struct amdgpu_device *adev)
  */
 void amdgpu_ttm_fini(struct amdgpu_device *adev)
 {
-	int idx;
-
 	if (!adev->mman.initialized)
 		return;
 
@@ -2255,14 +2276,7 @@ void amdgpu_ttm_fini(struct amdgpu_device *adev)
 	amdgpu_ttm_unmark_vram_reserved(adev, AMDGPU_RESV_FW_VRAM_USAGE);
 	amdgpu_ttm_unmark_vram_reserved(adev, AMDGPU_RESV_DRV_VRAM_USAGE);
 
-	if (drm_dev_enter(adev_to_drm(adev), &idx)) {
-
-		if (adev->mman.aper_base_kaddr)
-			iounmap(adev->mman.aper_base_kaddr);
-		adev->mman.aper_base_kaddr = NULL;
-
-		drm_dev_exit(idx);
-	}
+	adev->mman.aper_base_kaddr = NULL;
 
 	if (!adev->gmc.is_app_apu)
 		amdgpu_vram_mgr_fini(adev);
diff --git linux-libre-7.1.5-gnu/drivers/gpu/drm/amd/amdgpu/amdgpu_userq.c linux-libre-7.1.6-gnu/drivers/gpu/drm/amd/amdgpu/amdgpu_userq.c
index 59ffaa7b61c2d..73421f8021fbf 100644
--- linux-libre-7.1.5-gnu/drivers/gpu/drm/amd/amdgpu/amdgpu_userq.c
+++ linux-libre-7.1.6-gnu/drivers/gpu/drm/amd/amdgpu/amdgpu_userq.c
@@ -523,6 +523,15 @@ amdgpu_userq_destroy(struct amdgpu_userq_mgr *uq_mgr, struct amdgpu_usermode_que
 	amdgpu_userq_cleanup(queue);
 	mutex_unlock(&uq_mgr->userq_mutex);
 
+	/*
+	 * A failed unmap means MES could not remove the hung queue and is now
+	 * unresponsive.  Recover the GPU here so the wedged MES does not fail
+	 * the next, unrelated queue submission and trigger a reset attributed
+	 * to an innocent workload.
+	 */
+	if (r)
+		queue_work(adev->reset_domain->wq, &uq_mgr->reset_work);
+
 	cancel_delayed_work_sync(&queue->hang_detect_work);
 	uq_funcs->mqd_destroy(queue);
 	queue->userq_mgr = NULL;
@@ -680,8 +689,8 @@ amdgpu_userq_create(struct drm_file *filp, union drm_amdgpu_userq *args)
 	/* Update VM owner at userq submit-time for page-fault attribution. */
 	amdgpu_vm_set_task_info(&fpriv->vm);
 
-	r = xa_err(xa_store_irq(&adev->userq_doorbell_xa, index, queue,
-				GFP_KERNEL));
+	r = xa_insert_irq(&adev->userq_doorbell_xa, index, queue,
+			  GFP_KERNEL);
 	if (r)
 		goto clean_mqd;
 
@@ -1367,16 +1376,19 @@ void amdgpu_userq_pre_reset(struct amdgpu_device *adev)
 
 	/* TODO: We probably need a new lock for the queue state */
 	xa_for_each(&adev->userq_doorbell_xa, queue_id, queue) {
-		if (queue->state != AMDGPU_USERQ_STATE_MAPPED)
-			continue;
-
-		userq_funcs = adev->userq_funcs[queue->queue_type];
-		userq_funcs->unmap(queue);
-		/* just mark all queues as hung at this point.
-		 * if unmap succeeds, we could map again
-		 * in amdgpu_userq_post_reset() if vram is not lost
+		if (queue->state == AMDGPU_USERQ_STATE_MAPPED) {
+			userq_funcs = adev->userq_funcs[queue->queue_type];
+			userq_funcs->unmap(queue);
+			/* just mark all queues as hung at this point.
+			 * if unmap succeeds, we could map again
+			 * in amdgpu_userq_post_reset() if vram is not lost
+			 */
+			queue->state = AMDGPU_USERQ_STATE_HUNG;
+		}
+		/* Force-complete any pending fence regardless of queue state so
+		 * that eviction/suspend and queue teardown waiters don't block
+		 * forever on a fence that will never signal after the reset.
 		 */
-		queue->state = AMDGPU_USERQ_STATE_HUNG;
 		amdgpu_userq_fence_driver_force_completion(queue);
 	}
 }
diff --git linux-libre-7.1.5-gnu/drivers/gpu/drm/amd/amdgpu/amdgpu_uvd.c linux-libre-7.1.6-gnu/drivers/gpu/drm/amd/amdgpu/amdgpu_uvd.c
index f6abbab6f9947..e507849608bf6 100644
--- linux-libre-7.1.5-gnu/drivers/gpu/drm/amd/amdgpu/amdgpu_uvd.c
+++ linux-libre-7.1.6-gnu/drivers/gpu/drm/amd/amdgpu/amdgpu_uvd.c
@@ -117,7 +117,7 @@ struct amdgpu_uvd_cs_ctx {
 /*(DEBLOBBED)*/
 
 static void amdgpu_uvd_idle_work_handler(struct work_struct *work);
-static void amdgpu_uvd_force_into_uvd_segment(struct amdgpu_bo *abo);
+static void amdgpu_uvd_force_into_vcpu_segment(struct amdgpu_bo *abo);
 
 static int amdgpu_uvd_create_msg_bo_helper(struct amdgpu_device *adev,
 					   uint32_t size,
@@ -140,7 +140,7 @@ static int amdgpu_uvd_create_msg_bo_helper(struct amdgpu_device *adev,
 	amdgpu_bo_kunmap(bo);
 	amdgpu_bo_unpin(bo);
 	amdgpu_bo_placement_from_domain(bo, AMDGPU_GEM_DOMAIN_VRAM);
-	amdgpu_uvd_force_into_uvd_segment(bo);
+	amdgpu_uvd_force_into_vcpu_segment(bo);
 	r = ttm_bo_validate(&bo->tbo, &bo->placement, &ctx);
 	if (r)
 		goto err;
@@ -170,6 +170,7 @@ int amdgpu_uvd_sw_init(struct amdgpu_device *adev)
 	const struct common_firmware_header *hdr;
 	unsigned int family_id;
 	int i, j, r;
+	u32 vcpu_bo_domain;
 
 	INIT_DELAYED_WORK(&adev->uvd.idle_work, amdgpu_uvd_idle_work_handler);
 
@@ -301,12 +302,20 @@ int amdgpu_uvd_sw_init(struct amdgpu_device *adev)
 	if (adev->firmware.load_type != AMDGPU_FW_LOAD_PSP)
 		bo_size += AMDGPU_GPU_PAGE_ALIGN(le32_to_cpu(hdr->ucode_size_bytes) + 8);
 
+	/* UVD 5.0 and newer HW can use 64 bit addressing. */
+	adev->uvd.address_64_bit =
+		!amdgpu_device_ip_block_version_cmp(adev, AMD_IP_BLOCK_TYPE_UVD, 5, 0);
+
+	vcpu_bo_domain = AMDGPU_GEM_DOMAIN_VRAM;
+	if (adev->uvd.address_64_bit)
+		vcpu_bo_domain |= AMDGPU_GEM_DOMAIN_GTT;
+
 	for (j = 0; j < adev->uvd.num_uvd_inst; j++) {
 		if (adev->uvd.harvest_config & (1 << j))
 			continue;
+
 		r = amdgpu_bo_create_kernel(adev, bo_size, PAGE_SIZE,
-					    AMDGPU_GEM_DOMAIN_VRAM |
-					    AMDGPU_GEM_DOMAIN_GTT,
+					    vcpu_bo_domain,
 					    &adev->uvd.inst[j].vcpu_bo,
 					    &adev->uvd.inst[j].gpu_addr,
 					    &adev->uvd.inst[j].cpu_addr);
@@ -321,10 +330,6 @@ int amdgpu_uvd_sw_init(struct amdgpu_device *adev)
 		adev->uvd.filp[i] = NULL;
 	}
 
-	/* from uvd v5.0 HW addressing capacity increased to 64 bits */
-	if (!amdgpu_device_ip_block_version_cmp(adev, AMD_IP_BLOCK_TYPE_UVD, 5, 0))
-		adev->uvd.address_64_bit = true;
-
 	r = amdgpu_uvd_create_msg_bo_helper(adev, 128 << 10, &adev->uvd.ib_bo);
 	if (r)
 		return r;
@@ -527,6 +532,24 @@ void amdgpu_uvd_free_handles(struct amdgpu_device *adev, struct drm_file *filp)
 	}
 }
 
+static void amdgpu_uvd_force_into_vcpu_segment(struct amdgpu_bo *bo)
+{
+	struct amdgpu_device *adev = amdgpu_ttm_adev(bo->tbo.bdev);
+	struct amdgpu_bo *vcpu_bo = adev->uvd.inst[0].vcpu_bo;
+	struct amdgpu_res_cursor vcpu_cur;
+
+	amdgpu_res_first(vcpu_bo->tbo.resource, 0,
+			 amdgpu_bo_size(vcpu_bo), &vcpu_cur);
+
+	bo->placement.num_placement = 1;
+	bo->placement.placement = &bo->placements[0];
+	bo->placements[0].fpfn = ALIGN_DOWN(vcpu_cur.start, SZ_256M) >> PAGE_SHIFT;
+	bo->placements[0].lpfn = bo->placements[0].fpfn + (SZ_256M >> PAGE_SHIFT);
+	bo->placements[0].mem_type = vcpu_bo->tbo.resource->mem_type;
+	if (bo->placements[0].mem_type == TTM_PL_VRAM)
+		bo->placements[0].flags |= TTM_PL_FLAG_CONTIGUOUS;
+}
+
 static void amdgpu_uvd_force_into_uvd_segment(struct amdgpu_bo *abo)
 {
 	int i;
@@ -577,13 +600,10 @@ static int amdgpu_uvd_cs_pass1(struct amdgpu_uvd_cs_ctx *ctx)
 	if (!ctx->parser->adev->uvd.address_64_bit) {
 		/* check if it's a message or feedback command */
 		cmd = amdgpu_ib_get_value(ctx->ib, ctx->idx) >> 1;
-		if (cmd == 0x0 || cmd == 0x3) {
-			/* yes, force it into VRAM */
-			uint32_t domain = AMDGPU_GEM_DOMAIN_VRAM;
-
-			amdgpu_bo_placement_from_domain(bo, domain);
-		}
-		amdgpu_uvd_force_into_uvd_segment(bo);
+		if (cmd == 0x0 || cmd == 0x3)
+			amdgpu_uvd_force_into_vcpu_segment(bo);
+		else
+			amdgpu_uvd_force_into_uvd_segment(bo);
 
 		r = ttm_bo_validate(&bo->tbo, &bo->placement, &tctx);
 	}
@@ -617,6 +637,14 @@ static int amdgpu_uvd_cs_msg_decode(struct amdgpu_device *adev, uint32_t *msg,
 	unsigned int image_size, tmp, min_dpb_size, num_dpb_buffer;
 	unsigned int min_ctx_size = ~0;
 
+	/* Reject invalid dimensions to prevent division by zero */
+	if (width < 16 || height < 16) {
+		dev_WARN_ONCE(adev->dev, 1,
+			      "Invalid UVD decoding dimensions (%dx%d)!\n",
+			      width, height);
+		return -EINVAL;
+	}
+
 	image_size = width * height;
 	image_size += image_size / 2;
 	image_size = ALIGN(image_size, 1024);
diff --git linux-libre-7.1.5-gnu/drivers/gpu/drm/amd/amdgpu/amdgpu_vce.c linux-libre-7.1.6-gnu/drivers/gpu/drm/amd/amdgpu/amdgpu_vce.c
index 7879342099a45..6a429f106066a 100644
--- linux-libre-7.1.5-gnu/drivers/gpu/drm/amd/amdgpu/amdgpu_vce.c
+++ linux-libre-7.1.6-gnu/drivers/gpu/drm/amd/amdgpu/amdgpu_vce.c
@@ -862,9 +862,20 @@ int amdgpu_vce_ring_parse_cs(struct amdgpu_cs_parser *p,
 				goto out;
 			}
 
-			*size = amdgpu_ib_get_value(ib, idx + 8) *
-				amdgpu_ib_get_value(ib, idx + 10) *
-				8 * 3 / 2;
+			uint32_t width, height;
+			width = amdgpu_ib_get_value(ib, idx + 8);
+			height = amdgpu_ib_get_value(ib, idx + 10);
+
+			if (width == 0 || height == 0 ||
+			    width > 4096 || height > 2304) {
+				DRM_ERROR("invalid VCE image size: %ux%u\n",
+					  width, height);
+				r = -EINVAL;
+				goto out;
+			}
+
+			*size = width * height * 8 * 3 / 2;
+
 			break;
 
 		case 0x04000001: /* config extension */
diff --git linux-libre-7.1.5-gnu/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c linux-libre-7.1.6-gnu/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c
index 381901bc539fd..7ed027b288894 100644
--- linux-libre-7.1.5-gnu/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c
+++ linux-libre-7.1.6-gnu/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c
@@ -865,12 +865,10 @@ void amdgpu_vm_flush(struct amdgpu_ring *ring, struct amdgpu_job *job,
 					    job->oa_size);
 	}
 
-	if (vm_flush_needed || pasid_mapping_needed || cleaner_shader_needed) {
-		amdgpu_fence_emit(ring, job->hw_vm_fence, 0);
-		fence = &job->hw_vm_fence->base;
-		/* get a ref for the job */
-		dma_fence_get(fence);
-	}
+	amdgpu_fence_emit(ring, job->hw_vm_fence, 0);
+	fence = &job->hw_vm_fence->base;
+	/* get a ref for the job */
+	dma_fence_get(fence);
 
 	if (vm_flush_needed) {
 		mutex_lock(&id_mgr->lock);
@@ -2487,19 +2485,6 @@ static void amdgpu_vm_destroy_task_info(struct kref *kref)
 	kfree(ti);
 }
 
-static inline struct amdgpu_vm *
-amdgpu_vm_get_vm_from_pasid(struct amdgpu_device *adev, u32 pasid)
-{
-	struct amdgpu_vm *vm;
-	unsigned long flags;
-
-	xa_lock_irqsave(&adev->vm_manager.pasids, flags);
-	vm = xa_load(&adev->vm_manager.pasids, pasid);
-	xa_unlock_irqrestore(&adev->vm_manager.pasids, flags);
-
-	return vm;
-}
-
 /**
  * amdgpu_vm_put_task_info - reference down the vm task_info ptr
  *
@@ -2546,8 +2531,16 @@ amdgpu_vm_get_task_info_vm(struct amdgpu_vm *vm)
 struct amdgpu_task_info *
 amdgpu_vm_get_task_info_pasid(struct amdgpu_device *adev, u32 pasid)
 {
-	return amdgpu_vm_get_task_info_vm(
-			amdgpu_vm_get_vm_from_pasid(adev, pasid));
+	struct amdgpu_task_info *ti;
+	struct amdgpu_vm *vm;
+	unsigned long flags;
+
+	xa_lock_irqsave(&adev->vm_manager.pasids, flags);
+	vm = xa_load(&adev->vm_manager.pasids, pasid);
+	ti = amdgpu_vm_get_task_info_vm(vm);
+	xa_unlock_irqrestore(&adev->vm_manager.pasids, flags);
+
+	return ti;
 }
 
 static int amdgpu_vm_create_task_info(struct amdgpu_vm *vm)
diff --git linux-libre-7.1.5-gnu/drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c linux-libre-7.1.6-gnu/drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c
index 534b9e60ac6cd..95c82da96d4e7 100644
--- linux-libre-7.1.5-gnu/drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c
+++ linux-libre-7.1.6-gnu/drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c
@@ -3935,7 +3935,7 @@ static void gfx_v10_0_wait_reg_mem(struct amdgpu_ring *ring, int eng_sel,
 			   WAIT_REG_MEM_ENGINE(eng_sel)));
 
 	if (mem_space)
-		BUG_ON(addr0 & 0x3); /* Dword align */
+		WARN_ON(addr0 & 0x3); /* Dword align */
 	amdgpu_ring_write(ring, addr0);
 	amdgpu_ring_write(ring, addr1);
 	amdgpu_ring_write(ring, ref);
@@ -5263,6 +5263,15 @@ static void gfx_v10_0_constants_init(struct amdgpu_device *adev)
 	gfx_v10_0_get_tcc_info(adev);
 	adev->gfx.config.pa_sc_tile_steering_override =
 		gfx_v10_0_init_pa_sc_tile_steering_override(adev);
+	/* Program DB_RING_CONTROL for multiple GFX pipes
+	 * Default power up value is 1.
+	 * Possible values:
+	 * 0 - split occlusion counters between gfx pipes
+	 * 1 - all occlusion counters to pipe 0
+	 * 2 - all occlusion counters to pipe 1
+	 */
+	WREG32_FIELD15(GC, 0, DB_RING_CONTROL, COUNTER_CONTROL,
+		       (adev->gfx.me.num_pipe_per_me > 1) ? 0 : 1);
 
 	/* XXX SH_MEM regs */
 	/* where to put LDS, scratch, GPUVM in FSA64 space */
@@ -8568,7 +8577,7 @@ static void gfx_v10_0_ring_emit_ib_gfx(struct amdgpu_ring *ring,
 	}
 
 	amdgpu_ring_write(ring, header);
-	BUG_ON(ib->gpu_addr & 0x3); /* Dword align */
+	WARN_ON(ib->gpu_addr & 0x3); /* Dword align */
 	amdgpu_ring_write(ring,
 #ifdef __BIG_ENDIAN
 		(2 << 0) |
@@ -8603,7 +8612,7 @@ static void gfx_v10_0_ring_emit_ib_compute(struct amdgpu_ring *ring,
 	}
 
 	amdgpu_ring_write(ring, PACKET3(PACKET3_INDIRECT_BUFFER, 2));
-	BUG_ON(ib->gpu_addr & 0x3); /* Dword align */
+	WARN_ON(ib->gpu_addr & 0x3); /* Dword align */
 	amdgpu_ring_write(ring,
 #ifdef __BIG_ENDIAN
 				(2 << 0) |
@@ -8636,9 +8645,9 @@ static void gfx_v10_0_ring_emit_fence(struct amdgpu_ring *ring, u64 addr,
 	 * aligned if only send 32bit data low (discard data high)
 	 */
 	if (write64bit)
-		BUG_ON(addr & 0x7);
+		WARN_ON(addr & 0x7);
 	else
-		BUG_ON(addr & 0x3);
+		WARN_ON(addr & 0x3);
 	amdgpu_ring_write(ring, lower_32_bits(addr));
 	amdgpu_ring_write(ring, upper_32_bits(addr));
 	amdgpu_ring_write(ring, lower_32_bits(seq));
@@ -8686,9 +8695,6 @@ static void gfx_v10_0_ring_emit_fence_kiq(struct amdgpu_ring *ring, u64 addr,
 {
 	struct amdgpu_device *adev = ring->adev;
 
-	/* we only allocate 32bit for each seq wb address */
-	BUG_ON(flags & AMDGPU_FENCE_FLAG_64BIT);
-
 	/* write fence seq to the "addr" */
 	amdgpu_ring_write(ring, PACKET3(PACKET3_WRITE_DATA, 3));
 	amdgpu_ring_write(ring, (WRITE_DATA_ENGINE_SEL(0) |
diff --git linux-libre-7.1.5-gnu/drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c linux-libre-7.1.6-gnu/drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c
index 29c93cef208dd..d30e606d4bb34 100644
--- linux-libre-7.1.5-gnu/drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c
+++ linux-libre-7.1.6-gnu/drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c
@@ -500,7 +500,7 @@ static void gfx_v11_0_wait_reg_mem(struct amdgpu_ring *ring, int eng_sel,
 			   WAIT_REG_MEM_ENGINE(eng_sel)));
 
 	if (mem_space)
-		BUG_ON(addr0 & 0x3); /* Dword align */
+		WARN_ON(addr0 & 0x3); /* Dword align */
 	amdgpu_ring_write(ring, addr0);
 	amdgpu_ring_write(ring, addr1);
 	amdgpu_ring_write(ring, ref);
@@ -5911,7 +5911,7 @@ static void gfx_v11_0_ring_emit_ib_gfx(struct amdgpu_ring *ring,
 	}
 
 	amdgpu_ring_write(ring, header);
-	BUG_ON(ib->gpu_addr & 0x3); /* Dword align */
+	WARN_ON(ib->gpu_addr & 0x3); /* Dword align */
 	amdgpu_ring_write(ring,
 #ifdef __BIG_ENDIAN
 		(2 << 0) |
@@ -5946,7 +5946,7 @@ static void gfx_v11_0_ring_emit_ib_compute(struct amdgpu_ring *ring,
 	}
 
 	amdgpu_ring_write(ring, PACKET3(PACKET3_INDIRECT_BUFFER, 2));
-	BUG_ON(ib->gpu_addr & 0x3); /* Dword align */
+	WARN_ON(ib->gpu_addr & 0x3); /* Dword align */
 	amdgpu_ring_write(ring,
 #ifdef __BIG_ENDIAN
 				(2 << 0) |
@@ -5979,9 +5979,9 @@ static void gfx_v11_0_ring_emit_fence(struct amdgpu_ring *ring, u64 addr,
 	 * aligned if only send 32bit data low (discard data high)
 	 */
 	if (write64bit)
-		BUG_ON(addr & 0x7);
+		WARN_ON(addr & 0x7);
 	else
-		BUG_ON(addr & 0x3);
+		WARN_ON(addr & 0x3);
 	amdgpu_ring_write(ring, lower_32_bits(addr));
 	amdgpu_ring_write(ring, upper_32_bits(addr));
 	amdgpu_ring_write(ring, lower_32_bits(seq));
@@ -6035,9 +6035,6 @@ static void gfx_v11_0_ring_emit_fence_kiq(struct amdgpu_ring *ring, u64 addr,
 {
 	struct amdgpu_device *adev = ring->adev;
 
-	/* we only allocate 32bit for each seq wb address */
-	BUG_ON(flags & AMDGPU_FENCE_FLAG_64BIT);
-
 	/* write fence seq to the "addr" */
 	amdgpu_ring_write(ring, PACKET3(PACKET3_WRITE_DATA, 3));
 	amdgpu_ring_write(ring, (WRITE_DATA_ENGINE_SEL(0) |
@@ -6474,25 +6471,33 @@ static int gfx_v11_0_eop_irq(struct amdgpu_device *adev,
 			     struct amdgpu_iv_entry *entry)
 {
 	u32 doorbell_offset = entry->src_data[0];
-	u8 me_id, pipe_id, queue_id;
-	struct amdgpu_ring *ring;
-	int i;
 
 	DRM_DEBUG("IH: CP EOP\n");
 
-	if (adev->enable_mes && doorbell_offset) {
-		amdgpu_userq_process_fence_irq(adev, doorbell_offset);
-	} else {
-		me_id = (entry->ring_id & 0x0c) >> 2;
-		pipe_id = (entry->ring_id & 0x03) >> 0;
-		queue_id = (entry->ring_id & 0x70) >> 4;
+	if (!adev->gfx.disable_kq) {
+		u8 me_id = (entry->ring_id & 0x0c) >> 2;
+		u8 pipe_id = (entry->ring_id & 0x03) >> 0;
+		u8 queue_id = (entry->ring_id & 0x70) >> 4;
+		struct amdgpu_ring *ring;
+		int i;
 
 		switch (me_id) {
 		case 0:
-			if (pipe_id == 0)
-				amdgpu_fence_process(&adev->gfx.gfx_ring[0]);
-			else
-				amdgpu_fence_process(&adev->gfx.gfx_ring[1]);
+			/*
+			 * MES splits gfx HQDs per (me,pipe): KGQ owns queue=0,
+			 * userq gfx owns queue>=1 (see amdgpu_mes_get_hqd_mask).
+			 * Require a strict (me,pipe,queue) match so userq gfx
+			 * EOPs fall through to amdgpu_userq_process_fence_irq().
+			 */
+			for (i = 0; i < adev->gfx.num_gfx_rings; i++) {
+				ring = &adev->gfx.gfx_ring[i];
+				if ((ring->me == me_id) &&
+				    (ring->pipe == pipe_id) &&
+				    (ring->queue == queue_id)) {
+					amdgpu_fence_process(ring);
+					return 0;
+				}
+			}
 			break;
 		case 1:
 		case 2:
@@ -6504,13 +6509,20 @@ static int gfx_v11_0_eop_irq(struct amdgpu_device *adev,
 				 */
 				if ((ring->me == me_id) &&
 				    (ring->pipe == pipe_id) &&
-				    (ring->queue == queue_id))
+				    (ring->queue == queue_id)) {
 					amdgpu_fence_process(ring);
+					return 0;
+				}
 			}
 			break;
+		default:
+			break;
 		}
 	}
 
+	if (adev->enable_mes && doorbell_offset)
+		amdgpu_userq_process_fence_irq(adev, doorbell_offset);
+
 	return 0;
 }
 
diff --git linux-libre-7.1.5-gnu/drivers/gpu/drm/amd/amdgpu/gfx_v12_0.c linux-libre-7.1.6-gnu/drivers/gpu/drm/amd/amdgpu/gfx_v12_0.c
index fe88fb49fc261..e742bf91e00bc 100644
--- linux-libre-7.1.5-gnu/drivers/gpu/drm/amd/amdgpu/gfx_v12_0.c
+++ linux-libre-7.1.6-gnu/drivers/gpu/drm/amd/amdgpu/gfx_v12_0.c
@@ -430,7 +430,7 @@ static void gfx_v12_0_wait_reg_mem(struct amdgpu_ring *ring, int eng_sel,
 			   WAIT_REG_MEM_ENGINE(eng_sel)));
 
 	if (mem_space)
-		BUG_ON(addr0 & 0x3); /* Dword align */
+		WARN_ON(addr0 & 0x3); /* Dword align */
 	amdgpu_ring_write(ring, addr0);
 	amdgpu_ring_write(ring, addr1);
 	amdgpu_ring_write(ring, ref);
@@ -3504,10 +3504,19 @@ static int gfx_v12_0_cp_resume(struct amdgpu_device *adev)
 		gfx_v12_0_cp_gfx_enable(adev, true);
 	}
 
-	if (adev->enable_mes_kiq && adev->mes.kiq_hw_init)
+	if (adev->enable_mes_kiq && adev->mes.kiq_hw_init) {
 		r = amdgpu_mes_kiq_hw_init(adev, 0);
-	else
+		/*
+		 * With MES, GFX KIQ ring is owned by the MES and is never
+		 * initialized/used directly by the driver, so it must
+		 * not be left flagged as ready. mes_v12_0_hw_init() clears
+		 * but clear here if MES init fails
+		*/
+		if (r)
+			adev->gfx.kiq[0].ring.sched.ready = false;
+	} else {
 		r = gfx_v12_0_kiq_resume(adev);
+	}
 	if (r)
 		return r;
 
@@ -4449,7 +4458,7 @@ static void gfx_v12_0_ring_emit_ib_gfx(struct amdgpu_ring *ring,
 	control |= ib->length_dw | (vmid << 24);
 
 	amdgpu_ring_write(ring, header);
-	BUG_ON(ib->gpu_addr & 0x3); /* Dword align */
+	WARN_ON(ib->gpu_addr & 0x3); /* Dword align */
 	amdgpu_ring_write(ring,
 #ifdef __BIG_ENDIAN
 		(2 << 0) |
@@ -4468,7 +4477,7 @@ static void gfx_v12_0_ring_emit_ib_compute(struct amdgpu_ring *ring,
 	u32 control = INDIRECT_BUFFER_VALID | ib->length_dw | (vmid << 24);
 
 	amdgpu_ring_write(ring, PACKET3(PACKET3_INDIRECT_BUFFER, 2));
-	BUG_ON(ib->gpu_addr & 0x3); /* Dword align */
+	WARN_ON(ib->gpu_addr & 0x3); /* Dword align */
 	amdgpu_ring_write(ring,
 #ifdef __BIG_ENDIAN
 				(2 << 0) |
@@ -4499,9 +4508,9 @@ static void gfx_v12_0_ring_emit_fence(struct amdgpu_ring *ring, u64 addr,
 	 * aligned if only send 32bit data low (discard data high)
 	 */
 	if (write64bit)
-		BUG_ON(addr & 0x7);
+		WARN_ON(addr & 0x7);
 	else
-		BUG_ON(addr & 0x3);
+		WARN_ON(addr & 0x3);
 	amdgpu_ring_write(ring, lower_32_bits(addr));
 	amdgpu_ring_write(ring, upper_32_bits(addr));
 	amdgpu_ring_write(ring, lower_32_bits(seq));
@@ -4549,9 +4558,6 @@ static void gfx_v12_0_ring_emit_fence_kiq(struct amdgpu_ring *ring, u64 addr,
 {
 	struct amdgpu_device *adev = ring->adev;
 
-	/* we only allocate 32bit for each seq wb address */
-	BUG_ON(flags & AMDGPU_FENCE_FLAG_64BIT);
-
 	/* write fence seq to the "addr" */
 	amdgpu_ring_write(ring, PACKET3(PACKET3_WRITE_DATA, 3));
 	amdgpu_ring_write(ring, (WRITE_DATA_ENGINE_SEL(0) |
@@ -4844,25 +4850,33 @@ static int gfx_v12_0_eop_irq(struct amdgpu_device *adev,
 			     struct amdgpu_iv_entry *entry)
 {
 	u32 doorbell_offset = entry->src_data[0];
-	u8 me_id, pipe_id, queue_id;
-	struct amdgpu_ring *ring;
-	int i;
 
 	DRM_DEBUG("IH: CP EOP\n");
 
-	if (adev->enable_mes && doorbell_offset) {
-		amdgpu_userq_process_fence_irq(adev, doorbell_offset);
-	} else {
-		me_id = (entry->ring_id & 0x0c) >> 2;
-		pipe_id = (entry->ring_id & 0x03) >> 0;
-		queue_id = (entry->ring_id & 0x70) >> 4;
+	if (!adev->gfx.disable_kq) {
+		u8 me_id = (entry->ring_id & 0x0c) >> 2;
+		u8 pipe_id = (entry->ring_id & 0x03) >> 0;
+		u8 queue_id = (entry->ring_id & 0x70) >> 4;
+		struct amdgpu_ring *ring;
+		int i;
 
 		switch (me_id) {
 		case 0:
-			if (pipe_id == 0)
-				amdgpu_fence_process(&adev->gfx.gfx_ring[0]);
-			else
-				amdgpu_fence_process(&adev->gfx.gfx_ring[1]);
+			/*
+			 * MES splits gfx HQDs per (me,pipe): KGQ owns queue=0,
+			 * userq gfx owns queue>=1 (see amdgpu_mes_get_hqd_mask).
+			 * Require a strict (me,pipe,queue) match so userq gfx
+			 * EOPs fall through to amdgpu_userq_process_fence_irq().
+			 */
+			for (i = 0; i < adev->gfx.num_gfx_rings; i++) {
+				ring = &adev->gfx.gfx_ring[i];
+				if ((ring->me == me_id) &&
+				    (ring->pipe == pipe_id) &&
+				    (ring->queue == queue_id)) {
+					amdgpu_fence_process(ring);
+					return 0;
+				}
+			}
 			break;
 		case 1:
 		case 2:
@@ -4874,13 +4888,20 @@ static int gfx_v12_0_eop_irq(struct amdgpu_device *adev,
 				 */
 				if ((ring->me == me_id) &&
 				    (ring->pipe == pipe_id) &&
-				    (ring->queue == queue_id))
+				    (ring->queue == queue_id)) {
 					amdgpu_fence_process(ring);
+					return 0;
+				}
 			}
 			break;
+		default:
+			break;
 		}
 	}
 
+	if (adev->enable_mes && doorbell_offset)
+		amdgpu_userq_process_fence_irq(adev, doorbell_offset);
+
 	return 0;
 }
 
diff --git linux-libre-7.1.5-gnu/drivers/gpu/drm/amd/amdgpu/gfx_v12_1.c linux-libre-7.1.6-gnu/drivers/gpu/drm/amd/amdgpu/gfx_v12_1.c
index 8a6dc56e80be6..2f053d479d70e 100644
--- linux-libre-7.1.5-gnu/drivers/gpu/drm/amd/amdgpu/gfx_v12_1.c
+++ linux-libre-7.1.6-gnu/drivers/gpu/drm/amd/amdgpu/gfx_v12_1.c
@@ -247,7 +247,7 @@ static void gfx_v12_1_wait_reg_mem(struct amdgpu_ring *ring, int eng_sel,
 			   WAIT_REG_MEM_FUNCTION(3)));  /* equal */
 
 	if (mem_space)
-		BUG_ON(addr0 & 0x3); /* Dword align */
+		WARN_ON(addr0 & 0x3); /* Dword align */
 	amdgpu_ring_write(ring, addr0);
 	amdgpu_ring_write(ring, addr1);
 	amdgpu_ring_write(ring, ref);
@@ -2501,10 +2501,19 @@ static int gfx_v12_1_xcc_cp_resume(struct amdgpu_device *adev, uint16_t xcc_mask
 
 		gfx_v12_1_xcc_cp_compute_enable(adev, true, xcc_id);
 
-		if (adev->enable_mes_kiq && adev->mes.kiq_hw_init)
+		if (adev->enable_mes_kiq && adev->mes.kiq_hw_init) {
 			r = amdgpu_mes_kiq_hw_init(adev, xcc_id);
-		else
+			/*
+			 * With MES, GFX KIQ ring is owned by the MES and is never
+			 * initialized/used directly by the driver, so it must
+			 * not be left flagged as ready. mes_v12_0_hw_init() clears
+			 * but clear here if MES init fails
+			 */
+			if (r)
+				adev->gfx.kiq[xcc_id].ring.sched.ready = false;
+		} else {
 			r = gfx_v12_1_xcc_kiq_resume(adev, xcc_id);
+		}
 		if (r)
 			return r;
 
@@ -3372,7 +3381,7 @@ static void gfx_v12_1_ring_emit_ib_compute(struct amdgpu_ring *ring,
 	}
 
 	amdgpu_ring_write(ring, PACKET3(PACKET3_INDIRECT_BUFFER, 2));
-	BUG_ON(ib->gpu_addr & 0x3); /* Dword align */
+	WARN_ON(ib->gpu_addr & 0x3); /* Dword align */
 	amdgpu_ring_write(ring,
 #ifdef __BIG_ENDIAN
 				(2 << 0) |
@@ -3405,9 +3414,9 @@ static void gfx_v12_1_ring_emit_fence(struct amdgpu_ring *ring, u64 addr,
 	 * aligned if only send 32bit data low (discard data high)
 	 */
 	if (write64bit)
-		BUG_ON(addr & 0x7);
+		WARN_ON(addr & 0x7);
 	else
-		BUG_ON(addr & 0x3);
+		WARN_ON(addr & 0x3);
 	amdgpu_ring_write(ring, lower_32_bits(addr));
 	amdgpu_ring_write(ring, upper_32_bits(addr));
 	amdgpu_ring_write(ring, lower_32_bits(seq));
@@ -3454,9 +3463,6 @@ static void gfx_v12_1_ring_emit_fence_kiq(struct amdgpu_ring *ring, u64 addr,
 {
 	struct amdgpu_device *adev = ring->adev;
 
-	/* we only allocate 32bit for each seq wb address */
-	BUG_ON(flags & AMDGPU_FENCE_FLAG_64BIT);
-
 	/* write fence seq to the "addr" */
 	amdgpu_ring_write(ring, PACKET3(PACKET3_WRITE_DATA, 3));
 	amdgpu_ring_write(ring, (WRITE_DATA_DST_SEL(5) | WR_CONFIRM));
diff --git linux-libre-7.1.5-gnu/drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c linux-libre-7.1.6-gnu/drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c
index 89fbfe330d30b..04ecb1ab55f36 100644
--- linux-libre-7.1.5-gnu/drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c
+++ linux-libre-7.1.6-gnu/drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c
@@ -6178,9 +6178,6 @@ static void gfx_v8_0_ring_emit_fence_compute(struct amdgpu_ring *ring,
 static void gfx_v8_0_ring_emit_fence_kiq(struct amdgpu_ring *ring, u64 addr,
 					 u64 seq, unsigned int flags)
 {
-	/* we only allocate 32bit for each seq wb address */
-	BUG_ON(flags & AMDGPU_FENCE_FLAG_64BIT);
-
 	/* write fence seq to the "addr" */
 	amdgpu_ring_write(ring, PACKET3(PACKET3_WRITE_DATA, 3));
 	amdgpu_ring_write(ring, (WRITE_DATA_ENGINE_SEL(0) |
diff --git linux-libre-7.1.5-gnu/drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c linux-libre-7.1.6-gnu/drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c
index 2bc40dc2525b6..266b1fc9660d5 100644
--- linux-libre-7.1.5-gnu/drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c
+++ linux-libre-7.1.6-gnu/drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c
@@ -1119,7 +1119,7 @@ static void gfx_v9_0_wait_reg_mem(struct amdgpu_ring *ring, int eng_sel,
 				 WAIT_REG_MEM_ENGINE(eng_sel)));
 
 	if (mem_space)
-		BUG_ON(addr0 & 0x3); /* Dword align */
+		WARN_ON(addr0 & 0x3); /* Dword align */
 	amdgpu_ring_write(ring, addr0);
 	amdgpu_ring_write(ring, addr1);
 	amdgpu_ring_write(ring, ref);
@@ -3978,6 +3978,41 @@ static int gfx_v9_0_hw_init(struct amdgpu_ip_block *ip_block)
 	return r;
 }
 
+static void gfx_v9_0_deactivate_kcq_hqd(struct amdgpu_device *adev)
+{
+	amdgpu_gfx_rlc_enter_safe_mode(adev, 0);
+	for (int i = 0; i < adev->gfx.num_compute_rings; i++) {
+		u32 tmp;
+		struct amdgpu_ring *ring = &adev->gfx.compute_ring[i];
+
+		mutex_lock(&adev->srbm_mutex);
+		soc15_grbm_select(adev, ring->me, ring->pipe, ring->queue, 0, 0);
+		tmp = RREG32_SOC15(GC, 0, mmCP_HQD_ACTIVE);
+		/* disable the queue if it's active */
+		if (tmp & CP_HQD_ACTIVE__ACTIVE_MASK) {
+			int j;
+
+			WREG32_SOC15(GC, 0, mmCP_HQD_DEQUEUE_REQUEST, 1);
+			for (j = 0; j < adev->usec_timeout; j++) {
+				tmp = RREG32_SOC15(GC, 0, mmCP_HQD_ACTIVE);
+				if (!(tmp & CP_HQD_ACTIVE__ACTIVE_MASK))
+					break;
+				udelay(1);
+			}
+			if (j == AMDGPU_MAX_USEC_TIMEOUT) {
+				DRM_DEBUG("comp_%u_%u_%u dequeue request failed.\n",
+							ring->me, ring->pipe, ring->queue);
+				/* Manual disable if dequeue request times out */
+				WREG32_SOC15(GC, 0, mmCP_HQD_ACTIVE, 0);
+			}
+			WREG32_SOC15(GC, 0, mmCP_HQD_DEQUEUE_REQUEST, 0);
+		}
+		soc15_grbm_select(adev, 0, 0, 0, 0, 0);
+		mutex_unlock(&adev->srbm_mutex);
+	}
+	amdgpu_gfx_rlc_exit_safe_mode(adev, 0);
+}
+
 static int gfx_v9_0_hw_fini(struct amdgpu_ip_block *ip_block)
 {
 	struct amdgpu_device *adev = ip_block->adev;
@@ -4004,6 +4039,10 @@ static int gfx_v9_0_hw_fini(struct amdgpu_ip_block *ip_block)
 		return 0;
 	}
 
+	if ((adev->flags & AMD_IS_APU) && amdgpu_in_reset(adev) &&
+		amdgpu_asic_reset_method(adev) == AMD_RESET_METHOD_MODE2)
+		gfx_v9_0_deactivate_kcq_hqd(adev);
+
 	/* Use deinitialize sequence from CAIL when unbinding device from driver,
 	 * otherwise KIQ is hanging when binding back
 	 */
@@ -5356,7 +5395,7 @@ static void gfx_v9_0_ring_emit_ib_gfx(struct amdgpu_ring *ring,
 	}
 
 	amdgpu_ring_write(ring, header);
-	BUG_ON(ib->gpu_addr & 0x3); /* Dword align */
+	WARN_ON(ib->gpu_addr & 0x3); /* Dword align */
 	amdgpu_ring_write(ring,
 #ifdef __BIG_ENDIAN
 		(2 << 0) |
@@ -5452,7 +5491,7 @@ static void gfx_v9_0_ring_emit_ib_compute(struct amdgpu_ring *ring,
 	}
 
 	amdgpu_ring_write(ring, PACKET3(PACKET3_INDIRECT_BUFFER, 2));
-	BUG_ON(ib->gpu_addr & 0x3); /* Dword align */
+	WARN_ON(ib->gpu_addr & 0x3); /* Dword align */
 	amdgpu_ring_write(ring,
 #ifdef __BIG_ENDIAN
 				(2 << 0) |
@@ -5493,9 +5532,9 @@ static void gfx_v9_0_ring_emit_fence(struct amdgpu_ring *ring, u64 addr,
 	 * aligned if only send 32bit data low (discard data high)
 	 */
 	if (write64bit)
-		BUG_ON(addr & 0x7);
+		WARN_ON(addr & 0x7);
 	else
-		BUG_ON(addr & 0x3);
+		WARN_ON(addr & 0x3);
 	amdgpu_ring_write(ring, lower_32_bits(addr));
 	amdgpu_ring_write(ring, upper_32_bits(addr));
 	amdgpu_ring_write(ring, lower_32_bits(seq));
diff --git linux-libre-7.1.5-gnu/drivers/gpu/drm/amd/amdgpu/gfx_v9_4_3.c linux-libre-7.1.6-gnu/drivers/gpu/drm/amd/amdgpu/gfx_v9_4_3.c
index 8343b36f20d3e..87c3bfe0a88ae 100644
--- linux-libre-7.1.5-gnu/drivers/gpu/drm/amd/amdgpu/gfx_v9_4_3.c
+++ linux-libre-7.1.6-gnu/drivers/gpu/drm/amd/amdgpu/gfx_v9_4_3.c
@@ -398,7 +398,7 @@ static void gfx_v9_4_3_wait_reg_mem(struct amdgpu_ring *ring, int eng_sel,
 				 WAIT_REG_MEM_ENGINE(eng_sel)));
 
 	if (mem_space)
-		BUG_ON(addr0 & 0x3); /* Dword align */
+		WARN_ON(addr0 & 0x3); /* Dword align */
 	amdgpu_ring_write(ring, addr0);
 	amdgpu_ring_write(ring, addr1);
 	amdgpu_ring_write(ring, ref);
@@ -2850,7 +2850,7 @@ static void gfx_v9_4_3_ring_emit_ib_compute(struct amdgpu_ring *ring,
 	}
 
 	amdgpu_ring_write(ring, PACKET3(PACKET3_INDIRECT_BUFFER, 2));
-	BUG_ON(ib->gpu_addr & 0x3); /* Dword align */
+	WARN_ON(ib->gpu_addr & 0x3); /* Dword align */
 	amdgpu_ring_write(ring,
 #ifdef __BIG_ENDIAN
 				(2 << 0) |
@@ -2884,9 +2884,9 @@ static void gfx_v9_4_3_ring_emit_fence(struct amdgpu_ring *ring, u64 addr,
 	 * aligned if only send 32bit data low (discard data high)
 	 */
 	if (write64bit)
-		BUG_ON(addr & 0x7);
+		WARN_ON(addr & 0x7);
 	else
-		BUG_ON(addr & 0x3);
+		WARN_ON(addr & 0x3);
 	amdgpu_ring_write(ring, lower_32_bits(addr));
 	amdgpu_ring_write(ring, upper_32_bits(addr));
 	amdgpu_ring_write(ring, lower_32_bits(seq));
@@ -2946,9 +2946,6 @@ static void gfx_v9_4_3_ring_emit_fence_kiq(struct amdgpu_ring *ring, u64 addr,
 {
 	struct amdgpu_device *adev = ring->adev;
 
-	/* we only allocate 32bit for each seq wb address */
-	BUG_ON(flags & AMDGPU_FENCE_FLAG_64BIT);
-
 	/* write fence seq to the "addr" */
 	amdgpu_ring_write(ring, PACKET3(PACKET3_WRITE_DATA, 3));
 	amdgpu_ring_write(ring, (WRITE_DATA_ENGINE_SEL(0) |
diff --git linux-libre-7.1.5-gnu/drivers/gpu/drm/amd/amdgpu/jpeg_v4_0_3.c linux-libre-7.1.6-gnu/drivers/gpu/drm/amd/amdgpu/jpeg_v4_0_3.c
index 0c746580de113..d8204fbc198d6 100644
--- linux-libre-7.1.5-gnu/drivers/gpu/drm/amd/amdgpu/jpeg_v4_0_3.c
+++ linux-libre-7.1.6-gnu/drivers/gpu/drm/amd/amdgpu/jpeg_v4_0_3.c
@@ -1010,7 +1010,7 @@ void jpeg_v4_0_3_dec_ring_nop(struct amdgpu_ring *ring, uint32_t count)
 static bool jpeg_v4_0_3_is_idle(struct amdgpu_ip_block *ip_block)
 {
 	struct amdgpu_device *adev = ip_block->adev;
-	bool ret = false;
+	bool ret = true;
 	int i, j;
 
 	for (i = 0; i < adev->jpeg.num_jpeg_inst; ++i) {
diff --git linux-libre-7.1.5-gnu/drivers/gpu/drm/amd/amdgpu/jpeg_v5_0_1.c linux-libre-7.1.6-gnu/drivers/gpu/drm/amd/amdgpu/jpeg_v5_0_1.c
index 250316704dfac..ae3afc7ab3267 100644
--- linux-libre-7.1.5-gnu/drivers/gpu/drm/amd/amdgpu/jpeg_v5_0_1.c
+++ linux-libre-7.1.6-gnu/drivers/gpu/drm/amd/amdgpu/jpeg_v5_0_1.c
@@ -657,7 +657,7 @@ static void jpeg_v5_0_1_dec_ring_set_wptr(struct amdgpu_ring *ring)
 static bool jpeg_v5_0_1_is_idle(struct amdgpu_ip_block *ip_block)
 {
 	struct amdgpu_device *adev = ip_block->adev;
-	bool ret = false;
+	bool ret = true;
 	int i, j;
 
 	for (i = 0; i < adev->jpeg.num_jpeg_inst; ++i) {
diff --git linux-libre-7.1.5-gnu/drivers/gpu/drm/amd/amdgpu/mes_v11_0.c linux-libre-7.1.6-gnu/drivers/gpu/drm/amd/amdgpu/mes_v11_0.c
index 59d5cae5cedad..f3789f8aeac6a 100644
--- linux-libre-7.1.5-gnu/drivers/gpu/drm/amd/amdgpu/mes_v11_0.c
+++ linux-libre-7.1.6-gnu/drivers/gpu/drm/amd/amdgpu/mes_v11_0.c
@@ -533,6 +533,7 @@ static int mes_v11_0_suspend_gang(struct amdgpu_mes *mes,
 	mes_suspend_gang_pkt.gang_context_addr = input->gang_context_addr;
 	mes_suspend_gang_pkt.suspend_fence_addr = input->suspend_fence_addr;
 	mes_suspend_gang_pkt.suspend_fence_value = input->suspend_fence_value;
+	mes_suspend_gang_pkt.doorbell_offset = input->doorbell_offset;
 
 	return mes_v11_0_submit_pkt_and_poll_completion(mes,
 			&mes_suspend_gang_pkt, sizeof(mes_suspend_gang_pkt),
@@ -552,6 +553,7 @@ static int mes_v11_0_resume_gang(struct amdgpu_mes *mes,
 
 	mes_resume_gang_pkt.resume_all_gangs = input->resume_all_gangs;
 	mes_resume_gang_pkt.gang_context_addr = input->gang_context_addr;
+	mes_resume_gang_pkt.doorbell_offset = input->doorbell_offset;
 
 	return mes_v11_0_submit_pkt_and_poll_completion(mes,
 			&mes_resume_gang_pkt, sizeof(mes_resume_gang_pkt),
diff --git linux-libre-7.1.5-gnu/drivers/gpu/drm/amd/amdgpu/sdma_v4_4_2.c linux-libre-7.1.6-gnu/drivers/gpu/drm/amd/amdgpu/sdma_v4_4_2.c
index 99464528a89cb..506c728e14171 100644
--- linux-libre-7.1.5-gnu/drivers/gpu/drm/amd/amdgpu/sdma_v4_4_2.c
+++ linux-libre-7.1.6-gnu/drivers/gpu/drm/amd/amdgpu/sdma_v4_4_2.c
@@ -455,7 +455,7 @@ static void sdma_v4_4_2_ring_emit_fence(struct amdgpu_ring *ring, u64 addr, u64
 	/* write the fence */
 	amdgpu_ring_write(ring, SDMA_PKT_HEADER_OP(SDMA_OP_FENCE));
 	/* zero in first two bits */
-	BUG_ON(addr & 0x3);
+	WARN_ON(addr & 0x3);
 	amdgpu_ring_write(ring, lower_32_bits(addr));
 	amdgpu_ring_write(ring, upper_32_bits(addr));
 	amdgpu_ring_write(ring, lower_32_bits(seq));
@@ -465,7 +465,7 @@ static void sdma_v4_4_2_ring_emit_fence(struct amdgpu_ring *ring, u64 addr, u64
 		addr += 4;
 		amdgpu_ring_write(ring, SDMA_PKT_HEADER_OP(SDMA_OP_FENCE));
 		/* zero in first two bits */
-		BUG_ON(addr & 0x3);
+		WARN_ON(addr & 0x3);
 		amdgpu_ring_write(ring, lower_32_bits(addr));
 		amdgpu_ring_write(ring, upper_32_bits(addr));
 		amdgpu_ring_write(ring, upper_32_bits(seq));
diff --git linux-libre-7.1.5-gnu/drivers/gpu/drm/amd/amdgpu/sdma_v5_0.c linux-libre-7.1.6-gnu/drivers/gpu/drm/amd/amdgpu/sdma_v5_0.c
index 608be833b5d1c..0d6dc67b08ee7 100644
--- linux-libre-7.1.5-gnu/drivers/gpu/drm/amd/amdgpu/sdma_v5_0.c
+++ linux-libre-7.1.6-gnu/drivers/gpu/drm/amd/amdgpu/sdma_v5_0.c
@@ -517,7 +517,7 @@ static void sdma_v5_0_ring_emit_fence(struct amdgpu_ring *ring, u64 addr, u64 se
 	amdgpu_ring_write(ring, SDMA_PKT_HEADER_OP(SDMA_OP_FENCE) |
 			  SDMA_PKT_FENCE_HEADER_MTYPE(0x3)); /* Ucached(UC) */
 	/* zero in first two bits */
-	BUG_ON(addr & 0x3);
+	WARN_ON(addr & 0x3);
 	amdgpu_ring_write(ring, lower_32_bits(addr));
 	amdgpu_ring_write(ring, upper_32_bits(addr));
 	amdgpu_ring_write(ring, lower_32_bits(seq));
@@ -528,7 +528,7 @@ static void sdma_v5_0_ring_emit_fence(struct amdgpu_ring *ring, u64 addr, u64 se
 		amdgpu_ring_write(ring, SDMA_PKT_HEADER_OP(SDMA_OP_FENCE) |
 				  SDMA_PKT_FENCE_HEADER_MTYPE(0x3));
 		/* zero in first two bits */
-		BUG_ON(addr & 0x3);
+		WARN_ON(addr & 0x3);
 		amdgpu_ring_write(ring, lower_32_bits(addr));
 		amdgpu_ring_write(ring, upper_32_bits(addr));
 		amdgpu_ring_write(ring, upper_32_bits(seq));
diff --git linux-libre-7.1.5-gnu/drivers/gpu/drm/amd/amdgpu/sdma_v5_2.c linux-libre-7.1.6-gnu/drivers/gpu/drm/amd/amdgpu/sdma_v5_2.c
index 349f68d16ffac..3589768490bb2 100644
--- linux-libre-7.1.5-gnu/drivers/gpu/drm/amd/amdgpu/sdma_v5_2.c
+++ linux-libre-7.1.6-gnu/drivers/gpu/drm/amd/amdgpu/sdma_v5_2.c
@@ -369,7 +369,7 @@ static void sdma_v5_2_ring_emit_fence(struct amdgpu_ring *ring, u64 addr, u64 se
 	amdgpu_ring_write(ring, SDMA_PKT_HEADER_OP(SDMA_OP_FENCE) |
 			  SDMA_PKT_FENCE_HEADER_MTYPE(0x3)); /* Ucached(UC) */
 	/* zero in first two bits */
-	BUG_ON(addr & 0x3);
+	WARN_ON(addr & 0x3);
 	amdgpu_ring_write(ring, lower_32_bits(addr));
 	amdgpu_ring_write(ring, upper_32_bits(addr));
 	amdgpu_ring_write(ring, lower_32_bits(seq));
@@ -380,7 +380,7 @@ static void sdma_v5_2_ring_emit_fence(struct amdgpu_ring *ring, u64 addr, u64 se
 		amdgpu_ring_write(ring, SDMA_PKT_HEADER_OP(SDMA_OP_FENCE) |
 				  SDMA_PKT_FENCE_HEADER_MTYPE(0x3));
 		/* zero in first two bits */
-		BUG_ON(addr & 0x3);
+		WARN_ON(addr & 0x3);
 		amdgpu_ring_write(ring, lower_32_bits(addr));
 		amdgpu_ring_write(ring, upper_32_bits(addr));
 		amdgpu_ring_write(ring, upper_32_bits(seq));
diff --git linux-libre-7.1.5-gnu/drivers/gpu/drm/amd/amdgpu/sdma_v6_0.c linux-libre-7.1.6-gnu/drivers/gpu/drm/amd/amdgpu/sdma_v6_0.c
index 5f228958405ae..082777388a687 100644
--- linux-libre-7.1.5-gnu/drivers/gpu/drm/amd/amdgpu/sdma_v6_0.c
+++ linux-libre-7.1.6-gnu/drivers/gpu/drm/amd/amdgpu/sdma_v6_0.c
@@ -352,7 +352,7 @@ static void sdma_v6_0_ring_emit_fence(struct amdgpu_ring *ring, u64 addr, u64 se
 	amdgpu_ring_write(ring, SDMA_PKT_COPY_LINEAR_HEADER_OP(SDMA_OP_FENCE) |
 			  SDMA_PKT_FENCE_HEADER_MTYPE(0x3)); /* Ucached(UC) */
 	/* zero in first two bits */
-	BUG_ON(addr & 0x3);
+	WARN_ON(addr & 0x3);
 	amdgpu_ring_write(ring, lower_32_bits(addr));
 	amdgpu_ring_write(ring, upper_32_bits(addr));
 	amdgpu_ring_write(ring, lower_32_bits(seq));
@@ -363,7 +363,7 @@ static void sdma_v6_0_ring_emit_fence(struct amdgpu_ring *ring, u64 addr, u64 se
 		amdgpu_ring_write(ring, SDMA_PKT_COPY_LINEAR_HEADER_OP(SDMA_OP_FENCE) |
 				  SDMA_PKT_FENCE_HEADER_MTYPE(0x3));
 		/* zero in first two bits */
-		BUG_ON(addr & 0x3);
+		WARN_ON(addr & 0x3);
 		amdgpu_ring_write(ring, lower_32_bits(addr));
 		amdgpu_ring_write(ring, upper_32_bits(addr));
 		amdgpu_ring_write(ring, upper_32_bits(seq));
diff --git linux-libre-7.1.5-gnu/drivers/gpu/drm/amd/amdgpu/sdma_v7_0.c linux-libre-7.1.6-gnu/drivers/gpu/drm/amd/amdgpu/sdma_v7_0.c
index 73a391160e1bf..4c94bd757b7b5 100644
--- linux-libre-7.1.5-gnu/drivers/gpu/drm/amd/amdgpu/sdma_v7_0.c
+++ linux-libre-7.1.6-gnu/drivers/gpu/drm/amd/amdgpu/sdma_v7_0.c
@@ -362,7 +362,7 @@ static void sdma_v7_0_ring_emit_fence(struct amdgpu_ring *ring, u64 addr, u64 se
 	amdgpu_ring_write(ring, SDMA_PKT_COPY_LINEAR_HEADER_OP(SDMA_OP_FENCE) |
 			  SDMA_PKT_FENCE_HEADER_MTYPE(0x3)); /* Ucached(UC) */
 	/* zero in first two bits */
-	BUG_ON(addr & 0x3);
+	WARN_ON(addr & 0x3);
 	amdgpu_ring_write(ring, lower_32_bits(addr));
 	amdgpu_ring_write(ring, upper_32_bits(addr));
 	amdgpu_ring_write(ring, lower_32_bits(seq));
@@ -373,7 +373,7 @@ static void sdma_v7_0_ring_emit_fence(struct amdgpu_ring *ring, u64 addr, u64 se
 		amdgpu_ring_write(ring, SDMA_PKT_COPY_LINEAR_HEADER_OP(SDMA_OP_FENCE) |
 				  SDMA_PKT_FENCE_HEADER_MTYPE(0x3));
 		/* zero in first two bits */
-		BUG_ON(addr & 0x3);
+		WARN_ON(addr & 0x3);
 		amdgpu_ring_write(ring, lower_32_bits(addr));
 		amdgpu_ring_write(ring, upper_32_bits(addr));
 		amdgpu_ring_write(ring, upper_32_bits(seq));
diff --git linux-libre-7.1.5-gnu/drivers/gpu/drm/amd/amdgpu/sdma_v7_1.c linux-libre-7.1.6-gnu/drivers/gpu/drm/amd/amdgpu/sdma_v7_1.c
index 810447a207fe3..76c6c123b0978 100644
--- linux-libre-7.1.5-gnu/drivers/gpu/drm/amd/amdgpu/sdma_v7_1.c
+++ linux-libre-7.1.6-gnu/drivers/gpu/drm/amd/amdgpu/sdma_v7_1.c
@@ -331,7 +331,7 @@ static void sdma_v7_1_ring_emit_fence(struct amdgpu_ring *ring, u64 addr, u64 se
 	amdgpu_ring_write(ring, SDMA_PKT_COPY_LINEAR_HEADER_OP(SDMA_OP_FENCE) |
 			  SDMA_PKT_FENCE_HEADER_MTYPE(0x3)); /* Ucached(UC) */
 	/* zero in first two bits */
-	BUG_ON(addr & 0x3);
+	WARN_ON(addr & 0x3);
 	amdgpu_ring_write(ring, lower_32_bits(addr));
 	amdgpu_ring_write(ring, upper_32_bits(addr));
 	amdgpu_ring_write(ring, lower_32_bits(seq));
@@ -342,7 +342,7 @@ static void sdma_v7_1_ring_emit_fence(struct amdgpu_ring *ring, u64 addr, u64 se
 		amdgpu_ring_write(ring, SDMA_PKT_COPY_LINEAR_HEADER_OP(SDMA_OP_FENCE) |
 				  SDMA_PKT_FENCE_HEADER_MTYPE(0x3));
 		/* zero in first two bits */
-		BUG_ON(addr & 0x3);
+		WARN_ON(addr & 0x3);
 		amdgpu_ring_write(ring, lower_32_bits(addr));
 		amdgpu_ring_write(ring, upper_32_bits(addr));
 		amdgpu_ring_write(ring, upper_32_bits(seq));
diff --git linux-libre-7.1.5-gnu/drivers/gpu/drm/amd/amdgpu/soc24.c linux-libre-7.1.6-gnu/drivers/gpu/drm/amd/amdgpu/soc24.c
index d1adf19a51c45..d5bbb022426ef 100644
--- linux-libre-7.1.5-gnu/drivers/gpu/drm/amd/amdgpu/soc24.c
+++ linux-libre-7.1.6-gnu/drivers/gpu/drm/amd/amdgpu/soc24.c
@@ -515,8 +515,36 @@ static int soc24_common_suspend(struct amdgpu_ip_block *ip_block)
 	return soc24_common_hw_fini(ip_block);
 }
 
+static bool soc24_need_reset_on_resume(struct amdgpu_device *adev)
+{
+	u32 sol_reg1, sol_reg2;
+
+	/* Will reset for the following suspend abort cases.
+	 * 1) Only reset dGPU side.
+	 * 2) S3 suspend got aborted and TOS is active.
+	 *    As for dGPU suspend abort cases the SOL value
+	 *    will be kept as zero at this resume point.
+	 */
+	if (!(adev->flags & AMD_IS_APU) && adev->in_s3) {
+		sol_reg1 = RREG32_SOC15(MP0, 0, regMPASP_SMN_C2PMSG_81);
+		msleep(100);
+		sol_reg2 = RREG32_SOC15(MP0, 0, regMPASP_SMN_C2PMSG_81);
+
+		return (sol_reg1 != sol_reg2);
+	}
+
+	return false;
+}
+
 static int soc24_common_resume(struct amdgpu_ip_block *ip_block)
 {
+	struct amdgpu_device *adev = ip_block->adev;
+
+	if (soc24_need_reset_on_resume(adev)) {
+		dev_info(adev->dev, "S3 suspend aborted, resetting...");
+		soc24_asic_reset(adev);
+	}
+
 	return soc24_common_hw_init(ip_block);
 }
 
diff --git linux-libre-7.1.5-gnu/drivers/gpu/drm/amd/amdgpu/vcn_v4_0.c linux-libre-7.1.6-gnu/drivers/gpu/drm/amd/amdgpu/vcn_v4_0.c
index ff7269bafae8e..894780669f9cf 100644
--- linux-libre-7.1.5-gnu/drivers/gpu/drm/amd/amdgpu/vcn_v4_0.c
+++ linux-libre-7.1.6-gnu/drivers/gpu/drm/amd/amdgpu/vcn_v4_0.c
@@ -1927,14 +1927,17 @@ out:
 #define RENCODE_IB_PARAM_SESSION_INIT			0x00000003
 
 /* return the offset in ib if id is found, -1 otherwise */
-static int vcn_v4_0_enc_find_ib_param(struct amdgpu_ib *ib, uint32_t id, int start)
+static int vcn_v4_0_enc_find_ib_param(struct amdgpu_ib *ib, uint32_t id, int start, uint32_t *length)
 {
 	int i;
 	uint32_t len;
 
 	for (i = start; (len = amdgpu_ib_get_value(ib, i)) >= 8; i += len / 4) {
-		if (amdgpu_ib_get_value(ib, i + 1) == id)
+		if (amdgpu_ib_get_value(ib, i + 1) == id) {
+			if (length)
+				*length = len;
 			return i;
+		}
 	}
 	return -1;
 }
@@ -1944,14 +1947,14 @@ static int vcn_v4_0_ring_patch_cs_in_place(struct amdgpu_cs_parser *p,
 					   struct amdgpu_ib *ib)
 {
 	struct amdgpu_ring *ring = amdgpu_job_ring(job);
-	uint32_t val;
+	uint32_t val, len;
 	int idx = 0, sidx;
 
 	/* The first instance can decode anything */
 	if (!ring->me)
 		return 0;
 
-	while ((idx = vcn_v4_0_enc_find_ib_param(ib, RADEON_VCN_ENGINE_INFO, idx)) >= 0) {
+	while ((idx = vcn_v4_0_enc_find_ib_param(ib, RADEON_VCN_ENGINE_INFO, idx, &len)) >= 0) {
 		val = amdgpu_ib_get_value(ib, idx + 2); /* RADEON_VCN_ENGINE_TYPE */
 		if (val == RADEON_VCN_ENGINE_TYPE_DECODE) {
 			uint32_t valid_buf_flag = amdgpu_ib_get_value(ib, idx + 6);
@@ -1964,12 +1967,12 @@ static int vcn_v4_0_ring_patch_cs_in_place(struct amdgpu_cs_parser *p,
 				amdgpu_ib_get_value(ib, idx + 8);
 			return vcn_v4_0_dec_msg(p, job, msg_buffer_addr);
 		} else if (val == RADEON_VCN_ENGINE_TYPE_ENCODE) {
-			sidx = vcn_v4_0_enc_find_ib_param(ib, RENCODE_IB_PARAM_SESSION_INIT, idx);
+			sidx = vcn_v4_0_enc_find_ib_param(ib, RENCODE_IB_PARAM_SESSION_INIT, idx, NULL);
 			if (sidx >= 0 &&
 			    amdgpu_ib_get_value(ib, sidx + 2) == RENCODE_ENCODE_STANDARD_AV1)
 				return vcn_v4_0_limit_sched(p, job);
 		}
-		idx += amdgpu_ib_get_value(ib, idx) / 4;
+		idx += len / 4;
 	}
 	return 0;
 }
diff --git linux-libre-7.1.5-gnu/drivers/gpu/drm/amd/amdkfd/kfd_chardev.c linux-libre-7.1.6-gnu/drivers/gpu/drm/amd/amdkfd/kfd_chardev.c
index 78068b2c96856..4f7f9d0bd8008 100644
--- linux-libre-7.1.5-gnu/drivers/gpu/drm/amd/amdkfd/kfd_chardev.c
+++ linux-libre-7.1.6-gnu/drivers/gpu/drm/amd/amdkfd/kfd_chardev.c
@@ -1837,13 +1837,13 @@ static int criu_checkpoint_devices(struct kfd_process *p,
 	struct kfd_criu_device_bucket *device_buckets = NULL;
 	int ret = 0, i;
 
-	device_buckets = kvzalloc(num_devices * sizeof(*device_buckets), GFP_KERNEL);
+	device_buckets = kvcalloc(num_devices, sizeof(*device_buckets), GFP_KERNEL);
 	if (!device_buckets) {
 		ret = -ENOMEM;
 		goto exit;
 	}
 
-	device_priv = kvzalloc(num_devices * sizeof(*device_priv), GFP_KERNEL);
+	device_priv = kvcalloc(num_devices, sizeof(*device_priv), GFP_KERNEL);
 	if (!device_priv) {
 		ret = -ENOMEM;
 		goto exit;
@@ -1963,17 +1963,17 @@ static int criu_checkpoint_bos(struct kfd_process *p,
 	int ret = 0, pdd_index, bo_index = 0, id;
 	void *mem;
 
-	bo_buckets = kvzalloc(num_bos * sizeof(*bo_buckets), GFP_KERNEL);
+	bo_buckets = kvcalloc(num_bos, sizeof(*bo_buckets), GFP_KERNEL);
 	if (!bo_buckets)
 		return -ENOMEM;
 
-	bo_privs = kvzalloc(num_bos * sizeof(*bo_privs), GFP_KERNEL);
+	bo_privs = kvcalloc(num_bos, sizeof(*bo_privs), GFP_KERNEL);
 	if (!bo_privs) {
 		ret = -ENOMEM;
 		goto exit;
 	}
 
-	files = kvzalloc(num_bos * sizeof(struct file *), GFP_KERNEL);
+	files = kvcalloc(num_bos, sizeof(struct file *), GFP_KERNEL);
 	if (!files) {
 		ret = -ENOMEM;
 		goto exit;
@@ -2510,7 +2510,7 @@ static int criu_restore_bos(struct kfd_process *p,
 	if (!bo_buckets)
 		return -ENOMEM;
 
-	files = kvzalloc(args->num_bos * sizeof(struct file *), GFP_KERNEL);
+	files = kvcalloc(args->num_bos, sizeof(struct file *), GFP_KERNEL);
 	if (!files) {
 		ret = -ENOMEM;
 		goto exit;
diff --git linux-libre-7.1.5-gnu/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.c linux-libre-7.1.6-gnu/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.c
index ee413117b0ff6..10a5916ec6c2f 100644
--- linux-libre-7.1.5-gnu/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.c
+++ linux-libre-7.1.6-gnu/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.c
@@ -2936,6 +2936,7 @@ static void deallocate_hiq_sdma_mqd(struct kfd_node *dev,
 struct device_queue_manager *device_queue_manager_init(struct kfd_node *dev)
 {
 	struct device_queue_manager *dqm;
+	int i;
 
 	pr_debug("Loading device queue manager\n");
 
@@ -3062,6 +3063,9 @@ struct device_queue_manager *device_queue_manager_init(struct kfd_node *dev)
 		deallocate_hiq_sdma_mqd(dev, &dqm->hiq_sdma_mqd);
 
 out_free:
+	for (i = 0; i < KFD_MQD_TYPE_MAX; i++)
+		kfree(dqm->mqd_mgrs[i]);
+
 	kfree(dqm);
 	return NULL;
 }
@@ -3649,6 +3653,12 @@ out:
 	dqm_unlock(dqm);
 	return r;
 }
+
+size_t mqd_size_from_queue_type(struct device_queue_manager *dqm, enum kfd_queue_type type)
+{
+	return dqm->mqd_mgrs[get_mqd_type_from_queue_type(type)]->mqd_size;
+}
+
 #if defined(CONFIG_DEBUG_FS)
 
 static void seq_reg_dump(struct seq_file *m,
diff --git linux-libre-7.1.5-gnu/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.h linux-libre-7.1.6-gnu/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.h
index 3272328da11f9..4a1dcae95f755 100644
--- linux-libre-7.1.5-gnu/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.h
+++ linux-libre-7.1.6-gnu/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.h
@@ -329,6 +329,8 @@ int debug_refresh_runlist(struct device_queue_manager *dqm);
 bool kfd_dqm_is_queue_in_process(struct device_queue_manager *dqm,
 				 struct qcm_process_device *qpd,
 				 int doorbell_off, u32 *queue_format);
+size_t mqd_size_from_queue_type(struct device_queue_manager *dqm,
+				enum kfd_queue_type type);
 
 static inline unsigned int get_sh_mem_bases_32(struct kfd_process_device *pdd)
 {
diff --git linux-libre-7.1.5-gnu/drivers/gpu/drm/amd/amdkfd/kfd_events.c linux-libre-7.1.6-gnu/drivers/gpu/drm/amd/amdkfd/kfd_events.c
index 81900b49d9d5b..ebdd1fbf9ac00 100644
--- linux-libre-7.1.5-gnu/drivers/gpu/drm/amd/amdkfd/kfd_events.c
+++ linux-libre-7.1.6-gnu/drivers/gpu/drm/amd/amdkfd/kfd_events.c
@@ -107,6 +107,9 @@ static int allocate_event_notification_slot(struct kfd_process *p,
 	}
 
 	if (restore_id) {
+		if (*restore_id >= KFD_SIGNAL_EVENT_LIMIT)
+			return -EINVAL;
+
 		id = idr_alloc(&p->event_idr, ev, *restore_id, *restore_id + 1,
 				GFP_KERNEL);
 	} else {
diff --git linux-libre-7.1.5-gnu/drivers/gpu/drm/amd/amdkfd/kfd_mqd_manager.h linux-libre-7.1.6-gnu/drivers/gpu/drm/amd/amdkfd/kfd_mqd_manager.h
index 06ca6235ff1b7..63ea70e5c0e65 100644
--- linux-libre-7.1.5-gnu/drivers/gpu/drm/amd/amdkfd/kfd_mqd_manager.h
+++ linux-libre-7.1.6-gnu/drivers/gpu/drm/amd/amdkfd/kfd_mqd_manager.h
@@ -127,6 +127,7 @@ struct mqd_manager {
 	struct mutex	mqd_mutex;
 	struct kfd_node	*dev;
 	uint32_t mqd_size;
+	uint32_t ctl_stack_size;
 };
 
 struct mqd_user_context_save_area_header {
diff --git linux-libre-7.1.5-gnu/drivers/gpu/drm/amd/amdkfd/kfd_mqd_manager_v10.c linux-libre-7.1.6-gnu/drivers/gpu/drm/amd/amdkfd/kfd_mqd_manager_v10.c
index 77fb41e2486a4..f36f0e8631d41 100644
--- linux-libre-7.1.5-gnu/drivers/gpu/drm/amd/amdkfd/kfd_mqd_manager_v10.c
+++ linux-libre-7.1.6-gnu/drivers/gpu/drm/amd/amdkfd/kfd_mqd_manager_v10.c
@@ -198,8 +198,8 @@ static void update_mqd(struct mqd_manager *mm, void *mqd,
 	 * more than (EOP entry count - 1) so a queue size of 0x800 dwords
 	 * is safe, giving a maximum field value of 0xA.
 	 */
-	m->cp_hqd_eop_control = min(0xA,
-		ffs(q->eop_ring_buffer_size / sizeof(unsigned int)) - 1 - 1);
+	m->cp_hqd_eop_control = q->eop_ring_buffer_size ? min(0xA,
+		ffs(q->eop_ring_buffer_size / sizeof(unsigned int)) - 1 - 1) : 0;
 	m->cp_hqd_eop_base_addr_lo =
 			lower_32_bits(q->eop_ring_buffer_address >> 8);
 	m->cp_hqd_eop_base_addr_hi =
diff --git linux-libre-7.1.5-gnu/drivers/gpu/drm/amd/amdkfd/kfd_mqd_manager_v11.c linux-libre-7.1.6-gnu/drivers/gpu/drm/amd/amdkfd/kfd_mqd_manager_v11.c
index 527c531676e43..d09ba9b30b6e7 100644
--- linux-libre-7.1.5-gnu/drivers/gpu/drm/amd/amdkfd/kfd_mqd_manager_v11.c
+++ linux-libre-7.1.6-gnu/drivers/gpu/drm/amd/amdkfd/kfd_mqd_manager_v11.c
@@ -237,8 +237,8 @@ static void update_mqd(struct mqd_manager *mm, void *mqd,
 	 * more than (EOP entry count - 1) so a queue size of 0x800 dwords
 	 * is safe, giving a maximum field value of 0xA.
 	 */
-	m->cp_hqd_eop_control = min(0xA,
-		ffs(q->eop_ring_buffer_size / sizeof(unsigned int)) - 1 - 1);
+	m->cp_hqd_eop_control = q->eop_ring_buffer_size ? min(0xA,
+		ffs(q->eop_ring_buffer_size / sizeof(unsigned int)) - 1 - 1) : 0;
 	m->cp_hqd_eop_base_addr_lo =
 			lower_32_bits(q->eop_ring_buffer_address >> 8);
 	m->cp_hqd_eop_base_addr_hi =
diff --git linux-libre-7.1.5-gnu/drivers/gpu/drm/amd/amdkfd/kfd_mqd_manager_v12.c linux-libre-7.1.6-gnu/drivers/gpu/drm/amd/amdkfd/kfd_mqd_manager_v12.c
index b3e122d7876e0..9897cc6048651 100644
--- linux-libre-7.1.5-gnu/drivers/gpu/drm/amd/amdkfd/kfd_mqd_manager_v12.c
+++ linux-libre-7.1.6-gnu/drivers/gpu/drm/amd/amdkfd/kfd_mqd_manager_v12.c
@@ -212,8 +212,8 @@ static void update_mqd(struct mqd_manager *mm, void *mqd,
 	 * more than (EOP entry count - 1) so a queue size of 0x800 dwords
 	 * is safe, giving a maximum field value of 0xA.
 	 */
-	m->cp_hqd_eop_control = min(0xA,
-		ffs(q->eop_ring_buffer_size / sizeof(unsigned int)) - 1 - 1);
+	m->cp_hqd_eop_control = q->eop_ring_buffer_size ? min(0xA,
+		ffs(q->eop_ring_buffer_size / sizeof(unsigned int)) - 1 - 1) : 0;
 	m->cp_hqd_eop_base_addr_lo =
 			lower_32_bits(q->eop_ring_buffer_address >> 8);
 	m->cp_hqd_eop_base_addr_hi =
diff --git linux-libre-7.1.5-gnu/drivers/gpu/drm/amd/amdkfd/kfd_mqd_manager_v12_1.c linux-libre-7.1.6-gnu/drivers/gpu/drm/amd/amdkfd/kfd_mqd_manager_v12_1.c
index 475589b924e90..431a940f91f3b 100644
--- linux-libre-7.1.5-gnu/drivers/gpu/drm/amd/amdkfd/kfd_mqd_manager_v12_1.c
+++ linux-libre-7.1.6-gnu/drivers/gpu/drm/amd/amdkfd/kfd_mqd_manager_v12_1.c
@@ -294,8 +294,8 @@ static void update_mqd(struct mqd_manager *mm, void *mqd,
 	 * more than (EOP entry count - 1) so a queue size of 0x800 dwords
 	 * is safe, giving a maximum field value of 0xA.
 	 */
-	m->cp_hqd_eop_control = min(0xA,
-		ffs(q->eop_ring_buffer_size / sizeof(unsigned int)) - 1 - 1);
+	m->cp_hqd_eop_control = q->eop_ring_buffer_size ? min(0xA,
+		ffs(q->eop_ring_buffer_size / sizeof(unsigned int)) - 1 - 1) : 0;
 	m->cp_hqd_eop_base_addr_lo =
 			lower_32_bits(q->eop_ring_buffer_address >> 8);
 	m->cp_hqd_eop_base_addr_hi =
diff --git linux-libre-7.1.5-gnu/drivers/gpu/drm/amd/amdkfd/kfd_mqd_manager_v9.c linux-libre-7.1.6-gnu/drivers/gpu/drm/amd/amdkfd/kfd_mqd_manager_v9.c
index f6d9d81003dc3..9164735058bc9 100644
--- linux-libre-7.1.5-gnu/drivers/gpu/drm/amd/amdkfd/kfd_mqd_manager_v9.c
+++ linux-libre-7.1.6-gnu/drivers/gpu/drm/amd/amdkfd/kfd_mqd_manager_v9.c
@@ -27,6 +27,7 @@
 #include <linux/uaccess.h>
 #include "kfd_priv.h"
 #include "kfd_mqd_manager.h"
+#include "kfd_topology.h"
 #include "v9_structs.h"
 #include "gc/gc_9_0_offset.h"
 #include "gc/gc_9_0_sh_mask.h"
@@ -400,8 +401,11 @@ static int get_wave_state(struct mqd_manager *mm, void *mqd,
 static int get_checkpoint_info(struct mqd_manager *mm, void *mqd, u32 *ctl_stack_size)
 {
 	struct v9_mqd *m = get_mqd(mqd);
+	u32 per_xcc_size;
 
-	if (check_mul_overflow(m->cp_hqd_cntl_stack_size, NUM_XCC(mm->dev->xcc_mask), ctl_stack_size))
+	per_xcc_size = min_t(u32, m->cp_hqd_cntl_stack_size, mm->ctl_stack_size);
+
+	if (check_mul_overflow(per_xcc_size, NUM_XCC(mm->dev->xcc_mask), ctl_stack_size))
 		return -EINVAL;
 
 	return 0;
@@ -410,13 +414,15 @@ static int get_checkpoint_info(struct mqd_manager *mm, void *mqd, u32 *ctl_stack
 static void checkpoint_mqd(struct mqd_manager *mm, void *mqd, void *mqd_dst, void *ctl_stack_dst)
 {
 	struct v9_mqd *m;
+	u32 ctl_stack_copy_size;
 	/* Control stack is located one page after MQD. */
 	void *ctl_stack = (void *)((uintptr_t)mqd + AMDGPU_GPU_PAGE_SIZE);
 
 	m = get_mqd(mqd);
+	ctl_stack_copy_size = min_t(u32, m->cp_hqd_cntl_stack_size, mm->ctl_stack_size);
 
 	memcpy(mqd_dst, m, sizeof(struct v9_mqd));
-	memcpy(ctl_stack_dst, ctl_stack, m->cp_hqd_cntl_stack_size);
+	memcpy(ctl_stack_dst, ctl_stack, ctl_stack_copy_size);
 }
 
 static void checkpoint_mqd_v9_4_3(struct mqd_manager *mm,
@@ -425,15 +431,19 @@ static void checkpoint_mqd_v9_4_3(struct mqd_manager *mm,
 								  void *ctl_stack_dst)
 {
 	struct v9_mqd *m;
+	u32 ctl_stack_stride;
 	int xcc;
 	uint64_t size = get_mqd(mqd)->cp_mqd_stride_size;
 
+	ctl_stack_stride = min_t(u32, get_mqd(mqd)->cp_hqd_cntl_stack_size,
+				 mm->ctl_stack_size);
+
 	for (xcc = 0; xcc < NUM_XCC(mm->dev->xcc_mask); xcc++) {
 		m = get_mqd(mqd + size * xcc);
 
 		checkpoint_mqd(mm, m,
 				(uint8_t *)mqd_dst + sizeof(*m) * xcc,
-				(uint8_t *)ctl_stack_dst + m->cp_hqd_cntl_stack_size * xcc);
+				(uint8_t *)ctl_stack_dst + ctl_stack_stride * xcc);
 	}
 }
 
@@ -987,6 +997,15 @@ struct mqd_manager *mqd_manager_init_v9(enum KFD_MQD_TYPE type,
 		mqd->is_occupied = kfd_is_occupied_cp;
 		mqd->get_checkpoint_info = get_checkpoint_info;
 		mqd->mqd_size = sizeof(struct v9_mqd);
+		if (dev->kfd->cwsr_enabled) {
+			struct kfd_topology_device *topo_dev;
+
+			topo_dev = kfd_topology_device_by_id(dev->id);
+			if (topo_dev)
+				mqd->ctl_stack_size =
+					ALIGN(topo_dev->node_props.ctl_stack_size,
+					      AMDGPU_GPU_PAGE_SIZE);
+		}
 		mqd->mqd_stride = mqd_stride_v9;
 #if defined(CONFIG_DEBUG_FS)
 		mqd->debugfs_show_mqd = debugfs_show_mqd;
diff --git linux-libre-7.1.5-gnu/drivers/gpu/drm/amd/amdkfd/kfd_mqd_manager_vi.c linux-libre-7.1.6-gnu/drivers/gpu/drm/amd/amdkfd/kfd_mqd_manager_vi.c
index 431a20323146b..f2a24edeba845 100644
--- linux-libre-7.1.5-gnu/drivers/gpu/drm/amd/amdkfd/kfd_mqd_manager_vi.c
+++ linux-libre-7.1.6-gnu/drivers/gpu/drm/amd/amdkfd/kfd_mqd_manager_vi.c
@@ -209,8 +209,8 @@ static void __update_mqd(struct mqd_manager *mm, void *mqd,
 	 * more than (EOP entry count - 1) so a queue size of 0x800 dwords
 	 * is safe, giving a maximum field value of 0xA.
 	 */
-	m->cp_hqd_eop_control |= min(0xA,
-		order_base_2(q->eop_ring_buffer_size / 4) - 1);
+	m->cp_hqd_eop_control |= q->eop_ring_buffer_size ? min(0xA,
+		order_base_2(q->eop_ring_buffer_size / 4) - 1) : 0;
 	m->cp_hqd_eop_base_addr_lo =
 			lower_32_bits(q->eop_ring_buffer_address >> 8);
 	m->cp_hqd_eop_base_addr_hi =
diff --git linux-libre-7.1.5-gnu/drivers/gpu/drm/amd/amdkfd/kfd_priv.h linux-libre-7.1.6-gnu/drivers/gpu/drm/amd/amdkfd/kfd_priv.h
index d5b07789eda43..347e54456f7db 100644
--- linux-libre-7.1.5-gnu/drivers/gpu/drm/amd/amdkfd/kfd_priv.h
+++ linux-libre-7.1.6-gnu/drivers/gpu/drm/amd/amdkfd/kfd_priv.h
@@ -436,7 +436,8 @@ enum kfd_queue_type  {
 	KFD_QUEUE_TYPE_SDMA,
 	KFD_QUEUE_TYPE_HIQ,
 	KFD_QUEUE_TYPE_SDMA_XGMI,
-	KFD_QUEUE_TYPE_SDMA_BY_ENG_ID
+	KFD_QUEUE_TYPE_SDMA_BY_ENG_ID,
+	KFD_QUEUE_TYPE_MAX,
 };
 
 enum kfd_queue_format {
diff --git linux-libre-7.1.5-gnu/drivers/gpu/drm/amd/amdkfd/kfd_process_queue_manager.c linux-libre-7.1.6-gnu/drivers/gpu/drm/amd/amdkfd/kfd_process_queue_manager.c
index 44e39ce222b78..858cf5801f052 100644
--- linux-libre-7.1.5-gnu/drivers/gpu/drm/amd/amdkfd/kfd_process_queue_manager.c
+++ linux-libre-7.1.6-gnu/drivers/gpu/drm/amd/amdkfd/kfd_process_queue_manager.c
@@ -1003,6 +1003,23 @@ int kfd_criu_restore_queue(struct kfd_process *p,
 		goto exit;
 	}
 
+	pdd = kfd_process_device_data_by_id(p, q_data->gpu_id);
+	if (!pdd) {
+		pr_err("Failed to get pdd\n");
+		ret = -EINVAL;
+		goto exit;
+	}
+
+	if (q_data->type >= KFD_QUEUE_TYPE_MAX) {
+		ret = -EINVAL;
+		goto exit;
+	}
+
+	if (q_data->mqd_size != mqd_size_from_queue_type(pdd->dev->dqm, q_data->type)) {
+		ret = -EINVAL;
+		goto exit;
+	}
+
 	*priv_data_offset += sizeof(*q_data);
 	q_extra_data_size = (uint64_t)q_data->ctl_stack_size + q_data->mqd_size;
 
@@ -1025,13 +1042,6 @@ int kfd_criu_restore_queue(struct kfd_process *p,
 
 	*priv_data_offset += q_extra_data_size;
 
-	pdd = kfd_process_device_data_by_id(p, q_data->gpu_id);
-	if (!pdd) {
-		pr_err("Failed to get pdd\n");
-		ret = -EINVAL;
-		goto exit;
-	}
-
 	/*
 	 * data stored in this order:
 	 * mqd[xcc0], mqd[xcc1],..., ctl_stack[xcc0], ctl_stack[xcc1]...
diff --git linux-libre-7.1.5-gnu/drivers/gpu/drm/amd/amdkfd/kfd_queue.c linux-libre-7.1.6-gnu/drivers/gpu/drm/amd/amdkfd/kfd_queue.c
index 28354a4e5dd5d..98a5512b701b1 100644
--- linux-libre-7.1.5-gnu/drivers/gpu/drm/amd/amdkfd/kfd_queue.c
+++ linux-libre-7.1.6-gnu/drivers/gpu/drm/amd/amdkfd/kfd_queue.c
@@ -23,6 +23,7 @@
  */
 
 #include <linux/slab.h>
+#include <linux/overflow.h>
 #include "kfd_priv.h"
 #include "kfd_topology.h"
 #include "kfd_svm.h"
@@ -235,7 +236,7 @@ int kfd_queue_acquire_buffers(struct kfd_process_device *pdd, struct queue_prope
 	struct kfd_topology_device *topo_dev;
 	u64 expected_queue_size;
 	struct amdgpu_vm *vm;
-	u32 total_cwsr_size;
+	u64 total_cwsr_size;
 	int err;
 
 	topo_dev = kfd_topology_device_by_id(pdd->dev->id);
@@ -308,8 +309,14 @@ int kfd_queue_acquire_buffers(struct kfd_process_device *pdd, struct queue_prope
 		goto out_err_unreserve;
 	}
 
-	total_cwsr_size = (properties->ctx_save_restore_area_size +
-			   topo_dev->node_props.debug_memory_size) * NUM_XCC(pdd->dev->xcc_mask);
+	total_cwsr_size = (u64)properties->ctx_save_restore_area_size +
+			  topo_dev->node_props.debug_memory_size;
+	if (check_mul_overflow(total_cwsr_size,
+			       NUM_XCC(pdd->dev->xcc_mask),
+			       &total_cwsr_size)) {
+		err = -EINVAL;
+		goto out_err_unreserve;
+	}
 	total_cwsr_size = ALIGN(total_cwsr_size, PAGE_SIZE);
 
 	err = kfd_queue_buffer_get(vm, (void *)properties->ctx_save_restore_area_address,
@@ -344,7 +351,7 @@ out_err_release:
 int kfd_queue_release_buffers(struct kfd_process_device *pdd, struct queue_properties *properties)
 {
 	struct kfd_topology_device *topo_dev;
-	u32 total_cwsr_size;
+	u64 total_cwsr_size;
 
 	kfd_queue_buffer_put(&properties->wptr_bo);
 	kfd_queue_buffer_put(&properties->rptr_bo);
@@ -355,8 +362,12 @@ int kfd_queue_release_buffers(struct kfd_process_device *pdd, struct queue_prope
 	topo_dev = kfd_topology_device_by_id(pdd->dev->id);
 	if (!topo_dev)
 		return -EINVAL;
-	total_cwsr_size = (properties->ctx_save_restore_area_size +
-			   topo_dev->node_props.debug_memory_size) * NUM_XCC(pdd->dev->xcc_mask);
+	total_cwsr_size = (u64)properties->ctx_save_restore_area_size +
+			  topo_dev->node_props.debug_memory_size;
+	if (check_mul_overflow(total_cwsr_size,
+			       NUM_XCC(pdd->dev->xcc_mask),
+			       &total_cwsr_size))
+		return -EINVAL;
 	total_cwsr_size = ALIGN(total_cwsr_size, PAGE_SIZE);
 
 	kfd_queue_buffer_svm_put(pdd, properties->ctx_save_restore_area_address, total_cwsr_size);
diff --git linux-libre-7.1.5-gnu/drivers/gpu/drm/amd/amdkfd/kfd_svm.c linux-libre-7.1.6-gnu/drivers/gpu/drm/amd/amdkfd/kfd_svm.c
index 0b54ad8036b64..13f170a6de1ff 100644
--- linux-libre-7.1.5-gnu/drivers/gpu/drm/amd/amdkfd/kfd_svm.c
+++ linux-libre-7.1.6-gnu/drivers/gpu/drm/amd/amdkfd/kfd_svm.c
@@ -1144,7 +1144,7 @@ static int
 svm_range_split_tail(struct svm_range *prange, uint64_t new_last,
 		     struct list_head *insert_list, struct list_head *remap_list)
 {
-	unsigned long last_align_down = ALIGN_DOWN(prange->last, 512);
+	unsigned long last_align_down = ALIGN_DOWN(prange->last + 1, 512);
 	unsigned long start_align = ALIGN(prange->start, 512);
 	bool huge_page_mapping = last_align_down > start_align;
 	struct svm_range *tail = NULL;
@@ -1168,7 +1168,7 @@ static int
 svm_range_split_head(struct svm_range *prange, uint64_t new_start,
 		     struct list_head *insert_list, struct list_head *remap_list)
 {
-	unsigned long last_align_down = ALIGN_DOWN(prange->last, 512);
+	unsigned long last_align_down = ALIGN_DOWN(prange->last + 1, 512);
 	unsigned long start_align = ALIGN(prange->start, 512);
 	bool huge_page_mapping = last_align_down > start_align;
 	struct svm_range *head = NULL;
@@ -1181,8 +1181,8 @@ svm_range_split_head(struct svm_range *prange, uint64_t new_start,
 
 	list_add(&head->list, insert_list);
 
-	if (huge_page_mapping && head->last + 1 > start_align &&
-	    head->last + 1 < last_align_down && (!IS_ALIGNED(head->last, 512)))
+	if (huge_page_mapping && new_start > start_align &&
+	    new_start < last_align_down && !IS_ALIGNED(new_start, 512))
 		list_add(&head->update_list, remap_list);
 
 	return 0;
diff --git linux-libre-7.1.5-gnu/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c linux-libre-7.1.6-gnu/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
index c8b37b139155f..ac6cfbe73057b 100644
--- linux-libre-7.1.5-gnu/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
+++ linux-libre-7.1.6-gnu/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
@@ -576,89 +576,25 @@ static void schedule_dc_vmin_vmax(struct amdgpu_device *adev,
 	queue_work(system_percpu_wq, &offload_work->work);
 }
 
-static void dm_vupdate_high_irq(void *interrupt_params)
-{
-	struct common_irq_params *irq_params = interrupt_params;
-	struct amdgpu_device *adev = irq_params->adev;
-	struct amdgpu_crtc *acrtc;
-	struct drm_device *drm_dev;
-	struct drm_vblank_crtc *vblank;
-	ktime_t frame_duration_ns, previous_timestamp;
-	unsigned long flags;
-	int vrr_active;
-
-	acrtc = get_crtc_by_otg_inst(adev, irq_params->irq_src - IRQ_TYPE_VUPDATE);
-
-	if (acrtc) {
-		vrr_active = amdgpu_dm_crtc_vrr_active_irq(acrtc);
-		drm_dev = acrtc->base.dev;
-		vblank = drm_crtc_vblank_crtc(&acrtc->base);
-		previous_timestamp = atomic64_read(&irq_params->previous_timestamp);
-		frame_duration_ns = vblank->time - previous_timestamp;
-
-		if (frame_duration_ns > 0) {
-			trace_amdgpu_refresh_rate_track(acrtc->base.index,
-						frame_duration_ns,
-						ktime_divns(NSEC_PER_SEC, frame_duration_ns));
-			atomic64_set(&irq_params->previous_timestamp, vblank->time);
-		}
-
-		drm_dbg_vbl(drm_dev,
-			    "crtc:%d, vupdate-vrr:%d\n", acrtc->crtc_id,
-			    vrr_active);
-
-		/* Core vblank handling is done here after end of front-porch in
-		 * vrr mode, as vblank timestamping will give valid results
-		 * while now done after front-porch. This will also deliver
-		 * page-flip completion events that have been queued to us
-		 * if a pageflip happened inside front-porch.
-		 */
-		if (vrr_active && acrtc->dm_irq_params.stream) {
-			bool replay_en = acrtc->dm_irq_params.stream->link->replay_settings.replay_feature_enabled;
-			bool psr_en = acrtc->dm_irq_params.stream->link->psr_settings.psr_feature_enabled;
-			bool fs_active_var_en = acrtc->dm_irq_params.freesync_config.state
-				== VRR_STATE_ACTIVE_VARIABLE;
-
-			amdgpu_dm_crtc_handle_vblank(acrtc);
-
-			/* BTR processing for pre-DCE12 ASICs */
-			if (adev->family < AMDGPU_FAMILY_AI) {
-				spin_lock_irqsave(&adev_to_drm(adev)->event_lock, flags);
-				mod_freesync_handle_v_update(
-				    adev->dm.freesync_module,
-				    acrtc->dm_irq_params.stream,
-				    &acrtc->dm_irq_params.vrr_params);
-
-				if (fs_active_var_en || (!fs_active_var_en && !replay_en && !psr_en)) {
-					schedule_dc_vmin_vmax(adev,
-						acrtc->dm_irq_params.stream,
-						&acrtc->dm_irq_params.vrr_params.adjust);
-				}
-				spin_unlock_irqrestore(&adev_to_drm(adev)->event_lock, flags);
-			}
-		}
-	}
-}
-
 /**
- * dm_crtc_high_irq() - Handles CRTC interrupt
- * @interrupt_params: used for determining the CRTC instance
+ * dm_crtc_high_irq_handler() - Common OTG vblank/flip event handling
+ * @adev: amdgpu device
+ * @acrtc: the CRTC to service
  *
- * Handles the CRTC/VSYNC interrupt by notfying DRM's VBLANK
- * event handler.
+ * Performs writeback completion, vblank event handling, CRC processing, VRR BTR
+ * updates and pageflip completion delivery.
+ *
+ * On DCN this is driven by VUPDATE_NO_LOCK (the register latch point) from
+ * dm_vupdate_high_irq(); on DCE it is driven by VLINE0 at the start of vblank
+ * from dm_crtc_high_irq().
  */
-static void dm_crtc_high_irq(void *interrupt_params)
+static void dm_crtc_high_irq_handler(struct amdgpu_device *adev,
+				     struct amdgpu_crtc *acrtc)
 {
-	struct common_irq_params *irq_params = interrupt_params;
-	struct amdgpu_device *adev = irq_params->adev;
 	struct drm_writeback_job *job;
-	struct amdgpu_crtc *acrtc;
 	unsigned long flags;
 	int vrr_active;
-
-	acrtc = get_crtc_by_otg_inst(adev, irq_params->irq_src - IRQ_TYPE_VBLANK);
-	if (!acrtc)
-		return;
+	bool is_dcn = amdgpu_ip_version(adev, DCE_HWIP, 0) != 0;
 
 	if (acrtc->wb_conn) {
 		spin_lock_irqsave(&acrtc->wb_conn->job_lock, flags);
@@ -695,12 +631,17 @@ static void dm_crtc_high_irq(void *interrupt_params)
 		    vrr_active, acrtc->dm_irq_params.active_planes);
 
 	/**
-	 * Core vblank handling at start of front-porch is only possible
-	 * in non-vrr mode, as only there vblank timestamping will give
-	 * valid results while done in front-porch. Otherwise defer it
-	 * to dm_vupdate_high_irq after end of front-porch.
+	 * Core vblank handling.
+	 *
+	 * On DCN this handler runs at VUPDATE_NO_LOCK, the register latch
+	 * point, which is the correct place to timestamp both VRR and non-VRR
+	 * vblanks.
+	 *
+	 * On DCE this handler runs at the start of front-porch, where only
+	 * non-VRR timestamping is valid; VRR vblank is deferred to
+	 * dm_vupdate_high_irq() after end of front-porch.
 	 */
-	if (!vrr_active)
+	if (is_dcn || !vrr_active)
 		amdgpu_dm_crtc_handle_vblank(acrtc);
 
 	/**
@@ -733,18 +674,16 @@ static void dm_crtc_high_irq(void *interrupt_params)
 	}
 
 	/*
-	 * If there aren't any active_planes then DCH HUBP may be clock-gated.
-	 * In that case, pageflip completion interrupts won't fire and pageflip
-	 * completion events won't get delivered. Prevent this by sending
-	 * pending pageflip events from here if a flip is still pending.
+	 * Deliver pageflip completion events (DCN only).
+	 *
+	 * Since GRPH_PFLIP is not used, VUPDATE_NO_LOCK is the flip latch
+	 * point. Deliver any pending pageflip completion event from here.
 	 *
-	 * If any planes are enabled, use dm_pflip_high_irq() instead, to
-	 * avoid race conditions between flip programming and completion,
-	 * which could cause too early flip completion events.
+	 * NOTE: This can deliver an event for a flip that was armed but not yet
+	 * programmed into HW; that race is closed in a follow-up change by
+	 * checking the programmed flip status.
 	 */
-	if (adev->family >= AMDGPU_FAMILY_RV &&
-	    acrtc->pflip_status == AMDGPU_FLIP_SUBMITTED &&
-	    acrtc->dm_irq_params.active_planes == 0) {
+	if (is_dcn && acrtc->pflip_status == AMDGPU_FLIP_SUBMITTED) {
 		if (acrtc->event) {
 			drm_crtc_send_vblank_event(&acrtc->base, acrtc->event);
 			acrtc->event = NULL;
@@ -756,6 +695,104 @@ static void dm_crtc_high_irq(void *interrupt_params)
 	spin_unlock_irqrestore(&adev_to_drm(adev)->event_lock, flags);
 }
 
+static void dm_vupdate_high_irq(void *interrupt_params)
+{
+	struct common_irq_params *irq_params = interrupt_params;
+	struct amdgpu_device *adev = irq_params->adev;
+	struct amdgpu_crtc *acrtc;
+	struct drm_device *drm_dev;
+	struct drm_vblank_crtc *vblank;
+	ktime_t frame_duration_ns, previous_timestamp;
+	unsigned long flags;
+	int vrr_active;
+
+	acrtc = get_crtc_by_otg_inst(adev, irq_params->irq_src - IRQ_TYPE_VUPDATE);
+	if (!acrtc)
+		return;
+
+	vrr_active = amdgpu_dm_crtc_vrr_active_irq(acrtc);
+	drm_dev = acrtc->base.dev;
+	vblank = drm_crtc_vblank_crtc(&acrtc->base);
+	previous_timestamp = atomic64_read(&irq_params->previous_timestamp);
+	frame_duration_ns = vblank->time - previous_timestamp;
+
+	if (frame_duration_ns > 0) {
+		trace_amdgpu_refresh_rate_track(acrtc->base.index,
+					frame_duration_ns,
+					ktime_divns(NSEC_PER_SEC, frame_duration_ns));
+		atomic64_set(&irq_params->previous_timestamp, vblank->time);
+	}
+
+	drm_dbg_vbl(drm_dev,
+		    "crtc:%d, vupdate-vrr:%d\n", acrtc->crtc_id,
+		    vrr_active);
+
+	/*
+	 * On DCN, VUPDATE_NO_LOCK is the single OTG interrupt used to deliver
+	 * vblank and pageflip completion events; VSTARTUP and GRPH_PFLIP are
+	 * not used. Run the full handler here.
+	 */
+	if (amdgpu_ip_version(adev, DCE_HWIP, 0) != 0) {
+		dm_crtc_high_irq_handler(adev, acrtc);
+		return;
+	}
+
+	/* DCE only below. */
+
+	/* Core vblank handling is done here after end of front-porch in
+	 * vrr mode, as vblank timestamping will give valid results
+	 * while now done after front-porch. This will also deliver
+	 * page-flip completion events that have been queued to us
+	 * if a pageflip happened inside front-porch.
+	 */
+	if (vrr_active && acrtc->dm_irq_params.stream) {
+		bool replay_en = acrtc->dm_irq_params.stream->link->replay_settings.replay_feature_enabled;
+		bool psr_en = acrtc->dm_irq_params.stream->link->psr_settings.psr_feature_enabled;
+		bool fs_active_var_en = acrtc->dm_irq_params.freesync_config.state
+			== VRR_STATE_ACTIVE_VARIABLE;
+
+		amdgpu_dm_crtc_handle_vblank(acrtc);
+
+		/* BTR processing for pre-DCE12 ASICs */
+		if (adev->family < AMDGPU_FAMILY_AI) {
+			spin_lock_irqsave(&adev_to_drm(adev)->event_lock, flags);
+			mod_freesync_handle_v_update(
+				adev->dm.freesync_module,
+				acrtc->dm_irq_params.stream,
+				&acrtc->dm_irq_params.vrr_params);
+
+			if (fs_active_var_en || (!fs_active_var_en && !replay_en && !psr_en)) {
+				schedule_dc_vmin_vmax(adev,
+					acrtc->dm_irq_params.stream,
+					&acrtc->dm_irq_params.vrr_params.adjust);
+			}
+			spin_unlock_irqrestore(&adev_to_drm(adev)->event_lock, flags);
+		}
+	}
+}
+
+/**
+ * dm_crtc_high_irq() - Handles CRTC interrupt
+ * @interrupt_params: used for determining the CRTC instance
+ *
+ * Handles the CRTC/VSYNC interrupt by notifying DRM's VBLANK event handler.
+ *
+ * Used on DCE (VLINE0, set to vblank start). On DCN the equivalent handling is
+ * driven by VUPDATE_NO_LOCK in dm_vupdate_high_irq().
+ */
+static void dm_crtc_high_irq(void *interrupt_params)
+{
+	struct common_irq_params *irq_params = interrupt_params;
+	struct amdgpu_device *adev = irq_params->adev;
+	struct amdgpu_crtc *acrtc;
+
+	acrtc = get_crtc_by_otg_inst(adev, irq_params->irq_src - IRQ_TYPE_VBLANK);
+	if (!acrtc)
+		return;
+
+	dm_crtc_high_irq_handler(adev, acrtc);
+}
+
 #if defined(CONFIG_DRM_AMD_SECURE_DISPLAY)
 /**
  * dm_dcn_vertical_interrupt0_high_irq() - Handles OTG Vertical interrupt0 for
@@ -2260,9 +2297,16 @@ static void amdgpu_dm_fini(struct amdgpu_device *adev)
 		adev->dm.idle_workqueue = NULL;
 	}
 
-	/* Disable ISM before dc_destroy() invalidates dm->dc */
+	/*
+	 * Disable ISM before dc_destroy() invalidates dm->dc.
+	 *
+	 * Quiesce workers first without dc_lock (they take dc_lock
+	 * themselves, so syncing under it would deadlock), then drive the
+	 * FSM back to FULL_POWER_RUNNING under dc_lock.
+	 */
+	amdgpu_dm_ism_disable(&adev->dm);
 	scoped_guard(mutex, &adev->dm.dc_lock)
-		amdgpu_dm_ism_disable(&adev->dm);
+		amdgpu_dm_ism_force_full_power(&adev->dm);
 
 	amdgpu_dm_destroy_drm_device(&adev->dm);
 
@@ -3134,7 +3178,8 @@ static void dm_gpureset_toggle_interrupts(struct amdgpu_device *adev,
 		acrtc = get_crtc_by_otg_inst(
 				adev, state->stream_status[i].primary_otg_inst);
 
-		if (acrtc && state->stream_status[i].plane_count != 0) {
+		if (acrtc && state->stream_status[i].plane_count != 0 &&
+		    amdgpu_ip_version(adev, DCE_HWIP, 0) == 0) {
 			irq_source = IRQ_TYPE_PFLIP + acrtc->otg_inst;
 			rc = dc_interrupt_set(adev->dm.dc, irq_source, enable) ? 0 : -EBUSY;
 			if (rc)
@@ -3162,6 +3207,13 @@ static void dm_gpureset_toggle_interrupts(struct amdgpu_device *adev,
 			 */
 			if (!dc_interrupt_set(adev->dm.dc, irq_source, enable))
 				drm_warn(adev_to_drm(adev), "Failed to %sable vblank interrupt\n", enable ? "en" : "dis");
+
+		} else if (acrtc && state->stream_status[i].plane_count != 0) {
+			/* DCN only needs to toggle VUPDATE_NO_LOCK */
+			rc = amdgpu_dm_crtc_set_vupdate_irq(&acrtc->base, enable);
+			if (rc)
+				drm_warn(adev_to_drm(adev), "Failed to %sable vupdate interrupt\n",
+					 enable ? "en" : "dis");
 		}
 	}
 
@@ -3290,9 +3342,14 @@ static int dm_suspend(struct amdgpu_ip_block *ip_block)
 	if (amdgpu_in_reset(adev)) {
 		enum dc_status res;
 
+		/* Quiesce ISM workers before taking dc_lock (workers take
+		 * dc_lock themselves; syncing under it would deadlock).
+		 */
+		amdgpu_dm_ism_disable(dm);
+
 		mutex_lock(&dm->dc_lock);
 
-		amdgpu_dm_ism_disable(dm);
+		amdgpu_dm_ism_force_full_power(dm);
 		dc_allow_idle_optimizations(adev->dm.dc, false);
 
 		dm->cached_dc_state = dc_state_create_copy(dm->dc->current_state);
@@ -3326,8 +3383,13 @@ static int dm_suspend(struct amdgpu_ip_block *ip_block)
 
 	amdgpu_dm_irq_suspend(adev);
 
+	/*
+	 * Quiesce ISM workers before taking dc_lock (workers take dc_lock
+	 * themselves; syncing under it would deadlock).
+	 */
+	amdgpu_dm_ism_disable(dm);
 	scoped_guard(mutex, &dm->dc_lock)
-		amdgpu_dm_ism_disable(dm);
+		amdgpu_dm_ism_force_full_power(dm);
 
 	hpd_rx_irq_work_suspend(dm);
 
@@ -3923,6 +3985,8 @@ static void update_connector_ext_caps(struct amdgpu_dm_connector *aconnector)
 	caps->ext_caps = &aconnector->dc_link->dpcd_sink_ext_caps;
 	caps->aux_support = false;
 
+	panel_backlight_quirk = drm_get_panel_backlight_quirk(aconnector->drm_edid);
+
 	if (caps->ext_caps->bits.oled == 1
 	    /*
 	     * ||
@@ -3935,6 +3999,9 @@ static void update_connector_ext_caps(struct amdgpu_dm_connector *aconnector)
 		caps->aux_support = false;
 	else if (amdgpu_backlight == 1)
 		caps->aux_support = true;
+	else if (!IS_ERR_OR_NULL(panel_backlight_quirk) &&
+		 panel_backlight_quirk->force_pwm)
+		caps->aux_support = false;
 	if (caps->aux_support)
 		aconnector->dc_link->backlight_control_type = BACKLIGHT_CONTROL_AMD_AUX;
 
@@ -3950,8 +4017,6 @@ static void update_connector_ext_caps(struct amdgpu_dm_connector *aconnector)
 	else
 		caps->aux_min_input_signal = 1;
 
-	panel_backlight_quirk =
-		drm_get_panel_backlight_quirk(aconnector->drm_edid);
 	if (!IS_ERR_OR_NULL(panel_backlight_quirk)) {
 		if (panel_backlight_quirk->min_brightness) {
 			caps->min_input_signal =
@@ -4717,38 +4782,6 @@ static int dcn10_register_irq_handlers(struct amdgpu_device *adev)
 	 *    for acknowledging and handling.
 	 */
 
-	/* Use VSTARTUP interrupt */
-	for (i = DCN_1_0__SRCID__DC_D1_OTG_VSTARTUP;
-			i <= DCN_1_0__SRCID__DC_D1_OTG_VSTARTUP + adev->mode_info.num_crtc - 1;
-			i++) {
-		r = amdgpu_irq_add_id(adev, SOC15_IH_CLIENTID_DCE, i, &adev->crtc_irq);
-
-		if (r) {
-			drm_err(adev_to_drm(adev), "Failed to add crtc irq id!\n");
-			return r;
-		}
-
-		int_params.int_context = INTERRUPT_HIGH_IRQ_CONTEXT;
-		int_params.irq_source =
-			dc_interrupt_to_irq_source(dc, i, 0);
-
-		if (int_params.irq_source == DC_IRQ_SOURCE_INVALID ||
-			int_params.irq_source  < DC_IRQ_SOURCE_VBLANK1 ||
-			int_params.irq_source  > DC_IRQ_SOURCE_VBLANK6) {
-			drm_err(adev_to_drm(adev), "Failed to register vblank irq!\n");
-			return -EINVAL;
-		}
-
-		c_irq_params = &adev->dm.vblank_params[int_params.irq_source - DC_IRQ_SOURCE_VBLANK1];
-
-		c_irq_params->adev = adev;
-		c_irq_params->irq_src = int_params.irq_source;
-
-		if (!amdgpu_dm_irq_register_interrupt(adev, &int_params,
-			dm_crtc_high_irq, c_irq_params))
-			return -ENOMEM;
-	}
-
 	/* Use otg vertical line interrupt */
 #if defined(CONFIG_DRM_AMD_SECURE_DISPLAY)
 	for (i = 0; i <= adev->mode_info.num_crtc - 1; i++) {
@@ -4820,37 +4853,6 @@ static int dcn10_register_irq_handlers(struct amdgpu_device *adev)
 			return -ENOMEM;
 	}
 
-	/* Use GRPH_PFLIP interrupt */
-	for (i = DCN_1_0__SRCID__HUBP0_FLIP_INTERRUPT;
-			i <= DCN_1_0__SRCID__HUBP0_FLIP_INTERRUPT + dc->caps.max_otg_num - 1;
-			i++) {
-		r = amdgpu_irq_add_id(adev, SOC15_IH_CLIENTID_DCE, i, &adev->pageflip_irq);
-		if (r) {
-			drm_err(adev_to_drm(adev), "Failed to add page flip irq id!\n");
-			return r;
-		}
-
-		int_params.int_context = INTERRUPT_HIGH_IRQ_CONTEXT;
-		int_params.irq_source =
-			dc_interrupt_to_irq_source(dc, i, 0);
-
-		if (int_params.irq_source == DC_IRQ_SOURCE_INVALID ||
-			int_params.irq_source  < DC_IRQ_SOURCE_PFLIP_FIRST ||
-			int_params.irq_source  > DC_IRQ_SOURCE_PFLIP_LAST) {
-			drm_err(adev_to_drm(adev), "Failed to register pflip irq!\n");
-			return -EINVAL;
-		}
-
-		c_irq_params = &adev->dm.pflip_params[int_params.irq_source - DC_IRQ_SOURCE_PFLIP_FIRST];
-
-		c_irq_params->adev = adev;
-		c_irq_params->irq_src = int_params.irq_source;
-
-		if (!amdgpu_dm_irq_register_interrupt(adev, &int_params,
-			dm_pflip_high_irq, c_irq_params))
-			return -ENOMEM;
-	}
-
 	/* HPD */
 	r = amdgpu_irq_add_id(adev, SOC15_IH_CLIENTID_DCE, DCN_1_0__SRCID__DC_HPD1_INT,
 			&adev->hpd_irq);
@@ -5382,11 +5384,11 @@ amdgpu_dm_register_backlight_device(struct amdgpu_dm_connector *aconnector)
 	caps = &dm->backlight_caps[aconnector->bl_idx];
 	if (get_brightness_range(caps, &min, &max)) {
 		if (power_supply_is_system_supplied() > 0)
-			props.brightness = DIV_ROUND_CLOSEST((max - min) * caps->ac_level, 100);
+			props.brightness = DIV_ROUND_CLOSEST(max * caps->ac_level, 100);
 		else
-			props.brightness = DIV_ROUND_CLOSEST((max - min) * caps->dc_level, 100);
+			props.brightness = DIV_ROUND_CLOSEST(max * caps->dc_level, 100);
 		/* min is zero, so max needs to be adjusted */
-		props.max_brightness = max - min;
+		props.max_brightness = max;
 		drm_dbg(drm, "Backlight caps: min: %d, max: %d, ac %d, dc %d\n", min, max,
 			caps->ac_level, caps->dc_level);
 	} else
@@ -6423,8 +6425,8 @@ static void fill_dc_dirty_rects(struct drm_plane *plane,
 {
 	struct dm_crtc_state *dm_crtc_state = to_dm_crtc_state(crtc_state);
 	struct rect *dirty_rects = flip_addrs->dirty_rects;
-	u32 num_clips;
-	struct drm_mode_rect *clips;
+	u32 num_clips = 0;
+	struct drm_mode_rect *clips = NULL;
 	bool bb_changed;
 	bool fb_changed;
 	u32 i = 0;
@@ -6440,8 +6442,10 @@ static void fill_dc_dirty_rects(struct drm_plane *plane,
 	if (new_plane_state->rotation != DRM_MODE_ROTATE_0)
 		goto ffu;
 
-	num_clips = drm_plane_get_damage_clips_count(new_plane_state);
-	clips = drm_plane_get_damage_clips(new_plane_state);
+	if (!new_plane_state->ignore_damage_clips) {
+		num_clips = drm_plane_get_damage_clips_count(new_plane_state);
+		clips = drm_plane_get_damage_clips(new_plane_state);
+	}
 
 	if (num_clips && (!amdgpu_damage_clips || (amdgpu_damage_clips < 0 &&
 						   is_psr_su)))
@@ -9408,21 +9412,9 @@ static void manage_dm_interrupts(struct amdgpu_device *adev,
 	if (acrtc_state) {
 		timing = &acrtc_state->stream->timing;
 
-		if (amdgpu_ip_version(adev, DCE_HWIP, 0) >=
-		      IP_VERSION(3, 2, 0) &&
-		      !(adev->flags & AMD_IS_APU)) {
-			/*
-			 * DGPUs NV3x and newer that support idle optimizations
-			 * experience intermittent flip-done timeouts on cursor
-			 * updates. Restore 5s offdelay behavior for now.
-			 *
-			 * Discussion on the issue:
-			 * https://lore.kernel.org/amd-gfx/20260217191632.1243826-1-sysdadmin@m1k.cloud/
-			 */
-			config.offdelay_ms = 5000;
-			config.disable_immediate = false;
-		} else if (amdgpu_ip_version(adev, DCE_HWIP, 0) <
-			     IP_VERSION(3, 5, 0)) {
+		if (amdgpu_ip_version(adev, DCE_HWIP, 0) <
+			   IP_VERSION(3, 5, 0) ||
+			   !(adev->flags & AMD_IS_APU)) {
 			/*
 			 * Older HW and DGPU have issues with instant off;
 			 * use a 2 frame offdelay.
@@ -9441,14 +9433,22 @@ static void manage_dm_interrupts(struct amdgpu_device *adev,
 
 		drm_crtc_vblank_on_config(&acrtc->base,
 					  &config);
-		/* Allow RX6xxx, RX7700, RX7800 GPUs to call amdgpu_irq_get.*/
+		/*
+		 * Since pflip_high_irq is no longer registered for DCN, grab an
+		 * extra reference to vupdate irq instead to workaround this
+		 * issue:
+		 * https://gitlab.freedesktop.org/drm/amd/-/work_items/3936
+		 *
+		 * The callbacks to drm_vblank_on/off should really take care of
+		 * this though.
+		 */
 		switch (amdgpu_ip_version(adev, DCE_HWIP, 0)) {
 		case IP_VERSION(3, 0, 0):
 		case IP_VERSION(3, 0, 2):
 		case IP_VERSION(3, 0, 3):
 		case IP_VERSION(3, 2, 0):
-			if (amdgpu_irq_get(adev, &adev->pageflip_irq, irq_type))
-				drm_err(dev, "DM_IRQ: Cannot get pageflip irq!\n");
+			if (amdgpu_irq_get(adev, &adev->vupdate_irq, irq_type))
+				drm_err(dev, "DM_IRQ: Cannot get vupdate irq!\n");
 #if defined(CONFIG_DRM_AMD_SECURE_DISPLAY)
 			if (amdgpu_irq_get(adev, &adev->vline0_irq, irq_type))
 				drm_err(dev, "DM_IRQ: Cannot get vline0 irq!\n");
@@ -9466,8 +9466,8 @@ static void manage_dm_interrupts(struct amdgpu_device *adev,
 			if (amdgpu_irq_put(adev, &adev->vline0_irq, irq_type))
 				drm_err(dev, "DM_IRQ: Cannot put vline0 irq!\n");
 #endif
-			if (amdgpu_irq_put(adev, &adev->pageflip_irq, irq_type))
-				drm_err(dev, "DM_IRQ: Cannot put pageflip irq!\n");
+			if (amdgpu_irq_put(adev, &adev->vupdate_irq, irq_type))
+				drm_err(dev, "DM_IRQ: Cannot put vupdate irq!\n");
 		}
 
 		drm_crtc_vblank_off(&acrtc->base);
@@ -9480,6 +9480,10 @@ static void dm_update_pflip_irq_state(struct amdgpu_device *adev,
 	int irq_type =
 		amdgpu_display_crtc_idx_to_irq_type(adev, acrtc->crtc_id);
 
+	/* GRPH_PFLIP is not used on DCN; nothing to reapply. */
+	if (amdgpu_ip_version(adev, DCE_HWIP, 0) != 0)
+		return;
+
 	/**
 	 * This reads the current state for the IRQ and force reapplies
 	 * the setting to hardware.
@@ -9811,9 +9815,13 @@ static void update_stream_irq_parameters(
 static void amdgpu_dm_handle_vrr_transition(struct dm_crtc_state *old_state,
 					    struct dm_crtc_state *new_state)
 {
+	struct amdgpu_device *adev = drm_to_adev(new_state->base.crtc->dev);
 	bool old_vrr_active = amdgpu_dm_crtc_vrr_active(old_state);
 	bool new_vrr_active = amdgpu_dm_crtc_vrr_active(new_state);
 
+	/* Only DCE gates vupdate on VRR, keep it enabled for DCN */
+	bool vrr_gates_vupdate = amdgpu_ip_version(adev, DCE_HWIP, 0) == 0;
+
 	if (!old_vrr_active && new_vrr_active) {
 		/* Transition VRR inactive -> active:
 		 * While VRR is active, we must not disable vblank irq, as a
@@ -9823,7 +9831,8 @@ static void amdgpu_dm_handle_vrr_transition(struct dm_crtc_state *old_state,
 		 * We also need vupdate irq for the actual core vblank handling
 		 * at end of vblank.
 		 */
-		WARN_ON(amdgpu_dm_crtc_set_vupdate_irq(new_state->base.crtc, true) != 0);
+		if (vrr_gates_vupdate)
+			WARN_ON(amdgpu_dm_crtc_set_vupdate_irq(new_state->base.crtc, true) != 0);
 		WARN_ON(drm_crtc_vblank_get(new_state->base.crtc) != 0);
 		drm_dbg_driver(new_state->base.crtc->dev, "%s: crtc=%u VRR off->on: Get vblank ref\n",
 				 __func__, new_state->base.crtc->base.id);
@@ -9831,7 +9840,8 @@ static void amdgpu_dm_handle_vrr_transition(struct dm_crtc_state *old_state,
 		/* Transition VRR active -> inactive:
 		 * Allow vblank irq disable again for fixed refresh rate.
 		 */
-		WARN_ON(amdgpu_dm_crtc_set_vupdate_irq(new_state->base.crtc, false) != 0);
+		if (vrr_gates_vupdate)
+			WARN_ON(amdgpu_dm_crtc_set_vupdate_irq(new_state->base.crtc, false) != 0);
 		drm_crtc_vblank_put(new_state->base.crtc);
 		drm_dbg_driver(new_state->base.crtc->dev, "%s: crtc=%u VRR on->off: Drop vblank ref\n",
 				 __func__, new_state->base.crtc->base.id);
@@ -10007,6 +10017,7 @@ static void amdgpu_dm_commit_planes(struct drm_atomic_state *state,
 	bool vrr_active = amdgpu_dm_crtc_vrr_active(acrtc_state);
 	bool cursor_update = false;
 	bool pflip_present = false;
+	bool immediate_flip = false;
 	bool dirty_rects_changed = false;
 	bool updated_planes_and_streams = false;
 	struct {
@@ -10173,6 +10184,8 @@ static void amdgpu_dm_commit_planes(struct drm_atomic_state *state,
 			acrtc_state->update_type == UPDATE_TYPE_FAST &&
 			get_mem_type(old_plane_state->fb) == get_mem_type(fb);
 
+		immediate_flip |= bundle->flip_addrs[planes_count].flip_immediate;
+
 		timestamp_ns = ktime_get_ns();
 		bundle->flip_addrs[planes_count].flip_timestamp_in_us = div_u64(timestamp_ns, 1000);
 		bundle->surface_updates[planes_count].flip_addr = &bundle->flip_addrs[planes_count];
@@ -10374,6 +10387,29 @@ static void amdgpu_dm_commit_planes(struct drm_atomic_state *state,
 	    acrtc_state->cursor_mode == DM_CURSOR_NATIVE_MODE)
 		amdgpu_dm_commit_cursors(state);
 
+	/*
+	 * On DCN, flip completion is normally delivered from VUPDATE_NO_LOCK.
+	 * However, an immediate (tearing / async) flip is latched by HW right
+	 * away and does not wait for the next vupdate, so deliver its
+	 * completion event here after programming.
+	 *
+	 * On DCE, GRPH_PFLIP already fires immediately for immediate flips, so
+	 * this is DCN-only.
+	 */
+	if (immediate_flip && amdgpu_ip_version(dm->adev, DCE_HWIP, 0) != 0) {
+		spin_lock_irqsave(&pcrtc->dev->event_lock, flags);
+		if (acrtc_attach->pflip_status == AMDGPU_FLIP_SUBMITTED &&
+		    acrtc_attach->event) {
+			drm_crtc_accurate_vblank_count(&acrtc_attach->base);
+			drm_crtc_send_vblank_event(&acrtc_attach->base,
+						   acrtc_attach->event);
+			acrtc_attach->event = NULL;
+			drm_crtc_vblank_put(&acrtc_attach->base);
+			acrtc_attach->pflip_status = AMDGPU_FLIP_NONE;
+		}
+		spin_unlock_irqrestore(&pcrtc->dev->event_lock, flags);
+	}
+
 cleanup:
 	kfree(bundle);
 }
@@ -11708,6 +11744,7 @@ skip_modeset:
 	/* Release extra reference */
 	if (new_stream)
 		dc_stream_release(new_stream);
+	new_stream = NULL;
 
 	/*
 	 * We want to do dc stream updates that do not require a
diff --git linux-libre-7.1.5-gnu/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_crtc.c linux-libre-7.1.6-gnu/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_crtc.c
index d69f5a75b685a..9d5782b4958c0 100644
--- linux-libre-7.1.5-gnu/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_crtc.c
+++ linux-libre-7.1.6-gnu/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_crtc.c
@@ -308,9 +308,25 @@ static inline int amdgpu_dm_crtc_set_vblank(struct drm_crtc *crtc, bool enable)
 			drm_crtc_vblank_restore(crtc);
 	}
 
-	if (dc_supports_vrr(dm->dc->ctx->dce_version)) {
+	/*
+	 * On DCN, VUPDATE_NO_LOCK is the single OTG interrupt used to deliver
+	 * vblank and pageflip completion events, so enable it whenever vblank
+	 * is enabled. On DCE, vupdate is only needed in VRR mode.
+	 */
+	if (amdgpu_ip_version(adev, DCE_HWIP, 0) != 0) {
 		if (enable) {
-			/* vblank irq on -> Only need vupdate irq in vrr mode */
+			rc = amdgpu_irq_get(adev, &adev->vupdate_irq, irq_type);
+			drm_dbg_vbl(crtc->dev, "Get vupdate_irq ret=%d\n", rc);
+		} else {
+			rc = amdgpu_irq_put(adev, &adev->vupdate_irq, irq_type);
+			drm_dbg_vbl(crtc->dev, "Put vupdate_irq ret=%d\n", rc);
+		}
+	} else if (dc_supports_vrr(dm->dc->ctx->dce_version)) {
+		if (enable) {
+			/* vblank irq on -> Only need vupdate irq in vrr mode
+			 * Not ref-counted since we need explicit enable/disable
+			 * for DCE VRR handling
+			 */
 			if (amdgpu_dm_crtc_vrr_active(acrtc_state))
 				rc = amdgpu_dm_crtc_set_vupdate_irq(crtc, true);
 		} else {
@@ -319,39 +335,46 @@ static inline int amdgpu_dm_crtc_set_vblank(struct drm_crtc *crtc, bool enable)
 		}
 	}
 
-	if (rc)
-		return rc;
-
-	/* crtc vblank or vstartup interrupt */
-	if (enable) {
-		rc = amdgpu_irq_get(adev, &adev->crtc_irq, irq_type);
-		drm_dbg_vbl(crtc->dev, "Get crtc_irq ret=%d\n", rc);
-	} else {
-		rc = amdgpu_irq_put(adev, &adev->crtc_irq, irq_type);
-		drm_dbg_vbl(crtc->dev, "Put crtc_irq ret=%d\n", rc);
-	}
-
 	if (rc)
 		return rc;
 
 	/*
-	 * hubp surface flip interrupt
-	 *
-	 * We have no guarantee that the frontend index maps to the same
-	 * backend index - some even map to more than one.
-	 *
-	 * TODO: Use a different interrupt or check DC itself for the mapping.
+	 * VLINE0 (crtc_irq) and GRPH_PFLIP (pageflip_irq) are only used on
+	 * DCE. On DCN, vblank and pageflip completion are delivered from
+	 * VUPDATE_NO_LOCK (enabled above), so don't touch them here.
 	 */
-	if (enable) {
-		rc = amdgpu_irq_get(adev, &adev->pageflip_irq, irq_type);
-		drm_dbg_vbl(crtc->dev, "Get pageflip_irq ret=%d\n", rc);
-	} else {
-		rc = amdgpu_irq_put(adev, &adev->pageflip_irq, irq_type);
-		drm_dbg_vbl(crtc->dev, "Put pageflip_irq ret=%d\n", rc);
-	}
+	if (amdgpu_ip_version(adev, DCE_HWIP, 0) == 0) {
+		/* crtc vblank or vstartup interrupt */
+		if (enable) {
+			rc = amdgpu_irq_get(adev, &adev->crtc_irq, irq_type);
+			drm_dbg_vbl(crtc->dev, "Get crtc_irq ret=%d\n", rc);
+		} else {
+			rc = amdgpu_irq_put(adev, &adev->crtc_irq, irq_type);
+			drm_dbg_vbl(crtc->dev, "Put crtc_irq ret=%d\n", rc);
+		}
 
-	if (rc)
-		return rc;
+		if (rc)
+			return rc;
+
+		/*
+		 * hubp surface flip interrupt
+		 *
+		 * We have no guarantee that the frontend index maps to the same
+		 * backend index - some even map to more than one.
+		 *
+		 * TODO: Use a different interrupt or check DC itself for the mapping.
+		 */
+		if (enable) {
+			rc = amdgpu_irq_get(adev, &adev->pageflip_irq, irq_type);
+			drm_dbg_vbl(crtc->dev, "Get pageflip_irq ret=%d\n", rc);
+		} else {
+			rc = amdgpu_irq_put(adev, &adev->pageflip_irq, irq_type);
+			drm_dbg_vbl(crtc->dev, "Put pageflip_irq ret=%d\n", rc);
+		}
+
+		if (rc)
+			return rc;
+	}
 
 #if defined(CONFIG_DRM_AMD_SECURE_DISPLAY)
 	/* crtc vline0 interrupt, only available on DCN+ */
diff --git linux-libre-7.1.5-gnu/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_ism.c linux-libre-7.1.6-gnu/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_ism.c
index a64e95860e99b..b32c8d3ac1523 100644
--- linux-libre-7.1.5-gnu/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_ism.c
+++ linux-libre-7.1.6-gnu/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_ism.c
@@ -524,13 +524,20 @@ static void dm_ism_sso_delayed_work_func(struct work_struct *work)
 }
 
 /**
- * amdgpu_dm_ism_disable - Disable the ISM
+ * amdgpu_dm_ism_disable - Quiesce ISM workers
  *
  * @dm: The amdgpu display manager
  *
- * Disable the idle state manager by disabling any ISM work, canceling pending
- * work, and waiting for in-progress work to finish. After disabling, the system
- * is left in DM_ISM_STATE_FULL_POWER_RUNNING state.
+ * Cancels and disables any pending or in-flight ISM delayed work and waits
+ * for in-progress work to finish. After this returns, no ISM worker can run
+ * and subsequent mod_delayed_work() calls become no-ops via
+ * clear_pending_if_disabled().
+ *
+ * Must NOT be called with dc_lock held: the workers themselves take dc_lock,
+ * so a synchronous wait under dc_lock would deadlock.
+ *
+ * The caller is responsible for driving the FSM back to FULL_POWER_RUNNING
+ * (under dc_lock) by calling amdgpu_dm_ism_force_full_power().
  */
 void amdgpu_dm_ism_disable(struct amdgpu_display_manager *dm)
 {
@@ -538,21 +545,54 @@ void amdgpu_dm_ism_disable(struct amdgpu_display_manager *dm)
 	struct amdgpu_crtc *acrtc;
 	struct amdgpu_dm_ism *ism;
 
-	ASSERT(mutex_is_locked(&dm->dc_lock));
+	/*
+	 * Caller must NOT hold dc_lock: the ISM delayed work handlers
+	 * acquire dc_lock themselves, so waiting for them via
+	 * disable_delayed_work_sync() while holding dc_lock would
+	 * self-deadlock against an in-flight worker.
+	 */
+	lockdep_assert_not_held(&dm->dc_lock);
 
 	drm_for_each_crtc(crtc, dm->ddev) {
 		acrtc = to_amdgpu_crtc(crtc);
 		ism = &acrtc->ism;
 
-		/* Cancel and disable any pending work */
 		disable_delayed_work_sync(&ism->delayed_work);
 		disable_delayed_work_sync(&ism->sso_delayed_work);
+	}
+}
+
+/**
+ * amdgpu_dm_ism_force_full_power - Force every CRTC's ISM FSM to FULL_POWER
+ *
+ * @dm: The amdgpu display manager
+ *
+ * Sends DM_ISM_EVENT_EXIT_IDLE_REQUESTED to every CRTC's ISM, leaving each
+ * FSM in FULL_POWER_RUNNING. Intended to be paired with
+ * amdgpu_dm_ism_disable(): callers should first quiesce workers (without
+ * dc_lock), then take dc_lock and call this helper.
+ *
+ * Must be called with dc_lock held.
+ */
+void amdgpu_dm_ism_force_full_power(struct amdgpu_display_manager *dm)
+{
+	struct drm_crtc *crtc;
+	struct amdgpu_crtc *acrtc;
+
+	/*
+	 * Caller must hold dc_lock: commit_event() drives the FSM and
+	 * may touch dc state via dc_allow_idle_optimizations() etc.
+	 */
+	lockdep_assert_held(&dm->dc_lock);
+
+	drm_for_each_crtc(crtc, dm->ddev) {
+		acrtc = to_amdgpu_crtc(crtc);
 
 		/*
 		 * When disabled, leave in FULL_POWER_RUNNING state.
-		 * EXIT_IDLE will not queue any work
+		 * EXIT_IDLE will not queue any work.
 		 */
-		amdgpu_dm_ism_commit_event(ism,
+		amdgpu_dm_ism_commit_event(&acrtc->ism,
 					   DM_ISM_EVENT_EXIT_IDLE_REQUESTED);
 	}
 }
diff --git linux-libre-7.1.5-gnu/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_ism.h linux-libre-7.1.6-gnu/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_ism.h
index fde0ddc8d4e4b..964408cd9a839 100644
--- linux-libre-7.1.5-gnu/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_ism.h
+++ linux-libre-7.1.6-gnu/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_ism.h
@@ -146,6 +146,7 @@ void amdgpu_dm_ism_fini(struct amdgpu_dm_ism *ism);
 void amdgpu_dm_ism_commit_event(struct amdgpu_dm_ism *ism,
 				enum amdgpu_dm_ism_event event);
 void amdgpu_dm_ism_disable(struct amdgpu_display_manager *dm);
+void amdgpu_dm_ism_force_full_power(struct amdgpu_display_manager *dm);
 void amdgpu_dm_ism_enable(struct amdgpu_display_manager *dm);
 
 #endif
diff --git linux-libre-7.1.5-gnu/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn31/dcn31_clk_mgr.c linux-libre-7.1.6-gnu/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn31/dcn31_clk_mgr.c
index 89fc482947eff..4951570720791 100644
--- linux-libre-7.1.5-gnu/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn31/dcn31_clk_mgr.c
+++ linux-libre-7.1.6-gnu/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn31/dcn31_clk_mgr.c
@@ -155,7 +155,6 @@ void dcn31_update_clocks(struct clk_mgr *clk_mgr_base,
 		if (new_clocks->zstate_support != DCN_ZSTATE_SUPPORT_DISALLOW &&
 				new_clocks->zstate_support != clk_mgr_base->clks.zstate_support) {
 			dcn31_smu_set_zstate_support(clk_mgr, new_clocks->zstate_support);
-			dm_helpers_enable_periodic_detection(clk_mgr_base->ctx, true);
 			clk_mgr_base->clks.zstate_support = new_clocks->zstate_support;
 		}
 
@@ -181,7 +180,6 @@ void dcn31_update_clocks(struct clk_mgr *clk_mgr_base,
 		if (new_clocks->zstate_support == DCN_ZSTATE_SUPPORT_DISALLOW &&
 				new_clocks->zstate_support != clk_mgr_base->clks.zstate_support) {
 			dcn31_smu_set_zstate_support(clk_mgr, DCN_ZSTATE_SUPPORT_DISALLOW);
-			dm_helpers_enable_periodic_detection(clk_mgr_base->ctx, false);
 			clk_mgr_base->clks.zstate_support = new_clocks->zstate_support;
 		}
 
diff --git linux-libre-7.1.5-gnu/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn314/dcn314_clk_mgr.c linux-libre-7.1.6-gnu/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn314/dcn314_clk_mgr.c
index b08a70a2f571d..9b9524fde2b98 100644
--- linux-libre-7.1.5-gnu/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn314/dcn314_clk_mgr.c
+++ linux-libre-7.1.6-gnu/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn314/dcn314_clk_mgr.c
@@ -227,7 +227,6 @@ void dcn314_update_clocks(struct clk_mgr *clk_mgr_base,
 		if (new_clocks->zstate_support != DCN_ZSTATE_SUPPORT_DISALLOW &&
 				new_clocks->zstate_support != clk_mgr_base->clks.zstate_support) {
 			dcn314_smu_set_zstate_support(clk_mgr, new_clocks->zstate_support);
-			dm_helpers_enable_periodic_detection(clk_mgr_base->ctx, true);
 			clk_mgr_base->clks.zstate_support = new_clocks->zstate_support;
 		}
 
@@ -252,7 +251,6 @@ void dcn314_update_clocks(struct clk_mgr *clk_mgr_base,
 		if (new_clocks->zstate_support == DCN_ZSTATE_SUPPORT_DISALLOW &&
 				new_clocks->zstate_support != clk_mgr_base->clks.zstate_support) {
 			dcn314_smu_set_zstate_support(clk_mgr, DCN_ZSTATE_SUPPORT_DISALLOW);
-			dm_helpers_enable_periodic_detection(clk_mgr_base->ctx, false);
 			clk_mgr_base->clks.zstate_support = new_clocks->zstate_support;
 		}
 
diff --git linux-libre-7.1.5-gnu/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn32/dcn32_clk_mgr.c linux-libre-7.1.6-gnu/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn32/dcn32_clk_mgr.c
index fda6cade30a8d..e2787c7084ec0 100644
--- linux-libre-7.1.5-gnu/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn32/dcn32_clk_mgr.c
+++ linux-libre-7.1.6-gnu/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn32/dcn32_clk_mgr.c
@@ -276,13 +276,20 @@ static void dcn32_update_clocks_update_dtb_dto(struct clk_mgr_internal *clk_mgr,
 		struct dtbclk_dto_params dto_params = {0};
 
 		/* use mask to program DTO once per tg */
-		if (pipe_ctx->stream_res.tg &&
+		if (pipe_ctx->stream && pipe_ctx->stream_res.tg &&
 				!(tg_mask & (1 << pipe_ctx->stream_res.tg->inst))) {
 			tg_mask |= (1 << pipe_ctx->stream_res.tg->inst);
 
 			dto_params.otg_inst = pipe_ctx->stream_res.tg->inst;
 			dto_params.ref_dtbclk_khz = ref_dtbclk_khz;
 
+			if (dccg->ctx->dc->link_srv->dp_is_128b_132b_signal(pipe_ctx))
+				dto_params.pixclk_khz = pipe_ctx->stream->timing.pix_clk_100hz / 10;
+
+			if (dc_is_hdmi_signal(pipe_ctx->stream->signal) ||
+					dc_is_dvi_signal(pipe_ctx->stream->signal))
+				dto_params.is_hdmi = true;
+
 			dccg->funcs->set_dtbclk_dto(clk_mgr->dccg, &dto_params);
 			//dccg->funcs->set_audio_dtbclk_dto(clk_mgr->dccg, &dto_params);
 		}
diff --git linux-libre-7.1.5-gnu/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn35/dcn35_clk_mgr.c linux-libre-7.1.6-gnu/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn35/dcn35_clk_mgr.c
index 2798088842f41..020d43c7fab85 100644
--- linux-libre-7.1.5-gnu/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn35/dcn35_clk_mgr.c
+++ linux-libre-7.1.6-gnu/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn35/dcn35_clk_mgr.c
@@ -264,13 +264,20 @@ static void dcn35_update_clocks_update_dtb_dto(struct clk_mgr_internal *clk_mgr,
 		struct dtbclk_dto_params dto_params = {0};
 
 		/* use mask to program DTO once per tg */
-		if (pipe_ctx->stream_res.tg &&
+		if (pipe_ctx->stream && pipe_ctx->stream_res.tg &&
 				!(tg_mask & (1 << pipe_ctx->stream_res.tg->inst))) {
 			tg_mask |= (1 << pipe_ctx->stream_res.tg->inst);
 
 			dto_params.otg_inst = pipe_ctx->stream_res.tg->inst;
 			dto_params.ref_dtbclk_khz = ref_dtbclk_khz;
 
+			if (dccg->ctx->dc->link_srv->dp_is_128b_132b_signal(pipe_ctx))
+				dto_params.pixclk_khz = pipe_ctx->stream->timing.pix_clk_100hz / 10;
+
+			if (dc_is_hdmi_signal(pipe_ctx->stream->signal) ||
+					dc_is_dvi_signal(pipe_ctx->stream->signal))
+				dto_params.is_hdmi = true;
+
 			dccg->funcs->set_dtbclk_dto(clk_mgr->dccg, &dto_params);
 			//dccg->funcs->set_audio_dtbclk_dto(clk_mgr->dccg, &dto_params);
 		}
@@ -405,6 +412,7 @@ void dcn35_update_clocks(struct clk_mgr *clk_mgr_base,
 		if (new_clocks->zstate_support != DCN_ZSTATE_SUPPORT_DISALLOW &&
 				new_clocks->zstate_support != clk_mgr_base->clks.zstate_support) {
 			dcn35_smu_set_zstate_support(clk_mgr, new_clocks->zstate_support);
+			dm_helpers_enable_periodic_detection(clk_mgr_base->ctx, true);
 			clk_mgr_base->clks.zstate_support = new_clocks->zstate_support;
 		}
 
@@ -424,6 +432,7 @@ void dcn35_update_clocks(struct clk_mgr *clk_mgr_base,
 		if (new_clocks->zstate_support == DCN_ZSTATE_SUPPORT_DISALLOW &&
 				new_clocks->zstate_support != clk_mgr_base->clks.zstate_support) {
 			dcn35_smu_set_zstate_support(clk_mgr, DCN_ZSTATE_SUPPORT_DISALLOW);
+			dm_helpers_enable_periodic_detection(clk_mgr_base->ctx, false);
 			clk_mgr_base->clks.zstate_support = new_clocks->zstate_support;
 		}
 
diff --git linux-libre-7.1.5-gnu/drivers/gpu/drm/amd/display/dc/core/dc.c linux-libre-7.1.6-gnu/drivers/gpu/drm/amd/display/dc/core/dc.c
index 5f2c62fcba9bf..ec194dd3b7985 100644
--- linux-libre-7.1.5-gnu/drivers/gpu/drm/amd/display/dc/core/dc.c
+++ linux-libre-7.1.6-gnu/drivers/gpu/drm/amd/display/dc/core/dc.c
@@ -1507,7 +1507,7 @@ static void disable_vbios_mode_if_required(
 
 struct dc *dc_create(const struct dc_init_data *init_params)
 {
-	struct dc *dc = kzalloc_obj(*dc);
+	struct dc *dc = kvzalloc_obj(*dc);
 	unsigned int full_pipe_count;
 
 	if (!dc)
@@ -1555,7 +1555,7 @@ struct dc *dc_create(const struct dc_init_data *init_params)
 
 destruct_dc:
 	dc_destruct(dc);
-	kfree(dc);
+	kvfree(dc);
 	return NULL;
 }
 
@@ -1604,7 +1604,7 @@ void dc_deinit_callbacks(struct dc *dc)
 void dc_destroy(struct dc **dc)
 {
 	dc_destruct(*dc);
-	kfree(*dc);
+	kvfree(*dc);
 	*dc = NULL;
 }
 
diff --git linux-libre-7.1.5-gnu/drivers/gpu/drm/amd/display/dc/dc.h linux-libre-7.1.6-gnu/drivers/gpu/drm/amd/display/dc/dc.h
index 55152f12af48b..61a28e287c1b9 100644
--- linux-libre-7.1.5-gnu/drivers/gpu/drm/amd/display/dc/dc.h
+++ linux-libre-7.1.6-gnu/drivers/gpu/drm/amd/display/dc/dc.h
@@ -1727,6 +1727,8 @@ struct dc_scratch_space {
 		bool dp_skip_DID2;
 		bool dp_skip_reset_segment;
 		bool dp_skip_fs_144hz;
+		/* Some DP bridges don't work with RBR and must use HBR. */
+		bool dp_skip_rbr;
 		bool dp_mot_reset_segment;
 		/* Some USB4 docks do not handle turning off MST DSC once it has been enabled. */
 		bool dpia_mst_dsc_always_on;
diff --git linux-libre-7.1.5-gnu/drivers/gpu/drm/amd/display/dc/dce/dce_stream_encoder.c linux-libre-7.1.6-gnu/drivers/gpu/drm/amd/display/dc/dce/dce_stream_encoder.c
index ed407e779c127..2c3a20d35fe9b 100644
--- linux-libre-7.1.5-gnu/drivers/gpu/drm/amd/display/dc/dce/dce_stream_encoder.c
+++ linux-libre-7.1.6-gnu/drivers/gpu/drm/amd/display/dc/dce/dce_stream_encoder.c
@@ -271,7 +271,6 @@ static void dce110_stream_encoder_dp_set_stream_attribute(
 	bool use_vsc_sdp_for_colorimetry,
 	uint32_t enable_sdp_splitting)
 {
-	(void)use_vsc_sdp_for_colorimetry;
 	(void)enable_sdp_splitting;
 	uint32_t h_active_start;
 	uint32_t v_active_start;
@@ -334,6 +333,16 @@ static void dce110_stream_encoder_dp_set_stream_attribute(
 	if (REG(DP_MSA_MISC))
 		misc1 = REG_READ(DP_MSA_MISC);
 
+	/* For YCbCr420 and BT2020 Colorimetry Formats, VSC SDP shall be used.
+	 * When MISC1, bit 6, is Set to 1, a Source device uses a VSC SDP to indicate the
+	 * Pixel Encoding/Colorimetry Format and that a Sink device shall ignore MISC1, bit 7,
+	 * and MISC0, bits 7:1 (MISC1, bit 7, and MISC0, bits 7:1, become "don't care").
+	 */
+	if (use_vsc_sdp_for_colorimetry)
+		misc1 = misc1 | 0x40;
+	else
+		misc1 = misc1 & ~0x40;
+
 	/* set color depth */
 
 	switch (hw_crtc_timing.display_color_depth) {
@@ -499,6 +508,10 @@ static void dce110_stream_encoder_dp_set_stream_attribute(
 				hw_crtc_timing.h_addressable + hw_crtc_timing.h_border_right,
 				DP_MSA_VHEIGHT, hw_crtc_timing.v_border_top +
 				hw_crtc_timing.v_addressable + hw_crtc_timing.v_border_bottom);
+	} else {
+		/* DCE-only path */
+		if (REG(DP_MSA_MISC))
+			REG_WRITE(DP_MSA_MISC, misc1);   /* MSA_MISC1 */
 	}
 }
 
diff --git linux-libre-7.1.5-gnu/drivers/gpu/drm/amd/display/dc/dce/dce_stream_encoder.h linux-libre-7.1.6-gnu/drivers/gpu/drm/amd/display/dc/dce/dce_stream_encoder.h
index 342c0afe6a949..88d6044904d1f 100644
--- linux-libre-7.1.5-gnu/drivers/gpu/drm/amd/display/dc/dce/dce_stream_encoder.h
+++ linux-libre-7.1.6-gnu/drivers/gpu/drm/amd/display/dc/dce/dce_stream_encoder.h
@@ -96,7 +96,8 @@
 
 #define SE_COMMON_REG_LIST(id)\
 	SE_COMMON_REG_LIST_DCE_BASE(id), \
-	SRI(AFMT_CNTL, DIG, id)
+	SRI(AFMT_CNTL, DIG, id), \
+	SRI(DP_MSA_MISC, DP, id)
 
 #define SE_DCN_REG_LIST(id)\
 	SE_COMMON_REG_LIST_BASE(id),\
diff --git linux-libre-7.1.5-gnu/drivers/gpu/drm/amd/display/dc/link/link_detection.c linux-libre-7.1.6-gnu/drivers/gpu/drm/amd/display/dc/link/link_detection.c
index 794dd6a959183..2ba323e6c3f7d 100644
--- linux-libre-7.1.5-gnu/drivers/gpu/drm/amd/display/dc/link/link_detection.c
+++ linux-libre-7.1.6-gnu/drivers/gpu/drm/amd/display/dc/link/link_detection.c
@@ -621,7 +621,7 @@ static bool detect_dp(struct dc_link *link,
 		link->dpcd_caps.sink_count.bits.SINK_COUNT = 1;
 		/* NUTMEG requires that we use HBR, doesn't work with RBR. */
 		if (link->dpcd_caps.branch_dev_id == DP_BRANCH_DEVICE_ID_00001A)
-			link->preferred_link_setting.link_rate = LINK_RATE_HIGH;
+			link->wa_flags.dp_skip_rbr = true;
 	}
 
 	return true;
@@ -1069,8 +1069,11 @@ static bool detect_link_and_local_sink(struct dc_link *link,
 			    link->link_enc->features.flags.bits.DP_IS_USB_C == 1) {
 
 				/* if alt mode times out, return false */
-				if (!wait_for_entering_dp_alt_mode(link))
+				if (!wait_for_entering_dp_alt_mode(link)) {
+					if (prev_sink)
+						dc_sink_release(prev_sink);
 					return false;
+				}
 			}
 
 			if (!detect_dp(link, &sink_caps, reason)) {
diff --git linux-libre-7.1.5-gnu/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_capability.c linux-libre-7.1.6-gnu/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_capability.c
index 782a45caa13d4..fe8420b803eed 100644
--- linux-libre-7.1.5-gnu/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_capability.c
+++ linux-libre-7.1.6-gnu/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_capability.c
@@ -750,8 +750,10 @@ static bool decide_dp_link_settings(struct dc_link *link, struct dc_link_setting
 	if (req_bw > dp_link_bandwidth_kbps(link, &link->verified_link_cap))
 		return false;
 
-	if (link->preferred_link_setting.link_rate != LINK_RATE_UNKNOWN)
-		initial_link_setting.link_rate = link->preferred_link_setting.link_rate;
+	if (link->wa_flags.dp_skip_rbr) {
+		initial_link_setting.link_rate = LINK_RATE_HIGH;
+		current_link_setting.link_rate = LINK_RATE_HIGH;
+	}
 
 	/* search for the minimum link setting that:
 	 * 1. is supported according to the link training result
diff --git linux-libre-7.1.5-gnu/drivers/gpu/drm/amd/display/dc/resource/dce100/dce100_resource.c linux-libre-7.1.6-gnu/drivers/gpu/drm/amd/display/dc/resource/dce100/dce100_resource.c
index caafebe921299..3f9228033cd0b 100644
--- linux-libre-7.1.5-gnu/drivers/gpu/drm/amd/display/dc/resource/dce100/dce100_resource.c
+++ linux-libre-7.1.6-gnu/drivers/gpu/drm/amd/display/dc/resource/dce100/dce100_resource.c
@@ -992,6 +992,11 @@ struct stream_encoder *dce100_find_first_free_match_stream_enc_for_link(
 	for (i = 0; i < pool->stream_enc_count; i++) {
 		if (!res_ctx->is_stream_enc_acquired[i] &&
 				pool->stream_enc[i]) {
+			/* DP/MST needs a digital encoder; skip analog/no-DP encoders */
+			if (dc_is_dp_signal(stream->signal) &&
+			    (!pool->stream_enc[i]->funcs ||
+			     !pool->stream_enc[i]->funcs->dp_set_stream_attribute))
+				continue;
 			/* Store first available for MST second display
 			 * in daisy chain use case
 			 */
@@ -1014,7 +1019,7 @@ struct stream_encoder *dce100_find_first_free_match_stream_enc_for_link(
 	 * required for non DP connectors.
 	 */
 
-	if (j >= 0 && link->connector_signal == SIGNAL_TYPE_DISPLAY_PORT)
+	if (j >= 0 && dc_is_dp_signal(stream->signal))
 		return pool->stream_enc[j];
 
 	return NULL;
diff --git linux-libre-7.1.5-gnu/drivers/gpu/drm/amd/display/modules/info_packet/info_packet.c linux-libre-7.1.6-gnu/drivers/gpu/drm/amd/display/modules/info_packet/info_packet.c
index 614db22d62f38..00473c6284d5c 100644
--- linux-libre-7.1.5-gnu/drivers/gpu/drm/amd/display/modules/info_packet/info_packet.c
+++ linux-libre-7.1.6-gnu/drivers/gpu/drm/amd/display/modules/info_packet/info_packet.c
@@ -502,8 +502,6 @@ void mod_build_vsc_infopacket(const struct dc_stream_state *stream,
  *
  *  @stream:      contains data we may need to construct VSIF (i.e. timing_3d_format, etc.)
  *  @info_packet: output structure where to store VSIF
- *  @ALLMEnabled: indicates whether ALLM HF-VSIF should be generated
- *  @ALLMValue:   ALLM bit value to advertise in HF-VSIF
  */
 void mod_build_hf_vsif_infopacket(const struct dc_stream_state *stream,
 		struct dc_info_packet *info_packet)
diff --git linux-libre-7.1.5-gnu/drivers/gpu/drm/amd/include/mes_v11_api_def.h linux-libre-7.1.6-gnu/drivers/gpu/drm/amd/include/mes_v11_api_def.h
index f9629d42ada27..7808147ada38c 100644
--- linux-libre-7.1.5-gnu/drivers/gpu/drm/amd/include/mes_v11_api_def.h
+++ linux-libre-7.1.6-gnu/drivers/gpu/drm/amd/include/mes_v11_api_def.h
@@ -427,6 +427,7 @@ union MESAPI__SUSPEND {
 		uint32_t		suspend_fence_value;
 
 		struct MES_API_STATUS	api_status;
+		uint32_t		doorbell_offset;
 	};
 
 	uint32_t	max_dwords_in_api[API_FRAME_SIZE_IN_DWORDS];
@@ -444,6 +445,7 @@ union MESAPI__RESUME {
 		uint64_t		gang_context_addr;
 
 		struct MES_API_STATUS	api_status;
+		uint32_t		doorbell_offset;
 	};
 
 	uint32_t	max_dwords_in_api[API_FRAME_SIZE_IN_DWORDS];
diff --git linux-libre-7.1.5-gnu/drivers/gpu/drm/amd/pm/amdgpu_pm.c linux-libre-7.1.6-gnu/drivers/gpu/drm/amd/pm/amdgpu_pm.c
index 952391aecf2d3..8915a4d18ffa9 100644
--- linux-libre-7.1.5-gnu/drivers/gpu/drm/amd/pm/amdgpu_pm.c
+++ linux-libre-7.1.6-gnu/drivers/gpu/drm/amd/pm/amdgpu_pm.c
@@ -41,6 +41,8 @@
 
 #define DEVICE_ATTR_IS(_name)		(attr_id == device_attr_id__##_name)
 
+#define power_2_mwatt(power)	(((power) >> 8) * 1000 + ((power) & 0xff))
+
 struct od_attribute {
 	struct kobj_attribute	attribute;
 	struct list_head	entry;
@@ -2680,6 +2682,11 @@ static int default_attr_update(struct amdgpu_device *adev, struct amdgpu_device_
 		     gc_ver != IP_VERSION(9, 4, 3)) ||
 		    gc_ver < IP_VERSION(9, 0, 0))
 			*states = ATTR_STATE_UNSUPPORTED;
+
+		if (adev->scpm_enabled) {
+			dev_attr->attr.mode &= ~S_IWUGO;
+			dev_attr->store = NULL;
+		}
 	} else if (DEVICE_ATTR_IS(gpu_metrics)) {
 		if (gc_ver < IP_VERSION(9, 1, 0))
 			*states = ATTR_STATE_UNSUPPORTED;
@@ -3333,7 +3340,6 @@ static int amdgpu_hwmon_get_power(struct device *dev,
 				  enum amd_pp_sensors sensor)
 {
 	struct amdgpu_device *adev = dev_get_drvdata(dev);
-	unsigned int uw;
 	u32 query = 0;
 	int r;
 
@@ -3342,9 +3348,7 @@ static int amdgpu_hwmon_get_power(struct device *dev,
 		return r;
 
 	/* convert to microwatts */
-	uw = (query >> 8) * 1000000 + (query & 0xff) * 1000;
-
-	return uw;
+	return power_2_mwatt(query) * 1000;
 }
 
 static ssize_t amdgpu_hwmon_show_power_avg(struct device *dev,
@@ -4882,7 +4886,7 @@ static int amdgpu_debugfs_pm_info_pp(struct seq_file *m, struct amdgpu_device *a
 {
 	uint32_t mp1_ver = amdgpu_ip_version(adev, MP1_HWIP, 0);
 	uint32_t gc_ver = amdgpu_ip_version(adev, GC_HWIP, 0);
-	uint32_t value;
+	uint32_t value, mwatt, centiwatt;
 	uint64_t value64 = 0;
 	uint32_t query = 0;
 	int size;
@@ -4907,17 +4911,21 @@ static int amdgpu_debugfs_pm_info_pp(struct seq_file *m, struct amdgpu_device *a
 		seq_printf(m, "\t%u mV (VDDNB)\n", value);
 	size = sizeof(uint32_t);
 	if (!amdgpu_dpm_read_sensor(adev, AMDGPU_PP_SENSOR_GPU_AVG_POWER, (void *)&query, &size)) {
+		mwatt = power_2_mwatt(query);
+		centiwatt = DIV_ROUND_CLOSEST(mwatt, 10);
 		if (adev->flags & AMD_IS_APU)
-			seq_printf(m, "\t%u.%02u W (average SoC including CPU)\n", query >> 8, query & 0xff);
+			seq_printf(m, "\t%u.%02u W (average SoC including CPU)\n", centiwatt / 100, centiwatt % 100);
 		else
-			seq_printf(m, "\t%u.%02u W (average SoC)\n", query >> 8, query & 0xff);
+			seq_printf(m, "\t%u.%02u W (average SoC)\n", centiwatt / 100, centiwatt % 100);
 	}
 	size = sizeof(uint32_t);
 	if (!amdgpu_dpm_read_sensor(adev, AMDGPU_PP_SENSOR_GPU_INPUT_POWER, (void *)&query, &size)) {
+		mwatt = power_2_mwatt(query);
+		centiwatt = DIV_ROUND_CLOSEST(mwatt, 10);
 		if (adev->flags & AMD_IS_APU)
-			seq_printf(m, "\t%u.%02u W (current SoC including CPU)\n", query >> 8, query & 0xff);
+			seq_printf(m, "\t%u.%02u W (current SoC including CPU)\n", centiwatt / 100, centiwatt % 100);
 		else
-			seq_printf(m, "\t%u.%02u W (current SoC)\n", query >> 8, query & 0xff);
+			seq_printf(m, "\t%u.%02u W (current SoC)\n", centiwatt / 100, centiwatt % 100);
 	}
 	size = sizeof(value);
 	seq_printf(m, "\n");
diff --git linux-libre-7.1.5-gnu/drivers/gpu/drm/amd/pm/powerplay/hwmgr/hwmgr.c linux-libre-7.1.6-gnu/drivers/gpu/drm/amd/pm/powerplay/hwmgr/hwmgr.c
index 1d6e30269d567..4d553be56396f 100644
--- linux-libre-7.1.5-gnu/drivers/gpu/drm/amd/pm/powerplay/hwmgr/hwmgr.c
+++ linux-libre-7.1.6-gnu/drivers/gpu/drm/amd/pm/powerplay/hwmgr/hwmgr.c
@@ -106,11 +106,8 @@ int hwmgr_early_init(struct pp_hwmgr *hwmgr)
 		hwmgr->od_enabled = false;
 		switch (hwmgr->chip_id) {
 		case CHIP_BONAIRE:
-			/* R9 M380 in iMac 2015: SMU hangs when enabling MCLK DPM
-			 * R7 260X cards with old MC ucode: MCLK DPM is unstable
-			 */
-			if (adev->pdev->subsystem_vendor == 0x106B ||
-			    adev->pdev->device == 0x6658) {
+			/* R9 M380 in iMac 2015: SMU hangs when enabling MCLK DPM */
+			if (adev->pdev->subsystem_vendor == 0x106B) {
 				dev_info(adev->dev, "disabling MCLK DPM on quirky ASIC");
 				adev->pm.pp_feature &= ~PP_MCLK_DPM_MASK;
 				hwmgr->feature_mask &= ~PP_MCLK_DPM_MASK;
diff --git linux-libre-7.1.5-gnu/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c linux-libre-7.1.6-gnu/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c
index 8faf7de7aaa9a..f65bb1dc44ac9 100644
--- linux-libre-7.1.5-gnu/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c
+++ linux-libre-7.1.6-gnu/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c
@@ -1365,6 +1365,14 @@ static void smu_feature_cap_init(struct smu_context *smu)
 	bitmap_zero(fea_cap->cap_map, SMU_FEATURE_CAP_ID__COUNT);
 }
 
+static int smu_set_power_dep(struct smu_context *smu, bool enable)
+{
+	if (!smu->ppt_funcs->set_power_dep)
+		return 0;
+
+	return smu->ppt_funcs->set_power_dep(smu, enable);
+}
+
 static int smu_sw_init(struct amdgpu_ip_block *ip_block)
 {
 	struct amdgpu_device *adev = ip_block->adev;
@@ -1426,6 +1434,8 @@ static int smu_sw_init(struct amdgpu_ip_block *ip_block)
 	if (!smu->ppt_funcs->get_fan_control_mode)
 		smu->adev->pm.no_fan = true;
 
+	smu_set_power_dep(smu, true);
+
 	return 0;
 }
 
@@ -1448,6 +1458,8 @@ static int smu_sw_fini(struct amdgpu_ip_block *ip_block)
 
 	smu_fini_microcode(smu);
 
+	smu_set_power_dep(smu, false);
+
 	return 0;
 }
 
diff --git linux-libre-7.1.5-gnu/drivers/gpu/drm/amd/pm/swsmu/inc/amdgpu_smu.h linux-libre-7.1.6-gnu/drivers/gpu/drm/amd/pm/swsmu/inc/amdgpu_smu.h
index d76e0b005308f..e3a89e9a9df41 100644
--- linux-libre-7.1.5-gnu/drivers/gpu/drm/amd/pm/swsmu/inc/amdgpu_smu.h
+++ linux-libre-7.1.6-gnu/drivers/gpu/drm/amd/pm/swsmu/inc/amdgpu_smu.h
@@ -749,6 +749,9 @@ struct smu_context {
 	bool pm_enabled;
 	bool is_apu;
 
+	/* Power dependency link from an integrated xHCI controller to the GPU */
+	struct device_link		*usb_power_link;
+
 	uint32_t smc_driver_if_version;
 	uint32_t smc_fw_if_version;
 	uint32_t smc_fw_version;
@@ -1648,12 +1651,19 @@ struct pptable_funcs {
 	int (*ras_send_msg)(struct smu_context *smu,
 			    enum smu_message_type msg, uint32_t param, uint32_t *read_arg);
 
-
 	/**
 	 * @get_ras_smu_drv: Get RAS smu driver interface
 	 * Return: ras_smu_drv *
 	 */
 	int (*get_ras_smu_drv)(struct smu_context *smu, const struct ras_smu_drv **ras_smu_drv);
+
+	/**
+	 * @set_power_dep: Create or destroy a power dependency link
+	 * from an integrated xHCI controller to the GPU so that the GPU is
+	 * resumed before the USB controller during PM resume. @enable is true
+	 * to create the link and false to tear it down.
+	 */
+	int (*set_power_dep)(struct smu_context *smu, bool enable);
 };
 
 typedef enum {
diff --git linux-libre-7.1.5-gnu/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_0_ppt.c linux-libre-7.1.6-gnu/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_0_ppt.c
index 7f8d4bb47d02e..acbd7046d8a50 100644
--- linux-libre-7.1.5-gnu/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_0_ppt.c
+++ linux-libre-7.1.6-gnu/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_0_ppt.c
@@ -2403,11 +2403,14 @@ static int smu_v13_0_0_get_power_limit(struct smu_context *smu,
 	uint32_t pp_limit = smu->adev->pm.ac_power ?
 			      skutable->SocketPowerLimitAc[PPT_THROTTLER_PPT0] :
 			      skutable->SocketPowerLimitDc[PPT_THROTTLER_PPT0];
-	uint32_t power_limit = 0, od_percent_upper = 0, od_percent_lower = 0;
+	uint32_t msg_limit = skutable->MsgLimits.Power[PPT_THROTTLER_PPT0][POWER_SOURCE_AC];
+	uint32_t min_limit = min_t(uint32_t, pp_limit, msg_limit);
+	uint32_t max_limit = max_t(uint32_t, pp_limit, msg_limit);
+	uint32_t od_percent_upper = 0, od_percent_lower = 0;
 	int ret;
 
 	if (current_power_limit) {
-		ret = smu_v13_0_get_current_power_limit(smu, &power_limit);
+		ret = smu_v13_0_get_current_power_limit(smu, current_power_limit);
 		if (ret)
 			*current_power_limit = pp_limit;
 	}
@@ -2430,12 +2433,12 @@ static int smu_v13_0_0_get_power_limit(struct smu_context *smu,
 		od_percent_upper, od_percent_lower, pp_limit);
 
 	if (max_power_limit) {
-		*max_power_limit = pp_limit * (100 + od_percent_upper);
+		*max_power_limit = max_limit * (100 + od_percent_upper);
 		*max_power_limit /= 100;
 	}
 
 	if (min_power_limit) {
-		*min_power_limit = pp_limit * (100 - od_percent_lower);
+		*min_power_limit = min_limit * (100 - od_percent_lower);
 		*min_power_limit /= 100;
 	}
 
diff --git linux-libre-7.1.5-gnu/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_7_ppt.c linux-libre-7.1.6-gnu/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_7_ppt.c
index 0f774b0920ce9..42c9ceeb4f7db 100644
--- linux-libre-7.1.5-gnu/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_7_ppt.c
+++ linux-libre-7.1.6-gnu/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_7_ppt.c
@@ -2385,15 +2385,16 @@ static int smu_v13_0_7_get_power_limit(struct smu_context *smu,
 	uint32_t pp_limit = smu->adev->pm.ac_power ?
 			      skutable->SocketPowerLimitAc[PPT_THROTTLER_PPT0] :
 			      skutable->SocketPowerLimitDc[PPT_THROTTLER_PPT0];
-	uint32_t power_limit = 0, od_percent_upper = 0, od_percent_lower = 0;
+	uint32_t msg_limit = skutable->MsgLimits.Power[PPT_THROTTLER_PPT0][POWER_SOURCE_AC];
+	uint32_t min_limit = min_t(uint32_t, pp_limit, msg_limit);
+	uint32_t max_limit = max_t(uint32_t, pp_limit, msg_limit);
+	uint32_t od_percent_upper = 0, od_percent_lower = 0;
 	int ret;
 
 	if (current_power_limit) {
-		ret = smu_v13_0_get_current_power_limit(smu, &power_limit);
+		ret = smu_v13_0_get_current_power_limit(smu, current_power_limit);
 		if (ret)
-			power_limit = pp_limit;
-
-		*current_power_limit = power_limit;
+			*current_power_limit = pp_limit;
 	}
 
 	if (default_power_limit)
@@ -2414,12 +2415,12 @@ static int smu_v13_0_7_get_power_limit(struct smu_context *smu,
 		od_percent_upper, od_percent_lower, pp_limit);
 
 	if (max_power_limit) {
-		*max_power_limit = pp_limit * (100 + od_percent_upper);
+		*max_power_limit = max_limit * (100 + od_percent_upper);
 		*max_power_limit /= 100;
 	}
 
 	if (min_power_limit) {
-		*min_power_limit = pp_limit * (100 - od_percent_lower);
+		*min_power_limit = min_limit * (100 - od_percent_lower);
 		*min_power_limit /= 100;
 	}
 
diff --git linux-libre-7.1.5-gnu/drivers/gpu/drm/amd/pm/swsmu/smu14/smu_v14_0_0_ppt.c linux-libre-7.1.6-gnu/drivers/gpu/drm/amd/pm/swsmu/smu14/smu_v14_0_0_ppt.c
index 75719c47a41e2..3d73f2050bbef 100644
--- linux-libre-7.1.5-gnu/drivers/gpu/drm/amd/pm/swsmu/smu14/smu_v14_0_0_ppt.c
+++ linux-libre-7.1.6-gnu/drivers/gpu/drm/amd/pm/swsmu/smu14/smu_v14_0_0_ppt.c
@@ -1701,6 +1701,50 @@ static int smu_v14_0_0_restore_user_od_settings(struct smu_context *smu)
 	return 0;
 }
 
+/*
+ * Link any xHCI controller sharing the GPU's PCIe root port as a consumer
+ * of the GPU so the GPU resumes first, avoiding an xHCI resume race.
+ */
+static int smu_v14_0_0_set_power_dep(struct smu_context *smu, bool enable)
+{
+	struct amdgpu_device *adev = smu->adev;
+	struct pci_dev *gpu_pdev = adev->pdev;
+	struct pci_dev *root_port, *usb_pdev = NULL;
+	struct device_link *link;
+
+	if (!enable) {
+		if (smu->usb_power_link) {
+			device_link_del(smu->usb_power_link);
+			smu->usb_power_link = NULL;
+		}
+		return 0;
+	}
+
+	root_port = pcie_find_root_port(gpu_pdev);
+	while ((usb_pdev = pci_get_class(PCI_CLASS_SERIAL_USB_XHCI, usb_pdev))) {
+		struct pci_dev *usb_root;
+
+		usb_root = pcie_find_root_port(usb_pdev);
+		if (usb_root != root_port)
+			continue;
+
+		/* Create device link: USB (consumer) depends on GPU (supplier) */
+		link = device_link_add(&usb_pdev->dev, &gpu_pdev->dev,
+				       DL_FLAG_STATELESS | DL_FLAG_PM_RUNTIME);
+		if (link) {
+			smu->usb_power_link = link;
+			drm_info(adev_to_drm(adev), "USB controller %s D0 power state depends on %s\n",
+				 pci_name(usb_pdev), pci_name(gpu_pdev));
+			/* Only create one link for the first USB controller found */
+			break;
+		}
+	}
+
+	pci_dev_put(usb_pdev);
+
+	return 0;
+}
+
 static const struct pptable_funcs smu_v14_0_0_ppt_funcs = {
 	.check_fw_status = smu_v14_0_check_fw_status,
 	.check_fw_version = smu_cmn_check_fw_version,
@@ -1734,6 +1778,7 @@ static const struct pptable_funcs smu_v14_0_0_ppt_funcs = {
 	.dpm_set_umsch_mm_enable = smu_v14_0_0_set_umsch_mm_enable,
 	.get_dpm_clock_table = smu_v14_0_common_get_dpm_table,
 	.set_mall_enable = smu_v14_0_common_set_mall_enable,
+	.set_power_dep = smu_v14_0_0_set_power_dep,
 };
 
 static void smu_v14_0_0_init_msg_ctl(struct smu_context *smu)
diff --git linux-libre-7.1.5-gnu/drivers/gpu/drm/amd/pm/swsmu/smu14/smu_v14_0_2_ppt.c linux-libre-7.1.6-gnu/drivers/gpu/drm/amd/pm/swsmu/smu14/smu_v14_0_2_ppt.c
index fdc1456b885ce..a6a88e7b26685 100644
--- linux-libre-7.1.5-gnu/drivers/gpu/drm/amd/pm/swsmu/smu14/smu_v14_0_2_ppt.c
+++ linux-libre-7.1.6-gnu/drivers/gpu/drm/amd/pm/swsmu/smu14/smu_v14_0_2_ppt.c
@@ -1621,19 +1621,23 @@ static int smu_v14_0_2_get_power_limit(struct smu_context *smu,
 		table_context->power_play_table;
 	PPTable_t *pptable = table_context->driver_pptable;
 	CustomSkuTable_t *skutable = &pptable->CustomSkuTable;
-	int16_t od_percent_upper = 0, od_percent_lower = 0;
+	uint32_t pp_limit = smu->adev->pm.ac_power ?
+		skutable->SocketPowerLimitAc[PPT_THROTTLER_PPT0] :
+		skutable->SocketPowerLimitDc[PPT_THROTTLER_PPT0];
 	uint32_t msg_limit = pptable->SkuTable.MsgLimits.Power[PPT_THROTTLER_PPT0][POWER_SOURCE_AC];
-	uint32_t power_limit;
+	uint32_t min_limit = min_t(uint32_t, pp_limit, msg_limit);
+	uint32_t max_limit = max_t(uint32_t, pp_limit, msg_limit);
+	int16_t od_percent_upper = 0, od_percent_lower = 0;
+	int ret;
 
-	if (smu_v14_0_get_current_power_limit(smu, &power_limit))
-		power_limit = smu->adev->pm.ac_power ?
-			      skutable->SocketPowerLimitAc[PPT_THROTTLER_PPT0] :
-			      skutable->SocketPowerLimitDc[PPT_THROTTLER_PPT0];
+	if (current_power_limit) {
+		ret = smu_v14_0_get_current_power_limit(smu, current_power_limit);
+		if (ret)
+			*current_power_limit = pp_limit;
+	}
 
-	if (current_power_limit)
-		*current_power_limit = power_limit;
 	if (default_power_limit)
-		*default_power_limit = power_limit;
+		*default_power_limit = pp_limit;
 
 	if (powerplay_table) {
 		if (smu->od_enabled &&
@@ -1647,15 +1651,15 @@ static int smu_v14_0_2_get_power_limit(struct smu_context *smu,
 	}
 
 	dev_dbg(smu->adev->dev, "od percent upper:%d, od percent lower:%d (default power: %d)\n",
-					od_percent_upper, od_percent_lower, power_limit);
+					od_percent_upper, od_percent_lower, pp_limit);
 
 	if (max_power_limit) {
-		*max_power_limit = msg_limit * (100 + od_percent_upper);
+		*max_power_limit = max_limit * (100 + od_percent_upper);
 		*max_power_limit /= 100;
 	}
 
 	if (min_power_limit) {
-		*min_power_limit = power_limit * (100 + od_percent_lower);
+		*min_power_limit = min_limit * (100 + od_percent_lower);
 		*min_power_limit /= 100;
 	}
 
diff --git linux-libre-7.1.5-gnu/drivers/gpu/drm/amd/pm/swsmu/smu15/smu_v15_0_0_ppt.c linux-libre-7.1.6-gnu/drivers/gpu/drm/amd/pm/swsmu/smu15/smu_v15_0_0_ppt.c
index 8d092c347076e..6cd4c38a1341a 100644
--- linux-libre-7.1.5-gnu/drivers/gpu/drm/amd/pm/swsmu/smu15/smu_v15_0_0_ppt.c
+++ linux-libre-7.1.6-gnu/drivers/gpu/drm/amd/pm/swsmu/smu15/smu_v15_0_0_ppt.c
@@ -227,9 +227,14 @@ static int smu_v15_0_0_system_features_control(struct smu_context *smu, bool en)
 	struct amdgpu_device *adev = smu->adev;
 	int ret = 0;
 
-	if (!en && !adev->in_s0ix)
+	if (!en && !adev->in_s0ix) {
 		ret = smu_cmn_send_smc_msg(smu, SMU_MSG_PrepareMp1ForUnload, NULL);
 
+		/* SMU resets BIF_FB_EN to zero, re-enable MC access on APUs with SMU V15 */
+		if (!ret && adev->nbio.funcs && adev->nbio.funcs->mc_access_enable)
+			adev->nbio.funcs->mc_access_enable(adev, true);
+	}
+
 	return ret;
 }
 
diff --git linux-libre-7.1.5-gnu/drivers/gpu/drm/bridge/cadence/cdns-dsi-core.c linux-libre-7.1.6-gnu/drivers/gpu/drm/bridge/cadence/cdns-dsi-core.c
index 0dd85e26248cc..e07a9892df4ef 100644
--- linux-libre-7.1.5-gnu/drivers/gpu/drm/bridge/cadence/cdns-dsi-core.c
+++ linux-libre-7.1.6-gnu/drivers/gpu/drm/bridge/cadence/cdns-dsi-core.c
@@ -1230,7 +1230,7 @@ static const struct mipi_dsi_host_ops cdns_dsi_ops = {
 	.transfer = cdns_dsi_transfer,
 };
 
-static int __maybe_unused cdns_dsi_resume(struct device *dev)
+static int cdns_dsi_resume(struct device *dev)
 {
 	struct cdns_dsi *dsi = dev_get_drvdata(dev);
 
@@ -1241,7 +1241,7 @@ static int __maybe_unused cdns_dsi_resume(struct device *dev)
 	return 0;
 }
 
-static int __maybe_unused cdns_dsi_suspend(struct device *dev)
+static int cdns_dsi_suspend(struct device *dev)
 {
 	struct cdns_dsi *dsi = dev_get_drvdata(dev);
 
@@ -1251,8 +1251,9 @@ static int __maybe_unused cdns_dsi_suspend(struct device *dev)
 	return 0;
 }
 
-static UNIVERSAL_DEV_PM_OPS(cdns_dsi_pm_ops, cdns_dsi_suspend, cdns_dsi_resume,
-			    NULL);
+static const struct dev_pm_ops cdns_dsi_pm_ops = {
+	RUNTIME_PM_OPS(cdns_dsi_suspend, cdns_dsi_resume, NULL)
+};
 
 static int cdns_dsi_drm_probe(struct platform_device *pdev)
 {
@@ -1399,7 +1400,7 @@ static struct platform_driver cdns_dsi_platform_driver = {
 	.driver = {
 		.name   = "cdns-dsi",
 		.of_match_table = cdns_dsi_of_match,
-		.pm = &cdns_dsi_pm_ops,
+		.pm = pm_ptr(&cdns_dsi_pm_ops),
 	},
 };
 module_platform_driver(cdns_dsi_platform_driver);
diff --git linux-libre-7.1.5-gnu/drivers/gpu/drm/display/drm_dp_mst_topology.c linux-libre-7.1.6-gnu/drivers/gpu/drm/display/drm_dp_mst_topology.c
index 8757972e8e242..41151c533d2f5 100644
--- linux-libre-7.1.5-gnu/drivers/gpu/drm/display/drm_dp_mst_topology.c
+++ linux-libre-7.1.6-gnu/drivers/gpu/drm/display/drm_dp_mst_topology.c
@@ -789,6 +789,12 @@ static bool drm_dp_sideband_append_payload(struct drm_dp_sideband_msg_rx *msg,
 {
 	u8 crc4;
 
+	/* curchunk_len must be >= 1 (min 1 CRC byte) and fit in chunk[] */
+	if (!msg->curchunk_len ||
+	    msg->curchunk_len > ARRAY_SIZE(msg->chunk) ||
+	    msg->curchunk_idx + replybuflen > ARRAY_SIZE(msg->chunk))
+		return false;
+
 	memcpy(&msg->chunk[msg->curchunk_idx], replybuf, replybuflen);
 	msg->curchunk_idx += replybuflen;
 
@@ -799,6 +805,9 @@ static bool drm_dp_sideband_append_payload(struct drm_dp_sideband_msg_rx *msg,
 			print_hex_dump(KERN_DEBUG, "wrong crc",
 				       DUMP_PREFIX_NONE, 16, 1,
 				       msg->chunk,  msg->curchunk_len, false);
+		/* Guard against accumulated msg[] overflow */
+		if (msg->curlen + msg->curchunk_len - 1 > ARRAY_SIZE(msg->msg))
+			return false;
 		/* copy chunk into bigger msg */
 		memcpy(&msg->msg[msg->curlen], msg->chunk, msg->curchunk_len - 1);
 		msg->curlen += msg->curchunk_len - 1;
@@ -871,7 +880,7 @@ static bool drm_dp_sideband_parse_remote_dpcd_read(struct drm_dp_sideband_msg_rx
 		goto fail_len;
 	repmsg->u.remote_dpcd_read_ack.num_bytes = raw->msg[idx];
 	idx++;
-	if (idx > raw->curlen)
+	if (idx + repmsg->u.remote_dpcd_read_ack.num_bytes > raw->curlen)
 		goto fail_len;
 
 	memcpy(repmsg->u.remote_dpcd_read_ack.bytes, &raw->msg[idx], repmsg->u.remote_dpcd_read_ack.num_bytes);
@@ -907,7 +916,9 @@ static bool drm_dp_sideband_parse_remote_i2c_read_ack(struct drm_dp_sideband_msg
 		goto fail_len;
 	repmsg->u.remote_i2c_read_ack.num_bytes = raw->msg[idx];
 	idx++;
-	/* TODO check */
+	if (idx + repmsg->u.remote_i2c_read_ack.num_bytes > raw->curlen)
+		goto fail_len;
+
 	memcpy(repmsg->u.remote_i2c_read_ack.bytes, &raw->msg[idx], repmsg->u.remote_i2c_read_ack.num_bytes);
 	return true;
 fail_len:
@@ -923,16 +934,13 @@ static bool drm_dp_sideband_parse_enum_path_resources_ack(struct drm_dp_sideband
 	repmsg->u.path_resources.port_number = (raw->msg[idx] >> 4) & 0xf;
 	repmsg->u.path_resources.fec_capable = raw->msg[idx] & 0x1;
 	idx++;
-	if (idx > raw->curlen)
+	if (idx + 2 > raw->curlen)
 		goto fail_len;
 	repmsg->u.path_resources.full_payload_bw_number = (raw->msg[idx] << 8) | (raw->msg[idx+1]);
 	idx += 2;
-	if (idx > raw->curlen)
+	if (idx + 2 > raw->curlen)
 		goto fail_len;
 	repmsg->u.path_resources.avail_payload_bw_number = (raw->msg[idx] << 8) | (raw->msg[idx+1]);
-	idx += 2;
-	if (idx > raw->curlen)
-		goto fail_len;
 	return true;
 fail_len:
 	DRM_DEBUG_KMS("enum resource parse length fail %d %d\n", idx, raw->curlen);
@@ -950,12 +958,9 @@ static bool drm_dp_sideband_parse_allocate_payload_ack(struct drm_dp_sideband_ms
 		goto fail_len;
 	repmsg->u.allocate_payload.vcpi = raw->msg[idx];
 	idx++;
-	if (idx > raw->curlen)
+	if (idx + 2 > raw->curlen)
 		goto fail_len;
 	repmsg->u.allocate_payload.allocated_pbn = (raw->msg[idx] << 8) | (raw->msg[idx+1]);
-	idx += 2;
-	if (idx > raw->curlen)
-		goto fail_len;
 	return true;
 fail_len:
 	DRM_DEBUG_KMS("allocate payload parse length fail %d %d\n", idx, raw->curlen);
@@ -969,12 +974,9 @@ static bool drm_dp_sideband_parse_query_payload_ack(struct drm_dp_sideband_msg_r
 
 	repmsg->u.query_payload.port_number = (raw->msg[idx] >> 4) & 0xf;
 	idx++;
-	if (idx > raw->curlen)
+	if (idx + 2 > raw->curlen)
 		goto fail_len;
 	repmsg->u.query_payload.allocated_pbn = (raw->msg[idx] << 8) | (raw->msg[idx + 1]);
-	idx += 2;
-	if (idx > raw->curlen)
-		goto fail_len;
 	return true;
 fail_len:
 	DRM_DEBUG_KMS("query payload parse length fail %d %d\n", idx, raw->curlen);
@@ -3738,8 +3740,10 @@ void drm_dp_mst_topology_queue_probe(struct drm_dp_mst_topology_mgr *mgr)
 {
 	mutex_lock(&mgr->lock);
 
-	if (drm_WARN_ON(mgr->dev, !mgr->mst_state || !mgr->mst_primary))
+	if (!mgr->mst_state || !mgr->mst_primary) {
+		drm_dbg_kms(mgr->dev, "queue_probe skipped: topology torn down\n");
 		goto out_unlock;
+	}
 
 	drm_dp_mst_topology_mgr_invalidate_mstb(mgr->mst_primary);
 	drm_dp_mst_queue_probe_work(mgr);
diff --git linux-libre-7.1.5-gnu/drivers/gpu/drm/drm_connector.c linux-libre-7.1.6-gnu/drivers/gpu/drm/drm_connector.c
index 47dc53c4a738f..29634757c06d1 100644
--- linux-libre-7.1.5-gnu/drivers/gpu/drm/drm_connector.c
+++ linux-libre-7.1.6-gnu/drivers/gpu/drm/drm_connector.c
@@ -3576,7 +3576,7 @@ EXPORT_SYMBOL(drm_mode_put_tile_group);
 /**
  * drm_mode_get_tile_group - get a reference to an existing tile group
  * @dev: DRM device
- * @topology: 8-bytes unique per monitor.
+ * @topology_id: 9-byte unique ID per monitor.
  *
  * Use the unique bytes to get a reference to an existing tile group.
  *
@@ -3584,14 +3584,14 @@ EXPORT_SYMBOL(drm_mode_put_tile_group);
  * tile group or NULL if not found.
  */
 struct drm_tile_group *drm_mode_get_tile_group(struct drm_device *dev,
-					       const char topology[8])
+					       const char topology_id[9])
 {
 	struct drm_tile_group *tg;
 	int id;
 
 	mutex_lock(&dev->mode_config.idr_mutex);
 	idr_for_each_entry(&dev->mode_config.tile_idr, tg, id) {
-		if (!memcmp(tg->group_data, topology, 8)) {
+		if (!memcmp(tg->group_data, topology_id, sizeof(tg->group_data))) {
 			if (!kref_get_unless_zero(&tg->refcount))
 				tg = NULL;
 			mutex_unlock(&dev->mode_config.idr_mutex);
@@ -3606,7 +3606,7 @@ EXPORT_SYMBOL(drm_mode_get_tile_group);
 /**
  * drm_mode_create_tile_group - create a tile group from a displayid description
  * @dev: DRM device
- * @topology: 8-bytes unique per monitor.
+ * @topology_id: 9-byte unique ID per monitor.
  *
  * Create a tile group for the unique monitor, and get a unique
  * identifier for the tile group.
@@ -3615,7 +3615,7 @@ EXPORT_SYMBOL(drm_mode_get_tile_group);
  * new tile group or NULL.
  */
 struct drm_tile_group *drm_mode_create_tile_group(struct drm_device *dev,
-						  const char topology[8])
+						  const char topology_id[9])
 {
 	struct drm_tile_group *tg;
 	int ret;
@@ -3625,7 +3625,7 @@ struct drm_tile_group *drm_mode_create_tile_group(struct drm_device *dev,
 		return NULL;
 
 	kref_init(&tg->refcount);
-	memcpy(tg->group_data, topology, 8);
+	memcpy(tg->group_data, topology_id, sizeof(tg->group_data));
 	tg->dev = dev;
 
 	mutex_lock(&dev->mode_config.idr_mutex);
diff --git linux-libre-7.1.5-gnu/drivers/gpu/drm/drm_displayid_internal.h linux-libre-7.1.6-gnu/drivers/gpu/drm/drm_displayid_internal.h
index 5b1b32f735166..4590d6a3d8215 100644
--- linux-libre-7.1.5-gnu/drivers/gpu/drm/drm_displayid_internal.h
+++ linux-libre-7.1.6-gnu/drivers/gpu/drm/drm_displayid_internal.h
@@ -109,7 +109,7 @@ struct displayid_tiled_block {
 	u8 topo[3];
 	u8 tile_size[4];
 	u8 tile_pixel_bezel[5];
-	u8 topology_id[8];
+	u8 topology_id[9];
 } __packed;
 
 struct displayid_detailed_timings_1 {
diff --git linux-libre-7.1.5-gnu/drivers/gpu/drm/drm_gpusvm.c linux-libre-7.1.6-gnu/drivers/gpu/drm/drm_gpusvm.c
index 7993e85c05661..a2bba46b72c1f 100644
--- linux-libre-7.1.5-gnu/drivers/gpu/drm/drm_gpusvm.c
+++ linux-libre-7.1.6-gnu/drivers/gpu/drm/drm_gpusvm.c
@@ -781,7 +781,7 @@ enum drm_gpusvm_scan_result drm_gpusvm_scan_mm(struct drm_gpusvm_range *range,
 	const struct dev_pagemap *other = NULL;
 	int err, i;
 
-	pfns = kvmalloc_array(npages, sizeof(*pfns), GFP_KERNEL);
+	pfns = kvcalloc(npages, sizeof(*pfns), GFP_KERNEL);
 	if (!pfns)
 		return DRM_GPUSVM_SCAN_UNPOPULATED;
 
@@ -1519,6 +1519,16 @@ map_pages:
 					err = -EAGAIN;
 					goto err_unmap;
 				}
+
+				/*
+				 * Set the dpagemap as soon as the first
+				 * device page is mapped so the err_unmap path
+				 * can device_unmap() the device mappings that
+				 * have already been created.
+				 */
+				drm_pagemap_get(dpagemap);
+				drm_pagemap_put(svm_pages->dpagemap);
+				svm_pages->dpagemap = dpagemap;
 			}
 			svm_pages->dma_addr[j] =
 				dpagemap->ops->device_map(dpagemap,
@@ -1562,12 +1572,8 @@ map_pages:
 		flags.has_dma_mapping = true;
 	}
 
-	if (pagemap) {
+	if (pagemap)
 		flags.has_devmem_pages = true;
-		drm_pagemap_get(dpagemap);
-		drm_pagemap_put(svm_pages->dpagemap);
-		svm_pages->dpagemap = dpagemap;
-	}
 
 	/* WRITE_ONCE pairs with READ_ONCE for opportunistic checks */
 	WRITE_ONCE(svm_pages->flags.__flags, flags.__flags);
@@ -1698,8 +1704,10 @@ int drm_gpusvm_range_evict(struct drm_gpusvm *gpusvm,
 		return -EFAULT;
 
 	pfns = kvmalloc_array(npages, sizeof(*pfns), GFP_KERNEL);
-	if (!pfns)
+	if (!pfns) {
+		mmput(mm);
 		return -ENOMEM;
+	}
 
 	hmm_range.hmm_pfns = pfns;
 	while (!time_after(jiffies, timeout)) {
diff --git linux-libre-7.1.5-gnu/drivers/gpu/drm/drm_pagemap.c linux-libre-7.1.6-gnu/drivers/gpu/drm/drm_pagemap.c
index 5002049e01981..43ed97d5cc031 100644
--- linux-libre-7.1.5-gnu/drivers/gpu/drm/drm_pagemap.c
+++ linux-libre-7.1.6-gnu/drivers/gpu/drm/drm_pagemap.c
@@ -12,6 +12,12 @@
 #include <drm/drm_pagemap_util.h>
 #include <drm/drm_print.h>
 
+#if IS_ENABLED(CONFIG_ARCH_ENABLE_THP_MIGRATION)
+#define DRM_PAGEMAP_PMD_ORDER	HPAGE_PMD_ORDER
+#else
+#define DRM_PAGEMAP_PMD_ORDER	(-1)
+#endif
+
 /**
  * DOC: Overview
  *
@@ -480,7 +486,7 @@ static int drm_pagemap_cpages(unsigned long *migrate_pfn, unsigned long npages)
 			order = folio_order(folio);
 			cpages += NR_PAGES(order);
 		} else if (migrate_pfn[i] & MIGRATE_PFN_COMPOUND) {
-			order = HPAGE_PMD_ORDER;
+			order = DRM_PAGEMAP_PMD_ORDER;
 			cpages += NR_PAGES(order);
 		}
 
@@ -628,8 +634,10 @@ int drm_pagemap_migrate_to_devmem(struct drm_pagemap_devmem *devmem_allocation,
 	}
 
 	err = ops->populate_devmem_pfn(devmem_allocation, npages, migrate.dst);
-	if (err)
-		goto err_aborted_migration;
+	if (err) {
+		npages = 0;
+		goto err_finalize;
+	}
 
 	own_pages = 0;
 
@@ -668,10 +676,11 @@ int drm_pagemap_migrate_to_devmem(struct drm_pagemap_devmem *devmem_allocation,
 
 		if (migrate.src[i] & MIGRATE_PFN_COMPOUND) {
 			drm_WARN_ONCE(dpagemap->drm, src_page &&
-				      folio_order(page_folio(src_page)) != HPAGE_PMD_ORDER,
+				      folio_order(page_folio(src_page)) !=
+				      DRM_PAGEMAP_PMD_ORDER,
 				      "Unexpected folio order\n");
 
-			order = HPAGE_PMD_ORDER;
+			order = DRM_PAGEMAP_PMD_ORDER;
 			migrate.dst[i] |= MIGRATE_PFN_COMPOUND;
 
 			for (j = 1; j < NR_PAGES(order) && i + j < npages; j++)
@@ -710,8 +719,11 @@ next:
 		msecs_to_jiffies(mdetails->timeslice_ms);
 
 err_finalize:
-	if (err)
+	if (err) {
 		drm_pagemap_migration_unlock_put_pages(npages, migrate.dst);
+		for (i = npages; i < npages_in_range(start, end); ++i)
+			migrate.dst[i] = 0;
+	}
 err_aborted_migration:
 	migrate_vma_pages(&migrate);
 
diff --git linux-libre-7.1.5-gnu/drivers/gpu/drm/drm_panel_backlight_quirks.c linux-libre-7.1.6-gnu/drivers/gpu/drm/drm_panel_backlight_quirks.c
index 537dc6dd05343..2d0238382ebd5 100644
--- linux-libre-7.1.5-gnu/drivers/gpu/drm/drm_panel_backlight_quirks.c
+++ linux-libre-7.1.6-gnu/drivers/gpu/drm/drm_panel_backlight_quirks.c
@@ -21,6 +21,15 @@ struct drm_get_panel_backlight_quirk {
 };
 
 static const struct drm_get_panel_backlight_quirk drm_panel_min_backlight_quirks[] = {
+	/* Lenovo Legion 5 15ARH05, AUX backlight non-functional, force PWM */
+	{
+		.dmi_match.field = DMI_SYS_VENDOR,
+		.dmi_match.value = "LENOVO",
+		.dmi_match_other.field = DMI_PRODUCT_VERSION,
+		.dmi_match_other.value = "Lenovo Legion 5 15ARH05",
+		.ident.panel_id = drm_edid_encode_panel_id('B', 'O', 'E', 0x08df),
+		.quirk = { .force_pwm = true, },
+	},
 	/* 13 inch matte panel */
 	{
 		.dmi_match.field = DMI_BOARD_VENDOR,
diff --git linux-libre-7.1.5-gnu/drivers/gpu/drm/exynos/exynos_drm_fbdev.c linux-libre-7.1.6-gnu/drivers/gpu/drm/exynos/exynos_drm_fbdev.c
index 637927818dfe4..d283ded266d5d 100644
--- linux-libre-7.1.5-gnu/drivers/gpu/drm/exynos/exynos_drm_fbdev.c
+++ linux-libre-7.1.6-gnu/drivers/gpu/drm/exynos/exynos_drm_fbdev.c
@@ -61,17 +61,13 @@ static int exynos_drm_fbdev_update(struct drm_fb_helper *helper,
 	struct fb_info *fbi = helper->info;
 	struct drm_framebuffer *fb = helper->fb;
 	unsigned int size = fb->width * fb->height * fb->format->cpp[0];
-	unsigned long offset;
 
 	fbi->fbops = &exynos_drm_fb_ops;
 
 	drm_fb_helper_fill_info(fbi, helper, sizes);
 
-	offset = fbi->var.xoffset * fb->format->cpp[0];
-	offset += fbi->var.yoffset * fb->pitches[0];
-
 	fbi->flags |= FBINFO_VIRTFB;
-	fbi->screen_buffer = exynos_gem->kvaddr + offset;
+	fbi->screen_buffer = exynos_gem->kvaddr;
 	fbi->screen_size = size;
 	fbi->fix.smem_len = size;
 
diff --git linux-libre-7.1.5-gnu/drivers/gpu/drm/i915/display/intel_bios.c linux-libre-7.1.6-gnu/drivers/gpu/drm/i915/display/intel_bios.c
index ddaaa568f39ff..478c7409731b2 100644
--- linux-libre-7.1.5-gnu/drivers/gpu/drm/i915/display/intel_bios.c
+++ linux-libre-7.1.6-gnu/drivers/gpu/drm/i915/display/intel_bios.c
@@ -623,6 +623,21 @@ get_lfp_data_tail(const struct bdb_lfp_data *data,
 		return NULL;
 }
 
+static bool is_panel_type_valid(int panel_type)
+{
+	return panel_type >= 0 && panel_type < 16;
+}
+
+static bool is_panel_type_pnp(int panel_type)
+{
+	return panel_type == 0xff;
+}
+
+static bool is_panel_type_valid_or_pnp(int panel_type)
+{
+	return is_panel_type_valid(panel_type) || is_panel_type_pnp(panel_type);
+}
+
 static int opregion_get_panel_type(struct intel_display *display,
 				   const struct intel_bios_encoder_data *devdata,
 				   const struct drm_edid *drm_edid, bool use_fallback)
@@ -640,15 +655,21 @@ static int vbt_get_panel_type(struct intel_display *display,
 	if (!lfp_options)
 		return -1;
 
-	if (lfp_options->panel_type > 0xf &&
-	    lfp_options->panel_type != 0xff) {
+	if (!is_panel_type_valid_or_pnp(lfp_options->panel_type)) {
 		drm_dbg_kms(display->drm, "Invalid VBT panel type 0x%x\n",
 			    lfp_options->panel_type);
 		return -1;
 	}
 
-	if (devdata && devdata->child.handle == DEVICE_HANDLE_LFP2)
+	if (devdata && devdata->child.handle == DEVICE_HANDLE_LFP2) {
+		if (!is_panel_type_valid_or_pnp(lfp_options->panel_type2)) {
+			drm_dbg_kms(display->drm, "Invalid VBT panel type 2 0x%x\n",
+				    lfp_options->panel_type2);
+			return -1;
+		}
+
 		return lfp_options->panel_type2;
+	}
 
 	drm_WARN_ON(display->drm,
 		    devdata && devdata->child.handle != DEVICE_HANDLE_LFP1);
@@ -762,13 +783,12 @@ static int get_panel_type(struct intel_display *display,
 				    panel_types[i].name, panel_types[i].panel_type);
 	}
 
-	if (panel_types[PANEL_TYPE_OPREGION].panel_type >= 0)
+	if (is_panel_type_valid(panel_types[PANEL_TYPE_OPREGION].panel_type))
 		i = PANEL_TYPE_OPREGION;
-	else if (panel_types[PANEL_TYPE_VBT].panel_type == 0xff &&
-		 panel_types[PANEL_TYPE_PNPID].panel_type >= 0)
+	else if (is_panel_type_pnp(panel_types[PANEL_TYPE_VBT].panel_type) &&
+		 is_panel_type_valid(panel_types[PANEL_TYPE_PNPID].panel_type))
 		i = PANEL_TYPE_PNPID;
-	else if (panel_types[PANEL_TYPE_VBT].panel_type != 0xff &&
-		 panel_types[PANEL_TYPE_VBT].panel_type >= 0)
+	else if (is_panel_type_valid(panel_types[PANEL_TYPE_VBT].panel_type))
 		i = PANEL_TYPE_VBT;
 	else
 		i = PANEL_TYPE_FALLBACK;
diff --git linux-libre-7.1.5-gnu/drivers/gpu/drm/i915/display/intel_cdclk.c linux-libre-7.1.6-gnu/drivers/gpu/drm/i915/display/intel_cdclk.c
index a47736613f6e8..2417438e8d5d4 100644
--- linux-libre-7.1.5-gnu/drivers/gpu/drm/i915/display/intel_cdclk.c
+++ linux-libre-7.1.6-gnu/drivers/gpu/drm/i915/display/intel_cdclk.c
@@ -1256,9 +1256,22 @@ static void skl_sanitize_cdclk(struct intel_display *display)
 	cdctl = intel_de_read(display, CDCLK_CTL);
 	expected = (cdctl & CDCLK_FREQ_SEL_MASK) |
 		skl_cdclk_decimal(display->cdclk.hw.cdclk);
-	if (cdctl == expected)
-		/* All well; nothing to sanitize */
-		return;
+
+	if (cdctl != expected) {
+		cdctl &= ~CDCLK_FREQ_DECIMAL_MASK;
+		cdctl |= expected & CDCLK_FREQ_DECIMAL_MASK;
+
+		if (cdctl != expected)
+			goto sanitize;
+
+		drm_dbg_kms(display->drm, "Sanitizing CDCLK decimal divider (CDCLK_CTL 0x%x, expected 0x%x)\n",
+			    intel_de_read(display, CDCLK_CTL), expected);
+
+		intel_de_write(display, CDCLK_CTL, expected);
+	}
+
+	/* All well; nothing to sanitize */
+	return;
 
 sanitize:
 	drm_dbg_kms(display->drm, "Sanitizing cdclk programmed by pre-os\n");
@@ -2354,11 +2367,25 @@ static void bxt_sanitize_cdclk(struct intel_display *display)
 	 * (PIPE_NONE).
 	 */
 	cdctl &= ~bxt_cdclk_cd2x_pipe(display, INVALID_PIPE);
-	expected &= ~bxt_cdclk_cd2x_pipe(display, INVALID_PIPE);
+	cdctl |= bxt_cdclk_cd2x_pipe(display, INVALID_PIPE);
 
-	if (cdctl == expected)
-		/* All well; nothing to sanitize */
-		return;
+	if (cdctl != expected) {
+		if (DISPLAY_VER(display) < 20) {
+			cdctl &= ~CDCLK_FREQ_DECIMAL_MASK;
+			cdctl |= expected & CDCLK_FREQ_DECIMAL_MASK;
+		}
+
+		if (cdctl != expected)
+			goto sanitize;
+
+		drm_dbg_kms(display->drm, "Sanitizing CDCLK decimal divider (CDCLK_CTL 0x%x, expected 0x%x)\n",
+			    intel_de_read(display, CDCLK_CTL), expected);
+
+		intel_de_write(display, CDCLK_CTL, expected);
+	}
+
+	/* All well; nothing to sanitize */
+	return;
 
 sanitize:
 	drm_dbg_kms(display->drm, "Sanitizing cdclk programmed by pre-os\n");
diff --git linux-libre-7.1.5-gnu/drivers/gpu/drm/i915/display/intel_ddi.c linux-libre-7.1.6-gnu/drivers/gpu/drm/i915/display/intel_ddi.c
index ebefa889bc8c5..0987eee38bd13 100644
--- linux-libre-7.1.5-gnu/drivers/gpu/drm/i915/display/intel_ddi.c
+++ linux-libre-7.1.6-gnu/drivers/gpu/drm/i915/display/intel_ddi.c
@@ -2652,9 +2652,6 @@ static void mtl_ddi_pre_enable_dp(struct intel_atomic_state *state,
 	/* 3. Select Thunderbolt */
 	mtl_port_buf_ctl_io_selection(encoder);
 
-	/* 4. Enable Panel Power if PPS is required */
-	intel_pps_on(intel_dp);
-
 	/* 5. Enable the port PLL */
 	intel_ddi_enable_clock(encoder, crtc_state);
 
@@ -3710,6 +3707,14 @@ intel_ddi_pre_pll_enable(struct intel_atomic_state *state,
 	else if (display->platform.geminilake || display->platform.broxton)
 		bxt_dpio_phy_set_lane_optim_mask(encoder,
 						 crtc_state->lane_lat_optim_mask);
+
+	/*
+	 * There is no direct connection between the PLL and PPS, however
+	 * enabling PPS before PLL is required to avoid PLL/DDI BUF timeouts
+	 * during system resume. Do that matching the Bspec order as well.
+	 */
+	if (DISPLAY_VER(display) >= 14)
+		intel_pps_on(&dig_port->dp);
 }
 
 static void adlp_tbt_to_dp_alt_switch_wa(struct intel_encoder *encoder)
diff --git linux-libre-7.1.5-gnu/drivers/gpu/drm/i915/display/intel_dp.c linux-libre-7.1.6-gnu/drivers/gpu/drm/i915/display/intel_dp.c
index 5c3e816b01352..f34da1a055dd5 100644
--- linux-libre-7.1.5-gnu/drivers/gpu/drm/i915/display/intel_dp.c
+++ linux-libre-7.1.6-gnu/drivers/gpu/drm/i915/display/intel_dp.c
@@ -5589,8 +5589,9 @@ intel_dp_check_mst_status(struct intel_dp *intel_dp)
 	struct intel_display *display = to_intel_display(intel_dp);
 	bool force_retrain = intel_dp->link.force_retrain;
 	bool reprobe_needed = false;
+	int tries = 33;
 
-	for (;;) {
+	while (--tries) {
 		u8 esi[4] = {};
 		u8 ack[4] = {};
 		bool new_irqs;
@@ -5633,6 +5634,11 @@ intel_dp_check_mst_status(struct intel_dp *intel_dp)
 			break;
 	}
 
+	if (!tries) {
+		drm_dbg_kms(display->drm, "DPRX ESI not clearing, device may be stuck\n");
+		reprobe_needed = true;
+	}
+
 	return !reprobe_needed;
 }
 
diff --git linux-libre-7.1.5-gnu/drivers/gpu/drm/i915/display/intel_dp_aux_backlight.c linux-libre-7.1.6-gnu/drivers/gpu/drm/i915/display/intel_dp_aux_backlight.c
index 7a6c07f6aaeb4..266e042e00237 100644
--- linux-libre-7.1.5-gnu/drivers/gpu/drm/i915/display/intel_dp_aux_backlight.c
+++ linux-libre-7.1.6-gnu/drivers/gpu/drm/i915/display/intel_dp_aux_backlight.c
@@ -615,12 +615,7 @@ check_if_vesa_backlight_possible(struct intel_dp *intel_dp)
 	int ret;
 	u8 bit_min, bit_max;
 
-	/*
-	 * Since we only support Fully AUX Based VESA Backlight interface make sure
-	 * backlight enable is possible via AUX along with backlight adjustment
-	 */
-	if (!(intel_dp->edp_dpcd[1] & DP_EDP_BACKLIGHT_AUX_ENABLE_CAP &&
-	      intel_dp->edp_dpcd[2] & DP_EDP_BACKLIGHT_BRIGHTNESS_AUX_SET_CAP))
+	if (!(intel_dp->edp_dpcd[2] & DP_EDP_BACKLIGHT_BRIGHTNESS_AUX_SET_CAP))
 		return false;
 
 	ret = drm_dp_dpcd_read_byte(&intel_dp->aux, DP_EDP_PWMGEN_BIT_COUNT_CAP_MIN, &bit_min);
diff --git linux-libre-7.1.5-gnu/drivers/gpu/drm/i915/display/intel_hdcp.c linux-libre-7.1.6-gnu/drivers/gpu/drm/i915/display/intel_hdcp.c
index 892eab4b6f925..878df0e2d6789 100644
--- linux-libre-7.1.5-gnu/drivers/gpu/drm/i915/display/intel_hdcp.c
+++ linux-libre-7.1.6-gnu/drivers/gpu/drm/i915/display/intel_hdcp.c
@@ -132,6 +132,9 @@ intel_hdcp_required_content_stream(struct intel_atomic_state *state,
 		if (conn_dig_port != dig_port)
 			continue;
 
+		if (drm_WARN_ON(display->drm, data->k >= INTEL_NUM_PIPES(display)))
+			return -EINVAL;
+
 		data->streams[data->k].stream_id =
 			intel_conn_to_vcpi(state, connector);
 		data->k++;
@@ -142,7 +145,7 @@ intel_hdcp_required_content_stream(struct intel_atomic_state *state,
 	}
 	drm_connector_list_iter_end(&conn_iter);
 
-	if (drm_WARN_ON(display->drm, data->k > INTEL_NUM_PIPES(display) || data->k == 0))
+	if (drm_WARN_ON(display->drm, !data->k))
 		return -EINVAL;
 
 	/*
@@ -1785,9 +1788,10 @@ int hdcp2_authenticate_repeater_topology(struct intel_connector *connector)
 		return -EINVAL;
 	}
 
-	if (seq_num_v < hdcp->seq_num_v) {
-		/* Roll over of the seq_num_v from repeater. Reauthenticate. */
-		drm_dbg_kms(display->drm, "Seq_num_v roll over.\n");
+	if (hdcp->hdcp2_encrypted && seq_num_v <= hdcp->seq_num_v) {
+		/* Reauthenticate on Seq_num_v repeat or rollover */
+		drm_dbg_kms(display->drm, "Seq_num_v %s\n",
+			    seq_num_v == hdcp->seq_num_v ? "repeat" : "rollover");
 		return -EINVAL;
 	}
 
diff --git linux-libre-7.1.5-gnu/drivers/gpu/drm/i915/display/intel_vrr.c linux-libre-7.1.6-gnu/drivers/gpu/drm/i915/display/intel_vrr.c
index 8a957804cb970..4908cc34b52d5 100644
--- linux-libre-7.1.5-gnu/drivers/gpu/drm/i915/display/intel_vrr.c
+++ linux-libre-7.1.6-gnu/drivers/gpu/drm/i915/display/intel_vrr.c
@@ -64,6 +64,10 @@ bool intel_vrr_is_capable(struct intel_connector *connector)
 		return false;
 	}
 
+	if (!info->monitor_range.min_vfreq || !info->monitor_range.max_vfreq ||
+	    info->monitor_range.min_vfreq > info->monitor_range.max_vfreq)
+		return false;
+
 	return info->monitor_range.max_vfreq - info->monitor_range.min_vfreq > 10;
 }
 
diff --git linux-libre-7.1.5-gnu/drivers/gpu/drm/i915/display/skl_watermark.c linux-libre-7.1.6-gnu/drivers/gpu/drm/i915/display/skl_watermark.c
index e0ac4e2ce4dcb..29b7661f88141 100644
--- linux-libre-7.1.5-gnu/drivers/gpu/drm/i915/display/skl_watermark.c
+++ linux-libre-7.1.6-gnu/drivers/gpu/drm/i915/display/skl_watermark.c
@@ -3908,7 +3908,7 @@ void skl_wm_plane_disable_noatomic(struct intel_crtc *crtc,
 		return;
 
 	skl_ddb_entry_init(&crtc_state->wm.skl.plane_ddb[plane->id], 0, 0);
-	skl_ddb_entry_init(&crtc_state->wm.skl.plane_ddb[plane->id], 0, 0);
+	skl_ddb_entry_init(&crtc_state->wm.skl.plane_ddb_y[plane->id], 0, 0);
 
 	crtc_state->wm.skl.plane_min_ddb[plane->id] = 0;
 	crtc_state->wm.skl.plane_interim_ddb[plane->id] = 0;
diff --git linux-libre-7.1.5-gnu/drivers/gpu/drm/i915/gem/i915_gem_context.c linux-libre-7.1.6-gnu/drivers/gpu/drm/i915/gem/i915_gem_context.c
index 6ac0f23570f33..c58ffa5a8fa6f 100644
--- linux-libre-7.1.5-gnu/drivers/gpu/drm/i915/gem/i915_gem_context.c
+++ linux-libre-7.1.6-gnu/drivers/gpu/drm/i915/gem/i915_gem_context.c
@@ -613,6 +613,7 @@ set_proto_ctx_engines_parallel_submit(struct i915_user_extension __user *base,
 		return -EINVAL;
 	}
 
+	slot = array_index_nospec(slot, set->num_engines);
 	if (set->engines[slot].type != I915_GEM_ENGINE_TYPE_INVALID) {
 		drm_dbg(&i915->drm,
 			"Invalid placement[%d], already occupied\n", slot);
@@ -768,8 +769,8 @@ static int set_proto_ctx_engines(struct drm_i915_file_private *fpriv,
 		struct intel_engine_cs *engine;
 
 		if (copy_from_user(&ci, &user->engines[n], sizeof(ci))) {
-			kfree(set.engines);
-			return -EFAULT;
+			err = -EFAULT;
+			goto err;
 		}
 
 		memset(&set.engines[n], 0, sizeof(set.engines[n]));
@@ -785,8 +786,8 @@ static int set_proto_ctx_engines(struct drm_i915_file_private *fpriv,
 			drm_dbg(&i915->drm,
 				"Invalid engine[%d]: { class:%d, instance:%d }\n",
 				n, ci.engine_class, ci.engine_instance);
-			kfree(set.engines);
-			return -ENOENT;
+			err = -ENOENT;
+			goto err;
 		}
 
 		set.engines[n].type = I915_GEM_ENGINE_TYPE_PHYSICAL;
@@ -799,15 +800,21 @@ static int set_proto_ctx_engines(struct drm_i915_file_private *fpriv,
 					   set_proto_ctx_engines_extensions,
 					   ARRAY_SIZE(set_proto_ctx_engines_extensions),
 					   &set);
-	if (err) {
-		kfree(set.engines);
-		return err;
-	}
+	if (err)
+		goto err_extensions;
 
 	pc->num_user_engines = set.num_engines;
 	pc->user_engines = set.engines;
 
 	return 0;
+
+err_extensions:
+	for (n = 0; n < set.num_engines; n++)
+		kfree(set.engines[n].siblings);
+err:
+	kfree(set.engines);
+
+	return err;
 }
 
 static int set_proto_ctx_sseu(struct drm_i915_file_private *fpriv,
@@ -849,7 +856,7 @@ static int set_proto_ctx_sseu(struct drm_i915_file_private *fpriv,
 		pe = &pc->user_engines[idx];
 
 		/* Only render engine supports RPCS configuration. */
-		if (pe->engine->class != RENDER_CLASS)
+		if (!pe->engine || pe->engine->class != RENDER_CLASS)
 			return -EINVAL;
 
 		sseu = &pe->sseu;
diff --git linux-libre-7.1.5-gnu/drivers/gpu/drm/i915/gt/intel_engine_user.c linux-libre-7.1.6-gnu/drivers/gpu/drm/i915/gt/intel_engine_user.c
index be4bbff1a57c9..d5190e11b2706 100644
--- linux-libre-7.1.5-gnu/drivers/gpu/drm/i915/gt/intel_engine_user.c
+++ linux-libre-7.1.6-gnu/drivers/gpu/drm/i915/gt/intel_engine_user.c
@@ -259,7 +259,7 @@ void intel_engines_driver_register(struct drm_i915_private *i915)
 		p = &prev->rb_right;
 	}
 
-	if (IS_ENABLED(CONFIG_DRM_I915_SELFTESTS) &&
+	if (IS_ENABLED(CONFIG_DRM_I915_SELFTEST) &&
 	    IS_ENABLED(CONFIG_DRM_I915_DEBUG_GEM)) {
 		struct intel_engine_cs *engine;
 		unsigned int isolation;
diff --git linux-libre-7.1.5-gnu/drivers/gpu/drm/i915/gt/intel_execlists_submission.c linux-libre-7.1.6-gnu/drivers/gpu/drm/i915/gt/intel_execlists_submission.c
index 1359fc9cb88ef..e693b0c9d2a3e 100644
--- linux-libre-7.1.5-gnu/drivers/gpu/drm/i915/gt/intel_execlists_submission.c
+++ linux-libre-7.1.6-gnu/drivers/gpu/drm/i915/gt/intel_execlists_submission.c
@@ -3932,11 +3932,11 @@ execlists_create_virtual(struct intel_engine_cs **siblings, unsigned int count,
 	struct drm_i915_private *i915 = siblings[0]->i915;
 	struct virtual_engine *ve;
 	unsigned int n;
-	int err;
+	int err = -ENOMEM;
 
 	ve = kzalloc_flex(*ve, siblings, count);
 	if (!ve)
-		return ERR_PTR(-ENOMEM);
+		goto err;
 
 	ve->base.i915 = i915;
 	ve->base.gt = siblings[0]->gt;
@@ -3968,10 +3968,8 @@ execlists_create_virtual(struct intel_engine_cs **siblings, unsigned int count,
 	intel_engine_init_execlists(&ve->base);
 
 	ve->base.sched_engine = i915_sched_engine_create(ENGINE_VIRTUAL);
-	if (!ve->base.sched_engine) {
-		err = -ENOMEM;
-		goto err_put;
-	}
+	if (!ve->base.sched_engine)
+		goto err_noput;
 	ve->base.sched_engine->private_data = &ve->base;
 
 	ve->base.cops = &virtual_context_ops;
@@ -3987,10 +3985,8 @@ execlists_create_virtual(struct intel_engine_cs **siblings, unsigned int count,
 	intel_context_init(&ve->context, &ve->base);
 
 	ve->base.breadcrumbs = intel_breadcrumbs_create(NULL);
-	if (!ve->base.breadcrumbs) {
-		err = -ENOMEM;
+	if (!ve->base.breadcrumbs)
 		goto err_put;
-	}
 
 	for (n = 0; n < count; n++) {
 		struct intel_engine_cs *sibling = siblings[n];
@@ -4065,8 +4061,13 @@ execlists_create_virtual(struct intel_engine_cs **siblings, unsigned int count,
 	virtual_engine_initial_hint(ve);
 	return &ve->context;
 
+err_noput:
+	kfree(ve);
+	goto err;
+
 err_put:
 	intel_context_put(&ve->context);
+err:
 	return ERR_PTR(err);
 }
 
diff --git linux-libre-7.1.5-gnu/drivers/gpu/drm/i915/gt/selftest_gt_pm.c linux-libre-7.1.6-gnu/drivers/gpu/drm/i915/gt/selftest_gt_pm.c
index 33351deeea4f0..07eaf71955c44 100644
--- linux-libre-7.1.5-gnu/drivers/gpu/drm/i915/gt/selftest_gt_pm.c
+++ linux-libre-7.1.6-gnu/drivers/gpu/drm/i915/gt/selftest_gt_pm.c
@@ -16,9 +16,9 @@ static int cmp_u64(const void *A, const void *B)
 {
 	const u64 *a = A, *b = B;
 
-	if (a < b)
+	if (*a < *b)
 		return -1;
-	else if (a > b)
+	else if (*a > *b)
 		return 1;
 	else
 		return 0;
@@ -28,9 +28,9 @@ static int cmp_u32(const void *A, const void *B)
 {
 	const u32 *a = A, *b = B;
 
-	if (a < b)
+	if (*a < *b)
 		return -1;
-	else if (a > b)
+	else if (*a > *b)
 		return 1;
 	else
 		return 0;
diff --git linux-libre-7.1.5-gnu/drivers/gpu/drm/i915/i915_active.c linux-libre-7.1.6-gnu/drivers/gpu/drm/i915/i915_active.c
index 5cb7a72774a0e..aa77def0bc0d2 100644
--- linux-libre-7.1.5-gnu/drivers/gpu/drm/i915/i915_active.c
+++ linux-libre-7.1.6-gnu/drivers/gpu/drm/i915/i915_active.c
@@ -318,7 +318,7 @@ active_instance(struct i915_active *ref, u64 idx)
 	 */
 	node = kmem_cache_alloc(slab_cache, GFP_ATOMIC);
 	if (!node)
-		goto out;
+		goto err;
 
 	__i915_active_fence_init(&node->base, NULL, node_retire);
 	node->ref = ref;
@@ -332,6 +332,11 @@ out:
 	spin_unlock_irq(&ref->tree_lock);
 
 	return &node->base;
+
+err:
+	spin_unlock_irq(&ref->tree_lock);
+
+	return NULL;
 }
 
 void __i915_active_init(struct i915_active *ref,
diff --git linux-libre-7.1.5-gnu/drivers/gpu/drm/imagination/pvr_context.c linux-libre-7.1.6-gnu/drivers/gpu/drm/imagination/pvr_context.c
index 8de70c30b9de0..5131fcfccffc7 100644
--- linux-libre-7.1.5-gnu/drivers/gpu/drm/imagination/pvr_context.c
+++ linux-libre-7.1.6-gnu/drivers/gpu/drm/imagination/pvr_context.c
@@ -161,22 +161,24 @@ ctx_fw_data_init(void *cpu_ptr, void *priv)
 /**
  * pvr_context_destroy_queues() - Destroy all queues attached to a context.
  * @ctx: Context to destroy queues on.
+ * @cleanup_queue_entity: Whether to cleanup the queue entity e.g. context
+ * creation failure path.
  *
  * Should be called when the last reference to a context object is dropped.
  * It releases all resources attached to the queues bound to this context.
  */
-static void pvr_context_destroy_queues(struct pvr_context *ctx)
+static void pvr_context_destroy_queues(struct pvr_context *ctx, bool cleanup_queue_entity)
 {
 	switch (ctx->type) {
 	case DRM_PVR_CTX_TYPE_RENDER:
-		pvr_queue_destroy(ctx->queues.fragment);
-		pvr_queue_destroy(ctx->queues.geometry);
+		pvr_queue_destroy(ctx->queues.fragment, cleanup_queue_entity);
+		pvr_queue_destroy(ctx->queues.geometry, cleanup_queue_entity);
 		break;
 	case DRM_PVR_CTX_TYPE_COMPUTE:
-		pvr_queue_destroy(ctx->queues.compute);
+		pvr_queue_destroy(ctx->queues.compute, cleanup_queue_entity);
 		break;
 	case DRM_PVR_CTX_TYPE_TRANSFER_FRAG:
-		pvr_queue_destroy(ctx->queues.transfer);
+		pvr_queue_destroy(ctx->queues.transfer, cleanup_queue_entity);
 		break;
 	}
 }
@@ -240,7 +242,7 @@ static int pvr_context_create_queues(struct pvr_context *ctx,
 	return -EINVAL;
 
 err_destroy_queues:
-	pvr_context_destroy_queues(ctx);
+	pvr_context_destroy_queues(ctx, true);
 	return err;
 }
 
@@ -307,8 +309,8 @@ int pvr_context_create(struct pvr_file *pvr_file, struct drm_pvr_ioctl_create_co
 		goto err_free_ctx;
 
 	ctx->vm_ctx = pvr_vm_context_lookup(pvr_file, args->vm_context_handle);
-	if (IS_ERR(ctx->vm_ctx)) {
-		err = PTR_ERR(ctx->vm_ctx);
+	if (!ctx->vm_ctx) {
+		err = -EINVAL;
 		goto err_free_ctx;
 	}
 
@@ -356,7 +358,7 @@ err_destroy_fw_obj:
 	pvr_fw_object_destroy(ctx->fw_obj);
 
 err_destroy_queues:
-	pvr_context_destroy_queues(ctx);
+	pvr_context_destroy_queues(ctx, true);
 
 err_free_ctx_data:
 	kfree(ctx->data);
@@ -382,7 +384,7 @@ pvr_context_release(struct kref *ref_count)
 	spin_unlock(&pvr_dev->ctx_list_lock);
 
 	xa_erase(&pvr_dev->ctx_ids, ctx->ctx_id);
-	pvr_context_destroy_queues(ctx);
+	pvr_context_destroy_queues(ctx, false);
 	pvr_fw_object_destroy(ctx->fw_obj);
 	kfree(ctx->data);
 	pvr_vm_context_put(ctx->vm_ctx);
diff --git linux-libre-7.1.5-gnu/drivers/gpu/drm/imagination/pvr_drv.c linux-libre-7.1.6-gnu/drivers/gpu/drm/imagination/pvr_drv.c
index 44bd3fe91373c..38c46151a8ae2 100644
--- linux-libre-7.1.5-gnu/drivers/gpu/drm/imagination/pvr_drv.c
+++ linux-libre-7.1.6-gnu/drivers/gpu/drm/imagination/pvr_drv.c
@@ -1254,14 +1254,13 @@ pvr_set_uobj_array(const struct drm_pvr_obj_array *out, u32 min_stride, u32 obj_
 			if (copy_to_user(out_ptr, in_ptr, cpy_elem_size))
 				return -EFAULT;
 
-			out_ptr += obj_size;
-			in_ptr += out->stride;
-		}
+			if (out->stride > obj_size &&
+			    clear_user(out_ptr + cpy_elem_size, out->stride - obj_size)) {
+				return -EFAULT;
+			}
 
-		if (out->stride > obj_size &&
-		    clear_user(u64_to_user_ptr(out->array + obj_size),
-			       out->stride - obj_size)) {
-			return -EFAULT;
+			out_ptr += out->stride;
+			in_ptr += obj_size;
 		}
 	}
 
diff --git linux-libre-7.1.5-gnu/drivers/gpu/drm/imagination/pvr_queue.c linux-libre-7.1.6-gnu/drivers/gpu/drm/imagination/pvr_queue.c
index dd88949f61944..b5b82ae12892b 100644
--- linux-libre-7.1.5-gnu/drivers/gpu/drm/imagination/pvr_queue.c
+++ linux-libre-7.1.6-gnu/drivers/gpu/drm/imagination/pvr_queue.c
@@ -179,7 +179,7 @@ static const struct dma_fence_ops pvr_queue_job_fence_ops = {
 
 /**
  * to_pvr_queue_job_fence() - Return a pvr_queue_fence object if the fence is
- * backed by a UFO.
+ * already backed by a UFO.
  * @f: The dma_fence to turn into a pvr_queue_fence.
  *
  * Return:
@@ -356,6 +356,15 @@ static u32 job_cmds_size(struct pvr_job *job, u32 ufo_wait_count)
 	       pvr_cccb_get_size_of_cmd_with_hdr(job->cmd_len);
 }
 
+static bool
+is_paired_job_fence(struct dma_fence *fence, struct pvr_job *job)
+{
+	/* This assumes "fence" is one of "job"'s drm_sched_job::dependencies */
+	return job->type == DRM_PVR_JOB_TYPE_FRAGMENT &&
+	       job->paired_job &&
+	       &job->paired_job->base.s_fence->scheduled == fence;
+}
+
 /**
  * job_count_remaining_native_deps() - Count the number of non-signaled native dependencies.
  * @job: Job to operate on.
@@ -371,6 +380,17 @@ static unsigned long job_count_remaining_native_deps(struct pvr_job *job)
 	xa_for_each(&job->base.dependencies, index, fence) {
 		struct pvr_queue_fence *jfence;
 
+		if (is_paired_job_fence(fence, job)) {
+			/*
+			 * A fence between paired jobs won't resolve to a pvr_queue_fence (i.e.
+			 * be backed by a UFO) until the jobs have been submitted, together.
+			 * The submitting code will insert a partial render fence command for this.
+			 */
+			WARN_ON(dma_fence_is_signaled(fence));
+			remaining_count++;
+			continue;
+		}
+
 		jfence = to_pvr_queue_job_fence(fence);
 		if (!jfence)
 			continue;
@@ -468,10 +488,11 @@ pvr_queue_get_job_kccb_fence(struct pvr_queue *queue, struct pvr_job *job)
 }
 
 static struct dma_fence *
-pvr_queue_get_paired_frag_job_dep(struct pvr_queue *queue, struct pvr_job *job)
+pvr_queue_get_paired_frag_job_dep(struct pvr_job *job)
 {
 	struct pvr_job *frag_job = job->type == DRM_PVR_JOB_TYPE_GEOMETRY ?
 				   job->paired_job : NULL;
+	struct pvr_queue *frag_queue = frag_job ? frag_job->ctx->queues.fragment : NULL;
 	struct dma_fence *f;
 	unsigned long index;
 
@@ -490,7 +511,10 @@ pvr_queue_get_paired_frag_job_dep(struct pvr_queue *queue, struct pvr_job *job)
 		return dma_fence_get(f);
 	}
 
-	return frag_job->base.sched->ops->prepare_job(&frag_job->base, &queue->entity);
+	/* Initialize the paired fragment job's done_fence, so we can signal it. */
+	pvr_queue_job_fence_init(frag_job->done_fence, frag_queue);
+
+	return pvr_queue_get_job_cccb_fence(frag_queue, frag_job);
 }
 
 /**
@@ -509,11 +533,6 @@ pvr_queue_prepare_job(struct drm_sched_job *sched_job,
 	struct pvr_queue *queue = container_of(s_entity, struct pvr_queue, entity);
 	struct dma_fence *internal_dep = NULL;
 
-	/*
-	 * Initialize the done_fence, so we can signal it. This must be done
-	 * here because otherwise by the time of run_job() the job will end up
-	 * in the pending list without a valid fence.
-	 */
 	if (job->type == DRM_PVR_JOB_TYPE_FRAGMENT && job->paired_job) {
 		/*
 		 * This will be called on a paired fragment job after being
@@ -523,18 +542,15 @@ pvr_queue_prepare_job(struct drm_sched_job *sched_job,
 		 */
 		if (job->paired_job->has_pm_ref)
 			return NULL;
-
-		/*
-		 * In this case we need to use the job's own ctx to initialise
-		 * the done_fence.  The other steps are done in the ctx of the
-		 * paired geometry job.
-		 */
-		pvr_queue_job_fence_init(job->done_fence,
-					 job->ctx->queues.fragment);
-	} else {
-		pvr_queue_job_fence_init(job->done_fence, queue);
 	}
 
+	/*
+	 * Initialize the done_fence, so we can signal it. This must be done
+	 * here because otherwise by the time of run_job() the job will end up
+	 * in the pending list without a valid fence.
+	 */
+	pvr_queue_job_fence_init(job->done_fence, queue);
+
 	/* CCCB fence is used to make sure we have enough space in the CCCB to
 	 * submit our commands.
 	 */
@@ -555,7 +571,7 @@ pvr_queue_prepare_job(struct drm_sched_job *sched_job,
 
 	/* The paired job fence should come last, when everything else is ready. */
 	if (!internal_dep)
-		internal_dep = pvr_queue_get_paired_frag_job_dep(queue, job);
+		internal_dep = pvr_queue_get_paired_frag_job_dep(job);
 
 	return internal_dep;
 }
@@ -630,9 +646,8 @@ static void pvr_queue_submit_job_to_cccb(struct pvr_job *job)
 		if (!jfence)
 			continue;
 
-		/* Skip the partial render fence, we will place it at the end. */
-		if (job->type == DRM_PVR_JOB_TYPE_FRAGMENT && job->paired_job &&
-		    &job->paired_job->base.s_fence->scheduled == fence)
+		/* This fence will be placed last, as partial render fence. */
+		if (is_paired_job_fence(fence, job))
 			continue;
 
 		if (dma_fence_is_signaled(&jfence->base))
@@ -1386,11 +1401,12 @@ void pvr_queue_kill(struct pvr_queue *queue)
 /**
  * pvr_queue_destroy() - Destroy a queue.
  * @queue: The queue to destroy.
+ * @cleanup_queue_entity: Whether to cleanup the queue entity.
  *
  * Cleanup the queue and free the resources attached to it. Should be
  * called from the context release function.
  */
-void pvr_queue_destroy(struct pvr_queue *queue)
+void pvr_queue_destroy(struct pvr_queue *queue, bool cleanup_queue_entity)
 {
 	if (!queue)
 		return;
@@ -1400,7 +1416,8 @@ void pvr_queue_destroy(struct pvr_queue *queue)
 	mutex_unlock(&queue->ctx->pvr_dev->queues.lock);
 
 	drm_sched_fini(&queue->scheduler);
-	drm_sched_entity_fini(&queue->entity);
+	if (cleanup_queue_entity)
+		drm_sched_entity_fini(&queue->entity);
 
 	if (WARN_ON(queue->last_queued_job_scheduled_fence))
 		dma_fence_put(queue->last_queued_job_scheduled_fence);
diff --git linux-libre-7.1.5-gnu/drivers/gpu/drm/imagination/pvr_queue.h linux-libre-7.1.6-gnu/drivers/gpu/drm/imagination/pvr_queue.h
index fc1986d73fc88..a205e29437f4e 100644
--- linux-libre-7.1.5-gnu/drivers/gpu/drm/imagination/pvr_queue.h
+++ linux-libre-7.1.6-gnu/drivers/gpu/drm/imagination/pvr_queue.h
@@ -158,7 +158,7 @@ struct pvr_queue *pvr_queue_create(struct pvr_context *ctx,
 
 void pvr_queue_kill(struct pvr_queue *queue);
 
-void pvr_queue_destroy(struct pvr_queue *queue);
+void pvr_queue_destroy(struct pvr_queue *queue, bool cleanup_queue_entity);
 
 void pvr_queue_process(struct pvr_queue *queue);
 
diff --git linux-libre-7.1.5-gnu/drivers/gpu/drm/imagination/pvr_vm.c linux-libre-7.1.6-gnu/drivers/gpu/drm/imagination/pvr_vm.c
index 396d349fb6ce4..ceb78694cd987 100644
--- linux-libre-7.1.5-gnu/drivers/gpu/drm/imagination/pvr_vm.c
+++ linux-libre-7.1.6-gnu/drivers/gpu/drm/imagination/pvr_vm.c
@@ -747,6 +747,7 @@ pvr_vm_map(struct pvr_vm_context *vm_ctx, struct pvr_gem_object *pvr_obj,
 
 	pvr_gem_object_get(pvr_obj);
 
+	mutex_lock(&vm_ctx->lock);
 	err = drm_gpuvm_exec_lock(&vm_exec);
 	if (err)
 		goto err_cleanup;
@@ -756,6 +757,7 @@ pvr_vm_map(struct pvr_vm_context *vm_ctx, struct pvr_gem_object *pvr_obj,
 	drm_gpuvm_exec_unlock(&vm_exec);
 
 err_cleanup:
+	mutex_unlock(&vm_ctx->lock);
 	pvr_vm_bind_op_fini(&bind_op);
 
 	return err;
diff --git linux-libre-7.1.5-gnu/drivers/gpu/drm/nouveau/nouveau_exec.c linux-libre-7.1.6-gnu/drivers/gpu/drm/nouveau/nouveau_exec.c
index c01a01aee32be..a08ab1cfea9be 100644
--- linux-libre-7.1.5-gnu/drivers/gpu/drm/nouveau/nouveau_exec.c
+++ linux-libre-7.1.6-gnu/drivers/gpu/drm/nouveau/nouveau_exec.c
@@ -331,10 +331,10 @@ nouveau_exec_ucopy(struct nouveau_exec_job_args *args,
 
 	return 0;
 
-err_free_pushs:
-	u_free(args->push.s);
 err_free_ins:
 	u_free(args->in_sync.s);
+err_free_pushs:
+	u_free(args->push.s);
 	return ret;
 }
 
diff --git linux-libre-7.1.5-gnu/drivers/gpu/drm/nouveau/nouveau_uvmm.c linux-libre-7.1.6-gnu/drivers/gpu/drm/nouveau/nouveau_uvmm.c
index 36445915aa58c..f5e4756b4de4a 100644
--- linux-libre-7.1.5-gnu/drivers/gpu/drm/nouveau/nouveau_uvmm.c
+++ linux-libre-7.1.6-gnu/drivers/gpu/drm/nouveau/nouveau_uvmm.c
@@ -1779,10 +1779,10 @@ nouveau_uvmm_vm_bind_ucopy(struct nouveau_uvmm_bind_job_args *args,
 
 	return 0;
 
-err_free_ops:
-	u_free(args->op.s);
 err_free_ins:
 	u_free(args->in_sync.s);
+err_free_ops:
+	u_free(args->op.s);
 	return ret;
 }
 
diff --git linux-libre-7.1.5-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/acr/base.c linux-libre-7.1.6-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/acr/base.c
index 4c7745cd6ae52..7fd967a2554f9 100644
--- linux-libre-7.1.5-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/acr/base.c
+++ linux-libre-7.1.6-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/acr/base.c
@@ -315,6 +315,7 @@ nvkm_acr_oneinit(struct nvkm_subdev *subdev)
 					  i, us, fw);
 			}
 		}
+		nvkm_done(acr->wpr);
 		return -EINVAL;
 	}
 	nvkm_done(acr->wpr);
diff --git linux-libre-7.1.5-gnu/drivers/gpu/drm/panel/Kconfig linux-libre-7.1.6-gnu/drivers/gpu/drm/panel/Kconfig
index b2153e04a59af..adab94b3ebdfd 100644
--- linux-libre-7.1.5-gnu/drivers/gpu/drm/panel/Kconfig
+++ linux-libre-7.1.6-gnu/drivers/gpu/drm/panel/Kconfig
@@ -208,6 +208,7 @@ config DRM_PANEL_HIMAX_HX83121A
 	depends on OF
 	depends on DRM_MIPI_DSI
 	depends on BACKLIGHT_CLASS_DEVICE
+	select DRM_DISPLAY_HELPER
 	select DRM_DISPLAY_DSC_HELPER
 	select DRM_KMS_HELPER
 	help
@@ -308,6 +309,7 @@ config DRM_PANEL_ILITEK_ILI9882T
 	depends on OF
 	depends on DRM_MIPI_DSI
 	depends on BACKLIGHT_CLASS_DEVICE
+	select DRM_DISPLAY_HELPER
 	select DRM_DISPLAY_DSC_HELPER
 	help
 	  Say Y if you want to enable support for panels based on the
@@ -914,6 +916,7 @@ config DRM_PANEL_SAMSUNG_S6E3HA8
 	depends on OF
 	depends on DRM_MIPI_DSI
 	depends on BACKLIGHT_CLASS_DEVICE
+	select DRM_DISPLAY_HELPER
 	select DRM_DISPLAY_DSC_HELPER
 	help
 	  Say Y or M here if you want to enable support for the
diff --git linux-libre-7.1.5-gnu/drivers/gpu/drm/panthor/panthor_device.c linux-libre-7.1.6-gnu/drivers/gpu/drm/panthor/panthor_device.c
index 4f522a912d896..48bb33bac3663 100644
--- linux-libre-7.1.5-gnu/drivers/gpu/drm/panthor/panthor_device.c
+++ linux-libre-7.1.6-gnu/drivers/gpu/drm/panthor/panthor_device.c
@@ -207,7 +207,10 @@ int panthor_device_init(struct panthor_device *ptdev)
 		return ret;
 
 #ifdef CONFIG_DEBUG_FS
-	drmm_mutex_init(&ptdev->base, &ptdev->gems.lock);
+	ret = drmm_mutex_init(&ptdev->base, &ptdev->gems.lock);
+	if (ret)
+		return ret;
+
 	INIT_LIST_HEAD(&ptdev->gems.node);
 #endif
 
diff --git linux-libre-7.1.5-gnu/drivers/gpu/drm/panthor/panthor_fw.c linux-libre-7.1.6-gnu/drivers/gpu/drm/panthor/panthor_fw.c
index 7c93f3b98f8e7..9ecb103ce1f94 100644
--- linux-libre-7.1.5-gnu/drivers/gpu/drm/panthor/panthor_fw.c
+++ linux-libre-7.1.6-gnu/drivers/gpu/drm/panthor/panthor_fw.c
@@ -824,6 +824,7 @@ static int panthor_fw_load(struct panthor_device *ptdev)
 	}
 
 	if (hdr.size > iter.size) {
+		ret = -EINVAL;
 		drm_err(&ptdev->base, "Firmware image is truncated\n");
 		goto out;
 	}
diff --git linux-libre-7.1.5-gnu/drivers/gpu/drm/radeon/r100.c linux-libre-7.1.6-gnu/drivers/gpu/drm/radeon/r100.c
index 3446896d3ba45..d71ef7191dfc6 100644
--- linux-libre-7.1.5-gnu/drivers/gpu/drm/radeon/r100.c
+++ linux-libre-7.1.6-gnu/drivers/gpu/drm/radeon/r100.c
@@ -900,6 +900,7 @@ struct radeon_fence *r100_copy_blit(struct radeon_device *rdev,
 {
 	struct radeon_ring *ring = &rdev->ring[RADEON_RING_TYPE_GFX_INDEX];
 	struct radeon_fence *fence;
+	uint64_t cur_src_offset, cur_dst_offset;
 	uint32_t cur_pages;
 	uint32_t stride_bytes = RADEON_GPU_PAGE_SIZE;
 	uint32_t pitch;
@@ -928,6 +929,10 @@ struct radeon_fence *r100_copy_blit(struct radeon_device *rdev,
 			cur_pages = 8191;
 		}
 		num_gpu_pages -= cur_pages;
+		cur_src_offset = src_offset +
+			(uint64_t)num_gpu_pages * RADEON_GPU_PAGE_SIZE;
+		cur_dst_offset = dst_offset +
+			(uint64_t)num_gpu_pages * RADEON_GPU_PAGE_SIZE;
 
 		/* pages are in Y direction - height
 		   page width in X direction - width */
@@ -944,13 +949,13 @@ struct radeon_fence *r100_copy_blit(struct radeon_device *rdev,
 				  RADEON_DP_SRC_SOURCE_MEMORY |
 				  RADEON_GMC_CLR_CMP_CNTL_DIS |
 				  RADEON_GMC_WR_MSK_DIS);
-		radeon_ring_write(ring, (pitch << 22) | (src_offset >> 10));
-		radeon_ring_write(ring, (pitch << 22) | (dst_offset >> 10));
+		radeon_ring_write(ring, (pitch << 22) | (cur_src_offset >> 10));
+		radeon_ring_write(ring, (pitch << 22) | (cur_dst_offset >> 10));
 		radeon_ring_write(ring, (0x1fff) | (0x1fff << 16));
 		radeon_ring_write(ring, 0);
 		radeon_ring_write(ring, (0x1fff) | (0x1fff << 16));
-		radeon_ring_write(ring, num_gpu_pages);
-		radeon_ring_write(ring, num_gpu_pages);
+		radeon_ring_write(ring, 0);
+		radeon_ring_write(ring, 0);
 		radeon_ring_write(ring, cur_pages | (stride_pixels << 16));
 	}
 	radeon_ring_write(ring, PACKET0(RADEON_DSTCACHE_CTLSTAT, 0));
diff --git linux-libre-7.1.5-gnu/drivers/gpu/drm/renesas/rz-du/rzg2l_mipi_dsi.c linux-libre-7.1.6-gnu/drivers/gpu/drm/renesas/rz-du/rzg2l_mipi_dsi.c
index 0d0cf10225bb5..9a83f4e03e9ba 100644
--- linux-libre-7.1.5-gnu/drivers/gpu/drm/renesas/rz-du/rzg2l_mipi_dsi.c
+++ linux-libre-7.1.6-gnu/drivers/gpu/drm/renesas/rz-du/rzg2l_mipi_dsi.c
@@ -528,7 +528,7 @@ static int rzg2l_mipi_dsi_dphy_init(struct rzg2l_mipi_dsi *dsi,
 	if (ret < 0)
 		return ret;
 
-	udelay(1);
+	fsleep(1000);
 
 	return 0;
 }
@@ -1025,29 +1025,33 @@ static void rzg2l_mipi_dsi_atomic_pre_enable(struct drm_bridge *bridge,
 	const struct drm_display_mode *mode;
 	struct drm_connector *connector;
 	struct drm_crtc *crtc;
-	int ret;
 
 	connector = drm_atomic_get_new_connector_for_encoder(state, bridge->encoder);
 	crtc = drm_atomic_get_new_connector_state(state, connector)->crtc;
 	mode = &drm_atomic_get_new_crtc_state(state, crtc)->adjusted_mode;
 
-	ret = rzg2l_mipi_dsi_startup(dsi, mode);
-	if (ret < 0)
-		return;
-
-	rzg2l_mipi_dsi_set_display_timing(dsi, mode);
+	rzg2l_mipi_dsi_startup(dsi, mode);
 }
 
 static void rzg2l_mipi_dsi_atomic_enable(struct drm_bridge *bridge,
 					 struct drm_atomic_state *state)
 {
 	struct rzg2l_mipi_dsi *dsi = bridge_to_rzg2l_mipi_dsi(bridge);
+	const struct drm_display_mode *mode;
+	struct drm_connector *connector;
+	struct drm_crtc *crtc;
 	int ret;
 
 	ret = rzg2l_mipi_dsi_start_hs_clock(dsi);
 	if (ret < 0)
 		goto err_stop;
 
+	connector = drm_atomic_get_new_connector_for_encoder(state, bridge->encoder);
+	crtc = drm_atomic_get_new_connector_state(state, connector)->crtc;
+	mode = &drm_atomic_get_new_crtc_state(state, crtc)->adjusted_mode;
+
+	rzg2l_mipi_dsi_set_display_timing(dsi, mode);
+
 	ret = rzg2l_mipi_dsi_start_video(dsi);
 	if (ret < 0)
 		goto err_stop_clock;
diff --git linux-libre-7.1.5-gnu/drivers/gpu/drm/rockchip/analogix_dp-rockchip.c linux-libre-7.1.6-gnu/drivers/gpu/drm/rockchip/analogix_dp-rockchip.c
index 96bd3dd239d25..387fb6259edde 100644
--- linux-libre-7.1.5-gnu/drivers/gpu/drm/rockchip/analogix_dp-rockchip.c
+++ linux-libre-7.1.6-gnu/drivers/gpu/drm/rockchip/analogix_dp-rockchip.c
@@ -461,6 +461,8 @@ static int rockchip_dp_probe(struct platform_device *pdev)
 		return -ENOMEM;
 
 	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!res)
+		return -EINVAL;
 
 	i = 0;
 	while (dp_data[i].reg) {
diff --git linux-libre-7.1.5-gnu/drivers/gpu/drm/rockchip/cdn-dp-reg.c linux-libre-7.1.6-gnu/drivers/gpu/drm/rockchip/cdn-dp-reg.c
index 0dc3804051a94..9b82b27770e5c 100644
--- linux-libre-7.1.5-gnu/drivers/gpu/drm/rockchip/cdn-dp-reg.c
+++ linux-libre-7.1.6-gnu/drivers/gpu/drm/rockchip/cdn-dp-reg.c
@@ -685,6 +685,8 @@ int cdn_dp_config_video(struct cdn_dp_device *dp)
 	val = div_u64(8 * (symbol + 1), bit_per_pix) - val;
 	val += 2;
 	ret = cdn_dp_reg_write(dp, DP_VC_TABLE(15), val);
+	if (ret)
+		goto err_config_video;
 
 	switch (video->color_depth) {
 	case 6:
diff --git linux-libre-7.1.5-gnu/drivers/gpu/drm/sysfb/drm_sysfb_helper.h linux-libre-7.1.6-gnu/drivers/gpu/drm/sysfb/drm_sysfb_helper.h
index b14df5b54bc9a..d48b92a903f75 100644
--- linux-libre-7.1.5-gnu/drivers/gpu/drm/sysfb/drm_sysfb_helper.h
+++ linux-libre-7.1.6-gnu/drivers/gpu/drm/sysfb/drm_sysfb_helper.h
@@ -50,7 +50,7 @@ struct resource *drm_sysfb_get_memory_si(struct drm_device *dev,
 int drm_sysfb_get_stride_si(struct drm_device *dev, const struct screen_info *si,
 			    const struct drm_format_info *format,
 			    unsigned int width, unsigned int height, u64 size);
-u64 drm_sysfb_get_visible_size_si(struct drm_device *dev, const struct screen_info *si,
+s64 drm_sysfb_get_visible_size_si(struct drm_device *dev, const struct screen_info *si,
 				  unsigned int height, unsigned int stride, u64 size);
 #endif
 
diff --git linux-libre-7.1.5-gnu/drivers/gpu/drm/sysfb/drm_sysfb_screen_info.c linux-libre-7.1.6-gnu/drivers/gpu/drm/sysfb/drm_sysfb_screen_info.c
index 749290196c6af..1c479ce0e5033 100644
--- linux-libre-7.1.5-gnu/drivers/gpu/drm/sysfb/drm_sysfb_screen_info.c
+++ linux-libre-7.1.6-gnu/drivers/gpu/drm/sysfb/drm_sysfb_screen_info.c
@@ -2,6 +2,7 @@
 
 #include <linux/export.h>
 #include <linux/limits.h>
+#include <linux/math64.h>
 #include <linux/minmax.h>
 #include <linux/screen_info.h>
 
@@ -56,18 +57,24 @@ int drm_sysfb_get_stride_si(struct drm_device *dev, const struct screen_info *si
 			    unsigned int width, unsigned int height, u64 size)
 {
 	u64 lfb_linelength = si->lfb_linelength;
+	s64 stride;
 
 	if (!lfb_linelength)
 		lfb_linelength = drm_format_info_min_pitch(format, 0, width);
 
-	return drm_sysfb_get_validated_int0(dev, "stride", lfb_linelength, div64_u64(size, height));
+	stride = drm_sysfb_get_validated_size0(dev, "stride", lfb_linelength,
+					       div64_u64(size, height));
+	if (stride < INT_MIN || stride > INT_MAX)
+		return -EINVAL;
+
+	return (int)stride; /* stride or negative errno code */
 }
 EXPORT_SYMBOL(drm_sysfb_get_stride_si);
 
-u64 drm_sysfb_get_visible_size_si(struct drm_device *dev, const struct screen_info *si,
+s64 drm_sysfb_get_visible_size_si(struct drm_device *dev, const struct screen_info *si,
 				  unsigned int height, unsigned int stride, u64 size)
 {
-	u64 vsize = PAGE_ALIGN(height * stride);
+	u64 vsize = mul_u32_u32(height, stride);
 
 	return drm_sysfb_get_validated_size0(dev, "visible size", vsize, size);
 }
diff --git linux-libre-7.1.5-gnu/drivers/gpu/drm/sysfb/efidrm.c linux-libre-7.1.6-gnu/drivers/gpu/drm/sysfb/efidrm.c
index a335c94a7bd75..d5adef5deb638 100644
--- linux-libre-7.1.5-gnu/drivers/gpu/drm/sysfb/efidrm.c
+++ linux-libre-7.1.6-gnu/drivers/gpu/drm/sysfb/efidrm.c
@@ -150,7 +150,8 @@ static struct efidrm_device *efidrm_device_create(struct drm_driver *drv,
 	const struct screen_info *si;
 	const struct drm_format_info *format;
 	int width, height, stride;
-	u64 vsize, mem_flags;
+	s64 vsize;
+	u64 mem_flags;
 	struct resource resbuf;
 	struct resource *res;
 	struct efidrm_device *efi;
@@ -204,8 +205,8 @@ static struct efidrm_device *efidrm_device_create(struct drm_driver *drv,
 	if (stride < 0)
 		return ERR_PTR(stride);
 	vsize = drm_sysfb_get_visible_size_si(dev, si, height, stride, resource_size(res));
-	if (!vsize)
-		return ERR_PTR(-EINVAL);
+	if (vsize < 0)
+		return ERR_PTR(vsize);
 
 	drm_dbg(dev, "framebuffer format=%p4cc, size=%dx%d, stride=%d bytes\n",
 		&format->format, width, height, stride);
diff --git linux-libre-7.1.5-gnu/drivers/gpu/drm/sysfb/vesadrm.c linux-libre-7.1.6-gnu/drivers/gpu/drm/sysfb/vesadrm.c
index 4e00113e5c770..d60a67fc1d5b4 100644
--- linux-libre-7.1.5-gnu/drivers/gpu/drm/sysfb/vesadrm.c
+++ linux-libre-7.1.6-gnu/drivers/gpu/drm/sysfb/vesadrm.c
@@ -400,7 +400,7 @@ static struct vesadrm_device *vesadrm_device_create(struct drm_driver *drv,
 	const struct screen_info *si;
 	const struct drm_format_info *format;
 	int width, height, stride;
-	u64 vsize;
+	s64 vsize;
 	struct resource resbuf;
 	struct resource *res;
 	struct vesadrm_device *vesa;
@@ -455,8 +455,8 @@ static struct vesadrm_device *vesadrm_device_create(struct drm_driver *drv,
 	if (stride < 0)
 		return ERR_PTR(stride);
 	vsize = drm_sysfb_get_visible_size_si(dev, si, height, stride, resource_size(res));
-	if (!vsize)
-		return ERR_PTR(-EINVAL);
+	if (vsize < 0)
+		return ERR_PTR(vsize);
 
 	drm_dbg(dev, "framebuffer format=%p4cc, size=%dx%d, stride=%d bytes\n",
 		&format->format, width, height, stride);
diff --git linux-libre-7.1.5-gnu/drivers/gpu/drm/tegra/fbdev.c linux-libre-7.1.6-gnu/drivers/gpu/drm/tegra/fbdev.c
index 19e39fa54bfae..793849199783a 100644
--- linux-libre-7.1.5-gnu/drivers/gpu/drm/tegra/fbdev.c
+++ linux-libre-7.1.6-gnu/drivers/gpu/drm/tegra/fbdev.c
@@ -76,7 +76,6 @@ int tegra_fbdev_driver_fbdev_probe(struct drm_fb_helper *helper,
 	struct fb_info *info = helper->info;
 	unsigned int bytes_per_pixel;
 	struct drm_framebuffer *fb;
-	unsigned long offset;
 	struct tegra_bo *bo;
 	size_t size;
 	int err;
@@ -115,9 +114,6 @@ int tegra_fbdev_driver_fbdev_probe(struct drm_fb_helper *helper,
 
 	drm_fb_helper_fill_info(info, helper, sizes);
 
-	offset = info->var.xoffset * bytes_per_pixel +
-		 info->var.yoffset * fb->pitches[0];
-
 	if (bo->pages) {
 		bo->vaddr = vmap(bo->pages, bo->num_pages, VM_MAP,
 				 pgprot_writecombine(PAGE_KERNEL));
@@ -129,9 +125,9 @@ int tegra_fbdev_driver_fbdev_probe(struct drm_fb_helper *helper,
 	}
 
 	info->flags |= FBINFO_VIRTFB;
-	info->screen_buffer = bo->vaddr + offset;
+	info->screen_buffer = bo->vaddr;
 	info->screen_size = size;
-	info->fix.smem_start = (unsigned long)(bo->iova + offset);
+	info->fix.smem_start = (unsigned long)(bo->iova);
 	info->fix.smem_len = size;
 
 	return 0;
diff --git linux-libre-7.1.5-gnu/drivers/gpu/drm/tests/drm_gem_shmem_test.c linux-libre-7.1.6-gnu/drivers/gpu/drm/tests/drm_gem_shmem_test.c
index 44a1901092497..5e69ff1d1ad67 100644
--- linux-libre-7.1.5-gnu/drivers/gpu/drm/tests/drm_gem_shmem_test.c
+++ linux-libre-7.1.6-gnu/drivers/gpu/drm/tests/drm_gem_shmem_test.c
@@ -95,13 +95,9 @@ static void drm_gem_shmem_test_obj_create_private(struct kunit *test)
 	sg_init_one(sgt->sgl, buf, TEST_SIZE);
 
 	/*
-	 * Set the DMA mask to 64-bits and map the sgtables
-	 * otherwise drm_gem_shmem_free will cause a warning
-	 * on debug kernels.
+	 * Map the sgtables otherwise drm_gem_shmem_free will cause a warning on
+	 * debug kernels.
 	 */
-	ret = dma_set_mask(drm_dev->dev, DMA_BIT_MASK(64));
-	KUNIT_ASSERT_EQ(test, ret, 0);
-
 	ret = dma_map_sgtable(drm_dev->dev, sgt, DMA_BIDIRECTIONAL, 0);
 	KUNIT_ASSERT_EQ(test, ret, 0);
 
@@ -352,11 +348,19 @@ static int drm_gem_shmem_test_init(struct kunit *test)
 {
 	struct device *dev;
 	struct drm_device *drm_dev;
+	int ret;
 
 	/* Allocate a parent device */
 	dev = drm_kunit_helper_alloc_device(test);
 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, dev);
 
+	/*
+	 * Set the DMA mask to 64-bits to avoid intermittent failures calling
+	 * drm_gem_shmem_get_pages_sgt().
+	 */
+	ret = dma_set_mask(dev, DMA_BIT_MASK(64));
+	KUNIT_ASSERT_EQ(test, ret, 0);
+
 	/*
 	 * The DRM core will automatically initialize the GEM core and create
 	 * a DRM Memory Manager object which provides an address space pool
diff --git linux-libre-7.1.5-gnu/drivers/gpu/drm/tidss/tidss_encoder.c linux-libre-7.1.6-gnu/drivers/gpu/drm/tidss/tidss_encoder.c
index 81a04f7677701..db467bbcdb776 100644
--- linux-libre-7.1.5-gnu/drivers/gpu/drm/tidss/tidss_encoder.c
+++ linux-libre-7.1.6-gnu/drivers/gpu/drm/tidss/tidss_encoder.c
@@ -106,6 +106,8 @@ int tidss_encoder_create(struct tidss_device *tidss,
 	enc = &t_enc->encoder;
 	enc->possible_crtcs = possible_crtcs;
 
+	devm_drm_bridge_add(tidss->dev, &t_enc->bridge);
+
 	/* Attaching first bridge to the encoder */
 	ret = drm_bridge_attach(enc, &t_enc->bridge, NULL,
 				DRM_BRIDGE_ATTACH_NO_CONNECTOR);
diff --git linux-libre-7.1.5-gnu/drivers/gpu/drm/ttm/ttm_backup.c linux-libre-7.1.6-gnu/drivers/gpu/drm/ttm/ttm_backup.c
index 81df4cb5606b4..3c067aadc52de 100644
--- linux-libre-7.1.5-gnu/drivers/gpu/drm/ttm/ttm_backup.c
+++ linux-libre-7.1.6-gnu/drivers/gpu/drm/ttm/ttm_backup.c
@@ -6,9 +6,10 @@
 #include <drm/ttm/ttm_backup.h>
 
 #include <linux/export.h>
-#include <linux/page-flags.h>
 #include <linux/swap.h>
 
+#include "ttm_pool_internal.h"
+
 /*
  * Need to map shmem indices to handle since a handle value
  * of 0 means error, following the swp_entry_t convention.
@@ -68,17 +69,23 @@ int ttm_backup_copy_page(struct file *backup, struct page *dst,
 }
 
 /**
- * ttm_backup_backup_page() - Backup a page
+ * ttm_backup_backup_folio() - Backup a folio
  * @backup: The struct backup pointer to use.
- * @page: The page to back up.
- * @writeback: Whether to perform immediate writeback of the page.
+ * @folio: The folio to back up.
+ * @order: The allocation order of @folio.  Since TTM allocates higher-order
+ *         pages without __GFP_COMP, folio_nr_pages(@folio) would always
+ *         return 1; the caller must pass the true order explicitly.
+ * @writeback: Whether to perform immediate writeback of the folio's pages.
  * This may have performance implications.
- * @idx: A unique integer for each page and each struct backup.
+ * @idx: A unique integer for the first page of the folio and each struct backup.
  * This allows the backup implementation to avoid managing
  * its address space separately.
- * @page_gfp: The gfp value used when the page was allocated.
- * This is used for accounting purposes.
+ * @folio_gfp: The gfp value used when the folio was allocated.
+ * Currently unused.
  * @alloc_gfp: The gfp to be used when allocating memory.
+ * @nr_pages_backed: Output. On a successful return, set to the number of
+ * pages actually backed up, which may be less than (1 << @order)
+ * if an -ENOMEM was encountered mid-folio.
  *
  * Context: If called from reclaim context, the caller needs to
  * assert that the shrinker gfp has __GFP_FS set, to avoid
@@ -87,53 +94,87 @@ int ttm_backup_copy_page(struct file *backup, struct page *dst,
  * that the shrinker gfp has __GFP_IO set, since without it,
  * we're not allowed to start backup IO.
  *
- * Return: A handle on success. Negative error code on failure.
- *
- * Note: This function could be extended to back up a folio and
- * implementations would then split the folio internally if needed.
- * Drawback is that the caller would then have to keep track of
- * the folio size- and usage.
+ * Return: A handle for the first backed-up page on success (handles for
+ * subsequent pages follow sequentially). -ENOMEM if no pages could be backed
+ * up. Any other negative error code if a non-ENOMEM failure occurred; in that
+ * case any pages backed up so far are truncated before returning.
  */
 s64
-ttm_backup_backup_page(struct file *backup, struct page *page,
-		       bool writeback, pgoff_t idx, gfp_t page_gfp,
-		       gfp_t alloc_gfp)
+ttm_backup_backup_folio(struct file *backup, struct folio *folio,
+			unsigned int order, bool writeback, pgoff_t idx,
+			gfp_t folio_gfp, gfp_t alloc_gfp,
+			pgoff_t *nr_pages_backed)
 {
 	struct address_space *mapping = backup->f_mapping;
-	unsigned long handle = 0;
+	int nr_pages = 1 << order;
 	struct folio *to_folio;
-	int ret;
-
-	to_folio = shmem_read_folio_gfp(mapping, idx, alloc_gfp);
-	if (IS_ERR(to_folio))
-		return PTR_ERR(to_folio);
-
-	folio_mark_accessed(to_folio);
-	folio_lock(to_folio);
-	folio_mark_dirty(to_folio);
-	copy_highpage(folio_file_page(to_folio, idx), page);
-	handle = ttm_backup_shmem_idx_to_handle(idx);
-
-	if (writeback && !folio_mapped(to_folio) &&
-	    folio_clear_dirty_for_io(to_folio)) {
-		folio_set_reclaim(to_folio);
-		ret = shmem_writeout(to_folio, NULL, NULL);
-		if (!folio_test_writeback(to_folio))
-			folio_clear_reclaim(to_folio);
+	int ret, i;
+
+	*nr_pages_backed = 0;
+
+	for (i = 0; i < nr_pages; ) {
+		int to_nr, j;
+
 		/*
-		 * If writeout succeeds, it unlocks the folio.	errors
-		 * are otherwise dropped, since writeout is only best
-		 * effort here.
+		 * Only inject past the first subpage so *nr_pages_backed is
+		 * always > 0 here, matching a genuine mid-compound -ENOMEM
+		 * and driving the caller's reactive split fallback instead
+		 * of an early, no-progress failure.
 		 */
-		if (ret)
+		if (IS_ENABLED(CONFIG_FAULT_INJECTION) && i &&
+		    ttm_backup_fault_inject_folio())
+			to_folio = ERR_PTR(-ENOMEM);
+		else
+			to_folio = shmem_read_folio_gfp(mapping, idx + i, alloc_gfp);
+		if (IS_ERR(to_folio)) {
+			int err = PTR_ERR(to_folio);
+
+			if (err == -ENOMEM && *nr_pages_backed)
+				return ttm_backup_shmem_idx_to_handle(idx);
+
+			if (*nr_pages_backed) {
+				shmem_truncate_range(file_inode(backup),
+						     (loff_t)idx << PAGE_SHIFT,
+						     ((loff_t)(idx + i) << PAGE_SHIFT) - 1);
+				/*
+				 * The pages just truncated are no longer
+				 * backed up; don't let the caller mistake
+				 * them for valid handles.
+				 */
+				*nr_pages_backed = 0;
+			}
+			return err;
+		}
+
+		to_nr = min_t(int, nr_pages - i,
+			      folio_next_index(to_folio) - (idx + i));
+
+		folio_mark_accessed(to_folio);
+		folio_lock(to_folio);
+		folio_mark_dirty(to_folio);
+
+		for (j = 0; j < to_nr; j++)
+			copy_highpage(folio_file_page(to_folio, idx + i + j),
+				      folio_page(folio, i + j));
+
+		if (writeback && !folio_mapped(to_folio) &&
+		    folio_clear_dirty_for_io(to_folio)) {
+			folio_set_reclaim(to_folio);
+			ret = shmem_writeout(to_folio, NULL, NULL);
+			if (!folio_test_writeback(to_folio))
+				folio_clear_reclaim(to_folio);
+			if (ret == AOP_WRITEPAGE_ACTIVATE)
+				folio_unlock(to_folio);
+		} else {
 			folio_unlock(to_folio);
-	} else {
-		folio_unlock(to_folio);
-	}
+		}
 
-	folio_put(to_folio);
+		folio_put(to_folio);
+		i += to_nr;
+		*nr_pages_backed = i;
+	}
 
-	return handle;
+	return ttm_backup_shmem_idx_to_handle(idx);
 }
 
 /**
diff --git linux-libre-7.1.5-gnu/drivers/gpu/drm/ttm/ttm_pool.c linux-libre-7.1.6-gnu/drivers/gpu/drm/ttm/ttm_pool.c
index 278bbe7a11add..e7648ad3e6159 100644
--- linux-libre-7.1.5-gnu/drivers/gpu/drm/ttm/ttm_pool.c
+++ linux-libre-7.1.6-gnu/drivers/gpu/drm/ttm/ttm_pool.c
@@ -53,8 +53,23 @@
 #ifdef CONFIG_FAULT_INJECTION
 #include <linux/fault-inject.h>
 static DECLARE_FAULT_ATTR(backup_fault_inject);
+
+/*
+ * Exposed to ttm_backup.c so a mid-compound subpage can be made to fail
+ * with -ENOMEM, exercising the reactive split-and-retry fallback in
+ * ttm_pool_backup() for high-order backups.
+ */
+bool ttm_backup_fault_inject_folio(void)
+{
+	return should_fail(&backup_fault_inject, 1);
+}
 #else
 #define should_fail(...) false
+
+bool ttm_backup_fault_inject_folio(void)
+{
+	return false;
+}
 #endif
 
 /**
@@ -487,7 +502,7 @@ static void ttm_pool_split_for_swap(struct ttm_pool *pool, struct page *p)
 /**
  * DOC: Partial backup and restoration of a struct ttm_tt.
  *
- * Swapout using ttm_backup_backup_page() and swapin using
+ * Swapout using ttm_backup_backup_folio() and swapin using
  * ttm_backup_copy_page() may fail.
  * The former most likely due to lack of swap-space or memory, the latter due
  * to lack of memory or because of signal interruption during waits.
@@ -1036,12 +1051,12 @@ long ttm_pool_backup(struct ttm_pool *pool, struct ttm_tt *tt,
 {
 	struct file *backup = tt->backup;
 	struct page *page;
-	unsigned long handle;
 	gfp_t alloc_gfp;
 	gfp_t gfp;
 	int ret = 0;
 	pgoff_t shrunken = 0;
-	pgoff_t i, num_pages;
+	pgoff_t i, j, num_pages, npages;
+	pgoff_t nr_backed;
 
 	if (WARN_ON(ttm_tt_is_backed_up(tt)))
 		return -EINVAL;
@@ -1051,9 +1066,31 @@ long ttm_pool_backup(struct ttm_pool *pool, struct ttm_tt *tt,
 		return -EBUSY;
 
 #ifdef CONFIG_X86
-	/* Anything returned to the system needs to be cached. */
-	if (tt->caching != ttm_cached)
-		set_pages_array_wb(tt->pages, tt->num_pages);
+	/* Anything returned to the system needs to be cached. Walk allocations
+	 * skipping NULL pages and issue set_pages_array_wb() per contiguous run.
+	 */
+	if (tt->caching != ttm_cached) {
+		pgoff_t run_start = 0, run_count = 0;
+
+		for (i = 0; i < tt->num_pages; i += num_pages) {
+			page = tt->pages[i];
+			if (unlikely(!page || ttm_backup_page_ptr_is_handle(page))) {
+				if (run_count) {
+					set_pages_array_wb(&tt->pages[run_start],
+							   run_count);
+					run_count = 0;
+				}
+				num_pages = 1;
+				continue;
+			}
+			num_pages = 1UL << ttm_pool_page_order(pool, page);
+			if (!run_count)
+				run_start = i;
+			run_count += num_pages;
+		}
+		if (run_count)
+			set_pages_array_wb(&tt->pages[run_start], run_count);
+	}
 #endif
 
 	if (tt->dma_address || flags->purge) {
@@ -1061,7 +1098,7 @@ long ttm_pool_backup(struct ttm_pool *pool, struct ttm_tt *tt,
 			unsigned int order;
 
 			page = tt->pages[i];
-			if (unlikely(!page)) {
+			if (unlikely(!page || ttm_backup_page_ptr_is_handle(page))) {
 				num_pages = 1;
 				continue;
 			}
@@ -1097,26 +1134,74 @@ long ttm_pool_backup(struct ttm_pool *pool, struct ttm_tt *tt,
 	if (IS_ENABLED(CONFIG_FAULT_INJECTION) && should_fail(&backup_fault_inject, 1))
 		num_pages = DIV_ROUND_UP(num_pages, 2);
 
-	for (i = 0; i < num_pages; ++i) {
-		s64 shandle;
+	for (i = 0; i < num_pages; i += npages) {
+		unsigned int order;
+		s64 handle;
 
+		npages = 1;
 		page = tt->pages[i];
 		if (unlikely(!page))
 			continue;
 
-		ttm_pool_split_for_swap(pool, page);
+		/* Already-handled entry from a previous attempt. */
+		if (unlikely(ttm_backup_page_ptr_is_handle(page)))
+			continue;
 
-		shandle = ttm_backup_backup_page(backup, page, flags->writeback, i,
-						 gfp, alloc_gfp);
-		if (shandle < 0) {
-			/* We allow partially shrunken tts */
-			ret = shandle;
+		order = ttm_pool_page_order(pool, page);
+		npages = 1UL << order;
+
+		/*
+		 * We don't allow dipping kernel reserves for high order backup
+		 */
+		if (order)
+			alloc_gfp |= __GFP_NOMEMALLOC;
+		else
+			alloc_gfp &= ~__GFP_NOMEMALLOC;
+
+		/*
+		 * Back up the compound atomically at its native order. If
+		 * fault injection truncated num_pages mid-compound, skip
+		 * the partial tail rather than splitting.
+		 */
+		if (unlikely(i + npages > num_pages))
+			break;
+
+		handle = ttm_backup_backup_folio(backup, page_folio(page),
+						 order, flags->writeback, i,
+						 gfp, alloc_gfp,
+						 &nr_backed);
+		/*
+		 * Zero progress on this compound (whether order 0 or a
+		 * high-order compound that failed before backing up even
+		 * its first subpage) is unrecoverable: bail out rather than
+		 * looping forever with npages == nr_backed == 0 below.
+		 */
+		if (unlikely(handle < 0 && !nr_backed)) {
+			ret = handle;
 			break;
 		}
-		handle = shandle;
-		tt->pages[i] = ttm_backup_handle_to_page_ptr(handle);
-		__free_pages_gpu_account(page, 0, false);
-		shrunken++;
+
+		for (j = 0; j < nr_backed; j++)
+			tt->pages[i + j] = ttm_backup_handle_to_page_ptr(handle + j);
+
+		shrunken += nr_backed;
+
+		if (unlikely(nr_backed < npages)) {
+			/*
+			 * Partial OOM backup: split the compound and free the
+			 * subpages whose content is now in shmem. Continue the
+			 * loop from the first un-backed order-0 page.
+			 */
+			ttm_pool_split_for_swap(pool, page);
+			for (j = 0; j < nr_backed; j++)
+				__free_pages_gpu_account(page + j, 0, false);
+			npages = nr_backed;
+			continue;
+		}
+
+		/* Fully backed up: free at native order. */
+		page->private = 0;
+		__free_pages_gpu_account(page, order, false);
 	}
 
 	return shrunken ? shrunken : ret;
diff --git linux-libre-7.1.5-gnu/drivers/gpu/drm/ttm/ttm_pool_internal.h linux-libre-7.1.6-gnu/drivers/gpu/drm/ttm/ttm_pool_internal.h
index 24c179fd69d1a..cbb17a2129fee 100644
--- linux-libre-7.1.5-gnu/drivers/gpu/drm/ttm/ttm_pool_internal.h
+++ linux-libre-7.1.6-gnu/drivers/gpu/drm/ttm/ttm_pool_internal.h
@@ -22,4 +22,12 @@ static inline unsigned int ttm_pool_beneficial_order(struct ttm_pool *pool)
 	return pool->alloc_flags & 0xff;
 }
 
+/*
+ * Implemented in ttm_pool.c, used by ttm_backup.c. Returns true if a fault
+ * should be injected mid-compound to test the reactive split-and-retry
+ * fallback in ttm_pool_backup(). Always returns false when
+ * CONFIG_FAULT_INJECTION is disabled.
+ */
+bool ttm_backup_fault_inject_folio(void);
+
 #endif
diff --git linux-libre-7.1.5-gnu/drivers/gpu/drm/v3d/v3d_gem.c linux-libre-7.1.6-gnu/drivers/gpu/drm/v3d/v3d_gem.c
index dd7da419702fc..8277b3182754b 100644
--- linux-libre-7.1.5-gnu/drivers/gpu/drm/v3d/v3d_gem.c
+++ linux-libre-7.1.6-gnu/drivers/gpu/drm/v3d/v3d_gem.c
@@ -46,6 +46,18 @@ v3d_init_hw_state(struct v3d_dev *v3d)
 static void
 v3d_idle_axi(struct v3d_dev *v3d, int core)
 {
+	if (v3d->ver >= V3D_GEN_71) {
+		V3D_WRITE(V3D_GMP_CFG(v3d->ver), V3D_GMP_CFG_STOP_REQ);
+
+		if (wait_for((V3D_READ(V3D_GMP_STATUS(v3d->ver)) &
+			      (V3D_GMP_STATUS_RD_COUNT_MASK |
+			       V3D_GMP_STATUS_WR_COUNT_MASK |
+			       V3D_GMP_STATUS_CFG_BUSY)) == 0, 100)) {
+			drm_err(&v3d->drm, "Failed to wait for safe GMP shutdown\n");
+		}
+		return;
+	}
+
 	V3D_CORE_WRITE(core, V3D_GMP_CFG(v3d->ver), V3D_GMP_CFG_STOP_REQ);
 
 	if (wait_for((V3D_CORE_READ(core, V3D_GMP_STATUS(v3d->ver)) &
diff --git linux-libre-7.1.5-gnu/drivers/gpu/drm/vc4/vc4_bo.c linux-libre-7.1.6-gnu/drivers/gpu/drm/vc4/vc4_bo.c
index 9377e58f9bc25..9e7c26244aedf 100644
--- linux-libre-7.1.5-gnu/drivers/gpu/drm/vc4/vc4_bo.c
+++ linux-libre-7.1.6-gnu/drivers/gpu/drm/vc4/vc4_bo.c
@@ -733,9 +733,13 @@ static int vc4_gem_object_mmap(struct drm_gem_object *obj, struct vm_area_struct
 {
 	struct vc4_bo *bo = to_vc4_bo(obj);
 
-	if (bo->validated_shader && (vma->vm_flags & VM_WRITE)) {
-		DRM_DEBUG("mmapping of shader BOs for writing not allowed.\n");
-		return -EINVAL;
+	if (bo->validated_shader) {
+		if (vma->vm_flags & VM_WRITE) {
+			DRM_DEBUG("mmapping of shader BOs for writing not allowed.\n");
+			return -EINVAL;
+		}
+
+		vm_flags_clear(vma, VM_MAYWRITE);
 	}
 
 	mutex_lock(&bo->madv_lock);
@@ -1045,7 +1049,7 @@ static void vc4_bo_cache_destroy(struct drm_device *dev, void *unused)
 	struct vc4_dev *vc4 = to_vc4_dev(dev);
 	int i;
 
-	timer_delete(&vc4->bo_cache.time_timer);
+	timer_shutdown_sync(&vc4->bo_cache.time_timer);
 	cancel_work_sync(&vc4->bo_cache.time_work);
 
 	vc4_bo_cache_purge(dev);
diff --git linux-libre-7.1.5-gnu/drivers/gpu/drm/vc4/vc4_hvs.c linux-libre-7.1.6-gnu/drivers/gpu/drm/vc4/vc4_hvs.c
index ee8d0738501b8..89359d1900087 100644
--- linux-libre-7.1.5-gnu/drivers/gpu/drm/vc4/vc4_hvs.c
+++ linux-libre-7.1.6-gnu/drivers/gpu/drm/vc4/vc4_hvs.c
@@ -1752,7 +1752,7 @@ static int vc4_hvs_bind(struct device *dev, struct device *master, void *data)
 static void vc4_hvs_unbind(struct device *dev, struct device *master,
 			   void *data)
 {
-	struct drm_device *drm = dev_get_drvdata(master);
+	struct drm_device *drm = data;
 	struct vc4_dev *vc4 = to_vc4_dev(drm);
 	struct vc4_hvs *hvs = vc4->hvs;
 	struct drm_mm_node *node, *next;
diff --git linux-libre-7.1.5-gnu/drivers/gpu/drm/vc4/vc4_v3d.c linux-libre-7.1.6-gnu/drivers/gpu/drm/vc4/vc4_v3d.c
index d31b906cb8e78..f32410420d3e4 100644
--- linux-libre-7.1.5-gnu/drivers/gpu/drm/vc4/vc4_v3d.c
+++ linux-libre-7.1.6-gnu/drivers/gpu/drm/vc4/vc4_v3d.c
@@ -494,7 +494,7 @@ err_put_runtime_pm:
 static void vc4_v3d_unbind(struct device *dev, struct device *master,
 			   void *data)
 {
-	struct drm_device *drm = dev_get_drvdata(master);
+	struct drm_device *drm = data;
 	struct vc4_dev *vc4 = to_vc4_dev(drm);
 
 	vc4_irq_uninstall(drm);
diff --git linux-libre-7.1.5-gnu/drivers/gpu/drm/virtio/virtgpu_gem.c linux-libre-7.1.6-gnu/drivers/gpu/drm/virtio/virtgpu_gem.c
index 435d37d360340..66c3f6f74e9c6 100644
--- linux-libre-7.1.5-gnu/drivers/gpu/drm/virtio/virtgpu_gem.c
+++ linux-libre-7.1.6-gnu/drivers/gpu/drm/virtio/virtgpu_gem.c
@@ -139,13 +139,15 @@ void virtio_gpu_gem_object_close(struct drm_gem_object *obj,
 	if (!vgdev->has_virgl_3d)
 		return;
 
-	objs = virtio_gpu_array_alloc(1);
-	if (!objs)
-		return;
-	virtio_gpu_array_add_obj(objs, obj);
+	if (vfpriv->context_created) {
+		objs = virtio_gpu_array_alloc(1);
+		if (!objs)
+			return;
+		virtio_gpu_array_add_obj(objs, obj);
 
-	virtio_gpu_cmd_context_detach_resource(vgdev, vfpriv->ctx_id,
-					       objs);
+		virtio_gpu_cmd_context_detach_resource(vgdev, vfpriv->ctx_id,
+						       objs);
+	}
 	virtio_gpu_notify(vgdev);
 }
 
diff --git linux-libre-7.1.5-gnu/drivers/gpu/drm/virtio/virtgpu_kms.c linux-libre-7.1.6-gnu/drivers/gpu/drm/virtio/virtgpu_kms.c
index 80ba69b4860bc..b79fd8350b6a4 100644
--- linux-libre-7.1.5-gnu/drivers/gpu/drm/virtio/virtgpu_kms.c
+++ linux-libre-7.1.6-gnu/drivers/gpu/drm/virtio/virtgpu_kms.c
@@ -49,7 +49,10 @@ static void virtio_gpu_config_changed_work_func(struct work_struct *work)
 				virtio_gpu_cmd_get_edids(vgdev);
 			virtio_gpu_cmd_get_display_info(vgdev);
 			virtio_gpu_notify(vgdev);
-			drm_helper_hpd_irq_event(vgdev->ddev);
+			wait_event_timeout(vgdev->resp_wq,
+					   !vgdev->display_info_pending,
+					   5 * HZ);
+			drm_kms_helper_hotplug_event(vgdev->ddev);
 		}
 		events_clear |= VIRTIO_GPU_EVENT_DISPLAY;
 	}
diff --git linux-libre-7.1.5-gnu/drivers/gpu/drm/virtio/virtgpu_vq.c linux-libre-7.1.6-gnu/drivers/gpu/drm/virtio/virtgpu_vq.c
index 67865810a2e70..e5e1af8b8e8a0 100644
--- linux-libre-7.1.5-gnu/drivers/gpu/drm/virtio/virtgpu_vq.c
+++ linux-libre-7.1.6-gnu/drivers/gpu/drm/virtio/virtgpu_vq.c
@@ -840,9 +840,6 @@ static void virtio_gpu_cmd_get_display_info_cb(struct virtio_gpu_device *vgdev,
 	vgdev->display_info_pending = false;
 	spin_unlock(&vgdev->display_info_lock);
 	wake_up(&vgdev->resp_wq);
-
-	if (!drm_helper_hpd_irq_event(vgdev->ddev))
-		drm_kms_helper_hotplug_event(vgdev->ddev);
 }
 
 static void virtio_gpu_cmd_get_capset_info_cb(struct virtio_gpu_device *vgdev,
@@ -897,7 +894,8 @@ static int virtio_get_edid_block(void *data, u8 *buf,
 	struct virtio_gpu_resp_edid *resp = data;
 	size_t start = block * EDID_LENGTH;
 
-	if (start + len > le32_to_cpu(resp->size))
+	if (start + len > le32_to_cpu(resp->size) ||
+	    start + len > sizeof(resp->edid))
 		return -EINVAL;
 	memcpy(buf, resp->edid + start, len);
 	return 0;
diff --git linux-libre-7.1.5-gnu/drivers/gpu/drm/vmwgfx/vmwgfx_surface.c linux-libre-7.1.6-gnu/drivers/gpu/drm/vmwgfx/vmwgfx_surface.c
index b2d3927b55673..bd0563741e89d 100644
--- linux-libre-7.1.5-gnu/drivers/gpu/drm/vmwgfx/vmwgfx_surface.c
+++ linux-libre-7.1.6-gnu/drivers/gpu/drm/vmwgfx/vmwgfx_surface.c
@@ -78,7 +78,7 @@ static int vmw_gb_surface_unbind(struct vmw_resource *res,
 static int vmw_gb_surface_destroy(struct vmw_resource *res);
 static int
 vmw_gb_surface_define_internal(struct drm_device *dev,
-			       struct drm_vmw_gb_surface_create_ext_req *req,
+			       const  struct drm_vmw_gb_surface_create_ext_req *req,
 			       struct drm_vmw_gb_surface_create_rep *rep,
 			       struct drm_file *file_priv);
 static int
@@ -1503,7 +1503,7 @@ int vmw_gb_surface_reference_ext_ioctl(struct drm_device *dev, void *data,
  */
 static int
 vmw_gb_surface_define_internal(struct drm_device *dev,
-			       struct drm_vmw_gb_surface_create_ext_req *req,
+			       const  struct drm_vmw_gb_surface_create_ext_req *req,
 			       struct drm_vmw_gb_surface_create_rep *rep,
 			       struct drm_file *file_priv)
 {
@@ -1521,9 +1521,21 @@ vmw_gb_surface_define_internal(struct drm_device *dev,
 				req->base.svga3d_flags);
 
 	/* array_size must be null for non-GL3 host. */
-	if (req->base.array_size > 0 && !has_sm4_context(dev_priv)) {
-		VMW_DEBUG_USER("SM4 surface not supported.\n");
-		return -EINVAL;
+	if (req->base.array_size > 0) {
+		if (has_sm5_context(dev_priv)) {
+			if (req->base.array_size > SVGA3D_SM5_MAX_SURFACE_ARRAYSIZE) {
+				VMW_DEBUG_USER("Invalid Surface Array Size.\n");
+				return -EINVAL;
+			}
+		} else if (has_sm4_context(dev_priv)) {
+			if (req->base.array_size > SVGA3D_SM4_MAX_SURFACE_ARRAYSIZE) {
+				VMW_DEBUG_USER("Invalid Surface Array Size.\n");
+				return -EINVAL;
+			}
+		} else {
+			VMW_DEBUG_USER("SM4+ surface not supported.\n");
+			return -EINVAL;
+		}
 	}
 
 	if (!has_sm4_1_context(dev_priv)) {
diff --git linux-libre-7.1.5-gnu/drivers/gpu/drm/xe/display/xe_display_bo.c linux-libre-7.1.6-gnu/drivers/gpu/drm/xe/display/xe_display_bo.c
index 1d81b9908265f..4958217172062 100644
--- linux-libre-7.1.5-gnu/drivers/gpu/drm/xe/display/xe_display_bo.c
+++ linux-libre-7.1.6-gnu/drivers/gpu/drm/xe/display/xe_display_bo.c
@@ -42,7 +42,8 @@ static int xe_display_bo_framebuffer_init(struct drm_gem_object *obj,
 	if (ret)
 		goto err;
 
-	if (!(bo->flags & XE_BO_FLAG_FORCE_WC)) {
+	if (!(bo->flags & XE_BO_FLAG_FORCE_WC) &&
+	    bo->ttm.type != ttm_bo_type_sg) {
 		/*
 		 * XE_BO_FLAG_FORCE_WC should ideally be set at creation, or is
 		 * automatically set when creating FB. We cannot change caching
diff --git linux-libre-7.1.5-gnu/drivers/gpu/drm/xe/display/xe_fb_pin.c linux-libre-7.1.6-gnu/drivers/gpu/drm/xe/display/xe_fb_pin.c
index e45a1e7a4670e..bfbe3e44e78d5 100644
--- linux-libre-7.1.5-gnu/drivers/gpu/drm/xe/display/xe_fb_pin.c
+++ linux-libre-7.1.6-gnu/drivers/gpu/drm/xe/display/xe_fb_pin.c
@@ -481,7 +481,8 @@ int intel_plane_pin_fb(struct intel_plane_state *new_plane_state,
 		return 0;
 
 	/* We reject creating !SCANOUT fb's, so this is weird.. */
-	drm_WARN_ON(bo->ttm.base.dev, !(bo->flags & XE_BO_FLAG_FORCE_WC));
+	drm_WARN_ON(bo->ttm.base.dev, !(bo->flags & XE_BO_FLAG_FORCE_WC) &&
+		    bo->ttm.type != ttm_bo_type_sg);
 
 	vma = __xe_pin_fb_vma(intel_fb, &new_plane_state->view.gtt, alignment);
 
diff --git linux-libre-7.1.5-gnu/drivers/gpu/drm/xe/regs/xe_gtt_defs.h linux-libre-7.1.6-gnu/drivers/gpu/drm/xe/regs/xe_gtt_defs.h
index 4d83461e538b1..d6bc19ef277be 100644
--- linux-libre-7.1.5-gnu/drivers/gpu/drm/xe/regs/xe_gtt_defs.h
+++ linux-libre-7.1.6-gnu/drivers/gpu/drm/xe/regs/xe_gtt_defs.h
@@ -9,7 +9,11 @@
 #define XELPG_GGTT_PTE_PAT0	BIT_ULL(52)
 #define XELPG_GGTT_PTE_PAT1	BIT_ULL(53)
 
-#define XE_PTE_ADDR_MASK	GENMASK_ULL(51, 12)
+/*
+ * Mask for PTE address bits [51:shift].
+ * shift is the lower address boundary of page.
+ */
+#define XE_PAGE_ADDR_MASK(shift)	GENMASK_ULL(51, (shift))
 #define GGTT_PTE_VFID		GENMASK_ULL(11, 2)
 
 #define GUC_GGTT_TOP		0xFEE00000
diff --git linux-libre-7.1.5-gnu/drivers/gpu/drm/xe/xe_bo.c linux-libre-7.1.6-gnu/drivers/gpu/drm/xe/xe_bo.c
index 6b518858538f5..013b7f3e0649f 100644
--- linux-libre-7.1.5-gnu/drivers/gpu/drm/xe/xe_bo.c
+++ linux-libre-7.1.6-gnu/drivers/gpu/drm/xe/xe_bo.c
@@ -1109,6 +1109,21 @@ static int xe_bo_move(struct ttm_buffer_object *ttm_bo, bool evict,
 		xe_pm_runtime_get_noresume(xe);
 	}
 
+	/*
+	 * Attach CCS BBs before submitting the copy job below so a VF
+	 * migration racing the copy sees valid, up to date attach state.
+	 */
+	if (IS_VF_CCS_READY(xe) &&
+	    ((move_lacks_source && new_mem->mem_type == XE_PL_TT) ||
+	     (old_mem_type == XE_PL_SYSTEM && new_mem->mem_type == XE_PL_TT)) &&
+	    handle_system_ccs) {
+		ret = xe_sriov_vf_ccs_attach_bo(bo, new_mem);
+		if (ret) {
+			xe_pm_runtime_put(xe);
+			goto out;
+		}
+	}
+
 	if (move_lacks_source) {
 		u32 flags = 0;
 
@@ -1146,22 +1161,19 @@ static int xe_bo_move(struct ttm_buffer_object *ttm_bo, bool evict,
 		ttm_bo_move_null(ttm_bo, new_mem);
 	}
 
-	dma_fence_put(fence);
-	xe_pm_runtime_put(xe);
-
 	/*
-	 * CCS meta data is migrated from TT -> SMEM. So, let us detach the
-	 * BBs from BO as it is no longer needed.
+	 * Detach must wait for the copy above to complete: a VF migration
+	 * racing an in-flight copy must still see valid CCS BBs, so don't
+	 * tear them down until the copy fence has signaled.
 	 */
 	if (IS_VF_CCS_READY(xe) && old_mem_type == XE_PL_TT &&
-	    new_mem->mem_type == XE_PL_SYSTEM)
+	    new_mem->mem_type == XE_PL_SYSTEM) {
+		dma_fence_wait(fence, false);
 		xe_sriov_vf_ccs_detach_bo(bo);
+	}
 
-	if (IS_VF_CCS_READY(xe) &&
-	    ((move_lacks_source && new_mem->mem_type == XE_PL_TT) ||
-	     (old_mem_type == XE_PL_SYSTEM && new_mem->mem_type == XE_PL_TT)) &&
-	    handle_system_ccs)
-		ret = xe_sriov_vf_ccs_attach_bo(bo);
+	dma_fence_put(fence);
+	xe_pm_runtime_put(xe);
 
 out:
 	if ((!ttm_bo->resource || ttm_bo->resource->mem_type == XE_PL_SYSTEM) &&
@@ -1356,7 +1368,7 @@ int xe_bo_notifier_prepare_pinned(struct xe_bo *bo)
 		backup = xe_bo_init_locked(xe, NULL, NULL, bo->ttm.base.resv, NULL, xe_bo_size(bo),
 					   DRM_XE_GEM_CPU_CACHING_WB, ttm_bo_type_kernel,
 					   XE_BO_FLAG_SYSTEM | XE_BO_FLAG_NEEDS_CPU_ACCESS |
-					   XE_BO_FLAG_PINNED, &exec);
+					   XE_BO_FLAG_PINNED, NULL, &exec);
 		if (IS_ERR(backup)) {
 			drm_exec_retry_on_contention(&exec);
 			ret = PTR_ERR(backup);
@@ -1497,7 +1509,7 @@ int xe_bo_evict_pinned(struct xe_bo *bo)
 						   xe_bo_size(bo),
 						   DRM_XE_GEM_CPU_CACHING_WB, ttm_bo_type_kernel,
 						   XE_BO_FLAG_SYSTEM | XE_BO_FLAG_NEEDS_CPU_ACCESS |
-						   XE_BO_FLAG_PINNED, &exec);
+						   XE_BO_FLAG_PINNED, NULL, &exec);
 			if (IS_ERR(backup)) {
 				drm_exec_retry_on_contention(&exec);
 				ret = PTR_ERR(backup);
@@ -1833,6 +1845,8 @@ static void xe_ttm_bo_destroy(struct ttm_buffer_object *ttm_bo)
 
 	if (bo->ttm.base.import_attach)
 		drm_prime_gem_destroy(&bo->ttm.base, NULL);
+	if (bo->dma_buf)
+		dma_buf_put(bo->dma_buf);
 	drm_gem_object_release(&bo->ttm.base);
 
 	xe_assert(xe, list_empty(&ttm_bo->base.gpuva.list));
@@ -2290,6 +2304,8 @@ void xe_bo_free(struct xe_bo *bo)
  * @cpu_caching: The cpu caching used for system memory backing store.
  * @type: The TTM buffer object type.
  * @flags: XE_BO_FLAG_ flags.
+ * @dma_buf: The dma-buf to reference for the BO lifetime (imported BOs),
+ * or NULL.
  * @exec: The drm_exec transaction to use for exhaustive eviction.
  *
  * Initialize or create an xe buffer object. On failure, any allocated buffer
@@ -2301,7 +2317,8 @@ struct xe_bo *xe_bo_init_locked(struct xe_device *xe, struct xe_bo *bo,
 				struct xe_tile *tile, struct dma_resv *resv,
 				struct ttm_lru_bulk_move *bulk, size_t size,
 				u16 cpu_caching, enum ttm_bo_type type,
-				u32 flags, struct drm_exec *exec)
+				u32 flags, struct dma_buf *dma_buf,
+				struct drm_exec *exec)
 {
 	struct ttm_operation_ctx ctx = {
 		.interruptible = true,
@@ -2390,6 +2407,17 @@ struct xe_bo *xe_bo_init_locked(struct xe_device *xe, struct xe_bo *bo,
 	placement = (type == ttm_bo_type_sg ||
 		     bo->flags & XE_BO_FLAG_DEFER_BACKING) ? &sys_placement :
 		&bo->placement;
+
+	/*
+	 * For imported BOs, keep the exporter dma-buf alive for the BO
+	 * lifetime. Taken before ttm_bo_init_reserved() to also cover a
+	 * creation failure there. Released in xe_ttm_bo_destroy().
+	 */
+	if (dma_buf) {
+		get_dma_buf(dma_buf);
+		bo->dma_buf = dma_buf;
+	}
+
 	err = ttm_bo_init_reserved(&xe->ttm, &bo->ttm, type,
 				   placement, alignment,
 				   &ctx, NULL, resv, xe_ttm_bo_destroy);
@@ -2507,7 +2535,7 @@ __xe_bo_create_locked(struct xe_device *xe,
 			       vm && !xe_vm_in_fault_mode(vm) &&
 			       flags & XE_BO_FLAG_USER ?
 			       &vm->lru_bulk_move : NULL, size,
-			       cpu_caching, type, flags, exec);
+			       cpu_caching, type, flags, NULL, exec);
 	if (IS_ERR(bo))
 		return bo;
 
diff --git linux-libre-7.1.5-gnu/drivers/gpu/drm/xe/xe_bo.h linux-libre-7.1.6-gnu/drivers/gpu/drm/xe/xe_bo.h
index 6340317f7d2e6..7ae1d9ac05743 100644
--- linux-libre-7.1.5-gnu/drivers/gpu/drm/xe/xe_bo.h
+++ linux-libre-7.1.6-gnu/drivers/gpu/drm/xe/xe_bo.h
@@ -118,7 +118,8 @@ struct xe_bo *xe_bo_init_locked(struct xe_device *xe, struct xe_bo *bo,
 				struct xe_tile *tile, struct dma_resv *resv,
 				struct ttm_lru_bulk_move *bulk, size_t size,
 				u16 cpu_caching, enum ttm_bo_type type,
-				u32 flags, struct drm_exec *exec);
+				u32 flags, struct dma_buf *dma_buf,
+				struct drm_exec *exec);
 struct xe_bo *xe_bo_create_locked(struct xe_device *xe, struct xe_tile *tile,
 				  struct xe_vm *vm, size_t size,
 				  enum ttm_bo_type type, u32 flags,
diff --git linux-libre-7.1.5-gnu/drivers/gpu/drm/xe/xe_bo_types.h linux-libre-7.1.6-gnu/drivers/gpu/drm/xe/xe_bo_types.h
index 077e35b4cdce7..b1cdd7acc15c6 100644
--- linux-libre-7.1.5-gnu/drivers/gpu/drm/xe/xe_bo_types.h
+++ linux-libre-7.1.6-gnu/drivers/gpu/drm/xe/xe_bo_types.h
@@ -36,6 +36,8 @@ struct xe_bo {
 	struct xe_bo *backup_obj;
 	/** @parent_obj: Ref to parent bo if this a backup_obj */
 	struct xe_bo *parent_obj;
+	/** @dma_buf: Imported dma-buf ref to keep its resv alive. */
+	struct dma_buf *dma_buf;
 	/** @flags: flags for this buffer object */
 	u32 flags;
 	/** @vm: VM this BO is attached to, for extobj this will be NULL */
diff --git linux-libre-7.1.5-gnu/drivers/gpu/drm/xe/xe_device.c linux-libre-7.1.6-gnu/drivers/gpu/drm/xe/xe_device.c
index ffea4a453c01c..991b0ea9218bb 100644
--- linux-libre-7.1.5-gnu/drivers/gpu/drm/xe/xe_device.c
+++ linux-libre-7.1.6-gnu/drivers/gpu/drm/xe/xe_device.c
@@ -509,7 +509,7 @@ struct xe_device *xe_device_create(struct pci_dev *pdev,
 						       WQ_MEM_RECLAIM);
 	xe->ordered_wq = alloc_ordered_workqueue("xe-ordered-wq", 0);
 	xe->unordered_wq = alloc_workqueue("xe-unordered-wq", WQ_PERCPU, 0);
-	xe->destroy_wq = alloc_workqueue("xe-destroy-wq", WQ_PERCPU, 0);
+	xe->destroy_wq = alloc_workqueue("xe-destroy-wq", WQ_PERCPU | WQ_MEM_RECLAIM, 0);
 	if (!xe->ordered_wq || !xe->unordered_wq ||
 	    !xe->preempt_fence_wq || !xe->destroy_wq) {
 		/*
diff --git linux-libre-7.1.5-gnu/drivers/gpu/drm/xe/xe_device_types.h linux-libre-7.1.6-gnu/drivers/gpu/drm/xe/xe_device_types.h
index 615218d775b14..7e0901ac95c91 100644
--- linux-libre-7.1.5-gnu/drivers/gpu/drm/xe/xe_device_types.h
+++ linux-libre-7.1.6-gnu/drivers/gpu/drm/xe/xe_device_types.h
@@ -351,7 +351,7 @@ struct xe_device {
 	/** @unordered_wq: used to serialize unordered work */
 	struct workqueue_struct *unordered_wq;
 
-	/** @destroy_wq: used to serialize user destroy work, like queue */
+	/** @destroy_wq: used to serialize SVM pagemap destroy work */
 	struct workqueue_struct *destroy_wq;
 
 	/** @tiles: device tiles */
diff --git linux-libre-7.1.5-gnu/drivers/gpu/drm/xe/xe_dma_buf.c linux-libre-7.1.6-gnu/drivers/gpu/drm/xe/xe_dma_buf.c
index 8a920e58245cd..bf0728838ead5 100644
--- linux-libre-7.1.5-gnu/drivers/gpu/drm/xe/xe_dma_buf.c
+++ linux-libre-7.1.6-gnu/drivers/gpu/drm/xe/xe_dma_buf.c
@@ -302,7 +302,7 @@ xe_dma_buf_create_obj(struct drm_device *dev, struct dma_buf *dma_buf)
 
 		bo = xe_bo_init_locked(xe, NULL, NULL, resv, NULL, dma_buf->size,
 				       0, /* Will require 1way or 2way for vm_bind */
-				       ttm_bo_type_sg, XE_BO_FLAG_SYSTEM, &exec);
+				       ttm_bo_type_sg, XE_BO_FLAG_SYSTEM, dma_buf, &exec);
 		drm_exec_retry_on_contention(&exec);
 		if (IS_ERR(bo)) {
 			ret = PTR_ERR(bo);
diff --git linux-libre-7.1.5-gnu/drivers/gpu/drm/xe/xe_guc_capture.c linux-libre-7.1.6-gnu/drivers/gpu/drm/xe/xe_guc_capture.c
index 2f5816c78fba2..14d175f22e0e6 100644
--- linux-libre-7.1.5-gnu/drivers/gpu/drm/xe/xe_guc_capture.c
+++ linux-libre-7.1.6-gnu/drivers/gpu/drm/xe/xe_guc_capture.c
@@ -461,8 +461,14 @@ static void guc_capture_alloc_steered_lists(struct xe_guc *guc)
 	if (!list || guc->capture->extlists)
 		return;
 
-	total = bitmap_weight(gt->fuse_topo.g_dss_mask, sizeof(gt->fuse_topo.g_dss_mask) * 8) *
-		guc_capture_get_steer_reg_num(guc_to_xe(guc));
+	{
+		xe_dss_mask_t all_dss;
+
+		total = bitmap_weighted_or(all_dss, gt->fuse_topo.g_dss_mask,
+					   gt->fuse_topo.c_dss_mask,
+					   XE_MAX_DSS_FUSE_BITS) *
+			guc_capture_get_steer_reg_num(guc_to_xe(guc));
+	}
 
 	if (!total)
 		return;
diff --git linux-libre-7.1.5-gnu/drivers/gpu/drm/xe/xe_guc_exec_queue_types.h linux-libre-7.1.6-gnu/drivers/gpu/drm/xe/xe_guc_exec_queue_types.h
index e5e53b421f29f..cda14d954e572 100644
--- linux-libre-7.1.5-gnu/drivers/gpu/drm/xe/xe_guc_exec_queue_types.h
+++ linux-libre-7.1.6-gnu/drivers/gpu/drm/xe/xe_guc_exec_queue_types.h
@@ -10,6 +10,7 @@
 #include <linux/workqueue.h>
 
 #include "xe_gpu_scheduler_types.h"
+#include "xe_hw_fence_types.h"
 
 struct dma_fence;
 struct xe_exec_queue;
@@ -24,6 +25,10 @@ struct xe_guc_exec_queue {
 	struct rcu_head rcu;
 	/** @sched: GPU scheduler for this xe_exec_queue */
 	struct xe_gpu_scheduler sched;
+	/**
+	 * @name: Scheduler timeline name, kept with @sched until RCU free.
+	 */
+	char name[MAX_FENCE_NAME_LEN];
 	/** @entity: Scheduler entity for this xe_exec_queue */
 	struct xe_sched_entity entity;
 	/**
diff --git linux-libre-7.1.5-gnu/drivers/gpu/drm/xe/xe_guc_submit.c linux-libre-7.1.6-gnu/drivers/gpu/drm/xe/xe_guc_submit.c
index 42110e01b7d09..b8465553aed2d 100644
--- linux-libre-7.1.5-gnu/drivers/gpu/drm/xe/xe_guc_submit.c
+++ linux-libre-7.1.6-gnu/drivers/gpu/drm/xe/xe_guc_submit.c
@@ -10,6 +10,7 @@
 #include <linux/circ_buf.h>
 #include <linux/dma-fence-array.h>
 
+#include <drm/drm_drv.h>
 #include <drm/drm_managed.h>
 
 #include "abi/guc_actions_abi.h"
@@ -37,6 +38,7 @@
 #include "xe_macros.h"
 #include "xe_map.h"
 #include "xe_mocs.h"
+#include "xe_module.h"
 #include "xe_pm.h"
 #include "xe_ring_ops_types.h"
 #include "xe_sched_job.h"
@@ -232,17 +234,9 @@ static bool exec_queue_killed_or_banned_or_wedged(struct xe_exec_queue *q)
 static void guc_submit_sw_fini(struct drm_device *drm, void *arg)
 {
 	struct xe_guc *guc = arg;
-	struct xe_device *xe = guc_to_xe(guc);
 	struct xe_gt *gt = guc_to_gt(guc);
-	int ret;
-
-	ret = wait_event_timeout(guc->submission_state.fini_wq,
-				 xa_empty(&guc->submission_state.exec_queue_lookup),
-				 HZ * 5);
-
-	drain_workqueue(xe->destroy_wq);
 
-	xe_gt_assert(gt, ret);
+	xe_gt_assert(gt, xa_empty(&guc->submission_state.exec_queue_lookup));
 
 	xa_destroy(&guc->submission_state.exec_queue_lookup);
 }
@@ -319,8 +313,6 @@ int xe_guc_submit_init(struct xe_guc *guc, unsigned int num_ids)
 
 	xa_init(&guc->submission_state.exec_queue_lookup);
 
-	init_waitqueue_head(&guc->submission_state.fini_wq);
-
 	primelockdep(guc);
 
 	guc->submission_state.initialized = true;
@@ -397,46 +389,40 @@ void xe_guc_submit_disable(struct xe_guc *guc)
 	guc->submission_state.enabled = false;
 }
 
-static void __release_guc_id(struct xe_guc *guc, struct xe_exec_queue *q, u32 xa_count)
+static void __release_guc_id(struct xe_guc *guc, struct xe_exec_queue *q,
+			     int count)
 {
 	int i;
 
-	lockdep_assert_held(&guc->submission_state.lock);
+	mutex_lock(&guc->submission_state.lock);
 
-	for (i = 0; i < xa_count; ++i)
-		xa_erase(&guc->submission_state.exec_queue_lookup, q->guc->id + i);
+	for (i = 0; i < count; ++i)
+		xa_erase(&guc->submission_state.exec_queue_lookup,
+			 q->guc->id + i);
 
 	xe_guc_id_mgr_release_locked(&guc->submission_state.idm,
 				     q->guc->id, q->width);
 
-	if (xa_empty(&guc->submission_state.exec_queue_lookup))
-		wake_up(&guc->submission_state.fini_wq);
+	mutex_unlock(&guc->submission_state.lock);
 }
 
 static int alloc_guc_id(struct xe_guc *guc, struct xe_exec_queue *q)
 {
-	int ret;
-	int i;
-
-	/*
-	 * Must use GFP_NOWAIT as this lock is in the dma fence signalling path,
-	 * worse case user gets -ENOMEM on engine create and has to try again.
-	 *
-	 * FIXME: Have caller pre-alloc or post-alloc /w GFP_KERNEL to prevent
-	 * failure.
-	 */
-	lockdep_assert_held(&guc->submission_state.lock);
+	int ret, i;
 
+	mutex_lock(&guc->submission_state.lock);
 	ret = xe_guc_id_mgr_reserve_locked(&guc->submission_state.idm,
 					   q->width);
+	mutex_unlock(&guc->submission_state.lock);
 	if (ret < 0)
 		return ret;
 
 	q->guc->id = ret;
 
+	/* Reserve empty slots. */
 	for (i = 0; i < q->width; ++i) {
-		ret = xa_err(xa_store(&guc->submission_state.exec_queue_lookup,
-				      q->guc->id + i, q, GFP_NOWAIT));
+		ret = xa_insert(&guc->submission_state.exec_queue_lookup,
+				 q->guc->id + i, NULL, GFP_KERNEL);
 		if (ret)
 			goto err_release;
 	}
@@ -449,11 +435,24 @@ err_release:
 	return ret;
 }
 
+static void publish_guc_id(struct xe_guc *guc, struct xe_exec_queue *q)
+{
+	int i;
+
+	lockdep_assert_held(&guc->submission_state.lock);
+
+	for (i = 0; i < q->width; ++i) {
+		void *old;
+
+		old = xa_store(&guc->submission_state.exec_queue_lookup,
+			       q->guc->id + i, q, GFP_NOWAIT);
+		XE_WARN_ON(old || xa_is_err(old));
+	}
+}
+
 static void release_guc_id(struct xe_guc *guc, struct xe_exec_queue *q)
 {
-	mutex_lock(&guc->submission_state.lock);
 	__release_guc_id(guc, q, q->width);
-	mutex_unlock(&guc->submission_state.lock);
 }
 
 struct exec_queue_policy {
@@ -1680,6 +1679,7 @@ static void guc_exec_queue_fini(struct xe_exec_queue *q)
 {
 	struct xe_guc_exec_queue *ge = q->guc;
 	struct xe_guc *guc = exec_queue_to_guc(q);
+	struct drm_device *drm = &guc_to_xe(guc)->drm;
 
 	if (xe_exec_queue_is_multi_queue_secondary(q)) {
 		struct xe_exec_queue_group *group = q->multi_queue.group;
@@ -1698,36 +1698,52 @@ static void guc_exec_queue_fini(struct xe_exec_queue *q)
 	 * (timeline name).
 	 */
 	kfree_rcu(ge, rcu);
+
+	drm_dev_put(drm);
 }
 
-static void __guc_exec_queue_destroy_async(struct work_struct *w)
+static void guc_exec_queue_do_destroy(struct xe_exec_queue *q)
 {
-	struct xe_guc_exec_queue *ge =
-		container_of(w, struct xe_guc_exec_queue, destroy_async);
-	struct xe_exec_queue *q = ge->q;
+	struct xe_guc_exec_queue *ge = q->guc;
 	struct xe_guc *guc = exec_queue_to_guc(q);
+	struct xe_device *xe = guc_to_xe(guc);
+	struct drm_device *drm = &xe->drm;
 
-	guard(xe_pm_runtime)(guc_to_xe(guc));
-	trace_xe_exec_queue_destroy(q);
+	/*
+	 * guc_exec_queue_fini() drops the queue's drm_device ref.
+	 * Keep the device alive until the PM-runtime guard unwinds.
+	 */
+	drm_dev_get(drm);
+
+	scoped_guard(xe_pm_runtime, xe) {
+		trace_xe_exec_queue_destroy(q);
 
-	/* Confirm no work left behind accessing device structures */
-	cancel_delayed_work_sync(&ge->sched.base.work_tdr);
+		/* Confirm no work left behind accessing device structures */
+		cancel_delayed_work_sync(&ge->sched.base.work_tdr);
+
+		xe_exec_queue_fini(q);
+	}
 
-	xe_exec_queue_fini(q);
+	drm_dev_put(drm);
 }
 
-static void guc_exec_queue_destroy_async(struct xe_exec_queue *q)
+static void __guc_exec_queue_destroy_async(struct work_struct *w)
 {
-	struct xe_guc *guc = exec_queue_to_guc(q);
-	struct xe_device *xe = guc_to_xe(guc);
+	struct xe_guc_exec_queue *ge =
+		container_of(w, struct xe_guc_exec_queue, destroy_async);
 
+	guc_exec_queue_do_destroy(ge->q);
+}
+
+static void guc_exec_queue_destroy_async(struct xe_exec_queue *q)
+{
 	INIT_WORK(&q->guc->destroy_async, __guc_exec_queue_destroy_async);
 
 	/* We must block on kernel engines so slabs are empty on driver unload */
 	if (q->flags & EXEC_QUEUE_FLAG_PERMANENT || exec_queue_wedged(q))
-		__guc_exec_queue_destroy_async(&q->guc->destroy_async);
+		guc_exec_queue_do_destroy(q);
 	else
-		queue_work(xe->destroy_wq, &q->guc->destroy_async);
+		xe_destroy_wq_queue(&q->guc->destroy_async);
 }
 
 static void __guc_exec_queue_destroy(struct xe_guc *guc, struct xe_exec_queue *q)
@@ -1935,6 +1951,7 @@ static int guc_exec_queue_init(struct xe_exec_queue *q)
 {
 	struct xe_gpu_scheduler *sched;
 	struct xe_guc *guc = exec_queue_to_guc(q);
+	struct drm_device *drm = &guc_to_xe(guc)->drm;
 	struct workqueue_struct *submit_wq = NULL;
 	struct xe_guc_exec_queue *ge;
 	long timeout;
@@ -1946,6 +1963,8 @@ static int guc_exec_queue_init(struct xe_exec_queue *q)
 	if (!ge)
 		return -ENOMEM;
 
+	drm_dev_get(drm);
+
 	q->guc = ge;
 	ge->q = q;
 	init_rcu_head(&ge->rcu);
@@ -1957,6 +1976,14 @@ static int guc_exec_queue_init(struct xe_exec_queue *q)
 	timeout = (q->vm && xe_vm_in_lr_mode(q->vm)) ? MAX_SCHEDULE_TIMEOUT :
 		  msecs_to_jiffies(q->sched_props.job_timeout_ms);
 
+	err = alloc_guc_id(guc, q);
+	if (err)
+		goto err_free;
+
+	xe_exec_queue_assign_name(q, q->guc->id);
+
+	strscpy(ge->name, q->name, sizeof(ge->name));
+
 	/*
 	 * Use primary queue's submit_wq for all secondary queues of a
 	 * multi queue group. This serialization avoids any locking around
@@ -1971,30 +1998,23 @@ static int guc_exec_queue_init(struct xe_exec_queue *q)
 	err = xe_sched_init(&ge->sched, &drm_sched_ops, &xe_sched_ops,
 			    submit_wq, xe_lrc_ring_size() / MAX_JOB_SIZE_BYTES, 64,
 			    timeout, guc_to_gt(guc)->ordered_wq, NULL,
-			    q->name, gt_to_xe(q->gt)->drm.dev);
+			    ge->name, gt_to_xe(q->gt)->drm.dev);
 	if (err)
-		goto err_free;
+		goto err_release_id;
 
 	sched = &ge->sched;
 	err = xe_sched_entity_init(&ge->entity, sched);
 	if (err)
 		goto err_sched;
 
-	mutex_lock(&guc->submission_state.lock);
-
-	err = alloc_guc_id(guc, q);
-	if (err)
-		goto err_entity;
-
 	q->entity = &ge->entity;
 
+	mutex_lock(&guc->submission_state.lock);
 	if (xe_guc_read_stopped(guc) || vf_recovery(guc))
 		xe_sched_stop(sched);
-
+	publish_guc_id(guc, q);
 	mutex_unlock(&guc->submission_state.lock);
 
-	xe_exec_queue_assign_name(q, q->guc->id);
-
 	/*
 	 * Maintain secondary queues of the multi queue group in a list
 	 * for handling dependencies across the queues in the group.
@@ -2017,13 +2037,13 @@ static int guc_exec_queue_init(struct xe_exec_queue *q)
 
 	return 0;
 
-err_entity:
-	mutex_unlock(&guc->submission_state.lock);
-	xe_sched_entity_fini(&ge->entity);
 err_sched:
 	xe_sched_fini(&ge->sched);
+err_release_id:
+	release_guc_id(guc, q);
 err_free:
 	kfree(ge);
+	drm_dev_put(drm);
 
 	return err;
 }
diff --git linux-libre-7.1.5-gnu/drivers/gpu/drm/xe/xe_guc_types.h linux-libre-7.1.6-gnu/drivers/gpu/drm/xe/xe_guc_types.h
index c7b9642b41ba7..31a2acb63ac34 100644
--- linux-libre-7.1.5-gnu/drivers/gpu/drm/xe/xe_guc_types.h
+++ linux-libre-7.1.6-gnu/drivers/gpu/drm/xe/xe_guc_types.h
@@ -100,8 +100,6 @@ struct xe_guc {
 		 * even initialized - before that not even the lock is valid
 		 */
 		bool initialized;
-		/** @submission_state.fini_wq: submit fini wait queue */
-		wait_queue_head_t fini_wq;
 	} submission_state;
 
 	/** @hwconfig: Hardware config state */
diff --git linux-libre-7.1.5-gnu/drivers/gpu/drm/xe/xe_i2c.c linux-libre-7.1.6-gnu/drivers/gpu/drm/xe/xe_i2c.c
index 706783863d07d..f05f23221c1b7 100644
--- linux-libre-7.1.5-gnu/drivers/gpu/drm/xe/xe_i2c.c
+++ linux-libre-7.1.6-gnu/drivers/gpu/drm/xe/xe_i2c.c
@@ -95,18 +95,21 @@ static int xe_i2c_register_adapter(struct xe_i2c *i2c)
 	struct platform_device *pdev;
 	struct fwnode_handle *fwnode;
 	int ret;
+	u32 id;
 
 	fwnode = fwnode_create_software_node(xe_i2c_adapter_properties, NULL);
 	if (IS_ERR(fwnode))
 		return PTR_ERR(fwnode);
 
+	id = (pci_domain_nr(pci->bus) << 16) | pci_dev_id(pci);
+
 	/*
 	 * Not using platform_device_register_full() here because we don't have
 	 * a handle to the platform_device before it returns. xe_i2c_notifier()
 	 * uses that handle, but it may be called before
 	 * platform_device_register_full() is done.
 	 */
-	pdev = platform_device_alloc(adapter_name, pci_dev_id(pci));
+	pdev = platform_device_alloc(adapter_name, id);
 	if (!pdev) {
 		ret = -ENOMEM;
 		goto err_fwnode_remove;
diff --git linux-libre-7.1.5-gnu/drivers/gpu/drm/xe/xe_migrate.c linux-libre-7.1.6-gnu/drivers/gpu/drm/xe/xe_migrate.c
index a22413f892a09..5dd03d4cbf5bb 100644
--- linux-libre-7.1.5-gnu/drivers/gpu/drm/xe/xe_migrate.c
+++ linux-libre-7.1.6-gnu/drivers/gpu/drm/xe/xe_migrate.c
@@ -1145,6 +1145,8 @@ static int emit_flush_invalidate(u32 *dw, int i, u32 flags)
  * @tile: Tile whose migration context to be used.
  * @q : Execution to be used along with migration context.
  * @src_bo: The buffer object @src is currently bound to.
+ * @new_mem: The (not yet committed) destination resource @src_bo is being
+ *          moved into; src_bo->ttm.resource is still the old resource.
  * @read_write : Creates BB commands for CCS read/write.
  *
  * Creates batch buffer instructions to copy CCS metadata from CCS pool to
@@ -1156,12 +1158,13 @@ static int emit_flush_invalidate(u32 *dw, int i, u32 flags)
  */
 int xe_migrate_ccs_rw_copy(struct xe_tile *tile, struct xe_exec_queue *q,
 			   struct xe_bo *src_bo,
+			   struct ttm_resource *new_mem,
 			   enum xe_sriov_vf_ccs_rw_ctxs read_write)
 
 {
 	bool src_is_pltt = read_write == XE_SRIOV_VF_CCS_READ_CTX;
 	bool dst_is_pltt = read_write == XE_SRIOV_VF_CCS_WRITE_CTX;
-	struct ttm_resource *src = src_bo->ttm.resource;
+	struct ttm_resource *src = new_mem;
 	struct xe_migrate *m = tile->migrate;
 	struct xe_gt *gt = tile->primary_gt;
 	u32 batch_size, batch_size_allocated;
@@ -1289,6 +1292,7 @@ int xe_migrate_ccs_rw_copy(struct xe_tile *tile, struct xe_exec_queue *q,
  * content.
  * @src_bo: The buffer object @src is currently bound to.
  * @read_write : Creates BB commands for CCS read/write.
+ * @bound: Device is bound
  *
  * Directly clearing the BB lacks atomicity and can lead to undefined
  * behavior if the vCPU is halted mid-operation during the clearing
@@ -1301,7 +1305,8 @@ int xe_migrate_ccs_rw_copy(struct xe_tile *tile, struct xe_exec_queue *q,
  * Returns: None.
  */
 void xe_migrate_ccs_rw_copy_clear(struct xe_bo *src_bo,
-				  enum xe_sriov_vf_ccs_rw_ctxs read_write)
+				  enum xe_sriov_vf_ccs_rw_ctxs read_write,
+				  bool bound)
 {
 	struct xe_mem_pool_node *bb = src_bo->bb_ccs[read_write];
 	struct xe_device *xe = xe_bo_device(src_bo);
@@ -1315,13 +1320,15 @@ void xe_migrate_ccs_rw_copy_clear(struct xe_bo *src_bo,
 	bb_pool = ctx->mem.ccs_bb_pool;
 
 	scoped_guard(mutex, xe_mem_pool_bo_swap_guard(bb_pool)) {
-		xe_mem_pool_swap_shadow_locked(bb_pool);
+		if (bound) {
+			xe_mem_pool_swap_shadow_locked(bb_pool);
 
-		cs = xe_mem_pool_node_cpu_addr(bb);
-		memset(cs, MI_NOOP, bb->sa_node.size);
-		xe_sriov_vf_ccs_rw_update_bb_addr(ctx);
+			cs = xe_mem_pool_node_cpu_addr(bb);
+			memset(cs, MI_NOOP, bb->sa_node.size);
+			xe_sriov_vf_ccs_rw_update_bb_addr(ctx);
 
-		xe_mem_pool_sync_shadow_locked(bb);
+			xe_mem_pool_sync_shadow_locked(bb);
+		}
 		xe_mem_pool_free_node(bb);
 		src_bo->bb_ccs[read_write] = NULL;
 	}
diff --git linux-libre-7.1.5-gnu/drivers/gpu/drm/xe/xe_migrate.h linux-libre-7.1.6-gnu/drivers/gpu/drm/xe/xe_migrate.h
index 169279d9d8c24..0bcc122c1c343 100644
--- linux-libre-7.1.5-gnu/drivers/gpu/drm/xe/xe_migrate.h
+++ linux-libre-7.1.6-gnu/drivers/gpu/drm/xe/xe_migrate.h
@@ -138,10 +138,12 @@ struct dma_fence *xe_migrate_resolve(struct xe_migrate *m,
 
 int xe_migrate_ccs_rw_copy(struct xe_tile *tile, struct xe_exec_queue *q,
 			   struct xe_bo *src_bo,
+			   struct ttm_resource *new_mem,
 			   enum xe_sriov_vf_ccs_rw_ctxs read_write);
 
 void xe_migrate_ccs_rw_copy_clear(struct xe_bo *src_bo,
-				  enum xe_sriov_vf_ccs_rw_ctxs read_write);
+				  enum xe_sriov_vf_ccs_rw_ctxs read_write,
+				  bool bound);
 
 struct xe_lrc *xe_migrate_lrc(struct xe_migrate *migrate);
 struct xe_exec_queue *xe_migrate_exec_queue(struct xe_migrate *migrate);
diff --git linux-libre-7.1.5-gnu/drivers/gpu/drm/xe/xe_module.c linux-libre-7.1.6-gnu/drivers/gpu/drm/xe/xe_module.c
index 4cb5781829122..99347f216ec89 100644
--- linux-libre-7.1.5-gnu/drivers/gpu/drm/xe/xe_module.c
+++ linux-libre-7.1.6-gnu/drivers/gpu/drm/xe/xe_module.c
@@ -7,6 +7,7 @@
 
 #include <linux/init.h>
 #include <linux/module.h>
+#include <linux/workqueue.h>
 
 #include <drm/drm_module.h>
 
@@ -91,6 +92,50 @@ static int xe_check_nomodeset(void)
 	return 0;
 }
 
+static struct workqueue_struct *xe_destroy_wq;
+
+static int __init xe_destroy_wq_module_init(void)
+{
+	xe_destroy_wq = alloc_workqueue("xe-guc-destroy-wq", WQ_UNBOUND, 0);
+	if (!xe_destroy_wq)
+		return -ENOMEM;
+	return 0;
+}
+
+static void xe_destroy_wq_module_exit(void)
+{
+	if (xe_destroy_wq)
+		destroy_workqueue(xe_destroy_wq);
+	xe_destroy_wq = NULL;
+}
+
+/**
+ * xe_destroy_wq_queue() - Queue work on the destroy workqueue
+ * @work: work item to queue
+ *
+ * The destroy workqueue has module lifetime and is used for GuC exec queue
+ * teardown that can outlive a single xe_device. SVM pagemap destroy uses the
+ * per-device xe->destroy_wq instead.
+ *
+ * Return: %true if @work was queued, %false if it was already pending.
+ */
+bool xe_destroy_wq_queue(struct work_struct *work)
+{
+	return queue_work(xe_destroy_wq, work);
+}
+
+/**
+ * xe_destroy_wq_flush() - Flush the destroy workqueue
+ *
+ * Drains all pending destroy work. Called from PCI remove to ensure
+ * teardown ordering before the device is destroyed.
+ */
+void xe_destroy_wq_flush(void)
+{
+	if (xe_destroy_wq)
+		flush_workqueue(xe_destroy_wq);
+}
+
 struct init_funcs {
 	int (*init)(void);
 	void (*exit)(void);
@@ -112,6 +157,10 @@ static const struct init_funcs init_funcs[] = {
 		.init = xe_sched_job_module_init,
 		.exit = xe_sched_job_module_exit,
 	},
+	{
+		.init = xe_destroy_wq_module_init,
+		.exit = xe_destroy_wq_module_exit,
+	},
 	{
 		.init = xe_register_pci_driver,
 		.exit = xe_unregister_pci_driver,
diff --git linux-libre-7.1.5-gnu/drivers/gpu/drm/xe/xe_module.h linux-libre-7.1.6-gnu/drivers/gpu/drm/xe/xe_module.h
index 79cb9639c0f3d..e8e54f701cf3e 100644
--- linux-libre-7.1.5-gnu/drivers/gpu/drm/xe/xe_module.h
+++ linux-libre-7.1.6-gnu/drivers/gpu/drm/xe/xe_module.h
@@ -8,6 +8,8 @@
 
 #include <linux/types.h>
 
+struct work_struct;
+
 /* Module modprobe variables */
 struct xe_modparam {
 	bool force_execlist;
@@ -27,5 +29,8 @@ struct xe_modparam {
 
 extern struct xe_modparam xe_modparam;
 
+bool xe_destroy_wq_queue(struct work_struct *work);
+void xe_destroy_wq_flush(void);
+
 #endif
 
diff --git linux-libre-7.1.5-gnu/drivers/gpu/drm/xe/xe_nvm.c linux-libre-7.1.6-gnu/drivers/gpu/drm/xe/xe_nvm.c
index 33487e91f366c..1ea67eaeae243 100644
--- linux-libre-7.1.5-gnu/drivers/gpu/drm/xe/xe_nvm.c
+++ linux-libre-7.1.6-gnu/drivers/gpu/drm/xe/xe_nvm.c
@@ -60,35 +60,40 @@ static bool xe_nvm_writable_override(struct xe_device *xe)
 	struct xe_mmio *mmio = xe_root_tile_mmio(xe);
 	bool writable_override;
 	struct xe_reg reg;
-	u32 test_bit;
+	u32 test_bit, test_val;
 
 	switch (xe->info.platform) {
 	case XE_CRESCENTISLAND:
 		reg = PCODE_SCRATCH(0);
 		test_bit = FDO_MODE;
+		test_val = FDO_MODE;
 		break;
 	case XE_BATTLEMAGE:
 		reg = HECI_FWSTS2(DG2_GSC_HECI2_BASE);
 		test_bit = HECI_FW_STATUS_2_NVM_ACCESS_MODE;
+		test_val = 0;
 		break;
 	case XE_PVC:
 		reg = HECI_FWSTS2(PVC_GSC_HECI2_BASE);
 		test_bit = HECI_FW_STATUS_2_NVM_ACCESS_MODE;
+		test_val = 0;
 		break;
 	case XE_DG2:
 		reg = HECI_FWSTS2(DG2_GSC_HECI2_BASE);
 		test_bit = HECI_FW_STATUS_2_NVM_ACCESS_MODE;
+		test_val = 0;
 		break;
 	case XE_DG1:
 		reg = HECI_FWSTS2(DG1_GSC_HECI2_BASE);
 		test_bit = HECI_FW_STATUS_2_NVM_ACCESS_MODE;
+		test_val = 0;
 		break;
 	default:
 		drm_err(&xe->drm, "Unknown platform\n");
 		return true;
 	}
 
-	writable_override = !(xe_mmio_read32(mmio, reg) & test_bit);
+	writable_override = (xe_mmio_read32(mmio, reg) & test_bit) == test_val;
 	if (writable_override)
 		drm_info(&xe->drm, "NVM access overridden by jumper\n");
 	return writable_override;
diff --git linux-libre-7.1.5-gnu/drivers/gpu/drm/xe/xe_pci.c linux-libre-7.1.6-gnu/drivers/gpu/drm/xe/xe_pci.c
index c2ecd27ec770a..ad4955fe5ade7 100644
--- linux-libre-7.1.5-gnu/drivers/gpu/drm/xe/xe_pci.c
+++ linux-libre-7.1.6-gnu/drivers/gpu/drm/xe/xe_pci.c
@@ -1029,6 +1029,12 @@ static void xe_pci_remove(struct pci_dev *pdev)
 		return;
 
 	xe_device_remove(xe);
+
+	/*
+	 * Preserve remove-time flush after moving destroy work to module
+	 * lifetime.
+	 */
+	xe_destroy_wq_flush();
 	xe_pm_fini(xe);
 }
 
diff --git linux-libre-7.1.5-gnu/drivers/gpu/drm/xe/xe_pt.c linux-libre-7.1.6-gnu/drivers/gpu/drm/xe/xe_pt.c
index c3a69103b9bbf..cf371c0d7b2bb 100644
--- linux-libre-7.1.5-gnu/drivers/gpu/drm/xe/xe_pt.c
+++ linux-libre-7.1.6-gnu/drivers/gpu/drm/xe/xe_pt.c
@@ -1025,12 +1025,22 @@ xe_vm_populate_pgtable(struct xe_migrate_pt_update *pt_update, struct xe_tile *t
 	u64 *ptr = data;
 	u32 i;
 
+	/*
+	 * @qword_ofs is the absolute entry offset within the page table, while
+	 * @ptes is indexed relative to @update->ofs (its first entry). The GPU
+	 * path (write_pgtable) splits a single update into MAX_PTE_PER_SDI-sized
+	 * chunks, calling this with an advancing @qword_ofs but a fresh @data
+	 * pointer per chunk, so translate back into a @ptes index rather than
+	 * assuming the chunk starts at ptes[0].
+	 */
 	for (i = 0; i < num_qwords; i++) {
+		u32 idx = qword_ofs - update->ofs + i;
+
 		if (map)
 			xe_map_wr(tile_to_xe(tile), map, (qword_ofs + i) *
-				  sizeof(u64), u64, ptes[i].pte);
+				  sizeof(u64), u64, ptes[idx].pte);
 		else
-			ptr[i] = ptes[i].pte;
+			ptr[i] = ptes[idx].pte;
 	}
 }
 
@@ -1643,23 +1653,21 @@ static bool xe_pt_check_kill(u64 addr, u64 next, unsigned int level,
 	return false;
 }
 
-/* page_size = 2^(reclamation_size + XE_PTE_SHIFT) */
-#define COMPUTE_RECLAIM_ADDRESS_MASK(page_size)				\
-({									\
-	BUILD_BUG_ON(!__builtin_constant_p(page_size));			\
-	ilog2(page_size) - XE_PTE_SHIFT;				\
-})
-
 static int generate_reclaim_entry(struct xe_tile *tile,
 				  struct xe_page_reclaim_list *prl,
 				  u64 pte, struct xe_pt *xe_child)
 {
 	struct xe_gt *gt = tile->primary_gt;
 	struct xe_guc_page_reclaim_entry *reclaim_entries = prl->entries;
-	u64 phys_addr = pte & XE_PTE_ADDR_MASK;
+	bool is_2m = xe_child->level == 1 && (pte & XE_PDE_PS_2M);
+	bool is_64k = xe_child->level == 0 && ((pte & XE_PTE_PS64) || xe_child->is_compact);
+	u32 page_shift = is_2m ? ilog2(SZ_2M) : is_64k ? ilog2(SZ_64K) : ilog2(SZ_4K);
+	/* Physical address bits start at page shift: 2M->[51:21], 64K->[51:16], 4K->[51:12] */
+	u64 phys_addr = pte & XE_PAGE_ADDR_MASK(page_shift);
+	/* Page address is relative to 4K page regardless of entry level */
 	u64 phys_page = phys_addr >> XE_PTE_SHIFT;
 	int num_entries = prl->num_entries;
-	u32 reclamation_size;
+	u32 reclamation_size = page_shift - XE_PTE_SHIFT;
 
 	xe_tile_assert(tile, xe_child->level <= MAX_HUGEPTE_LEVEL);
 	xe_tile_assert(tile, reclaim_entries);
@@ -1674,18 +1682,12 @@ static int generate_reclaim_entry(struct xe_tile *tile,
 	 * Page size is computed as 2^(reclamation_size + XE_PTE_SHIFT) bytes.
 	 * Only 4K, 64K (level 0), and 2M pages are supported by hardware for page reclaim
 	 */
-	if (xe_child->level == 0 && !(pte & XE_PTE_PS64)) {
-		xe_gt_stats_incr(gt, XE_GT_STATS_ID_PRL_4K_ENTRY_COUNT, 1);
-		reclamation_size = COMPUTE_RECLAIM_ADDRESS_MASK(SZ_4K);  /* reclamation_size = 0 */
-		xe_tile_assert(tile, phys_addr % SZ_4K == 0);
-	} else if (xe_child->level == 0) {
-		xe_gt_stats_incr(gt, XE_GT_STATS_ID_PRL_64K_ENTRY_COUNT, 1);
-		reclamation_size = COMPUTE_RECLAIM_ADDRESS_MASK(SZ_64K); /* reclamation_size = 4 */
-		xe_tile_assert(tile, phys_addr % SZ_64K == 0);
-	} else if (xe_child->level == 1 && pte & XE_PDE_PS_2M) {
+	if (is_2m) {
 		xe_gt_stats_incr(gt, XE_GT_STATS_ID_PRL_2M_ENTRY_COUNT, 1);
-		reclamation_size = COMPUTE_RECLAIM_ADDRESS_MASK(SZ_2M);  /* reclamation_size = 9 */
-		xe_tile_assert(tile, phys_addr % SZ_2M == 0);
+	} else if (is_64k) {
+		xe_gt_stats_incr(gt, XE_GT_STATS_ID_PRL_64K_ENTRY_COUNT, 1);
+	} else if (xe_child->level == 0) {
+		xe_gt_stats_incr(gt, XE_GT_STATS_ID_PRL_4K_ENTRY_COUNT, 1);
 	} else {
 		xe_page_reclaim_list_abort(tile->primary_gt, prl,
 					   "unsupported PTE level=%u pte=%#llx",
@@ -1706,6 +1708,48 @@ static int generate_reclaim_entry(struct xe_tile *tile,
 	return 0;
 }
 
+static int add_pte_to_prl(struct xe_tile *tile, struct xe_page_reclaim_list *prl,
+			  struct xe_pt *xe_child, u64 pte, u64 addr)
+{
+	/*
+	 * In rare scenarios, pte may not be written yet due to racy conditions.
+	 * In such cases, invalidate the PRL and fallback to full PPC invalidation.
+	 */
+	if (!pte) {
+		xe_page_reclaim_list_abort(tile->primary_gt, prl,
+					   "found zero pte at addr=%#llx", addr);
+		return -EINVAL;
+	}
+
+	/* Ensure it is a defined page */
+	xe_tile_assert(tile, xe_child->level == 0 ||
+		       (pte & (XE_PDE_PS_2M | XE_PDPE_PS_1G)));
+
+	/* Account for NULL terminated entry on end (-1) */
+	if (prl->num_entries >= XE_PAGE_RECLAIM_MAX_ENTRIES - 1) {
+		xe_page_reclaim_list_abort(tile->primary_gt, prl,
+					   "overflow while adding pte=%#llx", pte);
+		return -ENOSPC;
+	}
+
+	return generate_reclaim_entry(tile, prl, pte, xe_child);
+}
+
+static bool add_compact_pt_prl(struct xe_tile *tile, struct xe_page_reclaim_list *prl,
+			       struct xe_device *xe, struct xe_pt *compact_pt, u64 addr)
+{
+	struct iosys_map *map = &compact_pt->bo->vmap;
+
+	for (pgoff_t i = 0; i < SZ_2M / SZ_64K && xe_page_reclaim_list_valid(prl); i++) {
+		u64 pte = xe_map_rd(xe, map, i * sizeof(u64), u64);
+
+		if (add_pte_to_prl(tile, prl, compact_pt, pte, addr + i * SZ_64K))
+			break;
+	}
+
+	return xe_page_reclaim_list_valid(prl);
+}
+
 static int xe_pt_stage_unbind_entry(struct xe_ptw *parent, pgoff_t offset,
 				    unsigned int level, u64 addr, u64 next,
 				    struct xe_ptw **child,
@@ -1715,21 +1759,22 @@ static int xe_pt_stage_unbind_entry(struct xe_ptw *parent, pgoff_t offset,
 	struct xe_pt *xe_child = container_of(*child, typeof(*xe_child), base);
 	struct xe_pt_stage_unbind_walk *xe_walk =
 		container_of(walk, typeof(*xe_walk), base);
-	struct xe_device *xe = tile_to_xe(xe_walk->tile);
+	struct xe_page_reclaim_list *prl = xe_walk->prl;
+	struct xe_tile *tile = xe_walk->tile;
+	struct xe_device *xe = tile_to_xe(tile);
 	pgoff_t first = xe_pt_offset(addr, xe_child->level, walk);
 	bool killed;
 
 	XE_WARN_ON(!*child);
 	XE_WARN_ON(!level);
 	/* Check for leaf node */
-	if (xe_walk->prl && xe_page_reclaim_list_valid(xe_walk->prl) &&
+	if (prl && xe_page_reclaim_list_valid(prl) &&
 	    xe_child->level <= MAX_HUGEPTE_LEVEL) {
 		struct iosys_map *leaf_map = &xe_child->bo->vmap;
 		pgoff_t count = xe_pt_num_entries(addr, next, xe_child->level, walk);
 
 		for (pgoff_t i = 0; i < count; i++) {
 			u64 pte;
-			int ret;
 
 			/*
 			 * If not a leaf pt, skip unless non-leaf pt is interleaved between
@@ -1739,10 +1784,23 @@ static int xe_pt_stage_unbind_entry(struct xe_ptw *parent, pgoff_t offset,
 				u64 pt_size = 1ULL << walk->shifts[xe_child->level];
 				bool edge_pt = (i == 0 && !IS_ALIGNED(addr, pt_size)) ||
 					       (i == count - 1 && !IS_ALIGNED(next, pt_size));
-
-				if (!edge_pt) {
-					xe_page_reclaim_list_abort(xe_walk->tile->primary_gt,
-								   xe_walk->prl,
+				struct xe_pt *child_pt =
+					container_of(xe_child->base.children[first + i],
+						     struct xe_pt, base);
+
+				/* Compact PTs always fill a full 2M-aligned slot, never an edge. */
+				XE_WARN_ON(child_pt->is_compact && edge_pt);
+				if (edge_pt)
+					continue;
+
+				/* Walker never descends into compact PTs, descend now */
+				if (child_pt->is_compact) {
+					if (!add_compact_pt_prl(tile, prl, xe, child_pt,
+								addr + (u64)i * pt_size))
+						break;
+				} else {
+					xe_page_reclaim_list_abort(tile->primary_gt,
+								   prl,
 								   "PT is skipped by walk at level=%u offset=%lu",
 								   xe_child->level, first + i);
 					break;
@@ -1752,37 +1810,12 @@ static int xe_pt_stage_unbind_entry(struct xe_ptw *parent, pgoff_t offset,
 
 			pte = xe_map_rd(xe, leaf_map, (first + i) * sizeof(u64), u64);
 
-			/*
-			 * In rare scenarios, pte may not be written yet due to racy conditions.
-			 * In such cases, invalidate the PRL and fallback to full PPC invalidation.
-			 */
-			if (!pte) {
-				xe_page_reclaim_list_abort(xe_walk->tile->primary_gt, xe_walk->prl,
-							   "found zero pte at addr=%#llx", addr);
+			if (add_pte_to_prl(tile, prl, xe_child, pte, addr))
 				break;
-			}
-
-			/* Ensure it is a defined page */
-			xe_tile_assert(xe_walk->tile, xe_child->level == 0 ||
-				       (pte & (XE_PDE_PS_2M | XE_PDPE_PS_1G)));
 
 			/* An entry should be added for 64KB but contigious 4K have XE_PTE_PS64 */
 			if (pte & XE_PTE_PS64)
 				i += 15; /* Skip other 15 consecutive 4K pages in the 64K page */
-
-			/* Account for NULL terminated entry on end (-1) */
-			if (xe_walk->prl->num_entries < XE_PAGE_RECLAIM_MAX_ENTRIES - 1) {
-				ret = generate_reclaim_entry(xe_walk->tile, xe_walk->prl,
-							     pte, xe_child);
-				if (ret)
-					break;
-			} else {
-				/* overflow, mark as invalid */
-				xe_page_reclaim_list_abort(xe_walk->tile->primary_gt, xe_walk->prl,
-							   "overflow while adding pte=%#llx",
-							   pte);
-				break;
-			}
 		}
 	}
 
@@ -1792,7 +1825,7 @@ static int xe_pt_stage_unbind_entry(struct xe_ptw *parent, pgoff_t offset,
 	 * Verify if any PTE are potentially dropped at non-leaf levels, either from being
 	 * killed or the page walk covers the region.
 	 */
-	if (xe_walk->prl && xe_page_reclaim_list_valid(xe_walk->prl) &&
+	if (prl && xe_page_reclaim_list_valid(prl) &&
 	    xe_child->level > MAX_HUGEPTE_LEVEL && xe_child->num_live) {
 		bool covered = xe_pt_covers(addr, next, xe_child->level, &xe_walk->base);
 
@@ -1801,7 +1834,7 @@ static int xe_pt_stage_unbind_entry(struct xe_ptw *parent, pgoff_t offset,
 		 * we need to invalidate the PRL.
 		 */
 		if (killed || covered)
-			xe_page_reclaim_list_abort(xe_walk->tile->primary_gt, xe_walk->prl,
+			xe_page_reclaim_list_abort(tile->primary_gt, prl,
 						   "kill at level=%u addr=%#llx next=%#llx num_live=%u",
 						   level, addr, next, xe_child->num_live);
 	}
@@ -2331,8 +2364,11 @@ static void
 xe_pt_update_ops_init(struct xe_vm_pgtable_update_ops *pt_update_ops)
 {
 	init_llist_head(&pt_update_ops->deferred);
+	pt_update_ops->current_op = 0;
 	pt_update_ops->start = ~0x0ull;
 	pt_update_ops->last = 0x0ull;
+	pt_update_ops->needs_svm_lock = false;
+	pt_update_ops->needs_invalidation = false;
 	xe_page_reclaim_list_init(&pt_update_ops->prl);
 }
 
diff --git linux-libre-7.1.5-gnu/drivers/gpu/drm/xe/xe_reg_whitelist.c linux-libre-7.1.6-gnu/drivers/gpu/drm/xe/xe_reg_whitelist.c
index 8cc313182968d..506501d77f389 100644
--- linux-libre-7.1.5-gnu/drivers/gpu/drm/xe/xe_reg_whitelist.c
+++ linux-libre-7.1.6-gnu/drivers/gpu/drm/xe/xe_reg_whitelist.c
@@ -90,10 +90,12 @@ static const struct xe_rtp_entry_sr register_whitelist[] = {
 				   RING_FORCE_TO_NONPRIV_ACCESS_RW))
 	},
 
+#define WHITELIST_DENY(r, f) WHITELIST(r, (f) | RING_FORCE_TO_NONPRIV_DENY)
+
 #define WHITELIST_OA_MMIO_TRG(trg, status, head) \
-	WHITELIST(trg, RING_FORCE_TO_NONPRIV_ACCESS_RW), \
-	WHITELIST(status, RING_FORCE_TO_NONPRIV_ACCESS_RD), \
-	WHITELIST(head, RING_FORCE_TO_NONPRIV_ACCESS_RD | RING_FORCE_TO_NONPRIV_RANGE_4)
+	WHITELIST_DENY(trg, RING_FORCE_TO_NONPRIV_ACCESS_RW), \
+	WHITELIST_DENY(status, RING_FORCE_TO_NONPRIV_ACCESS_RD), \
+	WHITELIST_DENY(head, RING_FORCE_TO_NONPRIV_ACCESS_RD | RING_FORCE_TO_NONPRIV_RANGE_4)
 
 #define WHITELIST_OAG_MMIO_TRG \
 	WHITELIST_OA_MMIO_TRG(OAG_MMIOTRIGGER, OAG_OASTATUS, OAG_OAHEADPTR)
@@ -110,7 +112,7 @@ static const struct xe_rtp_entry_sr register_whitelist[] = {
 			      OAM_HEAD_POINTER(XE_OAM_SCMI_1_BASE_ADJ))
 
 #define WHITELIST_OA_MERT_MMIO_TRG \
-	WHITELIST_OA_MMIO_TRG(OAMERT_MMIO_TRG, OAMERT_STATUS, OAMERT_HEAD_POINTER)
+	WHITELIST_OA_MMIO_TRG(OAMERT_MMIO_TRG, OAMERT_STATUS, OAMERT_TAIL_POINTER)
 
 	{ XE_RTP_NAME("oag_mmio_trg_rcs"),
 	  XE_RTP_RULES(GRAPHICS_VERSION_RANGE(1200, XE_RTP_END_VERSION_UNDEFINED),
diff --git linux-libre-7.1.5-gnu/drivers/gpu/drm/xe/xe_sriov_vf_ccs.c linux-libre-7.1.6-gnu/drivers/gpu/drm/xe/xe_sriov_vf_ccs.c
index 09b99fb2608bc..a8c831fbee3b5 100644
--- linux-libre-7.1.5-gnu/drivers/gpu/drm/xe/xe_sriov_vf_ccs.c
+++ linux-libre-7.1.6-gnu/drivers/gpu/drm/xe/xe_sriov_vf_ccs.c
@@ -3,6 +3,8 @@
  * Copyright © 2025 Intel Corporation
  */
 
+#include <drm/drm_drv.h>
+
 #include "instructions/xe_mi_commands.h"
 #include "instructions/xe_gpu_commands.h"
 #include "xe_bb.h"
@@ -404,6 +406,8 @@ void xe_sriov_vf_ccs_rw_update_bb_addr(struct xe_sriov_vf_ccs_ctx *ctx)
 /**
  * xe_sriov_vf_ccs_attach_bo - Insert CCS read write commands in the BO.
  * @bo: the &buffer object to which batch buffer commands will be added.
+ * @new_mem: the (not yet committed) destination resource @bo is being moved
+ *          into; bo->ttm.resource is still the old resource at this point.
  *
  * This function shall be called only by VF. It inserts the PTEs and copy
  * command instructions in the BO by calling xe_migrate_ccs_rw_copy()
@@ -411,7 +415,7 @@ void xe_sriov_vf_ccs_rw_update_bb_addr(struct xe_sriov_vf_ccs_ctx *ctx)
  *
  * Returns: 0 if successful, negative error code on failure.
  */
-int xe_sriov_vf_ccs_attach_bo(struct xe_bo *bo)
+int xe_sriov_vf_ccs_attach_bo(struct xe_bo *bo, struct ttm_resource *new_mem)
 {
 	struct xe_device *xe = xe_bo_device(bo);
 	enum xe_sriov_vf_ccs_rw_ctxs ctx_id;
@@ -430,7 +434,21 @@ int xe_sriov_vf_ccs_attach_bo(struct xe_bo *bo)
 		xe_assert(xe, !bb);
 
 		ctx = &xe->sriov.vf.ccs.contexts[ctx_id];
-		err = xe_migrate_ccs_rw_copy(tile, ctx->mig_q, bo, ctx_id);
+		err = xe_migrate_ccs_rw_copy(tile, ctx->mig_q, bo, new_mem, ctx_id);
+		if (err)
+			goto err_unwind;
+	}
+	return 0;
+
+err_unwind:
+	/*
+	 * Clean up any contexts already attached. Can't reuse
+	 * xe_sriov_vf_ccs_detach_bo() here as it requires both contexts
+	 * attached before cleaning up either one.
+	 */
+	for_each_ccs_rw_ctx(ctx_id) {
+		if (bo->bb_ccs[ctx_id])
+			xe_migrate_ccs_rw_copy_clear(bo, ctx_id, true);
 	}
 	return err;
 }
@@ -450,19 +468,27 @@ int xe_sriov_vf_ccs_detach_bo(struct xe_bo *bo)
 	struct xe_device *xe = xe_bo_device(bo);
 	enum xe_sriov_vf_ccs_rw_ctxs ctx_id;
 	struct xe_mem_pool_node *bb;
+	bool bound;
+	int idx;
 
 	xe_assert(xe, IS_VF_CCS_READY(xe));
 
 	if (!xe_bo_has_valid_ccs_bb(bo))
 		return 0;
 
+	bound = drm_dev_enter(&xe->drm, &idx);
+
 	for_each_ccs_rw_ctx(ctx_id) {
 		bb = bo->bb_ccs[ctx_id];
 		if (!bb)
 			continue;
 
-		xe_migrate_ccs_rw_copy_clear(bo, ctx_id);
+		xe_migrate_ccs_rw_copy_clear(bo, ctx_id, bound);
 	}
+
+	if (bound)
+		drm_dev_exit(idx);
+
 	return 0;
 }
 
diff --git linux-libre-7.1.5-gnu/drivers/gpu/drm/xe/xe_sriov_vf_ccs.h linux-libre-7.1.6-gnu/drivers/gpu/drm/xe/xe_sriov_vf_ccs.h
index 00e58b36c510a..e1034d8521040 100644
--- linux-libre-7.1.5-gnu/drivers/gpu/drm/xe/xe_sriov_vf_ccs.h
+++ linux-libre-7.1.6-gnu/drivers/gpu/drm/xe/xe_sriov_vf_ccs.h
@@ -11,11 +11,12 @@
 #include "xe_sriov_vf_ccs_types.h"
 
 struct drm_printer;
+struct ttm_resource;
 struct xe_device;
 struct xe_bo;
 
 int xe_sriov_vf_ccs_init(struct xe_device *xe);
-int xe_sriov_vf_ccs_attach_bo(struct xe_bo *bo);
+int xe_sriov_vf_ccs_attach_bo(struct xe_bo *bo, struct ttm_resource *new_mem);
 int xe_sriov_vf_ccs_detach_bo(struct xe_bo *bo);
 int xe_sriov_vf_ccs_register_context(struct xe_device *xe);
 void xe_sriov_vf_ccs_rebase(struct xe_device *xe);
diff --git linux-libre-7.1.5-gnu/drivers/gpu/drm/xe/xe_svm.c linux-libre-7.1.6-gnu/drivers/gpu/drm/xe/xe_svm.c
index 5933b2b6392b1..1c0df523a4369 100644
--- linux-libre-7.1.5-gnu/drivers/gpu/drm/xe/xe_svm.c
+++ linux-libre-7.1.6-gnu/drivers/gpu/drm/xe/xe_svm.c
@@ -1255,10 +1255,8 @@ retry:
 
 	xe_svm_range_fault_count_stats_incr(gt, range);
 
-	if (ctx.devmem_only && !range->base.pages.flags.migrate_devmem) {
-		err = -EACCES;
-		goto out;
-	}
+	if (ctx.devmem_only && !range->base.pages.flags.migrate_devmem)
+		return -EACCES;
 
 	if (xe_svm_range_is_valid(range, tile, ctx.devmem_only, dpagemap)) {
 		xe_svm_range_valid_fault_count_stats_incr(gt, range);
diff --git linux-libre-7.1.5-gnu/drivers/gpu/drm/xe/xe_vm.c linux-libre-7.1.6-gnu/drivers/gpu/drm/xe/xe_vm.c
index ab6cc1f0a7894..70b71ab802725 100644
--- linux-libre-7.1.5-gnu/drivers/gpu/drm/xe/xe_vm.c
+++ linux-libre-7.1.6-gnu/drivers/gpu/drm/xe/xe_vm.c
@@ -1810,10 +1810,10 @@ err_close:
 	return ERR_PTR(err);
 
 err_svm_fini:
-	if (flags & XE_VM_FLAG_FAULT_MODE) {
-		vm->size = 0; /* close the vm */
-		xe_svm_fini(vm);
-	}
+	vm->size = 0; /* close the vm */
+	if (flags & XE_VM_FLAG_FAULT_MODE)
+		xe_svm_close(vm);
+	xe_svm_fini(vm);
 err_no_resv:
 	mutex_destroy(&vm->snap_mutex);
 	for_each_tile(tile, xe, id)
@@ -3256,11 +3256,26 @@ static int op_lock_and_prep(struct drm_exec *exec, struct xe_vm *vm,
 						    .request_decompress = false,
 						    .check_purged = true,
 					    });
-		if (!err && !xe_vma_has_no_bo(vma))
-			err = xe_bo_migrate(xe_vma_bo(vma),
-					    region_to_mem_type[region],
-					    NULL,
-					    exec);
+		if (!err && !xe_vma_has_no_bo(vma)) {
+			struct xe_bo *bo = xe_vma_bo(vma);
+			u32 mem_type;
+
+			if (region == DRM_XE_CONSULT_MEM_ADVISE_PREF_LOC) {
+				unsigned int i;
+
+				mem_type = XE_PL_TT;
+				for (i = 0; i < bo->placement.num_placement; i++) {
+					if (mem_type_is_vram(bo->placements[i].mem_type)) {
+						mem_type = bo->placements[i].mem_type;
+						break;
+					}
+				}
+			} else {
+				mem_type = region_to_mem_type[region];
+			}
+
+			err = xe_bo_migrate(bo, mem_type, NULL, exec);
+		}
 		break;
 	}
 	default:
diff --git linux-libre-7.1.5-gnu/drivers/gpu/drm/xe/xe_vm_madvise.c linux-libre-7.1.6-gnu/drivers/gpu/drm/xe/xe_vm_madvise.c
index 246fe18431428..0474768a38aaa 100644
--- linux-libre-7.1.5-gnu/drivers/gpu/drm/xe/xe_vm_madvise.c
+++ linux-libre-7.1.6-gnu/drivers/gpu/drm/xe/xe_vm_madvise.c
@@ -332,6 +332,20 @@ static int xe_vm_invalidate_madvise_range(struct xe_vm *vm, u64 start, u64 end)
 	return err;
 }
 
+/**
+ * madvise_range_needs_invalidation() - Check whether madvise needs invalidation
+ * @args: madvise ioctl arguments
+ *
+ * Purgeable state updates only touch VMA/BO metadata. PTEs stay valid and are
+ * zapped only if the BO is later purged.
+ *
+ * Return: true when the update needs PTE invalidation.
+ */
+static bool madvise_range_needs_invalidation(const struct drm_xe_madvise *args)
+{
+	return args->type != DRM_XE_VMA_ATTR_PURGEABLE_STATE;
+}
+
 static bool madvise_args_are_sane(struct xe_device *xe, const struct drm_xe_madvise *args)
 {
 	if (XE_IOCTL_DBG(xe, !args))
@@ -708,8 +722,9 @@ int xe_vm_madvise_ioctl(struct drm_device *dev, void *data, struct drm_file *fil
 	madvise_funcs[attr_type](xe, vm, madvise_range.vmas, madvise_range.num_vmas, args,
 				 &details);
 
-	err = xe_vm_invalidate_madvise_range(vm, madvise_range.addr,
-					     madvise_range.addr + args->range);
+	if (madvise_range_needs_invalidation(args))
+		err = xe_vm_invalidate_madvise_range(vm, madvise_range.addr,
+						     madvise_range.addr + args->range);
 
 	if (madvise_range.has_svm_userptr_vmas)
 		xe_svm_notifier_unlock(vm);
diff --git linux-libre-7.1.5-gnu/drivers/gpu/drm/xe/xe_wopcm.c linux-libre-7.1.6-gnu/drivers/gpu/drm/xe/xe_wopcm.c
index 900daf1d1b1bb..fe65ed246775d 100644
--- linux-libre-7.1.5-gnu/drivers/gpu/drm/xe/xe_wopcm.c
+++ linux-libre-7.1.6-gnu/drivers/gpu/drm/xe/xe_wopcm.c
@@ -49,9 +49,9 @@
  */
 
 /* Default WOPCM size is 2MB from Gen11, 1MB on previous platforms */
-/* FIXME: Larger size require for 2 tile PVC, do a proper probe sooner or later */
+/* FIXME: Larger size require for some platforms, do a proper probe sooner or later */
 #define DGFX_WOPCM_SIZE			SZ_4M
-/* FIXME: Larger size require for MTL, do a proper probe sooner or later */
+#define LNL_WOPCM_SIZE			SZ_8M
 #define MTL_WOPCM_SIZE			SZ_4M
 #define WOPCM_SIZE			SZ_2M
 
@@ -179,9 +179,14 @@ err_out:
 
 u32 xe_wopcm_size(struct xe_device *xe)
 {
-	return IS_DGFX(xe) ? DGFX_WOPCM_SIZE :
-		xe->info.platform == XE_METEORLAKE ? MTL_WOPCM_SIZE :
-		WOPCM_SIZE;
+	if (xe->info.platform >= XE_LUNARLAKE)
+		return LNL_WOPCM_SIZE;
+	else if (IS_DGFX(xe))
+		return DGFX_WOPCM_SIZE;
+	else if (xe->info.platform == XE_METEORLAKE)
+		return MTL_WOPCM_SIZE;
+	else
+		return WOPCM_SIZE;
 }
 
 static u32 max_wopcm_size(struct xe_device *xe)
diff --git linux-libre-7.1.5-gnu/drivers/gpu/host1x/bus.c linux-libre-7.1.6-gnu/drivers/gpu/host1x/bus.c
index c273a4476f237..a8cddb3425b42 100644
--- linux-libre-7.1.5-gnu/drivers/gpu/host1x/bus.c
+++ linux-libre-7.1.6-gnu/drivers/gpu/host1x/bus.c
@@ -1012,10 +1012,10 @@ void host1x_bo_clear_cached_mappings(struct host1x_bo *bo)
 		if (WARN_ON(!cache))
 			continue;
 
-		mutex_lock(&mapping->cache->lock);
+		mutex_lock(&cache->lock);
 		WARN_ON(kref_read(&mapping->ref) != 1);
 		__host1x_bo_unpin(&mapping->ref);
-		mutex_unlock(&mapping->cache->lock);
+		mutex_unlock(&cache->lock);
 	}
 }
 EXPORT_SYMBOL(host1x_bo_clear_cached_mappings);
diff --git linux-libre-7.1.5-gnu/drivers/hwmon/ad7414.c linux-libre-7.1.6-gnu/drivers/hwmon/ad7414.c
index f0b17e59827f9..c2df631ae93a3 100644
--- linux-libre-7.1.5-gnu/drivers/hwmon/ad7414.c
+++ linux-libre-7.1.6-gnu/drivers/hwmon/ad7414.c
@@ -205,8 +205,8 @@ static int ad7414_probe(struct i2c_client *client)
 }
 
 static const struct i2c_device_id ad7414_id[] = {
-	{ "ad7414" },
-	{}
+	{ .name = "ad7414" },
+	{ }
 };
 MODULE_DEVICE_TABLE(i2c, ad7414_id);
 
diff --git linux-libre-7.1.5-gnu/drivers/hwmon/ad7418.c linux-libre-7.1.6-gnu/drivers/hwmon/ad7418.c
index 7a132accdf8a3..a0c9cf5e12cc4 100644
--- linux-libre-7.1.5-gnu/drivers/hwmon/ad7418.c
+++ linux-libre-7.1.6-gnu/drivers/hwmon/ad7418.c
@@ -281,9 +281,9 @@ static int ad7418_probe(struct i2c_client *client)
 }
 
 static const struct i2c_device_id ad7418_id[] = {
-	{ "ad7416", ad7416 },
-	{ "ad7417", ad7417 },
-	{ "ad7418", ad7418 },
+	{ .name = "ad7416", .driver_data = ad7416 },
+	{ .name = "ad7417", .driver_data = ad7417 },
+	{ .name = "ad7418", .driver_data = ad7418 },
 	{ }
 };
 MODULE_DEVICE_TABLE(i2c, ad7418_id);
diff --git linux-libre-7.1.5-gnu/drivers/hwmon/adc128d818.c linux-libre-7.1.6-gnu/drivers/hwmon/adc128d818.c
index 5e805d4ee76ab..e45adc0b84d1c 100644
--- linux-libre-7.1.5-gnu/drivers/hwmon/adc128d818.c
+++ linux-libre-7.1.6-gnu/drivers/hwmon/adc128d818.c
@@ -480,7 +480,7 @@ static int adc128_probe(struct i2c_client *client)
 }
 
 static const struct i2c_device_id adc128_id[] = {
-	{ "adc128d818" },
+	{ .name = "adc128d818" },
 	{ }
 };
 MODULE_DEVICE_TABLE(i2c, adc128_id);
diff --git linux-libre-7.1.5-gnu/drivers/hwmon/adm1025.c linux-libre-7.1.6-gnu/drivers/hwmon/adm1025.c
index 389382d54752e..ccac7ba601e99 100644
--- linux-libre-7.1.5-gnu/drivers/hwmon/adm1025.c
+++ linux-libre-7.1.6-gnu/drivers/hwmon/adm1025.c
@@ -548,8 +548,8 @@ static int adm1025_probe(struct i2c_client *client)
 }
 
 static const struct i2c_device_id adm1025_id[] = {
-	{ "adm1025", adm1025 },
-	{ "ne1619", ne1619 },
+	{ .name = "adm1025", .driver_data = adm1025 },
+	{ .name = "ne1619", .driver_data = ne1619 },
 	{ }
 };
 MODULE_DEVICE_TABLE(i2c, adm1025_id);
diff --git linux-libre-7.1.5-gnu/drivers/hwmon/adm1026.c linux-libre-7.1.6-gnu/drivers/hwmon/adm1026.c
index c38c932e5d2af..3ad82c01f81d5 100644
--- linux-libre-7.1.5-gnu/drivers/hwmon/adm1026.c
+++ linux-libre-7.1.6-gnu/drivers/hwmon/adm1026.c
@@ -1857,7 +1857,7 @@ static int adm1026_probe(struct i2c_client *client)
 }
 
 static const struct i2c_device_id adm1026_id[] = {
-	{ "adm1026" },
+	{ .name = "adm1026" },
 	{ }
 };
 MODULE_DEVICE_TABLE(i2c, adm1026_id);
diff --git linux-libre-7.1.5-gnu/drivers/hwmon/adm1029.c linux-libre-7.1.6-gnu/drivers/hwmon/adm1029.c
index 71eea8ae51b95..6cb0a238e059b 100644
--- linux-libre-7.1.5-gnu/drivers/hwmon/adm1029.c
+++ linux-libre-7.1.6-gnu/drivers/hwmon/adm1029.c
@@ -382,7 +382,7 @@ static int adm1029_probe(struct i2c_client *client)
 }
 
 static const struct i2c_device_id adm1029_id[] = {
-	{ "adm1029" },
+	{ .name = "adm1029" },
 	{ }
 };
 MODULE_DEVICE_TABLE(i2c, adm1029_id);
diff --git linux-libre-7.1.5-gnu/drivers/hwmon/adm1031.c linux-libre-7.1.6-gnu/drivers/hwmon/adm1031.c
index 343118532cdb4..24d0d4146c877 100644
--- linux-libre-7.1.5-gnu/drivers/hwmon/adm1031.c
+++ linux-libre-7.1.6-gnu/drivers/hwmon/adm1031.c
@@ -1055,8 +1055,8 @@ static int adm1031_probe(struct i2c_client *client)
 }
 
 static const struct i2c_device_id adm1031_id[] = {
-	{ "adm1030", adm1030 },
-	{ "adm1031", adm1031 },
+	{ .name = "adm1030", .driver_data = adm1030 },
+	{ .name = "adm1031", .driver_data = adm1031 },
 	{ }
 };
 MODULE_DEVICE_TABLE(i2c, adm1031_id);
diff --git linux-libre-7.1.5-gnu/drivers/hwmon/adm1177.c linux-libre-7.1.6-gnu/drivers/hwmon/adm1177.c
index 7888afe8dafd6..dc4d8a214d1b4 100644
--- linux-libre-7.1.5-gnu/drivers/hwmon/adm1177.c
+++ linux-libre-7.1.6-gnu/drivers/hwmon/adm1177.c
@@ -246,8 +246,8 @@ static int adm1177_probe(struct i2c_client *client)
 }
 
 static const struct i2c_device_id adm1177_id[] = {
-	{"adm1177"},
-	{}
+	{ .name = "adm1177" },
+	{ }
 };
 MODULE_DEVICE_TABLE(i2c, adm1177_id);
 
diff --git linux-libre-7.1.5-gnu/drivers/hwmon/adm9240.c linux-libre-7.1.6-gnu/drivers/hwmon/adm9240.c
index 86f6044b5bd04..586650e8d043f 100644
--- linux-libre-7.1.5-gnu/drivers/hwmon/adm9240.c
+++ linux-libre-7.1.6-gnu/drivers/hwmon/adm9240.c
@@ -794,9 +794,9 @@ static int adm9240_probe(struct i2c_client *client)
 }
 
 static const struct i2c_device_id adm9240_id[] = {
-	{ "adm9240", adm9240 },
-	{ "ds1780", ds1780 },
-	{ "lm81", lm81 },
+	{ .name = "adm9240", .driver_data = adm9240 },
+	{ .name = "ds1780", .driver_data = ds1780 },
+	{ .name = "lm81", .driver_data = lm81 },
 	{ }
 };
 MODULE_DEVICE_TABLE(i2c, adm9240_id);
diff --git linux-libre-7.1.5-gnu/drivers/hwmon/ads7828.c linux-libre-7.1.6-gnu/drivers/hwmon/ads7828.c
index 7f43565ca2841..149cfcec78dcc 100644
--- linux-libre-7.1.5-gnu/drivers/hwmon/ads7828.c
+++ linux-libre-7.1.6-gnu/drivers/hwmon/ads7828.c
@@ -176,8 +176,8 @@ static int ads7828_probe(struct i2c_client *client)
 }
 
 static const struct i2c_device_id ads7828_device_ids[] = {
-	{ "ads7828", ads7828 },
-	{ "ads7830", ads7830 },
+	{ .name = "ads7828", .driver_data = ads7828 },
+	{ .name = "ads7830", .driver_data = ads7830 },
 	{ }
 };
 MODULE_DEVICE_TABLE(i2c, ads7828_device_ids);
diff --git linux-libre-7.1.5-gnu/drivers/hwmon/adt7410.c linux-libre-7.1.6-gnu/drivers/hwmon/adt7410.c
index 73b196a78f3a0..0aa7ce0a04be0 100644
--- linux-libre-7.1.5-gnu/drivers/hwmon/adt7410.c
+++ linux-libre-7.1.6-gnu/drivers/hwmon/adt7410.c
@@ -89,10 +89,10 @@ static int adt7410_i2c_probe(struct i2c_client *client)
 }
 
 static const struct i2c_device_id adt7410_ids[] = {
-	{ "adt7410" },
-	{ "adt7420" },
-	{ "adt7422" },
-	{}
+	{ .name = "adt7410" },
+	{ .name = "adt7420" },
+	{ .name = "adt7422" },
+	{ }
 };
 MODULE_DEVICE_TABLE(i2c, adt7410_ids);
 
diff --git linux-libre-7.1.5-gnu/drivers/hwmon/adt7411.c linux-libre-7.1.6-gnu/drivers/hwmon/adt7411.c
index b9991a69e6c60..5dce2a7017258 100644
--- linux-libre-7.1.5-gnu/drivers/hwmon/adt7411.c
+++ linux-libre-7.1.6-gnu/drivers/hwmon/adt7411.c
@@ -670,7 +670,7 @@ static int adt7411_probe(struct i2c_client *client)
 }
 
 static const struct i2c_device_id adt7411_id[] = {
-	{ "adt7411" },
+	{ .name = "adt7411" },
 	{ }
 };
 MODULE_DEVICE_TABLE(i2c, adt7411_id);
diff --git linux-libre-7.1.5-gnu/drivers/hwmon/adt7462.c linux-libre-7.1.6-gnu/drivers/hwmon/adt7462.c
index 174dfee47f7a7..5101d30ed9c68 100644
--- linux-libre-7.1.5-gnu/drivers/hwmon/adt7462.c
+++ linux-libre-7.1.6-gnu/drivers/hwmon/adt7462.c
@@ -1809,7 +1809,7 @@ static int adt7462_probe(struct i2c_client *client)
 }
 
 static const struct i2c_device_id adt7462_id[] = {
-	{ "adt7462" },
+	{ .name = "adt7462" },
 	{ }
 };
 MODULE_DEVICE_TABLE(i2c, adt7462_id);
diff --git linux-libre-7.1.5-gnu/drivers/hwmon/adt7470.c linux-libre-7.1.6-gnu/drivers/hwmon/adt7470.c
index dbee6926fa055..664349756dc2b 100644
--- linux-libre-7.1.5-gnu/drivers/hwmon/adt7470.c
+++ linux-libre-7.1.6-gnu/drivers/hwmon/adt7470.c
@@ -1296,7 +1296,7 @@ static void adt7470_remove(struct i2c_client *client)
 }
 
 static const struct i2c_device_id adt7470_id[] = {
-	{ "adt7470" },
+	{ .name = "adt7470" },
 	{ }
 };
 MODULE_DEVICE_TABLE(i2c, adt7470_id);
diff --git linux-libre-7.1.5-gnu/drivers/hwmon/adt7475.c linux-libre-7.1.6-gnu/drivers/hwmon/adt7475.c
index 8cefa14e1633b..7fb96f5395fa6 100644
--- linux-libre-7.1.5-gnu/drivers/hwmon/adt7475.c
+++ linux-libre-7.1.6-gnu/drivers/hwmon/adt7475.c
@@ -165,10 +165,10 @@ static const unsigned short normal_i2c[] = { 0x2c, 0x2d, 0x2e, I2C_CLIENT_END };
 enum chips { adt7473, adt7475, adt7476, adt7490 };
 
 static const struct i2c_device_id adt7475_id[] = {
-	{ "adt7473", adt7473 },
-	{ "adt7475", adt7475 },
-	{ "adt7476", adt7476 },
-	{ "adt7490", adt7490 },
+	{ .name = "adt7473", .driver_data = adt7473 },
+	{ .name = "adt7475", .driver_data = adt7475 },
+	{ .name = "adt7476", .driver_data = adt7476 },
+	{ .name = "adt7490", .driver_data = adt7490 },
 	{ }
 };
 MODULE_DEVICE_TABLE(i2c, adt7475_id);
diff --git linux-libre-7.1.5-gnu/drivers/hwmon/aht10.c linux-libre-7.1.6-gnu/drivers/hwmon/aht10.c
index 66955395d0583..6c263cb577666 100644
--- linux-libre-7.1.5-gnu/drivers/hwmon/aht10.c
+++ linux-libre-7.1.6-gnu/drivers/hwmon/aht10.c
@@ -55,10 +55,10 @@
 enum aht10_variant { aht10, aht20, dht20};
 
 static const struct i2c_device_id aht10_id[] = {
-	{ "aht10", aht10 },
-	{ "aht20", aht20 },
-	{ "dht20", dht20 },
-	{ },
+	{ .name = "aht10", .driver_data = aht10 },
+	{ .name = "aht20", .driver_data = aht20 },
+	{ .name = "dht20", .driver_data = dht20 },
+	{ }
 };
 MODULE_DEVICE_TABLE(i2c, aht10_id);
 
diff --git linux-libre-7.1.5-gnu/drivers/hwmon/amc6821.c linux-libre-7.1.6-gnu/drivers/hwmon/amc6821.c
index d5f864b360b03..bbc0542a7d380 100644
--- linux-libre-7.1.5-gnu/drivers/hwmon/amc6821.c
+++ linux-libre-7.1.6-gnu/drivers/hwmon/amc6821.c
@@ -1083,7 +1083,7 @@ static int amc6821_probe(struct i2c_client *client)
 }
 
 static const struct i2c_device_id amc6821_id[] = {
-	{ "amc6821" },
+	{ .name = "amc6821" },
 	{ }
 };
 
diff --git linux-libre-7.1.5-gnu/drivers/hwmon/asb100.c linux-libre-7.1.6-gnu/drivers/hwmon/asb100.c
index 14e7737866c25..5f5c945051665 100644
--- linux-libre-7.1.5-gnu/drivers/hwmon/asb100.c
+++ linux-libre-7.1.6-gnu/drivers/hwmon/asb100.c
@@ -213,7 +213,7 @@ static struct asb100_data *asb100_update_device(struct device *dev);
 static void asb100_init_client(struct i2c_client *client);
 
 static const struct i2c_device_id asb100_id[] = {
-	{ "asb100" },
+	{ .name = "asb100" },
 	{ }
 };
 MODULE_DEVICE_TABLE(i2c, asb100_id);
diff --git linux-libre-7.1.5-gnu/drivers/hwmon/asc7621.c linux-libre-7.1.6-gnu/drivers/hwmon/asc7621.c
index 87e1867008499..e8145bb13ab34 100644
--- linux-libre-7.1.5-gnu/drivers/hwmon/asc7621.c
+++ linux-libre-7.1.6-gnu/drivers/hwmon/asc7621.c
@@ -1179,9 +1179,9 @@ static void asc7621_remove(struct i2c_client *client)
 }
 
 static const struct i2c_device_id asc7621_id[] = {
-	{"asc7621", asc7621},
-	{"asc7621a", asc7621a},
-	{},
+	{ .name = "asc7621", .driver_data = asc7621 },
+	{ .name = "asc7621a", .driver_data = asc7621a },
+	{ }
 };
 
 MODULE_DEVICE_TABLE(i2c, asc7621_id);
diff --git linux-libre-7.1.5-gnu/drivers/hwmon/asus-ec-sensors.c linux-libre-7.1.6-gnu/drivers/hwmon/asus-ec-sensors.c
index b5d97a27f80d3..7c281c6005ec6 100644
--- linux-libre-7.1.5-gnu/drivers/hwmon/asus-ec-sensors.c
+++ linux-libre-7.1.6-gnu/drivers/hwmon/asus-ec-sensors.c
@@ -974,7 +974,7 @@ struct ec_sensors_data {
 	/* sorted list of unique register banks */
 	u8 banks[ASUS_EC_MAX_BANK + 1];
 	/* in jiffies */
-	unsigned long last_updated;
+	u64 next_update;
 	struct lock_data lock_data;
 	/* number of board EC sensors */
 	u8 nr_sensors;
@@ -1154,7 +1154,7 @@ static int asus_ec_block_read(const struct device *dev,
 		}
 		for (ireg = 0; ireg < ec->nr_registers; ireg++) {
 			reg_bank = register_bank(ec->registers[ireg]);
-			if (reg_bank < bank) {
+			if (reg_bank != bank) {
 				continue;
 			}
 			ec_read(register_index(ec->registers[ireg]),
@@ -1243,13 +1243,12 @@ static int get_cached_value_or_update(const struct device *dev,
 				      int sensor_index,
 				      struct ec_sensors_data *state, s32 *value)
 {
-	if (time_after(jiffies, state->last_updated + HZ)) {
+	if (time_after64(get_jiffies_64(), state->next_update)) {
 		if (update_ec_sensors(dev, state)) {
 			dev_err(dev, "update_ec_sensors() failure\n");
 			return -EIO;
 		}
-
-		state->last_updated = jiffies;
+		state->next_update = get_jiffies_64() + HZ;
 	}
 
 	*value = state->sensors[sensor_index].cached_value;
@@ -1367,6 +1366,7 @@ static int asus_ec_probe(struct platform_device *pdev)
 	if (!ec_data)
 		return -ENOMEM;
 
+	ec_data->next_update = INITIAL_JIFFIES;
 	dev_set_drvdata(dev, ec_data);
 	ec_data->board_info = pboard_info;
 
@@ -1460,9 +1460,11 @@ static int asus_ec_probe(struct platform_device *pdev)
 		if (!nr_count[type])
 			continue;
 
-		asus_ec_hwmon_add_chan_info(asus_ec_hwmon_chan, dev,
-					     nr_count[type], type,
-					     hwmon_attributes[type]);
+		status = asus_ec_hwmon_add_chan_info(asus_ec_hwmon_chan, dev,
+						     nr_count[type], type,
+						     hwmon_attributes[type]);
+		if (status)
+			return status;
 		*ptr_asus_ec_ci++ = asus_ec_hwmon_chan++;
 	}
 
diff --git linux-libre-7.1.5-gnu/drivers/hwmon/atxp1.c linux-libre-7.1.6-gnu/drivers/hwmon/atxp1.c
index 1c7e9a98b757c..f5de4894f0a2e 100644
--- linux-libre-7.1.5-gnu/drivers/hwmon/atxp1.c
+++ linux-libre-7.1.6-gnu/drivers/hwmon/atxp1.c
@@ -278,7 +278,7 @@ static int atxp1_probe(struct i2c_client *client)
 };
 
 static const struct i2c_device_id atxp1_id[] = {
-	{ "atxp1" },
+	{ .name = "atxp1" },
 	{ }
 };
 MODULE_DEVICE_TABLE(i2c, atxp1_id);
diff --git linux-libre-7.1.5-gnu/drivers/hwmon/chipcap2.c linux-libre-7.1.6-gnu/drivers/hwmon/chipcap2.c
index 645b8c2e704e6..4aecf463180fd 100644
--- linux-libre-7.1.5-gnu/drivers/hwmon/chipcap2.c
+++ linux-libre-7.1.6-gnu/drivers/hwmon/chipcap2.c
@@ -736,14 +736,14 @@ static void cc2_remove(struct i2c_client *client)
 }
 
 static const struct i2c_device_id cc2_id[] = {
-	{ "cc2d23" },
-	{ "cc2d23s" },
-	{ "cc2d25" },
-	{ "cc2d25s" },
-	{ "cc2d33" },
-	{ "cc2d33s" },
-	{ "cc2d35" },
-	{ "cc2d35s" },
+	{ .name = "cc2d23" },
+	{ .name = "cc2d23s" },
+	{ .name = "cc2d25" },
+	{ .name = "cc2d25s" },
+	{ .name = "cc2d33" },
+	{ .name = "cc2d33s" },
+	{ .name = "cc2d35" },
+	{ .name = "cc2d35s" },
 	{ }
 };
 MODULE_DEVICE_TABLE(i2c, cc2_id);
diff --git linux-libre-7.1.5-gnu/drivers/hwmon/corsair-cpro.c linux-libre-7.1.6-gnu/drivers/hwmon/corsair-cpro.c
index b6e508e43fa17..8354a002f4c5e 100644
--- linux-libre-7.1.5-gnu/drivers/hwmon/corsair-cpro.c
+++ linux-libre-7.1.6-gnu/drivers/hwmon/corsair-cpro.c
@@ -645,6 +645,7 @@ static int ccp_probe(struct hid_device *hdev, const struct hid_device_id *id)
 
 out_hw_close:
 	hid_hw_close(hdev);
+	hid_device_io_stop(hdev);
 out_hw_stop:
 	hid_hw_stop(hdev);
 	return ret;
diff --git linux-libre-7.1.5-gnu/drivers/hwmon/corsair-psu.c linux-libre-7.1.6-gnu/drivers/hwmon/corsair-psu.c
index 76f3e1da68d09..ce958cdaef58a 100644
--- linux-libre-7.1.5-gnu/drivers/hwmon/corsair-psu.c
+++ linux-libre-7.1.6-gnu/drivers/hwmon/corsair-psu.c
@@ -822,6 +822,7 @@ static int corsairpsu_probe(struct hid_device *hdev, const struct hid_device_id
 
 fail_and_close:
 	hid_hw_close(hdev);
+	hid_device_io_stop(hdev);
 fail_and_stop:
 	hid_hw_stop(hdev);
 	return ret;
diff --git linux-libre-7.1.5-gnu/drivers/hwmon/dme1737.c linux-libre-7.1.6-gnu/drivers/hwmon/dme1737.c
index 3d4057309950d..7e839308e58fa 100644
--- linux-libre-7.1.5-gnu/drivers/hwmon/dme1737.c
+++ linux-libre-7.1.6-gnu/drivers/hwmon/dme1737.c
@@ -2515,8 +2515,8 @@ static void dme1737_i2c_remove(struct i2c_client *client)
 }
 
 static const struct i2c_device_id dme1737_id[] = {
-	{ "dme1737", dme1737 },
-	{ "sch5027", sch5027 },
+	{ .name = "dme1737", .driver_data = dme1737 },
+	{ .name = "sch5027", .driver_data = sch5027 },
 	{ }
 };
 MODULE_DEVICE_TABLE(i2c, dme1737_id);
diff --git linux-libre-7.1.5-gnu/drivers/hwmon/ds1621.c linux-libre-7.1.6-gnu/drivers/hwmon/ds1621.c
index 42ec34cb8a5f8..0618f6de9679c 100644
--- linux-libre-7.1.5-gnu/drivers/hwmon/ds1621.c
+++ linux-libre-7.1.6-gnu/drivers/hwmon/ds1621.c
@@ -367,11 +367,11 @@ static int ds1621_probe(struct i2c_client *client)
 }
 
 static const struct i2c_device_id ds1621_id[] = {
-	{ "ds1621", ds1621 },
-	{ "ds1625", ds1625 },
-	{ "ds1631", ds1631 },
-	{ "ds1721", ds1721 },
-	{ "ds1731", ds1731 },
+	{ .name = "ds1621", .driver_data = ds1621 },
+	{ .name = "ds1625", .driver_data = ds1625 },
+	{ .name = "ds1631", .driver_data = ds1631 },
+	{ .name = "ds1721", .driver_data = ds1721 },
+	{ .name = "ds1731", .driver_data = ds1731 },
 	{ }
 };
 MODULE_DEVICE_TABLE(i2c, ds1621_id);
diff --git linux-libre-7.1.5-gnu/drivers/hwmon/ds620.c linux-libre-7.1.6-gnu/drivers/hwmon/ds620.c
index ce397042d90b8..25287f0fa4c2e 100644
--- linux-libre-7.1.5-gnu/drivers/hwmon/ds620.c
+++ linux-libre-7.1.6-gnu/drivers/hwmon/ds620.c
@@ -233,8 +233,8 @@ static int ds620_probe(struct i2c_client *client)
 }
 
 static const struct i2c_device_id ds620_id[] = {
-	{"ds620"},
-	{}
+	{ .name = "ds620" },
+	{ }
 };
 
 MODULE_DEVICE_TABLE(i2c, ds620_id);
diff --git linux-libre-7.1.5-gnu/drivers/hwmon/emc1403.c linux-libre-7.1.6-gnu/drivers/hwmon/emc1403.c
index 964a8cb278f16..cd753b38709f2 100644
--- linux-libre-7.1.5-gnu/drivers/hwmon/emc1403.c
+++ linux-libre-7.1.6-gnu/drivers/hwmon/emc1403.c
@@ -639,18 +639,18 @@ static const struct hwmon_chip_info emc1403_chip_info = {
 
 /* Last digit of chip name indicates number of channels */
 static const struct i2c_device_id emc1403_idtable[] = {
-	{ "emc1402", emc1402 },
-	{ "emc1403", emc1403 },
-	{ "emc1404", emc1404 },
-	{ "emc1412", emc1402 },
-	{ "emc1413", emc1403 },
-	{ "emc1414", emc1404 },
-	{ "emc1422", emc1402 },
-	{ "emc1423", emc1403 },
-	{ "emc1424", emc1404 },
-	{ "emc1428", emc1428 },
-	{ "emc1438", emc1428 },
-	{ "emc1442", emc1402 },
+	{ .name = "emc1402", .driver_data = emc1402 },
+	{ .name = "emc1403", .driver_data = emc1403 },
+	{ .name = "emc1404", .driver_data = emc1404 },
+	{ .name = "emc1412", .driver_data = emc1402 },
+	{ .name = "emc1413", .driver_data = emc1403 },
+	{ .name = "emc1414", .driver_data = emc1404 },
+	{ .name = "emc1422", .driver_data = emc1402 },
+	{ .name = "emc1423", .driver_data = emc1403 },
+	{ .name = "emc1424", .driver_data = emc1404 },
+	{ .name = "emc1428", .driver_data = emc1428 },
+	{ .name = "emc1438", .driver_data = emc1428 },
+	{ .name = "emc1442", .driver_data = emc1402 },
 	{ }
 };
 MODULE_DEVICE_TABLE(i2c, emc1403_idtable);
diff --git linux-libre-7.1.5-gnu/drivers/hwmon/emc2103.c linux-libre-7.1.6-gnu/drivers/hwmon/emc2103.c
index 9b8e925af0300..27dc149a3ed99 100644
--- linux-libre-7.1.5-gnu/drivers/hwmon/emc2103.c
+++ linux-libre-7.1.6-gnu/drivers/hwmon/emc2103.c
@@ -624,7 +624,7 @@ emc2103_probe(struct i2c_client *client)
 }
 
 static const struct i2c_device_id emc2103_ids[] = {
-	{ "emc2103" },
+	{ .name = "emc2103" },
 	{ /* LIST END */ }
 };
 MODULE_DEVICE_TABLE(i2c, emc2103_ids);
diff --git linux-libre-7.1.5-gnu/drivers/hwmon/emc2305.c linux-libre-7.1.6-gnu/drivers/hwmon/emc2305.c
index 64b213e1451e7..8fcdac6cfb24d 100644
--- linux-libre-7.1.5-gnu/drivers/hwmon/emc2305.c
+++ linux-libre-7.1.6-gnu/drivers/hwmon/emc2305.c
@@ -59,10 +59,10 @@ enum emc230x_product_id {
 };
 
 static const struct i2c_device_id emc2305_ids[] = {
-	{ "emc2305" },
-	{ "emc2303" },
-	{ "emc2302" },
-	{ "emc2301" },
+	{ .name = "emc2305" },
+	{ .name = "emc2303" },
+	{ .name = "emc2302" },
+	{ .name = "emc2301" },
 	{ }
 };
 MODULE_DEVICE_TABLE(i2c, emc2305_ids);
diff --git linux-libre-7.1.5-gnu/drivers/hwmon/emc6w201.c linux-libre-7.1.6-gnu/drivers/hwmon/emc6w201.c
index 1100c6e5daa77..c13ea87486835 100644
--- linux-libre-7.1.5-gnu/drivers/hwmon/emc6w201.c
+++ linux-libre-7.1.6-gnu/drivers/hwmon/emc6w201.c
@@ -464,7 +464,7 @@ static int emc6w201_probe(struct i2c_client *client)
 }
 
 static const struct i2c_device_id emc6w201_id[] = {
-	{ "emc6w201" },
+	{ .name = "emc6w201" },
 	{ }
 };
 MODULE_DEVICE_TABLE(i2c, emc6w201_id);
diff --git linux-libre-7.1.5-gnu/drivers/hwmon/f75375s.c linux-libre-7.1.6-gnu/drivers/hwmon/f75375s.c
index 7e867f1324201..cc3a9612f2c0a 100644
--- linux-libre-7.1.5-gnu/drivers/hwmon/f75375s.c
+++ linux-libre-7.1.6-gnu/drivers/hwmon/f75375s.c
@@ -877,9 +877,9 @@ static int f75375_detect(struct i2c_client *client,
 }
 
 static const struct i2c_device_id f75375_id[] = {
-	{ "f75373", f75373 },
-	{ "f75375", f75375 },
-	{ "f75387", f75387 },
+	{ .name = "f75373", .driver_data = f75373 },
+	{ .name = "f75375", .driver_data = f75375 },
+	{ .name = "f75387", .driver_data = f75387 },
 	{ }
 };
 MODULE_DEVICE_TABLE(i2c, f75375_id);
diff --git linux-libre-7.1.5-gnu/drivers/hwmon/fschmd.c linux-libre-7.1.6-gnu/drivers/hwmon/fschmd.c
index 1211fa2259e52..019fc32bf3181 100644
--- linux-libre-7.1.5-gnu/drivers/hwmon/fschmd.c
+++ linux-libre-7.1.6-gnu/drivers/hwmon/fschmd.c
@@ -225,13 +225,13 @@ static struct fschmd_data *fschmd_update_device(struct device *dev);
  */
 
 static const struct i2c_device_id fschmd_id[] = {
-	{ "fscpos", fscpos },
-	{ "fscher", fscher },
-	{ "fscscy", fscscy },
-	{ "fschrc", fschrc },
-	{ "fschmd", fschmd },
-	{ "fschds", fschds },
-	{ "fscsyl", fscsyl },
+	{ .name = "fscpos", .driver_data = fscpos },
+	{ .name = "fscher", .driver_data = fscher },
+	{ .name = "fscscy", .driver_data = fscscy },
+	{ .name = "fschrc", .driver_data = fschrc },
+	{ .name = "fschmd", .driver_data = fschmd },
+	{ .name = "fschds", .driver_data = fschds },
+	{ .name = "fscsyl", .driver_data = fscsyl },
 	{ }
 };
 MODULE_DEVICE_TABLE(i2c, fschmd_id);
diff --git linux-libre-7.1.5-gnu/drivers/hwmon/ftsteutates.c linux-libre-7.1.6-gnu/drivers/hwmon/ftsteutates.c
index 08dcc6a7fb625..06be120a349d6 100644
--- linux-libre-7.1.5-gnu/drivers/hwmon/ftsteutates.c
+++ linux-libre-7.1.6-gnu/drivers/hwmon/ftsteutates.c
@@ -49,7 +49,7 @@
 static const unsigned short normal_i2c[] = { 0x73, I2C_CLIENT_END };
 
 static const struct i2c_device_id fts_id[] = {
-	{ "ftsteutates" },
+	{ .name = "ftsteutates" },
 	{ }
 };
 MODULE_DEVICE_TABLE(i2c, fts_id);
diff --git linux-libre-7.1.5-gnu/drivers/hwmon/g760a.c linux-libre-7.1.6-gnu/drivers/hwmon/g760a.c
index 39ae8f8264176..e2166ee762860 100644
--- linux-libre-7.1.5-gnu/drivers/hwmon/g760a.c
+++ linux-libre-7.1.6-gnu/drivers/hwmon/g760a.c
@@ -197,7 +197,7 @@ static int g760a_probe(struct i2c_client *client)
 }
 
 static const struct i2c_device_id g760a_id[] = {
-	{ "g760a" },
+	{ .name = "g760a" },
 	{ }
 };
 MODULE_DEVICE_TABLE(i2c, g760a_id);
diff --git linux-libre-7.1.5-gnu/drivers/hwmon/g762.c linux-libre-7.1.6-gnu/drivers/hwmon/g762.c
index 4fa3aa1271daa..407cf7af4fdd9 100644
--- linux-libre-7.1.5-gnu/drivers/hwmon/g762.c
+++ linux-libre-7.1.6-gnu/drivers/hwmon/g762.c
@@ -44,9 +44,9 @@
 #define DRVNAME "g762"
 
 static const struct i2c_device_id g762_id[] = {
-	{ "g761" },
-	{ "g762" },
-	{ "g763" },
+	{ .name = "g761" },
+	{ .name = "g762" },
+	{ .name = "g763" },
 	{ }
 };
 MODULE_DEVICE_TABLE(i2c, g762_id);
diff --git linux-libre-7.1.5-gnu/drivers/hwmon/gigabyte_waterforce.c linux-libre-7.1.6-gnu/drivers/hwmon/gigabyte_waterforce.c
index 27487e215bddf..4eea05f8b569c 100644
--- linux-libre-7.1.5-gnu/drivers/hwmon/gigabyte_waterforce.c
+++ linux-libre-7.1.6-gnu/drivers/hwmon/gigabyte_waterforce.c
@@ -371,13 +371,15 @@ static int waterforce_probe(struct hid_device *hdev, const struct hid_device_id
 	if (IS_ERR(priv->hwmon_dev)) {
 		ret = PTR_ERR(priv->hwmon_dev);
 		hid_err(hdev, "hwmon registration failed with %d\n", ret);
-		goto fail_and_close;
+		goto fail_and_io_stop;
 	}
 
 	waterforce_debugfs_init(priv);
 
 	return 0;
 
+fail_and_io_stop:
+	hid_device_io_stop(hdev);
 fail_and_close:
 	hid_hw_close(hdev);
 fail_and_stop:
diff --git linux-libre-7.1.5-gnu/drivers/hwmon/gl518sm.c linux-libre-7.1.6-gnu/drivers/hwmon/gl518sm.c
index 9c68bc0139503..742c130cec7f1 100644
--- linux-libre-7.1.5-gnu/drivers/hwmon/gl518sm.c
+++ linux-libre-7.1.6-gnu/drivers/hwmon/gl518sm.c
@@ -642,7 +642,7 @@ static int gl518_probe(struct i2c_client *client)
 }
 
 static const struct i2c_device_id gl518_id[] = {
-	{ "gl518sm" },
+	{ .name = "gl518sm" },
 	{ }
 };
 MODULE_DEVICE_TABLE(i2c, gl518_id);
diff --git linux-libre-7.1.5-gnu/drivers/hwmon/gl520sm.c linux-libre-7.1.6-gnu/drivers/hwmon/gl520sm.c
index 972f4f8caa2b7..f4fe39912ee29 100644
--- linux-libre-7.1.5-gnu/drivers/hwmon/gl520sm.c
+++ linux-libre-7.1.6-gnu/drivers/hwmon/gl520sm.c
@@ -885,7 +885,7 @@ static int gl520_probe(struct i2c_client *client)
 }
 
 static const struct i2c_device_id gl520_id[] = {
-	{ "gl520sm" },
+	{ .name = "gl520sm" },
 	{ }
 };
 MODULE_DEVICE_TABLE(i2c, gl520_id);
diff --git linux-libre-7.1.5-gnu/drivers/hwmon/hih6130.c linux-libre-7.1.6-gnu/drivers/hwmon/hih6130.c
index 85af8299150a5..7984be1e706d5 100644
--- linux-libre-7.1.5-gnu/drivers/hwmon/hih6130.c
+++ linux-libre-7.1.6-gnu/drivers/hwmon/hih6130.c
@@ -233,7 +233,7 @@ static int hih6130_probe(struct i2c_client *client)
 
 /* Device ID table */
 static const struct i2c_device_id hih6130_id[] = {
-	{ "hih6130" },
+	{ .name = "hih6130" },
 	{ }
 };
 MODULE_DEVICE_TABLE(i2c, hih6130_id);
diff --git linux-libre-7.1.5-gnu/drivers/hwmon/hs3001.c linux-libre-7.1.6-gnu/drivers/hwmon/hs3001.c
index 50c6c15f8b180..b263cbeca0747 100644
--- linux-libre-7.1.5-gnu/drivers/hwmon/hs3001.c
+++ linux-libre-7.1.6-gnu/drivers/hwmon/hs3001.c
@@ -169,8 +169,8 @@ static const struct hwmon_chip_info hs3001_chip_info = {
 
 /* device ID table */
 static const struct i2c_device_id hs3001_ids[] = {
-	{ "hs3001" },
-	{ },
+	{ .name = "hs3001" },
+	{ }
 };
 
 MODULE_DEVICE_TABLE(i2c, hs3001_ids);
diff --git linux-libre-7.1.5-gnu/drivers/hwmon/htu31.c linux-libre-7.1.6-gnu/drivers/hwmon/htu31.c
index 7521a371aa6cd..5d2cdbdb773b0 100644
--- linux-libre-7.1.5-gnu/drivers/hwmon/htu31.c
+++ linux-libre-7.1.6-gnu/drivers/hwmon/htu31.c
@@ -322,7 +322,7 @@ static int htu31_probe(struct i2c_client *client)
 }
 
 static const struct i2c_device_id htu31_id[] = {
-	{ "htu31" },
+	{ .name = "htu31" },
 	{ }
 };
 MODULE_DEVICE_TABLE(i2c, htu31_id);
diff --git linux-libre-7.1.5-gnu/drivers/hwmon/ina209.c linux-libre-7.1.6-gnu/drivers/hwmon/ina209.c
index a116f1600e810..39aca2cdf27f7 100644
--- linux-libre-7.1.5-gnu/drivers/hwmon/ina209.c
+++ linux-libre-7.1.6-gnu/drivers/hwmon/ina209.c
@@ -569,7 +569,7 @@ static void ina209_remove(struct i2c_client *client)
 }
 
 static const struct i2c_device_id ina209_id[] = {
-	{ "ina209" },
+	{ .name = "ina209" },
 	{ }
 };
 MODULE_DEVICE_TABLE(i2c, ina209_id);
diff --git linux-libre-7.1.5-gnu/drivers/hwmon/ina238.c linux-libre-7.1.6-gnu/drivers/hwmon/ina238.c
index ff67b03189f73..c20dd164a6a6c 100644
--- linux-libre-7.1.5-gnu/drivers/hwmon/ina238.c
+++ linux-libre-7.1.6-gnu/drivers/hwmon/ina238.c
@@ -837,12 +837,12 @@ static int ina238_probe(struct i2c_client *client)
 }
 
 static const struct i2c_device_id ina238_id[] = {
-	{ "ina228", ina228 },
-	{ "ina237", ina237 },
-	{ "ina238", ina238 },
-	{ "ina700", ina700 },
-	{ "ina780", ina780 },
-	{ "sq52206", sq52206 },
+	{ .name = "ina228", .driver_data = ina228 },
+	{ .name = "ina237", .driver_data = ina237 },
+	{ .name = "ina238", .driver_data = ina238 },
+	{ .name = "ina700", .driver_data = ina700 },
+	{ .name = "ina780", .driver_data = ina780 },
+	{ .name = "sq52206", .driver_data = sq52206 },
 	{ }
 };
 MODULE_DEVICE_TABLE(i2c, ina238_id);
diff --git linux-libre-7.1.5-gnu/drivers/hwmon/ina2xx.c linux-libre-7.1.6-gnu/drivers/hwmon/ina2xx.c
index 613ffb622b7c4..32bf4595bcb48 100644
--- linux-libre-7.1.5-gnu/drivers/hwmon/ina2xx.c
+++ linux-libre-7.1.6-gnu/drivers/hwmon/ina2xx.c
@@ -1000,14 +1000,14 @@ static int ina2xx_probe(struct i2c_client *client)
 }
 
 static const struct i2c_device_id ina2xx_id[] = {
-	{ "ina219", ina219 },
-	{ "ina220", ina219 },
-	{ "ina226", ina226 },
-	{ "ina230", ina226 },
-	{ "ina231", ina226 },
-	{ "ina234", ina234 },
-	{ "ina260", ina260 },
-	{ "sy24655", sy24655 },
+	{ .name = "ina219", .driver_data = ina219 },
+	{ .name = "ina220", .driver_data = ina219 },
+	{ .name = "ina226", .driver_data = ina226 },
+	{ .name = "ina230", .driver_data = ina226 },
+	{ .name = "ina231", .driver_data = ina226 },
+	{ .name = "ina234", .driver_data = ina234 },
+	{ .name = "ina260", .driver_data = ina260 },
+	{ .name = "sy24655", .driver_data = sy24655 },
 	{ }
 };
 MODULE_DEVICE_TABLE(i2c, ina2xx_id);
diff --git linux-libre-7.1.5-gnu/drivers/hwmon/ina3221.c linux-libre-7.1.6-gnu/drivers/hwmon/ina3221.c
index 5ecc68dcf1698..3ab5de3a11102 100644
--- linux-libre-7.1.5-gnu/drivers/hwmon/ina3221.c
+++ linux-libre-7.1.6-gnu/drivers/hwmon/ina3221.c
@@ -1002,7 +1002,7 @@ static const struct of_device_id ina3221_of_match_table[] = {
 MODULE_DEVICE_TABLE(of, ina3221_of_match_table);
 
 static const struct i2c_device_id ina3221_ids[] = {
-	{ "ina3221" },
+	{ .name = "ina3221" },
 	{ /* sentinel */ }
 };
 MODULE_DEVICE_TABLE(i2c, ina3221_ids);
diff --git linux-libre-7.1.5-gnu/drivers/hwmon/isl28022.c linux-libre-7.1.6-gnu/drivers/hwmon/isl28022.c
index 96fcfbfff48f4..0c60d2ef28f5d 100644
--- linux-libre-7.1.5-gnu/drivers/hwmon/isl28022.c
+++ linux-libre-7.1.6-gnu/drivers/hwmon/isl28022.c
@@ -475,7 +475,7 @@ static int isl28022_probe(struct i2c_client *client)
 }
 
 static const struct i2c_device_id isl28022_ids[] = {
-	{ "isl28022" },
+	{ .name = "isl28022" },
 	{ /* LIST END */ }
 };
 MODULE_DEVICE_TABLE(i2c, isl28022_ids);
diff --git linux-libre-7.1.5-gnu/drivers/hwmon/jc42.c linux-libre-7.1.6-gnu/drivers/hwmon/jc42.c
index 6549dc5437812..77fece680358d 100644
--- linux-libre-7.1.5-gnu/drivers/hwmon/jc42.c
+++ linux-libre-7.1.6-gnu/drivers/hwmon/jc42.c
@@ -579,7 +579,7 @@ static const struct dev_pm_ops jc42_dev_pm_ops = {
 #endif /* CONFIG_PM */
 
 static const struct i2c_device_id jc42_id[] = {
-	{ "jc42" },
+	{ .name = "jc42" },
 	{ }
 };
 MODULE_DEVICE_TABLE(i2c, jc42_id);
diff --git linux-libre-7.1.5-gnu/drivers/hwmon/lineage-pem.c linux-libre-7.1.6-gnu/drivers/hwmon/lineage-pem.c
index 64a335a64a2eb..2553e49f84015 100644
--- linux-libre-7.1.5-gnu/drivers/hwmon/lineage-pem.c
+++ linux-libre-7.1.6-gnu/drivers/hwmon/lineage-pem.c
@@ -502,8 +502,8 @@ static int pem_probe(struct i2c_client *client)
 }
 
 static const struct i2c_device_id pem_id[] = {
-	{"lineage_pem"},
-	{}
+	{ .name = "lineage_pem" },
+	{ }
 };
 MODULE_DEVICE_TABLE(i2c, pem_id);
 
diff --git linux-libre-7.1.5-gnu/drivers/hwmon/lm63.c linux-libre-7.1.6-gnu/drivers/hwmon/lm63.c
index 30500b4d22212..a0d77a7386a9d 100644
--- linux-libre-7.1.5-gnu/drivers/hwmon/lm63.c
+++ linux-libre-7.1.6-gnu/drivers/hwmon/lm63.c
@@ -1152,9 +1152,9 @@ static int lm63_probe(struct i2c_client *client)
  */
 
 static const struct i2c_device_id lm63_id[] = {
-	{ "lm63", lm63 },
-	{ "lm64", lm64 },
-	{ "lm96163", lm96163 },
+	{ .name = "lm63", .driver_data = lm63 },
+	{ .name = "lm64", .driver_data = lm64 },
+	{ .name = "lm96163", .driver_data = lm96163 },
 	{ }
 };
 MODULE_DEVICE_TABLE(i2c, lm63_id);
diff --git linux-libre-7.1.5-gnu/drivers/hwmon/lm73.c linux-libre-7.1.6-gnu/drivers/hwmon/lm73.c
index 581b01572e1bd..63ee67481a16c 100644
--- linux-libre-7.1.5-gnu/drivers/hwmon/lm73.c
+++ linux-libre-7.1.6-gnu/drivers/hwmon/lm73.c
@@ -220,7 +220,7 @@ lm73_probe(struct i2c_client *client)
 }
 
 static const struct i2c_device_id lm73_ids[] = {
-	{ "lm73" },
+	{ .name = "lm73" },
 	{ /* LIST END */ }
 };
 MODULE_DEVICE_TABLE(i2c, lm73_ids);
diff --git linux-libre-7.1.5-gnu/drivers/hwmon/lm75.c linux-libre-7.1.6-gnu/drivers/hwmon/lm75.c
index c283443e363b4..05293383f9cc2 100644
--- linux-libre-7.1.5-gnu/drivers/hwmon/lm75.c
+++ linux-libre-7.1.6-gnu/drivers/hwmon/lm75.c
@@ -816,37 +816,37 @@ static int lm75_i2c_probe(struct i2c_client *client)
 }
 
 static const struct i2c_device_id lm75_i2c_ids[] = {
-	{ "adt75", adt75, },
-	{ "as6200", as6200, },
-	{ "at30ts74", at30ts74, },
-	{ "ds1775", ds1775, },
-	{ "ds75", ds75, },
-	{ "ds7505", ds7505, },
-	{ "g751", g751, },
-	{ "lm75", lm75, },
-	{ "lm75a", lm75a, },
-	{ "lm75b", lm75b, },
-	{ "max6625", max6625, },
-	{ "max6626", max6626, },
-	{ "max31725", max31725, },
-	{ "max31726", max31725, },
-	{ "mcp980x", mcp980x, },
-	{ "p3t1750", p3t1750, },
-	{ "p3t1755", p3t1755, },
-	{ "pct2075", pct2075, },
-	{ "stds75", stds75, },
-	{ "stlm75", stlm75, },
-	{ "tcn75", tcn75, },
-	{ "tmp100", tmp100, },
-	{ "tmp101", tmp101, },
-	{ "tmp105", tmp105, },
-	{ "tmp112", tmp112, },
-	{ "tmp175", tmp175, },
-	{ "tmp275", tmp275, },
-	{ "tmp75", tmp75, },
-	{ "tmp75b", tmp75b, },
-	{ "tmp75c", tmp75c, },
-	{ "tmp1075", tmp1075, },
+	{ .name = "adt75", .driver_data = adt75 },
+	{ .name = "as6200", .driver_data = as6200 },
+	{ .name = "at30ts74", .driver_data = at30ts74 },
+	{ .name = "ds1775", .driver_data = ds1775 },
+	{ .name = "ds75", .driver_data = ds75 },
+	{ .name = "ds7505", .driver_data = ds7505 },
+	{ .name = "g751", .driver_data = g751 },
+	{ .name = "lm75", .driver_data = lm75 },
+	{ .name = "lm75a", .driver_data = lm75a },
+	{ .name = "lm75b", .driver_data = lm75b },
+	{ .name = "max6625", .driver_data = max6625 },
+	{ .name = "max6626", .driver_data = max6626 },
+	{ .name = "max31725", .driver_data = max31725 },
+	{ .name = "max31726", .driver_data = max31725 },
+	{ .name = "mcp980x", .driver_data = mcp980x },
+	{ .name = "p3t1750", .driver_data = p3t1750 },
+	{ .name = "p3t1755", .driver_data = p3t1755 },
+	{ .name = "pct2075", .driver_data = pct2075 },
+	{ .name = "stds75", .driver_data = stds75 },
+	{ .name = "stlm75", .driver_data = stlm75 },
+	{ .name = "tcn75", .driver_data = tcn75 },
+	{ .name = "tmp100", .driver_data = tmp100 },
+	{ .name = "tmp101", .driver_data = tmp101 },
+	{ .name = "tmp105", .driver_data = tmp105 },
+	{ .name = "tmp112", .driver_data = tmp112 },
+	{ .name = "tmp175", .driver_data = tmp175 },
+	{ .name = "tmp275", .driver_data = tmp275 },
+	{ .name = "tmp75", .driver_data = tmp75 },
+	{ .name = "tmp75b", .driver_data = tmp75b },
+	{ .name = "tmp75c", .driver_data = tmp75c },
+	{ .name = "tmp1075", .driver_data = tmp1075 },
 	{ /* LIST END */ }
 };
 MODULE_DEVICE_TABLE(i2c, lm75_i2c_ids);
diff --git linux-libre-7.1.5-gnu/drivers/hwmon/lm77.c linux-libre-7.1.6-gnu/drivers/hwmon/lm77.c
index 80f7a6a3f9a29..96c5c2584d37e 100644
--- linux-libre-7.1.5-gnu/drivers/hwmon/lm77.c
+++ linux-libre-7.1.6-gnu/drivers/hwmon/lm77.c
@@ -337,7 +337,7 @@ static int lm77_probe(struct i2c_client *client)
 }
 
 static const struct i2c_device_id lm77_id[] = {
-	{ "lm77" },
+	{ .name = "lm77" },
 	{ }
 };
 MODULE_DEVICE_TABLE(i2c, lm77_id);
diff --git linux-libre-7.1.5-gnu/drivers/hwmon/lm78.c linux-libre-7.1.6-gnu/drivers/hwmon/lm78.c
index 9378a47bf5afa..e4834f9eca6a2 100644
--- linux-libre-7.1.5-gnu/drivers/hwmon/lm78.c
+++ linux-libre-7.1.6-gnu/drivers/hwmon/lm78.c
@@ -649,8 +649,8 @@ static int lm78_i2c_probe(struct i2c_client *client)
 }
 
 static const struct i2c_device_id lm78_i2c_id[] = {
-	{ "lm78", lm78 },
-	{ "lm79", lm79 },
+	{ .name = "lm78", .driver_data = lm78 },
+	{ .name = "lm79", .driver_data = lm79 },
 	{ }
 };
 MODULE_DEVICE_TABLE(i2c, lm78_i2c_id);
diff --git linux-libre-7.1.5-gnu/drivers/hwmon/lm80.c linux-libre-7.1.6-gnu/drivers/hwmon/lm80.c
index 63c7831bd3e11..94f3dabaaa6f6 100644
--- linux-libre-7.1.5-gnu/drivers/hwmon/lm80.c
+++ linux-libre-7.1.6-gnu/drivers/hwmon/lm80.c
@@ -622,8 +622,8 @@ static int lm80_probe(struct i2c_client *client)
  */
 
 static const struct i2c_device_id lm80_id[] = {
-	{ "lm80", 0 },
-	{ "lm96080", 1 },
+	{ .name = "lm80" },
+	{ .name = "lm96080" },
 	{ }
 };
 MODULE_DEVICE_TABLE(i2c, lm80_id);
diff --git linux-libre-7.1.5-gnu/drivers/hwmon/lm83.c linux-libre-7.1.6-gnu/drivers/hwmon/lm83.c
index f800fe2ef18b8..8d49df8c9314f 100644
--- linux-libre-7.1.5-gnu/drivers/hwmon/lm83.c
+++ linux-libre-7.1.6-gnu/drivers/hwmon/lm83.c
@@ -443,8 +443,8 @@ static int lm83_probe(struct i2c_client *client)
  */
 
 static const struct i2c_device_id lm83_id[] = {
-	{ "lm83", lm83 },
-	{ "lm82", lm82 },
+	{ .name = "lm83", .driver_data = lm83 },
+	{ .name = "lm82", .driver_data = lm82 },
 	{ }
 };
 MODULE_DEVICE_TABLE(i2c, lm83_id);
diff --git linux-libre-7.1.5-gnu/drivers/hwmon/lm85.c linux-libre-7.1.6-gnu/drivers/hwmon/lm85.c
index 1c244ed75122e..c56e164d61c18 100644
--- linux-libre-7.1.5-gnu/drivers/hwmon/lm85.c
+++ linux-libre-7.1.6-gnu/drivers/hwmon/lm85.c
@@ -1618,18 +1618,18 @@ static int lm85_probe(struct i2c_client *client)
 }
 
 static const struct i2c_device_id lm85_id[] = {
-	{ "adm1027", adm1027 },
-	{ "adt7463", adt7463 },
-	{ "adt7468", adt7468 },
-	{ "lm85", lm85 },
-	{ "lm85b", lm85 },
-	{ "lm85c", lm85 },
-	{ "lm96000", lm96000 },
-	{ "emc6d100", emc6d100 },
-	{ "emc6d101", emc6d100 },
-	{ "emc6d102", emc6d102 },
-	{ "emc6d103", emc6d103 },
-	{ "emc6d103s", emc6d103s },
+	{ .name = "adm1027", .driver_data = adm1027 },
+	{ .name = "adt7463", .driver_data = adt7463 },
+	{ .name = "adt7468", .driver_data = adt7468 },
+	{ .name = "lm85", .driver_data = lm85 },
+	{ .name = "lm85b", .driver_data = lm85 },
+	{ .name = "lm85c", .driver_data = lm85 },
+	{ .name = "lm96000", .driver_data = lm96000 },
+	{ .name = "emc6d100", .driver_data = emc6d100 },
+	{ .name = "emc6d101", .driver_data = emc6d100 },
+	{ .name = "emc6d102", .driver_data = emc6d102 },
+	{ .name = "emc6d103", .driver_data = emc6d103 },
+	{ .name = "emc6d103s", .driver_data = emc6d103s },
 	{ }
 };
 MODULE_DEVICE_TABLE(i2c, lm85_id);
diff --git linux-libre-7.1.5-gnu/drivers/hwmon/lm87.c linux-libre-7.1.6-gnu/drivers/hwmon/lm87.c
index 37bf2d1d3d099..c09074f447083 100644
--- linux-libre-7.1.5-gnu/drivers/hwmon/lm87.c
+++ linux-libre-7.1.6-gnu/drivers/hwmon/lm87.c
@@ -981,8 +981,8 @@ static int lm87_probe(struct i2c_client *client)
  */
 
 static const struct i2c_device_id lm87_id[] = {
-	{ "lm87" },
-	{ "adm1024" },
+	{ .name = "lm87" },
+	{ .name = "adm1024" },
 	{ }
 };
 MODULE_DEVICE_TABLE(i2c, lm87_id);
diff --git linux-libre-7.1.5-gnu/drivers/hwmon/lm90.c linux-libre-7.1.6-gnu/drivers/hwmon/lm90.c
index 1eeb608e59039..c78c96e1bd83f 100644
--- linux-libre-7.1.5-gnu/drivers/hwmon/lm90.c
+++ linux-libre-7.1.6-gnu/drivers/hwmon/lm90.c
@@ -243,54 +243,54 @@ enum chips { adm1023, adm1032, adt7461, adt7461a, adt7481,
  */
 
 static const struct i2c_device_id lm90_id[] = {
-	{ "adm1020", max1617 },
-	{ "adm1021", max1617 },
-	{ "adm1023", adm1023 },
-	{ "adm1032", adm1032 },
-	{ "adt7421", adt7461a },
-	{ "adt7461", adt7461 },
-	{ "adt7461a", adt7461a },
-	{ "adt7481", adt7481 },
-	{ "adt7482", adt7481 },
-	{ "adt7483a", adt7481 },
-	{ "g781", g781 },
-	{ "gl523sm", max1617 },
-	{ "lm84", lm84 },
-	{ "lm86", lm90 },
-	{ "lm89", lm90 },
-	{ "lm90", lm90 },
-	{ "lm99", lm99 },
-	{ "max1617", max1617 },
-	{ "max6642", max6642 },
-	{ "max6646", max6646 },
-	{ "max6647", max6646 },
-	{ "max6648", max6648 },
-	{ "max6649", max6646 },
-	{ "max6654", max6654 },
-	{ "max6657", max6657 },
-	{ "max6658", max6657 },
-	{ "max6659", max6659 },
-	{ "max6680", max6680 },
-	{ "max6681", max6680 },
-	{ "max6690", max6654 },
-	{ "max6692", max6648 },
-	{ "max6695", max6696 },
-	{ "max6696", max6696 },
-	{ "mc1066", max1617 },
-	{ "nct1008", adt7461a },
-	{ "nct210", nct210 },
-	{ "nct214", nct72 },
-	{ "nct218", nct72 },
-	{ "nct72", nct72 },
-	{ "nct7716", nct7716 },
-	{ "nct7717", nct7717 },
-	{ "nct7718", nct7718 },
-	{ "ne1618", ne1618 },
-	{ "w83l771", w83l771 },
-	{ "sa56004", sa56004 },
-	{ "thmc10", max1617 },
-	{ "tmp451", tmp451 },
-	{ "tmp461", tmp461 },
+	{ .name = "adm1020", .driver_data = max1617 },
+	{ .name = "adm1021", .driver_data = max1617 },
+	{ .name = "adm1023", .driver_data = adm1023 },
+	{ .name = "adm1032", .driver_data = adm1032 },
+	{ .name = "adt7421", .driver_data = adt7461a },
+	{ .name = "adt7461", .driver_data = adt7461 },
+	{ .name = "adt7461a", .driver_data = adt7461a },
+	{ .name = "adt7481", .driver_data = adt7481 },
+	{ .name = "adt7482", .driver_data = adt7481 },
+	{ .name = "adt7483a", .driver_data = adt7481 },
+	{ .name = "g781", .driver_data = g781 },
+	{ .name = "gl523sm", .driver_data = max1617 },
+	{ .name = "lm84", .driver_data = lm84 },
+	{ .name = "lm86", .driver_data = lm90 },
+	{ .name = "lm89", .driver_data = lm90 },
+	{ .name = "lm90", .driver_data = lm90 },
+	{ .name = "lm99", .driver_data = lm99 },
+	{ .name = "max1617", .driver_data = max1617 },
+	{ .name = "max6642", .driver_data = max6642 },
+	{ .name = "max6646", .driver_data = max6646 },
+	{ .name = "max6647", .driver_data = max6646 },
+	{ .name = "max6648", .driver_data = max6648 },
+	{ .name = "max6649", .driver_data = max6646 },
+	{ .name = "max6654", .driver_data = max6654 },
+	{ .name = "max6657", .driver_data = max6657 },
+	{ .name = "max6658", .driver_data = max6657 },
+	{ .name = "max6659", .driver_data = max6659 },
+	{ .name = "max6680", .driver_data = max6680 },
+	{ .name = "max6681", .driver_data = max6680 },
+	{ .name = "max6690", .driver_data = max6654 },
+	{ .name = "max6692", .driver_data = max6648 },
+	{ .name = "max6695", .driver_data = max6696 },
+	{ .name = "max6696", .driver_data = max6696 },
+	{ .name = "mc1066", .driver_data = max1617 },
+	{ .name = "nct1008", .driver_data = adt7461a },
+	{ .name = "nct210", .driver_data = nct210 },
+	{ .name = "nct214", .driver_data = nct72 },
+	{ .name = "nct218", .driver_data = nct72 },
+	{ .name = "nct72", .driver_data = nct72 },
+	{ .name = "nct7716", .driver_data = nct7716 },
+	{ .name = "nct7717", .driver_data = nct7717 },
+	{ .name = "nct7718", .driver_data = nct7718 },
+	{ .name = "ne1618", .driver_data = ne1618 },
+	{ .name = "w83l771", .driver_data = w83l771 },
+	{ .name = "sa56004", .driver_data = sa56004 },
+	{ .name = "thmc10", .driver_data = max1617 },
+	{ .name = "tmp451", .driver_data = tmp451 },
+	{ .name = "tmp461", .driver_data = tmp461 },
 	{ }
 };
 MODULE_DEVICE_TABLE(i2c, lm90_id);
diff --git linux-libre-7.1.5-gnu/drivers/hwmon/lm92.c linux-libre-7.1.6-gnu/drivers/hwmon/lm92.c
index 91a6b7525bb67..4aadbabc27bb9 100644
--- linux-libre-7.1.5-gnu/drivers/hwmon/lm92.c
+++ linux-libre-7.1.6-gnu/drivers/hwmon/lm92.c
@@ -405,10 +405,10 @@ static int lm92_probe(struct i2c_client *client)
  * Module and driver stuff
  */
 
-/* .driver_data is limit register resolution */ 
+/* .driver_data is limit register resolution */
 static const struct i2c_device_id lm92_id[] = {
-	{ "lm92", 13 },
-	{ "max6635", 9 },
+	{ .name = "lm92", .driver_data = 13 },
+	{ .name = "max6635", .driver_data = 9 },
 	{ }
 };
 MODULE_DEVICE_TABLE(i2c, lm92_id);
diff --git linux-libre-7.1.5-gnu/drivers/hwmon/lm93.c linux-libre-7.1.6-gnu/drivers/hwmon/lm93.c
index be4853fad80fd..d58a3c2a85930 100644
--- linux-libre-7.1.5-gnu/drivers/hwmon/lm93.c
+++ linux-libre-7.1.6-gnu/drivers/hwmon/lm93.c
@@ -2624,8 +2624,8 @@ static int lm93_probe(struct i2c_client *client)
 }
 
 static const struct i2c_device_id lm93_id[] = {
-	{ "lm93" },
-	{ "lm94" },
+	{ .name = "lm93" },
+	{ .name = "lm94" },
 	{ }
 };
 MODULE_DEVICE_TABLE(i2c, lm93_id);
diff --git linux-libre-7.1.5-gnu/drivers/hwmon/lm95234.c linux-libre-7.1.6-gnu/drivers/hwmon/lm95234.c
index 387b3ba81dbfc..74f280b90e3e9 100644
--- linux-libre-7.1.5-gnu/drivers/hwmon/lm95234.c
+++ linux-libre-7.1.6-gnu/drivers/hwmon/lm95234.c
@@ -532,8 +532,8 @@ static int lm95234_probe(struct i2c_client *client)
 
 /* Driver data (common to all clients) */
 static const struct i2c_device_id lm95234_id[] = {
-	{ "lm95233", lm95233 },
-	{ "lm95234", lm95234 },
+	{ .name = "lm95233", .driver_data = lm95233 },
+	{ .name = "lm95234", .driver_data = lm95234 },
 	{ }
 };
 MODULE_DEVICE_TABLE(i2c, lm95234_id);
diff --git linux-libre-7.1.5-gnu/drivers/hwmon/lm95241.c linux-libre-7.1.6-gnu/drivers/hwmon/lm95241.c
index 456381b0938e7..0cb0edb3845db 100644
--- linux-libre-7.1.5-gnu/drivers/hwmon/lm95241.c
+++ linux-libre-7.1.6-gnu/drivers/hwmon/lm95241.c
@@ -441,8 +441,8 @@ static int lm95241_probe(struct i2c_client *client)
 
 /* Driver data (common to all clients) */
 static const struct i2c_device_id lm95241_id[] = {
-	{ "lm95231" },
-	{ "lm95241" },
+	{ .name = "lm95231" },
+	{ .name = "lm95241" },
 	{ }
 };
 MODULE_DEVICE_TABLE(i2c, lm95241_id);
diff --git linux-libre-7.1.5-gnu/drivers/hwmon/lm95245.c linux-libre-7.1.6-gnu/drivers/hwmon/lm95245.c
index 9ed300c6b5f70..11553391f54b1 100644
--- linux-libre-7.1.5-gnu/drivers/hwmon/lm95245.c
+++ linux-libre-7.1.6-gnu/drivers/hwmon/lm95245.c
@@ -546,8 +546,8 @@ static int lm95245_probe(struct i2c_client *client)
 
 /* Driver data (common to all clients) */
 static const struct i2c_device_id lm95245_id[] = {
-	{ "lm95235" },
-	{ "lm95245" },
+	{ .name = "lm95235" },
+	{ .name = "lm95245" },
 	{ }
 };
 MODULE_DEVICE_TABLE(i2c, lm95245_id);
diff --git linux-libre-7.1.5-gnu/drivers/hwmon/ltc2945.c linux-libre-7.1.6-gnu/drivers/hwmon/ltc2945.c
index 3e0e0e0687bdd..b521100afe53a 100644
--- linux-libre-7.1.5-gnu/drivers/hwmon/ltc2945.c
+++ linux-libre-7.1.6-gnu/drivers/hwmon/ltc2945.c
@@ -508,7 +508,7 @@ static int ltc2945_probe(struct i2c_client *client)
 }
 
 static const struct i2c_device_id ltc2945_id[] = {
-	{"ltc2945"},
+	{ .name = "ltc2945" },
 	{ }
 };
 
diff --git linux-libre-7.1.5-gnu/drivers/hwmon/ltc2947-i2c.c linux-libre-7.1.6-gnu/drivers/hwmon/ltc2947-i2c.c
index 176d710706dd9..e07d33983d5ce 100644
--- linux-libre-7.1.5-gnu/drivers/hwmon/ltc2947-i2c.c
+++ linux-libre-7.1.6-gnu/drivers/hwmon/ltc2947-i2c.c
@@ -27,8 +27,8 @@ static int ltc2947_probe(struct i2c_client *i2c)
 }
 
 static const struct i2c_device_id ltc2947_id[] = {
-	{"ltc2947"},
-	{}
+	{ .name = "ltc2947" },
+	{ }
 };
 MODULE_DEVICE_TABLE(i2c, ltc2947_id);
 
diff --git linux-libre-7.1.5-gnu/drivers/hwmon/ltc2990.c linux-libre-7.1.6-gnu/drivers/hwmon/ltc2990.c
index f1c1933c52cf4..a2725e4b2f213 100644
--- linux-libre-7.1.5-gnu/drivers/hwmon/ltc2990.c
+++ linux-libre-7.1.6-gnu/drivers/hwmon/ltc2990.c
@@ -259,8 +259,8 @@ static int ltc2990_i2c_probe(struct i2c_client *i2c)
 }
 
 static const struct i2c_device_id ltc2990_i2c_id[] = {
-	{ "ltc2990" },
-	{}
+	{ .name = "ltc2990" },
+	{ }
 };
 MODULE_DEVICE_TABLE(i2c, ltc2990_i2c_id);
 
diff --git linux-libre-7.1.5-gnu/drivers/hwmon/ltc2991.c linux-libre-7.1.6-gnu/drivers/hwmon/ltc2991.c
index 6d5d4cb846daf..bc8d803e8cc90 100644
--- linux-libre-7.1.5-gnu/drivers/hwmon/ltc2991.c
+++ linux-libre-7.1.6-gnu/drivers/hwmon/ltc2991.c
@@ -409,8 +409,8 @@ static const struct of_device_id ltc2991_of_match[] = {
 MODULE_DEVICE_TABLE(of, ltc2991_of_match);
 
 static const struct i2c_device_id ltc2991_i2c_id[] = {
-	{ "ltc2991" },
-	{}
+	{ .name = "ltc2991" },
+	{ }
 };
 MODULE_DEVICE_TABLE(i2c, ltc2991_i2c_id);
 
diff --git linux-libre-7.1.5-gnu/drivers/hwmon/ltc2992.c linux-libre-7.1.6-gnu/drivers/hwmon/ltc2992.c
index 2617c4538af91..43b6029c08404 100644
--- linux-libre-7.1.5-gnu/drivers/hwmon/ltc2992.c
+++ linux-libre-7.1.6-gnu/drivers/hwmon/ltc2992.c
@@ -948,8 +948,8 @@ static const struct of_device_id ltc2992_of_match[] = {
 MODULE_DEVICE_TABLE(of, ltc2992_of_match);
 
 static const struct i2c_device_id ltc2992_i2c_id[] = {
-	{"ltc2992"},
-	{}
+	{ .name = "ltc2992" },
+	{ }
 };
 MODULE_DEVICE_TABLE(i2c, ltc2992_i2c_id);
 
diff --git linux-libre-7.1.5-gnu/drivers/hwmon/ltc4151.c linux-libre-7.1.6-gnu/drivers/hwmon/ltc4151.c
index fa66eda78efe4..fa7c57aae5f5f 100644
--- linux-libre-7.1.5-gnu/drivers/hwmon/ltc4151.c
+++ linux-libre-7.1.6-gnu/drivers/hwmon/ltc4151.c
@@ -188,7 +188,7 @@ static int ltc4151_probe(struct i2c_client *client)
 }
 
 static const struct i2c_device_id ltc4151_id[] = {
-	{ "ltc4151" },
+	{ .name = "ltc4151" },
 	{ }
 };
 MODULE_DEVICE_TABLE(i2c, ltc4151_id);
diff --git linux-libre-7.1.5-gnu/drivers/hwmon/ltc4215.c linux-libre-7.1.6-gnu/drivers/hwmon/ltc4215.c
index cce452711cec4..3d439fbbbef93 100644
--- linux-libre-7.1.5-gnu/drivers/hwmon/ltc4215.c
+++ linux-libre-7.1.6-gnu/drivers/hwmon/ltc4215.c
@@ -245,7 +245,7 @@ static int ltc4215_probe(struct i2c_client *client)
 }
 
 static const struct i2c_device_id ltc4215_id[] = {
-	{ "ltc4215" },
+	{ .name = "ltc4215" },
 	{ }
 };
 MODULE_DEVICE_TABLE(i2c, ltc4215_id);
diff --git linux-libre-7.1.5-gnu/drivers/hwmon/ltc4222.c linux-libre-7.1.6-gnu/drivers/hwmon/ltc4222.c
index f7eb007fd766b..4fc69be5f2bc9 100644
--- linux-libre-7.1.5-gnu/drivers/hwmon/ltc4222.c
+++ linux-libre-7.1.6-gnu/drivers/hwmon/ltc4222.c
@@ -200,7 +200,7 @@ static int ltc4222_probe(struct i2c_client *client)
 }
 
 static const struct i2c_device_id ltc4222_id[] = {
-	{"ltc4222"},
+	{ .name = "ltc4222" },
 	{ }
 };
 
diff --git linux-libre-7.1.5-gnu/drivers/hwmon/ltc4245.c linux-libre-7.1.6-gnu/drivers/hwmon/ltc4245.c
index e8131a48bda7f..d87aa9c32c873 100644
--- linux-libre-7.1.5-gnu/drivers/hwmon/ltc4245.c
+++ linux-libre-7.1.6-gnu/drivers/hwmon/ltc4245.c
@@ -461,7 +461,7 @@ static int ltc4245_probe(struct i2c_client *client)
 }
 
 static const struct i2c_device_id ltc4245_id[] = {
-	{ "ltc4245" },
+	{ .name = "ltc4245" },
 	{ }
 };
 MODULE_DEVICE_TABLE(i2c, ltc4245_id);
diff --git linux-libre-7.1.5-gnu/drivers/hwmon/ltc4260.c linux-libre-7.1.6-gnu/drivers/hwmon/ltc4260.c
index 9750dc9aa336d..37a85125d619c 100644
--- linux-libre-7.1.5-gnu/drivers/hwmon/ltc4260.c
+++ linux-libre-7.1.6-gnu/drivers/hwmon/ltc4260.c
@@ -163,7 +163,7 @@ static int ltc4260_probe(struct i2c_client *client)
 }
 
 static const struct i2c_device_id ltc4260_id[] = {
-	{"ltc4260"},
+	{ .name = "ltc4260" },
 	{ }
 };
 
diff --git linux-libre-7.1.5-gnu/drivers/hwmon/ltc4261.c linux-libre-7.1.6-gnu/drivers/hwmon/ltc4261.c
index 2cd218a6a3be7..a2e52ca0b06e1 100644
--- linux-libre-7.1.5-gnu/drivers/hwmon/ltc4261.c
+++ linux-libre-7.1.6-gnu/drivers/hwmon/ltc4261.c
@@ -222,8 +222,8 @@ static int ltc4261_probe(struct i2c_client *client)
 }
 
 static const struct i2c_device_id ltc4261_id[] = {
-	{"ltc4261"},
-	{}
+	{ .name = "ltc4261" },
+	{ }
 };
 
 MODULE_DEVICE_TABLE(i2c, ltc4261_id);
diff --git linux-libre-7.1.5-gnu/drivers/hwmon/max127.c linux-libre-7.1.6-gnu/drivers/hwmon/max127.c
index 5102d86d2619a..b294e86d52d16 100644
--- linux-libre-7.1.5-gnu/drivers/hwmon/max127.c
+++ linux-libre-7.1.6-gnu/drivers/hwmon/max127.c
@@ -312,7 +312,7 @@ static int max127_probe(struct i2c_client *client)
 }
 
 static const struct i2c_device_id max127_id[] = {
-	{ "max127" },
+	{ .name = "max127" },
 	{ }
 };
 MODULE_DEVICE_TABLE(i2c, max127_id);
diff --git linux-libre-7.1.5-gnu/drivers/hwmon/max16065.c linux-libre-7.1.6-gnu/drivers/hwmon/max16065.c
index 43fbb9b26b102..f8b4217542203 100644
--- linux-libre-7.1.5-gnu/drivers/hwmon/max16065.c
+++ linux-libre-7.1.6-gnu/drivers/hwmon/max16065.c
@@ -592,12 +592,12 @@ static int max16065_probe(struct i2c_client *client)
 }
 
 static const struct i2c_device_id max16065_id[] = {
-	{ "max16065", max16065 },
-	{ "max16066", max16066 },
-	{ "max16067", max16067 },
-	{ "max16068", max16068 },
-	{ "max16070", max16070 },
-	{ "max16071", max16071 },
+	{ .name = "max16065", .driver_data = max16065 },
+	{ .name = "max16066", .driver_data = max16066 },
+	{ .name = "max16067", .driver_data = max16067 },
+	{ .name = "max16068", .driver_data = max16068 },
+	{ .name = "max16070", .driver_data = max16070 },
+	{ .name = "max16071", .driver_data = max16071 },
 	{ }
 };
 
diff --git linux-libre-7.1.5-gnu/drivers/hwmon/max1619.c linux-libre-7.1.6-gnu/drivers/hwmon/max1619.c
index 9b6d03cff4df5..77ef39e8ae7e3 100644
--- linux-libre-7.1.5-gnu/drivers/hwmon/max1619.c
+++ linux-libre-7.1.6-gnu/drivers/hwmon/max1619.c
@@ -366,7 +366,7 @@ static int max1619_probe(struct i2c_client *client)
 }
 
 static const struct i2c_device_id max1619_id[] = {
-	{ "max1619" },
+	{ .name = "max1619" },
 	{ }
 };
 MODULE_DEVICE_TABLE(i2c, max1619_id);
diff --git linux-libre-7.1.5-gnu/drivers/hwmon/max1668.c linux-libre-7.1.6-gnu/drivers/hwmon/max1668.c
index a8197a86f5590..32548f56409ce 100644
--- linux-libre-7.1.5-gnu/drivers/hwmon/max1668.c
+++ linux-libre-7.1.6-gnu/drivers/hwmon/max1668.c
@@ -293,9 +293,9 @@ static int max1668_probe(struct i2c_client *client)
 }
 
 static const struct i2c_device_id max1668_id[] = {
-	{ "max1668", 5 },
-	{ "max1805", 3 },
-	{ "max1989", 5 },
+	{ .name = "max1668", .driver_data = 5 },
+	{ .name = "max1805", .driver_data = 3 },
+	{ .name = "max1989", .driver_data = 5 },
 	{ }
 };
 MODULE_DEVICE_TABLE(i2c, max1668_id);
diff --git linux-libre-7.1.5-gnu/drivers/hwmon/max31730.c linux-libre-7.1.6-gnu/drivers/hwmon/max31730.c
index 2f4b419b6c9e3..d132be2d6487d 100644
--- linux-libre-7.1.5-gnu/drivers/hwmon/max31730.c
+++ linux-libre-7.1.6-gnu/drivers/hwmon/max31730.c
@@ -345,7 +345,7 @@ max31730_probe(struct i2c_client *client)
 }
 
 static const struct i2c_device_id max31730_ids[] = {
-	{ "max31730" },
+	{ .name = "max31730" },
 	{ }
 };
 MODULE_DEVICE_TABLE(i2c, max31730_ids);
diff --git linux-libre-7.1.5-gnu/drivers/hwmon/max31760.c linux-libre-7.1.6-gnu/drivers/hwmon/max31760.c
index 127e31ca3c873..8d3be064b0251 100644
--- linux-libre-7.1.5-gnu/drivers/hwmon/max31760.c
+++ linux-libre-7.1.6-gnu/drivers/hwmon/max31760.c
@@ -555,7 +555,7 @@ static const struct of_device_id max31760_of_match[] = {
 MODULE_DEVICE_TABLE(of, max31760_of_match);
 
 static const struct i2c_device_id max31760_id[] = {
-	{"max31760"},
+	{ .name = "max31760" },
 	{ }
 };
 MODULE_DEVICE_TABLE(i2c, max31760_id);
diff --git linux-libre-7.1.5-gnu/drivers/hwmon/max31790.c linux-libre-7.1.6-gnu/drivers/hwmon/max31790.c
index 4f6171a17d9f1..db8a0f6f18294 100644
--- linux-libre-7.1.5-gnu/drivers/hwmon/max31790.c
+++ linux-libre-7.1.6-gnu/drivers/hwmon/max31790.c
@@ -517,7 +517,7 @@ static int max31790_probe(struct i2c_client *client)
 }
 
 static const struct i2c_device_id max31790_id[] = {
-	{ "max31790" },
+	{ .name = "max31790" },
 	{ }
 };
 MODULE_DEVICE_TABLE(i2c, max31790_id);
diff --git linux-libre-7.1.5-gnu/drivers/hwmon/max31827.c linux-libre-7.1.6-gnu/drivers/hwmon/max31827.c
index 9b2e56c040df1..6a7048fdd8ab7 100644
--- linux-libre-7.1.5-gnu/drivers/hwmon/max31827.c
+++ linux-libre-7.1.6-gnu/drivers/hwmon/max31827.c
@@ -463,9 +463,9 @@ static struct attribute *max31827_attrs[] = {
 ATTRIBUTE_GROUPS(max31827);
 
 static const struct i2c_device_id max31827_i2c_ids[] = {
-	{ "max31827", max31827 },
-	{ "max31828", max31828 },
-	{ "max31829", max31829 },
+	{ .name = "max31827", .driver_data = max31827 },
+	{ .name = "max31828", .driver_data = max31828 },
+	{ .name = "max31829", .driver_data = max31829 },
 	{ }
 };
 MODULE_DEVICE_TABLE(i2c, max31827_i2c_ids);
diff --git linux-libre-7.1.5-gnu/drivers/hwmon/max6620.c linux-libre-7.1.6-gnu/drivers/hwmon/max6620.c
index 4316dcdd03fc2..100acf357b5f5 100644
--- linux-libre-7.1.5-gnu/drivers/hwmon/max6620.c
+++ linux-libre-7.1.6-gnu/drivers/hwmon/max6620.c
@@ -474,7 +474,7 @@ static int max6620_probe(struct i2c_client *client)
 }
 
 static const struct i2c_device_id max6620_id[] = {
-	{ "max6620" },
+	{ .name = "max6620" },
 	{ }
 };
 MODULE_DEVICE_TABLE(i2c, max6620_id);
diff --git linux-libre-7.1.5-gnu/drivers/hwmon/max6621.c linux-libre-7.1.6-gnu/drivers/hwmon/max6621.c
index a7066f3a0bb4e..e86ec6d237ca6 100644
--- linux-libre-7.1.5-gnu/drivers/hwmon/max6621.c
+++ linux-libre-7.1.6-gnu/drivers/hwmon/max6621.c
@@ -537,7 +537,7 @@ static int max6621_probe(struct i2c_client *client)
 }
 
 static const struct i2c_device_id max6621_id[] = {
-	{ MAX6621_DRV_NAME },
+	{ .name = MAX6621_DRV_NAME },
 	{ }
 };
 MODULE_DEVICE_TABLE(i2c, max6621_id);
diff --git linux-libre-7.1.5-gnu/drivers/hwmon/max6639.c linux-libre-7.1.6-gnu/drivers/hwmon/max6639.c
index 163d31f17bd49..dd5f4b3b128da 100644
--- linux-libre-7.1.5-gnu/drivers/hwmon/max6639.c
+++ linux-libre-7.1.6-gnu/drivers/hwmon/max6639.c
@@ -778,7 +778,7 @@ static int max6639_resume(struct device *dev)
 }
 
 static const struct i2c_device_id max6639_id[] = {
-	{"max6639"},
+	{ .name = "max6639" },
 	{ }
 };
 
diff --git linux-libre-7.1.5-gnu/drivers/hwmon/max6650.c linux-libre-7.1.6-gnu/drivers/hwmon/max6650.c
index 56b8157885bbf..f0140ef9c40ee 100644
--- linux-libre-7.1.5-gnu/drivers/hwmon/max6650.c
+++ linux-libre-7.1.6-gnu/drivers/hwmon/max6650.c
@@ -807,8 +807,8 @@ static int max6650_probe(struct i2c_client *client)
 }
 
 static const struct i2c_device_id max6650_id[] = {
-	{ "max6650", 1 },
-	{ "max6651", 4 },
+	{ .name = "max6650", .driver_data = 1 },
+	{ .name = "max6651", .driver_data = 4 },
 	{ }
 };
 MODULE_DEVICE_TABLE(i2c, max6650_id);
diff --git linux-libre-7.1.5-gnu/drivers/hwmon/max6697.c linux-libre-7.1.6-gnu/drivers/hwmon/max6697.c
index dd906cf491cae..c864093f015c0 100644
--- linux-libre-7.1.5-gnu/drivers/hwmon/max6697.c
+++ linux-libre-7.1.6-gnu/drivers/hwmon/max6697.c
@@ -564,16 +564,16 @@ static int max6697_probe(struct i2c_client *client)
 }
 
 static const struct i2c_device_id max6697_id[] = {
-	{ "max6581", max6581 },
-	{ "max6602", max6602 },
-	{ "max6622", max6622 },
-	{ "max6636", max6636 },
-	{ "max6689", max6689 },
-	{ "max6693", max6693 },
-	{ "max6694", max6694 },
-	{ "max6697", max6697 },
-	{ "max6698", max6698 },
-	{ "max6699", max6699 },
+	{ .name = "max6581", .driver_data = max6581 },
+	{ .name = "max6602", .driver_data = max6602 },
+	{ .name = "max6622", .driver_data = max6622 },
+	{ .name = "max6636", .driver_data = max6636 },
+	{ .name = "max6689", .driver_data = max6689 },
+	{ .name = "max6693", .driver_data = max6693 },
+	{ .name = "max6694", .driver_data = max6694 },
+	{ .name = "max6697", .driver_data = max6697 },
+	{ .name = "max6698", .driver_data = max6698 },
+	{ .name = "max6699", .driver_data = max6699 },
 	{ }
 };
 MODULE_DEVICE_TABLE(i2c, max6697_id);
diff --git linux-libre-7.1.5-gnu/drivers/hwmon/mc34vr500.c linux-libre-7.1.6-gnu/drivers/hwmon/mc34vr500.c
index 84458e4533d86..8cb9d5c09033f 100644
--- linux-libre-7.1.5-gnu/drivers/hwmon/mc34vr500.c
+++ linux-libre-7.1.6-gnu/drivers/hwmon/mc34vr500.c
@@ -235,8 +235,8 @@ static int mc34vr500_probe(struct i2c_client *client)
 }
 
 static const struct i2c_device_id mc34vr500_id[] = {
-	{ "mc34vr500" },
-	{ },
+	{ .name = "mc34vr500" },
+	{ }
 };
 MODULE_DEVICE_TABLE(i2c, mc34vr500_id);
 
diff --git linux-libre-7.1.5-gnu/drivers/hwmon/mcp3021.c linux-libre-7.1.6-gnu/drivers/hwmon/mcp3021.c
index bcddf6804d3ab..d6b0ebf27941f 100644
--- linux-libre-7.1.5-gnu/drivers/hwmon/mcp3021.c
+++ linux-libre-7.1.6-gnu/drivers/hwmon/mcp3021.c
@@ -177,8 +177,8 @@ static int mcp3021_probe(struct i2c_client *client)
 }
 
 static const struct i2c_device_id mcp3021_id[] = {
-	{ "mcp3021", mcp3021 },
-	{ "mcp3221", mcp3221 },
+	{ .name = "mcp3021", .driver_data = mcp3021 },
+	{ .name = "mcp3221", .driver_data = mcp3221 },
 	{ }
 };
 MODULE_DEVICE_TABLE(i2c, mcp3021_id);
diff --git linux-libre-7.1.5-gnu/drivers/hwmon/nct6775-i2c.c linux-libre-7.1.6-gnu/drivers/hwmon/nct6775-i2c.c
index ba71d776a2911..07783910c0588 100644
--- linux-libre-7.1.5-gnu/drivers/hwmon/nct6775-i2c.c
+++ linux-libre-7.1.6-gnu/drivers/hwmon/nct6775-i2c.c
@@ -93,19 +93,19 @@ static const struct of_device_id __maybe_unused nct6775_i2c_of_match[] = {
 MODULE_DEVICE_TABLE(of, nct6775_i2c_of_match);
 
 static const struct i2c_device_id nct6775_i2c_id[] = {
-	{ "nct6106", nct6106 },
-	{ "nct6116", nct6116 },
-	{ "nct6775", nct6775 },
-	{ "nct6776", nct6776 },
-	{ "nct6779", nct6779 },
-	{ "nct6791", nct6791 },
-	{ "nct6792", nct6792 },
-	{ "nct6793", nct6793 },
-	{ "nct6795", nct6795 },
-	{ "nct6796", nct6796 },
-	{ "nct6797", nct6797 },
-	{ "nct6798", nct6798 },
-	{ "nct6799", nct6799 },
+	{ .name = "nct6106", .driver_data = nct6106 },
+	{ .name = "nct6116", .driver_data = nct6116 },
+	{ .name = "nct6775", .driver_data = nct6775 },
+	{ .name = "nct6776", .driver_data = nct6776 },
+	{ .name = "nct6779", .driver_data = nct6779 },
+	{ .name = "nct6791", .driver_data = nct6791 },
+	{ .name = "nct6792", .driver_data = nct6792 },
+	{ .name = "nct6793", .driver_data = nct6793 },
+	{ .name = "nct6795", .driver_data = nct6795 },
+	{ .name = "nct6796", .driver_data = nct6796 },
+	{ .name = "nct6797", .driver_data = nct6797 },
+	{ .name = "nct6798", .driver_data = nct6798 },
+	{ .name = "nct6799", .driver_data = nct6799 },
 	{ }
 };
 MODULE_DEVICE_TABLE(i2c, nct6775_i2c_id);
diff --git linux-libre-7.1.5-gnu/drivers/hwmon/nct7802.c linux-libre-7.1.6-gnu/drivers/hwmon/nct7802.c
index 8c9351da12c6e..9c3e169547a9a 100644
--- linux-libre-7.1.5-gnu/drivers/hwmon/nct7802.c
+++ linux-libre-7.1.6-gnu/drivers/hwmon/nct7802.c
@@ -1193,7 +1193,7 @@ static const unsigned short nct7802_address_list[] = {
 };
 
 static const struct i2c_device_id nct7802_idtable[] = {
-	{ "nct7802" },
+	{ .name = "nct7802" },
 	{ }
 };
 MODULE_DEVICE_TABLE(i2c, nct7802_idtable);
diff --git linux-libre-7.1.5-gnu/drivers/hwmon/nct7904.c linux-libre-7.1.6-gnu/drivers/hwmon/nct7904.c
index 2fa091720c79b..976b8a008e448 100644
--- linux-libre-7.1.5-gnu/drivers/hwmon/nct7904.c
+++ linux-libre-7.1.6-gnu/drivers/hwmon/nct7904.c
@@ -1146,8 +1146,8 @@ static int nct7904_probe(struct i2c_client *client)
 }
 
 static const struct i2c_device_id nct7904_id[] = {
-	{"nct7904"},
-	{}
+	{ .name = "nct7904" },
+	{ }
 };
 MODULE_DEVICE_TABLE(i2c, nct7904_id);
 
diff --git linux-libre-7.1.5-gnu/drivers/hwmon/nzxt-kraken3.c linux-libre-7.1.6-gnu/drivers/hwmon/nzxt-kraken3.c
index d00409bcab93a..05525406c5fbb 100644
--- linux-libre-7.1.5-gnu/drivers/hwmon/nzxt-kraken3.c
+++ linux-libre-7.1.6-gnu/drivers/hwmon/nzxt-kraken3.c
@@ -948,7 +948,7 @@ static int kraken3_probe(struct hid_device *hdev, const struct hid_device_id *id
 	ret = kraken3_init_device(hdev);
 	if (ret < 0) {
 		hid_err(hdev, "device init failed with %d\n", ret);
-		goto fail_and_close;
+		goto fail_and_stop_io;
 	}
 
 	ret = kraken3_get_fw_ver(hdev);
@@ -960,13 +960,15 @@ static int kraken3_probe(struct hid_device *hdev, const struct hid_device_id *id
 	if (IS_ERR(priv->hwmon_dev)) {
 		ret = PTR_ERR(priv->hwmon_dev);
 		hid_err(hdev, "hwmon registration failed with %d\n", ret);
-		goto fail_and_close;
+		goto fail_and_stop_io;
 	}
 
 	kraken3_debugfs_init(priv, device_name);
 
 	return 0;
 
+fail_and_stop_io:
+	hid_device_io_stop(hdev);
 fail_and_close:
 	hid_hw_close(hdev);
 fail_and_stop:
diff --git linux-libre-7.1.5-gnu/drivers/hwmon/nzxt-smart2.c linux-libre-7.1.6-gnu/drivers/hwmon/nzxt-smart2.c
index 58ef9fa0184be..e2316c46629d6 100644
--- linux-libre-7.1.5-gnu/drivers/hwmon/nzxt-smart2.c
+++ linux-libre-7.1.6-gnu/drivers/hwmon/nzxt-smart2.c
@@ -768,7 +768,7 @@ static int nzxt_smart2_hid_probe(struct hid_device *hdev,
 
 out_hw_close:
 	hid_hw_close(hdev);
-
+	hid_device_io_stop(hdev);
 out_hw_stop:
 	hid_hw_stop(hdev);
 	return ret;
diff --git linux-libre-7.1.5-gnu/drivers/hwmon/occ/common.c linux-libre-7.1.6-gnu/drivers/hwmon/occ/common.c
index e18e80e832fd3..175208d712b06 100644
--- linux-libre-7.1.5-gnu/drivers/hwmon/occ/common.c
+++ linux-libre-7.1.6-gnu/drivers/hwmon/occ/common.c
@@ -1052,32 +1052,49 @@ static int occ_setup_sensor_attrs(struct occ *occ)
 }
 
 /* only need to do this once at startup, as OCC won't change sensors on us */
-static void occ_parse_poll_response(struct occ *occ)
+static int occ_parse_poll_response(struct occ *occ)
 {
 	unsigned int i, old_offset, offset = 0, size = 0;
+	u16 data_length;
 	struct occ_sensor *sensor;
-	struct occ_sensors *sensors = &occ->sensors;
+	struct occ_sensors parsed = {};
+	struct occ_sensors *sensors = &parsed;
 	struct occ_response *resp = &occ->resp;
 	struct occ_poll_response *poll =
 		(struct occ_poll_response *)&resp->data[0];
 	struct occ_poll_response_header *header = &poll->header;
 	struct occ_sensor_data_block *block = &poll->block;
 
+	data_length = get_unaligned_be16(&resp->data_length);
+	if (data_length < sizeof(*header) || data_length > OCC_RESP_DATA_BYTES) {
+		dev_err(occ->bus_dev, "invalid OCC poll response length %u\n",
+			data_length);
+		return -EMSGSIZE;
+	}
+
 	dev_info(occ->bus_dev, "OCC found, code level: %.16s\n",
 		 header->occ_code_level);
 
 	for (i = 0; i < header->num_sensor_data_blocks; ++i) {
 		block = (struct occ_sensor_data_block *)((u8 *)block + offset);
+		if (size + sizeof(*header) + sizeof(block->header) >
+		    data_length) {
+			dev_err(occ->bus_dev,
+				"truncated OCC sensor block header\n");
+			return -EMSGSIZE;
+		}
+
 		old_offset = offset;
 		offset = (block->header.num_sensors *
 			  block->header.sensor_length) + sizeof(block->header);
-		size += offset;
 
 		/* validate all the length/size fields */
-		if ((size + sizeof(*header)) >= OCC_RESP_DATA_BYTES) {
-			dev_warn(occ->bus_dev, "exceeded response buffer\n");
-			return;
+		if (size + sizeof(*header) + offset > data_length) {
+			dev_err(occ->bus_dev,
+				"exceeded OCC poll response length\n");
+			return -EMSGSIZE;
 		}
+		size += offset;
 
 		dev_dbg(occ->bus_dev, " %04x..%04x: %.4s (%d sensors)\n",
 			old_offset, offset - 1, block->header.eye_catcher,
@@ -1107,6 +1124,9 @@ static void occ_parse_poll_response(struct occ *occ)
 
 	dev_dbg(occ->bus_dev, "Max resp size: %u+%zd=%zd\n", size,
 		sizeof(*header), size + sizeof(*header));
+	occ->sensors = parsed;
+
+	return 0;
 }
 
 int occ_active(struct occ *occ, bool active)
@@ -1138,10 +1158,12 @@ int occ_active(struct occ *occ, bool active)
 			goto unlock;
 		}
 
-		occ->active = true;
 		occ->next_update = jiffies + OCC_UPDATE_FREQUENCY;
-		occ_parse_poll_response(occ);
+		rc = occ_parse_poll_response(occ);
+		if (rc)
+			goto unlock;
 
+		occ->active = true;
 		rc = occ_setup_sensor_attrs(occ);
 		if (rc) {
 			dev_err(occ->bus_dev,
diff --git linux-libre-7.1.5-gnu/drivers/hwmon/pcf8591.c linux-libre-7.1.6-gnu/drivers/hwmon/pcf8591.c
index 167d2fe4d5432..c0220ebfd4b60 100644
--- linux-libre-7.1.5-gnu/drivers/hwmon/pcf8591.c
+++ linux-libre-7.1.6-gnu/drivers/hwmon/pcf8591.c
@@ -285,7 +285,7 @@ static int pcf8591_read_channel(struct device *dev, int channel)
 }
 
 static const struct i2c_device_id pcf8591_id[] = {
-	{ "pcf8591" },
+	{ .name = "pcf8591" },
 	{ }
 };
 MODULE_DEVICE_TABLE(i2c, pcf8591_id);
diff --git linux-libre-7.1.5-gnu/drivers/hwmon/pmbus/acbel-fsg032.c linux-libre-7.1.6-gnu/drivers/hwmon/pmbus/acbel-fsg032.c
index 9f07fb4abaffd..d283005d92ae7 100644
--- linux-libre-7.1.5-gnu/drivers/hwmon/pmbus/acbel-fsg032.c
+++ linux-libre-7.1.6-gnu/drivers/hwmon/pmbus/acbel-fsg032.c
@@ -49,8 +49,8 @@ static void acbel_fsg032_init_debugfs(struct i2c_client *client)
 }
 
 static const struct i2c_device_id acbel_fsg032_id[] = {
-	{ "acbel_fsg032" },
-	{}
+	{ .name = "acbel_fsg032" },
+	{ }
 };
 
 static struct pmbus_driver_info acbel_fsg032_info = {
diff --git linux-libre-7.1.5-gnu/drivers/hwmon/pmbus/adm1266.c linux-libre-7.1.6-gnu/drivers/hwmon/pmbus/adm1266.c
index 6f6ad7b20e9a9..360a7730b8070 100644
--- linux-libre-7.1.5-gnu/drivers/hwmon/pmbus/adm1266.c
+++ linux-libre-7.1.6-gnu/drivers/hwmon/pmbus/adm1266.c
@@ -510,7 +510,7 @@ static const struct of_device_id adm1266_of_match[] = {
 MODULE_DEVICE_TABLE(of, adm1266_of_match);
 
 static const struct i2c_device_id adm1266