diff mbox

[01/10] irqchip: irq-mips-gic: export gic_send_ipi

Message ID 1440419959-14315-2-git-send-email-qais.yousef@imgtec.com (mailing list archive)
State New, archived
Headers show

Commit Message

Qais Yousef Aug. 24, 2015, 12:39 p.m. UTC
Some drivers might require to send ipi to other cores. So export it.
This will be used later by AXD driver.

Signed-off-by: Qais Yousef <qais.yousef@imgtec.com>
Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: Jason Cooper <jason@lakedaemon.net>
Cc: Marc Zyngier <marc.zyngier@arm.com>
Cc: linux-kernel@vger.kernel.org
Cc: linux-mips@linux-mips.org
---
 drivers/irqchip/irq-mips-gic.c | 1 +
 1 file changed, 1 insertion(+)

Comments

Thomas Gleixner Aug. 24, 2015, 12:49 p.m. UTC | #1
On Mon, 24 Aug 2015, Qais Yousef wrote:

> Some drivers might require to send ipi to other cores. So export it.

Which IPIs do you need to send from a driver which are not exposed by
the SMP functions already?

> This will be used later by AXD driver.

That smells fishy and it wants a proper explanation WHY and not just a
sloppy statement that it will be used later. I can figure that out
myself as exporting a function without using it does not make any sense.

Thanks,

	tglx
Qais Yousef Aug. 24, 2015, 1:02 p.m. UTC | #2
On 08/24/2015 01:49 PM, Thomas Gleixner wrote:
> On Mon, 24 Aug 2015, Qais Yousef wrote:
>
>> Some drivers might require to send ipi to other cores. So export it.
> Which IPIs do you need to send from a driver which are not exposed by
> the SMP functions already?

It's not an SMP IPI. We use GIC to exchange interrupts between AXD and 
the host system since AXD is another MIPS core in the cluster.

>> This will be used later by AXD driver.
> That smells fishy and it wants a proper explanation WHY and not just a
> sloppy statement that it will be used later. I can figure that out
> myself as exporting a function without using it does not make any sense.

Sorry for the terse explanation. As pointed above AXD uses GIC to send 
and receive interrupts to the host core. Without this change I can't 
compile the driver as a driver module because the symbol is not exported.

Does this make things clearer?

Thanks,
Qais

>
> Thanks,
>
> 	tglx
Marc Zyngier Aug. 24, 2015, 1:32 p.m. UTC | #3
On 24/08/15 14:02, Qais Yousef wrote:
> On 08/24/2015 01:49 PM, Thomas Gleixner wrote:
>> On Mon, 24 Aug 2015, Qais Yousef wrote:
>>
>>> Some drivers might require to send ipi to other cores. So export it.
>> Which IPIs do you need to send from a driver which are not exposed by
>> the SMP functions already?
> 
> It's not an SMP IPI. We use GIC to exchange interrupts between AXD and 
> the host system since AXD is another MIPS core in the cluster.

So is this the case of another CPU in the system that is not under
control of Linux, but that you need to signal anyway? How do you agree
on the IPI number between the two systems?

>>> This will be used later by AXD driver.
>> That smells fishy and it wants a proper explanation WHY and not just a
>> sloppy statement that it will be used later. I can figure that out
>> myself as exporting a function without using it does not make any sense.
> 
> Sorry for the terse explanation. As pointed above AXD uses GIC to send 
> and receive interrupts to the host core. Without this change I can't 
> compile the driver as a driver module because the symbol is not exported.
> 
> Does this make things clearer?

To me, it feels like this is yet another case of routing interrupts to
another agent in the system, which is not a CPU under the kernel's
control. There is at least two other platforms doing similar craziness
(a Freescale platform, and at least one Nvidia).

I'd rather see something more "architected" than this blind export, or
at least some level of filtering (the idea random drivers can access
such a low-level function doesn't make me feel very good).

Thanks,

	M.
Qais Yousef Aug. 24, 2015, 2:27 p.m. UTC | #4
On 08/24/2015 02:32 PM, Marc Zyngier wrote:
> On 24/08/15 14:02, Qais Yousef wrote:
>> On 08/24/2015 01:49 PM, Thomas Gleixner wrote:
>>> On Mon, 24 Aug 2015, Qais Yousef wrote:
>>>
>>>> Some drivers might require to send ipi to other cores. So export it.
>>> Which IPIs do you need to send from a driver which are not exposed by
>>> the SMP functions already?
>> It's not an SMP IPI. We use GIC to exchange interrupts between AXD and
>> the host system since AXD is another MIPS core in the cluster.
> So is this the case of another CPU in the system that is not under
> control of Linux, but that you need to signal anyway? How do you agree
> on the IPI number between the two systems?

When Linux loads AXD firmware into memory it places the GIC numbers to 
use at a specific offset there as part of the startup protocol. When AXD 
starts running it will see these values and use them to send and receive 
interrupts.

>
>>>> This will be used later by AXD driver.
>>> That smells fishy and it wants a proper explanation WHY and not just a
>>> sloppy statement that it will be used later. I can figure that out
>>> myself as exporting a function without using it does not make any sense.
>> Sorry for the terse explanation. As pointed above AXD uses GIC to send
>> and receive interrupts to the host core. Without this change I can't
>> compile the driver as a driver module because the symbol is not exported.
>>
>> Does this make things clearer?
> To me, it feels like this is yet another case of routing interrupts to
> another agent in the system, which is not a CPU under the kernel's
> control. There is at least two other platforms doing similar craziness
> (a Freescale platform, and at least one Nvidia).
>
> I'd rather see something more "architected" than this blind export, or
> at least some level of filtering (the idea random drivers can access
> such a low-level function doesn't make me feel very good).

I don't know how to architect this better or how to perform  the 
filtering, but I'm happy to hear suggestions and try them out.
Keep in mind that detecting GIC and writing your own gic_send_ipi() is 
very simple. I have done this when the driver was out of tree. So 
restricting it by not exporting it will not prevent someone from really 
accessing the functionality, it's just they have to do it their own way.

Thanks,
Qais

>
> Thanks,
>
> 	M.
Thomas Gleixner Aug. 24, 2015, 2:55 p.m. UTC | #5
On Mon, 24 Aug 2015, Qais Yousef wrote:
> On 08/24/2015 01:49 PM, Thomas Gleixner wrote:
> > On Mon, 24 Aug 2015, Qais Yousef wrote:
> > 
> > > Some drivers might require to send ipi to other cores. So export it.
> > Which IPIs do you need to send from a driver which are not exposed by
> > the SMP functions already?
> 
> It's not an SMP IPI. We use GIC to exchange interrupts between AXD and the
> host system since AXD is another MIPS core in the cluster.

So that should have been in the changelog to begin with.
 
> > > This will be used later by AXD driver.
> > That smells fishy and it wants a proper explanation WHY and not just a
> > sloppy statement that it will be used later. I can figure that out
> > myself as exporting a function without using it does not make any sense.
> 
> Sorry for the terse explanation. As pointed above AXD uses GIC to send and
> receive interrupts to the host core. Without this change I can't compile the
> driver as a driver module because the symbol is not exported.

Really? Exporting it solves that problem then. That's interesting news
for me.

Thanks,

	tglx
Thomas Gleixner Aug. 24, 2015, 3:07 p.m. UTC | #6
On Mon, 24 Aug 2015, Qais Yousef wrote:
> On 08/24/2015 02:32 PM, Marc Zyngier wrote:
> > I'd rather see something more "architected" than this blind export, or
> > at least some level of filtering (the idea random drivers can access
> > such a low-level function doesn't make me feel very good).
> 
> I don't know how to architect this better or how to perform  the filtering,
> but I'm happy to hear suggestions and try them out.
> Keep in mind that detecting GIC and writing your own gic_send_ipi() is very
> simple. I have done this when the driver was out of tree. So restricting it by
> not exporting it will not prevent someone from really accessing the
> functionality, it's just they have to do it their own way.

Keep in mind that we are not talking about out of tree hackery. We
talk about a kernel code submission and I doubt, that you will get
away with a GIC detection/fiddling burried in your driver code.

Keep in mind that just slapping an export to some random function is
not much better than doing a GIC hack in the driver.

Marcs concerns about blindly exposing IPI functionality to drivers is
well justified and that kind of coprocessor stuff is not unique to
your particular SoC. We're going to see such things more frequently in
the not so distant future, so we better think now about proper
solutions to that problem.

There are a couple of issues to solve:

1) How is the IPI which is received by the coprocessor reserved in the
   system?

2) How is it associated to a particular driver?

3) How do we ensure that a driver cannot issue random IPIs and can
   only send the associated ones?

None of these issues are handled by your export.

