irq.c
来自「优龙2410linux2.6.8内核源代码」· C语言 代码 · 共 718 行 · 第 1/2 页
C
718 行
if (i == 0) { seq_puts(p, " "); for (j=0; j<NR_CPUS; j++) if (cpu_online(j)) seq_printf(p, "CPU%d ", j); seq_putc(p, '\n'); } if (i < NR_IRQS) { spin_lock_irqsave(&irq_desc[i].lock, flags); action = irq_desc[i].action; if ( !action || !action->handler ) goto skip; seq_printf(p, "%3d: ", i);#ifdef CONFIG_SMP for (j = 0; j < NR_CPUS; j++) if (cpu_online(j)) seq_printf(p, "%10u ", kstat_cpu(j).irqs[i]);#else seq_printf(p, "%10u ", kstat_irqs(i));#endif /* CONFIG_SMP */ if (irq_desc[i].handler) seq_printf(p, " %s ", irq_desc[i].handler->typename); else seq_puts(p, " None "); seq_printf(p, "%s", (irq_desc[i].status & IRQ_LEVEL) ? "Level " : "Edge "); seq_printf(p, " %s", action->name); for (action = action->next; action; action = action->next) seq_printf(p, ", %s", action->name); seq_putc(p, '\n');skip: spin_unlock_irqrestore(&irq_desc[i].lock, flags); } else if (i == NR_IRQS) {#ifdef CONFIG_TAU_INT if (tau_initialized){ seq_puts(p, "TAU: "); for (j = 0; j < NR_CPUS; j++) if (cpu_online(j)) seq_printf(p, "%10u ", tau_interrupts(j)); seq_puts(p, " PowerPC Thermal Assist (cpu temp)\n"); }#endif#ifdef CONFIG_SMP /* should this be per processor send/receive? */ seq_printf(p, "IPI (recv/sent): %10u/%u\n", atomic_read(&ipi_recv), atomic_read(&ipi_sent));#endif seq_printf(p, "BAD: %10u\n", ppc_spurious_interrupts); } return 0;}static inline voidhandle_irq_event(int irq, struct pt_regs *regs, struct irqaction *action){ int status = 0; if (!(action->flags & SA_INTERRUPT)) local_irq_enable(); do { status |= action->flags; action->handler(irq, action->dev_id, regs); action = action->next; } while (action); if (status & SA_SAMPLE_RANDOM) add_interrupt_randomness(irq); local_irq_disable();}/* * Eventually, this should take an array of interrupts and an array size * so it can dispatch multiple interrupts. */void ppc_irq_dispatch_handler(struct pt_regs *regs, int irq){ int status; struct irqaction *action; irq_desc_t *desc = irq_desc + irq; kstat_this_cpu.irqs[irq]++; spin_lock(&desc->lock); ack_irq(irq); /* REPLAY is when Linux resends an IRQ that was dropped earlier WAITING is used by probe to mark irqs that are being tested */ status = desc->status & ~(IRQ_REPLAY | IRQ_WAITING); if (!(status & IRQ_PER_CPU)) status |= IRQ_PENDING; /* we _want_ to handle it */ /* * If the IRQ is disabled for whatever reason, we cannot * use the action we have. */ action = NULL; if (likely(!(status & (IRQ_DISABLED | IRQ_INPROGRESS)))) { action = desc->action; if (!action || !action->handler) { ppc_spurious_interrupts++; printk(KERN_DEBUG "Unhandled interrupt %x, disabled\n", irq); /* We can't call disable_irq here, it would deadlock */ ++desc->depth; desc->status |= IRQ_DISABLED; mask_irq(irq); /* This is a real interrupt, we have to eoi it, so we jump to out */ goto out; } status &= ~IRQ_PENDING; /* we commit to handling */ if (!(status & IRQ_PER_CPU)) status |= IRQ_INPROGRESS; /* we are handling it */ } desc->status = status; /* * If there is no IRQ handler or it was disabled, exit early. Since we set PENDING, if another processor is handling a different instance of this same irq, the other processor will take care of it. */ if (unlikely(!action)) goto out; /* * Edge triggered interrupts need to remember * pending events. * This applies to any hw interrupts that allow a second * instance of the same irq to arrive while we are in do_IRQ * or in the handler. But the code here only handles the _second_ * instance of the irq, not the third or fourth. So it is mostly * useful for irq hardware that does not mask cleanly in an * SMP environment. */ for (;;) { spin_unlock(&desc->lock); handle_irq_event(irq, regs, action); spin_lock(&desc->lock); if (likely(!(desc->status & IRQ_PENDING))) break; desc->status &= ~IRQ_PENDING; }out: desc->status &= ~IRQ_INPROGRESS; /* * The ->end() handler has to deal with interrupts which got * disabled while the handler was running. */ if (irq_desc[irq].handler) { if (irq_desc[irq].handler->end) irq_desc[irq].handler->end(irq); else if (irq_desc[irq].handler->enable) irq_desc[irq].handler->enable(irq); } spin_unlock(&desc->lock);}void do_IRQ(struct pt_regs *regs){ int irq, first = 1; irq_enter(); /* * Every platform is required to implement ppc_md.get_irq. * This function will either return an irq number or -1 to * indicate there are no more pending. But the first time * through the loop this means there wasn't and IRQ pending. * The value -2 is for buggy hardware and means that this IRQ * has already been handled. -- Tom */ while ((irq = ppc_md.get_irq(regs)) >= 0) { ppc_irq_dispatch_handler(regs, irq); first = 0; } if (irq != -2 && first) /* That's not SMP safe ... but who cares ? */ ppc_spurious_interrupts++; irq_exit();}unsigned long probe_irq_on (void){ return 0;}EXPORT_SYMBOL(probe_irq_on);int probe_irq_off (unsigned long irqs){ return 0;}EXPORT_SYMBOL(probe_irq_off);unsigned int probe_irq_mask(unsigned long irqs){ return 0;}#ifdef CONFIG_SMPvoid synchronize_irq(unsigned int irq){ while (irq_desc[irq].status & IRQ_INPROGRESS) barrier();}#endif /* CONFIG_SMP */static struct proc_dir_entry *root_irq_dir;static struct proc_dir_entry *irq_dir[NR_IRQS];static struct proc_dir_entry *smp_affinity_entry[NR_IRQS];#ifdef CONFIG_IRQ_ALL_CPUS#define DEFAULT_CPU_AFFINITY CPU_MASK_ALL#else#define DEFAULT_CPU_AFFINITY cpumask_of_cpu(0)#endifcpumask_t irq_affinity [NR_IRQS];static int irq_affinity_read_proc (char *page, char **start, off_t off, int count, int *eof, void *data){ int len = cpumask_scnprintf(page, count, irq_affinity[(long)data]); if (count - len < 2) return -EINVAL; len += sprintf(page + len, "\n"); return len;}static int irq_affinity_write_proc (struct file *file, const char __user *buffer, unsigned long count, void *data){ int irq = (int) data, full_count = count, err; cpumask_t new_value, tmp; if (!irq_desc[irq].handler->set_affinity) return -EIO; err = cpumask_parse(buffer, count, new_value); /* * Do not allow disabling IRQs completely - it's a too easy * way to make the system unusable accidentally :-) At least * one online CPU still has to be targeted. * * We assume a 1-1 logical<->physical cpu mapping here. If * we assume that the cpu indices in /proc/irq/../smp_affinity * are actually logical cpu #'s then we have no problem. * -- Cort <cort@fsmlabs.com> */ cpus_and(tmp, new_value, cpu_online_map); if (cpus_empty(tmp)) return -EINVAL; irq_affinity[irq] = new_value; irq_desc[irq].handler->set_affinity(irq, new_value); return full_count;}static int prof_cpu_mask_read_proc (char *page, char **start, off_t off, int count, int *eof, void *data){ int len = cpumask_scnprintf(page, count, *(cpumask_t *)data); if (count - len < 2) return -EINVAL; len += sprintf(page + len, "\n"); return len;}static int prof_cpu_mask_write_proc (struct file *file, const char __user *buffer, unsigned long count, void *data){ int err; int full_count = count; cpumask_t *mask = (cpumask_t *)data; cpumask_t new_value; err = cpumask_parse(buffer, count, new_value); if (err) return err; *mask = new_value; return full_count;}#define MAX_NAMELEN 10static void register_irq_proc (unsigned int irq){ struct proc_dir_entry *entry; char name [MAX_NAMELEN]; if (!root_irq_dir || (irq_desc[irq].handler == NULL) || irq_dir[irq]) return; memset(name, 0, MAX_NAMELEN); sprintf(name, "%d", irq); /* create /proc/irq/1234 */ irq_dir[irq] = proc_mkdir(name, root_irq_dir); /* create /proc/irq/1234/smp_affinity */ entry = create_proc_entry("smp_affinity", 0600, irq_dir[irq]); entry->nlink = 1; entry->data = (void *)irq; entry->read_proc = irq_affinity_read_proc; entry->write_proc = irq_affinity_write_proc; smp_affinity_entry[irq] = entry;}unsigned long prof_cpu_mask = -1;void init_irq_proc (void){ struct proc_dir_entry *entry; int i; /* create /proc/irq */ root_irq_dir = proc_mkdir("irq", NULL); /* create /proc/irq/prof_cpu_mask */ entry = create_proc_entry("prof_cpu_mask", 0600, root_irq_dir); entry->nlink = 1; entry->data = (void *)&prof_cpu_mask; entry->read_proc = prof_cpu_mask_read_proc; entry->write_proc = prof_cpu_mask_write_proc; /* * Create entries for all existing IRQs. */ for (i = 0; i < NR_IRQS; i++) { if (irq_desc[i].handler == NULL) continue; register_irq_proc(i); }}irqreturn_t no_action(int irq, void *dev, struct pt_regs *regs){ return IRQ_NONE;}void __init init_IRQ(void){ int i; for (i = 0; i < NR_IRQS; ++i) irq_affinity[i] = DEFAULT_CPU_AFFINITY; ppc_md.init_IRQ();}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?