]> xenbits.xensource.com Git - people/julieng/freebsd.git/commitdiff
An IPI must be cleared before it is handled otherwise next IPI could be
authorandrew <andrew@FreeBSD.org>
Thu, 1 Oct 2015 12:09:05 +0000 (12:09 +0000)
committerandrew <andrew@FreeBSD.org>
Thu, 1 Oct 2015 12:09:05 +0000 (12:09 +0000)
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 <onwahe@gmail.com>
Reviewed by: loos, kib
MFC after: 1 week
Differential Revision: https://reviews.freebsd.org/D3722

sys/arm/broadcom/bcm2835/bcm2836_mp.c
sys/arm/mv/mpic.c

index 717f24208cf20272632056fef939d14112fcbbcd..93cc0d862d86d777d77a1deea4d9b7f5e5ec9c6e 100644 (file)
@@ -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
index bfb55544ad765fcf72c9103b0c90082cdc57687c..7eb5d2a022b0de11f5b66140e2bb082e460fac6a 100644 (file)
@@ -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