📄 ip27-irq.c
字号:
}void free_irq(unsigned int irq, void *dev_id){ struct irqaction * action, **p; unsigned long flags; if (irq >= NR_IRQS) { printk("Trying to free IRQ%d\n", irq); return; } for (p = irq + irq_action; (action = *p) != NULL; p = &action->next) { if (action->dev_id != dev_id) continue; /* Found it - now free it */ save_and_cli(flags); *p = action->next; if (irq >= BASE_PCI_IRQ) bridge_shutdown(irq); restore_flags(flags); kfree(action); return; } printk("Trying to free free IRQ%d\n",irq);}/* Useless ISA nonsense. */unsigned long probe_irq_on (void){ panic("probe_irq_on called!\n"); return 0;}int probe_irq_off (unsigned long irqs){ return 0;}void __init init_IRQ(void){ set_except_vector(0, ip27_irq);}#ifdef CONFIG_SMP/* * This following are the global intr on off routines, copied almost * entirely from i386 code. */int global_irq_holder = NO_PROC_ID;spinlock_t global_irq_lock = SPIN_LOCK_UNLOCKED;extern void show_stack(unsigned long* esp);static void show(char * str){ int i; int cpu = smp_processor_id(); printk("\n%s, CPU %d:\n", str, cpu); printk("irq: %d [",irqs_running()); for(i=0;i < smp_num_cpus;i++) printk(" %d",local_irq_count(i)); printk(" ]\nbh: %d [",spin_is_locked(&global_bh_lock) ? 1 : 0); for(i=0;i < smp_num_cpus;i++) printk(" %d",local_bh_count(i)); printk(" ]\nStack dumps:"); for(i = 0; i < smp_num_cpus; i++) { unsigned long esp; if (i == cpu) continue; printk("\nCPU %d:",i); printk("Code not developed yet\n"); /* show_stack(0); */ } printk("\nCPU %d:",cpu); printk("Code not developed yet\n"); /* show_stack(NULL); */ printk("\n");}#define MAXCOUNT 100000000#define SYNC_OTHER_CORES(x) udelay(x+1)static inline void wait_on_irq(int cpu){ int count = MAXCOUNT; for (;;) { /* * Wait until all interrupts are gone. Wait * for bottom half handlers unless we're * already executing in one.. */ if (!irqs_running()) if (local_bh_count(cpu) || !spin_is_locked(&global_bh_lock)) break; /* Duh, we have to loop. Release the lock to avoid deadlocks */ spin_unlock(&global_irq_lock); for (;;) { if (!--count) { show("wait_on_irq"); count = ~0; } __sti(); SYNC_OTHER_CORES(cpu); __cli(); if (irqs_running()) continue; if (spin_is_locked(&global_irq_lock)) continue; if (!local_bh_count(cpu) && spin_is_locked(&global_bh_lock)) continue; if (spin_trylock(&global_irq_lock)) break; } }}void synchronize_irq(void){ if (irqs_running()) { /* Stupid approach */ cli(); sti(); }}static inline void get_irqlock(int cpu){ if (!spin_trylock(&global_irq_lock)) { /* do we already hold the lock? */ if ((unsigned char) cpu == global_irq_holder) return; /* Uhhuh.. Somebody else got it. Wait.. */ spin_lock(&global_irq_lock); } /* * We also to make sure that nobody else is running * in an interrupt context. */ wait_on_irq(cpu); /* * Ok, finally.. */ global_irq_holder = cpu;}void __global_cli(void){ unsigned int flags; __save_flags(flags); if (flags & ST0_IE) { int cpu = smp_processor_id(); __cli(); if (!local_irq_count(cpu)) get_irqlock(cpu); }}void __global_sti(void){ int cpu = smp_processor_id(); if (!local_irq_count(cpu)) release_irqlock(cpu); __sti();}/* * SMP flags value to restore to: * 0 - global cli * 1 - global sti * 2 - local cli * 3 - local sti */unsigned long __global_save_flags(void){ int retval; int local_enabled; unsigned long flags; int cpu = smp_processor_id(); __save_flags(flags); local_enabled = (flags & ST0_IE); /* default to local */ retval = 2 + local_enabled; /* check for global flags if we're not in an interrupt */ if (!local_irq_count(cpu)) { if (local_enabled) retval = 1; if (global_irq_holder == cpu) retval = 0; } return retval;}void __global_restore_flags(unsigned long flags){ switch (flags) { case 0: __global_cli(); break; case 1: __global_sti(); break; case 2: __cli(); break; case 3: __sti(); break; default: printk("global_restore_flags: %08lx\n", flags); }}#endif /* CONFIG_SMP *//* * Get values that vary depending on which CPU and bit we're operating on. */static hub_intmasks_t *intr_get_ptrs(cpuid_t cpu, int bit, int *new_bit, hubreg_t **intpend_masks, int *ip){ hub_intmasks_t *hub_intmasks; hub_intmasks = &cpu_data[cpu].p_intmasks; if (bit < N_INTPEND_BITS) { *intpend_masks = hub_intmasks->intpend0_masks; *ip = 0; *new_bit = bit; } else { *intpend_masks = hub_intmasks->intpend1_masks; *ip = 1; *new_bit = bit - N_INTPEND_BITS; } return hub_intmasks;}int intr_connect_level(int cpu, int bit){ int ip; int slice = cputoslice(cpu); volatile hubreg_t *mask_reg; hubreg_t *intpend_masks; nasid_t nasid = COMPACT_TO_NASID_NODEID(cputocnode(cpu)); (void)intr_get_ptrs(cpu, bit, &bit, &intpend_masks, &ip); /* Make sure it's not already pending when we connect it. */ REMOTE_HUB_CLR_INTR(nasid, bit + ip * N_INTPEND_BITS); intpend_masks[0] |= (1ULL << (u64)bit); if (ip == 0) { mask_reg = REMOTE_HUB_ADDR(nasid, PI_INT_MASK0_A + PI_INT_MASK_OFFSET * slice); } else { mask_reg = REMOTE_HUB_ADDR(nasid, PI_INT_MASK1_A + PI_INT_MASK_OFFSET * slice); } HUB_S(mask_reg, intpend_masks[0]); return(0);}int intr_disconnect_level(int cpu, int bit){ int ip; int slice = cputoslice(cpu); volatile hubreg_t *mask_reg; hubreg_t *intpend_masks; nasid_t nasid = COMPACT_TO_NASID_NODEID(cputocnode(cpu)); (void)intr_get_ptrs(cpu, bit, &bit, &intpend_masks, &ip); intpend_masks[0] &= ~(1ULL << (u64)bit); if (ip == 0) { mask_reg = REMOTE_HUB_ADDR(nasid, PI_INT_MASK0_A + PI_INT_MASK_OFFSET * slice); } else { mask_reg = REMOTE_HUB_ADDR(nasid, PI_INT_MASK1_A + PI_INT_MASK_OFFSET * slice); } HUB_S(mask_reg, intpend_masks[0]); return(0);}void handle_resched_intr(int irq, void *dev_id, struct pt_regs *regs){ /* Nothing, the return from intr will work for us */}extern void smp_call_function_interrupt(void);void install_cpuintr(int cpu){#ifdef CONFIG_SMP#if (CPUS_PER_NODE == 2) static int done = 0; int irq; /* * This is a hack till we have a pernode irqlist. Currently, * just have the master cpu set up the handlers for the per * cpu irqs. */ irq = CPU_RESCHED_A_IRQ + cputoslice(cpu); intr_connect_level(cpu, IRQ_TO_SWLEVEL(cpu, irq)); if (done == 0) if (request_irq(irq, handle_resched_intr, 0, "resched", 0)) panic("intercpu intr unconnectible\n"); irq = CPU_CALL_A_IRQ + cputoslice(cpu); intr_connect_level(cpu, IRQ_TO_SWLEVEL(cpu, irq)); if (done == 0) if (request_irq(irq, smp_call_function_interrupt, 0, "callfunc", 0)) panic("intercpu intr unconnectible\n"); /* HACK STARTS */ if (done) return; irq = CPU_RESCHED_A_IRQ + cputoslice(cpu) + 1; if (request_irq(irq, handle_resched_intr, 0, "resched", 0)) panic("intercpu intr unconnectible\n"); irq = CPU_CALL_A_IRQ + cputoslice(cpu) + 1; if (request_irq(irq, smp_call_function_interrupt, 0, "callfunc", 0)) panic("intercpu intr unconnectible\n"); done = 1; /* HACK ENDS */#else /* CPUS_PER_NODE */#error Must redefine this for more than 2 CPUS.#endif /* CPUS_PER_NODE */#endif /* CONFIG_SMP */}void install_tlbintr(int cpu){ int intr_bit = N_INTPEND_BITS + TLB_INTR_A + cputoslice(cpu); intr_connect_level(cpu, intr_bit);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -