diff mbox

[03/12] irqchip: gic: define register_routable_domain_ops conditional

Message ID 1417565531-4507-4-git-send-email-stefan@agner.ch (mailing list archive)
State New, archived
Headers show

Commit Message

Stefan Agner Dec. 3, 2014, 12:12 a.m. UTC
The inline function register_routable_domain_ops is only usable if
CONFIG_ARM_GIC is set. Make it depend on this configuration. This
also allows other SoC interrupt controller to provide such a
function.

Signed-off-by: Stefan Agner <stefan@agner.ch>
---
 include/linux/irqchip/arm-gic.h | 3 +++
 1 file changed, 3 insertions(+)

Comments

Arnd Bergmann Dec. 3, 2014, 10:46 a.m. UTC | #1
On Wednesday 03 December 2014 01:12:02 Stefan Agner wrote:
> The inline function register_routable_domain_ops is only usable if
> CONFIG_ARM_GIC is set. Make it depend on this configuration. This
> also allows other SoC interrupt controller to provide such a
> function.
> 
> Signed-off-by: Stefan Agner <stefan@agner.ch>

I don't think this is a good idea: either the interface is meant
to be generic and should work with any interrupt controller, or
it is specific to one irqchip and another irqchip should provide
a different interface that has a nonconflicting name.

I suppose you want the latter here, given that the declaration
is part of the gic specific header file.

	Arnd
Thomas Gleixner Dec. 3, 2014, 1:04 p.m. UTC | #2
On Wed, 3 Dec 2014, Arnd Bergmann wrote:

> On Wednesday 03 December 2014 01:12:02 Stefan Agner wrote:
> > The inline function register_routable_domain_ops is only usable if
> > CONFIG_ARM_GIC is set. Make it depend on this configuration. This
> > also allows other SoC interrupt controller to provide such a
> > function.
> > 
> > Signed-off-by: Stefan Agner <stefan@agner.ch>
> 
> I don't think this is a good idea: either the interface is meant
> to be generic and should work with any interrupt controller, or
> it is specific to one irqchip and another irqchip should provide
> a different interface that has a nonconflicting name.
> 
> I suppose you want the latter here, given that the declaration
> is part of the gic specific header file.

That routable_domain stuff should have never been invented. In
hindsight we should have done the stacked irq domains back then
already, but in hindsight ...

If you look at the crossbar scheme what we have now:

   GIC domain
|--------------|
|              |---------- private
| non routable |---------- peripheral
|              |---------- peripheral
|              |
|--------------|
|              |---------- peripheral
|   routable   |---------- peripheral
|    |         |---------- peripheral
|--------------|
     |               |----------------|
     |-------------->| crossbar magic |
                     |----------------|

which is not how the hardware looks. The hardware actually looks like
this:

   GIC domain
|--------------|
|              |---------- private
| non routable |---------- peripheral
|              |---------- peripheral
|              |
|--------------|           |--------------|
|              |           |              |---------- peripheral
|   routable   |-----------| crossbar     |---------- peripheral
|              |           | domain       |---------- peripheral
|--------------|           |--------------|

So it is completely obvious that the peripheral interrupts which need
to be routed through the crossbar belong to a different domain. We
really should convert crossbar to that scheme and get rid of the
routable domain stuff completely.

With vybrid thats not different according to the diagram in the
reference manual.

  GIC domain
|--------------|
|              |---------- private
| non routable |---------- peripheral
|              |---------- peripheral
|              |
|--------------|           |--------------|
|              |           |              |
|   routable   |-----------|  IRQ router  |
|              |           |  domain      |
|              |           |              |
|--------------|           |--------------|
                           | Shared state |---------- CPU to CPU 
  NVIC domain              | and hardware |---------- peripheral
|--------------|           |              |---------- peripheral
|              |           |--------------|
|              |           |              |
|   routable   |-----------|  IRQ router  |
|              |           |  domain      |
|              |           |              |
|--------------|           |--------------|
|              |
|              |---------- private
| non routable |---------- peripheral
|              |---------- peripheral
|--------------|

The routable domain stuff is just an adhoc redirector which must be
tied to a particular base irq chip implementation (i.e. GIC). With
stacked irq domains there is no dependency on the underlying irq
chip. No ifdeffery, nothing. So you can use the same router domain
implementation for both the A5 and the M4 side.

