Bläddra i källkod

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 <[email protected]>
Gopikrishnaiah Anandan 4 år sedan
förälder
incheckning
16c3eae807
3 ändrade filer med 52 tillägg och 13 borttagningar
  1. 40 9
      msm/sde/sde_color_processing.c
  2. 10 2
      msm/sde/sde_color_processing.h
  3. 2 2
      msm/sde/sde_crtc.c

+ 40 - 9
msm/sde/sde_color_processing.c

@@ -4708,7 +4708,7 @@ void sde_cp_crtc_disable(struct drm_crtc *drm_crtc)
 	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;
 	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);
 	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].len = 0;
 	}
-	memset(&crtc_state->cp_dirty_list, 0,
-		sizeof(crtc_state->cp_dirty_list));
-	memset(&crtc_state->cp_prop_values, 0,
-		sizeof(crtc_state->cp_prop_values));
-	crtc_state->cp_prop_cnt = 0;
+}
+
+void sde_cp_duplicate_state_info(struct drm_crtc_state *drm_old_state,
+				struct drm_crtc_state *drm_state)
+{
+	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);
+	}
 }

+ 10 - 2
msm/sde/sde_color_processing.h

@@ -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.
  * @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 */

+ 2 - 2
msm/sde/sde_crtc.c

@@ -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)
 		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);
 
 	/* 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,
 			old_cstate, cstate,
 			&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 */
 	__drm_atomic_helper_crtc_duplicate_state(crtc, &cstate->base);