Messages in this thread | | | Date | Mon, 5 Jun 2017 10:23:48 +0200 (CEST) | From | Thomas Gleixner <> | Subject | Re: Design of interrupt controller driver |
| |
On Mon, 5 Jun 2017, Mason wrote: > On 04/06/2017 22:13, Thomas Gleixner wrote: > > When you configure the interrupt as edge then you cannot share it. No > > matter whether it stays high or not. > > Could you explain why? (I must be missing something.)
Device A Device B Combined Output Edge detection Low Low 0 N
Low -> High Low 1 Y -> Interrupt handled
High Low -> High 1 N
When the A line stays high, which it does, then the edge detector will not see a transition for B and you lose an interrupt.
> > The only way to share it is, to configure it as level interrupt. But that > > requires that you can disable the interrupt at the DMA device level once it > > triggered. Otherwise you get an interrupt storm. > > I'm not sure what you mean with "disable the interrupt at the > DMA device level". The interrupt can be masked at the system > interrupt controller (i.e. before sharing the interrupt > signal). The DMA engine just outputs 0 when busy, 1 when idle.
Sharing level interrupts requires a way to disable the device (in your case the DMA engine) interrupt output in order to prevent irq storms.
Pseudo code (locking etc. omitted):
irq_handler_devA() { if (!interrupt_active(devA)) return IRQ_NONE;
handle_device_irq();
if (no_more_outstanding_requests(devA)) { reg = readl(devA->irq_control_reg); reg &= ~DEV_IRQ_ENABLE; writel(devA->irq_control_reg, reg); } return IRQ_HANDLED; }
queue_reqeust_devA() { if (no_more_outstanding_requests(devA)) { queue_request(); start_engine();
/* Reenable interrupt at device level */ reg = readl(devA->irq_control_reg); reg |= DEV_IRQ_ENABLE; writel(devA->irq_control_reg, reg); } else { queue_request(); } }
You get the idea.
Thanks,
tglx
| |