Browse Source

Merge branch 'linux-4.1' of git://anongit.freedesktop.org/git/nouveau/linux-2.6 into drm-next

- gk20a iommu support
- gm107 graphics support without needing proprietary ucode
- various random fixes
- more gm20x bring-up, fifo/ce are ok, gr is mostly complete with the
exception of ctxsw ucode.. nvidia aren't playing nice yet so there's
not much more that can be done at this point...

I spent a lot of time trying to find a viable way of doing gr ctxsw
without signed firmware, but the "security" restrictions on the
fecs/gpccs falcons are excessive and go beyond what'd be necessary to
protect the host from malicious firmware.  This newer nvidia hw is
VERY open-source unfriendly.

I have some experimental host-based ctxsw work that could be a viable
(albeit unsatisfactory and slow) workaround in the meantime, but it
needs some more work and i'd like to get the 3d driver working
properly before i commit to pushing it.

* 'linux-4.1' of git://anongit.freedesktop.org/git/nouveau/linux-2.6: (40 commits)
  drm/nouveau/bios: fix fetching from acpi on certain systems
  drm/nouveau/gr/gm206: initial init+ctx code
  drm/nouveau/ce/gm206: enable support via gm204 code
  drm/nouveau/fifo/gm206: enable support via gm204 code
  drm/nouveau/gr/gm204: initial init+ctx code
  drm/nouveau: support for buffer moves via MaxwellDmaCopyA
  drm/nouveau/ce/gm204: initial support
  drm/nouveau: add support for gm20x fifo channels
  drm/nouveau/fifo/gm204: initial support
  drm/nouveau/gr/gk104-: prevent reading non-existent regs in intr handler
  drm/nouveau/gr/gm107: very slightly demagic part of attrib cb setup
  drm/nouveau/gr/gk104-: correct crop/zrop num_active_fbps setting
  drm/nouveau/gr/gf100-: add symbolic names for classes
  drm/nouveau/gr/gm107: support tpc "strand" ctxsw in gpccs ucode
  drm/nouveau/gr/gf100-: support mmio access with gpc offset from gpccs ucode
  drm/nouveau/gr: fix engine name, cosmetic search+replace mistake
  drm/nouveau/pmu/gk20a: add some missing statics
  drm/nouveau/platform: fix probe error path
  drm/nouveau/platform: release IOMMU's mm upon exit
  drm/nouveau/gr/gk104-gk20a: call pmu to disable any power-gating before ctor()
  ...
Dave Airlie 10 years ago
parent
commit
665ae581ae
75 changed files with 3957 additions and 1314 deletions
  1. 10 0
      drivers/gpu/drm/nouveau/include/nvif/class.h
  2. 3 0
      drivers/gpu/drm/nouveau/include/nvkm/engine/ce.h
  3. 1 0
      drivers/gpu/drm/nouveau/include/nvkm/engine/fifo.h
  4. 3 1
      drivers/gpu/drm/nouveau/include/nvkm/engine/gr.h
  5. 1 0
      drivers/gpu/drm/nouveau/include/nvkm/subdev/instmem.h
  6. 1 0
      drivers/gpu/drm/nouveau/include/nvkm/subdev/pmu.h
  7. 2 0
      drivers/gpu/drm/nouveau/nouveau_bo.c
  8. 2 1
      drivers/gpu/drm/nouveau/nouveau_chan.c
  9. 8 1
      drivers/gpu/drm/nouveau/nouveau_display.c
  10. 1 0
      drivers/gpu/drm/nouveau/nouveau_drm.c
  11. 3 1
      drivers/gpu/drm/nouveau/nouveau_drm.h
  12. 3 0
      drivers/gpu/drm/nouveau/nouveau_gem.c
  13. 76 3
      drivers/gpu/drm/nouveau/nouveau_platform.c
  14. 18 0
      drivers/gpu/drm/nouveau/nouveau_platform.h
  15. 3 0
      drivers/gpu/drm/nouveau/nouveau_ttm.c
  16. 11 3
      drivers/gpu/drm/nouveau/nv84_fence.c
  17. 1 0
      drivers/gpu/drm/nouveau/nvkm/engine/ce/Kbuild
  18. 173 0
      drivers/gpu/drm/nouveau/nvkm/engine/ce/gm204.c
  19. 7 3
      drivers/gpu/drm/nouveau/nvkm/engine/device/base.c
  20. 3 3
      drivers/gpu/drm/nouveau/nvkm/engine/device/gk104.c
  21. 6 10
      drivers/gpu/drm/nouveau/nvkm/engine/device/gm100.c
  22. 2 2
      drivers/gpu/drm/nouveau/nvkm/engine/disp/gf110.c
  23. 1 1
      drivers/gpu/drm/nouveau/nvkm/engine/disp/nv50.c
  24. 1 0
      drivers/gpu/drm/nouveau/nvkm/engine/fifo/Kbuild
  25. 4 3
      drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk104.c
  26. 2 0
      drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk104.h
  27. 57 0
      drivers/gpu/drm/nouveau/nvkm/engine/fifo/gm204.c
  28. 4 0
      drivers/gpu/drm/nouveau/nvkm/engine/gr/Kbuild
  29. 29 0
      drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgf100.h
  30. 9 7
      drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgk104.c
  31. 7 13
      drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgm107.c
  32. 1054 0
      drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgm204.c
  33. 83 0
      drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgm206.c
  34. 113 1
      drivers/gpu/drm/nouveau/nvkm/engine/gr/fuc/gpc.fuc
  35. 147 147
      drivers/gpu/drm/nouveau/nvkm/engine/gr/fuc/gpcgf100.fuc3.h
  36. 177 177
      drivers/gpu/drm/nouveau/nvkm/engine/gr/fuc/gpcgf117.fuc3.h
  37. 177 177
      drivers/gpu/drm/nouveau/nvkm/engine/gr/fuc/gpcgk104.fuc3.h
  38. 177 177
      drivers/gpu/drm/nouveau/nvkm/engine/gr/fuc/gpcgk110.fuc3.h
  39. 115 115
      drivers/gpu/drm/nouveau/nvkm/engine/gr/fuc/gpcgk208.fuc5.h
  40. 1 1
      drivers/gpu/drm/nouveau/nvkm/engine/gr/fuc/gpcgm107.fuc5
  41. 306 174
      drivers/gpu/drm/nouveau/nvkm/engine/gr/fuc/gpcgm107.fuc5.h
  42. 32 0
      drivers/gpu/drm/nouveau/nvkm/engine/gr/fuc/macros.fuc
  43. 18 4
      drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.c
  44. 18 2
      drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.h
  45. 2 2
      drivers/gpu/drm/nouveau/nvkm/engine/gr/gf108.c
  46. 2 2
      drivers/gpu/drm/nouveau/nvkm/engine/gr/gf110.c
  47. 14 3
      drivers/gpu/drm/nouveau/nvkm/engine/gr/gk104.c
  48. 4 41
      drivers/gpu/drm/nouveau/nvkm/engine/gr/gk110.c
  49. 2 2
      drivers/gpu/drm/nouveau/nvkm/engine/gr/gk110b.c
  50. 5 42
      drivers/gpu/drm/nouveau/nvkm/engine/gr/gk208.c
  51. 2 2
      drivers/gpu/drm/nouveau/nvkm/engine/gr/gk20a.c
  52. 13 13
      drivers/gpu/drm/nouveau/nvkm/engine/gr/gm107.c
  53. 387 0
      drivers/gpu/drm/nouveau/nvkm/engine/gr/gm204.c
  54. 40 0
      drivers/gpu/drm/nouveau/nvkm/engine/gr/gm206.c
  55. 2 2
      drivers/gpu/drm/nouveau/nvkm/subdev/bios/shadowacpi.c
  56. 1 1
      drivers/gpu/drm/nouveau/nvkm/subdev/bus/hwsq.c
  57. 37 7
      drivers/gpu/drm/nouveau/nvkm/subdev/bus/hwsq.h
  58. 1 1
      drivers/gpu/drm/nouveau/nvkm/subdev/clk/base.c
  59. 1 1
      drivers/gpu/drm/nouveau/nvkm/subdev/devinit/nv04.h
  60. 0 1
      drivers/gpu/drm/nouveau/nvkm/subdev/fb/Kbuild
  61. 18 8
      drivers/gpu/drm/nouveau/nvkm/subdev/fb/base.c
  62. 0 1
      drivers/gpu/drm/nouveau/nvkm/subdev/fb/gk20a.c
  63. 0 1
      drivers/gpu/drm/nouveau/nvkm/subdev/fb/priv.h
  64. 0 149
      drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramgk20a.c
  65. 1 3
      drivers/gpu/drm/nouveau/nvkm/subdev/fuse/gm107.c
  66. 1 0
      drivers/gpu/drm/nouveau/nvkm/subdev/instmem/Kbuild
  67. 440 0
      drivers/gpu/drm/nouveau/nvkm/subdev/instmem/gk20a.c
  68. 9 1
      drivers/gpu/drm/nouveau/nvkm/subdev/ltc/gf100.c
  69. 1 1
      drivers/gpu/drm/nouveau/nvkm/subdev/mxm/nv50.c
  70. 1 0
      drivers/gpu/drm/nouveau/nvkm/subdev/pmu/Kbuild
  71. 95 0
      drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gk110.c
  72. 1 0
      drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gk208.c
  73. 4 3
      drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gk20a.c
  74. 2 0
      drivers/gpu/drm/nouveau/nvkm/subdev/pmu/priv.h
  75. 1 0
      include/uapi/drm/nouveau_drm.h

+ 10 - 0
drivers/gpu/drm/nouveau/include/nvif/class.h

@@ -12,6 +12,13 @@
 #define NV_DMA_TO_MEMORY                                             0x00000003
 #define NV_DMA_IN_MEMORY                                             0x0000003d
 
+#define FERMI_TWOD_A                                                 0x0000902d
+
+#define FERMI_MEMORY_TO_MEMORY_FORMAT_A                              0x0000903d
+
+#define KEPLER_INLINE_TO_MEMORY_A                                    0x0000a040
+#define KEPLER_INLINE_TO_MEMORY_B                                    0x0000a140
+
 #define NV04_DISP                                                    0x00000046
 
 #define NV03_CHANNEL_DMA                                             0x0000006b
@@ -25,6 +32,7 @@
 #define G82_CHANNEL_GPFIFO                                           0x0000826f
 #define FERMI_CHANNEL_GPFIFO                                         0x0000906f
 #define KEPLER_CHANNEL_GPFIFO_A                                      0x0000a06f
+#define MAXWELL_CHANNEL_GPFIFO_A                                     0x0000b06f
 
 #define NV50_DISP                                                    0x00005070
 #define G82_DISP                                                     0x00008270
@@ -84,6 +92,7 @@
 #define KEPLER_C                                                     0x0000a297
 
 #define MAXWELL_A                                                    0x0000b097
+#define MAXWELL_B                                                    0x0000b197
 
 #define FERMI_COMPUTE_A                                              0x000090c0
 #define FERMI_COMPUTE_B                                              0x000091c0
@@ -92,6 +101,7 @@
 #define KEPLER_COMPUTE_B                                             0x0000a1c0
 
 #define MAXWELL_COMPUTE_A                                            0x0000b0c0
+#define MAXWELL_COMPUTE_B                                            0x0000b1c0
 
 
 /*******************************************************************************

+ 3 - 0
drivers/gpu/drm/nouveau/include/nvkm/engine/ce.h

@@ -10,4 +10,7 @@ extern struct nvkm_oclass gf100_ce1_oclass;
 extern struct nvkm_oclass gk104_ce0_oclass;
 extern struct nvkm_oclass gk104_ce1_oclass;
 extern struct nvkm_oclass gk104_ce2_oclass;
+extern struct nvkm_oclass gm204_ce0_oclass;
+extern struct nvkm_oclass gm204_ce1_oclass;
+extern struct nvkm_oclass gm204_ce2_oclass;
 #endif

+ 1 - 0
drivers/gpu/drm/nouveau/include/nvkm/engine/fifo.h

@@ -116,6 +116,7 @@ extern struct nvkm_oclass *gf100_fifo_oclass;
 extern struct nvkm_oclass *gk104_fifo_oclass;
 extern struct nvkm_oclass *gk20a_fifo_oclass;
 extern struct nvkm_oclass *gk208_fifo_oclass;
+extern struct nvkm_oclass *gm204_fifo_oclass;
 
 int  nvkm_fifo_uevent_ctor(struct nvkm_object *, void *, u32,
 			   struct nvkm_notify *);

+ 3 - 1
drivers/gpu/drm/nouveau/include/nvkm/engine/gr.h

@@ -38,7 +38,7 @@ nvkm_gr(void *obj)
 }
 
 #define nvkm_gr_create(p,e,c,y,d)                                        \
-	nvkm_engine_create((p), (e), (c), (y), "PGR", "graphics", (d))
+	nvkm_engine_create((p), (e), (c), (y), "PGRAPH", "graphics", (d))
 #define nvkm_gr_destroy(d)                                               \
 	nvkm_engine_destroy(&(d)->base)
 #define nvkm_gr_init(d)                                                  \
@@ -72,6 +72,8 @@ extern struct nvkm_oclass *gk110_gr_oclass;
 extern struct nvkm_oclass *gk110b_gr_oclass;
 extern struct nvkm_oclass *gk208_gr_oclass;
 extern struct nvkm_oclass *gm107_gr_oclass;
+extern struct nvkm_oclass *gm204_gr_oclass;
+extern struct nvkm_oclass *gm206_gr_oclass;
 
 #include <core/enum.h>
 

+ 1 - 0
drivers/gpu/drm/nouveau/include/nvkm/subdev/instmem.h

@@ -45,4 +45,5 @@ nvkm_instmem(void *obj)
 extern struct nvkm_oclass *nv04_instmem_oclass;
 extern struct nvkm_oclass *nv40_instmem_oclass;
 extern struct nvkm_oclass *nv50_instmem_oclass;
+extern struct nvkm_oclass *gk20a_instmem_oclass;
 #endif

+ 1 - 0
drivers/gpu/drm/nouveau/include/nvkm/subdev/pmu.h

@@ -35,6 +35,7 @@ extern struct nvkm_oclass *gt215_pmu_oclass;
 extern struct nvkm_oclass *gf100_pmu_oclass;
 extern struct nvkm_oclass *gf110_pmu_oclass;
 extern struct nvkm_oclass *gk104_pmu_oclass;
+extern struct nvkm_oclass *gk110_pmu_oclass;
 extern struct nvkm_oclass *gk208_pmu_oclass;
 extern struct nvkm_oclass *gk20a_pmu_oclass;
 

+ 2 - 0
drivers/gpu/drm/nouveau/nouveau_bo.c

@@ -1110,6 +1110,8 @@ nouveau_bo_move_init(struct nouveau_drm *drm)
 			    struct ttm_mem_reg *, struct ttm_mem_reg *);
 		int (*init)(struct nouveau_channel *, u32 handle);
 	} _methods[] = {
+		{  "COPY", 4, 0xb0b5, nve0_bo_move_copy, nve0_bo_move_init },
+		{  "GRCE", 0, 0xb0b5, nve0_bo_move_copy, nvc0_bo_move_init },
 		{  "COPY", 4, 0xa0b5, nve0_bo_move_copy, nve0_bo_move_init },
 		{  "GRCE", 0, 0xa0b5, nve0_bo_move_copy, nvc0_bo_move_init },
 		{ "COPY1", 5, 0x90b8, nvc0_bo_move_copy, nvc0_bo_move_init },

+ 2 - 1
drivers/gpu/drm/nouveau/nouveau_chan.c

@@ -184,7 +184,8 @@ static int
 nouveau_channel_ind(struct nouveau_drm *drm, struct nvif_device *device,
 		    u32 handle, u32 engine, struct nouveau_channel **pchan)
 {
-	static const u16 oclasses[] = { KEPLER_CHANNEL_GPFIFO_A,
+	static const u16 oclasses[] = { MAXWELL_CHANNEL_GPFIFO_A,
+					KEPLER_CHANNEL_GPFIFO_A,
 					FERMI_CHANNEL_GPFIFO,
 					G82_CHANNEL_GPFIFO,
 					NV50_CHANNEL_GPFIFO,

+ 8 - 1
drivers/gpu/drm/nouveau/nouveau_display.c

@@ -869,13 +869,20 @@ nouveau_display_dumb_create(struct drm_file *file_priv, struct drm_device *dev,
 			    struct drm_mode_create_dumb *args)
 {
 	struct nouveau_bo *bo;
+	uint32_t domain;
 	int ret;
 
 	args->pitch = roundup(args->width * (args->bpp / 8), 256);
 	args->size = args->pitch * args->height;
 	args->size = roundup(args->size, PAGE_SIZE);
 
-	ret = nouveau_gem_new(dev, args->size, 0, NOUVEAU_GEM_DOMAIN_VRAM, 0, 0, &bo);
+	/* Use VRAM if there is any ; otherwise fallback to system memory */
+	if (nouveau_drm(dev)->device.info.ram_size != 0)
+		domain = NOUVEAU_GEM_DOMAIN_VRAM;
+	else
+		domain = NOUVEAU_GEM_DOMAIN_GART;
+
+	ret = nouveau_gem_new(dev, args->size, 0, domain, 0, 0, &bo);
 	if (ret)
 		return ret;
 

+ 1 - 0
drivers/gpu/drm/nouveau/nouveau_drm.c

@@ -181,6 +181,7 @@ nouveau_accel_init(struct nouveau_drm *drm)
 			break;
 		case FERMI_CHANNEL_GPFIFO:
 		case KEPLER_CHANNEL_GPFIFO_A:
+		case MAXWELL_CHANNEL_GPFIFO_A:
 			ret = nvc0_fence_create(drm);
 			break;
 		default:

+ 3 - 1
drivers/gpu/drm/nouveau/nouveau_drm.h

@@ -10,7 +10,7 @@
 
 #define DRIVER_MAJOR		1
 #define DRIVER_MINOR		2
-#define DRIVER_PATCHLEVEL	1
+#define DRIVER_PATCHLEVEL	2
 
 /*
  * 1.1.1:
@@ -28,6 +28,8 @@
  * 	- fermi,kepler,maxwell zbc
  * 1.2.1:
  *      - allow concurrent access to bo's mapped read/write.
+ * 1.2.2:
+ *      - add NOUVEAU_GEM_DOMAIN_COHERENT flag
  */
 
 #include <nvif/client.h>

+ 3 - 0
drivers/gpu/drm/nouveau/nouveau_gem.c

@@ -189,6 +189,9 @@ nouveau_gem_new(struct drm_device *dev, int size, int align, uint32_t domain,
 	if (!flags || domain & NOUVEAU_GEM_DOMAIN_CPU)
 		flags |= TTM_PL_FLAG_SYSTEM;
 
+	if (domain & NOUVEAU_GEM_DOMAIN_COHERENT)
+		flags |= TTM_PL_FLAG_UNCACHED;
+
 	ret = nouveau_bo_new(dev, size, align, flags, tile_mode,
 			     tile_flags, NULL, NULL, pnvbo);
 	if (ret)

+ 76 - 3
drivers/gpu/drm/nouveau/nouveau_platform.c

@@ -27,6 +27,7 @@
 #include <linux/of.h>
 #include <linux/reset.h>
 #include <linux/regulator/consumer.h>
+#include <linux/iommu.h>
 #include <soc/tegra/fuse.h>
 #include <soc/tegra/pmc.h>
 
@@ -91,6 +92,72 @@ static int nouveau_platform_power_down(struct nouveau_platform_gpu *gpu)
 	return 0;
 }
 
+static void nouveau_platform_probe_iommu(struct device *dev,
+					 struct nouveau_platform_gpu *gpu)
+{
+	int err;
+	unsigned long pgsize_bitmap;
+
+	mutex_init(&gpu->iommu.mutex);
+
+	if (iommu_present(&platform_bus_type)) {
+		gpu->iommu.domain = iommu_domain_alloc(&platform_bus_type);
+		if (IS_ERR(gpu->iommu.domain))
+			goto error;
+
+		/*
+		 * A IOMMU is only usable if it supports page sizes smaller
+		 * or equal to the system's PAGE_SIZE, with a preference if
+		 * both are equal.
+		 */
+		pgsize_bitmap = gpu->iommu.domain->ops->pgsize_bitmap;
+		if (pgsize_bitmap & PAGE_SIZE) {
+			gpu->iommu.pgshift = PAGE_SHIFT;
+		} else {
+			gpu->iommu.pgshift = fls(pgsize_bitmap & ~PAGE_MASK);
+			if (gpu->iommu.pgshift == 0) {
+				dev_warn(dev, "unsupported IOMMU page size\n");
+				goto free_domain;
+			}
+			gpu->iommu.pgshift -= 1;
+		}
+
+		err = iommu_attach_device(gpu->iommu.domain, dev);
+		if (err)
+			goto free_domain;
+
+		err = nvkm_mm_init(&gpu->iommu._mm, 0,
+				   (1ULL << 40) >> gpu->iommu.pgshift, 1);
+		if (err)
+			goto detach_device;
+
+		gpu->iommu.mm = &gpu->iommu._mm;
+	}
+
+	return;
+
+detach_device:
+	iommu_detach_device(gpu->iommu.domain, dev);
+
+free_domain:
+	iommu_domain_free(gpu->iommu.domain);
+
+error:
+	gpu->iommu.domain = NULL;
+	gpu->iommu.pgshift = 0;
+	dev_err(dev, "cannot initialize IOMMU MM\n");
+}
+
+static void nouveau_platform_remove_iommu(struct device *dev,
+					  struct nouveau_platform_gpu *gpu)
+{
+	if (gpu->iommu.domain) {
+		nvkm_mm_fini(&gpu->iommu._mm);
+		iommu_detach_device(gpu->iommu.domain, dev);
+		iommu_domain_free(gpu->iommu.domain);
+	}
+}
+
 static int nouveau_platform_probe(struct platform_device *pdev)
 {
 	struct nouveau_platform_gpu *gpu;
@@ -118,6 +185,8 @@ static int nouveau_platform_probe(struct platform_device *pdev)
 	if (IS_ERR(gpu->clk_pwr))
 		return PTR_ERR(gpu->clk_pwr);
 
+	nouveau_platform_probe_iommu(&pdev->dev, gpu);
+
 	err = nouveau_platform_power_up(gpu);
 	if (err)
 		return err;
@@ -140,10 +209,9 @@ static int nouveau_platform_probe(struct platform_device *pdev)
 err_unref:
 	drm_dev_unref(drm);
 
-	return 0;
-
 power_down:
 	nouveau_platform_power_down(gpu);
+	nouveau_platform_remove_iommu(&pdev->dev, gpu);
 
 	return err;
 }
@@ -154,10 +222,15 @@ static int nouveau_platform_remove(struct platform_device *pdev)
 	struct nouveau_drm *drm = nouveau_drm(drm_dev);
 	struct nvkm_device *device = nvxx_device(&drm->device);
 	struct nouveau_platform_gpu *gpu = nv_device_to_platform(device)->gpu;
+	int err;
 
 	nouveau_drm_device_remove(drm_dev);
 
-	return nouveau_platform_power_down(gpu);
+	err = nouveau_platform_power_down(gpu);
+
+	nouveau_platform_remove_iommu(&pdev->dev, gpu);
+
+	return err;
 }
 
 #if IS_ENABLED(CONFIG_OF)

+ 18 - 0
drivers/gpu/drm/nouveau/nouveau_platform.h

@@ -24,10 +24,12 @@
 #define __NOUVEAU_PLATFORM_H__
 
 #include "core/device.h"
+#include "core/mm.h"
 
 struct reset_control;
 struct clk;
 struct regulator;
