aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/irq/chip.c
diff options
context:
space:
mode:
Diffstat (limited to 'kernel/irq/chip.c')
-rw-r--r--kernel/irq/chip.c102
1 files changed, 46 insertions, 56 deletions
diff --git a/kernel/irq/chip.c b/kernel/irq/chip.c
index 3cd441ebf5d2..10b5092e9bfe 100644
--- a/kernel/irq/chip.c
+++ b/kernel/irq/chip.c
@@ -24,16 +24,15 @@
24 */ 24 */
25void dynamic_irq_init(unsigned int irq) 25void dynamic_irq_init(unsigned int irq)
26{ 26{
27 struct irq_desc *desc; 27 struct irq_desc *desc = irq_to_desc(irq);
28 unsigned long flags; 28 unsigned long flags;
29 29
30 if (irq >= NR_IRQS) { 30 if (!desc) {
31 WARN(1, KERN_ERR "Trying to initialize invalid IRQ%d\n", irq); 31 WARN(1, KERN_ERR "Trying to initialize invalid IRQ%d\n", irq);
32 return; 32 return;
33 } 33 }
34 34
35 /* Ensure we don't have left over values from a previous use of this irq */ 35 /* Ensure we don't have left over values from a previous use of this irq */
36 desc = irq_desc + irq;
37 spin_lock_irqsave(&desc->lock, flags); 36 spin_lock_irqsave(&desc->lock, flags);
38 desc->status = IRQ_DISABLED; 37 desc->status = IRQ_DISABLED;
39 desc->chip = &no_irq_chip; 38 desc->chip = &no_irq_chip;
@@ -57,15 +56,14 @@ void dynamic_irq_init(unsigned int irq)
57 */ 56 */
58void dynamic_irq_cleanup(unsigned int irq) 57void dynamic_irq_cleanup(unsigned int irq)
59{ 58{
60 struct irq_desc *desc; 59 struct irq_desc *desc = irq_to_desc(irq);
61 unsigned long flags; 60 unsigned long flags;
62 61
63 if (irq >= NR_IRQS) { 62 if (!desc) {
64 WARN(1, KERN_ERR "Trying to cleanup invalid IRQ%d\n", irq); 63 WARN(1, KERN_ERR "Trying to cleanup invalid IRQ%d\n", irq);
65 return; 64 return;
66 } 65 }
67 66
68 desc = irq_desc + irq;
69 spin_lock_irqsave(&desc->lock, flags); 67 spin_lock_irqsave(&desc->lock, flags);
70 if (desc->action) { 68 if (desc->action) {
71 spin_unlock_irqrestore(&desc->lock, flags); 69 spin_unlock_irqrestore(&desc->lock, flags);
@@ -78,6 +76,7 @@ void dynamic_irq_cleanup(unsigned int irq)
78 desc->chip_data = NULL; 76 desc->chip_data = NULL;
79 desc->handle_irq = handle_bad_irq; 77 desc->handle_irq = handle_bad_irq;
80 desc->chip = &no_irq_chip; 78 desc->chip = &no_irq_chip;
79 desc->name = NULL;
81 spin_unlock_irqrestore(&desc->lock, flags); 80 spin_unlock_irqrestore(&desc->lock, flags);
82} 81}
83 82
@@ -89,10 +88,10 @@ void dynamic_irq_cleanup(unsigned int irq)
89 */ 88 */
90int set_irq_chip(unsigned int irq, struct irq_chip *chip) 89int set_irq_chip(unsigned int irq, struct irq_chip *chip)
91{ 90{
92 struct irq_desc *desc; 91 struct irq_desc *desc = irq_to_desc(irq);
93 unsigned long flags; 92 unsigned long flags;
94 93
95 if (irq >= NR_IRQS) { 94 if (!desc) {
96 WARN(1, KERN_ERR "Trying to install chip for IRQ%d\n", irq); 95 WARN(1, KERN_ERR "Trying to install chip for IRQ%d\n", irq);
97 return -EINVAL; 96 return -EINVAL;
98 } 97 }
@@ -100,7 +99,6 @@ int set_irq_chip(unsigned int irq, struct irq_chip *chip)
100 if (!chip) 99 if (!chip)
101 chip = &no_irq_chip; 100 chip = &no_irq_chip;
102 101
103 desc = irq_desc + irq;
104 spin_lock_irqsave(&desc->lock, flags); 102 spin_lock_irqsave(&desc->lock, flags);
105 irq_chip_set_defaults(chip); 103 irq_chip_set_defaults(chip);
106 desc->chip = chip; 104 desc->chip = chip;
@@ -111,27 +109,27 @@ int set_irq_chip(unsigned int irq, struct irq_chip *chip)
111EXPORT_SYMBOL(set_irq_chip); 109EXPORT_SYMBOL(set_irq_chip);
112 110
113/** 111/**
114 * set_irq_type - set the irq type for an irq 112 * set_irq_type - set the irq trigger type for an irq
115 * @irq: irq number 113 * @irq: irq number
116 * @type: interrupt type - see include/linux/interrupt.h 114 * @type: IRQ_TYPE_{LEVEL,EDGE}_* value - see include/linux/irq.h
117 */ 115 */
118int set_irq_type(unsigned int irq, unsigned int type) 116int set_irq_type(unsigned int irq, unsigned int type)
119{ 117{
120 struct irq_desc *desc; 118 struct irq_desc *desc = irq_to_desc(irq);
121 unsigned long flags; 119 unsigned long flags;
122 int ret = -ENXIO; 120 int ret = -ENXIO;
123 121
124 if (irq >= NR_IRQS) { 122 if (!desc) {
125 printk(KERN_ERR "Trying to set irq type for IRQ%d\n", irq); 123 printk(KERN_ERR "Trying to set irq type for IRQ%d\n", irq);
126 return -ENODEV; 124 return -ENODEV;
127 } 125 }
128 126
129 desc = irq_desc + irq; 127 if (type == IRQ_TYPE_NONE)
130 if (desc->chip->set_type) { 128 return 0;
131 spin_lock_irqsave(&desc->lock, flags); 129
132 ret = desc->chip->set_type(irq, type); 130 spin_lock_irqsave(&desc->lock, flags);
133 spin_unlock_irqrestore(&desc->lock, flags); 131 ret = __irq_set_trigger(desc, irq, type);
134 } 132 spin_unlock_irqrestore(&desc->lock, flags);
135 return ret; 133 return ret;
136} 134}
137EXPORT_SYMBOL(set_irq_type); 135EXPORT_SYMBOL(set_irq_type);
@@ -145,16 +143,15 @@ EXPORT_SYMBOL(set_irq_type);
145 */ 143 */
146int set_irq_data(unsigned int irq, void *data) 144int set_irq_data(unsigned int irq, void *data)
147{ 145{
148 struct irq_desc *desc; 146 struct irq_desc *desc = irq_to_desc(irq);
149 unsigned long flags; 147 unsigned long flags;
150 148
151 if (irq >= NR_IRQS) { 149 if (!desc) {
152 printk(KERN_ERR 150 printk(KERN_ERR
153 "Trying to install controller data for IRQ%d\n", irq); 151 "Trying to install controller data for IRQ%d\n", irq);
154 return -EINVAL; 152 return -EINVAL;
155 } 153 }
156 154
157 desc = irq_desc + irq;
158 spin_lock_irqsave(&desc->lock, flags); 155 spin_lock_irqsave(&desc->lock, flags);
159 desc->handler_data = data; 156 desc->handler_data = data;
160 spin_unlock_irqrestore(&desc->lock, flags); 157 spin_unlock_irqrestore(&desc->lock, flags);
@@ -171,15 +168,15 @@ EXPORT_SYMBOL(set_irq_data);
171 */ 168 */
172int set_irq_msi(unsigned int irq, struct msi_desc *entry) 169int set_irq_msi(unsigned int irq, struct msi_desc *entry)
173{ 170{
174 struct irq_desc *desc; 171 struct irq_desc *desc = irq_to_desc(irq);
175 unsigned long flags; 172 unsigned long flags;
176 173
177 if (irq >= NR_IRQS) { 174 if (!desc) {
178 printk(KERN_ERR 175 printk(KERN_ERR
179 "Trying to install msi data for IRQ%d\n", irq); 176 "Trying to install msi data for IRQ%d\n", irq);
180 return -EINVAL; 177 return -EINVAL;
181 } 178 }
182 desc = irq_desc + irq; 179
183 spin_lock_irqsave(&desc->lock, flags); 180 spin_lock_irqsave(&desc->lock, flags);
184 desc->msi_desc = entry; 181 desc->msi_desc = entry;
185 if (entry) 182 if (entry)
@@ -197,10 +194,16 @@ int set_irq_msi(unsigned int irq, struct msi_desc *entry)
197 */ 194 */
198int set_irq_chip_data(unsigned int irq, void *data) 195int set_irq_chip_data(unsigned int irq, void *data)
199{ 196{
200 struct irq_desc *desc = irq_desc + irq; 197 struct irq_desc *desc = irq_to_desc(irq);
201 unsigned long flags; 198 unsigned long flags;
202 199
203 if (irq >= NR_IRQS || !desc->chip) { 200 if (!desc) {
201 printk(KERN_ERR
202 "Trying to install chip data for IRQ%d\n", irq);
203 return -EINVAL;
204 }
205
206 if (!desc->chip) {
204 printk(KERN_ERR "BUG: bad set_irq_chip_data(IRQ#%d)\n", irq); 207 printk(KERN_ERR "BUG: bad set_irq_chip_data(IRQ#%d)\n", irq);
205 return -EINVAL; 208 return -EINVAL;
206 } 209 }
@@ -218,7 +221,7 @@ EXPORT_SYMBOL(set_irq_chip_data);
218 */ 221 */
219static void default_enable(unsigned int irq) 222static void default_enable(unsigned int irq)
220{ 223{
221 struct irq_desc *desc = irq_desc + irq; 224 struct irq_desc *desc = irq_to_desc(irq);
222 225
223 desc->chip->unmask(irq); 226 desc->chip->unmask(irq);
224 desc->status &= ~IRQ_MASKED; 227 desc->status &= ~IRQ_MASKED;
@@ -236,8 +239,9 @@ static void default_disable(unsigned int irq)
236 */ 239 */
237static unsigned int default_startup(unsigned int irq) 240static unsigned int default_startup(unsigned int irq)
238{ 241{
239 irq_desc[irq].chip->enable(irq); 242 struct irq_desc *desc = irq_to_desc(irq);
240 243
244 desc->chip->enable(irq);
241 return 0; 245 return 0;
242} 246}
243 247
@@ -246,7 +250,7 @@ static unsigned int default_startup(unsigned int irq)
246 */ 250 */
247static void default_shutdown(unsigned int irq) 251static void default_shutdown(unsigned int irq)
248{ 252{
249 struct irq_desc *desc = irq_desc + irq; 253 struct irq_desc *desc = irq_to_desc(irq);
250 254
251 desc->chip->mask(irq); 255 desc->chip->mask(irq);
252 desc->status |= IRQ_MASKED; 256 desc->status |= IRQ_MASKED;
@@ -305,14 +309,13 @@ handle_simple_irq(unsigned int irq, struct irq_desc *desc)
305{ 309{
306 struct irqaction *action; 310 struct irqaction *action;
307 irqreturn_t action_ret; 311 irqreturn_t action_ret;
308 const unsigned int cpu = smp_processor_id();
309 312
310 spin_lock(&desc->lock); 313 spin_lock(&desc->lock);
311 314
312 if (unlikely(desc->status & IRQ_INPROGRESS)) 315 if (unlikely(desc->status & IRQ_INPROGRESS))
313 goto out_unlock; 316 goto out_unlock;
314 desc->status &= ~(IRQ_REPLAY | IRQ_WAITING); 317 desc->status &= ~(IRQ_REPLAY | IRQ_WAITING);
315 kstat_cpu(cpu).irqs[irq]++; 318 kstat_incr_irqs_this_cpu(irq, desc);
316 319
317 action = desc->action; 320 action = desc->action;
318 if (unlikely(!action || (desc->status & IRQ_DISABLED))) 321 if (unlikely(!action || (desc->status & IRQ_DISABLED)))
@@ -344,7 +347,6 @@ out_unlock:
344void 347void
345handle_level_irq(unsigned int irq, struct irq_desc *desc) 348handle_level_irq(unsigned int irq, struct irq_desc *desc)
346{ 349{
347 unsigned int cpu = smp_processor_id();
348 struct irqaction *action; 350 struct irqaction *action;
349 irqreturn_t action_ret; 351 irqreturn_t action_ret;
350 352
@@ -354,7 +356,7 @@ handle_level_irq(unsigned int irq, struct irq_desc *desc)
354 if (unlikely(desc->status & IRQ_INPROGRESS)) 356 if (unlikely(desc->status & IRQ_INPROGRESS))
355 goto out_unlock; 357 goto out_unlock;
356 desc->status &= ~(IRQ_REPLAY | IRQ_WAITING); 358 desc->status &= ~(IRQ_REPLAY | IRQ_WAITING);
357 kstat_cpu(cpu).irqs[irq]++; 359 kstat_incr_irqs_this_cpu(irq, desc);
358 360
359 /* 361 /*
360 * If its disabled or no action available 362 * If its disabled or no action available
@@ -392,7 +394,6 @@ out_unlock:
392void 394void
393handle_fasteoi_irq(unsigned int irq, struct irq_desc *desc) 395handle_fasteoi_irq(unsigned int irq, struct irq_desc *desc)
394{ 396{
395 unsigned int cpu = smp_processor_id();
396 struct irqaction *action; 397 struct irqaction *action;
397 irqreturn_t action_ret; 398 irqreturn_t action_ret;
398 399
@@ -402,7 +403,7 @@ handle_fasteoi_irq(unsigned int irq, struct irq_desc *desc)
402 goto out; 403 goto out;
403 404
404 desc->status &= ~(IRQ_REPLAY | IRQ_WAITING); 405 desc->status &= ~(IRQ_REPLAY | IRQ_WAITING);
405 kstat_cpu(cpu).irqs[irq]++; 406 kstat_incr_irqs_this_cpu(irq, desc);
406 407
407 /* 408 /*
408 * If its disabled or no action available 409 * If its disabled or no action available
@@ -451,8 +452,6 @@ out:
451void 452void
452handle_edge_irq(unsigned int irq, struct irq_desc *desc) 453handle_edge_irq(unsigned int irq, struct irq_desc *desc)
453{ 454{
454 const unsigned int cpu = smp_processor_id();
455
456 spin_lock(&desc->lock); 455 spin_lock(&desc->lock);
457 456
458 desc->status &= ~(IRQ_REPLAY | IRQ_WAITING); 457 desc->status &= ~(IRQ_REPLAY | IRQ_WAITING);
@@ -468,8 +467,7 @@ handle_edge_irq(unsigned int irq, struct irq_desc *desc)
468 mask_ack_irq(desc, irq); 467 mask_ack_irq(desc, irq);
469 goto out_unlock; 468 goto out_unlock;
470 } 469 }
471 470 kstat_incr_irqs_this_cpu(irq, desc);
472 kstat_cpu(cpu).irqs[irq]++;
473 471
474 /* Start handling the irq */ 472 /* Start handling the irq */
475 desc->chip->ack(irq); 473 desc->chip->ack(irq);
@@ -524,7 +522,7 @@ handle_percpu_irq(unsigned int irq, struct irq_desc *desc)
524{ 522{
525 irqreturn_t action_ret; 523 irqreturn_t action_ret;
526 524
527 kstat_this_cpu.irqs[irq]++; 525 kstat_incr_irqs_this_cpu(irq, desc);
528 526
529 if (desc->chip->ack) 527 if (desc->chip->ack)
530 desc->chip->ack(irq); 528 desc->chip->ack(irq);
@@ -541,17 +539,15 @@ void
541__set_irq_handler(unsigned int irq, irq_flow_handler_t handle, int is_chained, 539__set_irq_handler(unsigned int irq, irq_flow_handler_t handle, int is_chained,
542 const char *name) 540 const char *name)
543{ 541{
544 struct irq_desc *desc; 542 struct irq_desc *desc = irq_to_desc(irq);
545 unsigned long flags; 543 unsigned long flags;
546 544
547 if (irq >= NR_IRQS) { 545 if (!desc) {
548 printk(KERN_ERR 546 printk(KERN_ERR
549 "Trying to install type control for IRQ%d\n", irq); 547 "Trying to install type control for IRQ%d\n", irq);
550 return; 548 return;
551 } 549 }
552 550
553 desc = irq_desc + irq;
554
555 if (!handle) 551 if (!handle)
556 handle = handle_bad_irq; 552 handle = handle_bad_irq;
557 else if (desc->chip == &no_irq_chip) { 553 else if (desc->chip == &no_irq_chip) {
@@ -583,7 +579,7 @@ __set_irq_handler(unsigned int irq, irq_flow_handler_t handle, int is_chained,
583 desc->status &= ~IRQ_DISABLED; 579 desc->status &= ~IRQ_DISABLED;
584 desc->status |= IRQ_NOREQUEST | IRQ_NOPROBE; 580 desc->status |= IRQ_NOREQUEST | IRQ_NOPROBE;
585 desc->depth = 0; 581 desc->depth = 0;
586 desc->chip->unmask(irq); 582 desc->chip->startup(irq);
587 } 583 }
588 spin_unlock_irqrestore(&desc->lock, flags); 584 spin_unlock_irqrestore(&desc->lock, flags);
589} 585}
@@ -606,17 +602,14 @@ set_irq_chip_and_handler_name(unsigned int irq, struct irq_chip *chip,
606 602
607void __init set_irq_noprobe(unsigned int irq) 603void __init set_irq_noprobe(unsigned int irq)
608{ 604{
609 struct irq_desc *desc; 605 struct irq_desc *desc = irq_to_desc(irq);
610 unsigned long flags; 606 unsigned long flags;
611 607
612 if (irq >= NR_IRQS) { 608 if (!desc) {
613 printk(KERN_ERR "Trying to mark IRQ%d non-probeable\n", irq); 609 printk(KERN_ERR "Trying to mark IRQ%d non-probeable\n", irq);
614
615 return; 610 return;
616 } 611 }
617 612
618 desc = irq_desc + irq;
619
620 spin_lock_irqsave(&desc->lock, flags); 613 spin_lock_irqsave(&desc->lock, flags);
621 desc->status |= IRQ_NOPROBE; 614 desc->status |= IRQ_NOPROBE;
622 spin_unlock_irqrestore(&desc->lock, flags); 615 spin_unlock_irqrestore(&desc->lock, flags);
@@ -624,17 +617,14 @@ void __init set_irq_noprobe(unsigned int irq)
624 617
625void __init set_irq_probe(unsigned int irq) 618void __init set_irq_probe(unsigned int irq)
626{ 619{
627 struct irq_desc *desc; 620 struct irq_desc *desc = irq_to_desc(irq);
628 unsigned long flags; 621 unsigned long flags;
629 622
630 if (irq >= NR_IRQS) { 623 if (!desc) {
631 printk(KERN_ERR "Trying to mark IRQ%d probeable\n", irq); 624 printk(KERN_ERR "Trying to mark IRQ%d probeable\n", irq);
632
633 return; 625 return;
634 } 626 }
635 627
636 desc = irq_desc + irq;
637
638 spin_lock_irqsave(&desc->lock, flags); 628 spin_lock_irqsave(&desc->lock, flags);
639 desc->status &= ~IRQ_NOPROBE; 629 desc->status &= ~IRQ_NOPROBE;
640 spin_unlock_irqrestore(&desc->lock, flags); 630 spin_unlock_irqrestore(&desc->lock, flags);