Commit 274fec93 authored by Ben Skeggs's avatar Ben Skeggs

drm/nouveau: tidy+move PGRAPH ISRs to their respective *_graph.c files

Reviewed-by: default avatarFrancisco Jerez <currojerez@riseup.net>
Signed-off-by: default avatarBen Skeggs <bskeggs@redhat.com>
parent 5178d40d
...@@ -54,6 +54,7 @@ struct nouveau_fpriv { ...@@ -54,6 +54,7 @@ struct nouveau_fpriv {
#include "nouveau_drm.h" #include "nouveau_drm.h"
#include "nouveau_reg.h" #include "nouveau_reg.h"
#include "nouveau_bios.h" #include "nouveau_bios.h"
#include "nouveau_util.h"
struct nouveau_grctx; struct nouveau_grctx;
#define MAX_NUM_DCB_ENTRIES 16 #define MAX_NUM_DCB_ENTRIES 16
...@@ -872,6 +873,7 @@ extern int nouveau_gpuobj_mthd_new(struct drm_device *, u32 class, u32 mthd, ...@@ -872,6 +873,7 @@ extern int nouveau_gpuobj_mthd_new(struct drm_device *, u32 class, u32 mthd,
int (*exec)(struct nouveau_channel *, int (*exec)(struct nouveau_channel *,
u32 class, u32 mthd, u32 data)); u32 class, u32 mthd, u32 data));
extern int nouveau_gpuobj_mthd_call(struct nouveau_channel *, u32, u32, u32); extern int nouveau_gpuobj_mthd_call(struct nouveau_channel *, u32, u32, u32);
extern int nouveau_gpuobj_mthd_call2(struct drm_device *, int, u32, u32, u32);
extern int nouveau_gpuobj_channel_init(struct nouveau_channel *, extern int nouveau_gpuobj_channel_init(struct nouveau_channel *,
uint32_t vram_h, uint32_t tt_h); uint32_t vram_h, uint32_t tt_h);
extern void nouveau_gpuobj_channel_takedown(struct nouveau_channel *); extern void nouveau_gpuobj_channel_takedown(struct nouveau_channel *);
...@@ -1110,9 +1112,9 @@ extern int nv04_graph_create_context(struct nouveau_channel *); ...@@ -1110,9 +1112,9 @@ extern int nv04_graph_create_context(struct nouveau_channel *);
extern void nv04_graph_destroy_context(struct nouveau_channel *); extern void nv04_graph_destroy_context(struct nouveau_channel *);
extern int nv04_graph_load_context(struct nouveau_channel *); extern int nv04_graph_load_context(struct nouveau_channel *);
extern int nv04_graph_unload_context(struct drm_device *); extern int nv04_graph_unload_context(struct drm_device *);
extern void nv04_graph_context_switch(struct drm_device *);
extern int nv04_graph_mthd_page_flip(struct nouveau_channel *chan, extern int nv04_graph_mthd_page_flip(struct nouveau_channel *chan,
u32 class, u32 mthd, u32 data); u32 class, u32 mthd, u32 data);
extern struct nouveau_bitfield nv04_graph_nsource[];
/* nv10_graph.c */ /* nv10_graph.c */
extern int nv10_graph_init(struct drm_device *); extern int nv10_graph_init(struct drm_device *);
...@@ -1122,8 +1124,9 @@ extern int nv10_graph_create_context(struct nouveau_channel *); ...@@ -1122,8 +1124,9 @@ extern int nv10_graph_create_context(struct nouveau_channel *);
extern void nv10_graph_destroy_context(struct nouveau_channel *); extern void nv10_graph_destroy_context(struct nouveau_channel *);
extern int nv10_graph_load_context(struct nouveau_channel *); extern int nv10_graph_load_context(struct nouveau_channel *);
extern int nv10_graph_unload_context(struct drm_device *); extern int nv10_graph_unload_context(struct drm_device *);
extern void nv10_graph_context_switch(struct drm_device *);
extern void nv10_graph_set_tile_region(struct drm_device *dev, int i); extern void nv10_graph_set_tile_region(struct drm_device *dev, int i);
extern struct nouveau_bitfield nv10_graph_intr[];
extern struct nouveau_bitfield nv10_graph_nstatus[];
/* nv20_graph.c */ /* nv20_graph.c */
extern int nv20_graph_create_context(struct nouveau_channel *); extern int nv20_graph_create_context(struct nouveau_channel *);
...@@ -1155,7 +1158,6 @@ extern int nv50_graph_create_context(struct nouveau_channel *); ...@@ -1155,7 +1158,6 @@ extern int nv50_graph_create_context(struct nouveau_channel *);
extern void nv50_graph_destroy_context(struct nouveau_channel *); extern void nv50_graph_destroy_context(struct nouveau_channel *);
extern int nv50_graph_load_context(struct nouveau_channel *); 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 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 nv50_graph_tlb_flush(struct drm_device *dev);
extern void nv86_graph_tlb_flush(struct drm_device *dev); extern void nv86_graph_tlb_flush(struct drm_device *dev);
......
This diff is collapsed.
...@@ -113,6 +113,24 @@ nouveau_gpuobj_mthd_call(struct nouveau_channel *chan, ...@@ -113,6 +113,24 @@ nouveau_gpuobj_mthd_call(struct nouveau_channel *chan,
return -ENOENT; return -ENOENT;
} }
int
nouveau_gpuobj_mthd_call2(struct drm_device *dev, int chid,
u32 class, u32 mthd, u32 data)
{
struct drm_nouveau_private *dev_priv = dev->dev_private;
struct nouveau_channel *chan = NULL;
unsigned long flags;
int ret = -EINVAL;
spin_lock_irqsave(&dev_priv->channels.lock, flags);
if (chid > 0 && chid < dev_priv->engine.fifo.channels)
chan = dev_priv->channels.ptr[chid];
if (chan)
ret = nouveau_gpuobj_mthd_call(chan, class, mthd, data);
spin_unlock_irqrestore(&dev_priv->channels.lock, flags);
return ret;
}
/* NVidia uses context objects to drive drawing operations. /* NVidia uses context objects to drive drawing operations.
Context objects can be selected into 8 subchannels in the FIFO, Context objects can be selected into 8 subchannels in the FIFO,
......
...@@ -27,8 +27,10 @@ ...@@ -27,8 +27,10 @@
#include "nouveau_drm.h" #include "nouveau_drm.h"
#include "nouveau_drv.h" #include "nouveau_drv.h"
#include "nouveau_hw.h" #include "nouveau_hw.h"
#include "nouveau_util.h"
static int nv04_graph_register(struct drm_device *dev); static int nv04_graph_register(struct drm_device *dev);
static void nv04_graph_isr(struct drm_device *dev);
static uint32_t nv04_graph_ctx_regs[] = { static uint32_t nv04_graph_ctx_regs[] = {
0x0040053c, 0x0040053c,
...@@ -363,7 +365,7 @@ nv04_graph_channel(struct drm_device *dev) ...@@ -363,7 +365,7 @@ nv04_graph_channel(struct drm_device *dev)
return dev_priv->channels.ptr[chid]; return dev_priv->channels.ptr[chid];
} }
void static void
nv04_graph_context_switch(struct drm_device *dev) nv04_graph_context_switch(struct drm_device *dev)
{ {
struct drm_nouveau_private *dev_priv = dev->dev_private; struct drm_nouveau_private *dev_priv = dev->dev_private;
...@@ -498,6 +500,7 @@ int nv04_graph_init(struct drm_device *dev) ...@@ -498,6 +500,7 @@ int nv04_graph_init(struct drm_device *dev)
return ret; return ret;
/* Enable PGRAPH interrupts */ /* Enable PGRAPH interrupts */
nouveau_irq_register(dev, 12, nv04_graph_isr);
nv_wr32(dev, NV03_PGRAPH_INTR, 0xFFFFFFFF); nv_wr32(dev, NV03_PGRAPH_INTR, 0xFFFFFFFF);
nv_wr32(dev, NV03_PGRAPH_INTR_EN, 0xFFFFFFFF); nv_wr32(dev, NV03_PGRAPH_INTR_EN, 0xFFFFFFFF);
...@@ -533,6 +536,8 @@ int nv04_graph_init(struct drm_device *dev) ...@@ -533,6 +536,8 @@ int nv04_graph_init(struct drm_device *dev)
void nv04_graph_takedown(struct drm_device *dev) void nv04_graph_takedown(struct drm_device *dev)
{ {
nv_wr32(dev, NV03_PGRAPH_INTR_EN, 0x00000000);
nouveau_irq_unregister(dev, 12);
} }
void void
...@@ -1224,3 +1229,89 @@ nv04_graph_register(struct drm_device *dev) ...@@ -1224,3 +1229,89 @@ nv04_graph_register(struct drm_device *dev)
dev_priv->engine.graph.registered = true; dev_priv->engine.graph.registered = true;
return 0; return 0;
}; };
static struct nouveau_bitfield nv04_graph_intr[] = {
{ NV_PGRAPH_INTR_NOTIFY, "NOTIFY" },
{}
};
static struct nouveau_bitfield nv04_graph_nstatus[] =
{
{ NV04_PGRAPH_NSTATUS_STATE_IN_USE, "STATE_IN_USE" },
{ NV04_PGRAPH_NSTATUS_INVALID_STATE, "INVALID_STATE" },
{ NV04_PGRAPH_NSTATUS_BAD_ARGUMENT, "BAD_ARGUMENT" },
{ NV04_PGRAPH_NSTATUS_PROTECTION_FAULT, "PROTECTION_FAULT" },
{}
};
struct nouveau_bitfield nv04_graph_nsource[] =
{
{ NV03_PGRAPH_NSOURCE_NOTIFICATION, "NOTIFICATION" },
{ NV03_PGRAPH_NSOURCE_DATA_ERROR, "DATA_ERROR" },
{ NV03_PGRAPH_NSOURCE_PROTECTION_ERROR, "PROTECTION_ERROR" },
{ NV03_PGRAPH_NSOURCE_RANGE_EXCEPTION, "RANGE_EXCEPTION" },
{ NV03_PGRAPH_NSOURCE_LIMIT_COLOR, "LIMIT_COLOR" },
{ NV03_PGRAPH_NSOURCE_LIMIT_ZETA, "LIMIT_ZETA" },
{ NV03_PGRAPH_NSOURCE_ILLEGAL_MTHD, "ILLEGAL_MTHD" },
{ NV03_PGRAPH_NSOURCE_DMA_R_PROTECTION, "DMA_R_PROTECTION" },
{ NV03_PGRAPH_NSOURCE_DMA_W_PROTECTION, "DMA_W_PROTECTION" },
{ NV03_PGRAPH_NSOURCE_FORMAT_EXCEPTION, "FORMAT_EXCEPTION" },
{ NV03_PGRAPH_NSOURCE_PATCH_EXCEPTION, "PATCH_EXCEPTION" },
{ NV03_PGRAPH_NSOURCE_STATE_INVALID, "STATE_INVALID" },
{ NV03_PGRAPH_NSOURCE_DOUBLE_NOTIFY, "DOUBLE_NOTIFY" },
{ NV03_PGRAPH_NSOURCE_NOTIFY_IN_USE, "NOTIFY_IN_USE" },
{ NV03_PGRAPH_NSOURCE_METHOD_CNT, "METHOD_CNT" },
{ NV03_PGRAPH_NSOURCE_BFR_NOTIFICATION, "BFR_NOTIFICATION" },
{ NV03_PGRAPH_NSOURCE_DMA_VTX_PROTECTION, "DMA_VTX_PROTECTION" },
{ NV03_PGRAPH_NSOURCE_DMA_WIDTH_A, "DMA_WIDTH_A" },
{ NV03_PGRAPH_NSOURCE_DMA_WIDTH_B, "DMA_WIDTH_B" },
{}
};
static void
nv04_graph_isr(struct drm_device *dev)
{
u32 stat;
while ((stat = nv_rd32(dev, NV03_PGRAPH_INTR))) {
u32 nsource = nv_rd32(dev, NV03_PGRAPH_NSOURCE);
u32 nstatus = nv_rd32(dev, NV03_PGRAPH_NSTATUS);
u32 addr = nv_rd32(dev, NV04_PGRAPH_TRAPPED_ADDR);
u32 chid = (addr & 0x0f000000) >> 24;
u32 subc = (addr & 0x0000e000) >> 13;
u32 mthd = (addr & 0x00001ffc);
u32 data = nv_rd32(dev, NV04_PGRAPH_TRAPPED_DATA);
u32 class = nv_rd32(dev, 0x400180 + subc * 4) & 0xff;
u32 show = stat;
if (stat & NV_PGRAPH_INTR_NOTIFY) {
if (nsource & NV03_PGRAPH_NSOURCE_ILLEGAL_MTHD) {
if (!nouveau_gpuobj_mthd_call2(dev, chid, class, mthd, data))
show &= ~NV_PGRAPH_INTR_NOTIFY;
}
}
if (stat & NV_PGRAPH_INTR_CONTEXT_SWITCH) {
nv_wr32(dev, NV03_PGRAPH_INTR, NV_PGRAPH_INTR_CONTEXT_SWITCH);
stat &= ~NV_PGRAPH_INTR_CONTEXT_SWITCH;
show &= ~NV_PGRAPH_INTR_CONTEXT_SWITCH;
nv04_graph_context_switch(dev);
}
nv_wr32(dev, NV03_PGRAPH_INTR, stat);
nv_wr32(dev, NV04_PGRAPH_FIFO, 0x00000001);
if (show && nouveau_ratelimit()) {
NV_INFO(dev, "PGRAPH -");
nouveau_bitfield_print(nv04_graph_intr, show);
printk(" nsource:");
nouveau_bitfield_print(nv04_graph_nsource, nsource);
printk(" nstatus:");
nouveau_bitfield_print(nv04_graph_nstatus, nstatus);
printk("\n");
NV_INFO(dev, "PGRAPH - ch %d/%d class 0x%04x "
"mthd 0x%04x data 0x%08x\n",
chid, subc, class, mthd, data);
}
}
}
...@@ -26,8 +26,10 @@ ...@@ -26,8 +26,10 @@
#include "drm.h" #include "drm.h"
#include "nouveau_drm.h" #include "nouveau_drm.h"
#include "nouveau_drv.h" #include "nouveau_drv.h"
#include "nouveau_util.h"
static int nv10_graph_register(struct drm_device *); static int nv10_graph_register(struct drm_device *);
static void nv10_graph_isr(struct drm_device *);
#define NV10_FIFO_NUMBER 32 #define NV10_FIFO_NUMBER 32
...@@ -788,7 +790,7 @@ nv10_graph_unload_context(struct drm_device *dev) ...@@ -788,7 +790,7 @@ nv10_graph_unload_context(struct drm_device *dev)
return 0; return 0;
} }
void static void
nv10_graph_context_switch(struct drm_device *dev) nv10_graph_context_switch(struct drm_device *dev)
{ {
struct drm_nouveau_private *dev_priv = dev->dev_private; struct drm_nouveau_private *dev_priv = dev->dev_private;
...@@ -924,6 +926,7 @@ int nv10_graph_init(struct drm_device *dev) ...@@ -924,6 +926,7 @@ int nv10_graph_init(struct drm_device *dev)
if (ret) if (ret)
return ret; return ret;
nouveau_irq_register(dev, 12, nv10_graph_isr);
nv_wr32(dev, NV03_PGRAPH_INTR , 0xFFFFFFFF); nv_wr32(dev, NV03_PGRAPH_INTR , 0xFFFFFFFF);
nv_wr32(dev, NV03_PGRAPH_INTR_EN, 0xFFFFFFFF); nv_wr32(dev, NV03_PGRAPH_INTR_EN, 0xFFFFFFFF);
...@@ -966,6 +969,8 @@ int nv10_graph_init(struct drm_device *dev) ...@@ -966,6 +969,8 @@ int nv10_graph_init(struct drm_device *dev)
void nv10_graph_takedown(struct drm_device *dev) void nv10_graph_takedown(struct drm_device *dev)
{ {
nv_wr32(dev, NV03_PGRAPH_INTR_EN, 0x00000000);
nouveau_irq_unregister(dev, 12);
} }
static int static int
...@@ -1117,3 +1122,66 @@ nv10_graph_register(struct drm_device *dev) ...@@ -1117,3 +1122,66 @@ nv10_graph_register(struct drm_device *dev)
dev_priv->engine.graph.registered = true; dev_priv->engine.graph.registered = true;
return 0; return 0;
} }
struct nouveau_bitfield nv10_graph_intr[] = {
{ NV_PGRAPH_INTR_NOTIFY, "NOTIFY" },
{ NV_PGRAPH_INTR_ERROR, "ERROR" },
{}
};
struct nouveau_bitfield nv10_graph_nstatus[] =
{
{ NV10_PGRAPH_NSTATUS_STATE_IN_USE, "STATE_IN_USE" },
{ NV10_PGRAPH_NSTATUS_INVALID_STATE, "INVALID_STATE" },
{ NV10_PGRAPH_NSTATUS_BAD_ARGUMENT, "BAD_ARGUMENT" },
{ NV10_PGRAPH_NSTATUS_PROTECTION_FAULT, "PROTECTION_FAULT" },
{}
};
static void
nv10_graph_isr(struct drm_device *dev)
{
u32 stat;
while ((stat = nv_rd32(dev, NV03_PGRAPH_INTR))) {
u32 nsource = nv_rd32(dev, NV03_PGRAPH_NSOURCE);
u32 nstatus = nv_rd32(dev, NV03_PGRAPH_NSTATUS);
u32 addr = nv_rd32(dev, NV04_PGRAPH_TRAPPED_ADDR);
u32 chid = (addr & 0x01f00000) >> 20;
u32 subc = (addr & 0x00070000) >> 16;
u32 mthd = (addr & 0x00001ffc);
u32 data = nv_rd32(dev, NV04_PGRAPH_TRAPPED_DATA);
u32 class = nv_rd32(dev, 0x400160 + subc * 4) & 0xfff;
u32 show = stat;
if (stat & NV_PGRAPH_INTR_ERROR) {
if (nsource & NV03_PGRAPH_NSOURCE_ILLEGAL_MTHD) {
if (!nouveau_gpuobj_mthd_call2(dev, chid, class, mthd, data))
show &= ~NV_PGRAPH_INTR_ERROR;
}
}
if (stat & NV_PGRAPH_INTR_CONTEXT_SWITCH) {
nv_wr32(dev, NV03_PGRAPH_INTR, NV_PGRAPH_INTR_CONTEXT_SWITCH);
stat &= ~NV_PGRAPH_INTR_CONTEXT_SWITCH;
show &= ~NV_PGRAPH_INTR_CONTEXT_SWITCH;
nv10_graph_context_switch(dev);
}
nv_wr32(dev, NV03_PGRAPH_INTR, stat);
nv_wr32(dev, NV04_PGRAPH_FIFO, 0x00000001);
if (show && nouveau_ratelimit()) {
NV_INFO(dev, "PGRAPH -");
nouveau_bitfield_print(nv10_graph_intr, show);
printk(" nsource:");
nouveau_bitfield_print(nv04_graph_nsource, nsource);
printk(" nstatus:");
nouveau_bitfield_print(nv10_graph_nstatus, nstatus);
printk("\n");
NV_INFO(dev, "PGRAPH - ch %d/%d class 0x%04x "
"mthd 0x%04x data 0x%08x\n",
chid, subc, class, mthd, data);
}
}
}
...@@ -34,6 +34,7 @@ ...@@ -34,6 +34,7 @@
static int nv20_graph_register(struct drm_device *); static int nv20_graph_register(struct drm_device *);
static int nv30_graph_register(struct drm_device *); static int nv30_graph_register(struct drm_device *);
static void nv20_graph_isr(struct drm_device *);
static void static void
nv20_graph_context_init(struct drm_device *dev, struct nouveau_gpuobj *ctx) nv20_graph_context_init(struct drm_device *dev, struct nouveau_gpuobj *ctx)
...@@ -584,6 +585,7 @@ nv20_graph_init(struct drm_device *dev) ...@@ -584,6 +585,7 @@ nv20_graph_init(struct drm_device *dev)
return ret; return ret;
} }
nouveau_irq_register(dev, 12, nv20_graph_isr);
nv_wr32(dev, NV03_PGRAPH_INTR , 0xFFFFFFFF); nv_wr32(dev, NV03_PGRAPH_INTR , 0xFFFFFFFF);
nv_wr32(dev, NV03_PGRAPH_INTR_EN, 0xFFFFFFFF); nv_wr32(dev, NV03_PGRAPH_INTR_EN, 0xFFFFFFFF);
...@@ -661,6 +663,9 @@ nv20_graph_takedown(struct drm_device *dev) ...@@ -661,6 +663,9 @@ nv20_graph_takedown(struct drm_device *dev)
struct drm_nouveau_private *dev_priv = dev->dev_private; struct drm_nouveau_private *dev_priv = dev->dev_private;
struct nouveau_pgraph_engine *pgraph = &dev_priv->engine.graph; struct nouveau_pgraph_engine *pgraph = &dev_priv->engine.graph;
nv_wr32(dev, NV03_PGRAPH_INTR_EN, 0x00000000);
nouveau_irq_unregister(dev, 12);
nouveau_gpuobj_ref(NULL, &pgraph->ctx_table); nouveau_gpuobj_ref(NULL, &pgraph->ctx_table);
} }
...@@ -712,6 +717,7 @@ nv30_graph_init(struct drm_device *dev) ...@@ -712,6 +717,7 @@ nv30_graph_init(struct drm_device *dev)
nv_wr32(dev, NV20_PGRAPH_CHANNEL_CTX_TABLE, nv_wr32(dev, NV20_PGRAPH_CHANNEL_CTX_TABLE,
pgraph->ctx_table->pinst >> 4); pgraph->ctx_table->pinst >> 4);
nouveau_irq_register(dev, 12, nv20_graph_isr);
nv_wr32(dev, NV03_PGRAPH_INTR , 0xFFFFFFFF); nv_wr32(dev, NV03_PGRAPH_INTR , 0xFFFFFFFF);
nv_wr32(dev, NV03_PGRAPH_INTR_EN, 0xFFFFFFFF); nv_wr32(dev, NV03_PGRAPH_INTR_EN, 0xFFFFFFFF);
...@@ -850,3 +856,44 @@ nv30_graph_register(struct drm_device *dev) ...@@ -850,3 +856,44 @@ nv30_graph_register(struct drm_device *dev)
dev_priv->engine.graph.registered = true; dev_priv->engine.graph.registered = true;
return 0; return 0;
} }
static void
nv20_graph_isr(struct drm_device *dev)
{
u32 stat;
while ((stat = nv_rd32(dev, NV03_PGRAPH_INTR))) {
u32 nsource = nv_rd32(dev, NV03_PGRAPH_NSOURCE);
u32 nstatus = nv_rd32(dev, NV03_PGRAPH_NSTATUS);
u32 addr = nv_rd32(dev, NV04_PGRAPH_TRAPPED_ADDR);
u32 chid = (addr & 0x01f00000) >> 20;
u32 subc = (addr & 0x00070000) >> 16;
u32 mthd = (addr & 0x00001ffc);
u32 data = nv_rd32(dev, NV04_PGRAPH_TRAPPED_DATA);
u32 class = nv_rd32(dev, 0x400160 + subc * 4) & 0xfff;
u32 show = stat;
if (stat & NV_PGRAPH_INTR_ERROR) {
if (nsource & NV03_PGRAPH_NSOURCE_ILLEGAL_MTHD) {
if (!nouveau_gpuobj_mthd_call2(dev, chid, class, mthd, data))
show &= ~NV_PGRAPH_INTR_ERROR;
}
}
nv_wr32(dev, NV03_PGRAPH_INTR, stat);
nv_wr32(dev, NV04_PGRAPH_FIFO, 0x00000001);
if (show && nouveau_ratelimit()) {
NV_INFO(dev, "PGRAPH -");
nouveau_bitfield_print(nv10_graph_intr, show);
printk(" nsource:");
nouveau_bitfield_print(nv04_graph_nsource, nsource);
printk(" nstatus:");
nouveau_bitfield_print(nv10_graph_nstatus, nstatus);
printk("\n");
NV_INFO(dev, "PGRAPH - ch %d/%d class 0x%04x "
"mthd 0x%04x data 0x%08x\n",
chid, subc, class, mthd, data);
}
}
}
...@@ -30,6 +30,7 @@ ...@@ -30,6 +30,7 @@
#include "nouveau_grctx.h" #include "nouveau_grctx.h"
static int nv40_graph_register(struct drm_device *); static int nv40_graph_register(struct drm_device *);
static void nv40_graph_isr(struct drm_device *);
struct nouveau_channel * struct nouveau_channel *
nv40_graph_channel(struct drm_device *dev) nv40_graph_channel(struct drm_device *dev)
...@@ -277,6 +278,7 @@ nv40_graph_init(struct drm_device *dev) ...@@ -277,6 +278,7 @@ nv40_graph_init(struct drm_device *dev)
/* No context present currently */ /* No context present currently */
nv_wr32(dev, NV40_PGRAPH_CTXCTL_CUR, 0x00000000); nv_wr32(dev, NV40_PGRAPH_CTXCTL_CUR, 0x00000000);
nouveau_irq_register(dev, 12, nv40_graph_isr);
nv_wr32(dev, NV03_PGRAPH_INTR , 0xFFFFFFFF); nv_wr32(dev, NV03_PGRAPH_INTR , 0xFFFFFFFF);
nv_wr32(dev, NV40_PGRAPH_INTR_EN, 0xFFFFFFFF); nv_wr32(dev, NV40_PGRAPH_INTR_EN, 0xFFFFFFFF);
...@@ -408,6 +410,7 @@ nv40_graph_init(struct drm_device *dev) ...@@ -408,6 +410,7 @@ nv40_graph_init(struct drm_device *dev)
void nv40_graph_takedown(struct drm_device *dev) void nv40_graph_takedown(struct drm_device *dev)
{ {
nouveau_irq_unregister(dev, 12);
} }
static int static int
...@@ -449,3 +452,69 @@ nv40_graph_register(struct drm_device *dev) ...@@ -449,3 +452,69 @@ nv40_graph_register(struct drm_device *dev)
dev_priv->engine.graph.registered = true; dev_priv->engine.graph.registered = true;
return 0; return 0;
} }
static int
nv40_graph_isr_chid(struct drm_device *dev, u32 inst)
{
struct drm_nouveau_private *dev_priv = dev->dev_private;
struct nouveau_channel *chan;
unsigned long flags;
int i;
spin_lock_irqsave(&dev_priv->channels.lock, flags);
for (i = 0; i < dev_priv->engine.fifo.channels; i++) {
chan = dev_priv->channels.ptr[i];
if (!chan || !chan->ramin_grctx)
continue;
if (inst == chan->ramin_grctx->pinst)
break;
}
spin_unlock_irqrestore(&dev_priv->channels.lock, flags);
return i;
}
static void
nv40_graph_isr(struct drm_device *dev)
{
u32 stat;
while ((stat = nv_rd32(dev, NV03_PGRAPH_INTR))) {
u32 nsource = nv_rd32(dev, NV03_PGRAPH_NSOURCE);
u32 nstatus = nv_rd32(dev, NV03_PGRAPH_NSTATUS);
u32 inst = (nv_rd32(dev, 0x40032c) & 0x000fffff) << 4;
u32 chid = nv40_graph_isr_chid(dev, inst);
u32 addr = nv_rd32(dev, NV04_PGRAPH_TRAPPED_ADDR);
u32 subc = (addr & 0x00070000) >> 16;
u32 mthd = (addr & 0x00001ffc);
u32 data = nv_rd32(dev, NV04_PGRAPH_TRAPPED_DATA);
u32 class = nv_rd32(dev, 0x400160 + subc * 4) & 0xffff;
u32 show = stat;
if (stat & NV_PGRAPH_INTR_ERROR) {
if (nsource & NV03_PGRAPH_NSOURCE_ILLEGAL_MTHD) {
if (!nouveau_gpuobj_mthd_call2(dev, chid, class, mthd, data))
show &= ~NV_PGRAPH_INTR_ERROR;
} else
if (nsource & NV03_PGRAPH_NSOURCE_DMA_VTX_PROTECTION) {
nv_mask(dev, 0x402000, 0, 0);
}
}
nv_wr32(dev, NV03_PGRAPH_INTR, stat);
nv_wr32(dev, NV04_PGRAPH_FIFO, 0x00000001);
if (show && nouveau_ratelimit()) {
NV_INFO(dev, "PGRAPH -");
nouveau_bitfield_print(nv10_graph_intr, show);
printk(" nsource:");
nouveau_bitfield_print(nv04_graph_nsource, nsource);
printk(" nstatus:");
nouveau_bitfield_print(nv10_graph_nstatus, nstatus);
printk("\n");
NV_INFO(dev, "PGRAPH - ch %d (0x%08x) subc %d "
"class 0x%04x mthd 0x%04x data 0x%08x\n",
chid, inst, subc, class, mthd, data);
}
}
}
This diff is collapsed.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment