All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH] genirq: fix trigger flags check for shared irqs
@ 2016-01-26 10:31 Brian Starkey
  2016-01-26 20:45 ` Thomas Gleixner
  0 siblings, 1 reply; 17+ messages in thread
From: Brian Starkey @ 2016-01-26 10:31 UTC (permalink / raw)
  To: tglx; +Cc: linux-kernel, marc.zyngier

For shared interrupts, if one requester passes in any IRQF_TRIGGER_*
flags whilst another doesn't, __setup_irq() can erroneously fail.

The no-flags case should be treated as "already configured", so change
__setup_irq() to only check that the flags match if any have been
provided.

Signed-off-by: Brian Starkey <brian.starkey@arm.com>
Reviewed-by: Marc Zyngier <marc.zyngier@arm.com>
---

 kernel/irq/manage.c |   17 +++++++++++------
 1 file changed, 11 insertions(+), 6 deletions(-)

diff --git a/kernel/irq/manage.c b/kernel/irq/manage.c
index a79d267..032c8fa 100644
--- a/kernel/irq/manage.c
+++ b/kernel/irq/manage.c
@@ -995,14 +995,10 @@ __setup_irq(unsigned int irq, struct irq_desc *desc, struct irqaction *new)
 	old = *old_ptr;
 	if (old) {
 		/*
-		 * Can't share interrupts unless both agree to and are
-		 * the same type (level, edge, polarity). So both flag
-		 * fields must have IRQF_SHARED set and the bits which
-		 * set the trigger type must match. Also all must
-		 * agree on ONESHOT.
+		 * Can't share interrupts unless both agree to and all
+		 * must agree on ONESHOT
 		 */
 		if (!((old->flags & new->flags) & IRQF_SHARED) ||
-		    ((old->flags ^ new->flags) & IRQF_TRIGGER_MASK) ||
 		    ((old->flags ^ new->flags) & IRQF_ONESHOT))
 			goto mismatch;
 
@@ -1014,6 +1010,15 @@ __setup_irq(unsigned int irq, struct irq_desc *desc, struct irqaction *new)
 		/* add new interrupt at end of irq queue */
 		do {
 			/*
+			 * If 'new' requests a trigger type it must match all
+			 * previously requested trigger types.
+			 */
+			if (((new->flags & IRQF_TRIGGER_MASK) &&
+			     (old->flags & IRQF_TRIGGER_MASK)) &&
+			    ((new->flags ^ old->flags) & IRQF_TRIGGER_MASK))
+				goto mismatch;
+
+			/*
 			 * Or all existing action->thread_mask bits,
 			 * so we can find the next zero bit for this
 			 * new action.
-- 
1.7.9.5

^ permalink raw reply related	[flat|nested] 17+ messages in thread

* Re: [PATCH] genirq: fix trigger flags check for shared irqs
  2016-01-26 10:31 [PATCH] genirq: fix trigger flags check for shared irqs Brian Starkey
@ 2016-01-26 20:45 ` Thomas Gleixner
  2016-01-28  9:59   ` Brian Starkey
  0 siblings, 1 reply; 17+ messages in thread
From: Thomas Gleixner @ 2016-01-26 20:45 UTC (permalink / raw)
  To: Brian Starkey; +Cc: linux-kernel, marc.zyngier

On Tue, 26 Jan 2016, Brian Starkey wrote:

> For shared interrupts, if one requester passes in any IRQF_TRIGGER_*
> flags whilst another doesn't, __setup_irq() can erroneously fail.
> 
> The no-flags case should be treated as "already configured", so change
> __setup_irq() to only check that the flags match if any have been
> provided.

What happens if that "already configured", i.e. the default setting, is
conflicting with the newly requested interrupt?

I rather prefer the failure than the resulting silent wreckage.
 
Thanks,

	tglx

^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: [PATCH] genirq: fix trigger flags check for shared irqs
  2016-01-26 20:45 ` Thomas Gleixner
@ 2016-01-28  9:59   ` Brian Starkey
  2016-01-28 10:29     ` Thomas Gleixner
  0 siblings, 1 reply; 17+ messages in thread
From: Brian Starkey @ 2016-01-28  9:59 UTC (permalink / raw)
  To: Thomas Gleixner; +Cc: linux-kernel, marc.zyngier

Hi Thomas,

Thanks for taking a look at this.

On Tue, Jan 26, 2016 at 09:45:32PM +0100, Thomas Gleixner wrote:
>On Tue, 26 Jan 2016, Brian Starkey wrote:
>
>> For shared interrupts, if one requester passes in any IRQF_TRIGGER_*
>> flags whilst another doesn't, __setup_irq() can erroneously fail.
>>
>> The no-flags case should be treated as "already configured", so change
>> __setup_irq() to only check that the flags match if any have been
>> provided.
>
>What happens if that "already configured", i.e. the default setting, is
>conflicting with the newly requested interrupt?
>
>I rather prefer the failure than the resulting silent wreckage.
>

Yes, I agree that would be best avoided. It seems to me that this case
is actually handled a bit lower down:

	} else if (new->flags & IRQF_TRIGGER_MASK) {
		unsigned int nmsk = new->flags & IRQF_TRIGGER_MASK;
		unsigned int omsk = irq_settings_get_trigger_mask(desc);

		if (nmsk != omsk)
			/* hope the handler works with current  trigger mode */
			pr_warning("irq %d uses trigger mode %u; requested %u\n",
				   irq, nmsk, omsk);
	}

Perhaps that should be louder/fatal?

Best regards,

-Brian

>Thanks,
>
>	tglx
>

