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.

Signed-off-by: Maarten Lankhorst <maarten.lankhorst at linux.intel.com>
---
 drivers/gpu/drm/drm_atomic_helper.c         | 25 +++++++++++++------------
 drivers/gpu/drm/drm_crtc.c                  |  4 ++--
 drivers/gpu/drm/drm_crtc_helper.c           |  6 +++---
 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 +-
 include/drm/drm_atomic_helper.h             |  4 ++--
 include/drm/drm_crtc.h                      |  2 +-
 include/drm/drm_crtc_helper.h               |  2 +-
 14 files changed, 39 insertions(+), 32 deletions(-)

diff --git a/drivers/gpu/drm/drm_atomic_helper.c 
b/drivers/gpu/drm/drm_atomic_helper.c
index d5eba80dc39f..7eb6f751445c 100644
--- a/drivers/gpu/drm/drm_atomic_helper.c
+++ b/drivers/gpu/drm/drm_atomic_helper.c
@@ -1958,8 +1958,8 @@ EXPORT_SYMBOL(drm_atomic_helper_page_flip);
  * ->active state for the corresponding CRTC (if the connector is enabled) and
  *  updates it.
  */
-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;
@@ -1968,6 +1968,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;
@@ -1976,18 +1977,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));

@@ -2006,17 +2008,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 a717d18e7a97..5c11083dd186 100644
--- a/drivers/gpu/drm/drm_crtc.c
+++ b/drivers/gpu/drm/drm_crtc.c
@@ -4869,9 +4869,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 d3dfb0ebbeb2..ae5e52f8f5b3 100644
--- a/drivers/gpu/drm/drm_crtc_helper.c
+++ b/drivers/gpu/drm/drm_crtc_helper.c
@@ -763,14 +763,14 @@ static int drm_helper_choose_crtc_dpms(struct drm_crtc 
*crtc)
  * state for all encoders and crtcs in the output mesh and calls the ->dpms()
  * callback provided by the driver appropriately.
  */
-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 +802,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/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 257b10be5cda..983afb4b856c 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
diff --git a/include/drm/drm_atomic_helper.h b/include/drm/drm_atomic_helper.h
index cc1fee8a12d0..11266d147a29 100644
--- a/include/drm/drm_atomic_helper.h
+++ b/include/drm/drm_atomic_helper.h
@@ -87,8 +87,8 @@ int drm_atomic_helper_page_flip(struct drm_crtc *crtc,
                                struct drm_framebuffer *fb,
                                struct drm_pending_vblank_event *event,
                                uint32_t flags);
-void drm_atomic_helper_connector_dpms(struct drm_connector *connector,
-                                     int mode);
+int drm_atomic_helper_connector_dpms(struct drm_connector *connector,
+                                    int mode);

 /* default implementations for state handling */
 void drm_atomic_helper_crtc_reset(struct drm_crtc *crtc);
diff --git a/include/drm/drm_crtc.h b/include/drm/drm_crtc.h
index 57ca8cc383a6..8159a0627b6b 100644
--- a/include/drm/drm_crtc.h
+++ b/include/drm/drm_crtc.h
@@ -525,7 +525,7 @@ struct drm_connector_state {
  * etc.
  */
 struct drm_connector_funcs {
-       void (*dpms)(struct drm_connector *connector, int mode);
+       int (*dpms)(struct drm_connector *connector, int mode);
        void (*save)(struct drm_connector *connector);
        void (*restore)(struct drm_connector *connector);
        void (*reset)(struct drm_connector *connector);
diff --git a/include/drm/drm_crtc_helper.h b/include/drm/drm_crtc_helper.h
index c8fc187061de..4562bd12bb4a 100644
--- a/include/drm/drm_crtc_helper.h
+++ b/include/drm/drm_crtc_helper.h
@@ -187,7 +187,7 @@ extern bool drm_crtc_helper_set_mode(struct drm_crtc *crtc,
 extern bool drm_helper_crtc_in_use(struct drm_crtc *crtc);
 extern bool drm_helper_encoder_in_use(struct drm_encoder *encoder);

-extern void drm_helper_connector_dpms(struct drm_connector *connector, int 
mode);
+extern int drm_helper_connector_dpms(struct drm_connector *connector, int 
mode);

 extern void drm_helper_move_panel_connectors_to_head(struct drm_device *);

-- 
2.1.0

Reply via email to