[PATCH 0/9] drm/nouveau: Cleanup event/handler design

Ben Skeggs skeggsb at gmail.com
Wed Aug 28 00:15:34 PDT 2013


On Wed, Aug 28, 2013 at 6:12 AM, Peter Hurley <peter at hurleysoftware.com> wrote:
> This series was originally motivated by a deadlock, introduced in
> commit 1d7c71a3e2f77336df536855b0efd2dc5bdeb41b
> 'drm/nouveau/disp: port vblank handling to event interface',
> due to inverted lock order between nouveau_drm_vblank_enable()
> and nouveau_drm_vblank_handler() (the complete
> lockdep report is included in the patch 4/5 changelog).
Hey Peter,

Thanks for the patch series.  I've only taken a cursory glance through
the patches thus far, as they're definitely too intrusive for -fixes
at this point.  I will take a proper look through the series within
the next week or so, I have some work pending which may possibly make
some of these changes unnecessary, though from what I can tell,
there's other good bits here we'll want.

In a previous mail on the locking issue, you mentioned the drm core
doing the "wrong thing" here too, did you have any further thoughts on
correcting that issue too?

Ben.

>
> Because this series fixes the vblank event deadlock, it is
> a competing solution to Maarten Lankhorst's 'drm/nouveau:
> fix vblank deadlock'.
>
> This series fixes the vblank event deadlock by converting the
> event handler list to RCU. This solution allows the event trigger
> to be lockless, and thus avoiding the lock inversion.
>
> Typical hurdles to RCU conversion include: 1) ensuring the
> object lifetime exceeds the lockless access; 2) preventing
> premature object reuse; and 3) verifying that stale object
> use not present logical errors.
>
> Because object reuse is not safe in RCU-based operations,
> the nouveau_event_get/_put interface is migrated from
> add/remove semantics to enable/disable semantics with a separate
> install/remove step (which also serves to document the
> handler lifetime). This also corrects an unsafe interface design
> where handlers can mistakenly be reused while in use.
>
> The nouveau driver currently supports 4 events -- gpio, uevent, cevent,
> and vblank. Every event is created by and stored within its
> respective subdev/engine object -- gpio in the GPIO subdev, uevent
> and cevent in the FIFO engine, and vblank in the DISP engine.
> Thus event lifetime extends until the subdev is destructed during
> devobj teardown.
>
> Event handler lifetime varies and is detailed in the table below
> (apologies for the wide-format):
>
> Event  Handler function                   Container                     Until
> -----  ----------------                   ---------------               ------------------
> gpio   nouveau_connector_hotplug          struct nouveau_connector      nouveau_connector_destroy
> uevent nouveau_fence_wait_uevent_handler  local stack object            nouveau_fence_wait_uevent returns
> cevent none                               n/a                           n/a
> vblank nouveau_drm_vblank_handler         struct nouveau_drm            nouveau_drm_remove
> vblank nv50_software_vblsem_release       struct nouveau_software_chan  _nouveau_engctx_dtor
>                                                                           (call stack originates with
>                                                                            nouveau_abi16_chan_free ioctl)
> vblank nvc0_software_vblsem_release       struct nouveau_software_chan  same as above
>
>
> RCU lifetime considerations for handlers:
>
> Event  Handler                            Lifetime
> -----  ----------------                   ---------------------------------
> gpio   nouveau_connector_hotplug          kfree_rcu(nv_connector)
> uevent nouveau_fence_wait_uevent_handler  explicit use of nouveau_event_hander_create/_destroy
> cevent none                               n/a
> vblank nouveau_drm_vblank_handler         synchronize_rcu() in nouveau_drm_unload
> vblank nv50_software_vblsem_release       synchronize_rcu() in container dtor
> vblank nvc0_software_vblsem_release       synchronize_rcu() in container dtor
>
> synchronize_rcu() is used for nouveau_object-based containers for which
> kfree_rcu() is not suitable/possible.
>
> Stale event handler execution is not a concern for the existing handlers
> because either: 1) the handler is responsible for disabling itself (via
> returning NVKM_EVENT_DROP), or 2) the existing handler can already be stale,
> as is the case with nouveau_connector_hotplug, which only schedules a work
> item, and nouveau_drm_vblank_handler, which the drm core expects may be stale.
>
>
> Peter Hurley (9):
>   drm/nouveau: Add priv field for event handlers
>   drm/nouveau: Move event index check from critical section
>   drm/nouveau: Allocate local event handlers
>   drm/nouveau: Allow asymmetric nouveau_event_get/_put
>   drm/nouveau: Add install/remove semantics for event handlers
>   drm/nouveau: Convert event handler list to RCU
>   drm/nouveau: Fold nouveau_event_put_locked into caller
>   drm/nouveau: Simplify event interface
>   drm/nouveau: Simplify event handler interface
>
>  drivers/gpu/drm/nouveau/core/core/event.c          | 121 +++++++++++++++++----
>  .../gpu/drm/nouveau/core/engine/software/nv50.c    |  32 ++++--
>  .../gpu/drm/nouveau/core/engine/software/nvc0.c    |  32 ++++--
>  drivers/gpu/drm/nouveau/core/include/core/event.h  |  27 ++++-
>  .../gpu/drm/nouveau/core/include/engine/software.h |   2 +-
>  drivers/gpu/drm/nouveau/nouveau_connector.c        |  16 ++-
>  drivers/gpu/drm/nouveau/nouveau_display.c          |  16 +--
>  drivers/gpu/drm/nouveau/nouveau_drm.c              |  35 +++---
>  drivers/gpu/drm/nouveau/nouveau_fence.c            |  27 ++---
>  9 files changed, 220 insertions(+), 88 deletions(-)
>
> --
> 1.8.1.2
>
> _______________________________________________
> dri-devel mailing list
> dri-devel at lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/dri-devel


More information about the dri-devel mailing list