#define PIRQ_NEEDS_EOI       (1 << 0)
   #define PIRQ_SHAREABLE       (1 << 1)
   
-- static struct irq_info *irq_info;
-- static int *pirq_to_irq;
-- 
   static int *evtchn_to_irq;
-- struct cpu_evtchn_s {
--      unsigned long bits[NR_EVENT_CHANNELS/BITS_PER_LONG];
-- };
   
-- static __initdata struct cpu_evtchn_s init_evtchn_mask = {
--      .bits[0 ... (NR_EVENT_CHANNELS/BITS_PER_LONG)-1] = ~0ul,
-- };
-  static struct cpu_evtchn_s __refdata *cpu_evtchn_mask_p = &init_evtchn_mask;
 - static struct cpu_evtchn_s *cpu_evtchn_mask_p = &init_evtchn_mask;
-- 
-- static inline unsigned long *cpu_evtchn_mask(int cpu)
-- {
--      return cpu_evtchn_mask_p[cpu].bits;
-- }
++ static DEFINE_PER_CPU(unsigned long [NR_EVENT_CHANNELS/BITS_PER_LONG],
++                    cpu_evtchn_mask);
   
   /* Xen will never allocate port zero for any purpose. */
   #define VALID_EVTCHN(chn)    ((chn) != 0)
        set_irq_chip_and_handler_name(irq, &xen_pirq_chip,
                                      handle_level_irq, name);
   
--      irq_info[irq] = mk_pirq_info(0, pirq, 0, vector);
--      pirq_to_irq[pirq] = irq;
 -      ret = set_irq_msi(irq, msidesc);
++      xen_irq_info_pirq_init(irq, 0, pirq, 0, vector, 0);
  -     ret = set_irq_msi(irq, msidesc);
 ++     ret = irq_set_msi_desc(irq, msidesc);
        if (ret < 0)
                goto error_irq;
   out:
                wmb();
   #endif
                pending_words = xchg(&vcpu_info->evtchn_pending_sel, 0);
- -             while (pending_words != 0) {
+ +
+ +             start_word_idx = __this_cpu_read(current_word_idx);
+ +             start_bit_idx = __this_cpu_read(current_bit_idx);
+ +
+ +             word_idx = start_word_idx;
+ +
+ +             for (i = 0; pending_words != 0; i++) {
                        unsigned long pending_bits;
- -                     int word_idx = __ffs(pending_words);
- -                     pending_words &= ~(1UL << word_idx);
+ +                     unsigned long words;
  +
-                       while ((pending_bits = active_evtchns(cpu, s, word_idx)) != 0) {
-                               int bit_idx = __ffs(pending_bits);
-                               int port = (word_idx * BITS_PER_LONG) + bit_idx;
-                               int irq = evtchn_to_irq[port];
+ +                     words = MASK_LSBS(pending_words, word_idx);
+ +
+ +                     /*
+ +                      * If we masked out all events, wrap to beginning.
+ +                      */
+ +                     if (words == 0) {
+ +                             word_idx = 0;
+ +                             bit_idx = 0;
+ +                             continue;
+ +                     }
+ +                     word_idx = __ffs(words);
+ +
+ +                     pending_bits = active_evtchns(cpu, s, word_idx);
+ +                     bit_idx = 0; /* usually scan entire word from start */
+ +                     if (word_idx == start_word_idx) {
+ +                             /* We scan the starting word in two parts */
+ +                             if (i == 0)
+ +                                     /* 1st time: start in the middle */
+ +                                     bit_idx = start_bit_idx;
+ +                             else
+ +                                     /* 2nd time: mask bits done already */
+ +                                     bit_idx &= (1UL << start_bit_idx) - 1;
+ +                     }
+  
  -                     while ((pending_bits = active_evtchns(cpu, s, word_idx)) != 0) {
  -                             int bit_idx = __ffs(pending_bits);
  -                             int port = (word_idx * BITS_PER_LONG) + bit_idx;
  -                             int irq = evtchn_to_irq[port];
+ +                     do {
+ +                             unsigned long bits;
+ +                             int port, irq;
                                struct irq_desc *desc;
   
+ +                             bits = MASK_LSBS(pending_bits, bit_idx);
+ +
+ +                             /* If we masked out all events, move on. */
+ +                             if (bits == 0)
+ +                                     break;
+ +
+ +                             bit_idx = __ffs(bits);
+ +
+ +                             /* Process port. */
+ +                             port = (word_idx * BITS_PER_LONG) + bit_idx;
+ +                             irq = evtchn_to_irq[port];
+ +
                                mask_evtchn(port);
                                clear_evtchn(port);