All of lore.kernel.org
 help / color / mirror / Atom feed
From: Chanwoo Choi <chanwoo@kernel.org>
To: "Artur Świgoń" <a.swigon@samsung.com>
Cc: devicetree <devicetree@vger.kernel.org>,
	linux-arm-kernel <linux-arm-kernel@lists.infradead.org>,
	linux-samsung-soc <linux-samsung-soc@vger.kernel.org>,
	linux-kernel <linux-kernel@vger.kernel.org>,
	Linux PM list <linux-pm@vger.kernel.org>,
	dri-devel <dri-devel@lists.freedesktop.org>,
	Chanwoo Choi <cw00.choi@samsung.com>,
	MyungJoo Ham <myungjoo.ham@samsung.com>,
	inki.dae@samsung.com, Seung-Woo Kim <sw0312.kim@samsung.com>,
	Georgi Djakov <georgi.djakov@linaro.org>,
	Leonard Crestez <leonard.crestez@nxp.com>,
	Marek Szyprowski <m.szyprowski@samsung.com>,
	Bartlomiej Zolnierkiewicz <b.zolnierkie@samsung.com>,
	Krzysztof Kozlowski <krzk@kernel.org>
Subject: Re: [RFC PATCH v3 5/7] devfreq: exynos-bus: Add interconnect functionality to exynos-bus
Date: Sun, 22 Dec 2019 04:53:31 +0900	[thread overview]
Message-ID: <CAGTfZH0M5yJ3e2mEEc6XE89zV1289C6FvhqVEcuBdi2OgeMtig@mail.gmail.com> (raw)
In-Reply-To: <20191220115653.6487-6-a.swigon@samsung.com>

Hi,

On Fri, Dec 20, 2019 at 9:02 PM Artur Świgoń <a.swigon@samsung.com> wrote:
>
> This patch adds interconnect functionality to the exynos-bus devfreq
> driver.
>
> The SoC topology is a graph (or, more specifically, a tree) and its
> edges are specified using the 'exynos,interconnect-parent-node' in the
> DT. Due to unspecified relative probing order, -EPROBE_DEFER may be
> propagated to ensure that the parent is probed before its children.
>
> 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@samsung.com>
> ---
>  drivers/devfreq/exynos-bus.c | 144 +++++++++++++++++++++++++++++++++++
>  1 file changed, 144 insertions(+)
>
> diff --git a/drivers/devfreq/exynos-bus.c b/drivers/devfreq/exynos-bus.c
> index 9fdb188915e8..694a9581dcdb 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 kbps_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;
>  };
>
>  /*
> @@ -205,6 +216,39 @@ 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 = kbps_to_khz(src->avg_bw);
> +       s32 dst_freq = kbps_to_khz(dst->avg_bw);
> +       int ret;
> +
> +       ret = dev_pm_qos_update_request(&src_bus->qos_req, src_freq);
> +       if (ret < 0) {
> +               dev_err(src_bus->dev, "failed to update PM QoS request");

To catch the correct error point, better to add 'src node' to error message
as following:

dev_err(src_bus->dev, "failed to update PM QoS of %s\n",
                                               dev_name(src_bus->dev.parent))

> +               return ret;
> +       }
> +
> +       ret = dev_pm_qos_update_request(&dst_bus->qos_req, dst_freq);
> +       if (ret < 0) {
> +               dev_err(dst_bus->dev, "failed to update PM QoS request");

ditto.

dev_err(src_bus->dev, "failed to update PM QoS of %s\n",
                                               dev_name(dst_bus->dev.parent))


> +               return ret;
> +       }
> +
> +       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)
>  {
> @@ -419,6 +463,96 @@ static int exynos_bus_profile_init_passive(struct exynos_bus *bus,
>         return 0;
>  }
>
> +static struct icc_node *exynos_bus_icc_get_parent(struct exynos_bus *bus)
> +{
> +       struct device_node *np = bus->dev->of_node;
> +       struct of_phandle_args args;
> +       int num, ret;
> +
> +       num = of_count_phandle_with_args(np, "exynos,interconnect-parent-node",
> +                                       "#interconnect-cells");
> +       if (num != 1)
> +               return NULL; /* parent nodes are optional */

You better to add the comment before calling exynos_bus_icc_get_parent
and remove '/* parent nodes are optional */'. Actually, it is not enough
to understand the role of 'interconnect-parent-node' with '/* parent
nodes are optional */'.
And I add my opinion about this comment below.

And I expect that you will add the description and example for
'exynos,interconnect-parent-node' on exynos-bus dt-binding document.

> +
> +       ret = of_parse_phandle_with_args(np, "exynos,interconnect-parent-node",
> +                                       "#interconnect-cells", 0, &args);
> +       if (ret < 0)
> +               return ERR_PTR(ret);
> +
> +       of_node_put(args.np);
> +
> +       return of_icc_get_from_provider(&args);
> +}
> +
> +static int exynos_bus_icc_init(struct exynos_bus *bus)
> +{
> +       static DEFINE_IDA(ida);
> +
> +       struct device *dev = bus->dev;
> +       struct icc_provider *provider = &bus->provider;
> +       struct icc_node *node, *parent_node;
> +       int id, ret;
> +
> +       /* Initialize the interconnect provider */
> +       provider->set = exynos_bus_icc_set;
> +       provider->aggregate = icc_std_aggregate;
> +       provider->xlate = exynos_bus_icc_xlate;
> +       provider->dev = dev;
> +       provider->inter_set = true;
> +       provider->data = bus;
> +
> +       ret = icc_provider_add(provider);
> +       if (ret < 0)
> +               return ret;
> +
> +       ret = id = ida_alloc(&ida, GFP_KERNEL);
> +       if (ret < 0)
> +               goto err_id;
> +
> +       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);
> +

Better to add the following comment. If you add following comment
before calling exynos_bus_icc_get_parent, don't need to add the
same comment into exynos_bus_icc.
    /* If interconnect parent node is not existing, don't use
interconnect feature */

> +       parent_node = exynos_bus_icc_get_parent(bus);
> +       if (IS_ERR(parent_node)) {
> +               ret = PTR_ERR(parent_node);
> +               goto err_parent;
> +       }
> +
> +       if (parent_node) {

Better to change this if statement as following:
else if (parent_node)


> +               ret = icc_link_create(node, parent_node->id);
> +               if (ret < 0)
> +                       goto err_parent;
> +       }
> +
> +       ret = dev_pm_qos_add_request(bus->devfreq->dev.parent, &bus->qos_req,
> +                                       DEV_PM_QOS_MIN_FREQUENCY, 0);

Is it necessary if interconnect-parent-node is not existing?


> +       if (ret < 0)
> +               goto err_request;
> +
> +       return 0;
> +
> +err_request:
> +       if (parent_node)
> +               icc_link_destroy(node, parent_node);
> +err_parent:
> +       icc_node_del(node);
> +       icc_node_destroy(id);
> +err_node:
> +       ida_free(&ida, id);
> +err_id:
> +       icc_provider_del(provider);
> +
> +       return ret;
> +}
> +
>  static int exynos_bus_probe(struct platform_device *pdev)
>  {
>         struct device *dev = &pdev->dev;
> @@ -468,6 +602,16 @@ 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) {
> +               dev_err(dev, "failed to initialize the interconnect provider");
> +               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
>


-- 
Best Regards,
Chanwoo Choi

WARNING: multiple messages have this Message-ID (diff)
From: Chanwoo Choi <chanwoo@kernel.org>
To: "Artur Świgoń" <a.swigon@samsung.com>
Cc: devicetree <devicetree@vger.kernel.org>,
	linux-samsung-soc <linux-samsung-soc@vger.kernel.org>,
	Linux PM list <linux-pm@vger.kernel.org>,
	Bartlomiej Zolnierkiewicz <b.zolnierkie@samsung.com>,
	Seung-Woo Kim <sw0312.kim@samsung.com>,
	linux-kernel <linux-kernel@vger.kernel.org>,
	dri-devel <dri-devel@lists.freedesktop.org>,
	inki.dae@samsung.com, Chanwoo Choi <cw00.choi@samsung.com>,
	MyungJoo Ham <myungjoo.ham@samsung.com>,
	Krzysztof Kozlowski <krzk@kernel.org>,
	Leonard Crestez <leonard.crestez@nxp.com>,
	Georgi Djakov <georgi.djakov@linaro.org>,
	linux-arm-kernel <linux-arm-kernel@lists.infradead.org>,
	Marek Szyprowski <m.szyprowski@samsung.com>
Subject: Re: [RFC PATCH v3 5/7] devfreq: exynos-bus: Add interconnect functionality to exynos-bus
Date: Sun, 22 Dec 2019 04:53:31 +0900	[thread overview]
Message-ID: <CAGTfZH0M5yJ3e2mEEc6XE89zV1289C6FvhqVEcuBdi2OgeMtig@mail.gmail.com> (raw)
In-Reply-To: <20191220115653.6487-6-a.swigon@samsung.com>

Hi,

On Fri, Dec 20, 2019 at 9:02 PM Artur Świgoń <a.swigon@samsung.com> wrote:
>
> This patch adds interconnect functionality to the exynos-bus devfreq
> driver.
>
> The SoC topology is a graph (or, more specifically, a tree) and its
> edges are specified using the 'exynos,interconnect-parent-node' in the
> DT. Due to unspecified relative probing order, -EPROBE_DEFER may be
> propagated to ensure that the parent is probed before its children.
>
> 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@samsung.com>
> ---
>  drivers/devfreq/exynos-bus.c | 144 +++++++++++++++++++++++++++++++++++
>  1 file changed, 144 insertions(+)
>
> diff --git a/drivers/devfreq/exynos-bus.c b/drivers/devfreq/exynos-bus.c
> index 9fdb188915e8..694a9581dcdb 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 kbps_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;
>  };
>
>  /*
> @@ -205,6 +216,39 @@ 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 = kbps_to_khz(src->avg_bw);
> +       s32 dst_freq = kbps_to_khz(dst->avg_bw);
> +       int ret;
> +
> +       ret = dev_pm_qos_update_request(&src_bus->qos_req, src_freq);
> +       if (ret < 0) {
> +               dev_err(src_bus->dev, "failed to update PM QoS request");

To catch the correct error point, better to add 'src node' to error message
as following:

dev_err(src_bus->dev, "failed to update PM QoS of %s\n",
                                               dev_name(src_bus->dev.parent))

> +               return ret;
> +       }
> +
> +       ret = dev_pm_qos_update_request(&dst_bus->qos_req, dst_freq);
> +       if (ret < 0) {
> +               dev_err(dst_bus->dev, "failed to update PM QoS request");

ditto.

dev_err(src_bus->dev, "failed to update PM QoS of %s\n",
                                               dev_name(dst_bus->dev.parent))


> +               return ret;
> +       }
> +
> +       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)
>  {
> @@ -419,6 +463,96 @@ static int exynos_bus_profile_init_passive(struct exynos_bus *bus,
>         return 0;
>  }
>
> +static struct icc_node *exynos_bus_icc_get_parent(struct exynos_bus *bus)
> +{
> +       struct device_node *np = bus->dev->of_node;
> +       struct of_phandle_args args;
> +       int num, ret;
> +
> +       num = of_count_phandle_with_args(np, "exynos,interconnect-parent-node",
> +                                       "#interconnect-cells");
> +       if (num != 1)
> +               return NULL; /* parent nodes are optional */

You better to add the comment before calling exynos_bus_icc_get_parent
and remove '/* parent nodes are optional */'. Actually, it is not enough
to understand the role of 'interconnect-parent-node' with '/* parent
nodes are optional */'.
And I add my opinion about this comment below.

And I expect that you will add the description and example for
'exynos,interconnect-parent-node' on exynos-bus dt-binding document.

> +
> +       ret = of_parse_phandle_with_args(np, "exynos,interconnect-parent-node",
> +                                       "#interconnect-cells", 0, &args);
> +       if (ret < 0)
> +               return ERR_PTR(ret);
> +
> +       of_node_put(args.np);
> +
> +       return of_icc_get_from_provider(&args);
> +}
> +
> +static int exynos_bus_icc_init(struct exynos_bus *bus)
> +{
> +       static DEFINE_IDA(ida);
> +
> +       struct device *dev = bus->dev;
> +       struct icc_provider *provider = &bus->provider;
> +       struct icc_node *node, *parent_node;
> +       int id, ret;
> +
> +       /* Initialize the interconnect provider */
> +       provider->set = exynos_bus_icc_set;
> +       provider->aggregate = icc_std_aggregate;
> +       provider->xlate = exynos_bus_icc_xlate;
> +       provider->dev = dev;
> +       provider->inter_set = true;
> +       provider->data = bus;
> +
> +       ret = icc_provider_add(provider);
> +       if (ret < 0)
> +               return ret;
> +
> +       ret = id = ida_alloc(&ida, GFP_KERNEL);
> +       if (ret < 0)
> +               goto err_id;
> +
> +       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);
> +

Better to add the following comment. If you add following comment
before calling exynos_bus_icc_get_parent, don't need to add the
same comment into exynos_bus_icc.
    /* If interconnect parent node is not existing, don't use
interconnect feature */

> +       parent_node = exynos_bus_icc_get_parent(bus);
> +       if (IS_ERR(parent_node)) {
> +               ret = PTR_ERR(parent_node);
> +               goto err_parent;
> +       }
> +
> +       if (parent_node) {

Better to change this if statement as following:
else if (parent_node)


> +               ret = icc_link_create(node, parent_node->id);
> +               if (ret < 0)
> +                       goto err_parent;
> +       }
> +
> +       ret = dev_pm_qos_add_request(bus->devfreq->dev.parent, &bus->qos_req,
> +                                       DEV_PM_QOS_MIN_FREQUENCY, 0);

Is it necessary if interconnect-parent-node is not existing?


> +       if (ret < 0)
> +               goto err_request;
> +
> +       return 0;
> +
> +err_request:
> +       if (parent_node)
> +               icc_link_destroy(node, parent_node);
> +err_parent:
> +       icc_node_del(node);
> +       icc_node_destroy(id);
> +err_node:
> +       ida_free(&ida, id);
> +err_id:
> +       icc_provider_del(provider);
> +
> +       return ret;
> +}
> +
>  static int exynos_bus_probe(struct platform_device *pdev)
>  {
>         struct device *dev = &pdev->dev;
> @@ -468,6 +602,16 @@ 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) {
> +               dev_err(dev, "failed to initialize the interconnect provider");
> +               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
>


-- 
Best Regards,
Chanwoo Choi

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

WARNING: multiple messages have this Message-ID (diff)
From: Chanwoo Choi <chanwoo@kernel.org>
To: "Artur Świgoń" <a.swigon@samsung.com>
Cc: devicetree <devicetree@vger.kernel.org>,
	linux-samsung-soc <linux-samsung-soc@vger.kernel.org>,
	Linux PM list <linux-pm@vger.kernel.org>,
	Bartlomiej Zolnierkiewicz <b.zolnierkie@samsung.com>,
	Seung-Woo Kim <sw0312.kim@samsung.com>,
	linux-kernel <linux-kernel@vger.kernel.org>,
	dri-devel <dri-devel@lists.freedesktop.org>,
	Chanwoo Choi <cw00.choi@samsung.com>,
	MyungJoo Ham <myungjoo.ham@samsung.com>,
	Krzysztof Kozlowski <krzk@kernel.org>,
	Leonard Crestez <leonard.crestez@nxp.com>,
	Georgi Djakov <georgi.djakov@linaro.org>,
	linux-arm-kernel <linux-arm-kernel@lists.infradead.org>,
	Marek Szyprowski <m.szyprowski@samsung.com>
Subject: Re: [RFC PATCH v3 5/7] devfreq: exynos-bus: Add interconnect functionality to exynos-bus
Date: Sun, 22 Dec 2019 04:53:31 +0900	[thread overview]
Message-ID: <CAGTfZH0M5yJ3e2mEEc6XE89zV1289C6FvhqVEcuBdi2OgeMtig@mail.gmail.com> (raw)
In-Reply-To: <20191220115653.6487-6-a.swigon@samsung.com>

Hi,

On Fri, Dec 20, 2019 at 9:02 PM Artur Świgoń <a.swigon@samsung.com> wrote:
>
> This patch adds interconnect functionality to the exynos-bus devfreq
> driver.
>
> The SoC topology is a graph (or, more specifically, a tree) and its
> edges are specified using the 'exynos,interconnect-parent-node' in the
> DT. Due to unspecified relative probing order, -EPROBE_DEFER may be
> propagated to ensure that the parent is probed before its children.
>
> 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@samsung.com>
> ---
>  drivers/devfreq/exynos-bus.c | 144 +++++++++++++++++++++++++++++++++++
>  1 file changed, 144 insertions(+)
>
> diff --git a/drivers/devfreq/exynos-bus.c b/drivers/devfreq/exynos-bus.c
> index 9fdb188915e8..694a9581dcdb 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 kbps_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;
>  };
>
>  /*
> @@ -205,6 +216,39 @@ 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 = kbps_to_khz(src->avg_bw);
> +       s32 dst_freq = kbps_to_khz(dst->avg_bw);
> +       int ret;
> +
> +       ret = dev_pm_qos_update_request(&src_bus->qos_req, src_freq);
> +       if (ret < 0) {
> +               dev_err(src_bus->dev, "failed to update PM QoS request");

To catch the correct error point, better to add 'src node' to error message
as following:

dev_err(src_bus->dev, "failed to update PM QoS of %s\n",
                                               dev_name(src_bus->dev.parent))

> +               return ret;
> +       }
> +
> +       ret = dev_pm_qos_update_request(&dst_bus->qos_req, dst_freq);
> +       if (ret < 0) {
> +               dev_err(dst_bus->dev, "failed to update PM QoS request");

ditto.

dev_err(src_bus->dev, "failed to update PM QoS of %s\n",
                                               dev_name(dst_bus->dev.parent))


> +               return ret;
> +       }
> +
> +       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)
>  {
> @@ -419,6 +463,96 @@ static int exynos_bus_profile_init_passive(struct exynos_bus *bus,
>         return 0;
>  }
>
> +static struct icc_node *exynos_bus_icc_get_parent(struct exynos_bus *bus)
> +{
> +       struct device_node *np = bus->dev->of_node;
> +       struct of_phandle_args args;
> +       int num, ret;
> +
> +       num = of_count_phandle_with_args(np, "exynos,interconnect-parent-node",
> +                                       "#interconnect-cells");
> +       if (num != 1)
> +               return NULL; /* parent nodes are optional */

