Эх сурвалжийг харах

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 <[email protected]>
Steve Cohen 5 жил өмнө
parent
commit
85c0c75dd7
2 өөрчлөгдсөн 133 нэмэгдсэн , 111 устгасан
  1. 7 4
      msm/sde/sde_trace.h
  2. 126 107
      msm/sde_power_handle.c

+ 7 - 4
msm/sde/sde_trace.h

@@ -63,22 +63,25 @@ TRACE_EVENT(sde_perf_set_ot,
 
 TRACE_EVENT(sde_perf_update_bus,
 	TP_PROTO(u32 bus_id, unsigned long long ab_quota,
-	unsigned long long ib_quota),
-	TP_ARGS(bus_id, ab_quota, ib_quota),
+	unsigned long long ib_quota, u32 paths),
+	TP_ARGS(bus_id, ab_quota, ib_quota, paths),
 	TP_STRUCT__entry(
 			__field(u32, bus_id);
 			__field(u64, ab_quota)
 			__field(u64, ib_quota)
+			__field(u32, paths)
 	),
 	TP_fast_assign(
 			__entry->bus_id = bus_id;
 			__entry->ab_quota = ab_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->ab_quota,
-			__entry->ib_quota)
+			__entry->ib_quota,
+			__entry->paths)
 )
 
 

+ 126 - 107
msm/sde_power_handle.c

@@ -290,22 +290,21 @@ static int _sde_power_data_bus_set_quota(
 	struct sde_power_data_bus_handle *pdbus,
 	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) {
-		pr_err("invalid data bus handle\n");
+	if (!paths || paths > DATA_BUS_PATH_MAX) {
+		pr_err("invalid data bus handle, paths %d\n", paths);
 		return -EINVAL;
 	}
 
-	pr_debug("ab=%llu ib=%llu\n", in_ab_quota, in_ib_quota);
-
-	in_ab_quota = div_u64(in_ab_quota, pdbus->data_paths_cnt);
+	in_ab_quota = div_u64(in_ab_quota, paths);
 
 	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]) {
-			rc = icc_set_bw(pdbus->data_bus_hdl[i],
-				in_ab_quota, in_ib_quota);
+			rc = icc_set_bw(pdbus->data_bus_hdl[i], in_ab_quota,
+					in_ib_quota);
 			if (rc)
 				goto err;
 		}
@@ -318,9 +317,9 @@ static int _sde_power_data_bus_set_quota(
 
 	return rc;
 err:
-	for (j = 0; j < i; j++)
-		if (pdbus->data_bus_hdl[j])
-			icc_set_bw(pdbus->data_bus_hdl[j],
+	for (; i >= 0; --i)
+		if (pdbus->data_bus_hdl[i])
+			icc_set_bw(pdbus->data_bus_hdl[i],
 				   pdbus->curr_val.ab,
 				   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)
 {
 	int rc = 0;
+	u32 paths;
 
 	if (!phandle || bus_id >= SDE_POWER_HANDLE_DBUS_ID_MAX) {
 		pr_err("invalid parameters\n");
 		return -EINVAL;
 	}
 
-	mutex_lock(&phandle->phandle_lock);
-
-	trace_sde_perf_update_bus(bus_id, ab_quota, ib_quota);
+	paths = phandle->data_bus_handle[bus_id].data_paths_cnt;
+	if (!paths)
+		goto skip_vote;
 
-	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);
+	trace_sde_perf_update_bus(bus_id, ab_quota, ib_quota, paths);
 
+	mutex_lock(&phandle->phandle_lock);
+	rc = _sde_power_data_bus_set_quota(&phandle->data_bus_handle[bus_id],
+			ab_quota, ib_quota);
 	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;
 }
 
-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,
+			"interconnect-names", bus_name);
 
-	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;
-		}
+	/* bus_names are optional for any given device node, skip if missing */
+	if (rc < 0)
+		goto end;
+
+	*path = of_icc_get(&pdev->dev, bus_name);
+	if (IS_ERR_OR_NULL(*path)) {
+		rc = PTR_ERR(*path);
+		pr_err("bus %s parsing failed, rc:%d\n", bus_name, rc);
+		*path = NULL;
+		return rc;
 	}