So we need a core infrastructure which allows us to do that. The
requirements are pretty clear from the above and Marc might have some
further restrictions in mind.

Thanks,

	tglx
Qais Yousef Aug. 24, 2015, 3:11 p.m. UTC | #7
On 08/24/2015 03:55 PM, Thomas Gleixner wrote:
> On Mon, 24 Aug 2015, Qais Yousef wrote:
>> On 08/24/2015 01:49 PM, Thomas Gleixner wrote:
>>> On Mon, 24 Aug 2015, Qais Yousef wrote:
>>>
>>>> Some drivers might require to send ipi to other cores. So export it.
>>> Which IPIs do you need to send from a driver which are not exposed by
>>> the SMP functions already?
>> It's not an SMP IPI. We use GIC to exchange interrupts between AXD and the
>> host system since AXD is another MIPS core in the cluster.
> So that should have been in the changelog to begin with.
>   

OK sorry for the confusion. I'll amend the changelog and be more careful 
in the future.

Thanks,
Qais

>>>> This will be used later by AXD driver.
>>> That smells fishy and it wants a proper explanation WHY and not just a
>>> sloppy statement that it will be used later. I can figure that out
>>> myself as exporting a function without using it does not make any sense.
>> Sorry for the terse explanation. As pointed above AXD uses GIC to send and
>> receive interrupts to the host core. Without this change I can't compile the
>> driver as a driver module because the symbol is not exported.
> Really? Exporting it solves that problem then. That's interesting news
> for me.
>
> Thanks,
>
> 	tglx
Qais Yousef Aug. 24, 2015, 4:39 p.m. UTC | #8
On 08/24/2015 04:07 PM, Thomas Gleixner wrote:
> On Mon, 24 Aug 2015, Qais Yousef wrote:
>> On 08/24/2015 02:32 PM, Marc Zyngier wrote:
>>> I'd rather see something more "architected" than this blind export, or
>>> at least some level of filtering (the idea random drivers can access
>>> such a low-level function doesn't make me feel very good).
>> I don't know how to architect this better or how to perform  the filtering,
>> but I'm happy to hear suggestions and try them out.
>> Keep in mind that detecting GIC and writing your own gic_send_ipi() is very
>> simple. I have done this when the driver was out of tree. So restricting it by
>> not exporting it will not prevent someone from really accessing the
>> functionality, it's just they have to do it their own way.
> Keep in mind that we are not talking about out of tree hackery. We
> talk about a kernel code submission and I doubt, that you will get
> away with a GIC detection/fiddling burried in your driver code.
>
> Keep in mind that just slapping an export to some random function is
> not much better than doing a GIC hack in the driver.
>
> Marcs concerns about blindly exposing IPI functionality to drivers is
> well justified and that kind of coprocessor stuff is not unique to
> your particular SoC. We're going to see such things more frequently in
> the not so distant future, so we better think now about proper
> solutions to that problem.

Sure I'm not trying to argue against that.

>
> There are a couple of issues to solve:
>
> 1) How is the IPI which is received by the coprocessor reserved in the
>     system?
>
> 2) How is it associated to a particular driver?

Shouldn't 'interrupts' property in DT take care of these 2 questions? 
Maybe we can give it an alias name to make it more readable that this 
interrupt is requested for external IPI.

>
> 3) How do we ensure that a driver cannot issue random IPIs and can
>     only send the associated ones?

If we get the irq number from DT then I'm not sure how feasible it is to 
implement a generic_send_ipi() function that takes this number to 
generate an IPI.

Do you think this approach would work?

>
> None of these issues are handled by your export.
>
> So we need a core infrastructure which allows us to do that. The
> requirements are pretty clear from the above and Marc might have some
> further restrictions in mind.

Another issue I'm having which is related is that I need to communicate 
these GIC irq numbers to AXD core when it starts up. So the logic is 
that these IPIs are not hardwired and it's up to the system designer to 
allocate 2 free GIC irqs to be used for that purpose. At the moment I 
have my own DT property to take these numbers. Hopefully this link would 
explain the issue. See the question about gic-irq property.

     https://lkml.org/lkml/2015/8/24/459

 From what I know there's no generic way for the driver to get the hw 
irq number from linux irq number unless I missed something. Is it 
possible to add something to support this? Or maybe there's something 
but I failed to find?

Thanks,
Qais

>
> Thanks,
>
> 	tglx
Marc Zyngier Aug. 24, 2015, 5:17 p.m. UTC | #9
[adding Mark Rutland, as this is heading straight into uncharted DT
territory]

On 24/08/15 17:39, Qais Yousef wrote:
> On 08/24/2015 04:07 PM, Thomas Gleixner wrote:
>> On Mon, 24 Aug 2015, Qais Yousef wrote:
>>> On 08/24/2015 02:32 PM, Marc Zyngier wrote:
>>>> I'd rather see something more "architected" than this blind export, or
>>>> at least some level of filtering (the idea random drivers can access
>>>> such a low-level function doesn't make me feel very good).
>>> I don't know how to architect this better or how to perform  the filtering,
>>> but I'm happy to hear suggestions and try them out.
>>> Keep in mind that detecting GIC and writing your own gic_send_ipi() is very
>>> simple. I have done this when the driver was out of tree. So restricting it by
>>> not exporting it will not prevent someone from really accessing the
>>> functionality, it's just they have to do it their own way.
>> Keep in mind that we are not talking about out of tree hackery. We
>> talk about a kernel code submission and I doubt, that you will get
>> away with a GIC detection/fiddling burried in your driver code.
>>
>> Keep in mind that just slapping an export to some random function is
>> not much better than doing a GIC hack in the driver.
>>
>> Marcs concerns about blindly exposing IPI functionality to drivers is
>> well justified and that kind of coprocessor stuff is not unique to
>> your particular SoC. We're going to see such things more frequently in
>> the not so distant future, so we better think now about proper
>> solutions to that problem.
> 
> Sure I'm not trying to argue against that.
> 
>>
>> There are a couple of issues to solve:
>>
>> 1) How is the IPI which is received by the coprocessor reserved in the
>>     system?
>>
>> 2) How is it associated to a particular driver?
> 
> Shouldn't 'interrupts' property in DT take care of these 2 questions? 
> Maybe we can give it an alias name to make it more readable that this 
> interrupt is requested for external IPI.

The "interrupts" property has a rather different meaning, and isn't
designed to hardcode IPIs. Also, this property describes an interrupt
from a device to the CPU, not the other way around (I imagine you also
have an interrupt coming from the AXD to the CPU, possibly using an IPI
too).

We can deal with these issues, but that's not something we can improvise.

What I had in mind was something fairly generic:
- interrupt-source: something generating an interrupt
- interrupt-sink: something being targeted by an interrupt

You could then express things like:

intc: interrupt-controller@1000 {
	interrupt-controller;
};

mydevice@f0000000 {
	interrupt-source = <&intc INT_SPEC 2 &inttarg1 &inttarg1>;
};

inttarg1: mydevice@f1000000 {
	interrupt-sink = <&intc HWAFFINITY1>;
};

inttarg2: cpu@1 {
	interrupt-sink = <&intc HWAFFINITY2>;
};

You could also imagine having CPUs being both source and sink.

>>
>> 3) How do we ensure that a driver cannot issue random IPIs and can
>>     only send the associated ones?
> 
> If we get the irq number from DT then I'm not sure how feasible it is to 
> implement a generic_send_ipi() function that takes this number to 
> generate an IPI.
> 
> Do you think this approach would work?

If you follow the above approach, it should be pretty easy to derive a
source identifier and a sink identifier from the DT, and have the core
code to route one to the other and do the right thing.

The source identifier could also be used to describe an IPI in a fairly
safe way (the target being fixed by DT, but the actual number used
dynamically allocated by the kernel).

This is just a 10 minutes braindump, so feel free to throw rocks at it
and to come up with a better solution! :-)

Thanks,

	M.
