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

Commit ce501003 authored by Georgi Djakov's avatar Georgi Djakov Committed by Mike Tipton
Browse files

interconnect: qcom: Set QoS on the first bandwidth request



Move the QoS configuration to happen on the first non-zero bandwidth
request from the consumer driver. This allows configuring QoS also
for consumers like IPA, which can probe asynchronously and their clock
should not be touched until the firmware has completed booting.

Change-Id: I2a8e385d99f3c489d920a7c85e9415d540f6df87
Signed-off-by: default avatarGeorgi Djakov <gdjako@codeaurora.org>
Signed-off-by: default avatarMike Tipton <mdtipton@codeaurora.org>
parent e51f74d2
Loading
Loading
Loading
Loading
+13 −0
Original line number Diff line number Diff line
@@ -6,11 +6,13 @@

#include <asm/div64.h>
#include <dt-bindings/interconnect/qcom,sdm845.h>
#include <linux/clk.h>
#include <linux/interconnect.h>
#include <linux/interconnect-provider.h>

#include "icc-rpmh.h"
#include "bcm-voter.h"
#include "qnoc-qos.h"

/**
 * qcom_icc_pre_aggregate - cleans up stale values from prior icc_set
@@ -80,6 +82,7 @@ EXPORT_SYMBOL(qcom_icc_aggregate);
int qcom_icc_set(struct icc_node *src, struct icc_node *dst)
{
	struct qcom_icc_provider *qp;
	struct qcom_icc_node *qn;
	struct icc_node *node;
	int i;

@@ -89,10 +92,20 @@ int qcom_icc_set(struct icc_node *src, struct icc_node *dst)
		node = src;

	qp = to_qcom_provider(node->provider);
	qn = node->data;

	for (i = 0; i < qp->num_voters; i++)
		qcom_icc_bcm_voter_commit(qp->voters[i]);

	/* Defer setting QoS until the first non-zero bandwidth request. */
	if (qn && qn->qosbox && !qn->qosbox->initialized &&
	    (node->avg_bw || node->peak_bw)) {
		clk_bulk_prepare_enable(qp->num_clks, qp->clks);
		qn->noc_ops->set_qos(qn);
		clk_bulk_disable_unprepare(qp->num_clks, qp->clks);
		qn->qosbox->initialized = true;
	}

	return 0;
}
EXPORT_SYMBOL(qcom_icc_set);
+4 −14
Original line number Diff line number Diff line
@@ -991,6 +991,8 @@ static int qnoc_probe(struct platform_device *pdev)
		icc_node_destroy(node->id);
	}

	clk_bulk_put_all(qp->num_clks, qp->clks);

	icc_provider_del(provider);
	return ret;
}
@@ -1006,6 +1008,8 @@ static int qnoc_remove(struct platform_device *pdev)
		icc_node_destroy(n->id);
	}

	clk_bulk_put_all(qp->num_clks, qp->clks);

	return icc_provider_del(provider);
}

@@ -1040,26 +1044,12 @@ static void qnoc_sync_state(struct device *dev)
{
	struct platform_device *pdev = to_platform_device(dev);
	struct qcom_icc_provider *qp = platform_get_drvdata(pdev);
	struct icc_provider *provider = &qp->provider;
	struct qcom_icc_node *qnode;
	struct qcom_icc_bcm *bcm;
	struct bcm_voter *voter;
	struct icc_node *node;

	mutex_lock(&probe_list_lock);
	probe_count++;

	clk_bulk_prepare_enable(qp->num_clks, qp->clks);

	list_for_each_entry(node, &provider->nodes, node_list) {
		qnode = node->data;
		if (qnode && qnode->noc_ops)
			qnode->noc_ops->set_qos(qnode);
	}

	clk_bulk_disable_unprepare(qp->num_clks, qp->clks);
	clk_bulk_put_all(qp->num_clks, qp->clks);

	if (probe_count < ARRAY_SIZE(qnoc_of_match) - 1) {
		mutex_unlock(&probe_list_lock);
		return;
+1 −0
Original line number Diff line number Diff line
@@ -37,6 +37,7 @@ struct qos_config {
struct qcom_icc_qosbox {
	u32 num_ports;
	const u8 *regs;
	bool initialized;
	struct qos_config *config;
	u32 offsets[];
};