disp: msm: add split-vote support with interconnect

Add support for parsing ebi and llcc data busses for split vote
support as only the mnoc interconnect data bus was getting
parsed correctly.

Change-Id: I331bbcb0c61b341d935882f5560702f6317fc2a7
Signed-off-by: Steve Cohen <cohens@codeaurora.org>
This commit is contained in:
Steve Cohen
2020-03-25 02:45:32 -04:00
parent 6b664b94bc
commit 85c0c75dd7
2 changed files with 147 additions and 125 deletions

View File

@@ -63,22 +63,25 @@ TRACE_EVENT(sde_perf_set_ot,
TRACE_EVENT(sde_perf_update_bus, TRACE_EVENT(sde_perf_update_bus,
TP_PROTO(u32 bus_id, unsigned long long ab_quota, TP_PROTO(u32 bus_id, unsigned long long ab_quota,
unsigned long long ib_quota), unsigned long long ib_quota, u32 paths),
TP_ARGS(bus_id, ab_quota, ib_quota), TP_ARGS(bus_id, ab_quota, ib_quota, paths),
TP_STRUCT__entry( TP_STRUCT__entry(
__field(u32, bus_id); __field(u32, bus_id);
__field(u64, ab_quota) __field(u64, ab_quota)
__field(u64, ib_quota) __field(u64, ib_quota)
__field(u32, paths)
), ),
TP_fast_assign( TP_fast_assign(
__entry->bus_id = bus_id; __entry->bus_id = bus_id;
__entry->ab_quota = ab_quota; __entry->ab_quota = ab_quota;
__entry->ib_quota = ib_quota; __entry->ib_quota = ib_quota;
__entry->paths = paths;
), ),
TP_printk("Request bus_id:%d ab=%llu ib=%llu", TP_printk("Request bus_id:%d ab=%llu ib=%llu paths=%d",
__entry->bus_id, __entry->bus_id,
__entry->ab_quota, __entry->ab_quota,
__entry->ib_quota) __entry->ib_quota,
__entry->paths)
) )

View File

@@ -290,22 +290,21 @@ static int _sde_power_data_bus_set_quota(
struct sde_power_data_bus_handle *pdbus, struct sde_power_data_bus_handle *pdbus,
u64 in_ab_quota, u64 in_ib_quota) u64 in_ab_quota, u64 in_ib_quota)
{ {
int rc = 0, i = 0, j = 0; int rc = 0, i = 0;
u32 paths = pdbus->data_paths_cnt;
if (!pdbus->data_paths_cnt) { if (!paths || paths > DATA_BUS_PATH_MAX) {
pr_err("invalid data bus handle\n"); pr_err("invalid data bus handle, paths %d\n", paths);
return -EINVAL; return -EINVAL;
} }
pr_debug("ab=%llu ib=%llu\n", in_ab_quota, in_ib_quota); in_ab_quota = div_u64(in_ab_quota, paths);
in_ab_quota = div_u64(in_ab_quota, pdbus->data_paths_cnt);
SDE_ATRACE_BEGIN("msm_bus_scale_req"); SDE_ATRACE_BEGIN("msm_bus_scale_req");
for (i = 0; i < pdbus->data_paths_cnt; i++) { for (i = 0; i < paths; i++) {
if (pdbus->data_bus_hdl[i]) { if (pdbus->data_bus_hdl[i]) {
rc = icc_set_bw(pdbus->data_bus_hdl[i], rc = icc_set_bw(pdbus->data_bus_hdl[i], in_ab_quota,
in_ab_quota, in_ib_quota); in_ib_quota);
if (rc) if (rc)
goto err; goto err;
} }
@@ -318,9 +317,9 @@ static int _sde_power_data_bus_set_quota(
return rc; return rc;
err: err:
for (j = 0; j < i; j++) for (; i >= 0; --i)
if (pdbus->data_bus_hdl[j]) if (pdbus->data_bus_hdl[i])
icc_set_bw(pdbus->data_bus_hdl[j], icc_set_bw(pdbus->data_bus_hdl[i],
pdbus->curr_val.ab, pdbus->curr_val.ab,
pdbus->curr_val.ib); pdbus->curr_val.ib);
@@ -335,116 +334,154 @@ int sde_power_data_bus_set_quota(struct sde_power_handle *phandle,
u32 bus_id, u64 ab_quota, u64 ib_quota) u32 bus_id, u64 ab_quota, u64 ib_quota)
{ {
int rc = 0; int rc = 0;
u32 paths;
if (!phandle || bus_id >= SDE_POWER_HANDLE_DBUS_ID_MAX) { if (!phandle || bus_id >= SDE_POWER_HANDLE_DBUS_ID_MAX) {
pr_err("invalid parameters\n"); pr_err("invalid parameters\n");
return -EINVAL; return -EINVAL;
} }
paths = phandle->data_bus_handle[bus_id].data_paths_cnt;
if (!paths)
goto skip_vote;
trace_sde_perf_update_bus(bus_id, ab_quota, ib_quota, paths);
mutex_lock(&phandle->phandle_lock); mutex_lock(&phandle->phandle_lock);
rc = _sde_power_data_bus_set_quota(&phandle->data_bus_handle[bus_id],
trace_sde_perf_update_bus(bus_id, ab_quota, ib_quota); ab_quota, ib_quota);
if (phandle->data_bus_handle[bus_id].data_paths_cnt > 0)
rc = _sde_power_data_bus_set_quota(
&phandle->data_bus_handle[bus_id], ab_quota, ib_quota);
mutex_unlock(&phandle->phandle_lock); mutex_unlock(&phandle->phandle_lock);
skip_vote:
pr_debug("bus=%d, ab=%llu, ib=%llu, paths=%d\n", bus_id, ab_quota,
ib_quota, paths);
return rc; return rc;
} }
static void sde_power_data_bus_unregister( /**
struct sde_power_data_bus_handle *pdbus) * sde_power_icc_get - get the interconnect path for the given bus_name
* @pdev - platform device
* @bus_name - bus name for the corresponding interconnect
* @path - the icc_path object we want to obtain for this @bus_name (output)
* @count - if given, incremented only if the path was successfully retrieved
**/
static int sde_power_icc_get(struct platform_device *pdev,
const char *bus_name, struct icc_path **path, u32 *count)
{ {
int i = 0; int rc = of_property_match_string(pdev->dev.of_node,
for (i = 0; i < pdbus->data_paths_cnt; i++) {
if (pdbus->data_bus_hdl[i]) {
icc_put(pdbus->data_bus_hdl[i]);
pdbus->data_bus_hdl[i] = NULL;
}
}
}
static int sde_power_data_bus_parse(struct platform_device *pdev,
struct sde_power_data_bus_handle *pdbus, const char *name)
{
char bus_name[32];
int i = 0, ret = 0;
for (i = 0; i < DATA_BUS_PATH_MAX; i++) {
snprintf(bus_name, sizeof(bus_name), "%s%d", name, i);
ret = of_property_match_string(pdev->dev.of_node,
"interconnect-names", bus_name); "interconnect-names", bus_name);
if (ret < 0) {
if (!pdbus->data_paths_cnt) {
pr_debug("sde: bus %s dt node missing\n", bus_name);
return 0;
} else
goto end;
} else
pdbus->data_bus_hdl[i] = of_icc_get(&pdev->dev, bus_name);
if (IS_ERR_OR_NULL(pdbus->data_bus_hdl[i])) { /* bus_names are optional for any given device node, skip if missing */
pr_debug("icc get path failed for %s\n", bus_name);
break;
}
pdbus->data_paths_cnt++;
}
if (!pdbus->data_paths_cnt) {
pr_err("get none data bus path for %s\n", name);
return -EINVAL;
}
end:
if (of_find_property(pdev->dev.of_node,
"qcom,msm-bus,active-only", NULL)) {
pdbus->bus_active_only = true;
for (i = 0; i < pdbus->data_paths_cnt; i++) {
icc_set_tag(pdbus->data_bus_hdl[i],
QCOM_ICC_TAG_ACTIVE_ONLY);
}
}
pr_debug("register %s data_bus success, path number=%d\n",
name, pdbus->data_paths_cnt);
return 0;
}
static int sde_power_reg_bus_parse(struct platform_device *pdev,
struct sde_power_handle *phandle)
{
int rc = 0;
const char *bus_name = "qcom,sde-reg-bus";
/* not all clients need reg-bus, skip if not referenced for this node */
rc = of_property_match_string(pdev->dev.of_node,
"interconnect-names", bus_name);
if (rc < 0) if (rc < 0)
goto end; goto end;
phandle->reg_bus_hdl = of_icc_get(&pdev->dev, bus_name); *path = of_icc_get(&pdev->dev, bus_name);
if (IS_ERR_OR_NULL(phandle->reg_bus_hdl)) { if (IS_ERR_OR_NULL(*path)) {
rc = PTR_ERR(phandle->reg_bus_hdl); rc = PTR_ERR(*path);
pr_err("bus %s parsing failed, rc:%d\n", bus_name, rc); pr_err("bus %s parsing failed, rc:%d\n", bus_name, rc);
phandle->reg_bus_hdl = NULL; *path = NULL;
return rc; return rc;
} }
if (count)
(*count)++;
end: end:
pr_debug("bus %s dt node %s(%d), hdl is %s\n", pr_debug("bus %s dt node %s(%d), icc_path is %s, count:%d\n",
bus_name, rc < 0 ? "missing" : "found", rc, bus_name, rc < 0 ? "missing" : "found", rc,
phandle->reg_bus_hdl ? "valid" : "NULL"); *path ? "valid" : "NULL", count ? *count : -1);
return 0; return 0;
} }
static void sde_power_reg_bus_unregister(struct icc_path *reg_bus_hdl) static int sde_power_mnoc_bus_parse(struct platform_device *pdev,
struct sde_power_data_bus_handle *pdbus, const char *name)
{ {
if (reg_bus_hdl) int i, rc = 0;
icc_put(reg_bus_hdl); char bus_name[32];
for (i = 0; i < DATA_BUS_PATH_MAX; ++i) {
snprintf(bus_name, sizeof(bus_name), "%s%d", name, i);
rc = sde_power_icc_get(pdev, bus_name, &pdbus->data_bus_hdl[i],
&pdbus->data_paths_cnt);
if (rc)
break;
}
/* at least one databus path is required */
if (!pdbus->data_paths_cnt) {
pr_err("missing required interconnect:%s, rc:%d\n", name, rc);
return -EINVAL;
} else if (rc) {
pr_info("ignoring error %d for non-primary data path\n", rc);
rc = 0;
}
return rc;
}
static int sde_power_bus_parse(struct platform_device *pdev,
struct sde_power_handle *phandle)
{
int i, j, rc = 0;
bool active_only = false;
const char *bus_name = "qcom,sde-reg-bus";
struct sde_power_data_bus_handle *pdbus = phandle->data_bus_handle;
/* reg bus */
rc = sde_power_icc_get(pdev, bus_name, &phandle->reg_bus_hdl, NULL);
if (rc)
return rc;
/* data buses */
if (of_find_property(pdev->dev.of_node,
"qcom,msm-bus,active-only", NULL))
active_only = true;
for (i = SDE_POWER_HANDLE_DBUS_ID_MNOC;
i < SDE_POWER_HANDLE_DBUS_ID_MAX; ++i) {
if (i == SDE_POWER_HANDLE_DBUS_ID_MNOC)
rc = sde_power_mnoc_bus_parse(pdev, &pdbus[i],
data_bus_name[i]);
else
rc = sde_power_icc_get(pdev, data_bus_name[i],
&pdbus[i].data_bus_hdl[0],
&pdbus[i].data_paths_cnt);
if (rc)
break;
if (active_only) {
pdbus[i].bus_active_only = true;
for (j = 0; j < pdbus[i].data_paths_cnt; ++j)
icc_set_tag(pdbus[i].data_bus_hdl[j],
QCOM_ICC_TAG_ACTIVE_ONLY);
}
pr_debug("found %d paths for %s\n", pdbus[i].data_paths_cnt,
data_bus_name[i]);
}
return rc;
}
static void sde_power_bus_unregister(struct sde_power_handle *phandle)
{
int i, j;
struct sde_power_data_bus_handle *pdbus = phandle->data_bus_handle;
icc_put(phandle->reg_bus_hdl);
phandle->reg_bus_hdl = NULL;
for (i = SDE_POWER_HANDLE_DBUS_ID_MAX - 1;
i >= SDE_POWER_HANDLE_DBUS_ID_MNOC; i--) {
for (j = 0; j < pdbus[i].data_paths_cnt; j++) {
if (pdbus[i].data_bus_hdl[j]) {
icc_put(pdbus[i].data_bus_hdl[j]);
pdbus[i].data_bus_hdl[j] = NULL;
}
}
}
} }
static int sde_power_reg_bus_update(struct icc_path *reg_bus_hdl, static int sde_power_reg_bus_update(struct icc_path *reg_bus_hdl,
@@ -469,7 +506,7 @@ static int sde_power_reg_bus_update(struct icc_path *reg_bus_hdl,
int sde_power_resource_init(struct platform_device *pdev, int sde_power_resource_init(struct platform_device *pdev,
struct sde_power_handle *phandle) struct sde_power_handle *phandle)
{ {
int rc = 0, i; int rc = 0;
struct dss_module_power *mp; struct dss_module_power *mp;
if (!phandle || !pdev) { if (!phandle || !pdev) {
@@ -502,33 +539,21 @@ int sde_power_resource_init(struct platform_device *pdev,
rc = msm_dss_get_clk(&pdev->dev, mp->clk_config, mp->num_clk); rc = msm_dss_get_clk(&pdev->dev, mp->clk_config, mp->num_clk);
if (rc) { if (rc) {
pr_err("clock get failed rc=%d\n", rc); pr_err("clock get failed rc=%d\n", rc);
goto clk_err; goto clkget_err;
} }
rc = msm_dss_clk_set_rate(mp->clk_config, mp->num_clk); rc = msm_dss_clk_set_rate(mp->clk_config, mp->num_clk);
if (rc) { if (rc) {
pr_err("clock set rate failed rc=%d\n", rc); pr_err("clock set rate failed rc=%d\n", rc);
goto bus_err; goto clkset_err;
} }
rc = sde_power_reg_bus_parse(pdev, phandle); rc = sde_power_bus_parse(pdev, phandle);
if (rc) { if (rc) {
pr_err("register bus parse failed rc=%d\n", rc); pr_err("bus parse failed rc=%d\n", rc);
goto bus_err; goto bus_err;
} }
for (i = SDE_POWER_HANDLE_DBUS_ID_MNOC;
i < SDE_POWER_HANDLE_DBUS_ID_MAX; i++) {
rc = sde_power_data_bus_parse(pdev,
&phandle->data_bus_handle[i],
data_bus_name[i]);
if (rc) {
pr_err("register data bus parse failed id=%d rc=%d\n",
i, rc);
goto data_bus_err;
}
}
INIT_LIST_HEAD(&phandle->event_list); INIT_LIST_HEAD(&phandle->event_list);
phandle->rsc_client = NULL; phandle->rsc_client = NULL;
@@ -538,13 +563,11 @@ int sde_power_resource_init(struct platform_device *pdev,
return rc; return rc;
data_bus_err:
for (i--; i >= 0; i--)
sde_power_data_bus_unregister(&phandle->data_bus_handle[i]);
sde_power_reg_bus_unregister(phandle->reg_bus_hdl);
bus_err: bus_err:
sde_power_bus_unregister(phandle);
clkset_err:
msm_dss_put_clk(mp->clk_config, mp->num_clk); msm_dss_put_clk(mp->clk_config, mp->num_clk);
clk_err: clkget_err:
msm_dss_config_vreg(&pdev->dev, mp->vreg_config, mp->num_vreg, 0); msm_dss_config_vreg(&pdev->dev, mp->vreg_config, mp->num_vreg, 0);
vreg_err: vreg_err:
if (mp->vreg_config) if (mp->vreg_config)
@@ -563,7 +586,6 @@ void sde_power_resource_deinit(struct platform_device *pdev,
{ {
struct dss_module_power *mp; struct dss_module_power *mp;
struct sde_power_event *curr_event, *next_event; struct sde_power_event *curr_event, *next_event;
int i;
if (!phandle || !pdev) { if (!phandle || !pdev) {
pr_err("invalid input param\n"); pr_err("invalid input param\n");
@@ -582,10 +604,7 @@ void sde_power_resource_deinit(struct platform_device *pdev,
} }
mutex_unlock(&phandle->phandle_lock); mutex_unlock(&phandle->phandle_lock);
for (i = 0; i < SDE_POWER_HANDLE_DBUS_ID_MAX; i++) sde_power_bus_unregister(phandle);
sde_power_data_bus_unregister(&phandle->data_bus_handle[i]);
sde_power_reg_bus_unregister(phandle->reg_bus_hdl);
msm_dss_put_clk(mp->clk_config, mp->num_clk); msm_dss_put_clk(mp->clk_config, mp->num_clk);