aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/irq/manage.c
diff options
context:
space:
mode:
Diffstat (limited to 'kernel/irq/manage.c')
-rw-r--r--kernel/irq/manage.c123
1 files changed, 80 insertions, 43 deletions
diff --git a/kernel/irq/manage.c b/kernel/irq/manage.c
index 60c49e324390..c498a1b8c621 100644
--- a/kernel/irq/manage.c
+++ b/kernel/irq/manage.c
@@ -31,10 +31,10 @@ cpumask_t irq_default_affinity = CPU_MASK_ALL;
31 */ 31 */
32void synchronize_irq(unsigned int irq) 32void synchronize_irq(unsigned int irq)
33{ 33{
34 struct irq_desc *desc = irq_desc + irq; 34 struct irq_desc *desc = irq_to_desc(irq);
35 unsigned int status; 35 unsigned int status;
36 36
37 if (irq >= NR_IRQS) 37 if (!desc)
38 return; 38 return;
39 39
40 do { 40 do {
@@ -64,7 +64,7 @@ EXPORT_SYMBOL(synchronize_irq);
64 */ 64 */
65int irq_can_set_affinity(unsigned int irq) 65int irq_can_set_affinity(unsigned int irq)
66{ 66{
67 struct irq_desc *desc = irq_desc + irq; 67 struct irq_desc *desc = irq_to_desc(irq);
68 68
69 if (CHECK_IRQ_PER_CPU(desc->status) || !desc->chip || 69 if (CHECK_IRQ_PER_CPU(desc->status) || !desc->chip ||
70 !desc->chip->set_affinity) 70 !desc->chip->set_affinity)
@@ -81,18 +81,17 @@ int irq_can_set_affinity(unsigned int irq)
81 */ 81 */
82int irq_set_affinity(unsigned int irq, cpumask_t cpumask) 82int irq_set_affinity(unsigned int irq, cpumask_t cpumask)
83{ 83{
84 struct irq_desc *desc = irq_desc + irq; 84 struct irq_desc *desc = irq_to_desc(irq);
85 85
86 if (!desc->chip->set_affinity) 86 if (!desc->chip->set_affinity)
87 return -EINVAL; 87 return -EINVAL;
88 88
89 set_balance_irq_affinity(irq, cpumask);
90
91#ifdef CONFIG_GENERIC_PENDING_IRQ 89#ifdef CONFIG_GENERIC_PENDING_IRQ
92 if (desc->status & IRQ_MOVE_PCNTXT) { 90 if (desc->status & IRQ_MOVE_PCNTXT || desc->status & IRQ_DISABLED) {
93 unsigned long flags; 91 unsigned long flags;
94 92
95 spin_lock_irqsave(&desc->lock, flags); 93 spin_lock_irqsave(&desc->lock, flags);
94 desc->affinity = cpumask;
96 desc->chip->set_affinity(irq, cpumask); 95 desc->chip->set_affinity(irq, cpumask);
97 spin_unlock_irqrestore(&desc->lock, flags); 96 spin_unlock_irqrestore(&desc->lock, flags);
98 } else 97 } else
@@ -111,16 +110,17 @@ int irq_set_affinity(unsigned int irq, cpumask_t cpumask)
111int irq_select_affinity(unsigned int irq) 110int irq_select_affinity(unsigned int irq)
112{ 111{
113 cpumask_t mask; 112 cpumask_t mask;
113 struct irq_desc *desc;
114 114
115 if (!irq_can_set_affinity(irq)) 115 if (!irq_can_set_affinity(irq))
116 return 0; 116 return 0;
117 117
118 cpus_and(mask, cpu_online_map, irq_default_affinity); 118 cpus_and(mask, cpu_online_map, irq_default_affinity);
119 119
120 irq_desc[irq].affinity = mask; 120 desc = irq_to_desc(irq);
121 irq_desc[irq].chip->set_affinity(irq, mask); 121 desc->affinity = mask;
122 desc->chip->set_affinity(irq, mask);
122 123
123 set_balance_irq_affinity(irq, mask);
124 return 0; 124 return 0;
125} 125}
126#endif 126#endif
@@ -140,10 +140,10 @@ int irq_select_affinity(unsigned int irq)
140 */ 140 */
141void disable_irq_nosync(unsigned int irq) 141void disable_irq_nosync(unsigned int irq)
142{ 142{
143 struct irq_desc *desc = irq_desc + irq; 143 struct irq_desc *desc = irq_to_desc(irq);
144 unsigned long flags; 144 unsigned long flags;
145 145
146 if (irq >= NR_IRQS) 146 if (!desc)
147 return; 147 return;
148 148
149 spin_lock_irqsave(&desc->lock, flags); 149 spin_lock_irqsave(&desc->lock, flags);
@@ -169,9 +169,9 @@ EXPORT_SYMBOL(disable_irq_nosync);
169 */ 169 */
170void disable_irq(unsigned int irq) 170void disable_irq(unsigned int irq)
171{ 171{
172 struct irq_desc *desc = irq_desc + irq; 172 struct irq_desc *desc = irq_to_desc(irq);
173 173
174 if (irq >= NR_IRQS) 174 if (!desc)
175 return; 175 return;
176 176
177 disable_irq_nosync(irq); 177 disable_irq_nosync(irq);
@@ -211,10 +211,10 @@ static void __enable_irq(struct irq_desc *desc, unsigned int irq)
211 */ 211 */
212void enable_irq(unsigned int irq) 212void enable_irq(unsigned int irq)
213{ 213{
214 struct irq_desc *desc = irq_desc + irq; 214 struct irq_desc *desc = irq_to_desc(irq);
215 unsigned long flags; 215 unsigned long flags;
216 216
217 if (irq >= NR_IRQS) 217 if (!desc)
218 return; 218 return;
219 219
220 spin_lock_irqsave(&desc->lock, flags); 220 spin_lock_irqsave(&desc->lock, flags);
@@ -223,9 +223,9 @@ void enable_irq(unsigned int irq)
223} 223}
224EXPORT_SYMBOL(enable_irq); 224EXPORT_SYMBOL(enable_irq);
225 225
226int set_irq_wake_real(unsigned int irq, unsigned int on) 226static int set_irq_wake_real(unsigned int irq, unsigned int on)
227{ 227{
228 struct irq_desc *desc = irq_desc + irq; 228 struct irq_desc *desc = irq_to_desc(irq);
229 int ret = -ENXIO; 229 int ret = -ENXIO;
230 230
231 if (desc->chip->set_wake) 231 if (desc->chip->set_wake)
@@ -248,7 +248,7 @@ int set_irq_wake_real(unsigned int irq, unsigned int on)
248 */ 248 */
249int set_irq_wake(unsigned int irq, unsigned int on) 249int set_irq_wake(unsigned int irq, unsigned int on)
250{ 250{
251 struct irq_desc *desc = irq_desc + irq; 251 struct irq_desc *desc = irq_to_desc(irq);
252 unsigned long flags; 252 unsigned long flags;
253 int ret = 0; 253 int ret = 0;
254 254
@@ -288,12 +288,16 @@ EXPORT_SYMBOL(set_irq_wake);
288 */ 288 */
289int can_request_irq(unsigned int irq, unsigned long irqflags) 289int can_request_irq(unsigned int irq, unsigned long irqflags)
290{ 290{
291 struct irq_desc *desc = irq_to_desc(irq);
291 struct irqaction *action; 292 struct irqaction *action;
292 293
293 if (irq >= NR_IRQS || irq_desc[irq].status & IRQ_NOREQUEST) 294 if (!desc)
295 return 0;
296
297 if (desc->status & IRQ_NOREQUEST)
294 return 0; 298 return 0;
295 299
296 action = irq_desc[irq].action; 300 action = desc->action;
297 if (action) 301 if (action)
298 if (irqflags & action->flags & IRQF_SHARED) 302 if (irqflags & action->flags & IRQF_SHARED)
299 action = NULL; 303 action = NULL;
@@ -312,10 +316,11 @@ void compat_irq_chip_set_default_handler(struct irq_desc *desc)
312 desc->handle_irq = NULL; 316 desc->handle_irq = NULL;
313} 317}
314 318
315static int __irq_set_trigger(struct irq_chip *chip, unsigned int irq, 319int __irq_set_trigger(struct irq_desc *desc, unsigned int irq,
316 unsigned long flags) 320 unsigned long flags)
317{ 321{
318 int ret; 322 int ret;
323 struct irq_chip *chip = desc->chip;
319 324
320 if (!chip || !chip->set_type) { 325 if (!chip || !chip->set_type) {
321 /* 326 /*
@@ -333,6 +338,11 @@ static int __irq_set_trigger(struct irq_chip *chip, unsigned int irq,
333 pr_err("setting trigger mode %d for irq %u failed (%pF)\n", 338 pr_err("setting trigger mode %d for irq %u failed (%pF)\n",
334 (int)(flags & IRQF_TRIGGER_MASK), 339 (int)(flags & IRQF_TRIGGER_MASK),
335 irq, chip->set_type); 340 irq, chip->set_type);
341 else {
342 /* note that IRQF_TRIGGER_MASK == IRQ_TYPE_SENSE_MASK */
343 desc->status &= ~IRQ_TYPE_SENSE_MASK;
344 desc->status |= flags & IRQ_TYPE_SENSE_MASK;
345 }
336 346
337 return ret; 347 return ret;
338} 348}
@@ -341,16 +351,16 @@ static int __irq_set_trigger(struct irq_chip *chip, unsigned int irq,
341 * Internal function to register an irqaction - typically used to 351 * Internal function to register an irqaction - typically used to
342 * allocate special interrupts that are part of the architecture. 352 * allocate special interrupts that are part of the architecture.
343 */ 353 */
344int setup_irq(unsigned int irq, struct irqaction *new) 354static int
355__setup_irq(unsigned int irq, struct irq_desc * desc, struct irqaction *new)
345{ 356{
346 struct irq_desc *desc = irq_desc + irq;
347 struct irqaction *old, **p; 357 struct irqaction *old, **p;
348 const char *old_name = NULL; 358 const char *old_name = NULL;
349 unsigned long flags; 359 unsigned long flags;
350 int shared = 0; 360 int shared = 0;
351 int ret; 361 int ret;
352 362
353 if (irq >= NR_IRQS) 363 if (!desc)
354 return -EINVAL; 364 return -EINVAL;
355 365
356 if (desc->chip == &no_irq_chip) 366 if (desc->chip == &no_irq_chip)
@@ -411,7 +421,7 @@ int setup_irq(unsigned int irq, struct irqaction *new)
411 421
412 /* Setup the type (level, edge polarity) if configured: */ 422 /* Setup the type (level, edge polarity) if configured: */
413 if (new->flags & IRQF_TRIGGER_MASK) { 423 if (new->flags & IRQF_TRIGGER_MASK) {
414 ret = __irq_set_trigger(desc->chip, irq, new->flags); 424 ret = __irq_set_trigger(desc, irq, new->flags);
415 425
416 if (ret) { 426 if (ret) {
417 spin_unlock_irqrestore(&desc->lock, flags); 427 spin_unlock_irqrestore(&desc->lock, flags);
@@ -430,16 +440,21 @@ int setup_irq(unsigned int irq, struct irqaction *new)
430 if (!(desc->status & IRQ_NOAUTOEN)) { 440 if (!(desc->status & IRQ_NOAUTOEN)) {
431 desc->depth = 0; 441 desc->depth = 0;
432 desc->status &= ~IRQ_DISABLED; 442 desc->status &= ~IRQ_DISABLED;
433 if (desc->chip->startup) 443 desc->chip->startup(irq);
434 desc->chip->startup(irq);
435 else
436 desc->chip->enable(irq);
437 } else 444 } else
438 /* Undo nested disables: */ 445 /* Undo nested disables: */
439 desc->depth = 1; 446 desc->depth = 1;
440 447
441 /* Set default affinity mask once everything is setup */ 448 /* Set default affinity mask once everything is setup */
442 irq_select_affinity(irq); 449 irq_select_affinity(irq);
450
451 } else if ((new->flags & IRQF_TRIGGER_MASK)
452 && (new->flags & IRQF_TRIGGER_MASK)
453 != (desc->status & IRQ_TYPE_SENSE_MASK)) {
454 /* hope the handler works with the actual trigger mode... */
455 pr_warning("IRQ %d uses trigger mode %d; requested %d\n",
456 irq, (int)(desc->status & IRQ_TYPE_SENSE_MASK),
457 (int)(new->flags & IRQF_TRIGGER_MASK));
443 } 458 }
444 459
445 *p = new; 460 *p = new;
@@ -464,7 +479,7 @@ int setup_irq(unsigned int irq, struct irqaction *new)
464 spin_unlock_irqrestore(&desc->lock, flags); 479 spin_unlock_irqrestore(&desc->lock, flags);
465 480
466 new->irq = irq; 481 new->irq = irq;
467 register_irq_proc(irq); 482 register_irq_proc(irq, desc);
468 new->dir = NULL; 483 new->dir = NULL;
469 register_handler_proc(irq, new); 484 register_handler_proc(irq, new);
470 485
@@ -484,6 +499,20 @@ mismatch:
484} 499}
485 500
486/** 501/**
502 * setup_irq - setup an interrupt
503 * @irq: Interrupt line to setup
504 * @act: irqaction for the interrupt
505 *
506 * Used to statically setup interrupts in the early boot process.
507 */
508int setup_irq(unsigned int irq, struct irqaction *act)
509{
510 struct irq_desc *desc = irq_to_desc(irq);
511
512 return __setup_irq(irq, desc, act);
513}
514
515/**
487 * free_irq - free an interrupt 516 * free_irq - free an interrupt
488 * @irq: Interrupt line to free 517 * @irq: Interrupt line to free
489 * @dev_id: Device identity to free 518 * @dev_id: Device identity to free
@@ -499,15 +528,15 @@ mismatch:
499 */ 528 */
500void free_irq(unsigned int irq, void *dev_id) 529void free_irq(unsigned int irq, void *dev_id)
501{ 530{
502 struct irq_desc *desc; 531 struct irq_desc *desc = irq_to_desc(irq);
503 struct irqaction **p; 532 struct irqaction **p;
504 unsigned long flags; 533 unsigned long flags;
505 534
506 WARN_ON(in_interrupt()); 535 WARN_ON(in_interrupt());
507 if (irq >= NR_IRQS) 536
537 if (!desc)
508 return; 538 return;
509 539
510 desc = irq_desc + irq;
511 spin_lock_irqsave(&desc->lock, flags); 540 spin_lock_irqsave(&desc->lock, flags);
512 p = &desc->action; 541 p = &desc->action;
513 for (;;) { 542 for (;;) {
@@ -596,12 +625,14 @@ EXPORT_SYMBOL(free_irq);
596 * IRQF_SHARED Interrupt is shared 625 * IRQF_SHARED Interrupt is shared
597 * IRQF_DISABLED Disable local interrupts while processing 626 * IRQF_DISABLED Disable local interrupts while processing
598 * IRQF_SAMPLE_RANDOM The interrupt can be used for entropy 627 * IRQF_SAMPLE_RANDOM The interrupt can be used for entropy
628 * IRQF_TRIGGER_* Specify active edge(s) or level
599 * 629 *
600 */ 630 */
601int request_irq(unsigned int irq, irq_handler_t handler, 631int request_irq(unsigned int irq, irq_handler_t handler,
602 unsigned long irqflags, const char *devname, void *dev_id) 632 unsigned long irqflags, const char *devname, void *dev_id)
603{ 633{
604 struct irqaction *action; 634 struct irqaction *action;
635 struct irq_desc *desc;
605 int retval; 636 int retval;
606 637
607#ifdef CONFIG_LOCKDEP 638#ifdef CONFIG_LOCKDEP
@@ -618,9 +649,12 @@ int request_irq(unsigned int irq, irq_handler_t handler,
618 */ 649 */
619 if ((irqflags & IRQF_SHARED) && !dev_id) 650 if ((irqflags & IRQF_SHARED) && !dev_id)
620 return -EINVAL; 651 return -EINVAL;
621 if (irq >= NR_IRQS) 652
653 desc = irq_to_desc(irq);
654 if (!desc)
622 return -EINVAL; 655 return -EINVAL;
623 if (irq_desc[irq].status & IRQ_NOREQUEST) 656
657 if (desc->status & IRQ_NOREQUEST)
624 return -EINVAL; 658 return -EINVAL;
625 if (!handler) 659 if (!handler)
626 return -EINVAL; 660 return -EINVAL;
@@ -636,26 +670,29 @@ int request_irq(unsigned int irq, irq_handler_t handler,
636 action->next = NULL; 670 action->next = NULL;
637 action->dev_id = dev_id; 671 action->dev_id = dev_id;
638 672
673 retval = __setup_irq(irq, desc, action);
674 if (retval)
675 kfree(action);
676
639#ifdef CONFIG_DEBUG_SHIRQ 677#ifdef CONFIG_DEBUG_SHIRQ
640 if (irqflags & IRQF_SHARED) { 678 if (irqflags & IRQF_SHARED) {
641 /* 679 /*
642 * It's a shared IRQ -- the driver ought to be prepared for it 680 * It's a shared IRQ -- the driver ought to be prepared for it
643 * to happen immediately, so let's make sure.... 681 * to happen immediately, so let's make sure....
644 * We do this before actually registering it, to make sure that 682 * We disable the irq to make sure that a 'real' IRQ doesn't
645 * a 'real' IRQ doesn't run in parallel with our fake 683 * run in parallel with our fake.
646 */ 684 */
647 unsigned long flags; 685 unsigned long flags;
648 686
687 disable_irq(irq);
649 local_irq_save(flags); 688 local_irq_save(flags);
689
650 handler(irq, dev_id); 690 handler(irq, dev_id);
691
651 local_irq_restore(flags); 692 local_irq_restore(flags);
693 enable_irq(irq);
652 } 694 }
653#endif 695#endif
654
655 retval = setup_irq(irq, action);
656 if (retval)
657 kfree(action);
658
659 return retval; 696 return retval;
660} 697}
661EXPORT_SYMBOL(request_irq); 698EXPORT_SYMBOL(request_irq);