From 9a69a9ac20f7f3435dd18019f902351c61a9ad1d Mon Sep 17 00:00:00 2001 From: Maarten Lankhorst Date: Tue, 21 Jul 2015 11:34:55 +0200 Subject: drm: Make the connector dpms callback return a value, v2. This is required to properly handle failing dpms calls. When making a wait in i915 interruptible, I've noticed that the dpms sequence could fail with -ERESTARTSYS because it was waiting interruptibly for flips. So from now on allow drivers to fail in their connector dpms callback. Encoder and crtc dpms callbacks are unaffected. Changes since v1: - Update kerneldoc for the drm helper functions. Signed-off-by: Maarten Lankhorst [danvet: Resolve conflicts due to different merge order.] Signed-off-by: Daniel Vetter --- drivers/gpu/drm/drm_atomic_helper.c | 28 ++++++++++++++++------------ drivers/gpu/drm/drm_crtc.c | 4 ++-- drivers/gpu/drm/drm_crtc_helper.c | 9 ++++++--- drivers/gpu/drm/i915/intel_crt.c | 8 +++++--- drivers/gpu/drm/i915/intel_display.c | 6 ++++-- drivers/gpu/drm/i915/intel_drv.h | 2 +- drivers/gpu/drm/i915/intel_dvo.c | 8 +++++--- drivers/gpu/drm/i915/intel_sdvo.c | 8 +++++--- drivers/gpu/drm/nouveau/nouveau_connector.c | 4 ++-- drivers/gpu/drm/radeon/radeon_dp_mst.c | 3 ++- drivers/gpu/drm/tegra/dsi.c | 3 ++- drivers/gpu/drm/tegra/hdmi.c | 5 +++-- drivers/gpu/drm/tegra/rgb.c | 5 +++-- drivers/gpu/drm/tegra/sor.c | 3 ++- drivers/gpu/drm/vmwgfx/vmwgfx_kms.c | 3 ++- drivers/gpu/drm/vmwgfx/vmwgfx_kms.h | 2 +- 16 files changed, 61 insertions(+), 40 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/drm_atomic_helper.c b/drivers/gpu/drm/drm_atomic_helper.c index 5ec13c7cc832..57847ae8ce8c 100644 --- a/drivers/gpu/drm/drm_atomic_helper.c +++ b/drivers/gpu/drm/drm_atomic_helper.c @@ -1974,9 +1974,12 @@ EXPORT_SYMBOL(drm_atomic_helper_page_flip); * implementing the legacy DPMS connector interface. It computes the new desired * ->active state for the corresponding CRTC (if the connector is enabled) and * updates it. + * + * Returns: + * Returns 0 on success, negative errno numbers on failure. */ -void drm_atomic_helper_connector_dpms(struct drm_connector *connector, - int mode) +int drm_atomic_helper_connector_dpms(struct drm_connector *connector, + int mode) { struct drm_mode_config *config = &connector->dev->mode_config; struct drm_atomic_state *state; @@ -1985,6 +1988,7 @@ void drm_atomic_helper_connector_dpms(struct drm_connector *connector, struct drm_connector *tmp_connector; int ret; bool active = false; + int old_mode = connector->dpms; if (mode != DRM_MODE_DPMS_ON) mode = DRM_MODE_DPMS_OFF; @@ -1993,18 +1997,19 @@ void drm_atomic_helper_connector_dpms(struct drm_connector *connector, crtc = connector->state->crtc; if (!crtc) - return; + return 0; - /* FIXME: ->dpms has no return value so can't forward the -ENOMEM. */ state = drm_atomic_state_alloc(connector->dev); if (!state) - return; + return -ENOMEM; state->acquire_ctx = drm_modeset_legacy_acquire_ctx(crtc); retry: crtc_state = drm_atomic_get_crtc_state(state, crtc); - if (IS_ERR(crtc_state)) - return; + if (IS_ERR(crtc_state)) { + ret = PTR_ERR(crtc_state); + goto fail; + } WARN_ON(!drm_modeset_is_locked(&config->connection_mutex)); @@ -2023,17 +2028,16 @@ retry: if (ret != 0) goto fail; - /* Driver takes ownership of state on successful async commit. */ - return; + /* Driver takes ownership of state on successful commit. */ + return 0; fail: if (ret == -EDEADLK) goto backoff; + connector->dpms = old_mode; drm_atomic_state_free(state); - WARN(1, "Driver bug: Changing ->active failed with ret=%i\n", ret); - - return; + return ret; backoff: drm_atomic_state_clear(state); drm_atomic_legacy_backoff(state); diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c index 1f0da41ae2a1..dfac394d0602 100644 --- a/drivers/gpu/drm/drm_crtc.c +++ b/drivers/gpu/drm/drm_crtc.c @@ -4753,9 +4753,9 @@ static int drm_mode_connector_set_obj_prop(struct drm_mode_object *obj, /* Do DPMS ourselves */ if (property == connector->dev->mode_config.dpms_property) { - if (connector->funcs->dpms) - (*connector->funcs->dpms)(connector, (int)value); ret = 0; + if (connector->funcs->dpms) + ret = (*connector->funcs->dpms)(connector, (int)value); } else if (connector->funcs->set_property) ret = connector->funcs->set_property(connector, property, value); diff --git a/drivers/gpu/drm/drm_crtc_helper.c b/drivers/gpu/drm/drm_crtc_helper.c index d3d038f05bf7..ef534758a02c 100644 --- a/drivers/gpu/drm/drm_crtc_helper.c +++ b/drivers/gpu/drm/drm_crtc_helper.c @@ -762,15 +762,18 @@ static int drm_helper_choose_crtc_dpms(struct drm_crtc *crtc) * implementing the DPMS connector attribute. It computes the new desired DPMS * state for all encoders and crtcs in the output mesh and calls the ->dpms() * callback provided by the driver appropriately. + * + * Returns: + * Always returns 0. */ -void drm_helper_connector_dpms(struct drm_connector *connector, int mode) +int drm_helper_connector_dpms(struct drm_connector *connector, int mode) { struct drm_encoder *encoder = connector->encoder; struct drm_crtc *crtc = encoder ? encoder->crtc : NULL; int old_dpms, encoder_dpms = DRM_MODE_DPMS_OFF; if (mode == connector->dpms) - return; + return 0; old_dpms = connector->dpms; connector->dpms = mode; @@ -802,7 +805,7 @@ void drm_helper_connector_dpms(struct drm_connector *connector, int mode) } } - return; + return 0; } EXPORT_SYMBOL(drm_helper_connector_dpms); diff --git a/drivers/gpu/drm/i915/intel_crt.c b/drivers/gpu/drm/i915/intel_crt.c index 521af2c069cb..5d78c1feec81 100644 --- a/drivers/gpu/drm/i915/intel_crt.c +++ b/drivers/gpu/drm/i915/intel_crt.c @@ -237,7 +237,7 @@ static void intel_enable_crt(struct intel_encoder *encoder) } /* Special dpms function to support cloning between dvo/sdvo/crt. */ -static void intel_crt_dpms(struct drm_connector *connector, int mode) +static int intel_crt_dpms(struct drm_connector *connector, int mode) { struct drm_device *dev = connector->dev; struct intel_encoder *encoder = intel_attached_encoder(connector); @@ -249,7 +249,7 @@ static void intel_crt_dpms(struct drm_connector *connector, int mode) mode = DRM_MODE_DPMS_OFF; if (mode == connector->dpms) - return; + return 0; old_dpms = connector->dpms; connector->dpms = mode; @@ -258,7 +258,7 @@ static void intel_crt_dpms(struct drm_connector *connector, int mode) crtc = encoder->base.crtc; if (!crtc) { encoder->connectors_active = false; - return; + return 0; } /* We need the pipe to run for anything but OFF. */ @@ -281,6 +281,8 @@ static void intel_crt_dpms(struct drm_connector *connector, int mode) } intel_modeset_check_state(connector->dev); + + return 0; } static enum drm_mode_status diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 40c73da2abcf..13a6608be689 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -6429,14 +6429,14 @@ struct intel_connector *intel_connector_alloc(void) /* Even simpler default implementation, if there's really no special case to * consider. */ -void intel_connector_dpms(struct drm_connector *connector, int mode) +int intel_connector_dpms(struct drm_connector *connector, int mode) { /* All the simple cases only support two dpms states. */ if (mode != DRM_MODE_DPMS_ON) mode = DRM_MODE_DPMS_OFF; if (mode == connector->dpms) - return; + return 0; connector->dpms = mode; @@ -6445,6 +6445,8 @@ void intel_connector_dpms(struct drm_connector *connector, int mode) intel_encoder_dpms(to_intel_encoder(connector->encoder), mode); intel_modeset_check_state(connector->dev); + + return 0; } /* Simple connector->get_hw_state implementation for encoders that support only diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h index 47cef0e6c79c..320c9e6bd848 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h @@ -997,7 +997,7 @@ void intel_crtc_update_dpms(struct drm_crtc *crtc); void intel_encoder_destroy(struct drm_encoder *encoder); int intel_connector_init(struct intel_connector *); struct intel_connector *intel_connector_alloc(void); -void intel_connector_dpms(struct drm_connector *, int mode); +int intel_connector_dpms(struct drm_connector *, int mode); bool intel_connector_get_hw_state(struct intel_connector *connector); void intel_modeset_check_state(struct drm_device *dev); bool ibx_digital_port_connected(struct drm_i915_private *dev_priv, diff --git a/drivers/gpu/drm/i915/intel_dvo.c b/drivers/gpu/drm/i915/intel_dvo.c index ece5bd754f85..fd5e522abebb 100644 --- a/drivers/gpu/drm/i915/intel_dvo.c +++ b/drivers/gpu/drm/i915/intel_dvo.c @@ -197,7 +197,7 @@ static void intel_enable_dvo(struct intel_encoder *encoder) } /* Special dpms function to support cloning between dvo/sdvo/crt. */ -static void intel_dvo_dpms(struct drm_connector *connector, int mode) +static int intel_dvo_dpms(struct drm_connector *connector, int mode) { struct intel_dvo *intel_dvo = intel_attached_dvo(connector); struct drm_crtc *crtc; @@ -208,7 +208,7 @@ static void intel_dvo_dpms(struct drm_connector *connector, int mode) mode = DRM_MODE_DPMS_OFF; if (mode == connector->dpms) - return; + return 0; connector->dpms = mode; @@ -216,7 +216,7 @@ static void intel_dvo_dpms(struct drm_connector *connector, int mode) crtc = intel_dvo->base.base.crtc; if (!crtc) { intel_dvo->base.connectors_active = false; - return; + return 0; } /* We call connector dpms manually below in case pipe dpms doesn't @@ -238,6 +238,8 @@ static void intel_dvo_dpms(struct drm_connector *connector, int mode) } intel_modeset_check_state(connector->dev); + + return 0; } static enum drm_mode_status diff --git a/drivers/gpu/drm/i915/intel_sdvo.c b/drivers/gpu/drm/i915/intel_sdvo.c index aa2fd751609c..2c435a79d4da 100644 --- a/drivers/gpu/drm/i915/intel_sdvo.c +++ b/drivers/gpu/drm/i915/intel_sdvo.c @@ -1509,7 +1509,7 @@ static void intel_enable_sdvo(struct intel_encoder *encoder) } /* Special dpms function to support cloning between dvo/sdvo/crt. */ -static void intel_sdvo_dpms(struct drm_connector *connector, int mode) +static int intel_sdvo_dpms(struct drm_connector *connector, int mode) { struct drm_crtc *crtc; struct intel_sdvo *intel_sdvo = intel_attached_sdvo(connector); @@ -1519,7 +1519,7 @@ static void intel_sdvo_dpms(struct drm_connector *connector, int mode) mode = DRM_MODE_DPMS_OFF; if (mode == connector->dpms) - return; + return 0; connector->dpms = mode; @@ -1527,7 +1527,7 @@ static void intel_sdvo_dpms(struct drm_connector *connector, int mode) crtc = intel_sdvo->base.base.crtc; if (!crtc) { intel_sdvo->base.connectors_active = false; - return; + return 0; } /* We set active outputs manually below in case pipe dpms doesn't change @@ -1551,6 +1551,8 @@ static void intel_sdvo_dpms(struct drm_connector *connector, int mode) } intel_modeset_check_state(connector->dev); + + return 0; } static enum drm_mode_status diff --git a/drivers/gpu/drm/nouveau/nouveau_connector.c b/drivers/gpu/drm/nouveau/nouveau_connector.c index 3162040bc314..1f26eba245d1 100644 --- a/drivers/gpu/drm/nouveau/nouveau_connector.c +++ b/drivers/gpu/drm/nouveau/nouveau_connector.c @@ -919,7 +919,7 @@ nouveau_connector_funcs_lvds = { .force = nouveau_connector_force }; -static void +static int nouveau_connector_dp_dpms(struct drm_connector *connector, int mode) { struct nouveau_encoder *nv_encoder = NULL; @@ -938,7 +938,7 @@ nouveau_connector_dp_dpms(struct drm_connector *connector, int mode) } } - drm_helper_connector_dpms(connector, mode); + return drm_helper_connector_dpms(connector, mode); } static const struct drm_connector_funcs diff --git a/drivers/gpu/drm/radeon/radeon_dp_mst.c b/drivers/gpu/drm/radeon/radeon_dp_mst.c index e4fc8f3bf58b..5e09c061847f 100644 --- a/drivers/gpu/drm/radeon/radeon_dp_mst.c +++ b/drivers/gpu/drm/radeon/radeon_dp_mst.c @@ -246,9 +246,10 @@ radeon_dp_mst_connector_destroy(struct drm_connector *connector) kfree(radeon_connector); } -static void radeon_connector_dpms(struct drm_connector *connector, int mode) +static int radeon_connector_dpms(struct drm_connector *connector, int mode) { DRM_DEBUG_KMS("\n"); + return 0; } static const struct drm_connector_funcs radeon_dp_mst_connector_funcs = { diff --git a/drivers/gpu/drm/tegra/dsi.c b/drivers/gpu/drm/tegra/dsi.c index ed970f622903..dc97c0b3681d 100644 --- a/drivers/gpu/drm/tegra/dsi.c +++ b/drivers/gpu/drm/tegra/dsi.c @@ -726,8 +726,9 @@ static void tegra_dsi_soft_reset(struct tegra_dsi *dsi) tegra_dsi_soft_reset(dsi->slave); } -static void tegra_dsi_connector_dpms(struct drm_connector *connector, int mode) +static int tegra_dsi_connector_dpms(struct drm_connector *connector, int mode) { + return 0; } static void tegra_dsi_connector_reset(struct drm_connector *connector) diff --git a/drivers/gpu/drm/tegra/hdmi.c b/drivers/gpu/drm/tegra/hdmi.c index 06ab1783bba1..fe4008a7ddba 100644 --- a/drivers/gpu/drm/tegra/hdmi.c +++ b/drivers/gpu/drm/tegra/hdmi.c @@ -772,9 +772,10 @@ static bool tegra_output_is_hdmi(struct tegra_output *output) return drm_detect_hdmi_monitor(edid); } -static void tegra_hdmi_connector_dpms(struct drm_connector *connector, - int mode) +static int tegra_hdmi_connector_dpms(struct drm_connector *connector, + int mode) { + return 0; } static const struct drm_connector_funcs tegra_hdmi_connector_funcs = { diff --git a/drivers/gpu/drm/tegra/rgb.c b/drivers/gpu/drm/tegra/rgb.c index 7cd833f5b5b5..9a99d213e1b1 100644 --- a/drivers/gpu/drm/tegra/rgb.c +++ b/drivers/gpu/drm/tegra/rgb.c @@ -88,9 +88,10 @@ static void tegra_dc_write_regs(struct tegra_dc *dc, tegra_dc_writel(dc, table[i].value, table[i].offset); } -static void tegra_rgb_connector_dpms(struct drm_connector *connector, - int mode) +static int tegra_rgb_connector_dpms(struct drm_connector *connector, + int mode) { + return 0; } static const struct drm_connector_funcs tegra_rgb_connector_funcs = { diff --git a/drivers/gpu/drm/tegra/sor.c b/drivers/gpu/drm/tegra/sor.c index 7591d8901f9a..ee8ad0d4a0f2 100644 --- a/drivers/gpu/drm/tegra/sor.c +++ b/drivers/gpu/drm/tegra/sor.c @@ -866,8 +866,9 @@ static void tegra_sor_debugfs_exit(struct tegra_sor *sor) sor->debugfs_files = NULL; } -static void tegra_sor_connector_dpms(struct drm_connector *connector, int mode) +static int tegra_sor_connector_dpms(struct drm_connector *connector, int mode) { + return 0; } static enum drm_connector_status diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c index 07cda8cbbddb..2adc11bc0920 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c @@ -1808,8 +1808,9 @@ void vmw_du_crtc_gamma_set(struct drm_crtc *crtc, } } -void vmw_du_connector_dpms(struct drm_connector *connector, int mode) +int vmw_du_connector_dpms(struct drm_connector *connector, int mode) { + return 0; } void vmw_du_connector_save(struct drm_connector *connector) diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.h b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.h index 8d038c36bd57..f1a324cfb4c3 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.h +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.h @@ -133,7 +133,7 @@ void vmw_du_crtc_gamma_set(struct drm_crtc *crtc, int vmw_du_crtc_cursor_set(struct drm_crtc *crtc, struct drm_file *file_priv, uint32_t handle, uint32_t width, uint32_t height); int vmw_du_crtc_cursor_move(struct drm_crtc *crtc, int x, int y); -void vmw_du_connector_dpms(struct drm_connector *connector, int mode); +int vmw_du_connector_dpms(struct drm_connector *connector, int mode); void vmw_du_connector_save(struct drm_connector *connector); void vmw_du_connector_restore(struct drm_connector *connector); enum drm_connector_status -- cgit v1.2.3