Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 56ac7475 authored by Ben Skeggs's avatar Ben Skeggs
Browse files

drm/nv50: implement possible workaround for NV86 PGRAPH TLB flush hang



Signed-off-by: default avatarBen Skeggs <bskeggs@redhat.com>
parent 06ef3e61
Loading
Loading
Loading
Loading
+5 −0
Original line number Original line Diff line number Diff line
@@ -307,6 +307,7 @@ struct nouveau_fifo_engine {
	void (*destroy_context)(struct nouveau_channel *);
	void (*destroy_context)(struct nouveau_channel *);
	int  (*load_context)(struct nouveau_channel *);
	int  (*load_context)(struct nouveau_channel *);
	int  (*unload_context)(struct drm_device *);
	int  (*unload_context)(struct drm_device *);
	void (*tlb_flush)(struct drm_device *dev);
};
};


struct nouveau_pgraph_object_method {
struct nouveau_pgraph_object_method {
@@ -339,6 +340,7 @@ struct nouveau_pgraph_engine {
	void (*destroy_context)(struct nouveau_channel *);
	void (*destroy_context)(struct nouveau_channel *);
	int  (*load_context)(struct nouveau_channel *);
	int  (*load_context)(struct nouveau_channel *);
	int  (*unload_context)(struct drm_device *);
	int  (*unload_context)(struct drm_device *);
	void (*tlb_flush)(struct drm_device *dev);


	void (*set_region_tiling)(struct drm_device *dev, int i, uint32_t addr,
	void (*set_region_tiling)(struct drm_device *dev, int i, uint32_t addr,
				  uint32_t size, uint32_t pitch);
				  uint32_t size, uint32_t pitch);
@@ -1014,6 +1016,7 @@ extern int nv50_fifo_create_context(struct nouveau_channel *);
extern void nv50_fifo_destroy_context(struct nouveau_channel *);
extern void nv50_fifo_destroy_context(struct nouveau_channel *);
extern int  nv50_fifo_load_context(struct nouveau_channel *);
extern int  nv50_fifo_load_context(struct nouveau_channel *);
extern int  nv50_fifo_unload_context(struct drm_device *);
extern int  nv50_fifo_unload_context(struct drm_device *);
extern void nv50_fifo_tlb_flush(struct drm_device *dev);


/* nvc0_fifo.c */
/* nvc0_fifo.c */
extern int  nvc0_fifo_init(struct drm_device *);
extern int  nvc0_fifo_init(struct drm_device *);
@@ -1091,6 +1094,8 @@ extern int nv50_graph_load_context(struct nouveau_channel *);
extern int  nv50_graph_unload_context(struct drm_device *);
extern int  nv50_graph_unload_context(struct drm_device *);
extern void nv50_graph_context_switch(struct drm_device *);
extern void nv50_graph_context_switch(struct drm_device *);
extern int  nv50_grctx_init(struct nouveau_grctx *);
extern int  nv50_grctx_init(struct nouveau_grctx *);
extern void nv50_graph_tlb_flush(struct drm_device *dev);
extern void nv86_graph_tlb_flush(struct drm_device *dev);


/* nvc0_graph.c */
/* nvc0_graph.c */
extern int  nvc0_graph_init(struct drm_device *);
extern int  nvc0_graph_init(struct drm_device *);
+6 −8
Original line number Original line Diff line number Diff line
@@ -175,11 +175,10 @@ nv50_mem_vm_bind_linear(struct drm_device *dev, uint64_t virt, uint32_t size,
			}
			}
		}
		}
	}
	}
	dev_priv->engine.instmem.flush(dev);


	nv50_vm_flush(dev, 5);
	dev_priv->engine.instmem.flush(dev);
	nv50_vm_flush(dev, 0);
	dev_priv->engine.fifo.tlb_flush(dev);
	nv50_vm_flush(dev, 4);
	dev_priv->engine.graph.tlb_flush(dev);
	nv50_vm_flush(dev, 6);
	nv50_vm_flush(dev, 6);
	return 0;
	return 0;
}
}
@@ -209,11 +208,10 @@ nv50_mem_vm_unbind(struct drm_device *dev, uint64_t virt, uint32_t size)
			pte++;
			pte++;
		}
		}
	}
	}
	dev_priv->engine.instmem.flush(dev);


	nv50_vm_flush(dev, 5);
	dev_priv->engine.instmem.flush(dev);
	nv50_vm_flush(dev, 0);
	dev_priv->engine.fifo.tlb_flush(dev);
	nv50_vm_flush(dev, 4);
	dev_priv->engine.graph.tlb_flush(dev);
	nv50_vm_flush(dev, 6);
	nv50_vm_flush(dev, 6);
}
}