You better to add the comment before calling exynos_bus_icc_get_parent
and remove '/* parent nodes are optional */'. Actually, it is not enough
to understand the role of 'interconnect-parent-node' with '/* parent
nodes are optional */'.
And I add my opinion about this comment below.

And I expect that you will add the description and example for
'exynos,interconnect-parent-node' on exynos-bus dt-binding document.

> +
> +       ret = of_parse_phandle_with_args(np, "exynos,interconnect-parent-node",
> +                                       "#interconnect-cells", 0, &args);
> +       if (ret < 0)
> +               return ERR_PTR(ret);
> +
> +       of_node_put(args.np);
> +
> +       return of_icc_get_from_provider(&args);
> +}
> +
> +static int exynos_bus_icc_init(struct exynos_bus *bus)
> +{
> +       static DEFINE_IDA(ida);
> +
> +       struct device *dev = bus->dev;
> +       struct icc_provider *provider = &bus->provider;
> +       struct icc_node *node, *parent_node;
> +       int id, ret;
> +
> +       /* Initialize the interconnect provider */
> +       provider->set = exynos_bus_icc_set;
> +       provider->aggregate = icc_std_aggregate;
> +       provider->xlate = exynos_bus_icc_xlate;
> +       provider->dev = dev;
> +       provider->inter_set = true;
> +       provider->data = bus;
> +
> +       ret = icc_provider_add(provider);
> +       if (ret < 0)
> +               return ret;
> +
> +       ret = id = ida_alloc(&ida, GFP_KERNEL);
> +       if (ret < 0)
> +               goto err_id;
> +
> +       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);
> +

Better to add the following comment. If you add following comment
before calling exynos_bus_icc_get_parent, don't need to add the
same comment into exynos_bus_icc.
    /* If interconnect parent node is not existing, don't use
interconnect feature */

> +       parent_node = exynos_bus_icc_get_parent(bus);
> +       if (IS_ERR(parent_node)) {
> +               ret = PTR_ERR(parent_node);
> +               goto err_parent;
> +       }
> +
> +       if (parent_node) {

Better to change this if statement as following:
else if (parent_node)


> +               ret = icc_link_create(node, parent_node->id);
> +               if (ret < 0)
> +                       goto err_parent;
> +       }
> +
> +       ret = dev_pm_qos_add_request(bus->devfreq->dev.parent, &bus->qos_req,
> +                                       DEV_PM_QOS_MIN_FREQUENCY, 0);

Is it necessary if interconnect-parent-node is not existing?


