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 | |
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')
-rw-r--r-- | drivers/iommu/intel_intr_remapping.c | 89 | ||||
-rw-r--r-- | drivers/iommu/intr_remapping.c | 12 | ||||
-rw-r--r-- | drivers/iommu/intr_remapping.h | 8 |
3 files changed, 109 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 | }; |
diff --git a/drivers/iommu/intr_remapping.c b/drivers/iommu/intr_remapping.c index 9aabed7c0320..739148ab2538 100644 --- a/drivers/iommu/intr_remapping.c +++ b/drivers/iommu/intr_remapping.c | |||
@@ -98,3 +98,15 @@ int __init intr_enable_fault_handling(void) | |||
98 | 98 | ||
99 | return remap_ops->enable_faulting(); | 99 | return remap_ops->enable_faulting(); |
100 | } | 100 | } |
101 | |||
102 | int intr_setup_ioapic_entry(int irq, | ||
103 | struct IO_APIC_route_entry *entry, | ||
104 | unsigned int destination, int vector, | ||
105 | struct io_apic_irq_attr *attr) | ||
106 | { | ||
107 | if (!remap_ops || !remap_ops->setup_ioapic_entry) | ||
108 | return -ENODEV; | ||
109 | |||
110 | return remap_ops->setup_ioapic_entry(irq, entry, destination, | ||
111 | vector, attr); | ||
112 | } | ||
diff --git a/drivers/iommu/intr_remapping.h b/drivers/iommu/intr_remapping.h index 2744c9ae4aec..e8994f2b3bbe 100644 --- a/drivers/iommu/intr_remapping.h +++ b/drivers/iommu/intr_remapping.h | |||
@@ -24,6 +24,9 @@ | |||
24 | 24 | ||
25 | #ifdef CONFIG_IRQ_REMAP | 25 | #ifdef CONFIG_IRQ_REMAP |
26 | 26 | ||
27 | struct IO_APIC_route_entry; | ||
28 | struct io_apic_irq_attr; | ||
29 | |||
27 | extern int disable_intremap; | 30 | extern int disable_intremap; |
28 | extern int disable_sourceid_checking; | 31 | extern int disable_sourceid_checking; |
29 | extern int no_x2apic_optout; | 32 | extern int no_x2apic_optout; |
@@ -46,6 +49,11 @@ struct irq_remap_ops { | |||
46 | 49 | ||
47 | /* Enable fault handling */ | 50 | /* Enable fault handling */ |
48 | int (*enable_faulting)(void); | 51 | int (*enable_faulting)(void); |
52 | |||
53 | /* IO-APIC setup routine */ | ||
54 | int (*setup_ioapic_entry)(int irq, struct IO_APIC_route_entry *, | ||
55 | unsigned int, int, | ||
56 | struct io_apic_irq_attr *); | ||
49 | }; | 57 | }; |
50 | 58 | ||
51 | extern struct irq_remap_ops intel_irq_remap_ops; | 59 | extern struct irq_remap_ops intel_irq_remap_ops; |