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