aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/irq
diff options
context:
space:
mode:
Diffstat (limited to 'kernel/irq')
-rw-r--r--kernel/irq/chip.c12
-rw-r--r--kernel/irq/manage.c110
2 files changed, 75 insertions, 47 deletions
diff --git a/kernel/irq/chip.c b/kernel/irq/chip.c
index 964964baefa2..3cd441ebf5d2 100644
--- a/kernel/irq/chip.c
+++ b/kernel/irq/chip.c
@@ -28,8 +28,7 @@ void dynamic_irq_init(unsigned int irq)
28 unsigned long flags; 28 unsigned long flags;
29 29
30 if (irq >= NR_IRQS) { 30 if (irq >= NR_IRQS) {
31 printk(KERN_ERR "Trying to initialize invalid IRQ%d\n", irq); 31 WARN(1, KERN_ERR "Trying to initialize invalid IRQ%d\n", irq);
32 WARN_ON(1);
33 return; 32 return;
34 } 33 }
35 34
@@ -62,8 +61,7 @@ void dynamic_irq_cleanup(unsigned int irq)
62 unsigned long flags; 61 unsigned long flags;
63 62
64 if (irq >= NR_IRQS) { 63 if (irq >= NR_IRQS) {
65 printk(KERN_ERR "Trying to cleanup invalid IRQ%d\n", irq); 64 WARN(1, KERN_ERR "Trying to cleanup invalid IRQ%d\n", irq);
66 WARN_ON(1);
67 return; 65 return;
68 } 66 }
69 67
@@ -71,9 +69,8 @@ void dynamic_irq_cleanup(unsigned int irq)
71 spin_lock_irqsave(&desc->lock, flags); 69 spin_lock_irqsave(&desc->lock, flags);
72 if (desc->action) { 70 if (desc->action) {
73 spin_unlock_irqrestore(&desc->lock, flags); 71 spin_unlock_irqrestore(&desc->lock, flags);
74 printk(KERN_ERR "Destroying IRQ%d without calling free_irq\n", 72 WARN(1, KERN_ERR "Destroying IRQ%d without calling free_irq\n",
75 irq); 73 irq);
76 WARN_ON(1);
77 return; 74 return;
78 } 75 }
79 desc->msi_desc = NULL; 76 desc->msi_desc = NULL;
@@ -96,8 +93,7 @@ int set_irq_chip(unsigned int irq, struct irq_chip *chip)
96 unsigned long flags; 93 unsigned long flags;
97 94
98 if (irq >= NR_IRQS) { 95 if (irq >= NR_IRQS) {
99 printk(KERN_ERR "Trying to install chip for IRQ%d\n", irq); 96 WARN(1, KERN_ERR "Trying to install chip for IRQ%d\n", irq);
100 WARN_ON(1);
101 return -EINVAL; 97 return -EINVAL;
102 } 98 }
103 99
diff --git a/kernel/irq/manage.c b/kernel/irq/manage.c
index 77a51be36010..152abfd3589f 100644
--- a/kernel/irq/manage.c
+++ b/kernel/irq/manage.c
@@ -177,8 +177,7 @@ static void __enable_irq(struct irq_desc *desc, unsigned int irq)
177{ 177{
178 switch (desc->depth) { 178 switch (desc->depth) {
179 case 0: 179 case 0:
180 printk(KERN_WARNING "Unbalanced enable for IRQ %d\n", irq); 180 WARN(1, KERN_WARNING "Unbalanced enable for IRQ %d\n", irq);
181 WARN_ON(1);
182 break; 181 break;
183 case 1: { 182 case 1: {
184 unsigned int status = desc->status & ~IRQ_DISABLED; 183 unsigned int status = desc->status & ~IRQ_DISABLED;
@@ -217,6 +216,17 @@ void enable_irq(unsigned int irq)
217} 216}
218EXPORT_SYMBOL(enable_irq); 217EXPORT_SYMBOL(enable_irq);
219 218
219int set_irq_wake_real(unsigned int irq, unsigned int on)
220{
221 struct irq_desc *desc = irq_desc + irq;
222 int ret = -ENXIO;
223
224 if (desc->chip->set_wake)
225 ret = desc->chip->set_wake(irq, on);
226
227 return ret;
228}
229
220/** 230/**
221 * set_irq_wake - control irq power management wakeup 231 * set_irq_wake - control irq power management wakeup
222 * @irq: interrupt to control 232 * @irq: interrupt to control
@@ -233,30 +243,32 @@ int set_irq_wake(unsigned int irq, unsigned int on)
233{ 243{
234 struct irq_desc *desc = irq_desc + irq; 244 struct irq_desc *desc = irq_desc + irq;
235 unsigned long flags; 245 unsigned long flags;
236 int ret = -ENXIO; 246 int ret = 0;
237 int (*set_wake)(unsigned, unsigned) = desc->chip->set_wake;
238 247
239 /* wakeup-capable irqs can be shared between drivers that 248 /* wakeup-capable irqs can be shared between drivers that
240 * don't need to have the same sleep mode behaviors. 249 * don't need to have the same sleep mode behaviors.
241 */ 250 */
242 spin_lock_irqsave(&desc->lock, flags); 251 spin_lock_irqsave(&desc->lock, flags);
243 if (on) { 252 if (on) {
244 if (desc->wake_depth++ == 0) 253 if (desc->wake_depth++ == 0) {
245 desc->status |= IRQ_WAKEUP; 254 ret = set_irq_wake_real(irq, on);
246 else 255 if (ret)
247 set_wake = NULL; 256 desc->wake_depth = 0;
257 else
258 desc->status |= IRQ_WAKEUP;
259 }
248 } else { 260 } else {
249 if (desc->wake_depth == 0) { 261 if (desc->wake_depth == 0) {
250 printk(KERN_WARNING "Unbalanced IRQ %d " 262 WARN(1, "Unbalanced IRQ %d wake disable\n", irq);
251 "wake disable\n", irq); 263 } else if (--desc->wake_depth == 0) {
252 WARN_ON(1); 264 ret = set_irq_wake_real(irq, on);
253 } else if (--desc->wake_depth == 0) 265 if (ret)
254 desc->status &= ~IRQ_WAKEUP; 266 desc->wake_depth = 1;
255 else 267 else
256 set_wake = NULL; 268 desc->status &= ~IRQ_WAKEUP;
269 }
257 } 270 }
258 if (set_wake) 271
259 ret = desc->chip->set_wake(irq, on);
260 spin_unlock_irqrestore(&desc->lock, flags); 272 spin_unlock_irqrestore(&desc->lock, flags);
261 return ret; 273 return ret;
262} 274}
@@ -293,6 +305,30 @@ void compat_irq_chip_set_default_handler(struct irq_desc *desc)
293 desc->handle_irq = NULL; 305 desc->handle_irq = NULL;
294} 306}
295 307
308static int __irq_set_trigger(struct irq_chip *chip, unsigned int irq,
309 unsigned long flags)
310{
311 int ret;
312
313 if (!chip || !chip->set_type) {
314 /*
315 * IRQF_TRIGGER_* but the PIC does not support multiple
316 * flow-types?
317 */
318 pr_warning("No set_type function for IRQ %d (%s)\n", irq,
319 chip ? (chip->name ? : "unknown") : "unknown");
320 return 0;
321 }
322
323 ret = chip->set_type(irq, flags & IRQF_TRIGGER_MASK);
324
325 if (ret)
326 pr_err("setting flow type for irq %u failed (%pF)\n",
327 irq, chip->set_type);
328
329 return ret;
330}
331
296/* 332/*
297 * Internal function to register an irqaction - typically used to 333 * Internal function to register an irqaction - typically used to
298 * allocate special interrupts that are part of the architecture. 334 * allocate special interrupts that are part of the architecture.
@@ -304,6 +340,7 @@ int setup_irq(unsigned int irq, struct irqaction *new)
304 const char *old_name = NULL; 340 const char *old_name = NULL;
305 unsigned long flags; 341 unsigned long flags;
306 int shared = 0; 342 int shared = 0;
343 int ret;
307 344
308 if (irq >= NR_IRQS) 345 if (irq >= NR_IRQS)
309 return -EINVAL; 346 return -EINVAL;
@@ -361,35 +398,23 @@ int setup_irq(unsigned int irq, struct irqaction *new)
361 shared = 1; 398 shared = 1;
362 } 399 }
363 400
364 *p = new;
365
366 /* Exclude IRQ from balancing */
367 if (new->flags & IRQF_NOBALANCING)
368 desc->status |= IRQ_NO_BALANCING;
369
370 if (!shared) { 401 if (!shared) {
371 irq_chip_set_defaults(desc->chip); 402 irq_chip_set_defaults(desc->chip);
372 403
373#if defined(CONFIG_IRQ_PER_CPU)
374 if (new->flags & IRQF_PERCPU)
375 desc->status |= IRQ_PER_CPU;
376#endif
377
378 /* Setup the type (level, edge polarity) if configured: */ 404 /* Setup the type (level, edge polarity) if configured: */
379 if (new->flags & IRQF_TRIGGER_MASK) { 405 if (new->flags & IRQF_TRIGGER_MASK) {
380 if (desc->chip->set_type) 406 ret = __irq_set_trigger(desc->chip, irq, new->flags);
381 desc->chip->set_type(irq, 407
382 new->flags & IRQF_TRIGGER_MASK); 408 if (ret) {
383 else 409 spin_unlock_irqrestore(&desc->lock, flags);
384 /* 410 return ret;
385 * IRQF_TRIGGER_* but the PIC does not support 411 }
386 * multiple flow-types?
387 */
388 printk(KERN_WARNING "No IRQF_TRIGGER set_type "
389 "function for IRQ %d (%s)\n", irq,
390 desc->chip->name);
391 } else 412 } else
392 compat_irq_chip_set_default_handler(desc); 413 compat_irq_chip_set_default_handler(desc);
414#if defined(CONFIG_IRQ_PER_CPU)
415 if (new->flags & IRQF_PERCPU)
416 desc->status |= IRQ_PER_CPU;
417#endif
393 418
394 desc->status &= ~(IRQ_AUTODETECT | IRQ_WAITING | 419 desc->status &= ~(IRQ_AUTODETECT | IRQ_WAITING |
395 IRQ_INPROGRESS | IRQ_SPURIOUS_DISABLED); 420 IRQ_INPROGRESS | IRQ_SPURIOUS_DISABLED);
@@ -408,6 +433,13 @@ int setup_irq(unsigned int irq, struct irqaction *new)
408 /* Set default affinity mask once everything is setup */ 433 /* Set default affinity mask once everything is setup */
409 irq_select_affinity(irq); 434 irq_select_affinity(irq);
410 } 435 }
436
437 *p = new;
438
439 /* Exclude IRQ from balancing */
440 if (new->flags & IRQF_NOBALANCING)
441 desc->status |= IRQ_NO_BALANCING;
442
411 /* Reset broken irq detection when installing new handler */ 443 /* Reset broken irq detection when installing new handler */
412 desc->irq_count = 0; 444 desc->irq_count = 0;
413 desc->irqs_unhandled = 0; 445 desc->irqs_unhandled = 0;