From ada6814c878c4d95fc8ca1402e49effbf3cc319a Mon Sep 17 00:00:00 2001 From: Keir Fraser Date: Thu, 3 Mar 2011 10:01:11 +0000 Subject: [PATCH] xen: events: Clean up round-robin evtchn scan. Also fixes a couple of boundary cases. Signed-off-by: Keir Fraser Signed-off-by: Ian Campbell [ijc: forward ported from linux-2.6.18-xen.hg 988:c88a02a22a05] Signed-off-by: Konrad Rzeszutek Wilk --- drivers/xen/events.c | 44 ++++++++++++++++++++------------------------ 1 file 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()); -- 2.34.1