^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: [PATCH] genirq: fix trigger flags check for shared irqs
  2016-01-28  9:59   ` Brian Starkey
@ 2016-01-28 10:29     ` Thomas Gleixner
  2016-01-28 11:10       ` Brian Starkey
  0 siblings, 1 reply; 17+ messages in thread
From: Thomas Gleixner @ 2016-01-28 10:29 UTC (permalink / raw)
  To: Brian Starkey; +Cc: linux-kernel, marc.zyngier

Brian,

On Thu, 28 Jan 2016, Brian Starkey wrote:
> On Tue, Jan 26, 2016 at 09:45:32PM +0100, Thomas Gleixner wrote:
> > On Tue, 26 Jan 2016, Brian Starkey wrote:
> > 
> > > For shared interrupts, if one requester passes in any IRQF_TRIGGER_*
> > > flags whilst another doesn't, __setup_irq() can erroneously fail.
> > > 
> > > The no-flags case should be treated as "already configured", so change
> > > __setup_irq() to only check that the flags match if any have been
> > > provided.
> > 
> > What happens if that "already configured", i.e. the default setting, is
> > conflicting with the newly requested interrupt?
> > 
> > I rather prefer the failure than the resulting silent wreckage.
> > 
> 
> Yes, I agree that would be best avoided. It seems to me that this case
> is actually handled a bit lower down:
> 
> 	} else if (new->flags & IRQF_TRIGGER_MASK) {
> 		unsigned int nmsk = new->flags & IRQF_TRIGGER_MASK;
> 		unsigned int omsk = irq_settings_get_trigger_mask(desc);
> 
> 		if (nmsk != omsk)
> 			/* hope the handler works with current  trigger mode
> */
> 			pr_warning("irq %d uses trigger mode %u; requested
> %u\n",
> 				   irq, nmsk, omsk);
> 	}
> 
> Perhaps that should be louder/fatal?

Perhaps. So what's the actual problem case you are trying to solve?

Thanks,

	tglx

^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: [PATCH] genirq: fix trigger flags check for shared irqs
  2016-01-28 10:29     ` Thomas Gleixner
@ 2016-01-28 11:10       ` Brian Starkey
  2016-01-28 11:49         ` Thomas Gleixner
  0 siblings, 1 reply; 17+ messages in thread
From: Brian Starkey @ 2016-01-28 11:10 UTC (permalink / raw)
  To: Thomas Gleixner; +Cc: linux-kernel, marc.zyngier

On Thu, Jan 28, 2016 at 11:29:21AM +0100, Thomas Gleixner wrote:
>Brian,
>
>On Thu, 28 Jan 2016, Brian Starkey wrote:
>> On Tue, Jan 26, 2016 at 09:45:32PM +0100, Thomas Gleixner wrote:
>> > On Tue, 26 Jan 2016, Brian Starkey wrote:
>> >
>> > > For shared interrupts, if one requester passes in any IRQF_TRIGGER_*
>> > > flags whilst another doesn't, __setup_irq() can erroneously fail.
>> > >
>> > > The no-flags case should be treated as "already configured", so change
>> > > __setup_irq() to only check that the flags match if any have been
>> > > provided.
>> >
>> > What happens if that "already configured", i.e. the default setting, is
>> > conflicting with the newly requested interrupt?
>> >
>> > I rather prefer the failure than the resulting silent wreckage.
>> >
>>
>> Yes, I agree that would be best avoided. It seems to me that this case
>> is actually handled a bit lower down:
>>
>> 	} else if (new->flags & IRQF_TRIGGER_MASK) {
>> 		unsigned int nmsk = new->flags & IRQF_TRIGGER_MASK;
>> 		unsigned int omsk = irq_settings_get_trigger_mask(desc);
>>
>> 		if (nmsk != omsk)
>> 			/* hope the handler works with current  trigger mode
>> */
>> 			pr_warning("irq %d uses trigger mode %u; requested
>> %u\n",
>> 				   irq, nmsk, omsk);
>> 	}
>>
>> Perhaps that should be louder/fatal?
>
>Perhaps. So what's the actual problem case you are trying to solve?

I've got a few devices on the same interrupt line. One driver does
something along these lines:

	res = platform_get_resource(dev, IORESOURCE_IRQ, 0);
	flags = (res->flags & IRQF_TRIGGER_MASK) | IRQF_SHARED;
	request_irq(res->start, handler, flags, "name", dev);

This seems pretty reasonable. The problem is since 4a43d686fe33:
    of/irq: Pass trigger type in IRQ resource flags[1]
the trigger type information from device-tree is in res->flags.

So when the other drivers don't pass in any flags, they fail the check
in __setup_irq().

Changing the former driver to remove the flags doesn't seem right, and
adding flags to the latter would imply adding flags to _every_ driver,
which is an awful lot to change - and I'm not sure it would be possible
and/or effective in all cases.

Cheers,

-Brian

[1]http://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/commit/?id=4a43d686fe336cc0e955c4400ba4d3fcff788786

>
>Thanks,
>
>	tglx
>

^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: [PATCH] genirq: fix trigger flags check for shared irqs
  2016-01-28 11:10       ` Brian Starkey
@ 2016-01-28 11:49         ` Thomas Gleixner
  2016-01-28 12:22             ` Brian Starkey
  2016-01-28 15:58             ` Rob Herring
  0 siblings, 2 replies; 17+ messages in thread
From: Thomas Gleixner @ 2016-01-28 11:49 UTC (permalink / raw)
  To: Brian Starkey
  Cc: LKML, Marc Zyngier, Tomasz Figa, Rob Herring, Frank Rowand,
	Grant Likely, devicetree

On Thu, 28 Jan 2016, Brian Starkey wrote:
> I've got a few devices on the same interrupt line. One driver does

Just for the record: When will hardware folks finally understand that shared
interrupt lines are a nightmare?

