linux/include/drm
Daniel Vetter 613051dac4 drm: locking&new iterators for connector_list
The requirements for connector_list locking are a bit tricky:
- We need to be able to jump over zombie conectors (i.e. with refcount
  == 0, but not yet removed from the list). If instead we require that
  there's no zombies on the list then the final kref_put must happen
  under the list protection lock, which means that locking context
  leaks all over the place. Not pretty - better to deal with zombies
  and wrap the locking just around the list_del in the destructor.

- When we walk the list we must _not_ hold the connector list lock. We
  walk the connector list at an absolutely massive amounts of places,
  if all those places can't ever call drm_connector_unreference the
  code would get unecessarily complicated.

- connector_list needs it own lock, again too many places that walk it
  that we could reuse e.g. mode_config.mutex without resulting in
  inversions.

- Lots of code uses these loops to look-up a connector, i.e. they want
  to be able to call drm_connector_reference. But on the other hand we
  want connectors to stay on that list until they're dead (i.e.
  connector_list can't hold a full reference), which means despite the
  "can't hold lock for the loop body" rule we need to make sure a
  connector doesn't suddenly become a zombie.

At first Dave&I discussed various horror-show approaches using srcu,
but turns out it's fairly easy:

- For the loop body we always hold an additional reference to the
  current connector. That means it can't zombify, and it also means
  it'll stay on the list, which means we can use it as our iterator to
  find the next connector.

- When we try to find the next connector we only have to jump over
  zombies. To make sure we don't chase bad pointers that entire loop
  is protected with the new connect_list_lock spinlock. And because we
  know that we're starting out with a non-zombie (need to drop our
  reference for the old connector only after we have our new one),
  we're guranteed to still be on the connector_list and either find
  the next non-zombie or complete the iteration.

- Only downside is that we need to make sure that the temporary
  reference for the loop body doesn't leak. iter_get/put() functions +
  lockdep make sure that's the case.

