/* |
|
* We ack quickly, we don ' t want the IRQ controller |
|
* Thinking we ' re snobs just because some other CPUs have |
|
* Disabled global interrupts (we have already done the |
|
* Int_ack Cycles, it ' s too late to try to pretend to the |
|
* Controller that we aren ' t taking the interrupt). |
|
* |
|
* 0 return value means that this IRQ is already being |
|
* Handled by some and other CPUs. (or is disabled) |
|
*/ |
|
int IRQ = REGS.ORIG_EAX & 0xFF; |
/* High bits used in ret_from_ code * * because before the pressure stack pressure irq-256, so here need & 0xFF to restore, it is amazing,& can use this, IRQ is between 0-223 |
int cpu = SMP_PROCESSOR_ID (); |
Get CPU number |
irq_desc_t *desc = Irq_desc + IRQ; |
Gets the entry for the Interrupt Service Descriptor (Interrupt service program), not the interrupt service routine Descriptor OH |
struct irqaction * action; |
|
unsigned int status; |
|
kstat.irqs[cpu][irq]++; |
Record number of interrupt requests |
Spin_lock (&desc->lock); |
Lock the CPU, interrupt the design into a single CPU non-reentrant, so that a broken line at a point in time can only be processed by one CPU |
Desc->handler->ack (IRQ); |
To confirm the interrupt request, and do not know what to confirm,8259A Controller does not have this function. |
/* |
|
REPLAY is when Linux resends a IRQ that was dropped earlier |
|
Waiting is used by probe to mark IRQs this is being tested |
|
*/ |
|
Status = Desc->status & ~ (Irq_replay | irq_waiting); |
Set the status to not be deleted, not probed, because it is a real interrupt request from the hardware |
Status |= irq_pending; |
/* We _want_ to handle it * * Accept interrupts and prepare to process |
/* |
|
* If The IRQ is disabled for whatever reason, we cannot |
|
* Use the action we have. |
|
*/ |
|
action = NULL; |
Interrupt Service Routine Queue (single-linked list) initially empty |
if (! ( Status & (Irq_disabled | irq_inprogress)) { |
If not, the interrupt is disabled or the service example is impersonating is processed |
action = desc->action; |
Get Interrupt Service Routine queue |
status &= ~irq_pending; |
/* We commit to handling */submit processing |
status |= irq_inprogress; |
/* We are handling it */start processing |
} |
|
Desc->status = status; |
Break status in Update |
/* |
|
* If There is the no IRQ handler or it was disabled, exit early. |
|
Since we set PENDING, if another processor is handling |
|
A different instance of this same IRQ, the other processor |
|
Would take care of it. |
|
*/ |
|
if (!action) |
If the Get Interrupt service queue fails |
goto out; |
Exit |
/* |
|
* Edge triggered interrupts need to remember |
|
* Pending events. |
|
* This applies to any HW interrupts a second |
|
* instance of the same IRQ to arrive while we is in DO_IRQ |
|
* or in the handler. But the code here is only handles the _second_ |
|
* Instance of the IRQ, not the third or fourth. So it is mostly |
|
* Useful for IRQ hardware This does not mask cleanly in an |
|
* SMP environment. |
|
*/ |
|
for (;;) { |
Cycle |
Spin_unlock (&desc->lock); |
Frees a multi- CPU lock, but at this point the disconnection state is irq_inprogress, so even if the other CPUs cannot get the interrupt Service routine queue for the current interrupt line, and this should be the off interrupt state, here are some questions |
handle_irq_event (IRQ, ®s, action); |
The interrupt Service routine queue handles interrupts by allowing each routine in the queue to try to process |
Spin_lock (&desc->lock); |
Get a multi- CPU lock, because the above interrupt Service routine processing will shut down the interrupt, and then open the interrupt, it is possible to get the lock after the shutdown of the outage before another interrupt, that is, the interruption of nesting, although this should be avoided as far as possible. However, it is not understood that even if this interrupt line is interrupted again, because status is irq_inprocess and cannot set status to irq_pending Ah, Is it feared that the driver set this status? Anyway the operating system for us to consider very comprehensive, there are nested can also be executed here serially |
if (! ( Desc->status & irq_pending)) |
Re-detect if there is an interrupt request, if not nested |
Break ; |
Exit |
desc->status &= ~irq_pending; |
Submit Request |
} |
Processing interrupts again |
Desc->status &= ~irq_inprogress; |
Resume interrupt line for no interrupt routine in service state |