diff options
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/gpu/nvgpu/gk20a/fifo_gk20a.c | 70 |
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 | } |