2023-02-17 10:46:40

by Konrad Dybcio

[permalink] [raw]
Subject: [PATCH v5 00/10] The great interconnecification fixation

Hi!

v4 -> v5 changelog:
- Previously the "Always set QoS params on QNoC" contained part of what
should have been included in "make QoS INVALID default".. (very bad)
Fix it!

- Drop negative offset and keep_alive, they will be resubmitted with new
icc driver submissions

- use b4 this time.. hopefully the series gets to everybody now

Link to v4: https://lore.kernel.org/linux-arm-msm/[email protected]/

v3 -> v4 changelog:
- Drop "Always set QoS params on QNoC", it only causes issues.. this
can be investigated another day, as it's not necessary for operation

- Drop "Add a way to always set QoS registers", same as /\

- Add a way (and use it) to have no bus_clocks (the ones we set rate on),
as at least msm8996 has a bus (A0NoC) that doesn't have any and does
all the scaling through RPM requests

- Promote 8996 icc to core_initcall

- Introduce keep_alive (see patch [11/12]) (important!, will be used by at least 6375)

- Allow negative QoS offsets in preparation for introducing 8998 icc [12/12]

Link to v3: https://lore.kernel.org/linux-arm-msm/[email protected]/

v2 -> v3 changelog:
- Drop "Don't set QoS params before non-zero bw is requested"

- Rebase on next

- [1/9] ("..make QoS INVALID default.."): remove unused define for
MODE_INVALID_VAL

- Pick up tags

v1 -> v2 changelog:
- reorder "make QoS INVALID default", makes more sense to have it
before "Always set QoS params on QNoC"

- Limit ap_owned-independent QoS setting to QNoC only

- Add new patches for handling the 8996-and-friends clocks situation
and optional BIMC regardless-of-ap_owned QoS programming

[1] https://lore.kernel.org/linux-arm-msm/[email protected]/T/#m056692bea71d4c272968d5e07afbd9eb07a88123
[2] https://lore.kernel.org/linux-arm-msm/[email protected]/

This series grew quite a bit bigger than the previous [1] attempt, so
I decided to also add a cover letter.

Link to v2: [2]

It addresses a few things that were not quite right:

- Setting QoS params before a "real" (non-zero) bandwidth request
makes little sense (since there's no data supposed to flow through
the bus, why would the QoS matter) and (at least newer) downstream
prevents that from happening. Do the same in Patch 1.

- QNoC type buses expect to always have their QoS registers set as long
as there's a non-INVALID QoS mode set; ap_owned is not really a thing
on these anymore, Patch 3 handles that.

- The recent MSM8996 boot fix was done quickly and not quite properly,
leading to possibly setting the aggregate bus rate on "normal"
hardware interface clocks; this series handles that by limiting the
number of bus_clocks to 2 (which is the maximum that makes sense,
anyway) and handling the rest as "intf_clocks", which are required
to access the hardware at the other end. Patches 5-8 take care of
that and Patch 10 reverts the _optional moniker in clk_get_ to make
sure we always have the bus scaling clocks, as they're well, kind
of important ????

- Similarly to QNoC, BIMC on "newer" (which can be loosely approximated
by "new enough" == "has only BIMC and QNoC hosts") SoCs expects to
always receive QoS programming, whereas BIMC on "older" SoCs cries
like a wild boar and crashes the platform when trying to do so
unconditionally. Patch 9 adds a way to take care of that for newer
SoCs (like SM6375)

- QoS mode INVALID was assumed by developers before to be the default
("I didn't specify any QoS settings, so the driver can't assume I
did.. right? right!?" - wrong, partial struct initialization led to
0 being set and 0 corresponded to QoS mode FIXED). Make it so, as
that's the logical choice. This allows the "Always set QoS params
on QNoC" patch to work without setting tons of what-should-
-obviously-be-the-default values everywhere, as well as fixes older
drivers that set ap_owned = true but left the QoS mode field unset.
Patch 2 cleans that up.

- Some nodes are physically connected over more than one channel
(usually DDR or other high-throughput paths). Patch 4 allows that
to be reflected in calculations. This will be required for at least
MSM8998 and SM6375 (which will be submitted soon after this lands)

Konrad Dybcio (12):
interconnect: qcom: rpm: make QoS INVALID default, separate out driver
data
interconnect: qcom: rpm: Add support for specifying channel num
interconnect: qcom: Sort kerneldoc entries
interconnect: qcom: rpm: Rename icc desc clocks to bus_blocks
interconnect: qcom: rpm: Rename icc provider num_clocks to
num_bus_clocks
interconnect: qcom: rpm: Handle interface clocks
interconnect: qcom: icc-rpm: Allow negative num_bus_clocks
interconnect: qcom: msm8996: Specify no bus clock scaling on A0NoC
interconnect: qcom: rpm: Don't use clk_get_optional for bus clocks
anymore
interconnect: qcom: msm8996: Promote to core_initcall
interconnect: qcom: icc-rpm: Introduce keep_alive
interconnect: qcom: icc-rpm: Allow negative QoS offset

drivers/interconnect/qcom/icc-rpm.c | 101 ++++++++++++++++++++--------
drivers/interconnect/qcom/icc-rpm.h | 41 +++++++----
drivers/interconnect/qcom/msm8996.c | 35 ++++++----
drivers/interconnect/qcom/sdm660.c | 16 ++---
4 files changed, 126 insertions(+), 67 deletions(-)

--
2.39.1

Signed-off-by: Konrad Dybcio <[email protected]>
---
Konrad Dybcio (10):
interconnect: qcom: rpm: make QoS INVALID default, separate out driver data
interconnect: qcom: rpm: Add support for specifying channel num
interconnect: qcom: Sort kerneldoc entries
interconnect: qcom: rpm: Rename icc desc clocks to bus_blocks
interconnect: qcom: rpm: Rename icc provider num_clocks to num_bus_clocks
interconnect: qcom: rpm: Handle interface clocks
interconnect: qcom: icc-rpm: Allow negative num_bus_clocks
interconnect: qcom: msm8996: Specify no bus clock scaling on A0NoC
interconnect: qcom: rpm: Don't use clk_get_optional for bus clocks anymore
interconnect: qcom: msm8996: Promote to core_initcall

drivers/interconnect/qcom/icc-rpm.c | 93 +++++++++++++++++++++++++------------
drivers/interconnect/qcom/icc-rpm.h | 34 +++++++++-----
drivers/interconnect/qcom/msm8996.c | 35 ++++++++------
drivers/interconnect/qcom/sdm660.c | 16 +++----
4 files changed, 112 insertions(+), 66 deletions(-)
---
base-commit: c068f40300a0eaa34f7105d137a5560b86951aa9
change-id: 20230217-topic-icc-fixes-v5-5fbbe48ced69

Best regards,
--
Konrad Dybcio <[email protected]>



2023-02-17 10:46:43

by Konrad Dybcio

[permalink] [raw]
Subject: [PATCH v5 01/10] interconnect: qcom: rpm: make QoS INVALID default, separate out driver data

Currently, NOC_QOS_MODE_FIXED is defined as 0x0, which makes it the
"default" option (as that's what uninitialized members of partially
initialized structs are set to), which should really have been
NOC_QOS_MODE_INVALID, and that's what people (wrongly) assumed was
the case when .qos.qos_mode was not defined and what really makes
the most sense..

That resulted in {port 0, prio 0, areq_prio 0, urg_fwd = false, rpm-voted}
QoS being always voted for, because the code flow assumed "hey, it's fixed
QoS, so let's just roll with whatever parameters are set" [again, set by
partial struct initialization, as these fields were left unfilled by the
developers]. That is of course incorrect, and on many of these platforms
port 0 is MAS_APPS_PROC, which 9/10 times is supposed to be handled by
the ap_owned path, not to mention the rest of the parameters may differ.
Arguably, the APPS node is the most important one, next to EBI0..

The modes are defined as preprocessor constants. They are not used
anywhere outside the driver or sent to any remote processor outside
qcom_icc_set_noc_qos(), which is easily worked around.
Separate the type specified in driver data from the value sent to msmbus.
Make the former an enum for better mainainability.

This is an implicit fix for every SMD RPM ICC driver that didn't
explicitly specify NOC_QOS_MODE_INVALID on non-AP_owned nodes that
don't have QoS settings.

