sparse irq_desc[] array: core kernel and x86 changes
[deliverable/linux.git] / drivers / pci / intr_remapping.c
index 2de5a3238c947be89213119d9cf468d2fa59e11d..c9958ec5e25eaee4298d3d758786f36fd2d51c85 100644 (file)
@@ -19,17 +19,75 @@ struct irq_2_iommu {
        u8  irte_mask;
 };
 
-static struct irq_2_iommu irq_2_iommuX[NR_IRQS];
+#ifdef CONFIG_SPARSE_IRQ
+static struct irq_2_iommu *get_one_free_irq_2_iommu(int cpu)
+{
+       struct irq_2_iommu *iommu;
+       int node;
+
+       node = cpu_to_node(cpu);
+
+       iommu = kzalloc_node(sizeof(*iommu), GFP_ATOMIC, node);
+       printk(KERN_DEBUG "alloc irq_2_iommu on cpu %d node %d\n", cpu, node);
+
+       return iommu;
+}
 
 static struct irq_2_iommu *irq_2_iommu(unsigned int irq)
 {
-       return (irq < nr_irqs) ? irq_2_iommuX + irq : NULL;
+       struct irq_desc *desc;
+
+       desc = irq_to_desc(irq);
+
+       if (WARN_ON_ONCE(!desc))
+               return NULL;
+
+       return desc->irq_2_iommu;
+}
+
+static struct irq_2_iommu *irq_2_iommu_alloc_cpu(unsigned int irq, int cpu)
+{
+       struct irq_desc *desc;
+       struct irq_2_iommu *irq_iommu;
+
+       /*
+        * alloc irq desc if not allocated already.
+        */
+       desc = irq_to_desc_alloc_cpu(irq, cpu);
+       if (!desc) {
+               printk(KERN_INFO "can not get irq_desc for %d\n", irq);
+               return NULL;
+       }
+
+       irq_iommu = desc->irq_2_iommu;
+
+       if (!irq_iommu)
+               desc->irq_2_iommu = get_one_free_irq_2_iommu(cpu);
+
+       return desc->irq_2_iommu;
 }
 
+static struct irq_2_iommu *irq_2_iommu_alloc(unsigned int irq)
+{
+       return irq_2_iommu_alloc_cpu(irq, boot_cpu_id);
+}
+
+#else /* !CONFIG_SPARSE_IRQ */
+
+static struct irq_2_iommu irq_2_iommuX[NR_IRQS];
+
+static struct irq_2_iommu *irq_2_iommu(unsigned int irq)
+{
+       if (irq < nr_irqs)
+               return &irq_2_iommuX[irq];
+
+       return NULL;
+}
 static struct irq_2_iommu *irq_2_iommu_alloc(unsigned int irq)
 {
        return irq_2_iommu(irq);
 }
+#endif
 
 static DEFINE_SPINLOCK(irq_2_ir_lock);
 
@@ -86,9 +144,11 @@ int alloc_irte(struct intel_iommu *iommu, int irq, u16 count)
        if (!count)
                return -1;
 
+#ifndef CONFIG_SPARSE_IRQ
        /* protect irq_2_iommu_alloc later */
        if (irq >= nr_irqs)
                return -1;
+#endif
 
        /*
         * start the IRTE search from index 0.
@@ -130,6 +190,12 @@ int alloc_irte(struct intel_iommu *iommu, int irq, u16 count)
                table->base[i].present = 1;
 
        irq_iommu = irq_2_iommu_alloc(irq);
+       if (!irq_iommu) {
+               spin_unlock(&irq_2_ir_lock);
+               printk(KERN_ERR "can't allocate irq_2_iommu\n");
+               return -1;
+       }
+
        irq_iommu->iommu = iommu;
        irq_iommu->irte_index =  index;
        irq_iommu->sub_handle = 0;
@@ -177,6 +243,12 @@ int set_irte_irq(int irq, struct intel_iommu *iommu, u16 index, u16 subhandle)
 
        irq_iommu = irq_2_iommu_alloc(irq);
 
+       if (!irq_iommu) {
+               spin_unlock(&irq_2_ir_lock);
+               printk(KERN_ERR "can't allocate irq_2_iommu\n");
+               return -1;
+       }
+
        irq_iommu->iommu = iommu;
        irq_iommu->irte_index = index;
        irq_iommu->sub_handle = subhandle;
This page took 0.027139 seconds and 5 git commands to generate.