Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit b3f54ff6 authored by David Dai's avatar David Dai Committed by Gerrit - the friendly Code Review server
Browse files

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: default avatarDavid Dai <daidavid1@codeaurora.org>
parent 008f057b
Loading
Loading
Loading
Loading
+26 −0
Original line number Diff line number Diff line
@@ -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 =
+17 −2
Original line number Diff line number Diff line
/* 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");