Commit b182cc59 authored by Daniel Vetter's avatar Daniel Vetter Committed by Dave Airlie

drm/crtc-helper: fix locking for drm_helper_disable_unused_functions

We have two calling contexts for thise function:

- In the crtc helper code itself as part of the ->set_config
  implementation. In this calling context all modeset locks are
  already held, as they should.

- In drivers not implementing fastboot before the fbdev/fbcon setup
  and initialization. This has been added for all drivers in

  commit 76a39dbf
  Author: Daniel Vetter <daniel.vetter@ffwll.ch>
  Date:   Sun Jan 20 23:12:54 2013 +0100

      drm/fb-helper: don't disable everything in initial_config

  In this calling context we do not hold any modeset locks since the
  immediately following call to initialize the fbev emulation grabs
  all these locks themselves.

- There are two exceptions to the above rule: shmob doesn't have fbdev
  emulation support. I've manually checked the callchain up to the
  driver load function and no kms locks are held.

The right fix therefore is to split this helper into an internal and
external version and add the required locking to the function exported
to drivers.

This remedies locking inconsistencies exposed by me adding locking
WARNs as part of the recent kerneldoc abi polishing done in

commit 62ff94a5
Author: Daniel Vetter <daniel.vetter@ffwll.ch>
Date:   Thu Jan 23 22:18:47 2014 +0100

    drm/crtc-helper: remove LOCKING from kerneldoc

and

commit 63951385
Author: Daniel Vetter <daniel.vetter@ffwll.ch>
Date:   Thu Jan 23 15:14:15 2014 +0100

    drm/doc: Repleace LOCKING kerneldoc sections in drm_modes.c

v2: It helps when I actually git add the entire thing.

Cc: Chris Wilson <chris@chris-wilson.co.uk>
Signed-off-by: default avatarDaniel Vetter <daniel.vetter@ffwll.ch>
Reviewed-by: default avatarChris Wilson <chris@chris-wilson.co.uk>
Tested-by: default avatarThierry Reding <treding@nvidia.com>
Signed-off-by: default avatarDave Airlie <airlied@redhat.com>
parent 55004938
...@@ -278,17 +278,7 @@ drm_encoder_disable(struct drm_encoder *encoder) ...@@ -278,17 +278,7 @@ drm_encoder_disable(struct drm_encoder *encoder)
encoder->bridge->funcs->post_disable(encoder->bridge); encoder->bridge->funcs->post_disable(encoder->bridge);
} }
/** static void __drm_helper_disable_unused_functions(struct drm_device *dev)
* drm_helper_disable_unused_functions - disable unused objects
* @dev: DRM device
*
* This function walks through the entire mode setting configuration of @dev. It
* will remove any crtc links of unused encoders and encoder links of
* disconnected connectors. Then it will disable all unused encoders and crtcs
* either by calling their disable callback if available or by calling their
* dpms callback with DRM_MODE_DPMS_OFF.
*/
void drm_helper_disable_unused_functions(struct drm_device *dev)
{ {
struct drm_encoder *encoder; struct drm_encoder *encoder;
struct drm_connector *connector; struct drm_connector *connector;
...@@ -323,6 +313,23 @@ void drm_helper_disable_unused_functions(struct drm_device *dev) ...@@ -323,6 +313,23 @@ void drm_helper_disable_unused_functions(struct drm_device *dev)
} }
} }
} }
/**
* drm_helper_disable_unused_functions - disable unused objects
* @dev: DRM device
*
* This function walks through the entire mode setting configuration of @dev. It
* will remove any crtc links of unused encoders and encoder links of
* disconnected connectors. Then it will disable all unused encoders and crtcs
* either by calling their disable callback if available or by calling their
* dpms callback with DRM_MODE_DPMS_OFF.
*/
void drm_helper_disable_unused_functions(struct drm_device *dev)
{
drm_modeset_lock_all(dev);
__drm_helper_disable_unused_functions(dev);
drm_modeset_unlock_all(dev);
}
EXPORT_SYMBOL(drm_helper_disable_unused_functions); EXPORT_SYMBOL(drm_helper_disable_unused_functions);
/* /*
...@@ -552,7 +559,7 @@ drm_crtc_helper_disable(struct drm_crtc *crtc) ...@@ -552,7 +559,7 @@ drm_crtc_helper_disable(struct drm_crtc *crtc)
} }
} }
drm_helper_disable_unused_functions(dev); __drm_helper_disable_unused_functions(dev);
return 0; return 0;
} }
...@@ -776,7 +783,7 @@ int drm_crtc_helper_set_config(struct drm_mode_set *set) ...@@ -776,7 +783,7 @@ int drm_crtc_helper_set_config(struct drm_mode_set *set)
set->connectors[i]->funcs->dpms(set->connectors[i], DRM_MODE_DPMS_ON); set->connectors[i]->funcs->dpms(set->connectors[i], DRM_MODE_DPMS_ON);
} }
} }
drm_helper_disable_unused_functions(dev); __drm_helper_disable_unused_functions(dev);
} else if (fb_changed) { } else if (fb_changed) {
set->crtc->x = set->x; set->crtc->x = set->x;
set->crtc->y = set->y; set->crtc->y = set->y;
...@@ -1009,7 +1016,7 @@ void drm_helper_resume_force_mode(struct drm_device *dev) ...@@ -1009,7 +1016,7 @@ void drm_helper_resume_force_mode(struct drm_device *dev)
} }
/* disable the unused connectors while restoring the modesetting */ /* disable the unused connectors while restoring the modesetting */
drm_helper_disable_unused_functions(dev); __drm_helper_disable_unused_functions(dev);
} }
EXPORT_SYMBOL(drm_helper_resume_force_mode); EXPORT_SYMBOL(drm_helper_resume_force_mode);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment