drm/msm: Avoid subclassing of drm_atomic_state
cover drm/msm: Avoid subclassing of drm_atomic_state
It's been recommended that we use drm_private_objs embedded in drm_atomic_state to hold shared resources instead of subclassing drm_atomic_state.
This will also help us in getting one step closer to using the atomic commit helpers instead of the msm_atomic_commit() funcs in msm_atomic.c
I've taken the drm_private_obj usage in drm_dp_mst_topology as reference. I've put this as RFC because I want others to see if the private_obj stuff is used correctly.
Archit Taneja (3):
drm/msm/mdp5: Add global state as a private atomic object drm/msm/mdp5: Use the new private_obj state drm/msm: Don't subclass drm_atomic_state anymore
drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.c | 104 +++++++++++++++++++++--------- drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.h | 29 +++++---- drivers/gpu/drm/msm/mdp/mdp5/mdp5_mixer.c | 12 ++-- drivers/gpu/drm/msm/mdp/mdp5/mdp5_pipe.c | 20 +++--- drivers/gpu/drm/msm/mdp/mdp5/mdp5_smp.c | 17 +++-- drivers/gpu/drm/msm/msm_atomic.c | 31 --------- drivers/gpu/drm/msm/msm_drv.c | 3 - drivers/gpu/drm/msm/msm_kms.h | 14 ---- 8 files changed, 121 insertions(+), 109 deletions(-)
Signature · 7 lines
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum, hosted by The Linux Foundation _______________________________________________ dri-devel mailing list [email protected] https://lists.freedesktop.org/mailman/listinfo/dri-devel
RFC 1/3 drm/msm/mdp5: Add global state as a private atomic object
Global shared resources (hwpipes, hwmixers and SMP) for MDP5 are implemented as a part of atomic state by subclassing drm_atomic_state.
The preferred approach is to use the drm_private_obj infrastructure available in the atomic core.
mdp5_global_state is introduced as a drm atomic private object. The two funcs mdp5_get_global_state() and mdp5_get_existing_global_state() are the two variants that will be used to access mdp5_global_state.
This will replace the existing mdp5_state struct (which subclasses drm_atomic_state) and the funcs around it. These will be removed later once we mdp5_global_state is put to use everywhere.
--- drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.c | 86 +++++++++++++++++++++++++++++++++ drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.h | 27 +++++++++++ 2 files changed, 113 insertions(+)
drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.c +86 -0
@@ -106,6 +106,86 @@ static void mdp5_swap_state(struct msm_kms *kms, struct drm_atomic_state *state)swap (to_kms_state (state)->state, mdp5_kms->state); } +/* Global/shared object state funcs */ + +/* +* This is a helper that returns the private state currently in operation. +* Note that this would return the "old_state" if called in the atomic check +* path, and the "new_state" after the atomic swap has been done. +*/ +struct mdp5_global_state * +mdp5_get_existing_global_state (struct mdp5_kms *mdp5_kms) +{ +return to_mdp5_global_state (mdp5_kms->glob_base.state); +} + +/* +* This acquires the modeset lock set aside for global state, creates +* a new duplicated private object state. +*/ +struct mdp5_global_state *mdp5_get_global_state (struct drm_atomic_state *s) +{ +struct msm_drm_private *priv = s->dev->dev_private; +struct mdp5_kms *mdp5_kms =to_mdp5_kms (to_mdp_kms (priv->kms)); +struct drm_private_state *priv_state; +int ret; + + ret =drm_modeset_lock (&mdp5_kms->glob_state_lock, s->acquire_ctx); +if (ret) +return ERR_PTR (ret); + + priv_state =drm_atomic_get_private_obj_state (s, &mdp5_kms->glob_base); +if (IS_ERR (priv_state)) +return ERR_CAST (priv_state); + +return to_mdp5_global_state (priv_state); +} + +static struct drm_private_state * +mdp5_global_duplicate_state (struct drm_private_obj *obj) +{ +struct mdp5_global_state *state; + + state =kmemdup (obj->state,sizeof (*state),GFP_KERNEL ); +if (!state) +return NULL ; + +__drm_atomic_helper_private_obj_duplicate_state (obj, &state->base); + +return &state->base; +} + +static void mdp5_global_destroy_state (struct drm_private_obj *obj, +struct drm_private_state *state) +{ +struct mdp5_global_state *mdp5_state =to_mdp5_global_state (state); + +kfree (mdp5_state); +} + +static const struct drm_private_state_funcs mdp5_global_state_funcs = { + .atomic_duplicate_state = mdp5_global_duplicate_state, + .atomic_destroy_state = mdp5_global_destroy_state, +}; + +static int mdp5_global_obj_init (struct mdp5_kms *mdp5_kms) +{ +struct mdp5_global_state *state; + + state =kzalloc (sizeof (*state),GFP_KERNEL ); +if (!state) +return -ENOMEM ; + +drm_modeset_lock_init (&mdp5_kms->glob_state_lock); + + state->mdp5_kms = mdp5_kms; + +drm_atomic_private_obj_init (&mdp5_kms->glob_base, + &state->base, + &mdp5_global_state_funcs); +return 0 ; +} +static void mdp5_prepare_commit (struct msm_kms *kms,struct drm_atomic_state *state) {struct mdp5_kms *mdp5_kms =to_mdp5_kms (to_mdp_kms (kms));
@@ -727,6 +807,8 @@ static void mdp5_destroy(struct platform_device *pdev)if (mdp5_kms->rpm_enabled)pm_runtime_disable (&pdev->dev); +drm_atomic_private_obj_fini (&mdp5_kms->glob_base); +kfree (mdp5_kms->state); }
@@ -887,6 +969,10 @@ static int mdp5_init(struct platform_device *pdev, struct drm_device *dev) goto fail; } + ret =mdp5_global_obj_init (mdp5_kms); +if (ret) + goto fail; + mdp5_kms->mmio =msm_ioremap (pdev,"mdp_phys" ,"MDP5" );if (IS_ERR (mdp5_kms->mmio)) { ret =PTR_ERR (mdp5_kms->mmio);
drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.h +27 -0
@@ -55,6 +55,13 @@ struct mdp5_kms {struct mdp5_state *state;struct drm_modeset_lock state_lock; +/* +* Global private object state, Do not access directly, use +* mdp5_global_get_state() +*/ +struct drm_private_obj glob_base; +struct drm_modeset_lock glob_state_lock; +struct mdp5_smp *smp;struct mdp5_ctl_manager *ctlm;
@@ -95,6 +102,26 @@ struct mdp5_state {struct mdp5_state *__must_check mdp5_get_state (struct drm_atomic_state *s); +/* Global private object state for tracking resources that are shared across +* multiple kms objects (planes/crtcs/etc). +*/ +#define to_mdp5_global_state (x) container_of(x, struct mdp5_global_state, base) +struct mdp5_global_state { +struct drm_private_state base; + +struct drm_atomic_state *state; +struct mdp5_kms *mdp5_kms; + +struct mdp5_hw_pipe_state hwpipe; +struct mdp5_hw_mixer_state hwmixer; +struct mdp5_smp_state smp; +}; + +struct mdp5_global_state * +mdp5_get_existing_global_state (struct mdp5_kms *mdp5_kms); +struct mdp5_global_state *__must_check +mdp5_get_global_state (struct drm_atomic_state *s); +/* Atomic plane state. Subclasses the base drm_plane_state in order to * track assigned hwpipe and hw specific state. */
Signature · 2 lines
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum, hosted by The Linux Foundation
Re: [RFC 1/3] drm/msm/mdp5: Add global state as a private atomic object
Quoted 29 lines · Archit Taneja
Global shared resources (hwpipes, hwmixers and SMP) for MDP5 are implemented as a part of atomic state by subclassing
drm_atomic_state.The preferred approach is to use the
drm_private_objinfrastructure available in the atomic core.
mdp5_global_stateis introduced as a drm atomic private object. The two funcsmdp5_get_global_state()andmdp5_get_existing_global_state()are the two variants that will be used to accessmdp5_global_state.This will replace the existing
mdp5_statestruct (which subclassesdrm_atomic_state) and the funcs around it. These will be removed later once wemdp5_global_stateis put to use everywhere.Signed-off-by Archit Taneja <[email protected]>--- drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.c | 86 +++++++++++++++++++++++++++++++++ drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.h | 27 +++++++++++ 2 files changed, 113 insertions(+)drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.c +1
-0@@ -106,6 +106,86 @@ static void mdp5_swap_state(struct msm_kms *kms, struct drm_atomic_state *state)swap (to_kms_state (state)->state, mdp5_kms->state); } +/* Global/shared object state funcs */
drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.c static void mdp5_swap_state(struct msm_kms *kms, struct drm_atomic_state *state) · line 119
Quoted 10 lines
drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.c +10
-0+ +/* +* This is a helper that returns the private state currently in operation. +* Note that this would return the "old_state" if called in the atomic check +* path, and the "new_state" after the atomic swap has been done. +*/ +struct mdp5_global_state * +mdp5_get_existing_global_state (struct mdp5_kms *mdp5_kms) +{ +return to_mdp5_global_state (mdp5_kms->glob_base.state);
This doesn't match the existing state stuff for everything else. Here you look at the global state, but not at the one hanging off drm_atomic_state.
Maybe we should add a drm_atomic_get_existing_private_obj_state function to make this easier?
I'm also not 100% sure on what semantics you want precisely.
Quoted 50 lines
drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.c +50
-0+} + +/* +* This acquires the modeset lock set aside for global state, creates +* a new duplicated private object state. +*/ +struct mdp5_global_state *mdp5_get_global_state (struct drm_atomic_state *s) +{ +struct msm_drm_private *priv = s->dev->dev_private; +struct mdp5_kms *mdp5_kms =to_mdp5_kms (to_mdp_kms (priv->kms)); +struct drm_private_state *priv_state; +int ret; + + ret =drm_modeset_lock (&mdp5_kms->glob_state_lock, s->acquire_ctx); +if (ret) +return ERR_PTR (ret); + + priv_state =drm_atomic_get_private_obj_state (s, &mdp5_kms->glob_base); +if (IS_ERR (priv_state)) +return ERR_CAST (priv_state); + +return to_mdp5_global_state (priv_state); +} + +static struct drm_private_state * +mdp5_global_duplicate_state (struct drm_private_obj *obj) +{ +struct mdp5_global_state *state; + + state =kmemdup (obj->state,sizeof (*state),GFP_KERNEL ); +if (!state) +return NULL ; + +__drm_atomic_helper_private_obj_duplicate_state (obj, &state->base); + +return &state->base; +} + +static void mdp5_global_destroy_state (struct drm_private_obj *obj, +struct drm_private_state *state) +{ +struct mdp5_global_state *mdp5_state =to_mdp5_global_state (state); + +kfree (mdp5_state); +} + +static const struct drm_private_state_funcs mdp5_global_state_funcs = { + .atomic_duplicate_state = mdp5_global_duplicate_state, + .atomic_destroy_state = mdp5_global_destroy_state, +};
drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.c static void mdp5_swap_state(struct msm_kms *kms, struct drm_atomic_state *state) · line 179
Quoted 10 lines
drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.c +10
-0+ +static int mdp5_global_obj_init (struct mdp5_kms *mdp5_kms) +{ +struct mdp5_global_state *state; + + state =kzalloc (sizeof (*state),GFP_KERNEL ); +if (!state) +return -ENOMEM ; + +drm_modeset_lock_init (&mdp5_kms->glob_state_lock);
I thought a bit the last few days about how to integrate modeset locking into driver private state objects. I think the simplest solution would be if we just add a drm_modeset_lock to drm_private_obj, and push the locking (both here and in the mst helper) into the core private obj code.
Per-object locking might be a bit overkill (it's definitely overkill for mst), but it's also easier to avoid special cases.
That would reduce the boilerplate here a bit more, essentially converting the wrappers into type casting functions.
-Daniel
Quoted 81 lines
drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.c +15
-0+ + state->mdp5_kms = mdp5_kms; + +drm_atomic_private_obj_init (&mdp5_kms->glob_base, + &state->base, + &mdp5_global_state_funcs); +return 0 ; +} +static void mdp5_prepare_commit (struct msm_kms *kms,struct drm_atomic_state *state) {struct mdp5_kms *mdp5_kms =to_mdp5_kms (to_mdp_kms (kms));@@ -727,6 +807,8 @@ static void mdp5_destroy(struct platform_device *pdev)if (mdp5_kms->rpm_enabled)pm_runtime_disable (&pdev->dev); +drm_atomic_private_obj_fini (&mdp5_kms->glob_base); +kfree (mdp5_kms->state); }@@ -887,6 +969,10 @@ static int mdp5_init(struct platform_device *pdev, struct drm_device *dev) goto fail; } + ret =mdp5_global_obj_init (mdp5_kms); +if (ret) + goto fail; + mdp5_kms->mmio =msm_ioremap (pdev,"mdp_phys" ,"MDP5" );if (IS_ERR (mdp5_kms->mmio)) { ret =PTR_ERR (mdp5_kms->mmio);drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.h +27
-0@@ -55,6 +55,13 @@ struct mdp5_kms {struct mdp5_state *state;struct drm_modeset_lock state_lock; +/* +* Global private object state, Do not access directly, use +* mdp5_global_get_state() +*/ +struct drm_private_obj glob_base; +struct drm_modeset_lock glob_state_lock; +struct mdp5_smp *smp;struct mdp5_ctl_manager *ctlm;@@ -95,6 +102,26 @@ struct mdp5_state {struct mdp5_state *__must_check mdp5_get_state (struct drm_atomic_state *s); +/* Global private object state for tracking resources that are shared across +* multiple kms objects (planes/crtcs/etc). +*/ +#define to_mdp5_global_state (x) container_of(x, struct mdp5_global_state, base) +struct mdp5_global_state { +struct drm_private_state base; + +struct drm_atomic_state *state; +struct mdp5_kms *mdp5_kms; + +struct mdp5_hw_pipe_state hwpipe; +struct mdp5_hw_mixer_state hwmixer; +struct mdp5_smp_state smp; +}; + +struct mdp5_global_state * +mdp5_get_existing_global_state (struct mdp5_kms *mdp5_kms); +struct mdp5_global_state *__must_check +mdp5_get_global_state (struct drm_atomic_state *s); +/* Atomic plane state. Subclasses the base drm_plane_state in order to * track assigned hwpipe and hw specific state. */ Signature · 2 lines
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum, hosted by The Linux Foundation
Signature · 7 lines
Daniel Vetter Software Engineer, Intel Corporation http://blog.ffwll.ch _______________________________________________ dri-devel mailing list [email protected] https://lists.freedesktop.org/mailman/listinfo/dri-devel
Re: [RFC 1/3] drm/msm/mdp5: Add global state as a private atomic object
Quoted 44 lines · Daniel Vetter
Quoted 29 lines · Archit Taneja
Global shared resources (hwpipes, hwmixers and SMP) for MDP5 are implemented as a part of atomic state by subclassing
drm_atomic_state.The preferred approach is to use the
drm_private_objinfrastructure available in the atomic core.
mdp5_global_stateis introduced as a drm atomic private object. The two funcsmdp5_get_global_state()andmdp5_get_existing_global_state()are the two variants that will be used to accessmdp5_global_state.This will replace the existing
mdp5_statestruct (which subclassesdrm_atomic_state) and the funcs around it. These will be removed later once wemdp5_global_stateis put to use everywhere.Signed-off-by Archit Taneja <[email protected]>--- drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.c | 86 +++++++++++++++++++++++++++++++++ drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.h | 27 +++++++++++ 2 files changed, 113 insertions(+)drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.c +1
-0@@ -106,6 +106,86 @@ static void mdp5_swap_state(struct msm_kms *kms, struct drm_atomic_state *state)swap (to_kms_state (state)->state, mdp5_kms->state); } +/* Global/shared object state funcs */ drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.c static void mdp5_swap_state(struct msm_kms *kms, struct drm_atomic_state *state) · line 119
Quoted 10 lines
drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.c +10
-0+ +/* +* This is a helper that returns the private state currently in operation. +* Note that this would return the "old_state" if called in the atomic check +* path, and the "new_state" after the atomic swap has been done. +*/ +struct mdp5_global_state * +mdp5_get_existing_global_state (struct mdp5_kms *mdp5_kms) +{ +return to_mdp5_global_state (mdp5_kms->glob_base.state);This doesn't match the existing state stuff for everything else. Here you look at the global state, but not at the one hanging off
drm_atomic_state.
Quoted 4 lines
Maybe we should add a
drm_atomic_get_existing_private_obj_statefunction to make this easier?I'm also not 100% sure on what semantics you want precisely.
I just wanted a func that returns me the private obj's state that is currently "in use". I.e, the old state pre-swap, and the new state post-swap. If I use drm_atomic_get_private_obj_state() after the swap has occurred, I get the old state back. In other words, there aren't funcs for private objs like drm_atomic_get_new_crtc_state() and drm_atomic_get_old_crtc_state() that we can use. I'll go through the code again carefully to see if my understanding isn't screwed up.
Quoted 59 lines
Quoted 59 lines
drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.c +57
-0+} + +/* +* This acquires the modeset lock set aside for global state, creates +* a new duplicated private object state. +*/ +struct mdp5_global_state *mdp5_get_global_state (struct drm_atomic_state *s) +{ +struct msm_drm_private *priv = s->dev->dev_private; +struct mdp5_kms *mdp5_kms =to_mdp5_kms (to_mdp_kms (priv->kms)); +struct drm_private_state *priv_state; +int ret; + + ret =drm_modeset_lock (&mdp5_kms->glob_state_lock, s->acquire_ctx); +if (ret) +return ERR_PTR (ret); + + priv_state =drm_atomic_get_private_obj_state (s, &mdp5_kms->glob_base); +if (IS_ERR (priv_state)) +return ERR_CAST (priv_state); + +return to_mdp5_global_state (priv_state); +} + +static struct drm_private_state * +mdp5_global_duplicate_state (struct drm_private_obj *obj) +{ +struct mdp5_global_state *state; + + state =kmemdup (obj->state,sizeof (*state),GFP_KERNEL ); +if (!state) +return NULL ; + +__drm_atomic_helper_private_obj_duplicate_state (obj, &state->base); + +return &state->base; +} + +static void mdp5_global_destroy_state (struct drm_private_obj *obj, +struct drm_private_state *state) +{ +struct mdp5_global_state *mdp5_state =to_mdp5_global_state (state); + +kfree (mdp5_state); +} + +static const struct drm_private_state_funcs mdp5_global_state_funcs = { + .atomic_duplicate_state = mdp5_global_duplicate_state, + .atomic_destroy_state = mdp5_global_destroy_state, +}; + +static int mdp5_global_obj_init (struct mdp5_kms *mdp5_kms) +{ +struct mdp5_global_state *state; + + state =kzalloc (sizeof (*state),GFP_KERNEL ); +if (!state)
Quoted 8 lines
drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.c static void mdp5_swap_state(struct msm_kms *kms, struct drm_atomic_state *state) · line 179
Quoted 3 lines
drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.c +3
-0+return -ENOMEM ; + +drm_modeset_lock_init (&mdp5_kms->glob_state_lock);I thought a bit the last few days about how to integrate modeset locking into driver private state objects. I think the simplest solution would be if we just add a
drm_modeset_locktodrm_private_obj, and push the locking (both here and in the mst helper) into the core private obj code.
I'm also a bit unclear on how many private objs one should create. In this patchset, I just create one private obj instance, and stuff all of our shared resources into it (see mdp5_global_state below). I didn't see the point in creating one priv object per shared resource, since a single lock for all of them seemed okay here.
Thanks,
Archit
Quoted 90 lines
Per-object locking might be a bit overkill (it's definitely overkill for mst), but it's also easier to avoid special cases.
That would reduce the boilerplate here a bit more, essentially converting the wrappers into type casting functions.
-DanielQuoted 81 lines
drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.c +15
-0+ + state->mdp5_kms = mdp5_kms; + +drm_atomic_private_obj_init (&mdp5_kms->glob_base, + &state->base, + &mdp5_global_state_funcs); +return 0 ; +} +static void mdp5_prepare_commit (struct msm_kms *kms,struct drm_atomic_state *state) {struct mdp5_kms *mdp5_kms =to_mdp5_kms (to_mdp_kms (kms));@@ -727,6 +807,8 @@ static void mdp5_destroy(struct platform_device *pdev)if (mdp5_kms->rpm_enabled)pm_runtime_disable (&pdev->dev); +drm_atomic_private_obj_fini (&mdp5_kms->glob_base); +kfree (mdp5_kms->state); }@@ -887,6 +969,10 @@ static int mdp5_init(struct platform_device *pdev, struct drm_device *dev) goto fail; } + ret =mdp5_global_obj_init (mdp5_kms); +if (ret) + goto fail; + mdp5_kms->mmio =msm_ioremap (pdev,"mdp_phys" ,"MDP5" );if (IS_ERR (mdp5_kms->mmio)) { ret =PTR_ERR (mdp5_kms->mmio);drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.h +27
-0@@ -55,6 +55,13 @@ struct mdp5_kms {struct mdp5_state *state;struct drm_modeset_lock state_lock; +/* +* Global private object state, Do not access directly, use +* mdp5_global_get_state() +*/ +struct drm_private_obj glob_base; +struct drm_modeset_lock glob_state_lock; +struct mdp5_smp *smp;struct mdp5_ctl_manager *ctlm;@@ -95,6 +102,26 @@ struct mdp5_state {struct mdp5_state *__must_check mdp5_get_state (struct drm_atomic_state *s); +/* Global private object state for tracking resources that are shared across +* multiple kms objects (planes/crtcs/etc). +*/ +#define to_mdp5_global_state (x) container_of(x, struct mdp5_global_state, base) +struct mdp5_global_state { +struct drm_private_state base; + +struct drm_atomic_state *state; +struct mdp5_kms *mdp5_kms; + +struct mdp5_hw_pipe_state hwpipe; +struct mdp5_hw_mixer_state hwmixer; +struct mdp5_smp_state smp; +}; + +struct mdp5_global_state * +mdp5_get_existing_global_state (struct mdp5_kms *mdp5_kms); +struct mdp5_global_state *__must_check +mdp5_get_global_state (struct drm_atomic_state *s); +/* Atomic plane state. Subclasses the base drm_plane_state in order to * track assigned hwpipe and hw specific state. */ Signature · 2 lines
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum, hosted by The Linux Foundation
Signature · 6 lines
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, a Linux Foundation Collaborative Project _______________________________________________ dri-devel mailing list [email protected] https://lists.freedesktop.org/mailman/listinfo/dri-devel
Re: [RFC 1/3] drm/msm/mdp5: Add global state as a private atomic object
Quoted 146 lines · Archit Taneja
Quoted 51 lines · Daniel Vetter
Quoted 40 lines · Archit Taneja
Global shared resources (hwpipes, hwmixers and SMP) for MDP5 are implemented as a part of atomic state by subclassing
drm_atomic_state.The preferred approach is to use the
drm_private_objinfrastructure available in the atomic core.
mdp5_global_stateis introduced as a drm atomic private object. The two funcsmdp5_get_global_state()andmdp5_get_existing_global_state()are the two variants that will be used to accessmdp5_global_state.This will replace the existing
mdp5_statestruct (which subclassesdrm_atomic_state) and the funcs around it. These will be removed later once wemdp5_global_stateis put to use everywhere.Signed-off-by Archit Taneja <[email protected]>--- drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.c | 86 +++++++++++++++++++++++++++++++++ drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.h | 27 +++++++++++ 2 files changed, 113 insertions(+)drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.c +3
-0@@ -106,6 +106,86 @@ static void mdp5_swap_state(struct msm_kms *kms, struct drm_atomic_state *state) swap(to_kms_state(state)->state, mdp5_kms->state); } +/* Global/shared object state funcs */ + +/* +* This is a helper that returns the private state currently in operation.
+ * Note that this would return the "old_state" if called in the atomic check
+ * path, and the "new_state" after the atomic swap has been done.
+ */drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.c static void mdp5_swap_state(struct msm_kms *kms, struct drm_atomic_state *state) · line 119
Quoted 4 lines
drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.c +4
-0+struct mdp5_global_state * +mdp5_get_existing_global_state (struct mdp5_kms *mdp5_kms) +{ +return to_mdp5_global_state (mdp5_kms->glob_base.state);This doesn't match the existing state stuff for everything else. Here you look at the global state, but not at the one hanging off
drm_atomic_state.Quoted 4 lines
Maybe we should add a
drm_atomic_get_existing_private_obj_statefunction to make this easier?I'm also not 100% sure on what semantics you want precisely.
I just wanted a func that returns me the private obj's state that is currently
"in use". I.e, the old state pre-swap, and the new state post-swap. If I usedrm_atomic_get_private_obj_state()after the swap has occurred, I get the old
state back. In other words, there aren't funcs for private objs likedrm_atomic_get_new_crtc_state()anddrm_atomic_get_old_crtc_state()that we can use. I'll go through the code again carefully to see if my understanding isn't screwed up.Quoted 65 lines
Quoted 65 lines
drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.c +7
-0+} + +/* +* This acquires the modeset lock set aside for global state, creates +* a new duplicated private object state. +*/ +struct mdp5_global_state *mdp5_get_global_state(struct drm_atomic_state*s)
drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.c +7
-0+{ +struct msm_drm_private *priv = s->dev->dev_private; +struct mdp5_kms *mdp5_kms =to_mdp5_kms (to_mdp_kms (priv->kms)); +struct drm_private_state *priv_state; +int ret; + + ret = drm_modeset_lock(&mdp5_kms->glob_state_lock,
s->acquire_ctx);drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.c +4
-0+if (ret) +return ERR_PTR (ret); + + priv_state = drm_atomic_get_private_obj_state(s,
&mdp5_kms->glob_base);drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.c +16
-0+if (IS_ERR (priv_state)) +return ERR_CAST (priv_state); + +return to_mdp5_global_state (priv_state); +} + +static struct drm_private_state * +mdp5_global_duplicate_state (struct drm_private_obj *obj) +{ +struct mdp5_global_state *state; + + state =kmemdup (obj->state,sizeof (*state),GFP_KERNEL ); +if (!state) +return NULL ; + + __drm_atomic_helper_private_obj_duplicate_state(obj,
&state->base);drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.c +8
-0+ +return &state->base; +} + +static void mdp5_global_destroy_state (struct drm_private_obj *obj, +struct drm_private_state *state) +{ + struct mdp5_global_state *mdp5_state =
to_mdp5_global_state(state);drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.c +16
-0+ +kfree (mdp5_state); +} + +static const struct drm_private_state_funcs mdp5_global_state_funcs = { + .atomic_duplicate_state = mdp5_global_duplicate_state, + .atomic_destroy_state = mdp5_global_destroy_state, +}; + +static int mdp5_global_obj_init (struct mdp5_kms *mdp5_kms) +{ +struct mdp5_global_state *state; + + state =kzalloc (sizeof (*state),GFP_KERNEL ); +if (!state) +return -ENOMEM ;Quoted 8 lines
drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.c
Quoted 2 lines
drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.c +2
-0+ +drm_modeset_lock_init (&mdp5_kms->glob_state_lock);I thought a bit the last few days about how to integrate modeset locking into driver private state objects. I think the simplest solution would be if we just add a
drm_modeset_locktodrm_private_obj, and push the locking (both here and in the mst helper) into the core private obj code.
Quoted 8 lines
I'm also a bit unclear on how many private objs one should create. In this patchset,
I just create one private obj instance, and stuff all of our shared resources into
it (seemdp5_global_statebelow). I didn't see the point in creating one priv object
per shared resource, since a single lock for all of them seemed okay here.
fwiw, with the current code, I stuck with just a single modeset lock, since if you are re-assigning hwpipe's you are also re-assigning SMP blocks. Perhaps we should already split that into two now that we added dynamic assignment of mixers. (Ie. so a modeset on one output wouldn't block pagefile on another.)
Maybe just separate private objects + locks for each thing would make more sense than trying to micro-optimize the locking ;-)
BR,
-R
Quoted 96 lines
Thanks,
ArchitQuoted 82 lines
Per-object locking might be a bit overkill (it's definitely overkill for mst), but it's also easier to avoid special cases.
That would reduce the boilerplate here a bit more, essentially converting the wrappers into type casting functions.
-DanielQuoted 74 lines
drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.c +9
-0+ + state->mdp5_kms = mdp5_kms; + +drm_atomic_private_obj_init (&mdp5_kms->glob_base, + &state->base, + &mdp5_global_state_funcs); +return 0 ; +} + static void mdp5_prepare_commit(struct msm_kms *kms, struct
drm_atomic_state*state){ struct mdp5_kms *mdp5_kms = to_mdp5_kms(to_mdp_kms(kms));drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.c +1
-0@@ -727,6 +807,8 @@ static void mdp5_destroy(struct platform_device *pdev)if (mdp5_kms->rpm_enabled)pm_runtime_disable (&pdev->dev); +drm_atomic_private_obj_fini (&mdp5_kms->glob_base); +kfree (mdp5_kms->state); } @@ -887,6 +969,10 @@ static int mdp5_init(struct platform_device *pdev,struct
drm_device*dev)goto fail; }+ ret =
mdp5_global_obj_init(mdp5_kms);drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.c +3
-0+if (ret) + goto fail; + mdp5_kms->mmio =msm_ioremap (pdev,"mdp_phys" ,"MDP5" );if (IS_ERR (mdp5_kms->mmio)) { ret =PTR_ERR (mdp5_kms->mmio);drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.h +6
-0@@ -55,6 +55,13 @@ struct mdp5_kms {struct mdp5_state *state;struct drm_modeset_lock state_lock; +/* +* Global private object state, Do not access directly, use +* mdp5_global_get_state() +*/ + struct drm_private_obj glob_base; +struct drm_modeset_lock glob_state_lock; +struct mdp5_smp *smp;struct mdp5_ctl_manager *ctlm; @@ -95,6 +102,26 @@ struct mdp5_state { struct mdp5_state *__must_check mdp5_get_state(struct drm_atomic_state *s); +/* Global private object state for tracking resources that are sharedacross
+ * multiple kms objects (planes/crtcs/etc).
+ */
+#defineto_mdp5_global_state(x)container_of(x, struct mdp5_global_state, base)drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.h +16
-0+struct mdp5_global_state { +struct drm_private_state base; + +struct drm_atomic_state *state; +struct mdp5_kms *mdp5_kms; + +struct mdp5_hw_pipe_state hwpipe; +struct mdp5_hw_mixer_state hwmixer; +struct mdp5_smp_state smp; +}; + +struct mdp5_global_state * +mdp5_get_existing_global_state (struct mdp5_kms *mdp5_kms); +struct mdp5_global_state *__must_check +mdp5_get_global_state (struct drm_atomic_state *s); +Quoted 9 lines
Quoted 8 lines
/* Atomic plane state. Subclasses the base
drm_plane_statein order to
* track assigned hwpipe and hw specific state.
*/
--
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
hosted by The Linux Foundation
Quoted 3 lines
--
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, a Linux Foundation Collaborative Project
_______________________________________________
dri-devel mailing list
[email protected]
https://lists.freedesktop.org/mailman/listinfo/dri-devel
Re: [RFC 1/3] drm/msm/mdp5: Add global state as a private atomic object
In reply to Daniel VetterQuoted 44 lines · Daniel Vetter
Quoted 29 lines · Archit Taneja
Global shared resources (hwpipes, hwmixers and SMP) for MDP5 are implemented as a part of atomic state by subclassing
drm_atomic_state.The preferred approach is to use the
drm_private_objinfrastructure available in the atomic core.
mdp5_global_stateis introduced as a drm atomic private object. The two funcsmdp5_get_global_state()andmdp5_get_existing_global_state()are the two variants that will be used to accessmdp5_global_state.This will replace the existing
mdp5_statestruct (which subclassesdrm_atomic_state) and the funcs around it. These will be removed later once wemdp5_global_stateis put to use everywhere.Signed-off-by Archit Taneja <[email protected]>--- drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.c | 86 +++++++++++++++++++++++++++++++++ drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.h | 27 +++++++++++ 2 files changed, 113 insertions(+)drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.c +1
-0@@ -106,6 +106,86 @@ static void mdp5_swap_state(struct msm_kms *kms, struct drm_atomic_state *state)swap (to_kms_state (state)->state, mdp5_kms->state); } +/* Global/shared object state funcs */ drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.c static void mdp5_swap_state(struct msm_kms *kms, struct drm_atomic_state *state) · line 119
Quoted 10 lines
drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.c +10
-0+ +/* +* This is a helper that returns the private state currently in operation. +* Note that this would return the "old_state" if called in the atomic check +* path, and the "new_state" after the atomic swap has been done. +*/ +struct mdp5_global_state * +mdp5_get_existing_global_state (struct mdp5_kms *mdp5_kms) +{ +return to_mdp5_global_state (mdp5_kms->glob_base.state);This doesn't match the existing state stuff for everything else. Here you look at the global state, but not at the one hanging off
drm_atomic_state.
Quoted 5 lines
Maybe we should add a
drm_atomic_get_existing_private_obj_statefunction to make this easier?I'm also not 100% sure on what semantics you want precisely.
This is used for read-only access to current state, a couple places in atomic update post-swap (where drm_atomic_get_existing_private_obj_state() would work, but also for things like debugfs, where it wouldn't)..
Probably should const'ify the return value to make it clear that this is read-only.
Quoted 58 lines
Quoted 58 lines
drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.c +57
-0+} + +/* +* This acquires the modeset lock set aside for global state, creates +* a new duplicated private object state. +*/ +struct mdp5_global_state *mdp5_get_global_state (struct drm_atomic_state *s) +{ +struct msm_drm_private *priv = s->dev->dev_private; +struct mdp5_kms *mdp5_kms =to_mdp5_kms (to_mdp_kms (priv->kms)); +struct drm_private_state *priv_state; +int ret; + + ret =drm_modeset_lock (&mdp5_kms->glob_state_lock, s->acquire_ctx); +if (ret) +return ERR_PTR (ret); + + priv_state =drm_atomic_get_private_obj_state (s, &mdp5_kms->glob_base); +if (IS_ERR (priv_state)) +return ERR_CAST (priv_state); + +return to_mdp5_global_state (priv_state); +} + +static struct drm_private_state * +mdp5_global_duplicate_state (struct drm_private_obj *obj) +{ +struct mdp5_global_state *state; + + state =kmemdup (obj->state,sizeof (*state),GFP_KERNEL ); +if (!state) +return NULL ; + +__drm_atomic_helper_private_obj_duplicate_state (obj, &state->base); + +return &state->base; +} + +static void mdp5_global_destroy_state (struct drm_private_obj *obj, +struct drm_private_state *state) +{ +struct mdp5_global_state *mdp5_state =to_mdp5_global_state (state); + +kfree (mdp5_state); +} + +static const struct drm_private_state_funcs mdp5_global_state_funcs = { + .atomic_duplicate_state = mdp5_global_duplicate_state, + .atomic_destroy_state = mdp5_global_destroy_state, +}; + +static int mdp5_global_obj_init (struct mdp5_kms *mdp5_kms) +{ +struct mdp5_global_state *state; + + state =kzalloc (sizeof (*state),GFP_KERNEL ); +if (!state)
Quoted 8 lines
drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.c static void mdp5_swap_state(struct msm_kms *kms, struct drm_atomic_state *state) · line 179
Quoted 3 lines
drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.c +3
-0+return -ENOMEM ; + +drm_modeset_lock_init (&mdp5_kms->glob_state_lock);I thought a bit the last few days about how to integrate modeset locking into driver private state objects. I think the simplest solution would be if we just add a
drm_modeset_locktodrm_private_obj, and push the locking (both here and in the mst helper) into the core private obj code.
I like the idea of adding a modeset lock to private objs.. I've got a WIP patch to do this.
BR,
-R
Quoted 85 lines
Per-object locking might be a bit overkill (it's definitely overkill for mst), but it's also easier to avoid special cases.
That would reduce the boilerplate here a bit more, essentially converting the wrappers into type casting functions.
-DanielQuoted 78 lines
drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.c +15
-0+ + state->mdp5_kms = mdp5_kms; + +drm_atomic_private_obj_init (&mdp5_kms->glob_base, + &state->base, + &mdp5_global_state_funcs); +return 0 ; +} +static void mdp5_prepare_commit (struct msm_kms *kms,struct drm_atomic_state *state) {struct mdp5_kms *mdp5_kms =to_mdp5_kms (to_mdp_kms (kms));@@ -727,6 +807,8 @@ static void mdp5_destroy(struct platform_device *pdev)if (mdp5_kms->rpm_enabled)pm_runtime_disable (&pdev->dev); +drm_atomic_private_obj_fini (&mdp5_kms->glob_base); +kfree (mdp5_kms->state); }@@ -887,6 +969,10 @@ static int mdp5_init(struct platform_device *pdev, struct drm_device *dev) goto fail; } + ret =mdp5_global_obj_init (mdp5_kms); +if (ret) + goto fail; + mdp5_kms->mmio =msm_ioremap (pdev,"mdp_phys" ,"MDP5" );if (IS_ERR (mdp5_kms->mmio)) { ret =PTR_ERR (mdp5_kms->mmio);drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.h +27
-1@@ -55,6 +55,13 @@ struct mdp5_kms {struct mdp5_state *state;struct drm_modeset_lock state_lock; +/* +* Global private object state, Do not access directly, use +* mdp5_global_get_state() +*/ +struct drm_private_obj glob_base; +struct drm_modeset_lock glob_state_lock; +struct mdp5_smp *smp;struct mdp5_ctl_manager *ctlm;@@ -95,6 +102,26 @@ struct mdp5_state {struct mdp5_state *__must_check mdp5_get_state (struct drm_atomic_state *s); +/* Global private object state for tracking resources that are shared across +* multiple kms objects (planes/crtcs/etc). +*/ +#define to_mdp5_global_state (x) container_of(x, struct mdp5_global_state, base) +struct mdp5_global_state { +struct drm_private_state base; + +struct drm_atomic_state *state; +struct mdp5_kms *mdp5_kms; + +struct mdp5_hw_pipe_state hwpipe; +struct mdp5_hw_mixer_state hwmixer; +struct mdp5_smp_state smp; +}; + +struct mdp5_global_state * +mdp5_get_existing_global_state (struct mdp5_kms *mdp5_kms); +struct mdp5_global_state *__must_check +mdp5_get_global_state (struct drm_atomic_state *s); +/* Atomic plane state. Subclasses the base drm_plane_state in order to * track assigned hwpipe and hw specific state. */ --
Quoted 8 lines
Quoted 3 lines
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum, hosted by The Linux Foundation
--
Daniel Vetter
Software Engineer, Intel Corporation
http://blog.ffwll.ch
_______________________________________________
dri-devel mailing list
[email protected]
https://lists.freedesktop.org/mailman/listinfo/dri-devel
RFC 2/3 drm/msm/mdp5: Use the new private_obj state
In reply to Archit TanejaThis replaces the usage of the subclassed atomic state (mdp5_state) with a private_obj state embedded within drm_atomic_state. The latter method is the preferred approach, since it's simpler to implement and less prone to errors.
The new API replaces the older and equivalent mdp5_state usage in the following pattern:
- References to "mdp5_kms->state" (i.e, the old/existing state) is replaced with mdp5_get_existing_global_state(). In the atomic_check path, this should be called with the glob_state_lock drm_modeset_lock alredy taken.
- References to "mdp5_get_state()" are replaced with mdp5_get_global_state(). This acquires glob_state_lock and uses drm_atomic_get_private_obj_state() to create a new duplicated state.
--- drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.c | 10 ++++++++-- drivers/gpu/drm/msm/mdp/mdp5/mdp5_mixer.c | 12 ++++++------ drivers/gpu/drm/msm/mdp/mdp5/mdp5_pipe.c | 20 +++++++++++--------- drivers/gpu/drm/msm/mdp/mdp5/mdp5_smp.c | 17 ++++++++++++----- 4 files changed, 37 insertions(+), 22 deletions(-)
drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.c +8 -2
@@ -190,20 +190,26 @@ static void mdp5_prepare_commit(struct msm_kms *kms, struct drm_atomic_state *st {struct mdp5_kms *mdp5_kms =to_mdp5_kms (to_mdp_kms (kms));struct device *dev = &mdp5_kms->pdev->dev; +struct mdp5_global_state *global_state; + + global_state =mdp5_get_existing_global_state (mdp5_kms);pm_runtime_get_sync (dev);if (mdp5_kms->smp) -mdp5_smp_prepare_commit (mdp5_kms->smp, &mdp5_kms->state->smp); +mdp5_smp_prepare_commit (mdp5_kms->smp, &global_state->smp); }static void mdp5_complete_commit (struct msm_kms *kms,struct drm_atomic_state *state) {struct mdp5_kms *mdp5_kms =to_mdp5_kms (to_mdp_kms (kms));struct device *dev = &mdp5_kms->pdev->dev; +struct mdp5_global_state *global_state; + + global_state =mdp5_get_existing_global_state (mdp5_kms);if (mdp5_kms->smp) -mdp5_smp_complete_commit (mdp5_kms->smp, &mdp5_kms->state->smp); +mdp5_smp_complete_commit (mdp5_kms->smp, &global_state->smp);pm_runtime_put_autosuspend (dev); }
drivers/gpu/drm/msm/mdp/mdp5/mdp5_mixer.c +6 -6
@@ -52,14 +52,14 @@ int mdp5_mixer_assign(struct drm_atomic_state *s, struct drm_crtc *crtc, {struct msm_drm_private *priv = s->dev->dev_private;struct mdp5_kms *mdp5_kms =to_mdp5_kms (to_mdp_kms (priv->kms)); -struct mdp5_state *state =mdp5_get_state (s); +struct mdp5_global_state *global_state =mdp5_get_global_state (s);struct mdp5_hw_mixer_state *new_state;int i; -if (IS_ERR (state)) -return PTR_ERR (state); +if (IS_ERR (global_state)) +return PTR_ERR (global_state); - new_state = &state->hwmixer; + new_state = &global_state->hwmixer;for (i =0 ; i < mdp5_kms->num_hwmixers; i++) {struct mdp5_hw_mixer *cur = mdp5_kms->hwmixers[i];
@@ -129,8 +129,8 @@ int mdp5_mixer_assign(struct drm_atomic_state *s, struct drm_crtc *crtc,void mdp5_mixer_release (struct drm_atomic_state *s,struct mdp5_hw_mixer *mixer) { -struct mdp5_state *state =mdp5_get_state (s); -struct mdp5_hw_mixer_state *new_state = &state->hwmixer; +struct mdp5_global_state *global_state =mdp5_get_global_state (s); +struct mdp5_hw_mixer_state *new_state = &global_state->hwmixer;if (!mixer)return ;
drivers/gpu/drm/msm/mdp/mdp5/mdp5_pipe.c +11 -9
@@ -22,18 +22,20 @@ struct mdp5_hw_pipe *mdp5_pipe_assign(struct drm_atomic_state *s, {struct msm_drm_private *priv = s->dev->dev_private;struct mdp5_kms *mdp5_kms =to_mdp5_kms (to_mdp_kms (priv->kms)); -struct mdp5_state *state; +struct mdp5_global_state *new_global_state, *old_global_state;struct mdp5_hw_pipe_state *old_state, *new_state;struct mdp5_hw_pipe *hwpipe =NULL ;int i; - state =mdp5_get_state (s); -if (IS_ERR (state)) -return ERR_CAST (state); + new_global_state =mdp5_get_global_state (s); +if (IS_ERR (new_global_state)) +return ERR_CAST (new_global_state); -/* grab old_state after mdp5_get_state(), since now we hold lock: */ - old_state = &mdp5_kms->state->hwpipe; - new_state = &state->hwpipe; +/* grab old_state after mdp5_get_global_state(), since now we hold lock: */ + old_global_state =mdp5_get_existing_global_state (mdp5_kms); + + old_state = &old_global_state->hwpipe; + new_state = &new_global_state->hwpipe;for (i =0 ; i < mdp5_kms->num_hwpipes; i++) {struct mdp5_hw_pipe *cur = mdp5_kms->hwpipes[i];
@@ -76,7 +78,7 @@ struct mdp5_hw_pipe *mdp5_pipe_assign(struct drm_atomic_state *s,int ret;DBG ("%s: alloc SMP blocks" , hwpipe->name); - ret =mdp5_smp_assign (mdp5_kms->smp, &state->smp, + ret =mdp5_smp_assign (mdp5_kms->smp, &new_global_state->smp, hwpipe->pipe, blkcfg);if (ret)return ERR_PTR (-ENOMEM );
@@ -95,7 +97,7 @@ void mdp5_pipe_release(struct drm_atomic_state *s, struct mdp5_hw_pipe *hwpipe) {struct msm_drm_private *priv = s->dev->dev_private;struct mdp5_kms *mdp5_kms =to_mdp5_kms (to_mdp_kms (priv->kms)); -struct mdp5_state *state =mdp5_get_state (s); +struct mdp5_global_state *state =mdp5_get_global_state (s);struct mdp5_hw_pipe_state *new_state = &state->hwpipe;if (!hwpipe)
drivers/gpu/drm/msm/mdp/mdp5/mdp5_smp.c +12 -5
@@ -340,17 +340,20 @@ void mdp5_smp_dump(struct mdp5_smp *smp, struct drm_printer *p)struct mdp5_kms *mdp5_kms =get_kms (smp);struct mdp5_hw_pipe_state *hwpstate;struct mdp5_smp_state *state; +struct mdp5_global_state *global_state;int total =0 , i, j;drm_printf (p,"name\tinuse\tplane\n" );drm_printf (p,"----\t-----\t-----\n" );if (drm_can_sleep ()) -drm_modeset_lock (&mdp5_kms->state_lock,NULL ); +drm_modeset_lock (&mdp5_kms->glob_state_lock,NULL ); + + global_state =mdp5_get_existing_global_state (mdp5_kms);/* grab these *after* we hold the state_lock */ - hwpstate = &mdp5_kms->state->hwpipe; - state = &mdp5_kms->state->smp; + hwpstate = &global_state->hwpipe; + state = &global_state->smp;for (i =0 ; i < mdp5_kms->num_hwpipes; i++) {struct mdp5_hw_pipe *hwpipe = mdp5_kms->hwpipes[i];
@@ -374,7 +377,7 @@ void mdp5_smp_dump(struct mdp5_smp *smp, struct drm_printer *p) bitmap_weight(state->state, smp->blk_cnt));if (drm_can_sleep ()) -drm_modeset_unlock (&mdp5_kms->state_lock); +drm_modeset_unlock (&mdp5_kms->glob_state_lock); }void mdp5_smp_destroy (struct mdp5_smp *smp)
@@ -384,7 +387,8 @@ void mdp5_smp_destroy(struct mdp5_smp *smp)struct mdp5_smp *mdp5_smp_init (struct mdp5_kms *mdp5_kms,const struct mdp5_smp_block *cfg) { -struct mdp5_smp_state *state = &mdp5_kms->state->smp; +struct mdp5_smp_state *state; +struct mdp5_global_state *global_state;struct mdp5_smp *smp =NULL ;int ret;
@@ -398,6 +402,9 @@ struct mdp5_smp *mdp5_smp_init(struct mdp5_kms *mdp5_kms, const struct mdp5_smp_ smp->blk_cnt = cfg->mmb_count; smp->blk_size = cfg->mmb_size; + global_state =mdp5_get_existing_global_state (mdp5_kms); + state = &global_state->smp; +/* statically tied MMBs cannot be re-allocated: */ bitmap_copy (state->state, cfg->reserved_state, smp->blk_cnt);memcpy (smp->reserved, cfg->reserved,sizeof (smp->reserved));
Signature · 2 lines
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum, hosted by The Linux Foundation
RFC 3/3 drm/msm: Don't subclass drm_atomic_state anymore
In reply to Archit TanejaWith the addition of "private_objs" in drm_atomic_state, we no longer need to subclass drm_atomic_state to store state of share resources that don't perfectly fit within planes/crtc/connector state information. We can now save this state within drm_atomic_state itself using the private objects.
Remove the infrastructure that allowed subclassing of drm_atomic_state in the driver.
--- drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.c | 46 --------------------------------- drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.h | 22 ---------------- drivers/gpu/drm/msm/msm_atomic.c | 31 ---------------------- drivers/gpu/drm/msm/msm_drv.c | 3 --- drivers/gpu/drm/msm/msm_kms.h | 14 ---------- 5 files changed, 116 deletions(-)
drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.c +0 -46
@@ -70,42 +70,6 @@ static int mdp5_hw_init(struct msm_kms *kms)return 0 ; } -struct mdp5_state *mdp5_get_state (struct drm_atomic_state *s) -{ -struct msm_drm_private *priv = s->dev->dev_private; -struct mdp5_kms *mdp5_kms =to_mdp5_kms (to_mdp_kms (priv->kms)); -struct msm_kms_state *state =to_kms_state (s); -struct mdp5_state *new_state; -int ret; - -if (state->state) -return state->state; - - ret =drm_modeset_lock (&mdp5_kms->state_lock, s->acquire_ctx); -if (ret) -return ERR_PTR (ret); - - new_state =kmalloc (sizeof (*mdp5_kms->state),GFP_KERNEL ); -if (!new_state) -return ERR_PTR (-ENOMEM ); - -/* Copy state: */ - new_state->hwpipe = mdp5_kms->state->hwpipe; - new_state->hwmixer = mdp5_kms->state->hwmixer; -if (mdp5_kms->smp) - new_state->smp = mdp5_kms->state->smp; - - state->state = new_state; - -return new_state; -} - -static void mdp5_swap_state (struct msm_kms *kms,struct drm_atomic_state *state) -{ -struct mdp5_kms *mdp5_kms =to_mdp5_kms (to_mdp_kms (kms)); -swap (to_kms_state (state)->state, mdp5_kms->state); -} -/* Global/shared object state funcs */ /*
@@ -315,7 +279,6 @@ static const struct mdp_kms_funcs kms_funcs = { .irq = mdp5_irq, .enable_vblank = mdp5_enable_vblank, .disable_vblank = mdp5_disable_vblank, - .swap_state = mdp5_swap_state, .prepare_commit = mdp5_prepare_commit, .complete_commit = mdp5_complete_commit, .wait_for_crtc_commit_done = mdp5_wait_for_crtc_commit_done,
@@ -814,8 +777,6 @@ static void mdp5_destroy(struct platform_device *pdev)pm_runtime_disable (&pdev->dev);drm_atomic_private_obj_fini (&mdp5_kms->glob_base); - -kfree (mdp5_kms->state); } static int construct_pipes(struct mdp5_kms *mdp5_kms, int cnt,
@@ -968,13 +929,6 @@ static int mdp5_init(struct platform_device *pdev, struct drm_device *dev) mdp5_kms->dev = dev; mdp5_kms->pdev = pdev; -drm_modeset_lock_init (&mdp5_kms->state_lock); - mdp5_kms->state =kzalloc (sizeof (*mdp5_kms->state),GFP_KERNEL ); -if (!mdp5_kms->state) { - ret = -ENOMEM ; - goto fail; - } - ret =mdp5_global_obj_init (mdp5_kms);if (ret) goto fail;
drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.h +0 -22
@@ -28,8 +28,6 @@#include "mdp5_ctl.h" #include "mdp5_smp.h" -struct mdp5_state ; -struct mdp5_kms {struct mdp_kms base;
@@ -49,12 +47,6 @@ struct mdp5_kms {struct mdp5_cfg_handler *cfg;uint32_t caps;/* MDP capabilities (MDP_CAP_XXX bits) */ -/** -* Global atomic state. Do not access directly, use mdp5_get_state() -*/ -struct mdp5_state *state; -struct drm_modeset_lock state_lock; -/* * Global private object state, Do not access directly, use * mdp5_global_get_state()
@@ -88,20 +80,6 @@ struct mdp5_kms { };#define to_mdp5_kms (x) container_of(x, struct mdp5_kms, base) -/* Global atomic state for tracking resources that are shared across -* multiple kms objects (planes/crtcs/etc). -* -* For atomic updates which require modifying global state, -*/ -struct mdp5_state { -struct mdp5_hw_pipe_state hwpipe; -struct mdp5_hw_mixer_state hwmixer; -struct mdp5_smp_state smp; -}; - -struct mdp5_state *__must_check -mdp5_get_state (struct drm_atomic_state *s); -/* Global private object state for tracking resources that are shared across * multiple kms objects (planes/crtcs/etc). */
drivers/gpu/drm/msm/msm_atomic.c +0 -31
@@ -241,11 +241,7 @@ int msm_atomic_commit(struct drm_device *dev,* This is the point of no return - everything below never fails except * when the hw goes bonghits. Which means we can commit the new state on * the software side now. -* -* swap driver private state while still holding state_lock */ -if (to_kms_state (state)->state) - priv->kms->funcs->swap_state (priv->kms, state);/* * Everything below can be run asynchronously without the need to grab
@@ -279,30 +275,3 @@ int msm_atomic_commit(struct drm_device *dev,drm_atomic_helper_cleanup_planes (dev, state);return ret; } - -struct drm_atomic_state *msm_atomic_state_alloc (struct drm_device *dev) -{ -struct msm_kms_state *state =kzalloc (sizeof (*state),GFP_KERNEL ); - -if (!state ||drm_atomic_state_init (dev, &state->base) <0 ) { -kfree (state); -return NULL ; - } - -return &state->base; -} - -void msm_atomic_state_clear (struct drm_atomic_state *s) -{ -struct msm_kms_state *state =to_kms_state (s); -drm_atomic_state_default_clear (&state->base); -kfree (state->state); - state->state =NULL ; -} - -void msm_atomic_state_free (struct drm_atomic_state *state) -{ -kfree (to_kms_state (state)->state); -drm_atomic_state_default_release (state); -kfree (state); -}
drivers/gpu/drm/msm/msm_drv.c +0 -3
@@ -46,9 +46,6 @@ static const struct drm_mode_config_funcs mode_config_funcs = { .output_poll_changed = msm_fb_output_poll_changed, .atomic_check = msm_atomic_check, .atomic_commit = msm_atomic_commit, - .atomic_state_alloc = msm_atomic_state_alloc, - .atomic_state_clear = msm_atomic_state_clear, - .atomic_state_free = msm_atomic_state_free, };#ifdef CONFIG_DRM_MSM_REGISTER_LOGGING
drivers/gpu/drm/msm/msm_kms.h +0 -14
@@ -40,8 +40,6 @@ struct msm_kms_funcs {irqreturn_t (*irq)(struct msm_kms *kms);int (*enable_vblank)(struct msm_kms *kms,struct drm_crtc *crtc);void (*disable_vblank)(struct msm_kms *kms,struct drm_crtc *crtc); -/* swap global atomic state: */ -void (*swap_state)(struct msm_kms *kms,struct drm_atomic_state *state);/* modeset, bracketing atomic_commit(): */ void (*prepare_commit)(struct msm_kms *kms,struct drm_atomic_state *state);void (*complete_commit)(struct msm_kms *kms,struct drm_atomic_state *state);
@@ -77,18 +75,6 @@ struct msm_kms {struct msm_gem_address_space *aspace; }; -/** -* Subclass of drm_atomic_state, to allow kms backend to have driver -* private global state. The kms backend can do whatever it wants -* with the ->state ptr. On ->atomic_state_clear() the ->state ptr -* is kfree'd and set back to NULL. -*/ -struct msm_kms_state { -struct drm_atomic_state base; -void *state; -}; -#define to_kms_state (x) container_of(x, struct msm_kms_state, base) -static inline void msm_kms_init (struct msm_kms *kms,const struct msm_kms_funcs *funcs) {
Signature · 2 lines
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum, hosted by The Linux Foundation