A msix interrupt is currently being debugged and a probabilistic loss interruption is found during the test. Msix interrupts are the edge -triggered interrupts by default , andedge -triggered interrupts are interrupted by the corresponding pin When the level signal jumps, an interrupt request is issued. Because the jump is instantaneous, will not be like the level triggered by the interruption of the constant levels, so you may miss a certain jump moment, performance is lost an interrupt.
The function that handles edge triggering interrupts in the kernel is HANDLE_EDGE_IRQ, which is called by the Do_irq function.
void HANDLE_EDGE_IRQ (unsigned int IRQ, struct irq_desc *desc ) { raw_spin_lock (& desc->lock); /* Clear the following two flags because of an interrupt received */ desc->istate &= ~ (Irqs_replay | irqs_waiting ); Whether the/*IRQ is forbidden, is in process, or is not hooked up with an interrupt handler function * /     if   ( unlikely ( irqd_irq_disabled ( & desc ->irq_data ) | |   irqd_irq_inprogress ( & desc ->irq_data ) | | ! desc ->action   {        if   ( ! irq_check_poll ( desc   { ,         desc ->ISTATE |=  irqs_pending ;    /* set irq In the suspended state */   MASK_ACK_IRQ (DESC); / * send ACK to Hardware , block interrupt * / goto out_unlock; } } kstat_incr_irqs_this_cpu (IRQ, desc ); corresponding IRQ calculation plus 1*/ in/*process/interrupts /*cpu The response to this IRQ , indicating that it is ready to receive the next interrupt for this IRQ * / desc->irq_data.chip->irq_ack(&desc ->irq_data ); do { if (unlikely(! desc ->action ) { / * no hook-up interrupt handler function * / mask_irq(desc); /* shielded irq*/ goto out_unlock; } /*IRQ in interrupt pending state * / if (unlikely(desc->istate & irqs_pending)) { if (! irqd_irq_disabled (&desc->irq_data) && irqd_irq_masked(&desc->irq_data) ) unmask_irq(desc); } / * processing interrupts * / handle_irq_event(desc); } while (desc->istate & irqs_pending ) && / * There are pending interrupts that need to be processed * / ! irqd_irq_disabled (&desc->irq_data)); /*IRQ not Forbidden */ |
The Istate member was just beginning to be found in the IRQ_DESC structure, in fact it is defined as follows
#define Istate Core_internal_state__do_not_mess_with_it
the istate corresponds to the core_internal_state__do_not_mess_with_it member.
The IRQS_REPLAY flag is used to save lost interrupts. This flag is set in the check_irq_resend function to re-interrupt the CPU by interrupting the interrupt on the controller APIC, rather than through the peripheral hardware to resend the interrupt. Here the handle_edge_irq function indicates that the interrupt has been received and does not need to be re-sent, so clear this flag.
The irqs_waiting flag indicates the arrival of interrupts, where interrupts are received, and therefore this flag is also cleared. This flag will be cleared at the beginning of the handle_xxx_irq function.
If<1>current IRQ is forbidden ,<2>current IRQ is in process ,<3>The current IRQ has no hook-up handler function , we do not process the receivedIRQ. If the above conditions are met, we set thisIRQto beIrqs_pending hangs and masks interrupts, and then returns. Discard the interrupt processing, leaving the processIRQInterruption ofCPUto deal with thispendingthe interrupt.
The underlying implementation of the Irq_ack function is the write eoi Register, which is the CPU 's response to this IRQ , indicating that the IRQ You want to clear the pending state of this IRQ (used to clear APIC IRR Pending bit), ready to receive the next interrupt. This allows the other CPU to receive this IRQ for processing.
The program is followed by a while loop, with the condition that the IRQ is not blocked and there are pending pending interrupts . Because of the ACK during the processing of the interrupt, the other CPU may receive a new interrupt for this IRQ .
If this IRQ is not hooked up with an interrupt handler , the IRQis directly maskedand returned.
If the IRQ is in the irqs_pending state and the interrupt is not suppressed but is masked, call Unmask_irq to unblock. Think about why you're in a irqs_pending state, and how do you handle it? As mentioned earlier, when this IRQ is being processed, the newly received interrupt sets the irqs_pending state and masks the IRQ.
interrupts in the Edge trigger mode are easily lost, so you cannot block IRQ for long periods of time when processing interrupts . In the HANDLE_EDGE_IRQ function comes up to judge in the IRQ useless is forbidden, useless is processing the case, just ack response to the hardware, no use blocking IRQ , indicating that the additional CPU can receive interrupts for this IRQ.
Copyright NOTICE: This article for Bo Master original article, without Bo Master permission not reproduced.
Edge Interrupt Analysis