linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH 1/4] drm/msm/dpu: Remove unused function arguments
@ 2020-02-19 17:42 Drew Davenport
  2020-02-19 17:42 ` [PATCH 2/4] drm/msm/dpu: Refactor rm iterator Drew Davenport
                   ` (3 more replies)
  0 siblings, 4 replies; 7+ messages in thread
From: Drew Davenport @ 2020-02-19 17:42 UTC (permalink / raw)
  To: dri-devel
  Cc: Drew Davenport, Alexios Zavras, Daniel Vetter, David Airlie,
	Greg Kroah-Hartman, Rob Clark, Sean Paul, Stephen Boyd,
	Thomas Gleixner, freedreno, linux-arm-msm, linux-kernel

Several functions arguments in the resource manager are unused, so
remove them.

Signed-off-by: Drew Davenport <ddavenport@chromium.org>
---

 drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c | 37 ++++++++++----------------
 1 file changed, 14 insertions(+), 23 deletions(-)

diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c
index 23f5b1433b357..dea1dba441fe7 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c
@@ -144,8 +144,7 @@ static int _dpu_rm_hw_blk_create(
 		const struct dpu_mdss_cfg *cat,
 		void __iomem *mmio,
 		enum dpu_hw_blk_type type,
-		uint32_t id,
-		const void *hw_catalog_info)
+		uint32_t id)
 {
 	struct dpu_rm_hw_blk *blk;
 	void *hw;
@@ -223,7 +222,7 @@ int dpu_rm_init(struct dpu_rm *rm,
 		}
 
 		rc = _dpu_rm_hw_blk_create(rm, cat, mmio, DPU_HW_BLK_LM,
-				cat->mixer[i].id, &cat->mixer[i]);
+				cat->mixer[i].id);
 		if (rc) {
 			DPU_ERROR("failed: lm hw not available\n");
 			goto fail;
@@ -244,7 +243,7 @@ int dpu_rm_init(struct dpu_rm *rm,
 
 	for (i = 0; i < cat->pingpong_count; i++) {
 		rc = _dpu_rm_hw_blk_create(rm, cat, mmio, DPU_HW_BLK_PINGPONG,
-				cat->pingpong[i].id, &cat->pingpong[i]);
+				cat->pingpong[i].id);
 		if (rc) {
 			DPU_ERROR("failed: pp hw not available\n");
 			goto fail;
@@ -258,7 +257,7 @@ int dpu_rm_init(struct dpu_rm *rm,
 		}
 
 		rc = _dpu_rm_hw_blk_create(rm, cat, mmio, DPU_HW_BLK_INTF,
-				cat->intf[i].id, &cat->intf[i]);
+				cat->intf[i].id);
 		if (rc) {
 			DPU_ERROR("failed: intf hw not available\n");
 			goto fail;
@@ -267,7 +266,7 @@ int dpu_rm_init(struct dpu_rm *rm,
 
 	for (i = 0; i < cat->ctl_count; i++) {
 		rc = _dpu_rm_hw_blk_create(rm, cat, mmio, DPU_HW_BLK_CTL,
-				cat->ctl[i].id, &cat->ctl[i]);
+				cat->ctl[i].id);
 		if (rc) {
 			DPU_ERROR("failed: ctl hw not available\n");
 			goto fail;
@@ -293,7 +292,6 @@ static bool _dpu_rm_needs_split_display(const struct msm_display_topology *top)
  *	pingpong
  * @rm: dpu resource manager handle
  * @enc_id: encoder id requesting for allocation
- * @reqs: proposed use case requirements
  * @lm: proposed layer mixer, function checks if lm, and all other hardwired
  *      blocks connected to the lm (pp) is available and appropriate
  * @pp: output parameter, pingpong block attached to the layer mixer.
@@ -305,7 +303,6 @@ static bool _dpu_rm_needs_split_display(const struct msm_display_topology *top)
 static bool _dpu_rm_check_lm_and_get_connected_blks(
 		struct dpu_rm *rm,
 		uint32_t enc_id,
-		struct dpu_rm_requirements *reqs,
 		struct dpu_rm_hw_blk *lm,
 		struct dpu_rm_hw_blk **pp,
 		struct dpu_rm_hw_blk *primary_lm)
@@ -384,7 +381,7 @@ static int _dpu_rm_reserve_lms(struct dpu_rm *rm, uint32_t enc_id,
 		lm[lm_count] = iter_i.blk;
 
 		if (!_dpu_rm_check_lm_and_get_connected_blks(
-				rm, enc_id, reqs, lm[lm_count],
+				rm, enc_id, lm[lm_count],
 				&pp[lm_count], NULL))
 			continue;
 
@@ -399,7 +396,7 @@ static int _dpu_rm_reserve_lms(struct dpu_rm *rm, uint32_t enc_id,
 				continue;
 
 			if (!_dpu_rm_check_lm_and_get_connected_blks(
-					rm, enc_id, reqs, iter_j.blk,
+					rm, enc_id, iter_j.blk,
 					&pp[lm_count], iter_i.blk))
 				continue;
 
@@ -480,20 +477,19 @@ static int _dpu_rm_reserve_ctls(
 static int _dpu_rm_reserve_intf(
 		struct dpu_rm *rm,
 		uint32_t enc_id,
-		uint32_t id,
-		enum dpu_hw_blk_type type)
+		uint32_t id)
 {
 	struct dpu_rm_hw_iter iter;
 	int ret = 0;
 
 	/* Find the block entry in the rm, and note the reservation */
-	dpu_rm_init_hw_iter(&iter, 0, type);
+	dpu_rm_init_hw_iter(&iter, 0, DPU_HW_BLK_INTF);
 	while (_dpu_rm_get_hw_locked(rm, &iter)) {
 		if (iter.blk->id != id)
 			continue;
 
 		if (RESERVED_BY_OTHER(iter.blk, enc_id)) {
-			DPU_ERROR("type %d id %d already reserved\n", type, id);
+			DPU_ERROR("intf id %d already reserved\n", id);
 			return -ENAVAIL;
 		}
 
@@ -504,7 +500,7 @@ static int _dpu_rm_reserve_intf(
 
 	/* Shouldn't happen since intfs are fixed at probe */
 	if (!iter.hw) {
-		DPU_ERROR("couldn't find type %d id %d\n", type, id);
+		DPU_ERROR("couldn't find intf id %d\n", id);
 		return -EINVAL;
 	}
 
@@ -523,8 +519,7 @@ static int _dpu_rm_reserve_intf_related_hw(
 		if (hw_res->intfs[i] == INTF_MODE_NONE)
 			continue;
 		id = i + INTF_0;
-		ret = _dpu_rm_reserve_intf(rm, enc_id, id,
-				DPU_HW_BLK_INTF);
+		ret = _dpu_rm_reserve_intf(rm, enc_id, id);
 		if (ret)
 			return ret;
 	}
@@ -535,7 +530,6 @@ static int _dpu_rm_reserve_intf_related_hw(
 static int _dpu_rm_make_reservation(
 		struct dpu_rm *rm,
 		struct drm_encoder *enc,
-		struct drm_crtc_state *crtc_state,
 		struct dpu_rm_requirements *reqs)
 {
 	int ret;
@@ -560,9 +554,7 @@ static int _dpu_rm_make_reservation(
 }
 
 static int _dpu_rm_populate_requirements(
-		struct dpu_rm *rm,
 		struct drm_encoder *enc,
-		struct drm_crtc_state *crtc_state,
 		struct dpu_rm_requirements *reqs,
 		struct msm_display_topology req_topology)
 {
@@ -621,14 +613,13 @@ int dpu_rm_reserve(
 
 	mutex_lock(&rm->rm_lock);
 
-	ret = _dpu_rm_populate_requirements(rm, enc, crtc_state, &reqs,
-					    topology);
+	ret = _dpu_rm_populate_requirements(enc, &reqs, topology);
 	if (ret) {
 		DPU_ERROR("failed to populate hw requirements\n");
 		goto end;
 	}
 
-	ret = _dpu_rm_make_reservation(rm, enc, crtc_state, &reqs);
+	ret = _dpu_rm_make_reservation(rm, enc, &reqs);
 	if (ret) {
 		DPU_ERROR("failed to reserve hw resources: %d\n", ret);
 		_dpu_rm_release_reservation(rm, enc->base.id);
-- 
2.24.1


^ permalink raw reply related	[flat|nested] 7+ messages in thread

* [PATCH 2/4] drm/msm/dpu: Refactor rm iterator
  2020-02-19 17:42 [PATCH 1/4] drm/msm/dpu: Remove unused function arguments Drew Davenport
@ 2020-02-19 17:42 ` Drew Davenport
  2020-02-25 19:33   ` Stephen Boyd
  2020-02-19 17:42 ` [PATCH 3/4] drm/msm/dpu: Refactor resource manager Drew Davenport
                   ` (2 subsequent siblings)
  3 siblings, 1 reply; 7+ messages in thread
From: Drew Davenport @ 2020-02-19 17:42 UTC (permalink / raw)
  To: dri-devel
  Cc: Drew Davenport, Alexios Zavras, Allison Randal, Daniel Vetter,
	David Airlie, Fritz Koenig, Greg Kroah-Hartman,
	Jeykumar Sankaran, Kalyan Thota, Rob Clark, Sean Paul,
	Shubhashree Dhar, Stephen Boyd, Thomas Gleixner, freedreno,
	linux-arm-msm, linux-kernel, zhengbin

Make iterator implementation private, and add function to
query resources assigned to an encoder.

Signed-off-by: Drew Davenport <ddavenport@chromium.org>
---

 drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c   | 59 ++++++++-----------
 drivers/gpu/drm/msm/disp/dpu1/dpu_hw_intf.h   | 10 ++++
 .../gpu/drm/msm/disp/dpu1/dpu_hw_pingpong.h   | 10 ++++
 drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c        | 31 +++++++++-
 drivers/gpu/drm/msm/disp/dpu1/dpu_rm.h        | 47 ++-------------
 5 files changed, 76 insertions(+), 81 deletions(-)

diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
index f8ac3bf60fd60..6cadeff456f09 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
@@ -957,11 +957,11 @@ static void dpu_encoder_virt_mode_set(struct drm_encoder *drm_enc,
 	struct drm_connector *conn = NULL, *conn_iter;
 	struct drm_crtc *drm_crtc;
 	struct dpu_crtc_state *cstate;
-	struct dpu_rm_hw_iter hw_iter;
 	struct msm_display_topology topology;
-	struct dpu_hw_ctl *hw_ctl[MAX_CHANNELS_PER_ENC] = { NULL };
-	struct dpu_hw_mixer *hw_lm[MAX_CHANNELS_PER_ENC] = { NULL };
-	int num_lm = 0, num_ctl = 0;
+	struct dpu_hw_blk *hw_pp[MAX_CHANNELS_PER_ENC];
+	struct dpu_hw_blk *hw_ctl[MAX_CHANNELS_PER_ENC];
+	struct dpu_hw_blk *hw_lm[MAX_CHANNELS_PER_ENC];
+	int num_lm, num_ctl, num_pp;
 	int i, j, ret;
 
 	if (!drm_enc) {
@@ -1005,42 +1005,31 @@ static void dpu_encoder_virt_mode_set(struct drm_encoder *drm_enc,
 		return;
 	}
 
-	dpu_rm_init_hw_iter(&hw_iter, drm_enc->base.id, DPU_HW_BLK_PINGPONG);
-	for (i = 0; i < MAX_CHANNELS_PER_ENC; i++) {
-		dpu_enc->hw_pp[i] = NULL;
-		if (!dpu_rm_get_hw(&dpu_kms->rm, &hw_iter))
-			break;
-		dpu_enc->hw_pp[i] = (struct dpu_hw_pingpong *) hw_iter.hw;
-	}
-
-	dpu_rm_init_hw_iter(&hw_iter, drm_enc->base.id, DPU_HW_BLK_CTL);
-	for (i = 0; i < MAX_CHANNELS_PER_ENC; i++) {
-		if (!dpu_rm_get_hw(&dpu_kms->rm, &hw_iter))
-			break;
-		hw_ctl[i] = (struct dpu_hw_ctl *)hw_iter.hw;
-		num_ctl++;
-	}
+	num_pp = dpu_rm_get_assigned_resources(&dpu_kms->rm, drm_enc->base.id,
+		DPU_HW_BLK_PINGPONG, hw_pp, ARRAY_SIZE(hw_pp));
+	num_ctl = dpu_rm_get_assigned_resources(&dpu_kms->rm, drm_enc->base.id,
+		DPU_HW_BLK_CTL, hw_ctl, ARRAY_SIZE(hw_ctl));
+	num_lm = dpu_rm_get_assigned_resources(&dpu_kms->rm, drm_enc->base.id,
+		DPU_HW_BLK_LM, hw_lm, ARRAY_SIZE(hw_lm));
 
-	dpu_rm_init_hw_iter(&hw_iter, drm_enc->base.id, DPU_HW_BLK_LM);
-	for (i = 0; i < MAX_CHANNELS_PER_ENC; i++) {
-		if (!dpu_rm_get_hw(&dpu_kms->rm, &hw_iter))
-			break;
-		hw_lm[i] = (struct dpu_hw_mixer *)hw_iter.hw;
-		num_lm++;
-	}
+	for (i = 0; i < MAX_CHANNELS_PER_ENC; i++)
+		dpu_enc->hw_pp[i] = i < num_pp ? to_dpu_hw_pingpong(hw_pp[i])
+						: NULL;
 
 	cstate = to_dpu_crtc_state(drm_crtc->state);
 
 	for (i = 0; i < num_lm; i++) {
 		int ctl_idx = (i < num_ctl) ? i : (num_ctl-1);
 
-		cstate->mixers[i].hw_lm = hw_lm[i];
-		cstate->mixers[i].lm_ctl = hw_ctl[ctl_idx];
+		cstate->mixers[i].hw_lm = to_dpu_hw_mixer(hw_lm[i]);
+		cstate->mixers[i].lm_ctl = to_dpu_hw_ctl(hw_ctl[ctl_idx]);
 	}
 
 	cstate->num_mixers = num_lm;
 
 	for (i = 0; i < dpu_enc->num_phys_encs; i++) {
+		int num_blk;
+		struct dpu_hw_blk *hw_blk[MAX_CHANNELS_PER_ENC];
 		struct dpu_encoder_phys *phys = dpu_enc->phys_encs[i];
 
 		if (!dpu_enc->hw_pp[i]) {
@@ -1056,17 +1045,15 @@ static void dpu_encoder_virt_mode_set(struct drm_encoder *drm_enc,
 		}
 
 		phys->hw_pp = dpu_enc->hw_pp[i];
-		phys->hw_ctl = hw_ctl[i];
+		phys->hw_ctl = to_dpu_hw_ctl(hw_ctl[i]);
 
-		dpu_rm_init_hw_iter(&hw_iter, drm_enc->base.id,
-				    DPU_HW_BLK_INTF);
-		for (j = 0; j < MAX_CHANNELS_PER_ENC; j++) {
+		num_blk = dpu_rm_get_assigned_resources(&dpu_kms->rm,
+			drm_enc->base.id, DPU_HW_BLK_INTF, hw_blk,
+			ARRAY_SIZE(hw_blk));
+		for (j = 0; j < num_blk; j++) {
 			struct dpu_hw_intf *hw_intf;
 
-			if (!dpu_rm_get_hw(&dpu_kms->rm, &hw_iter))
-				break;
-
-			hw_intf = (struct dpu_hw_intf *)hw_iter.hw;
+			hw_intf = to_dpu_hw_intf(hw_blk[i]);
 			if (hw_intf->idx == phys->intf_idx)
 				phys->hw_intf = hw_intf;
 		}
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_intf.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_intf.h
index 85468981632de..0ead64d3f63d9 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_intf.h
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_intf.h
@@ -89,6 +89,16 @@ struct dpu_hw_intf {
 	struct dpu_hw_intf_ops ops;
 };
 
+/**
+ * to_dpu_hw_intf - convert base object dpu_hw_base to container
+ * @hw: Pointer to base hardware block
+ * return: Pointer to hardware block container
+ */
+static inline struct dpu_hw_intf *to_dpu_hw_intf(struct dpu_hw_blk *hw)
+{
+	return container_of(hw, struct dpu_hw_intf, base);
+}
+
 /**
  * dpu_hw_intf_init(): Initializes the intf driver for the passed
  * interface idx.
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_pingpong.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_pingpong.h
index 3d6f46b1db308..d73cb73e938b6 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_pingpong.h
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_pingpong.h
@@ -96,6 +96,16 @@ struct dpu_hw_pingpong {
 	struct dpu_hw_pingpong_ops ops;
 };
 
+/**
+ * to_dpu_hw_pingpong - convert base object dpu_hw_base to container
+ * @hw: Pointer to base hardware block
+ * return: Pointer to hardware block container
+ */
+static inline struct dpu_hw_pingpong *to_dpu_hw_pingpong(struct dpu_hw_blk *hw)
+{
+	return container_of(hw, struct dpu_hw_pingpong, base);
+}
+
 /**
  * dpu_hw_pingpong_init - initializes the pingpong driver for the passed
  *	pingpong idx.
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c
index dea1dba441fe7..779df26dc81ae 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c
@@ -40,7 +40,21 @@ struct dpu_rm_hw_blk {
 	struct dpu_hw_blk *hw;
 };
 
-void dpu_rm_init_hw_iter(
+/**
+ * struct dpu_rm_hw_iter - iterator for use with dpu_rm
+ * @hw: dpu_hw object requested, or NULL on failure
+ * @blk: dpu_rm internal block representation. Clients ignore. Used as iterator.
+ * @enc_id: DRM ID of Encoder client wishes to search for, or 0 for Any Encoder
+ * @type: Hardware Block Type client wishes to search for.
+ */
+struct dpu_rm_hw_iter {
+	void *hw;
+	struct dpu_rm_hw_blk *blk;
+	uint32_t enc_id;
+	enum dpu_hw_blk_type type;
+};
+
+static void dpu_rm_init_hw_iter(
 		struct dpu_rm_hw_iter *iter,
 		uint32_t enc_id,
 		enum dpu_hw_blk_type type)
@@ -83,7 +97,7 @@ static bool _dpu_rm_get_hw_locked(struct dpu_rm *rm, struct dpu_rm_hw_iter *i)
 	return false;
 }
 
-bool dpu_rm_get_hw(struct dpu_rm *rm, struct dpu_rm_hw_iter *i)
+static bool dpu_rm_get_hw(struct dpu_rm *rm, struct dpu_rm_hw_iter *i)
 {
 	bool ret;
 
@@ -635,3 +649,16 @@ int dpu_rm_reserve(
 
 	return ret;
 }
+
+int dpu_rm_get_assigned_resources(struct dpu_rm *rm, uint32_t enc_id,
+	enum dpu_hw_blk_type type, struct dpu_hw_blk **blks, int blks_size)
+{
+	struct dpu_rm_hw_iter hw_iter;
+	int num_blks = 0;
+
+	dpu_rm_init_hw_iter(&hw_iter, enc_id, type);
+	while (num_blks < blks_size && dpu_rm_get_hw(rm, &hw_iter))
+		blks[num_blks++] = hw_iter.blk->hw;
+
+	return num_blks;
+}
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.h
index 9c580a0170946..982b91e272275 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.h
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.h
@@ -24,26 +24,6 @@ struct dpu_rm {
 	struct mutex rm_lock;
 };
 
-/**
- *  struct dpu_rm_hw_blk - resource manager internal structure
- *	forward declaration for single iterator definition without void pointer
- */
-struct dpu_rm_hw_blk;
-
-/**
- * struct dpu_rm_hw_iter - iterator for use with dpu_rm
- * @hw: dpu_hw object requested, or NULL on failure
- * @blk: dpu_rm internal block representation. Clients ignore. Used as iterator.
- * @enc_id: DRM ID of Encoder client wishes to search for, or 0 for Any Encoder
- * @type: Hardware Block Type client wishes to search for.
- */
-struct dpu_rm_hw_iter {
-	void *hw;
-	struct dpu_rm_hw_blk *blk;
-	uint32_t enc_id;
-	enum dpu_hw_blk_type type;
-};
-
 /**
  * dpu_rm_init - Read hardware catalog and create reservation tracking objects
  *	for all HW blocks.
@@ -93,28 +73,9 @@ int dpu_rm_reserve(struct dpu_rm *rm,
 void dpu_rm_release(struct dpu_rm *rm, struct drm_encoder *enc);
 
 /**
- * dpu_rm_init_hw_iter - setup given iterator for new iteration over hw list
- *	using dpu_rm_get_hw
- * @iter: iter object to initialize
- * @enc_id: DRM ID of Encoder client wishes to search for, or 0 for Any Encoder
- * @type: Hardware Block Type client wishes to search for.
+ * Get hw resources of the given type that are assigned to this encoder.
  */
-void dpu_rm_init_hw_iter(
-		struct dpu_rm_hw_iter *iter,
-		uint32_t enc_id,
-		enum dpu_hw_blk_type type);
-/**
- * dpu_rm_get_hw - retrieve reserved hw object given encoder and hw type
- *	Meant to do a single pass through the hardware list to iteratively
- *	retrieve hardware blocks of a given type for a given encoder.
- *	Initialize an iterator object.
- *	Set hw block type of interest. Set encoder id of interest, 0 for any.
- *	Function returns first hw of type for that encoder.
- *	Subsequent calls will return the next reserved hw of that type in-order.
- *	Iterator HW pointer will be null on failure to find hw.
- * @rm: DPU Resource Manager handle
- * @iter: iterator object
- * @Return: true on match found, false on no match found
- */
-bool dpu_rm_get_hw(struct dpu_rm *rm, struct dpu_rm_hw_iter *iter);
+int dpu_rm_get_assigned_resources(struct dpu_rm *rm, uint32_t enc_id,
+	enum dpu_hw_blk_type type, struct dpu_hw_blk **blks, int blks_size);
 #endif /* __DPU_RM_H__ */
+
-- 
2.24.1


^ permalink raw reply related	[flat|nested] 7+ messages in thread

* [PATCH 3/4] drm/msm/dpu: Refactor resource manager
  2020-02-19 17:42 [PATCH 1/4] drm/msm/dpu: Remove unused function arguments Drew Davenport
  2020-02-19 17:42 ` [PATCH 2/4] drm/msm/dpu: Refactor rm iterator Drew Davenport
@ 2020-02-19 17:42 ` Drew Davenport
  2020-02-19 17:42 ` [PATCH 4/4] drm/msm/dpu: Track resources in global state Drew Davenport
  2020-02-25 19:27 ` [PATCH 1/4] drm/msm/dpu: Remove unused function arguments Stephen Boyd
  3 siblings, 0 replies; 7+ messages in thread
From: Drew Davenport @ 2020-02-19 17:42 UTC (permalink / raw)
  To: dri-devel
  Cc: Drew Davenport, Alexios Zavras, Allison Randal, Daniel Vetter,
	David Airlie, Greg Kroah-Hartman, Rob Clark, Sean Paul,
	Stephen Boyd, Thomas Gleixner, freedreno, linux-arm-msm,
	linux-kernel

Track hardware resource objects in arrays rather than
a list and remove the resource manager's iterator idiom. Separate
the mapping of hardware resources to an encoder ID into a different
array.

Use an implicit mapping between the hardware blocks' ids, which
are 1-based, and array indices in these arrays to replace iteration
with index lookups in several places.

Signed-off-by: Drew Davenport <ddavenport@chromium.org>
---

 drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c | 553 +++++++++++--------------
 drivers/gpu/drm/msm/disp/dpu1/dpu_rm.h |  22 +-
 2 files changed, 255 insertions(+), 320 deletions(-)

diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c
index 779df26dc81ae..f1483b00b7423 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c
@@ -12,8 +12,12 @@
 #include "dpu_encoder.h"
 #include "dpu_trace.h"
 
-#define RESERVED_BY_OTHER(h, r)  \
-		((h)->enc_id && (h)->enc_id != r)
+
+static inline bool reserved_by_other(uint32_t *res_map, int idx,
+				     uint32_t enc_id)
+{
+	return res_map[idx] && res_map[idx] != enc_id;
+}
 
 /**
  * struct dpu_rm_requirements - Reservation requirements parameter bundle
@@ -25,126 +29,40 @@ struct dpu_rm_requirements {
 	struct dpu_encoder_hw_resources hw_res;
 };
 
-
-/**
- * struct dpu_rm_hw_blk - hardware block tracking list member
- * @list:	List head for list of all hardware blocks tracking items
- * @id:		Hardware ID number, within it's own space, ie. LM_X
- * @enc_id:	Encoder id to which this blk is binded
- * @hw:		Pointer to the hardware register access object for this block
- */
-struct dpu_rm_hw_blk {
-	struct list_head list;
-	uint32_t id;
-	uint32_t enc_id;
-	struct dpu_hw_blk *hw;
-};
-
-/**
- * struct dpu_rm_hw_iter - iterator for use with dpu_rm
- * @hw: dpu_hw object requested, or NULL on failure
- * @blk: dpu_rm internal block representation. Clients ignore. Used as iterator.
- * @enc_id: DRM ID of Encoder client wishes to search for, or 0 for Any Encoder
- * @type: Hardware Block Type client wishes to search for.
- */
-struct dpu_rm_hw_iter {
-	void *hw;
-	struct dpu_rm_hw_blk *blk;
-	uint32_t enc_id;
-	enum dpu_hw_blk_type type;
-};
-
-static void dpu_rm_init_hw_iter(
-		struct dpu_rm_hw_iter *iter,
-		uint32_t enc_id,
-		enum dpu_hw_blk_type type)
-{
-	memset(iter, 0, sizeof(*iter));
-	iter->enc_id = enc_id;
-	iter->type = type;
-}
-
-static bool _dpu_rm_get_hw_locked(struct dpu_rm *rm, struct dpu_rm_hw_iter *i)
+int dpu_rm_destroy(struct dpu_rm *rm)
 {
-	struct list_head *blk_list;
+	int i;
 
-	if (!rm || !i || i->type >= DPU_HW_BLK_MAX) {
-		DPU_ERROR("invalid rm\n");
-		return false;
-	}
+	for (i = 0; i < ARRAY_SIZE(rm->pingpong_blks); i++) {
+		struct dpu_hw_pingpong *hw;
 
-	i->hw = NULL;
-	blk_list = &rm->hw_blks[i->type];
-
-	if (i->blk && (&i->blk->list == blk_list)) {
-		DPU_DEBUG("attempt resume iteration past last\n");
-		return false;
+		if (rm->pingpong_blks[i]) {
+			hw = to_dpu_hw_pingpong(rm->pingpong_blks[i]);
+			dpu_hw_pingpong_destroy(hw);
+		}
 	}
+	for (i = 0; i < ARRAY_SIZE(rm->mixer_blks); i++) {
+		struct dpu_hw_mixer *hw;
 
-	i->blk = list_prepare_entry(i->blk, blk_list, list);
-
-	list_for_each_entry_continue(i->blk, blk_list, list) {
-		if (i->enc_id == i->blk->enc_id) {
-			i->hw = i->blk->hw;
-			DPU_DEBUG("found type %d id %d for enc %d\n",
-					i->type, i->blk->id, i->enc_id);
-			return true;
+		if (rm->mixer_blks[i]) {
+			hw = to_dpu_hw_mixer(rm->mixer_blks[i]);
+			dpu_hw_lm_destroy(hw);
 		}
 	}
+	for (i = 0; i < ARRAY_SIZE(rm->ctl_blks); i++) {
+		struct dpu_hw_ctl *hw;
 
-	DPU_DEBUG("no match, type %d for enc %d\n", i->type, i->enc_id);
-
-	return false;
-}
-
-static bool dpu_rm_get_hw(struct dpu_rm *rm, struct dpu_rm_hw_iter *i)
-{
-	bool ret;
-
-	mutex_lock(&rm->rm_lock);
-	ret = _dpu_rm_get_hw_locked(rm, i);
-	mutex_unlock(&rm->rm_lock);
-
-	return ret;
-}
-
-static void _dpu_rm_hw_destroy(enum dpu_hw_blk_type type, void *hw)
-{
-	switch (type) {
-	case DPU_HW_BLK_LM:
-		dpu_hw_lm_destroy(hw);
-		break;
-	case DPU_HW_BLK_CTL:
-		dpu_hw_ctl_destroy(hw);
-		break;
-	case DPU_HW_BLK_PINGPONG:
-		dpu_hw_pingpong_destroy(hw);
-		break;
-	case DPU_HW_BLK_INTF:
-		dpu_hw_intf_destroy(hw);
-		break;
-	case DPU_HW_BLK_SSPP:
-		/* SSPPs are not managed by the resource manager */
-	case DPU_HW_BLK_TOP:
-		/* Top is a singleton, not managed in hw_blks list */
-	case DPU_HW_BLK_MAX:
-	default:
-		DPU_ERROR("unsupported block type %d\n", type);
-		break;
+		if (rm->ctl_blks[i]) {
+			hw = to_dpu_hw_ctl(rm->ctl_blks[i]);
+			dpu_hw_ctl_destroy(hw);
+		}
 	}
-}
+	for (i = 0; i < ARRAY_SIZE(rm->intf_blks); i++) {
+		struct dpu_hw_intf *hw;
 
-int dpu_rm_destroy(struct dpu_rm *rm)
-{
-	struct dpu_rm_hw_blk *hw_cur, *hw_nxt;
-	enum dpu_hw_blk_type type;
-
-	for (type = 0; type < DPU_HW_BLK_MAX; type++) {
-		list_for_each_entry_safe(hw_cur, hw_nxt, &rm->hw_blks[type],
-				list) {
-			list_del(&hw_cur->list);
-			_dpu_rm_hw_destroy(type, hw_cur->hw);
-			kfree(hw_cur);
+		if (rm->intf_blks[i]) {
+			hw = to_dpu_hw_intf(rm->intf_blks[i]);
+			dpu_hw_intf_destroy(hw);
 		}
 	}
 
@@ -153,65 +71,11 @@ int dpu_rm_destroy(struct dpu_rm *rm)
 	return 0;
 }
 
-static int _dpu_rm_hw_blk_create(
-		struct dpu_rm *rm,
-		const struct dpu_mdss_cfg *cat,
-		void __iomem *mmio,
-		enum dpu_hw_blk_type type,
-		uint32_t id)
-{
-	struct dpu_rm_hw_blk *blk;
-	void *hw;
-
-	switch (type) {
-	case DPU_HW_BLK_LM:
-		hw = dpu_hw_lm_init(id, mmio, cat);
-		break;
-	case DPU_HW_BLK_CTL:
-		hw = dpu_hw_ctl_init(id, mmio, cat);
-		break;
-	case DPU_HW_BLK_PINGPONG:
-		hw = dpu_hw_pingpong_init(id, mmio, cat);
-		break;
-	case DPU_HW_BLK_INTF:
-		hw = dpu_hw_intf_init(id, mmio, cat);
-		break;
-	case DPU_HW_BLK_SSPP:
-		/* SSPPs are not managed by the resource manager */
-	case DPU_HW_BLK_TOP:
-		/* Top is a singleton, not managed in hw_blks list */
-	case DPU_HW_BLK_MAX:
-	default:
-		DPU_ERROR("unsupported block type %d\n", type);
-		return -EINVAL;
-	}
-
-	if (IS_ERR_OR_NULL(hw)) {
-		DPU_ERROR("failed hw object creation: type %d, err %ld\n",
-				type, PTR_ERR(hw));
-		return -EFAULT;
-	}
-
-	blk = kzalloc(sizeof(*blk), GFP_KERNEL);
-	if (!blk) {
-		_dpu_rm_hw_destroy(type, hw);
-		return -ENOMEM;
-	}
-
-	blk->id = id;
-	blk->hw = hw;
-	blk->enc_id = 0;
-	list_add_tail(&blk->list, &rm->hw_blks[type]);
-
-	return 0;
-}
-
 int dpu_rm_init(struct dpu_rm *rm,
 		struct dpu_mdss_cfg *cat,
 		void __iomem *mmio)
 {
 	int rc, i;
-	enum dpu_hw_blk_type type;
 
 	if (!rm || !cat || !mmio) {
 		DPU_ERROR("invalid kms\n");
@@ -223,11 +87,9 @@ int dpu_rm_init(struct dpu_rm *rm,
 
 	mutex_init(&rm->rm_lock);
 
-	for (type = 0; type < DPU_HW_BLK_MAX; type++)
-		INIT_LIST_HEAD(&rm->hw_blks[type]);
-
 	/* Interrogate HW catalog and create tracking items for hw blocks */
 	for (i = 0; i < cat->mixer_count; i++) {
+		struct dpu_hw_mixer *hw;
 		const struct dpu_lm_cfg *lm = &cat->mixer[i];
 
 		if (lm->pingpong == PINGPONG_MAX) {
@@ -235,12 +97,17 @@ int dpu_rm_init(struct dpu_rm *rm,
 			continue;
 		}
 
-		rc = _dpu_rm_hw_blk_create(rm, cat, mmio, DPU_HW_BLK_LM,
-				cat->mixer[i].id);
-		if (rc) {
-			DPU_ERROR("failed: lm hw not available\n");
+		if (lm->id < LM_0 || lm->id >= LM_MAX) {
+			DPU_ERROR("skip mixer %d with invalid id\n", lm->id);
+			continue;
+		}
+		hw = dpu_hw_lm_init(lm->id, mmio, cat);
+		if (IS_ERR_OR_NULL(hw)) {
+			rc = PTR_ERR(hw);
+			DPU_ERROR("failed lm object creation: err %ld\n", rc);
 			goto fail;
 		}
+		rm->mixer_blks[lm->id - LM_0] = &hw->base;
 
 		if (!rm->lm_max_width) {
 			rm->lm_max_width = lm->sblk->maxwidth;
@@ -256,35 +123,59 @@ int dpu_rm_init(struct dpu_rm *rm,
 	}
 
 	for (i = 0; i < cat->pingpong_count; i++) {
-		rc = _dpu_rm_hw_blk_create(rm, cat, mmio, DPU_HW_BLK_PINGPONG,
-				cat->pingpong[i].id);
-		if (rc) {
-			DPU_ERROR("failed: pp hw not available\n");
+		struct dpu_hw_pingpong *hw;
+		const struct dpu_pingpong_cfg *pp = &cat->pingpong[i];
+
+		if (pp->id < PINGPONG_0 || pp->id >= PINGPONG_MAX) {
+			DPU_ERROR("skip pingpong %d with invalid id\n", pp->id);
+			continue;
+		}
+		hw = dpu_hw_pingpong_init(pp->id, mmio, cat);
+		if (IS_ERR_OR_NULL(hw)) {
+			rc = PTR_ERR(hw);
+			DPU_ERROR("failed pingpong object creation: err %ld\n",
+				rc);
 			goto fail;
 		}
+		rm->pingpong_blks[pp->id - PINGPONG_0] = &hw->base;
 	}
 
 	for (i = 0; i < cat->intf_count; i++) {
-		if (cat->intf[i].type == INTF_NONE) {
+		struct dpu_hw_intf *hw;
+		const struct dpu_intf_cfg *intf = &cat->intf[i];
+
+		if (intf->type == INTF_NONE) {
 			DPU_DEBUG("skip intf %d with type none\n", i);
 			continue;
 		}
-
-		rc = _dpu_rm_hw_blk_create(rm, cat, mmio, DPU_HW_BLK_INTF,
-				cat->intf[i].id);
-		if (rc) {
-			DPU_ERROR("failed: intf hw not available\n");
+		if (intf->id < INTF_0 || intf->id >= INTF_MAX) {
+			DPU_ERROR("skip intf %d with invalid id\n", intf->id);
+			continue;
+		}
+		hw = dpu_hw_intf_init(intf->id, mmio, cat);
+		if (IS_ERR_OR_NULL(hw)) {
+			rc = PTR_ERR(hw);
+			DPU_ERROR("failed intf object creation: err %ld\n", rc);
 			goto fail;
 		}
+		rm->intf_blks[intf->id - INTF_0] = &hw->base;
 	}
 
 	for (i = 0; i < cat->ctl_count; i++) {
-		rc = _dpu_rm_hw_blk_create(rm, cat, mmio, DPU_HW_BLK_CTL,
-				cat->ctl[i].id);
-		if (rc) {
-			DPU_ERROR("failed: ctl hw not available\n");
+		struct dpu_hw_ctl *hw;
+		const struct dpu_ctl_cfg *ctl = &cat->ctl[i];
+
+		if (ctl->id < CTL_0 || ctl->id >= CTL_MAX) {
+			DPU_ERROR("skip ctl %d with invalid id\n", ctl->id);
+			continue;
+		}
+		hw = dpu_hw_ctl_init(ctl->id, mmio, cat);
+		if (IS_ERR_OR_NULL(hw)) {
+			rc = PTR_ERR(hw);
+			DPU_ERROR("failed ctl object creation: err %ld\n", rc);
 			goto fail;
 		}
+		rm->ctl_blks[ctl->id - CTL_0] = &hw->base;
 	}
 
 	return 0;
@@ -292,7 +183,7 @@ int dpu_rm_init(struct dpu_rm *rm,
 fail:
 	dpu_rm_destroy(rm);
 
-	return rc;
+	return rc ? rc : -EFAULT;
 }
 
 static bool _dpu_rm_needs_split_display(const struct msm_display_topology *top)
@@ -300,72 +191,69 @@ static bool _dpu_rm_needs_split_display(const struct msm_display_topology *top)
 	return top->num_intf > 1;
 }
 
+/**
+ * _dpu_rm_check_lm_peer - check if a mixer is a peer of the primary
+ * @rm: dpu resource manager handle
+ * @primary_idx: index of primary mixer in rm->mixer_blks[]
+ * @peer_idx: index of other mixer in rm->mixer_blks[]
+ * @Return: true if rm->mixer_blks[peer_idx] is a peer of
+ *          rm->mixer_blks[primary_idx]
+ */
+static bool _dpu_rm_check_lm_peer(struct dpu_rm *rm, int primary_idx,
+		int peer_idx)
+{
+	const struct dpu_lm_cfg *prim_lm_cfg;
+	const struct dpu_lm_cfg *peer_cfg;
+
+	prim_lm_cfg = to_dpu_hw_mixer(rm->mixer_blks[primary_idx])->cap;
+	peer_cfg = to_dpu_hw_mixer(rm->mixer_blks[peer_idx])->cap;
+
+	if (!test_bit(peer_cfg->id, &prim_lm_cfg->lm_pair_mask)) {
+		DPU_DEBUG("lm %d not peer of lm %d\n", peer_cfg->id,
+				peer_cfg->id);
+		return false;
+	}
+	return true;
+}
+
 /**
  * _dpu_rm_check_lm_and_get_connected_blks - check if proposed layer mixer meets
  *	proposed use case requirements, incl. hardwired dependent blocks like
  *	pingpong
  * @rm: dpu resource manager handle
  * @enc_id: encoder id requesting for allocation
- * @lm: proposed layer mixer, function checks if lm, and all other hardwired
- *      blocks connected to the lm (pp) is available and appropriate
- * @pp: output parameter, pingpong block attached to the layer mixer.
- *      NULL if pp was not available, or not matching requirements.
- * @primary_lm: if non-null, this function check if lm is compatible primary_lm
- *              as well as satisfying all other requirements
+ * @lm_idx: index of proposed layer mixer in rm->mixer_blks[], function checks
+ *      if lm, and all other hardwired blocks connected to the lm (pp) is
+ *      available and appropriate
+ * @pp_idx: output parameter, index of pingpong block attached to the layer
+ *      mixer in rm->pongpong_blks[].
  * @Return: true if lm matches all requirements, false otherwise
  */
-static bool _dpu_rm_check_lm_and_get_connected_blks(
-		struct dpu_rm *rm,
-		uint32_t enc_id,
-		struct dpu_rm_hw_blk *lm,
-		struct dpu_rm_hw_blk **pp,
-		struct dpu_rm_hw_blk *primary_lm)
+static bool _dpu_rm_check_lm_and_get_connected_blks(struct dpu_rm *rm,
+		uint32_t enc_id, int lm_idx, int *pp_idx)
 {
-	const struct dpu_lm_cfg *lm_cfg = to_dpu_hw_mixer(lm->hw)->cap;
-	struct dpu_rm_hw_iter iter;
-
-	*pp = NULL;
-
-	DPU_DEBUG("check lm %d pp %d\n",
-			   lm_cfg->id, lm_cfg->pingpong);
-
-	/* Check if this layer mixer is a peer of the proposed primary LM */
-	if (primary_lm) {
-		const struct dpu_lm_cfg *prim_lm_cfg =
-				to_dpu_hw_mixer(primary_lm->hw)->cap;
-
-		if (!test_bit(lm_cfg->id, &prim_lm_cfg->lm_pair_mask)) {
-			DPU_DEBUG("lm %d not peer of lm %d\n", lm_cfg->id,
-					prim_lm_cfg->id);
-			return false;
-		}
-	}
+	const struct dpu_lm_cfg *lm_cfg;
+	int idx;
 
 	/* Already reserved? */
-	if (RESERVED_BY_OTHER(lm, enc_id)) {
-		DPU_DEBUG("lm %d already reserved\n", lm_cfg->id);
+	if (reserved_by_other(rm->mixer_to_enc_id, lm_idx, enc_id)) {
+		DPU_DEBUG("lm %d already reserved\n", lm_idx + LM_0);
 		return false;
 	}
 
-	dpu_rm_init_hw_iter(&iter, 0, DPU_HW_BLK_PINGPONG);
-	while (_dpu_rm_get_hw_locked(rm, &iter)) {
-		if (iter.blk->id == lm_cfg->pingpong) {
-			*pp = iter.blk;
-			break;
-		}
-	}
-
-	if (!*pp) {
+	lm_cfg = to_dpu_hw_mixer(rm->mixer_blks[lm_idx])->cap;
+	idx = lm_cfg->pingpong - PINGPONG_0;
+	if (idx < 0 || idx >= ARRAY_SIZE(rm->pingpong_blks)) {
 		DPU_ERROR("failed to get pp on lm %d\n", lm_cfg->pingpong);
 		return false;
 	}
 
-	if (RESERVED_BY_OTHER(*pp, enc_id)) {
-		DPU_DEBUG("lm %d pp %d already reserved\n", lm->id,
-				(*pp)->id);
+	if (reserved_by_other(rm->pingpong_to_enc_id, idx, enc_id)) {
+		DPU_DEBUG("lm %d pp %d already reserved\n", lm_cfg->id,
+				lm_cfg->pingpong);
 		return false;
 	}
-
+	*pp_idx = idx;
 	return true;
 }
 
@@ -373,11 +261,9 @@ static int _dpu_rm_reserve_lms(struct dpu_rm *rm, uint32_t enc_id,
 			       struct dpu_rm_requirements *reqs)
 
 {
-	struct dpu_rm_hw_blk *lm[MAX_BLOCKS];
-	struct dpu_rm_hw_blk *pp[MAX_BLOCKS];
-	struct dpu_rm_hw_iter iter_i, iter_j;
-	int lm_count = 0;
-	int i, rc = 0;
+	int lm_idx[MAX_BLOCKS];
+	int pp_idx[MAX_BLOCKS];
+	int i, j, lm_count = 0;
 
 	if (!reqs->topology.num_lm) {
 		DPU_ERROR("invalid number of lm: %d\n", reqs->topology.num_lm);
@@ -385,36 +271,39 @@ static int _dpu_rm_reserve_lms(struct dpu_rm *rm, uint32_t enc_id,
 	}
 
 	/* Find a primary mixer */
-	dpu_rm_init_hw_iter(&iter_i, 0, DPU_HW_BLK_LM);
-	while (lm_count != reqs->topology.num_lm &&
-			_dpu_rm_get_hw_locked(rm, &iter_i)) {
-		memset(&lm, 0, sizeof(lm));
-		memset(&pp, 0, sizeof(pp));
+	for (i = 0; i < ARRAY_SIZE(rm->mixer_blks) &&
+			lm_count < reqs->topology.num_lm; i++) {
+		if (!rm->mixer_blks[i])
+			continue;
 
 		lm_count = 0;
-		lm[lm_count] = iter_i.blk;
+		lm_idx[lm_count] = i;
 
 		if (!_dpu_rm_check_lm_and_get_connected_blks(
-				rm, enc_id, lm[lm_count],
-				&pp[lm_count], NULL))
+				rm, enc_id, i, &pp_idx[lm_count])) {
 			continue;
+		}
 
 		++lm_count;
 
 		/* Valid primary mixer found, find matching peers */
-		dpu_rm_init_hw_iter(&iter_j, 0, DPU_HW_BLK_LM);
+		for (j = i + 1; j < ARRAY_SIZE(rm->mixer_blks) &&
+				lm_count < reqs->topology.num_lm; j++) {
+			if (!rm->mixer_blks[j])
+				continue;
 
-		while (lm_count != reqs->topology.num_lm &&
-				_dpu_rm_get_hw_locked(rm, &iter_j)) {
-			if (iter_i.blk == iter_j.blk)
+			if (!_dpu_rm_check_lm_peer(rm, i, j)) {
+				DPU_DEBUG("lm %d not peer of lm %d\n", LM_0 + j,
+						LM_0 + i);
 				continue;
+			}
 
 			if (!_dpu_rm_check_lm_and_get_connected_blks(
-					rm, enc_id, iter_j.blk,
-					&pp[lm_count], iter_i.blk))
+					rm, enc_id, j, &pp_idx[lm_count])) {
 				continue;
+			}
 
-			lm[lm_count] = iter_j.blk;
+			lm_idx[lm_count] = j;
 			++lm_count;
 		}
 	}
@@ -424,17 +313,15 @@ static int _dpu_rm_reserve_lms(struct dpu_rm *rm, uint32_t enc_id,
 		return -ENAVAIL;
 	}
 
-	for (i = 0; i < ARRAY_SIZE(lm); i++) {
-		if (!lm[i])
-			break;
-
-		lm[i]->enc_id = enc_id;
-		pp[i]->enc_id = enc_id;
+	for (i = 0; i < lm_count; i++) {
+		rm->mixer_to_enc_id[lm_idx[i]] = enc_id;
+		rm->pingpong_to_enc_id[pp_idx[i]] = enc_id;
 
-		trace_dpu_rm_reserve_lms(lm[i]->id, enc_id, pp[i]->id);
+		trace_dpu_rm_reserve_lms(lm_idx[i] + LM_0, enc_id,
+					 pp_idx[i] + PINGPONG_0);
 	}
 
-	return rc;
+	return 0;
 }
 
 static int _dpu_rm_reserve_ctls(
@@ -442,47 +329,48 @@ static int _dpu_rm_reserve_ctls(
 		uint32_t enc_id,
 		const struct msm_display_topology *top)
 {
-	struct dpu_rm_hw_blk *ctls[MAX_BLOCKS];
-	struct dpu_rm_hw_iter iter;
-	int i = 0, num_ctls = 0;
-	bool needs_split_display = false;
-
-	memset(&ctls, 0, sizeof(ctls));
+	int ctl_idx[MAX_BLOCKS];
+	int i = 0, j, num_ctls;
+	bool needs_split_display;
 
 	/* each hw_intf needs its own hw_ctrl to program its control path */
 	num_ctls = top->num_intf;
 
 	needs_split_display = _dpu_rm_needs_split_display(top);
 
-	dpu_rm_init_hw_iter(&iter, 0, DPU_HW_BLK_CTL);
-	while (_dpu_rm_get_hw_locked(rm, &iter)) {
-		const struct dpu_hw_ctl *ctl = to_dpu_hw_ctl(iter.blk->hw);
-		unsigned long features = ctl->caps->features;
+	for (j = 0; j < ARRAY_SIZE(rm->ctl_blks); j++) {
+		const struct dpu_hw_ctl *ctl;
+		unsigned long features;
 		bool has_split_display;
 
-		if (RESERVED_BY_OTHER(iter.blk, enc_id))
+		if (!rm->ctl_blks[j])
+			continue;
+		if (reserved_by_other(rm->ctl_to_enc_id, j, enc_id))
 			continue;
 
+		ctl = to_dpu_hw_ctl(rm->ctl_blks[j]);
+		features = ctl->caps->features;
 		has_split_display = BIT(DPU_CTL_SPLIT_DISPLAY) & features;
 
-		DPU_DEBUG("ctl %d caps 0x%lX\n", iter.blk->id, features);
+		DPU_DEBUG("ctl %d caps 0x%lX\n", rm->ctl_blks[j]->id, features);
 
 		if (needs_split_display != has_split_display)
 			continue;
 
-		ctls[i] = iter.blk;
-		DPU_DEBUG("ctl %d match\n", iter.blk->id);
+		ctl_idx[i] = j;
+		DPU_DEBUG("ctl %d match\n", j + CTL_0);
 
 		if (++i == num_ctls)
 			break;
+
 	}
 
 	if (i != num_ctls)
 		return -ENAVAIL;
 
-	for (i = 0; i < ARRAY_SIZE(ctls) && i < num_ctls; i++) {
-		ctls[i]->enc_id = enc_id;
-		trace_dpu_rm_reserve_ctls(ctls[i]->id, enc_id);
+	for (i = 0; i < ARRAY_SIZE(ctl_idx) && i < num_ctls; i++) {
+		rm->ctl_to_enc_id[ctl_idx[i]] = enc_id;
+		trace_dpu_rm_reserve_ctls(i + CTL_0, enc_id);
 	}
 
 	return 0;
@@ -493,32 +381,20 @@ static int _dpu_rm_reserve_intf(
 		uint32_t enc_id,
 		uint32_t id)
 {
-	struct dpu_rm_hw_iter iter;
-	int ret = 0;
-
-	/* Find the block entry in the rm, and note the reservation */
-	dpu_rm_init_hw_iter(&iter, 0, DPU_HW_BLK_INTF);
-	while (_dpu_rm_get_hw_locked(rm, &iter)) {
-		if (iter.blk->id != id)
-			continue;
-
-		if (RESERVED_BY_OTHER(iter.blk, enc_id)) {
-			DPU_ERROR("intf id %d already reserved\n", id);
-			return -ENAVAIL;
-		}
+	int idx = id - INTF_0;
 
-		iter.blk->enc_id = enc_id;
-		trace_dpu_rm_reserve_intf(iter.blk->id, enc_id);
-		break;
-	}
-
-	/* Shouldn't happen since intfs are fixed at probe */
-	if (!iter.hw) {
+	if (!rm->intf_blks[idx]) {
 		DPU_ERROR("couldn't find intf id %d\n", id);
 		return -EINVAL;
 	}
 
-	return ret;
+	if (reserved_by_other(rm->intf_to_enc_id, idx, enc_id)) {
+		DPU_ERROR("intf id %d already reserved\n", id);
+		return -ENAVAIL;
+	}
+
+	rm->intf_to_enc_id[idx] = enc_id;
+	return 0;
 }
 
 static int _dpu_rm_reserve_intf_related_hw(
@@ -583,22 +459,29 @@ static int _dpu_rm_populate_requirements(
 	return 0;
 }
 
-static void _dpu_rm_release_reservation(struct dpu_rm *rm, uint32_t enc_id)
+static void _dpu_rm_clear_mapping(uint32_t *res_mapping, int cnt,
+				  uint32_t enc_id)
 {
-	struct dpu_rm_hw_blk *blk;
-	enum dpu_hw_blk_type type;
-
-	for (type = 0; type < DPU_HW_BLK_MAX; type++) {
-		list_for_each_entry(blk, &rm->hw_blks[type], list) {
-			if (blk->enc_id == enc_id) {
-				blk->enc_id = 0;
-				DPU_DEBUG("rel enc %d %d %d\n", enc_id,
-					  type, blk->id);
-			}
-		}
+	int i;
+
+	for (i = 0; i < cnt; i++) {
+		if (res_mapping[i] == enc_id)
+			res_mapping[i] = 0;
 	}
 }
 
+static void _dpu_rm_release_reservation(struct dpu_rm *rm, uint32_t enc_id)
+{
+	_dpu_rm_clear_mapping(rm->pingpong_to_enc_id,
+		ARRAY_SIZE(rm->pingpong_to_enc_id), enc_id);
+	_dpu_rm_clear_mapping(rm->mixer_to_enc_id,
+		ARRAY_SIZE(rm->mixer_to_enc_id), enc_id);
+	_dpu_rm_clear_mapping(rm->ctl_to_enc_id,
+		ARRAY_SIZE(rm->ctl_to_enc_id), enc_id);
+	_dpu_rm_clear_mapping(rm->intf_to_enc_id,
+		ARRAY_SIZE(rm->intf_to_enc_id), enc_id);
+}
+
 void dpu_rm_release(struct dpu_rm *rm, struct drm_encoder *enc)
 {
 	mutex_lock(&rm->rm_lock);
@@ -653,12 +536,48 @@ int dpu_rm_reserve(
 int dpu_rm_get_assigned_resources(struct dpu_rm *rm, uint32_t enc_id,
 	enum dpu_hw_blk_type type, struct dpu_hw_blk **blks, int blks_size)
 {
-	struct dpu_rm_hw_iter hw_iter;
-	int num_blks = 0;
+	struct dpu_hw_blk **hw_blks;
+	uint32_t *hw_to_enc_id;
+	int i, num_blks, max_blks;
+
+	switch (type) {
+	case DPU_HW_BLK_PINGPONG:
+		hw_blks = rm->pingpong_blks;
+		hw_to_enc_id = rm->pingpong_to_enc_id;
+		max_blks = ARRAY_SIZE(rm->pingpong_blks);
+		break;
+	case DPU_HW_BLK_LM:
+		hw_blks = rm->mixer_blks;
+		hw_to_enc_id = rm->mixer_to_enc_id;
+		max_blks = ARRAY_SIZE(rm->mixer_blks);
+		break;
+	case DPU_HW_BLK_CTL:
+		hw_blks = rm->ctl_blks;
+		hw_to_enc_id = rm->ctl_to_enc_id;
+		max_blks = ARRAY_SIZE(rm->ctl_blks);
+		break;
+	case DPU_HW_BLK_INTF:
+		hw_blks = rm->intf_blks;
+		hw_to_enc_id = rm->intf_to_enc_id;
+		max_blks = ARRAY_SIZE(rm->intf_blks);
+		break;
+	default:
+		DPU_ERROR("blk type %d not managed by rm\n", type);
+		return 0;
+	}
 
-	dpu_rm_init_hw_iter(&hw_iter, enc_id, type);
-	while (num_blks < blks_size && dpu_rm_get_hw(rm, &hw_iter))
-		blks[num_blks++] = hw_iter.blk->hw;
+	num_blks = 0;
+	for (i = 0; i < max_blks; i++) {
+		if (hw_to_enc_id[i] != enc_id)
+			continue;
+
+		if (num_blks == blks_size) {
+			DPU_ERROR("More than %d resources assigned to enc %d\n",
+				  blks_size, enc_id);
+			break;
+		}
+		blks[num_blks++] = hw_blks[i];
+	}
 
 	return num_blks;
 }
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.h
index 982b91e272275..9c8a436ba6cc1 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.h
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.h
@@ -11,15 +11,31 @@
 #include "msm_kms.h"
 #include "dpu_hw_top.h"
 
+
 /**
  * struct dpu_rm - DPU dynamic hardware resource manager
- * @hw_blks: array of lists of hardware resources present in the system, one
- *	list per type of hardware block
+ * @pingpong_blks: array of pingpong hardware resources
+ * @mixer_blks: array of layer mixer hardware resources
+ * @ctl_blks: array of ctl hardware resources
+ * @intf_blks: array of intf hardware resources
+ * @pingpong_to_enc_id: mapping of pingpong hardware resources to an encoder ID
+ * @mixer_to_enc_id: mapping of mixer hardware resources to an encoder ID
+ * @ctl_to_enc_id: mapping of ctl hardware resources to an encoder ID
+ * @intf_to_enc_id: mapping of intf hardware resources to an encoder ID
  * @lm_max_width: cached layer mixer maximum width
  * @rm_lock: resource manager mutex
  */
 struct dpu_rm {
-	struct list_head hw_blks[DPU_HW_BLK_MAX];
+	struct dpu_hw_blk *pingpong_blks[PINGPONG_MAX - PINGPONG_0];
+	struct dpu_hw_blk *mixer_blks[LM_MAX - LM_0];
+	struct dpu_hw_blk *ctl_blks[CTL_MAX - CTL_0];
+	struct dpu_hw_blk *intf_blks[INTF_MAX - INTF_0];
+
+	uint32_t pingpong_to_enc_id[PINGPONG_MAX - PINGPONG_0];
+	uint32_t mixer_to_enc_id[LM_MAX - LM_0];
+	uint32_t ctl_to_enc_id[CTL_MAX - CTL_0];
+	uint32_t intf_to_enc_id[INTF_MAX - INTF_0];
+
 	uint32_t lm_max_width;
 	struct mutex rm_lock;
 };
-- 
2.24.1


^ permalink raw reply related	[flat|nested] 7+ messages in thread

* [PATCH 4/4] drm/msm/dpu: Track resources in global state
  2020-02-19 17:42 [PATCH 1/4] drm/msm/dpu: Remove unused function arguments Drew Davenport
  2020-02-19 17:42 ` [PATCH 2/4] drm/msm/dpu: Refactor rm iterator Drew Davenport
  2020-02-19 17:42 ` [PATCH 3/4] drm/msm/dpu: Refactor resource manager Drew Davenport
@ 2020-02-19 17:42 ` Drew Davenport
  2020-02-25 19:27 ` [PATCH 1/4] drm/msm/dpu: Remove unused function arguments Stephen Boyd
  3 siblings, 0 replies; 7+ messages in thread
From: Drew Davenport @ 2020-02-19 17:42 UTC (permalink / raw)
  To: dri-devel
  Cc: Drew Davenport, Alexios Zavras, Allison Randal, Daniel Vetter,
	David Airlie, Fritz Koenig, Greg Kroah-Hartman, Jani Nikula,
	Jeykumar Sankaran, Jordan Crouse, Kalyan Thota, Rob Clark,
	Sam Ravnborg, Sean Paul, Stephen Boyd, Thomas Gleixner,
	freedreno, linux-arm-msm, linux-kernel, zhengbin

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 <ddavenport@chromium.org>
---

 drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c |  65 +++++------
 drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c     |  84 ++++++++++++++
 drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h     |  26 +++++
 drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c      | 121 ++++++++++----------
 drivers/gpu/drm/msm/disp/dpu1/dpu_rm.h      |  22 ++--
 5 files changed, 207 insertions(+), 111 deletions(-)

diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
index 6cadeff456f09..5afde2e7fef08 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
@@ -164,7 +164,6 @@ enum dpu_enc_rc_states {
  *				clks and resources after IDLE_TIMEOUT time.
  * @vsync_event_work:		worker to handle vsync event for autorefresh
  * @topology:                   topology of the display
- * @mode_set_complete:          flag to indicate modeset completion
  * @idle_timeout:		idle timeout duration in milliseconds
  */
 struct dpu_encoder_virt {
@@ -202,7 +201,6 @@ struct dpu_encoder_virt {
 	struct delayed_work delayed_off_work;
 	struct kthread_work vsync_event_work;
 	struct msm_display_topology topology;
-	bool mode_set_complete;
 
 	u32 idle_timeout;
 };
@@ -563,6 +561,7 @@ static int dpu_encoder_virt_atomic_check(
 	const struct drm_display_mode *mode;
 	struct drm_display_mode *adj_mode;
 	struct msm_display_topology topology;
+	struct dpu_global_state *global_state;
 	int i = 0;
 	int ret = 0;
 
@@ -579,6 +578,7 @@ static int dpu_encoder_virt_atomic_check(
 	dpu_kms = to_dpu_kms(priv->kms);
 	mode = &crtc_state->mode;
 	adj_mode = &crtc_state->adjusted_mode;
+	global_state = dpu_kms_get_existing_global_state(dpu_kms);
 	trace_dpu_enc_atomic_check(DRMID(drm_enc));
 
 	/*
@@ -610,17 +610,15 @@ static int dpu_encoder_virt_atomic_check(
 
 	topology = dpu_encoder_get_topology(dpu_enc, dpu_kms, adj_mode);
 
-	/* Reserve dynamic resources now. Indicating AtomicTest phase */
+	/* Reserve dynamic resources now. */
 	if (!ret) {
 		/*
 		 * Avoid reserving resources when mode set is pending. Topology
 		 * info may not be available to complete reservation.
 		 */
-		if (drm_atomic_crtc_needs_modeset(crtc_state)
-				&& dpu_enc->mode_set_complete) {
-			ret = dpu_rm_reserve(&dpu_kms->rm, drm_enc, crtc_state,
-					     topology, true);
-			dpu_enc->mode_set_complete = false;
+		if (drm_atomic_crtc_needs_modeset(crtc_state)) {
+			ret = dpu_rm_reserve(&dpu_kms->rm, global_state,
+					drm_enc, crtc_state, topology);
 		}
 	}
 
@@ -957,12 +955,13 @@ static void dpu_encoder_virt_mode_set(struct drm_encoder *drm_enc,
 	struct drm_connector *conn = NULL, *conn_iter;
 	struct drm_crtc *drm_crtc;
 	struct dpu_crtc_state *cstate;
+	struct dpu_global_state *global_state;
 	struct msm_display_topology topology;
 	struct dpu_hw_blk *hw_pp[MAX_CHANNELS_PER_ENC];
 	struct dpu_hw_blk *hw_ctl[MAX_CHANNELS_PER_ENC];
 	struct dpu_hw_blk *hw_lm[MAX_CHANNELS_PER_ENC];
 	int num_lm, num_ctl, num_pp;
-	int i, j, ret;
+	int i, j;
 
 	if (!drm_enc) {
 		DPU_ERROR("invalid encoder\n");
@@ -976,6 +975,12 @@ static void dpu_encoder_virt_mode_set(struct drm_encoder *drm_enc,
 	dpu_kms = to_dpu_kms(priv->kms);
 	connector_list = &dpu_kms->dev->mode_config.connector_list;
 
+	global_state = dpu_kms_get_existing_global_state(dpu_kms);
+	if (IS_ERR_OR_NULL(global_state)) {
+		DPU_ERROR("Failed to get global state");
+		return;
+	}
+
 	trace_dpu_enc_mode_set(DRMID(drm_enc));
 
 	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,
 
 	topology = dpu_encoder_get_topology(dpu_enc, dpu_kms, adj_mode);
 
-	/* Reserve dynamic resources now. Indicating non-AtomicTest phase */
-	ret = dpu_rm_reserve(&dpu_kms->rm, drm_enc, drm_crtc->state,
-			     topology, false);
-	if (ret) {
-		DPU_ERROR_ENC(dpu_enc,
-				"failed to reserve hw resources, %d\n", ret);
-		return;
-	}
-
-	num_pp = dpu_rm_get_assigned_resources(&dpu_kms->rm, drm_enc->base.id,
-		DPU_HW_BLK_PINGPONG, hw_pp, ARRAY_SIZE(hw_pp));
-	num_ctl = dpu_rm_get_assigned_resources(&dpu_kms->rm, drm_enc->base.id,
-		DPU_HW_BLK_CTL, hw_ctl, ARRAY_SIZE(hw_ctl));
-	num_lm = dpu_rm_get_assigned_resources(&dpu_kms->rm, drm_enc->base.id,
-		DPU_HW_BLK_LM, hw_lm, ARRAY_SIZE(hw_lm));
+	/* Query resource that have been reserved in atomic check step. */
+	num_pp = dpu_rm_get_assigned_resources(&dpu_kms->rm, global_state,
+		drm_enc->base.id, DPU_HW_BLK_PINGPONG, hw_pp,
+		ARRAY_SIZE(hw_pp));
+	num_ctl = dpu_rm_get_assigned_resources(&dpu_kms->rm, global_state,
+		drm_enc->base.id, DPU_HW_BLK_CTL, hw_ctl, ARRAY_SIZE(hw_ctl));
+	num_lm = dpu_rm_get_assigned_resources(&dpu_kms->rm, global_state,
+		drm_enc->base.id, DPU_HW_BLK_LM, hw_lm, ARRAY_SIZE(hw_lm));
 
 	for (i = 0; i < MAX_CHANNELS_PER_ENC; i++)
 		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,
 		if (!dpu_enc->hw_pp[i]) {
 			DPU_ERROR_ENC(dpu_enc,
 				"no pp block assigned at idx: %d\n", i);
-			goto error;
+			return;
 		}
 
 		if (!hw_ctl[i]) {
 			DPU_ERROR_ENC(dpu_enc,
 				"no ctl block assigned at idx: %d\n", i);
-			goto error;
+			return;
 		}
 
 		phys->hw_pp = dpu_enc->hw_pp[i];
 		phys->hw_ctl = to_dpu_hw_ctl(hw_ctl[i]);
 
 		num_blk = dpu_rm_get_assigned_resources(&dpu_kms->rm,
-			drm_enc->base.id, DPU_HW_BLK_INTF, hw_blk,
-			ARRAY_SIZE(hw_blk));
+			global_state, drm_enc->base.id, DPU_HW_BLK_INTF,
+			hw_blk, ARRAY_SIZE(hw_blk));
 		for (j = 0; j < num_blk; j++) {
 			struct dpu_hw_intf *hw_intf;
 
@@ -1061,18 +1059,13 @@ static void dpu_encoder_virt_mode_set(struct drm_encoder *drm_enc,
 		if (!phys->hw_intf) {
 			DPU_ERROR_ENC(dpu_enc,
 				      "no intf block assigned at idx: %d\n", i);
-				goto error;
+			return;
 		}
 
 		phys->connector = conn->state->connector;
 		if (phys->ops.mode_set)
 			phys->ops.mode_set(phys, mode, adj_mode);
 	}
-
-	dpu_enc->mode_set_complete = true;
-
-error:
-	dpu_rm_release(&dpu_kms->rm, drm_enc);
 }
 
 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)
 	struct dpu_encoder_virt *dpu_enc = NULL;
 	struct msm_drm_private *priv;
 	struct dpu_kms *dpu_kms;
+	struct dpu_global_state *global_state;
 	int i = 0;
 
 	if (!drm_enc) {
@@ -1187,6 +1181,7 @@ static void dpu_encoder_virt_disable(struct drm_encoder *drm_enc)
 
 	priv = drm_enc->dev->dev_private;
 	dpu_kms = to_dpu_kms(priv->kms);
+	global_state = dpu_kms_get_existing_global_state(dpu_kms);
 
 	trace_dpu_enc_disable(DRMID(drm_enc));
 
@@ -1216,7 +1211,7 @@ static void dpu_encoder_virt_disable(struct drm_encoder *drm_enc)
 
 	DPU_DEBUG_ENC(dpu_enc, "encoder disabled\n");
 
-	dpu_rm_release(&dpu_kms->rm, drm_enc);
+	dpu_rm_release(global_state, drm_enc);
 
 	mutex_unlock(&dpu_enc->enc_lock);
 }
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c
index cb08fafb1dc14..59d42ff9da645 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c
@@ -228,6 +228,85 @@ static int dpu_kms_debugfs_init(struct msm_kms *kms, struct drm_minor *minor)
 }
 #endif
 
+/* Global/shared object state funcs */
+
+/*
+ * This is a helper that returns the private state currently in operation.
+ * Note that this would return the "old_state" if called in the atomic check
+ * path, and the "new_state" after the atomic swap has been done.
+ */
+struct dpu_global_state *
+dpu_kms_get_existing_global_state(struct dpu_kms *dpu_kms)
+{
+	return to_dpu_global_state(dpu_kms->global_state.state);
+}
+
+/*
+ * This acquires the modeset lock set aside for global state, creates
+ * a new duplicated private object state.
+ */
+struct dpu_global_state *dpu_kms_get_global_state(struct drm_atomic_state *s)
+{
+	struct msm_drm_private *priv = s->dev->dev_private;
+	struct dpu_kms *dpu_kms = to_dpu_kms(priv->kms);
+	struct drm_private_state *priv_state;
+	int ret;
+
+	ret = drm_modeset_lock(&dpu_kms->global_state_lock, s->acquire_ctx);
+	if (ret)
+		return ERR_PTR(ret);
+
+	priv_state = drm_atomic_get_private_obj_state(s,
+						&dpu_kms->global_state);
+	if (IS_ERR(priv_state))
+		return ERR_CAST(priv_state);
+
+	return to_dpu_global_state(priv_state);
+}
+
+static struct drm_private_state *
+dpu_kms_global_duplicate_state(struct drm_private_obj *obj)
+{
+	struct dpu_global_state *state;
+
+	state = kmemdup(obj->state, sizeof(*state), GFP_KERNEL);
+	if (!state)
+		return NULL;
+
+	__drm_atomic_helper_private_obj_duplicate_state(obj, &state->base);
+
+	return &state->base;
+}
+
+static void dpu_kms_global_destroy_state(struct drm_private_obj *obj,
+				      struct drm_private_state *state)
+{
+	struct dpu_global_state *dpu_state = to_dpu_global_state(state);
+
+	kfree(dpu_state);
+}
+
+static const struct drm_private_state_funcs dpu_kms_global_state_funcs = {
+	.atomic_duplicate_state = dpu_kms_global_duplicate_state,
+	.atomic_destroy_state = dpu_kms_global_destroy_state,
+};
+
+static int dpu_kms_global_obj_init(struct dpu_kms *dpu_kms)
+{
+	struct dpu_global_state *state;
+
+	drm_modeset_lock_init(&dpu_kms->global_state_lock);
+
+	state = kzalloc(sizeof(*state), GFP_KERNEL);
+	if (!state)
+		return -ENOMEM;
+
+	drm_atomic_private_obj_init(dpu_kms->dev, &dpu_kms->global_state,
+				    &state->base,
+				    &dpu_kms_global_state_funcs);
+	return 0;
+}
+
 static int dpu_kms_enable_vblank(struct msm_kms *kms, struct drm_crtc *crtc)
 {
 	return dpu_crtc_vblank(crtc, true);
@@ -770,6 +849,11 @@ static int dpu_kms_hw_init(struct msm_kms *kms)
 
 	dpu_kms = to_dpu_kms(kms);
 	dev = dpu_kms->dev;
+
+	rc = dpu_kms_global_obj_init(dpu_kms);
+	if (rc)
+		return rc;
+
 	priv = dev->dev_private;
 
 	atomic_set(&dpu_kms->bandwidth_ref, 0);
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h
index c6169e7df19de..211f5de99a441 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h
@@ -111,6 +111,13 @@ struct dpu_kms {
 
 	struct dpu_core_perf perf;
 
+	/*
+	 * Global private object state, Do not access directly, use
+	 * dpu_kms_global_get_state()
+	 */
+	struct drm_modeset_lock global_state_lock;
+	struct drm_private_obj global_state;
+
 	struct dpu_rm rm;
 	bool rm_init;
 
@@ -139,6 +146,25 @@ struct vsync_info {
 
 #define to_dpu_kms(x) container_of(x, struct dpu_kms, base)
 
+#define to_dpu_global_state(x) container_of(x, struct dpu_global_state, base)
+
+/* Global private object state for tracking resources that are shared across
+ * multiple kms objects (planes/crtcs/etc).
+ */
+struct dpu_global_state {
+	struct drm_private_state base;
+
+	uint32_t pingpong_to_enc_id[PINGPONG_MAX - PINGPONG_0];
+	uint32_t mixer_to_enc_id[LM_MAX - LM_0];
+	uint32_t ctl_to_enc_id[CTL_MAX - CTL_0];
+	uint32_t intf_to_enc_id[INTF_MAX - INTF_0];
+};
+
+struct dpu_global_state
+	*dpu_kms_get_existing_global_state(struct dpu_kms *dpu_kms);
+struct dpu_global_state
+	*__must_check dpu_kms_get_global_state(struct drm_atomic_state *s);
+
 /**
  * Debugfs functions - extra helper functions for debugfs support
  *
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c
index f1483b00b7423..bc940f9b12d7e 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c
@@ -66,8 +66,6 @@ int dpu_rm_destroy(struct dpu_rm *rm)
 		}
 	}
 
-	mutex_destroy(&rm->rm_lock);
-
 	return 0;
 }
 
@@ -85,8 +83,6 @@ int dpu_rm_init(struct dpu_rm *rm,
 	/* Clear, setup lists */
 	memset(rm, 0, sizeof(*rm));
 
-	mutex_init(&rm->rm_lock);
-
 	/* Interrogate HW catalog and create tracking items for hw blocks */
 	for (i = 0; i < cat->mixer_count; i++) {
 		struct dpu_hw_mixer *hw;
@@ -230,13 +226,14 @@ static bool _dpu_rm_check_lm_peer(struct dpu_rm *rm, int primary_idx,
  * @Return: true if lm matches all requirements, false otherwise
  */
 static bool _dpu_rm_check_lm_and_get_connected_blks(struct dpu_rm *rm,
+		struct dpu_global_state *global_state,
 		uint32_t enc_id, int lm_idx, int *pp_idx)
 {
 	const struct dpu_lm_cfg *lm_cfg;
 	int idx;
 
 	/* Already reserved? */
-	if (reserved_by_other(rm->mixer_to_enc_id, lm_idx, enc_id)) {
+	if (reserved_by_other(global_state->mixer_to_enc_id, lm_idx, enc_id)) {
 		DPU_DEBUG("lm %d already reserved\n", lm_idx + LM_0);
 		return false;
 	}
@@ -248,7 +245,7 @@ static bool _dpu_rm_check_lm_and_get_connected_blks(struct dpu_rm *rm,
 		return false;
 	}
 
-	if (reserved_by_other(rm->pingpong_to_enc_id, idx, enc_id)) {
+	if (reserved_by_other(global_state->pingpong_to_enc_id, idx, enc_id)) {
 		DPU_DEBUG("lm %d pp %d already reserved\n", lm_cfg->id,
 				lm_cfg->pingpong);
 		return false;
@@ -257,7 +254,9 @@ static bool _dpu_rm_check_lm_and_get_connected_blks(struct dpu_rm *rm,
 	return true;
 }
 
-static int _dpu_rm_reserve_lms(struct dpu_rm *rm, uint32_t enc_id,
+static int _dpu_rm_reserve_lms(struct dpu_rm *rm,
+			       struct dpu_global_state *global_state,
+			       uint32_t enc_id,
 			       struct dpu_rm_requirements *reqs)
 
 {
@@ -279,8 +278,8 @@ static int _dpu_rm_reserve_lms(struct dpu_rm *rm, uint32_t enc_id,
 		lm_count = 0;
 		lm_idx[lm_count] = i;
 
-		if (!_dpu_rm_check_lm_and_get_connected_blks(
-				rm, enc_id, i, &pp_idx[lm_count])) {
+		if (!_dpu_rm_check_lm_and_get_connected_blks(rm, global_state,
+				enc_id, i, &pp_idx[lm_count])) {
 			continue;
 		}
 
@@ -298,8 +297,9 @@ static int _dpu_rm_reserve_lms(struct dpu_rm *rm, uint32_t enc_id,
 				continue;
 			}
 
-			if (!_dpu_rm_check_lm_and_get_connected_blks(
-					rm, enc_id, j, &pp_idx[lm_count])) {
+			if (!_dpu_rm_check_lm_and_get_connected_blks(rm,
+					global_state, enc_id, j,
+					&pp_idx[lm_count])) {
 				continue;
 			}
 
@@ -314,8 +314,8 @@ static int _dpu_rm_reserve_lms(struct dpu_rm *rm, uint32_t enc_id,
 	}
 
 	for (i = 0; i < lm_count; i++) {
-		rm->mixer_to_enc_id[lm_idx[i]] = enc_id;
-		rm->pingpong_to_enc_id[pp_idx[i]] = enc_id;
+		global_state->mixer_to_enc_id[lm_idx[i]] = enc_id;
+		global_state->pingpong_to_enc_id[pp_idx[i]] = enc_id;
 
 		trace_dpu_rm_reserve_lms(lm_idx[i] + LM_0, enc_id,
 					 pp_idx[i] + PINGPONG_0);
@@ -326,6 +326,7 @@ static int _dpu_rm_reserve_lms(struct dpu_rm *rm, uint32_t enc_id,
 
 static int _dpu_rm_reserve_ctls(
 		struct dpu_rm *rm,
+		struct dpu_global_state *global_state,
 		uint32_t enc_id,
 		const struct msm_display_topology *top)
 {
@@ -345,7 +346,7 @@ static int _dpu_rm_reserve_ctls(
 
 		if (!rm->ctl_blks[j])
 			continue;
-		if (reserved_by_other(rm->ctl_to_enc_id, j, enc_id))
+		if (reserved_by_other(global_state->ctl_to_enc_id, j, enc_id))
 			continue;
 
 		ctl = to_dpu_hw_ctl(rm->ctl_blks[j]);
@@ -369,7 +370,7 @@ static int _dpu_rm_reserve_ctls(
 		return -ENAVAIL;
 
 	for (i = 0; i < ARRAY_SIZE(ctl_idx) && i < num_ctls; i++) {
-		rm->ctl_to_enc_id[ctl_idx[i]] = enc_id;
+		global_state->ctl_to_enc_id[ctl_idx[i]] = enc_id;
 		trace_dpu_rm_reserve_ctls(i + CTL_0, enc_id);
 	}
 
@@ -378,27 +379,34 @@ static int _dpu_rm_reserve_ctls(
 
 static int _dpu_rm_reserve_intf(
 		struct dpu_rm *rm,
+		struct dpu_global_state *global_state,
 		uint32_t enc_id,
 		uint32_t id)
 {
 	int idx = id - INTF_0;
 
+	if (idx < 0 || idx >= ARRAY_SIZE(rm->intf_blks)) {
+		DPU_ERROR("invalid intf id: %d", id);
+		return -EINVAL;
+	}
+
 	if (!rm->intf_blks[idx]) {
 		DPU_ERROR("couldn't find intf id %d\n", id);
 		return -EINVAL;
 	}
 
-	if (reserved_by_other(rm->intf_to_enc_id, idx, enc_id)) {
+	if (reserved_by_other(global_state->intf_to_enc_id, idx, enc_id)) {
 		DPU_ERROR("intf id %d already reserved\n", id);
 		return -ENAVAIL;
 	}
 
-	rm->intf_to_enc_id[idx] = enc_id;
+	global_state->intf_to_enc_id[idx] = enc_id;
 	return 0;
 }
 
 static int _dpu_rm_reserve_intf_related_hw(
 		struct dpu_rm *rm,
+		struct dpu_global_state *global_state,
 		uint32_t enc_id,
 		struct dpu_encoder_hw_resources *hw_res)
 {
@@ -409,7 +417,7 @@ static int _dpu_rm_reserve_intf_related_hw(
 		if (hw_res->intfs[i] == INTF_MODE_NONE)
 			continue;
 		id = i + INTF_0;
-		ret = _dpu_rm_reserve_intf(rm, enc_id, id);
+		ret = _dpu_rm_reserve_intf(rm, global_state, enc_id, id);
 		if (ret)
 			return ret;
 	}
@@ -419,24 +427,27 @@ static int _dpu_rm_reserve_intf_related_hw(
 
 static int _dpu_rm_make_reservation(
 		struct dpu_rm *rm,
+		struct dpu_global_state *global_state,
 		struct drm_encoder *enc,
 		struct dpu_rm_requirements *reqs)
 {
 	int ret;
 
-	ret = _dpu_rm_reserve_lms(rm, enc->base.id, reqs);
+	ret = _dpu_rm_reserve_lms(rm, global_state, enc->base.id, reqs);
 	if (ret) {
 		DPU_ERROR("unable to find appropriate mixers\n");
 		return ret;
 	}
 
-	ret = _dpu_rm_reserve_ctls(rm, enc->base.id, &reqs->topology);
+	ret = _dpu_rm_reserve_ctls(rm, global_state, enc->base.id,
+				&reqs->topology);
 	if (ret) {
 		DPU_ERROR("unable to find appropriate CTL\n");
 		return ret;
 	}
 
-	ret = _dpu_rm_reserve_intf_related_hw(rm, enc->base.id, &reqs->hw_res);
+	ret = _dpu_rm_reserve_intf_related_hw(rm, global_state, enc->base.id,
+				&reqs->hw_res);
 	if (ret)
 		return ret;
 
@@ -470,33 +481,25 @@ static void _dpu_rm_clear_mapping(uint32_t *res_mapping, int cnt,
 	}
 }
 
-static void _dpu_rm_release_reservation(struct dpu_rm *rm, uint32_t enc_id)
-{
-	_dpu_rm_clear_mapping(rm->pingpong_to_enc_id,
-		ARRAY_SIZE(rm->pingpong_to_enc_id), enc_id);
-	_dpu_rm_clear_mapping(rm->mixer_to_enc_id,
-		ARRAY_SIZE(rm->mixer_to_enc_id), enc_id);
-	_dpu_rm_clear_mapping(rm->ctl_to_enc_id,
-		ARRAY_SIZE(rm->ctl_to_enc_id), enc_id);
-	_dpu_rm_clear_mapping(rm->intf_to_enc_id,
-		ARRAY_SIZE(rm->intf_to_enc_id), enc_id);
-}
-
-void dpu_rm_release(struct dpu_rm *rm, struct drm_encoder *enc)
+void dpu_rm_release(struct dpu_global_state *global_state,
+		    struct drm_encoder *enc)
 {
-	mutex_lock(&rm->rm_lock);
-
-	_dpu_rm_release_reservation(rm, enc->base.id);
-
-	mutex_unlock(&rm->rm_lock);
+	_dpu_rm_clear_mapping(global_state->pingpong_to_enc_id,
+		ARRAY_SIZE(global_state->pingpong_to_enc_id), enc->base.id);
+	_dpu_rm_clear_mapping(global_state->mixer_to_enc_id,
+		ARRAY_SIZE(global_state->mixer_to_enc_id), enc->base.id);
+	_dpu_rm_clear_mapping(global_state->ctl_to_enc_id,
+		ARRAY_SIZE(global_state->ctl_to_enc_id), enc->base.id);
+	_dpu_rm_clear_mapping(global_state->intf_to_enc_id,
+		ARRAY_SIZE(global_state->intf_to_enc_id), enc->base.id);
 }
 
 int dpu_rm_reserve(
 		struct dpu_rm *rm,
+		struct dpu_global_state *global_state,
 		struct drm_encoder *enc,
 		struct drm_crtc_state *crtc_state,
-		struct msm_display_topology topology,
-		bool test_only)
+		struct msm_display_topology topology)
 {
 	struct dpu_rm_requirements reqs;
 	int ret;
@@ -505,35 +508,31 @@ int dpu_rm_reserve(
 	if (!drm_atomic_crtc_needs_modeset(crtc_state))
 		return 0;
 
-	DRM_DEBUG_KMS("reserving hw for enc %d crtc %d test_only %d\n",
-		      enc->base.id, crtc_state->crtc->base.id, test_only);
+	if (IS_ERR(global_state)) {
+		DPU_ERROR("failed to global state\n");
+		return PTR_ERR(global_state);
+	}
 
-	mutex_lock(&rm->rm_lock);
+	DRM_DEBUG_KMS("reserving hw for enc %d crtc %d\n",
+		      enc->base.id, crtc_state->crtc->base.id);
 
 	ret = _dpu_rm_populate_requirements(enc, &reqs, topology);
 	if (ret) {
 		DPU_ERROR("failed to populate hw requirements\n");
-		goto end;
+		return ret;
 	}
 
-	ret = _dpu_rm_make_reservation(rm, enc, &reqs);
-	if (ret) {
+	ret = _dpu_rm_make_reservation(rm, global_state, enc, &reqs);
+	if (ret)
 		DPU_ERROR("failed to reserve hw resources: %d\n", ret);
-		_dpu_rm_release_reservation(rm, enc->base.id);
-	} else if (test_only) {
-		 /* test_only: test the reservation and then undo */
-		DPU_DEBUG("test_only: discard test [enc: %d]\n",
-				enc->base.id);
-		_dpu_rm_release_reservation(rm, enc->base.id);
-	}
 
-end:
-	mutex_unlock(&rm->rm_lock);
+
 
 	return ret;
 }
 
-int dpu_rm_get_assigned_resources(struct dpu_rm *rm, uint32_t enc_id,
+int dpu_rm_get_assigned_resources(struct dpu_rm *rm,
+	struct dpu_global_state *global_state, uint32_t enc_id,
 	enum dpu_hw_blk_type type, struct dpu_hw_blk **blks, int blks_size)
 {
 	struct dpu_hw_blk **hw_blks;
@@ -543,22 +542,22 @@ int dpu_rm_get_assigned_resources(struct dpu_rm *rm, uint32_t enc_id,
 	switch (type) {
 	case DPU_HW_BLK_PINGPONG:
 		hw_blks = rm->pingpong_blks;
-		hw_to_enc_id = rm->pingpong_to_enc_id;
+		hw_to_enc_id = global_state->pingpong_to_enc_id;
 		max_blks = ARRAY_SIZE(rm->pingpong_blks);
 		break;
 	case DPU_HW_BLK_LM:
 		hw_blks = rm->mixer_blks;
-		hw_to_enc_id = rm->mixer_to_enc_id;
+		hw_to_enc_id = global_state->mixer_to_enc_id;
 		max_blks = ARRAY_SIZE(rm->mixer_blks);
 		break;
 	case DPU_HW_BLK_CTL:
 		hw_blks = rm->ctl_blks;
-		hw_to_enc_id = rm->ctl_to_enc_id;
+		hw_to_enc_id = global_state->ctl_to_enc_id;
 		max_blks = ARRAY_SIZE(rm->ctl_blks);
 		break;
 	case DPU_HW_BLK_INTF:
 		hw_blks = rm->intf_blks;
-		hw_to_enc_id = rm->intf_to_enc_id;
+		hw_to_enc_id = global_state->intf_to_enc_id;
 		max_blks = ARRAY_SIZE(rm->intf_blks);
 		break;
 	default:
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.h
index 9c8a436ba6cc1..6d2b04f306f09 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.h
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.h
@@ -11,6 +11,7 @@
 #include "msm_kms.h"
 #include "dpu_hw_top.h"
 
+struct dpu_global_state;
 
 /**
  * struct dpu_rm - DPU dynamic hardware resource manager
@@ -18,10 +19,6 @@
  * @mixer_blks: array of layer mixer hardware resources
  * @ctl_blks: array of ctl hardware resources
  * @intf_blks: array of intf hardware resources
- * @pingpong_to_enc_id: mapping of pingpong hardware resources to an encoder ID
- * @mixer_to_enc_id: mapping of mixer hardware resources to an encoder ID
- * @ctl_to_enc_id: mapping of ctl hardware resources to an encoder ID
- * @intf_to_enc_id: mapping of intf hardware resources to an encoder ID
  * @lm_max_width: cached layer mixer maximum width
  * @rm_lock: resource manager mutex
  */
@@ -31,13 +28,7 @@ struct dpu_rm {
 	struct dpu_hw_blk *ctl_blks[CTL_MAX - CTL_0];
 	struct dpu_hw_blk *intf_blks[INTF_MAX - INTF_0];
 
-	uint32_t pingpong_to_enc_id[PINGPONG_MAX - PINGPONG_0];
-	uint32_t mixer_to_enc_id[LM_MAX - LM_0];
-	uint32_t ctl_to_enc_id[CTL_MAX - CTL_0];
-	uint32_t intf_to_enc_id[INTF_MAX - INTF_0];
-
 	uint32_t lm_max_width;
-	struct mutex rm_lock;
 };
 
 /**
@@ -70,14 +61,13 @@ int dpu_rm_destroy(struct dpu_rm *rm);
  * @drm_enc: DRM Encoder handle
  * @crtc_state: Proposed Atomic DRM CRTC State handle
  * @topology: Pointer to topology info for the display
- * @test_only: Atomic-Test phase, discard results (unless property overrides)
  * @Return: 0 on Success otherwise -ERROR
  */
 int dpu_rm_reserve(struct dpu_rm *rm,
+		struct dpu_global_state *global_state,
 		struct drm_encoder *drm_enc,
 		struct drm_crtc_state *crtc_state,
-		struct msm_display_topology topology,
-		bool test_only);
+		struct msm_display_topology topology);
 
 /**
  * dpu_rm_reserve - Given the encoder for the display chain, release any
@@ -86,12 +76,14 @@ int dpu_rm_reserve(struct dpu_rm *rm,
  * @enc: DRM Encoder handle
  * @Return: 0 on Success otherwise -ERROR
  */
-void dpu_rm_release(struct dpu_rm *rm, struct drm_encoder *enc);
+void dpu_rm_release(struct dpu_global_state *global_state,
+		struct drm_encoder *enc);
 
 /**
  * Get hw resources of the given type that are assigned to this encoder.
  */
-int dpu_rm_get_assigned_resources(struct dpu_rm *rm, uint32_t enc_id,
+int dpu_rm_get_assigned_resources(struct dpu_rm *rm,
+	struct dpu_global_state *global_state, uint32_t enc_id,
 	enum dpu_hw_blk_type type, struct dpu_hw_blk **blks, int blks_size);
 #endif /* __DPU_RM_H__ */
 
-- 
2.24.1


^ permalink raw reply related	[flat|nested] 7+ messages in thread

* Re: [PATCH 1/4] drm/msm/dpu: Remove unused function arguments
  2020-02-19 17:42 [PATCH 1/4] drm/msm/dpu: Remove unused function arguments Drew Davenport
                   ` (2 preceding siblings ...)
  2020-02-19 17:42 ` [PATCH 4/4] drm/msm/dpu: Track resources in global state Drew Davenport
@ 2020-02-25 19:27 ` Stephen Boyd
  3 siblings, 0 replies; 7+ messages in thread
From: Stephen Boyd @ 2020-02-25 19:27 UTC (permalink / raw)
  To: Drew Davenport, dri-devel
  Cc: Drew Davenport, Alexios Zavras, Daniel Vetter, David Airlie,
	Greg Kroah-Hartman, Rob Clark, Sean Paul, Thomas Gleixner,
	freedreno, linux-arm-msm, linux-kernel

Quoting Drew Davenport (2020-02-19 09:42:24)
> Several functions arguments in the resource manager are unused, so
> remove them.
> 
> Signed-off-by: Drew Davenport <ddavenport@chromium.org>
> ---

Reviewed-by: Stephen Boyd <swboyd@chromium.org>

> 
>  drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c | 37 ++++++++++----------------
>  1 file changed, 14 insertions(+), 23 deletions(-)
> 
> diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c
> index 23f5b1433b357..dea1dba441fe7 100644
> --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c
> +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c
> @@ -144,8 +144,7 @@ static int _dpu_rm_hw_blk_create(
>                 const struct dpu_mdss_cfg *cat,
>                 void __iomem *mmio,
>                 enum dpu_hw_blk_type type,
> -               uint32_t id,
> -               const void *hw_catalog_info)
> +               uint32_t id)

It would be good to use u32 instead of uint32_t in this code too. The
kernel style is to use the shorter name for that type.

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [PATCH 2/4] drm/msm/dpu: Refactor rm iterator
  2020-02-19 17:42 ` [PATCH 2/4] drm/msm/dpu: Refactor rm iterator Drew Davenport
@ 2020-02-25 19:33   ` Stephen Boyd
  2020-02-25 19:41     ` Rob Clark
  0 siblings, 1 reply; 7+ messages in thread
From: Stephen Boyd @ 2020-02-25 19:33 UTC (permalink / raw)
  To: Drew Davenport, dri-devel
  Cc: Drew Davenport, Alexios Zavras, Allison Randal, Daniel Vetter,
	David Airlie, Fritz Koenig, Greg Kroah-Hartman,
	Jeykumar Sankaran, Kalyan Thota, Rob Clark, Sean Paul,
	Shubhashree Dhar, Thomas Gleixner, freedreno, linux-arm-msm,
	linux-kernel, zhengbin

Quoting Drew Davenport (2020-02-19 09:42:25)
> Make iterator implementation private, and add function to
> query resources assigned to an encoder.
> 
> Signed-off-by: Drew Davenport <ddavenport@chromium.org>

> diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
> index f8ac3bf60fd60..6cadeff456f09 100644
> --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
> +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
> @@ -957,11 +957,11 @@ static void dpu_encoder_virt_mode_set(struct drm_encoder *drm_enc,
>         struct drm_connector *conn = NULL, *conn_iter;
>         struct drm_crtc *drm_crtc;
>         struct dpu_crtc_state *cstate;
> -       struct dpu_rm_hw_iter hw_iter;
>         struct msm_display_topology topology;
> -       struct dpu_hw_ctl *hw_ctl[MAX_CHANNELS_PER_ENC] = { NULL };
> -       struct dpu_hw_mixer *hw_lm[MAX_CHANNELS_PER_ENC] = { NULL };
> -       int num_lm = 0, num_ctl = 0;
> +       struct dpu_hw_blk *hw_pp[MAX_CHANNELS_PER_ENC];
> +       struct dpu_hw_blk *hw_ctl[MAX_CHANNELS_PER_ENC];
> +       struct dpu_hw_blk *hw_lm[MAX_CHANNELS_PER_ENC];
> +       int num_lm, num_ctl, num_pp;

All these should be unsigned too?

>         int i, j, ret;
>  
>         if (!drm_enc) {
> @@ -1005,42 +1005,31 @@ static void dpu_encoder_virt_mode_set(struct drm_encoder *drm_enc,
>                 return;
>         }
>  
> -       dpu_rm_init_hw_iter(&hw_iter, drm_enc->base.id, DPU_HW_BLK_PINGPONG);
> -       for (i = 0; i < MAX_CHANNELS_PER_ENC; i++) {
> -               dpu_enc->hw_pp[i] = NULL;
> -               if (!dpu_rm_get_hw(&dpu_kms->rm, &hw_iter))
> -                       break;
> -               dpu_enc->hw_pp[i] = (struct dpu_hw_pingpong *) hw_iter.hw;
> -       }
> -
> -       dpu_rm_init_hw_iter(&hw_iter, drm_enc->base.id, DPU_HW_BLK_CTL);
> -       for (i = 0; i < MAX_CHANNELS_PER_ENC; i++) {
> -               if (!dpu_rm_get_hw(&dpu_kms->rm, &hw_iter))
> -                       break;
> -               hw_ctl[i] = (struct dpu_hw_ctl *)hw_iter.hw;

Why cast? Isn't it void pointer?

> -               num_ctl++;
> -       }
> +       num_pp = dpu_rm_get_assigned_resources(&dpu_kms->rm, drm_enc->base.id,
> +               DPU_HW_BLK_PINGPONG, hw_pp, ARRAY_SIZE(hw_pp));
> +       num_ctl = dpu_rm_get_assigned_resources(&dpu_kms->rm, drm_enc->base.id,
> +               DPU_HW_BLK_CTL, hw_ctl, ARRAY_SIZE(hw_ctl));
> +       num_lm = dpu_rm_get_assigned_resources(&dpu_kms->rm, drm_enc->base.id,
> +               DPU_HW_BLK_LM, hw_lm, ARRAY_SIZE(hw_lm));
>  
> -       dpu_rm_init_hw_iter(&hw_iter, drm_enc->base.id, DPU_HW_BLK_LM);
> -       for (i = 0; i < MAX_CHANNELS_PER_ENC; i++) {
> -               if (!dpu_rm_get_hw(&dpu_kms->rm, &hw_iter))
> -                       break;
> -               hw_lm[i] = (struct dpu_hw_mixer *)hw_iter.hw;

Why cast?

> -               num_lm++;
> -       }
> +       for (i = 0; i < MAX_CHANNELS_PER_ENC; i++)
> +               dpu_enc->hw_pp[i] = i < num_pp ? to_dpu_hw_pingpong(hw_pp[i])
> +                                               : NULL;

This line is pretty hard to read. Maybe use an if/else?

>  
>         cstate = to_dpu_crtc_state(drm_crtc->state);
>  
>         for (i = 0; i < num_lm; i++) {
>                 int ctl_idx = (i < num_ctl) ? i : (num_ctl-1);
>  
> -               cstate->mixers[i].hw_lm = hw_lm[i];
> -               cstate->mixers[i].lm_ctl = hw_ctl[ctl_idx];
> +               cstate->mixers[i].hw_lm = to_dpu_hw_mixer(hw_lm[i]);
> +               cstate->mixers[i].lm_ctl = to_dpu_hw_ctl(hw_ctl[ctl_idx]);
>         }
>  
>         cstate->num_mixers = num_lm;
>  
>         for (i = 0; i < dpu_enc->num_phys_encs; i++) {
> +               int num_blk;

unsigned int?

> +               struct dpu_hw_blk *hw_blk[MAX_CHANNELS_PER_ENC];
>                 struct dpu_encoder_phys *phys = dpu_enc->phys_encs[i];
>  
>                 if (!dpu_enc->hw_pp[i]) {
> @@ -1056,17 +1045,15 @@ static void dpu_encoder_virt_mode_set(struct drm_encoder *drm_enc,
>                 }
>  
>                 phys->hw_pp = dpu_enc->hw_pp[i];
> -               phys->hw_ctl = hw_ctl[i];
> +               phys->hw_ctl = to_dpu_hw_ctl(hw_ctl[i]);
>  
> -               dpu_rm_init_hw_iter(&hw_iter, drm_enc->base.id,
> -                                   DPU_HW_BLK_INTF);
> -               for (j = 0; j < MAX_CHANNELS_PER_ENC; j++) {
> +               num_blk = dpu_rm_get_assigned_resources(&dpu_kms->rm,
> +                       drm_enc->base.id, DPU_HW_BLK_INTF, hw_blk,
> +                       ARRAY_SIZE(hw_blk));
> +               for (j = 0; j < num_blk; j++) {
>                         struct dpu_hw_intf *hw_intf;
>  
> -                       if (!dpu_rm_get_hw(&dpu_kms->rm, &hw_iter))
> -                               break;
> -
> -                       hw_intf = (struct dpu_hw_intf *)hw_iter.hw;
> +                       hw_intf = to_dpu_hw_intf(hw_blk[i]);
>                         if (hw_intf->idx == phys->intf_idx)
>                                 phys->hw_intf = hw_intf;
>                 }
> diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c
> index dea1dba441fe7..779df26dc81ae 100644
> --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c
> +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c
> @@ -83,7 +97,7 @@ static bool _dpu_rm_get_hw_locked(struct dpu_rm *rm, struct dpu_rm_hw_iter *i)
>         return false;
>  }
>  
> -bool dpu_rm_get_hw(struct dpu_rm *rm, struct dpu_rm_hw_iter *i)
> +static bool dpu_rm_get_hw(struct dpu_rm *rm, struct dpu_rm_hw_iter *i)
>  {
>         bool ret;
>  
> @@ -635,3 +649,16 @@ int dpu_rm_reserve(
>  
>         return ret;
>  }
> +
> +int dpu_rm_get_assigned_resources(struct dpu_rm *rm, uint32_t enc_id,

Return unsigned int?

> +       enum dpu_hw_blk_type type, struct dpu_hw_blk **blks, int blks_size)

unsigned int blks_size?

> +{
> +       struct dpu_rm_hw_iter hw_iter;
> +       int num_blks = 0;

unsigned int?

> +
> +       dpu_rm_init_hw_iter(&hw_iter, enc_id, type);
> +       while (num_blks < blks_size && dpu_rm_get_hw(rm, &hw_iter))
> +               blks[num_blks++] = hw_iter.blk->hw;
> +
> +       return num_blks;

It's not possible for it to be negative number right?

> +}
> diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.h
> index 9c580a0170946..982b91e272275 100644
> --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.h
> +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.h
> @@ -24,26 +24,6 @@ struct dpu_rm {
>         struct mutex rm_lock;
>  };
>  
> -/**
> - *  struct dpu_rm_hw_blk - resource manager internal structure
> - *     forward declaration for single iterator definition without void pointer
> - */
> -struct dpu_rm_hw_blk;
> -
> -/**
> - * struct dpu_rm_hw_iter - iterator for use with dpu_rm
> - * @hw: dpu_hw object requested, or NULL on failure
> - * @blk: dpu_rm internal block representation. Clients ignore. Used as iterator.
> - * @enc_id: DRM ID of Encoder client wishes to search for, or 0 for Any Encoder

Why is Encoder and Any capitalized?

> - * @type: Hardware Block Type client wishes to search for.
> - */
> -struct dpu_rm_hw_iter {
> -       void *hw;
> -       struct dpu_rm_hw_blk *blk;
> -       uint32_t enc_id;
> -       enum dpu_hw_blk_type type;
> -};
> -
>  /**
>   * dpu_rm_init - Read hardware catalog and create reservation tracking objects
>   *     for all HW blocks.
> @@ -93,28 +73,9 @@ int dpu_rm_reserve(struct dpu_rm *rm,
>  void dpu_rm_release(struct dpu_rm *rm, struct drm_encoder *enc);
>  
>  /**
> - * dpu_rm_init_hw_iter - setup given iterator for new iteration over hw list
> - *     using dpu_rm_get_hw
> - * @iter: iter object to initialize
> - * @enc_id: DRM ID of Encoder client wishes to search for, or 0 for Any Encoder
> - * @type: Hardware Block Type client wishes to search for.

Ah I guess it's copied from here.

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [PATCH 2/4] drm/msm/dpu: Refactor rm iterator
  2020-02-25 19:33   ` Stephen Boyd
@ 2020-02-25 19:41     ` Rob Clark
  0 siblings, 0 replies; 7+ messages in thread
From: Rob Clark @ 2020-02-25 19:41 UTC (permalink / raw)
  To: Stephen Boyd
  Cc: Drew Davenport, dri-devel, Alexios Zavras, Allison Randal,
	Daniel Vetter, David Airlie, Fritz Koenig, Greg Kroah-Hartman,
	Jeykumar Sankaran, Kalyan Thota, Sean Paul, Shubhashree Dhar,
	Thomas Gleixner, freedreno, linux-arm-msm,
	Linux Kernel Mailing List, zhengbin

On Tue, Feb 25, 2020 at 11:33 AM Stephen Boyd <swboyd@chromium.org> wrote:
>
> Quoting Drew Davenport (2020-02-19 09:42:25)
> > Make iterator implementation private, and add function to
> > query resources assigned to an encoder.
> >
> > Signed-off-by: Drew Davenport <ddavenport@chromium.org>
>
> > diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
> > index f8ac3bf60fd60..6cadeff456f09 100644
> > --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
> > +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
> > @@ -957,11 +957,11 @@ static void dpu_encoder_virt_mode_set(struct drm_encoder *drm_enc,
> >         struct drm_connector *conn = NULL, *conn_iter;
> >         struct drm_crtc *drm_crtc;
> >         struct dpu_crtc_state *cstate;
> > -       struct dpu_rm_hw_iter hw_iter;
> >         struct msm_display_topology topology;
> > -       struct dpu_hw_ctl *hw_ctl[MAX_CHANNELS_PER_ENC] = { NULL };
> > -       struct dpu_hw_mixer *hw_lm[MAX_CHANNELS_PER_ENC] = { NULL };
> > -       int num_lm = 0, num_ctl = 0;
> > +       struct dpu_hw_blk *hw_pp[MAX_CHANNELS_PER_ENC];
> > +       struct dpu_hw_blk *hw_ctl[MAX_CHANNELS_PER_ENC];
> > +       struct dpu_hw_blk *hw_lm[MAX_CHANNELS_PER_ENC];
> > +       int num_lm, num_ctl, num_pp;
>
> All these should be unsigned too?
>
> >         int i, j, ret;
> >
> >         if (!drm_enc) {
> > @@ -1005,42 +1005,31 @@ static void dpu_encoder_virt_mode_set(struct drm_encoder *drm_enc,
> >                 return;
> >         }
> >
> > -       dpu_rm_init_hw_iter(&hw_iter, drm_enc->base.id, DPU_HW_BLK_PINGPONG);
> > -       for (i = 0; i < MAX_CHANNELS_PER_ENC; i++) {
> > -               dpu_enc->hw_pp[i] = NULL;
> > -               if (!dpu_rm_get_hw(&dpu_kms->rm, &hw_iter))
> > -                       break;
> > -               dpu_enc->hw_pp[i] = (struct dpu_hw_pingpong *) hw_iter.hw;
> > -       }
> > -
> > -       dpu_rm_init_hw_iter(&hw_iter, drm_enc->base.id, DPU_HW_BLK_CTL);
> > -       for (i = 0; i < MAX_CHANNELS_PER_ENC; i++) {
> > -               if (!dpu_rm_get_hw(&dpu_kms->rm, &hw_iter))
> > -                       break;
> > -               hw_ctl[i] = (struct dpu_hw_ctl *)hw_iter.hw;
>
> Why cast? Isn't it void pointer?

Comments on code that the patch removes is a new thing :-P

BR,
-R

>
> > -               num_ctl++;
> > -       }
> > +       num_pp = dpu_rm_get_assigned_resources(&dpu_kms->rm, drm_enc->base.id,
> > +               DPU_HW_BLK_PINGPONG, hw_pp, ARRAY_SIZE(hw_pp));
> > +       num_ctl = dpu_rm_get_assigned_resources(&dpu_kms->rm, drm_enc->base.id,
> > +               DPU_HW_BLK_CTL, hw_ctl, ARRAY_SIZE(hw_ctl));
> > +       num_lm = dpu_rm_get_assigned_resources(&dpu_kms->rm, drm_enc->base.id,
> > +               DPU_HW_BLK_LM, hw_lm, ARRAY_SIZE(hw_lm));
> >
> > -       dpu_rm_init_hw_iter(&hw_iter, drm_enc->base.id, DPU_HW_BLK_LM);
> > -       for (i = 0; i < MAX_CHANNELS_PER_ENC; i++) {
> > -               if (!dpu_rm_get_hw(&dpu_kms->rm, &hw_iter))
> > -                       break;
> > -               hw_lm[i] = (struct dpu_hw_mixer *)hw_iter.hw;
>
> Why cast?
>
> > -               num_lm++;
> > -       }
> > +       for (i = 0; i < MAX_CHANNELS_PER_ENC; i++)
> > +               dpu_enc->hw_pp[i] = i < num_pp ? to_dpu_hw_pingpong(hw_pp[i])
> > +                                               : NULL;
>
> This line is pretty hard to read. Maybe use an if/else?
>
> >
> >         cstate = to_dpu_crtc_state(drm_crtc->state);
> >
> >         for (i = 0; i < num_lm; i++) {
> >                 int ctl_idx = (i < num_ctl) ? i : (num_ctl-1);
> >
> > -               cstate->mixers[i].hw_lm = hw_lm[i];
> > -               cstate->mixers[i].lm_ctl = hw_ctl[ctl_idx];
> > +               cstate->mixers[i].hw_lm = to_dpu_hw_mixer(hw_lm[i]);
> > +               cstate->mixers[i].lm_ctl = to_dpu_hw_ctl(hw_ctl[ctl_idx]);
> >         }
> >
> >         cstate->num_mixers = num_lm;
> >
> >         for (i = 0; i < dpu_enc->num_phys_encs; i++) {
> > +               int num_blk;
>
> unsigned int?
>
> > +               struct dpu_hw_blk *hw_blk[MAX_CHANNELS_PER_ENC];
> >                 struct dpu_encoder_phys *phys = dpu_enc->phys_encs[i];
> >
> >                 if (!dpu_enc->hw_pp[i]) {
> > @@ -1056,17 +1045,15 @@ static void dpu_encoder_virt_mode_set(struct drm_encoder *drm_enc,
> >                 }
> >
> >                 phys->hw_pp = dpu_enc->hw_pp[i];
> > -               phys->hw_ctl = hw_ctl[i];
> > +               phys->hw_ctl = to_dpu_hw_ctl(hw_ctl[i]);
> >
> > -               dpu_rm_init_hw_iter(&hw_iter, drm_enc->base.id,
> > -                                   DPU_HW_BLK_INTF);
> > -               for (j = 0; j < MAX_CHANNELS_PER_ENC; j++) {
> > +               num_blk = dpu_rm_get_assigned_resources(&dpu_kms->rm,
> > +                       drm_enc->base.id, DPU_HW_BLK_INTF, hw_blk,
> > +                       ARRAY_SIZE(hw_blk));
> > +               for (j = 0; j < num_blk; j++) {
> >                         struct dpu_hw_intf *hw_intf;
> >
> > -                       if (!dpu_rm_get_hw(&dpu_kms->rm, &hw_iter))
> > -                               break;
> > -
> > -                       hw_intf = (struct dpu_hw_intf *)hw_iter.hw;
> > +                       hw_intf = to_dpu_hw_intf(hw_blk[i]);
> >                         if (hw_intf->idx == phys->intf_idx)
> >                                 phys->hw_intf = hw_intf;
> >                 }
> > diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c
> > index dea1dba441fe7..779df26dc81ae 100644
> > --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c
> > +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c
> > @@ -83,7 +97,7 @@ static bool _dpu_rm_get_hw_locked(struct dpu_rm *rm, struct dpu_rm_hw_iter *i)
> >         return false;
> >  }
> >
> > -bool dpu_rm_get_hw(struct dpu_rm *rm, struct dpu_rm_hw_iter *i)
> > +static bool dpu_rm_get_hw(struct dpu_rm *rm, struct dpu_rm_hw_iter *i)
> >  {
> >         bool ret;
> >
> > @@ -635,3 +649,16 @@ int dpu_rm_reserve(
> >
> >         return ret;
> >  }
> > +
> > +int dpu_rm_get_assigned_resources(struct dpu_rm *rm, uint32_t enc_id,
>
> Return unsigned int?
>
> > +       enum dpu_hw_blk_type type, struct dpu_hw_blk **blks, int blks_size)
>
> unsigned int blks_size?
>
> > +{
> > +       struct dpu_rm_hw_iter hw_iter;
> > +       int num_blks = 0;
>
> unsigned int?
>
> > +
> > +       dpu_rm_init_hw_iter(&hw_iter, enc_id, type);
> > +       while (num_blks < blks_size && dpu_rm_get_hw(rm, &hw_iter))
> > +               blks[num_blks++] = hw_iter.blk->hw;
> > +
> > +       return num_blks;
>
> It's not possible for it to be negative number right?
>
> > +}
> > diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.h
> > index 9c580a0170946..982b91e272275 100644
> > --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.h
> > +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.h
> > @@ -24,26 +24,6 @@ struct dpu_rm {
> >         struct mutex rm_lock;
> >  };
> >
> > -/**
> > - *  struct dpu_rm_hw_blk - resource manager internal structure
> > - *     forward declaration for single iterator definition without void pointer
> > - */
> > -struct dpu_rm_hw_blk;
> > -
> > -/**
> > - * struct dpu_rm_hw_iter - iterator for use with dpu_rm
> > - * @hw: dpu_hw object requested, or NULL on failure
> > - * @blk: dpu_rm internal block representation. Clients ignore. Used as iterator.
> > - * @enc_id: DRM ID of Encoder client wishes to search for, or 0 for Any Encoder
>
> Why is Encoder and Any capitalized?
>
> > - * @type: Hardware Block Type client wishes to search for.
> > - */
> > -struct dpu_rm_hw_iter {
> > -       void *hw;
> > -       struct dpu_rm_hw_blk *blk;
> > -       uint32_t enc_id;
> > -       enum dpu_hw_blk_type type;
> > -};
> > -
> >  /**
> >   * dpu_rm_init - Read hardware catalog and create reservation tracking objects
> >   *     for all HW blocks.
> > @@ -93,28 +73,9 @@ int dpu_rm_reserve(struct dpu_rm *rm,
> >  void dpu_rm_release(struct dpu_rm *rm, struct drm_encoder *enc);
> >
> >  /**
> > - * dpu_rm_init_hw_iter - setup given iterator for new iteration over hw list
> > - *     using dpu_rm_get_hw
> > - * @iter: iter object to initialize
> > - * @enc_id: DRM ID of Encoder client wishes to search for, or 0 for Any Encoder
> > - * @type: Hardware Block Type client wishes to search for.
>
> Ah I guess it's copied from here.

^ permalink raw reply	[flat|nested] 7+ messages in thread

end of thread, other threads:[~2020-02-25 19:41 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-02-19 17:42 [PATCH 1/4] drm/msm/dpu: Remove unused function arguments Drew Davenport
2020-02-19 17:42 ` [PATCH 2/4] drm/msm/dpu: Refactor rm iterator Drew Davenport
2020-02-25 19:33   ` Stephen Boyd
2020-02-25 19:41     ` Rob Clark
2020-02-19 17:42 ` [PATCH 3/4] drm/msm/dpu: Refactor resource manager Drew Davenport
2020-02-19 17:42 ` [PATCH 4/4] drm/msm/dpu: Track resources in global state Drew Davenport
2020-02-25 19:27 ` [PATCH 1/4] drm/msm/dpu: Remove unused function arguments Stephen Boyd

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).