Interconnects and interconnect paths quantify their performance levels in
terms of bandwidth and not in terms of frequency. So similar to how we have
frequency based OPP tables in DT and in the OPP framework, we need
bandwidth OPP table support in DT and in the OPP framework.
So with the DT bindings added in this patch series, the DT for a GPU
that does bandwidth voting from GPU to Cache and GPU to DDR would look
something like this:
gpu_cache_opp_table: gpu_cache_opp_table {
compatible = "operating-points-v2";
gpu_cache_3000: opp-3000 {
opp-peak-KBps = <3000000>;
opp-avg-KBps = <1000000>;
};
gpu_cache_6000: opp-6000 {
opp-peak-KBps = <6000000>;
opp-avg-KBps = <2000000>;
};
gpu_cache_9000: opp-9000 {
opp-peak-KBps = <9000000>;
opp-avg-KBps = <9000000>;
};
};
gpu_ddr_opp_table: gpu_ddr_opp_table {
compatible = "operating-points-v2";
gpu_ddr_1525: opp-1525 {
opp-peak-KBps = <1525000>;
opp-avg-KBps = <452000>;
};
gpu_ddr_3051: opp-3051 {
opp-peak-KBps = <3051000>;
opp-avg-KBps = <915000>;
};
gpu_ddr_7500: opp-7500 {
opp-peak-KBps = <7500000>;
opp-avg-KBps = <3000000>;
};
};
gpu_opp_table: gpu_opp_table {
compatible = "operating-points-v2";
opp-shared;
opp-200000000 {
opp-hz = /bits/ 64 <200000000>;
};
opp-400000000 {
opp-hz = /bits/ 64 <400000000>;
};
};
gpu@7864000 {
...
operating-points-v2 = <&gpu_opp_table>, <&gpu_cache_opp_table>, <&gpu_ddr_opp_table>;
...
};
v1 -> v3:
- Lots of patch additions that were later dropped
v3 -> v4:
- Fixed typo bugs pointed out by Sibi.
- Fixed bug that incorrectly reset rate to 0 all the time
- Added units documentation
- Dropped interconnect-opp-table property and related changes
v4->v5:
- Replaced KBps with kBps
- Minor documentation fix
Cheers,
Saravana
Saravana Kannan (3):
dt-bindings: opp: Introduce opp-peak-kBps and opp-avg-kBps bindings
OPP: Add support for bandwidth OPP tables
OPP: Add helper function for bandwidth OPP tables
Documentation/devicetree/bindings/opp/opp.txt | 15 ++++--
.../devicetree/bindings/property-units.txt | 4 ++
drivers/opp/core.c | 51 +++++++++++++++++++
drivers/opp/of.c | 41 +++++++++++----
drivers/opp/opp.h | 4 +-
include/linux/pm_opp.h | 19 +++++++
6 files changed, 121 insertions(+), 13 deletions(-)
--
2.23.0.rc1.153.gdeed80330f-goog
Interconnects often quantify their performance points in terms of
bandwidth. So, add opp-peak-kBps (required) and opp-avg-kBps (optional) to
allow specifying Bandwidth OPP tables in DT.
opp-peak-kBps is a required property that replaces opp-hz for Bandwidth OPP
tables.
opp-avg-kBps is an optional property that can be used in Bandwidth OPP
tables.
Signed-off-by: Saravana Kannan <[email protected]>
---
Documentation/devicetree/bindings/opp/opp.txt | 15 ++++++++++++---
.../devicetree/bindings/property-units.txt | 4 ++++
2 files changed, 16 insertions(+), 3 deletions(-)
diff --git a/Documentation/devicetree/bindings/opp/opp.txt b/Documentation/devicetree/bindings/opp/opp.txt
index 68592271461f..dbad8eb6c746 100644
--- a/Documentation/devicetree/bindings/opp/opp.txt
+++ b/Documentation/devicetree/bindings/opp/opp.txt
@@ -83,9 +83,14 @@ properties.
Required properties:
- opp-hz: Frequency in Hz, expressed as a 64-bit big-endian integer. This is a
- required property for all device nodes but devices like power domains. The
- power domain nodes must have another (implementation dependent) property which
- uniquely identifies the OPP nodes.
+ required property for all device nodes except for devices like power domains
+ or bandwidth opp tables. The power domain nodes must have another
+ (implementation dependent) property which uniquely identifies the OPP nodes.
+ The interconnect opps are required to have the opp-peak-kBps property.
+
+- opp-peak-kBps: Peak bandwidth in kilobytes per second, expressed as a 32-bit
+ big-endian integer. This is a required property for all devices that don't
+ have opp-hz. For example, bandwidth OPP tables for interconnect paths.
Optional properties:
- opp-microvolt: voltage in micro Volts.
@@ -132,6 +137,10 @@ Optional properties:
- opp-level: A value representing the performance level of the device,
expressed as a 32-bit integer.
+- opp-avg-kBps: Average bandwidth in kilobytes per second, expressed as a
+ 32-bit big-endian integer. This property is only meaningful in OPP tables
+ where opp-peak-kBps is present.
+
- clock-latency-ns: Specifies the maximum possible transition latency (in
nanoseconds) for switching to this OPP from any other OPP.
diff --git a/Documentation/devicetree/bindings/property-units.txt b/Documentation/devicetree/bindings/property-units.txt
index e9b8360b3288..c80a110c1e26 100644
--- a/Documentation/devicetree/bindings/property-units.txt
+++ b/Documentation/devicetree/bindings/property-units.txt
@@ -41,3 +41,7 @@ Temperature
Pressure
----------------------------------------
-kpascal : kilopascal
+
+Throughput
+----------------------------------------
+-kBps : kilobytes per second
--
2.23.0.rc1.153.gdeed80330f-goog
The frequency OPP tables have helper functions to search for entries in the
table based on frequency and get the frequency values for a given (or
suspend) OPP entry.
Add similar helper functions for bandwidth OPP tables to search for entries
in the table based on peak bandwidth and to get the peak and average
bandwidth for a given (or suspend) OPP entry.
Signed-off-by: Saravana Kannan <[email protected]>
---
drivers/opp/core.c | 51 ++++++++++++++++++++++++++++++++++++++++++
include/linux/pm_opp.h | 19 ++++++++++++++++
2 files changed, 70 insertions(+)
diff --git a/drivers/opp/core.c b/drivers/opp/core.c
index 3b7ffd0234e9..22dcf22f908f 100644
--- a/drivers/opp/core.c
+++ b/drivers/opp/core.c
@@ -127,6 +127,29 @@ unsigned long dev_pm_opp_get_freq(struct dev_pm_opp *opp)
}
EXPORT_SYMBOL_GPL(dev_pm_opp_get_freq);
+/**
+ * dev_pm_opp_get_bw() - Gets the bandwidth corresponding to an available opp
+ * @opp: opp for which frequency has to be returned for
+ * @avg_bw: Pointer where the corresponding average bandwidth is stored.
+ * Can be NULL.
+ *
+ * Return: Peak bandwidth in kBps corresponding to the opp, else
+ * return 0
+ */
+unsigned long dev_pm_opp_get_bw(struct dev_pm_opp *opp, unsigned long *avg_bw)
+{
+ if (IS_ERR_OR_NULL(opp) || !opp->available) {
+ pr_err("%s: Invalid parameters\n", __func__);
+ return 0;
+ }
+
+ if (avg_bw)
+ *avg_bw = opp->avg_bw;
+
+ return opp->rate;
+}
+EXPORT_SYMBOL_GPL(dev_pm_opp_get_bw);
+
/**
* dev_pm_opp_get_level() - Gets the level corresponding to an available opp
* @opp: opp for which level value has to be returned for
@@ -299,6 +322,34 @@ unsigned long dev_pm_opp_get_suspend_opp_freq(struct device *dev)
}
EXPORT_SYMBOL_GPL(dev_pm_opp_get_suspend_opp_freq);
+/**
+ * dev_pm_opp_get_suspend_opp_bw() - Get peak bandwidth of suspend opp in kBps
+ * @dev: device for which we do this operation
+ * @avg_bw: Pointer where the corresponding average bandwidth is stored.
+ * Can be NULL.
+ *
+ * Return: This function returns the peak bandwidth of the OPP marked as
+ * suspend_opp if one is available, else returns 0;
+ */
+unsigned long dev_pm_opp_get_suspend_opp_bw(struct device *dev,
+ unsigned long *avg_bw)
+{
+ struct opp_table *opp_table;
+ unsigned long peak_bw = 0;
+
+ opp_table = _find_opp_table(dev);
+ if (IS_ERR(opp_table))
+ return 0;
+
+ if (opp_table->suspend_opp && opp_table->suspend_opp->available)
+ peak_bw = dev_pm_opp_get_bw(opp_table->suspend_opp, avg_bw);
+
+ dev_pm_opp_put_opp_table(opp_table);
+
+ return peak_bw;
+}
+EXPORT_SYMBOL_GPL(dev_pm_opp_get_suspend_opp_bw);
+
int _get_opp_count(struct opp_table *opp_table)
{
struct dev_pm_opp *opp;
diff --git a/include/linux/pm_opp.h b/include/linux/pm_opp.h
index b8197ab014f2..f4e900f36414 100644
--- a/include/linux/pm_opp.h
+++ b/include/linux/pm_opp.h
@@ -82,6 +82,7 @@ void dev_pm_opp_put_opp_table(struct opp_table *opp_table);
unsigned long dev_pm_opp_get_voltage(struct dev_pm_opp *opp);
unsigned long dev_pm_opp_get_freq(struct dev_pm_opp *opp);
+unsigned long dev_pm_opp_get_bw(struct dev_pm_opp *opp, unsigned long *avg_bw);
unsigned int dev_pm_opp_get_level(struct dev_pm_opp *opp);
@@ -92,6 +93,8 @@ unsigned long dev_pm_opp_get_max_clock_latency(struct device *dev);
unsigned long dev_pm_opp_get_max_volt_latency(struct device *dev);
unsigned long dev_pm_opp_get_max_transition_latency(struct device *dev);
unsigned long dev_pm_opp_get_suspend_opp_freq(struct device *dev);
+unsigned long dev_pm_opp_get_suspend_opp_bw(struct device *dev,
+ unsigned long *avg_bw);
struct dev_pm_opp *dev_pm_opp_find_freq_exact(struct device *dev,
unsigned long freq,
@@ -160,6 +163,11 @@ static inline unsigned long dev_pm_opp_get_freq(struct dev_pm_opp *opp)
{
return 0;
}
+static inline unsigned long dev_pm_opp_get_bw(struct dev_pm_opp *opp,
+ unsigned long *avg_bw)
+{
+ return 0;
+}
static inline unsigned int dev_pm_opp_get_level(struct dev_pm_opp *opp)
{
@@ -196,6 +204,12 @@ static inline unsigned long dev_pm_opp_get_suspend_opp_freq(struct device *dev)
return 0;
}
+static inline unsigned long dev_pm_opp_get_suspend_opp_bw(struct device *dev,
+ unsigned long *avg_bw)
+{
+ return 0;
+}
+
static inline struct dev_pm_opp *dev_pm_opp_find_freq_exact(struct device *dev,
unsigned long freq, bool available)
{
@@ -337,6 +351,11 @@ static inline void dev_pm_opp_cpumask_remove_table(const struct cpumask *cpumask
#endif /* CONFIG_PM_OPP */
+#define dev_pm_opp_find_peak_bw_exact dev_pm_opp_find_freq_exact
+#define dev_pm_opp_find_peak_bw_floor dev_pm_opp_find_freq_floor
+#define dev_pm_opp_find_peak_bw_ceil_by_volt dev_pm_opp_find_freq_ceil_by_volt
+#define dev_pm_opp_find_peak_bw_ceil dev_pm_opp_find_freq_ceil
+
#if defined(CONFIG_PM_OPP) && defined(CONFIG_OF)
int dev_pm_opp_of_add_table(struct device *dev);
int dev_pm_opp_of_add_table_indexed(struct device *dev, int index);
--
2.23.0.rc1.153.gdeed80330f-goog
Not all devices quantify their performance points in terms of frequency.
Devices like interconnects quantify their performance points in terms of
bandwidth. We need a way to represent these bandwidth levels in OPP. So,
add support for parsing bandwidth OPPs from DT.
Signed-off-by: Saravana Kannan <[email protected]>
---
drivers/opp/of.c | 41 ++++++++++++++++++++++++++++++++---------
drivers/opp/opp.h | 4 +++-
2 files changed, 35 insertions(+), 10 deletions(-)
diff --git a/drivers/opp/of.c b/drivers/opp/of.c
index 1813f5ad5fa2..e1750033fef9 100644
--- a/drivers/opp/of.c
+++ b/drivers/opp/of.c
@@ -523,6 +523,35 @@ void dev_pm_opp_of_remove_table(struct device *dev)
}
EXPORT_SYMBOL_GPL(dev_pm_opp_of_remove_table);
+static int _read_opp_key(struct dev_pm_opp *new_opp, struct device_node *np)
+{
+ int ret;
+ u64 rate;
+ u32 bw;
+
+ ret = of_property_read_u64(np, "opp-hz", &rate);
+ if (!ret) {
+ /*
+ * Rate is defined as an unsigned long in clk API, and so
+ * casting explicitly to its type. Must be fixed once rate is 64
+ * bit guaranteed in clk API.
+ */
+ new_opp->rate = (unsigned long)rate;
+ return 0;
+ }
+
+ ret = of_property_read_u32(np, "opp-peak-kBps", &bw);
+ if (ret)
+ return ret;
+ new_opp->rate = (unsigned long) bw;
+
+ ret = of_property_read_u32(np, "opp-avg-kBps", &bw);
+ if (!ret)
+ new_opp->avg_bw = (unsigned long) bw;
+
+ return 0;
+}
+
/**
* _opp_add_static_v2() - Allocate static OPPs (As per 'v2' DT bindings)
* @opp_table: OPP table
@@ -560,22 +589,16 @@ static struct dev_pm_opp *_opp_add_static_v2(struct opp_table *opp_table,
if (!new_opp)
return ERR_PTR(-ENOMEM);
- ret = of_property_read_u64(np, "opp-hz", &rate);
+ ret = _read_opp_key(new_opp, np);
if (ret < 0) {
/* "opp-hz" is optional for devices like power domains. */
if (!opp_table->is_genpd) {
- dev_err(dev, "%s: opp-hz not found\n", __func__);
+ dev_err(dev, "%s: opp-hz or opp-peak-kBps not found\n",
+ __func__);
goto free_opp;
}
rate_not_available = true;
- } else {
- /*
- * Rate is defined as an unsigned long in clk API, and so
- * casting explicitly to its type. Must be fixed once rate is 64
- * bit guaranteed in clk API.
- */
- new_opp->rate = (unsigned long)rate;
}
of_property_read_u32(np, "opp-level", &new_opp->level);
diff --git a/drivers/opp/opp.h b/drivers/opp/opp.h
index 01a500e2c40a..6bb238af9cac 100644
--- a/drivers/opp/opp.h
+++ b/drivers/opp/opp.h
@@ -56,7 +56,8 @@ extern struct list_head opp_tables;
* @turbo: true if turbo (boost) OPP
* @suspend: true if suspend OPP
* @pstate: Device's power domain's performance state.
- * @rate: Frequency in hertz
+ * @rate: Frequency in hertz OR Peak bandwidth in kilobytes per second
+ * @avg_bw: Average bandwidth in kilobytes per second
* @level: Performance level
* @supplies: Power supplies voltage/current values
* @clock_latency_ns: Latency (in nanoseconds) of switching to this OPP's
@@ -78,6 +79,7 @@ struct dev_pm_opp {
bool suspend;
unsigned int pstate;
unsigned long rate;
+ unsigned long avg_bw;
unsigned int level;
struct dev_pm_opp_supply *supplies;
--
2.23.0.rc1.153.gdeed80330f-goog
Hi,
On 8/8/19 01:31, Saravana Kannan wrote:
> Interconnects and interconnect paths quantify their performance levels in
> terms of bandwidth and not in terms of frequency. So similar to how we have
> frequency based OPP tables in DT and in the OPP framework, we need
> bandwidth OPP table support in DT and in the OPP framework.
>
> So with the DT bindings added in this patch series, the DT for a GPU
> that does bandwidth voting from GPU to Cache and GPU to DDR would look
> something like this:
>
> gpu_cache_opp_table: gpu_cache_opp_table {
> compatible = "operating-points-v2";
>
> gpu_cache_3000: opp-3000 {
> opp-peak-KBps = <3000000>;
> opp-avg-KBps = <1000000>;
> };
> gpu_cache_6000: opp-6000 {
> opp-peak-KBps = <6000000>;
> opp-avg-KBps = <2000000>;
> };
> gpu_cache_9000: opp-9000 {
> opp-peak-KBps = <9000000>;
> opp-avg-KBps = <9000000>;
> };
> };
>
> gpu_ddr_opp_table: gpu_ddr_opp_table {
> compatible = "operating-points-v2";
>
> gpu_ddr_1525: opp-1525 {
> opp-peak-KBps = <1525000>;
> opp-avg-KBps = <452000>;
> };
> gpu_ddr_3051: opp-3051 {
> opp-peak-KBps = <3051000>;
> opp-avg-KBps = <915000>;
> };
> gpu_ddr_7500: opp-7500 {
> opp-peak-KBps = <7500000>;
> opp-avg-KBps = <3000000>;
> };
> };
>
> gpu_opp_table: gpu_opp_table {
> compatible = "operating-points-v2";
> opp-shared;
>
> opp-200000000 {
> opp-hz = /bits/ 64 <200000000>;
> };
> opp-400000000 {
> opp-hz = /bits/ 64 <400000000>;
> };
> };
>
> gpu@7864000 {
> ...
> operating-points-v2 = <&gpu_opp_table>, <&gpu_cache_opp_table>, <&gpu_ddr_opp_table>;
> ...
> };
>
> v1 -> v3:
> - Lots of patch additions that were later dropped
> v3 -> v4:
> - Fixed typo bugs pointed out by Sibi.
> - Fixed bug that incorrectly reset rate to 0 all the time
> - Added units documentation
> - Dropped interconnect-opp-table property and related changes
> v4->v5:
> - Replaced KBps with kBps
> - Minor documentation fix
>
> Cheers,
> Saravana
>
> Saravana Kannan (3):
> dt-bindings: opp: Introduce opp-peak-kBps and opp-avg-kBps bindings
> OPP: Add support for bandwidth OPP tables
> OPP: Add helper function for bandwidth OPP tables
>
> Documentation/devicetree/bindings/opp/opp.txt | 15 ++++--
> .../devicetree/bindings/property-units.txt | 4 ++
> drivers/opp/core.c | 51 +++++++++++++++++++
> drivers/opp/of.c | 41 +++++++++++----
> drivers/opp/opp.h | 4 +-
> include/linux/pm_opp.h | 19 +++++++
> 6 files changed, 121 insertions(+), 13 deletions(-)
>
For the series:
Acked-by: Georgi Djakov <[email protected]>
Thanks,
Georgi
On Thu, Aug 15, 2019 at 9:19 AM Georgi Djakov <[email protected]> wrote:
>
> Hi,
>
> On 8/8/19 01:31, Saravana Kannan wrote:
> > Interconnects and interconnect paths quantify their performance levels in
> > terms of bandwidth and not in terms of frequency. So similar to how we have
> > frequency based OPP tables in DT and in the OPP framework, we need
> > bandwidth OPP table support in DT and in the OPP framework.
> >
> > So with the DT bindings added in this patch series, the DT for a GPU
> > that does bandwidth voting from GPU to Cache and GPU to DDR would look
> > something like this:
> >
> > gpu_cache_opp_table: gpu_cache_opp_table {
> > compatible = "operating-points-v2";
> >
> > gpu_cache_3000: opp-3000 {
> > opp-peak-KBps = <3000000>;
> > opp-avg-KBps = <1000000>;
> > };
> > gpu_cache_6000: opp-6000 {
> > opp-peak-KBps = <6000000>;
> > opp-avg-KBps = <2000000>;
> > };
> > gpu_cache_9000: opp-9000 {
> > opp-peak-KBps = <9000000>;
> > opp-avg-KBps = <9000000>;
> > };
> > };
> >
> > gpu_ddr_opp_table: gpu_ddr_opp_table {
> > compatible = "operating-points-v2";
> >
> > gpu_ddr_1525: opp-1525 {
> > opp-peak-KBps = <1525000>;
> > opp-avg-KBps = <452000>;
> > };
> > gpu_ddr_3051: opp-3051 {
> > opp-peak-KBps = <3051000>;
> > opp-avg-KBps = <915000>;
> > };
> > gpu_ddr_7500: opp-7500 {
> > opp-peak-KBps = <7500000>;
> > opp-avg-KBps = <3000000>;
> > };
> > };
> >
> > gpu_opp_table: gpu_opp_table {
> > compatible = "operating-points-v2";
> > opp-shared;
> >
> > opp-200000000 {
> > opp-hz = /bits/ 64 <200000000>;
> > };
> > opp-400000000 {
> > opp-hz = /bits/ 64 <400000000>;
> > };
> > };
> >
> > gpu@7864000 {
> > ...
> > operating-points-v2 = <&gpu_opp_table>, <&gpu_cache_opp_table>, <&gpu_ddr_opp_table>;
> > ...
> > };
> >
> > v1 -> v3:
> > - Lots of patch additions that were later dropped
> > v3 -> v4:
> > - Fixed typo bugs pointed out by Sibi.
> > - Fixed bug that incorrectly reset rate to 0 all the time
> > - Added units documentation
> > - Dropped interconnect-opp-table property and related changes
> > v4->v5:
> > - Replaced KBps with kBps
> > - Minor documentation fix
> >
> > Cheers,
> > Saravana
> >
> > Saravana Kannan (3):
> > dt-bindings: opp: Introduce opp-peak-kBps and opp-avg-kBps bindings
> > OPP: Add support for bandwidth OPP tables
> > OPP: Add helper function for bandwidth OPP tables
> >
> > Documentation/devicetree/bindings/opp/opp.txt | 15 ++++--
> > .../devicetree/bindings/property-units.txt | 4 ++
> > drivers/opp/core.c | 51 +++++++++++++++++++
> > drivers/opp/of.c | 41 +++++++++++----
> > drivers/opp/opp.h | 4 +-
> > include/linux/pm_opp.h | 19 +++++++
> > 6 files changed, 121 insertions(+), 13 deletions(-)
> >
>
> For the series:
> Acked-by: Georgi Djakov <[email protected]>
Thanks Georgi.
Rob and Viresh, We've settled on one format. Can you pull this series in please?
Do you need me to resent the series with the Ack? Or can you put that
in if you pull in this series?
Thanks,
Saravana
Quoting Saravana Kannan (2019-08-07 15:31:10)
> diff --git a/drivers/opp/of.c b/drivers/opp/of.c
> index 1813f5ad5fa2..e1750033fef9 100644
> --- a/drivers/opp/of.c
> +++ b/drivers/opp/of.c
> @@ -523,6 +523,35 @@ void dev_pm_opp_of_remove_table(struct device *dev)
> }
> EXPORT_SYMBOL_GPL(dev_pm_opp_of_remove_table);
>
> +static int _read_opp_key(struct dev_pm_opp *new_opp, struct device_node *np)
> +{
> + int ret;
> + u64 rate;
> + u32 bw;
> +
> + ret = of_property_read_u64(np, "opp-hz", &rate);
> + if (!ret) {
> + /*
> + * Rate is defined as an unsigned long in clk API, and so
> + * casting explicitly to its type. Must be fixed once rate is 64
> + * bit guaranteed in clk API.
> + */
> + new_opp->rate = (unsigned long)rate;
> + return 0;
> + }
> +
> + ret = of_property_read_u32(np, "opp-peak-kBps", &bw);
> + if (ret)
> + return ret;
> + new_opp->rate = (unsigned long) bw;
> +
> + ret = of_property_read_u32(np, "opp-avg-kBps", &bw);
> + if (!ret)
I would write this as
if (!of_property_read_u32(np, "opp-avg-kBps", &bw))
new_opp->avg_bw = (unsigned long) bw;
because you don't care about the return value.
> + new_opp->avg_bw = (unsigned long) bw;
> +
> + return 0;
> +}
> +
> /**
> * _opp_add_static_v2() - Allocate static OPPs (As per 'v2' DT bindings)
> * @opp_table: OPP table
> diff --git a/drivers/opp/opp.h b/drivers/opp/opp.h
> index 01a500e2c40a..6bb238af9cac 100644
> --- a/drivers/opp/opp.h
> +++ b/drivers/opp/opp.h
> @@ -56,7 +56,8 @@ extern struct list_head opp_tables;
> * @turbo: true if turbo (boost) OPP
> * @suspend: true if suspend OPP
> * @pstate: Device's power domain's performance state.
> - * @rate: Frequency in hertz
> + * @rate: Frequency in hertz OR Peak bandwidth in kilobytes per second
Why is Peak capitalized?
> + * @avg_bw: Average bandwidth in kilobytes per second
> * @level: Performance level
> * @supplies: Power supplies voltage/current values
> * @clock_latency_ns: Latency (in nanoseconds) of switching to this OPP's
> @@ -78,6 +79,7 @@ struct dev_pm_opp {
> bool suspend;
> unsigned int pstate;
> unsigned long rate;
If you're trying to save space why not make an anonymous union here of
'rate' and 'bandwidth'? Then the code doesn't read all weird.
> + unsigned long avg_bw;
> unsigned int level;
>
> struct dev_pm_opp_supply *supplies;
Quoting Saravana Kannan (2019-08-07 15:31:11)
> diff --git a/drivers/opp/core.c b/drivers/opp/core.c
> index 3b7ffd0234e9..22dcf22f908f 100644
> --- a/drivers/opp/core.c
> +++ b/drivers/opp/core.c
> @@ -127,6 +127,29 @@ unsigned long dev_pm_opp_get_freq(struct dev_pm_opp *opp)
> }
> EXPORT_SYMBOL_GPL(dev_pm_opp_get_freq);
>
> +/**
> + * dev_pm_opp_get_bw() - Gets the bandwidth corresponding to an available opp
> + * @opp: opp for which frequency has to be returned for
s/frequency/bandwidth/ ?
> + * @avg_bw: Pointer where the corresponding average bandwidth is stored.
> + * Can be NULL.
> + *
> + * Return: Peak bandwidth in kBps corresponding to the opp, else
> + * return 0
> + */
> +unsigned long dev_pm_opp_get_bw(struct dev_pm_opp *opp, unsigned long *avg_bw)
> +{
> + if (IS_ERR_OR_NULL(opp) || !opp->available) {
> + pr_err("%s: Invalid parameters\n", __func__);
> + return 0;
> + }
> +
> + if (avg_bw)
> + *avg_bw = opp->avg_bw;
> +
> + return opp->rate;
It deserves a comment if it stays named 'rate'. At a glance it looks
like a bug.
> +}
> +EXPORT_SYMBOL_GPL(dev_pm_opp_get_bw);
> +
> /**
> * dev_pm_opp_get_level() - Gets the level corresponding to an available opp
> * @opp: opp for which level value has to be returned for
> @@ -299,6 +322,34 @@ unsigned long dev_pm_opp_get_suspend_opp_freq(struct device *dev)
> }
> EXPORT_SYMBOL_GPL(dev_pm_opp_get_suspend_opp_freq);
>
> +/**
> + * dev_pm_opp_get_suspend_opp_bw() - Get peak bandwidth of suspend opp in kBps
> + * @dev: device for which we do this operation
> + * @avg_bw: Pointer where the corresponding average bandwidth is stored.
> + * Can be NULL.
> + *
> + * Return: This function returns the peak bandwidth of the OPP marked as
> + * suspend_opp if one is available, else returns 0;
Why a semicolon instead a full stop?
On 07-08-19, 15:31, Saravana Kannan wrote:
> Not all devices quantify their performance points in terms of frequency.
> Devices like interconnects quantify their performance points in terms of
> bandwidth. We need a way to represent these bandwidth levels in OPP. So,
> add support for parsing bandwidth OPPs from DT.
>
> Signed-off-by: Saravana Kannan <[email protected]>
> ---
> drivers/opp/of.c | 41 ++++++++++++++++++++++++++++++++---------
> drivers/opp/opp.h | 4 +++-
> 2 files changed, 35 insertions(+), 10 deletions(-)
>
> diff --git a/drivers/opp/of.c b/drivers/opp/of.c
> index 1813f5ad5fa2..e1750033fef9 100644
> --- a/drivers/opp/of.c
> +++ b/drivers/opp/of.c
> @@ -523,6 +523,35 @@ void dev_pm_opp_of_remove_table(struct device *dev)
> }
> EXPORT_SYMBOL_GPL(dev_pm_opp_of_remove_table);
>
> +static int _read_opp_key(struct dev_pm_opp *new_opp, struct device_node *np)
> +{
> + int ret;
> + u64 rate;
> + u32 bw;
> +
> + ret = of_property_read_u64(np, "opp-hz", &rate);
> + if (!ret) {
> + /*
> + * Rate is defined as an unsigned long in clk API, and so
> + * casting explicitly to its type. Must be fixed once rate is 64
> + * bit guaranteed in clk API.
> + */
> + new_opp->rate = (unsigned long)rate;
> + return 0;
> + }
> +
Please read opp-level also here and do error handling.
> + ret = of_property_read_u32(np, "opp-peak-kBps", &bw);
> + if (ret)
> + return ret;
> + new_opp->rate = (unsigned long) bw;
> +
> + ret = of_property_read_u32(np, "opp-avg-kBps", &bw);
> + if (!ret)
> + new_opp->avg_bw = (unsigned long) bw;
If none of opp-hz/level/peak-kBps are available, print error message here
itself..
> +
> + return 0;
You are returning 0 on failure as well here.
> +}
> +
> /**
> * _opp_add_static_v2() - Allocate static OPPs (As per 'v2' DT bindings)
> * @opp_table: OPP table
> @@ -560,22 +589,16 @@ static struct dev_pm_opp *_opp_add_static_v2(struct opp_table *opp_table,
> if (!new_opp)
> return ERR_PTR(-ENOMEM);
>
> - ret = of_property_read_u64(np, "opp-hz", &rate);
> + ret = _read_opp_key(new_opp, np);
> if (ret < 0) {
> /* "opp-hz" is optional for devices like power domains. */
> if (!opp_table->is_genpd) {
> - dev_err(dev, "%s: opp-hz not found\n", __func__);
> + dev_err(dev, "%s: opp-hz or opp-peak-kBps not found\n",
> + __func__);
> goto free_opp;
> }
>
> rate_not_available = true;
Move all above as well to read_opp_key().
> - } else {
> - /*
> - * Rate is defined as an unsigned long in clk API, and so
> - * casting explicitly to its type. Must be fixed once rate is 64
> - * bit guaranteed in clk API.
> - */
> - new_opp->rate = (unsigned long)rate;
> }
>
> of_property_read_u32(np, "opp-level", &new_opp->level);
> diff --git a/drivers/opp/opp.h b/drivers/opp/opp.h
> index 01a500e2c40a..6bb238af9cac 100644
> --- a/drivers/opp/opp.h
> +++ b/drivers/opp/opp.h
> @@ -56,7 +56,8 @@ extern struct list_head opp_tables;
> * @turbo: true if turbo (boost) OPP
> * @suspend: true if suspend OPP
> * @pstate: Device's power domain's performance state.
> - * @rate: Frequency in hertz
> + * @rate: Frequency in hertz OR Peak bandwidth in kilobytes per second
> + * @avg_bw: Average bandwidth in kilobytes per second
Please add separate entry for peak_bw here.
I know you reused rate because you don't want to reimplement the helpers we
have. Maybe we can just update them to return peak_bw when opp-hz isn't present.
> * @level: Performance level
> * @supplies: Power supplies voltage/current values
> * @clock_latency_ns: Latency (in nanoseconds) of switching to this OPP's
> @@ -78,6 +79,7 @@ struct dev_pm_opp {
> bool suspend;
> unsigned int pstate;
> unsigned long rate;
> + unsigned long avg_bw;
> unsigned int level;
>
> struct dev_pm_opp_supply *supplies;
> --
> 2.23.0.rc1.153.gdeed80330f-goog
--
viresh
On Mon, Aug 19, 2019 at 11:13 PM Viresh Kumar <[email protected]> wrote:
>
> On 07-08-19, 15:31, Saravana Kannan wrote:
> > Not all devices quantify their performance points in terms of frequency.
> > Devices like interconnects quantify their performance points in terms of
> > bandwidth. We need a way to represent these bandwidth levels in OPP. So,
> > add support for parsing bandwidth OPPs from DT.
> >
> > Signed-off-by: Saravana Kannan <[email protected]>
> > ---
> > drivers/opp/of.c | 41 ++++++++++++++++++++++++++++++++---------
> > drivers/opp/opp.h | 4 +++-
> > 2 files changed, 35 insertions(+), 10 deletions(-)
> >
> > diff --git a/drivers/opp/of.c b/drivers/opp/of.c
> > index 1813f5ad5fa2..e1750033fef9 100644
> > --- a/drivers/opp/of.c
> > +++ b/drivers/opp/of.c
> > @@ -523,6 +523,35 @@ void dev_pm_opp_of_remove_table(struct device *dev)
> > }
> > EXPORT_SYMBOL_GPL(dev_pm_opp_of_remove_table);
> >
> > +static int _read_opp_key(struct dev_pm_opp *new_opp, struct device_node *np)
> > +{
> > + int ret;
> > + u64 rate;
> > + u32 bw;
> > +
> > + ret = of_property_read_u64(np, "opp-hz", &rate);
> > + if (!ret) {
> > + /*
> > + * Rate is defined as an unsigned long in clk API, and so
> > + * casting explicitly to its type. Must be fixed once rate is 64
> > + * bit guaranteed in clk API.
> > + */
> > + new_opp->rate = (unsigned long)rate;
> > + return 0;
> > + }
> > +
>
> Please read opp-level also here and do error handling.
Can you please explain what's the reasoning? opp-level doesn't seem to
be a "key" based on looking at the code.
>
> > + ret = of_property_read_u32(np, "opp-peak-kBps", &bw);
> > + if (ret)
> > + return ret;
> > + new_opp->rate = (unsigned long) bw;
> > +
> > + ret = of_property_read_u32(np, "opp-avg-kBps", &bw);
> > + if (!ret)
> > + new_opp->avg_bw = (unsigned long) bw;
>
> If none of opp-hz/level/peak-kBps are available, print error message here
> itself..
But you don't print any error for opp-level today. Seems like it's optional?
>
> > +
> > + return 0;
>
> You are returning 0 on failure as well here.
Thanks.
> > +}
> > +
> > /**
> > * _opp_add_static_v2() - Allocate static OPPs (As per 'v2' DT bindings)
> > * @opp_table: OPP table
> > @@ -560,22 +589,16 @@ static struct dev_pm_opp *_opp_add_static_v2(struct opp_table *opp_table,
> > if (!new_opp)
> > return ERR_PTR(-ENOMEM);
> >
> > - ret = of_property_read_u64(np, "opp-hz", &rate);
> > + ret = _read_opp_key(new_opp, np);
> > if (ret < 0) {
> > /* "opp-hz" is optional for devices like power domains. */
> > if (!opp_table->is_genpd) {
> > - dev_err(dev, "%s: opp-hz not found\n", __func__);
> > + dev_err(dev, "%s: opp-hz or opp-peak-kBps not found\n",
> > + __func__);
> > goto free_opp;
> > }
> >
> > rate_not_available = true;
>
> Move all above as well to read_opp_key().
Ok. I didn't want to print an error at the API level and instead print
at the caller level. But if that's what you want, that's fine by me.
>
> > - } else {
> > - /*
> > - * Rate is defined as an unsigned long in clk API, and so
> > - * casting explicitly to its type. Must be fixed once rate is 64
> > - * bit guaranteed in clk API.
> > - */
> > - new_opp->rate = (unsigned long)rate;
> > }
> >
> > of_property_read_u32(np, "opp-level", &new_opp->level);
> > diff --git a/drivers/opp/opp.h b/drivers/opp/opp.h
> > index 01a500e2c40a..6bb238af9cac 100644
> > --- a/drivers/opp/opp.h
> > +++ b/drivers/opp/opp.h
> > @@ -56,7 +56,8 @@ extern struct list_head opp_tables;
> > * @turbo: true if turbo (boost) OPP
> > * @suspend: true if suspend OPP
> > * @pstate: Device's power domain's performance state.
> > - * @rate: Frequency in hertz
> > + * @rate: Frequency in hertz OR Peak bandwidth in kilobytes per second
> > + * @avg_bw: Average bandwidth in kilobytes per second
>
> Please add separate entry for peak_bw here.
>
> I know you reused rate because you don't want to reimplement the helpers we
> have. Maybe we can just update them to return peak_bw when opp-hz isn't present.
How about I just rename this to "key"? That makes a lot more sense
than trying to save 3 different keys and going through them one at a
time.
> > * @level: Performance level
> > * @supplies: Power supplies voltage/current values
> > * @clock_latency_ns: Latency (in nanoseconds) of switching to this OPP's
> > @@ -78,6 +79,7 @@ struct dev_pm_opp {
> > bool suspend;
> > unsigned int pstate;
> > unsigned long rate;
> > + unsigned long avg_bw;
> > unsigned int level;
> >
> > struct dev_pm_opp_supply *supplies;
> > --
> > 2.23.0.rc1.153.gdeed80330f-goog
-Saravana
On Fri, Aug 16, 2019 at 11:21 AM Stephen Boyd <[email protected]> wrote:
>
> Quoting Saravana Kannan (2019-08-07 15:31:10)
> > diff --git a/drivers/opp/of.c b/drivers/opp/of.c
> > index 1813f5ad5fa2..e1750033fef9 100644
> > --- a/drivers/opp/of.c
> > +++ b/drivers/opp/of.c
> > @@ -523,6 +523,35 @@ void dev_pm_opp_of_remove_table(struct device *dev)
> > }
> > EXPORT_SYMBOL_GPL(dev_pm_opp_of_remove_table);
> >
> > +static int _read_opp_key(struct dev_pm_opp *new_opp, struct device_node *np)
> > +{
> > + int ret;
> > + u64 rate;
> > + u32 bw;
> > +
> > + ret = of_property_read_u64(np, "opp-hz", &rate);
> > + if (!ret) {
> > + /*
> > + * Rate is defined as an unsigned long in clk API, and so
> > + * casting explicitly to its type. Must be fixed once rate is 64
> > + * bit guaranteed in clk API.
> > + */
> > + new_opp->rate = (unsigned long)rate;
> > + return 0;
> > + }
> > +
> > + ret = of_property_read_u32(np, "opp-peak-kBps", &bw);
> > + if (ret)
> > + return ret;
> > + new_opp->rate = (unsigned long) bw;
> > +
> > + ret = of_property_read_u32(np, "opp-avg-kBps", &bw);
> > + if (!ret)
>
> I would write this as
>
> if (!of_property_read_u32(np, "opp-avg-kBps", &bw))
> new_opp->avg_bw = (unsigned long) bw;
>
> because you don't care about the return value.
Sure, will do.
>
> > + new_opp->avg_bw = (unsigned long) bw;
> > +
> > + return 0;
> > +}
> > +
> > /**
> > * _opp_add_static_v2() - Allocate static OPPs (As per 'v2' DT bindings)
> > * @opp_table: OPP table
> > diff --git a/drivers/opp/opp.h b/drivers/opp/opp.h
> > index 01a500e2c40a..6bb238af9cac 100644
> > --- a/drivers/opp/opp.h
> > +++ b/drivers/opp/opp.h
> > @@ -56,7 +56,8 @@ extern struct list_head opp_tables;
> > * @turbo: true if turbo (boost) OPP
> > * @suspend: true if suspend OPP
> > * @pstate: Device's power domain's performance state.
> > - * @rate: Frequency in hertz
> > + * @rate: Frequency in hertz OR Peak bandwidth in kilobytes per second
>
> Why is Peak capitalized?
Because it's another Key? :)
Just kidding. I'll fix it.
> > + * @avg_bw: Average bandwidth in kilobytes per second
> > * @level: Performance level
> > * @supplies: Power supplies voltage/current values
> > * @clock_latency_ns: Latency (in nanoseconds) of switching to this OPP's
> > @@ -78,6 +79,7 @@ struct dev_pm_opp {
> > bool suspend;
> > unsigned int pstate;
> > unsigned long rate;
>
> If you're trying to save space why not make an anonymous union here of
> 'rate' and 'bandwidth'? Then the code doesn't read all weird.
It's not about saving space. It's about having to rewrite all the
helper functions (see subsequent patch in this series) for different
"keys" with zero difference in the actual comparisons/logic. I'm
proposing I rename this to "key" in another email.
-Saravana
On Tue, Aug 20, 2019 at 3:27 PM Saravana Kannan <[email protected]> wrote:
>
> On Mon, Aug 19, 2019 at 11:13 PM Viresh Kumar <[email protected]> wrote:
> >
> > On 07-08-19, 15:31, Saravana Kannan wrote:
> > > + ret = of_property_read_u32(np, "opp-peak-kBps", &bw);
> > > + if (ret)
> > > + return ret;
> > > + new_opp->rate = (unsigned long) bw;
> > > +
> > > + ret = of_property_read_u32(np, "opp-avg-kBps", &bw);
> > > + if (!ret)
> > > + new_opp->avg_bw = (unsigned long) bw;
> >
> > If none of opp-hz/level/peak-kBps are available, print error message here
> > itself..
>
> But you don't print any error for opp-level today. Seems like it's optional?
>
> >
> > > +
> > > + return 0;
> >
> > You are returning 0 on failure as well here.
>
> Thanks.
Wait, no. This is not actually a failure. opp-avg-kBps is optional. So
returning 0 is the right thing to do. If the mandatory properties
aren't present an error is returned before you get to th end.
-Saravana
On 20-08-19, 15:27, Saravana Kannan wrote:
> On Mon, Aug 19, 2019 at 11:13 PM Viresh Kumar <[email protected]> wrote:
> >
> > On 07-08-19, 15:31, Saravana Kannan wrote:
> > > Not all devices quantify their performance points in terms of frequency.
> > > Devices like interconnects quantify their performance points in terms of
> > > bandwidth. We need a way to represent these bandwidth levels in OPP. So,
> > > add support for parsing bandwidth OPPs from DT.
> > >
> > > Signed-off-by: Saravana Kannan <[email protected]>
> > > ---
> > > drivers/opp/of.c | 41 ++++++++++++++++++++++++++++++++---------
> > > drivers/opp/opp.h | 4 +++-
> > > 2 files changed, 35 insertions(+), 10 deletions(-)
> > >
> > > diff --git a/drivers/opp/of.c b/drivers/opp/of.c
> > > index 1813f5ad5fa2..e1750033fef9 100644
> > > --- a/drivers/opp/of.c
> > > +++ b/drivers/opp/of.c
> > > @@ -523,6 +523,35 @@ void dev_pm_opp_of_remove_table(struct device *dev)
> > > }
> > > EXPORT_SYMBOL_GPL(dev_pm_opp_of_remove_table);
> > >
> > > +static int _read_opp_key(struct dev_pm_opp *new_opp, struct device_node *np)
> > > +{
> > > + int ret;
> > > + u64 rate;
> > > + u32 bw;
> > > +
> > > + ret = of_property_read_u64(np, "opp-hz", &rate);
> > > + if (!ret) {
> > > + /*
> > > + * Rate is defined as an unsigned long in clk API, and so
> > > + * casting explicitly to its type. Must be fixed once rate is 64
> > > + * bit guaranteed in clk API.
> > > + */
> > > + new_opp->rate = (unsigned long)rate;
> > > + return 0;
> > > + }
> > > +
> >
> > Please read opp-level also here and do error handling.
>
> Can you please explain what's the reasoning? opp-level doesn't seem to
> be a "key" based on looking at the code.
Because opp-level is the thing that distinguishes OPPs for power domains, those
nodes don't have opp-hz or bw.
> > > + ret = of_property_read_u32(np, "opp-peak-kBps", &bw);
> > > + if (ret)
> > > + return ret;
> > > + new_opp->rate = (unsigned long) bw;
> > > +
> > > + ret = of_property_read_u32(np, "opp-avg-kBps", &bw);
> > > + if (!ret)
> > > + new_opp->avg_bw = (unsigned long) bw;
> >
> > If none of opp-hz/level/peak-kBps are available, print error message here
> > itself..
>
> But you don't print any error for opp-level today. Seems like it's optional?
Yeah, probably it should have been there. It will be better to do it now as we
are creating a separate routine for that.
> >
> > > +
> > > + return 0;
> >
> > You are returning 0 on failure as well here.
>
> Thanks.
>
> > > +}
> > > +
> > > /**
> > > * _opp_add_static_v2() - Allocate static OPPs (As per 'v2' DT bindings)
> > > * @opp_table: OPP table
> > > @@ -560,22 +589,16 @@ static struct dev_pm_opp *_opp_add_static_v2(struct opp_table *opp_table,
> > > if (!new_opp)
> > > return ERR_PTR(-ENOMEM);
> > >
> > > - ret = of_property_read_u64(np, "opp-hz", &rate);
> > > + ret = _read_opp_key(new_opp, np);
> > > if (ret < 0) {
> > > /* "opp-hz" is optional for devices like power domains. */
> > > if (!opp_table->is_genpd) {
> > > - dev_err(dev, "%s: opp-hz not found\n", __func__);
> > > + dev_err(dev, "%s: opp-hz or opp-peak-kBps not found\n",
> > > + __func__);
> > > goto free_opp;
> > > }
> > >
> > > rate_not_available = true;
> >
> > Move all above as well to read_opp_key().
>
> Ok. I didn't want to print an error at the API level and instead print
> at the caller level. But if that's what you want, that's fine by me.
That would be fine, you can keep the print message here (but a generic one, like
key missing).
> > > - } else {
> > > - /*
> > > - * Rate is defined as an unsigned long in clk API, and so
> > > - * casting explicitly to its type. Must be fixed once rate is 64
> > > - * bit guaranteed in clk API.
> > > - */
> > > - new_opp->rate = (unsigned long)rate;
> > > }
> > >
> > > of_property_read_u32(np, "opp-level", &new_opp->level);
> > > diff --git a/drivers/opp/opp.h b/drivers/opp/opp.h
> > > index 01a500e2c40a..6bb238af9cac 100644
> > > --- a/drivers/opp/opp.h
> > > +++ b/drivers/opp/opp.h
> > > @@ -56,7 +56,8 @@ extern struct list_head opp_tables;
> > > * @turbo: true if turbo (boost) OPP
> > > * @suspend: true if suspend OPP
> > > * @pstate: Device's power domain's performance state.
> > > - * @rate: Frequency in hertz
> > > + * @rate: Frequency in hertz OR Peak bandwidth in kilobytes per second
> > > + * @avg_bw: Average bandwidth in kilobytes per second
> >
> > Please add separate entry for peak_bw here.
> >
> > I know you reused rate because you don't want to reimplement the helpers we
> > have. Maybe we can just update them to return peak_bw when opp-hz isn't present.
>
> How about I just rename this to "key"? That makes a lot more sense
> than trying to save 3 different keys and going through them one at a
> time.
I would still like to keep separate fields for now. We are still in continuous
development and don't know how things will be going forward. We may end up
having bw and hz in the OPP table as well. Over that I like to have separate
fields for readability.
Thanks.
--
viresh
On 20-08-19, 15:36, Saravana Kannan wrote:
> On Tue, Aug 20, 2019 at 3:27 PM Saravana Kannan <[email protected]> wrote:
> >
> > On Mon, Aug 19, 2019 at 11:13 PM Viresh Kumar <[email protected]> wrote:
> > >
> > > On 07-08-19, 15:31, Saravana Kannan wrote:
>
> > > > + ret = of_property_read_u32(np, "opp-peak-kBps", &bw);
> > > > + if (ret)
> > > > + return ret;
> > > > + new_opp->rate = (unsigned long) bw;
> > > > +
> > > > + ret = of_property_read_u32(np, "opp-avg-kBps", &bw);
> > > > + if (!ret)
> > > > + new_opp->avg_bw = (unsigned long) bw;
> > >
> > > If none of opp-hz/level/peak-kBps are available, print error message here
> > > itself..
> >
> > But you don't print any error for opp-level today. Seems like it's optional?
> >
> > >
> > > > +
> > > > + return 0;
> > >
> > > You are returning 0 on failure as well here.
> >
> > Thanks.
>
> Wait, no. This is not actually a failure. opp-avg-kBps is optional. So
> returning 0 is the right thing to do. If the mandatory properties
> aren't present an error is returned before you get to th end.
You are right :)
--
viresh
On 20-08-19, 15:36, Saravana Kannan wrote:
> On Tue, Aug 20, 2019 at 3:27 PM Saravana Kannan <[email protected]> wrote:
> >
> > On Mon, Aug 19, 2019 at 11:13 PM Viresh Kumar <[email protected]> wrote:
> > >
> > > On 07-08-19, 15:31, Saravana Kannan wrote:
>
> > > > + ret = of_property_read_u32(np, "opp-peak-kBps", &bw);
> > > > + if (ret)
> > > > + return ret;
> > > > + new_opp->rate = (unsigned long) bw;
> > > > +
> > > > + ret = of_property_read_u32(np, "opp-avg-kBps", &bw);
> > > > + if (!ret)
> > > > + new_opp->avg_bw = (unsigned long) bw;
Why is this casting required ? If you really want a 64 bit value for bw, then
make it 64 bit in bindings as well, like opp-hz. And then you can simply do:
of_property_read_u32(np, "opp-avg-kBps", &new_opp->avg_bw);
> > >
> > > If none of opp-hz/level/peak-kBps are available, print error message here
> > > itself..
> >
> > But you don't print any error for opp-level today. Seems like it's optional?
> >
> > >
> > > > +
> > > > + return 0;
> > >
> > > You are returning 0 on failure as well here.
> >
> > Thanks.
>
> Wait, no. This is not actually a failure. opp-avg-kBps is optional. So
> returning 0 is the right thing to do. If the mandatory properties
> aren't present an error is returned before you get to th end.
>
> -Saravana
--
viresh
On Wed, 7 Aug 2019 15:31:09 -0700, Saravana Kannan wrote:
> Interconnects often quantify their performance points in terms of
> bandwidth. So, add opp-peak-kBps (required) and opp-avg-kBps (optional) to
> allow specifying Bandwidth OPP tables in DT.
>
> opp-peak-kBps is a required property that replaces opp-hz for Bandwidth OPP
> tables.
>
> opp-avg-kBps is an optional property that can be used in Bandwidth OPP
> tables.
>
> Signed-off-by: Saravana Kannan <[email protected]>
> ---
> Documentation/devicetree/bindings/opp/opp.txt | 15 ++++++++++++---
> .../devicetree/bindings/property-units.txt | 4 ++++
> 2 files changed, 16 insertions(+), 3 deletions(-)
>
Reviewed-by: Rob Herring <[email protected]>
On Wed, Aug 21, 2019 at 1:33 PM Rob Herring <[email protected]> wrote:
>
> On Wed, 7 Aug 2019 15:31:09 -0700, Saravana Kannan wrote:
> > Interconnects often quantify their performance points in terms of
> > bandwidth. So, add opp-peak-kBps (required) and opp-avg-kBps (optional) to
> > allow specifying Bandwidth OPP tables in DT.
> >
> > opp-peak-kBps is a required property that replaces opp-hz for Bandwidth OPP
> > tables.
> >
> > opp-avg-kBps is an optional property that can be used in Bandwidth OPP
> > tables.
> >
> > Signed-off-by: Saravana Kannan <[email protected]>
> > ---
> > Documentation/devicetree/bindings/opp/opp.txt | 15 ++++++++++++---
> > .../devicetree/bindings/property-units.txt | 4 ++++
> > 2 files changed, 16 insertions(+), 3 deletions(-)
> >
>
> Reviewed-by: Rob Herring <[email protected]>
Thanks Rob!
-Saravana