]> xenbits.xensource.com Git - legacy/linux-2.6.18-xen.git/commitdiff
xen/evtchn: Clean up round-robin evtchn scan.
authorKeir Fraser <keir.fraser@citrix.com>
Fri, 29 Jan 2010 07:57:48 +0000 (07:57 +0000)
committerKeir Fraser <keir.fraser@citrix.com>
Fri, 29 Jan 2010 07:57:48 +0000 (07:57 +0000)
Also fixes a couple of boundary cases.

Signed-off-by: Keir Fraser <keir.fraser@citrix.com>
drivers/xen/core/evtchn.c

index 63ea95739a8dceb02069550c89b82b5cc90bff08..c395ce520139d0150909637bd65b0a219896d6e9 100644 (file)
@@ -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. */