diff --git a/drivers/gpu/nvgpu/gk20a/channel_gk20a.c b/drivers/gpu/nvgpu/gk20a/channel_gk20a.c index 129921ad4..38cb368c8 100644 --- a/drivers/gpu/nvgpu/gk20a/channel_gk20a.c +++ b/drivers/gpu/nvgpu/gk20a/channel_gk20a.c @@ -827,11 +827,12 @@ static int gk20a_init_error_notifier(struct channel_gk20a *ch, return 0; } -void gk20a_set_error_notifier(struct channel_gk20a *ch, __u32 error) +/** + * gk20a_set_error_notifier_locked() + * Should be called with ch->error_notifier_mutex held + */ +void gk20a_set_error_notifier_locked(struct channel_gk20a *ch, __u32 error) { - bool notifier_set = false; - - mutex_lock(&ch->error_notifier_mutex); if (ch->error_notifier_ref) { struct timespec time_data; u64 nsec; @@ -845,13 +846,16 @@ void gk20a_set_error_notifier(struct channel_gk20a *ch, __u32 error) ch->error_notifier->info32 = error; ch->error_notifier->status = 0xffff; - notifier_set = true; - } - mutex_unlock(&ch->error_notifier_mutex); - - if (notifier_set) gk20a_err(dev_from_gk20a(ch->g), "error notifier set to %d for ch %d", error, ch->hw_chid); + } +} + +void gk20a_set_error_notifier(struct channel_gk20a *ch, __u32 error) +{ + mutex_lock(&ch->error_notifier_mutex); + gk20a_set_error_notifier_locked(ch, error); + mutex_unlock(&ch->error_notifier_mutex); } static void gk20a_free_error_notifiers(struct channel_gk20a *ch) diff --git a/drivers/gpu/nvgpu/gk20a/channel_gk20a.h b/drivers/gpu/nvgpu/gk20a/channel_gk20a.h index ed0b04eed..0a0d94b7b 100644 --- a/drivers/gpu/nvgpu/gk20a/channel_gk20a.h +++ b/drivers/gpu/nvgpu/gk20a/channel_gk20a.h @@ -235,6 +235,7 @@ void gk20a_disable_channel(struct channel_gk20a *ch); void gk20a_channel_abort(struct channel_gk20a *ch, bool channel_preempt); void gk20a_channel_abort_clean_up(struct channel_gk20a *ch); void gk20a_set_error_notifier(struct channel_gk20a *ch, __u32 error); +void gk20a_set_error_notifier_locked(struct channel_gk20a *ch, __u32 error); void gk20a_channel_semaphore_wakeup(struct gk20a *g, bool post_events); int gk20a_channel_alloc_priv_cmdbuf(struct channel_gk20a *c, u32 size, struct priv_cmd_entry *entry); diff --git a/drivers/gpu/nvgpu/gk20a/fifo_gk20a.c b/drivers/gpu/nvgpu/gk20a/fifo_gk20a.c index b4fa8f0fb..fb772ebd8 100644 --- a/drivers/gpu/nvgpu/gk20a/fifo_gk20a.c +++ b/drivers/gpu/nvgpu/gk20a/fifo_gk20a.c @@ -1219,7 +1219,8 @@ static bool gk20a_fifo_set_ctx_mmu_error(struct gk20a *g, if (!ch) return verbose; - if (ch->error_notifier) { + mutex_lock(&ch->error_notifier_mutex); + if (ch->error_notifier_ref) { u32 err = ch->error_notifier->info32; if (ch->error_notifier->status == 0xffff) { /* If error code is already set, this mmu fault @@ -1230,10 +1231,12 @@ static bool gk20a_fifo_set_ctx_mmu_error(struct gk20a *g, if (err == NVGPU_CHANNEL_FIFO_ERROR_IDLE_TIMEOUT) verbose = ch->timeout_debug_dump; } else { - gk20a_set_error_notifier(ch, + gk20a_set_error_notifier_locked(ch, NVGPU_CHANNEL_FIFO_ERROR_MMU_ERR_FLT); } } + mutex_unlock(&ch->error_notifier_mutex); + /* mark channel as faulted */ ch->has_timedout = true; wmb(); diff --git a/drivers/gpu/nvgpu/vgpu/fifo_vgpu.c b/drivers/gpu/nvgpu/vgpu/fifo_vgpu.c index 5ffc6a003..e9a2d5822 100644 --- a/drivers/gpu/nvgpu/vgpu/fifo_vgpu.c +++ b/drivers/gpu/nvgpu/vgpu/fifo_vgpu.c @@ -678,17 +678,20 @@ static int vgpu_fifo_force_reset_ch(struct channel_gk20a *ch, static void vgpu_fifo_set_ctx_mmu_error(struct gk20a *g, struct channel_gk20a *ch) { - if (ch->error_notifier) { + mutex_lock(&ch->error_notifier_mutex); + if (ch->error_notifier_ref) { if (ch->error_notifier->status == 0xffff) { /* If error code is already set, this mmu fault * was triggered as part of recovery from other * error condition. * Don't overwrite error flag. */ } else { - gk20a_set_error_notifier(ch, + gk20a_set_error_notifier_locked(ch, NVGPU_CHANNEL_FIFO_ERROR_MMU_ERR_FLT); } } + mutex_unlock(&ch->error_notifier_mutex); + /* mark channel as faulted */ ch->has_timedout = true; wmb();