summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDavid Dai <daidavid1@codeaurora.org>2016-08-04 13:59:44 -0700
committerGerrit - the friendly Code Review server <code-review@localhost>2016-08-17 15:09:48 -0700
commitb3f54ff633c20ceb4a43686250e718fd8d5c456b (patch)
tree5d08fdd3af3426507b77d77bffd19cea1ef072ee
parent008f057bbab6dd6629b7e1a3b8c67b650a6b9ef1 (diff)
msm: msm_bus: allow QoS clocks to be specified at mas nodes
Allow for greater granularity of QoS clocks enabled when enabling clocks for QoS configuration for each node. Current implementation requires all QoS clocks related to the parent fab to enabled, which works well for mass QoS programming at probe time, but turns on unnecessary clocks when QoS programming defers at initial client request. This fixes an issue where Camera's initial client vote also caused the toggling of mdss gdscs which created a deadlock situation where the notifier callback from MDSS GDSC tries to obtain the same lock held by Camera's call in the same thread. Change-Id: Iff1d086fcfc92a709d198f84227cad9bd6f57646 Signed-off-by: David Dai <daidavid1@codeaurora.org>
-rw-r--r--drivers/soc/qcom/msm_bus/msm_bus_fabric_adhoc.c26
-rw-r--r--drivers/soc/qcom/msm_bus/msm_bus_of_adhoc.c19
2 files changed, 43 insertions, 2 deletions
diff --git a/drivers/soc/qcom/msm_bus/msm_bus_fabric_adhoc.c b/drivers/soc/qcom/msm_bus/msm_bus_fabric_adhoc.c
index 6c890e3b3b4f..fdb84b634254 100644
--- a/drivers/soc/qcom/msm_bus/msm_bus_fabric_adhoc.c
+++ b/drivers/soc/qcom/msm_bus/msm_bus_fabric_adhoc.c
@@ -514,6 +514,10 @@ static int msm_bus_disable_node_qos_clk(struct msm_bus_node_device_type *node)
ret = -ENXIO;
goto exit_disable_node_qos_clk;
}
+
+ for (i = 0; i < node->num_node_qos_clks; i++)
+ ret = disable_nodeclk(&node->node_qos_clks[i]);
+
bus_node = to_msm_bus_node(node->node_info->bus_device);
for (i = 0; i < bus_node->num_node_qos_clks; i++)
@@ -536,6 +540,28 @@ static int msm_bus_enable_node_qos_clk(struct msm_bus_node_device_type *node)
}
bus_node = to_msm_bus_node(node->node_info->bus_device);
+ for (i = 0; i < node->num_node_qos_clks; i++) {
+ if (!node->node_qos_clks[i].enable_only_clk) {
+ rounded_rate =
+ clk_round_rate(
+ node->node_qos_clks[i].clk, 1);
+ ret = setrate_nodeclk(&node->node_qos_clks[i],
+ rounded_rate);
+ if (ret)
+ MSM_BUS_DBG("%s: Failed set rate clk,node %d\n",
+ __func__, node->node_info->id);
+ }
+ ret = enable_nodeclk(&node->node_qos_clks[i],
+ node->node_info->bus_device);
+ if (ret) {
+ MSM_BUS_DBG("%s: Failed to set Qos Clks ret %d\n",
+ __func__, ret);
+ msm_bus_disable_node_qos_clk(node);
+ goto exit_enable_node_qos_clk;
+ }
+
+ }
+
for (i = 0; i < bus_node->num_node_qos_clks; i++) {
if (!bus_node->node_qos_clks[i].enable_only_clk) {
rounded_rate =
diff --git a/drivers/soc/qcom/msm_bus/msm_bus_of_adhoc.c b/drivers/soc/qcom/msm_bus/msm_bus_of_adhoc.c
index 620da95d1be4..571ac98972c1 100644
--- a/drivers/soc/qcom/msm_bus/msm_bus_of_adhoc.c
+++ b/drivers/soc/qcom/msm_bus/msm_bus_of_adhoc.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2014-2015, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2014-2016, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -495,6 +495,7 @@ static int get_bus_node_device_data(
{
bool enable_only;
bool setrate_only;
+ struct device_node *qos_clk_node;
node_device->node_info = get_node_info_data(dev_node, pdev);
if (IS_ERR_OR_NULL(node_device->node_info)) {
@@ -505,7 +506,6 @@ static int get_bus_node_device_data(
"qcom,ap-owned");
if (node_device->node_info->is_fab_dev) {
- struct device_node *qos_clk_node;
dev_dbg(&pdev->dev, "Dev %d\n", node_device->node_info->id);
if (!node_device->node_info->virt_dev) {
@@ -650,6 +650,21 @@ static int get_bus_node_device_data(
setrate_only;
}
+ qos_clk_node = of_get_child_by_name(dev_node,
+ "qcom,node-qos-clks");
+
+ if (qos_clk_node) {
+ if (msm_bus_of_parse_clk_array(qos_clk_node, dev_node,
+ pdev,
+ &node_device->node_qos_clks,
+ &node_device->num_node_qos_clks,
+ node_device->node_info->id)) {
+ dev_info(&pdev->dev, "Bypass QoS programming");
+ node_device->fabdev->bypass_qos_prg = true;
+ }
+ of_node_put(qos_clk_node);
+ }
+
node_device->clk[DUAL_CTX].clk = of_clk_get_by_name(dev_node,
"node_clk");