1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20#include <linux/config.h>
21#include <linux/errno.h>
22#include <linux/module.h>
23#include <linux/signal.h>
24#include <linux/sched.h>
25#include <linux/ioport.h>
26#include <linux/interrupt.h>
27#include <linux/timex.h>
28#include <linux/slab.h>
29#include <linux/random.h>
30#include <linux/smp_lock.h>
31#include <linux/init.h>
32#include <linux/kernel_stat.h>
33#include <linux/irq.h>
34#include <linux/proc_fs.h>
35#include <linux/seq_file.h>
36#include <linux/kallsyms.h>
37
38#include <asm/atomic.h>
39#include <asm/io.h>
40#include <asm/smp.h>
41#include <asm/system.h>
42#include <asm/bitops.h>
43#include <asm/uaccess.h>
44#include <asm/pgalloc.h>
45#include <asm/delay.h>
46#include <asm/desc.h>
47#include <asm/irq.h>
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68irq_desc_t irq_desc[NR_IRQS] __cacheline_aligned = {
69 [0 ... NR_IRQS-1] = {
70 .handler = &no_irq_type,
71 .lock = SPIN_LOCK_UNLOCKED
72 }
73};
74
75static void register_irq_proc (unsigned int irq);
76
77
78
79
80#ifdef CONFIG_4KSTACKS
81union irq_ctx *hardirq_ctx[NR_CPUS];
82union irq_ctx *softirq_ctx[NR_CPUS];
83#endif
84
85
86
87
88
89irqreturn_t no_action(int cpl, void *dev_id, struct pt_regs *regs)
90{ return IRQ_NONE; }
91
92
93
94
95
96static void enable_none(unsigned int irq) { }
97static unsigned int startup_none(unsigned int irq) { return 0; }
98static void disable_none(unsigned int irq) { }
99static void ack_none(unsigned int irq)
100{
101
102
103
104
105
106#ifdef CONFIG_X86
107 printk("unexpected IRQ trap at vector %02x\n", irq);
108#ifdef CONFIG_X86_LOCAL_APIC
109
110
111
112
113
114
115
116
117 ack_APIC_irq();
118#endif
119#endif
120}
121
122
123#define shutdown_none disable_none
124#define end_none enable_none
125
126struct hw_interrupt_type no_irq_type = {
127 "none",
128 startup_none,
129 shutdown_none,
130 enable_none,
131 disable_none,
132 ack_none,
133 end_none
134};
135
136atomic_t irq_err_count;
137#if defined(CONFIG_X86_IO_APIC) && defined(APIC_MISMATCH_DEBUG)
138atomic_t irq_mis_count;
139#endif
140
141
142
143
144
145int show_interrupts(struct seq_file *p, void *v)
146{
147 int i = *(loff_t *) v, j;
148 struct irqaction * action;
149 unsigned long flags;
150
151 if (i == 0) {
152 seq_printf(p, " ");
153 for (j=0; j<NR_CPUS; j++)
154 if (cpu_online(j))
155 seq_printf(p, "CPU%d ",j);
156 seq_putc(p, '\n');
157 }
158
159 if (i < NR_IRQS) {
160 spin_lock_irqsave(&irq_desc[i].lock, flags);
161 action = irq_desc[i].action;
162 if (!action)
163 goto skip;
164 seq_printf(p, "%3d: ",i);
165#ifndef CONFIG_SMP
166 seq_printf(p, "%10u ", kstat_irqs(i));
167#else
168 for (j = 0; j < NR_CPUS; j++)
169 if (cpu_online(j))
170 seq_printf(p, "%10u ", kstat_cpu(j).irqs[i]);
171#endif
172 seq_printf(p, " %14s", irq_desc[i].handler->typename);
173 seq_printf(p, " %s", action->name);
174
175 for (action=action->next; action; action = action->next)
176 seq_printf(p, ", %s", action->name);
177
178 seq_putc(p, '\n');
179skip:
180 spin_unlock_irqrestore(&irq_desc[i].lock, flags);
181 } else if (i == NR_IRQS) {
182 seq_printf(p, "NMI: ");
183 for (j = 0; j < NR_CPUS; j++)
184 if (cpu_online(j))
185 seq_printf(p, "%10u ", nmi_count(j));
186 seq_putc(p, '\n');
187#ifdef CONFIG_X86_LOCAL_APIC
188 seq_printf(p, "LOC: ");
189 for (j = 0; j < NR_CPUS; j++)
190 if (cpu_online(j))
191 seq_printf(p, "%10u ", irq_stat[j].apic_timer_irqs);
192 seq_putc(p, '\n');
193#endif
194 seq_printf(p, "ERR: %10u\n", atomic_read(&irq_err_count));
195#if defined(CONFIG_X86_IO_APIC) && defined(APIC_MISMATCH_DEBUG)
196 seq_printf(p, "MIS: %10u\n", atomic_read(&irq_mis_count));
197#endif
198 }
199 return 0;
200}
201
202
203
204
205#ifdef CONFIG_SMP
206inline void synchronize_irq(unsigned int irq)
207{
208 while (irq_desc[irq].status & IRQ_INPROGRESS)
209 cpu_relax();
210}
211#endif
212
213
214
215
216
217
218
219
220asmlinkage int handle_IRQ_event(unsigned int irq,
221 struct pt_regs *regs, struct irqaction *action)
222{
223 int status = 1;
224 int retval = 0;
225
226 if (!(action->flags & SA_INTERRUPT))
227 local_irq_enable();
228
229 do {
230 status |= action->flags;
231 retval |= action->handler(irq, action->dev_id, regs);
232 action = action->next;
233 } while (action);
234 if (status & SA_SAMPLE_RANDOM)
235 add_interrupt_randomness(irq);
236 local_irq_disable();
237 return retval;
238}
239
240static void __report_bad_irq(int irq, irq_desc_t *desc, irqreturn_t action_ret)
241{
242 struct irqaction *action;
243
244 if (action_ret != IRQ_HANDLED && action_ret != IRQ_NONE) {
245 printk(KERN_ERR "irq event %d: bogus return value %x\n",
246 irq, action_ret);
247 } else {
248 printk(KERN_ERR "irq %d: nobody cared!\n", irq);
249 }
250 dump_stack();
251 printk(KERN_ERR "handlers:\n");
252 action = desc->action;
253 do {
254 printk(KERN_ERR "[<%p>]", action->handler);
255 print_symbol(" (%s)",
256 (unsigned long)action->handler);
257 printk("\n");
258 action = action->next;
259 } while (action);
260}
261
262static void report_bad_irq(int irq, irq_desc_t *desc, irqreturn_t action_ret)
263{
264 static int count = 100;
265
266 if (count) {
267 count--;
268 __report_bad_irq(irq, desc, action_ret);
269 }
270}
271
272static int noirqdebug;
273
274static int __init noirqdebug_setup(char *str)
275{
276 noirqdebug = 1;
277 printk("IRQ lockup detection disabled\n");
278 return 1;
279}
280
281__setup("noirqdebug", noirqdebug_setup);
282
283
284
285
286
287
288
289
290
291
292
293static void note_interrupt(int irq, irq_desc_t *desc, irqreturn_t action_ret)
294{
295 if (action_ret != IRQ_HANDLED) {
296 desc->irqs_unhandled++;
297 if (action_ret != IRQ_NONE)
298 report_bad_irq(irq, desc, action_ret);
299 }
300
301 desc->irq_count++;
302 if (desc->irq_count < 100000)
303 return;
304
305 desc->irq_count = 0;
306 if (desc->irqs_unhandled > 99900) {
307
308
309
310 __report_bad_irq(irq, desc, action_ret);
311
312
313
314 printk(KERN_EMERG "Disabling IRQ #%d\n", irq);
315 desc->status |= IRQ_DISABLED;
316 desc->handler->disable(irq);
317 }
318 desc->irqs_unhandled = 0;
319}
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340inline void disable_irq_nosync(unsigned int irq)
341{
342 irq_desc_t *desc = irq_desc + irq;
343 unsigned long flags;
344
345 spin_lock_irqsave(&desc->lock, flags);
346 if (!desc->depth++) {
347 desc->status |= IRQ_DISABLED;
348 desc->handler->disable(irq);
349 }
350 spin_unlock_irqrestore(&desc->lock, flags);
351}
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366void disable_irq(unsigned int irq)
367{
368 irq_desc_t *desc = irq_desc + irq;
369 disable_irq_nosync(irq);
370 if (desc->action)
371 synchronize_irq(irq);
372}
373
374
375
376
377
378
379
380
381
382
383
384
385void enable_irq(unsigned int irq)
386{
387 irq_desc_t *desc = irq_desc + irq;
388 unsigned long flags;
389
390 spin_lock_irqsave(&desc->lock, flags);
391 switch (desc->depth) {
392 case 1: {
393 unsigned int status = desc->status & ~IRQ_DISABLED;
394 desc->status = status;
395 if ((status & (IRQ_PENDING | IRQ_REPLAY)) == IRQ_PENDING) {
396 desc->status = status | IRQ_REPLAY;
397 hw_resend_irq(desc->handler,irq);
398 }
399 desc->handler->enable(irq);
400
401 }
402 default:
403 desc->depth--;
404 break;
405 case 0:
406 printk("enable_irq(%u) unbalanced from %p\n", irq,
407 __builtin_return_address(0));
408 }
409 spin_unlock_irqrestore(&desc->lock, flags);
410}
411
412
413
414
415
416
417asmlinkage unsigned int do_IRQ(struct pt_regs regs)
418{
419
420
421
422
423
424
425
426
427
428
429 int irq = regs.orig_eax & 0xff;
430 irq_desc_t *desc = irq_desc + irq;
431 struct irqaction * action;
432 unsigned int status;
433
434 irq_enter();
435
436#ifdef CONFIG_DEBUG_STACKOVERFLOW
437
438 {
439 long esp;
440
441 __asm__ __volatile__("andl %%esp,%0" :
442 "=r" (esp) : "0" (THREAD_SIZE - 1));
443 if (unlikely(esp < (sizeof(struct thread_info) + STACK_WARN))) {
444 printk("do_IRQ: stack overflow: %ld\n",
445 esp - sizeof(struct thread_info));
446 dump_stack();
447 }
448 }
449#endif
450 kstat_this_cpu.irqs[irq]++;
451 spin_lock(&desc->lock);
452 desc->handler->ack(irq);
453
454
455
456
457 status = desc->status & ~(IRQ_REPLAY | IRQ_WAITING);
458 status |= IRQ_PENDING;
459
460
461
462
463
464 action = NULL;
465 if (likely(!(status & (IRQ_DISABLED | IRQ_INPROGRESS)))) {
466 action = desc->action;
467 status &= ~IRQ_PENDING;
468 status |= IRQ_INPROGRESS;
469 }
470 desc->status = status;
471
472
473
474
475
476
477
478 if (unlikely(!action))
479 goto out;
480
481
482
483
484
485
486
487
488
489
490
491#ifdef CONFIG_4KSTACKS
492
493 for (;;) {
494 irqreturn_t action_ret;
495 u32 *isp;
496 union irq_ctx * curctx;
497 union irq_ctx * irqctx;
498
499 curctx = (union irq_ctx *) current_thread_info();
500 irqctx = hardirq_ctx[smp_processor_id()];
501
502 spin_unlock(&desc->lock);
503
504
505
506
507
508
509
510
511 if (curctx == irqctx)
512 action_ret = handle_IRQ_event(irq, ®s, action);
513 else {
514
515 isp = (u32*) ((char*)irqctx + sizeof(*irqctx));
516 irqctx->tinfo.task = curctx->tinfo.task;
517 irqctx->tinfo.previous_esp = current_stack_pointer();
518
519 *--isp = (u32) action;
520 *--isp = (u32) ®s;
521 *--isp = (u32) irq;
522
523 asm volatile(
524 " xchgl %%ebx,%%esp \n"
525 " call handle_IRQ_event \n"
526 " xchgl %%ebx,%%esp \n"
527 : "=a"(action_ret)
528 : "b"(isp)
529 : "memory", "cc", "edx", "ecx"
530 );
531
532
533 }
534 spin_lock(&desc->lock);
535 if (!noirqdebug)
536 note_interrupt(irq, desc, action_ret);
537 if (curctx != irqctx)
538 irqctx->tinfo.task = NULL;
539 if (likely(!(desc->status & IRQ_PENDING)))
540 break;
541 desc->status &= ~IRQ_PENDING;
542 }
543
544#else
545
546 for (;;) {
547 irqreturn_t action_ret;
548
549 spin_unlock(&desc->lock);
550
551 action_ret = handle_IRQ_event(irq, ®s, action);
552
553 spin_lock(&desc->lock);
554 if (!noirqdebug)
555 note_interrupt(irq, desc, action_ret);
556 if (likely(!(desc->status & IRQ_PENDING)))
557 break;
558 desc->status &= ~IRQ_PENDING;
559 }
560#endif
561 desc->status &= ~IRQ_INPROGRESS;
562
563out:
564
565
566
567
568 desc->handler->end(irq);
569 spin_unlock(&desc->lock);
570
571 irq_exit();
572
573 return 1;
574}
575
576int can_request_irq(unsigned int irq, unsigned long irqflags)
577{
578 struct irqaction *action;
579
580 if (irq >= NR_IRQS)
581 return 0;
582 action = irq_desc[irq].action;
583 if (action) {
584 if (irqflags & action->flags & SA_SHIRQ)
585 action = NULL;
586 }
587 return !action;
588}
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622int request_irq(unsigned int irq,
623 irqreturn_t (*handler)(int, void *, struct pt_regs *),
624 unsigned long irqflags,
625 const char * devname,
626 void *dev_id)
627{
628 int retval;
629 struct irqaction * action;
630
631#if 1
632
633
634
635
636
637
638 if (irqflags & SA_SHIRQ) {
639 if (!dev_id)
640 printk("Bad boy: %s (at 0x%x) called us without a dev_id!\n", devname, (&irq)[-1]);
641 }
642#endif
643
644 if (irq >= NR_IRQS)
645 return -EINVAL;
646 if (!handler)
647 return -EINVAL;
648
649 action = (struct irqaction *)
650 kmalloc(sizeof(struct irqaction), GFP_ATOMIC);
651 if (!action)
652 return -ENOMEM;
653
654 action->handler = handler;
655 action->flags = irqflags;
656 action->mask = 0;
657 action->name = devname;
658 action->next = NULL;
659 action->dev_id = dev_id;
660
661 retval = setup_irq(irq, action);
662 if (retval)
663 kfree(action);
664 return retval;
665}
666
667EXPORT_SYMBOL(request_irq);
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684void free_irq(unsigned int irq, void *dev_id)
685{
686 irq_desc_t *desc;
687 struct irqaction **p;
688 unsigned long flags;
689
690 if (irq >= NR_IRQS)
691 return;
692
693 desc = irq_desc + irq;
694 spin_lock_irqsave(&desc->lock,flags);
695 p = &desc->action;
696 for (;;) {
697 struct irqaction * action = *p;
698 if (action) {
699 struct irqaction **pp = p;
700 p = &action->next;
701 if (action->dev_id != dev_id)
702 continue;
703
704
705 *pp = action->next;
706 if (!desc->action) {
707 desc->status |= IRQ_DISABLED;
708 desc->handler->shutdown(irq);
709 }
710 spin_unlock_irqrestore(&desc->lock,flags);
711
712
713 synchronize_irq(irq);
714 kfree(action);
715 return;
716 }
717 printk("Trying to free free IRQ%d\n",irq);
718 spin_unlock_irqrestore(&desc->lock,flags);
719 return;
720 }
721}
722
723EXPORT_SYMBOL(free_irq);
724
725
726
727
728
729
730
731
732
733
734static DECLARE_MUTEX(probe_sem);
735
736
737
738
739
740
741
742
743
744unsigned long probe_irq_on(void)
745{
746 unsigned int i;
747 irq_desc_t *desc;
748 unsigned long val;
749 unsigned long delay;
750
751 down(&probe_sem);
752
753
754
755
756 for (i = NR_IRQS-1; i > 0; i--) {
757 desc = irq_desc + i;
758
759 spin_lock_irq(&desc->lock);
760 if (!irq_desc[i].action)
761 irq_desc[i].handler->startup(i);
762 spin_unlock_irq(&desc->lock);
763 }
764
765
766 for (delay = jiffies + HZ/50; time_after(delay, jiffies); )
767 barrier();
768
769
770
771
772
773
774 for (i = NR_IRQS-1; i > 0; i--) {
775 desc = irq_desc + i;
776
777 spin_lock_irq(&desc->lock);
778 if (!desc->action) {
779 desc->status |= IRQ_AUTODETECT | IRQ_WAITING;
780 if (desc->handler->startup(i))
781 desc->status |= IRQ_PENDING;
782 }
783 spin_unlock_irq(&desc->lock);
784 }
785
786
787
788
789 for (delay = jiffies + HZ/10; time_after(delay, jiffies); )
790 barrier();
791
792
793
794
795 val = 0;
796 for (i = 0; i < NR_IRQS; i++) {
797 irq_desc_t *desc = irq_desc + i;
798 unsigned int status;
799
800 spin_lock_irq(&desc->lock);
801 status = desc->status;
802
803 if (status & IRQ_AUTODETECT) {
804
805 if (!(status & IRQ_WAITING)) {
806 desc->status = status & ~IRQ_AUTODETECT;
807 desc->handler->shutdown(i);
808 } else
809 if (i < 32)
810 val |= 1 << i;
811 }
812 spin_unlock_irq(&desc->lock);
813 }
814
815 return val;
816}
817
818EXPORT_SYMBOL(probe_irq_on);
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837unsigned int probe_irq_mask(unsigned long val)
838{
839 int i;
840 unsigned int mask;
841
842 mask = 0;
843 for (i = 0; i < NR_IRQS; i++) {
844 irq_desc_t *desc = irq_desc + i;
845 unsigned int status;
846
847 spin_lock_irq(&desc->lock);
848 status = desc->status;
849
850 if (status & IRQ_AUTODETECT) {
851 if (i < 16 && !(status & IRQ_WAITING))
852 mask |= 1 << i;
853
854 desc->status = status & ~IRQ_AUTODETECT;
855 desc->handler->shutdown(i);
856 }
857 spin_unlock_irq(&desc->lock);
858 }
859 up(&probe_sem);
860
861 return mask & val;
862}
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887int probe_irq_off(unsigned long val)
888{
889 int i, irq_found, nr_irqs;
890
891 nr_irqs = 0;
892 irq_found = 0;
893 for (i = 0; i < NR_IRQS; i++) {
894 irq_desc_t *desc = irq_desc + i;
895 unsigned int status;
896
897 spin_lock_irq(&desc->lock);
898 status = desc->status;
899
900 if (status & IRQ_AUTODETECT) {
901 if (!(status & IRQ_WAITING)) {
902 if (!nr_irqs)
903 irq_found = i;
904 nr_irqs++;
905 }
906 desc->status = status & ~IRQ_AUTODETECT;
907 desc->handler->shutdown(i);
908 }
909 spin_unlock_irq(&desc->lock);
910 }
911 up(&probe_sem);
912
913 if (nr_irqs > 1)
914 irq_found = -irq_found;
915 return irq_found;
916}
917
918EXPORT_SYMBOL(probe_irq_off);
919
920
921int setup_irq(unsigned int irq, struct irqaction * new)
922{
923 int shared = 0;
924 unsigned long flags;
925 struct irqaction *old, **p;
926 irq_desc_t *desc = irq_desc + irq;
927
928 if (desc->handler == &no_irq_type)
929 return -ENOSYS;
930
931
932
933
934
935 if (new->flags & SA_SAMPLE_RANDOM) {
936
937
938
939
940
941
942
943
944 rand_initialize_irq(irq);
945 }
946
947
948
949
950 spin_lock_irqsave(&desc->lock,flags);
951 p = &desc->action;
952 if ((old = *p) != NULL) {
953
954 if (!(old->flags & new->flags & SA_SHIRQ)) {
955 spin_unlock_irqrestore(&desc->lock,flags);
956 return -EBUSY;
957 }
958
959
960 do {
961 p = &old->next;
962 old = *p;
963 } while (old);
964 shared = 1;
965 }
966
967 *p = new;
968
969 if (!shared) {
970 desc->depth = 0;
971 desc->status &= ~(IRQ_DISABLED | IRQ_AUTODETECT | IRQ_WAITING | IRQ_INPROGRESS);
972 desc->handler->startup(irq);
973 }
974 spin_unlock_irqrestore(&desc->lock,flags);
975
976 register_irq_proc(irq);
977 return 0;
978}
979
980static struct proc_dir_entry * root_irq_dir;
981static struct proc_dir_entry * irq_dir [NR_IRQS];
982
983#ifdef CONFIG_SMP
984
985static struct proc_dir_entry *smp_affinity_entry[NR_IRQS];
986
987cpumask_t irq_affinity[NR_IRQS] = { [0 ... NR_IRQS-1] = CPU_MASK_ALL };
988
989static int irq_affinity_read_proc(char *page, char **start, off_t off,
990 int count, int *eof, void *data)
991{
992 int len = cpumask_scnprintf(page, count, irq_affinity[(long)data]);
993 if (count - len < 2)
994 return -EINVAL;
995 len += sprintf(page + len, "\n");
996 return len;
997}
998
999static int irq_affinity_write_proc(struct file *file, const char __user *buffer,
1000 unsigned long count, void *data)
1001{
1002 int irq = (long)data, full_count = count, err;
1003 cpumask_t new_value, tmp;
1004
1005 if (!irq_desc[irq].handler->set_affinity)
1006 return -EIO;
1007
1008 err = cpumask_parse(buffer, count, new_value);
1009 if (err)
1010 return err;
1011
1012
1013
1014
1015
1016
1017 cpus_and(tmp, new_value, cpu_online_map);
1018 if (cpus_empty(tmp))
1019 return -EINVAL;
1020
1021 irq_affinity[irq] = new_value;
1022 irq_desc[irq].handler->set_affinity(irq,
1023 cpumask_of_cpu(first_cpu(new_value)));
1024
1025 return full_count;
1026}
1027
1028#endif
1029
1030static int prof_cpu_mask_read_proc (char *page, char **start, off_t off,
1031 int count, int *eof, void *data)
1032{
1033 int len = cpumask_scnprintf(page, count, *(cpumask_t *)data);
1034 if (count - len < 2)
1035 return -EINVAL;
1036 len += sprintf(page + len, "\n");
1037 return len;
1038}
1039
1040static int prof_cpu_mask_write_proc (struct file *file, const char __user *buffer,
1041 unsigned long count, void *data)
1042{
1043 cpumask_t *mask = (cpumask_t *)data;
1044 unsigned long full_count = count, err;
1045 cpumask_t new_value;
1046
1047 err = cpumask_parse(buffer, count, new_value);
1048 if (err)
1049 return err;
1050
1051 *mask = new_value;
1052 return full_count;
1053}
1054
1055#define MAX_NAMELEN 10
1056
1057static void register_irq_proc (unsigned int irq)
1058{
1059 char name [MAX_NAMELEN];
1060
1061 if (!root_irq_dir || (irq_desc[irq].handler == &no_irq_type) ||
1062 irq_dir[irq])
1063 return;
1064
1065 memset(name, 0, MAX_NAMELEN);
1066 sprintf(name, "%d", irq);
1067
1068
1069 irq_dir[irq] = proc_mkdir(name, root_irq_dir);
1070
1071#ifdef CONFIG_SMP
1072 {
1073 struct proc_dir_entry *entry;
1074
1075
1076 entry = create_proc_entry("smp_affinity", 0600, irq_dir[irq]);
1077
1078 if (entry) {
1079 entry->nlink = 1;
1080 entry->data = (void *)(long)irq;
1081 entry->read_proc = irq_affinity_read_proc;
1082 entry->write_proc = irq_affinity_write_proc;
1083 }
1084
1085 smp_affinity_entry[irq] = entry;
1086 }
1087#endif
1088}
1089
1090unsigned long prof_cpu_mask = -1;
1091
1092void init_irq_proc (void)
1093{
1094 struct proc_dir_entry *entry;
1095 int i;
1096
1097
1098 root_irq_dir = proc_mkdir("irq", 0);
1099
1100
1101 entry = create_proc_entry("prof_cpu_mask", 0600, root_irq_dir);
1102
1103 if (!entry)
1104 return;
1105
1106 entry->nlink = 1;
1107 entry->data = (void *)&prof_cpu_mask;
1108 entry->read_proc = prof_cpu_mask_read_proc;
1109 entry->write_proc = prof_cpu_mask_write_proc;
1110
1111
1112
1113
1114 for (i = 0; i < NR_IRQS; i++)
1115 register_irq_proc(i);
1116}
1117
1118
1119#ifdef CONFIG_4KSTACKS
1120static char softirq_stack[NR_CPUS * THREAD_SIZE] __attribute__((__aligned__(THREAD_SIZE), __section__(".bss.page_aligned")));
1121static char hardirq_stack[NR_CPUS * THREAD_SIZE] __attribute__((__aligned__(THREAD_SIZE), __section__(".bss.page_aligned")));
1122
1123
1124
1125
1126void irq_ctx_init(int cpu)
1127{
1128 union irq_ctx *irqctx;
1129
1130 if (hardirq_ctx[cpu])
1131 return;
1132
1133 irqctx = (union irq_ctx*) &hardirq_stack[cpu*THREAD_SIZE];
1134 irqctx->tinfo.task = NULL;
1135 irqctx->tinfo.exec_domain = NULL;
1136 irqctx->tinfo.cpu = cpu;
1137 irqctx->tinfo.preempt_count = HARDIRQ_OFFSET;
1138 irqctx->tinfo.addr_limit = MAKE_MM_SEG(0);
1139
1140 hardirq_ctx[cpu] = irqctx;
1141
1142 irqctx = (union irq_ctx*) &softirq_stack[cpu*THREAD_SIZE];
1143 irqctx->tinfo.task = NULL;
1144 irqctx->tinfo.exec_domain = NULL;
1145 irqctx->tinfo.cpu = cpu;
1146 irqctx->tinfo.preempt_count = SOFTIRQ_OFFSET;
1147 irqctx->tinfo.addr_limit = MAKE_MM_SEG(0);
1148
1149 softirq_ctx[cpu] = irqctx;
1150
1151 printk("CPU %u irqstacks, hard=%p soft=%p\n",
1152 cpu,hardirq_ctx[cpu],softirq_ctx[cpu]);
1153}
1154
1155extern asmlinkage void __do_softirq(void);
1156
1157asmlinkage void do_softirq(void)
1158{
1159 unsigned long flags;
1160 struct thread_info *curctx;
1161 union irq_ctx *irqctx;
1162 u32 *isp;
1163
1164 if (in_interrupt())
1165 return;
1166
1167 local_irq_save(flags);
1168
1169 if (local_softirq_pending()) {
1170 curctx = current_thread_info();
1171 irqctx = softirq_ctx[smp_processor_id()];
1172 irqctx->tinfo.task = curctx->task;
1173 irqctx->tinfo.previous_esp = current_stack_pointer();
1174
1175
1176 isp = (u32*) ((char*)irqctx + sizeof(*irqctx));
1177
1178
1179 asm volatile(
1180 " xchgl %%ebx,%%esp \n"
1181 " call __do_softirq \n"
1182 " movl %%ebx,%%esp \n"
1183 : "=b"(isp)
1184 : "0"(isp)
1185 : "memory", "cc", "edx", "ecx", "eax"
1186 );
1187 }
1188
1189 local_irq_restore(flags);
1190}
1191
1192EXPORT_SYMBOL(do_softirq);
1193#endif
1194