diff options
Diffstat (limited to 'drivers/gpu/drm/nouveau/nv04_graph.c')
-rw-r--r-- | drivers/gpu/drm/nouveau/nv04_graph.c | 95 |
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 | ||
31 | static int nv04_graph_register(struct drm_device *dev); | 32 | static int nv04_graph_register(struct drm_device *dev); |
33 | static void nv04_graph_isr(struct drm_device *dev); | ||
32 | 34 | ||
33 | static uint32_t nv04_graph_ctx_regs[] = { | 35 | static 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 | ||
366 | void | 368 | static void |
367 | nv04_graph_context_switch(struct drm_device *dev) | 369 | nv04_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 | ||
534 | void nv04_graph_takedown(struct drm_device *dev) | 537 | void 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 | ||
538 | void | 543 | void |
@@ -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 | |||
1233 | static struct nouveau_bitfield nv04_graph_intr[] = { | ||
1234 | { NV_PGRAPH_INTR_NOTIFY, "NOTIFY" }, | ||
1235 | {} | ||
1236 | }; | ||
1237 | |||
1238 | static 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 | |||
1247 | struct 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 | |||
1271 | static void | ||
1272 | nv04_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 | } | ||