summaryrefslogtreecommitdiffstats
path: root/drivers/gpu/nvgpu/gk20a/channel_gk20a.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/gpu/nvgpu/gk20a/channel_gk20a.c')
-rw-r--r--drivers/gpu/nvgpu/gk20a/channel_gk20a.c26
1 files changed, 17 insertions, 9 deletions
diff --git a/drivers/gpu/nvgpu/gk20a/channel_gk20a.c b/drivers/gpu/nvgpu/gk20a/channel_gk20a.c
index d0d5c41f..0b8422a6 100644
--- a/drivers/gpu/nvgpu/gk20a/channel_gk20a.c
+++ b/drivers/gpu/nvgpu/gk20a/channel_gk20a.c
@@ -82,9 +82,6 @@ static void channel_gk20a_joblist_delete(struct channel_gk20a *c,
82static struct channel_gk20a_job *channel_gk20a_joblist_peek( 82static struct channel_gk20a_job *channel_gk20a_joblist_peek(
83 struct channel_gk20a *c); 83 struct channel_gk20a *c);
84 84
85static int channel_gk20a_update_runlist(struct channel_gk20a *c,
86 bool add);
87
88static u32 gk20a_get_channel_watchdog_timeout(struct channel_gk20a *ch); 85static u32 gk20a_get_channel_watchdog_timeout(struct channel_gk20a *ch);
89 86
90static void gk20a_channel_clean_up_jobs(struct channel_gk20a *c, 87static void gk20a_channel_clean_up_jobs(struct channel_gk20a *c,
@@ -189,7 +186,7 @@ int gk20a_channel_get_timescale_from_timeslice(struct gk20a *g,
189 return 0; 186 return 0;
190} 187}
191 188
192static int channel_gk20a_update_runlist(struct channel_gk20a *c, bool add) 189int channel_gk20a_update_runlist(struct channel_gk20a *c, bool add)
193{ 190{
194 return c->g->ops.fifo.update_runlist(c->g, c->runlist_id, c->chid, add, true); 191 return c->g->ops.fifo.update_runlist(c->g, c->runlist_id, c->chid, add, true);
195} 192}
@@ -459,6 +456,8 @@ static void gk20a_free_channel(struct channel_gk20a *ch, bool force)
459 struct dbg_session_gk20a *dbg_s; 456 struct dbg_session_gk20a *dbg_s;
460 struct dbg_session_data *session_data, *tmp_s; 457 struct dbg_session_data *session_data, *tmp_s;
461 struct dbg_session_channel_data *ch_data, *tmp; 458 struct dbg_session_channel_data *ch_data, *tmp;
459 bool was_tsg = false;
460 int err;
462 461
463 gk20a_dbg_fn(""); 462 gk20a_dbg_fn("");
464 463
@@ -467,7 +466,19 @@ static void gk20a_free_channel(struct channel_gk20a *ch, bool force)
467 trace_gk20a_free_channel(ch->chid); 466 trace_gk20a_free_channel(ch->chid);
468 467
469 /* abort channel and remove from runlist */ 468 /* abort channel and remove from runlist */
470 gk20a_disable_channel(ch); 469 if (gk20a_is_channel_marked_as_tsg(ch)) {
470 err = g->ops.fifo.tsg_unbind_channel(ch);
471 if (err)
472 nvgpu_err(g, "failed to unbind channel %d from TSG", ch->chid);
473 /*
474 * Channel is not a part of TSG this point onwards
475 * So stash its status and use it whenever necessary
476 * e.g. while releasing gr_ctx in g->ops.gr.free_channel_ctx()
477 */
478 was_tsg = true;
479 } else {
480 gk20a_disable_channel(ch);
481 }
471 482
472 /* wait until there's only our ref to the channel */ 483 /* wait until there's only our ref to the channel */
473 if (!force) 484 if (!force)
@@ -524,7 +535,7 @@ static void gk20a_free_channel(struct channel_gk20a *ch, bool force)
524 g->ops.fecs_trace.unbind_channel(g, ch); 535 g->ops.fecs_trace.unbind_channel(g, ch);
525 536
526 /* release channel ctx */ 537 /* release channel ctx */
527 g->ops.gr.free_channel_ctx(ch); 538 g->ops.gr.free_channel_ctx(ch, was_tsg);
528 539
529 gk20a_gr_flush_channel_tlb(gr); 540 gk20a_gr_flush_channel_tlb(gr);
530 541
@@ -571,9 +582,6 @@ static void gk20a_free_channel(struct channel_gk20a *ch, bool force)
571 nvgpu_wait_for_deferred_interrupts(g); 582 nvgpu_wait_for_deferred_interrupts(g);
572 583
573unbind: 584unbind:
574 if (gk20a_is_channel_marked_as_tsg(ch))
575 g->ops.fifo.tsg_unbind_channel(ch);
576
577 g->ops.fifo.unbind_channel(ch); 585 g->ops.fifo.unbind_channel(ch);
578 g->ops.fifo.free_inst(g, ch); 586 g->ops.fifo.free_inst(g, ch);
579 587