diff options
author | Linus Torvalds <torvalds@woody.linux-foundation.org> | 2007-07-16 10:45:23 -0700 |
---|---|---|
committer | Linus Torvalds <torvalds@woody.linux-foundation.org> | 2007-07-16 10:45:23 -0700 |
commit | 02b2318e07f98a7cdf7089a4457a8d62424aa824 (patch) | |
tree | b40353a9ee6b034e21192ceb5df445fbc5fbdd32 /arch/sparc64/kernel/irq.c | |
parent | b91cba52e9b7b3f1c0037908a192d93a869ca9e5 (diff) | |
parent | d54bc2793ec3405c6b8f217568a82b87bd8a591b (diff) |
Merge branch 'master' of master.kernel.org:/pub/scm/linux/kernel/git/davem/sparc-2.6
* 'master' of master.kernel.org:/pub/scm/linux/kernel/git/davem/sparc-2.6: (26 commits)
[SPARC64]: Fix UP build.
[SPARC64]: dr-cpu unconfigure support.
[SERIAL]: Fix console write locking in sparc drivers.
[SPARC64]: Give more accurate errors in dr_cpu_configure().
[SPARC64]: Clear cpu_{core,sibling}_map[] in smp_fill_in_sib_core_maps()
[SPARC64]: Fix leak when DR added cpu does not bootup.
[SPARC64]: Add ->set_affinity IRQ handlers.
[SPARC64]: Process dr-cpu events in a kthread instead of workqueue.
[SPARC64]: More sensible udelay implementation.
[SPARC64]: SMP build fixes.
[SPARC64]: mdesc.c needs linux/mm.h
[SPARC64]: Fix build regressions added by dr-cpu changes.
[SPARC64]: Unconditionally register vio_bus_type.
[SPARC64]: Initial LDOM cpu hotplug support.
[SPARC64]: Fix setting of variables in LDOM guest.
[SPARC64]: Fix MD property lifetime bugs.
[SPARC64]: Abstract out mdesc accesses for better MD update handling.
[SPARC64]: Use more mearningful names for IRQ registry.
[SPARC64]: Initial domain-services driver.
[SPARC64]: Export powerd facilities for external entities.
...
Diffstat (limited to 'arch/sparc64/kernel/irq.c')
-rw-r--r-- | arch/sparc64/kernel/irq.c | 84 |
1 files changed, 84 insertions, 0 deletions
diff --git a/arch/sparc64/kernel/irq.c b/arch/sparc64/kernel/irq.c index 6b6165d36fd8..8cb3358674f5 100644 --- a/arch/sparc64/kernel/irq.c +++ b/arch/sparc64/kernel/irq.c @@ -293,6 +293,11 @@ static void sun4u_irq_enable(unsigned int virt_irq) } } +static void sun4u_set_affinity(unsigned int virt_irq, cpumask_t mask) +{ + sun4u_irq_enable(virt_irq); +} + static void sun4u_irq_disable(unsigned int virt_irq) { struct irq_handler_data *data = get_irq_chip_data(virt_irq); @@ -309,6 +314,10 @@ static void sun4u_irq_disable(unsigned int virt_irq) static void sun4u_irq_end(unsigned int virt_irq) { struct irq_handler_data *data = get_irq_chip_data(virt_irq); + struct irq_desc *desc = irq_desc + virt_irq; + + if (unlikely(desc->status & (IRQ_DISABLED|IRQ_INPROGRESS))) + return; if (likely(data)) upa_writeq(ICLR_IDLE, data->iclr); @@ -340,6 +349,24 @@ static void sun4v_irq_enable(unsigned int virt_irq) } } +static void sun4v_set_affinity(unsigned int virt_irq, cpumask_t mask) +{ + struct ino_bucket *bucket = virt_irq_to_bucket(virt_irq); + unsigned int ino = bucket - &ivector_table[0]; + + if (likely(bucket)) { + unsigned long cpuid; + int err; + + cpuid = irq_choose_cpu(virt_irq); + + err = sun4v_intr_settarget(ino, cpuid); + if (err != HV_EOK) + printk("sun4v_intr_settarget(%x,%lu): err(%d)\n", + ino, cpuid, err); + } +} + static void sun4v_irq_disable(unsigned int virt_irq) { struct ino_bucket *bucket = virt_irq_to_bucket(virt_irq); @@ -373,6 +400,10 @@ static void sun4v_irq_end(unsigned int virt_irq) { struct ino_bucket *bucket = virt_irq_to_bucket(virt_irq); unsigned int ino = bucket - &ivector_table[0]; + struct irq_desc *desc = irq_desc + virt_irq; + + if (unlikely(desc->status & (IRQ_DISABLED|IRQ_INPROGRESS))) + return; if (likely(bucket)) { int err; @@ -418,6 +449,28 @@ static void sun4v_virq_enable(unsigned int virt_irq) } } +static void sun4v_virt_set_affinity(unsigned int virt_irq, cpumask_t mask) +{ + struct ino_bucket *bucket = virt_irq_to_bucket(virt_irq); + unsigned int ino = bucket - &ivector_table[0]; + + if (likely(bucket)) { + unsigned long cpuid, dev_handle, dev_ino; + int err; + + cpuid = irq_choose_cpu(virt_irq); + + dev_handle = ino & IMAP_IGN; + dev_ino = ino & IMAP_INO; + + err = sun4v_vintr_set_target(dev_handle, dev_ino, cpuid); + if (err != HV_EOK) + printk("sun4v_vintr_set_target(%lx,%lx,%lu): " + "err(%d)\n", + dev_handle, dev_ino, cpuid, err); + } +} + static void sun4v_virq_disable(unsigned int virt_irq) { struct ino_bucket *bucket = virt_irq_to_bucket(virt_irq); @@ -443,6 +496,10 @@ static void sun4v_virq_end(unsigned int virt_irq) { struct ino_bucket *bucket = virt_irq_to_bucket(virt_irq); unsigned int ino = bucket - &ivector_table[0]; + struct irq_desc *desc = irq_desc + virt_irq; + + if (unlikely(desc->status & (IRQ_DISABLED|IRQ_INPROGRESS))) + return; if (likely(bucket)) { unsigned long dev_handle, dev_ino; @@ -477,6 +534,7 @@ static struct irq_chip sun4u_irq = { .enable = sun4u_irq_enable, .disable = sun4u_irq_disable, .end = sun4u_irq_end, + .set_affinity = sun4u_set_affinity, }; static struct irq_chip sun4u_irq_ack = { @@ -485,6 +543,7 @@ static struct irq_chip sun4u_irq_ack = { .disable = sun4u_irq_disable, .ack = run_pre_handler, .end = sun4u_irq_end, + .set_affinity = sun4u_set_affinity, }; static struct irq_chip sun4v_irq = { @@ -492,6 +551,7 @@ static struct irq_chip sun4v_irq = { .enable = sun4v_irq_enable, .disable = sun4v_irq_disable, .end = sun4v_irq_end, + .set_affinity = sun4v_set_affinity, }; static struct irq_chip sun4v_irq_ack = { @@ -500,6 +560,7 @@ static struct irq_chip sun4v_irq_ack = { .disable = sun4v_irq_disable, .ack = run_pre_handler, .end = sun4v_irq_end, + .set_affinity = sun4v_set_affinity, }; #ifdef CONFIG_PCI_MSI @@ -511,6 +572,7 @@ static struct irq_chip sun4v_msi = { .disable = sun4v_msi_disable, .ack = run_pre_handler, .end = sun4v_irq_end, + .set_affinity = sun4v_set_affinity, }; #endif @@ -519,6 +581,7 @@ static struct irq_chip sun4v_virq = { .enable = sun4v_virq_enable, .disable = sun4v_virq_disable, .end = sun4v_virq_end, + .set_affinity = sun4v_virt_set_affinity, }; static struct irq_chip sun4v_virq_ack = { @@ -527,6 +590,7 @@ static struct irq_chip sun4v_virq_ack = { .disable = sun4v_virq_disable, .ack = run_pre_handler, .end = sun4v_virq_end, + .set_affinity = sun4v_virt_set_affinity, }; void irq_install_pre_handler(int virt_irq, @@ -739,6 +803,26 @@ void handler_irq(int irq, struct pt_regs *regs) set_irq_regs(old_regs); } +#ifdef CONFIG_HOTPLUG_CPU +void fixup_irqs(void) +{ + unsigned int irq; + + for (irq = 0; irq < NR_IRQS; irq++) { + unsigned long flags; + + spin_lock_irqsave(&irq_desc[irq].lock, flags); + if (irq_desc[irq].action && + !(irq_desc[irq].status & IRQ_PER_CPU)) { + if (irq_desc[irq].chip->set_affinity) + irq_desc[irq].chip->set_affinity(irq, + irq_desc[irq].affinity); + } + spin_unlock_irqrestore(&irq_desc[irq].lock, flags); + } +} +#endif + struct sun5_timer { u64 count0; u64 limit0; |