Merge branch 'irq-core-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git...
authorLinus Torvalds <torvalds@linux-foundation.org>
Wed, 26 Oct 2011 14:44:09 +0000 (16:44 +0200)
committerLinus Torvalds <torvalds@linux-foundation.org>
Wed, 26 Oct 2011 14:44:09 +0000 (16:44 +0200)
* 'irq-core-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip:
  genirq: Add IRQF_RESUME_EARLY and resume such IRQs earlier
  genirq: Fix fatfinered fixup really
  genirq: percpu: allow interrupt type to be set at enable time
  genirq: Add support for per-cpu dev_id interrupts
  genirq: Add IRQCHIP_SKIP_SET_WAKE flag

1  2 
drivers/xen/events.c

diff --combined drivers/xen/events.c
@@@ -54,7 -54,7 +54,7 @@@
   * This lock protects updates to the following mapping and reference-count
   * arrays. The lock does not need to be acquired to read the mapping tables.
   */
 -static DEFINE_SPINLOCK(irq_mapping_update_lock);
 +static DEFINE_MUTEX(irq_mapping_update_lock);
  
  static LIST_HEAD(xen_irq_list_head);
  
@@@ -432,8 -432,7 +432,8 @@@ static int __must_check xen_allocate_ir
  
        irq = irq_alloc_desc_from(first, -1);
  
 -      xen_irq_init(irq);
 +      if (irq >= 0)
 +              xen_irq_init(irq);
  
        return irq;
  }
@@@ -632,7 -631,7 +632,7 @@@ int xen_bind_pirq_gsi_to_irq(unsigned g
        int irq = -1;
        struct physdev_irq irq_op;
  
 -      spin_lock(&irq_mapping_update_lock);
 +      mutex_lock(&irq_mapping_update_lock);
  
        irq = find_irq_by_gsi(gsi);
        if (irq != -1) {
                                handle_edge_irq, name);
  
  out:
 -      spin_unlock(&irq_mapping_update_lock);
 +      mutex_unlock(&irq_mapping_update_lock);
  
        return irq;
  }
@@@ -711,10 -710,10 +711,10 @@@ int xen_bind_pirq_msi_to_irq(struct pci
  {
        int irq, ret;
  
 -      spin_lock(&irq_mapping_update_lock);
 +      mutex_lock(&irq_mapping_update_lock);
  
        irq = xen_allocate_irq_dynamic();
 -      if (irq == -1)
 +      if (irq < 0)
                goto out;
  
        irq_set_chip_and_handler_name(irq, &xen_pirq_chip, handle_edge_irq,
        if (ret < 0)
                goto error_irq;
  out:
 -      spin_unlock(&irq_mapping_update_lock);
 +      mutex_unlock(&irq_mapping_update_lock);
        return irq;
  error_irq:
 -      spin_unlock(&irq_mapping_update_lock);
 +      mutex_unlock(&irq_mapping_update_lock);
        xen_free_irq(irq);
 -      return -1;
 +      return ret;
  }
  #endif
  
@@@ -741,7 -740,7 +741,7 @@@ int xen_destroy_irq(int irq
        struct irq_info *info = info_for_irq(irq);
        int rc = -ENOENT;
  
 -      spin_lock(&irq_mapping_update_lock);
 +      mutex_lock(&irq_mapping_update_lock);
  
        desc = irq_to_desc(irq);
        if (!desc)
        xen_free_irq(irq);
  
  out:
 -      spin_unlock(&irq_mapping_update_lock);
 +      mutex_unlock(&irq_mapping_update_lock);
        return rc;
  }
  
@@@ -777,10 -776,10 +777,10 @@@ int xen_irq_from_pirq(unsigned pirq
  
        struct irq_info *info;
  
 -      spin_lock(&irq_mapping_update_lock);
 +      mutex_lock(&irq_mapping_update_lock);
  
        list_for_each_entry(info, &xen_irq_list_head, list) {
 -              if (info == NULL || info->type != IRQT_PIRQ)
 +              if (info->type != IRQT_PIRQ)
                        continue;
                irq = info->irq;
                if (info->u.pirq.pirq == pirq)
        }
        irq = -1;
  out:
 -      spin_unlock(&irq_mapping_update_lock);
 +      mutex_unlock(&irq_mapping_update_lock);
  
        return irq;
  }
@@@ -803,7 -802,7 +803,7 @@@ int bind_evtchn_to_irq(unsigned int evt
  {
        int irq;
  
 -      spin_lock(&irq_mapping_update_lock);
 +      mutex_lock(&irq_mapping_update_lock);
  
        irq = evtchn_to_irq[evtchn];
  
        }
  
  out:
 -      spin_unlock(&irq_mapping_update_lock);
 +      mutex_unlock(&irq_mapping_update_lock);
  
        return irq;
  }
@@@ -830,7 -829,7 +830,7 @@@ static int bind_ipi_to_irq(unsigned in
        struct evtchn_bind_ipi bind_ipi;
        int evtchn, irq;
  
 -      spin_lock(&irq_mapping_update_lock);
 +      mutex_lock(&irq_mapping_update_lock);
  
        irq = per_cpu(ipi_to_irq, cpu)[ipi];
  
        }
  
   out:
 -      spin_unlock(&irq_mapping_update_lock);
 +      mutex_unlock(&irq_mapping_update_lock);
        return irq;
  }
  
@@@ -873,34 -872,13 +873,34 @@@ static int bind_interdomain_evtchn_to_i
        return err ? : bind_evtchn_to_irq(bind_interdomain.local_port);
  }
  
 +static int find_virq(unsigned int virq, unsigned int cpu)
 +{
 +      struct evtchn_status status;
 +      int port, rc = -ENOENT;
 +
 +      memset(&status, 0, sizeof(status));
 +      for (port = 0; port <= NR_EVENT_CHANNELS; port++) {
 +              status.dom = DOMID_SELF;
 +              status.port = port;
 +              rc = HYPERVISOR_event_channel_op(EVTCHNOP_status, &status);
 +              if (rc < 0)
 +                      continue;
 +              if (status.status != EVTCHNSTAT_virq)
 +                      continue;
 +              if (status.u.virq == virq && status.vcpu == cpu) {
 +                      rc = port;
 +                      break;
 +              }
 +      }
 +      return rc;
 +}
  
  int bind_virq_to_irq(unsigned int virq, unsigned int cpu)
  {
        struct evtchn_bind_virq bind_virq;
 -      int evtchn, irq;
 +      int evtchn, irq, ret;
  
 -      spin_lock(&irq_mapping_update_lock);
 +      mutex_lock(&irq_mapping_update_lock);
  
        irq = per_cpu(virq_to_irq, cpu)[virq];
  
  
                bind_virq.virq = virq;
                bind_virq.vcpu = cpu;
 -              if (HYPERVISOR_event_channel_op(EVTCHNOP_bind_virq,
 -                                              &bind_virq) != 0)
 -                      BUG();
 -              evtchn = bind_virq.port;
 +              ret = HYPERVISOR_event_channel_op(EVTCHNOP_bind_virq,
 +                                              &bind_virq);
 +              if (ret == 0)
 +                      evtchn = bind_virq.port;
 +              else {
 +                      if (ret == -EEXIST)
 +                              ret = find_virq(virq, cpu);
 +                      BUG_ON(ret < 0);
 +                      evtchn = ret;
 +              }
  
                xen_irq_info_virq_init(cpu, irq, evtchn, virq);
  
        }
  
  out:
 -      spin_unlock(&irq_mapping_update_lock);
 +      mutex_unlock(&irq_mapping_update_lock);
  
        return irq;
  }
