ia64/xen-unstable

changeset 16881:3f5dec2011b0

[PV-on-HVM] Process event channels notifications in round-robin order
Signed-off-by: Takanori Kasai <kasai.takanori@jp.fujitsu.com>
Signed-off-by: Kouya Shimura <kouya@jp.fujitsu.com>
author Keir Fraser <keir.fraser@citrix.com>
date Fri Jan 25 13:23:39 2008 +0000 (2008-01-25)
parents 78a29cf8476b
children b321ef006189
files unmodified_drivers/linux-2.6/platform-pci/evtchn.c
line diff
     1.1 --- a/unmodified_drivers/linux-2.6/platform-pci/evtchn.c	Fri Jan 25 13:22:52 2008 +0000
     1.2 +++ b/unmodified_drivers/linux-2.6/platform-pci/evtchn.c	Fri Jan 25 13:23:39 2008 +0000
     1.3 @@ -254,6 +254,15 @@ void notify_remote_via_irq(int irq)
     1.4  }
     1.5  EXPORT_SYMBOL(notify_remote_via_irq);
     1.6  
     1.7 +static DEFINE_PER_CPU(unsigned int, last_processed_l1i) = { BITS_PER_LONG - 1 };
     1.8 +static DEFINE_PER_CPU(unsigned int, last_processed_l2i) = { BITS_PER_LONG - 1 };
     1.9 +
    1.10 +static inline unsigned long active_evtchns(unsigned int cpu, shared_info_t *sh,
    1.11 +						unsigned int idx)
    1.12 +{
    1.13 +	return (sh->evtchn_pending[idx] & ~sh->evtchn_mask[idx]);
    1.14 +}
    1.15 +
    1.16  static irqreturn_t evtchn_interrupt(int irq, void *dev_id
    1.17  #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,19)
    1.18  				    , struct pt_regs *regs
    1.19 @@ -262,7 +271,8 @@ static irqreturn_t evtchn_interrupt(int 
    1.20  #endif
    1.21  				    )
    1.22  {
    1.23 -	unsigned int l1i, port;
    1.24 +	unsigned int l1i, l2i, port;
    1.25 +	unsigned long masked_l1, masked_l2;
    1.26  	/* XXX: All events are bound to vcpu0 but irq may be redirected. */
    1.27  	int cpu = 0; /*smp_processor_id();*/
    1.28  	irq_handler_t handler;
    1.29 @@ -271,13 +281,42 @@ static irqreturn_t evtchn_interrupt(int 
    1.30  	unsigned long l1, l2;
    1.31  
    1.32  	v->evtchn_upcall_pending = 0;
    1.33 -	/* NB. No need for a barrier here -- XCHG is a barrier on x86. */
    1.34 +
    1.35 +#ifndef CONFIG_X86 /* No need for a barrier -- XCHG is a barrier on x86. */
    1.36 +	/* Clear master flag /before/ clearing selector flag. */
    1.37 +	rmb();
    1.38 +#endif
    1.39  	l1 = xchg(&v->evtchn_pending_sel, 0);
    1.40 +
    1.41 +	l1i = per_cpu(last_processed_l1i, cpu);
    1.42 +	l2i = per_cpu(last_processed_l2i, cpu);
    1.43 +
    1.44  	while (l1 != 0) {
    1.45 -		l1i = __ffs(l1);
    1.46 -		l1 &= ~(1 << l1i);
    1.47 -		while ((l2 = s->evtchn_pending[l1i] & ~s->evtchn_mask[l1i])) {
    1.48 -			port = (l1i * BITS_PER_LONG) + __ffs(l2);
    1.49 +
    1.50 +		l1i = (l1i + 1) % BITS_PER_LONG;
    1.51 +		masked_l1 = l1 & ((~0UL) << l1i);
    1.52 +
    1.53 +		if (masked_l1 == 0) { /* if we masked out all events, wrap around to the beginning */
    1.54 +			l1i = BITS_PER_LONG - 1;
    1.55 +			l2i = BITS_PER_LONG - 1;
    1.56 +			continue;
    1.57 +		}
    1.58 +		l1i = __ffs(masked_l1);
    1.59 +
    1.60 +		do {
    1.61 +			l2 = active_evtchns(cpu, s, l1i);
    1.62 +
    1.63 +			l2i = (l2i + 1) % BITS_PER_LONG;
    1.64 +			masked_l2 = l2 & ((~0UL) << l2i);
    1.65 +
    1.66 +			if (masked_l2 == 0) { /* if we masked out all events, move on */
    1.67 +				l2i = BITS_PER_LONG - 1;
    1.68 +				break;
    1.69 +			}
    1.70 +			l2i = __ffs(masked_l2);
    1.71 +
    1.72 +			/* process port */
    1.73 +			port = (l1i * BITS_PER_LONG) + l2i;
    1.74  			synch_clear_bit(port, &s->evtchn_pending[0]);
    1.75  
    1.76  			irq = evtchn_to_irq[port];
    1.77 @@ -303,7 +342,16 @@ static irqreturn_t evtchn_interrupt(int 
    1.78  			spin_lock(&irq_evtchn[irq].lock);
    1.79  			irq_evtchn[irq].in_handler = 0;
    1.80  			spin_unlock(&irq_evtchn[irq].lock);
    1.81 -		}
    1.82 +
    1.83 +			/* if this is the final port processed, we'll pick up here+1 next time */
    1.84 +			per_cpu(last_processed_l1i, cpu) = l1i;
    1.85 +			per_cpu(last_processed_l2i, cpu) = l2i;
    1.86 +
    1.87 +		} while (l2i != BITS_PER_LONG - 1);
    1.88 +
    1.89 +		l2 = active_evtchns(cpu, s, l1i);
    1.90 +		if (l2 == 0) /* we handled all ports, so we can clear the selector bit */
    1.91 +			l1 &= ~(1UL << l1i);
    1.92  	}
    1.93  
    1.94  	return IRQ_HANDLED;