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