nouveau: add workaround for nv86 hw bug
This commit is contained in:
parent
030d3b3b4b
commit
df57a85a75
|
@ -0,0 +1,229 @@
|
|||
From ad3ff4f72ef7fa1e559cc835535025a4b5a746e6 Mon Sep 17 00:00:00 2001
|
||||
From: Ben Skeggs <bskeggs@redhat.com>
|
||||
Date: Fri, 22 Oct 2010 10:26:24 +1000
|
||||
Subject: [PATCH] drm/nv50: implement possible workaround for NV86 PGRAPH TLB flush hang
|
||||
|
||||
Signed-off-by: Ben Skeggs <bskeggs@redhat.com>
|
||||
---
|
||||
drivers/gpu/drm/nouveau/nouveau_drv.h | 5 +++
|
||||
drivers/gpu/drm/nouveau/nouveau_mem.c | 14 +++-----
|
||||
drivers/gpu/drm/nouveau/nouveau_sgdma.c | 8 ++--
|
||||
drivers/gpu/drm/nouveau/nouveau_state.c | 10 ++++++
|
||||
drivers/gpu/drm/nouveau/nv50_fifo.c | 5 +++
|
||||
drivers/gpu/drm/nouveau/nv50_graph.c | 52 +++++++++++++++++++++++++++++++
|
||||
drivers/gpu/drm/nouveau/nv50_instmem.c | 1 -
|
||||
7 files changed, 82 insertions(+), 13 deletions(-)
|
||||
|
||||
diff --git a/drivers/gpu/drm/nouveau/nouveau_drv.h b/drivers/gpu/drm/nouveau/nouveau_drv.h
|
||||
index 88b5093..14236b8 100644
|
||||
--- a/drivers/gpu/drm/nouveau/nouveau_drv.h
|
||||
+++ b/drivers/gpu/drm/nouveau/nouveau_drv.h
|
||||
@@ -314,6 +314,7 @@ struct nouveau_fifo_engine {
|
||||
void (*destroy_context)(struct nouveau_channel *);
|
||||
int (*load_context)(struct nouveau_channel *);
|
||||
int (*unload_context)(struct drm_device *);
|
||||
+ void (*tlb_flush)(struct drm_device *dev);
|
||||
};
|
||||
|
||||
struct nouveau_pgraph_object_method {
|
||||
@@ -346,6 +347,7 @@ struct nouveau_pgraph_engine {
|
||||
void (*destroy_context)(struct nouveau_channel *);
|
||||
int (*load_context)(struct nouveau_channel *);
|
||||
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,
|
||||
uint32_t size, uint32_t pitch);
|
||||
@@ -943,6 +945,7 @@ extern int nv50_fifo_create_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_unload_context(struct drm_device *);
|
||||
+extern void nv50_fifo_tlb_flush(struct drm_device *dev);
|
||||
|
||||
/* nv04_graph.c */
|
||||
extern struct nouveau_pgraph_object_class nv04_graph_grclass[];
|
||||
@@ -1007,6 +1010,8 @@ extern int nv50_graph_load_context(struct nouveau_channel *);
|
||||
extern int nv50_graph_unload_context(struct drm_device *);
|
||||
extern void nv50_graph_context_switch(struct drm_device *);
|
||||
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);
|
||||
|
||||
/* nv04_instmem.c */
|
||||
extern int nv04_instmem_init(struct drm_device *);
|
||||
diff --git a/drivers/gpu/drm/nouveau/nouveau_mem.c b/drivers/gpu/drm/nouveau/nouveau_mem.c
|
||||
index 09db6f6..de43b3e 100644
|
||||
--- a/drivers/gpu/drm/nouveau/nouveau_mem.c
|
||||
+++ b/drivers/gpu/drm/nouveau/nouveau_mem.c
|
||||
@@ -174,11 +174,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);
|
||||
- nv50_vm_flush(dev, 0);
|
||||
- nv50_vm_flush(dev, 4);
|
||||
+ dev_priv->engine.instmem.flush(dev);
|
||||
+ dev_priv->engine.fifo.tlb_flush(dev);
|
||||
+ dev_priv->engine.graph.tlb_flush(dev);
|
||||
nv50_vm_flush(dev, 6);
|
||||
return 0;
|
||||
}
|
||||
@@ -206,11 +205,10 @@ nv50_mem_vm_unbind(struct drm_device *dev, uint64_t virt, uint32_t size)
|
||||
while (pte < end)
|
||||
nv_wo32(dev, pgt, pte++, 0);
|
||||
}
|
||||
- dev_priv->engine.instmem.flush(dev);
|
||||
|
||||
- nv50_vm_flush(dev, 5);
|
||||
- nv50_vm_flush(dev, 0);
|
||||
- nv50_vm_flush(dev, 4);
|
||||
+ dev_priv->engine.instmem.flush(dev);
|
||||
+ dev_priv->engine.fifo.tlb_flush(dev);
|
||||
+ dev_priv->engine.graph.tlb_flush(dev);
|
||||
nv50_vm_flush(dev, 6);
|
||||
}
|
||||
|
||||
diff --git a/drivers/gpu/drm/nouveau/nouveau_sgdma.c b/drivers/gpu/drm/nouveau/nouveau_sgdma.c
|
||||
index 491767f..ae9f353 100644
|
||||
--- a/drivers/gpu/drm/nouveau/nouveau_sgdma.c
|
||||
+++ b/drivers/gpu/drm/nouveau/nouveau_sgdma.c
|
||||
@@ -118,8 +118,8 @@ nouveau_sgdma_bind(struct ttm_backend *be, struct ttm_mem_reg *mem)
|
||||
dev_priv->engine.instmem.flush(nvbe->dev);
|
||||
|
||||
if (dev_priv->card_type == NV_50) {
|
||||
- nv50_vm_flush(dev, 5); /* PGRAPH */
|
||||
- nv50_vm_flush(dev, 0); /* PFIFO */
|
||||
+ dev_priv->engine.fifo.tlb_flush(dev);
|
||||
+ dev_priv->engine.graph.tlb_flush(dev);
|
||||
}
|
||||
|
||||
nvbe->bound = true;
|
||||
@@ -158,8 +158,8 @@ nouveau_sgdma_unbind(struct ttm_backend *be)
|
||||
dev_priv->engine.instmem.flush(nvbe->dev);
|
||||
|
||||
if (dev_priv->card_type == NV_50) {
|
||||
- nv50_vm_flush(dev, 5);
|
||||
- nv50_vm_flush(dev, 0);
|
||||
+ dev_priv->engine.fifo.tlb_flush(dev);
|
||||
+ dev_priv->engine.graph.tlb_flush(dev);
|
||||
}
|
||||
|
||||
nvbe->bound = false;
|
||||
diff --git a/drivers/gpu/drm/nouveau/nouveau_state.c b/drivers/gpu/drm/nouveau/nouveau_state.c
|
||||
index 866f437..32a9d81 100644
|
||||
--- a/drivers/gpu/drm/nouveau/nouveau_state.c
|
||||
+++ b/drivers/gpu/drm/nouveau/nouveau_state.c
|
||||
@@ -283,6 +283,15 @@ static int nouveau_init_engine_ptrs(struct drm_device *dev)
|
||||
engine->graph.destroy_context = nv50_graph_destroy_context;
|
||||
engine->graph.load_context = nv50_graph_load_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.init = nv50_fifo_init;
|
||||
engine->fifo.takedown = nv50_fifo_takedown;
|
||||
@@ -294,6 +303,7 @@ static int nouveau_init_engine_ptrs(struct drm_device *dev)
|
||||
engine->fifo.destroy_context = nv50_fifo_destroy_context;
|
||||
engine->fifo.load_context = nv50_fifo_load_context;
|
||||
engine->fifo.unload_context = nv50_fifo_unload_context;
|
||||
+ engine->fifo.tlb_flush = nv50_fifo_tlb_flush;
|
||||
break;
|
||||
default:
|
||||
NV_ERROR(dev, "NV%02x unsupported\n", dev_priv->chipset);
|
||||
diff --git a/drivers/gpu/drm/nouveau/nv50_fifo.c b/drivers/gpu/drm/nouveau/nv50_fifo.c
|
||||
index fb0281a..3c1cfde 100644
|
||||
--- a/drivers/gpu/drm/nouveau/nv50_fifo.c
|
||||
+++ b/drivers/gpu/drm/nouveau/nv50_fifo.c
|
||||
@@ -464,3 +464,8 @@ nv50_fifo_unload_context(struct drm_device *dev)
|
||||
return 0;
|
||||
}
|
||||
|
||||
+void
|
||||
+nv50_fifo_tlb_flush(struct drm_device *dev)
|
||||
+{
|
||||
+ nv50_vm_flush(dev, 5);
|
||||
+}
|
||||
diff --git a/drivers/gpu/drm/nouveau/nv50_graph.c b/drivers/gpu/drm/nouveau/nv50_graph.c
|
||||
index 1413028..8bdbbe4 100644
|
||||
--- a/drivers/gpu/drm/nouveau/nv50_graph.c
|
||||
+++ b/drivers/gpu/drm/nouveau/nv50_graph.c
|
||||
@@ -403,3 +403,55 @@ struct nouveau_pgraph_object_class nv50_graph_grclass[] = {
|
||||
{ 0x8597, false, NULL }, /* tesla (nva3, nva5, nva8) */
|
||||
{}
|
||||
};
|
||||
+
|
||||
+void
|
||||
+nv50_graph_tlb_flush(struct drm_device *dev)
|
||||
+{
|
||||
+ nv50_vm_flush(dev, 0);
|
||||
+}
|
||||
+
|
||||
+void
|
||||
+nv86_graph_tlb_flush(struct drm_device *dev)
|
||||
+{
|
||||
+ struct drm_nouveau_private *dev_priv = dev->dev_private;
|
||||
+ struct nouveau_timer_engine *ptimer = &dev_priv->engine.timer;
|
||||
+ bool idle, timeout = false;
|
||||
+ unsigned long flags;
|
||||
+ u64 start;
|
||||
+ u32 tmp;
|
||||
+
|
||||
+ spin_lock_irqsave(&dev_priv->context_switch_lock, flags);
|
||||
+ nv_mask(dev, 0x400500, 0x00000001, 0x00000000);
|
||||
+
|
||||
+ start = ptimer->read(dev);
|
||||
+ do {
|
||||
+ idle = true;
|
||||
+
|
||||
+ for (tmp = nv_rd32(dev, 0x400380); tmp && idle; tmp >>= 3) {
|
||||
+ if ((tmp & 7) == 1)
|
||||
+ idle = false;
|
||||
+ }
|
||||
+
|
||||
+ for (tmp = nv_rd32(dev, 0x400384); tmp && idle; tmp >>= 3) {
|
||||
+ if ((tmp & 7) == 1)
|
||||
+ idle = false;
|
||||
+ }
|
||||
+
|
||||
+ for (tmp = nv_rd32(dev, 0x400388); tmp && idle; tmp >>= 3) {
|
||||
+ if ((tmp & 7) == 1)
|
||||
+ idle = false;
|
||||
+ }
|
||||
+ } while (!idle && !(timeout = ptimer->read(dev) - start > 2000000000));
|
||||
+
|
||||
+ if (timeout) {
|
||||
+ NV_ERROR(dev, "PGRAPH TLB flush idle timeout fail: "
|
||||
+ "0x%08x 0x%08x 0x%08x 0x%08x\n",
|
||||
+ nv_rd32(dev, 0x400700), nv_rd32(dev, 0x400380),
|
||||
+ nv_rd32(dev, 0x400384), nv_rd32(dev, 0x400388));
|
||||
+ }
|
||||
+
|
||||
+ nv50_vm_flush(dev, 0);
|
||||
+
|
||||
+ nv_mask(dev, 0x400500, 0x00000001, 0x00000001);
|
||||
+ spin_unlock_irqrestore(&dev_priv->context_switch_lock, flags);
|
||||
+}
|
||||
diff --git a/drivers/gpu/drm/nouveau/nv50_instmem.c b/drivers/gpu/drm/nouveau/nv50_instmem.c
|
||||
index 0c8a6f2..42fcc65 100644
|
||||
--- a/drivers/gpu/drm/nouveau/nv50_instmem.c
|
||||
+++ b/drivers/gpu/drm/nouveau/nv50_instmem.c
|
||||
@@ -453,7 +453,6 @@ nv50_instmem_bind(struct drm_device *dev, struct nouveau_gpuobj *gpuobj)
|
||||
}
|
||||
dev_priv->engine.instmem.flush(dev);
|
||||
|
||||
- nv50_vm_flush(dev, 4);
|
||||
nv50_vm_flush(dev, 6);
|
||||
|
||||
gpuobj->im_bound = 1;
|
||||
--
|
||||
1.7.3.1
|
||||
|
|
@ -669,13 +669,13 @@ Patch1808: drm-ttm-fix.patch
|
|||
Patch1810: drm-nouveau-updates.patch
|
||||
Patch1811: drm-nouveau-race-fix.patch
|
||||
Patch1812: drm-nouveau-nva3-noaccel.patch
|
||||
Patch1813: drm-nouveau-nv86-bug.patch
|
||||
Patch1819: drm-intel-big-hammer.patch
|
||||
# intel drm is all merged upstream
|
||||
Patch1824: drm-intel-next.patch
|
||||
# make sure the lvds comes back on lid open
|
||||
Patch1825: drm-intel-make-lvds-work.patch
|
||||
Patch1900: linux-2.6-intel-iommu-igfx.patch
|
||||
|
||||
Patch2000: efifb-add-more-models.patch
|
||||
Patch2001: efifb-check-that-the-base-addr-is-plausible-on-pci-systems.patch
|
||||
|
||||
|
@ -1334,6 +1334,7 @@ ApplyPatch drm-ttm-fix.patch
|
|||
ApplyPatch drm-nouveau-updates.patch
|
||||
ApplyPatch drm-nouveau-race-fix.patch
|
||||
ApplyPatch drm-nouveau-nva3-noaccel.patch
|
||||
ApplyPatch drm-nouveau-nv86-bug.patch
|
||||
|
||||
ApplyPatch drm-intel-big-hammer.patch
|
||||
ApplyOptionalPatch drm-intel-next.patch
|
||||
|
|
Loading…
Reference in New Issue