Commit 8c4ccc4a authored by Daniel Vetter's avatar Daniel Vetter

drm/probe-helper: Grab mode_config.mutex in poll_init/enable

So on first looks this seems superflous since drivers should ensure
correct ordering to not make this a problem. Otoh ordering constraints
between hdp, fbdev load and enabling polling are already tricky on
some hardware and it helps to be more robust.

But the real goal is to just shut up a locking WARN_ON I'd like to
add, which means init code gets some additional locks just for
uniformity.

v2: Also grab the lock for the public poll_enable, not just poll_init
which is used for resume, with the same justification.
Reviewed-by: default avatarMaarten Lankhorst <maarten.lankhorst@linux.intel.com>
Signed-off-by: default avatarDaniel Vetter <daniel.vetter@intel.com>
parent 6295d607
...@@ -93,6 +93,27 @@ static int drm_helper_probe_add_cmdline_mode(struct drm_connector *connector) ...@@ -93,6 +93,27 @@ static int drm_helper_probe_add_cmdline_mode(struct drm_connector *connector)
return 1; return 1;
} }
#define DRM_OUTPUT_POLL_PERIOD (10*HZ)
static void __drm_kms_helper_poll_enable(struct drm_device *dev)
{
bool poll = false;
struct drm_connector *connector;
WARN_ON(!mutex_is_locked(&dev->mode_config.mutex));
if (!dev->mode_config.poll_enabled || !drm_kms_helper_poll)
return;
drm_for_each_connector(connector, dev) {
if (connector->polled & (DRM_CONNECTOR_POLL_CONNECT |
DRM_CONNECTOR_POLL_DISCONNECT))
poll = true;
}
if (poll)
schedule_delayed_work(&dev->mode_config.output_poll_work, DRM_OUTPUT_POLL_PERIOD);
}
static int drm_helper_probe_single_connector_modes_merge_bits(struct drm_connector *connector, static int drm_helper_probe_single_connector_modes_merge_bits(struct drm_connector *connector,
uint32_t maxX, uint32_t maxY, bool merge_type_bits) uint32_t maxX, uint32_t maxY, bool merge_type_bits)
{ {
...@@ -153,7 +174,7 @@ static int drm_helper_probe_single_connector_modes_merge_bits(struct drm_connect ...@@ -153,7 +174,7 @@ static int drm_helper_probe_single_connector_modes_merge_bits(struct drm_connect
/* Re-enable polling in case the global poll config changed. */ /* Re-enable polling in case the global poll config changed. */
if (drm_kms_helper_poll != dev->mode_config.poll_running) if (drm_kms_helper_poll != dev->mode_config.poll_running)
drm_kms_helper_poll_enable(dev); __drm_kms_helper_poll_enable(dev);
dev->mode_config.poll_running = drm_kms_helper_poll; dev->mode_config.poll_running = drm_kms_helper_poll;
...@@ -295,7 +316,6 @@ void drm_kms_helper_hotplug_event(struct drm_device *dev) ...@@ -295,7 +316,6 @@ void drm_kms_helper_hotplug_event(struct drm_device *dev)
} }
EXPORT_SYMBOL(drm_kms_helper_hotplug_event); EXPORT_SYMBOL(drm_kms_helper_hotplug_event);
#define DRM_OUTPUT_POLL_PERIOD (10*HZ)
static void output_poll_execute(struct work_struct *work) static void output_poll_execute(struct work_struct *work)
{ {
struct delayed_work *delayed_work = to_delayed_work(work); struct delayed_work *delayed_work = to_delayed_work(work);
...@@ -407,20 +427,9 @@ EXPORT_SYMBOL(drm_kms_helper_poll_disable); ...@@ -407,20 +427,9 @@ EXPORT_SYMBOL(drm_kms_helper_poll_disable);
*/ */
void drm_kms_helper_poll_enable(struct drm_device *dev) void drm_kms_helper_poll_enable(struct drm_device *dev)
{ {
bool poll = false; mutex_lock(&dev->mode_config.mutex);
struct drm_connector *connector; __drm_kms_helper_poll_enable(dev);
mutex_unlock(&dev->mode_config.mutex);
if (!dev->mode_config.poll_enabled || !drm_kms_helper_poll)
return;
drm_for_each_connector(connector, dev) {
if (connector->polled & (DRM_CONNECTOR_POLL_CONNECT |
DRM_CONNECTOR_POLL_DISCONNECT))
poll = true;
}
if (poll)
schedule_delayed_work(&dev->mode_config.output_poll_work, DRM_OUTPUT_POLL_PERIOD);
} }
EXPORT_SYMBOL(drm_kms_helper_poll_enable); EXPORT_SYMBOL(drm_kms_helper_poll_enable);
......
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