+
+	if (count)
+		(*count)++;
+
+end:
+	pr_debug("bus %s dt node %s(%d), icc_path is %s, count:%d\n",
+			bus_name, rc < 0 ? "missing" : "found", rc,
+			*path ? "valid" : "NULL", count ? *count : -1);
+	return 0;
 }
 
-static int sde_power_data_bus_parse(struct platform_device *pdev,
+static int sde_power_mnoc_bus_parse(struct platform_device *pdev,
 	struct sde_power_data_bus_handle *pdbus, const char *name)
 {
+	int i, rc = 0;
 	char bus_name[32];
-	int i = 0, ret = 0;
 
-	for (i = 0; i < DATA_BUS_PATH_MAX; i++) {
+	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);
-		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])) {
-			pr_debug("icc get path failed for %s\n", bus_name);
+		rc = sde_power_icc_get(pdev, bus_name, &pdbus->data_bus_hdl[i],
+				&pdbus->data_paths_cnt);
+		if (rc)
 			break;
-		}
-		pdbus->data_paths_cnt++;
 	}
 
+	/* at least one databus path is required */
 	if (!pdbus->data_paths_cnt) {
-		pr_err("get none data bus path for %s\n", name);
+		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;
 	}
 
-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;
+	return rc;
 }
 
-static int sde_power_reg_bus_parse(struct platform_device *pdev,
+static int sde_power_bus_parse(struct platform_device *pdev,
 	struct sde_power_handle *phandle)
 {
-	int rc = 0;
+	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;
 
-	/* 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)
-		goto end;
-
-	phandle->reg_bus_hdl = of_icc_get(&pdev->dev, bus_name);
-	if (IS_ERR_OR_NULL(phandle->reg_bus_hdl)) {
-		rc = PTR_ERR(phandle->reg_bus_hdl);
-		pr_err("bus %s parsing failed, rc:%d\n", bus_name, rc);
-		phandle->reg_bus_hdl = NULL;
+	/* 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]);
 	}
 
-end:
-	pr_debug("bus %s dt node %s(%d), hdl is %s\n",
-			bus_name, rc < 0 ? "missing" : "found", rc,
-			phandle->reg_bus_hdl ? "valid" : "NULL");
-	return 0;
+	return rc;
 }
 
-static void sde_power_reg_bus_unregister(struct icc_path *reg_bus_hdl)
+static void sde_power_bus_unregister(struct sde_power_handle *phandle)
 {
-	if (reg_bus_hdl)
-		icc_put(reg_bus_hdl);
+	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,
@@ -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,
 	struct sde_power_handle *phandle)
 {
-	int rc = 0, i;
+	int rc = 0;
 	struct dss_module_power *mp;
 
 	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);
 	if (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);
 	if (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) {
-		pr_err("register bus parse failed rc=%d\n", rc);
+		pr_err("bus parse failed rc=%d\n", rc);
 		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);
 
 	phandle->rsc_client = NULL;
@@ -538,13 +563,11 @@ int sde_power_resource_init(struct platform_device *pdev,
 
 	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:
+	sde_power_bus_unregister(phandle);
+clkset_err:
 	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);
 vreg_err:
 	if (mp->vreg_config)
@@ -563,7 +586,6 @@ void sde_power_resource_deinit(struct platform_device *pdev,
 {
 	struct dss_module_power *mp;
 	struct sde_power_event *curr_event, *next_event;
-	int i;
 
 	if (!phandle || !pdev) {
 		pr_err("invalid input param\n");
@@ -582,10 +604,7 @@ void sde_power_resource_deinit(struct platform_device *pdev,
 	}
 	mutex_unlock(&phandle->phandle_lock);
 
-	for (i = 0; i < SDE_POWER_HANDLE_DBUS_ID_MAX; i++)
-		sde_power_data_bus_unregister(&phandle->data_bus_handle[i]);
-
-	sde_power_reg_bus_unregister(phandle->reg_bus_hdl);
+	sde_power_bus_unregister(phandle);
 
 	msm_dss_put_clk(mp->clk_config, mp->num_clk);