lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite for Android: free password hash cracker in your pocket
[<prev] [next>] [thread-next>] [day] [month] [year] [list]
Date:   Mon, 11 Dec 2023 10:38:43 -0800
From:   Kuogee Hsieh <quic_khsieh@...cinc.com>
To:     <dri-devel@...ts.freedesktop.org>, <robdclark@...il.com>,
        <sean@...rly.run>, <swboyd@...omium.org>, <dianders@...omium.org>,
        <vkoul@...nel.org>, <daniel@...ll.ch>, <airlied@...il.com>,
        <agross@...nel.org>, <dmitry.baryshkov@...aro.org>,
        <andersson@...nel.org>
CC:     Kuogee Hsieh <quic_khsieh@...cinc.com>,
        <quic_abhinavk@...cinc.com>, <quic_jesszhan@...cinc.com>,
        <quic_sbillaka@...cinc.com>, <marijn.suijten@...ainline.org>,
        <freedreno@...ts.freedesktop.org>, <linux-arm-msm@...r.kernel.org>,
        <linux-kernel@...r.kernel.org>
Subject: [PATCH v3] drm/msm/dpu: improve DSC allocation

A DCE (Display Compression Engine) contains two DSC hard slice
encoders. Each DCE start with even DSC encoder index followed by
an odd DSC encoder index. Each encoder can work independently.
But Only two DSC encoders from same DCE can be paired to work
together to support merge mode. In addition, the DSC with even
index have to mapping to even pingpong index and DSC with odd
index have to mapping to odd pingpong index at its data path.
This patch improve DSC allocation mechanism with consideration
of above factors.

Changes in V3:
-- add dpu_rm_pingpong_dsc_check()
-- for pair allocation use i += 2 at for loop

Changes in V2:
    -- split _dpu_rm_reserve_dsc() into _dpu_rm_reserve_dsc_single() and
       _dpu_rm_reserve_dsc_pair()

Fixes: f2803ee91a41 ("drm/msm/disp/dpu1: Add DSC support in RM")
Signed-off-by: Kuogee Hsieh <quic_khsieh@...cinc.com>
---
 drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c | 171 ++++++++++++++++++++++++++++++---
 1 file changed, 155 insertions(+), 16 deletions(-)

diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c
index 17ecf23..43598ee 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c
@@ -470,33 +470,172 @@ static int _dpu_rm_reserve_ctls(
 	return 0;
 }
 
