From c71425db1defba63a53be54890e7405c56a072d6 Mon Sep 17 00:00:00 2001 From: andrew Date: Thu, 1 Oct 2015 12:09:05 +0000 Subject: [PATCH] An IPI must be cleared before it is handled otherwise next IPI could be missed. In other words, if a new request for an IPI is sent while the previous request is being handled but the IPI is not cleared yet, the clearing of the previous IPI request also clears the new one and the handling is missed. There are only three MP interrupt controllers in ARM now. Two of them are fixed by this change, the third one is correct, probably only just by accident. The fix is minimalistic as new interrupt framework is awaited. It was debugged on RPi2 where missing IPI handling together with SCHED_ULE led to situation in which tdq_ipipending was not cleared and so IPI_PREEMPT was stopped to be sent. Various odditys were found related to slow system response time like various events timed out, and slow console response. Submitted by: Svatopluk Kraus Reviewed by: loos, kib MFC after: 1 week Differential Revision: https://reviews.freebsd.org/D3722 --- sys/arm/broadcom/bcm2835/bcm2836_mp.c | 8 ++------ sys/arm/mv/mpic.c | 12 ++++++------ 2 files changed, 8 insertions(+), 12 deletions(-) diff --git a/sys/arm/broadcom/bcm2835/bcm2836_mp.c b/sys/arm/broadcom/bcm2835/bcm2836_mp.c index 717f24208cf2..93cc0d862d86 100644 --- a/sys/arm/broadcom/bcm2835/bcm2836_mp.c +++ b/sys/arm/broadcom/bcm2835/bcm2836_mp.c @@ -182,6 +182,8 @@ pic_ipi_read(int i) if (val == 0) return (0); ipi = ffs(val) - 1; + BSWR4(MBOX0CLR_CORE(cpu), 1 << ipi); + dsb(); return (ipi); } return (0x3ff); @@ -190,12 +192,6 @@ pic_ipi_read(int i) void pic_ipi_clear(int ipi) { - int cpu; - - cpu = PCPU_GET(cpuid); - dsb(); - BSWR4(MBOX0CLR_CORE(cpu), 1 << ipi); - wmb(); } void diff --git a/sys/arm/mv/mpic.c b/sys/arm/mv/mpic.c index bfb55544ad76..7eb5d2a022b0 100644 --- a/sys/arm/mv/mpic.c +++ b/sys/arm/mv/mpic.c @@ -378,10 +378,14 @@ int pic_ipi_read(int i __unused) { uint32_t val; + int ipi; val = MPIC_CPU_READ(mv_mpic_sc, MPIC_IN_DRBL); - if (val) - return (ffs(val) - 1); + if (val) { + ipi = ffs(val) - 1; + MPIC_CPU_WRITE(mv_mpic_sc, MPIC_IN_DRBL, ~(1 << ipi)); + return (ipi); + } return (0x3ff); } @@ -389,10 +393,6 @@ pic_ipi_read(int i __unused) void pic_ipi_clear(int ipi) { - uint32_t val; - - val = ~(1 << ipi); - MPIC_CPU_WRITE(mv_mpic_sc, MPIC_IN_DRBL, val); } #endif -- 2.39.5