Qais Yousef Aug. 26, 2015, 11:23 a.m. UTC | #10
On 08/24/2015 06:17 PM, Marc Zyngier wrote:
> [adding Mark Rutland, as this is heading straight into uncharted DT
> territory]
>
> On 24/08/15 17:39, Qais Yousef wrote:
>> On 08/24/2015 04:07 PM, Thomas Gleixner wrote:
>>> On Mon, 24 Aug 2015, Qais Yousef wrote:
>>>> On 08/24/2015 02:32 PM, Marc Zyngier wrote:
>>>>> I'd rather see something more "architected" than this blind export, or
>>>>> at least some level of filtering (the idea random drivers can access
>>>>> such a low-level function doesn't make me feel very good).
>>>> I don't know how to architect this better or how to perform  the filtering,
>>>> but I'm happy to hear suggestions and try them out.
>>>> Keep in mind that detecting GIC and writing your own gic_send_ipi() is very
>>>> simple. I have done this when the driver was out of tree. So restricting it by
>>>> not exporting it will not prevent someone from really accessing the
>>>> functionality, it's just they have to do it their own way.
>>> Keep in mind that we are not talking about out of tree hackery. We
>>> talk about a kernel code submission and I doubt, that you will get
>>> away with a GIC detection/fiddling burried in your driver code.
>>>
>>> Keep in mind that just slapping an export to some random function is
>>> not much better than doing a GIC hack in the driver.
>>>
>>> Marcs concerns about blindly exposing IPI functionality to drivers is
>>> well justified and that kind of coprocessor stuff is not unique to
>>> your particular SoC. We're going to see such things more frequently in
>>> the not so distant future, so we better think now about proper
>>> solutions to that problem.
>> Sure I'm not trying to argue against that.
>>
>>> There are a couple of issues to solve:
>>>
>>> 1) How is the IPI which is received by the coprocessor reserved in the
>>>      system?
>>>
>>> 2) How is it associated to a particular driver?
>> Shouldn't 'interrupts' property in DT take care of these 2 questions?
>> Maybe we can give it an alias name to make it more readable that this
>> interrupt is requested for external IPI.
> The "interrupts" property has a rather different meaning, and isn't
> designed to hardcode IPIs. Also, this property describes an interrupt
> from a device to the CPU, not the other way around (I imagine you also
> have an interrupt coming from the AXD to the CPU, possibly using an IPI
> too).

Yes we have an interrupt from AXD to the CPU. But the way I take
care of the routing at the moment is that the CPU routes the interrupt it
receives from AXD. And AXD routes the interrupt it receives from the
CPU. This is useful because in MIPS GIC the routing is done per hw thread
on the core so this gives the flexibility for each one to choose what it
suits it best.

>
> We can deal with these issues, but that's not something we can improvise.
>
> What I had in mind was something fairly generic:
> - interrupt-source: something generating an interrupt
> - interrupt-sink: something being targeted by an interrupt
>
> You could then express things like:
>
> intc: interrupt-controller@1000 {
> 	interrupt-controller;
> };
>
> mydevice@f0000000 {
> 	interrupt-source = <&intc INT_SPEC 2 &inttarg1 &inttarg1>;
> };

To make sure we're on the same page. INT_SPEC here refers to the arguments
we pass to a standard interrupts property, right?

>
> inttarg1: mydevice@f1000000 {
> 	interrupt-sink = <&intc HWAFFINITY1>;
> };
>
> inttarg2: cpu@1 {
> 	interrupt-sink = <&intc HWAFFINITY2>;
> };

And HWAFFINITY here is the core (or hardware thread) this interrupt will 
be routed to?

So for my case where CPU is on core 0 and AXD is on core 1 my 
description will look like

cpu: cpu@0 {
         interrupt-source = <&gic GIC_SHARED 36 IRQ_TYPE_EDGE_RISING 1 
&axd>;
         interrupt-sink = <&gic 0>;
}

axd: axd {
         interrupt-source = <&gic GIC_SHARED 37 IRQ_TYPE_EDGE_RISING 1 
&cpu>;
         interrupt-sink = <&gic 1>;
}

If I didn't misunderstand you, the issue I see with this is that the 
information about which IRQ to use to send an IPI to AXD is not present 
in the AXD node. We will need to search the cpu node for something that 
is meant to be routed to axd or have some logic to implicitly infer it 
from interrupt-sink in axd node. Not convenient IMO.

Can we replace 'something' in interrupt-source and interrupt-sink 
definitions to 'host' or 'CPU' or do we really care about creating IPI 
between any 2 'things'?

Changing the definition will also make interrupt-sink a synonym/alias to 
interrupts property. So the description will become

axd: axd {
         interrupt-source = <&gic GIC_SHARED 36 IRQ_TYPE_EDGE_RISING>; 
/* interrupt from CPU to AXD */
         interrupt-sink = <&gic GIC_SHARED 37 IRQ_TYPE_EDGE_RISING>; /* 
interrupt from AXD to CPU */
}

But this assume Linux won't take care of the routing. If we want Linux 
to take care of the routing, maybe something like this then?

axd: axd {
         interrupt-source = <&gic GIC_SHARED 36 IRQ_TYPE_EDGE_RISING 
HWAFFINITY1>; /* interrupt from CPU to
AXD@HWAFFINITY1*/
         interrupt-sink = <&gic GIC_SHARED 37 IRQ_TYPE_EDGE_RISING 
HWAFFINITY2>; /* interrupt from AXD to CPU@HWAFFINITY2 */
}

I don't think it's necessary to specify the HWAFFINITY2 for 
interrupt-sink as linux can use SMP affinity to move it around but we 
can make it optional in case there's a need to hardcode it to a specific 
Linux core. Or maybe the driver can use affinity hint..

>
> You could also imagine having CPUs being both source and sink.
>
>>> 3) How do we ensure that a driver cannot issue random IPIs and can
>>>      only send the associated ones?
>> If we get the irq number from DT then I'm not sure how feasible it is to
>> implement a generic_send_ipi() function that takes this number to
>> generate an IPI.
>>
>> Do you think this approach would work?
> If you follow the above approach, it should be pretty easy to derive a
> source identifier and a sink identifier from the DT, and have the core
> code to route one to the other and do the right thing.

Do you think it's better for linux to take care of all the routing 
instead of each core doing its own routing?
If Linux to do the routing for the other core (even if optionally), 
what's the mechanism to do that? We can't use irq_set_affinity() because 
we want to map something that is not part of Linux. A new mapping 
function in struct irq_domain_ops maybe?

>
> The source identifier could also be used to describe an IPI in a fairly
> safe way (the target being fixed by DT, but the actual number used
> dynamically allocated by the kernel).

To be dynamic, then the interrupt controller must specify which 
interrupts are actually free to use. What if the DT doesn't describe all 
the hardawre that is connected to GIC and Linux thinks its free to use 
but actually it's connected to a real hardware but no one told us about? 
I think since this information will always have to be looked up maybe 
it's better to give the responsibility to the user to specify something 
they know will work explicitly.

>
> This is just a 10 minutes braindump, so feel free to throw rocks at it
> and to come up with a better solution! :-)

Thanks for that. My brain is tied down to my use case to come up with 
something generic easily :-)

Any pointers on the best way to tie gic_send_ipi() with the driver/core 
code? The way it's currently tied to the core code is through SMP IPI 
functions which I don't think we can use. I'm thinking adding a pointer 
function in struct irq_chip would be the easiest approach maybe?

Thanks,
Qais

>
> Thanks,
>
> 	M.
Thomas Gleixner Aug. 26, 2015, 1:19 p.m. UTC | #11
On Wed, 26 Aug 2015, Qais Yousef wrote:
> Can we replace 'something' in interrupt-source and interrupt-sink definitions
> to 'host' or 'CPU' or do we really care about creating IPI between any 2
> 'things'?
> 
> Changing the definition will also make interrupt-sink a synonym/alias to
> interrupts property. So the description will become
> 
> axd: axd {
>         interrupt-source = <&gic GIC_SHARED 36 IRQ_TYPE_EDGE_RISING>; /*
> interrupt from CPU to AXD */
>         interrupt-sink = <&gic GIC_SHARED 37 IRQ_TYPE_EDGE_RISING>; /*
> interrupt from AXD to CPU */
> }
> 
> But this assume Linux won't take care of the routing. If we want Linux to take
> care of the routing, maybe something like this then?
> 
> axd: axd {
>         interrupt-source = <&gic GIC_SHARED 36 IRQ_TYPE_EDGE_RISING
> HWAFFINITY1>; /* interrupt from CPU to
> AXD@HWAFFINITY1*/
>         interrupt-sink = <&gic GIC_SHARED 37 IRQ_TYPE_EDGE_RISING
> HWAFFINITY2>; /* interrupt from AXD to CPU@HWAFFINITY2 */
> }
> 
> I don't think it's necessary to specify the HWAFFINITY2 for interrupt-sink as
> linux can use SMP affinity to move it around but we can make it optional in
> case there's a need to hardcode it to a specific Linux core. Or maybe the
> driver can use affinity hint..

Wrong. You cannot move an IPI around with set_affinity. It's possible
to send an IPI to more than one target CPU, but that has nothing to do
with affinities.

Are you talking about IPIs or about general interrupts which have an
affinity setting?

> Any pointers on the best way to tie gic_send_ipi() with the driver/core code?
> The way it's currently tied to the core code is through SMP IPI functions
> which I don't think we can use. I'm thinking adding a pointer function in
> struct irq_chip would be the easiest approach maybe?

