drm/atomic: Allow drivers to subclass drm_atomic_state, v3
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. Changes since v1: - Change member names for functions to atomic_state_(alloc,clear) - Change __drm_atomic_state_new to drm_atomic_state_init - Allow free function to be overridden too, in case extra memory is allocated in alloc. Changes since v2: - Rename *_default_free to default_release, to make clear it doesn't free the state object itself. Cc: dri-devel@lists.freedesktop.org Acked-by: Ander Conselvan de Oliveira <ander.conselvan.de.oliveira@intel.com> Signed-off-by: Maarten Lankhorst <maarten.lankhorst@linux.intel.com> Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
This commit is contained in:
Родитель
744b058827
Коммит
036ef5733b
|
@ -30,7 +30,15 @@
|
|||
#include <drm/drm_atomic.h>
|
||||
#include <drm/drm_plane_helper.h>
|
||||
|
||||
static void kfree_state(struct drm_atomic_state *state)
|
||||
/**
|
||||
* drm_atomic_state_default_release -
|
||||
* release memory initialized by drm_atomic_state_init
|
||||
* @state: atomic state
|
||||
*
|
||||
* Free all the memory allocated by drm_atomic_state_init.
|
||||
* This is useful for drivers that subclass the atomic state.
|
||||
*/
|
||||
void drm_atomic_state_default_release(struct drm_atomic_state *state)
|
||||
{
|
||||
kfree(state->connectors);
|
||||
kfree(state->connector_states);
|
||||
|
@ -38,24 +46,20 @@ static void kfree_state(struct drm_atomic_state *state)
|
|||
kfree(state->crtc_states);
|
||||
kfree(state->planes);
|
||||
kfree(state->plane_states);
|
||||
kfree(state);
|
||||
}
|
||||
EXPORT_SYMBOL(drm_atomic_state_default_release);
|
||||
|
||||
/**
|
||||
* drm_atomic_state_alloc - allocate atomic state
|
||||
* drm_atomic_state_init - 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_state_init(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 +96,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);
|
||||
drm_atomic_state_default_release(state);
|
||||
return -ENOMEM;
|
||||
}
|
||||
EXPORT_SYMBOL(drm_atomic_state_init);
|
||||
|
||||
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_state_alloc) {
|
||||
state = kzalloc(sizeof(*state), GFP_KERNEL);
|
||||
if (!state)
|
||||
return NULL;
|
||||
if (drm_atomic_state_init(dev, state) < 0) {
|
||||
kfree(state);
|
||||
return NULL;
|
||||
}
|
||||
return state;
|
||||
}
|
||||
|
||||
return config->funcs->atomic_state_alloc(dev);
|
||||
}
|
||||
EXPORT_SYMBOL(drm_atomic_state_alloc);
|
||||
|
||||
/**
|
||||
* drm_atomic_state_clear - clear state object
|
||||
* drm_atomic_state_default_clear - clear base 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_state_default_clear(struct drm_atomic_state *state)
|
||||
{
|
||||
struct drm_device *dev = state->dev;
|
||||
struct drm_mode_config *config = &dev->mode_config;
|
||||
|
@ -162,6 +185,32 @@ void drm_atomic_state_clear(struct drm_atomic_state *state)
|
|||
state->plane_states[i] = NULL;
|
||||
}
|
||||
}
|
||||
EXPORT_SYMBOL(drm_atomic_state_default_clear);
|
||||
|
||||
/**
|
||||
* 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_state_clear)
|
||||
config->funcs->atomic_state_clear(state);
|
||||
else
|
||||
drm_atomic_state_default_clear(state);
|
||||
}
|
||||
EXPORT_SYMBOL(drm_atomic_state_clear);
|
||||
|
||||
/**
|
||||
|
@ -173,14 +222,25 @@ EXPORT_SYMBOL(drm_atomic_state_clear);
|
|||
*/
|
||||
void drm_atomic_state_free(struct drm_atomic_state *state)
|
||||
{
|
||||
struct drm_device *dev;
|
||||
struct drm_mode_config *config;
|
||||
|
||||
if (!state)
|
||||
return;
|
||||
|
||||
dev = state->dev;
|
||||
config = &dev->mode_config;
|
||||
|
||||
drm_atomic_state_clear(state);
|
||||
|
||||
DRM_DEBUG_ATOMIC("Freeing atomic state %p\n", state);
|
||||
|
||||
kfree_state(state);
|
||||
if (config->funcs->atomic_state_free) {
|
||||
config->funcs->atomic_state_free(state);
|
||||
} else {
|
||||
drm_atomic_state_default_release(state);
|
||||
kfree(state);
|
||||
}
|
||||
}
|
||||
EXPORT_SYMBOL(drm_atomic_state_free);
|
||||
|
||||
|
|
|
@ -35,6 +35,11 @@ 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_state_init(struct drm_device *dev, struct drm_atomic_state *state);
|
||||
void drm_atomic_state_default_clear(struct drm_atomic_state *state);
|
||||
void drm_atomic_state_default_release(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);
|
||||
|
|
|
@ -979,6 +979,9 @@ 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_state_alloc: allocate a new atomic state
|
||||
* @atomic_state_clear: clear the atomic state
|
||||
* @atomic_state_free: free the atomic state
|
||||
*
|
||||
* Some global (i.e. not per-CRTC, connector, etc) mode setting functions that
|
||||
* involve drivers.
|
||||
|
@ -994,6 +997,9 @@ struct drm_mode_config_funcs {
|
|||
int (*atomic_commit)(struct drm_device *dev,
|
||||
struct drm_atomic_state *a,
|
||||
bool async);
|
||||
struct drm_atomic_state *(*atomic_state_alloc)(struct drm_device *dev);
|
||||
void (*atomic_state_clear)(struct drm_atomic_state *state);
|
||||
void (*atomic_state_free)(struct drm_atomic_state *state);
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
Загрузка…
Ссылка в новой задаче