[Intel-gfx] [PATCH 01/42] drm/atomic: Allow drivers to subclass drm_atomic_state

Maarten Lankhorst maarten.lankhorst at linux.intel.com
Mon May 11 07:24:37 PDT 2015


Drivers may need to store the state of shared resources, such as PLLs
or FIFO space, into the atomic state. Allow this by making it possible
to subclass drm_atomic_state.

Cc: dri-devel at lists.freedesktop.org
Acked-by: Ander Conselvan de Oliveira <ander.conselvan.de.oliveira at intel.com>
Signed-off-by: Maarten Lankhorst <maarten.lankhorst at linux.intel.com>
---
 drivers/gpu/drm/drm_atomic.c | 91 ++++++++++++++++++++++++++++++++------------
 include/drm/drm_atomic.h     |  4 ++
 include/drm/drm_crtc.h       |  4 ++
 3 files changed, 74 insertions(+), 25 deletions(-)

diff --git a/drivers/gpu/drm/drm_atomic.c b/drivers/gpu/drm/drm_atomic.c
index 6e3b78ee7d16..f0f914591f1d 100644
--- a/drivers/gpu/drm/drm_atomic.c
+++ b/drivers/gpu/drm/drm_atomic.c
@@ -38,24 +38,19 @@ static void kfree_state(struct drm_atomic_state *state)
 	kfree(state->crtc_states);
 	kfree(state->planes);
 	kfree(state->plane_states);
-	kfree(state);
 }
 
 /**
- * drm_atomic_state_alloc - allocate atomic state
+ * __drm_atomic_new_state - init new atomic state
  * @dev: DRM device
+ * @state: atomic state
  *
- * This allocates an empty atomic state to track updates.
+ * Default implementation for filling in a new atomic state.
+ * This is useful for drivers that subclass the atomic state.
  */
-struct drm_atomic_state *
-drm_atomic_state_alloc(struct drm_device *dev)
+int __drm_atomic_new_state(struct drm_device *dev,
+			   struct drm_atomic_state *state)
 {
-	struct drm_atomic_state *state;
-
-	state = kzalloc(sizeof(*state), GFP_KERNEL);
-	if (!state)
-		return NULL;
-
 	/* TODO legacy paths should maybe do a better job about
 	 * setting this appropriately?
 	 */
@@ -92,31 +87,50 @@ drm_atomic_state_alloc(struct drm_device *dev)
 
 	state->dev = dev;
 
-	DRM_DEBUG_ATOMIC("Allocate atomic state %p\n", state);
+	DRM_DEBUG_ATOMIC("Allocated atomic state %p\n", state);
 
-	return state;
+	return 0;
 fail:
 	kfree_state(state);
+	return -ENOMEM;
+}
+EXPORT_SYMBOL(__drm_atomic_new_state);
 
-	return NULL;
+/**
+ * drm_atomic_state_alloc - allocate atomic state
+ * @dev: DRM device
+ *
+ * This allocates an empty atomic state to track updates.
+ */
+struct drm_atomic_state *
+drm_atomic_state_alloc(struct drm_device *dev)
+{
+	struct drm_mode_config *config = &dev->mode_config;
+	struct drm_atomic_state *state;
+
+	if (!config->funcs->atomic_new_state) {
+		state = kzalloc(sizeof(*state), GFP_KERNEL);
+		if (!state)
+			return NULL;
+		if (__drm_atomic_new_state(dev, state) < 0) {
+			kfree(state);
+			return NULL;
+		}
+		return state;
+	}
+
+	return config->funcs->atomic_new_state(dev);
 }
 EXPORT_SYMBOL(drm_atomic_state_alloc);
 
 /**
- * drm_atomic_state_clear - clear state object
+ * __drm_atomic_clear_state - clear atomic state
  * @state: atomic state
  *
- * When the w/w mutex algorithm detects a deadlock we need to back off and drop
- * all locks. So someone else could sneak in and change the current modeset
- * configuration. Which means that all the state assembled in @state is no
- * longer an atomic update to the current state, but to some arbitrary earlier
- * state. Which could break assumptions the driver's ->atomic_check likely
- * relies on.
- *
- * Hence we must clear all cached state and completely start over, using this
- * function.
+ * Default implementation for clearing atomic state.
+ * This is useful for drivers that subclass the atomic state.
  */