On the A5 side the router domain has the gic domain as parent and on
the M4 side the nvic domain.

The shared interrupts are allocated through the router domain which
decides whether the interrupt can be assigned to a particular core or
not. If it can be assigned it allocates the corresponding interrupt in
the parent domain, sets up the routing and everything just works.

See: http://git.kernel.org/cgit/linux/kernel/git/tip/tip.git/log/?h=irq/irqdomain-arm

Thanks,

	tglx
Stefan Agner Dec. 3, 2014, 5:28 p.m. UTC | #3
On 2014-12-03 14:04, Thomas Gleixner wrote:
> On Wed, 3 Dec 2014, Arnd Bergmann wrote:
> 
>> On Wednesday 03 December 2014 01:12:02 Stefan Agner wrote:
>> > The inline function register_routable_domain_ops is only usable if
>> > CONFIG_ARM_GIC is set. Make it depend on this configuration. This
>> > also allows other SoC interrupt controller to provide such a
>> > function.
>> >
>> > Signed-off-by: Stefan Agner <stefan@agner.ch>
>>
>> I don't think this is a good idea: either the interface is meant
>> to be generic and should work with any interrupt controller, or
>> it is specific to one irqchip and another irqchip should provide
>> a different interface that has a nonconflicting name.
>>
>> I suppose you want the latter here, given that the declaration
>> is part of the gic specific header file.
> 
> That routable_domain stuff should have never been invented. In
> hindsight we should have done the stacked irq domains back then
> already, but in hindsight ...

I must admit that my first implementation even used arch_extn (through
the mask/unmask stuff). Then I saw the routable domain stuff, which
looked more like a fit. But when I realized that only GIC has support
for that, I soon realized that this might either need a proper
framework... my hackish NVIC extension probably won't be acceptable...

Stack-able IRQ domain sounds like exactly what I was looking for...

> 
> If you look at the crossbar scheme what we have now:
> 
>    GIC domain
> |--------------|
> |              |---------- private
> | non routable |---------- peripheral
> |              |---------- peripheral
> |              |
> |--------------|
> |              |---------- peripheral
> |   routable   |---------- peripheral
> |    |         |---------- peripheral
> |--------------|
>      |               |----------------|
>      |-------------->| crossbar magic |
>                      |----------------|
> 
> which is not how the hardware looks. The hardware actually looks like
> this:
> 
>    GIC domain
> |--------------|
> |              |---------- private
> | non routable |---------- peripheral
> |              |---------- peripheral
> |              |
> |--------------|           |--------------|
> |              |           |              |---------- peripheral
> |   routable   |-----------| crossbar     |---------- peripheral
> |              |           | domain       |---------- peripheral
> |--------------|           |--------------|
> 
> So it is completely obvious that the peripheral interrupts which need
> to be routed through the crossbar belong to a different domain. We
> really should convert crossbar to that scheme and get rid of the
> routable domain stuff completely.
> 
> With vybrid thats not different according to the diagram in the
> reference manual.
> 
>   GIC domain
> |--------------|
> |              |---------- private
> | non routable |---------- peripheral
> |              |---------- peripheral
> |              |
> |--------------|           |--------------|
> |              |           |              |
> |   routable   |-----------|  IRQ router  |
> |              |           |  domain      |
> |              |           |              |
> |--------------|           |--------------|
>                            | Shared state |---------- CPU to CPU 
>   NVIC domain              | and hardware |---------- peripheral
> |--------------|           |              |---------- peripheral
> |              |           |--------------|
> |              |           |              |
> |   routable   |-----------|  IRQ router  |
> |              |           |  domain      |
> |              |           |              |
> |--------------|           |--------------|
> |              |
> |              |---------- private
> | non routable |---------- peripheral
> |              |---------- peripheral
> |--------------|
> 
> The routable domain stuff is just an adhoc redirector which must be
> tied to a particular base irq chip implementation (i.e. GIC). With
> stacked irq domains there is no dependency on the underlying irq
> chip. No ifdeffery, nothing. So you can use the same router domain
> implementation for both the A5 and the M4 side.
> 
> On the A5 side the router domain has the gic domain as parent and on
> the M4 side the nvic domain.
> 
> The shared interrupts are allocated through the router domain which
> decides whether the interrupt can be assigned to a particular core or
> not. If it can be assigned it allocates the corresponding interrupt in
> the parent domain, sets up the routing and everything just works.