-static int _dpu_rm_reserve_dsc(struct dpu_rm *rm,
+static int _dpu_rm_pingpong_dsc_check(int dsc_idx,
+				      uint32_t enc_id,
+				      uint32_t *pp_to_enc_id,
+				      int pp_max,
+				      bool pair)
+{
+	int pp_idx;
+
+	/*
+	 * find the pingpong index which had been reserved
+	 * previously at layer mixer allocation
+	 */
+	for (pp_idx = 0; pp_idx < pp_max; pp_idx++) {
+		if (pp_to_enc_id[pp_idx] == enc_id)
+			break;
+	}
+
+	/*
+	 * dsc even index must map to pingpong even index
+	 * dsc odd index must map to pingpong odd index
+	 */
+	if ((dsc_idx & 0x01) != (pp_idx & 0x01))
+		return -ENAVAIL;
+
+	if (pair) {
+		/*
+		 * delete pp_idx so that same pp_id can not be paired with
+		 * next dsc_id
+		 */
+		pp_to_enc_id[pp_idx] = 0xffff;
+	}
+
+	return 0;
+
+}
+
+static int _dpu_rm_reserve_dsc_single(struct dpu_rm *rm,
 			       struct dpu_global_state *global_state,
-			       struct drm_encoder *enc,
+			       uint32_t enc_id,
 			       const struct msm_display_topology *top)
 {
-	int num_dsc = top->num_dsc;
-	int i;
+	int num_dsc = 0;
+	int i, ret;
+	int dsc_id[DSC_MAX - DSC_0];
+	uint32_t *pp_enc_id = global_state->pingpong_to_enc_id;
+	int pp_max = PINGPONG_MAX - PINGPONG_0;
 
-	/* check if DSC required are allocated or not */
-	for (i = 0; i < num_dsc; i++) {
-		if (!rm->dsc_blks[i]) {
-			DPU_ERROR("DSC %d does not exist\n", i);
-			return -EIO;
-		}
+	memset(dsc_id, 0, sizeof(dsc_id));
 
-		if (global_state->dsc_to_enc_id[i]) {
-			DPU_ERROR("DSC %d is already allocated\n", i);
-			return -EIO;
-		}
+	for (i = 0; i < ARRAY_SIZE(rm->dsc_blks) && num_dsc >= top->num_dsc; i++) {
+		if (!rm->dsc_blks[i])
+			continue;
+
+		if (global_state->dsc_to_enc_id[i])	/* used */
+			continue;
+
+		ret = _dpu_rm_pingpong_dsc_check(i, enc_id, pp_enc_id, pp_max, false);
+		if (!ret)
+			dsc_id[num_dsc++] = DSC_0 + i;	/* found, start from DSC_0 */
 	}
 
-	for (i = 0; i < num_dsc; i++)
-		global_state->dsc_to_enc_id[i] = enc->base.id;
+	if (num_dsc < top->num_dsc) {
+		DPU_ERROR("DSC allocation failed num_dsc=%d required=%d\n",
+						num_dsc, top->num_dsc);
+		return -ENAVAIL;
+	}
+
+	/* allocate dsc */
+	for (i = 0; i < top->num_dsc; i++) {
+		int id;
+
+		id = dsc_id[i];
+		if (id >= DSC_0)
+			global_state->dsc_to_enc_id[id - DSC_0] = enc_id;
+	}
 
 	return 0;
 }
 
+static int _dpu_rm_reserve_dsc_pair(struct dpu_rm *rm,
+			       struct dpu_global_state *global_state,
+			       uint32_t enc_id,
+			       const struct msm_display_topology *top)
+{
+	int num_dsc = 0;
+	int i, ret;
+	int dsc_id[DSC_MAX - DSC_0];
+	uint32_t pp_to_enc_id[PINGPONG_MAX - PINGPONG_0];
+	uint32_t *dsc_enc_id = global_state->dsc_to_enc_id;
+	int pp_max = PINGPONG_MAX - PINGPONG_0;
+
+	memset(dsc_id, 0, sizeof(dsc_id));
+
+	/* only start from even dsc index */
+	for (i = 0; i < ARRAY_SIZE(rm->dsc_blks) && num_dsc >= top->num_dsc; i += 2) {
+		if (!rm->dsc_blks[i] || !rm->dsc_blks[i + 1])
+			continue;
+
+		/* consective dsc index to be paired */
+		if (dsc_enc_id[i] || dsc_enc_id[i + 1])	/* used */
+			continue;
+
+		/* fill working copy with pingpong list */
+		memcpy(pp_to_enc_id, global_state->pingpong_to_enc_id, sizeof(pp_to_enc_id));
+
+		ret = _dpu_rm_pingpong_dsc_check(i, enc_id, pp_to_enc_id, pp_max, true);
+		if (ret)
+			continue;
+
+		ret = _dpu_rm_pingpong_dsc_check(i + 1, enc_id, pp_to_enc_id, pp_max, true);
+		if (ret)
+			continue;
+
+		/* pair found, start from DSC_0 */
+		dsc_id[num_dsc++] = DSC_0 + i;
+		dsc_id[num_dsc++] = DSC_0 + i + 1;
+	}
+
+	if (num_dsc < top->num_dsc) {
+		DPU_ERROR("DSC allocation failed num_dsc=%d required=%d\n",
+						num_dsc, top->num_dsc);
+		return -ENAVAIL;
+	}
+
+	/* allocate dsc */
+	for (i = 0; i < top->num_dsc; i++) {
+		int id;
+
+		id = dsc_id[i];
+		if (id >= DSC_0)
+			global_state->dsc_to_enc_id[id - DSC_0] = enc_id;
+	}
+
+	return 0;
+}
+
+static int _dpu_rm_reserve_dsc(struct dpu_rm *rm,
+			       struct dpu_global_state *global_state,
+			       struct drm_encoder *enc,
+			       const struct msm_display_topology *top)
+{
+	uint32_t enc_id = enc->base.id;
+
+	if (!top->num_dsc || !top->num_intf)
+		return 0;
+
+	/*
+	 * Truth:
+	 * 1) every layer mixer only connects to one pingpong
+	 * 2) no pingpong split -- which is two layer mixers shared one pingpong
+	 * 3) each DSC engine contains two dsc encoders
+	 *    -- index(0,1), index (2,3),... etc
+	 * 4) dsc pair can only happens with same DSC engine
+	 * 5) odd pingpong connect to odd dsc
+	 * 6) even pingpong connect to even dsc
+	 * 7) pair: encoder +--> pp_idx_0 --> dsc_idx_0
+			    +--> pp_idx_1 --> dsc_idx_1
+	 */
+
+	/* num_dsc should be either 1, 2 or 4 */
+	if (top->num_dsc > top->num_intf)	/* merge mode */
+		return _dpu_rm_reserve_dsc_pair(rm, global_state, enc_id, top);
+	else
+		return _dpu_rm_reserve_dsc_single(rm, global_state, enc_id, top);
+}
+
 static int _dpu_rm_make_reservation(
 		struct dpu_rm *rm,
 		struct dpu_global_state *global_state,
-- 
2.7.4

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