summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/gpu/nvgpu/gk20a/channel_gk20a.c18
-rw-r--r--drivers/gpu/nvgpu/gk20a/channel_gk20a.h2
2 files changed, 18 insertions, 2 deletions
diff --git a/drivers/gpu/nvgpu/gk20a/channel_gk20a.c b/drivers/gpu/nvgpu/gk20a/channel_gk20a.c
index f554cf77..f48ef35f 100644
--- a/drivers/gpu/nvgpu/gk20a/channel_gk20a.c
+++ b/drivers/gpu/nvgpu/gk20a/channel_gk20a.c
@@ -682,8 +682,11 @@ void gk20a_free_channel(struct channel_gk20a *ch, bool finish)
682 else 682 else
683 gk20a_vm_put(ch_vm); 683 gk20a_vm_put(ch_vm);
684 684
685 spin_lock(&ch->update_fn_lock);
685 ch->update_fn = NULL; 686 ch->update_fn = NULL;
686 ch->update_fn_data = NULL; 687 ch->update_fn_data = NULL;
688 spin_unlock(&ch->update_fn_lock);
689 cancel_work_sync(&ch->update_fn_work);
687 690
688unbind: 691unbind:
689 if (gk20a_is_channel_marked_as_tsg(ch)) 692 if (gk20a_is_channel_marked_as_tsg(ch))
@@ -745,7 +748,16 @@ static void gk20a_channel_update_runcb_fn(struct work_struct *work)
745{ 748{
746 struct channel_gk20a *ch = 749 struct channel_gk20a *ch =
747 container_of(work, struct channel_gk20a, update_fn_work); 750 container_of(work, struct channel_gk20a, update_fn_work);
748 ch->update_fn(ch, ch->update_fn_data); 751 void (*update_fn)(struct channel_gk20a *, void *);
752 void *update_fn_data;
753
754 spin_lock(&ch->update_fn_lock);
755 update_fn = ch->update_fn;
756 update_fn_data = ch->update_fn_data;
757 spin_unlock(&ch->update_fn_lock);
758
759 if (update_fn)
760 update_fn(ch, update_fn_data);
749} 761}
750 762
751struct channel_gk20a *gk20a_open_new_channel_with_cb(struct gk20a *g, 763struct channel_gk20a *gk20a_open_new_channel_with_cb(struct gk20a *g,
@@ -755,8 +767,10 @@ struct channel_gk20a *gk20a_open_new_channel_with_cb(struct gk20a *g,
755 struct channel_gk20a *ch = gk20a_open_new_channel(g); 767 struct channel_gk20a *ch = gk20a_open_new_channel(g);
756 768
757 if (ch) { 769 if (ch) {
770 spin_lock(&ch->update_fn_lock);
758 ch->update_fn = update_fn; 771 ch->update_fn = update_fn;
759 ch->update_fn_data = update_fn_data; 772 ch->update_fn_data = update_fn_data;
773 spin_unlock(&ch->update_fn_lock);
760 } 774 }
761 775
762 return ch; 776 return ch;
@@ -811,7 +825,7 @@ struct channel_gk20a *gk20a_open_new_channel(struct gk20a *g)
811 825
812 ch->update_fn = NULL; 826 ch->update_fn = NULL;
813 ch->update_fn_data = NULL; 827 ch->update_fn_data = NULL;
814 828 spin_lock_init(&ch->update_fn_lock);
815 INIT_WORK(&ch->update_fn_work, gk20a_channel_update_runcb_fn); 829 INIT_WORK(&ch->update_fn_work, gk20a_channel_update_runcb_fn);
816 830
817 return ch; 831 return ch;
diff --git a/drivers/gpu/nvgpu/gk20a/channel_gk20a.h b/drivers/gpu/nvgpu/gk20a/channel_gk20a.h
index a028b6f3..263ca291 100644
--- a/drivers/gpu/nvgpu/gk20a/channel_gk20a.h
+++ b/drivers/gpu/nvgpu/gk20a/channel_gk20a.h
@@ -24,6 +24,7 @@
24#include <linux/mutex.h> 24#include <linux/mutex.h>
25#include <uapi/linux/nvgpu.h> 25#include <uapi/linux/nvgpu.h>
26#include <linux/poll.h> 26#include <linux/poll.h>
27#include <linux/spinlock.h>
27 28
28struct gk20a; 29struct gk20a;
29struct gr_gk20a; 30struct gr_gk20a;
@@ -162,6 +163,7 @@ struct channel_gk20a {
162 * via schedule_work */ 163 * via schedule_work */
163 void (*update_fn)(struct channel_gk20a *, void *); 164 void (*update_fn)(struct channel_gk20a *, void *);
164 void *update_fn_data; 165 void *update_fn_data;
166 spinlock_t update_fn_lock; /* make access to the two above atomic */
165 struct work_struct update_fn_work; 167 struct work_struct update_fn_work;
166}; 168};
167 169