aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/linux/irq.h54
-rw-r--r--kernel/irq/autoprobe.c16
-rw-r--r--kernel/irq/handle.c4
-rw-r--r--kernel/irq/manage.c29
-rw-r--r--kernel/irq/spurious.c23
5 files changed, 66 insertions, 60 deletions
diff --git a/include/linux/irq.h b/include/linux/irq.h
index eac1273dc4e1..92c685414622 100644
--- a/include/linux/irq.h
+++ b/include/linux/irq.h
@@ -1,5 +1,5 @@
1#ifndef __irq_h 1#ifndef _LINUX_IRQ_H
2#define __irq_h 2#define _LINUX_IRQ_H
3 3
4/* 4/*
5 * Please do not include this file in generic code. There is currently 5 * Please do not include this file in generic code. There is currently
@@ -11,7 +11,7 @@
11 11
12#include <linux/smp.h> 12#include <linux/smp.h>
13 13
14#if !defined(CONFIG_S390) 14#ifndef CONFIG_S390
15 15
16#include <linux/linkage.h> 16#include <linux/linkage.h>
17#include <linux/cache.h> 17#include <linux/cache.h>
@@ -33,7 +33,7 @@
33#define IRQ_WAITING 32 /* IRQ not yet seen - for autodetection */ 33#define IRQ_WAITING 32 /* IRQ not yet seen - for autodetection */
34#define IRQ_LEVEL 64 /* IRQ level triggered */ 34#define IRQ_LEVEL 64 /* IRQ level triggered */
35#define IRQ_MASKED 128 /* IRQ masked - shouldn't be seen again */ 35#define IRQ_MASKED 128 /* IRQ masked - shouldn't be seen again */
36#if defined(ARCH_HAS_IRQ_PER_CPU) 36#ifdef ARCH_HAS_IRQ_PER_CPU
37# define IRQ_PER_CPU 256 /* IRQ is per CPU */ 37# define IRQ_PER_CPU 256 /* IRQ is per CPU */
38# define CHECK_IRQ_PER_CPU(var) ((var) & IRQ_PER_CPU) 38# define CHECK_IRQ_PER_CPU(var) ((var) & IRQ_PER_CPU)
39#else 39#else
@@ -45,7 +45,7 @@
45 * to describe about the low-level hardware. 45 * to describe about the low-level hardware.
46 */ 46 */
47struct hw_interrupt_type { 47struct hw_interrupt_type {
48 const char * typename; 48 const char *typename;
49 unsigned int (*startup)(unsigned int irq); 49 unsigned int (*startup)(unsigned int irq);
50 void (*shutdown)(unsigned int irq); 50 void (*shutdown)(unsigned int irq);
51 void (*enable)(unsigned int irq); 51 void (*enable)(unsigned int irq);
@@ -80,7 +80,7 @@ typedef struct irq_desc {
80#ifdef CONFIG_SMP 80#ifdef CONFIG_SMP
81 cpumask_t affinity; 81 cpumask_t affinity;
82#endif 82#endif
83#if defined (CONFIG_GENERIC_PENDING_IRQ) || defined (CONFIG_IRQBALANCE) 83#if defined(CONFIG_GENERIC_PENDING_IRQ) || defined(CONFIG_IRQBALANCE)
84 unsigned int move_irq; /* Flag need to re-target intr dest*/ 84 unsigned int move_irq; /* Flag need to re-target intr dest*/
85#endif 85#endif
86} ____cacheline_aligned irq_desc_t; 86} ____cacheline_aligned irq_desc_t;
@@ -89,9 +89,10 @@ extern irq_desc_t irq_desc [NR_IRQS];
89 89
90#include <asm/hw_irq.h> /* the arch dependent stuff */ 90#include <asm/hw_irq.h> /* the arch dependent stuff */
91 91
92extern int setup_irq(unsigned int irq, struct irqaction * new); 92extern int setup_irq(unsigned int irq, struct irqaction *new);
93 93
94#ifdef CONFIG_GENERIC_HARDIRQS 94#ifdef CONFIG_GENERIC_HARDIRQS
95
95#ifdef CONFIG_SMP 96#ifdef CONFIG_SMP
96static inline void set_native_irq_info(int irq, cpumask_t mask) 97static inline void set_native_irq_info(int irq, cpumask_t mask)
97{ 98{
@@ -105,7 +106,7 @@ static inline void set_native_irq_info(int irq, cpumask_t mask)
105 106
106#ifdef CONFIG_SMP 107#ifdef CONFIG_SMP
107 108
108#if defined (CONFIG_GENERIC_PENDING_IRQ) || defined (CONFIG_IRQBALANCE) 109#if defined(CONFIG_GENERIC_PENDING_IRQ) || defined(CONFIG_IRQBALANCE)
109extern cpumask_t pending_irq_cpumask[NR_IRQS]; 110extern cpumask_t pending_irq_cpumask[NR_IRQS];
110 111
111void set_pending_irq(unsigned int irq, cpumask_t mask); 112void set_pending_irq(unsigned int irq, cpumask_t mask);
@@ -127,7 +128,7 @@ static inline void set_irq_info(int irq, cpumask_t mask)
127{ 128{
128} 129}
129 130
130#else // CONFIG_PCI_MSI 131#else /* CONFIG_PCI_MSI */
131 132
132static inline void move_irq(int irq) 133static inline void move_irq(int irq)
133{ 134{
@@ -138,26 +139,36 @@ static inline void set_irq_info(int irq, cpumask_t mask)
138{ 139{
139 set_native_irq_info(irq, mask); 140 set_native_irq_info(irq, mask);
140} 141}
141#endif // CONFIG_PCI_MSI
142 142
143#else // CONFIG_GENERIC_PENDING_IRQ || CONFIG_IRQBALANCE 143#endif /* CONFIG_PCI_MSI */
144
145#else /* CONFIG_GENERIC_PENDING_IRQ || CONFIG_IRQBALANCE */
146
147static inline void move_irq(int irq)
148{
149}
150
151static inline void move_native_irq(int irq)
152{
153}
154
155static inline void set_pending_irq(unsigned int irq, cpumask_t mask)
156{
157}
144 158
145#define move_irq(x)
146#define move_native_irq(x)
147#define set_pending_irq(x,y)
148static inline void set_irq_info(int irq, cpumask_t mask) 159static inline void set_irq_info(int irq, cpumask_t mask)
149{ 160{
150 set_native_irq_info(irq, mask); 161 set_native_irq_info(irq, mask);
151} 162}
152 163
153#endif // CONFIG_GENERIC_PENDING_IRQ 164#endif /* CONFIG_GENERIC_PENDING_IRQ */
154 165
155#else // CONFIG_SMP 166#else /* CONFIG_SMP */
156 167
157#define move_irq(x) 168#define move_irq(x)
158#define move_native_irq(x) 169#define move_native_irq(x)
159 170
160#endif // CONFIG_SMP 171#endif /* CONFIG_SMP */
161 172
162#ifdef CONFIG_IRQBALANCE 173#ifdef CONFIG_IRQBALANCE
163extern void set_balance_irq_affinity(unsigned int irq, cpumask_t mask); 174extern void set_balance_irq_affinity(unsigned int irq, cpumask_t mask);
@@ -186,17 +197,16 @@ extern void init_irq_proc(void);
186#ifdef CONFIG_AUTO_IRQ_AFFINITY 197#ifdef CONFIG_AUTO_IRQ_AFFINITY
187extern int select_smp_affinity(unsigned int irq); 198extern int select_smp_affinity(unsigned int irq);
188#else 199#else
189static inline int 200static inline int select_smp_affinity(unsigned int irq)
190select_smp_affinity(unsigned int irq)
191{ 201{
192 return 1; 202 return 1;
193} 203}
194#endif 204#endif
195 205
196#endif 206#endif /* CONFIG_GENERIC_HARDIRQS */
197 207
198extern hw_irq_controller no_irq_type; /* needed in every arch ? */ 208extern hw_irq_controller no_irq_type; /* needed in every arch ? */
199 209
200#endif 210#endif /* !CONFIG_S390 */
201 211
202#endif /* __irq_h */ 212#endif /* _LINUX_IRQ_H */
diff --git a/kernel/irq/autoprobe.c b/kernel/irq/autoprobe.c
index d1f1e6f10a23..d6eab98a3173 100644
--- a/kernel/irq/autoprobe.c
+++ b/kernel/irq/autoprobe.c
@@ -27,7 +27,7 @@ static DEFINE_MUTEX(probing_active);
27 */ 27 */
28unsigned long probe_irq_on(void) 28unsigned long probe_irq_on(void)
29{ 29{
30 unsigned long val; 30 unsigned long mask;
31 irq_desc_t *desc; 31 irq_desc_t *desc;
32 unsigned int i; 32 unsigned int i;
33 33
@@ -40,8 +40,8 @@ unsigned long probe_irq_on(void)
40 desc = irq_desc + i; 40 desc = irq_desc + i;
41 41
42 spin_lock_irq(&desc->lock); 42 spin_lock_irq(&desc->lock);
43 if (!irq_desc[i].action) 43 if (!desc->action)
44 irq_desc[i].chip->startup(i); 44 desc->chip->startup(i);
45 spin_unlock_irq(&desc->lock); 45 spin_unlock_irq(&desc->lock);
46 } 46 }
47 47
@@ -73,11 +73,11 @@ unsigned long probe_irq_on(void)
73 /* 73 /*
74 * Now filter out any obviously spurious interrupts 74 * Now filter out any obviously spurious interrupts
75 */ 75 */
76 val = 0; 76 mask = 0;
77 for (i = 0; i < NR_IRQS; i++) { 77 for (i = 0; i < NR_IRQS; i++) {
78 irq_desc_t *desc = irq_desc + i;
79 unsigned int status; 78 unsigned int status;
80 79
80 desc = irq_desc + i;
81 spin_lock_irq(&desc->lock); 81 spin_lock_irq(&desc->lock);
82 status = desc->status; 82 status = desc->status;
83 83
@@ -88,14 +88,13 @@ unsigned long probe_irq_on(void)
88 desc->chip->shutdown(i); 88 desc->chip->shutdown(i);
89 } else 89 } else
90 if (i < 32) 90 if (i < 32)
91 val |= 1 << i; 91 mask |= 1 << i;
92 } 92 }
93 spin_unlock_irq(&desc->lock); 93 spin_unlock_irq(&desc->lock);
94 } 94 }
95 95
96 return val; 96 return mask;
97} 97}
98
99EXPORT_SYMBOL(probe_irq_on); 98EXPORT_SYMBOL(probe_irq_on);
100 99
101/** 100/**
@@ -184,6 +183,5 @@ int probe_irq_off(unsigned long val)
184 183
185 return irq_found; 184 return irq_found;
186} 185}
187
188EXPORT_SYMBOL(probe_irq_off); 186EXPORT_SYMBOL(probe_irq_off);
189 187
diff --git a/kernel/irq/handle.c b/kernel/irq/handle.c
index 6b313ccf0edd..f9c33a86cbdf 100644
--- a/kernel/irq/handle.c
+++ b/kernel/irq/handle.c
@@ -18,7 +18,7 @@
18 * Linux has a controller-independent interrupt architecture. 18 * Linux has a controller-independent interrupt architecture.
19 * Every controller has a 'controller-template', that is used 19 * Every controller has a 'controller-template', that is used
20 * by the main code to do the right thing. Each driver-visible 20 * by the main code to do the right thing. Each driver-visible
21 * interrupt source is transparently wired to the apropriate 21 * interrupt source is transparently wired to the appropriate
22 * controller. Thus drivers need not be aware of the 22 * controller. Thus drivers need not be aware of the
23 * interrupt-controller. 23 * interrupt-controller.
24 * 24 *
@@ -111,7 +111,7 @@ irqreturn_t handle_IRQ_event(unsigned int irq, struct pt_regs *regs,
111fastcall unsigned int __do_IRQ(unsigned int irq, struct pt_regs *regs) 111fastcall unsigned int __do_IRQ(unsigned int irq, struct pt_regs *regs)
112{ 112{
113 irq_desc_t *desc = irq_desc + irq; 113 irq_desc_t *desc = irq_desc + irq;
114 struct irqaction * action; 114 struct irqaction *action;
115 unsigned int status; 115 unsigned int status;
116 116
117 kstat_this_cpu.irqs[irq]++; 117 kstat_this_cpu.irqs[irq]++;
diff --git a/kernel/irq/manage.c b/kernel/irq/manage.c
index c53662edc73d..261906ebdf04 100644
--- a/kernel/irq/manage.c
+++ b/kernel/irq/manage.c
@@ -40,7 +40,6 @@ void synchronize_irq(unsigned int irq)
40 while (desc->status & IRQ_INPROGRESS) 40 while (desc->status & IRQ_INPROGRESS)
41 cpu_relax(); 41 cpu_relax();
42} 42}
43
44EXPORT_SYMBOL(synchronize_irq); 43EXPORT_SYMBOL(synchronize_irq);
45 44
46#endif 45#endif
@@ -71,7 +70,6 @@ void disable_irq_nosync(unsigned int irq)
71 } 70 }
72 spin_unlock_irqrestore(&desc->lock, flags); 71 spin_unlock_irqrestore(&desc->lock, flags);
73} 72}
74
75EXPORT_SYMBOL(disable_irq_nosync); 73EXPORT_SYMBOL(disable_irq_nosync);
76 74
77/** 75/**
@@ -97,7 +95,6 @@ void disable_irq(unsigned int irq)
97 if (desc->action) 95 if (desc->action)
98 synchronize_irq(irq); 96 synchronize_irq(irq);
99} 97}
100
101EXPORT_SYMBOL(disable_irq); 98EXPORT_SYMBOL(disable_irq);
102 99
103/** 100/**
@@ -139,7 +136,6 @@ void enable_irq(unsigned int irq)
139 } 136 }
140 spin_unlock_irqrestore(&desc->lock, flags); 137 spin_unlock_irqrestore(&desc->lock, flags);
141} 138}
142
143EXPORT_SYMBOL(enable_irq); 139EXPORT_SYMBOL(enable_irq);
144 140
145/* 141/*
@@ -166,7 +162,7 @@ int can_request_irq(unsigned int irq, unsigned long irqflags)
166 * Internal function to register an irqaction - typically used to 162 * Internal function to register an irqaction - typically used to
167 * allocate special interrupts that are part of the architecture. 163 * allocate special interrupts that are part of the architecture.
168 */ 164 */
169int setup_irq(unsigned int irq, struct irqaction * new) 165int setup_irq(unsigned int irq, struct irqaction *new)
170{ 166{
171 struct irq_desc *desc = irq_desc + irq; 167 struct irq_desc *desc = irq_desc + irq;
172 struct irqaction *old, **p; 168 struct irqaction *old, **p;
@@ -198,9 +194,10 @@ int setup_irq(unsigned int irq, struct irqaction * new)
198 /* 194 /*
199 * The following block of code has to be executed atomically 195 * The following block of code has to be executed atomically
200 */ 196 */
201 spin_lock_irqsave(&desc->lock,flags); 197 spin_lock_irqsave(&desc->lock, flags);
202 p = &desc->action; 198 p = &desc->action;
203 if ((old = *p) != NULL) { 199 old = *p;
200 if (old) {
204 /* Can't share interrupts unless both agree to */ 201 /* Can't share interrupts unless both agree to */
205 if (!(old->flags & new->flags & SA_SHIRQ)) 202 if (!(old->flags & new->flags & SA_SHIRQ))
206 goto mismatch; 203 goto mismatch;
@@ -233,7 +230,7 @@ int setup_irq(unsigned int irq, struct irqaction * new)
233 else 230 else
234 desc->chip->enable(irq); 231 desc->chip->enable(irq);
235 } 232 }
236 spin_unlock_irqrestore(&desc->lock,flags); 233 spin_unlock_irqrestore(&desc->lock, flags);
237 234
238 new->irq = irq; 235 new->irq = irq;
239 register_irq_proc(irq); 236 register_irq_proc(irq);
@@ -276,10 +273,10 @@ void free_irq(unsigned int irq, void *dev_id)
276 return; 273 return;
277 274
278 desc = irq_desc + irq; 275 desc = irq_desc + irq;
279 spin_lock_irqsave(&desc->lock,flags); 276 spin_lock_irqsave(&desc->lock, flags);
280 p = &desc->action; 277 p = &desc->action;
281 for (;;) { 278 for (;;) {
282 struct irqaction * action = *p; 279 struct irqaction *action = *p;
283 280
284 if (action) { 281 if (action) {
285 struct irqaction **pp = p; 282 struct irqaction **pp = p;
@@ -304,7 +301,7 @@ void free_irq(unsigned int irq, void *dev_id)
304 else 301 else
305 desc->chip->disable(irq); 302 desc->chip->disable(irq);
306 } 303 }
307 spin_unlock_irqrestore(&desc->lock,flags); 304 spin_unlock_irqrestore(&desc->lock, flags);
308 unregister_handler_proc(irq, action); 305 unregister_handler_proc(irq, action);
309 306
310 /* Make sure it's not being used on another CPU */ 307 /* Make sure it's not being used on another CPU */
@@ -312,12 +309,11 @@ void free_irq(unsigned int irq, void *dev_id)
312 kfree(action); 309 kfree(action);
313 return; 310 return;
314 } 311 }
315 printk(KERN_ERR "Trying to free free IRQ%d\n",irq); 312 printk(KERN_ERR "Trying to free free IRQ%d\n", irq);
316 spin_unlock_irqrestore(&desc->lock,flags); 313 spin_unlock_irqrestore(&desc->lock, flags);
317 return; 314 return;
318 } 315 }
319} 316}
320
321EXPORT_SYMBOL(free_irq); 317EXPORT_SYMBOL(free_irq);
322 318
323/** 319/**
@@ -351,9 +347,9 @@ EXPORT_SYMBOL(free_irq);
351 */ 347 */
352int request_irq(unsigned int irq, 348int request_irq(unsigned int irq,
353 irqreturn_t (*handler)(int, void *, struct pt_regs *), 349 irqreturn_t (*handler)(int, void *, struct pt_regs *),
354 unsigned long irqflags, const char * devname, void *dev_id) 350 unsigned long irqflags, const char *devname, void *dev_id)
355{ 351{
356 struct irqaction * action; 352 struct irqaction *action;
357 int retval; 353 int retval;
358 354
359 /* 355 /*
@@ -388,6 +384,5 @@ int request_irq(unsigned int irq,
388 384
389 return retval; 385 return retval;
390} 386}
391
392EXPORT_SYMBOL(request_irq); 387EXPORT_SYMBOL(request_irq);
393 388
diff --git a/kernel/irq/spurious.c b/kernel/irq/spurious.c
index ea3ceed362da..5eae7bf3c347 100644
--- a/kernel/irq/spurious.c
+++ b/kernel/irq/spurious.c
@@ -16,22 +16,20 @@ static int irqfixup __read_mostly;
16/* 16/*
17 * Recovery handler for misrouted interrupts. 17 * Recovery handler for misrouted interrupts.
18 */ 18 */
19
20static int misrouted_irq(int irq, struct pt_regs *regs) 19static int misrouted_irq(int irq, struct pt_regs *regs)
21{ 20{
22 int i; 21 int i;
23 irq_desc_t *desc;
24 int ok = 0; 22 int ok = 0;
25 int work = 0; /* Did we do work for a real IRQ */ 23 int work = 0; /* Did we do work for a real IRQ */
26 24
27 for(i = 1; i < NR_IRQS; i++) { 25 for (i = 1; i < NR_IRQS; i++) {
26 struct irq_desc *desc = irq_desc + i;
28 struct irqaction *action; 27 struct irqaction *action;
29 28
30 if (i == irq) /* Already tried */ 29 if (i == irq) /* Already tried */
31 continue; 30 continue;
32 desc = &irq_desc[i]; 31
33 spin_lock(&desc->lock); 32 spin_lock(&desc->lock);
34 action = desc->action;
35 /* Already running on another processor */ 33 /* Already running on another processor */
36 if (desc->status & IRQ_INPROGRESS) { 34 if (desc->status & IRQ_INPROGRESS) {
37 /* 35 /*
@@ -45,7 +43,9 @@ static int misrouted_irq(int irq, struct pt_regs *regs)
45 } 43 }
46 /* Honour the normal IRQ locking */ 44 /* Honour the normal IRQ locking */
47 desc->status |= IRQ_INPROGRESS; 45 desc->status |= IRQ_INPROGRESS;
46 action = desc->action;
48 spin_unlock(&desc->lock); 47 spin_unlock(&desc->lock);
48
49 while (action) { 49 while (action) {
50 /* Only shared IRQ handlers are safe to call */ 50 /* Only shared IRQ handlers are safe to call */
51 if (action->flags & SA_SHIRQ) { 51 if (action->flags & SA_SHIRQ) {
@@ -62,9 +62,8 @@ static int misrouted_irq(int irq, struct pt_regs *regs)
62 62
63 /* 63 /*
64 * While we were looking for a fixup someone queued a real 64 * While we were looking for a fixup someone queued a real
65 * IRQ clashing with our walk 65 * IRQ clashing with our walk:
66 */ 66 */
67
68 while ((desc->status & IRQ_PENDING) && action) { 67 while ((desc->status & IRQ_PENDING) && action) {
69 /* 68 /*
70 * Perform real IRQ processing for the IRQ we deferred 69 * Perform real IRQ processing for the IRQ we deferred
@@ -80,7 +79,7 @@ static int misrouted_irq(int irq, struct pt_regs *regs)
80 * If we did actual work for the real IRQ line we must let the 79 * If we did actual work for the real IRQ line we must let the
81 * IRQ controller clean up too 80 * IRQ controller clean up too
82 */ 81 */
83 if(work) 82 if (work)
84 desc->chip->end(i); 83 desc->chip->end(i);
85 spin_unlock(&desc->lock); 84 spin_unlock(&desc->lock);
86 } 85 }
@@ -113,6 +112,7 @@ __report_bad_irq(unsigned int irq, irq_desc_t *desc, irqreturn_t action_ret)
113 } 112 }
114 dump_stack(); 113 dump_stack();
115 printk(KERN_ERR "handlers:\n"); 114 printk(KERN_ERR "handlers:\n");
115
116 action = desc->action; 116 action = desc->action;
117 while (action) { 117 while (action) {
118 printk(KERN_ERR "[<%p>]", action->handler); 118 printk(KERN_ERR "[<%p>]", action->handler);
@@ -123,7 +123,8 @@ __report_bad_irq(unsigned int irq, irq_desc_t *desc, irqreturn_t action_ret)
123 } 123 }
124} 124}
125 125
126static void report_bad_irq(unsigned int irq, irq_desc_t *desc, irqreturn_t action_ret) 126static void
127report_bad_irq(unsigned int irq, irq_desc_t *desc, irqreturn_t action_ret)
127{ 128{
128 static int count = 100; 129 static int count = 100;
129 130
@@ -134,7 +135,7 @@ static void report_bad_irq(unsigned int irq, irq_desc_t *desc, irqreturn_t actio
134} 135}
135 136
136void note_interrupt(unsigned int irq, irq_desc_t *desc, irqreturn_t action_ret, 137void note_interrupt(unsigned int irq, irq_desc_t *desc, irqreturn_t action_ret,
137 struct pt_regs *regs) 138 struct pt_regs *regs)
138{ 139{
139 if (unlikely(action_ret != IRQ_HANDLED)) { 140 if (unlikely(action_ret != IRQ_HANDLED)) {
140 desc->irqs_unhandled++; 141 desc->irqs_unhandled++;
@@ -177,6 +178,7 @@ int __init noirqdebug_setup(char *str)
177{ 178{
178 noirqdebug = 1; 179 noirqdebug = 1;
179 printk(KERN_INFO "IRQ lockup detection disabled\n"); 180 printk(KERN_INFO "IRQ lockup detection disabled\n");
181
180 return 1; 182 return 1;
181} 183}
182 184
@@ -187,6 +189,7 @@ static int __init irqfixup_setup(char *str)
187 irqfixup = 1; 189 irqfixup = 1;
188 printk(KERN_WARNING "Misrouted IRQ fixup support enabled.\n"); 190 printk(KERN_WARNING "Misrouted IRQ fixup support enabled.\n");
189 printk(KERN_WARNING "This may impact system performance.\n"); 191 printk(KERN_WARNING "This may impact system performance.\n");
192
190 return 1; 193 return 1;
191} 194}
192 195