aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/nouveau/nv04_graph.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/gpu/drm/nouveau/nv04_graph.c')
-rw-r--r--drivers/gpu/drm/nouveau/nv04_graph.c95
1 files changed, 93 insertions, 2 deletions
diff --git a/drivers/gpu/drm/nouveau/nv04_graph.c b/drivers/gpu/drm/nouveau/nv04_graph.c
index 239519aefce6..0bc616d35eb6 100644
--- a/drivers/gpu/drm/nouveau/nv04_graph.c
+++ b/drivers/gpu/drm/nouveau/nv04_graph.c
@@ -27,8 +27,10 @@
27#include "nouveau_drm.h" 27#include "nouveau_drm.h"
28#include "nouveau_drv.h" 28#include "nouveau_drv.h"
29#include "nouveau_hw.h" 29#include "nouveau_hw.h"
30#include "nouveau_util.h"
30 31
31static int nv04_graph_register(struct drm_device *dev); 32static int nv04_graph_register(struct drm_device *dev);
33static void nv04_graph_isr(struct drm_device *dev);
32 34
33static uint32_t nv04_graph_ctx_regs[] = { 35static uint32_t nv04_graph_ctx_regs[] = {
34 0x0040053c, 36 0x0040053c,
@@ -363,7 +365,7 @@ nv04_graph_channel(struct drm_device *dev)
363 return dev_priv->channels.ptr[chid]; 365 return dev_priv->channels.ptr[chid];
364} 366}
365 367
366void 368static void
367nv04_graph_context_switch(struct drm_device *dev) 369nv04_graph_context_switch(struct drm_device *dev)
368{ 370{
369 struct drm_nouveau_private *dev_priv = dev->dev_private; 371 struct drm_nouveau_private *dev_priv = dev->dev_private;
@@ -498,6 +500,7 @@ int nv04_graph_init(struct drm_device *dev)
498 return ret; 500 return ret;
499 501
500 /* Enable PGRAPH interrupts */ 502 /* Enable PGRAPH interrupts */
503 nouveau_irq_register(dev, 12, nv04_graph_isr);
501 nv_wr32(dev, NV03_PGRAPH_INTR, 0xFFFFFFFF); 504 nv_wr32(dev, NV03_PGRAPH_INTR, 0xFFFFFFFF);
502 nv_wr32(dev, NV03_PGRAPH_INTR_EN, 0xFFFFFFFF); 505 nv_wr32(dev, NV03_PGRAPH_INTR_EN, 0xFFFFFFFF);
503 506
@@ -533,6 +536,8 @@ int nv04_graph_init(struct drm_device *dev)
533 536
534void nv04_graph_takedown(struct drm_device *dev) 537void nv04_graph_takedown(struct drm_device *dev)
535{ 538{
539 nv_wr32(dev, NV03_PGRAPH_INTR_EN, 0x00000000);
540 nouveau_irq_unregister(dev, 12);
536} 541}
537 542
538void 543void
@@ -1224,3 +1229,89 @@ nv04_graph_register(struct drm_device *dev)
1224 dev_priv->engine.graph.registered = true; 1229 dev_priv->engine.graph.registered = true;
1225 return 0; 1230 return 0;
1226}; 1231};
1232
1233static struct nouveau_bitfield nv04_graph_intr[] = {
1234 { NV_PGRAPH_INTR_NOTIFY, "NOTIFY" },
1235 {}
1236};
1237
1238static struct nouveau_bitfield nv04_graph_nstatus[] =
1239{
1240 { NV04_PGRAPH_NSTATUS_STATE_IN_USE, "STATE_IN_USE" },
1241 { NV04_PGRAPH_NSTATUS_INVALID_STATE, "INVALID_STATE" },
1242 { NV04_PGRAPH_NSTATUS_BAD_ARGUMENT, "BAD_ARGUMENT" },
1243 { NV04_PGRAPH_NSTATUS_PROTECTION_FAULT, "PROTECTION_FAULT" },
1244 {}
1245};
1246
1247struct nouveau_bitfield nv04_graph_nsource[] =
1248{
1249 { NV03_PGRAPH_NSOURCE_NOTIFICATION, "NOTIFICATION" },
1250 { NV03_PGRAPH_NSOURCE_DATA_ERROR, "DATA_ERROR" },
1251 { NV03_PGRAPH_NSOURCE_PROTECTION_ERROR, "PROTECTION_ERROR" },
1252 { NV03_PGRAPH_NSOURCE_RANGE_EXCEPTION, "RANGE_EXCEPTION" },
1253 { NV03_PGRAPH_NSOURCE_LIMIT_COLOR, "LIMIT_COLOR" },
1254 { NV03_PGRAPH_NSOURCE_LIMIT_ZETA, "LIMIT_ZETA" },
1255 { NV03_PGRAPH_NSOURCE_ILLEGAL_MTHD, "ILLEGAL_MTHD" },
1256 { NV03_PGRAPH_NSOURCE_DMA_R_PROTECTION, "DMA_R_PROTECTION" },
1257 { NV03_PGRAPH_NSOURCE_DMA_W_PROTECTION, "DMA_W_PROTECTION" },
1258 { NV03_PGRAPH_NSOURCE_FORMAT_EXCEPTION, "FORMAT_EXCEPTION" },
1259 { NV03_PGRAPH_NSOURCE_PATCH_EXCEPTION, "PATCH_EXCEPTION" },
1260 { NV03_PGRAPH_NSOURCE_STATE_INVALID, "STATE_INVALID" },
1261 { NV03_PGRAPH_NSOURCE_DOUBLE_NOTIFY, "DOUBLE_NOTIFY" },
1262 { NV03_PGRAPH_NSOURCE_NOTIFY_IN_USE, "NOTIFY_IN_USE" },
1263 { NV03_PGRAPH_NSOURCE_METHOD_CNT, "METHOD_CNT" },
1264 { NV03_PGRAPH_NSOURCE_BFR_NOTIFICATION, "BFR_NOTIFICATION" },
1265 { NV03_PGRAPH_NSOURCE_DMA_VTX_PROTECTION, "DMA_VTX_PROTECTION" },
1266 { NV03_PGRAPH_NSOURCE_DMA_WIDTH_A, "DMA_WIDTH_A" },
1267 { NV03_PGRAPH_NSOURCE_DMA_WIDTH_B, "DMA_WIDTH_B" },
1268 {}
1269};
1270
1271static void
1272nv04_graph_isr(struct drm_device *dev)
1273{
1274 u32 stat;
1275
1276 while ((stat = nv_rd32(dev, NV03_PGRAPH_INTR))) {
1277 u32 nsource = nv_rd32(dev, NV03_PGRAPH_NSOURCE);
1278 u32 nstatus = nv_rd32(dev, NV03_PGRAPH_NSTATUS);
1279 u32 addr = nv_rd32(dev, NV04_PGRAPH_TRAPPED_ADDR);
1280 u32 chid = (addr & 0x0f000000) >> 24;
1281 u32 subc = (addr & 0x0000e000) >> 13;
1282 u32 mthd = (addr & 0x00001ffc);
1283 u32 data = nv_rd32(dev, NV04_PGRAPH_TRAPPED_DATA);
1284 u32 class = nv_rd32(dev, 0x400180 + subc * 4) & 0xff;
1285 u32 show = stat;
1286
1287 if (stat & NV_PGRAPH_INTR_NOTIFY) {
1288 if (nsource & NV03_PGRAPH_NSOURCE_ILLEGAL_MTHD) {
1289 if (!nouveau_gpuobj_mthd_call2(dev, chid, class, mthd, data))
1290 show &= ~NV_PGRAPH_INTR_NOTIFY;
1291 }
1292 }
1293
1294 if (stat & NV_PGRAPH_INTR_CONTEXT_SWITCH) {
1295 nv_wr32(dev, NV03_PGRAPH_INTR, NV_PGRAPH_INTR_CONTEXT_SWITCH);
1296 stat &= ~NV_PGRAPH_INTR_CONTEXT_SWITCH;
1297 show &= ~NV_PGRAPH_INTR_CONTEXT_SWITCH;
1298 nv04_graph_context_switch(dev);
1299 }
1300
1301 nv_wr32(dev, NV03_PGRAPH_INTR, stat);
1302 nv_wr32(dev, NV04_PGRAPH_FIFO, 0x00000001);
1303
1304 if (show && nouveau_ratelimit()) {
1305 NV_INFO(dev, "PGRAPH -");
1306 nouveau_bitfield_print(nv04_graph_intr, show);
1307 printk(" nsource:");
1308 nouveau_bitfield_print(nv04_graph_nsource, nsource);
1309 printk(" nstatus:");
1310 nouveau_bitfield_print(nv04_graph_nstatus, nstatus);
1311 printk("\n");
1312 NV_INFO(dev, "PGRAPH - ch %d/%d class 0x%04x "
1313 "mthd 0x%04x data 0x%08x\n",
1314 chid, subc, class, mthd, data);
1315 }
1316 }
1317}