What do you mean by the shared state in the drawing above? Currently, I
check whether a interrupt is already used by the other core by reading
the register (do this configuration register reflect the "shared state"
in your drawing?).


> 
> See:
> http://git.kernel.org/cgit/linux/kernel/git/tip/tip.git/log/?h=irq/irqdomain-arm
> 

Thanks for the link. So my work would involve to support domain
hierarchy for NVIC (proper irq_domain_ops, introduce arm,routable-irqs
property, anything else?) and then make use of the hierarchy code in my
MSCM driver like for instance the mtk-sysirq driver...?

What is the state of the IRQ domain hierarchy, when will it go upstream?

--
Stefan
Marc Zyngier Dec. 3, 2014, 7:04 p.m. UTC | #4
Hi Stefan,

On 03/12/14 17:28, Stefan Agner wrote:
> On 2014-12-03 14:04, Thomas Gleixner wrote:
>> On Wed, 3 Dec 2014, Arnd Bergmann wrote:
>>
>>> On Wednesday 03 December 2014 01:12:02 Stefan Agner wrote:
>>>> The inline function register_routable_domain_ops is only usable if
>>>> CONFIG_ARM_GIC is set. Make it depend on this configuration. This
>>>> also allows other SoC interrupt controller to provide such a
>>>> function.
>>>>
>>>> Signed-off-by: Stefan Agner <stefan@agner.ch>
>>>
>>> I don't think this is a good idea: either the interface is meant
>>> to be generic and should work with any interrupt controller, or
>>> it is specific to one irqchip and another irqchip should provide
>>> a different interface that has a nonconflicting name.
>>>
>>> I suppose you want the latter here, given that the declaration
>>> is part of the gic specific header file.
>>
>> That routable_domain stuff should have never been invented. In
>> hindsight we should have done the stacked irq domains back then
>> already, but in hindsight ...
> 
> I must admit that my first implementation even used arch_extn (through

I'm glad I didn't see that! ;-)

> the mask/unmask stuff). Then I saw the routable domain stuff, which
> looked more like a fit. But when I realized that only GIC has support
> for that, I soon realized that this might either need a proper
> framework... my hackish NVIC extension probably won't be acceptable...
> 
> Stack-able IRQ domain sounds like exactly what I was looking for...

Like Thomas said, we should have had that ages ago. It solves so many
problems in one go it's mind-boggling. On the down side, we end-up
refactoring *a lot* of the existing code...

