Skip to content

Commit de3916c

Browse files
ddavenport-chromiumrobclark
authored andcommitted
drm/msm/dpu: Track resources in global state
Move mapping of resources to encoder ids from the resource manager to a new dpu_global_state struct. Store this struct in global atomic state. Before this patch, atomic test would be performed by modifying global state (resource manager), and backing out any changes if the test fails. By using drm atomic global state, this is not necessary as any changes to the global state will be discarded if the test fails. Signed-off-by: Drew Davenport <[email protected]> Signed-off-by: Rob Clark <[email protected]>
1 parent bb00a45 commit de3916c

File tree

5 files changed

+207
-111
lines changed

5 files changed

+207
-111
lines changed

drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c

Lines changed: 30 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -164,7 +164,6 @@ enum dpu_enc_rc_states {
164164
* clks and resources after IDLE_TIMEOUT time.
165165
* @vsync_event_work: worker to handle vsync event for autorefresh
166166
* @topology: topology of the display
167-
* @mode_set_complete: flag to indicate modeset completion
168167
* @idle_timeout: idle timeout duration in milliseconds
169168
*/
170169
struct dpu_encoder_virt {
@@ -202,7 +201,6 @@ struct dpu_encoder_virt {
202201
struct delayed_work delayed_off_work;
203202
struct kthread_work vsync_event_work;
204203
struct msm_display_topology topology;
205-
bool mode_set_complete;
206204

207205
u32 idle_timeout;
208206
};
@@ -563,6 +561,7 @@ static int dpu_encoder_virt_atomic_check(
563561
const struct drm_display_mode *mode;
564562
struct drm_display_mode *adj_mode;
565563
struct msm_display_topology topology;
564+
struct dpu_global_state *global_state;
566565
int i = 0;
567566
int ret = 0;
568567

@@ -579,6 +578,7 @@ static int dpu_encoder_virt_atomic_check(
579578
dpu_kms = to_dpu_kms(priv->kms);
580579
mode = &crtc_state->mode;
581580
adj_mode = &crtc_state->adjusted_mode;
581+
global_state = dpu_kms_get_existing_global_state(dpu_kms);
582582
trace_dpu_enc_atomic_check(DRMID(drm_enc));
583583

584584
/*
@@ -610,17 +610,15 @@ static int dpu_encoder_virt_atomic_check(
610610

611611
topology = dpu_encoder_get_topology(dpu_enc, dpu_kms, adj_mode);
612612

613-
/* Reserve dynamic resources now. Indicating AtomicTest phase */
613+
/* Reserve dynamic resources now. */
614614
if (!ret) {
615615
/*
616616
* Avoid reserving resources when mode set is pending. Topology
617617
* info may not be available to complete reservation.
618618
*/
619-
if (drm_atomic_crtc_needs_modeset(crtc_state)
620-
&& dpu_enc->mode_set_complete) {
621-
ret = dpu_rm_reserve(&dpu_kms->rm, drm_enc, crtc_state,
622-
topology, true);
623-
dpu_enc->mode_set_complete = false;
619+
if (drm_atomic_crtc_needs_modeset(crtc_state)) {
620+
ret = dpu_rm_reserve(&dpu_kms->rm, global_state,
621+
drm_enc, crtc_state, topology);
624622
}
625623
}
626624

@@ -957,12 +955,13 @@ static void dpu_encoder_virt_mode_set(struct drm_encoder *drm_enc,
957955
struct drm_connector *conn = NULL, *conn_iter;
958956
struct drm_crtc *drm_crtc;
959957
struct dpu_crtc_state *cstate;
958+
struct dpu_global_state *global_state;
960959
struct msm_display_topology topology;
961960
struct dpu_hw_blk *hw_pp[MAX_CHANNELS_PER_ENC];
962961
struct dpu_hw_blk *hw_ctl[MAX_CHANNELS_PER_ENC];
963962
struct dpu_hw_blk *hw_lm[MAX_CHANNELS_PER_ENC];
964963
int num_lm, num_ctl, num_pp;
965-
int i, j, ret;
964+
int i, j;
966965

967966
if (!drm_enc) {
968967
DPU_ERROR("invalid encoder\n");
@@ -976,6 +975,12 @@ static void dpu_encoder_virt_mode_set(struct drm_encoder *drm_enc,
976975
dpu_kms = to_dpu_kms(priv->kms);
977976
connector_list = &dpu_kms->dev->mode_config.connector_list;
978977

978+
global_state = dpu_kms_get_existing_global_state(dpu_kms);
979+
if (IS_ERR_OR_NULL(global_state)) {
980+
DPU_ERROR("Failed to get global state");
981+
return;
982+
}
983+
979984
trace_dpu_enc_mode_set(DRMID(drm_enc));
980985

981986
list_for_each_entry(conn_iter, connector_list, head)
@@ -996,21 +1001,14 @@ static void dpu_encoder_virt_mode_set(struct drm_encoder *drm_enc,
9961001

9971002
topology = dpu_encoder_get_topology(dpu_enc, dpu_kms, adj_mode);
9981003

999-
/* Reserve dynamic resources now. Indicating non-AtomicTest phase */
1000-
ret = dpu_rm_reserve(&dpu_kms->rm, drm_enc, drm_crtc->state,
1001-
topology, false);
1002-
if (ret) {
1003-
DPU_ERROR_ENC(dpu_enc,
1004-
"failed to reserve hw resources, %d\n", ret);
1005-
return;
1006-
}
1007-
1008-
num_pp = dpu_rm_get_assigned_resources(&dpu_kms->rm, drm_enc->base.id,
1009-
DPU_HW_BLK_PINGPONG, hw_pp, ARRAY_SIZE(hw_pp));
1010-
num_ctl = dpu_rm_get_assigned_resources(&dpu_kms->rm, drm_enc->base.id,
1011-
DPU_HW_BLK_CTL, hw_ctl, ARRAY_SIZE(hw_ctl));
1012-
num_lm = dpu_rm_get_assigned_resources(&dpu_kms->rm, drm_enc->base.id,
1013-
DPU_HW_BLK_LM, hw_lm, ARRAY_SIZE(hw_lm));
1004+
/* Query resource that have been reserved in atomic check step. */
1005+
num_pp = dpu_rm_get_assigned_resources(&dpu_kms->rm, global_state,
1006+
drm_enc->base.id, DPU_HW_BLK_PINGPONG, hw_pp,
1007+
ARRAY_SIZE(hw_pp));
1008+
num_ctl = dpu_rm_get_assigned_resources(&dpu_kms->rm, global_state,
1009+
drm_enc->base.id, DPU_HW_BLK_CTL, hw_ctl, ARRAY_SIZE(hw_ctl));
1010+
num_lm = dpu_rm_get_assigned_resources(&dpu_kms->rm, global_state,
1011+
drm_enc->base.id, DPU_HW_BLK_LM, hw_lm, ARRAY_SIZE(hw_lm));
10141012

10151013
for (i = 0; i < MAX_CHANNELS_PER_ENC; i++)
10161014
dpu_enc->hw_pp[i] = i < num_pp ? to_dpu_hw_pingpong(hw_pp[i])
@@ -1035,21 +1033,21 @@ static void dpu_encoder_virt_mode_set(struct drm_encoder *drm_enc,
10351033
if (!dpu_enc->hw_pp[i]) {
10361034
DPU_ERROR_ENC(dpu_enc,
10371035
"no pp block assigned at idx: %d\n", i);
1038-
goto error;
1036+
return;
10391037
}
10401038

10411039
if (!hw_ctl[i]) {
10421040
DPU_ERROR_ENC(dpu_enc,
10431041
"no ctl block assigned at idx: %d\n", i);
1044-
goto error;
1042+
return;
10451043
}
10461044

10471045
phys->hw_pp = dpu_enc->hw_pp[i];
10481046
phys->hw_ctl = to_dpu_hw_ctl(hw_ctl[i]);
10491047

10501048
num_blk = dpu_rm_get_assigned_resources(&dpu_kms->rm,
1051-
drm_enc->base.id, DPU_HW_BLK_INTF, hw_blk,
1052-
ARRAY_SIZE(hw_blk));
1049+
global_state, drm_enc->base.id, DPU_HW_BLK_INTF,
1050+
hw_blk, ARRAY_SIZE(hw_blk));
10531051
for (j = 0; j < num_blk; j++) {
10541052
struct dpu_hw_intf *hw_intf;
10551053

@@ -1061,18 +1059,13 @@ static void dpu_encoder_virt_mode_set(struct drm_encoder *drm_enc,
10611059
if (!phys->hw_intf) {
10621060
DPU_ERROR_ENC(dpu_enc,
10631061
"no intf block assigned at idx: %d\n", i);
1064-
goto error;
1062+
return;
10651063
}
10661064

10671065
phys->connector = conn->state->connector;
10681066
if (phys->ops.mode_set)
10691067
phys->ops.mode_set(phys, mode, adj_mode);
10701068
}
1071-
1072-
dpu_enc->mode_set_complete = true;
1073-
1074-
error:
1075-
dpu_rm_release(&dpu_kms->rm, drm_enc);
10761069
}
10771070

10781071
static void _dpu_encoder_virt_enable_helper(struct drm_encoder *drm_enc)
@@ -1169,6 +1162,7 @@ static void dpu_encoder_virt_disable(struct drm_encoder *drm_enc)
11691162
struct dpu_encoder_virt *dpu_enc = NULL;
11701163
struct msm_drm_private *priv;
11711164
struct dpu_kms *dpu_kms;
1165+
struct dpu_global_state *global_state;
11721166
int i = 0;
11731167

11741168
if (!drm_enc) {
@@ -1187,6 +1181,7 @@ static void dpu_encoder_virt_disable(struct drm_encoder *drm_enc)
11871181

11881182
priv = drm_enc->dev->dev_private;
11891183
dpu_kms = to_dpu_kms(priv->kms);
1184+
global_state = dpu_kms_get_existing_global_state(dpu_kms);
11901185

11911186
trace_dpu_enc_disable(DRMID(drm_enc));
11921187

@@ -1216,7 +1211,7 @@ static void dpu_encoder_virt_disable(struct drm_encoder *drm_enc)
12161211

12171212
DPU_DEBUG_ENC(dpu_enc, "encoder disabled\n");
12181213

1219-
dpu_rm_release(&dpu_kms->rm, drm_enc);
1214+
dpu_rm_release(global_state, drm_enc);
12201215

12211216
mutex_unlock(&dpu_enc->enc_lock);
12221217
}

drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c

Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -228,6 +228,85 @@ static int dpu_kms_debugfs_init(struct msm_kms *kms, struct drm_minor *minor)
228228
}
229229
#endif
230230

231+
/* Global/shared object state funcs */
232+
233+
/*
234+
* This is a helper that returns the private state currently in operation.
235+
* Note that this would return the "old_state" if called in the atomic check
236+
* path, and the "new_state" after the atomic swap has been done.
237+
*/
238+
struct dpu_global_state *
239+
dpu_kms_get_existing_global_state(struct dpu_kms *dpu_kms)
240+
{
241+
return to_dpu_global_state(dpu_kms->global_state.state);
242+
}
243+
244+
/*
245+
* This acquires the modeset lock set aside for global state, creates
246+
* a new duplicated private object state.
247+
*/
248+
struct dpu_global_state *dpu_kms_get_global_state(struct drm_atomic_state *s)
249+
{
250+
struct msm_drm_private *priv = s->dev->dev_private;
251+
struct dpu_kms *dpu_kms = to_dpu_kms(priv->kms);
252+
struct drm_private_state *priv_state;
253+
int ret;
254+
255+
ret = drm_modeset_lock(&dpu_kms->global_state_lock, s->acquire_ctx);
256+
if (ret)
257+
return ERR_PTR(ret);
258+
259+
priv_state = drm_atomic_get_private_obj_state(s,
260+
&dpu_kms->global_state);
261+
if (IS_ERR(priv_state))
262+
return ERR_CAST(priv_state);
263+
264+
return to_dpu_global_state(priv_state);
265+
}
266+
267+
static struct drm_private_state *
268+
dpu_kms_global_duplicate_state(struct drm_private_obj *obj)
269+
{
270+
struct dpu_global_state *state;
271+
272+
state = kmemdup(obj->state, sizeof(*state), GFP_KERNEL);
273+
if (!state)
274+
return NULL;
275+
276+
__drm_atomic_helper_private_obj_duplicate_state(obj, &state->base);
277+
278+
return &state->base;
279+
}
280+
281+
static void dpu_kms_global_destroy_state(struct drm_private_obj *obj,
282+
struct drm_private_state *state)
283+
{
284+
struct dpu_global_state *dpu_state = to_dpu_global_state(state);
285+
286+
kfree(dpu_state);
287+
}
288+
289+
static const struct drm_private_state_funcs dpu_kms_global_state_funcs = {
290+
.atomic_duplicate_state = dpu_kms_global_duplicate_state,
291+
.atomic_destroy_state = dpu_kms_global_destroy_state,
292+
};
293+
294+
static int dpu_kms_global_obj_init(struct dpu_kms *dpu_kms)
295+
{
296+
struct dpu_global_state *state;
297+
298+
drm_modeset_lock_init(&dpu_kms->global_state_lock);
299+
300+
state = kzalloc(sizeof(*state), GFP_KERNEL);
301+
if (!state)
302+
return -ENOMEM;
303+
304+
drm_atomic_private_obj_init(dpu_kms->dev, &dpu_kms->global_state,
305+
&state->base,
306+
&dpu_kms_global_state_funcs);
307+
return 0;
308+
}
309+
231310
static int dpu_kms_enable_vblank(struct msm_kms *kms, struct drm_crtc *crtc)
232311
{
233312
return dpu_crtc_vblank(crtc, true);
@@ -770,6 +849,11 @@ static int dpu_kms_hw_init(struct msm_kms *kms)
770849

771850
dpu_kms = to_dpu_kms(kms);
772851
dev = dpu_kms->dev;
852+
853+
rc = dpu_kms_global_obj_init(dpu_kms);
854+
if (rc)
855+
return rc;
856+
773857
priv = dev->dev_private;
774858

775859
atomic_set(&dpu_kms->bandwidth_ref, 0);

drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -111,6 +111,13 @@ struct dpu_kms {
111111

112112
struct dpu_core_perf perf;
113113

114+
/*
115+
* Global private object state, Do not access directly, use
116+
* dpu_kms_global_get_state()
117+
*/
118+
struct drm_modeset_lock global_state_lock;
119+
struct drm_private_obj global_state;
120+
114121
struct dpu_rm rm;
115122
bool rm_init;
116123

@@ -139,6 +146,25 @@ struct vsync_info {
139146

140147
#define to_dpu_kms(x) container_of(x, struct dpu_kms, base)
141148

149+
#define to_dpu_global_state(x) container_of(x, struct dpu_global_state, base)
150+
151+
/* Global private object state for tracking resources that are shared across
152+
* multiple kms objects (planes/crtcs/etc).
153+
*/
154+
struct dpu_global_state {
155+
struct drm_private_state base;
156+
157+
uint32_t pingpong_to_enc_id[PINGPONG_MAX - PINGPONG_0];
158+
uint32_t mixer_to_enc_id[LM_MAX - LM_0];
159+
uint32_t ctl_to_enc_id[CTL_MAX - CTL_0];
160+
uint32_t intf_to_enc_id[INTF_MAX - INTF_0];
161+
};
162+
163+
struct dpu_global_state
164+
*dpu_kms_get_existing_global_state(struct dpu_kms *dpu_kms);
165+
struct dpu_global_state
166+
*__must_check dpu_kms_get_global_state(struct drm_atomic_state *s);
167+
142168
/**
143169
* Debugfs functions - extra helper functions for debugfs support
144170
*

0 commit comments

Comments
 (0)