Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit ada6814c authored by Keir Fraser's avatar Keir Fraser Committed by Konrad Rzeszutek Wilk
Browse files

xen: events: Clean up round-robin evtchn scan.



Also fixes a couple of boundary cases.

Signed-off-by: default avatarKeir Fraser <keir.fraser@citrix.com>
Signed-off-by: default avatarIan Campbell <ian.campbell@citrix.com>
[ijc: forward ported from linux-2.6.18-xen.hg 988:c88a02a22a05]
Signed-off-by: default avatarKonrad Rzeszutek Wilk <konrad.wilk@oracle.com>
parent f1f4a323
Loading
Loading
Loading
Loading
+20 −24
Original line number Original line Diff line number Diff line
@@ -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, xed_nesting_count);
static DEFINE_PER_CPU(unsigned int, last_word_idx) = { BITS_PER_LONG - 1 };
static DEFINE_PER_CPU(unsigned int, current_word_idx);
static DEFINE_PER_CPU(unsigned int, last_bit_idx) = { BITS_PER_LONG - 1 };
static DEFINE_PER_CPU(unsigned int, current_bit_idx);


/*
/*
 * Mask out the i least significant bits of w
 * Mask out the i least significant bits of w
@@ -1065,23 +1065,21 @@ static void __xen_evtchn_do_upcall(void)
#endif
#endif
		pending_words = xchg(&vcpu_info->evtchn_pending_sel, 0);
		pending_words = xchg(&vcpu_info->evtchn_pending_sel, 0);


		word_idx = __this_cpu_read(last_word_idx);
		word_idx = __this_cpu_read(current_word_idx);
		bit_idx = __this_cpu_read(last_bit_idx);
		bit_idx = __this_cpu_read(current_bit_idx);


		while (pending_words != 0) {
		while (pending_words != 0) {
			unsigned long pending_bits;
			unsigned long pending_bits;
			unsigned long words;
			unsigned long words;


			word_idx = (word_idx + 1) % BITS_PER_LONG;
			words = MASK_LSBS(pending_words, word_idx);
			words = MASK_LSBS(pending_words, word_idx);


			/*
			/*
			 * If we masked out all events, wrap around to the
			 * If we masked out all events, wrap to beginning.
			 * beginning.
			 */
			 */
			if (words == 0) {
			if (words == 0) {
				word_idx = BITS_PER_LONG - 1;
				word_idx = 0;
				bit_idx = BITS_PER_LONG - 1;
				bit_idx = 0;
				continue;
				continue;
			}
			}
			word_idx = __ffs(words);
			word_idx = __ffs(words);
@@ -1093,14 +1091,11 @@ static void __xen_evtchn_do_upcall(void)


				pending_bits = active_evtchns(cpu, s, word_idx);
				pending_bits = active_evtchns(cpu, s, word_idx);


				bit_idx = (bit_idx + 1) % BITS_PER_LONG;
				bits = MASK_LSBS(pending_bits, bit_idx);
				bits = MASK_LSBS(pending_bits, bit_idx);


				/* If we masked out all events, move on. */
				/* If we masked out all events, move on. */
				if (bits == 0) {
				if (bits == 0)
					bit_idx = BITS_PER_LONG - 1;
					break;
					break;
				}


				bit_idx = __ffs(bits);
				bit_idx = __ffs(bits);


@@ -1117,22 +1112,23 @@ static void __xen_evtchn_do_upcall(void)
						generic_handle_irq_desc(irq, desc);
						generic_handle_irq_desc(irq, desc);
				}
				}


				/*
				bit_idx = (bit_idx + 1) % BITS_PER_LONG;
				 * If this is the final port processed, we'll

				 * pick up here+1 next time.
				/* Next caller starts at last processed + 1 */
				 */
				__this_cpu_write(current_word_idx,
				__this_cpu_write(last_word_idx, word_idx);
						 bit_idx ? word_idx :
				__this_cpu_write(last_bit_idx, bit_idx);
						 (word_idx+1) % BITS_PER_LONG);
			} while (bit_idx != BITS_PER_LONG - 1);
				__this_cpu_write(current_bit_idx, bit_idx);
			} while (bit_idx != 0);


			pending_bits = active_evtchns(cpu, s, word_idx);
			pending_bits = active_evtchns(cpu, s, word_idx);


			/*
			/* If we handled all ports, clear the selector bit. */
			 * We handled all ports, so we can clear the
			 * selector bit.
			 */
			if (pending_bits == 0)
			if (pending_bits == 0)
				pending_words &= ~(1UL << word_idx);
				pending_words &= ~(1UL << word_idx);

			word_idx = (word_idx + 1) % BITS_PER_LONG;
			bit_idx = 0;
		}
		}


		BUG_ON(!irqs_disabled());
		BUG_ON(!irqs_disabled());