From 98b202c507eaaa2cd685d0c69be60ec4e955eddd Mon Sep 17 00:00:00 2001 From: Mike Tipton Date: Tue, 12 Jan 2021 12:31:37 -0800 Subject: [PATCH 1/8] interconnect: qcom: Add debug library Add a debug library that provides QCOM-specific interconnect debug features. This includes support for printing all enabled interconnect votes to console when entering suspend. Change-Id: I61302f95c94176f833bd1c88ddc76b88121b3f79 Signed-off-by: Mike Tipton --- drivers/interconnect/qcom/Kconfig | 8 ++ drivers/interconnect/qcom/Makefile | 1 + drivers/interconnect/qcom/icc-debug.c | 175 ++++++++++++++++++++++++++ drivers/interconnect/qcom/icc-debug.h | 12 ++ drivers/interconnect/qcom/icc-rpmh.c | 6 +- 5 files changed, 201 insertions(+), 1 deletion(-) create mode 100644 drivers/interconnect/qcom/icc-debug.c create mode 100644 drivers/interconnect/qcom/icc-debug.h diff --git a/drivers/interconnect/qcom/Kconfig b/drivers/interconnect/qcom/Kconfig index b2997f115d56..334978510c9d 100644 --- a/drivers/interconnect/qcom/Kconfig +++ b/drivers/interconnect/qcom/Kconfig @@ -178,3 +178,11 @@ config INTERCONNECT_QCOM_SMD_RPM config INTERCONNECT_QCOM_QOS tristate + +config INTERCONNECT_QCOM_DEBUG + tristate "QCOM-specific interconnect debug features" + depends on INTERCONNECT_QCOM + help + This driver provides QCOM-specific interconnect debug features. These + features include optionally printing all enabled interconnect votes + when entering suspend. diff --git a/drivers/interconnect/qcom/Makefile b/drivers/interconnect/qcom/Makefile index c4fdc45579df..b303950b30ff 100644 --- a/drivers/interconnect/qcom/Makefile +++ b/drivers/interconnect/qcom/Makefile @@ -43,3 +43,4 @@ obj-$(CONFIG_INTERCONNECT_QCOM_SM8350) += qnoc-sm8350.o obj-$(CONFIG_INTERCONNECT_QCOM_SM8450) += qnoc-sm8450.o obj-$(CONFIG_INTERCONNECT_QCOM_SMD_RPM) += icc-smd-rpm.o obj-$(CONFIG_INTERCONNECT_QCOM_QOS) += qnoc-qos.o +obj-$(CONFIG_INTERCONNECT_QCOM_DEBUG) += icc-debug.o diff --git a/drivers/interconnect/qcom/icc-debug.c b/drivers/interconnect/qcom/icc-debug.c new file mode 100644 index 000000000000..302b7c09e25d --- /dev/null +++ b/drivers/interconnect/qcom/icc-debug.c @@ -0,0 +1,175 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* Copyright (c) 2021, The Linux Foundation. All rights reserved. */ + +#include +#include +#include +#include +#include +#include +#include + +#include "../internal.h" + +static LIST_HEAD(icc_providers); +static DEFINE_MUTEX(debug_lock); +static struct dentry *dentry_suspend; +static bool debug_suspend; + +struct qcom_icc_debug_provider { + struct list_head list; + struct icc_provider *provider; +}; + +static int icc_print_enabled(void) +{ + struct qcom_icc_debug_provider *dp; + struct icc_provider *provider; + struct icc_node *n; + struct icc_req *r; + u32 avg_bw, peak_bw; + + pr_info(" node tag avg peak\n"); + pr_info("--------------------------------------------------------------------\n"); + + list_for_each_entry(dp, &icc_providers, list) { + provider = dp->provider; + + list_for_each_entry(n, &provider->nodes, node_list) { + if (!n->avg_bw && !n->peak_bw) + continue; + + pr_info("%-42s %12u %12u\n", + n->name, n->avg_bw, n->peak_bw); + + hlist_for_each_entry(r, &n->req_list, req_node) { + if (!r->dev) + continue; + + if (r->enabled) { + avg_bw = r->avg_bw; + peak_bw = r->peak_bw; + } else { + avg_bw = 0; + peak_bw = 0; + } + + if (avg_bw || peak_bw) + pr_info(" %-27s %12u %12u %12u\n", + dev_name(r->dev), r->tag, avg_bw, peak_bw); + } + } + } + + return 0; +} + +static int icc_debug_suspend_get(void *data, u64 *val) +{ + *val = debug_suspend; + + return 0; +} + +static void icc_debug_suspend_trace_probe(void *unused, const char *action, + int val, bool start) +{ + if (start && val > 0 && !strcmp("machine_suspend", action)) { + pr_info("Enabled interconnect votes:\n"); + icc_print_enabled(); + } +} + +static int icc_debug_suspend_set(void *data, u64 val) +{ + int ret; + + val = !!val; + if (val == debug_suspend) + return 0; + + if (val) + ret = register_trace_suspend_resume(icc_debug_suspend_trace_probe, NULL); + else + ret = unregister_trace_suspend_resume(icc_debug_suspend_trace_probe, NULL); + + if (ret) { + pr_err("%s: Failed to %sregister suspend trace callback, ret=%d\n", + __func__, val ? "" : "un", ret); + return ret; + } + + debug_suspend = val; + + return 0; +} +DEFINE_DEBUGFS_ATTRIBUTE(icc_debug_suspend_fops, icc_debug_suspend_get, + icc_debug_suspend_set, "%llu\n"); + +int qcom_icc_debug_register(struct icc_provider *provider) +{ + struct qcom_icc_debug_provider *dp; + + dp = kzalloc(sizeof(*dp), GFP_KERNEL); + if (!dp) + return -ENOMEM; + + dp->provider = provider; + + mutex_lock(&debug_lock); + list_add_tail(&dp->list, &icc_providers); + mutex_unlock(&debug_lock); + + return 0; +} +EXPORT_SYMBOL(qcom_icc_debug_register); + +int qcom_icc_debug_unregister(struct icc_provider *provider) +{ + struct qcom_icc_debug_provider *dp, *temp; + + mutex_lock(&debug_lock); + + list_for_each_entry_safe(dp, temp, &icc_providers, list) { + if (dp->provider == provider) { + list_del(&dp->list); + kfree(dp); + } + } + + mutex_unlock(&debug_lock); + + return 0; +} +EXPORT_SYMBOL(qcom_icc_debug_unregister); + +static int __init qcom_icc_debug_init(void) +{ + static struct dentry *dir; + int ret; + + dir = debugfs_lookup("interconnect", NULL); + if (IS_ERR_OR_NULL(dir)) { + ret = PTR_ERR(dir); + pr_err("%s: unable to find root interconnect debugfs directory, ret=%d\n", + __func__, ret); + return 0; + } + + dentry_suspend = debugfs_create_file_unsafe("debug_suspend", + 0644, dir, NULL, + &icc_debug_suspend_fops); + return 0; +} +module_init(qcom_icc_debug_init); + +static void __exit qcom_icc_debug_exit(void) +{ + debugfs_remove(dentry_suspend); + if (debug_suspend) + unregister_trace_suspend_resume(icc_debug_suspend_trace_probe, NULL); +} +module_exit(qcom_icc_debug_exit); + +MODULE_DESCRIPTION("QCOM ICC debug library"); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/interconnect/qcom/icc-debug.h b/drivers/interconnect/qcom/icc-debug.h new file mode 100644 index 000000000000..d747854749c0 --- /dev/null +++ b/drivers/interconnect/qcom/icc-debug.h @@ -0,0 +1,12 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* Copyright (c) 2021, The Linux Foundation. All rights reserved. */ + +#ifndef __QCOM_ICC_DEBUG_H__ +#define __QCOM_ICC_DEBUG_H__ + +#include + +int qcom_icc_debug_register(struct icc_provider *provider); +int qcom_icc_debug_unregister(struct icc_provider *provider); + +#endif diff --git a/drivers/interconnect/qcom/icc-rpmh.c b/drivers/interconnect/qcom/icc-rpmh.c index 1e3da6b98fe9..609c0d37b624 100644 --- a/drivers/interconnect/qcom/icc-rpmh.c +++ b/drivers/interconnect/qcom/icc-rpmh.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0 /* - * Copyright (c) 2020, The Linux Foundation. All rights reserved. + * Copyright (c) 2020-2021, The Linux Foundation. All rights reserved. */ #include @@ -13,6 +13,7 @@ #include #include "bcm-voter.h" +#include "icc-debug.h" #include "icc-rpmh.h" #include "qnoc-qos.h" @@ -329,6 +330,8 @@ int qcom_icc_rpmh_probe(struct platform_device *pdev) provider->set = qcom_icc_set; provider->aggregate = qcom_icc_aggregate; + qcom_icc_debug_register(provider); + mutex_lock(&probe_list_lock); list_add_tail(&qp->probe_list, &qnoc_probe_list); mutex_unlock(&probe_list_lock); @@ -347,6 +350,7 @@ int qcom_icc_rpmh_remove(struct platform_device *pdev) { struct qcom_icc_provider *qp = platform_get_drvdata(pdev); + qcom_icc_debug_unregister(&qp->provider); clk_bulk_put_all(qp->num_clks, qp->clks); icc_nodes_remove(&qp->provider); From 07cbd50500b1525b2bc83a136a8417f504b87eab Mon Sep 17 00:00:00 2001 From: Vivek Aknurwar Date: Wed, 3 Feb 2021 14:53:59 -0800 Subject: [PATCH 2/8] interconnect: qcom: Add stub icc_get_bw stub callback Currently avg and peak bandwidth are voted as allowed max on kernel boot. Add stub icc_get_bw() callback that return default avg, peak bandwidth. Change-Id: I5c42f933d770e2c63c8bbc2d8e7afe5b9748ba1d Signed-off-by: Vivek Aknurwar --- drivers/interconnect/qcom/icc-rpmh.c | 10 ++++++++++ drivers/interconnect/qcom/icc-rpmh.h | 3 ++- 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/drivers/interconnect/qcom/icc-rpmh.c b/drivers/interconnect/qcom/icc-rpmh.c index 609c0d37b624..fbb9ec23f34f 100644 --- a/drivers/interconnect/qcom/icc-rpmh.c +++ b/drivers/interconnect/qcom/icc-rpmh.c @@ -123,6 +123,15 @@ int qcom_icc_set_stub(struct icc_node *src, struct icc_node *dst) } EXPORT_SYMBOL(qcom_icc_set_stub); +int qcom_icc_get_bw_stub(struct icc_node *node, u32 *avg, u32 *peak) +{ + *avg = 0; + *peak = 0; + + return 0; +} +EXPORT_SYMBOL(qcom_icc_get_bw_stub); + struct icc_node_data *qcom_icc_xlate_extended(struct of_phandle_args *spec, void *data) { struct icc_node_data *ndata; @@ -259,6 +268,7 @@ int qcom_icc_rpmh_probe(struct platform_device *pdev) provider->xlate_extended = qcom_icc_xlate_extended; INIT_LIST_HEAD(&provider->nodes); provider->data = data; + provider->get_bw = qcom_icc_get_bw_stub; qp->dev = dev; qp->bcms = desc->bcms; diff --git a/drivers/interconnect/qcom/icc-rpmh.h b/drivers/interconnect/qcom/icc-rpmh.h index 562164a128c8..4d37fa276fe5 100644 --- a/drivers/interconnect/qcom/icc-rpmh.h +++ b/drivers/interconnect/qcom/icc-rpmh.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0 */ /* - * Copyright (c) 2020, The Linux Foundation. All rights reserved. + * Copyright (c) 2020-2021, The Linux Foundation. All rights reserved. */ #ifndef __DRIVERS_INTERCONNECT_QCOM_ICC_RPMH_H__ @@ -154,4 +154,5 @@ void qcom_icc_pre_aggregate(struct icc_node *node); int qcom_icc_rpmh_probe(struct platform_device *pdev); int qcom_icc_rpmh_remove(struct platform_device *pdev); void qcom_icc_rpmh_sync_state(struct device *dev); +int qcom_icc_get_bw_stub(struct icc_node *node, u32 *avg, u32 *peak); #endif From 5d9a29660bfe81c94b5dc79030c6f563f1a41716 Mon Sep 17 00:00:00 2001 From: Mike Tipton Date: Mon, 25 Jan 2021 14:33:26 -0800 Subject: [PATCH 3/8] interconnect: qcom: Set floor of 1 for BCM unit/width Some BCMs that aren't directly associated with NOC ports (i.e. ACV) publish their width as 0 in cmd_db. The client votes are multiplied by this width when adjusting for node/BCM width differences. This means a zero width also zeroes the client votes, making it impossible to vote on these zero-width BCMs. Set a width floor of 1 to allow aggregation on these nodes. Also set a floor on the BCM units. They should never by 0 in cmd_db, but if they are it would cause a div-by-zero. Change-Id: I14ba89411ec02077db6d2c27b6de932c5b7dfe1e Signed-off-by: Mike Tipton --- drivers/interconnect/qcom/icc-rpmh.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/interconnect/qcom/icc-rpmh.c b/drivers/interconnect/qcom/icc-rpmh.c index fbb9ec23f34f..b9ad2ca9fe95 100644 --- a/drivers/interconnect/qcom/icc-rpmh.c +++ b/drivers/interconnect/qcom/icc-rpmh.c @@ -194,8 +194,8 @@ int qcom_icc_bcm_init(struct qcom_icc_bcm *bcm, struct device *dev) return -EINVAL; } - bcm->aux_data.unit = le32_to_cpu(data->unit); - bcm->aux_data.width = le16_to_cpu(data->width); + bcm->aux_data.unit = max_t(u32, 1, le32_to_cpu(data->unit)); + bcm->aux_data.width = max_t(u16, 1, le16_to_cpu(data->width)); bcm->aux_data.vcd = data->vcd; bcm->aux_data.reserved = data->reserved; INIT_LIST_HEAD(&bcm->list); From 6d75baa3d23e38ef159ab96080da1e240345d026 Mon Sep 17 00:00:00 2001 From: Mike Tipton Date: Fri, 15 Jan 2021 17:43:20 -0800 Subject: [PATCH 4/8] interconnect: qcom: Add support for mask-based BCMs Some BCMs aren't directly associated with the data path (i.e. ACV) and therefore don't communicate using BW. Instead, they are simply enabled/disabled with a simple bit mask. Add support for these. Change-Id: I9b73e0ce05a09338d22571ff311c5b058fb8e1b2 Signed-off-by: Mike Tipton --- drivers/interconnect/qcom/bcm-voter.c | 5 +++++ drivers/interconnect/qcom/icc-rpmh.h | 2 ++ 2 files changed, 7 insertions(+) diff --git a/drivers/interconnect/qcom/bcm-voter.c b/drivers/interconnect/qcom/bcm-voter.c index 905d382e221d..567ef0b4dda8 100644 --- a/drivers/interconnect/qcom/bcm-voter.c +++ b/drivers/interconnect/qcom/bcm-voter.c @@ -85,6 +85,11 @@ static void bcm_aggregate(struct qcom_icc_bcm *bcm, bool init) temp = agg_peak[bucket] * bcm->vote_scale; bcm->vote_y[bucket] = bcm_div(temp, bcm->aux_data.unit); + + if (bcm->enable_mask && (bcm->vote_x[bucket] || bcm->vote_y[bucket])) { + bcm->vote_x[bucket] = 0; + bcm->vote_y[bucket] = bcm->enable_mask; + } } if (bcm->keepalive) { diff --git a/drivers/interconnect/qcom/icc-rpmh.h b/drivers/interconnect/qcom/icc-rpmh.h index 4d37fa276fe5..826e4c76a287 100644 --- a/drivers/interconnect/qcom/icc-rpmh.h +++ b/drivers/interconnect/qcom/icc-rpmh.h @@ -91,6 +91,7 @@ struct qcom_icc_node { * @vote_x: aggregated threshold values, represents sum_bw when @type is bw bcm * @vote_y: aggregated threshold values, represents peak_bw when @type is bw bcm * @vote_scale: scaling factor for vote_x and vote_y + * @enable_mask: optional mask to send as vote instead of vote_x/vote_y * @dirty: flag used to indicate whether the bcm needs to be committed * @keepalive: flag used to indicate whether a keepalive is required * @aux_data: auxiliary data used when calculating threshold values and @@ -107,6 +108,7 @@ struct qcom_icc_bcm { u64 vote_x[QCOM_ICC_NUM_BUCKETS]; u64 vote_y[QCOM_ICC_NUM_BUCKETS]; u64 vote_scale; + u32 enable_mask; bool dirty; bool keepalive; struct bcm_db aux_data; From 1f035351b70f9713d726adda76f3a8afacabdef7 Mon Sep 17 00:00:00 2001 From: Mike Tipton Date: Fri, 15 Jan 2021 17:40:22 -0800 Subject: [PATCH 5/8] dt-bindings: interconnect: Add QCOM_ICC_TAG_PERF_MODE Add binding for QCOM_ICC_TAG_PERF_MODE, which can be used with icc_set_tag() to indicate that the path should use latency-optimized settings for each node in the path if supported. Change-Id: I748df7bdaa79784ade4ad9a135e4f91b92b97513 Signed-off-by: Mike Tipton --- include/dt-bindings/interconnect/qcom,icc.h | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/include/dt-bindings/interconnect/qcom,icc.h b/include/dt-bindings/interconnect/qcom,icc.h index cd34f36daaaa..710e4839b992 100644 --- a/include/dt-bindings/interconnect/qcom,icc.h +++ b/include/dt-bindings/interconnect/qcom,icc.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* - * Copyright (c) 2020, The Linux Foundation. All rights reserved. + * Copyright (c) 2020-2021, The Linux Foundation. All rights reserved. */ #ifndef __DT_BINDINGS_INTERCONNECT_QCOM_ICC_H @@ -23,4 +23,10 @@ #define QCOM_ICC_TAG_ALWAYS (QCOM_ICC_TAG_AMC | QCOM_ICC_TAG_WAKE |\ QCOM_ICC_TAG_SLEEP) +/* + * PERF_MODE indicates that each node in the requested path should use + * performance-optimized settings if supported by the node. + */ +#define QCOM_ICC_TAG_PERF_MODE (1 << 3) + #endif From bdebb74665d0b1b7d24f54ab6c89ba5799028dc8 Mon Sep 17 00:00:00 2001 From: Mike Tipton Date: Fri, 15 Jan 2021 17:41:20 -0800 Subject: [PATCH 6/8] interconnect: qcom: Add support for PERF_MODE on RPMh targets Add support for QCOM_ICC_TAG_PERF_MODE on RPMh architectures. When QCOM_ICC_TAG_PERF_MODE is specified using icc_set_tag(), each node in the requested path will use latency-optimized settings if supported by the node. The improved latency comes at the cost of higher power. Change-Id: I83c52e5677f8842b4c17987053d566971b84086f Signed-off-by: Mike Tipton --- drivers/interconnect/qcom/bcm-voter.c | 5 +++++ drivers/interconnect/qcom/icc-rpmh.c | 3 +++ drivers/interconnect/qcom/icc-rpmh.h | 4 ++++ 3 files changed, 12 insertions(+) diff --git a/drivers/interconnect/qcom/bcm-voter.c b/drivers/interconnect/qcom/bcm-voter.c index 567ef0b4dda8..8a1ef9301e77 100644 --- a/drivers/interconnect/qcom/bcm-voter.c +++ b/drivers/interconnect/qcom/bcm-voter.c @@ -66,6 +66,7 @@ static void bcm_aggregate(struct qcom_icc_bcm *bcm, bool init) size_t i, bucket; u64 agg_avg[QCOM_ICC_NUM_BUCKETS] = {0}; u64 agg_peak[QCOM_ICC_NUM_BUCKETS] = {0}; + bool perf_mode[QCOM_ICC_NUM_BUCKETS] = {0}; u64 temp; for (bucket = 0; bucket < QCOM_ICC_NUM_BUCKETS; bucket++) { @@ -78,6 +79,8 @@ static void bcm_aggregate(struct qcom_icc_bcm *bcm, bool init) temp = bcm_div(node->max_peak[bucket] * bcm->aux_data.width, node->buswidth); agg_peak[bucket] = max(agg_peak[bucket], temp); + + perf_mode[bucket] |= node->perf_mode[bucket]; } temp = agg_avg[bucket] * bcm->vote_scale; @@ -89,6 +92,8 @@ static void bcm_aggregate(struct qcom_icc_bcm *bcm, bool init) if (bcm->enable_mask && (bcm->vote_x[bucket] || bcm->vote_y[bucket])) { bcm->vote_x[bucket] = 0; bcm->vote_y[bucket] = bcm->enable_mask; + if (perf_mode[bucket]) + bcm->vote_y[bucket] |= bcm->perf_mode_mask; } } diff --git a/drivers/interconnect/qcom/icc-rpmh.c b/drivers/interconnect/qcom/icc-rpmh.c index b9ad2ca9fe95..3072ecad5172 100644 --- a/drivers/interconnect/qcom/icc-rpmh.c +++ b/drivers/interconnect/qcom/icc-rpmh.c @@ -36,6 +36,7 @@ void qcom_icc_pre_aggregate(struct icc_node *node) for (i = 0; i < QCOM_ICC_NUM_BUCKETS; i++) { qn->sum_avg[i] = 0; qn->max_peak[i] = 0; + qn->perf_mode[i] = false; } for (i = 0; i < qn->num_bcms; i++) @@ -68,6 +69,8 @@ int qcom_icc_aggregate(struct icc_node *node, u32 tag, u32 avg_bw, if (tag & BIT(i)) { qn->sum_avg[i] += avg_bw; qn->max_peak[i] = max_t(u32, qn->max_peak[i], peak_bw); + if (tag & QCOM_ICC_TAG_PERF_MODE && (avg_bw || peak_bw)) + qn->perf_mode[i] = true; } if (node->init_avg || node->init_peak) { diff --git a/drivers/interconnect/qcom/icc-rpmh.h b/drivers/interconnect/qcom/icc-rpmh.h index 826e4c76a287..6fa78ddf2987 100644 --- a/drivers/interconnect/qcom/icc-rpmh.h +++ b/drivers/interconnect/qcom/icc-rpmh.h @@ -63,6 +63,7 @@ struct bcm_db { * @buswidth: width of the interconnect between a node and the bus * @sum_avg: current sum aggregate value of all avg bw requests * @max_peak: current max aggregate value of all peak bw requests + * @perf_mode: current OR aggregate value of all QCOM_ICC_TAG_PERF_MODE votes * @bcms: list of bcms associated with this logical node * @num_bcms: num of @bcms */ @@ -75,6 +76,7 @@ struct qcom_icc_node { u16 buswidth; u64 sum_avg[QCOM_ICC_NUM_BUCKETS]; u64 max_peak[QCOM_ICC_NUM_BUCKETS]; + bool perf_mode[QCOM_ICC_NUM_BUCKETS]; struct qcom_icc_bcm *bcms[MAX_BCM_PER_NODE]; size_t num_bcms; struct regmap *regmap; @@ -92,6 +94,7 @@ struct qcom_icc_node { * @vote_y: aggregated threshold values, represents peak_bw when @type is bw bcm * @vote_scale: scaling factor for vote_x and vote_y * @enable_mask: optional mask to send as vote instead of vote_x/vote_y + * @perf_mode_mask: mask to OR with enable_mask when QCOM_ICC_TAG_PERF_MODE is set * @dirty: flag used to indicate whether the bcm needs to be committed * @keepalive: flag used to indicate whether a keepalive is required * @aux_data: auxiliary data used when calculating threshold values and @@ -109,6 +112,7 @@ struct qcom_icc_bcm { u64 vote_y[QCOM_ICC_NUM_BUCKETS]; u64 vote_scale; u32 enable_mask; + u32 perf_mode_mask; bool dirty; bool keepalive; struct bcm_db aux_data; From bc2e1198ccdc32b608b7b962deb04b7c4d794eee Mon Sep 17 00:00:00 2001 From: Vivek Aknurwar Date: Wed, 9 Jun 2021 20:49:38 -0700 Subject: [PATCH 7/8] interconnect: qcom: icc-rpmh: Implement stub handling Skip bcm init and implement stubs for icc apis when stub property is defined. Change-Id: Ic56a75578b6fa4fe35bebaf103d41205e444efed Signed-off-by: Vivek Aknurwar --- drivers/interconnect/qcom/icc-rpmh.c | 31 +++++++++++++++++----------- drivers/interconnect/qcom/icc-rpmh.h | 1 + 2 files changed, 20 insertions(+), 12 deletions(-) diff --git a/drivers/interconnect/qcom/icc-rpmh.c b/drivers/interconnect/qcom/icc-rpmh.c index 3072ecad5172..93e999f99e63 100644 --- a/drivers/interconnect/qcom/icc-rpmh.c +++ b/drivers/interconnect/qcom/icc-rpmh.c @@ -263,6 +263,8 @@ int qcom_icc_rpmh_probe(struct platform_device *pdev) if (!data) return -ENOMEM; + qp->stub = of_property_read_bool(pdev->dev.of_node, "qcom,stub"); + provider = &qp->provider; provider->dev = dev; provider->set = qcom_icc_set_stub; @@ -275,19 +277,22 @@ int qcom_icc_rpmh_probe(struct platform_device *pdev) qp->dev = dev; qp->bcms = desc->bcms; - qp->num_bcms = desc->num_bcms; - qp->num_voters = desc->num_voters; - qp->voters = devm_kcalloc(&pdev->dev, qp->num_voters, - sizeof(*qp->voters), GFP_KERNEL); + if (!qp->stub) { + qp->num_bcms = desc->num_bcms; + qp->num_voters = desc->num_voters; - if (!qp->voters) - return -ENOMEM; + qp->voters = devm_kcalloc(&pdev->dev, qp->num_voters, + sizeof(*qp->voters), GFP_KERNEL); - for (i = 0; i < qp->num_voters; i++) { - qp->voters[i] = of_bcm_voter_get(qp->dev, desc->voters[i]); - if (IS_ERR(qp->voters[i])) - return PTR_ERR(qp->voters[i]); + if (!qp->voters) + return -ENOMEM; + + for (i = 0; i < qp->num_voters; i++) { + qp->voters[i] = of_bcm_voter_get(qp->dev, desc->voters[i]); + if (IS_ERR(qp->voters[i])) + return PTR_ERR(qp->voters[i]); + } } qp->regmap = qcom_icc_rpmh_map(pdev, desc); @@ -340,8 +345,10 @@ int qcom_icc_rpmh_probe(struct platform_device *pdev) data->num_nodes = num_nodes; platform_set_drvdata(pdev, qp); - provider->set = qcom_icc_set; - provider->aggregate = qcom_icc_aggregate; + if (!qp->stub) { + provider->set = qcom_icc_set; + provider->aggregate = qcom_icc_aggregate; + } qcom_icc_debug_register(provider); diff --git a/drivers/interconnect/qcom/icc-rpmh.h b/drivers/interconnect/qcom/icc-rpmh.h index 6fa78ddf2987..b75609a55e9a 100644 --- a/drivers/interconnect/qcom/icc-rpmh.h +++ b/drivers/interconnect/qcom/icc-rpmh.h @@ -32,6 +32,7 @@ struct qcom_icc_provider { int num_clks; struct bcm_voter **voters; size_t num_voters; + bool stub; }; /** From 81216c014f760b5f5ae9c61cb69fb5990de03c74 Mon Sep 17 00:00:00 2001 From: Mike Tipton Date: Thu, 6 May 2021 16:51:35 -0700 Subject: [PATCH 8/8] interconnect: qcom: qnoc-qos: Don't skip writing urg_fwd when it's zero Some QoS enable urgent forwarding by default, but we don't always want this. So don't assume the register already has zero and write it unconditionally. Change-Id: I257e099a588870f8d6e6d68b7fd794e22781450e Signed-off-by: Mike Tipton --- drivers/interconnect/qcom/qnoc-qos.c | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/drivers/interconnect/qcom/qnoc-qos.c b/drivers/interconnect/qcom/qnoc-qos.c index cf78e497e743..2eb98897a216 100644 --- a/drivers/interconnect/qcom/qnoc-qos.c +++ b/drivers/interconnect/qcom/qnoc-qos.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (c) 2020, The Linux Foundation. All rights reserved. + * Copyright (c) 2020-2021, The Linux Foundation. All rights reserved. * */ @@ -13,7 +13,7 @@ #define QOSGEN_MAINCTL_LO(p, qp) ((p)->offsets[qp] + \ (p)->regs[QOSGEN_OFF_MAINCTL_LO]) -# define QOS_SLV_URG_MSG_EN BIT(3) +#define QOS_SLV_URG_MSG_EN_SHFT 3 # define QOS_DFLT_PRIO_MASK 0x7 # define QOS_DFLT_PRIO_SHFT 4 @@ -49,11 +49,9 @@ static void qcom_icc_set_qos(struct qcom_icc_node *node) QOS_DFLT_PRIO_MASK << QOS_DFLT_PRIO_SHFT, qos->config->prio << QOS_DFLT_PRIO_SHFT); - if (qos->config->urg_fwd) - regmap_update_bits(node->regmap, - QOSGEN_MAINCTL_LO(qos, port), - QOS_SLV_URG_MSG_EN, - QOS_SLV_URG_MSG_EN); + regmap_update_bits(node->regmap, QOSGEN_MAINCTL_LO(qos, port), + BIT(QOS_SLV_URG_MSG_EN_SHFT), + qos->config->urg_fwd << QOS_SLV_URG_MSG_EN_SHFT); } }