* [PATCH v2] gpio: lynxpoint: lock IRQs when starting them
@ 2013-11-26 10:23 Linus Walleij
2013-11-26 11:49 ` Mika Westerberg
0 siblings, 1 reply; 5+ messages in thread
From: Linus Walleij @ 2013-11-26 10:23 UTC (permalink / raw)
To: linux-gpio, Mathias Nyman, Mika Westerberg
Cc: Alexandre Courbot, Linus Walleij
This uses the new API for tagging GPIO lines as in use by
IRQs. This enforces a few semantic checks on how the underlying
GPIO line is used.
Cc: Mathias Nyman <mathias.nyman@linux.intel.com>
Cc: Mika Westerberg <mika.westerberg@linux.intel.com>
Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
---
ChangeLog v1->v2:
- Explicitly call .enable()/.disable() callbacks from the
startup()/shutdown() callbacks to satisfy implicit semantics.
---
drivers/gpio/gpio-lynxpoint.c | 22 ++++++++++++++++++++++
1 file changed, 22 insertions(+)
diff --git a/drivers/gpio/gpio-lynxpoint.c b/drivers/gpio/gpio-lynxpoint.c
index a0804740a0b7..70831e4b2c8b 100644
--- a/drivers/gpio/gpio-lynxpoint.c
+++ b/drivers/gpio/gpio-lynxpoint.c
@@ -301,6 +301,26 @@ static void lp_irq_disable(struct irq_data *d)
spin_unlock_irqrestore(&lg->lock, flags);
}
+static unsigned int lp_irq_startup(struct irq_data *d)
+{
+ struct lp_gpio *lg = irq_data_get_irq_chip_data(d);
+
+ if (gpio_lock_as_irq(&lg->chip, irqd_to_hwirq(d)))
+ dev_err(lg->chip.dev,
+ "unable to lock HW IRQ %lu for IRQ\n",
+ irqd_to_hwirq(d));
+ lp_irq_enable(d);
+ return 0;
+}
+
+static void lp_irq_shutdown(struct irq_data *d)
+{
+ struct lp_gpio *lg = irq_data_get_irq_chip_data(d);
+
+ lp_irq_disable(d);
+ gpio_unlock_as_irq(&lg->chip, irqd_to_hwirq(d));
+}
+
static struct irq_chip lp_irqchip = {
.name = "LP-GPIO",
.irq_mask = lp_irq_mask,
@@ -308,6 +328,8 @@ static struct irq_chip lp_irqchip = {
.irq_enable = lp_irq_enable,
.irq_disable = lp_irq_disable,
.irq_set_type = lp_irq_type,
+ .irq_startup = lp_irq_startup,
+ .irq_shutdown = lp_irq_shutdown,
.flags = IRQCHIP_SKIP_SET_WAKE,
};
--
1.8.3.1
^ permalink raw reply related [flat|nested] 5+ messages in thread
* Re: [PATCH v2] gpio: lynxpoint: lock IRQs when starting them
2013-11-26 10:23 [PATCH v2] gpio: lynxpoint: lock IRQs when starting them Linus Walleij
@ 2013-11-26 11:49 ` Mika Westerberg
2013-11-26 12:18 ` Javier Martinez Canillas
2013-11-26 12:27 ` Linus Walleij
0 siblings, 2 replies; 5+ messages in thread
From: Mika Westerberg @ 2013-11-26 11:49 UTC (permalink / raw)
To: Linus Walleij; +Cc: linux-gpio, Mathias Nyman, Alexandre Courbot
On Tue, Nov 26, 2013 at 11:23:39AM +0100, Linus Walleij wrote:
> This uses the new API for tagging GPIO lines as in use by
> IRQs. This enforces a few semantic checks on how the underlying
> GPIO line is used.
>
> Cc: Mathias Nyman <mathias.nyman@linux.intel.com>
> Cc: Mika Westerberg <mika.westerberg@linux.intel.com>
> Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
> ---
> ChangeLog v1->v2:
> - Explicitly call .enable()/.disable() callbacks from the
> startup()/shutdown() callbacks to satisfy implicit semantics.
> ---
> drivers/gpio/gpio-lynxpoint.c | 22 ++++++++++++++++++++++
> 1 file changed, 22 insertions(+)
>
> diff --git a/drivers/gpio/gpio-lynxpoint.c b/drivers/gpio/gpio-lynxpoint.c
> index a0804740a0b7..70831e4b2c8b 100644
> --- a/drivers/gpio/gpio-lynxpoint.c
> +++ b/drivers/gpio/gpio-lynxpoint.c
> @@ -301,6 +301,26 @@ static void lp_irq_disable(struct irq_data *d)
> spin_unlock_irqrestore(&lg->lock, flags);
> }
>
> +static unsigned int lp_irq_startup(struct irq_data *d)
> +{
> + struct lp_gpio *lg = irq_data_get_irq_chip_data(d);
> +
> + if (gpio_lock_as_irq(&lg->chip, irqd_to_hwirq(d)))
> + dev_err(lg->chip.dev,
> + "unable to lock HW IRQ %lu for IRQ\n",
> + irqd_to_hwirq(d));
> + lp_irq_enable(d);
I may be missing something but doesn't this now end up calling
lp_irq_enable() twice? First in ->irq_startup() and then later on in
->irq_enable().
^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: [PATCH v2] gpio: lynxpoint: lock IRQs when starting them
2013-11-26 11:49 ` Mika Westerberg
@ 2013-11-26 12:18 ` Javier Martinez Canillas
2013-11-26 12:27 ` Linus Walleij
1 sibling, 0 replies; 5+ messages in thread
From: Javier Martinez Canillas @ 2013-11-26 12:18 UTC (permalink / raw)
To: Mika Westerberg
Cc: Linus Walleij, Linux GPIO List, Mathias Nyman, Alexandre Courbot
Hi Mika,
On Tue, Nov 26, 2013 at 12:49 PM, Mika Westerberg
<mika.westerberg@linux.intel.com> wrote:
> On Tue, Nov 26, 2013 at 11:23:39AM +0100, Linus Walleij wrote:
>> This uses the new API for tagging GPIO lines as in use by
>> IRQs. This enforces a few semantic checks on how the underlying
>> GPIO line is used.
>>
>> Cc: Mathias Nyman <mathias.nyman@linux.intel.com>
>> Cc: Mika Westerberg <mika.westerberg@linux.intel.com>
>> Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
>> ---
>> ChangeLog v1->v2:
>> - Explicitly call .enable()/.disable() callbacks from the
>> startup()/shutdown() callbacks to satisfy implicit semantics.
>> ---
>> drivers/gpio/gpio-lynxpoint.c | 22 ++++++++++++++++++++++
>> 1 file changed, 22 insertions(+)
>>
>> diff --git a/drivers/gpio/gpio-lynxpoint.c b/drivers/gpio/gpio-lynxpoint.c
>> index a0804740a0b7..70831e4b2c8b 100644
>> --- a/drivers/gpio/gpio-lynxpoint.c
>> +++ b/drivers/gpio/gpio-lynxpoint.c
>> @@ -301,6 +301,26 @@ static void lp_irq_disable(struct irq_data *d)
>> spin_unlock_irqrestore(&lg->lock, flags);
>> }
>>
>> +static unsigned int lp_irq_startup(struct irq_data *d)
>> +{
>> + struct lp_gpio *lg = irq_data_get_irq_chip_data(d);
>> +
>> + if (gpio_lock_as_irq(&lg->chip, irqd_to_hwirq(d)))
>> + dev_err(lg->chip.dev,
>> + "unable to lock HW IRQ %lu for IRQ\n",
>> + irqd_to_hwirq(d));
>> + lp_irq_enable(d);
>
> I may be missing something but doesn't this now end up calling
> lp_irq_enable() twice? First in ->irq_startup() and then later on in
> ->irq_enable().
> --
As far as I understood from Grygorii explanation chip->irq_startup()
and chip->irq_enable() are mutually exclusive at
request_[threaded]_irq(). And he seems to be correct by looking at
irq_startup() in irq/chip.c [0].
Thanks a lot and best regards,
Javier
[0]: http://lxr.free-electrons.com/source/kernel/irq/chip.c#L175
^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: [PATCH v2] gpio: lynxpoint: lock IRQs when starting them
2013-11-26 11:49 ` Mika Westerberg
2013-11-26 12:18 ` Javier Martinez Canillas
@ 2013-11-26 12:27 ` Linus Walleij
2013-11-26 12:58 ` Mika Westerberg
1 sibling, 1 reply; 5+ messages in thread
From: Linus Walleij @ 2013-11-26 12:27 UTC (permalink / raw)
To: Mika Westerberg
Cc: linux-gpio@vger.kernel.org, Mathias Nyman, Alexandre Courbot
On Tue, Nov 26, 2013 at 12:49 PM, Mika Westerberg
<mika.westerberg@linux.intel.com> wrote:
> On Tue, Nov 26, 2013 at 11:23:39AM +0100, Linus Walleij wrote:
>> +static unsigned int lp_irq_startup(struct irq_data *d)
>> +{
>> + struct lp_gpio *lg = irq_data_get_irq_chip_data(d);
>> +
>> + if (gpio_lock_as_irq(&lg->chip, irqd_to_hwirq(d)))
>> + dev_err(lg->chip.dev,
>> + "unable to lock HW IRQ %lu for IRQ\n",
>> + irqd_to_hwirq(d));
>> + lp_irq_enable(d);
>
> I may be missing something but doesn't this now end up calling
> lp_irq_enable() twice? First in ->irq_startup() and then later on in
> ->irq_enable().
kernel/irq/chip.c:
int irq_startup(struct irq_desc *desc, bool resend)
{
int ret = 0;
irq_state_clr_disabled(desc);
desc->depth = 0;
if (desc->irq_data.chip->irq_startup) {
ret = desc->irq_data.chip->irq_startup(&desc->irq_data);
irq_state_clr_masked(desc);
} else {
irq_enable(desc);
}
if (resend)
check_irq_resend(desc, desc->irq_data.irq);
return ret;
}
If this hook exists, calls irq_startup() on the chip.
Else, calls irq_enable() which looks like this:
void irq_enable(struct irq_desc *desc)
{
irq_state_clr_disabled(desc);
if (desc->irq_data.chip->irq_enable)
desc->irq_data.chip->irq_enable(&desc->irq_data);
else
desc->irq_data.chip->irq_unmask(&desc->irq_data);
irq_state_clr_masked(desc);
}
I.e. calls .enable() or .unmask().
So there is a strict semantic requirement that if you implement
startup() it should perform the same as .enable(), or .unmask()
depending on whether the former is implemented.
I think this patch is OK ... can you test it on the Lynxpoint?
Yours,
Linus Walleij
^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: [PATCH v2] gpio: lynxpoint: lock IRQs when starting them
2013-11-26 12:27 ` Linus Walleij
@ 2013-11-26 12:58 ` Mika Westerberg
0 siblings, 0 replies; 5+ messages in thread
From: Mika Westerberg @ 2013-11-26 12:58 UTC (permalink / raw)
To: Linus Walleij
Cc: linux-gpio@vger.kernel.org, Mathias Nyman, Alexandre Courbot
On Tue, Nov 26, 2013 at 01:27:21PM +0100, Linus Walleij wrote:
> On Tue, Nov 26, 2013 at 12:49 PM, Mika Westerberg
> <mika.westerberg@linux.intel.com> wrote:
> > On Tue, Nov 26, 2013 at 11:23:39AM +0100, Linus Walleij wrote:
>
> >> +static unsigned int lp_irq_startup(struct irq_data *d)
> >> +{
> >> + struct lp_gpio *lg = irq_data_get_irq_chip_data(d);
> >> +
> >> + if (gpio_lock_as_irq(&lg->chip, irqd_to_hwirq(d)))
> >> + dev_err(lg->chip.dev,
> >> + "unable to lock HW IRQ %lu for IRQ\n",
> >> + irqd_to_hwirq(d));
> >> + lp_irq_enable(d);
> >
> > I may be missing something but doesn't this now end up calling
> > lp_irq_enable() twice? First in ->irq_startup() and then later on in
> > ->irq_enable().
>
> kernel/irq/chip.c:
>
> int irq_startup(struct irq_desc *desc, bool resend)
> {
> int ret = 0;
>
> irq_state_clr_disabled(desc);
> desc->depth = 0;
>
> if (desc->irq_data.chip->irq_startup) {
> ret = desc->irq_data.chip->irq_startup(&desc->irq_data);
> irq_state_clr_masked(desc);
> } else {
> irq_enable(desc);
> }
> if (resend)
> check_irq_resend(desc, desc->irq_data.irq);
> return ret;
> }
>
> If this hook exists, calls irq_startup() on the chip.
> Else, calls irq_enable() which looks like this:
>
> void irq_enable(struct irq_desc *desc)
> {
> irq_state_clr_disabled(desc);
> if (desc->irq_data.chip->irq_enable)
> desc->irq_data.chip->irq_enable(&desc->irq_data);
> else
> desc->irq_data.chip->irq_unmask(&desc->irq_data);
> irq_state_clr_masked(desc);
> }
>
> I.e. calls .enable() or .unmask().
>
> So there is a strict semantic requirement that if you implement
> startup() it should perform the same as .enable(), or .unmask()
> depending on whether the former is implemented.
Thanks for the explanation, got it now :)
> I think this patch is OK ... can you test it on the Lynxpoint?
Tried on haswell/lynxpoint with a slightly modified i2c-hid driver (so that
it is able to use GPIOs as interrupts) and here's what I got:
# cat /sys/kernel/debug/gpio
GPIOs 162-255, platform/INT33C7:00, INT33C7:00:
gpio-217 (hid-irq ) in hi IRQ
Also the device itself works, so
Tested-by: Mika Westerberg <mika.westerberg@linux.intel.com>
^ permalink raw reply [flat|nested] 5+ messages in thread
end of thread, other threads:[~2013-11-26 12:51 UTC | newest]
Thread overview: 5+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2013-11-26 10:23 [PATCH v2] gpio: lynxpoint: lock IRQs when starting them Linus Walleij
2013-11-26 11:49 ` Mika Westerberg
2013-11-26 12:18 ` Javier Martinez Canillas
2013-11-26 12:27 ` Linus Walleij
2013-11-26 12:58 ` Mika Westerberg
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).