From: Keir Fraser Date: Fri, 29 Jan 2010 07:57:48 +0000 (+0000) Subject: xen/evtchn: Clean up round-robin evtchn scan. X-Git-Url: http://xenbits.xensource.com/gitweb?a=commitdiff_plain;h=07e336d0808476acff9c7d409c364360c641bee2;p=legacy%2Flinux-2.6.18-xen.git xen/evtchn: Clean up round-robin evtchn scan. Also fixes a couple of boundary cases. Signed-off-by: Keir Fraser --- diff --git a/drivers/xen/core/evtchn.c b/drivers/xen/core/evtchn.c index 63ea9573..c395ce52 100644 --- a/drivers/xen/core/evtchn.c +++ b/drivers/xen/core/evtchn.c @@ -229,9 +229,9 @@ void force_evtchn_callback(void) /* Not a GPL symbol: used in ubiquitous macros, so too restrictive. */ EXPORT_SYMBOL(force_evtchn_callback); -static DEFINE_PER_CPU(unsigned int, upcall_count) = { 0 }; -static DEFINE_PER_CPU(unsigned int, last_processed_l1i) = { BITS_PER_LONG - 1 }; -static DEFINE_PER_CPU(unsigned int, last_processed_l2i) = { BITS_PER_LONG - 1 }; +static DEFINE_PER_CPU(unsigned int, upcall_count); +static DEFINE_PER_CPU(unsigned int, current_l1i); +static DEFINE_PER_CPU(unsigned int, current_l2i); /* NB. Interrupts are disabled on entry. */ asmlinkage void evtchn_do_upcall(struct pt_regs *regs) @@ -261,32 +261,23 @@ asmlinkage void evtchn_do_upcall(struct pt_regs *regs) #endif l1 = xchg(&vcpu_info->evtchn_pending_sel, 0); - l1i = per_cpu(last_processed_l1i, cpu); - l2i = per_cpu(last_processed_l2i, cpu); + l1i = per_cpu(current_l1i, cpu); + l2i = per_cpu(current_l2i, cpu); while (l1 != 0) { - - l1i = (l1i + 1) % BITS_PER_LONG; masked_l1 = l1 & ((~0UL) << l1i); - - if (masked_l1 == 0) { /* if we masked out all events, wrap around to the beginning */ - l1i = BITS_PER_LONG - 1; - l2i = BITS_PER_LONG - 1; + /* If we masked out all events, wrap to beginning. */ + if (masked_l1 == 0) { + l1i = l2i = 0; continue; } l1i = __ffs(masked_l1); do { l2 = active_evtchns(cpu, s, l1i); - - l2i = (l2i + 1) % BITS_PER_LONG; masked_l2 = l2 & ((~0UL) << l2i); - - if (masked_l2 == 0) { /* if we masked out all events, move on */ - l2i = BITS_PER_LONG - 1; + if (masked_l2 == 0) break; - } - l2i = __ffs(masked_l2); /* process port */ @@ -296,16 +287,22 @@ asmlinkage void evtchn_do_upcall(struct pt_regs *regs) else evtchn_device_upcall(port); - /* if this is the final port processed, we'll pick up here+1 next time */ - per_cpu(last_processed_l1i, cpu) = l1i; - per_cpu(last_processed_l2i, cpu) = l2i; + l2i = (l2i + 1) % BITS_PER_LONG; - } while (l2i != BITS_PER_LONG - 1); + /* Next caller starts at last processed + 1 */ + per_cpu(current_l1i, cpu) = + l2i ? l1i : (l1i + 1) % BITS_PER_LONG; + per_cpu(current_l2i, cpu) = l2i; + + } while (l2i != 0); l2 = active_evtchns(cpu, s, l1i); - if (l2 == 0) /* we handled all ports, so we can clear the selector bit */ + /* If we handled all ports, clear the selector bit. */ + if (l2 == 0) l1 &= ~(1UL << l1i); + l1i = (l1i + 1) % BITS_PER_LONG; + l2i = 0; } /* If there were nested callbacks then we have more to do. */