That's the least of our worries. We need to get the high level
interfaces and the devicetree mechanism straight before we talk about
this kind of details.

Thanks,

	tglx
Qais Yousef Aug. 26, 2015, 2:57 p.m. UTC | #12
On 08/26/2015 02:19 PM, Thomas Gleixner wrote:
> On Wed, 26 Aug 2015, Qais Yousef wrote:
>> Can we replace 'something' in interrupt-source and interrupt-sink definitions
>> to 'host' or 'CPU' or do we really care about creating IPI between any 2
>> 'things'?
>>
>> Changing the definition will also make interrupt-sink a synonym/alias to
>> interrupts property. So the description will become
>>
>> axd: axd {
>>          interrupt-source = <&gic GIC_SHARED 36 IRQ_TYPE_EDGE_RISING>; /*
>> interrupt from CPU to AXD */
>>          interrupt-sink = <&gic GIC_SHARED 37 IRQ_TYPE_EDGE_RISING>; /*
>> interrupt from AXD to CPU */
>> }
>>
>> But this assume Linux won't take care of the routing. If we want Linux to take
>> care of the routing, maybe something like this then?
>>
>> axd: axd {
>>          interrupt-source = <&gic GIC_SHARED 36 IRQ_TYPE_EDGE_RISING
>> HWAFFINITY1>; /* interrupt from CPU to
>> AXD@HWAFFINITY1*/
>>          interrupt-sink = <&gic GIC_SHARED 37 IRQ_TYPE_EDGE_RISING
>> HWAFFINITY2>; /* interrupt from AXD to CPU@HWAFFINITY2 */
>> }
>>
>> I don't think it's necessary to specify the HWAFFINITY2 for interrupt-sink as
>> linux can use SMP affinity to move it around but we can make it optional in
>> case there's a need to hardcode it to a specific Linux core. Or maybe the
>> driver can use affinity hint..
> Wrong. You cannot move an IPI around with set_affinity. It's possible
> to send an IPI to more than one target CPU, but that has nothing to do
> with affinities.
>
> Are you talking about IPIs or about general interrupts which have an
> affinity setting?

Maybe my view of the world is limited. I wrote this because the 
mechanism to route an IPI and set affinities is the same.
So specifying which core or hardware thread should Linux CPU route this 
IPI to is the same as setting the affinity, no? Linux will not move the 
IPI that is routed to the coprocessor core. Just the IPI it will receive.

Also the way I see it is that this is an external interrupt whether it 
was asserted by real signal or through IPI mechanism and it should be 
treated as such in terms of moving inside Linux SMP, no? Again maybe my 
view of the world is limited but I can't see why migrating the interrupt 
would affect correctness unless there's a hardware limitation like only 
core 0 can read info from AXD (which is where my suggestion to using 
affinity hint above to accommodate such limitations).

When you say 'It is possible to send an IPI to more than one target 
CPU', is it a case we need to cater for? The way I was seeing this 
problem is communication between single Linux SMP and a single 
coprocessor unit. I didn't think of it as single to many. Even if the 
coprocessor is a cluster I'd expect it to act as a single unit like 
Linux SMP. And if it wanted to send 2 different interrupts it will need 
to use 2 different IPIs.

If I'm stating anything obvious above please bear with me. I'm just 
trying to be clear about my view of the world in case I'm missing 
something :-)

>
>> Any pointers on the best way to tie gic_send_ipi() with the driver/core code?
>> The way it's currently tied to the core code is through SMP IPI functions
>> which I don't think we can use. I'm thinking adding a pointer function in
>> struct irq_chip would be the easiest approach maybe?
> That's the least of our worries. We need to get the high level
> interfaces and the devicetree mechanism straight before we talk about
> this kind of details.

Fair enough. The reason I asked is to help me start writing some test 
code but I'll wait.

Thanks,
Qais

>
> Thanks,
>
> 	tglx
Thomas Gleixner Aug. 26, 2015, 3:08 p.m. UTC | #13
On Wed, 26 Aug 2015, Qais Yousef wrote:
> On 08/26/2015 02:19 PM, Thomas Gleixner wrote:
> > Wrong. You cannot move an IPI around with set_affinity. It's possible
> > to send an IPI to more than one target CPU, but that has nothing to do
> > with affinities.
> > 
> > Are you talking about IPIs or about general interrupts which have an
> > affinity setting?
> 
> Maybe my view of the world is limited. I wrote this because the mechanism to
> route an IPI and set affinities is the same.

That might be the case on your particular platform, but that's not
generally true.

> So specifying which core or hardware thread should Linux CPU route this IPI to
> is the same as setting the affinity, no? Linux will not move the IPI that is
> routed to the coprocessor core. Just the IPI it will receive.
> 
> Also the way I see it is that this is an external interrupt whether it was
> asserted by real signal or through IPI mechanism and it should be treated as
> such in terms of moving inside Linux SMP, no? Again maybe my view of the world
> is limited but I can't see why migrating the interrupt would affect
> correctness unless there's a hardware limitation like only core 0 can read
> info from AXD (which is where my suggestion to using affinity hint above to
> accommodate such limitations).
> 
> When you say 'It is possible to send an IPI to more than one target CPU', is
> it a case we need to cater for? The way I was seeing this problem is
> communication between single Linux SMP and a single coprocessor unit. I didn't
> think of it as single to many. Even if the coprocessor is a cluster I'd expect
> it to act as a single unit like Linux SMP. And if it wanted to send 2
> different interrupts it will need to use 2 different IPIs.

You are confusing the terms.

IPI = Inter Processor Interrupt

As the name says that's an interrupt which goes from one cpu to
another. So an IPI has a very clear target.

Whether the platform implements IPIs via general interrupts which are
made affine to a particular cpu or some other specialized mechanism is
completely irrelevant. An IPI is not subject to affinity settings,
period.

So if you want to use an IPI then you need a target cpu for that IPI.

If you want something which can be affined to any cpu, then you need a
general interrupt and not an IPI.

That's what I asked before and you still did not answer that question.

> > Are you talking about IPIs or about general interrupts which have an
> > affinity setting?

Thanks,

	tglx
Qais Yousef Aug. 26, 2015, 3:41 p.m. UTC | #14
On 08/26/2015 04:08 PM, Thomas Gleixner wrote:
> On Wed, 26 Aug 2015, Qais Yousef wrote:
>> On 08/26/2015 02:19 PM, Thomas Gleixner wrote:
>>> Wrong. You cannot move an IPI around with set_affinity. It's possible
>>> to send an IPI to more than one target CPU, but that has nothing to do
>>> with affinities.
>>>
>>> Are you talking about IPIs or about general interrupts which have an
>>> affinity setting?
>> Maybe my view of the world is limited. I wrote this because the mechanism to
>> route an IPI and set affinities is the same.
> That might be the case on your particular platform, but that's not
> generally true.
>
>> So specifying which core or hardware thread should Linux CPU route this IPI to
>> is the same as setting the affinity, no? Linux will not move the IPI that is
>> routed to the coprocessor core. Just the IPI it will receive.
>>
>> Also the way I see it is that this is an external interrupt whether it was
>> asserted by real signal or through IPI mechanism and it should be treated as
>> such in terms of moving inside Linux SMP, no? Again maybe my view of the world
>> is limited but I can't see why migrating the interrupt would affect
>> correctness unless there's a hardware limitation like only core 0 can read
>> info from AXD (which is where my suggestion to using affinity hint above to
>> accommodate such limitations).
>>
>> When you say 'It is possible to send an IPI to more than one target CPU', is
>> it a case we need to cater for? The way I was seeing this problem is
>> communication between single Linux SMP and a single coprocessor unit. I didn't
>> think of it as single to many. Even if the coprocessor is a cluster I'd expect
>> it to act as a single unit like Linux SMP. And if it wanted to send 2
>> different interrupts it will need to use 2 different IPIs.
> You are confusing the terms.
>
> IPI = Inter Processor Interrupt
>
> As the name says that's an interrupt which goes from one cpu to
> another. So an IPI has a very clear target.

OK understood. My interpretation of the processor here was the 
difference. I was viewing the whole linux cpus as one unit with regard 
to its coprocessors.

>
> Whether the platform implements IPIs via general interrupts which are
> made affine to a particular cpu or some other specialized mechanism is
> completely irrelevant. An IPI is not subject to affinity settings,
> period.
>
> So if you want to use an IPI then you need a target cpu for that IPI.
>
> If you want something which can be affined to any cpu, then you need a
> general interrupt and not an IPI.

We are using IPIs to exchange interrupts. Affinity is not important to me.

Thanks,
Qais

