summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLloyd Atkinson <latkinso@codeaurora.org>2016-08-31 10:04:02 -0400
committerGerrit - the friendly Code Review server <code-review@localhost>2016-09-06 11:33:19 -0700
commitd7143d28ce99f8bf39c8675cbab0aba63383ea11 (patch)
tree28e776d9a72399b5a604c2f26ac3239579286fc1
parentdbf0d50ee39b43f4f911080010135fcdcada0eaf (diff)
drm/msm/sde: improve resource manager hw block lookup time
Move hardware blocks tracking in the resource manager to use one list per hardware block type to reduce list traversal cost when looking for a specific hardware block type. Change-Id: I5b574c7ecd80054a26937a95531a28c097d52c25 Signed-off-by: Lloyd Atkinson <latkinso@codeaurora.org>
-rw-r--r--drivers/gpu/drm/msm/sde/sde_rm.c94
-rw-r--r--drivers/gpu/drm/msm/sde/sde_rm.h5
2 files changed, 61 insertions, 38 deletions
diff --git a/drivers/gpu/drm/msm/sde/sde_rm.c b/drivers/gpu/drm/msm/sde/sde_rm.c
index 54f0e3a5d65c..0039a005a975 100644
--- a/drivers/gpu/drm/msm/sde/sde_rm.c
+++ b/drivers/gpu/drm/msm/sde/sde_rm.c
@@ -92,6 +92,7 @@ static void _sde_rm_print_rsvps(struct sde_rm *rm, const char *msg)
{
struct sde_rm_rsvp *rsvp;
struct sde_rm_hw_blk *blk;
+ enum sde_hw_blk_type type;
SDE_DEBUG("%s\n", msg);
@@ -99,16 +100,18 @@ static void _sde_rm_print_rsvps(struct sde_rm *rm, const char *msg)
SDE_DEBUG("%s rsvp[s%ue%u] topology %d\n", msg, rsvp->seq,
rsvp->enc_id, rsvp->topology);
- list_for_each_entry(blk, &rm->hw_blks, list) {
- if (!blk->rsvp && !blk->rsvp_nxt)
- continue;
+ for (type = 0; type < SDE_HW_BLK_MAX; type++) {
+ list_for_each_entry(blk, &rm->hw_blks[type], list) {
+ if (!blk->rsvp && !blk->rsvp_nxt)
+ continue;
- SDE_DEBUG("%s rsvp[s%ue%u->s%ue%u] %s %d\n", msg,
- (blk->rsvp) ? blk->rsvp->seq : 0,
- (blk->rsvp) ? blk->rsvp->enc_id : 0,
- (blk->rsvp_nxt) ? blk->rsvp_nxt->seq : 0,
- (blk->rsvp_nxt) ? blk->rsvp_nxt->enc_id : 0,
- blk->type_name, blk->id);
+ SDE_DEBUG("%s rsvp[s%ue%u->s%ue%u] %s %d\n", msg,
+ (blk->rsvp) ? blk->rsvp->seq : 0,
+ (blk->rsvp) ? blk->rsvp->enc_id : 0,
+ (blk->rsvp_nxt) ? blk->rsvp_nxt->seq : 0,
+ (blk->rsvp_nxt) ? blk->rsvp_nxt->enc_id : 0,
+ blk->type_name, blk->id);
+ }
}
}
@@ -129,25 +132,31 @@ void sde_rm_init_hw_iter(
bool sde_rm_get_hw(struct sde_rm *rm, struct sde_rm_hw_iter *i)
{
+ struct list_head *blk_list;
+
if (!rm || !i || i->type >= SDE_HW_BLK_MAX) {
SDE_ERROR("invalid rm\n");
return false;
}
i->hw = NULL;
+ blk_list = &rm->hw_blks[i->type];
- if (i->blk && (&i->blk->list == &rm->hw_blks)) {
+ if (i->blk && (&i->blk->list == blk_list)) {
SDE_ERROR("attempt resume iteration past last\n");
return false;
}
- i->blk = list_prepare_entry(i->blk, &rm->hw_blks, list);
+ i->blk = list_prepare_entry(i->blk, blk_list, list);
- list_for_each_entry_continue(i->blk, &rm->hw_blks, list) {
+ list_for_each_entry_continue(i->blk, blk_list, list) {
struct sde_rm_rsvp *rsvp = i->blk->rsvp;
- if (i->blk->type != i->type)
- continue;
+ if (i->blk->type != i->type) {
+ SDE_ERROR("found incorrect block type %d on %d list\n",
+ i->blk->type, i->type);
+ return false;
+ }
if ((i->enc_id == 0) || (rsvp && rsvp->enc_id == i->enc_id)) {
i->hw = i->blk->hw;
@@ -203,6 +212,7 @@ int sde_rm_destroy(struct sde_rm *rm)
struct sde_rm_rsvp *rsvp_cur, *rsvp_nxt;
struct sde_rm_hw_blk *hw_cur, *hw_nxt;
+ enum sde_hw_blk_type type;
if (!rm) {
SDE_ERROR("invalid rm\n");
@@ -214,10 +224,14 @@ int sde_rm_destroy(struct sde_rm *rm)
kfree(rsvp_cur);
}
- list_for_each_entry_safe(hw_cur, hw_nxt, &rm->hw_blks, list) {
- list_del(&hw_cur->list);
- _sde_rm_hw_destroy(hw_cur->type, hw_cur->hw);
- kfree(hw_cur);
+
+ for (type = 0; type < SDE_HW_BLK_MAX; type++) {
+ list_for_each_entry_safe(hw_cur, hw_nxt, &rm->hw_blks[type],
+ list) {
+ list_del(&hw_cur->list);
+ _sde_rm_hw_destroy(hw_cur->type, hw_cur->hw);
+ kfree(hw_cur);
+ }
}
sde_hw_mdp_destroy(rm->hw_mdp);
@@ -297,7 +311,7 @@ static int _sde_rm_hw_blk_create(
blk->id = id;
blk->catalog = hw_catalog_info;
blk->hw = hw;
- list_add_tail(&blk->list, &rm->hw_blks);
+ list_add_tail(&blk->list, &rm->hw_blks[type]);
return 0;
}
@@ -308,6 +322,7 @@ int sde_rm_init(struct sde_rm *rm,
struct drm_device *dev)
{
int rc, i;
+ enum sde_hw_blk_type type;
if (!rm || !cat || !mmio || !dev) {
SDE_ERROR("invalid kms\n");
@@ -317,7 +332,8 @@ int sde_rm_init(struct sde_rm *rm,
/* Clear, setup lists */
memset(rm, 0, sizeof(*rm));
INIT_LIST_HEAD(&rm->rsvps);
- INIT_LIST_HEAD(&rm->hw_blks);
+ for (type = 0; type < SDE_HW_BLK_MAX; type++)
+ INIT_LIST_HEAD(&rm->hw_blks[type]);
/* Some of the sub-blocks require an mdptop to be created */
rm->hw_mdp = sde_hw_mdptop_init(MDP_TOP, mmio, cat);
@@ -930,6 +946,7 @@ void _sde_rm_release_rsvp(
{
struct sde_rm_rsvp *rsvp_c, *rsvp_n;
struct sde_rm_hw_blk *blk;
+ enum sde_hw_blk_type type;
if (!rsvp)
return;
@@ -943,18 +960,20 @@ void _sde_rm_release_rsvp(
}
}
- list_for_each_entry(blk, &rm->hw_blks, list) {
- if (blk->rsvp == rsvp) {
- blk->rsvp = NULL;
- SDE_DEBUG("rel rsvp %d enc %d %s %d\n",
- rsvp->seq, rsvp->enc_id, blk->type_name,
- blk->id);
- }
- if (blk->rsvp_nxt == rsvp) {
- blk->rsvp_nxt = NULL;
- SDE_DEBUG("rel rsvp_nxt %d enc %d %s %d\n",
- rsvp->seq, rsvp->enc_id, blk->type_name,
- blk->id);
+ for (type = 0; type < SDE_HW_BLK_MAX; type++) {
+ list_for_each_entry(blk, &rm->hw_blks[type], list) {
+ if (blk->rsvp == rsvp) {
+ blk->rsvp = NULL;
+ SDE_DEBUG("rel rsvp %d enc %d %s %d\n",
+ rsvp->seq, rsvp->enc_id,
+ blk->type_name, blk->id);
+ }
+ if (blk->rsvp_nxt == rsvp) {
+ blk->rsvp_nxt = NULL;
+ SDE_DEBUG("rel rsvp_nxt %d enc %d %s %d\n",
+ rsvp->seq, rsvp->enc_id,
+ blk->type_name, blk->id);
+ }
}
}
@@ -1008,6 +1027,7 @@ static int _sde_rm_commit_rsvp(
struct drm_connector_state *conn_state)
{
struct sde_rm_hw_blk *blk;
+ enum sde_hw_blk_type type;
int ret = 0;
ret = msm_property_set_property(
@@ -1019,10 +1039,12 @@ static int _sde_rm_commit_rsvp(
_sde_rm_release_rsvp(rm, rsvp);
/* Swap next rsvp to be the active */
- list_for_each_entry(blk, &rm->hw_blks, list) {
- if (blk->rsvp_nxt) {
- blk->rsvp = blk->rsvp_nxt;
- blk->rsvp_nxt = NULL;
+ for (type = 0; type < SDE_HW_BLK_MAX; type++) {
+ list_for_each_entry(blk, &rm->hw_blks[type], list) {
+ if (blk->rsvp_nxt) {
+ blk->rsvp = blk->rsvp_nxt;
+ blk->rsvp_nxt = NULL;
+ }
}
}
diff --git a/drivers/gpu/drm/msm/sde/sde_rm.h b/drivers/gpu/drm/msm/sde/sde_rm.h
index 5f1726932a84..98e69552ffb2 100644
--- a/drivers/gpu/drm/msm/sde/sde_rm.h
+++ b/drivers/gpu/drm/msm/sde/sde_rm.h
@@ -65,7 +65,8 @@ enum sde_rm_topology_control {
* struct sde_rm - SDE dynamic hardware resource manager
* @dev: device handle for event logging purposes
* @rsvps: list of hardware reservations by each crtc->encoder->connector
- * @hw_blks: list of hardware resources present in the system
+ * @hw_blks: array of lists of hardware resources present in the system, one
+ * list per type of hardware block
* @hw_mdp: hardware object for mdp_top
* @lm_max_width: cached layer mixer maximum width
* @rsvp_next_seq: sequence number for next reservation for debugging purposes
@@ -73,7 +74,7 @@ enum sde_rm_topology_control {
struct sde_rm {
struct drm_device *dev;
struct list_head rsvps;
- struct list_head hw_blks;
+ struct list_head hw_blks[SDE_HW_BLK_MAX];
struct sde_hw_mdp *hw_mdp;
uint32_t lm_max_width;
uint32_t rsvp_next_seq;