-void drm_atomic_state_clear(struct drm_atomic_state *state)
+void __drm_atomic_clear_state(struct drm_atomic_state *state)
 {
 	struct drm_device *dev = state->dev;
 	struct drm_mode_config *config = &dev->mode_config;
@@ -162,6 +176,32 @@ void drm_atomic_state_clear(struct drm_atomic_state *state)
 		state->plane_states[i] = NULL;
 	}
 }
+EXPORT_SYMBOL(__drm_atomic_clear_state);
+
+/**
+ * drm_atomic_state_clear - clear state object
+ * @state: atomic state
+ *
+ * When the w/w mutex algorithm detects a deadlock we need to back off and drop
+ * all locks. So someone else could sneak in and change the current modeset
+ * configuration. Which means that all the state assembled in @state is no
+ * longer an atomic update to the current state, but to some arbitrary earlier
+ * state. Which could break assumptions the driver's ->atomic_check likely
+ * relies on.
+ *
+ * Hence we must clear all cached state and completely start over, using this
+ * function.
+ */
+void drm_atomic_state_clear(struct drm_atomic_state *state)
+{
+	struct drm_device *dev = state->dev;
+	struct drm_mode_config *config = &dev->mode_config;
+
+	if (config->funcs->atomic_clear_state)
+		config->funcs->atomic_clear_state(state);
+	else
+		__drm_atomic_clear_state(state);
+}
 EXPORT_SYMBOL(drm_atomic_state_clear);
 
 /**
@@ -181,6 +221,7 @@ void drm_atomic_state_free(struct drm_atomic_state *state)
 	DRM_DEBUG_ATOMIC("Freeing atomic state %p\n", state);
 
 	kfree_state(state);
+	kfree(state);
 }
 EXPORT_SYMBOL(drm_atomic_state_free);
 
diff --git a/include/drm/drm_atomic.h b/include/drm/drm_atomic.h
index c157103492b0..6125eec6ad79 100644
--- a/include/drm/drm_atomic.h
+++ b/include/drm/drm_atomic.h
@@ -35,6 +35,10 @@ drm_atomic_state_alloc(struct drm_device *dev);
 void drm_atomic_state_clear(struct drm_atomic_state *state);
 void drm_atomic_state_free(struct drm_atomic_state *state);
 
+int  __must_check
+__drm_atomic_new_state(struct drm_device *dev, struct drm_atomic_state *state);
+void __drm_atomic_clear_state(struct drm_atomic_state *state);
+
 struct drm_crtc_state * __must_check
 drm_atomic_get_crtc_state(struct drm_atomic_state *state,
 			  struct drm_crtc *crtc);
diff --git a/include/drm/drm_crtc.h b/include/drm/drm_crtc.h
index 0a4a040d6bb7..e5bea3a45484 100644
--- a/include/drm/drm_crtc.h
+++ b/include/drm/drm_crtc.h
@@ -983,6 +983,8 @@ struct drm_mode_set {
  * @atomic_check: check whether a given atomic state update is possible
  * @atomic_commit: commit an atomic state update previously verified with
  * 	atomic_check()
+ * @atomic_clear_state: allocate a new atomic state
+ * @atomic_clear_state: clear the atomic state
  *
  * Some global (i.e. not per-CRTC, connector, etc) mode setting functions that
  * involve drivers.
@@ -998,6 +1000,8 @@ struct drm_mode_config_funcs {
 	int (*atomic_commit)(struct drm_device *dev,
 			     struct drm_atomic_state *a,
 			     bool async);
+	struct drm_atomic_state *(*atomic_new_state)(struct drm_device *dev);
+	void (*atomic_clear_state)(struct drm_atomic_state *state);
 };
 
 /**
-- 
2.1.0



More information about the Intel-gfx mailing list