You've already forked linux-apfs
mirror of
https://github.com/linux-apfs/linux-apfs.git
synced 2026-05-01 15:00:59 -07:00
drm/nv50: Improve PGRAPH interrupt handling.
This makes nouveau recognise and report more kinds of PGRAPH errors, as well as prevent GPU lockups resulting from some of them. Lots of guesswork was involved and some part of this is probably incorrect. Some potential-lockuop situations are handled by just resetting a whole PGRAPH subunit, which doesn't sound like a "proper" solution, but seems to work just fine... for now. Signed-off-by: Marcin Kościelnicki <koriakin@0x04.net> Signed-off-by: Ben Skeggs <bskeggs@redhat.com>
This commit is contained in:
committed by
Ben Skeggs
parent
3bf777bf0a
commit
304424e17d
@@ -12,7 +12,7 @@ nouveau-y := nouveau_drv.o nouveau_state.o nouveau_channel.o nouveau_mem.o \
|
||||
nouveau_dp.o nouveau_grctx.o \
|
||||
nv04_timer.o \
|
||||
nv04_mc.o nv40_mc.o nv50_mc.o \
|
||||
nv04_fb.o nv10_fb.o nv40_fb.o \
|
||||
nv04_fb.o nv10_fb.o nv40_fb.o nv50_fb.o \
|
||||
nv04_fifo.o nv10_fifo.o nv40_fifo.o nv50_fifo.o \
|
||||
nv04_graph.o nv10_graph.o nv20_graph.o \
|
||||
nv40_graph.o nv50_graph.o \
|
||||
|
||||
@@ -930,6 +930,10 @@ extern void nv40_fb_takedown(struct drm_device *);
|
||||
extern void nv40_fb_set_region_tiling(struct drm_device *, int, uint32_t,
|
||||
uint32_t, uint32_t);
|
||||
|
||||
/* nv50_fb.c */
|
||||
extern int nv50_fb_init(struct drm_device *);
|
||||
extern void nv50_fb_takedown(struct drm_device *);
|
||||
|
||||
/* nv04_fifo.c */
|
||||
extern int nv04_fifo_init(struct drm_device *);
|
||||
extern void nv04_fifo_disable(struct drm_device *);
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -34,7 +34,6 @@
|
||||
#include "nouveau_drm.h"
|
||||
#include "nv50_display.h"
|
||||
|
||||
static int nouveau_stub_init(struct drm_device *dev) { return 0; }
|
||||
static void nouveau_stub_takedown(struct drm_device *dev) {}
|
||||
|
||||
static int nouveau_init_engine_ptrs(struct drm_device *dev)
|
||||
@@ -276,8 +275,8 @@ static int nouveau_init_engine_ptrs(struct drm_device *dev)
|
||||
engine->timer.init = nv04_timer_init;
|
||||
engine->timer.read = nv04_timer_read;
|
||||
engine->timer.takedown = nv04_timer_takedown;
|
||||
engine->fb.init = nouveau_stub_init;
|
||||
engine->fb.takedown = nouveau_stub_takedown;
|
||||
engine->fb.init = nv50_fb_init;
|
||||
engine->fb.takedown = nv50_fb_takedown;
|
||||
engine->graph.grclass = nv50_graph_grclass;
|
||||
engine->graph.init = nv50_graph_init;
|
||||
engine->graph.takedown = nv50_graph_takedown;
|
||||
|
||||
@@ -0,0 +1,32 @@
|
||||
#include "drmP.h"
|
||||
#include "drm.h"
|
||||
#include "nouveau_drv.h"
|
||||
#include "nouveau_drm.h"
|
||||
|
||||
int
|
||||
nv50_fb_init(struct drm_device *dev)
|
||||
{
|
||||
/* This is needed to get meaningful information from 100c90
|
||||
* on traps. No idea what these values mean exactly. */
|
||||
struct drm_nouveau_private *dev_priv = dev->dev_private;
|
||||
|
||||
switch (dev_priv->chipset) {
|
||||
case 0x50:
|
||||
nv_wr32(dev, 0x100c90, 0x0707ff);
|
||||
break;
|
||||
case 0xa5:
|
||||
case 0xa8:
|
||||
nv_wr32(dev, 0x100c90, 0x0d0fff);
|
||||
break;
|
||||
default:
|
||||
nv_wr32(dev, 0x100c90, 0x1d07ff);
|
||||
break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
nv50_fb_takedown(struct drm_device *dev)
|
||||
{
|
||||
}
|
||||
@@ -56,6 +56,10 @@ nv50_graph_init_intr(struct drm_device *dev)
|
||||
static void
|
||||
nv50_graph_init_regs__nv(struct drm_device *dev)
|
||||
{
|
||||
struct drm_nouveau_private *dev_priv = dev->dev_private;
|
||||
uint32_t units = nv_rd32(dev, 0x1540);
|
||||
int i;
|
||||
|
||||
NV_DEBUG(dev, "\n");
|
||||
|
||||
nv_wr32(dev, 0x400804, 0xc0000000);
|
||||
@@ -65,6 +69,20 @@ nv50_graph_init_regs__nv(struct drm_device *dev)
|
||||
nv_wr32(dev, 0x405018, 0xc0000000);
|
||||
nv_wr32(dev, 0x402000, 0xc0000000);
|
||||
|
||||
for (i = 0; i < 16; i++) {
|
||||
if (units & 1 << i) {
|
||||
if (dev_priv->chipset < 0xa0) {
|
||||
nv_wr32(dev, 0x408900 + (i << 12), 0xc0000000);
|
||||
nv_wr32(dev, 0x408e08 + (i << 12), 0xc0000000);
|
||||
nv_wr32(dev, 0x408314 + (i << 12), 0xc0000000);
|
||||
} else {
|
||||
nv_wr32(dev, 0x408600 + (i << 11), 0xc0000000);
|
||||
nv_wr32(dev, 0x408708 + (i << 11), 0xc0000000);
|
||||
nv_wr32(dev, 0x40831c + (i << 11), 0xc0000000);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
nv_wr32(dev, 0x400108, 0xffffffff);
|
||||
|
||||
nv_wr32(dev, 0x400824, 0x00004000);
|
||||
|
||||
@@ -274,7 +274,7 @@ nv50_graph_construct_mmio(struct nouveau_grctx *ctx)
|
||||
int offset, base;
|
||||
uint32_t units = nv_rd32 (ctx->dev, 0x1540);
|
||||
|
||||
/* 0800 */
|
||||
/* 0800: DISPATCH */
|
||||
cp_ctx(ctx, 0x400808, 7);
|
||||
gr_def(ctx, 0x400814, 0x00000030);
|
||||
cp_ctx(ctx, 0x400834, 0x32);
|
||||
@@ -305,7 +305,7 @@ nv50_graph_construct_mmio(struct nouveau_grctx *ctx)
|
||||
gr_def(ctx, 0x400b20, 0x0001629d);
|
||||
}
|
||||
|
||||
/* 0C00 */
|
||||
/* 0C00: VFETCH */
|
||||
cp_ctx(ctx, 0x400c08, 0x2);
|
||||
gr_def(ctx, 0x400c08, 0x0000fe0c);
|
||||
|
||||
@@ -331,7 +331,7 @@ nv50_graph_construct_mmio(struct nouveau_grctx *ctx)
|
||||
cp_ctx(ctx, 0x401540, 0x5);
|
||||
gr_def(ctx, 0x401550, 0x00001018);
|
||||
|
||||
/* 1800 */
|
||||
/* 1800: STREAMOUT */
|
||||
cp_ctx(ctx, 0x401814, 0x1);
|
||||
gr_def(ctx, 0x401814, 0x000000ff);
|
||||
if (dev_priv->chipset == 0x50) {
|
||||
@@ -646,7 +646,7 @@ nv50_graph_construct_mmio(struct nouveau_grctx *ctx)
|
||||
if (dev_priv->chipset == 0x50)
|
||||
cp_ctx(ctx, 0x4063e0, 0x1);
|
||||
|
||||
/* 6800 */
|
||||
/* 6800: M2MF */
|
||||
if (dev_priv->chipset < 0x90) {
|
||||
cp_ctx(ctx, 0x406814, 0x2b);
|
||||
gr_def(ctx, 0x406818, 0x00000f80);
|
||||
|
||||
Reference in New Issue
Block a user