1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16#include <linux/config.h>
17#include <linux/ptrace.h>
18#include <linux/errno.h>
19#include <linux/kernel_stat.h>
20#include <linux/signal.h>
21#include <linux/sched.h>
22#include <linux/ioport.h>
23#include <linux/interrupt.h>
24#include <linux/timex.h>
25#include <linux/slab.h>
26#include <linux/random.h>
27#include <linux/smp.h>
28#include <linux/smp_lock.h>
29#include <linux/init.h>
30
31#include <asm/system.h>
32#include <asm/io.h>
33#include <asm/bitops.h>
34#include <asm/pgalloc.h>
35#include <asm/delay.h>
36#include <asm/irq.h>
37#include <linux/irq.h>
38
39
40
41
42irq_desc_t irq_desc[NR_IRQS] __cacheline_aligned =
43 { [0 ... NR_IRQS-1] = { 0, &no_irq_type, }};
44
45
46
47
48
49void no_action(int cpl, void *dev_id, struct pt_regs *regs) { }
50
51
52
53
54
55static void enable_none(unsigned int irq) { }
56static unsigned int startup_none(unsigned int irq) { return 0; }
57static void disable_none(unsigned int irq) { }
58static void ack_none(unsigned int irq)
59{
60
61
62
63
64
65 printk("unexpected IRQ trap at vector %02x\n", irq);
66}
67
68
69#define shutdown_none disable_none
70#define end_none enable_none
71
72struct hw_interrupt_type no_irq_type = {
73 "none",
74 startup_none,
75 shutdown_none,
76 enable_none,
77 disable_none,
78 ack_none,
79 end_none
80};
81
82
83
84
85
86#if defined(CONFIG_PROC_FS)
87int get_irq_list(char *buf)
88{
89 int i, j;
90 struct irqaction * action;
91 char *p = buf;
92
93 p += sprintf(p, " ");
94 for (j=0; j<smp_num_cpus; j++)
95 p += sprintf(p, "CPU%d ",j);
96 *p++ = '\n';
97
98 for (i = 0 ; i < ACTUAL_NR_IRQS ; i++) {
99 action = irq_desc[i].action;
100 if (!action)
101 continue;
102 p += sprintf(p, "%3d: ",i);
103 p += sprintf(p, "%10u ", kstat_irqs(i));
104 p += sprintf(p, " %14s", irq_desc[i].handler->typename);
105 p += sprintf(p, " %s", action->name);
106
107 for (action=action->next; action; action = action->next)
108 p += sprintf(p, ", %s", action->name);
109 *p++ = '\n';
110 }
111 return p - buf;
112}
113#endif
114
115
116
117
118
119
120
121
122int handle_IRQ_event(unsigned int irq, struct pt_regs * regs, struct irqaction * action)
123{
124 int status;
125 int cpu = smp_processor_id();
126
127 irq_enter(cpu, irq);
128
129 status = 1;
130
131 if (!(action->flags & SA_INTERRUPT))
132 __sti();
133
134 do {
135 status |= action->flags;
136 action->handler(irq, action->dev_id, regs);
137 action = action->next;
138 } while (action);
139 if (status & SA_SAMPLE_RANDOM)
140 add_interrupt_randomness(irq);
141 __cli();
142
143 irq_exit(cpu, irq);
144
145 return status;
146}
147
148
149
150
151
152
153
154void disable_irq_nosync(unsigned int irq)
155{
156 irq_desc_t *desc = irq_desc + irq;
157 unsigned long flags;
158
159 spin_lock_irqsave(&desc->lock, flags);
160 if (!desc->depth++) {
161 desc->status |= IRQ_DISABLED;
162 desc->handler->disable(irq);
163 }
164 spin_unlock_irqrestore(&desc->lock, flags);
165}
166
167
168
169
170
171void disable_irq(unsigned int irq)
172{
173 disable_irq_nosync(irq);
174
175 if (!local_irq_count(smp_processor_id())) {
176 do {
177 barrier();
178 } while (irq_desc[irq].status & IRQ_INPROGRESS);
179 }
180}
181
182void enable_irq(unsigned int irq)
183{
184 irq_desc_t *desc = irq_desc + irq;
185 unsigned long flags;
186
187 spin_lock_irqsave(&desc->lock, flags);
188 switch (desc->depth) {
189 case 1: {
190 unsigned int status = desc->status & ~IRQ_DISABLED;
191 desc->status = status;
192 if ((status & (IRQ_PENDING | IRQ_REPLAY)) == IRQ_PENDING) {
193 desc->status = status | IRQ_REPLAY;
194 hw_resend_irq(desc->handler,irq);
195 }
196 desc->handler->enable(irq);
197
198 }
199 default:
200 desc->depth--;
201 break;
202 case 0:
203 printk("enable_irq() unbalanced from %p\n",
204 __builtin_return_address(0));
205 }
206 spin_unlock_irqrestore(&desc->lock, flags);
207}
208
209
210
211
212asmlinkage int do_IRQ(unsigned long r4, unsigned long r5,
213 unsigned long r6, unsigned long r7,
214 struct pt_regs regs)
215{
216
217
218
219
220
221
222
223
224
225
226 int irq;
227 int cpu = smp_processor_id();
228 irq_desc_t *desc;
229 struct irqaction * action;
230 unsigned int status;
231
232
233 asm volatile("stc r2_bank, %0\n\t"
234 "shlr2 %0\n\t"
235 "shlr2 %0\n\t"
236 "shlr %0\n\t"
237 "add #-16, %0\n\t"
238 :"=z" (irq));
239 irq = irq_demux(irq);
240
241 kstat.irqs[cpu][irq]++;
242 desc = irq_desc + irq;
243 spin_lock(&desc->lock);
244 desc->handler->ack(irq);
245
246
247
248
249 status = desc->status & ~(IRQ_REPLAY | IRQ_WAITING | IRQ_INPROGRESS);
250 status |= IRQ_PENDING;
251
252
253
254
255
256 action = NULL;
257 if (!(status & (IRQ_DISABLED | IRQ_INPROGRESS))) {
258 action = desc->action;
259 status &= ~IRQ_PENDING;
260 status |= IRQ_INPROGRESS;
261 }
262 desc->status = status;
263
264
265
266
267
268
269
270 if (!action)
271 goto out;
272
273
274
275
276
277
278
279
280
281
282
283 for (;;) {
284 spin_unlock(&desc->lock);
285 handle_IRQ_event(irq, ®s, action);
286 spin_lock(&desc->lock);
287
288 if (!(desc->status & IRQ_PENDING))
289 break;
290 desc->status &= ~IRQ_PENDING;
291 }
292 desc->status &= ~IRQ_INPROGRESS;
293out:
294
295
296
297
298 desc->handler->end(irq);
299 spin_unlock(&desc->lock);
300
301 if (softirq_pending(cpu))
302 do_softirq();
303 return 1;
304}
305
306int request_irq(unsigned int irq,
307 void (*handler)(int, void *, struct pt_regs *),
308 unsigned long irqflags,
309 const char * devname,
310 void *dev_id)
311{
312 int retval;
313 struct irqaction * action;
314
315 if (irq >= ACTUAL_NR_IRQS)
316 return -EINVAL;
317 if (!handler)
318 return -EINVAL;
319
320 action = (struct irqaction *)
321 kmalloc(sizeof(struct irqaction), GFP_KERNEL);
322 if (!action)
323 return -ENOMEM;
324
325 action->handler = handler;
326 action->flags = irqflags;
327 action->mask = 0;
328 action->name = devname;
329 action->next = NULL;
330 action->dev_id = dev_id;
331
332 retval = setup_irq(irq, action);
333 if (retval)
334 kfree(action);
335 return retval;
336}
337
338void free_irq(unsigned int irq, void *dev_id)
339{
340 irq_desc_t *desc;
341 struct irqaction **p;
342 unsigned long flags;
343
344 if (irq >= ACTUAL_NR_IRQS)
345 return;
346
347 desc = irq_desc + irq;
348 spin_lock_irqsave(&desc->lock,flags);
349 p = &desc->action;
350 for (;;) {
351 struct irqaction * action = *p;
352 if (action) {
353 struct irqaction **pp = p;
354 p = &action->next;
355 if (action->dev_id != dev_id)
356 continue;
357
358
359 *pp = action->next;
360 if (!desc->action) {
361 desc->status |= IRQ_DISABLED;
362 desc->handler->shutdown(irq);
363 }
364 spin_unlock_irqrestore(&desc->lock,flags);
365 kfree(action);
366 return;
367 }
368 printk("Trying to free free IRQ%d\n",irq);
369 spin_unlock_irqrestore(&desc->lock,flags);
370 return;
371 }
372}
373
374static DECLARE_MUTEX(probe_sem);
375
376
377
378
379
380
381
382
383
384unsigned long probe_irq_on(void)
385{
386 unsigned int i;
387 irq_desc_t *desc;
388 unsigned long val;
389 unsigned long delay;
390
391 down(&probe_sem);
392
393
394
395
396 for (i = NR_IRQS-1; i > 0; i--) {
397 desc = irq_desc + i;
398
399 spin_lock_irq(&desc->lock);
400 if (!desc->action)
401 desc->handler->startup(i);
402 spin_unlock_irq(&desc->lock);
403 }
404
405
406 for (delay = jiffies + HZ/50; time_after(delay, jiffies); )
407 synchronize_irq();
408
409
410
411
412
413
414 for (i = NR_IRQS-1; i > 0; i--) {
415 desc = irq_desc + i;
416
417 spin_lock_irq(&desc->lock);
418 if (!desc->action) {
419 desc->status |= IRQ_AUTODETECT | IRQ_WAITING;
420 if (desc->handler->startup(i))
421 desc->status |= IRQ_PENDING;
422 }
423 spin_unlock_irq(&desc->lock);
424 }
425
426
427
428
429 for (delay = jiffies + HZ/10; time_after(delay, jiffies); )
430 synchronize_irq();
431
432
433
434
435 val = 0;
436 for (i=0; i<NR_IRQS; i++) {
437 desc = irq_desc + i;
438 unsigned int status;
439
440 spin_lock_irq(&desc->lock);
441 status = desc->status;
442
443 if (status & IRQ_AUTODETECT) {
444
445 if (!(status & IRQ_WAITING)) {
446 desc->status = status & ~IRQ_AUTODETECT;
447 desc->handler->shutdown(i);
448 } else
449 if (i < 32)
450 val |= 1 << i;
451 }
452 spin_unlock_irq(&desc->lock);
453 }
454
455 return val;
456}
457
458int probe_irq_off(unsigned long val)
459{
460 int i, irq_found, nr_irqs;
461
462 nr_irqs = 0;
463 irq_found = 0;
464 for (i=0; i<NR_IRQS; i++) {
465 irq_desc_t *desc = irq_desc + i;
466 unsigned int status;
467
468 spin_lock_irq(&desc->lock);
469 status = desc->status;
470
471 if (status & IRQ_AUTODETECT) {
472 if (!(status & IRQ_WAITING)) {
473 if (!nr_irqs)
474 irq_found = i;
475 nr_irqs++;
476 }
477 desc->status = status & ~IRQ_AUTODETECT;
478 desc->handler->shutdown(i);
479 }
480 spin_unlock_irq(&desc->lock);
481 }
482 up(&probe_sem);
483
484 if (nr_irqs > 1)
485 irq_found = -irq_found;
486 return irq_found;
487}
488
489int setup_irq(unsigned int irq, struct irqaction * new)
490{
491 int shared = 0;
492 struct irqaction *old, **p;
493 unsigned long flags;
494 irq_desc_t *desc = irq_desc + irq;
495
496
497
498
499
500
501 if (new->flags & SA_SAMPLE_RANDOM) {
502
503
504
505
506
507
508
509
510 rand_initialize_irq(irq);
511 }
512
513
514
515
516 spin_lock_irqsave(&desc->lock,flags);
517 p = &desc->action;
518 if ((old = *p) != NULL) {
519
520 if (!(old->flags & new->flags & SA_SHIRQ)) {
521 spin_unlock_irqrestore(&desc->lock,flags);
522 return -EBUSY;
523 }
524
525
526 do {
527 p = &old->next;
528 old = *p;
529 } while (old);
530 shared = 1;
531 }
532
533 *p = new;
534
535 if (!shared) {
536 desc->depth = 0;
537 desc->status &= ~(IRQ_DISABLED | IRQ_AUTODETECT | IRQ_WAITING);
538 desc->handler->startup(irq);
539 }
540 spin_unlock_irqrestore(&desc->lock,flags);
541 return 0;
542}
543
544#if defined(CONFIG_PROC_FS) && defined(CONFIG_SYSCTL)
545
546void init_irq_proc(void)
547{
548}
549#endif
550