]> git.karo-electronics.de Git - karo-tx-linux.git/commitdiff
Merge branch 'x86-irq-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git...
authorLinus Torvalds <torvalds@linux-foundation.org>
Fri, 13 Jun 2014 03:03:47 +0000 (20:03 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Fri, 13 Jun 2014 03:03:47 +0000 (20:03 -0700)
Pull x86 irq fixes from Ingo Molnar:
 "Two changes: a cpu-hotplug/irq race fix, plus a HyperV related fix"

* 'x86-irq-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip:
  x86/irq: Fix fixup_irqs() error handling
  x86, irq, pic: Probe for legacy PIC and set legacy_pic appropriately

1  2 
arch/x86/kernel/apic/io_apic.c
arch/x86/kernel/irq.c

index 9d0a9795a0f80e56e7ff9acfd414ee7f5ed44459,b4b21db9f4ade070cc21a0f542aa6e7468e4e07d..81e08eff05eedbd2e839a14229464cbea456e84c
@@@ -206,6 -206,9 +206,6 @@@ int __init arch_early_irq_init(void
        count = ARRAY_SIZE(irq_cfgx);
        node = cpu_to_node(0);
  
 -      /* Make sure the legacy interrupts are marked in the bitmap */
 -      irq_reserve_irqs(0, legacy_pic->nr_legacy_irqs);
 -
        for (i = 0; i < count; i++) {
                irq_set_chip_data(i, &cfg[i]);
                zalloc_cpumask_var_node(&cfg[i].domain, GFP_KERNEL, node);
@@@ -278,6 -281,18 +278,6 @@@ static struct irq_cfg *alloc_irq_and_cf
        return cfg;
  }
  
 -static int alloc_irqs_from(unsigned int from, unsigned int count, int node)
 -{
 -      return irq_alloc_descs_from(from, count, node);
 -}
 -
 -static void free_irq_at(unsigned int at, struct irq_cfg *cfg)
 -{
 -      free_irq_cfg(at, cfg);
 -      irq_free_desc(at);
 -}
 -
 -
  struct io_apic {
        unsigned int index;
        unsigned int unused[3];
@@@ -2174,7 -2189,7 +2174,7 @@@ void send_cleanup_vector(struct irq_cf
        cfg->move_in_progress = 0;
  }
  
 -asmlinkage void smp_irq_move_cleanup_interrupt(void)
 +asmlinkage __visible void smp_irq_move_cleanup_interrupt(void)
  {
        unsigned vector, me;
  
@@@ -2297,7 -2312,7 +2297,7 @@@ int __ioapic_set_affinity(struct irq_da
        int err;
  
        if (!config_enabled(CONFIG_SMP))
-               return -1;
+               return -EPERM;
  
        if (!cpumask_intersects(mask, cpu_online_mask))
                return -EINVAL;
@@@ -2328,7 -2343,7 +2328,7 @@@ int native_ioapic_set_affinity(struct i
        int ret;
  
        if (!config_enabled(CONFIG_SMP))
-               return -1;
+               return -EPERM;
  
        raw_spin_lock_irqsave(&ioapic_lock, flags);
        ret = __ioapic_set_affinity(data, mask, &dest);
@@@ -2901,39 -2916,98 +2901,39 @@@ static int __init ioapic_init_ops(void
  device_initcall(ioapic_init_ops);
  
  /*
 - * Dynamic irq allocate and deallocation
 + * Dynamic irq allocate and deallocation. Should be replaced by irq domains!
   */
 -unsigned int __create_irqs(unsigned int from, unsigned int count, int node)
 +int arch_setup_hwirq(unsigned int irq, int node)
  {
 -      struct irq_cfg **cfg;
 +      struct irq_cfg *cfg;
        unsigned long flags;
 -      int irq, i;
 -
 -      if (from < nr_irqs_gsi)
 -              from = nr_irqs_gsi;
 +      int ret;
  
 -      cfg = kzalloc_node(count * sizeof(cfg[0]), GFP_KERNEL, node);
 +      cfg = alloc_irq_cfg(irq, node);
        if (!cfg)
 -              return 0;
 -
 -      irq = alloc_irqs_from(from, count, node);
 -      if (irq < 0)
 -              goto out_cfgs;
 -
 -      for (i = 0; i < count; i++) {
 -              cfg[i] = alloc_irq_cfg(irq + i, node);
 -              if (!cfg[i])
 -                      goto out_irqs;
 -      }
 +              return -ENOMEM;
  
        raw_spin_lock_irqsave(&vector_lock, flags);
 -      for (i = 0; i < count; i++)
 -              if (__assign_irq_vector(irq + i, cfg[i], apic->target_cpus()))
 -                      goto out_vecs;
 +      ret = __assign_irq_vector(irq, cfg, apic->target_cpus());
        raw_spin_unlock_irqrestore(&vector_lock, flags);
  
 -      for (i = 0; i < count; i++) {
 -              irq_set_chip_data(irq + i, cfg[i]);
 -              irq_clear_status_flags(irq + i, IRQ_NOREQUEST);
 -      }
 -
 -      kfree(cfg);
 -      return irq;
 -
 -out_vecs:
 -      for (i--; i >= 0; i--)
 -              __clear_irq_vector(irq + i, cfg[i]);
 -      raw_spin_unlock_irqrestore(&vector_lock, flags);
 -out_irqs:
 -      for (i = 0; i < count; i++)
 -              free_irq_at(irq + i, cfg[i]);
 -out_cfgs:
 -      kfree(cfg);
 -      return 0;
 -}
 -
 -unsigned int create_irq_nr(unsigned int from, int node)
 -{
 -      return __create_irqs(from, 1, node);
 -}
 -
 -int create_irq(void)
 -{
 -      int node = cpu_to_node(0);
 -      unsigned int irq_want;
 -      int irq;
 -
 -      irq_want = nr_irqs_gsi;
 -      irq = create_irq_nr(irq_want, node);
 -
 -      if (irq == 0)
 -              irq = -1;
 -
 -      return irq;
 +      if (!ret)
 +              irq_set_chip_data(irq, cfg);
 +      else
 +              free_irq_cfg(irq, cfg);
 +      return ret;
  }
  
 -void destroy_irq(unsigned int irq)
 +void arch_teardown_hwirq(unsigned int irq)
  {
        struct irq_cfg *cfg = irq_get_chip_data(irq);
        unsigned long flags;
  
 -      irq_set_status_flags(irq, IRQ_NOREQUEST|IRQ_NOPROBE);
 -
        free_remapped_irq(irq);
 -
        raw_spin_lock_irqsave(&vector_lock, flags);
        __clear_irq_vector(irq, cfg);
        raw_spin_unlock_irqrestore(&vector_lock, flags);
 -      free_irq_at(irq, cfg);
 -}
 -
 -void destroy_irqs(unsigned int irq, unsigned int count)
 -{
 -      unsigned int i;
 -
 -      for (i = 0; i < count; i++)
 -              destroy_irq(irq + i);
 +      free_irq_cfg(irq, cfg);
  }
  
  /*
@@@ -3001,9 -3075,11 +3001,11 @@@ msi_set_affinity(struct irq_data *data
        struct irq_cfg *cfg = data->chip_data;
        struct msi_msg msg;
        unsigned int dest;
+       int ret;
  
-       if (__ioapic_set_affinity(data, mask, &dest))
-               return -1;
+       ret = __ioapic_set_affinity(data, mask, &dest);
+       if (ret)
+               return ret;
  
        __get_cached_msi_msg(data->msi_desc, &msg);
  
@@@ -3062,8 -3138,8 +3064,8 @@@ int setup_msi_irq(struct pci_dev *dev, 
  
  int native_setup_msi_irqs(struct pci_dev *dev, int nvec, int type)
  {
 -      unsigned int irq, irq_want;
        struct msi_desc *msidesc;
 +      unsigned int irq;
        int node, ret;
  
        /* Multiple MSI vectors only supported with interrupt remapping */
                return 1;
  
        node = dev_to_node(&dev->dev);
 -      irq_want = nr_irqs_gsi;
 +
        list_for_each_entry(msidesc, &dev->msi_list, list) {
 -              irq = create_irq_nr(irq_want, node);
 -              if (irq == 0)
 +              irq = irq_alloc_hwirq(node);
 +              if (!irq)
                        return -ENOSPC;
  
 -              irq_want = irq + 1;
 -
                ret = setup_msi_irq(dev, msidesc, irq, 0);
 -              if (ret < 0)
 -                      goto error;
 +              if (ret < 0) {
 +                      irq_free_hwirq(irq);
 +                      return ret;
 +              }
 +
        }
        return 0;
 -
 -error:
 -      destroy_irq(irq);
 -      return ret;
  }
  
  void native_teardown_msi_irq(unsigned int irq)
  {
 -      destroy_irq(irq);
 +      irq_free_hwirq(irq);
  }
  
  #ifdef CONFIG_DMAR_TABLE
@@@ -3100,9 -3179,11 +3102,11 @@@ dmar_msi_set_affinity(struct irq_data *
        struct irq_cfg *cfg = data->chip_data;
        unsigned int dest, irq = data->irq;
        struct msi_msg msg;
+       int ret;
  
-       if (__ioapic_set_affinity(data, mask, &dest))
-               return -1;
+       ret = __ioapic_set_affinity(data, mask, &dest);
+       if (ret)
+               return ret;
  
        dmar_msi_read(irq, &msg);
  
@@@ -3149,9 -3230,11 +3153,11 @@@ static int hpet_msi_set_affinity(struc
        struct irq_cfg *cfg = data->chip_data;
        struct msi_msg msg;
        unsigned int dest;
+       int ret;
  
-       if (__ioapic_set_affinity(data, mask, &dest))
-               return -1;
+       ret = __ioapic_set_affinity(data, mask, &dest);
+       if (ret)
+               return ret;
  
        hpet_msi_read(data->handler_data, &msg);
  
@@@ -3218,9 -3301,11 +3224,11 @@@ ht_set_affinity(struct irq_data *data, 
  {
        struct irq_cfg *cfg = data->chip_data;
        unsigned int dest;
+       int ret;
  
-       if (__ioapic_set_affinity(data, mask, &dest))
-               return -1;
+       ret = __ioapic_set_affinity(data, mask, &dest);
+       if (ret)
+               return ret;
  
        target_ht_irq(data->irq, dest, cfg->vector);
        return IRQ_SET_MASK_OK_NOCOPY;
@@@ -3343,9 -3428,9 +3351,9 @@@ static void __init probe_nr_irqs_gsi(vo
        printk(KERN_DEBUG "nr_irqs_gsi: %d\n", nr_irqs_gsi);
  }
  
 -int get_nr_irqs_gsi(void)
 +unsigned int arch_dynirq_lower_bound(unsigned int from)
  {
 -      return nr_irqs_gsi;
 +      return from < nr_irqs_gsi ? nr_irqs_gsi : from;
  }
  
  int __init arch_probe_nr_irqs(void)
diff --combined arch/x86/kernel/irq.c
index 11ccfb0a63e78d68908440c1690b3f544ee9c6c7,49bbb57da7f581666b06f8db4f5e5a6b6a2f307e..922d285810246aaf4382104d01be52cf6cf31767
@@@ -17,7 -17,6 +17,7 @@@
  #include <asm/idle.h>
  #include <asm/mce.h>
  #include <asm/hw_irq.h>
 +#include <asm/desc.h>
  
  #define CREATE_TRACE_POINTS
  #include <asm/trace/irq_vectors.h>
@@@ -335,17 -334,10 +335,17 @@@ int check_irq_vectors_for_cpu_disable(v
        for_each_online_cpu(cpu) {
                if (cpu == this_cpu)
                        continue;
 -              for (vector = FIRST_EXTERNAL_VECTOR; vector < NR_VECTORS;
 -                   vector++) {
 -                      if (per_cpu(vector_irq, cpu)[vector] < 0)
 -                              count++;
 +              /*
 +               * We scan from FIRST_EXTERNAL_VECTOR to first system
 +               * vector. If the vector is marked in the used vectors
 +               * bitmap or an irq is assigned to it, we don't count
 +               * it as available.
 +               */
 +              for (vector = FIRST_EXTERNAL_VECTOR;
 +                   vector < first_system_vector; vector++) {
 +                      if (!test_bit(vector, used_vectors) &&
 +                          per_cpu(vector_irq, cpu)[vector] < 0)
 +                                      count++;
                }
        }
  
@@@ -365,6 -357,7 +365,7 @@@ void fixup_irqs(void
        struct irq_desc *desc;
        struct irq_data *data;
        struct irq_chip *chip;
+       int ret;
  
        for_each_irq_desc(irq, desc) {
                int break_affinity = 0;
                if (!irqd_can_move_in_process_context(data) && chip->irq_mask)
                        chip->irq_mask(data);
  
-               if (chip->irq_set_affinity)
-                       chip->irq_set_affinity(data, affinity, true);
-               else if (!(warned++))
-                       set_affinity = 0;
+               if (chip->irq_set_affinity) {
+                       ret = chip->irq_set_affinity(data, affinity, true);
+                       if (ret == -ENOSPC)
+                               pr_crit("IRQ %d set affinity failed because there are no available vectors.  The device assigned to this IRQ is unstable.\n", irq);
+               } else {
+                       if (!(warned++))
+                               set_affinity = 0;
+               }
  
                /*
                 * We unmask if the irq was not marked masked by the