Fedora kernel-2.6.17-1.2142_FC4 patched with stable patch-2.6.17.4-vs2.0.2-rc26.diff
[linux-2.6.git] / drivers / parisc / gsc.c
index 1796084..16d40f9 100644 (file)
 
 int gsc_alloc_irq(struct gsc_irq *i)
 {
-       int irq = txn_alloc_irq();
+       int irq = txn_alloc_irq(GSC_EIM_WIDTH);
        if (irq < 0) {
                printk("cannot get irq\n");
                return irq;
        }
 
        i->txn_addr = txn_alloc_addr(irq);
-       i->txn_data = txn_alloc_data(irq, GSC_EIM_WIDTH);
+       i->txn_data = txn_alloc_data(irq);
        i->irq = irq;
 
        return irq;
@@ -64,7 +64,7 @@ int gsc_claim_irq(struct gsc_irq *i, int irq)
        }
 
        i->txn_addr = txn_alloc_addr(irq);
-       i->txn_data = txn_alloc_data(irq, GSC_EIM_WIDTH);
+       i->txn_data = txn_alloc_data(irq);
        i->irq = irq;
 
        return irq;
@@ -171,20 +171,32 @@ int gsc_assign_irq(struct hw_interrupt_type *type, void *data)
 
 void gsc_asic_assign_irq(struct gsc_asic *asic, int local_irq, int *irqp)
 {
-       int irq = gsc_assign_irq(&gsc_asic_interrupt_type, asic);
-       if (irq == NO_IRQ)
-               return;
-
+       int irq = asic->global_irq[local_irq];
+       
+       if (irq <= 0) {
+               irq = gsc_assign_irq(&gsc_asic_interrupt_type, asic);
+               if (irq == NO_IRQ)
+                       return;
+
+               asic->global_irq[local_irq] = irq;
+       }
        *irqp = irq;
-       asic->global_irq[local_irq] = irq;
+}
+
+static struct device *next_device(struct klist_iter *i)
+{
+       struct klist_node * n = klist_next(i);
+       return n ? container_of(n, struct device, knode_parent) : NULL;
 }
 
 void gsc_fixup_irqs(struct parisc_device *parent, void *ctrl,
                        void (*choose_irq)(struct parisc_device *, void *))
 {
        struct device *dev;
+       struct klist_iter i;
 
-       list_for_each_entry(dev, &parent->dev.children, node) {
+       klist_iter_init(&parent->dev.klist_children, &i);
+       while ((dev = next_device(&i))) {
                struct parisc_device *padev = to_parisc_device(dev);
 
                /* work-around for 715/64 and others which have parent 
@@ -193,14 +205,21 @@ void gsc_fixup_irqs(struct parisc_device *parent, void *ctrl,
                        return gsc_fixup_irqs(padev, ctrl, choose_irq);
                choose_irq(padev, ctrl);
        }
+       klist_iter_exit(&i);
 }
 
 int gsc_common_setup(struct parisc_device *parent, struct gsc_asic *gsc_asic)
 {
        struct resource *res;
+       int i;
 
        gsc_asic->gsc = parent;
 
+       /* Initialise local irq -> global irq mapping */
+       for (i = 0; i < 32; i++) {
+               gsc_asic->global_irq[i] = NO_IRQ;
+       }
+
        /* allocate resource region */
        res = request_mem_region(gsc_asic->hpa, 0x100000, gsc_asic->name);
        if (res) {