linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [RFC PATCH v2 00/11] Simple QoS for exynos-bus driver using interconnect
       [not found] <CGME20190919142321eucas1p164c2591ad402427cb71fd00c348a29ec@eucas1p1.samsung.com>
@ 2019-09-19 14:22 ` Artur Świgoń
       [not found]   ` <CGME20190919142322eucas1p24bc477ee6e1bcd65546c305d55af097d@eucas1p2.samsung.com>
                     ` (11 more replies)
  0 siblings, 12 replies; 41+ messages in thread
From: Artur Świgoń @ 2019-09-19 14:22 UTC (permalink / raw)
  To: devicetree, linux-arm-kernel, linux-samsung-soc, linux-kernel,
	linux-pm, dri-devel
  Cc: Artur Świgoń,
	cw00.choi, myungjoo.ham, inki.dae, sw0312.kim, georgi.djakov,
	leonard.crestez, m.szyprowski, b.zolnierkie, krzk

The following patchset adds interconnect[1][2] framework support to the
exynos-bus devfreq driver. Extending the devfreq driver with interconnect
capabilities started as a response to the issue referenced in [3]. The
patches can be subdivided into four logical groups:

(a) Refactoring the existing devfreq driver in order to improve readability
and accommodate for adding new code (patches 01--04/11).

(b) Tweaking the interconnect framework to support the exynos-bus use case
(patches 05--07/11). Exporting of_icc_get_from_provider() allows us to
avoid hardcoding every single graph edge in the DT or driver source, and
relaxing the requirement contained in that function removes the need to
provide dummy node IDs in the DT. Adjusting the logic in
apply_constraints() (drivers/interconnect/core.c) accounts for the fact
that every bus is a separate entity and therefore a separate interconnect
provider, albeit constituting a part of a larger hierarchy.

(c) Implementing interconnect providers in the exynos-bus devfreq driver
and adding required DT properties for one selected platform, namely
Exynos4412 (patches 08--09/11). Due to the fact that this aims to be a
generic driver for various Exynos SoCs, node IDs are generated dynamically
rather than hardcoded. This has been determined to be a simpler approach,
but depends on changes described in (b).

(d) Implementing a sample interconnect consumer for exynos-mixer targeted
at the issue referenced in [3], again with DT info only for Exynos4412
(patches 10--11/11).

Integration of devfreq and interconnect functionalities is achieved by
using dev_pm_qos_*() API[5]. All new code works equally well when
CONFIG_INTERCONNECT is 'n' (as in exynos_defconfig) in which case all
interconnect API functions are no-ops.

This patchset depends on [5].

--- Changes since v1 [6]:
* Rebase on [4] (coupled regulators).
* Rebase on [5] (dev_pm_qos for devfreq).
* Use dev_pm_qos_*() API[5] instead of overriding frequency in
  exynos_bus_target().
* Use IDR for node ID allocation.
* Avoid goto in functions extracted in patches 01 & 02 (cf. patch 04).
* Reverse order of multiplication and division in
  mixer_set_memory_bandwidth() (patch 11) to avoid integer overflow.

---
Artur Świgoń
Samsung R&D Institute Poland
Samsung Electronics

---
References:
[1] Documentation/interconnect/interconnect.rst
[2] Documentation/devicetree/bindings/interconnect/interconnect.txt
[3] https://patchwork.kernel.org/patch/10861757/ (original issue)
[4] https://patchwork.kernel.org/cover/11083663/ (coupled regulators; merged)
[5] https://patchwork.kernel.org/cover/11149497/ (dev_pm_qos for devfreq)
[6] https://patchwork.kernel.org/cover/11054417/ (v1 of this RFC)

Artur Świgoń (10):
  devfreq: exynos-bus: Extract exynos_bus_profile_init()
  devfreq: exynos-bus: Extract exynos_bus_profile_init_passive()
  devfreq: exynos-bus: Change goto-based logic to if-else logic
  devfreq: exynos-bus: Clean up code
  interconnect: Export of_icc_get_from_provider()
  interconnect: Relax requirement in of_icc_get_from_provider()
  interconnect: Relax condition in apply_constraints()
  arm: dts: exynos: Add parents and #interconnect-cells to Exynos4412
  devfreq: exynos-bus: Add interconnect functionality to exynos-bus
  arm: dts: exynos: Add interconnects to Exynos4412 mixer

Marek Szyprowski (1):
  drm: exynos: mixer: Add interconnect support

 .../boot/dts/exynos4412-odroid-common.dtsi    |   1 +
 arch/arm/boot/dts/exynos4412.dtsi             |  10 +
 drivers/devfreq/exynos-bus.c                  | 319 +++++++++++++-----
 drivers/gpu/drm/exynos/exynos_mixer.c         |  71 +++-
 drivers/interconnect/core.c                   |  12 +-
 include/linux/interconnect-provider.h         |   6 +
 6 files changed, 327 insertions(+), 92 deletions(-)

-- 
2.17.1


^ permalink raw reply	[flat|nested] 41+ messages in thread

* [RFC PATCH v2 01/11] devfreq: exynos-bus: Extract exynos_bus_profile_init()
       [not found]   ` <CGME20190919142322eucas1p24bc477ee6e1bcd65546c305d55af097d@eucas1p2.samsung.com>
@ 2019-09-19 14:22     ` Artur Świgoń
  2019-09-20  2:15       ` Chanwoo Choi
  0 siblings, 1 reply; 41+ messages in thread
From: Artur Świgoń @ 2019-09-19 14:22 UTC (permalink / raw)
  To: devicetree, linux-arm-kernel, linux-samsung-soc, linux-kernel,
	linux-pm, dri-devel
  Cc: Artur Świgoń,
	cw00.choi, myungjoo.ham, inki.dae, sw0312.kim, georgi.djakov,
	leonard.crestez, m.szyprowski, b.zolnierkie, krzk

From: Artur Świgoń <a.swigon@partner.samsung.com>

This patch adds a new static function, exynos_bus_profile_init(), extracted
from exynos_bus_probe().

Signed-off-by: Artur Świgoń <a.swigon@partner.samsung.com>
---
 drivers/devfreq/exynos-bus.c | 92 +++++++++++++++++++++---------------
 1 file changed, 53 insertions(+), 39 deletions(-)

diff --git a/drivers/devfreq/exynos-bus.c b/drivers/devfreq/exynos-bus.c
index 29f422469960..78f38b7fb596 100644
--- a/drivers/devfreq/exynos-bus.c
+++ b/drivers/devfreq/exynos-bus.c
@@ -287,12 +287,62 @@ static int exynos_bus_parse_of(struct device_node *np,
 	return ret;
 }
 
+static int exynos_bus_profile_init(struct exynos_bus *bus,
+				   struct devfreq_dev_profile *profile)
+{
+	struct device *dev = bus->dev;
+	struct devfreq_simple_ondemand_data *ondemand_data;
+	int ret;
+
+	/* Initialize the struct profile and governor data for parent device */
+	profile->polling_ms = 50;
+	profile->target = exynos_bus_target;
+	profile->get_dev_status = exynos_bus_get_dev_status;
+	profile->exit = exynos_bus_exit;
+
+	ondemand_data = devm_kzalloc(dev, sizeof(*ondemand_data), GFP_KERNEL);
+	if (!ondemand_data) {
+		ret = -ENOMEM;
+		goto err;
+	}
+	ondemand_data->upthreshold = 40;
+	ondemand_data->downdifferential = 5;
+
+	/* Add devfreq device to monitor and handle the exynos bus */
+	bus->devfreq = devm_devfreq_add_device(dev, profile,
+						DEVFREQ_GOV_SIMPLE_ONDEMAND,
+						ondemand_data);
+	if (IS_ERR(bus->devfreq)) {
+		dev_err(dev, "failed to add devfreq device\n");
+		ret = PTR_ERR(bus->devfreq);
+		goto err;
+	}
+
+	/*
+	 * Enable devfreq-event to get raw data which is used to determine
+	 * current bus load.
+	 */
+	ret = exynos_bus_enable_edev(bus);
+	if (ret < 0) {
+		dev_err(dev, "failed to enable devfreq-event devices\n");
+		goto err;
+	}
+
+	ret = exynos_bus_set_event(bus);
+	if (ret < 0) {
+		dev_err(dev, "failed to set event to devfreq-event devices\n");
+		goto err;
+	}
+
+err:
+	return ret;
+}
+
 static int exynos_bus_probe(struct platform_device *pdev)
 {
 	struct device *dev = &pdev->dev;
 	struct device_node *np = dev->of_node, *node;
 	struct devfreq_dev_profile *profile;
-	struct devfreq_simple_ondemand_data *ondemand_data;
 	struct devfreq_passive_data *passive_data;
 	struct devfreq *parent_devfreq;
 	struct exynos_bus *bus;
@@ -334,45 +384,9 @@ static int exynos_bus_probe(struct platform_device *pdev)
 	if (passive)
 		goto passive;
 
-	/* Initialize the struct profile and governor data for parent device */
-	profile->polling_ms = 50;
-	profile->target = exynos_bus_target;
-	profile->get_dev_status = exynos_bus_get_dev_status;
-	profile->exit = exynos_bus_exit;
-
-	ondemand_data = devm_kzalloc(dev, sizeof(*ondemand_data), GFP_KERNEL);
-	if (!ondemand_data) {
-		ret = -ENOMEM;
+	ret = exynos_bus_profile_init(bus, profile);
+	if (ret < 0)
 		goto err;
-	}
-	ondemand_data->upthreshold = 40;
-	ondemand_data->downdifferential = 5;
-
-	/* Add devfreq device to monitor and handle the exynos bus */
-	bus->devfreq = devm_devfreq_add_device(dev, profile,
-						DEVFREQ_GOV_SIMPLE_ONDEMAND,
-						ondemand_data);
-	if (IS_ERR(bus->devfreq)) {
-		dev_err(dev, "failed to add devfreq device\n");
-		ret = PTR_ERR(bus->devfreq);
-		goto err;
-	}
-
-	/*
-	 * Enable devfreq-event to get raw data which is used to determine
-	 * current bus load.
-	 */
-	ret = exynos_bus_enable_edev(bus);
-	if (ret < 0) {
-		dev_err(dev, "failed to enable devfreq-event devices\n");
-		goto err;
-	}
-
-	ret = exynos_bus_set_event(bus);
-	if (ret < 0) {
-		dev_err(dev, "failed to set event to devfreq-event devices\n");
-		goto err;
-	}
 
 	goto out;
 passive:
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 41+ messages in thread

* [RFC PATCH v2 02/11] devfreq: exynos-bus: Extract exynos_bus_profile_init_passive()
       [not found]   ` <CGME20190919142322eucas1p1949ad95468af26698c4c5addc060ce00@eucas1p1.samsung.com>
@ 2019-09-19 14:22     ` Artur Świgoń
  0 siblings, 0 replies; 41+ messages in thread
From: Artur Świgoń @ 2019-09-19 14:22 UTC (permalink / raw)
  To: devicetree, linux-arm-kernel, linux-samsung-soc, linux-kernel,
	linux-pm, dri-devel
  Cc: Artur Świgoń,
	cw00.choi, myungjoo.ham, inki.dae, sw0312.kim, georgi.djakov,
	leonard.crestez, m.szyprowski, b.zolnierkie, krzk

From: Artur Świgoń <a.swigon@partner.samsung.com>

This patch adds a new static function, exynos_bus_profile_init_passive(),
extracted from exynos_bus_probe().

Signed-off-by: Artur Świgoń <a.swigon@partner.samsung.com>
---
 drivers/devfreq/exynos-bus.c | 70 +++++++++++++++++++++---------------
 1 file changed, 42 insertions(+), 28 deletions(-)

diff --git a/drivers/devfreq/exynos-bus.c b/drivers/devfreq/exynos-bus.c
index 78f38b7fb596..f85bed241631 100644
--- a/drivers/devfreq/exynos-bus.c
+++ b/drivers/devfreq/exynos-bus.c
@@ -338,13 +338,51 @@ static int exynos_bus_profile_init(struct exynos_bus *bus,
 	return ret;
 }
 
+static int exynos_bus_profile_init_passive(struct exynos_bus *bus,
+					   struct devfreq_dev_profile *profile)
+{
+	struct device *dev = bus->dev;
+	struct devfreq_passive_data *passive_data;
+	struct devfreq *parent_devfreq;
+	int ret = 0;
+
+	/* Initialize the struct profile and governor data for passive device */
+	profile->target = exynos_bus_target;
+	profile->exit = exynos_bus_passive_exit;
+
+	/* Get the instance of parent devfreq device */
+	parent_devfreq = devfreq_get_devfreq_by_phandle(dev, 0);
+	if (IS_ERR(parent_devfreq)) {
+		ret = -EPROBE_DEFER;
+		goto err;
+	}
+
+	passive_data = devm_kzalloc(dev, sizeof(*passive_data), GFP_KERNEL);
+	if (!passive_data) {
+		ret = -ENOMEM;
+		goto err;
+	}
+	passive_data->parent = parent_devfreq;
+
+	/* Add devfreq device for exynos bus with passive governor */
+	bus->devfreq = devm_devfreq_add_device(dev, profile, DEVFREQ_GOV_PASSIVE,
+						passive_data);
+	if (IS_ERR(bus->devfreq)) {
+		dev_err(dev,
+			"failed to add devfreq dev with passive governor\n");
+		ret = PTR_ERR(bus->devfreq);
+		goto err;
+	}
+
+err:
+	return ret;
+}
+
 static int exynos_bus_probe(struct platform_device *pdev)
 {
 	struct device *dev = &pdev->dev;
 	struct device_node *np = dev->of_node, *node;
 	struct devfreq_dev_profile *profile;
-	struct devfreq_passive_data *passive_data;
-	struct devfreq *parent_devfreq;
 	struct exynos_bus *bus;
 	int ret, max_state;
 	unsigned long min_freq, max_freq;
@@ -390,33 +428,9 @@ static int exynos_bus_probe(struct platform_device *pdev)
 
 	goto out;
 passive:
-	/* Initialize the struct profile and governor data for passive device */
-	profile->target = exynos_bus_target;
-	profile->exit = exynos_bus_passive_exit;
-
-	/* Get the instance of parent devfreq device */
-	parent_devfreq = devfreq_get_devfreq_by_phandle(dev, 0);
-	if (IS_ERR(parent_devfreq)) {
-		ret = -EPROBE_DEFER;
+	ret = exynos_bus_profile_init_passive(bus, profile);
+	if (ret < 0)
 		goto err;
-	}
-
-	passive_data = devm_kzalloc(dev, sizeof(*passive_data), GFP_KERNEL);
-	if (!passive_data) {
-		ret = -ENOMEM;
-		goto err;
-	}
-	passive_data->parent = parent_devfreq;
-
-	/* Add devfreq device for exynos bus with passive governor */
-	bus->devfreq = devm_devfreq_add_device(dev, profile, DEVFREQ_GOV_PASSIVE,
-						passive_data);
-	if (IS_ERR(bus->devfreq)) {
-		dev_err(dev,
-			"failed to add devfreq dev with passive governor\n");
-		ret = PTR_ERR(bus->devfreq);
-		goto err;
-	}
 
 out:
 	max_state = bus->devfreq->profile->max_state;
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 41+ messages in thread

* [RFC PATCH v2 03/11] devfreq: exynos-bus: Change goto-based logic to if-else logic
       [not found]   ` <CGME20190919142323eucas1p2fc73a765389432f880fa28945fd28975@eucas1p2.samsung.com>
@ 2019-09-19 14:22     ` Artur Świgoń
  0 siblings, 0 replies; 41+ messages in thread
From: Artur Świgoń @ 2019-09-19 14:22 UTC (permalink / raw)
  To: devicetree, linux-arm-kernel, linux-samsung-soc, linux-kernel,
	linux-pm, dri-devel
  Cc: Artur Świgoń,
	cw00.choi, myungjoo.ham, inki.dae, sw0312.kim, georgi.djakov,
	leonard.crestez, m.szyprowski, b.zolnierkie, krzk

From: Artur Świgoń <a.swigon@partner.samsung.com>

This patch improves code readability by changing the following construct:

>    if (cond)
>        goto passive;
>    foo();
>    goto out;
>passive:
>    bar();
>out:

into this:

>    if (cond)
>        bar();
>    else
>        foo();

Signed-off-by: Artur Świgoń <a.swigon@partner.samsung.com>
---
 drivers/devfreq/exynos-bus.c | 12 +++---------
 1 file changed, 3 insertions(+), 9 deletions(-)

diff --git a/drivers/devfreq/exynos-bus.c b/drivers/devfreq/exynos-bus.c
index f85bed241631..60ad4319fd80 100644
--- a/drivers/devfreq/exynos-bus.c
+++ b/drivers/devfreq/exynos-bus.c
@@ -420,19 +420,13 @@ static int exynos_bus_probe(struct platform_device *pdev)
 		goto err_reg;
 
 	if (passive)
-		goto passive;
+		ret = exynos_bus_profile_init_passive(bus, profile);
+	else
+		ret = exynos_bus_profile_init(bus, profile);
 
-	ret = exynos_bus_profile_init(bus, profile);
 	if (ret < 0)
 		goto err;
 
-	goto out;
-passive:
-	ret = exynos_bus_profile_init_passive(bus, profile);
-	if (ret < 0)
-		goto err;
-
-out:
 	max_state = bus->devfreq->profile->max_state;
 	min_freq = (bus->devfreq->profile->freq_table[0] / 1000);
 	max_freq = (bus->devfreq->profile->freq_table[max_state - 1] / 1000);
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 41+ messages in thread

* [RFC PATCH v2 04/11] devfreq: exynos-bus: Clean up code
       [not found]   ` <CGME20190919142324eucas1p1638cec2aafbfcaf03cfdfa7d0189143a@eucas1p1.samsung.com>
@ 2019-09-19 14:22     ` Artur Świgoń
  2019-09-20  2:22       ` Chanwoo Choi
  0 siblings, 1 reply; 41+ messages in thread
From: Artur Świgoń @ 2019-09-19 14:22 UTC (permalink / raw)
  To: devicetree, linux-arm-kernel, linux-samsung-soc, linux-kernel,
	linux-pm, dri-devel
  Cc: Artur Świgoń,
	cw00.choi, myungjoo.ham, inki.dae, sw0312.kim, georgi.djakov,
	leonard.crestez, m.szyprowski, b.zolnierkie, krzk

From: Artur Świgoń <a.swigon@partner.samsung.com>

This patch adds minor improvements to the exynos-bus driver.

Signed-off-by: Artur Świgoń <a.swigon@partner.samsung.com>
Reviewed-by: Krzysztof Kozlowski <krzk@kernel.org>
---
 drivers/devfreq/exynos-bus.c | 66 ++++++++++++++----------------------
 1 file changed, 25 insertions(+), 41 deletions(-)

diff --git a/drivers/devfreq/exynos-bus.c b/drivers/devfreq/exynos-bus.c
index 60ad4319fd80..8d44810cac69 100644
--- a/drivers/devfreq/exynos-bus.c
+++ b/drivers/devfreq/exynos-bus.c
@@ -15,11 +15,10 @@
 #include <linux/device.h>
 #include <linux/export.h>
 #include <linux/module.h>
-#include <linux/of_device.h>
+#include <linux/of.h>
 #include <linux/pm_opp.h>
 #include <linux/platform_device.h>
 #include <linux/regulator/consumer.h>
-#include <linux/slab.h>
 
 #define DEFAULT_SATURATION_RATIO	40
 
@@ -178,7 +177,7 @@ static int exynos_bus_parent_parse_of(struct device_node *np,
 	struct device *dev = bus->dev;
 	struct opp_table *opp_table;
 	const char *vdd = "vdd";
-	int i, ret, count, size;
+	int i, ret, count;
 
 	opp_table = dev_pm_opp_set_regulators(dev, &vdd, 1);
 	if (IS_ERR(opp_table)) {
@@ -201,8 +200,7 @@ static int exynos_bus_parent_parse_of(struct device_node *np,
 	}
 	bus->edev_count = count;
 
-	size = sizeof(*bus->edev) * count;
-	bus->edev = devm_kzalloc(dev, size, GFP_KERNEL);
+	bus->edev = devm_kcalloc(dev, count, sizeof(*bus->edev), GFP_KERNEL);
 	if (!bus->edev) {
 		ret = -ENOMEM;
 		goto err_regulator;
@@ -301,10 +299,9 @@ static int exynos_bus_profile_init(struct exynos_bus *bus,
 	profile->exit = exynos_bus_exit;
 
 	ondemand_data = devm_kzalloc(dev, sizeof(*ondemand_data), GFP_KERNEL);
-	if (!ondemand_data) {
-		ret = -ENOMEM;
-		goto err;
-	}
+	if (!ondemand_data)
+		return -ENOMEM;
+
 	ondemand_data->upthreshold = 40;
 	ondemand_data->downdifferential = 5;
 
@@ -314,8 +311,7 @@ static int exynos_bus_profile_init(struct exynos_bus *bus,
 						ondemand_data);
 	if (IS_ERR(bus->devfreq)) {
 		dev_err(dev, "failed to add devfreq device\n");
-		ret = PTR_ERR(bus->devfreq);
-		goto err;
+		return PTR_ERR(bus->devfreq);
 	}
 
 	/*
@@ -325,16 +321,13 @@ static int exynos_bus_profile_init(struct exynos_bus *bus,
 	ret = exynos_bus_enable_edev(bus);
 	if (ret < 0) {
 		dev_err(dev, "failed to enable devfreq-event devices\n");
-		goto err;
+		return ret;
 	}
 
 	ret = exynos_bus_set_event(bus);
-	if (ret < 0) {
+	if (ret < 0)
 		dev_err(dev, "failed to set event to devfreq-event devices\n");
-		goto err;
-	}
 
-err:
 	return ret;
 }
 
@@ -344,7 +337,6 @@ static int exynos_bus_profile_init_passive(struct exynos_bus *bus,
 	struct device *dev = bus->dev;
 	struct devfreq_passive_data *passive_data;
 	struct devfreq *parent_devfreq;
-	int ret = 0;
 
 	/* Initialize the struct profile and governor data for passive device */
 	profile->target = exynos_bus_target;
@@ -352,30 +344,26 @@ static int exynos_bus_profile_init_passive(struct exynos_bus *bus,
 
 	/* Get the instance of parent devfreq device */
 	parent_devfreq = devfreq_get_devfreq_by_phandle(dev, 0);
-	if (IS_ERR(parent_devfreq)) {
-		ret = -EPROBE_DEFER;
-		goto err;
-	}
+	if (IS_ERR(parent_devfreq))
+		return -EPROBE_DEFER;
 
 	passive_data = devm_kzalloc(dev, sizeof(*passive_data), GFP_KERNEL);
-	if (!passive_data) {
-		ret = -ENOMEM;
-		goto err;
-	}
+	if (!passive_data)
+		return -ENOMEM;
+
 	passive_data->parent = parent_devfreq;
 
 	/* Add devfreq device for exynos bus with passive governor */
-	bus->devfreq = devm_devfreq_add_device(dev, profile, DEVFREQ_GOV_PASSIVE,
+	bus->devfreq = devm_devfreq_add_device(dev, profile,
+						DEVFREQ_GOV_PASSIVE,
 						passive_data);
 	if (IS_ERR(bus->devfreq)) {
 		dev_err(dev,
 			"failed to add devfreq dev with passive governor\n");
-		ret = PTR_ERR(bus->devfreq);
-		goto err;
+		return PTR_ERR(bus->devfreq);
 	}
 
-err:
-	return ret;
+	return 0;
 }
 
 static int exynos_bus_probe(struct platform_device *pdev)
@@ -393,18 +381,18 @@ static int exynos_bus_probe(struct platform_device *pdev)
 		return -EINVAL;
 	}
 
-	bus = devm_kzalloc(&pdev->dev, sizeof(*bus), GFP_KERNEL);
+	bus = devm_kzalloc(dev, sizeof(*bus), GFP_KERNEL);
 	if (!bus)
 		return -ENOMEM;
 	mutex_init(&bus->lock);
-	bus->dev = &pdev->dev;
+	bus->dev = dev;
 	platform_set_drvdata(pdev, bus);
 
 	profile = devm_kzalloc(dev, sizeof(*profile), GFP_KERNEL);
 	if (!profile)
 		return -ENOMEM;
 
-	node = of_parse_phandle(dev->of_node, "devfreq", 0);
+	node = of_parse_phandle(np, "devfreq", 0);
 	if (node) {
 		of_node_put(node);
 		passive = true;
@@ -461,12 +449,10 @@ static int exynos_bus_resume(struct device *dev)
 	int ret;
 
 	ret = exynos_bus_enable_edev(bus);
-	if (ret < 0) {
+	if (ret < 0)
 		dev_err(dev, "failed to enable the devfreq-event devices\n");
-		return ret;
-	}
 
-	return 0;
+	return ret;
 }
 
 static int exynos_bus_suspend(struct device *dev)
@@ -475,12 +461,10 @@ static int exynos_bus_suspend(struct device *dev)
 	int ret;
 
 	ret = exynos_bus_disable_edev(bus);
-	if (ret < 0) {
+	if (ret < 0)
 		dev_err(dev, "failed to disable the devfreq-event devices\n");
-		return ret;
-	}
 
-	return 0;
+	return ret;
 }
 #endif
 
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 41+ messages in thread

* [RFC PATCH v2 05/11] interconnect: Export of_icc_get_from_provider()
       [not found]   ` <CGME20190919142325eucas1p28102446c22b1e1c61aae0bad46d079b0@eucas1p2.samsung.com>
@ 2019-09-19 14:22     ` Artur Świgoń
  2019-12-16  0:57       ` Chanwoo Choi
  0 siblings, 1 reply; 41+ messages in thread
From: Artur Świgoń @ 2019-09-19 14:22 UTC (permalink / raw)
  To: devicetree, linux-arm-kernel, linux-samsung-soc, linux-kernel,
	linux-pm, dri-devel
  Cc: Artur Świgoń,
	cw00.choi, myungjoo.ham, inki.dae, sw0312.kim, georgi.djakov,
	leonard.crestez, m.szyprowski, b.zolnierkie, krzk

From: Artur Świgoń <a.swigon@partner.samsung.com>

This patch makes the above function public (for use in exynos-bus devfreq
driver).

Signed-off-by: Artur Świgoń <a.swigon@partner.samsung.com>
Reviewed-by: Krzysztof Kozlowski <krzk@kernel.org>
---
 drivers/interconnect/core.c           | 3 ++-
 include/linux/interconnect-provider.h | 6 ++++++
 2 files changed, 8 insertions(+), 1 deletion(-)

diff --git a/drivers/interconnect/core.c b/drivers/interconnect/core.c
index 7b971228df38..95850700e367 100644
--- a/drivers/interconnect/core.c
+++ b/drivers/interconnect/core.c
@@ -279,7 +279,7 @@ EXPORT_SYMBOL_GPL(of_icc_xlate_onecell);
  * Returns a valid pointer to struct icc_node on success or ERR_PTR()
  * on failure.
  */
-static struct icc_node *of_icc_get_from_provider(struct of_phandle_args *spec)
+struct icc_node *of_icc_get_from_provider(struct of_phandle_args *spec)
 {
 	struct icc_node *node = ERR_PTR(-EPROBE_DEFER);
 	struct icc_provider *provider;
@@ -298,6 +298,7 @@ static struct icc_node *of_icc_get_from_provider(struct of_phandle_args *spec)
 
 	return node;
 }
+EXPORT_SYMBOL_GPL(of_icc_get_from_provider);
 
 /**
  * of_icc_get() - get a path handle from a DT node based on name
diff --git a/include/linux/interconnect-provider.h b/include/linux/interconnect-provider.h
index b16f9effa555..070e411564e1 100644
--- a/include/linux/interconnect-provider.h
+++ b/include/linux/interconnect-provider.h
@@ -100,6 +100,7 @@ void icc_node_add(struct icc_node *node, struct icc_provider *provider);
 void icc_node_del(struct icc_node *node);
 int icc_provider_add(struct icc_provider *provider);
 int icc_provider_del(struct icc_provider *provider);
+struct icc_node *of_icc_get_from_provider(struct of_phandle_args *spec);
 
 #else
 
@@ -140,6 +141,11 @@ static inline int icc_provider_del(struct icc_provider *provider)
 	return -ENOTSUPP;
 }
 
+struct icc_node *of_icc_get_from_provider(struct of_phandle_args *spec)
+{
+	return ERR_PTR(-ENOTSUPP);
+}
+
 #endif /* CONFIG_INTERCONNECT */
 
 #endif /* __LINUX_INTERCONNECT_PROVIDER_H */
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 41+ messages in thread

* [RFC PATCH v2 06/11] interconnect: Relax requirement in of_icc_get_from_provider()
       [not found]   ` <CGME20190919142326eucas1p204819014fe85716b47e2de4af9102cd5@eucas1p2.samsung.com>
@ 2019-09-19 14:22     ` Artur Świgoń
  0 siblings, 0 replies; 41+ messages in thread
From: Artur Świgoń @ 2019-09-19 14:22 UTC (permalink / raw)
  To: devicetree, linux-arm-kernel, linux-samsung-soc, linux-kernel,
	linux-pm, dri-devel
  Cc: Artur Świgoń,
	cw00.choi, myungjoo.ham, inki.dae, sw0312.kim, georgi.djakov,
	leonard.crestez, m.szyprowski, b.zolnierkie, krzk

From: Artur Świgoń <a.swigon@partner.samsung.com>

This patch relaxes the condition in of_icc_get_from_provider() so that it
is no longer required to set #interconnect-cells = <1> in the DT. In case
of the devfreq driver for exynos-bus, #interconnect-cells is always zero.

Signed-off-by: Artur Świgoń <a.swigon@partner.samsung.com>
Acked-by: Krzysztof Kozlowski <krzk@kernel.org>
---
 drivers/interconnect/core.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/interconnect/core.c b/drivers/interconnect/core.c
index 95850700e367..f357c3a78858 100644
--- a/drivers/interconnect/core.c
+++ b/drivers/interconnect/core.c
@@ -284,7 +284,7 @@ struct icc_node *of_icc_get_from_provider(struct of_phandle_args *spec)
 	struct icc_node *node = ERR_PTR(-EPROBE_DEFER);
 	struct icc_provider *provider;
 
-	if (!spec || spec->args_count != 1)
+	if (!spec)
 		return ERR_PTR(-EINVAL);
 
 	mutex_lock(&icc_lock);
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 41+ messages in thread

* [RFC PATCH v2 07/11] interconnect: Relax condition in apply_constraints()
       [not found]   ` <CGME20190919142327eucas1p183470eede07b50c1e3acda58f2af1eba@eucas1p1.samsung.com>
@ 2019-09-19 14:22     ` Artur Świgoń
  0 siblings, 0 replies; 41+ messages in thread
From: Artur Świgoń @ 2019-09-19 14:22 UTC (permalink / raw)
  To: devicetree, linux-arm-kernel, linux-samsung-soc, linux-kernel,
	linux-pm, dri-devel
  Cc: Artur Świgoń,
	cw00.choi, myungjoo.ham, inki.dae, sw0312.kim, georgi.djakov,
	leonard.crestez, m.szyprowski, b.zolnierkie, krzk

From: Artur Świgoń <a.swigon@partner.samsung.com>

The exynos-bus devfreq driver is extended with interconnect functionality
by a subsequent patch. This patch removes a check from the interconnect
framework that prevents interconnect from working on exynos-bus, in which
every bus is a separate interconnect provider.

Signed-off-by: Artur Świgoń <a.swigon@partner.samsung.com>
---
 drivers/interconnect/core.c | 7 ++-----
 1 file changed, 2 insertions(+), 5 deletions(-)

diff --git a/drivers/interconnect/core.c b/drivers/interconnect/core.c
index f357c3a78858..e8243665d5ba 100644
--- a/drivers/interconnect/core.c
+++ b/drivers/interconnect/core.c
@@ -224,11 +224,8 @@ static int apply_constraints(struct icc_path *path)
 	for (i = 0; i < path->num_nodes; i++) {
 		next = path->reqs[i].node;
 
-		/*
-		 * Both endpoints should be valid master-slave pairs of the
-		 * same interconnect provider that will be configured.
-		 */
-		if (!prev || next->provider != prev->provider) {
+		/* both endpoints should be valid master-slave pairs */
+		if (!prev) {
 			prev = next;
 			continue;
 		}
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 41+ messages in thread

* [RFC PATCH v2 08/11] arm: dts: exynos: Add parents and #interconnect-cells to Exynos4412
       [not found]   ` <CGME20190919142329eucas1p299762f99dd55a5d625633ceec84219f9@eucas1p2.samsung.com>
@ 2019-09-19 14:22     ` Artur Świgoń
  2019-12-16  0:51       ` Chanwoo Choi
  2019-12-16  0:55       ` Chanwoo Choi
  0 siblings, 2 replies; 41+ messages in thread
From: Artur Świgoń @ 2019-09-19 14:22 UTC (permalink / raw)
  To: devicetree, linux-arm-kernel, linux-samsung-soc, linux-kernel,
	linux-pm, dri-devel
  Cc: Artur Świgoń,
	cw00.choi, myungjoo.ham, inki.dae, sw0312.kim, georgi.djakov,
	leonard.crestez, m.szyprowski, b.zolnierkie, krzk

From: Artur Świgoń <a.swigon@partner.samsung.com>

This patch adds two fields to the Exynos4412 DTS:
  - parent: to declare connections between nodes that are not in a
    parent-child relation in devfreq;
  - #interconnect-cells: required by the interconnect framework.

Please note that #interconnect-cells is always zero and node IDs are not
hardcoded anywhere. The above-mentioned parent-child relation in devfreq
means that there is a shared power line ('devfreq' property). The 'parent'
property only signifies an interconnect connection.

Signed-off-by: Artur Świgoń <a.swigon@partner.samsung.com>
---
 arch/arm/boot/dts/exynos4412-odroid-common.dtsi | 1 +
 arch/arm/boot/dts/exynos4412.dtsi               | 9 +++++++++
 2 files changed, 10 insertions(+)

diff --git a/arch/arm/boot/dts/exynos4412-odroid-common.dtsi b/arch/arm/boot/dts/exynos4412-odroid-common.dtsi
index ea55f377d17c..bdd61ae86103 100644
--- a/arch/arm/boot/dts/exynos4412-odroid-common.dtsi
+++ b/arch/arm/boot/dts/exynos4412-odroid-common.dtsi
@@ -106,6 +106,7 @@
 &bus_leftbus {
 	devfreq-events = <&ppmu_leftbus_3>, <&ppmu_rightbus_3>;
 	vdd-supply = <&buck3_reg>;
+	parent = <&bus_dmc>;
 	status = "okay";
 };
 
diff --git a/arch/arm/boot/dts/exynos4412.dtsi b/arch/arm/boot/dts/exynos4412.dtsi
index d20db2dfe8e2..a70a671acacd 100644
--- a/arch/arm/boot/dts/exynos4412.dtsi
+++ b/arch/arm/boot/dts/exynos4412.dtsi
@@ -390,6 +390,7 @@
 			clocks = <&clock CLK_DIV_DMC>;
 			clock-names = "bus";
 			operating-points-v2 = <&bus_dmc_opp_table>;
+			#interconnect-cells = <0>;
 			status = "disabled";
 		};
 
@@ -398,6 +399,7 @@
 			clocks = <&clock CLK_DIV_ACP>;
 			clock-names = "bus";
 			operating-points-v2 = <&bus_acp_opp_table>;
+			#interconnect-cells = <0>;
 			status = "disabled";
 		};
 
@@ -406,6 +408,7 @@
 			clocks = <&clock CLK_DIV_C2C>;
 			clock-names = "bus";
 			operating-points-v2 = <&bus_dmc_opp_table>;
+			#interconnect-cells = <0>;
 			status = "disabled";
 		};
 
@@ -459,6 +462,7 @@
 			clocks = <&clock CLK_DIV_GDL>;
 			clock-names = "bus";
 			operating-points-v2 = <&bus_leftbus_opp_table>;
+			#interconnect-cells = <0>;
 			status = "disabled";
 		};
 
@@ -467,6 +471,7 @@
 			clocks = <&clock CLK_DIV_GDR>;
 			clock-names = "bus";
 			operating-points-v2 = <&bus_leftbus_opp_table>;
+			#interconnect-cells = <0>;
 			status = "disabled";
 		};
 
@@ -475,6 +480,7 @@
 			clocks = <&clock CLK_ACLK160>;
 			clock-names = "bus";
 			operating-points-v2 = <&bus_display_opp_table>;
+			#interconnect-cells = <0>;
 			status = "disabled";
 		};
 
@@ -483,6 +489,7 @@
 			clocks = <&clock CLK_ACLK133>;
 			clock-names = "bus";
 			operating-points-v2 = <&bus_fsys_opp_table>;
+			#interconnect-cells = <0>;
 			status = "disabled";
 		};
 
@@ -491,6 +498,7 @@
 			clocks = <&clock CLK_ACLK100>;
 			clock-names = "bus";
 			operating-points-v2 = <&bus_peri_opp_table>;
+			#interconnect-cells = <0>;
 			status = "disabled";
 		};
 
@@ -499,6 +507,7 @@
 			clocks = <&clock CLK_SCLK_MFC>;
 			clock-names = "bus";
 			operating-points-v2 = <&bus_leftbus_opp_table>;
+			#interconnect-cells = <0>;
 			status = "disabled";
 		};
 
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 41+ messages in thread

* [RFC PATCH v2 09/11] devfreq: exynos-bus: Add interconnect functionality to exynos-bus
       [not found]   ` <CGME20190919142329eucas1p2e53992eab9ec6b404f716f955b3c228e@eucas1p2.samsung.com>
@ 2019-09-19 14:22     ` Artur Świgoń
  2019-09-25  7:03       ` Chanwoo Choi
  2019-12-16  0:44       ` Chanwoo Choi
  0 siblings, 2 replies; 41+ messages in thread
From: Artur Świgoń @ 2019-09-19 14:22 UTC (permalink / raw)
  To: devicetree, linux-arm-kernel, linux-samsung-soc, linux-kernel,
	linux-pm, dri-devel
  Cc: Artur Świgoń,
	cw00.choi, myungjoo.ham, inki.dae, sw0312.kim, georgi.djakov,
	leonard.crestez, m.szyprowski, b.zolnierkie, krzk

From: Artur Świgoń <a.swigon@partner.samsung.com>

This patch adds interconnect functionality to the exynos-bus devfreq
driver.

The SoC topology is a graph (or, more specifically, a tree) and most of
its edges are taken from the devfreq parent-child hierarchy (cf.
Documentation/devicetree/bindings/devfreq/exynos-bus.txt). Due to
unspecified relative probing order, -EPROBE_DEFER may be propagated to
guarantee that a child is probed before its parent.

Each bus is now an interconnect provider and an interconnect node as well
(cf. Documentation/interconnect/interconnect.rst), i.e. every bus registers
itself as a node. Node IDs are not hardcoded but rather assigned at
runtime, in probing order (subject to the above-mentioned exception
regarding relative order). This approach allows for using this driver with
various Exynos SoCs.

Frequencies requested via the interconnect API for a given node are
propagated to devfreq using dev_pm_qos_update_request(). Please note that
it is not an error when CONFIG_INTERCONNECT is 'n', in which case all
interconnect API functions are no-op.

Signed-off-by: Artur Świgoń <a.swigon@partner.samsung.com>
---
 drivers/devfreq/exynos-bus.c | 153 +++++++++++++++++++++++++++++++++++
 1 file changed, 153 insertions(+)

diff --git a/drivers/devfreq/exynos-bus.c b/drivers/devfreq/exynos-bus.c
index 8d44810cac69..e0232202720d 100644
--- a/drivers/devfreq/exynos-bus.c
+++ b/drivers/devfreq/exynos-bus.c
@@ -14,14 +14,19 @@
 #include <linux/devfreq-event.h>
 #include <linux/device.h>
 #include <linux/export.h>
+#include <linux/idr.h>
+#include <linux/interconnect-provider.h>
 #include <linux/module.h>
 #include <linux/of.h>
 #include <linux/pm_opp.h>
+#include <linux/pm_qos.h>
 #include <linux/platform_device.h>
 #include <linux/regulator/consumer.h>
 
 #define DEFAULT_SATURATION_RATIO	40
 
+#define icc_units_to_khz(x) ((x) / 8)
+
 struct exynos_bus {
 	struct device *dev;
 
@@ -35,6 +40,12 @@ struct exynos_bus {
 	struct opp_table *opp_table;
 	struct clk *clk;
 	unsigned int ratio;
+
+	/* One provider per bus, one node per provider */
+	struct icc_provider provider;
+	struct icc_node *node;
+
+	struct dev_pm_qos_request qos_req;
 };
 
 /*
@@ -59,6 +70,13 @@ exynos_bus_ops_edev(enable_edev);
 exynos_bus_ops_edev(disable_edev);
 exynos_bus_ops_edev(set_event);
 
+static int exynos_bus_next_id(void)
+{
+	static DEFINE_IDA(exynos_bus_icc_ida);
+
+	return ida_alloc(&exynos_bus_icc_ida, GFP_KERNEL);
+}
+
 static int exynos_bus_get_event(struct exynos_bus *bus,
 				struct devfreq_event_data *edata)
 {
@@ -171,6 +189,38 @@ static void exynos_bus_passive_exit(struct device *dev)
 	clk_disable_unprepare(bus->clk);
 }
 
+static int exynos_bus_icc_set(struct icc_node *src, struct icc_node *dst)
+{
+	struct exynos_bus *src_bus = src->data, *dst_bus = dst->data;
+	s32 src_freq = icc_units_to_khz(src->avg_bw);
+	s32 dst_freq = icc_units_to_khz(dst->avg_bw);
+
+	dev_pm_qos_update_request(&src_bus->qos_req, src_freq);
+	dev_pm_qos_update_request(&dst_bus->qos_req, dst_freq);
+
+	return 0;
+}
+
+static int exynos_bus_icc_aggregate(struct icc_node *node, u32 tag, u32 avg_bw,
+				    u32 peak_bw, u32 *agg_avg, u32 *agg_peak)
+{
+	*agg_avg += avg_bw;
+	*agg_peak = max(*agg_peak, peak_bw);
+
+	return 0;
+}
+
+static struct icc_node *exynos_bus_icc_xlate(struct of_phandle_args *spec,
+					     void *data)
+{
+	struct exynos_bus *bus = data;
+
+	if (spec->np != bus->dev->of_node)
+		return ERR_PTR(-EINVAL);
+
+	return bus->node;
+}
+
 static int exynos_bus_parent_parse_of(struct device_node *np,
 					struct exynos_bus *bus)
 {
@@ -366,6 +416,101 @@ static int exynos_bus_profile_init_passive(struct exynos_bus *bus,
 	return 0;
 }
 
+static int exynos_bus_icc_connect(struct exynos_bus *bus)
+{
+	struct device_node *np = bus->dev->of_node;
+	struct devfreq *parent_devfreq;
+	struct icc_node *parent_node = NULL;
+	struct of_phandle_args args;
+	int ret = 0;
+
+	parent_devfreq = devfreq_get_devfreq_by_phandle(bus->dev, 0);
+	if (!IS_ERR(parent_devfreq)) {
+		struct exynos_bus *parent_bus;
+
+		parent_bus = dev_get_drvdata(parent_devfreq->dev.parent);
+		parent_node = parent_bus->node;
+	} else {
+		/* Look for parent in DT */
+		int num = of_count_phandle_with_args(np, "parent",
+						     "#interconnect-cells");
+		if (num != 1)
+			goto out; /* 'parent' is optional */
+
+		ret = of_parse_phandle_with_args(np, "parent",
+						 "#interconnect-cells",
+						 0, &args);
+		if (ret < 0)
+			goto out;
+
+		of_node_put(args.np);
+
+		parent_node = of_icc_get_from_provider(&args);
+		if (IS_ERR(parent_node)) {
+			/* May be -EPROBE_DEFER */
+			ret = PTR_ERR(parent_node);
+			goto out;
+		}
+	}
+
+	ret = icc_link_create(bus->node, parent_node->id);
+
+out:
+	return ret;
+}
+
+static int exynos_bus_icc_init(struct exynos_bus *bus)
+{
+	struct device *dev = bus->dev;
+	struct icc_provider *provider = &bus->provider;
+	struct icc_node *node;
+	int id, ret;
+
+	/* Initialize the interconnect provider */
+	provider->set = exynos_bus_icc_set;
+	provider->aggregate = exynos_bus_icc_aggregate;
+	provider->xlate = exynos_bus_icc_xlate;
+	provider->dev = dev;
+	provider->data = bus;
+
+	ret = icc_provider_add(provider);
+	if (ret < 0)
+		goto out;
+
+	ret = id = exynos_bus_next_id();
+	if (ret < 0)
+		goto err_node;
+
+	node = icc_node_create(id);
+	if (IS_ERR(node)) {
+		ret = PTR_ERR(node);
+		goto err_node;
+	}
+
+	bus->node = node;
+	node->name = dev->of_node->name;
+	node->data = bus;
+	icc_node_add(node, provider);
+
+	ret = exynos_bus_icc_connect(bus);
+	if (ret < 0)
+		goto err_connect;
+
+	ret = dev_pm_qos_add_request(bus->devfreq->dev.parent, &bus->qos_req,
+				     DEV_PM_QOS_MIN_FREQUENCY, 0);
+
+out:
+	return ret;
+
+err_connect:
+	icc_node_del(node);
+	icc_node_destroy(id);
+err_node:
+	icc_provider_del(provider);
+
+	return ret;
+}
+
 static int exynos_bus_probe(struct platform_device *pdev)
 {
 	struct device *dev = &pdev->dev;
@@ -415,6 +560,14 @@ static int exynos_bus_probe(struct platform_device *pdev)
 	if (ret < 0)
 		goto err;
 
+	/*
+	 * Initialize interconnect provider. A return value of -ENOTSUPP means
+	 * that CONFIG_INTERCONNECT is disabled.
+	 */
+	ret = exynos_bus_icc_init(bus);
+	if (ret < 0 && ret != -ENOTSUPP)
+		goto err;
+
 	max_state = bus->devfreq->profile->max_state;
 	min_freq = (bus->devfreq->profile->freq_table[0] / 1000);
 	max_freq = (bus->devfreq->profile->freq_table[max_state - 1] / 1000);
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 41+ messages in thread

* [RFC PATCH v2 10/11] arm: dts: exynos: Add interconnects to Exynos4412 mixer
       [not found]   ` <CGME20190919142330eucas1p1eceae78b148a03f2af71657b7cdd6694@eucas1p1.samsung.com>
@ 2019-09-19 14:22     ` Artur Świgoń
  0 siblings, 0 replies; 41+ messages in thread
From: Artur Świgoń @ 2019-09-19 14:22 UTC (permalink / raw)
  To: devicetree, linux-arm-kernel, linux-samsung-soc, linux-kernel,
	linux-pm, dri-devel
  Cc: Artur Świgoń,
	cw00.choi, myungjoo.ham, inki.dae, sw0312.kim, georgi.djakov,
	leonard.crestez, m.szyprowski, b.zolnierkie, krzk

From: Artur Świgoń <a.swigon@partner.samsung.com>

This patch adds an 'interconnects' property to Exynos4412 DTS in order to
declare the interconnect path used by the mixer. Please note that the
'interconnect-names' property is not needed when there is only one path in
'interconnects', in which case calling of_icc_get() with a NULL name simply
returns the right path.

Signed-off-by: Artur Świgoń <a.swigon@partner.samsung.com>
---
 arch/arm/boot/dts/exynos4412.dtsi | 1 +
 1 file changed, 1 insertion(+)

diff --git a/arch/arm/boot/dts/exynos4412.dtsi b/arch/arm/boot/dts/exynos4412.dtsi
index a70a671acacd..faaec6c40412 100644
--- a/arch/arm/boot/dts/exynos4412.dtsi
+++ b/arch/arm/boot/dts/exynos4412.dtsi
@@ -789,6 +789,7 @@
 	clock-names = "mixer", "hdmi", "sclk_hdmi", "vp";
 	clocks = <&clock CLK_MIXER>, <&clock CLK_HDMI>,
 		 <&clock CLK_SCLK_HDMI>, <&clock CLK_VP>;
+	interconnects = <&bus_display &bus_dmc>;
 };
 
 &pmu {
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 41+ messages in thread

* [RFC PATCH v2 11/11] drm: exynos: mixer: Add interconnect support
       [not found]   ` <CGME20190919142331eucas1p2107a7cb9ce8b3817ed171c21a8ad5b00@eucas1p2.samsung.com>
@ 2019-09-19 14:22     ` Artur Świgoń
  0 siblings, 0 replies; 41+ messages in thread
From: Artur Świgoń @ 2019-09-19 14:22 UTC (permalink / raw)
  To: devicetree, linux-arm-kernel, linux-samsung-soc, linux-kernel,
	linux-pm, dri-devel
  Cc: Marek Szyprowski, cw00.choi, myungjoo.ham, inki.dae, sw0312.kim,
	georgi.djakov, leonard.crestez, b.zolnierkie, krzk,
	Artur Świgoń

From: Marek Szyprowski <m.szyprowski@samsung.com>

This patch adds interconnect support to exynos-mixer. Please note that the
mixer works the same as before when CONFIG_INTERCONNECT is 'n'.

Co-developed-by: Artur Świgoń <a.swigon@partner.samsung.com>
Signed-off-by: Marek Szyprowski <m.szyprowski@samsung.com>
Signed-off-by: Artur Świgoń <a.swigon@partner.samsung.com>
---
 drivers/gpu/drm/exynos/exynos_mixer.c | 71 +++++++++++++++++++++++++--
 1 file changed, 66 insertions(+), 5 deletions(-)

diff --git a/drivers/gpu/drm/exynos/exynos_mixer.c b/drivers/gpu/drm/exynos/exynos_mixer.c
index 7b24338fad3c..a44f3284b071 100644
--- a/drivers/gpu/drm/exynos/exynos_mixer.c
+++ b/drivers/gpu/drm/exynos/exynos_mixer.c
@@ -13,6 +13,7 @@
 #include <linux/component.h>
 #include <linux/delay.h>
 #include <linux/i2c.h>
+#include <linux/interconnect.h>
 #include <linux/interrupt.h>
 #include <linux/irq.h>
 #include <linux/kernel.h>
@@ -97,6 +98,7 @@ struct mixer_context {
 	struct exynos_drm_crtc	*crtc;
 	struct exynos_drm_plane	planes[MIXER_WIN_NR];
 	unsigned long		flags;
+	struct icc_path		*soc_path;
 
 	int			irq;
 	void __iomem		*mixer_regs;
@@ -931,6 +933,40 @@ static void mixer_disable_vblank(struct exynos_drm_crtc *crtc)
 	mixer_reg_writemask(mixer_ctx, MXR_INT_EN, 0, MXR_INT_EN_VSYNC);
 }
 
+static void mixer_set_memory_bandwidth(struct exynos_drm_crtc *crtc)
+{
+	struct drm_display_mode *mode = &crtc->base.state->adjusted_mode;
+	struct mixer_context *ctx = crtc->ctx;
+	unsigned long bw, bandwidth = 0;
+	int i, j, sub;
+
+	if (!ctx->soc_path)
+		return;
+
+	for (i = 0; i < MIXER_WIN_NR; i++) {
+		struct drm_plane *plane = &ctx->planes[i].base;
+		const struct drm_format_info *format;
+
+		if (plane->state && plane->state->crtc && plane->state->fb) {
+			format = plane->state->fb->format;
+			bw = mode->hdisplay * mode->vdisplay *
+							drm_mode_vrefresh(mode);
+			if (mode->flags & DRM_MODE_FLAG_INTERLACE)
+				bw /= 2;
+			for (j = 0; j < format->num_planes; j++) {
+				sub = j ? (format->vsub * format->hsub) : 1;
+				bandwidth += format->cpp[j] * bw / sub;
+			}
+		}
+	}
+
+	/* add 20% safety margin */
+	bandwidth = bandwidth / 4 * 5;
+
+	dev_dbg(ctx->dev, "exynos-mixer: safe bandwidth %ld Bps\n", bandwidth);
+	icc_set_bw(ctx->soc_path, Bps_to_icc(bandwidth), 0);
+}
+
 static void mixer_atomic_begin(struct exynos_drm_crtc *crtc)
 {
 	struct mixer_context *ctx = crtc->ctx;
@@ -982,6 +1018,7 @@ static void mixer_atomic_flush(struct exynos_drm_crtc *crtc)
 	if (!test_bit(MXR_BIT_POWERED, &mixer_ctx->flags))
 		return;
 
+	mixer_set_memory_bandwidth(crtc);
 	mixer_enable_sync(mixer_ctx);
 	exynos_crtc_handle_event(crtc);
 }
@@ -1029,6 +1066,7 @@ static void mixer_disable(struct exynos_drm_crtc *crtc)
 	for (i = 0; i < MIXER_WIN_NR; i++)
 		mixer_disable_plane(crtc, &ctx->planes[i]);
 
+	mixer_set_memory_bandwidth(crtc);
 	exynos_drm_pipe_clk_enable(crtc, false);
 
 	pm_runtime_put(ctx->dev);
@@ -1220,12 +1258,22 @@ static int mixer_probe(struct platform_device *pdev)
 	struct device *dev = &pdev->dev;
 	const struct mixer_drv_data *drv;
 	struct mixer_context *ctx;
+	struct icc_path *path;
 	int ret;
 
+	/*
+	 * Returns NULL if CONFIG_INTERCONNECT is disabled.
+	 * May return ERR_PTR(-EPROBE_DEFER).
+	 */
+	path = of_icc_get(dev, NULL);
+	if (IS_ERR(path))
+		return PTR_ERR(path);
+
 	ctx = devm_kzalloc(&pdev->dev, sizeof(*ctx), GFP_KERNEL);
 	if (!ctx) {
 		DRM_DEV_ERROR(dev, "failed to alloc mixer context.\n");
-		return -ENOMEM;
+		ret = -ENOMEM;
+		goto err;
 	}
 
 	drv = of_device_get_match_data(dev);
@@ -1233,6 +1281,7 @@ static int mixer_probe(struct platform_device *pdev)
 	ctx->pdev = pdev;
 	ctx->dev = dev;
 	ctx->mxr_ver = drv->version;
+	ctx->soc_path = path;
 
 	if (drv->is_vp_enabled)
 		__set_bit(MXR_BIT_VP_ENABLED, &ctx->flags);
@@ -1242,17 +1291,29 @@ static int mixer_probe(struct platform_device *pdev)
 	platform_set_drvdata(pdev, ctx);
 
 	ret = component_add(&pdev->dev, &mixer_component_ops);
-	if (!ret)
-		pm_runtime_enable(dev);
+	if (ret < 0)
+		goto err;
+
+	pm_runtime_enable(dev);
+
+	return 0;
+
+err:
+	icc_put(path);
 
 	return ret;
 }
 
 static int mixer_remove(struct platform_device *pdev)
 {
-	pm_runtime_disable(&pdev->dev);
+	struct device *dev = &pdev->dev;
+	struct mixer_context *ctx = dev_get_drvdata(dev);
 
-	component_del(&pdev->dev, &mixer_component_ops);
+	pm_runtime_disable(dev);
+
+	component_del(dev, &mixer_component_ops);
+
+	icc_put(ctx->soc_path);
 
 	return 0;
 }
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 41+ messages in thread

* Re: [RFC PATCH v2 00/11] Simple QoS for exynos-bus driver using interconnect
  2019-09-19 14:22 ` [RFC PATCH v2 00/11] Simple QoS for exynos-bus driver using interconnect Artur Świgoń
                     ` (10 preceding siblings ...)
       [not found]   ` <CGME20190919142331eucas1p2107a7cb9ce8b3817ed171c21a8ad5b00@eucas1p2.samsung.com>
@ 2019-09-20  1:07   ` Chanwoo Choi
  2019-09-20  2:14     ` Chanwoo Choi
  11 siblings, 1 reply; 41+ messages in thread
From: Chanwoo Choi @ 2019-09-20  1:07 UTC (permalink / raw)
  To: Artur Świgoń,
	devicetree, linux-arm-kernel, linux-samsung-soc, linux-kernel,
	linux-pm, dri-devel
  Cc: myungjoo.ham, inki.dae, sw0312.kim, georgi.djakov,
	leonard.crestez, m.szyprowski, b.zolnierkie, krzk,
	cpgs (cpgs@samsung.com)

Hi Artur,

On v1, I mentioned that we need to discuss how to change
the v2 for this. But, I have not received any reply from you on v1.
And, without your reply from v1, you just send v2.

I think that it is not proper development sequence.
I have spent many times to review your patches
and also I'll review your patches. You have to take care
the reply of reviewer and and keep the basic rule
of mailing contribution for discussion.

On 19. 9. 19. 오후 11:22, Artur Świgoń wrote:
> The following patchset adds interconnect[1][2] framework support to the
> exynos-bus devfreq driver. Extending the devfreq driver with interconnect
> capabilities started as a response to the issue referenced in [3]. The
> patches can be subdivided into four logical groups:
> 
> (a) Refactoring the existing devfreq driver in order to improve readability
> and accommodate for adding new code (patches 01--04/11).
> 
> (b) Tweaking the interconnect framework to support the exynos-bus use case
> (patches 05--07/11). Exporting of_icc_get_from_provider() allows us to
> avoid hardcoding every single graph edge in the DT or driver source, and
> relaxing the requirement contained in that function removes the need to
> provide dummy node IDs in the DT. Adjusting the logic in
> apply_constraints() (drivers/interconnect/core.c) accounts for the fact
> that every bus is a separate entity and therefore a separate interconnect
> provider, albeit constituting a part of a larger hierarchy.
> 
> (c) Implementing interconnect providers in the exynos-bus devfreq driver
> and adding required DT properties for one selected platform, namely
> Exynos4412 (patches 08--09/11). Due to the fact that this aims to be a
> generic driver for various Exynos SoCs, node IDs are generated dynamically
> rather than hardcoded. This has been determined to be a simpler approach,
> but depends on changes described in (b).
> 
> (d) Implementing a sample interconnect consumer for exynos-mixer targeted
> at the issue referenced in [3], again with DT info only for Exynos4412
> (patches 10--11/11).
> 
> Integration of devfreq and interconnect functionalities is achieved by
> using dev_pm_qos_*() API[5]. All new code works equally well when
> CONFIG_INTERCONNECT is 'n' (as in exynos_defconfig) in which case all
> interconnect API functions are no-ops.
> 
> This patchset depends on [5].
> 
> --- Changes since v1 [6]:
> * Rebase on [4] (coupled regulators).
> * Rebase on [5] (dev_pm_qos for devfreq).
> * Use dev_pm_qos_*() API[5] instead of overriding frequency in
>   exynos_bus_target().
> * Use IDR for node ID allocation.
> * Avoid goto in functions extracted in patches 01 & 02 (cf. patch 04).
> * Reverse order of multiplication and division in
>   mixer_set_memory_bandwidth() (patch 11) to avoid integer overflow.
> 
> ---
> Artur Świgoń
> Samsung R&D Institute Poland
> Samsung Electronics
> 
> ---
> References:
> [1] Documentation/interconnect/interconnect.rst
> [2] Documentation/devicetree/bindings/interconnect/interconnect.txt
> [3] https://patchwork.kernel.org/patch/10861757/ (original issue)
> [4] https://patchwork.kernel.org/cover/11083663/ (coupled regulators; merged)
> [5] https://patchwork.kernel.org/cover/11149497/ (dev_pm_qos for devfreq)
> [6] https://patchwork.kernel.org/cover/11054417/ (v1 of this RFC)
> 
> Artur Świgoń (10):
>   devfreq: exynos-bus: Extract exynos_bus_profile_init()
>   devfreq: exynos-bus: Extract exynos_bus_profile_init_passive()
>   devfreq: exynos-bus: Change goto-based logic to if-else logic
>   devfreq: exynos-bus: Clean up code
>   interconnect: Export of_icc_get_from_provider()
>   interconnect: Relax requirement in of_icc_get_from_provider()
>   interconnect: Relax condition in apply_constraints()
>   arm: dts: exynos: Add parents and #interconnect-cells to Exynos4412
>   devfreq: exynos-bus: Add interconnect functionality to exynos-bus
>   arm: dts: exynos: Add interconnects to Exynos4412 mixer
> 
> Marek Szyprowski (1):
>   drm: exynos: mixer: Add interconnect support
> 
>  .../boot/dts/exynos4412-odroid-common.dtsi    |   1 +
>  arch/arm/boot/dts/exynos4412.dtsi             |  10 +
>  drivers/devfreq/exynos-bus.c                  | 319 +++++++++++++-----
>  drivers/gpu/drm/exynos/exynos_mixer.c         |  71 +++-
>  drivers/interconnect/core.c                   |  12 +-
>  include/linux/interconnect-provider.h         |   6 +
>  6 files changed, 327 insertions(+), 92 deletions(-)
> 


-- 
Best Regards,
Chanwoo Choi
Samsung Electronics

^ permalink raw reply	[flat|nested] 41+ messages in thread

* Re: [RFC PATCH v2 00/11] Simple QoS for exynos-bus driver using interconnect
  2019-09-20  1:07   ` [RFC PATCH v2 00/11] Simple QoS for exynos-bus driver using interconnect Chanwoo Choi
@ 2019-09-20  2:14     ` Chanwoo Choi
  2019-09-25  5:47       ` Artur Świgoń
  0 siblings, 1 reply; 41+ messages in thread
From: Chanwoo Choi @ 2019-09-20  2:14 UTC (permalink / raw)
  To: Artur Świgoń,
	devicetree, linux-arm-kernel, linux-samsung-soc, linux-kernel,
	linux-pm, dri-devel
  Cc: myungjoo.ham, inki.dae, sw0312.kim, georgi.djakov,
	leonard.crestez, m.szyprowski, b.zolnierkie, krzk,
	cpgs (cpgs@samsung.com)

Hi Artur,

I tried to just build this patch on mainline kernel or linux-next.
But, when I applied them, merge conflict happens. You didn't develop
them on latest version. Please rebase them based on latest mainline kernel.

On 19. 9. 20. 오전 10:07, Chanwoo Choi wrote:
> Hi Artur,
> 
> On v1, I mentioned that we need to discuss how to change
> the v2 for this. But, I have not received any reply from you on v1.
> And, without your reply from v1, you just send v2.
> 
> I think that it is not proper development sequence.
> I have spent many times to review your patches
> and also I'll review your patches. You have to take care
> the reply of reviewer and and keep the basic rule
> of mailing contribution for discussion.
> 
> On 19. 9. 19. 오후 11:22, Artur Świgoń wrote:
>> The following patchset adds interconnect[1][2] framework support to the
>> exynos-bus devfreq driver. Extending the devfreq driver with interconnect
>> capabilities started as a response to the issue referenced in [3]. The
>> patches can be subdivided into four logical groups:
>>
>> (a) Refactoring the existing devfreq driver in order to improve readability
>> and accommodate for adding new code (patches 01--04/11).
>>
>> (b) Tweaking the interconnect framework to support the exynos-bus use case
>> (patches 05--07/11). Exporting of_icc_get_from_provider() allows us to
>> avoid hardcoding every single graph edge in the DT or driver source, and
>> relaxing the requirement contained in that function removes the need to
>> provide dummy node IDs in the DT. Adjusting the logic in
>> apply_constraints() (drivers/interconnect/core.c) accounts for the fact
>> that every bus is a separate entity and therefore a separate interconnect
>> provider, albeit constituting a part of a larger hierarchy.
>>
>> (c) Implementing interconnect providers in the exynos-bus devfreq driver
>> and adding required DT properties for one selected platform, namely
>> Exynos4412 (patches 08--09/11). Due to the fact that this aims to be a
>> generic driver for various Exynos SoCs, node IDs are generated dynamically
>> rather than hardcoded. This has been determined to be a simpler approach,
>> but depends on changes described in (b).
>>
>> (d) Implementing a sample interconnect consumer for exynos-mixer targeted
>> at the issue referenced in [3], again with DT info only for Exynos4412
>> (patches 10--11/11).
>>
>> Integration of devfreq and interconnect functionalities is achieved by
>> using dev_pm_qos_*() API[5]. All new code works equally well when
>> CONFIG_INTERCONNECT is 'n' (as in exynos_defconfig) in which case all
>> interconnect API functions are no-ops.
>>
>> This patchset depends on [5].
>>
>> --- Changes since v1 [6]:
>> * Rebase on [4] (coupled regulators).
>> * Rebase on [5] (dev_pm_qos for devfreq).
>> * Use dev_pm_qos_*() API[5] instead of overriding frequency in
>>   exynos_bus_target().
>> * Use IDR for node ID allocation.
>> * Avoid goto in functions extracted in patches 01 & 02 (cf. patch 04).
>> * Reverse order of multiplication and division in
>>   mixer_set_memory_bandwidth() (patch 11) to avoid integer overflow.
>>
>> ---
>> Artur Świgoń
>> Samsung R&D Institute Poland
>> Samsung Electronics
>>
>> ---
>> References:
>> [1] Documentation/interconnect/interconnect.rst
>> [2] Documentation/devicetree/bindings/interconnect/interconnect.txt
>> [3] https://patchwork.kernel.org/patch/10861757/ (original issue)
>> [4] https://patchwork.kernel.org/cover/11083663/ (coupled regulators; merged)
>> [5] https://patchwork.kernel.org/cover/11149497/ (dev_pm_qos for devfreq)
>> [6] https://patchwork.kernel.org/cover/11054417/ (v1 of this RFC)
>>
>> Artur Świgoń (10):
>>   devfreq: exynos-bus: Extract exynos_bus_profile_init()
>>   devfreq: exynos-bus: Extract exynos_bus_profile_init_passive()
>>   devfreq: exynos-bus: Change goto-based logic to if-else logic
>>   devfreq: exynos-bus: Clean up code
>>   interconnect: Export of_icc_get_from_provider()
>>   interconnect: Relax requirement in of_icc_get_from_provider()
>>   interconnect: Relax condition in apply_constraints()
>>   arm: dts: exynos: Add parents and #interconnect-cells to Exynos4412
>>   devfreq: exynos-bus: Add interconnect functionality to exynos-bus
>>   arm: dts: exynos: Add interconnects to Exynos4412 mixer
>>
>> Marek Szyprowski (1):
>>   drm: exynos: mixer: Add interconnect support
>>
>>  .../boot/dts/exynos4412-odroid-common.dtsi    |   1 +
>>  arch/arm/boot/dts/exynos4412.dtsi             |  10 +
>>  drivers/devfreq/exynos-bus.c                  | 319 +++++++++++++-----
>>  drivers/gpu/drm/exynos/exynos_mixer.c         |  71 +++-
>>  drivers/interconnect/core.c                   |  12 +-
>>  include/linux/interconnect-provider.h         |   6 +
>>  6 files changed, 327 insertions(+), 92 deletions(-)
>>
> 
> 


-- 
Best Regards,
Chanwoo Choi
Samsung Electronics

^ permalink raw reply	[flat|nested] 41+ messages in thread

* Re: [RFC PATCH v2 01/11] devfreq: exynos-bus: Extract exynos_bus_profile_init()
  2019-09-19 14:22     ` [RFC PATCH v2 01/11] devfreq: exynos-bus: Extract exynos_bus_profile_init() Artur Świgoń
@ 2019-09-20  2:15       ` Chanwoo Choi
  2019-09-25  5:44         ` Artur Świgoń
  0 siblings, 1 reply; 41+ messages in thread
From: Chanwoo Choi @ 2019-09-20  2:15 UTC (permalink / raw)
  To: Artur Świgoń,
	devicetree, linux-arm-kernel, linux-samsung-soc, linux-kernel,
	linux-pm, dri-devel
  Cc: Artur Świgoń,
	myungjoo.ham, inki.dae, sw0312.kim, georgi.djakov,
	leonard.crestez, m.szyprowski, b.zolnierkie, krzk

Hi,

As I already replied on v1, patch1/2/3 clean-up code
for readability without any behavior changes. 

I think that you better to merge patch1/2/3 to one patch.

On 19. 9. 19. 오후 11:22, Artur Świgoń wrote:
> From: Artur Świgoń <a.swigon@partner.samsung.com>
> 
> This patch adds a new static function, exynos_bus_profile_init(), extracted
> from exynos_bus_probe().
> 
> Signed-off-by: Artur Świgoń <a.swigon@partner.samsung.com>
> ---
>  drivers/devfreq/exynos-bus.c | 92 +++++++++++++++++++++---------------
>  1 file changed, 53 insertions(+), 39 deletions(-)
> 
> diff --git a/drivers/devfreq/exynos-bus.c b/drivers/devfreq/exynos-bus.c
> index 29f422469960..78f38b7fb596 100644
> --- a/drivers/devfreq/exynos-bus.c
> +++ b/drivers/devfreq/exynos-bus.c
> @@ -287,12 +287,62 @@ static int exynos_bus_parse_of(struct device_node *np,
>  	return ret;
>  }
>  
> +static int exynos_bus_profile_init(struct exynos_bus *bus,
> +				   struct devfreq_dev_profile *profile)
> +{
> +	struct device *dev = bus->dev;
> +	struct devfreq_simple_ondemand_data *ondemand_data;
> +	int ret;
> +
> +	/* Initialize the struct profile and governor data for parent device */
> +	profile->polling_ms = 50;
> +	profile->target = exynos_bus_target;
> +	profile->get_dev_status = exynos_bus_get_dev_status;
> +	profile->exit = exynos_bus_exit;
> +
> +	ondemand_data = devm_kzalloc(dev, sizeof(*ondemand_data), GFP_KERNEL);
> +	if (!ondemand_data) {
> +		ret = -ENOMEM;
> +		goto err;
> +	}
> +	ondemand_data->upthreshold = 40;
> +	ondemand_data->downdifferential = 5;
> +
> +	/* Add devfreq device to monitor and handle the exynos bus */
> +	bus->devfreq = devm_devfreq_add_device(dev, profile,
> +						DEVFREQ_GOV_SIMPLE_ONDEMAND,
> +						ondemand_data);
> +	if (IS_ERR(bus->devfreq)) {
> +		dev_err(dev, "failed to add devfreq device\n");
> +		ret = PTR_ERR(bus->devfreq);
> +		goto err;
> +	}
> +
> +	/*
> +	 * Enable devfreq-event to get raw data which is used to determine
> +	 * current bus load.
> +	 */
> +	ret = exynos_bus_enable_edev(bus);
> +	if (ret < 0) {
> +		dev_err(dev, "failed to enable devfreq-event devices\n");
> +		goto err;
> +	}
> +
> +	ret = exynos_bus_set_event(bus);
> +	if (ret < 0) {
> +		dev_err(dev, "failed to set event to devfreq-event devices\n");
> +		goto err;
> +	}
> +
> +err:
> +	return ret;
> +}
> +
>  static int exynos_bus_probe(struct platform_device *pdev)
>  {
>  	struct device *dev = &pdev->dev;
>  	struct device_node *np = dev->of_node, *node;
>  	struct devfreq_dev_profile *profile;
> -	struct devfreq_simple_ondemand_data *ondemand_data;
>  	struct devfreq_passive_data *passive_data;
>  	struct devfreq *parent_devfreq;
>  	struct exynos_bus *bus;
> @@ -334,45 +384,9 @@ static int exynos_bus_probe(struct platform_device *pdev)
>  	if (passive)
>  		goto passive;
>  
> -	/* Initialize the struct profile and governor data for parent device */
> -	profile->polling_ms = 50;
> -	profile->target = exynos_bus_target;
> -	profile->get_dev_status = exynos_bus_get_dev_status;
> -	profile->exit = exynos_bus_exit;
> -
> -	ondemand_data = devm_kzalloc(dev, sizeof(*ondemand_data), GFP_KERNEL);
> -	if (!ondemand_data) {
> -		ret = -ENOMEM;
> +	ret = exynos_bus_profile_init(bus, profile);
> +	if (ret < 0)
>  		goto err;
> -	}
> -	ondemand_data->upthreshold = 40;
> -	ondemand_data->downdifferential = 5;
> -
> -	/* Add devfreq device to monitor and handle the exynos bus */
> -	bus->devfreq = devm_devfreq_add_device(dev, profile,
> -						DEVFREQ_GOV_SIMPLE_ONDEMAND,
> -						ondemand_data);
> -	if (IS_ERR(bus->devfreq)) {
> -		dev_err(dev, "failed to add devfreq device\n");
> -		ret = PTR_ERR(bus->devfreq);
> -		goto err;
> -	}
> -
> -	/*
> -	 * Enable devfreq-event to get raw data which is used to determine
> -	 * current bus load.
> -	 */
> -	ret = exynos_bus_enable_edev(bus);
> -	if (ret < 0) {
> -		dev_err(dev, "failed to enable devfreq-event devices\n");
> -		goto err;
> -	}
> -
> -	ret = exynos_bus_set_event(bus);
> -	if (ret < 0) {
> -		dev_err(dev, "failed to set event to devfreq-event devices\n");
> -		goto err;
> -	}
>  
>  	goto out;
>  passive:
> 


-- 
Best Regards,
Chanwoo Choi
Samsung Electronics

^ permalink raw reply	[flat|nested] 41+ messages in thread

* Re: [RFC PATCH v2 04/11] devfreq: exynos-bus: Clean up code
  2019-09-19 14:22     ` [RFC PATCH v2 04/11] devfreq: exynos-bus: Clean up code Artur Świgoń
@ 2019-09-20  2:22       ` Chanwoo Choi
  2019-10-03  8:10         ` Artur Świgoń
  0 siblings, 1 reply; 41+ messages in thread
From: Chanwoo Choi @ 2019-09-20  2:22 UTC (permalink / raw)
  To: Artur Świgoń,
	devicetree, linux-arm-kernel, linux-samsung-soc, linux-kernel,
	linux-pm, dri-devel
  Cc: Artur Świgoń,
	myungjoo.ham, inki.dae, sw0312.kim, georgi.djakov,
	leonard.crestez, m.szyprowski, b.zolnierkie, krzk

Hi Artur,

On 19. 9. 19. 오후 11:22, Artur Świgoń wrote:
> From: Artur Świgoń <a.swigon@partner.samsung.com>
> 
> This patch adds minor improvements to the exynos-bus driver.
> 
> Signed-off-by: Artur Świgoń <a.swigon@partner.samsung.com>
> Reviewed-by: Krzysztof Kozlowski <krzk@kernel.org>
> ---
>  drivers/devfreq/exynos-bus.c | 66 ++++++++++++++----------------------
>  1 file changed, 25 insertions(+), 41 deletions(-)
> 
> diff --git a/drivers/devfreq/exynos-bus.c b/drivers/devfreq/exynos-bus.c
> index 60ad4319fd80..8d44810cac69 100644
> --- a/drivers/devfreq/exynos-bus.c
> +++ b/drivers/devfreq/exynos-bus.c
> @@ -15,11 +15,10 @@
>  #include <linux/device.h>
>  #include <linux/export.h>
>  #include <linux/module.h>
> -#include <linux/of_device.h>
> +#include <linux/of.h>
>  #include <linux/pm_opp.h>
>  #include <linux/platform_device.h>
>  #include <linux/regulator/consumer.h>
> -#include <linux/slab.h>
>  
>  #define DEFAULT_SATURATION_RATIO	40
>  
> @@ -178,7 +177,7 @@ static int exynos_bus_parent_parse_of(struct device_node *np,
>  	struct device *dev = bus->dev;
>  	struct opp_table *opp_table;
>  	const char *vdd = "vdd";
> -	int i, ret, count, size;
> +	int i, ret, count;
>  
>  	opp_table = dev_pm_opp_set_regulators(dev, &vdd, 1);
>  	if (IS_ERR(opp_table)) {
> @@ -201,8 +200,7 @@ static int exynos_bus_parent_parse_of(struct device_node *np,
>  	}
>  	bus->edev_count = count;
>  
> -	size = sizeof(*bus->edev) * count;
> -	bus->edev = devm_kzalloc(dev, size, GFP_KERNEL);
> +	bus->edev = devm_kcalloc(dev, count, sizeof(*bus->edev), GFP_KERNEL);
>  	if (!bus->edev) {
>  		ret = -ENOMEM;
>  		goto err_regulator;
> @@ -301,10 +299,9 @@ static int exynos_bus_profile_init(struct exynos_bus *bus,
>  	profile->exit = exynos_bus_exit;
>  
>  	ondemand_data = devm_kzalloc(dev, sizeof(*ondemand_data), GFP_KERNEL);
> -	if (!ondemand_data) {
> -		ret = -ENOMEM;
> -		goto err;
> -	}
> +	if (!ondemand_data)
> +		return -ENOMEM;
> +
>  	ondemand_data->upthreshold = 40;
>  	ondemand_data->downdifferential = 5;
>  
> @@ -314,8 +311,7 @@ static int exynos_bus_profile_init(struct exynos_bus *bus,
>  						ondemand_data);
>  	if (IS_ERR(bus->devfreq)) {
>  		dev_err(dev, "failed to add devfreq device\n");
> -		ret = PTR_ERR(bus->devfreq);
> -		goto err;
> +		return PTR_ERR(bus->devfreq);
>  	}
>  
>  	/*
> @@ -325,16 +321,13 @@ static int exynos_bus_profile_init(struct exynos_bus *bus,
>  	ret = exynos_bus_enable_edev(bus);
>  	if (ret < 0) {
>  		dev_err(dev, "failed to enable devfreq-event devices\n");
> -		goto err;
> +		return ret;
>  	}
>  
>  	ret = exynos_bus_set_event(bus);
> -	if (ret < 0) {
> +	if (ret < 0)
>  		dev_err(dev, "failed to set event to devfreq-event devices\n");
> -		goto err;

Instead of removing 'goto err', just return err as I commented[1] on v1.
[1] https://lkml.org/lkml/2019/7/26/331

> -	}
>  
> -err:
>  	return ret;

And you just keep 'return ret' or you can change it as 'return 0'.


>  }
>  
> @@ -344,7 +337,6 @@ static int exynos_bus_profile_init_passive(struct exynos_bus *bus,
>  	struct device *dev = bus->dev;
>  	struct devfreq_passive_data *passive_data;
>  	struct devfreq *parent_devfreq;
> -	int ret = 0;
>  
>  	/* Initialize the struct profile and governor data for passive device */
>  	profile->target = exynos_bus_target;
> @@ -352,30 +344,26 @@ static int exynos_bus_profile_init_passive(struct exynos_bus *bus,
>  
>  	/* Get the instance of parent devfreq device */
>  	parent_devfreq = devfreq_get_devfreq_by_phandle(dev, 0);
> -	if (IS_ERR(parent_devfreq)) {
> -		ret = -EPROBE_DEFER;
> -		goto err;
> -	}
> +	if (IS_ERR(parent_devfreq))
> +		return -EPROBE_DEFER;
>  
>  	passive_data = devm_kzalloc(dev, sizeof(*passive_data), GFP_KERNEL);
> -	if (!passive_data) {
> -		ret = -ENOMEM;
> -		goto err;
> -	}
> +	if (!passive_data)
> +		return -ENOMEM;
> +
>  	passive_data->parent = parent_devfreq;
>  
>  	/* Add devfreq device for exynos bus with passive governor */
> -	bus->devfreq = devm_devfreq_add_device(dev, profile, DEVFREQ_GOV_PASSIVE,
> +	bus->devfreq = devm_devfreq_add_device(dev, profile,
> +						DEVFREQ_GOV_PASSIVE,
>  						passive_data);
>  	if (IS_ERR(bus->devfreq)) {
>  		dev_err(dev,
>  			"failed to add devfreq dev with passive governor\n");
> -		ret = PTR_ERR(bus->devfreq);
> -		goto err;
> +		return PTR_ERR(bus->devfreq);
>  	}
>  
> -err:
> -	return ret;
> +	return 0;
>  }
>  
>  static int exynos_bus_probe(struct platform_device *pdev)
> @@ -393,18 +381,18 @@ static int exynos_bus_probe(struct platform_device *pdev)
>  		return -EINVAL;
>  	}
>  
> -	bus = devm_kzalloc(&pdev->dev, sizeof(*bus), GFP_KERNEL);
> +	bus = devm_kzalloc(dev, sizeof(*bus), GFP_KERNEL);
>  	if (!bus)
>  		return -ENOMEM;
>  	mutex_init(&bus->lock);
> -	bus->dev = &pdev->dev;
> +	bus->dev = dev;
>  	platform_set_drvdata(pdev, bus);
>  
>  	profile = devm_kzalloc(dev, sizeof(*profile), GFP_KERNEL);
>  	if (!profile)
>  		return -ENOMEM;
>  
> -	node = of_parse_phandle(dev->of_node, "devfreq", 0);
> +	node = of_parse_phandle(np, "devfreq", 0);
>  	if (node) {
>  		of_node_put(node);
>  		passive = true;
> @@ -461,12 +449,10 @@ static int exynos_bus_resume(struct device *dev)
>  	int ret;
>  
>  	ret = exynos_bus_enable_edev(bus);
> -	if (ret < 0) {
> +	if (ret < 0)
>  		dev_err(dev, "failed to enable the devfreq-event devices\n");
> -		return ret;

Keep the 'return ret' if error happen as I commented[1] on v1.
[1] https://lkml.org/lkml/2019/7/26/331

> -	}
>  
> -	return 0;
> +	return ret;

And you just keep 'return 0' or you can change it as 'return ret'.

>  }
>  
>  static int exynos_bus_suspend(struct device *dev)
> @@ -475,12 +461,10 @@ static int exynos_bus_suspend(struct device *dev)
>  	int ret;
>  
>  	ret = exynos_bus_disable_edev(bus);
> -	if (ret < 0) {
> +	if (ret < 0)
>  		dev_err(dev, "failed to disable the devfreq-event devices\n");
> -		return ret;

Keep the 'return ret' if error happen as I commented[1] on v1.
[1] https://lkml.org/lkml/2019/7/26/331

> -	}
>  
> -	return 0;
> +	return ret;

And you just keep 'return 0' or you can change it as 'return ret'.

>  }
>  #endif
>  
> 


-- 
Best Regards,
Chanwoo Choi
Samsung Electronics

^ permalink raw reply	[flat|nested] 41+ messages in thread

* Re: [RFC PATCH v2 01/11] devfreq: exynos-bus: Extract exynos_bus_profile_init()
  2019-09-20  2:15       ` Chanwoo Choi
@ 2019-09-25  5:44         ` Artur Świgoń
  2019-09-25  6:37           ` Chanwoo Choi
  0 siblings, 1 reply; 41+ messages in thread
From: Artur Świgoń @ 2019-09-25  5:44 UTC (permalink / raw)
  To: Chanwoo Choi, devicetree, linux-arm-kernel, linux-samsung-soc,
	linux-kernel, linux-pm, dri-devel
  Cc: Artur Świgoń,
	myungjoo.ham, inki.dae, sw0312.kim, georgi.djakov,
	leonard.crestez, m.szyprowski, b.zolnierkie, krzk

Hi,

On Fri, 2019-09-20 at 11:15 +0900, Chanwoo Choi wrote:
> Hi,
> 
> As I already replied on v1, patch1/2/3 clean-up code
> for readability without any behavior changes. 
> 
> I think that you better to merge patch1/2/3 to one patch.

Yes, when writing the cover letter I think I forgot to explain why I decided not
to merge these patches. Basically, none of the diff algorithms available in git
(I've got v2.17.1) is able to produce a readable patch with these changes
combined together into a single patch (functions are intermixed together in the
output, git thinks that 'exynos_bus_probe' is a new function).

Please take a look at the diff at the bottom of this message to see how patches
01..03 look when combined. If such patch looks acceptable to you, I can merge.

> On 19. 9. 19. 오후 11:22, Artur Świgoń wrote:
> > From: Artur Świgoń <a.swigon@partner.samsung.com>
> > 
> > This patch adds a new static function, exynos_bus_profile_init(), extracted
> > from exynos_bus_probe().
> > 
> > Signed-off-by: Artur Świgoń <a.swigon@partner.samsung.com>
> > ---
> >  drivers/devfreq/exynos-bus.c | 92 +++++++++++++++++++++---------------
> >  1 file changed, 53 insertions(+), 39 deletions(-)
> > 
> > diff --git a/drivers/devfreq/exynos-bus.c b/drivers/devfreq/exynos-bus.c
> > index 29f422469960..78f38b7fb596 100644
> > --- a/drivers/devfreq/exynos-bus.c
> > +++ b/drivers/devfreq/exynos-bus.c
> > @@ -287,12 +287,62 @@ static int exynos_bus_parse_of(struct device_node *np,
> >  	return ret;
> >  }
> >  
> > +static int exynos_bus_profile_init(struct exynos_bus *bus,
> > +				   struct devfreq_dev_profile *profile)
> > +{
> > +	struct device *dev = bus->dev;
> > +	struct devfreq_simple_ondemand_data *ondemand_data;
> > +	int ret;
> > +
> > +	/* Initialize the struct profile and governor data for parent device */
> > +	profile->polling_ms = 50;
> > +	profile->target = exynos_bus_target;
> > +	profile->get_dev_status = exynos_bus_get_dev_status;
> > +	profile->exit = exynos_bus_exit;
> > +
> > +	ondemand_data = devm_kzalloc(dev, sizeof(*ondemand_data), GFP_KERNEL);
> > +	if (!ondemand_data) {
> > +		ret = -ENOMEM;
> > +		goto err;
> > +	}
> > +	ondemand_data->upthreshold = 40;
> > +	ondemand_data->downdifferential = 5;
> > +
> > +	/* Add devfreq device to monitor and handle the exynos bus */
> > +	bus->devfreq = devm_devfreq_add_device(dev, profile,
> > +						DEVFREQ_GOV_SIMPLE_ONDEMAND,
> > +						ondemand_data);
> > +	if (IS_ERR(bus->devfreq)) {
> > +		dev_err(dev, "failed to add devfreq device\n");
> > +		ret = PTR_ERR(bus->devfreq);
> > +		goto err;
> > +	}
> > +
> > +	/*
> > +	 * Enable devfreq-event to get raw data which is used to determine
> > +	 * current bus load.
> > +	 */
> > +	ret = exynos_bus_enable_edev(bus);
> > +	if (ret < 0) {
> > +		dev_err(dev, "failed to enable devfreq-event devices\n");
> > +		goto err;
> > +	}
> > +
> > +	ret = exynos_bus_set_event(bus);
> > +	if (ret < 0) {
> > +		dev_err(dev, "failed to set event to devfreq-event devices\n");
> > +		goto err;
> > +	}
> > +
> > +err:
> > +	return ret;
> > +}
> > +
> >  static int exynos_bus_probe(struct platform_device *pdev)
> >  {
> >  	struct device *dev = &pdev->dev;
> >  	struct device_node *np = dev->of_node, *node;
> >  	struct devfreq_dev_profile *profile;
> > -	struct devfreq_simple_ondemand_data *ondemand_data;
> >  	struct devfreq_passive_data *passive_data;
> >  	struct devfreq *parent_devfreq;
> >  	struct exynos_bus *bus;
> > @@ -334,45 +384,9 @@ static int exynos_bus_probe(struct platform_device *pdev)
> >  	if (passive)
> >  		goto passive;
> >  
> > -	/* Initialize the struct profile and governor data for parent device */
> > -	profile->polling_ms = 50;
> > -	profile->target = exynos_bus_target;
> > -	profile->get_dev_status = exynos_bus_get_dev_status;
> > -	profile->exit = exynos_bus_exit;
> > -
> > -	ondemand_data = devm_kzalloc(dev, sizeof(*ondemand_data), GFP_KERNEL);
> > -	if (!ondemand_data) {
> > -		ret = -ENOMEM;
> > +	ret = exynos_bus_profile_init(bus, profile);
> > +	if (ret < 0)
> >  		goto err;
> > -	}
> > -	ondemand_data->upthreshold = 40;
> > -	ondemand_data->downdifferential = 5;
> > -
> > -	/* Add devfreq device to monitor and handle the exynos bus */
> > -	bus->devfreq = devm_devfreq_add_device(dev, profile,
> > -						DEVFREQ_GOV_SIMPLE_ONDEMAND,
> > -						ondemand_data);
> > -	if (IS_ERR(bus->devfreq)) {
> > -		dev_err(dev, "failed to add devfreq device\n");
> > -		ret = PTR_ERR(bus->devfreq);
> > -		goto err;
> > -	}
> > -
> > -	/*
> > -	 * Enable devfreq-event to get raw data which is used to determine
> > -	 * current bus load.
> > -	 */
> > -	ret = exynos_bus_enable_edev(bus);
> > -	if (ret < 0) {
> > -		dev_err(dev, "failed to enable devfreq-event devices\n");
> > -		goto err;
> > -	}
> > -
> > -	ret = exynos_bus_set_event(bus);
> > -	if (ret < 0) {
> > -		dev_err(dev, "failed to set event to devfreq-event devices\n");
> > -		goto err;
> > -	}
> >  
> >  	goto out;
> >  passive:

commit cacf8e4ea0e111908d11779977c81e29d6418801
Author: Artur Świgoń <a.swigon@partner.samsung.com>
Date:   Tue Aug 27 13:17:28 2019 +0200

    tmp: merge patches 01-03
    
    Signed-off-by: Artur Świgoń <a.swigon@partner.samsung.com>

diff --git a/drivers/devfreq/exynos-bus.c b/drivers/devfreq/exynos-bus.c
index 29f422469960..60ad4319fd80 100644
--- a/drivers/devfreq/exynos-bus.c
+++ b/drivers/devfreq/exynos-bus.c
@@ -287,52 +287,12 @@ static int exynos_bus_parse_of(struct device_node *np,
 	return ret;
 }
 
-static int exynos_bus_probe(struct platform_device *pdev)
+static int exynos_bus_profile_init(struct exynos_bus *bus,
+				   struct devfreq_dev_profile *profile)
 {
-	struct device *dev = &pdev->dev;
-	struct device_node *np = dev->of_node, *node;
-	struct devfreq_dev_profile *profile;
+	struct device *dev = bus->dev;
 	struct devfreq_simple_ondemand_data *ondemand_data;
-	struct devfreq_passive_data *passive_data;
-	struct devfreq *parent_devfreq;
-	struct exynos_bus *bus;
-	int ret, max_state;
-	unsigned long min_freq, max_freq;
-	bool passive = false;
-
-	if (!np) {
-		dev_err(dev, "failed to find devicetree node\n");
-		return -EINVAL;
-	}
-
-	bus = devm_kzalloc(&pdev->dev, sizeof(*bus), GFP_KERNEL);
-	if (!bus)
-		return -ENOMEM;
-	mutex_init(&bus->lock);
-	bus->dev = &pdev->dev;
-	platform_set_drvdata(pdev, bus);
-
-	profile = devm_kzalloc(dev, sizeof(*profile), GFP_KERNEL);
-	if (!profile)
-		return -ENOMEM;
-
-	node = of_parse_phandle(dev->of_node, "devfreq", 0);
-	if (node) {
-		of_node_put(node);
-		passive = true;
-	} else {
-		ret = exynos_bus_parent_parse_of(np, bus);
-		if (ret < 0)
-			return ret;
-	}
-
-	/* Parse the device-tree to get the resource information */
-	ret = exynos_bus_parse_of(np, bus);
-	if (ret < 0)
-		goto err_reg;
-
-	if (passive)
-		goto passive;
+	int ret;
 
 	/* Initialize the struct profile and governor data for parent device */
 	profile->polling_ms = 50;
@@ -374,8 +334,18 @@ static int exynos_bus_probe(struct platform_device *pdev)
 		goto err;
 	}
 
-	goto out;
-passive:
+err:
+	return ret;
+}
+
+static int exynos_bus_profile_init_passive(struct exynos_bus *bus,
+					   struct devfreq_dev_profile *profile)
+{
+	struct device *dev = bus->dev;
+	struct devfreq_passive_data *passive_data;
+	struct devfreq *parent_devfreq;
+	int ret = 0;
+
 	/* Initialize the struct profile and governor data for passive device */
 	profile->target = exynos_bus_target;
 	profile->exit = exynos_bus_passive_exit;
@@ -404,7 +374,59 @@ static int exynos_bus_probe(struct platform_device *pdev)
 		goto err;
 	}
 
-out:
+err:
+	return ret;
+}
+
+static int exynos_bus_probe(struct platform_device *pdev)
+{
+	struct device *dev = &pdev->dev;
+	struct device_node *np = dev->of_node, *node;
+	struct devfreq_dev_profile *profile;
+	struct exynos_bus *bus;
+	int ret, max_state;
+	unsigned long min_freq, max_freq;
+	bool passive = false;
+
+	if (!np) {
+		dev_err(dev, "failed to find devicetree node\n");
+		return -EINVAL;
+	}
+
+	bus = devm_kzalloc(&pdev->dev, sizeof(*bus), GFP_KERNEL);
+	if (!bus)
+		return -ENOMEM;
+	mutex_init(&bus->lock);
+	bus->dev = &pdev->dev;
+	platform_set_drvdata(pdev, bus);
+
+	profile = devm_kzalloc(dev, sizeof(*profile), GFP_KERNEL);
+	if (!profile)
+		return -ENOMEM;
+
+	node = of_parse_phandle(dev->of_node, "devfreq", 0);
+	if (node) {
+		of_node_put(node);
+		passive = true;
+	} else {
+		ret = exynos_bus_parent_parse_of(np, bus);
+		if (ret < 0)
+			return ret;
+	}
+
+	/* Parse the device-tree to get the resource information */
+	ret = exynos_bus_parse_of(np, bus);
+	if (ret < 0)
+		goto err_reg;
+
+	if (passive)
+		ret = exynos_bus_profile_init_passive(bus, profile);
+	else
+		ret = exynos_bus_profile_init(bus, profile);
+
+	if (ret < 0)
+		goto err;
+
 	max_state = bus->devfreq->profile->max_state;
 	min_freq = (bus->devfreq->profile->freq_table[0] / 1000);
 	max_freq = (bus->devfreq->profile->freq_table[max_state - 1] / 1000);



^ permalink raw reply related	[flat|nested] 41+ messages in thread

* Re: [RFC PATCH v2 00/11] Simple QoS for exynos-bus driver using interconnect
  2019-09-20  2:14     ` Chanwoo Choi
@ 2019-09-25  5:47       ` Artur Świgoń
  2019-09-25  6:12         ` Chanwoo Choi
  0 siblings, 1 reply; 41+ messages in thread
From: Artur Świgoń @ 2019-09-25  5:47 UTC (permalink / raw)
  To: Chanwoo Choi, devicetree, linux-arm-kernel, linux-samsung-soc,
	linux-kernel, linux-pm, dri-devel
  Cc: myungjoo.ham, inki.dae, sw0312.kim, georgi.djakov,
	leonard.crestez, m.szyprowski, b.zolnierkie, krzk,
	cpgs (cpgs@samsung.com)

Hi,

On Fri, 2019-09-20 at 11:14 +0900, Chanwoo Choi wrote:
> Hi Artur,
> 
> I tried to just build this patch on mainline kernel or linux-next.
> But, when I applied them, merge conflict happens. You didn't develop
> them on latest version. Please rebase them based on latest mainline kernel.

I developed on top of next-20190918 on which I applied
https://patchwork.kernel.org/cover/11149497/ as I mentioned in the cover
letter. The dev_pm_qos patches and my RFC have just cleanly rebased together on
top of next-20190920. Could you check if you have the dev_pm_qos patches (v5,
the version number is missing in this one; link above) and if so, where does the
conflict appear?

> On 19. 9. 20. 오전 10:07, Chanwoo Choi wrote:
> > Hi Artur,
> > 
> > On v1, I mentioned that we need to discuss how to change
> > the v2 for this. But, I have not received any reply from you on v1.
> > And, without your reply from v1, you just send v2.
> > 
> > I think that it is not proper development sequence.
> > I have spent many times to review your patches
> > and also I'll review your patches. You have to take care
> > the reply of reviewer and and keep the basic rule
> > of mailing contribution for discussion.
> > 
> > On 19. 9. 19. 오후 11:22, Artur Świgoń wrote:
> > > The following patchset adds interconnect[1][2] framework support to the
> > > exynos-bus devfreq driver. Extending the devfreq driver with interconnect
> > > capabilities started as a response to the issue referenced in [3]. The
> > > patches can be subdivided into four logical groups:
> > > 
> > > (a) Refactoring the existing devfreq driver in order to improve readability
> > > and accommodate for adding new code (patches 01--04/11).
> > > 
> > > (b) Tweaking the interconnect framework to support the exynos-bus use case
> > > (patches 05--07/11). Exporting of_icc_get_from_provider() allows us to
> > > avoid hardcoding every single graph edge in the DT or driver source, and
> > > relaxing the requirement contained in that function removes the need to
> > > provide dummy node IDs in the DT. Adjusting the logic in
> > > apply_constraints() (drivers/interconnect/core.c) accounts for the fact
> > > that every bus is a separate entity and therefore a separate interconnect
> > > provider, albeit constituting a part of a larger hierarchy.
> > > 
> > > (c) Implementing interconnect providers in the exynos-bus devfreq driver
> > > and adding required DT properties for one selected platform, namely
> > > Exynos4412 (patches 08--09/11). Due to the fact that this aims to be a
> > > generic driver for various Exynos SoCs, node IDs are generated dynamically
> > > rather than hardcoded. This has been determined to be a simpler approach,
> > > but depends on changes described in (b).
> > > 
> > > (d) Implementing a sample interconnect consumer for exynos-mixer targeted
> > > at the issue referenced in [3], again with DT info only for Exynos4412
> > > (patches 10--11/11).
> > > 
> > > Integration of devfreq and interconnect functionalities is achieved by
> > > using dev_pm_qos_*() API[5]. All new code works equally well when
> > > CONFIG_INTERCONNECT is 'n' (as in exynos_defconfig) in which case all
> > > interconnect API functions are no-ops.
> > > 
> > > This patchset depends on [5].
> > > 
> > > --- Changes since v1 [6]:
> > > * Rebase on [4] (coupled regulators).
> > > * Rebase on [5] (dev_pm_qos for devfreq).
> > > * Use dev_pm_qos_*() API[5] instead of overriding frequency in
> > >   exynos_bus_target().
> > > * Use IDR for node ID allocation.
> > > * Avoid goto in functions extracted in patches 01 & 02 (cf. patch 04).
> > > * Reverse order of multiplication and division in
> > >   mixer_set_memory_bandwidth() (patch 11) to avoid integer overflow.
> > > 
> > > ---
> > > Artur Świgoń
> > > Samsung R&D Institute Poland
> > > Samsung Electronics
> > > 
> > > ---
> > > References:
> > > [1] Documentation/interconnect/interconnect.rst
> > > [2] Documentation/devicetree/bindings/interconnect/interconnect.txt
> > > [3] https://patchwork.kernel.org/patch/10861757/ (original issue)
> > > [4] https://patchwork.kernel.org/cover/11083663/ (coupled regulators; merged)
> > > [5] https://patchwork.kernel.org/cover/11149497/ (dev_pm_qos for devfreq)
> > > [6] https://patchwork.kernel.org/cover/11054417/ (v1 of this RFC)
> > > 
> > > Artur Świgoń (10):
> > >   devfreq: exynos-bus: Extract exynos_bus_profile_init()
> > >   devfreq: exynos-bus: Extract exynos_bus_profile_init_passive()
> > >   devfreq: exynos-bus: Change goto-based logic to if-else logic
> > >   devfreq: exynos-bus: Clean up code
> > >   interconnect: Export of_icc_get_from_provider()
> > >   interconnect: Relax requirement in of_icc_get_from_provider()
> > >   interconnect: Relax condition in apply_constraints()
> > >   arm: dts: exynos: Add parents and #interconnect-cells to Exynos4412
> > >   devfreq: exynos-bus: Add interconnect functionality to exynos-bus
> > >   arm: dts: exynos: Add interconnects to Exynos4412 mixer
> > > 
> > > Marek Szyprowski (1):
> > >   drm: exynos: mixer: Add interconnect support
> > > 
> > >  .../boot/dts/exynos4412-odroid-common.dtsi    |   1 +
> > >  arch/arm/boot/dts/exynos4412.dtsi             |  10 +
> > >  drivers/devfreq/exynos-bus.c                  | 319 +++++++++++++-----
> > >  drivers/gpu/drm/exynos/exynos_mixer.c         |  71 +++-
> > >  drivers/interconnect/core.c                   |  12 +-
> > >  include/linux/interconnect-provider.h         |   6 +
> > >  6 files changed, 327 insertions(+), 92 deletions(-)
> > > 
> > 
> > 
> 
> 
-- 
Artur Świgoń
Samsung R&D Institute Poland
Samsung Electronics



^ permalink raw reply	[flat|nested] 41+ messages in thread

* Re: [RFC PATCH v2 00/11] Simple QoS for exynos-bus driver using interconnect
  2019-09-25  5:47       ` Artur Świgoń
@ 2019-09-25  6:12         ` Chanwoo Choi
  2019-09-25  6:37           ` Artur Świgoń
  0 siblings, 1 reply; 41+ messages in thread
From: Chanwoo Choi @ 2019-09-25  6:12 UTC (permalink / raw)
  To: Artur Świgoń,
	devicetree, linux-arm-kernel, linux-samsung-soc, linux-kernel,
	linux-pm, dri-devel
  Cc: myungjoo.ham, inki.dae, sw0312.kim, georgi.djakov,
	leonard.crestez, m.szyprowski, b.zolnierkie, krzk,
	cpgs (cpgs@samsung.com)

Hi,

On 19. 9. 25. 오후 2:47, Artur Świgoń wrote:
> Hi,
> 
> On Fri, 2019-09-20 at 11:14 +0900, Chanwoo Choi wrote:
>> Hi Artur,
>>
>> I tried to just build this patch on mainline kernel or linux-next.
>> But, when I applied them, merge conflict happens. You didn't develop
>> them on latest version. Please rebase them based on latest mainline kernel.
> 
> I developed on top of next-20190918 on which I applied
> https://patchwork.kernel.org/cover/11149497/ as I mentioned in the cover
> letter. The dev_pm_qos patches and my RFC have just cleanly rebased together on
> top of next-20190920. Could you check if you have the dev_pm_qos patches (v5,
> the version number is missing in this one; link above) and if so, where does the
> conflict appear?

I faced on the merge conflict of drivers/devfreq/exynos-bus.c.
I think that It is not related to to dev_pm_qos patch.

Maybe, Kamil's patches[1] changed the many things of exynos-bus.c
If your test branch doesn't contain following patches, 
you need to rebase your patches based on latest mainline kernel 
from Linus Torvald.
[1] https://patchwork.kernel.org/cover/11083663/
- [RESEND PATCH v5 0/4] add coupled regulators for Exynos5422/5800

Today, I tried to apply these patch again based on latest mainline kernel.
The merge conflict happen still.

- merge conflict log
Applying: devfreq: exynos-bus: Extract exynos_bus_profile_init()
error: patch failed: drivers/devfreq/exynos-bus.c:334
error: drivers/devfreq/exynos-bus.c: patch does not apply
Patch failed at 0001 devfreq: exynos-bus: Extract exynos_bus_profile_init()


> 
>> On 19. 9. 20. 오전 10:07, Chanwoo Choi wrote:
>>> Hi Artur,
>>>
>>> On v1, I mentioned that we need to discuss how to change
>>> the v2 for this. But, I have not received any reply from you on v1.
>>> And, without your reply from v1, you just send v2.
>>>
>>> I think that it is not proper development sequence.
>>> I have spent many times to review your patches
>>> and also I'll review your patches. You have to take care
>>> the reply of reviewer and and keep the basic rule
>>> of mailing contribution for discussion.
>>>
>>> On 19. 9. 19. 오후 11:22, Artur Świgoń wrote:
>>>> The following patchset adds interconnect[1][2] framework support to the
>>>> exynos-bus devfreq driver. Extending the devfreq driver with interconnect
>>>> capabilities started as a response to the issue referenced in [3]. The
>>>> patches can be subdivided into four logical groups:
>>>>
>>>> (a) Refactoring the existing devfreq driver in order to improve readability
>>>> and accommodate for adding new code (patches 01--04/11).
>>>>
>>>> (b) Tweaking the interconnect framework to support the exynos-bus use case
>>>> (patches 05--07/11). Exporting of_icc_get_from_provider() allows us to
>>>> avoid hardcoding every single graph edge in the DT or driver source, and
>>>> relaxing the requirement contained in that function removes the need to
>>>> provide dummy node IDs in the DT. Adjusting the logic in
>>>> apply_constraints() (drivers/interconnect/core.c) accounts for the fact
>>>> that every bus is a separate entity and therefore a separate interconnect
>>>> provider, albeit constituting a part of a larger hierarchy.
>>>>
>>>> (c) Implementing interconnect providers in the exynos-bus devfreq driver
>>>> and adding required DT properties for one selected platform, namely
>>>> Exynos4412 (patches 08--09/11). Due to the fact that this aims to be a
>>>> generic driver for various Exynos SoCs, node IDs are generated dynamically
>>>> rather than hardcoded. This has been determined to be a simpler approach,
>>>> but depends on changes described in (b).
>>>>
>>>> (d) Implementing a sample interconnect consumer for exynos-mixer targeted
>>>> at the issue referenced in [3], again with DT info only for Exynos4412
>>>> (patches 10--11/11).
>>>>
>>>> Integration of devfreq and interconnect functionalities is achieved by
>>>> using dev_pm_qos_*() API[5]. All new code works equally well when
>>>> CONFIG_INTERCONNECT is 'n' (as in exynos_defconfig) in which case all
>>>> interconnect API functions are no-ops.
>>>>
>>>> This patchset depends on [5].
>>>>
>>>> --- Changes since v1 [6]:
>>>> * Rebase on [4] (coupled regulators).
>>>> * Rebase on [5] (dev_pm_qos for devfreq).
>>>> * Use dev_pm_qos_*() API[5] instead of overriding frequency in
>>>>   exynos_bus_target().
>>>> * Use IDR for node ID allocation.
>>>> * Avoid goto in functions extracted in patches 01 & 02 (cf. patch 04).
>>>> * Reverse order of multiplication and division in
>>>>   mixer_set_memory_bandwidth() (patch 11) to avoid integer overflow.
>>>>
>>>> ---
>>>> Artur Świgoń
>>>> Samsung R&D Institute Poland
>>>> Samsung Electronics
>>>>
>>>> ---
>>>> References:
>>>> [1] Documentation/interconnect/interconnect.rst
>>>> [2] Documentation/devicetree/bindings/interconnect/interconnect.txt
>>>> [3] https://patchwork.kernel.org/patch/10861757/ (original issue)
>>>> [4] https://patchwork.kernel.org/cover/11083663/ (coupled regulators; merged)
>>>> [5] https://patchwork.kernel.org/cover/11149497/ (dev_pm_qos for devfreq)
>>>> [6] https://patchwork.kernel.org/cover/11054417/ (v1 of this RFC)
>>>>
>>>> Artur Świgoń (10):
>>>>   devfreq: exynos-bus: Extract exynos_bus_profile_init()
>>>>   devfreq: exynos-bus: Extract exynos_bus_profile_init_passive()
>>>>   devfreq: exynos-bus: Change goto-based logic to if-else logic
>>>>   devfreq: exynos-bus: Clean up code
>>>>   interconnect: Export of_icc_get_from_provider()
>>>>   interconnect: Relax requirement in of_icc_get_from_provider()
>>>>   interconnect: Relax condition in apply_constraints()
>>>>   arm: dts: exynos: Add parents and #interconnect-cells to Exynos4412
>>>>   devfreq: exynos-bus: Add interconnect functionality to exynos-bus
>>>>   arm: dts: exynos: Add interconnects to Exynos4412 mixer
>>>>
>>>> Marek Szyprowski (1):
>>>>   drm: exynos: mixer: Add interconnect support
>>>>
>>>>  .../boot/dts/exynos4412-odroid-common.dtsi    |   1 +
>>>>  arch/arm/boot/dts/exynos4412.dtsi             |  10 +
>>>>  drivers/devfreq/exynos-bus.c                  | 319 +++++++++++++-----
>>>>  drivers/gpu/drm/exynos/exynos_mixer.c         |  71 +++-
>>>>  drivers/interconnect/core.c                   |  12 +-
>>>>  include/linux/interconnect-provider.h         |   6 +
>>>>  6 files changed, 327 insertions(+), 92 deletions(-)
>>>>
>>>
>>>
>>
>>


-- 
Best Regards,
Chanwoo Choi
Samsung Electronics

^ permalink raw reply	[flat|nested] 41+ messages in thread

* Re: [RFC PATCH v2 01/11] devfreq: exynos-bus: Extract exynos_bus_profile_init()
  2019-09-25  5:44         ` Artur Świgoń
@ 2019-09-25  6:37           ` Chanwoo Choi
  2019-09-25  6:41             ` Artur Świgoń
  0 siblings, 1 reply; 41+ messages in thread
From: Chanwoo Choi @ 2019-09-25  6:37 UTC (permalink / raw)
  To: Artur Świgoń,
	devicetree, linux-arm-kernel, linux-samsung-soc, linux-kernel,
	linux-pm, dri-devel
  Cc: myungjoo.ham, inki.dae, sw0312.kim, georgi.djakov,
	leonard.crestez, m.szyprowski, b.zolnierkie, krzk

Hi,

On 19. 9. 25. 오후 2:44, Artur Świgoń wrote:
> Hi,
> 
> On Fri, 2019-09-20 at 11:15 +0900, Chanwoo Choi wrote:
>> Hi,
>>
>> As I already replied on v1, patch1/2/3 clean-up code
>> for readability without any behavior changes. 
>>
>> I think that you better to merge patch1/2/3 to one patch.
> 
> Yes, when writing the cover letter I think I forgot to explain why I decided not
> to merge these patches. Basically, none of the diff algorithms available in git
> (I've got v2.17.1) is able to produce a readable patch with these changes
> combined together into a single patch (functions are intermixed together in the
> output, git thinks that 'exynos_bus_probe' is a new function).

After merged three patches, as you commented, looks like that 'exynos_bus_probe'
is new function. Your patch style(three patches) is better than one merged patch.
Keep your original patches. Thanks.

> 
> Please take a look at the diff at the bottom of this message to see how patches
> 01..03 look when combined. If such patch looks acceptable to you, I can merge.
> 
>> On 19. 9. 19. 오후 11:22, Artur Świgoń wrote:
>>> From: Artur Świgoń <a.swigon@partner.samsung.com>
>>>
>>> This patch adds a new static function, exynos_bus_profile_init(), extracted
>>> from exynos_bus_probe().
>>>
>>> Signed-off-by: Artur Świgoń <a.swigon@partner.samsung.com>
>>> ---
>>>  drivers/devfreq/exynos-bus.c | 92 +++++++++++++++++++++---------------
>>>  1 file changed, 53 insertions(+), 39 deletions(-)
>>>
>>> diff --git a/drivers/devfreq/exynos-bus.c b/drivers/devfreq/exynos-bus.c
>>> index 29f422469960..78f38b7fb596 100644
>>> --- a/drivers/devfreq/exynos-bus.c
>>> +++ b/drivers/devfreq/exynos-bus.c
>>> @@ -287,12 +287,62 @@ static int exynos_bus_parse_of(struct device_node *np,
>>>  	return ret;
>>>  }
>>>  
>>> +static int exynos_bus_profile_init(struct exynos_bus *bus,
>>> +				   struct devfreq_dev_profile *profile)
>>> +{
>>> +	struct device *dev = bus->dev;
>>> +	struct devfreq_simple_ondemand_data *ondemand_data;
>>> +	int ret;
>>> +
>>> +	/* Initialize the struct profile and governor data for parent device */
>>> +	profile->polling_ms = 50;
>>> +	profile->target = exynos_bus_target;
>>> +	profile->get_dev_status = exynos_bus_get_dev_status;
>>> +	profile->exit = exynos_bus_exit;
>>> +
>>> +	ondemand_data = devm_kzalloc(dev, sizeof(*ondemand_data), GFP_KERNEL);
>>> +	if (!ondemand_data) {
>>> +		ret = -ENOMEM;
>>> +		goto err;
>>> +	}
>>> +	ondemand_data->upthreshold = 40;
>>> +	ondemand_data->downdifferential = 5;
>>> +
>>> +	/* Add devfreq device to monitor and handle the exynos bus */
>>> +	bus->devfreq = devm_devfreq_add_device(dev, profile,
>>> +						DEVFREQ_GOV_SIMPLE_ONDEMAND,
>>> +						ondemand_data);
>>> +	if (IS_ERR(bus->devfreq)) {
>>> +		dev_err(dev, "failed to add devfreq device\n");
>>> +		ret = PTR_ERR(bus->devfreq);
>>> +		goto err;
>>> +	}
>>> +
>>> +	/*
>>> +	 * Enable devfreq-event to get raw data which is used to determine
>>> +	 * current bus load.
>>> +	 */
>>> +	ret = exynos_bus_enable_edev(bus);
>>> +	if (ret < 0) {
>>> +		dev_err(dev, "failed to enable devfreq-event devices\n");
>>> +		goto err;
>>> +	}
>>> +
>>> +	ret = exynos_bus_set_event(bus);
>>> +	if (ret < 0) {
>>> +		dev_err(dev, "failed to set event to devfreq-event devices\n");
>>> +		goto err;
>>> +	}
>>> +
>>> +err:
>>> +	return ret;
>>> +}
>>> +
>>>  static int exynos_bus_probe(struct platform_device *pdev)
>>>  {
>>>  	struct device *dev = &pdev->dev;
>>>  	struct device_node *np = dev->of_node, *node;
>>>  	struct devfreq_dev_profile *profile;
>>> -	struct devfreq_simple_ondemand_data *ondemand_data;
>>>  	struct devfreq_passive_data *passive_data;
>>>  	struct devfreq *parent_devfreq;
>>>  	struct exynos_bus *bus;
>>> @@ -334,45 +384,9 @@ static int exynos_bus_probe(struct platform_device *pdev)
>>>  	if (passive)
>>>  		goto passive;
>>>  
>>> -	/* Initialize the struct profile and governor data for parent device */
>>> -	profile->polling_ms = 50;
>>> -	profile->target = exynos_bus_target;
>>> -	profile->get_dev_status = exynos_bus_get_dev_status;
>>> -	profile->exit = exynos_bus_exit;
>>> -
>>> -	ondemand_data = devm_kzalloc(dev, sizeof(*ondemand_data), GFP_KERNEL);
>>> -	if (!ondemand_data) {
>>> -		ret = -ENOMEM;
>>> +	ret = exynos_bus_profile_init(bus, profile);
>>> +	if (ret < 0)
>>>  		goto err;
>>> -	}
>>> -	ondemand_data->upthreshold = 40;
>>> -	ondemand_data->downdifferential = 5;
>>> -
>>> -	/* Add devfreq device to monitor and handle the exynos bus */
>>> -	bus->devfreq = devm_devfreq_add_device(dev, profile,
>>> -						DEVFREQ_GOV_SIMPLE_ONDEMAND,
>>> -						ondemand_data);
>>> -	if (IS_ERR(bus->devfreq)) {
>>> -		dev_err(dev, "failed to add devfreq device\n");
>>> -		ret = PTR_ERR(bus->devfreq);
>>> -		goto err;
>>> -	}
>>> -
>>> -	/*
>>> -	 * Enable devfreq-event to get raw data which is used to determine
>>> -	 * current bus load.
>>> -	 */
>>> -	ret = exynos_bus_enable_edev(bus);
>>> -	if (ret < 0) {
>>> -		dev_err(dev, "failed to enable devfreq-event devices\n");
>>> -		goto err;
>>> -	}
>>> -
>>> -	ret = exynos_bus_set_event(bus);
>>> -	if (ret < 0) {
>>> -		dev_err(dev, "failed to set event to devfreq-event devices\n");
>>> -		goto err;
>>> -	}
>>>  
>>>  	goto out;
>>>  passive:
> 
> commit cacf8e4ea0e111908d11779977c81e29d6418801
> Author: Artur Świgoń <a.swigon@partner.samsung.com>
> Date:   Tue Aug 27 13:17:28 2019 +0200
> 
>     tmp: merge patches 01-03
>     
>     Signed-off-by: Artur Świgoń <a.swigon@partner.samsung.com>
> 
> diff --git a/drivers/devfreq/exynos-bus.c b/drivers/devfreq/exynos-bus.c
> index 29f422469960..60ad4319fd80 100644
> --- a/drivers/devfreq/exynos-bus.c
> +++ b/drivers/devfreq/exynos-bus.c
> @@ -287,52 +287,12 @@ static int exynos_bus_parse_of(struct device_node *np,
>  	return ret;
>  }
>  
> -static int exynos_bus_probe(struct platform_device *pdev)
> +static int exynos_bus_profile_init(struct exynos_bus *bus,
> +				   struct devfreq_dev_profile *profile)
>  {
> -	struct device *dev = &pdev->dev;
> -	struct device_node *np = dev->of_node, *node;
> -	struct devfreq_dev_profile *profile;
> +	struct device *dev = bus->dev;
>  	struct devfreq_simple_ondemand_data *ondemand_data;
> -	struct devfreq_passive_data *passive_data;
> -	struct devfreq *parent_devfreq;
> -	struct exynos_bus *bus;
> -	int ret, max_state;
> -	unsigned long min_freq, max_freq;
> -	bool passive = false;
> -
> -	if (!np) {
> -		dev_err(dev, "failed to find devicetree node\n");
> -		return -EINVAL;
> -	}
> -
> -	bus = devm_kzalloc(&pdev->dev, sizeof(*bus), GFP_KERNEL);
> -	if (!bus)
> -		return -ENOMEM;
> -	mutex_init(&bus->lock);
> -	bus->dev = &pdev->dev;
> -	platform_set_drvdata(pdev, bus);
> -
> -	profile = devm_kzalloc(dev, sizeof(*profile), GFP_KERNEL);
> -	if (!profile)
> -		return -ENOMEM;
> -
> -	node = of_parse_phandle(dev->of_node, "devfreq", 0);
> -	if (node) {
> -		of_node_put(node);
> -		passive = true;
> -	} else {
> -		ret = exynos_bus_parent_parse_of(np, bus);
> -		if (ret < 0)
> -			return ret;
> -	}
> -
> -	/* Parse the device-tree to get the resource information */
> -	ret = exynos_bus_parse_of(np, bus);
> -	if (ret < 0)
> -		goto err_reg;
> -
> -	if (passive)
> -		goto passive;
> +	int ret;
>  
>  	/* Initialize the struct profile and governor data for parent device */
>  	profile->polling_ms = 50;
> @@ -374,8 +334,18 @@ static int exynos_bus_probe(struct platform_device *pdev)
>  		goto err;
>  	}
>  
> -	goto out;
> -passive:
> +err:
> +	return ret;
> +}
> +
> +static int exynos_bus_profile_init_passive(struct exynos_bus *bus,
> +					   struct devfreq_dev_profile *profile)
> +{
> +	struct device *dev = bus->dev;
> +	struct devfreq_passive_data *passive_data;
> +	struct devfreq *parent_devfreq;
> +	int ret = 0;
> +
>  	/* Initialize the struct profile and governor data for passive device */
>  	profile->target = exynos_bus_target;
>  	profile->exit = exynos_bus_passive_exit;
> @@ -404,7 +374,59 @@ static int exynos_bus_probe(struct platform_device *pdev)
>  		goto err;
>  	}
>  
> -out:
> +err:
> +	return ret;
> +}
> +
> +static int exynos_bus_probe(struct platform_device *pdev)
> +{
> +	struct device *dev = &pdev->dev;
> +	struct device_node *np = dev->of_node, *node;
> +	struct devfreq_dev_profile *profile;
> +	struct exynos_bus *bus;
> +	int ret, max_state;
> +	unsigned long min_freq, max_freq;
> +	bool passive = false;
> +
> +	if (!np) {
> +		dev_err(dev, "failed to find devicetree node\n");
> +		return -EINVAL;
> +	}
> +
> +	bus = devm_kzalloc(&pdev->dev, sizeof(*bus), GFP_KERNEL);
> +	if (!bus)
> +		return -ENOMEM;
> +	mutex_init(&bus->lock);
> +	bus->dev = &pdev->dev;
> +	platform_set_drvdata(pdev, bus);
> +
> +	profile = devm_kzalloc(dev, sizeof(*profile), GFP_KERNEL);
> +	if (!profile)
> +		return -ENOMEM;
> +
> +	node = of_parse_phandle(dev->of_node, "devfreq", 0);
> +	if (node) {
> +		of_node_put(node);
> +		passive = true;
> +	} else {
> +		ret = exynos_bus_parent_parse_of(np, bus);
> +		if (ret < 0)
> +			return ret;
> +	}
> +
> +	/* Parse the device-tree to get the resource information */
> +	ret = exynos_bus_parse_of(np, bus);
> +	if (ret < 0)
> +		goto err_reg;
> +
> +	if (passive)
> +		ret = exynos_bus_profile_init_passive(bus, profile);
> +	else
> +		ret = exynos_bus_profile_init(bus, profile);
> +
> +	if (ret < 0)
> +		goto err;
> +
>  	max_state = bus->devfreq->profile->max_state;
>  	min_freq = (bus->devfreq->profile->freq_table[0] / 1000);
>  	max_freq = (bus->devfreq->profile->freq_table[max_state - 1] / 1000);
> 
> 
> 
> 


-- 
Best Regards,
Chanwoo Choi
Samsung Electronics

^ permalink raw reply	[flat|nested] 41+ messages in thread

* Re: [RFC PATCH v2 00/11] Simple QoS for exynos-bus driver using interconnect
  2019-09-25  6:12         ` Chanwoo Choi
@ 2019-09-25  6:37           ` Artur Świgoń
  2019-09-25  6:48             ` Chanwoo Choi
  0 siblings, 1 reply; 41+ messages in thread
From: Artur Świgoń @ 2019-09-25  6:37 UTC (permalink / raw)
  To: Chanwoo Choi, devicetree, linux-arm-kernel, linux-samsung-soc,
	linux-kernel, linux-pm, dri-devel
  Cc: a.swigon, myungjoo.ham, inki.dae, sw0312.kim, georgi.djakov,
	leonard.crestez, m.szyprowski, b.zolnierkie, krzk,
	cpgs (cpgs@samsung.com),
	k.konieczny

On Wed, 2019-09-25 at 15:12 +0900, Chanwoo Choi wrote:
> Hi,
> 
> On 19. 9. 25. 오후 2:47, Artur Świgoń wrote:
> > Hi,
> > 
> > On Fri, 2019-09-20 at 11:14 +0900, Chanwoo Choi wrote:
> > > Hi Artur,
> > > 
> > > I tried to just build this patch on mainline kernel or linux-next.
> > > But, when I applied them, merge conflict happens. You didn't develop
> > > them on latest version. Please rebase them based on latest mainline kernel.
> > 
> > I developed on top of next-20190918 on which I applied
> > https://patchwork.kernel.org/cover/11149497/ as I mentioned in the cover
> > letter. The dev_pm_qos patches and my RFC have just cleanly rebased together on
> > top of next-20190920. Could you check if you have the dev_pm_qos patches (v5,
> > the version number is missing in this one; link above) and if so, where does the
> > conflict appear?
> 
> I faced on the merge conflict of drivers/devfreq/exynos-bus.c.
> I think that It is not related to to dev_pm_qos patch.

I think that it is actually related to the specific version of dev_pm_qos (v5) that
I used because patch 08/08 of dev_pm_qos series modifies exynos_bus_probe() in
drivers/devfreq/exynos-bus.c (https://patchwork.kernel.org/patch/11149507/).

I will rebase the next RFC (v3) on latest dev_pm_qos patches from Leonard and the
latest Linux-next kernel.

> Maybe, Kamil's patches[1] changed the many things of exynos-bus.c
> If your test branch doesn't contain following patches, 
> you need to rebase your patches based on latest mainline kernel 
> from Linus Torvald.
> [1] https://patchwork.kernel.org/cover/11083663/
> - [RESEND PATCH v5 0/4] add coupled regulators for Exynos5422/5800

Yes, requiring Kamil's patches is one of the changes in this RFC (v2), since they
are already merged.

> Today, I tried to apply these patch again based on latest mainline kernel.
> The merge conflict happen still.
> 
> - merge conflict log
> Applying: devfreq: exynos-bus: Extract exynos_bus_profile_init()
> error: patch failed: drivers/devfreq/exynos-bus.c:334
> error: drivers/devfreq/exynos-bus.c: patch does not apply
> Patch failed at 0001 devfreq: exynos-bus: Extract exynos_bus_profile_init()
> 
> 
> > 
> > > On 19. 9. 20. 오전 10:07, Chanwoo Choi wrote:
> > > > Hi Artur,
> > > > 
> > > > On v1, I mentioned that we need to discuss how to change
> > > > the v2 for this. But, I have not received any reply from you on v1.
> > > > And, without your reply from v1, you just send v2.
> > > > 
> > > > I think that it is not proper development sequence.
> > > > I have spent many times to review your patches
> > > > and also I'll review your patches. You have to take care
> > > > the reply of reviewer and and keep the basic rule
> > > > of mailing contribution for discussion.
> > > > 
> > > > On 19. 9. 19. 오후 11:22, Artur Świgoń wrote:
> > > > > The following patchset adds interconnect[1][2] framework support to the
> > > > > exynos-bus devfreq driver. Extending the devfreq driver with interconnect
> > > > > capabilities started as a response to the issue referenced in [3]. The
> > > > > patches can be subdivided into four logical groups:
> > > > > 
> > > > > (a) Refactoring the existing devfreq driver in order to improve readability
> > > > > and accommodate for adding new code (patches 01--04/11).
> > > > > 
> > > > > (b) Tweaking the interconnect framework to support the exynos-bus use case
> > > > > (patches 05--07/11). Exporting of_icc_get_from_provider() allows us to
> > > > > avoid hardcoding every single graph edge in the DT or driver source, and
> > > > > relaxing the requirement contained in that function removes the need to
> > > > > provide dummy node IDs in the DT. Adjusting the logic in
> > > > > apply_constraints() (drivers/interconnect/core.c) accounts for the fact
> > > > > that every bus is a separate entity and therefore a separate interconnect
> > > > > provider, albeit constituting a part of a larger hierarchy.
> > > > > 
> > > > > (c) Implementing interconnect providers in the exynos-bus devfreq driver
> > > > > and adding required DT properties for one selected platform, namely
> > > > > Exynos4412 (patches 08--09/11). Due to the fact that this aims to be a
> > > > > generic driver for various Exynos SoCs, node IDs are generated dynamically
> > > > > rather than hardcoded. This has been determined to be a simpler approach,
> > > > > but depends on changes described in (b).
> > > > > 
> > > > > (d) Implementing a sample interconnect consumer for exynos-mixer targeted
> > > > > at the issue referenced in [3], again with DT info only for Exynos4412
> > > > > (patches 10--11/11).
> > > > > 
> > > > > Integration of devfreq and interconnect functionalities is achieved by
> > > > > using dev_pm_qos_*() API[5]. All new code works equally well when
> > > > > CONFIG_INTERCONNECT is 'n' (as in exynos_defconfig) in which case all
> > > > > interconnect API functions are no-ops.
> > > > > 
> > > > > This patchset depends on [5].
> > > > > 
> > > > > --- Changes since v1 [6]:
> > > > > * Rebase on [4] (coupled regulators).
> > > > > * Rebase on [5] (dev_pm_qos for devfreq).
> > > > > * Use dev_pm_qos_*() API[5] instead of overriding frequency in
> > > > >   exynos_bus_target().
> > > > > * Use IDR for node ID allocation.
> > > > > * Avoid goto in functions extracted in patches 01 & 02 (cf. patch 04).
> > > > > * Reverse order of multiplication and division in
> > > > >   mixer_set_memory_bandwidth() (patch 11) to avoid integer overflow.
> > > > > 
> > > > > ---
> > > > > Artur Świgoń
> > > > > Samsung R&D Institute Poland
> > > > > Samsung Electronics
> > > > > 
> > > > > ---
> > > > > References:
> > > > > [1] Documentation/interconnect/interconnect.rst
> > > > > [2] Documentation/devicetree/bindings/interconnect/interconnect.txt
> > > > > [3] https://patchwork.kernel.org/patch/10861757/ (original issue)
> > > > > [4] https://patchwork.kernel.org/cover/11083663/ (coupled regulators; merged)
> > > > > [5] https://patchwork.kernel.org/cover/11149497/ (dev_pm_qos for devfreq)
> > > > > [6] https://patchwork.kernel.org/cover/11054417/ (v1 of this RFC)
> > > > > 
> > > > > Artur Świgoń (10):
> > > > >   devfreq: exynos-bus: Extract exynos_bus_profile_init()
> > > > >   devfreq: exynos-bus: Extract exynos_bus_profile_init_passive()
> > > > >   devfreq: exynos-bus: Change goto-based logic to if-else logic
> > > > >   devfreq: exynos-bus: Clean up code
> > > > >   interconnect: Export of_icc_get_from_provider()
> > > > >   interconnect: Relax requirement in of_icc_get_from_provider()
> > > > >   interconnect: Relax condition in apply_constraints()
> > > > >   arm: dts: exynos: Add parents and #interconnect-cells to Exynos4412
> > > > >   devfreq: exynos-bus: Add interconnect functionality to exynos-bus
> > > > >   arm: dts: exynos: Add interconnects to Exynos4412 mixer
> > > > > 
> > > > > Marek Szyprowski (1):
> > > > >   drm: exynos: mixer: Add interconnect support
> > > > > 
> > > > >  .../boot/dts/exynos4412-odroid-common.dtsi    |   1 +
> > > > >  arch/arm/boot/dts/exynos4412.dtsi             |  10 +
> > > > >  drivers/devfreq/exynos-bus.c                  | 319 +++++++++++++-----
> > > > >  drivers/gpu/drm/exynos/exynos_mixer.c         |  71 +++-
> > > > >  drivers/interconnect/core.c                   |  12 +-
> > > > >  include/linux/interconnect-provider.h         |   6 +
> > > > >  6 files changed, 327 insertions(+), 92 deletions(-)
> > > > > 



^ permalink raw reply	[flat|nested] 41+ messages in thread

* Re: [RFC PATCH v2 01/11] devfreq: exynos-bus: Extract exynos_bus_profile_init()
  2019-09-25  6:37           ` Chanwoo Choi
@ 2019-09-25  6:41             ` Artur Świgoń
  0 siblings, 0 replies; 41+ messages in thread
From: Artur Świgoń @ 2019-09-25  6:41 UTC (permalink / raw)
  To: Chanwoo Choi, devicetree, linux-arm-kernel, linux-samsung-soc,
	linux-kernel, linux-pm, dri-devel
  Cc: a.swigon, myungjoo.ham, inki.dae, sw0312.kim, georgi.djakov,
	leonard.crestez, m.szyprowski, b.zolnierkie, krzk

On Wed, 2019-09-25 at 15:37 +0900, Chanwoo Choi wrote:
> Hi,
> 
> On 19. 9. 25. 오후 2:44, Artur Świgoń wrote:
> > Hi,
> > 
> > On Fri, 2019-09-20 at 11:15 +0900, Chanwoo Choi wrote:
> > > Hi,
> > > 
> > > As I already replied on v1, patch1/2/3 clean-up code
> > > for readability without any behavior changes. 
> > > 
> > > I think that you better to merge patch1/2/3 to one patch.
> > 
> > Yes, when writing the cover letter I think I forgot to explain why I decided not
> > to merge these patches. Basically, none of the diff algorithms available in git
> > (I've got v2.17.1) is able to produce a readable patch with these changes
> > combined together into a single patch (functions are intermixed together in the
> > output, git thinks that 'exynos_bus_probe' is a new function).
> 
> After merged three patches, as you commented, looks like that 'exynos_bus_probe'
> is new function. Your patch style(three patches) is better than one merged patch.
> Keep your original patches. Thanks.

I know that having three separate patches is suboptimal, but they are more readable
this way. I am glad you agree. I will keep them separate. Thank you for your
comments.

> > 
> > Please take a look at the diff at the bottom of this message to see how patches
> > 01..03 look when combined. If such patch looks acceptable to you, I can merge.
> > 
> > > On 19. 9. 19. 오후 11:22, Artur Świgoń wrote:
> > > > From: Artur Świgoń <a.swigon@partner.samsung.com>
> > > > 
> > > > This patch adds a new static function, exynos_bus_profile_init(), extracted
> > > > from exynos_bus_probe().
> > > > 
> > > > Signed-off-by: Artur Świgoń <a.swigon@partner.samsung.com>
> > > > ---
> > > >  drivers/devfreq/exynos-bus.c | 92 +++++++++++++++++++++---------------
> > > >  1 file changed, 53 insertions(+), 39 deletions(-)
> > > > 
> > > > diff --git a/drivers/devfreq/exynos-bus.c b/drivers/devfreq/exynos-bus.c
> > > > index 29f422469960..78f38b7fb596 100644
> > > > --- a/drivers/devfreq/exynos-bus.c
> > > > +++ b/drivers/devfreq/exynos-bus.c
> > > > @@ -287,12 +287,62 @@ static int exynos_bus_parse_of(struct device_node *np,
> > > >  	return ret;
> > > >  }
> > > >  
> > > > +static int exynos_bus_profile_init(struct exynos_bus *bus,
> > > > +				   struct devfreq_dev_profile *profile)
> > > > +{
> > > > +	struct device *dev = bus->dev;
> > > > +	struct devfreq_simple_ondemand_data *ondemand_data;
> > > > +	int ret;
> > > > +
> > > > +	/* Initialize the struct profile and governor data for parent device */
> > > > +	profile->polling_ms = 50;
> > > > +	profile->target = exynos_bus_target;
> > > > +	profile->get_dev_status = exynos_bus_get_dev_status;
> > > > +	profile->exit = exynos_bus_exit;
> > > > +
> > > > +	ondemand_data = devm_kzalloc(dev, sizeof(*ondemand_data), GFP_KERNEL);
> > > > +	if (!ondemand_data) {
> > > > +		ret = -ENOMEM;
> > > > +		goto err;
> > > > +	}
> > > > +	ondemand_data->upthreshold = 40;
> > > > +	ondemand_data->downdifferential = 5;
> > > > +
> > > > +	/* Add devfreq device to monitor and handle the exynos bus */
> > > > +	bus->devfreq = devm_devfreq_add_device(dev, profile,
> > > > +						DEVFREQ_GOV_SIMPLE_ONDEMAND,
> > > > +						ondemand_data);
> > > > +	if (IS_ERR(bus->devfreq)) {
> > > > +		dev_err(dev, "failed to add devfreq device\n");
> > > > +		ret = PTR_ERR(bus->devfreq);
> > > > +		goto err;
> > > > +	}
> > > > +
> > > > +	/*
> > > > +	 * Enable devfreq-event to get raw data which is used to determine
> > > > +	 * current bus load.
> > > > +	 */
> > > > +	ret = exynos_bus_enable_edev(bus);
> > > > +	if (ret < 0) {
> > > > +		dev_err(dev, "failed to enable devfreq-event devices\n");
> > > > +		goto err;
> > > > +	}
> > > > +
> > > > +	ret = exynos_bus_set_event(bus);
> > > > +	if (ret < 0) {
> > > > +		dev_err(dev, "failed to set event to devfreq-event devices\n");
> > > > +		goto err;
> > > > +	}
> > > > +
> > > > +err:
> > > > +	return ret;
> > > > +}
> > > > +
> > > >  static int exynos_bus_probe(struct platform_device *pdev)
> > > >  {
> > > >  	struct device *dev = &pdev->dev;
> > > >  	struct device_node *np = dev->of_node, *node;
> > > >  	struct devfreq_dev_profile *profile;
> > > > -	struct devfreq_simple_ondemand_data *ondemand_data;
> > > >  	struct devfreq_passive_data *passive_data;
> > > >  	struct devfreq *parent_devfreq;
> > > >  	struct exynos_bus *bus;
> > > > @@ -334,45 +384,9 @@ static int exynos_bus_probe(struct platform_device *pdev)
> > > >  	if (passive)
> > > >  		goto passive;
> > > >  
> > > > -	/* Initialize the struct profile and governor data for parent device */
> > > > -	profile->polling_ms = 50;
> > > > -	profile->target = exynos_bus_target;
> > > > -	profile->get_dev_status = exynos_bus_get_dev_status;
> > > > -	profile->exit = exynos_bus_exit;
> > > > -
> > > > -	ondemand_data = devm_kzalloc(dev, sizeof(*ondemand_data), GFP_KERNEL);
> > > > -	if (!ondemand_data) {
> > > > -		ret = -ENOMEM;
> > > > +	ret = exynos_bus_profile_init(bus, profile);
> > > > +	if (ret < 0)
> > > >  		goto err;
> > > > -	}
> > > > -	ondemand_data->upthreshold = 40;
> > > > -	ondemand_data->downdifferential = 5;
> > > > -
> > > > -	/* Add devfreq device to monitor and handle the exynos bus */
> > > > -	bus->devfreq = devm_devfreq_add_device(dev, profile,
> > > > -						DEVFREQ_GOV_SIMPLE_ONDEMAND,
> > > > -						ondemand_data);
> > > > -	if (IS_ERR(bus->devfreq)) {
> > > > -		dev_err(dev, "failed to add devfreq device\n");
> > > > -		ret = PTR_ERR(bus->devfreq);
> > > > -		goto err;
> > > > -	}
> > > > -
> > > > -	/*
> > > > -	 * Enable devfreq-event to get raw data which is used to determine
> > > > -	 * current bus load.
> > > > -	 */
> > > > -	ret = exynos_bus_enable_edev(bus);
> > > > -	if (ret < 0) {
> > > > -		dev_err(dev, "failed to enable devfreq-event devices\n");
> > > > -		goto err;
> > > > -	}
> > > > -
> > > > -	ret = exynos_bus_set_event(bus);
> > > > -	if (ret < 0) {
> > > > -		dev_err(dev, "failed to set event to devfreq-event devices\n");
> > > > -		goto err;
> > > > -	}
> > > >  
> > > >  	goto out;
> > > >  passive:
> > 
> > commit cacf8e4ea0e111908d11779977c81e29d6418801
> > Author: Artur Świgoń <a.swigon@partner.samsung.com>
> > Date:   Tue Aug 27 13:17:28 2019 +0200
> > 
> >     tmp: merge patches 01-03
> >     
> >     Signed-off-by: Artur Świgoń <a.swigon@partner.samsung.com>
> > 
> > diff --git a/drivers/devfreq/exynos-bus.c b/drivers/devfreq/exynos-bus.c
> > index 29f422469960..60ad4319fd80 100644
> > --- a/drivers/devfreq/exynos-bus.c
> > +++ b/drivers/devfreq/exynos-bus.c
> > @@ -287,52 +287,12 @@ static int exynos_bus_parse_of(struct device_node *np,
> >  	return ret;
> >  }
> >  
> > -static int exynos_bus_probe(struct platform_device *pdev)
> > +static int exynos_bus_profile_init(struct exynos_bus *bus,
> > +				   struct devfreq_dev_profile *profile)
> >  {
> > -	struct device *dev = &pdev->dev;
> > -	struct device_node *np = dev->of_node, *node;
> > -	struct devfreq_dev_profile *profile;
> > +	struct device *dev = bus->dev;
> >  	struct devfreq_simple_ondemand_data *ondemand_data;
> > -	struct devfreq_passive_data *passive_data;
> > -	struct devfreq *parent_devfreq;
> > -	struct exynos_bus *bus;
> > -	int ret, max_state;
> > -	unsigned long min_freq, max_freq;
> > -	bool passive = false;
> > -
> > -	if (!np) {
> > -		dev_err(dev, "failed to find devicetree node\n");
> > -		return -EINVAL;
> > -	}
> > -
> > -	bus = devm_kzalloc(&pdev->dev, sizeof(*bus), GFP_KERNEL);
> > -	if (!bus)
> > -		return -ENOMEM;
> > -	mutex_init(&bus->lock);
> > -	bus->dev = &pdev->dev;
> > -	platform_set_drvdata(pdev, bus);
> > -
> > -	profile = devm_kzalloc(dev, sizeof(*profile), GFP_KERNEL);
> > -	if (!profile)
> > -		return -ENOMEM;
> > -
> > -	node = of_parse_phandle(dev->of_node, "devfreq", 0);
> > -	if (node) {
> > -		of_node_put(node);
> > -		passive = true;
> > -	} else {
> > -		ret = exynos_bus_parent_parse_of(np, bus);
> > -		if (ret < 0)
> > -			return ret;
> > -	}
> > -
> > -	/* Parse the device-tree to get the resource information */
> > -	ret = exynos_bus_parse_of(np, bus);
> > -	if (ret < 0)
> > -		goto err_reg;
> > -
> > -	if (passive)
> > -		goto passive;
> > +	int ret;
> >  
> >  	/* Initialize the struct profile and governor data for parent device */
> >  	profile->polling_ms = 50;
> > @@ -374,8 +334,18 @@ static int exynos_bus_probe(struct platform_device *pdev)
> >  		goto err;
> >  	}
> >  
> > -	goto out;
> > -passive:
> > +err:
> > +	return ret;
> > +}
> > +
> > +static int exynos_bus_profile_init_passive(struct exynos_bus *bus,
> > +					   struct devfreq_dev_profile *profile)
> > +{
> > +	struct device *dev = bus->dev;
> > +	struct devfreq_passive_data *passive_data;
> > +	struct devfreq *parent_devfreq;
> > +	int ret = 0;
> > +
> >  	/* Initialize the struct profile and governor data for passive device */
> >  	profile->target = exynos_bus_target;
> >  	profile->exit = exynos_bus_passive_exit;
> > @@ -404,7 +374,59 @@ static int exynos_bus_probe(struct platform_device *pdev)
> >  		goto err;
> >  	}
> >  
> > -out:
> > +err:
> > +	return ret;
> > +}
> > +
> > +static int exynos_bus_probe(struct platform_device *pdev)
> > +{
> > +	struct device *dev = &pdev->dev;
> > +	struct device_node *np = dev->of_node, *node;
> > +	struct devfreq_dev_profile *profile;
> > +	struct exynos_bus *bus;
> > +	int ret, max_state;
> > +	unsigned long min_freq, max_freq;
> > +	bool passive = false;
> > +
> > +	if (!np) {
> > +		dev_err(dev, "failed to find devicetree node\n");
> > +		return -EINVAL;
> > +	}
> > +
> > +	bus = devm_kzalloc(&pdev->dev, sizeof(*bus), GFP_KERNEL);
> > +	if (!bus)
> > +		return -ENOMEM;
> > +	mutex_init(&bus->lock);
> > +	bus->dev = &pdev->dev;
> > +	platform_set_drvdata(pdev, bus);
> > +
> > +	profile = devm_kzalloc(dev, sizeof(*profile), GFP_KERNEL);
> > +	if (!profile)
> > +		return -ENOMEM;
> > +
> > +	node = of_parse_phandle(dev->of_node, "devfreq", 0);
> > +	if (node) {
> > +		of_node_put(node);
> > +		passive = true;
> > +	} else {
> > +		ret = exynos_bus_parent_parse_of(np, bus);
> > +		if (ret < 0)
> > +			return ret;
> > +	}
> > +
> > +	/* Parse the device-tree to get the resource information */
> > +	ret = exynos_bus_parse_of(np, bus);
> > +	if (ret < 0)
> > +		goto err_reg;
> > +
> > +	if (passive)
> > +		ret = exynos_bus_profile_init_passive(bus, profile);
> > +	else
> > +		ret = exynos_bus_profile_init(bus, profile);
> > +
> > +	if (ret < 0)
> > +		goto err;
> > +
> >  	max_state = bus->devfreq->profile->max_state;
> >  	min_freq = (bus->devfreq->profile->freq_table[0] / 1000);
> >  	max_freq = (bus->devfreq->profile->freq_table[max_state - 1] / 1000);
> > 
> > 
> > 
> > 
> 
> 
-- 
Artur Świgoń
Samsung R&D Institute Poland
Samsung Electronics



^ permalink raw reply	[flat|nested] 41+ messages in thread

* Re: [RFC PATCH v2 00/11] Simple QoS for exynos-bus driver using interconnect
  2019-09-25  6:37           ` Artur Świgoń
@ 2019-09-25  6:48             ` Chanwoo Choi
  0 siblings, 0 replies; 41+ messages in thread
From: Chanwoo Choi @ 2019-09-25  6:48 UTC (permalink / raw)
  To: Artur Świgoń,
	devicetree, linux-arm-kernel, linux-samsung-soc, linux-kernel,
	linux-pm, dri-devel
  Cc: myungjoo.ham, inki.dae, sw0312.kim, georgi.djakov,
	leonard.crestez, m.szyprowski, b.zolnierkie, krzk,
	cpgs (cpgs@samsung.com),
	k.konieczny

Hi,

On 19. 9. 25. 오후 3:37, Artur Świgoń wrote:
> On Wed, 2019-09-25 at 15:12 +0900, Chanwoo Choi wrote:
>> Hi,
>>
>> On 19. 9. 25. 오후 2:47, Artur Świgoń wrote:
>>> Hi,
>>>
>>> On Fri, 2019-09-20 at 11:14 +0900, Chanwoo Choi wrote:
>>>> Hi Artur,
>>>>
>>>> I tried to just build this patch on mainline kernel or linux-next.
>>>> But, when I applied them, merge conflict happens. You didn't develop
>>>> them on latest version. Please rebase them based on latest mainline kernel.
>>>
>>> I developed on top of next-20190918 on which I applied
>>> https://patchwork.kernel.org/cover/11149497/ as I mentioned in the cover
>>> letter. The dev_pm_qos patches and my RFC have just cleanly rebased together on
>>> top of next-20190920. Could you check if you have the dev_pm_qos patches (v5,
>>> the version number is missing in this one; link above) and if so, where does the
>>> conflict appear?
>>
>> I faced on the merge conflict of drivers/devfreq/exynos-bus.c.
>> I think that It is not related to to dev_pm_qos patch.
> 
> I think that it is actually related to the specific version of dev_pm_qos (v5) that
> I used because patch 08/08 of dev_pm_qos series modifies exynos_bus_probe() in
> drivers/devfreq/exynos-bus.c (https://patchwork.kernel.org/patch/11149507/).
> 
> I will rebase the next RFC (v3) on latest dev_pm_qos patches from Leonard and the
> latest Linux-next kernel.

My mistake. I only checked the Leonard's latest patches(v8)
which doesn't contain this patch. OK. I'll try again. Thanks.
[1] https://patchwork.kernel.org/patch/11149507/
- PM / devfreq: Move opp notifier registration to core

> 
>> Maybe, Kamil's patches[1] changed the many things of exynos-bus.c
>> If your test branch doesn't contain following patches, 
>> you need to rebase your patches based on latest mainline kernel 
>> from Linus Torvald.
>> [1] https://patchwork.kernel.org/cover/11083663/
>> - [RESEND PATCH v5 0/4] add coupled regulators for Exynos5422/5800
> 
> Yes, requiring Kamil's patches is one of the changes in this RFC (v2), since they
> are already merged.
> 
>> Today, I tried to apply these patch again based on latest mainline kernel.
>> The merge conflict happen still.
>>
>> - merge conflict log
>> Applying: devfreq: exynos-bus: Extract exynos_bus_profile_init()
>> error: patch failed: drivers/devfreq/exynos-bus.c:334
>> error: drivers/devfreq/exynos-bus.c: patch does not apply
>> Patch failed at 0001 devfreq: exynos-bus: Extract exynos_bus_profile_init()
>>
>>
>>>
>>>> On 19. 9. 20. 오전 10:07, Chanwoo Choi wrote:
>>>>> Hi Artur,
>>>>>
>>>>> On v1, I mentioned that we need to discuss how to change
>>>>> the v2 for this. But, I have not received any reply from you on v1.
>>>>> And, without your reply from v1, you just send v2.
>>>>>
>>>>> I think that it is not proper development sequence.
>>>>> I have spent many times to review your patches
>>>>> and also I'll review your patches. You have to take care
>>>>> the reply of reviewer and and keep the basic rule
>>>>> of mailing contribution for discussion.
>>>>>
>>>>> On 19. 9. 19. 오후 11:22, Artur Świgoń wrote:
>>>>>> The following patchset adds interconnect[1][2] framework support to the
>>>>>> exynos-bus devfreq driver. Extending the devfreq driver with interconnect
>>>>>> capabilities started as a response to the issue referenced in [3]. The
>>>>>> patches can be subdivided into four logical groups:
>>>>>>
>>>>>> (a) Refactoring the existing devfreq driver in order to improve readability
>>>>>> and accommodate for adding new code (patches 01--04/11).
>>>>>>
>>>>>> (b) Tweaking the interconnect framework to support the exynos-bus use case
>>>>>> (patches 05--07/11). Exporting of_icc_get_from_provider() allows us to
>>>>>> avoid hardcoding every single graph edge in the DT or driver source, and
>>>>>> relaxing the requirement contained in that function removes the need to
>>>>>> provide dummy node IDs in the DT. Adjusting the logic in
>>>>>> apply_constraints() (drivers/interconnect/core.c) accounts for the fact
>>>>>> that every bus is a separate entity and therefore a separate interconnect
>>>>>> provider, albeit constituting a part of a larger hierarchy.
>>>>>>
>>>>>> (c) Implementing interconnect providers in the exynos-bus devfreq driver
>>>>>> and adding required DT properties for one selected platform, namely
>>>>>> Exynos4412 (patches 08--09/11). Due to the fact that this aims to be a
>>>>>> generic driver for various Exynos SoCs, node IDs are generated dynamically
>>>>>> rather than hardcoded. This has been determined to be a simpler approach,
>>>>>> but depends on changes described in (b).
>>>>>>
>>>>>> (d) Implementing a sample interconnect consumer for exynos-mixer targeted
>>>>>> at the issue referenced in [3], again with DT info only for Exynos4412
>>>>>> (patches 10--11/11).
>>>>>>
>>>>>> Integration of devfreq and interconnect functionalities is achieved by
>>>>>> using dev_pm_qos_*() API[5]. All new code works equally well when
>>>>>> CONFIG_INTERCONNECT is 'n' (as in exynos_defconfig) in which case all
>>>>>> interconnect API functions are no-ops.
>>>>>>
>>>>>> This patchset depends on [5].
>>>>>>
>>>>>> --- Changes since v1 [6]:
>>>>>> * Rebase on [4] (coupled regulators).
>>>>>> * Rebase on [5] (dev_pm_qos for devfreq).
>>>>>> * Use dev_pm_qos_*() API[5] instead of overriding frequency in
>>>>>>   exynos_bus_target().
>>>>>> * Use IDR for node ID allocation.
>>>>>> * Avoid goto in functions extracted in patches 01 & 02 (cf. patch 04).
>>>>>> * Reverse order of multiplication and division in
>>>>>>   mixer_set_memory_bandwidth() (patch 11) to avoid integer overflow.
>>>>>>
>>>>>> ---
>>>>>> Artur Świgoń
>>>>>> Samsung R&D Institute Poland
>>>>>> Samsung Electronics
>>>>>>
>>>>>> ---
>>>>>> References:
>>>>>> [1] Documentation/interconnect/interconnect.rst
>>>>>> [2] Documentation/devicetree/bindings/interconnect/interconnect.txt
>>>>>> [3] https://patchwork.kernel.org/patch/10861757/ (original issue)
>>>>>> [4] https://patchwork.kernel.org/cover/11083663/ (coupled regulators; merged)
>>>>>> [5] https://patchwork.kernel.org/cover/11149497/ (dev_pm_qos for devfreq)
>>>>>> [6] https://patchwork.kernel.org/cover/11054417/ (v1 of this RFC)
>>>>>>
>>>>>> Artur Świgoń (10):
>>>>>>   devfreq: exynos-bus: Extract exynos_bus_profile_init()
>>>>>>   devfreq: exynos-bus: Extract exynos_bus_profile_init_passive()
>>>>>>   devfreq: exynos-bus: Change goto-based logic to if-else logic
>>>>>>   devfreq: exynos-bus: Clean up code
>>>>>>   interconnect: Export of_icc_get_from_provider()
>>>>>>   interconnect: Relax requirement in of_icc_get_from_provider()
>>>>>>   interconnect: Relax condition in apply_constraints()
>>>>>>   arm: dts: exynos: Add parents and #interconnect-cells to Exynos4412
>>>>>>   devfreq: exynos-bus: Add interconnect functionality to exynos-bus
>>>>>>   arm: dts: exynos: Add interconnects to Exynos4412 mixer
>>>>>>
>>>>>> Marek Szyprowski (1):
>>>>>>   drm: exynos: mixer: Add interconnect support
>>>>>>
>>>>>>  .../boot/dts/exynos4412-odroid-common.dtsi    |   1 +
>>>>>>  arch/arm/boot/dts/exynos4412.dtsi             |  10 +
>>>>>>  drivers/devfreq/exynos-bus.c                  | 319 +++++++++++++-----
>>>>>>  drivers/gpu/drm/exynos/exynos_mixer.c         |  71 +++-
>>>>>>  drivers/interconnect/core.c                   |  12 +-
>>>>>>  include/linux/interconnect-provider.h         |   6 +
>>>>>>  6 files changed, 327 insertions(+), 92 deletions(-)
>>>>>>
> 
> 
> 
> 


-- 
Best Regards,
Chanwoo Choi
Samsung Electronics

^ permalink raw reply	[flat|nested] 41+ messages in thread

* Re: [RFC PATCH v2 09/11] devfreq: exynos-bus: Add interconnect functionality to exynos-bus
  2019-09-19 14:22     ` [RFC PATCH v2 09/11] devfreq: exynos-bus: Add interconnect functionality to exynos-bus Artur Świgoń
@ 2019-09-25  7:03       ` Chanwoo Choi
  2019-09-25  7:12         ` Artur Świgoń
  2019-12-02 17:05         ` Artur Świgoń
  2019-12-16  0:44       ` Chanwoo Choi
  1 sibling, 2 replies; 41+ messages in thread
From: Chanwoo Choi @ 2019-09-25  7:03 UTC (permalink / raw)
  To: Artur Świgoń,
	devicetree, linux-arm-kernel, linux-samsung-soc, linux-kernel,
	linux-pm, dri-devel
  Cc: Artur Świgoń,
	myungjoo.ham, inki.dae, sw0312.kim, georgi.djakov,
	leonard.crestez, m.szyprowski, b.zolnierkie, krzk

Hi,

I need the time to dig the ICC framework
to understand them detailed. After that, I'll review this.

Basically, I agree this approach. But, I'm wondering
the existing binding method between 'bus_leftbus' and 'bus_dmc'.
From before, I thought that devfreq framework need to
enhance the binding method between parent devfreq device
and passive devfreq device instead of 'devfreq' property.

On this patch, use the same binding way between
'bus_leftbus' and 'bus_dmc' with 'parent' property
as following:

+++ b/arch/arm/boot/dts/exynos4412-odroid-common.dtsi
@@ -106,6 +106,7 @@
 &bus_leftbus {
 	devfreq-events = <&ppmu_leftbus_3>, <&ppmu_rightbus_3>;
 	vdd-supply = <&buck3_reg>;
+	parent = <&bus_dmc>;
 	status = "okay";
 };

I'm not sure about continuing to use this method for new feature.
If possible, hope to replace the existing binding style
with new method like of_graph. Actually, I don't know the correct method.


On 19. 9. 19. 오후 11:22, Artur Świgoń wrote:
> From: Artur Świgoń <a.swigon@partner.samsung.com>
> 
> This patch adds interconnect functionality to the exynos-bus devfreq
> driver.
> 
> The SoC topology is a graph (or, more specifically, a tree) and most of
> its edges are taken from the devfreq parent-child hierarchy (cf.
> Documentation/devicetree/bindings/devfreq/exynos-bus.txt). Due to
> unspecified relative probing order, -EPROBE_DEFER may be propagated to
> guarantee that a child is probed before its parent.
> 
> Each bus is now an interconnect provider and an interconnect node as well
> (cf. Documentation/interconnect/interconnect.rst), i.e. every bus registers
> itself as a node. Node IDs are not hardcoded but rather assigned at
> runtime, in probing order (subject to the above-mentioned exception
> regarding relative order). This approach allows for using this driver with
> various Exynos SoCs.
> 
> Frequencies requested via the interconnect API for a given node are
> propagated to devfreq using dev_pm_qos_update_request(). Please note that
> it is not an error when CONFIG_INTERCONNECT is 'n', in which case all
> interconnect API functions are no-op.
> 
> Signed-off-by: Artur Świgoń <a.swigon@partner.samsung.com>
> ---
>  drivers/devfreq/exynos-bus.c | 153 +++++++++++++++++++++++++++++++++++
>  1 file changed, 153 insertions(+)
> 
> diff --git a/drivers/devfreq/exynos-bus.c b/drivers/devfreq/exynos-bus.c
> index 8d44810cac69..e0232202720d 100644
> --- a/drivers/devfreq/exynos-bus.c
> +++ b/drivers/devfreq/exynos-bus.c
> @@ -14,14 +14,19 @@
>  #include <linux/devfreq-event.h>
>  #include <linux/device.h>
>  #include <linux/export.h>
> +#include <linux/idr.h>
> +#include <linux/interconnect-provider.h>
>  #include <linux/module.h>
>  #include <linux/of.h>
>  #include <linux/pm_opp.h>
> +#include <linux/pm_qos.h>
>  #include <linux/platform_device.h>
>  #include <linux/regulator/consumer.h>
>  
>  #define DEFAULT_SATURATION_RATIO	40
>  
> +#define icc_units_to_khz(x) ((x) / 8)
> +
>  struct exynos_bus {
>  	struct device *dev;
>  
> @@ -35,6 +40,12 @@ struct exynos_bus {
>  	struct opp_table *opp_table;
>  	struct clk *clk;
>  	unsigned int ratio;
> +
> +	/* One provider per bus, one node per provider */
> +	struct icc_provider provider;
> +	struct icc_node *node;
> +
> +	struct dev_pm_qos_request qos_req;
>  };
>  
>  /*
> @@ -59,6 +70,13 @@ exynos_bus_ops_edev(enable_edev);
>  exynos_bus_ops_edev(disable_edev);
>  exynos_bus_ops_edev(set_event);
>  
> +static int exynos_bus_next_id(void)
> +{
> +	static DEFINE_IDA(exynos_bus_icc_ida);
> +
> +	return ida_alloc(&exynos_bus_icc_ida, GFP_KERNEL);
> +}
> +
>  static int exynos_bus_get_event(struct exynos_bus *bus,
>  				struct devfreq_event_data *edata)
>  {
> @@ -171,6 +189,38 @@ static void exynos_bus_passive_exit(struct device *dev)
>  	clk_disable_unprepare(bus->clk);
>  }
>  
> +static int exynos_bus_icc_set(struct icc_node *src, struct icc_node *dst)
> +{
> +	struct exynos_bus *src_bus = src->data, *dst_bus = dst->data;
> +	s32 src_freq = icc_units_to_khz(src->avg_bw);
> +	s32 dst_freq = icc_units_to_khz(dst->avg_bw);
> +
> +	dev_pm_qos_update_request(&src_bus->qos_req, src_freq);
> +	dev_pm_qos_update_request(&dst_bus->qos_req, dst_freq);
> +
> +	return 0;
> +}
> +
> +static int exynos_bus_icc_aggregate(struct icc_node *node, u32 tag, u32 avg_bw,
> +				    u32 peak_bw, u32 *agg_avg, u32 *agg_peak)
> +{
> +	*agg_avg += avg_bw;
> +	*agg_peak = max(*agg_peak, peak_bw);
> +
> +	return 0;
> +}
> +
> +static struct icc_node *exynos_bus_icc_xlate(struct of_phandle_args *spec,
> +					     void *data)
> +{
> +	struct exynos_bus *bus = data;
> +
> +	if (spec->np != bus->dev->of_node)
> +		return ERR_PTR(-EINVAL);
> +
> +	return bus->node;
> +}
> +
>  static int exynos_bus_parent_parse_of(struct device_node *np,
>  					struct exynos_bus *bus)
>  {
> @@ -366,6 +416,101 @@ static int exynos_bus_profile_init_passive(struct exynos_bus *bus,
>  	return 0;
>  }
>  
> +static int exynos_bus_icc_connect(struct exynos_bus *bus)
> +{
> +	struct device_node *np = bus->dev->of_node;
> +	struct devfreq *parent_devfreq;
> +	struct icc_node *parent_node = NULL;
> +	struct of_phandle_args args;
> +	int ret = 0;
> +
> +	parent_devfreq = devfreq_get_devfreq_by_phandle(bus->dev, 0);
> +	if (!IS_ERR(parent_devfreq)) {
> +		struct exynos_bus *parent_bus;
> +
> +		parent_bus = dev_get_drvdata(parent_devfreq->dev.parent);
> +		parent_node = parent_bus->node;
> +	} else {
> +		/* Look for parent in DT */
> +		int num = of_count_phandle_with_args(np, "parent",
> +						     "#interconnect-cells");
> +		if (num != 1)
> +			goto out; /* 'parent' is optional */
> +
> +		ret = of_parse_phandle_with_args(np, "parent",
> +						 "#interconnect-cells",
> +						 0, &args);
> +		if (ret < 0)
> +			goto out;
> +
> +		of_node_put(args.np);
> +
> +		parent_node = of_icc_get_from_provider(&args);
> +		if (IS_ERR(parent_node)) {
> +			/* May be -EPROBE_DEFER */
> +			ret = PTR_ERR(parent_node);
> +			goto out;
> +		}
> +	}



> +
> +	ret = icc_link_create(bus->node, parent_node->id);
> +
> +out:
> +	return ret;
> +}
> +
> +static int exynos_bus_icc_init(struct exynos_bus *bus)
> +{
> +	struct device *dev = bus->dev;
> +	struct icc_provider *provider = &bus->provider;
> +	struct icc_node *node;
> +	int id, ret;
> +
> +	/* Initialize the interconnect provider */
> +	provider->set = exynos_bus_icc_set;
> +	provider->aggregate = exynos_bus_icc_aggregate;
> +	provider->xlate = exynos_bus_icc_xlate;
> +	provider->dev = dev;
> +	provider->data = bus;
> +
> +	ret = icc_provider_add(provider);
> +	if (ret < 0)
> +		goto out;
> +
> +	ret = id = exynos_bus_next_id();
> +	if (ret < 0)
> +		goto err_node;
> +
> +	node = icc_node_create(id);
> +	if (IS_ERR(node)) {
> +		ret = PTR_ERR(node);
> +		goto err_node;
> +	}
> +
> +	bus->node = node;
> +	node->name = dev->of_node->name;
> +	node->data = bus;
> +	icc_node_add(node, provider);
> +
> +	ret = exynos_bus_icc_connect(bus);
> +	if (ret < 0)
> +		goto err_connect;
> +
> +	ret = dev_pm_qos_add_request(bus->devfreq->dev.parent, &bus->qos_req,
> +				     DEV_PM_QOS_MIN_FREQUENCY, 0);
> +
> +out:
> +	return ret;
> +
> +err_connect:
> +	icc_node_del(node);
> +	icc_node_destroy(id);
> +err_node:
> +	icc_provider_del(provider);
> +
> +	return ret;
> +}
> +
>  static int exynos_bus_probe(struct platform_device *pdev)
>  {
>  	struct device *dev = &pdev->dev;
> @@ -415,6 +560,14 @@ static int exynos_bus_probe(struct platform_device *pdev)
>  	if (ret < 0)
>  		goto err;
>  
> +	/*
> +	 * Initialize interconnect provider. A return value of -ENOTSUPP means
> +	 * that CONFIG_INTERCONNECT is disabled.
> +	 */
> +	ret = exynos_bus_icc_init(bus);
> +	if (ret < 0 && ret != -ENOTSUPP)
> +		goto err;
> +
>  	max_state = bus->devfreq->profile->max_state;
>  	min_freq = (bus->devfreq->profile->freq_table[0] / 1000);
>  	max_freq = (bus->devfreq->profile->freq_table[max_state - 1] / 1000);
> 


-- 
Best Regards,
Chanwoo Choi
Samsung Electronics

^ permalink raw reply	[flat|nested] 41+ messages in thread

* Re: [RFC PATCH v2 09/11] devfreq: exynos-bus: Add interconnect functionality to exynos-bus
  2019-09-25  7:03       ` Chanwoo Choi
@ 2019-09-25  7:12         ` Artur Świgoń
  2019-12-02 17:05         ` Artur Świgoń
  1 sibling, 0 replies; 41+ messages in thread
From: Artur Świgoń @ 2019-09-25  7:12 UTC (permalink / raw)
  To: Chanwoo Choi, devicetree, linux-arm-kernel, linux-samsung-soc,
	linux-kernel, linux-pm, dri-devel
  Cc: Artur Świgoń,
	myungjoo.ham, inki.dae, sw0312.kim, georgi.djakov,
	leonard.crestez, m.szyprowski, b.zolnierkie, krzk

Hi,

On Wed, 2019-09-25 at 16:03 +0900, Chanwoo Choi wrote:
> Hi,
> 
> I need the time to dig the ICC framework
> to understand them detailed. After that, I'll review this.
> 
> Basically, I agree this approach. But, I'm wondering
> the existing binding method between 'bus_leftbus' and 'bus_dmc'.
> From before, I thought that devfreq framework need to
> enhance the binding method between parent devfreq device
> and passive devfreq device instead of 'devfreq' property.
> 
> On this patch, use the same binding way between
> 'bus_leftbus' and 'bus_dmc' with 'parent' property
> as following:
> 
> +++ b/arch/arm/boot/dts/exynos4412-odroid-common.dtsi
> @@ -106,6 +106,7 @@
>  &bus_leftbus {
>  	devfreq-events = <&ppmu_leftbus_3>, <&ppmu_rightbus_3>;
>  	vdd-supply = <&buck3_reg>;
> +	parent = <&bus_dmc>;
>  	status = "okay";
>  };
> 
> I'm not sure about continuing to use this method for new feature.
> If possible, hope to replace the existing binding style
> with new method like of_graph. Actually, I don't know the correct method.

Adding the 'parent' binding was the simplest solution to create this
RFC to show the concept of using interconnect functionality in devfreq.
I agree that a method like of_graph is probably more elegant. I am open
to suggestions.

> On 19. 9. 19. 오후 11:22, Artur Świgoń wrote:
> > From: Artur Świgoń <a.swigon@partner.samsung.com>
> > 
> > This patch adds interconnect functionality to the exynos-bus devfreq
> > driver.
> > 
> > The SoC topology is a graph (or, more specifically, a tree) and most of
> > its edges are taken from the devfreq parent-child hierarchy (cf.
> > Documentation/devicetree/bindings/devfreq/exynos-bus.txt). Due to
> > unspecified relative probing order, -EPROBE_DEFER may be propagated to
> > guarantee that a child is probed before its parent.
> > 
> > Each bus is now an interconnect provider and an interconnect node as well
> > (cf. Documentation/interconnect/interconnect.rst), i.e. every bus registers
> > itself as a node. Node IDs are not hardcoded but rather assigned at
> > runtime, in probing order (subject to the above-mentioned exception
> > regarding relative order). This approach allows for using this driver with
> > various Exynos SoCs.
> > 
> > Frequencies requested via the interconnect API for a given node are
> > propagated to devfreq using dev_pm_qos_update_request(). Please note that
> > it is not an error when CONFIG_INTERCONNECT is 'n', in which case all
> > interconnect API functions are no-op.
> > 
> > Signed-off-by: Artur Świgoń <a.swigon@partner.samsung.com>
> > ---
> >  drivers/devfreq/exynos-bus.c | 153 +++++++++++++++++++++++++++++++++++
> >  1 file changed, 153 insertions(+)
> > 
> > diff --git a/drivers/devfreq/exynos-bus.c b/drivers/devfreq/exynos-bus.c
> > index 8d44810cac69..e0232202720d 100644
> > --- a/drivers/devfreq/exynos-bus.c
> > +++ b/drivers/devfreq/exynos-bus.c
> > @@ -14,14 +14,19 @@
> >  #include <linux/devfreq-event.h>
> >  #include <linux/device.h>
> >  #include <linux/export.h>
> > +#include <linux/idr.h>
> > +#include <linux/interconnect-provider.h>
> >  #include <linux/module.h>
> >  #include <linux/of.h>
> >  #include <linux/pm_opp.h>
> > +#include <linux/pm_qos.h>
> >  #include <linux/platform_device.h>
> >  #include <linux/regulator/consumer.h>
> >  
> >  #define DEFAULT_SATURATION_RATIO	40
> >  
> > +#define icc_units_to_khz(x) ((x) / 8)
> > +
> >  struct exynos_bus {
> >  	struct device *dev;
> >  
> > @@ -35,6 +40,12 @@ struct exynos_bus {
> >  	struct opp_table *opp_table;
> >  	struct clk *clk;
> >  	unsigned int ratio;
> > +
> > +	/* One provider per bus, one node per provider */
> > +	struct icc_provider provider;
> > +	struct icc_node *node;
> > +
> > +	struct dev_pm_qos_request qos_req;
> >  };
> >  
> >  /*
> > @@ -59,6 +70,13 @@ exynos_bus_ops_edev(enable_edev);
> >  exynos_bus_ops_edev(disable_edev);
> >  exynos_bus_ops_edev(set_event);
> >  
> > +static int exynos_bus_next_id(void)
> > +{
> > +	static DEFINE_IDA(exynos_bus_icc_ida);
> > +
> > +	return ida_alloc(&exynos_bus_icc_ida, GFP_KERNEL);
> > +}
> > +
> >  static int exynos_bus_get_event(struct exynos_bus *bus,
> >  				struct devfreq_event_data *edata)
> >  {
> > @@ -171,6 +189,38 @@ static void exynos_bus_passive_exit(struct device *dev)
> >  	clk_disable_unprepare(bus->clk);
> >  }
> >  
> > +static int exynos_bus_icc_set(struct icc_node *src, struct icc_node *dst)
> > +{
> > +	struct exynos_bus *src_bus = src->data, *dst_bus = dst->data;
> > +	s32 src_freq = icc_units_to_khz(src->avg_bw);
> > +	s32 dst_freq = icc_units_to_khz(dst->avg_bw);
> > +
> > +	dev_pm_qos_update_request(&src_bus->qos_req, src_freq);
> > +	dev_pm_qos_update_request(&dst_bus->qos_req, dst_freq);
> > +
> > +	return 0;
> > +}
> > +
> > +static int exynos_bus_icc_aggregate(struct icc_node *node, u32 tag, u32 avg_bw,
> > +				    u32 peak_bw, u32 *agg_avg, u32 *agg_peak)
> > +{
> > +	*agg_avg += avg_bw;
> > +	*agg_peak = max(*agg_peak, peak_bw);
> > +
> > +	return 0;
> > +}
> > +
> > +static struct icc_node *exynos_bus_icc_xlate(struct of_phandle_args *spec,
> > +					     void *data)
> > +{
> > +	struct exynos_bus *bus = data;
> > +
> > +	if (spec->np != bus->dev->of_node)
> > +		return ERR_PTR(-EINVAL);
> > +
> > +	return bus->node;
> > +}
> > +
> >  static int exynos_bus_parent_parse_of(struct device_node *np,
> >  					struct exynos_bus *bus)
> >  {
> > @@ -366,6 +416,101 @@ static int exynos_bus_profile_init_passive(struct exynos_bus *bus,
> >  	return 0;
> >  }
> >  
> > +static int exynos_bus_icc_connect(struct exynos_bus *bus)
> > +{
> > +	struct device_node *np = bus->dev->of_node;
> > +	struct devfreq *parent_devfreq;
> > +	struct icc_node *parent_node = NULL;
> > +	struct of_phandle_args args;
> > +	int ret = 0;
> > +
> > +	parent_devfreq = devfreq_get_devfreq_by_phandle(bus->dev, 0);
> > +	if (!IS_ERR(parent_devfreq)) {
> > +		struct exynos_bus *parent_bus;
> > +
> > +		parent_bus = dev_get_drvdata(parent_devfreq->dev.parent);
> > +		parent_node = parent_bus->node;
> > +	} else {
> > +		/* Look for parent in DT */
> > +		int num = of_count_phandle_with_args(np, "parent",
> > +						     "#interconnect-cells");
> > +		if (num != 1)
> > +			goto out; /* 'parent' is optional */
> > +
> > +		ret = of_parse_phandle_with_args(np, "parent",
> > +						 "#interconnect-cells",
> > +						 0, &args);
> > +		if (ret < 0)
> > +			goto out;
> > +
> > +		of_node_put(args.np);
> > +
> > +		parent_node = of_icc_get_from_provider(&args);
> > +		if (IS_ERR(parent_node)) {
> > +			/* May be -EPROBE_DEFER */
> > +			ret = PTR_ERR(parent_node);
> > +			goto out;
> > +		}
> > +	}
> 
> 
> 
> > +
> > +	ret = icc_link_create(bus->node, parent_node->id);
> > +
> > +out:
> > +	return ret;
> > +}
> > +
> > +static int exynos_bus_icc_init(struct exynos_bus *bus)
> > +{
> > +	struct device *dev = bus->dev;
> > +	struct icc_provider *provider = &bus->provider;
> > +	struct icc_node *node;
> > +	int id, ret;
> > +
> > +	/* Initialize the interconnect provider */
> > +	provider->set = exynos_bus_icc_set;
> > +	provider->aggregate = exynos_bus_icc_aggregate;
> > +	provider->xlate = exynos_bus_icc_xlate;
> > +	provider->dev = dev;
> > +	provider->data = bus;
> > +
> > +	ret = icc_provider_add(provider);
> > +	if (ret < 0)
> > +		goto out;
> > +
> > +	ret = id = exynos_bus_next_id();
> > +	if (ret < 0)
> > +		goto err_node;
> > +
> > +	node = icc_node_create(id);
> > +	if (IS_ERR(node)) {
> > +		ret = PTR_ERR(node);
> > +		goto err_node;
> > +	}
> > +
> > +	bus->node = node;
> > +	node->name = dev->of_node->name;
> > +	node->data = bus;
> > +	icc_node_add(node, provider);
> > +
> > +	ret = exynos_bus_icc_connect(bus);
> > +	if (ret < 0)
> > +		goto err_connect;
> > +
> > +	ret = dev_pm_qos_add_request(bus->devfreq->dev.parent, &bus->qos_req,
> > +				     DEV_PM_QOS_MIN_FREQUENCY, 0);
> > +
> > +out:
> > +	return ret;
> > +
> > +err_connect:
> > +	icc_node_del(node);
> > +	icc_node_destroy(id);
> > +err_node:
> > +	icc_provider_del(provider);
> > +
> > +	return ret;
> > +}
> > +
> >  static int exynos_bus_probe(struct platform_device *pdev)
> >  {
> >  	struct device *dev = &pdev->dev;
> > @@ -415,6 +560,14 @@ static int exynos_bus_probe(struct platform_device *pdev)
> >  	if (ret < 0)
> >  		goto err;
> >  
> > +	/*
> > +	 * Initialize interconnect provider. A return value of -ENOTSUPP means
> > +	 * that CONFIG_INTERCONNECT is disabled.
> > +	 */
> > +	ret = exynos_bus_icc_init(bus);
> > +	if (ret < 0 && ret != -ENOTSUPP)
> > +		goto err;
> > +
> >  	max_state = bus->devfreq->profile->max_state;
> >  	min_freq = (bus->devfreq->profile->freq_table[0] / 1000);
> >  	max_freq = (bus->devfreq->profile->freq_table[max_state - 1] / 1000);
> > 
> 
> 
-- 
Artur Świgoń
Samsung R&D Institute Poland
Samsung Electronics



^ permalink raw reply	[flat|nested] 41+ messages in thread

* Re: [RFC PATCH v2 04/11] devfreq: exynos-bus: Clean up code
  2019-09-20  2:22       ` Chanwoo Choi
@ 2019-10-03  8:10         ` Artur Świgoń
  0 siblings, 0 replies; 41+ messages in thread
From: Artur Świgoń @ 2019-10-03  8:10 UTC (permalink / raw)
  To: Chanwoo Choi, devicetree, linux-arm-kernel, linux-samsung-soc,
	linux-kernel, linux-pm, dri-devel
  Cc: Artur Świgoń,
	myungjoo.ham, inki.dae, sw0312.kim, georgi.djakov,
	leonard.crestez, m.szyprowski, b.zolnierkie, krzk

Hi,

On Fri, 2019-09-20 at 11:22 +0900, Chanwoo Choi wrote:
> Hi Artur,
> 
> On 19. 9. 19. 오후 11:22, Artur Świgoń wrote:
> > From: Artur Świgoń <a.swigon@partner.samsung.com>
> > 
> > This patch adds minor improvements to the exynos-bus driver.
> > 
> > Signed-off-by: Artur Świgoń <a.swigon@partner.samsung.com>
> > Reviewed-by: Krzysztof Kozlowski <krzk@kernel.org>
> > ---
> >  drivers/devfreq/exynos-bus.c | 66 ++++++++++++++----------------------
> >  1 file changed, 25 insertions(+), 41 deletions(-)
> > 
> > diff --git a/drivers/devfreq/exynos-bus.c b/drivers/devfreq/exynos-bus.c
> > index 60ad4319fd80..8d44810cac69 100644
> > --- a/drivers/devfreq/exynos-bus.c
> > +++ b/drivers/devfreq/exynos-bus.c
> > @@ -15,11 +15,10 @@
> >  #include <linux/device.h>
> >  #include <linux/export.h>
> >  #include <linux/module.h>
> > -#include <linux/of_device.h>
> > +#include <linux/of.h>
> >  #include <linux/pm_opp.h>
> >  #include <linux/platform_device.h>
> >  #include <linux/regulator/consumer.h>
> > -#include <linux/slab.h>
> >  
> >  #define DEFAULT_SATURATION_RATIO	40
> >  
> > @@ -178,7 +177,7 @@ static int exynos_bus_parent_parse_of(struct device_node *np,
> >  	struct device *dev = bus->dev;
> >  	struct opp_table *opp_table;
> >  	const char *vdd = "vdd";
> > -	int i, ret, count, size;
> > +	int i, ret, count;
> >  
> >  	opp_table = dev_pm_opp_set_regulators(dev, &vdd, 1);
> >  	if (IS_ERR(opp_table)) {
> > @@ -201,8 +200,7 @@ static int exynos_bus_parent_parse_of(struct device_node *np,
> >  	}
> >  	bus->edev_count = count;
> >  
> > -	size = sizeof(*bus->edev) * count;
> > -	bus->edev = devm_kzalloc(dev, size, GFP_KERNEL);
> > +	bus->edev = devm_kcalloc(dev, count, sizeof(*bus->edev), GFP_KERNEL);
> >  	if (!bus->edev) {
> >  		ret = -ENOMEM;
> >  		goto err_regulator;
> > @@ -301,10 +299,9 @@ static int exynos_bus_profile_init(struct exynos_bus *bus,
> >  	profile->exit = exynos_bus_exit;
> >  
> >  	ondemand_data = devm_kzalloc(dev, sizeof(*ondemand_data), GFP_KERNEL);
> > -	if (!ondemand_data) {
> > -		ret = -ENOMEM;
> > -		goto err;
> > -	}
> > +	if (!ondemand_data)
> > +		return -ENOMEM;
> > +
> >  	ondemand_data->upthreshold = 40;
> >  	ondemand_data->downdifferential = 5;
> >  
> > @@ -314,8 +311,7 @@ static int exynos_bus_profile_init(struct exynos_bus *bus,
> >  						ondemand_data);
> >  	if (IS_ERR(bus->devfreq)) {
> >  		dev_err(dev, "failed to add devfreq device\n");
> > -		ret = PTR_ERR(bus->devfreq);
> > -		goto err;
> > +		return PTR_ERR(bus->devfreq);
> >  	}
> >  
> >  	/*
> > @@ -325,16 +321,13 @@ static int exynos_bus_profile_init(struct exynos_bus *bus,
> >  	ret = exynos_bus_enable_edev(bus);
> >  	if (ret < 0) {
> >  		dev_err(dev, "failed to enable devfreq-event devices\n");
> > -		goto err;
> > +		return ret;
> >  	}
> >  
> >  	ret = exynos_bus_set_event(bus);
> > -	if (ret < 0) {
> > +	if (ret < 0)
> >  		dev_err(dev, "failed to set event to devfreq-event devices\n");
> > -		goto err;
> 
> Instead of removing 'goto err', just return err as I commented[1] on v1.
> [1] https://lkml.org/lkml/2019/7/26/331
> 
> > -	}
> >  
> > -err:
> >  	return ret;
> 
> And you just keep 'return ret' or you can change it as 'return 0'.

OK, I went for:

ret = exynos_bus_set_event(bus);
if (ret < 0) {
	dev_err(dev, "failed to set event to devfreq-event devices\n");
	return ret;
}

return 0;

> >  }
> >  
> > @@ -344,7 +337,6 @@ static int exynos_bus_profile_init_passive(struct exynos_bus *bus,
> >  	struct device *dev = bus->dev;
> >  	struct devfreq_passive_data *passive_data;
> >  	struct devfreq *parent_devfreq;
> > -	int ret = 0;
> >  
> >  	/* Initialize the struct profile and governor data for passive device */
> >  	profile->target = exynos_bus_target;
> > @@ -352,30 +344,26 @@ static int exynos_bus_profile_init_passive(struct exynos_bus *bus,
> >  
> >  	/* Get the instance of parent devfreq device */
> >  	parent_devfreq = devfreq_get_devfreq_by_phandle(dev, 0);
> > -	if (IS_ERR(parent_devfreq)) {
> > -		ret = -EPROBE_DEFER;
> > -		goto err;
> > -	}
> > +	if (IS_ERR(parent_devfreq))
> > +		return -EPROBE_DEFER;
> >  
> >  	passive_data = devm_kzalloc(dev, sizeof(*passive_data), GFP_KERNEL);
> > -	if (!passive_data) {
> > -		ret = -ENOMEM;
> > -		goto err;
> > -	}
> > +	if (!passive_data)
> > +		return -ENOMEM;
> > +
> >  	passive_data->parent = parent_devfreq;
> >  
> >  	/* Add devfreq device for exynos bus with passive governor */
> > -	bus->devfreq = devm_devfreq_add_device(dev, profile, DEVFREQ_GOV_PASSIVE,
> > +	bus->devfreq = devm_devfreq_add_device(dev, profile,
> > +						DEVFREQ_GOV_PASSIVE,
> >  						passive_data);
> >  	if (IS_ERR(bus->devfreq)) {
> >  		dev_err(dev,
> >  			"failed to add devfreq dev with passive governor\n");
> > -		ret = PTR_ERR(bus->devfreq);
> > -		goto err;
> > +		return PTR_ERR(bus->devfreq);
> >  	}
> >  
> > -err:
> > -	return ret;
> > +	return 0;
> >  }
> >  
> >  static int exynos_bus_probe(struct platform_device *pdev)
> > @@ -393,18 +381,18 @@ static int exynos_bus_probe(struct platform_device *pdev)
> >  		return -EINVAL;
> >  	}
> >  
> > -	bus = devm_kzalloc(&pdev->dev, sizeof(*bus), GFP_KERNEL);
> > +	bus = devm_kzalloc(dev, sizeof(*bus), GFP_KERNEL);
> >  	if (!bus)
> >  		return -ENOMEM;
> >  	mutex_init(&bus->lock);
> > -	bus->dev = &pdev->dev;
> > +	bus->dev = dev;
> >  	platform_set_drvdata(pdev, bus);
> >  
> >  	profile = devm_kzalloc(dev, sizeof(*profile), GFP_KERNEL);
> >  	if (!profile)
> >  		return -ENOMEM;
> >  
> > -	node = of_parse_phandle(dev->of_node, "devfreq", 0);
> > +	node = of_parse_phandle(np, "devfreq", 0);
> >  	if (node) {
> >  		of_node_put(node);
> >  		passive = true;
> > @@ -461,12 +449,10 @@ static int exynos_bus_resume(struct device *dev)
> >  	int ret;
> >  
> >  	ret = exynos_bus_enable_edev(bus);
> > -	if (ret < 0) {
> > +	if (ret < 0)
> >  		dev_err(dev, "failed to enable the devfreq-event devices\n");
> > -		return ret;
> 
> Keep the 'return ret' if error happen as I commented[1] on v1.
> [1] https://lkml.org/lkml/2019/7/26/331
> 
> > -	}
> >  
> > -	return 0;
> > +	return ret;
> 
> And you just keep 'return 0' or you can change it as 'return ret'.

OK, I kept the original code:

ret = exynos_bus_enable_edev(bus);
if (ret < 0) {
	dev_err(dev, "failed to enable the devfreq-event devices\n");
	return ret;
}

return 0;

> >  }
> >  
> >  static int exynos_bus_suspend(struct device *dev)
> > @@ -475,12 +461,10 @@ static int exynos_bus_suspend(struct device *dev)
> >  	int ret;
> >  
> >  	ret = exynos_bus_disable_edev(bus);
> > -	if (ret < 0) {
> > +	if (ret < 0)
> >  		dev_err(dev, "failed to disable the devfreq-event devices\n");
> > -		return ret;
> 
> Keep the 'return ret' if error happen as I commented[1] on v1.
> [1] https://lkml.org/lkml/2019/7/26/331

OK, I kept the original code.

> > -	}
> >  
> > -	return 0;
> > +	return ret;
> 
> And you just keep 'return 0' or you can change it as 'return ret'.
> 
> >  }
> >  #endif
> >  
> > 
> 
> 

Best regards,
-- 
Artur Świgoń
Samsung R&D Institute Poland
Samsung Electronics



^ permalink raw reply	[flat|nested] 41+ messages in thread

* Re: [RFC PATCH v2 09/11] devfreq: exynos-bus: Add interconnect functionality to exynos-bus
  2019-09-25  7:03       ` Chanwoo Choi
  2019-09-25  7:12         ` Artur Świgoń
@ 2019-12-02 17:05         ` Artur Świgoń
  2019-12-05  2:36           ` Chanwoo Choi
  1 sibling, 1 reply; 41+ messages in thread
From: Artur Świgoń @ 2019-12-02 17:05 UTC (permalink / raw)
  To: Chanwoo Choi, devicetree, linux-arm-kernel, linux-samsung-soc,
	linux-kernel, linux-pm, dri-devel
  Cc: myungjoo.ham, inki.dae, sw0312.kim, georgi.djakov,
	leonard.crestez, m.szyprowski, b.zolnierkie, krzk

Hi Chanwoo,

On Wed, 2019-09-25 at 16:03 +0900, Chanwoo Choi wrote:
> Hi,
> 
> I need the time to dig the ICC framework
> to understand them detailed. After that, I'll review this.

Any updates on this topic?

Regardless of the purpose of this RFC, I think patches 01-04
are still beneficial to devfreq. I can rebase and post them
as a separate series if you wish.

> Basically, I agree this approach. But, I'm wondering
> the existing binding method between 'bus_leftbus' and 'bus_dmc'.
> From before, I thought that devfreq framework need to
> enhance the binding method between parent devfreq device
> and passive devfreq device instead of 'devfreq' property.
> 
> On this patch, use the same binding way between
> 'bus_leftbus' and 'bus_dmc' with 'parent' property
> as following:
> 
> +++ b/arch/arm/boot/dts/exynos4412-odroid-common.dtsi
> @@ -106,6 +106,7 @@
>  &bus_leftbus {
>  	devfreq-events = <&ppmu_leftbus_3>, <&ppmu_rightbus_3>;
>  	vdd-supply = <&buck3_reg>;
> +	parent = <&bus_dmc>;
>  	status = "okay";
>  };
> 
> I'm not sure about continuing to use this method for new feature.
> If possible, hope to replace the existing binding style
> with new method like of_graph. Actually, I don't know the correct method.
> 
> 
> On 19. 9. 19. 오후 11:22, Artur Świgoń wrote:
> > From: Artur Świgoń <a.swigon@partner.samsung.com>
> > 
> > This patch adds interconnect functionality to the exynos-bus devfreq
> > driver.
> > 
> > The SoC topology is a graph (or, more specifically, a tree) and most of
> > its edges are taken from the devfreq parent-child hierarchy (cf.
> > Documentation/devicetree/bindings/devfreq/exynos-bus.txt). Due to
> > unspecified relative probing order, -EPROBE_DEFER may be propagated to
> > guarantee that a child is probed before its parent.
> > 
> > Each bus is now an interconnect provider and an interconnect node as well
> > (cf. Documentation/interconnect/interconnect.rst), i.e. every bus registers
> > itself as a node. Node IDs are not hardcoded but rather assigned at
> > runtime, in probing order (subject to the above-mentioned exception
> > regarding relative order). This approach allows for using this driver with
> > various Exynos SoCs.
> > 
> > Frequencies requested via the interconnect API for a given node are
> > propagated to devfreq using dev_pm_qos_update_request(). Please note that
> > it is not an error when CONFIG_INTERCONNECT is 'n', in which case all
> > interconnect API functions are no-op.
> > 
> > Signed-off-by: Artur Świgoń <a.swigon@partner.samsung.com>
> > ---
> >  drivers/devfreq/exynos-bus.c | 153 +++++++++++++++++++++++++++++++++++
> >  1 file changed, 153 insertions(+)
> > 
> > diff --git a/drivers/devfreq/exynos-bus.c b/drivers/devfreq/exynos-bus.c
> > index 8d44810cac69..e0232202720d 100644
> > --- a/drivers/devfreq/exynos-bus.c
> > +++ b/drivers/devfreq/exynos-bus.c
> > @@ -14,14 +14,19 @@
> >  #include <linux/devfreq-event.h>
> >  #include <linux/device.h>
> >  #include <linux/export.h>
> > +#include <linux/idr.h>
> > +#include <linux/interconnect-provider.h>
> >  #include <linux/module.h>
> >  #include <linux/of.h>
> >  #include <linux/pm_opp.h>
> > +#include <linux/pm_qos.h>
> >  #include <linux/platform_device.h>
> >  #include <linux/regulator/consumer.h>
> >  
> >  #define DEFAULT_SATURATION_RATIO	40
> >  
> > +#define icc_units_to_khz(x) ((x) / 8)
> > +
> >  struct exynos_bus {
> >  	struct device *dev;
> >  
> > @@ -35,6 +40,12 @@ struct exynos_bus {
> >  	struct opp_table *opp_table;
> >  	struct clk *clk;
> >  	unsigned int ratio;
> > +
> > +	/* One provider per bus, one node per provider */
> > +	struct icc_provider provider;
> > +	struct icc_node *node;
> > +
> > +	struct dev_pm_qos_request qos_req;
> >  };
> >  
> >  /*
> > @@ -59,6 +70,13 @@ exynos_bus_ops_edev(enable_edev);
> >  exynos_bus_ops_edev(disable_edev);
> >  exynos_bus_ops_edev(set_event);
> >  
> > +static int exynos_bus_next_id(void)
> > +{
> > +	static DEFINE_IDA(exynos_bus_icc_ida);
> > +
> > +	return ida_alloc(&exynos_bus_icc_ida, GFP_KERNEL);
> > +}
> > +
> >  static int exynos_bus_get_event(struct exynos_bus *bus,
> >  				struct devfreq_event_data *edata)
> >  {
> > @@ -171,6 +189,38 @@ static void exynos_bus_passive_exit(struct device *dev)
> >  	clk_disable_unprepare(bus->clk);
> >  }
> >  
> > +static int exynos_bus_icc_set(struct icc_node *src, struct icc_node *dst)
> > +{
> > +	struct exynos_bus *src_bus = src->data, *dst_bus = dst->data;
> > +	s32 src_freq = icc_units_to_khz(src->avg_bw);
> > +	s32 dst_freq = icc_units_to_khz(dst->avg_bw);
> > +
> > +	dev_pm_qos_update_request(&src_bus->qos_req, src_freq);
> > +	dev_pm_qos_update_request(&dst_bus->qos_req, dst_freq);
> > +
> > +	return 0;
> > +}
> > +
> > +static int exynos_bus_icc_aggregate(struct icc_node *node, u32 tag, u32 avg_bw,
> > +				    u32 peak_bw, u32 *agg_avg, u32 *agg_peak)
> > +{
> > +	*agg_avg += avg_bw;
> > +	*agg_peak = max(*agg_peak, peak_bw);
> > +
> > +	return 0;
> > +}
> > +
> > +static struct icc_node *exynos_bus_icc_xlate(struct of_phandle_args *spec,
> > +					     void *data)
> > +{
> > +	struct exynos_bus *bus = data;
> > +
> > +	if (spec->np != bus->dev->of_node)
> > +		return ERR_PTR(-EINVAL);
> > +
> > +	return bus->node;
> > +}
> > +
> >  static int exynos_bus_parent_parse_of(struct device_node *np,
> >  					struct exynos_bus *bus)
> >  {
> > @@ -366,6 +416,101 @@ static int exynos_bus_profile_init_passive(struct exynos_bus *bus,
> >  	return 0;
> >  }
> >  
> > +static int exynos_bus_icc_connect(struct exynos_bus *bus)
> > +{
> > +	struct device_node *np = bus->dev->of_node;
> > +	struct devfreq *parent_devfreq;
> > +	struct icc_node *parent_node = NULL;
> > +	struct of_phandle_args args;
> > +	int ret = 0;
> > +
> > +	parent_devfreq = devfreq_get_devfreq_by_phandle(bus->dev, 0);
> > +	if (!IS_ERR(parent_devfreq)) {
> > +		struct exynos_bus *parent_bus;
> > +
> > +		parent_bus = dev_get_drvdata(parent_devfreq->dev.parent);
> > +		parent_node = parent_bus->node;
> > +	} else {
> > +		/* Look for parent in DT */
> > +		int num = of_count_phandle_with_args(np, "parent",
> > +						     "#interconnect-cells");
> > +		if (num != 1)
> > +			goto out; /* 'parent' is optional */
> > +
> > +		ret = of_parse_phandle_with_args(np, "parent",
> > +						 "#interconnect-cells",
> > +						 0, &args);
> > +		if (ret < 0)
> > +			goto out;
> > +
> > +		of_node_put(args.np);
> > +
> > +		parent_node = of_icc_get_from_provider(&args);
> > +		if (IS_ERR(parent_node)) {
> > +			/* May be -EPROBE_DEFER */
> > +			ret = PTR_ERR(parent_node);
> > +			goto out;
> > +		}
> > +	}
> 
> 
> 
> > +
> > +	ret = icc_link_create(bus->node, parent_node->id);
> > +
> > +out:
> > +	return ret;
> > +}
> > +
> > +static int exynos_bus_icc_init(struct exynos_bus *bus)
> > +{
> > +	struct device *dev = bus->dev;
> > +	struct icc_provider *provider = &bus->provider;
> > +	struct icc_node *node;
> > +	int id, ret;
> > +
> > +	/* Initialize the interconnect provider */
> > +	provider->set = exynos_bus_icc_set;
> > +	provider->aggregate = exynos_bus_icc_aggregate;
> > +	provider->xlate = exynos_bus_icc_xlate;
> > +	provider->dev = dev;
> > +	provider->data = bus;
> > +
> > +	ret = icc_provider_add(provider);
> > +	if (ret < 0)
> > +		goto out;
> > +
> > +	ret = id = exynos_bus_next_id();
> > +	if (ret < 0)
> > +		goto err_node;
> > +
> > +	node = icc_node_create(id);
> > +	if (IS_ERR(node)) {
> > +		ret = PTR_ERR(node);
> > +		goto err_node;
> > +	}
> > +
> > +	bus->node = node;
> > +	node->name = dev->of_node->name;
> > +	node->data = bus;
> > +	icc_node_add(node, provider);
> > +
> > +	ret = exynos_bus_icc_connect(bus);
> > +	if (ret < 0)
> > +		goto err_connect;
> > +
> > +	ret = dev_pm_qos_add_request(bus->devfreq->dev.parent, &bus->qos_req,
> > +				     DEV_PM_QOS_MIN_FREQUENCY, 0);
> > +
> > +out:
> > +	return ret;
> > +
> > +err_connect:
> > +	icc_node_del(node);
> > +	icc_node_destroy(id);
> > +err_node:
> > +	icc_provider_del(provider);
> > +
> > +	return ret;
> > +}
> > +
> >  static int exynos_bus_probe(struct platform_device *pdev)
> >  {
> >  	struct device *dev = &pdev->dev;
> > @@ -415,6 +560,14 @@ static int exynos_bus_probe(struct platform_device *pdev)
> >  	if (ret < 0)
> >  		goto err;
> >  
> > +	/*
> > +	 * Initialize interconnect provider. A return value of -ENOTSUPP means
> > +	 * that CONFIG_INTERCONNECT is disabled.
> > +	 */
> > +	ret = exynos_bus_icc_init(bus);
> > +	if (ret < 0 && ret != -ENOTSUPP)
> > +		goto err;
> > +
> >  	max_state = bus->devfreq->profile->max_state;
> >  	min_freq = (bus->devfreq->profile->freq_table[0] / 1000);
> >  	max_freq = (bus->devfreq->profile->freq_table[max_state - 1] / 1000);
> > 
> 

Best regards,
-- 
Artur Świgoń
Samsung R&D Institute Poland
Samsung Electronics



^ permalink raw reply	[flat|nested] 41+ messages in thread

* Re: [RFC PATCH v2 09/11] devfreq: exynos-bus: Add interconnect functionality to exynos-bus
  2019-12-02 17:05         ` Artur Świgoń
@ 2019-12-05  2:36           ` Chanwoo Choi
  0 siblings, 0 replies; 41+ messages in thread
From: Chanwoo Choi @ 2019-12-05  2:36 UTC (permalink / raw)
  To: Artur Świgoń,
	devicetree, linux-arm-kernel, linux-samsung-soc, linux-kernel,
	linux-pm, dri-devel
  Cc: myungjoo.ham, inki.dae, sw0312.kim, georgi.djakov,
	leonard.crestez, m.szyprowski, b.zolnierkie, krzk

Hi Artur,

On 12/3/19 2:05 AM, Artur Świgoń wrote:
> Hi Chanwoo,
> 
> On Wed, 2019-09-25 at 16:03 +0900, Chanwoo Choi wrote:
>> Hi,
>>
>> I need the time to dig the ICC framework
>> to understand them detailed. After that, I'll review this.
> 
> Any updates on this topic?

I'm sorry for delaying the review of  this topic related to icc.
The review and merge of devfreq pm-qos feature will be finished over soon.
Because this series depends on the devfreq pm-qos feature

I'll dig into ICC related patches for exynos and imx[1].
[1] https://lore.kernel.org/linux-arm-kernel/008f2fa973b23fc716d678c5bd35af54@akkea.ca/T/
[PATCH RFC v6 0/9] interconnect: Add imx support via devfreq

> 
> Regardless of the purpose of this RFC, I think patches 01-04
> are still beneficial to devfreq. I can rebase and post them
> as a separate series if you wish.

Yes. please split out patch1-4 from this series
and send them based on linux-next.git separately.

> 
>> Basically, I agree this approach. But, I'm wondering
>> the existing binding method between 'bus_leftbus' and 'bus_dmc'.
>> From before, I thought that devfreq framework need to
>> enhance the binding method between parent devfreq device
>> and passive devfreq device instead of 'devfreq' property.
>>
>> On this patch, use the same binding way between
>> 'bus_leftbus' and 'bus_dmc' with 'parent' property
>> as following:
>>
>> +++ b/arch/arm/boot/dts/exynos4412-odroid-common.dtsi
>> @@ -106,6 +106,7 @@
>>  &bus_leftbus {
>>  	devfreq-events = <&ppmu_leftbus_3>, <&ppmu_rightbus_3>;
>>  	vdd-supply = <&buck3_reg>;
>> +	parent = <&bus_dmc>;
>>  	status = "okay";
>>  };
>>
>> I'm not sure about continuing to use this method for new feature.
>> If possible, hope to replace the existing binding style
>> with new method like of_graph. Actually, I don't know the correct method.
>>
>>
>> On 19. 9. 19. 오후 11:22, Artur Świgoń wrote:
>>> From: Artur Świgoń <a.swigon@partner.samsung.com>
>>>
>>> This patch adds interconnect functionality to the exynos-bus devfreq
>>> driver.
>>>
>>> The SoC topology is a graph (or, more specifically, a tree) and most of
>>> its edges are taken from the devfreq parent-child hierarchy (cf.
>>> Documentation/devicetree/bindings/devfreq/exynos-bus.txt). Due to
>>> unspecified relative probing order, -EPROBE_DEFER may be propagated to
>>> guarantee that a child is probed before its parent.
>>>
>>> Each bus is now an interconnect provider and an interconnect node as well
>>> (cf. Documentation/interconnect/interconnect.rst), i.e. every bus registers
>>> itself as a node. Node IDs are not hardcoded but rather assigned at
>>> runtime, in probing order (subject to the above-mentioned exception
>>> regarding relative order). This approach allows for using this driver with
>>> various Exynos SoCs.
>>>
>>> Frequencies requested via the interconnect API for a given node are
>>> propagated to devfreq using dev_pm_qos_update_request(). Please note that
>>> it is not an error when CONFIG_INTERCONNECT is 'n', in which case all
>>> interconnect API functions are no-op.
>>>
>>> Signed-off-by: Artur Świgoń <a.swigon@partner.samsung.com>
>>> ---
>>>  drivers/devfreq/exynos-bus.c | 153 +++++++++++++++++++++++++++++++++++
>>>  1 file changed, 153 insertions(+)
>>>
>>> diff --git a/drivers/devfreq/exynos-bus.c b/drivers/devfreq/exynos-bus.c
>>> index 8d44810cac69..e0232202720d 100644
>>> --- a/drivers/devfreq/exynos-bus.c
>>> +++ b/drivers/devfreq/exynos-bus.c
>>> @@ -14,14 +14,19 @@
>>>  #include <linux/devfreq-event.h>
>>>  #include <linux/device.h>
>>>  #include <linux/export.h>
>>> +#include <linux/idr.h>
>>> +#include <linux/interconnect-provider.h>
>>>  #include <linux/module.h>
>>>  #include <linux/of.h>
>>>  #include <linux/pm_opp.h>
>>> +#include <linux/pm_qos.h>
>>>  #include <linux/platform_device.h>
>>>  #include <linux/regulator/consumer.h>
>>>  
>>>  #define DEFAULT_SATURATION_RATIO	40
>>>  
>>> +#define icc_units_to_khz(x) ((x) / 8)
>>> +
>>>  struct exynos_bus {
>>>  	struct device *dev;
>>>  
>>> @@ -35,6 +40,12 @@ struct exynos_bus {
>>>  	struct opp_table *opp_table;
>>>  	struct clk *clk;
>>>  	unsigned int ratio;
>>> +
>>> +	/* One provider per bus, one node per provider */
>>> +	struct icc_provider provider;
>>> +	struct icc_node *node;
>>> +
>>> +	struct dev_pm_qos_request qos_req;
>>>  };
>>>  
>>>  /*
>>> @@ -59,6 +70,13 @@ exynos_bus_ops_edev(enable_edev);
>>>  exynos_bus_ops_edev(disable_edev);
>>>  exynos_bus_ops_edev(set_event);
>>>  
>>> +static int exynos_bus_next_id(void)
>>> +{
>>> +	static DEFINE_IDA(exynos_bus_icc_ida);
>>> +
>>> +	return ida_alloc(&exynos_bus_icc_ida, GFP_KERNEL);
>>> +}
>>> +
>>>  static int exynos_bus_get_event(struct exynos_bus *bus,
>>>  				struct devfreq_event_data *edata)
>>>  {
>>> @@ -171,6 +189,38 @@ static void exynos_bus_passive_exit(struct device *dev)
>>>  	clk_disable_unprepare(bus->clk);
>>>  }
>>>  
>>> +static int exynos_bus_icc_set(struct icc_node *src, struct icc_node *dst)
>>> +{
>>> +	struct exynos_bus *src_bus = src->data, *dst_bus = dst->data;
>>> +	s32 src_freq = icc_units_to_khz(src->avg_bw);
>>> +	s32 dst_freq = icc_units_to_khz(dst->avg_bw);
>>> +
>>> +	dev_pm_qos_update_request(&src_bus->qos_req, src_freq);
>>> +	dev_pm_qos_update_request(&dst_bus->qos_req, dst_freq);
>>> +
>>> +	return 0;
>>> +}
>>> +
>>> +static int exynos_bus_icc_aggregate(struct icc_node *node, u32 tag, u32 avg_bw,
>>> +				    u32 peak_bw, u32 *agg_avg, u32 *agg_peak)
>>> +{
>>> +	*agg_avg += avg_bw;
>>> +	*agg_peak = max(*agg_peak, peak_bw);
>>> +
>>> +	return 0;
>>> +}
>>> +
>>> +static struct icc_node *exynos_bus_icc_xlate(struct of_phandle_args *spec,
>>> +					     void *data)
>>> +{
>>> +	struct exynos_bus *bus = data;
>>> +
>>> +	if (spec->np != bus->dev->of_node)
>>> +		return ERR_PTR(-EINVAL);
>>> +
>>> +	return bus->node;
>>> +}
>>> +
>>>  static int exynos_bus_parent_parse_of(struct device_node *np,
>>>  					struct exynos_bus *bus)
>>>  {
>>> @@ -366,6 +416,101 @@ static int exynos_bus_profile_init_passive(struct exynos_bus *bus,
>>>  	return 0;
>>>  }
>>>  
>>> +static int exynos_bus_icc_connect(struct exynos_bus *bus)
>>> +{
>>> +	struct device_node *np = bus->dev->of_node;
>>> +	struct devfreq *parent_devfreq;
>>> +	struct icc_node *parent_node = NULL;
>>> +	struct of_phandle_args args;
>>> +	int ret = 0;
>>> +
>>> +	parent_devfreq = devfreq_get_devfreq_by_phandle(bus->dev, 0);
>>> +	if (!IS_ERR(parent_devfreq)) {
>>> +		struct exynos_bus *parent_bus;
>>> +
>>> +		parent_bus = dev_get_drvdata(parent_devfreq->dev.parent);
>>> +		parent_node = parent_bus->node;
>>> +	} else {
>>> +		/* Look for parent in DT */
>>> +		int num = of_count_phandle_with_args(np, "parent",
>>> +						     "#interconnect-cells");
>>> +		if (num != 1)
>>> +			goto out; /* 'parent' is optional */
>>> +
>>> +		ret = of_parse_phandle_with_args(np, "parent",
>>> +						 "#interconnect-cells",
>>> +						 0, &args);
>>> +		if (ret < 0)
>>> +			goto out;
>>> +
>>> +		of_node_put(args.np);
>>> +
>>> +		parent_node = of_icc_get_from_provider(&args);
>>> +		if (IS_ERR(parent_node)) {
>>> +			/* May be -EPROBE_DEFER */
>>> +			ret = PTR_ERR(parent_node);
>>> +			goto out;
>>> +		}
>>> +	}
>>
>>
>>
>>> +
>>> +	ret = icc_link_create(bus->node, parent_node->id);
>>> +
>>> +out:
>>> +	return ret;
>>> +}
>>> +
>>> +static int exynos_bus_icc_init(struct exynos_bus *bus)
>>> +{
>>> +	struct device *dev = bus->dev;
>>> +	struct icc_provider *provider = &bus->provider;
>>> +	struct icc_node *node;
>>> +	int id, ret;
>>> +
>>> +	/* Initialize the interconnect provider */
>>> +	provider->set = exynos_bus_icc_set;
>>> +	provider->aggregate = exynos_bus_icc_aggregate;
>>> +	provider->xlate = exynos_bus_icc_xlate;
>>> +	provider->dev = dev;
>>> +	provider->data = bus;
>>> +
>>> +	ret = icc_provider_add(provider);
>>> +	if (ret < 0)
>>> +		goto out;
>>> +
>>> +	ret = id = exynos_bus_next_id();
>>> +	if (ret < 0)
>>> +		goto err_node;
>>> +
>>> +	node = icc_node_create(id);
>>> +	if (IS_ERR(node)) {
>>> +		ret = PTR_ERR(node);
>>> +		goto err_node;
>>> +	}
>>> +
>>> +	bus->node = node;
>>> +	node->name = dev->of_node->name;
>>> +	node->data = bus;
>>> +	icc_node_add(node, provider);
>>> +
>>> +	ret = exynos_bus_icc_connect(bus);
>>> +	if (ret < 0)
>>> +		goto err_connect;
>>> +
>>> +	ret = dev_pm_qos_add_request(bus->devfreq->dev.parent, &bus->qos_req,
>>> +				     DEV_PM_QOS_MIN_FREQUENCY, 0);
>>> +
>>> +out:
>>> +	return ret;
>>> +
>>> +err_connect:
>>> +	icc_node_del(node);
>>> +	icc_node_destroy(id);
>>> +err_node:
>>> +	icc_provider_del(provider);
>>> +
>>> +	return ret;
>>> +}
>>> +
>>>  static int exynos_bus_probe(struct platform_device *pdev)
>>>  {
>>>  	struct device *dev = &pdev->dev;
>>> @@ -415,6 +560,14 @@ static int exynos_bus_probe(struct platform_device *pdev)
>>>  	if (ret < 0)
>>>  		goto err;
>>>  
>>> +	/*
>>> +	 * Initialize interconnect provider. A return value of -ENOTSUPP means
>>> +	 * that CONFIG_INTERCONNECT is disabled.
>>> +	 */
>>> +	ret = exynos_bus_icc_init(bus);
>>> +	if (ret < 0 && ret != -ENOTSUPP)
>>> +		goto err;
>>> +
>>>  	max_state = bus->devfreq->profile->max_state;
>>>  	min_freq = (bus->devfreq->profile->freq_table[0] / 1000);
>>>  	max_freq = (bus->devfreq->profile->freq_table[max_state - 1] / 1000);
>>>
>>
> 
> Best regards,
> 


-- 
Best Regards,
Chanwoo Choi
Samsung Electronics

^ permalink raw reply	[flat|nested] 41+ messages in thread

* Re: [RFC PATCH v2 09/11] devfreq: exynos-bus: Add interconnect functionality to exynos-bus
  2019-09-19 14:22     ` [RFC PATCH v2 09/11] devfreq: exynos-bus: Add interconnect functionality to exynos-bus Artur Świgoń
  2019-09-25  7:03       ` Chanwoo Choi
@ 2019-12-16  0:44       ` Chanwoo Choi
  2019-12-18 10:18         ` Artur Świgoń
  1 sibling, 1 reply; 41+ messages in thread
From: Chanwoo Choi @ 2019-12-16  0:44 UTC (permalink / raw)
  To: Artur Świgoń,
	devicetree, linux-arm-kernel, linux-samsung-soc, linux-kernel,
	linux-pm, dri-devel
  Cc: myungjoo.ham, inki.dae, sw0312.kim, georgi.djakov,
	leonard.crestez, m.szyprowski, b.zolnierkie, krzk

Hi,

On 9/19/19 11:22 PM, Artur Świgoń wrote:
> From: Artur Świgoń <a.swigon@partner.samsung.com>
> 
> This patch adds interconnect functionality to the exynos-bus devfreq
> driver.
> 
> The SoC topology is a graph (or, more specifically, a tree) and most of
> its edges are taken from the devfreq parent-child hierarchy (cf.
> Documentation/devicetree/bindings/devfreq/exynos-bus.txt). Due to
> unspecified relative probing order, -EPROBE_DEFER may be propagated to
> guarantee that a child is probed before its parent.
> 
> Each bus is now an interconnect provider and an interconnect node as well
> (cf. Documentation/interconnect/interconnect.rst), i.e. every bus registers
> itself as a node. Node IDs are not hardcoded but rather assigned at
> runtime, in probing order (subject to the above-mentioned exception
> regarding relative order). This approach allows for using this driver with
> various Exynos SoCs.
> 
> Frequencies requested via the interconnect API for a given node are
> propagated to devfreq using dev_pm_qos_update_request(). Please note that
> it is not an error when CONFIG_INTERCONNECT is 'n', in which case all
> interconnect API functions are no-op.
> 
> Signed-off-by: Artur Świgoń <a.swigon@partner.samsung.com>
> ---
>  drivers/devfreq/exynos-bus.c | 153 +++++++++++++++++++++++++++++++++++
>  1 file changed, 153 insertions(+)
> 
> diff --git a/drivers/devfreq/exynos-bus.c b/drivers/devfreq/exynos-bus.c
> index 8d44810cac69..e0232202720d 100644
> --- a/drivers/devfreq/exynos-bus.c
> +++ b/drivers/devfreq/exynos-bus.c
> @@ -14,14 +14,19 @@
>  #include <linux/devfreq-event.h>
>  #include <linux/device.h>
>  #include <linux/export.h>
> +#include <linux/idr.h>
> +#include <linux/interconnect-provider.h>
>  #include <linux/module.h>
>  #include <linux/of.h>
>  #include <linux/pm_opp.h>
> +#include <linux/pm_qos.h>
>  #include <linux/platform_device.h>
>  #include <linux/regulator/consumer.h>
>  
>  #define DEFAULT_SATURATION_RATIO	40
>  
> +#define icc_units_to_khz(x) ((x) / 8)

icc_units_to_khz() -> kpbs_to_khz()

> +
>  struct exynos_bus {
>  	struct device *dev;
>  
> @@ -35,6 +40,12 @@ struct exynos_bus {
>  	struct opp_table *opp_table;
>  	struct clk *clk;
>  	unsigned int ratio;
> +
> +	/* One provider per bus, one node per provider */
> +	struct icc_provider provider;
> +	struct icc_node *node;
> +
> +	struct dev_pm_qos_request qos_req;
>  };
>  
>  /*
> @@ -59,6 +70,13 @@ exynos_bus_ops_edev(enable_edev);
>  exynos_bus_ops_edev(disable_edev);
>  exynos_bus_ops_edev(set_event);
>  
> +static int exynos_bus_next_id(void)
> +{
> +	static DEFINE_IDA(exynos_bus_icc_ida);
> +
> +	return ida_alloc(&exynos_bus_icc_ida, GFP_KERNEL);
> +}
> +
>  static int exynos_bus_get_event(struct exynos_bus *bus,
>  				struct devfreq_event_data *edata)
>  {
> @@ -171,6 +189,38 @@ static void exynos_bus_passive_exit(struct device *dev)
>  	clk_disable_unprepare(bus->clk);
>  }
>  
> +static int exynos_bus_icc_set(struct icc_node *src, struct icc_node *dst)
> +{
> +	struct exynos_bus *src_bus = src->data, *dst_bus = dst->data;
> +	s32 src_freq = icc_units_to_khz(src->avg_bw);
> +	s32 dst_freq = icc_units_to_khz(dst->avg_bw);
> +
> +	dev_pm_qos_update_request(&src_bus->qos_req, src_freq);

Have to check the return value.
If return error, show the waring with dev_warn.

> +	dev_pm_qos_update_request(&dst_bus->qos_req, dst_freq);

ditto.

> +
> +	return 0;
> +}
> +
> +static int exynos_bus_icc_aggregate(struct icc_node *node, u32 tag, u32 avg_bw,
> +				    u32 peak_bw, u32 *agg_avg, u32 *agg_peak)
> +{
> +	*agg_avg += avg_bw;
> +	*agg_peak = max(*agg_peak, peak_bw);
> +
> +	return 0;
> +}
> +
> +static struct icc_node *exynos_bus_icc_xlate(struct of_phandle_args *spec,
> +					     void *data)
> +{
> +	struct exynos_bus *bus = data;
> +
> +	if (spec->np != bus->dev->of_node)
> +		return ERR_PTR(-EINVAL);
> +
> +	return bus->node;
> +}
> +
>  static int exynos_bus_parent_parse_of(struct device_node *np,
>  					struct exynos_bus *bus)
>  {
> @@ -366,6 +416,101 @@ static int exynos_bus_profile_init_passive(struct exynos_bus *bus,
>  	return 0;
>  }
>  
> +static int exynos_bus_icc_connect(struct exynos_bus *bus)
> +{
> +	struct device_node *np = bus->dev->of_node;
> +	struct devfreq *parent_devfreq;
> +	struct icc_node *parent_node = NULL;
> +	struct of_phandle_args args;
> +	int ret = 0;
> +
> +	parent_devfreq = devfreq_get_devfreq_by_phandle(bus->dev, 0);
> +	if (!IS_ERR(parent_devfreq)) {
> +		struct exynos_bus *parent_bus;
> +
> +		parent_bus = dev_get_drvdata(parent_devfreq->dev.parent);
> +		parent_node = parent_bus->node;
> +	} else {
> +		/* Look for parent in DT */
> +		int num = of_count_phandle_with_args(np, "parent",
> +						     "#interconnect-cells");
> +		if (num != 1)
> +			goto out; /* 'parent' is optional */
> +
> +		ret = of_parse_phandle_with_args(np, "parent",
> +						 "#interconnect-cells",
> +						 0, &args);


Actually, I agree your approach. I think that it is very useful
and necessary to guarantee the PM QoS requirements between devices.

But,
As I already commented, I'm not sure that the "parent" property 
is proper for only this driver. If possible, you better to get
the parent phandle through other way like OF graph.

If you suggest the standard way to make the tree between
the exynos-bus, I'll agree.

Also, for interconnect path, you have to add the connection
between 'bus_display' and 'bus_leftbus' regardless
of the existing 'devfreq' property.
- bus_display - bus_leftbus - bus_dmc

> +		if (ret < 0)
> +			goto out;
> +
> +		of_node_put(args.np);
> +
> +		parent_node = of_icc_get_from_provider(&args);
> +		if (IS_ERR(parent_node)) {
> +			/* May be -EPROBE_DEFER */
> +			ret = PTR_ERR(parent_node);
> +			goto out;
> +		}
> +	}
> +
> +	ret = icc_link_create(bus->node, parent_node->id);
> +
> +out:
> +	return ret;
> +}
> +
> +static int exynos_bus_icc_init(struct exynos_bus *bus)
> +{
> +	struct device *dev = bus->dev;
> +	struct icc_provider *provider = &bus->provider;
> +	struct icc_node *node;
> +	int id, ret;
> +
> +	/* Initialize the interconnect provider */
> +	provider->set = exynos_bus_icc_set;
> +	provider->aggregate = exynos_bus_icc_aggregate;
> +	provider->xlate = exynos_bus_icc_xlate;
> +	provider->dev = dev;
> +	provider->data = bus;
> +
> +	ret = icc_provider_add(provider);
> +	if (ret < 0)
> +		goto out;

Return error without goto because there is no any requirement
to free the resource before.

> +
> +	ret = id = exynos_bus_next_id();
> +	if (ret < 0)
> +		goto err_node;
> +
> +	node = icc_node_create(id);
> +	if (IS_ERR(node)) {
> +		ret = PTR_ERR(node);
> +		goto err_node;
> +	}
> +
> +	bus->node = node;
> +	node->name = dev->of_node->name;
> +	node->data = bus;
> +	icc_node_add(node, provider);
> +
> +	ret = exynos_bus_icc_connect(bus);
> +	if (ret < 0)
> +		goto err_connect;
> +
> +	ret = dev_pm_qos_add_request(bus->devfreq->dev.parent, &bus->qos_req,

Check whether this line is over 80 char.

> +				     DEV_PM_QOS_MIN_FREQUENCY, 0);

	Check the return value.

> +
> +out:

Remove this goto due to not necessary.

> +	return ret;

	return 0;

> +
> +err_connect:
> +	icc_node_del(node);
> +	icc_node_destroy(id);
> +err_node:
> +	icc_provider_del(provider);
> +
> +	return ret;
> +}
> +
>  static int exynos_bus_probe(struct platform_device *pdev)
>  {
>  	struct device *dev = &pdev->dev;
> @@ -415,6 +560,14 @@ static int exynos_bus_probe(struct platform_device *pdev)
>  	if (ret < 0)
>  		goto err;
>  
> +	/*
> +	 * Initialize interconnect provider. A return value of -ENOTSUPP means
> +	 * that CONFIG_INTERCONNECT is disabled.
> +	 */
> +	ret = exynos_bus_icc_init(bus);
> +	if (ret < 0 && ret != -ENOTSUPP)
> +		goto err;

Print error message.
	dev_err(dev, "failed to initialize the interconnect provider");

> +
>  	max_state = bus->devfreq->profile->max_state;
>  	min_freq = (bus->devfreq->profile->freq_table[0] / 1000);
>  	max_freq = (bus->devfreq->profile->freq_table[max_state - 1] / 1000);
> 


-- 
Best Regards,
Chanwoo Choi
Samsung Electronics

^ permalink raw reply	[flat|nested] 41+ messages in thread

* Re: [RFC PATCH v2 08/11] arm: dts: exynos: Add parents and #interconnect-cells to Exynos4412
  2019-09-19 14:22     ` [RFC PATCH v2 08/11] arm: dts: exynos: Add parents and #interconnect-cells to Exynos4412 Artur Świgoń
@ 2019-12-16  0:51       ` Chanwoo Choi
  2019-12-16  2:59         ` Chanwoo Choi
  2019-12-16  0:55       ` Chanwoo Choi
  1 sibling, 1 reply; 41+ messages in thread
From: Chanwoo Choi @ 2019-12-16  0:51 UTC (permalink / raw)
  To: Artur Świgoń,
	devicetree, linux-arm-kernel, linux-samsung-soc, linux-kernel,
	linux-pm, dri-devel
  Cc: myungjoo.ham, inki.dae, sw0312.kim, georgi.djakov,
	leonard.crestez, m.szyprowski, b.zolnierkie, krzk

On 9/19/19 11:22 PM, Artur Świgoń wrote:
> From: Artur Świgoń <a.swigon@partner.samsung.com>
> 
> This patch adds two fields to the Exynos4412 DTS:
>   - parent: to declare connections between nodes that are not in a
>     parent-child relation in devfreq;
>   - #interconnect-cells: required by the interconnect framework.
> 
> Please note that #interconnect-cells is always zero and node IDs are not
> hardcoded anywhere. The above-mentioned parent-child relation in devfreq
> means that there is a shared power line ('devfreq' property). The 'parent'
> property only signifies an interconnect connection.
> 
> Signed-off-by: Artur Świgoń <a.swigon@partner.samsung.com>
> ---
>  arch/arm/boot/dts/exynos4412-odroid-common.dtsi | 1 +
>  arch/arm/boot/dts/exynos4412.dtsi               | 9 +++++++++
>  2 files changed, 10 insertions(+)
> 
> diff --git a/arch/arm/boot/dts/exynos4412-odroid-common.dtsi b/arch/arm/boot/dts/exynos4412-odroid-common.dtsi
> index ea55f377d17c..bdd61ae86103 100644
> --- a/arch/arm/boot/dts/exynos4412-odroid-common.dtsi
> +++ b/arch/arm/boot/dts/exynos4412-odroid-common.dtsi
> @@ -106,6 +106,7 @@
>  &bus_leftbus {
>  	devfreq-events = <&ppmu_leftbus_3>, <&ppmu_rightbus_3>;
>  	vdd-supply = <&buck3_reg>;
> +	parent = <&bus_dmc>;

As I mentioned on other reply,
I'm not sure to use the specific 'parent' property to make
the connection between buses. If possible, you better to
use the standard way like OF graph. Except for making
the connection between buses by 'parent' property,
looks good to me.


>  	status = "okay";
>  };
>  
> diff --git a/arch/arm/boot/dts/exynos4412.dtsi b/arch/arm/boot/dts/exynos4412.dtsi
> index d20db2dfe8e2..a70a671acacd 100644
> --- a/arch/arm/boot/dts/exynos4412.dtsi
> +++ b/arch/arm/boot/dts/exynos4412.dtsi
> @@ -390,6 +390,7 @@
>  			clocks = <&clock CLK_DIV_DMC>;
>  			clock-names = "bus";
>  			operating-points-v2 = <&bus_dmc_opp_table>;
> +			#interconnect-cells = <0>;
>  			status = "disabled";
>  		};
>  
> @@ -398,6 +399,7 @@
>  			clocks = <&clock CLK_DIV_ACP>;
>  			clock-names = "bus";
>  			operating-points-v2 = <&bus_acp_opp_table>;
> +			#interconnect-cells = <0>;
>  			status = "disabled";
>  		};
>  
> @@ -406,6 +408,7 @@
>  			clocks = <&clock CLK_DIV_C2C>;
>  			clock-names = "bus";
>  			operating-points-v2 = <&bus_dmc_opp_table>;
> +			#interconnect-cells = <0>;
>  			status = "disabled";
>  		};
>  
> @@ -459,6 +462,7 @@
>  			clocks = <&clock CLK_DIV_GDL>;
>  			clock-names = "bus";
>  			operating-points-v2 = <&bus_leftbus_opp_table>;
> +			#interconnect-cells = <0>;
>  			status = "disabled";
>  		};
>  
> @@ -467,6 +471,7 @@
>  			clocks = <&clock CLK_DIV_GDR>;
>  			clock-names = "bus";
>  			operating-points-v2 = <&bus_leftbus_opp_table>;
> +			#interconnect-cells = <0>;
>  			status = "disabled";
>  		};
>  
> @@ -475,6 +480,7 @@
>  			clocks = <&clock CLK_ACLK160>;
>  			clock-names = "bus";
>  			operating-points-v2 = <&bus_display_opp_table>;
> +			#interconnect-cells = <0>;
>  			status = "disabled";
>  		};
>  
> @@ -483,6 +489,7 @@
>  			clocks = <&clock CLK_ACLK133>;
>  			clock-names = "bus";
>  			operating-points-v2 = <&bus_fsys_opp_table>;
> +			#interconnect-cells = <0>;
>  			status = "disabled";
>  		};
>  
> @@ -491,6 +498,7 @@
>  			clocks = <&clock CLK_ACLK100>;
>  			clock-names = "bus";
>  			operating-points-v2 = <&bus_peri_opp_table>;
> +			#interconnect-cells = <0>;
>  			status = "disabled";
>  		};
>  
> @@ -499,6 +507,7 @@
>  			clocks = <&clock CLK_SCLK_MFC>;
>  			clock-names = "bus";
>  			operating-points-v2 = <&bus_leftbus_opp_table>;
> +			#interconnect-cells = <0>;
>  			status = "disabled";
>  		};
>  
> 


-- 
Best Regards,
Chanwoo Choi
Samsung Electronics

^ permalink raw reply	[flat|nested] 41+ messages in thread

* Re: [RFC PATCH v2 08/11] arm: dts: exynos: Add parents and #interconnect-cells to Exynos4412
  2019-09-19 14:22     ` [RFC PATCH v2 08/11] arm: dts: exynos: Add parents and #interconnect-cells to Exynos4412 Artur Świgoń
  2019-12-16  0:51       ` Chanwoo Choi
@ 2019-12-16  0:55       ` Chanwoo Choi
  2019-12-16  0:57         ` Chanwoo Choi
  1 sibling, 1 reply; 41+ messages in thread
From: Chanwoo Choi @ 2019-12-16  0:55 UTC (permalink / raw)
  To: Artur Świgoń,
	devicetree, linux-arm-kernel, linux-samsung-soc, linux-kernel,
	linux-pm, dri-devel
  Cc: myungjoo.ham, inki.dae, sw0312.kim, georgi.djakov,
	leonard.crestez, m.szyprowski, b.zolnierkie, krzk

Hi,

On 9/19/19 11:22 PM, Artur Świgoń wrote:
> From: Artur Świgoń <a.swigon@partner.samsung.com>
> 
> This patch adds two fields to the Exynos4412 DTS:
>   - parent: to declare connections between nodes that are not in a
>     parent-child relation in devfreq;
>   - #interconnect-cells: required by the interconnect framework.
> 
> Please note that #interconnect-cells is always zero and node IDs are not
> hardcoded anywhere. The above-mentioned parent-child relation in devfreq
> means that there is a shared power line ('devfreq' property). The 'parent'
> property only signifies an interconnect connection.
> 
> Signed-off-by: Artur Świgoń <a.swigon@partner.samsung.com>
> ---
>  arch/arm/boot/dts/exynos4412-odroid-common.dtsi | 1 +
>  arch/arm/boot/dts/exynos4412.dtsi               | 9 +++++++++
>  2 files changed, 10 insertions(+)
> 
> diff --git a/arch/arm/boot/dts/exynos4412-odroid-common.dtsi b/arch/arm/boot/dts/exynos4412-odroid-common.dtsi
> index ea55f377d17c..bdd61ae86103 100644
> --- a/arch/arm/boot/dts/exynos4412-odroid-common.dtsi
> +++ b/arch/arm/boot/dts/exynos4412-odroid-common.dtsi
> @@ -106,6 +106,7 @@
>  &bus_leftbus {
>  	devfreq-events = <&ppmu_leftbus_3>, <&ppmu_rightbus_3>;
>  	vdd-supply = <&buck3_reg>;
> +	parent = <&bus_dmc>;

As I mentioned on other patch,
I'm not sure to use 'parent' property for this driver.
If possible, we better to use the standard way like OF graph
in order to make the tree between buses. Except for making
the connection between the buses with 'parent', looks good to me.

>  	status = "okay";
>  };
>  
> diff --git a/arch/arm/boot/dts/exynos4412.dtsi b/arch/arm/boot/dts/exynos4412.dtsi
> index d20db2dfe8e2..a70a671acacd 100644
> --- a/arch/arm/boot/dts/exynos4412.dtsi
> +++ b/arch/arm/boot/dts/exynos4412.dtsi
> @@ -390,6 +390,7 @@
>  			clocks = <&clock CLK_DIV_DMC>;
>  			clock-names = "bus";
>  			operating-points-v2 = <&bus_dmc_opp_table>;
> +			#interconnect-cells = <0>;
>  			status = "disabled";
>  		};
>  
> @@ -398,6 +399,7 @@
>  			clocks = <&clock CLK_DIV_ACP>;
>  			clock-names = "bus";
>  			operating-points-v2 = <&bus_acp_opp_table>;
> +			#interconnect-cells = <0>;
>  			status = "disabled";
>  		};
>  
> @@ -406,6 +408,7 @@
>  			clocks = <&clock CLK_DIV_C2C>;
>  			clock-names = "bus";
>  			operating-points-v2 = <&bus_dmc_opp_table>;
> +			#interconnect-cells = <0>;
>  			status = "disabled";
>  		};
>  
> @@ -459,6 +462,7 @@
>  			clocks = <&clock CLK_DIV_GDL>;
>  			clock-names = "bus";
>  			operating-points-v2 = <&bus_leftbus_opp_table>;
> +			#interconnect-cells = <0>;
>  			status = "disabled";
>  		};
>  
> @@ -467,6 +471,7 @@
>  			clocks = <&clock CLK_DIV_GDR>;
>  			clock-names = "bus";
>  			operating-points-v2 = <&bus_leftbus_opp_table>;
> +			#interconnect-cells = <0>;
>  			status = "disabled";
>  		};
>  
> @@ -475,6 +480,7 @@
>  			clocks = <&clock CLK_ACLK160>;
>  			clock-names = "bus";
>  			operating-points-v2 = <&bus_display_opp_table>;
> +			#interconnect-cells = <0>;
>  			status = "disabled";
>  		};
>  
> @@ -483,6 +489,7 @@
>  			clocks = <&clock CLK_ACLK133>;
>  			clock-names = "bus";
>  			operating-points-v2 = <&bus_fsys_opp_table>;
> +			#interconnect-cells = <0>;
>  			status = "disabled";
>  		};
>  
> @@ -491,6 +498,7 @@
>  			clocks = <&clock CLK_ACLK100>;
>  			clock-names = "bus";
>  			operating-points-v2 = <&bus_peri_opp_table>;
> +			#interconnect-cells = <0>;
>  			status = "disabled";
>  		};
>  
> @@ -499,6 +507,7 @@
>  			clocks = <&clock CLK_SCLK_MFC>;
>  			clock-names = "bus";
>  			operating-points-v2 = <&bus_leftbus_opp_table>;
> +			#interconnect-cells = <0>;
>  			status = "disabled";
>  		};
>  
> 


-- 
Best Regards,
Chanwoo Choi
Samsung Electronics

^ permalink raw reply	[flat|nested] 41+ messages in thread

* Re: [RFC PATCH v2 08/11] arm: dts: exynos: Add parents and #interconnect-cells to Exynos4412
  2019-12-16  0:55       ` Chanwoo Choi
@ 2019-12-16  0:57         ` Chanwoo Choi
  0 siblings, 0 replies; 41+ messages in thread
From: Chanwoo Choi @ 2019-12-16  0:57 UTC (permalink / raw)
  To: Artur Świgoń,
	devicetree, linux-arm-kernel, linux-samsung-soc, linux-kernel,
	linux-pm, dri-devel
  Cc: myungjoo.ham, inki.dae, sw0312.kim, georgi.djakov,
	leonard.crestez, m.szyprowski, b.zolnierkie, krzk

Hi,

Please ignore second reply. It is my mistake
to send the duplicate message because of my company firewall issue.

Regards,
Chanwoo Choi

On 12/16/19 9:55 AM, Chanwoo Choi wrote:
> Hi,
> 
> On 9/19/19 11:22 PM, Artur Świgoń wrote:
>> From: Artur Świgoń <a.swigon@partner.samsung.com>
>>
>> This patch adds two fields to the Exynos4412 DTS:
>>   - parent: to declare connections between nodes that are not in a
>>     parent-child relation in devfreq;
>>   - #interconnect-cells: required by the interconnect framework.
>>
>> Please note that #interconnect-cells is always zero and node IDs are not
>> hardcoded anywhere. The above-mentioned parent-child relation in devfreq
>> means that there is a shared power line ('devfreq' property). The 'parent'
>> property only signifies an interconnect connection.
>>
>> Signed-off-by: Artur Świgoń <a.swigon@partner.samsung.com>
>> ---
>>  arch/arm/boot/dts/exynos4412-odroid-common.dtsi | 1 +
>>  arch/arm/boot/dts/exynos4412.dtsi               | 9 +++++++++
>>  2 files changed, 10 insertions(+)
>>
>> diff --git a/arch/arm/boot/dts/exynos4412-odroid-common.dtsi b/arch/arm/boot/dts/exynos4412-odroid-common.dtsi
>> index ea55f377d17c..bdd61ae86103 100644
>> --- a/arch/arm/boot/dts/exynos4412-odroid-common.dtsi
>> +++ b/arch/arm/boot/dts/exynos4412-odroid-common.dtsi
>> @@ -106,6 +106,7 @@
>>  &bus_leftbus {
>>  	devfreq-events = <&ppmu_leftbus_3>, <&ppmu_rightbus_3>;
>>  	vdd-supply = <&buck3_reg>;
>> +	parent = <&bus_dmc>;
> 
> As I mentioned on other patch,
> I'm not sure to use 'parent' property for this driver.
> If possible, we better to use the standard way like OF graph
> in order to make the tree between buses. Except for making
> the connection between the buses with 'parent', looks good to me.
> 
>>  	status = "okay";
>>  };
>>  
>> diff --git a/arch/arm/boot/dts/exynos4412.dtsi b/arch/arm/boot/dts/exynos4412.dtsi
>> index d20db2dfe8e2..a70a671acacd 100644
>> --- a/arch/arm/boot/dts/exynos4412.dtsi
>> +++ b/arch/arm/boot/dts/exynos4412.dtsi
>> @@ -390,6 +390,7 @@
>>  			clocks = <&clock CLK_DIV_DMC>;
>>  			clock-names = "bus";
>>  			operating-points-v2 = <&bus_dmc_opp_table>;
>> +			#interconnect-cells = <0>;
>>  			status = "disabled";
>>  		};
>>  
>> @@ -398,6 +399,7 @@
>>  			clocks = <&clock CLK_DIV_ACP>;
>>  			clock-names = "bus";
>>  			operating-points-v2 = <&bus_acp_opp_table>;
>> +			#interconnect-cells = <0>;
>>  			status = "disabled";
>>  		};
>>  
>> @@ -406,6 +408,7 @@
>>  			clocks = <&clock CLK_DIV_C2C>;
>>  			clock-names = "bus";
>>  			operating-points-v2 = <&bus_dmc_opp_table>;
>> +			#interconnect-cells = <0>;
>>  			status = "disabled";
>>  		};
>>  
>> @@ -459,6 +462,7 @@
>>  			clocks = <&clock CLK_DIV_GDL>;
>>  			clock-names = "bus";
>>  			operating-points-v2 = <&bus_leftbus_opp_table>;
>> +			#interconnect-cells = <0>;
>>  			status = "disabled";
>>  		};
>>  
>> @@ -467,6 +471,7 @@
>>  			clocks = <&clock CLK_DIV_GDR>;
>>  			clock-names = "bus";
>>  			operating-points-v2 = <&bus_leftbus_opp_table>;
>> +			#interconnect-cells = <0>;
>>  			status = "disabled";
>>  		};
>>  
>> @@ -475,6 +480,7 @@
>>  			clocks = <&clock CLK_ACLK160>;
>>  			clock-names = "bus";
>>  			operating-points-v2 = <&bus_display_opp_table>;
>> +			#interconnect-cells = <0>;
>>  			status = "disabled";
>>  		};
>>  
>> @@ -483,6 +489,7 @@
>>  			clocks = <&clock CLK_ACLK133>;
>>  			clock-names = "bus";
>>  			operating-points-v2 = <&bus_fsys_opp_table>;
>> +			#interconnect-cells = <0>;
>>  			status = "disabled";
>>  		};
>>  
>> @@ -491,6 +498,7 @@
>>  			clocks = <&clock CLK_ACLK100>;
>>  			clock-names = "bus";
>>  			operating-points-v2 = <&bus_peri_opp_table>;
>> +			#interconnect-cells = <0>;
>>  			status = "disabled";
>>  		};
>>  
>> @@ -499,6 +507,7 @@
>>  			clocks = <&clock CLK_SCLK_MFC>;
>>  			clock-names = "bus";
>>  			operating-points-v2 = <&bus_leftbus_opp_table>;
>> +			#interconnect-cells = <0>;
>>  			status = "disabled";
>>  		};
>>  
>>
> 
> 

^ permalink raw reply	[flat|nested] 41+ messages in thread

* Re: [RFC PATCH v2 05/11] interconnect: Export of_icc_get_from_provider()
  2019-09-19 14:22     ` [RFC PATCH v2 05/11] interconnect: Export of_icc_get_from_provider() Artur Świgoń
@ 2019-12-16  0:57       ` Chanwoo Choi
  0 siblings, 0 replies; 41+ messages in thread
From: Chanwoo Choi @ 2019-12-16  0:57 UTC (permalink / raw)
  To: Artur Świgoń,
	devicetree, linux-arm-kernel, linux-samsung-soc, linux-kernel,
	linux-pm, dri-devel
  Cc: myungjoo.ham, inki.dae, sw0312.kim, georgi.djakov,
	leonard.crestez, m.szyprowski, b.zolnierkie, krzk

On 9/19/19 11:22 PM, Artur Świgoń wrote:
> From: Artur Świgoń <a.swigon@partner.samsung.com>
> 
> This patch makes the above function public (for use in exynos-bus devfreq
> driver).
> 
> Signed-off-by: Artur Świgoń <a.swigon@partner.samsung.com>
> Reviewed-by: Krzysztof Kozlowski <krzk@kernel.org>
> ---
>  drivers/interconnect/core.c           | 3 ++-
>  include/linux/interconnect-provider.h | 6 ++++++
>  2 files changed, 8 insertions(+), 1 deletion(-)
> 
> diff --git a/drivers/interconnect/core.c b/drivers/interconnect/core.c
> index 7b971228df38..95850700e367 100644
> --- a/drivers/interconnect/core.c
> +++ b/drivers/interconnect/core.c
> @@ -279,7 +279,7 @@ EXPORT_SYMBOL_GPL(of_icc_xlate_onecell);
>   * Returns a valid pointer to struct icc_node on success or ERR_PTR()
>   * on failure.
>   */
> -static struct icc_node *of_icc_get_from_provider(struct of_phandle_args *spec)
> +struct icc_node *of_icc_get_from_provider(struct of_phandle_args *spec)
>  {
>  	struct icc_node *node = ERR_PTR(-EPROBE_DEFER);
>  	struct icc_provider *provider;
> @@ -298,6 +298,7 @@ static struct icc_node *of_icc_get_from_provider(struct of_phandle_args *spec)
>  
>  	return node;
>  }
> +EXPORT_SYMBOL_GPL(of_icc_get_from_provider);
>  
>  /**
>   * of_icc_get() - get a path handle from a DT node based on name
> diff --git a/include/linux/interconnect-provider.h b/include/linux/interconnect-provider.h
> index b16f9effa555..070e411564e1 100644
> --- a/include/linux/interconnect-provider.h
> +++ b/include/linux/interconnect-provider.h
> @@ -100,6 +100,7 @@ void icc_node_add(struct icc_node *node, struct icc_provider *provider);
>  void icc_node_del(struct icc_node *node);
>  int icc_provider_add(struct icc_provider *provider);
>  int icc_provider_del(struct icc_provider *provider);
> +struct icc_node *of_icc_get_from_provider(struct of_phandle_args *spec);
>  
>  #else
>  
> @@ -140,6 +141,11 @@ static inline int icc_provider_del(struct icc_provider *provider)
>  	return -ENOTSUPP;
>  }
>  
> +struct icc_node *of_icc_get_from_provider(struct of_phandle_args *spec)
> +{
> +	return ERR_PTR(-ENOTSUPP);
> +}
> +
>  #endif /* CONFIG_INTERCONNECT */
>  
>  #endif /* __LINUX_INTERCONNECT_PROVIDER_H */
> 

Reviewed-by: Chanwoo Choi <cw00.choi@samsung.com>

-- 
Best Regards,
Chanwoo Choi
Samsung Electronics

^ permalink raw reply	[flat|nested] 41+ messages in thread

* Re: [RFC PATCH v2 08/11] arm: dts: exynos: Add parents and #interconnect-cells to Exynos4412
  2019-12-16  0:51       ` Chanwoo Choi
@ 2019-12-16  2:59         ` Chanwoo Choi
  2019-12-18 10:17           ` Artur Świgoń
  0 siblings, 1 reply; 41+ messages in thread
From: Chanwoo Choi @ 2019-12-16  2:59 UTC (permalink / raw)
  To: Artur Świgoń,
	devicetree, linux-arm-kernel, linux-samsung-soc, linux-kernel,
	linux-pm, dri-devel
  Cc: myungjoo.ham, inki.dae, sw0312.kim, georgi.djakov,
	leonard.crestez, m.szyprowski, b.zolnierkie, krzk

Hi,

On 12/16/19 9:51 AM, Chanwoo Choi wrote:
> On 9/19/19 11:22 PM, Artur Świgoń wrote:
>> From: Artur Świgoń <a.swigon@partner.samsung.com>
>>
>> This patch adds two fields to the Exynos4412 DTS:
>>   - parent: to declare connections between nodes that are not in a
>>     parent-child relation in devfreq;
>>   - #interconnect-cells: required by the interconnect framework.
>>
>> Please note that #interconnect-cells is always zero and node IDs are not
>> hardcoded anywhere. The above-mentioned parent-child relation in devfreq
>> means that there is a shared power line ('devfreq' property). The 'parent'
>> property only signifies an interconnect connection.
>>
>> Signed-off-by: Artur Świgoń <a.swigon@partner.samsung.com>
>> ---
>>  arch/arm/boot/dts/exynos4412-odroid-common.dtsi | 1 +
>>  arch/arm/boot/dts/exynos4412.dtsi               | 9 +++++++++
>>  2 files changed, 10 insertions(+)
>>
>> diff --git a/arch/arm/boot/dts/exynos4412-odroid-common.dtsi b/arch/arm/boot/dts/exynos4412-odroid-common.dtsi
>> index ea55f377d17c..bdd61ae86103 100644
>> --- a/arch/arm/boot/dts/exynos4412-odroid-common.dtsi
>> +++ b/arch/arm/boot/dts/exynos4412-odroid-common.dtsi
>> @@ -106,6 +106,7 @@
>>  &bus_leftbus {
>>  	devfreq-events = <&ppmu_leftbus_3>, <&ppmu_rightbus_3>;
>>  	vdd-supply = <&buck3_reg>;
>> +	parent = <&bus_dmc>;
> 
> As I mentioned on other reply,
> I'm not sure to use the specific 'parent' property to make
> the connection between buses. If possible, you better to
> use the standard way like OF graph. Except for making
> the connection between buses by 'parent' property,
> looks good to me.

I tried to think it continuously. I withdraw the my opinion
using OF graph. If you make the property name like the following
example, it is possible for exynos.
- exynos,interconnect-parent-node = <&bus_dmc>; or other proper name.

Regardless of existing 'devfreq' property, I think you better to
make the connection between buses for only interconnect as following
example: This make it possible user can draw the correct tree by tracking
the 'exynos,interconnect-parent-node' value.

diff --git a/arch/arm/boot/dts/exynos4412-odroid-common.dtsi b/arch/arm/boot/dts/exynos4412-odroid-common.dtsi
index ea55f377d17c..53f87f46e161 100644
--- a/arch/arm/boot/dts/exynos4412-odroid-common.dtsi
+++ b/arch/arm/boot/dts/exynos4412-odroid-common.dtsi
@@ -90,6 +90,7 @@
 &bus_dmc {
        devfreq-events = <&ppmu_dmc0_3>, <&ppmu_dmc1_3>;
        vdd-supply = <&buck1_reg>;
+       #interconnect-cells = <0>;
        status = "okay";
 };
 
@@ -106,6 +107,8 @@
 &bus_leftbus {
        devfreq-events = <&ppmu_leftbus_3>, <&ppmu_rightbus_3>;
        vdd-supply = <&buck3_reg>;
+       exynos,interconnect-parent-node = <&bus_dmc>;
+       #interconnect-cells = <0>;
        status = "okay";
 };
 
@@ -116,6 +119,8 @@
 
 &bus_display {
        devfreq = <&bus_leftbus>;
+       exynos,interconnect-parent-node = <&bus_leftbus>;
+       #interconnect-cells = <0>;
        status = "okay";
 };


> 
> 
>>  	status = "okay";
>>  };
>>  
>> diff --git a/arch/arm/boot/dts/exynos4412.dtsi b/arch/arm/boot/dts/exynos4412.dtsi
>> index d20db2dfe8e2..a70a671acacd 100644
>> --- a/arch/arm/boot/dts/exynos4412.dtsi
>> +++ b/arch/arm/boot/dts/exynos4412.dtsi
>> @@ -390,6 +390,7 @@
>>  			clocks = <&clock CLK_DIV_DMC>;
>>  			clock-names = "bus";
>>  			operating-points-v2 = <&bus_dmc_opp_table>;
>> +			#interconnect-cells = <0>;
>>  			status = "disabled";
>>  		};
>>  
>> @@ -398,6 +399,7 @@
>>  			clocks = <&clock CLK_DIV_ACP>;
>>  			clock-names = "bus";
>>  			operating-points-v2 = <&bus_acp_opp_table>;
>> +			#interconnect-cells = <0>;
>>  			status = "disabled";
>>  		};
>>  
>> @@ -406,6 +408,7 @@
>>  			clocks = <&clock CLK_DIV_C2C>;
>>  			clock-names = "bus";
>>  			operating-points-v2 = <&bus_dmc_opp_table>;
>> +			#interconnect-cells = <0>;
>>  			status = "disabled";
>>  		};
>>  
>> @@ -459,6 +462,7 @@
>>  			clocks = <&clock CLK_DIV_GDL>;
>>  			clock-names = "bus";
>>  			operating-points-v2 = <&bus_leftbus_opp_table>;
>> +			#interconnect-cells = <0>;
>>  			status = "disabled";
>>  		};
>>  
>> @@ -467,6 +471,7 @@
>>  			clocks = <&clock CLK_DIV_GDR>;
>>  			clock-names = "bus";
>>  			operating-points-v2 = <&bus_leftbus_opp_table>;
>> +			#interconnect-cells = <0>;
>>  			status = "disabled";
>>  		};
>>  
>> @@ -475,6 +480,7 @@
>>  			clocks = <&clock CLK_ACLK160>;
>>  			clock-names = "bus";
>>  			operating-points-v2 = <&bus_display_opp_table>;
>> +			#interconnect-cells = <0>;
>>  			status = "disabled";
>>  		};
>>  
>> @@ -483,6 +489,7 @@
>>  			clocks = <&clock CLK_ACLK133>;
>>  			clock-names = "bus";
>>  			operating-points-v2 = <&bus_fsys_opp_table>;
>> +			#interconnect-cells = <0>;
>>  			status = "disabled";
>>  		};
>>  
>> @@ -491,6 +498,7 @@
>>  			clocks = <&clock CLK_ACLK100>;
>>  			clock-names = "bus";
>>  			operating-points-v2 = <&bus_peri_opp_table>;
>> +			#interconnect-cells = <0>;
>>  			status = "disabled";
>>  		};
>>  
>> @@ -499,6 +507,7 @@
>>  			clocks = <&clock CLK_SCLK_MFC>;
>>  			clock-names = "bus";
>>  			operating-points-v2 = <&bus_leftbus_opp_table>;
>> +			#interconnect-cells = <0>;
>>  			status = "disabled";
>>  		};
>>  
>>
> 
> 


-- 
Best Regards,
Chanwoo Choi
Samsung Electronics

^ permalink raw reply related	[flat|nested] 41+ messages in thread

* Re: [RFC PATCH v2 08/11] arm: dts: exynos: Add parents and #interconnect-cells to Exynos4412
  2019-12-16  2:59         ` Chanwoo Choi
@ 2019-12-18 10:17           ` Artur Świgoń
  2019-12-18 10:29             ` Chanwoo Choi
  0 siblings, 1 reply; 41+ messages in thread
From: Artur Świgoń @ 2019-12-18 10:17 UTC (permalink / raw)
  To: Chanwoo Choi, devicetree, linux-arm-kernel, linux-samsung-soc,
	linux-kernel, linux-pm, dri-devel
  Cc: myungjoo.ham, inki.dae, sw0312.kim, georgi.djakov,
	leonard.crestez, m.szyprowski, b.zolnierkie, krzk

Hi,

On Mon, 2019-12-16 at 11:59 +0900, Chanwoo Choi wrote:
> Hi,
> 
> On 12/16/19 9:51 AM, Chanwoo Choi wrote:
> > On 9/19/19 11:22 PM, Artur Świgoń wrote:
> > > From: Artur Świgoń <a.swigon@partner.samsung.com>
> > > 
> > > This patch adds two fields to the Exynos4412 DTS:
> > >   - parent: to declare connections between nodes that are not in a
> > >     parent-child relation in devfreq;
> > >   - #interconnect-cells: required by the interconnect framework.
> > > 
> > > Please note that #interconnect-cells is always zero and node IDs are not
> > > hardcoded anywhere. The above-mentioned parent-child relation in devfreq
> > > means that there is a shared power line ('devfreq' property). The 'parent'
> > > property only signifies an interconnect connection.
> > > 
> > > Signed-off-by: Artur Świgoń <a.swigon@partner.samsung.com>
> > > ---
> > >  arch/arm/boot/dts/exynos4412-odroid-common.dtsi | 1 +
> > >  arch/arm/boot/dts/exynos4412.dtsi               | 9 +++++++++
> > >  2 files changed, 10 insertions(+)
> > > 
> > > diff --git a/arch/arm/boot/dts/exynos4412-odroid-common.dtsi b/arch/arm/boot/dts/exynos4412-odroid-common.dtsi
> > > index ea55f377d17c..bdd61ae86103 100644
> > > --- a/arch/arm/boot/dts/exynos4412-odroid-common.dtsi
> > > +++ b/arch/arm/boot/dts/exynos4412-odroid-common.dtsi
> > > @@ -106,6 +106,7 @@
> > >  &bus_leftbus {
> > >  	devfreq-events = <&ppmu_leftbus_3>, <&ppmu_rightbus_3>;
> > >  	vdd-supply = <&buck3_reg>;
> > > +	parent = <&bus_dmc>;
> > 
> > As I mentioned on other reply,
> > I'm not sure to use the specific 'parent' property to make
> > the connection between buses. If possible, you better to
> > use the standard way like OF graph. Except for making
> > the connection between buses by 'parent' property,
> > looks good to me.
> 
> I tried to think it continuously. I withdraw the my opinion
> using OF graph. If you make the property name like the following
> example, it is possible for exynos.
> - exynos,interconnect-parent-node = <&bus_dmc>; or other proper name.
> 
> Regardless of existing 'devfreq' property, I think you better to
> make the connection between buses for only interconnect as following
> example: This make it possible user can draw the correct tree by tracking
> the 'exynos,interconnect-parent-node' value.

OK, for v3 I will add 'exynos,interconnect-parent-node' to bus_dmc,
bus_leftbus and bus_display as you suggested below and change the code
so that the 'devfreq' (or the upcoming 'exynos,parent-bus') property is
not taken into account.

> diff --git a/arch/arm/boot/dts/exynos4412-odroid-common.dtsi b/arch/arm/boot/dts/exynos4412-odroid-common.dtsi
> index ea55f377d17c..53f87f46e161 100644
> --- a/arch/arm/boot/dts/exynos4412-odroid-common.dtsi
> +++ b/arch/arm/boot/dts/exynos4412-odroid-common.dtsi
> @@ -90,6 +90,7 @@
>  &bus_dmc {
>         devfreq-events = <&ppmu_dmc0_3>, <&ppmu_dmc1_3>;
>         vdd-supply = <&buck1_reg>;
> +       #interconnect-cells = <0>;
>         status = "okay";
>  };
>  
> @@ -106,6 +107,8 @@
>  &bus_leftbus {
>         devfreq-events = <&ppmu_leftbus_3>, <&ppmu_rightbus_3>;
>         vdd-supply = <&buck3_reg>;
> +       exynos,interconnect-parent-node = <&bus_dmc>;
> +       #interconnect-cells = <0>;
>         status = "okay";
>  };
>  
> @@ -116,6 +119,8 @@
>  
>  &bus_display {
>         devfreq = <&bus_leftbus>;
> +       exynos,interconnect-parent-node = <&bus_leftbus>;
> +       #interconnect-cells = <0>;
>         status = "okay";
>  };
> 
> 
> > 
> > 
> > >  	status = "okay";
> > >  };
> > >  
> > > diff --git a/arch/arm/boot/dts/exynos4412.dtsi b/arch/arm/boot/dts/exynos4412.dtsi
> > > index d20db2dfe8e2..a70a671acacd 100644
> > > --- a/arch/arm/boot/dts/exynos4412.dtsi
> > > +++ b/arch/arm/boot/dts/exynos4412.dtsi
> > > @@ -390,6 +390,7 @@
> > >  			clocks = <&clock CLK_DIV_DMC>;
> > >  			clock-names = "bus";
> > >  			operating-points-v2 = <&bus_dmc_opp_table>;
> > > +			#interconnect-cells = <0>;
> > >  			status = "disabled";
> > >  		};
> > >  
> > > @@ -398,6 +399,7 @@
> > >  			clocks = <&clock CLK_DIV_ACP>;
> > >  			clock-names = "bus";
> > >  			operating-points-v2 = <&bus_acp_opp_table>;
> > > +			#interconnect-cells = <0>;
> > >  			status = "disabled";
> > >  		};
> > >  
> > > @@ -406,6 +408,7 @@
> > >  			clocks = <&clock CLK_DIV_C2C>;
> > >  			clock-names = "bus";
> > >  			operating-points-v2 = <&bus_dmc_opp_table>;
> > > +			#interconnect-cells = <0>;
> > >  			status = "disabled";
> > >  		};
> > >  
> > > @@ -459,6 +462,7 @@
> > >  			clocks = <&clock CLK_DIV_GDL>;
> > >  			clock-names = "bus";
> > >  			operating-points-v2 = <&bus_leftbus_opp_table>;
> > > +			#interconnect-cells = <0>;
> > >  			status = "disabled";
> > >  		};
> > >  
> > > @@ -467,6 +471,7 @@
> > >  			clocks = <&clock CLK_DIV_GDR>;
> > >  			clock-names = "bus";
> > >  			operating-points-v2 = <&bus_leftbus_opp_table>;
> > > +			#interconnect-cells = <0>;
> > >  			status = "disabled";
> > >  		};
> > >  
> > > @@ -475,6 +480,7 @@
> > >  			clocks = <&clock CLK_ACLK160>;
> > >  			clock-names = "bus";
> > >  			operating-points-v2 = <&bus_display_opp_table>;
> > > +			#interconnect-cells = <0>;
> > >  			status = "disabled";
> > >  		};
> > >  
> > > @@ -483,6 +489,7 @@
> > >  			clocks = <&clock CLK_ACLK133>;
> > >  			clock-names = "bus";
> > >  			operating-points-v2 = <&bus_fsys_opp_table>;
> > > +			#interconnect-cells = <0>;
> > >  			status = "disabled";
> > >  		};
> > >  
> > > @@ -491,6 +498,7 @@
> > >  			clocks = <&clock CLK_ACLK100>;
> > >  			clock-names = "bus";
> > >  			operating-points-v2 = <&bus_peri_opp_table>;
> > > +			#interconnect-cells = <0>;
> > >  			status = "disabled";
> > >  		};
> > >  
> > > @@ -499,6 +507,7 @@
> > >  			clocks = <&clock CLK_SCLK_MFC>;
> > >  			clock-names = "bus";
> > >  			operating-points-v2 = <&bus_leftbus_opp_table>;
> > > +			#interconnect-cells = <0>;
> > >  			status = "disabled";
> > >  		};
> > >  
> > > 
> > 
> > 
> 

Best regards,
-- 
Artur Świgoń
Samsung R&D Institute Poland
Samsung Electronics



^ permalink raw reply	[flat|nested] 41+ messages in thread

* Re: [RFC PATCH v2 09/11] devfreq: exynos-bus: Add interconnect functionality to exynos-bus
  2019-12-16  0:44       ` Chanwoo Choi
@ 2019-12-18 10:18         ` Artur Świgoń
  2019-12-18 10:39           ` Chanwoo Choi
  0 siblings, 1 reply; 41+ messages in thread
From: Artur Świgoń @ 2019-12-18 10:18 UTC (permalink / raw)
  To: Chanwoo Choi, devicetree, linux-arm-kernel, linux-samsung-soc,
	linux-kernel, linux-pm, dri-devel
  Cc: myungjoo.ham, inki.dae, sw0312.kim, georgi.djakov,
	leonard.crestez, m.szyprowski, b.zolnierkie, krzk

Hi,

Thank you for the review.

On Mon, 2019-12-16 at 09:44 +0900, Chanwoo Choi wrote:
> Hi,
> 
> On 9/19/19 11:22 PM, Artur Świgoń wrote:
> > From: Artur Świgoń <a.swigon@partner.samsung.com>
> > 
> > This patch adds interconnect functionality to the exynos-bus devfreq
> > driver.
> > 
> > The SoC topology is a graph (or, more specifically, a tree) and most of
> > its edges are taken from the devfreq parent-child hierarchy (cf.
> > Documentation/devicetree/bindings/devfreq/exynos-bus.txt). Due to
> > unspecified relative probing order, -EPROBE_DEFER may be propagated to
> > guarantee that a child is probed before its parent.
> > 
> > Each bus is now an interconnect provider and an interconnect node as well
> > (cf. Documentation/interconnect/interconnect.rst), i.e. every bus registers
> > itself as a node. Node IDs are not hardcoded but rather assigned at
> > runtime, in probing order (subject to the above-mentioned exception
> > regarding relative order). This approach allows for using this driver with
> > various Exynos SoCs.
> > 
> > Frequencies requested via the interconnect API for a given node are
> > propagated to devfreq using dev_pm_qos_update_request(). Please note that
> > it is not an error when CONFIG_INTERCONNECT is 'n', in which case all
> > interconnect API functions are no-op.
> > 
> > Signed-off-by: Artur Świgoń <a.swigon@partner.samsung.com>
> > ---
> >  drivers/devfreq/exynos-bus.c | 153 +++++++++++++++++++++++++++++++++++
> >  1 file changed, 153 insertions(+)
> > 
> > diff --git a/drivers/devfreq/exynos-bus.c b/drivers/devfreq/exynos-bus.c
> > index 8d44810cac69..e0232202720d 100644
> > --- a/drivers/devfreq/exynos-bus.c
> > +++ b/drivers/devfreq/exynos-bus.c
> > @@ -14,14 +14,19 @@
> >  #include <linux/devfreq-event.h>
> >  #include <linux/device.h>
> >  #include <linux/export.h>
> > +#include <linux/idr.h>
> > +#include <linux/interconnect-provider.h>
> >  #include <linux/module.h>
> >  #include <linux/of.h>
> >  #include <linux/pm_opp.h>
> > +#include <linux/pm_qos.h>
> >  #include <linux/platform_device.h>
> >  #include <linux/regulator/consumer.h>
> >  
> >  #define DEFAULT_SATURATION_RATIO	40
> >  
> > +#define icc_units_to_khz(x) ((x) / 8)
> 
> icc_units_to_khz() -> kpbs_to_khz()

OK

> > +
> >  struct exynos_bus {
> >  	struct device *dev;
> >  
> > @@ -35,6 +40,12 @@ struct exynos_bus {
> >  	struct opp_table *opp_table;
> >  	struct clk *clk;
> >  	unsigned int ratio;
> > +
> > +	/* One provider per bus, one node per provider */
> > +	struct icc_provider provider;
> > +	struct icc_node *node;
> > +
> > +	struct dev_pm_qos_request qos_req;
> >  };
> >  
> >  /*
> > @@ -59,6 +70,13 @@ exynos_bus_ops_edev(enable_edev);
> >  exynos_bus_ops_edev(disable_edev);
> >  exynos_bus_ops_edev(set_event);
> >  
> > +static int exynos_bus_next_id(void)
> > +{
> > +	static DEFINE_IDA(exynos_bus_icc_ida);
> > +
> > +	return ida_alloc(&exynos_bus_icc_ida, GFP_KERNEL);
> > +}
> > +
> >  static int exynos_bus_get_event(struct exynos_bus *bus,
> >  				struct devfreq_event_data *edata)
> >  {
> > @@ -171,6 +189,38 @@ static void exynos_bus_passive_exit(struct device *dev)
> >  	clk_disable_unprepare(bus->clk);
> >  }
> >  
> > +static int exynos_bus_icc_set(struct icc_node *src, struct icc_node *dst)
> > +{
> > +	struct exynos_bus *src_bus = src->data, *dst_bus = dst->data;
> > +	s32 src_freq = icc_units_to_khz(src->avg_bw);
> > +	s32 dst_freq = icc_units_to_khz(dst->avg_bw);
> > +
> > +	dev_pm_qos_update_request(&src_bus->qos_req, src_freq);
> 
> Have to check the return value.
> If return error, show the waring with dev_warn.

OK, I will change it to:

ret = dev_pm_qos_update_request(&src_bus->qos_req, src_freq);
if (ret < 0) {
	dev_warn(src_bus->dev, "failed to update PM QoS request");
	return ret;
}

> > +	dev_pm_qos_update_request(&dst_bus->qos_req, dst_freq);
> 
> ditto.

OK (same as above).

> > +
> > +	return 0;
> > +}
> > +
> > +static int exynos_bus_icc_aggregate(struct icc_node *node, u32 tag, u32 avg_bw,
> > +				    u32 peak_bw, u32 *agg_avg, u32 *agg_peak)
> > +{
> > +	*agg_avg += avg_bw;
> > +	*agg_peak = max(*agg_peak, peak_bw);
> > +
> > +	return 0;
> > +}
> > +
> > +static struct icc_node *exynos_bus_icc_xlate(struct of_phandle_args *spec,
> > +					     void *data)
> > +{
> > +	struct exynos_bus *bus = data;
> > +
> > +	if (spec->np != bus->dev->of_node)
> > +		return ERR_PTR(-EINVAL);
> > +
> > +	return bus->node;
> > +}
> > +
> >  static int exynos_bus_parent_parse_of(struct device_node *np,
> >  					struct exynos_bus *bus)
> >  {
> > @@ -366,6 +416,101 @@ static int exynos_bus_profile_init_passive(struct exynos_bus *bus,
> >  	return 0;
> >  }
> >  
> > +static int exynos_bus_icc_connect(struct exynos_bus *bus)
> > +{
> > +	struct device_node *np = bus->dev->of_node;
> > +	struct devfreq *parent_devfreq;
> > +	struct icc_node *parent_node = NULL;
> > +	struct of_phandle_args args;
> > +	int ret = 0;
> > +
> > +	parent_devfreq = devfreq_get_devfreq_by_phandle(bus->dev, 0);
> > +	if (!IS_ERR(parent_devfreq)) {
> > +		struct exynos_bus *parent_bus;
> > +
> > +		parent_bus = dev_get_drvdata(parent_devfreq->dev.parent);
> > +		parent_node = parent_bus->node;
> > +	} else {
> > +		/* Look for parent in DT */
> > +		int num = of_count_phandle_with_args(np, "parent",
> > +						     "#interconnect-cells");
> > +		if (num != 1)
> > +			goto out; /* 'parent' is optional */
> > +
> > +		ret = of_parse_phandle_with_args(np, "parent",
> > +						 "#interconnect-cells",
> > +						 0, &args);
> 
> 
> Actually, I agree your approach. I think that it is very useful
> and necessary to guarantee the PM QoS requirements between devices.
> 
> But,
> As I already commented, I'm not sure that the "parent" property 
> is proper for only this driver. If possible, you better to get
> the parent phandle through other way like OF graph.
> 
> If you suggest the standard way to make the tree between
> the exynos-bus, I'll agree.

As I commented in the answer to patch 08, I will use the
'exynos,interconnect-parent-node' property for bus_display,
bus_leftbus and bus_dmc.

> Also, for interconnect path, you have to add the connection
> between 'bus_display' and 'bus_leftbus' regardless
> of the existing 'devfreq' property.
> - bus_display - bus_leftbus - bus_dmc
> 
> > +		if (ret < 0)
> > +			goto out;
> > +
> > +		of_node_put(args.np);
> > +
> > +		parent_node = of_icc_get_from_provider(&args);
> > +		if (IS_ERR(parent_node)) {
> > +			/* May be -EPROBE_DEFER */
> > +			ret = PTR_ERR(parent_node);
> > +			goto out;
> > +		}
> > +	}
> > +
> > +	ret = icc_link_create(bus->node, parent_node->id);
> > +
> > +out:
> > +	return ret;
> > +}
> > +
> > +static int exynos_bus_icc_init(struct exynos_bus *bus)
> > +{
> > +	struct device *dev = bus->dev;
> > +	struct icc_provider *provider = &bus->provider;
> > +	struct icc_node *node;
> > +	int id, ret;
> > +
> > +	/* Initialize the interconnect provider */
> > +	provider->set = exynos_bus_icc_set;
> > +	provider->aggregate = exynos_bus_icc_aggregate;
> > +	provider->xlate = exynos_bus_icc_xlate;
> > +	provider->dev = dev;
> > +	provider->data = bus;
> > +
> > +	ret = icc_provider_add(provider);
> > +	if (ret < 0)
> > +		goto out;
> 
> Return error without goto because there is no any requirement
> to free the resource before.

OK.

> > +
> > +	ret = id = exynos_bus_next_id();
> > +	if (ret < 0)
> > +		goto err_node;
> > +
> > +	node = icc_node_create(id);
> > +	if (IS_ERR(node)) {
> > +		ret = PTR_ERR(node);
> > +		goto err_node;
> > +	}
> > +
> > +	bus->node = node;
> > +	node->name = dev->of_node->name;
> > +	node->data = bus;
> > +	icc_node_add(node, provider);
> > +
> > +	ret = exynos_bus_icc_connect(bus);
> > +	if (ret < 0)
> > +		goto err_connect;
> > +
> > +	ret = dev_pm_qos_add_request(bus->devfreq->dev.parent, &bus->qos_req,
> 
> Check whether this line is over 80 char.

It looks like 77 columns to me.

> 
> > +				     DEV_PM_QOS_MIN_FREQUENCY, 0);
> 
> 	Check the return value.

OK.

> 
> > +
> > +out:
> 
> Remove this goto due to not necessary.
> 
> > +	return ret;
> 
> 	return 0;

OK.

Please also note that this function as well as exynos_bus_icc_connect()
will
slightly change in v3 due to the changes regarding DT properties.

> 
> > +
> > +err_connect:
> > +	icc_node_del(node);
> > +	icc_node_destroy(id);
> > +err_node:
> > +	icc_provider_del(provider);
> > +
> > +	return ret;
> > +}
> > +
> >  static int exynos_bus_probe(struct platform_device *pdev)
> >  {
> >  	struct device *dev = &pdev->dev;
> > @@ -415,6 +560,14 @@ static int exynos_bus_probe(struct platform_device *pdev)
> >  	if (ret < 0)
> >  		goto err;
> >  
> > +	/*
> > +	 * Initialize interconnect provider. A return value of -ENOTSUPP means
> > +	 * that CONFIG_INTERCONNECT is disabled.
> > +	 */
> > +	ret = exynos_bus_icc_init(bus);
> > +	if (ret < 0 && ret != -ENOTSUPP)
> > +		goto err;
> 
> Print error message.
> 	dev_err(dev, "failed to initialize the interconnect provider");

OK.

> 
> > +
> >  	max_state = bus->devfreq->profile->max_state;
> >  	min_freq = (bus->devfreq->profile->freq_table[0] / 1000);
> >  	max_freq = (bus->devfreq->profile->freq_table[max_state - 1] / 1000);
> > 
> 
> 

Best regards,
-- 
Artur Świgoń
Samsung R&D Institute Poland
Samsung Electronics



^ permalink raw reply	[flat|nested] 41+ messages in thread

* Re: [RFC PATCH v2 08/11] arm: dts: exynos: Add parents and #interconnect-cells to Exynos4412
  2019-12-18 10:17           ` Artur Świgoń
@ 2019-12-18 10:29             ` Chanwoo Choi
  2019-12-18 10:41               ` Artur Świgoń
  0 siblings, 1 reply; 41+ messages in thread
From: Chanwoo Choi @ 2019-12-18 10:29 UTC (permalink / raw)
  To: Artur Świgoń
  Cc: Chanwoo Choi, devicetree, linux-arm-kernel, linux-samsung-soc,
	linux-kernel, Linux PM list, dri-devel, MyungJoo Ham, inki.dae,
	Seung-Woo Kim, georgi.djakov, Leonard Crestez, Marek Szyprowski,
	Bartlomiej Zolnierkiewicz, Krzysztof Kozlowski

Hi

2019년 12월 18일 (수) 오후 7:18, Artur Świgoń <a.swigon@samsung.com>님이 작성:
>
> Hi,
>
> On Mon, 2019-12-16 at 11:59 +0900, Chanwoo Choi wrote:
> > Hi,
> >
> > On 12/16/19 9:51 AM, Chanwoo Choi wrote:
> > > On 9/19/19 11:22 PM, Artur Świgoń wrote:
> > > > From: Artur Świgoń <a.swigon@partner.samsung.com>
> > > >
> > > > This patch adds two fields to the Exynos4412 DTS:
> > > >   - parent: to declare connections between nodes that are not in a
> > > >     parent-child relation in devfreq;
> > > >   - #interconnect-cells: required by the interconnect framework.
> > > >
> > > > Please note that #interconnect-cells is always zero and node IDs are not
> > > > hardcoded anywhere. The above-mentioned parent-child relation in devfreq
> > > > means that there is a shared power line ('devfreq' property). The 'parent'
> > > > property only signifies an interconnect connection.
> > > >
> > > > Signed-off-by: Artur Świgoń <a.swigon@partner.samsung.com>
> > > > ---
> > > >  arch/arm/boot/dts/exynos4412-odroid-common.dtsi | 1 +
> > > >  arch/arm/boot/dts/exynos4412.dtsi               | 9 +++++++++
> > > >  2 files changed, 10 insertions(+)
> > > >
> > > > diff --git a/arch/arm/boot/dts/exynos4412-odroid-common.dtsi b/arch/arm/boot/dts/exynos4412-odroid-common.dtsi
> > > > index ea55f377d17c..bdd61ae86103 100644
> > > > --- a/arch/arm/boot/dts/exynos4412-odroid-common.dtsi
> > > > +++ b/arch/arm/boot/dts/exynos4412-odroid-common.dtsi
> > > > @@ -106,6 +106,7 @@
> > > >  &bus_leftbus {
> > > >   devfreq-events = <&ppmu_leftbus_3>, <&ppmu_rightbus_3>;
> > > >   vdd-supply = <&buck3_reg>;
> > > > + parent = <&bus_dmc>;
> > >
> > > As I mentioned on other reply,
> > > I'm not sure to use the specific 'parent' property to make
> > > the connection between buses. If possible, you better to
> > > use the standard way like OF graph. Except for making
> > > the connection between buses by 'parent' property,
> > > looks good to me.
> >
> > I tried to think it continuously. I withdraw the my opinion
> > using OF graph. If you make the property name like the following
> > example, it is possible for exynos.
> > - exynos,interconnect-parent-node = <&bus_dmc>; or other proper name.
> >
> > Regardless of existing 'devfreq' property, I think you better to
> > make the connection between buses for only interconnect as following
> > example: This make it possible user can draw the correct tree by tracking
> > the 'exynos,interconnect-parent-node' value.
>
> OK, for v3 I will add 'exynos,interconnect-parent-node' to bus_dmc,
> bus_leftbus and bus_display as you suggested below and change the code
> so that the 'devfreq' (or the upcoming 'exynos,parent-bus') property is
> not taken into account.

I'd like you to make the v3 based on my patches[1]
[1]  https://lkml.org/lkml/2019/12/17/21
- [PATCH 0/9] PM / devfreq: Remove deprecated 'devfreq' and
'devfreq-events' properties

I uploaded the patches to devfreq-testing branch[2]
[2] https://git.kernel.org/pub/scm/linux/kernel/git/chanwoo/linux.git/log/?h=devfreq-testing


>
> > diff --git a/arch/arm/boot/dts/exynos4412-odroid-common.dtsi b/arch/arm/boot/dts/exynos4412-odroid-common.dtsi
> > index ea55f377d17c..53f87f46e161 100644
> > --- a/arch/arm/boot/dts/exynos4412-odroid-common.dtsi
> > +++ b/arch/arm/boot/dts/exynos4412-odroid-common.dtsi
> > @@ -90,6 +90,7 @@
> >  &bus_dmc {
> >         devfreq-events = <&ppmu_dmc0_3>, <&ppmu_dmc1_3>;
> >         vdd-supply = <&buck1_reg>;
> > +       #interconnect-cells = <0>;
> >         status = "okay";
> >  };
> >
> > @@ -106,6 +107,8 @@
> >  &bus_leftbus {
> >         devfreq-events = <&ppmu_leftbus_3>, <&ppmu_rightbus_3>;
> >         vdd-supply = <&buck3_reg>;
> > +       exynos,interconnect-parent-node = <&bus_dmc>;
> > +       #interconnect-cells = <0>;
> >         status = "okay";
> >  };
> >
> > @@ -116,6 +119,8 @@
> >
> >  &bus_display {
> >         devfreq = <&bus_leftbus>;
> > +       exynos,interconnect-parent-node = <&bus_leftbus>;
> > +       #interconnect-cells = <0>;
> >         status = "okay";
> >  };
> >
> >
> > >
> > >
> > > >   status = "okay";
> > > >  };
> > > >
> > > > diff --git a/arch/arm/boot/dts/exynos4412.dtsi b/arch/arm/boot/dts/exynos4412.dtsi
> > > > index d20db2dfe8e2..a70a671acacd 100644
> > > > --- a/arch/arm/boot/dts/exynos4412.dtsi
> > > > +++ b/arch/arm/boot/dts/exynos4412.dtsi
> > > > @@ -390,6 +390,7 @@
> > > >                   clocks = <&clock CLK_DIV_DMC>;
> > > >                   clock-names = "bus";
> > > >                   operating-points-v2 = <&bus_dmc_opp_table>;
> > > > +                 #interconnect-cells = <0>;
> > > >                   status = "disabled";
> > > >           };
> > > >
> > > > @@ -398,6 +399,7 @@
> > > >                   clocks = <&clock CLK_DIV_ACP>;
> > > >                   clock-names = "bus";
> > > >                   operating-points-v2 = <&bus_acp_opp_table>;
> > > > +                 #interconnect-cells = <0>;
> > > >                   status = "disabled";
> > > >           };
> > > >
> > > > @@ -406,6 +408,7 @@
> > > >                   clocks = <&clock CLK_DIV_C2C>;
> > > >                   clock-names = "bus";
> > > >                   operating-points-v2 = <&bus_dmc_opp_table>;
> > > > +                 #interconnect-cells = <0>;
> > > >                   status = "disabled";
> > > >           };
> > > >
> > > > @@ -459,6 +462,7 @@
> > > >                   clocks = <&clock CLK_DIV_GDL>;
> > > >                   clock-names = "bus";
> > > >                   operating-points-v2 = <&bus_leftbus_opp_table>;
> > > > +                 #interconnect-cells = <0>;
> > > >                   status = "disabled";
> > > >           };
> > > >
> > > > @@ -467,6 +471,7 @@
> > > >                   clocks = <&clock CLK_DIV_GDR>;
> > > >                   clock-names = "bus";
> > > >                   operating-points-v2 = <&bus_leftbus_opp_table>;
> > > > +                 #interconnect-cells = <0>;
> > > >                   status = "disabled";
> > > >           };
> > > >
> > > > @@ -475,6 +480,7 @@
> > > >                   clocks = <&clock CLK_ACLK160>;
> > > >                   clock-names = "bus";
> > > >                   operating-points-v2 = <&bus_display_opp_table>;
> > > > +                 #interconnect-cells = <0>;
> > > >                   status = "disabled";
> > > >           };
> > > >
> > > > @@ -483,6 +489,7 @@
> > > >                   clocks = <&clock CLK_ACLK133>;
> > > >                   clock-names = "bus";
> > > >                   operating-points-v2 = <&bus_fsys_opp_table>;
> > > > +                 #interconnect-cells = <0>;
> > > >                   status = "disabled";
> > > >           };
> > > >
> > > > @@ -491,6 +498,7 @@
> > > >                   clocks = <&clock CLK_ACLK100>;
> > > >                   clock-names = "bus";
> > > >                   operating-points-v2 = <&bus_peri_opp_table>;
> > > > +                 #interconnect-cells = <0>;
> > > >                   status = "disabled";
> > > >           };
> > > >
> > > > @@ -499,6 +507,7 @@
> > > >                   clocks = <&clock CLK_SCLK_MFC>;
> > > >                   clock-names = "bus";
> > > >                   operating-points-v2 = <&bus_leftbus_opp_table>;
> > > > +                 #interconnect-cells = <0>;
> > > >                   status = "disabled";
> > > >           };
> > > >
> > > >
> > >
> > >
> >
>
> Best regards,
> --
> Artur Świgoń
> Samsung R&D Institute Poland
> Samsung Electronics
>
>


--
Best Regards,
Chanwoo Choi

^ permalink raw reply	[flat|nested] 41+ messages in thread

* Re: [RFC PATCH v2 09/11] devfreq: exynos-bus: Add interconnect functionality to exynos-bus
  2019-12-18 10:18         ` Artur Świgoń
@ 2019-12-18 10:39           ` Chanwoo Choi
  2019-12-18 10:48             ` Artur Świgoń
  0 siblings, 1 reply; 41+ messages in thread
From: Chanwoo Choi @ 2019-12-18 10:39 UTC (permalink / raw)
  To: Artur Świgoń
  Cc: Chanwoo Choi, devicetree, linux-arm-kernel, linux-samsung-soc,
	linux-kernel, Linux PM list, dri-devel, MyungJoo Ham, inki.dae,
	Seung-Woo Kim, georgi.djakov, Leonard Crestez, Marek Szyprowski,
	Bartlomiej Zolnierkiewicz, Krzysztof Kozlowski

Hi,

2019년 12월 18일 (수) 오후 7:19, Artur Świgoń <a.swigon@samsung.com>님이 작성:
>
> Hi,
>
> Thank you for the review.
>
> On Mon, 2019-12-16 at 09:44 +0900, Chanwoo Choi wrote:
> > Hi,
> >
> > On 9/19/19 11:22 PM, Artur Świgoń wrote:
> > > From: Artur Świgoń <a.swigon@partner.samsung.com>
> > >
> > > This patch adds interconnect functionality to the exynos-bus devfreq
> > > driver.
> > >
> > > The SoC topology is a graph (or, more specifically, a tree) and most of
> > > its edges are taken from the devfreq parent-child hierarchy (cf.
> > > Documentation/devicetree/bindings/devfreq/exynos-bus.txt). Due to
> > > unspecified relative probing order, -EPROBE_DEFER may be propagated to
> > > guarantee that a child is probed before its parent.
> > >
> > > Each bus is now an interconnect provider and an interconnect node as well
> > > (cf. Documentation/interconnect/interconnect.rst), i.e. every bus registers
> > > itself as a node. Node IDs are not hardcoded but rather assigned at
> > > runtime, in probing order (subject to the above-mentioned exception
> > > regarding relative order). This approach allows for using this driver with
> > > various Exynos SoCs.
> > >
> > > Frequencies requested via the interconnect API for a given node are
> > > propagated to devfreq using dev_pm_qos_update_request(). Please note that
> > > it is not an error when CONFIG_INTERCONNECT is 'n', in which case all
> > > interconnect API functions are no-op.
> > >
> > > Signed-off-by: Artur Świgoń <a.swigon@partner.samsung.com>
> > > ---
> > >  drivers/devfreq/exynos-bus.c | 153 +++++++++++++++++++++++++++++++++++
> > >  1 file changed, 153 insertions(+)
> > >
> > > diff --git a/drivers/devfreq/exynos-bus.c b/drivers/devfreq/exynos-bus.c
> > > index 8d44810cac69..e0232202720d 100644
> > > --- a/drivers/devfreq/exynos-bus.c
> > > +++ b/drivers/devfreq/exynos-bus.c
> > > @@ -14,14 +14,19 @@
> > >  #include <linux/devfreq-event.h>
> > >  #include <linux/device.h>
> > >  #include <linux/export.h>
> > > +#include <linux/idr.h>
> > > +#include <linux/interconnect-provider.h>
> > >  #include <linux/module.h>
> > >  #include <linux/of.h>
> > >  #include <linux/pm_opp.h>
> > > +#include <linux/pm_qos.h>
> > >  #include <linux/platform_device.h>
> > >  #include <linux/regulator/consumer.h>
> > >
> > >  #define DEFAULT_SATURATION_RATIO   40
> > >
> > > +#define icc_units_to_khz(x) ((x) / 8)
> >
> > icc_units_to_khz() -> kpbs_to_khz()
>
> OK
>
> > > +
> > >  struct exynos_bus {
> > >     struct device *dev;
> > >
> > > @@ -35,6 +40,12 @@ struct exynos_bus {
> > >     struct opp_table *opp_table;
> > >     struct clk *clk;
> > >     unsigned int ratio;
> > > +
> > > +   /* One provider per bus, one node per provider */
> > > +   struct icc_provider provider;
> > > +   struct icc_node *node;
> > > +
> > > +   struct dev_pm_qos_request qos_req;
> > >  };
> > >
> > >  /*
> > > @@ -59,6 +70,13 @@ exynos_bus_ops_edev(enable_edev);
> > >  exynos_bus_ops_edev(disable_edev);
> > >  exynos_bus_ops_edev(set_event);
> > >
> > > +static int exynos_bus_next_id(void)
> > > +{
> > > +   static DEFINE_IDA(exynos_bus_icc_ida);
> > > +
> > > +   return ida_alloc(&exynos_bus_icc_ida, GFP_KERNEL);
> > > +}
> > > +
> > >  static int exynos_bus_get_event(struct exynos_bus *bus,
> > >                             struct devfreq_event_data *edata)
> > >  {
> > > @@ -171,6 +189,38 @@ static void exynos_bus_passive_exit(struct device *dev)
> > >     clk_disable_unprepare(bus->clk);
> > >  }
> > >
> > > +static int exynos_bus_icc_set(struct icc_node *src, struct icc_node *dst)
> > > +{
> > > +   struct exynos_bus *src_bus = src->data, *dst_bus = dst->data;
> > > +   s32 src_freq = icc_units_to_khz(src->avg_bw);
> > > +   s32 dst_freq = icc_units_to_khz(dst->avg_bw);
> > > +
> > > +   dev_pm_qos_update_request(&src_bus->qos_req, src_freq);
> >
> > Have to check the return value.
> > If return error, show the waring with dev_warn.
>
> OK, I will change it to:
>
> ret = dev_pm_qos_update_request(&src_bus->qos_req, src_freq);
> if (ret < 0) {
>         dev_warn(src_bus->dev, "failed to update PM QoS request");
>         return ret;

If you return right after, better to use dev_err.
If you use dev_warn, just show the warning message without return.

> }
>
> > > +   dev_pm_qos_update_request(&dst_bus->qos_req, dst_freq);
> >
> > ditto.
>
> OK (same as above).

ditto.

>
> > > +
> > > +   return 0;
> > > +}
> > > +
> > > +static int exynos_bus_icc_aggregate(struct icc_node *node, u32 tag, u32 avg_bw,
> > > +                               u32 peak_bw, u32 *agg_avg, u32 *agg_peak)
> > > +{
> > > +   *agg_avg += avg_bw;
> > > +   *agg_peak = max(*agg_peak, peak_bw);
> > > +
> > > +   return 0;
> > > +}
> > > +
> > > +static struct icc_node *exynos_bus_icc_xlate(struct of_phandle_args *spec,
> > > +                                        void *data)
> > > +{
> > > +   struct exynos_bus *bus = data;
> > > +
> > > +   if (spec->np != bus->dev->of_node)
> > > +           return ERR_PTR(-EINVAL);
> > > +
> > > +   return bus->node;
> > > +}
> > > +
> > >  static int exynos_bus_parent_parse_of(struct device_node *np,
> > >                                     struct exynos_bus *bus)
> > >  {
> > > @@ -366,6 +416,101 @@ static int exynos_bus_profile_init_passive(struct exynos_bus *bus,
> > >     return 0;
> > >  }
> > >
> > > +static int exynos_bus_icc_connect(struct exynos_bus *bus)
> > > +{
> > > +   struct device_node *np = bus->dev->of_node;
> > > +   struct devfreq *parent_devfreq;
> > > +   struct icc_node *parent_node = NULL;
> > > +   struct of_phandle_args args;
> > > +   int ret = 0;
> > > +
> > > +   parent_devfreq = devfreq_get_devfreq_by_phandle(bus->dev, 0);
> > > +   if (!IS_ERR(parent_devfreq)) {
> > > +           struct exynos_bus *parent_bus;
> > > +
> > > +           parent_bus = dev_get_drvdata(parent_devfreq->dev.parent);
> > > +           parent_node = parent_bus->node;
> > > +   } else {
> > > +           /* Look for parent in DT */
> > > +           int num = of_count_phandle_with_args(np, "parent",
> > > +                                                "#interconnect-cells");
> > > +           if (num != 1)
> > > +                   goto out; /* 'parent' is optional */
> > > +
> > > +           ret = of_parse_phandle_with_args(np, "parent",
> > > +                                            "#interconnect-cells",
> > > +                                            0, &args);
> >
> >
> > Actually, I agree your approach. I think that it is very useful
> > and necessary to guarantee the PM QoS requirements between devices.
> >
> > But,
> > As I already commented, I'm not sure that the "parent" property
> > is proper for only this driver. If possible, you better to get
> > the parent phandle through other way like OF graph.
> >
> > If you suggest the standard way to make the tree between
> > the exynos-bus, I'll agree.
>
> As I commented in the answer to patch 08, I will use the
> 'exynos,interconnect-parent-node' property for bus_display,
> bus_leftbus and bus_dmc.

OK.

>
> > Also, for interconnect path, you have to add the connection
> > between 'bus_display' and 'bus_leftbus' regardless
> > of the existing 'devfreq' property.
> > - bus_display - bus_leftbus - bus_dmc
> >
> > > +           if (ret < 0)
> > > +                   goto out;
> > > +
> > > +           of_node_put(args.np);
> > > +
> > > +           parent_node = of_icc_get_from_provider(&args);
> > > +           if (IS_ERR(parent_node)) {
> > > +                   /* May be -EPROBE_DEFER */
> > > +                   ret = PTR_ERR(parent_node);
> > > +                   goto out;
> > > +           }
> > > +   }
> > > +
> > > +   ret = icc_link_create(bus->node, parent_node->id);
> > > +
> > > +out:
> > > +   return ret;
> > > +}
> > > +
> > > +static int exynos_bus_icc_init(struct exynos_bus *bus)
> > > +{
> > > +   struct device *dev = bus->dev;
> > > +   struct icc_provider *provider = &bus->provider;
> > > +   struct icc_node *node;
> > > +   int id, ret;
> > > +
> > > +   /* Initialize the interconnect provider */
> > > +   provider->set = exynos_bus_icc_set;
> > > +   provider->aggregate = exynos_bus_icc_aggregate;
> > > +   provider->xlate = exynos_bus_icc_xlate;
> > > +   provider->dev = dev;
> > > +   provider->data = bus;
> > > +
> > > +   ret = icc_provider_add(provider);
> > > +   if (ret < 0)
> > > +           goto out;
> >
> > Return error without goto because there is no any requirement
> > to free the resource before.
>
> OK.
>
> > > +
> > > +   ret = id = exynos_bus_next_id();
> > > +   if (ret < 0)
> > > +           goto err_node;
> > > +
> > > +   node = icc_node_create(id);
> > > +   if (IS_ERR(node)) {
> > > +           ret = PTR_ERR(node);
> > > +           goto err_node;
> > > +   }
> > > +
> > > +   bus->node = node;
> > > +   node->name = dev->of_node->name;
> > > +   node->data = bus;
> > > +   icc_node_add(node, provider);
> > > +
> > > +   ret = exynos_bus_icc_connect(bus);
> > > +   if (ret < 0)
> > > +           goto err_connect;
> > > +
> > > +   ret = dev_pm_qos_add_request(bus->devfreq->dev.parent, &bus->qos_req,
> >
> > Check whether this line is over 80 char.
>
> It looks like 77 columns to me.
>
> >
> > > +                                DEV_PM_QOS_MIN_FREQUENCY, 0);
> >
> >       Check the return value.
>
> OK.
>
> >
> > > +
> > > +out:
> >
> > Remove this goto due to not necessary.
> >
> > > +   return ret;
> >
> >       return 0;
>
> OK.
>
> Please also note that this function as well as exynos_bus_icc_connect()
> will
> slightly change in v3 due to the changes regarding DT properties.
>
> >
> > > +
> > > +err_connect:
> > > +   icc_node_del(node);
> > > +   icc_node_destroy(id);
> > > +err_node:
> > > +   icc_provider_del(provider);
> > > +
> > > +   return ret;
> > > +}
> > > +
> > >  static int exynos_bus_probe(struct platform_device *pdev)
> > >  {
> > >     struct device *dev = &pdev->dev;
> > > @@ -415,6 +560,14 @@ static int exynos_bus_probe(struct platform_device *pdev)
> > >     if (ret < 0)
> > >             goto err;
> > >
> > > +   /*
> > > +    * Initialize interconnect provider. A return value of -ENOTSUPP means
> > > +    * that CONFIG_INTERCONNECT is disabled.
> > > +    */
> > > +   ret = exynos_bus_icc_init(bus);
> > > +   if (ret < 0 && ret != -ENOTSUPP)
> > > +           goto err;
> >
> > Print error message.
> >       dev_err(dev, "failed to initialize the interconnect provider");
>
> OK.
>
> >
> > > +
> > >     max_state = bus->devfreq->profile->max_state;
> > >     min_freq = (bus->devfreq->profile->freq_table[0] / 1000);
> > >     max_freq = (bus->devfreq->profile->freq_table[max_state - 1] / 1000);
> > >
> >
> >
>
> Best regards,
> --
> Artur Świgoń
> Samsung R&D Institute Poland
> Samsung Electronics
>
>


-- 
Best Regards,
Chanwoo Choi

^ permalink raw reply	[flat|nested] 41+ messages in thread

* Re: [RFC PATCH v2 08/11] arm: dts: exynos: Add parents and #interconnect-cells to Exynos4412
  2019-12-18 10:29             ` Chanwoo Choi
@ 2019-12-18 10:41               ` Artur Świgoń
  0 siblings, 0 replies; 41+ messages in thread
From: Artur Świgoń @ 2019-12-18 10:41 UTC (permalink / raw)
  To: Chanwoo Choi
  Cc: Chanwoo Choi, devicetree, linux-arm-kernel, linux-samsung-soc,
	linux-kernel, Linux PM list, dri-devel, MyungJoo Ham, inki.dae,
	Seung-Woo Kim, georgi.djakov, Leonard Crestez, Marek Szyprowski,
	Bartlomiej Zolnierkiewicz, Krzysztof Kozlowski

On Wed, 2019-12-18 at 19:29 +0900, Chanwoo Choi wrote:
> Hi
> 
> 2019년 12월 18일 (수) 오후 7:18, Artur Świgoń <a.swigon@samsung.com>님이 작성:
> > 
> > Hi,
> > 
> > On Mon, 2019-12-16 at 11:59 +0900, Chanwoo Choi wrote:
> > > Hi,
> > > 
> > > On 12/16/19 9:51 AM, Chanwoo Choi wrote:
> > > > On 9/19/19 11:22 PM, Artur Świgoń wrote:
> > > > > From: Artur Świgoń <a.swigon@partner.samsung.com>
> > > > > 
> > > > > This patch adds two fields to the Exynos4412 DTS:
> > > > >   - parent: to declare connections between nodes that are not in a
> > > > >     parent-child relation in devfreq;
> > > > >   - #interconnect-cells: required by the interconnect framework.
> > > > > 
> > > > > Please note that #interconnect-cells is always zero and node IDs are not
> > > > > hardcoded anywhere. The above-mentioned parent-child relation in devfreq
> > > > > means that there is a shared power line ('devfreq' property). The 'parent'
> > > > > property only signifies an interconnect connection.
> > > > > 
> > > > > Signed-off-by: Artur Świgoń <a.swigon@partner.samsung.com>
> > > > > ---
> > > > >  arch/arm/boot/dts/exynos4412-odroid-common.dtsi | 1 +
> > > > >  arch/arm/boot/dts/exynos4412.dtsi               | 9 +++++++++
> > > > >  2 files changed, 10 insertions(+)
> > > > > 
> > > > > diff --git a/arch/arm/boot/dts/exynos4412-odroid-common.dtsi b/arch/arm/boot/dts/exynos4412-odroid-common.dtsi
> > > > > index ea55f377d17c..bdd61ae86103 100644
> > > > > --- a/arch/arm/boot/dts/exynos4412-odroid-common.dtsi
> > > > > +++ b/arch/arm/boot/dts/exynos4412-odroid-common.dtsi
> > > > > @@ -106,6 +106,7 @@
> > > > >  &bus_leftbus {
> > > > >   devfreq-events = <&ppmu_leftbus_3>, <&ppmu_rightbus_3>;
> > > > >   vdd-supply = <&buck3_reg>;
> > > > > + parent = <&bus_dmc>;
> > > > 
> > > > As I mentioned on other reply,
> > > > I'm not sure to use the specific 'parent' property to make
> > > > the connection between buses. If possible, you better to
> > > > use the standard way like OF graph. Except for making
> > > > the connection between buses by 'parent' property,
> > > > looks good to me.
> > > 
> > > I tried to think it continuously. I withdraw the my opinion
> > > using OF graph. If you make the property name like the following
> > > example, it is possible for exynos.
> > > - exynos,interconnect-parent-node = <&bus_dmc>; or other proper name.
> > > 
> > > Regardless of existing 'devfreq' property, I think you better to
> > > make the connection between buses for only interconnect as following
> > > example: This make it possible user can draw the correct tree by tracking
> > > the 'exynos,interconnect-parent-node' value.
> > 
> > OK, for v3 I will add 'exynos,interconnect-parent-node' to bus_dmc,
> > bus_leftbus and bus_display as you suggested below and change the code
> > so that the 'devfreq' (or the upcoming 'exynos,parent-bus') property is
> > not taken into account.
> 
> I'd like you to make the v3 based on my patches[1]
> [1]  https://protect2.fireeye.com/url?k=3fbd62a4-6276e59a-3fbce9eb-0cc47a31309a-5329151b98fc2653&u=https://lkml.org/lkml/2019/12/17/21
> - [PATCH 0/9] PM / devfreq: Remove deprecated 'devfreq' and
> 'devfreq-events' properties
> 
> I uploaded the patches to devfreq-testing branch[2]
> [2] https://git.kernel.org/pub/scm/linux/kernel/git/chanwoo/linux.git/log/?h=devfreq-testing

OK.

> 
> > 
> > > diff --git a/arch/arm/boot/dts/exynos4412-odroid-common.dtsi b/arch/arm/boot/dts/exynos4412-odroid-common.dtsi
> > > index ea55f377d17c..53f87f46e161 100644
> > > --- a/arch/arm/boot/dts/exynos4412-odroid-common.dtsi
> > > +++ b/arch/arm/boot/dts/exynos4412-odroid-common.dtsi
> > > @@ -90,6 +90,7 @@
> > >  &bus_dmc {
> > >         devfreq-events = <&ppmu_dmc0_3>, <&ppmu_dmc1_3>;
> > >         vdd-supply = <&buck1_reg>;
> > > +       #interconnect-cells = <0>;
> > >         status = "okay";
> > >  };
> > > 
> > > @@ -106,6 +107,8 @@
> > >  &bus_leftbus {
> > >         devfreq-events = <&ppmu_leftbus_3>, <&ppmu_rightbus_3>;
> > >         vdd-supply = <&buck3_reg>;
> > > +       exynos,interconnect-parent-node = <&bus_dmc>;
> > > +       #interconnect-cells = <0>;
> > >         status = "okay";
> > >  };
> > > 
> > > @@ -116,6 +119,8 @@
> > > 
> > >  &bus_display {
> > >         devfreq = <&bus_leftbus>;
> > > +       exynos,interconnect-parent-node = <&bus_leftbus>;
> > > +       #interconnect-cells = <0>;
> > >         status = "okay";
> > >  };
> > > 
> > > 
> > > > 
> > > > 
> > > > >   status = "okay";
> > > > >  };
> > > > > 
> > > > > diff --git a/arch/arm/boot/dts/exynos4412.dtsi b/arch/arm/boot/dts/exynos4412.dtsi
> > > > > index d20db2dfe8e2..a70a671acacd 100644
> > > > > --- a/arch/arm/boot/dts/exynos4412.dtsi
> > > > > +++ b/arch/arm/boot/dts/exynos4412.dtsi
> > > > > @@ -390,6 +390,7 @@
> > > > >                   clocks = <&clock CLK_DIV_DMC>;
> > > > >                   clock-names = "bus";
> > > > >                   operating-points-v2 = <&bus_dmc_opp_table>;
> > > > > +                 #interconnect-cells = <0>;
> > > > >                   status = "disabled";
> > > > >           };
> > > > > 
> > > > > @@ -398,6 +399,7 @@
> > > > >                   clocks = <&clock CLK_DIV_ACP>;
> > > > >                   clock-names = "bus";
> > > > >                   operating-points-v2 = <&bus_acp_opp_table>;
> > > > > +                 #interconnect-cells = <0>;
> > > > >                   status = "disabled";
> > > > >           };
> > > > > 
> > > > > @@ -406,6 +408,7 @@
> > > > >                   clocks = <&clock CLK_DIV_C2C>;
> > > > >                   clock-names = "bus";
> > > > >                   operating-points-v2 = <&bus_dmc_opp_table>;
> > > > > +                 #interconnect-cells = <0>;
> > > > >                   status = "disabled";
> > > > >           };
> > > > > 
> > > > > @@ -459,6 +462,7 @@
> > > > >                   clocks = <&clock CLK_DIV_GDL>;
> > > > >                   clock-names = "bus";
> > > > >                   operating-points-v2 = <&bus_leftbus_opp_table>;
> > > > > +                 #interconnect-cells = <0>;
> > > > >                   status = "disabled";
> > > > >           };
> > > > > 
> > > > > @@ -467,6 +471,7 @@
> > > > >                   clocks = <&clock CLK_DIV_GDR>;
> > > > >                   clock-names = "bus";
> > > > >                   operating-points-v2 = <&bus_leftbus_opp_table>;
> > > > > +                 #interconnect-cells = <0>;
> > > > >                   status = "disabled";
> > > > >           };
> > > > > 
> > > > > @@ -475,6 +480,7 @@
> > > > >                   clocks = <&clock CLK_ACLK160>;
> > > > >                   clock-names = "bus";
> > > > >                   operating-points-v2 = <&bus_display_opp_table>;
> > > > > +                 #interconnect-cells = <0>;
> > > > >                   status = "disabled";
> > > > >           };
> > > > > 
> > > > > @@ -483,6 +489,7 @@
> > > > >                   clocks = <&clock CLK_ACLK133>;
> > > > >                   clock-names = "bus";
> > > > >                   operating-points-v2 = <&bus_fsys_opp_table>;
> > > > > +                 #interconnect-cells = <0>;
> > > > >                   status = "disabled";
> > > > >           };
> > > > > 
> > > > > @@ -491,6 +498,7 @@
> > > > >                   clocks = <&clock CLK_ACLK100>;
> > > > >                   clock-names = "bus";
> > > > >                   operating-points-v2 = <&bus_peri_opp_table>;
> > > > > +                 #interconnect-cells = <0>;
> > > > >                   status = "disabled";
> > > > >           };
> > > > > 
> > > > > @@ -499,6 +507,7 @@
> > > > >                   clocks = <&clock CLK_SCLK_MFC>;
> > > > >                   clock-names = "bus";
> > > > >                   operating-points-v2 = <&bus_leftbus_opp_table>;
> > > > > +                 #interconnect-cells = <0>;
> > > > >                   status = "disabled";
> > > > >           };
> > > > > 
> > > > > 

-- 
Artur Świgoń
Samsung R&D Institute Poland
Samsung Electronics



^ permalink raw reply	[flat|nested] 41+ messages in thread

* Re: [RFC PATCH v2 09/11] devfreq: exynos-bus: Add interconnect functionality to exynos-bus
  2019-12-18 10:39           ` Chanwoo Choi
@ 2019-12-18 10:48             ` Artur Świgoń
  2019-12-18 11:08               ` Chanwoo Choi
  0 siblings, 1 reply; 41+ messages in thread
From: Artur Świgoń @ 2019-12-18 10:48 UTC (permalink / raw)
  To: Chanwoo Choi
  Cc: Chanwoo Choi, devicetree, linux-arm-kernel, linux-samsung-soc,
	linux-kernel, Linux PM list, dri-devel, MyungJoo Ham, inki.dae,
	Seung-Woo Kim, georgi.djakov, Leonard Crestez, Marek Szyprowski,
	Bartlomiej Zolnierkiewicz, Krzysztof Kozlowski

On Wed, 2019-12-18 at 19:39 +0900, Chanwoo Choi wrote:
> Hi,
> 
> 2019년 12월 18일 (수) 오후 7:19, Artur Świgoń <a.swigon@samsung.com>님이 작성:
> > 
> > Hi,
> > 
> > Thank you for the review.
> > 
> > On Mon, 2019-12-16 at 09:44 +0900, Chanwoo Choi wrote:
> > > Hi,
> > > 
> > > On 9/19/19 11:22 PM, Artur Świgoń wrote:
> > > > From: Artur Świgoń <a.swigon@partner.samsung.com>
> > > > 
> > > > This patch adds interconnect functionality to the exynos-bus devfreq
> > > > driver.
> > > > 
> > > > The SoC topology is a graph (or, more specifically, a tree) and most of
> > > > its edges are taken from the devfreq parent-child hierarchy (cf.
> > > > Documentation/devicetree/bindings/devfreq/exynos-bus.txt). Due to
> > > > unspecified relative probing order, -EPROBE_DEFER may be propagated to
> > > > guarantee that a child is probed before its parent.
> > > > 
> > > > Each bus is now an interconnect provider and an interconnect node as well
> > > > (cf. Documentation/interconnect/interconnect.rst), i.e. every bus registers
> > > > itself as a node. Node IDs are not hardcoded but rather assigned at
> > > > runtime, in probing order (subject to the above-mentioned exception
> > > > regarding relative order). This approach allows for using this driver with
> > > > various Exynos SoCs.
> > > > 
> > > > Frequencies requested via the interconnect API for a given node are
> > > > propagated to devfreq using dev_pm_qos_update_request(). Please note that
> > > > it is not an error when CONFIG_INTERCONNECT is 'n', in which case all
> > > > interconnect API functions are no-op.
> > > > 
> > > > Signed-off-by: Artur Świgoń <a.swigon@partner.samsung.com>
> > > > ---
> > > >  drivers/devfreq/exynos-bus.c | 153 +++++++++++++++++++++++++++++++++++
> > > >  1 file changed, 153 insertions(+)
> > > > 
> > > > diff --git a/drivers/devfreq/exynos-bus.c b/drivers/devfreq/exynos-bus.c
> > > > index 8d44810cac69..e0232202720d 100644
> > > > --- a/drivers/devfreq/exynos-bus.c
> > > > +++ b/drivers/devfreq/exynos-bus.c
> > > > @@ -14,14 +14,19 @@
> > > >  #include <linux/devfreq-event.h>
> > > >  #include <linux/device.h>
> > > >  #include <linux/export.h>
> > > > +#include <linux/idr.h>
> > > > +#include <linux/interconnect-provider.h>
> > > >  #include <linux/module.h>
> > > >  #include <linux/of.h>
> > > >  #include <linux/pm_opp.h>
> > > > +#include <linux/pm_qos.h>
> > > >  #include <linux/platform_device.h>
> > > >  #include <linux/regulator/consumer.h>
> > > > 
> > > >  #define DEFAULT_SATURATION_RATIO   40
> > > > 
> > > > +#define icc_units_to_khz(x) ((x) / 8)
> > > 
> > > icc_units_to_khz() -> kpbs_to_khz()
> > 
> > OK
> > 
> > > > +
> > > >  struct exynos_bus {
> > > >     struct device *dev;
> > > > 
> > > > @@ -35,6 +40,12 @@ struct exynos_bus {
> > > >     struct opp_table *opp_table;
> > > >     struct clk *clk;
> > > >     unsigned int ratio;
> > > > +
> > > > +   /* One provider per bus, one node per provider */
> > > > +   struct icc_provider provider;
> > > > +   struct icc_node *node;
> > > > +
> > > > +   struct dev_pm_qos_request qos_req;
> > > >  };
> > > > 
> > > >  /*
> > > > @@ -59,6 +70,13 @@ exynos_bus_ops_edev(enable_edev);
> > > >  exynos_bus_ops_edev(disable_edev);
> > > >  exynos_bus_ops_edev(set_event);
> > > > 
> > > > +static int exynos_bus_next_id(void)
> > > > +{
> > > > +   static DEFINE_IDA(exynos_bus_icc_ida);
> > > > +
> > > > +   return ida_alloc(&exynos_bus_icc_ida, GFP_KERNEL);
> > > > +}
> > > > +
> > > >  static int exynos_bus_get_event(struct exynos_bus *bus,
> > > >                             struct devfreq_event_data *edata)
> > > >  {
> > > > @@ -171,6 +189,38 @@ static void exynos_bus_passive_exit(struct device *dev)
> > > >     clk_disable_unprepare(bus->clk);
> > > >  }
> > > > 
> > > > +static int exynos_bus_icc_set(struct icc_node *src, struct icc_node *dst)
> > > > +{
> > > > +   struct exynos_bus *src_bus = src->data, *dst_bus = dst->data;
> > > > +   s32 src_freq = icc_units_to_khz(src->avg_bw);
> > > > +   s32 dst_freq = icc_units_to_khz(dst->avg_bw);
> > > > +
> > > > +   dev_pm_qos_update_request(&src_bus->qos_req, src_freq);
> > > 
> > > Have to check the return value.
> > > If return error, show the waring with dev_warn.
> > 
> > OK, I will change it to:
> > 
> > ret = dev_pm_qos_update_request(&src_bus->qos_req, src_freq);
> > if (ret < 0) {
> >         dev_warn(src_bus->dev, "failed to update PM QoS request");
> >         return ret;
> 
> If you return right after, better to use dev_err.
> If you use dev_warn, just show the warning message without return.

OK, I will use dev_err().

> > }
> > 
> > > > +   dev_pm_qos_update_request(&dst_bus->qos_req, dst_freq);
> > > 
> > > ditto.
> > 
> > OK (same as above).
> 
> ditto.
> 
> > 
> > > > +
> > > > +   return 0;
> > > > +}
> > > > +
> > > > +static int exynos_bus_icc_aggregate(struct icc_node *node, u32 tag, u32 avg_bw,
> > > > +                               u32 peak_bw, u32 *agg_avg, u32 *agg_peak)
> > > > +{
> > > > +   *agg_avg += avg_bw;
> > > > +   *agg_peak = max(*agg_peak, peak_bw);
> > > > +
> > > > +   return 0;
> > > > +}
> > > > +
> > > > +static struct icc_node *exynos_bus_icc_xlate(struct of_phandle_args *spec,
> > > > +                                        void *data)
> > > > +{
> > > > +   struct exynos_bus *bus = data;
> > > > +
> > > > +   if (spec->np != bus->dev->of_node)
> > > > +           return ERR_PTR(-EINVAL);
> > > > +
> > > > +   return bus->node;
> > > > +}
> > > > +
> > > >  static int exynos_bus_parent_parse_of(struct device_node *np,
> > > >                                     struct exynos_bus *bus)
> > > >  {
> > > > @@ -366,6 +416,101 @@ static int exynos_bus_profile_init_passive(struct exynos_bus *bus,
> > > >     return 0;
> > > >  }
> > > > 
> > > > +static int exynos_bus_icc_connect(struct exynos_bus *bus)
> > > > +{
> > > > +   struct device_node *np = bus->dev->of_node;
> > > > +   struct devfreq *parent_devfreq;
> > > > +   struct icc_node *parent_node = NULL;
> > > > +   struct of_phandle_args args;
> > > > +   int ret = 0;
> > > > +
> > > > +   parent_devfreq = devfreq_get_devfreq_by_phandle(bus->dev, 0);
> > > > +   if (!IS_ERR(parent_devfreq)) {
> > > > +           struct exynos_bus *parent_bus;
> > > > +
> > > > +           parent_bus = dev_get_drvdata(parent_devfreq->dev.parent);
> > > > +           parent_node = parent_bus->node;
> > > > +   } else {
> > > > +           /* Look for parent in DT */
> > > > +           int num = of_count_phandle_with_args(np, "parent",
> > > > +                                                "#interconnect-cells");
> > > > +           if (num != 1)
> > > > +                   goto out; /* 'parent' is optional */
> > > > +
> > > > +           ret = of_parse_phandle_with_args(np, "parent",
> > > > +                                            "#interconnect-cells",
> > > > +                                            0, &args);
> > > 
> > > 
> > > Actually, I agree your approach. I think that it is very useful
> > > and necessary to guarantee the PM QoS requirements between devices.
> > > 
> > > But,
> > > As I already commented, I'm not sure that the "parent" property
> > > is proper for only this driver. If possible, you better to get
> > > the parent phandle through other way like OF graph.
> > > 
> > > If you suggest the standard way to make the tree between
> > > the exynos-bus, I'll agree.
> > 
> > As I commented in the answer to patch 08, I will use the
> > 'exynos,interconnect-parent-node' property for bus_display,
> > bus_leftbus and bus_dmc.
> 
> OK.
> 
> > 
> > > Also, for interconnect path, you have to add the connection
> > > between 'bus_display' and 'bus_leftbus' regardless
> > > of the existing 'devfreq' property.
> > > - bus_display - bus_leftbus - bus_dmc
> > > 
> > > > +           if (ret < 0)
> > > > +                   goto out;
> > > > +
> > > > +           of_node_put(args.np);
> > > > +
> > > > +           parent_node = of_icc_get_from_provider(&args);
> > > > +           if (IS_ERR(parent_node)) {
> > > > +                   /* May be -EPROBE_DEFER */
> > > > +                   ret = PTR_ERR(parent_node);
> > > > +                   goto out;
> > > > +           }
> > > > +   }
> > > > +
> > > > +   ret = icc_link_create(bus->node, parent_node->id);
> > > > +
> > > > +out:
> > > > +   return ret;
> > > > +}
> > > > +
> > > > +static int exynos_bus_icc_init(struct exynos_bus *bus)
> > > > +{
> > > > +   struct device *dev = bus->dev;
> > > > +   struct icc_provider *provider = &bus->provider;
> > > > +   struct icc_node *node;
> > > > +   int id, ret;
> > > > +
> > > > +   /* Initialize the interconnect provider */
> > > > +   provider->set = exynos_bus_icc_set;
> > > > +   provider->aggregate = exynos_bus_icc_aggregate;
> > > > +   provider->xlate = exynos_bus_icc_xlate;
> > > > +   provider->dev = dev;
> > > > +   provider->data = bus;
> > > > +
> > > > +   ret = icc_provider_add(provider);
> > > > +   if (ret < 0)
> > > > +           goto out;
> > > 
> > > Return error without goto because there is no any requirement
> > > to free the resource before.
> > 
> > OK.
> > 
> > > > +
> > > > +   ret = id = exynos_bus_next_id();
> > > > +   if (ret < 0)
> > > > +           goto err_node;
> > > > +
> > > > +   node = icc_node_create(id);
> > > > +   if (IS_ERR(node)) {
> > > > +           ret = PTR_ERR(node);
> > > > +           goto err_node;
> > > > +   }
> > > > +
> > > > +   bus->node = node;
> > > > +   node->name = dev->of_node->name;
> > > > +   node->data = bus;
> > > > +   icc_node_add(node, provider);
> > > > +
> > > > +   ret = exynos_bus_icc_connect(bus);
> > > > +   if (ret < 0)
> > > > +           goto err_connect;
> > > > +
> > > > +   ret = dev_pm_qos_add_request(bus->devfreq->dev.parent, &bus->qos_req,
> > > 
> > > Check whether this line is over 80 char.
> > 
> > It looks like 77 columns to me.
> > 
> > > 
> > > > +                                DEV_PM_QOS_MIN_FREQUENCY, 0);
> > > 
> > >       Check the return value.
> > 
> > OK.
> > 
> > > 
> > > > +
> > > > +out:
> > > 
> > > Remove this goto due to not necessary.
> > > 
> > > > +   return ret;
> > > 
> > >       return 0;
> > 
> > OK.
> > 
> > Please also note that this function as well as exynos_bus_icc_connect()
> > will
> > slightly change in v3 due to the changes regarding DT properties.
> > 
> > > 
> > > > +
> > > > +err_connect:
> > > > +   icc_node_del(node);
> > > > +   icc_node_destroy(id);
> > > > +err_node:
> > > > +   icc_provider_del(provider);
> > > > +
> > > > +   return ret;
> > > > +}
> > > > +
> > > >  static int exynos_bus_probe(struct platform_device *pdev)
> > > >  {
> > > >     struct device *dev = &pdev->dev;
> > > > @@ -415,6 +560,14 @@ static int exynos_bus_probe(struct platform_device *pdev)
> > > >     if (ret < 0)
> > > >             goto err;
> > > > 
> > > > +   /*
> > > > +    * Initialize interconnect provider. A return value of -ENOTSUPP means
> > > > +    * that CONFIG_INTERCONNECT is disabled.
> > > > +    */
> > > > +   ret = exynos_bus_icc_init(bus);
> > > > +   if (ret < 0 && ret != -ENOTSUPP)
> > > > +           goto err;
> > > 
> > > Print error message.
> > >       dev_err(dev, "failed to initialize the interconnect provider");
> > 
> > OK.
> > 
> > > 
> > > > +
> > > >     max_state = bus->devfreq->profile->max_state;
> > > >     min_freq = (bus->devfreq->profile->freq_table[0] / 1000);
> > > >     max_freq = (bus->devfreq->profile->freq_table[max_state - 1] / 1000);
> > > > 

-- 
Artur Świgoń
Samsung R&D Institute Poland
Samsung Electronics



^ permalink raw reply	[flat|nested] 41+ messages in thread

* Re: [RFC PATCH v2 09/11] devfreq: exynos-bus: Add interconnect functionality to exynos-bus
  2019-12-18 10:48             ` Artur Świgoń
@ 2019-12-18 11:08               ` Chanwoo Choi
  0 siblings, 0 replies; 41+ messages in thread
From: Chanwoo Choi @ 2019-12-18 11:08 UTC (permalink / raw)
  To: Artur Świgoń
  Cc: Chanwoo Choi, devicetree, linux-arm-kernel, linux-samsung-soc,
	linux-kernel, Linux PM list, dri-devel, MyungJoo Ham, inki.dae,
	Seung-Woo Kim, Georgi Djakov, Leonard Crestez, Marek Szyprowski,
	Bartlomiej Zolnierkiewicz, Krzysztof Kozlowski

Hi,

If possible, I'd like to apply these patches to v5.6-rc1.
It is very useful feature to support the QoS for user device using memory bus.

2019년 12월 18일 (수) 오후 7:48, Artur Świgoń <a.swigon@samsung.com>님이 작성:
>
> On Wed, 2019-12-18 at 19:39 +0900, Chanwoo Choi wrote:
> > Hi,
> >
> > 2019년 12월 18일 (수) 오후 7:19, Artur Świgoń <a.swigon@samsung.com>님이 작성:
> > >
> > > Hi,
> > >
> > > Thank you for the review.
> > >
> > > On Mon, 2019-12-16 at 09:44 +0900, Chanwoo Choi wrote:
> > > > Hi,
> > > >
> > > > On 9/19/19 11:22 PM, Artur Świgoń wrote:
> > > > > From: Artur Świgoń <a.swigon@partner.samsung.com>
> > > > >
> > > > > This patch adds interconnect functionality to the exynos-bus devfreq
> > > > > driver.
> > > > >
> > > > > The SoC topology is a graph (or, more specifically, a tree) and most of
> > > > > its edges are taken from the devfreq parent-child hierarchy (cf.
> > > > > Documentation/devicetree/bindings/devfreq/exynos-bus.txt). Due to
> > > > > unspecified relative probing order, -EPROBE_DEFER may be propagated to
> > > > > guarantee that a child is probed before its parent.
> > > > >
> > > > > Each bus is now an interconnect provider and an interconnect node as well
> > > > > (cf. Documentation/interconnect/interconnect.rst), i.e. every bus registers
> > > > > itself as a node. Node IDs are not hardcoded but rather assigned at
> > > > > runtime, in probing order (subject to the above-mentioned exception
> > > > > regarding relative order). This approach allows for using this driver with
> > > > > various Exynos SoCs.
> > > > >
> > > > > Frequencies requested via the interconnect API for a given node are
> > > > > propagated to devfreq using dev_pm_qos_update_request(). Please note that
> > > > > it is not an error when CONFIG_INTERCONNECT is 'n', in which case all
> > > > > interconnect API functions are no-op.
> > > > >
> > > > > Signed-off-by: Artur Świgoń <a.swigon@partner.samsung.com>
> > > > > ---
> > > > >  drivers/devfreq/exynos-bus.c | 153 +++++++++++++++++++++++++++++++++++
> > > > >  1 file changed, 153 insertions(+)
> > > > >
> > > > > diff --git a/drivers/devfreq/exynos-bus.c b/drivers/devfreq/exynos-bus.c
> > > > > index 8d44810cac69..e0232202720d 100644
> > > > > --- a/drivers/devfreq/exynos-bus.c
> > > > > +++ b/drivers/devfreq/exynos-bus.c
> > > > > @@ -14,14 +14,19 @@
> > > > >  #include <linux/devfreq-event.h>
> > > > >  #include <linux/device.h>
> > > > >  #include <linux/export.h>
> > > > > +#include <linux/idr.h>
> > > > > +#include <linux/interconnect-provider.h>
> > > > >  #include <linux/module.h>
> > > > >  #include <linux/of.h>
> > > > >  #include <linux/pm_opp.h>
> > > > > +#include <linux/pm_qos.h>
> > > > >  #include <linux/platform_device.h>
> > > > >  #include <linux/regulator/consumer.h>
> > > > >
> > > > >  #define DEFAULT_SATURATION_RATIO   40
> > > > >
> > > > > +#define icc_units_to_khz(x) ((x) / 8)
> > > >
> > > > icc_units_to_khz() -> kpbs_to_khz()
> > >
> > > OK
> > >
> > > > > +
> > > > >  struct exynos_bus {
> > > > >     struct device *dev;
> > > > >
> > > > > @@ -35,6 +40,12 @@ struct exynos_bus {
> > > > >     struct opp_table *opp_table;
> > > > >     struct clk *clk;
> > > > >     unsigned int ratio;
> > > > > +
> > > > > +   /* One provider per bus, one node per provider */
> > > > > +   struct icc_provider provider;
> > > > > +   struct icc_node *node;
> > > > > +
> > > > > +   struct dev_pm_qos_request qos_req;
> > > > >  };
> > > > >
> > > > >  /*
> > > > > @@ -59,6 +70,13 @@ exynos_bus_ops_edev(enable_edev);
> > > > >  exynos_bus_ops_edev(disable_edev);
> > > > >  exynos_bus_ops_edev(set_event);
> > > > >
> > > > > +static int exynos_bus_next_id(void)
> > > > > +{
> > > > > +   static DEFINE_IDA(exynos_bus_icc_ida);
> > > > > +
> > > > > +   return ida_alloc(&exynos_bus_icc_ida, GFP_KERNEL);
> > > > > +}
> > > > > +
> > > > >  static int exynos_bus_get_event(struct exynos_bus *bus,
> > > > >                             struct devfreq_event_data *edata)
> > > > >  {
> > > > > @@ -171,6 +189,38 @@ static void exynos_bus_passive_exit(struct device *dev)
> > > > >     clk_disable_unprepare(bus->clk);
> > > > >  }
> > > > >
> > > > > +static int exynos_bus_icc_set(struct icc_node *src, struct icc_node *dst)
> > > > > +{
> > > > > +   struct exynos_bus *src_bus = src->data, *dst_bus = dst->data;
> > > > > +   s32 src_freq = icc_units_to_khz(src->avg_bw);
> > > > > +   s32 dst_freq = icc_units_to_khz(dst->avg_bw);
> > > > > +
> > > > > +   dev_pm_qos_update_request(&src_bus->qos_req, src_freq);
> > > >
> > > > Have to check the return value.
> > > > If return error, show the waring with dev_warn.
> > >
> > > OK, I will change it to:
> > >
> > > ret = dev_pm_qos_update_request(&src_bus->qos_req, src_freq);
> > > if (ret < 0) {
> > >         dev_warn(src_bus->dev, "failed to update PM QoS request");
> > >         return ret;
> >
> > If you return right after, better to use dev_err.
> > If you use dev_warn, just show the warning message without return.
>
> OK, I will use dev_err().
>
> > > }
> > >
> > > > > +   dev_pm_qos_update_request(&dst_bus->qos_req, dst_freq);
> > > >
> > > > ditto.
> > >
> > > OK (same as above).
> >
> > ditto.
> >
> > >
> > > > > +
> > > > > +   return 0;
> > > > > +}
> > > > > +
> > > > > +static int exynos_bus_icc_aggregate(struct icc_node *node, u32 tag, u32 avg_bw,
> > > > > +                               u32 peak_bw, u32 *agg_avg, u32 *agg_peak)
> > > > > +{
> > > > > +   *agg_avg += avg_bw;
> > > > > +   *agg_peak = max(*agg_peak, peak_bw);
> > > > > +
> > > > > +   return 0;
> > > > > +}
> > > > > +
> > > > > +static struct icc_node *exynos_bus_icc_xlate(struct of_phandle_args *spec,
> > > > > +                                        void *data)
> > > > > +{
> > > > > +   struct exynos_bus *bus = data;
> > > > > +
> > > > > +   if (spec->np != bus->dev->of_node)
> > > > > +           return ERR_PTR(-EINVAL);
> > > > > +
> > > > > +   return bus->node;
> > > > > +}
> > > > > +
> > > > >  static int exynos_bus_parent_parse_of(struct device_node *np,
> > > > >                                     struct exynos_bus *bus)
> > > > >  {
> > > > > @@ -366,6 +416,101 @@ static int exynos_bus_profile_init_passive(struct exynos_bus *bus,
> > > > >     return 0;
> > > > >  }
> > > > >
> > > > > +static int exynos_bus_icc_connect(struct exynos_bus *bus)
> > > > > +{
> > > > > +   struct device_node *np = bus->dev->of_node;
> > > > > +   struct devfreq *parent_devfreq;
> > > > > +   struct icc_node *parent_node = NULL;
> > > > > +   struct of_phandle_args args;
> > > > > +   int ret = 0;
> > > > > +
> > > > > +   parent_devfreq = devfreq_get_devfreq_by_phandle(bus->dev, 0);
> > > > > +   if (!IS_ERR(parent_devfreq)) {
> > > > > +           struct exynos_bus *parent_bus;
> > > > > +
> > > > > +           parent_bus = dev_get_drvdata(parent_devfreq->dev.parent);
> > > > > +           parent_node = parent_bus->node;
> > > > > +   } else {
> > > > > +           /* Look for parent in DT */
> > > > > +           int num = of_count_phandle_with_args(np, "parent",
> > > > > +                                                "#interconnect-cells");
> > > > > +           if (num != 1)
> > > > > +                   goto out; /* 'parent' is optional */
> > > > > +
> > > > > +           ret = of_parse_phandle_with_args(np, "parent",
> > > > > +                                            "#interconnect-cells",
> > > > > +                                            0, &args);
> > > >
> > > >
> > > > Actually, I agree your approach. I think that it is very useful
> > > > and necessary to guarantee the PM QoS requirements between devices.
> > > >
> > > > But,
> > > > As I already commented, I'm not sure that the "parent" property
> > > > is proper for only this driver. If possible, you better to get
> > > > the parent phandle through other way like OF graph.
> > > >
> > > > If you suggest the standard way to make the tree between
> > > > the exynos-bus, I'll agree.
> > >
> > > As I commented in the answer to patch 08, I will use the
> > > 'exynos,interconnect-parent-node' property for bus_display,
> > > bus_leftbus and bus_dmc.
> >
> > OK.
> >
> > >
> > > > Also, for interconnect path, you have to add the connection
> > > > between 'bus_display' and 'bus_leftbus' regardless
> > > > of the existing 'devfreq' property.
> > > > - bus_display - bus_leftbus - bus_dmc
> > > >
> > > > > +           if (ret < 0)
> > > > > +                   goto out;
> > > > > +
> > > > > +           of_node_put(args.np);
> > > > > +
> > > > > +           parent_node = of_icc_get_from_provider(&args);
> > > > > +           if (IS_ERR(parent_node)) {
> > > > > +                   /* May be -EPROBE_DEFER */
> > > > > +                   ret = PTR_ERR(parent_node);
> > > > > +                   goto out;
> > > > > +           }
> > > > > +   }
> > > > > +
> > > > > +   ret = icc_link_create(bus->node, parent_node->id);
> > > > > +
> > > > > +out:
> > > > > +   return ret;
> > > > > +}
> > > > > +
> > > > > +static int exynos_bus_icc_init(struct exynos_bus *bus)
> > > > > +{
> > > > > +   struct device *dev = bus->dev;
> > > > > +   struct icc_provider *provider = &bus->provider;
> > > > > +   struct icc_node *node;
> > > > > +   int id, ret;
> > > > > +
> > > > > +   /* Initialize the interconnect provider */
> > > > > +   provider->set = exynos_bus_icc_set;
> > > > > +   provider->aggregate = exynos_bus_icc_aggregate;
> > > > > +   provider->xlate = exynos_bus_icc_xlate;
> > > > > +   provider->dev = dev;
> > > > > +   provider->data = bus;
> > > > > +
> > > > > +   ret = icc_provider_add(provider);
> > > > > +   if (ret < 0)
> > > > > +           goto out;
> > > >
> > > > Return error without goto because there is no any requirement
> > > > to free the resource before.
> > >
> > > OK.
> > >
> > > > > +
> > > > > +   ret = id = exynos_bus_next_id();
> > > > > +   if (ret < 0)
> > > > > +           goto err_node;
> > > > > +
> > > > > +   node = icc_node_create(id);
> > > > > +   if (IS_ERR(node)) {
> > > > > +           ret = PTR_ERR(node);
> > > > > +           goto err_node;
> > > > > +   }
> > > > > +
> > > > > +   bus->node = node;
> > > > > +   node->name = dev->of_node->name;
> > > > > +   node->data = bus;
> > > > > +   icc_node_add(node, provider);
> > > > > +
> > > > > +   ret = exynos_bus_icc_connect(bus);
> > > > > +   if (ret < 0)
> > > > > +           goto err_connect;
> > > > > +
> > > > > +   ret = dev_pm_qos_add_request(bus->devfreq->dev.parent, &bus->qos_req,
> > > >
> > > > Check whether this line is over 80 char.
> > >
> > > It looks like 77 columns to me.
> > >
> > > >
> > > > > +                                DEV_PM_QOS_MIN_FREQUENCY, 0);
> > > >
> > > >       Check the return value.
> > >
> > > OK.
> > >
> > > >
> > > > > +
> > > > > +out:
> > > >
> > > > Remove this goto due to not necessary.
> > > >
> > > > > +   return ret;
> > > >
> > > >       return 0;
> > >
> > > OK.
> > >
> > > Please also note that this function as well as exynos_bus_icc_connect()
> > > will
> > > slightly change in v3 due to the changes regarding DT properties.
> > >
> > > >
> > > > > +
> > > > > +err_connect:
> > > > > +   icc_node_del(node);
> > > > > +   icc_node_destroy(id);
> > > > > +err_node:
> > > > > +   icc_provider_del(provider);
> > > > > +
> > > > > +   return ret;
> > > > > +}
> > > > > +
> > > > >  static int exynos_bus_probe(struct platform_device *pdev)
> > > > >  {
> > > > >     struct device *dev = &pdev->dev;
> > > > > @@ -415,6 +560,14 @@ static int exynos_bus_probe(struct platform_device *pdev)
> > > > >     if (ret < 0)
> > > > >             goto err;
> > > > >
> > > > > +   /*
> > > > > +    * Initialize interconnect provider. A return value of -ENOTSUPP means
> > > > > +    * that CONFIG_INTERCONNECT is disabled.
> > > > > +    */
> > > > > +   ret = exynos_bus_icc_init(bus);
> > > > > +   if (ret < 0 && ret != -ENOTSUPP)
> > > > > +           goto err;
> > > >
> > > > Print error message.
> > > >       dev_err(dev, "failed to initialize the interconnect provider");
> > >
> > > OK.
> > >
> > > >
> > > > > +
> > > > >     max_state = bus->devfreq->profile->max_state;
> > > > >     min_freq = (bus->devfreq->profile->freq_table[0] / 1000);
> > > > >     max_freq = (bus->devfreq->profile->freq_table[max_state - 1] / 1000);
> > > > >
>
> --
> Artur Świgoń
> Samsung R&D Institute Poland
> Samsung Electronics
>
>


-- 
Best Regards,
Chanwoo Choi

^ permalink raw reply	[flat|nested] 41+ messages in thread

end of thread, other threads:[~2019-12-18 11:08 UTC | newest]

Thread overview: 41+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
     [not found] <CGME20190919142321eucas1p164c2591ad402427cb71fd00c348a29ec@eucas1p1.samsung.com>
2019-09-19 14:22 ` [RFC PATCH v2 00/11] Simple QoS for exynos-bus driver using interconnect Artur Świgoń
     [not found]   ` <CGME20190919142322eucas1p24bc477ee6e1bcd65546c305d55af097d@eucas1p2.samsung.com>
2019-09-19 14:22     ` [RFC PATCH v2 01/11] devfreq: exynos-bus: Extract exynos_bus_profile_init() Artur Świgoń
2019-09-20  2:15       ` Chanwoo Choi
2019-09-25  5:44         ` Artur Świgoń
2019-09-25  6:37           ` Chanwoo Choi
2019-09-25  6:41             ` Artur Świgoń
     [not found]   ` <CGME20190919142322eucas1p1949ad95468af26698c4c5addc060ce00@eucas1p1.samsung.com>
2019-09-19 14:22     ` [RFC PATCH v2 02/11] devfreq: exynos-bus: Extract exynos_bus_profile_init_passive() Artur Świgoń
     [not found]   ` <CGME20190919142323eucas1p2fc73a765389432f880fa28945fd28975@eucas1p2.samsung.com>
2019-09-19 14:22     ` [RFC PATCH v2 03/11] devfreq: exynos-bus: Change goto-based logic to if-else logic Artur Świgoń
     [not found]   ` <CGME20190919142324eucas1p1638cec2aafbfcaf03cfdfa7d0189143a@eucas1p1.samsung.com>
2019-09-19 14:22     ` [RFC PATCH v2 04/11] devfreq: exynos-bus: Clean up code Artur Świgoń
2019-09-20  2:22       ` Chanwoo Choi
2019-10-03  8:10         ` Artur Świgoń
     [not found]   ` <CGME20190919142325eucas1p28102446c22b1e1c61aae0bad46d079b0@eucas1p2.samsung.com>
2019-09-19 14:22     ` [RFC PATCH v2 05/11] interconnect: Export of_icc_get_from_provider() Artur Świgoń
2019-12-16  0:57       ` Chanwoo Choi
     [not found]   ` <CGME20190919142326eucas1p204819014fe85716b47e2de4af9102cd5@eucas1p2.samsung.com>
2019-09-19 14:22     ` [RFC PATCH v2 06/11] interconnect: Relax requirement in of_icc_get_from_provider() Artur Świgoń
     [not found]   ` <CGME20190919142327eucas1p183470eede07b50c1e3acda58f2af1eba@eucas1p1.samsung.com>
2019-09-19 14:22     ` [RFC PATCH v2 07/11] interconnect: Relax condition in apply_constraints() Artur Świgoń
     [not found]   ` <CGME20190919142329eucas1p299762f99dd55a5d625633ceec84219f9@eucas1p2.samsung.com>
2019-09-19 14:22     ` [RFC PATCH v2 08/11] arm: dts: exynos: Add parents and #interconnect-cells to Exynos4412 Artur Świgoń
2019-12-16  0:51       ` Chanwoo Choi
2019-12-16  2:59         ` Chanwoo Choi
2019-12-18 10:17           ` Artur Świgoń
2019-12-18 10:29             ` Chanwoo Choi
2019-12-18 10:41               ` Artur Świgoń
2019-12-16  0:55       ` Chanwoo Choi
2019-12-16  0:57         ` Chanwoo Choi
     [not found]   ` <CGME20190919142329eucas1p2e53992eab9ec6b404f716f955b3c228e@eucas1p2.samsung.com>
2019-09-19 14:22     ` [RFC PATCH v2 09/11] devfreq: exynos-bus: Add interconnect functionality to exynos-bus Artur Świgoń
2019-09-25  7:03       ` Chanwoo Choi
2019-09-25  7:12         ` Artur Świgoń
2019-12-02 17:05         ` Artur Świgoń
2019-12-05  2:36           ` Chanwoo Choi
2019-12-16  0:44       ` Chanwoo Choi
2019-12-18 10:18         ` Artur Świgoń
2019-12-18 10:39           ` Chanwoo Choi
2019-12-18 10:48             ` Artur Świgoń
2019-12-18 11:08               ` Chanwoo Choi
     [not found]   ` <CGME20190919142330eucas1p1eceae78b148a03f2af71657b7cdd6694@eucas1p1.samsung.com>
2019-09-19 14:22     ` [RFC PATCH v2 10/11] arm: dts: exynos: Add interconnects to Exynos4412 mixer Artur Świgoń
     [not found]   ` <CGME20190919142331eucas1p2107a7cb9ce8b3817ed171c21a8ad5b00@eucas1p2.samsung.com>
2019-09-19 14:22     ` [RFC PATCH v2 11/11] drm: exynos: mixer: Add interconnect support Artur Świgoń
2019-09-20  1:07   ` [RFC PATCH v2 00/11] Simple QoS for exynos-bus driver using interconnect Chanwoo Choi
2019-09-20  2:14     ` Chanwoo Choi
2019-09-25  5:47       ` Artur Świgoń
2019-09-25  6:12         ` Chanwoo Choi
2019-09-25  6:37           ` Artur Świgoń
2019-09-25  6:48             ` Chanwoo Choi

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).