* Re: [PATCH 1/5] of/device: Add of_ functions for device_link_{add,remove} [not found] ` <d038f078-08dc-41ff-edc2-12f37d88a8a3@intel.com> @ 2019-04-24 13:39 ` Benjamin GAIGNARD 2019-04-24 13:39 ` Benjamin GAIGNARD 0 siblings, 1 reply; 2+ messages in thread From: Benjamin GAIGNARD @ 2019-04-24 13:39 UTC (permalink / raw) To: Rafael J. Wysocki, agx@sigxcpu.org, Yannick FERTRE Cc: dmitry.torokhov@gmail.com, robh+dt@kernel.org, mark.rutland@arm.com, hadess@hadess.net, frowand.list@gmail.com, m.felsch@pengutronix.de, arnd@arndb.de, linux-input@vger.kernel.org, devicetree@vger.kernel.org, linux-kernel@vger.kernel.org, linux-stm32@st-md-mailman.stormreply.com, broonie@kernel.org, Linux PM On 4/24/19 3:06 PM, Rafael J. Wysocki wrote: > On 4/24/2019 12:19 PM, Benjamin Gaignard wrote: >> Allows to create and remove links between consumer and suppliers from >> device-tree data. Use 'links-add' property from consumer node to setup >> a link with a list of suppliers. > > One immediate question about this one is why stateless links are > better here? They aren't better, it is just because I wanted to keep one of_ function for each related device_link_* functions. > >> Consumers will be suspend before their suppliers and resume after them. >> >> Add devm_of_device_links_add() to automatically remove the links >> when the device is unbound from the bus. > > And this might not be necessary even with managed links. I guess I could use DL_FLAG_PM_RUNTIME and DL_FLAG_AUTOREMOVE_CONSUMER flags and just keep of_device_links_add() but the naming will not be explicit. > >> Signed-off-by: Benjamin Gaignard <benjamin.gaignard@st.com> >> --- >> drivers/of/device.c | 103 >> ++++++++++++++++++++++++++++++++++++++++++++++ >> include/linux/of_device.h | 20 +++++++++ >> 2 files changed, 123 insertions(+) >> >> diff --git a/drivers/of/device.c b/drivers/of/device.c >> index 3717f2a20d0d..011ba9bf7642 100644 >> --- a/drivers/of/device.c >> +++ b/drivers/of/device.c >> @@ -336,3 +336,106 @@ int of_device_uevent_modalias(struct device >> *dev, struct kobj_uevent_env *env) >> return 0; >> } >> EXPORT_SYMBOL_GPL(of_device_uevent_modalias); >> + >> +/** >> + * of_device_links_add - Create links between consumer and suppliers >> from >> + * device tree data >> + * >> + * @consumer: consumer device >> + * >> + * Returns 0 on success, < 0 on failure. >> + */ >> +int of_device_links_add(struct device *consumer) >> +{ >> + struct device_node *np; >> + struct platform_device *pdev; >> + int i = 0; >> + >> + np = of_parse_phandle(consumer->of_node, "links-add", i++); >> + while (np) { >> + pdev = of_find_device_by_node(np); >> + of_node_put(np); >> + if (!pdev) >> + return -EINVAL; >> + >> + device_link_add(consumer, &pdev->dev, DL_FLAG_STATELESS); >> + platform_device_put(pdev); >> + >> + np = of_parse_phandle(consumer->of_node, "links-add", i++); >> + } >> + >> + return 0; >> +} >> +EXPORT_SYMBOL_GPL(of_device_links_add); >> + >> +/** >> + * of_device_links_remove - Remove links between consumer and >> suppliers from >> + * device tree data >> + * >> + * @consumer: consumer device >> + * >> + * Returns 0 on success, < 0 on failure. >> + */ >> +int of_device_links_remove(struct device *consumer) >> +{ >> + struct device_node *np; >> + struct platform_device *pdev; >> + int i = 0; >> + >> + np = of_parse_phandle(consumer->of_node, "links-add", i++); >> + while (np) { >> + pdev = of_find_device_by_node(np); >> + of_node_put(np); >> + if (!pdev) >> + return -EINVAL; >> + >> + device_link_remove(consumer, &pdev->dev); >> + platform_device_put(pdev); >> + >> + np = of_parse_phandle(consumer->of_node, "links-add", i++); >> + } >> + >> + return 0; >> +} >> +EXPORT_SYMBOL_GPL(of_device_links_remove); >> + >> +static void devm_of_device_links_remove(struct device *dev, void *res) >> +{ >> + of_device_links_remove(*(struct device **)res); >> +} >> + >> +/** >> + * devm_of_device_links_add - Create links between consumer and >> suppliers >> + * from device tree data >> + * >> + * @consumer: consumer device >> + * >> + * Returns 0 on success, < 0 on failure. >> + * >> + * Similar to of_device_links_add(), but will automatically call >> + * of_device_links_remove() when the device is unbound from the bus. >> + */ >> +int devm_of_device_links_add(struct device *consumer) >> +{ >> + struct device **ptr; >> + int ret; >> + >> + if (!consumer) >> + return -EINVAL; >> + >> + ptr = devres_alloc(devm_of_device_links_remove, >> + sizeof(*ptr), GFP_KERNEL); >> + if (!ptr) >> + return -ENOMEM; >> + >> + ret = of_device_links_add(consumer); >> + if (ret < 0) { >> + devres_free(ptr); >> + } else { >> + *ptr = consumer; >> + devres_add(consumer, ptr); >> + } >> + >> + return ret; >> +} >> +EXPORT_SYMBOL_GPL(devm_of_device_links_add); >> diff --git a/include/linux/of_device.h b/include/linux/of_device.h >> index 8d31e39dd564..ad01db6828e8 100644 >> --- a/include/linux/of_device.h >> +++ b/include/linux/of_device.h >> @@ -41,6 +41,11 @@ extern int of_device_request_module(struct device >> *dev); >> extern void of_device_uevent(struct device *dev, struct >> kobj_uevent_env *env); >> extern int of_device_uevent_modalias(struct device *dev, struct >> kobj_uevent_env *env); >> + >> +extern int of_device_links_add(struct device *consumer); >> +extern int of_device_links_remove(struct device *consumer); >> +extern int devm_of_device_links_add(struct device *consumer); >> + >> static inline void of_device_node_put(struct device *dev) >> { >> of_node_put(dev->of_node); >> @@ -91,6 +96,21 @@ static inline int of_device_uevent_modalias(struct >> device *dev, >> return -ENODEV; >> } >> +static int of_device_links_add(struct device *consumer) >> +{ >> + return 0; >> +} >> + >> +static int of_device_links_remove(struct device *consumer) >> +{ >> + return 0; >> +} >> + >> +static int devm_of_device_links_add(struct device *consumer) >> +{ >> + return 0; >> +} >> + >> static inline void of_device_node_put(struct device *dev) { } >> static inline const struct of_device_id *__of_match_device( > > ^ permalink raw reply [flat|nested] 2+ messages in thread
* Re: [PATCH 1/5] of/device: Add of_ functions for device_link_{add,remove} 2019-04-24 13:39 ` [PATCH 1/5] of/device: Add of_ functions for device_link_{add,remove} Benjamin GAIGNARD @ 2019-04-24 13:39 ` Benjamin GAIGNARD 0 siblings, 0 replies; 2+ messages in thread From: Benjamin GAIGNARD @ 2019-04-24 13:39 UTC (permalink / raw) To: Rafael J. Wysocki, agx@sigxcpu.org, Yannick FERTRE Cc: dmitry.torokhov@gmail.com, robh+dt@kernel.org, mark.rutland@arm.com, hadess@hadess.net, frowand.list@gmail.com, m.felsch@pengutronix.de, arnd@arndb.de, linux-input@vger.kernel.org, devicetree@vger.kernel.org, linux-kernel@vger.kernel.org, linux-stm32@st-md-mailman.stormreply.com, broonie@kernel.org, Linux PM On 4/24/19 3:06 PM, Rafael J. Wysocki wrote: > On 4/24/2019 12:19 PM, Benjamin Gaignard wrote: >> Allows to create and remove links between consumer and suppliers from >> device-tree data. Use 'links-add' property from consumer node to setup >> a link with a list of suppliers. > > One immediate question about this one is why stateless links are > better here? They aren't better, it is just because I wanted to keep one of_ function for each related device_link_* functions. > >> Consumers will be suspend before their suppliers and resume after them. >> >> Add devm_of_device_links_add() to automatically remove the links >> when the device is unbound from the bus. > > And this might not be necessary even with managed links. I guess I could use DL_FLAG_PM_RUNTIME and DL_FLAG_AUTOREMOVE_CONSUMER flags and just keep of_device_links_add() but the naming will not be explicit. > >> Signed-off-by: Benjamin Gaignard <benjamin.gaignard@st.com> >> --- >> drivers/of/device.c | 103 >> ++++++++++++++++++++++++++++++++++++++++++++++ >> include/linux/of_device.h | 20 +++++++++ >> 2 files changed, 123 insertions(+) >> >> diff --git a/drivers/of/device.c b/drivers/of/device.c >> index 3717f2a20d0d..011ba9bf7642 100644 >> --- a/drivers/of/device.c >> +++ b/drivers/of/device.c >> @@ -336,3 +336,106 @@ int of_device_uevent_modalias(struct device >> *dev, struct kobj_uevent_env *env) >> return 0; >> } >> EXPORT_SYMBOL_GPL(of_device_uevent_modalias); >> + >> +/** >> + * of_device_links_add - Create links between consumer and suppliers >> from >> + * device tree data >> + * >> + * @consumer: consumer device >> + * >> + * Returns 0 on success, < 0 on failure. >> + */ >> +int of_device_links_add(struct device *consumer) >> +{ >> + struct device_node *np; >> + struct platform_device *pdev; >> + int i = 0; >> + >> + np = of_parse_phandle(consumer->of_node, "links-add", i++); >> + while (np) { >> + pdev = of_find_device_by_node(np); >> + of_node_put(np); >> + if (!pdev) >> + return -EINVAL; >> + >> + device_link_add(consumer, &pdev->dev, DL_FLAG_STATELESS); >> + platform_device_put(pdev); >> + >> + np = of_parse_phandle(consumer->of_node, "links-add", i++); >> + } >> + >> + return 0; >> +} >> +EXPORT_SYMBOL_GPL(of_device_links_add); >> + >> +/** >> + * of_device_links_remove - Remove links between consumer and >> suppliers from >> + * device tree data >> + * >> + * @consumer: consumer device >> + * >> + * Returns 0 on success, < 0 on failure. >> + */ >> +int of_device_links_remove(struct device *consumer) >> +{ >> + struct device_node *np; >> + struct platform_device *pdev; >> + int i = 0; >> + >> + np = of_parse_phandle(consumer->of_node, "links-add", i++); >> + while (np) { >> + pdev = of_find_device_by_node(np); >> + of_node_put(np); >> + if (!pdev) >> + return -EINVAL; >> + >> + device_link_remove(consumer, &pdev->dev); >> + platform_device_put(pdev); >> + >> + np = of_parse_phandle(consumer->of_node, "links-add", i++); >> + } >> + >> + return 0; >> +} >> +EXPORT_SYMBOL_GPL(of_device_links_remove); >> + >> +static void devm_of_device_links_remove(struct device *dev, void *res) >> +{ >> + of_device_links_remove(*(struct device **)res); >> +} >> + >> +/** >> + * devm_of_device_links_add - Create links between consumer and >> suppliers >> + * from device tree data >> + * >> + * @consumer: consumer device >> + * >> + * Returns 0 on success, < 0 on failure. >> + * >> + * Similar to of_device_links_add(), but will automatically call >> + * of_device_links_remove() when the device is unbound from the bus. >> + */ >> +int devm_of_device_links_add(struct device *consumer) >> +{ >> + struct device **ptr; >> + int ret; >> + >> + if (!consumer) >> + return -EINVAL; >> + >> + ptr = devres_alloc(devm_of_device_links_remove, >> + sizeof(*ptr), GFP_KERNEL); >> + if (!ptr) >> + return -ENOMEM; >> + >> + ret = of_device_links_add(consumer); >> + if (ret < 0) { >> + devres_free(ptr); >> + } else { >> + *ptr = consumer; >> + devres_add(consumer, ptr); >> + } >> + >> + return ret; >> +} >> +EXPORT_SYMBOL_GPL(devm_of_device_links_add); >> diff --git a/include/linux/of_device.h b/include/linux/of_device.h >> index 8d31e39dd564..ad01db6828e8 100644 >> --- a/include/linux/of_device.h >> +++ b/include/linux/of_device.h >> @@ -41,6 +41,11 @@ extern int of_device_request_module(struct device >> *dev); >> extern void of_device_uevent(struct device *dev, struct >> kobj_uevent_env *env); >> extern int of_device_uevent_modalias(struct device *dev, struct >> kobj_uevent_env *env); >> + >> +extern int of_device_links_add(struct device *consumer); >> +extern int of_device_links_remove(struct device *consumer); >> +extern int devm_of_device_links_add(struct device *consumer); >> + >> static inline void of_device_node_put(struct device *dev) >> { >> of_node_put(dev->of_node); >> @@ -91,6 +96,21 @@ static inline int of_device_uevent_modalias(struct >> device *dev, >> return -ENODEV; >> } >> +static int of_device_links_add(struct device *consumer) >> +{ >> + return 0; >> +} >> + >> +static int of_device_links_remove(struct device *consumer) >> +{ >> + return 0; >> +} >> + >> +static int devm_of_device_links_add(struct device *consumer) >> +{ >> + return 0; >> +} >> + >> static inline void of_device_node_put(struct device *dev) { } >> static inline const struct of_device_id *__of_match_device( > > ^ permalink raw reply [flat|nested] 2+ messages in thread
end of thread, other threads:[~2019-04-24 13:39 UTC | newest]
Thread overview: 2+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
[not found] <20190424101913.1534-1-benjamin.gaignard@st.com>
[not found] ` <20190424101913.1534-2-benjamin.gaignard@st.com>
[not found] ` <d038f078-08dc-41ff-edc2-12f37d88a8a3@intel.com>
2019-04-24 13:39 ` [PATCH 1/5] of/device: Add of_ functions for device_link_{add,remove} Benjamin GAIGNARD
2019-04-24 13:39 ` Benjamin GAIGNARD
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox