]> git.karo-electronics.de Git - karo-tx-linux.git/blobdiff - arch/x86/kernel/apic/io_apic.c
Merge branch 'for-arm' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/signal...
[karo-tx-linux.git] / arch / x86 / kernel / apic / io_apic.c
index e88300d8e80aa2465aec91af3768578dee32c727..ef0648cd7084a08c57ad3acb4b7f7fce1dbbdfea 100644 (file)
@@ -86,6 +86,22 @@ void __init set_io_apic_ops(const struct io_apic_ops *ops)
        io_apic_ops = *ops;
 }
 
+#ifdef CONFIG_IRQ_REMAP
+static void irq_remap_modify_chip_defaults(struct irq_chip *chip);
+static inline bool irq_remapped(struct irq_cfg *cfg)
+{
+       return cfg->irq_2_iommu.iommu != NULL;
+}
+#else
+static inline bool irq_remapped(struct irq_cfg *cfg)
+{
+       return false;
+}
+static inline void irq_remap_modify_chip_defaults(struct irq_chip *chip)
+{
+}
+#endif
+
 /*
  *      Is the SiS APIC rmw bug present ?
  *      -1 = don't know, 0 = no, 1 = yes
@@ -1361,77 +1377,13 @@ static void ioapic_register_intr(unsigned int irq, struct irq_cfg *cfg,
                                      fasteoi ? "fasteoi" : "edge");
 }
 
-
-static int setup_ir_ioapic_entry(int irq,
-                             struct IR_IO_APIC_route_entry *entry,
-                             unsigned int destination, int vector,
-                             struct io_apic_irq_attr *attr)
-{
-       int index;
-       struct irte irte;
-       int ioapic_id = mpc_ioapic_id(attr->ioapic);
-       struct intel_iommu *iommu = map_ioapic_to_ir(ioapic_id);
-
-       if (!iommu) {
-               pr_warn("No mapping iommu for ioapic %d\n", ioapic_id);
-               return -ENODEV;
-       }
-
-       index = alloc_irte(iommu, irq, 1);
-       if (index < 0) {
-               pr_warn("Failed to allocate IRTE for ioapic %d\n", ioapic_id);
-               return -ENOMEM;
-       }
-
-       prepare_irte(&irte, vector, destination);
-
-       /* Set source-id of interrupt request */
-       set_ioapic_sid(&irte, ioapic_id);
-
-       modify_irte(irq, &irte);
-
-       apic_printk(APIC_VERBOSE, KERN_DEBUG "IOAPIC[%d]: "
-               "Set IRTE entry (P:%d FPD:%d Dst_Mode:%d "
-               "Redir_hint:%d Trig_Mode:%d Dlvry_Mode:%X "
-               "Avail:%X Vector:%02X Dest:%08X "
-               "SID:%04X SQ:%X SVT:%X)\n",
-               attr->ioapic, irte.present, irte.fpd, irte.dst_mode,
-               irte.redir_hint, irte.trigger_mode, irte.dlvry_mode,
-               irte.avail, irte.vector, irte.dest_id,
-               irte.sid, irte.sq, irte.svt);
-
-       memset(entry, 0, sizeof(*entry));
-
-       entry->index2   = (index >> 15) & 0x1;
-       entry->zero     = 0;
-       entry->format   = 1;
-       entry->index    = (index & 0x7fff);
-       /*
-        * IO-APIC RTE will be configured with virtual vector.
-        * irq handler will do the explicit EOI to the io-apic.
-        */
-       entry->vector   = attr->ioapic_pin;
-       entry->mask     = 0;                    /* enable IRQ */
-       entry->trigger  = attr->trigger;
-       entry->polarity = attr->polarity;
-
-       /* Mask level triggered irqs.
-        * Use IRQ_DELAYED_DISABLE for edge triggered irqs.
-        */
-       if (attr->trigger)
-               entry->mask = 1;
-
-       return 0;
-}
-
 static int setup_ioapic_entry(int irq, struct IO_APIC_route_entry *entry,
                               unsigned int destination, int vector,
                               struct io_apic_irq_attr *attr)
 {
-       if (intr_remapping_enabled)
-               return setup_ir_ioapic_entry(irq,
-                        (struct IR_IO_APIC_route_entry *)entry,
-                        destination, vector, attr);
+       if (irq_remapping_enabled)
+               return setup_ioapic_remapped_entry(irq, entry, destination,
+                                                  vector, attr);
 
        memset(entry, 0, sizeof(*entry));
 
@@ -1588,7 +1540,7 @@ static void __init setup_timer_IRQ0_pin(unsigned int ioapic_idx,
 {
        struct IO_APIC_route_entry entry;
 
-       if (intr_remapping_enabled)
+       if (irq_remapping_enabled)
                return;
 
        memset(&entry, 0, sizeof(entry));
@@ -1674,7 +1626,7 @@ __apicdebuginit(void) print_IO_APIC(int ioapic_idx)
 
        printk(KERN_DEBUG ".... IRQ redirection table:\n");
 
-       if (intr_remapping_enabled) {
+       if (irq_remapping_enabled) {
                printk(KERN_DEBUG " NR Indx Fmt Mask Trig IRR"
                        " Pol Stat Indx2 Zero Vect:\n");
        } else {
@@ -1683,7 +1635,7 @@ __apicdebuginit(void) print_IO_APIC(int ioapic_idx)
        }
 
        for (i = 0; i <= reg_01.bits.entries; i++) {
-               if (intr_remapping_enabled) {
+               if (irq_remapping_enabled) {
                        struct IO_APIC_route_entry entry;
                        struct IR_IO_APIC_route_entry *ir_entry;
 
@@ -2050,7 +2002,7 @@ void disable_IO_APIC(void)
         * IOAPIC RTE as well as interrupt-remapping table entry).
         * As this gets called during crash dump, keep this simple for now.
         */
-       if (ioapic_i8259.pin != -1 && !intr_remapping_enabled) {
+       if (ioapic_i8259.pin != -1 && !irq_remapping_enabled) {
                struct IO_APIC_route_entry entry;
 
                memset(&entry, 0, sizeof(entry));
@@ -2074,7 +2026,7 @@ void disable_IO_APIC(void)
         * Use virtual wire A mode when interrupt remapping is enabled.
         */
        if (cpu_has_apic || apic_from_smp_config())
-               disconnect_bsp_APIC(!intr_remapping_enabled &&
+               disconnect_bsp_APIC(!irq_remapping_enabled &&
                                ioapic_i8259.pin != -1);
 }
 
@@ -2390,71 +2342,6 @@ ioapic_set_affinity(struct irq_data *data, const struct cpumask *mask,
        return ret;
 }
 
-#ifdef CONFIG_IRQ_REMAP
-
-/*
- * Migrate the IO-APIC irq in the presence of intr-remapping.
- *
- * For both level and edge triggered, irq migration is a simple atomic
- * update(of vector and cpu destination) of IRTE and flush the hardware cache.
- *
- * For level triggered, we eliminate the io-apic RTE modification (with the
- * updated vector information), by using a virtual vector (io-apic pin number).
- * Real vector that is used for interrupting cpu will be coming from
- * the interrupt-remapping table entry.
- *
- * As the migration is a simple atomic update of IRTE, the same mechanism
- * is used to migrate MSI irq's in the presence of interrupt-remapping.
- */
-static int
-ir_ioapic_set_affinity(struct irq_data *data, const struct cpumask *mask,
-                      bool force)
-{
-       struct irq_cfg *cfg = data->chip_data;
-       unsigned int dest, irq = data->irq;
-       struct irte irte;
-
-       if (!cpumask_intersects(mask, cpu_online_mask))
-               return -EINVAL;
-
-       if (get_irte(irq, &irte))
-               return -EBUSY;
-
-       if (assign_irq_vector(irq, cfg, mask))
-               return -EBUSY;
-
-       dest = apic->cpu_mask_to_apicid_and(cfg->domain, mask);
-
-       irte.vector = cfg->vector;
-       irte.dest_id = IRTE_DEST(dest);
-
-       /*
-        * Atomically updates the IRTE with the new destination, vector
-        * and flushes the interrupt entry cache.
-        */
-       modify_irte(irq, &irte);
-
-       /*
-        * After this point, all the interrupts will start arriving
-        * at the new destination. So, time to cleanup the previous
-        * vector allocation.
-        */
-       if (cfg->move_in_progress)
-               send_cleanup_vector(cfg);
-
-       cpumask_copy(data->affinity, mask);
-       return 0;
-}
-
-#else
-static inline int
-ir_ioapic_set_affinity(struct irq_data *data, const struct cpumask *mask,
-                      bool force)
-{
-       return 0;
-}
-#endif
-
 asmlinkage void smp_irq_move_cleanup_interrupt(void)
 {
        unsigned vector, me;
@@ -2699,7 +2586,7 @@ static void irq_remap_modify_chip_defaults(struct irq_chip *chip)
        chip->irq_eoi = ir_ack_apic_level;
 
 #ifdef CONFIG_SMP
-       chip->irq_set_affinity = ir_ioapic_set_affinity;
+       chip->irq_set_affinity = set_remapped_irq_affinity;
 #endif
 }
 #endif /* CONFIG_IRQ_REMAP */
@@ -2912,7 +2799,7 @@ static inline void __init check_timer(void)
         * 8259A.
         */
        if (pin1 == -1) {
-               if (intr_remapping_enabled)
+               if (irq_remapping_enabled)
                        panic("BIOS bug: timer not connected to IO-APIC");
                pin1 = pin2;
                apic1 = apic2;
@@ -2945,7 +2832,7 @@ static inline void __init check_timer(void)
                                clear_IO_APIC_pin(0, pin1);
                        goto out;
                }
-               if (intr_remapping_enabled)
+               if (irq_remapping_enabled)
                        panic("timer doesn't work through Interrupt-remapped IO-APIC");
                local_irq_disable();
                clear_IO_APIC_pin(apic1, pin1);
@@ -3169,7 +3056,7 @@ void destroy_irq(unsigned int irq)
        irq_set_status_flags(irq, IRQ_NOREQUEST|IRQ_NOPROBE);
 
        if (irq_remapped(cfg))
-               free_irte(irq);
+               free_remapped_irq(irq);
        raw_spin_lock_irqsave(&vector_lock, flags);
        __clear_irq_vector(irq, cfg);
        raw_spin_unlock_irqrestore(&vector_lock, flags);
@@ -3198,54 +3085,34 @@ static int msi_compose_msg(struct pci_dev *pdev, unsigned int irq,
        dest = apic->cpu_mask_to_apicid_and(cfg->domain, apic->target_cpus());
 
        if (irq_remapped(cfg)) {
-               struct irte irte;
-               int ir_index;
-               u16 sub_handle;
-
-               ir_index = map_irq_to_irte_handle(irq, &sub_handle);
-               BUG_ON(ir_index == -1);
-
-               prepare_irte(&irte, cfg->vector, dest);
-
-               /* Set source-id of interrupt request */
-               if (pdev)
-                       set_msi_sid(&irte, pdev);
-               else
-                       set_hpet_sid(&irte, hpet_id);
-
-               modify_irte(irq, &irte);
+               compose_remapped_msi_msg(pdev, irq, dest, msg, hpet_id);
+               return err;
+       }
 
+       if (x2apic_enabled())
+               msg->address_hi = MSI_ADDR_BASE_HI |
+                                 MSI_ADDR_EXT_DEST_ID(dest);
+       else
                msg->address_hi = MSI_ADDR_BASE_HI;
-               msg->data = sub_handle;
-               msg->address_lo = MSI_ADDR_BASE_LO | MSI_ADDR_IR_EXT_INT |
-                                 MSI_ADDR_IR_SHV |
-                                 MSI_ADDR_IR_INDEX1(ir_index) |
-                                 MSI_ADDR_IR_INDEX2(ir_index);
-       } else {
-               if (x2apic_enabled())
-                       msg->address_hi = MSI_ADDR_BASE_HI |
-                                         MSI_ADDR_EXT_DEST_ID(dest);
-               else
-                       msg->address_hi = MSI_ADDR_BASE_HI;
 
-               msg->address_lo =
-                       MSI_ADDR_BASE_LO |
-                       ((apic->irq_dest_mode == 0) ?
-                               MSI_ADDR_DEST_MODE_PHYSICAL:
-                               MSI_ADDR_DEST_MODE_LOGICAL) |
-                       ((apic->irq_delivery_mode != dest_LowestPrio) ?
-                               MSI_ADDR_REDIRECTION_CPU:
-                               MSI_ADDR_REDIRECTION_LOWPRI) |
-                       MSI_ADDR_DEST_ID(dest);
+       msg->address_lo =
+               MSI_ADDR_BASE_LO |
+               ((apic->irq_dest_mode == 0) ?
+                       MSI_ADDR_DEST_MODE_PHYSICAL:
+                       MSI_ADDR_DEST_MODE_LOGICAL) |
+               ((apic->irq_delivery_mode != dest_LowestPrio) ?
+                       MSI_ADDR_REDIRECTION_CPU:
+                       MSI_ADDR_REDIRECTION_LOWPRI) |
+               MSI_ADDR_DEST_ID(dest);
+
+       msg->data =
+               MSI_DATA_TRIGGER_EDGE |
+               MSI_DATA_LEVEL_ASSERT |
+               ((apic->irq_delivery_mode != dest_LowestPrio) ?
+                       MSI_DATA_DELIVERY_FIXED:
+                       MSI_DATA_DELIVERY_LOWPRI) |
+               MSI_DATA_VECTOR(cfg->vector);
 
-               msg->data =
-                       MSI_DATA_TRIGGER_EDGE |
-                       MSI_DATA_LEVEL_ASSERT |
-                       ((apic->irq_delivery_mode != dest_LowestPrio) ?
-                               MSI_DATA_DELIVERY_FIXED:
-                               MSI_DATA_DELIVERY_LOWPRI) |
-                       MSI_DATA_VECTOR(cfg->vector);
-       }
        return err;
 }
 
@@ -3288,33 +3155,6 @@ static struct irq_chip msi_chip = {
        .irq_retrigger          = ioapic_retrigger_irq,
 };
 
-/*
- * Map the PCI dev to the corresponding remapping hardware unit
- * and allocate 'nvec' consecutive interrupt-remapping table entries
- * in it.
- */
-static int msi_alloc_irte(struct pci_dev *dev, int irq, int nvec)
-{
-       struct intel_iommu *iommu;
-       int index;
-
-       iommu = map_dev_to_ir(dev);
-       if (!iommu) {
-               printk(KERN_ERR
-                      "Unable to map PCI %s to iommu\n", pci_name(dev));
-               return -ENOENT;
-       }
-
-       index = alloc_irte(iommu, irq, nvec);
-       if (index < 0) {
-               printk(KERN_ERR
-                      "Unable to allocate %d IRTE for PCI %s\n", nvec,
-                      pci_name(dev));
-               return -ENOSPC;
-       }
-       return index;
-}
-
 static int setup_msi_irq(struct pci_dev *dev, struct msi_desc *msidesc, int irq)
 {
        struct irq_chip *chip = &msi_chip;
@@ -3345,7 +3185,6 @@ int native_setup_msi_irqs(struct pci_dev *dev, int nvec, int type)
        int node, ret, sub_handle, index = 0;
        unsigned int irq, irq_want;
        struct msi_desc *msidesc;
-       struct intel_iommu *iommu = NULL;
 
        /* x86 doesn't support multiple MSI yet */
        if (type == PCI_CAP_ID_MSI && nvec > 1)
@@ -3359,7 +3198,7 @@ int native_setup_msi_irqs(struct pci_dev *dev, int nvec, int type)
                if (irq == 0)
                        return -1;
                irq_want = irq + 1;
-               if (!intr_remapping_enabled)
+               if (!irq_remapping_enabled)
                        goto no_ir;
 
                if (!sub_handle) {
@@ -3367,23 +3206,16 @@ int native_setup_msi_irqs(struct pci_dev *dev, int nvec, int type)
                         * allocate the consecutive block of IRTE's
                         * for 'nvec'
                         */
-                       index = msi_alloc_irte(dev, irq, nvec);
+                       index = msi_alloc_remapped_irq(dev, irq, nvec);
                        if (index < 0) {
                                ret = index;
                                goto error;
                        }
                } else {
-                       iommu = map_dev_to_ir(dev);
-                       if (!iommu) {
-                               ret = -ENOENT;
+                       ret = msi_setup_remapped_irq(dev, irq, index,
+                                                    sub_handle);
+                       if (ret < 0)
                                goto error;
-                       }
-                       /*
-                        * setup the mapping between the irq and the IRTE
-                        * base index, the sub_handle pointing to the
-                        * appropriate interrupt remap table entry.
-                        */
-                       set_irte_irq(irq, iommu, index, sub_handle);
                }
 no_ir:
                ret = setup_msi_irq(dev, msidesc, irq);
@@ -3501,15 +3333,8 @@ int arch_setup_hpet_msi(unsigned int irq, unsigned int id)
        struct msi_msg msg;
        int ret;
 
-       if (intr_remapping_enabled) {
-               struct intel_iommu *iommu = map_hpet_to_ir(id);
-               int index;
-
-               if (!iommu)
-                       return -1;
-
-               index = alloc_irte(iommu, irq, 1);
-               if (index < 0)
+       if (irq_remapping_enabled) {
+               if (!setup_hpet_msi_remapped(irq, id))
                        return -1;
        }
 
@@ -3888,8 +3713,8 @@ void __init setup_ioapic_dest(void)
                else
                        mask = apic->target_cpus();
 
-               if (intr_remapping_enabled)
-                       ir_ioapic_set_affinity(idata, mask, false);
+               if (irq_remapping_enabled)
+                       set_remapped_irq_affinity(idata, mask, false);
                else
                        ioapic_set_affinity(idata, mask, false);
        }