>
> That's what I asked before and you still did not answer that question.
>
>>> Are you talking about IPIs or about general interrupts which have an
>>> affinity setting?
> Thanks,
>
> 	tglx
Thomas Gleixner Aug. 26, 2015, 9:40 p.m. UTC | #15
On Wed, 26 Aug 2015, Qais Yousef wrote:
> On 08/26/2015 04:08 PM, Thomas Gleixner wrote:
> > IPI = Inter Processor Interrupt
> > 
> > As the name says that's an interrupt which goes from one cpu to
> > another. So an IPI has a very clear target.
> 
> OK understood. My interpretation of the processor here was the difference. I
> was viewing the whole linux cpus as one unit with regard to its coprocessors.

You can only view it this way if you talk about peripheral interrupts
which are not used as per cpu interrupts and can be routed to a single
cpu or a set of cpus via set_affinity.

> > Whether the platform implements IPIs via general interrupts which are
> > made affine to a particular cpu or some other specialized mechanism is
> > completely irrelevant. An IPI is not subject to affinity settings,
> > period.
> > 
> > So if you want to use an IPI then you need a target cpu for that IPI.
> > 
> > If you want something which can be affined to any cpu, then you need a
> > general interrupt and not an IPI.
> 
> We are using IPIs to exchange interrupts. Affinity is not important to me.

That's a bold statement. If you chose CPU x as the target for the
interrupts received from the coprocessor, then you have pinned the
processing for this stuff on to CPU x. So you limit the freedom of
moving stuff around on the linux cpus.

And if your root irq controller supports sending normal device
interrupts in the same or a similar way as it sends IPIs you can spare
quite some extra handling on the linux side for receiving the
coprocessor interrupt, i.e. you can use just the bog standard
request_irq() mechanism and have the ability to set the affinity of
that interrupt from user space so you can move it to the core on which
your processing happens. Definitely simpler and more flexible, so I
would go there if the hardware allows.

But back to the IPIs. We need infrastructure and DT support to:

1) reserve an IPI

2) send an IPI

3) request/free an IPI

#1 We have no infrastructure for that, but we definitely need one.

   We can look at the IPI as a single linux irq number which is
   replicated on all cpu cores. The replication can happen in hardware
   or by software, but that depends on the underlying root irq
   controller. How that is implemented does not matter for the
   reservation.

   The most flexible and platform independent solution would be to
   describe the IPI space as a seperate irq domain. In most cases this
   would be a hierarchical domain stacked on the root irq domain:

   [IPI-domain] --> [GIC-MIPS-domain]

   on x86 this would be:

   [IPI-domain] --> [vector-domain]

   That needs some change how the IPIs which are used by the kernel
   (rescheduling, function call ..) are set up, but we get a proper
   management and collision avoidance that way. Depending on the
   platform we could actually remove the whole IPI compile time
   reservation and hand out IPIs at boot time on demand and
   dynamically.

   So the reservation function would be something like:

   unsigned int irq_reserve_ipi(const struct cpumask *dest, void *devid);

   @dest contains the possible targets for the IPI. So for generic
   linux IPIs this would be cpu_possible_mask. For your coprocessor
   the target would be a cpumask with just the bit of the coprocessor
   core set. If you need to use an IPI for sending an interrupt from
   the coprocessor to a specific linux core then @dest will contain
   just that target cpu.

   @devid is stored in the IPI domain for sanity checks during
   operation.

   The function returns a linux irq number or 0 if allocation fails.

   We need a complementary interface as well, so you can hand back the
   IPI to the core when the coprocessor is disabled:

   void irq_destroy_ipi(unsigned int irq, void *devid);


   To configure your coprocessor proper, we need a translation
   mechanism from the linux interrupt number to the magic value which
   needs to be written into the trigger register when the coprocessor
   wants to send an interrupt or an IPI.

   int irq_get_irq_hwcfg(unsigned int irq, struct irq_hwcfg *cfg);

   struct irq_hwcfg needs to be defined, but it might look like this:

     {
	/* Generic fields */
	x;
	...
	union {
	      mips_gic;
	      ...
	};
     };

   The actual hw specific value(s) need to be filled in from the irq
   domain specific code.


#2 We have no generic mechanism for that either.

   Something like this is needed:

   void irq_send_ipi(unsigned int irq, const struct cpumask *dest,
   		     void *devid);	      

   @dest is for generic linux IPIs and can be NULL so the IPI is sent to
    	 the core(s) which have been handed in at reservation time

   @devid is used to sanity check the driver call.

   So that finally will call down via a irq chip callback into the
   code which sends the IPI.


#3 Now you get lucky, because we actually have an interface for this

   request_percpu_irq()
   free_percpu_irq()
   disable_percpu_irq()
   enable_percpu_irq()

   Though there is a caveat. enable/disable_percpu_irq() must be
   called from the target cpu, but that should be a solvable problem.

   And at the IPI-domain side we need sanity checks whether the cpu
   from which enable/disable is called is actually configured in the
   reservation mask.
   
   There are a few other nasty details, but that's not important for
   the big picture.

   As I said above, I really would recommend to avoid that if possible
   because a bog standard device interrupt is way simpler to deal
   with. 

That's certainly not the quick and dirty solution you are looking for,
but exposing IPIs to drivers by anything else than a well thought out
infrastructure is not going to happen.

Thanks,

	tglx
Jiang Liu Aug. 27, 2015, 2:22 a.m. UTC | #16
On 2015/8/27 5:40, Thomas Gleixner wrote:
> But back to the IPIs. We need infrastructure and DT support to:
> 
> 1) reserve an IPI
> 
> 2) send an IPI
> 
> 3) request/free an IPI
> 
> #1 We have no infrastructure for that, but we definitely need one.
> 
>    We can look at the IPI as a single linux irq number which is
>    replicated on all cpu cores. The replication can happen in hardware
>    or by software, but that depends on the underlying root irq
>    controller. How that is implemented does not matter for the
>    reservation.
> 
>    The most flexible and platform independent solution would be to
>    describe the IPI space as a seperate irq domain. In most cases this
>    would be a hierarchical domain stacked on the root irq domain:
> 
>    [IPI-domain] --> [GIC-MIPS-domain]
> 
>    on x86 this would be:
> 
>    [IPI-domain] --> [vector-domain]
> 
>    That needs some change how the IPIs which are used by the kernel
>    (rescheduling, function call ..) are set up, but we get a proper
>    management and collision avoidance that way. Depending on the
>    platform we could actually remove the whole IPI compile time
>    reservation and hand out IPIs at boot time on demand and
>    dynamically.
Hi Thomas,
	Good point:) That will make the code more clear.
Thanks!
Gerry
Qais Yousef Aug. 28, 2015, 10:38 a.m. UTC | #17
On 08/26/2015 10:40 PM, Thomas Gleixner wrote:
> On Wed, 26 Aug 2015, Qais Yousef wrote:
>> On 08/26/2015 04:08 PM, Thomas Gleixner wrote:
>>> IPI = Inter Processor Interrupt
>>>
>>> As the name says that's an interrupt which goes from one cpu to
>>> another. So an IPI has a very clear target.
>> OK understood. My interpretation of the processor here was the difference. I
>> was viewing the whole linux cpus as one unit with regard to its coprocessors.
> You can only view it this way if you talk about peripheral interrupts
> which are not used as per cpu interrupts and can be routed to a single
> cpu or a set of cpus via set_affinity.
>
>>> Whether the platform implements IPIs via general interrupts which are
>>> made affine to a particular cpu or some other specialized mechanism is
>>> completely irrelevant. An IPI is not subject to affinity settings,
>>> period.
>>>
>>> So if you want to use an IPI then you need a target cpu for that IPI.
>>>
>>> If you want something which can be affined to any cpu, then you need a
>>> general interrupt and not an IPI.
>> We are using IPIs to exchange interrupts. Affinity is not important to me.
> That's a bold statement. If you chose CPU x as the target for the
> interrupts received from the coprocessor, then you have pinned the
> processing for this stuff on to CPU x. So you limit the freedom of
> moving stuff around on the linux cpus.

I said that because I thought you were telling me if I'm expecting my 
IPIs to be movable then I must be using general interrupts. So what I 
was saying is that we use IPIs and if it's against the rule for them to 
have affinity we can live with that.

>
> And if your root irq controller supports sending normal device
> interrupts in the same or a similar way as it sends IPIs you can spare
> quite some extra handling on the linux side for receiving the
> coprocessor interrupt, i.e. you can use just the bog standard
> request_irq() mechanism and have the ability to set the affinity of
> that interrupt from user space so you can move it to the core on which
> your processing happens. Definitely simpler and more flexible, so I
> would go there if the hardware allows.

