commit e0b2077164250c4a8c7e7deebadb94ad633d530a Author: Zbigniew Bodek Date: Wed Apr 25 16:57:18 2012 +0200 powerpc: Use OpenPIC IPI multicasting feature. - Before this commit IPI to more than one CPU was send sequentally one by one to each CPU. However this behaviour caused losing of IPI interrupts. After first IPI request, the OpenPIC IPI channel is busy until interrupt acklownedge and ingnores subsequent requests. This commit enables IPI multicasting which eliminates problem described above by sending IPI to multiple CPUs simultaneously. Also PowerPC PIC API was slighty changed to allow specify more than one CPU in IPI request. diff --git a/sys/powerpc/include/openpicvar.h b/sys/powerpc/include/openpicvar.h index 556dbd3..c5b7976 100644 --- a/sys/powerpc/include/openpicvar.h +++ b/sys/powerpc/include/openpicvar.h @@ -62,7 +62,7 @@ void openpic_config(device_t, u_int, enum intr_trigger, enum intr_polarity); void openpic_dispatch(device_t, struct trapframe *); void openpic_enable(device_t, u_int, u_int); void openpic_eoi(device_t, u_int); -void openpic_ipi(device_t, u_int); +void openpic_ipi(device_t, cpuset_t); void openpic_mask(device_t, u_int); void openpic_unmask(device_t, u_int); diff --git a/sys/powerpc/powerpc/mp_machdep.c b/sys/powerpc/powerpc/mp_machdep.c index 6fc603b..ccaf1a6 100644 --- a/sys/powerpc/powerpc/mp_machdep.c +++ b/sys/powerpc/powerpc/mp_machdep.c @@ -328,47 +328,45 @@ powerpc_ipi_handler(void *arg) return (FILTER_HANDLED); } -static void -ipi_send(struct pcpu *pc, int ipi) -{ - - CTR4(KTR_SMP, "%s: pc=%p, targetcpu=%d, IPI=%d", __func__, - pc, pc->pc_cpuid, ipi); - - atomic_set_32(&pc->pc_ipimask, (1 << ipi)); - PIC_IPI(root_pic, pc->pc_cpuid); - - CTR1(KTR_SMP, "%s: sent", __func__); -} - /* Send an IPI to a set of cpus. */ void ipi_selected(cpuset_t cpus, int ipi) { struct pcpu *pc; + CTR3(KTR_SMP, "%s(): ipi=%d cpus=0x%08X", __func__, ipi, + cpus.__bits[0]); + STAILQ_FOREACH(pc, &cpuhead, pc_allcpu) { if (CPU_ISSET(pc->pc_cpuid, &cpus)) - ipi_send(pc, ipi); + atomic_set_32(&pc->pc_ipimask, (1 << ipi)); } + + PIC_IPI(root_pic, cpus); } /* Send an IPI to a specific CPU. */ void ipi_cpu(int cpu, u_int ipi) { + cpuset_t cpus; + + CTR2(KTR_SMP, "%s(): ipi=%d", __func__, ipi); - ipi_send(cpuid_to_pcpu[cpu], ipi); + CPU_SETOF(cpu, &cpus); + ipi_selected(cpus, ipi); } /* Send an IPI to all CPUs EXCEPT myself. */ void ipi_all_but_self(int ipi) { - struct pcpu *pc; + cpuset_t cpus; - STAILQ_FOREACH(pc, &cpuhead, pc_allcpu) { - if (pc != pcpup) - ipi_send(pc, ipi); - } + CTR2(KTR_SMP, "%s(): ipi=%d", __func__, ipi); + + cpus = all_cpus; + CPU_CLR(PCPU_GET(cpuid), &cpus); + + ipi_selected(cpus, ipi); } diff --git a/sys/powerpc/powerpc/openpic.c b/sys/powerpc/powerpc/openpic.c index f876d38..95af605 100644 --- a/sys/powerpc/powerpc/openpic.c +++ b/sys/powerpc/powerpc/openpic.c @@ -341,7 +341,7 @@ openpic_eoi(device_t dev, u_int irq __unused) } void -openpic_ipi(device_t dev, u_int cpu) +openpic_ipi(device_t dev, cpuset_t cpumask) { struct openpic_softc *sc; @@ -350,7 +350,7 @@ openpic_ipi(device_t dev, u_int cpu) sc = device_get_softc(dev); sched_pin(); openpic_write(sc, OPENPIC_PCPU_IPI_DISPATCH(PCPU_GET(cpuid), 0), - 1u << cpu); + cpumask.__bits[0] & ~0UL); sched_unpin(); } diff --git a/sys/powerpc/powerpc/pic_if.m b/sys/powerpc/powerpc/pic_if.m index 945feca..d86011c 100644 --- a/sys/powerpc/powerpc/pic_if.m +++ b/sys/powerpc/powerpc/pic_if.m @@ -64,7 +64,7 @@ METHOD void eoi { METHOD void ipi { device_t dev; - u_int cpu; + cpuset_t cpumask; }; METHOD void mask {