Fixes: 30c8fa3ec61a ("interconnect: qcom: Add MSM8916 interconnect provider driver")
Fixes: 6c6fe5d3dc5e ("interconnect: qcom: Add MSM8939 interconnect provider driver")
Fixes: 4e60a9568dc6 ("interconnect: qcom: add msm8974 driver")
Fixes: 7add937f5222 ("interconnect: qcom: Add MSM8996 interconnect provider driver")
Signed-off-by: Konrad Dybcio <[email protected]>
---
drivers/interconnect/qcom/icc-rpm.c | 24 +++++++++++++-----------
drivers/interconnect/qcom/icc-rpm.h | 10 ++++++----
2 files changed, 19 insertions(+), 15 deletions(-)

diff --git a/drivers/interconnect/qcom/icc-rpm.c b/drivers/interconnect/qcom/icc-rpm.c
index df3196f72536..ffbeeca8c2b0 100644
--- a/drivers/interconnect/qcom/icc-rpm.c
+++ b/drivers/interconnect/qcom/icc-rpm.c
@@ -48,6 +48,9 @@
#define NOC_QOS_MODEn_ADDR(n) (0xc + (n * 0x1000))
#define NOC_QOS_MODEn_MASK 0x3

+#define NOC_QOS_MODE_FIXED_VAL 0x0
+#define NOC_QOS_MODE_BYPASS_VAL 0x2
+
static int qcom_icc_set_qnoc_qos(struct icc_node *src, u64 max_bw)
{
struct icc_provider *provider = src->provider;
@@ -153,7 +156,7 @@ static int qcom_icc_set_noc_qos(struct icc_node *src, u64 max_bw)
struct qcom_icc_provider *qp;
struct qcom_icc_node *qn;
struct icc_provider *provider;
- u32 mode = NOC_QOS_MODE_BYPASS;
+ u32 mode = NOC_QOS_MODE_BYPASS_VAL;
int rc = 0;

qn = src->data;
@@ -167,18 +170,17 @@ static int qcom_icc_set_noc_qos(struct icc_node *src, u64 max_bw)
return 0;
}