That's what I was trying to say but words failed me to explain it 
clearly maybe :(

>
> But back to the IPIs. We need infrastructure and DT support to:
>
> 1) reserve an IPI
>
> 2) send an IPI
>
> 3) request/free an IPI
>
> #1 We have no infrastructure for that, but we definitely need one.
>
>     We can look at the IPI as a single linux irq number which is
>     replicated on all cpu cores. The replication can happen in hardware
>     or by software, but that depends on the underlying root irq
>     controller. How that is implemented does not matter for the
>     reservation.
>
>     The most flexible and platform independent solution would be to
>     describe the IPI space as a seperate irq domain. In most cases this
>     would be a hierarchical domain stacked on the root irq domain:
>
>     [IPI-domain] --> [GIC-MIPS-domain]
>
>     on x86 this would be:
>
>     [IPI-domain] --> [vector-domain]
>
>     That needs some change how the IPIs which are used by the kernel
>     (rescheduling, function call ..) are set up, but we get a proper
>     management and collision avoidance that way. Depending on the
>     platform we could actually remove the whole IPI compile time
>     reservation and hand out IPIs at boot time on demand and
>     dynamically.
>
>     So the reservation function would be something like:
>
>     unsigned int irq_reserve_ipi(const struct cpumask *dest, void *devid);
>
>     @dest contains the possible targets for the IPI. So for generic
>     linux IPIs this would be cpu_possible_mask. For your coprocessor
>     the target would be a cpumask with just the bit of the coprocessor
>     core set. If you need to use an IPI for sending an interrupt from
>     the coprocessor to a specific linux core then @dest will contain
>     just that target cpu.
>
>     @devid is stored in the IPI domain for sanity checks during
>     operation.
>
>     The function returns a linux irq number or 0 if allocation fails.
>
>     We need a complementary interface as well, so you can hand back the
>     IPI to the core when the coprocessor is disabled:
>
>     void irq_destroy_ipi(unsigned int irq, void *devid);
>
>
>     To configure your coprocessor proper, we need a translation
>     mechanism from the linux interrupt number to the magic value which
>     needs to be written into the trigger register when the coprocessor
>     wants to send an interrupt or an IPI.
>
>     int irq_get_irq_hwcfg(unsigned int irq, struct irq_hwcfg *cfg);
>
>     struct irq_hwcfg needs to be defined, but it might look like this:
>
>       {
> 	/* Generic fields */
> 	x;
> 	...
> 	union {
> 	      mips_gic;
> 	      ...
> 	};
>       };
>
>     The actual hw specific value(s) need to be filled in from the irq
>     domain specific code.
>
>
> #2 We have no generic mechanism for that either.
>
>     Something like this is needed:
>
>     void irq_send_ipi(unsigned int irq, const struct cpumask *dest,
>     		     void *devid);	
>
>     @dest is for generic linux IPIs and can be NULL so the IPI is sent to
>      	 the core(s) which have been handed in at reservation time
>
>     @devid is used to sanity check the driver call.
>
>     So that finally will call down via a irq chip callback into the
>     code which sends the IPI.
>
>
> #3 Now you get lucky, because we actually have an interface for this
>
>     request_percpu_irq()
>     free_percpu_irq()
>     disable_percpu_irq()
>     enable_percpu_irq()
>
>     Though there is a caveat. enable/disable_percpu_irq() must be
>     called from the target cpu, but that should be a solvable problem.
>
>     And at the IPI-domain side we need sanity checks whether the cpu
>     from which enable/disable is called is actually configured in the
>     reservation mask.
>     
>     There are a few other nasty details, but that's not important for
>     the big picture.
>
>     As I said above, I really would recommend to avoid that if possible
>     because a bog standard device interrupt is way simpler to deal
>     with.

Agreed. Something for us to think about and consider. But if not for AXD 
this kind of mechanism is important for us for other reasons so we 
probably want to see it through.

>
> That's certainly not the quick and dirty solution you are looking for,
> but exposing IPIs to drivers by anything else than a well thought out
> infrastructure is not going to happen.

Thanks a lot for the detailed explanation. I wasn't looking for a quick 
and dirty solution but my view of the problem is much simpler than yours 
so my idea of a solution would look quick and dirty. I have a better 
appreciation of the problem now and a way to approach it :-)

 From DT point of view are we OK with this form then

     coprocessor {
             interrupt-source = <&intc INT_SPEC COP_HWAFFINITY>;
             interrupt-sink = <&intc INT_SPEC CPU_HWAFFINITY>;
     }

and if the root controller sends normal IPI as it sends normal device 
interrupts then interrupt-sink can be a standard interrupts property 
(like in my case)

     coprocessor {
             interrupt-source = <&intc INT_SPEC COP_HWAFFINITY>;
             interrupts = <INT_SPEC>;
     }

Does this look right to you? Is there something else that needs to be 
covered still?

One more thing I can think of now is that the coprocessor will need the 
raw irq numbers that are picked by linux so that it can use them to 
trigger the IPI. Are we ok to add a function that returns this raw irq 
number (as opposed to linux irq number) directly from DT? The way this 
is communicated to the coprocessor will be platform specific.

Thanks,
Qais

>
> Thanks,
>
> 	tglx
Thomas Gleixner Aug. 28, 2015, 2:22 p.m. UTC | #18
On Fri, 28 Aug 2015, Qais Yousef wrote:
> Thanks a lot for the detailed explanation. I wasn't looking for a quick and
> dirty solution but my view of the problem is much simpler than yours so my
> idea of a solution would look quick and dirty. I have a better appreciation of
> the problem now and a way to approach it :-)
> 
> From DT point of view are we OK with this form then
> 
>     coprocessor {
>             interrupt-source = <&intc INT_SPEC COP_HWAFFINITY>;
>             interrupt-sink = <&intc INT_SPEC CPU_HWAFFINITY>;
>     }
> 
> and if the root controller sends normal IPI as it sends normal device
> interrupts then interrupt-sink can be a standard interrupts property (like in
> my case)
> 
>     coprocessor {
>             interrupt-source = <&intc INT_SPEC COP_HWAFFINITY>;
>             interrupts = <INT_SPEC>;
>     }
> 
> Does this look right to you? Is there something else that needs to be covered
> still?

I'm not an DT wizard. I leave that to the DT experts.
 
> One more thing I can think of now is that the coprocessor will need the raw
> irq numbers that are picked by linux so that it can use them to trigger the
> IPI. Are we ok to add a function that returns this raw irq number (as opposed
> to linux irq number) directly from DT? The way this is communicated to the
> coprocessor will be platform specific.

Why do you want that to be hacked into DT? 

> >     To configure your coprocessor proper, we need a translation
> >     mechanism from the linux interrupt number to the magic value which
> >     needs to be written into the trigger register when the coprocessor
> >     wants to send an interrupt or an IPI.
> > 
> >     int irq_get_irq_hwcfg(unsigned int irq, struct irq_hwcfg *cfg);
> > 
> >     struct irq_hwcfg needs to be defined, but it might look like this:
> > 
> >       {
> > 	/* Generic fields */
> > 	x;
> > 	...
> > 	union {
> > 	      mips_gic;
> > 	      ...
> > 	};
> >       };

That function provides you the information which you have to hand over
to your coprocessor firmware.

Thanks,

	tglx
Qais Yousef Aug. 28, 2015, 3:12 p.m. UTC | #19
On 08/28/2015 03:22 PM, Thomas Gleixner wrote:
>>>      To configure your coprocessor proper, we need a translation
>>>      mechanism from the linux interrupt number to the magic value which
>>>      needs to be written into the trigger register when the coprocessor
>>>      wants to send an interrupt or an IPI.
>>>
>>>      int irq_get_irq_hwcfg(unsigned int irq, struct irq_hwcfg *cfg);
>>>
>>>      struct irq_hwcfg needs to be defined, but it might look like this:
>>>
>>>        {
>>> 	/* Generic fields */
>>> 	x;
>>> 	...
>>> 	union {
>>> 	      mips_gic;
>>> 	      ...
>>> 	};
>>>        };
> That function provides you the information which you have to hand over
> to your coprocessor firmware.
>
>

Of course!

* me slapping myself on the back *

