Hello,
In DDE Linux26, the interrupt is ignored when an interrupt line is disabled, i.e., the handle_irq field of ddekit_irq_ctrl is 0.
In ne2k-pci, an example in DDE Linux26, when a packet is transmitted by the driver, disable_irq_nosync_lockdep_irqsave() is called to disable irq. Then it triggers a send and calls enable_irq_lockdep_irqrestore().
Now the problem is that after a packet is transmitted, the transmission-done interrupt can be delivered before enable_irq_lockdep_irqrestore is called, so the interrupt is ignored and the driver thinks the packet cannot be transmitted. This situation happens when I run ne2k-pci in the Hurd porting of DDE Linux26.
disable_irq_nosync_lockdep_irqsave is exactly the same as disable_irq_nosync when there isn't CONFIG_LOCKDEP. It seems to me that ne2k-pci shouldn't call it in the first place when transmitting packets, but Linux drivers should be correct. Then what goes wrong? Should the interrupt handler delays interrupts instead of ignoring them silently when the interrupt line is disabled?
Best regards, Zheng Da
Hi,
On Fri, May 07, 2010 at 12:53:20AM +0800, Da Zheng wrote:
disable_irq_nosync_lockdep_irqsave is exactly the same as disable_irq_nosync when there isn't CONFIG_LOCKDEP. It seems to me that ne2k-pci shouldn't call it in the first place when transmitting packets, but Linux drivers should be correct. Then what goes wrong? Should the interrupt handler delays interrupts instead of ignoring them silently when the interrupt line is disabled?
Not really an answer to your question -- but maybe you could try running a Linux image with this driver in the same VM, so you could compare how the driver behaves in its "native" environment?...
-antrik-
On 10-5-7 上午7:51, olafBuddenhagen@gmx.net wrote:
Hi,
On Fri, May 07, 2010 at 12:53:20AM +0800, Da Zheng wrote:
disable_irq_nosync_lockdep_irqsave is exactly the same as disable_irq_nosync when there isn't CONFIG_LOCKDEP. It seems to me that ne2k-pci shouldn't call it in the first place when transmitting packets, but Linux drivers should be correct. Then what goes wrong? Should the interrupt handler delays interrupts instead of ignoring them silently when the interrupt line is disabled?
Not really an answer to your question -- but maybe you could try running a Linux image with this driver in the same VM, so you could compare how the driver behaves in its "native" environment?...
It's difficult to observe the behavior of interrupt handling. It depends on how it is scheduled.
One thing I'm not sure of is whether the interrupt is completely ignored or is delayed to be delivered when a interrupt line is masked with IMR. If the interrupt is ignored, aren't many interrupts lost?
Zheng Da
Hello,
Da Zheng, le Fri 07 May 2010 00:53:20 +0800, a écrit :
In ne2k-pci, an example in DDE Linux26, when a packet is transmitted by the driver, disable_irq_nosync_lockdep_irqsave() is called to disable irq. Then it triggers a send and calls enable_irq_lockdep_irqrestore().
Should the interrupt handler delays interrupts instead of ignoring them silently when the interrupt line is disabled?
See __enable_irq in the linux source code:
check_irq_resend(desc, irq);
which re-sends the irq if it has been set to pending while it was disabled.
Samuel
On 10-5-7 下午4:31, Samuel Thibault wrote:
Hello,
Da Zheng, le Fri 07 May 2010 00:53:20 +0800, a écrit :
In ne2k-pci, an example in DDE Linux26, when a packet is transmitted by the driver, disable_irq_nosync_lockdep_irqsave() is called to disable irq. Then it triggers a send and calls enable_irq_lockdep_irqrestore().
Should the interrupt handler delays interrupts instead of ignoring them silently when the interrupt line is disabled?
See __enable_irq in the linux source code:
check_irq_resend(desc, irq);
which re-sends the irq if it has been set to pending while it was disabled.
OK, I see. Thanks. I kind of understand how irq is handled by Linux. It seems DDE Linux26 might lose some edge-triggered interrupts when irq is disabled since it doesn't set irq pending.
A stupid question: when disable_irq_nosync is called, IRQ_DISABLED is set in the irq descriptor in the Linux kernel and the corresponding hardirq line should be masked as well (at least, it seems the kernel for x86 does so). How can handle_edge_irq be called? or this can only happen on SMP as only the hardirq line in the local CPU is masked?
Zheng Da
Da Zheng, le Sat 08 May 2010 23:19:08 +0800, a écrit :
A stupid question: when disable_irq_nosync is called, IRQ_DISABLED is set in the irq descriptor in the Linux kernel and the corresponding hardirq line should be masked as well (at least, it seems the kernel for x86 does so).
AIUI, on unmask the hardware will trigger the interrupt that was raised by the hardware in the meanwhile. Which precise x86 file are you looking at? What do you exactly mean by "hardirq": the actual hardware chip or the software hardIRQ handler?
How can handle_edge_irq be called?
AIUI, on hardware irq unmasking.
Samuel
On 10-5-12 上午6:03, Samuel Thibault wrote:
Da Zheng, le Sat 08 May 2010 23:19:08 +0800, a écrit :
A stupid question: when disable_irq_nosync is called, IRQ_DISABLED is set in the irq descriptor in the Linux kernel and the corresponding hardirq line should be masked as well (at least, it seems the kernel for x86 does so).
AIUI, on unmask the hardware will trigger the interrupt that was raised by the hardware in the meanwhile. Which precise x86 file are you looking at? What do you exactly mean by "hardirq": the actual hardware chip or the software hardIRQ handler?
In disable_irq_nosync, there is code as follow: desc->status |= IRQ_DISABLED; desc->chip->disable(irq); For the x86 platform, `disable' points to disable_8259A_irq. So when disable_irq_nosync is called, IRQ_DISABLED is set and the irq line (the hardware) is masked.
How can handle_edge_irq be called?
AIUI, on hardware irq unmasking.
When hardware irq is unmasked, IRQ_DISABLED should have been removed. I meant, how can handle_edge_irq be called when IRQ_DISABLED is still set? It seems to me that IRQ_PENDING cannot be set in handle_edge_irq when the irq line is disabled.
Best regards, Zheng Da
Da Zheng, le Wed 12 May 2010 17:36:36 +0800, a écrit :
On 10-5-12 上午6:03, Samuel Thibault wrote:
Da Zheng, le Sat 08 May 2010 23:19:08 +0800, a écrit :
A stupid question: when disable_irq_nosync is called, IRQ_DISABLED is set in the irq descriptor in the Linux kernel and the corresponding hardirq line should be masked as well (at least, it seems the kernel for x86 does so).
AIUI, on unmask the hardware will trigger the interrupt that was raised by the hardware in the meanwhile. Which precise x86 file are you looking at? What do you exactly mean by "hardirq": the actual hardware chip or the software hardIRQ handler?
In disable_irq_nosync, there is code as follow: desc->status |= IRQ_DISABLED; desc->chip->disable(irq); For the x86 platform, `disable' points to disable_8259A_irq. So when disable_irq_nosync is called, IRQ_DISABLED is set and the irq line (the hardware) is masked.
Yes.
How can handle_edge_irq be called?
AIUI, on hardware irq unmasking.
When hardware irq is unmasked, IRQ_DISABLED should have been removed. I meant, how can handle_edge_irq be called when IRQ_DISABLED is still set? It seems to me that IRQ_PENDING cannot be set in handle_edge_irq when the irq line is disabled.
?
if (unlikely((desc->status & (IRQ_INPROGRESS | IRQ_DISABLED)) || !desc->action)) { desc->status |= (IRQ_PENDING | IRQ_MASKED); mask_ack_irq(desc, irq); goto out_unlock; }
So here, even if IRQ_DISABLED is not cleared before the hardware chip part is unmasked, IRQ_PENDING flag will be set.
Samuel
l4-hackers@os.inf.tu-dresden.de