diff options
Diffstat (limited to 'drivers/pci/intr_remapping.c')
-rw-r--r-- | drivers/pci/intr_remapping.c | 212 |
1 files changed, 27 insertions, 185 deletions
diff --git a/drivers/pci/intr_remapping.c b/drivers/pci/intr_remapping.c index fd1d2867cdcc..ec87cd66f3eb 100644 --- a/drivers/pci/intr_remapping.c +++ b/drivers/pci/intr_remapping.c @@ -46,109 +46,24 @@ static __init int setup_intremap(char *str) } early_param("intremap", setup_intremap); -struct irq_2_iommu { - struct intel_iommu *iommu; - u16 irte_index; - u16 sub_handle; - u8 irte_mask; -}; - -#ifdef CONFIG_GENERIC_HARDIRQS -static struct irq_2_iommu *get_one_free_irq_2_iommu(int node) -{ - struct irq_2_iommu *iommu; - - iommu = kzalloc_node(sizeof(*iommu), GFP_ATOMIC, node); - printk(KERN_DEBUG "alloc irq_2_iommu on node %d\n", node); - - return iommu; -} - -static struct irq_2_iommu *irq_2_iommu(unsigned int irq) -{ - 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(unsigned int irq) -{ - struct irq_desc *desc; - struct irq_2_iommu *irq_iommu; - - desc = irq_to_desc(irq); - 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(irq_node(irq)); - - return desc->irq_2_iommu; -} - -#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); -static struct irq_2_iommu *valid_irq_2_iommu(unsigned int irq) -{ - struct irq_2_iommu *irq_iommu; - - irq_iommu = irq_2_iommu(irq); - - if (!irq_iommu) - return NULL; - - if (!irq_iommu->iommu) - return NULL; - - return irq_iommu; -} - -int irq_remapped(int irq) +static struct irq_2_iommu *irq_2_iommu(unsigned int irq) { - return valid_irq_2_iommu(irq) != NULL; + struct irq_cfg *cfg = get_irq_chip_data(irq); + return cfg ? &cfg->irq_2_iommu : NULL; } int get_irte(int irq, struct irte *entry) { - int index; - struct irq_2_iommu *irq_iommu; + struct irq_2_iommu *irq_iommu = irq_2_iommu(irq); unsigned long flags; + int index; - if (!entry) + if (!entry || !irq_iommu) return -1; spin_lock_irqsave(&irq_2_ir_lock, flags); - irq_iommu = valid_irq_2_iommu(irq); - if (!irq_iommu) { - spin_unlock_irqrestore(&irq_2_ir_lock, flags); - return -1; - } index = irq_iommu->irte_index + irq_iommu->sub_handle; *entry = *(irq_iommu->iommu->ir_table->base + index); @@ -160,20 +75,14 @@ int get_irte(int irq, struct irte *entry) int alloc_irte(struct intel_iommu *iommu, int irq, u16 count) { struct ir_table *table = iommu->ir_table; - struct irq_2_iommu *irq_iommu; + struct irq_2_iommu *irq_iommu = irq_2_iommu(irq); u16 index, start_index; unsigned int mask = 0; unsigned long flags; int i; - if (!count) - return -1; - -#ifndef CONFIG_SPARSE_IRQ - /* protect irq_2_iommu_alloc later */ - if (irq >= nr_irqs) + if (!count || !irq_iommu) return -1; -#endif /* * start the IRTE search from index 0. @@ -214,13 +123,6 @@ int alloc_irte(struct intel_iommu *iommu, int irq, u16 count) for (i = index; i < index + count; i++) table->base[i].present = 1; - irq_iommu = irq_2_iommu_alloc(irq); - if (!irq_iommu) { - spin_unlock_irqrestore(&irq_2_ir_lock, flags); - 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; @@ -244,17 +146,14 @@ static int qi_flush_iec(struct intel_iommu *iommu, int index, int mask) int map_irq_to_irte_handle(int irq, u16 *sub_handle) { - int index; - struct irq_2_iommu *irq_iommu; + struct irq_2_iommu *irq_iommu = irq_2_iommu(irq); unsigned long flags; + int index; - spin_lock_irqsave(&irq_2_ir_lock, flags); - irq_iommu = valid_irq_2_iommu(irq); - if (!irq_iommu) { - spin_unlock_irqrestore(&irq_2_ir_lock, flags); + if (!irq_iommu) return -1; - } + spin_lock_irqsave(&irq_2_ir_lock, flags); *sub_handle = irq_iommu->sub_handle; index = irq_iommu->irte_index; spin_unlock_irqrestore(&irq_2_ir_lock, flags); @@ -263,18 +162,13 @@ int map_irq_to_irte_handle(int irq, u16 *sub_handle) int set_irte_irq(int irq, struct intel_iommu *iommu, u16 index, u16 subhandle) { - struct irq_2_iommu *irq_iommu; + struct irq_2_iommu *irq_iommu = irq_2_iommu(irq); unsigned long flags; - spin_lock_irqsave(&irq_2_ir_lock, flags); - - irq_iommu = irq_2_iommu_alloc(irq); - - if (!irq_iommu) { - spin_unlock_irqrestore(&irq_2_ir_lock, flags); - printk(KERN_ERR "can't allocate irq_2_iommu\n"); + if (!irq_iommu) return -1; - } + + spin_lock_irqsave(&irq_2_ir_lock, flags); irq_iommu->iommu = iommu; irq_iommu->irte_index = index; @@ -286,43 +180,18 @@ int set_irte_irq(int irq, struct intel_iommu *iommu, u16 index, u16 subhandle) return 0; } -int clear_irte_irq(int irq, struct intel_iommu *iommu, u16 index) -{ - struct irq_2_iommu *irq_iommu; - unsigned long flags; - - spin_lock_irqsave(&irq_2_ir_lock, flags); - irq_iommu = valid_irq_2_iommu(irq); - if (!irq_iommu) { - spin_unlock_irqrestore(&irq_2_ir_lock, flags); - return -1; - } - - irq_iommu->iommu = NULL; - irq_iommu->irte_index = 0; - irq_iommu->sub_handle = 0; - irq_2_iommu(irq)->irte_mask = 0; - - spin_unlock_irqrestore(&irq_2_ir_lock, flags); - - return 0; -} - int modify_irte(int irq, struct irte *irte_modified) { - int rc; - int index; - struct irte *irte; + struct irq_2_iommu *irq_iommu = irq_2_iommu(irq); struct intel_iommu *iommu; - struct irq_2_iommu *irq_iommu; unsigned long flags; + struct irte *irte; + int rc, index; - spin_lock_irqsave(&irq_2_ir_lock, flags); - irq_iommu = valid_irq_2_iommu(irq); - if (!irq_iommu) { - spin_unlock_irqrestore(&irq_2_ir_lock, flags); + if (!irq_iommu) return -1; - } + + spin_lock_irqsave(&irq_2_ir_lock, flags); iommu = irq_iommu->iommu; @@ -339,31 +208,6 @@ int modify_irte(int irq, struct irte *irte_modified) return rc; } -int flush_irte(int irq) -{ - int rc; - int index; - struct intel_iommu *iommu; - struct irq_2_iommu *irq_iommu; - unsigned long flags; - - spin_lock_irqsave(&irq_2_ir_lock, flags); - irq_iommu = valid_irq_2_iommu(irq); - if (!irq_iommu) { - spin_unlock_irqrestore(&irq_2_ir_lock, flags); - return -1; - } - - iommu = irq_iommu->iommu; - - index = irq_iommu->irte_index + irq_iommu->sub_handle; - - rc = qi_flush_iec(iommu, index, irq_iommu->irte_mask); - spin_unlock_irqrestore(&irq_2_ir_lock, flags); - - return rc; -} - struct intel_iommu *map_hpet_to_ir(u8 hpet_id) { int i; @@ -420,16 +264,14 @@ static int clear_entries(struct irq_2_iommu *irq_iommu) int free_irte(int irq) { - int rc = 0; - struct irq_2_iommu *irq_iommu; + struct irq_2_iommu *irq_iommu = irq_2_iommu(irq); unsigned long flags; + int rc; - spin_lock_irqsave(&irq_2_ir_lock, flags); - irq_iommu = valid_irq_2_iommu(irq); - if (!irq_iommu) { - spin_unlock_irqrestore(&irq_2_ir_lock, flags); + if (!irq_iommu) return -1; - } + + spin_lock_irqsave(&irq_2_ir_lock, flags); rc = clear_entries(irq_iommu); |