drm/nouveau/core: allow event source to handle multiple event types per index
authorBen Skeggs <bskeggs@redhat.com>
Tue, 13 May 2014 05:30:15 +0000 (15:30 +1000)
committerBen Skeggs <bskeggs@redhat.com>
Wed, 11 Jun 2014 06:09:13 +0000 (16:09 +1000)
Signed-off-by: Ben Skeggs <bskeggs@redhat.com>
21 files changed:
drivers/gpu/drm/nouveau/core/core/event.c
drivers/gpu/drm/nouveau/core/engine/disp/base.c
drivers/gpu/drm/nouveau/core/engine/disp/nv04.c
drivers/gpu/drm/nouveau/core/engine/disp/nv50.c
drivers/gpu/drm/nouveau/core/engine/disp/nvd0.c
drivers/gpu/drm/nouveau/core/engine/fifo/base.c
drivers/gpu/drm/nouveau/core/engine/fifo/nv04.c
drivers/gpu/drm/nouveau/core/engine/fifo/nv84.c
drivers/gpu/drm/nouveau/core/engine/fifo/nvc0.c
drivers/gpu/drm/nouveau/core/engine/fifo/nve0.c
drivers/gpu/drm/nouveau/core/engine/software/nv50.c
drivers/gpu/drm/nouveau/core/engine/software/nv50.h
drivers/gpu/drm/nouveau/core/engine/software/nvc0.c
drivers/gpu/drm/nouveau/core/include/core/event.h
drivers/gpu/drm/nouveau/core/subdev/gpio/base.c
drivers/gpu/drm/nouveau/core/subdev/gpio/nv10.c
drivers/gpu/drm/nouveau/core/subdev/gpio/nv50.c
drivers/gpu/drm/nouveau/core/subdev/gpio/nve0.c
drivers/gpu/drm/nouveau/nouveau_connector.c
drivers/gpu/drm/nouveau/nouveau_display.c
drivers/gpu/drm/nouveau/nouveau_fence.c

