From: Hans de Goede <hansg@kernel.org>
To: Armin Wolf <W_Armin@gmx.de>,
sre@kernel.org, hdegoede@redhat.com,
ilpo.jarvinen@linux.intel.com
Cc: linux-pm@vger.kernel.org, platform-driver-x86@vger.kernel.org,
linux-kernel@vger.kernel.org
Subject: Re: [PATCH 1/3] power: supply: core: Add power_supply_get/set_property_direct()
Date: Sat, 28 Jun 2025 11:25:11 +0200 [thread overview]
Message-ID: <b4e077d9-a5f5-47ec-abc7-9e957c32cd5b@kernel.org> (raw)
In-Reply-To: <20250627205124.250433-1-W_Armin@gmx.de>
Hi Armin,
On 27-Jun-25 10:51 PM, Armin Wolf wrote:
> Power supply extensions might want to interact with the underlying
> power supply to retrieve data like serial numbers, charging status
> and more. However doing so causes psy->extensions_sem to be locked
> twice, possibly causing a deadlock.
>
> Provide special variants of power_supply_get/set_property() that
> ignore any power supply extensions and thus do not touch the
> associated psy->extensions_sem lock.
>
> Suggested-by: Hans de Goede <hansg@kernel.org>
> Signed-off-by: Armin Wolf <W_Armin@gmx.de>
Thank you for your work on this.
The entire series looks good to me:
Reviewed-by: Hans de Goede <hansg@kernel.org>
for the series.
There is the question of how to merge this. I think it might
be best for the entire series to go through the power-supply
tree.
Ilpo would that work for you and if yes can we have your ack ?
Sebastian, IMHO this should be merged as fixed not as for-next
material.
Regards,
Hans
> ---
> drivers/power/supply/power_supply_core.c | 82 ++++++++++++++++++++----
> include/linux/power_supply.h | 8 +++
> 2 files changed, 78 insertions(+), 12 deletions(-)
>
> diff --git a/drivers/power/supply/power_supply_core.c b/drivers/power/supply/power_supply_core.c
> index aedb20c1d276..e70ffedf1a80 100644
> --- a/drivers/power/supply/power_supply_core.c
> +++ b/drivers/power/supply/power_supply_core.c
> @@ -1241,9 +1241,8 @@ bool power_supply_has_property(struct power_supply *psy,
> return false;
> }
>
> -int power_supply_get_property(struct power_supply *psy,
> - enum power_supply_property psp,
> - union power_supply_propval *val)
> +static int __power_supply_get_property(struct power_supply *psy, enum power_supply_property psp,
> + union power_supply_propval *val, bool use_extensions)
> {
> struct power_supply_ext_registration *reg;
>
> @@ -1253,10 +1252,14 @@ int power_supply_get_property(struct power_supply *psy,
> return -ENODEV;
> }
>
> - scoped_guard(rwsem_read, &psy->extensions_sem) {
> - power_supply_for_each_extension(reg, psy) {
> - if (power_supply_ext_has_property(reg->ext, psp))
> + if (use_extensions) {
> + scoped_guard(rwsem_read, &psy->extensions_sem) {
> + power_supply_for_each_extension(reg, psy) {
> + if (!power_supply_ext_has_property(reg->ext, psp))
> + continue;
> +
> return reg->ext->get_property(psy, reg->ext, reg->data, psp, val);
> + }
> }
> }
>
> @@ -1267,20 +1270,49 @@ int power_supply_get_property(struct power_supply *psy,
> else
> return -EINVAL;
> }
> +
> +int power_supply_get_property(struct power_supply *psy, enum power_supply_property psp,
> + union power_supply_propval *val)
> +{
> + return __power_supply_get_property(psy, psp, val, true);
> +}
> EXPORT_SYMBOL_GPL(power_supply_get_property);
>
> -int power_supply_set_property(struct power_supply *psy,
> - enum power_supply_property psp,
> - const union power_supply_propval *val)
> +/**
> + * power_supply_get_property_direct - Read a power supply property without checking for extensions
> + * @psy: The power supply
> + * @psp: The power supply property to read
> + * @val: The resulting value of the power supply property
> + *
> + * Read a power supply property without taking into account any power supply extensions registered
> + * on the given power supply. This is mostly useful for power supply extensions that want to access
> + * their own power supply as using power_supply_get_property() directly will result in a potential
> + * deadlock.
> + *
> + * Return: 0 on success or negative error code on failure.
> + */
> +int power_supply_get_property_direct(struct power_supply *psy, enum power_supply_property psp,
> + union power_supply_propval *val)
> +{
> + return __power_supply_get_property(psy, psp, val, false);
> +}
> +EXPORT_SYMBOL_GPL(power_supply_get_property_direct);
> +
> +
> +static int __power_supply_set_property(struct power_supply *psy, enum power_supply_property psp,
> + const union power_supply_propval *val, bool use_extensions)
> {
> struct power_supply_ext_registration *reg;
>
> if (atomic_read(&psy->use_cnt) <= 0)
> return -ENODEV;
>
> - scoped_guard(rwsem_read, &psy->extensions_sem) {
> - power_supply_for_each_extension(reg, psy) {
> - if (power_supply_ext_has_property(reg->ext, psp)) {
> + if (use_extensions) {
> + scoped_guard(rwsem_read, &psy->extensions_sem) {
> + power_supply_for_each_extension(reg, psy) {
> + if (!power_supply_ext_has_property(reg->ext, psp))
> + continue;
> +
> if (reg->ext->set_property)
> return reg->ext->set_property(psy, reg->ext, reg->data,
> psp, val);
> @@ -1295,8 +1327,34 @@ int power_supply_set_property(struct power_supply *psy,
>
> return psy->desc->set_property(psy, psp, val);
> }
> +
> +int power_supply_set_property(struct power_supply *psy, enum power_supply_property psp,
> + const union power_supply_propval *val)
> +{
> + return __power_supply_set_property(psy, psp, val, true);
> +}
> EXPORT_SYMBOL_GPL(power_supply_set_property);
>
> +/**
> + * power_supply_set_property_direct - Write a power supply property without checking for extensions
> + * @psy: The power supply
> + * @psp: The power supply property to write
> + * @val: The value to write to the power supply property
> + *
> + * Write a power supply property without taking into account any power supply extensions registered
> + * on the given power supply. This is mostly useful for power supply extensions that want to access
> + * their own power supply as using power_supply_set_property() directly will result in a potential
> + * deadlock.
> + *
> + * Return: 0 on success or negative error code on failure.
> + */
> +int power_supply_set_property_direct(struct power_supply *psy, enum power_supply_property psp,
> + const union power_supply_propval *val)
> +{
> + return __power_supply_set_property(psy, psp, val, false);
> +}
> +EXPORT_SYMBOL_GPL(power_supply_set_property_direct);
> +
> int power_supply_property_is_writeable(struct power_supply *psy,
> enum power_supply_property psp)
> {
> diff --git a/include/linux/power_supply.h b/include/linux/power_supply.h
> index 45468959dd98..f21f806bfb38 100644
> --- a/include/linux/power_supply.h
> +++ b/include/linux/power_supply.h
> @@ -878,15 +878,23 @@ static inline int power_supply_is_system_supplied(void) { return -ENOSYS; }
> extern int power_supply_get_property(struct power_supply *psy,
> enum power_supply_property psp,
> union power_supply_propval *val);
> +int power_supply_get_property_direct(struct power_supply *psy, enum power_supply_property psp,
> + union power_supply_propval *val);
> #if IS_ENABLED(CONFIG_POWER_SUPPLY)
> extern int power_supply_set_property(struct power_supply *psy,
> enum power_supply_property psp,
> const union power_supply_propval *val);
> +int power_supply_set_property_direct(struct power_supply *psy, enum power_supply_property psp,
> + const union power_supply_propval *val);
> #else
> static inline int power_supply_set_property(struct power_supply *psy,
> enum power_supply_property psp,
> const union power_supply_propval *val)
> { return 0; }
> +static inline int power_supply_set_property_direct(struct power_supply *psy,
> + enum power_supply_property psp,
> + const union power_supply_propval *val)
> +{ return 0; }
> #endif
> extern void power_supply_external_power_changed(struct power_supply *psy);
>
next prev parent reply other threads:[~2025-06-28 9:25 UTC|newest]
Thread overview: 12+ messages / expand[flat|nested] mbox.gz Atom feed top
2025-06-27 20:51 [PATCH 1/3] power: supply: core: Add power_supply_get/set_property_direct() Armin Wolf
2025-06-27 20:51 ` [PATCH 2/3] power: supply: test-power: Test access to extended power supply Armin Wolf
2025-07-06 23:13 ` Sebastian Reichel
2025-06-27 20:51 ` [PATCH 3/3] platform/x86: dell-ddv: Fix taking the psy->extensions_sem lock twice Armin Wolf
2025-06-28 9:25 ` Hans de Goede [this message]
2025-06-28 21:34 ` [PATCH 1/3] power: supply: core: Add power_supply_get/set_property_direct() Armin Wolf
2025-06-30 8:58 ` Ilpo Järvinen
2025-07-06 23:14 ` Sebastian Reichel
2025-07-06 23:11 ` Sebastian Reichel
2025-07-07 13:00 ` Ilpo Järvinen
-- strict thread matches above, loose matches on Subject: below --
2025-06-27 20:53 Armin Wolf
2025-06-27 20:55 ` Armin Wolf
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=b4e077d9-a5f5-47ec-abc7-9e957c32cd5b@kernel.org \
--to=hansg@kernel.org \
--cc=W_Armin@gmx.de \
--cc=hdegoede@redhat.com \
--cc=ilpo.jarvinen@linux.intel.com \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-pm@vger.kernel.org \
--cc=platform-driver-x86@vger.kernel.org \
--cc=sre@kernel.org \
/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.