diff --git a/drivers/gpu/nvgpu/gk20a/channel_gk20a.c b/drivers/gpu/nvgpu/gk20a/channel_gk20a.c index 92b43c8a1..6a69de3e2 100644 --- a/drivers/gpu/nvgpu/gk20a/channel_gk20a.c +++ b/drivers/gpu/nvgpu/gk20a/channel_gk20a.c @@ -742,8 +742,7 @@ static int gk20a_init_error_notifier(struct channel_gk20a *ch, dmabuf = dma_buf_get(args->mem); - if (ch->error_notifier_ref) - gk20a_free_error_notifiers(ch); + gk20a_free_error_notifiers(ch); if (IS_ERR(dmabuf)) { pr_err("Invalid handle: %d\n", args->mem); @@ -764,16 +763,23 @@ static int gk20a_init_error_notifier(struct channel_gk20a *ch, return -ENOMEM; } - /* set channel notifiers pointer */ - ch->error_notifier_ref = dmabuf; ch->error_notifier = va + args->offset; ch->error_notifier_va = va; memset(ch->error_notifier, 0, sizeof(struct nvgpu_notification)); + + /* set channel notifiers pointer */ + mutex_lock(&ch->error_notifier_mutex); + ch->error_notifier_ref = dmabuf; + mutex_unlock(&ch->error_notifier_mutex); + return 0; } void gk20a_set_error_notifier(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; @@ -787,13 +793,18 @@ 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); - } } static void gk20a_free_error_notifiers(struct channel_gk20a *ch) { + mutex_lock(&ch->error_notifier_mutex); if (ch->error_notifier_ref) { dma_buf_vunmap(ch->error_notifier_ref, ch->error_notifier_va); dma_buf_put(ch->error_notifier_ref); @@ -801,6 +812,7 @@ static void gk20a_free_error_notifiers(struct channel_gk20a *ch) ch->error_notifier = NULL; ch->error_notifier_va = NULL; } + mutex_unlock(&ch->error_notifier_mutex); } /* Returns delta of cyclic integers a and b. If a is ahead of b, delta @@ -2387,6 +2399,7 @@ int gk20a_init_channel_support(struct gk20a *g, u32 chid) c->referenceable = false; init_waitqueue_head(&c->ref_count_dec_wq); mutex_init(&c->ioctl_lock); + mutex_init(&c->error_notifier_mutex); spin_lock_init(&c->jobs_lock); raw_spin_lock_init(&c->timeout.lock); mutex_init(&c->sync_lock); diff --git a/drivers/gpu/nvgpu/gk20a/channel_gk20a.h b/drivers/gpu/nvgpu/gk20a/channel_gk20a.h index a44321bc7..f6571b6fd 100644 --- a/drivers/gpu/nvgpu/gk20a/channel_gk20a.h +++ b/drivers/gpu/nvgpu/gk20a/channel_gk20a.h @@ -177,6 +177,7 @@ struct channel_gk20a { struct dma_buf *error_notifier_ref; struct nvgpu_notification *error_notifier; void *error_notifier_va; + struct mutex error_notifier_mutex; struct mutex sync_lock; struct gk20a_channel_sync *sync;