mbox series

[v2,0/4] irqchip: qcom: pdc: Introduce irq_set_wake call

Message ID 1590253873-11556-1-git-send-email-mkshah@codeaurora.org
Headers show
Series irqchip: qcom: pdc: Introduce irq_set_wake call | expand

Message

Maulik Shah May 23, 2020, 5:11 p.m. UTC
Changes in v2:
- Fix compiler error on gpiolib patch

This series adds support to lazy disable pdc interrupt.

Some drivers using gpio interrupts want to configure gpio for wakeup using
enable_irq_wake() but during suspend entry disables irq and expects system
to resume when interrupt occurs. In the driver resume call interrupt is
re-enabled and removes wakeup capability using disable_irq_wake() one such
example is cros ec driver.

With [1] in documentation saying "An irq can be disabled with disable_irq()
and still wake the system as long as the irq has wake enabled".

The PDC IRQs are currently "unlazy disabled" (disable here means that it
will be masked in PDC & GIC HW GICD_ISENABLER, the moment driver invokes
disable_irq()) such IRQs can not wakeup from low power modes like suspend
to RAM since the driver chosen to disable this.

During suspend entry, no one re-enable/unmask in HW, even if its marked for
wakeup.

One solutions thought to address this problem was...During suspend entry at
last point, irq chip driver re-enable/unmask IRQs in HW that are marked for
wakeup. This was attemped in [2].

This series adds alternate solution to [2] by "lazy disable" IRQs in HW.
The genirq takes care of lazy disable in case if irqchip did not implement
irq_disable callback. Below is high level steps on how this works out..

a. During driver's disable_irq() call, IRQ will be marked disabled in SW
b. IRQ will still be enabled(read unmasked in HW)
c. The device then enters low power mode like suspend to RAM
d. The HW detects unmasked IRQs and wakesup the CPU
e. During resume after local_irq_enable() CPU goes to handle the wake IRQ
f. Generic handler comes to know that IRQ is disabled in SW
g. Generic handler marks IRQ as pending and now invokes mask callback
h. IRQ gets disabled/masked in HW now
i. When driver invokes enable_irq() the SW pending IRQ leads IRQ's handler
j. enable_irq() will again enable/unmask in HW

[1] https://www.spinics.net/lists/kernel/msg3398294.html
[2] https://patchwork.kernel.org/patch/11466021/

Maulik Shah (4):
  gpio: gpiolib: Allow GPIO IRQs to lazy disable
  pinctrl: qcom: Remove irq_disable callback from msmgpio irqchip
  pinctrl: qcom: Add msmgpio irqchip flags
  irqchip: qcom-pdc: Introduce irq_set_wake call

 drivers/gpio/gpiolib.c             | 55 +++++++++++++++++++++++++-------------
 drivers/irqchip/qcom-pdc.c         | 33 ++++++++++++-----------
 drivers/pinctrl/qcom/pinctrl-msm.c | 15 ++---------
 include/linux/gpio/driver.h        | 13 +++++++++
 4 files changed, 68 insertions(+), 48 deletions(-)

Comments

Maulik Shah May 27, 2020, 12:30 p.m. UTC | #1
Hi,

On 5/27/2020 3:17 PM, Stephen Boyd wrote:
> Quoting Maulik Shah (2020-05-23 10:11:12)
>> Add irqchip specific flags for msmgpio irqchip to mask non wakeirqs
>> during suspend and mask before setting irq type.
> Why do we need to mask before setting irq type? Does something go wrong?
> Can you explain in the commit text?

i don't think anything goes wrong but there might be a case where some 
driver changing type at runtime,

masking before changing type should make sure any spurious interrupt is 
not detected during this operation.

>
>> Signed-off-by: Maulik Shah <mkshah@codeaurora.org>
> Does this need a Fixes tag?
Thanks i will add.
>
>> ---
>>   drivers/pinctrl/qcom/pinctrl-msm.c | 2 ++
>>   1 file changed, 2 insertions(+)
>>
>> diff --git a/drivers/pinctrl/qcom/pinctrl-msm.c b/drivers/pinctrl/qcom/pinctrl-msm.c
>> index 2419023..b909ffe 100644
>> --- a/drivers/pinctrl/qcom/pinctrl-msm.c
>> +++ b/drivers/pinctrl/qcom/pinctrl-msm.c
>> @@ -1143,6 +1143,8 @@ static int msm_gpio_init(struct msm_pinctrl *pctrl)
>>          pctrl->irq_chip.irq_release_resources = msm_gpio_irq_relres;
>>          pctrl->irq_chip.irq_set_affinity = msm_gpio_irq_set_affinity;
>>          pctrl->irq_chip.irq_set_vcpu_affinity = msm_gpio_irq_set_vcpu_affinity;
>> +       pctrl->irq_chip.flags = IRQCHIP_MASK_ON_SUSPEND
> This is sort of sad. We have to set the IRQCHIP_MASK_ON_SUSPEND flag
> here so that genirq can call the mask op during suspend for the parent
> irqchip (pdc)?
During suspend, suspend_device_irq() will check this flag in msmgpio 
irqchip and then call it to mask if its not marked for wakeup.

in this case, setting this flag will call first invoke gpiolib's 
callback  (we override in first patch of this series), then it goes to 
msmgpio chip's mask callback,

this call will then get forwarded to its parent PDC and then to PDC's 
parent GIC.

This seems the way hierarchical irqchip works. i don't see any issue 
with this.
> Is there some way to not need to do that and instead let
> genirq do mask on suspend at the chip level instead of the irq level?
>
>> +                               | IRQCHIP_SET_TYPE_MASKED;
>>   
>>          np = of_parse_phandle(pctrl->dev->of_node, "wakeup-parent", 0);
>>          if (np) {