summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTerje Bergstrom <tbergstrom@nvidia.com>2014-05-23 12:46:58 +0300
committerMrutyunjay Sawant <msawant@nvidia.com>2014-06-04 06:13:09 -0700
commit6f526945f0746db3d0eb0b2d76a212d96dc1c18d (patch)
tree4758162da6759fc6c5381d2c2207fcfd58bb42da
parent6c8f204fe29c074287147c7fcc3dfdbd61d038df (diff)
gpu: nvgpu: Handle PBDMA errors
Add handling for PBDMA errors. Bug 1498688 Change-Id: Iff391110db1c270c05c76e6a14b7c666da8e3751 Signed-off-by: Terje Bergstrom <tbergstrom@nvidia.com> (cherry picked from commit 85f46d83227893f283d0247937dfa9da3e2d54fd) Reviewed-on: http://git-master/r/417729 Reviewed-by: Automatic_Commit_Validation_User
-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 4cc7781ddbd3..8ee6177ae14f 100644
--- a/drivers/gpu/nvgpu/gk20a/fifo_gk20a.c
+++ b/drivers/gpu/nvgpu/gk20a/fifo_gk20a.c
@@ -1338,35 +1338,25 @@ static u32 gk20a_fifo_handle_pbdma_intr(struct device *dev,
u32 pbdma_intr_0 = gk20a_readl(g, pbdma_intr_0_r(pbdma_id));
u32 pbdma_intr_1 = gk20a_readl(g, pbdma_intr_1_r(pbdma_id));
u32 handled = 0;
- bool reset_device = false;
- bool reset_channel = false;
+ bool reset = false;
gk20a_dbg_fn("");
gk20a_dbg(gpu_dbg_intr, "pbdma id intr pending %d %08x %08x", pbdma_id,
pbdma_intr_0, pbdma_intr_1);
if (pbdma_intr_0) {
- if (f->intr.pbdma.device_fatal_0 & pbdma_intr_0) {
- dev_err(dev, "unrecoverable device error: "
- "pbdma_intr_0(%d):0x%08x", pbdma_id, pbdma_intr_0);
- reset_device = true;
- /* TODO: disable pbdma intrs */
- handled |= f->intr.pbdma.device_fatal_0 & pbdma_intr_0;
- }
- if (f->intr.pbdma.channel_fatal_0 & pbdma_intr_0) {
- dev_warn(dev, "channel error: "
- "pbdma_intr_0(%d):0x%08x", pbdma_id, pbdma_intr_0);
- reset_channel = true;
- /* TODO: clear pbdma channel errors */
- handled |= f->intr.pbdma.channel_fatal_0 & pbdma_intr_0;
- }
- if (f->intr.pbdma.restartable_0 & pbdma_intr_0) {
- dev_warn(dev, "sw method: %08x %08x",
- gk20a_readl(g, pbdma_method0_r(0)),
- gk20a_readl(g, pbdma_method0_r(0)+4));
- gk20a_writel(g, pbdma_method0_r(0), 0);
- gk20a_writel(g, pbdma_method0_r(0)+4, 0);
- handled |= f->intr.pbdma.restartable_0 & pbdma_intr_0;
+ if ((f->intr.pbdma.device_fatal_0 |
+ f->intr.pbdma.channel_fatal_0 |
+ f->intr.pbdma.restartable_0) & pbdma_intr_0) {
+ dev_err(dev, "pbdma_intr_0(%d):0x%08x PBH: %08x M0: %08x",
+ pbdma_id, pbdma_intr_0,
+ gk20a_readl(g, pbdma_pb_header_r(pbdma_id)),
+ gk20a_readl(g, pbdma_method0_r(pbdma_id)));
+ reset = true;
+ handled |= ((f->intr.pbdma.device_fatal_0 |
+ f->intr.pbdma.channel_fatal_0 |
+ f->intr.pbdma.restartable_0) &
+ pbdma_intr_0);
}
gk20a_writel(g, pbdma_intr_0_r(pbdma_id), pbdma_intr_0);
@@ -1377,11 +1367,41 @@ static u32 gk20a_fifo_handle_pbdma_intr(struct device *dev,
if (pbdma_intr_1) {
dev_err(dev, "channel hce error: pbdma_intr_1(%d): 0x%08x",
pbdma_id, pbdma_intr_1);
- reset_channel = true;
+ reset = true;
gk20a_writel(g, pbdma_intr_1_r(pbdma_id), pbdma_intr_1);
}
-
+ if (reset) {
+ /* Remove the channel from runlist */
+ u32 status = gk20a_readl(g, fifo_pbdma_status_r(pbdma_id));
+ if (fifo_pbdma_status_id_type_v(status)
+ == fifo_pbdma_status_id_type_chid_v()) {
+ struct channel_gk20a *ch = g->fifo.channel +
+ fifo_pbdma_status_id_v(status);
+ struct fifo_runlist_info_gk20a *runlist =
+ g->fifo.runlist_info;
+ int i;
+ bool verbose;
+
+ /* disable the channel from hw and increment
+ * syncpoints */
+ gk20a_disable_channel_no_update(ch);
+
+ /* remove the channel from runlist */
+ clear_bit(ch->hw_chid,
+ runlist->active_channels);
+ ch->has_timedout = true;
+
+ /* Recreate the runlist */
+ for (i = 0; i < g->fifo.max_runlists; i++)
+ gk20a_fifo_update_runlist(g,
+ 0, ~0, false, false);
+
+ verbose = gk20a_fifo_set_ctx_mmu_error(g, ch);
+ if (verbose)
+ gk20a_debug_dump(g->dev);
+ }
+ }
return handled;
}