x86, ioapic: Get rid of needless check and simplify ioapic_setup_resources()
[safe/jmp/linux-2.6] / arch / x86 / kernel / apic / io_apic.c
index cf51b0b..d836b4d 100644 (file)
@@ -66,6 +66,8 @@
 #include <asm/apic.h>
 
 #define __apicdebuginit(type) static type __init
+#define for_each_irq_pin(entry, head) \
+       for (entry = head; entry; entry = entry->next)
 
 /*
  *      Is the SiS APIC rmw bug present ?
@@ -410,7 +412,7 @@ static bool io_apic_level_ack_pending(struct irq_cfg *cfg)
        unsigned long flags;
 
        spin_lock_irqsave(&ioapic_lock, flags);
-       for (entry = cfg->irq_2_pin; entry != NULL; entry = entry->next) {
+       for_each_irq_pin(entry, cfg->irq_2_pin) {
                unsigned int reg;
                int pin;
 
@@ -488,24 +490,36 @@ static void ioapic_mask_entry(int apic, int pin)
  * shared ISA-space IRQs, so we have to support them. We are super
  * fast in the common case, and fast for shared ISA-space IRQs.
  */
-static void add_pin_to_irq_node(struct irq_cfg *cfg, int node, int apic, int pin)
+static int
+add_pin_to_irq_node_nopanic(struct irq_cfg *cfg, int node, int apic, int pin)
 {
-       struct irq_pin_list **entryp, *entry;
+       struct irq_pin_list **last, *entry;
 
-       for (entryp = &cfg->irq_2_pin;
-            *entryp != NULL;
-            entryp = &(*entryp)->next) {
-               entry = *entryp;
-               /* not again, please */
+       /* don't allow duplicates */
+       last = &cfg->irq_2_pin;
+       for_each_irq_pin(entry, cfg->irq_2_pin) {
                if (entry->apic == apic && entry->pin == pin)
-                       return;
+                       return 0;
+               last = &entry->next;
        }
 
        entry = get_one_free_irq_2_pin(node);
+       if (!entry) {
+               printk(KERN_ERR "can not alloc irq_pin_list (%d,%d,%d)\n",
+                               node, apic, pin);
+               return -ENOMEM;
+       }
        entry->apic = apic;
        entry->pin = pin;
 
-       *entryp = entry;
+       *last = entry;
+       return 0;
+}
+
+static void add_pin_to_irq_node(struct irq_cfg *cfg, int node, int apic, int pin)
+{
+       if (add_pin_to_irq_node_nopanic(cfg, node, apic, pin))
+               panic("IO-APIC: failed to add irq-pin. Can not proceed\n");
 }
 
 /*
@@ -517,7 +531,7 @@ static void __init replace_pin_at_irq_node(struct irq_cfg *cfg, int node,
 {
        struct irq_pin_list *entry;
 
-       for (entry = cfg->irq_2_pin; entry != NULL; entry = entry->next) {
+       for_each_irq_pin(entry, cfg->irq_2_pin) {
                if (entry->apic == oldapic && entry->pin == oldpin) {
                        entry->apic = newapic;
                        entry->pin = newpin;
@@ -537,7 +551,7 @@ static void io_apic_modify_irq(struct irq_cfg *cfg,
        int pin;
        struct irq_pin_list *entry;
 
-       for (entry = cfg->irq_2_pin; entry != NULL; entry = entry->next) {
+       for_each_irq_pin(entry, cfg->irq_2_pin) {
                unsigned int reg;
                pin = entry->pin;
                reg = io_apic_read(entry->apic, 0x10 + pin * 2);
@@ -1669,12 +1683,8 @@ __apicdebuginit(void) print_IO_APIC(void)
                if (!entry)
                        continue;
                printk(KERN_DEBUG "IRQ%d ", irq);
-               for (;;) {
+               for_each_irq_pin(entry, cfg->irq_2_pin)
                        printk("-> %d:%d", entry->apic, entry->pin);
-                       if (!entry->next)
-                               break;
-                       entry = entry->next;
-               }
                printk("\n");
        }
 
@@ -2227,7 +2237,7 @@ static void __target_IO_APIC_irq(unsigned int irq, unsigned int dest, struct irq
        struct irq_pin_list *entry;
        u8 vector = cfg->vector;
 
-       for (entry = cfg->irq_2_pin; entry != NULL; entry = entry->next) {
+       for_each_irq_pin(entry, cfg->irq_2_pin) {
                unsigned int reg;
 
                apic = entry->apic;
@@ -2556,20 +2566,10 @@ static void ack_apic_level(unsigned int irq)
 #ifdef CONFIG_INTR_REMAP
 static void __eoi_ioapic_irq(unsigned int irq, struct irq_cfg *cfg)
 {
-       int apic, pin;
        struct irq_pin_list *entry;
 
-       entry = cfg->irq_2_pin;
-       for (;;) {
-
-               if (!entry)
-                       break;
-
-               apic = entry->apic;
-               pin = entry->pin;
-               io_apic_eoi(apic, pin);
-               entry = entry->next;
-       }
+       for_each_irq_pin(entry, cfg->irq_2_pin)
+               io_apic_eoi(entry->apic, entry->pin);
 }
 
 static void
@@ -3185,8 +3185,7 @@ void destroy_irq(unsigned int irq)
        cfg = desc->chip_data;
        dynamic_irq_cleanup(irq);
        /* connect back irq_cfg */
-       if (desc)
-               desc->chip_data = cfg;
+       desc->chip_data = cfg;
 
        free_irte(irq);
        spin_lock_irqsave(&vector_lock, flags);
@@ -3853,7 +3852,11 @@ static int __io_apic_set_pci_routing(struct device *dev, int irq,
         */
        if (irq >= NR_IRQS_LEGACY) {
                cfg = desc->chip_data;
-               add_pin_to_irq_node(cfg, node, ioapic, pin);
+               if (add_pin_to_irq_node_nopanic(cfg, node, ioapic, pin)) {
+                       printk(KERN_INFO "can not add pin %d for irq %d\n",
+                               pin, irq);
+                       return 0;
+               }
        }
 
        setup_IO_APIC_irq(ioapic, pin, irq, desc, trigger, polarity);
@@ -4050,7 +4053,7 @@ void __init setup_ioapic_dest(void)
 
 static struct resource *ioapic_resources;
 
-static struct resource * __init ioapic_setup_resources(void)
+static struct resource * __init ioapic_setup_resources(int nr_ioapics)
 {
        unsigned long n;
        struct resource *res;
@@ -4066,15 +4069,13 @@ static struct resource * __init ioapic_setup_resources(void)
        mem = alloc_bootmem(n);
        res = (void *)mem;
 
-       if (mem != NULL) {
-               mem += sizeof(struct resource) * nr_ioapics;
+       mem += sizeof(struct resource) * nr_ioapics;
 
-               for (i = 0; i < nr_ioapics; i++) {
-                       res[i].name = mem;
-                       res[i].flags = IORESOURCE_MEM | IORESOURCE_BUSY;
-                       sprintf(mem,  "IOAPIC %u", i);
-                       mem += IOAPIC_RESOURCE_NAME_SIZE;
-               }
+       for (i = 0; i < nr_ioapics; i++) {
+               res[i].name = mem;
+               res[i].flags = IORESOURCE_MEM | IORESOURCE_BUSY;
+               sprintf(mem,  "IOAPIC %u", i);
+               mem += IOAPIC_RESOURCE_NAME_SIZE;
        }
 
        ioapic_resources = res;
@@ -4088,7 +4089,7 @@ void __init ioapic_init_mappings(void)
        struct resource *ioapic_res;
        int i;
 
-       ioapic_res = ioapic_setup_resources();
+       ioapic_res = ioapic_setup_resources(nr_ioapics);
        for (i = 0; i < nr_ioapics; i++) {
                if (smp_found_config) {
                        ioapic_phys = mp_ioapics[i].apicaddr;
@@ -4117,11 +4118,9 @@ fake_ioapic_page:
                            __fix_to_virt(idx), ioapic_phys);
                idx++;
 
-               if (ioapic_res != NULL) {
-                       ioapic_res->start = ioapic_phys;
-                       ioapic_res->end = ioapic_phys + (4 * 1024) - 1;
-                       ioapic_res++;
-               }
+               ioapic_res->start = ioapic_phys;
+               ioapic_res->end = ioapic_phys + (4 * 1024) - 1;
+               ioapic_res++;
        }
 }