>>
>> If you look at the crossbar scheme what we have now:
>>
>>    GIC domain
>> |--------------|
>> |              |---------- private
>> | non routable |---------- peripheral
>> |              |---------- peripheral
>> |              |
>> |--------------|
>> |              |---------- peripheral
>> |   routable   |---------- peripheral
>> |    |         |---------- peripheral
>> |--------------|
>>      |               |----------------|
>>      |-------------->| crossbar magic |
>>                      |----------------|
>>
>> which is not how the hardware looks. The hardware actually looks like
>> this:
>>
>>    GIC domain
>> |--------------|
>> |              |---------- private
>> | non routable |---------- peripheral
>> |              |---------- peripheral
>> |              |
>> |--------------|           |--------------|
>> |              |           |              |---------- peripheral
>> |   routable   |-----------| crossbar     |---------- peripheral
>> |              |           | domain       |---------- peripheral
>> |--------------|           |--------------|
>>
>> So it is completely obvious that the peripheral interrupts which need
>> to be routed through the crossbar belong to a different domain. We
>> really should convert crossbar to that scheme and get rid of the
>> routable domain stuff completely.
>>
>> With vybrid thats not different according to the diagram in the
>> reference manual.
>>
>>   GIC domain
>> |--------------|
>> |              |---------- private
>> | non routable |---------- peripheral
>> |              |---------- peripheral
>> |              |
>> |--------------|           |--------------|
>> |              |           |              |
>> |   routable   |-----------|  IRQ router  |
>> |              |           |  domain      |
>> |              |           |              |
>> |--------------|           |--------------|
>>                            | Shared state |---------- CPU to CPU 
>>   NVIC domain              | and hardware |---------- peripheral
>> |--------------|           |              |---------- peripheral
>> |              |           |--------------|
>> |              |           |              |
>> |   routable   |-----------|  IRQ router  |
>> |              |           |  domain      |
>> |              |           |              |
>> |--------------|           |--------------|
>> |              |
>> |              |---------- private
>> | non routable |---------- peripheral
>> |              |---------- peripheral
>> |--------------|
>>
>> The routable domain stuff is just an adhoc redirector which must be
>> tied to a particular base irq chip implementation (i.e. GIC). With
>> stacked irq domains there is no dependency on the underlying irq
>> chip. No ifdeffery, nothing. So you can use the same router domain
>> implementation for both the A5 and the M4 side.
>>
>> On the A5 side the router domain has the gic domain as parent and on
>> the M4 side the nvic domain.
>>
>> The shared interrupts are allocated through the router domain which
>> decides whether the interrupt can be assigned to a particular core or
>> not. If it can be assigned it allocates the corresponding interrupt in
>> the parent domain, sets up the routing and everything just works.
> 
> What do you mean by the shared state in the drawing above? Currently, I
> check whether a interrupt is already used by the other core by reading
> the register (do this configuration register reflect the "shared state"
> in your drawing?).

I think that is basically it. It should only be the register that
decides on the actual routing. BTW, how do you arbitrate between
concurrent accesses to this register? Or is only the A5 allowed to
change it?

> 
>>
>> See:
>> http://git.kernel.org/cgit/linux/kernel/git/tip/tip.git/log/?h=irq/irqdomain-arm
>>
> 
> Thanks for the link. So my work would involve to support domain
> hierarchy for NVIC (proper irq_domain_ops, introduce arm,routable-irqs
> property, anything else?) and then make use of the hierarchy code in my
> MSCM driver like for instance the mtk-sysirq driver...?

I don't think we need the arm,routable-irq property at all, and I'm
looking at refactoring the crossbar thingy to remove most of its
entanglement with the GIC.

All you need to know is the range of interrupts you're allowed to
request through the "routable" domain. The inner-most irqchip shouldn't
even know about it (after all, they are just wires coming in). It should
be the duty of the outer-most irqchip (the "router") to generate the
correct request to the GIC/NVIC. So all the knowledge should be at the
router level.

The mtk-sysrq code is indeed a good example of what you can do.

> What is the state of the IRQ domain hierarchy, when will it go upstream?

Scheduled for 3.19, if everything goes according to plan. Don't think we
can go back anyway... ;-)

Thanks,

	M.
Thomas Gleixner Dec. 4, 2014, 12:03 a.m. UTC | #5
On Wed, 3 Dec 2014, Marc Zyngier wrote:
> On 03/12/14 17:28, Stefan Agner wrote:
> > On 2014-12-03 14:04, Thomas Gleixner wrote:
> >> The shared interrupts are allocated through the router domain which
> >> decides whether the interrupt can be assigned to a particular core or
> >> not. If it can be assigned it allocates the corresponding interrupt in
> >> the parent domain, sets up the routing and everything just works.
> > 
> > What do you mean by the shared state in the drawing above? Currently, I
> > check whether a interrupt is already used by the other core by reading
> > the register (do this configuration register reflect the "shared state"
> > in your drawing?).
> 
> I think that is basically it. It should only be the register that
> decides on the actual routing. BTW, how do you arbitrate between
> concurrent accesses to this register? Or is only the A5 allowed to
> change it?

What I meant with 'shared state' is basically the configuration
register space. Plus depending on the mechanism you want to use for
correlating the routing between the A5 and the M4 some shared memory
state, locking, IPC or whatever you need for this.
 