- To avoid a flag day the new iterator macro has an _iter postfix. We
  can rename it back once all the users of the unsafe version are gone
  (there's about 100 list walkers for the connector_list).

For now this patch only converts all the list walking in the core,
leaving helpers and drivers for later patches. The nice thing is that
we can now finally remove 2 FIXME comments from the
register/unregister functions.

v2:
- use irqsafe spinlocks, so that we can use this in drm_state_dump
  too.
- nuke drm_modeset_lock_all from drm_connector_init, now entirely
  cargo-culted nonsense.

v3:
- do {} while (!kref_get_unless_zero), makes for a tidier loop (Dave).
- pretty kerneldoc
- add EXPORT_SYMBOL, helpers&drivers are supposed to use this.

v4: Change lockdep annotations to only check whether we release the
iter fake lock again (i.e. make sure that iter_put is called), but
not check any locking dependecies itself. That seams to require a
recursive read lock in trylock mode.

Cc: Dave Airlie <airlied@gmail.com>
Cc: Chris Wilson <chris@chris-wilson.co.uk>
Reviewed-by: Chris Wilson <chris@chris-wilson.co.uk>
Reviewed-by: Sean Paul <seanpaul@chromium.org>
Signed-off-by: Daniel Vetter <daniel.vetter@intel.com>
Link: http://patchwork.freedesktop.org/patch/msgid/20161213230814.19598-6-daniel.vetter@ffwll.ch
2016-12-18 14:32:35 +01:00
..
bridge video: add header file for Mobile High-Definition Link (MHL) interface 2016-10-26 10:29:58 +05:30
i2c drm/i2c: tda998x: Register ASoC hdmi-codec and add audio DT binding 2016-09-07 13:10:10 +01:00
ttm Merge tag 'topic/drm-misc-2016-10-27' of git://anongit.freedesktop.org/git/drm-intel into drm-next 2016-10-28 11:33:52 +10:00
ati_pcigart.h drm: Move legacy buffer structures to <drm/drm_legacy.h> 2014-09-12 15:28:12 +02:00
drm_agpsupport.h drm: Give drm_agp_clear drm_legacy_ prefix 2016-04-27 08:41:34 +02:00
drm_atomic_helper.h drm/fence: allow fence waiting to be interrupted by userspace 2016-09-12 16:59:15 -04:00
drm_atomic.h drm: Move atomic debugfs functions into drm_crtc_internal.h 2016-12-18 14:18:12 +01:00
drm_auth.h drm: Protect master->unique with dev->master_mutex 2016-12-13 09:36:13 +01:00
drm_blend.h drm: RIP mode_config->rotation_property 2016-10-22 10:42:11 +02:00
drm_bridge.h drm: bridge: Detach bridge from encoder at encoder cleanup time 2016-12-18 16:32:49 +05:30
drm_cache.h drm: Loongson-3 doesn't fully support wc memory 2016-04-22 10:24:11 +10:00
drm_color_mgmt.h drm/doc: Document color space handling 2016-09-22 00:04:03 -07:00
drm_connector.h drm: locking&new iterators for connector_list 2016-12-18 14:32:35 +01:00
drm_crtc_helper.h drm/kms-helpers: Extract drm_modeset_helper.[hc] 2016-08-16 16:10:19 +02:00
drm_crtc.h drm: Don't include <drm/drm_encoder.h> in <drm/drm_crtc.h> 2016-12-18 16:29:29 +05:30
drm_debugfs_crc.h drm: Add API for capturing frame CRCs 2016-10-17 16:44:34 +02:00
drm_displayid.h drm/edid: add displayid detailed 1 timings to the modelist. (v1.1) 2016-05-23 11:35:31 +10:00
drm_dp_dual_mode_helper.h drm: Fix LSPCON kernel-doc 2016-10-19 18:20:40 +03:00
drm_dp_helper.h drm/dp: Factor out helper to distinguish between branch and sink devices 2016-10-25 08:53:44 +02:00
drm_dp_mst_helper.h drm/dp-mst: Missing kernel doc 2016-07-19 10:31:53 +02:00
drm_drv.h Merge tag 'drm-misc-next-2016-11-29' of git://anongit.freedesktop.org/git/drm-misc into drm-next 2016-11-30 14:28:20 +10:00
drm_edid.h drm/edid: Remove drm_select_eld 2016-11-09 13:55:13 +01:00
drm_encoder_slave.h drm: Don't include <drm/drm_encoder.h> in <drm/drm_crtc.h> 2016-12-18 16:29:29 +05:30
drm_encoder.h drm: Fix compilation warning caused by static inline forward declaration 2016-12-18 16:29:30 +05:30
drm_fb_cma_helper.h drm/fb_cma_helper: Add missing forward declaration 2016-11-15 12:24:08 +01:00
drm_fb_helper.h drm/fb-helper: add fb_debug_* to DRM_FB_HELPER_DEFAULT_OPS 2016-11-14 07:47:46 +01:00
drm_fixed.h drm: Add drm_fixp_from_fraction and drm_fixp2int_ceil 2016-02-05 15:23:48 +10:00
drm_flip_work.h drm: flip-work: change drm_flip_work_init prototype 2014-11-15 09:29:14 +10:00
drm_fourcc.h drm: move allocation out of drm_get_format_name() 2016-11-12 14:19:38 +01:00
drm_framebuffer.h drm: Nuke fb->pixel_format 2016-12-15 14:55:34 +02:00
drm_gem_cma_helper.h drm/cma: Introduce drm_gem_cma_dumb_create_internal() 2014-11-13 13:27:17 +01:00
drm_gem.h drm/doc: Fix more kerneldoc/sphinx warnings 2016-08-16 16:09:58 +02:00
drm_global.h
drm_hashtab.h drm: Add a hash-tab rcu-safe API 2012-11-28 18:36:05 +10:00
drm_irq.h drm: drm_irq.h header cleanup 2016-11-15 23:33:48 +01:00
drm_legacy.h drm: document drm_auth.c 2016-06-21 22:10:55 +02:00
drm_mem_util.h drm,i915: Introduce drm_malloc_gfp() 2016-04-11 17:13:10 +01:00
drm_mipi_dsi.h drm/dsi: Implement DCS set/get display brightness 2016-08-24 13:34:00 +02:00
drm_mm.h drm: Constify the drm_mm API 2016-12-16 14:38:49 +01:00
drm_mode_config.h drm: locking&new iterators for connector_list 2016-12-18 14:32:35 +01:00
drm_mode_object.h drm: Extract drm_bridge.h 2016-09-19 15:04:15 +02:00
drm_modes.h drm: Extract drm_bridge.h 2016-09-19 15:04:15 +02:00
drm_modeset_helper_vtables.h drm: Don't include <drm/drm_encoder.h> in <drm/drm_crtc.h> 2016-12-18 16:29:29 +05:30
drm_modeset_helper.h drm: Pass 'dev' to drm_helper_mode_fill_fb_struct() 2016-12-15 14:03:30 +02:00
drm_modeset_lock.h drm: don't let crtc_ww_class leak out 2016-11-15 08:33:35 +01:00
drm_of.h drm: mark drm_of_component_match_add dummy inline 2016-10-26 15:48:42 -04:00
drm_os_linux.h drm: Kill DRM_SUSER 2013-12-18 11:35:45 +10:00
drm_panel.h drm/panel: Flesh out kerneldoc 2016-05-06 16:04:48 +02:00
drm_pciids.h drm/radeon: add new OLAND pci id 2015-08-12 12:24:05 -04:00
drm_plane_helper.h drm/kms-helpers: Extract drm_modeset_helper.[hc] 2016-08-16 16:10:19 +02:00
drm_plane.h drm: fix possible_crtc's type 2016-12-08 13:42:57 +02:00
drm_print.h drm/print: Move kerneldoc next to definition 2016-11-15 12:55:24 +01:00
drm_property.h drm: Move a few macros away from drm_crtc.h 2016-09-19 15:03:46 +02:00
drm_rect.h drm: Add "prefix" parameter to drm_rect_debug_print() 2015-11-24 11:47:46 +01:00
drm_simple_kms_helper.h drm: bridge: Detach bridge from encoder at encoder cleanup time 2016-12-18 16:32:49 +05:30
drm_sysfs.h
drm_vma_manager.h drm: use drm_file to tag vm-bos 2016-09-19 11:22:08 +02:00
drmP.h drm/virtio: fix busid in a different way, allocate more vbufs. 2016-11-30 14:18:51 +10:00
gma_drm.h drm/gma500: Remove unused ioctls 2014-03-17 20:11:57 +01:00
i915_component.h drm/i915/dp: DP audio API changes for MST 2016-09-22 09:01:55 -07:00
i915_drm.h drm: avoid "possible bad bitmask?" warning 2016-08-09 22:18:26 +02:00
i915_pciids.h drm/i915: Remove .is_mobile field from platform struct 2016-09-07 16:07:07 -07:00
intel-gtt.h drm/i915: Add support for mapping an object page by page 2016-06-13 10:03:54 +01:00