disp: msm: sde: fix cp state handling

When states are duplicated ensure that payload addresses are not copied
for range overloaded properties. Allocate the memory and copy the
payload so that each state has its own heap pointer.

Change-Id: I0fb8941f69216a48f73aba9b59338ace9916e179
Signed-off-by: Gopikrishnaiah Anandan <agopik@codeaurora.org>
This commit is contained in:
Gopikrishnaiah Anandan
2020-12-21 18:01:52 -08:00
parent 9161487a45
commit 16c3eae807
3 changed files with 52 additions and 13 deletions

View File

@@ -4708,7 +4708,7 @@ void sde_cp_crtc_disable(struct drm_crtc *drm_crtc)
kfree(info); kfree(info);
} }
void sde_cp_clear_state_info(struct drm_crtc_state *state, bool free_mem) void sde_cp_clear_state_info(struct drm_crtc_state *state)
{ {
struct sde_crtc_state *crtc_state; struct sde_crtc_state *crtc_state;
int i; int i;
@@ -4722,15 +4722,46 @@ void sde_cp_clear_state_info(struct drm_crtc_state *state, bool free_mem)
} }
SDE_EVT32(SDE_EVTLOG_FUNC_ENTRY); SDE_EVT32(SDE_EVTLOG_FUNC_ENTRY);
for (i = 0; i < ARRAY_SIZE(crtc_state->cp_range_payload); i++) { for (i = 0; i < ARRAY_SIZE(crtc_state->cp_range_payload); i++) {
if (free_mem) kfree((void *)crtc_state->cp_range_payload[i].addr);
kfree((void *)crtc_state->cp_range_payload[i].addr);
crtc_state->cp_range_payload[i].addr = 0; crtc_state->cp_range_payload[i].addr = 0;
crtc_state->cp_range_payload[i].len = 0; crtc_state->cp_range_payload[i].len = 0;
} }
memset(&crtc_state->cp_dirty_list, 0, }
sizeof(crtc_state->cp_dirty_list));
memset(&crtc_state->cp_prop_values, 0, void sde_cp_duplicate_state_info(struct drm_crtc_state *drm_old_state,
sizeof(crtc_state->cp_prop_values)); struct drm_crtc_state *drm_state)
crtc_state->cp_prop_cnt = 0; {
struct sde_crtc_state *old_state, *curr_state;
u32 len, i;
if (!drm_old_state || !drm_state)
return;
old_state = to_sde_crtc_state(drm_old_state);
curr_state = to_sde_crtc_state(drm_state);
if (!old_state || !curr_state)
return;
SDE_EVT32(SDE_EVTLOG_FUNC_ENTRY);
for (i = 0; i < ARRAY_SIZE(old_state->cp_range_payload); i++) {
/* heap address copied from old state should be cleared, each state should have
* its own heap allocation.
*/
curr_state->cp_range_payload[i].addr = 0;
curr_state->cp_range_payload[i].len = 0;
if (!old_state->cp_range_payload[i].addr || !old_state->cp_range_payload[i].len)
continue;
len = old_state->cp_range_payload[i].len;
curr_state->cp_range_payload[i].addr = (u64)kmalloc(len, GFP_KERNEL);
if (!curr_state->cp_range_payload[i].addr) {
SDE_EVT32(curr_state->cp_range_payload[i].addr);
continue;
}
memcpy((u8 *)curr_state->cp_range_payload[i].addr,
(u8 *)old_state->cp_range_payload[i].addr, len);
curr_state->cp_range_payload[i].len = len;
SDE_EVT32(curr_state->cp_range_payload[i].addr,
curr_state->cp_range_payload[i].len);
}
} }

View File

@@ -319,7 +319,15 @@ void sde_cp_crtc_disable(struct drm_crtc *crtc);
/** /**
* sde_cp_clear_state_info(): clear color processing info in the state. * sde_cp_clear_state_info(): clear color processing info in the state.
* @state: Pointer to drm_crtc_state. * @state: Pointer to drm_crtc_state.
* @free_mem: Boolean indicating if owned memory should be freed.
*/ */
void sde_cp_clear_state_info(struct drm_crtc_state *state, bool free_mem); void sde_cp_clear_state_info(struct drm_crtc_state *state);
/**
* sde_cp_duplicate_state_info(): duplicate the cp state information.
* Function should be called only from sde_crtc_duplicate_state.
* @old_state: Pointer to old drm_crtc_state.
* @state: Pointer to current drm_crtc_state.
*/
void sde_cp_duplicate_state_info(struct drm_crtc_state *old_state,
struct drm_crtc_state *state);
#endif /*_SDE_COLOR_PROCESSING_H */ #endif /*_SDE_COLOR_PROCESSING_H */

View File

@@ -3606,7 +3606,7 @@ static void sde_crtc_destroy_state(struct drm_crtc *crtc,
drm_for_each_encoder_mask(enc, crtc->dev, state->encoder_mask) drm_for_each_encoder_mask(enc, crtc->dev, state->encoder_mask)
sde_rm_release(&sde_kms->rm, enc, true); sde_rm_release(&sde_kms->rm, enc, true);
sde_cp_clear_state_info(state, true); sde_cp_clear_state_info(state);
__drm_atomic_helper_crtc_destroy_state(state); __drm_atomic_helper_crtc_destroy_state(state);
/* destroy value helper */ /* destroy value helper */
@@ -4024,7 +4024,7 @@ static struct drm_crtc_state *sde_crtc_duplicate_state(struct drm_crtc *crtc)
msm_property_duplicate_state(&sde_crtc->property_info, msm_property_duplicate_state(&sde_crtc->property_info,
old_cstate, cstate, old_cstate, cstate,
&cstate->property_state, cstate->property_values); &cstate->property_state, cstate->property_values);
sde_cp_clear_state_info(&cstate->base, false); sde_cp_duplicate_state_info(&old_cstate->base, &cstate->base);
/* duplicate base helper */ /* duplicate base helper */
__drm_atomic_helper_crtc_duplicate_state(crtc, &cstate->base); __drm_atomic_helper_crtc_duplicate_state(crtc, &cstate->base);