Thanks,
Qais
Qais Yousef Sept. 2, 2015, 9:33 a.m. UTC | #20
On 08/28/2015 03:22 PM, Thomas Gleixner wrote:
> On Fri, 28 Aug 2015, Qais Yousef wrote:
>> Thanks a lot for the detailed explanation. I wasn't looking for a quick and
>> dirty solution but my view of the problem is much simpler than yours so my
>> idea of a solution would look quick and dirty. I have a better appreciation of
>> the problem now and a way to approach it :-)
>>
>>  From DT point of view are we OK with this form then
>>
>>      coprocessor {
>>              interrupt-source = <&intc INT_SPEC COP_HWAFFINITY>;
>>              interrupt-sink = <&intc INT_SPEC CPU_HWAFFINITY>;
>>      }
>>
>> and if the root controller sends normal IPI as it sends normal device
>> interrupts then interrupt-sink can be a standard interrupts property (like in
>> my case)
>>
>>      coprocessor {
>>              interrupt-source = <&intc INT_SPEC COP_HWAFFINITY>;
>>              interrupts = <INT_SPEC>;
>>      }
>>
>> Does this look right to you? Is there something else that needs to be covered
>> still?
> I'm not an DT wizard. I leave that to the DT experts.
>   

Hi Marc Zyngier, Mark Rutland,

Any comments about the DT binding for the IPIs?

To recap, the proposal which is based on Marc Zyngier's is to use 
interrupt-source to represent an IPI from Linux CPU to a coprocessor and 
interrupt-sink to receive an IPI from coprocessor to Linux CPU. 
Hopefully the description above is self explanatory. Please let me know 
if you need more info. Thomas covered the routing, synthesising, and 
requesting parts in the core code. The remaining (high level) issue is 
how to describe the IPIs in DT.

Thanks,
Qais
Marc Zyngier Sept. 2, 2015, 9:55 a.m. UTC | #21
On 02/09/15 10:33, Qais Yousef wrote:
> On 08/28/2015 03:22 PM, Thomas Gleixner wrote:
>> On Fri, 28 Aug 2015, Qais Yousef wrote:
>>> Thanks a lot for the detailed explanation. I wasn't looking for a quick and
>>> dirty solution but my view of the problem is much simpler than yours so my
>>> idea of a solution would look quick and dirty. I have a better appreciation of
>>> the problem now and a way to approach it :-)
>>>
>>>  From DT point of view are we OK with this form then
>>>
>>>      coprocessor {
>>>              interrupt-source = <&intc INT_SPEC COP_HWAFFINITY>;
>>>              interrupt-sink = <&intc INT_SPEC CPU_HWAFFINITY>;
>>>      }
>>>
>>> and if the root controller sends normal IPI as it sends normal device
>>> interrupts then interrupt-sink can be a standard interrupts property (like in
>>> my case)
>>>
>>>      coprocessor {
>>>              interrupt-source = <&intc INT_SPEC COP_HWAFFINITY>;
>>>              interrupts = <INT_SPEC>;
>>>      }
>>>
>>> Does this look right to you? Is there something else that needs to be covered
>>> still?
>> I'm not an DT wizard. I leave that to the DT experts.
>>   
> 
> Hi Marc Zyngier, Mark Rutland,
> 
> Any comments about the DT binding for the IPIs?
> 
> To recap, the proposal which is based on Marc Zyngier's is to use 
> interrupt-source to represent an IPI from Linux CPU to a coprocessor and 
> interrupt-sink to receive an IPI from coprocessor to Linux CPU. 
> Hopefully the description above is self explanatory. Please let me know 
> if you need more info. Thomas covered the routing, synthesising, and 
> requesting parts in the core code. The remaining (high level) issue is 
> how to describe the IPIs in DT.

I'm definitely *not* a DT expert! ;-) My initial binding proposal was
only for wired interrupts, not for IPIs. There is definitely some common
aspects, except for one part:

Who decides on the IPI number? So far, we've avoided encoding IPI
numbers in the DT just like we don't encode MSIs, because they are
programmable things. My feeling is that we shouldn't put the IPI number
in the DT because the rest of the kernel uses them as well and could
decide to use this particular IPI number for its own use: *clash*.

The way I see it would be to have a pool of IPI numbers that the kernel
requests for its own use first, leaving whatever remains to drivers.

Mark (as *you* are the expert ;-), what do you think?

	M.
Qais Yousef Sept. 2, 2015, 10:48 a.m. UTC | #22
On 09/02/2015 10:55 AM, Marc Zyngier wrote:
> On 02/09/15 10:33, Qais Yousef wrote:
>> On 08/28/2015 03:22 PM, Thomas Gleixner wrote:
>>> On Fri, 28 Aug 2015, Qais Yousef wrote:
>>>> Thanks a lot for the detailed explanation. I wasn't looking for a quick and
>>>> dirty solution but my view of the problem is much simpler than yours so my
>>>> idea of a solution would look quick and dirty. I have a better appreciation of
>>>> the problem now and a way to approach it :-)
>>>>
>>>>   From DT point of view are we OK with this form then
>>>>
>>>>       coprocessor {
>>>>               interrupt-source = <&intc INT_SPEC COP_HWAFFINITY>;
>>>>               interrupt-sink = <&intc INT_SPEC CPU_HWAFFINITY>;
>>>>       }
>>>>
>>>> and if the root controller sends normal IPI as it sends normal device
>>>> interrupts then interrupt-sink can be a standard interrupts property (like in
>>>> my case)
>>>>
>>>>       coprocessor {
>>>>               interrupt-source = <&intc INT_SPEC COP_HWAFFINITY>;
>>>>               interrupts = <INT_SPEC>;
>>>>       }
>>>>
>>>> Does this look right to you? Is there something else that needs to be covered
>>>> still?
>>> I'm not an DT wizard. I leave that to the DT experts.
>>>    
>> Hi Marc Zyngier, Mark Rutland,
>>
>> Any comments about the DT binding for the IPIs?
>>
>> To recap, the proposal which is based on Marc Zyngier's is to use
>> interrupt-source to represent an IPI from Linux CPU to a coprocessor and
>> interrupt-sink to receive an IPI from coprocessor to Linux CPU.
>> Hopefully the description above is self explanatory. Please let me know
>> if you need more info. Thomas covered the routing, synthesising, and
>> requesting parts in the core code. The remaining (high level) issue is
>> how to describe the IPIs in DT.
> I'm definitely *not* a DT expert! ;-) My initial binding proposal was
> only for wired interrupts, not for IPIs. There is definitely some common
> aspects, except for one part:
>
> Who decides on the IPI number? So far, we've avoided encoding IPI
> numbers in the DT just like we don't encode MSIs, because they are
> programmable things. My feeling is that we shouldn't put the IPI number
> in the DT because the rest of the kernel uses them as well and could
> decide to use this particular IPI number for its own use: *clash*.

I think this is covered in Thomas proposal to reserve IPIs. His thoughts 
is to use a separate irq-domain for IPIs and use irq_reserve_ipi() and 
irq_destroy_ipi() to get and release IPIs.

>
> The way I see it would be to have a pool of IPI numbers that the kernel
> requests for its own use first, leaving whatever remains to drivers.

That's what Thomas thinks too and he covered this by using 
irq_reserve_ipi() and irq_destroy_ipi().

     https://lkml.org/lkml/2015/8/26/713

It's worth noting in the light of this that INT_SPEC should be optional 
since for hardware similar to mine there's not much to tell the 
controller if it's all dynamic except where we want the IPI to be routed 
to - the INT_SPEC is implicitly defined by the notion it's an IPI.

Thanks,
Qais