> +       if (ret < 0)
> +               goto err_request;
> +
> +       return 0;
> +
> +err_request:
> +       if (parent_node)
> +               icc_link_destroy(node, parent_node);
> +err_parent:
> +       icc_node_del(node);
> +       icc_node_destroy(id);
> +err_node:
> +       ida_free(&ida, id);
> +err_id:
> +       icc_provider_del(provider);
> +
> +       return ret;
> +}
> +
>  static int exynos_bus_probe(struct platform_device *pdev)
>  {
>         struct device *dev = &pdev->dev;
> @@ -468,6 +602,16 @@ 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) {
> +               dev_err(dev, "failed to initialize the interconnect provider");
> +               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
>


-- 
Best Regards,
Chanwoo Choi
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

  reply	other threads:[~2019-12-21 19:54 UTC|newest]

Thread overview: 93+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
     [not found] <CGME20191220120140eucas1p14ad33c20882f8f48e02337ea16754d91@eucas1p1.samsung.com>
2019-12-20 11:56 ` [RFC PATCH v3 0/7] PM / devfreq: Simple QoS for exynos-bus using interconnect Artur Świgoń
2019-12-20 11:56   ` Artur Świgoń
2019-12-20 11:56   ` Artur Świgoń
     [not found]   ` <CGME20191220120141eucas1p11f5fa9d76d17e80e06199cb7a911c482@eucas1p1.samsung.com>
2019-12-20 11:56     ` [RFC PATCH v3 1/7] interconnect: Export of_icc_get_from_provider() Artur Świgoń
2019-12-20 11:56       ` Artur Świgoń
2019-12-20 11:56       ` Artur Świgoń
     [not found]   ` <CGME20191220120142eucas1p1f43c7a862d9c0faa72e14b21d7d697e9@eucas1p1.samsung.com>
2019-12-20 11:56     ` [RFC PATCH v3 2/7] interconnect: Relax requirement in of_icc_get_from_provider() Artur Świgoń
2019-12-20 11:56       ` Artur Świgoń
2019-12-20 11:56       ` Artur Świgoń
2019-12-21 17:20       ` Chanwoo Choi
2019-12-21 17:20         ` Chanwoo Choi
2019-12-21 17:20         ` Chanwoo Choi
     [not found]   ` <CGME20191220120143eucas1p1c9b01ae8c2e4ecd70423ef9d8001536f@eucas1p1.samsung.com>
2019-12-20 11:56     ` [RFC PATCH v3 3/7] interconnect: Allow inter-provider pairs to be configured Artur Świgoń
2019-12-20 11:56       ` Artur Świgoń
2019-12-20 11:56       ` Artur Świgoń
2019-12-22 17:08       ` Chanwoo Choi
2019-12-22 17:08         ` Chanwoo Choi
2019-12-22 17:08         ` Chanwoo Choi
     [not found]   ` <CGME20191220120144eucas1p119ececf161a6d45a6a194e432bbbd1f9@eucas1p1.samsung.com>
2019-12-20 11:56     ` [RFC PATCH v3 4/7] arm: dts: exynos: Add interconnect bindings for Exynos4412 Artur Świgoń
2019-12-20 11:56       ` Artur Świgoń
2019-12-20 11:56       ` Artur Świgoń
2019-12-21 20:00       ` Chanwoo Choi
2019-12-21 20:00         ` Chanwoo Choi
2019-12-21 20:00         ` Chanwoo Choi
2019-12-30 15:44       ` Krzysztof Kozlowski
2019-12-30 15:44         ` Krzysztof Kozlowski
2019-12-30 15:44         ` Krzysztof Kozlowski
2019-12-31  7:18         ` Artur Świgoń
2019-12-31  7:18           ` Artur Świgoń
2019-12-31  7:18           ` Artur Świgoń
2019-12-31  9:22           ` Krzysztof Kozlowski
2019-12-31  9:22             ` Krzysztof Kozlowski
2019-12-31  9:22             ` Krzysztof Kozlowski
2019-12-31  9:41             ` Artur Świgoń
2019-12-31  9:41               ` Artur Świgoń
2019-12-31  9:41               ` Artur Świgoń
2019-12-31 10:02               ` Krzysztof Kozlowski
2019-12-31 10:02                 ` Krzysztof Kozlowski
2019-12-31 10:02                 ` Krzysztof Kozlowski
2019-12-31 10:23                 ` Artur Świgoń
2019-12-31 10:23                   ` Artur Świgoń
2019-12-31 10:23                   ` Artur Świgoń
2019-12-31 10:38                   ` Krzysztof Kozlowski
2019-12-31 10:38                     ` Krzysztof Kozlowski
2019-12-31 10:38                     ` Krzysztof Kozlowski
2019-12-31 11:03                     ` Artur Świgoń
2019-12-31 11:03                       ` Artur Świgoń
2019-12-31 11:03                       ` Artur Świgoń
2020-01-22 16:54       ` Georgi Djakov
2020-01-22 16:54         ` Georgi Djakov
2020-01-22 16:54         ` Georgi Djakov
2020-01-24 11:22         ` Artur Świgoń
2020-01-24 11:22           ` Artur Świgoń
2020-01-24 11:22           ` Artur Świgoń
     [not found]   ` <CGME20191220120145eucas1p295af63eed7b23982d8c49fcf875cec8c@eucas1p2.samsung.com>
2019-12-20 11:56     ` [RFC PATCH v3 5/7] devfreq: exynos-bus: Add interconnect functionality to exynos-bus Artur Świgoń
2019-12-20 11:56       ` Artur Świgoń
2019-12-20 11:56       ` Artur Świgoń
2019-12-21 19:53       ` Chanwoo Choi [this message]
2019-12-21 19:53         ` Chanwoo Choi
2019-12-21 19:53         ` Chanwoo Choi
2019-12-21 19:55         ` Chanwoo Choi
2019-12-21 19:55           ` Chanwoo Choi
2019-12-21 19:55           ` Chanwoo Choi
2020-01-22 17:02       ` Georgi Djakov
2020-01-22 17:02         ` Georgi Djakov
2020-01-22 17:02         ` Georgi Djakov
2020-01-24 11:22         ` Artur Świgoń
2020-01-24 11:22           ` Artur Świgoń
2020-01-24 11:22           ` Artur Świgoń
2020-01-24 12:32           ` Georgi Djakov
2020-01-24 12:32             ` Georgi Djakov
2020-01-24 12:32             ` Georgi Djakov
     [not found]   ` <CGME20191220120146eucas1p25dada01c315215d18bb8a15e3173b52c@eucas1p2.samsung.com>
2019-12-20 11:56     ` [RFC PATCH v3 6/7] arm: dts: exynos: Add interconnects to Exynos4412 mixer Artur Świgoń
2019-12-20 11:56       ` Artur Świgoń
2019-12-20 11:56       ` Artur Świgoń
2019-12-21 20:08       ` Chanwoo Choi
2019-12-21 20:08         ` Chanwoo Choi
2019-12-21 20:08         ` Chanwoo Choi
     [not found]   ` <CGME20191220120146eucas1p22a7b0457be4f378b113f67dc25f2eba7@eucas1p2.samsung.com>
2019-12-20 11:56     ` [RFC PATCH v3 7/7] drm: exynos: mixer: Add interconnect support Artur Świgoń
2019-12-20 11:56       ` Artur Świgoń
2019-12-20 11:56       ` Artur Świgoń
2019-12-21 20:15       ` Chanwoo Choi
2019-12-21 20:15         ` Chanwoo Choi
2019-12-21 20:15         ` Chanwoo Choi
2019-12-24  4:56       ` Inki Dae
2019-12-24  4:56         ` Inki Dae
2019-12-24  4:56         ` Inki Dae
2019-12-30  9:35         ` Artur Świgoń
2019-12-30  9:35           ` Artur Świgoń
2019-12-30  9:35           ` Artur Świgoń
2019-12-21 19:58   ` [RFC PATCH v3 0/7] PM / devfreq: Simple QoS for exynos-bus using interconnect Chanwoo Choi
2019-12-21 19:58     ` Chanwoo Choi
2019-12-21 19:58     ` Chanwoo Choi

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=CAGTfZH0M5yJ3e2mEEc6XE89zV1289C6FvhqVEcuBdi2OgeMtig@mail.gmail.com \
    --to=chanwoo@kernel.org \
    --cc=a.swigon@samsung.com \
    --cc=b.zolnierkie@samsung.com \
    --cc=cw00.choi@samsung.com \
    --cc=devicetree@vger.kernel.org \
    --cc=dri-devel@lists.freedesktop.org \
    --cc=georgi.djakov@linaro.org \
    --cc=inki.dae@samsung.com \
    --cc=krzk@kernel.org \
    --cc=leonard.crestez@nxp.com \
    --cc=linux-arm-kernel@lists.infradead.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-pm@vger.kernel.org \
    --cc=linux-samsung-soc@vger.kernel.org \
    --cc=m.szyprowski@samsung.com \
    --cc=myungjoo.ham@samsung.com \
    --cc=sw0312.kim@samsung.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.