msm: msm_bus: Add ACV voting
Vote on behalf of clients with requests to ebi_slv as destination,
ACV is one-hot encoded to indicate which master port is actively
requesting bandwidth to the ddr controller. Currently using
DRV voted on as an indicator for ACV coding.
Change-Id: I5e3dc56e34e3d748e73952c65abca739cc62458d
Signed-off-by: David Dai <daidavid1@codeaurora.org>
diff --git a/drivers/soc/qcom/msm_bus/msm_bus_arb_rpmh.c b/drivers/soc/qcom/msm_bus/msm_bus_arb_rpmh.c
index bf5a526..9d0adbb 100644
--- a/drivers/soc/qcom/msm_bus/msm_bus_arb_rpmh.c
+++ b/drivers/soc/qcom/msm_bus/msm_bus_arb_rpmh.c
@@ -24,8 +24,10 @@
#define NUM_LNODES 3
#define MAX_STR_CL 50
-#define MSM_BUS_MAS_ALC 144
-#define MSM_BUS_RSC_APPS 8000
+#define MSM_BUS_MAS_ALC 144
+#define MSM_BUS_RSC_APPS 8000
+#define MSM_BUS_RSC_DISP 8001
+#define BCM_TCS_CMD_ACV_APPS 0x8
struct bus_search_type {
struct list_head link;
@@ -127,16 +129,14 @@
goto exit_bcm_add_bus_req;
}
- if (cur_dev->node_info->bcm_req_idx != -1)
- goto exit_bcm_add_bus_req;
-
if (!cur_dev->node_info->num_bcm_devs)
goto exit_bcm_add_bus_req;
for (i = 0; i < cur_dev->node_info->num_bcm_devs; i++) {
+ if (cur_dev->node_info->bcm_req_idx[i] != -1)
+ continue;
bcm_dev = to_msm_bus_node(cur_dev->node_info->bcm_devs[i]);
max_num_lnodes = bcm_dev->bcmdev->num_bus_devs;
-
if (!bcm_dev->num_lnodes) {
bcm_dev->lnode_list = devm_kzalloc(dev,
sizeof(struct link_node) * max_num_lnodes,
@@ -183,7 +183,7 @@
lnode->in_use = 1;
lnode->bus_dev_id = cur_dev->node_info->id;
- cur_dev->node_info->bcm_req_idx = lnode_idx;
+ cur_dev->node_info->bcm_req_idx[i] = lnode_idx;
memset(lnode->lnode_ib, 0, sizeof(uint64_t) * NUM_CTX);
memset(lnode->lnode_ab, 0, sizeof(uint64_t) * NUM_CTX);
}
@@ -483,11 +483,35 @@
return first_hop;
}
+static void bcm_update_acv_req(struct msm_bus_node_device_type *cur_rsc,
+ uint64_t max_ab, uint64_t max_ib,
+ uint64_t *vec_a, uint64_t *vec_b,
+ uint32_t *acv, int ctx)
+{
+ uint32_t acv_bmsk = 0;
+ /*
+ * Base ACV voting on current RSC until mapping is set up in commanddb
+ * that allows us to vote ACV based on master.
+ */
+
+ if (cur_rsc->node_info->id == MSM_BUS_RSC_APPS)
+ acv_bmsk = BCM_TCS_CMD_ACV_APPS;
+
+ if (max_ab == 0 && max_ib == 0)
+ *acv = *acv & ~acv_bmsk;
+ else
+ *acv = *acv | acv_bmsk;
+ *vec_a = 0;
+ *vec_b = *acv;
+}
+
static void bcm_update_bus_req(struct device *dev, int ctx)
{
struct msm_bus_node_device_type *cur_dev = NULL;
struct msm_bus_node_device_type *bcm_dev = NULL;
- int i;
+ struct msm_bus_node_device_type *cur_rsc = NULL;
+
+ int i, j;
uint64_t max_ib = 0;
uint64_t max_ab = 0;
int lnode_idx = 0;
@@ -507,7 +531,7 @@
if (!bcm_dev)
goto exit_bcm_update_bus_req;
- lnode_idx = cur_dev->node_info->bcm_req_idx;
+ lnode_idx = cur_dev->node_info->bcm_req_idx[i];
bcm_dev->lnode_list[lnode_idx].lnode_ib[ctx] =
msm_bus_div64(cur_dev->node_bw[ctx].max_ib *
(uint64_t)bcm_dev->bcmdev->width,
@@ -519,19 +543,19 @@
cur_dev->node_info->agg_params.buswidth *
cur_dev->node_info->agg_params.num_aggports);
- for (i = 0; i < bcm_dev->num_lnodes; i++) {
+ for (j = 0; j < bcm_dev->num_lnodes; j++) {
if (ctx == ACTIVE_CTX) {
max_ib = max(max_ib,
- max(bcm_dev->lnode_list[i].lnode_ib[ACTIVE_CTX],
- bcm_dev->lnode_list[i].lnode_ib[DUAL_CTX]));
+ max(bcm_dev->lnode_list[j].lnode_ib[ACTIVE_CTX],
+ bcm_dev->lnode_list[j].lnode_ib[DUAL_CTX]));
max_ab = max(max_ab,
- bcm_dev->lnode_list[i].lnode_ab[ACTIVE_CTX] +
- bcm_dev->lnode_list[i].lnode_ab[DUAL_CTX]);
+ bcm_dev->lnode_list[j].lnode_ab[ACTIVE_CTX] +
+ bcm_dev->lnode_list[j].lnode_ab[DUAL_CTX]);
} else {
max_ib = max(max_ib,
- bcm_dev->lnode_list[i].lnode_ib[ctx]);
+ bcm_dev->lnode_list[j].lnode_ib[ctx]);
max_ab = max(max_ab,
- bcm_dev->lnode_list[i].lnode_ab[ctx]);
+ bcm_dev->lnode_list[j].lnode_ab[ctx]);
}
}
bcm_dev->node_bw[ctx].max_ab = max_ab;
@@ -540,8 +564,18 @@
max_ab = msm_bus_div64(max_ab, bcm_dev->bcmdev->unit_size);
max_ib = msm_bus_div64(max_ib, bcm_dev->bcmdev->unit_size);
- bcm_dev->node_vec[ctx].vec_a = max_ab;
- bcm_dev->node_vec[ctx].vec_b = max_ib;
+ if (bcm_dev->node_info->id == MSM_BUS_BCM_ACV) {
+ cur_rsc = to_msm_bus_node(bcm_dev->node_info->
+ rsc_devs[0]);
+ bcm_update_acv_req(cur_rsc, max_ab, max_ib,
+ &bcm_dev->node_vec[ctx].vec_a,
+ &bcm_dev->node_vec[ctx].vec_b,
+ &cur_rsc->rscdev->acv[ctx], ctx);
+
+ } else {
+ bcm_dev->node_vec[ctx].vec_a = max_ab;
+ bcm_dev->node_vec[ctx].vec_b = max_ib;
+ }
}
exit_bcm_update_bus_req:
return;
@@ -551,7 +585,8 @@
{
struct msm_bus_node_device_type *cur_dev = NULL;
struct msm_bus_node_device_type *bcm_dev = NULL;
- int i;
+ struct msm_bus_node_device_type *cur_rsc = NULL;
+ int i, j;
uint64_t max_query_ib = 0;
uint64_t max_query_ab = 0;
int lnode_idx = 0;
@@ -571,7 +606,7 @@
if (!bcm_dev)
goto exit_bcm_query_bus_req;
- lnode_idx = cur_dev->node_info->bcm_req_idx;
+ lnode_idx = cur_dev->node_info->bcm_req_idx[i];
bcm_dev->lnode_list[lnode_idx].lnode_query_ib[ctx] =
msm_bus_div64(cur_dev->node_bw[ctx].max_query_ib *
(uint64_t)bcm_dev->bcmdev->width,
@@ -583,25 +618,25 @@
cur_dev->node_info->agg_params.num_aggports *
cur_dev->node_info->agg_params.buswidth);
- for (i = 0; i < bcm_dev->num_lnodes; i++) {
+ for (j = 0; j < bcm_dev->num_lnodes; j++) {
if (ctx == ACTIVE_CTX) {
max_query_ib = max(max_query_ib,
- max(bcm_dev->lnode_list[i].
+ max(bcm_dev->lnode_list[j].
lnode_query_ib[ACTIVE_CTX],
- bcm_dev->lnode_list[i].
+ bcm_dev->lnode_list[j].
lnode_query_ib[DUAL_CTX]));
max_query_ab = max(max_query_ab,
- bcm_dev->lnode_list[i].
+ bcm_dev->lnode_list[j].
lnode_query_ab[ACTIVE_CTX] +
- bcm_dev->lnode_list[i].
+ bcm_dev->lnode_list[j].
lnode_query_ab[DUAL_CTX]);
} else {
max_query_ib = max(max_query_ib,
- bcm_dev->lnode_list[i].
+ bcm_dev->lnode_list[j].
lnode_query_ib[ctx]);
max_query_ab = max(max_query_ab,
- bcm_dev->lnode_list[i].
+ bcm_dev->lnode_list[j].
lnode_query_ab[ctx]);
}
}
@@ -611,6 +646,18 @@
max_query_ib = msm_bus_div64(max_query_ib,
bcm_dev->bcmdev->unit_size);
+ if (bcm_dev->node_info->id == MSM_BUS_BCM_ACV) {
+ cur_rsc = to_msm_bus_node(bcm_dev->node_info->
+ rsc_devs[0]);
+ bcm_update_acv_req(cur_rsc, max_query_ab, max_query_ib,
+ &bcm_dev->node_vec[ctx].query_vec_a,
+ &bcm_dev->node_vec[ctx].query_vec_b,
+ &cur_rsc->rscdev->query_acv[ctx], ctx);
+ } else {
+ bcm_dev->node_vec[ctx].query_vec_a = max_query_ab;
+ bcm_dev->node_vec[ctx].query_vec_b = max_query_ib;
+ }
+
bcm_dev->node_bw[ctx].max_query_ab = max_query_ab;
bcm_dev->node_bw[ctx].max_query_ib = max_query_ib;
}
diff --git a/drivers/soc/qcom/msm_bus/msm_bus_fabric_rpmh.c b/drivers/soc/qcom/msm_bus/msm_bus_fabric_rpmh.c
index c950367..458cf0d 100644
--- a/drivers/soc/qcom/msm_bus/msm_bus_fabric_rpmh.c
+++ b/drivers/soc/qcom/msm_bus/msm_bus_fabric_rpmh.c
@@ -418,8 +418,8 @@
commit = true;
}
tcs_cmd_gen(cur_bcm, &cmdlist_active[k],
- cur_bcm->node_bw[ACTIVE_CTX].max_query_ib,
- cur_bcm->node_bw[ACTIVE_CTX].max_query_ab,
+ cur_bcm->node_vec[ACTIVE_CTX].query_vec_a,
+ cur_bcm->node_vec[ACTIVE_CTX].query_vec_b,
commit);
k++;
}
@@ -433,26 +433,30 @@
{
int ret = 0;
int cur_vcd = 0;
+ int i = 0;
struct msm_bus_node_device_type *cur_bcm = NULL;
if (!cur_dev->node_info->num_bcm_devs)
goto exit_bcm_clist_add;
- cur_bcm = to_msm_bus_node(cur_dev->node_info->bcm_devs[0]);
- cur_vcd = cur_bcm->bcmdev->clk_domain;
+ for (i = 0; i < cur_dev->node_info->num_bcm_devs; i++) {
+ cur_bcm = to_msm_bus_node(cur_dev->node_info->bcm_devs[i]);
+ cur_vcd = cur_bcm->bcmdev->clk_domain;
- if (!cur_bcm->node_info->num_rsc_devs)
- goto exit_bcm_clist_add;
+ if (!cur_bcm->node_info->num_rsc_devs)
+ goto exit_bcm_clist_add;
- if (!cur_rsc)
- cur_rsc = to_msm_bus_node(cur_bcm->node_info->rsc_devs[0]);
+ if (!cur_rsc)
+ cur_rsc = to_msm_bus_node(cur_bcm->node_info->
+ rsc_devs[0]);
- if (!cur_bcm->dirty) {
- list_add_tail(&cur_bcm->link,
+ if (!cur_bcm->dirty) {
+ list_add_tail(&cur_bcm->link,
&cur_rsc->rscdev->bcm_clist[cur_vcd]);
- cur_bcm->dirty = true;
+ cur_bcm->dirty = true;
+ }
+ cur_bcm->updated = false;
}
- cur_bcm->updated = false;
exit_bcm_clist_add:
return ret;
@@ -462,17 +466,20 @@
{
int ret = 0;
int cur_vcd = 0;
+ int i = 0;
struct msm_bus_node_device_type *cur_bcm = NULL;
if (!cur_dev->node_info->num_bcm_devs)
goto exit_bcm_query_list_add;
- cur_bcm = to_msm_bus_node(cur_dev->node_info->bcm_devs[0]);
- cur_vcd = cur_bcm->bcmdev->clk_domain;
+ for (i = 0; i < cur_dev->node_info->num_bcm_devs; i++) {
+ cur_bcm = to_msm_bus_node(cur_dev->node_info->bcm_devs[i]);
+ cur_vcd = cur_bcm->bcmdev->clk_domain;
- if (!cur_bcm->query_dirty)
- list_add_tail(&cur_bcm->query_link,
+ if (!cur_bcm->query_dirty)
+ list_add_tail(&cur_bcm->query_link,
&bcm_query_list_inorder[cur_vcd]);
+ }
exit_bcm_query_list_add:
return ret;
@@ -481,20 +488,23 @@
static int bcm_clist_clean(struct msm_bus_node_device_type *cur_dev)
{
int ret = 0;
+ int i = 0;
struct msm_bus_node_device_type *cur_bcm = NULL;
if (!cur_dev->node_info->num_bcm_devs)
goto exit_bcm_clist_clean;
- cur_bcm = to_msm_bus_node(cur_dev->node_info->bcm_devs[0]);
+ for (i = 0; i < cur_dev->node_info->num_bcm_devs; i++) {
+ cur_bcm = to_msm_bus_node(cur_dev->node_info->bcm_devs[i]);
- if (cur_bcm->node_vec[DUAL_CTX].vec_a == 0 &&
+ if (cur_bcm->node_vec[DUAL_CTX].vec_a == 0 &&
cur_bcm->node_vec[ACTIVE_CTX].vec_a == 0 &&
cur_bcm->node_vec[DUAL_CTX].vec_b == 0 &&
cur_bcm->node_vec[ACTIVE_CTX].vec_b == 0 &&
init_time == false) {
- cur_bcm->dirty = false;
- list_del_init(&cur_bcm->link);
+ cur_bcm->dirty = false;
+ list_del_init(&cur_bcm->link);
+ }
}
exit_bcm_clist_clean:
@@ -504,15 +514,18 @@
static int bcm_query_list_clean(struct msm_bus_node_device_type *cur_dev)
{
int ret = 0;
+ int i = 0;
struct msm_bus_node_device_type *cur_bcm = NULL;
if (!cur_dev->node_info->num_bcm_devs)
goto exit_bcm_clist_add;
- cur_bcm = to_msm_bus_node(cur_dev->node_info->bcm_devs[0]);
+ for (i = 0; i < cur_dev->node_info->num_bcm_devs; i++) {
+ cur_bcm = to_msm_bus_node(cur_dev->node_info->bcm_devs[i]);
- cur_bcm->query_dirty = false;
- list_del_init(&cur_bcm->query_link);
+ cur_bcm->query_dirty = false;
+ list_del_init(&cur_bcm->query_link);
+ }
exit_bcm_clist_add:
return ret;
@@ -1081,7 +1094,7 @@
static int msm_bus_copy_node_info(struct msm_bus_node_device_type *pdata,
struct device *bus_dev)
{
- int ret = 0;
+ int ret = 0, i = 0;
struct msm_bus_node_info_type *node_info = NULL;
struct msm_bus_node_info_type *pdata_node_info = NULL;
struct msm_bus_node_device_type *bus_node = NULL;
@@ -1100,7 +1113,17 @@
node_info->name = pdata_node_info->name;
node_info->id = pdata_node_info->id;
- node_info->bcm_req_idx = -1;
+ node_info->bcm_req_idx = devm_kzalloc(bus_dev,
+ sizeof(int) * pdata_node_info->num_bcm_devs,
+ GFP_KERNEL);
+ if (!node_info->bcm_req_idx) {
+ ret = -ENOMEM;
+ goto exit_copy_node_info;
+ }
+
+ for (i = 0; i < pdata_node_info->num_bcm_devs; i++)
+ node_info->bcm_req_idx[i] = -1;
+
node_info->bus_device_id = pdata_node_info->bus_device_id;
node_info->mas_rpm_id = pdata_node_info->mas_rpm_id;
node_info->slv_rpm_id = pdata_node_info->slv_rpm_id;
diff --git a/drivers/soc/qcom/msm_bus/msm_bus_rpmh.h b/drivers/soc/qcom/msm_bus/msm_bus_rpmh.h
index fad7afa..f7f17c3 100644
--- a/drivers/soc/qcom/msm_bus/msm_bus_rpmh.h
+++ b/drivers/soc/qcom/msm_bus/msm_bus_rpmh.h
@@ -71,12 +71,16 @@
struct nodevector {
uint64_t vec_a;
uint64_t vec_b;
+ uint64_t query_vec_a;
+ uint64_t query_vec_b;
};
struct msm_bus_rsc_device_type {
struct rpmh_client *mbox;
struct list_head bcm_clist[VCD_MAX_CNT];
int req_state;
+ uint32_t acv[NUM_CTX];
+ uint32_t query_acv[NUM_CTX];
};
struct msm_bus_bcm_device_type {
@@ -157,7 +161,7 @@
struct device **black_connections;
struct device **bcm_devs;
struct device **rsc_devs;
- int bcm_req_idx;
+ int *bcm_req_idx;
unsigned int bus_device_id;
struct device *bus_device;
struct rule_update_path_info rule;