> >> http://git.kernel.org/cgit/linux/kernel/git/tip/tip.git/log/?h=irq/irqdomain-arm
> >>
> > 
> > Thanks for the link. So my work would involve to support domain
> > hierarchy for NVIC (proper irq_domain_ops, introduce arm,routable-irqs
> > property, anything else?) and then make use of the hierarchy code in my
> > MSCM driver like for instance the mtk-sysirq driver...?
> 
> I don't think we need the arm,routable-irq property at all, and I'm
> looking at refactoring the crossbar thingy to remove most of its
> entanglement with the GIC.
> 
> All you need to know is the range of interrupts you're allowed to
> request through the "routable" domain. The inner-most irqchip shouldn't
> even know about it (after all, they are just wires coming in). It should
> be the duty of the outer-most irqchip (the "router") to generate the
> correct request to the GIC/NVIC. So all the knowledge should be at the
> router level.
> 
> The mtk-sysrq code is indeed a good example of what you can do.

The gic-v2m MSI stuff is probably helpful as well.
 
> > What is the state of the IRQ domain hierarchy, when will it go upstream?
> 
> Scheduled for 3.19, if everything goes according to plan. Don't think we
> can go back anyway... ;-)

Indeed. That would be a major headache...

Thanks,

	tglx
Stefan Agner Dec. 4, 2014, 1:35 p.m. UTC | #6
On 2014-12-03 20:04, Marc Zyngier wrote:
<snip>
>> What do you mean by the shared state in the drawing above? Currently, I
>> check whether a interrupt is already used by the other core by reading
>> the register (do this configuration register reflect the "shared state"
>> in your drawing?).
> 
> I think that is basically it. It should only be the register that
> decides on the actual routing. BTW, how do you arbitrate between
> concurrent accesses to this register? Or is only the A5 allowed to
> change it?
 
No arbitration so far... The whole Vybrid on M4 stuff is quite a hack
right now. For instance also the concurrent access to the clock
registers is not handled. Currently, I start the M4 from a booted A5
Linux. To avoid half of the clocks get turned of by the M4 clock driver,
I need to specify clk_ignore_unused. Beside that, peripherals have to be
enabled/disabled in a non conflicting manor in the device trees...

For the interrupt router in MSCM, it would be nice if the access could
be done an atomic way, which would avoid the use of a lock mechanism.
But I guess this is not possible, since peripherals only support
standard ldr/str...?

There is the SEMA4 module which provides hardware semaphores. I'm aware
of the hardware spinlock drivers (drivers/hwspinlock/), I started to
implement such a driver for Vybrid. But so far a grep through the kernel
does not show one usage of that framework... I guess we could add dt
support for that, so we can assign the locks to individual drivers.

I also plan to have a deeper look into remoteproc/rpmsg, not sure if
locking of shared peripherals is part (or planned to be part) of that
framework.

For the clock stuff, the problem is more complex: I guess the would need
some kind of master/slave definition, where we disallow the change of
the shared clocks for the slave.

If you are aware of patches/solutions, I'm happy to hear it...

--
Stefan


<snip>
Marc Zyngier Dec. 4, 2014, 1:42 p.m. UTC | #7
On 04/12/14 13:35, Stefan Agner wrote:
> On 2014-12-03 20:04, Marc Zyngier wrote:
> <snip>
>>> What do you mean by the shared state in the drawing above? Currently, I
>>> check whether a interrupt is already used by the other core by reading
>>> the register (do this configuration register reflect the "shared state"
>>> in your drawing?).
>>
>> I think that is basically it. It should only be the register that
>> decides on the actual routing. BTW, how do you arbitrate between
>> concurrent accesses to this register? Or is only the A5 allowed to
>> change it?
>  
> No arbitration so far... The whole Vybrid on M4 stuff is quite a hack
> right now. For instance also the concurrent access to the clock
> registers is not handled. Currently, I start the M4 from a booted A5
> Linux. To avoid half of the clocks get turned of by the M4 clock driver,
> I need to specify clk_ignore_unused. Beside that, peripherals have to be
> enabled/disabled in a non conflicting manor in the device trees...
> 
> For the interrupt router in MSCM, it would be nice if the access could
> be done an atomic way, which would avoid the use of a lock mechanism.
> But I guess this is not possible, since peripherals only support
> standard ldr/str...?
> 
> There is the SEMA4 module which provides hardware semaphores. I'm aware
> of the hardware spinlock drivers (drivers/hwspinlock/), I started to
> implement such a driver for Vybrid. But so far a grep through the kernel
> does not show one usage of that framework... I guess we could add dt
> support for that, so we can assign the locks to individual drivers.
> 
> I also plan to have a deeper look into remoteproc/rpmsg, not sure if
> locking of shared peripherals is part (or planned to be part) of that
> framework.
> 
> For the clock stuff, the problem is more complex: I guess the would need
> some kind of master/slave definition, where we disallow the change of
> the shared clocks for the slave.
> 
> If you are aware of patches/solutions, I'm happy to hear it...

