Linux Kernel  3.7.1
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
autoprobe.c
Go to the documentation of this file.
1 /*
2  * linux/kernel/irq/autoprobe.c
3  *
4  * Copyright (C) 1992, 1998-2004 Linus Torvalds, Ingo Molnar
5  *
6  * This file contains the interrupt probing code and driver APIs.
7  */
8 
9 #include <linux/irq.h>
10 #include <linux/module.h>
11 #include <linux/interrupt.h>
12 #include <linux/delay.h>
13 #include <linux/async.h>
14 
15 #include "internals.h"
16 
17 /*
18  * Autodetection depends on the fact that any interrupt that
19  * comes in on to an unassigned handler will get stuck with
20  * "IRQS_WAITING" cleared and the interrupt disabled.
21  */
22 static DEFINE_MUTEX(probing_active);
23 
31 unsigned long probe_irq_on(void)
32 {
33  struct irq_desc *desc;
34  unsigned long mask = 0;
35  int i;
36 
37  /*
38  * quiesce the kernel, or at least the asynchronous portion
39  */
41  mutex_lock(&probing_active);
42  /*
43  * something may have generated an irq long ago and we want to
44  * flush such a longstanding irq before considering it as spurious.
45  */
46  for_each_irq_desc_reverse(i, desc) {
47  raw_spin_lock_irq(&desc->lock);
48  if (!desc->action && irq_settings_can_probe(desc)) {
49  /*
50  * Some chips need to know about probing in
51  * progress:
52  */
53  if (desc->irq_data.chip->irq_set_type)
54  desc->irq_data.chip->irq_set_type(&desc->irq_data,
56  irq_startup(desc, false);
57  }
58  raw_spin_unlock_irq(&desc->lock);
59  }
60 
61  /* Wait for longstanding interrupts to trigger. */
62  msleep(20);
63 
64  /*
65  * enable any unassigned irqs
66  * (we must startup again here because if a longstanding irq
67  * happened in the previous stage, it may have masked itself)
68  */
69  for_each_irq_desc_reverse(i, desc) {
70  raw_spin_lock_irq(&desc->lock);
71  if (!desc->action && irq_settings_can_probe(desc)) {
72  desc->istate |= IRQS_AUTODETECT | IRQS_WAITING;
73  if (irq_startup(desc, false))
74  desc->istate |= IRQS_PENDING;
75  }
76  raw_spin_unlock_irq(&desc->lock);
77  }
78 
79  /*
80  * Wait for spurious interrupts to trigger
81  */
82  msleep(100);
83 
84  /*
85  * Now filter out any obviously spurious interrupts
86  */
87  for_each_irq_desc(i, desc) {
88  raw_spin_lock_irq(&desc->lock);
89 
90  if (desc->istate & IRQS_AUTODETECT) {
91  /* It triggered already - consider it spurious. */
92  if (!(desc->istate & IRQS_WAITING)) {
93  desc->istate &= ~IRQS_AUTODETECT;
94  irq_shutdown(desc);
95  } else
96  if (i < 32)
97  mask |= 1 << i;
98  }
99  raw_spin_unlock_irq(&desc->lock);
100  }
101 
102  return mask;
103 }
105 
118 unsigned int probe_irq_mask(unsigned long val)
119 {
120  unsigned int mask = 0;
121  struct irq_desc *desc;
122  int i;
123 
124  for_each_irq_desc(i, desc) {
125  raw_spin_lock_irq(&desc->lock);
126  if (desc->istate & IRQS_AUTODETECT) {
127  if (i < 16 && !(desc->istate & IRQS_WAITING))
128  mask |= 1 << i;
129 
130  desc->istate &= ~IRQS_AUTODETECT;
131  irq_shutdown(desc);
132  }
133  raw_spin_unlock_irq(&desc->lock);
134  }
135  mutex_unlock(&probing_active);
136 
137  return mask & val;
138 }
140 
158 int probe_irq_off(unsigned long val)
159 {
160  int i, irq_found = 0, nr_of_irqs = 0;
161  struct irq_desc *desc;
162 
163  for_each_irq_desc(i, desc) {
164  raw_spin_lock_irq(&desc->lock);
165 
166  if (desc->istate & IRQS_AUTODETECT) {
167  if (!(desc->istate & IRQS_WAITING)) {
168  if (!nr_of_irqs)
169  irq_found = i;
170  nr_of_irqs++;
171  }
172  desc->istate &= ~IRQS_AUTODETECT;
173  irq_shutdown(desc);
174  }
175  raw_spin_unlock_irq(&desc->lock);
176  }
177  mutex_unlock(&probing_active);
178 
179  if (nr_of_irqs > 1)
180  irq_found = -irq_found;
181 
182  return irq_found;
183 }
185