diff options
Diffstat (limited to 'drivers/gpu/nvgpu/gk20a/fifo_gk20a.c')
-rw-r--r-- | drivers/gpu/nvgpu/gk20a/fifo_gk20a.c | 31 |
1 files changed, 20 insertions, 11 deletions
diff --git a/drivers/gpu/nvgpu/gk20a/fifo_gk20a.c b/drivers/gpu/nvgpu/gk20a/fifo_gk20a.c index 68c0ddcb..0bd75026 100644 --- a/drivers/gpu/nvgpu/gk20a/fifo_gk20a.c +++ b/drivers/gpu/nvgpu/gk20a/fifo_gk20a.c | |||
@@ -476,6 +476,7 @@ static int gk20a_init_fifo_setup_sw(struct gk20a *g) | |||
476 | f->g = g; | 476 | f->g = g; |
477 | 477 | ||
478 | mutex_init(&f->intr.isr.mutex); | 478 | mutex_init(&f->intr.isr.mutex); |
479 | mutex_init(&f->gr_reset_mutex); | ||
479 | gk20a_init_fifo_pbdma_intr_descs(f); /* just filling in data/tables */ | 480 | gk20a_init_fifo_pbdma_intr_descs(f); /* just filling in data/tables */ |
480 | 481 | ||
481 | f->num_channels = g->ops.fifo.get_num_fifos(g); | 482 | f->num_channels = g->ops.fifo.get_num_fifos(g); |
@@ -767,12 +768,15 @@ void gk20a_fifo_reset_engine(struct gk20a *g, u32 engine_id) | |||
767 | gk20a_dbg_fn(""); | 768 | gk20a_dbg_fn(""); |
768 | 769 | ||
769 | if (engine_id == top_device_info_type_enum_graphics_v()) { | 770 | if (engine_id == top_device_info_type_enum_graphics_v()) { |
770 | /*HALT_PIPELINE method, halt GR engine*/ | 771 | if (support_gk20a_pmu(g->dev) && g->elpg_enabled) |
771 | if (gr_gk20a_halt_pipe(g)) | 772 | gk20a_pmu_disable_elpg(g); |
772 | gk20a_err(dev_from_gk20a(g), "failed to HALT gr pipe"); | 773 | /*HALT_PIPELINE method, halt GR engine*/ |
773 | /* resetting engine using mc_enable_r() is not enough, | 774 | if (gr_gk20a_halt_pipe(g)) |
774 | * we do full init sequence */ | 775 | gk20a_err(dev_from_gk20a(g), |
775 | gk20a_gr_reset(g); | 776 | "failed to HALT gr pipe"); |
777 | /* resetting engine using mc_enable_r() is not | ||
778 | enough, we do full init sequence */ | ||
779 | gk20a_gr_reset(g); | ||
776 | } | 780 | } |
777 | if (engine_id == top_device_info_type_enum_copy0_v()) | 781 | if (engine_id == top_device_info_type_enum_copy0_v()) |
778 | gk20a_reset(g, mc_enable_ce2_m()); | 782 | gk20a_reset(g, mc_enable_ce2_m()); |
@@ -950,6 +954,7 @@ static bool gk20a_fifo_handle_mmu_fault( | |||
950 | struct channel_gk20a *ch = NULL; | 954 | struct channel_gk20a *ch = NULL; |
951 | struct tsg_gk20a *tsg = NULL; | 955 | struct tsg_gk20a *tsg = NULL; |
952 | struct channel_gk20a *referenced_channel = NULL; | 956 | struct channel_gk20a *referenced_channel = NULL; |
957 | bool was_reset; | ||
953 | /* read and parse engine status */ | 958 | /* read and parse engine status */ |
954 | u32 status = gk20a_readl(g, fifo_engine_status_r(engine_id)); | 959 | u32 status = gk20a_readl(g, fifo_engine_status_r(engine_id)); |
955 | u32 ctx_status = fifo_engine_status_ctx_status_v(status); | 960 | u32 ctx_status = fifo_engine_status_ctx_status_v(status); |
@@ -1029,9 +1034,15 @@ static bool gk20a_fifo_handle_mmu_fault( | |||
1029 | 1034 | ||
1030 | /* handled during channel free */ | 1035 | /* handled during channel free */ |
1031 | g->fifo.deferred_reset_pending = true; | 1036 | g->fifo.deferred_reset_pending = true; |
1032 | } else if (engine_id != ~0) | 1037 | } else if (engine_id != ~0) { |
1033 | gk20a_fifo_reset_engine(g, engine_id); | 1038 | was_reset = mutex_is_locked(&g->fifo.gr_reset_mutex); |
1034 | 1039 | mutex_lock(&g->fifo.gr_reset_mutex); | |
1040 | /* if lock is already taken, a reset is taking place | ||
1041 | so no need to repeat */ | ||
1042 | if (!was_reset) | ||
1043 | gk20a_fifo_reset_engine(g, engine_id); | ||
1044 | mutex_unlock(&g->fifo.gr_reset_mutex); | ||
1045 | } | ||
1035 | /* disable the channel/TSG from hw and increment | 1046 | /* disable the channel/TSG from hw and increment |
1036 | * syncpoints */ | 1047 | * syncpoints */ |
1037 | 1048 | ||
@@ -2120,12 +2131,10 @@ static int gk20a_fifo_update_runlist_locked(struct gk20a *g, u32 runlist_id, | |||
2120 | gk20a_fifo_runlist_reset_engines(g, runlist_id); | 2131 | gk20a_fifo_runlist_reset_engines(g, runlist_id); |
2121 | 2132 | ||
2122 | /* engine reset needs the lock. drop it */ | 2133 | /* engine reset needs the lock. drop it */ |
2123 | mutex_unlock(&runlist->mutex); | ||
2124 | /* wait until the runlist is active again */ | 2134 | /* wait until the runlist is active again */ |
2125 | ret = gk20a_fifo_runlist_wait_pending(g, runlist_id); | 2135 | ret = gk20a_fifo_runlist_wait_pending(g, runlist_id); |
2126 | /* get the lock back. at this point everything should | 2136 | /* get the lock back. at this point everything should |
2127 | * should be fine */ | 2137 | * should be fine */ |
2128 | mutex_lock(&runlist->mutex); | ||
2129 | 2138 | ||
2130 | if (ret) | 2139 | if (ret) |
2131 | gk20a_err(dev_from_gk20a(g), | 2140 | gk20a_err(dev_from_gk20a(g), |