Blame view

kernel/irq/resend.c 2.45 KB
a4633adcd   Thomas Gleixner   [PATCH] genirq: a...
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
  /*
   * linux/kernel/irq/resend.c
   *
   * Copyright (C) 1992, 1998-2006 Linus Torvalds, Ingo Molnar
   * Copyright (C) 2005-2006, Thomas Gleixner
   *
   * This file contains the IRQ-resend code
   *
   * If the interrupt is waiting to be processed, we try to re-run it.
   * We can't directly run it from here since the caller might be in an
   * interrupt-protected region. Not all irq controller chips can
   * retrigger interrupts at the hardware level, so in those cases
   * we allow the resending of IRQs via a tasklet.
   */
  
  #include <linux/irq.h>
  #include <linux/module.h>
  #include <linux/random.h>
  #include <linux/interrupt.h>
  
  #include "internals.h"
  
  #ifdef CONFIG_HARDIRQS_SW_RESEND
  
  /* Bitmap to handle software resend of interrupts: */
c1ee62642   Thomas Gleixner   genirq: Prevent a...
26
  static DECLARE_BITMAP(irqs_resend, IRQ_BITMAP_BITS);
a4633adcd   Thomas Gleixner   [PATCH] genirq: a...
27
28
29
30
31
32
33
34
  
  /*
   * Run software resends of IRQ's
   */
  static void resend_irqs(unsigned long arg)
  {
  	struct irq_desc *desc;
  	int irq;
85c0f9097   Yinghai Lu   irq: introduce nr...
35
36
  	while (!bitmap_empty(irqs_resend, nr_irqs)) {
  		irq = find_first_bit(irqs_resend, nr_irqs);
a4633adcd   Thomas Gleixner   [PATCH] genirq: a...
37
  		clear_bit(irq, irqs_resend);
08678b084   Yinghai Lu   generic: sparse i...
38
  		desc = irq_to_desc(irq);
6a6de9ef5   Thomas Gleixner   [PATCH] genirq: core
39
  		local_irq_disable();
bd0b9ac40   Thomas Gleixner   genirq: Remove ir...
40
  		desc->handle_irq(desc);
6a6de9ef5   Thomas Gleixner   [PATCH] genirq: core
41
  		local_irq_enable();
a4633adcd   Thomas Gleixner   [PATCH] genirq: a...
42
43
44
45
46
47
48
49
50
51
52
53
54
  	}
  }
  
  /* Tasklet to handle resend: */
  static DECLARE_TASKLET(resend_tasklet, resend_irqs, 0);
  
  #endif
  
  /*
   * IRQ resend
   *
   * Is called with interrupts disabled and desc->lock held.
   */
0798abeb7   Jiang Liu   genirq: Remove th...
55
  void check_irq_resend(struct irq_desc *desc)
a4633adcd   Thomas Gleixner   [PATCH] genirq: a...
56
  {
a4633adcd   Thomas Gleixner   [PATCH] genirq: a...
57
  	/*
2464286ac   Thomas Gleixner   genirq: suppress ...
58
59
  	 * We do not resend level type interrupts. Level type
  	 * interrupts are resent by hardware when they are still
d4dc0f90d   Thomas Gleixner   genirq: Allow che...
60
61
  	 * active. Clear the pending bit so suspend/resume does not
  	 * get confused.
2464286ac   Thomas Gleixner   genirq: suppress ...
62
  	 */
d4dc0f90d   Thomas Gleixner   genirq: Allow che...
63
64
  	if (irq_settings_is_level(desc)) {
  		desc->istate &= ~IRQS_PENDING;
87923470c   Thomas Gleixner   genirq: Consolida...
65
  		return;
d4dc0f90d   Thomas Gleixner   genirq: Allow che...
66
  	}
163ef3091   Thomas Gleixner   genirq: Move IRQ_...
67
68
  	if (desc->istate & IRQS_REPLAY)
  		return;
2a0d6fb33   Thomas Gleixner   genirq: Move IRQ_...
69
  	if (desc->istate & IRQS_PENDING) {
2a0d6fb33   Thomas Gleixner   genirq: Move IRQ_...
70
  		desc->istate &= ~IRQS_PENDING;
163ef3091   Thomas Gleixner   genirq: Move IRQ_...
71
  		desc->istate |= IRQS_REPLAY;
a4633adcd   Thomas Gleixner   [PATCH] genirq: a...
72

21e2b8c62   Thomas Gleixner   genirq: Provide c...
73
74
  		if (!desc->irq_data.chip->irq_retrigger ||
  		    !desc->irq_data.chip->irq_retrigger(&desc->irq_data)) {
a4633adcd   Thomas Gleixner   [PATCH] genirq: a...
75
  #ifdef CONFIG_HARDIRQS_SW_RESEND
0798abeb7   Jiang Liu   genirq: Remove th...
76
  			unsigned int irq = irq_desc_get_irq(desc);
293a7a0a1   Thomas Gleixner   genirq: Provide m...
77
  			/*
75a06189f   Thomas Gleixner   genirq: Prevent r...
78
79
80
81
  			 * If the interrupt is running in the thread
  			 * context of the parent irq we need to be
  			 * careful, because we cannot trigger it
  			 * directly.
293a7a0a1   Thomas Gleixner   genirq: Provide m...
82
  			 */
75a06189f   Thomas Gleixner   genirq: Prevent r...
83
84
85
86
87
88
89
90
  			if (irq_settings_is_nested_thread(desc)) {
  				/*
  				 * If the parent_irq is valid, we
  				 * retrigger the parent, otherwise we
  				 * do nothing.
  				 */
  				if (!desc->parent_irq)
  					return;
293a7a0a1   Thomas Gleixner   genirq: Provide m...
91
  				irq = desc->parent_irq;
75a06189f   Thomas Gleixner   genirq: Prevent r...
92
  			}
a4633adcd   Thomas Gleixner   [PATCH] genirq: a...
93
94
95
96
97
98
99
  			/* Set it pending and activate the softirq: */
  			set_bit(irq, irqs_resend);
  			tasklet_schedule(&resend_tasklet);
  #endif
  		}
  	}
  }