Sfoglia il codice sorgente

disp: msm: sde: fix tracking of pending rsvps

Previous logic expected rsvp_nxt to always be the 2nd rsvp for
a given encoder. This does not work for releasing back-to-back
test-only reservations (with no current rsvp). If new
resources become available between the 2 test-only commits we
may end up reserving more resources than necessary. Change the
logic by adding a pending flag to the rsvp to simplify lookup
of both current and pending/next resource reservations.

Change-Id: Iefa8085f1b4c0cf49bb744dcc2deb7fb92608454
Signed-off-by: Steve Cohen <[email protected]>
Steve Cohen 4 anni fa
parent
commit
36470038e6
1 ha cambiato i file con 25 aggiunte e 44 eliminazioni
  1. 25 44
      msm/sde/sde_rm.c

+ 25 - 44
msm/sde/sde_rm.c

@@ -126,13 +126,15 @@ struct sde_rm_requirements {
  * @enc_id:	Reservations are tracked by Encoder DRM object ID.
  *		CRTCs may be connected to multiple Encoders.
  *		An encoder or connector id identifies the display path.
- * @topology	DRM<->HW topology use case
+ * @topology:	DRM<->HW topology use case
+ * @pending:	True for pending rsvp-nxt, cleared when the rsvp is committed
  */
 struct sde_rm_rsvp {
 	struct list_head list;
 	uint32_t seq;
 	uint32_t enc_id;
 	enum sde_rm_topology_name topology;
+	bool pending;
 };
 
 /**
@@ -275,9 +277,9 @@ static void _sde_rm_print_rsvps(
 	SDE_DEBUG("%d\n", stage);
 
 	list_for_each_entry(rsvp, &rm->rsvps, list) {
-		SDE_DEBUG("%d rsvp[s%ue%u] topology %d\n", stage, rsvp->seq,
-				rsvp->enc_id, rsvp->topology);
-		SDE_EVT32(stage, rsvp->seq, rsvp->enc_id, rsvp->topology);
+		SDE_DEBUG("%d rsvp%s[s%ue%u] topology %d\n", stage, rsvp->pending ? "_nxt" : "",
+				rsvp->seq, rsvp->enc_id, rsvp->topology);
+		SDE_EVT32(stage, rsvp->seq, rsvp->enc_id, rsvp->topology, rsvp->pending);
 	}
 
 	for (type = 0; type < SDE_HW_BLK_MAX; type++) {
@@ -1822,6 +1824,7 @@ static int _sde_rm_make_next_rsvp(struct sde_rm *rm, struct drm_encoder *enc,
 	rsvp->seq = ++rm->rsvp_next_seq;
 	rsvp->enc_id = enc->base.id;
 	rsvp->topology = reqs->topology->top_name;
+	rsvp->pending = true;
 	list_add_tail(&rsvp->list, &rm->rsvps);
 
 	ret = _sde_rm_make_lm_rsvp(rm, rsvp, reqs, splash_display);
@@ -2078,9 +2081,7 @@ static int _sde_rm_populate_requirements(
 	return 0;
 }
 
-static struct sde_rm_rsvp *_sde_rm_get_rsvp(
-		struct sde_rm *rm,
-		struct drm_encoder *enc)
+static struct sde_rm_rsvp *_sde_rm_get_rsvp(struct sde_rm *rm, struct drm_encoder *enc, bool nxt)
 {
 	struct sde_rm_rsvp *i;
 
@@ -2093,30 +2094,20 @@ static struct sde_rm_rsvp *_sde_rm_get_rsvp(
 		return NULL;
 
 	list_for_each_entry(i, &rm->rsvps, list)
-		if (i->enc_id == enc->base.id)
+		if (i->pending == nxt && i->enc_id == enc->base.id)
 			return i;
 
 	return NULL;
 }
 
-static struct sde_rm_rsvp *_sde_rm_get_rsvp_nxt(
-		struct sde_rm *rm,
-		struct drm_encoder *enc)
+static struct sde_rm_rsvp *_sde_rm_get_rsvp_nxt(struct sde_rm *rm, struct drm_encoder *enc)
 {
-	struct sde_rm_rsvp *i;
-
-	if (list_empty(&rm->rsvps))
-		return NULL;
-
-	list_for_each_entry(i, &rm->rsvps, list)
-		if (i->enc_id == enc->base.id)
-			break;
-
-	list_for_each_entry_continue(i, &rm->rsvps, list)
-		if (i->enc_id == enc->base.id)
-			return i;
+        return _sde_rm_get_rsvp(rm, enc, true);
+}
 
-	return NULL;
+static struct sde_rm_rsvp *_sde_rm_get_rsvp_cur(struct sde_rm *rm, struct drm_encoder *enc)
+{
+	return _sde_rm_get_rsvp(rm, enc, false);
 }
 
 static struct drm_connector *_sde_rm_get_connector(
@@ -2314,10 +2305,7 @@ void sde_rm_release(struct sde_rm *rm, struct drm_encoder *enc, bool nxt)
 
 	mutex_lock(&rm->rm_lock);
 
-	if (nxt)
-		rsvp = _sde_rm_get_rsvp_nxt(rm, enc);
-	else
-		rsvp = _sde_rm_get_rsvp(rm, enc);
+	rsvp = _sde_rm_get_rsvp(rm, enc, nxt);
 	if (!rsvp) {
 		SDE_DEBUG("failed to find rsvp for enc %d, nxt %d",
 				enc->base.id, nxt);
@@ -2355,14 +2343,11 @@ end:
 	mutex_unlock(&rm->rm_lock);
 }
 
-static int _sde_rm_commit_rsvp(
-		struct sde_rm *rm,
-		struct sde_rm_rsvp *rsvp,
+static void _sde_rm_commit_rsvp(struct sde_rm *rm, struct sde_rm_rsvp *rsvp,
 		struct drm_connector_state *conn_state)
 {
 	struct sde_rm_hw_blk *blk;
 	enum sde_hw_blk_type type;
-	int ret = 0;
 
 	/* Swap next rsvp to be the active */
 	for (type = 0; type < SDE_HW_BLK_MAX; type++) {
@@ -2377,13 +2362,9 @@ static int _sde_rm_commit_rsvp(
 		}
 	}
 
-	if (!ret) {
-		SDE_DEBUG("rsrv enc %d topology %d\n", rsvp->enc_id,
-				rsvp->topology);
-		SDE_EVT32(rsvp->enc_id, rsvp->topology);
-	}
-
-	return ret;
+	rsvp->pending = false;
+	SDE_DEBUG("rsrv enc %d topology %d\n", rsvp->enc_id, rsvp->topology);
+	SDE_EVT32(rsvp->enc_id, rsvp->topology);
 }
 
 /* call this only after rm_mutex held */
