mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
* [PATCH] genirq: Increment irq count for second edge irq when the first is in progress
@ 2012-06-14  6:52 Ning Jiang
  0 siblings, 0 replies; only message in thread
From: Ning Jiang @ 2012-06-14  6:52 UTC (permalink / raw)
  To: tglx; +Cc: linux-kernel, Ning Jiang

kstat_incr_irqs_this_cpu() records the real number of interruptions
to a certain CPU, regardless of the current irq state. That includes
interrupts which are delivered in a state where the device handler
cannot be called.

For level irq, if its disabled or no action available, we'll skip
irq handling. When it is enabled later, the irq will be retriggered
and kstat_incr_irqs_this_cpu() will be incremented again. This counts
the number of interrupts arrived at the CPU and therefor it counts
TWO in this situation. The CPU is interrupted twice, not once. The
accounting works correctly as expected.

But for edge irq, we have a subtle problem. Suppose a second irq
happens when the first is still in progress, it will mark itself
pending and quit, then it will be handled in the same loop after
the first one has been handled. Thus kstat_incr_irqs_this_cpu()
will only be counted once for two irqs.

Add a check in edge handler if there is a irq already in progress,
we'll first kstat_incr_irqs_this_cpu() before we mask and quit, so
that we can get correct irq count in this case.

[ Thanks Thomas for his excellent comments ]

Signed-off-by: Ning Jiang <ning.n.jiang@gmail.com>
---
 kernel/irq/chip.c |    4 ++++
 1 files changed, 4 insertions(+), 0 deletions(-)

diff --git a/kernel/irq/chip.c b/kernel/irq/chip.c
index eebd6d5..254b8aa 100644
--- a/kernel/irq/chip.c
+++ b/kernel/irq/chip.c
@@ -489,6 +489,8 @@ handle_edge_irq(unsigned int irq, struct irq_desc *desc)
 	if (unlikely(irqd_irq_disabled(&desc->irq_data) ||
 		     irqd_irq_inprogress(&desc->irq_data) || !desc->action)) {
 		if (!irq_check_poll(desc)) {
+			if (irqd_irq_inprogress(&desc->irq_data))
+				kstat_incr_irqs_this_cpu(irq, desc);
 			desc->istate |= IRQS_PENDING;
 			mask_ack_irq(desc);
 			goto out_unlock;
@@ -550,6 +552,8 @@ void handle_edge_eoi_irq(unsigned int irq, struct irq_desc *desc)
 	if (unlikely(irqd_irq_disabled(&desc->irq_data) ||
 		     irqd_irq_inprogress(&desc->irq_data) || !desc->action)) {
 		if (!irq_check_poll(desc)) {
+			if (irqd_irq_inprogress(&desc->irq_data))
+				kstat_incr_irqs_this_cpu(irq, desc);
 			desc->istate |= IRQS_PENDING;
 			goto out_eoi;
 		}
-- 
1.7.1


^ permalink raw reply	[flat|nested] only message in thread

only message in thread, other threads:[~2012-06-14  6:55 UTC | newest]

Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2012-06-14  6:52 [PATCH] genirq: Increment irq count for second edge irq when the first is in progress Ning Jiang

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox

all inboxes | Powered by JetHome®