From patchwork Tue Aug 27 20:12:58 2013 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Peter Hurley X-Patchwork-Id: 2850307 Return-Path: X-Original-To: patchwork-dri-devel@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork2.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.19.201]) by patchwork2.web.kernel.org (Postfix) with ESMTP id B1DFABF546 for ; Tue, 27 Aug 2013 20:21:19 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id 5764C2013C for ; Tue, 27 Aug 2013 20:21:13 +0000 (UTC) Received: from gabe.freedesktop.org (gabe.freedesktop.org [131.252.210.177]) by mail.kernel.org (Postfix) with ESMTP id 5C8E720414 for ; Tue, 27 Aug 2013 20:21:11 +0000 (UTC) Received: from gabe.freedesktop.org (localhost [127.0.0.1]) by gabe.freedesktop.org (Postfix) with ESMTP id B2642E5C3E for ; Tue, 27 Aug 2013 13:21:10 -0700 (PDT) X-Original-To: dri-devel@lists.freedesktop.org Delivered-To: dri-devel@lists.freedesktop.org Received: from mailout02.c08.mtsvc.net (mailout02.c08.mtsvc.net [205.186.168.190]) by gabe.freedesktop.org (Postfix) with ESMTP id DAB9DE76C6 for ; Tue, 27 Aug 2013 13:13:58 -0700 (PDT) Received: from n18.c08.mtsvc.net ([205.186.176.18]) by mailout02.c08.mtsvc.net with esmtp (Exim 4.72) (envelope-from ) id 1VEPe9-0001u9-4n; Tue, 27 Aug 2013 13:13:50 -0700 Received: from 68-184-16-174.dhcp.unas.ma.charter.com ([68.184.16.174]:56256 helo=thor.lan) by n18.c08.mtsvc.net with esmtpsa (TLS1.1:DHE_RSA_AES_256_CBC_SHA1:256) (Exim 4.80.1) (envelope-from ) id 1VEPe2-0001XP-QD; Tue, 27 Aug 2013 13:13:48 -0700 From: Peter Hurley To: Dave Airlie , Ben Skeggs Subject: [PATCH 5/9] drm/nouveau: Add install/remove semantics for event handlers Date: Tue, 27 Aug 2013 16:12:58 -0400 Message-Id: <1377634382-13872-6-git-send-email-peter@hurleysoftware.com> X-Mailer: git-send-email 1.8.1.2 In-Reply-To: <1377634382-13872-1-git-send-email-peter@hurleysoftware.com> References: <1377634382-13872-1-git-send-email-peter@hurleysoftware.com> X-Authenticated-User: 125194 peter@hurleysoftware.com X-Spam-Status: No, score=-6.7 required=5.0 tests=BAYES_00, RCVD_IN_DNSWL_MED, RP_MATCHES_RCVD, UNPARSEABLE_RELAY autolearn=unavailable version=3.3.1 X-Spam-Level: Cc: nouveau@lists.freedesktop.org, Peter Hurley , dri-devel@lists.freedesktop.org X-BeenThere: dri-devel@lists.freedesktop.org X-Mailman-Version: 2.1.13 Precedence: list List-Id: Direct Rendering Infrastructure - Development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Sender: dri-devel-bounces+patchwork-dri-devel=patchwork.kernel.org@lists.freedesktop.org Errors-To: dri-devel-bounces+patchwork-dri-devel=patchwork.kernel.org@lists.freedesktop.org X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on mail.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP Complete migration of nouveau_event_get/_put from add/remove semantics to enable/disable semantics. Introduce nouveau_event_handler_install/_remove interface to add/remove non-local-scope event handlers (ie., those stored in parent containers). This change in semantics makes explicit the handler lifetime, and distinguishes "one-of" event handlers (such as gpio) from "many temporary" event handlers (such as uevent). Signed-off-by: Peter Hurley --- drivers/gpu/drm/nouveau/core/core/event.c | 63 +++++++++++++++++++--- .../gpu/drm/nouveau/core/engine/software/nv50.c | 31 +++++++++-- .../gpu/drm/nouveau/core/engine/software/nvc0.c | 31 +++++++++-- drivers/gpu/drm/nouveau/core/include/core/event.h | 6 +++ .../gpu/drm/nouveau/core/include/engine/software.h | 2 +- drivers/gpu/drm/nouveau/nouveau_connector.c | 10 +++- drivers/gpu/drm/nouveau/nouveau_drm.c | 17 +++++- 7 files changed, 140 insertions(+), 20 deletions(-) diff --git a/drivers/gpu/drm/nouveau/core/core/event.c b/drivers/gpu/drm/nouveau/core/core/event.c index 0a65ede..4cd1ebe 100644 --- a/drivers/gpu/drm/nouveau/core/core/event.c +++ b/drivers/gpu/drm/nouveau/core/core/event.c @@ -23,19 +23,60 @@ #include #include +void +nouveau_event_handler_install(struct nouveau_event *event, int index, + int (*func)(struct nouveau_eventh*, int), + void *priv, struct nouveau_eventh *handler) +{ + unsigned long flags; + + if (index >= event->index_nr) + return; + + handler->func = func; + handler->priv = priv; + + spin_lock_irqsave(&event->lock, flags); + list_add(&handler->head, &event->index[index].list); + spin_unlock_irqrestore(&event->lock, flags); +} + +void +nouveau_event_handler_remove(struct nouveau_event *event, int index, + struct nouveau_eventh *handler) +{ + unsigned long flags; + + if (index >= event->index_nr) + return; + + spin_lock_irqsave(&event->lock, flags); + list_del(&handler->head); + spin_unlock_irqrestore(&event->lock, flags); +} + int nouveau_event_handler_create(struct nouveau_event *event, int index, int (*func)(struct nouveau_eventh*, int), void *priv, struct nouveau_eventh **phandler) { struct nouveau_eventh *handler; + unsigned long flags; handler = *phandler = kzalloc(sizeof(*handler), GFP_KERNEL); if (!handler) return -ENOMEM; handler->func = func; handler->priv = priv; - nouveau_event_get(event, index, handler); + __set_bit(NVKM_EVENT_ENABLE, &handler->flags); + + spin_lock_irqsave(&event->lock, flags); + list_add(&handler->head, &event->index[index].list); + if (!event->index[index].refs++) { + if (event->enable) + event->enable(event, index); + } + spin_unlock_irqrestore(&event->lock, flags); return 0; } @@ -43,7 +84,18 @@ void nouveau_event_handler_destroy(struct nouveau_event *event, int index, struct nouveau_eventh *handler) { - nouveau_event_put(event, index, handler); + unsigned long flags; + + if (index >= event->index_nr) + return; + + spin_lock_irqsave(&event->lock, flags); + if (!--event->index[index].refs) { + if (event->disable) + event->disable(event, index); + } + list_del(&handler->head); + spin_unlock_irqrestore(&event->lock, flags); kfree(handler); } @@ -56,7 +108,6 @@ nouveau_event_put_locked(struct nouveau_event *event, int index, if (event->disable) event->disable(event, index); } - list_del(&handler->head); } } @@ -85,7 +136,6 @@ nouveau_event_get(struct nouveau_event *event, int index, 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++) { if (event->enable) event->enable(event, index); @@ -105,8 +155,9 @@ 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) { - nouveau_event_put_locked(event, index, handler); + if (test_bit(NVKM_EVENT_ENABLE, &handler->flags)) { + if (handler->func(handler, index) == NVKM_EVENT_DROP) + nouveau_event_put_locked(event, index, handler); } } spin_unlock_irqrestore(&event->lock, flags); diff --git a/drivers/gpu/drm/nouveau/core/engine/software/nv50.c b/drivers/gpu/drm/nouveau/core/engine/software/nv50.c index c48e749..dfce1f5 100644 --- a/drivers/gpu/drm/nouveau/core/engine/software/nv50.c +++ b/drivers/gpu/drm/nouveau/core/engine/software/nv50.c @@ -97,7 +97,7 @@ nv50_software_mthd_vblsem_release(struct nouveau_object *object, u32 mthd, if (crtc > 1) return -EINVAL; - nouveau_event_get(disp->vblank, crtc, &chan->base.vblank.event); + nouveau_event_get(disp->vblank, crtc, &chan->base.vblank.event[crtc]); return 0; } @@ -135,7 +135,7 @@ static int nv50_software_vblsem_release(struct nouveau_eventh *event, int head) { struct nouveau_software_chan *chan = - container_of(event, struct nouveau_software_chan, vblank.event); + container_of(event, struct nouveau_software_chan, vblank.event[head]); struct nv50_software_priv *priv = (void *)nv_object(chan)->engine; struct nouveau_bar *bar = nouveau_bar(priv); @@ -161,7 +161,8 @@ nv50_software_context_ctor(struct nouveau_object *parent, struct nouveau_object **pobject) { struct nv50_software_chan *chan; - int ret; + struct nouveau_disp *disp = nouveau_disp(engine); + int ret, i; ret = nouveau_software_context_create(parent, engine, oclass, &chan); *pobject = nv_object(chan); @@ -169,16 +170,36 @@ nv50_software_context_ctor(struct nouveau_object *parent, return ret; chan->base.vblank.channel = nv_gpuobj(parent->parent)->addr >> 12; - chan->base.vblank.event.func = nv50_software_vblsem_release; + for (i = 0; i < ARRAY_SIZE(chan->base.vblank.event); i++) { + nouveau_event_handler_install(disp->vblank, i, + nv50_software_vblsem_release, + NULL, + &chan->base.vblank.event[i]); + } return 0; } +void +nv50_software_context_dtor(struct nouveau_object *object) +{ + struct nv50_software_chan *chan = (void *)object; + struct nv50_software_priv *priv = (void *)nv_object(chan)->engine; + struct nouveau_disp *disp = nouveau_disp(priv); + int i; + + for (i = 0; i < ARRAY_SIZE(chan->base.vblank.event); i++) { + nouveau_event_handler_remove(disp->vblank, i, + &chan->base.vblank.event[i]); + } + _nouveau_software_context_dtor(object); +} + static struct nouveau_oclass nv50_software_cclass = { .handle = NV_ENGCTX(SW, 0x50), .ofuncs = &(struct nouveau_ofuncs) { .ctor = nv50_software_context_ctor, - .dtor = _nouveau_software_context_dtor, + .dtor = nv50_software_context_dtor, .init = _nouveau_software_context_init, .fini = _nouveau_software_context_fini, }, diff --git a/drivers/gpu/drm/nouveau/core/engine/software/nvc0.c b/drivers/gpu/drm/nouveau/core/engine/software/nvc0.c index d698e71..d1f52c0 100644 --- a/drivers/gpu/drm/nouveau/core/engine/software/nvc0.c +++ b/drivers/gpu/drm/nouveau/core/engine/software/nvc0.c @@ -80,7 +80,7 @@ nvc0_software_mthd_vblsem_release(struct nouveau_object *object, u32 mthd, if ((nv_device(object)->card_type < NV_E0 && crtc > 1) || crtc > 3) return -EINVAL; - nouveau_event_get(disp->vblank, crtc, &chan->base.vblank.event); + nouveau_event_get(disp->vblank, crtc, &chan->base.vblank.event[crtc]); return 0; } @@ -147,7 +147,7 @@ static int nvc0_software_vblsem_release(struct nouveau_eventh *event, int head) { struct nouveau_software_chan *chan = - container_of(event, struct nouveau_software_chan, vblank.event); + container_of(event, struct nouveau_software_chan, vblank.event[head]); struct nvc0_software_priv *priv = (void *)nv_object(chan)->engine; struct nouveau_bar *bar = nouveau_bar(priv); @@ -167,7 +167,8 @@ nvc0_software_context_ctor(struct nouveau_object *parent, struct nouveau_object **pobject) { struct nvc0_software_chan *chan; - int ret; + struct nouveau_disp *disp = nouveau_disp(engine); + int ret, i; ret = nouveau_software_context_create(parent, engine, oclass, &chan); *pobject = nv_object(chan); @@ -175,16 +176,36 @@ nvc0_software_context_ctor(struct nouveau_object *parent, return ret; chan->base.vblank.channel = nv_gpuobj(parent->parent)->addr >> 12; - chan->base.vblank.event.func = nvc0_software_vblsem_release; + for (i = 0; i < ARRAY_SIZE(chan->base.vblank.event); i++) { + nouveau_event_handler_install(disp->vblank, i, + nvc0_software_vblsem_release, + NULL, + &chan->base.vblank.event[i]); + } return 0; } +void +nvc0_software_context_dtor(struct nouveau_object *object) +{ + struct nvc0_software_chan *chan = (void *)object; + struct nvc0_software_priv *priv = (void *)nv_object(chan)->engine; + struct nouveau_disp *disp = nouveau_disp(priv); + int i; + + for (i = 0; i < ARRAY_SIZE(chan->base.vblank.event); i++) { + nouveau_event_handler_remove(disp->vblank, i, + &chan->base.vblank.event[i]); + } + _nouveau_software_context_dtor(object); +} + static struct nouveau_oclass nvc0_software_cclass = { .handle = NV_ENGCTX(SW, 0xc0), .ofuncs = &(struct nouveau_ofuncs) { .ctor = nvc0_software_context_ctor, - .dtor = _nouveau_software_context_dtor, + .dtor = nvc0_software_context_dtor, .init = _nouveau_software_context_init, .fini = _nouveau_software_context_fini, }, diff --git a/drivers/gpu/drm/nouveau/core/include/core/event.h b/drivers/gpu/drm/nouveau/core/include/core/event.h index 3e704d5..45e8a0f 100644 --- a/drivers/gpu/drm/nouveau/core/include/core/event.h +++ b/drivers/gpu/drm/nouveau/core/include/core/event.h @@ -44,4 +44,10 @@ int nouveau_event_handler_create(struct nouveau_event *, int index, void nouveau_event_handler_destroy(struct nouveau_event *, int index, struct nouveau_eventh *); +void nouveau_event_handler_install(struct nouveau_event *, int index, + int (*func)(struct nouveau_eventh*, int), + void *priv, struct nouveau_eventh *); +void nouveau_event_handler_remove(struct nouveau_event *, int index, + struct nouveau_eventh *); + #endif diff --git a/drivers/gpu/drm/nouveau/core/include/engine/software.h b/drivers/gpu/drm/nouveau/core/include/engine/software.h index 4579948..bc26ea8 100644 --- a/drivers/gpu/drm/nouveau/core/include/engine/software.h +++ b/drivers/gpu/drm/nouveau/core/include/engine/software.h @@ -9,7 +9,7 @@ struct nouveau_software_chan { struct nouveau_engctx base; struct { - struct nouveau_eventh event; + struct nouveau_eventh event[4]; u32 channel; u32 ctxdma; u64 offset; diff --git a/drivers/gpu/drm/nouveau/nouveau_connector.c b/drivers/gpu/drm/nouveau/nouveau_connector.c index 4da776f..13b38ed 100644 --- a/drivers/gpu/drm/nouveau/nouveau_connector.c +++ b/drivers/gpu/drm/nouveau/nouveau_connector.c @@ -98,6 +98,11 @@ static void nouveau_connector_destroy(struct drm_connector *connector) { struct nouveau_connector *nv_connector = nouveau_connector(connector); + struct nouveau_drm *drm = nouveau_drm(connector->dev); + struct nouveau_gpio *gpio = nouveau_gpio(drm->device); + + nouveau_event_handler_remove(gpio->events, nv_connector->hpd.line, + &nv_connector->hpd_func); kfree(nv_connector->edid); drm_sysfs_connector_remove(connector); drm_connector_cleanup(connector); @@ -990,7 +995,10 @@ 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; + nouveau_event_handler_install(gpio->events, + nv_connector->hpd.line, + nouveau_connector_hotplug, NULL, + &nv_connector->hpd_func); if (ret) nv_connector->hpd.func = DCB_GPIO_UNUSED; diff --git a/drivers/gpu/drm/nouveau/nouveau_drm.c b/drivers/gpu/drm/nouveau/nouveau_drm.c index ccea2c4..4187cad 100644 --- a/drivers/gpu/drm/nouveau/nouveau_drm.c +++ b/drivers/gpu/drm/nouveau/nouveau_drm.c @@ -88,7 +88,6 @@ nouveau_drm_vblank_enable(struct drm_device *dev, int head) 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; } @@ -298,7 +297,8 @@ nouveau_drm_load(struct drm_device *dev, unsigned long flags) struct pci_dev *pdev = dev->pdev; struct nouveau_device *device; struct nouveau_drm *drm; - int ret; + struct nouveau_disp *disp; + int ret, i; ret = nouveau_cli_create(pdev, "DRM", sizeof(*drm), (void**)&drm); if (ret) @@ -352,6 +352,13 @@ nouveau_drm_load(struct drm_device *dev, unsigned long flags) if (nv_device(drm->device)->chipset == 0xc1) nv_mask(device, 0x00088080, 0x00000800, 0x00000000); + disp = nouveau_disp(device); + for (i = 0; i < ARRAY_SIZE(drm->vblank); i++) { + nouveau_event_handler_install(disp->vblank, i, + nouveau_drm_vblank_handler, + NULL, &drm->vblank[i]); + } + nouveau_vga_init(drm); nouveau_agp_init(drm); @@ -404,6 +411,8 @@ static int nouveau_drm_unload(struct drm_device *dev) { struct nouveau_drm *drm = nouveau_drm(dev); + struct nouveau_disp *disp = nouveau_disp(drm->device); + int i; nouveau_fbcon_fini(dev); nouveau_accel_fini(drm); @@ -420,6 +429,10 @@ nouveau_drm_unload(struct drm_device *dev) nouveau_agp_fini(drm); nouveau_vga_fini(drm); + for (i = 0; i < ARRAY_SIZE(drm->vblank); i++) + nouveau_event_handler_remove(disp->vblank, i, + &drm->vblank[i]); + nouveau_cli_destroy(&drm->client); return 0; }