Merge tag 'staging-4.5-rc2' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh...
[deliverable/linux.git] / drivers / gpu / drm / drm_atomic.c
index aeee083c7f95064fed6c6b08cd67b58d174204af..3f74193885f1ff1df95db09fa76e01174f6353b4 100644 (file)
@@ -288,8 +288,8 @@ drm_atomic_get_crtc_state(struct drm_atomic_state *state,
        state->crtcs[index] = crtc;
        crtc_state->state = state;
 
-       DRM_DEBUG_ATOMIC("Added [CRTC:%d] %p state to %p\n",
-                        crtc->base.id, crtc_state, state);
+       DRM_DEBUG_ATOMIC("Added [CRTC:%d:%s] %p state to %p\n",
+                        crtc->base.id, crtc->name, crtc_state, state);
 
        return crtc_state;
 }
@@ -316,8 +316,7 @@ int drm_atomic_set_mode_for_crtc(struct drm_crtc_state *state,
        if (mode && memcmp(&state->mode, mode, sizeof(*mode)) == 0)
                return 0;
 
-       if (state->mode_blob)
-               drm_property_unreference_blob(state->mode_blob);
+       drm_property_unreference_blob(state->mode_blob);
        state->mode_blob = NULL;
 
        if (mode) {
@@ -363,8 +362,7 @@ int drm_atomic_set_mode_prop_for_crtc(struct drm_crtc_state *state,
        if (blob == state->mode_blob)
                return 0;
 
-       if (state->mode_blob)
-               drm_property_unreference_blob(state->mode_blob);
+       drm_property_unreference_blob(state->mode_blob);
        state->mode_blob = NULL;
 
        if (blob) {
@@ -419,8 +417,7 @@ int drm_atomic_crtc_set_property(struct drm_crtc *crtc,
                struct drm_property_blob *mode =
                        drm_property_lookup_blob(dev, val);
                ret = drm_atomic_set_mode_prop_for_crtc(state, mode);
-               if (mode)
-                       drm_property_unreference_blob(mode);
+               drm_property_unreference_blob(mode);
                return ret;
        }
        else if (crtc->funcs->atomic_set_property)
@@ -432,11 +429,20 @@ int drm_atomic_crtc_set_property(struct drm_crtc *crtc,
 }
 EXPORT_SYMBOL(drm_atomic_crtc_set_property);
 
-/*
+/**
+ * drm_atomic_crtc_get_property - get property value from CRTC state
+ * @crtc: the drm CRTC to set a property on
+ * @state: the state object to get the property value from
+ * @property: the property to set
+ * @val: return location for the property value
+ *
  * This function handles generic/core properties and calls out to
  * driver's ->atomic_get_property() for driver properties.  To ensure
  * consistent behavior you must call this function rather than the
  * driver hook directly.
+ *
+ * RETURNS:
+ * Zero on success, error code on failure
  */
 static int
 drm_atomic_crtc_get_property(struct drm_crtc *crtc,
@@ -480,8 +486,8 @@ static int drm_atomic_crtc_check(struct drm_crtc *crtc,
         */
 
        if (state->active && !state->enable) {
-               DRM_DEBUG_ATOMIC("[CRTC:%d] active without enabled\n",
-                                crtc->base.id);
+               DRM_DEBUG_ATOMIC("[CRTC:%d:%s] active without enabled\n",
+                                crtc->base.id, crtc->name);
                return -EINVAL;
        }
 
@@ -490,14 +496,30 @@ static int drm_atomic_crtc_check(struct drm_crtc *crtc,
         * be able to trigger. */
        if (drm_core_check_feature(crtc->dev, DRIVER_ATOMIC) &&
            WARN_ON(state->enable && !state->mode_blob)) {
-               DRM_DEBUG_ATOMIC("[CRTC:%d] enabled without mode blob\n",
-                                crtc->base.id);
+               DRM_DEBUG_ATOMIC("[CRTC:%d:%s] enabled without mode blob\n",
+                                crtc->base.id, crtc->name);
                return -EINVAL;
        }
 
        if (drm_core_check_feature(crtc->dev, DRIVER_ATOMIC) &&
            WARN_ON(!state->enable && state->mode_blob)) {
-               DRM_DEBUG_ATOMIC("[CRTC:%d] disabled with mode blob\n",
+               DRM_DEBUG_ATOMIC("[CRTC:%d:%s] disabled with mode blob\n",
+                                crtc->base.id, crtc->name);
+               return -EINVAL;
+       }
+
+       /*
+        * Reject event generation for when a CRTC is off and stays off.
+        * It wouldn't be hard to implement this, but userspace has a track
+        * record of happily burning through 100% cpu (or worse, crash) when the
+        * display pipe is suspended. To avoid all that fun just reject updates
+        * that ask for events since likely that indicates a bug in the
+        * compositor's drawing loop. This is consistent with the vblank IOCTL
+        * and legacy page_flip IOCTL which also reject service on a disabled
+        * pipe.
+        */
+       if (state->event && !state->active && !crtc->state->active) {
+               DRM_DEBUG_ATOMIC("[CRTC:%d] requesting event but off\n",
                                 crtc->base.id);
                return -EINVAL;
        }
@@ -543,8 +565,8 @@ drm_atomic_get_plane_state(struct drm_atomic_state *state,
        state->planes[index] = plane;
        plane_state->state = state;
 
-       DRM_DEBUG_ATOMIC("Added [PLANE:%d] %p state to %p\n",
-                        plane->base.id, plane_state, state);
+       DRM_DEBUG_ATOMIC("Added [PLANE:%d:%s] %p state to %p\n",
+                        plane->base.id, plane->name, plane_state, state);
 
        if (plane_state->crtc) {
                struct drm_crtc_state *crtc_state;
@@ -619,11 +641,20 @@ int drm_atomic_plane_set_property(struct drm_plane *plane,
 }
 EXPORT_SYMBOL(drm_atomic_plane_set_property);
 
-/*
+/**
+ * drm_atomic_plane_get_property - get property value from plane state
+ * @plane: the drm plane to set a property on
+ * @state: the state object to get the property value from
+ * @property: the property to set
+ * @val: return location for the property value
+ *
  * This function handles generic/core properties and calls out to
  * driver's ->atomic_get_property() for driver properties.  To ensure
  * consistent behavior you must call this function rather than the
  * driver hook directly.
+ *
+ * RETURNS:
+ * Zero on success, error code on failure
  */
 static int
 drm_atomic_plane_get_property(struct drm_plane *plane,
@@ -755,8 +786,8 @@ static int drm_atomic_plane_check(struct drm_plane *plane,
        }
 
        if (plane_switching_crtc(state->state, plane, state)) {
-               DRM_DEBUG_ATOMIC("[PLANE:%d] switching CRTC directly\n",
-                                plane->base.id);
+               DRM_DEBUG_ATOMIC("[PLANE:%d:%s] switching CRTC directly\n",
+                                plane->base.id, plane->name);
                return -EINVAL;
        }
 
@@ -875,11 +906,20 @@ int drm_atomic_connector_set_property(struct drm_connector *connector,
 }
 EXPORT_SYMBOL(drm_atomic_connector_set_property);
 
-/*
+/**
+ * drm_atomic_connector_get_property - get property value from connector state
+ * @connector: the drm connector to set a property on
+ * @state: the state object to get the property value from
+ * @property: the property to set
+ * @val: return location for the property value
+ *
  * This function handles generic/core properties and calls out to
  * driver's ->atomic_get_property() for driver properties.  To ensure
  * consistent behavior you must call this function rather than the
  * driver hook directly.
+ *
+ * RETURNS:
+ * Zero on success, error code on failure
  */
 static int
 drm_atomic_connector_get_property(struct drm_connector *connector,
@@ -980,8 +1020,8 @@ drm_atomic_set_crtc_for_plane(struct drm_plane_state *plane_state,
        }
 
        if (crtc)
-               DRM_DEBUG_ATOMIC("Link plane state %p to [CRTC:%d]\n",
-                                plane_state, crtc->base.id);
+               DRM_DEBUG_ATOMIC("Link plane state %p to [CRTC:%d:%s]\n",
+                                plane_state, crtc->base.id, crtc->name);
        else
                DRM_DEBUG_ATOMIC("Link plane state %p to [NOCRTC]\n",
                                 plane_state);
@@ -1039,17 +1079,28 @@ drm_atomic_set_crtc_for_connector(struct drm_connector_state *conn_state,
 {
        struct drm_crtc_state *crtc_state;
 
+       if (conn_state->crtc && conn_state->crtc != crtc) {
+               crtc_state = drm_atomic_get_existing_crtc_state(conn_state->state,
+                                                               conn_state->crtc);
+
+               crtc_state->connector_mask &=
+                       ~(1 << drm_connector_index(conn_state->connector));
+       }
+
        if (crtc) {
                crtc_state = drm_atomic_get_crtc_state(conn_state->state, crtc);
                if (IS_ERR(crtc_state))
                        return PTR_ERR(crtc_state);
+
+               crtc_state->connector_mask |=
+                       1 << drm_connector_index(conn_state->connector);
        }
 
        conn_state->crtc = crtc;
 
        if (crtc)
-               DRM_DEBUG_ATOMIC("Link connector state %p to [CRTC:%d]\n",
-                                conn_state, crtc->base.id);
+               DRM_DEBUG_ATOMIC("Link connector state %p to [CRTC:%d:%s]\n",
+                                conn_state, crtc->base.id, crtc->name);
        else
                DRM_DEBUG_ATOMIC("Link connector state %p to [NOCRTC]\n",
                                 conn_state);
@@ -1088,8 +1139,8 @@ drm_atomic_add_affected_connectors(struct drm_atomic_state *state,
        if (ret)
                return ret;
 
-       DRM_DEBUG_ATOMIC("Adding all current connectors for [CRTC:%d] to %p\n",
-                        crtc->base.id, state);
+       DRM_DEBUG_ATOMIC("Adding all current connectors for [CRTC:%d:%s] to %p\n",
+                        crtc->base.id, crtc->name, state);
 
        /*
         * Changed connectors are already in @state, so only need to look at the
@@ -1147,35 +1198,6 @@ drm_atomic_add_affected_planes(struct drm_atomic_state *state,
 }
 EXPORT_SYMBOL(drm_atomic_add_affected_planes);
 
-/**
- * drm_atomic_connectors_for_crtc - count number of connected outputs
- * @state: atomic state
- * @crtc: DRM crtc
- *
- * This function counts all connectors which will be connected to @crtc
- * according to @state. Useful to recompute the enable state for @crtc.
- */
-int
-drm_atomic_connectors_for_crtc(struct drm_atomic_state *state,
-                              struct drm_crtc *crtc)
-{
-       struct drm_connector *connector;
-       struct drm_connector_state *conn_state;
-
-       int i, num_connected_connectors = 0;
-
-       for_each_connector_in_state(state, connector, conn_state, i) {
-               if (conn_state->crtc == crtc)
-                       num_connected_connectors++;
-       }
-
-       DRM_DEBUG_ATOMIC("State %p has %i connectors for [CRTC:%d]\n",
-                        state, num_connected_connectors, crtc->base.id);
-
-       return num_connected_connectors;
-}
-EXPORT_SYMBOL(drm_atomic_connectors_for_crtc);
-
 /**
  * drm_atomic_legacy_backoff - locking backoff for legacy ioctls
  * @state: atomic state
@@ -1191,12 +1213,7 @@ void drm_atomic_legacy_backoff(struct drm_atomic_state *state)
 retry:
        drm_modeset_backoff(state->acquire_ctx);
 
-       ret = drm_modeset_lock(&state->dev->mode_config.connection_mutex,
-                              state->acquire_ctx);
-       if (ret)
-               goto retry;
-       ret = drm_modeset_lock_all_crtcs(state->dev,
-                                        state->acquire_ctx);
+       ret = drm_modeset_lock_all_ctx(state->dev, state->acquire_ctx);
        if (ret)
                goto retry;
 }
@@ -1228,8 +1245,8 @@ int drm_atomic_check_only(struct drm_atomic_state *state)
        for_each_plane_in_state(state, plane, plane_state, i) {
                ret = drm_atomic_plane_check(plane, plane_state);
                if (ret) {
-                       DRM_DEBUG_ATOMIC("[PLANE:%d] atomic core check failed\n",
-                                        plane->base.id);
+                       DRM_DEBUG_ATOMIC("[PLANE:%d:%s] atomic core check failed\n",
+                                        plane->base.id, plane->name);
                        return ret;
                }
        }
@@ -1237,8 +1254,8 @@ int drm_atomic_check_only(struct drm_atomic_state *state)
        for_each_crtc_in_state(state, crtc, crtc_state, i) {
                ret = drm_atomic_crtc_check(crtc, crtc_state);
                if (ret) {
-                       DRM_DEBUG_ATOMIC("[CRTC:%d] atomic core check failed\n",
-                                        crtc->base.id);
+                       DRM_DEBUG_ATOMIC("[CRTC:%d:%s] atomic core check failed\n",
+                                        crtc->base.id, crtc->name);
                        return ret;
                }
        }
@@ -1249,8 +1266,8 @@ int drm_atomic_check_only(struct drm_atomic_state *state)
        if (!state->allow_modeset) {
                for_each_crtc_in_state(state, crtc, crtc_state, i) {
                        if (drm_atomic_crtc_needs_modeset(crtc_state)) {
-                               DRM_DEBUG_ATOMIC("[CRTC:%d] requires full modeset\n",
-                                                crtc->base.id);
+                               DRM_DEBUG_ATOMIC("[CRTC:%d:%s] requires full modeset\n",
+                                                crtc->base.id, crtc->name);
                                return -EINVAL;
                        }
                }
@@ -1433,7 +1450,7 @@ static int atomic_set_prop(struct drm_atomic_state *state,
 }
 
 /**
- * drm_atomic_update_old_fb -- Unset old_fb pointers and set plane->fb pointers.
+ * drm_atomic_clean_old_fb -- Unset old_fb pointers and set plane->fb pointers.
  *
  * @dev: drm device to check.
  * @plane_mask: plane mask for planes that were updated.
This page took 0.02899 seconds and 5 git commands to generate.