+4 −4
Original line number Original line Diff line number Diff line
@@ -120,8 +120,8 @@ nouveau_sgdma_bind(struct ttm_backend *be, struct ttm_mem_reg *mem)
	dev_priv->engine.instmem.flush(nvbe->dev);
	dev_priv->engine.instmem.flush(nvbe->dev);


	if (dev_priv->card_type == NV_50) {
	if (dev_priv->card_type == NV_50) {
		nv50_vm_flush(dev, 5); /* PGRAPH */
		dev_priv->engine.fifo.tlb_flush(dev);
		nv50_vm_flush(dev, 0); /* PFIFO */
		dev_priv->engine.graph.tlb_flush(dev);
	}
	}


	nvbe->bound = true;
	nvbe->bound = true;
@@ -162,8 +162,8 @@ nouveau_sgdma_unbind(struct ttm_backend *be)
	dev_priv->engine.instmem.flush(nvbe->dev);
	dev_priv->engine.instmem.flush(nvbe->dev);


	if (dev_priv->card_type == NV_50) {
	if (dev_priv->card_type == NV_50) {
		nv50_vm_flush(dev, 5);
		dev_priv->engine.fifo.tlb_flush(dev);
		nv50_vm_flush(dev, 0);
		dev_priv->engine.graph.tlb_flush(dev);
	}
	}


	nvbe->bound = false;
	nvbe->bound = false;
+10 −0
Original line number Original line Diff line number Diff line
@@ -354,6 +354,15 @@ static int nouveau_init_engine_ptrs(struct drm_device *dev)
		engine->graph.destroy_context	= nv50_graph_destroy_context;
		engine->graph.destroy_context	= nv50_graph_destroy_context;
		engine->graph.load_context	= nv50_graph_load_context;
		engine->graph.load_context	= nv50_graph_load_context;
		engine->graph.unload_context	= nv50_graph_unload_context;
		engine->graph.unload_context	= nv50_graph_unload_context;
		if (dev_priv->chipset != 0x86)
			engine->graph.tlb_flush	= nv50_graph_tlb_flush;
		else {
			/* from what i can see nvidia do this on every
			 * pre-NVA3 board except NVAC, but, we've only
			 * ever seen problems on NV86
			 */
			engine->graph.tlb_flush	= nv86_graph_tlb_flush;
		}
		engine->fifo.channels		= 128;
		engine->fifo.channels		= 128;
		engine->fifo.init		= nv50_fifo_init;
		engine->fifo.init		= nv50_fifo_init;
		engine->fifo.takedown		= nv50_fifo_takedown;
		engine->fifo.takedown		= nv50_fifo_takedown;
@@ -365,6 +374,7 @@ static int nouveau_init_engine_ptrs(struct drm_device *dev)
		engine->fifo.destroy_context	= nv50_fifo_destroy_context;
		engine->fifo.destroy_context	= nv50_fifo_destroy_context;
		engine->fifo.load_context	= nv50_fifo_load_context;
		engine->fifo.load_context	= nv50_fifo_load_context;
		engine->fifo.unload_context	= nv50_fifo_unload_context;
		engine->fifo.unload_context	= nv50_fifo_unload_context;
		engine->fifo.tlb_flush		= nv50_fifo_tlb_flush;
		engine->display.early_init	= nv50_display_early_init;
		engine->display.early_init	= nv50_display_early_init;
		engine->display.late_takedown	= nv50_display_late_takedown;
		engine->display.late_takedown	= nv50_display_late_takedown;
		engine->display.create		= nv50_display_create;
		engine->display.create		= nv50_display_create;
+5 −0
Original line number Original line Diff line number Diff line
@@ -464,3 +464,8 @@ nv50_fifo_unload_context(struct drm_device *dev)
	return 0;
	return 0;
}
}


void
nv50_fifo_tlb_flush(struct drm_device *dev)
{
	nv50_vm_flush(dev, 5);
}
Loading