> something along these lines:
> 
> 	res = platform_get_resource(dev, IORESOURCE_IRQ, 0);
> 	flags = (res->flags & IRQF_TRIGGER_MASK) | IRQF_SHARED;
> 	request_irq(res->start, handler, flags, "name", dev);
> 
> This seems pretty reasonable. The problem is since 4a43d686fe33:
>    of/irq: Pass trigger type in IRQ resource flags[1]
> the trigger type information from device-tree is in res->flags.
> 
> So when the other drivers don't pass in any flags, they fail the check
> in __setup_irq().
> 
> Changing the former driver to remove the flags doesn't seem right, and
> adding flags to the latter would imply adding flags to _every_ driver,
> which is an awful lot to change - and I'm not sure it would be possible
> and/or effective in all cases.

So that commit does:

   r->flags = IORESOURCE_IRQ | irqd_get_trigger_type(irq_get_irq_data(irq));

which reads the current setting of the interrupt line.

Now we pass exactly that to request_irq(). So first irq_of_parse_and_map()
configures the interrupt type when mapping it and then hands in the same type
information when requesting the irq.

I have no idea what the purpose of this is and the changelog of that commit is
completely useless, sigh!

I've cc'ed the author and the device tree folks. Perhaps are they able to
explain what this commit tries to 'fix'.

Thanks,

	tglx

^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: [PATCH] genirq: fix trigger flags check for shared irqs
  2016-01-28 11:49         ` Thomas Gleixner
@ 2016-01-28 12:22             ` Brian Starkey
  2016-01-28 15:58             ` Rob Herring
  1 sibling, 0 replies; 17+ messages in thread
From: Brian Starkey @ 2016-01-28 12:22 UTC (permalink / raw)
  To: Thomas Gleixner
  Cc: LKML, Marc Zyngier, Tomasz Figa, Rob Herring, Frank Rowand,
	Grant Likely, devicetree

On Thu, Jan 28, 2016 at 12:49:37PM +0100, Thomas Gleixner wrote:
>On Thu, 28 Jan 2016, Brian Starkey wrote:
>> I've got a few devices on the same interrupt line. One driver does
>
>Just for the record: When will hardware folks finally understand that shared
>interrupt lines are a nightmare?
>

In general, agreed. In this case though I think they get some grace - my
devices are all in an FPGA which only has one interrupt line to the SoC.

>> something along these lines:
>>
>> 	res = platform_get_resource(dev, IORESOURCE_IRQ, 0);
>> 	flags = (res->flags & IRQF_TRIGGER_MASK) | IRQF_SHARED;
>> 	request_irq(res->start, handler, flags, "name", dev);
>>
>> This seems pretty reasonable. The problem is since 4a43d686fe33:
>>    of/irq: Pass trigger type in IRQ resource flags[1]
>> the trigger type information from device-tree is in res->flags.
>>
>> So when the other drivers don't pass in any flags, they fail the check
>> in __setup_irq().
>>
>> Changing the former driver to remove the flags doesn't seem right, and
>> adding flags to the latter would imply adding flags to _every_ driver,
>> which is an awful lot to change - and I'm not sure it would be possible
>> and/or effective in all cases.
>
>So that commit does:
>
>   r->flags = IORESOURCE_IRQ | irqd_get_trigger_type(irq_get_irq_data(irq));
>
>which reads the current setting of the interrupt line.
>
>Now we pass exactly that to request_irq(). So first irq_of_parse_and_map()
>configures the interrupt type when mapping it and then hands in the same type
>information when requesting the irq.

Right, there's some redundancy here.

>
>I have no idea what the purpose of this is and the changelog of that commit is
>completely useless, sigh!
>
>I've cc'ed the author and the device tree folks. Perhaps are they able to
>explain what this commit tries to 'fix'.

This 'fix' is what makes me hit the problem - but even without it I
think the problem still exists.

It seems like in principle two drivers ought to be able to do

	request_irq(irq, handler, IRQF_SHARED | IRQF_TRIGGER_HIGH, ...);

and

	request_irq(irq, handler, IRQF_SHARED, ...);

without the latter call failing. Or do you disagree?

-Brian

>
>Thanks,
>
>	tglx
>

^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: [PATCH] genirq: fix trigger flags check for shared irqs
@ 2016-01-28 12:22             ` Brian Starkey
  0 siblings, 0 replies; 17+ messages in thread
From: Brian Starkey @ 2016-01-28 12:22 UTC (permalink / raw)
  To: Thomas Gleixner
  Cc: LKML, Marc Zyngier, Tomasz Figa, Rob Herring, Frank Rowand,
	Grant Likely, devicetree-u79uwXL29TY76Z2rM5mHXA

On Thu, Jan 28, 2016 at 12:49:37PM +0100, Thomas Gleixner wrote:
>On Thu, 28 Jan 2016, Brian Starkey wrote:
>> I've got a few devices on the same interrupt line. One driver does
>
>Just for the record: When will hardware folks finally understand that shared
>interrupt lines are a nightmare?
>

In general, agreed. In this case though I think they get some grace - my
devices are all in an FPGA which only has one interrupt line to the SoC.

>> something along these lines:
>>
>> 	res = platform_get_resource(dev, IORESOURCE_IRQ, 0);
>> 	flags = (res->flags & IRQF_TRIGGER_MASK) | IRQF_SHARED;
>> 	request_irq(res->start, handler, flags, "name", dev);
>>
>> This seems pretty reasonable. The problem is since 4a43d686fe33:
>>    of/irq: Pass trigger type in IRQ resource flags[1]
>> the trigger type information from device-tree is in res->flags.
>>
>> So when the other drivers don't pass in any flags, they fail the check
>> in __setup_irq().
>>
>> Changing the former driver to remove the flags doesn't seem right, and
>> adding flags to the latter would imply adding flags to _every_ driver,
>> which is an awful lot to change - and I'm not sure it would be possible
>> and/or effective in all cases.
>
>So that commit does:
>
>   r->flags = IORESOURCE_IRQ | irqd_get_trigger_type(irq_get_irq_data(irq));
>
>which reads the current setting of the interrupt line.
>
>Now we pass exactly that to request_irq(). So first irq_of_parse_and_map()
>configures the interrupt type when mapping it and then hands in the same type
>information when requesting the irq.

