From: Dave Airlie <airlied@xxxxxxxxxx> In order to avoid a lockdep between pm resume and output poll over the mode_config mutex we need to order the wakeup of the device before we take the mode config mutex (as pm resume can also try and take the mode config mutex). This introduces an API for drivers to insert themselves into the output poll path to do pm gets before taking the mutex. Signed-off-by: Dave Airlie <airlied@xxxxxxxxxx> --- drivers/gpu/drm/drm_probe_helper.c | 25 ++++++++++++++++++++++--- include/drm/drm_crtc_helper.h | 2 +- include/drm/drm_mode_config.h | 8 ++++++++ 3 files changed, 31 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/drm_probe_helper.c b/drivers/gpu/drm/drm_probe_helper.c index 97a3289..a2896d8 100644 --- a/drivers/gpu/drm/drm_probe_helper.c +++ b/drivers/gpu/drm/drm_probe_helper.c @@ -380,10 +380,15 @@ void drm_kms_helper_hotplug_event(struct drm_device *dev) } EXPORT_SYMBOL(drm_kms_helper_hotplug_event); -static void output_poll_execute(struct work_struct *work) +/** + * drm_kms_helper_poll_outputs - poll all the outputs for hotplug + * @dev: drm_device to probe outputs on. + * + * This is to be called by drivers that need to wrap the output poll + * execution for power management purposes. + */ +bool drm_kms_helper_poll_outputs(struct drm_device *dev) { - struct delayed_work *delayed_work = to_delayed_work(work); - struct drm_device *dev = container_of(delayed_work, struct drm_device, mode_config.output_poll_work); struct drm_connector *connector; struct drm_connector_list_iter conn_iter; enum drm_connector_status old_status; @@ -463,6 +468,20 @@ static void output_poll_execute(struct work_struct *work) if (changed) drm_kms_helper_hotplug_event(dev); + return repoll; +} +EXPORT_SYMBOL(drm_kms_helper_poll_outputs); + +static void output_poll_execute(struct work_struct *work) +{ + struct delayed_work *delayed_work = to_delayed_work(work); + struct drm_device *dev = container_of(delayed_work, struct drm_device, mode_config.output_poll_work); + bool repoll; + + if (dev->mode_config.funcs->output_poll_execute) + repoll = dev->mode_config.funcs->output_poll_execute(dev); + else + repoll = drm_kms_helper_poll_outputs(dev); if (repoll) schedule_delayed_work(delayed_work, DRM_OUTPUT_POLL_PERIOD); } diff --git a/include/drm/drm_crtc_helper.h b/include/drm/drm_crtc_helper.h index 982c299..861f9b0 100644 --- a/include/drm/drm_crtc_helper.h +++ b/include/drm/drm_crtc_helper.h @@ -74,5 +74,5 @@ extern void drm_kms_helper_hotplug_event(struct drm_device *dev); extern void drm_kms_helper_poll_disable(struct drm_device *dev); extern void drm_kms_helper_poll_enable(struct drm_device *dev); extern void drm_kms_helper_poll_enable_locked(struct drm_device *dev); - +extern bool drm_kms_helper_poll_outputs(struct drm_device *dev); #endif diff --git a/include/drm/drm_mode_config.h b/include/drm/drm_mode_config.h index 17942c0..e9fc078 100644 --- a/include/drm/drm_mode_config.h +++ b/include/drm/drm_mode_config.h @@ -87,6 +87,14 @@ struct drm_mode_config_funcs { void (*output_poll_changed)(struct drm_device *dev); /** + * @output_poll_execute: + * + * Used to allow driver to wrap the output polling for power management + * purposes and avoid locking issues. + */ + bool (*output_poll_execute)(struct drm_device *dev); + + /** * @atomic_check: * * This is the only hook to validate an atomic modeset update. This -- 2.9.3 _______________________________________________ dri-devel mailing list dri-devel@xxxxxxxxxxxxxxxxxxxxx https://lists.freedesktop.org/mailman/listinfo/dri-devel