@@@ -941,7 -913,7 +941,7 @@@ static void unbind_from_irq(unsigned in
        struct evtchn_close close;
        int evtchn = evtchn_from_irq(irq);
  
 -      spin_lock(&irq_mapping_update_lock);
 +      mutex_lock(&irq_mapping_update_lock);
  
        if (VALID_EVTCHN(evtchn)) {
                close.port = evtchn;
  
        xen_free_irq(irq);
  
 -      spin_unlock(&irq_mapping_update_lock);
 +      mutex_unlock(&irq_mapping_update_lock);
  }
  
  int bind_evtchn_to_irqhandler(unsigned int evtchn,
@@@ -1049,7 -1021,7 +1049,7 @@@ int bind_ipi_to_irqhandler(enum ipi_vec
        if (irq < 0)
                return irq;
  
-       irqflags |= IRQF_NO_SUSPEND | IRQF_FORCE_RESUME;
+       irqflags |= IRQF_NO_SUSPEND | IRQF_FORCE_RESUME | IRQF_EARLY_RESUME;
        retval = request_irq(irq, handler, irqflags, devname, dev_id);
        if (retval != 0) {
                unbind_from_irq(irq);
@@@ -1307,7 -1279,7 +1307,7 @@@ void rebind_evtchn_irq(int evtchn, int 
           will also be masked. */
        disable_irq(irq);
  
 -      spin_lock(&irq_mapping_update_lock);
 +      mutex_lock(&irq_mapping_update_lock);
  
        /* After resume the irq<->evtchn mappings are all cleared out */
        BUG_ON(evtchn_to_irq[evtchn] != -1);
  
        xen_irq_info_evtchn_init(irq, evtchn);
  
 -      spin_unlock(&irq_mapping_update_lock);
 +      mutex_unlock(&irq_mapping_update_lock);
  
        /* new event channels are always bound to cpu 0 */
        irq_set_affinity(irq, cpumask_of(0));
@@@ -1698,7 -1670,6 +1698,7 @@@ void __init xen_init_IRQ(void
  
        evtchn_to_irq = kcalloc(NR_EVENT_CHANNELS, sizeof(*evtchn_to_irq),
                                    GFP_KERNEL);
 +      BUG_ON(!evtchn_to_irq);
        for (i = 0; i < NR_EVENT_CHANNELS; i++)
                evtchn_to_irq[i] = -1;