Right, there's some redundancy here.

>
>I have no idea what the purpose of this is and the changelog of that commit is
>completely useless, sigh!
>
>I've cc'ed the author and the device tree folks. Perhaps are they able to
>explain what this commit tries to 'fix'.

This 'fix' is what makes me hit the problem - but even without it I
think the problem still exists.

It seems like in principle two drivers ought to be able to do

	request_irq(irq, handler, IRQF_SHARED | IRQF_TRIGGER_HIGH, ...);

and

	request_irq(irq, handler, IRQF_SHARED, ...);

without the latter call failing. Or do you disagree?

-Brian

>
>Thanks,
>
>	tglx
>
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: [PATCH] genirq: fix trigger flags check for shared irqs
@ 2016-01-28 13:37               ` Thomas Gleixner
  0 siblings, 0 replies; 17+ messages in thread
From: Thomas Gleixner @ 2016-01-28 13:37 UTC (permalink / raw)
  To: Brian Starkey
  Cc: LKML, Marc Zyngier, Tomasz Figa, Rob Herring, Frank Rowand,
	Grant Likely, devicetree

On Thu, 28 Jan 2016, Brian Starkey wrote:

> On Thu, Jan 28, 2016 at 12:49:37PM +0100, Thomas Gleixner wrote:
> > On Thu, 28 Jan 2016, Brian Starkey wrote:
> > > I've got a few devices on the same interrupt line. One driver does
> > 
> > Just for the record: When will hardware folks finally understand that shared
> > interrupt lines are a nightmare?
> > 
> 
> In general, agreed. In this case though I think they get some grace - my
> devices are all in an FPGA which only has one interrupt line to the SoC.

No grace at all. Adding an real irqchip which lets you mask/unmask each device
irq seperately and having a demux handler on the interrupt line to the SoC is
the proper solution for this for lots of reasons.

> > So that commit does:
> > 
> >   r->flags = IORESOURCE_IRQ | irqd_get_trigger_type(irq_get_irq_data(irq));
> > 
> > which reads the current setting of the interrupt line.
> > 
> > Now we pass exactly that to request_irq(). So first irq_of_parse_and_map()
> > configures the interrupt type when mapping it and then hands in the same
> > type
> > information when requesting the irq.
> 
> Right, there's some redundancy here.

Some?

> > I have no idea what the purpose of this is and the changelog of that commit
> > is
> > completely useless, sigh!
> > 
> > I've cc'ed the author and the device tree folks. Perhaps are they able to
> > explain what this commit tries to 'fix'.
> 
> This 'fix' is what makes me hit the problem - but even without it I
> think the problem still exists.
> 
> It seems like in principle two drivers ought to be able to do
> 
> 	request_irq(irq, handler, IRQF_SHARED | IRQF_TRIGGER_HIGH, ...);
> 
> and
> 
> 	request_irq(irq, handler, IRQF_SHARED, ...);
> 
> without the latter call failing. Or do you disagree?

In principle I agree. The issue is that it really depends on the particular
hardware situation.

If there is an explicit requirement for one driver - expressed by a trigger
flag - and the other driver relies on the default configuration, then this
might cause malfunction.

The hassle is, that IRQF_TRIGGER_NONE has unclear semantics. It can mean "I
don't care" or "I rely on the hw configuration". The latter is what worries
me.

first driver: 

      creates the mapping and sets the trigger type according to the DT
      setting.

      driver calls request_irq() with IRQF_TRIGGER_NONE. It relies on the DT
      setting to be correct.

second driver:

      Finds an existing mapping. Now we have two cases:

      1) flat irqdomains:

      	 The DT setting is applied to the trigger type unconditionally.

	 So if that setting is contrary to first drivers DT setting then we
	 are already in trouble.

	 If the driver uses IRQF_TRIGGER_NONE, bad luck as nothing will notice
	 the issue.

      2) hierarchical irqdomains

      	 That code path ignores the type setting of the second driver and
      	 leaves the irq line in the existing state.

	 If the driver uses IRQF_TRIGGER_NONE, bad luck as nothing will notice
	 the issue.
      	 
So we have two problems here.

1) We should detect the mismatch already in the mapping function.

   But, that's hard for legacy reasons. Interrupts can be mapped at early boot
   with hardware default settings and we currently have no way to distinguish
   that. It shouldn't be hard to fix that.

2) How to deal with the mismatch in request_irq()

   Relaxing the check is not really a good decision. So what we could do is:

   if ((new_action->flags & IRQF_TRIGGER_MASK) == IRQF_TRIGGER_NONE)
      	new_action->flags |= irqd_get_trigger_type(irqdata);

   Now that has an issue as well. If the driver requests with
   IRQF_TRIGGER_NONE and does an explicit type setting afterwards, the
   action->flags still do not reflect it.

The whole trigger handling versus shared interrupts needs some deep thoughts
and I really want to understand what that of commit 4a43d686fe336 before
making any decisions.

Thanks,

	tglx

^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: [PATCH] genirq: fix trigger flags check for shared irqs
@ 2016-01-28 13:37               ` Thomas Gleixner
  0 siblings, 0 replies; 17+ messages in thread
