drm/nouveau/nvif: fix a number of notify thinkos

Note to self: more sleep

Signed-off-by: Ben Skeggs <bskeggs@redhat.com>
This commit is contained in:
Ben Skeggs 2014-08-11 11:36:45 +10:00
parent 27111a23d0
commit 7caa63c040
3 changed files with 20 additions and 11 deletions

View File

@ -132,12 +132,12 @@ nvkm_client_notify_new(struct nouveau_client *client,
if (ret == 0) { if (ret == 0) {
client->notify[index] = notify; client->notify[index] = notify;
notify->client = client; notify->client = client;
return 0; return index;
} }
} }
kfree(notify); kfree(notify);
return 0; return ret;
} }
static int static int

View File

@ -14,7 +14,7 @@ struct nouveau_client {
void *data; void *data;
int (*ntfy)(const void *, u32, const void *, u32); int (*ntfy)(const void *, u32, const void *, u32);
struct nvkm_client_notify *notify[8]; struct nvkm_client_notify *notify[16];
}; };
static inline struct nouveau_client * static inline struct nouveau_client *

View File

@ -87,12 +87,25 @@ nvif_notify_get(struct nvif_notify *notify)
return 0; return 0;
} }
static inline int
nvif_notify_func(struct nvif_notify *notify, bool keep)
{
int ret = notify->func(notify);
if (ret == NVIF_NOTIFY_KEEP ||
!test_and_clear_bit(NVKM_NOTIFY_USER, &notify->flags)) {
if (!keep)
atomic_dec(&notify->putcnt);
else
nvif_notify_get_(notify);
}
return ret;
}
static void static void
nvif_notify_work(struct work_struct *work) nvif_notify_work(struct work_struct *work)
{ {
struct nvif_notify *notify = container_of(work, typeof(*notify), work); struct nvif_notify *notify = container_of(work, typeof(*notify), work);
if (notify->func(notify) == NVIF_NOTIFY_KEEP) nvif_notify_func(notify, true);
nvif_notify_get_(notify);
} }
int int
@ -113,19 +126,15 @@ nvif_notify(const void *header, u32 length, const void *data, u32 size)
if (!WARN_ON(notify == NULL)) { if (!WARN_ON(notify == NULL)) {
struct nvif_client *client = nvif_client(notify->object); struct nvif_client *client = nvif_client(notify->object);
if (!WARN_ON(notify->size != size)) { if (!WARN_ON(notify->size != size)) {
atomic_inc(&notify->putcnt);
if (test_bit(NVIF_NOTIFY_WORK, &notify->flags)) { if (test_bit(NVIF_NOTIFY_WORK, &notify->flags)) {
atomic_inc(&notify->putcnt);
memcpy((void *)notify->data, data, size); memcpy((void *)notify->data, data, size);
schedule_work(&notify->work); schedule_work(&notify->work);
return NVIF_NOTIFY_DROP; return NVIF_NOTIFY_DROP;
} }
notify->data = data; notify->data = data;
ret = notify->func(notify); ret = nvif_notify_func(notify, client->driver->keep);
notify->data = NULL; notify->data = NULL;
if (ret != NVIF_NOTIFY_DROP && client->driver->keep) {
atomic_inc(&notify->putcnt);
nvif_notify_get_(notify);
}
} }
} }