index 3f3c765..ae81d3b 100644 (file)
@@ -28,14 +28,20 @@ nouveau_event_put(struct nouveau_eventh *handler)
 {
        struct nouveau_event *event = handler->event;
        unsigned long flags;
-       if (__test_and_clear_bit(NVKM_EVENT_ENABLE, &handler->flags)) {
-               spin_lock_irqsave(&event->refs_lock, flags);
-               if (!--event->index[handler->index].refs) {
+       u32 m, t;
+
+       if (!__test_and_clear_bit(NVKM_EVENT_ENABLE, &handler->flags))
+               return;
+
+       spin_lock_irqsave(&event->refs_lock, flags);
+       for (m = handler->types; t = __ffs(m), m; m &= ~(1 << t)) {
+               if (!--event->refs[handler->index * event->types_nr + t]) {
                        if (event->disable)
-                               event->disable(event, handler->index);
+                               event->disable(event, 1 << t, handler->index);
                }
-               spin_unlock_irqrestore(&event->refs_lock, flags);
+
        }
+       spin_unlock_irqrestore(&event->refs_lock, flags);
 }
 
 void
@@ -43,14 +49,20 @@ nouveau_event_get(struct nouveau_eventh *handler)
 {
        struct nouveau_event *event = handler->event;
        unsigned long flags;
-       if (!__test_and_set_bit(NVKM_EVENT_ENABLE, &handler->flags)) {
-               spin_lock_irqsave(&event->refs_lock, flags);
-               if (!event->index[handler->index].refs++) {
+       u32 m, t;
+
+       if (__test_and_set_bit(NVKM_EVENT_ENABLE, &handler->flags))
+               return;
+
+       spin_lock_irqsave(&event->refs_lock, flags);
+       for (m = handler->types; t = __ffs(m), m; m &= ~(1 << t)) {
+               if (!event->refs[handler->index * event->types_nr + t]++) {
                        if (event->enable)
-                               event->enable(event, handler->index);
+                               event->enable(event, 1 << t, handler->index);
                }
-               spin_unlock_irqrestore(&event->refs_lock, flags);
+
        }
+       spin_unlock_irqrestore(&event->refs_lock, flags);
 }
 
 static void
@@ -65,38 +77,47 @@ nouveau_event_fini(struct nouveau_eventh *handler)
 }
 
 static int
-nouveau_event_init(struct nouveau_event *event, int index,
-                  int (*func)(void *, int), void *priv,
+nouveau_event_init(struct nouveau_event *event, u32 types, int index,
+                  int (*func)(void *, u32, int), void *priv,
                   struct nouveau_eventh *handler)
 {
        unsigned long flags;
 
+       if (types & ~((1 << event->types_nr) - 1))
+               return -EINVAL;
        if (index >= event->index_nr)
                return -EINVAL;
 
        handler->event = event;
        handler->flags = 0;
+       handler->types = types;
        handler->index = index;
        handler->func = func;
        handler->priv = priv;
 
        spin_lock_irqsave(&event->list_lock, flags);
-       list_add_tail(&handler->head, &event->index[index].list);
+       list_add_tail(&handler->head, &event->list[index]);
        spin_unlock_irqrestore(&event->list_lock, flags);
        return 0;
 }
 
 int
-nouveau_event_new(struct nouveau_event *event, int index,
-                 int (*func)(void *, int), void *priv,
+nouveau_event_new(struct nouveau_event *event, u32 types, int index,
+                 int (*func)(void *, u32, int), void *priv,
                  struct nouveau_eventh **phandler)
 {
        struct nouveau_eventh *handler;
        int ret = -ENOMEM;
 
+       if (event->check) {
+               ret = event->check(event, types, index);
+               if (ret)
+                       return ret;
+       }
+
        handler = *phandler = kmalloc(sizeof(*handler), GFP_KERNEL);
        if (handler) {
-               ret = nouveau_event_init(event, index, func, priv, handler);
+               ret = nouveau_event_init(event, types, index, func, priv, handler);
                if (ret)
                        kfree(handler);
        }
@@ -116,7 +137,7 @@ nouveau_event_ref(struct nouveau_eventh *handler, struct nouveau_eventh **ref)
 }
 
 void
-nouveau_event_trigger(struct nouveau_event *event, int index)
+nouveau_event_trigger(struct nouveau_event *event, u32 types, int index)
 {
        struct nouveau_eventh *handler;
        unsigned long flags;
@@ -125,10 +146,15 @@ nouveau_event_trigger(struct nouveau_event *event, int index)
                return;
 
        spin_lock_irqsave(&event->list_lock, flags);
-       list_for_each_entry(handler, &event->index[index].list, head) {
-               if (test_bit(NVKM_EVENT_ENABLE, &handler->flags) &&
-                   handler->func(handler->priv, index) == NVKM_EVENT_DROP)
-                       nouveau_event_put(handler);
+       list_for_each_entry(handler, &event->list[index], head) {
+               if (!test_bit(NVKM_EVENT_ENABLE, &handler->flags))
+                       continue;
+               if (!(handler->types & types))
+                       continue;
+               if (handler->func(handler->priv, handler->types & types, index)
+                               != NVKM_EVENT_DROP)
+                       continue;
+               nouveau_event_put(handler);
        }
        spin_unlock_irqrestore(&event->list_lock, flags);
 }
@@ -144,20 +170,27 @@ nouveau_event_destroy(struct nouveau_event **pevent)
 }
 
 int
-nouveau_event_create(int index_nr, struct nouveau_event **pevent)
+nouveau_event_create(int types_nr, int index_nr, struct nouveau_event **pevent)
 {
        struct nouveau_event *event;
        int i;
 
-       event = *pevent = kzalloc(sizeof(*event) + index_nr *
-                                 sizeof(event->index[0]), GFP_KERNEL);
+       event = *pevent = kzalloc(sizeof(*event) + (index_nr * types_nr) *
+                                 sizeof(event->refs[0]), GFP_KERNEL);
        if (!event)
                return -ENOMEM;
 
+       event->list = kmalloc(sizeof(*event->list) * index_nr, GFP_KERNEL);
+       if (!event->list) {
+               kfree(event);
+               return -ENOMEM;
+       }
+
        spin_lock_init(&event->list_lock);
        spin_lock_init(&event->refs_lock);
        for (i = 0; i < index_nr; i++)
-               INIT_LIST_HEAD(&event->index[i].list);
+               INIT_LIST_HEAD(&event->list[i]);
+       event->types_nr = types_nr;
        event->index_nr = index_nr;
        return 0;
 }
index 7a5cae4..ade59eb 100644 (file)
@@ -48,5 +48,5 @@ nouveau_disp_create_(struct nouveau_object *parent,
        if (ret)
                return ret;
 
-       return nouveau_event_create(heads, &disp->vblank);
+       return nouveau_event_create(1, heads, &disp->vblank);
 }
index 94a2cc6..a32666e 100644 (file)
@@ -86,13 +86,13 @@ nv04_disp_sclass[] = {
  ******************************************************************************/
 
 static void
-nv04_disp_vblank_enable(struct nouveau_event *event, int head)
+nv04_disp_vblank_enable(struct nouveau_event *event, int type, int head)
 {
        nv_wr32(event->priv, 0x600140 + (head * 0x2000) , 0x00000001);
 }
 
 static void
-nv04_disp_vblank_disable(struct nouveau_event *event, int head)
+nv04_disp_vblank_disable(struct nouveau_event *event, int type, int head)
 {
        nv_wr32(event->priv, 0x600140 + (head * 0x2000) , 0x00000000);
 }
@@ -106,12 +106,12 @@ nv04_disp_intr(struct nouveau_subdev *subdev)
        u32 pvideo;
 
        if (crtc0 & 0x00000001) {
-               nouveau_event_trigger(priv->base.vblank, 0);
+               nouveau_event_trigger(priv->base.vblank, 1, 0);
                nv_wr32(priv, 0x600100, 0x00000001);
        }
 
        if (crtc1 & 0x00000001) {
-               nouveau_event_trigger(priv->base.vblank, 1);
+               nouveau_event_trigger(priv->base.vblank, 1, 1);
                nv_wr32(priv, 0x602100, 0x00000001);
        }
 
index 9a0cab9..2956c13 100644 (file)
@@ -829,13 +829,13 @@ nv50_disp_base_scanoutpos(struct nouveau_object *object, u32 mthd,
 }
 
 static void
-nv50_disp_base_vblank_enable(struct nouveau_event *event, int head)
+nv50_disp_base_vblank_enable(struct nouveau_event *event, int type, int head)
 {
        nv_mask(event->priv, 0x61002c, (4 << head), (4 << head));
 }
 
 static void
-nv50_disp_base_vblank_disable(struct nouveau_event *event, int head)
+nv50_disp_base_vblank_disable(struct nouveau_event *event, int type, int head)
 {
        nv_mask(event->priv, 0x61002c, (4 << head), 0);
 }
@@ -1610,13 +1610,13 @@ nv50_disp_intr(struct nouveau_subdev *subdev)
        }
 
        if (intr1 & 0x00000004) {
-               nouveau_event_trigger(priv->base.vblank, 0);
+               nouveau_event_trigger(priv->base.vblank, 1, 0);
                nv_wr32(priv, 0x610024, 0x00000004);
                intr1 &= ~0x00000004;
        }
 
        if (intr1 & 0x00000008) {
-               nouveau_event_trigger(priv->base.vblank, 1);
+               nouveau_event_trigger(priv->base.vblank, 1, 1);
                nv_wr32(priv, 0x610024, 0x00000008);
                intr1 &= ~0x00000008;
        }
index 876de9a..7bf54e8 100644 (file)
@@ -748,13 +748,13 @@ nvd0_disp_base_scanoutpos(struct nouveau_object *object, u32 mthd,
 }
 
 static void
-nvd0_disp_base_vblank_enable(struct nouveau_event *event, int head)
+nvd0_disp_base_vblank_enable(struct nouveau_event *event, int type, int head)
 {
        nv_mask(event->priv, 0x6100c0 + (head * 0x800), 0x00000001, 0x00000001);
 }
 
 static void
-nvd0_disp_base_vblank_disable(struct nouveau_event *event, int head)
+nvd0_disp_base_vblank_disable(struct nouveau_event *event, int type, int head)
 {
        nv_mask(event->priv, 0x6100c0 + (head * 0x800), 0x00000001, 0x00000000);
 }
@@ -1317,7 +1317,7 @@ nvd0_disp_intr(struct nouveau_subdev *subdev)
                if (mask & intr) {
                        u32 stat = nv_rd32(priv, 0x6100bc + (i * 0x800));
                        if (stat & 0x00000001)
-                               nouveau_event_trigger(priv->base.vblank, i);
+                               nouveau_event_trigger(priv->base.vblank, 1, i);
                        nv_mask(priv, 0x6100bc + (i * 0x800), 0, 0);
                        nv_rd32(priv, 0x6100c0 + (i * 0x800));
                }
index 6f9041c..56ed3d7 100644 (file)
@@ -91,7 +91,7 @@ nouveau_fifo_channel_create_(struct nouveau_object *parent,
        if (!chan->user)
                return -EFAULT;
 
-       nouveau_event_trigger(priv->cevent, 0);
+       nouveau_event_trigger(priv->cevent, 1, 0);
 
        chan->size = size;
        return 0;
@@ -194,11 +194,11 @@ nouveau_fifo_create_(struct nouveau_object *parent,
        if (!priv->channel)
                return -ENOMEM;
 
-       ret = nouveau_event_create(1, &priv->cevent);
+       ret = nouveau_event_create(1, 1, &priv->cevent);
        if (ret)
                return ret;
 
-       ret = nouveau_event_create(1, &priv->uevent);
+       ret = nouveau_event_create(1, 1, &priv->uevent);
        if (ret)
                return ret;
 
index 54f26cc..c61b16a 100644 (file)
@@ -539,7 +539,7 @@ nv04_fifo_intr(struct nouveau_subdev *subdev)
                        }
 
                        if (status & 0x40000000) {
-                               nouveau_event_trigger(priv->base.uevent, 0);
+                               nouveau_event_trigger(priv->base.uevent, 1, 0);
                                nv_wr32(priv, 0x002100, 0x40000000);
                                status &= ~0x40000000;
                        }
index fe0f41e..6e5ac16 100644 (file)
@@ -389,14 +389,14 @@ nv84_fifo_cclass = {
  ******************************************************************************/
 
 static void
-nv84_fifo_uevent_enable(struct nouveau_event *event, int index)
+nv84_fifo_uevent_enable(struct nouveau_event *event, int type, int index)
 {
        struct nv84_fifo_priv *priv = event->priv;
        nv_mask(priv, 0x002140, 0x40000000, 0x40000000);
 }
 
 static void
-nv84_fifo_uevent_disable(struct nouveau_event *event, int index)
+nv84_fifo_uevent_disable(struct nouveau_event *event, int type, int index)
 {
        struct nv84_fifo_priv *priv = event->priv;
        nv_mask(priv, 0x002140, 0x40000000, 0x00000000);
index fa1e719..ae4a4dc 100644 (file)
@@ -730,7 +730,7 @@ nvc0_fifo_intr_engine_unit(struct nvc0_fifo_priv *priv, int engn)
        for (unkn = 0; unkn < 8; unkn++) {
                u32 ints = (intr >> (unkn * 0x04)) & inte;
                if (ints & 0x1) {
-                       nouveau_event_trigger(priv->base.uevent, 0);
+                       nouveau_event_trigger(priv->base.uevent, 1, 0);
                        ints &= ~1;
                }
                if (ints) {
@@ -827,14 +827,14 @@ nvc0_fifo_intr(struct nouveau_subdev *subdev)
 }
 
 static void
-nvc0_fifo_uevent_enable(struct nouveau_event *event, int index)
+nvc0_fifo_uevent_enable(struct nouveau_event *event, int type, int index)
 {
        struct nvc0_fifo_priv *priv = event->priv;
        nv_mask(priv, 0x002140, 0x80000000, 0x80000000);
 }
 
 static void
-nvc0_fifo_uevent_disable(struct nouveau_event *event, int index)
+nvc0_fifo_uevent_disable(struct nouveau_event *event, int type, int index)
 {
        struct nvc0_fifo_priv *priv = event->priv;
        nv_mask(priv, 0x002140, 0x80000000, 0x00000000);
index a9a1a9c..298063e 100644 (file)
@@ -859,7 +859,7 @@ nve0_fifo_intr_runlist(struct nve0_fifo_priv *priv)
 static void
 nve0_fifo_intr_engine(struct nve0_fifo_priv *priv)
 {
-       nouveau_event_trigger(priv->base.uevent, 0);
+       nouveau_event_trigger(priv->base.uevent, 1, 0);
 }
 
 static void
@@ -952,14 +952,14 @@ nve0_fifo_intr(struct nouveau_subdev *subdev)
 }
 
 static void
-nve0_fifo_uevent_enable(struct nouveau_event *event, int index)
+nve0_fifo_uevent_enable(struct nouveau_event *event, int type, int index)
 {
        struct nve0_fifo_priv *priv = event->priv;
        nv_mask(priv, 0x002140, 0x80000000, 0x80000000);
 }
 
 static void
-nve0_fifo_uevent_disable(struct nouveau_event *event, int index)
+nve0_fifo_uevent_disable(struct nouveau_event *event, int type, int index)
 {
        struct nve0_fifo_priv *priv = event->priv;
        nv_mask(priv, 0x002140, 0x80000000, 0x00000000);
index 5ce686e..f3b4d9d 100644 (file)
@@ -124,7 +124,7 @@ nv50_software_sclass[] = {
  ******************************************************************************/
 
 static int
-nv50_software_vblsem_release(void *data, int head)
+nv50_software_vblsem_release(void *data, u32 type, int head)
 {
        struct nv50_software_chan *chan = data;
        struct nv50_software_priv *priv = (void *)nv_object(chan)->engine;
@@ -183,7 +183,7 @@ nv50_software_context_ctor(struct nouveau_object *parent,
                return -ENOMEM;
 
        for (i = 0; i < chan->vblank.nr_event; i++) {
-               ret = nouveau_event_new(pdisp->vblank, i, pclass->vblank,
+               ret = nouveau_event_new(pdisp->vblank, 1, i, pclass->vblank,
                                        chan, &chan->vblank.event[i]);
                if (ret)
                        return ret;
index 2de370c..bb49a7a 100644 (file)
@@ -19,7 +19,7 @@ int  nv50_software_ctor(struct nouveau_object *, struct nouveau_object *,
 
 struct nv50_software_cclass {
        struct nouveau_oclass base;
-       int (*vblank)(void *, int);
+       int (*vblank)(void *, u32, int);
 };
 
 struct nv50_software_chan {
index f9430c1..135c20f 100644 (file)
@@ -104,7 +104,7 @@ nvc0_software_sclass[] = {
  ******************************************************************************/
 
 static int
-nvc0_software_vblsem_release(void *data, int head)
+nvc0_software_vblsem_release(void *data, u32 type, int head)
 {
        struct nv50_software_chan *chan = data;
        struct nv50_software_priv *priv = (void *)nv_object(chan)->engine;
index 5d539eb..ba3f1a7 100644 (file)
@@ -12,32 +12,33 @@ struct nouveau_eventh {
        struct nouveau_event *event;
        struct list_head head;
        unsigned long flags;
+       u32 types;
        int index;
-       int (*func)(void *, int);
+       int (*func)(void *, u32, int);
        void *priv;
 };
 
 struct nouveau_event {
-       spinlock_t list_lock;
-       spinlock_t refs_lock;
-
        void *priv;
-       void (*enable)(struct nouveau_event *, int index);
-       void (*disable)(struct nouveau_event *, int index);
+       int (*check)(struct nouveau_event *, u32 type, int index);
+       void (*enable)(struct nouveau_event *, int type, int index);
+       void (*disable)(struct nouveau_event *, int type, int index);
 
+       int types_nr;
        int index_nr;
-       struct {
-               struct list_head list;
-               int refs;
-       } index[];
+
+       spinlock_t list_lock;
+       struct list_head *list;
+       spinlock_t refs_lock;
+       int refs[];
 };
 
-int  nouveau_event_create(int index_nr, struct nouveau_event **);
+int  nouveau_event_create(int types_nr, int index_nr, struct nouveau_event **);
 void nouveau_event_destroy(struct nouveau_event **);
-void nouveau_event_trigger(struct nouveau_event *, int index);
+void nouveau_event_trigger(struct nouveau_event *, u32 types, int index);
 
-int  nouveau_event_new(struct nouveau_event *, int index,
-                      int (*func)(void *, int), void *,
+int  nouveau_event_new(struct nouveau_event *, u32 types, int index,
+                      int (*func)(void *, u32, int), void *,
                       struct nouveau_eventh **);
 void nouveau_event_ref(struct nouveau_eventh *, struct nouveau_eventh **);
 void nouveau_event_get(struct nouveau_eventh *);
index f572c28..c2f0742 100644 (file)
@@ -125,7 +125,7 @@ nouveau_gpio_create_(struct nouveau_object *parent,
        if (ret)
                return ret;
 
-       ret = nouveau_event_create(lines, &gpio->events);
+       ret = nouveau_event_create(1, lines, &gpio->events);
        if (ret)
                return ret;
 
index 76d5d54..c0eaa5c 100644 (file)
@@ -93,7 +93,7 @@ nv10_gpio_intr(struct nouveau_subdev *subdev)
 
        for (i = 0; (hi | lo) && i < 32; i++) {
                if ((hi | lo) & (1 << i))
-                       nouveau_event_trigger(priv->base.events, i);
+                       nouveau_event_trigger(priv->base.events, 1, i);
        }
 
        nv_wr32(priv, 0x001104, intr);
index 2ef7747..06dde2f 100644 (file)
@@ -112,7 +112,7 @@ nv50_gpio_intr(struct nouveau_subdev *subdev)
 
        for (i = 0; (hi | lo) && i < 32; i++) {
                if ((hi | lo) & (1 << i))
-                       nouveau_event_trigger(priv->base.events, i);
+                       nouveau_event_trigger(priv->base.events, 1, i);
        }
 
        nv_wr32(priv, 0xe054, intr0);
index 8988621..66a3a6c 100644 (file)
@@ -40,7 +40,7 @@ nve0_gpio_intr(struct nouveau_subdev *subdev)
 
        for (i = 0; (hi | lo) && i < 32; i++) {
                if ((hi | lo) & (1 << i))
-                       nouveau_event_trigger(priv->base.events, i);
+                       nouveau_event_trigger(priv->base.events, 1, i);
        }
 
        nv_wr32(priv, 0xdc00, intr0);
index 6ecea9b..0f3fdc6 100644 (file)
@@ -934,7 +934,7 @@ nouveau_connector_hotplug_work(struct work_struct *work)
 }
 
 static int
-nouveau_connector_hotplug(void *data, int index)
+nouveau_connector_hotplug(void *data, u32 type, int index)
 {
        struct nouveau_connector *nv_connector = data;
        schedule_work(&nv_connector->hpd_work);
@@ -1013,7 +1013,8 @@ nouveau_connector_create(struct drm_device *dev, int index)
                        nv_connector->hpd.func = DCB_GPIO_UNUSED;
 
                if (nv_connector->hpd.func != DCB_GPIO_UNUSED) {
-                       nouveau_event_new(gpio->events, nv_connector->hpd.line,
+                       nouveau_event_new(gpio->events, 1,
+                                         nv_connector->hpd.line,
                                          nouveau_connector_hotplug,
                                          nv_connector,
                                         &nv_connector->hpd_func);
index 26fbc4f..64f9de9 100644 (file)
@@ -42,7 +42,7 @@
 #include <core/class.h>
 
 static int
-nouveau_display_vblank_handler(void *data, int head)
+nouveau_display_vblank_handler(void *data, u32 type, int head)
 {
        struct nouveau_drm *drm = data;
        drm_handle_vblank(drm->dev, head);
@@ -178,7 +178,7 @@ nouveau_display_vblank_init(struct drm_device *dev)
                return -ENOMEM;
 
        for (i = 0; i < dev->mode_config.num_crtc; i++) {
-               ret = nouveau_event_new(pdisp->vblank, i,
+               ret = nouveau_event_new(pdisp->vblank, 1, i,
                                        nouveau_display_vblank_handler,
                                        drm, &disp->vblank[i]);
                if (ret) {
index 90074d6..ab5ea3b 100644 (file)
@@ -166,7 +166,7 @@ nouveau_fence_done(struct nouveau_fence *fence)
 }
 
 static int
-nouveau_fence_wait_uevent_handler(void *data, int index)
+nouveau_fence_wait_uevent_handler(void *data, u32 type, int index)
 {
        struct nouveau_fence_priv *priv = data;
        wake_up_all(&priv->waiting);
@@ -183,7 +183,7 @@ nouveau_fence_wait_uevent(struct nouveau_fence *fence, bool intr)
        struct nouveau_eventh *handler;
        int ret = 0;
 
-       ret = nouveau_event_new(pfifo->uevent, 0,
+       ret = nouveau_event_new(pfifo->uevent, 1, 0,
                                nouveau_fence_wait_uevent_handler,
                                priv, &handler);
        if (ret)