From: Thomas Gleixner @ 2016-01-28 13:37 UTC (permalink / raw)
  To: Brian Starkey
  Cc: LKML, Marc Zyngier, Tomasz Figa, Rob Herring, Frank Rowand,
	Grant Likely, devicetree-u79uwXL29TY76Z2rM5mHXA

On Thu, 28 Jan 2016, Brian Starkey wrote:

> On Thu, Jan 28, 2016 at 12:49:37PM +0100, Thomas Gleixner wrote:
> > On Thu, 28 Jan 2016, Brian Starkey wrote:
> > > I've got a few devices on the same interrupt line. One driver does
> > 
> > Just for the record: When will hardware folks finally understand that shared
> > interrupt lines are a nightmare?
> > 
> 
> In general, agreed. In this case though I think they get some grace - my
> devices are all in an FPGA which only has one interrupt line to the SoC.

No grace at all. Adding an real irqchip which lets you mask/unmask each device
irq seperately and having a demux handler on the interrupt line to the SoC is
the proper solution for this for lots of reasons.

> > So that commit does:
> > 
> >   r->flags = IORESOURCE_IRQ | irqd_get_trigger_type(irq_get_irq_data(irq));
> > 
> > which reads the current setting of the interrupt line.
> > 
> > Now we pass exactly that to request_irq(). So first irq_of_parse_and_map()
> > configures the interrupt type when mapping it and then hands in the same
> > type
> > information when requesting the irq.
> 
> Right, there's some redundancy here.

Some?

> > I have no idea what the purpose of this is and the changelog of that commit
> > is
> > completely useless, sigh!
> > 
> > I've cc'ed the author and the device tree folks. Perhaps are they able to
> > explain what this commit tries to 'fix'.
> 
> This 'fix' is what makes me hit the problem - but even without it I
> think the problem still exists.
> 
> It seems like in principle two drivers ought to be able to do
> 
> 	request_irq(irq, handler, IRQF_SHARED | IRQF_TRIGGER_HIGH, ...);
> 
> and
> 
> 	request_irq(irq, handler, IRQF_SHARED, ...);
> 
> without the latter call failing. Or do you disagree?

In principle I agree. The issue is that it really depends on the particular
hardware situation.

If there is an explicit requirement for one driver - expressed by a trigger
flag - and the other driver relies on the default configuration, then this
might cause malfunction.

The hassle is, that IRQF_TRIGGER_NONE has unclear semantics. It can mean "I
don't care" or "I rely on the hw configuration". The latter is what worries
me.

first driver: 

      creates the mapping and sets the trigger type according to the DT
      setting.

      driver calls request_irq() with IRQF_TRIGGER_NONE. It relies on the DT
      setting to be correct.

second driver:

      Finds an existing mapping. Now we have two cases:

      1) flat irqdomains:

      	 The DT setting is applied to the trigger type unconditionally.

	 So if that setting is contrary to first drivers DT setting then we
	 are already in trouble.

	 If the driver uses IRQF_TRIGGER_NONE, bad luck as nothing will notice
	 the issue.

      2) hierarchical irqdomains

      	 That code path ignores the type setting of the second driver and
      	 leaves the irq line in the existing state.

	 If the driver uses IRQF_TRIGGER_NONE, bad luck as nothing will notice
	 the issue.
      	 
So we have two problems here.

1) We should detect the mismatch already in the mapping function.

   But, that's hard for legacy reasons. Interrupts can be mapped at early boot
   with hardware default settings and we currently have no way to distinguish
   that. It shouldn't be hard to fix that.

2) How to deal with the mismatch in request_irq()

   Relaxing the check is not really a good decision. So what we could do is:

   if ((new_action->flags & IRQF_TRIGGER_MASK) == IRQF_TRIGGER_NONE)
      	new_action->flags |= irqd_get_trigger_type(irqdata);

   Now that has an issue as well. If the driver requests with
   IRQF_TRIGGER_NONE and does an explicit type setting afterwards, the
   action->flags still do not reflect it.

The whole trigger handling versus shared interrupts needs some deep thoughts
and I really want to understand what that of commit 4a43d686fe336 before
making any decisions.

Thanks,

	tglx
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: [PATCH] genirq: fix trigger flags check for shared irqs
  2016-01-28 11:49         ` Thomas Gleixner
@ 2016-01-28 15:58             ` Rob Herring
  2016-01-28 15:58             ` Rob Herring
  1 sibling, 0 replies; 17+ messages in thread
From: Rob Herring @ 2016-01-28 15:58 UTC (permalink / raw)
  To: Thomas Gleixner
  Cc: Brian Starkey, LKML, Marc Zyngier, Tomasz Figa, Frank Rowand,
	Grant Likely, devicetree

On Thu, Jan 28, 2016 at 5:49 AM, Thomas Gleixner <tglx@linutronix.de> wrote:
> On Thu, 28 Jan 2016, Brian Starkey wrote:
>> I've got a few devices on the same interrupt line. One driver does
>
> Just for the record: When will hardware folks finally understand that shared
> interrupt lines are a nightmare?
>
>> something along these lines:
>>
>>       res = platform_get_resource(dev, IORESOURCE_IRQ, 0);
>>       flags = (res->flags & IRQF_TRIGGER_MASK) | IRQF_SHARED;
>>       request_irq(res->start, handler, flags, "name", dev);
>>
>> This seems pretty reasonable. The problem is since 4a43d686fe33:
>>    of/irq: Pass trigger type in IRQ resource flags[1]
>> the trigger type information from device-tree is in res->flags.
>>
>> So when the other drivers don't pass in any flags, they fail the check
>> in __setup_irq().
>>
>> Changing the former driver to remove the flags doesn't seem right, and
>> adding flags to the latter would imply adding flags to _every_ driver,
>> which is an awful lot to change - and I'm not sure it would be possible
>> and/or effective in all cases.
>
> So that commit does:
>
>    r->flags = IORESOURCE_IRQ | irqd_get_trigger_type(irq_get_irq_data(irq));
>
> which reads the current setting of the interrupt line.
>
> Now we pass exactly that to request_irq(). So first irq_of_parse_and_map()
> configures the interrupt type when mapping it and then hands in the same type
> information when requesting the irq.
>
> I have no idea what the purpose of this is and the changelog of that commit is
> completely useless, sigh!
>
> I've cc'ed the author and the device tree folks. Perhaps are they able to
> explain what this commit tries to 'fix'.

It's certainly not clear what driver was being fixed. I think the
intention was to provide the trigger flags from the DT to drivers in a
standard, non-DT specific way. The implementation of it certainly
seems convoluted. The usecase I can think of is drivers may need the
trigger information for cases where the device can support different
trigger modes/polarity. The DT says which trigger mode to use and the
device and irqchip need to be programmed to match. IIRC, SMSC ethernet
chips frequently used on ARM boards do this.

Rob

^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: [PATCH] genirq: fix trigger flags check for shared irqs
@ 2016-01-28 15:58             ` Rob Herring
  0 siblings, 0 replies; 17+ messages in thread
From: Rob Herring @ 2016-01-28 15:58 UTC (permalink / raw)
  To: Thomas Gleixner
  Cc: Brian Starkey, LKML, Marc Zyngier, Tomasz Figa, Frank Rowand,
	Grant Likely, devicetree-u79uwXL29TY76Z2rM5mHXA

On Thu, Jan 28, 2016 at 5:49 AM, Thomas Gleixner <tglx-hfZtesqFncYOwBW4kG4KsQ@public.gmane.org> wrote:
> On Thu, 28 Jan 2016, Brian Starkey wrote:
>> I've got a few devices on the same interrupt line. One driver does
>
> Just for the record: When will hardware folks finally understand that shared
> interrupt lines are a nightmare?
>
>> something along these lines:
>>
>>       res = platform_get_resource(dev, IORESOURCE_IRQ, 0);
>>       flags = (res->flags & IRQF_TRIGGER_MASK) | IRQF_SHARED;
>>       request_irq(res->start, handler, flags, "name", dev);
>>
>> This seems pretty reasonable. The problem is since 4a43d686fe33:
>>    of/irq: Pass trigger type in IRQ resource flags[1]
>> the trigger type information from device-tree is in res->flags.
>>
>> So when the other drivers don't pass in any flags, they fail the check
>> in __setup_irq().
>>
>> Changing the former driver to remove the flags doesn't seem right, and
>> adding flags to the latter would imply adding flags to _every_ driver,
>> which is an awful lot to change - and I'm not sure it would be possible
>> and/or effective in all cases.
>
> So that commit does:
>
>    r->flags = IORESOURCE_IRQ | irqd_get_trigger_type(irq_get_irq_data(irq));
>
> which reads the current setting of the interrupt line.
>
> Now we pass exactly that to request_irq(). So first irq_of_parse_and_map()
> configures the interrupt type when mapping it and then hands in the same type
> information when requesting the irq.
>
> I have no idea what the purpose of this is and the changelog of that commit is
> completely useless, sigh!
>
> I've cc'ed the author and the device tree folks. Perhaps are they able to
> explain what this commit tries to 'fix'.

It's certainly not clear what driver was being fixed. I think the
intention was to provide the trigger flags from the DT to drivers in a
standard, non-DT specific way. The implementation of it certainly
seems convoluted. The usecase I can think of is drivers may need the
trigger information for cases where the device can support different
trigger modes/polarity. The DT says which trigger mode to use and the
device and irqchip need to be programmed to match. IIRC, SMSC ethernet
chips frequently used on ARM boards do this.

Rob
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: [PATCH] genirq: fix trigger flags check for shared irqs
  2016-01-28 15:58             ` Rob Herring
  (?)
@ 2016-01-28 20:06             ` Thomas Gleixner
  2016-01-29  4:17                 ` Tomasz Figa
  -1 siblings, 1 reply; 17+ messages in thread
From: Thomas Gleixner @ 2016-01-28 20:06 UTC (permalink / raw)
  To: Rob Herring
  Cc: Brian Starkey, LKML, Marc Zyngier, Tomasz Figa, Frank Rowand,
	Grant Likely, devicetree

On Thu, 28 Jan 2016, Rob Herring wrote:
> On Thu, Jan 28, 2016 at 5:49 AM, Thomas Gleixner <tglx@linutronix.de> wrote:
> > I've cc'ed the author and the device tree folks. Perhaps are they able to
> > explain what this commit tries to 'fix'.
> 
> It's certainly not clear what driver was being fixed. I think the
> intention was to provide the trigger flags from the DT to drivers in a
> standard, non-DT specific way. The implementation of it certainly
> seems convoluted. The usecase I can think of is drivers may need the
> trigger information for cases where the device can support different
> trigger modes/polarity. The DT says which trigger mode to use and the
> device and irqchip need to be programmed to match. IIRC, SMSC ethernet
> chips frequently used on ARM boards do this.

I can see that the driver wants this information, but why would one feed that
back into request_irq() when the interrupt was already configured by DT.

Still confused.

Thanks,

	tglx

^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: [PATCH] genirq: fix trigger flags check for shared irqs
  2016-01-28 20:06             ` Thomas Gleixner
