diff --git a/Documentation/devicetree/bindings/gpu/nvidia,tegra20-host1x.txt b/Documentation/devicetree/bindings/gpu/nvidia,tegra20-host1x.txt
index 9e9008f8fa323..efaeec8961b64 100644
--- a/Documentation/devicetree/bindings/gpu/nvidia,tegra20-host1x.txt
+++ b/Documentation/devicetree/bindings/gpu/nvidia,tegra20-host1x.txt
@@ -118,6 +118,9 @@ of the following host1x client modules:
     See ../reset/reset.txt for details.
   - reset-names: Must include the following entries:
     - dc
+  - nvidia,head: The number of the display controller head. This is used to
+    setup the various types of output to receive video data from the given
+    head.
 
   Each display controller node has a child node, named "rgb", that represents
   the RGB output associated with the controller. It can take the following
diff --git a/Documentation/devicetree/bindings/panel/chunghwa,claa101wa01a.txt b/Documentation/devicetree/bindings/panel/chunghwa,claa101wa01a.txt
new file mode 100644
index 0000000000000..f24614e4d5ecb
--- /dev/null
+++ b/Documentation/devicetree/bindings/panel/chunghwa,claa101wa01a.txt
@@ -0,0 +1,7 @@
+Chunghwa Picture Tubes Ltd. 10.1" WXGA TFT LCD panel
+
+Required properties:
+- compatible: should be "chunghwa,claa101wa01a"
+
+This binding is compatible with the simple-panel binding, which is specified
+in simple-panel.txt in this directory.
diff --git a/Documentation/devicetree/bindings/panel/samsung,ltn101nt05.txt b/Documentation/devicetree/bindings/panel/samsung,ltn101nt05.txt
new file mode 100644
index 0000000000000..ef522c6bb85f8
--- /dev/null
+++ b/Documentation/devicetree/bindings/panel/samsung,ltn101nt05.txt
@@ -0,0 +1,7 @@
+Samsung Electronics 10.1" WSVGA TFT LCD panel
+
+Required properties:
+- compatible: should be "samsung,ltn101nt05"
+
+This binding is compatible with the simple-panel binding, which is specified
+in simple-panel.txt in this directory.
diff --git a/MAINTAINERS b/MAINTAINERS
index 31a046213274e..6a6e4ac722877 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -9231,6 +9231,7 @@ F:	include/media/videobuf2-*
 
 VIRTIO CONSOLE DRIVER
 M:	Amit Shah <amit.shah@redhat.com>
+L:	virtio-dev@lists.oasis-open.org
 L:	virtualization@lists.linux-foundation.org
 S:	Maintained
 F:	drivers/char/virtio_console.c
@@ -9240,6 +9241,7 @@ F:	include/uapi/linux/virtio_console.h
 VIRTIO CORE, NET AND BLOCK DRIVERS
 M:	Rusty Russell <rusty@rustcorp.com.au>
 M:	"Michael S. Tsirkin" <mst@redhat.com>
+L:	virtio-dev@lists.oasis-open.org
 L:	virtualization@lists.linux-foundation.org
 S:	Maintained
 F:	drivers/virtio/
@@ -9252,6 +9254,7 @@ F:	include/uapi/linux/virtio_*.h
 VIRTIO HOST (VHOST)
 M:	"Michael S. Tsirkin" <mst@redhat.com>
 L:	kvm@vger.kernel.org
+L:	virtio-dev@lists.oasis-open.org
 L:	virtualization@lists.linux-foundation.org
 L:	netdev@vger.kernel.org
 S:	Maintained
diff --git a/Makefile b/Makefile
index eeec740776f35..b8b7f74696b40 100644
--- a/Makefile
+++ b/Makefile
@@ -1,7 +1,7 @@
 VERSION = 3
 PATCHLEVEL = 13
 SUBLEVEL = 0
-EXTRAVERSION = -rc8
+EXTRAVERSION =
 NAME = One Giant Leap for Frogkind
 
 # *DOCUMENTATION*
diff --git a/arch/arm/kernel/devtree.c b/arch/arm/kernel/devtree.c
index 739c3dfc1da25..34d5fd585bbb1 100644
--- a/arch/arm/kernel/devtree.c
+++ b/arch/arm/kernel/devtree.c
@@ -171,7 +171,7 @@ void __init arm_dt_init_cpu_maps(void)
 
 bool arch_match_cpu_phys_id(int cpu, u64 phys_id)
 {
-	return (phys_id & MPIDR_HWID_BITMASK) == cpu_logical_map(cpu);
+	return phys_id == cpu_logical_map(cpu);
 }
 
 static const void * __init arch_get_next_mach(const char *const **match)
diff --git a/arch/arm/kernel/perf_event_cpu.c b/arch/arm/kernel/perf_event_cpu.c
index d85055cd24bac..20d553c9f5e29 100644
--- a/arch/arm/kernel/perf_event_cpu.c
+++ b/arch/arm/kernel/perf_event_cpu.c
@@ -254,7 +254,7 @@ static int probe_current_pmu(struct arm_pmu *pmu)
 static int cpu_pmu_device_probe(struct platform_device *pdev)
 {
 	const struct of_device_id *of_id;
-	int (*init_fn)(struct arm_pmu *);
+	const int (*init_fn)(struct arm_pmu *);
 	struct device_node *node = pdev->dev.of_node;
 	struct arm_pmu *pmu;
 	int ret = -ENODEV;
diff --git a/arch/arm/kernel/traps.c b/arch/arm/kernel/traps.c
index 6eda3bf85c521..4636d56af2db6 100644
--- a/arch/arm/kernel/traps.c
+++ b/arch/arm/kernel/traps.c
@@ -431,9 +431,10 @@ asmlinkage void __exception do_undefinstr(struct pt_regs *regs)
 			instr2 = __mem_to_opcode_thumb16(instr2);
 			instr = __opcode_thumb32_compose(instr, instr2);
 		}
-	} else if (get_user(instr, (u32 __user *)pc)) {
+	} else {
+		if (get_user(instr, (u32 __user *)pc))
+			goto die_sig;
 		instr = __mem_to_opcode_arm(instr);
-		goto die_sig;
 	}
 
 	if (call_undef_hook(regs, instr) == 0)
diff --git a/arch/arm/mach-highbank/highbank.c b/arch/arm/mach-highbank/highbank.c
index bd3bf66ce3449..c7de89b263dd3 100644
--- a/arch/arm/mach-highbank/highbank.c
+++ b/arch/arm/mach-highbank/highbank.c
@@ -53,6 +53,7 @@ static void __init highbank_scu_map_io(void)
 
 static void highbank_l2x0_disable(void)
 {
+	outer_flush_all();
 	/* Disable PL310 L2 Cache controller */
 	highbank_smc1(0x102, 0x0);
 }
diff --git a/arch/arm/mach-omap2/omap4-common.c b/arch/arm/mach-omap2/omap4-common.c
index b39efd46abf99..c0ab9b26be3da 100644
--- a/arch/arm/mach-omap2/omap4-common.c
+++ b/arch/arm/mach-omap2/omap4-common.c
@@ -162,6 +162,7 @@ void __iomem *omap4_get_l2cache_base(void)
 
 static void omap4_l2x0_disable(void)
 {
+	outer_flush_all();
 	/* Disable PL310 L2 Cache controller */
 	omap_smc1(0x102, 0x0);
 }
diff --git a/arch/arm/mm/init.c b/arch/arm/mm/init.c
index 1f7b19a470606..3e8f106ee5fe0 100644
--- a/arch/arm/mm/init.c
+++ b/arch/arm/mm/init.c
@@ -229,7 +229,7 @@ void __init setup_dma_zone(const struct machine_desc *mdesc)
 #ifdef CONFIG_ZONE_DMA
 	if (mdesc->dma_zone_size) {
 		arm_dma_zone_size = mdesc->dma_zone_size;
-		arm_dma_limit = __pv_phys_offset + arm_dma_zone_size - 1;
+		arm_dma_limit = PHYS_OFFSET + arm_dma_zone_size - 1;
 	} else
 		arm_dma_limit = 0xffffffff;
 	arm_dma_pfn_limit = arm_dma_limit >> PAGE_SHIFT;
diff --git a/arch/arm/net/bpf_jit_32.c b/arch/arm/net/bpf_jit_32.c
index 9ed155ad0f97c..271b5e9715682 100644
--- a/arch/arm/net/bpf_jit_32.c
+++ b/arch/arm/net/bpf_jit_32.c
@@ -641,10 +641,10 @@ static int build_body(struct jit_ctx *ctx)
 			emit(ARM_MUL(r_A, r_A, r_X), ctx);
 			break;
 		case BPF_S_ALU_DIV_K:
-			/* current k == reciprocal_value(userspace k) */
+			if (k == 1)
+				break;
 			emit_mov_i(r_scratch, k, ctx);
-			/* A = top 32 bits of the product */
-			emit(ARM_UMULL(r_scratch, r_A, r_A, r_scratch), ctx);
+			emit_udiv(r_A, r_A, r_scratch, ctx);
 			break;
 		case BPF_S_ALU_DIV_X:
 			update_on_xread(ctx);
diff --git a/arch/arm64/include/asm/io.h b/arch/arm64/include/asm/io.h
index 5727697272276..4cc813eddacbe 100644
--- a/arch/arm64/include/asm/io.h
+++ b/arch/arm64/include/asm/io.h
@@ -229,7 +229,7 @@ extern void __iomem *__ioremap(phys_addr_t phys_addr, size_t size, pgprot_t prot
 extern void __iounmap(volatile void __iomem *addr);
 extern void __iomem *ioremap_cache(phys_addr_t phys_addr, size_t size);
 
-#define PROT_DEFAULT		(pgprot_default | PTE_DIRTY)
+#define PROT_DEFAULT		(PTE_TYPE_PAGE | PTE_AF | PTE_DIRTY)
 #define PROT_DEVICE_nGnRE	(PROT_DEFAULT | PTE_PXN | PTE_UXN | PTE_ATTRINDX(MT_DEVICE_nGnRE))
 #define PROT_NORMAL_NC		(PROT_DEFAULT | PTE_ATTRINDX(MT_NORMAL_NC))
 #define PROT_NORMAL		(PROT_DEFAULT | PTE_ATTRINDX(MT_NORMAL))
diff --git a/arch/mips/include/asm/cacheops.h b/arch/mips/include/asm/cacheops.h
index c75025f27c201..06b9bc7ea14b1 100644
--- a/arch/mips/include/asm/cacheops.h
+++ b/arch/mips/include/asm/cacheops.h
@@ -83,6 +83,6 @@
 /*
  * Loongson2-specific cacheops
  */
-#define Hit_Invalidate_I_Loongson23	0x00
+#define Hit_Invalidate_I_Loongson2	0x00
 
 #endif	/* __ASM_CACHEOPS_H */
diff --git a/arch/mips/include/asm/r4kcache.h b/arch/mips/include/asm/r4kcache.h
index 34d1a19171257..c84caddb8bded 100644
--- a/arch/mips/include/asm/r4kcache.h
+++ b/arch/mips/include/asm/r4kcache.h
@@ -165,7 +165,7 @@ static inline void flush_icache_line(unsigned long addr)
 	__iflush_prologue
 	switch (boot_cpu_type()) {
 	case CPU_LOONGSON2:
-		cache_op(Hit_Invalidate_I_Loongson23, addr);
+		cache_op(Hit_Invalidate_I_Loongson2, addr);
 		break;
 
 	default:
@@ -219,7 +219,7 @@ static inline void protected_flush_icache_line(unsigned long addr)
 {
 	switch (boot_cpu_type()) {
 	case CPU_LOONGSON2:
-		protected_cache_op(Hit_Invalidate_I_Loongson23, addr);
+		protected_cache_op(Hit_Invalidate_I_Loongson2, addr);
 		break;
 
 	default:
@@ -357,8 +357,8 @@ static inline void invalidate_tcache_page(unsigned long addr)
 		  "i" (op));
 
 /* build blast_xxx, blast_xxx_page, blast_xxx_page_indexed */
-#define __BUILD_BLAST_CACHE(pfx, desc, indexop, hitop, lsize) \
-static inline void blast_##pfx##cache##lsize(void)			\
+#define __BUILD_BLAST_CACHE(pfx, desc, indexop, hitop, lsize, extra)	\
+static inline void extra##blast_##pfx##cache##lsize(void)		\
 {									\
 	unsigned long start = INDEX_BASE;				\
 	unsigned long end = start + current_cpu_data.desc.waysize;	\
@@ -376,7 +376,7 @@ static inline void blast_##pfx##cache##lsize(void)			\
 	__##pfx##flush_epilogue						\
 }									\
 									\
-static inline void blast_##pfx##cache##lsize##_page(unsigned long page) \
+static inline void extra##blast_##pfx##cache##lsize##_page(unsigned long page) \
 {									\
 	unsigned long start = page;					\
 	unsigned long end = page + PAGE_SIZE;				\
@@ -391,7 +391,7 @@ static inline void blast_##pfx##cache##lsize##_page(unsigned long page) \
 	__##pfx##flush_epilogue						\
 }									\
 									\
-static inline void blast_##pfx##cache##lsize##_page_indexed(unsigned long page) \
+static inline void extra##blast_##pfx##cache##lsize##_page_indexed(unsigned long page) \
 {									\
 	unsigned long indexmask = current_cpu_data.desc.waysize - 1;	\
 	unsigned long start = INDEX_BASE + (page & indexmask);		\
@@ -410,23 +410,24 @@ static inline void blast_##pfx##cache##lsize##_page_indexed(unsigned long page)
 	__##pfx##flush_epilogue						\
 }
 
-__BUILD_BLAST_CACHE(d, dcache, Index_Writeback_Inv_D, Hit_Writeback_Inv_D, 16)
-__BUILD_BLAST_CACHE(i, icache, Index_Invalidate_I, Hit_Invalidate_I, 16)
-__BUILD_BLAST_CACHE(s, scache, Index_Writeback_Inv_SD, Hit_Writeback_Inv_SD, 16)
-__BUILD_BLAST_CACHE(d, dcache, Index_Writeback_Inv_D, Hit_Writeback_Inv_D, 32)
-__BUILD_BLAST_CACHE(i, icache, Index_Invalidate_I, Hit_Invalidate_I, 32)
-__BUILD_BLAST_CACHE(s, scache, Index_Writeback_Inv_SD, Hit_Writeback_Inv_SD, 32)
-__BUILD_BLAST_CACHE(d, dcache, Index_Writeback_Inv_D, Hit_Writeback_Inv_D, 64)
-__BUILD_BLAST_CACHE(i, icache, Index_Invalidate_I, Hit_Invalidate_I, 64)
-__BUILD_BLAST_CACHE(s, scache, Index_Writeback_Inv_SD, Hit_Writeback_Inv_SD, 64)
-__BUILD_BLAST_CACHE(s, scache, Index_Writeback_Inv_SD, Hit_Writeback_Inv_SD, 128)
-
-__BUILD_BLAST_CACHE(inv_d, dcache, Index_Writeback_Inv_D, Hit_Invalidate_D, 16)
-__BUILD_BLAST_CACHE(inv_d, dcache, Index_Writeback_Inv_D, Hit_Invalidate_D, 32)
-__BUILD_BLAST_CACHE(inv_s, scache, Index_Writeback_Inv_SD, Hit_Invalidate_SD, 16)
-__BUILD_BLAST_CACHE(inv_s, scache, Index_Writeback_Inv_SD, Hit_Invalidate_SD, 32)
-__BUILD_BLAST_CACHE(inv_s, scache, Index_Writeback_Inv_SD, Hit_Invalidate_SD, 64)
-__BUILD_BLAST_CACHE(inv_s, scache, Index_Writeback_Inv_SD, Hit_Invalidate_SD, 128)
+__BUILD_BLAST_CACHE(d, dcache, Index_Writeback_Inv_D, Hit_Writeback_Inv_D, 16, )
+__BUILD_BLAST_CACHE(i, icache, Index_Invalidate_I, Hit_Invalidate_I, 16, )
+__BUILD_BLAST_CACHE(s, scache, Index_Writeback_Inv_SD, Hit_Writeback_Inv_SD, 16, )
+__BUILD_BLAST_CACHE(d, dcache, Index_Writeback_Inv_D, Hit_Writeback_Inv_D, 32, )
+__BUILD_BLAST_CACHE(i, icache, Index_Invalidate_I, Hit_Invalidate_I, 32, )
+__BUILD_BLAST_CACHE(i, icache, Index_Invalidate_I, Hit_Invalidate_I_Loongson2, 32, loongson2_)
+__BUILD_BLAST_CACHE(s, scache, Index_Writeback_Inv_SD, Hit_Writeback_Inv_SD, 32, )
+__BUILD_BLAST_CACHE(d, dcache, Index_Writeback_Inv_D, Hit_Writeback_Inv_D, 64, )
+__BUILD_BLAST_CACHE(i, icache, Index_Invalidate_I, Hit_Invalidate_I, 64, )
+__BUILD_BLAST_CACHE(s, scache, Index_Writeback_Inv_SD, Hit_Writeback_Inv_SD, 64, )
+__BUILD_BLAST_CACHE(s, scache, Index_Writeback_Inv_SD, Hit_Writeback_Inv_SD, 128, )
+
+__BUILD_BLAST_CACHE(inv_d, dcache, Index_Writeback_Inv_D, Hit_Invalidate_D, 16, )
+__BUILD_BLAST_CACHE(inv_d, dcache, Index_Writeback_Inv_D, Hit_Invalidate_D, 32, )
+__BUILD_BLAST_CACHE(inv_s, scache, Index_Writeback_Inv_SD, Hit_Invalidate_SD, 16, )
+__BUILD_BLAST_CACHE(inv_s, scache, Index_Writeback_Inv_SD, Hit_Invalidate_SD, 32, )
+__BUILD_BLAST_CACHE(inv_s, scache, Index_Writeback_Inv_SD, Hit_Invalidate_SD, 64, )
+__BUILD_BLAST_CACHE(inv_s, scache, Index_Writeback_Inv_SD, Hit_Invalidate_SD, 128, )
 
 /* build blast_xxx_range, protected_blast_xxx_range */
 #define __BUILD_BLAST_CACHE_RANGE(pfx, desc, hitop, prot, extra)	\
@@ -452,8 +453,8 @@ static inline void prot##extra##blast_##pfx##cache##_range(unsigned long start,
 __BUILD_BLAST_CACHE_RANGE(d, dcache, Hit_Writeback_Inv_D, protected_, )
 __BUILD_BLAST_CACHE_RANGE(s, scache, Hit_Writeback_Inv_SD, protected_, )
 __BUILD_BLAST_CACHE_RANGE(i, icache, Hit_Invalidate_I, protected_, )
-__BUILD_BLAST_CACHE_RANGE(i, icache, Hit_Invalidate_I_Loongson23, \
-	protected_, loongson23_)
+__BUILD_BLAST_CACHE_RANGE(i, icache, Hit_Invalidate_I_Loongson2, \
+	protected_, loongson2_)
 __BUILD_BLAST_CACHE_RANGE(d, dcache, Hit_Writeback_Inv_D, , )
 __BUILD_BLAST_CACHE_RANGE(s, scache, Hit_Writeback_Inv_SD, , )
 /* blast_inv_dcache_range */
diff --git a/arch/mips/mm/c-r4k.c b/arch/mips/mm/c-r4k.c
index 62ffd20ea8690..49e572d879e13 100644
--- a/arch/mips/mm/c-r4k.c
+++ b/arch/mips/mm/c-r4k.c
@@ -237,6 +237,8 @@ static void r4k_blast_icache_page_setup(void)
 		r4k_blast_icache_page = (void *)cache_noop;
 	else if (ic_lsize == 16)
 		r4k_blast_icache_page = blast_icache16_page;
+	else if (ic_lsize == 32 && current_cpu_type() == CPU_LOONGSON2)
+		r4k_blast_icache_page = loongson2_blast_icache32_page;
 	else if (ic_lsize == 32)
 		r4k_blast_icache_page = blast_icache32_page;
 	else if (ic_lsize == 64)
@@ -261,6 +263,9 @@ static void r4k_blast_icache_page_indexed_setup(void)
 		else if (TX49XX_ICACHE_INDEX_INV_WAR)
 			r4k_blast_icache_page_indexed =
 				tx49_blast_icache32_page_indexed;
+		else if (current_cpu_type() == CPU_LOONGSON2)
+			r4k_blast_icache_page_indexed =
+				loongson2_blast_icache32_page_indexed;
 		else
 			r4k_blast_icache_page_indexed =
 				blast_icache32_page_indexed;
@@ -284,6 +289,8 @@ static void r4k_blast_icache_setup(void)
 			r4k_blast_icache = blast_r4600_v1_icache32;
 		else if (TX49XX_ICACHE_INDEX_INV_WAR)
 			r4k_blast_icache = tx49_blast_icache32;
+		else if (current_cpu_type() == CPU_LOONGSON2)
+			r4k_blast_icache = loongson2_blast_icache32;
 		else
 			r4k_blast_icache = blast_icache32;
 	} else if (ic_lsize == 64)
@@ -580,11 +587,11 @@ static inline void local_r4k_flush_icache_range(unsigned long start, unsigned lo
 	else {
 		switch (boot_cpu_type()) {
 		case CPU_LOONGSON2:
-			protected_blast_icache_range(start, end);
+			protected_loongson2_blast_icache_range(start, end);
 			break;
 
 		default:
-			protected_loongson23_blast_icache_range(start, end);
+			protected_blast_icache_range(start, end);
 			break;
 		}
 	}
diff --git a/arch/parisc/include/uapi/asm/socket.h b/arch/parisc/include/uapi/asm/socket.h
index f33113a6141e7..70b3674dac4e3 100644
--- a/arch/parisc/include/uapi/asm/socket.h
+++ b/arch/parisc/include/uapi/asm/socket.h
@@ -75,6 +75,6 @@
 
 #define SO_BUSY_POLL		0x4027
 
-#define SO_MAX_PACING_RATE	0x4048
+#define SO_MAX_PACING_RATE	0x4028
 
 #endif /* _UAPI_ASM_SOCKET_H */
diff --git a/arch/powerpc/net/bpf_jit_comp.c b/arch/powerpc/net/bpf_jit_comp.c
index ac3c2a10dafda..555034f8505e8 100644
--- a/arch/powerpc/net/bpf_jit_comp.c
+++ b/arch/powerpc/net/bpf_jit_comp.c
@@ -223,10 +223,11 @@ static int bpf_jit_build_body(struct sk_filter *fp, u32 *image,
 			}
 			PPC_DIVWU(r_A, r_A, r_X);
 			break;
-		case BPF_S_ALU_DIV_K: /* A = reciprocal_divide(A, K); */
+		case BPF_S_ALU_DIV_K: /* A /= K */
+			if (K == 1)
+				break;
 			PPC_LI32(r_scratch1, K);
-			/* Top 32 bits of 64bit result -> A */
-			PPC_MULHWU(r_A, r_A, r_scratch1);
+			PPC_DIVWU(r_A, r_A, r_scratch1);
 			break;
 		case BPF_S_ALU_AND_X:
 			ctx->seen |= SEEN_XREG;
diff --git a/arch/s390/net/bpf_jit_comp.c b/arch/s390/net/bpf_jit_comp.c
index 16871da373716..708d60e400667 100644
--- a/arch/s390/net/bpf_jit_comp.c
+++ b/arch/s390/net/bpf_jit_comp.c
@@ -368,14 +368,16 @@ static int bpf_jit_insn(struct bpf_jit *jit, struct sock_filter *filter,
 		EMIT4_PCREL(0xa7840000, (jit->ret0_ip - jit->prg));
 		/* lhi %r4,0 */
 		EMIT4(0xa7480000);
-		/* dr %r4,%r12 */
-		EMIT2(0x1d4c);
+		/* dlr %r4,%r12 */
+		EMIT4(0xb997004c);
 		break;
-	case BPF_S_ALU_DIV_K: /* A = reciprocal_divide(A, K) */
-		/* m %r4,<d(K)>(%r13) */
-		EMIT4_DISP(0x5c40d000, EMIT_CONST(K));
-		/* lr %r5,%r4 */
-		EMIT2(0x1854);
+	case BPF_S_ALU_DIV_K: /* A /= K */
+		if (K == 1)
+			break;
+		/* lhi %r4,0 */
+		EMIT4(0xa7480000);
+		/* dl %r4,<d(K)>(%r13) */
+		EMIT6_DISP(0xe340d000, 0x0097, EMIT_CONST(K));
 		break;
 	case BPF_S_ALU_MOD_X: /* A %= X */
 		jit->seen |= SEEN_XREG | SEEN_RET0;
@@ -385,16 +387,21 @@ static int bpf_jit_insn(struct bpf_jit *jit, struct sock_filter *filter,
 		EMIT4_PCREL(0xa7840000, (jit->ret0_ip - jit->prg));
 		/* lhi %r4,0 */
 		EMIT4(0xa7480000);
-		/* dr %r4,%r12 */
-		EMIT2(0x1d4c);
+		/* dlr %r4,%r12 */
+		EMIT4(0xb997004c);
 		/* lr %r5,%r4 */
 		EMIT2(0x1854);
 		break;
 	case BPF_S_ALU_MOD_K: /* A %= K */
+		if (K == 1) {
+			/* lhi %r5,0 */
+			EMIT4(0xa7580000);
+			break;
+		}
 		/* lhi %r4,0 */
 		EMIT4(0xa7480000);
-		/* d %r4,<d(K)>(%r13) */
-		EMIT4_DISP(0x5d40d000, EMIT_CONST(K));
+		/* dl %r4,<d(K)>(%r13) */
+		EMIT6_DISP(0xe340d000, 0x0097, EMIT_CONST(K));
 		/* lr %r5,%r4 */
 		EMIT2(0x1854);
 		break;
diff --git a/arch/sparc/net/bpf_jit_comp.c b/arch/sparc/net/bpf_jit_comp.c
index 218b6b23c378f..01fe9946d388d 100644
--- a/arch/sparc/net/bpf_jit_comp.c
+++ b/arch/sparc/net/bpf_jit_comp.c
@@ -497,9 +497,20 @@ void bpf_jit_compile(struct sk_filter *fp)
 			case BPF_S_ALU_MUL_K:	/* A *= K */
 				emit_alu_K(MUL, K);
 				break;
-			case BPF_S_ALU_DIV_K:	/* A /= K */
-				emit_alu_K(MUL, K);
-				emit_read_y(r_A);
+			case BPF_S_ALU_DIV_K:	/* A /= K with K != 0*/
+				if (K == 1)
+					break;
+				emit_write_y(G0);
+#ifdef CONFIG_SPARC32
+				/* The Sparc v8 architecture requires
+				 * three instructions between a %y
+				 * register write and the first use.
+				 */
+				emit_nop();
+				emit_nop();
+				emit_nop();
+#endif
+				emit_alu_K(DIV, K);
 				break;
 			case BPF_S_ALU_DIV_X:	/* A /= X; */
 				emit_cmpi(r_X, 0);
diff --git a/arch/x86/kernel/cpu/perf_event_amd_ibs.c b/arch/x86/kernel/cpu/perf_event_amd_ibs.c
index e09f0bfb7b8f2..4b8e4d3cd6ea6 100644
--- a/arch/x86/kernel/cpu/perf_event_amd_ibs.c
+++ b/arch/x86/kernel/cpu/perf_event_amd_ibs.c
@@ -10,6 +10,7 @@
 #include <linux/module.h>
 #include <linux/pci.h>
 #include <linux/ptrace.h>
+#include <linux/syscore_ops.h>
 
 #include <asm/apic.h>
 
@@ -816,6 +817,18 @@ static int force_ibs_eilvt_setup(void)
 	return ret;
 }
 
+static void ibs_eilvt_setup(void)
+{
+	/*
+	 * Force LVT offset assignment for family 10h: The offsets are
+	 * not assigned by the BIOS for this family, so the OS is
+	 * responsible for doing it. If the OS assignment fails, fall
+	 * back to BIOS settings and try to setup this.
+	 */
+	if (boot_cpu_data.x86 == 0x10)
+		force_ibs_eilvt_setup();
+}
+
 static inline int get_ibs_lvt_offset(void)
 {
 	u64 val;
@@ -851,6 +864,36 @@ static void clear_APIC_ibs(void *dummy)
 		setup_APIC_eilvt(offset, 0, APIC_EILVT_MSG_FIX, 1);
 }
 
+#ifdef CONFIG_PM
+
+static int perf_ibs_suspend(void)
+{
+	clear_APIC_ibs(NULL);
+	return 0;
+}
+
+static void perf_ibs_resume(void)
+{
+	ibs_eilvt_setup();
+	setup_APIC_ibs(NULL);
+}
+
+static struct syscore_ops perf_ibs_syscore_ops = {
+	.resume		= perf_ibs_resume,
+	.suspend	= perf_ibs_suspend,
+};
+
+static void perf_ibs_pm_init(void)
+{
+	register_syscore_ops(&perf_ibs_syscore_ops);
+}
+
+#else
+
+static inline void perf_ibs_pm_init(void) { }
+
+#endif
+
 static int
 perf_ibs_cpu_notifier(struct notifier_block *self, unsigned long action, void *hcpu)
 {
@@ -877,18 +920,12 @@ static __init int amd_ibs_init(void)
 	if (!caps)
 		return -ENODEV;	/* ibs not supported by the cpu */
 
-	/*
-	 * Force LVT offset assignment for family 10h: The offsets are
-	 * not assigned by the BIOS for this family, so the OS is
-	 * responsible for doing it. If the OS assignment fails, fall
-	 * back to BIOS settings and try to setup this.
-	 */
-	if (boot_cpu_data.x86 == 0x10)
-		force_ibs_eilvt_setup();
+	ibs_eilvt_setup();
 
 	if (!ibs_eilvt_valid())
 		goto out;
 
+	perf_ibs_pm_init();
 	get_online_cpus();
 	ibs_caps = caps;
 	/* make ibs_caps visible to other cpus: */
diff --git a/arch/x86/kvm/lapic.c b/arch/x86/kvm/lapic.c
index 1673940cf9c35..775702f649ca6 100644
--- a/arch/x86/kvm/lapic.c
+++ b/arch/x86/kvm/lapic.c
@@ -1355,7 +1355,7 @@ void kvm_lapic_set_base(struct kvm_vcpu *vcpu, u64 value)
 	vcpu->arch.apic_base = value;
 
 	/* update jump label if enable bit changes */
-	if ((vcpu->arch.apic_base ^ value) & MSR_IA32_APICBASE_ENABLE) {
+	if ((old_value ^ value) & MSR_IA32_APICBASE_ENABLE) {
 		if (value & MSR_IA32_APICBASE_ENABLE)
 			static_key_slow_dec_deferred(&apic_hw_disabled);
 		else
diff --git a/arch/x86/mm/fault.c b/arch/x86/mm/fault.c
index 9ff85bb8dd698..9d591c8958031 100644
--- a/arch/x86/mm/fault.c
+++ b/arch/x86/mm/fault.c
@@ -641,6 +641,20 @@ no_context(struct pt_regs *regs, unsigned long error_code,
 
 	/* Are we prepared to handle this kernel fault? */
 	if (fixup_exception(regs)) {
+		/*
+		 * Any interrupt that takes a fault gets the fixup. This makes
+		 * the below recursive fault logic only apply to a faults from
+		 * task context.
+		 */
+		if (in_interrupt())
+			return;
+
+		/*
+		 * Per the above we're !in_interrupt(), aka. task context.
+		 *
+		 * In this case we need to make sure we're not recursively
+		 * faulting through the emulate_vsyscall() logic.
+		 */
 		if (current_thread_info()->sig_on_uaccess_error && signal) {
 			tsk->thread.trap_nr = X86_TRAP_PF;
 			tsk->thread.error_code = error_code | PF_USER;
@@ -649,6 +663,10 @@ no_context(struct pt_regs *regs, unsigned long error_code,
 			/* XXX: hwpoison faults will set the wrong code. */
 			force_sig_info_fault(signal, si_code, address, tsk, 0);
 		}
+
+		/*
+		 * Barring that, we can do the fixup and be happy.
+		 */
 		return;
 	}
 
diff --git a/arch/x86/net/bpf_jit_comp.c b/arch/x86/net/bpf_jit_comp.c
index 26328e800869f..4ed75dd81d052 100644
--- a/arch/x86/net/bpf_jit_comp.c
+++ b/arch/x86/net/bpf_jit_comp.c
@@ -359,15 +359,21 @@ void bpf_jit_compile(struct sk_filter *fp)
 				EMIT2(0x89, 0xd0);	/* mov %edx,%eax */
 				break;
 			case BPF_S_ALU_MOD_K: /* A %= K; */
+				if (K == 1) {
+					CLEAR_A();
+					break;
+				}
 				EMIT2(0x31, 0xd2);	/* xor %edx,%edx */
 				EMIT1(0xb9);EMIT(K, 4);	/* mov imm32,%ecx */
 				EMIT2(0xf7, 0xf1);	/* div %ecx */
 				EMIT2(0x89, 0xd0);	/* mov %edx,%eax */
 				break;
-			case BPF_S_ALU_DIV_K: /* A = reciprocal_divide(A, K); */
-				EMIT3(0x48, 0x69, 0xc0); /* imul imm32,%rax,%rax */
-				EMIT(K, 4);
-				EMIT4(0x48, 0xc1, 0xe8, 0x20); /* shr $0x20,%rax */
+			case BPF_S_ALU_DIV_K: /* A /= K */
+				if (K == 1)
+					break;
+				EMIT2(0x31, 0xd2);	/* xor %edx,%edx */
+				EMIT1(0xb9);EMIT(K, 4);	/* mov imm32,%ecx */
+				EMIT2(0xf7, 0xf1);	/* div %ecx */
 				break;
 			case BPF_S_ALU_AND_X:
 				seen |= SEEN_XREG;
diff --git a/arch/x86/vdso/vclock_gettime.c b/arch/x86/vdso/vclock_gettime.c
index 2ada505067cce..eb5d7a56f8d4b 100644
--- a/arch/x86/vdso/vclock_gettime.c
+++ b/arch/x86/vdso/vclock_gettime.c
@@ -178,7 +178,7 @@ notrace static int __always_inline do_realtime(struct timespec *ts)
 
 	ts->tv_nsec = 0;
 	do {
-		seq = read_seqcount_begin_no_lockdep(&gtod->seq);
+		seq = raw_read_seqcount_begin(&gtod->seq);
 		mode = gtod->clock.vclock_mode;
 		ts->tv_sec = gtod->wall_time_sec;
 		ns = gtod->wall_time_snsec;
@@ -198,7 +198,7 @@ notrace static int do_monotonic(struct timespec *ts)
 
 	ts->tv_nsec = 0;
 	do {
-		seq = read_seqcount_begin_no_lockdep(&gtod->seq);
+		seq = raw_read_seqcount_begin(&gtod->seq);
 		mode = gtod->clock.vclock_mode;
 		ts->tv_sec = gtod->monotonic_time_sec;
 		ns = gtod->monotonic_time_snsec;
@@ -214,7 +214,7 @@ notrace static int do_realtime_coarse(struct timespec *ts)
 {
 	unsigned long seq;
 	do {
-		seq = read_seqcount_begin_no_lockdep(&gtod->seq);
+		seq = raw_read_seqcount_begin(&gtod->seq);
 		ts->tv_sec = gtod->wall_time_coarse.tv_sec;
 		ts->tv_nsec = gtod->wall_time_coarse.tv_nsec;
 	} while (unlikely(read_seqcount_retry(&gtod->seq, seq)));
@@ -225,7 +225,7 @@ notrace static int do_monotonic_coarse(struct timespec *ts)
 {
 	unsigned long seq;
 	do {
-		seq = read_seqcount_begin_no_lockdep(&gtod->seq);
+		seq = raw_read_seqcount_begin(&gtod->seq);
 		ts->tv_sec = gtod->monotonic_time_coarse.tv_sec;
 		ts->tv_nsec = gtod->monotonic_time_coarse.tv_nsec;
 	} while (unlikely(read_seqcount_retry(&gtod->seq, seq)));
diff --git a/drivers/acpi/acpi_lpss.c b/drivers/acpi/acpi_lpss.c
index e603905973721..6745fe137b9ea 100644
--- a/drivers/acpi/acpi_lpss.c
+++ b/drivers/acpi/acpi_lpss.c
@@ -162,7 +162,6 @@ static const struct acpi_device_id acpi_lpss_device_ids[] = {
 	{ "80860F14", (unsigned long)&byt_sdio_dev_desc },
 	{ "80860F41", (unsigned long)&byt_i2c_dev_desc },
 	{ "INT33B2", },
-	{ "INT33FC", },
 
 	{ "INT3430", (unsigned long)&lpt_dev_desc },
 	{ "INT3431", (unsigned long)&lpt_dev_desc },
diff --git a/drivers/clocksource/cadence_ttc_timer.c b/drivers/clocksource/cadence_ttc_timer.c
index b2bb3a4bc2054..a92350b55d326 100644
--- a/drivers/clocksource/cadence_ttc_timer.c
+++ b/drivers/clocksource/cadence_ttc_timer.c
@@ -67,11 +67,13 @@
  * struct ttc_timer - This definition defines local timer structure
  *
  * @base_addr:	Base address of timer
+ * @freq:	Timer input clock frequency
  * @clk:	Associated clock source
  * @clk_rate_change_nb	Notifier block for clock rate changes
  */
 struct ttc_timer {
 	void __iomem *base_addr;
+	unsigned long freq;
 	struct clk *clk;
 	struct notifier_block clk_rate_change_nb;
 };
@@ -196,9 +198,8 @@ static void ttc_set_mode(enum clock_event_mode mode,
 
 	switch (mode) {
 	case CLOCK_EVT_MODE_PERIODIC:
-		ttc_set_interval(timer,
-				DIV_ROUND_CLOSEST(clk_get_rate(ttce->ttc.clk),
-					PRESCALE * HZ));
+		ttc_set_interval(timer, DIV_ROUND_CLOSEST(ttce->ttc.freq,
+						PRESCALE * HZ));
 		break;
 	case CLOCK_EVT_MODE_ONESHOT:
 	case CLOCK_EVT_MODE_UNUSED:
@@ -273,6 +274,8 @@ static void __init ttc_setup_clocksource(struct clk *clk, void __iomem *base)
 		return;
 	}
 
+	ttccs->ttc.freq = clk_get_rate(ttccs->ttc.clk);
+
 	ttccs->ttc.clk_rate_change_nb.notifier_call =
 		ttc_rate_change_clocksource_cb;
 	ttccs->ttc.clk_rate_change_nb.next = NULL;
@@ -298,16 +301,14 @@ static void __init ttc_setup_clocksource(struct clk *clk, void __iomem *base)
 	__raw_writel(CNT_CNTRL_RESET,
 		     ttccs->ttc.base_addr + TTC_CNT_CNTRL_OFFSET);
 
-	err = clocksource_register_hz(&ttccs->cs,
-			clk_get_rate(ttccs->ttc.clk) / PRESCALE);
+	err = clocksource_register_hz(&ttccs->cs, ttccs->ttc.freq / PRESCALE);
 	if (WARN_ON(err)) {
 		kfree(ttccs);
 		return;
 	}
 
 	ttc_sched_clock_val_reg = base + TTC_COUNT_VAL_OFFSET;
-	setup_sched_clock(ttc_sched_clock_read, 16,
-			clk_get_rate(ttccs->ttc.clk) / PRESCALE);
+	setup_sched_clock(ttc_sched_clock_read, 16, ttccs->ttc.freq / PRESCALE);
 }
 
 static int ttc_rate_change_clockevent_cb(struct notifier_block *nb,
@@ -334,6 +335,9 @@ static int ttc_rate_change_clockevent_cb(struct notifier_block *nb,
 				ndata->new_rate / PRESCALE);
 		local_irq_restore(flags);
 
+		/* update cached frequency */
+		ttc->freq = ndata->new_rate;
+
 		/* fall through */
 	}
 	case PRE_RATE_CHANGE:
@@ -367,6 +371,7 @@ static void __init ttc_setup_clockevent(struct clk *clk,
 	if (clk_notifier_register(ttcce->ttc.clk,
 				&ttcce->ttc.clk_rate_change_nb))
 		pr_warn("Unable to register clock notifier.\n");
+	ttcce->ttc.freq = clk_get_rate(ttcce->ttc.clk);
 
 	ttcce->ttc.base_addr = base;
 	ttcce->ce.name = "ttc_clockevent";
@@ -396,7 +401,7 @@ static void __init ttc_setup_clockevent(struct clk *clk,
 	}
 
 	clockevents_config_and_register(&ttcce->ce,
-			clk_get_rate(ttcce->ttc.clk) / PRESCALE, 1, 0xfffe);
+			ttcce->ttc.freq / PRESCALE, 1, 0xfffe);
 }
 
 /**
diff --git a/drivers/gpu/drm/armada/Kconfig b/drivers/gpu/drm/armada/Kconfig
index 40d371521fe19..50ae88ad4d76f 100644
--- a/drivers/gpu/drm/armada/Kconfig
+++ b/drivers/gpu/drm/armada/Kconfig
@@ -5,6 +5,7 @@ config DRM_ARMADA
 	select FB_CFB_COPYAREA
 	select FB_CFB_IMAGEBLIT
 	select DRM_KMS_HELPER
+	select DRM_KMS_FB_HELPER
 	help
 	  Support the "LCD" controllers found on the Marvell Armada 510
 	  devices.  There are two controllers on the device, each controller
diff --git a/drivers/gpu/drm/ast/ast_fb.c b/drivers/gpu/drm/ast/ast_fb.c
index 7b33e14e44aa1..3f65dd6676b2c 100644
--- a/drivers/gpu/drm/ast/ast_fb.c
+++ b/drivers/gpu/drm/ast/ast_fb.c
@@ -65,7 +65,7 @@ static void ast_dirty_update(struct ast_fbdev *afbdev,
 	 * then the BO is being moved and we should
 	 * store up the damage until later.
 	 */
-	if (!in_interrupt())
+	if (!drm_can_sleep())
 		ret = ast_bo_reserve(bo, true);
 	if (ret) {
 		if (ret != -EBUSY)
diff --git a/drivers/gpu/drm/cirrus/cirrus_fbdev.c b/drivers/gpu/drm/cirrus/cirrus_fbdev.c
index e63a7533f849b..2fd4a92162cb8 100644
--- a/drivers/gpu/drm/cirrus/cirrus_fbdev.c
+++ b/drivers/gpu/drm/cirrus/cirrus_fbdev.c
@@ -39,7 +39,7 @@ static void cirrus_dirty_update(struct cirrus_fbdev *afbdev,
 	 * then the BO is being moved and we should
 	 * store up the damage until later.
 	 */
-	if (!in_interrupt())
+	if (!drm_can_sleep())
 		ret = cirrus_bo_reserve(bo, true);
 	if (ret) {
 		if (ret != -EBUSY)
diff --git a/drivers/gpu/drm/cirrus/cirrus_mode.c b/drivers/gpu/drm/cirrus/cirrus_mode.c
index 58dd900083b9e..530f78f84deed 100644
--- a/drivers/gpu/drm/cirrus/cirrus_mode.c
+++ b/drivers/gpu/drm/cirrus/cirrus_mode.c
@@ -273,8 +273,8 @@ static int cirrus_crtc_mode_set(struct drm_crtc *crtc,
 		sr07 |= 0x11;
 		break;
 	case 16:
-		sr07 |= 0xc1;
-		hdr = 0xc0;
+		sr07 |= 0x17;
+		hdr = 0xc1;
 		break;
 	case 24:
 		sr07 |= 0x15;
diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c
index 266a01d7f6353..3b7d32da16046 100644
--- a/drivers/gpu/drm/drm_crtc.c
+++ b/drivers/gpu/drm/drm_crtc.c
@@ -674,6 +674,29 @@ void drm_crtc_cleanup(struct drm_crtc *crtc)
 }
 EXPORT_SYMBOL(drm_crtc_cleanup);
 
+/**
+ * drm_crtc_index - find the index of a registered CRTC
+ * @crtc: CRTC to find index for
+ *
+ * Given a registered CRTC, return the index of that CRTC within a DRM
+ * device's list of CRTCs.
+ */
+unsigned int drm_crtc_index(struct drm_crtc *crtc)
+{
+	unsigned int index = 0;
+	struct drm_crtc *tmp;
+
+	list_for_each_entry(tmp, &crtc->dev->mode_config.crtc_list, head) {
+		if (tmp == crtc)
+			return index;
+
+		index++;
+	}
+
+	BUG();
+}
+EXPORT_SYMBOL(drm_crtc_index);
+
 /**
  * drm_mode_probed_add - add a mode to a connector's probed mode list
  * @connector: connector the new mode
diff --git a/drivers/gpu/drm/drm_crtc_helper.c b/drivers/gpu/drm/drm_crtc_helper.c
index 245fe4fa9c9ed..ea92b827e787e 100644
--- a/drivers/gpu/drm/drm_crtc_helper.c
+++ b/drivers/gpu/drm/drm_crtc_helper.c
@@ -324,35 +324,6 @@ void drm_helper_disable_unused_functions(struct drm_device *dev)
 }
 EXPORT_SYMBOL(drm_helper_disable_unused_functions);
 
-/**
- * drm_encoder_crtc_ok - can a given crtc drive a given encoder?
- * @encoder: encoder to test
- * @crtc: crtc to test
- *
- * Return false if @encoder can't be driven by @crtc, true otherwise.
- */
-static bool drm_encoder_crtc_ok(struct drm_encoder *encoder,
-				struct drm_crtc *crtc)
-{
-	struct drm_device *dev;
-	struct drm_crtc *tmp;
-	int crtc_mask = 1;
-
-	WARN(!crtc, "checking null crtc?\n");
-
-	dev = crtc->dev;
-
-	list_for_each_entry(tmp, &dev->mode_config.crtc_list, head) {
-		if (tmp == crtc)
-			break;
-		crtc_mask <<= 1;
-	}
-
-	if (encoder->possible_crtcs & crtc_mask)
-		return true;
-	return false;
-}
-
 /*
  * Check the CRTC we're going to map each output to vs. its current
  * CRTC.  If they don't match, we have to disable the output and the CRTC
diff --git a/drivers/gpu/drm/gma500/cdv_intel_dp.c b/drivers/gpu/drm/gma500/cdv_intel_dp.c
index 6a7c2481d4ab7..0490ce36b53fd 100644
--- a/drivers/gpu/drm/gma500/cdv_intel_dp.c
+++ b/drivers/gpu/drm/gma500/cdv_intel_dp.c
@@ -678,7 +678,7 @@ cdv_intel_dp_i2c_init(struct gma_connector *connector,
 	return ret;
 }
 
-void cdv_intel_fixed_panel_mode(struct drm_display_mode *fixed_mode,
+static void cdv_intel_fixed_panel_mode(struct drm_display_mode *fixed_mode,
 	struct drm_display_mode *adjusted_mode)
 {
 	adjusted_mode->hdisplay = fixed_mode->hdisplay;
diff --git a/drivers/gpu/drm/gma500/gma_display.c b/drivers/gpu/drm/gma500/gma_display.c
index 24e8af3d22bfd..386de2c9dc864 100644
--- a/drivers/gpu/drm/gma500/gma_display.c
+++ b/drivers/gpu/drm/gma500/gma_display.c
@@ -349,6 +349,7 @@ int gma_crtc_cursor_set(struct drm_crtc *crtc,
 	/* If we didn't get a handle then turn the cursor off */
 	if (!handle) {
 		temp = CURSOR_MODE_DISABLE;
+		mutex_lock(&dev->struct_mutex);
 
 		if (gma_power_begin(dev, false)) {
 			REG_WRITE(control, temp);
@@ -365,6 +366,7 @@ int gma_crtc_cursor_set(struct drm_crtc *crtc,
 			gma_crtc->cursor_obj = NULL;
 		}
 
+		mutex_unlock(&dev->struct_mutex);
 		return 0;
 	}
 
@@ -374,9 +376,12 @@ int gma_crtc_cursor_set(struct drm_crtc *crtc,
 		return -EINVAL;
 	}
 
+	mutex_lock(&dev->struct_mutex);
 	obj = drm_gem_object_lookup(dev, file_priv, handle);
-	if (!obj)
-		return -ENOENT;
+	if (!obj) {
+		ret = -ENOENT;
+		goto unlock;
+	}
 
 	if (obj->size < width * height * 4) {
 		dev_dbg(dev->dev, "Buffer is too small\n");
@@ -440,10 +445,13 @@ int gma_crtc_cursor_set(struct drm_crtc *crtc,
 	}
 
 	gma_crtc->cursor_obj = obj;
+unlock:
+	mutex_unlock(&dev->struct_mutex);
 	return ret;
 
 unref_cursor:
 	drm_gem_object_unreference(obj);
+	mutex_unlock(&dev->struct_mutex);
 	return ret;
 }
 
diff --git a/drivers/gpu/drm/i915/i915_dma.c b/drivers/gpu/drm/i915/i915_dma.c
index ee9502b88df3e..258b1be20db3c 100644
--- a/drivers/gpu/drm/i915/i915_dma.c
+++ b/drivers/gpu/drm/i915/i915_dma.c
@@ -1685,6 +1685,7 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags)
 
 	intel_teardown_gmbus(dev);
 	intel_teardown_mchbar(dev);
+	pm_qos_remove_request(&dev_priv->pm_qos);
 	destroy_workqueue(dev_priv->wq);
 out_mtrrfree:
 	arch_phys_wc_del(dev_priv->gtt.mtrr);
diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index 118675c8cc300..ac5cd7ec1b460 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -331,6 +331,7 @@ struct drm_i915_error_state {
 	u64 fence[I915_MAX_NUM_FENCES];
 	struct timeval time;
 	struct drm_i915_error_ring {
+		bool valid;
 		struct drm_i915_error_object {
 			int page_count;
 			u32 gtt_offset;
diff --git a/drivers/gpu/drm/i915/i915_gem_stolen.c b/drivers/gpu/drm/i915/i915_gem_stolen.c
index fed87ec172119..1a24e84f23157 100644
--- a/drivers/gpu/drm/i915/i915_gem_stolen.c
+++ b/drivers/gpu/drm/i915/i915_gem_stolen.c
@@ -250,7 +250,7 @@ i915_pages_create_for_stolen(struct drm_device *dev,
 	}
 
 	sg = st->sgl;
-	sg->offset = offset;
+	sg->offset = 0;
 	sg->length = size;
 
 	sg_dma_address(sg) = (dma_addr_t)dev_priv->mm.stolen_base + offset;
diff --git a/drivers/gpu/drm/i915/i915_gpu_error.c b/drivers/gpu/drm/i915/i915_gpu_error.c
index 685f6ccbcc079..4cc916213362c 100644
--- a/drivers/gpu/drm/i915/i915_gpu_error.c
+++ b/drivers/gpu/drm/i915/i915_gpu_error.c
@@ -239,6 +239,9 @@ static void i915_ring_error_state(struct drm_i915_error_state_buf *m,
 				  unsigned ring)
 {
 	BUG_ON(ring >= I915_NUM_RINGS); /* shut up confused gcc */
+	if (!error->ring[ring].valid)
+		return;
+
 	err_printf(m, "%s command stream:\n", ring_str(ring));
 	err_printf(m, "  HEAD: 0x%08x\n", error->head[ring]);
 	err_printf(m, "  TAIL: 0x%08x\n", error->tail[ring]);
@@ -294,7 +297,6 @@ int i915_error_state_to_str(struct drm_i915_error_state_buf *m,
 	struct drm_device *dev = error_priv->dev;
 	drm_i915_private_t *dev_priv = dev->dev_private;
 	struct drm_i915_error_state *error = error_priv->error;
-	struct intel_ring_buffer *ring;
 	int i, j, page, offset, elt;
 
 	if (!error) {
@@ -329,7 +331,7 @@ int i915_error_state_to_str(struct drm_i915_error_state_buf *m,
 	if (INTEL_INFO(dev)->gen == 7)
 		err_printf(m, "ERR_INT: 0x%08x\n", error->err_int);
 
-	for_each_ring(ring, dev_priv, i)
+	for (i = 0; i < ARRAY_SIZE(error->ring); i++)
 		i915_ring_error_state(m, dev, error, i);
 
 	if (error->active_bo)
@@ -402,8 +404,7 @@ int i915_error_state_to_str(struct drm_i915_error_state_buf *m,
 			}
 		}
 
-		obj = error->ring[i].ctx;
-		if (obj) {
+		if ((obj = error->ring[i].ctx)) {
 			err_printf(m, "%s --- HW Context = 0x%08x\n",
 				   dev_priv->ring[i].name,
 				   obj->gtt_offset);
@@ -718,7 +719,8 @@ i915_error_first_batchbuffer(struct drm_i915_private *dev_priv,
 			return NULL;
 
 		obj = ring->scratch.obj;
-		if (acthd >= i915_gem_obj_ggtt_offset(obj) &&
+		if (obj != NULL &&
+		    acthd >= i915_gem_obj_ggtt_offset(obj) &&
 		    acthd < i915_gem_obj_ggtt_offset(obj) + obj->base.size)
 			return i915_error_ggtt_object_create(dev_priv, obj);
 	}
@@ -863,11 +865,17 @@ static void i915_gem_record_rings(struct drm_device *dev,
 				  struct drm_i915_error_state *error)
 {
 	struct drm_i915_private *dev_priv = dev->dev_private;
-	struct intel_ring_buffer *ring;
 	struct drm_i915_gem_request *request;
 	int i, count;
 
-	for_each_ring(ring, dev_priv, i) {
+	for (i = 0; i < I915_NUM_RINGS; i++) {
+		struct intel_ring_buffer *ring = &dev_priv->ring[i];
+
+		if (ring->dev == NULL)
+			continue;
+
+		error->ring[i].valid = true;
+
 		i915_record_ring_state(dev, error, ring);
 
 		error->ring[i].batchbuffer =
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index 122f87155b8e1..4d4a0d912b8eb 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -8753,28 +8753,6 @@ static struct drm_crtc_helper_funcs intel_helper_funcs = {
 	.load_lut = intel_crtc_load_lut,
 };
 
-static bool intel_encoder_crtc_ok(struct drm_encoder *encoder,
-				  struct drm_crtc *crtc)
-{
-	struct drm_device *dev;
-	struct drm_crtc *tmp;
-	int crtc_mask = 1;
-
-	WARN(!crtc, "checking null crtc?\n");
-
-	dev = crtc->dev;
-
-	list_for_each_entry(tmp, &dev->mode_config.crtc_list, head) {
-		if (tmp == crtc)
-			break;
-		crtc_mask <<= 1;
-	}
-
-	if (encoder->possible_crtcs & crtc_mask)
-		return true;
-	return false;
-}
-
 /**
  * intel_modeset_update_staged_output_state
  *
@@ -9987,8 +9965,8 @@ intel_modeset_stage_output_state(struct drm_device *dev,
 		}
 
 		/* Make sure the new CRTC will work with the encoder */
-		if (!intel_encoder_crtc_ok(&connector->new_encoder->base,
-					   new_crtc)) {
+		if (!drm_encoder_crtc_ok(&connector->new_encoder->base,
+					 new_crtc)) {
 			return -EINVAL;
 		}
 		connector->encoder->new_crtc = to_intel_crtc(new_crtc);
diff --git a/drivers/gpu/drm/mgag200/mgag200_fb.c b/drivers/gpu/drm/mgag200/mgag200_fb.c
index 964f58cee5ea6..f9adc27ef32a0 100644
--- a/drivers/gpu/drm/mgag200/mgag200_fb.c
+++ b/drivers/gpu/drm/mgag200/mgag200_fb.c
@@ -41,7 +41,7 @@ static void mga_dirty_update(struct mga_fbdev *mfbdev,
 	 * then the BO is being moved and we should
 	 * store up the damage until later.
 	 */
-	if (!in_interrupt())
+	if (!drm_can_sleep())
 		ret = mgag200_bo_reserve(bo, true);
 	if (ret) {
 		if (ret != -EBUSY)
@@ -282,6 +282,11 @@ int mgag200_fbdev_init(struct mga_device *mdev)
 {
 	struct mga_fbdev *mfbdev;
 	int ret;
+	int bpp_sel = 32;
+
+	/* prefer 16bpp on low end gpus with limited VRAM */
+	if (IS_G200_SE(mdev) && mdev->mc.vram_size < (2048*1024))
+		bpp_sel = 16;
 
 	mfbdev = devm_kzalloc(mdev->dev->dev, sizeof(struct mga_fbdev), GFP_KERNEL);
 	if (!mfbdev)
@@ -301,7 +306,7 @@ int mgag200_fbdev_init(struct mga_device *mdev)
 	/* disable all the possible outputs/crtcs before entering KMS mode */
 	drm_helper_disable_unused_functions(mdev->dev);
 
-	drm_fb_helper_initial_config(&mfbdev->helper, 32);
+	drm_fb_helper_initial_config(&mfbdev->helper, bpp_sel);
 
 	return 0;
 }
diff --git a/drivers/gpu/drm/mgag200/mgag200_main.c b/drivers/gpu/drm/mgag200/mgag200_main.c
index a1bfe72583647..26868e5c55b07 100644
--- a/drivers/gpu/drm/mgag200/mgag200_main.c
+++ b/drivers/gpu/drm/mgag200/mgag200_main.c
@@ -217,7 +217,10 @@ int mgag200_driver_load(struct drm_device *dev, unsigned long flags)
 
 	drm_mode_config_init(dev);
 	dev->mode_config.funcs = (void *)&mga_mode_funcs;
-	dev->mode_config.preferred_depth = 24;
+	if (IS_G200_SE(mdev) && mdev->mc.vram_size < (2048*1024))
+		dev->mode_config.preferred_depth = 16;
+	else
+		dev->mode_config.preferred_depth = 24;
 	dev->mode_config.prefer_shadow = 1;
 
 	r = mgag200_modeset_init(mdev);
diff --git a/drivers/gpu/drm/nouveau/Makefile b/drivers/gpu/drm/nouveau/Makefile
index b3fa1ba191b71..e88145ba1bf51 100644
--- a/drivers/gpu/drm/nouveau/Makefile
+++ b/drivers/gpu/drm/nouveau/Makefile
@@ -41,6 +41,7 @@ nouveau-y += core/subdev/bios/init.o
 nouveau-y += core/subdev/bios/mxm.o
 nouveau-y += core/subdev/bios/perf.o
 nouveau-y += core/subdev/bios/pll.o
+nouveau-y += core/subdev/bios/ramcfg.o
 nouveau-y += core/subdev/bios/rammap.o
 nouveau-y += core/subdev/bios/timing.o
 nouveau-y += core/subdev/bios/therm.o
@@ -71,7 +72,10 @@ nouveau-y += core/subdev/devinit/nv10.o
 nouveau-y += core/subdev/devinit/nv1a.o
 nouveau-y += core/subdev/devinit/nv20.o
 nouveau-y += core/subdev/devinit/nv50.o
+nouveau-y += core/subdev/devinit/nv84.o
+nouveau-y += core/subdev/devinit/nv98.o
 nouveau-y += core/subdev/devinit/nva3.o
+nouveau-y += core/subdev/devinit/nvaf.o
 nouveau-y += core/subdev/devinit/nvc0.o
 nouveau-y += core/subdev/fb/base.o
 nouveau-y += core/subdev/fb/nv04.o
@@ -232,6 +236,7 @@ nouveau-y += core/engine/fifo/nv50.o
 nouveau-y += core/engine/fifo/nv84.o
 nouveau-y += core/engine/fifo/nvc0.o
 nouveau-y += core/engine/fifo/nve0.o
+nouveau-y += core/engine/fifo/nv108.o
 nouveau-y += core/engine/graph/ctxnv40.o
 nouveau-y += core/engine/graph/ctxnv50.o
 nouveau-y += core/engine/graph/ctxnvc0.o
@@ -242,6 +247,7 @@ nouveau-y += core/engine/graph/ctxnvd7.o
 nouveau-y += core/engine/graph/ctxnvd9.o
 nouveau-y += core/engine/graph/ctxnve4.o
 nouveau-y += core/engine/graph/ctxnvf0.o
+nouveau-y += core/engine/graph/ctxnv108.o
 nouveau-y += core/engine/graph/nv04.o
 nouveau-y += core/engine/graph/nv10.o
 nouveau-y += core/engine/graph/nv20.o
@@ -260,6 +266,7 @@ nouveau-y += core/engine/graph/nvd7.o
 nouveau-y += core/engine/graph/nvd9.o
 nouveau-y += core/engine/graph/nve4.o
 nouveau-y += core/engine/graph/nvf0.o
+nouveau-y += core/engine/graph/nv108.o
 nouveau-y += core/engine/mpeg/nv31.o
 nouveau-y += core/engine/mpeg/nv40.o
 nouveau-y += core/engine/mpeg/nv44.o
diff --git a/drivers/gpu/drm/nouveau/core/core/engine.c b/drivers/gpu/drm/nouveau/core/core/engine.c
index c8bed4a268333..1f6954ae9dd36 100644
--- a/drivers/gpu/drm/nouveau/core/core/engine.c
+++ b/drivers/gpu/drm/nouveau/core/core/engine.c
@@ -42,11 +42,24 @@ nouveau_engine_create_(struct nouveau_object *parent,
 	if (ret)
 		return ret;
 
-	if ( parent &&
-	    !nouveau_boolopt(nv_device(parent)->cfgopt, iname, enable)) {
-		if (!enable)
-			nv_warn(engine, "disabled, %s=1 to enable\n", iname);
-		return -ENODEV;
+	if (parent) {
+		struct nouveau_device *device = nv_device(parent);
+		int engidx = nv_engidx(nv_object(engine));
+
+		if (device->disable_mask & (1ULL << engidx)) {
+			if (!nouveau_boolopt(device->cfgopt, iname, false)) {
+				nv_debug(engine, "engine disabled by hw/fw\n");
+				return -ENODEV;
+			}
+
+			nv_warn(engine, "ignoring hw/fw engine disable\n");
+		}
+
+		if (!nouveau_boolopt(device->cfgopt, iname, enable)) {
+			if (!enable)
+				nv_warn(engine, "disabled, %s=1 to enable\n", iname);
+			return -ENODEV;
+		}
 	}
 
 	INIT_LIST_HEAD(&engine->contexts);
diff --git a/drivers/gpu/drm/nouveau/core/engine/copy/nvc0.c b/drivers/gpu/drm/nouveau/core/engine/copy/nvc0.c
index 993df09ad6438..ac3291f781f6e 100644
--- a/drivers/gpu/drm/nouveau/core/engine/copy/nvc0.c
+++ b/drivers/gpu/drm/nouveau/core/engine/copy/nvc0.c
@@ -105,9 +105,6 @@ nvc0_copy0_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
 	struct nvc0_copy_priv *priv;
 	int ret;
 
-	if (nv_rd32(parent, 0x022500) & 0x00000100)
-		return -ENODEV;
-
 	ret = nouveau_falcon_create(parent, engine, oclass, 0x104000, true,
 				    "PCE0", "copy0", &priv);
 	*pobject = nv_object(priv);
@@ -133,9 +130,6 @@ nvc0_copy1_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
 	struct nvc0_copy_priv *priv;
 	int ret;
 
-	if (nv_rd32(parent, 0x022500) & 0x00000200)
-		return -ENODEV;
-
 	ret = nouveau_falcon_create(parent, engine, oclass, 0x105000, true,
 				    "PCE1", "copy1", &priv);
 	*pobject = nv_object(priv);
diff --git a/drivers/gpu/drm/nouveau/core/engine/copy/nve0.c b/drivers/gpu/drm/nouveau/core/engine/copy/nve0.c
index 30f1ef1edcc59..748a61eb3c6f2 100644
--- a/drivers/gpu/drm/nouveau/core/engine/copy/nve0.c
+++ b/drivers/gpu/drm/nouveau/core/engine/copy/nve0.c
@@ -88,9 +88,6 @@ nve0_copy0_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
 	struct nve0_copy_priv *priv;
 	int ret;
 
-	if (nv_rd32(parent, 0x022500) & 0x00000100)
-		return -ENODEV;
-
 	ret = nouveau_engine_create(parent, engine, oclass, true,
 				    "PCE0", "copy0", &priv);
 	*pobject = nv_object(priv);
@@ -112,9 +109,6 @@ nve0_copy1_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
 	struct nve0_copy_priv *priv;
 	int ret;
 
-	if (nv_rd32(parent, 0x022500) & 0x00000200)
-		return -ENODEV;
-
 	ret = nouveau_engine_create(parent, engine, oclass, true,
 				    "PCE1", "copy1", &priv);
 	*pobject = nv_object(priv);
diff --git a/drivers/gpu/drm/nouveau/core/engine/device/nv04.c b/drivers/gpu/drm/nouveau/core/engine/device/nv04.c
index dbd2dde7b7e76..32113b08c4d5f 100644
--- a/drivers/gpu/drm/nouveau/core/engine/device/nv04.c
+++ b/drivers/gpu/drm/nouveau/core/engine/device/nv04.c
@@ -49,12 +49,12 @@ nv04_identify(struct nouveau_device *device)
 		device->oclass[NVDEV_SUBDEV_VBIOS  ] = &nouveau_bios_oclass;
 		device->oclass[NVDEV_SUBDEV_I2C    ] = &nv04_i2c_oclass;
 		device->oclass[NVDEV_SUBDEV_CLOCK  ] = &nv04_clock_oclass;
-		device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv04_devinit_oclass;
+		device->oclass[NVDEV_SUBDEV_DEVINIT] =  nv04_devinit_oclass;
 		device->oclass[NVDEV_SUBDEV_MC     ] =  nv04_mc_oclass;
 		device->oclass[NVDEV_SUBDEV_BUS    ] =  nv04_bus_oclass;
 		device->oclass[NVDEV_SUBDEV_TIMER  ] = &nv04_timer_oclass;
 		device->oclass[NVDEV_SUBDEV_FB     ] =  nv04_fb_oclass;
-		device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv04_instmem_oclass;
+		device->oclass[NVDEV_SUBDEV_INSTMEM] =  nv04_instmem_oclass;
 		device->oclass[NVDEV_SUBDEV_VM     ] = &nv04_vmmgr_oclass;
 		device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nv04_dmaeng_oclass;
 		device->oclass[NVDEV_ENGINE_FIFO   ] =  nv04_fifo_oclass;
@@ -67,12 +67,12 @@ nv04_identify(struct nouveau_device *device)
 		device->oclass[NVDEV_SUBDEV_VBIOS  ] = &nouveau_bios_oclass;
 		device->oclass[NVDEV_SUBDEV_I2C    ] = &nv04_i2c_oclass;
 		device->oclass[NVDEV_SUBDEV_CLOCK  ] = &nv04_clock_oclass;
-		device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv05_devinit_oclass;
+		device->oclass[NVDEV_SUBDEV_DEVINIT] =  nv05_devinit_oclass;
 		device->oclass[NVDEV_SUBDEV_MC     ] =  nv04_mc_oclass;
 		device->oclass[NVDEV_SUBDEV_BUS    ] =  nv04_bus_oclass;
 		device->oclass[NVDEV_SUBDEV_TIMER  ] = &nv04_timer_oclass;
 		device->oclass[NVDEV_SUBDEV_FB     ] =  nv04_fb_oclass;
-		device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv04_instmem_oclass;
+		device->oclass[NVDEV_SUBDEV_INSTMEM] =  nv04_instmem_oclass;
 		device->oclass[NVDEV_SUBDEV_VM     ] = &nv04_vmmgr_oclass;
 		device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nv04_dmaeng_oclass;
 		device->oclass[NVDEV_ENGINE_FIFO   ] =  nv04_fifo_oclass;
diff --git a/drivers/gpu/drm/nouveau/core/engine/device/nv10.c b/drivers/gpu/drm/nouveau/core/engine/device/nv10.c
index 6e03dd6abeea5..744f15d7e1315 100644
--- a/drivers/gpu/drm/nouveau/core/engine/device/nv10.c
+++ b/drivers/gpu/drm/nouveau/core/engine/device/nv10.c
@@ -51,12 +51,12 @@ nv10_identify(struct nouveau_device *device)
 		device->oclass[NVDEV_SUBDEV_GPIO   ] = &nv10_gpio_oclass;
 		device->oclass[NVDEV_SUBDEV_I2C    ] = &nv04_i2c_oclass;
 		device->oclass[NVDEV_SUBDEV_CLOCK  ] = &nv04_clock_oclass;
-		device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv10_devinit_oclass;
+		device->oclass[NVDEV_SUBDEV_DEVINIT] =  nv10_devinit_oclass;
 		device->oclass[NVDEV_SUBDEV_MC     ] =  nv04_mc_oclass;
 		device->oclass[NVDEV_SUBDEV_BUS    ] =  nv04_bus_oclass;
 		device->oclass[NVDEV_SUBDEV_TIMER  ] = &nv04_timer_oclass;
 		device->oclass[NVDEV_SUBDEV_FB     ] =  nv10_fb_oclass;
-		device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv04_instmem_oclass;
+		device->oclass[NVDEV_SUBDEV_INSTMEM] =  nv04_instmem_oclass;
 		device->oclass[NVDEV_SUBDEV_VM     ] = &nv04_vmmgr_oclass;
 		device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nv04_dmaeng_oclass;
 		device->oclass[NVDEV_ENGINE_GR     ] = &nv10_graph_oclass;
@@ -68,12 +68,12 @@ nv10_identify(struct nouveau_device *device)
 		device->oclass[NVDEV_SUBDEV_GPIO   ] = &nv10_gpio_oclass;
 		device->oclass[NVDEV_SUBDEV_I2C    ] = &nv04_i2c_oclass;
 		device->oclass[NVDEV_SUBDEV_CLOCK  ] = &nv04_clock_oclass;
-		device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv10_devinit_oclass;
+		device->oclass[NVDEV_SUBDEV_DEVINIT] =  nv10_devinit_oclass;
 		device->oclass[NVDEV_SUBDEV_MC     ] =  nv04_mc_oclass;
 		device->oclass[NVDEV_SUBDEV_BUS    ] =  nv04_bus_oclass;
 		device->oclass[NVDEV_SUBDEV_TIMER  ] = &nv04_timer_oclass;
 		device->oclass[NVDEV_SUBDEV_FB     ] =  nv10_fb_oclass;
-		device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv04_instmem_oclass;
+		device->oclass[NVDEV_SUBDEV_INSTMEM] =  nv04_instmem_oclass;
 		device->oclass[NVDEV_SUBDEV_VM     ] = &nv04_vmmgr_oclass;
 		device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nv04_dmaeng_oclass;
 		device->oclass[NVDEV_ENGINE_FIFO   ] =  nv10_fifo_oclass;
@@ -87,12 +87,12 @@ nv10_identify(struct nouveau_device *device)
 		device->oclass[NVDEV_SUBDEV_GPIO   ] = &nv10_gpio_oclass;
 		device->oclass[NVDEV_SUBDEV_I2C    ] = &nv04_i2c_oclass;
 		device->oclass[NVDEV_SUBDEV_CLOCK  ] = &nv04_clock_oclass;
-		device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv10_devinit_oclass;
+		device->oclass[NVDEV_SUBDEV_DEVINIT] =  nv10_devinit_oclass;
 		device->oclass[NVDEV_SUBDEV_MC     ] =  nv04_mc_oclass;
 		device->oclass[NVDEV_SUBDEV_BUS    ] =  nv04_bus_oclass;
 		device->oclass[NVDEV_SUBDEV_TIMER  ] = &nv04_timer_oclass;
 		device->oclass[NVDEV_SUBDEV_FB     ] =  nv10_fb_oclass;
-		device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv04_instmem_oclass;
+		device->oclass[NVDEV_SUBDEV_INSTMEM] =  nv04_instmem_oclass;
 		device->oclass[NVDEV_SUBDEV_VM     ] = &nv04_vmmgr_oclass;
 		device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nv04_dmaeng_oclass;
 		device->oclass[NVDEV_ENGINE_FIFO   ] =  nv10_fifo_oclass;
@@ -106,12 +106,12 @@ nv10_identify(struct nouveau_device *device)
 		device->oclass[NVDEV_SUBDEV_GPIO   ] = &nv10_gpio_oclass;
 		device->oclass[NVDEV_SUBDEV_I2C    ] = &nv04_i2c_oclass;
 		device->oclass[NVDEV_SUBDEV_CLOCK  ] = &nv04_clock_oclass;
-		device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv1a_devinit_oclass;
+		device->oclass[NVDEV_SUBDEV_DEVINIT] =  nv1a_devinit_oclass;
 		device->oclass[NVDEV_SUBDEV_MC     ] =  nv04_mc_oclass;
 		device->oclass[NVDEV_SUBDEV_BUS    ] =  nv04_bus_oclass;
 		device->oclass[NVDEV_SUBDEV_TIMER  ] = &nv04_timer_oclass;
 		device->oclass[NVDEV_SUBDEV_FB     ] =  nv1a_fb_oclass;
-		device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv04_instmem_oclass;
+		device->oclass[NVDEV_SUBDEV_INSTMEM] =  nv04_instmem_oclass;
 		device->oclass[NVDEV_SUBDEV_VM     ] = &nv04_vmmgr_oclass;
 		device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nv04_dmaeng_oclass;
 		device->oclass[NVDEV_ENGINE_FIFO   ] =  nv10_fifo_oclass;
@@ -125,12 +125,12 @@ nv10_identify(struct nouveau_device *device)
 		device->oclass[NVDEV_SUBDEV_GPIO   ] = &nv10_gpio_oclass;
 		device->oclass[NVDEV_SUBDEV_I2C    ] = &nv04_i2c_oclass;
 		device->oclass[NVDEV_SUBDEV_CLOCK  ] = &nv04_clock_oclass;
-		device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv10_devinit_oclass;
+		device->oclass[NVDEV_SUBDEV_DEVINIT] =  nv10_devinit_oclass;
 		device->oclass[NVDEV_SUBDEV_MC     ] =  nv04_mc_oclass;
 		device->oclass[NVDEV_SUBDEV_BUS    ] =  nv04_bus_oclass;
 		device->oclass[NVDEV_SUBDEV_TIMER  ] = &nv04_timer_oclass;
 		device->oclass[NVDEV_SUBDEV_FB     ] =  nv10_fb_oclass;
-		device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv04_instmem_oclass;
+		device->oclass[NVDEV_SUBDEV_INSTMEM] =  nv04_instmem_oclass;
 		device->oclass[NVDEV_SUBDEV_VM     ] = &nv04_vmmgr_oclass;
 		device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nv04_dmaeng_oclass;
 		device->oclass[NVDEV_ENGINE_FIFO   ] =  nv10_fifo_oclass;
@@ -144,12 +144,12 @@ nv10_identify(struct nouveau_device *device)
 		device->oclass[NVDEV_SUBDEV_GPIO   ] = &nv10_gpio_oclass;
 		device->oclass[NVDEV_SUBDEV_I2C    ] = &nv04_i2c_oclass;
 		device->oclass[NVDEV_SUBDEV_CLOCK  ] = &nv04_clock_oclass;
-		device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv10_devinit_oclass;
+		device->oclass[NVDEV_SUBDEV_DEVINIT] =  nv10_devinit_oclass;
 		device->oclass[NVDEV_SUBDEV_MC     ] =  nv04_mc_oclass;
 		device->oclass[NVDEV_SUBDEV_BUS    ] =  nv04_bus_oclass;
 		device->oclass[NVDEV_SUBDEV_TIMER  ] = &nv04_timer_oclass;
 		device->oclass[NVDEV_SUBDEV_FB     ] =  nv10_fb_oclass;
-		device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv04_instmem_oclass;
+		device->oclass[NVDEV_SUBDEV_INSTMEM] =  nv04_instmem_oclass;
 		device->oclass[NVDEV_SUBDEV_VM     ] = &nv04_vmmgr_oclass;
 		device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nv04_dmaeng_oclass;
 		device->oclass[NVDEV_ENGINE_FIFO   ] =  nv17_fifo_oclass;
@@ -163,12 +163,12 @@ nv10_identify(struct nouveau_device *device)
 		device->oclass[NVDEV_SUBDEV_GPIO   ] = &nv10_gpio_oclass;
 		device->oclass[NVDEV_SUBDEV_I2C    ] = &nv04_i2c_oclass;
 		device->oclass[NVDEV_SUBDEV_CLOCK  ] = &nv04_clock_oclass;
-		device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv1a_devinit_oclass;
+		device->oclass[NVDEV_SUBDEV_DEVINIT] =  nv1a_devinit_oclass;
 		device->oclass[NVDEV_SUBDEV_MC     ] =  nv04_mc_oclass;
 		device->oclass[NVDEV_SUBDEV_BUS    ] =  nv04_bus_oclass;
 		device->oclass[NVDEV_SUBDEV_TIMER  ] = &nv04_timer_oclass;
 		device->oclass[NVDEV_SUBDEV_FB     ] =  nv1a_fb_oclass;
-		device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv04_instmem_oclass;
+		device->oclass[NVDEV_SUBDEV_INSTMEM] =  nv04_instmem_oclass;
 		device->oclass[NVDEV_SUBDEV_VM     ] = &nv04_vmmgr_oclass;
 		device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nv04_dmaeng_oclass;
 		device->oclass[NVDEV_ENGINE_FIFO   ] =  nv17_fifo_oclass;
@@ -182,12 +182,12 @@ nv10_identify(struct nouveau_device *device)
 		device->oclass[NVDEV_SUBDEV_GPIO   ] = &nv10_gpio_oclass;
 		device->oclass[NVDEV_SUBDEV_I2C    ] = &nv04_i2c_oclass;
 		device->oclass[NVDEV_SUBDEV_CLOCK  ] = &nv04_clock_oclass;
-		device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv10_devinit_oclass;
+		device->oclass[NVDEV_SUBDEV_DEVINIT] =  nv10_devinit_oclass;
 		device->oclass[NVDEV_SUBDEV_MC     ] =  nv04_mc_oclass;
 		device->oclass[NVDEV_SUBDEV_BUS    ] =  nv04_bus_oclass;
 		device->oclass[NVDEV_SUBDEV_TIMER  ] = &nv04_timer_oclass;
 		device->oclass[NVDEV_SUBDEV_FB     ] =  nv10_fb_oclass;
-		device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv04_instmem_oclass;
+		device->oclass[NVDEV_SUBDEV_INSTMEM] =  nv04_instmem_oclass;
 		device->oclass[NVDEV_SUBDEV_VM     ] = &nv04_vmmgr_oclass;
 		device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nv04_dmaeng_oclass;
 		device->oclass[NVDEV_ENGINE_FIFO   ] =  nv17_fifo_oclass;
diff --git a/drivers/gpu/drm/nouveau/core/engine/device/nv20.c b/drivers/gpu/drm/nouveau/core/engine/device/nv20.c
index dcde53b9f07f7..27ba61fb27104 100644
--- a/drivers/gpu/drm/nouveau/core/engine/device/nv20.c
+++ b/drivers/gpu/drm/nouveau/core/engine/device/nv20.c
@@ -52,12 +52,12 @@ nv20_identify(struct nouveau_device *device)
 		device->oclass[NVDEV_SUBDEV_GPIO   ] = &nv10_gpio_oclass;
 		device->oclass[NVDEV_SUBDEV_I2C    ] = &nv04_i2c_oclass;
 		device->oclass[NVDEV_SUBDEV_CLOCK  ] = &nv04_clock_oclass;
-		device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv20_devinit_oclass;
+		device->oclass[NVDEV_SUBDEV_DEVINIT] =  nv20_devinit_oclass;
 		device->oclass[NVDEV_SUBDEV_MC     ] =  nv04_mc_oclass;
 		device->oclass[NVDEV_SUBDEV_BUS    ] =  nv04_bus_oclass;
 		device->oclass[NVDEV_SUBDEV_TIMER  ] = &nv04_timer_oclass;
 		device->oclass[NVDEV_SUBDEV_FB     ] =  nv20_fb_oclass;
-		device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv04_instmem_oclass;
+		device->oclass[NVDEV_SUBDEV_INSTMEM] =  nv04_instmem_oclass;
 		device->oclass[NVDEV_SUBDEV_VM     ] = &nv04_vmmgr_oclass;
 		device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nv04_dmaeng_oclass;
 		device->oclass[NVDEV_ENGINE_FIFO   ] =  nv17_fifo_oclass;
@@ -71,12 +71,12 @@ nv20_identify(struct nouveau_device *device)
 		device->oclass[NVDEV_SUBDEV_GPIO   ] = &nv10_gpio_oclass;
 		device->oclass[NVDEV_SUBDEV_I2C    ] = &nv04_i2c_oclass;
 		device->oclass[NVDEV_SUBDEV_CLOCK  ] = &nv04_clock_oclass;
-		device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv20_devinit_oclass;
+		device->oclass[NVDEV_SUBDEV_DEVINIT] =  nv20_devinit_oclass;
 		device->oclass[NVDEV_SUBDEV_MC     ] =  nv04_mc_oclass;
 		device->oclass[NVDEV_SUBDEV_BUS    ] =  nv04_bus_oclass;
 		device->oclass[NVDEV_SUBDEV_TIMER  ] = &nv04_timer_oclass;
 		device->oclass[NVDEV_SUBDEV_FB     ] =  nv25_fb_oclass;
-		device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv04_instmem_oclass;
+		device->oclass[NVDEV_SUBDEV_INSTMEM] =  nv04_instmem_oclass;
 		device->oclass[NVDEV_SUBDEV_VM     ] = &nv04_vmmgr_oclass;
 		device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nv04_dmaeng_oclass;
 		device->oclass[NVDEV_ENGINE_FIFO   ] =  nv17_fifo_oclass;
@@ -90,12 +90,12 @@ nv20_identify(struct nouveau_device *device)
 		device->oclass[NVDEV_SUBDEV_GPIO   ] = &nv10_gpio_oclass;
 		device->oclass[NVDEV_SUBDEV_I2C    ] = &nv04_i2c_oclass;
 		device->oclass[NVDEV_SUBDEV_CLOCK  ] = &nv04_clock_oclass;
-		device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv20_devinit_oclass;
+		device->oclass[NVDEV_SUBDEV_DEVINIT] =  nv20_devinit_oclass;
 		device->oclass[NVDEV_SUBDEV_MC     ] =  nv04_mc_oclass;
 		device->oclass[NVDEV_SUBDEV_BUS    ] =  nv04_bus_oclass;
 		device->oclass[NVDEV_SUBDEV_TIMER  ] = &nv04_timer_oclass;
 		device->oclass[NVDEV_SUBDEV_FB     ] =  nv25_fb_oclass;
-		device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv04_instmem_oclass;
+		device->oclass[NVDEV_SUBDEV_INSTMEM] =  nv04_instmem_oclass;
 		device->oclass[NVDEV_SUBDEV_VM     ] = &nv04_vmmgr_oclass;
 		device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nv04_dmaeng_oclass;
 		device->oclass[NVDEV_ENGINE_FIFO   ] =  nv17_fifo_oclass;
@@ -109,12 +109,12 @@ nv20_identify(struct nouveau_device *device)
 		device->oclass[NVDEV_SUBDEV_GPIO   ] = &nv10_gpio_oclass;
 		device->oclass[NVDEV_SUBDEV_I2C    ] = &nv04_i2c_oclass;
 		device->oclass[NVDEV_SUBDEV_CLOCK  ] = &nv04_clock_oclass;
-		device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv20_devinit_oclass;
+		device->oclass[NVDEV_SUBDEV_DEVINIT] =  nv20_devinit_oclass;
 		device->oclass[NVDEV_SUBDEV_MC     ] =  nv04_mc_oclass;
 		device->oclass[NVDEV_SUBDEV_BUS    ] =  nv04_bus_oclass;
 		device->oclass[NVDEV_SUBDEV_TIMER  ] = &nv04_timer_oclass;
 		device->oclass[NVDEV_SUBDEV_FB     ] =  nv25_fb_oclass;
-		device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv04_instmem_oclass;
+		device->oclass[NVDEV_SUBDEV_INSTMEM] =  nv04_instmem_oclass;
 		device->oclass[NVDEV_SUBDEV_VM     ] = &nv04_vmmgr_oclass;
 		device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nv04_dmaeng_oclass;
 		device->oclass[NVDEV_ENGINE_FIFO   ] =  nv17_fifo_oclass;
diff --git a/drivers/gpu/drm/nouveau/core/engine/device/nv30.c b/drivers/gpu/drm/nouveau/core/engine/device/nv30.c
index 7b8662ef4f591..fd47ace67543c 100644
--- a/drivers/gpu/drm/nouveau/core/engine/device/nv30.c
+++ b/drivers/gpu/drm/nouveau/core/engine/device/nv30.c
@@ -52,12 +52,12 @@ nv30_identify(struct nouveau_device *device)
 		device->oclass[NVDEV_SUBDEV_GPIO   ] = &nv10_gpio_oclass;
 		device->oclass[NVDEV_SUBDEV_I2C    ] = &nv04_i2c_oclass;
 		device->oclass[NVDEV_SUBDEV_CLOCK  ] = &nv04_clock_oclass;
-		device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv20_devinit_oclass;
+		device->oclass[NVDEV_SUBDEV_DEVINIT] =  nv20_devinit_oclass;
 		device->oclass[NVDEV_SUBDEV_MC     ] =  nv04_mc_oclass;
 		device->oclass[NVDEV_SUBDEV_BUS    ] =  nv04_bus_oclass;
 		device->oclass[NVDEV_SUBDEV_TIMER  ] = &nv04_timer_oclass;
 		device->oclass[NVDEV_SUBDEV_FB     ] =  nv30_fb_oclass;
-		device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv04_instmem_oclass;
+		device->oclass[NVDEV_SUBDEV_INSTMEM] =  nv04_instmem_oclass;
 		device->oclass[NVDEV_SUBDEV_VM     ] = &nv04_vmmgr_oclass;
 		device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nv04_dmaeng_oclass;
 		device->oclass[NVDEV_ENGINE_FIFO   ] =  nv17_fifo_oclass;
@@ -71,12 +71,12 @@ nv30_identify(struct nouveau_device *device)
 		device->oclass[NVDEV_SUBDEV_GPIO   ] = &nv10_gpio_oclass;
 		device->oclass[NVDEV_SUBDEV_I2C    ] = &nv04_i2c_oclass;
 		device->oclass[NVDEV_SUBDEV_CLOCK  ] = &nv04_clock_oclass;
-		device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv20_devinit_oclass;
+		device->oclass[NVDEV_SUBDEV_DEVINIT] =  nv20_devinit_oclass;
 		device->oclass[NVDEV_SUBDEV_MC     ] =  nv04_mc_oclass;
 		device->oclass[NVDEV_SUBDEV_BUS    ] =  nv04_bus_oclass;
 		device->oclass[NVDEV_SUBDEV_TIMER  ] = &nv04_timer_oclass;
 		device->oclass[NVDEV_SUBDEV_FB     ] =  nv35_fb_oclass;
-		device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv04_instmem_oclass;
+		device->oclass[NVDEV_SUBDEV_INSTMEM] =  nv04_instmem_oclass;
 		device->oclass[NVDEV_SUBDEV_VM     ] = &nv04_vmmgr_oclass;
 		device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nv04_dmaeng_oclass;
 		device->oclass[NVDEV_ENGINE_FIFO   ] =  nv17_fifo_oclass;
@@ -90,12 +90,12 @@ nv30_identify(struct nouveau_device *device)
 		device->oclass[NVDEV_SUBDEV_GPIO   ] = &nv10_gpio_oclass;
 		device->oclass[NVDEV_SUBDEV_I2C    ] = &nv04_i2c_oclass;
 		device->oclass[NVDEV_SUBDEV_CLOCK  ] = &nv04_clock_oclass;
-		device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv20_devinit_oclass;
+		device->oclass[NVDEV_SUBDEV_DEVINIT] =  nv20_devinit_oclass;
 		device->oclass[NVDEV_SUBDEV_MC     ] =  nv04_mc_oclass;
 		device->oclass[NVDEV_SUBDEV_BUS    ] =  nv31_bus_oclass;
 		device->oclass[NVDEV_SUBDEV_TIMER  ] = &nv04_timer_oclass;
 		device->oclass[NVDEV_SUBDEV_FB     ] =  nv30_fb_oclass;
-		device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv04_instmem_oclass;
+		device->oclass[NVDEV_SUBDEV_INSTMEM] =  nv04_instmem_oclass;
 		device->oclass[NVDEV_SUBDEV_VM     ] = &nv04_vmmgr_oclass;
 		device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nv04_dmaeng_oclass;
 		device->oclass[NVDEV_ENGINE_FIFO   ] =  nv17_fifo_oclass;
@@ -110,12 +110,12 @@ nv30_identify(struct nouveau_device *device)
 		device->oclass[NVDEV_SUBDEV_GPIO   ] = &nv10_gpio_oclass;
 		device->oclass[NVDEV_SUBDEV_I2C    ] = &nv04_i2c_oclass;
 		device->oclass[NVDEV_SUBDEV_CLOCK  ] = &nv04_clock_oclass;
-		device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv20_devinit_oclass;
+		device->oclass[NVDEV_SUBDEV_DEVINIT] =  nv20_devinit_oclass;
 		device->oclass[NVDEV_SUBDEV_MC     ] =  nv04_mc_oclass;
 		device->oclass[NVDEV_SUBDEV_BUS    ] =  nv31_bus_oclass;
 		device->oclass[NVDEV_SUBDEV_TIMER  ] = &nv04_timer_oclass;
 		device->oclass[NVDEV_SUBDEV_FB     ] =  nv36_fb_oclass;
-		device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv04_instmem_oclass;
+		device->oclass[NVDEV_SUBDEV_INSTMEM] =  nv04_instmem_oclass;
 		device->oclass[NVDEV_SUBDEV_VM     ] = &nv04_vmmgr_oclass;
 		device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nv04_dmaeng_oclass;
 		device->oclass[NVDEV_ENGINE_FIFO   ] =  nv17_fifo_oclass;
@@ -130,12 +130,12 @@ nv30_identify(struct nouveau_device *device)
 		device->oclass[NVDEV_SUBDEV_GPIO   ] = &nv10_gpio_oclass;
 		device->oclass[NVDEV_SUBDEV_I2C    ] = &nv04_i2c_oclass;
 		device->oclass[NVDEV_SUBDEV_CLOCK  ] = &nv04_clock_oclass;
-		device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv10_devinit_oclass;
+		device->oclass[NVDEV_SUBDEV_DEVINIT] =  nv10_devinit_oclass;
 		device->oclass[NVDEV_SUBDEV_MC     ] =  nv04_mc_oclass;
 		device->oclass[NVDEV_SUBDEV_BUS    ] =  nv31_bus_oclass;
 		device->oclass[NVDEV_SUBDEV_TIMER  ] = &nv04_timer_oclass;
 		device->oclass[NVDEV_SUBDEV_FB     ] =  nv10_fb_oclass;
-		device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv04_instmem_oclass;
+		device->oclass[NVDEV_SUBDEV_INSTMEM] =  nv04_instmem_oclass;
 		device->oclass[NVDEV_SUBDEV_VM     ] = &nv04_vmmgr_oclass;
 		device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nv04_dmaeng_oclass;
 		device->oclass[NVDEV_ENGINE_FIFO   ] =  nv17_fifo_oclass;
diff --git a/drivers/gpu/drm/nouveau/core/engine/device/nv40.c b/drivers/gpu/drm/nouveau/core/engine/device/nv40.c
index c8c41e93695ee..1b653dd74a704 100644
--- a/drivers/gpu/drm/nouveau/core/engine/device/nv40.c
+++ b/drivers/gpu/drm/nouveau/core/engine/device/nv40.c
@@ -57,12 +57,12 @@ nv40_identify(struct nouveau_device *device)
 		device->oclass[NVDEV_SUBDEV_I2C    ] = &nv04_i2c_oclass;
 		device->oclass[NVDEV_SUBDEV_CLOCK  ] = &nv40_clock_oclass;
 		device->oclass[NVDEV_SUBDEV_THERM  ] = &nv40_therm_oclass;
-		device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv1a_devinit_oclass;
+		device->oclass[NVDEV_SUBDEV_DEVINIT] =  nv1a_devinit_oclass;
 		device->oclass[NVDEV_SUBDEV_MC     ] =  nv40_mc_oclass;
 		device->oclass[NVDEV_SUBDEV_BUS    ] =  nv31_bus_oclass;
 		device->oclass[NVDEV_SUBDEV_TIMER  ] = &nv04_timer_oclass;
 		device->oclass[NVDEV_SUBDEV_FB     ] =  nv40_fb_oclass;
-		device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv40_instmem_oclass;
+		device->oclass[NVDEV_SUBDEV_INSTMEM] =  nv40_instmem_oclass;
 		device->oclass[NVDEV_SUBDEV_VM     ] = &nv04_vmmgr_oclass;
 		device->oclass[NVDEV_SUBDEV_VOLT   ] = &nv40_volt_oclass;
 		device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nv04_dmaeng_oclass;
@@ -80,12 +80,12 @@ nv40_identify(struct nouveau_device *device)
 		device->oclass[NVDEV_SUBDEV_I2C    ] = &nv04_i2c_oclass;
 		device->oclass[NVDEV_SUBDEV_CLOCK  ] = &nv40_clock_oclass;
 		device->oclass[NVDEV_SUBDEV_THERM  ] = &nv40_therm_oclass;
-		device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv1a_devinit_oclass;
+		device->oclass[NVDEV_SUBDEV_DEVINIT] =  nv1a_devinit_oclass;
 		device->oclass[NVDEV_SUBDEV_MC     ] =  nv40_mc_oclass;
 		device->oclass[NVDEV_SUBDEV_BUS    ] =  nv31_bus_oclass;
 		device->oclass[NVDEV_SUBDEV_TIMER  ] = &nv04_timer_oclass;
 		device->oclass[NVDEV_SUBDEV_FB     ] =  nv41_fb_oclass;
-		device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv40_instmem_oclass;
+		device->oclass[NVDEV_SUBDEV_INSTMEM] =  nv40_instmem_oclass;
 		device->oclass[NVDEV_SUBDEV_VM     ] = &nv41_vmmgr_oclass;
 		device->oclass[NVDEV_SUBDEV_VOLT   ] = &nv40_volt_oclass;
 		device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nv04_dmaeng_oclass;
@@ -103,12 +103,12 @@ nv40_identify(struct nouveau_device *device)
 		device->oclass[NVDEV_SUBDEV_I2C    ] = &nv04_i2c_oclass;
 		device->oclass[NVDEV_SUBDEV_CLOCK  ] = &nv40_clock_oclass;
 		device->oclass[NVDEV_SUBDEV_THERM  ] = &nv40_therm_oclass;
-		device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv1a_devinit_oclass;
+		device->oclass[NVDEV_SUBDEV_DEVINIT] =  nv1a_devinit_oclass;
 		device->oclass[NVDEV_SUBDEV_MC     ] =  nv40_mc_oclass;
 		device->oclass[NVDEV_SUBDEV_BUS    ] =  nv31_bus_oclass;
 		device->oclass[NVDEV_SUBDEV_TIMER  ] = &nv04_timer_oclass;
 		device->oclass[NVDEV_SUBDEV_FB     ] =  nv41_fb_oclass;
-		device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv40_instmem_oclass;
+		device->oclass[NVDEV_SUBDEV_INSTMEM] =  nv40_instmem_oclass;
 		device->oclass[NVDEV_SUBDEV_VM     ] = &nv41_vmmgr_oclass;
 		device->oclass[NVDEV_SUBDEV_VOLT   ] = &nv40_volt_oclass;
 		device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nv04_dmaeng_oclass;
@@ -126,12 +126,12 @@ nv40_identify(struct nouveau_device *device)
 		device->oclass[NVDEV_SUBDEV_I2C    ] = &nv04_i2c_oclass;
 		device->oclass[NVDEV_SUBDEV_CLOCK  ] = &nv40_clock_oclass;
 		device->oclass[NVDEV_SUBDEV_THERM  ] = &nv40_therm_oclass;
-		device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv1a_devinit_oclass;
+		device->oclass[NVDEV_SUBDEV_DEVINIT] =  nv1a_devinit_oclass;
 		device->oclass[NVDEV_SUBDEV_MC     ] =  nv40_mc_oclass;
 		device->oclass[NVDEV_SUBDEV_BUS    ] =  nv31_bus_oclass;
 		device->oclass[NVDEV_SUBDEV_TIMER  ] = &nv04_timer_oclass;
 		device->oclass[NVDEV_SUBDEV_FB     ] =  nv41_fb_oclass;
-		device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv40_instmem_oclass;
+		device->oclass[NVDEV_SUBDEV_INSTMEM] =  nv40_instmem_oclass;
 		device->oclass[NVDEV_SUBDEV_VM     ] = &nv41_vmmgr_oclass;
 		device->oclass[NVDEV_SUBDEV_VOLT   ] = &nv40_volt_oclass;
 		device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nv04_dmaeng_oclass;
@@ -149,12 +149,12 @@ nv40_identify(struct nouveau_device *device)
 		device->oclass[NVDEV_SUBDEV_I2C    ] = &nv04_i2c_oclass;
 		device->oclass[NVDEV_SUBDEV_CLOCK  ] = &nv40_clock_oclass;
 		device->oclass[NVDEV_SUBDEV_THERM  ] = &nv40_therm_oclass;
-		device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv1a_devinit_oclass;
+		device->oclass[NVDEV_SUBDEV_DEVINIT] =  nv1a_devinit_oclass;
 		device->oclass[NVDEV_SUBDEV_MC     ] =  nv40_mc_oclass;
 		device->oclass[NVDEV_SUBDEV_BUS    ] =  nv31_bus_oclass;
 		device->oclass[NVDEV_SUBDEV_TIMER  ] = &nv04_timer_oclass;
 		device->oclass[NVDEV_SUBDEV_FB     ] =  nv40_fb_oclass;
-		device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv40_instmem_oclass;
+		device->oclass[NVDEV_SUBDEV_INSTMEM] =  nv40_instmem_oclass;
 		device->oclass[NVDEV_SUBDEV_VM     ] = &nv04_vmmgr_oclass;
 		device->oclass[NVDEV_SUBDEV_VOLT   ] = &nv40_volt_oclass;
 		device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nv04_dmaeng_oclass;
@@ -172,12 +172,12 @@ nv40_identify(struct nouveau_device *device)
 		device->oclass[NVDEV_SUBDEV_I2C    ] = &nv04_i2c_oclass;
 		device->oclass[NVDEV_SUBDEV_CLOCK  ] = &nv40_clock_oclass;
 		device->oclass[NVDEV_SUBDEV_THERM  ] = &nv40_therm_oclass;
-		device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv1a_devinit_oclass;
+		device->oclass[NVDEV_SUBDEV_DEVINIT] =  nv1a_devinit_oclass;
 		device->oclass[NVDEV_SUBDEV_MC     ] =  nv40_mc_oclass;
 		device->oclass[NVDEV_SUBDEV_BUS    ] =  nv31_bus_oclass;
 		device->oclass[NVDEV_SUBDEV_TIMER  ] = &nv04_timer_oclass;
 		device->oclass[NVDEV_SUBDEV_FB     ] =  nv47_fb_oclass;
-		device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv40_instmem_oclass;
+		device->oclass[NVDEV_SUBDEV_INSTMEM] =  nv40_instmem_oclass;
 		device->oclass[NVDEV_SUBDEV_VM     ] = &nv41_vmmgr_oclass;
 		device->oclass[NVDEV_SUBDEV_VOLT   ] = &nv40_volt_oclass;
 		device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nv04_dmaeng_oclass;
@@ -195,12 +195,12 @@ nv40_identify(struct nouveau_device *device)
 		device->oclass[NVDEV_SUBDEV_I2C    ] = &nv04_i2c_oclass;
 		device->oclass[NVDEV_SUBDEV_CLOCK  ] = &nv40_clock_oclass;
 		device->oclass[NVDEV_SUBDEV_THERM  ] = &nv40_therm_oclass;
-		device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv1a_devinit_oclass;
+		device->oclass[NVDEV_SUBDEV_DEVINIT] =  nv1a_devinit_oclass;
 		device->oclass[NVDEV_SUBDEV_MC     ] =  nv40_mc_oclass;
 		device->oclass[NVDEV_SUBDEV_BUS    ] =  nv31_bus_oclass;
 		device->oclass[NVDEV_SUBDEV_TIMER  ] = &nv04_timer_oclass;
 		device->oclass[NVDEV_SUBDEV_FB     ] =  nv49_fb_oclass;
-		device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv40_instmem_oclass;
+		device->oclass[NVDEV_SUBDEV_INSTMEM] =  nv40_instmem_oclass;
 		device->oclass[NVDEV_SUBDEV_VM     ] = &nv41_vmmgr_oclass;
 		device->oclass[NVDEV_SUBDEV_VOLT   ] = &nv40_volt_oclass;
 		device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nv04_dmaeng_oclass;
@@ -218,12 +218,12 @@ nv40_identify(struct nouveau_device *device)
 		device->oclass[NVDEV_SUBDEV_I2C    ] = &nv04_i2c_oclass;
 		device->oclass[NVDEV_SUBDEV_CLOCK  ] = &nv40_clock_oclass;
 		device->oclass[NVDEV_SUBDEV_THERM  ] = &nv40_therm_oclass;
-		device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv1a_devinit_oclass;
+		device->oclass[NVDEV_SUBDEV_DEVINIT] =  nv1a_devinit_oclass;
 		device->oclass[NVDEV_SUBDEV_MC     ] =  nv40_mc_oclass;
 		device->oclass[NVDEV_SUBDEV_BUS    ] =  nv31_bus_oclass;
 		device->oclass[NVDEV_SUBDEV_TIMER  ] = &nv04_timer_oclass;
 		device->oclass[NVDEV_SUBDEV_FB     ] =  nv49_fb_oclass;
-		device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv40_instmem_oclass;
+		device->oclass[NVDEV_SUBDEV_INSTMEM] =  nv40_instmem_oclass;
 		device->oclass[NVDEV_SUBDEV_VM     ] = &nv41_vmmgr_oclass;
 		device->oclass[NVDEV_SUBDEV_VOLT   ] = &nv40_volt_oclass;
 		device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nv04_dmaeng_oclass;
@@ -241,12 +241,12 @@ nv40_identify(struct nouveau_device *device)
 		device->oclass[NVDEV_SUBDEV_I2C    ] = &nv04_i2c_oclass;
 		device->oclass[NVDEV_SUBDEV_CLOCK  ] = &nv40_clock_oclass;
 		device->oclass[NVDEV_SUBDEV_THERM  ] = &nv40_therm_oclass;
-		device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv1a_devinit_oclass;
+		device->oclass[NVDEV_SUBDEV_DEVINIT] =  nv1a_devinit_oclass;
 		device->oclass[NVDEV_SUBDEV_MC     ] =  nv44_mc_oclass;
 		device->oclass[NVDEV_SUBDEV_BUS    ] =  nv31_bus_oclass;
 		device->oclass[NVDEV_SUBDEV_TIMER  ] = &nv04_timer_oclass;
 		device->oclass[NVDEV_SUBDEV_FB     ] =  nv44_fb_oclass;
-		device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv40_instmem_oclass;
+		device->oclass[NVDEV_SUBDEV_INSTMEM] =  nv40_instmem_oclass;
 		device->oclass[NVDEV_SUBDEV_VM     ] = &nv44_vmmgr_oclass;
 		device->oclass[NVDEV_SUBDEV_VOLT   ] = &nv40_volt_oclass;
 		device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nv04_dmaeng_oclass;
@@ -264,12 +264,12 @@ nv40_identify(struct nouveau_device *device)
 		device->oclass[NVDEV_SUBDEV_I2C    ] = &nv04_i2c_oclass;
 		device->oclass[NVDEV_SUBDEV_CLOCK  ] = &nv40_clock_oclass;
 		device->oclass[NVDEV_SUBDEV_THERM  ] = &nv40_therm_oclass;
-		device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv1a_devinit_oclass;
+		device->oclass[NVDEV_SUBDEV_DEVINIT] =  nv1a_devinit_oclass;
 		device->oclass[NVDEV_SUBDEV_MC     ] =  nv44_mc_oclass;
 		device->oclass[NVDEV_SUBDEV_BUS    ] =  nv31_bus_oclass;
 		device->oclass[NVDEV_SUBDEV_TIMER  ] = &nv04_timer_oclass;
 		device->oclass[NVDEV_SUBDEV_FB     ] =  nv46_fb_oclass;
-		device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv40_instmem_oclass;
+		device->oclass[NVDEV_SUBDEV_INSTMEM] =  nv40_instmem_oclass;
 		device->oclass[NVDEV_SUBDEV_VM     ] = &nv44_vmmgr_oclass;
 		device->oclass[NVDEV_SUBDEV_VOLT   ] = &nv40_volt_oclass;
 		device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nv04_dmaeng_oclass;
@@ -287,12 +287,12 @@ nv40_identify(struct nouveau_device *device)
 		device->oclass[NVDEV_SUBDEV_I2C    ] = &nv04_i2c_oclass;
 		device->oclass[NVDEV_SUBDEV_CLOCK  ] = &nv40_clock_oclass;
 		device->oclass[NVDEV_SUBDEV_THERM  ] = &nv40_therm_oclass;
-		device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv1a_devinit_oclass;
+		device->oclass[NVDEV_SUBDEV_DEVINIT] =  nv1a_devinit_oclass;
 		device->oclass[NVDEV_SUBDEV_MC     ] =  nv44_mc_oclass;
 		device->oclass[NVDEV_SUBDEV_BUS    ] =  nv31_bus_oclass;
 		device->oclass[NVDEV_SUBDEV_TIMER  ] = &nv04_timer_oclass;
 		device->oclass[NVDEV_SUBDEV_FB     ] =  nv44_fb_oclass;
-		device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv40_instmem_oclass;
+		device->oclass[NVDEV_SUBDEV_INSTMEM] =  nv40_instmem_oclass;
 		device->oclass[NVDEV_SUBDEV_VM     ] = &nv44_vmmgr_oclass;
 		device->oclass[NVDEV_SUBDEV_VOLT   ] = &nv40_volt_oclass;
 		device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nv04_dmaeng_oclass;
@@ -310,12 +310,12 @@ nv40_identify(struct nouveau_device *device)
 		device->oclass[NVDEV_SUBDEV_I2C    ] = &nv04_i2c_oclass;
 		device->oclass[NVDEV_SUBDEV_CLOCK  ] = &nv40_clock_oclass;
 		device->oclass[NVDEV_SUBDEV_THERM  ] = &nv40_therm_oclass;
-		device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv1a_devinit_oclass;
+		device->oclass[NVDEV_SUBDEV_DEVINIT] =  nv1a_devinit_oclass;
 		device->oclass[NVDEV_SUBDEV_MC     ] =  nv44_mc_oclass;
 		device->oclass[NVDEV_SUBDEV_BUS    ] =  nv31_bus_oclass;
 		device->oclass[NVDEV_SUBDEV_TIMER  ] = &nv04_timer_oclass;
 		device->oclass[NVDEV_SUBDEV_FB     ] =  nv46_fb_oclass;
-		device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv40_instmem_oclass;
+		device->oclass[NVDEV_SUBDEV_INSTMEM] =  nv40_instmem_oclass;
 		device->oclass[NVDEV_SUBDEV_VM     ] = &nv44_vmmgr_oclass;
 		device->oclass[NVDEV_SUBDEV_VOLT   ] = &nv40_volt_oclass;
 		device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nv04_dmaeng_oclass;
@@ -333,12 +333,12 @@ nv40_identify(struct nouveau_device *device)
 		device->oclass[NVDEV_SUBDEV_I2C    ] = &nv4e_i2c_oclass;
 		device->oclass[NVDEV_SUBDEV_CLOCK  ] = &nv40_clock_oclass;
 		device->oclass[NVDEV_SUBDEV_THERM  ] = &nv40_therm_oclass;
-		device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv1a_devinit_oclass;
+		device->oclass[NVDEV_SUBDEV_DEVINIT] =  nv1a_devinit_oclass;
 		device->oclass[NVDEV_SUBDEV_MC     ] =  nv44_mc_oclass;
 		device->oclass[NVDEV_SUBDEV_BUS    ] =  nv31_bus_oclass;
 		device->oclass[NVDEV_SUBDEV_TIMER  ] = &nv04_timer_oclass;
 		device->oclass[NVDEV_SUBDEV_FB     ] =  nv4e_fb_oclass;
-		device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv40_instmem_oclass;
+		device->oclass[NVDEV_SUBDEV_INSTMEM] =  nv40_instmem_oclass;
 		device->oclass[NVDEV_SUBDEV_VM     ] = &nv44_vmmgr_oclass;
 		device->oclass[NVDEV_SUBDEV_VOLT   ] = &nv40_volt_oclass;
 		device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nv04_dmaeng_oclass;
@@ -356,12 +356,12 @@ nv40_identify(struct nouveau_device *device)
 		device->oclass[NVDEV_SUBDEV_I2C    ] = &nv04_i2c_oclass;
 		device->oclass[NVDEV_SUBDEV_CLOCK  ] = &nv40_clock_oclass;
 		device->oclass[NVDEV_SUBDEV_THERM  ] = &nv40_therm_oclass;
-		device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv1a_devinit_oclass;
+		device->oclass[NVDEV_SUBDEV_DEVINIT] =  nv1a_devinit_oclass;
 		device->oclass[NVDEV_SUBDEV_MC     ] =  nv44_mc_oclass;
 		device->oclass[NVDEV_SUBDEV_BUS    ] =  nv31_bus_oclass;
 		device->oclass[NVDEV_SUBDEV_TIMER  ] = &nv04_timer_oclass;
 		device->oclass[NVDEV_SUBDEV_FB     ] =  nv46_fb_oclass;
-		device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv40_instmem_oclass;
+		device->oclass[NVDEV_SUBDEV_INSTMEM] =  nv40_instmem_oclass;
 		device->oclass[NVDEV_SUBDEV_VM     ] = &nv44_vmmgr_oclass;
 		device->oclass[NVDEV_SUBDEV_VOLT   ] = &nv40_volt_oclass;
 		device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nv04_dmaeng_oclass;
@@ -379,12 +379,12 @@ nv40_identify(struct nouveau_device *device)
 		device->oclass[NVDEV_SUBDEV_I2C    ] = &nv04_i2c_oclass;
 		device->oclass[NVDEV_SUBDEV_CLOCK  ] = &nv40_clock_oclass;
 		device->oclass[NVDEV_SUBDEV_THERM  ] = &nv40_therm_oclass;
-		device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv1a_devinit_oclass;
+		device->oclass[NVDEV_SUBDEV_DEVINIT] =  nv1a_devinit_oclass;
 		device->oclass[NVDEV_SUBDEV_MC     ] =  nv44_mc_oclass;
 		device->oclass[NVDEV_SUBDEV_BUS    ] =  nv31_bus_oclass;
 		device->oclass[NVDEV_SUBDEV_TIMER  ] = &nv04_timer_oclass;
 		device->oclass[NVDEV_SUBDEV_FB     ] =  nv46_fb_oclass;
-		device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv40_instmem_oclass;
+		device->oclass[NVDEV_SUBDEV_INSTMEM] =  nv40_instmem_oclass;
 		device->oclass[NVDEV_SUBDEV_VM     ] = &nv44_vmmgr_oclass;
 		device->oclass[NVDEV_SUBDEV_VOLT   ] = &nv40_volt_oclass;
 		device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nv04_dmaeng_oclass;
@@ -402,12 +402,12 @@ nv40_identify(struct nouveau_device *device)
 		device->oclass[NVDEV_SUBDEV_I2C    ] = &nv04_i2c_oclass;
 		device->oclass[NVDEV_SUBDEV_CLOCK  ] = &nv40_clock_oclass;
 		device->oclass[NVDEV_SUBDEV_THERM  ] = &nv40_therm_oclass;
-		device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv1a_devinit_oclass;
+		device->oclass[NVDEV_SUBDEV_DEVINIT] =  nv1a_devinit_oclass;
 		device->oclass[NVDEV_SUBDEV_MC     ] =  nv44_mc_oclass;
 		device->oclass[NVDEV_SUBDEV_BUS    ] =  nv31_bus_oclass;
 		device->oclass[NVDEV_SUBDEV_TIMER  ] = &nv04_timer_oclass;
 		device->oclass[NVDEV_SUBDEV_FB     ] =  nv46_fb_oclass;
-		device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv40_instmem_oclass;
+		device->oclass[NVDEV_SUBDEV_INSTMEM] =  nv40_instmem_oclass;
 		device->oclass[NVDEV_SUBDEV_VM     ] = &nv44_vmmgr_oclass;
 		device->oclass[NVDEV_SUBDEV_VOLT   ] = &nv40_volt_oclass;
 		device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nv04_dmaeng_oclass;
diff --git a/drivers/gpu/drm/nouveau/core/engine/device/nv50.c b/drivers/gpu/drm/nouveau/core/engine/device/nv50.c
index db3fc7be856a7..81d5c26643d50 100644
--- a/drivers/gpu/drm/nouveau/core/engine/device/nv50.c
+++ b/drivers/gpu/drm/nouveau/core/engine/device/nv50.c
@@ -65,12 +65,12 @@ nv50_identify(struct nouveau_device *device)
 		device->oclass[NVDEV_SUBDEV_CLOCK  ] =  nv50_clock_oclass;
 		device->oclass[NVDEV_SUBDEV_THERM  ] = &nv50_therm_oclass;
 		device->oclass[NVDEV_SUBDEV_MXM    ] = &nv50_mxm_oclass;
-		device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv50_devinit_oclass;
+		device->oclass[NVDEV_SUBDEV_DEVINIT] =  nv50_devinit_oclass;
 		device->oclass[NVDEV_SUBDEV_MC     ] =  nv50_mc_oclass;
 		device->oclass[NVDEV_SUBDEV_BUS    ] =  nv50_bus_oclass;
 		device->oclass[NVDEV_SUBDEV_TIMER  ] = &nv04_timer_oclass;
 		device->oclass[NVDEV_SUBDEV_FB     ] =  nv50_fb_oclass;
-		device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv50_instmem_oclass;
+		device->oclass[NVDEV_SUBDEV_INSTMEM] =  nv50_instmem_oclass;
 		device->oclass[NVDEV_SUBDEV_VM     ] = &nv50_vmmgr_oclass;
 		device->oclass[NVDEV_SUBDEV_BAR    ] = &nv50_bar_oclass;
 		device->oclass[NVDEV_SUBDEV_VOLT   ] = &nv40_volt_oclass;
@@ -90,12 +90,12 @@ nv50_identify(struct nouveau_device *device)
 		device->oclass[NVDEV_SUBDEV_CLOCK  ] =  nv84_clock_oclass;
 		device->oclass[NVDEV_SUBDEV_THERM  ] = &nv84_therm_oclass;
 		device->oclass[NVDEV_SUBDEV_MXM    ] = &nv50_mxm_oclass;
-		device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv50_devinit_oclass;
+		device->oclass[NVDEV_SUBDEV_DEVINIT] =  nv84_devinit_oclass;
 		device->oclass[NVDEV_SUBDEV_MC     ] =  nv50_mc_oclass;
 		device->oclass[NVDEV_SUBDEV_BUS    ] =  nv50_bus_oclass;
 		device->oclass[NVDEV_SUBDEV_TIMER  ] = &nv04_timer_oclass;
 		device->oclass[NVDEV_SUBDEV_FB     ] =  nv84_fb_oclass;
-		device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv50_instmem_oclass;
+		device->oclass[NVDEV_SUBDEV_INSTMEM] =  nv50_instmem_oclass;
 		device->oclass[NVDEV_SUBDEV_VM     ] = &nv50_vmmgr_oclass;
 		device->oclass[NVDEV_SUBDEV_BAR    ] = &nv50_bar_oclass;
 		device->oclass[NVDEV_SUBDEV_VOLT   ] = &nv40_volt_oclass;
@@ -118,12 +118,12 @@ nv50_identify(struct nouveau_device *device)
 		device->oclass[NVDEV_SUBDEV_CLOCK  ] =  nv84_clock_oclass;
 		device->oclass[NVDEV_SUBDEV_THERM  ] = &nv84_therm_oclass;
 		device->oclass[NVDEV_SUBDEV_MXM    ] = &nv50_mxm_oclass;
-		device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv50_devinit_oclass;
+		device->oclass[NVDEV_SUBDEV_DEVINIT] =  nv84_devinit_oclass;
 		device->oclass[NVDEV_SUBDEV_MC     ] =  nv50_mc_oclass;
 		device->oclass[NVDEV_SUBDEV_BUS    ] =  nv50_bus_oclass;
 		device->oclass[NVDEV_SUBDEV_TIMER  ] = &nv04_timer_oclass;
 		device->oclass[NVDEV_SUBDEV_FB     ] =  nv84_fb_oclass;
-		device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv50_instmem_oclass;
+		device->oclass[NVDEV_SUBDEV_INSTMEM] =  nv50_instmem_oclass;
 		device->oclass[NVDEV_SUBDEV_VM     ] = &nv50_vmmgr_oclass;
 		device->oclass[NVDEV_SUBDEV_BAR    ] = &nv50_bar_oclass;
 		device->oclass[NVDEV_SUBDEV_VOLT   ] = &nv40_volt_oclass;
@@ -146,12 +146,12 @@ nv50_identify(struct nouveau_device *device)
 		device->oclass[NVDEV_SUBDEV_CLOCK  ] =  nv84_clock_oclass;
 		device->oclass[NVDEV_SUBDEV_THERM  ] = &nv84_therm_oclass;
 		device->oclass[NVDEV_SUBDEV_MXM    ] = &nv50_mxm_oclass;
-		device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv50_devinit_oclass;
+		device->oclass[NVDEV_SUBDEV_DEVINIT] =  nv84_devinit_oclass;
 		device->oclass[NVDEV_SUBDEV_MC     ] =  nv50_mc_oclass;
 		device->oclass[NVDEV_SUBDEV_BUS    ] =  nv50_bus_oclass;
 		device->oclass[NVDEV_SUBDEV_TIMER  ] = &nv04_timer_oclass;
 		device->oclass[NVDEV_SUBDEV_FB     ] =  nv84_fb_oclass;
-		device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv50_instmem_oclass;
+		device->oclass[NVDEV_SUBDEV_INSTMEM] =  nv50_instmem_oclass;
 		device->oclass[NVDEV_SUBDEV_VM     ] = &nv50_vmmgr_oclass;
 		device->oclass[NVDEV_SUBDEV_BAR    ] = &nv50_bar_oclass;
 		device->oclass[NVDEV_SUBDEV_VOLT   ] = &nv40_volt_oclass;
@@ -174,12 +174,12 @@ nv50_identify(struct nouveau_device *device)
 		device->oclass[NVDEV_SUBDEV_CLOCK  ] =  nv84_clock_oclass;
 		device->oclass[NVDEV_SUBDEV_THERM  ] = &nv84_therm_oclass;
 		device->oclass[NVDEV_SUBDEV_MXM    ] = &nv50_mxm_oclass;
-		device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv50_devinit_oclass;
+		device->oclass[NVDEV_SUBDEV_DEVINIT] =  nv84_devinit_oclass;
 		device->oclass[NVDEV_SUBDEV_MC     ] =  nv94_mc_oclass;
 		device->oclass[NVDEV_SUBDEV_BUS    ] =  nv94_bus_oclass;
 		device->oclass[NVDEV_SUBDEV_TIMER  ] = &nv04_timer_oclass;
 		device->oclass[NVDEV_SUBDEV_FB     ] =  nv84_fb_oclass;
-		device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv50_instmem_oclass;
+		device->oclass[NVDEV_SUBDEV_INSTMEM] =  nv50_instmem_oclass;
 		device->oclass[NVDEV_SUBDEV_VM     ] = &nv50_vmmgr_oclass;
 		device->oclass[NVDEV_SUBDEV_BAR    ] = &nv50_bar_oclass;
 		device->oclass[NVDEV_SUBDEV_VOLT   ] = &nv40_volt_oclass;
@@ -202,12 +202,12 @@ nv50_identify(struct nouveau_device *device)
 		device->oclass[NVDEV_SUBDEV_CLOCK  ] =  nv84_clock_oclass;
 		device->oclass[NVDEV_SUBDEV_THERM  ] = &nv84_therm_oclass;
 		device->oclass[NVDEV_SUBDEV_MXM    ] = &nv50_mxm_oclass;
-		device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv50_devinit_oclass;
+		device->oclass[NVDEV_SUBDEV_DEVINIT] =  nv84_devinit_oclass;
 		device->oclass[NVDEV_SUBDEV_MC     ] =  nv94_mc_oclass;
 		device->oclass[NVDEV_SUBDEV_BUS    ] =  nv94_bus_oclass;
 		device->oclass[NVDEV_SUBDEV_TIMER  ] = &nv04_timer_oclass;
 		device->oclass[NVDEV_SUBDEV_FB     ] =  nv84_fb_oclass;
-		device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv50_instmem_oclass;
+		device->oclass[NVDEV_SUBDEV_INSTMEM] =  nv50_instmem_oclass;
 		device->oclass[NVDEV_SUBDEV_VM     ] = &nv50_vmmgr_oclass;
 		device->oclass[NVDEV_SUBDEV_BAR    ] = &nv50_bar_oclass;
 		device->oclass[NVDEV_SUBDEV_VOLT   ] = &nv40_volt_oclass;
@@ -230,12 +230,12 @@ nv50_identify(struct nouveau_device *device)
 		device->oclass[NVDEV_SUBDEV_CLOCK  ] =  nv84_clock_oclass;
 		device->oclass[NVDEV_SUBDEV_THERM  ] = &nv84_therm_oclass;
 		device->oclass[NVDEV_SUBDEV_MXM    ] = &nv50_mxm_oclass;
-		device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv50_devinit_oclass;
+		device->oclass[NVDEV_SUBDEV_DEVINIT] =  nv98_devinit_oclass;
 		device->oclass[NVDEV_SUBDEV_MC     ] =  nv98_mc_oclass;
 		device->oclass[NVDEV_SUBDEV_BUS    ] =  nv94_bus_oclass;
 		device->oclass[NVDEV_SUBDEV_TIMER  ] = &nv04_timer_oclass;
 		device->oclass[NVDEV_SUBDEV_FB     ] =  nv84_fb_oclass;
-		device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv50_instmem_oclass;
+		device->oclass[NVDEV_SUBDEV_INSTMEM] =  nv50_instmem_oclass;
 		device->oclass[NVDEV_SUBDEV_VM     ] = &nv50_vmmgr_oclass;
 		device->oclass[NVDEV_SUBDEV_BAR    ] = &nv50_bar_oclass;
 		device->oclass[NVDEV_SUBDEV_VOLT   ] = &nv40_volt_oclass;
@@ -258,12 +258,12 @@ nv50_identify(struct nouveau_device *device)
 		device->oclass[NVDEV_SUBDEV_CLOCK  ] =  nv84_clock_oclass;
 		device->oclass[NVDEV_SUBDEV_THERM  ] = &nv84_therm_oclass;
 		device->oclass[NVDEV_SUBDEV_MXM    ] = &nv50_mxm_oclass;
-		device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv50_devinit_oclass;
+		device->oclass[NVDEV_SUBDEV_DEVINIT] =  nv84_devinit_oclass;
 		device->oclass[NVDEV_SUBDEV_MC     ] =  nv98_mc_oclass;
 		device->oclass[NVDEV_SUBDEV_BUS    ] =  nv94_bus_oclass;
 		device->oclass[NVDEV_SUBDEV_TIMER  ] = &nv04_timer_oclass;
 		device->oclass[NVDEV_SUBDEV_FB     ] =  nv84_fb_oclass;
-		device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv50_instmem_oclass;
+		device->oclass[NVDEV_SUBDEV_INSTMEM] =  nv50_instmem_oclass;
 		device->oclass[NVDEV_SUBDEV_VM     ] = &nv50_vmmgr_oclass;
 		device->oclass[NVDEV_SUBDEV_BAR    ] = &nv50_bar_oclass;
 		device->oclass[NVDEV_SUBDEV_VOLT   ] = &nv40_volt_oclass;
@@ -286,12 +286,12 @@ nv50_identify(struct nouveau_device *device)
 		device->oclass[NVDEV_SUBDEV_CLOCK  ] =  nvaa_clock_oclass;
 		device->oclass[NVDEV_SUBDEV_THERM  ] = &nv84_therm_oclass;
 		device->oclass[NVDEV_SUBDEV_MXM    ] = &nv50_mxm_oclass;
-		device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv50_devinit_oclass;
+		device->oclass[NVDEV_SUBDEV_DEVINIT] =  nv98_devinit_oclass;
 		device->oclass[NVDEV_SUBDEV_MC     ] =  nv98_mc_oclass;
 		device->oclass[NVDEV_SUBDEV_BUS    ] =  nv94_bus_oclass;
 		device->oclass[NVDEV_SUBDEV_TIMER  ] = &nv04_timer_oclass;
 		device->oclass[NVDEV_SUBDEV_FB     ] =  nvaa_fb_oclass;
-		device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv50_instmem_oclass;
+		device->oclass[NVDEV_SUBDEV_INSTMEM] =  nv50_instmem_oclass;
 		device->oclass[NVDEV_SUBDEV_VM     ] = &nv50_vmmgr_oclass;
 		device->oclass[NVDEV_SUBDEV_BAR    ] = &nv50_bar_oclass;
 		device->oclass[NVDEV_SUBDEV_VOLT   ] = &nv40_volt_oclass;
@@ -314,12 +314,12 @@ nv50_identify(struct nouveau_device *device)
 		device->oclass[NVDEV_SUBDEV_CLOCK  ] =  nvaa_clock_oclass;
 		device->oclass[NVDEV_SUBDEV_THERM  ] = &nv84_therm_oclass;
 		device->oclass[NVDEV_SUBDEV_MXM    ] = &nv50_mxm_oclass;
-		device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv50_devinit_oclass;
+		device->oclass[NVDEV_SUBDEV_DEVINIT] =  nv98_devinit_oclass;
 		device->oclass[NVDEV_SUBDEV_MC     ] =  nv98_mc_oclass;
 		device->oclass[NVDEV_SUBDEV_BUS    ] =  nv94_bus_oclass;
 		device->oclass[NVDEV_SUBDEV_TIMER  ] = &nv04_timer_oclass;
 		device->oclass[NVDEV_SUBDEV_FB     ] =  nvaa_fb_oclass;
-		device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv50_instmem_oclass;
+		device->oclass[NVDEV_SUBDEV_INSTMEM] =  nv50_instmem_oclass;
 		device->oclass[NVDEV_SUBDEV_VM     ] = &nv50_vmmgr_oclass;
 		device->oclass[NVDEV_SUBDEV_BAR    ] = &nv50_bar_oclass;
 		device->oclass[NVDEV_SUBDEV_VOLT   ] = &nv40_volt_oclass;
@@ -342,12 +342,12 @@ nv50_identify(struct nouveau_device *device)
 		device->oclass[NVDEV_SUBDEV_CLOCK  ] = &nva3_clock_oclass;
 		device->oclass[NVDEV_SUBDEV_THERM  ] = &nva3_therm_oclass;
 		device->oclass[NVDEV_SUBDEV_MXM    ] = &nv50_mxm_oclass;
-		device->oclass[NVDEV_SUBDEV_DEVINIT] = &nva3_devinit_oclass;
+		device->oclass[NVDEV_SUBDEV_DEVINIT] =  nva3_devinit_oclass;
 		device->oclass[NVDEV_SUBDEV_MC     ] =  nv98_mc_oclass;
 		device->oclass[NVDEV_SUBDEV_BUS    ] =  nv94_bus_oclass;
 		device->oclass[NVDEV_SUBDEV_TIMER  ] = &nv04_timer_oclass;
 		device->oclass[NVDEV_SUBDEV_FB     ] =  nva3_fb_oclass;
-		device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv50_instmem_oclass;
+		device->oclass[NVDEV_SUBDEV_INSTMEM] =  nv50_instmem_oclass;
 		device->oclass[NVDEV_SUBDEV_VM     ] = &nv50_vmmgr_oclass;
 		device->oclass[NVDEV_SUBDEV_BAR    ] = &nv50_bar_oclass;
 		device->oclass[NVDEV_SUBDEV_PWR    ] = &nva3_pwr_oclass;
@@ -372,12 +372,12 @@ nv50_identify(struct nouveau_device *device)
 		device->oclass[NVDEV_SUBDEV_CLOCK  ] = &nva3_clock_oclass;
 		device->oclass[NVDEV_SUBDEV_THERM  ] = &nva3_therm_oclass;
 		device->oclass[NVDEV_SUBDEV_MXM    ] = &nv50_mxm_oclass;
-		device->oclass[NVDEV_SUBDEV_DEVINIT] = &nva3_devinit_oclass;
+		device->oclass[NVDEV_SUBDEV_DEVINIT] =  nva3_devinit_oclass;
 		device->oclass[NVDEV_SUBDEV_MC     ] =  nv98_mc_oclass;
 		device->oclass[NVDEV_SUBDEV_BUS    ] =  nv94_bus_oclass;
 		device->oclass[NVDEV_SUBDEV_TIMER  ] = &nv04_timer_oclass;
 		device->oclass[NVDEV_SUBDEV_FB     ] =  nva3_fb_oclass;
-		device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv50_instmem_oclass;
+		device->oclass[NVDEV_SUBDEV_INSTMEM] =  nv50_instmem_oclass;
 		device->oclass[NVDEV_SUBDEV_VM     ] = &nv50_vmmgr_oclass;
 		device->oclass[NVDEV_SUBDEV_BAR    ] = &nv50_bar_oclass;
 		device->oclass[NVDEV_SUBDEV_PWR    ] = &nva3_pwr_oclass;
@@ -401,12 +401,12 @@ nv50_identify(struct nouveau_device *device)
 		device->oclass[NVDEV_SUBDEV_CLOCK  ] = &nva3_clock_oclass;
 		device->oclass[NVDEV_SUBDEV_THERM  ] = &nva3_therm_oclass;
 		device->oclass[NVDEV_SUBDEV_MXM    ] = &nv50_mxm_oclass;
-		device->oclass[NVDEV_SUBDEV_DEVINIT] = &nva3_devinit_oclass;
+		device->oclass[NVDEV_SUBDEV_DEVINIT] =  nva3_devinit_oclass;
 		device->oclass[NVDEV_SUBDEV_MC     ] =  nv98_mc_oclass;
 		device->oclass[NVDEV_SUBDEV_BUS    ] =  nv94_bus_oclass;
 		device->oclass[NVDEV_SUBDEV_TIMER  ] = &nv04_timer_oclass;
 		device->oclass[NVDEV_SUBDEV_FB     ] =  nva3_fb_oclass;
-		device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv50_instmem_oclass;
+		device->oclass[NVDEV_SUBDEV_INSTMEM] =  nv50_instmem_oclass;
 		device->oclass[NVDEV_SUBDEV_VM     ] = &nv50_vmmgr_oclass;
 		device->oclass[NVDEV_SUBDEV_BAR    ] = &nv50_bar_oclass;
 		device->oclass[NVDEV_SUBDEV_PWR    ] = &nva3_pwr_oclass;
@@ -430,12 +430,12 @@ nv50_identify(struct nouveau_device *device)
 		device->oclass[NVDEV_SUBDEV_CLOCK  ] = &nva3_clock_oclass;
 		device->oclass[NVDEV_SUBDEV_THERM  ] = &nva3_therm_oclass;
 		device->oclass[NVDEV_SUBDEV_MXM    ] = &nv50_mxm_oclass;
-		device->oclass[NVDEV_SUBDEV_DEVINIT] = &nva3_devinit_oclass;
+		device->oclass[NVDEV_SUBDEV_DEVINIT] =  nvaf_devinit_oclass;
 		device->oclass[NVDEV_SUBDEV_MC     ] =  nv98_mc_oclass;
 		device->oclass[NVDEV_SUBDEV_BUS    ] =  nv94_bus_oclass;
 		device->oclass[NVDEV_SUBDEV_TIMER  ] = &nv04_timer_oclass;
 		device->oclass[NVDEV_SUBDEV_FB     ] =  nvaf_fb_oclass;
-		device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv50_instmem_oclass;
+		device->oclass[NVDEV_SUBDEV_INSTMEM] =  nv50_instmem_oclass;
 		device->oclass[NVDEV_SUBDEV_VM     ] = &nv50_vmmgr_oclass;
 		device->oclass[NVDEV_SUBDEV_BAR    ] = &nv50_bar_oclass;
 		device->oclass[NVDEV_SUBDEV_PWR    ] = &nva3_pwr_oclass;
diff --git a/drivers/gpu/drm/nouveau/core/engine/device/nvc0.c b/drivers/gpu/drm/nouveau/core/engine/device/nvc0.c
index dbc5e33de94f8..b7d66b59f43d4 100644
--- a/drivers/gpu/drm/nouveau/core/engine/device/nvc0.c
+++ b/drivers/gpu/drm/nouveau/core/engine/device/nvc0.c
@@ -65,14 +65,14 @@ nvc0_identify(struct nouveau_device *device)
 		device->oclass[NVDEV_SUBDEV_CLOCK  ] = &nvc0_clock_oclass;
 		device->oclass[NVDEV_SUBDEV_THERM  ] = &nva3_therm_oclass;
 		device->oclass[NVDEV_SUBDEV_MXM    ] = &nv50_mxm_oclass;
-		device->oclass[NVDEV_SUBDEV_DEVINIT] = &nvc0_devinit_oclass;
+		device->oclass[NVDEV_SUBDEV_DEVINIT] =  nvc0_devinit_oclass;
 		device->oclass[NVDEV_SUBDEV_MC     ] =  nvc0_mc_oclass;
 		device->oclass[NVDEV_SUBDEV_BUS    ] =  nvc0_bus_oclass;
 		device->oclass[NVDEV_SUBDEV_TIMER  ] = &nv04_timer_oclass;
 		device->oclass[NVDEV_SUBDEV_FB     ] =  nvc0_fb_oclass;
 		device->oclass[NVDEV_SUBDEV_LTCG   ] = &nvc0_ltcg_oclass;
 		device->oclass[NVDEV_SUBDEV_IBUS   ] = &nvc0_ibus_oclass;
-		device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv50_instmem_oclass;
+		device->oclass[NVDEV_SUBDEV_INSTMEM] =  nv50_instmem_oclass;
 		device->oclass[NVDEV_SUBDEV_VM     ] = &nvc0_vmmgr_oclass;
 		device->oclass[NVDEV_SUBDEV_BAR    ] = &nvc0_bar_oclass;
 		device->oclass[NVDEV_SUBDEV_PWR    ] = &nvc0_pwr_oclass;
@@ -97,14 +97,14 @@ nvc0_identify(struct nouveau_device *device)
 		device->oclass[NVDEV_SUBDEV_CLOCK  ] = &nvc0_clock_oclass;
 		device->oclass[NVDEV_SUBDEV_THERM  ] = &nva3_therm_oclass;
 		device->oclass[NVDEV_SUBDEV_MXM    ] = &nv50_mxm_oclass;
-		device->oclass[NVDEV_SUBDEV_DEVINIT] = &nvc0_devinit_oclass;
+		device->oclass[NVDEV_SUBDEV_DEVINIT] =  nvc0_devinit_oclass;
 		device->oclass[NVDEV_SUBDEV_MC     ] =  nvc0_mc_oclass;
 		device->oclass[NVDEV_SUBDEV_BUS    ] =  nvc0_bus_oclass;
 		device->oclass[NVDEV_SUBDEV_TIMER  ] = &nv04_timer_oclass;
 		device->oclass[NVDEV_SUBDEV_FB     ] =  nvc0_fb_oclass;
 		device->oclass[NVDEV_SUBDEV_LTCG   ] = &nvc0_ltcg_oclass;
 		device->oclass[NVDEV_SUBDEV_IBUS   ] = &nvc0_ibus_oclass;
-		device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv50_instmem_oclass;
+		device->oclass[NVDEV_SUBDEV_INSTMEM] =  nv50_instmem_oclass;
 		device->oclass[NVDEV_SUBDEV_VM     ] = &nvc0_vmmgr_oclass;
 		device->oclass[NVDEV_SUBDEV_BAR    ] = &nvc0_bar_oclass;
 		device->oclass[NVDEV_SUBDEV_PWR    ] = &nvc0_pwr_oclass;
@@ -129,14 +129,14 @@ nvc0_identify(struct nouveau_device *device)
 		device->oclass[NVDEV_SUBDEV_CLOCK  ] = &nvc0_clock_oclass;
 		device->oclass[NVDEV_SUBDEV_THERM  ] = &nva3_therm_oclass;
 		device->oclass[NVDEV_SUBDEV_MXM    ] = &nv50_mxm_oclass;
-		device->oclass[NVDEV_SUBDEV_DEVINIT] = &nvc0_devinit_oclass;
+		device->oclass[NVDEV_SUBDEV_DEVINIT] =  nvc0_devinit_oclass;
 		device->oclass[NVDEV_SUBDEV_MC     ] =  nvc3_mc_oclass;
 		device->oclass[NVDEV_SUBDEV_BUS    ] =  nvc0_bus_oclass;
 		device->oclass[NVDEV_SUBDEV_TIMER  ] = &nv04_timer_oclass;
 		device->oclass[NVDEV_SUBDEV_FB     ] =  nvc0_fb_oclass;
 		device->oclass[NVDEV_SUBDEV_LTCG   ] = &nvc0_ltcg_oclass;
 		device->oclass[NVDEV_SUBDEV_IBUS   ] = &nvc0_ibus_oclass;
-		device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv50_instmem_oclass;
+		device->oclass[NVDEV_SUBDEV_INSTMEM] =  nv50_instmem_oclass;
 		device->oclass[NVDEV_SUBDEV_VM     ] = &nvc0_vmmgr_oclass;
 		device->oclass[NVDEV_SUBDEV_BAR    ] = &nvc0_bar_oclass;
 		device->oclass[NVDEV_SUBDEV_PWR    ] = &nvc0_pwr_oclass;
@@ -160,14 +160,14 @@ nvc0_identify(struct nouveau_device *device)
 		device->oclass[NVDEV_SUBDEV_CLOCK  ] = &nvc0_clock_oclass;
 		device->oclass[NVDEV_SUBDEV_THERM  ] = &nva3_therm_oclass;
 		device->oclass[NVDEV_SUBDEV_MXM    ] = &nv50_mxm_oclass;
-		device->oclass[NVDEV_SUBDEV_DEVINIT] = &nvc0_devinit_oclass;
+		device->oclass[NVDEV_SUBDEV_DEVINIT] =  nvc0_devinit_oclass;
 		device->oclass[NVDEV_SUBDEV_MC     ] =  nvc0_mc_oclass;
 		device->oclass[NVDEV_SUBDEV_BUS    ] =  nvc0_bus_oclass;
 		device->oclass[NVDEV_SUBDEV_TIMER  ] = &nv04_timer_oclass;
 		device->oclass[NVDEV_SUBDEV_FB     ] =  nvc0_fb_oclass;
 		device->oclass[NVDEV_SUBDEV_LTCG   ] = &nvc0_ltcg_oclass;
 		device->oclass[NVDEV_SUBDEV_IBUS   ] = &nvc0_ibus_oclass;
-		device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv50_instmem_oclass;
+		device->oclass[NVDEV_SUBDEV_INSTMEM] =  nv50_instmem_oclass;
 		device->oclass[NVDEV_SUBDEV_VM     ] = &nvc0_vmmgr_oclass;
 		device->oclass[NVDEV_SUBDEV_BAR    ] = &nvc0_bar_oclass;
 		device->oclass[NVDEV_SUBDEV_PWR    ] = &nvc0_pwr_oclass;
@@ -192,14 +192,14 @@ nvc0_identify(struct nouveau_device *device)
 		device->oclass[NVDEV_SUBDEV_CLOCK  ] = &nvc0_clock_oclass;
 		device->oclass[NVDEV_SUBDEV_THERM  ] = &nva3_therm_oclass;
 		device->oclass[NVDEV_SUBDEV_MXM    ] = &nv50_mxm_oclass;
-		device->oclass[NVDEV_SUBDEV_DEVINIT] = &nvc0_devinit_oclass;
+		device->oclass[NVDEV_SUBDEV_DEVINIT] =  nvc0_devinit_oclass;
 		device->oclass[NVDEV_SUBDEV_MC     ] =  nvc3_mc_oclass;
 		device->oclass[NVDEV_SUBDEV_BUS    ] =  nvc0_bus_oclass;
 		device->oclass[NVDEV_SUBDEV_TIMER  ] = &nv04_timer_oclass;
 		device->oclass[NVDEV_SUBDEV_FB     ] =  nvc0_fb_oclass;
 		device->oclass[NVDEV_SUBDEV_LTCG   ] = &nvc0_ltcg_oclass;
 		device->oclass[NVDEV_SUBDEV_IBUS   ] = &nvc0_ibus_oclass;
-		device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv50_instmem_oclass;
+		device->oclass[NVDEV_SUBDEV_INSTMEM] =  nv50_instmem_oclass;
 		device->oclass[NVDEV_SUBDEV_VM     ] = &nvc0_vmmgr_oclass;
 		device->oclass[NVDEV_SUBDEV_BAR    ] = &nvc0_bar_oclass;
 		device->oclass[NVDEV_SUBDEV_PWR    ] = &nvc0_pwr_oclass;
@@ -224,14 +224,14 @@ nvc0_identify(struct nouveau_device *device)
 		device->oclass[NVDEV_SUBDEV_CLOCK  ] = &nvc0_clock_oclass;
 		device->oclass[NVDEV_SUBDEV_THERM  ] = &nva3_therm_oclass;
 		device->oclass[NVDEV_SUBDEV_MXM    ] = &nv50_mxm_oclass;
-		device->oclass[NVDEV_SUBDEV_DEVINIT] = &nvc0_devinit_oclass;
+		device->oclass[NVDEV_SUBDEV_DEVINIT] =  nvc0_devinit_oclass;
 		device->oclass[NVDEV_SUBDEV_MC     ] =  nvc3_mc_oclass;
 		device->oclass[NVDEV_SUBDEV_BUS    ] =  nvc0_bus_oclass;
 		device->oclass[NVDEV_SUBDEV_TIMER  ] = &nv04_timer_oclass;
 		device->oclass[NVDEV_SUBDEV_FB     ] =  nvc0_fb_oclass;
 		device->oclass[NVDEV_SUBDEV_LTCG   ] = &nvc0_ltcg_oclass;
 		device->oclass[NVDEV_SUBDEV_IBUS   ] = &nvc0_ibus_oclass;
-		device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv50_instmem_oclass;
+		device->oclass[NVDEV_SUBDEV_INSTMEM] =  nv50_instmem_oclass;
 		device->oclass[NVDEV_SUBDEV_VM     ] = &nvc0_vmmgr_oclass;
 		device->oclass[NVDEV_SUBDEV_BAR    ] = &nvc0_bar_oclass;
 		device->oclass[NVDEV_SUBDEV_PWR    ] = &nvc0_pwr_oclass;
@@ -255,14 +255,14 @@ nvc0_identify(struct nouveau_device *device)
 		device->oclass[NVDEV_SUBDEV_CLOCK  ] = &nvc0_clock_oclass;
 		device->oclass[NVDEV_SUBDEV_THERM  ] = &nva3_therm_oclass;
 		device->oclass[NVDEV_SUBDEV_MXM    ] = &nv50_mxm_oclass;
-		device->oclass[NVDEV_SUBDEV_DEVINIT] = &nvc0_devinit_oclass;
+		device->oclass[NVDEV_SUBDEV_DEVINIT] =  nvc0_devinit_oclass;
 		device->oclass[NVDEV_SUBDEV_MC     ] =  nvc0_mc_oclass;
 		device->oclass[NVDEV_SUBDEV_BUS    ] =  nvc0_bus_oclass;
 		device->oclass[NVDEV_SUBDEV_TIMER  ] = &nv04_timer_oclass;
 		device->oclass[NVDEV_SUBDEV_FB     ] =  nvc0_fb_oclass;
 		device->oclass[NVDEV_SUBDEV_LTCG   ] = &nvc0_ltcg_oclass;
 		device->oclass[NVDEV_SUBDEV_IBUS   ] = &nvc0_ibus_oclass;
-		device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv50_instmem_oclass;
+		device->oclass[NVDEV_SUBDEV_INSTMEM] =  nv50_instmem_oclass;
 		device->oclass[NVDEV_SUBDEV_VM     ] = &nvc0_vmmgr_oclass;
 		device->oclass[NVDEV_SUBDEV_BAR    ] = &nvc0_bar_oclass;
 		device->oclass[NVDEV_SUBDEV_PWR    ] = &nvc0_pwr_oclass;
@@ -287,14 +287,14 @@ nvc0_identify(struct nouveau_device *device)
 		device->oclass[NVDEV_SUBDEV_CLOCK  ] = &nvc0_clock_oclass;
 		device->oclass[NVDEV_SUBDEV_THERM  ] = &nvd0_therm_oclass;
 		device->oclass[NVDEV_SUBDEV_MXM    ] = &nv50_mxm_oclass;
-		device->oclass[NVDEV_SUBDEV_DEVINIT] = &nvc0_devinit_oclass;
+		device->oclass[NVDEV_SUBDEV_DEVINIT] =  nvc0_devinit_oclass;
 		device->oclass[NVDEV_SUBDEV_MC     ] =  nvc3_mc_oclass;
 		device->oclass[NVDEV_SUBDEV_BUS    ] =  nvc0_bus_oclass;
 		device->oclass[NVDEV_SUBDEV_TIMER  ] = &nv04_timer_oclass;
 		device->oclass[NVDEV_SUBDEV_FB     ] =  nvc0_fb_oclass;
 		device->oclass[NVDEV_SUBDEV_LTCG   ] = &nvc0_ltcg_oclass;
 		device->oclass[NVDEV_SUBDEV_IBUS   ] = &nvc0_ibus_oclass;
-		device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv50_instmem_oclass;
+		device->oclass[NVDEV_SUBDEV_INSTMEM] =  nv50_instmem_oclass;
 		device->oclass[NVDEV_SUBDEV_VM     ] = &nvc0_vmmgr_oclass;
 		device->oclass[NVDEV_SUBDEV_BAR    ] = &nvc0_bar_oclass;
 		device->oclass[NVDEV_SUBDEV_PWR    ] = &nvd0_pwr_oclass;
@@ -318,14 +318,14 @@ nvc0_identify(struct nouveau_device *device)
 		device->oclass[NVDEV_SUBDEV_CLOCK  ] = &nvc0_clock_oclass;
 		device->oclass[NVDEV_SUBDEV_THERM  ] = &nvd0_therm_oclass;
 		device->oclass[NVDEV_SUBDEV_MXM    ] = &nv50_mxm_oclass;
-		device->oclass[NVDEV_SUBDEV_DEVINIT] = &nvc0_devinit_oclass;
+		device->oclass[NVDEV_SUBDEV_DEVINIT] =  nvc0_devinit_oclass;
 		device->oclass[NVDEV_SUBDEV_MC     ] =  nvc3_mc_oclass;
 		device->oclass[NVDEV_SUBDEV_BUS    ] =  nvc0_bus_oclass;
 		device->oclass[NVDEV_SUBDEV_TIMER  ] = &nv04_timer_oclass;
 		device->oclass[NVDEV_SUBDEV_FB     ] =  nvc0_fb_oclass;
 		device->oclass[NVDEV_SUBDEV_LTCG   ] = &nvc0_ltcg_oclass;
 		device->oclass[NVDEV_SUBDEV_IBUS   ] = &nvc0_ibus_oclass;
-		device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv50_instmem_oclass;
+		device->oclass[NVDEV_SUBDEV_INSTMEM] =  nv50_instmem_oclass;
 		device->oclass[NVDEV_SUBDEV_VM     ] = &nvc0_vmmgr_oclass;
 		device->oclass[NVDEV_SUBDEV_BAR    ] = &nvc0_bar_oclass;
 		device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nvd0_dmaeng_oclass;
diff --git a/drivers/gpu/drm/nouveau/core/engine/device/nve0.c b/drivers/gpu/drm/nouveau/core/engine/device/nve0.c
index 3900104976fc7..987edbc30a091 100644
--- a/drivers/gpu/drm/nouveau/core/engine/device/nve0.c
+++ b/drivers/gpu/drm/nouveau/core/engine/device/nve0.c
@@ -65,14 +65,14 @@ nve0_identify(struct nouveau_device *device)
 		device->oclass[NVDEV_SUBDEV_CLOCK  ] = &nve0_clock_oclass;
 		device->oclass[NVDEV_SUBDEV_THERM  ] = &nvd0_therm_oclass;
 		device->oclass[NVDEV_SUBDEV_MXM    ] = &nv50_mxm_oclass;
-		device->oclass[NVDEV_SUBDEV_DEVINIT] = &nvc0_devinit_oclass;
+		device->oclass[NVDEV_SUBDEV_DEVINIT] =  nvc0_devinit_oclass;
 		device->oclass[NVDEV_SUBDEV_MC     ] =  nvc3_mc_oclass;
 		device->oclass[NVDEV_SUBDEV_BUS    ] =  nvc0_bus_oclass;
 		device->oclass[NVDEV_SUBDEV_TIMER  ] = &nv04_timer_oclass;
 		device->oclass[NVDEV_SUBDEV_FB     ] =  nve0_fb_oclass;
 		device->oclass[NVDEV_SUBDEV_LTCG   ] = &nvc0_ltcg_oclass;
 		device->oclass[NVDEV_SUBDEV_IBUS   ] = &nve0_ibus_oclass;
-		device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv50_instmem_oclass;
+		device->oclass[NVDEV_SUBDEV_INSTMEM] =  nv50_instmem_oclass;
 		device->oclass[NVDEV_SUBDEV_VM     ] = &nvc0_vmmgr_oclass;
 		device->oclass[NVDEV_SUBDEV_BAR    ] = &nvc0_bar_oclass;
 		device->oclass[NVDEV_SUBDEV_PWR    ] = &nvd0_pwr_oclass;
@@ -98,14 +98,14 @@ nve0_identify(struct nouveau_device *device)
 		device->oclass[NVDEV_SUBDEV_CLOCK  ] = &nve0_clock_oclass;
 		device->oclass[NVDEV_SUBDEV_THERM  ] = &nvd0_therm_oclass;
 		device->oclass[NVDEV_SUBDEV_MXM    ] = &nv50_mxm_oclass;
-		device->oclass[NVDEV_SUBDEV_DEVINIT] = &nvc0_devinit_oclass;
+		device->oclass[NVDEV_SUBDEV_DEVINIT] =  nvc0_devinit_oclass;
 		device->oclass[NVDEV_SUBDEV_MC     ] =  nvc3_mc_oclass;
 		device->oclass[NVDEV_SUBDEV_BUS    ] =  nvc0_bus_oclass;
 		device->oclass[NVDEV_SUBDEV_TIMER  ] = &nv04_timer_oclass;
 		device->oclass[NVDEV_SUBDEV_FB     ] =  nve0_fb_oclass;
 		device->oclass[NVDEV_SUBDEV_LTCG   ] = &nvc0_ltcg_oclass;
 		device->oclass[NVDEV_SUBDEV_IBUS   ] = &nve0_ibus_oclass;
-		device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv50_instmem_oclass;
+		device->oclass[NVDEV_SUBDEV_INSTMEM] =  nv50_instmem_oclass;
 		device->oclass[NVDEV_SUBDEV_VM     ] = &nvc0_vmmgr_oclass;
 		device->oclass[NVDEV_SUBDEV_BAR    ] = &nvc0_bar_oclass;
 		device->oclass[NVDEV_SUBDEV_PWR    ] = &nvd0_pwr_oclass;
@@ -131,14 +131,14 @@ nve0_identify(struct nouveau_device *device)
 		device->oclass[NVDEV_SUBDEV_CLOCK  ] = &nve0_clock_oclass;
 		device->oclass[NVDEV_SUBDEV_THERM  ] = &nvd0_therm_oclass;
 		device->oclass[NVDEV_SUBDEV_MXM    ] = &nv50_mxm_oclass;
-		device->oclass[NVDEV_SUBDEV_DEVINIT] = &nvc0_devinit_oclass;
+		device->oclass[NVDEV_SUBDEV_DEVINIT] =  nvc0_devinit_oclass;
 		device->oclass[NVDEV_SUBDEV_MC     ] =  nvc3_mc_oclass;
 		device->oclass[NVDEV_SUBDEV_BUS    ] =  nvc0_bus_oclass;
 		device->oclass[NVDEV_SUBDEV_TIMER  ] = &nv04_timer_oclass;
 		device->oclass[NVDEV_SUBDEV_FB     ] =  nve0_fb_oclass;
 		device->oclass[NVDEV_SUBDEV_LTCG   ] = &nvc0_ltcg_oclass;
 		device->oclass[NVDEV_SUBDEV_IBUS   ] = &nve0_ibus_oclass;
-		device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv50_instmem_oclass;
+		device->oclass[NVDEV_SUBDEV_INSTMEM] =  nv50_instmem_oclass;
 		device->oclass[NVDEV_SUBDEV_VM     ] = &nvc0_vmmgr_oclass;
 		device->oclass[NVDEV_SUBDEV_BAR    ] = &nvc0_bar_oclass;
 		device->oclass[NVDEV_SUBDEV_PWR    ] = &nvd0_pwr_oclass;
@@ -164,14 +164,14 @@ nve0_identify(struct nouveau_device *device)
 		device->oclass[NVDEV_SUBDEV_CLOCK  ] = &nve0_clock_oclass;
 		device->oclass[NVDEV_SUBDEV_THERM  ] = &nvd0_therm_oclass;
 		device->oclass[NVDEV_SUBDEV_MXM    ] = &nv50_mxm_oclass;
-		device->oclass[NVDEV_SUBDEV_DEVINIT] = &nvc0_devinit_oclass;
+		device->oclass[NVDEV_SUBDEV_DEVINIT] =  nvc0_devinit_oclass;
 		device->oclass[NVDEV_SUBDEV_MC     ] =  nvc3_mc_oclass;
 		device->oclass[NVDEV_SUBDEV_BUS    ] =  nvc0_bus_oclass;
 		device->oclass[NVDEV_SUBDEV_TIMER  ] = &nv04_timer_oclass;
 		device->oclass[NVDEV_SUBDEV_FB     ] =  nve0_fb_oclass;
 		device->oclass[NVDEV_SUBDEV_LTCG   ] = &nvc0_ltcg_oclass;
 		device->oclass[NVDEV_SUBDEV_IBUS   ] = &nve0_ibus_oclass;
-		device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv50_instmem_oclass;
+		device->oclass[NVDEV_SUBDEV_INSTMEM] =  nv50_instmem_oclass;
 		device->oclass[NVDEV_SUBDEV_VM     ] = &nvc0_vmmgr_oclass;
 		device->oclass[NVDEV_SUBDEV_BAR    ] = &nvc0_bar_oclass;
 		device->oclass[NVDEV_SUBDEV_PWR    ] = &nvd0_pwr_oclass;
@@ -199,29 +199,27 @@ nve0_identify(struct nouveau_device *device)
 		device->oclass[NVDEV_SUBDEV_CLOCK  ] = &nve0_clock_oclass;
 		device->oclass[NVDEV_SUBDEV_THERM  ] = &nvd0_therm_oclass;
 		device->oclass[NVDEV_SUBDEV_MXM    ] = &nv50_mxm_oclass;
-		device->oclass[NVDEV_SUBDEV_DEVINIT] = &nvc0_devinit_oclass;
+		device->oclass[NVDEV_SUBDEV_DEVINIT] =  nvc0_devinit_oclass;
 		device->oclass[NVDEV_SUBDEV_MC     ] =  nvc3_mc_oclass;
 		device->oclass[NVDEV_SUBDEV_BUS    ] =  nvc0_bus_oclass;
 		device->oclass[NVDEV_SUBDEV_TIMER  ] = &nv04_timer_oclass;
 		device->oclass[NVDEV_SUBDEV_FB     ] =  nve0_fb_oclass;
 		device->oclass[NVDEV_SUBDEV_LTCG   ] = &nvc0_ltcg_oclass;
 		device->oclass[NVDEV_SUBDEV_IBUS   ] = &nve0_ibus_oclass;
-		device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv50_instmem_oclass;
+		device->oclass[NVDEV_SUBDEV_INSTMEM] =  nv50_instmem_oclass;
 		device->oclass[NVDEV_SUBDEV_VM     ] = &nvc0_vmmgr_oclass;
 		device->oclass[NVDEV_SUBDEV_BAR    ] = &nvc0_bar_oclass;
 		device->oclass[NVDEV_SUBDEV_PWR    ] = &nv108_pwr_oclass;
 		device->oclass[NVDEV_SUBDEV_VOLT   ] = &nv40_volt_oclass;
 		device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nvd0_dmaeng_oclass;
-#if 0
-		device->oclass[NVDEV_ENGINE_FIFO   ] =  nve0_fifo_oclass;
+		device->oclass[NVDEV_ENGINE_FIFO   ] =  nv108_fifo_oclass;
 		device->oclass[NVDEV_ENGINE_SW     ] =  nvc0_software_oclass;
-		device->oclass[NVDEV_ENGINE_GR     ] =  nvf0_graph_oclass;
-#endif
+		device->oclass[NVDEV_ENGINE_GR     ] =  nv108_graph_oclass;
 		device->oclass[NVDEV_ENGINE_DISP   ] = &nvf0_disp_oclass;
-#if 0
 		device->oclass[NVDEV_ENGINE_COPY0  ] = &nve0_copy0_oclass;
 		device->oclass[NVDEV_ENGINE_COPY1  ] = &nve0_copy1_oclass;
 		device->oclass[NVDEV_ENGINE_COPY2  ] = &nve0_copy2_oclass;
+#if 0
 		device->oclass[NVDEV_ENGINE_BSP    ] = &nve0_bsp_oclass;
 		device->oclass[NVDEV_ENGINE_VP     ] = &nve0_vp_oclass;
 		device->oclass[NVDEV_ENGINE_PPP    ] = &nvc0_ppp_oclass;
diff --git a/drivers/gpu/drm/nouveau/core/engine/disp/nv04.c b/drivers/gpu/drm/nouveau/core/engine/disp/nv04.c
index a0bc8a89b6994..7cf8b13486326 100644
--- a/drivers/gpu/drm/nouveau/core/engine/disp/nv04.c
+++ b/drivers/gpu/drm/nouveau/core/engine/disp/nv04.c
@@ -31,9 +31,45 @@ struct nv04_disp_priv {
 	struct nouveau_disp base;
 };
 
+static int
+nv04_disp_scanoutpos(struct nouveau_object *object, u32 mthd,
+		     void *data, u32 size)
+{
+	struct nv04_disp_priv *priv = (void *)object->engine;
+	struct nv04_display_scanoutpos *args = data;
+	const int head = (mthd & NV04_DISP_MTHD_HEAD);
+	u32 line;
+
+	if (size < sizeof(*args))
+		return -EINVAL;
+
+	args->vblanks = nv_rd32(priv, 0x680800 + (head * 0x2000)) & 0xffff;
+	args->vtotal  = nv_rd32(priv, 0x680804 + (head * 0x2000)) & 0xffff;
+	args->vblanke = args->vtotal - 1;
+
+	args->hblanks = nv_rd32(priv, 0x680820 + (head * 0x2000)) & 0xffff;
+	args->htotal  = nv_rd32(priv, 0x680824 + (head * 0x2000)) & 0xffff;
+	args->hblanke = args->htotal - 1;
+
+	args->time[0] = ktime_to_ns(ktime_get());
+	line = nv_rd32(priv, 0x600868 + (head * 0x2000));
+	args->time[1] = ktime_to_ns(ktime_get());
+	args->hline = (line & 0xffff0000) >> 16;
+	args->vline = (line & 0x0000ffff);
+	return 0;
+}
+
+#define HEAD_MTHD(n) (n), (n) + 0x01
+
+static struct nouveau_omthds
+nv04_disp_omthds[] = {
+	{ HEAD_MTHD(NV04_DISP_SCANOUTPOS), nv04_disp_scanoutpos },
+	{}
+};
+
 static struct nouveau_oclass
 nv04_disp_sclass[] = {
-	{ NV04_DISP_CLASS, &nouveau_object_ofuncs },
+	{ NV04_DISP_CLASS, &nouveau_object_ofuncs, nv04_disp_omthds },
 	{},
 };
 
diff --git a/drivers/gpu/drm/nouveau/core/engine/disp/nv50.c b/drivers/gpu/drm/nouveau/core/engine/disp/nv50.c
index c168ae3eaa97c..940eaa5d8b9a4 100644
--- a/drivers/gpu/drm/nouveau/core/engine/disp/nv50.c
+++ b/drivers/gpu/drm/nouveau/core/engine/disp/nv50.c
@@ -541,6 +541,35 @@ nv50_disp_curs_ofuncs = {
  * Base display object
  ******************************************************************************/
 
+int
+nv50_disp_base_scanoutpos(struct nouveau_object *object, u32 mthd,
+			  void *data, u32 size)
+{
+	struct nv50_disp_priv *priv = (void *)object->engine;
+	struct nv04_display_scanoutpos *args = data;
+	const int head = (mthd & NV50_DISP_MTHD_HEAD);
+	u32 blanke, blanks, total;
+
+	if (size < sizeof(*args) || head >= priv->head.nr)
+		return -EINVAL;
+	blanke = nv_rd32(priv, 0x610aec + (head * 0x540));
+	blanks = nv_rd32(priv, 0x610af4 + (head * 0x540));
+	total  = nv_rd32(priv, 0x610afc + (head * 0x540));
+
+	args->vblanke = (blanke & 0xffff0000) >> 16;
+	args->hblanke = (blanke & 0x0000ffff);
+	args->vblanks = (blanks & 0xffff0000) >> 16;
+	args->hblanks = (blanks & 0x0000ffff);
+	args->vtotal  = ( total & 0xffff0000) >> 16;
+	args->htotal  = ( total & 0x0000ffff);
+
+	args->time[0] = ktime_to_ns(ktime_get());
+	args->vline   = nv_rd32(priv, 0x616340 + (head * 0x800)) & 0xffff;
+	args->time[1] = ktime_to_ns(ktime_get()); /* vline read locks hline */
+	args->hline   = nv_rd32(priv, 0x616344 + (head * 0x800)) & 0xffff;
+	return 0;
+}
+
 static void
 nv50_disp_base_vblank_enable(struct nouveau_event *event, int head)
 {
@@ -675,6 +704,7 @@ nv50_disp_base_ofuncs = {
 
 static struct nouveau_omthds
 nv50_disp_base_omthds[] = {
+	{ HEAD_MTHD(NV50_DISP_SCANOUTPOS)     , nv50_disp_base_scanoutpos },
 	{ SOR_MTHD(NV50_DISP_SOR_PWR)         , nv50_sor_mthd },
 	{ SOR_MTHD(NV50_DISP_SOR_LVDS_SCRIPT) , nv50_sor_mthd },
 	{ DAC_MTHD(NV50_DISP_DAC_PWR)         , nv50_dac_mthd },
diff --git a/drivers/gpu/drm/nouveau/core/engine/disp/nv50.h b/drivers/gpu/drm/nouveau/core/engine/disp/nv50.h
index 1ae6ceb567040..d31d426ea1f63 100644
--- a/drivers/gpu/drm/nouveau/core/engine/disp/nv50.h
+++ b/drivers/gpu/drm/nouveau/core/engine/disp/nv50.h
@@ -43,6 +43,10 @@ struct nv50_disp_priv {
 	} pior;
 };
 
+#define HEAD_MTHD(n) (n), (n) + 0x03
+
+int nv50_disp_base_scanoutpos(struct nouveau_object *, u32, void *, u32);
+
 #define DAC_MTHD(n) (n), (n) + 0x03
 
 int nv50_dac_mthd(struct nouveau_object *, u32, void *, u32);
@@ -132,13 +136,12 @@ void nv50_disp_intr(struct nouveau_subdev *);
 
 extern struct nouveau_omthds nv84_disp_base_omthds[];
 
-extern struct nouveau_omthds nva3_disp_base_omthds[];
-
 extern struct nouveau_ofuncs nvd0_disp_mast_ofuncs;
 extern struct nouveau_ofuncs nvd0_disp_sync_ofuncs;
 extern struct nouveau_ofuncs nvd0_disp_ovly_ofuncs;
 extern struct nouveau_ofuncs nvd0_disp_oimm_ofuncs;
 extern struct nouveau_ofuncs nvd0_disp_curs_ofuncs;
+extern struct nouveau_omthds nvd0_disp_base_omthds[];
 extern struct nouveau_ofuncs nvd0_disp_base_ofuncs;
 extern struct nouveau_oclass nvd0_disp_cclass;
 void nvd0_disp_intr_supervisor(struct work_struct *);
diff --git a/drivers/gpu/drm/nouveau/core/engine/disp/nv84.c b/drivers/gpu/drm/nouveau/core/engine/disp/nv84.c
index d8c74c0883a16..ef9ce300a496e 100644
--- a/drivers/gpu/drm/nouveau/core/engine/disp/nv84.c
+++ b/drivers/gpu/drm/nouveau/core/engine/disp/nv84.c
@@ -41,6 +41,7 @@ nv84_disp_sclass[] = {
 
 struct nouveau_omthds
 nv84_disp_base_omthds[] = {
+	{ HEAD_MTHD(NV50_DISP_SCANOUTPOS)     , nv50_disp_base_scanoutpos },
 	{ SOR_MTHD(NV50_DISP_SOR_PWR)         , nv50_sor_mthd },
 	{ SOR_MTHD(NV84_DISP_SOR_HDMI_PWR)    , nv50_sor_mthd },
 	{ SOR_MTHD(NV50_DISP_SOR_LVDS_SCRIPT) , nv50_sor_mthd },
diff --git a/drivers/gpu/drm/nouveau/core/engine/disp/nv94.c b/drivers/gpu/drm/nouveau/core/engine/disp/nv94.c
index a66f949c1f841..a518543c00ab6 100644
--- a/drivers/gpu/drm/nouveau/core/engine/disp/nv94.c
+++ b/drivers/gpu/drm/nouveau/core/engine/disp/nv94.c
@@ -41,6 +41,7 @@ nv94_disp_sclass[] = {
 
 static struct nouveau_omthds
 nv94_disp_base_omthds[] = {
+	{ HEAD_MTHD(NV50_DISP_SCANOUTPOS)     , nv50_disp_base_scanoutpos },
 	{ SOR_MTHD(NV50_DISP_SOR_PWR)         , nv50_sor_mthd },
 	{ SOR_MTHD(NV84_DISP_SOR_HDMI_PWR)    , nv50_sor_mthd },
 	{ SOR_MTHD(NV50_DISP_SOR_LVDS_SCRIPT) , nv50_sor_mthd },
diff --git a/drivers/gpu/drm/nouveau/core/engine/disp/nva3.c b/drivers/gpu/drm/nouveau/core/engine/disp/nva3.c
index b75413169eaee..6ad6dcece43bd 100644
--- a/drivers/gpu/drm/nouveau/core/engine/disp/nva3.c
+++ b/drivers/gpu/drm/nouveau/core/engine/disp/nva3.c
@@ -39,8 +39,9 @@ nva3_disp_sclass[] = {
 	{}
 };
 
-struct nouveau_omthds
+static struct nouveau_omthds
 nva3_disp_base_omthds[] = {
+	{ HEAD_MTHD(NV50_DISP_SCANOUTPOS)     , nv50_disp_base_scanoutpos },
 	{ SOR_MTHD(NV50_DISP_SOR_PWR)         , nv50_sor_mthd },
 	{ SOR_MTHD(NVA3_DISP_SOR_HDA_ELD)     , nv50_sor_mthd },
 	{ SOR_MTHD(NV84_DISP_SOR_HDMI_PWR)    , nv50_sor_mthd },
diff --git a/drivers/gpu/drm/nouveau/core/engine/disp/nvd0.c b/drivers/gpu/drm/nouveau/core/engine/disp/nvd0.c
index 378a015091d2b..1c5e4e8b2c822 100644
--- a/drivers/gpu/drm/nouveau/core/engine/disp/nvd0.c
+++ b/drivers/gpu/drm/nouveau/core/engine/disp/nvd0.c
@@ -440,6 +440,36 @@ nvd0_disp_curs_ofuncs = {
  * Base display object
  ******************************************************************************/
 
+static int
+nvd0_disp_base_scanoutpos(struct nouveau_object *object, u32 mthd,
+			  void *data, u32 size)
+{
+	struct nv50_disp_priv *priv = (void *)object->engine;
+	struct nv04_display_scanoutpos *args = data;
+	const int head = (mthd & NV50_DISP_MTHD_HEAD);
+	u32 blanke, blanks, total;
+
+	if (size < sizeof(*args) || head >= priv->head.nr)
+		return -EINVAL;
+
+	total  = nv_rd32(priv, 0x640414 + (head * 0x300));
+	blanke = nv_rd32(priv, 0x64041c + (head * 0x300));
+	blanks = nv_rd32(priv, 0x640420 + (head * 0x300));
+
+	args->vblanke = (blanke & 0xffff0000) >> 16;
+	args->hblanke = (blanke & 0x0000ffff);
+	args->vblanks = (blanks & 0xffff0000) >> 16;
+	args->hblanks = (blanks & 0x0000ffff);
+	args->vtotal  = ( total & 0xffff0000) >> 16;
+	args->htotal  = ( total & 0x0000ffff);
+
+	args->time[0] = ktime_to_ns(ktime_get());
+	args->vline   = nv_rd32(priv, 0x616340 + (head * 0x800)) & 0xffff;
+	args->time[1] = ktime_to_ns(ktime_get()); /* vline read locks hline */
+	args->hline   = nv_rd32(priv, 0x616344 + (head * 0x800)) & 0xffff;
+	return 0;
+}
+
 static void
 nvd0_disp_base_vblank_enable(struct nouveau_event *event, int head)
 {
@@ -573,9 +603,24 @@ nvd0_disp_base_ofuncs = {
 	.fini = nvd0_disp_base_fini,
 };
 
+struct nouveau_omthds
+nvd0_disp_base_omthds[] = {
+	{ HEAD_MTHD(NV50_DISP_SCANOUTPOS)     , nvd0_disp_base_scanoutpos },
+	{ SOR_MTHD(NV50_DISP_SOR_PWR)         , nv50_sor_mthd },
+	{ SOR_MTHD(NVA3_DISP_SOR_HDA_ELD)     , nv50_sor_mthd },
+	{ SOR_MTHD(NV84_DISP_SOR_HDMI_PWR)    , nv50_sor_mthd },
+	{ SOR_MTHD(NV50_DISP_SOR_LVDS_SCRIPT) , nv50_sor_mthd },
+	{ DAC_MTHD(NV50_DISP_DAC_PWR)         , nv50_dac_mthd },
+	{ DAC_MTHD(NV50_DISP_DAC_LOAD)        , nv50_dac_mthd },
+	{ PIOR_MTHD(NV50_DISP_PIOR_PWR)       , nv50_pior_mthd },
+	{ PIOR_MTHD(NV50_DISP_PIOR_TMDS_PWR)  , nv50_pior_mthd },
+	{ PIOR_MTHD(NV50_DISP_PIOR_DP_PWR)    , nv50_pior_mthd },
+	{},
+};
+
 static struct nouveau_oclass
 nvd0_disp_base_oclass[] = {
-	{ NVD0_DISP_CLASS, &nvd0_disp_base_ofuncs, nva3_disp_base_omthds },
+	{ NVD0_DISP_CLASS, &nvd0_disp_base_ofuncs, nvd0_disp_base_omthds },
 	{}
 };
 
@@ -967,9 +1012,6 @@ nvd0_disp_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
 	int heads = nv_rd32(parent, 0x022448);
 	int ret;
 
-	if (nv_rd32(parent, 0x022500) & 0x00000001)
-		return -ENODEV;
-
 	ret = nouveau_disp_create(parent, engine, oclass, heads,
 				  "PDISP", "display", &priv);
 	*pobject = nv_object(priv);
diff --git a/drivers/gpu/drm/nouveau/core/engine/disp/nve0.c b/drivers/gpu/drm/nouveau/core/engine/disp/nve0.c
index fb1fe6ae5e74d..ab63f32c00b24 100644
--- a/drivers/gpu/drm/nouveau/core/engine/disp/nve0.c
+++ b/drivers/gpu/drm/nouveau/core/engine/disp/nve0.c
@@ -41,7 +41,7 @@ nve0_disp_sclass[] = {
 
 static struct nouveau_oclass
 nve0_disp_base_oclass[] = {
-	{ NVE0_DISP_CLASS, &nvd0_disp_base_ofuncs, nva3_disp_base_omthds },
+	{ NVE0_DISP_CLASS, &nvd0_disp_base_ofuncs, nvd0_disp_base_omthds },
 	{}
 };
 
@@ -54,9 +54,6 @@ nve0_disp_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
 	int heads = nv_rd32(parent, 0x022448);
 	int ret;
 
-	if (nv_rd32(parent, 0x022500) & 0x00000001)
-		return -ENODEV;
-
 	ret = nouveau_disp_create(parent, engine, oclass, heads,
 				  "PDISP", "display", &priv);
 	*pobject = nv_object(priv);
diff --git a/drivers/gpu/drm/nouveau/core/engine/disp/nvf0.c b/drivers/gpu/drm/nouveau/core/engine/disp/nvf0.c
index 42aa6b97dbea3..05fee10e0c975 100644
--- a/drivers/gpu/drm/nouveau/core/engine/disp/nvf0.c
+++ b/drivers/gpu/drm/nouveau/core/engine/disp/nvf0.c
@@ -41,7 +41,7 @@ nvf0_disp_sclass[] = {
 
 static struct nouveau_oclass
 nvf0_disp_base_oclass[] = {
-	{ NVF0_DISP_CLASS, &nvd0_disp_base_ofuncs, nva3_disp_base_omthds },
+	{ NVF0_DISP_CLASS, &nvd0_disp_base_ofuncs, nvd0_disp_base_omthds },
 	{}
 };
 
@@ -54,9 +54,6 @@ nvf0_disp_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
 	int heads = nv_rd32(parent, 0x022448);
 	int ret;
 
-	if (nv_rd32(parent, 0x022500) & 0x00000001)
-		return -ENODEV;
-
 	ret = nouveau_disp_create(parent, engine, oclass, heads,
 				  "PDISP", "display", &priv);
 	*pobject = nv_object(priv);
diff --git a/drivers/gpu/drm/nouveau/core/engine/disp/vga.c b/drivers/gpu/drm/nouveau/core/engine/disp/vga.c
index 5a1c68474597c..8836c3cb99c38 100644
--- a/drivers/gpu/drm/nouveau/core/engine/disp/vga.c
+++ b/drivers/gpu/drm/nouveau/core/engine/disp/vga.c
@@ -138,10 +138,15 @@ nv_wrvgai(void *obj, int head, u16 port, u8 index, u8 value)
 bool
 nv_lockvgac(void *obj, bool lock)
 {
+	struct nouveau_device *dev = nv_device(obj);
+
 	bool locked = !nv_rdvgac(obj, 0, 0x1f);
 	u8 data = lock ? 0x99 : 0x57;
-	nv_wrvgac(obj, 0, 0x1f, data);
-	if (nv_device(obj)->chipset == 0x11) {
+	if (dev->card_type < NV_50)
+		nv_wrvgac(obj, 0, 0x1f, data);
+	else
+		nv_wrvgac(obj, 0, 0x3f, data);
+	if (dev->chipset == 0x11) {
 		if (!(nv_rd32(obj, 0x001084) & 0x10000000))
 			nv_wrvgac(obj, 1, 0x1f, data);
 	}
diff --git a/drivers/gpu/drm/nouveau/core/engine/falcon.c b/drivers/gpu/drm/nouveau/core/engine/falcon.c
index e03fc8e4dc1da..5e077e4ed7f6a 100644
--- a/drivers/gpu/drm/nouveau/core/engine/falcon.c
+++ b/drivers/gpu/drm/nouveau/core/engine/falcon.c
@@ -56,6 +56,16 @@ _nouveau_falcon_wr32(struct nouveau_object *object, u64 addr, u32 data)
 	nv_wr32(falcon, falcon->addr + addr, data);
 }
 
+static void *
+vmemdup(const void *src, size_t len)
+{
+	void *p = vmalloc(len);
+
+	if (p)
+		memcpy(p, src, len);
+	return p;
+}
+
 int
 _nouveau_falcon_init(struct nouveau_object *object)
 {
@@ -111,7 +121,7 @@ _nouveau_falcon_init(struct nouveau_object *object)
 
 		ret = request_firmware(&fw, name, &device->pdev->dev);
 		if (ret == 0) {
-			falcon->code.data = kmemdup(fw->data, fw->size, GFP_KERNEL);
+			falcon->code.data = vmemdup(fw->data, fw->size);
 			falcon->code.size = fw->size;
 			falcon->data.data = NULL;
 			falcon->data.size = 0;
@@ -134,7 +144,7 @@ _nouveau_falcon_init(struct nouveau_object *object)
 			return ret;
 		}
 
-		falcon->data.data = kmemdup(fw->data, fw->size, GFP_KERNEL);
+		falcon->data.data = vmemdup(fw->data, fw->size);
 		falcon->data.size = fw->size;
 		release_firmware(fw);
 		if (!falcon->data.data)
@@ -149,7 +159,7 @@ _nouveau_falcon_init(struct nouveau_object *object)
 			return ret;
 		}
 
-		falcon->code.data = kmemdup(fw->data, fw->size, GFP_KERNEL);
+		falcon->code.data = vmemdup(fw->data, fw->size);
 		falcon->code.size = fw->size;
 		release_firmware(fw);
 		if (!falcon->code.data)
@@ -235,8 +245,8 @@ _nouveau_falcon_fini(struct nouveau_object *object, bool suspend)
 	if (!suspend) {
 		nouveau_gpuobj_ref(NULL, &falcon->core);
 		if (falcon->external) {
-			kfree(falcon->data.data);
-			kfree(falcon->code.data);
+			vfree(falcon->data.data);
+			vfree(falcon->code.data);
 			falcon->code.data = NULL;
 		}
 	}
diff --git a/drivers/gpu/drm/nouveau/core/engine/fifo/nv108.c b/drivers/gpu/drm/nouveau/core/engine/fifo/nv108.c
new file mode 100644
index 0000000000000..09362a51ba577
--- /dev/null
+++ b/drivers/gpu/drm/nouveau/core/engine/fifo/nv108.c
@@ -0,0 +1,37 @@
+/*
+ * Copyright 2013 Red Hat Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: Ben Skeggs
+ */
+
+#include "nve0.h"
+
+struct nouveau_oclass *
+nv108_fifo_oclass = &(struct nve0_fifo_impl) {
+	.base.handle = NV_ENGINE(FIFO, 0x08),
+	.base.ofuncs = &(struct nouveau_ofuncs) {
+		.ctor = nve0_fifo_ctor,
+		.dtor = nve0_fifo_dtor,
+		.init = nve0_fifo_init,
+		.fini = _nouveau_fifo_fini,
+	},
+	.channels = 1024,
+}.base;
diff --git a/drivers/gpu/drm/nouveau/core/engine/fifo/nvc0.c b/drivers/gpu/drm/nouveau/core/engine/fifo/nvc0.c
index 9ac94d4e5646d..b22a33f0702dd 100644
--- a/drivers/gpu/drm/nouveau/core/engine/fifo/nvc0.c
+++ b/drivers/gpu/drm/nouveau/core/engine/fifo/nvc0.c
@@ -33,6 +33,7 @@
 
 #include <subdev/timer.h>
 #include <subdev/bar.h>
+#include <subdev/fb.h>
 #include <subdev/vm.h>
 
 #include <engine/dmaobj.h>
diff --git a/drivers/gpu/drm/nouveau/core/engine/fifo/nve0.c b/drivers/gpu/drm/nouveau/core/engine/fifo/nve0.c
index 04f412922d2d4..9a850fe19515f 100644
--- a/drivers/gpu/drm/nouveau/core/engine/fifo/nve0.c
+++ b/drivers/gpu/drm/nouveau/core/engine/fifo/nve0.c
@@ -33,10 +33,12 @@
 
 #include <subdev/timer.h>
 #include <subdev/bar.h>
+#include <subdev/fb.h>
 #include <subdev/vm.h>
 
 #include <engine/dmaobj.h>
-#include <engine/fifo.h>
+
+#include "nve0.h"
 
 #define _(a,b) { (a), ((1ULL << (a)) | (b)) }
 static const struct {
@@ -56,8 +58,8 @@ static const struct {
 #define FIFO_ENGINE_NR ARRAY_SIZE(fifo_engine)
 
 struct nve0_fifo_engn {
-	struct nouveau_gpuobj *playlist[2];
-	int cur_playlist;
+	struct nouveau_gpuobj *runlist[2];
+	int cur_runlist;
 };
 
 struct nve0_fifo_priv {
@@ -86,7 +88,7 @@ struct nve0_fifo_chan {
  ******************************************************************************/
 
 static void
-nve0_fifo_playlist_update(struct nve0_fifo_priv *priv, u32 engine)
+nve0_fifo_runlist_update(struct nve0_fifo_priv *priv, u32 engine)
 {
 	struct nouveau_bar *bar = nouveau_bar(priv);
 	struct nve0_fifo_engn *engn = &priv->engine[engine];
@@ -95,8 +97,8 @@ nve0_fifo_playlist_update(struct nve0_fifo_priv *priv, u32 engine)
 	int i, p;
 
 	mutex_lock(&nv_subdev(priv)->mutex);
-	cur = engn->playlist[engn->cur_playlist];
-	engn->cur_playlist = !engn->cur_playlist;
+	cur = engn->runlist[engn->cur_runlist];
+	engn->cur_runlist = !engn->cur_runlist;
 
 	for (i = 0, p = 0; i < priv->base.max; i++) {
 		u32 ctrl = nv_rd32(priv, 0x800004 + (i * 8)) & 0x001f0001;
@@ -111,7 +113,7 @@ nve0_fifo_playlist_update(struct nve0_fifo_priv *priv, u32 engine)
 	nv_wr32(priv, 0x002270, cur->addr >> 12);
 	nv_wr32(priv, 0x002274, (engine << 20) | (p >> 3));
 	if (!nv_wait(priv, 0x002284 + (engine * 4), 0x00100000, 0x00000000))
-		nv_error(priv, "playlist %d update timeout\n", engine);
+		nv_error(priv, "runlist %d update timeout\n", engine);
 	mutex_unlock(&nv_subdev(priv)->mutex);
 }
 
@@ -278,7 +280,7 @@ nve0_fifo_chan_init(struct nouveau_object *object)
 	nv_mask(priv, 0x800004 + (chid * 8), 0x000f0000, chan->engine << 16);
 	nv_wr32(priv, 0x800000 + (chid * 8), 0x80000000 | base->addr >> 12);
 	nv_mask(priv, 0x800004 + (chid * 8), 0x00000400, 0x00000400);
-	nve0_fifo_playlist_update(priv, chan->engine);
+	nve0_fifo_runlist_update(priv, chan->engine);
 	nv_mask(priv, 0x800004 + (chid * 8), 0x00000400, 0x00000400);
 	return 0;
 }
@@ -291,7 +293,7 @@ nve0_fifo_chan_fini(struct nouveau_object *object, bool suspend)
 	u32 chid = chan->base.chid;
 
 	nv_mask(priv, 0x800004 + (chid * 8), 0x00000800, 0x00000800);
-	nve0_fifo_playlist_update(priv, chan->engine);
+	nve0_fifo_runlist_update(priv, chan->engine);
 	nv_wr32(priv, 0x800000 + (chid * 8), 0x00000000);
 
 	return nouveau_fifo_channel_fini(&chan->base, suspend);
@@ -375,54 +377,189 @@ nve0_fifo_cclass = {
  * PFIFO engine
  ******************************************************************************/
 
-static const struct nouveau_enum nve0_fifo_fault_unit[] = {
+static const struct nouveau_enum nve0_fifo_sched_reason[] = {
+	{ 0x0a, "CTXSW_TIMEOUT" },
+	{}
+};
+
+static const struct nouveau_enum nve0_fifo_fault_engine[] = {
+	{ 0x00, "GR", NULL, NVDEV_ENGINE_GR },
+	{ 0x03, "IFB" },
+	{ 0x04, "BAR1", NULL, NVDEV_SUBDEV_BAR },
+	{ 0x05, "BAR3", NULL, NVDEV_SUBDEV_INSTMEM },
+	{ 0x07, "PBDMA0", NULL, NVDEV_ENGINE_FIFO },
+	{ 0x08, "PBDMA1", NULL, NVDEV_ENGINE_FIFO },
+	{ 0x09, "PBDMA2", NULL, NVDEV_ENGINE_FIFO },
+	{ 0x10, "MSVLD", NULL, NVDEV_ENGINE_BSP },
+	{ 0x11, "MSPPP", NULL, NVDEV_ENGINE_PPP },
+	{ 0x13, "PERF" },
+	{ 0x14, "MSPDEC", NULL, NVDEV_ENGINE_VP },
+	{ 0x15, "CE0", NULL, NVDEV_ENGINE_COPY0 },
+	{ 0x16, "CE1", NULL, NVDEV_ENGINE_COPY1 },
+	{ 0x17, "PMU" },
+	{ 0x19, "MSENC", NULL, NVDEV_ENGINE_VENC },
+	{ 0x1b, "CE2", NULL, NVDEV_ENGINE_COPY2 },
 	{}
 };
 
 static const struct nouveau_enum nve0_fifo_fault_reason[] = {
-	{ 0x00, "PT_NOT_PRESENT" },
-	{ 0x01, "PT_TOO_SHORT" },
-	{ 0x02, "PAGE_NOT_PRESENT" },
-	{ 0x03, "VM_LIMIT_EXCEEDED" },
-	{ 0x04, "NO_CHANNEL" },
-	{ 0x05, "PAGE_SYSTEM_ONLY" },
-	{ 0x06, "PAGE_READ_ONLY" },
-	{ 0x0a, "COMPRESSED_SYSRAM" },
-	{ 0x0c, "INVALID_STORAGE_TYPE" },
+	{ 0x00, "PDE" },
+	{ 0x01, "PDE_SIZE" },
+	{ 0x02, "PTE" },
+	{ 0x03, "VA_LIMIT_VIOLATION" },
+	{ 0x04, "UNBOUND_INST_BLOCK" },
+	{ 0x05, "PRIV_VIOLATION" },
+	{ 0x06, "RO_VIOLATION" },
+	{ 0x07, "WO_VIOLATION" },
+	{ 0x08, "PITCH_MASK_VIOLATION" },
+	{ 0x09, "WORK_CREATION" },
+	{ 0x0a, "UNSUPPORTED_APERTURE" },
+	{ 0x0b, "COMPRESSION_FAILURE" },
+	{ 0x0c, "UNSUPPORTED_KIND" },
+	{ 0x0d, "REGION_VIOLATION" },
+	{ 0x0e, "BOTH_PTES_VALID" },
+	{ 0x0f, "INFO_TYPE_POISONED" },
 	{}
 };
 
 static const struct nouveau_enum nve0_fifo_fault_hubclient[] = {
+	{ 0x00, "VIP" },
+	{ 0x01, "CE0" },
+	{ 0x02, "CE1" },
+	{ 0x03, "DNISO" },
+	{ 0x04, "FE" },
+	{ 0x05, "FECS" },
+	{ 0x06, "HOST" },
+	{ 0x07, "HOST_CPU" },
+	{ 0x08, "HOST_CPU_NB" },
+	{ 0x09, "ISO" },
+	{ 0x0a, "MMU" },
+	{ 0x0b, "MSPDEC" },
+	{ 0x0c, "MSPPP" },
+	{ 0x0d, "MSVLD" },
+	{ 0x0e, "NISO" },
+	{ 0x0f, "P2P" },
+	{ 0x10, "PD" },
+	{ 0x11, "PERF" },
+	{ 0x12, "PMU" },
+	{ 0x13, "RASTERTWOD" },
+	{ 0x14, "SCC" },
+	{ 0x15, "SCC_NB" },
+	{ 0x16, "SEC" },
+	{ 0x17, "SSYNC" },
+	{ 0x18, "GR_COPY" },
+	{ 0x19, "CE2" },
+	{ 0x1a, "XV" },
+	{ 0x1b, "MMU_NB" },
+	{ 0x1c, "MSENC" },
+	{ 0x1d, "DFALCON" },
+	{ 0x1e, "SKED" },
+	{ 0x1f, "AFALCON" },
 	{}
 };
 
 static const struct nouveau_enum nve0_fifo_fault_gpcclient[] = {
+	{ 0x00, "L1_0" }, { 0x01, "T1_0" }, { 0x02, "PE_0" },
+	{ 0x03, "L1_1" }, { 0x04, "T1_1" }, { 0x05, "PE_1" },
+	{ 0x06, "L1_2" }, { 0x07, "T1_2" }, { 0x08, "PE_2" },
+	{ 0x09, "L1_3" }, { 0x0a, "T1_3" }, { 0x0b, "PE_3" },
+	{ 0x0c, "RAST" },
+	{ 0x0d, "GCC" },
+	{ 0x0e, "GPCCS" },
+	{ 0x0f, "PROP_0" },
+	{ 0x10, "PROP_1" },
+	{ 0x11, "PROP_2" },
+	{ 0x12, "PROP_3" },
+	{ 0x13, "L1_4" }, { 0x14, "T1_4" }, { 0x15, "PE_4" },
+	{ 0x16, "L1_5" }, { 0x17, "T1_5" }, { 0x18, "PE_5" },
+	{ 0x19, "L1_6" }, { 0x1a, "T1_6" }, { 0x1b, "PE_6" },
+	{ 0x1c, "L1_7" }, { 0x1d, "T1_7" }, { 0x1e, "PE_7" },
+	{ 0x1f, "GPM" },
+	{ 0x20, "LTP_UTLB_0" },
+	{ 0x21, "LTP_UTLB_1" },
+	{ 0x22, "LTP_UTLB_2" },
+	{ 0x23, "LTP_UTLB_3" },
+	{ 0x24, "GPC_RGG_UTLB" },
 	{}
 };
 
-static const struct nouveau_bitfield nve0_fifo_subfifo_intr[] = {
-	{ 0x00200000, "ILLEGAL_MTHD" },
-	{ 0x00800000, "EMPTY_SUBC" },
+static const struct nouveau_bitfield nve0_fifo_pbdma_intr[] = {
+	{ 0x00000001, "MEMREQ" },
+	{ 0x00000002, "MEMACK_TIMEOUT" },
+	{ 0x00000004, "MEMACK_EXTRA" },
+	{ 0x00000008, "MEMDAT_TIMEOUT" },
+	{ 0x00000010, "MEMDAT_EXTRA" },
+	{ 0x00000020, "MEMFLUSH" },
+	{ 0x00000040, "MEMOP" },
+	{ 0x00000080, "LBCONNECT" },
+	{ 0x00000100, "LBREQ" },
+	{ 0x00000200, "LBACK_TIMEOUT" },
+	{ 0x00000400, "LBACK_EXTRA" },
+	{ 0x00000800, "LBDAT_TIMEOUT" },
+	{ 0x00001000, "LBDAT_EXTRA" },
+	{ 0x00002000, "GPFIFO" },
+	{ 0x00004000, "GPPTR" },
+	{ 0x00008000, "GPENTRY" },
+	{ 0x00010000, "GPCRC" },
+	{ 0x00020000, "PBPTR" },
+	{ 0x00040000, "PBENTRY" },
+	{ 0x00080000, "PBCRC" },
+	{ 0x00100000, "XBARCONNECT" },
+	{ 0x00200000, "METHOD" },
+	{ 0x00400000, "METHODCRC" },
+	{ 0x00800000, "DEVICE" },
+	{ 0x02000000, "SEMAPHORE" },
+	{ 0x04000000, "ACQUIRE" },
+	{ 0x08000000, "PRI" },
+	{ 0x20000000, "NO_CTXSW_SEG" },
+	{ 0x40000000, "PBSEG" },
+	{ 0x80000000, "SIGNATURE" },
 	{}
 };
 
 static void
-nve0_fifo_isr_vm_fault(struct nve0_fifo_priv *priv, int unit)
+nve0_fifo_intr_sched(struct nve0_fifo_priv *priv)
+{
+	u32 intr = nv_rd32(priv, 0x00254c);
+	u32 code = intr & 0x000000ff;
+	nv_error(priv, "SCHED_ERROR [");
+	nouveau_enum_print(nve0_fifo_sched_reason, code);
+	pr_cont("]\n");
+}
+
+static void
+nve0_fifo_intr_chsw(struct nve0_fifo_priv *priv)
+{
+	u32 stat = nv_rd32(priv, 0x00256c);
+	nv_error(priv, "CHSW_ERROR 0x%08x\n", stat);
+	nv_wr32(priv, 0x00256c, stat);
+}
+
+static void
+nve0_fifo_intr_dropped_fault(struct nve0_fifo_priv *priv)
+{
+	u32 stat = nv_rd32(priv, 0x00259c);
+	nv_error(priv, "DROPPED_MMU_FAULT 0x%08x\n", stat);
+}
+
+static void
+nve0_fifo_intr_fault(struct nve0_fifo_priv *priv, int unit)
 {
 	u32 inst = nv_rd32(priv, 0x2800 + (unit * 0x10));
 	u32 valo = nv_rd32(priv, 0x2804 + (unit * 0x10));
 	u32 vahi = nv_rd32(priv, 0x2808 + (unit * 0x10));
 	u32 stat = nv_rd32(priv, 0x280c + (unit * 0x10));
 	u32 client = (stat & 0x00001f00) >> 8;
-	const struct nouveau_enum *en;
-	struct nouveau_engine *engine;
+	struct nouveau_engine *engine = NULL;
 	struct nouveau_object *engctx = NULL;
+	const struct nouveau_enum *en;
+	const char *name = "unknown";
 
 	nv_error(priv, "PFIFO: %s fault at 0x%010llx [", (stat & 0x00000080) ?
 		       "write" : "read", (u64)vahi << 32 | valo);
 	nouveau_enum_print(nve0_fifo_fault_reason, stat & 0x0000000f);
 	pr_cont("] from ");
-	en = nouveau_enum_print(nve0_fifo_fault_unit, unit);
+	en = nouveau_enum_print(nve0_fifo_fault_engine, unit);
 	if (stat & 0x00000040) {
 		pr_cont("/");
 		nouveau_enum_print(nve0_fifo_fault_hubclient, client);
@@ -432,14 +569,22 @@ nve0_fifo_isr_vm_fault(struct nve0_fifo_priv *priv, int unit)
 	}
 
 	if (en && en->data2) {
-		engine = nouveau_engine(priv, en->data2);
-		if (engine)
-			engctx = nouveau_engctx_get(engine, inst);
-
+		if (en->data2 == NVDEV_SUBDEV_BAR) {
+			nv_mask(priv, 0x001704, 0x00000000, 0x00000000);
+			name = "BAR1";
+		} else
+		if (en->data2 == NVDEV_SUBDEV_INSTMEM) {
+			nv_mask(priv, 0x001714, 0x00000000, 0x00000000);
+			name = "BAR3";
+		} else {
+			engine = nouveau_engine(priv, en->data2);
+			if (engine) {
+				engctx = nouveau_engctx_get(engine, inst);
+				name   = nouveau_client_name(engctx);
+			}
+		}
 	}
-
-	pr_cont(" on channel 0x%010llx [%s]\n", (u64)inst << 12,
-			nouveau_client_name(engctx));
+	pr_cont(" on channel 0x%010llx [%s]\n", (u64)inst << 12, name);
 
 	nouveau_engctx_put(engctx);
 }
@@ -471,7 +616,7 @@ nve0_fifo_swmthd(struct nve0_fifo_priv *priv, u32 chid, u32 mthd, u32 data)
 }
 
 static void
-nve0_fifo_isr_subfifo_intr(struct nve0_fifo_priv *priv, int unit)
+nve0_fifo_intr_pbdma(struct nve0_fifo_priv *priv, int unit)
 {
 	u32 stat = nv_rd32(priv, 0x040108 + (unit * 0x2000));
 	u32 addr = nv_rd32(priv, 0x0400c0 + (unit * 0x2000));
@@ -487,11 +632,11 @@ nve0_fifo_isr_subfifo_intr(struct nve0_fifo_priv *priv, int unit)
 	}
 
 	if (show) {
-		nv_error(priv, "SUBFIFO%d:", unit);
-		nouveau_bitfield_print(nve0_fifo_subfifo_intr, show);
+		nv_error(priv, "PBDMA%d:", unit);
+		nouveau_bitfield_print(nve0_fifo_pbdma_intr, show);
 		pr_cont("\n");
 		nv_error(priv,
-			 "SUBFIFO%d: ch %d [%s] subc %d mthd 0x%04x data 0x%08x\n",
+			 "PBDMA%d: ch %d [%s] subc %d mthd 0x%04x data 0x%08x\n",
 			 unit, chid,
 			 nouveau_client_name_for_fifo_chid(&priv->base, chid),
 			 subc, mthd, data);
@@ -508,19 +653,56 @@ nve0_fifo_intr(struct nouveau_subdev *subdev)
 	u32 mask = nv_rd32(priv, 0x002140);
 	u32 stat = nv_rd32(priv, 0x002100) & mask;
 
+	if (stat & 0x00000001) {
+		u32 stat = nv_rd32(priv, 0x00252c);
+		nv_error(priv, "BIND_ERROR 0x%08x\n", stat);
+		nv_wr32(priv, 0x002100, 0x00000001);
+		stat &= ~0x00000001;
+	}
+
+	if (stat & 0x00000010) {
+		nv_error(priv, "PIO_ERROR\n");
+		nv_wr32(priv, 0x002100, 0x00000010);
+		stat &= ~0x00000010;
+	}
+
 	if (stat & 0x00000100) {
-		nv_warn(priv, "unknown status 0x00000100\n");
+		nve0_fifo_intr_sched(priv);
 		nv_wr32(priv, 0x002100, 0x00000100);
 		stat &= ~0x00000100;
 	}
 
+	if (stat & 0x00010000) {
+		nve0_fifo_intr_chsw(priv);
+		nv_wr32(priv, 0x002100, 0x00010000);
+		stat &= ~0x00010000;
+	}
+
+	if (stat & 0x00800000) {
+		nv_error(priv, "FB_FLUSH_TIMEOUT\n");
+		nv_wr32(priv, 0x002100, 0x00800000);
+		stat &= ~0x00800000;
+	}
+
+	if (stat & 0x01000000) {
+		nv_error(priv, "LB_ERROR\n");
+		nv_wr32(priv, 0x002100, 0x01000000);
+		stat &= ~0x01000000;
+	}
+
+	if (stat & 0x08000000) {
+		nve0_fifo_intr_dropped_fault(priv);
+		nv_wr32(priv, 0x002100, 0x08000000);
+		stat &= ~0x08000000;
+	}
+
 	if (stat & 0x10000000) {
 		u32 units = nv_rd32(priv, 0x00259c);
 		u32 u = units;
 
 		while (u) {
 			int i = ffs(u) - 1;
-			nve0_fifo_isr_vm_fault(priv, i);
+			nve0_fifo_intr_fault(priv, i);
 			u &= ~(1 << i);
 		}
 
@@ -529,22 +711,28 @@ nve0_fifo_intr(struct nouveau_subdev *subdev)
 	}
 
 	if (stat & 0x20000000) {
-		u32 units = nv_rd32(priv, 0x0025a0);
-		u32 u = units;
+		u32 mask = nv_rd32(priv, 0x0025a0);
+		u32 temp = mask;
 
-		while (u) {
-			int i = ffs(u) - 1;
-			nve0_fifo_isr_subfifo_intr(priv, i);
-			u &= ~(1 << i);
+		while (temp) {
+			u32 unit = ffs(temp) - 1;
+			nve0_fifo_intr_pbdma(priv, unit);
+			temp &= ~(1 << unit);
 		}
 
-		nv_wr32(priv, 0x0025a0, units);
+		nv_wr32(priv, 0x0025a0, mask);
 		stat &= ~0x20000000;
 	}
 
 	if (stat & 0x40000000) {
-		nv_warn(priv, "unknown status 0x40000000\n");
-		nv_mask(priv, 0x002a00, 0x00000000, 0x00000000);
+		u32 mask = nv_mask(priv, 0x002a00, 0x00000000, 0x00000000);
+
+		while (mask) {
+			u32 engn = ffs(mask) - 1;
+			/* runlist event, not currently used */
+			mask &= ~(1 << engn);
+		}
+
 		stat &= ~0x40000000;
 	}
 
@@ -575,53 +763,52 @@ nve0_fifo_uevent_disable(struct nouveau_event *event, int index)
 	nv_mask(priv, 0x002140, 0x80000000, 0x00000000);
 }
 
-static int
-nve0_fifo_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
-	       struct nouveau_oclass *oclass, void *data, u32 size,
-	       struct nouveau_object **pobject)
+int
+nve0_fifo_fini(struct nouveau_object *object, bool suspend)
 {
-	struct nve0_fifo_priv *priv;
-	int ret, i;
+	struct nve0_fifo_priv *priv = (void *)object;
+	int ret;
 
-	ret = nouveau_fifo_create(parent, engine, oclass, 0, 4095, &priv);
-	*pobject = nv_object(priv);
+	ret = nouveau_fifo_fini(&priv->base, suspend);
 	if (ret)
 		return ret;
 
-	for (i = 0; i < FIFO_ENGINE_NR; i++) {
-		ret = nouveau_gpuobj_new(nv_object(priv), NULL, 0x8000, 0x1000,
-					 0, &priv->engine[i].playlist[0]);
-		if (ret)
-			return ret;
+	/* allow mmu fault interrupts, even when we're not using fifo */
+	nv_mask(priv, 0x002140, 0x10000000, 0x10000000);
+	return 0;
+}
 
-		ret = nouveau_gpuobj_new(nv_object(priv), NULL, 0x8000, 0x1000,
-					 0, &priv->engine[i].playlist[1]);
-		if (ret)
-			return ret;
-	}
+int
+nve0_fifo_init(struct nouveau_object *object)
+{
+	struct nve0_fifo_priv *priv = (void *)object;
+	int ret, i;
 
-	ret = nouveau_gpuobj_new(nv_object(priv), NULL, 4096 * 0x200, 0x1000,
-				 NVOBJ_FLAG_ZERO_ALLOC, &priv->user.mem);
+	ret = nouveau_fifo_init(&priv->base);
 	if (ret)
 		return ret;
 
-	ret = nouveau_gpuobj_map(priv->user.mem, NV_MEM_ACCESS_RW,
-				&priv->user.bar);
-	if (ret)
-		return ret;
+	/* enable all available PBDMA units */
+	nv_wr32(priv, 0x000204, 0xffffffff);
+	priv->spoon_nr = hweight32(nv_rd32(priv, 0x000204));
+	nv_debug(priv, "%d PBDMA unit(s)\n", priv->spoon_nr);
 
-	priv->base.uevent->enable = nve0_fifo_uevent_enable;
-	priv->base.uevent->disable = nve0_fifo_uevent_disable;
-	priv->base.uevent->priv = priv;
+	/* PBDMA[n] */
+	for (i = 0; i < priv->spoon_nr; i++) {
+		nv_mask(priv, 0x04013c + (i * 0x2000), 0x10000100, 0x00000000);
+		nv_wr32(priv, 0x040108 + (i * 0x2000), 0xffffffff); /* INTR */
+		nv_wr32(priv, 0x04010c + (i * 0x2000), 0xfffffeff); /* INTREN */
+	}
 
-	nv_subdev(priv)->unit = 0x00000100;
-	nv_subdev(priv)->intr = nve0_fifo_intr;
-	nv_engine(priv)->cclass = &nve0_fifo_cclass;
-	nv_engine(priv)->sclass = nve0_fifo_sclass;
+	nv_wr32(priv, 0x002254, 0x10000000 | priv->user.bar.offset >> 12);
+
+	nv_wr32(priv, 0x002a00, 0xffffffff);
+	nv_wr32(priv, 0x002100, 0xffffffff);
+	nv_wr32(priv, 0x002140, 0x3fffffff);
 	return 0;
 }
 
-static void
+void
 nve0_fifo_dtor(struct nouveau_object *object)
 {
 	struct nve0_fifo_priv *priv = (void *)object;
@@ -631,50 +818,69 @@ nve0_fifo_dtor(struct nouveau_object *object)
 	nouveau_gpuobj_ref(NULL, &priv->user.mem);
 
 	for (i = 0; i < FIFO_ENGINE_NR; i++) {
-		nouveau_gpuobj_ref(NULL, &priv->engine[i].playlist[1]);
-		nouveau_gpuobj_ref(NULL, &priv->engine[i].playlist[0]);
+		nouveau_gpuobj_ref(NULL, &priv->engine[i].runlist[1]);
+		nouveau_gpuobj_ref(NULL, &priv->engine[i].runlist[0]);
 	}
 
 	nouveau_fifo_destroy(&priv->base);
 }
 
-static int
-nve0_fifo_init(struct nouveau_object *object)
+int
+nve0_fifo_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
+	       struct nouveau_oclass *oclass, void *data, u32 size,
+	       struct nouveau_object **pobject)
 {
-	struct nve0_fifo_priv *priv = (void *)object;
+	struct nve0_fifo_impl *impl = (void *)oclass;
+	struct nve0_fifo_priv *priv;
 	int ret, i;
 
-	ret = nouveau_fifo_init(&priv->base);
+	ret = nouveau_fifo_create(parent, engine, oclass, 0,
+				  impl->channels - 1, &priv);
+	*pobject = nv_object(priv);
 	if (ret)
 		return ret;
 
-	/* enable all available PSUBFIFOs */
-	nv_wr32(priv, 0x000204, 0xffffffff);
-	priv->spoon_nr = hweight32(nv_rd32(priv, 0x000204));
-	nv_debug(priv, "%d subfifo(s)\n", priv->spoon_nr);
+	for (i = 0; i < FIFO_ENGINE_NR; i++) {
+		ret = nouveau_gpuobj_new(nv_object(priv), NULL, 0x8000, 0x1000,
+					 0, &priv->engine[i].runlist[0]);
+		if (ret)
+			return ret;
 
-	/* PSUBFIFO[n] */
-	for (i = 0; i < priv->spoon_nr; i++) {
-		nv_mask(priv, 0x04013c + (i * 0x2000), 0x10000100, 0x00000000);
-		nv_wr32(priv, 0x040108 + (i * 0x2000), 0xffffffff); /* INTR */
-		nv_wr32(priv, 0x04010c + (i * 0x2000), 0xfffffeff); /* INTREN */
+		ret = nouveau_gpuobj_new(nv_object(priv), NULL, 0x8000, 0x1000,
+					 0, &priv->engine[i].runlist[1]);
+		if (ret)
+			return ret;
 	}
 
-	nv_wr32(priv, 0x002254, 0x10000000 | priv->user.bar.offset >> 12);
+	ret = nouveau_gpuobj_new(nv_object(priv), NULL, 4096 * 0x200, 0x1000,
+				 NVOBJ_FLAG_ZERO_ALLOC, &priv->user.mem);
+	if (ret)
+		return ret;
 
-	nv_wr32(priv, 0x002a00, 0xffffffff);
-	nv_wr32(priv, 0x002100, 0xffffffff);
-	nv_wr32(priv, 0x002140, 0x3fffffff);
+	ret = nouveau_gpuobj_map(priv->user.mem, NV_MEM_ACCESS_RW,
+				&priv->user.bar);
+	if (ret)
+		return ret;
+
+	priv->base.uevent->enable = nve0_fifo_uevent_enable;
+	priv->base.uevent->disable = nve0_fifo_uevent_disable;
+	priv->base.uevent->priv = priv;
+
+	nv_subdev(priv)->unit = 0x00000100;
+	nv_subdev(priv)->intr = nve0_fifo_intr;
+	nv_engine(priv)->cclass = &nve0_fifo_cclass;
+	nv_engine(priv)->sclass = nve0_fifo_sclass;
 	return 0;
 }
 
 struct nouveau_oclass *
-nve0_fifo_oclass = &(struct nouveau_oclass) {
-	.handle = NV_ENGINE(FIFO, 0xe0),
-	.ofuncs = &(struct nouveau_ofuncs) {
+nve0_fifo_oclass = &(struct nve0_fifo_impl) {
+	.base.handle = NV_ENGINE(FIFO, 0xe0),
+	.base.ofuncs = &(struct nouveau_ofuncs) {
 		.ctor = nve0_fifo_ctor,
 		.dtor = nve0_fifo_dtor,
 		.init = nve0_fifo_init,
-		.fini = _nouveau_fifo_fini,
+		.fini = nve0_fifo_fini,
 	},
-};
+	.channels = 4096,
+}.base;
diff --git a/drivers/gpu/drm/nouveau/core/engine/fifo/nve0.h b/drivers/gpu/drm/nouveau/core/engine/fifo/nve0.h
new file mode 100644
index 0000000000000..014344ebee66c
--- /dev/null
+++ b/drivers/gpu/drm/nouveau/core/engine/fifo/nve0.h
@@ -0,0 +1,17 @@
+#ifndef __NVKM_FIFO_NVE0_H__
+#define __NVKM_FIFO_NVE0_H__
+
+#include <engine/fifo.h>
+
+int  nve0_fifo_ctor(struct nouveau_object *, struct nouveau_object *,
+		    struct nouveau_oclass *, void *, u32,
+		    struct nouveau_object **);
+void nve0_fifo_dtor(struct nouveau_object *);
+int  nve0_fifo_init(struct nouveau_object *);
+
+struct nve0_fifo_impl {
+	struct nouveau_oclass base;
+	u32 channels;
+};
+
+#endif
diff --git a/drivers/gpu/drm/nouveau/core/engine/graph/ctxnv108.c b/drivers/gpu/drm/nouveau/core/engine/graph/ctxnv108.c
new file mode 100644
index 0000000000000..a86bd3352bf82
--- /dev/null
+++ b/drivers/gpu/drm/nouveau/core/engine/graph/ctxnv108.c
@@ -0,0 +1,1408 @@
+/*
+ * Copyright 2013 Red Hat Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: Ben Skeggs <bskeggs@redhat.com>
+ */
+
+#include "nvc0.h"
+
+static struct nvc0_graph_init
+nv108_grctx_init_icmd[] = {
+	{ 0x001000,   1, 0x01, 0x00000004 },
+	{ 0x000039,   3, 0x01, 0x00000000 },
+	{ 0x0000a9,   1, 0x01, 0x0000ffff },
+	{ 0x000038,   1, 0x01, 0x0fac6881 },
+	{ 0x00003d,   1, 0x01, 0x00000001 },
+	{ 0x0000e8,   8, 0x01, 0x00000400 },
+	{ 0x000078,   8, 0x01, 0x00000300 },
+	{ 0x000050,   1, 0x01, 0x00000011 },
+	{ 0x000058,   8, 0x01, 0x00000008 },
+	{ 0x000208,   8, 0x01, 0x00000001 },
+	{ 0x000081,   1, 0x01, 0x00000001 },
+	{ 0x000085,   1, 0x01, 0x00000004 },
+	{ 0x000088,   1, 0x01, 0x00000400 },
+	{ 0x000090,   1, 0x01, 0x00000300 },
+	{ 0x000098,   1, 0x01, 0x00001001 },
+	{ 0x0000e3,   1, 0x01, 0x00000001 },
+	{ 0x0000da,   1, 0x01, 0x00000001 },
+	{ 0x0000f8,   1, 0x01, 0x00000003 },
+	{ 0x0000fa,   1, 0x01, 0x00000001 },
+	{ 0x00009f,   4, 0x01, 0x0000ffff },
+	{ 0x0000b1,   1, 0x01, 0x00000001 },
+	{ 0x0000ad,   1, 0x01, 0x0000013e },
+	{ 0x0000e1,   1, 0x01, 0x00000010 },
+	{ 0x000290,  16, 0x01, 0x00000000 },
+	{ 0x0003b0,  16, 0x01, 0x00000000 },
+	{ 0x0002a0,  16, 0x01, 0x00000000 },
+	{ 0x000420,  16, 0x01, 0x00000000 },
+	{ 0x0002b0,  16, 0x01, 0x00000000 },
+	{ 0x000430,  16, 0x01, 0x00000000 },
+	{ 0x0002c0,  16, 0x01, 0x00000000 },
+	{ 0x0004d0,  16, 0x01, 0x00000000 },
+	{ 0x000720,  16, 0x01, 0x00000000 },
+	{ 0x0008c0,  16, 0x01, 0x00000000 },
+	{ 0x000890,  16, 0x01, 0x00000000 },
+	{ 0x0008e0,  16, 0x01, 0x00000000 },
+	{ 0x0008a0,  16, 0x01, 0x00000000 },
+	{ 0x0008f0,  16, 0x01, 0x00000000 },
+	{ 0x00094c,   1, 0x01, 0x000000ff },
+	{ 0x00094d,   1, 0x01, 0xffffffff },
+	{ 0x00094e,   1, 0x01, 0x00000002 },
+	{ 0x0002ec,   1, 0x01, 0x00000001 },
+	{ 0x0002f2,   2, 0x01, 0x00000001 },
+	{ 0x0002f5,   1, 0x01, 0x00000001 },
+	{ 0x0002f7,   1, 0x01, 0x00000001 },
+	{ 0x000303,   1, 0x01, 0x00000001 },
+	{ 0x0002e6,   1, 0x01, 0x00000001 },
+	{ 0x000466,   1, 0x01, 0x00000052 },
+	{ 0x000301,   1, 0x01, 0x3f800000 },
+	{ 0x000304,   1, 0x01, 0x30201000 },
+	{ 0x000305,   1, 0x01, 0x70605040 },
+	{ 0x000306,   1, 0x01, 0xb8a89888 },
+	{ 0x000307,   1, 0x01, 0xf8e8d8c8 },
+	{ 0x00030a,   1, 0x01, 0x00ffff00 },
+	{ 0x00030b,   1, 0x01, 0x0000001a },
+	{ 0x00030c,   1, 0x01, 0x00000001 },
+	{ 0x000318,   1, 0x01, 0x00000001 },
+	{ 0x000340,   1, 0x01, 0x00000000 },
+	{ 0x000375,   1, 0x01, 0x00000001 },
+	{ 0x00037d,   1, 0x01, 0x00000006 },
+	{ 0x0003a0,   1, 0x01, 0x00000002 },
+	{ 0x0003aa,   1, 0x01, 0x00000001 },
+	{ 0x0003a9,   1, 0x01, 0x00000001 },
+	{ 0x000380,   1, 0x01, 0x00000001 },
+	{ 0x000383,   1, 0x01, 0x00000011 },
+	{ 0x000360,   1, 0x01, 0x00000040 },
+	{ 0x000366,   2, 0x01, 0x00000000 },
+	{ 0x000368,   1, 0x01, 0x00000fff },
+	{ 0x000370,   2, 0x01, 0x00000000 },
+	{ 0x000372,   1, 0x01, 0x000fffff },
+	{ 0x00037a,   1, 0x01, 0x00000012 },
+	{ 0x000619,   1, 0x01, 0x00000003 },
+	{ 0x000811,   1, 0x01, 0x00000003 },
+	{ 0x000812,   1, 0x01, 0x00000004 },
+	{ 0x000813,   1, 0x01, 0x00000006 },
+	{ 0x000814,   1, 0x01, 0x00000008 },
+	{ 0x000815,   1, 0x01, 0x0000000b },
+	{ 0x000800,   6, 0x01, 0x00000001 },
+	{ 0x000632,   1, 0x01, 0x00000001 },
+	{ 0x000633,   1, 0x01, 0x00000002 },
+	{ 0x000634,   1, 0x01, 0x00000003 },
+	{ 0x000635,   1, 0x01, 0x00000004 },
+	{ 0x000654,   1, 0x01, 0x3f800000 },
+	{ 0x000657,   1, 0x01, 0x3f800000 },
+	{ 0x000655,   2, 0x01, 0x3f800000 },
+	{ 0x0006cd,   1, 0x01, 0x3f800000 },
+	{ 0x0007f5,   1, 0x01, 0x3f800000 },
+	{ 0x0007dc,   1, 0x01, 0x39291909 },
+	{ 0x0007dd,   1, 0x01, 0x79695949 },
+	{ 0x0007de,   1, 0x01, 0xb9a99989 },
+	{ 0x0007df,   1, 0x01, 0xf9e9d9c9 },
+	{ 0x0007e8,   1, 0x01, 0x00003210 },
+	{ 0x0007e9,   1, 0x01, 0x00007654 },
+	{ 0x0007ea,   1, 0x01, 0x00000098 },
+	{ 0x0007ec,   1, 0x01, 0x39291909 },
+	{ 0x0007ed,   1, 0x01, 0x79695949 },
+	{ 0x0007ee,   1, 0x01, 0xb9a99989 },
+	{ 0x0007ef,   1, 0x01, 0xf9e9d9c9 },
+	{ 0x0007f0,   1, 0x01, 0x00003210 },
+	{ 0x0007f1,   1, 0x01, 0x00007654 },
+	{ 0x0007f2,   1, 0x01, 0x00000098 },
+	{ 0x0005a5,   1, 0x01, 0x00000001 },
+	{ 0x000980, 128, 0x01, 0x00000000 },
+	{ 0x000468,   1, 0x01, 0x00000004 },
+	{ 0x00046c,   1, 0x01, 0x00000001 },
+	{ 0x000470,  96, 0x01, 0x00000000 },
+	{ 0x000510,  16, 0x01, 0x3f800000 },
+	{ 0x000520,   1, 0x01, 0x000002b6 },
+	{ 0x000529,   1, 0x01, 0x00000001 },
+	{ 0x000530,  16, 0x01, 0xffff0000 },
+	{ 0x000585,   1, 0x01, 0x0000003f },
+	{ 0x000576,   1, 0x01, 0x00000003 },
+	{ 0x00057b,   1, 0x01, 0x00000059 },
+	{ 0x000586,   1, 0x01, 0x00000040 },
+	{ 0x000582,   2, 0x01, 0x00000080 },
+	{ 0x0005c2,   1, 0x01, 0x00000001 },
+	{ 0x000638,   2, 0x01, 0x00000001 },
+	{ 0x00063a,   1, 0x01, 0x00000002 },
+	{ 0x00063b,   2, 0x01, 0x00000001 },
+	{ 0x00063d,   1, 0x01, 0x00000002 },
+	{ 0x00063e,   1, 0x01, 0x00000001 },
+	{ 0x0008b8,   8, 0x01, 0x00000001 },
+	{ 0x000900,   8, 0x01, 0x00000001 },
+	{ 0x000908,   8, 0x01, 0x00000002 },
+	{ 0x000910,  16, 0x01, 0x00000001 },
+	{ 0x000920,   8, 0x01, 0x00000002 },
+	{ 0x000928,   8, 0x01, 0x00000001 },
+	{ 0x000662,   1, 0x01, 0x00000001 },
+	{ 0x000648,   9, 0x01, 0x00000001 },
+	{ 0x000658,   1, 0x01, 0x0000000f },
+	{ 0x0007ff,   1, 0x01, 0x0000000a },
+	{ 0x00066a,   1, 0x01, 0x40000000 },
+	{ 0x00066b,   1, 0x01, 0x10000000 },
+	{ 0x00066c,   2, 0x01, 0xffff0000 },
+	{ 0x0007af,   2, 0x01, 0x00000008 },
+	{ 0x0007f6,   1, 0x01, 0x00000001 },
+	{ 0x00080b,   1, 0x01, 0x00000002 },
+	{ 0x0006b2,   1, 0x01, 0x00000055 },
+	{ 0x0007ad,   1, 0x01, 0x00000003 },
+	{ 0x000937,   1, 0x01, 0x00000001 },
+	{ 0x000971,   1, 0x01, 0x00000008 },
+	{ 0x000972,   1, 0x01, 0x00000040 },
+	{ 0x000973,   1, 0x01, 0x0000012c },
+	{ 0x00097c,   1, 0x01, 0x00000040 },
+	{ 0x000979,   1, 0x01, 0x00000003 },
+	{ 0x000975,   1, 0x01, 0x00000020 },
+	{ 0x000976,   1, 0x01, 0x00000001 },
+	{ 0x000977,   1, 0x01, 0x00000020 },
+	{ 0x000978,   1, 0x01, 0x00000001 },
+	{ 0x000957,   1, 0x01, 0x00000003 },
+	{ 0x00095e,   1, 0x01, 0x20164010 },
+	{ 0x00095f,   1, 0x01, 0x00000020 },
+	{ 0x000a0d,   1, 0x01, 0x00000006 },
+	{ 0x00097d,   1, 0x01, 0x00000020 },
+	{ 0x000683,   1, 0x01, 0x00000006 },
+	{ 0x000685,   1, 0x01, 0x003fffff },
+	{ 0x000687,   1, 0x01, 0x003fffff },
+	{ 0x0006a0,   1, 0x01, 0x00000005 },
+	{ 0x000840,   1, 0x01, 0x00400008 },
+	{ 0x000841,   1, 0x01, 0x08000080 },
+	{ 0x000842,   1, 0x01, 0x00400008 },
+	{ 0x000843,   1, 0x01, 0x08000080 },
+	{ 0x0006aa,   1, 0x01, 0x00000001 },
+	{ 0x0006ab,   1, 0x01, 0x00000002 },
+	{ 0x0006ac,   1, 0x01, 0x00000080 },
+	{ 0x0006ad,   2, 0x01, 0x00000100 },
+	{ 0x0006b1,   1, 0x01, 0x00000011 },
+	{ 0x0006bb,   1, 0x01, 0x000000cf },
+	{ 0x0006ce,   1, 0x01, 0x2a712488 },
+	{ 0x000739,   1, 0x01, 0x4085c000 },
+	{ 0x00073a,   1, 0x01, 0x00000080 },
+	{ 0x000786,   1, 0x01, 0x80000100 },
+	{ 0x00073c,   1, 0x01, 0x00010100 },
+	{ 0x00073d,   1, 0x01, 0x02800000 },
+	{ 0x000787,   1, 0x01, 0x000000cf },
+	{ 0x00078c,   1, 0x01, 0x00000008 },
+	{ 0x000792,   1, 0x01, 0x00000001 },
+	{ 0x000794,   3, 0x01, 0x00000001 },
+	{ 0x000797,   1, 0x01, 0x000000cf },
+	{ 0x000836,   1, 0x01, 0x00000001 },
+	{ 0x00079a,   1, 0x01, 0x00000002 },
+	{ 0x000833,   1, 0x01, 0x04444480 },
+	{ 0x0007a1,   1, 0x01, 0x00000001 },
+	{ 0x0007a3,   3, 0x01, 0x00000001 },
+	{ 0x000831,   1, 0x01, 0x00000004 },
+	{ 0x000b07,   1, 0x01, 0x00000002 },
+	{ 0x000b08,   2, 0x01, 0x00000100 },
+	{ 0x000b0a,   1, 0x01, 0x00000001 },
+	{ 0x000a04,   1, 0x01, 0x000000ff },
+	{ 0x000a0b,   1, 0x01, 0x00000040 },
+	{ 0x00097f,   1, 0x01, 0x00000100 },
+	{ 0x000a02,   1, 0x01, 0x00000001 },
+	{ 0x000809,   1, 0x01, 0x00000007 },
+	{ 0x00c221,   1, 0x01, 0x00000040 },
+	{ 0x00c1b0,   8, 0x01, 0x0000000f },
+	{ 0x00c1b8,   1, 0x01, 0x0fac6881 },
+	{ 0x00c1b9,   1, 0x01, 0x00fac688 },
+	{ 0x00c401,   1, 0x01, 0x00000001 },
+	{ 0x00c402,   1, 0x01, 0x00010001 },
+	{ 0x00c403,   2, 0x01, 0x00000001 },
+	{ 0x00c40e,   1, 0x01, 0x00000020 },
+	{ 0x00c500,   1, 0x01, 0x00000003 },
+	{ 0x01e100,   1, 0x01, 0x00000001 },
+	{ 0x001000,   1, 0x01, 0x00000002 },
+	{ 0x0006aa,   1, 0x01, 0x00000001 },
+	{ 0x0006ad,   2, 0x01, 0x00000100 },
+	{ 0x0006b1,   1, 0x01, 0x00000011 },
+	{ 0x00078c,   1, 0x01, 0x00000008 },
+	{ 0x000792,   1, 0x01, 0x00000001 },
+	{ 0x000794,   3, 0x01, 0x00000001 },
+	{ 0x000797,   1, 0x01, 0x000000cf },
+	{ 0x00079a,   1, 0x01, 0x00000002 },
+	{ 0x0007a1,   1, 0x01, 0x00000001 },
+	{ 0x0007a3,   3, 0x01, 0x00000001 },
+	{ 0x000831,   1, 0x01, 0x00000004 },
+	{ 0x01e100,   1, 0x01, 0x00000001 },
+	{ 0x001000,   1, 0x01, 0x00000008 },
+	{ 0x000039,   3, 0x01, 0x00000000 },
+	{ 0x000380,   1, 0x01, 0x00000001 },
+	{ 0x000366,   2, 0x01, 0x00000000 },
+	{ 0x000368,   1, 0x01, 0x00000fff },
+	{ 0x000370,   2, 0x01, 0x00000000 },
+	{ 0x000372,   1, 0x01, 0x000fffff },
+	{ 0x000813,   1, 0x01, 0x00000006 },
+	{ 0x000814,   1, 0x01, 0x00000008 },
+	{ 0x000957,   1, 0x01, 0x00000003 },
+	{ 0x000b07,   1, 0x01, 0x00000002 },
+	{ 0x000b08,   2, 0x01, 0x00000100 },
+	{ 0x000b0a,   1, 0x01, 0x00000001 },
+	{ 0x000a04,   1, 0x01, 0x000000ff },
+	{ 0x000a0b,   1, 0x01, 0x00000040 },
+	{ 0x00097f,   1, 0x01, 0x00000100 },
+	{ 0x000a02,   1, 0x01, 0x00000001 },
+	{ 0x000809,   1, 0x01, 0x00000007 },
+	{ 0x00c221,   1, 0x01, 0x00000040 },
+	{ 0x00c401,   1, 0x01, 0x00000001 },
+	{ 0x00c402,   1, 0x01, 0x00010001 },
+	{ 0x00c403,   2, 0x01, 0x00000001 },
+	{ 0x00c40e,   1, 0x01, 0x00000020 },
+	{ 0x00c500,   1, 0x01, 0x00000003 },
+	{ 0x01e100,   1, 0x01, 0x00000001 },
+	{ 0x001000,   1, 0x01, 0x00000001 },
+	{ 0x000b07,   1, 0x01, 0x00000002 },
+	{ 0x000b08,   2, 0x01, 0x00000100 },
+	{ 0x000b0a,   1, 0x01, 0x00000001 },
+	{ 0x01e100,   1, 0x01, 0x00000001 },
+	{}
+};
+
+static struct nvc0_graph_init
+nv108_grctx_init_a197[] = {
+	{ 0x000800,   1, 0x04, 0x00000000 },
+	{ 0x000840,   1, 0x04, 0x00000000 },
+	{ 0x000880,   1, 0x04, 0x00000000 },
+	{ 0x0008c0,   1, 0x04, 0x00000000 },
+	{ 0x000900,   1, 0x04, 0x00000000 },
+	{ 0x000940,   1, 0x04, 0x00000000 },
+	{ 0x000980,   1, 0x04, 0x00000000 },
+	{ 0x0009c0,   1, 0x04, 0x00000000 },
+	{ 0x000804,   1, 0x04, 0x00000000 },
+	{ 0x000844,   1, 0x04, 0x00000000 },
+	{ 0x000884,   1, 0x04, 0x00000000 },
+	{ 0x0008c4,   1, 0x04, 0x00000000 },
+	{ 0x000904,   1, 0x04, 0x00000000 },
+	{ 0x000944,   1, 0x04, 0x00000000 },
+	{ 0x000984,   1, 0x04, 0x00000000 },
+	{ 0x0009c4,   1, 0x04, 0x00000000 },
+	{ 0x000808,   1, 0x04, 0x00000400 },
+	{ 0x000848,   1, 0x04, 0x00000400 },
+	{ 0x000888,   1, 0x04, 0x00000400 },
+	{ 0x0008c8,   1, 0x04, 0x00000400 },
+	{ 0x000908,   1, 0x04, 0x00000400 },
+	{ 0x000948,   1, 0x04, 0x00000400 },
+	{ 0x000988,   1, 0x04, 0x00000400 },
+	{ 0x0009c8,   1, 0x04, 0x00000400 },
+	{ 0x00080c,   1, 0x04, 0x00000300 },
+	{ 0x00084c,   1, 0x04, 0x00000300 },
+	{ 0x00088c,   1, 0x04, 0x00000300 },
+	{ 0x0008cc,   1, 0x04, 0x00000300 },
+	{ 0x00090c,   1, 0x04, 0x00000300 },
+	{ 0x00094c,   1, 0x04, 0x00000300 },
+	{ 0x00098c,   1, 0x04, 0x00000300 },
+	{ 0x0009cc,   1, 0x04, 0x00000300 },
+	{ 0x000810,   1, 0x04, 0x000000cf },
+	{ 0x000850,   1, 0x04, 0x00000000 },
+	{ 0x000890,   1, 0x04, 0x00000000 },
+	{ 0x0008d0,   1, 0x04, 0x00000000 },
+	{ 0x000910,   1, 0x04, 0x00000000 },
+	{ 0x000950,   1, 0x04, 0x00000000 },
+	{ 0x000990,   1, 0x04, 0x00000000 },
+	{ 0x0009d0,   1, 0x04, 0x00000000 },
+	{ 0x000814,   1, 0x04, 0x00000040 },
+	{ 0x000854,   1, 0x04, 0x00000040 },
+	{ 0x000894,   1, 0x04, 0x00000040 },
+	{ 0x0008d4,   1, 0x04, 0x00000040 },
+	{ 0x000914,   1, 0x04, 0x00000040 },
+	{ 0x000954,   1, 0x04, 0x00000040 },
+	{ 0x000994,   1, 0x04, 0x00000040 },
+	{ 0x0009d4,   1, 0x04, 0x00000040 },
+	{ 0x000818,   1, 0x04, 0x00000001 },
+	{ 0x000858,   1, 0x04, 0x00000001 },
+	{ 0x000898,   1, 0x04, 0x00000001 },
+	{ 0x0008d8,   1, 0x04, 0x00000001 },
+	{ 0x000918,   1, 0x04, 0x00000001 },
+	{ 0x000958,   1, 0x04, 0x00000001 },
+	{ 0x000998,   1, 0x04, 0x00000001 },
+	{ 0x0009d8,   1, 0x04, 0x00000001 },
+	{ 0x00081c,   1, 0x04, 0x00000000 },
+	{ 0x00085c,   1, 0x04, 0x00000000 },
+	{ 0x00089c,   1, 0x04, 0x00000000 },
+	{ 0x0008dc,   1, 0x04, 0x00000000 },
+	{ 0x00091c,   1, 0x04, 0x00000000 },
+	{ 0x00095c,   1, 0x04, 0x00000000 },
+	{ 0x00099c,   1, 0x04, 0x00000000 },
+	{ 0x0009dc,   1, 0x04, 0x00000000 },
+	{ 0x000820,   1, 0x04, 0x00000000 },
+	{ 0x000860,   1, 0x04, 0x00000000 },
+	{ 0x0008a0,   1, 0x04, 0x00000000 },
+	{ 0x0008e0,   1, 0x04, 0x00000000 },
+	{ 0x000920,   1, 0x04, 0x00000000 },
+	{ 0x000960,   1, 0x04, 0x00000000 },
+	{ 0x0009a0,   1, 0x04, 0x00000000 },
+	{ 0x0009e0,   1, 0x04, 0x00000000 },
+	{ 0x001c00,   1, 0x04, 0x00000000 },
+	{ 0x001c10,   1, 0x04, 0x00000000 },
+	{ 0x001c20,   1, 0x04, 0x00000000 },
+	{ 0x001c30,   1, 0x04, 0x00000000 },
+	{ 0x001c40,   1, 0x04, 0x00000000 },
+	{ 0x001c50,   1, 0x04, 0x00000000 },
+	{ 0x001c60,   1, 0x04, 0x00000000 },
+	{ 0x001c70,   1, 0x04, 0x00000000 },
+	{ 0x001c80,   1, 0x04, 0x00000000 },
+	{ 0x001c90,   1, 0x04, 0x00000000 },
+	{ 0x001ca0,   1, 0x04, 0x00000000 },
+	{ 0x001cb0,   1, 0x04, 0x00000000 },
+	{ 0x001cc0,   1, 0x04, 0x00000000 },
+	{ 0x001cd0,   1, 0x04, 0x00000000 },
+	{ 0x001ce0,   1, 0x04, 0x00000000 },
+	{ 0x001cf0,   1, 0x04, 0x00000000 },
+	{ 0x001c04,   1, 0x04, 0x00000000 },
+	{ 0x001c14,   1, 0x04, 0x00000000 },
+	{ 0x001c24,   1, 0x04, 0x00000000 },
+	{ 0x001c34,   1, 0x04, 0x00000000 },
+	{ 0x001c44,   1, 0x04, 0x00000000 },
+	{ 0x001c54,   1, 0x04, 0x00000000 },
+	{ 0x001c64,   1, 0x04, 0x00000000 },
+	{ 0x001c74,   1, 0x04, 0x00000000 },
+	{ 0x001c84,   1, 0x04, 0x00000000 },
+	{ 0x001c94,   1, 0x04, 0x00000000 },
+	{ 0x001ca4,   1, 0x04, 0x00000000 },
+	{ 0x001cb4,   1, 0x04, 0x00000000 },
+	{ 0x001cc4,   1, 0x04, 0x00000000 },
+	{ 0x001cd4,   1, 0x04, 0x00000000 },
+	{ 0x001ce4,   1, 0x04, 0x00000000 },
+	{ 0x001cf4,   1, 0x04, 0x00000000 },
+	{ 0x001c08,   1, 0x04, 0x00000000 },
+	{ 0x001c18,   1, 0x04, 0x00000000 },
+	{ 0x001c28,   1, 0x04, 0x00000000 },
+	{ 0x001c38,   1, 0x04, 0x00000000 },
+	{ 0x001c48,   1, 0x04, 0x00000000 },
+	{ 0x001c58,   1, 0x04, 0x00000000 },
+	{ 0x001c68,   1, 0x04, 0x00000000 },
+	{ 0x001c78,   1, 0x04, 0x00000000 },
+	{ 0x001c88,   1, 0x04, 0x00000000 },
+	{ 0x001c98,   1, 0x04, 0x00000000 },
+	{ 0x001ca8,   1, 0x04, 0x00000000 },
+	{ 0x001cb8,   1, 0x04, 0x00000000 },
+	{ 0x001cc8,   1, 0x04, 0x00000000 },
+	{ 0x001cd8,   1, 0x04, 0x00000000 },
+	{ 0x001ce8,   1, 0x04, 0x00000000 },
+	{ 0x001cf8,   1, 0x04, 0x00000000 },
+	{ 0x001c0c,   1, 0x04, 0x00000000 },
+	{ 0x001c1c,   1, 0x04, 0x00000000 },
+	{ 0x001c2c,   1, 0x04, 0x00000000 },
+	{ 0x001c3c,   1, 0x04, 0x00000000 },
+	{ 0x001c4c,   1, 0x04, 0x00000000 },
+	{ 0x001c5c,   1, 0x04, 0x00000000 },
+	{ 0x001c6c,   1, 0x04, 0x00000000 },
+	{ 0x001c7c,   1, 0x04, 0x00000000 },
+	{ 0x001c8c,   1, 0x04, 0x00000000 },
+	{ 0x001c9c,   1, 0x04, 0x00000000 },
+	{ 0x001cac,   1, 0x04, 0x00000000 },
+	{ 0x001cbc,   1, 0x04, 0x00000000 },
+	{ 0x001ccc,   1, 0x04, 0x00000000 },
+	{ 0x001cdc,   1, 0x04, 0x00000000 },
+	{ 0x001cec,   1, 0x04, 0x00000000 },
+	{ 0x001cfc,   2, 0x04, 0x00000000 },
+	{ 0x001d10,   1, 0x04, 0x00000000 },
+	{ 0x001d20,   1, 0x04, 0x00000000 },
+	{ 0x001d30,   1, 0x04, 0x00000000 },
+	{ 0x001d40,   1, 0x04, 0x00000000 },
+	{ 0x001d50,   1, 0x04, 0x00000000 },
+	{ 0x001d60,   1, 0x04, 0x00000000 },
+	{ 0x001d70,   1, 0x04, 0x00000000 },
+	{ 0x001d80,   1, 0x04, 0x00000000 },
+	{ 0x001d90,   1, 0x04, 0x00000000 },
+	{ 0x001da0,   1, 0x04, 0x00000000 },
+	{ 0x001db0,   1, 0x04, 0x00000000 },
+	{ 0x001dc0,   1, 0x04, 0x00000000 },
+	{ 0x001dd0,   1, 0x04, 0x00000000 },
+	{ 0x001de0,   1, 0x04, 0x00000000 },
+	{ 0x001df0,   1, 0x04, 0x00000000 },
+	{ 0x001d04,   1, 0x04, 0x00000000 },
+	{ 0x001d14,   1, 0x04, 0x00000000 },
+	{ 0x001d24,   1, 0x04, 0x00000000 },
+	{ 0x001d34,   1, 0x04, 0x00000000 },
+	{ 0x001d44,   1, 0x04, 0x00000000 },
+	{ 0x001d54,   1, 0x04, 0x00000000 },
+	{ 0x001d64,   1, 0x04, 0x00000000 },
+	{ 0x001d74,   1, 0x04, 0x00000000 },
+	{ 0x001d84,   1, 0x04, 0x00000000 },
+	{ 0x001d94,   1, 0x04, 0x00000000 },
+	{ 0x001da4,   1, 0x04, 0x00000000 },
+	{ 0x001db4,   1, 0x04, 0x00000000 },
+	{ 0x001dc4,   1, 0x04, 0x00000000 },
+	{ 0x001dd4,   1, 0x04, 0x00000000 },
+	{ 0x001de4,   1, 0x04, 0x00000000 },
+	{ 0x001df4,   1, 0x04, 0x00000000 },
+	{ 0x001d08,   1, 0x04, 0x00000000 },
+	{ 0x001d18,   1, 0x04, 0x00000000 },
+	{ 0x001d28,   1, 0x04, 0x00000000 },
+	{ 0x001d38,   1, 0x04, 0x00000000 },
+	{ 0x001d48,   1, 0x04, 0x00000000 },
+	{ 0x001d58,   1, 0x04, 0x00000000 },
+	{ 0x001d68,   1, 0x04, 0x00000000 },
+	{ 0x001d78,   1, 0x04, 0x00000000 },
+	{ 0x001d88,   1, 0x04, 0x00000000 },
+	{ 0x001d98,   1, 0x04, 0x00000000 },
+	{ 0x001da8,   1, 0x04, 0x00000000 },
+	{ 0x001db8,   1, 0x04, 0x00000000 },
+	{ 0x001dc8,   1, 0x04, 0x00000000 },
+	{ 0x001dd8,   1, 0x04, 0x00000000 },
+	{ 0x001de8,   1, 0x04, 0x00000000 },
+	{ 0x001df8,   1, 0x04, 0x00000000 },
+	{ 0x001d0c,   1, 0x04, 0x00000000 },
+	{ 0x001d1c,   1, 0x04, 0x00000000 },
+	{ 0x001d2c,   1, 0x04, 0x00000000 },
+	{ 0x001d3c,   1, 0x04, 0x00000000 },
+	{ 0x001d4c,   1, 0x04, 0x00000000 },
+	{ 0x001d5c,   1, 0x04, 0x00000000 },
+	{ 0x001d6c,   1, 0x04, 0x00000000 },
+	{ 0x001d7c,   1, 0x04, 0x00000000 },
+	{ 0x001d8c,   1, 0x04, 0x00000000 },
+	{ 0x001d9c,   1, 0x04, 0x00000000 },
+	{ 0x001dac,   1, 0x04, 0x00000000 },
+	{ 0x001dbc,   1, 0x04, 0x00000000 },
+	{ 0x001dcc,   1, 0x04, 0x00000000 },
+	{ 0x001ddc,   1, 0x04, 0x00000000 },
+	{ 0x001dec,   1, 0x04, 0x00000000 },
+	{ 0x001dfc,   1, 0x04, 0x00000000 },
+	{ 0x001f00,   1, 0x04, 0x00000000 },
+	{ 0x001f08,   1, 0x04, 0x00000000 },
+	{ 0x001f10,   1, 0x04, 0x00000000 },
+	{ 0x001f18,   1, 0x04, 0x00000000 },
+	{ 0x001f20,   1, 0x04, 0x00000000 },
+	{ 0x001f28,   1, 0x04, 0x00000000 },
+	{ 0x001f30,   1, 0x04, 0x00000000 },
+	{ 0x001f38,   1, 0x04, 0x00000000 },
+	{ 0x001f40,   1, 0x04, 0x00000000 },
+	{ 0x001f48,   1, 0x04, 0x00000000 },
+	{ 0x001f50,   1, 0x04, 0x00000000 },
+	{ 0x001f58,   1, 0x04, 0x00000000 },
+	{ 0x001f60,   1, 0x04, 0x00000000 },
+	{ 0x001f68,   1, 0x04, 0x00000000 },
+	{ 0x001f70,   1, 0x04, 0x00000000 },
+	{ 0x001f78,   1, 0x04, 0x00000000 },
+	{ 0x001f04,   1, 0x04, 0x00000000 },
+	{ 0x001f0c,   1, 0x04, 0x00000000 },
+	{ 0x001f14,   1, 0x04, 0x00000000 },
+	{ 0x001f1c,   1, 0x04, 0x00000000 },
+	{ 0x001f24,   1, 0x04, 0x00000000 },
+	{ 0x001f2c,   1, 0x04, 0x00000000 },
+	{ 0x001f34,   1, 0x04, 0x00000000 },
+	{ 0x001f3c,   1, 0x04, 0x00000000 },
+	{ 0x001f44,   1, 0x04, 0x00000000 },
+	{ 0x001f4c,   1, 0x04, 0x00000000 },
+	{ 0x001f54,   1, 0x04, 0x00000000 },
+	{ 0x001f5c,   1, 0x04, 0x00000000 },
+	{ 0x001f64,   1, 0x04, 0x00000000 },
+	{ 0x001f6c,   1, 0x04, 0x00000000 },
+	{ 0x001f74,   1, 0x04, 0x00000000 },
+	{ 0x001f7c,   2, 0x04, 0x00000000 },
+	{ 0x001f88,   1, 0x04, 0x00000000 },
+	{ 0x001f90,   1, 0x04, 0x00000000 },
+	{ 0x001f98,   1, 0x04, 0x00000000 },
+	{ 0x001fa0,   1, 0x04, 0x00000000 },
+	{ 0x001fa8,   1, 0x04, 0x00000000 },
+	{ 0x001fb0,   1, 0x04, 0x00000000 },
+	{ 0x001fb8,   1, 0x04, 0x00000000 },
+	{ 0x001fc0,   1, 0x04, 0x00000000 },
+	{ 0x001fc8,   1, 0x04, 0x00000000 },
+	{ 0x001fd0,   1, 0x04, 0x00000000 },
+	{ 0x001fd8,   1, 0x04, 0x00000000 },
+	{ 0x001fe0,   1, 0x04, 0x00000000 },
+	{ 0x001fe8,   1, 0x04, 0x00000000 },
+	{ 0x001ff0,   1, 0x04, 0x00000000 },
+	{ 0x001ff8,   1, 0x04, 0x00000000 },
+	{ 0x001f84,   1, 0x04, 0x00000000 },
+	{ 0x001f8c,   1, 0x04, 0x00000000 },
+	{ 0x001f94,   1, 0x04, 0x00000000 },
+	{ 0x001f9c,   1, 0x04, 0x00000000 },
+	{ 0x001fa4,   1, 0x04, 0x00000000 },
+	{ 0x001fac,   1, 0x04, 0x00000000 },
+	{ 0x001fb4,   1, 0x04, 0x00000000 },
+	{ 0x001fbc,   1, 0x04, 0x00000000 },
+	{ 0x001fc4,   1, 0x04, 0x00000000 },
+	{ 0x001fcc,   1, 0x04, 0x00000000 },
+	{ 0x001fd4,   1, 0x04, 0x00000000 },
+	{ 0x001fdc,   1, 0x04, 0x00000000 },
+	{ 0x001fe4,   1, 0x04, 0x00000000 },
+	{ 0x001fec,   1, 0x04, 0x00000000 },
+	{ 0x001ff4,   1, 0x04, 0x00000000 },
+	{ 0x001ffc,   2, 0x04, 0x00000000 },
+	{ 0x002040,   1, 0x04, 0x00000011 },
+	{ 0x002080,   1, 0x04, 0x00000020 },
+	{ 0x0020c0,   1, 0x04, 0x00000030 },
+	{ 0x002100,   1, 0x04, 0x00000040 },
+	{ 0x002140,   1, 0x04, 0x00000051 },
+	{ 0x00200c,   1, 0x04, 0x00000001 },
+	{ 0x00204c,   1, 0x04, 0x00000001 },
+	{ 0x00208c,   1, 0x04, 0x00000001 },
+	{ 0x0020cc,   1, 0x04, 0x00000001 },
+	{ 0x00210c,   1, 0x04, 0x00000001 },
+	{ 0x00214c,   1, 0x04, 0x00000001 },
+	{ 0x002010,   1, 0x04, 0x00000000 },
+	{ 0x002050,   1, 0x04, 0x00000000 },
+	{ 0x002090,   1, 0x04, 0x00000001 },
+	{ 0x0020d0,   1, 0x04, 0x00000002 },
+	{ 0x002110,   1, 0x04, 0x00000003 },
+	{ 0x002150,   1, 0x04, 0x00000004 },
+	{ 0x000380,   1, 0x04, 0x00000000 },
+	{ 0x0003a0,   1, 0x04, 0x00000000 },
+	{ 0x0003c0,   1, 0x04, 0x00000000 },
+	{ 0x0003e0,   1, 0x04, 0x00000000 },
+	{ 0x000384,   1, 0x04, 0x00000000 },
+	{ 0x0003a4,   1, 0x04, 0x00000000 },
+	{ 0x0003c4,   1, 0x04, 0x00000000 },
+	{ 0x0003e4,   1, 0x04, 0x00000000 },
+	{ 0x000388,   1, 0x04, 0x00000000 },
+	{ 0x0003a8,   1, 0x04, 0x00000000 },
+	{ 0x0003c8,   1, 0x04, 0x00000000 },
+	{ 0x0003e8,   1, 0x04, 0x00000000 },
+	{ 0x00038c,   1, 0x04, 0x00000000 },
+	{ 0x0003ac,   1, 0x04, 0x00000000 },
+	{ 0x0003cc,   1, 0x04, 0x00000000 },
+	{ 0x0003ec,   1, 0x04, 0x00000000 },
+	{ 0x000700,   1, 0x04, 0x00000000 },
+	{ 0x000710,   1, 0x04, 0x00000000 },
+	{ 0x000720,   1, 0x04, 0x00000000 },
+	{ 0x000730,   1, 0x04, 0x00000000 },
+	{ 0x000704,   1, 0x04, 0x00000000 },
+	{ 0x000714,   1, 0x04, 0x00000000 },
+	{ 0x000724,   1, 0x04, 0x00000000 },
+	{ 0x000734,   1, 0x04, 0x00000000 },
+	{ 0x000708,   1, 0x04, 0x00000000 },
+	{ 0x000718,   1, 0x04, 0x00000000 },
+	{ 0x000728,   1, 0x04, 0x00000000 },
+	{ 0x000738,   1, 0x04, 0x00000000 },
+	{ 0x002800, 128, 0x04, 0x00000000 },
+	{ 0x000a00,   1, 0x04, 0x00000000 },
+	{ 0x000a20,   1, 0x04, 0x00000000 },
+	{ 0x000a40,   1, 0x04, 0x00000000 },
+	{ 0x000a60,   1, 0x04, 0x00000000 },
+	{ 0x000a80,   1, 0x04, 0x00000000 },
+	{ 0x000aa0,   1, 0x04, 0x00000000 },
+	{ 0x000ac0,   1, 0x04, 0x00000000 },
+	{ 0x000ae0,   1, 0x04, 0x00000000 },
+	{ 0x000b00,   1, 0x04, 0x00000000 },
+	{ 0x000b20,   1, 0x04, 0x00000000 },
+	{ 0x000b40,   1, 0x04, 0x00000000 },
+	{ 0x000b60,   1, 0x04, 0x00000000 },
+	{ 0x000b80,   1, 0x04, 0x00000000 },
+	{ 0x000ba0,   1, 0x04, 0x00000000 },
+	{ 0x000bc0,   1, 0x04, 0x00000000 },
+	{ 0x000be0,   1, 0x04, 0x00000000 },
+	{ 0x000a04,   1, 0x04, 0x00000000 },
+	{ 0x000a24,   1, 0x04, 0x00000000 },
+	{ 0x000a44,   1, 0x04, 0x00000000 },
+	{ 0x000a64,   1, 0x04, 0x00000000 },
+	{ 0x000a84,   1, 0x04, 0x00000000 },
+	{ 0x000aa4,   1, 0x04, 0x00000000 },
+	{ 0x000ac4,   1, 0x04, 0x00000000 },
+	{ 0x000ae4,   1, 0x04, 0x00000000 },
+	{ 0x000b04,   1, 0x04, 0x00000000 },
+	{ 0x000b24,   1, 0x04, 0x00000000 },
+	{ 0x000b44,   1, 0x04, 0x00000000 },
+	{ 0x000b64,   1, 0x04, 0x00000000 },
+	{ 0x000b84,   1, 0x04, 0x00000000 },
+	{ 0x000ba4,   1, 0x04, 0x00000000 },
+	{ 0x000bc4,   1, 0x04, 0x00000000 },
+	{ 0x000be4,   1, 0x04, 0x00000000 },
+	{ 0x000a08,   1, 0x04, 0x00000000 },
+	{ 0x000a28,   1, 0x04, 0x00000000 },
+	{ 0x000a48,   1, 0x04, 0x00000000 },
+	{ 0x000a68,   1, 0x04, 0x00000000 },
+	{ 0x000a88,   1, 0x04, 0x00000000 },
+	{ 0x000aa8,   1, 0x04, 0x00000000 },
+	{ 0x000ac8,   1, 0x04, 0x00000000 },
+	{ 0x000ae8,   1, 0x04, 0x00000000 },
+	{ 0x000b08,   1, 0x04, 0x00000000 },
+	{ 0x000b28,   1, 0x04, 0x00000000 },
+	{ 0x000b48,   1, 0x04, 0x00000000 },
+	{ 0x000b68,   1, 0x04, 0x00000000 },
+	{ 0x000b88,   1, 0x04, 0x00000000 },
+	{ 0x000ba8,   1, 0x04, 0x00000000 },
+	{ 0x000bc8,   1, 0x04, 0x00000000 },
+	{ 0x000be8,   1, 0x04, 0x00000000 },
+	{ 0x000a0c,   1, 0x04, 0x00000000 },
+	{ 0x000a2c,   1, 0x04, 0x00000000 },
+	{ 0x000a4c,   1, 0x04, 0x00000000 },
+	{ 0x000a6c,   1, 0x04, 0x00000000 },
+	{ 0x000a8c,   1, 0x04, 0x00000000 },
+	{ 0x000aac,   1, 0x04, 0x00000000 },
+	{ 0x000acc,   1, 0x04, 0x00000000 },
+	{ 0x000aec,   1, 0x04, 0x00000000 },
+	{ 0x000b0c,   1, 0x04, 0x00000000 },
+	{ 0x000b2c,   1, 0x04, 0x00000000 },
+	{ 0x000b4c,   1, 0x04, 0x00000000 },
+	{ 0x000b6c,   1, 0x04, 0x00000000 },
+	{ 0x000b8c,   1, 0x04, 0x00000000 },
+	{ 0x000bac,   1, 0x04, 0x00000000 },
+	{ 0x000bcc,   1, 0x04, 0x00000000 },
+	{ 0x000bec,   1, 0x04, 0x00000000 },
+	{ 0x000a10,   1, 0x04, 0x00000000 },
+	{ 0x000a30,   1, 0x04, 0x00000000 },
+	{ 0x000a50,   1, 0x04, 0x00000000 },
+	{ 0x000a70,   1, 0x04, 0x00000000 },
+	{ 0x000a90,   1, 0x04, 0x00000000 },
+	{ 0x000ab0,   1, 0x04, 0x00000000 },
+	{ 0x000ad0,   1, 0x04, 0x00000000 },
+	{ 0x000af0,   1, 0x04, 0x00000000 },
+	{ 0x000b10,   1, 0x04, 0x00000000 },
+	{ 0x000b30,   1, 0x04, 0x00000000 },
+	{ 0x000b50,   1, 0x04, 0x00000000 },
+	{ 0x000b70,   1, 0x04, 0x00000000 },
+	{ 0x000b90,   1, 0x04, 0x00000000 },
+	{ 0x000bb0,   1, 0x04, 0x00000000 },
+	{ 0x000bd0,   1, 0x04, 0x00000000 },
+	{ 0x000bf0,   1, 0x04, 0x00000000 },
+	{ 0x000a14,   1, 0x04, 0x00000000 },
+	{ 0x000a34,   1, 0x04, 0x00000000 },
+	{ 0x000a54,   1, 0x04, 0x00000000 },
+	{ 0x000a74,   1, 0x04, 0x00000000 },
+	{ 0x000a94,   1, 0x04, 0x00000000 },
+	{ 0x000ab4,   1, 0x04, 0x00000000 },
+	{ 0x000ad4,   1, 0x04, 0x00000000 },
+	{ 0x000af4,   1, 0x04, 0x00000000 },
+	{ 0x000b14,   1, 0x04, 0x00000000 },
+	{ 0x000b34,   1, 0x04, 0x00000000 },
+	{ 0x000b54,   1, 0x04, 0x00000000 },
+	{ 0x000b74,   1, 0x04, 0x00000000 },
+	{ 0x000b94,   1, 0x04, 0x00000000 },
+	{ 0x000bb4,   1, 0x04, 0x00000000 },
+	{ 0x000bd4,   1, 0x04, 0x00000000 },
+	{ 0x000bf4,   1, 0x04, 0x00000000 },
+	{ 0x000c00,   1, 0x04, 0x00000000 },
+	{ 0x000c10,   1, 0x04, 0x00000000 },
+	{ 0x000c20,   1, 0x04, 0x00000000 },
+	{ 0x000c30,   1, 0x04, 0x00000000 },
+	{ 0x000c40,   1, 0x04, 0x00000000 },
+	{ 0x000c50,   1, 0x04, 0x00000000 },
+	{ 0x000c60,   1, 0x04, 0x00000000 },
+	{ 0x000c70,   1, 0x04, 0x00000000 },
+	{ 0x000c80,   1, 0x04, 0x00000000 },
+	{ 0x000c90,   1, 0x04, 0x00000000 },
+	{ 0x000ca0,   1, 0x04, 0x00000000 },
+	{ 0x000cb0,   1, 0x04, 0x00000000 },
+	{ 0x000cc0,   1, 0x04, 0x00000000 },
+	{ 0x000cd0,   1, 0x04, 0x00000000 },
+	{ 0x000ce0,   1, 0x04, 0x00000000 },
+	{ 0x000cf0,   1, 0x04, 0x00000000 },
+	{ 0x000c04,   1, 0x04, 0x00000000 },
+	{ 0x000c14,   1, 0x04, 0x00000000 },
+	{ 0x000c24,   1, 0x04, 0x00000000 },
+	{ 0x000c34,   1, 0x04, 0x00000000 },
+	{ 0x000c44,   1, 0x04, 0x00000000 },
+	{ 0x000c54,   1, 0x04, 0x00000000 },
+	{ 0x000c64,   1, 0x04, 0x00000000 },
+	{ 0x000c74,   1, 0x04, 0x00000000 },
+	{ 0x000c84,   1, 0x04, 0x00000000 },
+	{ 0x000c94,   1, 0x04, 0x00000000 },
+	{ 0x000ca4,   1, 0x04, 0x00000000 },
+	{ 0x000cb4,   1, 0x04, 0x00000000 },
+	{ 0x000cc4,   1, 0x04, 0x00000000 },
+	{ 0x000cd4,   1, 0x04, 0x00000000 },
+	{ 0x000ce4,   1, 0x04, 0x00000000 },
+	{ 0x000cf4,   1, 0x04, 0x00000000 },
+	{ 0x000c08,   1, 0x04, 0x00000000 },
+	{ 0x000c18,   1, 0x04, 0x00000000 },
+	{ 0x000c28,   1, 0x04, 0x00000000 },
+	{ 0x000c38,   1, 0x04, 0x00000000 },
+	{ 0x000c48,   1, 0x04, 0x00000000 },
+	{ 0x000c58,   1, 0x04, 0x00000000 },
+	{ 0x000c68,   1, 0x04, 0x00000000 },
+	{ 0x000c78,   1, 0x04, 0x00000000 },
+	{ 0x000c88,   1, 0x04, 0x00000000 },
+	{ 0x000c98,   1, 0x04, 0x00000000 },
+	{ 0x000ca8,   1, 0x04, 0x00000000 },
+	{ 0x000cb8,   1, 0x04, 0x00000000 },
+	{ 0x000cc8,   1, 0x04, 0x00000000 },
+	{ 0x000cd8,   1, 0x04, 0x00000000 },
+	{ 0x000ce8,   1, 0x04, 0x00000000 },
+	{ 0x000cf8,   1, 0x04, 0x00000000 },
+	{ 0x000c0c,   1, 0x04, 0x3f800000 },
+	{ 0x000c1c,   1, 0x04, 0x3f800000 },
+	{ 0x000c2c,   1, 0x04, 0x3f800000 },
+	{ 0x000c3c,   1, 0x04, 0x3f800000 },
+	{ 0x000c4c,   1, 0x04, 0x3f800000 },
+	{ 0x000c5c,   1, 0x04, 0x3f800000 },
+	{ 0x000c6c,   1, 0x04, 0x3f800000 },
+	{ 0x000c7c,   1, 0x04, 0x3f800000 },
+	{ 0x000c8c,   1, 0x04, 0x3f800000 },
+	{ 0x000c9c,   1, 0x04, 0x3f800000 },
+	{ 0x000cac,   1, 0x04, 0x3f800000 },
+	{ 0x000cbc,   1, 0x04, 0x3f800000 },
+	{ 0x000ccc,   1, 0x04, 0x3f800000 },
+	{ 0x000cdc,   1, 0x04, 0x3f800000 },
+	{ 0x000cec,   1, 0x04, 0x3f800000 },
+	{ 0x000cfc,   1, 0x04, 0x3f800000 },
+	{ 0x000d00,   1, 0x04, 0xffff0000 },
+	{ 0x000d08,   1, 0x04, 0xffff0000 },
+	{ 0x000d10,   1, 0x04, 0xffff0000 },
+	{ 0x000d18,   1, 0x04, 0xffff0000 },
+	{ 0x000d20,   1, 0x04, 0xffff0000 },
+	{ 0x000d28,   1, 0x04, 0xffff0000 },
+	{ 0x000d30,   1, 0x04, 0xffff0000 },
+	{ 0x000d38,   1, 0x04, 0xffff0000 },
+	{ 0x000d04,   1, 0x04, 0xffff0000 },
+	{ 0x000d0c,   1, 0x04, 0xffff0000 },
+	{ 0x000d14,   1, 0x04, 0xffff0000 },
+	{ 0x000d1c,   1, 0x04, 0xffff0000 },
+	{ 0x000d24,   1, 0x04, 0xffff0000 },
+	{ 0x000d2c,   1, 0x04, 0xffff0000 },
+	{ 0x000d34,   1, 0x04, 0xffff0000 },
+	{ 0x000d3c,   1, 0x04, 0xffff0000 },
+	{ 0x000e00,   1, 0x04, 0x00000000 },
+	{ 0x000e10,   1, 0x04, 0x00000000 },
+	{ 0x000e20,   1, 0x04, 0x00000000 },
+	{ 0x000e30,   1, 0x04, 0x00000000 },
+	{ 0x000e40,   1, 0x04, 0x00000000 },
+	{ 0x000e50,   1, 0x04, 0x00000000 },
+	{ 0x000e60,   1, 0x04, 0x00000000 },
+	{ 0x000e70,   1, 0x04, 0x00000000 },
+	{ 0x000e80,   1, 0x04, 0x00000000 },
+	{ 0x000e90,   1, 0x04, 0x00000000 },
+	{ 0x000ea0,   1, 0x04, 0x00000000 },
+	{ 0x000eb0,   1, 0x04, 0x00000000 },
+	{ 0x000ec0,   1, 0x04, 0x00000000 },
+	{ 0x000ed0,   1, 0x04, 0x00000000 },
+	{ 0x000ee0,   1, 0x04, 0x00000000 },
+	{ 0x000ef0,   1, 0x04, 0x00000000 },
+	{ 0x000e04,   1, 0x04, 0xffff0000 },
+	{ 0x000e14,   1, 0x04, 0xffff0000 },
+	{ 0x000e24,   1, 0x04, 0xffff0000 },
+	{ 0x000e34,   1, 0x04, 0xffff0000 },
+	{ 0x000e44,   1, 0x04, 0xffff0000 },
+	{ 0x000e54,   1, 0x04, 0xffff0000 },
+	{ 0x000e64,   1, 0x04, 0xffff0000 },
+	{ 0x000e74,   1, 0x04, 0xffff0000 },
+	{ 0x000e84,   1, 0x04, 0xffff0000 },
+	{ 0x000e94,   1, 0x04, 0xffff0000 },
+	{ 0x000ea4,   1, 0x04, 0xffff0000 },
+	{ 0x000eb4,   1, 0x04, 0xffff0000 },
+	{ 0x000ec4,   1, 0x04, 0xffff0000 },
+	{ 0x000ed4,   1, 0x04, 0xffff0000 },
+	{ 0x000ee4,   1, 0x04, 0xffff0000 },
+	{ 0x000ef4,   1, 0x04, 0xffff0000 },
+	{ 0x000e08,   1, 0x04, 0xffff0000 },
+	{ 0x000e18,   1, 0x04, 0xffff0000 },
+	{ 0x000e28,   1, 0x04, 0xffff0000 },
+	{ 0x000e38,   1, 0x04, 0xffff0000 },
+	{ 0x000e48,   1, 0x04, 0xffff0000 },
+	{ 0x000e58,   1, 0x04, 0xffff0000 },
+	{ 0x000e68,   1, 0x04, 0xffff0000 },
+	{ 0x000e78,   1, 0x04, 0xffff0000 },
+	{ 0x000e88,   1, 0x04, 0xffff0000 },
+	{ 0x000e98,   1, 0x04, 0xffff0000 },
+	{ 0x000ea8,   1, 0x04, 0xffff0000 },
+	{ 0x000eb8,   1, 0x04, 0xffff0000 },
+	{ 0x000ec8,   1, 0x04, 0xffff0000 },
+	{ 0x000ed8,   1, 0x04, 0xffff0000 },
+	{ 0x000ee8,   1, 0x04, 0xffff0000 },
+	{ 0x000ef8,   1, 0x04, 0xffff0000 },
+	{ 0x000d40,   1, 0x04, 0x00000000 },
+	{ 0x000d48,   1, 0x04, 0x00000000 },
+	{ 0x000d50,   1, 0x04, 0x00000000 },
+	{ 0x000d58,   1, 0x04, 0x00000000 },
+	{ 0x000d44,   1, 0x04, 0x00000000 },
+	{ 0x000d4c,   1, 0x04, 0x00000000 },
+	{ 0x000d54,   1, 0x04, 0x00000000 },
+	{ 0x000d5c,   1, 0x04, 0x00000000 },
+	{ 0x001e00,   1, 0x04, 0x00000001 },
+	{ 0x001e20,   1, 0x04, 0x00000001 },
+	{ 0x001e40,   1, 0x04, 0x00000001 },
+	{ 0x001e60,   1, 0x04, 0x00000001 },
+	{ 0x001e80,   1, 0x04, 0x00000001 },
+	{ 0x001ea0,   1, 0x04, 0x00000001 },
+	{ 0x001ec0,   1, 0x04, 0x00000001 },
+	{ 0x001ee0,   1, 0x04, 0x00000001 },
+	{ 0x001e04,   1, 0x04, 0x00000001 },
+	{ 0x001e24,   1, 0x04, 0x00000001 },
+	{ 0x001e44,   1, 0x04, 0x00000001 },
+	{ 0x001e64,   1, 0x04, 0x00000001 },
+	{ 0x001e84,   1, 0x04, 0x00000001 },
+	{ 0x001ea4,   1, 0x04, 0x00000001 },
+	{ 0x001ec4,   1, 0x04, 0x00000001 },
+	{ 0x001ee4,   1, 0x04, 0x00000001 },
+	{ 0x001e08,   1, 0x04, 0x00000002 },
+	{ 0x001e28,   1, 0x04, 0x00000002 },
+	{ 0x001e48,   1, 0x04, 0x00000002 },
+	{ 0x001e68,   1, 0x04, 0x00000002 },
+	{ 0x001e88,   1, 0x04, 0x00000002 },
+	{ 0x001ea8,   1, 0x04, 0x00000002 },
+	{ 0x001ec8,   1, 0x04, 0x00000002 },
+	{ 0x001ee8,   1, 0x04, 0x00000002 },
+	{ 0x001e0c,   1, 0x04, 0x00000001 },
+	{ 0x001e2c,   1, 0x04, 0x00000001 },
+	{ 0x001e4c,   1, 0x04, 0x00000001 },
+	{ 0x001e6c,   1, 0x04, 0x00000001 },
+	{ 0x001e8c,   1, 0x04, 0x00000001 },
+	{ 0x001eac,   1, 0x04, 0x00000001 },
+	{ 0x001ecc,   1, 0x04, 0x00000001 },
+	{ 0x001eec,   1, 0x04, 0x00000001 },
+	{ 0x001e10,   1, 0x04, 0x00000001 },
+	{ 0x001e30,   1, 0x04, 0x00000001 },
+	{ 0x001e50,   1, 0x04, 0x00000001 },
+	{ 0x001e70,   1, 0x04, 0x00000001 },
+	{ 0x001e90,   1, 0x04, 0x00000001 },
+	{ 0x001eb0,   1, 0x04, 0x00000001 },
+	{ 0x001ed0,   1, 0x04, 0x00000001 },
+	{ 0x001ef0,   1, 0x04, 0x00000001 },
+	{ 0x001e14,   1, 0x04, 0x00000002 },
+	{ 0x001e34,   1, 0x04, 0x00000002 },
+	{ 0x001e54,   1, 0x04, 0x00000002 },
+	{ 0x001e74,   1, 0x04, 0x00000002 },
+	{ 0x001e94,   1, 0x04, 0x00000002 },
+	{ 0x001eb4,   1, 0x04, 0x00000002 },
+	{ 0x001ed4,   1, 0x04, 0x00000002 },
+	{ 0x001ef4,   1, 0x04, 0x00000002 },
+	{ 0x001e18,   1, 0x04, 0x00000001 },
+	{ 0x001e38,   1, 0x04, 0x00000001 },
+	{ 0x001e58,   1, 0x04, 0x00000001 },
+	{ 0x001e78,   1, 0x04, 0x00000001 },
+	{ 0x001e98,   1, 0x04, 0x00000001 },
+	{ 0x001eb8,   1, 0x04, 0x00000001 },
+	{ 0x001ed8,   1, 0x04, 0x00000001 },
+	{ 0x001ef8,   1, 0x04, 0x00000001 },
+	{ 0x003400, 128, 0x04, 0x00000000 },
+	{ 0x00030c,   1, 0x04, 0x00000001 },
+	{ 0x001944,   1, 0x04, 0x00000000 },
+	{ 0x001514,   1, 0x04, 0x00000000 },
+	{ 0x000d68,   1, 0x04, 0x0000ffff },
+	{ 0x00121c,   1, 0x04, 0x0fac6881 },
+	{ 0x000fac,   1, 0x04, 0x00000001 },
+	{ 0x001538,   1, 0x04, 0x00000001 },
+	{ 0x000fe0,   2, 0x04, 0x00000000 },
+	{ 0x000fe8,   1, 0x04, 0x00000014 },
+	{ 0x000fec,   1, 0x04, 0x00000040 },
+	{ 0x000ff0,   1, 0x04, 0x00000000 },
+	{ 0x00179c,   1, 0x04, 0x00000000 },
+	{ 0x001228,   1, 0x04, 0x00000400 },
+	{ 0x00122c,   1, 0x04, 0x00000300 },
+	{ 0x001230,   1, 0x04, 0x00010001 },
+	{ 0x0007f8,   1, 0x04, 0x00000000 },
+	{ 0x0015b4,   1, 0x04, 0x00000001 },
+	{ 0x0015cc,   1, 0x04, 0x00000000 },
+	{ 0x001534,   1, 0x04, 0x00000000 },
+	{ 0x000fb0,   1, 0x04, 0x00000000 },
+	{ 0x0015d0,   1, 0x04, 0x00000000 },
+	{ 0x00153c,   1, 0x04, 0x00000000 },
+	{ 0x0016b4,   1, 0x04, 0x00000003 },
+	{ 0x000fbc,   4, 0x04, 0x0000ffff },
+	{ 0x000df8,   2, 0x04, 0x00000000 },
+	{ 0x001948,   1, 0x04, 0x00000000 },
+	{ 0x001970,   1, 0x04, 0x00000001 },
+	{ 0x00161c,   1, 0x04, 0x000009f0 },
+	{ 0x000dcc,   1, 0x04, 0x00000010 },
+	{ 0x00163c,   1, 0x04, 0x00000000 },
+	{ 0x0015e4,   1, 0x04, 0x00000000 },
+	{ 0x001160,  32, 0x04, 0x25e00040 },
+	{ 0x001880,  32, 0x04, 0x00000000 },
+	{ 0x000f84,   2, 0x04, 0x00000000 },
+	{ 0x0017c8,   2, 0x04, 0x00000000 },
+	{ 0x0017d0,   1, 0x04, 0x000000ff },
+	{ 0x0017d4,   1, 0x04, 0xffffffff },
+	{ 0x0017d8,   1, 0x04, 0x00000002 },
+	{ 0x0017dc,   1, 0x04, 0x00000000 },
+	{ 0x0015f4,   2, 0x04, 0x00000000 },
+	{ 0x001434,   2, 0x04, 0x00000000 },
+	{ 0x000d74,   1, 0x04, 0x00000000 },
+	{ 0x000dec,   1, 0x04, 0x00000001 },
+	{ 0x0013a4,   1, 0x04, 0x00000000 },
+	{ 0x001318,   1, 0x04, 0x00000001 },
+	{ 0x001644,   1, 0x04, 0x00000000 },
+	{ 0x000748,   1, 0x04, 0x00000000 },
+	{ 0x000de8,   1, 0x04, 0x00000000 },
+	{ 0x001648,   1, 0x04, 0x00000000 },
+	{ 0x0012a4,   1, 0x04, 0x00000000 },
+	{ 0x001120,   4, 0x04, 0x00000000 },
+	{ 0x001118,   1, 0x04, 0x00000000 },
+	{ 0x00164c,   1, 0x04, 0x00000000 },
+	{ 0x001658,   1, 0x04, 0x00000000 },
+	{ 0x001910,   1, 0x04, 0x00000290 },
+	{ 0x001518,   1, 0x04, 0x00000000 },
+	{ 0x00165c,   1, 0x04, 0x00000001 },
+	{ 0x001520,   1, 0x04, 0x00000000 },
+	{ 0x001604,   1, 0x04, 0x00000000 },
+	{ 0x001570,   1, 0x04, 0x00000000 },
+	{ 0x0013b0,   2, 0x04, 0x3f800000 },
+	{ 0x00020c,   1, 0x04, 0x00000000 },
+	{ 0x001670,   1, 0x04, 0x30201000 },
+	{ 0x001674,   1, 0x04, 0x70605040 },
+	{ 0x001678,   1, 0x04, 0xb8a89888 },
+	{ 0x00167c,   1, 0x04, 0xf8e8d8c8 },
+	{ 0x00166c,   1, 0x04, 0x00000000 },
+	{ 0x001680,   1, 0x04, 0x00ffff00 },
+	{ 0x0012d0,   1, 0x04, 0x00000003 },
+	{ 0x0012d4,   1, 0x04, 0x00000002 },
+	{ 0x001684,   2, 0x04, 0x00000000 },
+	{ 0x000dac,   2, 0x04, 0x00001b02 },
+	{ 0x000db4,   1, 0x04, 0x00000000 },
+	{ 0x00168c,   1, 0x04, 0x00000000 },
+	{ 0x0015bc,   1, 0x04, 0x00000000 },
+	{ 0x00156c,   1, 0x04, 0x00000000 },
+	{ 0x00187c,   1, 0x04, 0x00000000 },
+	{ 0x001110,   1, 0x04, 0x00000001 },
+	{ 0x000dc0,   3, 0x04, 0x00000000 },
+	{ 0x001234,   1, 0x04, 0x00000000 },
+	{ 0x001690,   1, 0x04, 0x00000000 },
+	{ 0x0012ac,   1, 0x04, 0x00000001 },
+	{ 0x0002c4,   1, 0x04, 0x00000000 },
+	{ 0x000790,   5, 0x04, 0x00000000 },
+	{ 0x00077c,   1, 0x04, 0x00000000 },
+	{ 0x001000,   1, 0x04, 0x00000010 },
+	{ 0x0010fc,   1, 0x04, 0x00000000 },
+	{ 0x001290,   1, 0x04, 0x00000000 },
+	{ 0x000218,   1, 0x04, 0x00000010 },
+	{ 0x0012d8,   1, 0x04, 0x00000000 },
+	{ 0x0012dc,   1, 0x04, 0x00000010 },
+	{ 0x000d94,   1, 0x04, 0x00000001 },
+	{ 0x00155c,   2, 0x04, 0x00000000 },
+	{ 0x001564,   1, 0x04, 0x00000fff },
+	{ 0x001574,   2, 0x04, 0x00000000 },
+	{ 0x00157c,   1, 0x04, 0x000fffff },
+	{ 0x001354,   1, 0x04, 0x00000000 },
+	{ 0x001610,   1, 0x04, 0x00000012 },
+	{ 0x001608,   2, 0x04, 0x00000000 },
+	{ 0x00260c,   1, 0x04, 0x00000000 },
+	{ 0x0007ac,   1, 0x04, 0x00000000 },
+	{ 0x00162c,   1, 0x04, 0x00000003 },
+	{ 0x000210,   1, 0x04, 0x00000000 },
+	{ 0x000320,   1, 0x04, 0x00000000 },
+	{ 0x000324,   6, 0x04, 0x3f800000 },
+	{ 0x000750,   1, 0x04, 0x00000000 },
+	{ 0x000760,   1, 0x04, 0x39291909 },
+	{ 0x000764,   1, 0x04, 0x79695949 },
+	{ 0x000768,   1, 0x04, 0xb9a99989 },
+	{ 0x00076c,   1, 0x04, 0xf9e9d9c9 },
+	{ 0x000770,   1, 0x04, 0x30201000 },
+	{ 0x000774,   1, 0x04, 0x70605040 },
+	{ 0x000778,   1, 0x04, 0x00009080 },
+	{ 0x000780,   1, 0x04, 0x39291909 },
+	{ 0x000784,   1, 0x04, 0x79695949 },
+	{ 0x000788,   1, 0x04, 0xb9a99989 },
+	{ 0x00078c,   1, 0x04, 0xf9e9d9c9 },
+	{ 0x0007d0,   1, 0x04, 0x30201000 },
+	{ 0x0007d4,   1, 0x04, 0x70605040 },
+	{ 0x0007d8,   1, 0x04, 0x00009080 },
+	{ 0x00037c,   1, 0x04, 0x00000001 },
+	{ 0x000740,   2, 0x04, 0x00000000 },
+	{ 0x002600,   1, 0x04, 0x00000000 },
+	{ 0x001918,   1, 0x04, 0x00000000 },
+	{ 0x00191c,   1, 0x04, 0x00000900 },
+	{ 0x001920,   1, 0x04, 0x00000405 },
+	{ 0x001308,   1, 0x04, 0x00000001 },
+	{ 0x001924,   1, 0x04, 0x00000000 },
+	{ 0x0013ac,   1, 0x04, 0x00000000 },
+	{ 0x00192c,   1, 0x04, 0x00000001 },
+	{ 0x00193c,   1, 0x04, 0x00002c1c },
+	{ 0x000d7c,   1, 0x04, 0x00000000 },
+	{ 0x000f8c,   1, 0x04, 0x00000000 },
+	{ 0x0002c0,   1, 0x04, 0x00000001 },
+	{ 0x001510,   1, 0x04, 0x00000000 },
+	{ 0x001940,   1, 0x04, 0x00000000 },
+	{ 0x000ff4,   2, 0x04, 0x00000000 },
+	{ 0x00194c,   2, 0x04, 0x00000000 },
+	{ 0x001968,   1, 0x04, 0x00000000 },
+	{ 0x001590,   1, 0x04, 0x0000003f },
+	{ 0x0007e8,   4, 0x04, 0x00000000 },
+	{ 0x00196c,   1, 0x04, 0x00000011 },
+	{ 0x0002e4,   1, 0x04, 0x0000b001 },
+	{ 0x00036c,   2, 0x04, 0x00000000 },
+	{ 0x00197c,   1, 0x04, 0x00000000 },
+	{ 0x000fcc,   2, 0x04, 0x00000000 },
+	{ 0x0002d8,   1, 0x04, 0x00000040 },
+	{ 0x001980,   1, 0x04, 0x00000080 },
+	{ 0x001504,   1, 0x04, 0x00000080 },
+	{ 0x001984,   1, 0x04, 0x00000000 },
+	{ 0x000300,   1, 0x04, 0x00000001 },
+	{ 0x0013a8,   1, 0x04, 0x00000000 },
+	{ 0x0012ec,   1, 0x04, 0x00000000 },
+	{ 0x001310,   1, 0x04, 0x00000000 },
+	{ 0x001314,   1, 0x04, 0x00000001 },
+	{ 0x001380,   1, 0x04, 0x00000000 },
+	{ 0x001384,   4, 0x04, 0x00000001 },
+	{ 0x001394,   1, 0x04, 0x00000000 },
+	{ 0x00139c,   1, 0x04, 0x00000000 },
+	{ 0x001398,   1, 0x04, 0x00000000 },
+	{ 0x001594,   1, 0x04, 0x00000000 },
+	{ 0x001598,   4, 0x04, 0x00000001 },
+	{ 0x000f54,   3, 0x04, 0x00000000 },
+	{ 0x0019bc,   1, 0x04, 0x00000000 },
+	{ 0x000f9c,   2, 0x04, 0x00000000 },
+	{ 0x0012cc,   1, 0x04, 0x00000000 },
+	{ 0x0012e8,   1, 0x04, 0x00000000 },
+	{ 0x00130c,   1, 0x04, 0x00000001 },
+	{ 0x001360,   8, 0x04, 0x00000000 },
+	{ 0x00133c,   2, 0x04, 0x00000001 },
+	{ 0x001344,   1, 0x04, 0x00000002 },
+	{ 0x001348,   2, 0x04, 0x00000001 },
+	{ 0x001350,   1, 0x04, 0x00000002 },
+	{ 0x001358,   1, 0x04, 0x00000001 },
+	{ 0x0012e4,   1, 0x04, 0x00000000 },
+	{ 0x00131c,   4, 0x04, 0x00000000 },
+	{ 0x0019c0,   1, 0x04, 0x00000000 },
+	{ 0x001140,   1, 0x04, 0x00000000 },
+	{ 0x0019c4,   1, 0x04, 0x00000000 },
+	{ 0x0019c8,   1, 0x04, 0x00001500 },
+	{ 0x00135c,   1, 0x04, 0x00000000 },
+	{ 0x000f90,   1, 0x04, 0x00000000 },
+	{ 0x0019e0,   8, 0x04, 0x00000001 },
+	{ 0x0019cc,   1, 0x04, 0x00000001 },
+	{ 0x0015b8,   1, 0x04, 0x00000000 },
+	{ 0x001a00,   1, 0x04, 0x00001111 },
+	{ 0x001a04,   7, 0x04, 0x00000000 },
+	{ 0x000d6c,   2, 0x04, 0xffff0000 },
+	{ 0x0010f8,   1, 0x04, 0x00001010 },
+	{ 0x000d80,   5, 0x04, 0x00000000 },
+	{ 0x000da0,   1, 0x04, 0x00000000 },
+	{ 0x0007a4,   2, 0x04, 0x00000000 },
+	{ 0x001508,   1, 0x04, 0x80000000 },
+	{ 0x00150c,   1, 0x04, 0x40000000 },
+	{ 0x001668,   1, 0x04, 0x00000000 },
+	{ 0x000318,   2, 0x04, 0x00000008 },
+	{ 0x000d9c,   1, 0x04, 0x00000001 },
+	{ 0x000ddc,   1, 0x04, 0x00000002 },
+	{ 0x000374,   1, 0x04, 0x00000000 },
+	{ 0x000378,   1, 0x04, 0x00000020 },
+	{ 0x0007dc,   1, 0x04, 0x00000000 },
+	{ 0x00074c,   1, 0x04, 0x00000055 },
+	{ 0x001420,   1, 0x04, 0x00000003 },
+	{ 0x0017bc,   2, 0x04, 0x00000000 },
+	{ 0x0017c4,   1, 0x04, 0x00000001 },
+	{ 0x001008,   1, 0x04, 0x00000008 },
+	{ 0x00100c,   1, 0x04, 0x00000040 },
+	{ 0x001010,   1, 0x04, 0x0000012c },
+	{ 0x000d60,   1, 0x04, 0x00000040 },
+	{ 0x00075c,   1, 0x04, 0x00000003 },
+	{ 0x001018,   1, 0x04, 0x00000020 },
+	{ 0x00101c,   1, 0x04, 0x00000001 },
+	{ 0x001020,   1, 0x04, 0x00000020 },
+	{ 0x001024,   1, 0x04, 0x00000001 },
+	{ 0x001444,   3, 0x04, 0x00000000 },
+	{ 0x000360,   1, 0x04, 0x20164010 },
+	{ 0x000364,   1, 0x04, 0x00000020 },
+	{ 0x000368,   1, 0x04, 0x00000000 },
+	{ 0x000de4,   1, 0x04, 0x00000000 },
+	{ 0x000204,   1, 0x04, 0x00000006 },
+	{ 0x000208,   1, 0x04, 0x00000000 },
+	{ 0x0002cc,   2, 0x04, 0x003fffff },
+	{ 0x001220,   1, 0x04, 0x00000005 },
+	{ 0x000fdc,   1, 0x04, 0x00000000 },
+	{ 0x000f98,   1, 0x04, 0x00400008 },
+	{ 0x001284,   1, 0x04, 0x08000080 },
+	{ 0x001450,   1, 0x04, 0x00400008 },
+	{ 0x001454,   1, 0x04, 0x08000080 },
+	{ 0x000214,   1, 0x04, 0x00000000 },
+	{}
+};
+
+static struct nvc0_graph_init
+nv108_grctx_init_unk40xx[] = {
+	{ 0x404004,   8, 0x04, 0x00000000 },
+	{ 0x404024,   1, 0x04, 0x0000e000 },
+	{ 0x404028,   8, 0x04, 0x00000000 },
+	{ 0x4040a8,   8, 0x04, 0x00000000 },
+	{ 0x4040c8,   1, 0x04, 0xf800008f },
+	{ 0x4040d0,   6, 0x04, 0x00000000 },
+	{ 0x4040e8,   1, 0x04, 0x00001000 },
+	{ 0x4040f8,   1, 0x04, 0x00000000 },
+	{ 0x404100,  10, 0x04, 0x00000000 },
+	{ 0x404130,   2, 0x04, 0x00000000 },
+	{ 0x404138,   1, 0x04, 0x20000040 },
+	{ 0x404150,   1, 0x04, 0x0000002e },
+	{ 0x404154,   1, 0x04, 0x00000400 },
+	{ 0x404158,   1, 0x04, 0x00000200 },
+	{ 0x404164,   1, 0x04, 0x00000055 },
+	{ 0x40417c,   2, 0x04, 0x00000000 },
+	{ 0x404194,   1, 0x04, 0x01000700 },
+	{ 0x4041a0,   4, 0x04, 0x00000000 },
+	{ 0x404200,   1, 0x04, 0x0000a197 },
+	{ 0x404204,   1, 0x04, 0x0000a1c0 },
+	{ 0x404208,   1, 0x04, 0x0000a140 },
+	{ 0x40420c,   1, 0x04, 0x0000902d },
+	{}
+};
+
+static struct nvc0_graph_init
+nv108_grctx_init_unk58xx[] = {
+	{ 0x405800,   1, 0x04, 0x0f8000bf },
+	{ 0x405830,   1, 0x04, 0x02180648 },
+	{ 0x405834,   1, 0x04, 0x08000000 },
+	{ 0x405838,   1, 0x04, 0x00000000 },
+	{ 0x405854,   1, 0x04, 0x00000000 },
+	{ 0x405870,   4, 0x04, 0x00000001 },
+	{ 0x405a00,   2, 0x04, 0x00000000 },
+	{ 0x405a18,   1, 0x04, 0x00000000 },
+	{ 0x405a1c,   1, 0x04, 0x000000ff },
+	{}
+};
+
+static struct nvc0_graph_init
+nv108_grctx_init_unk64xx[] = {
+	{ 0x4064a8,   1, 0x04, 0x00000000 },
+	{ 0x4064ac,   1, 0x04, 0x00003fff },
+	{ 0x4064b0,   3, 0x04, 0x00000000 },
+	{ 0x4064c0,   1, 0x04, 0x802000f0 },
+	{ 0x4064c4,   1, 0x04, 0x0192ffff },
+	{ 0x4064c8,   1, 0x04, 0x00c20200 },
+	{ 0x4064cc,   9, 0x04, 0x00000000 },
+	{ 0x4064fc,   1, 0x04, 0x0000022a },
+	{}
+};
+
+static struct nvc0_graph_init
+nv108_grctx_init_unk78xx[] = {
+	{ 0x407804,   1, 0x04, 0x00000063 },
+	{ 0x40780c,   1, 0x04, 0x0a418820 },
+	{ 0x407810,   1, 0x04, 0x062080e6 },
+	{ 0x407814,   1, 0x04, 0x020398a4 },
+	{ 0x407818,   1, 0x04, 0x0e629062 },
+	{ 0x40781c,   1, 0x04, 0x0a418820 },
+	{ 0x407820,   1, 0x04, 0x000000e6 },
+	{ 0x4078bc,   1, 0x04, 0x00000103 },
+	{}
+};
+
+static struct nvc0_graph_init
+nv108_grctx_init_unk88xx[] = {
+	{ 0x408800,   1, 0x04, 0x32802a3c },
+	{ 0x408804,   1, 0x04, 0x00000040 },
+	{ 0x408808,   1, 0x04, 0x1003e005 },
+	{ 0x408840,   1, 0x04, 0x0000000b },
+	{ 0x408900,   1, 0x04, 0xb080b801 },
+	{ 0x408904,   1, 0x04, 0x62000001 },
+	{ 0x408908,   1, 0x04, 0x02c8102f },
+	{ 0x408980,   1, 0x04, 0x0000011d },
+	{}
+};
+
+static struct nvc0_graph_init
+nv108_grctx_init_gpc_0[] = {
+	{ 0x418380,   1, 0x04, 0x00000016 },
+	{ 0x418400,   1, 0x04, 0x38005e00 },
+	{ 0x418404,   1, 0x04, 0x71e0ffff },
+	{ 0x41840c,   1, 0x04, 0x00001008 },
+	{ 0x418410,   1, 0x04, 0x0fff0fff },
+	{ 0x418414,   1, 0x04, 0x02200fff },
+	{ 0x418450,   6, 0x04, 0x00000000 },
+	{ 0x418468,   1, 0x04, 0x00000001 },
+	{ 0x41846c,   2, 0x04, 0x00000000 },
+	{ 0x418600,   1, 0x04, 0x0000007f },
+	{ 0x418684,   1, 0x04, 0x0000001f },
+	{ 0x418700,   1, 0x04, 0x00000002 },
+	{ 0x418704,   2, 0x04, 0x00000080 },
+	{ 0x41870c,   2, 0x04, 0x00000000 },
+	{ 0x418800,   1, 0x04, 0x7006863a },
+	{ 0x418808,   1, 0x04, 0x00000000 },
+	{ 0x41880c,   1, 0x04, 0x00000030 },
+	{ 0x418810,   1, 0x04, 0x00000000 },
+	{ 0x418828,   1, 0x04, 0x00000044 },
+	{ 0x418830,   1, 0x04, 0x10000001 },
+	{ 0x4188d8,   1, 0x04, 0x00000008 },
+	{ 0x4188e0,   1, 0x04, 0x01000000 },
+	{ 0x4188e8,   5, 0x04, 0x00000000 },
+	{ 0x4188fc,   1, 0x04, 0x20100058 },
+	{ 0x41891c,   1, 0x04, 0x00ff00ff },
+	{ 0x418924,   1, 0x04, 0x00000000 },
+	{ 0x418928,   1, 0x04, 0x00ffff00 },
+	{ 0x41892c,   1, 0x04, 0x0000ff00 },
+	{ 0x418b00,   1, 0x04, 0x0000001e },
+	{ 0x418b08,   1, 0x04, 0x0a418820 },
+	{ 0x418b0c,   1, 0x04, 0x062080e6 },
+	{ 0x418b10,   1, 0x04, 0x020398a4 },
+	{ 0x418b14,   1, 0x04, 0x0e629062 },
+	{ 0x418b18,   1, 0x04, 0x0a418820 },
+	{ 0x418b1c,   1, 0x04, 0x000000e6 },
+	{ 0x418bb8,   1, 0x04, 0x00000103 },
+	{ 0x418c08,   1, 0x04, 0x00000001 },
+	{ 0x418c10,   8, 0x04, 0x00000000 },
+	{ 0x418c40,   1, 0x04, 0xffffffff },
+	{ 0x418c6c,   1, 0x04, 0x00000001 },
+	{ 0x418c80,   1, 0x04, 0x2020000c },
+	{ 0x418c8c,   1, 0x04, 0x00000001 },
+	{ 0x418d24,   1, 0x04, 0x00000000 },
+	{ 0x419000,   1, 0x04, 0x00000780 },
+	{ 0x419004,   2, 0x04, 0x00000000 },
+	{ 0x419014,   1, 0x04, 0x00000004 },
+	{}
+};
+
+static struct nvc0_graph_init
+nv108_grctx_init_tpc[] = {
+	{ 0x419848,   1, 0x04, 0x00000000 },
+	{ 0x419864,   1, 0x04, 0x00000129 },
+	{ 0x419888,   1, 0x04, 0x00000000 },
+	{ 0x419a00,   1, 0x04, 0x000100f0 },
+	{ 0x419a04,   1, 0x04, 0x00000001 },
+	{ 0x419a08,   1, 0x04, 0x00000421 },
+	{ 0x419a0c,   1, 0x04, 0x00120000 },
+	{ 0x419a10,   1, 0x04, 0x00000000 },
+	{ 0x419a14,   1, 0x04, 0x00000200 },
+	{ 0x419a1c,   1, 0x04, 0x0000c000 },
+	{ 0x419a20,   1, 0x04, 0x00000800 },
+	{ 0x419a30,   1, 0x04, 0x00000001 },
+	{ 0x419ac4,   1, 0x04, 0x0037f440 },
+	{ 0x419c00,   1, 0x04, 0x0000001a },
+	{ 0x419c04,   1, 0x04, 0x80000006 },
+	{ 0x419c08,   1, 0x04, 0x00000002 },
+	{ 0x419c20,   1, 0x04, 0x00000000 },
+	{ 0x419c24,   1, 0x04, 0x00084210 },
+	{ 0x419c28,   1, 0x04, 0x3efbefbe },
+	{ 0x419ce8,   1, 0x04, 0x00000000 },
+	{ 0x419cf4,   1, 0x04, 0x00000203 },
+	{ 0x419e04,   1, 0x04, 0x00000000 },
+	{ 0x419e08,   1, 0x04, 0x0000001d },
+	{ 0x419e0c,   1, 0x04, 0x00000000 },
+	{ 0x419e10,   1, 0x04, 0x00001c02 },
+	{ 0x419e44,   1, 0x04, 0x0013eff2 },
+	{ 0x419e48,   1, 0x04, 0x00000000 },
+	{ 0x419e4c,   1, 0x04, 0x0000007f },
+	{ 0x419e50,   2, 0x04, 0x00000000 },
+	{ 0x419e58,   1, 0x04, 0x00000001 },
+	{ 0x419e5c,   3, 0x04, 0x00000000 },
+	{ 0x419e68,   1, 0x04, 0x00000002 },
+	{ 0x419e6c,  12, 0x04, 0x00000000 },
+	{ 0x419eac,   1, 0x04, 0x00001f8f },
+	{ 0x419eb0,   1, 0x04, 0x0db00da0 },
+	{ 0x419eb8,   1, 0x04, 0x00000000 },
+	{ 0x419ec8,   1, 0x04, 0x0001304f },
+	{ 0x419f30,   4, 0x04, 0x00000000 },
+	{ 0x419f40,   1, 0x04, 0x00000018 },
+	{ 0x419f44,   3, 0x04, 0x00000000 },
+	{ 0x419f58,   1, 0x04, 0x00000020 },
+	{ 0x419f70,   1, 0x04, 0x00000000 },
+	{ 0x419f78,   1, 0x04, 0x000001eb },
+	{ 0x419f7c,   1, 0x04, 0x00000404 },
+	{}
+};
+
+static struct nvc0_graph_init
+nv108_grctx_init_unk[] = {
+	{ 0x41be24,   1, 0x04, 0x00000006 },
+	{ 0x41bec0,   1, 0x04, 0x10000000 },
+	{ 0x41bec4,   1, 0x04, 0x00037f7f },
+	{ 0x41bee4,   1, 0x04, 0x00000000 },
+	{ 0x41bef0,   1, 0x04, 0x000003ff },
+	{ 0x41bf00,   1, 0x04, 0x0a418820 },
+	{ 0x41bf04,   1, 0x04, 0x062080e6 },
+	{ 0x41bf08,   1, 0x04, 0x020398a4 },
+	{ 0x41bf0c,   1, 0x04, 0x0e629062 },
+	{ 0x41bf10,   1, 0x04, 0x0a418820 },
+	{ 0x41bf14,   1, 0x04, 0x000000e6 },
+	{ 0x41bfd0,   1, 0x04, 0x00900103 },
+	{ 0x41bfe0,   1, 0x04, 0x00400001 },
+	{ 0x41bfe4,   1, 0x04, 0x00000000 },
+	{}
+};
+
+static void
+nv108_grctx_generate_mods(struct nvc0_graph_priv *priv, struct nvc0_grctx *info)
+{
+	u32 magic[GPC_MAX][2];
+	u32 offset;
+	int gpc;
+
+	mmio_data(0x003000, 0x0100, NV_MEM_ACCESS_RW | NV_MEM_ACCESS_SYS);
+	mmio_data(0x008000, 0x0100, NV_MEM_ACCESS_RW | NV_MEM_ACCESS_SYS);
+	mmio_data(0x060000, 0x1000, NV_MEM_ACCESS_RW);
+	mmio_list(0x40800c, 0x00000000,  8, 1);
+	mmio_list(0x408010, 0x80000000,  0, 0);
+	mmio_list(0x419004, 0x00000000,  8, 1);
+	mmio_list(0x419008, 0x00000000,  0, 0);
+	mmio_list(0x408004, 0x00000000,  8, 0);
+	mmio_list(0x408008, 0x80000030,  0, 0);
+	mmio_list(0x418808, 0x00000000,  8, 0);
+	mmio_list(0x41880c, 0x80000030,  0, 0);
+	mmio_list(0x418810, 0x80000000, 12, 2);
+	mmio_list(0x419848, 0x10000000, 12, 2);
+
+	mmio_list(0x405830, 0x02180648,  0, 0);
+	mmio_list(0x4064c4, 0x0192ffff,  0, 0);
+
+	for (gpc = 0, offset = 0; gpc < priv->gpc_nr; gpc++) {
+		u16 magic0 = 0x0218 * priv->tpc_nr[gpc];
+		u16 magic1 = 0x0648 * priv->tpc_nr[gpc];
+		magic[gpc][0]  = 0x10000000 | (magic0 << 16) | offset;
+		magic[gpc][1]  = 0x00000000 | (magic1 << 16);
+		offset += 0x0324 * priv->tpc_nr[gpc];
+	}
+
+	for (gpc = 0; gpc < priv->gpc_nr; gpc++) {
+		mmio_list(GPC_UNIT(gpc, 0x30c0), magic[gpc][0], 0, 0);
+		mmio_list(GPC_UNIT(gpc, 0x30e4), magic[gpc][1] | offset, 0, 0);
+		offset += 0x07ff * priv->tpc_nr[gpc];
+	}
+
+	mmio_list(0x17e91c, 0x0b040a0b, 0, 0);
+	mmio_list(0x17e920, 0x00090d08, 0, 0);
+}
+
+static struct nvc0_graph_init *
+nv108_grctx_init_hub[] = {
+	nvc0_grctx_init_base,
+	nv108_grctx_init_unk40xx,
+	nvf0_grctx_init_unk44xx,
+	nve4_grctx_init_unk46xx,
+	nve4_grctx_init_unk47xx,
+	nv108_grctx_init_unk58xx,
+	nvf0_grctx_init_unk5bxx,
+	nvf0_grctx_init_unk60xx,
+	nv108_grctx_init_unk64xx,
+	nv108_grctx_init_unk78xx,
+	nve4_grctx_init_unk80xx,
+	nv108_grctx_init_unk88xx,
+	NULL
+};
+
+struct nvc0_graph_init *
+nv108_grctx_init_gpc[] = {
+	nv108_grctx_init_gpc_0,
+	nvc0_grctx_init_gpc_1,
+	nv108_grctx_init_tpc,
+	nv108_grctx_init_unk,
+	NULL
+};
+
+struct nvc0_graph_init
+nv108_grctx_init_mthd_magic[] = {
+	{ 0x3410, 1, 0x04, 0x8e0e2006 },
+	{ 0x3414, 1, 0x04, 0x00000038 },
+	{}
+};
+
+static struct nvc0_graph_mthd
+nv108_grctx_init_mthd[] = {
+	{ 0xa197, nv108_grctx_init_a197, },
+	{ 0x902d, nvc0_grctx_init_902d, },
+	{ 0x902d, nv108_grctx_init_mthd_magic, },
+	{}
+};
+
+struct nouveau_oclass *
+nv108_grctx_oclass = &(struct nvc0_grctx_oclass) {
+	.base.handle = NV_ENGCTX(GR, 0x08),
+	.base.ofuncs = &(struct nouveau_ofuncs) {
+		.ctor = nvc0_graph_context_ctor,
+		.dtor = nvc0_graph_context_dtor,
+		.init = _nouveau_graph_context_init,
+		.fini = _nouveau_graph_context_fini,
+		.rd32 = _nouveau_graph_context_rd32,
+		.wr32 = _nouveau_graph_context_wr32,
+	},
+	.main = nve4_grctx_generate_main,
+	.mods = nv108_grctx_generate_mods,
+	.unkn = nve4_grctx_generate_unkn,
+	.hub  = nv108_grctx_init_hub,
+	.gpc  = nv108_grctx_init_gpc,
+	.icmd = nv108_grctx_init_icmd,
+	.mthd = nv108_grctx_init_mthd,
+}.base;
diff --git a/drivers/gpu/drm/nouveau/core/engine/graph/ctxnvf0.c b/drivers/gpu/drm/nouveau/core/engine/graph/ctxnvf0.c
index dcb2ebb8c29d9..44012c3da5383 100644
--- a/drivers/gpu/drm/nouveau/core/engine/graph/ctxnvf0.c
+++ b/drivers/gpu/drm/nouveau/core/engine/graph/ctxnvf0.c
@@ -50,7 +50,7 @@ nvf0_grctx_init_unk40xx[] = {
 	{}
 };
 
-static struct nvc0_graph_init
+struct nvc0_graph_init
 nvf0_grctx_init_unk44xx[] = {
 	{ 0x404404,  12, 0x04, 0x00000000 },
 	{ 0x404438,   1, 0x04, 0x00000000 },
@@ -62,7 +62,7 @@ nvf0_grctx_init_unk44xx[] = {
 	{}
 };
 
-static struct nvc0_graph_init
+struct nvc0_graph_init
 nvf0_grctx_init_unk5bxx[] = {
 	{ 0x405b00,   1, 0x04, 0x00000000 },
 	{ 0x405b10,   1, 0x04, 0x00001000 },
@@ -70,7 +70,7 @@ nvf0_grctx_init_unk5bxx[] = {
 	{}
 };
 
-static struct nvc0_graph_init
+struct nvc0_graph_init
 nvf0_grctx_init_unk60xx[] = {
 	{ 0x406020,   1, 0x04, 0x034103c1 },
 	{ 0x406028,   4, 0x04, 0x00000001 },
@@ -286,7 +286,6 @@ nvf0_grctx_init_hub[] = {
 	nvf0_grctx_init_unk64xx,
 	nve4_grctx_init_unk80xx,
 	nvf0_grctx_init_unk88xx,
-	nvd9_grctx_init_rop,
 	NULL
 };
 
diff --git a/drivers/gpu/drm/nouveau/core/engine/graph/fuc/com.fuc b/drivers/gpu/drm/nouveau/core/engine/graph/fuc/com.fuc
index 5d24b6de16cce..e148961b8075e 100644
--- a/drivers/gpu/drm/nouveau/core/engine/graph/fuc/com.fuc
+++ b/drivers/gpu/drm/nouveau/core/engine/graph/fuc/com.fuc
@@ -38,7 +38,7 @@ queue_put:
 	cmpu b32 $r8 $r9
 	bra ne #queue_put_next
 		mov $r15 E_CMD_OVERFLOW
-		call #error
+		call(error)
 		ret
 
 	// store cmd/data on queue
@@ -92,18 +92,16 @@ queue_get_done:
 // Out: $r15 value
 //
 nv_rd32:
-	mov $r11 0x728
-	shl b32 $r11 6
 	mov b32 $r12 $r14
 	bset $r12 31			// MMIO_CTRL_PENDING
-	iowr I[$r11 + 0x000] $r12	// MMIO_CTRL
+	nv_iowr(NV_PGRAPH_FECS_MMIO_CTRL, 0, $r12)
 	nv_rd32_wait:
-		iord $r12 I[$r11 + 0x000]
+		nv_iord($r12, NV_PGRAPH_FECS_MMIO_CTRL, 0)
 		xbit $r12 $r12 31
 		bra ne #nv_rd32_wait
 	mov $r10 6			// DONE_MMIO_RD
-	call #wait_doneo
-	iord $r15 I[$r11 + 0x100]	// MMIO_RDVAL
+	call(wait_doneo)
+	nv_iord($r15, NV_PGRAPH_FECS_MMIO_RDVAL, 0)
 	ret
 
 // nv_wr32 - write 32-bit value to nv register
@@ -112,37 +110,17 @@ nv_rd32:
 //      $r15 value
 //
 nv_wr32:
-	mov $r11 0x728
-	shl b32 $r11 6
-	iowr I[$r11 + 0x200] $r15	// MMIO_WRVAL
+	nv_iowr(NV_PGRAPH_FECS_MMIO_WRVAL, 0, $r15)
 	mov b32 $r12 $r14
 	bset $r12 31			// MMIO_CTRL_PENDING
 	bset $r12 30			// MMIO_CTRL_WRITE
-	iowr I[$r11 + 0x000] $r12	// MMIO_CTRL
+	nv_iowr(NV_PGRAPH_FECS_MMIO_CTRL, 0, $r12)
 	nv_wr32_wait:
-		iord $r12 I[$r11 + 0x000]
+		nv_iord($r12, NV_PGRAPH_FECS_MMIO_CTRL, 0)
 		xbit $r12 $r12 31
 		bra ne #nv_wr32_wait
 	ret
 
-// (re)set watchdog timer
-//
-// In : $r15 timeout
-//
-watchdog_reset:
-	mov $r8 0x430
-	shl b32 $r8 6
-	bset $r15 31
-	iowr I[$r8 + 0x000] $r15
-	ret
-
-// clear watchdog timer
-watchdog_clear:
-	mov $r8 0x430
-	shl b32 $r8 6
-	iowr I[$r8 + 0x000] $r0
-	ret
-
 // wait_donez - wait on FUC_DONE bit to become clear
 //
 // In : $r10 bit to wait on
@@ -163,13 +141,9 @@ wait_donez:
 //
 wait_doneo:
 	trace_set(T_WAIT);
-	mov $r8 0x818
-	shl b32 $r8 6
-	iowr I[$r8 + 0x000] $r10
+	nv_iowr(NV_PGRAPH_FECS_CC_SCRATCH_VAL(6), 0, $r10)
 	wait_doneo_e:
-		mov $r8 0x400
-		shl b32 $r8 6
-		iord $r8 I[$r8 + 0x000]
+		nv_iord($r8, NV_PGRAPH_FECS_SIGNAL, 0)
 		xbit $r8 $r8 $r10
 		bra e #wait_doneo_e
 	trace_clr(T_WAIT)
@@ -209,21 +183,18 @@ mmctx_size:
 //
 mmctx_xfer:
 	trace_set(T_MMCTX)
-	mov $r8 0x710
-	shl b32 $r8 6
 	clear b32 $r9
 	or $r11 $r11
 	bra e #mmctx_base_disabled
-		iowr I[$r8 + 0x000] $r11	// MMCTX_BASE
+		nv_iowr(NV_PGRAPH_FECS_MMCTX_BASE, 0, $r11)
 		bset $r9 0			// BASE_EN
 	mmctx_base_disabled:
 	or $r14 $r14
 	bra e #mmctx_multi_disabled
-		iowr I[$r8 + 0x200] $r14 	// MMCTX_MULTI_STRIDE
-		iowr I[$r8 + 0x300] $r15 	// MMCTX_MULTI_MASK
+		nv_iowr(NV_PGRAPH_FECS_MMCTX_MULTI_STRIDE, 0, $r14)
+		nv_iowr(NV_PGRAPH_FECS_MMCTX_MULTI_MASK, 0, $r15)
 		bset $r9 1			// MULTI_EN
 	mmctx_multi_disabled:
-	add b32 $r8 0x100
 
 	xbit $r11 $r10 0
 	shl b32 $r11 16			// DIR
@@ -231,20 +202,20 @@ mmctx_xfer:
 	xbit $r14 $r10 1
 	shl b32 $r14 17
 	or $r11 $r14			// START_TRIGGER
-	iowr I[$r8 + 0x000] $r11	// MMCTX_CTRL
+	nv_iowr(NV_PGRAPH_FECS_MMCTX_CTRL, 0, $r11)
 
 	// loop over the mmio list, and send requests to the hw
 	mmctx_exec_loop:
 		// wait for space in mmctx queue
 		mmctx_wait_free:
-			iord $r14 I[$r8 + 0x000] // MMCTX_CTRL
+			nv_iord($r14, NV_PGRAPH_FECS_MMCTX_CTRL, 0)
 			and $r14 0x1f
 			bra e #mmctx_wait_free
 
 		// queue up an entry
 		ld b32 $r14 D[$r12]
 		or $r14 $r9
-		iowr I[$r8 + 0x300] $r14
+		nv_iowr(NV_PGRAPH_FECS_MMCTX_QUEUE, 0, $r14)
 		add b32 $r12 4
 		cmpu b32 $r12 $r13
 		bra ne #mmctx_exec_loop
@@ -253,22 +224,22 @@ mmctx_xfer:
 	bra ne #mmctx_stop
 		// wait for queue to empty
 		mmctx_fini_wait:
-			iord $r11 I[$r8 + 0x000]	// MMCTX_CTRL
+			nv_iord($r11, NV_PGRAPH_FECS_MMCTX_CTRL, 0)
 			and $r11 0x1f
 			cmpu b32 $r11 0x10
 			bra ne #mmctx_fini_wait
 		mov $r10 2				// DONE_MMCTX
-		call #wait_donez
+		call(wait_donez)
 		bra #mmctx_done
 	mmctx_stop:
 		xbit $r11 $r10 0
 		shl b32 $r11 16			// DIR
 		bset $r11 12			// QLIMIT = 0x10
 		bset $r11 18			// STOP_TRIGGER
-		iowr I[$r8 + 0x000] $r11	// MMCTX_CTRL
+		nv_iowr(NV_PGRAPH_FECS_MMCTX_CTRL, 0, $r11)
 		mmctx_stop_wait:
 			// wait for STOP_TRIGGER to clear
-			iord $r11 I[$r8 + 0x000] // MMCTX_CTRL
+			nv_iord($r11, NV_PGRAPH_FECS_MMCTX_CTRL, 0)
 			xbit $r11 $r11 18
 			bra ne #mmctx_stop_wait
 	mmctx_done:
@@ -280,28 +251,24 @@ mmctx_xfer:
 strand_wait:
 	push $r10
 	mov $r10 2
-	call #wait_donez
+	call(wait_donez)
 	pop $r10
 	ret
 
 // unknown - call before issuing strand commands
 //
 strand_pre:
-	mov $r8 0x4afc
-	sethi $r8 0x20000
-	mov $r9 0xc
-	iowr I[$r8] $r9
-	call #strand_wait
+	mov $r9 NV_PGRAPH_FECS_STRAND_CMD_ENABLE
+	nv_iowr(NV_PGRAPH_FECS_STRAND_CMD, 0x3f, $r9)
+	call(strand_wait)
 	ret
 
 // unknown - call after issuing strand commands
 //
 strand_post:
-	mov $r8 0x4afc
-	sethi $r8 0x20000
-	mov $r9 0xd
-	iowr I[$r8] $r9
-	call #strand_wait
+	mov $r9 NV_PGRAPH_FECS_STRAND_CMD_DISABLE
+	nv_iowr(NV_PGRAPH_FECS_STRAND_CMD, 0x3f, $r9)
+	call(strand_wait)
 	ret
 
 // Selects strand set?!
@@ -309,18 +276,14 @@ strand_post:
 // In: $r14 id
 //
 strand_set:
-	mov $r10 0x4ffc
-	sethi $r10 0x20000
-	sub b32 $r11 $r10 0x500
 	mov $r12 0xf
-	iowr I[$r10 + 0x000] $r12		// 0x93c = 0xf
-	mov $r12 0xb
-	iowr I[$r11 + 0x000] $r12		// 0x928 = 0xb
-	call #strand_wait
-	iowr I[$r10 + 0x000] $r14		// 0x93c = <id>
-	mov $r12 0xa
-	iowr I[$r11 + 0x000] $r12		// 0x928 = 0xa
-	call #strand_wait
+	nv_iowr(NV_PGRAPH_FECS_STRAND_FILTER, 0x3f, $r12)
+	mov $r12 NV_PGRAPH_FECS_STRAND_CMD_DEACTIVATE_FILTER
+	nv_iowr(NV_PGRAPH_FECS_STRAND_CMD, 0x3f, $r12)
+	nv_iowr(NV_PGRAPH_FECS_STRAND_FILTER, 0x3f, $r14)
+	mov $r12 NV_PGRAPH_FECS_STRAND_CMD_ACTIVATE_FILTER
+	nv_iowr(NV_PGRAPH_FECS_STRAND_CMD, 0x3f, $r12)
+	call(strand_wait)
 	ret
 
 // Initialise strand context data
@@ -332,30 +295,27 @@ strand_set:
 //
 strand_ctx_init:
 	trace_set(T_STRINIT)
-	call #strand_pre
+	call(strand_pre)
 	mov $r14 3
-	call #strand_set
-	mov $r10 0x46fc
-	sethi $r10 0x20000
-	add b32 $r11 $r10 0x400
-	iowr I[$r10 + 0x100] $r0	// STRAND_FIRST_GENE = 0
-	mov $r12 1
-	iowr I[$r11 + 0x000] $r12	// STRAND_CMD = LATCH_FIRST_GENE
-	call #strand_wait
+	call(strand_set)
+
+	clear b32 $r12
+	nv_iowr(NV_PGRAPH_FECS_STRAND_SELECT, 0x3f, $r12)
+	mov $r12 NV_PGRAPH_FECS_STRAND_CMD_SEEK
+	nv_iowr(NV_PGRAPH_FECS_STRAND_CMD, 0x3f, $r12)
+	call(strand_wait)
 	sub b32 $r12 $r0 1
-	iowr I[$r10 + 0x000] $r12	// STRAND_GENE_CNT = 0xffffffff
-	mov $r12 2
-	iowr I[$r11 + 0x000] $r12	// STRAND_CMD = LATCH_GENE_CNT
-	call #strand_wait
-	call #strand_post
+	nv_iowr(NV_PGRAPH_FECS_STRAND_DATA, 0x3f, $r12)
+	mov $r12 NV_PGRAPH_FECS_STRAND_CMD_GET_INFO
+	nv_iowr(NV_PGRAPH_FECS_STRAND_CMD, 0x3f, $r12)
+	call(strand_wait)
+	call(strand_post)
 
 	// read the size of each strand, poke the context offset of
 	// each into STRAND_{SAVE,LOAD}_SWBASE now, no need to worry
 	// about it later then.
-	mov $r8 0x880
-	shl b32 $r8 6
-	iord $r9 I[$r8 + 0x000]		// STRANDS
-	add b32 $r8 0x2200
+	nv_mkio($r8, NV_PGRAPH_FECS_STRAND_SAVE_SWBASE, 0x00)
+	nv_iord($r9, NV_PGRAPH_FECS_STRANDS_CNT, 0x00)
 	shr b32 $r14 $r15 8
 	ctx_init_strand_loop:
 		iowr I[$r8 + 0x000] $r14	// STRAND_SAVE_SWBASE
diff --git a/drivers/gpu/drm/nouveau/core/engine/graph/fuc/gpc.fuc b/drivers/gpu/drm/nouveau/core/engine/graph/fuc/gpc.fuc
index 5547c1b3f4f29..96cbcea3b2c96 100644
--- a/drivers/gpu/drm/nouveau/core/engine/graph/fuc/gpc.fuc
+++ b/drivers/gpu/drm/nouveau/core/engine/graph/fuc/gpc.fuc
@@ -58,12 +58,9 @@ mmio_list_base:
 //
 error:
 	push $r14
-	mov $r14 -0x67ec 	// 0x9814
-	sethi $r14 0x400000
-	call #nv_wr32		// HUB_CTXCTL_CC_SCRATCH[5] = error code
-	add b32 $r14 0x41c
+	nv_wr32(NV_PGRAPH_FECS_CC_SCRATCH_VAL(5), $r15)
 	mov $r15 1
-	call #nv_wr32		// HUB_CTXCTL_INTR_UP_SET
+	nv_wr32(NV_PGRAPH_FECS_INTR_UP_SET, $r15)
 	pop $r14
 	ret
 
@@ -84,46 +81,40 @@ init:
 	mov $sp $r0
 
 	// enable fifo access
-	mov $r1 0x1200
-	mov $r2 2
-	iowr I[$r1 + 0x000] $r2		// FIFO_ENABLE
+	mov $r2 NV_PGRAPH_GPCX_GPCCS_ACCESS_FIFO
+	nv_iowr(NV_PGRAPH_GPCX_GPCCS_ACCESS, 0, $r2)
 
 	// setup i0 handler, and route all interrupts to it
 	mov $r1 #ih
 	mov $iv0 $r1
-	mov $r1 0x400
-	iowr I[$r1 + 0x300] $r0		// INTR_DISPATCH
+	nv_iowr(NV_PGRAPH_GPCX_GPCCS_INTR_ROUTE, 0, $r0)
 
 	// enable fifo interrupt
-	mov $r2 4
-	iowr I[$r1 + 0x000] $r2		// INTR_EN_SET
+	mov $r2 NV_PGRAPH_GPCX_GPCCS_INTR_EN_SET_FIFO
+	nv_iowr(NV_PGRAPH_GPCX_GPCCS_INTR_EN_SET, 0, $r2)
 
 	// enable interrupts
 	bset $flags ie0
 
 	// figure out which GPC we are, and how many TPCs we have
-	mov $r1 0x608
-	shl b32 $r1 6
-	iord $r2 I[$r1 + 0x000]		// UNITS
+	nv_iord($r2, NV_PGRAPH_GPCX_GPCCS_UNITS, 0)
 	mov $r3 1
 	and $r2 0x1f
 	shl b32 $r3 $r2
 	sub b32 $r3 1
 	st b32 D[$r0 + #tpc_count] $r2
 	st b32 D[$r0 + #tpc_mask] $r3
-	add b32 $r1 0x400
-	iord $r2 I[$r1 + 0x000]		// MYINDEX
+	nv_iord($r2, NV_PGRAPH_GPCX_GPCCS_MYINDEX, 0)
 	st b32 D[$r0 + #gpc_id] $r2
 
 #if NV_PGRAPH_GPCX_UNK__SIZE > 0
 	// figure out which, and how many, UNKs are actually present
-	mov $r14 0x0c30
-	sethi $r14 0x500000
+	imm32($r14, 0x500c30)
 	clear b32 $r2
 	clear b32 $r3
 	clear b32 $r4
 	init_unk_loop:
-		call #nv_rd32
+		call(nv_rd32)
 		cmp b32 $r15 0
 		bra z #init_unk_next
 			mov $r15 1
@@ -146,23 +137,21 @@ init:
 
 	// set mmctx base addresses now so we don't have to do it later,
 	// they don't currently ever change
-	mov $r4 0x700
-	shl b32 $r4 6
 	shr b32 $r5 $r2 8
-	iowr I[$r4 + 0x000] $r5		// MMCTX_SAVE_SWBASE
-	iowr I[$r4 + 0x100] $r5		// MMCTX_LOAD_SWBASE
+	nv_iowr(NV_PGRAPH_GPCX_GPCCS_MMCTX_SAVE_SWBASE, 0, $r5)
+	nv_iowr(NV_PGRAPH_GPCX_GPCCS_MMCTX_LOAD_SWBASE, 0, $r5)
 
 	// calculate GPC mmio context size
 	ld b32 $r14 D[$r0 + #gpc_mmio_list_head]
 	ld b32 $r15 D[$r0 + #gpc_mmio_list_tail]
-	call #mmctx_size
+	call(mmctx_size)
 	add b32 $r2 $r15
 	add b32 $r3 $r15
 
 	// calculate per-TPC mmio context size
 	ld b32 $r14 D[$r0 + #tpc_mmio_list_head]
 	ld b32 $r15 D[$r0 + #tpc_mmio_list_tail]
-	call #mmctx_size
+	call(mmctx_size)
 	ld b32 $r14 D[$r0 + #tpc_count]
 	mulu $r14 $r15
 	add b32 $r2 $r14
@@ -172,7 +161,7 @@ init:
 	// calculate per-UNK mmio context size
 	ld b32 $r14 D[$r0 + #unk_mmio_list_head]
 	ld b32 $r15 D[$r0 + #unk_mmio_list_tail]
-	call #mmctx_size
+	call(mmctx_size)
 	ld b32 $r14 D[$r0 + #unk_count]
 	mulu $r14 $r15
 	add b32 $r2 $r14
@@ -180,9 +169,8 @@ init:
 #endif
 
 	// round up base/size to 256 byte boundary (for strand SWBASE)
-	add b32 $r4 0x1300
 	shr b32 $r3 2
-	iowr I[$r4 + 0x000] $r3		// MMCTX_LOAD_COUNT, wtf for?!?
+	nv_iowr(NV_PGRAPH_GPCX_GPCCS_MMCTX_LOAD_COUNT, 0, $r3) // wtf for?!
 	shr b32 $r2 8
 	shr b32 $r3 6
 	add b32 $r2 1
@@ -192,7 +180,7 @@ init:
 
 	// calculate size of strand context data
 	mov b32 $r15 $r2
-	call #strand_ctx_init
+	call(strand_ctx_init)
 	add b32 $r3 $r15
 
 	// save context size, and tell HUB we're done
@@ -208,7 +196,7 @@ main:
 	bset $flags $p0
 	sleep $p0
 	mov $r13 #cmd_queue
-	call #queue_get
+	call(queue_get)
 	bra $p1 #main
 
 	// 0x0000-0x0003 are all context transfers
@@ -224,13 +212,13 @@ main:
 		or $r1 $r14
 		mov $flags $r1
 		// transfer context data
-		call #ctx_xfer
+		call(ctx_xfer)
 		bra #main
 
 	main_not_ctx_xfer:
 	shl b32 $r15 $r14 16
 	or $r15 E_BAD_COMMAND
-	call #error
+	call(error)
 	bra #main
 
 // interrupt handler
@@ -247,22 +235,20 @@ ih:
 	clear b32 $r0
 
 	// incoming fifo command?
-	iord $r10 I[$r0 + 0x200]	// INTR
-	and $r11 $r10 0x00000004
+	nv_iord($r10, NV_PGRAPH_GPCX_GPCCS_INTR, 0)
+	and $r11 $r10 NV_PGRAPH_GPCX_GPCCS_INTR_FIFO
 	bra e #ih_no_fifo
 		// queue incoming fifo command for later processing
-		mov $r11 0x1900
 		mov $r13 #cmd_queue
-		iord $r14 I[$r11 + 0x100]	// FIFO_CMD
-		iord $r15 I[$r11 + 0x000]	// FIFO_DATA
-		call #queue_put
-		add b32 $r11 0x400
+		nv_iord($r14, NV_PGRAPH_GPCX_GPCCS_FIFO_CMD, 0)
+		nv_iord($r15, NV_PGRAPH_GPCX_GPCCS_FIFO_DATA, 0)
+		call(queue_put)
 		mov $r14 1
-		iowr I[$r11 + 0x000] $r14	// FIFO_ACK
+		nv_iowr(NV_PGRAPH_GPCX_GPCCS_FIFO_ACK, 0, $r14)
 
 	// ack, and wake up main()
 	ih_no_fifo:
-	iowr I[$r0 + 0x100] $r10	// INTR_ACK
+	nv_iowr(NV_PGRAPH_GPCX_GPCCS_INTR_ACK, 0, $r10)
 
 	pop $r15
 	pop $r14
@@ -283,9 +269,7 @@ hub_barrier_done:
 	mov $r15 1
 	ld b32 $r14 D[$r0 + #gpc_id]
 	shl b32 $r15 $r14
-	mov $r14 -0x6be8 	// 0x409418 - HUB_BAR_SET
-	sethi $r14 0x400000
-	call #nv_wr32
+	nv_wr32(0x409418, $r15)	// 0x409418 - HUB_BAR_SET
 	ret
 
 // Disables various things, waits a bit, and re-enables them..
@@ -295,16 +279,15 @@ hub_barrier_done:
 // funny things happen.
 //
 ctx_redswitch:
-	mov $r14 0x614
-	shl b32 $r14 6
-	mov $r15 0x020
-	iowr I[$r14] $r15	// GPC_RED_SWITCH = POWER
-	mov $r15 8
+	mov $r15 NV_PGRAPH_GPCX_GPCCS_RED_SWITCH_POWER
+	nv_iowr(NV_PGRAPH_GPCX_GPCCS_RED_SWITCH, 0, $r15)
+	mov $r14 8
 	ctx_redswitch_delay:
-		sub b32 $r15 1
+		sub b32 $r14 1
 		bra ne #ctx_redswitch_delay
-	mov $r15 0xa20
-	iowr I[$r14] $r15	// GPC_RED_SWITCH = UNK11, ENABLE, POWER
+	or $r15 NV_PGRAPH_GPCX_GPCCS_RED_SWITCH_UNK11
+	or $r15 NV_PGRAPH_GPCX_GPCCS_RED_SWITCH_ENABLE
+	nv_iowr(NV_PGRAPH_GPCX_GPCCS_RED_SWITCH, 0, $r15)
 	ret
 
 // Transfer GPC context data between GPU and storage area
@@ -317,46 +300,37 @@ ctx_redswitch:
 //
 ctx_xfer:
 	// set context base address
-	mov $r1 0xa04
-	shl b32 $r1 6
-	iowr I[$r1 + 0x000] $r15// MEM_BASE
+	nv_iowr(NV_PGRAPH_GPCX_GPCCS_MEM_BASE, 0, $r15)
 	bra not $p1 #ctx_xfer_not_load
-		call #ctx_redswitch
+		call(ctx_redswitch)
 	ctx_xfer_not_load:
 
 	// strands
-	mov $r1 0x4afc
-	sethi $r1 0x20000
-	mov $r2 0xc
-	iowr I[$r1] $r2		// STRAND_CMD(0x3f) = 0x0c
-	call #strand_wait
-	mov $r2 0x47fc
-	sethi $r2 0x20000
-	iowr I[$r2] $r0		// STRAND_FIRST_GENE(0x3f) = 0x00
-	xbit $r2 $flags $p1
-	add b32 $r2 3
-	iowr I[$r1] $r2		// STRAND_CMD(0x3f) = 0x03/0x04 (SAVE/LOAD)
+	call(strand_pre)
+	clear b32 $r2
+	nv_iowr(NV_PGRAPH_GPCX_GPCCS_STRAND_SELECT, 0x3f, $r2)
+	xbit $r2 $flags $p1	// SAVE/LOAD
+	add b32 $r2 NV_PGRAPH_GPCX_GPCCS_STRAND_CMD_SAVE
+	nv_iowr(NV_PGRAPH_GPCX_GPCCS_STRAND_CMD, 0x3f, $r2)
 
 	// mmio context
 	xbit $r10 $flags $p1	// direction
 	or $r10 2		// first
-	mov $r11 0x0000
-	sethi $r11 0x500000
+	imm32($r11,0x500000)
 	ld b32 $r12 D[$r0 + #gpc_id]
 	shl b32 $r12 15
 	add b32 $r11 $r12	// base = NV_PGRAPH_GPCn
 	ld b32 $r12 D[$r0 + #gpc_mmio_list_head]
 	ld b32 $r13 D[$r0 + #gpc_mmio_list_tail]
 	mov $r14 0		// not multi
-	call #mmctx_xfer
+	call(mmctx_xfer)
 
 	// per-TPC mmio context
 	xbit $r10 $flags $p1	// direction
 #if !NV_PGRAPH_GPCX_UNK__SIZE
 	or $r10 4		// last
 #endif
-	mov $r11 0x4000
-	sethi $r11 0x500000	// base = NV_PGRAPH_GPC0_TPC0
+	imm32($r11, 0x504000)
 	ld b32 $r12 D[$r0 + #gpc_id]
 	shl b32 $r12 15
 	add b32 $r11 $r12	// base = NV_PGRAPH_GPCn_TPC0
@@ -364,14 +338,13 @@ ctx_xfer:
 	ld b32 $r13 D[$r0 + #tpc_mmio_list_tail]
 	ld b32 $r15 D[$r0 + #tpc_mask]
 	mov $r14 0x800		// stride = 0x800
-	call #mmctx_xfer
+	call(mmctx_xfer)
 
 #if NV_PGRAPH_GPCX_UNK__SIZE > 0
 	// per-UNK mmio context
 	xbit $r10 $flags $p1	// direction
 	or $r10 4		// last
-	mov $r11 0x3000
-	sethi $r11 0x500000	// base = NV_PGRAPH_GPC0_UNK0
+	imm32($r11, 0x503000)
 	ld b32 $r12 D[$r0 + #gpc_id]
 	shl b32 $r12 15
 	add b32 $r11 $r12	// base = NV_PGRAPH_GPCn_UNK0
@@ -379,11 +352,11 @@ ctx_xfer:
 	ld b32 $r13 D[$r0 + #unk_mmio_list_tail]
 	ld b32 $r15 D[$r0 + #unk_mask]
 	mov $r14 0x200		// stride = 0x200
-	call #mmctx_xfer
+	call(mmctx_xfer)
 #endif
 
 	// wait for strands to finish
-	call #strand_wait
+	call(strand_wait)
 
 	// if load, or a save without a load following, do some
 	// unknown stuff that's done after finishing a block of
@@ -391,14 +364,10 @@ ctx_xfer:
 	bra $p1 #ctx_xfer_post
 	bra not $p2 #ctx_xfer_done
 	ctx_xfer_post:
-		mov $r1 0x4afc
-		sethi $r1 0x20000
-		mov $r2 0xd
-		iowr I[$r1] $r2		// STRAND_CMD(0x3f) = 0x0d
-		call #strand_wait
+		call(strand_post)
 
 	// mark completion in HUB's barrier
 	ctx_xfer_done:
-	call #hub_barrier_done
+	call(hub_barrier_done)
 	ret
 #endif
diff --git a/drivers/gpu/drm/nouveau/core/engine/graph/fuc/gpcnv108.fuc5 b/drivers/gpu/drm/nouveau/core/engine/graph/fuc/gpcnv108.fuc5
new file mode 100644
index 0000000000000..bd30262d635b2
--- /dev/null
+++ b/drivers/gpu/drm/nouveau/core/engine/graph/fuc/gpcnv108.fuc5
@@ -0,0 +1,42 @@
+/*
+ * Copyright 2013 Red Hat Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: Ben Skeggs <bskeggs@redhat.com>
+ */
+
+#define NV_PGRAPH_GPCX_UNK__SIZE                                     0x00000001
+
+#define CHIPSET GK208
+#include "macros.fuc"
+
+.section #nv108_grgpc_data
+#define INCLUDE_DATA
+#include "com.fuc"
+#include "gpc.fuc"
+#undef INCLUDE_DATA
+
+.section #nv108_grgpc_code
+#define INCLUDE_CODE
+bra #init
+#include "com.fuc"
+#include "gpc.fuc"
+.align 256
+#undef INCLUDE_CODE
diff --git a/drivers/gpu/drm/nouveau/core/engine/graph/fuc/gpcnv108.fuc5.h b/drivers/gpu/drm/nouveau/core/engine/graph/fuc/gpcnv108.fuc5.h
new file mode 100644
index 0000000000000..27dc1280dc101
--- /dev/null
+++ b/drivers/gpu/drm/nouveau/core/engine/graph/fuc/gpcnv108.fuc5.h
@@ -0,0 +1,473 @@
+uint32_t nv108_grgpc_data[] = {
+/* 0x0000: gpc_mmio_list_head */
+	0x0000006c,
+/* 0x0004: gpc_mmio_list_tail */
+/* 0x0004: tpc_mmio_list_head */
+	0x0000006c,
+/* 0x0008: tpc_mmio_list_tail */
+/* 0x0008: unk_mmio_list_head */
+	0x0000006c,
+/* 0x000c: unk_mmio_list_tail */
+	0x0000006c,
+/* 0x0010: gpc_id */
+	0x00000000,
+/* 0x0014: tpc_count */
+	0x00000000,
+/* 0x0018: tpc_mask */
+	0x00000000,
+/* 0x001c: unk_count */
+	0x00000000,
+/* 0x0020: unk_mask */
+	0x00000000,
+/* 0x0024: cmd_queue */
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+};
+
+uint32_t nv108_grgpc_code[] = {
+	0x03140ef5,
+/* 0x0004: queue_put */
+	0x9800d898,
+	0x86f001d9,
+	0xf489a408,
+	0x020f0b1b,
+	0x0002f87e,
+/* 0x001a: queue_put_next */
+	0x98c400f8,
+	0x0384b607,
+	0xb6008dbb,
+	0x8eb50880,
+	0x018fb500,
+	0xf00190b6,
+	0xd9b50f94,
+/* 0x0037: queue_get */
+	0xf400f801,
+	0xd8980131,
+	0x01d99800,
+	0x0bf489a4,
+	0x0789c421,
+	0xbb0394b6,
+	0x90b6009d,
+	0x009e9808,
+	0xb6019f98,
+	0x84f00180,
+	0x00d8b50f,
+/* 0x0063: queue_get_done */
+	0xf80132f4,
+/* 0x0065: nv_rd32 */
+	0xf0ecb200,
+	0x00801fc9,
+	0x0cf601ca,
+/* 0x0073: nv_rd32_wait */
+	0x8c04bd00,
+	0xcf01ca00,
+	0xccc800cc,
+	0xf61bf41f,
+	0xec7e060a,
+	0x008f0000,
+	0xffcf01cb,
+/* 0x008f: nv_wr32 */
+	0x8000f800,
+	0xf601cc00,
+	0x04bd000f,
+	0xc9f0ecb2,
+	0x1ec9f01f,
+	0x01ca0080,
+	0xbd000cf6,
+/* 0x00a9: nv_wr32_wait */
+	0xca008c04,
+	0x00cccf01,
+	0xf41fccc8,
+	0x00f8f61b,
+/* 0x00b8: wait_donez */
+	0x99f094bd,
+	0x37008000,
+	0x0009f602,
+	0x008004bd,
+	0x0af60206,
+/* 0x00cf: wait_donez_ne */
+	0x8804bd00,
+	0xcf010000,
+	0x8aff0088,
+	0xf61bf488,
+	0x99f094bd,
+	0x17008000,
+	0x0009f602,
+	0x00f804bd,
+/* 0x00ec: wait_doneo */
+	0x99f094bd,
+	0x37008000,
+	0x0009f602,
+	0x008004bd,
+	0x0af60206,
+/* 0x0103: wait_doneo_e */
+	0x8804bd00,
+	0xcf010000,
+	0x8aff0088,
+	0xf60bf488,
+	0x99f094bd,
+	0x17008000,
+	0x0009f602,
+	0x00f804bd,
+/* 0x0120: mmctx_size */
+/* 0x0122: nv_mmctx_size_loop */
+	0xe89894bd,
+	0x1a85b600,
+	0xb60180b6,
+	0x98bb0284,
+	0x04e0b600,
+	0x1bf4efa4,
+	0xf89fb2ec,
+/* 0x013d: mmctx_xfer */
+	0xf094bd00,
+	0x00800199,
+	0x09f60237,
+	0xbd04bd00,
+	0x05bbfd94,
+	0x800f0bf4,
+	0xf601c400,
+	0x04bd000b,
+/* 0x015f: mmctx_base_disabled */
+	0xfd0099f0,
+	0x0bf405ee,
+	0xc6008018,
+	0x000ef601,
+	0x008004bd,
+	0x0ff601c7,
+	0xf004bd00,
+/* 0x017a: mmctx_multi_disabled */
+	0xabc80199,
+	0x10b4b600,
+	0xc80cb9f0,
+	0xe4b601ae,
+	0x05befd11,
+	0x01c50080,
+	0xbd000bf6,
+/* 0x0195: mmctx_exec_loop */
+/* 0x0195: mmctx_wait_free */
+	0xc5008e04,
+	0x00eecf01,
+	0xf41fe4f0,
+	0xce98f60b,
+	0x05e9fd00,
+	0x01c80080,
+	0xbd000ef6,
+	0x04c0b604,
+	0x1bf4cda4,
+	0x02abc8df,
+/* 0x01bf: mmctx_fini_wait */
+	0x8b1c1bf4,
+	0xcf01c500,
+	0xb4f000bb,
+	0x10b4b01f,
+	0x0af31bf4,
+	0x00b87e02,
+	0x250ef400,
+/* 0x01d8: mmctx_stop */
+	0xb600abc8,
+	0xb9f010b4,
+	0x12b9f00c,
+	0x01c50080,
+	0xbd000bf6,
+/* 0x01ed: mmctx_stop_wait */
+	0xc5008b04,
+	0x00bbcf01,
+	0xf412bbc8,
+/* 0x01fa: mmctx_done */
+	0x94bdf61b,
+	0x800199f0,
+	0xf6021700,
+	0x04bd0009,
+/* 0x020a: strand_wait */
+	0xa0f900f8,
+	0xb87e020a,
+	0xa0fc0000,
+/* 0x0216: strand_pre */
+	0x0c0900f8,
+	0x024afc80,
+	0xbd0009f6,
+	0x020a7e04,
+/* 0x0227: strand_post */
+	0x0900f800,
+	0x4afc800d,
+	0x0009f602,
+	0x0a7e04bd,
+	0x00f80002,
+/* 0x0238: strand_set */
+	0xfc800f0c,
+	0x0cf6024f,
+	0x0c04bd00,
+	0x4afc800b,
+	0x000cf602,
+	0xfc8004bd,
+	0x0ef6024f,
+	0x0c04bd00,
+	0x4afc800a,
+	0x000cf602,
+	0x0a7e04bd,
+	0x00f80002,
+/* 0x0268: strand_ctx_init */
+	0x99f094bd,
+	0x37008003,
+	0x0009f602,
+	0x167e04bd,
+	0x030e0002,
+	0x0002387e,
+	0xfc80c4bd,
+	0x0cf60247,
+	0x0c04bd00,
+	0x4afc8001,
+	0x000cf602,
+	0x0a7e04bd,
+	0x0c920002,
+	0x46fc8001,
+	0x000cf602,
+	0x020c04bd,
+	0x024afc80,
+	0xbd000cf6,
+	0x020a7e04,
+	0x02277e00,
+	0x42008800,
+	0x20008902,
+	0x0099cf02,
+/* 0x02c7: ctx_init_strand_loop */
+	0xf608fe95,
+	0x8ef6008e,
+	0x808acf40,
+	0xb606a5b6,
+	0xeabb01a0,
+	0x0480b600,
+	0xf40192b6,
+	0xe4b6e81b,
+	0xf2efbc08,
+	0x99f094bd,
+	0x17008003,
+	0x0009f602,
+	0x00f804bd,
+/* 0x02f8: error */
+	0xffb2e0f9,
+	0x4098148e,
+	0x00008f7e,
+	0xffb2010f,
+	0x409c1c8e,
+	0x00008f7e,
+	0x00f8e0fc,
+/* 0x0314: init */
+	0x04fe04bd,
+	0x40020200,
+	0x02f61200,
+	0x4104bd00,
+	0x10fe0465,
+	0x07004000,
+	0xbd0000f6,
+	0x40040204,
+	0x02f60400,
+	0xf404bd00,
+	0x00821031,
+	0x22cf0182,
+	0xf0010300,
+	0x32bb1f24,
+	0x0132b604,
+	0xb50502b5,
+	0x00820603,
+	0x22cf0186,
+	0x0402b500,
+	0x500c308e,
+	0x34bd24bd,
+/* 0x036a: init_unk_loop */
+	0x657e44bd,
+	0xf6b00000,
+	0x0e0bf400,
+	0xf2bb010f,
+	0x054ffd04,
+/* 0x037f: init_unk_next */
+	0xb60130b6,
+	0xe0b60120,
+	0x0126b004,
+/* 0x038b: init_unk_done */
+	0xb5e21bf4,
+	0x04b50703,
+	0x01008208,
+	0x0022cf02,
+	0x259534bd,
+	0xc0008008,
+	0x0005f601,
+	0x008004bd,
+	0x05f601c1,
+	0x9804bd00,
+	0x0f98000e,
+	0x01207e01,
+	0x002fbb00,
+	0x98003fbb,
+	0x0f98010e,
+	0x01207e02,
+	0x050e9800,
+	0xbb00effd,
+	0x3ebb002e,
+	0x020e9800,
+	0x7e030f98,
+	0x98000120,
+	0xeffd070e,
+	0x002ebb00,
+	0xb6003ebb,
+	0x00800235,
+	0x03f601d3,
+	0xb604bd00,
+	0x35b60825,
+	0x0120b606,
+	0xb60130b6,
+	0x34b60824,
+	0x7e2fb208,
+	0xbb000268,
+	0x0080003f,
+	0x03f60201,
+	0xbd04bd00,
+	0x1f29f024,
+	0x02300080,
+	0xbd0002f6,
+/* 0x0429: main */
+	0x0031f404,
+	0x0d0028f4,
+	0x00377e24,
+	0xf401f400,
+	0xf404e4b0,
+	0x81fe1d18,
+	0xbd060201,
+	0x0412fd20,
+	0xfd01e4b6,
+	0x18fe051e,
+	0x04fc7e00,
+	0xd40ef400,
+/* 0x0458: main_not_ctx_xfer */
+	0xf010ef94,
+	0xf87e01f5,
+	0x0ef40002,
+/* 0x0465: ih */
+	0xfe80f9c7,
+	0x80f90188,
+	0xa0f990f9,
+	0xd0f9b0f9,
+	0xf0f9e0f9,
+	0x004a04bd,
+	0x00aacf02,
+	0xf404abc4,
+	0x240d1f0b,
+	0xcf1a004e,
+	0x004f00ee,
+	0x00ffcf19,
+	0x0000047e,
+	0x0040010e,
+	0x000ef61d,
+/* 0x04a2: ih_no_fifo */
+	0x004004bd,
+	0x000af601,
+	0xf0fc04bd,
+	0xd0fce0fc,
+	0xa0fcb0fc,
+	0x80fc90fc,
+	0xfc0088fe,
+	0x0032f480,
+/* 0x04c2: hub_barrier_done */
+	0x010f01f8,
+	0xbb040e98,
+	0xffb204fe,
+	0x4094188e,
+	0x00008f7e,
+/* 0x04d6: ctx_redswitch */
+	0x200f00f8,
+	0x01850080,
+	0xbd000ff6,
+/* 0x04e3: ctx_redswitch_delay */
+	0xb6080e04,
+	0x1bf401e2,
+	0x00f5f1fd,
+	0x00f5f108,
+	0x85008002,
+	0x000ff601,
+	0x00f804bd,
+/* 0x04fc: ctx_xfer */
+	0x02810080,
+	0xbd000ff6,
+	0x0711f404,
+	0x0004d67e,
+/* 0x050c: ctx_xfer_not_load */
+	0x0002167e,
+	0xfc8024bd,
+	0x02f60247,
+	0xf004bd00,
+	0x20b6012c,
+	0x4afc8003,
+	0x0002f602,
+	0xacf004bd,
+	0x02a5f001,
+	0x5000008b,
+	0xb6040c98,
+	0xbcbb0fc4,
+	0x000c9800,
+	0x0e010d98,
+	0x013d7e00,
+	0x01acf000,
+	0x5040008b,
+	0xb6040c98,
+	0xbcbb0fc4,
+	0x010c9800,
+	0x98020d98,
+	0x004e060f,
+	0x013d7e08,
+	0x01acf000,
+	0x8b04a5f0,
+	0x98503000,
+	0xc4b6040c,
+	0x00bcbb0f,
+	0x98020c98,
+	0x0f98030d,
+	0x02004e08,
+	0x00013d7e,
+	0x00020a7e,
+	0xf40601f4,
+/* 0x0596: ctx_xfer_post */
+	0x277e0712,
+/* 0x059a: ctx_xfer_done */
+	0xc27e0002,
+	0x00f80004,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+};
diff --git a/drivers/gpu/drm/nouveau/core/engine/graph/fuc/gpcnvc0.fuc.h b/drivers/gpu/drm/nouveau/core/engine/graph/fuc/gpcnvc0.fuc.h
index f2b0dea80116f..0e7b01efae8d2 100644
--- a/drivers/gpu/drm/nouveau/core/engine/graph/fuc/gpcnvc0.fuc.h
+++ b/drivers/gpu/drm/nouveau/core/engine/graph/fuc/gpcnvc0.fuc.h
@@ -37,14 +37,14 @@ uint32_t nvc0_grgpc_data[] = {
 };
 
 uint32_t nvc0_grgpc_code[] = {
-	0x03180ef5,
+	0x03a10ef5,
 /* 0x0004: queue_put */
 	0x9800d898,
 	0x86f001d9,
 	0x0489b808,
 	0xf00c1bf4,
 	0x21f502f7,
-	0x00f802fe,
+	0x00f8037e,
 /* 0x001c: queue_put_next */
 	0xb60798c4,
 	0x8dbb0384,
@@ -68,184 +68,214 @@ uint32_t nvc0_grgpc_code[] = {
 /* 0x0066: queue_get_done */
 	0x00f80132,
 /* 0x0068: nv_rd32 */
-	0x0728b7f1,
-	0xb906b4b6,
-	0xc9f002ec,
-	0x00bcd01f,
-/* 0x0078: nv_rd32_wait */
-	0xc800bccf,
-	0x1bf41fcc,
-	0x06a7f0fa,
-	0x010921f5,
-	0xf840bfcf,
-/* 0x008d: nv_wr32 */
-	0x28b7f100,
-	0x06b4b607,
-	0xb980bfd0,
-	0xc9f002ec,
-	0x1ec9f01f,
-/* 0x00a3: nv_wr32_wait */
-	0xcf00bcd0,
-	0xccc800bc,
-	0xfa1bf41f,
-/* 0x00ae: watchdog_reset */
-	0x87f100f8,
-	0x84b60430,
-	0x1ff9f006,
-	0xf8008fd0,
-/* 0x00bd: watchdog_clear */
-	0x3087f100,
-	0x0684b604,
-	0xf80080d0,
-/* 0x00c9: wait_donez */
-	0xf094bd00,
-	0x07f10099,
-	0x03f00f00,
-	0x0009d002,
-	0x07f104bd,
-	0x03f00600,
-	0x000ad002,
-/* 0x00e6: wait_donez_ne */
-	0x87f104bd,
-	0x83f00000,
-	0x0088cf01,
-	0xf4888aff,
-	0x94bdf31b,
-	0xf10099f0,
-	0xf0170007,
-	0x09d00203,
-	0xf804bd00,
-/* 0x0109: wait_doneo */
-	0xf094bd00,
+	0xf002ecb9,
+	0x07f11fc9,
+	0x03f0ca00,
+	0x000cd001,
+/* 0x007a: nv_rd32_wait */
+	0xc7f104bd,
+	0xc3f0ca00,
+	0x00cccf01,
+	0xf41fccc8,
+	0xa7f0f31b,
+	0x1021f506,
+	0x00f7f101,
+	0x01f3f0cb,
+	0xf800ffcf,
+/* 0x009d: nv_wr32 */
+	0x0007f100,
+	0x0103f0cc,
+	0xbd000fd0,
+	0x02ecb904,
+	0xf01fc9f0,
+	0x07f11ec9,
+	0x03f0ca00,
+	0x000cd001,
+/* 0x00be: nv_wr32_wait */
+	0xc7f104bd,
+	0xc3f0ca00,
+	0x00cccf01,
+	0xf41fccc8,
+	0x00f8f31b,
+/* 0x00d0: wait_donez */
+	0x99f094bd,
+	0x0007f100,
+	0x0203f00f,
+	0xbd0009d0,
+	0x0007f104,
+	0x0203f006,
+	0xbd000ad0,
+/* 0x00ed: wait_donez_ne */
+	0x0087f104,
+	0x0183f000,
+	0xff0088cf,
+	0x1bf4888a,
+	0xf094bdf3,
 	0x07f10099,
-	0x03f00f00,
+	0x03f01700,
 	0x0009d002,
-	0x87f104bd,
-	0x84b60818,
-	0x008ad006,
-/* 0x0124: wait_doneo_e */
-	0x040087f1,
-	0xcf0684b6,
-	0x8aff0088,
-	0xf30bf488,
+	0x00f804bd,
+/* 0x0110: wait_doneo */
 	0x99f094bd,
 	0x0007f100,
-	0x0203f017,
+	0x0203f00f,
 	0xbd0009d0,
-/* 0x0147: mmctx_size */
-	0xbd00f804,
-/* 0x0149: nv_mmctx_size_loop */
-	0x00e89894,
-	0xb61a85b6,
-	0x84b60180,
-	0x0098bb02,
-	0xb804e0b6,
-	0x1bf404ef,
-	0x029fb9eb,
-/* 0x0166: mmctx_xfer */
-	0x94bd00f8,
-	0xf10199f0,
-	0xf00f0007,
-	0x09d00203,
-	0xf104bd00,
-	0xb6071087,
-	0x94bd0684,
-	0xf405bbfd,
-	0x8bd0090b,
-	0x0099f000,
-/* 0x018c: mmctx_base_disabled */
-	0xf405eefd,
-	0x8ed00c0b,
-	0xc08fd080,
-/* 0x019b: mmctx_multi_disabled */
-	0xb70199f0,
-	0xc8010080,
+	0x0007f104,
+	0x0203f006,
+	0xbd000ad0,
+/* 0x012d: wait_doneo_e */
+	0x0087f104,
+	0x0183f000,
+	0xff0088cf,
+	0x0bf4888a,
+	0xf094bdf3,
+	0x07f10099,
+	0x03f01700,
+	0x0009d002,
+	0x00f804bd,
+/* 0x0150: mmctx_size */
+/* 0x0152: nv_mmctx_size_loop */
+	0xe89894bd,
+	0x1a85b600,
+	0xb60180b6,
+	0x98bb0284,
+	0x04e0b600,
+	0xf404efb8,
+	0x9fb9eb1b,
+/* 0x016f: mmctx_xfer */
+	0xbd00f802,
+	0x0199f094,
+	0x0f0007f1,
+	0xd00203f0,
+	0x04bd0009,
+	0xbbfd94bd,
+	0x120bf405,
+	0xc40007f1,
+	0xd00103f0,
+	0x04bd000b,
+/* 0x0197: mmctx_base_disabled */
+	0xfd0099f0,
+	0x0bf405ee,
+	0x0007f11e,
+	0x0103f0c6,
+	0xbd000ed0,
+	0x0007f104,
+	0x0103f0c7,
+	0xbd000fd0,
+	0x0199f004,
+/* 0x01b8: mmctx_multi_disabled */
+	0xb600abc8,
+	0xb9f010b4,
+	0x01aec80c,
+	0xfd11e4b6,
+	0x07f105be,
+	0x03f0c500,
+	0x000bd001,
+/* 0x01d6: mmctx_exec_loop */
+/* 0x01d6: mmctx_wait_free */
+	0xe7f104bd,
+	0xe3f0c500,
+	0x00eecf01,
+	0xf41fe4f0,
+	0xce98f30b,
+	0x05e9fd00,
+	0xc80007f1,
+	0xd00103f0,
+	0x04bd000e,
+	0xb804c0b6,
+	0x1bf404cd,
+	0x02abc8d8,
+/* 0x0207: mmctx_fini_wait */
+	0xf11f1bf4,
+	0xf0c500b7,
+	0xbbcf01b3,
+	0x1fb4f000,
+	0xf410b4b0,
+	0xa7f0f01b,
+	0xd021f402,
+/* 0x0223: mmctx_stop */
+	0xc82b0ef4,
 	0xb4b600ab,
 	0x0cb9f010,
-	0xb601aec8,
-	0xbefd11e4,
-	0x008bd005,
-/* 0x01b4: mmctx_exec_loop */
-/* 0x01b4: mmctx_wait_free */
-	0xf0008ecf,
-	0x0bf41fe4,
-	0x00ce98fa,
-	0xd005e9fd,
-	0xc0b6c08e,
-	0x04cdb804,
-	0xc8e81bf4,
-	0x1bf402ab,
-/* 0x01d5: mmctx_fini_wait */
-	0x008bcf18,
-	0xb01fb4f0,
-	0x1bf410b4,
-	0x02a7f0f7,
-	0xf4c921f4,
-/* 0x01ea: mmctx_stop */
-	0xabc81b0e,
-	0x10b4b600,
-	0xf00cb9f0,
-	0x8bd012b9,
-/* 0x01f9: mmctx_stop_wait */
-	0x008bcf00,
-	0xf412bbc8,
-/* 0x0202: mmctx_done */
-	0x94bdfa1b,
-	0xf10199f0,
-	0xf0170007,
-	0x09d00203,
-	0xf804bd00,
-/* 0x0215: strand_wait */
-	0xf0a0f900,
-	0x21f402a7,
-	0xf8a0fcc9,
-/* 0x0221: strand_pre */
-	0xfc87f100,
-	0x0283f04a,
-	0xd00c97f0,
-	0x21f50089,
-	0x00f80215,
-/* 0x0234: strand_post */
-	0x4afc87f1,
-	0xf00283f0,
-	0x89d00d97,
-	0x1521f500,
-/* 0x0247: strand_set */
-	0xf100f802,
-	0xf04ffca7,
-	0xaba202a3,
-	0xc7f00500,
-	0x00acd00f,
-	0xd00bc7f0,
-	0x21f500bc,
-	0xaed00215,
-	0x0ac7f000,
-	0xf500bcd0,
-	0xf8021521,
-/* 0x0271: strand_ctx_init */
-	0xf094bd00,
-	0x07f10399,
-	0x03f00f00,
+	0xf112b9f0,
+	0xf0c50007,
+	0x0bd00103,
+/* 0x023b: mmctx_stop_wait */
+	0xf104bd00,
+	0xf0c500b7,
+	0xbbcf01b3,
+	0x12bbc800,
+/* 0x024b: mmctx_done */
+	0xbdf31bf4,
+	0x0199f094,
+	0x170007f1,
+	0xd00203f0,
+	0x04bd0009,
+/* 0x025e: strand_wait */
+	0xa0f900f8,
+	0xf402a7f0,
+	0xa0fcd021,
+/* 0x026a: strand_pre */
+	0x97f000f8,
+	0xfc07f10c,
+	0x0203f04a,
+	0xbd0009d0,
+	0x5e21f504,
+/* 0x027f: strand_post */
+	0xf000f802,
+	0x07f10d97,
+	0x03f04afc,
 	0x0009d002,
 	0x21f504bd,
-	0xe7f00221,
-	0x4721f503,
-	0xfca7f102,
-	0x02a3f046,
-	0x0400aba0,
-	0xf040a0d0,
-	0xbcd001c7,
-	0x1521f500,
-	0x010c9202,
-	0xf000acd0,
-	0xbcd002c7,
-	0x1521f500,
-	0x3421f502,
-	0x8087f102,
-	0x0684b608,
-	0xb70089cf,
-	0x95220080,
-/* 0x02ca: ctx_init_strand_loop */
+	0x00f8025e,
+/* 0x0294: strand_set */
+	0xf10fc7f0,
+	0xf04ffc07,
+	0x0cd00203,
+	0xf004bd00,
+	0x07f10bc7,
+	0x03f04afc,
+	0x000cd002,
+	0x07f104bd,
+	0x03f04ffc,
+	0x000ed002,
+	0xc7f004bd,
+	0xfc07f10a,
+	0x0203f04a,
+	0xbd000cd0,
+	0x5e21f504,
+/* 0x02d3: strand_ctx_init */
+	0xbd00f802,
+	0x0399f094,
+	0x0f0007f1,
+	0xd00203f0,
+	0x04bd0009,
+	0x026a21f5,
+	0xf503e7f0,
+	0xbd029421,
+	0xfc07f1c4,
+	0x0203f047,
+	0xbd000cd0,
+	0x01c7f004,
+	0x4afc07f1,
+	0xd00203f0,
+	0x04bd000c,
+	0x025e21f5,
+	0xf1010c92,
+	0xf046fc07,
+	0x0cd00203,
+	0xf004bd00,
+	0x07f102c7,
+	0x03f04afc,
+	0x000cd002,
+	0x21f504bd,
+	0x21f5025e,
+	0x87f1027f,
+	0x83f04200,
+	0x0097f102,
+	0x0293f020,
+	0x950099cf,
+/* 0x034a: ctx_init_strand_loop */
 	0x8ed008fe,
 	0x408ed000,
 	0xb6808acf,
@@ -259,167 +289,199 @@ uint32_t nvc0_grgpc_code[] = {
 	0x170007f1,
 	0xd00203f0,
 	0x04bd0009,
-/* 0x02fe: error */
+/* 0x037e: error */
 	0xe0f900f8,
-	0x9814e7f1,
-	0xf440e3f0,
-	0xe0b78d21,
-	0xf7f0041c,
-	0x8d21f401,
-	0x00f8e0fc,
-/* 0x0318: init */
-	0x04fe04bd,
-	0x0017f100,
-	0x0227f012,
-	0xf10012d0,
-	0xfe042617,
-	0x17f10010,
-	0x10d00400,
-	0x0427f0c0,
-	0xf40012d0,
-	0x17f11031,
-	0x14b60608,
-	0x0012cf06,
+	0xf102ffb9,
+	0xf09814e7,
+	0x21f440e3,
+	0x01f7f09d,
+	0xf102ffb9,
+	0xf09c1ce7,
+	0x21f440e3,
+	0xf8e0fc9d,
+/* 0x03a1: init */
+	0xfe04bd00,
+	0x27f00004,
+	0x0007f102,
+	0x0003f012,
+	0xbd0002d0,
+	0xd517f104,
+	0x0010fe04,
+	0x070007f1,
+	0xd00003f0,
+	0x04bd0000,
+	0xf10427f0,
+	0xf0040007,
+	0x02d00003,
+	0xf404bd00,
+	0x27f11031,
+	0x23f08200,
+	0x0022cf01,
 	0xf00137f0,
 	0x32bb1f24,
 	0x0132b604,
 	0x80050280,
-	0x10b70603,
-	0x12cf0400,
-	0x04028000,
-	0x010027f1,
-	0xcf0223f0,
-	0x34bd0022,
-	0x070047f1,
-	0x950644b6,
-	0x45d00825,
-	0x4045d000,
-	0x98000e98,
-	0x21f5010f,
-	0x2fbb0147,
-	0x003fbb00,
-	0x98010e98,
-	0x21f5020f,
-	0x0e980147,
-	0x00effd05,
-	0xbb002ebb,
-	0x40b7003e,
-	0x35b61300,
-	0x0043d002,
-	0xb60825b6,
-	0x20b60635,
-	0x0130b601,
-	0xb60824b6,
-	0x2fb90834,
-	0x7121f502,
-	0x003fbb02,
-	0x010007f1,
+	0x27f10603,
+	0x23f08600,
+	0x0022cf01,
+	0xf1040280,
+	0xf0010027,
+	0x22cf0223,
+	0x9534bd00,
+	0x07f10825,
+	0x03f0c000,
+	0x0005d001,
+	0x07f104bd,
+	0x03f0c100,
+	0x0005d001,
+	0x0e9804bd,
+	0x010f9800,
+	0x015021f5,
+	0xbb002fbb,
+	0x0e98003f,
+	0x020f9801,
+	0x015021f5,
+	0xfd050e98,
+	0x2ebb00ef,
+	0x003ebb00,
+	0xf10235b6,
+	0xf0d30007,
+	0x03d00103,
+	0xb604bd00,
+	0x35b60825,
+	0x0120b606,
+	0xb60130b6,
+	0x34b60824,
+	0x022fb908,
+	0x02d321f5,
+	0xf1003fbb,
+	0xf0010007,
+	0x03d00203,
+	0xbd04bd00,
+	0x1f29f024,
+	0x080007f1,
 	0xd00203f0,
-	0x04bd0003,
-	0x29f024bd,
-	0x0007f11f,
-	0x0203f008,
-	0xbd0002d0,
-/* 0x03e9: main */
-	0x0031f404,
-	0xf00028f4,
-	0x21f41cd7,
-	0xf401f439,
-	0xf404e4b0,
-	0x81fe1e18,
-	0x0627f001,
-	0x12fd20bd,
-	0x01e4b604,
-	0xfe051efd,
-	0x21f50018,
-	0x0ef404ad,
-/* 0x0419: main_not_ctx_xfer */
-	0x10ef94d3,
-	0xf501f5f0,
-	0xf402fe21,
-/* 0x0426: ih */
-	0x80f9c60e,
-	0xf90188fe,
-	0xf990f980,
-	0xf9b0f9a0,
-	0xf9e0f9d0,
-	0xcf04bdf0,
-	0xabc4800a,
-	0x1d0bf404,
-	0x1900b7f1,
-	0xcf1cd7f0,
-	0xbfcf40be,
+	0x04bd0002,
+/* 0x0498: main */
+	0xf40031f4,
+	0xd7f00028,
+	0x3921f41c,
+	0xb0f401f4,
+	0x18f404e4,
+	0x0181fe1e,
+	0xbd0627f0,
+	0x0412fd20,
+	0xfd01e4b6,
+	0x18fe051e,
+	0x8d21f500,
+	0xd30ef405,
+/* 0x04c8: main_not_ctx_xfer */
+	0xf010ef94,
+	0x21f501f5,
+	0x0ef4037e,
+/* 0x04d5: ih */
+	0xfe80f9c6,
+	0x80f90188,
+	0xa0f990f9,
+	0xd0f9b0f9,
+	0xf0f9e0f9,
+	0xa7f104bd,
+	0xa3f00200,
+	0x00aacf00,
+	0xf404abc4,
+	0xd7f02c0b,
+	0x00e7f11c,
+	0x00e3f01a,
+	0xf100eecf,
+	0xf01900f7,
+	0xffcf00f3,
 	0x0421f400,
-	0x0400b0b7,
-	0xd001e7f0,
-/* 0x045e: ih_no_fifo */
-	0x0ad000be,
-	0xfcf0fc40,
-	0xfcd0fce0,
-	0xfca0fcb0,
-	0xfe80fc90,
-	0x80fc0088,
-	0xf80032f4,
-/* 0x0479: hub_barrier_done */
-	0x01f7f001,
-	0xbb040e98,
-	0xe7f104fe,
-	0xe3f09418,
-	0x8d21f440,
-/* 0x048e: ctx_redswitch */
-	0xe7f100f8,
-	0xe4b60614,
-	0x20f7f006,
-	0xf000efd0,
-/* 0x049e: ctx_redswitch_delay */
-	0xf2b608f7,
-	0xfd1bf401,
-	0x0a20f7f1,
-	0xf800efd0,
-/* 0x04ad: ctx_xfer */
-	0x0417f100,
-	0x0614b60a,
-	0xf4001fd0,
-	0x21f50711,
-/* 0x04be: ctx_xfer_not_load */
-	0x17f1048e,
-	0x13f04afc,
-	0x0c27f002,
-	0xf50012d0,
-	0xf1021521,
-	0xf047fc27,
-	0x20d00223,
-	0x012cf000,
-	0xd00320b6,
-	0xacf00012,
-	0x02a5f001,
-	0xf000b7f0,
-	0x0c9850b3,
-	0x0fc4b604,
-	0x9800bcbb,
-	0x0d98000c,
-	0x00e7f001,
-	0x016621f5,
+	0xf101e7f0,
+	0xf01d0007,
+	0x0ed00003,
+/* 0x0523: ih_no_fifo */
+	0xf104bd00,
+	0xf0010007,
+	0x0ad00003,
+	0xfc04bd00,
+	0xfce0fcf0,
+	0xfcb0fcd0,
+	0xfc90fca0,
+	0x0088fe80,
+	0x32f480fc,
+/* 0x0547: hub_barrier_done */
+	0xf001f800,
+	0x0e9801f7,
+	0x04febb04,
+	0xf102ffb9,
+	0xf09418e7,
+	0x21f440e3,
+/* 0x055f: ctx_redswitch */
+	0xf000f89d,
+	0x07f120f7,
+	0x03f08500,
+	0x000fd001,
+	0xe7f004bd,
+/* 0x0571: ctx_redswitch_delay */
+	0x01e2b608,
+	0xf1fd1bf4,
+	0xf10800f5,
+	0xf10200f5,
+	0xf0850007,
+	0x0fd00103,
+	0xf804bd00,
+/* 0x058d: ctx_xfer */
+	0x0007f100,
+	0x0203f081,
+	0xbd000fd0,
+	0x0711f404,
+	0x055f21f5,
+/* 0x05a0: ctx_xfer_not_load */
+	0x026a21f5,
+	0x07f124bd,
+	0x03f047fc,
+	0x0002d002,
+	0x2cf004bd,
+	0x0320b601,
+	0x4afc07f1,
+	0xd00203f0,
+	0x04bd0002,
 	0xf001acf0,
-	0xb7f104a5,
-	0xb3f04000,
+	0xb7f102a5,
+	0xb3f00000,
 	0x040c9850,
 	0xbb0fc4b6,
 	0x0c9800bc,
-	0x020d9801,
-	0xf1060f98,
-	0xf50800e7,
-	0xf5016621,
-	0xf4021521,
-	0x12f40601,
-/* 0x0535: ctx_xfer_post */
-	0xfc17f114,
-	0x0213f04a,
-	0xd00d27f0,
-	0x21f50012,
-/* 0x0546: ctx_xfer_done */
-	0x21f50215,
-	0x00f80479,
+	0x010d9800,
+	0xf500e7f0,
+	0xf0016f21,
+	0xa5f001ac,
+	0x00b7f104,
+	0x50b3f040,
+	0xb6040c98,
+	0xbcbb0fc4,
+	0x010c9800,
+	0x98020d98,
+	0xe7f1060f,
+	0x21f50800,
+	0x21f5016f,
+	0x01f4025e,
+	0x0712f406,
+/* 0x0618: ctx_xfer_post */
+	0x027f21f5,
+/* 0x061c: ctx_xfer_done */
+	0x054721f5,
+	0x000000f8,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
 	0x00000000,
 	0x00000000,
 	0x00000000,
diff --git a/drivers/gpu/drm/nouveau/core/engine/graph/fuc/gpcnvd7.fuc.h b/drivers/gpu/drm/nouveau/core/engine/graph/fuc/gpcnvd7.fuc.h
index dd346c2a16245..84dd32db28a02 100644
--- a/drivers/gpu/drm/nouveau/core/engine/graph/fuc/gpcnvd7.fuc.h
+++ b/drivers/gpu/drm/nouveau/core/engine/graph/fuc/gpcnvd7.fuc.h
@@ -41,14 +41,14 @@ uint32_t nvd7_grgpc_data[] = {
 };
 
 uint32_t nvd7_grgpc_code[] = {
-	0x03180ef5,
+	0x03a10ef5,
 /* 0x0004: queue_put */
 	0x9800d898,
 	0x86f001d9,
 	0x0489b808,
 	0xf00c1bf4,
 	0x21f502f7,
-	0x00f802fe,
+	0x00f8037e,
 /* 0x001c: queue_put_next */
 	0xb60798c4,
 	0x8dbb0384,
@@ -72,184 +72,214 @@ uint32_t nvd7_grgpc_code[] = {
 /* 0x0066: queue_get_done */
 	0x00f80132,
 /* 0x0068: nv_rd32 */
-	0x0728b7f1,
-	0xb906b4b6,
-	0xc9f002ec,
-	0x00bcd01f,
-/* 0x0078: nv_rd32_wait */
-	0xc800bccf,
-	0x1bf41fcc,
-	0x06a7f0fa,
-	0x010921f5,
-	0xf840bfcf,
-/* 0x008d: nv_wr32 */
-	0x28b7f100,
-	0x06b4b607,
-	0xb980bfd0,
-	0xc9f002ec,
-	0x1ec9f01f,
-/* 0x00a3: nv_wr32_wait */
-	0xcf00bcd0,
-	0xccc800bc,
-	0xfa1bf41f,
-/* 0x00ae: watchdog_reset */
-	0x87f100f8,
-	0x84b60430,
-	0x1ff9f006,
-	0xf8008fd0,
-/* 0x00bd: watchdog_clear */
-	0x3087f100,
-	0x0684b604,
-	0xf80080d0,
-/* 0x00c9: wait_donez */
-	0xf094bd00,
-	0x07f10099,
-	0x03f00f00,
-	0x0009d002,
-	0x07f104bd,
-	0x03f00600,
-	0x000ad002,
-/* 0x00e6: wait_donez_ne */
-	0x87f104bd,
-	0x83f00000,
-	0x0088cf01,
-	0xf4888aff,
-	0x94bdf31b,
-	0xf10099f0,
-	0xf0170007,
-	0x09d00203,
-	0xf804bd00,
-/* 0x0109: wait_doneo */
-	0xf094bd00,
+	0xf002ecb9,
+	0x07f11fc9,
+	0x03f0ca00,
+	0x000cd001,
+/* 0x007a: nv_rd32_wait */
+	0xc7f104bd,
+	0xc3f0ca00,
+	0x00cccf01,
+	0xf41fccc8,
+	0xa7f0f31b,
+	0x1021f506,
+	0x00f7f101,
+	0x01f3f0cb,
+	0xf800ffcf,
+/* 0x009d: nv_wr32 */
+	0x0007f100,
+	0x0103f0cc,
+	0xbd000fd0,
+	0x02ecb904,
+	0xf01fc9f0,
+	0x07f11ec9,
+	0x03f0ca00,
+	0x000cd001,
+/* 0x00be: nv_wr32_wait */
+	0xc7f104bd,
+	0xc3f0ca00,
+	0x00cccf01,
+	0xf41fccc8,
+	0x00f8f31b,
+/* 0x00d0: wait_donez */
+	0x99f094bd,
+	0x0007f100,
+	0x0203f00f,
+	0xbd0009d0,
+	0x0007f104,
+	0x0203f006,
+	0xbd000ad0,
+/* 0x00ed: wait_donez_ne */
+	0x0087f104,
+	0x0183f000,
+	0xff0088cf,
+	0x1bf4888a,
+	0xf094bdf3,
 	0x07f10099,
-	0x03f00f00,
+	0x03f01700,
 	0x0009d002,
-	0x87f104bd,
-	0x84b60818,
-	0x008ad006,
-/* 0x0124: wait_doneo_e */
-	0x040087f1,
-	0xcf0684b6,
-	0x8aff0088,
-	0xf30bf488,
+	0x00f804bd,
+/* 0x0110: wait_doneo */
 	0x99f094bd,
 	0x0007f100,
-	0x0203f017,
+	0x0203f00f,
 	0xbd0009d0,
-/* 0x0147: mmctx_size */
-	0xbd00f804,
-/* 0x0149: nv_mmctx_size_loop */
-	0x00e89894,
-	0xb61a85b6,
-	0x84b60180,
-	0x0098bb02,
-	0xb804e0b6,
-	0x1bf404ef,
-	0x029fb9eb,
-/* 0x0166: mmctx_xfer */
-	0x94bd00f8,
-	0xf10199f0,
-	0xf00f0007,
-	0x09d00203,
-	0xf104bd00,
-	0xb6071087,
-	0x94bd0684,
-	0xf405bbfd,
-	0x8bd0090b,
-	0x0099f000,
-/* 0x018c: mmctx_base_disabled */
-	0xf405eefd,
-	0x8ed00c0b,
-	0xc08fd080,
-/* 0x019b: mmctx_multi_disabled */
-	0xb70199f0,
-	0xc8010080,
+	0x0007f104,
+	0x0203f006,
+	0xbd000ad0,
+/* 0x012d: wait_doneo_e */
+	0x0087f104,
+	0x0183f000,
+	0xff0088cf,
+	0x0bf4888a,
+	0xf094bdf3,
+	0x07f10099,
+	0x03f01700,
+	0x0009d002,
+	0x00f804bd,
+/* 0x0150: mmctx_size */
+/* 0x0152: nv_mmctx_size_loop */
+	0xe89894bd,
+	0x1a85b600,
+	0xb60180b6,
+	0x98bb0284,
+	0x04e0b600,
+	0xf404efb8,
+	0x9fb9eb1b,
+/* 0x016f: mmctx_xfer */
+	0xbd00f802,
+	0x0199f094,
+	0x0f0007f1,
+	0xd00203f0,
+	0x04bd0009,
+	0xbbfd94bd,
+	0x120bf405,
+	0xc40007f1,
+	0xd00103f0,
+	0x04bd000b,
+/* 0x0197: mmctx_base_disabled */
+	0xfd0099f0,
+	0x0bf405ee,
+	0x0007f11e,
+	0x0103f0c6,
+	0xbd000ed0,
+	0x0007f104,
+	0x0103f0c7,
+	0xbd000fd0,
+	0x0199f004,
+/* 0x01b8: mmctx_multi_disabled */
+	0xb600abc8,
+	0xb9f010b4,
+	0x01aec80c,
+	0xfd11e4b6,
+	0x07f105be,
+	0x03f0c500,
+	0x000bd001,
+/* 0x01d6: mmctx_exec_loop */
+/* 0x01d6: mmctx_wait_free */
+	0xe7f104bd,
+	0xe3f0c500,
+	0x00eecf01,
+	0xf41fe4f0,
+	0xce98f30b,
+	0x05e9fd00,
+	0xc80007f1,
+	0xd00103f0,
+	0x04bd000e,
+	0xb804c0b6,
+	0x1bf404cd,
+	0x02abc8d8,
+/* 0x0207: mmctx_fini_wait */
+	0xf11f1bf4,
+	0xf0c500b7,
+	0xbbcf01b3,
+	0x1fb4f000,
+	0xf410b4b0,
+	0xa7f0f01b,
+	0xd021f402,
+/* 0x0223: mmctx_stop */
+	0xc82b0ef4,
 	0xb4b600ab,
 	0x0cb9f010,
-	0xb601aec8,
-	0xbefd11e4,
-	0x008bd005,
-/* 0x01b4: mmctx_exec_loop */
-/* 0x01b4: mmctx_wait_free */
-	0xf0008ecf,
-	0x0bf41fe4,
-	0x00ce98fa,
-	0xd005e9fd,
-	0xc0b6c08e,
-	0x04cdb804,
-	0xc8e81bf4,
-	0x1bf402ab,
-/* 0x01d5: mmctx_fini_wait */
-	0x008bcf18,
-	0xb01fb4f0,
-	0x1bf410b4,
-	0x02a7f0f7,
-	0xf4c921f4,
-/* 0x01ea: mmctx_stop */
-	0xabc81b0e,
-	0x10b4b600,
-	0xf00cb9f0,
-	0x8bd012b9,
-/* 0x01f9: mmctx_stop_wait */
-	0x008bcf00,
-	0xf412bbc8,
-/* 0x0202: mmctx_done */
-	0x94bdfa1b,
-	0xf10199f0,
-	0xf0170007,
-	0x09d00203,
-	0xf804bd00,
-/* 0x0215: strand_wait */
-	0xf0a0f900,
-	0x21f402a7,
-	0xf8a0fcc9,
-/* 0x0221: strand_pre */
-	0xfc87f100,
-	0x0283f04a,
-	0xd00c97f0,
-	0x21f50089,
-	0x00f80215,
-/* 0x0234: strand_post */
-	0x4afc87f1,
-	0xf00283f0,
-	0x89d00d97,
-	0x1521f500,
-/* 0x0247: strand_set */
-	0xf100f802,
-	0xf04ffca7,
-	0xaba202a3,
-	0xc7f00500,
-	0x00acd00f,
-	0xd00bc7f0,
-	0x21f500bc,
-	0xaed00215,
-	0x0ac7f000,
-	0xf500bcd0,
-	0xf8021521,
-/* 0x0271: strand_ctx_init */
-	0xf094bd00,
-	0x07f10399,
-	0x03f00f00,
+	0xf112b9f0,
+	0xf0c50007,
+	0x0bd00103,
+/* 0x023b: mmctx_stop_wait */
+	0xf104bd00,
+	0xf0c500b7,
+	0xbbcf01b3,
+	0x12bbc800,
+/* 0x024b: mmctx_done */
+	0xbdf31bf4,
+	0x0199f094,
+	0x170007f1,
+	0xd00203f0,
+	0x04bd0009,
+/* 0x025e: strand_wait */
+	0xa0f900f8,
+	0xf402a7f0,
+	0xa0fcd021,
+/* 0x026a: strand_pre */
+	0x97f000f8,
+	0xfc07f10c,
+	0x0203f04a,
+	0xbd0009d0,
+	0x5e21f504,
+/* 0x027f: strand_post */
+	0xf000f802,
+	0x07f10d97,
+	0x03f04afc,
 	0x0009d002,
 	0x21f504bd,
-	0xe7f00221,
-	0x4721f503,
-	0xfca7f102,
-	0x02a3f046,
-	0x0400aba0,
-	0xf040a0d0,
-	0xbcd001c7,
-	0x1521f500,
-	0x010c9202,
-	0xf000acd0,
-	0xbcd002c7,
-	0x1521f500,
-	0x3421f502,
-	0x8087f102,
-	0x0684b608,
-	0xb70089cf,
-	0x95220080,
-/* 0x02ca: ctx_init_strand_loop */
+	0x00f8025e,
+/* 0x0294: strand_set */
+	0xf10fc7f0,
+	0xf04ffc07,
+	0x0cd00203,
+	0xf004bd00,
+	0x07f10bc7,
+	0x03f04afc,
+	0x000cd002,
+	0x07f104bd,
+	0x03f04ffc,
+	0x000ed002,
+	0xc7f004bd,
+	0xfc07f10a,
+	0x0203f04a,
+	0xbd000cd0,
+	0x5e21f504,
+/* 0x02d3: strand_ctx_init */
+	0xbd00f802,
+	0x0399f094,
+	0x0f0007f1,
+	0xd00203f0,
+	0x04bd0009,
+	0x026a21f5,
+	0xf503e7f0,
+	0xbd029421,
+	0xfc07f1c4,
+	0x0203f047,
+	0xbd000cd0,
+	0x01c7f004,
+	0x4afc07f1,
+	0xd00203f0,
+	0x04bd000c,
+	0x025e21f5,
+	0xf1010c92,
+	0xf046fc07,
+	0x0cd00203,
+	0xf004bd00,
+	0x07f102c7,
+	0x03f04afc,
+	0x000cd002,
+	0x21f504bd,
+	0x21f5025e,
+	0x87f1027f,
+	0x83f04200,
+	0x0097f102,
+	0x0293f020,
+	0x950099cf,
+/* 0x034a: ctx_init_strand_loop */
 	0x8ed008fe,
 	0x408ed000,
 	0xb6808acf,
@@ -263,198 +293,230 @@ uint32_t nvd7_grgpc_code[] = {
 	0x170007f1,
 	0xd00203f0,
 	0x04bd0009,
-/* 0x02fe: error */
+/* 0x037e: error */
 	0xe0f900f8,
-	0x9814e7f1,
-	0xf440e3f0,
-	0xe0b78d21,
-	0xf7f0041c,
-	0x8d21f401,
-	0x00f8e0fc,
-/* 0x0318: init */
-	0x04fe04bd,
-	0x0017f100,
-	0x0227f012,
-	0xf10012d0,
-	0xfe047017,
-	0x17f10010,
-	0x10d00400,
-	0x0427f0c0,
-	0xf40012d0,
-	0x17f11031,
-	0x14b60608,
-	0x0012cf06,
+	0xf102ffb9,
+	0xf09814e7,
+	0x21f440e3,
+	0x01f7f09d,
+	0xf102ffb9,
+	0xf09c1ce7,
+	0x21f440e3,
+	0xf8e0fc9d,
+/* 0x03a1: init */
+	0xfe04bd00,
+	0x27f00004,
+	0x0007f102,
+	0x0003f012,
+	0xbd0002d0,
+	0x1f17f104,
+	0x0010fe05,
+	0x070007f1,
+	0xd00003f0,
+	0x04bd0000,
+	0xf10427f0,
+	0xf0040007,
+	0x02d00003,
+	0xf404bd00,
+	0x27f11031,
+	0x23f08200,
+	0x0022cf01,
 	0xf00137f0,
 	0x32bb1f24,
 	0x0132b604,
 	0x80050280,
-	0x10b70603,
-	0x12cf0400,
-	0x04028000,
-	0x0c30e7f1,
-	0xbd50e3f0,
-	0xbd34bd24,
-/* 0x0371: init_unk_loop */
-	0x6821f444,
-	0xf400f6b0,
-	0xf7f00f0b,
-	0x04f2bb01,
-	0xb6054ffd,
-/* 0x0386: init_unk_next */
-	0x20b60130,
-	0x04e0b601,
-	0xf40126b0,
-/* 0x0392: init_unk_done */
-	0x0380e21b,
-	0x08048007,
-	0x010027f1,
-	0xcf0223f0,
-	0x34bd0022,
-	0x070047f1,
-	0x950644b6,
-	0x45d00825,
-	0x4045d000,
-	0x98000e98,
-	0x21f5010f,
-	0x2fbb0147,
-	0x003fbb00,
-	0x98010e98,
-	0x21f5020f,
-	0x0e980147,
-	0x00effd05,
-	0xbb002ebb,
-	0x0e98003e,
-	0x030f9802,
-	0x014721f5,
-	0xfd070e98,
+	0x27f10603,
+	0x23f08600,
+	0x0022cf01,
+	0xf1040280,
+	0xf00c30e7,
+	0x24bd50e3,
+	0x44bd34bd,
+/* 0x0410: init_unk_loop */
+	0xb06821f4,
+	0x0bf400f6,
+	0x01f7f00f,
+	0xfd04f2bb,
+	0x30b6054f,
+/* 0x0425: init_unk_next */
+	0x0120b601,
+	0xb004e0b6,
+	0x1bf40126,
+/* 0x0431: init_unk_done */
+	0x070380e2,
+	0xf1080480,
+	0xf0010027,
+	0x22cf0223,
+	0x9534bd00,
+	0x07f10825,
+	0x03f0c000,
+	0x0005d001,
+	0x07f104bd,
+	0x03f0c100,
+	0x0005d001,
+	0x0e9804bd,
+	0x010f9800,
+	0x015021f5,
+	0xbb002fbb,
+	0x0e98003f,
+	0x020f9801,
+	0x015021f5,
+	0xfd050e98,
 	0x2ebb00ef,
 	0x003ebb00,
-	0x130040b7,
-	0xd00235b6,
-	0x25b60043,
-	0x0635b608,
-	0xb60120b6,
-	0x24b60130,
-	0x0834b608,
-	0xf5022fb9,
-	0xbb027121,
-	0x07f1003f,
-	0x03f00100,
-	0x0003d002,
-	0x24bd04bd,
-	0xf11f29f0,
-	0xf0080007,
-	0x02d00203,
-/* 0x0433: main */
+	0x98020e98,
+	0x21f5030f,
+	0x0e980150,
+	0x00effd07,
+	0xbb002ebb,
+	0x35b6003e,
+	0x0007f102,
+	0x0103f0d3,
+	0xbd0003d0,
+	0x0825b604,
+	0xb60635b6,
+	0x30b60120,
+	0x0824b601,
+	0xb90834b6,
+	0x21f5022f,
+	0x3fbb02d3,
+	0x0007f100,
+	0x0203f001,
+	0xbd0003d0,
+	0xf024bd04,
+	0x07f11f29,
+	0x03f00800,
+	0x0002d002,
+/* 0x04e2: main */
+	0x31f404bd,
+	0x0028f400,
+	0xf424d7f0,
+	0x01f43921,
+	0x04e4b0f4,
+	0xfe1e18f4,
+	0x27f00181,
+	0xfd20bd06,
+	0xe4b60412,
+	0x051efd01,
+	0xf50018fe,
+	0xf405d721,
+/* 0x0512: main_not_ctx_xfer */
+	0xef94d30e,
+	0x01f5f010,
+	0x037e21f5,
+/* 0x051f: ih */
+	0xf9c60ef4,
+	0x0188fe80,
+	0x90f980f9,
+	0xb0f9a0f9,
+	0xe0f9d0f9,
+	0x04bdf0f9,
+	0x0200a7f1,
+	0xcf00a3f0,
+	0xabc400aa,
+	0x2c0bf404,
+	0xf124d7f0,
+	0xf01a00e7,
+	0xeecf00e3,
+	0x00f7f100,
+	0x00f3f019,
+	0xf400ffcf,
+	0xe7f00421,
+	0x0007f101,
+	0x0003f01d,
+	0xbd000ed0,
+/* 0x056d: ih_no_fifo */
+	0x0007f104,
+	0x0003f001,
+	0xbd000ad0,
+	0xfcf0fc04,
+	0xfcd0fce0,
+	0xfca0fcb0,
+	0xfe80fc90,
+	0x80fc0088,
+	0xf80032f4,
+/* 0x0591: hub_barrier_done */
+	0x01f7f001,
+	0xbb040e98,
+	0xffb904fe,
+	0x18e7f102,
+	0x40e3f094,
+	0xf89d21f4,
+/* 0x05a9: ctx_redswitch */
+	0x20f7f000,
+	0x850007f1,
+	0xd00103f0,
+	0x04bd000f,
+/* 0x05bb: ctx_redswitch_delay */
+	0xb608e7f0,
+	0x1bf401e2,
+	0x00f5f1fd,
+	0x00f5f108,
+	0x0007f102,
+	0x0103f085,
+	0xbd000fd0,
+/* 0x05d7: ctx_xfer */
+	0xf100f804,
+	0xf0810007,
+	0x0fd00203,
 	0xf404bd00,
-	0x28f40031,
-	0x24d7f000,
-	0xf43921f4,
-	0xe4b0f401,
-	0x1e18f404,
-	0xf00181fe,
-	0x20bd0627,
-	0xb60412fd,
-	0x1efd01e4,
-	0x0018fe05,
-	0x04f721f5,
-/* 0x0463: main_not_ctx_xfer */
-	0x94d30ef4,
-	0xf5f010ef,
-	0xfe21f501,
-	0xc60ef402,
-/* 0x0470: ih */
-	0x88fe80f9,
-	0xf980f901,
-	0xf9a0f990,
-	0xf9d0f9b0,
-	0xbdf0f9e0,
-	0x800acf04,
-	0xf404abc4,
-	0xb7f11d0b,
-	0xd7f01900,
-	0x40becf24,
-	0xf400bfcf,
-	0xb0b70421,
-	0xe7f00400,
-	0x00bed001,
-/* 0x04a8: ih_no_fifo */
-	0xfc400ad0,
-	0xfce0fcf0,
-	0xfcb0fcd0,
-	0xfc90fca0,
-	0x0088fe80,
-	0x32f480fc,
-/* 0x04c3: hub_barrier_done */
-	0xf001f800,
-	0x0e9801f7,
-	0x04febb04,
-	0x9418e7f1,
-	0xf440e3f0,
-	0x00f88d21,
-/* 0x04d8: ctx_redswitch */
-	0x0614e7f1,
-	0xf006e4b6,
-	0xefd020f7,
-	0x08f7f000,
-/* 0x04e8: ctx_redswitch_delay */
-	0xf401f2b6,
-	0xf7f1fd1b,
-	0xefd00a20,
-/* 0x04f7: ctx_xfer */
-	0xf100f800,
-	0xb60a0417,
-	0x1fd00614,
-	0x0711f400,
-	0x04d821f5,
-/* 0x0508: ctx_xfer_not_load */
-	0x4afc17f1,
-	0xf00213f0,
-	0x12d00c27,
-	0x1521f500,
-	0xfc27f102,
-	0x0223f047,
-	0xf00020d0,
-	0x20b6012c,
-	0x0012d003,
-	0xf001acf0,
-	0xb7f002a5,
-	0x50b3f000,
-	0xb6040c98,
-	0xbcbb0fc4,
-	0x000c9800,
-	0xf0010d98,
-	0x21f500e7,
-	0xacf00166,
-	0x00b7f101,
-	0x50b3f040,
-	0xb6040c98,
-	0xbcbb0fc4,
-	0x010c9800,
-	0x98020d98,
-	0xe7f1060f,
-	0x21f50800,
-	0xacf00166,
-	0x04a5f001,
-	0x3000b7f1,
+	0x21f50711,
+/* 0x05ea: ctx_xfer_not_load */
+	0x21f505a9,
+	0x24bd026a,
+	0x47fc07f1,
+	0xd00203f0,
+	0x04bd0002,
+	0xb6012cf0,
+	0x07f10320,
+	0x03f04afc,
+	0x0002d002,
+	0xacf004bd,
+	0x02a5f001,
+	0x0000b7f1,
 	0x9850b3f0,
 	0xc4b6040c,
 	0x00bcbb0f,
-	0x98020c98,
-	0x0f98030d,
-	0x00e7f108,
-	0x6621f502,
-	0x1521f501,
-	0x0601f402,
-/* 0x05a3: ctx_xfer_post */
-	0xf11412f4,
-	0xf04afc17,
-	0x27f00213,
-	0x0012d00d,
-	0x021521f5,
-/* 0x05b4: ctx_xfer_done */
-	0x04c321f5,
-	0x000000f8,
+	0x98000c98,
+	0xe7f0010d,
+	0x6f21f500,
+	0x01acf001,
+	0x4000b7f1,
+	0x9850b3f0,
+	0xc4b6040c,
+	0x00bcbb0f,
+	0x98010c98,
+	0x0f98020d,
+	0x00e7f106,
+	0x6f21f508,
+	0x01acf001,
+	0xf104a5f0,
+	0xf03000b7,
+	0x0c9850b3,
+	0x0fc4b604,
+	0x9800bcbb,
+	0x0d98020c,
+	0x080f9803,
+	0x0200e7f1,
+	0x016f21f5,
+	0x025e21f5,
+	0xf40601f4,
+/* 0x0686: ctx_xfer_post */
+	0x21f50712,
+/* 0x068a: ctx_xfer_done */
+	0x21f5027f,
+	0x00f80591,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
 	0x00000000,
 	0x00000000,
 	0x00000000,
diff --git a/drivers/gpu/drm/nouveau/core/engine/graph/fuc/gpcnve0.fuc.h b/drivers/gpu/drm/nouveau/core/engine/graph/fuc/gpcnve0.fuc.h
index 7ff5ef6b08048..b6da800ee9c2d 100644
--- a/drivers/gpu/drm/nouveau/core/engine/graph/fuc/gpcnve0.fuc.h
+++ b/drivers/gpu/drm/nouveau/core/engine/graph/fuc/gpcnve0.fuc.h
@@ -41,14 +41,14 @@ uint32_t nve0_grgpc_data[] = {
 };
 
 uint32_t nve0_grgpc_code[] = {
-	0x03180ef5,
+	0x03a10ef5,
 /* 0x0004: queue_put */
 	0x9800d898,
 	0x86f001d9,
 	0x0489b808,
 	0xf00c1bf4,
 	0x21f502f7,
-	0x00f802fe,
+	0x00f8037e,
 /* 0x001c: queue_put_next */
 	0xb60798c4,
 	0x8dbb0384,
@@ -72,184 +72,214 @@ uint32_t nve0_grgpc_code[] = {
 /* 0x0066: queue_get_done */
 	0x00f80132,
 /* 0x0068: nv_rd32 */
-	0x0728b7f1,
-	0xb906b4b6,
-	0xc9f002ec,
-	0x00bcd01f,
-/* 0x0078: nv_rd32_wait */
-	0xc800bccf,
-	0x1bf41fcc,
-	0x06a7f0fa,
-	0x010921f5,
-	0xf840bfcf,
-/* 0x008d: nv_wr32 */
-	0x28b7f100,
-	0x06b4b607,
-	0xb980bfd0,
-	0xc9f002ec,
-	0x1ec9f01f,
-/* 0x00a3: nv_wr32_wait */
-	0xcf00bcd0,
-	0xccc800bc,
-	0xfa1bf41f,
-/* 0x00ae: watchdog_reset */
-	0x87f100f8,
-	0x84b60430,
-	0x1ff9f006,
-	0xf8008fd0,
-/* 0x00bd: watchdog_clear */
-	0x3087f100,
-	0x0684b604,
-	0xf80080d0,
-/* 0x00c9: wait_donez */
-	0xf094bd00,
-	0x07f10099,
-	0x03f00f00,
-	0x0009d002,
-	0x07f104bd,
-	0x03f00600,
-	0x000ad002,
-/* 0x00e6: wait_donez_ne */
-	0x87f104bd,
-	0x83f00000,
-	0x0088cf01,
-	0xf4888aff,
-	0x94bdf31b,
-	0xf10099f0,
-	0xf0170007,
-	0x09d00203,
-	0xf804bd00,
-/* 0x0109: wait_doneo */
-	0xf094bd00,
+	0xf002ecb9,
+	0x07f11fc9,
+	0x03f0ca00,
+	0x000cd001,
+/* 0x007a: nv_rd32_wait */
+	0xc7f104bd,
+	0xc3f0ca00,
+	0x00cccf01,
+	0xf41fccc8,
+	0xa7f0f31b,
+	0x1021f506,
+	0x00f7f101,
+	0x01f3f0cb,
+	0xf800ffcf,
+/* 0x009d: nv_wr32 */
+	0x0007f100,
+	0x0103f0cc,
+	0xbd000fd0,
+	0x02ecb904,
+	0xf01fc9f0,
+	0x07f11ec9,
+	0x03f0ca00,
+	0x000cd001,
+/* 0x00be: nv_wr32_wait */
+	0xc7f104bd,
+	0xc3f0ca00,
+	0x00cccf01,
+	0xf41fccc8,
+	0x00f8f31b,
+/* 0x00d0: wait_donez */
+	0x99f094bd,
+	0x0007f100,
+	0x0203f00f,
+	0xbd0009d0,
+	0x0007f104,
+	0x0203f006,
+	0xbd000ad0,
+/* 0x00ed: wait_donez_ne */
+	0x0087f104,
+	0x0183f000,
+	0xff0088cf,
+	0x1bf4888a,
+	0xf094bdf3,
 	0x07f10099,
-	0x03f00f00,
+	0x03f01700,
 	0x0009d002,
-	0x87f104bd,
-	0x84b60818,
-	0x008ad006,
-/* 0x0124: wait_doneo_e */
-	0x040087f1,
-	0xcf0684b6,
-	0x8aff0088,
-	0xf30bf488,
+	0x00f804bd,
+/* 0x0110: wait_doneo */
 	0x99f094bd,
 	0x0007f100,
-	0x0203f017,
+	0x0203f00f,
 	0xbd0009d0,
-/* 0x0147: mmctx_size */
-	0xbd00f804,
-/* 0x0149: nv_mmctx_size_loop */
-	0x00e89894,
-	0xb61a85b6,
-	0x84b60180,
-	0x0098bb02,
-	0xb804e0b6,
-	0x1bf404ef,
-	0x029fb9eb,
-/* 0x0166: mmctx_xfer */
-	0x94bd00f8,
-	0xf10199f0,
-	0xf00f0007,
-	0x09d00203,
-	0xf104bd00,
-	0xb6071087,
-	0x94bd0684,
-	0xf405bbfd,
-	0x8bd0090b,
-	0x0099f000,
-/* 0x018c: mmctx_base_disabled */
-	0xf405eefd,
-	0x8ed00c0b,
-	0xc08fd080,
-/* 0x019b: mmctx_multi_disabled */
-	0xb70199f0,
-	0xc8010080,
+	0x0007f104,
+	0x0203f006,
+	0xbd000ad0,
+/* 0x012d: wait_doneo_e */
+	0x0087f104,
+	0x0183f000,
+	0xff0088cf,
+	0x0bf4888a,
+	0xf094bdf3,
+	0x07f10099,
+	0x03f01700,
+	0x0009d002,
+	0x00f804bd,
+/* 0x0150: mmctx_size */
+/* 0x0152: nv_mmctx_size_loop */
+	0xe89894bd,
+	0x1a85b600,
+	0xb60180b6,
+	0x98bb0284,
+	0x04e0b600,
+	0xf404efb8,
+	0x9fb9eb1b,
+/* 0x016f: mmctx_xfer */
+	0xbd00f802,
+	0x0199f094,
+	0x0f0007f1,
+	0xd00203f0,
+	0x04bd0009,
+	0xbbfd94bd,
+	0x120bf405,
+	0xc40007f1,
+	0xd00103f0,
+	0x04bd000b,
+/* 0x0197: mmctx_base_disabled */
+	0xfd0099f0,
+	0x0bf405ee,
+	0x0007f11e,
+	0x0103f0c6,
+	0xbd000ed0,
+	0x0007f104,
+	0x0103f0c7,
+	0xbd000fd0,
+	0x0199f004,
+/* 0x01b8: mmctx_multi_disabled */
+	0xb600abc8,
+	0xb9f010b4,
+	0x01aec80c,
+	0xfd11e4b6,
+	0x07f105be,
+	0x03f0c500,
+	0x000bd001,
+/* 0x01d6: mmctx_exec_loop */
+/* 0x01d6: mmctx_wait_free */
+	0xe7f104bd,
+	0xe3f0c500,
+	0x00eecf01,
+	0xf41fe4f0,
+	0xce98f30b,
+	0x05e9fd00,
+	0xc80007f1,
+	0xd00103f0,
+	0x04bd000e,
+	0xb804c0b6,
+	0x1bf404cd,
+	0x02abc8d8,
+/* 0x0207: mmctx_fini_wait */
+	0xf11f1bf4,
+	0xf0c500b7,
+	0xbbcf01b3,
+	0x1fb4f000,
+	0xf410b4b0,
+	0xa7f0f01b,
+	0xd021f402,
+/* 0x0223: mmctx_stop */
+	0xc82b0ef4,
 	0xb4b600ab,
 	0x0cb9f010,
-	0xb601aec8,
-	0xbefd11e4,
-	0x008bd005,
-/* 0x01b4: mmctx_exec_loop */
-/* 0x01b4: mmctx_wait_free */
-	0xf0008ecf,
-	0x0bf41fe4,
-	0x00ce98fa,
-	0xd005e9fd,
-	0xc0b6c08e,
-	0x04cdb804,
-	0xc8e81bf4,
-	0x1bf402ab,
-/* 0x01d5: mmctx_fini_wait */
-	0x008bcf18,
-	0xb01fb4f0,
-	0x1bf410b4,
-	0x02a7f0f7,
-	0xf4c921f4,
-/* 0x01ea: mmctx_stop */
-	0xabc81b0e,
-	0x10b4b600,
-	0xf00cb9f0,
-	0x8bd012b9,
-/* 0x01f9: mmctx_stop_wait */
-	0x008bcf00,
-	0xf412bbc8,
-/* 0x0202: mmctx_done */
-	0x94bdfa1b,
-	0xf10199f0,
-	0xf0170007,
-	0x09d00203,
-	0xf804bd00,
-/* 0x0215: strand_wait */
-	0xf0a0f900,
-	0x21f402a7,
-	0xf8a0fcc9,
-/* 0x0221: strand_pre */
-	0xfc87f100,
-	0x0283f04a,
-	0xd00c97f0,
-	0x21f50089,
-	0x00f80215,
-/* 0x0234: strand_post */
-	0x4afc87f1,
-	0xf00283f0,
-	0x89d00d97,
-	0x1521f500,
-/* 0x0247: strand_set */
-	0xf100f802,
-	0xf04ffca7,
-	0xaba202a3,
-	0xc7f00500,
-	0x00acd00f,
-	0xd00bc7f0,
-	0x21f500bc,
-	0xaed00215,
-	0x0ac7f000,
-	0xf500bcd0,
-	0xf8021521,
-/* 0x0271: strand_ctx_init */
-	0xf094bd00,
-	0x07f10399,
-	0x03f00f00,
+	0xf112b9f0,
+	0xf0c50007,
+	0x0bd00103,
+/* 0x023b: mmctx_stop_wait */
+	0xf104bd00,
+	0xf0c500b7,
+	0xbbcf01b3,
+	0x12bbc800,
+/* 0x024b: mmctx_done */
+	0xbdf31bf4,
+	0x0199f094,
+	0x170007f1,
+	0xd00203f0,
+	0x04bd0009,
+/* 0x025e: strand_wait */
+	0xa0f900f8,
+	0xf402a7f0,
+	0xa0fcd021,
+/* 0x026a: strand_pre */
+	0x97f000f8,
+	0xfc07f10c,
+	0x0203f04a,
+	0xbd0009d0,
+	0x5e21f504,
+/* 0x027f: strand_post */
+	0xf000f802,
+	0x07f10d97,
+	0x03f04afc,
 	0x0009d002,
 	0x21f504bd,
-	0xe7f00221,
-	0x4721f503,
-	0xfca7f102,
-	0x02a3f046,
-	0x0400aba0,
-	0xf040a0d0,
-	0xbcd001c7,
-	0x1521f500,
-	0x010c9202,
-	0xf000acd0,
-	0xbcd002c7,
-	0x1521f500,
-	0x3421f502,
-	0x8087f102,
-	0x0684b608,
-	0xb70089cf,
-	0x95220080,
-/* 0x02ca: ctx_init_strand_loop */
+	0x00f8025e,
+/* 0x0294: strand_set */
+	0xf10fc7f0,
+	0xf04ffc07,
+	0x0cd00203,
+	0xf004bd00,
+	0x07f10bc7,
+	0x03f04afc,
+	0x000cd002,
+	0x07f104bd,
+	0x03f04ffc,
+	0x000ed002,
+	0xc7f004bd,
+	0xfc07f10a,
+	0x0203f04a,
+	0xbd000cd0,
+	0x5e21f504,
+/* 0x02d3: strand_ctx_init */
+	0xbd00f802,
+	0x0399f094,
+	0x0f0007f1,
+	0xd00203f0,
+	0x04bd0009,
+	0x026a21f5,
+	0xf503e7f0,
+	0xbd029421,
+	0xfc07f1c4,
+	0x0203f047,
+	0xbd000cd0,
+	0x01c7f004,
+	0x4afc07f1,
+	0xd00203f0,
+	0x04bd000c,
+	0x025e21f5,
+	0xf1010c92,
+	0xf046fc07,
+	0x0cd00203,
+	0xf004bd00,
+	0x07f102c7,
+	0x03f04afc,
+	0x000cd002,
+	0x21f504bd,
+	0x21f5025e,
+	0x87f1027f,
+	0x83f04200,
+	0x0097f102,
+	0x0293f020,
+	0x950099cf,
+/* 0x034a: ctx_init_strand_loop */
 	0x8ed008fe,
 	0x408ed000,
 	0xb6808acf,
@@ -263,198 +293,230 @@ uint32_t nve0_grgpc_code[] = {
 	0x170007f1,
 	0xd00203f0,
 	0x04bd0009,
-/* 0x02fe: error */
+/* 0x037e: error */
 	0xe0f900f8,
-	0x9814e7f1,
-	0xf440e3f0,
-	0xe0b78d21,
-	0xf7f0041c,
-	0x8d21f401,
-	0x00f8e0fc,
-/* 0x0318: init */
-	0x04fe04bd,
-	0x0017f100,
-	0x0227f012,
-	0xf10012d0,
-	0xfe047017,
-	0x17f10010,
-	0x10d00400,
-	0x0427f0c0,
-	0xf40012d0,
-	0x17f11031,
-	0x14b60608,
-	0x0012cf06,
+	0xf102ffb9,
+	0xf09814e7,
+	0x21f440e3,
+	0x01f7f09d,
+	0xf102ffb9,
+	0xf09c1ce7,
+	0x21f440e3,
+	0xf8e0fc9d,
+/* 0x03a1: init */
+	0xfe04bd00,
+	0x27f00004,
+	0x0007f102,
+	0x0003f012,
+	0xbd0002d0,
+	0x1f17f104,
+	0x0010fe05,
+	0x070007f1,
+	0xd00003f0,
+	0x04bd0000,
+	0xf10427f0,
+	0xf0040007,
+	0x02d00003,
+	0xf404bd00,
+	0x27f11031,
+	0x23f08200,
+	0x0022cf01,
 	0xf00137f0,
 	0x32bb1f24,
 	0x0132b604,
 	0x80050280,
-	0x10b70603,
-	0x12cf0400,
-	0x04028000,
-	0x0c30e7f1,
-	0xbd50e3f0,
-	0xbd34bd24,
-/* 0x0371: init_unk_loop */
-	0x6821f444,
-	0xf400f6b0,
-	0xf7f00f0b,
-	0x04f2bb01,
-	0xb6054ffd,
-/* 0x0386: init_unk_next */
-	0x20b60130,
-	0x04e0b601,
-	0xf40126b0,
-/* 0x0392: init_unk_done */
-	0x0380e21b,
-	0x08048007,
-	0x010027f1,
-	0xcf0223f0,
-	0x34bd0022,
-	0x070047f1,
-	0x950644b6,
-	0x45d00825,
-	0x4045d000,
-	0x98000e98,
-	0x21f5010f,
-	0x2fbb0147,
-	0x003fbb00,
-	0x98010e98,
-	0x21f5020f,
-	0x0e980147,
-	0x00effd05,
-	0xbb002ebb,
-	0x0e98003e,
-	0x030f9802,
-	0x014721f5,
-	0xfd070e98,
+	0x27f10603,
+	0x23f08600,
+	0x0022cf01,
+	0xf1040280,
+	0xf00c30e7,
+	0x24bd50e3,
+	0x44bd34bd,
+/* 0x0410: init_unk_loop */
+	0xb06821f4,
+	0x0bf400f6,
+	0x01f7f00f,
+	0xfd04f2bb,
+	0x30b6054f,
+/* 0x0425: init_unk_next */
+	0x0120b601,
+	0xb004e0b6,
+	0x1bf40126,
+/* 0x0431: init_unk_done */
+	0x070380e2,
+	0xf1080480,
+	0xf0010027,
+	0x22cf0223,
+	0x9534bd00,
+	0x07f10825,
+	0x03f0c000,
+	0x0005d001,
+	0x07f104bd,
+	0x03f0c100,
+	0x0005d001,
+	0x0e9804bd,
+	0x010f9800,
+	0x015021f5,
+	0xbb002fbb,
+	0x0e98003f,
+	0x020f9801,
+	0x015021f5,
+	0xfd050e98,
 	0x2ebb00ef,
 	0x003ebb00,
-	0x130040b7,
-	0xd00235b6,
-	0x25b60043,
-	0x0635b608,
-	0xb60120b6,
-	0x24b60130,
-	0x0834b608,
-	0xf5022fb9,
-	0xbb027121,
-	0x07f1003f,
-	0x03f00100,
-	0x0003d002,
-	0x24bd04bd,
-	0xf11f29f0,
-	0xf0080007,
-	0x02d00203,
-/* 0x0433: main */
+	0x98020e98,
+	0x21f5030f,
+	0x0e980150,
+	0x00effd07,
+	0xbb002ebb,
+	0x35b6003e,
+	0x0007f102,
+	0x0103f0d3,
+	0xbd0003d0,
+	0x0825b604,
+	0xb60635b6,
+	0x30b60120,
+	0x0824b601,
+	0xb90834b6,
+	0x21f5022f,
+	0x3fbb02d3,
+	0x0007f100,
+	0x0203f001,
+	0xbd0003d0,
+	0xf024bd04,
+	0x07f11f29,
+	0x03f00800,
+	0x0002d002,
+/* 0x04e2: main */
+	0x31f404bd,
+	0x0028f400,
+	0xf424d7f0,
+	0x01f43921,
+	0x04e4b0f4,
+	0xfe1e18f4,
+	0x27f00181,
+	0xfd20bd06,
+	0xe4b60412,
+	0x051efd01,
+	0xf50018fe,
+	0xf405d721,
+/* 0x0512: main_not_ctx_xfer */
+	0xef94d30e,
+	0x01f5f010,
+	0x037e21f5,
+/* 0x051f: ih */
+	0xf9c60ef4,
+	0x0188fe80,
+	0x90f980f9,
+	0xb0f9a0f9,
+	0xe0f9d0f9,
+	0x04bdf0f9,
+	0x0200a7f1,
+	0xcf00a3f0,
+	0xabc400aa,
+	0x2c0bf404,
+	0xf124d7f0,
+	0xf01a00e7,
+	0xeecf00e3,
+	0x00f7f100,
+	0x00f3f019,
+	0xf400ffcf,
+	0xe7f00421,
+	0x0007f101,
+	0x0003f01d,
+	0xbd000ed0,
+/* 0x056d: ih_no_fifo */
+	0x0007f104,
+	0x0003f001,
+	0xbd000ad0,
+	0xfcf0fc04,
+	0xfcd0fce0,
+	0xfca0fcb0,
+	0xfe80fc90,
+	0x80fc0088,
+	0xf80032f4,
+/* 0x0591: hub_barrier_done */
+	0x01f7f001,
+	0xbb040e98,
+	0xffb904fe,
+	0x18e7f102,
+	0x40e3f094,
+	0xf89d21f4,
+/* 0x05a9: ctx_redswitch */
+	0x20f7f000,
+	0x850007f1,
+	0xd00103f0,
+	0x04bd000f,
+/* 0x05bb: ctx_redswitch_delay */
+	0xb608e7f0,
+	0x1bf401e2,
+	0x00f5f1fd,
+	0x00f5f108,
+	0x0007f102,
+	0x0103f085,
+	0xbd000fd0,
+/* 0x05d7: ctx_xfer */
+	0xf100f804,
+	0xf0810007,
+	0x0fd00203,
 	0xf404bd00,
-	0x28f40031,
-	0x24d7f000,
-	0xf43921f4,
-	0xe4b0f401,
-	0x1e18f404,
-	0xf00181fe,
-	0x20bd0627,
-	0xb60412fd,
-	0x1efd01e4,
-	0x0018fe05,
-	0x04f721f5,
-/* 0x0463: main_not_ctx_xfer */
-	0x94d30ef4,
-	0xf5f010ef,
-	0xfe21f501,
-	0xc60ef402,
-/* 0x0470: ih */
-	0x88fe80f9,
-	0xf980f901,
-	0xf9a0f990,
-	0xf9d0f9b0,
-	0xbdf0f9e0,
-	0x800acf04,
-	0xf404abc4,
-	0xb7f11d0b,
-	0xd7f01900,
-	0x40becf24,
-	0xf400bfcf,
-	0xb0b70421,
-	0xe7f00400,
-	0x00bed001,
-/* 0x04a8: ih_no_fifo */
-	0xfc400ad0,
-	0xfce0fcf0,
-	0xfcb0fcd0,
-	0xfc90fca0,
-	0x0088fe80,
-	0x32f480fc,
-/* 0x04c3: hub_barrier_done */
-	0xf001f800,
-	0x0e9801f7,
-	0x04febb04,
-	0x9418e7f1,
-	0xf440e3f0,
-	0x00f88d21,
-/* 0x04d8: ctx_redswitch */
-	0x0614e7f1,
-	0xf006e4b6,
-	0xefd020f7,
-	0x08f7f000,
-/* 0x04e8: ctx_redswitch_delay */
-	0xf401f2b6,
-	0xf7f1fd1b,
-	0xefd00a20,
-/* 0x04f7: ctx_xfer */
-	0xf100f800,
-	0xb60a0417,
-	0x1fd00614,
-	0x0711f400,
-	0x04d821f5,
-/* 0x0508: ctx_xfer_not_load */
-	0x4afc17f1,
-	0xf00213f0,
-	0x12d00c27,
-	0x1521f500,
-	0xfc27f102,
-	0x0223f047,
-	0xf00020d0,
-	0x20b6012c,
-	0x0012d003,
-	0xf001acf0,
-	0xb7f002a5,
-	0x50b3f000,
-	0xb6040c98,
-	0xbcbb0fc4,
-	0x000c9800,
-	0xf0010d98,
-	0x21f500e7,
-	0xacf00166,
-	0x00b7f101,
-	0x50b3f040,
-	0xb6040c98,
-	0xbcbb0fc4,
-	0x010c9800,
-	0x98020d98,
-	0xe7f1060f,
-	0x21f50800,
-	0xacf00166,
-	0x04a5f001,
-	0x3000b7f1,
+	0x21f50711,
+/* 0x05ea: ctx_xfer_not_load */
+	0x21f505a9,
+	0x24bd026a,
+	0x47fc07f1,
+	0xd00203f0,
+	0x04bd0002,
+	0xb6012cf0,
+	0x07f10320,
+	0x03f04afc,
+	0x0002d002,
+	0xacf004bd,
+	0x02a5f001,
+	0x0000b7f1,
 	0x9850b3f0,
 	0xc4b6040c,
 	0x00bcbb0f,
-	0x98020c98,
-	0x0f98030d,
-	0x00e7f108,
-	0x6621f502,
-	0x1521f501,
-	0x0601f402,
-/* 0x05a3: ctx_xfer_post */
-	0xf11412f4,
-	0xf04afc17,
-	0x27f00213,
-	0x0012d00d,
-	0x021521f5,
-/* 0x05b4: ctx_xfer_done */
-	0x04c321f5,
-	0x000000f8,
+	0x98000c98,
+	0xe7f0010d,
+	0x6f21f500,
+	0x01acf001,
+	0x4000b7f1,
+	0x9850b3f0,
+	0xc4b6040c,
+	0x00bcbb0f,
+	0x98010c98,
+	0x0f98020d,
+	0x00e7f106,
+	0x6f21f508,
+	0x01acf001,
+	0xf104a5f0,
+	0xf03000b7,
+	0x0c9850b3,
+	0x0fc4b604,
+	0x9800bcbb,
+	0x0d98020c,
+	0x080f9803,
+	0x0200e7f1,
+	0x016f21f5,
+	0x025e21f5,
+	0xf40601f4,
+/* 0x0686: ctx_xfer_post */
+	0x21f50712,
+/* 0x068a: ctx_xfer_done */
+	0x21f5027f,
+	0x00f80591,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
 	0x00000000,
 	0x00000000,
 	0x00000000,
diff --git a/drivers/gpu/drm/nouveau/core/engine/graph/fuc/gpcnvf0.fuc.h b/drivers/gpu/drm/nouveau/core/engine/graph/fuc/gpcnvf0.fuc.h
index f870507be8801..6316ebaf5d9a5 100644
--- a/drivers/gpu/drm/nouveau/core/engine/graph/fuc/gpcnvf0.fuc.h
+++ b/drivers/gpu/drm/nouveau/core/engine/graph/fuc/gpcnvf0.fuc.h
@@ -41,14 +41,14 @@ uint32_t nvf0_grgpc_data[] = {
 };
 
 uint32_t nvf0_grgpc_code[] = {
-	0x03180ef5,
+	0x03a10ef5,
 /* 0x0004: queue_put */
 	0x9800d898,
 	0x86f001d9,
 	0x0489b808,
 	0xf00c1bf4,
 	0x21f502f7,
-	0x00f802fe,
+	0x00f8037e,
 /* 0x001c: queue_put_next */
 	0xb60798c4,
 	0x8dbb0384,
@@ -72,184 +72,214 @@ uint32_t nvf0_grgpc_code[] = {
 /* 0x0066: queue_get_done */
 	0x00f80132,
 /* 0x0068: nv_rd32 */
-	0x0728b7f1,
-	0xb906b4b6,
-	0xc9f002ec,
-	0x00bcd01f,
-/* 0x0078: nv_rd32_wait */
-	0xc800bccf,
-	0x1bf41fcc,
-	0x06a7f0fa,
-	0x010921f5,
-	0xf840bfcf,
-/* 0x008d: nv_wr32 */
-	0x28b7f100,
-	0x06b4b607,
-	0xb980bfd0,
-	0xc9f002ec,
-	0x1ec9f01f,
-/* 0x00a3: nv_wr32_wait */
-	0xcf00bcd0,
-	0xccc800bc,
-	0xfa1bf41f,
-/* 0x00ae: watchdog_reset */
-	0x87f100f8,
-	0x84b60430,
-	0x1ff9f006,
-	0xf8008fd0,
-/* 0x00bd: watchdog_clear */
-	0x3087f100,
-	0x0684b604,
-	0xf80080d0,
-/* 0x00c9: wait_donez */
-	0xf094bd00,
-	0x07f10099,
-	0x03f03700,
-	0x0009d002,
-	0x07f104bd,
-	0x03f00600,
-	0x000ad002,
-/* 0x00e6: wait_donez_ne */
-	0x87f104bd,
-	0x83f00000,
-	0x0088cf01,
-	0xf4888aff,
-	0x94bdf31b,
-	0xf10099f0,
-	0xf0170007,
-	0x09d00203,
-	0xf804bd00,
-/* 0x0109: wait_doneo */
-	0xf094bd00,
+	0xf002ecb9,
+	0x07f11fc9,
+	0x03f0ca00,
+	0x000cd001,
+/* 0x007a: nv_rd32_wait */
+	0xc7f104bd,
+	0xc3f0ca00,
+	0x00cccf01,
+	0xf41fccc8,
+	0xa7f0f31b,
+	0x1021f506,
+	0x00f7f101,
+	0x01f3f0cb,
+	0xf800ffcf,
+/* 0x009d: nv_wr32 */
+	0x0007f100,
+	0x0103f0cc,
+	0xbd000fd0,
+	0x02ecb904,
+	0xf01fc9f0,
+	0x07f11ec9,
+	0x03f0ca00,
+	0x000cd001,
+/* 0x00be: nv_wr32_wait */
+	0xc7f104bd,
+	0xc3f0ca00,
+	0x00cccf01,
+	0xf41fccc8,
+	0x00f8f31b,
+/* 0x00d0: wait_donez */
+	0x99f094bd,
+	0x0007f100,
+	0x0203f037,
+	0xbd0009d0,
+	0x0007f104,
+	0x0203f006,
+	0xbd000ad0,
+/* 0x00ed: wait_donez_ne */
+	0x0087f104,
+	0x0183f000,
+	0xff0088cf,
+	0x1bf4888a,
+	0xf094bdf3,
 	0x07f10099,
-	0x03f03700,
+	0x03f01700,
 	0x0009d002,
-	0x87f104bd,
-	0x84b60818,
-	0x008ad006,
-/* 0x0124: wait_doneo_e */
-	0x040087f1,
-	0xcf0684b6,
-	0x8aff0088,
-	0xf30bf488,
+	0x00f804bd,
+/* 0x0110: wait_doneo */
 	0x99f094bd,
 	0x0007f100,
-	0x0203f017,
+	0x0203f037,
 	0xbd0009d0,
-/* 0x0147: mmctx_size */
-	0xbd00f804,
-/* 0x0149: nv_mmctx_size_loop */
-	0x00e89894,
-	0xb61a85b6,
-	0x84b60180,
-	0x0098bb02,
-	0xb804e0b6,
-	0x1bf404ef,
-	0x029fb9eb,
-/* 0x0166: mmctx_xfer */
-	0x94bd00f8,
-	0xf10199f0,
-	0xf0370007,
-	0x09d00203,
-	0xf104bd00,
-	0xb6071087,
-	0x94bd0684,
-	0xf405bbfd,
-	0x8bd0090b,
-	0x0099f000,
-/* 0x018c: mmctx_base_disabled */
-	0xf405eefd,
-	0x8ed00c0b,
-	0xc08fd080,
-/* 0x019b: mmctx_multi_disabled */
-	0xb70199f0,
-	0xc8010080,
+	0x0007f104,
+	0x0203f006,
+	0xbd000ad0,
+/* 0x012d: wait_doneo_e */
+	0x0087f104,
+	0x0183f000,
+	0xff0088cf,
+	0x0bf4888a,
+	0xf094bdf3,
+	0x07f10099,
+	0x03f01700,
+	0x0009d002,
+	0x00f804bd,
+/* 0x0150: mmctx_size */
+/* 0x0152: nv_mmctx_size_loop */
+	0xe89894bd,
+	0x1a85b600,
+	0xb60180b6,
+	0x98bb0284,
+	0x04e0b600,
+	0xf404efb8,
+	0x9fb9eb1b,
+/* 0x016f: mmctx_xfer */
+	0xbd00f802,
+	0x0199f094,
+	0x370007f1,
+	0xd00203f0,
+	0x04bd0009,
+	0xbbfd94bd,
+	0x120bf405,
+	0xc40007f1,
+	0xd00103f0,
+	0x04bd000b,
+/* 0x0197: mmctx_base_disabled */
+	0xfd0099f0,
+	0x0bf405ee,
+	0x0007f11e,
+	0x0103f0c6,
+	0xbd000ed0,
+	0x0007f104,
+	0x0103f0c7,
+	0xbd000fd0,
+	0x0199f004,
+/* 0x01b8: mmctx_multi_disabled */
+	0xb600abc8,
+	0xb9f010b4,
+	0x01aec80c,
+	0xfd11e4b6,
+	0x07f105be,
+	0x03f0c500,
+	0x000bd001,
+/* 0x01d6: mmctx_exec_loop */
+/* 0x01d6: mmctx_wait_free */
+	0xe7f104bd,
+	0xe3f0c500,
+	0x00eecf01,
+	0xf41fe4f0,
+	0xce98f30b,
+	0x05e9fd00,
+	0xc80007f1,
+	0xd00103f0,
+	0x04bd000e,
+	0xb804c0b6,
+	0x1bf404cd,
+	0x02abc8d8,
+/* 0x0207: mmctx_fini_wait */
+	0xf11f1bf4,
+	0xf0c500b7,
+	0xbbcf01b3,
+	0x1fb4f000,
+	0xf410b4b0,
+	0xa7f0f01b,
+	0xd021f402,
+/* 0x0223: mmctx_stop */
+	0xc82b0ef4,
 	0xb4b600ab,
 	0x0cb9f010,
-	0xb601aec8,
-	0xbefd11e4,
-	0x008bd005,
-/* 0x01b4: mmctx_exec_loop */
-/* 0x01b4: mmctx_wait_free */
-	0xf0008ecf,
-	0x0bf41fe4,
-	0x00ce98fa,
-	0xd005e9fd,
-	0xc0b6c08e,
-	0x04cdb804,
-	0xc8e81bf4,
-	0x1bf402ab,
-/* 0x01d5: mmctx_fini_wait */
-	0x008bcf18,
-	0xb01fb4f0,
-	0x1bf410b4,
-	0x02a7f0f7,
-	0xf4c921f4,
-/* 0x01ea: mmctx_stop */
-	0xabc81b0e,
-	0x10b4b600,
-	0xf00cb9f0,
-	0x8bd012b9,
-/* 0x01f9: mmctx_stop_wait */
-	0x008bcf00,
-	0xf412bbc8,
-/* 0x0202: mmctx_done */
-	0x94bdfa1b,
-	0xf10199f0,
-	0xf0170007,
-	0x09d00203,
-	0xf804bd00,
-/* 0x0215: strand_wait */
-	0xf0a0f900,
-	0x21f402a7,
-	0xf8a0fcc9,
-/* 0x0221: strand_pre */
-	0xfc87f100,
-	0x0283f04a,
-	0xd00c97f0,
-	0x21f50089,
-	0x00f80215,
-/* 0x0234: strand_post */
-	0x4afc87f1,
-	0xf00283f0,
-	0x89d00d97,
-	0x1521f500,
-/* 0x0247: strand_set */
-	0xf100f802,
-	0xf04ffca7,
-	0xaba202a3,
-	0xc7f00500,
-	0x00acd00f,
-	0xd00bc7f0,
-	0x21f500bc,
-	0xaed00215,
-	0x0ac7f000,
-	0xf500bcd0,
-	0xf8021521,
-/* 0x0271: strand_ctx_init */
-	0xf094bd00,
-	0x07f10399,
-	0x03f03700,
+	0xf112b9f0,
+	0xf0c50007,
+	0x0bd00103,
+/* 0x023b: mmctx_stop_wait */
+	0xf104bd00,
+	0xf0c500b7,
+	0xbbcf01b3,
+	0x12bbc800,
+/* 0x024b: mmctx_done */
+	0xbdf31bf4,
+	0x0199f094,
+	0x170007f1,
+	0xd00203f0,
+	0x04bd0009,
+/* 0x025e: strand_wait */
+	0xa0f900f8,
+	0xf402a7f0,
+	0xa0fcd021,
+/* 0x026a: strand_pre */
+	0x97f000f8,
+	0xfc07f10c,
+	0x0203f04a,
+	0xbd0009d0,
+	0x5e21f504,
+/* 0x027f: strand_post */
+	0xf000f802,
+	0x07f10d97,
+	0x03f04afc,
 	0x0009d002,
 	0x21f504bd,
-	0xe7f00221,
-	0x4721f503,
-	0xfca7f102,
-	0x02a3f046,
-	0x0400aba0,
-	0xf040a0d0,
-	0xbcd001c7,
-	0x1521f500,
-	0x010c9202,
-	0xf000acd0,
-	0xbcd002c7,
-	0x1521f500,
-	0x3421f502,
-	0x8087f102,
-	0x0684b608,
-	0xb70089cf,
-	0x95220080,
-/* 0x02ca: ctx_init_strand_loop */
+	0x00f8025e,
+/* 0x0294: strand_set */
+	0xf10fc7f0,
+	0xf04ffc07,
+	0x0cd00203,
+	0xf004bd00,
+	0x07f10bc7,
+	0x03f04afc,
+	0x000cd002,
+	0x07f104bd,
+	0x03f04ffc,
+	0x000ed002,
+	0xc7f004bd,
+	0xfc07f10a,
+	0x0203f04a,
+	0xbd000cd0,
+	0x5e21f504,
+/* 0x02d3: strand_ctx_init */
+	0xbd00f802,
+	0x0399f094,
+	0x370007f1,
+	0xd00203f0,
+	0x04bd0009,
+	0x026a21f5,
+	0xf503e7f0,
+	0xbd029421,
+	0xfc07f1c4,
+	0x0203f047,
+	0xbd000cd0,
+	0x01c7f004,
+	0x4afc07f1,
+	0xd00203f0,
+	0x04bd000c,
+	0x025e21f5,
+	0xf1010c92,
+	0xf046fc07,
+	0x0cd00203,
+	0xf004bd00,
+	0x07f102c7,
+	0x03f04afc,
+	0x000cd002,
+	0x21f504bd,
+	0x21f5025e,
+	0x87f1027f,
+	0x83f04200,
+	0x0097f102,
+	0x0293f020,
+	0x950099cf,
+/* 0x034a: ctx_init_strand_loop */
 	0x8ed008fe,
 	0x408ed000,
 	0xb6808acf,
@@ -263,198 +293,230 @@ uint32_t nvf0_grgpc_code[] = {
 	0x170007f1,
 	0xd00203f0,
 	0x04bd0009,
-/* 0x02fe: error */
+/* 0x037e: error */
 	0xe0f900f8,
-	0x9814e7f1,
-	0xf440e3f0,
-	0xe0b78d21,
-	0xf7f0041c,
-	0x8d21f401,
-	0x00f8e0fc,
-/* 0x0318: init */
-	0x04fe04bd,
-	0x0017f100,
-	0x0227f012,
-	0xf10012d0,
-	0xfe047017,
-	0x17f10010,
-	0x10d00400,
-	0x0427f0c0,
-	0xf40012d0,
-	0x17f11031,
-	0x14b60608,
-	0x0012cf06,
+	0xf102ffb9,
+	0xf09814e7,
+	0x21f440e3,
+	0x01f7f09d,
+	0xf102ffb9,
+	0xf09c1ce7,
+	0x21f440e3,
+	0xf8e0fc9d,
+/* 0x03a1: init */
+	0xfe04bd00,
+	0x27f00004,
+	0x0007f102,
+	0x0003f012,
+	0xbd0002d0,
+	0x1f17f104,
+	0x0010fe05,
+	0x070007f1,
+	0xd00003f0,
+	0x04bd0000,
+	0xf10427f0,
+	0xf0040007,
+	0x02d00003,
+	0xf404bd00,
+	0x27f11031,
+	0x23f08200,
+	0x0022cf01,
 	0xf00137f0,
 	0x32bb1f24,
 	0x0132b604,
 	0x80050280,
-	0x10b70603,
-	0x12cf0400,
-	0x04028000,
-	0x0c30e7f1,
-	0xbd50e3f0,
-	0xbd34bd24,
-/* 0x0371: init_unk_loop */
-	0x6821f444,
-	0xf400f6b0,
-	0xf7f00f0b,
-	0x04f2bb01,
-	0xb6054ffd,
-/* 0x0386: init_unk_next */
-	0x20b60130,
-	0x04e0b601,
-	0xf40226b0,
-/* 0x0392: init_unk_done */
-	0x0380e21b,
-	0x08048007,
-	0x010027f1,
-	0xcf0223f0,
-	0x34bd0022,
-	0x070047f1,
-	0x950644b6,
-	0x45d00825,
-	0x4045d000,
-	0x98000e98,
-	0x21f5010f,
-	0x2fbb0147,
-	0x003fbb00,
-	0x98010e98,
-	0x21f5020f,
-	0x0e980147,
-	0x00effd05,
-	0xbb002ebb,
-	0x0e98003e,
-	0x030f9802,
-	0x014721f5,
-	0xfd070e98,
+	0x27f10603,
+	0x23f08600,
+	0x0022cf01,
+	0xf1040280,
+	0xf00c30e7,
+	0x24bd50e3,
+	0x44bd34bd,
+/* 0x0410: init_unk_loop */
+	0xb06821f4,
+	0x0bf400f6,
+	0x01f7f00f,
+	0xfd04f2bb,
+	0x30b6054f,
+/* 0x0425: init_unk_next */
+	0x0120b601,
+	0xb004e0b6,
+	0x1bf40226,
+/* 0x0431: init_unk_done */
+	0x070380e2,
+	0xf1080480,
+	0xf0010027,
+	0x22cf0223,
+	0x9534bd00,
+	0x07f10825,
+	0x03f0c000,
+	0x0005d001,
+	0x07f104bd,
+	0x03f0c100,
+	0x0005d001,
+	0x0e9804bd,
+	0x010f9800,
+	0x015021f5,
+	0xbb002fbb,
+	0x0e98003f,
+	0x020f9801,
+	0x015021f5,
+	0xfd050e98,
 	0x2ebb00ef,
 	0x003ebb00,
-	0x130040b7,
-	0xd00235b6,
-	0x25b60043,
-	0x0635b608,
-	0xb60120b6,
-	0x24b60130,
-	0x0834b608,
-	0xf5022fb9,
-	0xbb027121,
-	0x07f1003f,
-	0x03f00100,
-	0x0003d002,
-	0x24bd04bd,
-	0xf11f29f0,
-	0xf0300007,
-	0x02d00203,
-/* 0x0433: main */
+	0x98020e98,
+	0x21f5030f,
+	0x0e980150,
+	0x00effd07,
+	0xbb002ebb,
+	0x35b6003e,
+	0x0007f102,
+	0x0103f0d3,
+	0xbd0003d0,
+	0x0825b604,
+	0xb60635b6,
+	0x30b60120,
+	0x0824b601,
+	0xb90834b6,
+	0x21f5022f,
+	0x3fbb02d3,
+	0x0007f100,
+	0x0203f001,
+	0xbd0003d0,
+	0xf024bd04,
+	0x07f11f29,
+	0x03f03000,
+	0x0002d002,
+/* 0x04e2: main */
+	0x31f404bd,
+	0x0028f400,
+	0xf424d7f0,
+	0x01f43921,
+	0x04e4b0f4,
+	0xfe1e18f4,
+	0x27f00181,
+	0xfd20bd06,
+	0xe4b60412,
+	0x051efd01,
+	0xf50018fe,
+	0xf405d721,
+/* 0x0512: main_not_ctx_xfer */
+	0xef94d30e,
+	0x01f5f010,
+	0x037e21f5,
+/* 0x051f: ih */
+	0xf9c60ef4,
+	0x0188fe80,
+	0x90f980f9,
+	0xb0f9a0f9,
+	0xe0f9d0f9,
+	0x04bdf0f9,
+	0x0200a7f1,
+	0xcf00a3f0,
+	0xabc400aa,
+	0x2c0bf404,
+	0xf124d7f0,
+	0xf01a00e7,
+	0xeecf00e3,
+	0x00f7f100,
+	0x00f3f019,
+	0xf400ffcf,
+	0xe7f00421,
+	0x0007f101,
+	0x0003f01d,
+	0xbd000ed0,
+/* 0x056d: ih_no_fifo */
+	0x0007f104,
+	0x0003f001,
+	0xbd000ad0,
+	0xfcf0fc04,
+	0xfcd0fce0,
+	0xfca0fcb0,
+	0xfe80fc90,
+	0x80fc0088,
+	0xf80032f4,
+/* 0x0591: hub_barrier_done */
+	0x01f7f001,
+	0xbb040e98,
+	0xffb904fe,
+	0x18e7f102,
+	0x40e3f094,
+	0xf89d21f4,
+/* 0x05a9: ctx_redswitch */
+	0x20f7f000,
+	0x850007f1,
+	0xd00103f0,
+	0x04bd000f,
+/* 0x05bb: ctx_redswitch_delay */
+	0xb608e7f0,
+	0x1bf401e2,
+	0x00f5f1fd,
+	0x00f5f108,
+	0x0007f102,
+	0x0103f085,
+	0xbd000fd0,
+/* 0x05d7: ctx_xfer */
+	0xf100f804,
+	0xf0810007,
+	0x0fd00203,
 	0xf404bd00,
-	0x28f40031,
-	0x24d7f000,
-	0xf43921f4,
-	0xe4b0f401,
-	0x1e18f404,
-	0xf00181fe,
-	0x20bd0627,
-	0xb60412fd,
-	0x1efd01e4,
-	0x0018fe05,
-	0x04f721f5,
-/* 0x0463: main_not_ctx_xfer */
-	0x94d30ef4,
-	0xf5f010ef,
-	0xfe21f501,
-	0xc60ef402,
-/* 0x0470: ih */
-	0x88fe80f9,
-	0xf980f901,
-	0xf9a0f990,
-	0xf9d0f9b0,
-	0xbdf0f9e0,
-	0x800acf04,
-	0xf404abc4,
-	0xb7f11d0b,
-	0xd7f01900,
-	0x40becf24,
-	0xf400bfcf,
-	0xb0b70421,
-	0xe7f00400,
-	0x00bed001,
-/* 0x04a8: ih_no_fifo */
-	0xfc400ad0,
-	0xfce0fcf0,
-	0xfcb0fcd0,
-	0xfc90fca0,
-	0x0088fe80,
-	0x32f480fc,
-/* 0x04c3: hub_barrier_done */
-	0xf001f800,
-	0x0e9801f7,
-	0x04febb04,
-	0x9418e7f1,
-	0xf440e3f0,
-	0x00f88d21,
-/* 0x04d8: ctx_redswitch */
-	0x0614e7f1,
-	0xf006e4b6,
-	0xefd020f7,
-	0x08f7f000,
-/* 0x04e8: ctx_redswitch_delay */
-	0xf401f2b6,
-	0xf7f1fd1b,
-	0xefd00a20,
-/* 0x04f7: ctx_xfer */
-	0xf100f800,
-	0xb60a0417,
-	0x1fd00614,
-	0x0711f400,
-	0x04d821f5,
-/* 0x0508: ctx_xfer_not_load */
-	0x4afc17f1,
-	0xf00213f0,
-	0x12d00c27,
-	0x1521f500,
-	0xfc27f102,
-	0x0223f047,
-	0xf00020d0,
-	0x20b6012c,
-	0x0012d003,
-	0xf001acf0,
-	0xb7f002a5,
-	0x50b3f000,
-	0xb6040c98,
-	0xbcbb0fc4,
-	0x000c9800,
-	0xf0010d98,
-	0x21f500e7,
-	0xacf00166,
-	0x00b7f101,
-	0x50b3f040,
-	0xb6040c98,
-	0xbcbb0fc4,
-	0x010c9800,
-	0x98020d98,
-	0xe7f1060f,
-	0x21f50800,
-	0xacf00166,
-	0x04a5f001,
-	0x3000b7f1,
+	0x21f50711,
+/* 0x05ea: ctx_xfer_not_load */
+	0x21f505a9,
+	0x24bd026a,
+	0x47fc07f1,
+	0xd00203f0,
+	0x04bd0002,
+	0xb6012cf0,
+	0x07f10320,
+	0x03f04afc,
+	0x0002d002,
+	0xacf004bd,
+	0x02a5f001,
+	0x0000b7f1,
 	0x9850b3f0,
 	0xc4b6040c,
 	0x00bcbb0f,
-	0x98020c98,
-	0x0f98030d,
-	0x00e7f108,
-	0x6621f502,
-	0x1521f501,
-	0x0601f402,
-/* 0x05a3: ctx_xfer_post */
-	0xf11412f4,
-	0xf04afc17,
-	0x27f00213,
-	0x0012d00d,
-	0x021521f5,
-/* 0x05b4: ctx_xfer_done */
-	0x04c321f5,
-	0x000000f8,
+	0x98000c98,
+	0xe7f0010d,
+	0x6f21f500,
+	0x01acf001,
+	0x4000b7f1,
+	0x9850b3f0,
+	0xc4b6040c,
+	0x00bcbb0f,
+	0x98010c98,
+	0x0f98020d,
+	0x00e7f106,
+	0x6f21f508,
+	0x01acf001,
+	0xf104a5f0,
+	0xf03000b7,
+	0x0c9850b3,
+	0x0fc4b604,
+	0x9800bcbb,
+	0x0d98020c,
+	0x080f9803,
+	0x0200e7f1,
+	0x016f21f5,
+	0x025e21f5,
+	0xf40601f4,
+/* 0x0686: ctx_xfer_post */
+	0x21f50712,
+/* 0x068a: ctx_xfer_done */
+	0x21f5027f,
+	0x00f80591,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
 	0x00000000,
 	0x00000000,
 	0x00000000,
diff --git a/drivers/gpu/drm/nouveau/core/engine/graph/fuc/hub.fuc b/drivers/gpu/drm/nouveau/core/engine/graph/fuc/hub.fuc
index b82d2ae899174..c8ddb8d71b915 100644
--- a/drivers/gpu/drm/nouveau/core/engine/graph/fuc/hub.fuc
+++ b/drivers/gpu/drm/nouveau/core/engine/graph/fuc/hub.fuc
@@ -68,60 +68,57 @@ error:
 //
 init:
 	clear b32 $r0
-	mov $sp $r0
 	mov $xdbase $r0
 
+	// setup stack
+	nv_iord($r1, NV_PGRAPH_FECS_CAPS, 0)
+	extr $r1 $r1 9:17
+	shl b32 $r1 8
+	mov $sp $r1
+
 	// enable fifo access
-	mov $r1 0x1200
-	mov $r2 2
-	iowr I[$r1 + 0x000] $r2	// FIFO_ENABLE
+	mov $r2 NV_PGRAPH_FECS_ACCESS_FIFO
+	nv_iowr(NV_PGRAPH_FECS_ACCESS, 0, $r2)
 
 	// setup i0 handler, and route all interrupts to it
 	mov $r1 #ih
 	mov $iv0 $r1
-	mov $r1 0x400
-	iowr I[$r1 + 0x300] $r0	// INTR_DISPATCH
 
-	// route HUB_CHANNEL_SWITCH to fuc interrupt 8
-	mov $r3 0x404
-	shl b32 $r3 6
-	mov $r2 0x2003		// { HUB_CHANNEL_SWITCH, ZERO } -> intr 8
-	iowr I[$r3 + 0x000] $r2
+	clear b32 $r2
+	nv_iowr(NV_PGRAPH_FECS_INTR_ROUTE, 0, $r2)
+
+	// route HUB_CHSW_PULSE to fuc interrupt 8
+	mov $r2 0x2003		// { HUB_CHSW_PULSE, ZERO } -> intr 8
+	nv_iowr(NV_PGRAPH_FECS_IROUTE, 0, $r2)
 
 	// not sure what these are, route them because NVIDIA does, and
 	// the IRQ handler will signal the host if we ever get one.. we
 	// may find out if/why we need to handle these if so..
 	//
-	mov $r2 0x2004
-	iowr I[$r3 + 0x004] $r2 // { 0x04, ZERO } -> intr 9
-	mov $r2 0x200b
-	iowr I[$r3 + 0x008] $r2 // { 0x0b, ZERO } -> intr 10
-	mov $r2 0x200c
-	iowr I[$r3 + 0x01c] $r2 // { 0x0c, ZERO } -> intr 15
+	mov $r2 0x2004		// { 0x04, ZERO } -> intr 9
+	nv_iowr(NV_PGRAPH_FECS_IROUTE, 1, $r2)
+	mov $r2 0x200b		// { HUB_FIRMWARE_MTHD, ZERO } -> intr 10
+	nv_iowr(NV_PGRAPH_FECS_IROUTE, 2, $r2)
+	mov $r2 0x200c		// { 0x0c, ZERO } -> intr 15
+	nv_iowr(NV_PGRAPH_FECS_IROUTE, 7, $r2)
 
 	// enable all INTR_UP interrupts
-	mov $r2 0xc24
-	shl b32 $r2 6
-	not b32 $r3 $r0
-	iowr I[$r2] $r3
+	sub b32 $r3 $r0 1
+	nv_iowr(NV_PGRAPH_FECS_INTR_UP_EN, 0, $r3)
 
-	// enable fifo, ctxsw, 9, 10, 15 interrupts
-	mov $r2 -0x78fc		// 0x8704
-	sethi $r2 0
-	iowr I[$r1 + 0x000] $r2	// INTR_EN_SET
+	// enable fifo, ctxsw, 9, fwmthd, 15 interrupts
+	imm32($r2, 0x8704)
+	nv_iowr(NV_PGRAPH_FECS_INTR_EN_SET, 0, $r2)
 
 	// fifo level triggered, rest edge
-	sub b32 $r1 0x100
-	mov $r2 4
-	iowr I[$r1] $r2
+	mov $r2 NV_PGRAPH_FECS_INTR_MODE_FIFO_LEVEL
+	nv_iowr(NV_PGRAPH_FECS_INTR_MODE, 0, $r2)
 
 	// enable interrupts
 	bset $flags ie0
 
 	// fetch enabled GPC/ROP counts
-	mov $r14 -0x69fc	// 0x409604
-	sethi $r14 0x400000
-	call #nv_rd32
+	nv_rd32($r14, 0x409604)
 	extr $r1 $r15 16:20
 	st b32 D[$r0 + #rop_count] $r1
 	and $r15 0x1f
@@ -131,37 +128,40 @@ init:
 	mov $r1 1
 	shl b32 $r1 $r15
 	sub b32 $r1 1
-	mov $r2 0x40c
-	shl b32 $r2 6
-	iowr I[$r2 + 0x000] $r1
-	iowr I[$r2 + 0x100] $r1
+	nv_iowr(NV_PGRAPH_FECS_BAR_MASK0, 0, $r1)
+	nv_iowr(NV_PGRAPH_FECS_BAR_MASK1, 0, $r1)
 
 	// context size calculation, reserve first 256 bytes for use by fuc
 	mov $r1 256
 
+	//
+	mov $r15 2
+	call(ctx_4170s)
+	call(ctx_4170w)
+	mov $r15 0x10
+	call(ctx_86c)
+
 	// calculate size of mmio context data
 	ld b32 $r14 D[$r0 + #hub_mmio_list_head]
 	ld b32 $r15 D[$r0 + #hub_mmio_list_tail]
-	call #mmctx_size
+	call(mmctx_size)
 
 	// set mmctx base addresses now so we don't have to do it later,
 	// they don't (currently) ever change
-	mov $r3 0x700
-	shl b32 $r3 6
 	shr b32 $r4 $r1 8
-	iowr I[$r3 + 0x000] $r4		// MMCTX_SAVE_SWBASE
-	iowr I[$r3 + 0x100] $r4		// MMCTX_LOAD_SWBASE
+	nv_iowr(NV_PGRAPH_FECS_MMCTX_SAVE_SWBASE, 0, $r4)
+	nv_iowr(NV_PGRAPH_FECS_MMCTX_LOAD_SWBASE, 0, $r4)
 	add b32 $r3 0x1300
 	add b32 $r1 $r15
 	shr b32 $r15 2
-	iowr I[$r3 + 0x000] $r15	// MMCTX_LOAD_COUNT, wtf for?!?
+	nv_iowr(NV_PGRAPH_FECS_MMCTX_LOAD_COUNT, 0, $r15) // wtf??
 
 	// strands, base offset needs to be aligned to 256 bytes
 	shr b32 $r1 8
 	add b32 $r1 1
 	shl b32 $r1 8
 	mov b32 $r15 $r1
-	call #strand_ctx_init
+	call(strand_ctx_init)
 	add b32 $r1 $r15
 
 	// initialise each GPC in sequence by passing in the offset of its
@@ -173,30 +173,29 @@ init:
 	// in GPCn_CC_SCRATCH[1]
 	//
 	ld b32 $r3 D[$r0 + #gpc_count]
-	mov $r4 0x2000
-	sethi $r4 0x500000
+	imm32($r4, 0x502000)
 	init_gpc:
 		// setup, and start GPC ucode running
 		add b32 $r14 $r4 0x804
 		mov b32 $r15 $r1
-		call #nv_wr32			// CC_SCRATCH[1] = ctx offset
+		call(nv_wr32)			// CC_SCRATCH[1] = ctx offset
 		add b32 $r14 $r4 0x10c
 		clear b32 $r15
-		call #nv_wr32
+		call(nv_wr32)
 		add b32 $r14 $r4 0x104
-		call #nv_wr32			// ENTRY
+		call(nv_wr32)			// ENTRY
 		add b32 $r14 $r4 0x100
 		mov $r15 2			// CTRL_START_TRIGGER
-		call #nv_wr32			// CTRL
+		call(nv_wr32)			// CTRL
 
 		// wait for it to complete, and adjust context size
 		add b32 $r14 $r4 0x800
 		init_gpc_wait:
-			call #nv_rd32
+			call(nv_rd32)
 			xbit $r15 $r15 31
 			bra e #init_gpc_wait
 		add b32 $r14 $r4 0x804
-		call #nv_rd32
+		call(nv_rd32)
 		add b32 $r1 $r15
 
 		// next!
@@ -204,6 +203,12 @@ init:
 		sub b32 $r3 1
 		bra ne #init_gpc
 
+	//
+	mov $r15 0
+	call(ctx_86c)
+	mov $r15 0
+	call(ctx_4170s)
+
 	// save context size, and tell host we're ready
 	nv_iowr(NV_PGRAPH_FECS_CC_SCRATCH_VAL(1), 0, $r1)
 	clear b32 $r1
@@ -218,17 +223,15 @@ main:
 	bset $flags $p0
 	sleep $p0
 	mov $r13 #cmd_queue
-	call #queue_get
+	call(queue_get)
 	bra $p1 #main
 
 	// context switch, requested by GPU?
 	cmpu b32 $r14 0x4001
 	bra ne #main_not_ctx_switch
 		trace_set(T_AUTO)
-		mov $r1 0xb00
-		shl b32 $r1 6
-		iord $r2 I[$r1 + 0x100]		// CHAN_NEXT
-		iord $r1 I[$r1 + 0x000]		// CHAN_CUR
+		nv_iord($r1, NV_PGRAPH_FECS_CHAN_ADDR, 0)
+		nv_iord($r2, NV_PGRAPH_FECS_CHAN_NEXT, 0)
 
 		xbit $r3 $r1 31
 		bra e #chsw_no_prev
@@ -239,12 +242,12 @@ main:
 				trace_set(T_SAVE)
 				bclr $flags $p1
 				bset $flags $p2
-				call #ctx_xfer
+				call(ctx_xfer)
 				trace_clr(T_SAVE);
 				pop $r2
 				trace_set(T_LOAD);
 				bset $flags $p1
-				call #ctx_xfer
+				call(ctx_xfer)
 				trace_clr(T_LOAD);
 				bra #chsw_done
 			chsw_prev_no_next:
@@ -252,25 +255,21 @@ main:
 				mov b32 $r2 $r1
 				bclr $flags $p1
 				bclr $flags $p2
-				call #ctx_xfer
+				call(ctx_xfer)
 				pop $r2
-				mov $r1 0xb00
-				shl b32 $r1 6
-				iowr I[$r1] $r2
+				nv_iowr(NV_PGRAPH_FECS_CHAN_ADDR, 0, $r2)
 				bra #chsw_done
 		chsw_no_prev:
 			xbit $r3 $r2 31
 			bra e #chsw_done
 				bset $flags $p1
 				bclr $flags $p2
-				call #ctx_xfer
+				call(ctx_xfer)
 
 		// ack the context switch request
 		chsw_done:
-		mov $r1 0xb0c
-		shl b32 $r1 6
-		mov $r2 1
-		iowr I[$r1 + 0x000] $r2		// 0x409b0c
+		mov $r2 NV_PGRAPH_FECS_CHSW_ACK
+		nv_iowr(NV_PGRAPH_FECS_CHSW, 0, $r2)
 		trace_clr(T_AUTO)
 		bra #main
 
@@ -279,7 +278,7 @@ main:
 	cmpu b32 $r14 0x0001
 	bra ne #main_not_ctx_chan
 		mov b32 $r2 $r15
-		call #ctx_chan
+		call(ctx_chan)
 		bra #main_done
 
 	// request to store current channel context?
@@ -289,14 +288,14 @@ main:
 		trace_set(T_SAVE)
 		bclr $flags $p1
 		bclr $flags $p2
-		call #ctx_xfer
+		call(ctx_xfer)
 		trace_clr(T_SAVE)
 		bra #main_done
 
 	main_not_ctx_save:
 		shl b32 $r15 $r14 16
 		or $r15 E_BAD_COMMAND
-		call #error
+		call(error)
 		bra #main
 
 	main_done:
@@ -319,41 +318,46 @@ ih:
 	clear b32 $r0
 
 	// incoming fifo command?
-	iord $r10 I[$r0 + 0x200]	// INTR
-	and $r11 $r10 0x00000004
+	nv_iord($r10, NV_PGRAPH_FECS_INTR, 0)
+	and $r11 $r10 NV_PGRAPH_FECS_INTR_FIFO
 	bra e #ih_no_fifo
 		// queue incoming fifo command for later processing
-		mov $r11 0x1900
 		mov $r13 #cmd_queue
-		iord $r14 I[$r11 + 0x100]	// FIFO_CMD
-		iord $r15 I[$r11 + 0x000]	// FIFO_DATA
-		call #queue_put
+		nv_iord($r14, NV_PGRAPH_FECS_FIFO_CMD, 0)
+		nv_iord($r15, NV_PGRAPH_FECS_FIFO_DATA, 0)
+		call(queue_put)
 		add b32 $r11 0x400
 		mov $r14 1
-		iowr I[$r11 + 0x000] $r14	// FIFO_ACK
+		nv_iowr(NV_PGRAPH_FECS_FIFO_ACK, 0, $r14)
 
 	// context switch request?
 	ih_no_fifo:
-	and $r11 $r10 0x00000100
+	and $r11 $r10 NV_PGRAPH_FECS_INTR_CHSW
 	bra e #ih_no_ctxsw
 		// enqueue a context switch for later processing
 		mov $r13 #cmd_queue
 		mov $r14 0x4001
-		call #queue_put
+		call(queue_put)
 
-	// anything we didn't handle, bring it to the host's attention
+	// firmware method?
 	ih_no_ctxsw:
-	mov $r11 0x104
+	and $r11 $r10 NV_PGRAPH_FECS_INTR_FWMTHD
+	bra e #ih_no_fwmthd
+		// none we handle, ack, and fall-through to unhandled
+		mov $r11 0x100
+		nv_wr32(0x400144, $r11)
+
+	// anything we didn't handle, bring it to the host's attention
+	ih_no_fwmthd:
+	mov $r11 0x104 // FIFO | CHSW
 	not b32 $r11
 	and $r11 $r10 $r11
 	bra e #ih_no_other
-		mov $r10 0xc1c
-		shl b32 $r10 6
-		iowr I[$r10] $r11	// INTR_UP_SET
+		nv_iowr(NV_PGRAPH_FECS_INTR_UP_SET, 0, $r11)
 
 	// ack, and wake up main()
 	ih_no_other:
-	iowr I[$r0 + 0x100] $r10	// INTR_ACK
+	nv_iowr(NV_PGRAPH_FECS_INTR_ACK, 0, $r10)
 
 	pop $r15
 	pop $r14
@@ -370,12 +374,10 @@ ih:
 #if CHIPSET < GK100
 // Not real sure, but, MEM_CMD 7 will hang forever if this isn't done
 ctx_4160s:
-	mov $r14 0x4160
-	sethi $r14 0x400000
 	mov $r15 1
-	call #nv_wr32
+	nv_wr32(0x404160, $r15)
 	ctx_4160s_wait:
-		call #nv_rd32
+		nv_rd32($r15, 0x404160)
 		xbit $r15 $r15 4
 		bra e #ctx_4160s_wait
 	ret
@@ -384,10 +386,8 @@ ctx_4160s:
 // to hang with STATUS=0x00000007 until it's cleared.. fbcon can
 // still function with it set however...
 ctx_4160c:
-	mov $r14 0x4160
-	sethi $r14 0x400000
 	clear b32 $r15
-	call #nv_wr32
+	nv_wr32(0x404160, $r15)
 	ret
 #endif
 
@@ -396,18 +396,14 @@ ctx_4160c:
 // In: $r15 value to set 0x404170 to
 //
 ctx_4170s:
-	mov $r14 0x4170
-	sethi $r14 0x400000
 	or $r15 0x10
-	call #nv_wr32
+	nv_wr32(0x404170, $r15)
 	ret
 
 // Waits for a ctx_4170s() call to complete
 //
 ctx_4170w:
-	mov $r14 0x4170
-	sethi $r14 0x400000
-	call #nv_rd32
+	nv_rd32($r15, 0x404170)
 	and $r15 0x10
 	bra ne #ctx_4170w
 	ret
@@ -419,16 +415,18 @@ ctx_4170w:
 // funny things happen.
 //
 ctx_redswitch:
-	mov $r14 0x614
-	shl b32 $r14 6
-	mov $r15 0x270
-	iowr I[$r14] $r15	// HUB_RED_SWITCH = ENABLE_GPC, POWER_ALL
+	mov $r14 NV_PGRAPH_FECS_RED_SWITCH_ENABLE_GPC
+	or  $r14 NV_PGRAPH_FECS_RED_SWITCH_POWER_ROP
+	or  $r14 NV_PGRAPH_FECS_RED_SWITCH_POWER_GPC
+	or  $r14 NV_PGRAPH_FECS_RED_SWITCH_POWER_MAIN
+	nv_iowr(NV_PGRAPH_FECS_RED_SWITCH, 0, $r14)
 	mov $r15 8
 	ctx_redswitch_delay:
 		sub b32 $r15 1
 		bra ne #ctx_redswitch_delay
-	mov $r15 0x770
-	iowr I[$r14] $r15	// HUB_RED_SWITCH = ENABLE_ALL, POWER_ALL
+	or  $r14 NV_PGRAPH_FECS_RED_SWITCH_ENABLE_ROP
+	or  $r14 NV_PGRAPH_FECS_RED_SWITCH_ENABLE_MAIN
+	nv_iowr(NV_PGRAPH_FECS_RED_SWITCH, 0, $r14)
 	ret
 
 // Not a clue what this is for, except that unless the value is 0x10, the
@@ -437,15 +435,18 @@ ctx_redswitch:
 // In: $r15 value to set to (0x00/0x10 are used)
 //
 ctx_86c:
-	mov $r14 0x86c
-	shl b32 $r14 6
-	iowr I[$r14] $r15	// HUB(0x86c) = val
-	mov $r14 -0x75ec
-	sethi $r14 0x400000
-	call #nv_wr32		// ROP(0xa14) = val
-	mov $r14 -0x5794
-	sethi $r14 0x410000
-	call #nv_wr32		// GPC(0x86c) = val
+	nv_iowr(NV_PGRAPH_FECS_UNK86C, 0, $r15)
+	nv_wr32(0x408a14, $r15)
+	nv_wr32(NV_PGRAPH_GPCX_GPCCS_UNK86C, $r15)
+	ret
+
+// In: $r15 NV_PGRAPH_FECS_MEM_CMD_*
+ctx_mem:
+	nv_iowr(NV_PGRAPH_FECS_MEM_CMD, 0, $r15)
+	ctx_mem_wait:
+		nv_iord($r15, NV_PGRAPH_FECS_MEM_CMD, 0)
+		or $r15 $r15
+		bra ne #ctx_mem_wait
 	ret
 
 // ctx_load - load's a channel's ctxctl data, and selects its vm
@@ -457,23 +458,14 @@ ctx_load:
 
 	// switch to channel, somewhat magic in parts..
 	mov $r10 12		// DONE_UNK12
-	call #wait_donez
-	mov $r1 0xa24
-	shl b32 $r1 6
-	iowr I[$r1 + 0x000] $r0	// 0x409a24
-	mov $r3 0xb00
-	shl b32 $r3 6
-	iowr I[$r3 + 0x100] $r2	// CHAN_NEXT
-	mov $r1 0xa0c
-	shl b32 $r1 6
-	mov $r4 7
-	iowr I[$r1 + 0x000] $r2 // MEM_CHAN
-	iowr I[$r1 + 0x100] $r4	// MEM_CMD
-	ctx_chan_wait_0:
-		iord $r4 I[$r1 + 0x100]
-		and $r4 0x1f
-		bra ne #ctx_chan_wait_0
-	iowr I[$r3 + 0x000] $r2	// CHAN_CUR
+	call(wait_donez)
+	clear b32 $r15
+	nv_iowr(0x409a24, 0, $r15)
+	nv_iowr(NV_PGRAPH_FECS_CHAN_NEXT, 0, $r2)
+	nv_iowr(NV_PGRAPH_FECS_MEM_CHAN, 0, $r2)
+	mov $r15 NV_PGRAPH_FECS_MEM_CMD_LOAD_CHAN
+	call(ctx_mem)
+	nv_iowr(NV_PGRAPH_FECS_CHAN_ADDR, 0, $r2)
 
 	// load channel header, fetch PGRAPH context pointer
 	mov $xtargets $r0
@@ -482,14 +474,10 @@ ctx_load:
 	add b32 $r2 2
 
 	trace_set(T_LCHAN)
-	mov $r1 0xa04
-	shl b32 $r1 6
-	iowr I[$r1 + 0x000] $r2		// MEM_BASE
-	mov $r1 0xa20
-	shl b32 $r1 6
-	mov $r2 0x0002
-	sethi $r2 0x80000000
-	iowr I[$r1 + 0x000] $r2		// MEM_TARGET = vram
+	nv_iowr(NV_PGRAPH_FECS_MEM_BASE, 0, $r2)
+	imm32($r2, NV_PGRAPH_FECS_MEM_TARGET_UNK31)
+	or  $r2 NV_PGRAPH_FECS_MEM_TARGET_AS_VRAM
+	nv_iowr(NV_PGRAPH_FECS_MEM_TARGET, 0, $r2)
 	mov $r1 0x10			// chan + 0x0210
 	mov $r2 #xfer_data
 	sethi $r2 0x00020000		// 16 bytes
@@ -507,13 +495,9 @@ ctx_load:
 
 	// set transfer base to start of context, and fetch context header
 	trace_set(T_LCTXH)
-	mov $r2 0xa04
-	shl b32 $r2 6
-	iowr I[$r2 + 0x000] $r1		// MEM_BASE
-	mov $r2 1
-	mov $r1 0xa20
-	shl b32 $r1 6
-	iowr I[$r1 + 0x000] $r2		// MEM_TARGET = vm
+	nv_iowr(NV_PGRAPH_FECS_MEM_BASE, 0, $r1)
+	mov $r2 NV_PGRAPH_FECS_MEM_TARGET_AS_VM
+	nv_iowr(NV_PGRAPH_FECS_MEM_TARGET, 0, $r2)
 	mov $r1 #chan_data
 	sethi $r1 0x00060000		// 256 bytes
 	xdld $r0 $r1
@@ -532,21 +516,15 @@ ctx_load:
 //
 ctx_chan:
 #if CHIPSET < GK100
-	call #ctx_4160s
+	call(ctx_4160s)
 #endif
-	call #ctx_load
+	call(ctx_load)
 	mov $r10 12			// DONE_UNK12
-	call #wait_donez
-	mov $r1 0xa10
-	shl b32 $r1 6
-	mov $r2 5
-	iowr I[$r1 + 0x000] $r2		// MEM_CMD = 5 (???)
-	ctx_chan_wait:
-		iord $r2 I[$r1 + 0x000]
-		or $r2 $r2
-		bra ne #ctx_chan_wait
+	call(wait_donez)
+	mov $r15 5 // MEM_CMD 5 ???
+	call(ctx_mem)
 #if CHIPSET < GK100
-	call #ctx_4160c
+	call(ctx_4160c)
 #endif
 	ret
 
@@ -562,9 +540,7 @@ ctx_chan:
 ctx_mmio_exec:
 	// set transfer base to be the mmio list
 	ld b32 $r3 D[$r0 + #chan_mmio_address]
-	mov $r2 0xa04
-	shl b32 $r2 6
-	iowr I[$r2 + 0x000] $r3		// MEM_BASE
+	nv_iowr(NV_PGRAPH_FECS_MEM_BASE, 0, $r3)
 
 	clear b32 $r3
 	ctx_mmio_loop:
@@ -580,7 +556,7 @@ ctx_mmio_exec:
 		ctx_mmio_pull:
 		ld b32 $r14 D[$r4 + #xfer_data + 0x00]
 		ld b32 $r15 D[$r4 + #xfer_data + 0x04]
-		call #nv_wr32
+		call(nv_wr32)
 
 		// next!
 		add b32 $r3 8
@@ -590,7 +566,7 @@ ctx_mmio_exec:
 	// set transfer base back to the current context
 	ctx_mmio_done:
 	ld b32 $r3 D[$r0 + #ctx_current]
-	iowr I[$r2 + 0x000] $r3		// MEM_BASE
+	nv_iowr(NV_PGRAPH_FECS_MEM_BASE, 0, $r3)
 
 	// disable the mmio list now, we don't need/want to execute it again
 	st b32 D[$r0 + #chan_mmio_count] $r0
@@ -610,12 +586,10 @@ ctx_mmio_exec:
 //
 ctx_xfer:
 	// according to mwk, some kind of wait for idle
-	mov $r15 0xc00
-	shl b32 $r15 6
 	mov $r14 4
-	iowr I[$r15 + 0x200] $r14
+	nv_iowr(0x409c08, 0, $r14)
 	ctx_xfer_idle:
-		iord $r14 I[$r15 + 0x000]
+		nv_iord($r14, 0x409c00, 0)
 		and $r14 0x2000
 		bra ne #ctx_xfer_idle
 
@@ -623,50 +597,42 @@ ctx_xfer:
 	bra $p2 #ctx_xfer_pre_load
 	ctx_xfer_pre:
 		mov $r15 0x10
-		call #ctx_86c
+		call(ctx_86c)
 #if CHIPSET < GK100
-		call #ctx_4160s
+		call(ctx_4160s)
 #endif
 		bra not $p1 #ctx_xfer_exec
 
 	ctx_xfer_pre_load:
 		mov $r15 2
-		call #ctx_4170s
-		call #ctx_4170w
-		call #ctx_redswitch
+		call(ctx_4170s)
+		call(ctx_4170w)
+		call(ctx_redswitch)
 		clear b32 $r15
-		call #ctx_4170s
-		call #ctx_load
+		call(ctx_4170s)
+		call(ctx_load)
 
 	// fetch context pointer, and initiate xfer on all GPCs
 	ctx_xfer_exec:
 	ld b32 $r1 D[$r0 + #ctx_current]
-	mov $r2 0x414
-	shl b32 $r2 6
-	iowr I[$r2 + 0x000] $r0	// BAR_STATUS = reset
-	mov $r14 -0x5b00
-	sethi $r14 0x410000
-	mov b32 $r15 $r1
-	call #nv_wr32		// GPC_BCAST_WRCMD_DATA = ctx pointer
-	add b32 $r14 4
+
+	clear b32 $r2
+	nv_iowr(NV_PGRAPH_FECS_BAR, 0, $r2)
+
+	nv_wr32(0x41a500, $r1)	// GPC_BCAST_WRCMD_DATA = ctx pointer
 	xbit $r15 $flags $p1
 	xbit $r2 $flags $p2
 	shl b32 $r2 1
 	or $r15 $r2
-	call #nv_wr32		// GPC_BCAST_WRCMD_CMD = GPC_XFER(type)
+	nv_wr32(0x41a504, $r15)	// GPC_BCAST_WRCMD_CMD = GPC_XFER(type)
 
 	// strands
-	mov $r1 0x4afc
-	sethi $r1 0x20000
-	mov $r2 0xc
-	iowr I[$r1] $r2		// STRAND_CMD(0x3f) = 0x0c
-	call #strand_wait
-	mov $r2 0x47fc
-	sethi $r2 0x20000
-	iowr I[$r2] $r0		// STRAND_FIRST_GENE(0x3f) = 0x00
-	xbit $r2 $flags $p1
-	add b32 $r2 3
-	iowr I[$r1] $r2		// STRAND_CMD(0x3f) = 0x03/0x04 (SAVE/LOAD)
+	call(strand_pre)
+	clear b32 $r2
+	nv_iowr(NV_PGRAPH_FECS_STRAND_SELECT, 0x3f, $r2)
+	xbit $r2 $flags $p1	// SAVE/LOAD
+	add b32 $r2 NV_PGRAPH_FECS_STRAND_CMD_SAVE
+	nv_iowr(NV_PGRAPH_FECS_STRAND_CMD, 0x3f, $r2)
 
 	// mmio context
 	xbit $r10 $flags $p1	// direction
@@ -675,48 +641,42 @@ ctx_xfer:
 	ld b32 $r12 D[$r0 + #hub_mmio_list_head]
 	ld b32 $r13 D[$r0 + #hub_mmio_list_tail]
 	mov $r14 0		// not multi
-	call #mmctx_xfer
+	call(mmctx_xfer)
 
 	// wait for GPCs to all complete
 	mov $r10 8		// DONE_BAR
-	call #wait_doneo
+	call(wait_doneo)
 
 	// wait for strand xfer to complete
-	call #strand_wait
+	call(strand_wait)
 
 	// post-op
 	bra $p1 #ctx_xfer_post
 		mov $r10 12		// DONE_UNK12
-		call #wait_donez
-		mov $r1 0xa10
-		shl b32 $r1 6
-		mov $r2 5
-		iowr I[$r1] $r2		// MEM_CMD
-		ctx_xfer_post_save_wait:
-			iord $r2 I[$r1]
-			or $r2 $r2
-			bra ne #ctx_xfer_post_save_wait
+		call(wait_donez)
+		mov $r15 5 // MEM_CMD 5 ???
+		call(ctx_mem)
 
 	bra $p2 #ctx_xfer_done
 	ctx_xfer_post:
 		mov $r15 2
-		call #ctx_4170s
+		call(ctx_4170s)
 		clear b32 $r15
-		call #ctx_86c
-		call #strand_post
-		call #ctx_4170w
+		call(ctx_86c)
+		call(strand_post)
+		call(ctx_4170w)
 		clear b32 $r15
-		call #ctx_4170s
+		call(ctx_4170s)
 
 		bra not $p1 #ctx_xfer_no_post_mmio
 		ld b32 $r1 D[$r0 + #chan_mmio_count]
 		or $r1 $r1
 		bra e #ctx_xfer_no_post_mmio
-			call #ctx_mmio_exec
+			call(ctx_mmio_exec)
 
 		ctx_xfer_no_post_mmio:
 #if CHIPSET < GK100
-		call #ctx_4160c
+		call(ctx_4160c)
 #endif
 
 	ctx_xfer_done:
diff --git a/drivers/gpu/drm/nouveau/core/engine/graph/fuc/hubnv108.fuc5 b/drivers/gpu/drm/nouveau/core/engine/graph/fuc/hubnv108.fuc5
new file mode 100644
index 0000000000000..7c5d25630fa8d
--- /dev/null
+++ b/drivers/gpu/drm/nouveau/core/engine/graph/fuc/hubnv108.fuc5
@@ -0,0 +1,40 @@
+/*
+ * Copyright 2013 Red Hat Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: Ben Skeggs <bskeggs@redhat.com>
+ */
+
+#define CHIPSET GK208
+#include "macros.fuc"
+
+.section #nv108_grhub_data
+#define INCLUDE_DATA
+#include "com.fuc"
+#include "hub.fuc"
+#undef INCLUDE_DATA
+
+.section #nv108_grhub_code
+#define INCLUDE_CODE
+bra #init
+#include "com.fuc"
+#include "hub.fuc"
+.align 256
+#undef INCLUDE_CODE
diff --git a/drivers/gpu/drm/nouveau/core/engine/graph/fuc/hubnv108.fuc5.h b/drivers/gpu/drm/nouveau/core/engine/graph/fuc/hubnv108.fuc5.h
new file mode 100644
index 0000000000000..4750984bf380a
--- /dev/null
+++ b/drivers/gpu/drm/nouveau/core/engine/graph/fuc/hubnv108.fuc5.h
@@ -0,0 +1,916 @@
+uint32_t nv108_grhub_data[] = {
+/* 0x0000: hub_mmio_list_head */
+	0x00000300,
+/* 0x0004: hub_mmio_list_tail */
+	0x00000304,
+/* 0x0008: gpc_count */
+	0x00000000,
+/* 0x000c: rop_count */
+	0x00000000,
+/* 0x0010: cmd_queue */
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+/* 0x0058: ctx_current */
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+/* 0x0100: chan_data */
+/* 0x0100: chan_mmio_count */
+	0x00000000,
+/* 0x0104: chan_mmio_address */
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+/* 0x0200: xfer_data */
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+/* 0x0300: hub_mmio_list_base */
+	0x0417e91c,
+};
+
+uint32_t nv108_grhub_code[] = {
+	0x030e0ef5,
+/* 0x0004: queue_put */
+	0x9800d898,
+	0x86f001d9,
+	0xf489a408,
+	0x020f0b1b,
+	0x0002f87e,
+/* 0x001a: queue_put_next */
+	0x98c400f8,
+	0x0384b607,
+	0xb6008dbb,
+	0x8eb50880,
+	0x018fb500,
+	0xf00190b6,
+	0xd9b50f94,
+/* 0x0037: queue_get */
+	0xf400f801,
+	0xd8980131,
+	0x01d99800,
+	0x0bf489a4,
+	0x0789c421,
+	0xbb0394b6,
+	0x90b6009d,
+	0x009e9808,
+	0xb6019f98,
+	0x84f00180,
+	0x00d8b50f,
+/* 0x0063: queue_get_done */
+	0xf80132f4,
+/* 0x0065: nv_rd32 */
+	0xf0ecb200,
+	0x00801fc9,
+	0x0cf601ca,
+/* 0x0073: nv_rd32_wait */
+	0x8c04bd00,
+	0xcf01ca00,
+	0xccc800cc,
+	0xf61bf41f,
+	0xec7e060a,
+	0x008f0000,
+	0xffcf01cb,
+/* 0x008f: nv_wr32 */
+	0x8000f800,
+	0xf601cc00,
+	0x04bd000f,
+	0xc9f0ecb2,
+	0x1ec9f01f,
+	0x01ca0080,
+	0xbd000cf6,
+/* 0x00a9: nv_wr32_wait */
+	0xca008c04,
+	0x00cccf01,
+	0xf41fccc8,
+	0x00f8f61b,
+/* 0x00b8: wait_donez */
+	0x99f094bd,
+	0x37008000,
+	0x0009f602,
+	0x008004bd,
+	0x0af60206,
+/* 0x00cf: wait_donez_ne */
+	0x8804bd00,
+	0xcf010000,
+	0x8aff0088,
+	0xf61bf488,
+	0x99f094bd,
+	0x17008000,
+	0x0009f602,
+	0x00f804bd,
+/* 0x00ec: wait_doneo */
+	0x99f094bd,
+	0x37008000,
+	0x0009f602,
+	0x008004bd,
+	0x0af60206,
+/* 0x0103: wait_doneo_e */
+	0x8804bd00,
+	0xcf010000,
+	0x8aff0088,
+	0xf60bf488,
+	0x99f094bd,
+	0x17008000,
+	0x0009f602,
+	0x00f804bd,
+/* 0x0120: mmctx_size */
+/* 0x0122: nv_mmctx_size_loop */
+	0xe89894bd,
+	0x1a85b600,
+	0xb60180b6,
+	0x98bb0284,
+	0x04e0b600,
+	0x1bf4efa4,
+	0xf89fb2ec,
+/* 0x013d: mmctx_xfer */
+	0xf094bd00,
+	0x00800199,
+	0x09f60237,
+	0xbd04bd00,
+	0x05bbfd94,
+	0x800f0bf4,
+	0xf601c400,
+	0x04bd000b,
+/* 0x015f: mmctx_base_disabled */
+	0xfd0099f0,
+	0x0bf405ee,
+	0xc6008018,
+	0x000ef601,
+	0x008004bd,
+	0x0ff601c7,
+	0xf004bd00,
+/* 0x017a: mmctx_multi_disabled */
+	0xabc80199,
+	0x10b4b600,
+	0xc80cb9f0,
+	0xe4b601ae,
+	0x05befd11,
+	0x01c50080,
+	0xbd000bf6,
+/* 0x0195: mmctx_exec_loop */
+/* 0x0195: mmctx_wait_free */
+	0xc5008e04,
+	0x00eecf01,
+	0xf41fe4f0,
+	0xce98f60b,
+	0x05e9fd00,
+	0x01c80080,
+	0xbd000ef6,
+	0x04c0b604,
+	0x1bf4cda4,
+	0x02abc8df,
+/* 0x01bf: mmctx_fini_wait */
+	0x8b1c1bf4,
+	0xcf01c500,
+	0xb4f000bb,
+	0x10b4b01f,
+	0x0af31bf4,
+	0x00b87e02,
+	0x250ef400,
+/* 0x01d8: mmctx_stop */
+	0xb600abc8,
+	0xb9f010b4,
+	0x12b9f00c,
+	0x01c50080,
+	0xbd000bf6,
+/* 0x01ed: mmctx_stop_wait */
+	0xc5008b04,
+	0x00bbcf01,
+	0xf412bbc8,
+/* 0x01fa: mmctx_done */
+	0x94bdf61b,
+	0x800199f0,
+	0xf6021700,
+	0x04bd0009,
+/* 0x020a: strand_wait */
+	0xa0f900f8,
+	0xb87e020a,
+	0xa0fc0000,
+/* 0x0216: strand_pre */
+	0x0c0900f8,
+	0x024afc80,
+	0xbd0009f6,
+	0x020a7e04,
+/* 0x0227: strand_post */
+	0x0900f800,
+	0x4afc800d,
+	0x0009f602,
+	0x0a7e04bd,
+	0x00f80002,
+/* 0x0238: strand_set */
+	0xfc800f0c,
+	0x0cf6024f,
+	0x0c04bd00,
+	0x4afc800b,
+	0x000cf602,
+	0xfc8004bd,
+	0x0ef6024f,
+	0x0c04bd00,
+	0x4afc800a,
+	0x000cf602,
+	0x0a7e04bd,
+	0x00f80002,
+/* 0x0268: strand_ctx_init */
+	0x99f094bd,
+	0x37008003,
+	0x0009f602,
+	0x167e04bd,
+	0x030e0002,
+	0x0002387e,
+	0xfc80c4bd,
+	0x0cf60247,
+	0x0c04bd00,
+	0x4afc8001,
+	0x000cf602,
+	0x0a7e04bd,
+	0x0c920002,
+	0x46fc8001,
+	0x000cf602,
+	0x020c04bd,
+	0x024afc80,
+	0xbd000cf6,
+	0x020a7e04,
+	0x02277e00,
+	0x42008800,
+	0x20008902,
+	0x0099cf02,
+/* 0x02c7: ctx_init_strand_loop */
+	0xf608fe95,
+	0x8ef6008e,
+	0x808acf40,
+	0xb606a5b6,
+	0xeabb01a0,
+	0x0480b600,
+	0xf40192b6,
+	0xe4b6e81b,
+	0xf2efbc08,
+	0x99f094bd,
+	0x17008003,
+	0x0009f602,
+	0x00f804bd,
+/* 0x02f8: error */
+	0x02050080,
+	0xbd000ff6,
+	0x80010f04,
+	0xf6030700,
+	0x04bd000f,
+/* 0x030e: init */
+	0x04bd00f8,
+	0x410007fe,
+	0x11cf4200,
+	0x0911e700,
+	0x0814b601,
+	0x020014fe,
+	0x12004002,
+	0xbd0002f6,
+	0x05c94104,
+	0xbd0010fe,
+	0x07004024,
+	0xbd0002f6,
+	0x20034204,
+	0x01010080,
+	0xbd0002f6,
+	0x20044204,
+	0x01010480,
+	0xbd0002f6,
+	0x200b4204,
+	0x01010880,
+	0xbd0002f6,
+	0x200c4204,
+	0x01011c80,
+	0xbd0002f6,
+	0x01039204,
+	0x03090080,
+	0xbd0003f6,
+	0x87044204,
+	0xf6040040,
+	0x04bd0002,
+	0x00400402,
+	0x0002f603,
+	0x31f404bd,
+	0x96048e10,
+	0x00657e40,
+	0xc7feb200,
+	0x01b590f1,
+	0x1ff4f003,
+	0x01020fb5,
+	0x041fbb01,
+	0x800112b6,
+	0xf6010300,
+	0x04bd0001,
+	0x01040080,
+	0xbd0001f6,
+	0x01004104,
+	0x627e020f,
+	0x717e0006,
+	0x100f0006,
+	0x0006b37e,
+	0x98000e98,
+	0x207e010f,
+	0x14950001,
+	0xc0008008,
+	0x0004f601,
+	0x008004bd,
+	0x04f601c1,
+	0xb704bd00,
+	0xbb130030,
+	0xf5b6001f,
+	0xd3008002,
+	0x000ff601,
+	0x15b604bd,
+	0x0110b608,
+	0xb20814b6,
+	0x02687e1f,
+	0x001fbb00,
+	0x84020398,
+/* 0x041f: init_gpc */
+	0xb8502000,
+	0x0008044e,
+	0x8f7e1fb2,
+	0x4eb80000,
+	0xbd00010c,
+	0x008f7ef4,
+	0x044eb800,
+	0x8f7e0001,
+	0x4eb80000,
+	0x0f000100,
+	0x008f7e02,
+	0x004eb800,
+/* 0x044e: init_gpc_wait */
+	0x657e0008,
+	0xffc80000,
+	0xf90bf41f,
+	0x08044eb8,
+	0x00657e00,
+	0x001fbb00,
+	0x800040b7,
+	0xf40132b6,
+	0x000fb41b,
+	0x0006b37e,
+	0x627e000f,
+	0x00800006,
+	0x01f60201,
+	0xbd04bd00,
+	0x1f19f014,
+	0x02300080,
+	0xbd0001f6,
+/* 0x0491: main */
+	0x0031f404,
+	0x0d0028f4,
+	0x00377e10,
+	0xf401f400,
+	0x4001e4b1,
+	0x00c71bf5,
+	0x99f094bd,
+	0x37008004,
+	0x0009f602,
+	0x008104bd,
+	0x11cf02c0,
+	0xc1008200,
+	0x0022cf02,
+	0xf41f13c8,
+	0x23c8770b,
+	0x550bf41f,
+	0x12b220f9,
+	0x99f094bd,
+	0x37008007,
+	0x0009f602,
+	0x32f404bd,
+	0x0231f401,
+	0x0008367e,
+	0x99f094bd,
+	0x17008007,
+	0x0009f602,
+	0x20fc04bd,
+	0x99f094bd,
+	0x37008006,
+	0x0009f602,
+	0x31f404bd,
+	0x08367e01,
+	0xf094bd00,
+	0x00800699,
+	0x09f60217,
+	0xf404bd00,
+/* 0x0522: chsw_prev_no_next */
+	0x20f92f0e,
+	0x32f412b2,
+	0x0232f401,
+	0x0008367e,
+	0x008020fc,
+	0x02f602c0,
+	0xf404bd00,
+/* 0x053e: chsw_no_prev */
+	0x23c8130e,
+	0x0d0bf41f,
+	0xf40131f4,
+	0x367e0232,
+/* 0x054e: chsw_done */
+	0x01020008,
+	0x02c30080,
+	0xbd0002f6,
+	0xf094bd04,
+	0x00800499,
+	0x09f60217,
+	0xf504bd00,
+/* 0x056b: main_not_ctx_switch */
+	0xb0ff2a0e,
+	0x1bf401e4,
+	0x7ef2b20c,
+	0xf40007d6,
+/* 0x057a: main_not_ctx_chan */
+	0xe4b0400e,
+	0x2c1bf402,
+	0x99f094bd,
+	0x37008007,
+	0x0009f602,
+	0x32f404bd,
+	0x0232f401,
+	0x0008367e,
+	0x99f094bd,
+	0x17008007,
+	0x0009f602,
+	0x0ef404bd,
+/* 0x05a9: main_not_ctx_save */
+	0x10ef9411,
+	0x7e01f5f0,
+	0xf50002f8,
+/* 0x05b7: main_done */
+	0xbdfede0e,
+	0x1f29f024,
+	0x02300080,
+	0xbd0002f6,
+	0xcc0ef504,
+/* 0x05c9: ih */
+	0xfe80f9fe,
+	0x80f90188,
+	0xa0f990f9,
+	0xd0f9b0f9,
+	0xf0f9e0f9,
+	0x004a04bd,
+	0x00aacf02,
+	0xf404abc4,
+	0x100d230b,
+	0xcf1a004e,
+	0x004f00ee,
+	0x00ffcf19,
+	0x0000047e,
+	0x0400b0b7,
+	0x0040010e,
+	0x000ef61d,
+/* 0x060a: ih_no_fifo */
+	0xabe404bd,
+	0x0bf40100,
+	0x4e100d0c,
+	0x047e4001,
+/* 0x061a: ih_no_ctxsw */
+	0xabe40000,
+	0x0bf40400,
+	0x01004b10,
+	0x448ebfb2,
+	0x8f7e4001,
+/* 0x062e: ih_no_fwmthd */
+	0x044b0000,
+	0xffb0bd01,
+	0x0bf4b4ab,
+	0x0700800c,
+	0x000bf603,
+/* 0x0642: ih_no_other */
+	0x004004bd,
+	0x000af601,
+	0xf0fc04bd,
+	0xd0fce0fc,
+	0xa0fcb0fc,
+	0x80fc90fc,
+	0xfc0088fe,
+	0x0032f480,
+/* 0x0662: ctx_4170s */
+	0xf5f001f8,
+	0x8effb210,
+	0x7e404170,
+	0xf800008f,
+/* 0x0671: ctx_4170w */
+	0x41708e00,
+	0x00657e40,
+	0xf0ffb200,
+	0x1bf410f4,
+/* 0x0683: ctx_redswitch */
+	0x4e00f8f3,
+	0xe5f00200,
+	0x20e5f040,
+	0x8010e5f0,
+	0xf6018500,
+	0x04bd000e,
+/* 0x069a: ctx_redswitch_delay */
+	0xf2b6080f,
+	0xfd1bf401,
+	0x0400e5f1,
+	0x0100e5f1,
+	0x01850080,
+	0xbd000ef6,
+/* 0x06b3: ctx_86c */
+	0x8000f804,
+	0xf6022300,
+	0x04bd000f,
+	0x148effb2,
+	0x8f7e408a,
+	0xffb20000,
+	0x41a88c8e,
+	0x00008f7e,
+/* 0x06d2: ctx_mem */
+	0x008000f8,
+	0x0ff60284,
+/* 0x06db: ctx_mem_wait */
+	0x8f04bd00,
+	0xcf028400,
+	0xfffd00ff,
+	0xf61bf405,
+/* 0x06ea: ctx_load */
+	0x94bd00f8,
+	0x800599f0,
+	0xf6023700,
+	0x04bd0009,
+	0xb87e0c0a,
+	0xf4bd0000,
+	0x02890080,
+	0xbd000ff6,
+	0xc1008004,
+	0x0002f602,
+	0x008004bd,
+	0x02f60283,
+	0x0f04bd00,
+	0x06d27e07,
+	0xc0008000,
+	0x0002f602,
+	0x0bfe04bd,
+	0x1f2af000,
+	0xb60424b6,
+	0x94bd0220,
+	0x800899f0,
+	0xf6023700,
+	0x04bd0009,
+	0x02810080,
+	0xbd0002f6,
+	0x0000d204,
+	0x25f08000,
+	0x88008002,
+	0x0002f602,
+	0x100104bd,
+	0xf0020042,
+	0x12fa0223,
+	0xbd03f805,
+	0x0899f094,
+	0x02170080,
+	0xbd0009f6,
+	0x81019804,
+	0x981814b6,
+	0x25b68002,
+	0x0512fd08,
+	0xbd1601b5,
+	0x0999f094,
+	0x02370080,
+	0xbd0009f6,
+	0x81008004,
+	0x0001f602,
+	0x010204bd,
+	0x02880080,
+	0xbd0002f6,
+	0x01004104,
+	0xfa0613f0,
+	0x03f80501,
+	0x99f094bd,
+	0x17008009,
+	0x0009f602,
+	0x94bd04bd,
+	0x800599f0,
+	0xf6021700,
+	0x04bd0009,
+/* 0x07d6: ctx_chan */
+	0xea7e00f8,
+	0x0c0a0006,
+	0x0000b87e,
+	0xd27e050f,
+	0x00f80006,
+/* 0x07e8: ctx_mmio_exec */
+	0x80410398,
+	0xf6028100,
+	0x04bd0003,
+/* 0x07f6: ctx_mmio_loop */
+	0x34c434bd,
+	0x0e1bf4ff,
+	0xf0020045,
+	0x35fa0653,
+/* 0x0807: ctx_mmio_pull */
+	0x9803f805,
+	0x4f98804e,
+	0x008f7e81,
+	0x0830b600,
+	0xf40112b6,
+/* 0x081a: ctx_mmio_done */
+	0x0398df1b,
+	0x81008016,
+	0x0003f602,
+	0x00b504bd,
+	0x01004140,
+	0xfa0613f0,
+	0x03f80601,
+/* 0x0836: ctx_xfer */
+	0x040e00f8,
+	0x03020080,
+	0xbd000ef6,
+/* 0x0841: ctx_xfer_idle */
+	0x00008e04,
+	0x00eecf03,
+	0x2000e4f1,
+	0xf4f51bf4,
+	0x02f40611,
+/* 0x0855: ctx_xfer_pre */
+	0x7e100f0c,
+	0xf40006b3,
+/* 0x085e: ctx_xfer_pre_load */
+	0x020f1b11,
+	0x0006627e,
+	0x0006717e,
+	0x0006837e,
+	0x627ef4bd,
+	0xea7e0006,
+/* 0x0876: ctx_xfer_exec */
+	0x01980006,
+	0x8024bd16,
+	0xf6010500,
+	0x04bd0002,
+	0x008e1fb2,
+	0x8f7e41a5,
+	0xfcf00000,
+	0x022cf001,
+	0xfd0124b6,
+	0xffb205f2,
+	0x41a5048e,
+	0x00008f7e,
+	0x0002167e,
+	0xfc8024bd,
+	0x02f60247,
+	0xf004bd00,
+	0x20b6012c,
+	0x4afc8003,
+	0x0002f602,
+	0xacf004bd,
+	0x06a5f001,
+	0x0c98000b,
+	0x010d9800,
+	0x3d7e000e,
+	0x080a0001,
+	0x0000ec7e,
+	0x00020a7e,
+	0x0a1201f4,
+	0x00b87e0c,
+	0x7e050f00,
+	0xf40006d2,
+/* 0x08f2: ctx_xfer_post */
+	0x020f2d02,
+	0x0006627e,
+	0xb37ef4bd,
+	0x277e0006,
+	0x717e0002,
+	0xf4bd0006,
+	0x0006627e,
+	0x981011f4,
+	0x11fd4001,
+	0x070bf405,
+	0x0007e87e,
+/* 0x091c: ctx_xfer_no_post_mmio */
+/* 0x091c: ctx_xfer_done */
+	0x000000f8,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+};
diff --git a/drivers/gpu/drm/nouveau/core/engine/graph/fuc/hubnvc0.fuc.h b/drivers/gpu/drm/nouveau/core/engine/graph/fuc/hubnvc0.fuc.h
index b59f694c0423e..132f684b1946a 100644
--- a/drivers/gpu/drm/nouveau/core/engine/graph/fuc/hubnvc0.fuc.h
+++ b/drivers/gpu/drm/nouveau/core/engine/graph/fuc/hubnvc0.fuc.h
@@ -206,14 +206,14 @@ uint32_t nvc0_grhub_data[] = {
 };
 
 uint32_t nvc0_grhub_code[] = {
-	0x031b0ef5,
+	0x039b0ef5,
 /* 0x0004: queue_put */
 	0x9800d898,
 	0x86f001d9,
 	0x0489b808,
 	0xf00c1bf4,
 	0x21f502f7,
-	0x00f802fe,
+	0x00f8037e,
 /* 0x001c: queue_put_next */
 	0xb60798c4,
 	0x8dbb0384,
@@ -237,184 +237,214 @@ uint32_t nvc0_grhub_code[] = {
 /* 0x0066: queue_get_done */
 	0x00f80132,
 /* 0x0068: nv_rd32 */
-	0x0728b7f1,
-	0xb906b4b6,
-	0xc9f002ec,
-	0x00bcd01f,
-/* 0x0078: nv_rd32_wait */
-	0xc800bccf,
-	0x1bf41fcc,
-	0x06a7f0fa,
-	0x010921f5,
-	0xf840bfcf,
-/* 0x008d: nv_wr32 */
-	0x28b7f100,
-	0x06b4b607,
-	0xb980bfd0,
-	0xc9f002ec,
-	0x1ec9f01f,
-/* 0x00a3: nv_wr32_wait */
-	0xcf00bcd0,
-	0xccc800bc,
-	0xfa1bf41f,
-/* 0x00ae: watchdog_reset */
-	0x87f100f8,
-	0x84b60430,
-	0x1ff9f006,
-	0xf8008fd0,
-/* 0x00bd: watchdog_clear */
-	0x3087f100,
-	0x0684b604,
-	0xf80080d0,
-/* 0x00c9: wait_donez */
-	0xf094bd00,
-	0x07f10099,
-	0x03f00f00,
-	0x0009d002,
-	0x07f104bd,
-	0x03f00600,
-	0x000ad002,
-/* 0x00e6: wait_donez_ne */
-	0x87f104bd,
-	0x83f00000,
-	0x0088cf01,
-	0xf4888aff,
-	0x94bdf31b,
-	0xf10099f0,
-	0xf0170007,
-	0x09d00203,
-	0xf804bd00,
-/* 0x0109: wait_doneo */
-	0xf094bd00,
+	0xf002ecb9,
+	0x07f11fc9,
+	0x03f0ca00,
+	0x000cd001,
+/* 0x007a: nv_rd32_wait */
+	0xc7f104bd,
+	0xc3f0ca00,
+	0x00cccf01,
+	0xf41fccc8,
+	0xa7f0f31b,
+	0x1021f506,
+	0x00f7f101,
+	0x01f3f0cb,
+	0xf800ffcf,
+/* 0x009d: nv_wr32 */
+	0x0007f100,
+	0x0103f0cc,
+	0xbd000fd0,
+	0x02ecb904,
+	0xf01fc9f0,
+	0x07f11ec9,
+	0x03f0ca00,
+	0x000cd001,
+/* 0x00be: nv_wr32_wait */
+	0xc7f104bd,
+	0xc3f0ca00,
+	0x00cccf01,
+	0xf41fccc8,
+	0x00f8f31b,
+/* 0x00d0: wait_donez */
+	0x99f094bd,
+	0x0007f100,
+	0x0203f00f,
+	0xbd0009d0,
+	0x0007f104,
+	0x0203f006,
+	0xbd000ad0,
+/* 0x00ed: wait_donez_ne */
+	0x0087f104,
+	0x0183f000,
+	0xff0088cf,
+	0x1bf4888a,
+	0xf094bdf3,
 	0x07f10099,
-	0x03f00f00,
+	0x03f01700,
 	0x0009d002,
-	0x87f104bd,
-	0x84b60818,
-	0x008ad006,
-/* 0x0124: wait_doneo_e */
-	0x040087f1,
-	0xcf0684b6,
-	0x8aff0088,
-	0xf30bf488,
+	0x00f804bd,
+/* 0x0110: wait_doneo */
 	0x99f094bd,
 	0x0007f100,
-	0x0203f017,
+	0x0203f00f,
 	0xbd0009d0,
-/* 0x0147: mmctx_size */
-	0xbd00f804,
-/* 0x0149: nv_mmctx_size_loop */
-	0x00e89894,
-	0xb61a85b6,
-	0x84b60180,
-	0x0098bb02,
-	0xb804e0b6,
-	0x1bf404ef,
-	0x029fb9eb,
-/* 0x0166: mmctx_xfer */
-	0x94bd00f8,
-	0xf10199f0,
-	0xf00f0007,
-	0x09d00203,
-	0xf104bd00,
-	0xb6071087,
-	0x94bd0684,
-	0xf405bbfd,
-	0x8bd0090b,
-	0x0099f000,
-/* 0x018c: mmctx_base_disabled */
-	0xf405eefd,
-	0x8ed00c0b,
-	0xc08fd080,
-/* 0x019b: mmctx_multi_disabled */
-	0xb70199f0,
-	0xc8010080,
+	0x0007f104,
+	0x0203f006,
+	0xbd000ad0,
+/* 0x012d: wait_doneo_e */
+	0x0087f104,
+	0x0183f000,
+	0xff0088cf,
+	0x0bf4888a,
+	0xf094bdf3,
+	0x07f10099,
+	0x03f01700,
+	0x0009d002,
+	0x00f804bd,
+/* 0x0150: mmctx_size */
+/* 0x0152: nv_mmctx_size_loop */
+	0xe89894bd,
+	0x1a85b600,
+	0xb60180b6,
+	0x98bb0284,
+	0x04e0b600,
+	0xf404efb8,
+	0x9fb9eb1b,
+/* 0x016f: mmctx_xfer */
+	0xbd00f802,
+	0x0199f094,
+	0x0f0007f1,
+	0xd00203f0,
+	0x04bd0009,
+	0xbbfd94bd,
+	0x120bf405,
+	0xc40007f1,
+	0xd00103f0,
+	0x04bd000b,
+/* 0x0197: mmctx_base_disabled */
+	0xfd0099f0,
+	0x0bf405ee,
+	0x0007f11e,
+	0x0103f0c6,
+	0xbd000ed0,
+	0x0007f104,
+	0x0103f0c7,
+	0xbd000fd0,
+	0x0199f004,
+/* 0x01b8: mmctx_multi_disabled */
+	0xb600abc8,
+	0xb9f010b4,
+	0x01aec80c,
+	0xfd11e4b6,
+	0x07f105be,
+	0x03f0c500,
+	0x000bd001,
+/* 0x01d6: mmctx_exec_loop */
+/* 0x01d6: mmctx_wait_free */
+	0xe7f104bd,
+	0xe3f0c500,
+	0x00eecf01,
+	0xf41fe4f0,
+	0xce98f30b,
+	0x05e9fd00,
+	0xc80007f1,
+	0xd00103f0,
+	0x04bd000e,
+	0xb804c0b6,
+	0x1bf404cd,
+	0x02abc8d8,
+/* 0x0207: mmctx_fini_wait */
+	0xf11f1bf4,
+	0xf0c500b7,
+	0xbbcf01b3,
+	0x1fb4f000,
+	0xf410b4b0,
+	0xa7f0f01b,
+	0xd021f402,
+/* 0x0223: mmctx_stop */
+	0xc82b0ef4,
 	0xb4b600ab,
 	0x0cb9f010,
-	0xb601aec8,
-	0xbefd11e4,
-	0x008bd005,
-/* 0x01b4: mmctx_exec_loop */
-/* 0x01b4: mmctx_wait_free */
-	0xf0008ecf,
-	0x0bf41fe4,
-	0x00ce98fa,
-	0xd005e9fd,
-	0xc0b6c08e,
-	0x04cdb804,
-	0xc8e81bf4,
-	0x1bf402ab,
-/* 0x01d5: mmctx_fini_wait */
-	0x008bcf18,
-	0xb01fb4f0,
-	0x1bf410b4,
-	0x02a7f0f7,
-	0xf4c921f4,
-/* 0x01ea: mmctx_stop */
-	0xabc81b0e,
-	0x10b4b600,
-	0xf00cb9f0,
-	0x8bd012b9,
-/* 0x01f9: mmctx_stop_wait */
-	0x008bcf00,
-	0xf412bbc8,
-/* 0x0202: mmctx_done */
-	0x94bdfa1b,
-	0xf10199f0,
-	0xf0170007,
-	0x09d00203,
-	0xf804bd00,
-/* 0x0215: strand_wait */
-	0xf0a0f900,
-	0x21f402a7,
-	0xf8a0fcc9,
-/* 0x0221: strand_pre */
-	0xfc87f100,
-	0x0283f04a,
-	0xd00c97f0,
-	0x21f50089,
-	0x00f80215,
-/* 0x0234: strand_post */
-	0x4afc87f1,
-	0xf00283f0,
-	0x89d00d97,
-	0x1521f500,
-/* 0x0247: strand_set */
-	0xf100f802,
-	0xf04ffca7,
-	0xaba202a3,
-	0xc7f00500,
-	0x00acd00f,
-	0xd00bc7f0,
-	0x21f500bc,
-	0xaed00215,
-	0x0ac7f000,
-	0xf500bcd0,
-	0xf8021521,
-/* 0x0271: strand_ctx_init */
-	0xf094bd00,
-	0x07f10399,
-	0x03f00f00,
+	0xf112b9f0,
+	0xf0c50007,
+	0x0bd00103,
+/* 0x023b: mmctx_stop_wait */
+	0xf104bd00,
+	0xf0c500b7,
+	0xbbcf01b3,
+	0x12bbc800,
+/* 0x024b: mmctx_done */
+	0xbdf31bf4,
+	0x0199f094,
+	0x170007f1,
+	0xd00203f0,
+	0x04bd0009,
+/* 0x025e: strand_wait */
+	0xa0f900f8,
+	0xf402a7f0,
+	0xa0fcd021,
+/* 0x026a: strand_pre */
+	0x97f000f8,
+	0xfc07f10c,
+	0x0203f04a,
+	0xbd0009d0,
+	0x5e21f504,
+/* 0x027f: strand_post */
+	0xf000f802,
+	0x07f10d97,
+	0x03f04afc,
 	0x0009d002,
 	0x21f504bd,
-	0xe7f00221,
-	0x4721f503,
-	0xfca7f102,
-	0x02a3f046,
-	0x0400aba0,
-	0xf040a0d0,
-	0xbcd001c7,
-	0x1521f500,
-	0x010c9202,
-	0xf000acd0,
-	0xbcd002c7,
-	0x1521f500,
-	0x3421f502,
-	0x8087f102,
-	0x0684b608,
-	0xb70089cf,
-	0x95220080,
-/* 0x02ca: ctx_init_strand_loop */
+	0x00f8025e,
+/* 0x0294: strand_set */
+	0xf10fc7f0,
+	0xf04ffc07,
+	0x0cd00203,
+	0xf004bd00,
+	0x07f10bc7,
+	0x03f04afc,
+	0x000cd002,
+	0x07f104bd,
+	0x03f04ffc,
+	0x000ed002,
+	0xc7f004bd,
+	0xfc07f10a,
+	0x0203f04a,
+	0xbd000cd0,
+	0x5e21f504,
+/* 0x02d3: strand_ctx_init */
+	0xbd00f802,
+	0x0399f094,
+	0x0f0007f1,
+	0xd00203f0,
+	0x04bd0009,
+	0x026a21f5,
+	0xf503e7f0,
+	0xbd029421,
+	0xfc07f1c4,
+	0x0203f047,
+	0xbd000cd0,
+	0x01c7f004,
+	0x4afc07f1,
+	0xd00203f0,
+	0x04bd000c,
+	0x025e21f5,
+	0xf1010c92,
+	0xf046fc07,
+	0x0cd00203,
+	0xf004bd00,
+	0x07f102c7,
+	0x03f04afc,
+	0x000cd002,
+	0x21f504bd,
+	0x21f5025e,
+	0x87f1027f,
+	0x83f04200,
+	0x0097f102,
+	0x0293f020,
+	0x950099cf,
+/* 0x034a: ctx_init_strand_loop */
 	0x8ed008fe,
 	0x408ed000,
 	0xb6808acf,
@@ -428,7 +458,7 @@ uint32_t nvc0_grhub_code[] = {
 	0x170007f1,
 	0xd00203f0,
 	0x04bd0009,
-/* 0x02fe: error */
+/* 0x037e: error */
 	0x07f100f8,
 	0x03f00500,
 	0x000fd002,
@@ -436,82 +466,117 @@ uint32_t nvc0_grhub_code[] = {
 	0x0007f101,
 	0x0303f007,
 	0xbd000fd0,
-/* 0x031b: init */
+/* 0x039b: init */
 	0xbd00f804,
-	0x0004fe04,
-	0xf10007fe,
-	0xf0120017,
-	0x12d00227,
-	0xb117f100,
-	0x0010fe05,
-	0x040017f1,
-	0xf1c010d0,
-	0xb6040437,
-	0x27f10634,
-	0x32d02003,
-	0x0427f100,
-	0x0132d020,
+	0x0007fe04,
+	0x420017f1,
+	0xcf0013f0,
+	0x11e70011,
+	0x14b60109,
+	0x0014fe08,
+	0xf10227f0,
+	0xf0120007,
+	0x02d00003,
+	0xf104bd00,
+	0xfe06c817,
+	0x24bd0010,
+	0x070007f1,
+	0xd00003f0,
+	0x04bd0002,
+	0x200327f1,
+	0x010007f1,
+	0xd00103f0,
+	0x04bd0002,
+	0x200427f1,
+	0x010407f1,
+	0xd00103f0,
+	0x04bd0002,
 	0x200b27f1,
-	0xf10232d0,
-	0xd0200c27,
-	0x27f10732,
-	0x24b60c24,
-	0x0003b906,
-	0xf10023d0,
+	0x010807f1,
+	0xd00103f0,
+	0x04bd0002,
+	0x200c27f1,
+	0x011c07f1,
+	0xd00103f0,
+	0x04bd0002,
+	0xf1010392,
+	0xf0090007,
+	0x03d00303,
+	0xf104bd00,
 	0xf0870427,
-	0x12d00023,
-	0x0012b700,
-	0x0427f001,
-	0xf40012d0,
-	0xe7f11031,
-	0xe3f09604,
-	0x6821f440,
-	0x8090f1c7,
-	0xf4f00301,
-	0x020f801f,
-	0xbb0117f0,
-	0x12b6041f,
-	0x0c27f101,
-	0x0624b604,
-	0xd00021d0,
-	0x17f14021,
-	0x0e980100,
-	0x010f9800,
-	0x014721f5,
-	0x070037f1,
-	0x950634b6,
-	0x34d00814,
-	0x4034d000,
-	0x130030b7,
-	0xb6001fbb,
-	0x3fd002f5,
-	0x0815b600,
-	0xb60110b6,
-	0x1fb90814,
-	0x7121f502,
-	0x001fbb02,
-	0xf1020398,
-	0xf0200047,
-/* 0x03f6: init_gpc */
-	0x4ea05043,
-	0x1fb90804,
-	0x8d21f402,
-	0x010c4ea0,
-	0x21f4f4bd,
-	0x044ea08d,
-	0x8d21f401,
-	0x01004ea0,
-	0xf402f7f0,
-	0x4ea08d21,
-/* 0x041e: init_gpc_wait */
-	0x21f40800,
-	0x1fffc868,
-	0xa0fa0bf4,
-	0xf408044e,
-	0x1fbb6821,
-	0x0040b700,
-	0x0132b680,
-	0xf1be1bf4,
+	0x07f10023,
+	0x03f00400,
+	0x0002d000,
+	0x27f004bd,
+	0x0007f104,
+	0x0003f003,
+	0xbd0002d0,
+	0x1031f404,
+	0x9604e7f1,
+	0xf440e3f0,
+	0xfeb96821,
+	0x90f1c702,
+	0xf0030180,
+	0x0f801ff4,
+	0x0117f002,
+	0xb6041fbb,
+	0x07f10112,
+	0x03f00300,
+	0x0001d001,
+	0x07f104bd,
+	0x03f00400,
+	0x0001d001,
+	0x17f104bd,
+	0xf7f00100,
+	0xb521f502,
+	0xc721f507,
+	0x10f7f007,
+	0x081421f5,
+	0x98000e98,
+	0x21f5010f,
+	0x14950150,
+	0x0007f108,
+	0x0103f0c0,
+	0xbd0004d0,
+	0x0007f104,
+	0x0103f0c1,
+	0xbd0004d0,
+	0x0030b704,
+	0x001fbb13,
+	0xf102f5b6,
+	0xf0d30007,
+	0x0fd00103,
+	0xb604bd00,
+	0x10b60815,
+	0x0814b601,
+	0xf5021fb9,
+	0xbb02d321,
+	0x0398001f,
+	0x0047f102,
+	0x5043f020,
+/* 0x04f4: init_gpc */
+	0x08044ea0,
+	0xf4021fb9,
+	0x4ea09d21,
+	0xf4bd010c,
+	0xa09d21f4,
+	0xf401044e,
+	0x4ea09d21,
+	0xf7f00100,
+	0x9d21f402,
+	0x08004ea0,
+/* 0x051c: init_gpc_wait */
+	0xc86821f4,
+	0x0bf41fff,
+	0x044ea0fa,
+	0x6821f408,
+	0xb7001fbb,
+	0xb6800040,
+	0x1bf40132,
+	0x00f7f0be,
+	0x081421f5,
+	0xf500f7f0,
+	0xf107b521,
 	0xf0010007,
 	0x01d00203,
 	0xbd04bd00,
@@ -519,402 +584,399 @@ uint32_t nvc0_grhub_code[] = {
 	0x080007f1,
 	0xd00203f0,
 	0x04bd0001,
-/* 0x0458: main */
+/* 0x0564: main */
 	0xf40031f4,
 	0xd7f00028,
 	0x3921f410,
 	0xb1f401f4,
 	0xf54001e4,
-	0xbd00de1b,
+	0xbd00e91b,
 	0x0499f094,
 	0x0f0007f1,
 	0xd00203f0,
 	0x04bd0009,
-	0x0b0017f1,
-	0xcf0614b6,
-	0x11cf4012,
-	0x1f13c800,
-	0x00870bf5,
-	0xf41f23c8,
-	0x20f9620b,
-	0xbd0212b9,
-	0x0799f094,
-	0x0f0007f1,
-	0xd00203f0,
-	0x04bd0009,
-	0xf40132f4,
-	0x21f50231,
-	0x94bd082f,
+	0xc00017f1,
+	0xcf0213f0,
+	0x27f10011,
+	0x23f0c100,
+	0x0022cf02,
+	0xf51f13c8,
+	0xc800890b,
+	0x0bf41f23,
+	0xb920f962,
+	0x94bd0212,
 	0xf10799f0,
-	0xf0170007,
+	0xf00f0007,
 	0x09d00203,
-	0xfc04bd00,
-	0xf094bd20,
-	0x07f10699,
-	0x03f00f00,
-	0x0009d002,
-	0x31f404bd,
-	0x2f21f501,
-	0xf094bd08,
-	0x07f10699,
+	0xf404bd00,
+	0x31f40132,
+	0xe821f502,
+	0xf094bd09,
+	0x07f10799,
 	0x03f01700,
 	0x0009d002,
-	0x0ef404bd,
-/* 0x04f9: chsw_prev_no_next */
-	0xb920f931,
-	0x32f40212,
-	0x0232f401,
-	0x082f21f5,
-	0x17f120fc,
-	0x14b60b00,
-	0x0012d006,
-/* 0x0517: chsw_no_prev */
-	0xc8130ef4,
-	0x0bf41f23,
-	0x0131f40d,
-	0xf50232f4,
-/* 0x0527: chsw_done */
-	0xf1082f21,
-	0xb60b0c17,
-	0x27f00614,
-	0x0012d001,
+	0x20fc04bd,
 	0x99f094bd,
-	0x0007f104,
+	0x0007f106,
+	0x0203f00f,
+	0xbd0009d0,
+	0x0131f404,
+	0x09e821f5,
+	0x99f094bd,
+	0x0007f106,
 	0x0203f017,
 	0xbd0009d0,
-	0x130ef504,
-/* 0x0549: main_not_ctx_switch */
-	0x01e4b0ff,
-	0xb90d1bf4,
-	0x21f502f2,
-	0x0ef407bb,
-/* 0x0559: main_not_ctx_chan */
-	0x02e4b046,
-	0xbd321bf4,
-	0x0799f094,
-	0x0f0007f1,
+	0x330ef404,
+/* 0x060c: chsw_prev_no_next */
+	0x12b920f9,
+	0x0132f402,
+	0xf50232f4,
+	0xfc09e821,
+	0x0007f120,
+	0x0203f0c0,
+	0xbd0002d0,
+	0x130ef404,
+/* 0x062c: chsw_no_prev */
+	0xf41f23c8,
+	0x31f40d0b,
+	0x0232f401,
+	0x09e821f5,
+/* 0x063c: chsw_done */
+	0xf10127f0,
+	0xf0c30007,
+	0x02d00203,
+	0xbd04bd00,
+	0x0499f094,
+	0x170007f1,
 	0xd00203f0,
 	0x04bd0009,
-	0xf40132f4,
-	0x21f50232,
-	0x94bd082f,
+	0xff080ef5,
+/* 0x0660: main_not_ctx_switch */
+	0xf401e4b0,
+	0xf2b90d1b,
+	0x7821f502,
+	0x460ef409,
+/* 0x0670: main_not_ctx_chan */
+	0xf402e4b0,
+	0x94bd321b,
 	0xf10799f0,
-	0xf0170007,
+	0xf00f0007,
 	0x09d00203,
 	0xf404bd00,
-/* 0x058e: main_not_ctx_save */
-	0xef94110e,
-	0x01f5f010,
-	0x02fe21f5,
-	0xfec00ef5,
-/* 0x059c: main_done */
-	0x29f024bd,
-	0x0007f11f,
-	0x0203f008,
-	0xbd0002d0,
-	0xab0ef504,
-/* 0x05b1: ih */
-	0xfe80f9fe,
-	0x80f90188,
-	0xa0f990f9,
-	0xd0f9b0f9,
-	0xf0f9e0f9,
-	0x0acf04bd,
-	0x04abc480,
-	0xf11d0bf4,
-	0xf01900b7,
-	0xbecf10d7,
-	0x00bfcf40,
+	0x32f40132,
+	0xe821f502,
+	0xf094bd09,
+	0x07f10799,
+	0x03f01700,
+	0x0009d002,
+	0x0ef404bd,
+/* 0x06a5: main_not_ctx_save */
+	0x10ef9411,
+	0xf501f5f0,
+	0xf5037e21,
+/* 0x06b3: main_done */
+	0xbdfeb50e,
+	0x1f29f024,
+	0x080007f1,
+	0xd00203f0,
+	0x04bd0002,
+	0xfea00ef5,
+/* 0x06c8: ih */
+	0x88fe80f9,
+	0xf980f901,
+	0xf9a0f990,
+	0xf9d0f9b0,
+	0xbdf0f9e0,
+	0x00a7f104,
+	0x00a3f002,
+	0xc400aacf,
+	0x0bf404ab,
+	0x10d7f030,
+	0x1a00e7f1,
+	0xcf00e3f0,
+	0xf7f100ee,
+	0xf3f01900,
+	0x00ffcf00,
 	0xb70421f4,
 	0xf00400b0,
-	0xbed001e7,
-/* 0x05e9: ih_no_fifo */
-	0x00abe400,
-	0x0d0bf401,
-	0xf110d7f0,
-	0xf44001e7,
-/* 0x05fa: ih_no_ctxsw */
-	0xb7f10421,
-	0xb0bd0104,
-	0xf4b4abff,
-	0xa7f10d0b,
-	0xa4b60c1c,
-	0x00abd006,
-/* 0x0610: ih_no_other */
-	0xfc400ad0,
+	0x07f101e7,
+	0x03f01d00,
+	0x000ed000,
+/* 0x071a: ih_no_fifo */
+	0xabe404bd,
+	0x0bf40100,
+	0x10d7f00d,
+	0x4001e7f1,
+/* 0x072b: ih_no_ctxsw */
+	0xe40421f4,
+	0xf40400ab,
+	0xb7f1140b,
+	0xbfb90100,
+	0x44e7f102,
+	0x40e3f001,
+/* 0x0743: ih_no_fwmthd */
+	0xf19d21f4,
+	0xbd0104b7,
+	0xb4abffb0,
+	0xf10f0bf4,
+	0xf0070007,
+	0x0bd00303,
+/* 0x075b: ih_no_other */
+	0xf104bd00,
+	0xf0010007,
+	0x0ad00003,
+	0xfc04bd00,
 	0xfce0fcf0,
 	0xfcb0fcd0,
 	0xfc90fca0,
 	0x0088fe80,
 	0x32f480fc,
-/* 0x062b: ctx_4160s */
-	0xf101f800,
-	0xf04160e7,
-	0xf7f040e3,
-	0x8d21f401,
-/* 0x0638: ctx_4160s_wait */
-	0xc86821f4,
-	0x0bf404ff,
-/* 0x0643: ctx_4160c */
-	0xf100f8fa,
+/* 0x077f: ctx_4160s */
+	0xf001f800,
+	0xffb901f7,
+	0x60e7f102,
+	0x40e3f041,
+/* 0x078f: ctx_4160s_wait */
+	0xf19d21f4,
 	0xf04160e7,
-	0xf4bd40e3,
-	0xf88d21f4,
-/* 0x0651: ctx_4170s */
-	0x70e7f100,
+	0x21f440e3,
+	0x02ffb968,
+	0xf404ffc8,
+	0x00f8f00b,
+/* 0x07a4: ctx_4160c */
+	0xffb9f4bd,
+	0x60e7f102,
 	0x40e3f041,
-	0xf410f5f0,
-	0x00f88d21,
-/* 0x0660: ctx_4170w */
-	0x4170e7f1,
-	0xf440e3f0,
-	0xf4f06821,
-	0xf31bf410,
-/* 0x0672: ctx_redswitch */
-	0xe7f100f8,
-	0xe4b60614,
-	0x70f7f106,
-	0x00efd002,
-/* 0x0683: ctx_redswitch_delay */
-	0xb608f7f0,
-	0x1bf401f2,
-	0x70f7f1fd,
-	0x00efd007,
-/* 0x0692: ctx_86c */
-	0xe7f100f8,
-	0xe4b6086c,
-	0x00efd006,
-	0x8a14e7f1,
-	0xf440e3f0,
-	0xe7f18d21,
-	0xe3f0a86c,
-	0x8d21f441,
-/* 0x06b2: ctx_load */
+	0xf89d21f4,
+/* 0x07b5: ctx_4170s */
+	0x10f5f000,
+	0xf102ffb9,
+	0xf04170e7,
+	0x21f440e3,
+/* 0x07c7: ctx_4170w */
+	0xf100f89d,
+	0xf04170e7,
+	0x21f440e3,
+	0x02ffb968,
+	0xf410f4f0,
+	0x00f8f01b,
+/* 0x07dc: ctx_redswitch */
+	0x0200e7f1,
+	0xf040e5f0,
+	0xe5f020e5,
+	0x0007f110,
+	0x0103f085,
+	0xbd000ed0,
+	0x08f7f004,
+/* 0x07f8: ctx_redswitch_delay */
+	0xf401f2b6,
+	0xe5f1fd1b,
+	0xe5f10400,
+	0x07f10100,
+	0x03f08500,
+	0x000ed001,
+	0x00f804bd,
+/* 0x0814: ctx_86c */
+	0x1b0007f1,
+	0xd00203f0,
+	0x04bd000f,
+	0xf102ffb9,
+	0xf08a14e7,
+	0x21f440e3,
+	0x02ffb99d,
+	0xa86ce7f1,
+	0xf441e3f0,
+	0x00f89d21,
+/* 0x083c: ctx_mem */
+	0x840007f1,
+	0xd00203f0,
+	0x04bd000f,
+/* 0x0848: ctx_mem_wait */
+	0x8400f7f1,
+	0xcf02f3f0,
+	0xfffd00ff,
+	0xf31bf405,
+/* 0x085a: ctx_load */
 	0x94bd00f8,
 	0xf10599f0,
 	0xf00f0007,
 	0x09d00203,
 	0xf004bd00,
 	0x21f40ca7,
-	0x2417f1c9,
-	0x0614b60a,
-	0xf10010d0,
-	0xb60b0037,
-	0x32d00634,
-	0x0c17f140,
-	0x0614b60a,
-	0xd00747f0,
-	0x14d00012,
-/* 0x06ed: ctx_chan_wait_0 */
-	0x4014cf40,
-	0xf41f44f0,
-	0x32d0fa1b,
-	0x000bfe00,
-	0xb61f2af0,
-	0x20b60424,
-	0xf094bd02,
+	0xf1f4bdd0,
+	0xf0890007,
+	0x0fd00203,
+	0xf104bd00,
+	0xf0c10007,
+	0x02d00203,
+	0xf104bd00,
+	0xf0830007,
+	0x02d00203,
+	0xf004bd00,
+	0x21f507f7,
+	0x07f1083c,
+	0x03f0c000,
+	0x0002d002,
+	0x0bfe04bd,
+	0x1f2af000,
+	0xb60424b6,
+	0x94bd0220,
+	0xf10899f0,
+	0xf00f0007,
+	0x09d00203,
+	0xf104bd00,
+	0xf0810007,
+	0x02d00203,
+	0xf104bd00,
+	0xf1000027,
+	0xf0800023,
+	0x07f10225,
+	0x03f08800,
+	0x0002d002,
+	0x17f004bd,
+	0x0027f110,
+	0x0223f002,
+	0xf80512fa,
+	0xf094bd03,
 	0x07f10899,
-	0x03f00f00,
+	0x03f01700,
 	0x0009d002,
-	0x17f104bd,
-	0x14b60a04,
-	0x0012d006,
-	0x0a2017f1,
-	0xf00614b6,
-	0x23f10227,
-	0x12d08000,
-	0x1017f000,
-	0x020027f1,
-	0xfa0223f0,
-	0x03f80512,
+	0x019804bd,
+	0x1814b681,
+	0xb6800298,
+	0x12fd0825,
+	0x16018005,
 	0x99f094bd,
-	0x0007f108,
-	0x0203f017,
+	0x0007f109,
+	0x0203f00f,
 	0xbd0009d0,
-	0x81019804,
-	0x981814b6,
-	0x25b68002,
-	0x0512fd08,
-	0xbd160180,
-	0x0999f094,
-	0x0f0007f1,
-	0xd00203f0,
-	0x04bd0009,
-	0x0a0427f1,
-	0xd00624b6,
-	0x27f00021,
-	0x2017f101,
-	0x0614b60a,
-	0xf10012d0,
-	0xf0010017,
-	0x01fa0613,
-	0xbd03f805,
-	0x0999f094,
-	0x170007f1,
+	0x0007f104,
+	0x0203f081,
+	0xbd0001d0,
+	0x0127f004,
+	0x880007f1,
 	0xd00203f0,
-	0x04bd0009,
+	0x04bd0002,
+	0x010017f1,
+	0xfa0613f0,
+	0x03f80501,
 	0x99f094bd,
-	0x0007f105,
+	0x0007f109,
 	0x0203f017,
 	0xbd0009d0,
-/* 0x07bb: ctx_chan */
-	0xf500f804,
-	0xf5062b21,
-	0xf006b221,
-	0x21f40ca7,
-	0x1017f1c9,
-	0x0614b60a,
-	0xd00527f0,
-/* 0x07d6: ctx_chan_wait */
-	0x12cf0012,
-	0x0522fd00,
-	0xf5fa1bf4,
-	0xf8064321,
-/* 0x07e5: ctx_mmio_exec */
-	0x41039800,
-	0x0a0427f1,
-	0xd00624b6,
-	0x34bd0023,
-/* 0x07f4: ctx_mmio_loop */
+	0xf094bd04,
+	0x07f10599,
+	0x03f01700,
+	0x0009d002,
+	0x00f804bd,
+/* 0x0978: ctx_chan */
+	0x077f21f5,
+	0x085a21f5,
+	0xf40ca7f0,
+	0xf7f0d021,
+	0x3c21f505,
+	0xa421f508,
+/* 0x0993: ctx_mmio_exec */
+	0x9800f807,
+	0x07f14103,
+	0x03f08100,
+	0x0003d002,
+	0x34bd04bd,
+/* 0x09a4: ctx_mmio_loop */
 	0xf4ff34c4,
 	0x57f10f1b,
 	0x53f00200,
 	0x0535fa06,
-/* 0x0806: ctx_mmio_pull */
+/* 0x09b6: ctx_mmio_pull */
 	0x4e9803f8,
 	0x814f9880,
-	0xb68d21f4,
+	0xb69d21f4,
 	0x12b60830,
 	0xdf1bf401,
-/* 0x0818: ctx_mmio_done */
-	0xd0160398,
-	0x00800023,
-	0x0017f140,
-	0x0613f001,
-	0xf80601fa,
-/* 0x082f: ctx_xfer */
-	0xf100f803,
-	0xb60c00f7,
-	0xe7f006f4,
-	0x80fed004,
-/* 0x083c: ctx_xfer_idle */
-	0xf100fecf,
-	0xf42000e4,
-	0x11f4f91b,
-	0x1102f406,
-/* 0x084c: ctx_xfer_pre */
-	0xf510f7f0,
-	0xf5069221,
-	0xf4062b21,
-/* 0x085a: ctx_xfer_pre_load */
-	0xf7f01c11,
-	0x5121f502,
-	0x6021f506,
-	0x7221f506,
-	0xf5f4bd06,
-	0xf5065121,
-/* 0x0873: ctx_xfer_exec */
-	0x9806b221,
-	0x27f11601,
-	0x24b60414,
-	0x0020d006,
-	0xa500e7f1,
-	0xb941e3f0,
-	0x21f4021f,
-	0x04e0b68d,
-	0xf001fcf0,
-	0x24b6022c,
-	0x05f2fd01,
-	0xf18d21f4,
-	0xf04afc17,
-	0x27f00213,
-	0x0012d00c,
-	0x021521f5,
-	0x47fc27f1,
-	0xd00223f0,
-	0x2cf00020,
+/* 0x09c8: ctx_mmio_done */
+	0xf1160398,
+	0xf0810007,
+	0x03d00203,
+	0x8004bd00,
+	0x17f14000,
+	0x13f00100,
+	0x0601fa06,
+	0x00f803f8,
+/* 0x09e8: ctx_xfer */
+	0xf104e7f0,
+	0xf0020007,
+	0x0ed00303,
+/* 0x09f7: ctx_xfer_idle */
+	0xf104bd00,
+	0xf00000e7,
+	0xeecf03e3,
+	0x00e4f100,
+	0xf21bf420,
+	0xf40611f4,
+/* 0x0a0e: ctx_xfer_pre */
+	0xf7f01102,
+	0x1421f510,
+	0x7f21f508,
+	0x1c11f407,
+/* 0x0a1c: ctx_xfer_pre_load */
+	0xf502f7f0,
+	0xf507b521,
+	0xf507c721,
+	0xbd07dc21,
+	0xb521f5f4,
+	0x5a21f507,
+/* 0x0a35: ctx_xfer_exec */
+	0x16019808,
+	0x07f124bd,
+	0x03f00500,
+	0x0002d001,
+	0x1fb904bd,
+	0x00e7f102,
+	0x41e3f0a5,
+	0xf09d21f4,
+	0x2cf001fc,
+	0x0124b602,
+	0xb905f2fd,
+	0xe7f102ff,
+	0xe3f0a504,
+	0x9d21f441,
+	0x026a21f5,
+	0x07f124bd,
+	0x03f047fc,
+	0x0002d002,
+	0x2cf004bd,
 	0x0320b601,
-	0xf00012d0,
-	0xa5f001ac,
-	0x00b7f006,
-	0x98000c98,
-	0xe7f0010d,
-	0x6621f500,
-	0x08a7f001,
-	0x010921f5,
-	0x021521f5,
-	0xf02201f4,
-	0x21f40ca7,
-	0x1017f1c9,
-	0x0614b60a,
-	0xd00527f0,
-/* 0x08fa: ctx_xfer_post_save_wait */
-	0x12cf0012,
-	0x0522fd00,
-	0xf4fa1bf4,
-/* 0x0906: ctx_xfer_post */
-	0xf7f03202,
-	0x5121f502,
-	0xf5f4bd06,
-	0xf5069221,
-	0xf5023421,
-	0xbd066021,
-	0x5121f5f4,
-	0x1011f406,
-	0xfd400198,
-	0x0bf40511,
-	0xe521f507,
-/* 0x0931: ctx_xfer_no_post_mmio */
-	0x4321f507,
-/* 0x0935: ctx_xfer_done */
-	0x0000f806,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
+	0x4afc07f1,
+	0xd00203f0,
+	0x04bd0002,
+	0xf001acf0,
+	0xb7f006a5,
+	0x000c9800,
+	0xf0010d98,
+	0x21f500e7,
+	0xa7f0016f,
+	0x1021f508,
+	0x5e21f501,
+	0x1301f402,
+	0xf40ca7f0,
+	0xf7f0d021,
+	0x3c21f505,
+	0x3202f408,
+/* 0x0ac4: ctx_xfer_post */
+	0xf502f7f0,
+	0xbd07b521,
+	0x1421f5f4,
+	0x7f21f508,
+	0xc721f502,
+	0xf5f4bd07,
+	0xf407b521,
+	0x01981011,
+	0x0511fd40,
+	0xf5070bf4,
+/* 0x0aef: ctx_xfer_no_post_mmio */
+	0xf5099321,
+/* 0x0af3: ctx_xfer_done */
+	0xf807a421,
 	0x00000000,
 	0x00000000,
 	0x00000000,
diff --git a/drivers/gpu/drm/nouveau/core/engine/graph/fuc/hubnvd7.fuc.h b/drivers/gpu/drm/nouveau/core/engine/graph/fuc/hubnvd7.fuc.h
index a1b9f763996a3..84af824189876 100644
--- a/drivers/gpu/drm/nouveau/core/engine/graph/fuc/hubnvd7.fuc.h
+++ b/drivers/gpu/drm/nouveau/core/engine/graph/fuc/hubnvd7.fuc.h
@@ -206,14 +206,14 @@ uint32_t nvd7_grhub_data[] = {
 };
 
 uint32_t nvd7_grhub_code[] = {
-	0x031b0ef5,
+	0x039b0ef5,
 /* 0x0004: queue_put */
 	0x9800d898,
 	0x86f001d9,
 	0x0489b808,
 	0xf00c1bf4,
 	0x21f502f7,
-	0x00f802fe,
+	0x00f8037e,
 /* 0x001c: queue_put_next */
 	0xb60798c4,
 	0x8dbb0384,
@@ -237,184 +237,214 @@ uint32_t nvd7_grhub_code[] = {
 /* 0x0066: queue_get_done */
 	0x00f80132,
 /* 0x0068: nv_rd32 */
-	0x0728b7f1,
-	0xb906b4b6,
-	0xc9f002ec,
-	0x00bcd01f,
-/* 0x0078: nv_rd32_wait */
-	0xc800bccf,
-	0x1bf41fcc,
-	0x06a7f0fa,
-	0x010921f5,
-	0xf840bfcf,
-/* 0x008d: nv_wr32 */
-	0x28b7f100,
-	0x06b4b607,
-	0xb980bfd0,
-	0xc9f002ec,
-	0x1ec9f01f,
-/* 0x00a3: nv_wr32_wait */
-	0xcf00bcd0,
-	0xccc800bc,
-	0xfa1bf41f,
-/* 0x00ae: watchdog_reset */
-	0x87f100f8,
-	0x84b60430,
-	0x1ff9f006,
-	0xf8008fd0,
-/* 0x00bd: watchdog_clear */
-	0x3087f100,
-	0x0684b604,
-	0xf80080d0,
-/* 0x00c9: wait_donez */
-	0xf094bd00,
-	0x07f10099,
-	0x03f00f00,
-	0x0009d002,
-	0x07f104bd,
-	0x03f00600,
-	0x000ad002,
-/* 0x00e6: wait_donez_ne */
-	0x87f104bd,
-	0x83f00000,
-	0x0088cf01,
-	0xf4888aff,
-	0x94bdf31b,
-	0xf10099f0,
-	0xf0170007,
-	0x09d00203,
-	0xf804bd00,
-/* 0x0109: wait_doneo */
-	0xf094bd00,
+	0xf002ecb9,
+	0x07f11fc9,
+	0x03f0ca00,
+	0x000cd001,
+/* 0x007a: nv_rd32_wait */
+	0xc7f104bd,
+	0xc3f0ca00,
+	0x00cccf01,
+	0xf41fccc8,
+	0xa7f0f31b,
+	0x1021f506,
+	0x00f7f101,
+	0x01f3f0cb,
+	0xf800ffcf,
+/* 0x009d: nv_wr32 */
+	0x0007f100,
+	0x0103f0cc,
+	0xbd000fd0,
+	0x02ecb904,
+	0xf01fc9f0,
+	0x07f11ec9,
+	0x03f0ca00,
+	0x000cd001,
+/* 0x00be: nv_wr32_wait */
+	0xc7f104bd,
+	0xc3f0ca00,
+	0x00cccf01,
+	0xf41fccc8,
+	0x00f8f31b,
+/* 0x00d0: wait_donez */
+	0x99f094bd,
+	0x0007f100,
+	0x0203f00f,
+	0xbd0009d0,
+	0x0007f104,
+	0x0203f006,
+	0xbd000ad0,
+/* 0x00ed: wait_donez_ne */
+	0x0087f104,
+	0x0183f000,
+	0xff0088cf,
+	0x1bf4888a,
+	0xf094bdf3,
 	0x07f10099,
-	0x03f00f00,
+	0x03f01700,
 	0x0009d002,
-	0x87f104bd,
-	0x84b60818,
-	0x008ad006,
-/* 0x0124: wait_doneo_e */
-	0x040087f1,
-	0xcf0684b6,
-	0x8aff0088,
-	0xf30bf488,
+	0x00f804bd,
+/* 0x0110: wait_doneo */
 	0x99f094bd,
 	0x0007f100,
-	0x0203f017,
+	0x0203f00f,
 	0xbd0009d0,
-/* 0x0147: mmctx_size */
-	0xbd00f804,
-/* 0x0149: nv_mmctx_size_loop */
-	0x00e89894,
-	0xb61a85b6,
-	0x84b60180,
-	0x0098bb02,
-	0xb804e0b6,
-	0x1bf404ef,
-	0x029fb9eb,
-/* 0x0166: mmctx_xfer */
-	0x94bd00f8,
-	0xf10199f0,
-	0xf00f0007,
-	0x09d00203,
-	0xf104bd00,
-	0xb6071087,
-	0x94bd0684,
-	0xf405bbfd,
-	0x8bd0090b,
-	0x0099f000,
-/* 0x018c: mmctx_base_disabled */
-	0xf405eefd,
-	0x8ed00c0b,
-	0xc08fd080,
-/* 0x019b: mmctx_multi_disabled */
-	0xb70199f0,
-	0xc8010080,
+	0x0007f104,
+	0x0203f006,
+	0xbd000ad0,
+/* 0x012d: wait_doneo_e */
+	0x0087f104,
+	0x0183f000,
+	0xff0088cf,
+	0x0bf4888a,
+	0xf094bdf3,
+	0x07f10099,
+	0x03f01700,
+	0x0009d002,
+	0x00f804bd,
+/* 0x0150: mmctx_size */
+/* 0x0152: nv_mmctx_size_loop */
+	0xe89894bd,
+	0x1a85b600,
+	0xb60180b6,
+	0x98bb0284,
+	0x04e0b600,
+	0xf404efb8,
+	0x9fb9eb1b,
+/* 0x016f: mmctx_xfer */
+	0xbd00f802,
+	0x0199f094,
+	0x0f0007f1,
+	0xd00203f0,
+	0x04bd0009,
+	0xbbfd94bd,
+	0x120bf405,
+	0xc40007f1,
+	0xd00103f0,
+	0x04bd000b,
+/* 0x0197: mmctx_base_disabled */
+	0xfd0099f0,
+	0x0bf405ee,
+	0x0007f11e,
+	0x0103f0c6,
+	0xbd000ed0,
+	0x0007f104,
+	0x0103f0c7,
+	0xbd000fd0,
+	0x0199f004,
+/* 0x01b8: mmctx_multi_disabled */
+	0xb600abc8,
+	0xb9f010b4,
+	0x01aec80c,
+	0xfd11e4b6,
+	0x07f105be,
+	0x03f0c500,
+	0x000bd001,
+/* 0x01d6: mmctx_exec_loop */
+/* 0x01d6: mmctx_wait_free */
+	0xe7f104bd,
+	0xe3f0c500,
+	0x00eecf01,
+	0xf41fe4f0,
+	0xce98f30b,
+	0x05e9fd00,
+	0xc80007f1,
+	0xd00103f0,
+	0x04bd000e,
+	0xb804c0b6,
+	0x1bf404cd,
+	0x02abc8d8,
+/* 0x0207: mmctx_fini_wait */
+	0xf11f1bf4,
+	0xf0c500b7,
+	0xbbcf01b3,
+	0x1fb4f000,
+	0xf410b4b0,
+	0xa7f0f01b,
+	0xd021f402,
+/* 0x0223: mmctx_stop */
+	0xc82b0ef4,
 	0xb4b600ab,
 	0x0cb9f010,
-	0xb601aec8,
-	0xbefd11e4,
-	0x008bd005,
-/* 0x01b4: mmctx_exec_loop */
-/* 0x01b4: mmctx_wait_free */
-	0xf0008ecf,
-	0x0bf41fe4,
-	0x00ce98fa,
-	0xd005e9fd,
-	0xc0b6c08e,
-	0x04cdb804,
-	0xc8e81bf4,
-	0x1bf402ab,
-/* 0x01d5: mmctx_fini_wait */
-	0x008bcf18,
-	0xb01fb4f0,
-	0x1bf410b4,
-	0x02a7f0f7,
-	0xf4c921f4,
-/* 0x01ea: mmctx_stop */
-	0xabc81b0e,
-	0x10b4b600,
-	0xf00cb9f0,
-	0x8bd012b9,
-/* 0x01f9: mmctx_stop_wait */
-	0x008bcf00,
-	0xf412bbc8,
-/* 0x0202: mmctx_done */
-	0x94bdfa1b,
-	0xf10199f0,
-	0xf0170007,
-	0x09d00203,
-	0xf804bd00,
-/* 0x0215: strand_wait */
-	0xf0a0f900,
-	0x21f402a7,
-	0xf8a0fcc9,
-/* 0x0221: strand_pre */
-	0xfc87f100,
-	0x0283f04a,
-	0xd00c97f0,
-	0x21f50089,
-	0x00f80215,
-/* 0x0234: strand_post */
-	0x4afc87f1,
-	0xf00283f0,
-	0x89d00d97,
-	0x1521f500,
-/* 0x0247: strand_set */
-	0xf100f802,
-	0xf04ffca7,
-	0xaba202a3,
-	0xc7f00500,
-	0x00acd00f,
-	0xd00bc7f0,
-	0x21f500bc,
-	0xaed00215,
-	0x0ac7f000,
-	0xf500bcd0,
-	0xf8021521,
-/* 0x0271: strand_ctx_init */
-	0xf094bd00,
-	0x07f10399,
-	0x03f00f00,
+	0xf112b9f0,
+	0xf0c50007,
+	0x0bd00103,
+/* 0x023b: mmctx_stop_wait */
+	0xf104bd00,
+	0xf0c500b7,
+	0xbbcf01b3,
+	0x12bbc800,
+/* 0x024b: mmctx_done */
+	0xbdf31bf4,
+	0x0199f094,
+	0x170007f1,
+	0xd00203f0,
+	0x04bd0009,
+/* 0x025e: strand_wait */
+	0xa0f900f8,
+	0xf402a7f0,
+	0xa0fcd021,
+/* 0x026a: strand_pre */
+	0x97f000f8,
+	0xfc07f10c,
+	0x0203f04a,
+	0xbd0009d0,
+	0x5e21f504,
+/* 0x027f: strand_post */
+	0xf000f802,
+	0x07f10d97,
+	0x03f04afc,
 	0x0009d002,
 	0x21f504bd,
-	0xe7f00221,
-	0x4721f503,
-	0xfca7f102,
-	0x02a3f046,
-	0x0400aba0,
-	0xf040a0d0,
-	0xbcd001c7,
-	0x1521f500,
-	0x010c9202,
-	0xf000acd0,
-	0xbcd002c7,
-	0x1521f500,
-	0x3421f502,
-	0x8087f102,
-	0x0684b608,
-	0xb70089cf,
-	0x95220080,
-/* 0x02ca: ctx_init_strand_loop */
+	0x00f8025e,
+/* 0x0294: strand_set */
+	0xf10fc7f0,
+	0xf04ffc07,
+	0x0cd00203,
+	0xf004bd00,
+	0x07f10bc7,
+	0x03f04afc,
+	0x000cd002,
+	0x07f104bd,
+	0x03f04ffc,
+	0x000ed002,
+	0xc7f004bd,
+	0xfc07f10a,
+	0x0203f04a,
+	0xbd000cd0,
+	0x5e21f504,
+/* 0x02d3: strand_ctx_init */
+	0xbd00f802,
+	0x0399f094,
+	0x0f0007f1,
+	0xd00203f0,
+	0x04bd0009,
+	0x026a21f5,
+	0xf503e7f0,
+	0xbd029421,
+	0xfc07f1c4,
+	0x0203f047,
+	0xbd000cd0,
+	0x01c7f004,
+	0x4afc07f1,
+	0xd00203f0,
+	0x04bd000c,
+	0x025e21f5,
+	0xf1010c92,
+	0xf046fc07,
+	0x0cd00203,
+	0xf004bd00,
+	0x07f102c7,
+	0x03f04afc,
+	0x000cd002,
+	0x21f504bd,
+	0x21f5025e,
+	0x87f1027f,
+	0x83f04200,
+	0x0097f102,
+	0x0293f020,
+	0x950099cf,
+/* 0x034a: ctx_init_strand_loop */
 	0x8ed008fe,
 	0x408ed000,
 	0xb6808acf,
@@ -428,7 +458,7 @@ uint32_t nvd7_grhub_code[] = {
 	0x170007f1,
 	0xd00203f0,
 	0x04bd0009,
-/* 0x02fe: error */
+/* 0x037e: error */
 	0x07f100f8,
 	0x03f00500,
 	0x000fd002,
@@ -436,82 +466,117 @@ uint32_t nvd7_grhub_code[] = {
 	0x0007f101,
 	0x0303f007,
 	0xbd000fd0,
-/* 0x031b: init */
+/* 0x039b: init */
 	0xbd00f804,
-	0x0004fe04,
-	0xf10007fe,
-	0xf0120017,
-	0x12d00227,
-	0xb117f100,
-	0x0010fe05,
-	0x040017f1,
-	0xf1c010d0,
-	0xb6040437,
-	0x27f10634,
-	0x32d02003,
-	0x0427f100,
-	0x0132d020,
+	0x0007fe04,
+	0x420017f1,
+	0xcf0013f0,
+	0x11e70011,
+	0x14b60109,
+	0x0014fe08,
+	0xf10227f0,
+	0xf0120007,
+	0x02d00003,
+	0xf104bd00,
+	0xfe06c817,
+	0x24bd0010,
+	0x070007f1,
+	0xd00003f0,
+	0x04bd0002,
+	0x200327f1,
+	0x010007f1,
+	0xd00103f0,
+	0x04bd0002,
+	0x200427f1,
+	0x010407f1,
+	0xd00103f0,
+	0x04bd0002,
 	0x200b27f1,
-	0xf10232d0,
-	0xd0200c27,
-	0x27f10732,
-	0x24b60c24,
-	0x0003b906,
-	0xf10023d0,
+	0x010807f1,
+	0xd00103f0,
+	0x04bd0002,
+	0x200c27f1,
+	0x011c07f1,
+	0xd00103f0,
+	0x04bd0002,
+	0xf1010392,
+	0xf0090007,
+	0x03d00303,
+	0xf104bd00,
 	0xf0870427,
-	0x12d00023,
-	0x0012b700,
-	0x0427f001,
-	0xf40012d0,
-	0xe7f11031,
-	0xe3f09604,
-	0x6821f440,
-	0x8090f1c7,
-	0xf4f00301,
-	0x020f801f,
-	0xbb0117f0,
-	0x12b6041f,
-	0x0c27f101,
-	0x0624b604,
-	0xd00021d0,
-	0x17f14021,
-	0x0e980100,
-	0x010f9800,
-	0x014721f5,
-	0x070037f1,
-	0x950634b6,
-	0x34d00814,
-	0x4034d000,
-	0x130030b7,
-	0xb6001fbb,
-	0x3fd002f5,
-	0x0815b600,
-	0xb60110b6,
-	0x1fb90814,
-	0x7121f502,
-	0x001fbb02,
-	0xf1020398,
-	0xf0200047,
-/* 0x03f6: init_gpc */
-	0x4ea05043,
-	0x1fb90804,
-	0x8d21f402,
-	0x010c4ea0,
-	0x21f4f4bd,
-	0x044ea08d,
-	0x8d21f401,
-	0x01004ea0,
-	0xf402f7f0,
-	0x4ea08d21,
-/* 0x041e: init_gpc_wait */
-	0x21f40800,
-	0x1fffc868,
-	0xa0fa0bf4,
-	0xf408044e,
-	0x1fbb6821,
-	0x0040b700,
-	0x0132b680,
-	0xf1be1bf4,
+	0x07f10023,
+	0x03f00400,
+	0x0002d000,
+	0x27f004bd,
+	0x0007f104,
+	0x0003f003,
+	0xbd0002d0,
+	0x1031f404,
+	0x9604e7f1,
+	0xf440e3f0,
+	0xfeb96821,
+	0x90f1c702,
+	0xf0030180,
+	0x0f801ff4,
+	0x0117f002,
+	0xb6041fbb,
+	0x07f10112,
+	0x03f00300,
+	0x0001d001,
+	0x07f104bd,
+	0x03f00400,
+	0x0001d001,
+	0x17f104bd,
+	0xf7f00100,
+	0xb521f502,
+	0xc721f507,
+	0x10f7f007,
+	0x081421f5,
+	0x98000e98,
+	0x21f5010f,
+	0x14950150,
+	0x0007f108,
+	0x0103f0c0,
+	0xbd0004d0,
+	0x0007f104,
+	0x0103f0c1,
+	0xbd0004d0,
+	0x0030b704,
+	0x001fbb13,
+	0xf102f5b6,
+	0xf0d30007,
+	0x0fd00103,
+	0xb604bd00,
+	0x10b60815,
+	0x0814b601,
+	0xf5021fb9,
+	0xbb02d321,
+	0x0398001f,
+	0x0047f102,
+	0x5043f020,
+/* 0x04f4: init_gpc */
+	0x08044ea0,
+	0xf4021fb9,
+	0x4ea09d21,
+	0xf4bd010c,
+	0xa09d21f4,
+	0xf401044e,
+	0x4ea09d21,
+	0xf7f00100,
+	0x9d21f402,
+	0x08004ea0,
+/* 0x051c: init_gpc_wait */
+	0xc86821f4,
+	0x0bf41fff,
+	0x044ea0fa,
+	0x6821f408,
+	0xb7001fbb,
+	0xb6800040,
+	0x1bf40132,
+	0x00f7f0be,
+	0x081421f5,
+	0xf500f7f0,
+	0xf107b521,
 	0xf0010007,
 	0x01d00203,
 	0xbd04bd00,
@@ -519,402 +584,399 @@ uint32_t nvd7_grhub_code[] = {
 	0x080007f1,
 	0xd00203f0,
 	0x04bd0001,
-/* 0x0458: main */
+/* 0x0564: main */
 	0xf40031f4,
 	0xd7f00028,
 	0x3921f410,
 	0xb1f401f4,
 	0xf54001e4,
-	0xbd00de1b,
+	0xbd00e91b,
 	0x0499f094,
 	0x0f0007f1,
 	0xd00203f0,
 	0x04bd0009,
-	0x0b0017f1,
-	0xcf0614b6,
-	0x11cf4012,
-	0x1f13c800,
-	0x00870bf5,
-	0xf41f23c8,
-	0x20f9620b,
-	0xbd0212b9,
-	0x0799f094,
-	0x0f0007f1,
-	0xd00203f0,
-	0x04bd0009,
-	0xf40132f4,
-	0x21f50231,
-	0x94bd082f,
+	0xc00017f1,
+	0xcf0213f0,
+	0x27f10011,
+	0x23f0c100,
+	0x0022cf02,
+	0xf51f13c8,
+	0xc800890b,
+	0x0bf41f23,
+	0xb920f962,
+	0x94bd0212,
 	0xf10799f0,
-	0xf0170007,
+	0xf00f0007,
 	0x09d00203,
-	0xfc04bd00,
-	0xf094bd20,
-	0x07f10699,
-	0x03f00f00,
-	0x0009d002,
-	0x31f404bd,
-	0x2f21f501,
-	0xf094bd08,
-	0x07f10699,
+	0xf404bd00,
+	0x31f40132,
+	0xe821f502,
+	0xf094bd09,
+	0x07f10799,
 	0x03f01700,
 	0x0009d002,
-	0x0ef404bd,
-/* 0x04f9: chsw_prev_no_next */
-	0xb920f931,
-	0x32f40212,
-	0x0232f401,
-	0x082f21f5,
-	0x17f120fc,
-	0x14b60b00,
-	0x0012d006,
-/* 0x0517: chsw_no_prev */
-	0xc8130ef4,
-	0x0bf41f23,
-	0x0131f40d,
-	0xf50232f4,
-/* 0x0527: chsw_done */
-	0xf1082f21,
-	0xb60b0c17,
-	0x27f00614,
-	0x0012d001,
+	0x20fc04bd,
 	0x99f094bd,
-	0x0007f104,
+	0x0007f106,
+	0x0203f00f,
+	0xbd0009d0,
+	0x0131f404,
+	0x09e821f5,
+	0x99f094bd,
+	0x0007f106,
 	0x0203f017,
 	0xbd0009d0,
-	0x130ef504,
-/* 0x0549: main_not_ctx_switch */
-	0x01e4b0ff,
-	0xb90d1bf4,
-	0x21f502f2,
-	0x0ef407bb,
-/* 0x0559: main_not_ctx_chan */
-	0x02e4b046,
-	0xbd321bf4,
-	0x0799f094,
-	0x0f0007f1,
+	0x330ef404,
+/* 0x060c: chsw_prev_no_next */
+	0x12b920f9,
+	0x0132f402,
+	0xf50232f4,
+	0xfc09e821,
+	0x0007f120,
+	0x0203f0c0,
+	0xbd0002d0,
+	0x130ef404,
+/* 0x062c: chsw_no_prev */
+	0xf41f23c8,
+	0x31f40d0b,
+	0x0232f401,
+	0x09e821f5,
+/* 0x063c: chsw_done */
+	0xf10127f0,
+	0xf0c30007,
+	0x02d00203,
+	0xbd04bd00,
+	0x0499f094,
+	0x170007f1,
 	0xd00203f0,
 	0x04bd0009,
-	0xf40132f4,
-	0x21f50232,
-	0x94bd082f,
+	0xff080ef5,
+/* 0x0660: main_not_ctx_switch */
+	0xf401e4b0,
+	0xf2b90d1b,
+	0x7821f502,
+	0x460ef409,
+/* 0x0670: main_not_ctx_chan */
+	0xf402e4b0,
+	0x94bd321b,
 	0xf10799f0,
-	0xf0170007,
+	0xf00f0007,
 	0x09d00203,
 	0xf404bd00,
-/* 0x058e: main_not_ctx_save */
-	0xef94110e,
-	0x01f5f010,
-	0x02fe21f5,
-	0xfec00ef5,
-/* 0x059c: main_done */
-	0x29f024bd,
-	0x0007f11f,
-	0x0203f008,
-	0xbd0002d0,
-	0xab0ef504,
-/* 0x05b1: ih */
-	0xfe80f9fe,
-	0x80f90188,
-	0xa0f990f9,
-	0xd0f9b0f9,
-	0xf0f9e0f9,
-	0x0acf04bd,
-	0x04abc480,
-	0xf11d0bf4,
-	0xf01900b7,
-	0xbecf10d7,
-	0x00bfcf40,
+	0x32f40132,
+	0xe821f502,
+	0xf094bd09,
+	0x07f10799,
+	0x03f01700,
+	0x0009d002,
+	0x0ef404bd,
+/* 0x06a5: main_not_ctx_save */
+	0x10ef9411,
+	0xf501f5f0,
+	0xf5037e21,
+/* 0x06b3: main_done */
+	0xbdfeb50e,
+	0x1f29f024,
+	0x080007f1,
+	0xd00203f0,
+	0x04bd0002,
+	0xfea00ef5,
+/* 0x06c8: ih */
+	0x88fe80f9,
+	0xf980f901,
+	0xf9a0f990,
+	0xf9d0f9b0,
+	0xbdf0f9e0,
+	0x00a7f104,
+	0x00a3f002,
+	0xc400aacf,
+	0x0bf404ab,
+	0x10d7f030,
+	0x1a00e7f1,
+	0xcf00e3f0,
+	0xf7f100ee,
+	0xf3f01900,
+	0x00ffcf00,
 	0xb70421f4,
 	0xf00400b0,
-	0xbed001e7,
-/* 0x05e9: ih_no_fifo */
-	0x00abe400,
-	0x0d0bf401,
-	0xf110d7f0,
-	0xf44001e7,
-/* 0x05fa: ih_no_ctxsw */
-	0xb7f10421,
-	0xb0bd0104,
-	0xf4b4abff,
-	0xa7f10d0b,
-	0xa4b60c1c,
-	0x00abd006,
-/* 0x0610: ih_no_other */
-	0xfc400ad0,
+	0x07f101e7,
+	0x03f01d00,
+	0x000ed000,
+/* 0x071a: ih_no_fifo */
+	0xabe404bd,
+	0x0bf40100,
+	0x10d7f00d,
+	0x4001e7f1,
+/* 0x072b: ih_no_ctxsw */
+	0xe40421f4,
+	0xf40400ab,
+	0xb7f1140b,
+	0xbfb90100,
+	0x44e7f102,
+	0x40e3f001,
+/* 0x0743: ih_no_fwmthd */
+	0xf19d21f4,
+	0xbd0104b7,
+	0xb4abffb0,
+	0xf10f0bf4,
+	0xf0070007,
+	0x0bd00303,
+/* 0x075b: ih_no_other */
+	0xf104bd00,
+	0xf0010007,
+	0x0ad00003,
+	0xfc04bd00,
 	0xfce0fcf0,
 	0xfcb0fcd0,
 	0xfc90fca0,
 	0x0088fe80,
 	0x32f480fc,
-/* 0x062b: ctx_4160s */
-	0xf101f800,
-	0xf04160e7,
-	0xf7f040e3,
-	0x8d21f401,
-/* 0x0638: ctx_4160s_wait */
-	0xc86821f4,
-	0x0bf404ff,
-/* 0x0643: ctx_4160c */
-	0xf100f8fa,
+/* 0x077f: ctx_4160s */
+	0xf001f800,
+	0xffb901f7,
+	0x60e7f102,
+	0x40e3f041,
+/* 0x078f: ctx_4160s_wait */
+	0xf19d21f4,
 	0xf04160e7,
-	0xf4bd40e3,
-	0xf88d21f4,
-/* 0x0651: ctx_4170s */
-	0x70e7f100,
+	0x21f440e3,
+	0x02ffb968,
+	0xf404ffc8,
+	0x00f8f00b,
+/* 0x07a4: ctx_4160c */
+	0xffb9f4bd,
+	0x60e7f102,
 	0x40e3f041,
-	0xf410f5f0,
-	0x00f88d21,
-/* 0x0660: ctx_4170w */
-	0x4170e7f1,
-	0xf440e3f0,
-	0xf4f06821,
-	0xf31bf410,
-/* 0x0672: ctx_redswitch */
-	0xe7f100f8,
-	0xe4b60614,
-	0x70f7f106,
-	0x00efd002,
-/* 0x0683: ctx_redswitch_delay */
-	0xb608f7f0,
-	0x1bf401f2,
-	0x70f7f1fd,
-	0x00efd007,
-/* 0x0692: ctx_86c */
-	0xe7f100f8,
-	0xe4b6086c,
-	0x00efd006,
-	0x8a14e7f1,
-	0xf440e3f0,
-	0xe7f18d21,
-	0xe3f0a86c,
-	0x8d21f441,
-/* 0x06b2: ctx_load */
+	0xf89d21f4,
+/* 0x07b5: ctx_4170s */
+	0x10f5f000,
+	0xf102ffb9,
+	0xf04170e7,
+	0x21f440e3,
+/* 0x07c7: ctx_4170w */
+	0xf100f89d,
+	0xf04170e7,
+	0x21f440e3,
+	0x02ffb968,
+	0xf410f4f0,
+	0x00f8f01b,
+/* 0x07dc: ctx_redswitch */
+	0x0200e7f1,
+	0xf040e5f0,
+	0xe5f020e5,
+	0x0007f110,
+	0x0103f085,
+	0xbd000ed0,
+	0x08f7f004,
+/* 0x07f8: ctx_redswitch_delay */
+	0xf401f2b6,
+	0xe5f1fd1b,
+	0xe5f10400,
+	0x07f10100,
+	0x03f08500,
+	0x000ed001,
+	0x00f804bd,
+/* 0x0814: ctx_86c */
+	0x1b0007f1,
+	0xd00203f0,
+	0x04bd000f,
+	0xf102ffb9,
+	0xf08a14e7,
+	0x21f440e3,
+	0x02ffb99d,
+	0xa86ce7f1,
+	0xf441e3f0,
+	0x00f89d21,
+/* 0x083c: ctx_mem */
+	0x840007f1,
+	0xd00203f0,
+	0x04bd000f,
+/* 0x0848: ctx_mem_wait */
+	0x8400f7f1,
+	0xcf02f3f0,
+	0xfffd00ff,
+	0xf31bf405,
+/* 0x085a: ctx_load */
 	0x94bd00f8,
 	0xf10599f0,
 	0xf00f0007,
 	0x09d00203,
 	0xf004bd00,
 	0x21f40ca7,
-	0x2417f1c9,
-	0x0614b60a,
-	0xf10010d0,
-	0xb60b0037,
-	0x32d00634,
-	0x0c17f140,
-	0x0614b60a,
-	0xd00747f0,
-	0x14d00012,
-/* 0x06ed: ctx_chan_wait_0 */
-	0x4014cf40,
-	0xf41f44f0,
-	0x32d0fa1b,
-	0x000bfe00,
-	0xb61f2af0,
-	0x20b60424,
-	0xf094bd02,
+	0xf1f4bdd0,
+	0xf0890007,
+	0x0fd00203,
+	0xf104bd00,
+	0xf0c10007,
+	0x02d00203,
+	0xf104bd00,
+	0xf0830007,
+	0x02d00203,
+	0xf004bd00,
+	0x21f507f7,
+	0x07f1083c,
+	0x03f0c000,
+	0x0002d002,
+	0x0bfe04bd,
+	0x1f2af000,
+	0xb60424b6,
+	0x94bd0220,
+	0xf10899f0,
+	0xf00f0007,
+	0x09d00203,
+	0xf104bd00,
+	0xf0810007,
+	0x02d00203,
+	0xf104bd00,
+	0xf1000027,
+	0xf0800023,
+	0x07f10225,
+	0x03f08800,
+	0x0002d002,
+	0x17f004bd,
+	0x0027f110,
+	0x0223f002,
+	0xf80512fa,
+	0xf094bd03,
 	0x07f10899,
-	0x03f00f00,
+	0x03f01700,
 	0x0009d002,
-	0x17f104bd,
-	0x14b60a04,
-	0x0012d006,
-	0x0a2017f1,
-	0xf00614b6,
-	0x23f10227,
-	0x12d08000,
-	0x1017f000,
-	0x020027f1,
-	0xfa0223f0,
-	0x03f80512,
+	0x019804bd,
+	0x1814b681,
+	0xb6800298,
+	0x12fd0825,
+	0x16018005,
 	0x99f094bd,
-	0x0007f108,
-	0x0203f017,
+	0x0007f109,
+	0x0203f00f,
 	0xbd0009d0,
-	0x81019804,
-	0x981814b6,
-	0x25b68002,
-	0x0512fd08,
-	0xbd160180,
-	0x0999f094,
-	0x0f0007f1,
-	0xd00203f0,
-	0x04bd0009,
-	0x0a0427f1,
-	0xd00624b6,
-	0x27f00021,
-	0x2017f101,
-	0x0614b60a,
-	0xf10012d0,
-	0xf0010017,
-	0x01fa0613,
-	0xbd03f805,
-	0x0999f094,
-	0x170007f1,
+	0x0007f104,
+	0x0203f081,
+	0xbd0001d0,
+	0x0127f004,
+	0x880007f1,
 	0xd00203f0,
-	0x04bd0009,
+	0x04bd0002,
+	0x010017f1,
+	0xfa0613f0,
+	0x03f80501,
 	0x99f094bd,
-	0x0007f105,
+	0x0007f109,
 	0x0203f017,
 	0xbd0009d0,
-/* 0x07bb: ctx_chan */
-	0xf500f804,
-	0xf5062b21,
-	0xf006b221,
-	0x21f40ca7,
-	0x1017f1c9,
-	0x0614b60a,
-	0xd00527f0,
-/* 0x07d6: ctx_chan_wait */
-	0x12cf0012,
-	0x0522fd00,
-	0xf5fa1bf4,
-	0xf8064321,
-/* 0x07e5: ctx_mmio_exec */
-	0x41039800,
-	0x0a0427f1,
-	0xd00624b6,
-	0x34bd0023,
-/* 0x07f4: ctx_mmio_loop */
+	0xf094bd04,
+	0x07f10599,
+	0x03f01700,
+	0x0009d002,
+	0x00f804bd,
+/* 0x0978: ctx_chan */
+	0x077f21f5,
+	0x085a21f5,
+	0xf40ca7f0,
+	0xf7f0d021,
+	0x3c21f505,
+	0xa421f508,
+/* 0x0993: ctx_mmio_exec */
+	0x9800f807,
+	0x07f14103,
+	0x03f08100,
+	0x0003d002,
+	0x34bd04bd,
+/* 0x09a4: ctx_mmio_loop */
 	0xf4ff34c4,
 	0x57f10f1b,
 	0x53f00200,
 	0x0535fa06,
-/* 0x0806: ctx_mmio_pull */
+/* 0x09b6: ctx_mmio_pull */
 	0x4e9803f8,
 	0x814f9880,
-	0xb68d21f4,
+	0xb69d21f4,
 	0x12b60830,
 	0xdf1bf401,
-/* 0x0818: ctx_mmio_done */
-	0xd0160398,
-	0x00800023,
-	0x0017f140,
-	0x0613f001,
-	0xf80601fa,
-/* 0x082f: ctx_xfer */
-	0xf100f803,
-	0xb60c00f7,
-	0xe7f006f4,
-	0x80fed004,
-/* 0x083c: ctx_xfer_idle */
-	0xf100fecf,
-	0xf42000e4,
-	0x11f4f91b,
-	0x1102f406,
-/* 0x084c: ctx_xfer_pre */
-	0xf510f7f0,
-	0xf5069221,
-	0xf4062b21,
-/* 0x085a: ctx_xfer_pre_load */
-	0xf7f01c11,
-	0x5121f502,
-	0x6021f506,
-	0x7221f506,
-	0xf5f4bd06,
-	0xf5065121,
-/* 0x0873: ctx_xfer_exec */
-	0x9806b221,
-	0x27f11601,
-	0x24b60414,
-	0x0020d006,
-	0xa500e7f1,
-	0xb941e3f0,
-	0x21f4021f,
-	0x04e0b68d,
-	0xf001fcf0,
-	0x24b6022c,
-	0x05f2fd01,
-	0xf18d21f4,
-	0xf04afc17,
-	0x27f00213,
-	0x0012d00c,
-	0x021521f5,
-	0x47fc27f1,
-	0xd00223f0,
-	0x2cf00020,
+/* 0x09c8: ctx_mmio_done */
+	0xf1160398,
+	0xf0810007,
+	0x03d00203,
+	0x8004bd00,
+	0x17f14000,
+	0x13f00100,
+	0x0601fa06,
+	0x00f803f8,
+/* 0x09e8: ctx_xfer */
+	0xf104e7f0,
+	0xf0020007,
+	0x0ed00303,
+/* 0x09f7: ctx_xfer_idle */
+	0xf104bd00,
+	0xf00000e7,
+	0xeecf03e3,
+	0x00e4f100,
+	0xf21bf420,
+	0xf40611f4,
+/* 0x0a0e: ctx_xfer_pre */
+	0xf7f01102,
+	0x1421f510,
+	0x7f21f508,
+	0x1c11f407,
+/* 0x0a1c: ctx_xfer_pre_load */
+	0xf502f7f0,
+	0xf507b521,
+	0xf507c721,
+	0xbd07dc21,
+	0xb521f5f4,
+	0x5a21f507,
+/* 0x0a35: ctx_xfer_exec */
+	0x16019808,
+	0x07f124bd,
+	0x03f00500,
+	0x0002d001,
+	0x1fb904bd,
+	0x00e7f102,
+	0x41e3f0a5,
+	0xf09d21f4,
+	0x2cf001fc,
+	0x0124b602,
+	0xb905f2fd,
+	0xe7f102ff,
+	0xe3f0a504,
+	0x9d21f441,
+	0x026a21f5,
+	0x07f124bd,
+	0x03f047fc,
+	0x0002d002,
+	0x2cf004bd,
 	0x0320b601,
-	0xf00012d0,
-	0xa5f001ac,
-	0x00b7f006,
-	0x98000c98,
-	0xe7f0010d,
-	0x6621f500,
-	0x08a7f001,
-	0x010921f5,
-	0x021521f5,
-	0xf02201f4,
-	0x21f40ca7,
-	0x1017f1c9,
-	0x0614b60a,
-	0xd00527f0,
-/* 0x08fa: ctx_xfer_post_save_wait */
-	0x12cf0012,
-	0x0522fd00,
-	0xf4fa1bf4,
-/* 0x0906: ctx_xfer_post */
-	0xf7f03202,
-	0x5121f502,
-	0xf5f4bd06,
-	0xf5069221,
-	0xf5023421,
-	0xbd066021,
-	0x5121f5f4,
-	0x1011f406,
-	0xfd400198,
-	0x0bf40511,
-	0xe521f507,
-/* 0x0931: ctx_xfer_no_post_mmio */
-	0x4321f507,
-/* 0x0935: ctx_xfer_done */
-	0x0000f806,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
+	0x4afc07f1,
+	0xd00203f0,
+	0x04bd0002,
+	0xf001acf0,
+	0xb7f006a5,
+	0x000c9800,
+	0xf0010d98,
+	0x21f500e7,
+	0xa7f0016f,
+	0x1021f508,
+	0x5e21f501,
+	0x1301f402,
+	0xf40ca7f0,
+	0xf7f0d021,
+	0x3c21f505,
+	0x3202f408,
+/* 0x0ac4: ctx_xfer_post */
+	0xf502f7f0,
+	0xbd07b521,
+	0x1421f5f4,
+	0x7f21f508,
+	0xc721f502,
+	0xf5f4bd07,
+	0xf407b521,
+	0x01981011,
+	0x0511fd40,
+	0xf5070bf4,
+/* 0x0aef: ctx_xfer_no_post_mmio */
+	0xf5099321,
+/* 0x0af3: ctx_xfer_done */
+	0xf807a421,
 	0x00000000,
 	0x00000000,
 	0x00000000,
diff --git a/drivers/gpu/drm/nouveau/core/engine/graph/fuc/hubnve0.fuc.h b/drivers/gpu/drm/nouveau/core/engine/graph/fuc/hubnve0.fuc.h
index eb7bc0e9576ea..1c179bdd48cc2 100644
--- a/drivers/gpu/drm/nouveau/core/engine/graph/fuc/hubnve0.fuc.h
+++ b/drivers/gpu/drm/nouveau/core/engine/graph/fuc/hubnve0.fuc.h
@@ -206,14 +206,14 @@ uint32_t nve0_grhub_data[] = {
 };
 
 uint32_t nve0_grhub_code[] = {
-	0x031b0ef5,
+	0x039b0ef5,
 /* 0x0004: queue_put */
 	0x9800d898,
 	0x86f001d9,
 	0x0489b808,
 	0xf00c1bf4,
 	0x21f502f7,
-	0x00f802fe,
+	0x00f8037e,
 /* 0x001c: queue_put_next */
 	0xb60798c4,
 	0x8dbb0384,
@@ -237,184 +237,214 @@ uint32_t nve0_grhub_code[] = {
 /* 0x0066: queue_get_done */
 	0x00f80132,
 /* 0x0068: nv_rd32 */
-	0x0728b7f1,
-	0xb906b4b6,
-	0xc9f002ec,
-	0x00bcd01f,
-/* 0x0078: nv_rd32_wait */
-	0xc800bccf,
-	0x1bf41fcc,
-	0x06a7f0fa,
-	0x010921f5,
-	0xf840bfcf,
-/* 0x008d: nv_wr32 */
-	0x28b7f100,
-	0x06b4b607,
-	0xb980bfd0,
-	0xc9f002ec,
-	0x1ec9f01f,
-/* 0x00a3: nv_wr32_wait */
-	0xcf00bcd0,
-	0xccc800bc,
-	0xfa1bf41f,
-/* 0x00ae: watchdog_reset */
-	0x87f100f8,
-	0x84b60430,
-	0x1ff9f006,
-	0xf8008fd0,
-/* 0x00bd: watchdog_clear */
-	0x3087f100,
-	0x0684b604,
-	0xf80080d0,
-/* 0x00c9: wait_donez */
-	0xf094bd00,
-	0x07f10099,
-	0x03f00f00,
-	0x0009d002,
-	0x07f104bd,
-	0x03f00600,
-	0x000ad002,
-/* 0x00e6: wait_donez_ne */
-	0x87f104bd,
-	0x83f00000,
-	0x0088cf01,
-	0xf4888aff,
-	0x94bdf31b,
-	0xf10099f0,
-	0xf0170007,
-	0x09d00203,
-	0xf804bd00,
-/* 0x0109: wait_doneo */
-	0xf094bd00,
+	0xf002ecb9,
+	0x07f11fc9,
+	0x03f0ca00,
+	0x000cd001,
+/* 0x007a: nv_rd32_wait */
+	0xc7f104bd,
+	0xc3f0ca00,
+	0x00cccf01,
+	0xf41fccc8,
+	0xa7f0f31b,
+	0x1021f506,
+	0x00f7f101,
+	0x01f3f0cb,
+	0xf800ffcf,
+/* 0x009d: nv_wr32 */
+	0x0007f100,
+	0x0103f0cc,
+	0xbd000fd0,
+	0x02ecb904,
+	0xf01fc9f0,
+	0x07f11ec9,
+	0x03f0ca00,
+	0x000cd001,
+/* 0x00be: nv_wr32_wait */
+	0xc7f104bd,
+	0xc3f0ca00,
+	0x00cccf01,
+	0xf41fccc8,
+	0x00f8f31b,
+/* 0x00d0: wait_donez */
+	0x99f094bd,
+	0x0007f100,
+	0x0203f00f,
+	0xbd0009d0,
+	0x0007f104,
+	0x0203f006,
+	0xbd000ad0,
+/* 0x00ed: wait_donez_ne */
+	0x0087f104,
+	0x0183f000,
+	0xff0088cf,
+	0x1bf4888a,
+	0xf094bdf3,
 	0x07f10099,
-	0x03f00f00,
+	0x03f01700,
 	0x0009d002,
-	0x87f104bd,
-	0x84b60818,
-	0x008ad006,
-/* 0x0124: wait_doneo_e */
-	0x040087f1,
-	0xcf0684b6,
-	0x8aff0088,
-	0xf30bf488,
+	0x00f804bd,
+/* 0x0110: wait_doneo */
 	0x99f094bd,
 	0x0007f100,
-	0x0203f017,
+	0x0203f00f,
 	0xbd0009d0,
-/* 0x0147: mmctx_size */
-	0xbd00f804,
-/* 0x0149: nv_mmctx_size_loop */
-	0x00e89894,
-	0xb61a85b6,
-	0x84b60180,
-	0x0098bb02,
-	0xb804e0b6,
-	0x1bf404ef,
-	0x029fb9eb,
-/* 0x0166: mmctx_xfer */
-	0x94bd00f8,
-	0xf10199f0,
-	0xf00f0007,
-	0x09d00203,
-	0xf104bd00,
-	0xb6071087,
-	0x94bd0684,
-	0xf405bbfd,
-	0x8bd0090b,
-	0x0099f000,
-/* 0x018c: mmctx_base_disabled */
-	0xf405eefd,
-	0x8ed00c0b,
-	0xc08fd080,
-/* 0x019b: mmctx_multi_disabled */
-	0xb70199f0,
-	0xc8010080,
+	0x0007f104,
+	0x0203f006,
+	0xbd000ad0,
+/* 0x012d: wait_doneo_e */
+	0x0087f104,
+	0x0183f000,
+	0xff0088cf,
+	0x0bf4888a,
+	0xf094bdf3,
+	0x07f10099,
+	0x03f01700,
+	0x0009d002,
+	0x00f804bd,
+/* 0x0150: mmctx_size */
+/* 0x0152: nv_mmctx_size_loop */
+	0xe89894bd,
+	0x1a85b600,
+	0xb60180b6,
+	0x98bb0284,
+	0x04e0b600,
+	0xf404efb8,
+	0x9fb9eb1b,
+/* 0x016f: mmctx_xfer */
+	0xbd00f802,
+	0x0199f094,
+	0x0f0007f1,
+	0xd00203f0,
+	0x04bd0009,
+	0xbbfd94bd,
+	0x120bf405,
+	0xc40007f1,
+	0xd00103f0,
+	0x04bd000b,
+/* 0x0197: mmctx_base_disabled */
+	0xfd0099f0,
+	0x0bf405ee,
+	0x0007f11e,
+	0x0103f0c6,
+	0xbd000ed0,
+	0x0007f104,
+	0x0103f0c7,
+	0xbd000fd0,
+	0x0199f004,
+/* 0x01b8: mmctx_multi_disabled */
+	0xb600abc8,
+	0xb9f010b4,
+	0x01aec80c,
+	0xfd11e4b6,
+	0x07f105be,
+	0x03f0c500,
+	0x000bd001,
+/* 0x01d6: mmctx_exec_loop */
+/* 0x01d6: mmctx_wait_free */
+	0xe7f104bd,
+	0xe3f0c500,
+	0x00eecf01,
+	0xf41fe4f0,
+	0xce98f30b,
+	0x05e9fd00,
+	0xc80007f1,
+	0xd00103f0,
+	0x04bd000e,
+	0xb804c0b6,
+	0x1bf404cd,
+	0x02abc8d8,
+/* 0x0207: mmctx_fini_wait */
+	0xf11f1bf4,
+	0xf0c500b7,
+	0xbbcf01b3,
+	0x1fb4f000,
+	0xf410b4b0,
+	0xa7f0f01b,
+	0xd021f402,
+/* 0x0223: mmctx_stop */
+	0xc82b0ef4,
 	0xb4b600ab,
 	0x0cb9f010,
-	0xb601aec8,
-	0xbefd11e4,
-	0x008bd005,
-/* 0x01b4: mmctx_exec_loop */
-/* 0x01b4: mmctx_wait_free */
-	0xf0008ecf,
-	0x0bf41fe4,
-	0x00ce98fa,
-	0xd005e9fd,
-	0xc0b6c08e,
-	0x04cdb804,
-	0xc8e81bf4,
-	0x1bf402ab,
-/* 0x01d5: mmctx_fini_wait */
-	0x008bcf18,
-	0xb01fb4f0,
-	0x1bf410b4,
-	0x02a7f0f7,
-	0xf4c921f4,
-/* 0x01ea: mmctx_stop */
-	0xabc81b0e,
-	0x10b4b600,
-	0xf00cb9f0,
-	0x8bd012b9,
-/* 0x01f9: mmctx_stop_wait */
-	0x008bcf00,
-	0xf412bbc8,
-/* 0x0202: mmctx_done */
-	0x94bdfa1b,
-	0xf10199f0,
-	0xf0170007,
-	0x09d00203,
-	0xf804bd00,
-/* 0x0215: strand_wait */
-	0xf0a0f900,
-	0x21f402a7,
-	0xf8a0fcc9,
-/* 0x0221: strand_pre */
-	0xfc87f100,
-	0x0283f04a,
-	0xd00c97f0,
-	0x21f50089,
-	0x00f80215,
-/* 0x0234: strand_post */
-	0x4afc87f1,
-	0xf00283f0,
-	0x89d00d97,
-	0x1521f500,
-/* 0x0247: strand_set */
-	0xf100f802,
-	0xf04ffca7,
-	0xaba202a3,
-	0xc7f00500,
-	0x00acd00f,
-	0xd00bc7f0,
-	0x21f500bc,
-	0xaed00215,
-	0x0ac7f000,
-	0xf500bcd0,
-	0xf8021521,
-/* 0x0271: strand_ctx_init */
-	0xf094bd00,
-	0x07f10399,
-	0x03f00f00,
+	0xf112b9f0,
+	0xf0c50007,
+	0x0bd00103,
+/* 0x023b: mmctx_stop_wait */
+	0xf104bd00,
+	0xf0c500b7,
+	0xbbcf01b3,
+	0x12bbc800,
+/* 0x024b: mmctx_done */
+	0xbdf31bf4,
+	0x0199f094,
+	0x170007f1,
+	0xd00203f0,
+	0x04bd0009,
+/* 0x025e: strand_wait */
+	0xa0f900f8,
+	0xf402a7f0,
+	0xa0fcd021,
+/* 0x026a: strand_pre */
+	0x97f000f8,
+	0xfc07f10c,
+	0x0203f04a,
+	0xbd0009d0,
+	0x5e21f504,
+/* 0x027f: strand_post */
+	0xf000f802,
+	0x07f10d97,
+	0x03f04afc,
 	0x0009d002,
 	0x21f504bd,
-	0xe7f00221,
-	0x4721f503,
-	0xfca7f102,
-	0x02a3f046,
-	0x0400aba0,
-	0xf040a0d0,
-	0xbcd001c7,
-	0x1521f500,
-	0x010c9202,
-	0xf000acd0,
-	0xbcd002c7,
-	0x1521f500,
-	0x3421f502,
-	0x8087f102,
-	0x0684b608,
-	0xb70089cf,
-	0x95220080,
-/* 0x02ca: ctx_init_strand_loop */
+	0x00f8025e,
+/* 0x0294: strand_set */
+	0xf10fc7f0,
+	0xf04ffc07,
+	0x0cd00203,
+	0xf004bd00,
+	0x07f10bc7,
+	0x03f04afc,
+	0x000cd002,
+	0x07f104bd,
+	0x03f04ffc,
+	0x000ed002,
+	0xc7f004bd,
+	0xfc07f10a,
+	0x0203f04a,
+	0xbd000cd0,
+	0x5e21f504,
+/* 0x02d3: strand_ctx_init */
+	0xbd00f802,
+	0x0399f094,
+	0x0f0007f1,
+	0xd00203f0,
+	0x04bd0009,
+	0x026a21f5,
+	0xf503e7f0,
+	0xbd029421,
+	0xfc07f1c4,
+	0x0203f047,
+	0xbd000cd0,
+	0x01c7f004,
+	0x4afc07f1,
+	0xd00203f0,
+	0x04bd000c,
+	0x025e21f5,
+	0xf1010c92,
+	0xf046fc07,
+	0x0cd00203,
+	0xf004bd00,
+	0x07f102c7,
+	0x03f04afc,
+	0x000cd002,
+	0x21f504bd,
+	0x21f5025e,
+	0x87f1027f,
+	0x83f04200,
+	0x0097f102,
+	0x0293f020,
+	0x950099cf,
+/* 0x034a: ctx_init_strand_loop */
 	0x8ed008fe,
 	0x408ed000,
 	0xb6808acf,
@@ -428,7 +458,7 @@ uint32_t nve0_grhub_code[] = {
 	0x170007f1,
 	0xd00203f0,
 	0x04bd0009,
-/* 0x02fe: error */
+/* 0x037e: error */
 	0x07f100f8,
 	0x03f00500,
 	0x000fd002,
@@ -436,82 +466,117 @@ uint32_t nve0_grhub_code[] = {
 	0x0007f101,
 	0x0303f007,
 	0xbd000fd0,
-/* 0x031b: init */
+/* 0x039b: init */
 	0xbd00f804,
-	0x0004fe04,
-	0xf10007fe,
-	0xf0120017,
-	0x12d00227,
-	0xb117f100,
-	0x0010fe05,
-	0x040017f1,
-	0xf1c010d0,
-	0xb6040437,
-	0x27f10634,
-	0x32d02003,
-	0x0427f100,
-	0x0132d020,
+	0x0007fe04,
+	0x420017f1,
+	0xcf0013f0,
+	0x11e70011,
+	0x14b60109,
+	0x0014fe08,
+	0xf10227f0,
+	0xf0120007,
+	0x02d00003,
+	0xf104bd00,
+	0xfe06c817,
+	0x24bd0010,
+	0x070007f1,
+	0xd00003f0,
+	0x04bd0002,
+	0x200327f1,
+	0x010007f1,
+	0xd00103f0,
+	0x04bd0002,
+	0x200427f1,
+	0x010407f1,
+	0xd00103f0,
+	0x04bd0002,
 	0x200b27f1,
-	0xf10232d0,
-	0xd0200c27,
-	0x27f10732,
-	0x24b60c24,
-	0x0003b906,
-	0xf10023d0,
+	0x010807f1,
+	0xd00103f0,
+	0x04bd0002,
+	0x200c27f1,
+	0x011c07f1,
+	0xd00103f0,
+	0x04bd0002,
+	0xf1010392,
+	0xf0090007,
+	0x03d00303,
+	0xf104bd00,
 	0xf0870427,
-	0x12d00023,
-	0x0012b700,
-	0x0427f001,
-	0xf40012d0,
-	0xe7f11031,
-	0xe3f09604,
-	0x6821f440,
-	0x8090f1c7,
-	0xf4f00301,
-	0x020f801f,
-	0xbb0117f0,
-	0x12b6041f,
-	0x0c27f101,
-	0x0624b604,
-	0xd00021d0,
-	0x17f14021,
-	0x0e980100,
-	0x010f9800,
-	0x014721f5,
-	0x070037f1,
-	0x950634b6,
-	0x34d00814,
-	0x4034d000,
-	0x130030b7,
-	0xb6001fbb,
-	0x3fd002f5,
-	0x0815b600,
-	0xb60110b6,
-	0x1fb90814,
-	0x7121f502,
-	0x001fbb02,
-	0xf1020398,
-	0xf0200047,
-/* 0x03f6: init_gpc */
-	0x4ea05043,
-	0x1fb90804,
-	0x8d21f402,
-	0x010c4ea0,
-	0x21f4f4bd,
-	0x044ea08d,
-	0x8d21f401,
-	0x01004ea0,
-	0xf402f7f0,
-	0x4ea08d21,
-/* 0x041e: init_gpc_wait */
-	0x21f40800,
-	0x1fffc868,
-	0xa0fa0bf4,
-	0xf408044e,
-	0x1fbb6821,
-	0x0040b700,
-	0x0132b680,
-	0xf1be1bf4,
+	0x07f10023,
+	0x03f00400,
+	0x0002d000,
+	0x27f004bd,
+	0x0007f104,
+	0x0003f003,
+	0xbd0002d0,
+	0x1031f404,
+	0x9604e7f1,
+	0xf440e3f0,
+	0xfeb96821,
+	0x90f1c702,
+	0xf0030180,
+	0x0f801ff4,
+	0x0117f002,
+	0xb6041fbb,
+	0x07f10112,
+	0x03f00300,
+	0x0001d001,
+	0x07f104bd,
+	0x03f00400,
+	0x0001d001,
+	0x17f104bd,
+	0xf7f00100,
+	0x7f21f502,
+	0x9121f507,
+	0x10f7f007,
+	0x07de21f5,
+	0x98000e98,
+	0x21f5010f,
+	0x14950150,
+	0x0007f108,
+	0x0103f0c0,
+	0xbd0004d0,
+	0x0007f104,
+	0x0103f0c1,
+	0xbd0004d0,
+	0x0030b704,
+	0x001fbb13,
+	0xf102f5b6,
+	0xf0d30007,
+	0x0fd00103,
+	0xb604bd00,
+	0x10b60815,
+	0x0814b601,
+	0xf5021fb9,
+	0xbb02d321,
+	0x0398001f,
+	0x0047f102,
+	0x5043f020,
+/* 0x04f4: init_gpc */
+	0x08044ea0,
+	0xf4021fb9,
+	0x4ea09d21,
+	0xf4bd010c,
+	0xa09d21f4,
+	0xf401044e,
+	0x4ea09d21,
+	0xf7f00100,
+	0x9d21f402,
+	0x08004ea0,
+/* 0x051c: init_gpc_wait */
+	0xc86821f4,
+	0x0bf41fff,
+	0x044ea0fa,
+	0x6821f408,
+	0xb7001fbb,
+	0xb6800040,
+	0x1bf40132,
+	0x00f7f0be,
+	0x07de21f5,
+	0xf500f7f0,
+	0xf1077f21,
 	0xf0010007,
 	0x01d00203,
 	0xbd04bd00,
@@ -519,382 +584,379 @@ uint32_t nve0_grhub_code[] = {
 	0x080007f1,
 	0xd00203f0,
 	0x04bd0001,
-/* 0x0458: main */
+/* 0x0564: main */
 	0xf40031f4,
 	0xd7f00028,
 	0x3921f410,
 	0xb1f401f4,
 	0xf54001e4,
-	0xbd00de1b,
+	0xbd00e91b,
 	0x0499f094,
 	0x0f0007f1,
 	0xd00203f0,
 	0x04bd0009,
-	0x0b0017f1,
-	0xcf0614b6,
-	0x11cf4012,
-	0x1f13c800,
-	0x00870bf5,
-	0xf41f23c8,
-	0x20f9620b,
-	0xbd0212b9,
-	0x0799f094,
-	0x0f0007f1,
-	0xd00203f0,
-	0x04bd0009,
-	0xf40132f4,
-	0x21f50231,
-	0x94bd0801,
+	0xc00017f1,
+	0xcf0213f0,
+	0x27f10011,
+	0x23f0c100,
+	0x0022cf02,
+	0xf51f13c8,
+	0xc800890b,
+	0x0bf41f23,
+	0xb920f962,
+	0x94bd0212,
 	0xf10799f0,
-	0xf0170007,
+	0xf00f0007,
 	0x09d00203,
-	0xfc04bd00,
-	0xf094bd20,
-	0x07f10699,
-	0x03f00f00,
-	0x0009d002,
-	0x31f404bd,
-	0x0121f501,
-	0xf094bd08,
-	0x07f10699,
+	0xf404bd00,
+	0x31f40132,
+	0xaa21f502,
+	0xf094bd09,
+	0x07f10799,
 	0x03f01700,
 	0x0009d002,
-	0x0ef404bd,
-/* 0x04f9: chsw_prev_no_next */
-	0xb920f931,
-	0x32f40212,
-	0x0232f401,
-	0x080121f5,
-	0x17f120fc,
-	0x14b60b00,
-	0x0012d006,
-/* 0x0517: chsw_no_prev */
-	0xc8130ef4,
-	0x0bf41f23,
-	0x0131f40d,
-	0xf50232f4,
-/* 0x0527: chsw_done */
-	0xf1080121,
-	0xb60b0c17,
-	0x27f00614,
-	0x0012d001,
+	0x20fc04bd,
 	0x99f094bd,
-	0x0007f104,
+	0x0007f106,
+	0x0203f00f,
+	0xbd0009d0,
+	0x0131f404,
+	0x09aa21f5,
+	0x99f094bd,
+	0x0007f106,
 	0x0203f017,
 	0xbd0009d0,
-	0x130ef504,
-/* 0x0549: main_not_ctx_switch */
-	0x01e4b0ff,
-	0xb90d1bf4,
-	0x21f502f2,
-	0x0ef40795,
-/* 0x0559: main_not_ctx_chan */
-	0x02e4b046,
-	0xbd321bf4,
-	0x0799f094,
-	0x0f0007f1,
+	0x330ef404,
+/* 0x060c: chsw_prev_no_next */
+	0x12b920f9,
+	0x0132f402,
+	0xf50232f4,
+	0xfc09aa21,
+	0x0007f120,
+	0x0203f0c0,
+	0xbd0002d0,
+	0x130ef404,
+/* 0x062c: chsw_no_prev */
+	0xf41f23c8,
+	0x31f40d0b,
+	0x0232f401,
+	0x09aa21f5,
+/* 0x063c: chsw_done */
+	0xf10127f0,
+	0xf0c30007,
+	0x02d00203,
+	0xbd04bd00,
+	0x0499f094,
+	0x170007f1,
 	0xd00203f0,
 	0x04bd0009,
-	0xf40132f4,
-	0x21f50232,
-	0x94bd0801,
+	0xff080ef5,
+/* 0x0660: main_not_ctx_switch */
+	0xf401e4b0,
+	0xf2b90d1b,
+	0x4221f502,
+	0x460ef409,
+/* 0x0670: main_not_ctx_chan */
+	0xf402e4b0,
+	0x94bd321b,
 	0xf10799f0,
-	0xf0170007,
+	0xf00f0007,
 	0x09d00203,
 	0xf404bd00,
-/* 0x058e: main_not_ctx_save */
-	0xef94110e,
-	0x01f5f010,
-	0x02fe21f5,
-	0xfec00ef5,
-/* 0x059c: main_done */
-	0x29f024bd,
-	0x0007f11f,
-	0x0203f008,
-	0xbd0002d0,
-	0xab0ef504,
-/* 0x05b1: ih */
-	0xfe80f9fe,
-	0x80f90188,
-	0xa0f990f9,
-	0xd0f9b0f9,
-	0xf0f9e0f9,
-	0x0acf04bd,
-	0x04abc480,
-	0xf11d0bf4,
-	0xf01900b7,
-	0xbecf10d7,
-	0x00bfcf40,
+	0x32f40132,
+	0xaa21f502,
+	0xf094bd09,
+	0x07f10799,
+	0x03f01700,
+	0x0009d002,
+	0x0ef404bd,
+/* 0x06a5: main_not_ctx_save */
+	0x10ef9411,
+	0xf501f5f0,
+	0xf5037e21,
+/* 0x06b3: main_done */
+	0xbdfeb50e,
+	0x1f29f024,
+	0x080007f1,
+	0xd00203f0,
+	0x04bd0002,
+	0xfea00ef5,
+/* 0x06c8: ih */
+	0x88fe80f9,
+	0xf980f901,
+	0xf9a0f990,
+	0xf9d0f9b0,
+	0xbdf0f9e0,
+	0x00a7f104,
+	0x00a3f002,
+	0xc400aacf,
+	0x0bf404ab,
+	0x10d7f030,
+	0x1a00e7f1,
+	0xcf00e3f0,
+	0xf7f100ee,
+	0xf3f01900,
+	0x00ffcf00,
 	0xb70421f4,
 	0xf00400b0,
-	0xbed001e7,
-/* 0x05e9: ih_no_fifo */
-	0x00abe400,
-	0x0d0bf401,
-	0xf110d7f0,
-	0xf44001e7,
-/* 0x05fa: ih_no_ctxsw */
-	0xb7f10421,
-	0xb0bd0104,
-	0xf4b4abff,
-	0xa7f10d0b,
-	0xa4b60c1c,
-	0x00abd006,
-/* 0x0610: ih_no_other */
-	0xfc400ad0,
+	0x07f101e7,
+	0x03f01d00,
+	0x000ed000,
+/* 0x071a: ih_no_fifo */
+	0xabe404bd,
+	0x0bf40100,
+	0x10d7f00d,
+	0x4001e7f1,
+/* 0x072b: ih_no_ctxsw */
+	0xe40421f4,
+	0xf40400ab,
+	0xb7f1140b,
+	0xbfb90100,
+	0x44e7f102,
+	0x40e3f001,
+/* 0x0743: ih_no_fwmthd */
+	0xf19d21f4,
+	0xbd0104b7,
+	0xb4abffb0,
+	0xf10f0bf4,
+	0xf0070007,
+	0x0bd00303,
+/* 0x075b: ih_no_other */
+	0xf104bd00,
+	0xf0010007,
+	0x0ad00003,
+	0xfc04bd00,
 	0xfce0fcf0,
 	0xfcb0fcd0,
 	0xfc90fca0,
 	0x0088fe80,
 	0x32f480fc,
-/* 0x062b: ctx_4170s */
-	0xf101f800,
-	0xf04170e7,
-	0xf5f040e3,
-	0x8d21f410,
-/* 0x063a: ctx_4170w */
+/* 0x077f: ctx_4170s */
+	0xf001f800,
+	0xffb910f5,
+	0x70e7f102,
+	0x40e3f041,
+	0xf89d21f4,
+/* 0x0791: ctx_4170w */
+	0x70e7f100,
+	0x40e3f041,
+	0xb96821f4,
+	0xf4f002ff,
+	0xf01bf410,
+/* 0x07a6: ctx_redswitch */
 	0xe7f100f8,
-	0xe3f04170,
-	0x6821f440,
-	0xf410f4f0,
+	0xe5f00200,
+	0x20e5f040,
+	0xf110e5f0,
+	0xf0850007,
+	0x0ed00103,
+	0xf004bd00,
+/* 0x07c2: ctx_redswitch_delay */
+	0xf2b608f7,
+	0xfd1bf401,
+	0x0400e5f1,
+	0x0100e5f1,
+	0x850007f1,
+	0xd00103f0,
+	0x04bd000e,
+/* 0x07de: ctx_86c */
+	0x07f100f8,
+	0x03f01b00,
+	0x000fd002,
+	0xffb904bd,
+	0x14e7f102,
+	0x40e3f08a,
+	0xb99d21f4,
+	0xe7f102ff,
+	0xe3f0a86c,
+	0x9d21f441,
+/* 0x0806: ctx_mem */
+	0x07f100f8,
+	0x03f08400,
+	0x000fd002,
+/* 0x0812: ctx_mem_wait */
+	0xf7f104bd,
+	0xf3f08400,
+	0x00ffcf02,
+	0xf405fffd,
 	0x00f8f31b,
-/* 0x064c: ctx_redswitch */
-	0x0614e7f1,
-	0xf106e4b6,
-	0xd00270f7,
-	0xf7f000ef,
-/* 0x065d: ctx_redswitch_delay */
-	0x01f2b608,
-	0xf1fd1bf4,
-	0xd00770f7,
-	0x00f800ef,
-/* 0x066c: ctx_86c */
-	0x086ce7f1,
-	0xd006e4b6,
-	0xe7f100ef,
-	0xe3f08a14,
-	0x8d21f440,
-	0xa86ce7f1,
-	0xf441e3f0,
-	0x00f88d21,
-/* 0x068c: ctx_load */
+/* 0x0824: ctx_load */
 	0x99f094bd,
 	0x0007f105,
 	0x0203f00f,
 	0xbd0009d0,
 	0x0ca7f004,
-	0xf1c921f4,
-	0xb60a2417,
-	0x10d00614,
-	0x0037f100,
-	0x0634b60b,
-	0xf14032d0,
-	0xb60a0c17,
-	0x47f00614,
-	0x0012d007,
-/* 0x06c7: ctx_chan_wait_0 */
-	0xcf4014d0,
-	0x44f04014,
-	0xfa1bf41f,
-	0xfe0032d0,
-	0x2af0000b,
-	0x0424b61f,
-	0xbd0220b6,
+	0xbdd021f4,
+	0x0007f1f4,
+	0x0203f089,
+	0xbd000fd0,
+	0x0007f104,
+	0x0203f0c1,
+	0xbd0002d0,
+	0x0007f104,
+	0x0203f083,
+	0xbd0002d0,
+	0x07f7f004,
+	0x080621f5,
+	0xc00007f1,
+	0xd00203f0,
+	0x04bd0002,
+	0xf0000bfe,
+	0x24b61f2a,
+	0x0220b604,
+	0x99f094bd,
+	0x0007f108,
+	0x0203f00f,
+	0xbd0009d0,
+	0x0007f104,
+	0x0203f081,
+	0xbd0002d0,
+	0x0027f104,
+	0x0023f100,
+	0x0225f080,
+	0x880007f1,
+	0xd00203f0,
+	0x04bd0002,
+	0xf11017f0,
+	0xf0020027,
+	0x12fa0223,
+	0xbd03f805,
 	0x0899f094,
-	0x0f0007f1,
+	0x170007f1,
 	0xd00203f0,
 	0x04bd0009,
-	0x0a0417f1,
-	0xd00614b6,
-	0x17f10012,
-	0x14b60a20,
-	0x0227f006,
-	0x800023f1,
-	0xf00012d0,
-	0x27f11017,
-	0x23f00200,
-	0x0512fa02,
-	0x94bd03f8,
-	0xf10899f0,
-	0xf0170007,
+	0xb6810198,
+	0x02981814,
+	0x0825b680,
+	0x800512fd,
+	0x94bd1601,
+	0xf10999f0,
+	0xf00f0007,
 	0x09d00203,
-	0x9804bd00,
-	0x14b68101,
-	0x80029818,
-	0xfd0825b6,
-	0x01800512,
-	0xf094bd16,
-	0x07f10999,
-	0x03f00f00,
-	0x0009d002,
-	0x27f104bd,
-	0x24b60a04,
-	0x0021d006,
-	0xf10127f0,
-	0xb60a2017,
-	0x12d00614,
-	0x0017f100,
-	0x0613f001,
-	0xf80501fa,
-	0xf094bd03,
-	0x07f10999,
-	0x03f01700,
-	0x0009d002,
-	0x94bd04bd,
-	0xf10599f0,
+	0xf104bd00,
+	0xf0810007,
+	0x01d00203,
+	0xf004bd00,
+	0x07f10127,
+	0x03f08800,
+	0x0002d002,
+	0x17f104bd,
+	0x13f00100,
+	0x0501fa06,
+	0x94bd03f8,
+	0xf10999f0,
 	0xf0170007,
 	0x09d00203,
-	0xf804bd00,
-/* 0x0795: ctx_chan */
-	0x8c21f500,
-	0x0ca7f006,
-	0xf1c921f4,
-	0xb60a1017,
-	0x27f00614,
-	0x0012d005,
-/* 0x07ac: ctx_chan_wait */
-	0xfd0012cf,
-	0x1bf40522,
-/* 0x07b7: ctx_mmio_exec */
-	0x9800f8fa,
-	0x27f14103,
-	0x24b60a04,
-	0x0023d006,
-/* 0x07c6: ctx_mmio_loop */
+	0xbd04bd00,
+	0x0599f094,
+	0x170007f1,
+	0xd00203f0,
+	0x04bd0009,
+/* 0x0942: ctx_chan */
+	0x21f500f8,
+	0xa7f00824,
+	0xd021f40c,
+	0xf505f7f0,
+	0xf8080621,
+/* 0x0955: ctx_mmio_exec */
+	0x41039800,
+	0x810007f1,
+	0xd00203f0,
+	0x04bd0003,
+/* 0x0966: ctx_mmio_loop */
 	0x34c434bd,
 	0x0f1bf4ff,
 	0x020057f1,
 	0xfa0653f0,
 	0x03f80535,
-/* 0x07d8: ctx_mmio_pull */
+/* 0x0978: ctx_mmio_pull */
 	0x98804e98,
 	0x21f4814f,
-	0x0830b68d,
+	0x0830b69d,
 	0xf40112b6,
-/* 0x07ea: ctx_mmio_done */
+/* 0x098a: ctx_mmio_done */
 	0x0398df1b,
-	0x0023d016,
-	0xf1400080,
-	0xf0010017,
-	0x01fa0613,
-	0xf803f806,
-/* 0x0801: ctx_xfer */
-	0x00f7f100,
-	0x06f4b60c,
-	0xd004e7f0,
-/* 0x080e: ctx_xfer_idle */
-	0xfecf80fe,
-	0x00e4f100,
-	0xf91bf420,
-	0xf40611f4,
-/* 0x081e: ctx_xfer_pre */
-	0xf7f00d02,
-	0x6c21f510,
-	0x1c11f406,
-/* 0x0828: ctx_xfer_pre_load */
-	0xf502f7f0,
-	0xf5062b21,
-	0xf5063a21,
-	0xbd064c21,
-	0x2b21f5f4,
-	0x8c21f506,
-/* 0x0841: ctx_xfer_exec */
-	0x16019806,
-	0x041427f1,
-	0xd00624b6,
-	0xe7f10020,
-	0xe3f0a500,
-	0x021fb941,
-	0xb68d21f4,
-	0xfcf004e0,
-	0x022cf001,
-	0xfd0124b6,
-	0x21f405f2,
-	0xfc17f18d,
-	0x0213f04a,
-	0xd00c27f0,
-	0x21f50012,
-	0x27f10215,
-	0x23f047fc,
-	0x0020d002,
+	0x0007f116,
+	0x0203f081,
+	0xbd0003d0,
+	0x40008004,
+	0x010017f1,
+	0xfa0613f0,
+	0x03f80601,
+/* 0x09aa: ctx_xfer */
+	0xe7f000f8,
+	0x0007f104,
+	0x0303f002,
+	0xbd000ed0,
+/* 0x09b9: ctx_xfer_idle */
+	0x00e7f104,
+	0x03e3f000,
+	0xf100eecf,
+	0xf42000e4,
+	0x11f4f21b,
+	0x0d02f406,
+/* 0x09d0: ctx_xfer_pre */
+	0xf510f7f0,
+	0xf407de21,
+/* 0x09da: ctx_xfer_pre_load */
+	0xf7f01c11,
+	0x7f21f502,
+	0x9121f507,
+	0xa621f507,
+	0xf5f4bd07,
+	0xf5077f21,
+/* 0x09f3: ctx_xfer_exec */
+	0x98082421,
+	0x24bd1601,
+	0x050007f1,
+	0xd00103f0,
+	0x04bd0002,
+	0xf1021fb9,
+	0xf0a500e7,
+	0x21f441e3,
+	0x01fcf09d,
+	0xb6022cf0,
+	0xf2fd0124,
+	0x02ffb905,
+	0xa504e7f1,
+	0xf441e3f0,
+	0x21f59d21,
+	0x24bd026a,
+	0x47fc07f1,
+	0xd00203f0,
+	0x04bd0002,
 	0xb6012cf0,
-	0x12d00320,
-	0x01acf000,
-	0xf006a5f0,
-	0x0c9800b7,
-	0x010d9800,
-	0xf500e7f0,
-	0xf0016621,
-	0x21f508a7,
-	0x21f50109,
-	0x01f40215,
-	0x0ca7f022,
-	0xf1c921f4,
-	0xb60a1017,
-	0x27f00614,
-	0x0012d005,
-/* 0x08c8: ctx_xfer_post_save_wait */
-	0xfd0012cf,
-	0x1bf40522,
-	0x2e02f4fa,
-/* 0x08d4: ctx_xfer_post */
-	0xf502f7f0,
-	0xbd062b21,
-	0x6c21f5f4,
-	0x3421f506,
-	0x3a21f502,
-	0xf5f4bd06,
-	0xf4062b21,
-	0x01981011,
-	0x0511fd40,
-	0xf5070bf4,
-/* 0x08ff: ctx_xfer_no_post_mmio */
-/* 0x08ff: ctx_xfer_done */
-	0xf807b721,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
+	0x07f10320,
+	0x03f04afc,
+	0x0002d002,
+	0xacf004bd,
+	0x06a5f001,
+	0x9800b7f0,
+	0x0d98000c,
+	0x00e7f001,
+	0x016f21f5,
+	0xf508a7f0,
+	0xf5011021,
+	0xf4025e21,
+	0xa7f01301,
+	0xd021f40c,
+	0xf505f7f0,
+	0xf4080621,
+/* 0x0a82: ctx_xfer_post */
+	0xf7f02e02,
+	0x7f21f502,
+	0xf5f4bd07,
+	0xf507de21,
+	0xf5027f21,
+	0xbd079121,
+	0x7f21f5f4,
+	0x1011f407,
+	0xfd400198,
+	0x0bf40511,
+	0x5521f507,
+/* 0x0aad: ctx_xfer_no_post_mmio */
+/* 0x0aad: ctx_xfer_done */
+	0x0000f809,
 	0x00000000,
 	0x00000000,
 	0x00000000,
diff --git a/drivers/gpu/drm/nouveau/core/engine/graph/fuc/hubnvf0.fuc.h b/drivers/gpu/drm/nouveau/core/engine/graph/fuc/hubnvf0.fuc.h
index 438506d147499..229c0ae372284 100644
--- a/drivers/gpu/drm/nouveau/core/engine/graph/fuc/hubnvf0.fuc.h
+++ b/drivers/gpu/drm/nouveau/core/engine/graph/fuc/hubnvf0.fuc.h
@@ -206,14 +206,14 @@ uint32_t nvf0_grhub_data[] = {
 };
 
 uint32_t nvf0_grhub_code[] = {
-	0x031b0ef5,
+	0x039b0ef5,
 /* 0x0004: queue_put */
 	0x9800d898,
 	0x86f001d9,
 	0x0489b808,
 	0xf00c1bf4,
 	0x21f502f7,
-	0x00f802fe,
+	0x00f8037e,
 /* 0x001c: queue_put_next */
 	0xb60798c4,
 	0x8dbb0384,
@@ -237,184 +237,214 @@ uint32_t nvf0_grhub_code[] = {
 /* 0x0066: queue_get_done */
 	0x00f80132,
 /* 0x0068: nv_rd32 */
-	0x0728b7f1,
-	0xb906b4b6,
-	0xc9f002ec,
-	0x00bcd01f,
-/* 0x0078: nv_rd32_wait */
-	0xc800bccf,
-	0x1bf41fcc,
-	0x06a7f0fa,
-	0x010921f5,
-	0xf840bfcf,
-/* 0x008d: nv_wr32 */
-	0x28b7f100,
-	0x06b4b607,
-	0xb980bfd0,
-	0xc9f002ec,
-	0x1ec9f01f,
-/* 0x00a3: nv_wr32_wait */
-	0xcf00bcd0,
-	0xccc800bc,
-	0xfa1bf41f,
-/* 0x00ae: watchdog_reset */
-	0x87f100f8,
-	0x84b60430,
-	0x1ff9f006,
-	0xf8008fd0,
-/* 0x00bd: watchdog_clear */
-	0x3087f100,
-	0x0684b604,
-	0xf80080d0,
-/* 0x00c9: wait_donez */
-	0xf094bd00,
-	0x07f10099,
-	0x03f03700,
-	0x0009d002,
-	0x07f104bd,
-	0x03f00600,
-	0x000ad002,
-/* 0x00e6: wait_donez_ne */
-	0x87f104bd,
-	0x83f00000,
-	0x0088cf01,
-	0xf4888aff,
-	0x94bdf31b,
-	0xf10099f0,
-	0xf0170007,
-	0x09d00203,
-	0xf804bd00,
-/* 0x0109: wait_doneo */
-	0xf094bd00,
+	0xf002ecb9,
+	0x07f11fc9,
+	0x03f0ca00,
+	0x000cd001,
+/* 0x007a: nv_rd32_wait */
+	0xc7f104bd,
+	0xc3f0ca00,
+	0x00cccf01,
+	0xf41fccc8,
+	0xa7f0f31b,
+	0x1021f506,
+	0x00f7f101,
+	0x01f3f0cb,
+	0xf800ffcf,
+/* 0x009d: nv_wr32 */
+	0x0007f100,
+	0x0103f0cc,
+	0xbd000fd0,
+	0x02ecb904,
+	0xf01fc9f0,
+	0x07f11ec9,
+	0x03f0ca00,
+	0x000cd001,
+/* 0x00be: nv_wr32_wait */
+	0xc7f104bd,
+	0xc3f0ca00,
+	0x00cccf01,
+	0xf41fccc8,
+	0x00f8f31b,
+/* 0x00d0: wait_donez */
+	0x99f094bd,
+	0x0007f100,
+	0x0203f037,
+	0xbd0009d0,
+	0x0007f104,
+	0x0203f006,
+	0xbd000ad0,
+/* 0x00ed: wait_donez_ne */
+	0x0087f104,
+	0x0183f000,
+	0xff0088cf,
+	0x1bf4888a,
+	0xf094bdf3,
 	0x07f10099,
-	0x03f03700,
+	0x03f01700,
 	0x0009d002,
-	0x87f104bd,
-	0x84b60818,
-	0x008ad006,
-/* 0x0124: wait_doneo_e */
-	0x040087f1,
-	0xcf0684b6,
-	0x8aff0088,
-	0xf30bf488,
+	0x00f804bd,
+/* 0x0110: wait_doneo */
 	0x99f094bd,
 	0x0007f100,
-	0x0203f017,
+	0x0203f037,
 	0xbd0009d0,
-/* 0x0147: mmctx_size */
-	0xbd00f804,
-/* 0x0149: nv_mmctx_size_loop */
-	0x00e89894,
-	0xb61a85b6,
-	0x84b60180,
-	0x0098bb02,
-	0xb804e0b6,
-	0x1bf404ef,
-	0x029fb9eb,
-/* 0x0166: mmctx_xfer */
-	0x94bd00f8,
-	0xf10199f0,
-	0xf0370007,
-	0x09d00203,
-	0xf104bd00,
-	0xb6071087,
-	0x94bd0684,
-	0xf405bbfd,
-	0x8bd0090b,
-	0x0099f000,
-/* 0x018c: mmctx_base_disabled */
-	0xf405eefd,
-	0x8ed00c0b,
-	0xc08fd080,
-/* 0x019b: mmctx_multi_disabled */
-	0xb70199f0,
-	0xc8010080,
+	0x0007f104,
+	0x0203f006,
+	0xbd000ad0,
+/* 0x012d: wait_doneo_e */
+	0x0087f104,
+	0x0183f000,
+	0xff0088cf,
+	0x0bf4888a,
+	0xf094bdf3,
+	0x07f10099,
+	0x03f01700,
+	0x0009d002,
+	0x00f804bd,
+/* 0x0150: mmctx_size */
+/* 0x0152: nv_mmctx_size_loop */
+	0xe89894bd,
+	0x1a85b600,
+	0xb60180b6,
+	0x98bb0284,
+	0x04e0b600,
+	0xf404efb8,
+	0x9fb9eb1b,
+/* 0x016f: mmctx_xfer */
+	0xbd00f802,
+	0x0199f094,
+	0x370007f1,
+	0xd00203f0,
+	0x04bd0009,
+	0xbbfd94bd,
+	0x120bf405,
+	0xc40007f1,
+	0xd00103f0,
+	0x04bd000b,
+/* 0x0197: mmctx_base_disabled */
+	0xfd0099f0,
+	0x0bf405ee,
+	0x0007f11e,
+	0x0103f0c6,
+	0xbd000ed0,
+	0x0007f104,
+	0x0103f0c7,
+	0xbd000fd0,
+	0x0199f004,
+/* 0x01b8: mmctx_multi_disabled */
+	0xb600abc8,
+	0xb9f010b4,
+	0x01aec80c,
+	0xfd11e4b6,
+	0x07f105be,
+	0x03f0c500,
+	0x000bd001,
+/* 0x01d6: mmctx_exec_loop */
+/* 0x01d6: mmctx_wait_free */
+	0xe7f104bd,
+	0xe3f0c500,
+	0x00eecf01,
+	0xf41fe4f0,
+	0xce98f30b,
+	0x05e9fd00,
+	0xc80007f1,
+	0xd00103f0,
+	0x04bd000e,
+	0xb804c0b6,
+	0x1bf404cd,
+	0x02abc8d8,
+/* 0x0207: mmctx_fini_wait */
+	0xf11f1bf4,
+	0xf0c500b7,
+	0xbbcf01b3,
+	0x1fb4f000,
+	0xf410b4b0,
+	0xa7f0f01b,
+	0xd021f402,
+/* 0x0223: mmctx_stop */
+	0xc82b0ef4,
 	0xb4b600ab,
 	0x0cb9f010,
-	0xb601aec8,
-	0xbefd11e4,
-	0x008bd005,
-/* 0x01b4: mmctx_exec_loop */
-/* 0x01b4: mmctx_wait_free */
-	0xf0008ecf,
-	0x0bf41fe4,
-	0x00ce98fa,
-	0xd005e9fd,
-	0xc0b6c08e,
-	0x04cdb804,
-	0xc8e81bf4,
-	0x1bf402ab,
-/* 0x01d5: mmctx_fini_wait */
-	0x008bcf18,
-	0xb01fb4f0,
-	0x1bf410b4,
-	0x02a7f0f7,
-	0xf4c921f4,
-/* 0x01ea: mmctx_stop */
-	0xabc81b0e,
-	0x10b4b600,
-	0xf00cb9f0,
-	0x8bd012b9,
-/* 0x01f9: mmctx_stop_wait */
-	0x008bcf00,
-	0xf412bbc8,
-/* 0x0202: mmctx_done */
-	0x94bdfa1b,
-	0xf10199f0,
-	0xf0170007,
-	0x09d00203,
-	0xf804bd00,
-/* 0x0215: strand_wait */
-	0xf0a0f900,
-	0x21f402a7,
-	0xf8a0fcc9,
-/* 0x0221: strand_pre */
-	0xfc87f100,
-	0x0283f04a,
-	0xd00c97f0,
-	0x21f50089,
-	0x00f80215,
-/* 0x0234: strand_post */
-	0x4afc87f1,
-	0xf00283f0,
-	0x89d00d97,
-	0x1521f500,
-/* 0x0247: strand_set */
-	0xf100f802,
-	0xf04ffca7,
-	0xaba202a3,
-	0xc7f00500,
-	0x00acd00f,
-	0xd00bc7f0,
-	0x21f500bc,
-	0xaed00215,
-	0x0ac7f000,
-	0xf500bcd0,
-	0xf8021521,
-/* 0x0271: strand_ctx_init */
-	0xf094bd00,
-	0x07f10399,
-	0x03f03700,
+	0xf112b9f0,
+	0xf0c50007,
+	0x0bd00103,
+/* 0x023b: mmctx_stop_wait */
+	0xf104bd00,
+	0xf0c500b7,
+	0xbbcf01b3,
+	0x12bbc800,
+/* 0x024b: mmctx_done */
+	0xbdf31bf4,
+	0x0199f094,
+	0x170007f1,
+	0xd00203f0,
+	0x04bd0009,
+/* 0x025e: strand_wait */
+	0xa0f900f8,
+	0xf402a7f0,
+	0xa0fcd021,
+/* 0x026a: strand_pre */
+	0x97f000f8,
+	0xfc07f10c,
+	0x0203f04a,
+	0xbd0009d0,
+	0x5e21f504,
+/* 0x027f: strand_post */
+	0xf000f802,
+	0x07f10d97,
+	0x03f04afc,
 	0x0009d002,
 	0x21f504bd,
-	0xe7f00221,
-	0x4721f503,
-	0xfca7f102,
-	0x02a3f046,
-	0x0400aba0,
-	0xf040a0d0,
-	0xbcd001c7,
-	0x1521f500,
-	0x010c9202,
-	0xf000acd0,
-	0xbcd002c7,
-	0x1521f500,
-	0x3421f502,
-	0x8087f102,
-	0x0684b608,
-	0xb70089cf,
-	0x95220080,
-/* 0x02ca: ctx_init_strand_loop */
+	0x00f8025e,
+/* 0x0294: strand_set */
+	0xf10fc7f0,
+	0xf04ffc07,
+	0x0cd00203,
+	0xf004bd00,
+	0x07f10bc7,
+	0x03f04afc,
+	0x000cd002,
+	0x07f104bd,
+	0x03f04ffc,
+	0x000ed002,
+	0xc7f004bd,
+	0xfc07f10a,
+	0x0203f04a,
+	0xbd000cd0,
+	0x5e21f504,
+/* 0x02d3: strand_ctx_init */
+	0xbd00f802,
+	0x0399f094,
+	0x370007f1,
+	0xd00203f0,
+	0x04bd0009,
+	0x026a21f5,
+	0xf503e7f0,
+	0xbd029421,
+	0xfc07f1c4,
+	0x0203f047,
+	0xbd000cd0,
+	0x01c7f004,
+	0x4afc07f1,
+	0xd00203f0,
+	0x04bd000c,
+	0x025e21f5,
+	0xf1010c92,
+	0xf046fc07,
+	0x0cd00203,
+	0xf004bd00,
+	0x07f102c7,
+	0x03f04afc,
+	0x000cd002,
+	0x21f504bd,
+	0x21f5025e,
+	0x87f1027f,
+	0x83f04200,
+	0x0097f102,
+	0x0293f020,
+	0x950099cf,
+/* 0x034a: ctx_init_strand_loop */
 	0x8ed008fe,
 	0x408ed000,
 	0xb6808acf,
@@ -428,7 +458,7 @@ uint32_t nvf0_grhub_code[] = {
 	0x170007f1,
 	0xd00203f0,
 	0x04bd0009,
-/* 0x02fe: error */
+/* 0x037e: error */
 	0x07f100f8,
 	0x03f00500,
 	0x000fd002,
@@ -436,82 +466,117 @@ uint32_t nvf0_grhub_code[] = {
 	0x0007f101,
 	0x0303f007,
 	0xbd000fd0,
-/* 0x031b: init */
+/* 0x039b: init */
 	0xbd00f804,
-	0x0004fe04,
-	0xf10007fe,
-	0xf0120017,
-	0x12d00227,
-	0xb117f100,
-	0x0010fe05,
-	0x040017f1,
-	0xf1c010d0,
-	0xb6040437,
-	0x27f10634,
-	0x32d02003,
-	0x0427f100,
-	0x0132d020,
+	0x0007fe04,
+	0x420017f1,
+	0xcf0013f0,
+	0x11e70011,
+	0x14b60109,
+	0x0014fe08,
+	0xf10227f0,
+	0xf0120007,
+	0x02d00003,
+	0xf104bd00,
+	0xfe06c817,
+	0x24bd0010,
+	0x070007f1,
+	0xd00003f0,
+	0x04bd0002,
+	0x200327f1,
+	0x010007f1,
+	0xd00103f0,
+	0x04bd0002,
+	0x200427f1,
+	0x010407f1,
+	0xd00103f0,
+	0x04bd0002,
 	0x200b27f1,
-	0xf10232d0,
-	0xd0200c27,
-	0x27f10732,
-	0x24b60c24,
-	0x0003b906,
-	0xf10023d0,
+	0x010807f1,
+	0xd00103f0,
+	0x04bd0002,
+	0x200c27f1,
+	0x011c07f1,
+	0xd00103f0,
+	0x04bd0002,
+	0xf1010392,
+	0xf0090007,
+	0x03d00303,
+	0xf104bd00,
 	0xf0870427,
-	0x12d00023,
-	0x0012b700,
-	0x0427f001,
-	0xf40012d0,
-	0xe7f11031,
-	0xe3f09604,
-	0x6821f440,
-	0x8090f1c7,
-	0xf4f00301,
-	0x020f801f,
-	0xbb0117f0,
-	0x12b6041f,
-	0x0c27f101,
-	0x0624b604,
-	0xd00021d0,
-	0x17f14021,
-	0x0e980100,
-	0x010f9800,
-	0x014721f5,
-	0x070037f1,
-	0x950634b6,
-	0x34d00814,
-	0x4034d000,
-	0x130030b7,
-	0xb6001fbb,
-	0x3fd002f5,
-	0x0815b600,
-	0xb60110b6,
-	0x1fb90814,
-	0x7121f502,
-	0x001fbb02,
-	0xf1020398,
-	0xf0200047,
-/* 0x03f6: init_gpc */
-	0x4ea05043,
-	0x1fb90804,
-	0x8d21f402,
-	0x010c4ea0,
-	0x21f4f4bd,
-	0x044ea08d,
-	0x8d21f401,
-	0x01004ea0,
-	0xf402f7f0,
-	0x4ea08d21,
-/* 0x041e: init_gpc_wait */
-	0x21f40800,
-	0x1fffc868,
-	0xa0fa0bf4,
-	0xf408044e,
-	0x1fbb6821,
-	0x0040b700,
-	0x0132b680,
-	0xf1be1bf4,
+	0x07f10023,
+	0x03f00400,
+	0x0002d000,
+	0x27f004bd,
+	0x0007f104,
+	0x0003f003,
+	0xbd0002d0,
+	0x1031f404,
+	0x9604e7f1,
+	0xf440e3f0,
+	0xfeb96821,
+	0x90f1c702,
+	0xf0030180,
+	0x0f801ff4,
+	0x0117f002,
+	0xb6041fbb,
+	0x07f10112,
+	0x03f00300,
+	0x0001d001,
+	0x07f104bd,
+	0x03f00400,
+	0x0001d001,
+	0x17f104bd,
+	0xf7f00100,
+	0x7f21f502,
+	0x9121f507,
+	0x10f7f007,
+	0x07de21f5,
+	0x98000e98,
+	0x21f5010f,
+	0x14950150,
+	0x0007f108,
+	0x0103f0c0,
+	0xbd0004d0,
+	0x0007f104,
+	0x0103f0c1,
+	0xbd0004d0,
+	0x0030b704,
+	0x001fbb13,
+	0xf102f5b6,
+	0xf0d30007,
+	0x0fd00103,
+	0xb604bd00,
+	0x10b60815,
+	0x0814b601,
+	0xf5021fb9,
+	0xbb02d321,
+	0x0398001f,
+	0x0047f102,
+	0x5043f020,
+/* 0x04f4: init_gpc */
+	0x08044ea0,
+	0xf4021fb9,
+	0x4ea09d21,
+	0xf4bd010c,
+	0xa09d21f4,
+	0xf401044e,
+	0x4ea09d21,
+	0xf7f00100,
+	0x9d21f402,
+	0x08004ea0,
+/* 0x051c: init_gpc_wait */
+	0xc86821f4,
+	0x0bf41fff,
+	0x044ea0fa,
+	0x6821f408,
+	0xb7001fbb,
+	0xb6800040,
+	0x1bf40132,
+	0x00f7f0be,
+	0x07de21f5,
+	0xf500f7f0,
+	0xf1077f21,
 	0xf0010007,
 	0x01d00203,
 	0xbd04bd00,
@@ -519,382 +584,379 @@ uint32_t nvf0_grhub_code[] = {
 	0x300007f1,
 	0xd00203f0,
 	0x04bd0001,
-/* 0x0458: main */
+/* 0x0564: main */
 	0xf40031f4,
 	0xd7f00028,
 	0x3921f410,
 	0xb1f401f4,
 	0xf54001e4,
-	0xbd00de1b,
+	0xbd00e91b,
 	0x0499f094,
 	0x370007f1,
 	0xd00203f0,
 	0x04bd0009,
-	0x0b0017f1,
-	0xcf0614b6,
-	0x11cf4012,
-	0x1f13c800,
-	0x00870bf5,
-	0xf41f23c8,
-	0x20f9620b,
-	0xbd0212b9,
-	0x0799f094,
-	0x370007f1,
-	0xd00203f0,
-	0x04bd0009,
-	0xf40132f4,
-	0x21f50231,
-	0x94bd0801,
+	0xc00017f1,
+	0xcf0213f0,
+	0x27f10011,
+	0x23f0c100,
+	0x0022cf02,
+	0xf51f13c8,
+	0xc800890b,
+	0x0bf41f23,
+	0xb920f962,
+	0x94bd0212,
 	0xf10799f0,
-	0xf0170007,
+	0xf0370007,
 	0x09d00203,
-	0xfc04bd00,
-	0xf094bd20,
-	0x07f10699,
-	0x03f03700,
-	0x0009d002,
-	0x31f404bd,
-	0x0121f501,
-	0xf094bd08,
-	0x07f10699,
+	0xf404bd00,
+	0x31f40132,
+	0xaa21f502,
+	0xf094bd09,
+	0x07f10799,
 	0x03f01700,
 	0x0009d002,
-	0x0ef404bd,
-/* 0x04f9: chsw_prev_no_next */
-	0xb920f931,
-	0x32f40212,
-	0x0232f401,
-	0x080121f5,
-	0x17f120fc,
-	0x14b60b00,
-	0x0012d006,
-/* 0x0517: chsw_no_prev */
-	0xc8130ef4,
-	0x0bf41f23,
-	0x0131f40d,
-	0xf50232f4,
-/* 0x0527: chsw_done */
-	0xf1080121,
-	0xb60b0c17,
-	0x27f00614,
-	0x0012d001,
+	0x20fc04bd,
 	0x99f094bd,
-	0x0007f104,
+	0x0007f106,
+	0x0203f037,
+	0xbd0009d0,
+	0x0131f404,
+	0x09aa21f5,
+	0x99f094bd,
+	0x0007f106,
 	0x0203f017,
 	0xbd0009d0,
-	0x130ef504,
-/* 0x0549: main_not_ctx_switch */
-	0x01e4b0ff,
-	0xb90d1bf4,
-	0x21f502f2,
-	0x0ef40795,
-/* 0x0559: main_not_ctx_chan */
-	0x02e4b046,
-	0xbd321bf4,
-	0x0799f094,
-	0x370007f1,
+	0x330ef404,
+/* 0x060c: chsw_prev_no_next */
+	0x12b920f9,
+	0x0132f402,
+	0xf50232f4,
+	0xfc09aa21,
+	0x0007f120,
+	0x0203f0c0,
+	0xbd0002d0,
+	0x130ef404,
+/* 0x062c: chsw_no_prev */
+	0xf41f23c8,
+	0x31f40d0b,
+	0x0232f401,
+	0x09aa21f5,
+/* 0x063c: chsw_done */
+	0xf10127f0,
+	0xf0c30007,
+	0x02d00203,
+	0xbd04bd00,
+	0x0499f094,
+	0x170007f1,
 	0xd00203f0,
 	0x04bd0009,
-	0xf40132f4,
-	0x21f50232,
-	0x94bd0801,
+	0xff080ef5,
+/* 0x0660: main_not_ctx_switch */
+	0xf401e4b0,
+	0xf2b90d1b,
+	0x4221f502,
+	0x460ef409,
+/* 0x0670: main_not_ctx_chan */
+	0xf402e4b0,
+	0x94bd321b,
 	0xf10799f0,
-	0xf0170007,
+	0xf0370007,
 	0x09d00203,
 	0xf404bd00,
-/* 0x058e: main_not_ctx_save */
-	0xef94110e,
-	0x01f5f010,
-	0x02fe21f5,
-	0xfec00ef5,
-/* 0x059c: main_done */
-	0x29f024bd,
-	0x0007f11f,
-	0x0203f030,
-	0xbd0002d0,
-	0xab0ef504,
-/* 0x05b1: ih */
-	0xfe80f9fe,
-	0x80f90188,
-	0xa0f990f9,
-	0xd0f9b0f9,
-	0xf0f9e0f9,
-	0x0acf04bd,
-	0x04abc480,
-	0xf11d0bf4,
-	0xf01900b7,
-	0xbecf10d7,
-	0x00bfcf40,
+	0x32f40132,
+	0xaa21f502,
+	0xf094bd09,
+	0x07f10799,
+	0x03f01700,
+	0x0009d002,
+	0x0ef404bd,
+/* 0x06a5: main_not_ctx_save */
+	0x10ef9411,
+	0xf501f5f0,
+	0xf5037e21,
+/* 0x06b3: main_done */
+	0xbdfeb50e,
+	0x1f29f024,
+	0x300007f1,
+	0xd00203f0,
+	0x04bd0002,
+	0xfea00ef5,
+/* 0x06c8: ih */
+	0x88fe80f9,
+	0xf980f901,
+	0xf9a0f990,
+	0xf9d0f9b0,
+	0xbdf0f9e0,
+	0x00a7f104,
+	0x00a3f002,
+	0xc400aacf,
+	0x0bf404ab,
+	0x10d7f030,
+	0x1a00e7f1,
+	0xcf00e3f0,
+	0xf7f100ee,
+	0xf3f01900,
+	0x00ffcf00,
 	0xb70421f4,
 	0xf00400b0,
-	0xbed001e7,
-/* 0x05e9: ih_no_fifo */
-	0x00abe400,
-	0x0d0bf401,
-	0xf110d7f0,
-	0xf44001e7,
-/* 0x05fa: ih_no_ctxsw */
-	0xb7f10421,
-	0xb0bd0104,
-	0xf4b4abff,
-	0xa7f10d0b,
-	0xa4b60c1c,
-	0x00abd006,
-/* 0x0610: ih_no_other */
-	0xfc400ad0,
+	0x07f101e7,
+	0x03f01d00,
+	0x000ed000,
+/* 0x071a: ih_no_fifo */
+	0xabe404bd,
+	0x0bf40100,
+	0x10d7f00d,
+	0x4001e7f1,
+/* 0x072b: ih_no_ctxsw */
+	0xe40421f4,
+	0xf40400ab,
+	0xb7f1140b,
+	0xbfb90100,
+	0x44e7f102,
+	0x40e3f001,
+/* 0x0743: ih_no_fwmthd */
+	0xf19d21f4,
+	0xbd0104b7,
+	0xb4abffb0,
+	0xf10f0bf4,
+	0xf0070007,
+	0x0bd00303,
+/* 0x075b: ih_no_other */
+	0xf104bd00,
+	0xf0010007,
+	0x0ad00003,
+	0xfc04bd00,
 	0xfce0fcf0,
 	0xfcb0fcd0,
 	0xfc90fca0,
 	0x0088fe80,
 	0x32f480fc,
-/* 0x062b: ctx_4170s */
-	0xf101f800,
-	0xf04170e7,
-	0xf5f040e3,
-	0x8d21f410,
-/* 0x063a: ctx_4170w */
+/* 0x077f: ctx_4170s */
+	0xf001f800,
+	0xffb910f5,
+	0x70e7f102,
+	0x40e3f041,
+	0xf89d21f4,
+/* 0x0791: ctx_4170w */
+	0x70e7f100,
+	0x40e3f041,
+	0xb96821f4,
+	0xf4f002ff,
+	0xf01bf410,
+/* 0x07a6: ctx_redswitch */
 	0xe7f100f8,
-	0xe3f04170,
-	0x6821f440,
-	0xf410f4f0,
+	0xe5f00200,
+	0x20e5f040,
+	0xf110e5f0,
+	0xf0850007,
+	0x0ed00103,
+	0xf004bd00,
+/* 0x07c2: ctx_redswitch_delay */
+	0xf2b608f7,
+	0xfd1bf401,
+	0x0400e5f1,
+	0x0100e5f1,
+	0x850007f1,
+	0xd00103f0,
+	0x04bd000e,
+/* 0x07de: ctx_86c */
+	0x07f100f8,
+	0x03f02300,
+	0x000fd002,
+	0xffb904bd,
+	0x14e7f102,
+	0x40e3f08a,
+	0xb99d21f4,
+	0xe7f102ff,
+	0xe3f0a88c,
+	0x9d21f441,
+/* 0x0806: ctx_mem */
+	0x07f100f8,
+	0x03f08400,
+	0x000fd002,
+/* 0x0812: ctx_mem_wait */
+	0xf7f104bd,
+	0xf3f08400,
+	0x00ffcf02,
+	0xf405fffd,
 	0x00f8f31b,
-/* 0x064c: ctx_redswitch */
-	0x0614e7f1,
-	0xf106e4b6,
-	0xd00270f7,
-	0xf7f000ef,
-/* 0x065d: ctx_redswitch_delay */
-	0x01f2b608,
-	0xf1fd1bf4,
-	0xd00770f7,
-	0x00f800ef,
-/* 0x066c: ctx_86c */
-	0x086ce7f1,
-	0xd006e4b6,
-	0xe7f100ef,
-	0xe3f08a14,
-	0x8d21f440,
-	0xa86ce7f1,
-	0xf441e3f0,
-	0x00f88d21,
-/* 0x068c: ctx_load */
+/* 0x0824: ctx_load */
 	0x99f094bd,
 	0x0007f105,
 	0x0203f037,
 	0xbd0009d0,
 	0x0ca7f004,
-	0xf1c921f4,
-	0xb60a2417,
-	0x10d00614,
-	0x0037f100,
-	0x0634b60b,
-	0xf14032d0,
-	0xb60a0c17,
-	0x47f00614,
-	0x0012d007,
-/* 0x06c7: ctx_chan_wait_0 */
-	0xcf4014d0,
-	0x44f04014,
-	0xfa1bf41f,
-	0xfe0032d0,
-	0x2af0000b,
-	0x0424b61f,
-	0xbd0220b6,
+	0xbdd021f4,
+	0x0007f1f4,
+	0x0203f089,
+	0xbd000fd0,
+	0x0007f104,
+	0x0203f0c1,
+	0xbd0002d0,
+	0x0007f104,
+	0x0203f083,
+	0xbd0002d0,
+	0x07f7f004,
+	0x080621f5,
+	0xc00007f1,
+	0xd00203f0,
+	0x04bd0002,
+	0xf0000bfe,
+	0x24b61f2a,
+	0x0220b604,
+	0x99f094bd,
+	0x0007f108,
+	0x0203f037,
+	0xbd0009d0,
+	0x0007f104,
+	0x0203f081,
+	0xbd0002d0,
+	0x0027f104,
+	0x0023f100,
+	0x0225f080,
+	0x880007f1,
+	0xd00203f0,
+	0x04bd0002,
+	0xf11017f0,
+	0xf0020027,
+	0x12fa0223,
+	0xbd03f805,
 	0x0899f094,
-	0x370007f1,
+	0x170007f1,
 	0xd00203f0,
 	0x04bd0009,
-	0x0a0417f1,
-	0xd00614b6,
-	0x17f10012,
-	0x14b60a20,
-	0x0227f006,
-	0x800023f1,
-	0xf00012d0,
-	0x27f11017,
-	0x23f00200,
-	0x0512fa02,
-	0x94bd03f8,
-	0xf10899f0,
-	0xf0170007,
+	0xb6810198,
+	0x02981814,
+	0x0825b680,
+	0x800512fd,
+	0x94bd1601,
+	0xf10999f0,
+	0xf0370007,
 	0x09d00203,
-	0x9804bd00,
-	0x14b68101,
-	0x80029818,
-	0xfd0825b6,
-	0x01800512,
-	0xf094bd16,
-	0x07f10999,
-	0x03f03700,
-	0x0009d002,
-	0x27f104bd,
-	0x24b60a04,
-	0x0021d006,
-	0xf10127f0,
-	0xb60a2017,
-	0x12d00614,
-	0x0017f100,
-	0x0613f001,
-	0xf80501fa,
-	0xf094bd03,
-	0x07f10999,
-	0x03f01700,
-	0x0009d002,
-	0x94bd04bd,
-	0xf10599f0,
+	0xf104bd00,
+	0xf0810007,
+	0x01d00203,
+	0xf004bd00,
+	0x07f10127,
+	0x03f08800,
+	0x0002d002,
+	0x17f104bd,
+	0x13f00100,
+	0x0501fa06,
+	0x94bd03f8,
+	0xf10999f0,
 	0xf0170007,
 	0x09d00203,
-	0xf804bd00,
-/* 0x0795: ctx_chan */
-	0x8c21f500,
-	0x0ca7f006,
-	0xf1c921f4,
-	0xb60a1017,
-	0x27f00614,
-	0x0012d005,
-/* 0x07ac: ctx_chan_wait */
-	0xfd0012cf,
-	0x1bf40522,
-/* 0x07b7: ctx_mmio_exec */
-	0x9800f8fa,
-	0x27f14103,
-	0x24b60a04,
-	0x0023d006,
-/* 0x07c6: ctx_mmio_loop */
+	0xbd04bd00,
+	0x0599f094,
+	0x170007f1,
+	0xd00203f0,
+	0x04bd0009,
+/* 0x0942: ctx_chan */
+	0x21f500f8,
+	0xa7f00824,
+	0xd021f40c,
+	0xf505f7f0,
+	0xf8080621,
+/* 0x0955: ctx_mmio_exec */
+	0x41039800,
+	0x810007f1,
+	0xd00203f0,
+	0x04bd0003,
+/* 0x0966: ctx_mmio_loop */
 	0x34c434bd,
 	0x0f1bf4ff,
 	0x020057f1,
 	0xfa0653f0,
 	0x03f80535,
-/* 0x07d8: ctx_mmio_pull */
+/* 0x0978: ctx_mmio_pull */
 	0x98804e98,
 	0x21f4814f,
-	0x0830b68d,
+	0x0830b69d,
 	0xf40112b6,
-/* 0x07ea: ctx_mmio_done */
+/* 0x098a: ctx_mmio_done */
 	0x0398df1b,
-	0x0023d016,
-	0xf1400080,
-	0xf0010017,
-	0x01fa0613,
-	0xf803f806,
-/* 0x0801: ctx_xfer */
-	0x00f7f100,
-	0x06f4b60c,
-	0xd004e7f0,
-/* 0x080e: ctx_xfer_idle */
-	0xfecf80fe,
-	0x00e4f100,
-	0xf91bf420,
-	0xf40611f4,
-/* 0x081e: ctx_xfer_pre */
-	0xf7f00d02,
-	0x6c21f510,
-	0x1c11f406,
-/* 0x0828: ctx_xfer_pre_load */
-	0xf502f7f0,
-	0xf5062b21,
-	0xf5063a21,
-	0xbd064c21,
-	0x2b21f5f4,
-	0x8c21f506,
-/* 0x0841: ctx_xfer_exec */
-	0x16019806,
-	0x041427f1,
-	0xd00624b6,
-	0xe7f10020,
-	0xe3f0a500,
-	0x021fb941,
-	0xb68d21f4,
-	0xfcf004e0,
-	0x022cf001,
-	0xfd0124b6,
-	0x21f405f2,
-	0xfc17f18d,
-	0x0213f04a,
-	0xd00c27f0,
-	0x21f50012,
-	0x27f10215,
-	0x23f047fc,
-	0x0020d002,
+	0x0007f116,
+	0x0203f081,
+	0xbd0003d0,
+	0x40008004,
+	0x010017f1,
+	0xfa0613f0,
+	0x03f80601,
+/* 0x09aa: ctx_xfer */
+	0xe7f000f8,
+	0x0007f104,
+	0x0303f002,
+	0xbd000ed0,
+/* 0x09b9: ctx_xfer_idle */
+	0x00e7f104,
+	0x03e3f000,
+	0xf100eecf,
+	0xf42000e4,
+	0x11f4f21b,
+	0x0d02f406,
+/* 0x09d0: ctx_xfer_pre */
+	0xf510f7f0,
+	0xf407de21,
+/* 0x09da: ctx_xfer_pre_load */
+	0xf7f01c11,
+	0x7f21f502,
+	0x9121f507,
+	0xa621f507,
+	0xf5f4bd07,
+	0xf5077f21,
+/* 0x09f3: ctx_xfer_exec */
+	0x98082421,
+	0x24bd1601,
+	0x050007f1,
+	0xd00103f0,
+	0x04bd0002,
+	0xf1021fb9,
+	0xf0a500e7,
+	0x21f441e3,
+	0x01fcf09d,
+	0xb6022cf0,
+	0xf2fd0124,
+	0x02ffb905,
+	0xa504e7f1,
+	0xf441e3f0,
+	0x21f59d21,
+	0x24bd026a,
+	0x47fc07f1,
+	0xd00203f0,
+	0x04bd0002,
 	0xb6012cf0,
-	0x12d00320,
-	0x01acf000,
-	0xf006a5f0,
-	0x0c9800b7,
-	0x010d9800,
-	0xf500e7f0,
-	0xf0016621,
-	0x21f508a7,
-	0x21f50109,
-	0x01f40215,
-	0x0ca7f022,
-	0xf1c921f4,
-	0xb60a1017,
-	0x27f00614,
-	0x0012d005,
-/* 0x08c8: ctx_xfer_post_save_wait */
-	0xfd0012cf,
-	0x1bf40522,
-	0x2e02f4fa,
-/* 0x08d4: ctx_xfer_post */
-	0xf502f7f0,
-	0xbd062b21,
-	0x6c21f5f4,
-	0x3421f506,
-	0x3a21f502,
-	0xf5f4bd06,
-	0xf4062b21,
-	0x01981011,
-	0x0511fd40,
-	0xf5070bf4,
-/* 0x08ff: ctx_xfer_no_post_mmio */
-/* 0x08ff: ctx_xfer_done */
-	0xf807b721,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
+	0x07f10320,
+	0x03f04afc,
+	0x0002d002,
+	0xacf004bd,
+	0x06a5f001,
+	0x9800b7f0,
+	0x0d98000c,
+	0x00e7f001,
+	0x016f21f5,
+	0xf508a7f0,
+	0xf5011021,
+	0xf4025e21,
+	0xa7f01301,
+	0xd021f40c,
+	0xf505f7f0,
+	0xf4080621,
+/* 0x0a82: ctx_xfer_post */
+	0xf7f02e02,
+	0x7f21f502,
+	0xf5f4bd07,
+	0xf507de21,
+	0xf5027f21,
+	0xbd079121,
+	0x7f21f5f4,
+	0x1011f407,
+	0xfd400198,
+	0x0bf40511,
+	0x5521f507,
+/* 0x0aad: ctx_xfer_no_post_mmio */
+/* 0x0aad: ctx_xfer_done */
+	0x0000f809,
 	0x00000000,
 	0x00000000,
 	0x00000000,
diff --git a/drivers/gpu/drm/nouveau/core/engine/graph/fuc/macros.fuc b/drivers/gpu/drm/nouveau/core/engine/graph/fuc/macros.fuc
index 33a5a82eccbd6..6ffe28307dbd6 100644
--- a/drivers/gpu/drm/nouveau/core/engine/graph/fuc/macros.fuc
+++ b/drivers/gpu/drm/nouveau/core/engine/graph/fuc/macros.fuc
@@ -28,28 +28,135 @@
 #define GF117 0xd7
 #define GK100 0xe0
 #define GK110 0xf0
+#define GK208 0x108
 
+#define NV_PGRAPH_FECS_INTR_ACK                                        0x409004
+#define NV_PGRAPH_FECS_INTR                                            0x409008
+#define NV_PGRAPH_FECS_INTR_FWMTHD                                   0x00000400
+#define NV_PGRAPH_FECS_INTR_CHSW                                     0x00000100
+#define NV_PGRAPH_FECS_INTR_FIFO                                     0x00000004
+#define NV_PGRAPH_FECS_INTR_MODE                                       0x40900c
+#define NV_PGRAPH_FECS_INTR_MODE_FIFO                                0x00000004
+#define NV_PGRAPH_FECS_INTR_MODE_FIFO_LEVEL                          0x00000004
+#define NV_PGRAPH_FECS_INTR_MODE_FIFO_EDGE                           0x00000000
+#define NV_PGRAPH_FECS_INTR_EN_SET                                     0x409010
+#define NV_PGRAPH_FECS_INTR_EN_SET_FIFO                              0x00000004
+#define NV_PGRAPH_FECS_INTR_ROUTE                                      0x40901c
+#define NV_PGRAPH_FECS_ACCESS                                          0x409048
+#define NV_PGRAPH_FECS_ACCESS_FIFO                                   0x00000002
+#define NV_PGRAPH_FECS_FIFO_DATA                                       0x409064
+#define NV_PGRAPH_FECS_FIFO_CMD                                        0x409068
+#define NV_PGRAPH_FECS_FIFO_ACK                                        0x409074
+#define NV_PGRAPH_FECS_CAPS                                            0x409108
 #define NV_PGRAPH_FECS_SIGNAL                                          0x409400
+#define NV_PGRAPH_FECS_IROUTE                                          0x409404
+#define NV_PGRAPH_FECS_BAR_MASK0                                       0x40940c
+#define NV_PGRAPH_FECS_BAR_MASK1                                       0x409410
+#define NV_PGRAPH_FECS_BAR                                             0x409414
+#define NV_PGRAPH_FECS_BAR_SET                                         0x409418
+#define NV_PGRAPH_FECS_RED_SWITCH                                      0x409614
+#define NV_PGRAPH_FECS_RED_SWITCH_ENABLE_ROP                         0x00000400
+#define NV_PGRAPH_FECS_RED_SWITCH_ENABLE_GPC                         0x00000200
+#define NV_PGRAPH_FECS_RED_SWITCH_ENABLE_MAIN                        0x00000100
+#define NV_PGRAPH_FECS_RED_SWITCH_POWER_ROP                          0x00000040
+#define NV_PGRAPH_FECS_RED_SWITCH_POWER_GPC                          0x00000020
+#define NV_PGRAPH_FECS_RED_SWITCH_POWER_MAIN                         0x00000010
+#define NV_PGRAPH_FECS_RED_SWITCH_PAUSE_GPC                          0x00000002
+#define NV_PGRAPH_FECS_RED_SWITCH_PAUSE_MAIN                         0x00000001
+#define NV_PGRAPH_FECS_MMCTX_SAVE_SWBASE                               0x409700
+#define NV_PGRAPH_FECS_MMCTX_LOAD_SWBASE                               0x409704
+#define NV_PGRAPH_FECS_MMCTX_LOAD_COUNT                                0x40974c
+#define NV_PGRAPH_FECS_MMCTX_SAVE_SWBASE                               0x409700
+#define NV_PGRAPH_FECS_MMCTX_LOAD_SWBASE                               0x409704
+#define NV_PGRAPH_FECS_MMCTX_BASE                                      0x409710
+#define NV_PGRAPH_FECS_MMCTX_CTRL                                      0x409714
+#define NV_PGRAPH_FECS_MMCTX_MULTI_STRIDE                              0x409718
+#define NV_PGRAPH_FECS_MMCTX_MULTI_MASK                                0x40971c
+#define NV_PGRAPH_FECS_MMCTX_QUEUE                                     0x409720
+#define NV_PGRAPH_FECS_MMIO_CTRL                                       0x409728
+#define NV_PGRAPH_FECS_MMIO_RDVAL                                      0x40972c
+#define NV_PGRAPH_FECS_MMIO_WRVAL                                      0x409730
+#define NV_PGRAPH_FECS_MMCTX_LOAD_COUNT                                0x40974c
 #if CHIPSET < GK110
 #define NV_PGRAPH_FECS_CC_SCRATCH_VAL(n)                    ((n) * 4 + 0x409800)
 #define NV_PGRAPH_FECS_CC_SCRATCH_SET(n)                    ((n) * 4 + 0x409820)
 #define NV_PGRAPH_FECS_CC_SCRATCH_CLR(n)                    ((n) * 4 + 0x409840)
+#define NV_PGRAPH_FECS_UNK86C                                          0x40986c
 #else
 #define NV_PGRAPH_FECS_CC_SCRATCH_VAL(n)                    ((n) * 4 + 0x409800)
 #define NV_PGRAPH_FECS_CC_SCRATCH_CLR(n)                    ((n) * 4 + 0x409840)
+#define NV_PGRAPH_FECS_UNK86C                                          0x40988c
 #define NV_PGRAPH_FECS_CC_SCRATCH_SET(n)                    ((n) * 4 + 0x4098c0)
 #endif
+#define NV_PGRAPH_FECS_STRANDS_CNT                                     0x409880
+#define NV_PGRAPH_FECS_STRAND_SAVE_SWBASE                              0x409908
+#define NV_PGRAPH_FECS_STRAND_LOAD_SWBASE                              0x40990c
+#define NV_PGRAPH_FECS_STRAND_WORDS                                    0x409910
+#define NV_PGRAPH_FECS_STRAND_DATA                                     0x409918
+#define NV_PGRAPH_FECS_STRAND_SELECT                                   0x40991c
+#define NV_PGRAPH_FECS_STRAND_CMD                                      0x409928
+#define NV_PGRAPH_FECS_STRAND_CMD_SEEK                               0x00000001
+#define NV_PGRAPH_FECS_STRAND_CMD_GET_INFO                           0x00000002
+#define NV_PGRAPH_FECS_STRAND_CMD_SAVE                               0x00000003
+#define NV_PGRAPH_FECS_STRAND_CMD_LOAD                               0x00000004
+#define NV_PGRAPH_FECS_STRAND_CMD_ACTIVATE_FILTER                    0x0000000a
+#define NV_PGRAPH_FECS_STRAND_CMD_DEACTIVATE_FILTER                  0x0000000b
+#define NV_PGRAPH_FECS_STRAND_CMD_ENABLE                             0x0000000c
+#define NV_PGRAPH_FECS_STRAND_CMD_DISABLE                            0x0000000d
+#define NV_PGRAPH_FECS_STRAND_FILTER                                   0x40993c
+#define NV_PGRAPH_FECS_MEM_BASE                                        0x409a04
+#define NV_PGRAPH_FECS_MEM_CHAN                                        0x409a0c
+#define NV_PGRAPH_FECS_MEM_CMD                                         0x409a10
+#define NV_PGRAPH_FECS_MEM_CMD_LOAD_CHAN                             0x00000007
+#define NV_PGRAPH_FECS_MEM_TARGET                                      0x409a20
+#define NV_PGRAPH_FECS_MEM_TARGET_UNK31                              0x80000000
+#define NV_PGRAPH_FECS_MEM_TARGET_AS                                 0x0000001f
+#define NV_PGRAPH_FECS_MEM_TARGET_AS_VM                              0x00000001
+#define NV_PGRAPH_FECS_MEM_TARGET_AS_VRAM                            0x00000002
+#define NV_PGRAPH_FECS_CHAN_ADDR                                       0x409b00
+#define NV_PGRAPH_FECS_CHAN_NEXT                                       0x409b04
+#define NV_PGRAPH_FECS_CHSW                                            0x409b0c
+#define NV_PGRAPH_FECS_CHSW_ACK                                      0x00000001
 #define NV_PGRAPH_FECS_INTR_UP_SET                                     0x409c1c
+#define NV_PGRAPH_FECS_INTR_UP_EN                                      0x409c24
 
+#define NV_PGRAPH_GPCX_GPCCS_INTR_ACK                                  0x41a004
+#define NV_PGRAPH_GPCX_GPCCS_INTR                                      0x41a008
+#define NV_PGRAPH_GPCX_GPCCS_INTR_FIFO                               0x00000004
+#define NV_PGRAPH_GPCX_GPCCS_INTR_EN_SET                               0x41a010
+#define NV_PGRAPH_GPCX_GPCCS_INTR_EN_SET_FIFO                        0x00000004
+#define NV_PGRAPH_GPCX_GPCCS_INTR_ROUTE                                0x41a01c
+#define NV_PGRAPH_GPCX_GPCCS_ACCESS                                    0x41a048
+#define NV_PGRAPH_GPCX_GPCCS_ACCESS_FIFO                             0x00000002
+#define NV_PGRAPH_GPCX_GPCCS_FIFO_DATA                                 0x41a064
+#define NV_PGRAPH_GPCX_GPCCS_FIFO_CMD                                  0x41a068
+#define NV_PGRAPH_GPCX_GPCCS_FIFO_ACK                                  0x41a074
+#define NV_PGRAPH_GPCX_GPCCS_UNITS                                     0x41a608
+#define NV_PGRAPH_GPCX_GPCCS_RED_SWITCH                                0x41a614
+#define NV_PGRAPH_GPCX_GPCCS_RED_SWITCH_UNK11                        0x00000800
+#define NV_PGRAPH_GPCX_GPCCS_RED_SWITCH_ENABLE                       0x00000200
+#define NV_PGRAPH_GPCX_GPCCS_RED_SWITCH_POWER                        0x00000020
+#define NV_PGRAPH_GPCX_GPCCS_RED_SWITCH_PAUSE                        0x00000002
+#define NV_PGRAPH_GPCX_GPCCS_MYINDEX                                   0x41a618
+#define NV_PGRAPH_GPCX_GPCCS_MMCTX_SAVE_SWBASE                         0x41a700
+#define NV_PGRAPH_GPCX_GPCCS_MMCTX_LOAD_SWBASE                         0x41a704
+#define NV_PGRAPH_GPCX_GPCCS_MMCTX_LOAD_COUNT                          0x41a74c
 #if CHIPSET < GK110
 #define NV_PGRAPH_GPCX_GPCCS_CC_SCRATCH_VAL(n)              ((n) * 4 + 0x41a800)
 #define NV_PGRAPH_GPCX_GPCCS_CC_SCRATCH_SET(n)              ((n) * 4 + 0x41a820)
 #define NV_PGRAPH_GPCX_GPCCS_CC_SCRATCH_CLR(n)              ((n) * 4 + 0x41a840)
+#define NV_PGRAPH_GPCX_GPCCS_UNK86C                                    0x41a86c
 #else
 #define NV_PGRAPH_GPCX_GPCCS_CC_SCRATCH_VAL(n)              ((n) * 4 + 0x41a800)
 #define NV_PGRAPH_GPCX_GPCCS_CC_SCRATCH_CLR(n)              ((n) * 4 + 0x41a840)
+#define NV_PGRAPH_GPCX_GPCCS_UNK86C                                    0x41a88c
 #define NV_PGRAPH_GPCX_GPCCS_CC_SCRATCH_SET(n)              ((n) * 4 + 0x41a8c0)
 #endif
+#define NV_PGRAPH_GPCX_GPCCS_STRAND_SELECT                             0x41a91c
+#define NV_PGRAPH_GPCX_GPCCS_STRAND_CMD                                0x41a928
+#define NV_PGRAPH_GPCX_GPCCS_STRAND_CMD_SAVE                         0x00000003
+#define NV_PGRAPH_GPCX_GPCCS_STRAND_CMD_LOAD                         0x00000004
+#define NV_PGRAPH_GPCX_GPCCS_MEM_BASE                                  0x41aa04
 
 #define mmctx_data(r,c) .b32 (((c - 1) << 26) | r)
 #define queue_init      .skip 72 // (2 * 4) + ((8 * 4) * 2)
@@ -65,24 +172,50 @@
 #define T_LCHAN   8
 #define T_LCTXH   9
 
-#define nv_mkmm(rv,r) /*
-*/	movw rv  ((r) & 0x0000fffc) /*
-*/	sethi rv ((r) & 0x00ff0000)
+#if CHIPSET < GK208
+#define imm32(reg,val) /*
+*/	movw reg  ((val) & 0x0000ffff) /*
+*/	sethi reg ((val) & 0xffff0000)
+#else
+#define imm32(reg,val) /*
+*/	mov reg (val)
+#endif
+
 #define nv_mkio(rv,r,i) /*
-*/	nv_mkmm(rv, (((r) & 0xffc) << 6) | ((i) << 2))
+*/	imm32(rv, (((r) & 0xffc) << 6) | ((i) << 2))
+
+#define hash #
+#define fn(a) a
+#if CHIPSET < GK208
+#define call(a) call fn(hash)a
+#else
+#define call(a) lcall fn(hash)a
+#endif
 
 #define nv_iord(rv,r,i) /*
 */	nv_mkio(rv,r,i) /*
 */	iord rv I[rv]
+
 #define nv_iowr(r,i,rv) /*
 */	nv_mkio($r0,r,i) /*
 */	iowr I[$r0] rv /*
 */	clear b32 $r0
 
+#define nv_rd32(reg,addr) /*
+*/	imm32($r14, addr) /*
+*/	call(nv_rd32) /*
+*/	mov b32 reg $r15
+
+#define nv_wr32(addr,reg) /*
+*/	mov b32 $r15 reg /*
+*/	imm32($r14, addr) /*
+*/	call(nv_wr32)
+
 #define trace_set(bit) /*
 */	clear b32 $r9 /*
 */	bset $r9 bit /*
 */	nv_iowr(NV_PGRAPH_FECS_CC_SCRATCH_SET(7), 0, $r9)
+
 #define trace_clr(bit) /*
 */	clear b32 $r9 /*
 */	bset $r9 bit /*
diff --git a/drivers/gpu/drm/nouveau/core/engine/graph/nv108.c b/drivers/gpu/drm/nouveau/core/engine/graph/nv108.c
new file mode 100644
index 0000000000000..e1af65ead3798
--- /dev/null
+++ b/drivers/gpu/drm/nouveau/core/engine/graph/nv108.c
@@ -0,0 +1,236 @@
+/*
+ * Copyright 2013 Red Hat Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: Ben Skeggs <bskeggs@redhat.com>
+ */
+
+#include "nvc0.h"
+
+/*******************************************************************************
+ * Graphics object classes
+ ******************************************************************************/
+
+static struct nouveau_oclass
+nv108_graph_sclass[] = {
+	{ 0x902d, &nouveau_object_ofuncs },
+	{ 0xa140, &nouveau_object_ofuncs },
+	{ 0xa197, &nouveau_object_ofuncs },
+	{ 0xa1c0, &nouveau_object_ofuncs },
+	{}
+};
+
+/*******************************************************************************
+ * PGRAPH engine/subdev functions
+ ******************************************************************************/
+
+static struct nvc0_graph_init
+nv108_graph_init_regs[] = {
+	{ 0x400080,   1, 0x04, 0x003083c2 },
+	{ 0x400088,   1, 0x04, 0x0001bfe7 },
+	{ 0x40008c,   1, 0x04, 0x00000000 },
+	{ 0x400090,   1, 0x04, 0x00000030 },
+	{ 0x40013c,   1, 0x04, 0x003901f7 },
+	{ 0x400140,   1, 0x04, 0x00000100 },
+	{ 0x400144,   1, 0x04, 0x00000000 },
+	{ 0x400148,   1, 0x04, 0x00000110 },
+	{ 0x400138,   1, 0x04, 0x00000000 },
+	{ 0x400130,   2, 0x04, 0x00000000 },
+	{ 0x400124,   1, 0x04, 0x00000002 },
+	{}
+};
+
+struct nvc0_graph_init
+nv108_graph_init_unk58xx[] = {
+	{ 0x405844,   1, 0x04, 0x00ffffff },
+	{ 0x405850,   1, 0x04, 0x00000000 },
+	{ 0x405900,   1, 0x04, 0x00000000 },
+	{ 0x405908,   1, 0x04, 0x00000000 },
+	{ 0x405928,   1, 0x04, 0x00000000 },
+	{ 0x40592c,   1, 0x04, 0x00000000 },
+	{}
+};
+
+static struct nvc0_graph_init
+nv108_graph_init_gpc[] = {
+	{ 0x418408,   1, 0x04, 0x00000000 },
+	{ 0x4184a0,   3, 0x04, 0x00000000 },
+	{ 0x418604,   1, 0x04, 0x00000000 },
+	{ 0x418680,   1, 0x04, 0x00000000 },
+	{ 0x418714,   1, 0x04, 0x00000000 },
+	{ 0x418384,   2, 0x04, 0x00000000 },
+	{ 0x418814,   3, 0x04, 0x00000000 },
+	{ 0x418b04,   1, 0x04, 0x00000000 },
+	{ 0x4188c8,   2, 0x04, 0x00000000 },
+	{ 0x4188d0,   1, 0x04, 0x00010000 },
+	{ 0x4188d4,   1, 0x04, 0x00000201 },
+	{ 0x418910,   1, 0x04, 0x00010001 },
+	{ 0x418914,   1, 0x04, 0x00000301 },
+	{ 0x418918,   1, 0x04, 0x00800000 },
+	{ 0x418980,   1, 0x04, 0x77777770 },
+	{ 0x418984,   3, 0x04, 0x77777777 },
+	{ 0x418c04,   1, 0x04, 0x00000000 },
+	{ 0x418c64,   2, 0x04, 0x00000000 },
+	{ 0x418c88,   1, 0x04, 0x00000000 },
+	{ 0x418cb4,   2, 0x04, 0x00000000 },
+	{ 0x418d00,   1, 0x04, 0x00000000 },
+	{ 0x418d28,   2, 0x04, 0x00000000 },
+	{ 0x418f00,   1, 0x04, 0x00000400 },
+	{ 0x418f08,   1, 0x04, 0x00000000 },
+	{ 0x418f20,   2, 0x04, 0x00000000 },
+	{ 0x418e00,   1, 0x04, 0x00000000 },
+	{ 0x418e08,   1, 0x04, 0x00000000 },
+	{ 0x418e1c,   2, 0x04, 0x00000000 },
+	{ 0x41900c,   1, 0x04, 0x00000000 },
+	{ 0x419018,   1, 0x04, 0x00000000 },
+	{}
+};
+
+static struct nvc0_graph_init
+nv108_graph_init_tpc[] = {
+	{ 0x419d0c,   1, 0x04, 0x00000000 },
+	{ 0x419d10,   1, 0x04, 0x00000014 },
+	{ 0x419ab0,   1, 0x04, 0x00000000 },
+	{ 0x419ac8,   1, 0x04, 0x00000000 },
+	{ 0x419ab8,   1, 0x04, 0x000000e7 },
+	{ 0x419abc,   2, 0x04, 0x00000000 },
+	{ 0x419ab4,   1, 0x04, 0x00000000 },
+	{ 0x419aa8,   2, 0x04, 0x00000000 },
+	{ 0x41980c,   1, 0x04, 0x00000010 },
+	{ 0x419844,   1, 0x04, 0x00000000 },
+	{ 0x419850,   1, 0x04, 0x00000004 },
+	{ 0x419854,   2, 0x04, 0x00000000 },
+	{ 0x419c98,   1, 0x04, 0x00000000 },
+	{ 0x419ca8,   1, 0x04, 0x00000000 },
+	{ 0x419cb0,   1, 0x04, 0x01000000 },
+	{ 0x419cb4,   1, 0x04, 0x00000000 },
+	{ 0x419cb8,   1, 0x04, 0x00b08bea },
+	{ 0x419c84,   1, 0x04, 0x00010384 },
+	{ 0x419cbc,   1, 0x04, 0x281b3646 },
+	{ 0x419cc0,   2, 0x04, 0x00000000 },
+	{ 0x419c80,   1, 0x04, 0x00000230 },
+	{ 0x419ccc,   2, 0x04, 0x00000000 },
+	{ 0x419c0c,   1, 0x04, 0x00000000 },
+	{ 0x419e00,   1, 0x04, 0x00000080 },
+	{ 0x419ea0,   1, 0x04, 0x00000000 },
+	{ 0x419ee4,   1, 0x04, 0x00000000 },
+	{ 0x419ea4,   1, 0x04, 0x00000100 },
+	{ 0x419ea8,   1, 0x04, 0x00000000 },
+	{ 0x419eb4,   1, 0x04, 0x00000000 },
+	{ 0x419ebc,   2, 0x04, 0x00000000 },
+	{ 0x419edc,   1, 0x04, 0x00000000 },
+	{ 0x419f00,   1, 0x04, 0x00000000 },
+	{ 0x419ed0,   1, 0x04, 0x00003234 },
+	{ 0x419f74,   1, 0x04, 0x00015555 },
+	{ 0x419f80,   4, 0x04, 0x00000000 },
+	{}
+};
+
+static int
+nv108_graph_fini(struct nouveau_object *object, bool suspend)
+{
+	struct nvc0_graph_priv *priv = (void *)object;
+	static const struct {
+		u32 addr;
+		u32 data;
+	} magic[] = {
+		{ 0x020520, 0xfffffffc },
+		{ 0x020524, 0xfffffffe },
+		{ 0x020524, 0xfffffffc },
+		{ 0x020524, 0xfffffff8 },
+		{ 0x020524, 0xffffffe0 },
+		{ 0x020530, 0xfffffffe },
+		{ 0x02052c, 0xfffffffa },
+		{ 0x02052c, 0xfffffff0 },
+		{ 0x02052c, 0xffffffc0 },
+		{ 0x02052c, 0xffffff00 },
+		{ 0x02052c, 0xfffffc00 },
+		{ 0x02052c, 0xfffcfc00 },
+		{ 0x02052c, 0xfff0fc00 },
+		{ 0x02052c, 0xff80fc00 },
+		{ 0x020528, 0xfffffffe },
+		{ 0x020528, 0xfffffffc },
+	};
+	int i;
+
+	nv_mask(priv, 0x000200, 0x08001000, 0x00000000);
+	nv_mask(priv, 0x0206b4, 0x00000000, 0x00000000);
+	for (i = 0; i < ARRAY_SIZE(magic); i++) {
+		nv_wr32(priv, magic[i].addr, magic[i].data);
+		nv_wait(priv, magic[i].addr, 0x80000000, 0x00000000);
+	}
+
+	return nouveau_graph_fini(&priv->base, suspend);
+}
+
+static struct nvc0_graph_init *
+nv108_graph_init_mmio[] = {
+	nv108_graph_init_regs,
+	nvf0_graph_init_unk40xx,
+	nvc0_graph_init_unk44xx,
+	nvc0_graph_init_unk78xx,
+	nvc0_graph_init_unk60xx,
+	nvd9_graph_init_unk64xx,
+	nv108_graph_init_unk58xx,
+	nvc0_graph_init_unk80xx,
+	nvf0_graph_init_unk70xx,
+	nvf0_graph_init_unk5bxx,
+	nv108_graph_init_gpc,
+	nv108_graph_init_tpc,
+	nve4_graph_init_unk,
+	nve4_graph_init_unk88xx,
+	NULL
+};
+
+#include "fuc/hubnv108.fuc5.h"
+
+static struct nvc0_graph_ucode
+nv108_graph_fecs_ucode = {
+	.code.data = nv108_grhub_code,
+	.code.size = sizeof(nv108_grhub_code),
+	.data.data = nv108_grhub_data,
+	.data.size = sizeof(nv108_grhub_data),
+};
+
+#include "fuc/gpcnv108.fuc5.h"
+
+static struct nvc0_graph_ucode
+nv108_graph_gpccs_ucode = {
+	.code.data = nv108_grgpc_code,
+	.code.size = sizeof(nv108_grgpc_code),
+	.data.data = nv108_grgpc_data,
+	.data.size = sizeof(nv108_grgpc_data),
+};
+
+struct nouveau_oclass *
+nv108_graph_oclass = &(struct nvc0_graph_oclass) {
+	.base.handle = NV_ENGINE(GR, 0x08),
+	.base.ofuncs = &(struct nouveau_ofuncs) {
+		.ctor = nvc0_graph_ctor,
+		.dtor = nvc0_graph_dtor,
+		.init = nve4_graph_init,
+		.fini = nv108_graph_fini,
+	},
+	.cclass = &nv108_grctx_oclass,
+	.sclass =  nv108_graph_sclass,
+	.mmio = nv108_graph_init_mmio,
+	.fecs.ucode = &nv108_graph_fecs_ucode,
+	.gpccs.ucode = &nv108_graph_gpccs_ucode,
+}.base;
diff --git a/drivers/gpu/drm/nouveau/core/engine/graph/nv50.c b/drivers/gpu/drm/nouveau/core/engine/graph/nv50.c
index 03de5175dd9f8..30ed19c52e05c 100644
--- a/drivers/gpu/drm/nouveau/core/engine/graph/nv50.c
+++ b/drivers/gpu/drm/nouveau/core/engine/graph/nv50.c
@@ -304,12 +304,28 @@ nv84_graph_tlb_flush(struct nouveau_engine *engine)
 	return timeout ? -EBUSY : 0;
 }
 
-static const struct nouveau_enum nv50_mp_exec_error_names[] = {
-	{ 3, "STACK_UNDERFLOW", NULL },
-	{ 4, "QUADON_ACTIVE", NULL },
-	{ 8, "TIMEOUT", NULL },
-	{ 0x10, "INVALID_OPCODE", NULL },
-	{ 0x40, "BREAKPOINT", NULL },
+static const struct nouveau_bitfield nv50_mp_exec_errors[] = {
+	{ 0x01, "STACK_UNDERFLOW" },
+	{ 0x02, "STACK_MISMATCH" },
+	{ 0x04, "QUADON_ACTIVE" },
+	{ 0x08, "TIMEOUT" },
+	{ 0x10, "INVALID_OPCODE" },
+	{ 0x20, "PM_OVERFLOW" },
+	{ 0x40, "BREAKPOINT" },
+	{}
+};
+
+static const struct nouveau_bitfield nv50_mpc_traps[] = {
+	{ 0x0000001, "LOCAL_LIMIT_READ" },
+	{ 0x0000010, "LOCAL_LIMIT_WRITE" },
+	{ 0x0000040, "STACK_LIMIT" },
+	{ 0x0000100, "GLOBAL_LIMIT_READ" },
+	{ 0x0001000, "GLOBAL_LIMIT_WRITE" },
+	{ 0x0010000, "MP0" },
+	{ 0x0020000, "MP1" },
+	{ 0x0040000, "GLOBAL_LIMIT_RED" },
+	{ 0x0400000, "GLOBAL_LIMIT_ATOM" },
+	{ 0x4000000, "MP2" },
 	{}
 };
 
@@ -396,6 +412,60 @@ static const struct nouveau_bitfield nv50_graph_intr_name[] = {
 	{}
 };
 
+static const struct nouveau_bitfield nv50_graph_trap_prop[] = {
+	{ 0x00000004, "SURF_WIDTH_OVERRUN" },
+	{ 0x00000008, "SURF_HEIGHT_OVERRUN" },
+	{ 0x00000010, "DST2D_FAULT" },
+	{ 0x00000020, "ZETA_FAULT" },
+	{ 0x00000040, "RT_FAULT" },
+	{ 0x00000080, "CUDA_FAULT" },
+	{ 0x00000100, "DST2D_STORAGE_TYPE_MISMATCH" },
+	{ 0x00000200, "ZETA_STORAGE_TYPE_MISMATCH" },
+	{ 0x00000400, "RT_STORAGE_TYPE_MISMATCH" },
+	{ 0x00000800, "DST2D_LINEAR_MISMATCH" },
+	{ 0x00001000, "RT_LINEAR_MISMATCH" },
+	{}
+};
+
+static void
+nv50_priv_prop_trap(struct nv50_graph_priv *priv,
+		    u32 ustatus_addr, u32 ustatus, u32 tp)
+{
+	u32 e0c = nv_rd32(priv, ustatus_addr + 0x04);
+	u32 e10 = nv_rd32(priv, ustatus_addr + 0x08);
+	u32 e14 = nv_rd32(priv, ustatus_addr + 0x0c);
+	u32 e18 = nv_rd32(priv, ustatus_addr + 0x10);
+	u32 e1c = nv_rd32(priv, ustatus_addr + 0x14);
+	u32 e20 = nv_rd32(priv, ustatus_addr + 0x18);
+	u32 e24 = nv_rd32(priv, ustatus_addr + 0x1c);
+
+	/* CUDA memory: l[], g[] or stack. */
+	if (ustatus & 0x00000080) {
+		if (e18 & 0x80000000) {
+			/* g[] read fault? */
+			nv_error(priv, "TRAP_PROP - TP %d - CUDA_FAULT - Global read fault at address %02x%08x\n",
+					 tp, e14, e10 | ((e18 >> 24) & 0x1f));
+			e18 &= ~0x1f000000;
+		} else if (e18 & 0xc) {
+			/* g[] write fault? */
+			nv_error(priv, "TRAP_PROP - TP %d - CUDA_FAULT - Global write fault at address %02x%08x\n",
+				 tp, e14, e10 | ((e18 >> 7) & 0x1f));
+			e18 &= ~0x00000f80;
+		} else {
+			nv_error(priv, "TRAP_PROP - TP %d - Unknown CUDA fault at address %02x%08x\n",
+				 tp, e14, e10);
+		}
+		ustatus &= ~0x00000080;
+	}
+	if (ustatus) {
+		nv_error(priv, "TRAP_PROP - TP %d -", tp);
+		nouveau_bitfield_print(nv50_graph_trap_prop, ustatus);
+		pr_cont(" - Address %02x%08x\n", e14, e10);
+	}
+	nv_error(priv, "TRAP_PROP - TP %d - e0c: %08x, e18: %08x, e1c: %08x, e20: %08x, e24: %08x\n",
+		 tp, e0c, e18, e1c, e20, e24);
+}
+
 static void
 nv50_priv_mp_trap(struct nv50_graph_priv *priv, int tpid, int display)
 {
@@ -420,8 +490,8 @@ nv50_priv_mp_trap(struct nv50_graph_priv *priv, int tpid, int display)
 			oplow = nv_rd32(priv, addr + 0x70);
 			ophigh = nv_rd32(priv, addr + 0x74);
 			nv_error(priv, "TRAP_MP_EXEC - "
-					"TP %d MP %d: ", tpid, i);
-			nouveau_enum_print(nv50_mp_exec_error_names, status);
+					"TP %d MP %d:", tpid, i);
+			nouveau_bitfield_print(nv50_mp_exec_errors, status);
 			pr_cont(" at %06x warp %d, opcode %08x %08x\n",
 					pc&0xffffff, pc >> 24,
 					oplow, ophigh);
@@ -468,60 +538,19 @@ nv50_priv_tp_trap(struct nv50_graph_priv *priv, int type, u32 ustatus_old,
 				nv50_priv_mp_trap(priv, i, display);
 				ustatus &= ~0x04030000;
 			}
-			break;
-		case 8: /* TPDMA error */
-			{
-			u32 e0c = nv_rd32(priv, ustatus_addr + 4);
-			u32 e10 = nv_rd32(priv, ustatus_addr + 8);
-			u32 e14 = nv_rd32(priv, ustatus_addr + 0xc);
-			u32 e18 = nv_rd32(priv, ustatus_addr + 0x10);
-			u32 e1c = nv_rd32(priv, ustatus_addr + 0x14);
-			u32 e20 = nv_rd32(priv, ustatus_addr + 0x18);
-			u32 e24 = nv_rd32(priv, ustatus_addr + 0x1c);
-			/* 2d engine destination */
-			if (ustatus & 0x00000010) {
-				if (display) {
-					nv_error(priv, "TRAP_TPDMA_2D - TP %d - Unknown fault at address %02x%08x\n",
-							i, e14, e10);
-					nv_error(priv, "TRAP_TPDMA_2D - TP %d - e0c: %08x, e18: %08x, e1c: %08x, e20: %08x, e24: %08x\n",
-							i, e0c, e18, e1c, e20, e24);
-				}
-				ustatus &= ~0x00000010;
-			}
-			/* Render target */
-			if (ustatus & 0x00000040) {
-				if (display) {
-					nv_error(priv, "TRAP_TPDMA_RT - TP %d - Unknown fault at address %02x%08x\n",
-							i, e14, e10);
-					nv_error(priv, "TRAP_TPDMA_RT - TP %d - e0c: %08x, e18: %08x, e1c: %08x, e20: %08x, e24: %08x\n",
-							i, e0c, e18, e1c, e20, e24);
-				}
-				ustatus &= ~0x00000040;
-			}
-			/* CUDA memory: l[], g[] or stack. */
-			if (ustatus & 0x00000080) {
-				if (display) {
-					if (e18 & 0x80000000) {
-						/* g[] read fault? */
-						nv_error(priv, "TRAP_TPDMA - TP %d - Global read fault at address %02x%08x\n",
-								i, e14, e10 | ((e18 >> 24) & 0x1f));
-						e18 &= ~0x1f000000;
-					} else if (e18 & 0xc) {
-						/* g[] write fault? */
-						nv_error(priv, "TRAP_TPDMA - TP %d - Global write fault at address %02x%08x\n",
-								i, e14, e10 | ((e18 >> 7) & 0x1f));
-						e18 &= ~0x00000f80;
-					} else {
-						nv_error(priv, "TRAP_TPDMA - TP %d - Unknown CUDA fault at address %02x%08x\n",
-								i, e14, e10);
-					}
-					nv_error(priv, "TRAP_TPDMA - TP %d - e0c: %08x, e18: %08x, e1c: %08x, e20: %08x, e24: %08x\n",
-							i, e0c, e18, e1c, e20, e24);
-				}
-				ustatus &= ~0x00000080;
-			}
+			if (ustatus && display) {
+				nv_error("%s - TP%d:", name, i);
+				nouveau_bitfield_print(nv50_mpc_traps, ustatus);
+				pr_cont("\n");
+				ustatus = 0;
 			}
 			break;
+		case 8: /* PROP error */
+			if (display)
+				nv50_priv_prop_trap(
+						priv, ustatus_addr, ustatus, i);
+			ustatus = 0;
+			break;
 		}
 		if (ustatus) {
 			if (display)
@@ -727,11 +756,11 @@ nv50_graph_trap_handler(struct nv50_graph_priv *priv, u32 display,
 		status &= ~0x080;
 	}
 
-	/* TPDMA:  Handles TP-initiated uncached memory accesses:
+	/* PROP:  Handles TP-initiated uncached memory accesses:
 	 * l[], g[], stack, 2d surfaces, render targets. */
 	if (status & 0x100) {
 		nv50_priv_tp_trap(priv, 8, 0x408e08, 0x408708, display,
-				    "TRAP_TPDMA");
+				    "TRAP_PROP");
 		nv_wr32(priv, 0x400108, 0x100);
 		status &= ~0x100;
 	}
@@ -760,7 +789,7 @@ nv50_graph_intr(struct nouveau_subdev *subdev)
 	u32 mthd = (addr & 0x00001ffc);
 	u32 data = nv_rd32(priv, 0x400708);
 	u32 class = nv_rd32(priv, 0x400814);
-	u32 show = stat;
+	u32 show = stat, show_bitfield = stat;
 	int chid;
 
 	engctx = nouveau_engctx_get(engine, inst);
@@ -778,21 +807,26 @@ nv50_graph_intr(struct nouveau_subdev *subdev)
 		nv_error(priv, "DATA_ERROR ");
 		nouveau_enum_print(nv50_data_error_names, ecode);
 		pr_cont("\n");
+		show_bitfield &= ~0x00100000;
 	}
 
 	if (stat & 0x00200000) {
 		if (!nv50_graph_trap_handler(priv, show, chid, (u64)inst << 12,
 				engctx))
 			show &= ~0x00200000;
+		show_bitfield &= ~0x00200000;
 	}
 
 	nv_wr32(priv, 0x400100, stat);
 	nv_wr32(priv, 0x400500, 0x00010001);
 
 	if (show) {
-		nv_error(priv, "%s", "");
-		nouveau_bitfield_print(nv50_graph_intr_name, show);
-		pr_cont("\n");
+		show &= show_bitfield;
+		if (show) {
+			nv_error(priv, "%s", "");
+			nouveau_bitfield_print(nv50_graph_intr_name, show);
+			pr_cont("\n");
+		}
 		nv_error(priv,
 			 "ch %d [0x%010llx %s] subc %d class 0x%04x mthd 0x%04x data 0x%08x\n",
 			 chid, (u64)inst << 12, nouveau_client_name(engctx),
diff --git a/drivers/gpu/drm/nouveau/core/engine/graph/nvc0.c b/drivers/gpu/drm/nouveau/core/engine/graph/nvc0.c
index 5c8a63dc506aa..a73ab209ea88c 100644
--- a/drivers/gpu/drm/nouveau/core/engine/graph/nvc0.c
+++ b/drivers/gpu/drm/nouveau/core/engine/graph/nvc0.c
@@ -901,6 +901,9 @@ nvc0_graph_init_ctxctl(struct nvc0_graph_priv *priv)
 		}
 
 		return 0;
+	} else
+	if (!oclass->fecs.ucode) {
+		return -ENOSYS;
 	}
 
 	/* load HUB microcode */
diff --git a/drivers/gpu/drm/nouveau/core/engine/graph/nvc0.h b/drivers/gpu/drm/nouveau/core/engine/graph/nvc0.h
index ea17a80ad7fce..b0ab6de270b2e 100644
--- a/drivers/gpu/drm/nouveau/core/engine/graph/nvc0.h
+++ b/drivers/gpu/drm/nouveau/core/engine/graph/nvc0.h
@@ -205,6 +205,11 @@ extern struct nvc0_graph_init nve4_graph_init_regs[];
 extern struct nvc0_graph_init nve4_graph_init_unk[];
 extern struct nvc0_graph_init nve4_graph_init_unk88xx[];
 
+extern struct nvc0_graph_init nvf0_graph_init_unk40xx[];
+extern struct nvc0_graph_init nvf0_graph_init_unk70xx[];
+extern struct nvc0_graph_init nvf0_graph_init_unk5bxx[];
+extern struct nvc0_graph_init nvf0_graph_init_tpc[];
+
 int  nvc0_grctx_generate(struct nvc0_graph_priv *);
 void nvc0_grctx_generate_main(struct nvc0_graph_priv *, struct nvc0_grctx *);
 void nvc0_grctx_generate_mods(struct nvc0_graph_priv *, struct nvc0_grctx *);
@@ -266,6 +271,11 @@ extern struct nvc0_graph_init nve4_grctx_init_unk80xx[];
 extern struct nvc0_graph_init nve4_grctx_init_unk90xx[];
 
 extern struct nouveau_oclass *nvf0_grctx_oclass;
+extern struct nvc0_graph_init nvf0_grctx_init_unk44xx[];
+extern struct nvc0_graph_init nvf0_grctx_init_unk5bxx[];
+extern struct nvc0_graph_init nvf0_grctx_init_unk60xx[];
+
+extern struct nouveau_oclass *nv108_grctx_oclass;
 
 #define mmio_data(s,a,p) do {                                                  \
 	info->buffer[info->buffer_nr] = round_up(info->addr, (a));             \
diff --git a/drivers/gpu/drm/nouveau/core/engine/graph/nvf0.c b/drivers/gpu/drm/nouveau/core/engine/graph/nvf0.c
index 2f0ac78322345..b1acb9939d95c 100644
--- a/drivers/gpu/drm/nouveau/core/engine/graph/nvf0.c
+++ b/drivers/gpu/drm/nouveau/core/engine/graph/nvf0.c
@@ -41,7 +41,7 @@ nvf0_graph_sclass[] = {
  * PGRAPH engine/subdev functions
  ******************************************************************************/
 
-static struct nvc0_graph_init
+struct nvc0_graph_init
 nvf0_graph_init_unk40xx[] = {
 	{ 0x40415c,   1, 0x04, 0x00000000 },
 	{ 0x404170,   1, 0x04, 0x00000000 },
@@ -60,7 +60,7 @@ nvf0_graph_init_unk58xx[] = {
 	{}
 };
 
-static struct nvc0_graph_init
+struct nvc0_graph_init
 nvf0_graph_init_unk70xx[] = {
 	{ 0x407010,   1, 0x04, 0x00000000 },
 	{ 0x407040,   1, 0x04, 0x80440424 },
@@ -68,7 +68,7 @@ nvf0_graph_init_unk70xx[] = {
 	{}
 };
 
-static struct nvc0_graph_init
+struct nvc0_graph_init
 nvf0_graph_init_unk5bxx[] = {
 	{ 0x405b44,   1, 0x04, 0x00000000 },
 	{ 0x405b50,   1, 0x04, 0x00000000 },
@@ -114,7 +114,7 @@ nvf0_graph_init_gpc[] = {
 	{}
 };
 
-static struct nvc0_graph_init
+struct nvc0_graph_init
 nvf0_graph_init_tpc[] = {
 	{ 0x419d0c,   1, 0x04, 0x00000000 },
 	{ 0x419d10,   1, 0x04, 0x00000014 },
@@ -243,6 +243,6 @@ nvf0_graph_oclass = &(struct nvc0_graph_oclass) {
 	.cclass = &nvf0_grctx_oclass,
 	.sclass =  nvf0_graph_sclass,
 	.mmio = nvf0_graph_init_mmio,
-	.fecs.ucode = 0 ? &nvf0_graph_fecs_ucode : NULL,
+	.fecs.ucode = &nvf0_graph_fecs_ucode,
 	.gpccs.ucode = &nvf0_graph_gpccs_ucode,
 }.base;
diff --git a/drivers/gpu/drm/nouveau/core/include/core/class.h b/drivers/gpu/drm/nouveau/core/include/core/class.h
index 560c3593dae75..e71a4325e670f 100644
--- a/drivers/gpu/drm/nouveau/core/include/core/class.h
+++ b/drivers/gpu/drm/nouveau/core/include/core/class.h
@@ -230,9 +230,26 @@ struct nve0_channel_ind_class {
 
 #define NV04_DISP_CLASS                                              0x00000046
 
+#define NV04_DISP_MTHD                                               0x00000000
+#define NV04_DISP_MTHD_HEAD                                          0x00000001
+
+#define NV04_DISP_SCANOUTPOS                                         0x00000000
+
 struct nv04_display_class {
 };
 
+struct nv04_display_scanoutpos {
+	s64 time[2];
+	u32 vblanks;
+	u32 vblanke;
+	u32 vtotal;
+	u32 vline;
+	u32 hblanks;
+	u32 hblanke;
+	u32 htotal;
+	u32 hline;
+};
+
 /* 5070: NV50_DISP
  * 8270: NV84_DISP
  * 8370: NVA0_DISP
@@ -252,6 +269,11 @@ struct nv04_display_class {
 #define NVE0_DISP_CLASS                                              0x00009170
 #define NVF0_DISP_CLASS                                              0x00009270
 
+#define NV50_DISP_MTHD                                               0x00000000
+#define NV50_DISP_MTHD_HEAD                                          0x00000003
+
+#define NV50_DISP_SCANOUTPOS                                         0x00000000
+
 #define NV50_DISP_SOR_MTHD                                           0x00010000
 #define NV50_DISP_SOR_MTHD_TYPE                                      0x0000f000
 #define NV50_DISP_SOR_MTHD_HEAD                                      0x00000018
diff --git a/drivers/gpu/drm/nouveau/core/include/core/device.h b/drivers/gpu/drm/nouveau/core/include/core/device.h
index ac2881d1776ac..7b8ea221b00dc 100644
--- a/drivers/gpu/drm/nouveau/core/include/core/device.h
+++ b/drivers/gpu/drm/nouveau/core/include/core/device.h
@@ -38,7 +38,8 @@ enum nv_subdev_type {
 	NVDEV_SUBDEV_THERM,
 	NVDEV_SUBDEV_CLOCK,
 
-	NVDEV_ENGINE_DMAOBJ,
+	NVDEV_ENGINE_FIRST,
+	NVDEV_ENGINE_DMAOBJ = NVDEV_ENGINE_FIRST,
 	NVDEV_ENGINE_FIFO,
 	NVDEV_ENGINE_SW,
 	NVDEV_ENGINE_GR,
@@ -70,6 +71,7 @@ struct nouveau_device {
 	const char *dbgopt;
 	const char *name;
 	const char *cname;
+	u64 disable_mask;
 
 	enum {
 		NV_04    = 0x04,
diff --git a/drivers/gpu/drm/nouveau/core/include/engine/fifo.h b/drivers/gpu/drm/nouveau/core/include/engine/fifo.h
index 8c32cf4d83c78..26b6b2bb11121 100644
--- a/drivers/gpu/drm/nouveau/core/include/engine/fifo.h
+++ b/drivers/gpu/drm/nouveau/core/include/engine/fifo.h
@@ -109,6 +109,7 @@ extern struct nouveau_oclass *nv50_fifo_oclass;
 extern struct nouveau_oclass *nv84_fifo_oclass;
 extern struct nouveau_oclass *nvc0_fifo_oclass;
 extern struct nouveau_oclass *nve0_fifo_oclass;
+extern struct nouveau_oclass *nv108_fifo_oclass;
 
 void nv04_fifo_intr(struct nouveau_subdev *);
 int  nv04_fifo_context_attach(struct nouveau_object *, struct nouveau_object *);
diff --git a/drivers/gpu/drm/nouveau/core/include/engine/graph.h b/drivers/gpu/drm/nouveau/core/include/engine/graph.h
index 8e1b52312ddc5..97705618de979 100644
--- a/drivers/gpu/drm/nouveau/core/include/engine/graph.h
+++ b/drivers/gpu/drm/nouveau/core/include/engine/graph.h
@@ -69,6 +69,7 @@ extern struct nouveau_oclass *nvd7_graph_oclass;
 extern struct nouveau_oclass *nvd9_graph_oclass;
 extern struct nouveau_oclass *nve4_graph_oclass;
 extern struct nouveau_oclass *nvf0_graph_oclass;
+extern struct nouveau_oclass *nv108_graph_oclass;
 
 extern const struct nouveau_bitfield nv04_graph_nsource[];
 extern struct nouveau_ofuncs nv04_graph_ofuncs;
diff --git a/drivers/gpu/drm/nouveau/core/include/subdev/bar.h b/drivers/gpu/drm/nouveau/core/include/subdev/bar.h
index 4f4ff4502c3d2..9faa98e67ad8c 100644
--- a/drivers/gpu/drm/nouveau/core/include/subdev/bar.h
+++ b/drivers/gpu/drm/nouveau/core/include/subdev/bar.h
@@ -4,8 +4,7 @@
 #include <core/subdev.h>
 #include <core/device.h>
 
-#include <subdev/fb.h>
-
+struct nouveau_mem;
 struct nouveau_vma;
 
 struct nouveau_bar {
@@ -29,27 +28,7 @@ nouveau_bar(void *obj)
 	return (void *)nv_device(obj)->subdev[NVDEV_SUBDEV_BAR];
 }
 
-#define nouveau_bar_create(p,e,o,d)                                            \
-	nouveau_bar_create_((p), (e), (o), sizeof(**d), (void **)d)
-#define nouveau_bar_init(p)                                                    \
-	nouveau_subdev_init(&(p)->base)
-#define nouveau_bar_fini(p,s)                                                  \
-	nouveau_subdev_fini(&(p)->base, (s))
-
-int nouveau_bar_create_(struct nouveau_object *, struct nouveau_object *,
-			struct nouveau_oclass *, int, void **);
-void nouveau_bar_destroy(struct nouveau_bar *);
-
-void _nouveau_bar_dtor(struct nouveau_object *);
-#define _nouveau_bar_init _nouveau_subdev_init
-#define _nouveau_bar_fini _nouveau_subdev_fini
-
 extern struct nouveau_oclass nv50_bar_oclass;
 extern struct nouveau_oclass nvc0_bar_oclass;
 
-int nouveau_bar_alloc(struct nouveau_bar *, struct nouveau_object *,
-		      struct nouveau_mem *, struct nouveau_object **);
-
-void nv84_bar_flush(struct nouveau_bar *);
-
 #endif
diff --git a/drivers/gpu/drm/nouveau/core/include/subdev/bios/ramcfg.h b/drivers/gpu/drm/nouveau/core/include/subdev/bios/ramcfg.h
new file mode 100644
index 0000000000000..c5e6d1e6ac1d8
--- /dev/null
+++ b/drivers/gpu/drm/nouveau/core/include/subdev/bios/ramcfg.h
@@ -0,0 +1,66 @@
+#ifndef __NVBIOS_RAMCFG_H__
+#define __NVBIOS_RAMCFG_H__
+
+struct nouveau_bios;
+
+struct nvbios_ramcfg {
+	unsigned rammap_11_08_01:1;
+	unsigned rammap_11_08_0c:2;
+	unsigned rammap_11_08_10:1;
+	unsigned rammap_11_11_0c:2;
+
+	unsigned ramcfg_11_01_01:1;
+	unsigned ramcfg_11_01_02:1;
+	unsigned ramcfg_11_01_04:1;
+	unsigned ramcfg_11_01_08:1;
+	unsigned ramcfg_11_01_10:1;
+	unsigned ramcfg_11_01_20:1;
+	unsigned ramcfg_11_01_40:1;
+	unsigned ramcfg_11_01_80:1;
+	unsigned ramcfg_11_02_03:2;
+	unsigned ramcfg_11_02_04:1;
+	unsigned ramcfg_11_02_08:1;
+	unsigned ramcfg_11_02_10:1;
+	unsigned ramcfg_11_02_40:1;
+	unsigned ramcfg_11_02_80:1;
+	unsigned ramcfg_11_03_0f:4;
+	unsigned ramcfg_11_03_30:2;
+	unsigned ramcfg_11_03_c0:2;
+	unsigned ramcfg_11_03_f0:4;
+	unsigned ramcfg_11_04:8;
+	unsigned ramcfg_11_06:8;
+	unsigned ramcfg_11_07_02:1;
+	unsigned ramcfg_11_07_04:1;
+	unsigned ramcfg_11_07_08:1;
+	unsigned ramcfg_11_07_10:1;
+	unsigned ramcfg_11_07_40:1;
+	unsigned ramcfg_11_07_80:1;
+	unsigned ramcfg_11_08_01:1;
+	unsigned ramcfg_11_08_02:1;
+	unsigned ramcfg_11_08_04:1;
+	unsigned ramcfg_11_08_08:1;
+	unsigned ramcfg_11_08_10:1;
+	unsigned ramcfg_11_08_20:1;
+	unsigned ramcfg_11_09:8;
+
+	unsigned timing[11];
+	unsigned timing_20_2e_03:2;
+	unsigned timing_20_2e_30:2;
+	unsigned timing_20_2e_c0:2;
+	unsigned timing_20_2f_03:2;
+	unsigned timing_20_2c_003f:6;
+	unsigned timing_20_2c_1fc0:7;
+	unsigned timing_20_30_f8:5;
+	unsigned timing_20_30_07:3;
+	unsigned timing_20_31_0007:3;
+	unsigned timing_20_31_0078:4;
+	unsigned timing_20_31_0780:4;
+	unsigned timing_20_31_0800:1;
+	unsigned timing_20_31_7000:3;
+	unsigned timing_20_31_8000:1;
+};
+
+u8 nvbios_ramcfg_count(struct nouveau_bios *);
+u8 nvbios_ramcfg_index(struct nouveau_bios *);
+
+#endif
diff --git a/drivers/gpu/drm/nouveau/core/include/subdev/bios/rammap.h b/drivers/gpu/drm/nouveau/core/include/subdev/bios/rammap.h
index bc15e03208773..5bdf8e4db40a1 100644
--- a/drivers/gpu/drm/nouveau/core/include/subdev/bios/rammap.h
+++ b/drivers/gpu/drm/nouveau/core/include/subdev/bios/rammap.h
@@ -1,11 +1,25 @@
 #ifndef __NVBIOS_RAMMAP_H__
 #define __NVBIOS_RAMMAP_H__
 
-u16 nvbios_rammap_table(struct nouveau_bios *, u8 *ver, u8 *hdr,
-			u8 *cnt, u8 *len, u8 *snr, u8 *ssz);
-u16 nvbios_rammap_entry(struct nouveau_bios *, int idx,
-			u8 *ver, u8 *hdr, u8 *cnt, u8 *len);
-u16 nvbios_rammap_match(struct nouveau_bios *, u16 khz,
-			u8 *ver, u8 *hdr, u8 *cnt, u8 *len);
+struct nvbios_ramcfg;
+
+u32 nvbios_rammapTe(struct nouveau_bios *, u8 *ver, u8 *hdr,
+		    u8 *cnt, u8 *len, u8 *snr, u8 *ssz);
+
+u32 nvbios_rammapEe(struct nouveau_bios *, int idx,
+		    u8 *ver, u8 *hdr, u8 *cnt, u8 *len);
+u32 nvbios_rammapEm(struct nouveau_bios *, u16 mhz,
+		    u8 *ver, u8 *hdr, u8 *cnt, u8 *len);
+u32 nvbios_rammapEp(struct nouveau_bios *, u16 mhz,
+		    u8 *ver, u8 *hdr, u8 *cnt, u8 *len,
+		    struct nvbios_ramcfg *);
+
+u32 nvbios_rammapSe(struct nouveau_bios *, u32 data,
+		    u8 ever, u8 ehdr, u8 ecnt, u8 elen, int idx,
+		    u8 *ver, u8 *hdr);
+u32 nvbios_rammapSp(struct nouveau_bios *, u32 data,
+		    u8 ever, u8 ehdr, u8 ecnt, u8 elen, int idx,
+		    u8 *ver, u8 *hdr,
+		    struct nvbios_ramcfg *);
 
 #endif
diff --git a/drivers/gpu/drm/nouveau/core/include/subdev/bios/timing.h b/drivers/gpu/drm/nouveau/core/include/subdev/bios/timing.h
index 963694b542249..76d914b67ab5c 100644
--- a/drivers/gpu/drm/nouveau/core/include/subdev/bios/timing.h
+++ b/drivers/gpu/drm/nouveau/core/include/subdev/bios/timing.h
@@ -1,8 +1,14 @@
 #ifndef __NVBIOS_TIMING_H__
 #define __NVBIOS_TIMING_H__
 
-u16 nvbios_timing_table(struct nouveau_bios *,
-			u8 *ver, u8 *hdr, u8 *cnt, u8 *len);
-u16 nvbios_timing_entry(struct nouveau_bios *, int idx, u8 *ver, u8 *hdr);
+struct nvbios_ramcfg;
+
+u16 nvbios_timingTe(struct nouveau_bios *,
+		    u8 *ver, u8 *hdr, u8 *cnt, u8 *len, u8 *snr, u8 *ssz);
+u16 nvbios_timingEe(struct nouveau_bios *, int idx,
+		    u8 *ver, u8 *hdr, u8 *cnt, u8 *len);
+u16 nvbios_timingEp(struct nouveau_bios *, int idx,
+		    u8 *ver, u8 *hdr, u8 *cnt, u8 *len,
+		    struct nvbios_ramcfg *);
 
 #endif
diff --git a/drivers/gpu/drm/nouveau/core/include/subdev/devinit.h b/drivers/gpu/drm/nouveau/core/include/subdev/devinit.h
index 685c9b12ee4cf..ed1ac68c38b35 100644
--- a/drivers/gpu/drm/nouveau/core/include/subdev/devinit.h
+++ b/drivers/gpu/drm/nouveau/core/include/subdev/devinit.h
@@ -9,7 +9,6 @@ struct nouveau_devinit {
 	bool post;
 	void (*meminit)(struct nouveau_devinit *);
 	int  (*pll_set)(struct nouveau_devinit *, u32 type, u32 freq);
-
 };
 
 static inline struct nouveau_devinit *
@@ -18,32 +17,16 @@ nouveau_devinit(void *obj)
 	return (void *)nv_device(obj)->subdev[NVDEV_SUBDEV_DEVINIT];
 }
 
-#define nouveau_devinit_create(p,e,o,d)                                        \
-	nouveau_devinit_create_((p), (e), (o), sizeof(**d), (void **)d)
-#define nouveau_devinit_destroy(p)                                             \
-	nouveau_subdev_destroy(&(p)->base)
-#define nouveau_devinit_init(p) ({                                             \
-	struct nouveau_devinit *d = (p);                                       \
-	_nouveau_devinit_init(nv_object(d));                                   \
-})
-#define nouveau_devinit_fini(p,s) ({                                           \
-	struct nouveau_devinit *d = (p);                                       \
-	_nouveau_devinit_fini(nv_object(d), (s));                              \
-})
-
-int nouveau_devinit_create_(struct nouveau_object *, struct nouveau_object *,
-			    struct nouveau_oclass *, int, void **);
-#define _nouveau_devinit_dtor _nouveau_subdev_dtor
-int _nouveau_devinit_init(struct nouveau_object *);
-int _nouveau_devinit_fini(struct nouveau_object *, bool suspend);
-
-extern struct nouveau_oclass nv04_devinit_oclass;
-extern struct nouveau_oclass nv05_devinit_oclass;
-extern struct nouveau_oclass nv10_devinit_oclass;
-extern struct nouveau_oclass nv1a_devinit_oclass;
-extern struct nouveau_oclass nv20_devinit_oclass;
-extern struct nouveau_oclass nv50_devinit_oclass;
-extern struct nouveau_oclass nva3_devinit_oclass;
-extern struct nouveau_oclass nvc0_devinit_oclass;
+extern struct nouveau_oclass *nv04_devinit_oclass;
+extern struct nouveau_oclass *nv05_devinit_oclass;
+extern struct nouveau_oclass *nv10_devinit_oclass;
+extern struct nouveau_oclass *nv1a_devinit_oclass;
+extern struct nouveau_oclass *nv20_devinit_oclass;
+extern struct nouveau_oclass *nv50_devinit_oclass;
+extern struct nouveau_oclass *nv84_devinit_oclass;
+extern struct nouveau_oclass *nv98_devinit_oclass;
+extern struct nouveau_oclass *nva3_devinit_oclass;
+extern struct nouveau_oclass *nvaf_devinit_oclass;
+extern struct nouveau_oclass *nvc0_devinit_oclass;
 
 #endif
diff --git a/drivers/gpu/drm/nouveau/core/include/subdev/fb.h b/drivers/gpu/drm/nouveau/core/include/subdev/fb.h
index d89dbdf39b0db..d7ecafbae1ca1 100644
--- a/drivers/gpu/drm/nouveau/core/include/subdev/fb.h
+++ b/drivers/gpu/drm/nouveau/core/include/subdev/fb.h
@@ -106,6 +106,13 @@ extern struct nouveau_oclass *nvaf_fb_oclass;
 extern struct nouveau_oclass *nvc0_fb_oclass;
 extern struct nouveau_oclass *nve0_fb_oclass;
 
+#include <subdev/bios/ramcfg.h>
+
+struct nouveau_ram_data {
+	struct nvbios_ramcfg bios;
+	u32 freq;
+};
+
 struct nouveau_ram {
 	struct nouveau_object base;
 	enum {
@@ -142,6 +149,12 @@ struct nouveau_ram {
 	} rammap, ramcfg, timing;
 	u32 freq;
 	u32 mr[16];
+	u32 mr1_nuts;
+
+	struct nouveau_ram_data *next;
+	struct nouveau_ram_data former;
+	struct nouveau_ram_data xition;
+	struct nouveau_ram_data target;
 };
 
 #endif
diff --git a/drivers/gpu/drm/nouveau/core/include/subdev/instmem.h b/drivers/gpu/drm/nouveau/core/include/subdev/instmem.h
index 4aca33887aaa6..c1df26f3230c1 100644
--- a/drivers/gpu/drm/nouveau/core/include/subdev/instmem.h
+++ b/drivers/gpu/drm/nouveau/core/include/subdev/instmem.h
@@ -23,21 +23,6 @@ nv_memobj(void *obj)
 	return obj;
 }
 
-#define nouveau_instobj_create(p,e,o,d)                                        \
-	nouveau_instobj_create_((p), (e), (o), sizeof(**d), (void **)d)
-#define nouveau_instobj_init(p)                                                \
-	nouveau_object_init(&(p)->base)
-#define nouveau_instobj_fini(p,s)                                              \
-	nouveau_object_fini(&(p)->base, (s))
-
-int  nouveau_instobj_create_(struct nouveau_object *, struct nouveau_object *,
-			     struct nouveau_oclass *, int, void **);
-void nouveau_instobj_destroy(struct nouveau_instobj *);
-
-void _nouveau_instobj_dtor(struct nouveau_object *);
-#define _nouveau_instobj_init nouveau_object_init
-#define _nouveau_instobj_fini nouveau_object_fini
-
 struct nouveau_instmem {
 	struct nouveau_subdev base;
 	struct list_head list;
@@ -60,21 +45,8 @@ nouveau_instmem(void *obj)
 	return (void *)nv_device(obj)->subdev[NVDEV_SUBDEV_INSTMEM];
 }
 
-#define nouveau_instmem_create(p,e,o,d)                                        \
-	nouveau_instmem_create_((p), (e), (o), sizeof(**d), (void **)d)
-#define nouveau_instmem_destroy(p)                                             \
-	nouveau_subdev_destroy(&(p)->base)
-int nouveau_instmem_create_(struct nouveau_object *, struct nouveau_object *,
-			    struct nouveau_oclass *, int, void **);
-int nouveau_instmem_init(struct nouveau_instmem *);
-int nouveau_instmem_fini(struct nouveau_instmem *, bool);
-
-#define _nouveau_instmem_dtor _nouveau_subdev_dtor
-int _nouveau_instmem_init(struct nouveau_object *);
-int _nouveau_instmem_fini(struct nouveau_object *, bool);
-
-extern struct nouveau_oclass nv04_instmem_oclass;
-extern struct nouveau_oclass nv40_instmem_oclass;
-extern struct nouveau_oclass nv50_instmem_oclass;
+extern struct nouveau_oclass *nv04_instmem_oclass;
+extern struct nouveau_oclass *nv40_instmem_oclass;
+extern struct nouveau_oclass *nv50_instmem_oclass;
 
 #endif
diff --git a/drivers/gpu/drm/nouveau/core/include/subdev/vm.h b/drivers/gpu/drm/nouveau/core/include/subdev/vm.h
index fcf57fa309bfd..c9509039f94b4 100644
--- a/drivers/gpu/drm/nouveau/core/include/subdev/vm.h
+++ b/drivers/gpu/drm/nouveau/core/include/subdev/vm.h
@@ -131,9 +131,5 @@ void nouveau_vm_map(struct nouveau_vma *, struct nouveau_mem *);
 void nouveau_vm_map_at(struct nouveau_vma *, u64 offset, struct nouveau_mem *);
 void nouveau_vm_unmap(struct nouveau_vma *);
 void nouveau_vm_unmap_at(struct nouveau_vma *, u64 offset, u64 length);
-void nouveau_vm_map_sg(struct nouveau_vma *, u64 offset, u64 length,
-		       struct nouveau_mem *);
-void nouveau_vm_map_sg_table(struct nouveau_vma *vma, u64 delta, u64 length,
-		     struct nouveau_mem *mem);
 
 #endif
diff --git a/drivers/gpu/drm/nouveau/core/subdev/bar/base.c b/drivers/gpu/drm/nouveau/core/subdev/bar/base.c
index d70ba342aa2e8..7098ddd546788 100644
--- a/drivers/gpu/drm/nouveau/core/subdev/bar/base.c
+++ b/drivers/gpu/drm/nouveau/core/subdev/bar/base.c
@@ -23,7 +23,11 @@
  */
 
 #include <core/object.h>
-#include <subdev/bar.h>
+
+#include <subdev/fb.h>
+#include <subdev/vm.h>
+
+#include "priv.h"
 
 struct nouveau_barobj {
 	struct nouveau_object base;
diff --git a/drivers/gpu/drm/nouveau/core/subdev/bar/nv50.c b/drivers/gpu/drm/nouveau/core/subdev/bar/nv50.c
index 160d27f3c7b47..090d594a21b36 100644
--- a/drivers/gpu/drm/nouveau/core/subdev/bar/nv50.c
+++ b/drivers/gpu/drm/nouveau/core/subdev/bar/nv50.c
@@ -25,10 +25,11 @@
 #include <core/gpuobj.h>
 
 #include <subdev/timer.h>
-#include <subdev/bar.h>
 #include <subdev/fb.h>
 #include <subdev/vm.h>
 
+#include "priv.h"
+
 struct nv50_bar_priv {
 	struct nouveau_bar base;
 	spinlock_t lock;
diff --git a/drivers/gpu/drm/nouveau/core/subdev/bar/nvc0.c b/drivers/gpu/drm/nouveau/core/subdev/bar/nvc0.c
index b2ec7411eb2eb..bac5e754de35a 100644
--- a/drivers/gpu/drm/nouveau/core/subdev/bar/nvc0.c
+++ b/drivers/gpu/drm/nouveau/core/subdev/bar/nvc0.c
@@ -25,10 +25,11 @@
 #include <core/gpuobj.h>
 
 #include <subdev/timer.h>
-#include <subdev/bar.h>
 #include <subdev/fb.h>
 #include <subdev/vm.h>
 
+#include "priv.h"
+
 struct nvc0_bar_priv {
 	struct nouveau_bar base;
 	spinlock_t lock;
diff --git a/drivers/gpu/drm/nouveau/core/subdev/bar/priv.h b/drivers/gpu/drm/nouveau/core/subdev/bar/priv.h
new file mode 100644
index 0000000000000..ffad8f337ead1
--- /dev/null
+++ b/drivers/gpu/drm/nouveau/core/subdev/bar/priv.h
@@ -0,0 +1,26 @@
+#ifndef __NVKM_BAR_PRIV_H__
+#define __NVKM_BAR_PRIV_H__
+
+#include <subdev/bar.h>
+
+#define nouveau_bar_create(p,e,o,d)                                            \
+	nouveau_bar_create_((p), (e), (o), sizeof(**d), (void **)d)
+#define nouveau_bar_init(p)                                                    \
+	nouveau_subdev_init(&(p)->base)
+#define nouveau_bar_fini(p,s)                                                  \
+	nouveau_subdev_fini(&(p)->base, (s))
+
+int nouveau_bar_create_(struct nouveau_object *, struct nouveau_object *,
+			struct nouveau_oclass *, int, void **);
+void nouveau_bar_destroy(struct nouveau_bar *);
+
+void _nouveau_bar_dtor(struct nouveau_object *);
+#define _nouveau_bar_init _nouveau_subdev_init
+#define _nouveau_bar_fini _nouveau_subdev_fini
+
+int  nouveau_bar_alloc(struct nouveau_bar *, struct nouveau_object *,
+		       struct nouveau_mem *, struct nouveau_object **);
+
+void nv84_bar_flush(struct nouveau_bar *);
+
+#endif
diff --git a/drivers/gpu/drm/nouveau/core/subdev/bios/init.c b/drivers/gpu/drm/nouveau/core/subdev/bios/init.c
index df1b1b4230933..de201baeb053a 100644
--- a/drivers/gpu/drm/nouveau/core/subdev/bios/init.c
+++ b/drivers/gpu/drm/nouveau/core/subdev/bios/init.c
@@ -9,6 +9,7 @@
 #include <subdev/bios/dp.h>
 #include <subdev/bios/gpio.h>
 #include <subdev/bios/init.h>
+#include <subdev/bios/ramcfg.h>
 #include <subdev/devinit.h>
 #include <subdev/i2c.h>
 #include <subdev/vga.h>
@@ -391,43 +392,14 @@ init_unknown_script(struct nouveau_bios *bios)
 	return 0x0000;
 }
 
-static u16
-init_ram_restrict_table(struct nvbios_init *init)
-{
-	struct nouveau_bios *bios = init->bios;
-	struct bit_entry bit_M;
-	u16 data = 0x0000;
-
-	if (!bit_entry(bios, 'M', &bit_M)) {
-		if (bit_M.version == 1 && bit_M.length >= 5)
-			data = nv_ro16(bios, bit_M.offset + 3);
-		if (bit_M.version == 2 && bit_M.length >= 3)
-			data = nv_ro16(bios, bit_M.offset + 1);
-	}
-
-	if (data == 0x0000)
-		warn("ram restrict table not found\n");
-	return data;
-}
-
 static u8
 init_ram_restrict_group_count(struct nvbios_init *init)
 {
-	struct nouveau_bios *bios = init->bios;
-	struct bit_entry bit_M;
-
-	if (!bit_entry(bios, 'M', &bit_M)) {
-		if (bit_M.version == 1 && bit_M.length >= 5)
-			return nv_ro08(bios, bit_M.offset + 2);
-		if (bit_M.version == 2 && bit_M.length >= 3)
-			return nv_ro08(bios, bit_M.offset + 0);
-	}
-
-	return 0x00;
+	return nvbios_ramcfg_count(init->bios);
 }
 
 static u8
-init_ram_restrict_strap(struct nvbios_init *init)
+init_ram_restrict(struct nvbios_init *init)
 {
 	/* This appears to be the behaviour of the VBIOS parser, and *is*
 	 * important to cache the NV_PEXTDEV_BOOT0 on later chipsets to
@@ -438,18 +410,8 @@ init_ram_restrict_strap(struct nvbios_init *init)
 	 * in case *not* re-reading the strap causes similar breakage.
 	 */
 	if (!init->ramcfg || init->bios->version.major < 0x70)
-		init->ramcfg = init_rd32(init, 0x101000);
-	return (init->ramcfg & 0x00000003c) >> 2;
-}
-
-static u8
-init_ram_restrict(struct nvbios_init *init)
-{
-	u8  strap = init_ram_restrict_strap(init);
-	u16 table = init_ram_restrict_table(init);
-	if (table)
-		return nv_ro08(init->bios, table + strap);
-	return 0x00;
+		init->ramcfg = 0x80000000 | nvbios_ramcfg_index(init->bios);
+	return (init->ramcfg & 0x7fffffff);
 }
 
 static u8
diff --git a/drivers/gpu/drm/nouveau/core/subdev/bios/ramcfg.c b/drivers/gpu/drm/nouveau/core/subdev/bios/ramcfg.c
new file mode 100644
index 0000000000000..991aedda999b0
--- /dev/null
+++ b/drivers/gpu/drm/nouveau/core/subdev/bios/ramcfg.c
@@ -0,0 +1,67 @@
+/*
+ * Copyright 2013 Red Hat Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: Ben Skeggs <bskeggs@redhat.com>
+ */
+
+#include <subdev/bios.h>
+#include <subdev/bios/bit.h>
+#include <subdev/bios/ramcfg.h>
+
+static u8
+nvbios_ramcfg_strap(struct nouveau_bios *bios)
+{
+	return (nv_rd32(bios, 0x101000) & 0x0000003c) >> 2;
+}
+
+u8
+nvbios_ramcfg_count(struct nouveau_bios *bios)
+{
+	struct bit_entry bit_M;
+
+	if (!bit_entry(bios, 'M', &bit_M)) {
+		if (bit_M.version == 1 && bit_M.length >= 5)
+			return nv_ro08(bios, bit_M.offset + 2);
+		if (bit_M.version == 2 && bit_M.length >= 3)
+			return nv_ro08(bios, bit_M.offset + 0);
+	}
+
+	return 0x00;
+}
+
+u8
+nvbios_ramcfg_index(struct nouveau_bios *bios)
+{
+	u8 strap = nvbios_ramcfg_strap(bios);
+	u32 xlat = 0x00000000;
+	struct bit_entry bit_M;
+
+	if (!bit_entry(bios, 'M', &bit_M)) {
+		if (bit_M.version == 1 && bit_M.length >= 5)
+			xlat = nv_ro16(bios, bit_M.offset + 3);
+		if (bit_M.version == 2 && bit_M.length >= 3)
+			xlat = nv_ro16(bios, bit_M.offset + 1);
+	}
+
+	if (xlat)
+		strap = nv_ro08(bios, xlat + strap);
+	return strap;
+}
diff --git a/drivers/gpu/drm/nouveau/core/subdev/bios/rammap.c b/drivers/gpu/drm/nouveau/core/subdev/bios/rammap.c
index 916fa9d302b7f..1811b2cb04727 100644
--- a/drivers/gpu/drm/nouveau/core/subdev/bios/rammap.c
+++ b/drivers/gpu/drm/nouveau/core/subdev/bios/rammap.c
@@ -24,11 +24,12 @@
 
 #include <subdev/bios.h>
 #include <subdev/bios/bit.h>
+#include <subdev/bios/ramcfg.h>
 #include <subdev/bios/rammap.h>
 
-u16
-nvbios_rammap_table(struct nouveau_bios *bios, u8 *ver, u8 *hdr,
-		    u8 *cnt, u8 *len, u8 *snr, u8 *ssz)
+u32
+nvbios_rammapTe(struct nouveau_bios *bios, u8 *ver, u8 *hdr,
+		u8 *cnt, u8 *len, u8 *snr, u8 *ssz)
 {
 	struct bit_entry bit_P;
 	u16 rammap = 0x0000;
@@ -57,12 +58,12 @@ nvbios_rammap_table(struct nouveau_bios *bios, u8 *ver, u8 *hdr,
 	return 0x0000;
 }
 
-u16
-nvbios_rammap_entry(struct nouveau_bios *bios, int idx,
-		    u8 *ver, u8 *hdr, u8 *cnt, u8 *len)
+u32
+nvbios_rammapEe(struct nouveau_bios *bios, int idx,
+		u8 *ver, u8 *hdr, u8 *cnt, u8 *len)
 {
 	u8  snr, ssz;
-	u16 rammap = nvbios_rammap_table(bios, ver, hdr, cnt, len, &snr, &ssz);
+	u16 rammap = nvbios_rammapTe(bios, ver, hdr, cnt, len, &snr, &ssz);
 	if (rammap && idx < *cnt) {
 		rammap = rammap + *hdr + (idx * (*len + (snr * ssz)));
 		*hdr = *len;
@@ -73,16 +74,100 @@ nvbios_rammap_entry(struct nouveau_bios *bios, int idx,
 	return 0x0000;
 }
 
-u16
-nvbios_rammap_match(struct nouveau_bios *bios, u16 khz,
-		    u8 *ver, u8 *hdr, u8 *cnt, u8 *len)
+u32
+nvbios_rammapEm(struct nouveau_bios *bios, u16 khz,
+		u8 *ver, u8 *hdr, u8 *cnt, u8 *len)
 {
 	int idx = 0;
 	u32 data;
-	while ((data = nvbios_rammap_entry(bios, idx++, ver, hdr, cnt, len))) {
+	while ((data = nvbios_rammapEe(bios, idx++, ver, hdr, cnt, len))) {
 		if (khz >= nv_ro16(bios, data + 0x00) &&
 		    khz <= nv_ro16(bios, data + 0x02))
 			break;
 	}
 	return data;
 }
+
+u32
+nvbios_rammapEp(struct nouveau_bios *bios, u16 khz,
+		u8 *ver, u8 *hdr, u8 *cnt, u8 *len,
+		struct nvbios_ramcfg *p)
+{
+	u32 data = nvbios_rammapEm(bios, khz, ver, hdr, cnt, len);
+	memset(p, 0x00, sizeof(*p));
+	switch (!!data * *ver) {
+	case 0x11:
+		p->rammap_11_08_01 = (nv_ro08(bios, data + 0x08) & 0x01) >> 0;
+		p->rammap_11_08_0c = (nv_ro08(bios, data + 0x08) & 0x0c) >> 2;
+		p->rammap_11_08_10 = (nv_ro08(bios, data + 0x08) & 0x10) >> 4;
+		p->rammap_11_11_0c = (nv_ro08(bios, data + 0x11) & 0x0c) >> 2;
+		break;
+	default:
+		data = 0;
+		break;
+	}
+	return data;
+}
+
+u32
+nvbios_rammapSe(struct nouveau_bios *bios, u32 data,
+		u8 ever, u8 ehdr, u8 ecnt, u8 elen, int idx,
+		u8 *ver, u8 *hdr)
+{
+	if (idx < ecnt) {
+		data = data + ehdr + (idx * elen);
+		*ver = ever;
+		*hdr = elen;
+		return data;
+	}
+	return 0;
+}
+
+u32
+nvbios_rammapSp(struct nouveau_bios *bios, u32 data,
+		u8 ever, u8 ehdr, u8 ecnt, u8 elen, int idx,
+		u8 *ver, u8 *hdr, struct nvbios_ramcfg *p)
+{
+	data = nvbios_rammapSe(bios, data, ever, ehdr, ecnt, elen, idx, ver, hdr);
+	switch (!!data * *ver) {
+	case 0x11:
+		p->ramcfg_11_01_01 = (nv_ro08(bios, data + 0x01) & 0x01) >> 0;
+		p->ramcfg_11_01_02 = (nv_ro08(bios, data + 0x01) & 0x02) >> 1;
+		p->ramcfg_11_01_04 = (nv_ro08(bios, data + 0x01) & 0x04) >> 2;
+		p->ramcfg_11_01_08 = (nv_ro08(bios, data + 0x01) & 0x08) >> 3;
+		p->ramcfg_11_01_10 = (nv_ro08(bios, data + 0x01) & 0x10) >> 4;
+		p->ramcfg_11_01_20 = (nv_ro08(bios, data + 0x01) & 0x20) >> 5;
+		p->ramcfg_11_01_40 = (nv_ro08(bios, data + 0x01) & 0x40) >> 6;
+		p->ramcfg_11_01_80 = (nv_ro08(bios, data + 0x01) & 0x80) >> 7;
+		p->ramcfg_11_02_03 = (nv_ro08(bios, data + 0x02) & 0x03) >> 0;
+		p->ramcfg_11_02_04 = (nv_ro08(bios, data + 0x02) & 0x04) >> 2;
+		p->ramcfg_11_02_08 = (nv_ro08(bios, data + 0x02) & 0x08) >> 3;
+		p->ramcfg_11_02_10 = (nv_ro08(bios, data + 0x02) & 0x10) >> 4;
+		p->ramcfg_11_02_40 = (nv_ro08(bios, data + 0x02) & 0x40) >> 6;
+		p->ramcfg_11_02_80 = (nv_ro08(bios, data + 0x02) & 0x80) >> 7;
+		p->ramcfg_11_03_0f = (nv_ro08(bios, data + 0x03) & 0x0f) >> 0;
+		p->ramcfg_11_03_30 = (nv_ro08(bios, data + 0x03) & 0x30) >> 4;
+		p->ramcfg_11_03_c0 = (nv_ro08(bios, data + 0x03) & 0xc0) >> 6;
+		p->ramcfg_11_03_f0 = (nv_ro08(bios, data + 0x03) & 0xf0) >> 4;
+		p->ramcfg_11_04    = (nv_ro08(bios, data + 0x04) & 0xff) >> 0;
+		p->ramcfg_11_06    = (nv_ro08(bios, data + 0x06) & 0xff) >> 0;
+		p->ramcfg_11_07_02 = (nv_ro08(bios, data + 0x07) & 0x02) >> 1;
+		p->ramcfg_11_07_04 = (nv_ro08(bios, data + 0x07) & 0x04) >> 2;
+		p->ramcfg_11_07_08 = (nv_ro08(bios, data + 0x07) & 0x08) >> 3;
+		p->ramcfg_11_07_10 = (nv_ro08(bios, data + 0x07) & 0x10) >> 4;
+		p->ramcfg_11_07_40 = (nv_ro08(bios, data + 0x07) & 0x40) >> 6;
+		p->ramcfg_11_07_80 = (nv_ro08(bios, data + 0x07) & 0x80) >> 7;
+		p->ramcfg_11_08_01 = (nv_ro08(bios, data + 0x08) & 0x01) >> 0;
+		p->ramcfg_11_08_02 = (nv_ro08(bios, data + 0x08) & 0x02) >> 1;
+		p->ramcfg_11_08_04 = (nv_ro08(bios, data + 0x08) & 0x04) >> 2;
+		p->ramcfg_11_08_08 = (nv_ro08(bios, data + 0x08) & 0x08) >> 3;
+		p->ramcfg_11_08_10 = (nv_ro08(bios, data + 0x08) & 0x10) >> 4;
+		p->ramcfg_11_08_20 = (nv_ro08(bios, data + 0x08) & 0x20) >> 5;
+		p->ramcfg_11_09    = (nv_ro08(bios, data + 0x09) & 0xff) >> 0;
+		break;
+	default:
+		data = 0;
+		break;
+	}
+	return data;
+}
diff --git a/drivers/gpu/drm/nouveau/core/subdev/bios/timing.c b/drivers/gpu/drm/nouveau/core/subdev/bios/timing.c
index 151c2d6aaee87..350d44ab2ba24 100644
--- a/drivers/gpu/drm/nouveau/core/subdev/bios/timing.c
+++ b/drivers/gpu/drm/nouveau/core/subdev/bios/timing.c
@@ -24,11 +24,12 @@
 
 #include <subdev/bios.h>
 #include <subdev/bios/bit.h>
+#include <subdev/bios/ramcfg.h>
 #include <subdev/bios/timing.h>
 
 u16
-nvbios_timing_table(struct nouveau_bios *bios,
-		    u8 *ver, u8 *hdr, u8 *cnt, u8 *len)
+nvbios_timingTe(struct nouveau_bios *bios,
+		u8 *ver, u8 *hdr, u8 *cnt, u8 *len, u8 *snr, u8 *ssz)
 {
 	struct bit_entry bit_P;
 	u16 timing = 0x0000;
@@ -47,11 +48,15 @@ nvbios_timing_table(struct nouveau_bios *bios,
 				*hdr = nv_ro08(bios, timing + 1);
 				*cnt = nv_ro08(bios, timing + 2);
 				*len = nv_ro08(bios, timing + 3);
+				*snr = 0;
+				*ssz = 0;
 				return timing;
 			case 0x20:
 				*hdr = nv_ro08(bios, timing + 1);
-				*cnt = nv_ro08(bios, timing + 3);
+				*cnt = nv_ro08(bios, timing + 5);
 				*len = nv_ro08(bios, timing + 2);
+				*snr = nv_ro08(bios, timing + 4);
+				*ssz = nv_ro08(bios, timing + 3);
 				return timing;
 			default:
 				break;
@@ -63,11 +68,60 @@ nvbios_timing_table(struct nouveau_bios *bios,
 }
 
 u16
-nvbios_timing_entry(struct nouveau_bios *bios, int idx, u8 *ver, u8 *len)
+nvbios_timingEe(struct nouveau_bios *bios, int idx,
+		u8 *ver, u8 *hdr, u8 *cnt, u8 *len)
 {
-	u8  hdr, cnt;
-	u16 timing = nvbios_timing_table(bios, ver, &hdr, &cnt, len);
-	if (timing && idx < cnt)
-		return timing + hdr + (idx * *len);
+	u8  snr, ssz;
+	u16 timing = nvbios_timingTe(bios, ver, hdr, cnt, len, &snr, &ssz);
+	if (timing && idx < *cnt) {
+		timing += *hdr + idx * (*len + (snr * ssz));
+		*hdr = *len;
+		*cnt = snr;
+		*len = ssz;
+		return timing;
+	}
 	return 0x0000;
 }
+
+u16
+nvbios_timingEp(struct nouveau_bios *bios, int idx,
+		u8 *ver, u8 *hdr, u8 *cnt, u8 *len,
+		struct nvbios_ramcfg *p)
+{
+	u16 data = nvbios_timingEe(bios, idx, ver, hdr, cnt, len), temp;
+	switch (!!data * *ver) {
+	case 0x20:
+		p->timing[0] = nv_ro32(bios, data + 0x00);
+		p->timing[1] = nv_ro32(bios, data + 0x04);
+		p->timing[2] = nv_ro32(bios, data + 0x08);
+		p->timing[3] = nv_ro32(bios, data + 0x0c);
+		p->timing[4] = nv_ro32(bios, data + 0x10);
+		p->timing[5] = nv_ro32(bios, data + 0x14);
+		p->timing[6] = nv_ro32(bios, data + 0x18);
+		p->timing[7] = nv_ro32(bios, data + 0x1c);
+		p->timing[8] = nv_ro32(bios, data + 0x20);
+		p->timing[9] = nv_ro32(bios, data + 0x24);
+		p->timing[10] = nv_ro32(bios, data + 0x28);
+		p->timing_20_2e_03 = (nv_ro08(bios, data + 0x2e) & 0x03) >> 0;
+		p->timing_20_2e_30 = (nv_ro08(bios, data + 0x2e) & 0x30) >> 4;
+		p->timing_20_2e_c0 = (nv_ro08(bios, data + 0x2e) & 0xc0) >> 6;
+		p->timing_20_2f_03 = (nv_ro08(bios, data + 0x2f) & 0x03) >> 0;
+		temp = nv_ro16(bios, data + 0x2c);
+		p->timing_20_2c_003f = (temp & 0x003f) >> 0;
+		p->timing_20_2c_1fc0 = (temp & 0x1fc0) >> 6;
+		p->timing_20_30_07 = (nv_ro08(bios, data + 0x30) & 0x07) >> 0;
+		p->timing_20_30_f8 = (nv_ro08(bios, data + 0x30) & 0xf8) >> 3;
+		temp = nv_ro16(bios, data + 0x31);
+		p->timing_20_31_0007 = (temp & 0x0007) >> 0;
+		p->timing_20_31_0078 = (temp & 0x0078) >> 3;
+		p->timing_20_31_0780 = (temp & 0x0780) >> 7;
+		p->timing_20_31_0800 = (temp & 0x0800) >> 11;
+		p->timing_20_31_7000 = (temp & 0x7000) >> 12;
+		p->timing_20_31_8000 = (temp & 0x8000) >> 15;
+		break;
+	default:
+		data = 0;
+		break;
+	}
+	return data;
+}
diff --git a/drivers/gpu/drm/nouveau/core/subdev/clock/base.c b/drivers/gpu/drm/nouveau/core/subdev/clock/base.c
index e2938a21b06fe..dd62baead39c5 100644
--- a/drivers/gpu/drm/nouveau/core/subdev/clock/base.c
+++ b/drivers/gpu/drm/nouveau/core/subdev/clock/base.c
@@ -182,9 +182,12 @@ nouveau_pstate_prog(struct nouveau_clock *clk, int pstatei)
 	clk->pstate = pstatei;
 
 	if (pfb->ram->calc) {
-		ret = pfb->ram->calc(pfb, pstate->base.domain[nv_clk_src_mem]);
-		if (ret == 0)
-			ret = pfb->ram->prog(pfb);
+		int khz = pstate->base.domain[nv_clk_src_mem];
+		do {
+			ret = pfb->ram->calc(pfb, khz);
+			if (ret == 0)
+				ret = pfb->ram->prog(pfb);
+		} while (ret > 0);
 		pfb->ram->tidy(pfb);
 	}
 
diff --git a/drivers/gpu/drm/nouveau/core/subdev/clock/nv04.c b/drivers/gpu/drm/nouveau/core/subdev/clock/nv04.c
index 30c1f3a4158e3..b74db6cfc4e21 100644
--- a/drivers/gpu/drm/nouveau/core/subdev/clock/nv04.c
+++ b/drivers/gpu/drm/nouveau/core/subdev/clock/nv04.c
@@ -25,7 +25,7 @@
 #include <subdev/bios.h>
 #include <subdev/bios/pll.h>
 #include <subdev/clock.h>
-#include <subdev/devinit/priv.h>
+#include <subdev/devinit/nv04.h>
 
 #include "pll.h"
 
diff --git a/drivers/gpu/drm/nouveau/core/subdev/clock/nve0.c b/drivers/gpu/drm/nouveau/core/subdev/clock/nve0.c
index 4c62e84b96f5f..d3c37c96f0e7e 100644
--- a/drivers/gpu/drm/nouveau/core/subdev/clock/nve0.c
+++ b/drivers/gpu/drm/nouveau/core/subdev/clock/nve0.c
@@ -457,7 +457,7 @@ nve0_domain[] = {
 	{ nv_clk_src_gpc    , 0x00, NVKM_CLK_DOM_FLAG_CORE, "core", 2000 },
 	{ nv_clk_src_hubk07 , 0x01, NVKM_CLK_DOM_FLAG_CORE },
 	{ nv_clk_src_rop    , 0x02, NVKM_CLK_DOM_FLAG_CORE },
-	{ nv_clk_src_mem    , 0x03, 0, "memory", 1000 },
+	{ nv_clk_src_mem    , 0x03, 0, "memory", 500 },
 	{ nv_clk_src_hubk06 , 0x04, NVKM_CLK_DOM_FLAG_CORE },
 	{ nv_clk_src_hubk01 , 0x05 },
 	{ nv_clk_src_vdec   , 0x06 },
diff --git a/drivers/gpu/drm/nouveau/core/subdev/devinit/base.c b/drivers/gpu/drm/nouveau/core/subdev/devinit/base.c
index 79c81d3d9bace..8fa34e8152c20 100644
--- a/drivers/gpu/drm/nouveau/core/subdev/devinit/base.c
+++ b/drivers/gpu/drm/nouveau/core/subdev/devinit/base.c
@@ -24,9 +24,11 @@
 
 #include <core/option.h>
 
-#include <subdev/devinit.h>
 #include <subdev/bios.h>
 #include <subdev/bios/init.h>
+#include <subdev/vga.h>
+
+#include "priv.h"
 
 int
 _nouveau_devinit_fini(struct nouveau_object *object, bool suspend)
@@ -37,18 +39,41 @@ _nouveau_devinit_fini(struct nouveau_object *object, bool suspend)
 	if (suspend)
 		devinit->post = true;
 
+	/* unlock the extended vga crtc regs */
+	nv_lockvgac(devinit, false);
+
 	return nouveau_subdev_fini(&devinit->base, suspend);
 }
 
 int
 _nouveau_devinit_init(struct nouveau_object *object)
 {
+	struct nouveau_devinit_impl *impl = (void *)object->oclass;
 	struct nouveau_devinit *devinit = (void *)object;
-	int ret = nouveau_subdev_init(&devinit->base);
+	int ret;
+
+	ret = nouveau_subdev_init(&devinit->base);
+	if (ret)
+		return ret;
+
+	ret = nvbios_init(&devinit->base, devinit->post);
 	if (ret)
 		return ret;
 
-	return nvbios_init(&devinit->base, devinit->post);
+	if (impl->disable)
+		nv_device(devinit)->disable_mask |= impl->disable(devinit);
+	return 0;
+}
+
+void
+_nouveau_devinit_dtor(struct nouveau_object *object)
+{
+	struct nouveau_devinit *devinit = (void *)object;
+
+	/* lock crtc regs */
+	nv_lockvgac(devinit, true);
+
+	nouveau_subdev_destroy(&devinit->base);
 }
 
 int
@@ -57,6 +82,7 @@ nouveau_devinit_create_(struct nouveau_object *parent,
 			struct nouveau_oclass *oclass,
 			int size, void **pobject)
 {
+	struct nouveau_devinit_impl *impl = (void *)oclass;
 	struct nouveau_device *device = nv_device(parent);
 	struct nouveau_devinit *devinit;
 	int ret;
@@ -68,5 +94,7 @@ nouveau_devinit_create_(struct nouveau_object *parent,
 		return ret;
 
 	devinit->post = nouveau_boolopt(device->cfgopt, "NvForcePost", false);
+	devinit->meminit = impl->meminit;
+	devinit->pll_set = impl->pll_set;
 	return 0;
 }
diff --git a/drivers/gpu/drm/nouveau/core/subdev/devinit/nv04.c b/drivers/gpu/drm/nouveau/core/subdev/devinit/nv04.c
index 27c8235f1a85d..7037eae46e445 100644
--- a/drivers/gpu/drm/nouveau/core/subdev/devinit/nv04.c
+++ b/drivers/gpu/drm/nouveau/core/subdev/devinit/nv04.c
@@ -27,12 +27,7 @@
 #include <subdev/vga.h>
 
 #include "fbmem.h"
-#include "priv.h"
-
-struct nv04_devinit_priv {
-	struct nouveau_devinit base;
-	int owner;
-};
+#include "nv04.h"
 
 static void
 nv04_devinit_meminit(struct nouveau_devinit *devinit)
@@ -393,17 +388,21 @@ int
 nv04_devinit_fini(struct nouveau_object *object, bool suspend)
 {
 	struct nv04_devinit_priv *priv = (void *)object;
+	int ret;
 
 	/* make i2c busses accessible */
 	nv_mask(priv, 0x000200, 0x00000001, 0x00000001);
 
-	/* unlock extended vga crtc regs, and unslave crtcs */
-	nv_lockvgac(priv, false);
+	ret = nouveau_devinit_fini(&priv->base, suspend);
+	if (ret)
+		return ret;
+
+	/* unslave crtcs */
 	if (priv->owner < 0)
 		priv->owner = nv_rdvgaowner(priv);
 	nv_wrvgaowner(priv, 0);
 
-	return nouveau_devinit_fini(&priv->base, suspend);
+	return 0;
 }
 
 int
@@ -431,14 +430,13 @@ nv04_devinit_dtor(struct nouveau_object *object)
 {
 	struct nv04_devinit_priv *priv = (void *)object;
 
-	/* restore vga owner saved at first init, and lock crtc regs  */
+	/* restore vga owner saved at first init */
 	nv_wrvgaowner(priv, priv->owner);
-	nv_lockvgac(priv, true);
 
 	nouveau_devinit_destroy(&priv->base);
 }
 
-static int
+int
 nv04_devinit_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
 		  struct nouveau_oclass *oclass, void *data, u32 size,
 		  struct nouveau_object **pobject)
@@ -451,19 +449,19 @@ nv04_devinit_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
 	if (ret)
 		return ret;
 
-	priv->base.meminit = nv04_devinit_meminit;
-	priv->base.pll_set = nv04_devinit_pll_set;
 	priv->owner = -1;
 	return 0;
 }
 
-struct nouveau_oclass
-nv04_devinit_oclass = {
-	.handle = NV_SUBDEV(DEVINIT, 0x04),
-	.ofuncs = &(struct nouveau_ofuncs) {
+struct nouveau_oclass *
+nv04_devinit_oclass = &(struct nouveau_devinit_impl) {
+	.base.handle = NV_SUBDEV(DEVINIT, 0x04),
+	.base.ofuncs = &(struct nouveau_ofuncs) {
 		.ctor = nv04_devinit_ctor,
 		.dtor = nv04_devinit_dtor,
 		.init = nv04_devinit_init,
 		.fini = nv04_devinit_fini,
 	},
-};
+	.meminit = nv04_devinit_meminit,
+	.pll_set = nv04_devinit_pll_set,
+}.base;
diff --git a/drivers/gpu/drm/nouveau/core/subdev/devinit/nv04.h b/drivers/gpu/drm/nouveau/core/subdev/devinit/nv04.h
new file mode 100644
index 0000000000000..23470a57510c3
--- /dev/null
+++ b/drivers/gpu/drm/nouveau/core/subdev/devinit/nv04.h
@@ -0,0 +1,23 @@
+#ifndef __NVKM_DEVINIT_NV04_H__
+#define __NVKM_DEVINIT_NV04_H__
+
+#include "priv.h"
+
+struct nv04_devinit_priv {
+	struct nouveau_devinit base;
+	u8 owner;
+};
+
+int  nv04_devinit_ctor(struct nouveau_object *, struct nouveau_object *,
+		       struct nouveau_oclass *, void *, u32,
+		       struct nouveau_object **);
+void nv04_devinit_dtor(struct nouveau_object *);
+int  nv04_devinit_init(struct nouveau_object *);
+int  nv04_devinit_fini(struct nouveau_object *, bool);
+int  nv04_devinit_pll_set(struct nouveau_devinit *, u32, u32);
+
+void setPLL_single(struct nouveau_devinit *, u32, struct nouveau_pll_vals *);
+void setPLL_double_highregs(struct nouveau_devinit *, u32, struct nouveau_pll_vals *);
+void setPLL_double_lowregs(struct nouveau_devinit *, u32, struct nouveau_pll_vals *);
+
+#endif
diff --git a/drivers/gpu/drm/nouveau/core/subdev/devinit/nv05.c b/drivers/gpu/drm/nouveau/core/subdev/devinit/nv05.c
index b1912a8a89421..98b7e6780dc7f 100644
--- a/drivers/gpu/drm/nouveau/core/subdev/devinit/nv05.c
+++ b/drivers/gpu/drm/nouveau/core/subdev/devinit/nv05.c
@@ -29,12 +29,7 @@
 #include <subdev/vga.h>
 
 #include "fbmem.h"
-#include "priv.h"
-
-struct nv05_devinit_priv {
-	struct nouveau_devinit base;
-	u8 owner;
-};
+#include "nv04.h"
 
 static void
 nv05_devinit_meminit(struct nouveau_devinit *devinit)
@@ -49,7 +44,7 @@ nv05_devinit_meminit(struct nouveau_devinit *devinit)
 		{ 0x06, 0x00 },
 		{ 0x00, 0x00 }
 	};
-	struct nv05_devinit_priv *priv = (void *)devinit;
+	struct nv04_devinit_priv *priv = (void *)devinit;
 	struct nouveau_bios *bios = nouveau_bios(priv);
 	struct io_mapping *fb;
 	u32 patt = 0xdeadbeef;
@@ -130,31 +125,15 @@ nv05_devinit_meminit(struct nouveau_devinit *devinit)
 	fbmem_fini(fb);
 }
 
-static int
-nv05_devinit_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
-		  struct nouveau_oclass *oclass, void *data, u32 size,
-		  struct nouveau_object **pobject)
-{
-	struct nv05_devinit_priv *priv;
-	int ret;
-
-	ret = nouveau_devinit_create(parent, engine, oclass, &priv);
-	*pobject = nv_object(priv);
-	if (ret)
-		return ret;
-
-	priv->base.meminit = nv05_devinit_meminit;
-	priv->base.pll_set = nv04_devinit_pll_set;
-	return 0;
-}
-
-struct nouveau_oclass
-nv05_devinit_oclass = {
-	.handle = NV_SUBDEV(DEVINIT, 0x05),
-	.ofuncs = &(struct nouveau_ofuncs) {
-		.ctor = nv05_devinit_ctor,
+struct nouveau_oclass *
+nv05_devinit_oclass = &(struct nouveau_devinit_impl) {
+	.base.handle = NV_SUBDEV(DEVINIT, 0x05),
+	.base.ofuncs = &(struct nouveau_ofuncs) {
+		.ctor = nv04_devinit_ctor,
 		.dtor = nv04_devinit_dtor,
 		.init = nv04_devinit_init,
 		.fini = nv04_devinit_fini,
 	},
-};
+	.meminit = nv05_devinit_meminit,
+	.pll_set = nv04_devinit_pll_set,
+}.base;
diff --git a/drivers/gpu/drm/nouveau/core/subdev/devinit/nv10.c b/drivers/gpu/drm/nouveau/core/subdev/devinit/nv10.c
index 8d274dba1ef17..32b3d2131a7f0 100644
--- a/drivers/gpu/drm/nouveau/core/subdev/devinit/nv10.c
+++ b/drivers/gpu/drm/nouveau/core/subdev/devinit/nv10.c
@@ -27,17 +27,12 @@
 #include <subdev/vga.h>
 
 #include "fbmem.h"
-#include "priv.h"
-
-struct nv10_devinit_priv {
-	struct nouveau_devinit base;
-	u8 owner;
-};
+#include "nv04.h"
 
 static void
 nv10_devinit_meminit(struct nouveau_devinit *devinit)
 {
-	struct nv10_devinit_priv *priv = (void *)devinit;
+	struct nv04_devinit_priv *priv = (void *)devinit;
 	static const int mem_width[] = { 0x10, 0x00, 0x20 };
 	int mem_width_count;
 	uint32_t patt = 0xdeadbeef;
@@ -101,31 +96,15 @@ nv10_devinit_meminit(struct nouveau_devinit *devinit)
 	fbmem_fini(fb);
 }
 
-static int
-nv10_devinit_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
-		  struct nouveau_oclass *oclass, void *data, u32 size,
-		  struct nouveau_object **pobject)
-{
-	struct nv10_devinit_priv *priv;
-	int ret;
-
-	ret = nouveau_devinit_create(parent, engine, oclass, &priv);
-	*pobject = nv_object(priv);
-	if (ret)
-		return ret;
-
-	priv->base.meminit = nv10_devinit_meminit;
-	priv->base.pll_set = nv04_devinit_pll_set;
-	return 0;
-}
-
-struct nouveau_oclass
-nv10_devinit_oclass = {
-	.handle = NV_SUBDEV(DEVINIT, 0x10),
-	.ofuncs = &(struct nouveau_ofuncs) {
-		.ctor = nv10_devinit_ctor,
+struct nouveau_oclass *
+nv10_devinit_oclass = &(struct nouveau_devinit_impl) {
+	.base.handle = NV_SUBDEV(DEVINIT, 0x10),
+	.base.ofuncs = &(struct nouveau_ofuncs) {
+		.ctor = nv04_devinit_ctor,
 		.dtor = nv04_devinit_dtor,
 		.init = nv04_devinit_init,
 		.fini = nv04_devinit_fini,
 	},
-};
+	.meminit = nv10_devinit_meminit,
+	.pll_set = nv04_devinit_pll_set,
+}.base;
diff --git a/drivers/gpu/drm/nouveau/core/subdev/devinit/nv1a.c b/drivers/gpu/drm/nouveau/core/subdev/devinit/nv1a.c
index e9743cdabe757..526d0c6faacd3 100644
--- a/drivers/gpu/drm/nouveau/core/subdev/devinit/nv1a.c
+++ b/drivers/gpu/drm/nouveau/core/subdev/devinit/nv1a.c
@@ -22,37 +22,16 @@
  * Authors: Ben Skeggs
  */
 
-#include "priv.h"
+#include "nv04.h"
 
-struct nv1a_devinit_priv {
-	struct nouveau_devinit base;
-	u8 owner;
-};
-
-static int
-nv1a_devinit_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
-		  struct nouveau_oclass *oclass, void *data, u32 size,
-		  struct nouveau_object **pobject)
-{
-	struct nv1a_devinit_priv *priv;
-	int ret;
-
-	ret = nouveau_devinit_create(parent, engine, oclass, &priv);
-	*pobject = nv_object(priv);
-	if (ret)
-		return ret;
-
-	priv->base.pll_set = nv04_devinit_pll_set;
-	return 0;
-}
-
-struct nouveau_oclass
-nv1a_devinit_oclass = {
-	.handle = NV_SUBDEV(DEVINIT, 0x1a),
-	.ofuncs = &(struct nouveau_ofuncs) {
-		.ctor = nv1a_devinit_ctor,
+struct nouveau_oclass *
+nv1a_devinit_oclass = &(struct nouveau_devinit_impl) {
+	.base.handle = NV_SUBDEV(DEVINIT, 0x1a),
+	.base.ofuncs = &(struct nouveau_ofuncs) {
+		.ctor = nv04_devinit_ctor,
 		.dtor = nv04_devinit_dtor,
 		.init = nv04_devinit_init,
 		.fini = nv04_devinit_fini,
 	},
-};
+	.pll_set = nv04_devinit_pll_set,
+}.base;
diff --git a/drivers/gpu/drm/nouveau/core/subdev/devinit/nv20.c b/drivers/gpu/drm/nouveau/core/subdev/devinit/nv20.c
index 6cc6080d3bc01..4689ba303b0bd 100644
--- a/drivers/gpu/drm/nouveau/core/subdev/devinit/nv20.c
+++ b/drivers/gpu/drm/nouveau/core/subdev/devinit/nv20.c
@@ -24,18 +24,13 @@
  *
  */
 
-#include "priv.h"
+#include "nv04.h"
 #include "fbmem.h"
 
-struct nv20_devinit_priv {
-	struct nouveau_devinit base;
-	u8 owner;
-};
-
 static void
 nv20_devinit_meminit(struct nouveau_devinit *devinit)
 {
-	struct nv20_devinit_priv *priv = (void *)devinit;
+	struct nv04_devinit_priv *priv = (void *)devinit;
 	struct nouveau_device *device = nv_device(priv);
 	uint32_t mask = (device->chipset >= 0x25 ? 0x300 : 0x900);
 	uint32_t amount, off;
@@ -65,31 +60,15 @@ nv20_devinit_meminit(struct nouveau_devinit *devinit)
 	fbmem_fini(fb);
 }
 
-static int
-nv20_devinit_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
-		  struct nouveau_oclass *oclass, void *data, u32 size,
-		  struct nouveau_object **pobject)
-{
-	struct nv20_devinit_priv *priv;
-	int ret;
-
-	ret = nouveau_devinit_create(parent, engine, oclass, &priv);
-	*pobject = nv_object(priv);
-	if (ret)
-		return ret;
-
-	priv->base.meminit = nv20_devinit_meminit;
-	priv->base.pll_set = nv04_devinit_pll_set;
-	return 0;
-}
-
-struct nouveau_oclass
-nv20_devinit_oclass = {
-	.handle = NV_SUBDEV(DEVINIT, 0x20),
-	.ofuncs = &(struct nouveau_ofuncs) {
-		.ctor = nv20_devinit_ctor,
+struct nouveau_oclass *
+nv20_devinit_oclass = &(struct nouveau_devinit_impl) {
+	.base.handle = NV_SUBDEV(DEVINIT, 0x20),
+	.base.ofuncs = &(struct nouveau_ofuncs) {
+		.ctor = nv04_devinit_ctor,
 		.dtor = nv04_devinit_dtor,
 		.init = nv04_devinit_init,
 		.fini = nv04_devinit_fini,
 	},
-};
+	.meminit = nv20_devinit_meminit,
+	.pll_set = nv04_devinit_pll_set,
+}.base;
diff --git a/drivers/gpu/drm/nouveau/core/subdev/devinit/nv50.c b/drivers/gpu/drm/nouveau/core/subdev/devinit/nv50.c
index 6df72247c477b..b46c62a1d5d86 100644
--- a/drivers/gpu/drm/nouveau/core/subdev/devinit/nv50.c
+++ b/drivers/gpu/drm/nouveau/core/subdev/devinit/nv50.c
@@ -28,9 +28,9 @@
 #include <subdev/bios/init.h>
 #include <subdev/vga.h>
 
-#include "priv.h"
+#include "nv50.h"
 
-static int
+int
 nv50_devinit_pll_set(struct nouveau_devinit *devinit, u32 type, u32 freq)
 {
 	struct nv50_devinit_priv *priv = (void *)devinit;
@@ -74,6 +74,19 @@ nv50_devinit_pll_set(struct nouveau_devinit *devinit, u32 type, u32 freq)
 	return 0;
 }
 
+static u64
+nv50_devinit_disable(struct nouveau_devinit *devinit)
+{
+	struct nv50_devinit_priv *priv = (void *)devinit;
+	u32 r001540 = nv_rd32(priv, 0x001540);
+	u64 disable = 0ULL;
+
+	if (!(r001540 & 0x40000000))
+		disable |= (1ULL << NVDEV_ENGINE_MPEG);
+
+	return disable;
+}
+
 int
 nv50_devinit_init(struct nouveau_object *object)
 {
@@ -120,7 +133,7 @@ nv50_devinit_init(struct nouveau_object *object)
 	return 0;
 }
 
-static int
+int
 nv50_devinit_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
 		  struct nouveau_oclass *oclass, void *data, u32 size,
 		  struct nouveau_object **pobject)
@@ -133,17 +146,18 @@ nv50_devinit_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
 	if (ret)
 		return ret;
 
-	priv->base.pll_set = nv50_devinit_pll_set;
 	return 0;
 }
 
-struct nouveau_oclass
-nv50_devinit_oclass = {
-	.handle = NV_SUBDEV(DEVINIT, 0x50),
-	.ofuncs = &(struct nouveau_ofuncs) {
+struct nouveau_oclass *
+nv50_devinit_oclass = &(struct nouveau_devinit_impl) {
+	.base.handle = NV_SUBDEV(DEVINIT, 0x50),
+	.base.ofuncs = &(struct nouveau_ofuncs) {
 		.ctor = nv50_devinit_ctor,
 		.dtor = _nouveau_devinit_dtor,
 		.init = nv50_devinit_init,
 		.fini = _nouveau_devinit_fini,
 	},
-};
+	.pll_set = nv50_devinit_pll_set,
+	.disable = nv50_devinit_disable,
+}.base;
diff --git a/drivers/gpu/drm/nouveau/core/subdev/devinit/nv50.h b/drivers/gpu/drm/nouveau/core/subdev/devinit/nv50.h
new file mode 100644
index 0000000000000..141c27e9f1827
--- /dev/null
+++ b/drivers/gpu/drm/nouveau/core/subdev/devinit/nv50.h
@@ -0,0 +1,18 @@
+#ifndef __NVKM_DEVINIT_NV50_H__
+#define __NVKM_DEVINIT_NV50_H__
+
+#include "priv.h"
+
+struct nv50_devinit_priv {
+	struct nouveau_devinit base;
+};
+
+int  nv50_devinit_ctor(struct nouveau_object *, struct nouveau_object *,
+		       struct nouveau_oclass *, void *, u32,
+		       struct nouveau_object **);
+int  nv50_devinit_init(struct nouveau_object *);
+int  nv50_devinit_pll_set(struct nouveau_devinit *, u32, u32);
+
+int  nva3_devinit_pll_set(struct nouveau_devinit *, u32, u32);
+
+#endif
diff --git a/drivers/gpu/drm/nouveau/core/subdev/devinit/nv84.c b/drivers/gpu/drm/nouveau/core/subdev/devinit/nv84.c
new file mode 100644
index 0000000000000..787422505d87b
--- /dev/null
+++ b/drivers/gpu/drm/nouveau/core/subdev/devinit/nv84.c
@@ -0,0 +1,63 @@
+/*
+ * Copyright 2013 Red Hat Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: Ben Skeggs
+ */
+
+#include "nv50.h"
+
+static u64
+nv84_devinit_disable(struct nouveau_devinit *devinit)
+{
+	struct nv50_devinit_priv *priv = (void *)devinit;
+	u32 r001540 = nv_rd32(priv, 0x001540);
+	u32 r00154c = nv_rd32(priv, 0x00154c);
+	u64 disable = 0ULL;
+
+	if (!(r001540 & 0x40000000)) {
+		disable |= (1ULL << NVDEV_ENGINE_MPEG);
+		disable |= (1ULL << NVDEV_ENGINE_VP);
+		disable |= (1ULL << NVDEV_ENGINE_BSP);
+		disable |= (1ULL << NVDEV_ENGINE_CRYPT);
+	}
+
+	if (!(r00154c & 0x00000004))
+		disable |= (1ULL << NVDEV_ENGINE_DISP);
+	if (!(r00154c & 0x00000020))
+		disable |= (1ULL << NVDEV_ENGINE_BSP);
+	if (!(r00154c & 0x00000040))
+		disable |= (1ULL << NVDEV_ENGINE_CRYPT);
+
+	return disable;
+}
+
+struct nouveau_oclass *
+nv84_devinit_oclass = &(struct nouveau_devinit_impl) {
+	.base.handle = NV_SUBDEV(DEVINIT, 0x84),
+	.base.ofuncs = &(struct nouveau_ofuncs) {
+		.ctor = nv50_devinit_ctor,
+		.dtor = _nouveau_devinit_dtor,
+		.init = nv50_devinit_init,
+		.fini = _nouveau_devinit_fini,
+	},
+	.pll_set = nv50_devinit_pll_set,
+	.disable = nv84_devinit_disable,
+}.base;
diff --git a/drivers/gpu/drm/nouveau/core/subdev/devinit/nv98.c b/drivers/gpu/drm/nouveau/core/subdev/devinit/nv98.c
new file mode 100644
index 0000000000000..2b0e963fc6f01
--- /dev/null
+++ b/drivers/gpu/drm/nouveau/core/subdev/devinit/nv98.c
@@ -0,0 +1,62 @@
+/*
+ * Copyright 2013 Red Hat Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: Ben Skeggs
+ */
+
+#include "nv50.h"
+
+static u64
+nv98_devinit_disable(struct nouveau_devinit *devinit)
+{
+	struct nv50_devinit_priv *priv = (void *)devinit;
+	u32 r001540 = nv_rd32(priv, 0x001540);
+	u32 r00154c = nv_rd32(priv, 0x00154c);
+	u64 disable = 0ULL;
+
+	if (!(r001540 & 0x40000000)) {
+		disable |= (1ULL << NVDEV_ENGINE_VP);
+		disable |= (1ULL << NVDEV_ENGINE_BSP);
+		disable |= (1ULL << NVDEV_ENGINE_PPP);
+	}
+
+	if (!(r00154c & 0x00000004))
+		disable |= (1ULL << NVDEV_ENGINE_DISP);
+	if (!(r00154c & 0x00000020))
+		disable |= (1ULL << NVDEV_ENGINE_BSP);
+	if (!(r00154c & 0x00000040))
+		disable |= (1ULL << NVDEV_ENGINE_CRYPT);
+
+	return disable;
+}
+
+struct nouveau_oclass *
+nv98_devinit_oclass = &(struct nouveau_devinit_impl) {
+	.base.handle = NV_SUBDEV(DEVINIT, 0x98),
+	.base.ofuncs = &(struct nouveau_ofuncs) {
+		.ctor = nv50_devinit_ctor,
+		.dtor = _nouveau_devinit_dtor,
+		.init = nv50_devinit_init,
+		.fini = _nouveau_devinit_fini,
+	},
+	.pll_set = nv50_devinit_pll_set,
+	.disable = nv98_devinit_disable,
+}.base;
diff --git a/drivers/gpu/drm/nouveau/core/subdev/devinit/nva3.c b/drivers/gpu/drm/nouveau/core/subdev/devinit/nva3.c
index 76a68b2901411..6dedf1dad7f7b 100644
--- a/drivers/gpu/drm/nouveau/core/subdev/devinit/nva3.c
+++ b/drivers/gpu/drm/nouveau/core/subdev/devinit/nva3.c
@@ -22,12 +22,12 @@
  * Authors: Ben Skeggs
  */
 
-#include "priv.h"
+#include "nv50.h"
 
-static int
+int
 nva3_devinit_pll_set(struct nouveau_devinit *devinit, u32 type, u32 freq)
 {
-	struct nva3_devinit_priv *priv = (void *)devinit;
+	struct nv50_devinit_priv *priv = (void *)devinit;
 	struct nouveau_bios *bios = nouveau_bios(priv);
 	struct nvbios_pll info;
 	int N, fN, M, P;
@@ -58,30 +58,38 @@ nva3_devinit_pll_set(struct nouveau_devinit *devinit, u32 type, u32 freq)
 	return ret;
 }
 
-static int
-nva3_devinit_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
-		  struct nouveau_oclass *oclass, void *data, u32 size,
-		  struct nouveau_object **pobject)
+static u64
+nva3_devinit_disable(struct nouveau_devinit *devinit)
 {
-	struct nv50_devinit_priv *priv;
-	int ret;
+	struct nv50_devinit_priv *priv = (void *)devinit;
+	u32 r001540 = nv_rd32(priv, 0x001540);
+	u32 r00154c = nv_rd32(priv, 0x00154c);
+	u64 disable = 0ULL;
 
-	ret = nouveau_devinit_create(parent, engine, oclass, &priv);
-	*pobject = nv_object(priv);
-	if (ret)
-		return ret;
+	if (!(r001540 & 0x40000000)) {
+		disable |= (1ULL << NVDEV_ENGINE_VP);
+		disable |= (1ULL << NVDEV_ENGINE_PPP);
+	}
+
+	if (!(r00154c & 0x00000004))
+		disable |= (1ULL << NVDEV_ENGINE_DISP);
+	if (!(r00154c & 0x00000020))
+		disable |= (1ULL << NVDEV_ENGINE_BSP);
+	if (!(r00154c & 0x00000200))
+		disable |= (1ULL << NVDEV_ENGINE_COPY0);
 
-	priv->base.pll_set = nva3_devinit_pll_set;
-	return 0;
+	return disable;
 }
 
-struct nouveau_oclass
-nva3_devinit_oclass = {
-	.handle = NV_SUBDEV(DEVINIT, 0xa3),
-	.ofuncs = &(struct nouveau_ofuncs) {
-		.ctor = nva3_devinit_ctor,
+struct nouveau_oclass *
+nva3_devinit_oclass = &(struct nouveau_devinit_impl) {
+	.base.handle = NV_SUBDEV(DEVINIT, 0xa3),
+	.base.ofuncs = &(struct nouveau_ofuncs) {
+		.ctor = nv50_devinit_ctor,
 		.dtor = _nouveau_devinit_dtor,
 		.init = nv50_devinit_init,
 		.fini = _nouveau_devinit_fini,
 	},
-};
+	.pll_set = nva3_devinit_pll_set,
+	.disable = nva3_devinit_disable,
+}.base;
diff --git a/drivers/gpu/drm/nouveau/core/subdev/devinit/nvaf.c b/drivers/gpu/drm/nouveau/core/subdev/devinit/nvaf.c
new file mode 100644
index 0000000000000..4fc68d27eff39
--- /dev/null
+++ b/drivers/gpu/drm/nouveau/core/subdev/devinit/nvaf.c
@@ -0,0 +1,63 @@
+/*
+ * Copyright 2013 Red Hat Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: Ben Skeggs
+ */
+
+#include "nv50.h"
+
+static u64
+nvaf_devinit_disable(struct nouveau_devinit *devinit)
+{
+	struct nv50_devinit_priv *priv = (void *)devinit;
+	u32 r001540 = nv_rd32(priv, 0x001540);
+	u32 r00154c = nv_rd32(priv, 0x00154c);
+	u64 disable = 0;
+
+	if (!(r001540 & 0x40000000)) {
+		disable |= (1ULL << NVDEV_ENGINE_VP);
+		disable |= (1ULL << NVDEV_ENGINE_PPP);
+	}
+
+	if (!(r00154c & 0x00000004))
+		disable |= (1ULL << NVDEV_ENGINE_DISP);
+	if (!(r00154c & 0x00000020))
+		disable |= (1ULL << NVDEV_ENGINE_BSP);
+	if (!(r00154c & 0x00000040))
+		disable |= (1ULL << NVDEV_ENGINE_VIC);
+	if (!(r00154c & 0x00000200))
+		disable |= (1ULL << NVDEV_ENGINE_COPY0);
+
+	return disable;
+}
+
+struct nouveau_oclass *
+nvaf_devinit_oclass = &(struct nouveau_devinit_impl) {
+	.base.handle = NV_SUBDEV(DEVINIT, 0xaf),
+	.base.ofuncs = &(struct nouveau_ofuncs) {
+		.ctor = nv50_devinit_ctor,
+		.dtor = _nouveau_devinit_dtor,
+		.init = nv50_devinit_init,
+		.fini = _nouveau_devinit_fini,
+	},
+	.pll_set = nva3_devinit_pll_set,
+	.disable = nvaf_devinit_disable,
+}.base;
diff --git a/drivers/gpu/drm/nouveau/core/subdev/devinit/nvc0.c b/drivers/gpu/drm/nouveau/core/subdev/devinit/nvc0.c
index 19e265bf4574a..fa7e63766b1b1 100644
--- a/drivers/gpu/drm/nouveau/core/subdev/devinit/nvc0.c
+++ b/drivers/gpu/drm/nouveau/core/subdev/devinit/nvc0.c
@@ -22,12 +22,12 @@
  * Authors: Ben Skeggs
  */
 
-#include "priv.h"
+#include "nv50.h"
 
 static int
 nvc0_devinit_pll_set(struct nouveau_devinit *devinit, u32 type, u32 freq)
 {
-	struct nvc0_devinit_priv *priv = (void *)devinit;
+	struct nv50_devinit_priv *priv = (void *)devinit;
 	struct nouveau_bios *bios = nouveau_bios(priv);
 	struct nvbios_pll info;
 	int N, fN, M, P;
@@ -59,6 +59,33 @@ nvc0_devinit_pll_set(struct nouveau_devinit *devinit, u32 type, u32 freq)
 	return ret;
 }
 
+static u64
+nvc0_devinit_disable(struct nouveau_devinit *devinit)
+{
+	struct nv50_devinit_priv *priv = (void *)devinit;
+	u32 r022500 = nv_rd32(priv, 0x022500);
+	u64 disable = 0ULL;
+
+	if (r022500 & 0x00000001)
+		disable |= (1ULL << NVDEV_ENGINE_DISP);
+
+	if (r022500 & 0x00000002) {
+		disable |= (1ULL << NVDEV_ENGINE_VP);
+		disable |= (1ULL << NVDEV_ENGINE_PPP);
+	}
+
+	if (r022500 & 0x00000004)
+		disable |= (1ULL << NVDEV_ENGINE_BSP);
+	if (r022500 & 0x00000008)
+		disable |= (1ULL << NVDEV_ENGINE_VENC);
+	if (r022500 & 0x00000100)
+		disable |= (1ULL << NVDEV_ENGINE_COPY0);
+	if (r022500 & 0x00000200)
+		disable |= (1ULL << NVDEV_ENGINE_COPY1);
+
+	return disable;
+}
+
 static int
 nvc0_devinit_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
 		  struct nouveau_oclass *oclass, void *data, u32 size,
@@ -72,19 +99,20 @@ nvc0_devinit_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
 	if (ret)
 		return ret;
 
-	priv->base.pll_set = nvc0_devinit_pll_set;
 	if (nv_rd32(priv, 0x022500) & 0x00000001)
 		priv->base.post = true;
 	return 0;
 }
 
-struct nouveau_oclass
-nvc0_devinit_oclass = {
-	.handle = NV_SUBDEV(DEVINIT, 0xc0),
-	.ofuncs = &(struct nouveau_ofuncs) {
+struct nouveau_oclass *
+nvc0_devinit_oclass = &(struct nouveau_devinit_impl) {
+	.base.handle = NV_SUBDEV(DEVINIT, 0xc0),
+	.base.ofuncs = &(struct nouveau_ofuncs) {
 		.ctor = nvc0_devinit_ctor,
 		.dtor = _nouveau_devinit_dtor,
 		.init = nv50_devinit_init,
 		.fini = _nouveau_devinit_fini,
 	},
-};
+	.pll_set = nvc0_devinit_pll_set,
+	.disable = nvc0_devinit_disable,
+}.base;
diff --git a/drivers/gpu/drm/nouveau/core/subdev/devinit/priv.h b/drivers/gpu/drm/nouveau/core/subdev/devinit/priv.h
index 7d622e2b01712..822a2fbf44a5b 100644
--- a/drivers/gpu/drm/nouveau/core/subdev/devinit/priv.h
+++ b/drivers/gpu/drm/nouveau/core/subdev/devinit/priv.h
@@ -6,20 +6,32 @@
 #include <subdev/clock/pll.h>
 #include <subdev/devinit.h>
 
-void nv04_devinit_dtor(struct nouveau_object *);
-int  nv04_devinit_init(struct nouveau_object *);
-int  nv04_devinit_fini(struct nouveau_object *, bool);
-int  nv04_devinit_pll_set(struct nouveau_devinit *, u32, u32);
-
-void setPLL_single(struct nouveau_devinit *, u32, struct nouveau_pll_vals *);
-void setPLL_double_highregs(struct nouveau_devinit *, u32, struct nouveau_pll_vals *);
-void setPLL_double_lowregs(struct nouveau_devinit *, u32, struct nouveau_pll_vals *);
-
-
-struct nv50_devinit_priv {
-	struct nouveau_devinit base;
+struct nouveau_devinit_impl {
+	struct nouveau_oclass base;
+	void (*meminit)(struct nouveau_devinit *);
+	int  (*pll_set)(struct nouveau_devinit *, u32 type, u32 freq);
+	u64  (*disable)(struct nouveau_devinit *);
 };
 
-int  nv50_devinit_init(struct nouveau_object *);
+#define nouveau_devinit_create(p,e,o,d)                                        \
+	nouveau_devinit_create_((p), (e), (o), sizeof(**d), (void **)d)
+#define nouveau_devinit_destroy(p) ({                                          \
+	struct nouveau_devinit *d = (p);                                       \
+	_nouveau_devinit_dtor(nv_object(d));                                   \
+})
+#define nouveau_devinit_init(p) ({                                             \
+	struct nouveau_devinit *d = (p);                                       \
+	_nouveau_devinit_init(nv_object(d));                                   \
+})
+#define nouveau_devinit_fini(p,s) ({                                           \
+	struct nouveau_devinit *d = (p);                                       \
+	_nouveau_devinit_fini(nv_object(d), (s));                              \
+})
+
+int nouveau_devinit_create_(struct nouveau_object *, struct nouveau_object *,
+			    struct nouveau_oclass *, int, void **);
+void _nouveau_devinit_dtor(struct nouveau_object *);
+int _nouveau_devinit_init(struct nouveau_object *);
+int _nouveau_devinit_fini(struct nouveau_object *, bool suspend);
 
 #endif
diff --git a/drivers/gpu/drm/nouveau/core/subdev/fb/gddr5.c b/drivers/gpu/drm/nouveau/core/subdev/fb/gddr5.c
index 34f9605ffee61..66fe959b4f743 100644
--- a/drivers/gpu/drm/nouveau/core/subdev/fb/gddr5.c
+++ b/drivers/gpu/drm/nouveau/core/subdev/fb/gddr5.c
@@ -25,35 +25,44 @@
 #include <subdev/bios.h>
 #include "priv.h"
 
+/* binary driver only executes this path if the condition (a) is true
+ * for any configuration (combination of rammap+ramcfg+timing) that
+ * can be reached on a given card.  for now, we will execute the branch
+ * unconditionally in the hope that a "false everywhere" in the bios
+ * tables doesn't actually mean "don't touch this".
+ */
+#define NOTE00(a) 1
+
 int
-nouveau_gddr5_calc(struct nouveau_ram *ram)
+nouveau_gddr5_calc(struct nouveau_ram *ram, bool nuts)
 {
-	struct nouveau_bios *bios = nouveau_bios(ram);
-	int pd, lf, xd, vh, vr, vo;
-	int WL, CL, WR, at, dt, ds;
+	int pd, lf, xd, vh, vr, vo, l3;
+	int WL, CL, WR, at[2], dt, ds;
 	int rq = ram->freq < 1000000; /* XXX */
 
-	switch (!!ram->ramcfg.data * ram->ramcfg.version) {
+	switch (ram->ramcfg.version) {
 	case 0x11:
-		pd =  (nv_ro08(bios, ram->ramcfg.data + 0x01) & 0x80) >> 7;
-		lf =  (nv_ro08(bios, ram->ramcfg.data + 0x01) & 0x40) >> 6;
-		xd = !(nv_ro08(bios, ram->ramcfg.data + 0x01) & 0x20);
-		vh =  (nv_ro08(bios, ram->ramcfg.data + 0x02) & 0x10) >> 4;
-		vr =  (nv_ro08(bios, ram->ramcfg.data + 0x02) & 0x04) >> 2;
-		vo =   nv_ro08(bios, ram->ramcfg.data + 0x06) & 0xff;
+		pd =  ram->next->bios.ramcfg_11_01_80;
+		lf =  ram->next->bios.ramcfg_11_01_40;
+		xd = !ram->next->bios.ramcfg_11_01_20;
+		vh =  ram->next->bios.ramcfg_11_02_10;
+		vr =  ram->next->bios.ramcfg_11_02_04;
+		vo =  ram->next->bios.ramcfg_11_06;
+		l3 = !ram->next->bios.ramcfg_11_07_02;
 		break;
 	default:
 		return -ENOSYS;
 	}
 
-	switch (!!ram->timing.data * ram->timing.version) {
+	switch (ram->timing.version) {
 	case 0x20:
-		WL = (nv_ro16(bios, ram->timing.data + 0x04) & 0x0f80) >> 7;
-		CL =  nv_ro08(bios, ram->timing.data + 0x04) & 0x1f;
-		WR =  nv_ro08(bios, ram->timing.data + 0x0a) & 0x7f;
-		at = (nv_ro08(bios, ram->timing.data + 0x2e) & 0xc0) >> 6;
-		dt =  nv_ro08(bios, ram->timing.data + 0x2e) & 0x03;
-		ds =  nv_ro08(bios, ram->timing.data + 0x2f) & 0x03;
+		WL = (ram->next->bios.timing[1] & 0x00000f80) >> 7;
+		CL = (ram->next->bios.timing[1] & 0x0000001f);
+		WR = (ram->next->bios.timing[2] & 0x007f0000) >> 16;
+		at[0] = ram->next->bios.timing_20_2e_c0;
+		at[1] = ram->next->bios.timing_20_2e_30;
+		dt =  ram->next->bios.timing_20_2e_03;
+		ds =  ram->next->bios.timing_20_2f_03;
 		break;
 	default:
 		return -ENOSYS;
@@ -71,13 +80,25 @@ nouveau_gddr5_calc(struct nouveau_ram *ram)
 
 	ram->mr[1] &= ~0x0bf;
 	ram->mr[1] |= (xd & 0x01) << 7;
-	ram->mr[1] |= (at & 0x03) << 4;
+	ram->mr[1] |= (at[0] & 0x03) << 4;
 	ram->mr[1] |= (dt & 0x03) << 2;
 	ram->mr[1] |= (ds & 0x03) << 0;
 
+	/* this seems wrong, alternate field used for the broadcast
+	 * on nuts vs non-nuts configs..  meh, it matches for now.
+	 */
+	ram->mr1_nuts = ram->mr[1];
+	if (nuts) {
+		ram->mr[1] &= ~0x030;
+		ram->mr[1] |= (at[1] & 0x03) << 4;
+	}
+
 	ram->mr[3] &= ~0x020;
 	ram->mr[3] |= (rq & 0x01) << 5;
 
+	ram->mr[5] &= ~0x004;
+	ram->mr[5] |= (l3 << 2);
+
 	if (!vo)
 		vo = (ram->mr[6] & 0xff0) >> 4;
 	if (ram->mr[6] & 0x001)
@@ -86,11 +107,16 @@ nouveau_gddr5_calc(struct nouveau_ram *ram)
 	ram->mr[6] |= (vo & 0xff) << 4;
 	ram->mr[6] |= (pd & 0x01) << 0;
 
-	if (!(ram->mr[7] & 0x100))
-		vr = 0; /* binary driver does this.. bug? */
-	ram->mr[7] &= ~0x188;
-	ram->mr[7] |= (vr & 0x01) << 8;
+	if (NOTE00(vr)) {
+		ram->mr[7] &= ~0x300;
+		ram->mr[7] |= (vr & 0x03) << 8;
+	}
+	ram->mr[7] &= ~0x088;
 	ram->mr[7] |= (vh & 0x01) << 7;
 	ram->mr[7] |= (lf & 0x01) << 3;
+
+	ram->mr[8] &= ~0x003;
+	ram->mr[8] |= (WR & 0x10) >> 3;
+	ram->mr[8] |= (CL & 0x10) >> 4;
 	return 0;
 }
diff --git a/drivers/gpu/drm/nouveau/core/subdev/fb/nvc0.c b/drivers/gpu/drm/nouveau/core/subdev/fb/nvc0.c
index e5fc37c4caac8..45470e1f0385f 100644
--- a/drivers/gpu/drm/nouveau/core/subdev/fb/nvc0.c
+++ b/drivers/gpu/drm/nouveau/core/subdev/fb/nvc0.c
@@ -33,6 +33,21 @@ nvc0_fb_memtype_valid(struct nouveau_fb *pfb, u32 tile_flags)
 	return likely((nvc0_pte_storage_type_map[memtype] != 0xff));
 }
 
+static void
+nvc0_fb_intr(struct nouveau_subdev *subdev)
+{
+	struct nvc0_fb_priv *priv = (void *)subdev;
+	u32 intr = nv_rd32(priv, 0x000100);
+	if (intr & 0x08000000) {
+		nv_debug(priv, "PFFB intr\n");
+		intr &= ~0x08000000;
+	}
+	if (intr & 0x00002000) {
+		nv_debug(priv, "PBFB intr\n");
+		intr &= ~0x00002000;
+	}
+}
+
 int
 nvc0_fb_init(struct nouveau_object *object)
 {
@@ -86,6 +101,7 @@ nvc0_fb_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
 			return -EFAULT;
 	}
 
+	nv_subdev(priv)->intr = nvc0_fb_intr;
 	return 0;
 }
 
diff --git a/drivers/gpu/drm/nouveau/core/subdev/fb/priv.h b/drivers/gpu/drm/nouveau/core/subdev/fb/priv.h
index 493125214e886..edaf95dee6128 100644
--- a/drivers/gpu/drm/nouveau/core/subdev/fb/priv.h
+++ b/drivers/gpu/drm/nouveau/core/subdev/fb/priv.h
@@ -34,7 +34,7 @@ extern struct nouveau_oclass nvc0_ram_oclass;
 extern struct nouveau_oclass nve0_ram_oclass;
 
 int nouveau_sddr3_calc(struct nouveau_ram *ram);
-int nouveau_gddr5_calc(struct nouveau_ram *ram);
+int nouveau_gddr5_calc(struct nouveau_ram *ram, bool nuts);
 
 #define nouveau_fb_create(p,e,c,d)                                             \
 	nouveau_fb_create_((p), (e), (c), sizeof(**d), (void **)d)
diff --git a/drivers/gpu/drm/nouveau/core/subdev/fb/ramnv50.c b/drivers/gpu/drm/nouveau/core/subdev/fb/ramnv50.c
index 76762a17d89cf..c7fdb3a9e88b0 100644
--- a/drivers/gpu/drm/nouveau/core/subdev/fb/ramnv50.c
+++ b/drivers/gpu/drm/nouveau/core/subdev/fb/ramnv50.c
@@ -70,13 +70,11 @@ nv50_ram_calc(struct nouveau_fb *pfb, u32 freq)
 	struct nv50_ramseq *hwsq = &ram->hwsq;
 	struct nvbios_perfE perfE;
 	struct nvbios_pll mpll;
-	struct bit_entry M;
 	struct {
 		u32 data;
 		u8  size;
 	} ramcfg, timing;
-	u8  ver, hdr, cnt, strap;
-	u32 data;
+	u8  ver, hdr, cnt, len, strap;
 	int N1, M1, N2, M2, P;
 	int ret, i;
 
@@ -93,16 +91,7 @@ nv50_ram_calc(struct nouveau_fb *pfb, u32 freq)
 	} while (perfE.memory < freq);
 
 	/* locate specific data set for the attached memory */
-	if (bit_entry(bios, 'M', &M) || M.version != 1 || M.length < 5) {
-		nv_error(pfb, "invalid/missing memory table\n");
-		return -EINVAL;
-	}
-
-	strap = (nv_rd32(pfb, 0x101000) & 0x0000003c) >> 2;
-	data = nv_ro16(bios, M.offset + 3);
-	if (data)
-		strap = nv_ro08(bios, data + strap);
-
+	strap = nvbios_ramcfg_index(bios);
 	if (strap >= cnt) {
 		nv_error(pfb, "invalid ramcfg strap\n");
 		return -EINVAL;
@@ -113,7 +102,8 @@ nv50_ram_calc(struct nouveau_fb *pfb, u32 freq)
 	/* lookup memory timings, if bios says they're present */
 	strap = nv_ro08(bios, ramcfg.data + 0x01);
 	if (strap != 0xff) {
-		timing.data = nvbios_timing_entry(bios, strap, &ver, &hdr);
+		timing.data = nvbios_timingEe(bios, strap, &ver, &hdr,
+					     &cnt, &len);
 		if (!timing.data || ver != 0x10 || hdr < 0x12) {
 			nv_error(pfb, "invalid/missing timing entry "
 				 "%02x %04x %02x %02x\n",
diff --git a/drivers/gpu/drm/nouveau/core/subdev/fb/ramnva3.c b/drivers/gpu/drm/nouveau/core/subdev/fb/ramnva3.c
index f6292cd9207cf..f4ae8aa46a255 100644
--- a/drivers/gpu/drm/nouveau/core/subdev/fb/ramnva3.c
+++ b/drivers/gpu/drm/nouveau/core/subdev/fb/ramnva3.c
@@ -79,8 +79,7 @@ nva3_ram_calc(struct nouveau_fb *pfb, u32 freq)
 	struct nva3_ram *ram = (void *)pfb->ram;
 	struct nva3_ramfuc *fuc = &ram->fuc;
 	struct nva3_clock_info mclk;
-	struct bit_entry M;
-	u8  ver, cnt, strap;
+	u8  ver, cnt, len, strap;
 	u32 data;
 	struct {
 		u32 data;
@@ -91,24 +90,15 @@ nva3_ram_calc(struct nouveau_fb *pfb, u32 freq)
 	int ret;
 
 	/* lookup memory config data relevant to the target frequency */
-	rammap.data = nvbios_rammap_match(bios, freq / 1000, &ver, &rammap.size,
-					 &cnt, &ramcfg.size);
+	rammap.data = nvbios_rammapEm(bios, freq / 1000, &ver, &rammap.size,
+				     &cnt, &ramcfg.size);
 	if (!rammap.data || ver != 0x10 || rammap.size < 0x0e) {
 		nv_error(pfb, "invalid/missing rammap entry\n");
 		return -EINVAL;
 	}
 
 	/* locate specific data set for the attached memory */
-	if (bit_entry(bios, 'M', &M) || M.version != 2 || M.length < 3) {
-		nv_error(pfb, "invalid/missing memory table\n");
-		return -EINVAL;
-	}
-
-	strap = (nv_rd32(pfb, 0x101000) & 0x0000003c) >> 2;
-	data = nv_ro16(bios, M.offset + 1);
-	if (data)
-		strap = nv_ro08(bios, data + strap);
-
+	strap = nvbios_ramcfg_index(bios);
 	if (strap >= cnt) {
 		nv_error(pfb, "invalid ramcfg strap\n");
 		return -EINVAL;
@@ -123,8 +113,8 @@ nva3_ram_calc(struct nouveau_fb *pfb, u32 freq)
 	/* lookup memory timings, if bios says they're present */
 	strap = nv_ro08(bios, ramcfg.data + 0x01);
 	if (strap != 0xff) {
-		timing.data = nvbios_timing_entry(bios, strap, &ver,
-						 &timing.size);
+		timing.data = nvbios_timingEe(bios, strap, &ver, &timing.size,
+					     &cnt, &len);
 		if (!timing.data || ver != 0x10 || timing.size < 0x19) {
 			nv_error(pfb, "invalid/missing timing entry\n");
 			return -EINVAL;
diff --git a/drivers/gpu/drm/nouveau/core/subdev/fb/ramnvc0.c b/drivers/gpu/drm/nouveau/core/subdev/fb/ramnvc0.c
index f464547c6bab7..0391b824ee767 100644
--- a/drivers/gpu/drm/nouveau/core/subdev/fb/ramnvc0.c
+++ b/drivers/gpu/drm/nouveau/core/subdev/fb/ramnvc0.c
@@ -23,7 +23,6 @@
  */
 
 #include <subdev/bios.h>
-#include <subdev/bios/bit.h>
 #include <subdev/bios/pll.h>
 #include <subdev/bios/rammap.h>
 #include <subdev/bios/timing.h>
@@ -134,9 +133,7 @@ nvc0_ram_calc(struct nouveau_fb *pfb, u32 freq)
 	struct nouveau_bios *bios = nouveau_bios(pfb);
 	struct nvc0_ram *ram = (void *)pfb->ram;
 	struct nvc0_ramfuc *fuc = &ram->fuc;
-	struct bit_entry M;
-	u8  ver, cnt, strap;
-	u32 data;
+	u8  ver, cnt, len, strap;
 	struct {
 		u32 data;
 		u8  size;
@@ -147,24 +144,15 @@ nvc0_ram_calc(struct nouveau_fb *pfb, u32 freq)
 	int ret;
 
 	/* lookup memory config data relevant to the target frequency */
-	rammap.data = nvbios_rammap_match(bios, freq / 1000, &ver, &rammap.size,
-					 &cnt, &ramcfg.size);
+	rammap.data = nvbios_rammapEm(bios, freq / 1000, &ver, &rammap.size,
+				     &cnt, &ramcfg.size);
 	if (!rammap.data || ver != 0x10 || rammap.size < 0x0e) {
 		nv_error(pfb, "invalid/missing rammap entry\n");
 		return -EINVAL;
 	}
 
 	/* locate specific data set for the attached memory */
-	if (bit_entry(bios, 'M', &M) || M.version != 2 || M.length < 3) {
-		nv_error(pfb, "invalid/missing memory table\n");
-		return -EINVAL;
-	}
-
-	strap = (nv_rd32(pfb, 0x101000) & 0x0000003c) >> 2;
-	data = nv_ro16(bios, M.offset + 1);
-	if (data)
-		strap = nv_ro08(bios, data + strap);
-
+	strap = nvbios_ramcfg_index(bios);
 	if (strap >= cnt) {
 		nv_error(pfb, "invalid ramcfg strap\n");
 		return -EINVAL;
@@ -179,8 +167,8 @@ nvc0_ram_calc(struct nouveau_fb *pfb, u32 freq)
 	/* lookup memory timings, if bios says they're present */
 	strap = nv_ro08(bios, ramcfg.data + 0x01);
 	if (strap != 0xff) {
-		timing.data = nvbios_timing_entry(bios, strap, &ver,
-						 &timing.size);
+		timing.data = nvbios_timingEe(bios, strap, &ver, &timing.size,
+					     &cnt, &len);
 		if (!timing.data || ver != 0x10 || timing.size < 0x19) {
 			nv_error(pfb, "invalid/missing timing entry\n");
 			return -EINVAL;
diff --git a/drivers/gpu/drm/nouveau/core/subdev/fb/ramnve0.c b/drivers/gpu/drm/nouveau/core/subdev/fb/ramnve0.c
index bc86cfd084f66..3257c522a0219 100644
--- a/drivers/gpu/drm/nouveau/core/subdev/fb/ramnve0.c
+++ b/drivers/gpu/drm/nouveau/core/subdev/fb/ramnve0.c
@@ -25,7 +25,6 @@
 #include <subdev/gpio.h>
 
 #include <subdev/bios.h>
-#include <subdev/bios/bit.h>
 #include <subdev/bios/pll.h>
 #include <subdev/bios/init.h>
 #include <subdev/bios/rammap.h>
@@ -42,6 +41,14 @@
 
 #include "ramfuc.h"
 
+/* binary driver only executes this path if the condition (a) is true
+ * for any configuration (combination of rammap+ramcfg+timing) that
+ * can be reached on a given card.  for now, we will execute the branch
+ * unconditionally in the hope that a "false everywhere" in the bios
+ * tables doesn't actually mean "don't touch this".
+ */
+#define NOTE00(a) 1
+
 struct nve0_ramfuc {
 	struct ramfuc base;
 
@@ -104,7 +111,9 @@ struct nve0_ramfuc {
 	struct ramfuc_reg r_mr[16]; /* MR0 - MR8, MR15 */
 
 	struct ramfuc_reg r_0x62c000;
+
 	struct ramfuc_reg r_0x10f200;
+
 	struct ramfuc_reg r_0x10f210;
 	struct ramfuc_reg r_0x10f310;
 	struct ramfuc_reg r_0x10f314;
@@ -118,12 +127,17 @@ struct nve0_ramfuc {
 	struct ramfuc_reg r_0x10f65c;
 	struct ramfuc_reg r_0x10f6bc;
 	struct ramfuc_reg r_0x100710;
-	struct ramfuc_reg r_0x10f750;
+	struct ramfuc_reg r_0x100750;
 };
 
 struct nve0_ram {
 	struct nouveau_ram base;
 	struct nve0_ramfuc fuc;
+
+	u32 parts;
+	u32 pmask;
+	u32 pnuts;
+
 	int from;
 	int mode;
 	int N1, fN1, M1, P1;
@@ -134,17 +148,17 @@ struct nve0_ram {
  * GDDR5
  ******************************************************************************/
 static void
-train(struct nve0_ramfuc *fuc, u32 magic)
+nve0_ram_train(struct nve0_ramfuc *fuc, u32 mask, u32 data)
 {
 	struct nve0_ram *ram = container_of(fuc, typeof(*ram), fuc);
-	struct nouveau_fb *pfb = nouveau_fb(ram);
-	const int mc = nv_rd32(pfb, 0x02243c);
-	int i;
-
-	ram_mask(fuc, 0x10f910, 0xbc0e0000, magic);
-	ram_mask(fuc, 0x10f914, 0xbc0e0000, magic);
-	for (i = 0; i < mc; i++) {
-		const u32 addr = 0x110974 + (i * 0x1000);
+	u32 addr = 0x110974, i;
+
+	ram_mask(fuc, 0x10f910, mask, data);
+	ram_mask(fuc, 0x10f914, mask, data);
+
+	for (i = 0; (data & 0x80000000) && i < ram->parts; addr += 0x1000, i++) {
+		if (ram->pmask & (1 << i))
+			continue;
 		ram_wait(fuc, addr, 0x0000000f, 0x00000000, 500000);
 	}
 }
@@ -199,12 +213,12 @@ r1373f4_init(struct nve0_ramfuc *fuc)
 }
 
 static void
-r1373f4_fini(struct nve0_ramfuc *fuc, u32 ramcfg)
+r1373f4_fini(struct nve0_ramfuc *fuc)
 {
 	struct nve0_ram *ram = container_of(fuc, typeof(*ram), fuc);
-	struct nouveau_bios *bios = nouveau_bios(ram);
-	u8 v0 = (nv_ro08(bios, ramcfg + 0x03) & 0xc0) >> 6;
-	u8 v1 = (nv_ro08(bios, ramcfg + 0x03) & 0x30) >> 4;
+	struct nouveau_ram_data *next = ram->base.next;
+	u8 v0 = next->bios.ramcfg_11_03_c0;
+	u8 v1 = next->bios.ramcfg_11_03_30;
 	u32 tmp;
 
 	tmp = ram_rd32(fuc, 0x1373ec) & ~0x00030000;
@@ -220,25 +234,46 @@ r1373f4_fini(struct nve0_ramfuc *fuc, u32 ramcfg)
 	ram_mask(fuc, 0x10f800, 0x00000030, (v0 ^ v1) << 4);
 }
 
+static void
+nve0_ram_nuts(struct nve0_ram *ram, struct ramfuc_reg *reg,
+	      u32 _mask, u32 _data, u32 _copy)
+{
+	struct nve0_fb_priv *priv = (void *)nouveau_fb(ram);
+	struct ramfuc *fuc = &ram->fuc.base;
+	u32 addr = 0x110000 + (reg->addr[0] & 0xfff);
+	u32 mask = _mask | _copy;
+	u32 data = (_data & _mask) | (reg->data & _copy);
+	u32 i;
+
+	for (i = 0; i < 16; i++, addr += 0x1000) {
+		if (ram->pnuts & (1 << i)) {
+			u32 prev = nv_rd32(priv, addr);
+			u32 next = (prev & ~mask) | data;
+			nouveau_memx_wr32(fuc->memx, addr, next);
+		}
+	}
+}
+#define ram_nuts(s,r,m,d,c)                                                    \
+	nve0_ram_nuts((s), &(s)->fuc.r_##r, (m), (d), (c))
+
 static int
 nve0_ram_calc_gddr5(struct nouveau_fb *pfb, u32 freq)
 {
-	struct nouveau_bios *bios = nouveau_bios(pfb);
 	struct nve0_ram *ram = (void *)pfb->ram;
 	struct nve0_ramfuc *fuc = &ram->fuc;
-	const u32 rammap = ram->base.rammap.data;
-	const u32 ramcfg = ram->base.ramcfg.data;
-	const u32 timing = ram->base.timing.data;
-	int vc = !(nv_ro08(bios, ramcfg + 0x02) & 0x08);
-	int mv = 1; /*XXX*/
+	struct nouveau_ram_data *next = ram->base.next;
+	int vc = !(next->bios.ramcfg_11_02_08);
+	int mv = !(next->bios.ramcfg_11_02_04);
 	u32 mask, data;
 
 	ram_mask(fuc, 0x10f808, 0x40000000, 0x40000000);
 	ram_wr32(fuc, 0x62c000, 0x0f0f0000);
 
 	/* MR1: turn termination on early, for some reason.. */
-	if ((ram->base.mr[1] & 0x03c) != 0x030)
+	if ((ram->base.mr[1] & 0x03c) != 0x030) {
 		ram_mask(fuc, mr[1], 0x03c, ram->base.mr[1] & 0x03c);
+		ram_nuts(ram, mr[1], 0x03c, ram->base.mr1_nuts & 0x03c, 0x000);
+	}
 
 	if (vc == 1 && ram_have(fuc, gpio2E)) {
 		u32 temp  = ram_mask(fuc, gpio2E, 0x3000, fuc->r_func2E[1]);
@@ -250,8 +285,7 @@ nve0_ram_calc_gddr5(struct nouveau_fb *pfb, u32 freq)
 
 	ram_mask(fuc, 0x10f200, 0x00000800, 0x00000000);
 
-	ram_mask(fuc, 0x10f914, 0x01020000, 0x000c0000);
-	ram_mask(fuc, 0x10f910, 0x01020000, 0x000c0000);
+	nve0_ram_train(fuc, 0x01020000, 0x000c0000);
 
 	ram_wr32(fuc, 0x10f210, 0x00000000); /* REFRESH_AUTO = 0 */
 	ram_nsec(fuc, 1000);
@@ -280,28 +314,28 @@ nve0_ram_calc_gddr5(struct nouveau_fb *pfb, u32 freq)
 
 	if (1) {
 		data |= 0x800807e0;
-		switch (nv_ro08(bios, ramcfg + 0x03) & 0xc0) {
-		case 0xc0: data &= ~0x00000040; break;
-		case 0x80: data &= ~0x00000100; break;
-		case 0x40: data &= ~0x80000000; break;
-		case 0x00: data &= ~0x00000400; break;
+		switch (next->bios.ramcfg_11_03_c0) {
+		case 3: data &= ~0x00000040; break;
+		case 2: data &= ~0x00000100; break;
+		case 1: data &= ~0x80000000; break;
+		case 0: data &= ~0x00000400; break;
 		}
 
-		switch (nv_ro08(bios, ramcfg + 0x03) & 0x30) {
-		case 0x30: data &= ~0x00000020; break;
-		case 0x20: data &= ~0x00000080; break;
-		case 0x10: data &= ~0x00080000; break;
-		case 0x00: data &= ~0x00000200; break;
+		switch (next->bios.ramcfg_11_03_30) {
+		case 3: data &= ~0x00000020; break;
+		case 2: data &= ~0x00000080; break;
+		case 1: data &= ~0x00080000; break;
+		case 0: data &= ~0x00000200; break;
 		}
 	}
 
-	if (nv_ro08(bios, ramcfg + 0x02) & 0x80)
+	if (next->bios.ramcfg_11_02_80)
 		mask |= 0x03000000;
-	if (nv_ro08(bios, ramcfg + 0x02) & 0x40)
+	if (next->bios.ramcfg_11_02_40)
 		mask |= 0x00002000;
-	if (nv_ro08(bios, ramcfg + 0x07) & 0x10)
+	if (next->bios.ramcfg_11_07_10)
 		mask |= 0x00004000;
-	if (nv_ro08(bios, ramcfg + 0x07) & 0x08)
+	if (next->bios.ramcfg_11_07_08)
 		mask |= 0x00000003;
 	else {
 		mask |= 0x34000000;
@@ -314,18 +348,18 @@ nve0_ram_calc_gddr5(struct nouveau_fb *pfb, u32 freq)
 
 	if (ram->from == 2 && ram->mode != 2) {
 		ram_mask(fuc, 0x10f808, 0x00080000, 0x00000000);
-		ram_mask(fuc, 0x10f200, 0x00008000, 0x00008000);
+		ram_mask(fuc, 0x10f200, 0x18008000, 0x00008000);
 		ram_mask(fuc, 0x10f800, 0x00000000, 0x00000004);
 		ram_mask(fuc, 0x10f830, 0x00008000, 0x01040010);
 		ram_mask(fuc, 0x10f830, 0x01000000, 0x00000000);
 		r1373f4_init(fuc);
 		ram_mask(fuc, 0x1373f0, 0x00000002, 0x00000001);
-		r1373f4_fini(fuc, ramcfg);
+		r1373f4_fini(fuc);
 		ram_mask(fuc, 0x10f830, 0x00c00000, 0x00240001);
 	} else
 	if (ram->from != 2 && ram->mode != 2) {
 		r1373f4_init(fuc);
-		r1373f4_fini(fuc, ramcfg);
+		r1373f4_fini(fuc);
 	}
 
 	if (ram_have(fuc, gpioMV)) {
@@ -336,49 +370,54 @@ nve0_ram_calc_gddr5(struct nouveau_fb *pfb, u32 freq)
 		}
 	}
 
-	if ( (nv_ro08(bios, ramcfg + 0x02) & 0x40) ||
-	     (nv_ro08(bios, ramcfg + 0x07) & 0x10)) {
+	if ( (next->bios.ramcfg_11_02_40) ||
+	     (next->bios.ramcfg_11_07_10)) {
 		ram_mask(fuc, 0x132040, 0x00010000, 0x00010000);
 		ram_nsec(fuc, 20000);
 	}
 
 	if (ram->from != 2 && ram->mode == 2) {
+		if (0 /*XXX: Titan */)
+			ram_mask(fuc, 0x10f200, 0x18000000, 0x18000000);
 		ram_mask(fuc, 0x10f800, 0x00000004, 0x00000000);
 		ram_mask(fuc, 0x1373f0, 0x00000000, 0x00000002);
 		ram_mask(fuc, 0x10f830, 0x00800001, 0x00408010);
 		r1373f4_init(fuc);
-		r1373f4_fini(fuc, ramcfg);
+		r1373f4_fini(fuc);
 		ram_mask(fuc, 0x10f808, 0x00000000, 0x00080000);
 		ram_mask(fuc, 0x10f200, 0x00808000, 0x00800000);
 	} else
 	if (ram->from == 2 && ram->mode == 2) {
 		ram_mask(fuc, 0x10f800, 0x00000004, 0x00000000);
 		r1373f4_init(fuc);
-		r1373f4_fini(fuc, ramcfg);
+		r1373f4_fini(fuc);
 	}
 
 	if (ram->mode != 2) /*XXX*/ {
-		if (nv_ro08(bios, ramcfg + 0x07) & 0x40)
+		if (next->bios.ramcfg_11_07_40)
 			ram_mask(fuc, 0x10f670, 0x80000000, 0x80000000);
 	}
 
-	data = (nv_ro08(bios, rammap + 0x11) & 0x0c) >> 2;
-	ram_wr32(fuc, 0x10f65c, 0x00000011 * data);
-	ram_wr32(fuc, 0x10f6b8, 0x01010101 * nv_ro08(bios, ramcfg + 0x09));
-	ram_wr32(fuc, 0x10f6bc, 0x01010101 * nv_ro08(bios, ramcfg + 0x09));
+	ram_wr32(fuc, 0x10f65c, 0x00000011 * next->bios.rammap_11_11_0c);
+	ram_wr32(fuc, 0x10f6b8, 0x01010101 * next->bios.ramcfg_11_09);
+	ram_wr32(fuc, 0x10f6bc, 0x01010101 * next->bios.ramcfg_11_09);
 
-	data = nv_ro08(bios, ramcfg + 0x04);
-	if (!(nv_ro08(bios, ramcfg + 0x07) & 0x08)) {
-		ram_wr32(fuc, 0x10f698, 0x01010101 * data);
-		ram_wr32(fuc, 0x10f69c, 0x01010101 * data);
+	if (!next->bios.ramcfg_11_07_08 && !next->bios.ramcfg_11_07_04) {
+		ram_wr32(fuc, 0x10f698, 0x01010101 * next->bios.ramcfg_11_04);
+		ram_wr32(fuc, 0x10f69c, 0x01010101 * next->bios.ramcfg_11_04);
+	} else
+	if (!next->bios.ramcfg_11_07_08) {
+		ram_wr32(fuc, 0x10f698, 0x00000000);
+		ram_wr32(fuc, 0x10f69c, 0x00000000);
 	}
 
 	if (ram->mode != 2) {
-		u32 temp = ram_rd32(fuc, 0x10f694) & ~0xff00ff00;
-		ram_wr32(fuc, 0x10f694, temp | (0x01000100 * data));
+		u32 data = 0x01000100 * next->bios.ramcfg_11_04;
+		ram_nuke(fuc, 0x10f694);
+		ram_mask(fuc, 0x10f694, 0xff00ff00, data);
 	}
 
-	if (ram->mode == 2 && (nv_ro08(bios, ramcfg + 0x08) & 0x10))
+	if (ram->mode == 2 && (next->bios.ramcfg_11_08_10))
 		data = 0x00000080;
 	else
 		data = 0x00000000;
@@ -386,19 +425,19 @@ nve0_ram_calc_gddr5(struct nouveau_fb *pfb, u32 freq)
 
 	mask = 0x00070000;
 	data = 0x00000000;
-	if (!(nv_ro08(bios, ramcfg + 0x02) & 0x80))
+	if (!(next->bios.ramcfg_11_02_80))
 		data |= 0x03000000;
-	if (!(nv_ro08(bios, ramcfg + 0x02) & 0x40))
+	if (!(next->bios.ramcfg_11_02_40))
 		data |= 0x00002000;
-	if (!(nv_ro08(bios, ramcfg + 0x07) & 0x10))
+	if (!(next->bios.ramcfg_11_07_10))
 		data |= 0x00004000;
-	if (!(nv_ro08(bios, ramcfg + 0x07) & 0x08))
+	if (!(next->bios.ramcfg_11_07_08))
 		data |= 0x00000003;
 	else
 		data |= 0x74000000;
 	ram_mask(fuc, 0x10f824, mask, data);
 
-	if (nv_ro08(bios, ramcfg + 0x01) & 0x08)
+	if (next->bios.ramcfg_11_01_08)
 		data = 0x00000000;
 	else
 		data = 0x00001000;
@@ -409,61 +448,90 @@ nve0_ram_calc_gddr5(struct nouveau_fb *pfb, u32 freq)
 		ram_mask(fuc, 0x10f670, 0x80000000, 0x00000000);
 	}
 
-	if (nv_ro08(bios, ramcfg + 0x08) & 0x01)
+	if (next->bios.ramcfg_11_08_01)
 		data = 0x00100000;
 	else
 		data = 0x00000000;
 	ram_mask(fuc, 0x10f82c, 0x00100000, data);
 
 	data = 0x00000000;
-	if (nv_ro08(bios, ramcfg + 0x08) & 0x08)
+	if (next->bios.ramcfg_11_08_08)
 		data |= 0x00002000;
-	if (nv_ro08(bios, ramcfg + 0x08) & 0x04)
+	if (next->bios.ramcfg_11_08_04)
 		data |= 0x00001000;
-	if (nv_ro08(bios, ramcfg + 0x08) & 0x02)
+	if (next->bios.ramcfg_11_08_02)
 		data |= 0x00004000;
 	ram_mask(fuc, 0x10f830, 0x00007000, data);
 
 	/* PFB timing */
-	ram_mask(fuc, 0x10f248, 0xffffffff, nv_ro32(bios, timing + 0x28));
-	ram_mask(fuc, 0x10f290, 0xffffffff, nv_ro32(bios, timing + 0x00));
-	ram_mask(fuc, 0x10f294, 0xffffffff, nv_ro32(bios, timing + 0x04));
-	ram_mask(fuc, 0x10f298, 0xffffffff, nv_ro32(bios, timing + 0x08));
-	ram_mask(fuc, 0x10f29c, 0xffffffff, nv_ro32(bios, timing + 0x0c));
-	ram_mask(fuc, 0x10f2a0, 0xffffffff, nv_ro32(bios, timing + 0x10));
-	ram_mask(fuc, 0x10f2a4, 0xffffffff, nv_ro32(bios, timing + 0x14));
-	ram_mask(fuc, 0x10f2a8, 0xffffffff, nv_ro32(bios, timing + 0x18));
-	ram_mask(fuc, 0x10f2ac, 0xffffffff, nv_ro32(bios, timing + 0x1c));
-	ram_mask(fuc, 0x10f2cc, 0xffffffff, nv_ro32(bios, timing + 0x20));
-	ram_mask(fuc, 0x10f2e8, 0xffffffff, nv_ro32(bios, timing + 0x24));
-
-	data = (nv_ro08(bios, ramcfg + 0x02) & 0x03) << 8;
-	if (nv_ro08(bios, ramcfg + 0x01) & 0x10)
-		data |= 0x70000000;
-	ram_mask(fuc, 0x10f604, 0x70000300, data);
-
-	data = (nv_ro08(bios, timing + 0x30) & 0x07) << 28;
-	if (nv_ro08(bios, ramcfg + 0x01) & 0x01)
-		data |= 0x00000100;
-	ram_mask(fuc, 0x10f614, 0x70000000, data);
-
-	data = (nv_ro08(bios, timing + 0x30) & 0x07) << 28;
-	if (nv_ro08(bios, ramcfg + 0x01) & 0x02)
-		data |= 0x00000100;
-	ram_mask(fuc, 0x10f610, 0x70000000, data);
+	ram_mask(fuc, 0x10f248, 0xffffffff, next->bios.timing[10]);
+	ram_mask(fuc, 0x10f290, 0xffffffff, next->bios.timing[0]);
+	ram_mask(fuc, 0x10f294, 0xffffffff, next->bios.timing[1]);
+	ram_mask(fuc, 0x10f298, 0xffffffff, next->bios.timing[2]);
+	ram_mask(fuc, 0x10f29c, 0xffffffff, next->bios.timing[3]);
+	ram_mask(fuc, 0x10f2a0, 0xffffffff, next->bios.timing[4]);
+	ram_mask(fuc, 0x10f2a4, 0xffffffff, next->bios.timing[5]);
+	ram_mask(fuc, 0x10f2a8, 0xffffffff, next->bios.timing[6]);
+	ram_mask(fuc, 0x10f2ac, 0xffffffff, next->bios.timing[7]);
+	ram_mask(fuc, 0x10f2cc, 0xffffffff, next->bios.timing[8]);
+	ram_mask(fuc, 0x10f2e8, 0xffffffff, next->bios.timing[9]);
+
+	data = mask = 0x00000000;
+	if (NOTE00(ramcfg_08_20)) {
+		if (next->bios.ramcfg_11_08_20)
+			data |= 0x01000000;
+		mask |= 0x01000000;
+	}
+	ram_mask(fuc, 0x10f200, mask, data);
+
+	data = mask = 0x00000000;
+	if (NOTE00(ramcfg_02_03 != 0)) {
+		data |= (next->bios.ramcfg_11_02_03) << 8;
+		mask |= 0x00000300;
+	}
+	if (NOTE00(ramcfg_01_10)) {
+		if (next->bios.ramcfg_11_01_10)
+			data |= 0x70000000;
+		mask |= 0x70000000;
+	}
+	ram_mask(fuc, 0x10f604, mask, data);
+
+	data = mask = 0x00000000;
+	if (NOTE00(timing_30_07 != 0)) {
+		data |= (next->bios.timing_20_30_07) << 28;
+		mask |= 0x70000000;
+	}
+	if (NOTE00(ramcfg_01_01)) {
+		if (next->bios.ramcfg_11_01_01)
+			data |= 0x00000100;
+		mask |= 0x00000100;
+	}
+	ram_mask(fuc, 0x10f614, mask, data);
+
+	data = mask = 0x00000000;
+	if (NOTE00(timing_30_07 != 0)) {
+		data |= (next->bios.timing_20_30_07) << 28;
+		mask |= 0x70000000;
+	}
+	if (NOTE00(ramcfg_01_02)) {
+		if (next->bios.ramcfg_11_01_02)
+			data |= 0x00000100;
+		mask |= 0x00000100;
+	}
+	ram_mask(fuc, 0x10f610, mask, data);
 
 	mask = 0x33f00000;
 	data = 0x00000000;
-	if (!(nv_ro08(bios, ramcfg + 0x01) & 0x04))
+	if (!(next->bios.ramcfg_11_01_04))
 		data |= 0x20200000;
-	if (!(nv_ro08(bios, ramcfg + 0x07) & 0x80))
+	if (!(next->bios.ramcfg_11_07_80))
 		data |= 0x12800000;
 	/*XXX: see note above about there probably being some condition
 	 *     for the 10f824 stuff that uses ramcfg 3...
 	 */
-	if ( (nv_ro08(bios, ramcfg + 0x03) & 0xf0)) {
-		if (nv_ro08(bios, rammap + 0x08) & 0x0c) {
-			if (!(nv_ro08(bios, ramcfg + 0x07) & 0x80))
+	if ( (next->bios.ramcfg_11_03_f0)) {
+		if (next->bios.rammap_11_08_0c) {
+			if (!(next->bios.ramcfg_11_07_80))
 				mask |= 0x00000020;
 			else
 				data |= 0x00000020;
@@ -476,49 +544,53 @@ nve0_ram_calc_gddr5(struct nouveau_fb *pfb, u32 freq)
 
 	ram_mask(fuc, 0x10f808, mask, data);
 
-	data = nv_ro08(bios, ramcfg + 0x03) & 0x0f;
-	ram_wr32(fuc, 0x10f870, 0x11111111 * data);
+	ram_wr32(fuc, 0x10f870, 0x11111111 * next->bios.ramcfg_11_03_0f);
 
-	data = nv_ro08(bios, ramcfg + 0x02) & 0x03;
-	if (nv_ro08(bios, ramcfg + 0x01) & 0x10)
-		data |= 0x00000004;
-	if ((nv_rd32(bios, 0x100770) & 0x00000004) != (data & 0x00000004)) {
-		ram_wr32(fuc, 0x10f750, 0x04000009);
+	data = mask = 0x00000000;
+	if (NOTE00(ramcfg_02_03 != 0)) {
+		data |= next->bios.ramcfg_11_02_03;
+		mask |= 0x00000003;
+	}
+	if (NOTE00(ramcfg_01_10)) {
+		if (next->bios.ramcfg_11_01_10)
+			data |= 0x00000004;
+		mask |= 0x00000004;
+	}
+
+	if ((ram_mask(fuc, 0x100770, mask, data) & mask & 4) != (data & 4)) {
+		ram_mask(fuc, 0x100750, 0x00000008, 0x00000008);
 		ram_wr32(fuc, 0x100710, 0x00000000);
 		ram_wait(fuc, 0x100710, 0x80000000, 0x80000000, 200000);
 	}
-	ram_mask(fuc, 0x100770, 0x00000007, data);
 
-	data = (nv_ro08(bios, timing + 0x30) & 0x07) << 8;
-	if (nv_ro08(bios, ramcfg + 0x01) & 0x01)
+	data = (next->bios.timing_20_30_07) << 8;
+	if (next->bios.ramcfg_11_01_01)
 		data |= 0x80000000;
 	ram_mask(fuc, 0x100778, 0x00000700, data);
 
-	data = nv_ro16(bios, timing + 0x2c);
-	ram_mask(fuc, 0x10f250, 0x000003f0, (data & 0x003f) <<  4);
-	ram_mask(fuc, 0x10f24c, 0x7f000000, (data & 0x1fc0) << 18);
-
-	data = nv_ro08(bios, timing + 0x30);
-	ram_mask(fuc, 0x10f224, 0x001f0000, (data & 0xf8) << 13);
+	ram_mask(fuc, 0x10f250, 0x000003f0, next->bios.timing_20_2c_003f << 4);
+	data = (next->bios.timing[10] & 0x7f000000) >> 24;
+	if (data < next->bios.timing_20_2c_1fc0)
+		data = next->bios.timing_20_2c_1fc0;
+	ram_mask(fuc, 0x10f24c, 0x7f000000, data << 24);
+	ram_mask(fuc, 0x10f224, 0x001f0000, next->bios.timing_20_30_f8 << 16);
 
-	data = nv_ro16(bios, timing + 0x31);
-	ram_mask(fuc, 0x10fec4, 0x041e0f07, (data & 0x0800) << 15 |
-					    (data & 0x0780) << 10 |
-					    (data & 0x0078) <<  5 |
-					    (data & 0x0007));
-	ram_mask(fuc, 0x10fec8, 0x00000027, (data & 0x8000) >> 10 |
-					    (data & 0x7000) >> 12);
+	ram_mask(fuc, 0x10fec4, 0x041e0f07, next->bios.timing_20_31_0800 << 26 |
+					    next->bios.timing_20_31_0780 << 17 |
+					    next->bios.timing_20_31_0078 << 8 |
+					    next->bios.timing_20_31_0007);
+	ram_mask(fuc, 0x10fec8, 0x00000027, next->bios.timing_20_31_8000 << 5 |
+					    next->bios.timing_20_31_7000);
 
 	ram_wr32(fuc, 0x10f090, 0x4000007e);
-	ram_nsec(fuc, 1000);
+	ram_nsec(fuc, 2000);
 	ram_wr32(fuc, 0x10f314, 0x00000001); /* PRECHARGE */
 	ram_wr32(fuc, 0x10f310, 0x00000001); /* REFRESH */
-	ram_nsec(fuc, 2000);
 	ram_wr32(fuc, 0x10f210, 0x80000000); /* REFRESH_AUTO = 1 */
 
-	if ((nv_ro08(bios, ramcfg + 0x08) & 0x10) && (ram->mode == 2) /*XXX*/) {
+	if ((next->bios.ramcfg_11_08_10) && (ram->mode == 2) /*XXX*/) {
 		u32 temp = ram_mask(fuc, 0x10f294, 0xff000000, 0x24000000);
-		train(fuc, 0xa4010000); /*XXX*/
+		nve0_ram_train(fuc, 0xbc0e0000, 0xa4010000); /*XXX*/
 		ram_nsec(fuc, 1000);
 		ram_wr32(fuc, 0x10f294, temp);
 	}
@@ -528,7 +600,7 @@ nve0_ram_calc_gddr5(struct nouveau_fb *pfb, u32 freq)
 	ram_mask(fuc, mr[8], 0xfff, ram->base.mr[8]);
 	ram_nsec(fuc, 1000);
 	ram_mask(fuc, mr[1], 0xfff, ram->base.mr[1]);
-	ram_mask(fuc, mr[5], 0xfff, ram->base.mr[5]);
+	ram_mask(fuc, mr[5], 0xfff, ram->base.mr[5] & ~0x004); /* LP3 later */
 	ram_mask(fuc, mr[6], 0xfff, ram->base.mr[6]);
 	ram_mask(fuc, mr[7], 0xfff, ram->base.mr[7]);
 
@@ -544,12 +616,13 @@ nve0_ram_calc_gddr5(struct nouveau_fb *pfb, u32 freq)
 	ram_wr32(fuc, 0x10f318, 0x00000001); /* NOP? */
 	ram_mask(fuc, 0x10f200, 0x80000000, 0x00000000);
 	ram_nsec(fuc, 1000);
+	ram_nuts(ram, 0x10f200, 0x18808800, 0x00000000, 0x18808800);
 
 	data  = ram_rd32(fuc, 0x10f978);
 	data &= ~0x00046144;
 	data |=  0x0000000b;
-	if (!(nv_ro08(bios, ramcfg + 0x07) & 0x08)) {
-		if (!(nv_ro08(bios, ramcfg + 0x07) & 0x04))
+	if (!(next->bios.ramcfg_11_07_08)) {
+		if (!(next->bios.ramcfg_11_07_04))
 			data |= 0x0000200c;
 		else
 			data |= 0x00000000;
@@ -563,44 +636,43 @@ nve0_ram_calc_gddr5(struct nouveau_fb *pfb, u32 freq)
 		ram_wr32(fuc, 0x10f830, data);
 	}
 
-	if (!(nv_ro08(bios, ramcfg + 0x07) & 0x08)) {
+	if (!(next->bios.ramcfg_11_07_08)) {
 		data = 0x88020000;
-		if ( (nv_ro08(bios, ramcfg + 0x07) & 0x04))
+		if ( (next->bios.ramcfg_11_07_04))
 			data |= 0x10000000;
-		if (!(nv_ro08(bios, rammap + 0x08) & 0x10))
+		if (!(next->bios.rammap_11_08_10))
 			data |= 0x00080000;
 	} else {
 		data = 0xa40e0000;
 	}
-	train(fuc, data);
-	ram_nsec(fuc, 1000);
+	nve0_ram_train(fuc, 0xbc0f0000, data);
+	if (1) /* XXX: not always? */
+		ram_nsec(fuc, 1000);
 
 	if (ram->mode == 2) { /*XXX*/
 		ram_mask(fuc, 0x10f800, 0x00000004, 0x00000004);
 	}
 
-	/* MR5: (re)enable LP3 if necessary
-	 * XXX: need to find the switch, keeping off for now
-	 */
-	ram_mask(fuc, mr[5], 0x00000004, 0x00000000);
+	/* LP3 */
+	if (ram_mask(fuc, mr[5], 0x004, ram->base.mr[5]) != ram->base.mr[5])
+		ram_nsec(fuc, 1000);
 
 	if (ram->mode != 2) {
 		ram_mask(fuc, 0x10f830, 0x01000000, 0x01000000);
 		ram_mask(fuc, 0x10f830, 0x01000000, 0x00000000);
 	}
 
-	if (nv_ro08(bios, ramcfg + 0x07) & 0x02) {
-		ram_mask(fuc, 0x10f910, 0x80020000, 0x01000000);
-		ram_mask(fuc, 0x10f914, 0x80020000, 0x01000000);
-	}
+	if (next->bios.ramcfg_11_07_02)
+		nve0_ram_train(fuc, 0x80020000, 0x01000000);
 
 	ram_wr32(fuc, 0x62c000, 0x0f0f0f00);
 
-	if (nv_ro08(bios, rammap + 0x08) & 0x01)
+	if (next->bios.rammap_11_08_01)
 		data = 0x00000800;
 	else
 		data = 0x00000000;
 	ram_mask(fuc, 0x10f200, 0x00000800, data);
+	ram_nuts(ram, 0x10f200, 0x18808800, data, 0x18808800);
 	return 0;
 }
 
@@ -611,17 +683,14 @@ nve0_ram_calc_gddr5(struct nouveau_fb *pfb, u32 freq)
 static int
 nve0_ram_calc_sddr3(struct nouveau_fb *pfb, u32 freq)
 {
-	struct nouveau_bios *bios = nouveau_bios(pfb);
 	struct nve0_ram *ram = (void *)pfb->ram;
 	struct nve0_ramfuc *fuc = &ram->fuc;
 	const u32 rcoef = ((  ram->P1 << 16) | (ram->N1 << 8) | ram->M1);
 	const u32 runk0 = ram->fN1 << 16;
 	const u32 runk1 = ram->fN1;
-	const u32 rammap = ram->base.rammap.data;
-	const u32 ramcfg = ram->base.ramcfg.data;
-	const u32 timing = ram->base.timing.data;
-	int vc = !(nv_ro08(bios, ramcfg + 0x02) & 0x08);
-	int mv = 1; /*XXX*/
+	struct nouveau_ram_data *next = ram->base.next;
+	int vc = !(next->bios.ramcfg_11_02_08);
+	int mv = !(next->bios.ramcfg_11_02_04);
 	u32 mask, data;
 
 	ram_mask(fuc, 0x10f808, 0x40000000, 0x40000000);
@@ -636,7 +705,7 @@ nve0_ram_calc_sddr3(struct nouveau_fb *pfb, u32 freq)
 	}
 
 	ram_mask(fuc, 0x10f200, 0x00000800, 0x00000000);
-	if ((nv_ro08(bios, ramcfg + 0x03) & 0xf0))
+	if ((next->bios.ramcfg_11_03_f0))
 		ram_mask(fuc, 0x10f808, 0x04000000, 0x04000000);
 
 	ram_wr32(fuc, 0x10f314, 0x00000001); /* PRECHARGE */
@@ -661,28 +730,28 @@ nve0_ram_calc_sddr3(struct nouveau_fb *pfb, u32 freq)
 	if (1) {
 		mask |= 0x800807e0;
 		data |= 0x800807e0;
-		switch (nv_ro08(bios, ramcfg + 0x03) & 0xc0) {
-		case 0xc0: data &= ~0x00000040; break;
-		case 0x80: data &= ~0x00000100; break;
-		case 0x40: data &= ~0x80000000; break;
-		case 0x00: data &= ~0x00000400; break;
+		switch (next->bios.ramcfg_11_03_c0) {
+		case 3: data &= ~0x00000040; break;
+		case 2: data &= ~0x00000100; break;
+		case 1: data &= ~0x80000000; break;
+		case 0: data &= ~0x00000400; break;
 		}
 
-		switch (nv_ro08(bios, ramcfg + 0x03) & 0x30) {
-		case 0x30: data &= ~0x00000020; break;
-		case 0x20: data &= ~0x00000080; break;
-		case 0x10: data &= ~0x00080000; break;
-		case 0x00: data &= ~0x00000200; break;
+		switch (next->bios.ramcfg_11_03_30) {
+		case 3: data &= ~0x00000020; break;
+		case 2: data &= ~0x00000080; break;
+		case 1: data &= ~0x00080000; break;
+		case 0: data &= ~0x00000200; break;
 		}
 	}
 
-	if (nv_ro08(bios, ramcfg + 0x02) & 0x80)
+	if (next->bios.ramcfg_11_02_80)
 		mask |= 0x03000000;
-	if (nv_ro08(bios, ramcfg + 0x02) & 0x40)
+	if (next->bios.ramcfg_11_02_40)
 		mask |= 0x00002000;
-	if (nv_ro08(bios, ramcfg + 0x07) & 0x10)
+	if (next->bios.ramcfg_11_07_10)
 		mask |= 0x00004000;
-	if (nv_ro08(bios, ramcfg + 0x07) & 0x08)
+	if (next->bios.ramcfg_11_07_08)
 		mask |= 0x00000003;
 	else
 		mask |= 0x14000000;
@@ -692,7 +761,7 @@ nve0_ram_calc_sddr3(struct nouveau_fb *pfb, u32 freq)
 
 	ram_mask(fuc, 0x1373f4, 0x00000000, 0x00010010);
 	data  = ram_rd32(fuc, 0x1373ec) & ~0x00030000;
-	data |= (nv_ro08(bios, ramcfg + 0x03) & 0x30) << 12;
+	data |= (next->bios.ramcfg_11_03_30) << 12;
 	ram_wr32(fuc, 0x1373ec, data);
 	ram_mask(fuc, 0x1373f4, 0x00000003, 0x00000000);
 	ram_mask(fuc, 0x1373f4, 0x00000010, 0x00000000);
@@ -724,68 +793,67 @@ nve0_ram_calc_sddr3(struct nouveau_fb *pfb, u32 freq)
 		}
 	}
 
-	if ( (nv_ro08(bios, ramcfg + 0x02) & 0x40) ||
-	     (nv_ro08(bios, ramcfg + 0x07) & 0x10)) {
+	if ( (next->bios.ramcfg_11_02_40) ||
+	     (next->bios.ramcfg_11_07_10)) {
 		ram_mask(fuc, 0x132040, 0x00010000, 0x00010000);
 		ram_nsec(fuc, 20000);
 	}
 
 	if (ram->mode != 2) /*XXX*/ {
-		if (nv_ro08(bios, ramcfg + 0x07) & 0x40)
+		if (next->bios.ramcfg_11_07_40)
 			ram_mask(fuc, 0x10f670, 0x80000000, 0x80000000);
 	}
 
-	data = (nv_ro08(bios, rammap + 0x11) & 0x0c) >> 2;
-	ram_wr32(fuc, 0x10f65c, 0x00000011 * data);
-	ram_wr32(fuc, 0x10f6b8, 0x01010101 * nv_ro08(bios, ramcfg + 0x09));
-	ram_wr32(fuc, 0x10f6bc, 0x01010101 * nv_ro08(bios, ramcfg + 0x09));
+	ram_wr32(fuc, 0x10f65c, 0x00000011 * next->bios.rammap_11_11_0c);
+	ram_wr32(fuc, 0x10f6b8, 0x01010101 * next->bios.ramcfg_11_09);
+	ram_wr32(fuc, 0x10f6bc, 0x01010101 * next->bios.ramcfg_11_09);
 
 	mask = 0x00010000;
 	data = 0x00000000;
-	if (!(nv_ro08(bios, ramcfg + 0x02) & 0x80))
+	if (!(next->bios.ramcfg_11_02_80))
 		data |= 0x03000000;
-	if (!(nv_ro08(bios, ramcfg + 0x02) & 0x40))
+	if (!(next->bios.ramcfg_11_02_40))
 		data |= 0x00002000;
-	if (!(nv_ro08(bios, ramcfg + 0x07) & 0x10))
+	if (!(next->bios.ramcfg_11_07_10))
 		data |= 0x00004000;
-	if (!(nv_ro08(bios, ramcfg + 0x07) & 0x08))
+	if (!(next->bios.ramcfg_11_07_08))
 		data |= 0x00000003;
 	else
 		data |= 0x14000000;
 	ram_mask(fuc, 0x10f824, mask, data);
 	ram_nsec(fuc, 1000);
 
-	if (nv_ro08(bios, ramcfg + 0x08) & 0x01)
+	if (next->bios.ramcfg_11_08_01)
 		data = 0x00100000;
 	else
 		data = 0x00000000;
 	ram_mask(fuc, 0x10f82c, 0x00100000, data);
 
 	/* PFB timing */
-	ram_mask(fuc, 0x10f248, 0xffffffff, nv_ro32(bios, timing + 0x28));
-	ram_mask(fuc, 0x10f290, 0xffffffff, nv_ro32(bios, timing + 0x00));
-	ram_mask(fuc, 0x10f294, 0xffffffff, nv_ro32(bios, timing + 0x04));
-	ram_mask(fuc, 0x10f298, 0xffffffff, nv_ro32(bios, timing + 0x08));
-	ram_mask(fuc, 0x10f29c, 0xffffffff, nv_ro32(bios, timing + 0x0c));
-	ram_mask(fuc, 0x10f2a0, 0xffffffff, nv_ro32(bios, timing + 0x10));
-	ram_mask(fuc, 0x10f2a4, 0xffffffff, nv_ro32(bios, timing + 0x14));
-	ram_mask(fuc, 0x10f2a8, 0xffffffff, nv_ro32(bios, timing + 0x18));
-	ram_mask(fuc, 0x10f2ac, 0xffffffff, nv_ro32(bios, timing + 0x1c));
-	ram_mask(fuc, 0x10f2cc, 0xffffffff, nv_ro32(bios, timing + 0x20));
-	ram_mask(fuc, 0x10f2e8, 0xffffffff, nv_ro32(bios, timing + 0x24));
+	ram_mask(fuc, 0x10f248, 0xffffffff, next->bios.timing[10]);
+	ram_mask(fuc, 0x10f290, 0xffffffff, next->bios.timing[0]);
+	ram_mask(fuc, 0x10f294, 0xffffffff, next->bios.timing[1]);
+	ram_mask(fuc, 0x10f298, 0xffffffff, next->bios.timing[2]);
+	ram_mask(fuc, 0x10f29c, 0xffffffff, next->bios.timing[3]);
+	ram_mask(fuc, 0x10f2a0, 0xffffffff, next->bios.timing[4]);
+	ram_mask(fuc, 0x10f2a4, 0xffffffff, next->bios.timing[5]);
+	ram_mask(fuc, 0x10f2a8, 0xffffffff, next->bios.timing[6]);
+	ram_mask(fuc, 0x10f2ac, 0xffffffff, next->bios.timing[7]);
+	ram_mask(fuc, 0x10f2cc, 0xffffffff, next->bios.timing[8]);
+	ram_mask(fuc, 0x10f2e8, 0xffffffff, next->bios.timing[9]);
 
 	mask = 0x33f00000;
 	data = 0x00000000;
-	if (!(nv_ro08(bios, ramcfg + 0x01) & 0x04))
+	if (!(next->bios.ramcfg_11_01_04))
 		data |= 0x20200000;
-	if (!(nv_ro08(bios, ramcfg + 0x07) & 0x80))
+	if (!(next->bios.ramcfg_11_07_80))
 		data |= 0x12800000;
 	/*XXX: see note above about there probably being some condition
 	 *     for the 10f824 stuff that uses ramcfg 3...
 	 */
-	if ( (nv_ro08(bios, ramcfg + 0x03) & 0xf0)) {
-		if (nv_ro08(bios, rammap + 0x08) & 0x0c) {
-			if (!(nv_ro08(bios, ramcfg + 0x07) & 0x80))
+	if ( (next->bios.ramcfg_11_03_f0)) {
+		if (next->bios.rammap_11_08_0c) {
+			if (!(next->bios.ramcfg_11_07_80))
 				mask |= 0x00000020;
 			else
 				data |= 0x00000020;
@@ -799,21 +867,16 @@ nve0_ram_calc_sddr3(struct nouveau_fb *pfb, u32 freq)
 
 	ram_mask(fuc, 0x10f808, mask, data);
 
-	data = nv_ro08(bios, ramcfg + 0x03) & 0x0f;
-	ram_wr32(fuc, 0x10f870, 0x11111111 * data);
+	ram_wr32(fuc, 0x10f870, 0x11111111 * next->bios.ramcfg_11_03_0f);
 
-	data = nv_ro16(bios, timing + 0x2c);
-	ram_mask(fuc, 0x10f250, 0x000003f0, (data & 0x003f) <<  4);
+	ram_mask(fuc, 0x10f250, 0x000003f0, next->bios.timing_20_2c_003f << 4);
 
-	if (((nv_ro32(bios, timing + 0x2c) & 0x00001fc0) >>  6) >
-	    ((nv_ro32(bios, timing + 0x28) & 0x7f000000) >> 24))
-		data = (nv_ro32(bios, timing + 0x2c) & 0x00001fc0) >>  6;
-	else
-		data = (nv_ro32(bios, timing + 0x28) & 0x1f000000) >> 24;
+	data = (next->bios.timing[10] & 0x7f000000) >> 24;
+	if (data < next->bios.timing_20_2c_1fc0)
+		data = next->bios.timing_20_2c_1fc0;
 	ram_mask(fuc, 0x10f24c, 0x7f000000, data << 24);
 
-	data = nv_ro08(bios, timing + 0x30);
-	ram_mask(fuc, 0x10f224, 0x001f0000, (data & 0xf8) << 13);
+	ram_mask(fuc, 0x10f224, 0x001f0000, next->bios.timing_20_30_f8);
 
 	ram_wr32(fuc, 0x10f090, 0x4000007f);
 	ram_nsec(fuc, 1000);
@@ -855,7 +918,7 @@ nve0_ram_calc_sddr3(struct nouveau_fb *pfb, u32 freq)
 
 	ram_wr32(fuc, 0x62c000, 0x0f0f0f00);
 
-	if (nv_ro08(bios, rammap + 0x08) & 0x01)
+	if (next->bios.rammap_11_08_01)
 		data = 0x00000800;
 	else
 		data = 0x00000000;
@@ -868,21 +931,18 @@ nve0_ram_calc_sddr3(struct nouveau_fb *pfb, u32 freq)
  ******************************************************************************/
 
 static int
-nve0_ram_calc(struct nouveau_fb *pfb, u32 freq)
+nve0_ram_calc_data(struct nouveau_fb *pfb, u32 freq,
+		   struct nouveau_ram_data *data)
 {
 	struct nouveau_bios *bios = nouveau_bios(pfb);
 	struct nve0_ram *ram = (void *)pfb->ram;
-	struct nve0_ramfuc *fuc = &ram->fuc;
-	struct bit_entry M;
-	int ret, refclk, strap, i;
-	u32 data;
-	u8  cnt;
+	u8 strap, cnt, len;
 
 	/* lookup memory config data relevant to the target frequency */
-	ram->base.rammap.data = nvbios_rammap_match(bios, freq / 1000,
-						   &ram->base.rammap.version,
-						   &ram->base.rammap.size, &cnt,
-						   &ram->base.ramcfg.size);
+	ram->base.rammap.data = nvbios_rammapEp(bios, freq / 1000,
+					       &ram->base.rammap.version,
+					       &ram->base.rammap.size,
+					       &cnt, &len, &data->bios);
 	if (!ram->base.rammap.data || ram->base.rammap.version != 0x11 ||
 	     ram->base.rammap.size < 0x09) {
 		nv_error(pfb, "invalid/missing rammap entry\n");
@@ -890,24 +950,13 @@ nve0_ram_calc(struct nouveau_fb *pfb, u32 freq)
 	}
 
 	/* locate specific data set for the attached memory */
-	if (bit_entry(bios, 'M', &M) || M.version != 2 || M.length < 3) {
-		nv_error(pfb, "invalid/missing memory table\n");
-		return -EINVAL;
-	}
-
-	strap = (nv_rd32(pfb, 0x101000) & 0x0000003c) >> 2;
-	data = nv_ro16(bios, M.offset + 1);
-	if (data)
-		strap = nv_ro08(bios, data + strap);
-
-	if (strap >= cnt) {
-		nv_error(pfb, "invalid ramcfg strap\n");
-		return -EINVAL;
-	}
-
-	ram->base.ramcfg.version = ram->base.rammap.version;
-	ram->base.ramcfg.data = ram->base.rammap.data + ram->base.rammap.size +
-			       (ram->base.ramcfg.size * strap);
+	ram->base.ramcfg.data = nvbios_rammapSp(bios, ram->base.rammap.data,
+						ram->base.rammap.version,
+						ram->base.rammap.size, cnt, len,
+						nvbios_ramcfg_index(bios),
+						&ram->base.ramcfg.version,
+						&ram->base.ramcfg.size,
+						&data->bios);
 	if (!ram->base.ramcfg.data || ram->base.ramcfg.version != 0x11 ||
 	     ram->base.ramcfg.size < 0x08) {
 		nv_error(pfb, "invalid/missing ramcfg entry\n");
@@ -918,9 +967,9 @@ nve0_ram_calc(struct nouveau_fb *pfb, u32 freq)
 	strap = nv_ro08(bios, ram->base.ramcfg.data + 0x00);
 	if (strap != 0xff) {
 		ram->base.timing.data =
-			nvbios_timing_entry(bios, strap,
-					   &ram->base.timing.version,
-					   &ram->base.timing.size);
+			nvbios_timingEp(bios, strap, &ram->base.timing.version,
+				       &ram->base.timing.size, &cnt, &len,
+				       &data->bios);
 		if (!ram->base.timing.data ||
 		     ram->base.timing.version != 0x20 ||
 		     ram->base.timing.size < 0x33) {
@@ -931,11 +980,23 @@ nve0_ram_calc(struct nouveau_fb *pfb, u32 freq)
 		ram->base.timing.data = 0;
 	}
 
+	data->freq = freq;
+	return 0;
+}
+
+static int
+nve0_ram_calc_xits(struct nouveau_fb *pfb, struct nouveau_ram_data *next)
+{
+	struct nve0_ram *ram = (void *)pfb->ram;
+	struct nve0_ramfuc *fuc = &ram->fuc;
+	int refclk, i;
+	int ret;
+
 	ret = ram_init(fuc, pfb);
 	if (ret)
 		return ret;
 
-	ram->mode = (freq > fuc->refpll.vco1.max_freq) ? 2 : 1;
+	ram->mode = (next->freq > fuc->refpll.vco1.max_freq) ? 2 : 1;
 	ram->from = ram_rd32(fuc, 0x1373f4) & 0x0000000f;
 
 	/* XXX: this is *not* what nvidia do.  on fermi nvidia generally
@@ -946,7 +1007,7 @@ nve0_ram_calc(struct nouveau_fb *pfb, u32 freq)
 	 * so far, i've seen very weird values being chosen by nvidia on
 	 * kepler boards, no idea how/why they're chosen.
 	 */
-	refclk = freq;
+	refclk = next->freq;
 	if (ram->mode == 2)
 		refclk = fuc->mempll.refclk;
 
@@ -968,7 +1029,7 @@ nve0_ram_calc(struct nouveau_fb *pfb, u32 freq)
 		fuc->mempll.min_p = 1;
 		fuc->mempll.max_p = 2;
 
-		ret = nva3_pll_calc(nv_subdev(pfb), &fuc->mempll, freq,
+		ret = nva3_pll_calc(nv_subdev(pfb), &fuc->mempll, next->freq,
 				   &ram->N2, NULL, &ram->M2, &ram->P2);
 		if (ret <= 0) {
 			nv_error(pfb, "unable to calc mempll\n");
@@ -980,17 +1041,18 @@ nve0_ram_calc(struct nouveau_fb *pfb, u32 freq)
 		if (ram_have(fuc, mr[i]))
 			ram->base.mr[i] = ram_rd32(fuc, mr[i]);
 	}
+	ram->base.freq = next->freq;
 
 	switch (ram->base.type) {
 	case NV_MEM_TYPE_DDR3:
 		ret = nouveau_sddr3_calc(&ram->base);
 		if (ret == 0)
-			ret = nve0_ram_calc_sddr3(pfb, freq);
+			ret = nve0_ram_calc_sddr3(pfb, next->freq);
 		break;
 	case NV_MEM_TYPE_GDDR5:
-		ret = nouveau_gddr5_calc(&ram->base);
+		ret = nouveau_gddr5_calc(&ram->base, ram->pnuts != 0);
 		if (ret == 0)
-			ret = nve0_ram_calc_gddr5(pfb, freq);
+			ret = nve0_ram_calc_gddr5(pfb, next->freq);
 		break;
 	default:
 		ret = -ENOSYS;
@@ -1000,6 +1062,48 @@ nve0_ram_calc(struct nouveau_fb *pfb, u32 freq)
 	return ret;
 }
 
+static int
+nve0_ram_calc(struct nouveau_fb *pfb, u32 freq)
+{
+	struct nouveau_clock *clk = nouveau_clock(pfb);
+	struct nve0_ram *ram = (void *)pfb->ram;
+	struct nouveau_ram_data *xits = &ram->base.xition;
+	struct nouveau_ram_data *copy;
+	int ret;
+
+	if (ram->base.next == NULL) {
+		ret = nve0_ram_calc_data(pfb, clk->read(clk, nv_clk_src_mem),
+					&ram->base.former);
+		if (ret)
+			return ret;
+
+		ret = nve0_ram_calc_data(pfb, freq, &ram->base.target);
+		if (ret)
+			return ret;
+
+		if (ram->base.target.freq < ram->base.former.freq) {
+			*xits = ram->base.target;
+			copy = &ram->base.former;
+		} else {
+			*xits = ram->base.former;
+			copy = &ram->base.target;
+		}
+
+		xits->bios.ramcfg_11_02_04 = copy->bios.ramcfg_11_02_04;
+		xits->bios.ramcfg_11_02_03 = copy->bios.ramcfg_11_02_03;
+		xits->bios.timing_20_30_07 = copy->bios.timing_20_30_07;
+
+		ram->base.next = &ram->base.target;
+		if (memcmp(xits, &ram->base.former, sizeof(xits->bios)))
+			ram->base.next = &ram->base.xition;
+	} else {
+		BUG_ON(ram->base.next != &ram->base.xition);
+		ram->base.next = &ram->base.target;
+	}
+
+	return nve0_ram_calc_xits(pfb, ram->base.next);
+}
+
 static int
 nve0_ram_prog(struct nouveau_fb *pfb)
 {
@@ -1007,7 +1111,7 @@ nve0_ram_prog(struct nouveau_fb *pfb)
 	struct nve0_ram *ram = (void *)pfb->ram;
 	struct nve0_ramfuc *fuc = &ram->fuc;
 	ram_exec(fuc, nouveau_boolopt(device->cfgopt, "NvMemExec", false));
-	return 0;
+	return (ram->base.next == &ram->base.xition);
 }
 
 static void
@@ -1015,6 +1119,7 @@ nve0_ram_tidy(struct nouveau_fb *pfb)
 {
 	struct nve0_ram *ram = (void *)pfb->ram;
 	struct nve0_ramfuc *fuc = &ram->fuc;
+	ram->base.next = NULL;
 	ram_exec(fuc, false);
 }
 
@@ -1055,7 +1160,7 @@ nve0_ram_init(struct nouveau_object *object)
 	 * binary driver skips the one that's already been setup by
 	 * the init tables.
 	 */
-	data = nvbios_rammap_table(bios, &ver, &hdr, &cnt, &len, &snr, &ssz);
+	data = nvbios_rammapTe(bios, &ver, &hdr, &cnt, &len, &snr, &ssz);
 	if (!data || hdr < 0x15)
 		return -EINVAL;
 
@@ -1073,6 +1178,7 @@ nve0_ram_init(struct nouveau_object *object)
 		data += 4;
 	}
 	nv_wr32(pfb, 0x10f65c, save);
+	nv_mask(pfb, 0x10f584, 0x11000000, 0x00000000);
 
 	switch (ram->base.type) {
 	case NV_MEM_TYPE_GDDR5:
@@ -1117,7 +1223,8 @@ nve0_ram_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
 	struct nouveau_gpio *gpio = nouveau_gpio(pfb);
 	struct dcb_gpio_func func;
 	struct nve0_ram *ram;
-	int ret;
+	int ret, i;
+	u32 tmp;
 
 	ret = nvc0_ram_create(parent, engine, oclass, &ram);
 	*pobject = nv_object(ram);
@@ -1136,6 +1243,25 @@ nve0_ram_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
 		break;
 	}
 
+	/* calculate a mask of differently configured memory partitions,
+	 * because, of course reclocking wasn't complicated enough
+	 * already without having to treat some of them differently to
+	 * the others....
+	 */
+	ram->parts = nv_rd32(pfb, 0x022438);
+	ram->pmask = nv_rd32(pfb, 0x022554);
+	ram->pnuts = 0;
+	for (i = 0, tmp = 0; i < ram->parts; i++) {
+		if (!(ram->pmask & (1 << i))) {
+			u32 cfg1 = nv_rd32(pfb, 0x110204 + (i * 0x1000));
+			if (tmp && tmp != cfg1) {
+				ram->pnuts |= (1 << i);
+				continue;
+			}
+			tmp = cfg1;
+		}
+	}
+
 	// parse bios data for both pll's
 	ret = nvbios_pll_parse(bios, 0x0c, &ram->fuc.refpll);
 	if (ret) {
@@ -1248,7 +1374,7 @@ nve0_ram_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
 	ram->fuc.r_0x10f65c = ramfuc_reg(0x10f65c);
 	ram->fuc.r_0x10f6bc = ramfuc_reg(0x10f6bc);
 	ram->fuc.r_0x100710 = ramfuc_reg(0x100710);
-	ram->fuc.r_0x10f750 = ramfuc_reg(0x10f750);
+	ram->fuc.r_0x100750 = ramfuc_reg(0x100750);
 	return 0;
 }
 
diff --git a/drivers/gpu/drm/nouveau/core/subdev/instmem/base.c b/drivers/gpu/drm/nouveau/core/subdev/instmem/base.c
index 6565f3dbbe04e..14706d9842ca6 100644
--- a/drivers/gpu/drm/nouveau/core/subdev/instmem/base.c
+++ b/drivers/gpu/drm/nouveau/core/subdev/instmem/base.c
@@ -22,7 +22,24 @@
  * Authors: Ben Skeggs
  */
 
-#include <subdev/instmem.h>
+#include "priv.h"
+
+/******************************************************************************
+ * instmem object base implementation
+ *****************************************************************************/
+
+void
+_nouveau_instobj_dtor(struct nouveau_object *object)
+{
+	struct nouveau_instmem *imem = (void *)object->engine;
+	struct nouveau_instobj *iobj = (void *)object;
+
+	mutex_lock(&nv_subdev(imem)->mutex);
+	list_del(&iobj->head);
+	mutex_unlock(&nv_subdev(imem)->mutex);
+
+	return nouveau_object_destroy(&iobj->base);
+}
 
 int
 nouveau_instobj_create_(struct nouveau_object *parent,
@@ -46,73 +63,26 @@ nouveau_instobj_create_(struct nouveau_object *parent,
 	return 0;
 }
 
-void
-nouveau_instobj_destroy(struct nouveau_instobj *iobj)
-{
-	struct nouveau_subdev *subdev = nv_subdev(iobj->base.engine);
+/******************************************************************************
+ * instmem subdev base implementation
+ *****************************************************************************/
 
-	mutex_lock(&subdev->mutex);
-	list_del(&iobj->head);
-	mutex_unlock(&subdev->mutex);
-
-	return nouveau_object_destroy(&iobj->base);
-}
-
-void
-_nouveau_instobj_dtor(struct nouveau_object *object)
+static int
+nouveau_instmem_alloc(struct nouveau_instmem *imem,
+		      struct nouveau_object *parent, u32 size, u32 align,
+		      struct nouveau_object **pobject)
 {
-	struct nouveau_instobj *iobj = (void *)object;
-	return nouveau_instobj_destroy(iobj);
+	struct nouveau_object *engine = nv_object(imem);
+	struct nouveau_instmem_impl *impl = (void *)engine->oclass;
+	struct nouveau_instobj_args args = { .size = size, .align = align };
+	return nouveau_object_ctor(parent, engine, impl->instobj, &args,
+				   sizeof(args), pobject);
 }
 
 int
-nouveau_instmem_create_(struct nouveau_object *parent,
-			struct nouveau_object *engine,
-			struct nouveau_oclass *oclass,
-			int length, void **pobject)
-{
-	struct nouveau_instmem *imem;
-	int ret;
-
-	ret = nouveau_subdev_create_(parent, engine, oclass, 0,
-				     "INSTMEM", "instmem", length, pobject);
-	imem = *pobject;
-	if (ret)
-		return ret;
-
-	INIT_LIST_HEAD(&imem->list);
-	return 0;
-}
-
-int
-nouveau_instmem_init(struct nouveau_instmem *imem)
-{
-	struct nouveau_instobj *iobj;
-	int ret, i;
-
-	ret = nouveau_subdev_init(&imem->base);
-	if (ret)
-		return ret;
-
-	mutex_lock(&imem->base.mutex);
-
-	list_for_each_entry(iobj, &imem->list, head) {
-		if (iobj->suspend) {
-			for (i = 0; i < iobj->size; i += 4)
-				nv_wo32(iobj, i, iobj->suspend[i / 4]);
-			vfree(iobj->suspend);
-			iobj->suspend = NULL;
-		}
-	}
-
-	mutex_unlock(&imem->base.mutex);
-
-	return 0;
-}
-
-int
-nouveau_instmem_fini(struct nouveau_instmem *imem, bool suspend)
+_nouveau_instmem_fini(struct nouveau_object *object, bool suspend)
 {
+	struct nouveau_instmem *imem = (void *)object;
 	struct nouveau_instobj *iobj;
 	int i, ret = 0;
 
@@ -143,12 +113,45 @@ int
 _nouveau_instmem_init(struct nouveau_object *object)
 {
 	struct nouveau_instmem *imem = (void *)object;
-	return nouveau_instmem_init(imem);
+	struct nouveau_instobj *iobj;
+	int ret, i;
+
+	ret = nouveau_subdev_init(&imem->base);
+	if (ret)
+		return ret;
+
+	mutex_lock(&imem->base.mutex);
+
+	list_for_each_entry(iobj, &imem->list, head) {
+		if (iobj->suspend) {
+			for (i = 0; i < iobj->size; i += 4)
+				nv_wo32(iobj, i, iobj->suspend[i / 4]);
+			vfree(iobj->suspend);
+			iobj->suspend = NULL;
+		}
+	}
+
+	mutex_unlock(&imem->base.mutex);
+
+	return 0;
 }
 
 int
-_nouveau_instmem_fini(struct nouveau_object *object, bool suspend)
+nouveau_instmem_create_(struct nouveau_object *parent,
+			struct nouveau_object *engine,
+			struct nouveau_oclass *oclass,
+			int length, void **pobject)
 {
-	struct nouveau_instmem *imem = (void *)object;
-	return nouveau_instmem_fini(imem, suspend);
+	struct nouveau_instmem *imem;
+	int ret;
+
+	ret = nouveau_subdev_create_(parent, engine, oclass, 0,
+				     "INSTMEM", "instmem", length, pobject);
+	imem = *pobject;
+	if (ret)
+		return ret;
+
+	INIT_LIST_HEAD(&imem->list);
+	imem->alloc = nouveau_instmem_alloc;
+	return 0;
 }
diff --git a/drivers/gpu/drm/nouveau/core/subdev/instmem/nv04.c b/drivers/gpu/drm/nouveau/core/subdev/instmem/nv04.c
index 795393d7b2f56..7b64befee48fb 100644
--- a/drivers/gpu/drm/nouveau/core/subdev/instmem/nv04.c
+++ b/drivers/gpu/drm/nouveau/core/subdev/instmem/nv04.c
@@ -22,10 +22,35 @@
  * Authors: Ben Skeggs
  */
 
-#include <subdev/fb.h>
-
 #include "nv04.h"
 
+/******************************************************************************
+ * instmem object implementation
+ *****************************************************************************/
+
+static u32
+nv04_instobj_rd32(struct nouveau_object *object, u64 addr)
+{
+	struct nv04_instobj_priv *node = (void *)object;
+	return nv_ro32(object->engine, node->mem->offset + addr);
+}
+
+static void
+nv04_instobj_wr32(struct nouveau_object *object, u64 addr, u32 data)
+{
+	struct nv04_instobj_priv *node = (void *)object;
+	nv_wo32(object->engine, node->mem->offset + addr, data);
+}
+
+static void
+nv04_instobj_dtor(struct nouveau_object *object)
+{
+	struct nv04_instmem_priv *priv = (void *)object->engine;
+	struct nv04_instobj_priv *node = (void *)object;
+	nouveau_mm_free(&priv->heap, &node->mem);
+	nouveau_instobj_destroy(&node->base);
+}
+
 static int
 nv04_instobj_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
 		  struct nouveau_oclass *oclass, void *data, u32 size,
@@ -33,18 +58,19 @@ nv04_instobj_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
 {
 	struct nv04_instmem_priv *priv = (void *)engine;
 	struct nv04_instobj_priv *node;
-	int ret, align;
+	struct nouveau_instobj_args *args = data;
+	int ret;
 
-	align = (unsigned long)data;
-	if (!align)
-		align = 1;
+	if (!args->align)
+		args->align = 1;
 
 	ret = nouveau_instobj_create(parent, engine, oclass, &node);
 	*pobject = nv_object(node);
 	if (ret)
 		return ret;
 
-	ret = nouveau_mm_head(&priv->heap, 1, size, size, align, &node->mem);
+	ret = nouveau_mm_head(&priv->heap, 1, args->size, args->size,
+			      args->align, &node->mem);
 	if (ret)
 		return ret;
 
@@ -53,32 +79,9 @@ nv04_instobj_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
 	return 0;
 }
 
-static void
-nv04_instobj_dtor(struct nouveau_object *object)
-{
-	struct nv04_instmem_priv *priv = (void *)object->engine;
-	struct nv04_instobj_priv *node = (void *)object;
-	nouveau_mm_free(&priv->heap, &node->mem);
-	nouveau_instobj_destroy(&node->base);
-}
-
-static u32
-nv04_instobj_rd32(struct nouveau_object *object, u64 addr)
-{
-	struct nv04_instobj_priv *node = (void *)object;
-	return nv_ro32(object->engine, node->mem->offset + addr);
-}
-
-static void
-nv04_instobj_wr32(struct nouveau_object *object, u64 addr, u32 data)
-{
-	struct nv04_instobj_priv *node = (void *)object;
-	nv_wo32(object->engine, node->mem->offset + addr, data);
-}
-
-static struct nouveau_oclass
+struct nouveau_instobj_impl
 nv04_instobj_oclass = {
-	.ofuncs = &(struct nouveau_ofuncs) {
+	.base.ofuncs = &(struct nouveau_ofuncs) {
 		.ctor = nv04_instobj_ctor,
 		.dtor = nv04_instobj_dtor,
 		.init = _nouveau_instobj_init,
@@ -88,19 +91,34 @@ nv04_instobj_oclass = {
 	},
 };
 
-int
-nv04_instmem_alloc(struct nouveau_instmem *imem, struct nouveau_object *parent,
-		   u32 size, u32 align, struct nouveau_object **pobject)
+/******************************************************************************
+ * instmem subdev implementation
+ *****************************************************************************/
+
+static u32
+nv04_instmem_rd32(struct nouveau_object *object, u64 addr)
 {
-	struct nouveau_object *engine = nv_object(imem);
-	int ret;
+	return nv_rd32(object, 0x700000 + addr);
+}
 
-	ret = nouveau_object_ctor(parent, engine, &nv04_instobj_oclass,
-				  (void *)(unsigned long)align, size, pobject);
-	if (ret)
-		return ret;
+static void
+nv04_instmem_wr32(struct nouveau_object *object, u64 addr, u32 data)
+{
+	return nv_wr32(object, 0x700000 + addr, data);
+}
 
-	return 0;
+void
+nv04_instmem_dtor(struct nouveau_object *object)
+{
+	struct nv04_instmem_priv *priv = (void *)object;
+	nouveau_gpuobj_ref(NULL, &priv->ramfc);
+	nouveau_gpuobj_ref(NULL, &priv->ramro);
+	nouveau_ramht_ref(NULL, &priv->ramht);
+	nouveau_gpuobj_ref(NULL, &priv->vbios);
+	nouveau_mm_fini(&priv->heap);
+	if (priv->iomem)
+		iounmap(priv->iomem);
+	nouveau_instmem_destroy(&priv->base);
 }
 
 static int
@@ -118,7 +136,6 @@ nv04_instmem_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
 
 	/* PRAMIN aperture maps over the end of VRAM, reserve it */
 	priv->base.reserved = 512 * 1024;
-	priv->base.alloc    = nv04_instmem_alloc;
 
 	ret = nouveau_mm_init(&priv->heap, 0, priv->base.reserved, 1);
 	if (ret)
@@ -150,36 +167,10 @@ nv04_instmem_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
 	return 0;
 }
 
-void
-nv04_instmem_dtor(struct nouveau_object *object)
-{
-	struct nv04_instmem_priv *priv = (void *)object;
-	nouveau_gpuobj_ref(NULL, &priv->ramfc);
-	nouveau_gpuobj_ref(NULL, &priv->ramro);
-	nouveau_ramht_ref(NULL, &priv->ramht);
-	nouveau_gpuobj_ref(NULL, &priv->vbios);
-	nouveau_mm_fini(&priv->heap);
-	if (priv->iomem)
-		iounmap(priv->iomem);
-	nouveau_instmem_destroy(&priv->base);
-}
-
-static u32
-nv04_instmem_rd32(struct nouveau_object *object, u64 addr)
-{
-	return nv_rd32(object, 0x700000 + addr);
-}
-
-static void
-nv04_instmem_wr32(struct nouveau_object *object, u64 addr, u32 data)
-{
-	return nv_wr32(object, 0x700000 + addr, data);
-}
-
-struct nouveau_oclass
-nv04_instmem_oclass = {
-	.handle = NV_SUBDEV(INSTMEM, 0x04),
-	.ofuncs = &(struct nouveau_ofuncs) {
+struct nouveau_oclass *
+nv04_instmem_oclass = &(struct nouveau_instmem_impl) {
+	.base.handle = NV_SUBDEV(INSTMEM, 0x04),
+	.base.ofuncs = &(struct nouveau_ofuncs) {
 		.ctor = nv04_instmem_ctor,
 		.dtor = nv04_instmem_dtor,
 		.init = _nouveau_instmem_init,
@@ -187,4 +178,5 @@ nv04_instmem_oclass = {
 		.rd32 = nv04_instmem_rd32,
 		.wr32 = nv04_instmem_wr32,
 	},
-};
+	.instobj = &nv04_instobj_oclass.base,
+}.base;
diff --git a/drivers/gpu/drm/nouveau/core/subdev/instmem/nv04.h b/drivers/gpu/drm/nouveau/core/subdev/instmem/nv04.h
index b15b613102366..095fbc6fc099a 100644
--- a/drivers/gpu/drm/nouveau/core/subdev/instmem/nv04.h
+++ b/drivers/gpu/drm/nouveau/core/subdev/instmem/nv04.h
@@ -5,7 +5,9 @@
 #include <core/ramht.h>
 #include <core/mm.h>
 
-#include <subdev/instmem.h>
+#include "priv.h"
+
+extern struct nouveau_instobj_impl nv04_instobj_oclass;
 
 struct nv04_instmem_priv {
 	struct nouveau_instmem base;
diff --git a/drivers/gpu/drm/nouveau/core/subdev/instmem/nv40.c b/drivers/gpu/drm/nouveau/core/subdev/instmem/nv40.c
index b10a143787a7a..ec0b9661d614c 100644
--- a/drivers/gpu/drm/nouveau/core/subdev/instmem/nv40.c
+++ b/drivers/gpu/drm/nouveau/core/subdev/instmem/nv40.c
@@ -26,6 +26,24 @@
 
 #include "nv04.h"
 
+/******************************************************************************
+ * instmem subdev implementation
+ *****************************************************************************/
+
+static u32
+nv40_instmem_rd32(struct nouveau_object *object, u64 addr)
+{
+	struct nv04_instmem_priv *priv = (void *)object;
+	return ioread32_native(priv->iomem + addr);
+}
+
+static void
+nv40_instmem_wr32(struct nouveau_object *object, u64 addr, u32 data)
+{
+	struct nv04_instmem_priv *priv = (void *)object;
+	iowrite32_native(data, priv->iomem + addr);
+}
+
 static int
 nv40_instmem_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
 		  struct nouveau_oclass *oclass, void *data, u32 size,
@@ -69,7 +87,6 @@ nv40_instmem_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
 	priv->base.reserved += 512 * 1024;	/* object storage */
 
 	priv->base.reserved = round_up(priv->base.reserved, 4096);
-	priv->base.alloc    = nv04_instmem_alloc;
 
 	ret = nouveau_mm_init(&priv->heap, 0, priv->base.reserved, 1);
 	if (ret)
@@ -106,24 +123,10 @@ nv40_instmem_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
 	return 0;
 }
 
-static u32
-nv40_instmem_rd32(struct nouveau_object *object, u64 addr)
-{
-	struct nv04_instmem_priv *priv = (void *)object;
-	return ioread32_native(priv->iomem + addr);
-}
-
-static void
-nv40_instmem_wr32(struct nouveau_object *object, u64 addr, u32 data)
-{
-	struct nv04_instmem_priv *priv = (void *)object;
-	iowrite32_native(data, priv->iomem + addr);
-}
-
-struct nouveau_oclass
-nv40_instmem_oclass = {
-	.handle = NV_SUBDEV(INSTMEM, 0x40),
-	.ofuncs = &(struct nouveau_ofuncs) {
+struct nouveau_oclass *
+nv40_instmem_oclass = &(struct nouveau_instmem_impl) {
+	.base.handle = NV_SUBDEV(INSTMEM, 0x40),
+	.base.ofuncs = &(struct nouveau_ofuncs) {
 		.ctor = nv40_instmem_ctor,
 		.dtor = nv04_instmem_dtor,
 		.init = _nouveau_instmem_init,
@@ -131,4 +134,5 @@ nv40_instmem_oclass = {
 		.rd32 = nv40_instmem_rd32,
 		.wr32 = nv40_instmem_wr32,
 	},
-};
+	.instobj = &nv04_instobj_oclass.base,
+}.base;
diff --git a/drivers/gpu/drm/nouveau/core/subdev/instmem/nv50.c b/drivers/gpu/drm/nouveau/core/subdev/instmem/nv50.c
index 97bc5dff93e7a..7cb3b098a08d0 100644
--- a/drivers/gpu/drm/nouveau/core/subdev/instmem/nv50.c
+++ b/drivers/gpu/drm/nouveau/core/subdev/instmem/nv50.c
@@ -22,11 +22,11 @@
  * Authors: Ben Skeggs
  */
 
-#include <subdev/instmem.h>
 #include <subdev/fb.h>
-
 #include <core/mm.h>
 
+#include "priv.h"
+
 struct nv50_instmem_priv {
 	struct nouveau_instmem base;
 	spinlock_t lock;
@@ -38,42 +38,9 @@ struct nv50_instobj_priv {
 	struct nouveau_mem *mem;
 };
 
-static int
-nv50_instobj_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
-		  struct nouveau_oclass *oclass, void *data, u32 size,
-		  struct nouveau_object **pobject)
-{
-	struct nouveau_fb *pfb = nouveau_fb(parent);
-	struct nv50_instobj_priv *node;
-	u32 align = (unsigned long)data;
-	int ret;
-
-	size  = max((size  + 4095) & ~4095, (u32)4096);
-	align = max((align + 4095) & ~4095, (u32)4096);
-
-	ret = nouveau_instobj_create(parent, engine, oclass, &node);
-	*pobject = nv_object(node);
-	if (ret)
-		return ret;
-
-	ret = pfb->ram->get(pfb, size, align, 0, 0x800, &node->mem);
-	if (ret)
-		return ret;
-
-	node->base.addr = node->mem->offset;
-	node->base.size = node->mem->size << 12;
-	node->mem->page_shift = 12;
-	return 0;
-}
-
-static void
-nv50_instobj_dtor(struct nouveau_object *object)
-{
-	struct nv50_instobj_priv *node = (void *)object;
-	struct nouveau_fb *pfb = nouveau_fb(object);
-	pfb->ram->put(pfb, &node->mem);
-	nouveau_instobj_destroy(&node->base);
-}
+/******************************************************************************
+ * instmem object implementation
+ *****************************************************************************/
 
 static u32
 nv50_instobj_rd32(struct nouveau_object *object, u64 offset)
@@ -113,9 +80,46 @@ nv50_instobj_wr32(struct nouveau_object *object, u64 offset, u32 data)
 	spin_unlock_irqrestore(&priv->lock, flags);
 }
 
-static struct nouveau_oclass
+static void
+nv50_instobj_dtor(struct nouveau_object *object)
+{
+	struct nv50_instobj_priv *node = (void *)object;
+	struct nouveau_fb *pfb = nouveau_fb(object);
+	pfb->ram->put(pfb, &node->mem);
+	nouveau_instobj_destroy(&node->base);
+}
+
+static int
+nv50_instobj_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
+		  struct nouveau_oclass *oclass, void *data, u32 size,
+		  struct nouveau_object **pobject)
+{
+	struct nouveau_fb *pfb = nouveau_fb(parent);
+	struct nouveau_instobj_args *args = data;
+	struct nv50_instobj_priv *node;
+	int ret;
+
+	args->size  = max((args->size  + 4095) & ~4095, (u32)4096);
+	args->align = max((args->align + 4095) & ~4095, (u32)4096);
+
+	ret = nouveau_instobj_create(parent, engine, oclass, &node);
+	*pobject = nv_object(node);
+	if (ret)
+		return ret;
+
+	ret = pfb->ram->get(pfb, args->size, args->align, 0, 0x800, &node->mem);
+	if (ret)
+		return ret;
+
+	node->base.addr = node->mem->offset;
+	node->base.size = node->mem->size << 12;
+	node->mem->page_shift = 12;
+	return 0;
+}
+
+static struct nouveau_instobj_impl
 nv50_instobj_oclass = {
-	.ofuncs = &(struct nouveau_ofuncs) {
+	.base.ofuncs = &(struct nouveau_ofuncs) {
 		.ctor = nv50_instobj_ctor,
 		.dtor = nv50_instobj_dtor,
 		.init = _nouveau_instobj_init,
@@ -125,13 +129,16 @@ nv50_instobj_oclass = {
 	},
 };
 
+/******************************************************************************
+ * instmem subdev implementation
+ *****************************************************************************/
+
 static int
-nv50_instmem_alloc(struct nouveau_instmem *imem, struct nouveau_object *parent,
-		   u32 size, u32 align, struct nouveau_object **pobject)
+nv50_instmem_fini(struct nouveau_object *object, bool suspend)
 {
-	struct nouveau_object *engine = nv_object(imem);
-	return nouveau_object_ctor(parent, engine, &nv50_instobj_oclass,
-				   (void *)(unsigned long)align, size, pobject);
+	struct nv50_instmem_priv *priv = (void *)object;
+	priv->addr = ~0ULL;
+	return nouveau_instmem_fini(&priv->base, suspend);
 }
 
 static int
@@ -148,25 +155,17 @@ nv50_instmem_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
 		return ret;
 
 	spin_lock_init(&priv->lock);
-	priv->base.alloc = nv50_instmem_alloc;
 	return 0;
 }
 
-static int
-nv50_instmem_fini(struct nouveau_object *object, bool suspend)
-{
-	struct nv50_instmem_priv *priv = (void *)object;
-	priv->addr = ~0ULL;
-	return nouveau_instmem_fini(&priv->base, suspend);
-}
-
-struct nouveau_oclass
-nv50_instmem_oclass = {
-	.handle = NV_SUBDEV(INSTMEM, 0x50),
-	.ofuncs = &(struct nouveau_ofuncs) {
+struct nouveau_oclass *
+nv50_instmem_oclass = &(struct nouveau_instmem_impl) {
+	.base.handle = NV_SUBDEV(INSTMEM, 0x50),
+	.base.ofuncs = &(struct nouveau_ofuncs) {
 		.ctor = nv50_instmem_ctor,
 		.dtor = _nouveau_instmem_dtor,
 		.init = _nouveau_instmem_init,
 		.fini = nv50_instmem_fini,
 	},
-};
+	.instobj = &nv50_instobj_oclass.base,
+}.base;
diff --git a/drivers/gpu/drm/nouveau/core/subdev/instmem/priv.h b/drivers/gpu/drm/nouveau/core/subdev/instmem/priv.h
new file mode 100644
index 0000000000000..8d67dedc5bb23
--- /dev/null
+++ b/drivers/gpu/drm/nouveau/core/subdev/instmem/priv.h
@@ -0,0 +1,56 @@
+#ifndef __NVKM_INSTMEM_PRIV_H__
+#define __NVKM_INSTMEM_PRIV_H__
+
+#include <subdev/instmem.h>
+
+struct nouveau_instobj_impl {
+	struct nouveau_oclass base;
+};
+
+struct nouveau_instobj_args {
+	u32 size;
+	u32 align;
+};
+
+#define nouveau_instobj_create(p,e,o,d)                                        \
+	nouveau_instobj_create_((p), (e), (o), sizeof(**d), (void **)d)
+#define nouveau_instobj_destroy(p) ({                                          \
+	struct nouveau_instobj *iobj = (p);                                    \
+	_nouveau_instobj_dtor(nv_object(iobj));                                \
+})
+#define nouveau_instobj_init(p)                                                \
+	nouveau_object_init(&(p)->base)
+#define nouveau_instobj_fini(p,s)                                              \
+	nouveau_object_fini(&(p)->base, (s))
+
+int  nouveau_instobj_create_(struct nouveau_object *, struct nouveau_object *,
+			     struct nouveau_oclass *, int, void **);
+void _nouveau_instobj_dtor(struct nouveau_object *);
+#define _nouveau_instobj_init nouveau_object_init
+#define _nouveau_instobj_fini nouveau_object_fini
+
+struct nouveau_instmem_impl {
+	struct nouveau_oclass base;
+	struct nouveau_oclass *instobj;
+};
+
+#define nouveau_instmem_create(p,e,o,d)                                        \
+	nouveau_instmem_create_((p), (e), (o), sizeof(**d), (void **)d)
+#define nouveau_instmem_destroy(p)                                             \
+	nouveau_subdev_destroy(&(p)->base)
+#define nouveau_instmem_init(p) ({                                             \
+	struct nouveau_instmem *imem = (p);                                    \
+	_nouveau_instmem_init(nv_object(imem));                                \
+})
+#define nouveau_instmem_fini(p,s) ({                                           \
+	struct nouveau_instmem *imem = (p);                                    \
+	_nouveau_instmem_fini(nv_object(imem), (s));                           \
+})
+
+int nouveau_instmem_create_(struct nouveau_object *, struct nouveau_object *,
+			    struct nouveau_oclass *, int, void **);
+#define _nouveau_instmem_dtor _nouveau_subdev_dtor
+int _nouveau_instmem_init(struct nouveau_object *);
+int _nouveau_instmem_fini(struct nouveau_object *, bool);
+
+#endif
diff --git a/drivers/gpu/drm/nouveau/core/subdev/mc/nvc0.c b/drivers/gpu/drm/nouveau/core/subdev/mc/nvc0.c
index c02b4763a2d50..34472d3170974 100644
--- a/drivers/gpu/drm/nouveau/core/subdev/mc/nvc0.c
+++ b/drivers/gpu/drm/nouveau/core/subdev/mc/nvc0.c
@@ -32,6 +32,7 @@ nvc0_mc_intr[] = {
 	{ 0x00000080, NVDEV_ENGINE_COPY2 },
 	{ 0x00000100, NVDEV_ENGINE_FIFO },
 	{ 0x00001000, NVDEV_ENGINE_GR },
+	{ 0x00002000, NVDEV_SUBDEV_FB },
 	{ 0x00008000, NVDEV_ENGINE_BSP },
 	{ 0x00040000, NVDEV_SUBDEV_THERM },
 	{ 0x00020000, NVDEV_ENGINE_VP },
@@ -40,6 +41,7 @@ nvc0_mc_intr[] = {
 	{ 0x01000000, NVDEV_SUBDEV_PWR },
 	{ 0x02000000, NVDEV_SUBDEV_LTCG },
 	{ 0x04000000, NVDEV_ENGINE_DISP },
+	{ 0x08000000, NVDEV_SUBDEV_FB },
 	{ 0x10000000, NVDEV_SUBDEV_BUS },
 	{ 0x40000000, NVDEV_SUBDEV_IBUS },
 	{ 0x80000000, NVDEV_ENGINE_SW },
diff --git a/drivers/gpu/drm/nouveau/core/subdev/mxm/nv50.c b/drivers/gpu/drm/nouveau/core/subdev/mxm/nv50.c
index af129c2e81138..64f8b4702bf72 100644
--- a/drivers/gpu/drm/nouveau/core/subdev/mxm/nv50.c
+++ b/drivers/gpu/drm/nouveau/core/subdev/mxm/nv50.c
@@ -100,7 +100,7 @@ mxm_match_dcb(struct nouveau_mxm *mxm, u8 *data, void *info)
 static int
 mxm_dcb_sanitise_entry(struct nouveau_bios *bios, void *data, int idx, u16 pdcb)
 {
-	struct nouveau_mxm *mxm = nouveau_mxm(bios);
+	struct nouveau_mxm *mxm = data;
 	struct context ctx = { .outp = (u32 *)(bios->data + pdcb) };
 	u8 type, i2cidx, link, ver, len;
 	u8 *conn;
@@ -199,7 +199,7 @@ mxm_dcb_sanitise(struct nouveau_mxm *mxm)
 		return;
 	}
 
-	dcb_outp_foreach(bios, NULL, mxm_dcb_sanitise_entry);
+	dcb_outp_foreach(bios, mxm, mxm_dcb_sanitise_entry);
 	mxms_foreach(mxm, 0x01, mxm_show_unmatched, NULL);
 }
 
diff --git a/drivers/gpu/drm/nouveau/core/subdev/pwr/fuc/i2c_.fuc b/drivers/gpu/drm/nouveau/core/subdev/pwr/fuc/i2c_.fuc
new file mode 100644
index 0000000000000..757dda7000248
--- /dev/null
+++ b/drivers/gpu/drm/nouveau/core/subdev/pwr/fuc/i2c_.fuc
@@ -0,0 +1,393 @@
+/*
+ * Copyright 2013 Red Hat Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: Ben Skeggs
+ */
+
+#define T_TIMEOUT  2200000
+#define T_RISEFALL 1000
+#define T_HOLD     5000
+
+#ifdef INCLUDE_PROC
+process(PROC_I2C_, #i2c_init, #i2c_recv)
+#endif
+
+/******************************************************************************
+ * I2C_ data segment
+ *****************************************************************************/
+#ifdef INCLUDE_DATA
+i2c_scl_map:
+.b32 NV_PPWR_OUTPUT_I2C_0_SCL
+.b32 NV_PPWR_OUTPUT_I2C_1_SCL
+.b32 NV_PPWR_OUTPUT_I2C_2_SCL
+.b32 NV_PPWR_OUTPUT_I2C_3_SCL
+.b32 NV_PPWR_OUTPUT_I2C_4_SCL
+.b32 NV_PPWR_OUTPUT_I2C_5_SCL
+.b32 NV_PPWR_OUTPUT_I2C_6_SCL
+.b32 NV_PPWR_OUTPUT_I2C_7_SCL
+.b32 NV_PPWR_OUTPUT_I2C_8_SCL
+.b32 NV_PPWR_OUTPUT_I2C_9_SCL
+i2c_sda_map:
+.b32 NV_PPWR_OUTPUT_I2C_0_SDA
+.b32 NV_PPWR_OUTPUT_I2C_1_SDA
+.b32 NV_PPWR_OUTPUT_I2C_2_SDA
+.b32 NV_PPWR_OUTPUT_I2C_3_SDA
+.b32 NV_PPWR_OUTPUT_I2C_4_SDA
+.b32 NV_PPWR_OUTPUT_I2C_5_SDA
+.b32 NV_PPWR_OUTPUT_I2C_6_SDA
+.b32 NV_PPWR_OUTPUT_I2C_7_SDA
+.b32 NV_PPWR_OUTPUT_I2C_8_SDA
+.b32 NV_PPWR_OUTPUT_I2C_9_SDA
+#if NVKM_PPWR_CHIPSET < GF119
+i2c_ctrl:
+.b32 0x00e138
+.b32 0x00e150
+.b32 0x00e168
+.b32 0x00e180
+.b32 0x00e254
+.b32 0x00e274
+.b32 0x00e764
+.b32 0x00e780
+.b32 0x00e79c
+.b32 0x00e7b8
+#endif
+#endif
+
+/******************************************************************************
+ * I2C_ code segment
+ *****************************************************************************/
+#ifdef INCLUDE_CODE
+
+// $r3  - value
+// $r2  - sda line
+// $r1  - scl line
+// $r0  - zero
+i2c_drive_scl:
+	cmp b32 $r3 0
+	bra e #i2c_drive_scl_lo
+	nv_iowr(NV_PPWR_OUTPUT_SET, $r1)
+	ret
+	i2c_drive_scl_lo:
+	nv_iowr(NV_PPWR_OUTPUT_CLR, $r1)
+	ret
+
+i2c_drive_sda:
+	cmp b32 $r3 0
+	bra e #i2c_drive_sda_lo
+	nv_iowr(NV_PPWR_OUTPUT_SET, $r2)
+	ret
+	i2c_drive_sda_lo:
+	nv_iowr(NV_PPWR_OUTPUT_CLR, $r2)
+	ret
+
+i2c_sense_scl:
+	bclr $flags $p1
+	nv_iord($r3, NV_PPWR_INPUT)
+	and $r3 $r1
+	bra z #i2c_sense_scl_done
+		bset $flags $p1
+	i2c_sense_scl_done:
+	ret
+
+i2c_sense_sda:
+	bclr $flags $p1
+	nv_iord($r3, NV_PPWR_INPUT)
+	and $r3 $r2
+	bra z #i2c_sense_sda_done
+		bset $flags $p1
+	i2c_sense_sda_done:
+	ret
+
+#define i2c_drive_scl(v) /*
+*/	mov $r3 (v) /*
+*/	call(i2c_drive_scl)
+#define i2c_drive_sda(v) /*
+*/	mov $r3 (v) /*
+*/	call(i2c_drive_sda)
+#define i2c_sense_scl() /*
+*/	call(i2c_sense_scl)
+#define i2c_sense_sda() /*
+*/	call(i2c_sense_sda)
+#define i2c_delay(v) /*
+*/	mov $r14 (v) /*
+*/	call(nsec)
+
+#define i2c_trace_init() /*
+*/	imm32($r6, 0x10000000) /*
+*/	sub b32 $r7 $r6 1 /*
+*/
+#define i2c_trace_down() /*
+*/	shr b32 $r6 4 /*
+*/	push $r5 /*
+*/	shl b32 $r5 $r6 4 /*
+*/	sub b32 $r5 $r6 /*
+*/	not b32 $r5 /*
+*/	and $r7 $r5 /*
+*/	pop $r5 /*
+*/
+#define i2c_trace_exit() /*
+*/	shl b32 $r6 4 /*
+*/
+#define i2c_trace_next() /*
+*/	add b32 $r7 $r6 /*
+*/
+#define i2c_trace_call(func) /*
+*/	i2c_trace_next() /*
+*/	i2c_trace_down() /*
+*/	call(func) /*
+*/	i2c_trace_exit() /*
+*/
+
+i2c_raise_scl:
+	push $r4
+	mov $r4 (T_TIMEOUT / T_RISEFALL)
+	i2c_drive_scl(1)
+	i2c_raise_scl_wait:
+		i2c_delay(T_RISEFALL)
+		i2c_sense_scl()
+		bra $p1 #i2c_raise_scl_done
+		sub b32 $r4 1
+		bra nz #i2c_raise_scl_wait
+	i2c_raise_scl_done:
+	pop $r4
+	ret
+
+i2c_start:
+	i2c_sense_scl()
+	bra not $p1 #i2c_start_rep
+	i2c_sense_sda()
+	bra not $p1 #i2c_start_rep
+	bra #i2c_start_send
+	i2c_start_rep:
+		i2c_drive_scl(0)
+		i2c_drive_sda(1)
+		i2c_trace_call(i2c_raise_scl)
+		bra not $p1 #i2c_start_out
+	i2c_start_send:
+	i2c_drive_sda(0)
+	i2c_delay(T_HOLD)
+	i2c_drive_scl(0)
+	i2c_delay(T_HOLD)
+	i2c_start_out:
+	ret
+
+i2c_stop:
+	i2c_drive_scl(0)
+	i2c_drive_sda(0)
+	i2c_delay(T_RISEFALL)
+	i2c_drive_scl(1)
+	i2c_delay(T_HOLD)
+	i2c_drive_sda(1)
+	i2c_delay(T_HOLD)
+	ret
+
+// $r3  - value
+// $r2  - sda line
+// $r1  - scl line
+// $r0  - zero
+i2c_bitw:
+	call(i2c_drive_sda)
+	i2c_delay(T_RISEFALL)
+	i2c_trace_call(i2c_raise_scl)
+	bra not $p1 #i2c_bitw_out
+	i2c_delay(T_HOLD)
+	i2c_drive_scl(0)
+	i2c_delay(T_HOLD)
+	i2c_bitw_out:
+	ret
+
+// $r3  - value (out)
+// $r2  - sda line
+// $r1  - scl line
+// $r0  - zero
+i2c_bitr:
+	i2c_drive_sda(1)
+	i2c_delay(T_RISEFALL)
+	i2c_trace_call(i2c_raise_scl)
+	bra not $p1 #i2c_bitr_done
+	i2c_sense_sda()
+	i2c_drive_scl(0)
+	i2c_delay(T_HOLD)
+	xbit $r3 $flags $p1
+	bset $flags $p1
+	i2c_bitr_done:
+	ret
+
+i2c_get_byte:
+	mov $r5 0
+	mov $r4 8
+	i2c_get_byte_next:
+		shl b32 $r5 1
+		i2c_trace_call(i2c_bitr)
+		bra not $p1 #i2c_get_byte_done
+		or $r5 $r3
+		sub b32 $r4 1
+		bra nz #i2c_get_byte_next
+	mov $r3 1
+	i2c_trace_call(i2c_bitw)
+	i2c_get_byte_done:
+	ret
+
+i2c_put_byte:
+	mov $r4 8
+	i2c_put_byte_next:
+		sub b32 $r4 1
+		xbit $r3 $r5 $r4
+		i2c_trace_call(i2c_bitw)
+		bra not $p1 #i2c_put_byte_done
+		cmp b32 $r4 0
+		bra ne #i2c_put_byte_next
+	i2c_trace_call(i2c_bitr)
+	bra not $p1 #i2c_put_byte_done
+	i2c_trace_next()
+	cmp b32 $r3 1
+	bra ne #i2c_put_byte_done
+	bclr $flags $p1	// nack
+	i2c_put_byte_done:
+	ret
+
+i2c_addr:
+	i2c_trace_call(i2c_start)
+	bra not $p1 #i2c_addr_done
+	extr $r3 $r12 I2C__MSG_DATA0_ADDR
+	shl b32 $r3 1
+	or $r5 $r3
+	i2c_trace_call(i2c_put_byte)
+	i2c_addr_done:
+	ret
+
+i2c_acquire_addr:
+	extr $r14 $r12 I2C__MSG_DATA0_PORT
+#if NVKM_PPWR_CHIPSET < GF119
+	shl b32 $r14 2
+	add b32 $r14 #i2c_ctrl
+	ld b32 $r14 D[$r14]
+#else
+	shl b32 $r14 5
+	add b32 $r14 0x00d014
+#endif
+	ret
+
+i2c_acquire:
+	call(i2c_acquire_addr)
+	call(rd32)
+	bset $r13 3
+	call(wr32)
+	ret
+
+i2c_release:
+	call(i2c_acquire_addr)
+	call(rd32)
+	bclr $r13 3
+	call(wr32)
+	ret
+
+// description
+//
+// $r15 - current (i2c)
+// $r14 - sender process name
+// $r13 - message
+// $r12 - data0
+// $r11 - data1
+// $r0  - zero
+i2c_recv:
+	bclr $flags $p1
+	extr $r1 $r12 I2C__MSG_DATA0_PORT
+	shl b32 $r1 2
+	cmp b32 $r1 (#i2c_sda_map - #i2c_scl_map)
+	bra ge #i2c_recv_done
+	add b32 $r3 $r1 #i2c_sda_map
+	ld b32 $r2 D[$r3]
+	add b32 $r3 $r1 #i2c_scl_map
+	ld b32 $r1 D[$r3]
+
+	bset $flags $p2
+	push $r13
+	push $r14
+
+	push $r13
+	i2c_trace_init()
+	i2c_trace_call(i2c_acquire)
+	pop $r13
+
+	cmp b32 $r13 I2C__MSG_RD08
+	bra ne #i2c_recv_not_rd08
+		mov $r5 0
+		i2c_trace_call(i2c_addr)
+		bra not $p1 #i2c_recv_done
+		extr $r5 $r12 I2C__MSG_DATA0_RD08_REG
+		i2c_trace_call(i2c_put_byte)
+		bra not $p1 #i2c_recv_done
+		mov $r5 1
+		i2c_trace_call(i2c_addr)
+		bra not $p1 #i2c_recv_done
+		i2c_trace_call(i2c_get_byte)
+		bra not $p1 #i2c_recv_done
+		ins $r11 $r5 I2C__MSG_DATA1_RD08_VAL
+		i2c_trace_call(i2c_stop)
+		mov b32 $r11 $r5
+		clear b32 $r7
+		bra #i2c_recv_done
+
+	i2c_recv_not_rd08:
+	cmp b32 $r13 I2C__MSG_WR08
+	bra ne #i2c_recv_not_wr08
+		mov $r5 0
+		call(i2c_addr)
+		bra not $p1 #i2c_recv_done
+		extr $r5 $r12 I2C__MSG_DATA0_WR08_REG
+		call(i2c_put_byte)
+		bra not $p1 #i2c_recv_done
+		mov $r5 0
+		call(i2c_addr)
+		bra not $p1 #i2c_recv_done
+		extr $r5 $r11 I2C__MSG_DATA1_WR08_VAL
+		call(i2c_put_byte)
+		bra not $p1 #i2c_recv_done
+		call(i2c_stop)
+		clear b32 $r7
+		extr $r5 $r12 I2C__MSG_DATA0_WR08_SYNC
+		bra nz #i2c_recv_done
+		bclr $flags $p2
+		bra #i2c_recv_done
+
+	i2c_recv_not_wr08:
+
+	i2c_recv_done:
+	extr $r14 $r12 I2C__MSG_DATA0_PORT
+	call(i2c_release)
+
+	pop $r14
+	pop $r13
+	bra not $p2 #i2c_recv_exit
+	mov b32 $r12 $r7
+	call(send)
+
+	i2c_recv_exit:
+	ret
+
+// description
+//
+// $r15 - current (i2c)
+// $r0  - zero
+i2c_init:
+	ret
+#endif
diff --git a/drivers/gpu/drm/nouveau/core/subdev/pwr/fuc/kernel.fuc b/drivers/gpu/drm/nouveau/core/subdev/pwr/fuc/kernel.fuc
index 0a7b05fa5c111..8f29badd785f1 100644
--- a/drivers/gpu/drm/nouveau/core/subdev/pwr/fuc/kernel.fuc
+++ b/drivers/gpu/drm/nouveau/core/subdev/pwr/fuc/kernel.fuc
@@ -51,12 +51,12 @@ time_next: .b32 0
 // $r0  - zero
 rd32:
 	nv_iowr(NV_PPWR_MMIO_ADDR, $r14)
-	mov $r14 NV_PPWR_MMIO_CTRL_OP_RD
-	sethi $r14 NV_PPWR_MMIO_CTRL_TRIGGER
-	nv_iowr(NV_PPWR_MMIO_CTRL, $r14)
+	mov $r13 NV_PPWR_MMIO_CTRL_OP_RD
+	sethi $r13 NV_PPWR_MMIO_CTRL_TRIGGER
+	nv_iowr(NV_PPWR_MMIO_CTRL, $r13)
 	rd32_wait:
-		nv_iord($r14, NV_PPWR_MMIO_CTRL)
-		and $r14 NV_PPWR_MMIO_CTRL_STATUS
+		nv_iord($r13, NV_PPWR_MMIO_CTRL)
+		and $r13 NV_PPWR_MMIO_CTRL_STATUS
 		bra nz #rd32_wait
 	nv_iord($r13, NV_PPWR_MMIO_DATA)
 	ret
@@ -70,23 +70,25 @@ rd32:
 wr32:
 	nv_iowr(NV_PPWR_MMIO_ADDR, $r14)
 	nv_iowr(NV_PPWR_MMIO_DATA, $r13)
-	mov $r14 NV_PPWR_MMIO_CTRL_OP_WR
-	or $r14 NV_PPWR_MMIO_CTRL_MASK_B32_0
-	sethi $r14 NV_PPWR_MMIO_CTRL_TRIGGER
+	mov $r13 NV_PPWR_MMIO_CTRL_OP_WR
+	or $r13 NV_PPWR_MMIO_CTRL_MASK_B32_0
+	sethi $r13 NV_PPWR_MMIO_CTRL_TRIGGER
 
 #ifdef NVKM_FALCON_MMIO_TRAP
-	mov $r8 NV_PPWR_INTR_TRIGGER_USER1
-	nv_iowr(NV_PPWR_INTR_TRIGGER, $r8)
+	push $r13
+	mov $r13 NV_PPWR_INTR_TRIGGER_USER1
+	nv_iowr(NV_PPWR_INTR_TRIGGER, $r13)
 	wr32_host:
-		nv_iord($r8, NV_PPWR_INTR)
-		and $r8 NV_PPWR_INTR_USER1
+		nv_iord($r13, NV_PPWR_INTR)
+		and $r13 NV_PPWR_INTR_USER1
 		bra nz #wr32_host
+	pop $r13
 #endif
 
-	nv_iowr(NV_PPWR_MMIO_CTRL, $r14)
+	nv_iowr(NV_PPWR_MMIO_CTRL, $r13)
 	wr32_wait:
-		nv_iord($r14, NV_PPWR_MMIO_CTRL)
-		and $r14 NV_PPWR_MMIO_CTRL_STATUS
+		nv_iord($r13, NV_PPWR_MMIO_CTRL)
+		and $r13 NV_PPWR_MMIO_CTRL_STATUS
 		bra nz #wr32_wait
 	ret
 
diff --git a/drivers/gpu/drm/nouveau/core/subdev/pwr/fuc/macros.fuc b/drivers/gpu/drm/nouveau/core/subdev/pwr/fuc/macros.fuc
index 2a74ea9076043..e2a63ac5422b8 100644
--- a/drivers/gpu/drm/nouveau/core/subdev/pwr/fuc/macros.fuc
+++ b/drivers/gpu/drm/nouveau/core/subdev/pwr/fuc/macros.fuc
@@ -83,6 +83,50 @@
 #define NV_PPWR_MMIO_CTRL_OP_WR                                      0x00000002
 #define NV_PPWR_OUTPUT                                                   0x07c0
 #define NV_PPWR_OUTPUT_FB_PAUSE                                      0x00000004
+#if NVKM_PPWR_CHIPSET < GF119
+#define NV_PPWR_OUTPUT_I2C_3_SCL                                     0x00000100
+#define NV_PPWR_OUTPUT_I2C_3_SDA                                     0x00000200
+#define NV_PPWR_OUTPUT_I2C_0_SCL                                     0x00001000
+#define NV_PPWR_OUTPUT_I2C_0_SDA                                     0x00002000
+#define NV_PPWR_OUTPUT_I2C_1_SCL                                     0x00004000
+#define NV_PPWR_OUTPUT_I2C_1_SDA                                     0x00008000
+#define NV_PPWR_OUTPUT_I2C_2_SCL                                     0x00010000
+#define NV_PPWR_OUTPUT_I2C_2_SDA                                     0x00020000
+#define NV_PPWR_OUTPUT_I2C_4_SCL                                     0x00040000
+#define NV_PPWR_OUTPUT_I2C_4_SDA                                     0x00080000
+#define NV_PPWR_OUTPUT_I2C_5_SCL                                     0x00100000
+#define NV_PPWR_OUTPUT_I2C_5_SDA                                     0x00200000
+#define NV_PPWR_OUTPUT_I2C_6_SCL                                     0x00400000
+#define NV_PPWR_OUTPUT_I2C_6_SDA                                     0x00800000
+#define NV_PPWR_OUTPUT_I2C_7_SCL                                     0x01000000
+#define NV_PPWR_OUTPUT_I2C_7_SDA                                     0x02000000
+#define NV_PPWR_OUTPUT_I2C_8_SCL                                     0x04000000
+#define NV_PPWR_OUTPUT_I2C_8_SDA                                     0x08000000
+#define NV_PPWR_OUTPUT_I2C_9_SCL                                     0x10000000
+#define NV_PPWR_OUTPUT_I2C_9_SDA                                     0x20000000
+#else
+#define NV_PPWR_OUTPUT_I2C_0_SCL                                     0x00000400
+#define NV_PPWR_OUTPUT_I2C_1_SCL                                     0x00000800
+#define NV_PPWR_OUTPUT_I2C_2_SCL                                     0x00001000
+#define NV_PPWR_OUTPUT_I2C_3_SCL                                     0x00002000
+#define NV_PPWR_OUTPUT_I2C_4_SCL                                     0x00004000
+#define NV_PPWR_OUTPUT_I2C_5_SCL                                     0x00008000
+#define NV_PPWR_OUTPUT_I2C_6_SCL                                     0x00010000
+#define NV_PPWR_OUTPUT_I2C_7_SCL                                     0x00020000
+#define NV_PPWR_OUTPUT_I2C_8_SCL                                     0x00040000
+#define NV_PPWR_OUTPUT_I2C_9_SCL                                     0x00080000
+#define NV_PPWR_OUTPUT_I2C_0_SDA                                     0x00100000
+#define NV_PPWR_OUTPUT_I2C_1_SDA                                     0x00200000
+#define NV_PPWR_OUTPUT_I2C_2_SDA                                     0x00400000
+#define NV_PPWR_OUTPUT_I2C_3_SDA                                     0x00800000
+#define NV_PPWR_OUTPUT_I2C_4_SDA                                     0x01000000
+#define NV_PPWR_OUTPUT_I2C_5_SDA                                     0x02000000
+#define NV_PPWR_OUTPUT_I2C_6_SDA                                     0x04000000
+#define NV_PPWR_OUTPUT_I2C_7_SDA                                     0x08000000
+#define NV_PPWR_OUTPUT_I2C_8_SDA                                     0x10000000
+#define NV_PPWR_OUTPUT_I2C_9_SDA                                     0x20000000
+#endif
+#define NV_PPWR_INPUT                                                    0x07c4
 #define NV_PPWR_OUTPUT_SET                                               0x07e0
 #define NV_PPWR_OUTPUT_SET_FB_PAUSE                                  0x00000004
 #define NV_PPWR_OUTPUT_CLR                                               0x07e4
@@ -125,6 +169,15 @@
 */	.b32 0 /*
 */	.skip 64
 
+#if NV_PPWR_CHIPSET < GK208
+#define imm32(reg,val) /*
+*/	movw reg  ((val) & 0x0000ffff) /*
+*/	sethi reg ((val) & 0xffff0000)
+#else
+#define imm32(reg,val) /*
+*/	mov reg (val)
+#endif
+
 #ifndef NVKM_FALCON_UNSHIFTED_IO
 #define nv_iord(reg,ior) /*
 */	mov reg ior /*
diff --git a/drivers/gpu/drm/nouveau/core/subdev/pwr/fuc/nv108.fuc b/drivers/gpu/drm/nouveau/core/subdev/pwr/fuc/nv108.fuc
index 947be536daefc..17a8a383d91a9 100644
--- a/drivers/gpu/drm/nouveau/core/subdev/pwr/fuc/nv108.fuc
+++ b/drivers/gpu/drm/nouveau/core/subdev/pwr/fuc/nv108.fuc
@@ -37,6 +37,7 @@
 #include "host.fuc"
 #include "memx.fuc"
 #include "perf.fuc"
+#include "i2c_.fuc"
 #include "test.fuc"
 #include "idle.fuc"
 #undef INCLUDE_PROC
@@ -46,6 +47,7 @@
 #include "host.fuc"
 #include "memx.fuc"
 #include "perf.fuc"
+#include "i2c_.fuc"
 #include "test.fuc"
 #include "idle.fuc"
 #undef INCLUDE_DATA
@@ -57,6 +59,7 @@
 #include "host.fuc"
 #include "memx.fuc"
 #include "perf.fuc"
+#include "i2c_.fuc"
 #include "test.fuc"
 #include "idle.fuc"
 #undef INCLUDE_CODE
diff --git a/drivers/gpu/drm/nouveau/core/subdev/pwr/fuc/nv108.fuc.h b/drivers/gpu/drm/nouveau/core/subdev/pwr/fuc/nv108.fuc.h
index 9342e2d7d3b79..4bd43a99fdccb 100644
--- a/drivers/gpu/drm/nouveau/core/subdev/pwr/fuc/nv108.fuc.h
+++ b/drivers/gpu/drm/nouveau/core/subdev/pwr/fuc/nv108.fuc.h
@@ -89,16 +89,9 @@ uint32_t nv108_pwr_data[] = {
 	0x00000000,
 	0x00000000,
 	0x00000000,
-	0x54534554,
-	0x00000494,
-	0x00000475,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
+	0x5f433249,
+	0x00000877,
+	0x0000071e,
 	0x00000000,
 	0x00000000,
 	0x00000000,
@@ -111,16 +104,6 @@ uint32_t nv108_pwr_data[] = {
 	0x00000000,
 	0x00000000,
 	0x00000000,
-	0x454c4449,
-	0x0000049f,
-	0x0000049d,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
 	0x00000000,
 	0x00000000,
 	0x00000000,
@@ -128,17 +111,16 @@ uint32_t nv108_pwr_data[] = {
 	0x00000000,
 	0x00000000,
 	0x00000000,
+	0x54534554,
+	0x00000898,
+	0x00000879,
 	0x00000000,
 	0x00000000,
 	0x00000000,
 	0x00000000,
 	0x00000000,
-/* 0x0210: proc_list_tail */
-/* 0x0210: time_prev */
 	0x00000000,
-/* 0x0214: time_next */
 	0x00000000,
-/* 0x0218: fifo_queue */
 	0x00000000,
 	0x00000000,
 	0x00000000,
@@ -151,6 +133,9 @@ uint32_t nv108_pwr_data[] = {
 	0x00000000,
 	0x00000000,
 	0x00000000,
+	0x454c4449,
+	0x000008a3,
+	0x000008a1,
 	0x00000000,
 	0x00000000,
 	0x00000000,
@@ -170,9 +155,12 @@ uint32_t nv108_pwr_data[] = {
 	0x00000000,
 	0x00000000,
 	0x00000000,
+/* 0x0268: proc_list_tail */
+/* 0x0268: time_prev */
 	0x00000000,
-/* 0x0298: rfifo_queue */
+/* 0x026c: time_next */
 	0x00000000,
+/* 0x0270: fifo_queue */
 	0x00000000,
 	0x00000000,
 	0x00000000,
@@ -204,31 +192,8 @@ uint32_t nv108_pwr_data[] = {
 	0x00000000,
 	0x00000000,
 	0x00000000,
-/* 0x0318: memx_func_head */
-	0x00010000,
-	0x00000000,
-	0x000003a9,
-/* 0x0324: memx_func_next */
-	0x00000001,
-	0x00000000,
-	0x000003c7,
-	0x00000002,
-	0x00000002,
-	0x000003df,
-	0x00040003,
-	0x00000000,
-	0x00000407,
-	0x00010004,
-	0x00000000,
-	0x00000421,
-/* 0x0354: memx_func_tail */
-/* 0x0354: memx_data_head */
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
 	0x00000000,
+/* 0x02f0: rfifo_queue */
 	0x00000000,
 	0x00000000,
 	0x00000000,
@@ -261,10 +226,25 @@ uint32_t nv108_pwr_data[] = {
 	0x00000000,
 	0x00000000,
 	0x00000000,
+/* 0x0370: memx_func_head */
+	0x00010000,
 	0x00000000,
+	0x000003a9,
+/* 0x037c: memx_func_next */
+	0x00000001,
 	0x00000000,
+	0x000003c7,
+	0x00000002,
+	0x00000002,
+	0x000003df,
+	0x00040003,
 	0x00000000,
+	0x00000407,
+	0x00010004,
 	0x00000000,
+	0x00000421,
+/* 0x03ac: memx_func_tail */
+/* 0x03ac: memx_data_head */
 	0x00000000,
 	0x00000000,
 	0x00000000,
@@ -735,7 +715,6 @@ uint32_t nv108_pwr_data[] = {
 	0x00000000,
 	0x00000000,
 	0x00000000,
-/* 0x0b54: memx_data_tail */
 	0x00000000,
 	0x00000000,
 	0x00000000,
@@ -778,6 +757,29 @@ uint32_t nv108_pwr_data[] = {
 	0x00000000,
 	0x00000000,
 	0x00000000,
+/* 0x0bac: memx_data_tail */
+/* 0x0bac: i2c_scl_map */
+	0x00000400,
+	0x00000800,
+	0x00001000,
+	0x00002000,
+	0x00004000,
+	0x00008000,
+	0x00010000,
+	0x00020000,
+	0x00040000,
+	0x00080000,
+/* 0x0bd4: i2c_sda_map */
+	0x00100000,
+	0x00200000,
+	0x00400000,
+	0x00800000,
+	0x01000000,
+	0x02000000,
+	0x04000000,
+	0x08000000,
+	0x10000000,
+	0x20000000,
 	0x00000000,
 };
 
@@ -786,13 +788,13 @@ uint32_t nv108_pwr_code[] = {
 /* 0x0004: rd32 */
 	0xf607a040,
 	0x04bd000e,
-	0xe3f0010e,
+	0xd3f0010d,
 	0x07ac4001,
-	0xbd000ef6,
+	0xbd000df6,
 /* 0x0019: rd32_wait */
-	0x07ac4e04,
-	0xf100eecf,
-	0xf47000e4,
+	0x07ac4d04,
+	0xf100ddcf,
+	0xf47000d4,
 	0xa44df61b,
 	0x00ddcf07,
 /* 0x002e: wr32 */
@@ -800,14 +802,14 @@ uint32_t nv108_pwr_code[] = {
 	0x000ef607,
 	0xa44004bd,
 	0x000df607,
-	0x020e04bd,
-	0xf0f0e5f0,
-	0xac4001e3,
-	0x000ef607,
+	0x020d04bd,
+	0xf0f0d5f0,
+	0xac4001d3,
+	0x000df607,
 /* 0x004e: wr32_wait */
-	0xac4e04bd,
-	0x00eecf07,
-	0x7000e4f1,
+	0xac4d04bd,
+	0x00ddcf07,
+	0x7000d4f1,
 	0xf8f61bf4,
 /* 0x005d: nsec */
 	0xcf2c0800,
@@ -832,20 +834,20 @@ uint32_t nv108_pwr_code[] = {
 	0x03e99800,
 	0xf40096b0,
 	0x0a98280b,
-	0x029abb84,
+	0x029abb9a,
 	0x0d0e1cf4,
 	0x01de7e01,
 	0xf494bd00,
 /* 0x00b2: intr_watchdog_next_time */
 	0x0a98140e,
-	0x00a6b085,
+	0x00a6b09b,
 	0xa6080bf4,
 	0x061cf49a,
 /* 0x00c0: intr_watchdog_next_time_set */
 /* 0x00c3: intr_watchdog_next_proc */
-	0xb58509b5,
+	0xb59b09b5,
 	0xe0b603e9,
-	0x10e6b158,
+	0x68e6b158,
 	0xc81bf402,
 /* 0x00d2: intr */
 	0x00f900f8,
@@ -862,15 +864,15 @@ uint32_t nv108_pwr_code[] = {
 	0x080804bd,
 	0xc40088cf,
 	0x0bf40289,
-	0x8500b51f,
+	0x9b00b51f,
 	0x957e580e,
 	0x09980000,
-	0x0096b085,
+	0x0096b09b,
 	0x000d0bf4,
 	0x0009f634,
 	0x09b504bd,
 /* 0x0125: intr_skip_watchdog */
-	0x0089e484,
+	0x0089e49a,
 	0x360bf408,
 	0xcf068849,
 	0x9ac40099,
@@ -918,7 +920,7 @@ uint32_t nv108_pwr_code[] = {
 /* 0x01c6: timer_reset */
 	0x3400161e,
 	0xbd000ef6,
-	0x840eb504,
+	0x9a0eb504,
 /* 0x01d0: timer_enable */
 	0x38000108,
 	0xbd0008f6,
@@ -949,7 +951,7 @@ uint32_t nv108_pwr_code[] = {
 	0xa6008a98,
 	0x100bf4ae,
 	0xb15880b6,
-	0xf4021086,
+	0xf4026886,
 	0x32f4f11b,
 /* 0x0239: find_done */
 	0xfc8eb201,
@@ -1009,7 +1011,7 @@ uint32_t nv108_pwr_code[] = {
 	0x0bf412a6,
 	0x071ec42e,
 	0xb704ee94,
-	0x980218e0,
+	0x980270e0,
 	0xec9803eb,
 	0x01ed9802,
 	0x7e00ee98,
@@ -1031,7 +1033,7 @@ uint32_t nv108_pwr_code[] = {
 	0xf412a608,
 	0x23c4ef0b,
 	0x0434b607,
-	0x029830b7,
+	0x02f030b7,
 	0xb5033bb5,
 	0x3db5023c,
 	0x003eb501,
@@ -1044,11 +1046,11 @@ uint32_t nv108_pwr_code[] = {
 /* 0x0379: host_init */
 	0x00804100,
 	0xf11014b6,
-	0x40021815,
+	0x40027015,
 	0x01f604d0,
 	0x4104bd00,
 	0x14b60080,
-	0x9815f110,
+	0xf015f110,
 	0x04dc4002,
 	0xbd0001f6,
 	0x40010104,
@@ -1101,13 +1103,13 @@ uint32_t nv108_pwr_code[] = {
 	0x001398b2,
 	0x950410b6,
 	0x30f01034,
-	0xc835980c,
+	0xde35980c,
 	0x12a655f9,
 	0xfced1ef4,
 	0x7ee0fcd0,
 	0xf800023f,
 /* 0x0455: memx_info */
-	0x03544c00,
+	0x03ac4c00,
 	0x7e08004b,
 	0xf800023f,
 /* 0x0461: memx_recv */
@@ -1119,7 +1121,301 @@ uint32_t nv108_pwr_code[] = {
 /* 0x0471: perf_recv */
 /* 0x0473: perf_init */
 	0xf800f800,
-/* 0x0475: test_recv */
+/* 0x0475: i2c_drive_scl */
+	0x0036b000,
+	0x400d0bf4,
+	0x01f607e0,
+	0xf804bd00,
+/* 0x0485: i2c_drive_scl_lo */
+	0x07e44000,
+	0xbd0001f6,
+/* 0x048f: i2c_drive_sda */
+	0xb000f804,
+	0x0bf40036,
+	0x07e0400d,
+	0xbd0002f6,
+/* 0x049f: i2c_drive_sda_lo */
+	0x4000f804,
+	0x02f607e4,
+	0xf804bd00,
+/* 0x04a9: i2c_sense_scl */
+	0x0132f400,
+	0xcf07c443,
+	0x31fd0033,
+	0x060bf404,
+/* 0x04bb: i2c_sense_scl_done */
+	0xf80131f4,
+/* 0x04bd: i2c_sense_sda */
+	0x0132f400,
+	0xcf07c443,
+	0x32fd0033,
+	0x060bf404,
+/* 0x04cf: i2c_sense_sda_done */
+	0xf80131f4,
+/* 0x04d1: i2c_raise_scl */
+	0x4440f900,
+	0x01030898,
+	0x0004757e,
+/* 0x04dc: i2c_raise_scl_wait */
+	0x7e03e84e,
+	0x7e00005d,
+	0xf40004a9,
+	0x42b60901,
+	0xef1bf401,
+/* 0x04f0: i2c_raise_scl_done */
+	0x00f840fc,
+/* 0x04f4: i2c_start */
+	0x0004a97e,
+	0x7e0d11f4,
+	0xf40004bd,
+	0x0ef40611,
+/* 0x0505: i2c_start_rep */
+	0x7e00032e,
+	0x03000475,
+	0x048f7e01,
+	0x0076bb00,
+	0xf90465b6,
+	0x04659450,
+	0xbd0256bb,
+	0x0475fd50,
+	0xd17e50fc,
+	0x64b60004,
+	0x1d11f404,
+/* 0x0530: i2c_start_send */
+	0x8f7e0003,
+	0x884e0004,
+	0x005d7e13,
+	0x7e000300,
+	0x4e000475,
+	0x5d7e1388,
+/* 0x054a: i2c_start_out */
+	0x00f80000,
+/* 0x054c: i2c_stop */
+	0x757e0003,
+	0x00030004,
+	0x00048f7e,
+	0x7e03e84e,
+	0x0300005d,
+	0x04757e01,
+	0x13884e00,
+	0x00005d7e,
+	0x8f7e0103,
+	0x884e0004,
+	0x005d7e13,
+/* 0x057b: i2c_bitw */
+	0x7e00f800,
+	0x4e00048f,
+	0x5d7e03e8,
+	0x76bb0000,
+	0x0465b600,
+	0x659450f9,
+	0x0256bb04,
+	0x75fd50bd,
+	0x7e50fc04,
+	0xb60004d1,
+	0x11f40464,
+	0x13884e17,
+	0x00005d7e,
+	0x757e0003,
+	0x884e0004,
+	0x005d7e13,
+/* 0x05b9: i2c_bitw_out */
+/* 0x05bb: i2c_bitr */
+	0x0300f800,
+	0x048f7e01,
+	0x03e84e00,
+	0x00005d7e,
+	0xb60076bb,
+	0x50f90465,
+	0xbb046594,
+	0x50bd0256,
+	0xfc0475fd,
+	0x04d17e50,
+	0x0464b600,
+	0x7e1a11f4,
+	0x030004bd,
+	0x04757e00,
+	0x13884e00,
+	0x00005d7e,
+	0xf4013cf0,
+/* 0x05fe: i2c_bitr_done */
+	0x00f80131,
+/* 0x0600: i2c_get_byte */
+	0x08040005,
+/* 0x0604: i2c_get_byte_next */
+	0xbb0154b6,
+	0x65b60076,
+	0x9450f904,
+	0x56bb0465,
+	0xfd50bd02,
+	0x50fc0475,
+	0x0005bb7e,
+	0xf40464b6,
+	0x53fd2a11,
+	0x0142b605,
+	0x03d81bf4,
+	0x0076bb01,
+	0xf90465b6,
+	0x04659450,
+	0xbd0256bb,
+	0x0475fd50,
+	0x7b7e50fc,
+	0x64b60005,
+/* 0x064d: i2c_get_byte_done */
+/* 0x064f: i2c_put_byte */
+	0x0400f804,
+/* 0x0651: i2c_put_byte_next */
+	0x0142b608,
+	0xbb3854ff,
+	0x65b60076,
+	0x9450f904,
+	0x56bb0465,
+	0xfd50bd02,
+	0x50fc0475,
+	0x00057b7e,
+	0xf40464b6,
+	0x46b03411,
+	0xd81bf400,
+	0xb60076bb,
+	0x50f90465,
+	0xbb046594,
+	0x50bd0256,
+	0xfc0475fd,
+	0x05bb7e50,
+	0x0464b600,
+	0xbb0f11f4,
+	0x36b00076,
+	0x061bf401,
+/* 0x06a7: i2c_put_byte_done */
+	0xf80132f4,
+/* 0x06a9: i2c_addr */
+	0x0076bb00,
+	0xf90465b6,
+	0x04659450,
+	0xbd0256bb,
+	0x0475fd50,
+	0xf47e50fc,
+	0x64b60004,
+	0x2911f404,
+	0x012ec3e7,
+	0xfd0134b6,
+	0x76bb0553,
+	0x0465b600,
+	0x659450f9,
+	0x0256bb04,
+	0x75fd50bd,
+	0x7e50fc04,
+	0xb600064f,
+/* 0x06ee: i2c_addr_done */
+	0x00f80464,
+/* 0x06f0: i2c_acquire_addr */
+	0xb6f8cec7,
+	0xe0b705e4,
+	0x00f8d014,
+/* 0x06fc: i2c_acquire */
+	0x0006f07e,
+	0x0000047e,
+	0x7e03d9f0,
+	0xf800002e,
+/* 0x070d: i2c_release */
+	0x06f07e00,
+	0x00047e00,
+	0x03daf000,
+	0x00002e7e,
+/* 0x071e: i2c_recv */
+	0x32f400f8,
+	0xf8c1c701,
+	0xb00214b6,
+	0x1ff52816,
+	0x13b80137,
+	0x98000bd4,
+	0x13b80032,
+	0x98000bac,
+	0x31f40031,
+	0xf9d0f902,
+	0xf1d0f9e0,
+	0xf1000067,
+	0x92100063,
+	0x76bb0167,
+	0x0465b600,
+	0x659450f9,
+	0x0256bb04,
+	0x75fd50bd,
+	0x7e50fc04,
+	0xb60006fc,
+	0xd0fc0464,
+	0xf500d6b0,
+	0x0500b01b,
+	0x0076bb00,
+	0xf90465b6,
+	0x04659450,
+	0xbd0256bb,
+	0x0475fd50,
+	0xa97e50fc,
+	0x64b60006,
+	0xcc11f504,
+	0xe0c5c700,
+	0xb60076bb,
+	0x50f90465,
+	0xbb046594,
+	0x50bd0256,
+	0xfc0475fd,
+	0x064f7e50,
+	0x0464b600,
+	0x00a911f5,
+	0x76bb0105,
+	0x0465b600,
+	0x659450f9,
+	0x0256bb04,
+	0x75fd50bd,
+	0x7e50fc04,
+	0xb60006a9,
+	0x11f50464,
+	0x76bb0087,
+	0x0465b600,
+	0x659450f9,
+	0x0256bb04,
+	0x75fd50bd,
+	0x7e50fc04,
+	0xb6000600,
+	0x11f40464,
+	0xe05bcb67,
+	0xb60076bb,
+	0x50f90465,
+	0xbb046594,
+	0x50bd0256,
+	0xfc0475fd,
+	0x054c7e50,
+	0x0464b600,
+	0x74bd5bb2,
+/* 0x0823: i2c_recv_not_rd08 */
+	0xb0410ef4,
+	0x1bf401d6,
+	0x7e00053b,
+	0xf40006a9,
+	0xc5c73211,
+	0x064f7ee0,
+	0x2811f400,
+	0xa97e0005,
+	0x11f40006,
+	0xe0b5c71f,
+	0x00064f7e,
+	0x7e1511f4,
+	0xbd00054c,
+	0x08c5c774,
+	0xf4091bf4,
+	0x0ef40232,
+/* 0x0861: i2c_recv_not_wr08 */
+/* 0x0861: i2c_recv_done */
+	0xf8cec703,
+	0x00070d7e,
+	0xd0fce0fc,
+	0xb20912f4,
+	0x023f7e7c,
+/* 0x0875: i2c_recv_exit */
+/* 0x0877: i2c_init */
+	0xf800f800,
+/* 0x0879: test_recv */
 	0x04584100,
 	0xb60011cf,
 	0x58400110,
@@ -1128,26 +1424,26 @@ uint32_t nv108_pwr_code[] = {
 	0xe3f1d900,
 	0x967e134f,
 	0x00f80001,
-/* 0x0494: test_init */
+/* 0x0898: test_init */
 	0x7e08004e,
 	0xf8000196,
-/* 0x049d: idle_recv */
-/* 0x049f: idle */
+/* 0x08a1: idle_recv */
+/* 0x08a3: idle */
 	0xf400f800,
 	0x54410031,
 	0x0011cf04,
 	0x400110b6,
 	0x01f60454,
-/* 0x04b3: idle_loop */
+/* 0x08b7: idle_loop */
 	0x0104bd00,
 	0x0232f458,
-/* 0x04b8: idle_proc */
-/* 0x04b8: idle_proc_exec */
+/* 0x08bc: idle_proc */
+/* 0x08bc: idle_proc_exec */
 	0x1eb210f9,
 	0x0002487e,
 	0x11f410fc,
 	0x0231f409,
-/* 0x04cb: idle_proc_next */
+/* 0x08cf: idle_proc_next */
 	0xb6f00ef4,
 	0x1fa65810,
 	0xf4e81bf4,
@@ -1161,5 +1457,4 @@ uint32_t nv108_pwr_code[] = {
 	0x00000000,
 	0x00000000,
 	0x00000000,
-	0x00000000,
 };
diff --git a/drivers/gpu/drm/nouveau/core/subdev/pwr/fuc/nva3.fuc b/drivers/gpu/drm/nouveau/core/subdev/pwr/fuc/nva3.fuc
index 6fde0b89e5aa6..6744fcc061516 100644
--- a/drivers/gpu/drm/nouveau/core/subdev/pwr/fuc/nva3.fuc
+++ b/drivers/gpu/drm/nouveau/core/subdev/pwr/fuc/nva3.fuc
@@ -37,6 +37,7 @@
 #include "host.fuc"
 #include "memx.fuc"
 #include "perf.fuc"
+#include "i2c_.fuc"
 #include "test.fuc"
 #include "idle.fuc"
 #undef INCLUDE_PROC
@@ -46,6 +47,7 @@
 #include "host.fuc"
 #include "memx.fuc"
 #include "perf.fuc"
+#include "i2c_.fuc"
 #include "test.fuc"
 #include "idle.fuc"
 #undef INCLUDE_DATA
@@ -57,6 +59,7 @@
 #include "host.fuc"
 #include "memx.fuc"
 #include "perf.fuc"
+#include "i2c_.fuc"
 #include "test.fuc"
 #include "idle.fuc"
 #undef INCLUDE_CODE
diff --git a/drivers/gpu/drm/nouveau/core/subdev/pwr/fuc/nva3.fuc.h b/drivers/gpu/drm/nouveau/core/subdev/pwr/fuc/nva3.fuc.h
index 0fa4d7dcd407b..5a73fa620978a 100644
--- a/drivers/gpu/drm/nouveau/core/subdev/pwr/fuc/nva3.fuc.h
+++ b/drivers/gpu/drm/nouveau/core/subdev/pwr/fuc/nva3.fuc.h
@@ -89,9 +89,31 @@ uint32_t nva3_pwr_data[] = {
 	0x00000000,
 	0x00000000,
 	0x00000000,
+	0x5f433249,
+	0x00000982,
+	0x00000825,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
 	0x54534554,
-	0x0000057b,
-	0x00000554,
+	0x000009ab,
+	0x00000984,
 	0x00000000,
 	0x00000000,
 	0x00000000,
@@ -112,8 +134,8 @@ uint32_t nva3_pwr_data[] = {
 	0x00000000,
 	0x00000000,
 	0x454c4449,
-	0x00000587,
-	0x00000585,
+	0x000009b7,
+	0x000009b5,
 	0x00000000,
 	0x00000000,
 	0x00000000,
@@ -133,12 +155,12 @@ uint32_t nva3_pwr_data[] = {
 	0x00000000,
 	0x00000000,
 	0x00000000,
-/* 0x0210: proc_list_tail */
-/* 0x0210: time_prev */
+/* 0x0268: proc_list_tail */
+/* 0x0268: time_prev */
 	0x00000000,
-/* 0x0214: time_next */
+/* 0x026c: time_next */
 	0x00000000,
-/* 0x0218: fifo_queue */
+/* 0x0270: fifo_queue */
 	0x00000000,
 	0x00000000,
 	0x00000000,
@@ -171,7 +193,7 @@ uint32_t nva3_pwr_data[] = {
 	0x00000000,
 	0x00000000,
 	0x00000000,
-/* 0x0298: rfifo_queue */
+/* 0x02f0: rfifo_queue */
 	0x00000000,
 	0x00000000,
 	0x00000000,
@@ -204,11 +226,11 @@ uint32_t nva3_pwr_data[] = {
 	0x00000000,
 	0x00000000,
 	0x00000000,
-/* 0x0318: memx_func_head */
+/* 0x0370: memx_func_head */
 	0x00010000,
 	0x00000000,
 	0x0000046f,
-/* 0x0324: memx_func_next */
+/* 0x037c: memx_func_next */
 	0x00000001,
 	0x00000000,
 	0x00000496,
@@ -221,8 +243,18 @@ uint32_t nva3_pwr_data[] = {
 	0x00010004,
 	0x00000000,
 	0x000004fc,
-/* 0x0354: memx_func_tail */
-/* 0x0354: memx_data_head */
+/* 0x03ac: memx_func_tail */
+/* 0x03ac: memx_data_head */
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
 	0x00000000,
 	0x00000000,
 	0x00000000,
@@ -725,6 +757,42 @@ uint32_t nva3_pwr_data[] = {
 	0x00000000,
 	0x00000000,
 	0x00000000,
+/* 0x0bac: memx_data_tail */
+/* 0x0bac: i2c_scl_map */
+	0x00001000,
+	0x00004000,
+	0x00010000,
+	0x00000100,
+	0x00040000,
+	0x00100000,
+	0x00400000,
+	0x01000000,
+	0x04000000,
+	0x10000000,
+/* 0x0bd4: i2c_sda_map */
+	0x00002000,
+	0x00008000,
+	0x00020000,
+	0x00000200,
+	0x00080000,
+	0x00200000,
+	0x00800000,
+	0x02000000,
+	0x08000000,
+	0x20000000,
+/* 0x0bfc: i2c_ctrl */
+	0x0000e138,
+	0x0000e150,
+	0x0000e168,
+	0x0000e180,
+	0x0000e254,
+	0x0000e274,
+	0x0000e764,
+	0x0000e780,
+	0x0000e79c,
+	0x0000e7b8,
+	0x00000000,
+	0x00000000,
 	0x00000000,
 	0x00000000,
 	0x00000000,
@@ -735,7 +803,6 @@ uint32_t nva3_pwr_data[] = {
 	0x00000000,
 	0x00000000,
 	0x00000000,
-/* 0x0b54: memx_data_tail */
 	0x00000000,
 	0x00000000,
 	0x00000000,
@@ -787,15 +854,15 @@ uint32_t nva3_pwr_code[] = {
 	0x07a007f1,
 	0xd00604b6,
 	0x04bd000e,
-	0xf001e7f0,
-	0x07f101e3,
+	0xf001d7f0,
+	0x07f101d3,
 	0x04b607ac,
-	0x000ed006,
+	0x000dd006,
 /* 0x0022: rd32_wait */
-	0xe7f104bd,
-	0xe4b607ac,
-	0x00eecf06,
-	0x7000e4f1,
+	0xd7f104bd,
+	0xd4b607ac,
+	0x00ddcf06,
+	0x7000d4f1,
 	0xf1f21bf4,
 	0xb607a4d7,
 	0xddcf06d4,
@@ -807,15 +874,15 @@ uint32_t nva3_pwr_code[] = {
 	0xb607a407,
 	0x0dd00604,
 	0xf004bd00,
-	0xe5f002e7,
-	0x01e3f0f0,
+	0xd5f002d7,
+	0x01d3f0f0,
 	0x07ac07f1,
 	0xd00604b6,
-	0x04bd000e,
+	0x04bd000d,
 /* 0x006c: wr32_wait */
-	0x07ace7f1,
-	0xcf06e4b6,
-	0xe4f100ee,
+	0x07acd7f1,
+	0xcf06d4b6,
+	0xd4f100dd,
 	0x1bf47000,
 /* 0x007f: nsec */
 	0xf000f8f2,
@@ -845,21 +912,21 @@ uint32_t nva3_pwr_code[] = {
 	0x9800f8df,
 	0x96b003e9,
 	0x2a0bf400,
-	0xbb840a98,
+	0xbb9a0a98,
 	0x1cf4029a,
 	0x01d7f00f,
 	0x025421f5,
 	0x0ef494bd,
 /* 0x00e9: intr_watchdog_next_time */
-	0x850a9815,
+	0x9b0a9815,
 	0xf400a6b0,
 	0x9ab8090b,
 	0x061cf406,
 /* 0x00f8: intr_watchdog_next_time_set */
 /* 0x00fb: intr_watchdog_next_proc */
-	0x80850980,
+	0x809b0980,
 	0xe0b603e9,
-	0x10e6b158,
+	0x68e6b158,
 	0xc61bf402,
 /* 0x010a: intr */
 	0x00f900f8,
@@ -880,15 +947,15 @@ uint32_t nva3_pwr_code[] = {
 	0x0088cf06,
 	0xf40289c4,
 	0x0080230b,
-	0x58e7f085,
+	0x58e7f09b,
 	0x98cb21f4,
-	0x96b08509,
+	0x96b09b09,
 	0x110bf400,
 	0xb63407f0,
 	0x09d00604,
 	0x8004bd00,
 /* 0x016e: intr_skip_watchdog */
-	0x89e48409,
+	0x89e49a09,
 	0x0bf40800,
 	0x8897f148,
 	0x0694b606,
@@ -948,7 +1015,7 @@ uint32_t nva3_pwr_code[] = {
 	0x000ed006,
 	0x0e8004bd,
 /* 0x0241: timer_enable */
-	0x0187f084,
+	0x0187f09a,
 	0xb63807f0,
 	0x08d00604,
 /* 0x024f: timer_done */
@@ -979,7 +1046,7 @@ uint32_t nva3_pwr_code[] = {
 	0xb8008a98,
 	0x0bf406ae,
 	0x5880b610,
-	0x021086b1,
+	0x026886b1,
 	0xf4f01bf4,
 /* 0x02b2: find_done */
 	0x8eb90132,
@@ -1049,7 +1116,7 @@ uint32_t nva3_pwr_code[] = {
 	0x320bf406,
 	0x94071ec4,
 	0xe0b704ee,
-	0xeb980218,
+	0xeb980270,
 	0x02ec9803,
 	0x9801ed98,
 	0x21f500ee,
@@ -1075,7 +1142,7 @@ uint32_t nva3_pwr_code[] = {
 	0xe60bf406,
 	0xb60723c4,
 	0x30b70434,
-	0x3b800298,
+	0x3b8002f0,
 	0x023c8003,
 	0x80013d80,
 	0x20b6003e,
@@ -1090,13 +1157,13 @@ uint32_t nva3_pwr_code[] = {
 /* 0x0430: host_init */
 	0x008017f1,
 	0xf11014b6,
-	0xf1021815,
+	0xf1027015,
 	0xb604d007,
 	0x01d00604,
 	0xf104bd00,
 	0xb6008017,
 	0x15f11014,
-	0x07f10298,
+	0x07f102f0,
 	0x04b604dc,
 	0x0001d006,
 	0x17f004bd,
@@ -1156,14 +1223,14 @@ uint32_t nva3_pwr_code[] = {
 	0x00139802,
 	0x950410b6,
 	0x30f01034,
-	0xc835980c,
+	0xde35980c,
 	0x12b855f9,
 	0xec1ef406,
 	0xe0fcd0fc,
 	0x02b921f5,
 /* 0x0532: memx_info */
 	0xc7f100f8,
-	0xb7f10354,
+	0xb7f103ac,
 	0x21f50800,
 	0x00f802b9,
 /* 0x0540: memx_recv */
@@ -1175,7 +1242,312 @@ uint32_t nva3_pwr_code[] = {
 /* 0x0550: perf_recv */
 /* 0x0552: perf_init */
 	0x00f800f8,
-/* 0x0554: test_recv */
+/* 0x0554: i2c_drive_scl */
+	0xf40036b0,
+	0x07f1110b,
+	0x04b607e0,
+	0x0001d006,
+	0x00f804bd,
+/* 0x0568: i2c_drive_scl_lo */
+	0x07e407f1,
+	0xd00604b6,
+	0x04bd0001,
+/* 0x0576: i2c_drive_sda */
+	0x36b000f8,
+	0x110bf400,
+	0x07e007f1,
+	0xd00604b6,
+	0x04bd0002,
+/* 0x058a: i2c_drive_sda_lo */
+	0x07f100f8,
+	0x04b607e4,
+	0x0002d006,
+	0x00f804bd,
+/* 0x0598: i2c_sense_scl */
+	0xf10132f4,
+	0xb607c437,
+	0x33cf0634,
+	0x0431fd00,
+	0xf4060bf4,
+/* 0x05ae: i2c_sense_scl_done */
+	0x00f80131,
+/* 0x05b0: i2c_sense_sda */
+	0xf10132f4,
+	0xb607c437,
+	0x33cf0634,
+	0x0432fd00,
+	0xf4060bf4,
+/* 0x05c6: i2c_sense_sda_done */
+	0x00f80131,
+/* 0x05c8: i2c_raise_scl */
+	0x47f140f9,
+	0x37f00898,
+	0x5421f501,
+/* 0x05d5: i2c_raise_scl_wait */
+	0xe8e7f105,
+	0x7f21f403,
+	0x059821f5,
+	0xb60901f4,
+	0x1bf40142,
+/* 0x05e9: i2c_raise_scl_done */
+	0xf840fcef,
+/* 0x05ed: i2c_start */
+	0x9821f500,
+	0x0d11f405,
+	0x05b021f5,
+	0xf40611f4,
+/* 0x05fe: i2c_start_rep */
+	0x37f0300e,
+	0x5421f500,
+	0x0137f005,
+	0x057621f5,
+	0xb60076bb,
+	0x50f90465,
+	0xbb046594,
+	0x50bd0256,
+	0xfc0475fd,
+	0xc821f550,
+	0x0464b605,
+/* 0x062b: i2c_start_send */
+	0xf01f11f4,
+	0x21f50037,
+	0xe7f10576,
+	0x21f41388,
+	0x0037f07f,
+	0x055421f5,
+	0x1388e7f1,
+/* 0x0647: i2c_start_out */
+	0xf87f21f4,
+/* 0x0649: i2c_stop */
+	0x0037f000,
+	0x055421f5,
+	0xf50037f0,
+	0xf1057621,
+	0xf403e8e7,
+	0x37f07f21,
+	0x5421f501,
+	0x88e7f105,
+	0x7f21f413,
+	0xf50137f0,
+	0xf1057621,
+	0xf41388e7,
+	0x00f87f21,
+/* 0x067c: i2c_bitw */
+	0x057621f5,
+	0x03e8e7f1,
+	0xbb7f21f4,
+	0x65b60076,
+	0x9450f904,
+	0x56bb0465,
+	0xfd50bd02,
+	0x50fc0475,
+	0x05c821f5,
+	0xf40464b6,
+	0xe7f11811,
+	0x21f41388,
+	0x0037f07f,
+	0x055421f5,
+	0x1388e7f1,
+/* 0x06bb: i2c_bitw_out */
+	0xf87f21f4,
+/* 0x06bd: i2c_bitr */
+	0x0137f000,
+	0x057621f5,
+	0x03e8e7f1,
+	0xbb7f21f4,
+	0x65b60076,
+	0x9450f904,
+	0x56bb0465,
+	0xfd50bd02,
+	0x50fc0475,
+	0x05c821f5,
+	0xf40464b6,
+	0x21f51b11,
+	0x37f005b0,
+	0x5421f500,
+	0x88e7f105,
+	0x7f21f413,
+	0xf4013cf0,
+/* 0x0702: i2c_bitr_done */
+	0x00f80131,
+/* 0x0704: i2c_get_byte */
+	0xf00057f0,
+/* 0x070a: i2c_get_byte_next */
+	0x54b60847,
+	0x0076bb01,
+	0xf90465b6,
+	0x04659450,
+	0xbd0256bb,
+	0x0475fd50,
+	0x21f550fc,
+	0x64b606bd,
+	0x2b11f404,
+	0xb60553fd,
+	0x1bf40142,
+	0x0137f0d8,
+	0xb60076bb,
+	0x50f90465,
+	0xbb046594,
+	0x50bd0256,
+	0xfc0475fd,
+	0x7c21f550,
+	0x0464b606,
+/* 0x0754: i2c_get_byte_done */
+/* 0x0756: i2c_put_byte */
+	0x47f000f8,
+/* 0x0759: i2c_put_byte_next */
+	0x0142b608,
+	0xbb3854ff,
+	0x65b60076,
+	0x9450f904,
+	0x56bb0465,
+	0xfd50bd02,
+	0x50fc0475,
+	0x067c21f5,
+	0xf40464b6,
+	0x46b03411,
+	0xd81bf400,
+	0xb60076bb,
+	0x50f90465,
+	0xbb046594,
+	0x50bd0256,
+	0xfc0475fd,
+	0xbd21f550,
+	0x0464b606,
+	0xbb0f11f4,
+	0x36b00076,
+	0x061bf401,
+/* 0x07af: i2c_put_byte_done */
+	0xf80132f4,
+/* 0x07b1: i2c_addr */
+	0x0076bb00,
+	0xf90465b6,
+	0x04659450,
+	0xbd0256bb,
+	0x0475fd50,
+	0x21f550fc,
+	0x64b605ed,
+	0x2911f404,
+	0x012ec3e7,
+	0xfd0134b6,
+	0x76bb0553,
+	0x0465b600,
+	0x659450f9,
+	0x0256bb04,
+	0x75fd50bd,
+	0xf550fc04,
+	0xb6075621,
+/* 0x07f6: i2c_addr_done */
+	0x00f80464,
+/* 0x07f8: i2c_acquire_addr */
+	0xb6f8cec7,
+	0xe0b702e4,
+	0xee980bfc,
+/* 0x0807: i2c_acquire */
+	0xf500f800,
+	0xf407f821,
+	0xd9f00421,
+	0x3f21f403,
+/* 0x0816: i2c_release */
+	0x21f500f8,
+	0x21f407f8,
+	0x03daf004,
+	0xf83f21f4,
+/* 0x0825: i2c_recv */
+	0x0132f400,
+	0xb6f8c1c7,
+	0x16b00214,
+	0x3a1ff528,
+	0xd413a001,
+	0x0032980b,
+	0x0bac13a0,
+	0xf4003198,
+	0xd0f90231,
+	0xd0f9e0f9,
+	0x000067f1,
+	0x100063f1,
+	0xbb016792,
+	0x65b60076,
+	0x9450f904,
+	0x56bb0465,
+	0xfd50bd02,
+	0x50fc0475,
+	0x080721f5,
+	0xfc0464b6,
+	0x00d6b0d0,
+	0x00b31bf5,
+	0xbb0057f0,
+	0x65b60076,
+	0x9450f904,
+	0x56bb0465,
+	0xfd50bd02,
+	0x50fc0475,
+	0x07b121f5,
+	0xf50464b6,
+	0xc700d011,
+	0x76bbe0c5,
+	0x0465b600,
+	0x659450f9,
+	0x0256bb04,
+	0x75fd50bd,
+	0xf550fc04,
+	0xb6075621,
+	0x11f50464,
+	0x57f000ad,
+	0x0076bb01,
+	0xf90465b6,
+	0x04659450,
+	0xbd0256bb,
+	0x0475fd50,
+	0x21f550fc,
+	0x64b607b1,
+	0x8a11f504,
+	0x0076bb00,
+	0xf90465b6,
+	0x04659450,
+	0xbd0256bb,
+	0x0475fd50,
+	0x21f550fc,
+	0x64b60704,
+	0x6a11f404,
+	0xbbe05bcb,
+	0x65b60076,
+	0x9450f904,
+	0x56bb0465,
+	0xfd50bd02,
+	0x50fc0475,
+	0x064921f5,
+	0xb90464b6,
+	0x74bd025b,
+/* 0x092b: i2c_recv_not_rd08 */
+	0xb0430ef4,
+	0x1bf401d6,
+	0x0057f03d,
+	0x07b121f5,
+	0xc73311f4,
+	0x21f5e0c5,
+	0x11f40756,
+	0x0057f029,
+	0x07b121f5,
+	0xc71f11f4,
+	0x21f5e0b5,
+	0x11f40756,
+	0x4921f515,
+	0xc774bd06,
+	0x1bf408c5,
+	0x0232f409,
+/* 0x096b: i2c_recv_not_wr08 */
+/* 0x096b: i2c_recv_done */
+	0xc7030ef4,
+	0x21f5f8ce,
+	0xe0fc0816,
+	0x12f4d0fc,
+	0x027cb90a,
+	0x02b921f5,
+/* 0x0980: i2c_recv_exit */
+/* 0x0982: i2c_init */
+	0x00f800f8,
+/* 0x0984: test_recv */
 	0x05d817f1,
 	0xcf0614b6,
 	0x10b60011,
@@ -1185,12 +1557,12 @@ uint32_t nva3_pwr_code[] = {
 	0x00e7f104,
 	0x4fe3f1d9,
 	0xf521f513,
-/* 0x057b: test_init */
+/* 0x09ab: test_init */
 	0xf100f801,
 	0xf50800e7,
 	0xf801f521,
-/* 0x0585: idle_recv */
-/* 0x0587: idle */
+/* 0x09b5: idle_recv */
+/* 0x09b7: idle */
 	0xf400f800,
 	0x17f10031,
 	0x14b605d4,
@@ -1198,32 +1570,20 @@ uint32_t nva3_pwr_code[] = {
 	0xf10110b6,
 	0xb605d407,
 	0x01d00604,
-/* 0x05a3: idle_loop */
+/* 0x09d3: idle_loop */
 	0xf004bd00,
 	0x32f45817,
-/* 0x05a9: idle_proc */
-/* 0x05a9: idle_proc_exec */
+/* 0x09d9: idle_proc */
+/* 0x09d9: idle_proc_exec */
 	0xb910f902,
 	0x21f5021e,
 	0x10fc02c2,
 	0xf40911f4,
 	0x0ef40231,
-/* 0x05bd: idle_proc_next */
+/* 0x09ed: idle_proc_next */
 	0x5810b6ef,
 	0xf4061fb8,
 	0x02f4e61b,
 	0x0028f4dd,
 	0x00bb0ef4,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
 };
diff --git a/drivers/gpu/drm/nouveau/core/subdev/pwr/fuc/nvc0.fuc b/drivers/gpu/drm/nouveau/core/subdev/pwr/fuc/nvc0.fuc
index eaa64da68e360..48f79434a4491 100644
--- a/drivers/gpu/drm/nouveau/core/subdev/pwr/fuc/nvc0.fuc
+++ b/drivers/gpu/drm/nouveau/core/subdev/pwr/fuc/nvc0.fuc
@@ -37,6 +37,7 @@
 #include "host.fuc"
 #include "memx.fuc"
 #include "perf.fuc"
+#include "i2c_.fuc"
 #include "test.fuc"
 #include "idle.fuc"
 #undef INCLUDE_PROC
@@ -46,6 +47,7 @@
 #include "host.fuc"
 #include "memx.fuc"
 #include "perf.fuc"
+#include "i2c_.fuc"
 #include "test.fuc"
 #include "idle.fuc"
 #undef INCLUDE_DATA
@@ -57,6 +59,7 @@
 #include "host.fuc"
 #include "memx.fuc"
 #include "perf.fuc"
+#include "i2c_.fuc"
 #include "test.fuc"
 #include "idle.fuc"
 #undef INCLUDE_CODE
diff --git a/drivers/gpu/drm/nouveau/core/subdev/pwr/fuc/nvc0.fuc.h b/drivers/gpu/drm/nouveau/core/subdev/pwr/fuc/nvc0.fuc.h
index 82c8e8b889178..4dba00d2dd1a6 100644
--- a/drivers/gpu/drm/nouveau/core/subdev/pwr/fuc/nvc0.fuc.h
+++ b/drivers/gpu/drm/nouveau/core/subdev/pwr/fuc/nvc0.fuc.h
@@ -89,9 +89,31 @@ uint32_t nvc0_pwr_data[] = {
 	0x00000000,
 	0x00000000,
 	0x00000000,
+	0x5f433249,
+	0x00000982,
+	0x00000825,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
 	0x54534554,
-	0x0000057b,
-	0x00000554,
+	0x000009ab,
+	0x00000984,
 	0x00000000,
 	0x00000000,
 	0x00000000,
@@ -112,8 +134,8 @@ uint32_t nvc0_pwr_data[] = {
 	0x00000000,
 	0x00000000,
 	0x454c4449,
-	0x00000587,
-	0x00000585,
+	0x000009b7,
+	0x000009b5,
 	0x00000000,
 	0x00000000,
 	0x00000000,
@@ -133,12 +155,12 @@ uint32_t nvc0_pwr_data[] = {
 	0x00000000,
 	0x00000000,
 	0x00000000,
-/* 0x0210: proc_list_tail */
-/* 0x0210: time_prev */
+/* 0x0268: proc_list_tail */
+/* 0x0268: time_prev */
 	0x00000000,
-/* 0x0214: time_next */
+/* 0x026c: time_next */
 	0x00000000,
-/* 0x0218: fifo_queue */
+/* 0x0270: fifo_queue */
 	0x00000000,
 	0x00000000,
 	0x00000000,
@@ -171,7 +193,7 @@ uint32_t nvc0_pwr_data[] = {
 	0x00000000,
 	0x00000000,
 	0x00000000,
-/* 0x0298: rfifo_queue */
+/* 0x02f0: rfifo_queue */
 	0x00000000,
 	0x00000000,
 	0x00000000,
@@ -204,11 +226,11 @@ uint32_t nvc0_pwr_data[] = {
 	0x00000000,
 	0x00000000,
 	0x00000000,
-/* 0x0318: memx_func_head */
+/* 0x0370: memx_func_head */
 	0x00010000,
 	0x00000000,
 	0x0000046f,
-/* 0x0324: memx_func_next */
+/* 0x037c: memx_func_next */
 	0x00000001,
 	0x00000000,
 	0x00000496,
@@ -221,8 +243,18 @@ uint32_t nvc0_pwr_data[] = {
 	0x00010004,
 	0x00000000,
 	0x000004fc,
-/* 0x0354: memx_func_tail */
-/* 0x0354: memx_data_head */
+/* 0x03ac: memx_func_tail */
+/* 0x03ac: memx_data_head */
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
 	0x00000000,
 	0x00000000,
 	0x00000000,
@@ -725,6 +757,42 @@ uint32_t nvc0_pwr_data[] = {
 	0x00000000,
 	0x00000000,
 	0x00000000,
+/* 0x0bac: memx_data_tail */
+/* 0x0bac: i2c_scl_map */
+	0x00001000,
+	0x00004000,
+	0x00010000,
+	0x00000100,
+	0x00040000,
+	0x00100000,
+	0x00400000,
+	0x01000000,
+	0x04000000,
+	0x10000000,
+/* 0x0bd4: i2c_sda_map */
+	0x00002000,
+	0x00008000,
+	0x00020000,
+	0x00000200,
+	0x00080000,
+	0x00200000,
+	0x00800000,
+	0x02000000,
+	0x08000000,
+	0x20000000,
+/* 0x0bfc: i2c_ctrl */
+	0x0000e138,
+	0x0000e150,
+	0x0000e168,
+	0x0000e180,
+	0x0000e254,
+	0x0000e274,
+	0x0000e764,
+	0x0000e780,
+	0x0000e79c,
+	0x0000e7b8,
+	0x00000000,
+	0x00000000,
 	0x00000000,
 	0x00000000,
 	0x00000000,
@@ -735,7 +803,6 @@ uint32_t nvc0_pwr_data[] = {
 	0x00000000,
 	0x00000000,
 	0x00000000,
-/* 0x0b54: memx_data_tail */
 	0x00000000,
 	0x00000000,
 	0x00000000,
@@ -787,15 +854,15 @@ uint32_t nvc0_pwr_code[] = {
 	0x07a007f1,
 	0xd00604b6,
 	0x04bd000e,
-	0xf001e7f0,
-	0x07f101e3,
+	0xf001d7f0,
+	0x07f101d3,
 	0x04b607ac,
-	0x000ed006,
+	0x000dd006,
 /* 0x0022: rd32_wait */
-	0xe7f104bd,
-	0xe4b607ac,
-	0x00eecf06,
-	0x7000e4f1,
+	0xd7f104bd,
+	0xd4b607ac,
+	0x00ddcf06,
+	0x7000d4f1,
 	0xf1f21bf4,
 	0xb607a4d7,
 	0xddcf06d4,
@@ -807,15 +874,15 @@ uint32_t nvc0_pwr_code[] = {
 	0xb607a407,
 	0x0dd00604,
 	0xf004bd00,
-	0xe5f002e7,
-	0x01e3f0f0,
+	0xd5f002d7,
+	0x01d3f0f0,
 	0x07ac07f1,
 	0xd00604b6,
-	0x04bd000e,
+	0x04bd000d,
 /* 0x006c: wr32_wait */
-	0x07ace7f1,
-	0xcf06e4b6,
-	0xe4f100ee,
+	0x07acd7f1,
+	0xcf06d4b6,
+	0xd4f100dd,
 	0x1bf47000,
 /* 0x007f: nsec */
 	0xf000f8f2,
@@ -845,21 +912,21 @@ uint32_t nvc0_pwr_code[] = {
 	0x9800f8df,
 	0x96b003e9,
 	0x2a0bf400,
-	0xbb840a98,
+	0xbb9a0a98,
 	0x1cf4029a,
 	0x01d7f00f,
 	0x025421f5,
 	0x0ef494bd,
 /* 0x00e9: intr_watchdog_next_time */
-	0x850a9815,
+	0x9b0a9815,
 	0xf400a6b0,
 	0x9ab8090b,
 	0x061cf406,
 /* 0x00f8: intr_watchdog_next_time_set */
 /* 0x00fb: intr_watchdog_next_proc */
-	0x80850980,
+	0x809b0980,
 	0xe0b603e9,
-	0x10e6b158,
+	0x68e6b158,
 	0xc61bf402,
 /* 0x010a: intr */
 	0x00f900f8,
@@ -880,15 +947,15 @@ uint32_t nvc0_pwr_code[] = {
 	0x0088cf06,
 	0xf40289c4,
 	0x0080230b,
-	0x58e7f085,
+	0x58e7f09b,
 	0x98cb21f4,
-	0x96b08509,
+	0x96b09b09,
 	0x110bf400,
 	0xb63407f0,
 	0x09d00604,
 	0x8004bd00,
 /* 0x016e: intr_skip_watchdog */
-	0x89e48409,
+	0x89e49a09,
 	0x0bf40800,
 	0x8897f148,
 	0x0694b606,
@@ -948,7 +1015,7 @@ uint32_t nvc0_pwr_code[] = {
 	0x000ed006,
 	0x0e8004bd,
 /* 0x0241: timer_enable */
-	0x0187f084,
+	0x0187f09a,
 	0xb63807f0,
 	0x08d00604,
 /* 0x024f: timer_done */
@@ -979,7 +1046,7 @@ uint32_t nvc0_pwr_code[] = {
 	0xb8008a98,
 	0x0bf406ae,
 	0x5880b610,
-	0x021086b1,
+	0x026886b1,
 	0xf4f01bf4,
 /* 0x02b2: find_done */
 	0x8eb90132,
@@ -1049,7 +1116,7 @@ uint32_t nvc0_pwr_code[] = {
 	0x320bf406,
 	0x94071ec4,
 	0xe0b704ee,
-	0xeb980218,
+	0xeb980270,
 	0x02ec9803,
 	0x9801ed98,
 	0x21f500ee,
@@ -1075,7 +1142,7 @@ uint32_t nvc0_pwr_code[] = {
 	0xe60bf406,
 	0xb60723c4,
 	0x30b70434,
-	0x3b800298,
+	0x3b8002f0,
 	0x023c8003,
 	0x80013d80,
 	0x20b6003e,
@@ -1090,13 +1157,13 @@ uint32_t nvc0_pwr_code[] = {
 /* 0x0430: host_init */
 	0x008017f1,
 	0xf11014b6,
-	0xf1021815,
+	0xf1027015,
 	0xb604d007,
 	0x01d00604,
 	0xf104bd00,
 	0xb6008017,
 	0x15f11014,
-	0x07f10298,
+	0x07f102f0,
 	0x04b604dc,
 	0x0001d006,
 	0x17f004bd,
@@ -1156,14 +1223,14 @@ uint32_t nvc0_pwr_code[] = {
 	0x00139802,
 	0x950410b6,
 	0x30f01034,
-	0xc835980c,
+	0xde35980c,
 	0x12b855f9,
 	0xec1ef406,
 	0xe0fcd0fc,
 	0x02b921f5,
 /* 0x0532: memx_info */
 	0xc7f100f8,
-	0xb7f10354,
+	0xb7f103ac,
 	0x21f50800,
 	0x00f802b9,
 /* 0x0540: memx_recv */
@@ -1175,7 +1242,312 @@ uint32_t nvc0_pwr_code[] = {
 /* 0x0550: perf_recv */
 /* 0x0552: perf_init */
 	0x00f800f8,
-/* 0x0554: test_recv */
+/* 0x0554: i2c_drive_scl */
+	0xf40036b0,
+	0x07f1110b,
+	0x04b607e0,
+	0x0001d006,
+	0x00f804bd,
+/* 0x0568: i2c_drive_scl_lo */
+	0x07e407f1,
+	0xd00604b6,
+	0x04bd0001,
+/* 0x0576: i2c_drive_sda */
+	0x36b000f8,
+	0x110bf400,
+	0x07e007f1,
+	0xd00604b6,
+	0x04bd0002,
+/* 0x058a: i2c_drive_sda_lo */
+	0x07f100f8,
+	0x04b607e4,
+	0x0002d006,
+	0x00f804bd,
+/* 0x0598: i2c_sense_scl */
+	0xf10132f4,
+	0xb607c437,
+	0x33cf0634,
+	0x0431fd00,
+	0xf4060bf4,
+/* 0x05ae: i2c_sense_scl_done */
+	0x00f80131,
+/* 0x05b0: i2c_sense_sda */
+	0xf10132f4,
+	0xb607c437,
+	0x33cf0634,
+	0x0432fd00,
+	0xf4060bf4,
+/* 0x05c6: i2c_sense_sda_done */
+	0x00f80131,
+/* 0x05c8: i2c_raise_scl */
+	0x47f140f9,
+	0x37f00898,
+	0x5421f501,
+/* 0x05d5: i2c_raise_scl_wait */
+	0xe8e7f105,
+	0x7f21f403,
+	0x059821f5,
+	0xb60901f4,
+	0x1bf40142,
+/* 0x05e9: i2c_raise_scl_done */
+	0xf840fcef,
+/* 0x05ed: i2c_start */
+	0x9821f500,
+	0x0d11f405,
+	0x05b021f5,
+	0xf40611f4,
+/* 0x05fe: i2c_start_rep */
+	0x37f0300e,
+	0x5421f500,
+	0x0137f005,
+	0x057621f5,
+	0xb60076bb,
+	0x50f90465,
+	0xbb046594,
+	0x50bd0256,
+	0xfc0475fd,
+	0xc821f550,
+	0x0464b605,
+/* 0x062b: i2c_start_send */
+	0xf01f11f4,
+	0x21f50037,
+	0xe7f10576,
+	0x21f41388,
+	0x0037f07f,
+	0x055421f5,
+	0x1388e7f1,
+/* 0x0647: i2c_start_out */
+	0xf87f21f4,
+/* 0x0649: i2c_stop */
+	0x0037f000,
+	0x055421f5,
+	0xf50037f0,
+	0xf1057621,
+	0xf403e8e7,
+	0x37f07f21,
+	0x5421f501,
+	0x88e7f105,
+	0x7f21f413,
+	0xf50137f0,
+	0xf1057621,
+	0xf41388e7,
+	0x00f87f21,
+/* 0x067c: i2c_bitw */
+	0x057621f5,
+	0x03e8e7f1,
+	0xbb7f21f4,
+	0x65b60076,
+	0x9450f904,
+	0x56bb0465,
+	0xfd50bd02,
+	0x50fc0475,
+	0x05c821f5,
+	0xf40464b6,
+	0xe7f11811,
+	0x21f41388,
+	0x0037f07f,
+	0x055421f5,
+	0x1388e7f1,
+/* 0x06bb: i2c_bitw_out */
+	0xf87f21f4,
+/* 0x06bd: i2c_bitr */
+	0x0137f000,
+	0x057621f5,
+	0x03e8e7f1,
+	0xbb7f21f4,
+	0x65b60076,
+	0x9450f904,
+	0x56bb0465,
+	0xfd50bd02,
+	0x50fc0475,
+	0x05c821f5,
+	0xf40464b6,
+	0x21f51b11,
+	0x37f005b0,
+	0x5421f500,
+	0x88e7f105,
+	0x7f21f413,
+	0xf4013cf0,
+/* 0x0702: i2c_bitr_done */
+	0x00f80131,
+/* 0x0704: i2c_get_byte */
+	0xf00057f0,
+/* 0x070a: i2c_get_byte_next */
+	0x54b60847,
+	0x0076bb01,
+	0xf90465b6,
+	0x04659450,
+	0xbd0256bb,
+	0x0475fd50,
+	0x21f550fc,
+	0x64b606bd,
+	0x2b11f404,
+	0xb60553fd,
+	0x1bf40142,
+	0x0137f0d8,
+	0xb60076bb,
+	0x50f90465,
+	0xbb046594,
+	0x50bd0256,
+	0xfc0475fd,
+	0x7c21f550,
+	0x0464b606,
+/* 0x0754: i2c_get_byte_done */
+/* 0x0756: i2c_put_byte */
+	0x47f000f8,
+/* 0x0759: i2c_put_byte_next */
+	0x0142b608,
+	0xbb3854ff,
+	0x65b60076,
+	0x9450f904,
+	0x56bb0465,
+	0xfd50bd02,
+	0x50fc0475,
+	0x067c21f5,
+	0xf40464b6,
+	0x46b03411,
+	0xd81bf400,
+	0xb60076bb,
+	0x50f90465,
+	0xbb046594,
+	0x50bd0256,
+	0xfc0475fd,
+	0xbd21f550,
+	0x0464b606,
+	0xbb0f11f4,
+	0x36b00076,
+	0x061bf401,
+/* 0x07af: i2c_put_byte_done */
+	0xf80132f4,
+/* 0x07b1: i2c_addr */
+	0x0076bb00,
+	0xf90465b6,
+	0x04659450,
+	0xbd0256bb,
+	0x0475fd50,
+	0x21f550fc,
+	0x64b605ed,
+	0x2911f404,
+	0x012ec3e7,
+	0xfd0134b6,
+	0x76bb0553,
+	0x0465b600,
+	0x659450f9,
+	0x0256bb04,
+	0x75fd50bd,
+	0xf550fc04,
+	0xb6075621,
+/* 0x07f6: i2c_addr_done */
+	0x00f80464,
+/* 0x07f8: i2c_acquire_addr */
+	0xb6f8cec7,
+	0xe0b702e4,
+	0xee980bfc,
+/* 0x0807: i2c_acquire */
+	0xf500f800,
+	0xf407f821,
+	0xd9f00421,
+	0x3f21f403,
+/* 0x0816: i2c_release */
+	0x21f500f8,
+	0x21f407f8,
+	0x03daf004,
+	0xf83f21f4,
+/* 0x0825: i2c_recv */
+	0x0132f400,
+	0xb6f8c1c7,
+	0x16b00214,
+	0x3a1ff528,
+	0xd413a001,
+	0x0032980b,
+	0x0bac13a0,
+	0xf4003198,
+	0xd0f90231,
+	0xd0f9e0f9,
+	0x000067f1,
+	0x100063f1,
+	0xbb016792,
+	0x65b60076,
+	0x9450f904,
+	0x56bb0465,
+	0xfd50bd02,
+	0x50fc0475,
+	0x080721f5,
+	0xfc0464b6,
+	0x00d6b0d0,
+	0x00b31bf5,
+	0xbb0057f0,
+	0x65b60076,
+	0x9450f904,
+	0x56bb0465,
+	0xfd50bd02,
+	0x50fc0475,
+	0x07b121f5,
+	0xf50464b6,
+	0xc700d011,
+	0x76bbe0c5,
+	0x0465b600,
+	0x659450f9,
+	0x0256bb04,
+	0x75fd50bd,
+	0xf550fc04,
+	0xb6075621,
+	0x11f50464,
+	0x57f000ad,
+	0x0076bb01,
+	0xf90465b6,
+	0x04659450,
+	0xbd0256bb,
+	0x0475fd50,
+	0x21f550fc,
+	0x64b607b1,
+	0x8a11f504,
+	0x0076bb00,
+	0xf90465b6,
+	0x04659450,
+	0xbd0256bb,
+	0x0475fd50,
+	0x21f550fc,
+	0x64b60704,
+	0x6a11f404,
+	0xbbe05bcb,
+	0x65b60076,
+	0x9450f904,
+	0x56bb0465,
+	0xfd50bd02,
+	0x50fc0475,
+	0x064921f5,
+	0xb90464b6,
+	0x74bd025b,
+/* 0x092b: i2c_recv_not_rd08 */
+	0xb0430ef4,
+	0x1bf401d6,
+	0x0057f03d,
+	0x07b121f5,
+	0xc73311f4,
+	0x21f5e0c5,
+	0x11f40756,
+	0x0057f029,
+	0x07b121f5,
+	0xc71f11f4,
+	0x21f5e0b5,
+	0x11f40756,
+	0x4921f515,
+	0xc774bd06,
+	0x1bf408c5,
+	0x0232f409,
+/* 0x096b: i2c_recv_not_wr08 */
+/* 0x096b: i2c_recv_done */
+	0xc7030ef4,
+	0x21f5f8ce,
+	0xe0fc0816,
+	0x12f4d0fc,
+	0x027cb90a,
+	0x02b921f5,
+/* 0x0980: i2c_recv_exit */
+/* 0x0982: i2c_init */
+	0x00f800f8,
+/* 0x0984: test_recv */
 	0x05d817f1,
 	0xcf0614b6,
 	0x10b60011,
@@ -1185,12 +1557,12 @@ uint32_t nvc0_pwr_code[] = {
 	0x00e7f104,
 	0x4fe3f1d9,
 	0xf521f513,
-/* 0x057b: test_init */
+/* 0x09ab: test_init */
 	0xf100f801,
 	0xf50800e7,
 	0xf801f521,
-/* 0x0585: idle_recv */
-/* 0x0587: idle */
+/* 0x09b5: idle_recv */
+/* 0x09b7: idle */
 	0xf400f800,
 	0x17f10031,
 	0x14b605d4,
@@ -1198,32 +1570,20 @@ uint32_t nvc0_pwr_code[] = {
 	0xf10110b6,
 	0xb605d407,
 	0x01d00604,
-/* 0x05a3: idle_loop */
+/* 0x09d3: idle_loop */
 	0xf004bd00,
 	0x32f45817,
-/* 0x05a9: idle_proc */
-/* 0x05a9: idle_proc_exec */
+/* 0x09d9: idle_proc */
+/* 0x09d9: idle_proc_exec */
 	0xb910f902,
 	0x21f5021e,
 	0x10fc02c2,
 	0xf40911f4,
 	0x0ef40231,
-/* 0x05bd: idle_proc_next */
+/* 0x09ed: idle_proc_next */
 	0x5810b6ef,
 	0xf4061fb8,
 	0x02f4e61b,
 	0x0028f4dd,
 	0x00bb0ef4,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
 };
diff --git a/drivers/gpu/drm/nouveau/core/subdev/pwr/fuc/nvd0.fuc b/drivers/gpu/drm/nouveau/core/subdev/pwr/fuc/nvd0.fuc
index 32d65ea254dd8..8a89dfe41ce1b 100644
--- a/drivers/gpu/drm/nouveau/core/subdev/pwr/fuc/nvd0.fuc
+++ b/drivers/gpu/drm/nouveau/core/subdev/pwr/fuc/nvd0.fuc
@@ -37,6 +37,7 @@
 #include "host.fuc"
 #include "memx.fuc"
 #include "perf.fuc"
+#include "i2c_.fuc"
 #include "test.fuc"
 #include "idle.fuc"
 #undef INCLUDE_PROC
@@ -46,6 +47,7 @@
 #include "host.fuc"
 #include "memx.fuc"
 #include "perf.fuc"
+#include "i2c_.fuc"
 #include "test.fuc"
 #include "idle.fuc"
 #undef INCLUDE_DATA
@@ -57,6 +59,7 @@
 #include "host.fuc"
 #include "memx.fuc"
 #include "perf.fuc"
+#include "i2c_.fuc"
 #include "test.fuc"
 #include "idle.fuc"
 #undef INCLUDE_CODE
diff --git a/drivers/gpu/drm/nouveau/core/subdev/pwr/fuc/nvd0.fuc.h b/drivers/gpu/drm/nouveau/core/subdev/pwr/fuc/nvd0.fuc.h
index ce65e2a4b789b..5e24c6bc041d6 100644
--- a/drivers/gpu/drm/nouveau/core/subdev/pwr/fuc/nvd0.fuc.h
+++ b/drivers/gpu/drm/nouveau/core/subdev/pwr/fuc/nvd0.fuc.h
@@ -89,33 +89,13 @@ uint32_t nvd0_pwr_data[] = {
 	0x00000000,
 	0x00000000,
 	0x00000000,
-	0x54534554,
-	0x000004eb,
-	0x000004ca,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
+	0x5f433249,
+	0x000008e3,
+	0x00000786,
 	0x00000000,
 	0x00000000,
 	0x00000000,
 	0x00000000,
-	0x454c4449,
-	0x000004f7,
-	0x000004f5,
-	0x00000000,
-	0x00000000,
 	0x00000000,
 	0x00000000,
 	0x00000000,
@@ -131,14 +111,13 @@ uint32_t nvd0_pwr_data[] = {
 	0x00000000,
 	0x00000000,
 	0x00000000,
+	0x54534554,
+	0x00000906,
+	0x000008e5,
 	0x00000000,
 	0x00000000,
-/* 0x0210: proc_list_tail */
-/* 0x0210: time_prev */
 	0x00000000,
-/* 0x0214: time_next */
 	0x00000000,
-/* 0x0218: fifo_queue */
 	0x00000000,
 	0x00000000,
 	0x00000000,
@@ -154,6 +133,9 @@ uint32_t nvd0_pwr_data[] = {
 	0x00000000,
 	0x00000000,
 	0x00000000,
+	0x454c4449,
+	0x00000912,
+	0x00000910,
 	0x00000000,
 	0x00000000,
 	0x00000000,
@@ -171,11 +153,14 @@ uint32_t nvd0_pwr_data[] = {
 	0x00000000,
 	0x00000000,
 	0x00000000,
-/* 0x0298: rfifo_queue */
 	0x00000000,
 	0x00000000,
+/* 0x0268: proc_list_tail */
+/* 0x0268: time_prev */
 	0x00000000,
+/* 0x026c: time_next */
 	0x00000000,
+/* 0x0270: fifo_queue */
 	0x00000000,
 	0x00000000,
 	0x00000000,
@@ -204,31 +189,11 @@ uint32_t nvd0_pwr_data[] = {
 	0x00000000,
 	0x00000000,
 	0x00000000,
-/* 0x0318: memx_func_head */
-	0x00010000,
-	0x00000000,
-	0x000003f4,
-/* 0x0324: memx_func_next */
-	0x00000001,
-	0x00000000,
-	0x00000415,
-	0x00000002,
-	0x00000002,
-	0x00000430,
-	0x00040003,
-	0x00000000,
-	0x00000458,
-	0x00010004,
-	0x00000000,
-	0x00000472,
-/* 0x0354: memx_func_tail */
-/* 0x0354: memx_data_head */
-	0x00000000,
-	0x00000000,
 	0x00000000,
 	0x00000000,
 	0x00000000,
 	0x00000000,
+/* 0x02f0: rfifo_queue */
 	0x00000000,
 	0x00000000,
 	0x00000000,
@@ -261,10 +226,25 @@ uint32_t nvd0_pwr_data[] = {
 	0x00000000,
 	0x00000000,
 	0x00000000,
+/* 0x0370: memx_func_head */
+	0x00010000,
 	0x00000000,
+	0x000003f4,
+/* 0x037c: memx_func_next */
+	0x00000001,
 	0x00000000,
+	0x00000415,
+	0x00000002,
+	0x00000002,
+	0x00000430,
+	0x00040003,
 	0x00000000,
+	0x00000458,
+	0x00010004,
 	0x00000000,
+	0x00000472,
+/* 0x03ac: memx_func_tail */
+/* 0x03ac: memx_data_head */
 	0x00000000,
 	0x00000000,
 	0x00000000,
@@ -735,7 +715,6 @@ uint32_t nvd0_pwr_data[] = {
 	0x00000000,
 	0x00000000,
 	0x00000000,
-/* 0x0b54: memx_data_tail */
 	0x00000000,
 	0x00000000,
 	0x00000000,
@@ -778,6 +757,29 @@ uint32_t nvd0_pwr_data[] = {
 	0x00000000,
 	0x00000000,
 	0x00000000,
+/* 0x0bac: memx_data_tail */
+/* 0x0bac: i2c_scl_map */
+	0x00000400,
+	0x00000800,
+	0x00001000,
+	0x00002000,
+	0x00004000,
+	0x00008000,
+	0x00010000,
+	0x00020000,
+	0x00040000,
+	0x00080000,
+/* 0x0bd4: i2c_sda_map */
+	0x00100000,
+	0x00200000,
+	0x00400000,
+	0x00800000,
+	0x01000000,
+	0x02000000,
+	0x04000000,
+	0x08000000,
+	0x10000000,
+	0x20000000,
 	0x00000000,
 };
 
@@ -786,14 +788,14 @@ uint32_t nvd0_pwr_code[] = {
 /* 0x0004: rd32 */
 	0x07a007f1,
 	0xbd000ed0,
-	0x01e7f004,
-	0xf101e3f0,
+	0x01d7f004,
+	0xf101d3f0,
 	0xd007ac07,
-	0x04bd000e,
+	0x04bd000d,
 /* 0x001c: rd32_wait */
-	0x07ace7f1,
-	0xf100eecf,
-	0xf47000e4,
+	0x07acd7f1,
+	0xf100ddcf,
+	0xf47000d4,
 	0xd7f1f51b,
 	0xddcf07a4,
 /* 0x0033: wr32 */
@@ -802,14 +804,14 @@ uint32_t nvd0_pwr_code[] = {
 	0x04bd000e,
 	0x07a407f1,
 	0xbd000dd0,
-	0x02e7f004,
-	0xf0f0e5f0,
-	0x07f101e3,
-	0x0ed007ac,
+	0x02d7f004,
+	0xf0f0d5f0,
+	0x07f101d3,
+	0x0dd007ac,
 /* 0x0057: wr32_wait */
 	0xf104bd00,
-	0xcf07ace7,
-	0xe4f100ee,
+	0xcf07acd7,
+	0xd4f100dd,
 	0x1bf47000,
 /* 0x0067: nsec */
 	0xf000f8f5,
@@ -836,21 +838,21 @@ uint32_t nvd0_pwr_code[] = {
 	0x9800f8e2,
 	0x96b003e9,
 	0x2a0bf400,
-	0xbb840a98,
+	0xbb9a0a98,
 	0x1cf4029a,
 	0x01d7f00f,
 	0x020621f5,
 	0x0ef494bd,
 /* 0x00c5: intr_watchdog_next_time */
-	0x850a9815,
+	0x9b0a9815,
 	0xf400a6b0,
 	0x9ab8090b,
 	0x061cf406,
 /* 0x00d4: intr_watchdog_next_time_set */
 /* 0x00d7: intr_watchdog_next_proc */
-	0x80850980,
+	0x809b0980,
 	0xe0b603e9,
-	0x10e6b158,
+	0x68e6b158,
 	0xc61bf402,
 /* 0x00e6: intr */
 	0x00f900f8,
@@ -868,15 +870,15 @@ uint32_t nvd0_pwr_code[] = {
 	0x0887f004,
 	0xc40088cf,
 	0x0bf40289,
-	0x85008020,
+	0x9b008020,
 	0xf458e7f0,
 	0x0998a721,
-	0x0096b085,
+	0x0096b09b,
 	0xf00e0bf4,
 	0x09d03407,
 	0x8004bd00,
 /* 0x013e: intr_skip_watchdog */
-	0x89e48409,
+	0x89e49a09,
 	0x0bf40800,
 	0x8897f13c,
 	0x0099cf06,
@@ -929,7 +931,7 @@ uint32_t nvd0_pwr_code[] = {
 	0x0ed03407,
 	0x8004bd00,
 /* 0x01f6: timer_enable */
-	0x87f0840e,
+	0x87f09a0e,
 	0x3807f001,
 	0xbd0008d0,
 /* 0x0201: timer_done */
@@ -960,7 +962,7 @@ uint32_t nvd0_pwr_code[] = {
 	0x06aeb800,
 	0xb6100bf4,
 	0x86b15880,
-	0x1bf40210,
+	0x1bf40268,
 	0x0132f4f0,
 /* 0x0264: find_done */
 	0xfc028eb9,
@@ -1024,7 +1026,7 @@ uint32_t nvd0_pwr_code[] = {
 	0x0bf40612,
 	0x071ec42f,
 	0xb704ee94,
-	0x980218e0,
+	0x980270e0,
 	0xec9803eb,
 	0x01ed9802,
 	0xf500ee98,
@@ -1048,7 +1050,7 @@ uint32_t nvd0_pwr_code[] = {
 	0xec0bf406,
 	0xb60723c4,
 	0x30b70434,
-	0x3b800298,
+	0x3b8002f0,
 	0x023c8003,
 	0x80013d80,
 	0x20b6003e,
@@ -1061,12 +1063,12 @@ uint32_t nvd0_pwr_code[] = {
 /* 0x03be: host_init */
 	0x17f100f8,
 	0x14b60080,
-	0x1815f110,
+	0x7015f110,
 	0xd007f102,
 	0x0001d004,
 	0x17f104bd,
 	0x14b60080,
-	0x9815f110,
+	0xf015f110,
 	0xdc07f102,
 	0x0001d004,
 	0x17f004bd,
@@ -1122,13 +1124,13 @@ uint32_t nvd0_pwr_code[] = {
 	0x10b60013,
 	0x10349504,
 	0x980c30f0,
-	0x55f9c835,
+	0x55f9de35,
 	0xf40612b8,
 	0xd0fcec1e,
 	0x21f5e0fc,
 	0x00f8026b,
 /* 0x04a8: memx_info */
-	0x0354c7f1,
+	0x03acc7f1,
 	0x0800b7f1,
 	0x026b21f5,
 /* 0x04b6: memx_recv */
@@ -1140,49 +1142,342 @@ uint32_t nvd0_pwr_code[] = {
 /* 0x04c6: perf_recv */
 	0x00f800f8,
 /* 0x04c8: perf_init */
-/* 0x04ca: test_recv */
-	0x17f100f8,
-	0x11cf05d8,
-	0x0110b600,
-	0x05d807f1,
+/* 0x04ca: i2c_drive_scl */
+	0x36b000f8,
+	0x0e0bf400,
+	0x07e007f1,
 	0xbd0001d0,
-	0x00e7f104,
-	0x4fe3f1d9,
-	0xb621f513,
-/* 0x04eb: test_init */
-	0xf100f801,
-	0xf50800e7,
-	0xf801b621,
-/* 0x04f5: idle_recv */
-/* 0x04f7: idle */
-	0xf400f800,
-	0x17f10031,
-	0x11cf05d4,
-	0x0110b600,
-	0x05d407f1,
-	0xbd0001d0,
-/* 0x050d: idle_loop */
-	0x5817f004,
-/* 0x0513: idle_proc */
-/* 0x0513: idle_proc_exec */
-	0xf90232f4,
-	0x021eb910,
-	0x027421f5,
-	0x11f410fc,
-	0x0231f409,
-/* 0x0527: idle_proc_next */
-	0xb6ef0ef4,
-	0x1fb85810,
-	0xe61bf406,
-	0xf4dd02f4,
-	0x0ef40028,
-	0x000000c1,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
+/* 0x04db: i2c_drive_scl_lo */
+	0xf100f804,
+	0xd007e407,
+	0x04bd0001,
+/* 0x04e6: i2c_drive_sda */
+	0x36b000f8,
+	0x0e0bf400,
+	0x07e007f1,
+	0xbd0002d0,
+/* 0x04f7: i2c_drive_sda_lo */
+	0xf100f804,
+	0xd007e407,
+	0x04bd0002,
+/* 0x0502: i2c_sense_scl */
+	0x32f400f8,
+	0xc437f101,
+	0x0033cf07,
+	0xf40431fd,
+	0x31f4060b,
+/* 0x0515: i2c_sense_scl_done */
+/* 0x0517: i2c_sense_sda */
+	0xf400f801,
+	0x37f10132,
+	0x33cf07c4,
+	0x0432fd00,
+	0xf4060bf4,
+/* 0x052a: i2c_sense_sda_done */
+	0x00f80131,
+/* 0x052c: i2c_raise_scl */
+	0x47f140f9,
+	0x37f00898,
+	0xca21f501,
+/* 0x0539: i2c_raise_scl_wait */
+	0xe8e7f104,
+	0x6721f403,
+	0x050221f5,
+	0xb60901f4,
+	0x1bf40142,
+/* 0x054d: i2c_raise_scl_done */
+	0xf840fcef,
+/* 0x0551: i2c_start */
+	0x0221f500,
+	0x0d11f405,
+	0x051721f5,
+	0xf40611f4,
+/* 0x0562: i2c_start_rep */
+	0x37f0300e,
+	0xca21f500,
+	0x0137f004,
+	0x04e621f5,
+	0xb60076bb,
+	0x50f90465,
+	0xbb046594,
+	0x50bd0256,
+	0xfc0475fd,
+	0x2c21f550,
+	0x0464b605,
+/* 0x058f: i2c_start_send */
+	0xf01f11f4,
+	0x21f50037,
+	0xe7f104e6,
+	0x21f41388,
+	0x0037f067,
+	0x04ca21f5,
+	0x1388e7f1,
+/* 0x05ab: i2c_start_out */
+	0xf86721f4,
+/* 0x05ad: i2c_stop */
+	0x0037f000,
+	0x04ca21f5,
+	0xf50037f0,
+	0xf104e621,
+	0xf403e8e7,
+	0x37f06721,
+	0xca21f501,
+	0x88e7f104,
+	0x6721f413,
+	0xf50137f0,
+	0xf104e621,
+	0xf41388e7,
+	0x00f86721,
+/* 0x05e0: i2c_bitw */
+	0x04e621f5,
+	0x03e8e7f1,
+	0xbb6721f4,
+	0x65b60076,
+	0x9450f904,
+	0x56bb0465,
+	0xfd50bd02,
+	0x50fc0475,
+	0x052c21f5,
+	0xf40464b6,
+	0xe7f11811,
+	0x21f41388,
+	0x0037f067,
+	0x04ca21f5,
+	0x1388e7f1,
+/* 0x061f: i2c_bitw_out */
+	0xf86721f4,
+/* 0x0621: i2c_bitr */
+	0x0137f000,
+	0x04e621f5,
+	0x03e8e7f1,
+	0xbb6721f4,
+	0x65b60076,
+	0x9450f904,
+	0x56bb0465,
+	0xfd50bd02,
+	0x50fc0475,
+	0x052c21f5,
+	0xf40464b6,
+	0x21f51b11,
+	0x37f00517,
+	0xca21f500,
+	0x88e7f104,
+	0x6721f413,
+	0xf4013cf0,
+/* 0x0666: i2c_bitr_done */
+	0x00f80131,
+/* 0x0668: i2c_get_byte */
+	0xf00057f0,
+/* 0x066e: i2c_get_byte_next */
+	0x54b60847,
+	0x0076bb01,
+	0xf90465b6,
+	0x04659450,
+	0xbd0256bb,
+	0x0475fd50,
+	0x21f550fc,
+	0x64b60621,
+	0x2b11f404,
+	0xb60553fd,
+	0x1bf40142,
+	0x0137f0d8,
+	0xb60076bb,
+	0x50f90465,
+	0xbb046594,
+	0x50bd0256,
+	0xfc0475fd,
+	0xe021f550,
+	0x0464b605,
+/* 0x06b8: i2c_get_byte_done */
+/* 0x06ba: i2c_put_byte */
+	0x47f000f8,
+/* 0x06bd: i2c_put_byte_next */
+	0x0142b608,
+	0xbb3854ff,
+	0x65b60076,
+	0x9450f904,
+	0x56bb0465,
+	0xfd50bd02,
+	0x50fc0475,
+	0x05e021f5,
+	0xf40464b6,
+	0x46b03411,
+	0xd81bf400,
+	0xb60076bb,
+	0x50f90465,
+	0xbb046594,
+	0x50bd0256,
+	0xfc0475fd,
+	0x2121f550,
+	0x0464b606,
+	0xbb0f11f4,
+	0x36b00076,
+	0x061bf401,
+/* 0x0713: i2c_put_byte_done */
+	0xf80132f4,
+/* 0x0715: i2c_addr */
+	0x0076bb00,
+	0xf90465b6,
+	0x04659450,
+	0xbd0256bb,
+	0x0475fd50,
+	0x21f550fc,
+	0x64b60551,
+	0x2911f404,
+	0x012ec3e7,
+	0xfd0134b6,
+	0x76bb0553,
+	0x0465b600,
+	0x659450f9,
+	0x0256bb04,
+	0x75fd50bd,
+	0xf550fc04,
+	0xb606ba21,
+/* 0x075a: i2c_addr_done */
+	0x00f80464,
+/* 0x075c: i2c_acquire_addr */
+	0xb6f8cec7,
+	0xe0b705e4,
+	0x00f8d014,
+/* 0x0768: i2c_acquire */
+	0x075c21f5,
+	0xf00421f4,
+	0x21f403d9,
+/* 0x0777: i2c_release */
+	0xf500f833,
+	0xf4075c21,
+	0xdaf00421,
+	0x3321f403,
+/* 0x0786: i2c_recv */
+	0x32f400f8,
+	0xf8c1c701,
+	0xb00214b6,
+	0x1ff52816,
+	0x13a0013a,
+	0x32980bd4,
+	0xac13a000,
+	0x0031980b,
+	0xf90231f4,
+	0xf9e0f9d0,
+	0x0067f1d0,
+	0x0063f100,
+	0x01679210,
+	0xb60076bb,
+	0x50f90465,
+	0xbb046594,
+	0x50bd0256,
+	0xfc0475fd,
+	0x6821f550,
+	0x0464b607,
+	0xd6b0d0fc,
+	0xb31bf500,
+	0x0057f000,
+	0xb60076bb,
+	0x50f90465,
+	0xbb046594,
+	0x50bd0256,
+	0xfc0475fd,
+	0x1521f550,
+	0x0464b607,
+	0x00d011f5,
+	0xbbe0c5c7,
+	0x65b60076,
+	0x9450f904,
+	0x56bb0465,
+	0xfd50bd02,
+	0x50fc0475,
+	0x06ba21f5,
+	0xf50464b6,
+	0xf000ad11,
+	0x76bb0157,
+	0x0465b600,
+	0x659450f9,
+	0x0256bb04,
+	0x75fd50bd,
+	0xf550fc04,
+	0xb6071521,
+	0x11f50464,
+	0x76bb008a,
+	0x0465b600,
+	0x659450f9,
+	0x0256bb04,
+	0x75fd50bd,
+	0xf550fc04,
+	0xb6066821,
+	0x11f40464,
+	0xe05bcb6a,
+	0xb60076bb,
+	0x50f90465,
+	0xbb046594,
+	0x50bd0256,
+	0xfc0475fd,
+	0xad21f550,
+	0x0464b605,
+	0xbd025bb9,
+	0x430ef474,
+/* 0x088c: i2c_recv_not_rd08 */
+	0xf401d6b0,
+	0x57f03d1b,
+	0x1521f500,
+	0x3311f407,
+	0xf5e0c5c7,
+	0xf406ba21,
+	0x57f02911,
+	0x1521f500,
+	0x1f11f407,
+	0xf5e0b5c7,
+	0xf406ba21,
+	0x21f51511,
+	0x74bd05ad,
+	0xf408c5c7,
+	0x32f4091b,
+	0x030ef402,
+/* 0x08cc: i2c_recv_not_wr08 */
+/* 0x08cc: i2c_recv_done */
+	0xf5f8cec7,
+	0xfc077721,
+	0xf4d0fce0,
+	0x7cb90a12,
+	0x6b21f502,
+/* 0x08e1: i2c_recv_exit */
+/* 0x08e3: i2c_init */
+	0xf800f802,
+/* 0x08e5: test_recv */
+	0xd817f100,
+	0x0011cf05,
+	0xf10110b6,
+	0xd005d807,
+	0x04bd0001,
+	0xd900e7f1,
+	0x134fe3f1,
+	0x01b621f5,
+/* 0x0906: test_init */
+	0xe7f100f8,
+	0x21f50800,
+	0x00f801b6,
+/* 0x0910: idle_recv */
+/* 0x0912: idle */
+	0x31f400f8,
+	0xd417f100,
+	0x0011cf05,
+	0xf10110b6,
+	0xd005d407,
+	0x04bd0001,
+/* 0x0928: idle_loop */
+	0xf45817f0,
+/* 0x092e: idle_proc */
+/* 0x092e: idle_proc_exec */
+	0x10f90232,
+	0xf5021eb9,
+	0xfc027421,
+	0x0911f410,
+	0xf40231f4,
+/* 0x0942: idle_proc_next */
+	0x10b6ef0e,
+	0x061fb858,
+	0xf4e61bf4,
+	0x28f4dd02,
+	0xc10ef400,
 	0x00000000,
 	0x00000000,
 	0x00000000,
diff --git a/drivers/gpu/drm/nouveau/core/subdev/pwr/fuc/os.h b/drivers/gpu/drm/nouveau/core/subdev/pwr/fuc/os.h
index 5fb0cccc6c64b..574acfa44c8c7 100644
--- a/drivers/gpu/drm/nouveau/core/subdev/pwr/fuc/os.h
+++ b/drivers/gpu/drm/nouveau/core/subdev/pwr/fuc/os.h
@@ -7,6 +7,7 @@
 #define PROC_HOST 0x54534f48
 #define PROC_MEMX 0x584d454d
 #define PROC_PERF 0x46524550
+#define PROC_I2C_ 0x5f433249
 #define PROC_TEST 0x54534554
 
 /* KERN: message identifiers */
@@ -24,4 +25,22 @@
 #define MEMX_WAIT   3
 #define MEMX_DELAY  4
 
+/* I2C_: message identifiers */
+#define I2C__MSG_RD08 0
+#define I2C__MSG_WR08 1
+
+#define I2C__MSG_DATA0_PORT 24:31
+#define I2C__MSG_DATA0_ADDR 14:23
+
+#define I2C__MSG_DATA0_RD08_PORT I2C__MSG_DATA0_PORT
+#define I2C__MSG_DATA0_RD08_ADDR I2C__MSG_DATA0_ADDR
+#define I2C__MSG_DATA0_RD08_REG 0:7
+#define I2C__MSG_DATA1_RD08_VAL 0:7
+
+#define I2C__MSG_DATA0_WR08_PORT I2C__MSG_DATA0_PORT
+#define I2C__MSG_DATA0_WR08_ADDR I2C__MSG_DATA0_ADDR
+#define I2C__MSG_DATA0_WR08_SYNC 8:8
+#define I2C__MSG_DATA0_WR08_REG 0:7
+#define I2C__MSG_DATA1_WR08_VAL 0:7
+
 #endif
diff --git a/drivers/gpu/drm/nouveau/core/subdev/vm/base.c b/drivers/gpu/drm/nouveau/core/subdev/vm/base.c
index ef3133e7575c8..7dd680ff2f6f6 100644
--- a/drivers/gpu/drm/nouveau/core/subdev/vm/base.c
+++ b/drivers/gpu/drm/nouveau/core/subdev/vm/base.c
@@ -72,13 +72,7 @@ nouveau_vm_map_at(struct nouveau_vma *vma, u64 delta, struct nouveau_mem *node)
 	vmm->flush(vm);
 }
 
-void
-nouveau_vm_map(struct nouveau_vma *vma, struct nouveau_mem *node)
-{
-	nouveau_vm_map_at(vma, 0, node);
-}
-
-void
+static void
 nouveau_vm_map_sg_table(struct nouveau_vma *vma, u64 delta, u64 length,
 			struct nouveau_mem *mem)
 {
@@ -136,7 +130,7 @@ nouveau_vm_map_sg_table(struct nouveau_vma *vma, u64 delta, u64 length,
 	vmm->flush(vm);
 }
 
-void
+static void
 nouveau_vm_map_sg(struct nouveau_vma *vma, u64 delta, u64 length,
 		  struct nouveau_mem *mem)
 {
@@ -174,6 +168,18 @@ nouveau_vm_map_sg(struct nouveau_vma *vma, u64 delta, u64 length,
 	vmm->flush(vm);
 }
 
+void
+nouveau_vm_map(struct nouveau_vma *vma, struct nouveau_mem *node)
+{
+	if (node->sg)
+		nouveau_vm_map_sg_table(vma, 0, node->size << 12, node);
+	else
+	if (node->pages)
+		nouveau_vm_map_sg(vma, 0, node->size << 12, node);
+	else
+		nouveau_vm_map_at(vma, 0, node);
+}
+
 void
 nouveau_vm_unmap_at(struct nouveau_vma *vma, u64 delta, u64 length)
 {
diff --git a/drivers/gpu/drm/nouveau/dispnv04/disp.c b/drivers/gpu/drm/nouveau/dispnv04/disp.c
index b13ff0fc42de4..2f1ed61f7c8c9 100644
--- a/drivers/gpu/drm/nouveau/dispnv04/disp.c
+++ b/drivers/gpu/drm/nouveau/dispnv04/disp.c
@@ -77,11 +77,6 @@ nv04_display_create(struct drm_device *dev)
 
 	nouveau_hw_save_vga_fonts(dev, 1);
 
-	ret = nouveau_object_new(nv_object(drm), NVDRM_DEVICE, 0xd1500000,
-				 NV04_DISP_CLASS, NULL, 0, &disp->core);
-	if (ret)
-		return ret;
-
 	nv04_crtc_create(dev, 0);
 	if (nv_two_heads(dev))
 		nv04_crtc_create(dev, 1);
diff --git a/drivers/gpu/drm/nouveau/dispnv04/disp.h b/drivers/gpu/drm/nouveau/dispnv04/disp.h
index 56a28db040004..4245fc3dab70e 100644
--- a/drivers/gpu/drm/nouveau/dispnv04/disp.h
+++ b/drivers/gpu/drm/nouveau/dispnv04/disp.h
@@ -80,7 +80,6 @@ struct nv04_display {
 	struct nv04_mode_state saved_reg;
 	uint32_t saved_vga_font[4][16384];
 	uint32_t dac_users[4];
-	struct nouveau_object *core;
 	struct nouveau_bo *image[2];
 };
 
diff --git a/drivers/gpu/drm/nouveau/dispnv04/overlay.c b/drivers/gpu/drm/nouveau/dispnv04/overlay.c
index 32e7064b819b6..ab03f7719d2d3 100644
--- a/drivers/gpu/drm/nouveau/dispnv04/overlay.c
+++ b/drivers/gpu/drm/nouveau/dispnv04/overlay.c
@@ -55,9 +55,12 @@ struct nouveau_plane {
 	int hue;
 	int saturation;
 	int iturbt_709;
+
+	void (*set_params)(struct nouveau_plane *);
 };
 
 static uint32_t formats[] = {
+	DRM_FORMAT_YUYV,
 	DRM_FORMAT_UYVY,
 	DRM_FORMAT_NV12,
 };
@@ -140,10 +143,10 @@ nv10_update_plane(struct drm_plane *plane, struct drm_crtc *crtc,
 	nv_wr32(dev, NV_PVIDEO_POINT_OUT(flip), crtc_y << 16 | crtc_x);
 	nv_wr32(dev, NV_PVIDEO_SIZE_OUT(flip), crtc_h << 16 | crtc_w);
 
-	if (fb->pixel_format == DRM_FORMAT_NV12) {
+	if (fb->pixel_format != DRM_FORMAT_UYVY)
 		format |= NV_PVIDEO_FORMAT_COLOR_LE_CR8YB8CB8YA8;
+	if (fb->pixel_format == DRM_FORMAT_NV12)
 		format |= NV_PVIDEO_FORMAT_PLANAR;
-	}
 	if (nv_plane->iturbt_709)
 		format |= NV_PVIDEO_FORMAT_MATRIX_ITURBT709;
 	if (nv_plane->colorkey & (1 << 24))
@@ -182,9 +185,9 @@ nv10_disable_plane(struct drm_plane *plane)
 }
 
 static void
-nv10_destroy_plane(struct drm_plane *plane)
+nv_destroy_plane(struct drm_plane *plane)
 {
-	nv10_disable_plane(plane);
+	plane->funcs->disable_plane(plane);
 	drm_plane_cleanup(plane);
 	kfree(plane);
 }
@@ -217,9 +220,9 @@ nv10_set_params(struct nouveau_plane *plane)
 }
 
 static int
-nv10_set_property(struct drm_plane *plane,
-		  struct drm_property *property,
-		  uint64_t value)
+nv_set_property(struct drm_plane *plane,
+		struct drm_property *property,
+		uint64_t value)
 {
 	struct nouveau_plane *nv_plane = (struct nouveau_plane *)plane;
 
@@ -238,15 +241,16 @@ nv10_set_property(struct drm_plane *plane,
 	else
 		return -EINVAL;
 
-	nv10_set_params(nv_plane);
+	if (nv_plane->set_params)
+		nv_plane->set_params(nv_plane);
 	return 0;
 }
 
 static const struct drm_plane_funcs nv10_plane_funcs = {
 	.update_plane = nv10_update_plane,
 	.disable_plane = nv10_disable_plane,
-	.set_property = nv10_set_property,
-	.destroy = nv10_destroy_plane,
+	.set_property = nv_set_property,
+	.destroy = nv_destroy_plane,
 };
 
 static void
@@ -266,7 +270,7 @@ nv10_overlay_init(struct drm_device *device)
 	case 0x15:
 	case 0x1a:
 	case 0x20:
-		num_formats = 1;
+		num_formats = 2;
 		break;
 	}
 
@@ -321,8 +325,159 @@ nv10_overlay_init(struct drm_device *device)
 	drm_object_attach_property(&plane->base.base,
 				   plane->props.iturbt_709, plane->iturbt_709);
 
+	plane->set_params = nv10_set_params;
 	nv10_set_params(plane);
-	nv_wr32(dev, NV_PVIDEO_STOP, 1);
+	nv10_disable_plane(&plane->base);
+	return;
+cleanup:
+	drm_plane_cleanup(&plane->base);
+err:
+	kfree(plane);
+	nv_error(dev, "Failed to create plane\n");
+}
+
+static int
+nv04_update_plane(struct drm_plane *plane, struct drm_crtc *crtc,
+		  struct drm_framebuffer *fb, int crtc_x, int crtc_y,
+		  unsigned int crtc_w, unsigned int crtc_h,
+		  uint32_t src_x, uint32_t src_y,
+		  uint32_t src_w, uint32_t src_h)
+{
+	struct nouveau_device *dev = nouveau_dev(plane->dev);
+	struct nouveau_plane *nv_plane = (struct nouveau_plane *)plane;
+	struct nouveau_framebuffer *nv_fb = nouveau_framebuffer(fb);
+	struct nouveau_bo *cur = nv_plane->cur;
+	uint32_t overlay = 1;
+	int brightness = (nv_plane->brightness - 512) * 62 / 512;
+	int pitch, ret, i;
+
+	/* Source parameters given in 16.16 fixed point, ignore fractional. */
+	src_x >>= 16;
+	src_y >>= 16;
+	src_w >>= 16;
+	src_h >>= 16;
+
+	pitch = ALIGN(src_w * 4, 0x100);
+
+	if (pitch > 0xffff)
+		return -ERANGE;
+
+	/* TODO: Compute an offset? Not sure how to do this for YUYV. */
+	if (src_x != 0 || src_y != 0)
+		return -ERANGE;
+
+	if (crtc_w < src_w || crtc_h < src_h)
+		return -ERANGE;
+
+	ret = nouveau_bo_pin(nv_fb->nvbo, TTM_PL_FLAG_VRAM);
+	if (ret)
+		return ret;
+
+	nv_plane->cur = nv_fb->nvbo;
+
+	nv_wr32(dev, NV_PVIDEO_OE_STATE, 0);
+	nv_wr32(dev, NV_PVIDEO_SU_STATE, 0);
+	nv_wr32(dev, NV_PVIDEO_RM_STATE, 0);
+
+	for (i = 0; i < 2; i++) {
+		nv_wr32(dev, NV_PVIDEO_BUFF0_START_ADDRESS + 4 * i,
+			nv_fb->nvbo->bo.offset);
+		nv_wr32(dev, NV_PVIDEO_BUFF0_PITCH_LENGTH + 4 * i, pitch);
+		nv_wr32(dev, NV_PVIDEO_BUFF0_OFFSET + 4 * i, 0);
+	}
+	nv_wr32(dev, NV_PVIDEO_WINDOW_START, crtc_y << 16 | crtc_x);
+	nv_wr32(dev, NV_PVIDEO_WINDOW_SIZE, crtc_h << 16 | crtc_w);
+	nv_wr32(dev, NV_PVIDEO_STEP_SIZE,
+		(uint32_t)(((src_h - 1) << 11) / (crtc_h - 1)) << 16 | (uint32_t)(((src_w - 1) << 11) / (crtc_w - 1)));
+
+	/* It should be possible to convert hue/contrast to this */
+	nv_wr32(dev, NV_PVIDEO_RED_CSC_OFFSET, 0x69 - brightness);
+	nv_wr32(dev, NV_PVIDEO_GREEN_CSC_OFFSET, 0x3e + brightness);
+	nv_wr32(dev, NV_PVIDEO_BLUE_CSC_OFFSET, 0x89 - brightness);
+	nv_wr32(dev, NV_PVIDEO_CSC_ADJUST, 0);
+
+	nv_wr32(dev, NV_PVIDEO_CONTROL_Y, 0x001); /* (BLUR_ON, LINE_HALF) */
+	nv_wr32(dev, NV_PVIDEO_CONTROL_X, 0x111); /* (WEIGHT_HEAVY, SHARPENING_ON, SMOOTHING_ON) */
+
+	nv_wr32(dev, NV_PVIDEO_FIFO_BURST_LENGTH, 0x03);
+	nv_wr32(dev, NV_PVIDEO_FIFO_THRES_SIZE, 0x38);
+
+	nv_wr32(dev, NV_PVIDEO_KEY, nv_plane->colorkey);
+
+	if (nv_plane->colorkey & (1 << 24))
+		overlay |= 0x10;
+	if (fb->pixel_format == DRM_FORMAT_YUYV)
+		overlay |= 0x100;
+
+	nv_wr32(dev, NV_PVIDEO_OVERLAY, overlay);
+
+	nv_wr32(dev, NV_PVIDEO_SU_STATE, nv_rd32(dev, NV_PVIDEO_SU_STATE) ^ (1 << 16));
+
+	if (cur)
+		nouveau_bo_unpin(cur);
+
+	return 0;
+}
+
+static int
+nv04_disable_plane(struct drm_plane *plane)
+{
+	struct nouveau_device *dev = nouveau_dev(plane->dev);
+	struct nouveau_plane *nv_plane = (struct nouveau_plane *)plane;
+
+	nv_mask(dev, NV_PVIDEO_OVERLAY, 1, 0);
+	nv_wr32(dev, NV_PVIDEO_OE_STATE, 0);
+	nv_wr32(dev, NV_PVIDEO_SU_STATE, 0);
+	nv_wr32(dev, NV_PVIDEO_RM_STATE, 0);
+	if (nv_plane->cur) {
+		nouveau_bo_unpin(nv_plane->cur);
+		nv_plane->cur = NULL;
+	}
+
+	return 0;
+}
+
+static const struct drm_plane_funcs nv04_plane_funcs = {
+	.update_plane = nv04_update_plane,
+	.disable_plane = nv04_disable_plane,
+	.set_property = nv_set_property,
+	.destroy = nv_destroy_plane,
+};
+
+static void
+nv04_overlay_init(struct drm_device *device)
+{
+	struct nouveau_device *dev = nouveau_dev(device);
+	struct nouveau_plane *plane = kzalloc(sizeof(struct nouveau_plane), GFP_KERNEL);
+	int ret;
+
+	if (!plane)
+		return;
+
+	ret = drm_plane_init(device, &plane->base, 1 /* single crtc */,
+			     &nv04_plane_funcs,
+			     formats, 2, false);
+	if (ret)
+		goto err;
+
+	/* Set up the plane properties */
+	plane->props.colorkey = drm_property_create_range(
+			device, 0, "colorkey", 0, 0x01ffffff);
+	plane->props.brightness = drm_property_create_range(
+			device, 0, "brightness", 0, 1024);
+	if (!plane->props.colorkey ||
+	    !plane->props.brightness)
+		goto cleanup;
+
+	plane->colorkey = 0;
+	drm_object_attach_property(&plane->base.base,
+				   plane->props.colorkey, plane->colorkey);
+
+	plane->brightness = 512;
+	drm_object_attach_property(&plane->base.base,
+				   plane->props.brightness, plane->brightness);
+
+	nv04_disable_plane(&plane->base);
 	return;
 cleanup:
 	drm_plane_cleanup(&plane->base);
@@ -335,6 +490,8 @@ void
 nouveau_overlay_init(struct drm_device *device)
 {
 	struct nouveau_device *dev = nouveau_dev(device);
-	if (dev->chipset >= 0x10 && dev->chipset <= 0x40)
+	if (dev->chipset < 0x10)
+		nv04_overlay_init(device);
+	else if (dev->chipset <= 0x40)
 		nv10_overlay_init(device);
 }
diff --git a/drivers/gpu/drm/nouveau/nouveau_acpi.c b/drivers/gpu/drm/nouveau/nouveau_acpi.c
index ba0183fb84f3b..d9f6120e972e6 100644
--- a/drivers/gpu/drm/nouveau/nouveau_acpi.c
+++ b/drivers/gpu/drm/nouveau/nouveau_acpi.c
@@ -66,6 +66,7 @@ bool nouveau_is_v1_dsm(void) {
 #define NOUVEAU_DSM_HAS_MUX 0x1
 #define NOUVEAU_DSM_HAS_OPT 0x2
 
+#ifdef CONFIG_VGA_SWITCHEROO
 static const char nouveau_dsm_muid[] = {
 	0xA0, 0xA0, 0x95, 0x9D, 0x60, 0x00, 0x48, 0x4D,
 	0xB3, 0x4D, 0x7E, 0x5F, 0xEA, 0x12, 0x9F, 0xD4,
@@ -388,6 +389,11 @@ void nouveau_unregister_dsm_handler(void)
 	if (nouveau_dsm_priv.optimus_detected || nouveau_dsm_priv.dsm_detected)
 		vga_switcheroo_unregister_handler();
 }
+#else
+void nouveau_register_dsm_handler(void) {}
+void nouveau_unregister_dsm_handler(void) {}
+void nouveau_switcheroo_optimus_dsm(void) {}
+#endif
 
 /* retrieve the ROM in 4k blocks */
 static int nouveau_rom_call(acpi_handle rom_handle, uint8_t *bios,
diff --git a/drivers/gpu/drm/nouveau/nouveau_bo.c b/drivers/gpu/drm/nouveau/nouveau_bo.c
index c0fde6b9393cb..488686d490c0c 100644
--- a/drivers/gpu/drm/nouveau/nouveau_bo.c
+++ b/drivers/gpu/drm/nouveau/nouveau_bo.c
@@ -560,28 +560,6 @@ nouveau_bo_evict_flags(struct ttm_buffer_object *bo, struct ttm_placement *pl)
 }
 
 
-/* GPU-assisted copy using NV_MEMORY_TO_MEMORY_FORMAT, can access
- * TTM_PL_{VRAM,TT} directly.
- */
-
-static int
-nouveau_bo_move_accel_cleanup(struct nouveau_channel *chan,
-			      struct nouveau_bo *nvbo, bool evict,
-			      bool no_wait_gpu, struct ttm_mem_reg *new_mem)
-{
-	struct nouveau_fence *fence = NULL;
-	int ret;
-
-	ret = nouveau_fence_new(chan, false, &fence);
-	if (ret)
-		return ret;
-
-	ret = ttm_bo_move_accel_cleanup(&nvbo->bo, fence, evict,
-					no_wait_gpu, new_mem);
-	nouveau_fence_unref(&fence);
-	return ret;
-}
-
 static int
 nve0_bo_move_init(struct nouveau_channel *chan, u32 handle)
 {
@@ -798,25 +776,25 @@ nv50_bo_move_m2mf(struct nouveau_channel *chan, struct ttm_buffer_object *bo,
 		  struct ttm_mem_reg *old_mem, struct ttm_mem_reg *new_mem)
 {
 	struct nouveau_mem *node = old_mem->mm_node;
-	struct nouveau_bo *nvbo = nouveau_bo(bo);
 	u64 length = (new_mem->num_pages << PAGE_SHIFT);
 	u64 src_offset = node->vma[0].offset;
 	u64 dst_offset = node->vma[1].offset;
+	int src_tiled = !!node->memtype;
+	int dst_tiled = !!((struct nouveau_mem *)new_mem->mm_node)->memtype;
 	int ret;
 
 	while (length) {
 		u32 amount, stride, height;
 
+		ret = RING_SPACE(chan, 18 + 6 * (src_tiled + dst_tiled));
+		if (ret)
+			return ret;
+
 		amount  = min(length, (u64)(4 * 1024 * 1024));
 		stride  = 16 * 4;
 		height  = amount / stride;
 
-		if (old_mem->mem_type == TTM_PL_VRAM &&
-		    nouveau_bo_tile_layout(nvbo)) {
-			ret = RING_SPACE(chan, 8);
-			if (ret)
-				return ret;
-
+		if (src_tiled) {
 			BEGIN_NV04(chan, NvSubCopy, 0x0200, 7);
 			OUT_RING  (chan, 0);
 			OUT_RING  (chan, 0);
@@ -826,19 +804,10 @@ nv50_bo_move_m2mf(struct nouveau_channel *chan, struct ttm_buffer_object *bo,
 			OUT_RING  (chan, 0);
 			OUT_RING  (chan, 0);
 		} else {
-			ret = RING_SPACE(chan, 2);
-			if (ret)
-				return ret;
-
 			BEGIN_NV04(chan, NvSubCopy, 0x0200, 1);
 			OUT_RING  (chan, 1);
 		}
-		if (new_mem->mem_type == TTM_PL_VRAM &&
-		    nouveau_bo_tile_layout(nvbo)) {
-			ret = RING_SPACE(chan, 8);
-			if (ret)
-				return ret;
-
+		if (dst_tiled) {
 			BEGIN_NV04(chan, NvSubCopy, 0x021c, 7);
 			OUT_RING  (chan, 0);
 			OUT_RING  (chan, 0);
@@ -848,18 +817,10 @@ nv50_bo_move_m2mf(struct nouveau_channel *chan, struct ttm_buffer_object *bo,
 			OUT_RING  (chan, 0);
 			OUT_RING  (chan, 0);
 		} else {
-			ret = RING_SPACE(chan, 2);
-			if (ret)
-				return ret;
-
 			BEGIN_NV04(chan, NvSubCopy, 0x021c, 1);
 			OUT_RING  (chan, 1);
 		}
 
-		ret = RING_SPACE(chan, 14);
-		if (ret)
-			return ret;
-
 		BEGIN_NV04(chan, NvSubCopy, 0x0238, 2);
 		OUT_RING  (chan, upper_32_bits(src_offset));
 		OUT_RING  (chan, upper_32_bits(dst_offset));
@@ -953,23 +914,28 @@ nv04_bo_move_m2mf(struct nouveau_channel *chan, struct ttm_buffer_object *bo,
 }
 
 static int
-nouveau_vma_getmap(struct nouveau_channel *chan, struct nouveau_bo *nvbo,
-		   struct ttm_mem_reg *mem, struct nouveau_vma *vma)
+nouveau_bo_move_prep(struct nouveau_drm *drm, struct ttm_buffer_object *bo,
+		     struct ttm_mem_reg *mem)
 {
-	struct nouveau_mem *node = mem->mm_node;
+	struct nouveau_mem *old_node = bo->mem.mm_node;
+	struct nouveau_mem *new_node = mem->mm_node;
+	u64 size = (u64)mem->num_pages << PAGE_SHIFT;
 	int ret;
 
-	ret = nouveau_vm_get(nv_client(chan->cli)->vm, mem->num_pages <<
-			     PAGE_SHIFT, node->page_shift,
-			     NV_MEM_ACCESS_RW, vma);
+	ret = nouveau_vm_get(nv_client(drm)->vm, size, old_node->page_shift,
+			     NV_MEM_ACCESS_RW, &old_node->vma[0]);
 	if (ret)
 		return ret;
 
-	if (mem->mem_type == TTM_PL_VRAM)
-		nouveau_vm_map(vma, node);
-	else
-		nouveau_vm_map_sg(vma, 0, mem->num_pages << PAGE_SHIFT, node);
+	ret = nouveau_vm_get(nv_client(drm)->vm, size, new_node->page_shift,
+			     NV_MEM_ACCESS_RW, &old_node->vma[1]);
+	if (ret) {
+		nouveau_vm_put(&old_node->vma[0]);
+		return ret;
+	}
 
+	nouveau_vm_map(&old_node->vma[0], old_node);
+	nouveau_vm_map(&old_node->vma[1], new_node);
 	return 0;
 }
 
@@ -979,35 +945,34 @@ nouveau_bo_move_m2mf(struct ttm_buffer_object *bo, int evict, bool intr,
 {
 	struct nouveau_drm *drm = nouveau_bdev(bo->bdev);
 	struct nouveau_channel *chan = drm->ttm.chan;
-	struct nouveau_bo *nvbo = nouveau_bo(bo);
-	struct ttm_mem_reg *old_mem = &bo->mem;
+	struct nouveau_fence *fence;
 	int ret;
 
-	mutex_lock_nested(&chan->cli->mutex, SINGLE_DEPTH_NESTING);
-
 	/* create temporary vmas for the transfer and attach them to the
 	 * old nouveau_mem node, these will get cleaned up after ttm has
 	 * destroyed the ttm_mem_reg
 	 */
 	if (nv_device(drm->device)->card_type >= NV_50) {
-		struct nouveau_mem *node = old_mem->mm_node;
-
-		ret = nouveau_vma_getmap(chan, nvbo, old_mem, &node->vma[0]);
-		if (ret)
-			goto out;
-
-		ret = nouveau_vma_getmap(chan, nvbo, new_mem, &node->vma[1]);
+		ret = nouveau_bo_move_prep(drm, bo, new_mem);
 		if (ret)
-			goto out;
+			return ret;
 	}
 
-	ret = drm->ttm.move(chan, bo, &bo->mem, new_mem);
+	mutex_lock_nested(&chan->cli->mutex, SINGLE_DEPTH_NESTING);
+	ret = nouveau_fence_sync(bo->sync_obj, chan);
 	if (ret == 0) {
-		ret = nouveau_bo_move_accel_cleanup(chan, nvbo, evict,
-						    no_wait_gpu, new_mem);
+		ret = drm->ttm.move(chan, bo, &bo->mem, new_mem);
+		if (ret == 0) {
+			ret = nouveau_fence_new(chan, false, &fence);
+			if (ret == 0) {
+				ret = ttm_bo_move_accel_cleanup(bo, fence,
+								evict,
+								no_wait_gpu,
+								new_mem);
+				nouveau_fence_unref(&fence);
+			}
+		}
 	}
-
-out:
 	mutex_unlock(&chan->cli->mutex);
 	return ret;
 }
@@ -1147,19 +1112,10 @@ nouveau_bo_move_ntfy(struct ttm_buffer_object *bo, struct ttm_mem_reg *new_mem)
 		return;
 
 	list_for_each_entry(vma, &nvbo->vma_list, head) {
-		if (new_mem && new_mem->mem_type == TTM_PL_VRAM) {
+		if (new_mem && new_mem->mem_type != TTM_PL_SYSTEM &&
+			      (new_mem->mem_type == TTM_PL_VRAM ||
+			       nvbo->page_shift != vma->vm->vmm->lpg_shift)) {
 			nouveau_vm_map(vma, new_mem->mm_node);
-		} else
-		if (new_mem && new_mem->mem_type == TTM_PL_TT &&
-		    nvbo->page_shift == vma->vm->vmm->spg_shift) {
-			if (((struct nouveau_mem *)new_mem->mm_node)->sg)
-				nouveau_vm_map_sg_table(vma, 0, new_mem->
-						  num_pages << PAGE_SHIFT,
-						  new_mem->mm_node);
-			else
-				nouveau_vm_map_sg(vma, 0, new_mem->
-						  num_pages << PAGE_SHIFT,
-						  new_mem->mm_node);
 		} else {
 			nouveau_vm_unmap(vma);
 		}
@@ -1224,28 +1180,27 @@ nouveau_bo_move(struct ttm_buffer_object *bo, bool evict, bool intr,
 		goto out;
 	}
 
-	/* CPU copy if we have no accelerated method available */
-	if (!drm->ttm.move) {
-		ret = ttm_bo_move_memcpy(bo, evict, no_wait_gpu, new_mem);
-		goto out;
-	}
-
 	/* Hardware assisted copy. */
-	if (new_mem->mem_type == TTM_PL_SYSTEM)
-		ret = nouveau_bo_move_flipd(bo, evict, intr,
-					    no_wait_gpu, new_mem);
-	else if (old_mem->mem_type == TTM_PL_SYSTEM)
-		ret = nouveau_bo_move_flips(bo, evict, intr,
-					    no_wait_gpu, new_mem);
-	else
-		ret = nouveau_bo_move_m2mf(bo, evict, intr,
-					   no_wait_gpu, new_mem);
-
-	if (!ret)
-		goto out;
+	if (drm->ttm.move) {
+		if (new_mem->mem_type == TTM_PL_SYSTEM)
+			ret = nouveau_bo_move_flipd(bo, evict, intr,
+						    no_wait_gpu, new_mem);
+		else if (old_mem->mem_type == TTM_PL_SYSTEM)
+			ret = nouveau_bo_move_flips(bo, evict, intr,
+						    no_wait_gpu, new_mem);
+		else
+			ret = nouveau_bo_move_m2mf(bo, evict, intr,
+						   no_wait_gpu, new_mem);
+		if (!ret)
+			goto out;
+	}
 
 	/* Fallback to software copy. */
-	ret = ttm_bo_move_memcpy(bo, evict, no_wait_gpu, new_mem);
+	spin_lock(&bo->bdev->fence_lock);
+	ret = ttm_bo_wait(bo, true, intr, no_wait_gpu);
+	spin_unlock(&bo->bdev->fence_lock);
+	if (ret == 0)
+		ret = ttm_bo_move_memcpy(bo, evict, no_wait_gpu, new_mem);
 
 out:
 	if (nv_device(drm->device)->card_type < NV_50) {
@@ -1271,6 +1226,7 @@ nouveau_ttm_io_mem_reserve(struct ttm_bo_device *bdev, struct ttm_mem_reg *mem)
 {
 	struct ttm_mem_type_manager *man = &bdev->man[mem->mem_type];
 	struct nouveau_drm *drm = nouveau_bdev(bdev);
+	struct nouveau_mem *node = mem->mm_node;
 	struct drm_device *dev = drm->dev;
 	int ret;
 
@@ -1293,14 +1249,16 @@ nouveau_ttm_io_mem_reserve(struct ttm_bo_device *bdev, struct ttm_mem_reg *mem)
 			mem->bus.is_iomem = !dev->agp->cant_use_aperture;
 		}
 #endif
-		break;
+		if (!node->memtype)
+			/* untiled */
+			break;
+		/* fallthrough, tiled memory */
 	case TTM_PL_VRAM:
 		mem->bus.offset = mem->start << PAGE_SHIFT;
 		mem->bus.base = pci_resource_start(dev->pdev, 1);
 		mem->bus.is_iomem = true;
 		if (nv_device(drm->device)->card_type >= NV_50) {
 			struct nouveau_bar *bar = nouveau_bar(drm->device);
-			struct nouveau_mem *node = mem->mm_node;
 
 			ret = bar->umap(bar, node, NV_MEM_ACCESS_RW,
 					&node->bar_vma);
@@ -1336,6 +1294,7 @@ nouveau_ttm_fault_reserve_notify(struct ttm_buffer_object *bo)
 	struct nouveau_bo *nvbo = nouveau_bo(bo);
 	struct nouveau_device *device = nv_device(drm->device);
 	u32 mappable = pci_resource_len(device->pdev, 1) >> PAGE_SHIFT;
+	int ret;
 
 	/* as long as the bo isn't in vram, and isn't tiled, we've got
 	 * nothing to do here.
@@ -1344,10 +1303,20 @@ nouveau_ttm_fault_reserve_notify(struct ttm_buffer_object *bo)
 		if (nv_device(drm->device)->card_type < NV_50 ||
 		    !nouveau_bo_tile_layout(nvbo))
 			return 0;
+
+		if (bo->mem.mem_type == TTM_PL_SYSTEM) {
+			nouveau_bo_placement_set(nvbo, TTM_PL_TT, 0);
+
+			ret = nouveau_bo_validate(nvbo, false, false);
+			if (ret)
+				return ret;
+		}
+		return 0;
 	}
 
 	/* make sure bo is in mappable vram */
-	if (bo->mem.start + bo->mem.num_pages < mappable)
+	if (nv_device(drm->device)->card_type >= NV_50 ||
+	    bo->mem.start + bo->mem.num_pages < mappable)
 		return 0;
 
 
@@ -1535,7 +1504,6 @@ nouveau_bo_vma_add(struct nouveau_bo *nvbo, struct nouveau_vm *vm,
 		   struct nouveau_vma *vma)
 {
 	const u32 size = nvbo->bo.mem.num_pages << PAGE_SHIFT;
-	struct nouveau_mem *node = nvbo->bo.mem.mm_node;
 	int ret;
 
 	ret = nouveau_vm_get(vm, size, nvbo->page_shift,
@@ -1543,15 +1511,10 @@ nouveau_bo_vma_add(struct nouveau_bo *nvbo, struct nouveau_vm *vm,
 	if (ret)
 		return ret;
 
-	if (nvbo->bo.mem.mem_type == TTM_PL_VRAM)
+	if ( nvbo->bo.mem.mem_type != TTM_PL_SYSTEM &&
+	    (nvbo->bo.mem.mem_type == TTM_PL_VRAM ||
+	     nvbo->page_shift != vma->vm->vmm->lpg_shift))
 		nouveau_vm_map(vma, nvbo->bo.mem.mm_node);
-	else if (nvbo->bo.mem.mem_type == TTM_PL_TT &&
-		 nvbo->page_shift == vma->vm->vmm->spg_shift) {
-		if (node->sg)
-			nouveau_vm_map_sg_table(vma, 0, size, node);
-		else
-			nouveau_vm_map_sg(vma, 0, size, node);
-	}
 
 	list_add_tail(&vma->head, &nvbo->vma_list);
 	vma->refcount = 1;
diff --git a/drivers/gpu/drm/nouveau/nouveau_display.c b/drivers/gpu/drm/nouveau/nouveau_display.c
index 25ea82f8def3c..24011596af434 100644
--- a/drivers/gpu/drm/nouveau/nouveau_display.c
+++ b/drivers/gpu/drm/nouveau/nouveau_display.c
@@ -68,20 +68,100 @@ nouveau_display_vblank_disable(struct drm_device *dev, int head)
 		nouveau_event_put(disp->vblank[head]);
 }
 
+static inline int
+calc(int blanks, int blanke, int total, int line)
+{
+	if (blanke >= blanks) {
+		if (line >= blanks)
+			line -= total;
+	} else {
+		if (line >= blanks)
+			line -= total;
+		line -= blanke + 1;
+	}
+	return line;
+}
+
+int
+nouveau_display_scanoutpos_head(struct drm_crtc *crtc, int *vpos, int *hpos,
+				ktime_t *stime, ktime_t *etime)
+{
+	const u32 mthd = NV04_DISP_SCANOUTPOS + nouveau_crtc(crtc)->index;
+	struct nouveau_display *disp = nouveau_display(crtc->dev);
+	struct nv04_display_scanoutpos args;
+	int ret, retry = 1;
+
+	do {
+		ret = nv_exec(disp->core, mthd, &args, sizeof(args));
+		if (ret != 0)
+			return 0;
+
+		if (args.vline) {
+			ret |= DRM_SCANOUTPOS_ACCURATE;
+			ret |= DRM_SCANOUTPOS_VALID;
+			break;
+		}
+
+		if (retry) ndelay(crtc->linedur_ns);
+	} while (retry--);
+
+	*hpos = calc(args.hblanks, args.hblanke, args.htotal, args.hline);
+	*vpos = calc(args.vblanks, args.vblanke, args.vtotal, args.vline);
+	if (stime) *stime = ns_to_ktime(args.time[0]);
+	if (etime) *etime = ns_to_ktime(args.time[1]);
+
+	if (*vpos < 0)
+		ret |= DRM_SCANOUTPOS_INVBL;
+	return ret;
+}
+
+int
+nouveau_display_scanoutpos(struct drm_device *dev, int head, unsigned int flags,
+			   int *vpos, int *hpos, ktime_t *stime, ktime_t *etime)
+{
+	struct drm_crtc *crtc;
+
+	list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
+		if (nouveau_crtc(crtc)->index == head) {
+			return nouveau_display_scanoutpos_head(crtc, vpos, hpos,
+							       stime, etime);
+		}
+	}
+
+	return 0;
+}
+
+int
+nouveau_display_vblstamp(struct drm_device *dev, int head, int *max_error,
+			 struct timeval *time, unsigned flags)
+{
+	struct drm_crtc *crtc;
+
+	list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
+		if (nouveau_crtc(crtc)->index == head) {
+			return drm_calc_vbltimestamp_from_scanoutpos(dev,
+					head, max_error, time, flags, crtc,
+					&crtc->hwmode);
+		}
+	}
+
+	return -EINVAL;
+}
+
 static void
 nouveau_display_vblank_fini(struct drm_device *dev)
 {
 	struct nouveau_display *disp = nouveau_display(dev);
 	int i;
 
+	drm_vblank_cleanup(dev);
+
 	if (disp->vblank) {
 		for (i = 0; i < dev->mode_config.num_crtc; i++)
 			nouveau_event_ref(NULL, &disp->vblank[i]);
 		kfree(disp->vblank);
 		disp->vblank = NULL;
 	}
-
-	drm_vblank_cleanup(dev);
 }
 
 static int
@@ -407,10 +487,31 @@ nouveau_display_create(struct drm_device *dev)
 	drm_kms_helper_poll_disable(dev);
 
 	if (drm->vbios.dcb.entries) {
-		if (nv_device(drm->device)->card_type < NV_50)
-			ret = nv04_display_create(dev);
-		else
-			ret = nv50_display_create(dev);
+		static const u16 oclass[] = {
+			NVF0_DISP_CLASS,
+			NVE0_DISP_CLASS,
+			NVD0_DISP_CLASS,
+			NVA3_DISP_CLASS,
+			NV94_DISP_CLASS,
+			NVA0_DISP_CLASS,
+			NV84_DISP_CLASS,
+			NV50_DISP_CLASS,
+			NV04_DISP_CLASS,
+		};
+		int i;
+
+		for (i = 0, ret = -ENODEV; ret && i < ARRAY_SIZE(oclass); i++) {
+			ret = nouveau_object_new(nv_object(drm), NVDRM_DEVICE,
+						 NVDRM_DISPLAY, oclass[i],
+						 NULL, 0, &disp->core);
+		}
+
+		if (ret == 0) {
+			if (nv_mclass(disp->core) < NV50_DISP_CLASS)
+				ret = nv04_display_create(dev);
+			else
+				ret = nv50_display_create(dev);
+		}
 	} else {
 		ret = 0;
 	}
@@ -439,6 +540,7 @@ void
 nouveau_display_destroy(struct drm_device *dev)
 {
 	struct nouveau_display *disp = nouveau_display(dev);
+	struct nouveau_drm *drm = nouveau_drm(dev);
 
 	nouveau_backlight_exit(dev);
 	nouveau_display_vblank_fini(dev);
@@ -449,6 +551,8 @@ nouveau_display_destroy(struct drm_device *dev)
 	if (disp->dtor)
 		disp->dtor(dev);
 
+	nouveau_object_del(nv_object(drm), NVDRM_DEVICE, NVDRM_DISPLAY);
+
 	nouveau_drm(dev)->display = NULL;
 	kfree(disp);
 }
@@ -603,6 +707,14 @@ nouveau_crtc_page_flip(struct drm_crtc *crtc, struct drm_framebuffer *fb,
 	if (!s)
 		return -ENOMEM;
 
+	if (new_bo != old_bo) {
+		ret = nouveau_bo_pin(new_bo, TTM_PL_FLAG_VRAM);
+		if (ret)
+			goto fail_free;
+	}
+
+	mutex_lock(&chan->cli->mutex);
+
 	/* synchronise rendering channel with the kernel's channel */
 	spin_lock(&new_bo->bo.bdev->fence_lock);
 	fence = nouveau_fence_ref(new_bo->bo.sync_obj);
@@ -610,15 +722,8 @@ nouveau_crtc_page_flip(struct drm_crtc *crtc, struct drm_framebuffer *fb,
 	ret = nouveau_fence_sync(fence, chan);
 	nouveau_fence_unref(&fence);
 	if (ret)
-		goto fail_free;
-
-	if (new_bo != old_bo) {
-		ret = nouveau_bo_pin(new_bo, TTM_PL_FLAG_VRAM);
-		if (ret)
-			goto fail_free;
-	}
+		goto fail_unpin;
 
-	mutex_lock(&chan->cli->mutex);
 	ret = ttm_bo_reserve(&old_bo->bo, true, false, false, NULL);
 	if (ret)
 		goto fail_unpin;
diff --git a/drivers/gpu/drm/nouveau/nouveau_display.h b/drivers/gpu/drm/nouveau/nouveau_display.h
index 8bc8bab90e8d3..a71cf77e55b24 100644
--- a/drivers/gpu/drm/nouveau/nouveau_display.h
+++ b/drivers/gpu/drm/nouveau/nouveau_display.h
@@ -36,6 +36,7 @@ struct nouveau_display {
 	int  (*init)(struct drm_device *);
 	void (*fini)(struct drm_device *);
 
+	struct nouveau_object *core;
 	struct nouveau_eventh **vblank;
 
 	struct drm_property *dithering_mode;
@@ -63,6 +64,10 @@ void nouveau_display_repin(struct drm_device *dev);
 void nouveau_display_resume(struct drm_device *dev);
 int  nouveau_display_vblank_enable(struct drm_device *, int);
 void nouveau_display_vblank_disable(struct drm_device *, int);
+int  nouveau_display_scanoutpos(struct drm_device *, int, unsigned int,
+				int *, int *, ktime_t *, ktime_t *);
+int  nouveau_display_vblstamp(struct drm_device *, int, int *,
+			      struct timeval *, unsigned);
 
 int  nouveau_crtc_page_flip(struct drm_crtc *crtc, struct drm_framebuffer *fb,
 			    struct drm_pending_vblank_event *event,
diff --git a/drivers/gpu/drm/nouveau/nouveau_drm.c b/drivers/gpu/drm/nouveau/nouveau_drm.c
index 98a22e6e27a11..78c8e7146d56b 100644
--- a/drivers/gpu/drm/nouveau/nouveau_drm.c
+++ b/drivers/gpu/drm/nouveau/nouveau_drm.c
@@ -503,19 +503,21 @@ nouveau_do_suspend(struct drm_device *dev)
 	if (drm->cechan) {
 		ret = nouveau_channel_idle(drm->cechan);
 		if (ret)
-			return ret;
+			goto fail_display;
 	}
 
 	if (drm->channel) {
 		ret = nouveau_channel_idle(drm->channel);
 		if (ret)
-			return ret;
+			goto fail_display;
 	}
 
 	NV_INFO(drm, "suspending client object trees...\n");
 	if (drm->fence && nouveau_fence(drm)->suspend) {
-		if (!nouveau_fence(drm)->suspend(drm))
-			return -ENOMEM;
+		if (!nouveau_fence(drm)->suspend(drm)) {
+			ret = -ENOMEM;
+			goto fail_display;
+		}
 	}
 
 	list_for_each_entry(cli, &drm->clients, head) {
@@ -537,6 +539,10 @@ nouveau_do_suspend(struct drm_device *dev)
 		nouveau_client_init(&cli->base);
 	}
 
+	if (drm->fence && nouveau_fence(drm)->resume)
+		nouveau_fence(drm)->resume(drm);
+
+fail_display:
 	if (dev->mode_config.num_crtc) {
 		NV_INFO(drm, "resuming display...\n");
 		nouveau_display_resume(dev);
@@ -798,6 +804,8 @@ driver = {
 	.get_vblank_counter = drm_vblank_count,
 	.enable_vblank = nouveau_display_vblank_enable,
 	.disable_vblank = nouveau_display_vblank_disable,
+	.get_scanout_position = nouveau_display_scanoutpos,
+	.get_vblank_timestamp = nouveau_display_vblstamp,
 
 	.ioctls = nouveau_ioctls,
 	.num_ioctls = ARRAY_SIZE(nouveau_ioctls),
diff --git a/drivers/gpu/drm/nouveau/nouveau_drm.h b/drivers/gpu/drm/nouveau/nouveau_drm.h
index 4b0fb6c66be91..23ca7a517246f 100644
--- a/drivers/gpu/drm/nouveau/nouveau_drm.h
+++ b/drivers/gpu/drm/nouveau/nouveau_drm.h
@@ -54,6 +54,7 @@ enum nouveau_drm_handle {
 	NVDRM_CLIENT  = 0xffffffff,
 	NVDRM_DEVICE  = 0xdddddddd,
 	NVDRM_CONTROL = 0xdddddddc,
+	NVDRM_DISPLAY = 0xd1500000,
 	NVDRM_PUSH    = 0xbbbb0000, /* |= client chid */
 	NVDRM_CHAN    = 0xcccc0000, /* |= client chid */
 	NVDRM_NVSW    = 0x55550000,
diff --git a/drivers/gpu/drm/nouveau/nouveau_gem.c b/drivers/gpu/drm/nouveau/nouveau_gem.c
index 0447163cd2b43..27c3fd89e8ceb 100644
--- a/drivers/gpu/drm/nouveau/nouveau_gem.c
+++ b/drivers/gpu/drm/nouveau/nouveau_gem.c
@@ -463,12 +463,6 @@ validate_list(struct nouveau_channel *chan, struct nouveau_cli *cli,
 	list_for_each_entry(nvbo, list, entry) {
 		struct drm_nouveau_gem_pushbuf_bo *b = &pbbo[nvbo->pbbo_index];
 
-		ret = validate_sync(chan, nvbo);
-		if (unlikely(ret)) {
-			NV_ERROR(cli, "fail pre-validate sync\n");
-			return ret;
-		}
-
 		ret = nouveau_gem_set_domain(&nvbo->gem, b->read_domains,
 					     b->write_domains,
 					     b->valid_domains);
diff --git a/drivers/gpu/drm/nouveau/nouveau_sgdma.c b/drivers/gpu/drm/nouveau/nouveau_sgdma.c
index 0843ebc910d4d..a4d22e5eb176e 100644
--- a/drivers/gpu/drm/nouveau/nouveau_sgdma.c
+++ b/drivers/gpu/drm/nouveau/nouveau_sgdma.c
@@ -31,16 +31,17 @@ nv04_sgdma_bind(struct ttm_tt *ttm, struct ttm_mem_reg *mem)
 {
 	struct nouveau_sgdma_be *nvbe = (struct nouveau_sgdma_be *)ttm;
 	struct nouveau_mem *node = mem->mm_node;
-	u64 size = mem->num_pages << 12;
 
 	if (ttm->sg) {
-		node->sg = ttm->sg;
-		nouveau_vm_map_sg_table(&node->vma[0], 0, size, node);
+		node->sg    = ttm->sg;
+		node->pages = NULL;
 	} else {
+		node->sg    = NULL;
 		node->pages = nvbe->ttm.dma_address;
-		nouveau_vm_map_sg(&node->vma[0], 0, size, node);
 	}
+	node->size = (mem->num_pages << PAGE_SHIFT) >> 12;
 
+	nouveau_vm_map(&node->vma[0], node);
 	nvbe->node = node;
 	return 0;
 }
@@ -67,9 +68,13 @@ nv50_sgdma_bind(struct ttm_tt *ttm, struct ttm_mem_reg *mem)
 
 	/* noop: bound in move_notify() */
 	if (ttm->sg) {
-		node->sg = ttm->sg;
-	} else
+		node->sg    = ttm->sg;
+		node->pages = NULL;
+	} else {
+		node->sg    = NULL;
 		node->pages = nvbe->ttm.dma_address;
+	}
+	node->size = (mem->num_pages << PAGE_SHIFT) >> 12;
 	return 0;
 }
 
diff --git a/drivers/gpu/drm/nouveau/nouveau_ttm.c b/drivers/gpu/drm/nouveau/nouveau_ttm.c
index 19e3757291fba..d45d50da978f0 100644
--- a/drivers/gpu/drm/nouveau/nouveau_ttm.c
+++ b/drivers/gpu/drm/nouveau/nouveau_ttm.c
@@ -171,6 +171,7 @@ nouveau_gart_manager_new(struct ttm_mem_type_manager *man,
 	node = kzalloc(sizeof(*node), GFP_KERNEL);
 	if (!node)
 		return -ENOMEM;
+
 	node->page_shift = 12;
 
 	switch (nv_device(drm->device)->card_type) {
diff --git a/drivers/gpu/drm/nouveau/nv50_display.c b/drivers/gpu/drm/nouveau/nv50_display.c
index 4e384a2f99c36..2dccafc6e9db5 100644
--- a/drivers/gpu/drm/nouveau/nv50_display.c
+++ b/drivers/gpu/drm/nouveau/nv50_display.c
@@ -1035,6 +1035,7 @@ static bool
 nv50_crtc_mode_fixup(struct drm_crtc *crtc, const struct drm_display_mode *mode,
 		     struct drm_display_mode *adjusted_mode)
 {
+	drm_mode_set_crtcinfo(adjusted_mode, CRTC_INTERLACE_HALVE_V);
 	return true;
 }
 
@@ -2199,16 +2200,6 @@ nv50_display_destroy(struct drm_device *dev)
 int
 nv50_display_create(struct drm_device *dev)
 {
-	static const u16 oclass[] = {
-		NVF0_DISP_CLASS,
-		NVE0_DISP_CLASS,
-		NVD0_DISP_CLASS,
-		NVA3_DISP_CLASS,
-		NV94_DISP_CLASS,
-		NVA0_DISP_CLASS,
-		NV84_DISP_CLASS,
-		NV50_DISP_CLASS,
-	};
 	struct nouveau_device *device = nouveau_dev(dev);
 	struct nouveau_drm *drm = nouveau_drm(dev);
 	struct dcb_table *dcb = &drm->vbios.dcb;
@@ -2225,6 +2216,7 @@ nv50_display_create(struct drm_device *dev)
 	nouveau_display(dev)->dtor = nv50_display_destroy;
 	nouveau_display(dev)->init = nv50_display_init;
 	nouveau_display(dev)->fini = nv50_display_fini;
+	disp->core = nouveau_display(dev)->core;
 
 	/* small shared memory area we use for notifiers and semaphores */
 	ret = nouveau_bo_new(dev, 4096, 0x1000, TTM_PL_FLAG_VRAM,
@@ -2240,17 +2232,6 @@ nv50_display_create(struct drm_device *dev)
 			nouveau_bo_ref(NULL, &disp->sync);
 	}
 
-	if (ret)
-		goto out;
-
-	/* attempt to allocate a supported evo display class */
-	ret = -ENODEV;
-	for (i = 0; ret && i < ARRAY_SIZE(oclass); i++) {
-		ret = nouveau_object_new(nv_object(drm), NVDRM_DEVICE,
-					 0xd1500000, oclass[i], NULL, 0,
-					 &disp->core);
-	}
-
 	if (ret)
 		goto out;
 
diff --git a/drivers/gpu/drm/omapdrm/omap_crtc.c b/drivers/gpu/drm/omapdrm/omap_crtc.c
index 0fd2eb139f6e4..4313bb0a49a62 100644
--- a/drivers/gpu/drm/omapdrm/omap_crtc.c
+++ b/drivers/gpu/drm/omapdrm/omap_crtc.c
@@ -411,7 +411,7 @@ static void omap_crtc_error_irq(struct omap_drm_irq *irq, uint32_t irqstatus)
 	struct drm_crtc *crtc = &omap_crtc->base;
 	DRM_ERROR("%s: errors: %08x\n", omap_crtc->name, irqstatus);
 	/* avoid getting in a flood, unregister the irq until next vblank */
-	omap_irq_unregister(crtc->dev, &omap_crtc->error_irq);
+	__omap_irq_unregister(crtc->dev, &omap_crtc->error_irq);
 }
 
 static void omap_crtc_apply_irq(struct omap_drm_irq *irq, uint32_t irqstatus)
@@ -421,13 +421,13 @@ static void omap_crtc_apply_irq(struct omap_drm_irq *irq, uint32_t irqstatus)
 	struct drm_crtc *crtc = &omap_crtc->base;
 
 	if (!omap_crtc->error_irq.registered)
-		omap_irq_register(crtc->dev, &omap_crtc->error_irq);
+		__omap_irq_register(crtc->dev, &omap_crtc->error_irq);
 
 	if (!dispc_mgr_go_busy(omap_crtc->channel)) {
 		struct omap_drm_private *priv =
 				crtc->dev->dev_private;
 		DBG("%s: apply done", omap_crtc->name);
-		omap_irq_unregister(crtc->dev, &omap_crtc->apply_irq);
+		__omap_irq_unregister(crtc->dev, &omap_crtc->apply_irq);
 		queue_work(priv->wq, &omap_crtc->apply_work);
 	}
 }
@@ -623,6 +623,11 @@ void omap_crtc_pre_init(void)
 	dss_install_mgr_ops(&mgr_ops);
 }
 
+void omap_crtc_pre_uninit(void)
+{
+	dss_uninstall_mgr_ops();
+}
+
 /* initialize crtc */
 struct drm_crtc *omap_crtc_init(struct drm_device *dev,
 		struct drm_plane *plane, enum omap_channel channel, int id)
diff --git a/drivers/gpu/drm/omapdrm/omap_dmm_tiler.c b/drivers/gpu/drm/omapdrm/omap_dmm_tiler.c
index 701c4c10e08b5..f926b4caf4498 100644
--- a/drivers/gpu/drm/omapdrm/omap_dmm_tiler.c
+++ b/drivers/gpu/drm/omapdrm/omap_dmm_tiler.c
@@ -969,12 +969,21 @@ static const struct dev_pm_ops omap_dmm_pm_ops = {
 };
 #endif
 
+#if defined(CONFIG_OF)
+static const struct of_device_id dmm_of_match[] = {
+	{ .compatible = "ti,omap4-dmm", },
+	{ .compatible = "ti,omap5-dmm", },
+	{},
+};
+#endif
+
 struct platform_driver omap_dmm_driver = {
 	.probe = omap_dmm_probe,
 	.remove = omap_dmm_remove,
 	.driver = {
 		.owner = THIS_MODULE,
 		.name = DMM_DRIVER_NAME,
+		.of_match_table = of_match_ptr(dmm_of_match),
 #ifdef CONFIG_PM
 		.pm = &omap_dmm_pm_ops,
 #endif
diff --git a/drivers/gpu/drm/omapdrm/omap_drv.c b/drivers/gpu/drm/omapdrm/omap_drv.c
index 13f294aeaefd2..bf39fcc49e0f1 100644
--- a/drivers/gpu/drm/omapdrm/omap_drv.c
+++ b/drivers/gpu/drm/omapdrm/omap_drv.c
@@ -86,6 +86,47 @@ static bool channel_used(struct drm_device *dev, enum omap_channel channel)
 
 	return false;
 }
+static void omap_disconnect_dssdevs(void)
+{
+	struct omap_dss_device *dssdev = NULL;
+
+	for_each_dss_dev(dssdev)
+		dssdev->driver->disconnect(dssdev);
+}
+
+static int omap_connect_dssdevs(void)
+{
+	int r;
+	struct omap_dss_device *dssdev = NULL;
+	bool no_displays = true;
+
+	for_each_dss_dev(dssdev) {
+		r = dssdev->driver->connect(dssdev);
+		if (r == -EPROBE_DEFER) {
+			omap_dss_put_device(dssdev);
+			goto cleanup;
+		} else if (r) {
+			dev_warn(dssdev->dev, "could not connect display: %s\n",
+				dssdev->name);
+		} else {
+			no_displays = false;
+		}
+	}
+
+	if (no_displays)
+		return -EPROBE_DEFER;
+
+	return 0;
+
+cleanup:
+	/*
+	 * if we are deferring probe, we disconnect the devices we previously
+	 * connected
+	 */
+	omap_disconnect_dssdevs();
+
+	return r;
+}
 
 static int omap_modeset_init(struct drm_device *dev)
 {
@@ -95,9 +136,6 @@ static int omap_modeset_init(struct drm_device *dev)
 	int num_mgrs = dss_feat_get_num_mgrs();
 	int num_crtcs;
 	int i, id = 0;
-	int r;
-
-	omap_crtc_pre_init();
 
 	drm_mode_config_init(dev);
 
@@ -119,26 +157,8 @@ static int omap_modeset_init(struct drm_device *dev)
 		enum omap_channel channel;
 		struct omap_overlay_manager *mgr;
 
-		if (!dssdev->driver) {
-			dev_warn(dev->dev, "%s has no driver.. skipping it\n",
-					dssdev->name);
+		if (!omapdss_device_is_connected(dssdev))
 			continue;
-		}
-
-		if (!(dssdev->driver->get_timings ||
-					dssdev->driver->read_edid)) {
-			dev_warn(dev->dev, "%s driver does not support "
-				"get_timings or read_edid.. skipping it!\n",
-				dssdev->name);
-			continue;
-		}
-
-		r = dssdev->driver->connect(dssdev);
-		if (r) {
-			dev_err(dev->dev, "could not connect display: %s\n",
-					dssdev->name);
-			continue;
-		}
 
 		encoder = omap_encoder_init(dev, dssdev);
 
@@ -497,16 +517,16 @@ static int dev_unload(struct drm_device *dev)
 	DBG("unload: dev=%p", dev);
 
 	drm_kms_helper_poll_fini(dev);
-	drm_vblank_cleanup(dev);
-	omap_drm_irq_uninstall(dev);
 
 	omap_fbdev_free(dev);
 	omap_modeset_free(dev);
 	omap_gem_deinit(dev);
 
-	flush_workqueue(priv->wq);
 	destroy_workqueue(priv->wq);
 
+	drm_vblank_cleanup(dev);
+	omap_drm_irq_uninstall(dev);
+
 	kfree(dev->dev_private);
 	dev->dev_private = NULL;
 
@@ -655,9 +675,19 @@ static void pdev_shutdown(struct platform_device *device)
 
 static int pdev_probe(struct platform_device *device)
 {
+	int r;
+
 	if (omapdss_is_initialized() == false)
 		return -EPROBE_DEFER;
 
+	omap_crtc_pre_init();
+
+	r = omap_connect_dssdevs();
+	if (r) {
+		omap_crtc_pre_uninit();
+		return r;
+	}
+
 	DBG("%s", device->name);
 	return drm_platform_init(&omap_drm_driver, device);
 }
@@ -666,8 +696,10 @@ static int pdev_remove(struct platform_device *device)
 {
 	DBG("");
 
-	drm_put_dev(platform_get_drvdata(device));
+	omap_disconnect_dssdevs();
+	omap_crtc_pre_uninit();
 
+	drm_put_dev(platform_get_drvdata(device));
 	return 0;
 }
 
diff --git a/drivers/gpu/drm/omapdrm/omap_drv.h b/drivers/gpu/drm/omapdrm/omap_drv.h
index c88fea32dbf67..428b2981fd685 100644
--- a/drivers/gpu/drm/omapdrm/omap_drv.h
+++ b/drivers/gpu/drm/omapdrm/omap_drv.h
@@ -145,6 +145,8 @@ irqreturn_t omap_irq_handler(int irq, void *arg);
 void omap_irq_preinstall(struct drm_device *dev);
 int omap_irq_postinstall(struct drm_device *dev);
 void omap_irq_uninstall(struct drm_device *dev);
+void __omap_irq_register(struct drm_device *dev, struct omap_drm_irq *irq);
+void __omap_irq_unregister(struct drm_device *dev, struct omap_drm_irq *irq);
 void omap_irq_register(struct drm_device *dev, struct omap_drm_irq *irq);
 void omap_irq_unregister(struct drm_device *dev, struct omap_drm_irq *irq);
 int omap_drm_irq_uninstall(struct drm_device *dev);
@@ -158,6 +160,7 @@ enum omap_channel omap_crtc_channel(struct drm_crtc *crtc);
 int omap_crtc_apply(struct drm_crtc *crtc,
 		struct omap_drm_apply *apply);
 void omap_crtc_pre_init(void);
+void omap_crtc_pre_uninit(void);
 struct drm_crtc *omap_crtc_init(struct drm_device *dev,
 		struct drm_plane *plane, enum omap_channel channel, int id);
 
diff --git a/drivers/gpu/drm/omapdrm/omap_encoder.c b/drivers/gpu/drm/omapdrm/omap_encoder.c
index 6a12e899235bf..5290a88c681db 100644
--- a/drivers/gpu/drm/omapdrm/omap_encoder.c
+++ b/drivers/gpu/drm/omapdrm/omap_encoder.c
@@ -51,6 +51,9 @@ struct omap_dss_device *omap_encoder_get_dssdev(struct drm_encoder *encoder)
 static void omap_encoder_destroy(struct drm_encoder *encoder)
 {
 	struct omap_encoder *omap_encoder = to_omap_encoder(encoder);
+
+	omap_encoder_set_enabled(encoder, false);
+
 	drm_encoder_cleanup(encoder);
 	kfree(omap_encoder);
 }
diff --git a/drivers/gpu/drm/omapdrm/omap_irq.c b/drivers/gpu/drm/omapdrm/omap_irq.c
index 0e5336e5a7915..f035d2bceae7d 100644
--- a/drivers/gpu/drm/omapdrm/omap_irq.c
+++ b/drivers/gpu/drm/omapdrm/omap_irq.c
@@ -45,12 +45,11 @@ static void omap_irq_update(struct drm_device *dev)
 	dispc_read_irqenable();        /* flush posted write */
 }
 
-void omap_irq_register(struct drm_device *dev, struct omap_drm_irq *irq)
+void __omap_irq_register(struct drm_device *dev, struct omap_drm_irq *irq)
 {
 	struct omap_drm_private *priv = dev->dev_private;
 	unsigned long flags;
 
-	dispc_runtime_get();
 	spin_lock_irqsave(&list_lock, flags);
 
 	if (!WARN_ON(irq->registered)) {
@@ -60,14 +59,21 @@ void omap_irq_register(struct drm_device *dev, struct omap_drm_irq *irq)
 	}
 
 	spin_unlock_irqrestore(&list_lock, flags);
+}
+
+void omap_irq_register(struct drm_device *dev, struct omap_drm_irq *irq)
+{
+	dispc_runtime_get();
+
+	__omap_irq_register(dev, irq);
+
 	dispc_runtime_put();
 }
 
-void omap_irq_unregister(struct drm_device *dev, struct omap_drm_irq *irq)
+void __omap_irq_unregister(struct drm_device *dev, struct omap_drm_irq *irq)
 {
 	unsigned long flags;
 
-	dispc_runtime_get();
 	spin_lock_irqsave(&list_lock, flags);
 
 	if (!WARN_ON(!irq->registered)) {
@@ -77,6 +83,14 @@ void omap_irq_unregister(struct drm_device *dev, struct omap_drm_irq *irq)
 	}
 
 	spin_unlock_irqrestore(&list_lock, flags);
+}
+
+void omap_irq_unregister(struct drm_device *dev, struct omap_drm_irq *irq)
+{
+	dispc_runtime_get();
+
+	__omap_irq_unregister(dev, irq);
+
 	dispc_runtime_put();
 }
 
diff --git a/drivers/gpu/drm/panel/panel-simple.c b/drivers/gpu/drm/panel/panel-simple.c
index 3e611afc93f47..59d52ca2c67fd 100644
--- a/drivers/gpu/drm/panel/panel-simple.c
+++ b/drivers/gpu/drm/panel/panel-simple.c
@@ -162,6 +162,7 @@ static int panel_simple_get_modes(struct drm_panel *panel)
 	/* probe EDID if a DDC bus is available */
 	if (p->ddc) {
 		struct edid *edid = drm_get_edid(panel->connector, p->ddc);
+		drm_mode_connector_update_edid_property(panel->connector, edid);
 		if (edid) {
 			num += drm_add_edid_modes(panel->connector, edid);
 			kfree(edid);
@@ -316,6 +317,28 @@ static const struct panel_desc auo_b101aw03 = {
 	},
 };
 
+static const struct drm_display_mode chunghwa_claa101wa01a_mode = {
+	.clock = 72070,
+	.hdisplay = 1366,
+	.hsync_start = 1366 + 58,
+	.hsync_end = 1366 + 58 + 58,
+	.htotal = 1366 + 58 + 58 + 58,
+	.vdisplay = 768,
+	.vsync_start = 768 + 4,
+	.vsync_end = 768 + 4 + 4,
+	.vtotal = 768 + 4 + 4 + 4,
+	.vrefresh = 60,
+};
+
+static const struct panel_desc chunghwa_claa101wa01a = {
+	.modes = &chunghwa_claa101wa01a_mode,
+	.num_modes = 1,
+	.size = {
+		.width = 220,
+		.height = 120,
+	},
+};
+
 static const struct drm_display_mode chunghwa_claa101wb01_mode = {
 	.clock = 69300,
 	.hdisplay = 1366,
@@ -338,13 +361,41 @@ static const struct panel_desc chunghwa_claa101wb01 = {
 	},
 };
 
+static const struct drm_display_mode samsung_ltn101nt05_mode = {
+	.clock = 54030,
+	.hdisplay = 1024,
+	.hsync_start = 1024 + 24,
+	.hsync_end = 1024 + 24 + 136,
+	.htotal = 1024 + 24 + 136 + 160,
+	.vdisplay = 600,
+	.vsync_start = 600 + 3,
+	.vsync_end = 600 + 3 + 6,
+	.vtotal = 600 + 3 + 6 + 61,
+	.vrefresh = 60,
+};
+
+static const struct panel_desc samsung_ltn101nt05 = {
+	.modes = &samsung_ltn101nt05_mode,
+	.num_modes = 1,
+	.size = {
+		.width = 1024,
+		.height = 600,
+	},
+};
+
 static const struct of_device_id platform_of_match[] = {
 	{
 		.compatible = "auo,b101aw03",
 		.data = &auo_b101aw03,
+	}, {
+		.compatible = "chunghwa,claa101wa01a",
+		.data = &chunghwa_claa101wa01a
 	}, {
 		.compatible = "chunghwa,claa101wb01",
 		.data = &chunghwa_claa101wb01
+	}, {
+		.compatible = "samsung,ltn101nt05",
+		.data = &samsung_ltn101nt05,
 	}, {
 		.compatible = "simple-panel",
 	}, {
diff --git a/drivers/gpu/drm/radeon/atombios_crtc.c b/drivers/gpu/drm/radeon/atombios_crtc.c
index 4cf678306c9c1..a9338c85630fe 100644
--- a/drivers/gpu/drm/radeon/atombios_crtc.c
+++ b/drivers/gpu/drm/radeon/atombios_crtc.c
@@ -209,6 +209,16 @@ static void atombios_enable_crtc_memreq(struct drm_crtc *crtc, int state)
 	atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
 }
 
+static const u32 vga_control_regs[6] =
+{
+	AVIVO_D1VGA_CONTROL,
+	AVIVO_D2VGA_CONTROL,
+	EVERGREEN_D3VGA_CONTROL,
+	EVERGREEN_D4VGA_CONTROL,
+	EVERGREEN_D5VGA_CONTROL,
+	EVERGREEN_D6VGA_CONTROL,
+};
+
 static void atombios_blank_crtc(struct drm_crtc *crtc, int state)
 {
 	struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc);
@@ -216,13 +226,23 @@ static void atombios_blank_crtc(struct drm_crtc *crtc, int state)
 	struct radeon_device *rdev = dev->dev_private;
 	int index = GetIndexIntoMasterTable(COMMAND, BlankCRTC);
 	BLANK_CRTC_PS_ALLOCATION args;
+	u32 vga_control = 0;
 
 	memset(&args, 0, sizeof(args));
 
+	if (ASIC_IS_DCE8(rdev)) {
+		vga_control = RREG32(vga_control_regs[radeon_crtc->crtc_id]);
+		WREG32(vga_control_regs[radeon_crtc->crtc_id], vga_control | 1);
+	}
+
 	args.ucCRTC = radeon_crtc->crtc_id;
 	args.ucBlanking = state;
 
 	atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
+
+	if (ASIC_IS_DCE8(rdev)) {
+		WREG32(vga_control_regs[radeon_crtc->crtc_id], vga_control);
+	}
 }
 
 static void atombios_powergate_crtc(struct drm_crtc *crtc, int state)
diff --git a/drivers/gpu/drm/radeon/cik.c b/drivers/gpu/drm/radeon/cik.c
index 6ffe824624fb5..e6419ca7cd375 100644
--- a/drivers/gpu/drm/radeon/cik.c
+++ b/drivers/gpu/drm/radeon/cik.c
@@ -3840,6 +3840,8 @@ static void cik_cp_gfx_enable(struct radeon_device *rdev, bool enable)
 	if (enable)
 		WREG32(CP_ME_CNTL, 0);
 	else {
+		if (rdev->asic->copy.copy_ring_index == RADEON_RING_TYPE_GFX_INDEX)
+			radeon_ttm_set_active_vram_size(rdev, rdev->mc.visible_vram_size);
 		WREG32(CP_ME_CNTL, (CP_ME_HALT | CP_PFP_HALT | CP_CE_HALT));
 		rdev->ring[RADEON_RING_TYPE_GFX_INDEX].ready = false;
 	}
@@ -4038,6 +4040,10 @@ static int cik_cp_gfx_resume(struct radeon_device *rdev)
 		rdev->ring[RADEON_RING_TYPE_GFX_INDEX].ready = false;
 		return r;
 	}
+
+	if (rdev->asic->copy.copy_ring_index == RADEON_RING_TYPE_GFX_INDEX)
+		radeon_ttm_set_active_vram_size(rdev, rdev->mc.real_vram_size);
+
 	return 0;
 }
 
diff --git a/drivers/gpu/drm/radeon/cik_sdma.c b/drivers/gpu/drm/radeon/cik_sdma.c
index 9abea87a92133..1ecb3f1070e35 100644
--- a/drivers/gpu/drm/radeon/cik_sdma.c
+++ b/drivers/gpu/drm/radeon/cik_sdma.c
@@ -250,7 +250,9 @@ static void cik_sdma_gfx_stop(struct radeon_device *rdev)
 	u32 rb_cntl, reg_offset;
 	int i;
 
-	radeon_ttm_set_active_vram_size(rdev, rdev->mc.visible_vram_size);
+	if ((rdev->asic->copy.copy_ring_index == R600_RING_TYPE_DMA_INDEX) ||
+	    (rdev->asic->copy.copy_ring_index == CAYMAN_RING_TYPE_DMA1_INDEX))
+		radeon_ttm_set_active_vram_size(rdev, rdev->mc.visible_vram_size);
 
 	for (i = 0; i < 2; i++) {
 		if (i == 0)
@@ -381,7 +383,9 @@ static int cik_sdma_gfx_resume(struct radeon_device *rdev)
 		}
 	}
 
-	radeon_ttm_set_active_vram_size(rdev, rdev->mc.real_vram_size);
+	if ((rdev->asic->copy.copy_ring_index == R600_RING_TYPE_DMA_INDEX) ||
+	    (rdev->asic->copy.copy_ring_index == CAYMAN_RING_TYPE_DMA1_INDEX))
+		radeon_ttm_set_active_vram_size(rdev, rdev->mc.real_vram_size);
 
 	return 0;
 }
diff --git a/drivers/gpu/drm/radeon/evergreen.c b/drivers/gpu/drm/radeon/evergreen.c
index 4116d02795966..f2b9e21ce4da0 100644
--- a/drivers/gpu/drm/radeon/evergreen.c
+++ b/drivers/gpu/drm/radeon/evergreen.c
@@ -4348,8 +4348,8 @@ void evergreen_disable_interrupt_state(struct radeon_device *rdev)
 		WREG32(GRPH_INT_CONTROL + EVERGREEN_CRTC5_REGISTER_OFFSET, 0);
 	}
 
-	/* only one DAC on DCE6 */
-	if (!ASIC_IS_DCE6(rdev))
+	/* only one DAC on DCE5 */
+	if (!ASIC_IS_DCE5(rdev))
 		WREG32(DACA_AUTODETECT_INT_CONTROL, 0);
 	WREG32(DACB_AUTODETECT_INT_CONTROL, 0);
 
diff --git a/drivers/gpu/drm/radeon/ni.c b/drivers/gpu/drm/radeon/ni.c
index 647b1d0fa62c3..ea932ac66fc66 100644
--- a/drivers/gpu/drm/radeon/ni.c
+++ b/drivers/gpu/drm/radeon/ni.c
@@ -1390,7 +1390,8 @@ static void cayman_cp_enable(struct radeon_device *rdev, bool enable)
 	if (enable)
 		WREG32(CP_ME_CNTL, 0);
 	else {
-		radeon_ttm_set_active_vram_size(rdev, rdev->mc.visible_vram_size);
+		if (rdev->asic->copy.copy_ring_index == RADEON_RING_TYPE_GFX_INDEX)
+			radeon_ttm_set_active_vram_size(rdev, rdev->mc.visible_vram_size);
 		WREG32(CP_ME_CNTL, (CP_ME_HALT | CP_PFP_HALT));
 		WREG32(SCRATCH_UMSK, 0);
 		rdev->ring[RADEON_RING_TYPE_GFX_INDEX].ready = false;
@@ -1663,6 +1664,9 @@ static int cayman_cp_resume(struct radeon_device *rdev)
 		return r;
 	}
 
+	if (rdev->asic->copy.copy_ring_index == RADEON_RING_TYPE_GFX_INDEX)
+		radeon_ttm_set_active_vram_size(rdev, rdev->mc.real_vram_size);
+
 	return 0;
 }
 
diff --git a/drivers/gpu/drm/radeon/ni_dma.c b/drivers/gpu/drm/radeon/ni_dma.c
index 51424ab794327..7cf96b15377fa 100644
--- a/drivers/gpu/drm/radeon/ni_dma.c
+++ b/drivers/gpu/drm/radeon/ni_dma.c
@@ -157,7 +157,9 @@ void cayman_dma_stop(struct radeon_device *rdev)
 {
 	u32 rb_cntl;
 
-	radeon_ttm_set_active_vram_size(rdev, rdev->mc.visible_vram_size);
+	if ((rdev->asic->copy.copy_ring_index == R600_RING_TYPE_DMA_INDEX) ||
+	    (rdev->asic->copy.copy_ring_index == CAYMAN_RING_TYPE_DMA1_INDEX))
+		radeon_ttm_set_active_vram_size(rdev, rdev->mc.visible_vram_size);
 
 	/* dma0 */
 	rb_cntl = RREG32(DMA_RB_CNTL + DMA0_REGISTER_OFFSET);
@@ -259,7 +261,9 @@ int cayman_dma_resume(struct radeon_device *rdev)
 		}
 	}
 
-	radeon_ttm_set_active_vram_size(rdev, rdev->mc.real_vram_size);
+	if ((rdev->asic->copy.copy_ring_index == R600_RING_TYPE_DMA_INDEX) ||
+	    (rdev->asic->copy.copy_ring_index == CAYMAN_RING_TYPE_DMA1_INDEX))
+		radeon_ttm_set_active_vram_size(rdev, rdev->mc.real_vram_size);
 
 	return 0;
 }
diff --git a/drivers/gpu/drm/radeon/r600.c b/drivers/gpu/drm/radeon/r600.c
index 3dce370adc1b7..56140b4e5bb2e 100644
--- a/drivers/gpu/drm/radeon/r600.c
+++ b/drivers/gpu/drm/radeon/r600.c
@@ -2254,7 +2254,8 @@ void r600_pciep_wreg(struct radeon_device *rdev, u32 reg, u32 v)
  */
 void r600_cp_stop(struct radeon_device *rdev)
 {
-	radeon_ttm_set_active_vram_size(rdev, rdev->mc.visible_vram_size);
+	if (rdev->asic->copy.copy_ring_index == RADEON_RING_TYPE_GFX_INDEX)
+		radeon_ttm_set_active_vram_size(rdev, rdev->mc.visible_vram_size);
 	WREG32(R_0086D8_CP_ME_CNTL, S_0086D8_CP_ME_HALT(1));
 	WREG32(SCRATCH_UMSK, 0);
 	rdev->ring[RADEON_RING_TYPE_GFX_INDEX].ready = false;
@@ -2612,6 +2613,10 @@ int r600_cp_resume(struct radeon_device *rdev)
 		ring->ready = false;
 		return r;
 	}
+
+	if (rdev->asic->copy.copy_ring_index == RADEON_RING_TYPE_GFX_INDEX)
+		radeon_ttm_set_active_vram_size(rdev, rdev->mc.real_vram_size);
+
 	return 0;
 }
 
@@ -2895,12 +2900,6 @@ static int r600_startup(struct radeon_device *rdev)
 		return r;
 	}
 
-	r = radeon_fence_driver_start_ring(rdev, R600_RING_TYPE_DMA_INDEX);
-	if (r) {
-		dev_err(rdev->dev, "failed initializing DMA fences (%d).\n", r);
-		return r;
-	}
-
 	/* Enable IRQ */
 	if (!rdev->irq.installed) {
 		r = radeon_irq_kms_init(rdev);
@@ -2922,12 +2921,6 @@ static int r600_startup(struct radeon_device *rdev)
 	if (r)
 		return r;
 
-	ring = &rdev->ring[R600_RING_TYPE_DMA_INDEX];
-	r = radeon_ring_init(rdev, ring, ring->ring_size, R600_WB_DMA_RPTR_OFFSET,
-			     DMA_PACKET(DMA_PACKET_NOP, 0, 0, 0));
-	if (r)
-		return r;
-
 	r = r600_cp_load_microcode(rdev);
 	if (r)
 		return r;
@@ -2935,10 +2928,6 @@ static int r600_startup(struct radeon_device *rdev)
 	if (r)
 		return r;
 
-	r = r600_dma_resume(rdev);
-	if (r)
-		return r;
-
 	r = radeon_ib_pool_init(rdev);
 	if (r) {
 		dev_err(rdev->dev, "IB initialization failed (%d).\n", r);
@@ -2997,7 +2986,6 @@ int r600_suspend(struct radeon_device *rdev)
 	radeon_pm_suspend(rdev);
 	r600_audio_fini(rdev);
 	r600_cp_stop(rdev);
-	r600_dma_stop(rdev);
 	r600_irq_suspend(rdev);
 	radeon_wb_disable(rdev);
 	r600_pcie_gart_disable(rdev);
@@ -3077,9 +3065,6 @@ int r600_init(struct radeon_device *rdev)
 	rdev->ring[RADEON_RING_TYPE_GFX_INDEX].ring_obj = NULL;
 	r600_ring_init(rdev, &rdev->ring[RADEON_RING_TYPE_GFX_INDEX], 1024 * 1024);
 
-	rdev->ring[R600_RING_TYPE_DMA_INDEX].ring_obj = NULL;
-	r600_ring_init(rdev, &rdev->ring[R600_RING_TYPE_DMA_INDEX], 64 * 1024);
-
 	rdev->ih.ring_obj = NULL;
 	r600_ih_ring_init(rdev, 64 * 1024);
 
@@ -3092,7 +3077,6 @@ int r600_init(struct radeon_device *rdev)
 	if (r) {
 		dev_err(rdev->dev, "disabling GPU acceleration\n");
 		r600_cp_fini(rdev);
-		r600_dma_fini(rdev);
 		r600_irq_fini(rdev);
 		radeon_wb_fini(rdev);
 		radeon_ib_pool_fini(rdev);
@@ -3109,7 +3093,6 @@ void r600_fini(struct radeon_device *rdev)
 	radeon_pm_fini(rdev);
 	r600_audio_fini(rdev);
 	r600_cp_fini(rdev);
-	r600_dma_fini(rdev);
 	r600_irq_fini(rdev);
 	radeon_wb_fini(rdev);
 	radeon_ib_pool_fini(rdev);
diff --git a/drivers/gpu/drm/radeon/r600_dma.c b/drivers/gpu/drm/radeon/r600_dma.c
index 3452c8410bd76..b2d4c91e6272e 100644
--- a/drivers/gpu/drm/radeon/r600_dma.c
+++ b/drivers/gpu/drm/radeon/r600_dma.c
@@ -100,7 +100,8 @@ void r600_dma_stop(struct radeon_device *rdev)
 {
 	u32 rb_cntl = RREG32(DMA_RB_CNTL);
 
-	radeon_ttm_set_active_vram_size(rdev, rdev->mc.visible_vram_size);
+	if (rdev->asic->copy.copy_ring_index == R600_RING_TYPE_DMA_INDEX)
+		radeon_ttm_set_active_vram_size(rdev, rdev->mc.visible_vram_size);
 
 	rb_cntl &= ~DMA_RB_ENABLE;
 	WREG32(DMA_RB_CNTL, rb_cntl);
@@ -187,7 +188,8 @@ int r600_dma_resume(struct radeon_device *rdev)
 		return r;
 	}
 
-	radeon_ttm_set_active_vram_size(rdev, rdev->mc.real_vram_size);
+	if (rdev->asic->copy.copy_ring_index == R600_RING_TYPE_DMA_INDEX)
+		radeon_ttm_set_active_vram_size(rdev, rdev->mc.real_vram_size);
 
 	return 0;
 }
diff --git a/drivers/gpu/drm/radeon/radeon.h b/drivers/gpu/drm/radeon/radeon.h
index c5519ca4bbc4a..4a8ac1cd6b4c6 100644
--- a/drivers/gpu/drm/radeon/radeon.h
+++ b/drivers/gpu/drm/radeon/radeon.h
@@ -867,6 +867,8 @@ struct radeon_vm {
 	struct radeon_fence		*fence;
 	/* last flush or NULL if we still need to flush */
 	struct radeon_fence		*last_flush;
+	/* last use of vmid */
+	struct radeon_fence		*last_id_use;
 };
 
 struct radeon_vm_manager {
diff --git a/drivers/gpu/drm/radeon/radeon_atombios.c b/drivers/gpu/drm/radeon/radeon_atombios.c
index f48bd6dc10cda..30844814c25a3 100644
--- a/drivers/gpu/drm/radeon/radeon_atombios.c
+++ b/drivers/gpu/drm/radeon/radeon_atombios.c
@@ -3938,6 +3938,10 @@ void radeon_atom_initialize_bios_scratch_regs(struct drm_device *dev)
 	/* tell the bios not to handle mode switching */
 	bios_6_scratch |= ATOM_S6_ACC_BLOCK_DISPLAY_SWITCH;
 
+	/* clear the vbios dpms state */
+	if (ASIC_IS_DCE4(rdev))
+		bios_2_scratch &= ~ATOM_S2_DEVICE_DPMS_STATE;
+
 	if (rdev->family >= CHIP_R600) {
 		WREG32(R600_BIOS_2_SCRATCH, bios_2_scratch);
 		WREG32(R600_BIOS_6_SCRATCH, bios_6_scratch);
diff --git a/drivers/gpu/drm/radeon/radeon_cs.c b/drivers/gpu/drm/radeon/radeon_cs.c
index a8e3342fd4a9d..dfb5a1db87d4a 100644
--- a/drivers/gpu/drm/radeon/radeon_cs.c
+++ b/drivers/gpu/drm/radeon/radeon_cs.c
@@ -138,7 +138,7 @@ static int radeon_cs_get_ring(struct radeon_cs_parser *p, u32 ring, s32 priority
 				p->ring = R600_RING_TYPE_DMA_INDEX;
 			else
 				p->ring = CAYMAN_RING_TYPE_DMA1_INDEX;
-		} else if (p->rdev->family >= CHIP_R600) {
+		} else if (p->rdev->family >= CHIP_RV770) {
 			p->ring = R600_RING_TYPE_DMA_INDEX;
 		} else {
 			return -EINVAL;
diff --git a/drivers/gpu/drm/radeon/radeon_drv.c b/drivers/gpu/drm/radeon/radeon_drv.c
index 1235a78fbba15..ec8c388eec176 100644
--- a/drivers/gpu/drm/radeon/radeon_drv.c
+++ b/drivers/gpu/drm/radeon/radeon_drv.c
@@ -405,6 +405,9 @@ static int radeon_pmops_runtime_suspend(struct device *dev)
 	if (radeon_runtime_pm == 0)
 		return -EINVAL;
 
+	if (radeon_runtime_pm == -1 && !radeon_is_px())
+		return -EINVAL;
+
 	drm_dev->switch_power_state = DRM_SWITCH_POWER_CHANGING;
 	drm_kms_helper_poll_disable(drm_dev);
 	vga_switcheroo_set_dynamic_switch(pdev, VGA_SWITCHEROO_OFF);
@@ -427,6 +430,9 @@ static int radeon_pmops_runtime_resume(struct device *dev)
 	if (radeon_runtime_pm == 0)
 		return -EINVAL;
 
+	if (radeon_runtime_pm == -1 && !radeon_is_px())
+		return -EINVAL;
+
 	drm_dev->switch_power_state = DRM_SWITCH_POWER_CHANGING;
 
 	pci_set_power_state(pdev, PCI_D0);
diff --git a/drivers/gpu/drm/radeon/radeon_fence.c b/drivers/gpu/drm/radeon/radeon_fence.c
index 866744e47cfac..c37cb79a9489a 100644
--- a/drivers/gpu/drm/radeon/radeon_fence.c
+++ b/drivers/gpu/drm/radeon/radeon_fence.c
@@ -121,7 +121,7 @@ int radeon_fence_emit(struct radeon_device *rdev,
 	(*fence)->seq = ++rdev->fence_drv[ring].sync_seq[ring];
 	(*fence)->ring = ring;
 	radeon_fence_ring_emit(rdev, ring, *fence);
-	trace_radeon_fence_emit(rdev->ddev, (*fence)->seq);
+	trace_radeon_fence_emit(rdev->ddev, ring, (*fence)->seq);
 	return 0;
 }
 
@@ -313,7 +313,7 @@ static int radeon_fence_wait_seq(struct radeon_device *rdev, u64 *target_seq,
 				continue;
 
 			last_seq[i] = atomic64_read(&rdev->fence_drv[i].last_seq);
-			trace_radeon_fence_wait_begin(rdev->ddev, target_seq[i]);
+			trace_radeon_fence_wait_begin(rdev->ddev, i, target_seq[i]);
 			radeon_irq_kms_sw_irq_get(rdev, i);
 		}
 
@@ -332,7 +332,7 @@ static int radeon_fence_wait_seq(struct radeon_device *rdev, u64 *target_seq,
 				continue;
 
 			radeon_irq_kms_sw_irq_put(rdev, i);
-			trace_radeon_fence_wait_end(rdev->ddev, target_seq[i]);
+			trace_radeon_fence_wait_end(rdev->ddev, i, target_seq[i]);
 		}
 
 		if (unlikely(r < 0))
diff --git a/drivers/gpu/drm/radeon/radeon_gart.c b/drivers/gpu/drm/radeon/radeon_gart.c
index 96e440061bdbf..a8f9b463bf2a4 100644
--- a/drivers/gpu/drm/radeon/radeon_gart.c
+++ b/drivers/gpu/drm/radeon/radeon_gart.c
@@ -713,7 +713,7 @@ struct radeon_fence *radeon_vm_grab_id(struct radeon_device *rdev,
 	unsigned i;
 
 	/* check if the id is still valid */
-	if (vm->fence && vm->fence == rdev->vm_manager.active[vm->id])
+	if (vm->last_id_use && vm->last_id_use == rdev->vm_manager.active[vm->id])
 		return NULL;
 
 	/* we definately need to flush */
@@ -726,6 +726,7 @@ struct radeon_fence *radeon_vm_grab_id(struct radeon_device *rdev,
 		if (fence == NULL) {
 			/* found a free one */
 			vm->id = i;
+			trace_radeon_vm_grab_id(vm->id, ring);
 			return NULL;
 		}
 
@@ -769,6 +770,9 @@ void radeon_vm_fence(struct radeon_device *rdev,
 
 	radeon_fence_unref(&vm->fence);
 	vm->fence = radeon_fence_ref(fence);
+
+	radeon_fence_unref(&vm->last_id_use);
+	vm->last_id_use = radeon_fence_ref(fence);
 }
 
 /**
@@ -1303,6 +1307,8 @@ void radeon_vm_init(struct radeon_device *rdev, struct radeon_vm *vm)
 {
 	vm->id = 0;
 	vm->fence = NULL;
+	vm->last_flush = NULL;
+	vm->last_id_use = NULL;
 	mutex_init(&vm->mutex);
 	INIT_LIST_HEAD(&vm->list);
 	INIT_LIST_HEAD(&vm->va);
@@ -1341,5 +1347,6 @@ void radeon_vm_fini(struct radeon_device *rdev, struct radeon_vm *vm)
 	}
 	radeon_fence_unref(&vm->fence);
 	radeon_fence_unref(&vm->last_flush);
+	radeon_fence_unref(&vm->last_id_use);
 	mutex_unlock(&vm->mutex);
 }
diff --git a/drivers/gpu/drm/radeon/radeon_trace.h b/drivers/gpu/drm/radeon/radeon_trace.h
index 0473257d40788..f749f2c3bbdb8 100644
--- a/drivers/gpu/drm/radeon/radeon_trace.h
+++ b/drivers/gpu/drm/radeon/radeon_trace.h
@@ -106,42 +106,45 @@ TRACE_EVENT(radeon_vm_set_page,
 
 DECLARE_EVENT_CLASS(radeon_fence_request,
 
-	    TP_PROTO(struct drm_device *dev, u32 seqno),
+	    TP_PROTO(struct drm_device *dev, int ring, u32 seqno),
 
-	    TP_ARGS(dev, seqno),
+	    TP_ARGS(dev, ring, seqno),
 
 	    TP_STRUCT__entry(
 			     __field(u32, dev)
+			     __field(int, ring)
 			     __field(u32, seqno)
 			     ),
 
 	    TP_fast_assign(
 			   __entry->dev = dev->primary->index;
+			   __entry->ring = ring;
 			   __entry->seqno = seqno;
 			   ),
 
-	    TP_printk("dev=%u, seqno=%u", __entry->dev, __entry->seqno)
+	    TP_printk("dev=%u, ring=%d, seqno=%u",
+		      __entry->dev, __entry->ring, __entry->seqno)
 );
 
 DEFINE_EVENT(radeon_fence_request, radeon_fence_emit,
 
-	    TP_PROTO(struct drm_device *dev, u32 seqno),
+	    TP_PROTO(struct drm_device *dev, int ring, u32 seqno),
 
-	    TP_ARGS(dev, seqno)
+	    TP_ARGS(dev, ring, seqno)
 );
 
 DEFINE_EVENT(radeon_fence_request, radeon_fence_wait_begin,
 
-	    TP_PROTO(struct drm_device *dev, u32 seqno),
+	    TP_PROTO(struct drm_device *dev, int ring, u32 seqno),
 
-	    TP_ARGS(dev, seqno)
+	    TP_ARGS(dev, ring, seqno)
 );
 
 DEFINE_EVENT(radeon_fence_request, radeon_fence_wait_end,
 
-	    TP_PROTO(struct drm_device *dev, u32 seqno),
+	    TP_PROTO(struct drm_device *dev, int ring, u32 seqno),
 
-	    TP_ARGS(dev, seqno)
+	    TP_ARGS(dev, ring, seqno)
 );
 
 DECLARE_EVENT_CLASS(radeon_semaphore_request,
diff --git a/drivers/gpu/drm/radeon/rv770.c b/drivers/gpu/drm/radeon/rv770.c
index 18e02889ec7d7..6c772e58c7845 100644
--- a/drivers/gpu/drm/radeon/rv770.c
+++ b/drivers/gpu/drm/radeon/rv770.c
@@ -1071,7 +1071,8 @@ static void rv770_mc_program(struct radeon_device *rdev)
  */
 void r700_cp_stop(struct radeon_device *rdev)
 {
-	radeon_ttm_set_active_vram_size(rdev, rdev->mc.visible_vram_size);
+	if (rdev->asic->copy.copy_ring_index == RADEON_RING_TYPE_GFX_INDEX)
+		radeon_ttm_set_active_vram_size(rdev, rdev->mc.visible_vram_size);
 	WREG32(CP_ME_CNTL, (CP_ME_HALT | CP_PFP_HALT));
 	WREG32(SCRATCH_UMSK, 0);
 	rdev->ring[RADEON_RING_TYPE_GFX_INDEX].ready = false;
diff --git a/drivers/gpu/drm/radeon/si.c b/drivers/gpu/drm/radeon/si.c
index 07ce58716e44c..09ec4f6c53bb2 100644
--- a/drivers/gpu/drm/radeon/si.c
+++ b/drivers/gpu/drm/radeon/si.c
@@ -3249,7 +3249,8 @@ static void si_cp_enable(struct radeon_device *rdev, bool enable)
 	if (enable)
 		WREG32(CP_ME_CNTL, 0);
 	else {
-		radeon_ttm_set_active_vram_size(rdev, rdev->mc.visible_vram_size);
+		if (rdev->asic->copy.copy_ring_index == RADEON_RING_TYPE_GFX_INDEX)
+			radeon_ttm_set_active_vram_size(rdev, rdev->mc.visible_vram_size);
 		WREG32(CP_ME_CNTL, (CP_ME_HALT | CP_PFP_HALT | CP_CE_HALT));
 		WREG32(SCRATCH_UMSK, 0);
 		rdev->ring[RADEON_RING_TYPE_GFX_INDEX].ready = false;
@@ -3510,6 +3511,9 @@ static int si_cp_resume(struct radeon_device *rdev)
 
 	si_enable_gui_idle_interrupt(rdev, true);
 
+	if (rdev->asic->copy.copy_ring_index == RADEON_RING_TYPE_GFX_INDEX)
+		radeon_ttm_set_active_vram_size(rdev, rdev->mc.real_vram_size);
+
 	return 0;
 }
 
@@ -5678,7 +5682,7 @@ static void si_disable_interrupt_state(struct radeon_device *rdev)
 	}
 
 	if (!ASIC_IS_NODCE(rdev)) {
-		WREG32(DACA_AUTODETECT_INT_CONTROL, 0);
+		WREG32(DAC_AUTODETECT_INT_CONTROL, 0);
 
 		tmp = RREG32(DC_HPD1_INT_CONTROL) & DC_HPDx_INT_POLARITY;
 		WREG32(DC_HPD1_INT_CONTROL, tmp);
diff --git a/drivers/gpu/drm/radeon/si_dpm.c b/drivers/gpu/drm/radeon/si_dpm.c
index 36a5da4791ce7..0471501338fbb 100644
--- a/drivers/gpu/drm/radeon/si_dpm.c
+++ b/drivers/gpu/drm/radeon/si_dpm.c
@@ -3590,10 +3590,9 @@ static void si_program_display_gap(struct radeon_device *rdev)
 
 	/* Setting this to false forces the performance state to low if the crtcs are disabled.
 	 * This can be a problem on PowerXpress systems or if you want to use the card
-	 * for offscreen rendering or compute if there are no crtcs enabled.  Set it to
-	 * true for now so that performance scales even if the displays are off.
+	 * for offscreen rendering or compute if there are no crtcs enabled.
 	 */
-	si_notify_smc_display_change(rdev, true /*rdev->pm.dpm.new_active_crtc_count > 0*/);
+	si_notify_smc_display_change(rdev, rdev->pm.dpm.new_active_crtc_count > 0);
 }
 
 static void si_enable_spread_spectrum(struct radeon_device *rdev, bool enable)
diff --git a/drivers/gpu/drm/radeon/sid.h b/drivers/gpu/drm/radeon/sid.h
index caa3e61a38c25..9239a6d291280 100644
--- a/drivers/gpu/drm/radeon/sid.h
+++ b/drivers/gpu/drm/radeon/sid.h
@@ -822,7 +822,7 @@
 #       define GRPH_PFLIP_INT_MASK                      (1 << 0)
 #       define GRPH_PFLIP_INT_TYPE                      (1 << 8)
 
-#define	DACA_AUTODETECT_INT_CONTROL			0x66c8
+#define	DAC_AUTODETECT_INT_CONTROL			0x67c8
 
 #define DC_HPD1_INT_STATUS                              0x601c
 #define DC_HPD2_INT_STATUS                              0x6028
diff --git a/drivers/gpu/drm/tegra/dc.c b/drivers/gpu/drm/tegra/dc.c
index 386f3b4b00940..9336006b475d7 100644
--- a/drivers/gpu/drm/tegra/dc.c
+++ b/drivers/gpu/drm/tegra/dc.c
@@ -1100,8 +1100,6 @@ static int tegra_dc_init(struct host1x_client *client)
 	struct tegra_dc *dc = host1x_client_to_dc(client);
 	int err;
 
-	dc->pipe = tegra->drm->mode_config.num_crtc;
-
 	drm_crtc_init(tegra->drm, &dc->base, &tegra_crtc_funcs);
 	drm_mode_crtc_set_gamma_size(&dc->base, 256);
 	drm_crtc_helper_add(&dc->base, &tegra_crtc_helper_funcs);
@@ -1187,6 +1185,41 @@ static const struct of_device_id tegra_dc_of_match[] = {
 	}
 };
 
+static int tegra_dc_parse_dt(struct tegra_dc *dc)
+{
+	struct device_node *np;
+	u32 value = 0;
+	int err;
+
+	err = of_property_read_u32(dc->dev->of_node, "nvidia,head", &value);
+	if (err < 0) {
+		dev_err(dc->dev, "missing \"nvidia,head\" property\n");
+
+		/*
+		 * If the nvidia,head property isn't present, try to find the
+		 * correct head number by looking up the position of this
+		 * display controller's node within the device tree. Assuming
+		 * that the nodes are ordered properly in the DTS file and
+		 * that the translation into a flattened device tree blob
+		 * preserves that ordering this will actually yield the right
+		 * head number.
+		 *
+		 * If those assumptions don't hold, this will still work for
+		 * cases where only a single display controller is used.
+		 */
+		for_each_matching_node(np, tegra_dc_of_match) {
+			if (np == dc->dev->of_node)
+				break;
+
+			value++;
+		}
+	}
+
+	dc->pipe = value;
+
+	return 0;
+}
+
 static int tegra_dc_probe(struct platform_device *pdev)
 {
 	const struct of_device_id *id;
@@ -1207,6 +1240,10 @@ static int tegra_dc_probe(struct platform_device *pdev)
 	dc->dev = &pdev->dev;
 	dc->soc = id->data;
 
+	err = tegra_dc_parse_dt(dc);
+	if (err < 0)
+		return err;
+
 	dc->clk = devm_clk_get(&pdev->dev, NULL);
 	if (IS_ERR(dc->clk)) {
 		dev_err(&pdev->dev, "failed to get clock\n");
diff --git a/drivers/gpu/drm/tegra/hdmi.c b/drivers/gpu/drm/tegra/hdmi.c
index bc9cb1ac709b1..6928015d11a49 100644
--- a/drivers/gpu/drm/tegra/hdmi.c
+++ b/drivers/gpu/drm/tegra/hdmi.c
@@ -1418,9 +1418,6 @@ static int tegra_hdmi_probe(struct platform_device *pdev)
 		return err;
 
 	regs = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-	if (!regs)
-		return -ENXIO;
-
 	hdmi->regs = devm_ioremap_resource(&pdev->dev, regs);
 	if (IS_ERR(hdmi->regs))
 		return PTR_ERR(hdmi->regs);
diff --git a/drivers/gpu/drm/tegra/output.c b/drivers/gpu/drm/tegra/output.c
index f1b5030f55e33..57cecbd18ca88 100644
--- a/drivers/gpu/drm/tegra/output.c
+++ b/drivers/gpu/drm/tegra/output.c
@@ -18,6 +18,10 @@ static int tegra_connector_get_modes(struct drm_connector *connector)
 	struct edid *edid = NULL;
 	int err = 0;
 
+	/*
+	 * If the panel provides one or more modes, use them exclusively and
+	 * ignore any other means of obtaining a mode.
+	 */
 	if (output->panel) {
 		err = output->panel->funcs->get_modes(output->panel);
 		if (err > 0)
@@ -187,8 +191,7 @@ int tegra_output_probe(struct tegra_output *output)
 {
 	struct device_node *ddc, *panel;
 	enum of_gpio_flags flags;
-	size_t size;
-	int err;
+	int err, size;
 
 	if (!output->of_node)
 		output->of_node = output->dev->of_node;
diff --git a/drivers/gpu/drm/tegra/rgb.c b/drivers/gpu/drm/tegra/rgb.c
index 03885bb8dcc04..338f7f6561d70 100644
--- a/drivers/gpu/drm/tegra/rgb.c
+++ b/drivers/gpu/drm/tegra/rgb.c
@@ -258,7 +258,7 @@ int tegra_dc_rgb_init(struct drm_device *drm, struct tegra_dc *dc)
 	 * RGB outputs are an exception, so we make sure they can be attached
 	 * to only their parent display controller.
 	 */
-	rgb->output.encoder.possible_crtcs = 1 << dc->pipe;
+	rgb->output.encoder.possible_crtcs = drm_crtc_mask(&dc->base);
 
 	return 0;
 }
diff --git a/drivers/gpu/host1x/hw/intr_hw.c b/drivers/gpu/host1x/hw/intr_hw.c
index b26dcc83bc1b3..db9017adfe2bb 100644
--- a/drivers/gpu/host1x/hw/intr_hw.c
+++ b/drivers/gpu/host1x/hw/intr_hw.c
@@ -20,7 +20,6 @@
 #include <linux/interrupt.h>
 #include <linux/irq.h>
 #include <linux/io.h>
-#include <asm/mach/irq.h>
 
 #include "../intr.h"
 #include "../dev.h"
diff --git a/drivers/hwmon/coretemp.c b/drivers/hwmon/coretemp.c
index 78be66176840d..9425098928957 100644
--- a/drivers/hwmon/coretemp.c
+++ b/drivers/hwmon/coretemp.c
@@ -52,7 +52,7 @@ MODULE_PARM_DESC(tjmax, "TjMax value in degrees Celsius");
 
 #define BASE_SYSFS_ATTR_NO	2	/* Sysfs Base attr no for coretemp */
 #define NUM_REAL_CORES		32	/* Number of Real cores per cpu */
-#define CORETEMP_NAME_LENGTH	17	/* String Length of attrs */
+#define CORETEMP_NAME_LENGTH	19	/* String Length of attrs */
 #define MAX_CORE_ATTRS		4	/* Maximum no of basic attrs */
 #define TOTAL_ATTRS		(MAX_CORE_ATTRS + 1)
 #define MAX_CORE_DATA		(NUM_REAL_CORES + BASE_SYSFS_ATTR_NO)
diff --git a/drivers/md/md.c b/drivers/md/md.c
index 21f4d7ff0da22..369d919bdafef 100644
--- a/drivers/md/md.c
+++ b/drivers/md/md.c
@@ -1077,6 +1077,7 @@ static int super_90_validate(struct mddev *mddev, struct md_rdev *rdev)
 	rdev->raid_disk = -1;
 	clear_bit(Faulty, &rdev->flags);
 	clear_bit(In_sync, &rdev->flags);
+	clear_bit(Bitmap_sync, &rdev->flags);
 	clear_bit(WriteMostly, &rdev->flags);
 
 	if (mddev->raid_disks == 0) {
@@ -1155,6 +1156,8 @@ static int super_90_validate(struct mddev *mddev, struct md_rdev *rdev)
 		 */
 		if (ev1 < mddev->bitmap->events_cleared)
 			return 0;
+		if (ev1 < mddev->events)
+			set_bit(Bitmap_sync, &rdev->flags);
 	} else {
 		if (ev1 < mddev->events)
 			/* just a hot-add of a new device, leave raid_disk at -1 */
@@ -1563,6 +1566,7 @@ static int super_1_validate(struct mddev *mddev, struct md_rdev *rdev)
 	rdev->raid_disk = -1;
 	clear_bit(Faulty, &rdev->flags);
 	clear_bit(In_sync, &rdev->flags);
+	clear_bit(Bitmap_sync, &rdev->flags);
 	clear_bit(WriteMostly, &rdev->flags);
 
 	if (mddev->raid_disks == 0) {
@@ -1645,6 +1649,8 @@ static int super_1_validate(struct mddev *mddev, struct md_rdev *rdev)
 		 */
 		if (ev1 < mddev->bitmap->events_cleared)
 			return 0;
+		if (ev1 < mddev->events)
+			set_bit(Bitmap_sync, &rdev->flags);
 	} else {
 		if (ev1 < mddev->events)
 			/* just a hot-add of a new device, leave raid_disk at -1 */
@@ -2788,6 +2794,7 @@ slot_store(struct md_rdev *rdev, const char *buf, size_t len)
 		else
 			rdev->saved_raid_disk = -1;
 		clear_bit(In_sync, &rdev->flags);
+		clear_bit(Bitmap_sync, &rdev->flags);
 		err = rdev->mddev->pers->
 			hot_add_disk(rdev->mddev, rdev);
 		if (err) {
@@ -5760,6 +5767,7 @@ static int add_new_disk(struct mddev * mddev, mdu_disk_info_t *info)
 			    info->raid_disk < mddev->raid_disks) {
 				rdev->raid_disk = info->raid_disk;
 				set_bit(In_sync, &rdev->flags);
+				clear_bit(Bitmap_sync, &rdev->flags);
 			} else
 				rdev->raid_disk = -1;
 		} else
@@ -7706,7 +7714,8 @@ static int remove_and_add_spares(struct mddev *mddev,
 		if (test_bit(Faulty, &rdev->flags))
 			continue;
 		if (mddev->ro &&
-		    rdev->saved_raid_disk < 0)
+		    ! (rdev->saved_raid_disk >= 0 &&
+		       !test_bit(Bitmap_sync, &rdev->flags)))
 			continue;
 
 		rdev->recovery_offset = 0;
@@ -7787,9 +7796,12 @@ void md_check_recovery(struct mddev *mddev)
 			 * As we only add devices that are already in-sync,
 			 * we can activate the spares immediately.
 			 */
-			clear_bit(MD_RECOVERY_NEEDED, &mddev->recovery);
 			remove_and_add_spares(mddev, NULL);
-			mddev->pers->spare_active(mddev);
+			/* There is no thread, but we need to call
+			 * ->spare_active and clear saved_raid_disk
+			 */
+			md_reap_sync_thread(mddev);
+			clear_bit(MD_RECOVERY_NEEDED, &mddev->recovery);
 			goto unlock;
 		}
 
diff --git a/drivers/md/md.h b/drivers/md/md.h
index 2f5cc8a7ef3ed..0095ec84ffc7b 100644
--- a/drivers/md/md.h
+++ b/drivers/md/md.h
@@ -129,6 +129,9 @@ struct md_rdev {
 enum flag_bits {
 	Faulty,			/* device is known to have a fault */
 	In_sync,		/* device is in_sync with rest of array */
+	Bitmap_sync,		/* ..actually, not quite In_sync.  Need a
+				 * bitmap-based recovery to get fully in sync
+				 */
 	Unmerged,		/* device is being added to array and should
 				 * be considerred for bvec_merge_fn but not
 				 * yet for actual IO
diff --git a/drivers/md/raid1.c b/drivers/md/raid1.c
index 1e5a540995e93..a49cfcc7a3431 100644
--- a/drivers/md/raid1.c
+++ b/drivers/md/raid1.c
@@ -924,9 +924,8 @@ static sector_t wait_barrier(struct r1conf *conf, struct bio *bio)
 				conf->next_window_requests++;
 			else
 				conf->current_window_requests++;
-		}
-		if (bio->bi_sector >= conf->start_next_window)
 			sector = conf->start_next_window;
+		}
 	}
 
 	conf->nr_pending++;
diff --git a/drivers/md/raid10.c b/drivers/md/raid10.c
index c504e8389e69e..06eeb99ea6fc5 100644
--- a/drivers/md/raid10.c
+++ b/drivers/md/raid10.c
@@ -1319,7 +1319,7 @@ static void make_request(struct mddev *mddev, struct bio * bio)
 			/* Could not read all from this device, so we will
 			 * need another r10_bio.
 			 */
-			sectors_handled = (r10_bio->sectors + max_sectors
+			sectors_handled = (r10_bio->sector + max_sectors
 					   - bio->bi_sector);
 			r10_bio->sectors = max_sectors;
 			spin_lock_irq(&conf->device_lock);
@@ -1327,7 +1327,7 @@ static void make_request(struct mddev *mddev, struct bio * bio)
 				bio->bi_phys_segments = 2;
 			else
 				bio->bi_phys_segments++;
-			spin_unlock(&conf->device_lock);
+			spin_unlock_irq(&conf->device_lock);
 			/* Cannot call generic_make_request directly
 			 * as that will be queued in __generic_make_request
 			 * and subsequent mempool_alloc might block
@@ -3218,10 +3218,6 @@ static sector_t sync_request(struct mddev *mddev, sector_t sector_nr,
 			if (j == conf->copies) {
 				/* Cannot recover, so abort the recovery or
 				 * record a bad block */
-				put_buf(r10_bio);
-				if (rb2)
-					atomic_dec(&rb2->remaining);
-				r10_bio = rb2;
 				if (any_working) {
 					/* problem is that there are bad blocks
 					 * on other device(s)
@@ -3253,6 +3249,10 @@ static sector_t sync_request(struct mddev *mddev, sector_t sector_nr,
 					mirror->recovery_disabled
 						= mddev->recovery_disabled;
 				}
+				put_buf(r10_bio);
+				if (rb2)
+					atomic_dec(&rb2->remaining);
+				r10_bio = rb2;
 				break;
 			}
 		}
diff --git a/drivers/md/raid5.c b/drivers/md/raid5.c
index cc055da02e2a3..cbb15716a5db3 100644
--- a/drivers/md/raid5.c
+++ b/drivers/md/raid5.c
@@ -687,7 +687,8 @@ get_active_stripe(struct r5conf *conf, sector_t sector,
 			} else {
 				if (!test_bit(STRIPE_HANDLE, &sh->state))
 					atomic_inc(&conf->active_stripes);
-				BUG_ON(list_empty(&sh->lru));
+				BUG_ON(list_empty(&sh->lru) &&
+				       !test_bit(STRIPE_EXPANDING, &sh->state));
 				list_del_init(&sh->lru);
 				if (sh->group) {
 					sh->group->stripes_cnt--;
@@ -3608,7 +3609,7 @@ static void analyse_stripe(struct stripe_head *sh, struct stripe_head_state *s)
 			 */
 			set_bit(R5_Insync, &dev->flags);
 
-		if (rdev && test_bit(R5_WriteError, &dev->flags)) {
+		if (test_bit(R5_WriteError, &dev->flags)) {
 			/* This flag does not apply to '.replacement'
 			 * only to .rdev, so make sure to check that*/
 			struct md_rdev *rdev2 = rcu_dereference(
@@ -3621,7 +3622,7 @@ static void analyse_stripe(struct stripe_head *sh, struct stripe_head_state *s)
 			} else
 				clear_bit(R5_WriteError, &dev->flags);
 		}
-		if (rdev && test_bit(R5_MadeGood, &dev->flags)) {
+		if (test_bit(R5_MadeGood, &dev->flags)) {
 			/* This flag does not apply to '.replacement'
 			 * only to .rdev, so make sure to check that*/
 			struct md_rdev *rdev2 = rcu_dereference(
diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c
index 8b3107b2fcc13..0067b975873f1 100644
--- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c
+++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c
@@ -12942,25 +12942,26 @@ static void __bnx2x_remove(struct pci_dev *pdev,
 		pci_set_power_state(pdev, PCI_D3hot);
 	}
 
-	if (bp->regview)
-		iounmap(bp->regview);
+	if (remove_netdev) {
+		if (bp->regview)
+			iounmap(bp->regview);
 
-	/* for vf doorbells are part of the regview and were unmapped along with
-	 * it. FW is only loaded by PF.
-	 */
-	if (IS_PF(bp)) {
-		if (bp->doorbells)
-			iounmap(bp->doorbells);
+		/* For vfs, doorbells are part of the regview and were unmapped
+		 * along with it. FW is only loaded by PF.
+		 */
+		if (IS_PF(bp)) {
+			if (bp->doorbells)
+				iounmap(bp->doorbells);
 
-		bnx2x_release_firmware(bp);
-	}
-	bnx2x_free_mem_bp(bp);
+			bnx2x_release_firmware(bp);
+		}
+		bnx2x_free_mem_bp(bp);
 
-	if (remove_netdev)
 		free_netdev(dev);
 
-	if (atomic_read(&pdev->enable_cnt) == 1)
-		pci_release_regions(pdev);
+		if (atomic_read(&pdev->enable_cnt) == 1)
+			pci_release_regions(pdev);
+	}
 
 	pci_disable_device(pdev);
 }
diff --git a/drivers/net/ethernet/chelsio/cxgb4/l2t.c b/drivers/net/ethernet/chelsio/cxgb4/l2t.c
index cb05be905defd..81e8402a74b41 100644
--- a/drivers/net/ethernet/chelsio/cxgb4/l2t.c
+++ b/drivers/net/ethernet/chelsio/cxgb4/l2t.c
@@ -423,7 +423,7 @@ u64 cxgb4_select_ntuple(struct net_device *dev,
 	 * in the Compressed Filter Tuple.
 	 */
 	if (tp->vlan_shift >= 0 && l2t->vlan != VLAN_NONE)
-		ntuple |= (F_FT_VLAN_VLD | l2t->vlan) << tp->vlan_shift;
+		ntuple |= (u64)(F_FT_VLAN_VLD | l2t->vlan) << tp->vlan_shift;
 
 	if (tp->port_shift >= 0)
 		ntuple |= (u64)l2t->lport << tp->port_shift;
diff --git a/drivers/net/ethernet/emulex/benet/be_main.c b/drivers/net/ethernet/emulex/benet/be_main.c
index bf40fdaecfa3e..a37039d353c57 100644
--- a/drivers/net/ethernet/emulex/benet/be_main.c
+++ b/drivers/net/ethernet/emulex/benet/be_main.c
@@ -1776,6 +1776,7 @@ static void be_post_rx_frags(struct be_rx_obj *rxo, gfp_t gfp)
 	struct be_rx_page_info *page_info = NULL, *prev_page_info = NULL;
 	struct be_queue_info *rxq = &rxo->q;
 	struct page *pagep = NULL;
+	struct device *dev = &adapter->pdev->dev;
 	struct be_eth_rx_d *rxd;
 	u64 page_dmaaddr = 0, frag_dmaaddr;
 	u32 posted, page_offset = 0;
@@ -1788,9 +1789,15 @@ static void be_post_rx_frags(struct be_rx_obj *rxo, gfp_t gfp)
 				rx_stats(rxo)->rx_post_fail++;
 				break;
 			}
-			page_dmaaddr = dma_map_page(&adapter->pdev->dev, pagep,
-						    0, adapter->big_page_size,
+			page_dmaaddr = dma_map_page(dev, pagep, 0,
+						    adapter->big_page_size,
 						    DMA_FROM_DEVICE);
+			if (dma_mapping_error(dev, page_dmaaddr)) {
+				put_page(pagep);
+				pagep = NULL;
+				rx_stats(rxo)->rx_post_fail++;
+				break;
+			}
 			page_info->page_offset = 0;
 		} else {
 			get_page(pagep);
diff --git a/drivers/net/ethernet/intel/e1000e/netdev.c b/drivers/net/ethernet/intel/e1000e/netdev.c
index c30d41d6e4260..6d14eea179184 100644
--- a/drivers/net/ethernet/intel/e1000e/netdev.c
+++ b/drivers/net/ethernet/intel/e1000e/netdev.c
@@ -6174,7 +6174,7 @@ static int __e1000_resume(struct pci_dev *pdev)
 	return 0;
 }
 
-#ifdef CONFIG_PM
+#ifdef CONFIG_PM_SLEEP
 static int e1000_suspend(struct device *dev)
 {
 	struct pci_dev *pdev = to_pci_dev(dev);
@@ -6193,7 +6193,7 @@ static int e1000_resume(struct device *dev)
 
 	return __e1000_resume(pdev);
 }
-#endif /* CONFIG_PM */
+#endif /* CONFIG_PM_SLEEP */
 
 #ifdef CONFIG_PM_RUNTIME
 static int e1000_runtime_suspend(struct device *dev)
@@ -7015,13 +7015,11 @@ static DEFINE_PCI_DEVICE_TABLE(e1000_pci_tbl) = {
 };
 MODULE_DEVICE_TABLE(pci, e1000_pci_tbl);
 
-#ifdef CONFIG_PM
 static const struct dev_pm_ops e1000_pm_ops = {
 	SET_SYSTEM_SLEEP_PM_OPS(e1000_suspend, e1000_resume)
 	SET_RUNTIME_PM_OPS(e1000_runtime_suspend, e1000_runtime_resume,
 			   e1000_idle)
 };
-#endif
 
 /* PCI Device API Driver */
 static struct pci_driver e1000_driver = {
@@ -7029,11 +7027,9 @@ static struct pci_driver e1000_driver = {
 	.id_table = e1000_pci_tbl,
 	.probe    = e1000_probe,
 	.remove   = e1000_remove,
-#ifdef CONFIG_PM
 	.driver   = {
 		.pm = &e1000_pm_ops,
 	},
-#endif
 	.shutdown = e1000_shutdown,
 	.err_handler = &e1000_err_handler
 };
diff --git a/drivers/net/ethernet/qlogic/qlge/qlge_main.c b/drivers/net/ethernet/qlogic/qlge/qlge_main.c
index 449f506d2e8ff..f705aeeba767e 100644
--- a/drivers/net/ethernet/qlogic/qlge/qlge_main.c
+++ b/drivers/net/ethernet/qlogic/qlge/qlge_main.c
@@ -4765,6 +4765,8 @@ static int qlge_probe(struct pci_dev *pdev,
 			    NETIF_F_RXCSUM;
 	ndev->features = ndev->hw_features;
 	ndev->vlan_features = ndev->hw_features;
+	/* vlan gets same features (except vlan filter) */
+	ndev->vlan_features &= ~NETIF_F_HW_VLAN_CTAG_FILTER;
 
 	if (test_bit(QL_DMA64, &qdev->flags))
 		ndev->features |= NETIF_F_HIGHDMA;
diff --git a/drivers/net/ethernet/via/via-rhine.c b/drivers/net/ethernet/via/via-rhine.c
index cce6c4bc556a9..ef312bc6b8658 100644
--- a/drivers/net/ethernet/via/via-rhine.c
+++ b/drivers/net/ethernet/via/via-rhine.c
@@ -1618,6 +1618,7 @@ static void rhine_reset_task(struct work_struct *work)
 		goto out_unlock;
 
 	napi_disable(&rp->napi);
+	netif_tx_disable(dev);
 	spin_lock_bh(&rp->lock);
 
 	/* clear all descriptors */
diff --git a/drivers/net/usb/dm9601.c b/drivers/net/usb/dm9601.c
index 14aa48fa8d7e5..e802198777309 100644
--- a/drivers/net/usb/dm9601.c
+++ b/drivers/net/usb/dm9601.c
@@ -614,6 +614,18 @@ static const struct usb_device_id products[] = {
 	 USB_DEVICE(0x0a46, 0x9621),	/* DM9621A USB to Fast Ethernet Adapter */
 	 .driver_info = (unsigned long)&dm9601_info,
 	},
+	{
+	 USB_DEVICE(0x0a46, 0x9622),	/* DM9622 USB to Fast Ethernet Adapter */
+	 .driver_info = (unsigned long)&dm9601_info,
+	},
+	{
+	 USB_DEVICE(0x0a46, 0x0269),	/* DM962OA USB to Fast Ethernet Adapter */
+	 .driver_info = (unsigned long)&dm9601_info,
+	},
+	{
+	 USB_DEVICE(0x0a46, 0x1269),	/* DM9621A USB to Fast Ethernet Adapter */
+	 .driver_info = (unsigned long)&dm9601_info,
+	},
 	{},			// END
 };
 
diff --git a/drivers/net/usb/usbnet.c b/drivers/net/usb/usbnet.c
index 8494bb53ebdc9..aba04f5617600 100644
--- a/drivers/net/usb/usbnet.c
+++ b/drivers/net/usb/usbnet.c
@@ -1245,7 +1245,7 @@ static int build_dma_sg(const struct sk_buff *skb, struct urb *urb)
 		return -ENOMEM;
 
 	urb->num_sgs = num_sgs;
-	sg_init_table(urb->sg, urb->num_sgs);
+	sg_init_table(urb->sg, urb->num_sgs + 1);
 
 	sg_set_buf(&urb->sg[s++], skb->data, skb_headlen(skb));
 	total_len += skb_headlen(skb);
diff --git a/drivers/pinctrl/pinctrl-baytrail.c b/drivers/pinctrl/pinctrl-baytrail.c
index 114f5ef4b73ab..2832576d8b12e 100644
--- a/drivers/pinctrl/pinctrl-baytrail.c
+++ b/drivers/pinctrl/pinctrl-baytrail.c
@@ -512,7 +512,6 @@ static const struct dev_pm_ops byt_gpio_pm_ops = {
 
 static const struct acpi_device_id byt_gpio_acpi_match[] = {
 	{ "INT33B2", 0 },
-	{ "INT33FC", 0 },
 	{ }
 };
 MODULE_DEVICE_TABLE(acpi, byt_gpio_acpi_match);
diff --git a/drivers/video/omap2/dss/dispc.c b/drivers/video/omap2/dss/dispc.c
index 4ec59ca72e5d0..91c687fd002e5 100644
--- a/drivers/video/omap2/dss/dispc.c
+++ b/drivers/video/omap2/dss/dispc.c
@@ -3691,7 +3691,6 @@ static int __init omap_dispchw_probe(struct platform_device *pdev)
 	}
 
 	pm_runtime_enable(&pdev->dev);
-	pm_runtime_irq_safe(&pdev->dev);
 
 	r = dispc_runtime_get();
 	if (r)
diff --git a/fs/dcache.c b/fs/dcache.c
index 6055d61811d30..cb4a106908682 100644
--- a/fs/dcache.c
+++ b/fs/dcache.c
@@ -3061,8 +3061,13 @@ char *d_path(const struct path *path, char *buf, int buflen)
 	 * thus don't need to be hashed.  They also don't need a name until a
 	 * user wants to identify the object in /proc/pid/fd/.  The little hack
 	 * below allows us to generate a name for these objects on demand:
+	 *
+	 * Some pseudo inodes are mountable.  When they are mounted
+	 * path->dentry == path->mnt->mnt_root.  In that case don't call d_dname
+	 * and instead have d_path return the mounted path.
 	 */
-	if (path->dentry->d_op && path->dentry->d_op->d_dname)
+	if (path->dentry->d_op && path->dentry->d_op->d_dname &&
+	    (!IS_ROOT(path->dentry) || path->dentry != path->mnt->mnt_root))
 		return path->dentry->d_op->d_dname(path->dentry, buf, buflen);
 
 	rcu_read_lock();
diff --git a/fs/fs-writeback.c b/fs/fs-writeback.c
index 1f4a10ece2f12..e0259a163f98e 100644
--- a/fs/fs-writeback.c
+++ b/fs/fs-writeback.c
@@ -516,13 +516,16 @@ writeback_single_inode(struct inode *inode, struct bdi_writeback *wb,
 	}
 	WARN_ON(inode->i_state & I_SYNC);
 	/*
-	 * Skip inode if it is clean. We don't want to mess with writeback
-	 * lists in this function since flusher thread may be doing for example
-	 * sync in parallel and if we move the inode, it could get skipped. So
-	 * here we make sure inode is on some writeback list and leave it there
-	 * unless we have completely cleaned the inode.
+	 * Skip inode if it is clean and we have no outstanding writeback in
+	 * WB_SYNC_ALL mode. We don't want to mess with writeback lists in this
+	 * function since flusher thread may be doing for example sync in
+	 * parallel and if we move the inode, it could get skipped. So here we
+	 * make sure inode is on some writeback list and leave it there unless
+	 * we have completely cleaned the inode.
 	 */
-	if (!(inode->i_state & I_DIRTY))
+	if (!(inode->i_state & I_DIRTY) &&
+	    (wbc->sync_mode != WB_SYNC_ALL ||
+	     !mapping_tagged(inode->i_mapping, PAGECACHE_TAG_WRITEBACK)))
 		goto out;
 	inode->i_state |= I_SYNC;
 	spin_unlock(&inode->i_lock);
diff --git a/fs/namespace.c b/fs/namespace.c
index ac2ce8a766e1a..be32ebccdeb16 100644
--- a/fs/namespace.c
+++ b/fs/namespace.c
@@ -2886,7 +2886,7 @@ bool fs_fully_visible(struct file_system_type *type)
 			struct inode *inode = child->mnt_mountpoint->d_inode;
 			if (!S_ISDIR(inode->i_mode))
 				goto next;
-			if (inode->i_nlink != 2)
+			if (inode->i_nlink > 2)
 				goto next;
 		}
 		visible = true;
diff --git a/fs/nilfs2/segment.c b/fs/nilfs2/segment.c
index 9f6b486b6c01a..a1a191634abc1 100644
--- a/fs/nilfs2/segment.c
+++ b/fs/nilfs2/segment.c
@@ -1440,17 +1440,19 @@ static int nilfs_segctor_collect(struct nilfs_sc_info *sci,
 
 		nilfs_clear_logs(&sci->sc_segbufs);
 
-		err = nilfs_segctor_extend_segments(sci, nilfs, nadd);
-		if (unlikely(err))
-			return err;
-
 		if (sci->sc_stage.flags & NILFS_CF_SUFREED) {
 			err = nilfs_sufile_cancel_freev(nilfs->ns_sufile,
 							sci->sc_freesegs,
 							sci->sc_nfreesegs,
 							NULL);
 			WARN_ON(err); /* do not happen */
+			sci->sc_stage.flags &= ~NILFS_CF_SUFREED;
 		}
+
+		err = nilfs_segctor_extend_segments(sci, nilfs, nadd);
+		if (unlikely(err))
+			return err;
+
 		nadd = min_t(int, nadd << 1, SC_MAX_SEGDELTA);
 		sci->sc_stage = prev_stage;
 	}
diff --git a/include/drm/drm_crtc.h b/include/drm/drm_crtc.h
index e963470efd399..71727b6210ae5 100644
--- a/include/drm/drm_crtc.h
+++ b/include/drm/drm_crtc.h
@@ -931,6 +931,19 @@ extern int drm_crtc_init(struct drm_device *dev,
 			 struct drm_crtc *crtc,
 			 const struct drm_crtc_funcs *funcs);
 extern void drm_crtc_cleanup(struct drm_crtc *crtc);
+extern unsigned int drm_crtc_index(struct drm_crtc *crtc);
+
+/**
+ * drm_crtc_mask - find the mask of a registered CRTC
+ * @crtc: CRTC to find mask for
+ *
+ * Given a registered CRTC, return the mask bit of that CRTC for an
+ * encoder's possible_crtcs field.
+ */
+static inline uint32_t drm_crtc_mask(struct drm_crtc *crtc)
+{
+	return 1 << drm_crtc_index(crtc);
+}
 
 extern void drm_connector_ida_init(void);
 extern void drm_connector_ida_destroy(void);
@@ -952,6 +965,19 @@ extern int drm_encoder_init(struct drm_device *dev,
 			    const struct drm_encoder_funcs *funcs,
 			    int encoder_type);
 
+/**
+ * drm_encoder_crtc_ok - can a given crtc drive a given encoder?
+ * @encoder: encoder to test
+ * @crtc: crtc to test
+ *
+ * Return false if @encoder can't be driven by @crtc, true otherwise.
+ */
+static inline bool drm_encoder_crtc_ok(struct drm_encoder *encoder,
+				       struct drm_crtc *crtc)
+{
+	return !!(encoder->possible_crtcs & drm_crtc_mask(crtc));
+}
+
 extern int drm_plane_init(struct drm_device *dev,
 			  struct drm_plane *plane,
 			  unsigned long possible_crtcs,
diff --git a/include/linux/crash_dump.h b/include/linux/crash_dump.h
index fe68a5a985831..7032518f85424 100644
--- a/include/linux/crash_dump.h
+++ b/include/linux/crash_dump.h
@@ -6,6 +6,8 @@
 #include <linux/proc_fs.h>
 #include <linux/elf.h>
 
+#include <asm/pgtable.h> /* for pgprot_t */
+
 #define ELFCORE_ADDR_MAX	(-1ULL)
 #define ELFCORE_ADDR_ERR	(-2ULL)
 
diff --git a/include/linux/i2c.h b/include/linux/i2c.h
index eff50e062be85..d9c8dbd3373f9 100644
--- a/include/linux/i2c.h
+++ b/include/linux/i2c.h
@@ -445,7 +445,7 @@ static inline void i2c_set_adapdata(struct i2c_adapter *dev, void *data)
 static inline struct i2c_adapter *
 i2c_parent_is_i2c_adapter(const struct i2c_adapter *adapter)
 {
-#if IS_ENABLED(I2C_MUX)
+#if IS_ENABLED(CONFIG_I2C_MUX)
 	struct device *parent = adapter->dev.parent;
 
 	if (parent != NULL && parent->type == &i2c_adapter_type)
diff --git a/include/linux/seqlock.h b/include/linux/seqlock.h
index cf87a24c0f92f..535f158977b9d 100644
--- a/include/linux/seqlock.h
+++ b/include/linux/seqlock.h
@@ -117,15 +117,15 @@ static inline unsigned __read_seqcount_begin(const seqcount_t *s)
 }
 
 /**
- * read_seqcount_begin_no_lockdep - start seq-read critical section w/o lockdep
+ * raw_read_seqcount_begin - start seq-read critical section w/o lockdep
  * @s: pointer to seqcount_t
  * Returns: count to be passed to read_seqcount_retry
  *
- * read_seqcount_begin_no_lockdep opens a read critical section of the given
+ * raw_read_seqcount_begin opens a read critical section of the given
  * seqcount, but without any lockdep checking. Validity of the critical
  * section is tested by checking read_seqcount_retry function.
  */
-static inline unsigned read_seqcount_begin_no_lockdep(const seqcount_t *s)
+static inline unsigned raw_read_seqcount_begin(const seqcount_t *s)
 {
 	unsigned ret = __read_seqcount_begin(s);
 	smp_rmb();
@@ -144,7 +144,7 @@ static inline unsigned read_seqcount_begin_no_lockdep(const seqcount_t *s)
 static inline unsigned read_seqcount_begin(const seqcount_t *s)
 {
 	seqcount_lockdep_reader_access(s);
-	return read_seqcount_begin_no_lockdep(s);
+	return raw_read_seqcount_begin(s);
 }
 
 /**
@@ -206,14 +206,26 @@ static inline int read_seqcount_retry(const seqcount_t *s, unsigned start)
 }
 
 
+
+static inline void raw_write_seqcount_begin(seqcount_t *s)
+{
+	s->sequence++;
+	smp_wmb();
+}
+
+static inline void raw_write_seqcount_end(seqcount_t *s)
+{
+	smp_wmb();
+	s->sequence++;
+}
+
 /*
  * Sequence counter only version assumes that callers are using their
  * own mutexing.
  */
 static inline void write_seqcount_begin_nested(seqcount_t *s, int subclass)
 {
-	s->sequence++;
-	smp_wmb();
+	raw_write_seqcount_begin(s);
 	seqcount_acquire(&s->dep_map, subclass, 0, _RET_IP_);
 }
 
@@ -225,8 +237,7 @@ static inline void write_seqcount_begin(seqcount_t *s)
 static inline void write_seqcount_end(seqcount_t *s)
 {
 	seqcount_release(&s->dep_map, 1, _RET_IP_);
-	smp_wmb();
-	s->sequence++;
+	raw_write_seqcount_end(s);
 }
 
 /**
diff --git a/include/net/if_inet6.h b/include/net/if_inet6.h
index 76d54270f2e27..65bb13035598f 100644
--- a/include/net/if_inet6.h
+++ b/include/net/if_inet6.h
@@ -165,7 +165,6 @@ struct inet6_dev {
 	struct net_device	*dev;
 
 	struct list_head	addr_list;
-	int			valid_ll_addr_cnt;
 
 	struct ifmcaddr6	*mc_list;
 	struct ifmcaddr6	*mc_tomb;
diff --git a/kernel/fork.c b/kernel/fork.c
index 5721f0e3f2da4..dfa736c98d17b 100644
--- a/kernel/fork.c
+++ b/kernel/fork.c
@@ -1172,7 +1172,7 @@ static struct task_struct *copy_process(unsigned long clone_flags,
 	 * do not allow it to share a thread group or signal handlers or
 	 * parent with the forking task.
 	 */
-	if (clone_flags & (CLONE_SIGHAND | CLONE_PARENT)) {
+	if (clone_flags & CLONE_SIGHAND) {
 		if ((clone_flags & (CLONE_NEWUSER | CLONE_NEWPID)) ||
 		    (task_active_pid_ns(current) !=
 				current->nsproxy->pid_ns_for_children))
diff --git a/kernel/sched/fair.c b/kernel/sched/fair.c
index c7395d97e4cb7..e64b0794060e6 100644
--- a/kernel/sched/fair.c
+++ b/kernel/sched/fair.c
@@ -3923,7 +3923,7 @@ static long effective_load(struct task_group *tg, int cpu, long wl, long wg)
 {
 	struct sched_entity *se = tg->se[cpu];
 
-	if (!tg->parent || !wl)	/* the trivial, non-cgroup case */
+	if (!tg->parent)	/* the trivial, non-cgroup case */
 		return wl;
 
 	for_each_sched_entity(se) {
diff --git a/kernel/time/sched_clock.c b/kernel/time/sched_clock.c
index 68b7993759810..0abb364642818 100644
--- a/kernel/time/sched_clock.c
+++ b/kernel/time/sched_clock.c
@@ -74,7 +74,7 @@ unsigned long long notrace sched_clock(void)
 		return cd.epoch_ns;
 
 	do {
-		seq = read_seqcount_begin(&cd.seq);
+		seq = raw_read_seqcount_begin(&cd.seq);
 		epoch_cyc = cd.epoch_cyc;
 		epoch_ns = cd.epoch_ns;
 	} while (read_seqcount_retry(&cd.seq, seq));
@@ -99,10 +99,10 @@ static void notrace update_sched_clock(void)
 			  cd.mult, cd.shift);
 
 	raw_local_irq_save(flags);
-	write_seqcount_begin(&cd.seq);
+	raw_write_seqcount_begin(&cd.seq);
 	cd.epoch_ns = ns;
 	cd.epoch_cyc = cyc;
-	write_seqcount_end(&cd.seq);
+	raw_write_seqcount_end(&cd.seq);
 	raw_local_irq_restore(flags);
 }
 
diff --git a/lib/percpu_counter.c b/lib/percpu_counter.c
index 7473ee3b4ee71..8280a5dd17278 100644
--- a/lib/percpu_counter.c
+++ b/lib/percpu_counter.c
@@ -82,10 +82,10 @@ void __percpu_counter_add(struct percpu_counter *fbc, s64 amount, s32 batch)
 		unsigned long flags;
 		raw_spin_lock_irqsave(&fbc->lock, flags);
 		fbc->count += count;
+		__this_cpu_sub(*fbc->counters, count - amount);
 		raw_spin_unlock_irqrestore(&fbc->lock, flags);
-		__this_cpu_write(*fbc->counters, 0);
 	} else {
-		__this_cpu_write(*fbc->counters, count);
+		this_cpu_add(*fbc->counters, amount);
 	}
 	preempt_enable();
 }
diff --git a/mm/util.c b/mm/util.c
index f7bc2096071cb..808f375648e77 100644
--- a/mm/util.c
+++ b/mm/util.c
@@ -390,7 +390,10 @@ struct address_space *page_mapping(struct page *page)
 {
 	struct address_space *mapping = page->mapping;
 
-	VM_BUG_ON(PageSlab(page));
+	/* This happens if someone calls flush_dcache_page on slab page */
+	if (unlikely(PageSlab(page)))
+		return NULL;
+
 	if (unlikely(PageSwapCache(page))) {
 		swp_entry_t entry;
 
diff --git a/net/batman-adv/main.c b/net/batman-adv/main.c
index 1511f64a6ceaa..faba0f61ad535 100644
--- a/net/batman-adv/main.c
+++ b/net/batman-adv/main.c
@@ -277,7 +277,7 @@ int batadv_max_header_len(void)
 			   sizeof(struct batadv_coded_packet));
 #endif
 
-	return header_len;
+	return header_len + ETH_HLEN;
 }
 
 /**
diff --git a/net/core/filter.c b/net/core/filter.c
index 01b780856db29..ad30d626a5bd3 100644
--- a/net/core/filter.c
+++ b/net/core/filter.c
@@ -36,7 +36,6 @@
 #include <asm/uaccess.h>
 #include <asm/unaligned.h>
 #include <linux/filter.h>
-#include <linux/reciprocal_div.h>
 #include <linux/ratelimit.h>
 #include <linux/seccomp.h>
 #include <linux/if_vlan.h>
@@ -166,7 +165,7 @@ unsigned int sk_run_filter(const struct sk_buff *skb,
 			A /= X;
 			continue;
 		case BPF_S_ALU_DIV_K:
-			A = reciprocal_divide(A, K);
+			A /= K;
 			continue;
 		case BPF_S_ALU_MOD_X:
 			if (X == 0)
@@ -553,11 +552,6 @@ int sk_chk_filter(struct sock_filter *filter, unsigned int flen)
 		/* Some instructions need special checks */
 		switch (code) {
 		case BPF_S_ALU_DIV_K:
-			/* check for division by zero */
-			if (ftest->k == 0)
-				return -EINVAL;
-			ftest->k = reciprocal_value(ftest->k);
-			break;
 		case BPF_S_ALU_MOD_K:
 			/* check for division by zero */
 			if (ftest->k == 0)
@@ -853,27 +847,7 @@ void sk_decode_filter(struct sock_filter *filt, struct sock_filter *to)
 	to->code = decodes[code];
 	to->jt = filt->jt;
 	to->jf = filt->jf;
-
-	if (code == BPF_S_ALU_DIV_K) {
-		/*
-		 * When loaded this rule user gave us X, which was
-		 * translated into R = r(X). Now we calculate the
-		 * RR = r(R) and report it back. If next time this
-		 * value is loaded and RRR = r(RR) is calculated
-		 * then the R == RRR will be true.
-		 *
-		 * One exception. X == 1 translates into R == 0 and
-		 * we can't calculate RR out of it with r().
-		 */
-
-		if (filt->k == 0)
-			to->k = 1;
-		else
-			to->k = reciprocal_value(filt->k);
-
-		BUG_ON(reciprocal_value(to->k) != filt->k);
-	} else
-		to->k = filt->k;
+	to->k = filt->k;
 }
 
 int sk_get_filter(struct sock *sk, struct sock_filter __user *ubuf, unsigned int len)
diff --git a/net/ieee802154/nl-phy.c b/net/ieee802154/nl-phy.c
index d08c7a43dcd1c..89b265aea151e 100644
--- a/net/ieee802154/nl-phy.c
+++ b/net/ieee802154/nl-phy.c
@@ -221,8 +221,10 @@ int ieee802154_add_iface(struct sk_buff *skb, struct genl_info *info)
 
 	if (info->attrs[IEEE802154_ATTR_DEV_TYPE]) {
 		type = nla_get_u8(info->attrs[IEEE802154_ATTR_DEV_TYPE]);
-		if (type >= __IEEE802154_DEV_MAX)
-			return -EINVAL;
+		if (type >= __IEEE802154_DEV_MAX) {
+			rc = -EINVAL;
+			goto nla_put_failure;
+		}
 	}
 
 	dev = phy->add_iface(phy, devname, type);
diff --git a/net/ipv4/inet_diag.c b/net/ipv4/inet_diag.c
index a0f52dac8940d..e34dccbc4d70b 100644
--- a/net/ipv4/inet_diag.c
+++ b/net/ipv4/inet_diag.c
@@ -930,12 +930,15 @@ void inet_diag_dump_icsk(struct inet_hashinfo *hashinfo, struct sk_buff *skb,
 		spin_lock_bh(lock);
 		sk_nulls_for_each(sk, node, &head->chain) {
 			int res;
+			int state;
 
 			if (!net_eq(sock_net(sk), net))
 				continue;
 			if (num < s_num)
 				goto next_normal;
-			if (!(r->idiag_states & (1 << sk->sk_state)))
+			state = (sk->sk_state == TCP_TIME_WAIT) ?
+				inet_twsk(sk)->tw_substate : sk->sk_state;
+			if (!(r->idiag_states & (1 << state)))
 				goto next_normal;
 			if (r->sdiag_family != AF_UNSPEC &&
 			    sk->sk_family != r->sdiag_family)
diff --git a/net/ipv4/ipmr.c b/net/ipv4/ipmr.c
index 62212c772a4b9..1672409f5ba5a 100644
--- a/net/ipv4/ipmr.c
+++ b/net/ipv4/ipmr.c
@@ -157,9 +157,12 @@ static struct mr_table *ipmr_get_table(struct net *net, u32 id)
 static int ipmr_fib_lookup(struct net *net, struct flowi4 *flp4,
 			   struct mr_table **mrt)
 {
-	struct ipmr_result res;
-	struct fib_lookup_arg arg = { .result = &res, };
 	int err;
+	struct ipmr_result res;
+	struct fib_lookup_arg arg = {
+		.result = &res,
+		.flags = FIB_LOOKUP_NOREF,
+	};
 
 	err = fib_rules_lookup(net->ipv4.mr_rules_ops,
 			       flowi4_to_flowi(flp4), 0, &arg);
diff --git a/net/ipv4/tcp_metrics.c b/net/ipv4/tcp_metrics.c
index 06493736fbc82..098b3a29f6f3a 100644
--- a/net/ipv4/tcp_metrics.c
+++ b/net/ipv4/tcp_metrics.c
@@ -22,6 +22,9 @@
 
 int sysctl_tcp_nometrics_save __read_mostly;
 
+static struct tcp_metrics_block *__tcp_get_metrics(const struct inetpeer_addr *addr,
+						   struct net *net, unsigned int hash);
+
 struct tcp_fastopen_metrics {
 	u16	mss;
 	u16	syn_loss:10;		/* Recurring Fast Open SYN losses */
@@ -130,16 +133,41 @@ static void tcpm_suck_dst(struct tcp_metrics_block *tm, struct dst_entry *dst,
 	}
 }
 
+#define TCP_METRICS_TIMEOUT		(60 * 60 * HZ)
+
+static void tcpm_check_stamp(struct tcp_metrics_block *tm, struct dst_entry *dst)
+{
+	if (tm && unlikely(time_after(jiffies, tm->tcpm_stamp + TCP_METRICS_TIMEOUT)))
+		tcpm_suck_dst(tm, dst, false);
+}
+
+#define TCP_METRICS_RECLAIM_DEPTH	5
+#define TCP_METRICS_RECLAIM_PTR		(struct tcp_metrics_block *) 0x1UL
+
 static struct tcp_metrics_block *tcpm_new(struct dst_entry *dst,
 					  struct inetpeer_addr *addr,
-					  unsigned int hash,
-					  bool reclaim)
+					  unsigned int hash)
 {
 	struct tcp_metrics_block *tm;
 	struct net *net;
+	bool reclaim = false;
 
 	spin_lock_bh(&tcp_metrics_lock);
 	net = dev_net(dst->dev);
+
+	/* While waiting for the spin-lock the cache might have been populated
+	 * with this entry and so we have to check again.
+	 */
+	tm = __tcp_get_metrics(addr, net, hash);
+	if (tm == TCP_METRICS_RECLAIM_PTR) {
+		reclaim = true;
+		tm = NULL;
+	}
+	if (tm) {
+		tcpm_check_stamp(tm, dst);
+		goto out_unlock;
+	}
+
 	if (unlikely(reclaim)) {
 		struct tcp_metrics_block *oldest;
 
@@ -169,17 +197,6 @@ static struct tcp_metrics_block *tcpm_new(struct dst_entry *dst,
 	return tm;
 }
 
-#define TCP_METRICS_TIMEOUT		(60 * 60 * HZ)
-
-static void tcpm_check_stamp(struct tcp_metrics_block *tm, struct dst_entry *dst)
-{
-	if (tm && unlikely(time_after(jiffies, tm->tcpm_stamp + TCP_METRICS_TIMEOUT)))
-		tcpm_suck_dst(tm, dst, false);
-}
-
-#define TCP_METRICS_RECLAIM_DEPTH	5
-#define TCP_METRICS_RECLAIM_PTR		(struct tcp_metrics_block *) 0x1UL
-
 static struct tcp_metrics_block *tcp_get_encode(struct tcp_metrics_block *tm, int depth)
 {
 	if (tm)
@@ -282,7 +299,6 @@ static struct tcp_metrics_block *tcp_get_metrics(struct sock *sk,
 	struct inetpeer_addr addr;
 	unsigned int hash;
 	struct net *net;
-	bool reclaim;
 
 	addr.family = sk->sk_family;
 	switch (addr.family) {
@@ -304,13 +320,10 @@ static struct tcp_metrics_block *tcp_get_metrics(struct sock *sk,
 	hash = hash_32(hash, net->ipv4.tcp_metrics_hash_log);
 
 	tm = __tcp_get_metrics(&addr, net, hash);
-	reclaim = false;
-	if (tm == TCP_METRICS_RECLAIM_PTR) {
-		reclaim = true;
+	if (tm == TCP_METRICS_RECLAIM_PTR)
 		tm = NULL;
-	}
 	if (!tm && create)
-		tm = tcpm_new(dst, &addr, hash, reclaim);
+		tm = tcpm_new(dst, &addr, hash);
 	else
 		tcpm_check_stamp(tm, dst);
 
diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c
index abe46a4228ce9..4b6b720971b92 100644
--- a/net/ipv6/addrconf.c
+++ b/net/ipv6/addrconf.c
@@ -3189,6 +3189,22 @@ static void addrconf_dad_timer(unsigned long data)
 	in6_ifa_put(ifp);
 }
 
+/* ifp->idev must be at least read locked */
+static bool ipv6_lonely_lladdr(struct inet6_ifaddr *ifp)
+{
+	struct inet6_ifaddr *ifpiter;
+	struct inet6_dev *idev = ifp->idev;
+
+	list_for_each_entry(ifpiter, &idev->addr_list, if_list) {
+		if (ifp != ifpiter && ifpiter->scope == IFA_LINK &&
+		    (ifpiter->flags & (IFA_F_PERMANENT|IFA_F_TENTATIVE|
+				       IFA_F_OPTIMISTIC|IFA_F_DADFAILED)) ==
+		    IFA_F_PERMANENT)
+			return false;
+	}
+	return true;
+}
+
 static void addrconf_dad_completed(struct inet6_ifaddr *ifp)
 {
 	struct net_device *dev = ifp->idev->dev;
@@ -3208,14 +3224,11 @@ static void addrconf_dad_completed(struct inet6_ifaddr *ifp)
 	 */
 
 	read_lock_bh(&ifp->idev->lock);
-	spin_lock(&ifp->lock);
-	send_mld = ipv6_addr_type(&ifp->addr) & IPV6_ADDR_LINKLOCAL &&
-		   ifp->idev->valid_ll_addr_cnt == 1;
+	send_mld = ifp->scope == IFA_LINK && ipv6_lonely_lladdr(ifp);
 	send_rs = send_mld &&
 		  ipv6_accept_ra(ifp->idev) &&
 		  ifp->idev->cnf.rtr_solicits > 0 &&
 		  (dev->flags&IFF_LOOPBACK) == 0;
-	spin_unlock(&ifp->lock);
 	read_unlock_bh(&ifp->idev->lock);
 
 	/* While dad is in progress mld report's source address is in6_addrany.
@@ -4512,19 +4525,6 @@ static void inet6_prefix_notify(int event, struct inet6_dev *idev,
 		rtnl_set_sk_err(net, RTNLGRP_IPV6_PREFIX, err);
 }
 
-static void update_valid_ll_addr_cnt(struct inet6_ifaddr *ifp, int count)
-{
-	write_lock_bh(&ifp->idev->lock);
-	spin_lock(&ifp->lock);
-	if (((ifp->flags & (IFA_F_PERMANENT|IFA_F_TENTATIVE|IFA_F_OPTIMISTIC|
-			    IFA_F_DADFAILED)) == IFA_F_PERMANENT) &&
-	    (ipv6_addr_type(&ifp->addr) & IPV6_ADDR_LINKLOCAL))
-		ifp->idev->valid_ll_addr_cnt += count;
-	WARN_ON(ifp->idev->valid_ll_addr_cnt < 0);
-	spin_unlock(&ifp->lock);
-	write_unlock_bh(&ifp->idev->lock);
-}
-
 static void __ipv6_ifa_notify(int event, struct inet6_ifaddr *ifp)
 {
 	struct net *net = dev_net(ifp->idev->dev);
@@ -4533,8 +4533,6 @@ static void __ipv6_ifa_notify(int event, struct inet6_ifaddr *ifp)
 
 	switch (event) {
 	case RTM_NEWADDR:
-		update_valid_ll_addr_cnt(ifp, 1);
-
 		/*
 		 * If the address was optimistic
 		 * we inserted the route at the start of
@@ -4550,8 +4548,6 @@ static void __ipv6_ifa_notify(int event, struct inet6_ifaddr *ifp)
 					      ifp->idev->dev, 0, 0);
 		break;
 	case RTM_DELADDR:
-		update_valid_ll_addr_cnt(ifp, -1);
-
 		if (ifp->idev->cnf.forwarding)
 			addrconf_leave_anycast(ifp);
 		addrconf_leave_solict(ifp->idev, &ifp->addr);
diff --git a/net/ipv6/ip6mr.c b/net/ipv6/ip6mr.c
index f365310bfcca3..0eb4038a4d634 100644
--- a/net/ipv6/ip6mr.c
+++ b/net/ipv6/ip6mr.c
@@ -141,9 +141,12 @@ static struct mr6_table *ip6mr_get_table(struct net *net, u32 id)
 static int ip6mr_fib_lookup(struct net *net, struct flowi6 *flp6,
 			    struct mr6_table **mrt)
 {
-	struct ip6mr_result res;
-	struct fib_lookup_arg arg = { .result = &res, };
 	int err;
+	struct ip6mr_result res;
+	struct fib_lookup_arg arg = {
+		.result = &res,
+		.flags = FIB_LOOKUP_NOREF,
+	};
 
 	err = fib_rules_lookup(net->ipv6.mr6_rules_ops,
 			       flowi6_to_flowi(flp6), 0, &arg);
diff --git a/net/rds/ib_recv.c b/net/rds/ib_recv.c
index 8eb9501e3d60d..b7ebe23cdedfb 100644
--- a/net/rds/ib_recv.c
+++ b/net/rds/ib_recv.c
@@ -421,8 +421,7 @@ static void rds_ib_recv_cache_put(struct list_head *new_item,
 				 struct rds_ib_refill_cache *cache)
 {
 	unsigned long flags;
-	struct list_head *old;
-	struct list_head __percpu *chpfirst;
+	struct list_head *old, *chpfirst;
 
 	local_irq_save(flags);
 
@@ -432,7 +431,7 @@ static void rds_ib_recv_cache_put(struct list_head *new_item,
 	else /* put on front */
 		list_add_tail(new_item, chpfirst);
 
-	__this_cpu_write(chpfirst, new_item);
+	__this_cpu_write(cache->percpu->first, new_item);
 	__this_cpu_inc(cache->percpu->count);
 
 	if (__this_cpu_read(cache->percpu->count) < RDS_IB_RECYCLE_BATCH_COUNT)
@@ -452,7 +451,7 @@ static void rds_ib_recv_cache_put(struct list_head *new_item,
 	} while (old);
 
 
-	__this_cpu_write(chpfirst, NULL);
+	__this_cpu_write(cache->percpu->first, NULL);
 	__this_cpu_write(cache->percpu->count, 0);
 end:
 	local_irq_restore(flags);