Re: [PATCH v3 2/2] i2c: Add GPIO-based hotplug gate
From: Michał Mirosław
Date: Thu Aug 10 2023 - 17:52:26 EST
On Sat, Aug 05, 2023 at 09:17:50PM +0200, Krzysztof Kozlowski wrote:
> On 01/08/2023 00:50, Michał Mirosław wrote:
> > On Mon, Jul 31, 2023 at 02:59:41PM +0200, Krzysztof Kozlowski wrote:
> >> On 31/07/2023 10:49, Michał Mirosław wrote:
> >>> On Mon, Jul 31, 2023 at 08:58:14AM +0200, Krzysztof Kozlowski wrote:
> >>>> On 30/07/2023 23:55, Michał Mirosław wrote:
> >>>>> On Sun, Jul 30, 2023 at 10:30:56PM +0200, Krzysztof Kozlowski wrote:
> >>>>>> On 29/07/2023 18:08, Svyatoslav Ryhel wrote:
> >>>>>>> From: Michał Mirosław <mirq-linux@xxxxxxxxxxxx>
> >>>>>>>
> >>>>>>> Implement driver for hot-plugged I2C busses, where some devices on
> >>>>>>> a bus are hot-pluggable and their presence is indicated by GPIO line.
> >>>>> [...]
> >>>>>>> + priv->irq = platform_get_irq(pdev, 0);
> >>>>>>> + if (priv->irq < 0)
> >>>>>>> + return dev_err_probe(&pdev->dev, priv->irq,
> >>>>>>> + "failed to get IRQ %d\n", priv->irq);
> >>>>>>> +
> >>>>>>> + ret = devm_request_threaded_irq(&pdev->dev, priv->irq, NULL,
> >>>>>>> + i2c_hotplug_interrupt,
> >>>>>>> + IRQF_ONESHOT | IRQF_SHARED,
> >>>>>>
> >>>>>> Shared IRQ with devm is a recipe for disaster. Are you sure this is a
> >>>>>> shared one? You have a remove() function which also points that it is
> >>>>>> not safe. You can:
> >>>>>> 1. investigate to be sure it is 100% safe (please document why do you
> >>>>>> think it is safe)
[...]
> >> True, therefore non-devm interrupts are recommended also in such case.
> >> Maybe one of my solutions is actually not recommended.
> >>
> >> However if done right, driver with non-shared interrupts, is expected to
> >> disable interrupts in remove(), thus there is no risk. We have big
> >> discussions in the past about it, so feel free to dig through LKML to
> >> read more about. Anyway shared and devm is a clear no go.
> >
> > Can you share pointers to some of those discussions? Quick search
> > about devm_request_irq() and friends found only a thread from 2013
>
> Just look at CONFIG_DEBUG_SHIRQ. Some things lore points:
> https://lore.kernel.org/all/1592130544-19759-2-git-send-email-krzk@xxxxxxxxxx/
> https://lore.kernel.org/all/20200616103956.GL4447@xxxxxxxxxxxxx/
>
> I think pretty clear:
> https://lore.kernel.org/all/87mu52ca4b.fsf@xxxxxxxxxxxxxxxxxxxxxxx/
> https://lore.kernel.org/all/CA+h21hrxQ1fRahyQGFS42Xuop_Q2petE=No1dft4nVb-ijUu2g@xxxxxxxxxxxxxx/
>
> Also:
> https://lore.kernel.org/all/651c9a33-71e6-c042-58e2-6ad501e984cd@xxxxxxxxxxxxxx/
> https://lore.kernel.org/all/36AC4067-78C6-4986-8B97-591F93E266D8@xxxxxxxxx/
[...]
Thanks! It all looks like a proof by example [1]: a broken driver [2]
was converted to devres [3] and allowed a shared interrupt [4] and now is
used to back an argument that devres and/or shared IRQs are bad. I have
a hard time accepting this line of reasoning.
So: sure, if you disable device's clock, you should first disable the
interrupt handler one way or another, and if you request a shared interrupt
then you have to write the handler expecting spurious invocations anytime
between entry to register_irq() and return from free_irq() (BTW, DEBUG_SHIRQ
is here to help test exactly this). And, when used correctly, devres can
release you from having to write remove() and error paths (but I guess it
might be a challenge to find a single driver that is a complete, good and
complex-enough example).
Coming back from the digression: I gathered following items from the
review of the i2c-hotplug-gpio driver:
1. TODO: register i2c_hotplug_deactivate(priv) using
devm_add_action_or_reset() before registering the IRQ handler
and remove remove();
2. shared IRQ: it is expected to be an edge-triggered, rarely
signalled interrupt and the handler will work fine if called
spuriously; it is not required to be shared for my Transformer,
but I can't say much about other hardware. Would a comment help?
3. TODO: DT-binding needs an expanded example and fixing some schema issues;
4. question from Andi in another thread: I'll answer shortly.
Please correct me if I missed something.
Best Regards
Michał Mirosław
[1] https://en.wikipedia.org/wiki/Proof_by_example
[2] https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=aa11e38ce6fe8846fec046a95cecd5d4690c48cd
[3] https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=9f8a3e7fd5bd08e3fd9847c04a5a445e2994f6b3
[4] https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=df0a2fdab0068f7452bf0a97ea9ba0ad69d49a1f