VServer 1.9.2 (patch-2.6.8.1-vs1.9.2.diff)
[linux-2.6.git] / arch / ia64 / kernel / irq.c
index 42056fb..9ec161c 100644 (file)
@@ -87,7 +87,8 @@ irq_desc_t _irq_desc[NR_IRQS] __cacheline_aligned = {
 /*
  * This is updated when the user sets irq affinity via /proc
  */
-cpumask_t    __cacheline_aligned pending_irq_cpumask[NR_IRQS];
+cpumask_t __cacheline_aligned pending_irq_cpumask[NR_IRQS];
+static unsigned long pending_irq_redir[BITS_TO_LONGS(NR_IRQS)];
 
 #ifdef CONFIG_IA64_GENERIC
 irq_desc_t * __ia64_irq_desc (unsigned int irq)
@@ -607,7 +608,7 @@ int request_irq(unsigned int irq,
 
        action->handler = handler;
        action->flags = irqflags;
-       action->mask = 0;
+       cpus_clear(action->mask);
        action->name = devname;
        action->next = NULL;
        action->dev_id = dev_id;
@@ -973,6 +974,7 @@ static int irq_affinity_write_proc (struct file *file, const char *buffer,
        int prelen;
        irq_desc_t *desc = irq_descp(irq);
        unsigned long flags;
+       int redir = 0;
 
        if (!desc->handler->set_affinity)
                return -EIO;
@@ -995,7 +997,7 @@ static int irq_affinity_write_proc (struct file *file, const char *buffer,
        prelen = 0;
        if (tolower(*rbuf) == 'r') {
                prelen = strspn(rbuf, "Rr ");
-               irq |= IA64_IRQ_REDIRECTED;
+               redir++;
        }
 
        err = cpumask_parse(buffer+prelen, count-prelen, new_value);
@@ -1013,11 +1015,33 @@ static int irq_affinity_write_proc (struct file *file, const char *buffer,
 
        spin_lock_irqsave(&desc->lock, flags);
        pending_irq_cpumask[irq] = new_value;
+       if (redir)
+               set_bit(irq, pending_irq_redir);
+       else
+               clear_bit(irq, pending_irq_redir);
        spin_unlock_irqrestore(&desc->lock, flags);
 
        return full_count;
 }
 
+void move_irq(int irq)
+{
+       /* note - we hold desc->lock */
+       cpumask_t tmp;
+       irq_desc_t *desc = irq_descp(irq);
+       int redir = test_bit(irq, pending_irq_redir);
+
+       if (!cpus_empty(pending_irq_cpumask[irq])) {
+               cpus_and(tmp, pending_irq_cpumask[irq], cpu_online_map);
+               if (unlikely(!cpus_empty(tmp))) {
+                       desc->handler->set_affinity(irq | (redir ? IA64_IRQ_REDIRECTED : 0),
+                                                   pending_irq_cpumask[irq]);
+               }
+               cpus_clear(pending_irq_cpumask[irq]);
+       }
+}
+
+
 #endif /* CONFIG_SMP */
 
 #ifdef CONFIG_HOTPLUG_CPU