@@ -2422,7 +2403,7 @@ int sde_rm_reserve(
 	struct msm_drm_private *priv;
 	struct sde_kms *sde_kms;
 	struct msm_compression_info *comp_info;
-	int ret;
+	int ret = 0;
 
 	if (!rm || !enc || !crtc_state || !conn_state) {
 		SDE_ERROR("invalid arguments\n");
@@ -2458,7 +2439,7 @@ int sde_rm_reserve(
 
 	_sde_rm_print_rsvps(rm, SDE_RM_STAGE_BEGIN);
 
-	rsvp_cur = _sde_rm_get_rsvp(rm, enc);
+	rsvp_cur = _sde_rm_get_rsvp_cur(rm, enc);
 	rsvp_nxt = _sde_rm_get_rsvp_nxt(rm, enc);
 
 	/*
@@ -2547,7 +2528,7 @@ int sde_rm_reserve(
 
 commit_rsvp:
 	_sde_rm_release_rsvp(rm, rsvp_cur, conn_state->connector);
-	ret = _sde_rm_commit_rsvp(rm, rsvp_nxt, conn_state);
+	_sde_rm_commit_rsvp(rm, rsvp_nxt, conn_state);
 
 end:
 	kfree(comp_info);
@@ -2576,7 +2557,7 @@ int sde_rm_ext_blk_create_reserve(struct sde_rm *rm,
 
 	mutex_lock(&rm->rm_lock);
 
-	rsvp = _sde_rm_get_rsvp(rm, enc);
+	rsvp = _sde_rm_get_rsvp_cur(rm, enc);
 	if (!rsvp) {
 		rsvp = kzalloc(sizeof(*rsvp), GFP_KERNEL);
 		if (!rsvp) {
@@ -2627,7 +2608,7 @@ int sde_rm_ext_blk_destroy(struct sde_rm *rm,
 
 	mutex_lock(&rm->rm_lock);
 
-	rsvp = _sde_rm_get_rsvp(rm, enc);
+	rsvp = _sde_rm_get_rsvp_cur(rm, enc);
 	if (!rsvp) {
 		ret = -ENOENT;
 		SDE_ERROR("failed to find rsvp for enc %d\n", enc->base.id);