+struct iommu_domain;
 struct platform_driver;
 
 struct nouveau_platform_gpu {
@@ -36,6 +38,22 @@ struct nouveau_platform_gpu {
 	struct clk *clk_pwr;
 
 	struct regulator *vdd;
+
+	struct {
+		/*
+		 * Protects accesses to mm from subsystems
+		 */
+		struct mutex mutex;
+
+		struct nvkm_mm _mm;
+		/*
+		 * Just points to _mm. We need this to avoid embedding
+		 * struct nvkm_mm in os.h
+		 */
+		struct nvkm_mm *mm;
+		struct iommu_domain *domain;
+		unsigned long pgshift;
+	} iommu;
 };
 
 struct nouveau_platform_device {

+ 3 - 0
drivers/gpu/drm/nouveau/nouveau_ttm.c

@@ -82,6 +82,9 @@ nouveau_vram_manager_new(struct ttm_mem_type_manager *man,
 	u32 size_nc = 0;
 	int ret;
 
+	if (drm->device.info.ram_size == 0)
+		return -ENOMEM;
+
 	if (nvbo->tile_flags & NOUVEAU_GEM_TILE_NONCONTIG)
 		size_nc = 1 << nvbo->page_shift;
 

+ 11 - 3
drivers/gpu/drm/nouveau/nv84_fence.c

@@ -215,6 +215,7 @@ nv84_fence_create(struct nouveau_drm *drm)
 {
 	struct nvkm_fifo *pfifo = nvxx_fifo(&drm->device);
 	struct nv84_fence_priv *priv;
+	u32 domain;
 	int ret;
 
 	priv = drm->fence = kzalloc(sizeof(*priv), GFP_KERNEL);
@@ -231,10 +232,17 @@ nv84_fence_create(struct nouveau_drm *drm)
 	priv->base.context_base = fence_context_alloc(priv->base.contexts);
 	priv->base.uevent = true;
 
-	ret = nouveau_bo_new(drm->dev, 16 * priv->base.contexts, 0,
-			     TTM_PL_FLAG_VRAM, 0, 0, NULL, NULL, &priv->bo);
+	/* Use VRAM if there is any ; otherwise fallback to system memory */
+	domain = drm->device.info.ram_size != 0 ? TTM_PL_FLAG_VRAM :
+			 /*
+			  * fences created in sysmem must be non-cached or we
+			  * will lose CPU/GPU coherency!
+			  */
+			 TTM_PL_FLAG_TT | TTM_PL_FLAG_UNCACHED;
+	ret = nouveau_bo_new(drm->dev, 16 * priv->base.contexts, 0, domain, 0,
+			     0, NULL, NULL, &priv->bo);
 	if (ret == 0) {
-		ret = nouveau_bo_pin(priv->bo, TTM_PL_FLAG_VRAM, false);
+		ret = nouveau_bo_pin(priv->bo, domain, false);
 		if (ret == 0) {
 			ret = nouveau_bo_map(priv->bo);
 			if (ret)

+ 1 - 0
drivers/gpu/drm/nouveau/nvkm/engine/ce/Kbuild

@@ -1,3 +1,4 @@
 nvkm-y += nvkm/engine/ce/gt215.o
 nvkm-y += nvkm/engine/ce/gf100.o
 nvkm-y += nvkm/engine/ce/gk104.o
+nvkm-y += nvkm/engine/ce/gm204.o

+ 173 - 0
drivers/gpu/drm/nouveau/nvkm/engine/ce/gm204.c

@@ -0,0 +1,173 @@
+/*
+ * Copyright 2015 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 <engine/ce.h>
+
+#include <core/engctx.h>
+
+struct gm204_ce_priv {
+	struct nvkm_engine base;
+};
+
+/*******************************************************************************
+ * Copy object classes
+ ******************************************************************************/
+
+static struct nvkm_oclass
+gm204_ce_sclass[] = {
+	{ 0xb0b5, &nvkm_object_ofuncs },
+	{},
+};
+
+/*******************************************************************************
+ * PCE context
+ ******************************************************************************/
+
+static struct nvkm_ofuncs
+gm204_ce_context_ofuncs = {
+	.ctor = _nvkm_engctx_ctor,
+	.dtor = _nvkm_engctx_dtor,
+	.init = _nvkm_engctx_init,
+	.fini = _nvkm_engctx_fini,
+	.rd32 = _nvkm_engctx_rd32,
+	.wr32 = _nvkm_engctx_wr32,
+};
+
+static struct nvkm_oclass
+gm204_ce_cclass = {
+	.handle = NV_ENGCTX(CE0, 0x24),
+	.ofuncs = &gm204_ce_context_ofuncs,
+};
+
+/*******************************************************************************
+ * PCE engine/subdev functions
+ ******************************************************************************/
+
+static void
+gm204_ce_intr(struct nvkm_subdev *subdev)
+{
+	const int ce = nv_subidx(subdev) - NVDEV_ENGINE_CE0;
+	struct gm204_ce_priv *priv = (void *)subdev;
+	u32 stat = nv_rd32(priv, 0x104908 + (ce * 0x1000));
+
+	if (stat) {
+		nv_warn(priv, "unhandled intr 0x%08x\n", stat);
+		nv_wr32(priv, 0x104908 + (ce * 0x1000), stat);
+	}
+}
+
+static int
+gm204_ce0_ctor(struct nvkm_object *parent, struct nvkm_object *engine,
+	       struct nvkm_oclass *oclass, void *data, u32 size,
+	       struct nvkm_object **pobject)
+{
+	struct gm204_ce_priv *priv;
+	int ret;
+
+	ret = nvkm_engine_create(parent, engine, oclass, true,
+				 "PCE0", "ce0", &priv);
+	*pobject = nv_object(priv);
+	if (ret)
+		return ret;
+
+	nv_subdev(priv)->unit = 0x00000040;
+	nv_subdev(priv)->intr = gm204_ce_intr;
+	nv_engine(priv)->cclass = &gm204_ce_cclass;
+	nv_engine(priv)->sclass = gm204_ce_sclass;
+	return 0;
+}
+
+static int
+gm204_ce1_ctor(struct nvkm_object *parent, struct nvkm_object *engine,
+	       struct nvkm_oclass *oclass, void *data, u32 size,
+	       struct nvkm_object **pobject)
+{
+	struct gm204_ce_priv *priv;
+	int ret;
+
+	ret = nvkm_engine_create(parent, engine, oclass, true,
+				 "PCE1", "ce1", &priv);
+	*pobject = nv_object(priv);
+	if (ret)
+		return ret;
+
+	nv_subdev(priv)->unit = 0x00000080;
+	nv_subdev(priv)->intr = gm204_ce_intr;
+	nv_engine(priv)->cclass = &gm204_ce_cclass;
+	nv_engine(priv)->sclass = gm204_ce_sclass;
+	return 0;
+}
+
+static int
+gm204_ce2_ctor(struct nvkm_object *parent, struct nvkm_object *engine,
+	       struct nvkm_oclass *oclass, void *data, u32 size,
+	       struct nvkm_object **pobject)
+{
+	struct gm204_ce_priv *priv;
+	int ret;
+
+	ret = nvkm_engine_create(parent, engine, oclass, true,
+				 "PCE2", "ce2", &priv);
+	*pobject = nv_object(priv);
+	if (ret)
+		return ret;
+
+	nv_subdev(priv)->unit = 0x00200000;
+	nv_subdev(priv)->intr = gm204_ce_intr;
+	nv_engine(priv)->cclass = &gm204_ce_cclass;
+	nv_engine(priv)->sclass = gm204_ce_sclass;
+	return 0;
+}
+
+struct nvkm_oclass
+gm204_ce0_oclass = {
+	.handle = NV_ENGINE(CE0, 0x24),
+	.ofuncs = &(struct nvkm_ofuncs) {
+		.ctor = gm204_ce0_ctor,
+		.dtor = _nvkm_engine_dtor,
+		.init = _nvkm_engine_init,
+		.fini = _nvkm_engine_fini,
+	},
+};
+
+struct nvkm_oclass
+gm204_ce1_oclass = {
+	.handle = NV_ENGINE(CE1, 0x24),
+	.ofuncs = &(struct nvkm_ofuncs) {
+		.ctor = gm204_ce1_ctor,
+		.dtor = _nvkm_engine_dtor,
+		.init = _nvkm_engine_init,
+		.fini = _nvkm_engine_fini,
+	},
+};
+
+struct nvkm_oclass
+gm204_ce2_oclass = {
+	.handle = NV_ENGINE(CE2, 0x24),
+	.ofuncs = &(struct nvkm_ofuncs) {
+		.ctor = gm204_ce2_ctor,
+		.dtor = _nvkm_engine_dtor,
+		.init = _nvkm_engine_init,
+		.fini = _nvkm_engine_fini,
+	},
+};

+ 7 - 3
drivers/gpu/drm/nouveau/nvkm/engine/device/base.c

@@ -139,9 +139,13 @@ nvkm_devobj_info(struct nvkm_object *object, void *data, u32 size)
 
 	args->v0.chipset  = device->chipset;
 	args->v0.revision = device->chiprev;
-	if (pfb)  args->v0.ram_size = args->v0.ram_user = pfb->ram->size;
-	else      args->v0.ram_size = args->v0.ram_user = 0;
-	if (imem) args->v0.ram_user = args->v0.ram_user - imem->reserved;
+	if (pfb && pfb->ram)
+		args->v0.ram_size = args->v0.ram_user = pfb->ram->size;
+	else
+		args->v0.ram_size = args->v0.ram_user = 0;
+	if (imem && args->v0.ram_size > 0)
+		args->v0.ram_user = args->v0.ram_user - imem->reserved;
+
 	return 0;
 }
 

+ 3 - 3
drivers/gpu/drm/nouveau/nvkm/engine/device/gk104.c

@@ -171,7 +171,7 @@ gk104_identify(struct nvkm_device *device)
 		device->oclass[NVDEV_SUBDEV_FB     ] =  gk20a_fb_oclass;
 		device->oclass[NVDEV_SUBDEV_LTC    ] =  gk104_ltc_oclass;
 		device->oclass[NVDEV_SUBDEV_IBUS   ] = &gk20a_ibus_oclass;
-		device->oclass[NVDEV_SUBDEV_INSTMEM] = nv50_instmem_oclass;
+		device->oclass[NVDEV_SUBDEV_INSTMEM] = gk20a_instmem_oclass;
 		device->oclass[NVDEV_SUBDEV_MMU    ] = &gf100_mmu_oclass;
 		device->oclass[NVDEV_SUBDEV_BAR    ] = &gk20a_bar_oclass;
 		device->oclass[NVDEV_ENGINE_DMAOBJ ] =  gf110_dmaeng_oclass;
@@ -202,7 +202,7 @@ gk104_identify(struct nvkm_device *device)
 		device->oclass[NVDEV_SUBDEV_INSTMEM] =  nv50_instmem_oclass;
 		device->oclass[NVDEV_SUBDEV_MMU    ] = &gf100_mmu_oclass;
 		device->oclass[NVDEV_SUBDEV_BAR    ] = &gf100_bar_oclass;
-		device->oclass[NVDEV_SUBDEV_PMU    ] =  gf110_pmu_oclass;
+		device->oclass[NVDEV_SUBDEV_PMU    ] =  gk110_pmu_oclass;
 		device->oclass[NVDEV_SUBDEV_VOLT   ] = &nv40_volt_oclass;
 		device->oclass[NVDEV_ENGINE_DMAOBJ ] =  gf110_dmaeng_oclass;
 		device->oclass[NVDEV_ENGINE_FIFO   ] =  gk104_fifo_oclass;
@@ -236,7 +236,7 @@ gk104_identify(struct nvkm_device *device)
 		device->oclass[NVDEV_SUBDEV_INSTMEM] =  nv50_instmem_oclass;
 		device->oclass[NVDEV_SUBDEV_MMU    ] = &gf100_mmu_oclass;
 		device->oclass[NVDEV_SUBDEV_BAR    ] = &gf100_bar_oclass;
-		device->oclass[NVDEV_SUBDEV_PMU    ] =  gf110_pmu_oclass;
+		device->oclass[NVDEV_SUBDEV_PMU    ] =  gk110_pmu_oclass;
 		device->oclass[NVDEV_SUBDEV_VOLT   ] = &nv40_volt_oclass;
 		device->oclass[NVDEV_ENGINE_DMAOBJ ] =  gf110_dmaeng_oclass;
 		device->oclass[NVDEV_ENGINE_FIFO   ] =  gk104_fifo_oclass;

+ 6 - 10
drivers/gpu/drm/nouveau/nvkm/engine/device/gm100.c

@@ -127,16 +127,14 @@ gm100_identify(struct nvkm_device *device)
 		device->oclass[NVDEV_SUBDEV_VOLT   ] = &nv40_volt_oclass;
 #endif
 		device->oclass[NVDEV_ENGINE_DMAOBJ ] =  gf110_dmaeng_oclass;
-#if 0
-		device->oclass[NVDEV_ENGINE_FIFO   ] =  gk208_fifo_oclass;
+		device->oclass[NVDEV_ENGINE_FIFO   ] =  gm204_fifo_oclass;
 		device->oclass[NVDEV_ENGINE_SW     ] =  gf100_sw_oclass;
-		device->oclass[NVDEV_ENGINE_GR     ] =  gm107_gr_oclass;
-#endif
+		device->oclass[NVDEV_ENGINE_GR     ] =  gm204_gr_oclass;
 		device->oclass[NVDEV_ENGINE_DISP   ] =  gm204_disp_oclass;
-#if 0
 		device->oclass[NVDEV_ENGINE_CE0    ] = &gm204_ce0_oclass;
 		device->oclass[NVDEV_ENGINE_CE1    ] = &gm204_ce1_oclass;
 		device->oclass[NVDEV_ENGINE_CE2    ] = &gm204_ce2_oclass;
+#if 0
 		device->oclass[NVDEV_ENGINE_MSVLD  ] = &gk104_msvld_oclass;
 		device->oclass[NVDEV_ENGINE_MSPDEC ] = &gk104_mspdec_oclass;
 		device->oclass[NVDEV_ENGINE_MSPPP  ] = &gf100_msppp_oclass;
@@ -170,16 +168,14 @@ gm100_identify(struct nvkm_device *device)
 		device->oclass[NVDEV_SUBDEV_VOLT   ] = &nv40_volt_oclass;
 #endif
 		device->oclass[NVDEV_ENGINE_DMAOBJ ] =  gf110_dmaeng_oclass;
-#if 0
-		device->oclass[NVDEV_ENGINE_FIFO   ] =  gk208_fifo_oclass;
+		device->oclass[NVDEV_ENGINE_FIFO   ] =  gm204_fifo_oclass;
 		device->oclass[NVDEV_ENGINE_SW     ] =  gf100_sw_oclass;
-		device->oclass[NVDEV_ENGINE_GR     ] =  gm107_gr_oclass;
-#endif
+		device->oclass[NVDEV_ENGINE_GR     ] =  gm206_gr_oclass;
 		device->oclass[NVDEV_ENGINE_DISP   ] =  gm204_disp_oclass;
-#if 0
 		device->oclass[NVDEV_ENGINE_CE0    ] = &gm204_ce0_oclass;
 		device->oclass[NVDEV_ENGINE_CE1    ] = &gm204_ce1_oclass;
 		device->oclass[NVDEV_ENGINE_CE2    ] = &gm204_ce2_oclass;
+#if 0
 		device->oclass[NVDEV_ENGINE_MSVLD  ] = &gk104_msvld_oclass;
 		device->oclass[NVDEV_ENGINE_MSPDEC ] = &gk104_mspdec_oclass;
 		device->oclass[NVDEV_ENGINE_MSPPP  ] = &gf100_msppp_oclass;

+ 2 - 2
drivers/gpu/drm/nouveau/nvkm/engine/disp/gf110.c

@@ -413,8 +413,8 @@ gf110_disp_base_mthd_base = {
 
 static const struct nv50_disp_mthd_list
 gf110_disp_base_mthd_image = {
-	.mthd = 0x0400,
-	.addr = 0x000400,
+	.mthd = 0x0020,
+	.addr = 0x000020,
 	.data = {
 		{ 0x0400, 0x661400 },
 		{ 0x0404, 0x661404 },

+ 1 - 1
drivers/gpu/drm/nouveau/nvkm/engine/disp/nv50.c

@@ -229,7 +229,7 @@ nv50_disp_dmac_create_(struct nvkm_object *parent,
 
 		switch (dmac->pushdma->target) {
 		case NV_MEM_TARGET_VRAM:
-			dmac->push = 0x00000000 | dmac->pushdma->start >> 8;
+			dmac->push = 0x00000001 | dmac->pushdma->start >> 8;
 			break;
 		case NV_MEM_TARGET_PCI_NOSNOOP:
 			dmac->push = 0x00000003 | dmac->pushdma->start >> 8;

+ 1 - 0
drivers/gpu/drm/nouveau/nvkm/engine/fifo/Kbuild

@@ -9,3 +9,4 @@ nvkm-y += nvkm/engine/fifo/gf100.o
 nvkm-y += nvkm/engine/fifo/gk104.o
 nvkm-y += nvkm/engine/fifo/gk20a.o
 nvkm-y += nvkm/engine/fifo/gk208.o
+nvkm-y += nvkm/engine/fifo/gm204.o

+ 4 - 3
drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk104.c

@@ -323,8 +323,8 @@ gk104_fifo_chan_fini(struct nvkm_object *object, bool suspend)
 	return nvkm_fifo_channel_fini(&chan->base, suspend);
 }
 
-static struct nvkm_ofuncs
-gk104_fifo_ofuncs = {
+struct nvkm_ofuncs
+gk104_fifo_chan_ofuncs = {
 	.ctor = gk104_fifo_chan_ctor,
 	.dtor = _nvkm_fifo_channel_dtor,
 	.init = gk104_fifo_chan_init,
@@ -337,7 +337,7 @@ gk104_fifo_ofuncs = {
 
 static struct nvkm_oclass
 gk104_fifo_sclass[] = {
-	{ KEPLER_CHANNEL_GPFIFO_A, &gk104_fifo_ofuncs },
+	{ KEPLER_CHANNEL_GPFIFO_A, &gk104_fifo_chan_ofuncs },
 	{}
 };
 
@@ -774,6 +774,7 @@ gk104_fifo_intr_fault(struct gk104_fifo_priv *priv, int unit)
 	while (object) {
 		switch (nv_mclass(object)) {
 		case KEPLER_CHANNEL_GPFIFO_A:
+		case MAXWELL_CHANNEL_GPFIFO_A:
 			gk104_fifo_recover(priv, engine, (void *)object);
 			break;
 		}

+ 2 - 0
drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk104.h

@@ -13,4 +13,6 @@ struct gk104_fifo_impl {
 	struct nvkm_oclass base;
 	u32 channels;
 };
+
+extern struct nvkm_ofuncs gk104_fifo_chan_ofuncs;
 #endif

+ 57 - 0
drivers/gpu/drm/nouveau/nvkm/engine/fifo/gm204.c

@@ -0,0 +1,57 @@
+/*
+ * Copyright 2015 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 "gk104.h"
+
+#include <nvif/class.h>
+
+static struct nvkm_oclass
+gm204_fifo_sclass[] = {
+	{ MAXWELL_CHANNEL_GPFIFO_A, &gk104_fifo_chan_ofuncs },
+	{}
+};
+
+static int
+gm204_fifo_ctor(struct nvkm_object *parent, struct nvkm_object *engine,
+		struct nvkm_oclass *oclass, void *data, u32 size,
+		struct nvkm_object **pobject)
+{
+	int ret = gk104_fifo_ctor(parent, engine, oclass, data, size, pobject);
+	if (ret == 0) {
+		struct gk104_fifo_priv *priv = (void *)*pobject;
+		nv_engine(priv)->sclass = gm204_fifo_sclass;
+	}
+	return ret;
+}
+
+struct nvkm_oclass *
+gm204_fifo_oclass = &(struct gk104_fifo_impl) {
+	.base.handle = NV_ENGINE(FIFO, 0x24),
+	.base.ofuncs = &(struct nvkm_ofuncs) {
+		.ctor = gm204_fifo_ctor,
+		.dtor = gk104_fifo_dtor,
+		.init = gk104_fifo_init,
+		.fini = _nvkm_fifo_fini,
+	},
+	.channels = 4096,
+}.base;

+ 4 - 0
drivers/gpu/drm/nouveau/nvkm/engine/gr/Kbuild

@@ -12,6 +12,8 @@ nvkm-y += nvkm/engine/gr/ctxgk110.o
 nvkm-y += nvkm/engine/gr/ctxgk110b.o
 nvkm-y += nvkm/engine/gr/ctxgk208.o
 nvkm-y += nvkm/engine/gr/ctxgm107.o
+nvkm-y += nvkm/engine/gr/ctxgm204.o
+nvkm-y += nvkm/engine/gr/ctxgm206.o
 nvkm-y += nvkm/engine/gr/nv04.o
 nvkm-y += nvkm/engine/gr/nv10.o
 nvkm-y += nvkm/engine/gr/nv20.o
@@ -34,3 +36,5 @@ nvkm-y += nvkm/engine/gr/gk110.o
 nvkm-y += nvkm/engine/gr/gk110b.o
 nvkm-y += nvkm/engine/gr/gk208.o
 nvkm-y += nvkm/engine/gr/gm107.o
+nvkm-y += nvkm/engine/gr/gm204.o
+nvkm-y += nvkm/engine/gr/gm206.o

+ 29 - 0
drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgf100.h

@@ -88,11 +88,22 @@ void gk104_grctx_generate_bundle(struct gf100_grctx *);
 void gk104_grctx_generate_pagepool(struct gf100_grctx *);
 void gk104_grctx_generate_unkn(struct gf100_gr_priv *);
 void gk104_grctx_generate_r418bb8(struct gf100_gr_priv *);
+void gk104_grctx_generate_rop_active_fbps(struct gf100_gr_priv *);
+
 
 extern struct nvkm_oclass *gk110_grctx_oclass;
 extern struct nvkm_oclass *gk110b_grctx_oclass;
 extern struct nvkm_oclass *gk208_grctx_oclass;
+
 extern struct nvkm_oclass *gm107_grctx_oclass;
+void gm107_grctx_generate_bundle(struct gf100_grctx *);
+void gm107_grctx_generate_pagepool(struct gf100_grctx *);
+void gm107_grctx_generate_attrib(struct gf100_grctx *);
+
+extern struct nvkm_oclass *gm204_grctx_oclass;
+void gm204_grctx_generate_main(struct gf100_gr_priv *, struct gf100_grctx *);
+
+extern struct nvkm_oclass *gm206_grctx_oclass;
 
 /* context init value lists */
 
@@ -196,4 +207,22 @@ extern const struct gf100_gr_init gk208_grctx_init_rstr2d_0[];
 
 extern const struct gf100_gr_init gk208_grctx_init_prop_0[];
 extern const struct gf100_gr_init gk208_grctx_init_crstr_0[];
+
+extern const struct gf100_gr_init gm107_grctx_init_gpc_unk_0[];
+extern const struct gf100_gr_init gm107_grctx_init_wwdx_0[];
+
+extern const struct gf100_gr_pack gm204_grctx_pack_icmd[];
+
+extern const struct gf100_gr_pack gm204_grctx_pack_mthd[];
+
+extern const struct gf100_gr_pack gm204_grctx_pack_hub[];
+
+extern const struct gf100_gr_init gm204_grctx_init_prop_0[];
+extern const struct gf100_gr_init gm204_grctx_init_setup_0[];
+extern const struct gf100_gr_init gm204_grctx_init_gpm_0[];
+extern const struct gf100_gr_init gm204_grctx_init_gpc_unk_2[];
+
+extern const struct gf100_gr_pack gm204_grctx_pack_tpc[];
+
+extern const struct gf100_gr_pack gm204_grctx_pack_ppc[];
 #endif

+ 9 - 7
drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgk104.c

@@ -940,6 +940,14 @@ gk104_grctx_generate_r418bb8(struct gf100_gr_priv *priv)
 		nv_wr32(priv, 0x40780c + (i * 4), data[i]);
 }
 
+void
+gk104_grctx_generate_rop_active_fbps(struct gf100_gr_priv *priv)
+{
+	const u32 fbp_count = nv_rd32(priv, 0x120074);
+	nv_mask(priv, 0x408850, 0x0000000f, fbp_count); /* zrop */
+	nv_mask(priv, 0x408958, 0x0000000f, fbp_count); /* crop */
+}
+
 void
 gk104_grctx_generate_main(struct gf100_gr_priv *priv, struct gf100_grctx *info)
 {
@@ -970,13 +978,7 @@ gk104_grctx_generate_main(struct gf100_gr_priv *priv, struct gf100_grctx *info)
 		nv_wr32(priv, 0x4064d0 + (i * 0x04), 0x00000000);
 
 	nv_wr32(priv, 0x405b00, (priv->tpc_total << 8) | priv->gpc_nr);
-	if (priv->gpc_nr == 1) {
-		nv_mask(priv, 0x408850, 0x0000000f, priv->tpc_nr[0]);
-		nv_mask(priv, 0x408958, 0x0000000f, priv->tpc_nr[0]);
-	} else {
-		nv_mask(priv, 0x408850, 0x0000000f, priv->gpc_nr);
-		nv_mask(priv, 0x408958, 0x0000000f, priv->gpc_nr);
-	}
+	gk104_grctx_generate_rop_active_fbps(priv);
 	nv_mask(priv, 0x419f78, 0x00000001, 0x00000000);
 
 	gf100_gr_icmd(priv, oclass->icmd);

+ 7 - 13
drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgm107.c

@@ -699,7 +699,7 @@ gm107_grctx_pack_hub[] = {
 	{}
 };
 
-static const struct gf100_gr_init
+const struct gf100_gr_init
 gm107_grctx_init_gpc_unk_0[] = {
 	{ 0x418380,   1, 0x04, 0x00000056 },
 	{}
@@ -834,7 +834,7 @@ gm107_grctx_init_cbm_0[] = {
 	{}
 };
 
-static const struct gf100_gr_init
+const struct gf100_gr_init
 gm107_grctx_init_wwdx_0[] = {
 	{ 0x41bf00,   1, 0x04, 0x0a418820 },
 	{ 0x41bf04,   1, 0x04, 0x062080e6 },
@@ -860,7 +860,7 @@ gm107_grctx_pack_ppc[] = {
  * PGRAPH context implementation
  ******************************************************************************/
 
-static void
+void
 gm107_grctx_generate_bundle(struct gf100_grctx *info)
 {
 	const struct gf100_grctx_oclass *impl = gf100_grctx_impl(info->priv);
@@ -877,7 +877,7 @@ gm107_grctx_generate_bundle(struct gf100_grctx *info)
 	mmio_wr32(info, 0x4064c8, (state_limit << 16) | token_limit);
 }
 
-static void
+void
 gm107_grctx_generate_pagepool(struct gf100_grctx *info)
 {
 	const struct gf100_grctx_oclass *impl = gf100_grctx_impl(info->priv);
@@ -892,7 +892,7 @@ gm107_grctx_generate_pagepool(struct gf100_grctx *info)
 	mmio_wr32(info, 0x418e30, 0x80000000); /* guess at it being related */
 }
 
-static void
+void
 gm107_grctx_generate_attrib(struct gf100_grctx *info)
 {
 	struct gf100_gr_priv *priv = info->priv;
@@ -926,7 +926,7 @@ gm107_grctx_generate_attrib(struct gf100_grctx *info)
 			mmio_wr32(info, o + 0xe4, as);
 			mmio_wr32(info, o + 0xf8, ao);
 			ao += impl->alpha_nr_max * priv->ppc_tpc_nr[gpc][ppc];
-			mmio_wr32(info, u, (0x715 /*XXX*/ << 16) | bs);
+			mmio_wr32(info, u, ((bs / 3 /*XXX*/) << 16) | bs);
 		}
 	}
 }
@@ -982,13 +982,7 @@ gm107_grctx_generate_main(struct gf100_gr_priv *priv, struct gf100_grctx *info)
 
 	nv_wr32(priv, 0x405b00, (priv->tpc_total << 8) | priv->gpc_nr);
 
-	if (priv->gpc_nr == 1) {
-		nv_mask(priv, 0x408850, 0x0000000f, priv->tpc_nr[0]);
-		nv_mask(priv, 0x408958, 0x0000000f, priv->tpc_nr[0]);
-	} else {
-		nv_mask(priv, 0x408850, 0x0000000f, priv->gpc_nr);
-		nv_mask(priv, 0x408958, 0x0000000f, priv->gpc_nr);
-	}
+	gk104_grctx_generate_rop_active_fbps(priv);
 
 	gf100_gr_icmd(priv, oclass->icmd);
 	nv_wr32(priv, 0x404154, 0x00000400);

+ 1054 - 0
drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgm204.c

@@ -0,0 +1,1054 @@
+/*
+ * Copyright 2015 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 "ctxgf100.h"
+
+/*******************************************************************************
+ * PGRAPH context register lists
+ ******************************************************************************/
+
+static const struct gf100_gr_init
+gm204_grctx_init_icmd_0[] = {
+	{ 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 },
+	{ 0x000374,   1, 0x01, 0x00000100 },
+	{ 0x000818,   8, 0x01, 0x00000000 },
+	{ 0x000848,  16, 0x01, 0x00000000 },
+	{ 0x000738,   1, 0x01, 0x00000000 },
+	{ 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 },
+	{ 0x01e100,   1, 0x01, 0x00000001 },
+	{ 0x001000,   1, 0x01, 0x00000001 },
+	{ 0x000b07,   1, 0x01, 0x00000002 },
+	{ 0x000b08,   2, 0x01, 0x00000100 },
+	{ 0x000b0a,   1, 0x01, 0x00000001 },
+	{ 0x01e100,   1, 0x01, 0x00000001 },
+	{ 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 },
+	{ 0x0000b4,   4, 0x01, 0x88888888 },
+	{ 0x0000f8,   1, 0x01, 0x00000003 },
+	{ 0x0000fa,   1, 0x01, 0x00000001 },
+	{ 0x0000b1,   2, 0x01, 0x00000001 },
+	{ 0x00009f,   4, 0x01, 0x0000ffff },
+	{ 0x0000a8,   1, 0x01, 0x0000ffff },
+	{ 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 },
+	{ 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 },
+	{ 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 },
+	{ 0x000374,   1, 0x01, 0x00000100 },
+	{ 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 },
+	{ 0x0005aa,   1, 0x01, 0x00000002 },
+	{ 0x0005cb,   1, 0x01, 0x00000004 },
+	{ 0x0005d0,   1, 0x01, 0x20181008 },
+	{ 0x0005d1,   1, 0x01, 0x40383028 },
+	{ 0x0005d2,   1, 0x01, 0x60585048 },
+	{ 0x0005d3,   1, 0x01, 0x80787068 },
+	{ 0x000980, 128, 0x01, 0x00000000 },
+	{ 0x000468,   1, 0x01, 0x00000004 },
+	{ 0x00046c,   1, 0x01, 0x00000001 },
+	{ 0x000470,  96, 0x01, 0x00000000 },
+	{ 0x0005e0,  16, 0x01, 0x00000d10 },
+	{ 0x000510,  16, 0x01, 0x3f800000 },
+	{ 0x000520,   1, 0x01, 0x000002b6 },
+	{ 0x000529,   1, 0x01, 0x00000001 },
+	{ 0x000530,  16, 0x01, 0xffff0000 },
+	{ 0x000550,  32, 0x01, 0xffff0000 },
+	{ 0x000585,   1, 0x01, 0x0000003f },
+	{ 0x000576,   1, 0x01, 0x00000003 },
+	{ 0x00057b,   1, 0x01, 0x00000059 },
+	{ 0x000586,   1, 0x01, 0x00000040 },
+	{ 0x000582,   2, 0x01, 0x00000080 },
+	{ 0x000595,   1, 0x01, 0x00400040 },
+	{ 0x000596,   1, 0x01, 0x00000492 },
+	{ 0x000597,   1, 0x01, 0x08080203 },
+	{ 0x0005ad,   1, 0x01, 0x00000008 },
+	{ 0x000598,   1, 0x01, 0x00020001 },
+	{ 0x0005d4,   1, 0x01, 0x00000001 },
+	{ 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 },
+	{ 0x000674,   1, 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 },
+	{ 0x0006b2,   1, 0x01, 0x00000055 },
+	{ 0x0007ad,   1, 0x01, 0x00000003 },
+	{ 0x000971,   1, 0x01, 0x00000008 },
+	{ 0x000972,   1, 0x01, 0x00000040 },
+	{ 0x000973,   1, 0x01, 0x0000012c },
+	{ 0x00097c,   1, 0x01, 0x00000040 },
+	{ 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, 0x0000000c },
+	{ 0x000683,   1, 0x01, 0x00000006 },
+	{ 0x000687,   1, 0x01, 0x003fffff },
+	{ 0x0006a0,   1, 0x01, 0x00000005 },
+	{ 0x000840,   1, 0x01, 0x00400008 },
+	{ 0x000841,   1, 0x01, 0x08000080 },
+	{ 0x000842,   1, 0x01, 0x00400008 },
+	{ 0x000843,   1, 0x01, 0x08000080 },
+	{ 0x000818,   8, 0x01, 0x00000000 },
+	{ 0x000848,  16, 0x01, 0x00000000 },
+	{ 0x000738,   1, 0x01, 0x00000000 },
+	{ 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 },
+	{ 0x00c413,   4, 0x01, 0x88888888 },
+	{ 0x00c423,   1, 0x01, 0x0000ff00 },
+	{ 0x00c420,   1, 0x01, 0x00880101 },
+	{ 0x01e100,   1, 0x01, 0x00000001 },
+	{}
+};
+
+const struct gf100_gr_pack
+gm204_grctx_pack_icmd[] = {
+	{ gm204_grctx_init_icmd_0 },
+	{}
+};
+
+static const struct gf100_gr_init
+gm204_grctx_init_b197_0[] = {
+	{ 0x000800,   8, 0x40, 0x00000000 },
+	{ 0x000804,   8, 0x40, 0x00000000 },
+	{ 0x000808,   8, 0x40, 0x00000400 },
+	{ 0x00080c,   8, 0x40, 0x00000300 },
+	{ 0x000810,   1, 0x04, 0x000000cf },
+	{ 0x000850,   7, 0x40, 0x00000000 },
+	{ 0x000814,   8, 0x40, 0x00000040 },
+	{ 0x000818,   8, 0x40, 0x00000001 },
+	{ 0x00081c,   8, 0x40, 0x00000000 },
+	{ 0x000820,   8, 0x40, 0x00000000 },
+	{ 0x001c00,  16, 0x10, 0x00000000 },
+	{ 0x001c04,  16, 0x10, 0x00000000 },
+	{ 0x001c08,  16, 0x10, 0x00000000 },
+	{ 0x001c0c,  16, 0x10, 0x00000000 },
+	{ 0x001d00,  16, 0x10, 0x00000000 },
+	{ 0x001d04,  16, 0x10, 0x00000000 },
+	{ 0x001d08,  16, 0x10, 0x00000000 },
+	{ 0x001d0c,  16, 0x10, 0x00000000 },
+	{ 0x001f00,  16, 0x08, 0x00000000 },
+	{ 0x001f04,  16, 0x08, 0x00000000 },
+	{ 0x001f80,  16, 0x08, 0x00000000 },
+	{ 0x001f84,  16, 0x08, 0x00000000 },
+	{ 0x002000,   1, 0x04, 0x00000000 },
+	{ 0x002040,   1, 0x04, 0x00000011 },
+	{ 0x002080,   1, 0x04, 0x00000020 },
+	{ 0x0020c0,   1, 0x04, 0x00000030 },
+	{ 0x002100,   1, 0x04, 0x00000040 },
+	{ 0x002140,   1, 0x04, 0x00000051 },
+	{ 0x00200c,   6, 0x40, 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,   4, 0x20, 0x00000000 },
+	{ 0x000384,   4, 0x20, 0x00000000 },
+	{ 0x000388,   4, 0x20, 0x00000000 },
+	{ 0x00038c,   4, 0x20, 0x00000000 },
+	{ 0x000700,   4, 0x10, 0x00000000 },
+	{ 0x000704,   4, 0x10, 0x00000000 },
+	{ 0x000708,   4, 0x10, 0x00000000 },
+	{ 0x002800, 128, 0x04, 0x00000000 },
+	{ 0x000a00,  16, 0x20, 0x00000000 },
+	{ 0x000a04,  16, 0x20, 0x00000000 },
+	{ 0x000a08,  16, 0x20, 0x00000000 },
+	{ 0x000a0c,  16, 0x20, 0x00000000 },
+	{ 0x000a10,  16, 0x20, 0x00000000 },
+	{ 0x000a14,  16, 0x20, 0x00000000 },
+	{ 0x000a18,  16, 0x20, 0x00006420 },
+	{ 0x000a1c,  16, 0x20, 0x00000000 },
+	{ 0x000c00,  16, 0x10, 0x00000000 },
+	{ 0x000c04,  16, 0x10, 0x00000000 },
+	{ 0x000c08,  16, 0x10, 0x00000000 },
+	{ 0x000c0c,  16, 0x10, 0x3f800000 },
+	{ 0x000d00,   8, 0x08, 0xffff0000 },
+	{ 0x000d04,   8, 0x08, 0xffff0000 },
+	{ 0x000e00,  16, 0x10, 0x00000000 },
+	{ 0x000e04,  16, 0x10, 0xffff0000 },
+	{ 0x000e08,  16, 0x10, 0xffff0000 },
+	{ 0x000d40,   4, 0x08, 0x00000000 },
+	{ 0x000d44,   4, 0x08, 0x00000000 },
+	{ 0x001e00,   8, 0x20, 0x00000001 },
+	{ 0x001e04,   8, 0x20, 0x00000001 },
+	{ 0x001e08,   8, 0x20, 0x00000002 },
+	{ 0x001e0c,   8, 0x20, 0x00000001 },
+	{ 0x001e10,   8, 0x20, 0x00000001 },
+	{ 0x001e14,   8, 0x20, 0x00000002 },
+	{ 0x001e18,   8, 0x20, 0x00000001 },
+	{ 0x001480,   8, 0x10, 0x00000000 },
+	{ 0x001484,   8, 0x10, 0x00000000 },
+	{ 0x001488,   8, 0x10, 0x00000000 },
+	{ 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 },
+	{ 0x001208,   1, 0x04, 0x00000000 },
+	{ 0x0015b4,   1, 0x04, 0x00000001 },
+	{ 0x0015cc,   1, 0x04, 0x00000000 },
+	{ 0x001534,   1, 0x04, 0x00000000 },
+	{ 0x000754,   1, 0x04, 0x00000001 },
+	{ 0x000fb0,   1, 0x04, 0x00000000 },
+	{ 0x0015d0,   1, 0x04, 0x00000000 },
+	{ 0x0011e0,   4, 0x04, 0x88888888 },
+	{ 0x00153c,   1, 0x04, 0x00000000 },
+	{ 0x0016b4,   1, 0x04, 0x00000003 },
+	{ 0x000fa4,   1, 0x04, 0x00000001 },
+	{ 0x000fbc,   4, 0x04, 0x0000ffff },
+	{ 0x000fa8,   1, 0x04, 0x0000ffff },
+	{ 0x000df8,   2, 0x04, 0x00000000 },
+	{ 0x001948,   1, 0x04, 0x00000000 },
+	{ 0x001970,   1, 0x04, 0x00000001 },
+	{ 0x00161c,   1, 0x04, 0x000009f0 },
+	{ 0x000dcc,   1, 0x04, 0x00000010 },
+	{ 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 },
+	{ 0x0013a4,   1, 0x04, 0x00000000 },
+	{ 0x001318,   1, 0x04, 0x00000001 },
+	{ 0x001080,   2, 0x04, 0x00000000 },
+	{ 0x001088,   2, 0x04, 0x00000001 },
+	{ 0x001090,   1, 0x04, 0x00000000 },
+	{ 0x001094,   1, 0x04, 0x00000001 },
+	{ 0x001098,   1, 0x04, 0x00000000 },
+	{ 0x00109c,   1, 0x04, 0x00000001 },
+	{ 0x0010a0,   2, 0x04, 0x00000000 },
+	{ 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 },
+	{ 0x00113c,   1, 0x04, 0x00000000 },
+	{ 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 },
+	{ 0x000f40,   5, 0x04, 0x00000000 },
+	{ 0x001234,   1, 0x04, 0x00000000 },
+	{ 0x001690,   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 },
+	{ 0x001004,   1, 0x04, 0x00000000 },
+	{ 0x001240,   8, 0x04, 0x00000000 },
+	{ 0x00037c,   1, 0x04, 0x00000001 },
+	{ 0x000740,   1, 0x04, 0x00000000 },
+	{ 0x001148,   1, 0x04, 0x00000000 },
+	{ 0x000fb4,   1, 0x04, 0x00000000 },
+	{ 0x000fb8,   1, 0x04, 0x00000002 },
+	{ 0x001130,   1, 0x04, 0x00000002 },
+	{ 0x000fd4,   2, 0x04, 0x00000000 },
+	{ 0x001030,   1, 0x04, 0x20181008 },
+	{ 0x001034,   1, 0x04, 0x40383028 },
+	{ 0x001038,   1, 0x04, 0x60585048 },
+	{ 0x00103c,   1, 0x04, 0x80787068 },
+	{ 0x000744,   1, 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 },
+	{ 0x000f60,   1, 0x04, 0x00000000 },
+	{ 0x000f64,   1, 0x04, 0x00400040 },
+	{ 0x000f68,   1, 0x04, 0x00002212 },
+	{ 0x000f6c,   1, 0x04, 0x08080203 },
+	{ 0x001108,   1, 0x04, 0x00000008 },
+	{ 0x000f70,   1, 0x04, 0x00080001 },
+	{ 0x000ffc,   1, 0x04, 0x00000000 },
+	{ 0x001134,   1, 0x04, 0x00000000 },
+	{ 0x000f1c,   1, 0x04, 0x00000000 },
+	{ 0x0011f8,   1, 0x04, 0x00000000 },
+	{ 0x001138,   1, 0x04, 0x00000001 },
+	{ 0x000300,   1, 0x04, 0x00000001 },
+	{ 0x0013a8,   1, 0x04, 0x00000000 },
+	{ 0x001224,   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 },
+	{ 0x000dd0,   1, 0x04, 0x00000000 },
+	{ 0x000dd4,   1, 0x04, 0x00000001 },
+	{ 0x0002f4,   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 },
+	{ 0x00111c,   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 },
+	{ 0x000f14,   1, 0x04, 0x00000000 },
+	{ 0x000374,   1, 0x04, 0x00000000 },
+	{ 0x000378,   1, 0x04, 0x0000000c },
+	{ 0x0007dc,   1, 0x04, 0x00000000 },
+	{ 0x00074c,   1, 0x04, 0x00000055 },
+	{ 0x001420,   1, 0x04, 0x00000003 },
+	{ 0x001008,   1, 0x04, 0x00000008 },
+	{ 0x00100c,   1, 0x04, 0x00000040 },
+	{ 0x001010,   1, 0x04, 0x0000012c },
+	{ 0x000d60,   1, 0x04, 0x00000040 },
+	{ 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 },
+	{ 0x000da8,   1, 0x04, 0x00000030 },
+	{ 0x000de4,   1, 0x04, 0x00000000 },
+	{ 0x000204,   1, 0x04, 0x00000006 },
+	{ 0x0002d0,   1, 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 },
+	{}
+};
+
+const struct gf100_gr_pack
+gm204_grctx_pack_mthd[] = {
+	{ gm204_grctx_init_b197_0, 0xb197 },
+	{ gf100_grctx_init_902d_0, 0x902d },
+	{}
+};
+
+static const struct gf100_gr_init
+gm204_grctx_init_fe_0[] = {
+	{ 0x404004,   8, 0x04, 0x00000000 },
+	{ 0x404024,   1, 0x04, 0x0000e000 },
+	{ 0x404028,   8, 0x04, 0x00000000 },
+	{ 0x4040a8,   8, 0x04, 0x00000000 },
+	{ 0x4040c8,   1, 0x04, 0xf801008f },
+	{ 0x4040d0,   6, 0x04, 0x00000000 },
+	{ 0x4040f8,   1, 0x04, 0x00000000 },
+	{ 0x404100,  10, 0x04, 0x00000000 },
+	{ 0x404130,   2, 0x04, 0x00000000 },
+	{ 0x404150,   1, 0x04, 0x0000002e },
+	{ 0x404154,   2, 0x04, 0x00000800 },
+	{ 0x404164,   1, 0x04, 0x00000045 },
+	{ 0x40417c,   2, 0x04, 0x00000000 },
+	{ 0x404194,   1, 0x04, 0x33000700 },
+	{ 0x4041a0,   4, 0x04, 0x00000000 },
+	{ 0x4041c4,   2, 0x04, 0x00000000 },
+	{}
+};
+
+static const struct gf100_gr_init
+gm204_grctx_init_ds_0[] = {
+	{ 0x405800,   1, 0x04, 0x8f8001bf },
+	{ 0x405830,   1, 0x04, 0x04001000 },
+	{ 0x405834,   1, 0x04, 0x08000000 },
+	{ 0x405838,   1, 0x04, 0x00010000 },
+	{ 0x405854,   1, 0x04, 0x00000000 },
+	{ 0x405870,   4, 0x04, 0x00000001 },
+	{ 0x405a00,   2, 0x04, 0x00000000 },
+	{ 0x405a18,   1, 0x04, 0x00000000 },
+	{ 0x405a1c,   1, 0x04, 0x000000ff },
+	{}
+};
+
+static const struct gf100_gr_init
+gm204_grctx_init_cwd_0[] = {
+	{ 0x405b00,   1, 0x04, 0x00000000 },
+	{ 0x405b10,   1, 0x04, 0x00001000 },
+	{ 0x405b20,   1, 0x04, 0x04000000 },
+	{ 0x405b60,   6, 0x04, 0x00000000 },
+	{ 0x405ba0,   6, 0x04, 0x00000000 },
+	{}
+};
+
+static const struct gf100_gr_init
+gm204_grctx_init_pd_0[] = {
+	{ 0x406020,   1, 0x04, 0x17410001 },
+	{ 0x406028,   4, 0x04, 0x00000001 },
+	{ 0x4064a8,   1, 0x04, 0x00000000 },
+	{ 0x4064ac,   1, 0x04, 0x00003fff },
+	{ 0x4064b0,   3, 0x04, 0x00000000 },
+	{ 0x4064c0,   1, 0x04, 0x80400280 },
+	{ 0x4064c4,   1, 0x04, 0x0400ffff },
+	{ 0x4064c8,   1, 0x04, 0x01800780 },
+	{ 0x4064cc,   9, 0x04, 0x00000000 },
+	{ 0x4064fc,   1, 0x04, 0x0000022a },
+	{ 0x406500,   1, 0x04, 0x00000000 },
+	{}
+};
+
+static const struct gf100_gr_init
+gm204_grctx_init_be_0[] = {
+	{ 0x408800,   1, 0x04, 0x32882a3c },
+	{ 0x408804,   1, 0x04, 0x00000040 },
+	{ 0x408808,   1, 0x04, 0x1003e005 },
+	{ 0x408840,   1, 0x04, 0x00000e0b },
+	{ 0x408900,   1, 0x04, 0xb080b801 },
+	{ 0x408904,   1, 0x04, 0x63038001 },
+	{ 0x408908,   1, 0x04, 0x12c8502f },
+	{ 0x408980,   1, 0x04, 0x0000011d },
+	{}
+};
+
+const struct gf100_gr_pack
+gm204_grctx_pack_hub[] = {
+	{ gf100_grctx_init_main_0 },
+	{ gm204_grctx_init_fe_0 },
+	{ gk110_grctx_init_pri_0 },
+	{ gk104_grctx_init_memfmt_0 },
+	{ gm204_grctx_init_ds_0 },
+	{ gm204_grctx_init_cwd_0 },
+	{ gm204_grctx_init_pd_0 },
+	{ gk208_grctx_init_rstr2d_0 },
+	{ gk104_grctx_init_scc_0 },
+	{ gm204_grctx_init_be_0 },
+	{}
+};
+
+const struct gf100_gr_init
+gm204_grctx_init_prop_0[] = {
+	{ 0x418400,   1, 0x04, 0x38e01e00 },
+	{ 0x418404,   1, 0x04, 0x70001fff },
+	{ 0x41840c,   1, 0x04, 0x20001008 },
+	{ 0x418410,   2, 0x04, 0x0fff0fff },
+	{ 0x418418,   1, 0x04, 0x07ff07ff },
+	{ 0x41841c,   1, 0x04, 0x3feffbff },
+	{ 0x418450,   6, 0x04, 0x00000000 },
+	{ 0x418468,   1, 0x04, 0x00000001 },
+	{ 0x41846c,   2, 0x04, 0x00000000 },
+	{}
+};
+
+static const struct gf100_gr_init
+gm204_grctx_init_gpc_unk_1[] = {
+	{ 0x418600,   1, 0x04, 0x0000007f },
+	{ 0x418684,   1, 0x04, 0x0000001f },
+	{ 0x418700,   1, 0x04, 0x00000002 },
+	{ 0x418704,   1, 0x04, 0x00000080 },
+	{ 0x418708,   1, 0x04, 0x40000000 },
+	{ 0x41870c,   2, 0x04, 0x00000000 },
+	{ 0x418728,   1, 0x04, 0x00010000 },
+	{}
+};
+
+const struct gf100_gr_init
+gm204_grctx_init_setup_0[] = {
+	{ 0x418800,   1, 0x04, 0x7006863a },
+	{ 0x418808,   1, 0x04, 0x00000000 },
+	{ 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 },
+	{}
+};
+
+const struct gf100_gr_init
+gm204_grctx_init_gpm_0[] = {
+	{ 0x418c10,   8, 0x04, 0x00000000 },
+	{ 0x418c40,   1, 0x04, 0xffffffff },
+	{ 0x418c6c,   1, 0x04, 0x00000001 },
+	{ 0x418c80,   1, 0x04, 0x20200000 },
+	{}
+};
+
+const struct gf100_gr_init
+gm204_grctx_init_gpc_unk_2[] = {
+	{ 0x418e00,   1, 0x04, 0x90040000 },
+	{ 0x418e24,   1, 0x04, 0x00000000 },
+	{ 0x418e28,   1, 0x04, 0x00000030 },
+	{ 0x418e2c,   1, 0x04, 0x00000100 },
+	{ 0x418e30,   3, 0x04, 0x00000000 },
+	{ 0x418e40,  22, 0x04, 0x00000000 },
+	{ 0x418ea0,  12, 0x04, 0x00000000 },
+	{}
+};
+
+static const struct gf100_gr_pack
+gm204_grctx_pack_gpc[] = {
+	{ gm107_grctx_init_gpc_unk_0 },
+	{ gm204_grctx_init_prop_0 },
+	{ gm204_grctx_init_gpc_unk_1 },
+	{ gm204_grctx_init_setup_0 },
+	{ gf100_grctx_init_zcull_0 },
+	{ gk208_grctx_init_crstr_0 },
+	{ gm204_grctx_init_gpm_0 },
+	{ gm204_grctx_init_gpc_unk_2 },
+	{ gf100_grctx_init_gcc_0 },
+	{}
+};
+
+static const struct gf100_gr_init
+gm204_grctx_init_pe_0[] = {
+	{ 0x419848,   1, 0x04, 0x00000000 },
+	{ 0x419864,   1, 0x04, 0x00000029 },
+	{ 0x419888,   1, 0x04, 0x00000000 },
+	{}
+};
+
+static const struct gf100_gr_init
+gm204_grctx_init_tex_0[] = {
+	{ 0x419a00,   1, 0x04, 0x000100f0 },
+	{ 0x419a04,   1, 0x04, 0x00000005 },
+	{ 0x419a08,   1, 0x04, 0x00000621 },
+	{ 0x419a0c,   1, 0x04, 0x00320000 },
+	{ 0x419a10,   1, 0x04, 0x00000000 },
+	{ 0x419a14,   1, 0x04, 0x00000200 },
+	{ 0x419a1c,   1, 0x04, 0x0010c000 },
+	{ 0x419a20,   1, 0x04, 0x20008a00 },
+	{ 0x419a30,   1, 0x04, 0x00000001 },
+	{ 0x419a3c,   1, 0x04, 0x0000181e },
+	{ 0x419ac4,   1, 0x04, 0x00000000 },
+	{}
+};
+
+static const struct gf100_gr_init
+gm204_grctx_init_mpc_0[] = {
+	{ 0x419c00,   1, 0x04, 0x0000009a },
+	{ 0x419c04,   1, 0x04, 0x80000bd6 },
+	{ 0x419c08,   1, 0x04, 0x00000002 },
+	{ 0x419c20,   1, 0x04, 0x00000000 },
+	{ 0x419c24,   1, 0x04, 0x00084210 },
+	{ 0x419c28,   1, 0x04, 0x3efbefbe },
+	{ 0x419c2c,   1, 0x04, 0x00000000 },
+	{ 0x419c34,   1, 0x04, 0x71ff1ff3 },
+	{ 0x419c3c,   1, 0x04, 0x00001919 },
+	{ 0x419c50,   1, 0x04, 0x00000005 },
+	{}
+};
+
+static const struct gf100_gr_init
+gm204_grctx_init_l1c_0[] = {
+	{ 0x419c84,   1, 0x04, 0x0000003e },
+	{ 0x419c90,   1, 0x04, 0x0000000a },
+	{}
+};
+
+static const struct gf100_gr_init
+gm204_grctx_init_sm_0[] = {
+	{ 0x419e04,   3, 0x04, 0x00000000 },
+	{ 0x419e10,   1, 0x04, 0x00001c02 },
+	{ 0x419e44,   1, 0x04, 0x00d3eff2 },
+	{ 0x419e48,   1, 0x04, 0x00000000 },
+	{ 0x419e4c,   1, 0x04, 0x0000007f },
+	{ 0x419e50,   1, 0x04, 0x00000000 },
+	{ 0x419e58,   6, 0x04, 0x00000000 },
+	{ 0x419e74,  10, 0x04, 0x00000000 },
+	{ 0x419eac,   1, 0x04, 0x0001cf8b },
+	{ 0x419eb0,   1, 0x04, 0x00030300 },
+	{ 0x419eb8,   1, 0x04, 0x40000000 },
+	{ 0x419ef0,  24, 0x04, 0x00000000 },
+	{ 0x419f68,   2, 0x04, 0x00000000 },
+	{ 0x419f70,   1, 0x04, 0x00000020 },
+	{ 0x419f78,   1, 0x04, 0x00010beb },
+	{ 0x419f7c,   1, 0x04, 0x00000000 },
+	{}
+};
+
+const struct gf100_gr_pack
+gm204_grctx_pack_tpc[] = {
+	{ gm204_grctx_init_pe_0 },
+	{ gm204_grctx_init_tex_0 },
+	{ gm204_grctx_init_mpc_0 },
+	{ gm204_grctx_init_l1c_0 },
+	{ gm204_grctx_init_sm_0 },
+	{}
+};
+
+static const struct gf100_gr_init
+gm204_grctx_init_pes_0[] = {
+	{ 0x41be24,   1, 0x04, 0x0000000e },
+	{}
+};
+
+static const struct gf100_gr_init
+gm204_grctx_init_cbm_0[] = {
+	{ 0x41bec0,   1, 0x04, 0x00000000 },
+	{ 0x41bec4,   1, 0x04, 0x01030000 },
+	{ 0x41bee4,   1, 0x04, 0x00000000 },
+	{ 0x41bef0,   1, 0x04, 0x000003ff },
+	{ 0x41bef4,   2, 0x04, 0x00000000 },
+	{}
+};
+
+const struct gf100_gr_pack
+gm204_grctx_pack_ppc[] = {
+	{ gm204_grctx_init_pes_0 },
+	{ gm204_grctx_init_cbm_0 },
+	{ gm107_grctx_init_wwdx_0 },
+	{}
+};
+
+/*******************************************************************************
+ * PGRAPH context implementation
+ ******************************************************************************/
+
+static void
+gm204_grctx_generate_tpcid(struct gf100_gr_priv *priv)
+{
+	int gpc, tpc, id;
+
+	for (tpc = 0, id = 0; tpc < 4; tpc++) {
+		for (gpc = 0; gpc < priv->gpc_nr; gpc++) {
+			if (tpc < priv->tpc_nr[gpc]) {
+				nv_wr32(priv, TPC_UNIT(gpc, tpc, 0x698), id);
+				nv_wr32(priv, GPC_UNIT(gpc, 0x0c10 + tpc * 4), id);
+				nv_wr32(priv, TPC_UNIT(gpc, tpc, 0x088), id);
+				id++;
+			}
+		}
+	}
+}
+
+static void
+gm204_grctx_generate_rop_active_fbps(struct gf100_gr_priv *priv)
+{
+	const u32 fbp_count = nv_rd32(priv, 0x12006c);
+	nv_mask(priv, 0x408850, 0x0000000f, fbp_count); /* zrop */
+	nv_mask(priv, 0x408958, 0x0000000f, fbp_count); /* crop */
+}
+
+static void
+gm204_grctx_generate_405b60(struct gf100_gr_priv *priv)
+{
+	const u32 dist_nr = DIV_ROUND_UP(priv->tpc_total, 4);
+	u32 dist[TPC_MAX] = {};
+	u32 gpcs[GPC_MAX] = {};
+	u8  tpcnr[GPC_MAX];
+	int tpc, gpc, i;
+
+	memcpy(tpcnr, priv->tpc_nr, sizeof(priv->tpc_nr));
+
+	/* won't result in the same distribution as the binary driver where
+	 * some of the gpcs have more tpcs than others, but this shall do
+	 * for the moment.  the code for earlier gpus has this issue too.
+	 */
+	for (gpc = -1, i = 0; i < priv->tpc_total; i++) {
+		do {
+			gpc = (gpc + 1) % priv->gpc_nr;
+		} while(!tpcnr[gpc]);
+		tpc = priv->tpc_nr[gpc] - tpcnr[gpc]--;
+
+		dist[i / 4] |= ((gpc << 4) | tpc) << ((i % 4) * 8);
+		gpcs[gpc] |= i << (tpc * 8);
+	}
+
+	for (i = 0; i < dist_nr; i++)
+		nv_wr32(priv, 0x405b60 + (i * 4), dist[i]);
+	for (i = 0; i < priv->gpc_nr; i++)
+		nv_wr32(priv, 0x405ba0 + (i * 4), gpcs[i]);
+}
+
+void
+gm204_grctx_generate_main(struct gf100_gr_priv *priv, struct gf100_grctx *info)
+{
+	struct gf100_grctx_oclass *oclass = (void *)nv_engine(priv)->cclass;
+	u32 tmp;
+	int i;
+
+	gf100_gr_mmio(priv, oclass->hub);
+	gf100_gr_mmio(priv, oclass->gpc);
+	gf100_gr_mmio(priv, oclass->zcull);
+	gf100_gr_mmio(priv, oclass->tpc);
+	gf100_gr_mmio(priv, oclass->ppc);
+
+	nv_wr32(priv, 0x404154, 0x00000000);
+
+	oclass->bundle(info);
+	oclass->pagepool(info);
+	oclass->attrib(info);
+	oclass->unkn(priv);
+
+	gm204_grctx_generate_tpcid(priv);
+	gf100_grctx_generate_r406028(priv);
+	gk104_grctx_generate_r418bb8(priv);
+
+	for (i = 0; i < 8; i++)
+		nv_wr32(priv, 0x4064d0 + (i * 0x04), 0x00000000);
+	nv_wr32(priv, 0x406500, 0x00000000);
+
+	nv_wr32(priv, 0x405b00, (priv->tpc_total << 8) | priv->gpc_nr);
+
+	gm204_grctx_generate_rop_active_fbps(priv);
+
+	for (tmp = 0, i = 0; i < priv->gpc_nr; i++)
+		tmp |= ((1 << priv->tpc_nr[i]) - 1) << (i * 4);
+	nv_wr32(priv, 0x4041c4, tmp);
+
+	gm204_grctx_generate_405b60(priv);
+
+	gf100_gr_icmd(priv, oclass->icmd);
+	nv_wr32(priv, 0x404154, 0x00000800);
+	gf100_gr_mthd(priv, oclass->mthd);
+
+	nv_mask(priv, 0x418e94, 0xffffffff, 0xc4230000);
+	nv_mask(priv, 0x418e4c, 0xffffffff, 0x70000000);
+}
+
+struct nvkm_oclass *
+gm204_grctx_oclass = &(struct gf100_grctx_oclass) {
+	.base.handle = NV_ENGCTX(GR, 0x24),
+	.base.ofuncs = &(struct nvkm_ofuncs) {
+		.ctor = gf100_gr_context_ctor,
+		.dtor = gf100_gr_context_dtor,
+		.init = _nvkm_gr_context_init,
+		.fini = _nvkm_gr_context_fini,
+		.rd32 = _nvkm_gr_context_rd32,
+		.wr32 = _nvkm_gr_context_wr32,
+	},
+	.main  = gm204_grctx_generate_main,
+	.unkn  = gk104_grctx_generate_unkn,
+	.hub   = gm204_grctx_pack_hub,
+	.gpc   = gm204_grctx_pack_gpc,
+	.zcull = gf100_grctx_pack_zcull,
+	.tpc   = gm204_grctx_pack_tpc,
+	.ppc   = gm204_grctx_pack_ppc,
+	.icmd  = gm204_grctx_pack_icmd,
+	.mthd  = gm204_grctx_pack_mthd,
+	.bundle = gm107_grctx_generate_bundle,
+	.bundle_size = 0x3000,
+	.bundle_min_gpm_fifo_depth = 0x180,
+	.bundle_token_limit = 0x780,
+	.pagepool = gm107_grctx_generate_pagepool,
+	.pagepool_size = 0x20000,
+	.attrib = gm107_grctx_generate_attrib,
+	.attrib_nr_max = 0x600,
+	.attrib_nr = 0x400,
+	.alpha_nr_max = 0x1800,
+	.alpha_nr = 0x1000,
+}.base;

+ 83 - 0
drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgm206.c

@@ -0,0 +1,83 @@
+/*
+ * Copyright 2015 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 "ctxgf100.h"
+
+static const struct gf100_gr_init
+gm206_grctx_init_gpc_unk_1[] = {
+	{ 0x418600,   1, 0x04, 0x0000007f },
+	{ 0x418684,   1, 0x04, 0x0000001f },
+	{ 0x418700,   1, 0x04, 0x00000002 },
+	{ 0x418704,   1, 0x04, 0x00000080 },
+	{ 0x418708,   1, 0x04, 0x40000000 },
+	{ 0x41870c,   2, 0x04, 0x00000000 },
+	{ 0x418728,   1, 0x04, 0x00300020 },
+	{}
+};
+
+static const struct gf100_gr_pack
+gm206_grctx_pack_gpc[] = {
+	{ gm107_grctx_init_gpc_unk_0 },
+	{ gm204_grctx_init_prop_0 },
+	{ gm206_grctx_init_gpc_unk_1 },
+	{ gm204_grctx_init_setup_0 },
+	{ gf100_grctx_init_zcull_0 },
+	{ gk208_grctx_init_crstr_0 },
+	{ gm204_grctx_init_gpm_0 },
+	{ gm204_grctx_init_gpc_unk_2 },
+	{ gf100_grctx_init_gcc_0 },
+	{}
+};
+
+struct nvkm_oclass *
+gm206_grctx_oclass = &(struct gf100_grctx_oclass) {
+	.base.handle = NV_ENGCTX(GR, 0x26),
+	.base.ofuncs = &(struct nvkm_ofuncs) {
+		.ctor = gf100_gr_context_ctor,
+		.dtor = gf100_gr_context_dtor,
+		.init = _nvkm_gr_context_init,
+		.fini = _nvkm_gr_context_fini,
+		.rd32 = _nvkm_gr_context_rd32,
+		.wr32 = _nvkm_gr_context_wr32,
+	},
+	.main  = gm204_grctx_generate_main,
+	.unkn  = gk104_grctx_generate_unkn,
+	.hub   = gm204_grctx_pack_hub,
+	.gpc   = gm206_grctx_pack_gpc,
+	.zcull = gf100_grctx_pack_zcull,
+	.tpc   = gm204_grctx_pack_tpc,
+	.ppc   = gm204_grctx_pack_ppc,
+	.icmd  = gm204_grctx_pack_icmd,
+	.mthd  = gm204_grctx_pack_mthd,
+	.bundle = gm107_grctx_generate_bundle,
+	.bundle_size = 0x3000,
+	.bundle_min_gpm_fifo_depth = 0x180,
+	.bundle_token_limit = 0x780,
+	.pagepool = gm107_grctx_generate_pagepool,
+	.pagepool_size = 0x20000,
+	.attrib = gm107_grctx_generate_attrib,
+	.attrib_nr_max = 0x600,
+	.attrib_nr = 0x400,
+	.alpha_nr_max = 0x1800,
+	.alpha_nr = 0x1000,
+}.base;

+ 113 - 1
drivers/gpu/drm/nouveau/nvkm/engine/gr/fuc/gpc.fuc

@@ -52,6 +52,12 @@ mmio_list_base:
 #endif
 
 #ifdef INCLUDE_CODE
+#define gpc_wr32(addr,reg)                                                    /*
+*/	mov b32 $r15 reg                                                      /*
+*/	imm32($r14, addr)                                                     /*
+*/	or $r14 NV_PGRAPH_GPCX_GPCCS_MMIO_CTRL_BASE_ENABLE                    /*
+*/	call(nv_wr32)
+
 // reports an exception to the host
 //
 // In: $r15 error code (see os.h)
@@ -64,6 +70,43 @@ error:
 	pop $r14
 	ret
 
+#if CHIPSET >= GM107
+tpc_strand_wait:
+	push $r9
+	trace_set(T_STRTPC)
+	tpc_strand_busy:
+		nv_iord($r9, NV_PGRAPH_GPCX_GPCCS_TPC_STATUS, 0)
+		bra b32 $r9 0x0 ne #tpc_strand_busy
+	trace_clr(T_STRTPC)
+	pop $r9
+	ret
+
+#define tpc_strand_wait() call(tpc_strand_wait)
+#define tpc_strand_enable()                                                   /*
+*/	mov $r15 NV_PGRAPH_GPC0_TPCX_STRAND_CMD_ENABLE                        /*
+*/	gpc_wr32(NV_PGRAPH_GPC0_TPCX_STRAND_CMD, $r15)                        /*
+*/	tpc_strand_wait()
+#define tpc_strand_disable()                                                  /*
+*/	mov $r15 NV_PGRAPH_GPC0_TPCX_STRAND_CMD_DISABLE                       /*
+*/	gpc_wr32(NV_PGRAPH_GPC0_TPCX_STRAND_CMD, $r15)                        /*
+*/	tpc_strand_wait()
+#define tpc_strand_seek(p)                                                    /*
+*/	mov $r15 NV_PGRAPH_GPC0_TPCX_STRAND_INDEX_ALL                         /*
+*/	gpc_wr32(NV_PGRAPH_GPC0_TPCX_STRAND_INDEX, $r15)                      /*
+*/	mov $r15 p                                                            /*
+*/	gpc_wr32(NV_PGRAPH_GPC0_TPCX_STRAND_SELECT, $r15)                     /*
+*/	mov $r15 NV_PGRAPH_GPC0_TPCX_STRAND_CMD_SEEK                          /*
+*/	tpc_strand_wait()
+#define tpc_strand_info(m)                                                    /*
+*/	gpc_wr32(NV_PGRAPH_GPC0_TPCX_STRAND_CMD, $r15)                        /*
+*/	mov $r15 m                                                            /*
+*/	gpc_wr32(NV_PGRAPH_GPC0_TPCX_STRAND_DATA, $r15)                       /*
+*/	mov $r15 NV_PGRAPH_GPC0_TPCX_STRAND_CMD_GET_INFO                      /*
+*/	gpc_wr32(NV_PGRAPH_GPC0_TPCX_STRAND_CMD, $r15)                        /*
+*/	tpc_strand_wait()
+#endif
+
+
 // GPC fuc initialisation, executed by triggering ucode start, will
 // fall through to main loop after completion.
 //
@@ -101,7 +144,7 @@ init:
 	// enable interrupts
 	bset $flags ie0
 
-	// figure out which GPC we are, and how many TPCs we have
+	// how many TPCs do we have?
 	nv_iord($r2, NV_PGRAPH_GPCX_GPCCS_UNITS, 0)
 	mov $r3 1
 	and $r2 0x1f
@@ -109,8 +152,12 @@ init:
 	sub b32 $r3 1
 	st b32 D[$r0 + #tpc_count] $r2
 	st b32 D[$r0 + #tpc_mask] $r3
+
+	// determine which GPC we are, setup (optional) mmio access offset
 	nv_iord($r2, NV_PGRAPH_GPCX_GPCCS_MYINDEX, 0)
 	st b32 D[$r0 + #gpc_id] $r2
+	shl b32 $r2 15
+	nv_iowr(NV_PGRAPH_GPCX_GPCCS_MMIO_BASE, 0, $r2)
 
 #if NV_PGRAPH_GPCX_UNK__SIZE > 0
 	// figure out which, and how many, UNKs are actually present
@@ -186,8 +233,56 @@ init:
 	// calculate size of strand context data
 	mov b32 $r15 $r2
 	call(strand_ctx_init)
+	add b32 $r2 $r15
 	add b32 $r3 $r15
 
+#if CHIPSET >= GM107
+	// calculate size of tpc strand context data
+	mov $r15 NV_PGRAPH_GPC0_TPCX_STRAND_INDEX_ALL
+	gpc_wr32(NV_PGRAPH_GPC0_TPCX_STRAND_INDEX, $r15)
+	tpc_strand_enable();
+	tpc_strand_seek(0);
+	tpc_strand_info(-1);
+
+	ld b32 $r4 D[$r0 + #tpc_count]
+	mov $r5 NV_PGRAPH_GPC0_TPC0
+	ld b32 $r6 D[$r0 + #gpc_id]
+	shl b32 $r6 15
+	add b32 $r5 $r6
+	tpc_strand_init_tpc_loop:
+		add b32 $r14 $r5 NV_TPC_STRAND_CNT
+		call(nv_rd32)
+		mov b32 $r6 $r15
+		clear b32 $r7
+		tpc_strand_init_idx_loop:
+			add b32 $r14 $r5 NV_TPC_STRAND_INDEX
+			mov b32 $r15 $r7
+			call(nv_wr32)
+			add b32 $r14 $r5 NV_TPC_STRAND_SAVE_SWBASE
+			shr b32 $r15 $r2 8
+			call(nv_wr32)
+			add b32 $r14 $r5 NV_TPC_STRAND_LOAD_SWBASE
+			shr b32 $r15 $r2 8
+			call(nv_wr32)
+			add b32 $r14 $r5 NV_TPC_STRAND_WORDS
+			call(nv_rd32)
+			shr b32 $r15 6
+			add b32 $r15 1
+			shl b32 $r15 8
+			add b32 $r2 $r15
+			add b32 $r3 $r15
+			add b32 $r7 1
+			sub b32 $r6 1
+			bra nz #tpc_strand_init_idx_loop
+		add b32 $r5 NV_PGRAPH_GPC0_TPC0__SIZE
+		sub b32 $r4 1
+		bra nz #tpc_strand_init_tpc_loop
+
+	mov $r15 NV_PGRAPH_GPC0_TPCX_STRAND_INDEX_ALL
+	gpc_wr32(NV_PGRAPH_GPC0_TPCX_STRAND_INDEX, $r15)
+	tpc_strand_disable();
+#endif
+
 	// save context size, and tell HUB we're done
 	nv_iowr(NV_PGRAPH_GPCX_GPCCS_CC_SCRATCH_VAL(1), 0, $r3)
 	clear b32 $r2
@@ -306,6 +401,9 @@ ctx_redswitch:
 ctx_xfer:
 	// set context base address
 	nv_iowr(NV_PGRAPH_GPCX_GPCCS_MEM_BASE, 0, $r15)
+#if CHIPSET >= GM107
+	gpc_wr32(NV_PGRAPH_GPC0_TPCX_STRAND_MEM_BASE, $r15)
+#endif
 	bra not $p1 #ctx_xfer_not_load
 		call(ctx_redswitch)
 	ctx_xfer_not_load:
@@ -318,6 +416,14 @@ ctx_xfer:
 	add b32 $r2 NV_PGRAPH_GPCX_GPCCS_STRAND_CMD_SAVE
 	nv_iowr(NV_PGRAPH_GPCX_GPCCS_STRAND_CMD, 0x3f, $r2)
 
+#if CHIPSET >= GM107
+	tpc_strand_enable();
+	tpc_strand_seek(0);
+	xbit $r15 $flags $p1	// SAVE/LOAD
+	add b32 $r15 NV_PGRAPH_GPC0_TPCX_STRAND_CMD_SAVE
+	gpc_wr32(NV_PGRAPH_GPC0_TPCX_STRAND_CMD, $r15)
+#endif
+
 	// mmio context
 	xbit $r10 $flags $p1	// direction
 	or $r10 2		// first
@@ -362,6 +468,9 @@ ctx_xfer:
 
 	// wait for strands to finish
 	call(strand_wait)
+#if CHIPSET >= GM107
+	tpc_strand_wait()
+#endif
 
 	// if load, or a save without a load following, do some
 	// unknown stuff that's done after finishing a block of
@@ -370,6 +479,9 @@ ctx_xfer:
 	bra not $p2 #ctx_xfer_done
 	ctx_xfer_post:
 		call(strand_post)
+#if CHIPSET >= GM107
+		tpc_strand_disable()
+#endif
 
 	// mark completion in HUB's barrier
 	ctx_xfer_done:

+ 147 - 147
drivers/gpu/drm/nouveau/nvkm/engine/gr/fuc/gpcgf100.fuc3.h

@@ -310,7 +310,7 @@ uint32_t gf100_grgpc_code[] = {
 	0x03f01200,
 	0x0002d000,
 	0x17f104bd,
-	0x10fe04e6,
+	0x10fe04f8,
 	0x0007f100,
 	0x0003f007,
 	0xbd0000d0,
@@ -329,157 +329,157 @@ uint32_t gf100_grgpc_code[] = {
 	0xf0860027,
 	0x22cf0123,
 	0x04028000,
-	0x010027f1,
-	0xcf0223f0,
-	0x34bd0022,
-	0xf1082595,
-	0xf0c00007,
-	0x05d00103,
+	0xf10f24b6,
+	0xf0c90007,
+	0x02d00103,
 	0xf104bd00,
-	0xf0c10007,
-	0x05d00103,
-	0x9804bd00,
-	0x0f98000e,
-	0x5021f501,
-	0x002fbb01,
-	0x98003fbb,
-	0x0f98010e,
-	0x5021f502,
-	0x050e9801,
-	0xbb00effd,
-	0x3ebb002e,
-	0x0235b600,
-	0xd30007f1,
-	0xd00103f0,
-	0x04bd0003,
-	0xb60825b6,
-	0x20b60635,
-	0x0130b601,
-	0xb60824b6,
-	0x2fb90834,
-	0xd321f502,
-	0x003fbb02,
-	0x010007f1,
+	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,
+	0xbb002fbb,
+	0x07f1003f,
+	0x03f00100,
+	0x0003d002,
+	0x24bd04bd,
+	0xf11f29f0,
+	0xf0080007,
+	0x02d00203,
+/* 0x04bb: main */
+	0xf404bd00,
+	0x28f40031,
+	0x1cd7f000,
+	0xf43921f4,
+	0xe4b0f401,
+	0x1e18f404,
+	0xf00181fe,
+	0x20bd0627,
+	0xb60412fd,
+	0x1efd01e4,
+	0x0018fe05,
+	0x05b021f5,
+/* 0x04eb: main_not_ctx_xfer */
+	0x94d30ef4,
+	0xf5f010ef,
+	0x7e21f501,
+	0xc60ef403,
+/* 0x04f8: ih */
+	0x88fe80f9,
+	0xf980f901,
+	0xf9a0f990,
+	0xf9d0f9b0,
+	0xbdf0f9e0,
+	0x00a7f104,
+	0x00a3f002,
+	0xc400aacf,
+	0x0bf404ab,
+	0x1cd7f02c,
+	0x1a00e7f1,
+	0xcf00e3f0,
+	0xf7f100ee,
+	0xf3f01900,
+	0x00ffcf00,
+	0xf00421f4,
+	0x07f101e7,
+	0x03f01d00,
+	0x000ed000,
+/* 0x0546: ih_no_fifo */
+	0x07f104bd,
+	0x03f00100,
+	0x000ad000,
+	0xf0fc04bd,
+	0xd0fce0fc,
+	0xa0fcb0fc,
+	0x80fc90fc,
+	0xfc0088fe,
+	0x0032f480,
+/* 0x056a: hub_barrier_done */
+	0xf7f001f8,
+	0x040e9801,
+	0xb904febb,
+	0xe7f102ff,
+	0xe3f09418,
+	0x9d21f440,
+/* 0x0582: ctx_redswitch */
+	0xf7f000f8,
+	0x0007f120,
+	0x0103f085,
+	0xbd000fd0,
+	0x08e7f004,
+/* 0x0594: ctx_redswitch_delay */
+	0xf401e2b6,
+	0xf5f1fd1b,
+	0xf5f10800,
+	0x07f10200,
+	0x03f08500,
+	0x000fd001,
+	0x00f804bd,
+/* 0x05b0: ctx_xfer */
+	0x810007f1,
 	0xd00203f0,
-	0x04bd0003,
-	0x29f024bd,
-	0x0007f11f,
-	0x0203f008,
-	0xbd0002d0,
-/* 0x04a9: main */
-	0x0031f404,
-	0xf00028f4,
-	0x21f41cd7,
-	0xf401f439,
-	0xf404e4b0,
-	0x81fe1e18,
-	0x0627f001,
-	0x12fd20bd,
-	0x01e4b604,
-	0xfe051efd,
-	0x21f50018,
-	0x0ef4059e,
-/* 0x04d9: main_not_ctx_xfer */
-	0x10ef94d3,
-	0xf501f5f0,
-	0xf4037e21,
-/* 0x04e6: ih */
-	0x80f9c60e,
-	0xf90188fe,
-	0xf990f980,
-	0xf9b0f9a0,
-	0xf9e0f9d0,
-	0xf104bdf0,
-	0xf00200a7,
-	0xaacf00a3,
-	0x04abc400,
-	0xf02c0bf4,
-	0xe7f11cd7,
-	0xe3f01a00,
-	0x00eecf00,
-	0x1900f7f1,
-	0xcf00f3f0,
-	0x21f400ff,
-	0x01e7f004,
-	0x1d0007f1,
-	0xd00003f0,
-	0x04bd000e,
-/* 0x0534: ih_no_fifo */
-	0x010007f1,
-	0xd00003f0,
-	0x04bd000a,
-	0xe0fcf0fc,
-	0xb0fcd0fc,
-	0x90fca0fc,
-	0x88fe80fc,
-	0xf480fc00,
-	0x01f80032,
-/* 0x0558: hub_barrier_done */
-	0x9801f7f0,
-	0xfebb040e,
-	0x02ffb904,
-	0x9418e7f1,
-	0xf440e3f0,
-	0x00f89d21,
-/* 0x0570: ctx_redswitch */
-	0xf120f7f0,
-	0xf0850007,
-	0x0fd00103,
-	0xf004bd00,
-/* 0x0582: ctx_redswitch_delay */
-	0xe2b608e7,
-	0xfd1bf401,
-	0x0800f5f1,
-	0x0200f5f1,
-	0x850007f1,
-	0xd00103f0,
 	0x04bd000f,
-/* 0x059e: ctx_xfer */
-	0x07f100f8,
-	0x03f08100,
-	0x000fd002,
-	0x11f404bd,
-	0x7021f507,
-/* 0x05b1: ctx_xfer_not_load */
-	0x6a21f505,
-	0xf124bd02,
-	0xf047fc07,
+	0xf50711f4,
+/* 0x05c3: ctx_xfer_not_load */
+	0xf5058221,
+	0xbd026a21,
+	0xfc07f124,
+	0x0203f047,
+	0xbd0002d0,
+	0x012cf004,
+	0xf10320b6,
+	0xf04afc07,
 	0x02d00203,
 	0xf004bd00,
-	0x20b6012c,
-	0xfc07f103,
-	0x0203f04a,
-	0xbd0002d0,
-	0x01acf004,
-	0xf102a5f0,
-	0xf00000b7,
-	0x0c9850b3,
-	0x0fc4b604,
-	0x9800bcbb,
-	0x0d98000c,
-	0x00e7f001,
-	0x016f21f5,
-	0xf001acf0,
-	0xb7f104a5,
-	0xb3f04000,
-	0x040c9850,
-	0xbb0fc4b6,
-	0x0c9800bc,
-	0x020d9801,
-	0xf1060f98,
-	0xf50800e7,
-	0xf5016f21,
-	0xf4025e21,
-	0x12f40601,
-/* 0x0629: ctx_xfer_post */
-	0x7f21f507,
-/* 0x062d: ctx_xfer_done */
-	0x5821f502,
-	0x0000f805,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
+	0xa5f001ac,
+	0x00b7f102,
+	0x50b3f000,
+	0xb6040c98,
+	0xbcbb0fc4,
+	0x000c9800,
+	0xf0010d98,
+	0x21f500e7,
+	0xacf0016f,
+	0x04a5f001,
+	0x4000b7f1,
+	0x9850b3f0,
+	0xc4b6040c,
+	0x00bcbb0f,
+	0x98010c98,
+	0x0f98020d,
+	0x00e7f106,
+	0x6f21f508,
+	0x5e21f501,
+	0x0601f402,
+/* 0x063b: ctx_xfer_post */
+	0xf50712f4,
+/* 0x063f: ctx_xfer_done */
+	0xf5027f21,
+	0xf8056a21,
 	0x00000000,
 	0x00000000,
 	0x00000000,

+ 177 - 177
drivers/gpu/drm/nouveau/nvkm/engine/gr/fuc/gpcgf117.fuc3.h

@@ -314,7 +314,7 @@ uint32_t gf117_grgpc_code[] = {
 	0x03f01200,
 	0x0002d000,
 	0x17f104bd,
-	0x10fe0530,
+	0x10fe0542,
 	0x0007f100,
 	0x0003f007,
 	0xbd0000d0,
@@ -333,188 +333,188 @@ uint32_t gf117_grgpc_code[] = {
 	0xf0860027,
 	0x22cf0123,
 	0x04028000,
-	0x0c30e7f1,
-	0xbd50e3f0,
-	0xbd34bd24,
-/* 0x0421: init_unk_loop */
-	0x6821f444,
-	0xf400f6b0,
-	0xf7f00f0b,
-	0x04f2bb01,
-	0xb6054ffd,
-/* 0x0436: init_unk_next */
-	0x20b60130,
-	0x04e0b601,
-	0xf40126b0,
-/* 0x0442: init_unk_done */
-	0x0380e21b,
-	0x08048007,
-	0x010027f1,
-	0xcf0223f0,
-	0x34bd0022,
-	0xf1082595,
-	0xf0c00007,
-	0x05d00103,
+	0xf10f24b6,
+	0xf0c90007,
+	0x02d00103,
 	0xf104bd00,
-	0xf0c10007,
-	0x05d00103,
-	0x9804bd00,
-	0x0f98000e,
-	0x5021f501,
-	0x002fbb01,
-	0x98003fbb,
-	0x0f98010e,
-	0x5021f502,
-	0x050e9801,
-	0xbb00effd,
-	0x3ebb002e,
-	0x020e9800,
-	0xf5030f98,
-	0x98015021,
-	0xeffd070e,
-	0x002ebb00,
-	0xb6003ebb,
-	0x07f10235,
-	0x03f0d300,
-	0x0003d001,
-	0x25b604bd,
-	0x0635b608,
-	0xb60120b6,
-	0x24b60130,
-	0x0834b608,
-	0xf5022fb9,
-	0xbb02d321,
-	0x07f1003f,
-	0x03f00100,
-	0x0003d002,
-	0x24bd04bd,
-	0xf11f29f0,
-	0xf0080007,
-	0x02d00203,
-/* 0x04f3: main */
-	0xf404bd00,
-	0x28f40031,
-	0x24d7f000,
-	0xf43921f4,
-	0xe4b0f401,
-	0x1e18f404,
-	0xf00181fe,
-	0x20bd0627,
-	0xb60412fd,
-	0x1efd01e4,
-	0x0018fe05,
-	0x05e821f5,
-/* 0x0523: main_not_ctx_xfer */
-	0x94d30ef4,
-	0xf5f010ef,
-	0x7e21f501,
-	0xc60ef403,
-/* 0x0530: ih */
-	0x88fe80f9,
-	0xf980f901,
-	0xf9a0f990,
-	0xf9d0f9b0,
-	0xbdf0f9e0,
-	0x00a7f104,
-	0x00a3f002,
-	0xc400aacf,
-	0x0bf404ab,
-	0x24d7f02c,
-	0x1a00e7f1,
-	0xcf00e3f0,
-	0xf7f100ee,
-	0xf3f01900,
-	0x00ffcf00,
-	0xf00421f4,
-	0x07f101e7,
-	0x03f01d00,
-	0x000ed000,
-/* 0x057e: ih_no_fifo */
+	0xf00c30e7,
+	0x24bd50e3,
+	0x44bd34bd,
+/* 0x0430: init_unk_loop */
+	0xb06821f4,
+	0x0bf400f6,
+	0x01f7f00f,
+	0xfd04f2bb,
+	0x30b6054f,
+/* 0x0445: init_unk_next */
+	0x0120b601,
+	0xb004e0b6,
+	0x1bf40126,
+/* 0x0451: init_unk_done */
+	0x070380e2,
+	0xf1080480,
+	0xf0010027,
+	0x22cf0223,
+	0x9534bd00,
+	0x07f10825,
+	0x03f0c000,
+	0x0005d001,
 	0x07f104bd,
-	0x03f00100,
-	0x000ad000,
-	0xf0fc04bd,
-	0xd0fce0fc,
-	0xa0fcb0fc,
-	0x80fc90fc,
-	0xfc0088fe,
-	0x0032f480,
-/* 0x05a2: hub_barrier_done */
-	0xf7f001f8,
-	0x040e9801,
-	0xb904febb,
-	0xe7f102ff,
-	0xe3f09418,
-	0x9d21f440,
-/* 0x05ba: ctx_redswitch */
-	0xf7f000f8,
-	0x0007f120,
-	0x0103f085,
-	0xbd000fd0,
-	0x08e7f004,
-/* 0x05cc: ctx_redswitch_delay */
-	0xf401e2b6,
-	0xf5f1fd1b,
-	0xf5f10800,
-	0x07f10200,
-	0x03f08500,
-	0x000fd001,
-	0x00f804bd,
-/* 0x05e8: ctx_xfer */
-	0x810007f1,
+	0x03f0c100,
+	0x0005d001,
+	0x0e9804bd,
+	0x010f9800,
+	0x015021f5,
+	0xbb002fbb,
+	0x0e98003f,
+	0x020f9801,
+	0x015021f5,
+	0xfd050e98,
+	0x2ebb00ef,
+	0x003ebb00,
+	0x98020e98,
+	0x21f5030f,
+	0x0e980150,
+	0x00effd07,
+	0xbb002ebb,
+	0x35b6003e,
+	0x0007f102,
+	0x0103f0d3,
+	0xbd0003d0,
+	0x0825b604,
+	0xb60635b6,
+	0x30b60120,
+	0x0824b601,
+	0xb90834b6,
+	0x21f5022f,
+	0x2fbb02d3,
+	0x003fbb00,
+	0x010007f1,
 	0xd00203f0,
-	0x04bd000f,
-	0xf50711f4,
-/* 0x05fb: ctx_xfer_not_load */
-	0xf505ba21,
-	0xbd026a21,
-	0xfc07f124,
-	0x0203f047,
+	0x04bd0003,
+	0x29f024bd,
+	0x0007f11f,
+	0x0203f008,
 	0xbd0002d0,
-	0x012cf004,
-	0xf10320b6,
-	0xf04afc07,
+/* 0x0505: main */
+	0x0031f404,
+	0xf00028f4,
+	0x21f424d7,
+	0xf401f439,
+	0xf404e4b0,
+	0x81fe1e18,
+	0x0627f001,
+	0x12fd20bd,
+	0x01e4b604,
+	0xfe051efd,
+	0x21f50018,
+	0x0ef405fa,
+/* 0x0535: main_not_ctx_xfer */
+	0x10ef94d3,
+	0xf501f5f0,
+	0xf4037e21,
+/* 0x0542: ih */
+	0x80f9c60e,
+	0xf90188fe,
+	0xf990f980,
+	0xf9b0f9a0,
+	0xf9e0f9d0,
+	0xf104bdf0,
+	0xf00200a7,
+	0xaacf00a3,
+	0x04abc400,
+	0xf02c0bf4,
+	0xe7f124d7,
+	0xe3f01a00,
+	0x00eecf00,
+	0x1900f7f1,
+	0xcf00f3f0,
+	0x21f400ff,
+	0x01e7f004,
+	0x1d0007f1,
+	0xd00003f0,
+	0x04bd000e,
+/* 0x0590: ih_no_fifo */
+	0x010007f1,
+	0xd00003f0,
+	0x04bd000a,
+	0xe0fcf0fc,
+	0xb0fcd0fc,
+	0x90fca0fc,
+	0x88fe80fc,
+	0xf480fc00,
+	0x01f80032,
+/* 0x05b4: hub_barrier_done */
+	0x9801f7f0,
+	0xfebb040e,
+	0x02ffb904,
+	0x9418e7f1,
+	0xf440e3f0,
+	0x00f89d21,
+/* 0x05cc: ctx_redswitch */
+	0xf120f7f0,
+	0xf0850007,
+	0x0fd00103,
+	0xf004bd00,
+/* 0x05de: ctx_redswitch_delay */
+	0xe2b608e7,
+	0xfd1bf401,
+	0x0800f5f1,
+	0x0200f5f1,
+	0x850007f1,
+	0xd00103f0,
+	0x04bd000f,
+/* 0x05fa: ctx_xfer */
+	0x07f100f8,
+	0x03f08100,
+	0x000fd002,
+	0x11f404bd,
+	0xcc21f507,
+/* 0x060d: ctx_xfer_not_load */
+	0x6a21f505,
+	0xf124bd02,
+	0xf047fc07,
 	0x02d00203,
 	0xf004bd00,
-	0xa5f001ac,
-	0x00b7f102,
-	0x50b3f000,
-	0xb6040c98,
-	0xbcbb0fc4,
-	0x000c9800,
-	0xf0010d98,
-	0x21f500e7,
-	0xacf0016f,
-	0x00b7f101,
-	0x50b3f040,
-	0xb6040c98,
-	0xbcbb0fc4,
-	0x010c9800,
-	0x98020d98,
-	0xe7f1060f,
-	0x21f50800,
-	0xacf0016f,
-	0x04a5f001,
-	0x3000b7f1,
-	0x9850b3f0,
-	0xc4b6040c,
-	0x00bcbb0f,
-	0x98020c98,
-	0x0f98030d,
-	0x00e7f108,
-	0x6f21f502,
-	0x5e21f501,
-	0x0601f402,
-/* 0x0697: ctx_xfer_post */
-	0xf50712f4,
-/* 0x069b: ctx_xfer_done */
-	0xf5027f21,
-	0xf805a221,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
+	0x20b6012c,
+	0xfc07f103,
+	0x0203f04a,
+	0xbd0002d0,
+	0x01acf004,
+	0xf102a5f0,
+	0xf00000b7,
+	0x0c9850b3,
+	0x0fc4b604,
+	0x9800bcbb,
+	0x0d98000c,
+	0x00e7f001,
+	0x016f21f5,
+	0xf101acf0,
+	0xf04000b7,
+	0x0c9850b3,
+	0x0fc4b604,
+	0x9800bcbb,
+	0x0d98010c,
+	0x060f9802,
+	0x0800e7f1,
+	0x016f21f5,
+	0xf001acf0,
+	0xb7f104a5,
+	0xb3f03000,
+	0x040c9850,
+	0xbb0fc4b6,
+	0x0c9800bc,
+	0x030d9802,
+	0xf1080f98,
+	0xf50200e7,
+	0xf5016f21,
+	0xf4025e21,
+	0x12f40601,
+/* 0x06a9: ctx_xfer_post */
+	0x7f21f507,
+/* 0x06ad: ctx_xfer_done */
+	0xb421f502,
+	0x0000f805,
 	0x00000000,
 	0x00000000,
 	0x00000000,

+ 177 - 177
drivers/gpu/drm/nouveau/nvkm/engine/gr/fuc/gpcgk104.fuc3.h

@@ -314,7 +314,7 @@ uint32_t gk104_grgpc_code[] = {
 	0x03f01200,
 	0x0002d000,
 	0x17f104bd,
-	0x10fe0530,
+	0x10fe0542,
 	0x0007f100,
 	0x0003f007,
 	0xbd0000d0,
@@ -333,188 +333,188 @@ uint32_t gk104_grgpc_code[] = {
 	0xf0860027,
 	0x22cf0123,
 	0x04028000,
-	0x0c30e7f1,
-	0xbd50e3f0,
-	0xbd34bd24,
-/* 0x0421: init_unk_loop */
-	0x6821f444,
-	0xf400f6b0,
-	0xf7f00f0b,
-	0x04f2bb01,
-	0xb6054ffd,
-/* 0x0436: init_unk_next */
-	0x20b60130,
-	0x04e0b601,
-	0xf40126b0,
-/* 0x0442: init_unk_done */
-	0x0380e21b,
-	0x08048007,
-	0x010027f1,
-	0xcf0223f0,
-	0x34bd0022,
-	0xf1082595,
-	0xf0c00007,
-	0x05d00103,
+	0xf10f24b6,
+	0xf0c90007,
+	0x02d00103,
 	0xf104bd00,
-	0xf0c10007,
-	0x05d00103,
-	0x9804bd00,
-	0x0f98000e,
-	0x5021f501,
-	0x002fbb01,
-	0x98003fbb,
-	0x0f98010e,
-	0x5021f502,
-	0x050e9801,
-	0xbb00effd,
-	0x3ebb002e,
-	0x020e9800,
-	0xf5030f98,
-	0x98015021,
-	0xeffd070e,
-	0x002ebb00,
-	0xb6003ebb,
-	0x07f10235,
-	0x03f0d300,
-	0x0003d001,
-	0x25b604bd,
-	0x0635b608,
-	0xb60120b6,
-	0x24b60130,
-	0x0834b608,
-	0xf5022fb9,
-	0xbb02d321,
-	0x07f1003f,
-	0x03f00100,
-	0x0003d002,
-	0x24bd04bd,
-	0xf11f29f0,
-	0xf0080007,
-	0x02d00203,
-/* 0x04f3: main */
-	0xf404bd00,
-	0x28f40031,
-	0x24d7f000,
-	0xf43921f4,
-	0xe4b0f401,
-	0x1e18f404,
-	0xf00181fe,
-	0x20bd0627,
-	0xb60412fd,
-	0x1efd01e4,
-	0x0018fe05,
-	0x05e821f5,
-/* 0x0523: main_not_ctx_xfer */
-	0x94d30ef4,
-	0xf5f010ef,
-	0x7e21f501,
-	0xc60ef403,
-/* 0x0530: ih */
-	0x88fe80f9,
-	0xf980f901,
-	0xf9a0f990,
-	0xf9d0f9b0,
-	0xbdf0f9e0,
-	0x00a7f104,
-	0x00a3f002,
-	0xc400aacf,
-	0x0bf404ab,
-	0x24d7f02c,
-	0x1a00e7f1,
-	0xcf00e3f0,
-	0xf7f100ee,
-	0xf3f01900,
-	0x00ffcf00,
-	0xf00421f4,
-	0x07f101e7,
-	0x03f01d00,
-	0x000ed000,
-/* 0x057e: ih_no_fifo */
+	0xf00c30e7,
+	0x24bd50e3,
+	0x44bd34bd,
+/* 0x0430: init_unk_loop */
+	0xb06821f4,
+	0x0bf400f6,
+	0x01f7f00f,
+	0xfd04f2bb,
+	0x30b6054f,
+/* 0x0445: init_unk_next */
+	0x0120b601,
+	0xb004e0b6,
+	0x1bf40126,
+/* 0x0451: init_unk_done */
+	0x070380e2,
+	0xf1080480,
+	0xf0010027,
+	0x22cf0223,
+	0x9534bd00,
+	0x07f10825,
+	0x03f0c000,
+	0x0005d001,
 	0x07f104bd,
-	0x03f00100,
-	0x000ad000,
-	0xf0fc04bd,
-	0xd0fce0fc,
-	0xa0fcb0fc,
-	0x80fc90fc,
-	0xfc0088fe,
-	0x0032f480,
-/* 0x05a2: hub_barrier_done */
-	0xf7f001f8,
-	0x040e9801,
-	0xb904febb,
-	0xe7f102ff,
-	0xe3f09418,
-	0x9d21f440,
-/* 0x05ba: ctx_redswitch */
-	0xf7f000f8,
-	0x0007f120,
-	0x0103f085,
-	0xbd000fd0,
-	0x08e7f004,
-/* 0x05cc: ctx_redswitch_delay */
-	0xf401e2b6,
-	0xf5f1fd1b,
-	0xf5f10800,
-	0x07f10200,
-	0x03f08500,
-	0x000fd001,
-	0x00f804bd,
-/* 0x05e8: ctx_xfer */
-	0x810007f1,
+	0x03f0c100,
+	0x0005d001,
+	0x0e9804bd,
+	0x010f9800,
+	0x015021f5,
+	0xbb002fbb,
+	0x0e98003f,
+	0x020f9801,
+	0x015021f5,
+	0xfd050e98,
+	0x2ebb00ef,
+	0x003ebb00,
+	0x98020e98,
+	0x21f5030f,
+	0x0e980150,
+	0x00effd07,
+	0xbb002ebb,
+	0x35b6003e,
+	0x0007f102,
+	0x0103f0d3,
+	0xbd0003d0,
+	0x0825b604,
+	0xb60635b6,
+	0x30b60120,
+	0x0824b601,
+	0xb90834b6,
+	0x21f5022f,
+	0x2fbb02d3,
+	0x003fbb00,
+	0x010007f1,
 	0xd00203f0,
-	0x04bd000f,
-	0xf50711f4,
-/* 0x05fb: ctx_xfer_not_load */
-	0xf505ba21,
-	0xbd026a21,
-	0xfc07f124,
-	0x0203f047,
+	0x04bd0003,
+	0x29f024bd,
+	0x0007f11f,
+	0x0203f008,
 	0xbd0002d0,
-	0x012cf004,
-	0xf10320b6,
-	0xf04afc07,
+/* 0x0505: main */
+	0x0031f404,
+	0xf00028f4,
+	0x21f424d7,
+	0xf401f439,
+	0xf404e4b0,
+	0x81fe1e18,
+	0x0627f001,
+	0x12fd20bd,
+	0x01e4b604,
+	0xfe051efd,
+	0x21f50018,
+	0x0ef405fa,
+/* 0x0535: main_not_ctx_xfer */
+	0x10ef94d3,
+	0xf501f5f0,
+	0xf4037e21,
+/* 0x0542: ih */
+	0x80f9c60e,
+	0xf90188fe,
+	0xf990f980,
+	0xf9b0f9a0,
+	0xf9e0f9d0,
+	0xf104bdf0,
+	0xf00200a7,
+	0xaacf00a3,
+	0x04abc400,
+	0xf02c0bf4,
+	0xe7f124d7,
+	0xe3f01a00,
+	0x00eecf00,
+	0x1900f7f1,
+	0xcf00f3f0,
+	0x21f400ff,
+	0x01e7f004,
+	0x1d0007f1,
+	0xd00003f0,
+	0x04bd000e,
+/* 0x0590: ih_no_fifo */
+	0x010007f1,
+	0xd00003f0,
+	0x04bd000a,
+	0xe0fcf0fc,
+	0xb0fcd0fc,
+	0x90fca0fc,
+	0x88fe80fc,
+	0xf480fc00,
+	0x01f80032,
+/* 0x05b4: hub_barrier_done */
+	0x9801f7f0,
+	0xfebb040e,
+	0x02ffb904,
+	0x9418e7f1,
+	0xf440e3f0,
+	0x00f89d21,
+/* 0x05cc: ctx_redswitch */
+	0xf120f7f0,
+	0xf0850007,
+	0x0fd00103,
+	0xf004bd00,
+/* 0x05de: ctx_redswitch_delay */
+	0xe2b608e7,
+	0xfd1bf401,
+	0x0800f5f1,
+	0x0200f5f1,
+	0x850007f1,
+	0xd00103f0,
+	0x04bd000f,
+/* 0x05fa: ctx_xfer */
+	0x07f100f8,
+	0x03f08100,
+	0x000fd002,
+	0x11f404bd,
+	0xcc21f507,
+/* 0x060d: ctx_xfer_not_load */
+	0x6a21f505,
+	0xf124bd02,
+	0xf047fc07,
 	0x02d00203,
 	0xf004bd00,
-	0xa5f001ac,
-	0x00b7f102,
-	0x50b3f000,
-	0xb6040c98,
-	0xbcbb0fc4,
-	0x000c9800,
-	0xf0010d98,
-	0x21f500e7,
-	0xacf0016f,
-	0x00b7f101,
-	0x50b3f040,
-	0xb6040c98,
-	0xbcbb0fc4,
-	0x010c9800,
-	0x98020d98,
-	0xe7f1060f,
-	0x21f50800,
-	0xacf0016f,
-	0x04a5f001,
-	0x3000b7f1,
-	0x9850b3f0,
-	0xc4b6040c,
-	0x00bcbb0f,
-	0x98020c98,
-	0x0f98030d,
-	0x00e7f108,
-	0x6f21f502,
-	0x5e21f501,
-	0x0601f402,
-/* 0x0697: ctx_xfer_post */
-	0xf50712f4,
-/* 0x069b: ctx_xfer_done */
-	0xf5027f21,
-	0xf805a221,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
+	0x20b6012c,
+	0xfc07f103,
+	0x0203f04a,
+	0xbd0002d0,
+	0x01acf004,
+	0xf102a5f0,
+	0xf00000b7,
+	0x0c9850b3,
+	0x0fc4b604,
+	0x9800bcbb,
+	0x0d98000c,
+	0x00e7f001,
+	0x016f21f5,
+	0xf101acf0,
+	0xf04000b7,
+	0x0c9850b3,
+	0x0fc4b604,
+	0x9800bcbb,
+	0x0d98010c,
+	0x060f9802,
+	0x0800e7f1,
+	0x016f21f5,
+	0xf001acf0,
+	0xb7f104a5,
+	0xb3f03000,
+	0x040c9850,
+	0xbb0fc4b6,
+	0x0c9800bc,
+	0x030d9802,
+	0xf1080f98,
+	0xf50200e7,
+	0xf5016f21,
+	0xf4025e21,
+	0x12f40601,
+/* 0x06a9: ctx_xfer_post */
+	0x7f21f507,
+/* 0x06ad: ctx_xfer_done */
+	0xb421f502,
+	0x0000f805,
 	0x00000000,
 	0x00000000,
 	0x00000000,

+ 177 - 177
drivers/gpu/drm/nouveau/nvkm/engine/gr/fuc/gpcgk110.fuc3.h

@@ -314,7 +314,7 @@ uint32_t gk110_grgpc_code[] = {
 	0x03f01200,
 	0x0002d000,
 	0x17f104bd,
-	0x10fe0530,
+	0x10fe0542,
 	0x0007f100,
 	0x0003f007,
 	0xbd0000d0,
@@ -333,188 +333,188 @@ uint32_t gk110_grgpc_code[] = {
 	0xf0860027,
 	0x22cf0123,
 	0x04028000,
-	0x0c30e7f1,
-	0xbd50e3f0,
-	0xbd34bd24,
-/* 0x0421: init_unk_loop */
-	0x6821f444,
-	0xf400f6b0,
-	0xf7f00f0b,
-	0x04f2bb01,
-	0xb6054ffd,
-/* 0x0436: init_unk_next */
-	0x20b60130,
-	0x04e0b601,
-	0xf40226b0,
-/* 0x0442: init_unk_done */
-	0x0380e21b,
-	0x08048007,
-	0x010027f1,
-	0xcf0223f0,
-	0x34bd0022,
-	0xf1082595,
-	0xf0c00007,
-	0x05d00103,
+	0xf10f24b6,
+	0xf0c90007,
+	0x02d00103,
 	0xf104bd00,
-	0xf0c10007,
-	0x05d00103,
-	0x9804bd00,
-	0x0f98000e,
-	0x5021f501,
-	0x002fbb01,
-	0x98003fbb,
-	0x0f98010e,
-	0x5021f502,
-	0x050e9801,
-	0xbb00effd,
-	0x3ebb002e,
-	0x020e9800,
-	0xf5030f98,
-	0x98015021,
-	0xeffd070e,
-	0x002ebb00,
-	0xb6003ebb,
-	0x07f10235,
-	0x03f0d300,
-	0x0003d001,
-	0x25b604bd,
-	0x0635b608,
-	0xb60120b6,
-	0x24b60130,
-	0x0834b608,
-	0xf5022fb9,
-	0xbb02d321,
-	0x07f1003f,
-	0x03f00100,
-	0x0003d002,
-	0x24bd04bd,
-	0xf11f29f0,
-	0xf0300007,
-	0x02d00203,
-/* 0x04f3: main */
-	0xf404bd00,
-	0x28f40031,
-	0x24d7f000,
-	0xf43921f4,
-	0xe4b0f401,
-	0x1e18f404,
-	0xf00181fe,
-	0x20bd0627,
-	0xb60412fd,
-	0x1efd01e4,
-	0x0018fe05,
-	0x05e821f5,
-/* 0x0523: main_not_ctx_xfer */
-	0x94d30ef4,
-	0xf5f010ef,
-	0x7e21f501,
-	0xc60ef403,
-/* 0x0530: ih */
-	0x88fe80f9,
-	0xf980f901,
-	0xf9a0f990,
-	0xf9d0f9b0,
-	0xbdf0f9e0,
-	0x00a7f104,
-	0x00a3f002,
-	0xc400aacf,
-	0x0bf404ab,
-	0x24d7f02c,
-	0x1a00e7f1,
-	0xcf00e3f0,
-	0xf7f100ee,
-	0xf3f01900,
-	0x00ffcf00,
-	0xf00421f4,
-	0x07f101e7,
-	0x03f01d00,
-	0x000ed000,
-/* 0x057e: ih_no_fifo */
+	0xf00c30e7,
+	0x24bd50e3,
+	0x44bd34bd,
+/* 0x0430: init_unk_loop */
+	0xb06821f4,
+	0x0bf400f6,
+	0x01f7f00f,
+	0xfd04f2bb,
+	0x30b6054f,
+/* 0x0445: init_unk_next */
+	0x0120b601,
+	0xb004e0b6,
+	0x1bf40226,
+/* 0x0451: init_unk_done */
+	0x070380e2,
+	0xf1080480,
+	0xf0010027,
+	0x22cf0223,
+	0x9534bd00,
+	0x07f10825,
+	0x03f0c000,
+	0x0005d001,
 	0x07f104bd,
-	0x03f00100,
-	0x000ad000,
-	0xf0fc04bd,
-	0xd0fce0fc,
-	0xa0fcb0fc,
-	0x80fc90fc,
-	0xfc0088fe,
-	0x0032f480,
-/* 0x05a2: hub_barrier_done */
-	0xf7f001f8,
-	0x040e9801,
-	0xb904febb,
-	0xe7f102ff,
-	0xe3f09418,
-	0x9d21f440,
-/* 0x05ba: ctx_redswitch */
-	0xf7f000f8,
-	0x0007f120,
-	0x0103f085,
-	0xbd000fd0,
-	0x08e7f004,
-/* 0x05cc: ctx_redswitch_delay */
-	0xf401e2b6,
-	0xf5f1fd1b,
-	0xf5f10800,
-	0x07f10200,
-	0x03f08500,
-	0x000fd001,
-	0x00f804bd,
-/* 0x05e8: ctx_xfer */
-	0x810007f1,
+	0x03f0c100,
+	0x0005d001,
+	0x0e9804bd,
+	0x010f9800,
+	0x015021f5,
+	0xbb002fbb,
+	0x0e98003f,
+	0x020f9801,
+	0x015021f5,
+	0xfd050e98,
+	0x2ebb00ef,
+	0x003ebb00,
+	0x98020e98,
+	0x21f5030f,
+	0x0e980150,
+	0x00effd07,
+	0xbb002ebb,
+	0x35b6003e,
+	0x0007f102,
+	0x0103f0d3,
+	0xbd0003d0,
+	0x0825b604,
+	0xb60635b6,
+	0x30b60120,
+	0x0824b601,
+	0xb90834b6,
+	0x21f5022f,
+	0x2fbb02d3,
+	0x003fbb00,
+	0x010007f1,
 	0xd00203f0,
-	0x04bd000f,
-	0xf50711f4,
-/* 0x05fb: ctx_xfer_not_load */
-	0xf505ba21,
-	0xbd026a21,
-	0xfc07f124,
-	0x0203f047,
+	0x04bd0003,
+	0x29f024bd,
+	0x0007f11f,
+	0x0203f030,
 	0xbd0002d0,
-	0x012cf004,
-	0xf10320b6,
-	0xf04afc07,
+/* 0x0505: main */
+	0x0031f404,
+	0xf00028f4,
+	0x21f424d7,
+	0xf401f439,
+	0xf404e4b0,
+	0x81fe1e18,
+	0x0627f001,
+	0x12fd20bd,
+	0x01e4b604,
+	0xfe051efd,
+	0x21f50018,
+	0x0ef405fa,
+/* 0x0535: main_not_ctx_xfer */
+	0x10ef94d3,
+	0xf501f5f0,
+	0xf4037e21,
+/* 0x0542: ih */
+	0x80f9c60e,
+	0xf90188fe,
+	0xf990f980,
+	0xf9b0f9a0,
+	0xf9e0f9d0,
+	0xf104bdf0,
+	0xf00200a7,
+	0xaacf00a3,
+	0x04abc400,
+	0xf02c0bf4,
+	0xe7f124d7,
+	0xe3f01a00,
+	0x00eecf00,
+	0x1900f7f1,
+	0xcf00f3f0,
+	0x21f400ff,
+	0x01e7f004,
+	0x1d0007f1,
+	0xd00003f0,
+	0x04bd000e,
+/* 0x0590: ih_no_fifo */
+	0x010007f1,
+	0xd00003f0,
+	0x04bd000a,
+	0xe0fcf0fc,
+	0xb0fcd0fc,
+	0x90fca0fc,
+	0x88fe80fc,
+	0xf480fc00,
+	0x01f80032,
+/* 0x05b4: hub_barrier_done */
+	0x9801f7f0,
+	0xfebb040e,
+	0x02ffb904,
+	0x9418e7f1,
+	0xf440e3f0,
+	0x00f89d21,
+/* 0x05cc: ctx_redswitch */
+	0xf120f7f0,
+	0xf0850007,
+	0x0fd00103,
+	0xf004bd00,
+/* 0x05de: ctx_redswitch_delay */
+	0xe2b608e7,
+	0xfd1bf401,
+	0x0800f5f1,
+	0x0200f5f1,
+	0x850007f1,
+	0xd00103f0,
+	0x04bd000f,
+/* 0x05fa: ctx_xfer */
+	0x07f100f8,
+	0x03f08100,
+	0x000fd002,
+	0x11f404bd,
+	0xcc21f507,
+/* 0x060d: ctx_xfer_not_load */
+	0x6a21f505,
+	0xf124bd02,
+	0xf047fc07,
 	0x02d00203,
 	0xf004bd00,
-	0xa5f001ac,
-	0x00b7f102,
-	0x50b3f000,
-	0xb6040c98,
-	0xbcbb0fc4,
-	0x000c9800,
-	0xf0010d98,
-	0x21f500e7,
-	0xacf0016f,
-	0x00b7f101,
-	0x50b3f040,
-	0xb6040c98,
-	0xbcbb0fc4,
-	0x010c9800,
-	0x98020d98,
-	0xe7f1060f,
-	0x21f50800,
-	0xacf0016f,
-	0x04a5f001,
-	0x3000b7f1,
-	0x9850b3f0,
-	0xc4b6040c,
-	0x00bcbb0f,
-	0x98020c98,
-	0x0f98030d,
-	0x00e7f108,
-	0x6f21f502,
-	0x5e21f501,
-	0x0601f402,
-/* 0x0697: ctx_xfer_post */
-	0xf50712f4,
-/* 0x069b: ctx_xfer_done */
-	0xf5027f21,
-	0xf805a221,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
+	0x20b6012c,
+	0xfc07f103,
+	0x0203f04a,
+	0xbd0002d0,
+	0x01acf004,
+	0xf102a5f0,
+	0xf00000b7,
+	0x0c9850b3,
+	0x0fc4b604,
+	0x9800bcbb,
+	0x0d98000c,
+	0x00e7f001,
+	0x016f21f5,
+	0xf101acf0,
+	0xf04000b7,
+	0x0c9850b3,
+	0x0fc4b604,
+	0x9800bcbb,
+	0x0d98010c,
+	0x060f9802,
+	0x0800e7f1,
+	0x016f21f5,
+	0xf001acf0,
+	0xb7f104a5,
+	0xb3f03000,
+	0x040c9850,
+	0xbb0fc4b6,
+	0x0c9800bc,
+	0x030d9802,
+	0xf1080f98,
+	0xf50200e7,
+	0xf5016f21,
+	0xf4025e21,
+	0x12f40601,
+/* 0x06a9: ctx_xfer_post */
+	0x7f21f507,
+/* 0x06ad: ctx_xfer_done */
+	0xb421f502,
+	0x0000f805,
 	0x00000000,
 	0x00000000,
 	0x00000000,

+ 115 - 115
drivers/gpu/drm/nouveau/nvkm/engine/gr/fuc/gpcgk208.fuc5.h

@@ -276,7 +276,7 @@ uint32_t gk208_grgpc_code[] = {
 	0x02020014,
 	0xf6120040,
 	0x04bd0002,
-	0xfe047241,
+	0xfe048141,
 	0x00400010,
 	0x0000f607,
 	0x040204bd,
@@ -291,20 +291,23 @@ uint32_t gk208_grgpc_code[] = {
 	0x820603b5,
 	0xcf018600,
 	0x02b50022,
+	0x0f24b604,
+	0x01c90080,
+	0xbd0002f6,
 	0x0c308e04,
 	0xbd24bd50,
-/* 0x0377: init_unk_loop */
+/* 0x0383: init_unk_loop */
 	0x7e44bd34,
 	0xb0000065,
 	0x0bf400f6,
 	0xbb010f0e,
 	0x4ffd04f2,
 	0x0130b605,
-/* 0x038c: init_unk_next */
+/* 0x0398: init_unk_next */
 	0xb60120b6,
 	0x26b004e0,
 	0xe21bf401,
-/* 0x0398: init_unk_done */
+/* 0x03a4: init_unk_done */
 	0xb50703b5,
 	0x00820804,
 	0x22cf0201,
@@ -338,121 +341,118 @@ uint32_t gk208_grgpc_code[] = {
 	0xb60824b6,
 	0x2fb20834,
 	0x0002687e,
-	0x80003fbb,
-	0xf6020100,
-	0x04bd0003,
-	0x29f024bd,
-	0x3000801f,
-	0x0002f602,
-/* 0x0436: main */
-	0x31f404bd,
-	0x0028f400,
-	0x377e240d,
-	0x01f40000,
-	0x04e4b0f4,
-	0xfe1d18f4,
-	0x06020181,
-	0x12fd20bd,
-	0x01e4b604,
-	0xfe051efd,
-	0x097e0018,
-	0x0ef40005,
-/* 0x0465: main_not_ctx_xfer */
-	0x10ef94d4,
-	0x7e01f5f0,
-	0xf40002f8,
-/* 0x0472: ih */
-	0x80f9c70e,
-	0xf90188fe,
-	0xf990f980,
-	0xf9b0f9a0,
-	0xf9e0f9d0,
-	0x4a04bdf0,
-	0xaacf0200,
-	0x04abc400,
-	0x0d1f0bf4,
-	0x1a004e24,
-	0x4f00eecf,
-	0xffcf1900,
-	0x00047e00,
-	0x40010e00,
-	0x0ef61d00,
-/* 0x04af: ih_no_fifo */
-	0x4004bd00,
-	0x0af60100,
-	0xfc04bd00,
-	0xfce0fcf0,
-	0xfcb0fcd0,
-	0xfc90fca0,
-	0x0088fe80,
-	0x32f480fc,
-/* 0x04cf: hub_barrier_done */
-	0x0f01f800,
-	0x040e9801,
-	0xb204febb,
-	0x94188eff,
-	0x008f7e40,
-/* 0x04e3: ctx_redswitch */
-	0x0f00f800,
-	0x85008020,
+	0xbb002fbb,
+	0x0080003f,
+	0x03f60201,
+	0xbd04bd00,
+	0x1f29f024,
+	0x02300080,
+	0xbd0002f6,
+/* 0x0445: main */
+	0x0031f404,
+	0x0d0028f4,
+	0x00377e24,
+	0xf401f400,
+	0xf404e4b0,
+	0x81fe1d18,
+	0xbd060201,
+	0x0412fd20,
+	0xfd01e4b6,
+	0x18fe051e,
+	0x05187e00,
+	0xd40ef400,
+/* 0x0474: main_not_ctx_xfer */
+	0xf010ef94,
+	0xf87e01f5,
+	0x0ef40002,
+/* 0x0481: ih */
+	0xfe80f9c7,
+	0x80f90188,
+	0xa0f990f9,
+	0xd0f9b0f9,
+	0xf0f9e0f9,
+	0x004a04bd,
+	0x00aacf02,
+	0xf404abc4,
+	0x240d1f0b,
+	0xcf1a004e,
+	0x004f00ee,
+	0x00ffcf19,
+	0x0000047e,
+	0x0040010e,
+	0x000ef61d,
+/* 0x04be: ih_no_fifo */
+	0x004004bd,
+	0x000af601,
+	0xf0fc04bd,
+	0xd0fce0fc,
+	0xa0fcb0fc,
+	0x80fc90fc,
+	0xfc0088fe,
+	0x0032f480,
+/* 0x04de: hub_barrier_done */
+	0x010f01f8,
+	0xbb040e98,
+	0xffb204fe,
+	0x4094188e,
+	0x00008f7e,
+/* 0x04f2: ctx_redswitch */
+	0x200f00f8,
+	0x01850080,
+	0xbd000ff6,
+/* 0x04ff: ctx_redswitch_delay */
+	0xb6080e04,
+	0x1bf401e2,
+	0x00f5f1fd,
+	0x00f5f108,
+	0x85008002,
 	0x000ff601,
-	0x080e04bd,
-/* 0x04f0: ctx_redswitch_delay */
-	0xf401e2b6,
-	0xf5f1fd1b,
-	0xf5f10800,
-	0x00800200,
-	0x0ff60185,
-	0xf804bd00,
-/* 0x0509: ctx_xfer */
-	0x81008000,
-	0x000ff602,
-	0x11f404bd,
-	0x04e37e07,
-/* 0x0519: ctx_xfer_not_load */
-	0x02167e00,
-	0x8024bd00,
-	0xf60247fc,
-	0x04bd0002,
-	0xb6012cf0,
-	0xfc800320,
-	0x02f6024a,
+	0x00f804bd,
+/* 0x0518: ctx_xfer */
+	0x02810080,
+	0xbd000ff6,
+	0x0711f404,
+	0x0004f27e,
+/* 0x0528: ctx_xfer_not_load */
+	0x0002167e,
+	0xfc8024bd,
+	0x02f60247,
 	0xf004bd00,
-	0xa5f001ac,
-	0x00008b02,
-	0x040c9850,
-	0xbb0fc4b6,
-	0x0c9800bc,
-	0x010d9800,
-	0x3d7e000e,
-	0xacf00001,
-	0x40008b01,
-	0x040c9850,
-	0xbb0fc4b6,
-	0x0c9800bc,
-	0x020d9801,
-	0x4e060f98,
-	0x3d7e0800,
-	0xacf00001,
-	0x04a5f001,
-	0x5030008b,
+	0x20b6012c,
+	0x4afc8003,
+	0x0002f602,
+	0xacf004bd,
+	0x02a5f001,
+	0x5000008b,
 	0xb6040c98,
 	0xbcbb0fc4,
-	0x020c9800,
-	0x98030d98,
-	0x004e080f,
-	0x013d7e02,
-	0x020a7e00,
-	0x0601f400,
-/* 0x05a3: ctx_xfer_post */
-	0x7e0712f4,
-/* 0x05a7: ctx_xfer_done */
-	0x7e000227,
-	0xf80004cf,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
+	0x000c9800,
+	0x0e010d98,
+	0x013d7e00,
+	0x01acf000,
+	0x5040008b,
+	0xb6040c98,
+	0xbcbb0fc4,
+	0x010c9800,
+	0x98020d98,
+	0x004e060f,
+	0x013d7e08,
+	0x01acf000,
+	0x8b04a5f0,
+	0x98503000,
+	0xc4b6040c,
+	0x00bcbb0f,
+	0x98020c98,
+	0x0f98030d,
+	0x02004e08,
+	0x00013d7e,
+	0x00020a7e,
+	0xf40601f4,
+/* 0x05b2: ctx_xfer_post */
+	0x277e0712,
+/* 0x05b6: ctx_xfer_done */
+	0xde7e0002,
+	0x00f80004,
 	0x00000000,
 	0x00000000,
 	0x00000000,

+ 1 - 1
drivers/gpu/drm/nouveau/nvkm/engine/gr/fuc/gpcgm107.fuc5

@@ -24,7 +24,7 @@
 
 #define NV_PGRAPH_GPCX_UNK__SIZE                                     0x00000002
 
-#define CHIPSET GK208
+#define CHIPSET GM107
 #include "macros.fuc"
 
 .section #gm107_grgpc_data

+ 306 - 174
drivers/gpu/drm/nouveau/nvkm/engine/gr/fuc/gpcgm107.fuc5.h

@@ -41,7 +41,7 @@ uint32_t gm107_grgpc_data[] = {
 };
 
 uint32_t gm107_grgpc_code[] = {
-	0x03140ef5,
+	0x03410ef5,
 /* 0x0004: queue_put */
 	0x9800d898,
 	0x86f001d9,
@@ -268,187 +268,319 @@ uint32_t gm107_grgpc_code[] = {
 	0x409c1c8e,
 	0x00008f7e,
 	0x00f8e0fc,
-/* 0x0314: init */
-	0x004104bd,
-	0x0011cf42,
-	0x010911e7,
-	0xfe0814b6,
-	0x02020014,
-	0xf6120040,
-	0x04bd0002,
-	0xfe047241,
-	0x00400010,
-	0x0000f607,
-	0x040204bd,
-	0xf6040040,
-	0x04bd0002,
-	0x821031f4,
-	0xcf018200,
-	0x01030022,
-	0xbb1f24f0,
-	0x32b60432,
-	0x0502b501,
-	0x820603b5,
-	0xcf018600,
-	0x02b50022,
-	0x0c308e04,
-	0xbd24bd50,
-/* 0x0377: init_unk_loop */
-	0x7e44bd34,
-	0xb0000065,
-	0x0bf400f6,
-	0xbb010f0e,
-	0x4ffd04f2,
-	0x0130b605,
-/* 0x038c: init_unk_next */
-	0xb60120b6,
-	0x26b004e0,
-	0xe21bf402,
-/* 0x0398: init_unk_done */
-	0xb50703b5,
-	0x00820804,
-	0x22cf0201,
-	0x9534bd00,
-	0x00800825,
-	0x05f601c0,
-	0x8004bd00,
-	0xf601c100,
+/* 0x0314: tpc_strand_wait */
+	0x94bd90f9,
+	0x800a99f0,
+	0xf6023700,
+	0x04bd0009,
+/* 0x0324: tpc_strand_busy */
+	0x033f0089,
+	0xb30099cf,
+	0xbdf90094,
+	0x0a99f094,
+	0x02170080,
+	0xbd0009f6,
+	0xf890fc04,
+/* 0x0341: init */
+	0x4104bd00,
+	0x11cf4200,
+	0x0911e700,
+	0x0814b601,
+	0x020014fe,
+	0x12004002,
+	0xbd0002f6,
+	0x05b04104,
+	0x400010fe,
+	0x00f60700,
+	0x0204bd00,
+	0x04004004,
+	0xbd0002f6,
+	0x1031f404,
+	0x01820082,
+	0x030022cf,
+	0x1f24f001,
+	0xb60432bb,
+	0x02b50132,
+	0x0603b505,
+	0x01860082,
+	0xb50022cf,
+	0x24b60402,
+	0xc900800f,
+	0x0002f601,
+	0x308e04bd,
+	0x24bd500c,
+	0x44bd34bd,
+/* 0x03b0: init_unk_loop */
+	0x0000657e,
+	0xf400f6b0,
+	0x010f0e0b,
+	0xfd04f2bb,
+	0x30b6054f,
+/* 0x03c5: init_unk_next */
+	0x0120b601,
+	0xb004e0b6,
+	0x1bf40226,
+/* 0x03d1: init_unk_done */
+	0x0703b5e2,
+	0x820804b5,
+	0xcf020100,
+	0x34bd0022,
+	0x80082595,
+	0xf601c000,
 	0x04bd0005,
-	0x98000e98,
-	0x207e010f,
-	0x2fbb0001,
+	0x01c10080,
+	0xbd0005f6,
+	0x000e9804,
+	0x7e010f98,
+	0xbb000120,
+	0x3fbb002f,
+	0x010e9800,
+	0x7e020f98,
+	0x98000120,
+	0xeffd050e,
+	0x002ebb00,
+	0x98003ebb,
+	0x0f98020e,
+	0x01207e03,
+	0x070e9800,
+	0xbb00effd,
+	0x3ebb002e,
+	0x0235b600,
+	0x01d30080,
+	0xbd0003f6,
+	0x0825b604,
+	0xb60635b6,
+	0x30b60120,
+	0x0824b601,
+	0xb20834b6,
+	0x02687e2f,
+	0x002fbb00,
+	0x0f003fbb,
+	0x8effb23f,
+	0xf0501d60,
+	0x8f7e01e5,
+	0x0c0f0000,
+	0xa88effb2,
+	0xe5f0501d,
+	0x008f7e01,
+	0x03147e00,
+	0xb23f0f00,
+	0x1d608eff,
+	0x01e5f050,
+	0x00008f7e,
+	0xffb2000f,
+	0x501d9c8e,
+	0x7e01e5f0,
+	0x0f00008f,
+	0x03147e01,
+	0x8effb200,
+	0xf0501da8,
+	0x8f7e01e5,
+	0xff0f0000,
+	0x988effb2,
+	0xe5f0501d,
+	0x008f7e01,
+	0xb2020f00,
+	0x1da88eff,
+	0x01e5f050,
+	0x00008f7e,
+	0x0003147e,
+	0x85050498,
+	0x98504000,
+	0x64b60406,
+	0x0056bb0f,
+/* 0x04e0: tpc_strand_init_tpc_loop */
+	0x05705eb8,
+	0x00657e00,
+	0xbdf6b200,
+/* 0x04ed: tpc_strand_init_idx_loop */
+	0x605eb874,
+	0x7fb20005,
+	0x00008f7e,
+	0x05885eb8,
+	0x082f9500,
+	0x00008f7e,
+	0x058c5eb8,
+	0x082f9500,
+	0x00008f7e,
+	0x05905eb8,
+	0x00657e00,
+	0x06f5b600,
+	0xb601f0b6,
+	0x2fbb08f4,
 	0x003fbb00,
-	0x98010e98,
-	0x207e020f,
-	0x0e980001,
-	0x00effd05,
-	0xbb002ebb,
-	0x0e98003e,
-	0x030f9802,
-	0x0001207e,
-	0xfd070e98,
-	0x2ebb00ef,
-	0x003ebb00,
-	0x800235b6,
-	0xf601d300,
-	0x04bd0003,
-	0xb60825b6,
-	0x20b60635,
-	0x0130b601,
-	0xb60824b6,
-	0x2fb20834,
-	0x0002687e,
-	0x80003fbb,
-	0xf6020100,
-	0x04bd0003,
-	0x29f024bd,
-	0x3000801f,
-	0x0002f602,
-/* 0x0436: main */
-	0x31f404bd,
-	0x0028f400,
-	0x377e240d,
-	0x01f40000,
-	0x04e4b0f4,
-	0xfe1d18f4,
-	0x06020181,
-	0x12fd20bd,
-	0x01e4b604,
-	0xfe051efd,
-	0x097e0018,
-	0x0ef40005,
-/* 0x0465: main_not_ctx_xfer */
-	0x10ef94d4,
-	0x7e01f5f0,
-	0xf40002f8,
-/* 0x0472: ih */
-	0x80f9c70e,
-	0xf90188fe,
-	0xf990f980,
-	0xf9b0f9a0,
-	0xf9e0f9d0,
-	0x4a04bdf0,
-	0xaacf0200,
-	0x04abc400,
-	0x0d1f0bf4,
-	0x1a004e24,
-	0x4f00eecf,
-	0xffcf1900,
-	0x00047e00,
-	0x40010e00,
-	0x0ef61d00,
-/* 0x04af: ih_no_fifo */
-	0x4004bd00,
-	0x0af60100,
-	0xfc04bd00,
-	0xfce0fcf0,
-	0xfcb0fcd0,
-	0xfc90fca0,
-	0x0088fe80,
-	0x32f480fc,
-/* 0x04cf: hub_barrier_done */
-	0x0f01f800,
-	0x040e9801,
-	0xb204febb,
-	0x94188eff,
-	0x008f7e40,
-/* 0x04e3: ctx_redswitch */
-	0x0f00f800,
-	0x85008020,
-	0x000ff601,
-	0x080e04bd,
-/* 0x04f0: ctx_redswitch_delay */
-	0xf401e2b6,
-	0xf5f1fd1b,
-	0xf5f10800,
-	0x00800200,
-	0x0ff60185,
-	0xf804bd00,
-/* 0x0509: ctx_xfer */
-	0x81008000,
-	0x000ff602,
-	0x11f404bd,
-	0x04e37e07,
-/* 0x0519: ctx_xfer_not_load */
-	0x02167e00,
-	0x8024bd00,
-	0xf60247fc,
+	0xb60170b6,
+	0x1bf40162,
+	0x0050b7bf,
+	0x0142b608,
+	0x0fa81bf4,
+	0x8effb23f,
+	0xf0501d60,
+	0x8f7e01e5,
+	0x0d0f0000,
+	0xa88effb2,
+	0xe5f0501d,
+	0x008f7e01,
+	0x03147e00,
+	0x01008000,
+	0x0003f602,
+	0x24bd04bd,
+	0x801f29f0,
+	0xf6023000,
 	0x04bd0002,
-	0xb6012cf0,
-	0xfc800320,
-	0x02f6024a,
+/* 0x0574: main */
+	0xf40031f4,
+	0x240d0028,
+	0x0000377e,
+	0xb0f401f4,
+	0x18f404e4,
+	0x0181fe1d,
+	0x20bd0602,
+	0xb60412fd,
+	0x1efd01e4,
+	0x0018fe05,
+	0x0006477e,
+/* 0x05a3: main_not_ctx_xfer */
+	0x94d40ef4,
+	0xf5f010ef,
+	0x02f87e01,
+	0xc70ef400,
+/* 0x05b0: ih */
+	0x88fe80f9,
+	0xf980f901,
+	0xf9a0f990,
+	0xf9d0f9b0,
+	0xbdf0f9e0,
+	0x02004a04,
+	0xc400aacf,
+	0x0bf404ab,
+	0x4e240d1f,
+	0xeecf1a00,
+	0x19004f00,
+	0x7e00ffcf,
+	0x0e000004,
+	0x1d004001,
+	0xbd000ef6,
+/* 0x05ed: ih_no_fifo */
+	0x01004004,
+	0xbd000af6,
+	0xfcf0fc04,
+	0xfcd0fce0,
+	0xfca0fcb0,
+	0xfe80fc90,
+	0x80fc0088,
+	0xf80032f4,
+/* 0x060d: hub_barrier_done */
+	0x98010f01,
+	0xfebb040e,
+	0x8effb204,
+	0x7e409418,
+	0xf800008f,
+/* 0x0621: ctx_redswitch */
+	0x80200f00,
+	0xf6018500,
+	0x04bd000f,
+/* 0x062e: ctx_redswitch_delay */
+	0xe2b6080e,
+	0xfd1bf401,
+	0x0800f5f1,
+	0x0200f5f1,
+	0x01850080,
+	0xbd000ff6,
+/* 0x0647: ctx_xfer */
+	0x8000f804,
+	0xf6028100,
+	0x04bd000f,
+	0xc48effb2,
+	0xe5f0501d,
+	0x008f7e01,
+	0x0711f400,
+	0x0006217e,
+/* 0x0664: ctx_xfer_not_load */
+	0x0002167e,
+	0xfc8024bd,
+	0x02f60247,
 	0xf004bd00,
+	0x20b6012c,
+	0x4afc8003,
+	0x0002f602,
+	0x0c0f04bd,
+	0xa88effb2,
+	0xe5f0501d,
+	0x008f7e01,
+	0x03147e00,
+	0xb23f0f00,
+	0x1d608eff,
+	0x01e5f050,
+	0x00008f7e,
+	0xffb2000f,
+	0x501d9c8e,
+	0x7e01e5f0,
+	0x0f00008f,
+	0x03147e01,
+	0x01fcf000,
+	0xb203f0b6,
+	0x1da88eff,
+	0x01e5f050,
+	0x00008f7e,
+	0xf001acf0,
+	0x008b02a5,
+	0x0c985000,
+	0x0fc4b604,
+	0x9800bcbb,
+	0x0d98000c,
+	0x7e000e01,
+	0xf000013d,
+	0x008b01ac,
+	0x0c985040,
+	0x0fc4b604,
+	0x9800bcbb,
+	0x0d98010c,
+	0x060f9802,
+	0x7e08004e,
+	0xf000013d,
 	0xa5f001ac,
-	0x00008b02,
+	0x30008b04,
 	0x040c9850,
 	0xbb0fc4b6,
 	0x0c9800bc,
-	0x010d9800,
-	0x3d7e000e,
-	0xacf00001,
-	0x40008b01,
-	0x040c9850,
-	0xbb0fc4b6,
-	0x0c9800bc,
-	0x020d9801,
-	0x4e060f98,
-	0x3d7e0800,
-	0xacf00001,
-	0x04a5f001,
-	0x5030008b,
-	0xb6040c98,
-	0xbcbb0fc4,
-	0x020c9800,
-	0x98030d98,
-	0x004e080f,
-	0x013d7e02,
-	0x020a7e00,
-	0x0601f400,
-/* 0x05a3: ctx_xfer_post */
-	0x7e0712f4,
-/* 0x05a7: ctx_xfer_done */
-	0x7e000227,
-	0xf80004cf,
+	0x030d9802,
+	0x4e080f98,
+	0x3d7e0200,
+	0x0a7e0001,
+	0x147e0002,
+	0x01f40003,
+	0x1a12f406,
+/* 0x073c: ctx_xfer_post */
+	0x0002277e,
+	0xffb20d0f,
+	0x501da88e,
+	0x7e01e5f0,
+	0x7e00008f,
+/* 0x0753: ctx_xfer_done */
+	0x7e000314,
+	0xf800060d,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
 	0x00000000,
 	0x00000000,
 	0x00000000,

+ 32 - 0
drivers/gpu/drm/nouveau/nvkm/engine/gr/fuc/macros.fuc

@@ -29,6 +29,7 @@
 #define GK100 0xe0
 #define GK110 0xf0
 #define GK208 0x108
+#define GM107 0x117
 
 #define NV_PGRAPH_TRAPPED_ADDR                                         0x400704
 #define NV_PGRAPH_TRAPPED_DATA_LO                                      0x400708
@@ -79,7 +80,9 @@
 #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_BASE                                       0x409724
 #define NV_PGRAPH_FECS_MMIO_CTRL                                       0x409728
+#define NV_PGRAPH_FECS_MMIO_CTRL_BASE_ENABLE                         0x00000001
 #define NV_PGRAPH_FECS_MMIO_RDVAL                                      0x40972c
 #define NV_PGRAPH_FECS_MMIO_WRVAL                                      0x409730
 #define NV_PGRAPH_FECS_MMCTX_LOAD_COUNT                                0x40974c
@@ -147,6 +150,11 @@
 #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_MMIO_BASE                                 0x41a724
+#define NV_PGRAPH_GPCX_GPCCS_MMIO_CTRL                                 0x41a728
+#define NV_PGRAPH_GPCX_GPCCS_MMIO_CTRL_BASE_ENABLE                   0x00000001
+#define NV_PGRAPH_GPCX_GPCCS_MMIO_RDVAL                                0x41a72c
+#define NV_PGRAPH_GPCX_GPCCS_MMIO_WRVAL                                0x41a730
 #define NV_PGRAPH_GPCX_GPCCS_MMCTX_LOAD_COUNT                          0x41a74c
 #if CHIPSET < GK110
 #define NV_PGRAPH_GPCX_GPCCS_CC_SCRATCH_VAL(n)              ((n) * 4 + 0x41a800)
@@ -164,6 +172,29 @@
 #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 NV_PGRAPH_GPCX_GPCCS_TPC_STATUS                                0x41acfc
+
+#define NV_PGRAPH_GPC0_TPC0                                            0x504000
+#define NV_PGRAPH_GPC0_TPC0__SIZE                                      0x000800
+
+#define NV_PGRAPH_GPC0_TPCX_STRAND_INDEX                               0x501d60
+#define NV_PGRAPH_GPC0_TPCX_STRAND_INDEX_ALL                         0x0000003f
+#define NV_PGRAPH_GPC0_TPCX_STRAND_DATA                                0x501d98
+#define NV_PGRAPH_GPC0_TPCX_STRAND_SELECT                              0x501d9c
+#define NV_PGRAPH_GPC0_TPCX_STRAND_CMD                                 0x501da8
+#define NV_PGRAPH_GPC0_TPCX_STRAND_CMD_SEEK                          0x00000001
+#define NV_PGRAPH_GPC0_TPCX_STRAND_CMD_GET_INFO                      0x00000002
+#define NV_PGRAPH_GPC0_TPCX_STRAND_CMD_SAVE                          0x00000003
+#define NV_PGRAPH_GPC0_TPCX_STRAND_CMD_LOAD                          0x00000004
+#define NV_PGRAPH_GPC0_TPCX_STRAND_CMD_ENABLE                        0x0000000c
+#define NV_PGRAPH_GPC0_TPCX_STRAND_CMD_DISABLE                       0x0000000d
+#define NV_PGRAPH_GPC0_TPCX_STRAND_MEM_BASE                            0x501dc4
+
+#define NV_TPC_STRAND_INDEX                                               0x560
+#define NV_TPC_STRAND_CNT                                                 0x570
+#define NV_TPC_STRAND_SAVE_SWBASE                                         0x588
+#define NV_TPC_STRAND_LOAD_SWBASE                                         0x58c
+#define NV_TPC_STRAND_WORDS                                               0x590
 
 #define mmctx_data(r,c) .b32 (((c - 1) << 26) | r)
 #define queue_init      .skip 72 // (2 * 4) + ((8 * 4) * 2)
@@ -178,6 +209,7 @@
 #define T_SAVE    7
 #define T_LCHAN   8
 #define T_LCTXH   9
+#define T_STRTPC  10
 
 #if CHIPSET < GK208
 #define imm32(reg,val) /*

+ 18 - 4
drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.c

@@ -236,7 +236,7 @@ static int
 gf100_gr_set_shader_exceptions(struct nvkm_object *object, u32 mthd,
 			       void *pdata, u32 size)
 {
-	struct gf100_gr_priv *priv = (void *)nv_engine(object);
+	struct gf100_gr_priv *priv = (void *)object->engine;
 	if (size >= sizeof(u32)) {
 		u32 data = *(u32 *)pdata ? 0xffffffff : 0x00000000;
 		nv_wr32(priv, 0x419e44, data);
@@ -260,8 +260,8 @@ gf100_gr_90c0_omthds[] = {
 
 struct nvkm_oclass
 gf100_gr_sclass[] = {
-	{ 0x902d, &nvkm_object_ofuncs },
-	{ 0x9039, &nvkm_object_ofuncs },
+	{ FERMI_TWOD_A, &nvkm_object_ofuncs },
+	{ FERMI_MEMORY_TO_MEMORY_FORMAT_A, &nvkm_object_ofuncs },
 	{ FERMI_A, &gf100_fermi_ofuncs, gf100_gr_9097_omthds },
 	{ FERMI_COMPUTE_A, &nvkm_object_ofuncs, gf100_gr_90c0_omthds },
 	{}
@@ -1097,12 +1097,26 @@ gf100_gr_intr(struct nvkm_subdev *subdev)
 	u32 subc = (addr & 0x00070000) >> 16;
 	u32 data = nv_rd32(priv, 0x400708);
 	u32 code = nv_rd32(priv, 0x400110);
-	u32 class = nv_rd32(priv, 0x404200 + (subc * 4));
+	u32 class;
 	int chid;
 
+	if (nv_device(priv)->card_type < NV_E0 || subc < 4)
+		class = nv_rd32(priv, 0x404200 + (subc * 4));
+	else
+		class = 0x0000;
+
 	engctx = nvkm_engctx_get(engine, inst);
 	chid   = pfifo->chid(pfifo, engctx);
 
+	if (stat & 0x00000001) {
+		/*
+		 * notifier interrupt, only needed for cyclestats
+		 * can be safely ignored
+		 */
+		nv_wr32(priv, 0x400100, 0x00000001);
+		stat &= ~0x00000001;
+	}
+
 	if (stat & 0x00000010) {
 		handle = nvkm_handle_get_class(engctx, class);
 		if (!handle || nv_call(handle->object, mthd, data)) {

+ 18 - 2
drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.h

@@ -124,10 +124,12 @@ void gf100_gr_dtor(struct nvkm_object *);
 int  gf100_gr_init(struct nvkm_object *);
 void gf100_gr_zbc_init(struct gf100_gr_priv *);
 
-int  gk104_gr_fini(struct nvkm_object *, bool);
+int  gk104_gr_ctor(struct nvkm_object *, struct nvkm_object *,
+		     struct nvkm_oclass *, void *data, u32 size,
+		     struct nvkm_object **);
 int  gk104_gr_init(struct nvkm_object *);
 
-int  gk110_gr_fini(struct nvkm_object *, bool);
+int  gm204_gr_init(struct nvkm_object *);
 
 extern struct nvkm_ofuncs gf100_fermi_ofuncs;
 
@@ -136,6 +138,7 @@ extern struct nvkm_omthds gf100_gr_9097_omthds[];
 extern struct nvkm_omthds gf100_gr_90c0_omthds[];
 extern struct nvkm_oclass gf110_gr_sclass[];
 extern struct nvkm_oclass gk110_gr_sclass[];
+extern struct nvkm_oclass gm204_gr_sclass[];
 
 struct gf100_gr_init {
 	u32 addr;
@@ -247,4 +250,17 @@ extern const struct gf100_gr_init gk110_gr_init_tex_0[];
 extern const struct gf100_gr_init gk110_gr_init_sm_0[];
 
 extern const struct gf100_gr_init gk208_gr_init_gpc_unk_0[];
+
+extern const struct gf100_gr_init gm107_gr_init_scc_0[];
+extern const struct gf100_gr_init gm107_gr_init_prop_0[];
+extern const struct gf100_gr_init gm107_gr_init_setup_1[];
+extern const struct gf100_gr_init gm107_gr_init_zcull_0[];
+extern const struct gf100_gr_init gm107_gr_init_gpc_unk_1[];
+extern const struct gf100_gr_init gm107_gr_init_tex_0[];
+extern const struct gf100_gr_init gm107_gr_init_l1c_0[];
+extern const struct gf100_gr_init gm107_gr_init_wwdx_0[];
+extern const struct gf100_gr_init gm107_gr_init_cbm_0[];
+void gm107_gr_init_bios(struct gf100_gr_priv *);
+
+extern const struct gf100_gr_pack gm204_gr_pack_mmio[];
 #endif

+ 2 - 2
drivers/gpu/drm/nouveau/nvkm/engine/gr/gf108.c

@@ -32,8 +32,8 @@
 
 static struct nvkm_oclass
 gf108_gr_sclass[] = {
-	{ 0x902d, &nvkm_object_ofuncs },
-	{ 0x9039, &nvkm_object_ofuncs },
+	{ FERMI_TWOD_A, &nvkm_object_ofuncs },
+	{ FERMI_MEMORY_TO_MEMORY_FORMAT_A, &nvkm_object_ofuncs },
 	{ FERMI_A, &gf100_fermi_ofuncs, gf100_gr_9097_omthds },
 	{ FERMI_B, &gf100_fermi_ofuncs, gf100_gr_9097_omthds },
 	{ FERMI_COMPUTE_A, &nvkm_object_ofuncs, gf100_gr_90c0_omthds },

+ 2 - 2
drivers/gpu/drm/nouveau/nvkm/engine/gr/gf110.c

@@ -32,8 +32,8 @@
 
 struct nvkm_oclass
 gf110_gr_sclass[] = {
-	{ 0x902d, &nvkm_object_ofuncs },
-	{ 0x9039, &nvkm_object_ofuncs },
+	{ FERMI_TWOD_A, &nvkm_object_ofuncs },
+	{ FERMI_MEMORY_TO_MEMORY_FORMAT_A, &nvkm_object_ofuncs },
 	{ FERMI_A, &gf100_fermi_ofuncs, gf100_gr_9097_omthds },
 	{ FERMI_B, &gf100_fermi_ofuncs, gf100_gr_9097_omthds },
 	{ FERMI_C, &gf100_fermi_ofuncs, gf100_gr_9097_omthds },

+ 14 - 3
drivers/gpu/drm/nouveau/nvkm/engine/gr/gk104.c

@@ -34,8 +34,8 @@
 
 static struct nvkm_oclass
 gk104_gr_sclass[] = {
-	{ 0x902d, &nvkm_object_ofuncs },
-	{ 0xa040, &nvkm_object_ofuncs },
+	{ FERMI_TWOD_A, &nvkm_object_ofuncs },
+	{ KEPLER_INLINE_TO_MEMORY_A, &nvkm_object_ofuncs },
 	{ KEPLER_A, &gf100_fermi_ofuncs, gf100_gr_9097_omthds },
 	{ KEPLER_COMPUTE_A, &nvkm_object_ofuncs, gf100_gr_90c0_omthds },
 	{}
@@ -310,6 +310,17 @@ gk104_gr_init(struct nvkm_object *object)
 	return gf100_gr_init_ctxctl(priv);
 }
 
+int
+gk104_gr_ctor(struct nvkm_object *parent, struct nvkm_object *engine,
+	      struct nvkm_oclass *oclass, void *data, u32 size,
+	      struct nvkm_object **pobject)
+{
+	struct nvkm_pmu *pmu = nvkm_pmu(parent);
+	if (pmu)
+		pmu->pgob(pmu, false);
+	return gf100_gr_ctor(parent, engine, oclass, data, size, pobject);
+}
+
 #include "fuc/hubgk104.fuc3.h"
 
 static struct gf100_gr_ucode
@@ -334,7 +345,7 @@ struct nvkm_oclass *
 gk104_gr_oclass = &(struct gf100_gr_oclass) {
 	.base.handle = NV_ENGINE(GR, 0xe4),
 	.base.ofuncs = &(struct nvkm_ofuncs) {
-		.ctor = gf100_gr_ctor,
+		.ctor = gk104_gr_ctor,
 		.dtor = gf100_gr_dtor,
 		.init = gk104_gr_init,
 		.fini = _nvkm_gr_fini,

+ 4 - 41
drivers/gpu/drm/nouveau/nvkm/engine/gr/gk110.c

@@ -34,8 +34,8 @@
 
 struct nvkm_oclass
 gk110_gr_sclass[] = {
-	{ 0x902d, &nvkm_object_ofuncs },
-	{ 0xa140, &nvkm_object_ofuncs },
+	{ FERMI_TWOD_A, &nvkm_object_ofuncs },
+	{ KEPLER_INLINE_TO_MEMORY_B, &nvkm_object_ofuncs },
 	{ KEPLER_B, &gf100_fermi_ofuncs, gf100_gr_9097_omthds },
 	{ KEPLER_COMPUTE_B, &nvkm_object_ofuncs, gf100_gr_90c0_omthds },
 	{}
@@ -173,43 +173,6 @@ gk110_gr_pack_mmio[] = {
  * PGRAPH engine/subdev functions
  ******************************************************************************/
 
-int
-gk110_gr_fini(struct nvkm_object *object, bool suspend)
-{
-	struct gf100_gr_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 nvkm_gr_fini(&priv->base, suspend);
-}
-
 #include "fuc/hubgk110.fuc3.h"
 
 struct gf100_gr_ucode
@@ -234,10 +197,10 @@ struct nvkm_oclass *
 gk110_gr_oclass = &(struct gf100_gr_oclass) {
 	.base.handle = NV_ENGINE(GR, 0xf0),
 	.base.ofuncs = &(struct nvkm_ofuncs) {
-		.ctor = gf100_gr_ctor,
+		.ctor = gk104_gr_ctor,
 		.dtor = gf100_gr_dtor,
 		.init = gk104_gr_init,
-		.fini = gk110_gr_fini,
+		.fini = _nvkm_gr_fini,
 	},
 	.cclass = &gk110_grctx_oclass,
 	.sclass =  gk110_gr_sclass,

+ 2 - 2
drivers/gpu/drm/nouveau/nvkm/engine/gr/gk110b.c

@@ -102,10 +102,10 @@ struct nvkm_oclass *
 gk110b_gr_oclass = &(struct gf100_gr_oclass) {
 	.base.handle = NV_ENGINE(GR, 0xf1),
 	.base.ofuncs = &(struct nvkm_ofuncs) {
-		.ctor = gf100_gr_ctor,
+		.ctor = gk104_gr_ctor,
 		.dtor = gf100_gr_dtor,
 		.init = gk104_gr_init,
-		.fini = gk110_gr_fini,
+		.fini = _nvkm_gr_fini,
 	},
 	.cclass = &gk110b_grctx_oclass,
 	.sclass =  gk110_gr_sclass,

+ 5 - 42
drivers/gpu/drm/nouveau/nvkm/engine/gr/gk208.c

@@ -34,10 +34,10 @@
 
 static struct nvkm_oclass
 gk208_gr_sclass[] = {
-	{ 0x902d, &nvkm_object_ofuncs },
-	{ 0xa140, &nvkm_object_ofuncs },
+	{ FERMI_TWOD_A, &nvkm_object_ofuncs },
+	{ KEPLER_INLINE_TO_MEMORY_B, &nvkm_object_ofuncs },
 	{ KEPLER_B, &gf100_fermi_ofuncs },
-	{ 0xa1c0, &nvkm_object_ofuncs },
+	{ KEPLER_COMPUTE_B, &nvkm_object_ofuncs },
 	{}
 };
 
@@ -152,43 +152,6 @@ gk208_gr_pack_mmio[] = {
  * PGRAPH engine/subdev functions
  ******************************************************************************/
 
-static int
-gk208_gr_fini(struct nvkm_object *object, bool suspend)
-{
-	struct gf100_gr_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 nvkm_gr_fini(&priv->base, suspend);
-}
-
 #include "fuc/hubgk208.fuc5.h"
 
 static struct gf100_gr_ucode
@@ -213,10 +176,10 @@ struct nvkm_oclass *
 gk208_gr_oclass = &(struct gf100_gr_oclass) {
 	.base.handle = NV_ENGINE(GR, 0x08),
 	.base.ofuncs = &(struct nvkm_ofuncs) {
-		.ctor = gf100_gr_ctor,
+		.ctor = gk104_gr_ctor,
 		.dtor = gf100_gr_dtor,
 		.init = gk104_gr_init,
-		.fini = gk208_gr_fini,
+		.fini = _nvkm_gr_fini,
 	},
 	.cclass = &gk208_grctx_oclass,
 	.sclass =  gk208_gr_sclass,

+ 2 - 2
drivers/gpu/drm/nouveau/nvkm/engine/gr/gk20a.c

@@ -26,8 +26,8 @@
 
 static struct nvkm_oclass
 gk20a_gr_sclass[] = {
-	{ 0x902d, &nvkm_object_ofuncs },
-	{ 0xa040, &nvkm_object_ofuncs },
+	{ FERMI_TWOD_A, &nvkm_object_ofuncs },
+	{ KEPLER_INLINE_TO_MEMORY_A, &nvkm_object_ofuncs },
 	{ KEPLER_C, &gf100_fermi_ofuncs, gf100_gr_9097_omthds },
 	{ KEPLER_COMPUTE_A, &nvkm_object_ofuncs, gf100_gr_90c0_omthds },
 	{}

+ 13 - 13
drivers/gpu/drm/nouveau/nvkm/engine/gr/gm107.c

@@ -35,8 +35,8 @@
 
 static struct nvkm_oclass
 gm107_gr_sclass[] = {
-	{ 0x902d, &nvkm_object_ofuncs },
-	{ 0xa140, &nvkm_object_ofuncs },
+	{ FERMI_TWOD_A, &nvkm_object_ofuncs },
+	{ KEPLER_INLINE_TO_MEMORY_B, &nvkm_object_ofuncs },
 	{ MAXWELL_A, &gf100_fermi_ofuncs, gf100_gr_9097_omthds },
 	{ MAXWELL_COMPUTE_A, &nvkm_object_ofuncs, gf100_gr_90c0_omthds },
 	{}
@@ -71,7 +71,7 @@ gm107_gr_init_ds_0[] = {
 	{}
 };
 
-static const struct gf100_gr_init
+const struct gf100_gr_init
 gm107_gr_init_scc_0[] = {
 	{ 0x40803c,   1, 0x04, 0x00000010 },
 	{}
@@ -85,14 +85,14 @@ gm107_gr_init_sked_0[] = {
 	{}
 };
 
-static const struct gf100_gr_init
+const struct gf100_gr_init
 gm107_gr_init_prop_0[] = {
 	{ 0x418408,   1, 0x04, 0x00000000 },
 	{ 0x4184a0,   1, 0x04, 0x00000000 },
 	{}
 };
 
-static const struct gf100_gr_init
+const struct gf100_gr_init
 gm107_gr_init_setup_1[] = {
 	{ 0x4188c8,   2, 0x04, 0x00000000 },
 	{ 0x4188d0,   1, 0x04, 0x00010000 },
@@ -100,7 +100,7 @@ gm107_gr_init_setup_1[] = {
 	{}
 };
 
-static const struct gf100_gr_init
+const struct gf100_gr_init
 gm107_gr_init_zcull_0[] = {
 	{ 0x418910,   1, 0x04, 0x00010001 },
 	{ 0x418914,   1, 0x04, 0x00000301 },
@@ -111,7 +111,7 @@ gm107_gr_init_zcull_0[] = {
 	{}
 };
 
-static const struct gf100_gr_init
+const struct gf100_gr_init
 gm107_gr_init_gpc_unk_1[] = {
 	{ 0x418d00,   1, 0x04, 0x00000000 },
 	{ 0x418f00,   1, 0x04, 0x00000400 },
@@ -134,7 +134,7 @@ gm107_gr_init_tpccs_0[] = {
 	{}
 };
 
-static const struct gf100_gr_init
+const struct gf100_gr_init
 gm107_gr_init_tex_0[] = {
 	{ 0x419ab0,   1, 0x04, 0x00000000 },
 	{ 0x419ab8,   1, 0x04, 0x000000e7 },
@@ -160,7 +160,7 @@ gm107_gr_init_pe_0[] = {
 	{}
 };
 
-static const struct gf100_gr_init
+const struct gf100_gr_init
 gm107_gr_init_l1c_0[] = {
 	{ 0x419c98,   1, 0x04, 0x00000000 },
 	{ 0x419cc0,   2, 0x04, 0x00000000 },
@@ -206,14 +206,14 @@ gm107_gr_init_pes_0[] = {
 	{}
 };
 
-static const struct gf100_gr_init
+const struct gf100_gr_init
 gm107_gr_init_wwdx_0[] = {
 	{ 0x41bfd4,   1, 0x04, 0x00800000 },
 	{ 0x41bfdc,   1, 0x04, 0x00000000 },
 	{}
 };
 
-static const struct gf100_gr_init
+const struct gf100_gr_init
 gm107_gr_init_cbm_0[] = {
 	{ 0x41becc,   1, 0x04, 0x00000000 },
 	{}
@@ -291,7 +291,7 @@ gm107_gr_pack_mmio[] = {
  * PGRAPH engine/subdev functions
  ******************************************************************************/
 
-static void
+void
 gm107_gr_init_bios(struct gf100_gr_priv *priv)
 {
 	static const struct {
@@ -464,7 +464,7 @@ gm107_gr_oclass = &(struct gf100_gr_oclass) {
 	.cclass = &gm107_grctx_oclass,
 	.sclass =  gm107_gr_sclass,
 	.mmio = gm107_gr_pack_mmio,
-	.fecs.ucode = 0 ? &gm107_gr_fecs_ucode : NULL,
+	.fecs.ucode = &gm107_gr_fecs_ucode,
 	.gpccs.ucode = &gm107_gr_gpccs_ucode,
 	.ppc_nr = 2,
 }.base;

+ 387 - 0
drivers/gpu/drm/nouveau/nvkm/engine/gr/gm204.c

@@ -0,0 +1,387 @@
+/*
+ * Copyright 2015 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 "gf100.h"
+#include "ctxgf100.h"
+
+#include <nvif/class.h>
+
+/*******************************************************************************
+ * Graphics object classes
+ ******************************************************************************/
+
+struct nvkm_oclass
+gm204_gr_sclass[] = {
+	{ FERMI_TWOD_A, &nvkm_object_ofuncs },
+	{ KEPLER_INLINE_TO_MEMORY_B, &nvkm_object_ofuncs },
+	{ MAXWELL_B, &gf100_fermi_ofuncs, gf100_gr_9097_omthds },
+	{ MAXWELL_COMPUTE_B, &nvkm_object_ofuncs, gf100_gr_90c0_omthds },
+	{}
+};
+
+/*******************************************************************************
+ * PGRAPH register lists
+ ******************************************************************************/
+
+static const struct gf100_gr_init
+gm204_gr_init_main_0[] = {
+	{ 0x400080,   1, 0x04, 0x003003e2 },
+	{ 0x400088,   1, 0x04, 0xe007bfe7 },
+	{ 0x40008c,   1, 0x04, 0x00060000 },
+	{ 0x400090,   1, 0x04, 0x00000030 },
+	{ 0x40013c,   1, 0x04, 0x003901f3 },
+	{ 0x400140,   1, 0x04, 0x00000100 },
+	{ 0x400144,   1, 0x04, 0x00000000 },
+	{ 0x400148,   1, 0x04, 0x00000110 },
+	{ 0x400138,   1, 0x04, 0x00000000 },
+	{ 0x400130,   2, 0x04, 0x00000000 },
+	{ 0x400124,   1, 0x04, 0x00000002 },
+	{}
+};
+
+static const struct gf100_gr_init
+gm204_gr_init_fe_0[] = {
+	{ 0x40415c,   1, 0x04, 0x00000000 },
+	{ 0x404170,   1, 0x04, 0x00000000 },
+	{ 0x4041b4,   1, 0x04, 0x00000000 },
+	{ 0x4041b8,   1, 0x04, 0x00000010 },
+	{}
+};
+
+static const struct gf100_gr_init
+gm204_gr_init_ds_0[] = {
+	{ 0x40583c,   1, 0x04, 0x00000000 },
+	{ 0x405844,   1, 0x04, 0x00ffffff },
+	{ 0x40584c,   1, 0x04, 0x00000001 },
+	{ 0x405850,   1, 0x04, 0x00000000 },
+	{ 0x405900,   1, 0x04, 0x00000000 },
+	{ 0x405908,   1, 0x04, 0x00000000 },
+	{}
+};
+
+static const struct gf100_gr_init
+gm204_gr_init_sked_0[] = {
+	{ 0x407010,   1, 0x04, 0x00000000 },
+	{ 0x407040,   1, 0x04, 0x80440434 },
+	{ 0x407048,   1, 0x04, 0x00000008 },
+	{}
+};
+
+static const struct gf100_gr_init
+gm204_gr_init_tpccs_0[] = {
+	{ 0x419d60,   1, 0x04, 0x0000003f },
+	{ 0x419d88,   3, 0x04, 0x00000000 },
+	{ 0x419dc4,   1, 0x04, 0x00000000 },
+	{ 0x419dc8,   1, 0x04, 0x00000501 },
+	{ 0x419dd0,   1, 0x04, 0x00000000 },
+	{ 0x419dd4,   1, 0x04, 0x00000100 },
+	{ 0x419dd8,   1, 0x04, 0x00000001 },
+	{ 0x419ddc,   1, 0x04, 0x00000002 },
+	{ 0x419de0,   1, 0x04, 0x00000001 },
+	{ 0x419de8,   1, 0x04, 0x000000cc },
+	{ 0x419dec,   1, 0x04, 0x00000000 },
+	{ 0x419df0,   1, 0x04, 0x000000cc },
+	{ 0x419df4,   1, 0x04, 0x00000000 },
+	{ 0x419d0c,   1, 0x04, 0x00000000 },
+	{ 0x419d10,   1, 0x04, 0x00000014 },
+	{}
+};
+
+static const struct gf100_gr_init
+gm204_gr_init_pe_0[] = {
+	{ 0x419900,   1, 0x04, 0x000000ff },
+	{ 0x419810,   1, 0x04, 0x00000000 },
+	{ 0x41980c,   1, 0x04, 0x00000010 },
+	{ 0x419844,   1, 0x04, 0x00000000 },
+	{ 0x419838,   1, 0x04, 0x000000ff },
+	{ 0x419850,   1, 0x04, 0x00000004 },
+	{ 0x419854,   2, 0x04, 0x00000000 },
+	{ 0x419894,   3, 0x04, 0x00100401 },
+	{}
+};
+
+static const struct gf100_gr_init
+gm204_gr_init_sm_0[] = {
+	{ 0x419e30,   1, 0x04, 0x000000ff },
+	{ 0x419e00,   1, 0x04, 0x00000000 },
+	{ 0x419ea0,   1, 0x04, 0x00000000 },
+	{ 0x419ee4,   1, 0x04, 0x00000000 },
+	{ 0x419ea4,   1, 0x04, 0x00000100 },
+	{ 0x419ea8,   1, 0x04, 0x00000000 },
+	{ 0x419ee8,   1, 0x04, 0x00000091 },
+	{ 0x419eb4,   1, 0x04, 0x00000000 },
+	{ 0x419ebc,   2, 0x04, 0x00000000 },
+	{ 0x419edc,   1, 0x04, 0x000c1810 },
+	{ 0x419ed8,   1, 0x04, 0x00000000 },
+	{ 0x419ee0,   1, 0x04, 0x00000000 },
+	{}
+};
+
+static const struct gf100_gr_init
+gm204_gr_init_l1c_1[] = {
+	{ 0x419cf8,   2, 0x04, 0x00000000 },
+	{}
+};
+
+static const struct gf100_gr_init
+gm204_gr_init_sm_1[] = {
+	{ 0x419f74,   1, 0x04, 0x00055155 },
+	{ 0x419f80,   4, 0x04, 0x00000000 },
+	{}
+};
+
+static const struct gf100_gr_init
+gm204_gr_init_l1c_2[] = {
+	{ 0x419ccc,   2, 0x04, 0x00000000 },
+	{ 0x419c80,   1, 0x04, 0x3f006022 },
+	{ 0x419c88,   1, 0x04, 0x00210000 },
+	{}
+};
+
+static const struct gf100_gr_init
+gm204_gr_init_pes_0[] = {
+	{ 0x41be50,   1, 0x04, 0x000000ff },
+	{ 0x41be04,   1, 0x04, 0x00000000 },
+	{ 0x41be08,   1, 0x04, 0x00000004 },
+	{ 0x41be0c,   1, 0x04, 0x00000008 },
+	{ 0x41be10,   1, 0x04, 0x2e3b8bc7 },
+	{ 0x41be14,   2, 0x04, 0x00000000 },
+	{ 0x41be3c,   5, 0x04, 0x00100401 },
+	{}
+};
+
+static const struct gf100_gr_init
+gm204_gr_init_be_0[] = {
+	{ 0x408890,   1, 0x04, 0x000000ff },
+	{ 0x40880c,   1, 0x04, 0x00000000 },
+	{ 0x408850,   1, 0x04, 0x00000004 },
+	{ 0x408878,   1, 0x04, 0x01b4201c },
+	{ 0x40887c,   1, 0x04, 0x80004c55 },
+	{ 0x408880,   1, 0x04, 0x0018c258 },
+	{ 0x408884,   1, 0x04, 0x0000160f },
+	{ 0x408974,   1, 0x04, 0x000000ff },
+	{ 0x408910,   9, 0x04, 0x00000000 },
+	{ 0x408950,   1, 0x04, 0x00000000 },
+	{ 0x408954,   1, 0x04, 0x0000ffff },
+	{ 0x408958,   1, 0x04, 0x00000034 },
+	{ 0x40895c,   1, 0x04, 0x84b17403 },
+	{ 0x408960,   1, 0x04, 0x04c1884f },
+	{ 0x408964,   1, 0x04, 0x04714445 },
+	{ 0x408968,   1, 0x04, 0x0280802f },
+	{ 0x40896c,   1, 0x04, 0x04304856 },
+	{ 0x408970,   1, 0x04, 0x00012800 },
+	{ 0x408984,   1, 0x04, 0x00000000 },
+	{ 0x408988,   1, 0x04, 0x08040201 },
+	{ 0x40898c,   1, 0x04, 0x80402010 },
+	{}
+};
+
+const struct gf100_gr_pack
+gm204_gr_pack_mmio[] = {
+	{ gm204_gr_init_main_0 },
+	{ gm204_gr_init_fe_0 },
+	{ gf100_gr_init_pri_0 },
+	{ gf100_gr_init_rstr2d_0 },
+	{ gf100_gr_init_pd_0 },
+	{ gm204_gr_init_ds_0 },
+	{ gm107_gr_init_scc_0 },
+	{ gm204_gr_init_sked_0 },
+	{ gk110_gr_init_cwd_0 },
+	{ gm107_gr_init_prop_0 },
+	{ gk208_gr_init_gpc_unk_0 },
+	{ gf100_gr_init_setup_0 },
+	{ gf100_gr_init_crstr_0 },
+	{ gm107_gr_init_setup_1 },
+	{ gm107_gr_init_zcull_0 },
+	{ gf100_gr_init_gpm_0 },
+	{ gm107_gr_init_gpc_unk_1 },
+	{ gf100_gr_init_gcc_0 },
+	{ gm204_gr_init_tpccs_0 },
+	{ gm107_gr_init_tex_0 },
+	{ gm204_gr_init_pe_0 },
+	{ gm107_gr_init_l1c_0 },
+	{ gf100_gr_init_mpc_0 },
+	{ gm204_gr_init_sm_0 },
+	{ gm204_gr_init_l1c_1 },
+	{ gm204_gr_init_sm_1 },
+	{ gm204_gr_init_l1c_2 },
+	{ gm204_gr_init_pes_0 },
+	{ gm107_gr_init_wwdx_0 },
+	{ gm107_gr_init_cbm_0 },
+	{ gm204_gr_init_be_0 },
+	{}
+};
+
+const struct gf100_gr_pack *
+gm204_gr_data[] = {
+	gm204_gr_pack_mmio,
+	NULL
+};
+
+/*******************************************************************************
+ * PGRAPH engine/subdev functions
+ ******************************************************************************/
+
+static int
+gm204_gr_init_ctxctl(struct gf100_gr_priv *priv)
+{
+	return 0;
+}
+
+int
+gm204_gr_init(struct nvkm_object *object)
+{
+	struct gf100_gr_oclass *oclass = (void *)object->oclass;
+	struct gf100_gr_priv *priv = (void *)object;
+	const u32 magicgpc918 = DIV_ROUND_UP(0x00800000, priv->tpc_total);
+	u32 data[TPC_MAX / 8] = {};
+	u8  tpcnr[GPC_MAX];
+	int gpc, tpc, ppc, rop;
+	int ret, i;
+	u32 tmp;
+
+	ret = nvkm_gr_init(&priv->base);
+	if (ret)
+		return ret;
+
+	tmp = nv_rd32(priv, 0x100c80); /*XXX: mask? */
+	nv_wr32(priv, 0x418880, 0x00001000 | (tmp & 0x00000fff));
+	nv_wr32(priv, 0x418890, 0x00000000);
+	nv_wr32(priv, 0x418894, 0x00000000);
+	nv_wr32(priv, 0x4188b4, priv->unk4188b4->addr >> 8);
+	nv_wr32(priv, 0x4188b8, priv->unk4188b8->addr >> 8);
+	nv_mask(priv, 0x4188b0, 0x00040000, 0x00040000);
+
+	/*XXX: belongs in fb */
+	nv_wr32(priv, 0x100cc8, priv->unk4188b4->addr >> 8);
+	nv_wr32(priv, 0x100ccc, priv->unk4188b8->addr >> 8);
+	nv_mask(priv, 0x100cc4, 0x00040000, 0x00040000);
+
+	gf100_gr_mmio(priv, oclass->mmio);
+
+	gm107_gr_init_bios(priv);
+
+	nv_wr32(priv, GPC_UNIT(0, 0x3018), 0x00000001);
+
+	memset(data, 0x00, sizeof(data));
+	memcpy(tpcnr, priv->tpc_nr, sizeof(priv->tpc_nr));
+	for (i = 0, gpc = -1; i < priv->tpc_total; i++) {
+		do {
+			gpc = (gpc + 1) % priv->gpc_nr;
+		} while (!tpcnr[gpc]);
+		tpc = priv->tpc_nr[gpc] - tpcnr[gpc]--;
+
+		data[i / 8] |= tpc << ((i % 8) * 4);
+	}
+
+	nv_wr32(priv, GPC_BCAST(0x0980), data[0]);
+	nv_wr32(priv, GPC_BCAST(0x0984), data[1]);
+	nv_wr32(priv, GPC_BCAST(0x0988), data[2]);
+	nv_wr32(priv, GPC_BCAST(0x098c), data[3]);
+
+	for (gpc = 0; gpc < priv->gpc_nr; gpc++) {
+		nv_wr32(priv, GPC_UNIT(gpc, 0x0914),
+			priv->magic_not_rop_nr << 8 | priv->tpc_nr[gpc]);
+		nv_wr32(priv, GPC_UNIT(gpc, 0x0910), 0x00040000 |
+			priv->tpc_total);
+		nv_wr32(priv, GPC_UNIT(gpc, 0x0918), magicgpc918);
+	}
+
+	nv_wr32(priv, GPC_BCAST(0x3fd4), magicgpc918);
+	nv_wr32(priv, GPC_BCAST(0x08ac), nv_rd32(priv, 0x100800));
+	nv_wr32(priv, GPC_BCAST(0x033c), nv_rd32(priv, 0x100804));
+
+	nv_wr32(priv, 0x400500, 0x00010001);
+	nv_wr32(priv, 0x400100, 0xffffffff);
+	nv_wr32(priv, 0x40013c, 0xffffffff);
+	nv_wr32(priv, 0x400124, 0x00000002);
+	nv_wr32(priv, 0x409c24, 0x000e0000);
+	nv_wr32(priv, 0x405848, 0xc0000000);
+	nv_wr32(priv, 0x40584c, 0x00000001);
+	nv_wr32(priv, 0x404000, 0xc0000000);
+	nv_wr32(priv, 0x404600, 0xc0000000);
+	nv_wr32(priv, 0x408030, 0xc0000000);
+	nv_wr32(priv, 0x404490, 0xc0000000);
+	nv_wr32(priv, 0x406018, 0xc0000000);
+	nv_wr32(priv, 0x407020, 0x40000000);
+	nv_wr32(priv, 0x405840, 0xc0000000);
+	nv_wr32(priv, 0x405844, 0x00ffffff);
+	nv_mask(priv, 0x419cc0, 0x00000008, 0x00000008);
+
+	for (gpc = 0; gpc < priv->gpc_nr; gpc++) {
+	printk(KERN_ERR "ppc %d %d\n", gpc, priv->ppc_nr[gpc]);
+		for (ppc = 0; ppc < priv->ppc_nr[gpc]; ppc++)
+			nv_wr32(priv, PPC_UNIT(gpc, ppc, 0x038), 0xc0000000);
+		nv_wr32(priv, GPC_UNIT(gpc, 0x0420), 0xc0000000);
+		nv_wr32(priv, GPC_UNIT(gpc, 0x0900), 0xc0000000);
+		nv_wr32(priv, GPC_UNIT(gpc, 0x1028), 0xc0000000);
+		nv_wr32(priv, GPC_UNIT(gpc, 0x0824), 0xc0000000);
+		for (tpc = 0; tpc < priv->tpc_nr[gpc]; tpc++) {
+			nv_wr32(priv, TPC_UNIT(gpc, tpc, 0x508), 0xffffffff);
+			nv_wr32(priv, TPC_UNIT(gpc, tpc, 0x50c), 0xffffffff);
+			nv_wr32(priv, TPC_UNIT(gpc, tpc, 0x224), 0xc0000000);
+			nv_wr32(priv, TPC_UNIT(gpc, tpc, 0x48c), 0xc0000000);
+			nv_wr32(priv, TPC_UNIT(gpc, tpc, 0x084), 0xc0000000);
+			nv_wr32(priv, TPC_UNIT(gpc, tpc, 0x430), 0xc0000000);
+			nv_wr32(priv, TPC_UNIT(gpc, tpc, 0x644), 0x00dffffe);
+			nv_wr32(priv, TPC_UNIT(gpc, tpc, 0x64c), 0x00000005);
+		}
+		nv_wr32(priv, GPC_UNIT(gpc, 0x2c90), 0xffffffff);
+		nv_wr32(priv, GPC_UNIT(gpc, 0x2c94), 0xffffffff);
+	}
+
+	for (rop = 0; rop < priv->rop_nr; rop++) {
+		nv_wr32(priv, ROP_UNIT(rop, 0x144), 0x40000000);
+		nv_wr32(priv, ROP_UNIT(rop, 0x070), 0x40000000);
+		nv_wr32(priv, ROP_UNIT(rop, 0x204), 0xffffffff);
+		nv_wr32(priv, ROP_UNIT(rop, 0x208), 0xffffffff);
+	}
+
+	nv_wr32(priv, 0x400108, 0xffffffff);
+	nv_wr32(priv, 0x400138, 0xffffffff);
+	nv_wr32(priv, 0x400118, 0xffffffff);
+	nv_wr32(priv, 0x400130, 0xffffffff);
+	nv_wr32(priv, 0x40011c, 0xffffffff);
+	nv_wr32(priv, 0x400134, 0xffffffff);
+
+	nv_wr32(priv, 0x400054, 0x2c350f63);
+
+	gf100_gr_zbc_init(priv);
+
+	return gm204_gr_init_ctxctl(priv);
+}
+
+struct nvkm_oclass *
+gm204_gr_oclass = &(struct gf100_gr_oclass) {
+	.base.handle = NV_ENGINE(GR, 0x24),
+	.base.ofuncs = &(struct nvkm_ofuncs) {
+		.ctor = gf100_gr_ctor,
+		.dtor = gf100_gr_dtor,
+		.init = gm204_gr_init,
+		.fini = _nvkm_gr_fini,
+	},
+	.cclass = &gm204_grctx_oclass,
+	.sclass =  gm204_gr_sclass,
+	.mmio = gm204_gr_pack_mmio,
+	.ppc_nr = 2,
+}.base;

+ 40 - 0
drivers/gpu/drm/nouveau/nvkm/engine/gr/gm206.c

@@ -0,0 +1,40 @@
+/*
+ * Copyright 2015 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 "gf100.h"
+#include "ctxgf100.h"
+
+struct nvkm_oclass *
+gm206_gr_oclass = &(struct gf100_gr_oclass) {
+	.base.handle = NV_ENGINE(GR, 0x26),
+	.base.ofuncs = &(struct nvkm_ofuncs) {
+		.ctor = gf100_gr_ctor,
+		.dtor = gf100_gr_dtor,
+		.init = gm204_gr_init,
+		.fini = _nvkm_gr_fini,
+	},
+	.cclass = &gm206_grctx_oclass,
+	.sclass =  gm204_gr_sclass,
+	.mmio = gm204_gr_pack_mmio,
+	.ppc_nr = 2,
+}.base;

+ 2 - 2
drivers/gpu/drm/nouveau/nvkm/subdev/bios/shadowacpi.c

@@ -52,7 +52,7 @@ acpi_read_fast(void *data, u32 offset, u32 length, struct nvkm_bios *bios)
 	u32 start = offset & ~0x00000fff;
 	u32 fetch = limit - start;
 
-	if (nvbios_extend(bios, limit) > 0) {
+	if (nvbios_extend(bios, limit) >= 0) {
 		int ret = nouveau_acpi_get_bios_chunk(bios->data, start, fetch);
 		if (ret == fetch)
 			return fetch;
@@ -73,7 +73,7 @@ acpi_read_slow(void *data, u32 offset, u32 length, struct nvkm_bios *bios)
 	u32 start = offset & ~0xfff;
 	u32 fetch = 0;
 
-	if (nvbios_extend(bios, limit) > 0) {
+	if (nvbios_extend(bios, limit) >= 0) {
 		while (start + fetch < limit) {
 			int ret = nouveau_acpi_get_bios_chunk(bios->data,
 							      start + fetch,

+ 1 - 1
drivers/gpu/drm/nouveau/nvkm/subdev/bus/hwsq.c

@@ -29,7 +29,7 @@ struct nvkm_hwsq {
 	u32 data;
 	struct {
 		u8 data[512];
-		u8 size;
+		u16 size;
 	} c;
 };
 

+ 37 - 7
drivers/gpu/drm/nouveau/nvkm/subdev/bus/hwsq.h

@@ -11,17 +11,34 @@ struct hwsq {
 struct hwsq_reg {
 	int sequence;
 	bool force;
-	u32 addr[2];
+	u32 addr;
+	u32 stride; /* in bytes */
+	u32 mask;
 	u32 data;
 };
 
+static inline struct hwsq_reg
+hwsq_stride(u32 addr, u32 stride, u32 mask)
+{
+	return (struct hwsq_reg) {
+		.sequence = 0,
+		.force = 0,
+		.addr = addr,
+		.stride = stride,
+		.mask = mask,
+		.data = 0xdeadbeef,
+	};
+}
+
 static inline struct hwsq_reg
 hwsq_reg2(u32 addr1, u32 addr2)
 {
 	return (struct hwsq_reg) {
 		.sequence = 0,
 		.force = 0,
-		.addr = { addr1, addr2 },
+		.addr = addr1,
+		.stride = addr2 - addr1,
+		.mask = 0x3,
 		.data = 0xdeadbeef,
 	};
 }
@@ -29,7 +46,14 @@ hwsq_reg2(u32 addr1, u32 addr2)
 static inline struct hwsq_reg
 hwsq_reg(u32 addr)
 {
-	return hwsq_reg2(addr, addr);
+	return (struct hwsq_reg) {
+		.sequence = 0,
+		.force = 0,
+		.addr = addr,
+		.stride = 0,
+		.mask = 0x1,
+		.data = 0xdeadbeef,
+	};
 }
 
 static inline int
@@ -62,18 +86,24 @@ static inline u32
 hwsq_rd32(struct hwsq *ram, struct hwsq_reg *reg)
 {
 	if (reg->sequence != ram->sequence)
-		reg->data = nv_rd32(ram->subdev, reg->addr[0]);
+		reg->data = nv_rd32(ram->subdev, reg->addr);
 	return reg->data;
 }
 
 static inline void
 hwsq_wr32(struct hwsq *ram, struct hwsq_reg *reg, u32 data)
 {
+	u32 mask, off = 0;
+
 	reg->sequence = ram->sequence;
 	reg->data = data;
-	if (reg->addr[0] != reg->addr[1])
-		nvkm_hwsq_wr32(ram->hwsq, reg->addr[1], reg->data);
-	nvkm_hwsq_wr32(ram->hwsq, reg->addr[0], reg->data);
+
+	for (mask = reg->mask; mask > 0; mask = (mask & ~1) >> 1) {
+		if (mask & 1)
+			nvkm_hwsq_wr32(ram->hwsq, reg->addr+off, reg->data);
+
+		off += reg->stride;
+	}
 }
 
 static inline void

+ 1 - 1
drivers/gpu/drm/nouveau/nvkm/subdev/clk/base.c

@@ -184,7 +184,7 @@ nvkm_pstate_prog(struct nvkm_clk *clk, int pstatei)
 	nv_debug(clk, "setting performance state %d\n", pstatei);
 	clk->pstate = pstatei;
 
-	if (pfb->ram->calc) {
+	if (pfb->ram && pfb->ram->calc) {
 		int khz = pstate->base.domain[nv_clk_src_mem];
 		do {
 			ret = pfb->ram->calc(pfb, khz);

+ 1 - 1
drivers/gpu/drm/nouveau/nvkm/subdev/devinit/nv04.h

@@ -5,7 +5,7 @@ struct nvkm_pll_vals;
 
 struct nv04_devinit_priv {
 	struct nvkm_devinit base;
-	u8 owner;
+	int owner;
 };
 
 int  nv04_devinit_ctor(struct nvkm_object *, struct nvkm_object *,

+ 0 - 1
drivers/gpu/drm/nouveau/nvkm/subdev/fb/Kbuild

@@ -37,7 +37,6 @@ nvkm-y += nvkm/subdev/fb/ramgt215.o
 nvkm-y += nvkm/subdev/fb/rammcp77.o
 nvkm-y += nvkm/subdev/fb/ramgf100.o
 nvkm-y += nvkm/subdev/fb/ramgk104.o
-nvkm-y += nvkm/subdev/fb/ramgk20a.o
 nvkm-y += nvkm/subdev/fb/ramgm107.o
 nvkm-y += nvkm/subdev/fb/sddr2.o
 nvkm-y += nvkm/subdev/fb/sddr3.o

+ 18 - 8
drivers/gpu/drm/nouveau/nvkm/subdev/fb/base.c

@@ -55,9 +55,11 @@ _nvkm_fb_fini(struct nvkm_object *object, bool suspend)
 	struct nvkm_fb *pfb = (void *)object;
 	int ret;
 
-	ret = nv_ofuncs(pfb->ram)->fini(nv_object(pfb->ram), suspend);
-	if (ret && suspend)
-		return ret;
+	if (pfb->ram) {
+		ret = nv_ofuncs(pfb->ram)->fini(nv_object(pfb->ram), suspend);
+		if (ret && suspend)
+			return ret;
+	}
 
 	return nvkm_subdev_fini(&pfb->base, suspend);
 }
@@ -72,9 +74,11 @@ _nvkm_fb_init(struct nvkm_object *object)
 	if (ret)
 		return ret;
 
-	ret = nv_ofuncs(pfb->ram)->init(nv_object(pfb->ram));
-	if (ret)
-		return ret;
+	if (pfb->ram) {
+		ret = nv_ofuncs(pfb->ram)->init(nv_object(pfb->ram));
+		if (ret)
+			return ret;
+	}
 
 	for (i = 0; i < pfb->tile.regions; i++)
 		pfb->tile.prog(pfb, i, &pfb->tile.region[i]);
@@ -91,9 +95,12 @@ _nvkm_fb_dtor(struct nvkm_object *object)
 	for (i = 0; i < pfb->tile.regions; i++)
 		pfb->tile.fini(pfb, i, &pfb->tile.region[i]);
 	nvkm_mm_fini(&pfb->tags);
-	nvkm_mm_fini(&pfb->vram);
 
-	nvkm_object_ref(NULL, (struct nvkm_object **)&pfb->ram);
+	if (pfb->ram) {
+		nvkm_mm_fini(&pfb->vram);
+		nvkm_object_ref(NULL, (struct nvkm_object **)&pfb->ram);
+	}
+
 	nvkm_subdev_destroy(&pfb->base);
 }
 
@@ -127,6 +134,9 @@ nvkm_fb_create_(struct nvkm_object *parent, struct nvkm_object *engine,
 
 	pfb->memtype_valid = impl->memtype;
 
+	if (!impl->ram)
+		return 0;
+
 	ret = nvkm_object_ctor(nv_object(pfb), NULL, impl->ram, NULL, 0, &ram);
 	if (ret) {
 		nv_fatal(pfb, "error detecting memory configuration!!\n");

+ 0 - 1
drivers/gpu/drm/nouveau/nvkm/subdev/fb/gk20a.c

@@ -65,5 +65,4 @@ gk20a_fb_oclass = &(struct nvkm_fb_impl) {
 		.fini = _nvkm_fb_fini,
 	},
 	.memtype = gf100_fb_memtype_valid,
-	.ram = &gk20a_ram_oclass,
 }.base;

+ 0 - 1
drivers/gpu/drm/nouveau/nvkm/subdev/fb/priv.h

@@ -32,7 +32,6 @@ extern struct nvkm_oclass gt215_ram_oclass;
 extern struct nvkm_oclass mcp77_ram_oclass;
 extern struct nvkm_oclass gf100_ram_oclass;
 extern struct nvkm_oclass gk104_ram_oclass;
-extern struct nvkm_oclass gk20a_ram_oclass;
 extern struct nvkm_oclass gm107_ram_oclass;
 
 int nvkm_sddr2_calc(struct nvkm_ram *ram);

+ 0 - 149
drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramgk20a.c

@@ -1,149 +0,0 @@
-/*
- * Copyright (c) 2014, NVIDIA CORPORATION. All rights reserved.
- *
- * 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 AUTHORS OR COPYRIGHT HOLDERS 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.
- */
-#include "priv.h"
-
-#include <core/device.h>
-
-struct gk20a_mem {
-	struct nvkm_mem base;
-	void *cpuaddr;
-	dma_addr_t handle;
-};
-#define to_gk20a_mem(m) container_of(m, struct gk20a_mem, base)
-
-static void
-gk20a_ram_put(struct nvkm_fb *pfb, struct nvkm_mem **pmem)
-{
-	struct device *dev = nv_device_base(nv_device(pfb));
-	struct gk20a_mem *mem = to_gk20a_mem(*pmem);
-
-	*pmem = NULL;
-	if (unlikely(mem == NULL))
-		return;
-
-	if (likely(mem->cpuaddr))
-		dma_free_coherent(dev, mem->base.size << PAGE_SHIFT,
-				  mem->cpuaddr, mem->handle);
-
-	kfree(mem->base.pages);
-	kfree(mem);
-}
-
-static int
-gk20a_ram_get(struct nvkm_fb *pfb, u64 size, u32 align, u32 ncmin,
-	     u32 memtype, struct nvkm_mem **pmem)
-{
-	struct device *dev = nv_device_base(nv_device(pfb));
-	struct gk20a_mem *mem;
-	u32 type = memtype & 0xff;
-	u32 npages, order;
-	int i;
-
-	nv_debug(pfb, "%s: size: %llx align: %x, ncmin: %x\n", __func__, size,
-		 align, ncmin);
-
-	npages = size >> PAGE_SHIFT;
-	if (npages == 0)
-		npages = 1;
-
-	if (align == 0)
-		align = PAGE_SIZE;
-	align >>= PAGE_SHIFT;
-
-	/* round alignment to the next power of 2, if needed */
-	order = fls(align);
-	if ((align & (align - 1)) == 0)
-		order--;
-	align = BIT(order);
-
-	/* ensure returned address is correctly aligned */
-	npages = max(align, npages);
-
-	mem = kzalloc(sizeof(*mem), GFP_KERNEL);
-	if (!mem)
-		return -ENOMEM;
-
-	mem->base.size = npages;
-	mem->base.memtype = type;
-
-	mem->base.pages = kzalloc(sizeof(dma_addr_t) * npages, GFP_KERNEL);
-	if (!mem->base.pages) {
-		kfree(mem);
-		return -ENOMEM;
-	}
-
-	*pmem = &mem->base;
-
-	mem->cpuaddr = dma_alloc_coherent(dev, npages << PAGE_SHIFT,
-					  &mem->handle, GFP_KERNEL);
-	if (!mem->cpuaddr) {
-		nv_error(pfb, "%s: cannot allocate memory!\n", __func__);
-		gk20a_ram_put(pfb, pmem);
-		return -ENOMEM;
-	}
-
-	align <<= PAGE_SHIFT;
-
-	/* alignment check */
-	if (unlikely(mem->handle & (align - 1)))
-		nv_warn(pfb, "memory not aligned as requested: %pad (0x%x)\n",
-			&mem->handle, align);
-
-	nv_debug(pfb, "alloc size: 0x%x, align: 0x%x, paddr: %pad, vaddr: %p\n",
-		 npages << PAGE_SHIFT, align, &mem->handle, mem->cpuaddr);
-
-	for (i = 0; i < npages; i++)
-		mem->base.pages[i] = mem->handle + (PAGE_SIZE * i);
-
-	mem->base.offset = (u64)mem->base.pages[0];
-	return 0;
-}
-
-static int
-gk20a_ram_ctor(struct nvkm_object *parent, struct nvkm_object *engine,
-	       struct nvkm_oclass *oclass, void *data, u32 datasize,
-	       struct nvkm_object **pobject)
-{
-	struct nvkm_ram *ram;
-	int ret;
-
-	ret = nvkm_ram_create(parent, engine, oclass, &ram);
-	*pobject = nv_object(ram);
-	if (ret)
-		return ret;
-	ram->type = NV_MEM_TYPE_STOLEN;
-	ram->size = get_num_physpages() << PAGE_SHIFT;
-
-	ram->get = gk20a_ram_get;
-	ram->put = gk20a_ram_put;
-	return 0;
-}
-
-struct nvkm_oclass
-gk20a_ram_oclass = {
-	.ofuncs = &(struct nvkm_ofuncs) {
-		.ctor = gk20a_ram_ctor,
-		.dtor = _nvkm_ram_dtor,
-		.init = _nvkm_ram_init,
-		.fini = _nvkm_ram_fini,
-	},
-};

+ 1 - 3
drivers/gpu/drm/nouveau/nvkm/subdev/fuse/gm107.c

@@ -45,10 +45,8 @@ gm107_fuse_ctor(struct nvkm_object *parent, struct nvkm_object *engine,
 
 	ret = nvkm_fuse_create(parent, engine, oclass, &priv);
 	*pobject = nv_object(priv);
-	if (ret)
-		return ret;
 
-	return 0;
+	return ret;
 }
 
 struct nvkm_oclass

+ 1 - 0
drivers/gpu/drm/nouveau/nvkm/subdev/instmem/Kbuild

@@ -2,3 +2,4 @@ nvkm-y += nvkm/subdev/instmem/base.o
 nvkm-y += nvkm/subdev/instmem/nv04.o
 nvkm-y += nvkm/subdev/instmem/nv40.o
 nvkm-y += nvkm/subdev/instmem/nv50.o
+nvkm-y += nvkm/subdev/instmem/gk20a.o

+ 440 - 0
drivers/gpu/drm/nouveau/nvkm/subdev/instmem/gk20a.c

@@ -0,0 +1,440 @@
+/*
+ * Copyright (c) 2015, NVIDIA CORPORATION. All rights reserved.
+ *
+ * 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 AUTHORS OR COPYRIGHT HOLDERS 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.
+ */
+
+/*
+ * GK20A does not have dedicated video memory, and to accurately represent this
+ * fact Nouveau will not create a RAM device for it. Therefore its instmem
+ * implementation must be done directly on top of system memory, while providing
+ * coherent read and write operations.
+ *
+ * Instmem can be allocated through two means:
+ * 1) If an IOMMU mapping has been probed, the IOMMU API is used to make memory
+ *    pages contiguous to the GPU. This is the preferred way.
+ * 2) If no IOMMU mapping is probed, the DMA API is used to allocate physically
+ *    contiguous memory.
+ *
+ * In both cases CPU read and writes are performed using PRAMIN (i.e. using the
+ * GPU path) to ensure these operations are coherent for the GPU. This allows us
+ * to use more "relaxed" allocation parameters when using the DMA API, since we
+ * never need a kernel mapping.
+ */
+
+#include <subdev/fb.h>
+#include <core/mm.h>
+#include <core/device.h>
+
+#ifdef __KERNEL__
+#include <linux/dma-attrs.h>
+#include <linux/iommu.h>
+#include <nouveau_platform.h>
+#endif
+
+#include "priv.h"
+
+struct gk20a_instobj_priv {
+	struct nvkm_instobj base;
+	/* Must be second member here - see nouveau_gpuobj_map_vm() */
+	struct nvkm_mem *mem;
+	/* Pointed by mem */
+	struct nvkm_mem _mem;
+};
+
+/*
+ * Used for objects allocated using the DMA API
+ */
+struct gk20a_instobj_dma {
+	struct gk20a_instobj_priv base;
+
+	void *cpuaddr;
+	dma_addr_t handle;
+	struct nvkm_mm_node r;
+};
+
+/*
+ * Used for objects flattened using the IOMMU API
+ */
+struct gk20a_instobj_iommu {
+	struct gk20a_instobj_priv base;
+
+	/* array of base.mem->size pages */
+	struct page *pages[];
+};
+
+struct gk20a_instmem_priv {
+	struct nvkm_instmem base;
+	spinlock_t lock;
+	u64 addr;
+
+	/* Only used if IOMMU if present */
+	struct mutex *mm_mutex;
+	struct nvkm_mm *mm;
+	struct iommu_domain *domain;
+	unsigned long iommu_pgshift;
+
+	/* Only used by DMA API */
+	struct dma_attrs attrs;
+};
+
+/*
+ * Use PRAMIN to read/write data and avoid coherency issues.
+ * PRAMIN uses the GPU path and ensures data will always be coherent.
+ *
+ * A dynamic mapping based solution would be desirable in the future, but
+ * the issue remains of how to maintain coherency efficiently. On ARM it is
+ * not easy (if possible at all?) to create uncached temporary mappings.
+ */
+
+static u32
+gk20a_instobj_rd32(struct nvkm_object *object, u64 offset)
+{
+	struct gk20a_instmem_priv *priv = (void *)nvkm_instmem(object);
+	struct gk20a_instobj_priv *node = (void *)object;
+	unsigned long flags;
+	u64 base = (node->mem->offset + offset) & 0xffffff00000ULL;
+	u64 addr = (node->mem->offset + offset) & 0x000000fffffULL;
+	u32 data;
+
+	spin_lock_irqsave(&priv->lock, flags);
+	if (unlikely(priv->addr != base)) {
+		nv_wr32(priv, 0x001700, base >> 16);
+		priv->addr = base;
+	}
+	data = nv_rd32(priv, 0x700000 + addr);
+	spin_unlock_irqrestore(&priv->lock, flags);
+	return data;
+}
+
+static void
+gk20a_instobj_wr32(struct nvkm_object *object, u64 offset, u32 data)
+{
+	struct gk20a_instmem_priv *priv = (void *)nvkm_instmem(object);
+	struct gk20a_instobj_priv *node = (void *)object;
+	unsigned long flags;
+	u64 base = (node->mem->offset + offset) & 0xffffff00000ULL;
+	u64 addr = (node->mem->offset + offset) & 0x000000fffffULL;
+
+	spin_lock_irqsave(&priv->lock, flags);
+	if (unlikely(priv->addr != base)) {
+		nv_wr32(priv, 0x001700, base >> 16);
+		priv->addr = base;
+	}
+	nv_wr32(priv, 0x700000 + addr, data);
+	spin_unlock_irqrestore(&priv->lock, flags);
+}
+
+static void
+gk20a_instobj_dtor_dma(struct gk20a_instobj_priv *_node)
+{
+	struct gk20a_instobj_dma *node = (void *)_node;
+	struct gk20a_instmem_priv *priv = (void *)nvkm_instmem(node);
+	struct device *dev = nv_device_base(nv_device(priv));
+
+	if (unlikely(!node->cpuaddr))
+		return;
+
+	dma_free_attrs(dev, _node->mem->size << PAGE_SHIFT, node->cpuaddr,
+		       node->handle, &priv->attrs);
+}
+
+static void
+gk20a_instobj_dtor_iommu(struct gk20a_instobj_priv *_node)
+{
+	struct gk20a_instobj_iommu *node = (void *)_node;
+	struct gk20a_instmem_priv *priv = (void *)nvkm_instmem(node);
+	struct nvkm_mm_node *r;
+	int i;
+
+	if (unlikely(list_empty(&_node->mem->regions)))
+		return;
+
+	r = list_first_entry(&_node->mem->regions, struct nvkm_mm_node,
+			     rl_entry);
+
+	/* clear bit 34 to unmap pages */
+	r->offset &= ~BIT(34 - priv->iommu_pgshift);
+
+	/* Unmap pages from GPU address space and free them */
+	for (i = 0; i < _node->mem->size; i++) {
+		iommu_unmap(priv->domain,
+			    (r->offset + i) << priv->iommu_pgshift, PAGE_SIZE);
+		__free_page(node->pages[i]);
+	}
+
+	/* Release area from GPU address space */
+	mutex_lock(priv->mm_mutex);
+	nvkm_mm_free(priv->mm, &r);
+	mutex_unlock(priv->mm_mutex);
+}
+
+static void
+gk20a_instobj_dtor(struct nvkm_object *object)
+{
+	struct gk20a_instobj_priv *node = (void *)object;
+	struct gk20a_instmem_priv *priv = (void *)nvkm_instmem(node);
+
+	if (priv->domain)
+		gk20a_instobj_dtor_iommu(node);
+	else
+		gk20a_instobj_dtor_dma(node);
+
+	nvkm_instobj_destroy(&node->base);
+}
+
+static int
+gk20a_instobj_ctor_dma(struct nvkm_object *parent, struct nvkm_object *engine,
+		       struct nvkm_oclass *oclass, u32 npages, u32 align,
+		       struct gk20a_instobj_priv **_node)
+{
+	struct gk20a_instobj_dma *node;
+	struct gk20a_instmem_priv *priv = (void *)nvkm_instmem(parent);
+	struct device *dev = nv_device_base(nv_device(parent));
+	int ret;
+
+	ret = nvkm_instobj_create_(parent, engine, oclass, sizeof(*node),
+				   (void **)&node);
+	*_node = &node->base;
+	if (ret)
+		return ret;
+
+	node->cpuaddr = dma_alloc_attrs(dev, npages << PAGE_SHIFT,
+					&node->handle, GFP_KERNEL,
+					&priv->attrs);
+	if (!node->cpuaddr) {
+		nv_error(priv, "cannot allocate DMA memory\n");
+		return -ENOMEM;
+	}
+
+	/* alignment check */
+	if (unlikely(node->handle & (align - 1)))
+		nv_warn(priv, "memory not aligned as requested: %pad (0x%x)\n",
+			&node->handle, align);
+
+	/* present memory for being mapped using small pages */
+	node->r.type = 12;
+	node->r.offset = node->handle >> 12;
+	node->r.length = (npages << PAGE_SHIFT) >> 12;
+
+	node->base._mem.offset = node->handle;
+
+	INIT_LIST_HEAD(&node->base._mem.regions);
+	list_add_tail(&node->r.rl_entry, &node->base._mem.regions);
+
+	return 0;
+}
+
+static int
+gk20a_instobj_ctor_iommu(struct nvkm_object *parent, struct nvkm_object *engine,
+			 struct nvkm_oclass *oclass, u32 npages, u32 align,
+			 struct gk20a_instobj_priv **_node)
+{
+	struct gk20a_instobj_iommu *node;
+	struct gk20a_instmem_priv *priv = (void *)nvkm_instmem(parent);
+	struct nvkm_mm_node *r;
+	int ret;
+	int i;
+
+	ret = nvkm_instobj_create_(parent, engine, oclass,
+				sizeof(*node) + sizeof(node->pages[0]) * npages,
+				(void **)&node);
+	*_node = &node->base;
+	if (ret)
+		return ret;
+
+	/* Allocate backing memory */
+	for (i = 0; i < npages; i++) {
+		struct page *p = alloc_page(GFP_KERNEL);
+
+		if (p == NULL) {
+			ret = -ENOMEM;
+			goto free_pages;
+		}
+		node->pages[i] = p;
+	}
+
+	mutex_lock(priv->mm_mutex);
+	/* Reserve area from GPU address space */
+	ret = nvkm_mm_head(priv->mm, 0, 1, npages, npages,
+			   align >> priv->iommu_pgshift, &r);
+	mutex_unlock(priv->mm_mutex);
+	if (ret) {
+		nv_error(priv, "virtual space is full!\n");
+		goto free_pages;
+	}
+
+	/* Map into GPU address space */
+	for (i = 0; i < npages; i++) {
+		struct page *p = node->pages[i];
+		u32 offset = (r->offset + i) << priv->iommu_pgshift;
+
+		ret = iommu_map(priv->domain, offset, page_to_phys(p),
+				PAGE_SIZE, IOMMU_READ | IOMMU_WRITE);
+		if (ret < 0) {
+			nv_error(priv, "IOMMU mapping failure: %d\n", ret);
+
+			while (i-- > 0) {
+				offset -= PAGE_SIZE;
+				iommu_unmap(priv->domain, offset, PAGE_SIZE);
+			}
+			goto release_area;
+		}
+	}
+
+	/* Bit 34 tells that an address is to be resolved through the IOMMU */
+	r->offset |= BIT(34 - priv->iommu_pgshift);
+
+	node->base._mem.offset = ((u64)r->offset) << priv->iommu_pgshift;
+
+	INIT_LIST_HEAD(&node->base._mem.regions);
+	list_add_tail(&r->rl_entry, &node->base._mem.regions);
+
+	return 0;
+
+release_area:
+	mutex_lock(priv->mm_mutex);
+	nvkm_mm_free(priv->mm, &r);
+	mutex_unlock(priv->mm_mutex);
+
+free_pages:
+	for (i = 0; i < npages && node->pages[i] != NULL; i++)
+		__free_page(node->pages[i]);
+
+	return ret;
+}
+
+static int
+gk20a_instobj_ctor(struct nvkm_object *parent, struct nvkm_object *engine,
+		   struct nvkm_oclass *oclass, void *data, u32 _size,
+		   struct nvkm_object **pobject)
+{
+	struct nvkm_instobj_args *args = data;
+	struct gk20a_instmem_priv *priv = (void *)nvkm_instmem(parent);
+	struct gk20a_instobj_priv *node;
+	u32 size, align;
+	int ret;
+
+	nv_debug(parent, "%s (%s): size: %x align: %x\n", __func__,
+		 priv->domain ? "IOMMU" : "DMA", args->size, args->align);
+
+	/* Round size and align to page bounds */
+	size = max(roundup(args->size, PAGE_SIZE), PAGE_SIZE);
+	align = max(roundup(args->align, PAGE_SIZE), PAGE_SIZE);
+
+	if (priv->domain)
+		ret = gk20a_instobj_ctor_iommu(parent, engine, oclass,
+					      size >> PAGE_SHIFT, align, &node);
+	else
+		ret = gk20a_instobj_ctor_dma(parent, engine, oclass,
+					     size >> PAGE_SHIFT, align, &node);
+	*pobject = nv_object(node);
+	if (ret)
+		return ret;
+
+	node->mem = &node->_mem;
+
+	/* present memory for being mapped using small pages */
+	node->mem->size = size >> 12;
+	node->mem->memtype = 0;
+	node->mem->page_shift = 12;
+
+	node->base.addr = node->mem->offset;
+	node->base.size = size;
+
+	nv_debug(parent, "alloc size: 0x%x, align: 0x%x, gaddr: 0x%llx\n",
+		 size, align, node->mem->offset);
+
+	return 0;
+}
+
+static struct nvkm_instobj_impl
+gk20a_instobj_oclass = {
+	.base.ofuncs = &(struct nvkm_ofuncs) {
+		.ctor = gk20a_instobj_ctor,
+		.dtor = gk20a_instobj_dtor,
+		.init = _nvkm_instobj_init,
+		.fini = _nvkm_instobj_fini,
+		.rd32 = gk20a_instobj_rd32,
+		.wr32 = gk20a_instobj_wr32,
+	},
+};
+
+
+
+static int
+gk20a_instmem_fini(struct nvkm_object *object, bool suspend)
+{
+	struct gk20a_instmem_priv *priv = (void *)object;
+	priv->addr = ~0ULL;
+	return nvkm_instmem_fini(&priv->base, suspend);
+}
+
+static int
+gk20a_instmem_ctor(struct nvkm_object *parent, struct nvkm_object *engine,
+		   struct nvkm_oclass *oclass, void *data, u32 size,
+		   struct nvkm_object **pobject)
+{
+	struct gk20a_instmem_priv *priv;
+	struct nouveau_platform_device *plat;
+	int ret;
+
+	ret = nvkm_instmem_create(parent, engine, oclass, &priv);
+	*pobject = nv_object(priv);
+	if (ret)
+		return ret;
+
+	spin_lock_init(&priv->lock);
+
+	plat = nv_device_to_platform(nv_device(parent));
+	if (plat->gpu->iommu.domain) {
+		priv->domain = plat->gpu->iommu.domain;
+		priv->mm = plat->gpu->iommu.mm;
+		priv->iommu_pgshift = plat->gpu->iommu.pgshift;
+		priv->mm_mutex = &plat->gpu->iommu.mutex;
+
+		nv_info(priv, "using IOMMU\n");
+	} else {
+		init_dma_attrs(&priv->attrs);
+		/*
+		 * We will access instmem through PRAMIN and thus do not need a
+		 * consistent CPU pointer or kernel mapping
+		 */
+		dma_set_attr(DMA_ATTR_NON_CONSISTENT, &priv->attrs);
+		dma_set_attr(DMA_ATTR_WEAK_ORDERING, &priv->attrs);
+		dma_set_attr(DMA_ATTR_WRITE_COMBINE, &priv->attrs);
+		dma_set_attr(DMA_ATTR_NO_KERNEL_MAPPING, &priv->attrs);
+
+		nv_info(priv, "using DMA API\n");
+	}
+
+	return 0;
+}
+
+struct nvkm_oclass *
+gk20a_instmem_oclass = &(struct nvkm_instmem_impl) {
+	.base.handle = NV_SUBDEV(INSTMEM, 0xea),
+	.base.ofuncs = &(struct nvkm_ofuncs) {
+		.ctor = gk20a_instmem_ctor,
+		.dtor = _nvkm_instmem_dtor,
+		.init = _nvkm_instmem_init,
+		.fini = gk20a_instmem_fini,
+	},
+	.instobj = &gk20a_instobj_oclass.base,
+}.base;

+ 9 - 1
drivers/gpu/drm/nouveau/nvkm/subdev/ltc/gf100.c

@@ -136,7 +136,8 @@ gf100_ltc_dtor(struct nvkm_object *object)
 	struct nvkm_ltc_priv *priv = (void *)object;
 
 	nvkm_mm_fini(&priv->tags);
-	nvkm_mm_free(&pfb->vram, &priv->tag_ram);
+	if (pfb->ram)
+		nvkm_mm_free(&pfb->vram, &priv->tag_ram);
 
 	nvkm_ltc_destroy(priv);
 }
@@ -149,6 +150,12 @@ gf100_ltc_init_tag_ram(struct nvkm_fb *pfb, struct nvkm_ltc_priv *priv)
 	u32 tag_size, tag_margin, tag_align;
 	int ret;
 
+	/* No VRAM, no tags for now. */
+	if (!pfb->ram) {
+		priv->num_tags = 0;
+		goto mm_init;
+	}
+
 	/* tags for 1/4 of VRAM should be enough (8192/4 per GiB of VRAM) */
 	priv->num_tags = (pfb->ram->size >> 17) / 4;
 	if (priv->num_tags > (1 << 17))
@@ -183,6 +190,7 @@ gf100_ltc_init_tag_ram(struct nvkm_fb *pfb, struct nvkm_ltc_priv *priv)
 		priv->tag_base = tag_base;
 	}
 
+mm_init:
 	ret = nvkm_mm_init(&priv->tags, 0, priv->num_tags, 1);
 	return ret;
 }

+ 1 - 1
drivers/gpu/drm/nouveau/nvkm/subdev/mxm/nv50.c

@@ -182,7 +182,7 @@ mxm_show_unmatched(struct nvkm_mxm *mxm, u8 *data, void *info)
 {
 	u64 desc = *(u64 *)data;
 	if ((desc & 0xf0) != 0xf0)
-	nv_info(mxm, "unmatched output device 0x%016llx\n", desc);
+		nv_info(mxm, "unmatched output device 0x%016llx\n", desc);
 	return true;
 }
 

+ 1 - 0
drivers/gpu/drm/nouveau/nvkm/subdev/pmu/Kbuild

@@ -4,5 +4,6 @@ nvkm-y += nvkm/subdev/pmu/gt215.o
 nvkm-y += nvkm/subdev/pmu/gf100.o
 nvkm-y += nvkm/subdev/pmu/gf110.o
 nvkm-y += nvkm/subdev/pmu/gk104.o
+nvkm-y += nvkm/subdev/pmu/gk110.o
 nvkm-y += nvkm/subdev/pmu/gk208.o
 nvkm-y += nvkm/subdev/pmu/gk20a.o

+ 95 - 0
drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gk110.c

@@ -0,0 +1,95 @@
+/*
+ * Copyright 2015 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 gf110_pmu_code gk110_pmu_code
+#define gf110_pmu_data gk110_pmu_data
+#include "priv.h"
+#include "fuc/gf110.fuc4.h"
+
+#include <subdev/timer.h>
+
+void
+gk110_pmu_pgob(struct nvkm_pmu *pmu, bool enable)
+{
+	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(pmu, 0x000200, 0x00001000, 0x00000000);
+	nv_rd32(pmu, 0x000200);
+	nv_mask(pmu, 0x000200, 0x08000000, 0x08000000);
+	msleep(50);
+
+	nv_mask(pmu, 0x10a78c, 0x00000002, 0x00000002);
+	nv_mask(pmu, 0x10a78c, 0x00000001, 0x00000001);
+	nv_mask(pmu, 0x10a78c, 0x00000001, 0x00000000);
+
+	nv_mask(pmu, 0x0206b4, 0x00000000, 0x00000000);
+	for (i = 0; i < ARRAY_SIZE(magic); i++) {
+		nv_wr32(pmu, magic[i].addr, magic[i].data);
+		nv_wait(pmu, magic[i].addr, 0x80000000, 0x00000000);
+	}
+
+	nv_mask(pmu, 0x10a78c, 0x00000002, 0x00000000);
+	nv_mask(pmu, 0x10a78c, 0x00000001, 0x00000001);
+	nv_mask(pmu, 0x10a78c, 0x00000001, 0x00000000);
+
+	nv_mask(pmu, 0x000200, 0x08000000, 0x00000000);
+	nv_mask(pmu, 0x000200, 0x00001000, 0x00001000);
+	nv_rd32(pmu, 0x000200);
+}
+
+struct nvkm_oclass *
+gk110_pmu_oclass = &(struct nvkm_pmu_impl) {
+	.base.handle = NV_SUBDEV(PMU, 0xf0),
+	.base.ofuncs = &(struct nvkm_ofuncs) {
+		.ctor = _nvkm_pmu_ctor,
+		.dtor = _nvkm_pmu_dtor,
+		.init = _nvkm_pmu_init,
+		.fini = _nvkm_pmu_fini,
+	},
+	.code.data = gk110_pmu_code,
+	.code.size = sizeof(gk110_pmu_code),
+	.data.data = gk110_pmu_data,
+	.data.size = sizeof(gk110_pmu_data),
+	.pgob = gk110_pmu_pgob,
+}.base;

+ 1 - 0
drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gk208.c

@@ -37,4 +37,5 @@ gk208_pmu_oclass = &(struct nvkm_pmu_impl) {
 	.code.size = sizeof(gk208_pmu_code),
 	.data.data = gk208_pmu_data,
 	.data.size = sizeof(gk208_pmu_data),
+	.pgob = gk110_pmu_pgob,
 }.base;

+ 4 - 3
drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gk20a.c

@@ -159,7 +159,7 @@ resched:
 	nvkm_timer_alarm(priv, 100000000, alarm);
 }
 
-int
+static int
 gk20a_pmu_fini(struct nvkm_object *object, bool suspend)
 {
 	struct nvkm_pmu *pmu = (void *)object;
@@ -170,7 +170,7 @@ gk20a_pmu_fini(struct nvkm_object *object, bool suspend)
 	return nvkm_subdev_fini(&pmu->base, suspend);
 }
 
-int
+static int
 gk20a_pmu_init(struct nvkm_object *object)
 {
 	struct nvkm_pmu *pmu = (void *)object;
@@ -192,7 +192,8 @@ gk20a_pmu_init(struct nvkm_object *object)
 	return ret;
 }
 
-struct gk20a_pmu_dvfs_data gk20a_dvfs_data= {
+static struct gk20a_pmu_dvfs_data
+gk20a_dvfs_data= {
 	.p_load_target = 70,
 	.p_load_max = 90,
 	.p_smooth = 1,

+ 2 - 0
drivers/gpu/drm/nouveau/nvkm/subdev/pmu/priv.h

@@ -40,4 +40,6 @@ struct nvkm_pmu_impl {
 
 	void (*pgob)(struct nvkm_pmu *, bool);
 };
+
+void gk110_pmu_pgob(struct nvkm_pmu *, bool);
 #endif

+ 1 - 0
include/uapi/drm/nouveau_drm.h

@@ -39,6 +39,7 @@
 #define NOUVEAU_GEM_DOMAIN_VRAM      (1 << 1)
 #define NOUVEAU_GEM_DOMAIN_GART      (1 << 2)
 #define NOUVEAU_GEM_DOMAIN_MAPPABLE  (1 << 3)
+#define NOUVEAU_GEM_DOMAIN_COHERENT  (1 << 4)
 
 #define NOUVEAU_GEM_TILE_COMP        0x00030000 /* nv50-only */
 #define NOUVEAU_GEM_TILE_LAYOUT_MASK 0x0000ff00