>
> Mark (as *you* are the expert ;-), what do you think?
>
> 	M.
Marc Zyngier Sept. 2, 2015, 11:53 a.m. UTC | #23
On 02/09/15 11:48, Qais Yousef wrote:
> On 09/02/2015 10:55 AM, Marc Zyngier wrote:
>> On 02/09/15 10:33, Qais Yousef wrote:
>>> On 08/28/2015 03:22 PM, Thomas Gleixner wrote:
>>>> On Fri, 28 Aug 2015, Qais Yousef wrote:
>>>>> Thanks a lot for the detailed explanation. I wasn't looking for a quick and
>>>>> dirty solution but my view of the problem is much simpler than yours so my
>>>>> idea of a solution would look quick and dirty. I have a better appreciation of
>>>>> the problem now and a way to approach it :-)
>>>>>
>>>>>   From DT point of view are we OK with this form then
>>>>>
>>>>>       coprocessor {
>>>>>               interrupt-source = <&intc INT_SPEC COP_HWAFFINITY>;
>>>>>               interrupt-sink = <&intc INT_SPEC CPU_HWAFFINITY>;
>>>>>       }
>>>>>
>>>>> and if the root controller sends normal IPI as it sends normal device
>>>>> interrupts then interrupt-sink can be a standard interrupts property (like in
>>>>> my case)
>>>>>
>>>>>       coprocessor {
>>>>>               interrupt-source = <&intc INT_SPEC COP_HWAFFINITY>;
>>>>>               interrupts = <INT_SPEC>;
>>>>>       }
>>>>>
>>>>> Does this look right to you? Is there something else that needs to be covered
>>>>> still?
>>>> I'm not an DT wizard. I leave that to the DT experts.
>>>>    
>>> Hi Marc Zyngier, Mark Rutland,
>>>
>>> Any comments about the DT binding for the IPIs?
>>>
>>> To recap, the proposal which is based on Marc Zyngier's is to use
>>> interrupt-source to represent an IPI from Linux CPU to a coprocessor and
>>> interrupt-sink to receive an IPI from coprocessor to Linux CPU.
>>> Hopefully the description above is self explanatory. Please let me know
>>> if you need more info. Thomas covered the routing, synthesising, and
>>> requesting parts in the core code. The remaining (high level) issue is
>>> how to describe the IPIs in DT.
>> I'm definitely *not* a DT expert! ;-) My initial binding proposal was
>> only for wired interrupts, not for IPIs. There is definitely some common
>> aspects, except for one part:
>>
>> Who decides on the IPI number? So far, we've avoided encoding IPI
>> numbers in the DT just like we don't encode MSIs, because they are
>> programmable things. My feeling is that we shouldn't put the IPI number
>> in the DT because the rest of the kernel uses them as well and could
>> decide to use this particular IPI number for its own use: *clash*.
> 
> I think this is covered in Thomas proposal to reserve IPIs. His thoughts 
> is to use a separate irq-domain for IPIs and use irq_reserve_ipi() and 
> irq_destroy_ipi() to get and release IPIs.
> 
>>
>> The way I see it would be to have a pool of IPI numbers that the kernel
>> requests for its own use first, leaving whatever remains to drivers.
> 
> That's what Thomas thinks too and he covered this by using 
> irq_reserve_ipi() and irq_destroy_ipi().
> 
>      https://lkml.org/lkml/2015/8/26/713

Ah, I missed that, sorry for the noise. This looks very sensible.

> It's worth noting in the light of this that INT_SPEC should be optional 
> since for hardware similar to mine there's not much to tell the 
> controller if it's all dynamic except where we want the IPI to be routed 
> to - the INT_SPEC is implicitly defined by the notion it's an IPI.

Well, I'd think that the INT_SPEC should say that it is an IPI, and I
don't believe we should omit it. On the ARM GIC side, our interrupts are
typed (type 0 is a normal wired interrupt, type 1 a per-cpu interrupt,
and we could allocate type 2 to identify an IPI).

But we do need to identify it properly, as we should be able to cover
both IPIs and normal wired interrupts.

Thanks,

	M.
Jason Cooper Sept. 2, 2015, 12:12 p.m. UTC | #24
On Wed, Sep 02, 2015 at 10:55:20AM +0100, Marc Zyngier wrote:
> On 02/09/15 10:33, Qais Yousef wrote:
> > On 08/28/2015 03:22 PM, Thomas Gleixner wrote:
> >> On Fri, 28 Aug 2015, Qais Yousef wrote:
> >>> Thanks a lot for the detailed explanation. I wasn't looking for a quick and
> >>> dirty solution but my view of the problem is much simpler than yours so my
> >>> idea of a solution would look quick and dirty. I have a better appreciation of
> >>> the problem now and a way to approach it :-)
> >>>
> >>>  From DT point of view are we OK with this form then
> >>>
> >>>      coprocessor {
> >>>              interrupt-source = <&intc INT_SPEC COP_HWAFFINITY>;
> >>>              interrupt-sink = <&intc INT_SPEC CPU_HWAFFINITY>;
> >>>      }
> >>>
> >>> and if the root controller sends normal IPI as it sends normal device
> >>> interrupts then interrupt-sink can be a standard interrupts property (like in
> >>> my case)
> >>>
> >>>      coprocessor {
> >>>              interrupt-source = <&intc INT_SPEC COP_HWAFFINITY>;
> >>>              interrupts = <INT_SPEC>;
> >>>      }
> >>>
> >>> Does this look right to you? Is there something else that needs to be covered
> >>> still?
> >> I'm not an DT wizard. I leave that to the DT experts.
> >>   
> > 
> > Hi Marc Zyngier, Mark Rutland,
> > 
> > Any comments about the DT binding for the IPIs?
> > 
> > To recap, the proposal which is based on Marc Zyngier's is to use 
> > interrupt-source to represent an IPI from Linux CPU to a coprocessor and 
> > interrupt-sink to receive an IPI from coprocessor to Linux CPU. 
> > Hopefully the description above is self explanatory. Please let me know 
> > if you need more info. Thomas covered the routing, synthesising, and 
> > requesting parts in the core code. The remaining (high level) issue is 
> > how to describe the IPIs in DT.
> 
> I'm definitely *not* a DT expert! ;-) My initial binding proposal was
> only for wired interrupts, not for IPIs. There is definitely some common
> aspects, except for one part:
> 
> Who decides on the IPI number? So far, we've avoided encoding IPI
> numbers in the DT just like we don't encode MSIs, because they are
> programmable things. My feeling is that we shouldn't put the IPI number
> in the DT because the rest of the kernel uses them as well and could
> decide to use this particular IPI number for its own use: *clash*.

Agree.  The best way I've found to design DT bindings is to imagine
providing the DT to something other than Linux.  The DT should *only* be
describing the hardware.  As such, I think we should be describing the
connection here, and leaving the assignment up to the OS.

thx,

Jason.
Qais Yousef Sept. 2, 2015, 1:25 p.m. UTC | #25
On 09/02/2015 12:53 PM, Marc Zyngier wrote:
> On 02/09/15 11:48, Qais Yousef wrote:
>> It's worth noting in the light of this that INT_SPEC should be optional
>> since for hardware similar to mine there's not much to tell the
>> controller if it's all dynamic except where we want the IPI to be routed
>> to - the INT_SPEC is implicitly defined by the notion it's an IPI.
> Well, I'd think that the INT_SPEC should say that it is an IPI, and I
> don't believe we should omit it. On the ARM GIC side, our interrupts are
> typed (type 0 is a normal wired interrupt, type 1 a per-cpu interrupt,
> and we could allocate type 2 to identify an IPI).

I didn't mean to omit it completely, but just being optional so it's 
specified if the intc needs this info only. I'm assuming that INT_SPEC 
is interrupt controller specific. If not, then ignore me :-)

>
> But we do need to identify it properly, as we should be able to cover
> both IPIs and normal wired interrupts.

I'm a bit confused here. What do you mean by normal wired interrupts? I 
thought this DT binding is only to describe IPIs that needs reserving 
and routing. What am I missing?

Thanks,
Qais
Marc Zyngier Sept. 2, 2015, 2:14 p.m. UTC | #26
On 02/09/15 14:25, Qais Yousef wrote:
> On 09/02/2015 12:53 PM, Marc Zyngier wrote:
>> On 02/09/15 11:48, Qais Yousef wrote:
>>> It's worth noting in the light of this that INT_SPEC should be optional
>>> since for hardware similar to mine there's not much to tell the
>>> controller if it's all dynamic except where we want the IPI to be routed
>>> to - the INT_SPEC is implicitly defined by the notion it's an IPI.
>> Well, I'd think that the INT_SPEC should say that it is an IPI, and I
>> don't believe we should omit it. On the ARM GIC side, our interrupts are
>> typed (type 0 is a normal wired interrupt, type 1 a per-cpu interrupt,
>> and we could allocate type 2 to identify an IPI).
> 
> I didn't mean to omit it completely, but just being optional so it's 
> specified if the intc needs this info only. I'm assuming that INT_SPEC 
> is interrupt controller specific. If not, then ignore me :-)

It is, but I don't think it can really be made optional.

>>
>> But we do need to identify it properly, as we should be able to cover
>> both IPIs and normal wired interrupts.
> 
> I'm a bit confused here. What do you mean by normal wired interrupts? I 
> thought this DT binding is only to describe IPIs that needs reserving 
> and routing. What am I missing?

Look at my initial proposal, and the way I was describing a device
having an interrupt source, and two possible interrupt sinks, one being
a CPU and the other being another device.

I'm looking at solving that case as well, possibly with the same
infrastructure (the routing bit should be the same).

Thanks,

	M.
diff mbox

Patch

diff --git a/drivers/irqchip/irq-mips-gic.c b/drivers/irqchip/irq-mips-gic.c
index ff4be0515a0d..fc6fd506cd7e 100644
--- a/drivers/irqchip/irq-mips-gic.c
+++ b/drivers/irqchip/irq-mips-gic.c
@@ -227,6 +227,7 @@  void gic_send_ipi(unsigned int intr)
 {
 	gic_write(GIC_REG(SHARED, GIC_SH_WEDGE), GIC_SH_WEDGE_SET(intr));
 }
+EXPORT_SYMBOL(gic_send_ipi);
 
 int gic_get_c0_compare_int(void)
 {