Loading drivers/gpu/drm/nouveau/core/core/event.c +58 −25 Original line number Diff line number Diff line Loading @@ -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)) { u32 m, t; if (!__test_and_clear_bit(NVKM_EVENT_ENABLE, &handler->flags)) return; spin_lock_irqsave(&event->refs_lock, flags); if (!--event->index[handler->index].refs) { 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 Loading @@ -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)) { u32 m, t; if (__test_and_set_bit(NVKM_EVENT_ENABLE, &handler->flags)) return; spin_lock_irqsave(&event->refs_lock, flags); if (!event->index[handler->index].refs++) { 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 Loading @@ -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); } Loading @@ -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; Loading @@ -125,9 +146,14 @@ 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) 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); Loading @@ -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; } drivers/gpu/drm/nouveau/core/engine/disp/base.c +1 −1 Original line number Diff line number Diff line Loading @@ -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); } drivers/gpu/drm/nouveau/core/engine/disp/nv04.c +4 −4 Original line number Diff line number Diff line Loading @@ -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); } Loading @@ -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); } Loading drivers/gpu/drm/nouveau/core/engine/disp/nv50.c +4 −4 Original line number Diff line number Diff line Loading @@ -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); } Loading Loading @@ -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; } Loading drivers/gpu/drm/nouveau/core/engine/disp/nvd0.c +3 −3 Original line number Diff line number Diff line Loading @@ -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); } Loading Loading @@ -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)); } Loading Loading
drivers/gpu/drm/nouveau/core/core/event.c +58 −25 Original line number Diff line number Diff line Loading @@ -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)) { u32 m, t; if (!__test_and_clear_bit(NVKM_EVENT_ENABLE, &handler->flags)) return; spin_lock_irqsave(&event->refs_lock, flags); if (!--event->index[handler->index].refs) { 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 Loading @@ -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)) { u32 m, t; if (__test_and_set_bit(NVKM_EVENT_ENABLE, &handler->flags)) return; spin_lock_irqsave(&event->refs_lock, flags); if (!event->index[handler->index].refs++) { 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 Loading @@ -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); } Loading @@ -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; Loading @@ -125,9 +146,14 @@ 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) 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); Loading @@ -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; }
drivers/gpu/drm/nouveau/core/engine/disp/base.c +1 −1 Original line number Diff line number Diff line Loading @@ -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); }
drivers/gpu/drm/nouveau/core/engine/disp/nv04.c +4 −4 Original line number Diff line number Diff line Loading @@ -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); } Loading @@ -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); } Loading
drivers/gpu/drm/nouveau/core/engine/disp/nv50.c +4 −4 Original line number Diff line number Diff line Loading @@ -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); } Loading Loading @@ -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; } Loading
drivers/gpu/drm/nouveau/core/engine/disp/nvd0.c +3 −3 Original line number Diff line number Diff line Loading @@ -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); } Loading Loading @@ -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)); } Loading