drm/i915/panel: Reduce race window between bl_update_status and bl_enable
diff mbox series

Message ID 20200601140217.51709-1-sean@poorly.run
State New
Headers show
  • drm/i915/panel: Reduce race window between bl_update_status and bl_enable
Related show

Commit Message

Sean Paul June 1, 2020, 2:02 p.m. UTC
From: Sean Paul <seanpaul@chromium.org>

If the backlight is updated while the panel is being enabled, the value
from userspace (which is stored in panel->backlight.device->props.brightness)
can be replaced by the hardware's minimum level. There's really no good
way to tell if this is happening in enable_backlight() since
props.brightness can be initialized to the same value as is being set by
userspace. So we'll try to reduce the race window as much as possible.

Signed-off-by: Sean Paul <seanpaul@chromium.org>

I don't think there's any way to eliminate this race since grabbing
bd->op_lock in panel_enable would cause a lock inversion deadlock with
the connection_mutex lock in backlight_device_update_status

Suggestions very much welcome!

 drivers/gpu/drm/i915/display/intel_panel.c | 14 ++++++++++++++
 1 file changed, 14 insertions(+)

diff mbox series

diff --git a/drivers/gpu/drm/i915/display/intel_panel.c b/drivers/gpu/drm/i915/display/intel_panel.c
index 3c5056dbf607..abdfb9cc281b 100644
--- a/drivers/gpu/drm/i915/display/intel_panel.c
+++ b/drivers/gpu/drm/i915/display/intel_panel.c
@@ -1285,8 +1285,22 @@  static int intel_backlight_device_update_status(struct backlight_device *bd)
 	struct intel_connector *connector = bl_get_data(bd);
 	struct intel_panel *panel = &connector->panel;
 	struct drm_device *dev = connector->base.dev;
+	int value;
+	/*
+	 * Before we attempt to grab the connection mutex, cache the incoming
+	 * brightness value. If we're in the middle of a modeset,
+	 * intel_panel_enable_backlight will be called and could pave over
+	 * props.brightness. This is still racey, but the race window should be
+	 * significantly smaller and reflects the inherent raceyness of the
+	 * updating props.brightness outside of bd->op_lock.
+	 */
+	value = bd->props.brightness;
 	drm_modeset_lock(&dev->mode_config.connection_mutex, NULL);
+	bd->props.brightness = value;
 	DRM_DEBUG_KMS("updating intel_backlight, brightness=%d/%d\n",
 		      bd->props.brightness, bd->props.max_brightness);
 	intel_panel_set_backlight(connector->base.state, bd->props.brightness,