- if (qn->qos.qos_mode != NOC_QOS_MODE_INVALID)
- mode = qn->qos.qos_mode;
-
- if (mode == NOC_QOS_MODE_FIXED) {
- dev_dbg(src->provider->dev, "NoC QoS: %s: Set Fixed mode\n",
- qn->name);
+ if (qn->qos.qos_mode == NOC_QOS_MODE_FIXED) {
+ dev_dbg(src->provider->dev, "NoC QoS: %s: Set Fixed mode\n", qn->name);
+ mode = NOC_QOS_MODE_FIXED_VAL;
rc = qcom_icc_noc_set_qos_priority(qp, &qn->qos);
if (rc)
return rc;
- } else if (mode == NOC_QOS_MODE_BYPASS) {
- dev_dbg(src->provider->dev, "NoC QoS: %s: Set Bypass mode\n",
- qn->name);
+ } else if (qn->qos.qos_mode == NOC_QOS_MODE_BYPASS) {
+ dev_dbg(src->provider->dev, "NoC QoS: %s: Set Bypass mode\n", qn->name);
+ mode = NOC_QOS_MODE_BYPASS_VAL;
+ } else {
+ /* How did we get here? */
}

return regmap_update_bits(qp->regmap,
@@ -244,7 +246,7 @@ static int __qcom_icc_set(struct icc_node *n, struct qcom_icc_node *qn,
ret = qcom_icc_rpm_set(qn->mas_rpm_id, qn->slv_rpm_id, sum_bw);
if (ret)
return ret;
- } else if (qn->qos.qos_mode != -1) {
+ } else if (qn->qos.qos_mode != NOC_QOS_MODE_INVALID) {
/* set bandwidth directly from the AP */
ret = qcom_icc_qos_set(n, sum_bw);
if (ret)
diff --git a/drivers/interconnect/qcom/icc-rpm.h b/drivers/interconnect/qcom/icc-rpm.h
index a49af844ab13..8ba1918d7997 100644
--- a/drivers/interconnect/qcom/icc-rpm.h
+++ b/drivers/interconnect/qcom/icc-rpm.h
@@ -97,10 +97,12 @@ struct qcom_icc_desc {
unsigned int qos_offset;
};

-/* Valid for both NoC and BIMC */
-#define NOC_QOS_MODE_INVALID -1
-#define NOC_QOS_MODE_FIXED 0x0
-#define NOC_QOS_MODE_BYPASS 0x2
+/* Valid for all bus types */
+enum qos_mode {
+ NOC_QOS_MODE_INVALID = 0,
+ NOC_QOS_MODE_FIXED,
+ NOC_QOS_MODE_BYPASS,
+};

int qnoc_probe(struct platform_device *pdev);
int qnoc_remove(struct platform_device *pdev);

--
2.39.1


2023-02-17 10:46:47

by Konrad Dybcio

[permalink] [raw]
Subject: [PATCH v5 02/10] interconnect: qcom: rpm: Add support for specifying channel num

Some nodes, like EBI0 (DDR) or L3/LLCC, may be connected over more than
one channel. This should be taken into account in bandwidth calcualtion,
as we're supposed to feed msmbus with the per-channel bandwidth. Add
support for specifying that and use it during bandwidth aggregation.

Reviewed-by: Bryan O'Donoghue <[email protected]>
Signed-off-by: Konrad Dybcio <[email protected]>
---
drivers/interconnect/qcom/icc-rpm.c | 7 ++++++-
drivers/interconnect/qcom/icc-rpm.h | 2 ++
2 files changed, 8 insertions(+), 1 deletion(-)

diff --git a/drivers/interconnect/qcom/icc-rpm.c b/drivers/interconnect/qcom/icc-rpm.c
index ffbeeca8c2b0..6bd20f62f8ed 100644
--- a/drivers/interconnect/qcom/icc-rpm.c
+++ b/drivers/interconnect/qcom/icc-rpm.c
@@ -317,6 +317,7 @@ static void qcom_icc_bus_aggregate(struct icc_provider *provider,
{
struct icc_node *node;
struct qcom_icc_node *qn;
+ u64 sum_avg[QCOM_ICC_NUM_BUCKETS];
int i;

/* Initialise aggregate values */
@@ -334,7 +335,11 @@ static void qcom_icc_bus_aggregate(struct icc_provider *provider,
list_for_each_entry(node, &provider->nodes, node_list) {
qn = node->data;
for (i = 0; i < QCOM_ICC_NUM_BUCKETS; i++) {
- agg_avg[i] += qn->sum_avg[i];
+ if (qn->channels)
+ sum_avg[i] = div_u64(qn->sum_avg[i], qn->channels);
+ else
+ sum_avg[i] = qn->sum_avg[i];
+ agg_avg[i] += sum_avg[i];
agg_peak[i] = max_t(u64, agg_peak[i], qn->max_peak[i]);
}
}
diff --git a/drivers/interconnect/qcom/icc-rpm.h b/drivers/interconnect/qcom/icc-rpm.h
index 8ba1918d7997..8aed5400afda 100644
--- a/drivers/interconnect/qcom/icc-rpm.h
+++ b/drivers/interconnect/qcom/icc-rpm.h
@@ -66,6 +66,7 @@ struct qcom_icc_qos {
* @id: a unique node identifier
* @links: an array of nodes where we can go next while traversing
* @num_links: the total number of @links
+ * @channels: number of channels at this node (e.g. DDR channels)
* @buswidth: width of the interconnect between a node and the bus (bytes)
* @sum_avg: current sum aggregate value of all avg bw requests
* @max_peak: current max aggregate value of all peak bw requests
@@ -78,6 +79,7 @@ struct qcom_icc_node {
u16 id;
const u16 *links;
u16 num_links;
+ u16 channels;
u16 buswidth;
u64 sum_avg[QCOM_ICC_NUM_BUCKETS];
u64 max_peak[QCOM_ICC_NUM_BUCKETS];

--
2.39.1


2023-02-17 10:46:50

by Konrad Dybcio

[permalink] [raw]
Subject: [PATCH v5 03/10] interconnect: qcom: Sort kerneldoc entries

Sort the kerneldoc entries the same way the struct members are
sorted.

Signed-off-by: Konrad Dybcio <[email protected]>
---
drivers/interconnect/qcom/icc-rpm.h | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/interconnect/qcom/icc-rpm.h b/drivers/interconnect/qcom/icc-rpm.h
index 8aed5400afda..21f440beda86 100644
--- a/drivers/interconnect/qcom/icc-rpm.h
+++ b/drivers/interconnect/qcom/icc-rpm.h
@@ -23,12 +23,12 @@ enum qcom_icc_type {
/**
* struct qcom_icc_provider - Qualcomm specific interconnect provider
* @provider: generic interconnect provider
- * @bus_clks: the clk_bulk_data table of bus clocks
* @num_clks: the total number of clk_bulk_data entries
* @type: the ICC provider type
- * @qos_offset: offset to QoS registers
* @regmap: regmap for QoS registers read/write access
+ * @qos_offset: offset to QoS registers
* @bus_clk_rate: bus clock rate in Hz
+ * @bus_clks: the clk_bulk_data table of bus clocks
*/
struct qcom_icc_provider {
struct icc_provider provider;

--
2.39.1


2023-02-17 10:46:53

by Konrad Dybcio

[permalink] [raw]
Subject: [PATCH v5 04/10] interconnect: qcom: rpm: Rename icc desc clocks to bus_blocks

Rename the "clocks" (and _names) fields of qcom_icc_desc to
"bus_clocks" in preparation for introducing handling of clocks that
need to be enabled but not voted on with aggregate frequency.

Signed-off-by: Konrad Dybcio <[email protected]>
---
drivers/interconnect/qcom/icc-rpm.c | 6 +++---
drivers/interconnect/qcom/icc-rpm.h | 4 ++--
drivers/interconnect/qcom/msm8996.c | 12 ++++++------
drivers/interconnect/qcom/sdm660.c | 8 ++++----
4 files changed, 15 insertions(+), 15 deletions(-)

diff --git a/drivers/interconnect/qcom/icc-rpm.c b/drivers/interconnect/qcom/icc-rpm.c
index 6bd20f62f8ed..7a54fe4ccadd 100644
--- a/drivers/interconnect/qcom/icc-rpm.c
+++ b/drivers/interconnect/qcom/icc-rpm.c
@@ -441,9 +441,9 @@ int qnoc_probe(struct platform_device *pdev)
qnodes = desc->nodes;
num_nodes = desc->num_nodes;

- if (desc->num_clocks) {
- cds = desc->clocks;
- cd_num = desc->num_clocks;
+ if (desc->num_bus_clocks) {
+ cds = desc->bus_clocks;
+ cd_num = desc->num_bus_clocks;
} else {
cds = bus_clocks;
cd_num = ARRAY_SIZE(bus_clocks);
diff --git a/drivers/interconnect/qcom/icc-rpm.h b/drivers/interconnect/qcom/icc-rpm.h
index 21f440beda86..d6b4c56bf02c 100644
--- a/drivers/interconnect/qcom/icc-rpm.h
+++ b/drivers/interconnect/qcom/icc-rpm.h
@@ -91,8 +91,8 @@ struct qcom_icc_node {
struct qcom_icc_desc {
struct qcom_icc_node * const *nodes;
size_t num_nodes;
- const char * const *clocks;
- size_t num_clocks;
+ const char * const *bus_clocks;
+ size_t num_bus_clocks;
bool has_bus_pd;
enum qcom_icc_type type;
const struct regmap_config *regmap_cfg;
diff --git a/drivers/interconnect/qcom/msm8996.c b/drivers/interconnect/qcom/msm8996.c
index 25a1a32bc611..69fc50a6fa5c 100644
--- a/drivers/interconnect/qcom/msm8996.c
+++ b/drivers/interconnect/qcom/msm8996.c
@@ -1821,8 +1821,8 @@ static const struct qcom_icc_desc msm8996_a0noc = {
.type = QCOM_ICC_NOC,
.nodes = a0noc_nodes,
.num_nodes = ARRAY_SIZE(a0noc_nodes),
- .clocks = bus_a0noc_clocks,
- .num_clocks = ARRAY_SIZE(bus_a0noc_clocks),
+ .bus_clocks = bus_a0noc_clocks,
+ .num_bus_clocks = ARRAY_SIZE(bus_a0noc_clocks),
.has_bus_pd = true,
.regmap_cfg = &msm8996_a0noc_regmap_config
};
@@ -1866,8 +1866,8 @@ static const struct qcom_icc_desc msm8996_a2noc = {
.type = QCOM_ICC_NOC,
.nodes = a2noc_nodes,
.num_nodes = ARRAY_SIZE(a2noc_nodes),
- .clocks = bus_a2noc_clocks,
- .num_clocks = ARRAY_SIZE(bus_a2noc_clocks),
+ .bus_clocks = bus_a2noc_clocks,
+ .num_bus_clocks = ARRAY_SIZE(bus_a2noc_clocks),
.regmap_cfg = &msm8996_a2noc_regmap_config
};

@@ -2005,8 +2005,8 @@ static const struct qcom_icc_desc msm8996_mnoc = {
.type = QCOM_ICC_NOC,
.nodes = mnoc_nodes,
.num_nodes = ARRAY_SIZE(mnoc_nodes),
- .clocks = bus_mm_clocks,
- .num_clocks = ARRAY_SIZE(bus_mm_clocks),
+ .bus_clocks = bus_mm_clocks,
+ .num_bus_clocks = ARRAY_SIZE(bus_mm_clocks),
.regmap_cfg = &msm8996_mnoc_regmap_config
};

diff --git a/drivers/interconnect/qcom/sdm660.c b/drivers/interconnect/qcom/sdm660.c
index 8d879b0bcabc..a22ba821efbf 100644
--- a/drivers/interconnect/qcom/sdm660.c
+++ b/drivers/interconnect/qcom/sdm660.c
@@ -1516,8 +1516,8 @@ static const struct qcom_icc_desc sdm660_a2noc = {
.type = QCOM_ICC_NOC,
.nodes = sdm660_a2noc_nodes,
.num_nodes = ARRAY_SIZE(sdm660_a2noc_nodes),
- .clocks = bus_a2noc_clocks,
- .num_clocks = ARRAY_SIZE(bus_a2noc_clocks),
+ .bus_clocks = bus_a2noc_clocks,
+ .num_bus_clocks = ARRAY_SIZE(bus_a2noc_clocks),
.regmap_cfg = &sdm660_a2noc_regmap_config,
};

@@ -1659,8 +1659,8 @@ static const struct qcom_icc_desc sdm660_mnoc = {
.type = QCOM_ICC_NOC,
.nodes = sdm660_mnoc_nodes,
.num_nodes = ARRAY_SIZE(sdm660_mnoc_nodes),
- .clocks = bus_mm_clocks,
- .num_clocks = ARRAY_SIZE(bus_mm_clocks),
+ .bus_clocks = bus_mm_clocks,
+ .num_bus_clocks = ARRAY_SIZE(bus_mm_clocks),
.regmap_cfg = &sdm660_mnoc_regmap_config,
};


--
2.39.1


2023-02-17 10:46:56

by Konrad Dybcio

[permalink] [raw]
Subject: [PATCH v5 05/10] interconnect: qcom: rpm: Rename icc provider num_clocks to num_bus_clocks

In preparation for handling non-scaling clocks that we still have to
enable, rename num_clocks to more descriptive num_bus_clocks.

Signed-off-by: Konrad Dybcio <[email protected]>
---
drivers/interconnect/qcom/icc-rpm.c | 14 +++++++-------
drivers/interconnect/qcom/icc-rpm.h | 4 ++--
2 files changed, 9 insertions(+), 9 deletions(-)

diff --git a/drivers/interconnect/qcom/icc-rpm.c b/drivers/interconnect/qcom/icc-rpm.c
index 7a54fe4ccadd..f78c13e6c5ce 100644
--- a/drivers/interconnect/qcom/icc-rpm.c
+++ b/drivers/interconnect/qcom/icc-rpm.c
@@ -380,7 +380,7 @@ static int qcom_icc_set(struct icc_node *src, struct icc_node *dst)
return ret;
}

- for (i = 0; i < qp->num_clks; i++) {
+ for (i = 0; i < qp->num_bus_clks; i++) {
/*
* Use WAKE bucket for active clock, otherwise, use SLEEP bucket
* for other clocks. If a platform doesn't set interconnect
@@ -465,7 +465,7 @@ int qnoc_probe(struct platform_device *pdev)

for (i = 0; i < cd_num; i++)
qp->bus_clks[i].id = cds[i];
- qp->num_clks = cd_num;
+ qp->num_bus_clks = cd_num;

qp->type = desc->type;
qp->qos_offset = desc->qos_offset;
@@ -495,11 +495,11 @@ int qnoc_probe(struct platform_device *pdev)
}

regmap_done:
- ret = devm_clk_bulk_get_optional(dev, qp->num_clks, qp->bus_clks);
+ ret = devm_clk_bulk_get_optional(dev, qp->num_bus_clks, qp->bus_clks);
if (ret)
return ret;

- ret = clk_bulk_prepare_enable(qp->num_clks, qp->bus_clks);
+ ret = clk_bulk_prepare_enable(qp->num_bus_clks, qp->bus_clks);
if (ret)
return ret;

@@ -521,7 +521,7 @@ int qnoc_probe(struct platform_device *pdev)
ret = icc_provider_add(provider);
if (ret) {
dev_err(dev, "error adding interconnect provider: %d\n", ret);
- clk_bulk_disable_unprepare(qp->num_clks, qp->bus_clks);
+ clk_bulk_disable_unprepare(qp->num_bus_clks, qp->bus_clks);
return ret;
}

@@ -554,7 +554,7 @@ int qnoc_probe(struct platform_device *pdev)
return 0;
err:
icc_nodes_remove(provider);
- clk_bulk_disable_unprepare(qp->num_clks, qp->bus_clks);
+ clk_bulk_disable_unprepare(qp->num_bus_clks, qp->bus_clks);
icc_provider_del(provider);

return ret;
@@ -566,7 +566,7 @@ int qnoc_remove(struct platform_device *pdev)
struct qcom_icc_provider *qp = platform_get_drvdata(pdev);

icc_nodes_remove(&qp->provider);
- clk_bulk_disable_unprepare(qp->num_clks, qp->bus_clks);
+ clk_bulk_disable_unprepare(qp->num_bus_clks, qp->bus_clks);
icc_provider_del(&qp->provider);

return 0;
diff --git a/drivers/interconnect/qcom/icc-rpm.h b/drivers/interconnect/qcom/icc-rpm.h
index d6b4c56bf02c..d4401f35f6d2 100644
--- a/drivers/interconnect/qcom/icc-rpm.h
+++ b/drivers/interconnect/qcom/icc-rpm.h
@@ -23,7 +23,7 @@ enum qcom_icc_type {
/**
* struct qcom_icc_provider - Qualcomm specific interconnect provider
* @provider: generic interconnect provider
- * @num_clks: the total number of clk_bulk_data entries
+ * @num_bus_clks: the total number of bus_clks clk_bulk_data entries
* @type: the ICC provider type
* @regmap: regmap for QoS registers read/write access
* @qos_offset: offset to QoS registers
@@ -32,7 +32,7 @@ enum qcom_icc_type {
*/
struct qcom_icc_provider {
struct icc_provider provider;
- int num_clks;
+ int num_bus_clks;
enum qcom_icc_type type;
struct regmap *regmap;
unsigned int qos_offset;

--
2.39.1


2023-02-17 10:46:58

by Konrad Dybcio

[permalink] [raw]
Subject: [PATCH v5 06/10] interconnect: qcom: rpm: Handle interface clocks

Some (but not all) providers (or their specific nodes) require
specific clocks to be turned on before they can be accessed. Failure
to ensure that results in a seemingly random system crash (which
would usually happen at boot with the interconnect driver built-in),
resulting in the platform not booting up properly.

Limit the number of bus_clocks to 2 (which is the maximum that SMD
RPM interconnect supports anyway) and handle non-scaling clocks
separately. Update MSM8996 and SDM660 drivers to make sure they do
not regress with this change.

This unfortunately has to be done in one patch to prevent either
compile errors or broken bisect.

Signed-off-by: Konrad Dybcio <[email protected]>
---
drivers/interconnect/qcom/icc-rpm.c | 48 ++++++++++++++++++++++++++++---------
drivers/interconnect/qcom/icc-rpm.h | 10 ++++++--
drivers/interconnect/qcom/msm8996.c | 22 +++++++----------
drivers/interconnect/qcom/sdm660.c | 16 +++++--------
4 files changed, 60 insertions(+), 36 deletions(-)

diff --git a/drivers/interconnect/qcom/icc-rpm.c b/drivers/interconnect/qcom/icc-rpm.c
index f78c13e6c5ce..1b382a2f2710 100644
--- a/drivers/interconnect/qcom/icc-rpm.c
+++ b/drivers/interconnect/qcom/icc-rpm.c
@@ -441,28 +441,43 @@ int qnoc_probe(struct platform_device *pdev)
qnodes = desc->nodes;
num_nodes = desc->num_nodes;

- if (desc->num_bus_clocks) {
- cds = desc->bus_clocks;
- cd_num = desc->num_bus_clocks;
+ if (desc->num_intf_clocks) {
+ cds = desc->intf_clocks;
+ cd_num = desc->num_intf_clocks;
} else {
- cds = bus_clocks;
- cd_num = ARRAY_SIZE(bus_clocks);
+ /* 0 intf clocks is perfectly fine */
+ cd_num = 0;
}

- qp = devm_kzalloc(dev, struct_size(qp, bus_clks, cd_num), GFP_KERNEL);
+ qp = devm_kzalloc(dev, struct_size(qp, intf_clks, cd_num), GFP_KERNEL);
if (!qp)
return -ENOMEM;

- qp->bus_clk_rate = devm_kcalloc(dev, cd_num, sizeof(*qp->bus_clk_rate),
- GFP_KERNEL);
- if (!qp->bus_clk_rate)
- return -ENOMEM;
-
data = devm_kzalloc(dev, struct_size(data, nodes, num_nodes),
GFP_KERNEL);
if (!data)
return -ENOMEM;

+ for (i = 0; i < cd_num; i++)
+ qp->intf_clks[i].id = cds[i];
+ qp->num_intf_clks = cd_num;
+
+ if (desc->num_bus_clocks) {
+ cds = desc->bus_clocks;
+ cd_num = desc->num_bus_clocks;
+ } else {
+ cds = bus_clocks;
+ cd_num = ARRAY_SIZE(bus_clocks);
+ }
+
+ /*
+ * This is not realistic, scaling is only possible with an
+ * always-active and an active-only clock, or at least one
+ * of them in some very bizzare cases.
+ */
+ if (WARN_ON(cd_num > 2))
+ cd_num = 2;
+
for (i = 0; i < cd_num; i++)
qp->bus_clks[i].id = cds[i];
qp->num_bus_clks = cd_num;
@@ -503,6 +518,14 @@ int qnoc_probe(struct platform_device *pdev)
if (ret)
return ret;

+ ret = devm_clk_bulk_get(dev, qp->num_intf_clks, qp->intf_clks);
+ if (ret)
+ return ret;
+
+ ret = clk_bulk_prepare_enable(qp->num_intf_clks, qp->intf_clks);
+ if (ret)
+ return ret;
+
if (desc->has_bus_pd) {
ret = dev_pm_domain_attach(dev, true);
if (ret)
@@ -521,6 +544,7 @@ int qnoc_probe(struct platform_device *pdev)
ret = icc_provider_add(provider);
if (ret) {
dev_err(dev, "error adding interconnect provider: %d\n", ret);
+ clk_bulk_disable_unprepare(qp->num_intf_clks, qp->intf_clks);
clk_bulk_disable_unprepare(qp->num_bus_clks, qp->bus_clks);
return ret;
}
@@ -554,6 +578,7 @@ int qnoc_probe(struct platform_device *pdev)
return 0;
err:
icc_nodes_remove(provider);
+ clk_bulk_disable_unprepare(qp->num_intf_clks, qp->intf_clks);
clk_bulk_disable_unprepare(qp->num_bus_clks, qp->bus_clks);
icc_provider_del(provider);

@@ -566,6 +591,7 @@ int qnoc_remove(struct platform_device *pdev)
struct qcom_icc_provider *qp = platform_get_drvdata(pdev);

icc_nodes_remove(&qp->provider);
+ clk_bulk_disable_unprepare(qp->num_intf_clks, qp->intf_clks);
clk_bulk_disable_unprepare(qp->num_bus_clks, qp->bus_clks);
icc_provider_del(&qp->provider);

diff --git a/drivers/interconnect/qcom/icc-rpm.h b/drivers/interconnect/qcom/icc-rpm.h
index d4401f35f6d2..729573f0d9fe 100644
--- a/drivers/interconnect/qcom/icc-rpm.h
+++ b/drivers/interconnect/qcom/icc-rpm.h
@@ -24,20 +24,24 @@ enum qcom_icc_type {
* struct qcom_icc_provider - Qualcomm specific interconnect provider
* @provider: generic interconnect provider
* @num_bus_clks: the total number of bus_clks clk_bulk_data entries
+ * @num_intf_clks: the total number of intf_clks clk_bulk_data entries
* @type: the ICC provider type
* @regmap: regmap for QoS registers read/write access
* @qos_offset: offset to QoS registers
* @bus_clk_rate: bus clock rate in Hz
* @bus_clks: the clk_bulk_data table of bus clocks
+ * @intf_clks: the clk_bulk_data table of interface clocks
*/
struct qcom_icc_provider {
struct icc_provider provider;
int num_bus_clks;
+ int num_intf_clks;
enum qcom_icc_type type;
struct regmap *regmap;
unsigned int qos_offset;
- u64 *bus_clk_rate;
- struct clk_bulk_data bus_clks[];
+ u64 bus_clk_rate[2];
+ struct clk_bulk_data bus_clks[2];
+ struct clk_bulk_data intf_clks[];
};

/**
@@ -93,6 +97,8 @@ struct qcom_icc_desc {
size_t num_nodes;
const char * const *bus_clocks;
size_t num_bus_clocks;
+ const char * const *intf_clocks;
+ size_t num_intf_clocks;
bool has_bus_pd;
enum qcom_icc_type type;
const struct regmap_config *regmap_cfg;
diff --git a/drivers/interconnect/qcom/msm8996.c b/drivers/interconnect/qcom/msm8996.c
index 69fc50a6fa5c..1a5e0ad36cc4 100644
--- a/drivers/interconnect/qcom/msm8996.c
+++ b/drivers/interconnect/qcom/msm8996.c
@@ -21,21 +21,17 @@
#include "smd-rpm.h"
#include "msm8996.h"

-static const char * const bus_mm_clocks[] = {
- "bus",
- "bus_a",
+static const char * const mm_intf_clocks[] = {
"iface"
};

-static const char * const bus_a0noc_clocks[] = {
+static const char * const a0noc_intf_clocks[] = {
"aggre0_snoc_axi",
"aggre0_cnoc_ahb",
"aggre0_noc_mpu_cfg"
};

-static const char * const bus_a2noc_clocks[] = {
- "bus",
- "bus_a",
+static const char * const a2noc_intf_clocks[] = {
"aggre2_ufs_axi",
"ufs_axi"
};
@@ -1821,8 +1817,8 @@ static const struct qcom_icc_desc msm8996_a0noc = {
.type = QCOM_ICC_NOC,
.nodes = a0noc_nodes,
.num_nodes = ARRAY_SIZE(a0noc_nodes),
- .bus_clocks = bus_a0noc_clocks,
- .num_bus_clocks = ARRAY_SIZE(bus_a0noc_clocks),
+ .intf_clocks = a0noc_intf_clocks,
+ .num_intf_clocks = ARRAY_SIZE(a0noc_intf_clocks),
.has_bus_pd = true,
.regmap_cfg = &msm8996_a0noc_regmap_config
};
@@ -1866,8 +1862,8 @@ static const struct qcom_icc_desc msm8996_a2noc = {
.type = QCOM_ICC_NOC,
.nodes = a2noc_nodes,
.num_nodes = ARRAY_SIZE(a2noc_nodes),
- .bus_clocks = bus_a2noc_clocks,
- .num_bus_clocks = ARRAY_SIZE(bus_a2noc_clocks),
+ .intf_clocks = a2noc_intf_clocks,
+ .num_intf_clocks = ARRAY_SIZE(a2noc_intf_clocks),
.regmap_cfg = &msm8996_a2noc_regmap_config
};

@@ -2005,8 +2001,8 @@ static const struct qcom_icc_desc msm8996_mnoc = {
.type = QCOM_ICC_NOC,
.nodes = mnoc_nodes,
.num_nodes = ARRAY_SIZE(mnoc_nodes),
- .bus_clocks = bus_mm_clocks,
- .num_bus_clocks = ARRAY_SIZE(bus_mm_clocks),
+ .intf_clocks = mm_intf_clocks,
+ .num_intf_clocks = ARRAY_SIZE(mm_intf_clocks),
.regmap_cfg = &msm8996_mnoc_regmap_config
};

diff --git a/drivers/interconnect/qcom/sdm660.c b/drivers/interconnect/qcom/sdm660.c
index a22ba821efbf..0e8a96f4ce90 100644
--- a/drivers/interconnect/qcom/sdm660.c
+++ b/drivers/interconnect/qcom/sdm660.c
@@ -127,15 +127,11 @@ enum {
SDM660_SNOC,
};

-static const char * const bus_mm_clocks[] = {
- "bus",
- "bus_a",
+static const char * const mm_intf_clocks[] = {
"iface",
};

-static const char * const bus_a2noc_clocks[] = {
- "bus",
- "bus_a",
+static const char * const a2noc_intf_clocks[] = {
"ipa",
"ufs_axi",
"aggre2_ufs_axi",
@@ -1516,8 +1512,8 @@ static const struct qcom_icc_desc sdm660_a2noc = {
.type = QCOM_ICC_NOC,
.nodes = sdm660_a2noc_nodes,
.num_nodes = ARRAY_SIZE(sdm660_a2noc_nodes),
- .bus_clocks = bus_a2noc_clocks,
- .num_bus_clocks = ARRAY_SIZE(bus_a2noc_clocks),
+ .intf_clocks = a2noc_intf_clocks,
+ .num_intf_clocks = ARRAY_SIZE(a2noc_intf_clocks),
.regmap_cfg = &sdm660_a2noc_regmap_config,
};

@@ -1659,8 +1655,8 @@ static const struct qcom_icc_desc sdm660_mnoc = {
.type = QCOM_ICC_NOC,
.nodes = sdm660_mnoc_nodes,
.num_nodes = ARRAY_SIZE(sdm660_mnoc_nodes),
- .bus_clocks = bus_mm_clocks,
- .num_bus_clocks = ARRAY_SIZE(bus_mm_clocks),
+ .intf_clocks = mm_intf_clocks,
+ .num_intf_clocks = ARRAY_SIZE(mm_intf_clocks),
.regmap_cfg = &sdm660_mnoc_regmap_config,
};


--
2.39.1


2023-02-17 10:47:07

by Konrad Dybcio

[permalink] [raw]
Subject: [PATCH v5 07/10] interconnect: qcom: icc-rpm: Allow negative num_bus_clocks

In some rare cases, buses will not have *any* bus-scaling clocks,
which is "fine", as the voting can be done through RPM provided that
the necessary QoS clocks are enabled. Allow specifying a negative (-1)
number of clocks to make the driver accept such cases, without having
to add a lot of boilerplate to all existing ICC drivers for SoCs with
SMD RPM.

FWIW this value was previously being assigned to a >>signed<< integer
as well.

Signed-off-by: Konrad Dybcio <[email protected]>
---
drivers/interconnect/qcom/icc-rpm.h | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/interconnect/qcom/icc-rpm.h b/drivers/interconnect/qcom/icc-rpm.h
index 729573f0d9fe..9dd631964b8c 100644
--- a/drivers/interconnect/qcom/icc-rpm.h
+++ b/drivers/interconnect/qcom/icc-rpm.h
@@ -96,7 +96,7 @@ struct qcom_icc_desc {
struct qcom_icc_node * const *nodes;
size_t num_nodes;
const char * const *bus_clocks;
- size_t num_bus_clocks;
+ int num_bus_clocks;
const char * const *intf_clocks;
size_t num_intf_clocks;
bool has_bus_pd;

--
2.39.1


2023-02-17 10:47:11

by Konrad Dybcio

[permalink] [raw]
Subject: [PATCH v5 08/10] interconnect: qcom: msm8996: Specify no bus clock scaling on A0NoC

A0NoC only does bus scaling through RPM votes and does not have any
ICC clocks. Describe this.

Signed-off-by: Konrad Dybcio <[email protected]>
---
drivers/interconnect/qcom/msm8996.c | 1 +
1 file changed, 1 insertion(+)

diff --git a/drivers/interconnect/qcom/msm8996.c b/drivers/interconnect/qcom/msm8996.c
index 1a5e0ad36cc4..45eb8675fb11 100644
--- a/drivers/interconnect/qcom/msm8996.c
+++ b/drivers/interconnect/qcom/msm8996.c
@@ -1817,6 +1817,7 @@ static const struct qcom_icc_desc msm8996_a0noc = {
.type = QCOM_ICC_NOC,
.nodes = a0noc_nodes,
.num_nodes = ARRAY_SIZE(a0noc_nodes),
+ .num_bus_clocks = -1, /* No bus clock scaling */
.intf_clocks = a0noc_intf_clocks,
.num_intf_clocks = ARRAY_SIZE(a0noc_intf_clocks),
.has_bus_pd = true,

--
2.39.1


2023-02-17 10:47:15

by Konrad Dybcio

[permalink] [raw]
Subject: [PATCH v5 09/10] interconnect: qcom: rpm: Don't use clk_get_optional for bus clocks anymore

Commit dd42ec8ea5b9 ("interconnect: qcom: rpm: Use _optional func for provider clocks")
relaxed the requirements around probing bus clocks. This was a decent
solution for making sure MSM8996 would still boot with old DTs, but
now that there's a proper fix in place that both old and new DTs
will be happy about, revert back to the safer variant of the
function.

Fixes: dd42ec8ea5b9 ("interconnect: qcom: rpm: Use _optional func for provider clocks")
Signed-off-by: Konrad Dybcio <[email protected]>
---
drivers/interconnect/qcom/icc-rpm.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/interconnect/qcom/icc-rpm.c b/drivers/interconnect/qcom/icc-rpm.c
index 1b382a2f2710..7c2ed224d0e7 100644
--- a/drivers/interconnect/qcom/icc-rpm.c
+++ b/drivers/interconnect/qcom/icc-rpm.c
@@ -510,7 +510,7 @@ int qnoc_probe(struct platform_device *pdev)
}

regmap_done:
- ret = devm_clk_bulk_get_optional(dev, qp->num_bus_clks, qp->bus_clks);
+ ret = devm_clk_bulk_get(dev, qp->num_bus_clks, qp->bus_clks);
if (ret)
return ret;


--
2.39.1


2023-02-17 10:47:25

by Konrad Dybcio

[permalink] [raw]
Subject: [PATCH v5 10/10] interconnect: qcom: msm8996: Promote to core_initcall

The interconnect driver is (or soon will be) vital to many other
devices, as it's not a given that the bootloader will set up enough
bandwidth for us or that the values we come into are reasonable.

Promote the driver to core_initcall to ensure the consumers (i.e.
most "meaningful" parts of the SoC) can probe without deferrals.

Signed-off-by: Konrad Dybcio <[email protected]>
---
drivers/interconnect/qcom/msm8996.c | 12 +++++++++++-
1 file changed, 11 insertions(+), 1 deletion(-)

diff --git a/drivers/interconnect/qcom/msm8996.c b/drivers/interconnect/qcom/msm8996.c
index 45eb8675fb11..0e0395328dc7 100644
--- a/drivers/interconnect/qcom/msm8996.c
+++ b/drivers/interconnect/qcom/msm8996.c
@@ -2109,7 +2109,17 @@ static struct platform_driver qnoc_driver = {
.sync_state = icc_sync_state,
}
};
-module_platform_driver(qnoc_driver);
+static int __init qnoc_driver_init(void)
+{
+ return platform_driver_register(&qnoc_driver);
+}
+core_initcall(qnoc_driver_init);
+
+static void __exit qnoc_driver_exit(void)
+{
+ platform_driver_unregister(&qnoc_driver);
+}
+module_exit(qnoc_driver_exit);

MODULE_AUTHOR("Yassine Oudjana <[email protected]>");
MODULE_DESCRIPTION("Qualcomm MSM8996 NoC driver");

--
2.39.1


2023-02-17 19:27:38

by Konrad Dybcio

[permalink] [raw]
Subject: Re: [PATCH v5 08/10] interconnect: qcom: msm8996: Specify no bus clock scaling on A0NoC



On 17.02.2023 11:46, Konrad Dybcio wrote:
> A0NoC only does bus scaling through RPM votes and does not have any
> ICC clocks. Describe this.
>
> Signed-off-by: Konrad Dybcio <[email protected]>
> ---
This is bad, as devm_clk_get_bulk{"", _optional} doesn't
check if num_clocks makes sense and passes "-1" down the
devres alloc chain..

I'll rework this for the next revision by simply assigning
the common "bus", "bus_a" set everywhere instead of relying
on it being there by default..

Konrad
> drivers/interconnect/qcom/msm8996.c | 1 +
> 1 file changed, 1 insertion(+)
>
> diff --git a/drivers/interconnect/qcom/msm8996.c b/drivers/interconnect/qcom/msm8996.c
> index 1a5e0ad36cc4..45eb8675fb11 100644
> --- a/drivers/interconnect/qcom/msm8996.c
> +++ b/drivers/interconnect/qcom/msm8996.c
> @@ -1817,6 +1817,7 @@ static const struct qcom_icc_desc msm8996_a0noc = {
> .type = QCOM_ICC_NOC,
> .nodes = a0noc_nodes,
> .num_nodes = ARRAY_SIZE(a0noc_nodes),
> + .num_bus_clocks = -1, /* No bus clock scaling */
> .intf_clocks = a0noc_intf_clocks,
> .num_intf_clocks = ARRAY_SIZE(a0noc_intf_clocks),
> .has_bus_pd = true,
>

2023-02-17 19:53:25

by Konrad Dybcio

[permalink] [raw]
Subject: Re: [PATCH v5 08/10] interconnect: qcom: msm8996: Specify no bus clock scaling on A0NoC



On 17.02.2023 20:27, Konrad Dybcio wrote:
>
>
> On 17.02.2023 11:46, Konrad Dybcio wrote:
>> A0NoC only does bus scaling through RPM votes and does not have any
>> ICC clocks. Describe this.
>>
>> Signed-off-by: Konrad Dybcio <[email protected]>
>> ---
> This is bad, as devm_clk_get_bulk{"", _optional} doesn't
> check if num_clocks makes sense and passes "-1" down the
> devres alloc chain..
>
> I'll rework this for the next revision by simply assigning
> the common "bus", "bus_a" set everywhere instead of relying
> on it being there by default..
Or maybe I shouldn't, as that will require redefining the array
over and over again.. Perhaps just passing <&xo_board>, <&xo_board>
to a0noc's "bus", "bus_a", similar to what's been done on SDM630's
GNoC would be less messy?

Konrad
>
> Konrad
>> drivers/interconnect/qcom/msm8996.c | 1 +
>> 1 file changed, 1 insertion(+)
>>
>> diff --git a/drivers/interconnect/qcom/msm8996.c b/drivers/interconnect/qcom/msm8996.c
>> index 1a5e0ad36cc4..45eb8675fb11 100644
>> --- a/drivers/interconnect/qcom/msm8996.c
>> +++ b/drivers/interconnect/qcom/msm8996.c
>> @@ -1817,6 +1817,7 @@ static const struct qcom_icc_desc msm8996_a0noc = {
>> .type = QCOM_ICC_NOC,
>> .nodes = a0noc_nodes,
>> .num_nodes = ARRAY_SIZE(a0noc_nodes),
>> + .num_bus_clocks = -1, /* No bus clock scaling */
>> .intf_clocks = a0noc_intf_clocks,
>> .num_intf_clocks = ARRAY_SIZE(a0noc_intf_clocks),
>> .has_bus_pd = true,
>>

2023-02-17 20:26:51

by Dmitry Baryshkov

[permalink] [raw]
Subject: Re: [PATCH v5 08/10] interconnect: qcom: msm8996: Specify no bus clock scaling on A0NoC

On Fri, 17 Feb 2023 at 21:53, Konrad Dybcio <[email protected]> wrote:
>
>
>
> On 17.02.2023 20:27, Konrad Dybcio wrote:
> >
> >
> > On 17.02.2023 11:46, Konrad Dybcio wrote:
> >> A0NoC only does bus scaling through RPM votes and does not have any
> >> ICC clocks. Describe this.
> >>
> >> Signed-off-by: Konrad Dybcio <[email protected]>
> >> ---
> > This is bad, as devm_clk_get_bulk{"", _optional} doesn't
> > check if num_clocks makes sense and passes "-1" down the
> > devres alloc chain..
> >
> > I'll rework this for the next revision by simply assigning
> > the common "bus", "bus_a" set everywhere instead of relying
> > on it being there by default..
> Or maybe I shouldn't, as that will require redefining the array
> over and over again.. Perhaps just passing <&xo_board>, <&xo_board>
> to a0noc's "bus", "bus_a", similar to what's been done on SDM630's
> GNoC would be less messy?

What about simply skipping a call to devm_clk_get if num_bus_clocks is negative?

>
> Konrad
> >
> > Konrad
> >> drivers/interconnect/qcom/msm8996.c | 1 +
> >> 1 file changed, 1 insertion(+)
> >>
> >> diff --git a/drivers/interconnect/qcom/msm8996.c b/drivers/interconnect/qcom/msm8996.c
> >> index 1a5e0ad36cc4..45eb8675fb11 100644
> >> --- a/drivers/interconnect/qcom/msm8996.c
> >> +++ b/drivers/interconnect/qcom/msm8996.c
> >> @@ -1817,6 +1817,7 @@ static const struct qcom_icc_desc msm8996_a0noc = {
> >> .type = QCOM_ICC_NOC,
> >> .nodes = a0noc_nodes,
> >> .num_nodes = ARRAY_SIZE(a0noc_nodes),
> >> + .num_bus_clocks = -1, /* No bus clock scaling */
> >> .intf_clocks = a0noc_intf_clocks,
> >> .num_intf_clocks = ARRAY_SIZE(a0noc_intf_clocks),
> >> .has_bus_pd = true,
> >>



--
With best wishes
Dmitry

2023-02-17 20:29:02

by Konrad Dybcio

[permalink] [raw]
Subject: Re: [PATCH v5 08/10] interconnect: qcom: msm8996: Specify no bus clock scaling on A0NoC



On 17.02.2023 21:26, Dmitry Baryshkov wrote:
> On Fri, 17 Feb 2023 at 21:53, Konrad Dybcio <[email protected]> wrote:
>>
>>
>>
>> On 17.02.2023 20:27, Konrad Dybcio wrote:
>>>
>>>
>>> On 17.02.2023 11:46, Konrad Dybcio wrote:
>>>> A0NoC only does bus scaling through RPM votes and does not have any
>>>> ICC clocks. Describe this.
>>>>
>>>> Signed-off-by: Konrad Dybcio <[email protected]>
>>>> ---
>>> This is bad, as devm_clk_get_bulk{"", _optional} doesn't
>>> check if num_clocks makes sense and passes "-1" down the
>>> devres alloc chain..
>>>
>>> I'll rework this for the next revision by simply assigning
>>> the common "bus", "bus_a" set everywhere instead of relying
>>> on it being there by default..
>> Or maybe I shouldn't, as that will require redefining the array
>> over and over again.. Perhaps just passing <&xo_board>, <&xo_board>
>> to a0noc's "bus", "bus_a", similar to what's been done on SDM630's
>> GNoC would be less messy?
>
> What about simply skipping a call to devm_clk_get if num_bus_clocks is negative?
I tested that locally before reporting the mistake on my side and
while it works, I just consider it.. ugly, because:

num_clocks =
>0 => use the externally specified num_/clocks (logical)
=0 => use the default 2
<0 => consider there's zero

..but maybe that's just me.. if you don't find it ugly, I may just
go with that.

Konrad
>
>>
>> Konrad
>>>
>>> Konrad
>>>> drivers/interconnect/qcom/msm8996.c | 1 +
>>>> 1 file changed, 1 insertion(+)
>>>>
>>>> diff --git a/drivers/interconnect/qcom/msm8996.c b/drivers/interconnect/qcom/msm8996.c
>>>> index 1a5e0ad36cc4..45eb8675fb11 100644
>>>> --- a/drivers/interconnect/qcom/msm8996.c
>>>> +++ b/drivers/interconnect/qcom/msm8996.c
>>>> @@ -1817,6 +1817,7 @@ static const struct qcom_icc_desc msm8996_a0noc = {
>>>> .type = QCOM_ICC_NOC,
>>>> .nodes = a0noc_nodes,
>>>> .num_nodes = ARRAY_SIZE(a0noc_nodes),
>>>> + .num_bus_clocks = -1, /* No bus clock scaling */
>>>> .intf_clocks = a0noc_intf_clocks,
>>>> .num_intf_clocks = ARRAY_SIZE(a0noc_intf_clocks),
>>>> .has_bus_pd = true,
>>>>
>
>
>

2023-02-17 22:19:41

by Dmitry Baryshkov

[permalink] [raw]
Subject: Re: [PATCH v5 08/10] interconnect: qcom: msm8996: Specify no bus clock scaling on A0NoC

On 17/02/2023 22:28, Konrad Dybcio wrote:
>
>
> On 17.02.2023 21:26, Dmitry Baryshkov wrote:
>> On Fri, 17 Feb 2023 at 21:53, Konrad Dybcio <[email protected]> wrote:
>>>
>>>
>>>
>>> On 17.02.2023 20:27, Konrad Dybcio wrote:
>>>>
>>>>
>>>> On 17.02.2023 11:46, Konrad Dybcio wrote:
>>>>> A0NoC only does bus scaling through RPM votes and does not have any
>>>>> ICC clocks. Describe this.
>>>>>
>>>>> Signed-off-by: Konrad Dybcio <[email protected]>
>>>>> ---
>>>> This is bad, as devm_clk_get_bulk{"", _optional} doesn't
>>>> check if num_clocks makes sense and passes "-1" down the
>>>> devres alloc chain..
>>>>
>>>> I'll rework this for the next revision by simply assigning
>>>> the common "bus", "bus_a" set everywhere instead of relying
>>>> on it being there by default..
>>> Or maybe I shouldn't, as that will require redefining the array
>>> over and over again.. Perhaps just passing <&xo_board>, <&xo_board>
>>> to a0noc's "bus", "bus_a", similar to what's been done on SDM630's
>>> GNoC would be less messy?
>>
>> What about simply skipping a call to devm_clk_get if num_bus_clocks is negative?
> I tested that locally before reporting the mistake on my side and
> while it works, I just consider it.. ugly, because:
>
> num_clocks =
>> 0 => use the externally specified num_/clocks (logical)
> =0 => use the default 2
> <0 => consider there's zero
>
> ..but maybe that's just me.. if you don't find it ugly, I may just
> go with that.

Would 'lesser ugliness' count? Maybe add a define 'ICC_RPM_NO_CLOCKS =
-1'? I think that spawning default bus & bus_a everywhere would be worse.

When this driver is rewritten in Rust, we'll have a clear distinction
between None (meaning default two clocks) and Some(0) (meaning no
clocks). Wait, does that sound even more ugly?

--
With best wishes
Dmitry


2023-02-23 13:01:54

by Bryan O'Donoghue

[permalink] [raw]
Subject: Re: [PATCH v5 01/10] interconnect: qcom: rpm: make QoS INVALID default, separate out driver data

On 17/02/2023 10:46, Konrad Dybcio wrote:

I find this commit log difficult to understand.

Could you reduce it down ?

> Currently, NOC_QOS_MODE_FIXED is defined as 0x0, which makes it the
> "default" option (as that's what uninitialized members of partially
> initialized structs are set to), which should really have been
> NOC_QOS_MODE_INVALID, and that's what people (wrongly) assumed was
> the case when .qos.qos_mode was not defined and what really makes
> the most sense..

"Currently NOC_QOS_MODE_FIXED is defined as 0x0 which makes it the
default option. The default option however should be NOC_QOS_MODE_INVALID"

> That resulted in {port 0, prio 0, areq_prio 0, urg_fwd = false, rpm-voted}
> QoS being always voted for, because the code flow assumed "hey, it's fixed
> QoS, so let's just roll with whatever parameters are set" [again, set by
> partial struct initialization, as these fields were left unfilled by the
> developers]. That is of course incorrect, and on many of these platforms
> port 0 is MAS_APPS_PROC, which 9/10 times is supposed to be handled by
> the ap_owned path, not to mention the rest of the parameters may differ.
> Arguably, the APPS node is the most important one, next to EBI0..

This paragraph in particular is difficult to decipher, at least for me
with my native Dublinese


> The modes are defined as preprocessor constants. They are not used
> anywhere outside the driver or sent to any remote processor outside
> qcom_icc_set_noc_qos(), which is easily worked around.
> Separate the type specified in driver data from the value sent to msmbus.
> Make the former an enum for better mainainability.
>
> This is an implicit fix for every SMD RPM ICC driver that didn't
> explicitly specify NOC_QOS_MODE_INVALID on non-AP_owned nodes that
> don't have QoS settings.

It would be nice to reduce the commit log down to say three paragraphs
of no more than three sentences each.

---
bod

2023-02-23 14:04:06

by Bjorn Andersson

[permalink] [raw]
Subject: Re: [PATCH v5 08/10] interconnect: qcom: msm8996: Specify no bus clock scaling on A0NoC

On Fri, Feb 17, 2023 at 09:28:54PM +0100, Konrad Dybcio wrote:
>
>
> On 17.02.2023 21:26, Dmitry Baryshkov wrote:
> > On Fri, 17 Feb 2023 at 21:53, Konrad Dybcio <[email protected]> wrote:
> >>
> >>
> >>
> >> On 17.02.2023 20:27, Konrad Dybcio wrote:
> >>>
> >>>
> >>> On 17.02.2023 11:46, Konrad Dybcio wrote:
> >>>> A0NoC only does bus scaling through RPM votes and does not have any
> >>>> ICC clocks. Describe this.
> >>>>
> >>>> Signed-off-by: Konrad Dybcio <[email protected]>
> >>>> ---
> >>> This is bad, as devm_clk_get_bulk{"", _optional} doesn't
> >>> check if num_clocks makes sense and passes "-1" down the
> >>> devres alloc chain..
> >>>
> >>> I'll rework this for the next revision by simply assigning
> >>> the common "bus", "bus_a" set everywhere instead of relying
> >>> on it being there by default..
> >> Or maybe I shouldn't, as that will require redefining the array
> >> over and over again.. Perhaps just passing <&xo_board>, <&xo_board>
> >> to a0noc's "bus", "bus_a", similar to what's been done on SDM630's
> >> GNoC would be less messy?
> >
> > What about simply skipping a call to devm_clk_get if num_bus_clocks is negative?
> I tested that locally before reporting the mistake on my side and
> while it works, I just consider it.. ugly, because:
>
> num_clocks =
> >0 => use the externally specified num_/clocks (logical)
> =0 => use the default 2

Why not let go of this "convenience" and have num_clocks actually mean
number of clocks?

Regards,
Bjorn

> <0 => consider there's zero
>
> ..but maybe that's just me.. if you don't find it ugly, I may just
> go with that.
>
> Konrad
> >
> >>
> >> Konrad
> >>>
> >>> Konrad
> >>>> drivers/interconnect/qcom/msm8996.c | 1 +
> >>>> 1 file changed, 1 insertion(+)
> >>>>
> >>>> diff --git a/drivers/interconnect/qcom/msm8996.c b/drivers/interconnect/qcom/msm8996.c
> >>>> index 1a5e0ad36cc4..45eb8675fb11 100644
> >>>> --- a/drivers/interconnect/qcom/msm8996.c
> >>>> +++ b/drivers/interconnect/qcom/msm8996.c
> >>>> @@ -1817,6 +1817,7 @@ static const struct qcom_icc_desc msm8996_a0noc = {
> >>>> .type = QCOM_ICC_NOC,
> >>>> .nodes = a0noc_nodes,
> >>>> .num_nodes = ARRAY_SIZE(a0noc_nodes),
> >>>> + .num_bus_clocks = -1, /* No bus clock scaling */
> >>>> .intf_clocks = a0noc_intf_clocks,
> >>>> .num_intf_clocks = ARRAY_SIZE(a0noc_intf_clocks),
> >>>> .has_bus_pd = true,
> >>>>
> >
> >
> >

2023-02-23 14:18:24

by Konrad Dybcio

[permalink] [raw]
Subject: Re: [PATCH v5 08/10] interconnect: qcom: msm8996: Specify no bus clock scaling on A0NoC



On 23.02.2023 15:07, Bjorn Andersson wrote:
> On Fri, Feb 17, 2023 at 09:28:54PM +0100, Konrad Dybcio wrote:
>>
>>
>> On 17.02.2023 21:26, Dmitry Baryshkov wrote:
>>> On Fri, 17 Feb 2023 at 21:53, Konrad Dybcio <[email protected]> wrote:
>>>>
>>>>
>>>>
>>>> On 17.02.2023 20:27, Konrad Dybcio wrote:
>>>>>
>>>>>
>>>>> On 17.02.2023 11:46, Konrad Dybcio wrote:
>>>>>> A0NoC only does bus scaling through RPM votes and does not have any
>>>>>> ICC clocks. Describe this.
>>>>>>
>>>>>> Signed-off-by: Konrad Dybcio <[email protected]>
>>>>>> ---
>>>>> This is bad, as devm_clk_get_bulk{"", _optional} doesn't
>>>>> check if num_clocks makes sense and passes "-1" down the
>>>>> devres alloc chain..
>>>>>
>>>>> I'll rework this for the next revision by simply assigning
>>>>> the common "bus", "bus_a" set everywhere instead of relying
>>>>> on it being there by default..
>>>> Or maybe I shouldn't, as that will require redefining the array
>>>> over and over again.. Perhaps just passing <&xo_board>, <&xo_board>
>>>> to a0noc's "bus", "bus_a", similar to what's been done on SDM630's
>>>> GNoC would be less messy?
>>>
>>> What about simply skipping a call to devm_clk_get if num_bus_clocks is negative?
>> I tested that locally before reporting the mistake on my side and
>> while it works, I just consider it.. ugly, because:
>>
>> num_clocks =
>>> 0 => use the externally specified num_/clocks (logical)
>> =0 => use the default 2
>
> Why not let go of this "convenience" and have num_clocks actually mean
> number of clocks?
Sounds good.. Should I keep the default "bus", "bus_a" on absence of
.bus_clocks still, to avoid duplicating objects?

Konrad

>
> Regards,
> Bjorn
>
>> <0 => consider there's zero
>>
>> ..but maybe that's just me.. if you don't find it ugly, I may just
>> go with that.
>>
>> Konrad
>>>
>>>>
>>>> Konrad
>>>>>
>>>>> Konrad
>>>>>> drivers/interconnect/qcom/msm8996.c | 1 +
>>>>>> 1 file changed, 1 insertion(+)
>>>>>>
>>>>>> diff --git a/drivers/interconnect/qcom/msm8996.c b/drivers/interconnect/qcom/msm8996.c
>>>>>> index 1a5e0ad36cc4..45eb8675fb11 100644
>>>>>> --- a/drivers/interconnect/qcom/msm8996.c
>>>>>> +++ b/drivers/interconnect/qcom/msm8996.c
>>>>>> @@ -1817,6 +1817,7 @@ static const struct qcom_icc_desc msm8996_a0noc = {
>>>>>> .type = QCOM_ICC_NOC,
>>>>>> .nodes = a0noc_nodes,
>>>>>> .num_nodes = ARRAY_SIZE(a0noc_nodes),
>>>>>> + .num_bus_clocks = -1, /* No bus clock scaling */
>>>>>> .intf_clocks = a0noc_intf_clocks,
>>>>>> .num_intf_clocks = ARRAY_SIZE(a0noc_intf_clocks),
>>>>>> .has_bus_pd = true,
>>>>>>
>>>
>>>
>>>