From: Oleksij Rempel <o.rempel@pengutronix.de>
To: Carlo Szelinsky <github@szelinsky.de>
Cc: Jakub Kicinski <kuba@kernel.org>,
Kory Maincent <kory.maincent@bootlin.com>,
Andrew Lunn <andrew+netdev@lunn.ch>,
"David S . Miller" <davem@davemloft.net>,
Eric Dumazet <edumazet@google.com>,
Paolo Abeni <pabeni@redhat.com>,
Krzysztof Kozlowski <krzk@kernel.org>,
netdev@vger.kernel.org, linux-kernel@vger.kernel.org,
linux-leds@vger.kernel.org
Subject: Re: [PATCH net-next v5 2/2] net: pse-pd: add LED trigger support via notification path
Date: Sun, 17 May 2026 11:33:09 +0200 [thread overview]
Message-ID: <agmLVW-WfHf3S_2J@pengutronix.de> (raw)
In-Reply-To: <20260516101759.1686592-1-github@szelinsky.de>
Hi Carlo,
Thank you for your work!
On Sat, May 16, 2026 at 12:17:59PM +0200, Carlo Szelinsky wrote:
> Hi Jakub,
>
> Thanks for the second pass! I went through all four points and
> would love to clarify some points before moving on to v6.
> Replying inline again:
>
> On Mon, 4 May 2026 18:57:59 -0700 Jakub Kicinski wrote:
> > > + pcdev->pi_led_trigs = devm_kcalloc(dev, pcdev->nr_lines,
> > > + sizeof(*pcdev->pi_led_trigs),
> > > + GFP_KERNEL);
> >
> > Since devm resources are released in strict LIFO order, and pi_led_trigs
> > is allocated here after the regulators are registered in
> > pse_controller_register(), will the pi_led_trigs array be freed before
> > the regulators are unregistered on driver unbind?
> >
> > When the regulator core later unregisters the regulators and flushes
> > pending disables, could it invoke pse_pi_disable() and call pse_led_update(),
> > dereferencing the dangling pcdev->pi_led_trigs pointer?
>
> Yes, seems to be real: devm LIFO frees pi_led_trigs before the
> regulators get unregistered. If a deferred disable fires during
> regulator_unregister() (via flush_work on rdev->disable_work),
> pse_pi_disable() runs and pse_led_update() walks freed memory.
>
> But for one piece I got a question: the same path also touches
> pcdev->pi. pse_pi_disable() calls _pse_pi_disable(), before:
> pse_led_update(), and _pse_pi_disable() derefs pcdev->pi[id]
> (via pse_pi_deallocate_pw_budget(&pcdev->pi[id]) and
> pcdev->pi[id].pw_d). pcdev->pi is already freed by
> pse_release_pis() in pse_controller_unregister(). So setting
> pi_led_trigs NULL only fixes the LED half, or?
>
> Should v6 also handle pcdev->pi here (NULL after
> kfree, plus a guard in _pse_pi_disable)? Feels like the same
> class of bug as 1/2's reorder, just on the regulator-cleanup
> path. Or is a separate fix outside this patch series better?
Please, send fixes for existing bugs separately for stable fixes.
> > > + for (i = 0; i < pcdev->nr_lines; i++) {
> > > + struct pse_pi_led_triggers *trigs = &pcdev->pi_led_trigs[i];
> > [...]
> > > + trigs->delivering.name = devm_kasprintf(dev, GFP_KERNEL,
> > > + "pse-%s:port%d:delivering",
> > > + dev_id, i);
> > [...]
> > > + ret = devm_led_trigger_register(dev, &trigs->delivering);
> >
> > Regulators are exposed before this code runs in pse_controller_register().
> > What happens if a consumer calls regulator_enable() concurrently?
> > [...] Since devm_led_trigger_register() hasn't initialized the trigger's
> > internal led_cdevs list head yet, will led_trigger_event() attempt to
> > iterate a zeroed memory list and cause a NULL pointer dereference?
>
> Right, but the window is microseconds wide (between setting
> trigs->delivering.name and devm_led_trigger_register() returning).
> You'd need a consumer racing during probe to hit it, right?
>
> The fix seems to be simple: move pse_led_triggers_register() before the
> regulator loop in pse_controller_register(). of_load_pse_pis()
> runs earlier so pi[]/pi[i].np is already filled in, which is
> all the trigger loop needs. Regulators only get exposed after
> triggers are fully registered, no race window left.
>
> Question: Do you agree with that solution for v6?
Sounds plausible.
> > > + ret = pse_led_triggers_register(pcdev);
> > > + if (ret) {
> > > + /* LED triggers are non-essential for power delivery; warn
> > > + * and continue. [...]
> > > + dev_warn(pcdev->dev, "Failed to register LED triggers: %d\n",
> > > + ret);
> > > + pcdev->pi_led_trigs = NULL;
> > > + }
> >
> > If pse_led_triggers_register() fails halfway through, the device probe
> > still succeeds, which means devm cleanup will not run. Could the
> > successfully registered LED triggers from earlier loop iterations remain
> > registered indefinitely with the LED subsystem?
>
> Would love to clarify this one with you as well: devm cleanup does still run
> on driver unbind, since devm_led_trigger_register() attaches a
> per-call release action. So the partially-registered triggers
> stay in sysfs until unbind, but they're not leaked across it.
> And with pi_led_trigs = NULL, pse_led_update() short-circuits
> so the orphans never fire either. So practically they're inert
> sysfs entries until unbind, not a leak.
>
> That said, I agree the "warn and orphan" middle ground is a bit
> weird. So which path should I follow:
>
> 1) treat LED reg failure as fatal: return ret, fail probe.
> Smallest change, matches the rest of the function. The
> "non-essential" framing was mine, happy to drop it.
> 2) wrap the registration in a devres group so partial
> failures roll back the triggers we did manage to register.
> 3) leave as-is, since devm already cleans up on unbind.
>
> I'd go with 1) since OOM during probe is fatal for most things
> anyway, but happy to do 2) or 3) if you have a preference.
1 feels for me as most straightforward way. I would expect to see this
kind of errors in a pre-production phase not in the end product.
> > > + /* Update LEDs for described PIs regardless of consumer state.
> > [...]
> > > + if (pcdev->no_of_pse_pi || pcdev->pi[i].np)
> > > + pse_led_update(pcdev, i);
> >
> > The docstring for pse_led_update() requires it to be called with pcdev->lock
> > held. Does calling it here locklessly inside the event handler violate
> > that locking contract?
>
> From what I see, both callers of pse_handle_events() hold pcdev->lock
> across the call:
>
> * pse_isr() takes mutex_lock(&pcdev->lock) at line 1524, then
> calls pse_handle_events() at line 1531.
> * pse_poll_worker() takes mutex_lock(&pcdev->lock) at line 1547,
> then calls pse_handle_events() at line 1551.
>
> So pse_led_update() is running with the lock held in both paths.
>
> Tbh I don't get completely what the AI is flagging here, or is
> this a false positive?
Yes.
> If false positive, I'd still add
> lockdep_assert_held(&pcdev->lock) in pse_led_update() and
> pse_handle_events() to make the contract explicit and catch any
> future caller that forgets, but that would be documentation,
> not a bug fix.
I do not know what here went wrong, too much context?
In the raw log it looks like LLM was able to detect proper locking:
https://sashiko.dev/#/log/35678
"I'm seeing that in `pse_controller_register`, the code takes the mutex,
iterates and calls `pse_led_update`. Also, in `pse_handle_events`, this
is happening again, and this is called from `pse_isr` with
`mutex_lock(&pcdev->lock)`. And in `pse_pi_enable`, it's again called
within the mutex. So, `pse_led_update` *always* seems to be called with
the lock held. This is consistent and good."
And later:
"However, there's no evidence that `pcdev->lock` is held inside
`pse_handle_events`. Furthermore, the code uses a separate
`ntf_fifo_lock`."
We can ignore it. In case if you cares, lockdep_assert_held() sounds
good, comments can be misread. I would add it to pse_handle_events(), it
will make it fully visible for AI and detectable by CI.
> So plan for v6 [2/2], pending your answers:
> * NULL pcdev->pi_led_trigs in pse_controller_unregister()
> (and possibly NULL pcdev->pi too, depending on your answer?)
> * move pse_led_triggers_register() before the regulator loop
> * add lockdep_assert_held() (assuming is a false positive)
> * whichever option you pick for question 3?
>
> Depending on what we do with [1/2], I'll roll v6 with your
> decisions baked in.
>
> Sorry for the long text...
>
> Cheers,
> Carlo
Thank you!
Best Regards,
Oleksij
--
Pengutronix e.K. | |
Steuerwalder Str. 21 | http://www.pengutronix.de/ |
31137 Hildesheim, Germany | Phone: +49-5121-206917-0 |
Amtsgericht Hildesheim, HRA 2686 | Fax: +49-5121-206917-5555 |
prev parent reply other threads:[~2026-05-17 9:33 UTC|newest]
Thread overview: 18+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-04-10 12:44 [PATCH net-next v4 0/2] net: pse-pd: add poll path and LED trigger support Carlo Szelinsky
2026-04-10 12:44 ` [PATCH net-next v4 1/2] net: pse-pd: add devm_pse_poll_helper() Carlo Szelinsky
2026-04-13 22:50 ` Jakub Kicinski
2026-04-14 14:05 ` Kory Maincent
2026-04-14 14:11 ` Kory Maincent
2026-05-23 19:20 ` Carlo Szelinsky
2026-04-10 12:44 ` [PATCH net-next v4 2/2] net: pse-pd: add LED trigger support via notification path Carlo Szelinsky
2026-04-13 22:51 ` Jakub Kicinski
2026-04-13 22:53 ` Jakub Kicinski
2026-04-29 21:32 ` [PATCH net-next v5 0/2] net: pse-pd: add poll path and LED trigger support Carlo Szelinsky
2026-04-29 21:32 ` [PATCH net-next v5 1/2] net: pse-pd: add devm_pse_poll_helper() Carlo Szelinsky
2026-05-05 1:57 ` Jakub Kicinski
2026-05-16 10:17 ` Carlo Szelinsky
2026-05-17 9:57 ` Oleksij Rempel
2026-04-29 21:32 ` [PATCH net-next v5 2/2] net: pse-pd: add LED trigger support via notification path Carlo Szelinsky
2026-05-05 1:57 ` Jakub Kicinski
2026-05-16 10:17 ` Carlo Szelinsky
2026-05-17 9:33 ` Oleksij Rempel [this message]
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=agmLVW-WfHf3S_2J@pengutronix.de \
--to=o.rempel@pengutronix.de \
--cc=andrew+netdev@lunn.ch \
--cc=davem@davemloft.net \
--cc=edumazet@google.com \
--cc=github@szelinsky.de \
--cc=kory.maincent@bootlin.com \
--cc=krzk@kernel.org \
--cc=kuba@kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-leds@vger.kernel.org \
--cc=netdev@vger.kernel.org \
--cc=pabeni@redhat.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.