aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/nouveau/nvif/notify.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/gpu/drm/nouveau/nvif/notify.c')
-rw-r--r--drivers/gpu/drm/nouveau/nvif/notify.c29
1 files changed, 20 insertions, 9 deletions
diff --git a/drivers/gpu/drm/nouveau/nvif/notify.c b/drivers/gpu/drm/nouveau/nvif/notify.c
index 7c06123a559c..0898c3155292 100644
--- a/drivers/gpu/drm/nouveau/nvif/notify.c
+++ b/drivers/gpu/drm/nouveau/nvif/notify.c
@@ -87,12 +87,25 @@ nvif_notify_get(struct nvif_notify *notify)
87 return 0; 87 return 0;
88} 88}
89 89
90static inline int
91nvif_notify_func(struct nvif_notify *notify, bool keep)
92{
93 int ret = notify->func(notify);
94 if (ret == NVIF_NOTIFY_KEEP ||
95 !test_and_clear_bit(NVKM_NOTIFY_USER, &notify->flags)) {
96 if (!keep)
97 atomic_dec(&notify->putcnt);
98 else
99 nvif_notify_get_(notify);
100 }
101 return ret;
102}
103
90static void 104static void
91nvif_notify_work(struct work_struct *work) 105nvif_notify_work(struct work_struct *work)
92{ 106{
93 struct nvif_notify *notify = container_of(work, typeof(*notify), work); 107 struct nvif_notify *notify = container_of(work, typeof(*notify), work);
94 if (notify->func(notify) == NVIF_NOTIFY_KEEP) 108 nvif_notify_func(notify, true);
95 nvif_notify_get_(notify);
96} 109}
97 110
98int 111int
@@ -113,19 +126,15 @@ nvif_notify(const void *header, u32 length, const void *data, u32 size)
113 if (!WARN_ON(notify == NULL)) { 126 if (!WARN_ON(notify == NULL)) {
114 struct nvif_client *client = nvif_client(notify->object); 127 struct nvif_client *client = nvif_client(notify->object);
115 if (!WARN_ON(notify->size != size)) { 128 if (!WARN_ON(notify->size != size)) {
129 atomic_inc(&notify->putcnt);
116 if (test_bit(NVIF_NOTIFY_WORK, &notify->flags)) { 130 if (test_bit(NVIF_NOTIFY_WORK, &notify->flags)) {
117 atomic_inc(&notify->putcnt);
118 memcpy((void *)notify->data, data, size); 131 memcpy((void *)notify->data, data, size);
119 schedule_work(&notify->work); 132 schedule_work(&notify->work);
120 return NVIF_NOTIFY_DROP; 133 return NVIF_NOTIFY_DROP;
121 } 134 }
122 notify->data = data; 135 notify->data = data;
123 ret = notify->func(notify); 136 ret = nvif_notify_func(notify, client->driver->keep);
124 notify->data = NULL; 137 notify->data = NULL;
125 if (ret != NVIF_NOTIFY_DROP && client->driver->keep) {
126 atomic_inc(&notify->putcnt);
127 nvif_notify_get_(notify);
128 }
129 } 138 }
130 } 139 }
131 140
@@ -228,8 +237,10 @@ nvif_notify_new(struct nvif_object *object, int (*func)(struct nvif_notify *),
228 if (notify) { 237 if (notify) {
229 int ret = nvif_notify_init(object, nvif_notify_del, func, work, 238 int ret = nvif_notify_init(object, nvif_notify_del, func, work,
230 type, data, size, reply, notify); 239 type, data, size, reply, notify);
231 if (ret) 240 if (ret) {
232 kfree(notify); 241 kfree(notify);
242 notify = NULL;
243 }
233 *pnotify = notify; 244 *pnotify = notify;
234 return ret; 245 return ret;
235 } 246 }