summaryrefslogtreecommitdiffstats
path: root/drivers/gpu/nvgpu/gk20a/fifo_gk20a.c
diff options
context:
space:
mode:
authorTerje Bergstrom <tbergstrom@nvidia.com>2014-05-23 05:46:58 -0400
committerDan Willemsen <dwillemsen@nvidia.com>2015-03-18 15:09:59 -0400
commit5dc7fd024305f736bd920bdc12d116d1228ad2db (patch)
tree53231d2b67d4e85c6ff6d371221e1732e627e460 /drivers/gpu/nvgpu/gk20a/fifo_gk20a.c
parent2ad53bb4ca3877694853ac517c351ed1a9825772 (diff)
gpu: nvgpu: Handle PBDMA errors
Add handling for PBDMA errors. Bug 1498688 Change-Id: Iff391110db1c270c05c76e6a14b7c666da8e3751 Signed-off-by: Terje Bergstrom <tbergstrom@nvidia.com>
Diffstat (limited to 'drivers/gpu/nvgpu/gk20a/fifo_gk20a.c')
-rw-r--r--drivers/gpu/nvgpu/gk20a/fifo_gk20a.c70
1 files changed, 45 insertions, 25 deletions
diff --git a/drivers/gpu/nvgpu/gk20a/fifo_gk20a.c b/drivers/gpu/nvgpu/gk20a/fifo_gk20a.c
index 3bd5a994..db1ccd72 100644
--- a/drivers/gpu/nvgpu/gk20a/fifo_gk20a.c
+++ b/drivers/gpu/nvgpu/gk20a/fifo_gk20a.c
@@ -1335,35 +1335,25 @@ static u32 gk20a_fifo_handle_pbdma_intr(struct device *dev,
1335 u32 pbdma_intr_0 = gk20a_readl(g, pbdma_intr_0_r(pbdma_id)); 1335 u32 pbdma_intr_0 = gk20a_readl(g, pbdma_intr_0_r(pbdma_id));
1336 u32 pbdma_intr_1 = gk20a_readl(g, pbdma_intr_1_r(pbdma_id)); 1336 u32 pbdma_intr_1 = gk20a_readl(g, pbdma_intr_1_r(pbdma_id));
1337 u32 handled = 0; 1337 u32 handled = 0;
1338 bool reset_device = false; 1338 bool reset = false;
1339 bool reset_channel = false;
1340 1339
1341 gk20a_dbg_fn(""); 1340 gk20a_dbg_fn("");
1342 1341
1343 gk20a_dbg(gpu_dbg_intr, "pbdma id intr pending %d %08x %08x", pbdma_id, 1342 gk20a_dbg(gpu_dbg_intr, "pbdma id intr pending %d %08x %08x", pbdma_id,
1344 pbdma_intr_0, pbdma_intr_1); 1343 pbdma_intr_0, pbdma_intr_1);
1345 if (pbdma_intr_0) { 1344 if (pbdma_intr_0) {
1346 if (f->intr.pbdma.device_fatal_0 & pbdma_intr_0) { 1345 if ((f->intr.pbdma.device_fatal_0 |
1347 dev_err(dev, "unrecoverable device error: " 1346 f->intr.pbdma.channel_fatal_0 |
1348 "pbdma_intr_0(%d):0x%08x", pbdma_id, pbdma_intr_0); 1347 f->intr.pbdma.restartable_0) & pbdma_intr_0) {
1349 reset_device = true; 1348 dev_err(dev, "pbdma_intr_0(%d):0x%08x PBH: %08x M0: %08x",
1350 /* TODO: disable pbdma intrs */ 1349 pbdma_id, pbdma_intr_0,
1351 handled |= f->intr.pbdma.device_fatal_0 & pbdma_intr_0; 1350 gk20a_readl(g, pbdma_pb_header_r(pbdma_id)),
1352 } 1351 gk20a_readl(g, pbdma_method0_r(pbdma_id)));
1353 if (f->intr.pbdma.channel_fatal_0 & pbdma_intr_0) { 1352 reset = true;
1354 dev_warn(dev, "channel error: " 1353 handled |= ((f->intr.pbdma.device_fatal_0 |
1355 "pbdma_intr_0(%d):0x%08x", pbdma_id, pbdma_intr_0); 1354 f->intr.pbdma.channel_fatal_0 |
1356 reset_channel = true; 1355 f->intr.pbdma.restartable_0) &
1357 /* TODO: clear pbdma channel errors */ 1356 pbdma_intr_0);
1358 handled |= f->intr.pbdma.channel_fatal_0 & pbdma_intr_0;
1359 }
1360 if (f->intr.pbdma.restartable_0 & pbdma_intr_0) {
1361 dev_warn(dev, "sw method: %08x %08x",
1362 gk20a_readl(g, pbdma_method0_r(0)),
1363 gk20a_readl(g, pbdma_method0_r(0)+4));
1364 gk20a_writel(g, pbdma_method0_r(0), 0);
1365 gk20a_writel(g, pbdma_method0_r(0)+4, 0);
1366 handled |= f->intr.pbdma.restartable_0 & pbdma_intr_0;
1367 } 1357 }
1368 1358
1369 gk20a_writel(g, pbdma_intr_0_r(pbdma_id), pbdma_intr_0); 1359 gk20a_writel(g, pbdma_intr_0_r(pbdma_id), pbdma_intr_0);
@@ -1374,11 +1364,41 @@ static u32 gk20a_fifo_handle_pbdma_intr(struct device *dev,
1374 if (pbdma_intr_1) { 1364 if (pbdma_intr_1) {
1375 dev_err(dev, "channel hce error: pbdma_intr_1(%d): 0x%08x", 1365 dev_err(dev, "channel hce error: pbdma_intr_1(%d): 0x%08x",
1376 pbdma_id, pbdma_intr_1); 1366 pbdma_id, pbdma_intr_1);
1377 reset_channel = true; 1367 reset = true;
1378 gk20a_writel(g, pbdma_intr_1_r(pbdma_id), pbdma_intr_1); 1368 gk20a_writel(g, pbdma_intr_1_r(pbdma_id), pbdma_intr_1);
1379 } 1369 }
1380 1370
1381 1371 if (reset) {
1372 /* Remove the channel from runlist */
1373 u32 status = gk20a_readl(g, fifo_pbdma_status_r(pbdma_id));
1374 if (fifo_pbdma_status_id_type_v(status)
1375 == fifo_pbdma_status_id_type_chid_v()) {
1376 struct channel_gk20a *ch = g->fifo.channel +
1377 fifo_pbdma_status_id_v(status);
1378 struct fifo_runlist_info_gk20a *runlist =
1379 g->fifo.runlist_info;
1380 int i;
1381 bool verbose;
1382
1383 /* disable the channel from hw and increment
1384 * syncpoints */
1385 gk20a_disable_channel_no_update(ch);
1386
1387 /* remove the channel from runlist */
1388 clear_bit(ch->hw_chid,
1389 runlist->active_channels);
1390 ch->has_timedout = true;
1391
1392 /* Recreate the runlist */
1393 for (i = 0; i < g->fifo.max_runlists; i++)
1394 gk20a_fifo_update_runlist(g,
1395 0, ~0, false, false);
1396
1397 verbose = gk20a_fifo_set_ctx_mmu_error(g, ch);
1398 if (verbose)
1399 gk20a_debug_dump(g->dev);
1400 }
1401 }
1382 1402
1383 return handled; 1403 return handled;
1384} 1404}