diff options
author | Joerg Roedel <joerg.roedel@amd.com> | 2012-03-30 14:47:02 -0400 |
---|---|---|
committer | Joerg Roedel <joerg.roedel@amd.com> | 2012-05-07 08:34:59 -0400 |
commit | 0c3f173a88c4ae3e4253427cf574a59ad5352918 (patch) | |
tree | d34364dc8d7926de75ec486ce579b478d23098e3 /drivers/iommu/intel_intr_remapping.c | |
parent | 4f3d8b67ad3090f9fb72f8235d21cde53cd24b79 (diff) |
iommu/vt-d: Convert IR ioapic-setup to use remap_ops
The IOAPIC setup routine for interrupt remapping is VT-d
specific. Move it to the irq_remap_ops and add a call helper
function.
Signed-off-by: Joerg Roedel <joerg.roedel@amd.com>
Acked-by: Yinghai Lu <yinghai@kernel.org>
Cc: David Woodhouse <dwmw2@infradead.org>
Cc: Alex Williamson <alex.williamson@redhat.com>
Signed-off-by: Suresh Siddha <suresh.b.siddha@intel.com>
Signed-off-by: Joerg Roedel <joerg.roedel@amd.com>
Diffstat (limited to 'drivers/iommu/intel_intr_remapping.c')
-rw-r--r-- | drivers/iommu/intel_intr_remapping.c | 89 |
1 files changed, 89 insertions, 0 deletions
diff --git a/drivers/iommu/intel_intr_remapping.c b/drivers/iommu/intel_intr_remapping.c index 610b75b66c07..f495eba4b6ab 100644 --- a/drivers/iommu/intel_intr_remapping.c +++ b/drivers/iommu/intel_intr_remapping.c | |||
@@ -31,6 +31,7 @@ struct hpet_scope { | |||
31 | }; | 31 | }; |
32 | 32 | ||
33 | #define IR_X2APIC_MODE(mode) (mode ? (1 << 11) : 0) | 33 | #define IR_X2APIC_MODE(mode) (mode ? (1 << 11) : 0) |
34 | #define IRTE_DEST(dest) ((x2apic_mode) ? dest : dest << 8) | ||
34 | 35 | ||
35 | static struct ioapic_scope ir_ioapic[MAX_IO_APICS]; | 36 | static struct ioapic_scope ir_ioapic[MAX_IO_APICS]; |
36 | static struct hpet_scope ir_hpet[MAX_HPET_TBS]; | 37 | static struct hpet_scope ir_hpet[MAX_HPET_TBS]; |
@@ -814,6 +815,93 @@ error: | |||
814 | return -1; | 815 | return -1; |
815 | } | 816 | } |
816 | 817 | ||
818 | static void prepare_irte(struct irte *irte, int vector, | ||
819 | unsigned int dest) | ||
820 | { | ||
821 | memset(irte, 0, sizeof(*irte)); | ||
822 | |||
823 | irte->present = 1; | ||
824 | irte->dst_mode = apic->irq_dest_mode; | ||
825 | /* | ||
826 | * Trigger mode in the IRTE will always be edge, and for IO-APIC, the | ||
827 | * actual level or edge trigger will be setup in the IO-APIC | ||
828 | * RTE. This will help simplify level triggered irq migration. | ||
829 | * For more details, see the comments (in io_apic.c) explainig IO-APIC | ||
830 | * irq migration in the presence of interrupt-remapping. | ||
831 | */ | ||
832 | irte->trigger_mode = 0; | ||
833 | irte->dlvry_mode = apic->irq_delivery_mode; | ||
834 | irte->vector = vector; | ||
835 | irte->dest_id = IRTE_DEST(dest); | ||
836 | irte->redir_hint = 1; | ||
837 | } | ||
838 | |||
839 | static int intel_setup_ioapic_entry(int irq, | ||
840 | struct IO_APIC_route_entry *route_entry, | ||
841 | unsigned int destination, int vector, | ||
842 | struct io_apic_irq_attr *attr) | ||
843 | { | ||
844 | int ioapic_id = mpc_ioapic_id(attr->ioapic); | ||
845 | struct intel_iommu *iommu = map_ioapic_to_ir(ioapic_id); | ||
846 | struct IR_IO_APIC_route_entry *entry; | ||
847 | struct irte irte; | ||
848 | int index; | ||
849 | |||
850 | if (!iommu) { | ||
851 | pr_warn("No mapping iommu for ioapic %d\n", ioapic_id); | ||
852 | return -ENODEV; | ||
853 | } | ||
854 | |||
855 | entry = (struct IR_IO_APIC_route_entry *)route_entry; | ||
856 | |||
857 | index = alloc_irte(iommu, irq, 1); | ||
858 | if (index < 0) { | ||
859 | pr_warn("Failed to allocate IRTE for ioapic %d\n", ioapic_id); | ||
860 | return -ENOMEM; | ||
861 | } | ||
862 | |||
863 | prepare_irte(&irte, vector, destination); | ||
864 | |||
865 | /* Set source-id of interrupt request */ | ||
866 | set_ioapic_sid(&irte, ioapic_id); | ||
867 | |||
868 | modify_irte(irq, &irte); | ||
869 | |||
870 | apic_printk(APIC_VERBOSE, KERN_DEBUG "IOAPIC[%d]: " | ||
871 | "Set IRTE entry (P:%d FPD:%d Dst_Mode:%d " | ||
872 | "Redir_hint:%d Trig_Mode:%d Dlvry_Mode:%X " | ||
873 | "Avail:%X Vector:%02X Dest:%08X " | ||
874 | "SID:%04X SQ:%X SVT:%X)\n", | ||
875 | attr->ioapic, irte.present, irte.fpd, irte.dst_mode, | ||
876 | irte.redir_hint, irte.trigger_mode, irte.dlvry_mode, | ||
877 | irte.avail, irte.vector, irte.dest_id, | ||
878 | irte.sid, irte.sq, irte.svt); | ||
879 | |||
880 | memset(entry, 0, sizeof(*entry)); | ||
881 | |||
882 | entry->index2 = (index >> 15) & 0x1; | ||
883 | entry->zero = 0; | ||
884 | entry->format = 1; | ||
885 | entry->index = (index & 0x7fff); | ||
886 | /* | ||
887 | * IO-APIC RTE will be configured with virtual vector. | ||
888 | * irq handler will do the explicit EOI to the io-apic. | ||
889 | */ | ||
890 | entry->vector = attr->ioapic_pin; | ||
891 | entry->mask = 0; /* enable IRQ */ | ||
892 | entry->trigger = attr->trigger; | ||
893 | entry->polarity = attr->polarity; | ||
894 | |||
895 | /* Mask level triggered irqs. | ||
896 | * Use IRQ_DELAYED_DISABLE for edge triggered irqs. | ||
897 | */ | ||
898 | if (attr->trigger) | ||
899 | entry->mask = 1; | ||
900 | |||
901 | return 0; | ||
902 | } | ||
903 | |||
904 | |||
817 | struct irq_remap_ops intel_irq_remap_ops = { | 905 | struct irq_remap_ops intel_irq_remap_ops = { |
818 | .supported = intel_intr_remapping_supported, | 906 | .supported = intel_intr_remapping_supported, |
819 | .hardware_init = dmar_table_init, | 907 | .hardware_init = dmar_table_init, |
@@ -821,4 +909,5 @@ struct irq_remap_ops intel_irq_remap_ops = { | |||
821 | .hardware_disable = disable_intr_remapping, | 909 | .hardware_disable = disable_intr_remapping, |
822 | .hardware_reenable = reenable_intr_remapping, | 910 | .hardware_reenable = reenable_intr_remapping, |
823 | .enable_faulting = enable_drhd_fault_handling, | 911 | .enable_faulting = enable_drhd_fault_handling, |
912 | .setup_ioapic_entry = intel_setup_ioapic_entry, | ||
824 | }; | 913 | }; |