00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026 #include <linux/config.h>
00027 #include <linux/ptrace.h>
00028 #include <linux/errno.h>
00029 #include <linux/signal.h>
00030 #include <linux/sched.h>
00031 #include <linux/ioport.h>
00032 #include <linux/interrupt.h>
00033 #include <linux/timex.h>
00034 #include <linux/slab.h>
00035 #include <linux/random.h>
00036 #include <linux/smp_lock.h>
00037 #include <linux/init.h>
00038 #include <linux/kernel_stat.h>
00039 #include <linux/irq.h>
00040 #include <linux/proc_fs.h>
00041
00042 #include <asm/atomic.h>
00043 #include <asm/io.h>
00044 #include <asm/smp.h>
00045 #include <asm/system.h>
00046 #include <asm/bitops.h>
00047 #include <asm/uaccess.h>
00048 #include <asm/pgalloc.h>
00049 #include <asm/delay.h>
00050 #include <asm/desc.h>
00051 #include <asm/irq.h>
00052 #include <idbdef.h>
00053 #include <ucbdef.h>
00054 #include <crbdef.h>
00055 #include <vecdef.h>
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076 irq_desc_t vms_irq_desc[NR_IRQS] __cacheline_aligned =
00077 { [0 ... NR_IRQS-1] = { 0, &no_irq_type, NULL, 0, SPIN_LOCK_UNLOCKED}};
00078
00079 static void register_irq_proc (unsigned int irq);
00080
00081
00082
00083
00084
00085 void vms_no_action(int cpl, void *dev_id, struct pt_regs *regs) { }
00086
00087
00088
00089
00090
00091 static void enable_none(unsigned int irq) { }
00092 static unsigned int startup_none(unsigned int irq) { return 0; }
00093 static void disable_none(unsigned int irq) { }
00094 static void ack_none(unsigned int irq)
00095 {
00096
00097
00098
00099
00100
00101 #if CONFIG_X86
00102 printk("unexpected IRQ trap at vector %02x\n", irq);
00103 #ifdef CONFIG_X86_LOCAL_APIC
00104
00105
00106
00107
00108
00109
00110
00111
00112 ack_APIC_irq();
00113 #endif
00114 #endif
00115 }
00116
00117
00118 #define shutdown_none disable_none
00119 #define end_none enable_none
00120
00121 struct hw_interrupt_type vms_no_irq_type = {
00122 "none",
00123 startup_none,
00124 shutdown_none,
00125 enable_none,
00126 disable_none,
00127 ack_none,
00128 end_none
00129 };
00130
00131 atomic_t vms_irq_err_count;
00132 #ifdef CONFIG_X86_IO_APIC
00133 #ifdef APIC_MISMATCH_DEBUG
00134 atomic_t irq_mis_count;
00135 #endif
00136 #endif
00137
00138
00139
00140
00141
00142 int vms_get_irq_list(char *buf)
00143 {
00144 int i, j;
00145 struct irqaction * action;
00146 char *p = buf;
00147
00148 p += sprintf(p, " ");
00149 for (j=0; j<smp_num_cpus; j++)
00150 p += sprintf(p, "CPU%d ",j);
00151 *p++ = '\n';
00152
00153 for (i = 0 ; i < NR_IRQS ; i++) {
00154 action = irq_desc[i].action;
00155 if (!action)
00156 continue;
00157 p += sprintf(p, "%3d: ",i);
00158 #ifndef CONFIG_SMP
00159 p += sprintf(p, "%10u ", kstat_irqs(i));
00160 #else
00161 for (j = 0; j < smp_num_cpus; j++)
00162 p += sprintf(p, "%10u ",
00163 kstat.irqs[cpu_logical_map(j)][i]);
00164 #endif
00165 p += sprintf(p, " %14s", irq_desc[i].handler->typename);
00166 p += sprintf(p, " %s", action->name);
00167
00168 for (action=action->next; action; action = action->next)
00169 p += sprintf(p, ", %s", action->name);
00170 *p++ = '\n';
00171 }
00172 p += sprintf(p, "NMI: ");
00173 for (j = 0; j < smp_num_cpus; j++)
00174 p += sprintf(p, "%10u ",
00175 nmi_count(cpu_logical_map(j)));
00176 p += sprintf(p, "\n");
00177 #if CONFIG_X86_LOCAL_APIC
00178 p += sprintf(p, "LOC: ");
00179 for (j = 0; j < smp_num_cpus; j++)
00180 p += sprintf(p, "%10u ",
00181 apic_timer_irqs[cpu_logical_map(j)]);
00182 p += sprintf(p, "\n");
00183 #endif
00184 p += sprintf(p, "ERR: %10u\n", atomic_read(&irq_err_count));
00185 #ifdef CONFIG_X86_IO_APIC
00186 #ifdef APIC_MISMATCH_DEBUG
00187 p += sprintf(p, "MIS: %10u\n", atomic_read(&irq_mis_count));
00188 #endif
00189 #endif
00190 return p - buf;
00191 }
00192
00193
00194
00195
00196
00197
00198
00199 #ifdef CONFIG_SMP
00200 unsigned char global_irq_holder = NO_PROC_ID;
00201 unsigned volatile long global_irq_lock;
00202
00203 extern void show_stack(unsigned long* esp);
00204
00205 static void show(char * str)
00206 {
00207 int i;
00208 int cpu = smp_processor_id();
00209
00210 printk("\n%s, CPU %d:\n", str, cpu);
00211 printk("irq: %d [",irqs_running());
00212 for(i=0;i < smp_num_cpus;i++)
00213 printk(" %d",local_irq_count(i));
00214 printk(" ]\nbh: %d [",spin_is_locked(&global_bh_lock) ? 1 : 0);
00215 for(i=0;i < smp_num_cpus;i++)
00216 printk(" %d",local_bh_count(i));
00217
00218 printk(" ]\nStack dumps:");
00219 for(i = 0; i < smp_num_cpus; i++) {
00220 unsigned long esp;
00221 if (i == cpu)
00222 continue;
00223 printk("\nCPU %d:",i);
00224 esp = init_tss[i].esp0;
00225 if (!esp) {
00226
00227
00228
00229
00230 printk(" <unknown> ");
00231 continue;
00232 }
00233 esp &= ~(THREAD_SIZE-1);
00234 esp += sizeof(struct task_struct);
00235 show_stack((void*)esp);
00236 }
00237 printk("\nCPU %d:",cpu);
00238 show_stack(NULL);
00239 printk("\n");
00240 }
00241
00242 #define MAXCOUNT 100000000
00243
00244
00245
00246
00247
00248
00249
00250
00251
00252
00253
00254
00255
00256
00257
00258
00259
00260 #define SUSPECTED_CPU_OR_CHIPSET_BUG_WORKAROUND 0
00261
00262 #if SUSPECTED_CPU_OR_CHIPSET_BUG_WORKAROUND
00263 # define SYNC_OTHER_CORES(x) udelay(x+1)
00264 #else
00265
00266
00267
00268 # define SYNC_OTHER_CORES(x) __asm__ __volatile__ ("nop")
00269 #endif
00270
00271 static inline void wait_on_irq(int cpu)
00272 {
00273 int count = MAXCOUNT;
00274
00275 for (;;) {
00276
00277
00278
00279
00280
00281
00282 if (!irqs_running())
00283 if (local_bh_count(cpu) || !spin_is_locked(&global_bh_lock))
00284 break;
00285
00286
00287 clear_bit(0,&global_irq_lock);
00288
00289 for (;;) {
00290 if (!--count) {
00291 show("wait_on_irq");
00292 count = ~0;
00293 }
00294 __sti();
00295 SYNC_OTHER_CORES(cpu);
00296 __cli();
00297 if (irqs_running())
00298 continue;
00299 if (global_irq_lock)
00300 continue;
00301 if (!local_bh_count(cpu) && spin_is_locked(&global_bh_lock))
00302 continue;
00303 if (!test_and_set_bit(0,&global_irq_lock))
00304 break;
00305 }
00306 }
00307 }
00308
00309
00310
00311
00312
00313
00314
00315
00316 void vms_synchronize_irq(void)
00317 {
00318 if (irqs_running()) {
00319
00320 cli();
00321 sti();
00322 }
00323 }
00324
00325 static inline void get_irqlock(int cpu)
00326 {
00327 if (test_and_set_bit(0,&global_irq_lock)) {
00328
00329 if ((unsigned char) cpu == global_irq_holder)
00330 return;
00331
00332 do {
00333 do {
00334 rep_nop();
00335 } while (test_bit(0,&global_irq_lock));
00336 } while (test_and_set_bit(0,&global_irq_lock));
00337 }
00338
00339
00340
00341
00342 wait_on_irq(cpu);
00343
00344
00345
00346
00347 global_irq_holder = cpu;
00348 }
00349
00350 #define EFLAGS_IF_SHIFT 9
00351
00352
00353
00354
00355
00356
00357
00358
00359
00360
00361
00362
00363
00364 void vms___global_cli(void)
00365 {
00366 unsigned int flags;
00367
00368 __save_flags(flags);
00369 if (flags & (1 << EFLAGS_IF_SHIFT)) {
00370 int cpu = smp_processor_id();
00371 __cli();
00372 if (!local_irq_count(cpu))
00373 get_irqlock(cpu);
00374 }
00375 }
00376
00377 void vms___global_sti(void)
00378 {
00379 int cpu = smp_processor_id();
00380
00381 if (!local_irq_count(cpu))
00382 release_irqlock(cpu);
00383 __sti();
00384 }
00385
00386
00387
00388
00389
00390
00391
00392
00393 unsigned long __global_save_flags(void)
00394 {
00395 int retval;
00396 int local_enabled;
00397 unsigned long flags;
00398 int cpu = smp_processor_id();
00399
00400 __save_flags(flags);
00401 local_enabled = (flags >> EFLAGS_IF_SHIFT) & 1;
00402
00403 retval = 2 + local_enabled;
00404
00405
00406 if (!local_irq_count(cpu)) {
00407 if (local_enabled)
00408 retval = 1;
00409 if (global_irq_holder == cpu)
00410 retval = 0;
00411 }
00412 return retval;
00413 }
00414
00415 void vms___global_restore_flags(unsigned long flags)
00416 {
00417 switch (flags) {
00418 case 0:
00419 __global_cli();
00420 break;
00421 case 1:
00422 __global_sti();
00423 break;
00424 case 2:
00425 __cli();
00426 break;
00427 case 3:
00428 __sti();
00429 break;
00430 default:
00431 printk("global_restore_flags: %08lx (%08lx)\n",
00432 flags, (&flags)[-1]);
00433 }
00434 }
00435
00436 #endif
00437
00438
00439
00440
00441
00442
00443
00444
00445 int vms_handle_IRQ_event(struct _idb * idb, unsigned int irq, struct pt_regs * regs, struct irqaction * action)
00446 {
00447 int status;
00448 int cpu = smp_processor_id();
00449
00450 irq_enter(cpu, irq);
00451
00452 status = 1;
00453
00454 if (!(action->flags & SA_INTERRUPT))
00455 __sti();
00456
00457 do {
00458 void (*handler)(struct _idb * idb);
00459 status |= action->flags;
00460 handler=((struct _vec *)&idb->idb_ps_owner->ucb$l_crb->crb$l_intd)->vec$ps_isr_code;
00461 handler(idb);
00462 action = action->next;
00463 } while (action);
00464 if (status & SA_SAMPLE_RANDOM)
00465 add_interrupt_randomness(irq);
00466 __cli();
00467
00468 irq_exit(cpu, irq);
00469
00470 return status;
00471 }
00472
00473
00474
00475
00476
00477
00478
00479
00480
00481
00482
00483
00484
00485
00486
00487
00488
00489
00490
00491
00492 inline void vms_disable_irq_nosync(unsigned int irq)
00493 {
00494 irq_desc_t *desc = irq_desc + irq;
00495 unsigned long flags;
00496
00497 spin_lock_irqsave(&desc->lock, flags);
00498 if (!desc->depth++) {
00499 desc->status |= IRQ_DISABLED;
00500 desc->handler->disable(irq);
00501 }
00502 spin_unlock_irqrestore(&desc->lock, flags);
00503 }
00504
00505
00506
00507
00508
00509
00510
00511
00512
00513
00514
00515
00516
00517
00518 void vms_disable_irq(unsigned int irq)
00519 {
00520 disable_irq_nosync(irq);
00521
00522 if (!local_irq_count(smp_processor_id())) {
00523 do {
00524 barrier();
00525 cpu_relax();
00526 } while (irq_desc[irq].status & IRQ_INPROGRESS);
00527 }
00528 }
00529
00530
00531
00532
00533
00534
00535
00536
00537
00538
00539
00540
00541 void vms_enable_irq(unsigned int irq)
00542 {
00543 irq_desc_t *desc = irq_desc + irq;
00544 unsigned long flags;
00545
00546 spin_lock_irqsave(&desc->lock, flags);
00547 switch (desc->depth) {
00548 case 1: {
00549 unsigned int status = desc->status & ~IRQ_DISABLED;
00550 desc->status = status;
00551 if ((status & (IRQ_PENDING | IRQ_REPLAY)) == IRQ_PENDING) {
00552 desc->status = status | IRQ_REPLAY;
00553 hw_resend_irq(desc->handler,irq);
00554 }
00555 desc->handler->enable(irq);
00556
00557 }
00558 default:
00559 desc->depth--;
00560 break;
00561 case 0:
00562 printk("enable_irq(%u) unbalanced from %p\n", irq,
00563 __builtin_return_address(0));
00564 }
00565 spin_unlock_irqrestore(&desc->lock, flags);
00566 }
00567
00568
00569
00570
00571
00572
00573 asmlinkage unsigned int vms_do_IRQ(struct pt_regs regs)
00574 {
00575
00576
00577
00578
00579
00580
00581
00582
00583
00584
00585 int irq = regs.orig_eax & 0xff;
00586 int cpu = smp_processor_id();
00587 irq_desc_t *desc = irq_desc + irq;
00588 struct irqaction * action;
00589 unsigned int status;
00590
00591 kstat.irqs[cpu][irq]++;
00592 spin_lock(&desc->lock);
00593 desc->handler->ack(irq);
00594
00595
00596
00597
00598 status = desc->status & ~(IRQ_REPLAY | IRQ_WAITING);
00599 status |= IRQ_PENDING;
00600
00601
00602
00603
00604
00605 action = NULL;
00606 if (!(status & (IRQ_DISABLED | IRQ_INPROGRESS))) {
00607 action = desc->action;
00608 status &= ~IRQ_PENDING;
00609 status |= IRQ_INPROGRESS;
00610 }
00611 desc->status = status;
00612
00613
00614
00615
00616
00617
00618
00619 if (!action)
00620 goto out;
00621
00622
00623
00624
00625
00626
00627
00628
00629
00630
00631
00632 for (;;) {
00633 struct _idb * idb;
00634 spin_unlock(&desc->lock);
00635 vms_handle_IRQ_event(idb, irq, ®s, action);
00636 spin_lock(&desc->lock);
00637
00638 if (!(desc->status & IRQ_PENDING))
00639 break;
00640 desc->status &= ~IRQ_PENDING;
00641 }
00642 desc->status &= ~IRQ_INPROGRESS;
00643 out:
00644
00645
00646
00647
00648 desc->handler->end(irq);
00649 spin_unlock(&desc->lock);
00650
00651 #ifndef CONFIG_VMS
00652 if (softirq_pending(cpu))
00653 do_softirq();
00654 #endif
00655 return 1;
00656 }
00657
00658
00659
00660
00661
00662
00663
00664
00665
00666
00667
00668
00669
00670
00671
00672
00673
00674
00675
00676
00677
00678
00679
00680
00681
00682
00683
00684
00685
00686
00687
00688
00689
00690 int vms_request_irq(struct _idb * idb, unsigned int irq,
00691 void (*handler)(int, void *, struct pt_regs *),
00692 unsigned long irqflags,
00693 const char * devname,
00694 void *dev_id)
00695 {
00696 int retval;
00697 struct irqaction * action;
00698
00699 #if 1
00700
00701
00702
00703
00704
00705
00706 if (irqflags & SA_SHIRQ) {
00707 if (!dev_id)
00708 printk("Bad boy: %s (at 0x%x) called us without a dev_id!\n", devname, (&irq)[-1]);
00709 }
00710 #endif
00711
00712 if (irq >= NR_IRQS)
00713 return -EINVAL;
00714 if (!handler)
00715 return -EINVAL;
00716
00717 action = (struct irqaction *)
00718 kmalloc(sizeof(struct irqaction), GFP_KERNEL);
00719 if (!action)
00720 return -ENOMEM;
00721
00722 action->handler = handler;
00723 action->flags = irqflags;
00724 action->mask = 0;
00725 action->name = devname;
00726 action->next = NULL;
00727 action->dev_id = dev_id;
00728 action->vms_interrupt = 1;
00729 action->idb = idb;
00730
00731 retval = setup_irq(irq, action);
00732 if (retval)
00733 kfree(action);
00734 return retval;
00735 }
00736
00737
00738
00739
00740
00741
00742
00743
00744
00745
00746
00747
00748
00749
00750
00751
00752
00753
00754
00755 void vms_free_irq(unsigned int irq, void *dev_id)
00756 {
00757 irq_desc_t *desc;
00758 struct irqaction **p;
00759 unsigned long flags;
00760
00761 if (irq >= NR_IRQS)
00762 return;
00763
00764 desc = irq_desc + irq;
00765 spin_lock_irqsave(&desc->lock,flags);
00766 p = &desc->action;
00767 for (;;) {
00768 struct irqaction * action = *p;
00769 if (action) {
00770 struct irqaction **pp = p;
00771 p = &action->next;
00772 if (action->dev_id != dev_id)
00773 continue;
00774
00775
00776 *pp = action->next;
00777 if (!desc->action) {
00778 desc->status |= IRQ_DISABLED;
00779 desc->handler->shutdown(irq);
00780 }
00781 spin_unlock_irqrestore(&desc->lock,flags);
00782
00783 #ifdef CONFIG_SMP
00784
00785 while (desc->status & IRQ_INPROGRESS) {
00786 barrier();
00787 cpu_relax();
00788 }
00789 #endif
00790 kfree(action);
00791 return;
00792 }
00793 printk("Trying to free free IRQ%d\n",irq);
00794 spin_unlock_irqrestore(&desc->lock,flags);
00795 return;
00796 }
00797 }
00798
00799
00800
00801
00802
00803
00804
00805
00806
00807
00808 static DECLARE_MUTEX(vms_probe_sem);
00809
00810
00811
00812
00813
00814
00815
00816
00817
00818 unsigned long vms_probe_irq_on(void)
00819 {
00820 unsigned int i;
00821 irq_desc_t *desc;
00822 unsigned long val;
00823 unsigned long delay;
00824
00825 down(&vms_probe_sem);
00826
00827
00828
00829
00830 for (i = NR_IRQS-1; i > 0; i--) {
00831 desc = irq_desc + i;
00832
00833 spin_lock_irq(&desc->lock);
00834 if (!irq_desc[i].action)
00835 irq_desc[i].handler->startup(i);
00836 spin_unlock_irq(&desc->lock);
00837 }
00838
00839
00840 for (delay = jiffies + HZ/50; time_after(delay, jiffies); )
00841 synchronize_irq();
00842
00843
00844
00845
00846
00847
00848 for (i = NR_IRQS-1; i > 0; i--) {
00849 desc = irq_desc + i;
00850
00851 spin_lock_irq(&desc->lock);
00852 if (!desc->action) {
00853 desc->status |= IRQ_AUTODETECT | IRQ_WAITING;
00854 if (desc->handler->startup(i))
00855 desc->status |= IRQ_PENDING;
00856 }
00857 spin_unlock_irq(&desc->lock);
00858 }
00859
00860
00861
00862
00863 for (delay = jiffies + HZ/10; time_after(delay, jiffies); )
00864 synchronize_irq();
00865
00866
00867
00868
00869 val = 0;
00870 for (i = 0; i < NR_IRQS; i++) {
00871 irq_desc_t *desc = irq_desc + i;
00872 unsigned int status;
00873
00874 spin_lock_irq(&desc->lock);
00875 status = desc->status;
00876
00877 if (status & IRQ_AUTODETECT) {
00878
00879 if (!(status & IRQ_WAITING)) {
00880 desc->status = status & ~IRQ_AUTODETECT;
00881 desc->handler->shutdown(i);
00882 } else
00883 if (i < 32)
00884 val |= 1 << i;
00885 }
00886 spin_unlock_irq(&desc->lock);
00887 }
00888
00889 return val;
00890 }
00891
00892
00893
00894
00895
00896
00897
00898
00899
00900
00901
00902
00903
00904
00905
00906
00907
00908
00909 unsigned int vms_probe_irq_mask(unsigned long val)
00910 {
00911 int i;
00912 unsigned int mask;
00913
00914 mask = 0;
00915 for (i = 0; i < NR_IRQS; i++) {
00916 irq_desc_t *desc = irq_desc + i;
00917 unsigned int status;
00918
00919 spin_lock_irq(&desc->lock);
00920 status = desc->status;
00921
00922 if (status & IRQ_AUTODETECT) {
00923 if (i < 16 && !(status & IRQ_WAITING))
00924 mask |= 1 << i;
00925
00926 desc->status = status & ~IRQ_AUTODETECT;
00927 desc->handler->shutdown(i);
00928 }
00929 spin_unlock_irq(&desc->lock);
00930 }
00931 up(&vms_probe_sem);
00932
00933 return mask & val;
00934 }
00935
00936
00937
00938
00939
00940
00941
00942
00943
00944
00945
00946
00947
00948
00949
00950
00951
00952
00953
00954
00955
00956
00957
00958
00959 int vms_probe_irq_off(unsigned long val)
00960 {
00961 int i, irq_found, nr_irqs;
00962
00963 nr_irqs = 0;
00964 irq_found = 0;
00965 for (i = 0; i < NR_IRQS; i++) {
00966 irq_desc_t *desc = irq_desc + i;
00967 unsigned int status;
00968
00969 spin_lock_irq(&desc->lock);
00970 status = desc->status;
00971
00972 if (status & IRQ_AUTODETECT) {
00973 if (!(status & IRQ_WAITING)) {
00974 if (!nr_irqs)
00975 irq_found = i;
00976 nr_irqs++;
00977 }
00978 desc->status = status & ~IRQ_AUTODETECT;
00979 desc->handler->shutdown(i);
00980 }
00981 spin_unlock_irq(&desc->lock);
00982 }
00983 up(&vms_probe_sem);
00984
00985 if (nr_irqs > 1)
00986 irq_found = -irq_found;
00987 return irq_found;
00988 }
00989
00990
00991 int vms_setup_irq(unsigned int irq, struct irqaction * new)
00992 {
00993 int shared = 0;
00994 unsigned long flags;
00995 struct irqaction *old, **p;
00996 irq_desc_t *desc = irq_desc + irq;
00997
00998
00999
01000
01001
01002
01003 if (new->flags & SA_SAMPLE_RANDOM) {
01004
01005
01006
01007
01008
01009
01010
01011
01012 rand_initialize_irq(irq);
01013 }
01014
01015
01016
01017
01018 spin_lock_irqsave(&desc->lock,flags);
01019 p = &desc->action;
01020 if ((old = *p) != NULL) {
01021
01022 if (!(old->flags & new->flags & SA_SHIRQ)) {
01023 spin_unlock_irqrestore(&desc->lock,flags);
01024 return -EBUSY;
01025 }
01026
01027
01028 do {
01029 p = &old->next;
01030 old = *p;
01031 } while (old);
01032 shared = 1;
01033 }
01034
01035 *p = new;
01036
01037 if (!shared) {
01038 desc->depth = 0;
01039 desc->status &= ~(IRQ_DISABLED | IRQ_AUTODETECT | IRQ_WAITING);
01040 desc->handler->startup(irq);
01041 }
01042 spin_unlock_irqrestore(&desc->lock,flags);
01043
01044 register_irq_proc(irq);
01045 return 0;
01046 }
01047
01048 static struct proc_dir_entry * root_irq_dir;
01049 static struct proc_dir_entry * irq_dir [NR_IRQS];
01050
01051 #define HEX_DIGITS 8
01052
01053 static unsigned int parse_hex_value (const char *buffer,
01054 unsigned long count, unsigned long *ret)
01055 {
01056 unsigned char hexnum [HEX_DIGITS];
01057 unsigned long value;
01058 int i;
01059
01060 if (!count)
01061 return -EINVAL;
01062 if (count > HEX_DIGITS)
01063 count = HEX_DIGITS;
01064 if (copy_from_user(hexnum, buffer, count))
01065 return -EFAULT;
01066
01067
01068
01069
01070
01071 value = 0;
01072
01073 for (i = 0; i < count; i++) {
01074 unsigned int c = hexnum[i];
01075
01076 switch (c) {
01077 case '0' ... '9': c -= '0'; break;
01078 case 'a' ... 'f': c -= 'a'-10; break;
01079 case 'A' ... 'F': c -= 'A'-10; break;
01080 default:
01081 goto out;
01082 }
01083 value = (value << 4) | c;
01084 }
01085 out:
01086 *ret = value;
01087 return 0;
01088 }
01089
01090 #if CONFIG_SMP
01091
01092 static struct proc_dir_entry * smp_affinity_entry [NR_IRQS];
01093
01094 static unsigned long irq_affinity [NR_IRQS] = { [0 ... NR_IRQS-1] = ~0UL };
01095 static int irq_affinity_read_proc (char *page, char **start, off_t off,
01096 int count, int *eof, void *data)
01097 {
01098 if (count < HEX_DIGITS+1)
01099 return -EINVAL;
01100 return sprintf (page, "%08lx\n", irq_affinity[(long)data]);
01101 }
01102
01103 static int irq_affinity_write_proc (struct file *file, const char *buffer,
01104 unsigned long count, void *data)
01105 {
01106 int irq = (long) data, full_count = count, err;
01107 unsigned long new_value;
01108
01109 if (!irq_desc[irq].handler->set_affinity)
01110 return -EIO;
01111
01112 err = parse_hex_value(buffer, count, &new_value);
01113
01114
01115
01116
01117
01118
01119 if (!(new_value & cpu_online_map))
01120 return -EINVAL;
01121
01122 irq_affinity[irq] = new_value;
01123 irq_desc[irq].handler->set_affinity(irq, new_value);
01124
01125 return full_count;
01126 }
01127
01128 #endif
01129
01130 static int prof_cpu_mask_read_proc (char *page, char **start, off_t off,
01131 int count, int *eof, void *data)
01132 {
01133 unsigned long *mask = (unsigned long *) data;
01134 if (count < HEX_DIGITS+1)
01135 return -EINVAL;
01136 return sprintf (page, "%08lx\n", *mask);
01137 }
01138
01139 static int prof_cpu_mask_write_proc (struct file *file, const char *buffer,
01140 unsigned long count, void *data)
01141 {
01142 unsigned long *mask = (unsigned long *) data, full_count = count, err;
01143 unsigned long new_value;
01144
01145 err = parse_hex_value(buffer, count, &new_value);
01146 if (err)
01147 return err;
01148
01149 *mask = new_value;
01150 return full_count;
01151 }
01152
01153 #define MAX_NAMELEN 10
01154
01155 static void register_irq_proc (unsigned int irq)
01156 {
01157 char name [MAX_NAMELEN];
01158
01159 if (!root_irq_dir || (irq_desc[irq].handler == &no_irq_type) ||
01160 irq_dir[irq])
01161 return;
01162
01163 memset(name, 0, MAX_NAMELEN);
01164 sprintf(name, "%d", irq);
01165
01166
01167 irq_dir[irq] = proc_mkdir(name, root_irq_dir);
01168
01169 #if CONFIG_SMP
01170 {
01171 struct proc_dir_entry *entry;
01172
01173
01174 entry = create_proc_entry("smp_affinity", 0600, irq_dir[irq]);
01175
01176 if (entry) {
01177 entry->nlink = 1;
01178 entry->data = (void *)(long)irq;
01179 entry->read_proc = irq_affinity_read_proc;
01180 entry->write_proc = irq_affinity_write_proc;
01181 }
01182
01183 smp_affinity_entry[irq] = entry;
01184 }
01185 #endif
01186 }
01187
01188 unsigned long vms_prof_cpu_mask = -1;
01189
01190 void vms_init_irq_proc (void)
01191 {
01192 struct proc_dir_entry *entry;
01193 int i;
01194
01195
01196 root_irq_dir = proc_mkdir("irq", 0);
01197
01198
01199 entry = create_proc_entry("prof_cpu_mask", 0600, root_irq_dir);
01200
01201 if (!entry)
01202 return;
01203
01204 entry->nlink = 1;
01205 entry->data = (void *)&vms_prof_cpu_mask;
01206 entry->read_proc = prof_cpu_mask_read_proc;
01207 entry->write_proc = prof_cpu_mask_write_proc;
01208
01209
01210
01211
01212 for (i = 0; i < NR_IRQS; i++)
01213 register_irq_proc(i);
01214 }
01215
01216