I don't have a real solution for this, but I'd be tempted to generate
the M4 DT based on the HW the A5 is not using, and only describe that.

Clearly not ideal, but it gives you the control you need (don't describe
the HW you don't want to see touched)...

	M.
Stefan Agner Dec. 4, 2014, 1:50 p.m. UTC | #8
On 2014-12-04 14:42, Marc Zyngier wrote:
> On 04/12/14 13:35, Stefan Agner wrote:
>> On 2014-12-03 20:04, Marc Zyngier wrote:
>> <snip>
>>>> What do you mean by the shared state in the drawing above? Currently, I
>>>> check whether a interrupt is already used by the other core by reading
>>>> the register (do this configuration register reflect the "shared state"
>>>> in your drawing?).
>>>
>>> I think that is basically it. It should only be the register that
>>> decides on the actual routing. BTW, how do you arbitrate between
>>> concurrent accesses to this register? Or is only the A5 allowed to
>>> change it?
>>
>> No arbitration so far... The whole Vybrid on M4 stuff is quite a hack
>> right now. For instance also the concurrent access to the clock
>> registers is not handled. Currently, I start the M4 from a booted A5
>> Linux. To avoid half of the clocks get turned of by the M4 clock driver,
>> I need to specify clk_ignore_unused. Beside that, peripherals have to be
>> enabled/disabled in a non conflicting manor in the device trees...
>>
>> For the interrupt router in MSCM, it would be nice if the access could
>> be done an atomic way, which would avoid the use of a lock mechanism.
>> But I guess this is not possible, since peripherals only support
>> standard ldr/str...?
>>
>> There is the SEMA4 module which provides hardware semaphores. I'm aware
>> of the hardware spinlock drivers (drivers/hwspinlock/), I started to
>> implement such a driver for Vybrid. But so far a grep through the kernel
>> does not show one usage of that framework... I guess we could add dt
>> support for that, so we can assign the locks to individual drivers.
>>
>> I also plan to have a deeper look into remoteproc/rpmsg, not sure if
>> locking of shared peripherals is part (or planned to be part) of that
>> framework.
>>
>> For the clock stuff, the problem is more complex: I guess the would need
>> some kind of master/slave definition, where we disallow the change of
>> the shared clocks for the slave.
>>
>> If you are aware of patches/solutions, I'm happy to hear it...
> 
> I don't have a real solution for this, but I'd be tempted to generate
> the M4 DT based on the HW the A5 is not using, and only describe that.
> 
> Clearly not ideal, but it gives you the control you need (don't describe
> the HW you don't want to see touched)...
> 

Yeah, that avoids the need for any synchronization for those
peripherals.

However, for some hardware (e.g. clocks and that interrupt controller)
both sides need access... I guess to do it properly, I need to take care
of it...

--
Stefan
diff mbox

Patch

diff --git a/include/linux/irqchip/arm-gic.h b/include/linux/irqchip/arm-gic.h
index 13eed92..3b1baf1 100644
--- a/include/linux/irqchip/arm-gic.h
+++ b/include/linux/irqchip/arm-gic.h
@@ -111,11 +111,14 @@  int gic_get_cpu_id(unsigned int cpu);
 void gic_migrate_target(unsigned int new_cpu_id);
 unsigned long gic_get_sgir_physaddr(void);
 
+#ifdef CONFIG_ARM_GIC
 extern const struct irq_domain_ops *gic_routable_irq_domain_ops;
 static inline void __init register_routable_domain_ops
 					(const struct irq_domain_ops *ops)
 {
 	gic_routable_irq_domain_ops = ops;
 }
+#endif /* CONFIG_ARM_GIC */
+
 #endif /* __ASSEMBLY */
 #endif