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 | 23 +++++++++++++----------
drivers/interconnect/qcom/icc-rpm.h | 10 ++++++----
2 files changed, 19 insertions(+), 14 deletions(-)
diff --git a/drivers/interconnect/qcom/icc-rpm.c b/drivers/interconnect/qcom/icc-rpm.c
index 361dcbf3386f..cd1eab3d93ba 100644
--- a/drivers/interconnect/qcom/icc-rpm.c
+++ b/drivers/interconnect/qcom/icc-rpm.c
@@ -48,6 +48,10 @@
#define NOC_QOS_MODEn_ADDR(n) (0xc + (n * 0x1000))
#define NOC_QOS_MODEn_MASK 0x3
+#define NOC_QOS_MODE_INVALID_VAL -1
+#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 +157,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 +171,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,
diff --git a/drivers/interconnect/qcom/icc-rpm.h b/drivers/interconnect/qcom/icc-rpm.h
index 13d5252f08a5..3762648f9d47 100644
--- a/drivers/interconnect/qcom/icc-rpm.h
+++ b/drivers/interconnect/qcom/icc-rpm.h
@@ -97,10 +97,12 @@ struct qcom_icc_desc {
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.0
On 10/01/2023 13:21, Konrad Dybcio wrote:
> +#define NOC_QOS_MODE_INVALID_VAL -1
> +#define NOC_QOS_MODE_FIXED_VAL 0x0
> +#define NOC_QOS_MODE_BYPASS_VAL 0x2
The basic fix you are applying here makes sense to me.
But why bother with an additional _VAL defintion, you have your enum.
+enum qos_mode {
+ NOC_QOS_MODE_INVALID = 0,
+ NOC_QOS_MODE_FIXED,
+ NOC_QOS_MODE_BYPASS,
+};
---
bod
On 11.01.2023 00:13, Bryan O'Donoghue wrote:
> On 10/01/2023 13:21, Konrad Dybcio wrote:
>> +#define NOC_QOS_MODE_INVALID_VAL -1
>> +#define NOC_QOS_MODE_FIXED_VAL 0x0
>> +#define NOC_QOS_MODE_BYPASS_VAL 0x2
>
> The basic fix you are applying here makes sense to me.
>
> But why bother with an additional _VAL defintion, you have your enum.
Thinking about it, I was probably confused by MODE_INVALID checks in
qcom_icc_set_bimc_qos and only now realized that it's not even called
with MODE_INVALID.. Will surely fix!
Konrad
>
> +enum qos_mode {
> + NOC_QOS_MODE_INVALID = 0,
> + NOC_QOS_MODE_FIXED,
> + NOC_QOS_MODE_BYPASS,
> +};
>
> ---
> bod
On 11.01.2023 00:47, Konrad Dybcio wrote:
>
>
> On 11.01.2023 00:13, Bryan O'Donoghue wrote:
>> On 10/01/2023 13:21, Konrad Dybcio wrote:
>>> +#define NOC_QOS_MODE_INVALID_VAL -1
>>> +#define NOC_QOS_MODE_FIXED_VAL 0x0
>>> +#define NOC_QOS_MODE_BYPASS_VAL 0x2
>>
>> The basic fix you are applying here makes sense to me.
>>
>> But why bother with an additional _VAL defintion, you have your enum.
> Thinking about it, I was probably confused by MODE_INVALID checks in
> qcom_icc_set_bimc_qos and only now realized that it's not even called
> with MODE_INVALID.. Will surely fix!
Actually, no.. qcom_icc_set_noc_qos() writes the _VAL to
NOC_QOS_MODEn_ADDR(), so it does matter.
Konrad
>
> Konrad
>>
>> +enum qos_mode {
>> + NOC_QOS_MODE_INVALID = 0,
>> + NOC_QOS_MODE_FIXED,
>> + NOC_QOS_MODE_BYPASS,
>> +};
>>
>> ---
>> bod