1
2
3
4
5
6
7
8
9
10#include <linux/irq.h>
11#include <linux/module.h>
12#include <linux/random.h>
13#include <linux/interrupt.h>
14#include <linux/slab.h>
15
16#include "internals.h"
17
18#ifdef CONFIG_SMP
19
20cpumask_t irq_default_affinity = CPU_MASK_ALL;
21
22
23
24
25
26
27
28
29
30
31
32void synchronize_irq(unsigned int irq)
33{
34 struct irq_desc *desc = irq_desc + irq;
35 unsigned int status;
36
37 if (irq >= NR_IRQS)
38 return;
39
40 do {
41 unsigned long flags;
42
43
44
45
46
47 while (desc->status & IRQ_INPROGRESS)
48 cpu_relax();
49
50
51 spin_lock_irqsave(&desc->lock, flags);
52 status = desc->status;
53 spin_unlock_irqrestore(&desc->lock, flags);
54
55
56 } while (status & IRQ_INPROGRESS);
57}
58EXPORT_SYMBOL(synchronize_irq);
59
60
61
62
63
64
65int irq_can_set_affinity(unsigned int irq)
66{
67 struct irq_desc *desc = irq_desc + irq;
68
69 if (CHECK_IRQ_PER_CPU(desc->status) || !desc->chip ||
70 !desc->chip->set_affinity)
71 return 0;
72
73 return 1;
74}
75
76
77
78
79
80
81
82int irq_set_affinity(unsigned int irq, cpumask_t cpumask)
83{
84 struct irq_desc *desc = irq_desc + irq;
85
86 if (!desc->chip->set_affinity)
87 return -EINVAL;
88
89 set_balance_irq_affinity(irq, cpumask);
90
91#ifdef CONFIG_GENERIC_PENDING_IRQ
92 set_pending_irq(irq, cpumask);
93#else
94 desc->affinity = cpumask;
95 desc->chip->set_affinity(irq, cpumask);
96#endif
97 return 0;
98}
99
100#ifndef CONFIG_AUTO_IRQ_AFFINITY
101
102
103
104int irq_select_affinity(unsigned int irq)
105{
106 cpumask_t mask;
107
108 if (!irq_can_set_affinity(irq))
109 return 0;
110
111 cpus_and(mask, cpu_online_map, irq_default_affinity);
112
113 irq_desc[irq].affinity = mask;
114 irq_desc[irq].chip->set_affinity(irq, mask);
115
116 set_balance_irq_affinity(irq, mask);
117 return 0;
118}
119#endif
120
121#endif
122
123
124
125
126
127
128
129
130
131
132
133
134void disable_irq_nosync(unsigned int irq)
135{
136 struct irq_desc *desc = irq_desc + irq;
137 unsigned long flags;
138
139 if (irq >= NR_IRQS)
140 return;
141
142 spin_lock_irqsave(&desc->lock, flags);
143 if (!desc->depth++) {
144 desc->status |= IRQ_DISABLED;
145 desc->chip->disable(irq);
146 }
147 spin_unlock_irqrestore(&desc->lock, flags);
148}
149EXPORT_SYMBOL(disable_irq_nosync);
150
151
152
153
154
155
156
157
158
159
160
161
162
163void disable_irq(unsigned int irq)
164{
165 struct irq_desc *desc = irq_desc + irq;
166
167 if (irq >= NR_IRQS)
168 return;
169
170 disable_irq_nosync(irq);
171 if (desc->action)
172 synchronize_irq(irq);
173}
174EXPORT_SYMBOL(disable_irq);
175
176static void __enable_irq(struct irq_desc *desc, unsigned int irq)
177{
178 switch (desc->depth) {
179 case 0:
180 WARN(1, KERN_WARNING "Unbalanced enable for IRQ %d\n", irq);
181 break;
182 case 1: {
183 unsigned int status = desc->status & ~IRQ_DISABLED;
184
185
186 desc->status = status | IRQ_NOPROBE;
187 check_irq_resend(desc, irq);
188
189 }
190 default:
191 desc->depth--;
192 }
193}
194
195
196
197
198
199
200
201
202
203
204
205void enable_irq(unsigned int irq)
206{
207 struct irq_desc *desc = irq_desc + irq;
208 unsigned long flags;
209
210 if (irq >= NR_IRQS)
211 return;
212
213 spin_lock_irqsave(&desc->lock, flags);
214 __enable_irq(desc, irq);
215 spin_unlock_irqrestore(&desc->lock, flags);
216}
217EXPORT_SYMBOL(enable_irq);
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
230
231
232
233
234
235
236
237
238
239
240
241
242int set_irq_wake(unsigned int irq, unsigned int on)
243{
244 struct irq_desc *desc = irq_desc + irq;
245 unsigned long flags;
246 int ret = 0;
247
248
249
250
251 spin_lock_irqsave(&desc->lock, flags);
252 if (on) {
253 if (desc->wake_depth++ == 0) {
254 ret = set_irq_wake_real(irq, on);
255 if (ret)
256 desc->wake_depth = 0;
257 else
258 desc->status |= IRQ_WAKEUP;
259 }
260 } else {
261 if (desc->wake_depth == 0) {
262 WARN(1, "Unbalanced IRQ %d wake disable\n", irq);
263 } else if (--desc->wake_depth == 0) {
264 ret = set_irq_wake_real(irq, on);
265 if (ret)
266 desc->wake_depth = 1;
267 else
268 desc->status &= ~IRQ_WAKEUP;
269 }
270 }
271
272 spin_unlock_irqrestore(&desc->lock, flags);
273 return ret;
274}
275EXPORT_SYMBOL(set_irq_wake);
276
277
278
279
280
281
282int can_request_irq(unsigned int irq, unsigned long irqflags)
283{
284 struct irqaction *action;
285
286 if (irq >= NR_IRQS || irq_desc[irq].status & IRQ_NOREQUEST)
287 return 0;
288
289 action = irq_desc[irq].action;
290 if (action)
291 if (irqflags & action->flags & IRQF_SHARED)
292 action = NULL;
293
294 return !action;
295}
296
297void compat_irq_chip_set_default_handler(struct irq_desc *desc)
298{
299
300
301
302
303
304 if (desc->handle_irq == &handle_bad_irq)
305 desc->handle_irq = NULL;
306}
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
316
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 trigger mode %d for irq %u failed (%pF)\n",
327 (int)(flags & IRQF_TRIGGER_MASK),
328 irq, chip->set_type);
329
330 return ret;
331}
332
333
334
335
336
337int setup_irq(unsigned int irq, struct irqaction *new)
338{
339 struct irq_desc *desc = irq_desc + irq;
340 struct irqaction *old, **p;
341 const char *old_name = NULL;
342 unsigned long flags;
343 int shared = 0;
344 int ret;
345
346 if (irq >= NR_IRQS)
347 return -EINVAL;
348
349 if (desc->chip == &no_irq_chip)
350 return -ENOSYS;
351
352
353
354
355
356 if (new->flags & IRQF_SAMPLE_RANDOM) {
357
358
359
360
361
362
363
364
365 rand_initialize_irq(irq);
366 }
367
368
369
370
371 spin_lock_irqsave(&desc->lock, flags);
372 p = &desc->action;
373 old = *p;
374 if (old) {
375
376
377
378
379
380
381 if (!((old->flags & new->flags) & IRQF_SHARED) ||
382 ((old->flags ^ new->flags) & IRQF_TRIGGER_MASK)) {
383 old_name = old->name;
384 goto mismatch;
385 }
386
387#if defined(CONFIG_IRQ_PER_CPU)
388
389 if ((old->flags & IRQF_PERCPU) !=
390 (new->flags & IRQF_PERCPU))
391 goto mismatch;
392#endif
393
394
395 do {
396 p = &old->next;
397 old = *p;
398 } while (old);
399 shared = 1;
400 }
401
402 if (!shared) {
403 irq_chip_set_defaults(desc->chip);
404
405
406 if (new->flags & IRQF_TRIGGER_MASK) {
407 ret = __irq_set_trigger(desc->chip, irq, new->flags);
408
409 if (ret) {
410 spin_unlock_irqrestore(&desc->lock, flags);
411 return ret;
412 }
413 } else
414 compat_irq_chip_set_default_handler(desc);
415#if defined(CONFIG_IRQ_PER_CPU)
416 if (new->flags & IRQF_PERCPU)
417 desc->status |= IRQ_PER_CPU;
418#endif
419
420 desc->status &= ~(IRQ_AUTODETECT | IRQ_WAITING |
421 IRQ_INPROGRESS | IRQ_SPURIOUS_DISABLED);
422
423 if (!(desc->status & IRQ_NOAUTOEN)) {
424 desc->depth = 0;
425 desc->status &= ~IRQ_DISABLED;
426 if (desc->chip->startup)
427 desc->chip->startup(irq);
428 else
429 desc->chip->enable(irq);
430 } else
431
432 desc->depth = 1;
433
434
435 irq_select_affinity(irq);
436 }
437
438 *p = new;
439
440
441 if (new->flags & IRQF_NOBALANCING)
442 desc->status |= IRQ_NO_BALANCING;
443
444
445 desc->irq_count = 0;
446 desc->irqs_unhandled = 0;
447
448
449
450
451
452 if (shared && (desc->status & IRQ_SPURIOUS_DISABLED)) {
453 desc->status &= ~IRQ_SPURIOUS_DISABLED;
454 __enable_irq(desc, irq);
455 }
456
457 spin_unlock_irqrestore(&desc->lock, flags);
458
459 new->irq = irq;
460 register_irq_proc(irq);
461 new->dir = NULL;
462 register_handler_proc(irq, new);
463
464 return 0;
465
466mismatch:
467#ifdef CONFIG_DEBUG_SHIRQ
468 if (!(new->flags & IRQF_PROBE_SHARED)) {
469 printk(KERN_ERR "IRQ handler type mismatch for IRQ %d\n", irq);
470 if (old_name)
471 printk(KERN_ERR "current handler: %s\n", old_name);
472 dump_stack();
473 }
474#endif
475 spin_unlock_irqrestore(&desc->lock, flags);
476 return -EBUSY;
477}
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493void free_irq(unsigned int irq, void *dev_id)
494{
495 struct irq_desc *desc;
496 struct irqaction **p;
497 unsigned long flags;
498
499 WARN_ON(in_interrupt());
500 if (irq >= NR_IRQS)
501 return;
502
503 desc = irq_desc + irq;
504 spin_lock_irqsave(&desc->lock, flags);
505 p = &desc->action;
506 for (;;) {
507 struct irqaction *action = *p;
508
509 if (action) {
510 struct irqaction **pp = p;
511
512 p = &action->next;
513 if (action->dev_id != dev_id)
514 continue;
515
516
517 *pp = action->next;
518
519
520#ifdef CONFIG_IRQ_RELEASE_METHOD
521 if (desc->chip->release)
522 desc->chip->release(irq, dev_id);
523#endif
524
525 if (!desc->action) {
526 desc->status |= IRQ_DISABLED;
527 if (desc->chip->shutdown)
528 desc->chip->shutdown(irq);
529 else
530 desc->chip->disable(irq);
531 }
532 spin_unlock_irqrestore(&desc->lock, flags);
533 unregister_handler_proc(irq, action);
534
535
536 synchronize_irq(irq);
537#ifdef CONFIG_DEBUG_SHIRQ
538
539
540
541
542
543
544
545
546 if (action->flags & IRQF_SHARED) {
547 local_irq_save(flags);
548 action->handler(irq, dev_id);
549 local_irq_restore(flags);
550 }
551#endif
552 kfree(action);
553 return;
554 }
555 printk(KERN_ERR "Trying to free already-free IRQ %d\n", irq);
556#ifdef CONFIG_DEBUG_SHIRQ
557 dump_stack();
558#endif
559 spin_unlock_irqrestore(&desc->lock, flags);
560 return;
561 }
562}
563EXPORT_SYMBOL(free_irq);
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594int request_irq(unsigned int irq, irq_handler_t handler,
595 unsigned long irqflags, const char *devname, void *dev_id)
596{
597 struct irqaction *action;
598 int retval;
599
600#ifdef CONFIG_LOCKDEP
601
602
603
604 irqflags |= IRQF_DISABLED;
605#endif
606
607
608
609
610
611
612 if ((irqflags & IRQF_SHARED) && !dev_id)
613 return -EINVAL;
614 if (irq >= NR_IRQS)
615 return -EINVAL;
616 if (irq_desc[irq].status & IRQ_NOREQUEST)
617 return -EINVAL;
618 if (!handler)
619 return -EINVAL;
620
621 action = kmalloc(sizeof(struct irqaction), GFP_ATOMIC);
622 if (!action)
623 return -ENOMEM;
624
625 action->handler = handler;
626 action->flags = irqflags;
627 cpus_clear(action->mask);
628 action->name = devname;
629 action->next = NULL;
630 action->dev_id = dev_id;
631
632#ifdef CONFIG_DEBUG_SHIRQ_FIXME
633 if (irqflags & IRQF_SHARED) {
634
635
636
637
638
639
640 unsigned long flags;
641
642 local_irq_save(flags);
643 handler(irq, dev_id);
644 local_irq_restore(flags);
645 }
646#endif
647
648 retval = setup_irq(irq, action);
649 if (retval)
650 kfree(action);
651
652 return retval;
653}
654EXPORT_SYMBOL(request_irq);
655