aboutsummaryrefslogtreecommitdiff
path: root/drivers/gpu/drm
diff options
context:
space:
mode:
authorBen Skeggs <bskeggs@redhat.com>2013-10-03 07:02:29 +1000
committerBen Skeggs <bskeggs@redhat.com>2013-11-08 15:36:06 +1000
commit51cb4b392a307a8293b4f1f300ab803d7ad3b036 (patch)
tree8d3015ce594c93d63d1f4fbf025a9ceaad92ebb5 /drivers/gpu/drm
parent7589563eb34527fd1f357a1ef0dbb7ee6b02af1c (diff)
drm/nouveau/core: convert event handler apis to split create/enable semantics
This is a necessary step towards being able to work with the insane locking requirements of the DRM core's vblank routines, and a nice cleanup as a side-effect. This is similar in spirit to the interfaces that Peter Hurley arrived at with his nouveau_event rcu conversion series. Signed-off-by: Ben Skeggs <bskeggs@redhat.com>
Diffstat (limited to 'drivers/gpu/drm')
-rw-r--r--drivers/gpu/drm/nouveau/core/core/event.c75
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/software/nv50.c50
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/software/nv50.h10
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/software/nvc0.c45
-rw-r--r--drivers/gpu/drm/nouveau/core/include/core/event.h14
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_connector.c14
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_connector.h2
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_display.c95
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_display.h4
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_drm.c35
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_drm.h1
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_fence.c19
12 files changed, 226 insertions, 138 deletions
diff --git a/drivers/gpu/drm/nouveau/core/core/event.c b/drivers/gpu/drm/nouveau/core/core/event.c
index 9393c37b71c..313afcc65e0 100644
--- a/drivers/gpu/drm/nouveau/core/core/event.c
+++ b/drivers/gpu/drm/nouveau/core/core/event.c
@@ -37,39 +37,82 @@ nouveau_event_put_locked(struct nouveau_event *event, int index,
}
void
-nouveau_event_put(struct nouveau_event *event, int index,
- struct nouveau_eventh *handler)
+nouveau_event_put(struct nouveau_eventh *handler)
{
+ struct nouveau_event *event = handler->event;
unsigned long flags;
-
- if (index >= event->index_nr)
- return;
-
spin_lock_irqsave(&event->lock, flags);
- nouveau_event_put_locked(event, index, handler);
+ nouveau_event_put_locked(handler->event, handler->index, handler);
spin_unlock_irqrestore(&event->lock, flags);
}
void
-nouveau_event_get(struct nouveau_event *event, int index,
- struct nouveau_eventh *handler)
+nouveau_event_get(struct nouveau_eventh *handler)
{
+ struct nouveau_event *event = handler->event;
unsigned long flags;
- if (index >= event->index_nr)
- return;
-
spin_lock_irqsave(&event->lock, flags);
if (!__test_and_set_bit(NVKM_EVENT_ENABLE, &handler->flags)) {
- list_add(&handler->head, &event->index[index].list);
- if (!event->index[index].refs++) {
+ list_add(&handler->head, &event->index[handler->index].list);
+ if (!event->index[handler->index].refs++) {
if (event->enable)
- event->enable(event, index);
+ event->enable(event, handler->index);
}
}
spin_unlock_irqrestore(&event->lock, flags);
}
+static void
+nouveau_event_fini(struct nouveau_eventh *handler)
+{
+ nouveau_event_put(handler);
+}
+
+static int
+nouveau_event_init(struct nouveau_event *event, int index,
+ int (*func)(void *, int), void *priv,
+ struct nouveau_eventh *handler)
+{
+ if (index >= event->index_nr)
+ return -EINVAL;
+ handler->event = event;
+ handler->flags = 0;
+ handler->index = index;
+ handler->func = func;
+ handler->priv = priv;
+ return 0;
+}
+
+int
+nouveau_event_new(struct nouveau_event *event, int index,
+ int (*func)(void *, int), void *priv,
+ struct nouveau_eventh **phandler)
+{
+ struct nouveau_eventh *handler;
+ int ret = -ENOMEM;
+
+ handler = *phandler = kmalloc(sizeof(*handler), GFP_KERNEL);
+ if (handler) {
+ ret = nouveau_event_init(event, index, func, priv, handler);
+ if (ret)
+ kfree(handler);
+ }
+
+ return ret;
+}
+
+void
+nouveau_event_ref(struct nouveau_eventh *handler, struct nouveau_eventh **ref)
+{
+ BUG_ON(handler != NULL);
+ if (*ref) {
+ nouveau_event_fini(*ref);
+ kfree(*ref);
+ }
+ *ref = handler;
+}
+
void
nouveau_event_trigger(struct nouveau_event *event, int index)
{
@@ -81,7 +124,7 @@ nouveau_event_trigger(struct nouveau_event *event, int index)
spin_lock_irqsave(&event->lock, flags);
list_for_each_entry_safe(handler, temp, &event->index[index].list, head) {
- if (handler->func(handler, index) == NVKM_EVENT_DROP) {
+ if (handler->func(handler->priv, index) == NVKM_EVENT_DROP) {
nouveau_event_put_locked(event, index, handler);
}
}
diff --git a/drivers/gpu/drm/nouveau/core/engine/software/nv50.c b/drivers/gpu/drm/nouveau/core/engine/software/nv50.c
index 5236a1430ef..b574dd4bb82 100644
--- a/drivers/gpu/drm/nouveau/core/engine/software/nv50.c
+++ b/drivers/gpu/drm/nouveau/core/engine/software/nv50.c
@@ -71,7 +71,7 @@ nv50_software_mthd_vblsem_offset(struct nouveau_object *object, u32 mthd,
return 0;
}
-static int
+int
nv50_software_mthd_vblsem_value(struct nouveau_object *object, u32 mthd,
void *args, u32 size)
{
@@ -80,21 +80,20 @@ nv50_software_mthd_vblsem_value(struct nouveau_object *object, u32 mthd,
return 0;
}
-static int
+int
nv50_software_mthd_vblsem_release(struct nouveau_object *object, u32 mthd,
void *args, u32 size)
{
struct nv50_software_chan *chan = (void *)nv_engctx(object->parent);
- struct nouveau_disp *disp = nouveau_disp(object);
- u32 crtc = *(u32 *)args;
- if (crtc > 1)
+ u32 head = *(u32 *)args;
+ if (head >= chan->vblank.nr_event)
return -EINVAL;
- nouveau_event_get(disp->vblank, crtc, &chan->vblank.event);
+ nouveau_event_get(chan->vblank.event[head]);
return 0;
}
-static int
+int
nv50_software_mthd_flip(struct nouveau_object *object, u32 mthd,
void *args, u32 size)
{
@@ -125,10 +124,9 @@ nv50_software_sclass[] = {
******************************************************************************/
static int
-nv50_software_vblsem_release(struct nouveau_eventh *event, int head)
+nv50_software_vblsem_release(void *data, int head)
{
- struct nv50_software_chan *chan =
- container_of(event, typeof(*chan), vblank.event);
+ struct nv50_software_chan *chan = data;
struct nv50_software_priv *priv = (void *)nv_object(chan)->engine;
struct nouveau_bar *bar = nouveau_bar(priv);
@@ -147,23 +145,51 @@ nv50_software_vblsem_release(struct nouveau_eventh *event, int head)
return NVKM_EVENT_DROP;
}
+void
+nv50_software_context_dtor(struct nouveau_object *object)
+{
+ struct nv50_software_chan *chan = (void *)object;
+ int i;
+
+ if (chan->vblank.event) {
+ for (i = 0; i < chan->vblank.nr_event; i++)
+ nouveau_event_ref(NULL, &chan->vblank.event[i]);
+ kfree(chan->vblank.event);
+ }
+
+ nouveau_software_context_destroy(&chan->base);
+}
+
int
nv50_software_context_ctor(struct nouveau_object *parent,
struct nouveau_object *engine,
struct nouveau_oclass *oclass, void *data, u32 size,
struct nouveau_object **pobject)
{
+ struct nouveau_disp *pdisp = nouveau_disp(parent);
struct nv50_software_cclass *pclass = (void *)oclass;
struct nv50_software_chan *chan;
- int ret;
+ int ret, i;
ret = nouveau_software_context_create(parent, engine, oclass, &chan);
*pobject = nv_object(chan);
if (ret)
return ret;
+ chan->vblank.nr_event = pdisp->vblank->index_nr;
+ chan->vblank.event = kzalloc(chan->vblank.nr_event *
+ sizeof(*chan->vblank.event), GFP_KERNEL);
+ if (!chan->vblank.event)
+ return -ENOMEM;
+
+ for (i = 0; i < chan->vblank.nr_event; i++) {
+ ret = nouveau_event_new(pdisp->vblank, i, pclass->vblank,
+ chan, &chan->vblank.event[i]);
+ if (ret)
+ return ret;
+ }
+
chan->vblank.channel = nv_gpuobj(parent->parent)->addr >> 12;
- chan->vblank.event.func = pclass->vblank;
return 0;
}
diff --git a/drivers/gpu/drm/nouveau/core/engine/software/nv50.h b/drivers/gpu/drm/nouveau/core/engine/software/nv50.h
index 2c0b1b42b86..2de370c2127 100644
--- a/drivers/gpu/drm/nouveau/core/engine/software/nv50.h
+++ b/drivers/gpu/drm/nouveau/core/engine/software/nv50.h
@@ -19,13 +19,14 @@ int nv50_software_ctor(struct nouveau_object *, struct nouveau_object *,
struct nv50_software_cclass {
struct nouveau_oclass base;
- int (*vblank)(struct nouveau_eventh *, int);
+ int (*vblank)(void *, int);
};
struct nv50_software_chan {
struct nouveau_software_chan base;
struct {
- struct nouveau_eventh event;
+ struct nouveau_eventh **event;
+ int nr_event;
u32 channel;
u32 ctxdma;
u64 offset;
@@ -37,5 +38,10 @@ int nv50_software_context_ctor(struct nouveau_object *,
struct nouveau_object *,
struct nouveau_oclass *, void *, u32,
struct nouveau_object **);
+void nv50_software_context_dtor(struct nouveau_object *);
+
+int nv50_software_mthd_vblsem_value(struct nouveau_object *, u32, void *, u32);
+int nv50_software_mthd_vblsem_release(struct nouveau_object *, u32, void *, u32);
+int nv50_software_mthd_flip(struct nouveau_object *, u32, void *, u32);
#endif
diff --git a/drivers/gpu/drm/nouveau/core/engine/software/nvc0.c b/drivers/gpu/drm/nouveau/core/engine/software/nvc0.c
index 27e47230e3e..f9430c1bf3e 100644
--- a/drivers/gpu/drm/nouveau/core/engine/software/nvc0.c
+++ b/drivers/gpu/drm/nouveau/core/engine/software/nvc0.c
@@ -55,40 +55,6 @@ nvc0_software_mthd_vblsem_offset(struct nouveau_object *object, u32 mthd,
}
static int
-nvc0_software_mthd_vblsem_value(struct nouveau_object *object, u32 mthd,
- void *args, u32 size)
-{
- struct nv50_software_chan *chan = (void *)nv_engctx(object->parent);
- chan->vblank.value = *(u32 *)args;
- return 0;
-}
-
-static int
-nvc0_software_mthd_vblsem_release(struct nouveau_object *object, u32 mthd,
- void *args, u32 size)
-{
- struct nv50_software_chan *chan = (void *)nv_engctx(object->parent);
- struct nouveau_disp *disp = nouveau_disp(object);
- u32 crtc = *(u32 *)args;
-
- if ((nv_device(object)->card_type < NV_E0 && crtc > 1) || crtc > 3)
- return -EINVAL;
-
- nouveau_event_get(disp->vblank, crtc, &chan->vblank.event);
- return 0;
-}
-
-static int
-nvc0_software_mthd_flip(struct nouveau_object *object, u32 mthd,
- void *args, u32 size)
-{
- struct nv50_software_chan *chan = (void *)nv_engctx(object->parent);
- if (chan->base.flip)
- return chan->base.flip(chan->base.flip_data);
- return -EINVAL;
-}
-
-static int
nvc0_software_mthd_mp_control(struct nouveau_object *object, u32 mthd,
void *args, u32 size)
{
@@ -118,9 +84,9 @@ static struct nouveau_omthds
nvc0_software_omthds[] = {
{ 0x0400, 0x0400, nvc0_software_mthd_vblsem_offset },
{ 0x0404, 0x0404, nvc0_software_mthd_vblsem_offset },
- { 0x0408, 0x0408, nvc0_software_mthd_vblsem_value },
- { 0x040c, 0x040c, nvc0_software_mthd_vblsem_release },
- { 0x0500, 0x0500, nvc0_software_mthd_flip },
+ { 0x0408, 0x0408, nv50_software_mthd_vblsem_value },
+ { 0x040c, 0x040c, nv50_software_mthd_vblsem_release },
+ { 0x0500, 0x0500, nv50_software_mthd_flip },
{ 0x0600, 0x0600, nvc0_software_mthd_mp_control },
{ 0x0644, 0x0644, nvc0_software_mthd_mp_control },
{ 0x06ac, 0x06ac, nvc0_software_mthd_mp_control },
@@ -138,10 +104,9 @@ nvc0_software_sclass[] = {
******************************************************************************/
static int
-nvc0_software_vblsem_release(struct nouveau_eventh *event, int head)
+nvc0_software_vblsem_release(void *data, int head)
{
- struct nv50_software_chan *chan =
- container_of(event, typeof(*chan), vblank.event);
+ struct nv50_software_chan *chan = data;
struct nv50_software_priv *priv = (void *)nv_object(chan)->engine;
struct nouveau_bar *bar = nouveau_bar(priv);
diff --git a/drivers/gpu/drm/nouveau/core/include/core/event.h b/drivers/gpu/drm/nouveau/core/include/core/event.h
index cb2f632cb3a..b649c75d719 100644
--- a/drivers/gpu/drm/nouveau/core/include/core/event.h
+++ b/drivers/gpu/drm/nouveau/core/include/core/event.h
@@ -9,10 +9,12 @@
#define NVKM_EVENT_ENABLE 0
struct nouveau_eventh {
+ struct nouveau_event *event;
struct list_head head;
unsigned long flags;
+ int index;
+ int (*func)(void *, int);
void *priv;
- int (*func)(struct nouveau_eventh *, int index);
};
struct nouveau_event {
@@ -33,9 +35,11 @@ int nouveau_event_create(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_get(struct nouveau_event *, int index,
- struct nouveau_eventh *);
-void nouveau_event_put(struct nouveau_event *, int index,
- struct nouveau_eventh *);
+int nouveau_event_new(struct nouveau_event *, int index,
+ int (*func)(void *, int), void *,
+ struct nouveau_eventh **);
+void nouveau_event_ref(struct nouveau_eventh *, struct nouveau_eventh **);
+void nouveau_event_get(struct nouveau_eventh *);
+void nouveau_event_put(struct nouveau_eventh *);
#endif
diff --git a/drivers/gpu/drm/nouveau/nouveau_connector.c b/drivers/gpu/drm/nouveau/nouveau_connector.c
index 2136d003825..1aa682494a1 100644
--- a/drivers/gpu/drm/nouveau/nouveau_connector.c
+++ b/drivers/gpu/drm/nouveau/nouveau_connector.c
@@ -100,6 +100,7 @@ static void
nouveau_connector_destroy(struct drm_connector *connector)
{
struct nouveau_connector *nv_connector = nouveau_connector(connector);
+ nouveau_event_ref(NULL, &nv_connector->hpd_func);
kfree(nv_connector->edid);
drm_sysfs_connector_remove(connector);
drm_connector_cleanup(connector);
@@ -932,10 +933,9 @@ nouveau_connector_hotplug_work(struct work_struct *work)
}
static int
-nouveau_connector_hotplug(struct nouveau_eventh *event, int index)
+nouveau_connector_hotplug(void *data, int index)
{
- struct nouveau_connector *nv_connector =
- container_of(event, struct nouveau_connector, hpd_func);
+ struct nouveau_connector *nv_connector = data;
schedule_work(&nv_connector->hpd_work);
return NVKM_EVENT_KEEP;
}
@@ -1007,10 +1007,16 @@ nouveau_connector_create(struct drm_device *dev, int index)
ret = gpio->find(gpio, 0, hpd[ffs((entry & 0x07033000) >> 12)],
DCB_GPIO_UNUSED, &nv_connector->hpd);
- nv_connector->hpd_func.func = nouveau_connector_hotplug;
if (ret)
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_connector_hotplug,
+ nv_connector,
+ &nv_connector->hpd_func);
+ }
+
nv_connector->type = nv_connector->dcb[0];
if (drm_conntype_from_dcb(nv_connector->type) ==
DRM_MODE_CONNECTOR_Unknown) {
diff --git a/drivers/gpu/drm/nouveau/nouveau_connector.h b/drivers/gpu/drm/nouveau/nouveau_connector.h
index 6e399aad491..27c2be68810 100644
--- a/drivers/gpu/drm/nouveau/nouveau_connector.h
+++ b/drivers/gpu/drm/nouveau/nouveau_connector.h
@@ -69,7 +69,7 @@ struct nouveau_connector {
struct dcb_gpio_func hpd;
struct work_struct hpd_work;
- struct nouveau_eventh hpd_func;
+ struct nouveau_eventh *hpd_func;
int dithering_mode;
int dithering_depth;
diff --git a/drivers/gpu/drm/nouveau/nouveau_display.c b/drivers/gpu/drm/nouveau/nouveau_display.c
index bdd5cf71a24..510d13ee1a0 100644
--- a/drivers/gpu/drm/nouveau/nouveau_display.c
+++ b/drivers/gpu/drm/nouveau/nouveau_display.c
@@ -38,12 +38,85 @@
#include "nouveau_fence.h"
-#include <subdev/bios/gpio.h>
-#include <subdev/gpio.h>
#include <engine/disp.h>
#include <core/class.h>
+static int
+nouveau_display_vblank_handler(void *data, int head)
+{
+ struct nouveau_drm *drm = data;
+ drm_handle_vblank(drm->dev, head);
+ return NVKM_EVENT_KEEP;
+}
+
+int
+nouveau_display_vblank_enable(struct drm_device *dev, int head)
+{
+ struct nouveau_display *disp = nouveau_display(dev);
+ if (disp) {
+ nouveau_event_get(disp->vblank[head]);
+ return 0;
+ }
+ return -EIO;
+}
+
+void
+nouveau_display_vblank_disable(struct drm_device *dev, int head)
+{
+ struct nouveau_display *disp = nouveau_display(dev);
+ if (disp)
+ nouveau_event_put(disp->vblank[head]);
+}
+
+static void
+nouveau_display_vblank_fini(struct drm_device *dev)
+{
+ struct nouveau_display *disp = nouveau_display(dev);
+ int i;
+
+ if (disp->vblank) {
+ for (i = 0; i < dev->mode_config.num_crtc; i++)
+ nouveau_event_ref(NULL, &disp->vblank[i]);
+ kfree(disp->vblank);
+ disp->vblank = NULL;
+ }
+
+ drm_vblank_cleanup(dev);
+}
+
+static int
+nouveau_display_vblank_init(struct drm_device *dev)
+{
+ struct nouveau_display *disp = nouveau_display(dev);
+ struct nouveau_drm *drm = nouveau_drm(dev);
+ struct nouveau_disp *pdisp = nouveau_disp(drm->device);
+ int ret, i;
+
+ disp->vblank = kzalloc(dev->mode_config.num_crtc *
+ sizeof(*disp->vblank), GFP_KERNEL);
+ if (!disp->vblank)
+ return -ENOMEM;
+
+ for (i = 0; i < dev->mode_config.num_crtc; i++) {
+ ret = nouveau_event_new(pdisp->vblank, i,
+ nouveau_display_vblank_handler,
+ drm, &disp->vblank[i]);
+ if (ret) {
+ nouveau_display_vblank_fini(dev);
+ return ret;
+ }
+ }
+
+ ret = drm_vblank_init(dev, dev->mode_config.num_crtc);
+ if (ret) {
+ nouveau_display_vblank_fini(dev);
+ return ret;
+ }
+
+ return 0;
+}
+
static void
nouveau_user_framebuffer_destroy(struct drm_framebuffer *drm_fb)
{
@@ -227,9 +300,7 @@ static struct nouveau_drm_prop_enum_list dither_depth[] = {
int
nouveau_display_init(struct drm_device *dev)
{
- struct nouveau_drm *drm = nouveau_drm(dev);
struct nouveau_display *disp = nouveau_display(dev);
- struct nouveau_gpio *gpio = nouveau_gpio(drm->device);
struct drm_connector *connector;
int ret;
@@ -243,10 +314,7 @@ nouveau_display_init(struct drm_device *dev)
/* enable hotplug interrupts */
list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
struct nouveau_connector *conn = nouveau_connector(connector);
- if (gpio && conn->hpd.func != DCB_GPIO_UNUSED) {
- nouveau_event_get(gpio->events, conn->hpd.line,
- &conn->hpd_func);
- }
+ if (conn->hpd_func) nouveau_event_get(conn->hpd_func);
}
return ret;
@@ -255,18 +323,13 @@ nouveau_display_init(struct drm_device *dev)
void
nouveau_display_fini(struct drm_device *dev)
{
- struct nouveau_drm *drm = nouveau_drm(dev);
struct nouveau_display *disp = nouveau_display(dev);
- struct nouveau_gpio *gpio = nouveau_gpio(drm->device);
struct drm_connector *connector;
/* disable hotplug interrupts */
list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
struct nouveau_connector *conn = nouveau_connector(connector);
- if (gpio && conn->hpd.func != DCB_GPIO_UNUSED) {
- nouveau_event_put(gpio->events, conn->hpd.line,
- &conn->hpd_func);
- }
+ if (conn->hpd_func) nouveau_event_put(conn->hpd_func);
}
drm_kms_helper_poll_disable(dev);
@@ -352,7 +415,7 @@ nouveau_display_create(struct drm_device *dev)
goto disp_create_err;
if (dev->mode_config.num_crtc) {
- ret = drm_vblank_init(dev, dev->mode_config.num_crtc);
+ ret = nouveau_display_vblank_init(dev);
if (ret)
goto vblank_err;
}
@@ -374,7 +437,7 @@ nouveau_display_destroy(struct drm_device *dev)
struct nouveau_display *disp = nouveau_display(dev);
nouveau_backlight_exit(dev);
- drm_vblank_cleanup(dev);
+ nouveau_display_vblank_fini(dev);
drm_kms_helper_poll_fini(dev);
drm_mode_config_cleanup(dev);
diff --git a/drivers/gpu/drm/nouveau/nouveau_display.h b/drivers/gpu/drm/nouveau/nouveau_display.h
index 025c66f8e0e..8bc8bab90e8 100644
--- a/drivers/gpu/drm/nouveau/nouveau_display.h
+++ b/drivers/gpu/drm/nouveau/nouveau_display.h
@@ -36,6 +36,8 @@ struct nouveau_display {
int (*init)(struct drm_device *);
void (*fini)(struct drm_device *);
+ struct nouveau_eventh **vblank;
+
struct drm_property *dithering_mode;
struct drm_property *dithering_depth;
struct drm_property *underscan_property;
@@ -59,6 +61,8 @@ void nouveau_display_fini(struct drm_device *dev);
int nouveau_display_suspend(struct drm_device *dev);
void nouveau_display_repin(struct drm_device *dev);
void nouveau_display_resume(struct drm_device *dev);
+int nouveau_display_vblank_enable(struct drm_device *, int);
+void nouveau_display_vblank_disable(struct drm_device *, int);
int nouveau_crtc_page_flip(struct drm_crtc *crtc, struct drm_framebuffer *fb,
struct drm_pending_vblank_event *event,
diff --git a/drivers/gpu/drm/nouveau/nouveau_drm.c b/drivers/gpu/drm/nouveau/nouveau_drm.c
index 42e30e256cd..69bf82d126e 100644
--- a/drivers/gpu/drm/nouveau/nouveau_drm.c
+++ b/drivers/gpu/drm/nouveau/nouveau_drm.c
@@ -78,37 +78,6 @@ module_param_named(runpm, nouveau_runtime_pm, int, 0400);
static struct drm_driver driver;
-static int
-nouveau_drm_vblank_handler(struct nouveau_eventh *event, int head)
-{
- struct nouveau_drm *drm =
- container_of(event, struct nouveau_drm, vblank[head]);
- drm_handle_vblank(drm->dev, head);
- return NVKM_EVENT_KEEP;
-}
-
-static int
-nouveau_drm_vblank_enable(struct drm_device *dev, int head)
-{
- struct nouveau_drm *drm = nouveau_drm(dev);
- struct nouveau_disp *pdisp = nouveau_disp(drm->device);
-
- if (WARN_ON_ONCE(head >= ARRAY_SIZE(drm->vblank)))
- return -EIO;
- drm->vblank[head].func = nouveau_drm_vblank_handler;
- nouveau_event_get(pdisp->vblank, head, &drm->vblank[head]);
- return 0;
-}
-
-static void
-nouveau_drm_vblank_disable(struct drm_device *dev, int head)
-{
- struct nouveau_drm *drm = nouveau_drm(dev);
- struct nouveau_disp *pdisp = nouveau_disp(drm->device);
-
- nouveau_event_put(pdisp->vblank, head, &drm->vblank[head]);
-}
-
static u64
nouveau_name(struct pci_dev *pdev)
{
@@ -812,8 +781,8 @@ driver = {
#endif
.get_vblank_counter = drm_vblank_count,
- .enable_vblank = nouveau_drm_vblank_enable,
- .disable_vblank = nouveau_drm_vblank_disable,
+ .enable_vblank = nouveau_display_vblank_enable,
+ .disable_vblank = nouveau_display_vblank_disable,
.ioctls = nouveau_ioctls,
.num_ioctls = ARRAY_SIZE(nouveau_ioctls),
diff --git a/drivers/gpu/drm/nouveau/nouveau_drm.h b/drivers/gpu/drm/nouveau/nouveau_drm.h
index 994fd6ec373..910448f2b85 100644
--- a/drivers/gpu/drm/nouveau/nouveau_drm.h
+++ b/drivers/gpu/drm/nouveau/nouveau_drm.h
@@ -127,7 +127,6 @@ struct nouveau_drm {
struct nvbios vbios;
struct nouveau_display *display;
struct backlight_device *backlight;
- struct nouveau_eventh vblank[4];
/* power management */
struct nouveau_pm *pm;
diff --git a/drivers/gpu/drm/nouveau/nouveau_fence.c b/drivers/gpu/drm/nouveau/nouveau_fence.c
index c2e31677d03..34b82711e7c 100644
--- a/drivers/gpu/drm/nouveau/nouveau_fence.c
+++ b/drivers/gpu/drm/nouveau/nouveau_fence.c
@@ -166,9 +166,9 @@ nouveau_fence_done(struct nouveau_fence *fence)
}
static int
-nouveau_fence_wait_uevent_handler(struct nouveau_eventh *handler, int index)
+nouveau_fence_wait_uevent_handler(void *data, int index)
{
- struct nouveau_fence_priv *priv = handler->priv;
+ struct nouveau_fence_priv *priv = data;
wake_up_all(&priv->waiting);
return NVKM_EVENT_KEEP;
}
@@ -180,13 +180,16 @@ nouveau_fence_wait_uevent(struct nouveau_fence *fence, bool intr)
struct nouveau_channel *chan = fence->channel;
struct nouveau_fifo *pfifo = nouveau_fifo(chan->drm->device);
struct nouveau_fence_priv *priv = chan->drm->fence;
- struct nouveau_eventh handler = {
- .func = nouveau_fence_wait_uevent_handler,
- .priv = priv,
- };
+ struct nouveau_eventh *handler;
int ret = 0;
- nouveau_event_get(pfifo->uevent, 0, &handler);
+ ret = nouveau_event_new(pfifo->uevent, 0,
+ nouveau_fence_wait_uevent_handler,
+ priv, &handler);
+ if (ret)
+ return ret;
+
+ nouveau_event_get(handler);
if (fence->timeout) {
unsigned long timeout = fence->timeout - jiffies;
@@ -218,7 +221,7 @@ nouveau_fence_wait_uevent(struct nouveau_fence *fence, bool intr)
}
}
- nouveau_event_put(pfifo->uevent, 0, &handler);
+ nouveau_event_ref(NULL, &handler);
if (unlikely(ret < 0))
return ret;