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 <onwahe@gmail.com>
Reviewed by:	loos, kib
MFC after:	1 week
Differential Revision:	https://reviews.freebsd.org/D3722
This commit is contained in:
Andrew Turner 2015-10-01 12:09:05 +00:00
parent 2eb0015ab7
commit 17fb49c1e4
2 changed files with 8 additions and 12 deletions

View 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

View 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