diff options
author | Keir Fraser <keir.fraser@citrix.com> | 2011-03-03 10:01:11 +0000 |
---|---|---|
committer | Konrad Rzeszutek Wilk <konrad.wilk@oracle.com> | 2011-03-10 14:47:57 -0500 |
commit | ada6814c878c4d95fc8ca1402e49effbf3cc319a (patch) | |
tree | c78472cc7d08176e9d03533e7a666f4e8d73b09e /drivers/xen/events.c | |
parent | f1f4a323d46c90632a4d35d34f1d347ca7cb65f5 (diff) | |
download | lwn-ada6814c878c4d95fc8ca1402e49effbf3cc319a.tar.gz lwn-ada6814c878c4d95fc8ca1402e49effbf3cc319a.zip |
xen: events: Clean up round-robin evtchn scan.
Also fixes a couple of boundary cases.
Signed-off-by: Keir Fraser <keir.fraser@citrix.com>
Signed-off-by: Ian Campbell <ian.campbell@citrix.com>
[ijc: forward ported from linux-2.6.18-xen.hg 988:c88a02a22a05]
Signed-off-by: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>
Diffstat (limited to 'drivers/xen/events.c')
-rw-r--r-- | drivers/xen/events.c | 44 |
1 files changed, 20 insertions, 24 deletions
diff --git a/drivers/xen/events.c b/drivers/xen/events.c index 1fc3192468ef..c49cb6d6b838 100644 --- a/drivers/xen/events.c +++ b/drivers/xen/events.c @@ -1026,8 +1026,8 @@ irqreturn_t xen_debug_interrupt(int irq, void *dev_id) } static DEFINE_PER_CPU(unsigned, xed_nesting_count); -static DEFINE_PER_CPU(unsigned int, last_word_idx) = { BITS_PER_LONG - 1 }; -static DEFINE_PER_CPU(unsigned int, last_bit_idx) = { BITS_PER_LONG - 1 }; +static DEFINE_PER_CPU(unsigned int, current_word_idx); +static DEFINE_PER_CPU(unsigned int, current_bit_idx); /* * Mask out the i least significant bits of w @@ -1065,23 +1065,21 @@ static void __xen_evtchn_do_upcall(void) #endif pending_words = xchg(&vcpu_info->evtchn_pending_sel, 0); - word_idx = __this_cpu_read(last_word_idx); - bit_idx = __this_cpu_read(last_bit_idx); + word_idx = __this_cpu_read(current_word_idx); + bit_idx = __this_cpu_read(current_bit_idx); while (pending_words != 0) { unsigned long pending_bits; unsigned long words; - word_idx = (word_idx + 1) % BITS_PER_LONG; words = MASK_LSBS(pending_words, word_idx); /* - * If we masked out all events, wrap around to the - * beginning. + * If we masked out all events, wrap to beginning. */ if (words == 0) { - word_idx = BITS_PER_LONG - 1; - bit_idx = BITS_PER_LONG - 1; + word_idx = 0; + bit_idx = 0; continue; } word_idx = __ffs(words); @@ -1093,14 +1091,11 @@ static void __xen_evtchn_do_upcall(void) pending_bits = active_evtchns(cpu, s, word_idx); - bit_idx = (bit_idx + 1) % BITS_PER_LONG; bits = MASK_LSBS(pending_bits, bit_idx); /* If we masked out all events, move on. */ - if (bits == 0) { - bit_idx = BITS_PER_LONG - 1; + if (bits == 0) break; - } bit_idx = __ffs(bits); @@ -1117,22 +1112,23 @@ static void __xen_evtchn_do_upcall(void) generic_handle_irq_desc(irq, desc); } - /* - * If this is the final port processed, we'll - * pick up here+1 next time. - */ - __this_cpu_write(last_word_idx, word_idx); - __this_cpu_write(last_bit_idx, bit_idx); - } while (bit_idx != BITS_PER_LONG - 1); + bit_idx = (bit_idx + 1) % BITS_PER_LONG; + + /* Next caller starts at last processed + 1 */ + __this_cpu_write(current_word_idx, + bit_idx ? word_idx : + (word_idx+1) % BITS_PER_LONG); + __this_cpu_write(current_bit_idx, bit_idx); + } while (bit_idx != 0); pending_bits = active_evtchns(cpu, s, word_idx); - /* - * We handled all ports, so we can clear the - * selector bit. - */ + /* If we handled all ports, clear the selector bit. */ if (pending_bits == 0) pending_words &= ~(1UL << word_idx); + + word_idx = (word_idx + 1) % BITS_PER_LONG; + bit_idx = 0; } BUG_ON(!irqs_disabled()); |