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);
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;
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);
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
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);
mutex_init(&c->last_submit.fence_lock);
INIT_DELAYED_WORK(&c->clean_up.wq, gk20a_channel_clean_up_jobs);