It is possible that in the following order, one irq is resent twice:
CPU 1 CPU 2
ics_check_resend()
lock ics_lock
see resend set
unlock ics_lock
/* change affinity of the irq */
kvmppc_xics_set_xive()
write_xive()
lock ics_lock
see resend set
unlock ics_lock
icp_deliver_irq() /* resend */
icp_deliver_irq() /* resend again */
It doesn't have any user-visible effect at present, but needs to be avoided
when the following patch implementing the P/Q stuff is applied.
This patch clears the resend flag before releasing the ics lock, when we
know we will do a re-delivery after checking the flag, or setting the flag.
Signed-off-by: Li Zhong <zhong@linux.vnet.ibm.com>
Signed-off-by: Paul Mackerras <paulus@ozlabs.org>
if (!state->resend)
continue;
+ state->resend = 0;
+
arch_spin_unlock(&ics->lock);
icp_rm_deliver_irq(xics, icp, state->number);
arch_spin_lock(&ics->lock);
*/
smp_mb();
if (!icp->state.need_resend) {
+ state->resend = 0;
arch_spin_unlock(&ics->lock);
goto again;
}
if (!state->resend)
continue;
+ state->resend = 0;
+
XICS_DBG("resend %#x prio %#x\n", state->number,
state->priority);
deliver = false;
if ((state->masked_pending || state->resend) && priority != MASKED) {
state->masked_pending = 0;
+ state->resend = 0;
deliver = true;
}
*/
smp_mb();
if (!icp->state.need_resend) {
+ state->resend = 0;
arch_spin_unlock(&ics->lock);
local_irq_restore(flags);
goto again;