@ 2016-01-29  4:17                 ` Tomasz Figa
  0 siblings, 0 replies; 17+ messages in thread
From: Tomasz Figa @ 2016-01-29  4:17 UTC (permalink / raw)
  To: Thomas Gleixner
  Cc: Rob Herring, Brian Starkey, LKML, Marc Zyngier, Frank Rowand,
	Grant Likely, devicetree

Hi Thomas,

2016-01-29 5:06 GMT+09:00 Thomas Gleixner <tglx@linutronix.de>:
> On Thu, 28 Jan 2016, Rob Herring wrote:
>> On Thu, Jan 28, 2016 at 5:49 AM, Thomas Gleixner <tglx@linutronix.de> wrote:
>> > I've cc'ed the author and the device tree folks. Perhaps are they able to
>> > explain what this commit tries to 'fix'.
>>
>> It's certainly not clear what driver was being fixed. I think the
>> intention was to provide the trigger flags from the DT to drivers in a
>> standard, non-DT specific way. The implementation of it certainly
>> seems convoluted. The usecase I can think of is drivers may need the
>> trigger information for cases where the device can support different
>> trigger modes/polarity. The DT says which trigger mode to use and the
>> device and irqchip need to be programmed to match. IIRC, SMSC ethernet
>> chips frequently used on ARM boards do this.
>
> I can see that the driver wants this information, but why would one feed that
> back into request_irq() when the interrupt was already configured by DT.
>

I think Rob already explained the original intention of the patch in
question I sent quite long time ago.

To clarify, I have to add that passing interrupt trigger in resource
flags is not something specific for DT, but it is the general way used
for platform devices and dating times even before DT adoption on ARM
(=== wide spread DT adoption). The key point here is that on pre-DT
systems, the interrupt would not be already configured by DT code and
that's why you have to pass the trigger flags to request_irq().

Best regards,
Tomasz

^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: [PATCH] genirq: fix trigger flags check for shared irqs
@ 2016-01-29  4:17                 ` Tomasz Figa
  0 siblings, 0 replies; 17+ messages in thread
From: Tomasz Figa @ 2016-01-29  4:17 UTC (permalink / raw)
  To: Thomas Gleixner
  Cc: Rob Herring, Brian Starkey, LKML, Marc Zyngier, Frank Rowand,
	Grant Likely, devicetree-u79uwXL29TY76Z2rM5mHXA

Hi Thomas,

2016-01-29 5:06 GMT+09:00 Thomas Gleixner <tglx-hfZtesqFncYOwBW4kG4KsQ@public.gmane.org>:
> On Thu, 28 Jan 2016, Rob Herring wrote:
>> On Thu, Jan 28, 2016 at 5:49 AM, Thomas Gleixner <tglx-hfZtesqFncYOwBW4kG4KsQ@public.gmane.org> wrote:
>> > I've cc'ed the author and the device tree folks. Perhaps are they able to
>> > explain what this commit tries to 'fix'.
>>
>> It's certainly not clear what driver was being fixed. I think the
>> intention was to provide the trigger flags from the DT to drivers in a
>> standard, non-DT specific way. The implementation of it certainly
>> seems convoluted. The usecase I can think of is drivers may need the
>> trigger information for cases where the device can support different
>> trigger modes/polarity. The DT says which trigger mode to use and the
>> device and irqchip need to be programmed to match. IIRC, SMSC ethernet
>> chips frequently used on ARM boards do this.
>
> I can see that the driver wants this information, but why would one feed that
> back into request_irq() when the interrupt was already configured by DT.
>

I think Rob already explained the original intention of the patch in
question I sent quite long time ago.

To clarify, I have to add that passing interrupt trigger in resource
flags is not something specific for DT, but it is the general way used
for platform devices and dating times even before DT adoption on ARM
(=== wide spread DT adoption). The key point here is that on pre-DT
systems, the interrupt would not be already configured by DT code and
that's why you have to pass the trigger flags to request_irq().

Best regards,
Tomasz
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: [PATCH] genirq: fix trigger flags check for shared irqs
  2016-01-28 13:37               ` Thomas Gleixner
@ 2016-02-08 11:02                 ` Brian Starkey
  -1 siblings, 0 replies; 17+ messages in thread
From: Brian Starkey @ 2016-02-08 11:02 UTC (permalink / raw)
  To: Thomas Gleixner
  Cc: LKML, Marc Zyngier, Tomasz Figa, Rob Herring, Frank Rowand,
	Grant Likely, devicetree

Hi Thomas,

Any further thoughts on this? (some comments below)

On Thu, Jan 28, 2016 at 02:37:24PM +0100, Thomas Gleixner wrote:
>In principle I agree. The issue is that it really depends on the 
>particular
>hardware situation.
>
>If there is an explicit requirement for one driver - expressed by a trigger
>flag - and the other driver relies on the default configuration, then this
>might cause malfunction.
>
>The hassle is, that IRQF_TRIGGER_NONE has unclear semantics. It can mean "I
>don't care" or "I rely on the hw configuration". The latter is what worries
>me.
>
>first driver:
>
>      creates the mapping and sets the trigger type according to the DT
>      setting.
>
>      driver calls request_irq() with IRQF_TRIGGER_NONE. It relies on the DT
>      setting to be correct.
>
>second driver:
>
>      Finds an existing mapping. Now we have two cases:
>
>      1) flat irqdomains:
>
>      	 The DT setting is applied to the trigger type unconditionally.
>
>	 So if that setting is contrary to first drivers DT setting then we
>	 are already in trouble.
>
>	 If the driver uses IRQF_TRIGGER_NONE, bad luck as nothing will notice
>	 the issue.
>
>      2) hierarchical irqdomains
>
>      	 That code path ignores the type setting of the second driver and
>      	 leaves the irq line in the existing state.
>
>	 If the driver uses IRQF_TRIGGER_NONE, bad luck as nothing will notice
>	 the issue.
>      	
>So we have two problems here.
>
>1) We should detect the mismatch already in the mapping function.
>
>   But, that's hard for legacy reasons. Interrupts can be mapped at early boot
>   with hardware default settings and we currently have no way to distinguish
>   that. It shouldn't be hard to fix that.
>

Would you agree that this is a separate issue that should be fixed
separately? Even with this fixed, my problem would still exist.

>2) How to deal with the mismatch in request_irq()
>
>   Relaxing the check is not really a good decision. So what we could do is:
>
>   if ((new_action->flags & IRQF_TRIGGER_MASK) == IRQF_TRIGGER_NONE)
>      	new_action->flags |= irqd_get_trigger_type(irqdata);
>
>   Now that has an issue as well. If the driver requests with
>   IRQF_TRIGGER_NONE and does an explicit type setting afterwards, the
>   action->flags still do not reflect it.
>

Yes, an explicit type-setting afterwards would make action->flags get
out-of-sync, but isn't that already the case, regardless of the relaxed
check?

My patch fixes a bogus error for a real use-case, and as far as I can
see doesn't make any of the existing problems worse - so I feel like
that's a net win.

>The whole trigger handling versus shared interrupts needs some deep thoughts
>and I really want to understand what that of commit 4a43d686fe336 before
>making any decisions.
>

If you'd rather see a patch something like your 2) above, I can do that,
let me know what you think.

Many thanks,

Brian

>Thanks,
>
>	tglx
>

^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: [PATCH] genirq: fix trigger flags check for shared irqs
@ 2016-02-08 11:02                 ` Brian Starkey
  0 siblings, 0 replies; 17+ messages in thread
From: Brian Starkey @ 2016-02-08 11:02 UTC (permalink / raw)
  To: Thomas Gleixner
  Cc: LKML, Marc Zyngier, Tomasz Figa, Rob Herring, Frank Rowand,
	Grant Likely, devicetree-u79uwXL29TY76Z2rM5mHXA

Hi Thomas,

Any further thoughts on this? (some comments below)

On Thu, Jan 28, 2016 at 02:37:24PM +0100, Thomas Gleixner wrote:
>In principle I agree. The issue is that it really depends on the 
>particular
>hardware situation.
>
>If there is an explicit requirement for one driver - expressed by a trigger
>flag - and the other driver relies on the default configuration, then this
>might cause malfunction.
>
>The hassle is, that IRQF_TRIGGER_NONE has unclear semantics. It can mean "I
>don't care" or "I rely on the hw configuration". The latter is what worries
>me.
>
>first driver:
>
>      creates the mapping and sets the trigger type according to the DT
>      setting.
>
>      driver calls request_irq() with IRQF_TRIGGER_NONE. It relies on the DT
>      setting to be correct.
>
>second driver:
>
>      Finds an existing mapping. Now we have two cases:
>
>      1) flat irqdomains:
>
>      	 The DT setting is applied to the trigger type unconditionally.
>
>	 So if that setting is contrary to first drivers DT setting then we
>	 are already in trouble.
>
>	 If the driver uses IRQF_TRIGGER_NONE, bad luck as nothing will notice
>	 the issue.
>
>      2) hierarchical irqdomains
>
>      	 That code path ignores the type setting of the second driver and
>      	 leaves the irq line in the existing state.
>
>	 If the driver uses IRQF_TRIGGER_NONE, bad luck as nothing will notice
>	 the issue.
>      	
>So we have two problems here.
>
>1) We should detect the mismatch already in the mapping function.
>
>   But, that's hard for legacy reasons. Interrupts can be mapped at early boot
>   with hardware default settings and we currently have no way to distinguish
>   that. It shouldn't be hard to fix that.
>

Would you agree that this is a separate issue that should be fixed
separately? Even with this fixed, my problem would still exist.

>2) How to deal with the mismatch in request_irq()
>
>   Relaxing the check is not really a good decision. So what we could do is:
>
>   if ((new_action->flags & IRQF_TRIGGER_MASK) == IRQF_TRIGGER_NONE)
>      	new_action->flags |= irqd_get_trigger_type(irqdata);
>
>   Now that has an issue as well. If the driver requests with
>   IRQF_TRIGGER_NONE and does an explicit type setting afterwards, the
>   action->flags still do not reflect it.
>

Yes, an explicit type-setting afterwards would make action->flags get
out-of-sync, but isn't that already the case, regardless of the relaxed
check?

My patch fixes a bogus error for a real use-case, and as far as I can
see doesn't make any of the existing problems worse - so I feel like
that's a net win.

>The whole trigger handling versus shared interrupts needs some deep thoughts
>and I really want to understand what that of commit 4a43d686fe336 before
>making any decisions.
>

If you'd rather see a patch something like your 2) above, I can do that,
let me know what you think.

Many thanks,

Brian

>Thanks,
>
>	tglx
>
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 17+ messages in thread

end of thread, other threads:[~2016-02-08 11:02 UTC | newest]

Thread overview: 17+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2016-01-26 10:31 [PATCH] genirq: fix trigger flags check for shared irqs Brian Starkey
2016-01-26 20:45 ` Thomas Gleixner
2016-01-28  9:59   ` Brian Starkey
2016-01-28 10:29     ` Thomas Gleixner
2016-01-28 11:10       ` Brian Starkey
2016-01-28 11:49         ` Thomas Gleixner
2016-01-28 12:22           ` Brian Starkey
2016-01-28 12:22             ` Brian Starkey
2016-01-28 13:37             ` Thomas Gleixner
2016-01-28 13:37               ` Thomas Gleixner
2016-02-08 11:02               ` Brian Starkey
2016-02-08 11:02                 ` Brian Starkey
2016-01-28 15:58           ` Rob Herring
2016-01-28 15:58             ` Rob Herring
2016-01-28 20:06             ` Thomas Gleixner
2016-01-29  4:17               ` Tomasz Figa
2016-01-29  4:17                 ` Tomasz Figa

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.