diff options
author | Joerg Roedel <joerg.roedel@amd.com> | 2012-03-30 14:47:05 -0400 |
---|---|---|
committer | Joerg Roedel <joerg.roedel@amd.com> | 2012-05-07 08:35:00 -0400 |
commit | 5e2b930b0784a30c98dee8e9d79c1f84c31f7209 (patch) | |
tree | fae90c6dd23adf8d154ddd20492bf2efb61e1c29 /drivers/iommu | |
parent | 9d619f65722236e0e0c35467d1528caed206e439 (diff) |
iommu/vt-d: Convert MSI remapping setup to remap_ops
This patch introduces remapping-ops for setting ups MSI
interrupts.
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 | 97 | ||||
-rw-r--r-- | drivers/iommu/intr_remapping.c | 35 | ||||
-rw-r--r-- | drivers/iommu/intr_remapping.h | 16 |
3 files changed, 148 insertions, 0 deletions
diff --git a/drivers/iommu/intel_intr_remapping.c b/drivers/iommu/intel_intr_remapping.c index 44a6e04a070b..a3bae67ec43c 100644 --- a/drivers/iommu/intel_intr_remapping.c +++ b/drivers/iommu/intel_intr_remapping.c | |||
@@ -13,6 +13,7 @@ | |||
13 | #include <acpi/acpi.h> | 13 | #include <acpi/acpi.h> |
14 | #include <asm/intr_remapping.h> | 14 | #include <asm/intr_remapping.h> |
15 | #include <asm/pci-direct.h> | 15 | #include <asm/pci-direct.h> |
16 | #include <asm/msidef.h> | ||
16 | 17 | ||
17 | #include "intr_remapping.h" | 18 | #include "intr_remapping.h" |
18 | 19 | ||
@@ -955,6 +956,98 @@ intel_ioapic_set_affinity(struct irq_data *data, const struct cpumask *mask, | |||
955 | return 0; | 956 | return 0; |
956 | } | 957 | } |
957 | 958 | ||
959 | static void intel_compose_msi_msg(struct pci_dev *pdev, | ||
960 | unsigned int irq, unsigned int dest, | ||
961 | struct msi_msg *msg, u8 hpet_id) | ||
962 | { | ||
963 | struct irq_cfg *cfg; | ||
964 | struct irte irte; | ||
965 | u16 sub_handle; | ||
966 | int ir_index; | ||
967 | |||
968 | cfg = irq_get_chip_data(irq); | ||
969 | |||
970 | ir_index = map_irq_to_irte_handle(irq, &sub_handle); | ||
971 | BUG_ON(ir_index == -1); | ||
972 | |||
973 | prepare_irte(&irte, cfg->vector, dest); | ||
974 | |||
975 | /* Set source-id of interrupt request */ | ||
976 | if (pdev) | ||
977 | set_msi_sid(&irte, pdev); | ||
978 | else | ||
979 | set_hpet_sid(&irte, hpet_id); | ||
980 | |||
981 | modify_irte(irq, &irte); | ||
982 | |||
983 | msg->address_hi = MSI_ADDR_BASE_HI; | ||
984 | msg->data = sub_handle; | ||
985 | msg->address_lo = MSI_ADDR_BASE_LO | MSI_ADDR_IR_EXT_INT | | ||
986 | MSI_ADDR_IR_SHV | | ||
987 | MSI_ADDR_IR_INDEX1(ir_index) | | ||
988 | MSI_ADDR_IR_INDEX2(ir_index); | ||
989 | } | ||
990 | |||
991 | /* | ||
992 | * Map the PCI dev to the corresponding remapping hardware unit | ||
993 | * and allocate 'nvec' consecutive interrupt-remapping table entries | ||
994 | * in it. | ||
995 | */ | ||
996 | static int intel_msi_alloc_irq(struct pci_dev *dev, int irq, int nvec) | ||
997 | { | ||
998 | struct intel_iommu *iommu; | ||
999 | int index; | ||
1000 | |||
1001 | iommu = map_dev_to_ir(dev); | ||
1002 | if (!iommu) { | ||
1003 | printk(KERN_ERR | ||
1004 | "Unable to map PCI %s to iommu\n", pci_name(dev)); | ||
1005 | return -ENOENT; | ||
1006 | } | ||
1007 | |||
1008 | index = alloc_irte(iommu, irq, nvec); | ||
1009 | if (index < 0) { | ||
1010 | printk(KERN_ERR | ||
1011 | "Unable to allocate %d IRTE for PCI %s\n", nvec, | ||
1012 | pci_name(dev)); | ||
1013 | return -ENOSPC; | ||
1014 | } | ||
1015 | return index; | ||
1016 | } | ||
1017 | |||
1018 | static int intel_msi_setup_irq(struct pci_dev *pdev, unsigned int irq, | ||
1019 | int index, int sub_handle) | ||
1020 | { | ||
1021 | struct intel_iommu *iommu; | ||
1022 | |||
1023 | iommu = map_dev_to_ir(pdev); | ||
1024 | if (!iommu) | ||
1025 | return -ENOENT; | ||
1026 | /* | ||
1027 | * setup the mapping between the irq and the IRTE | ||
1028 | * base index, the sub_handle pointing to the | ||
1029 | * appropriate interrupt remap table entry. | ||
1030 | */ | ||
1031 | set_irte_irq(irq, iommu, index, sub_handle); | ||
1032 | |||
1033 | return 0; | ||
1034 | } | ||
1035 | |||
1036 | static int intel_setup_hpet_msi(unsigned int irq, unsigned int id) | ||
1037 | { | ||
1038 | struct intel_iommu *iommu = map_hpet_to_ir(id); | ||
1039 | int index; | ||
1040 | |||
1041 | if (!iommu) | ||
1042 | return -1; | ||
1043 | |||
1044 | index = alloc_irte(iommu, irq, 1); | ||
1045 | if (index < 0) | ||
1046 | return -1; | ||
1047 | |||
1048 | return 0; | ||
1049 | } | ||
1050 | |||
958 | struct irq_remap_ops intel_irq_remap_ops = { | 1051 | struct irq_remap_ops intel_irq_remap_ops = { |
959 | .supported = intel_intr_remapping_supported, | 1052 | .supported = intel_intr_remapping_supported, |
960 | .hardware_init = dmar_table_init, | 1053 | .hardware_init = dmar_table_init, |
@@ -965,4 +1058,8 @@ struct irq_remap_ops intel_irq_remap_ops = { | |||
965 | .setup_ioapic_entry = intel_setup_ioapic_entry, | 1058 | .setup_ioapic_entry = intel_setup_ioapic_entry, |
966 | .set_affinity = intel_ioapic_set_affinity, | 1059 | .set_affinity = intel_ioapic_set_affinity, |
967 | .free_irq = free_irte, | 1060 | .free_irq = free_irte, |
1061 | .compose_msi_msg = intel_compose_msi_msg, | ||
1062 | .msi_alloc_irq = intel_msi_alloc_irq, | ||
1063 | .msi_setup_irq = intel_msi_setup_irq, | ||
1064 | .setup_hpet_msi = intel_setup_hpet_msi, | ||
968 | }; | 1065 | }; |
diff --git a/drivers/iommu/intr_remapping.c b/drivers/iommu/intr_remapping.c index a68d304f9729..9dc179316ba1 100644 --- a/drivers/iommu/intr_remapping.c +++ b/drivers/iommu/intr_remapping.c | |||
@@ -127,3 +127,38 @@ void intr_free_irq(int irq) | |||
127 | 127 | ||
128 | remap_ops->free_irq(irq); | 128 | remap_ops->free_irq(irq); |
129 | } | 129 | } |
130 | |||
131 | void intr_compose_msi_msg(struct pci_dev *pdev, | ||
132 | unsigned int irq, unsigned int dest, | ||
133 | struct msi_msg *msg, u8 hpet_id) | ||
134 | { | ||
135 | if (!remap_ops || !remap_ops->compose_msi_msg) | ||
136 | return; | ||
137 | |||
138 | remap_ops->compose_msi_msg(pdev, irq, dest, msg, hpet_id); | ||
139 | } | ||
140 | |||
141 | int intr_msi_alloc_irq(struct pci_dev *pdev, int irq, int nvec) | ||
142 | { | ||
143 | if (!remap_ops || !remap_ops->msi_alloc_irq) | ||
144 | return -ENODEV; | ||
145 | |||
146 | return remap_ops->msi_alloc_irq(pdev, irq, nvec); | ||
147 | } | ||
148 | |||
149 | int intr_msi_setup_irq(struct pci_dev *pdev, unsigned int irq, | ||
150 | int index, int sub_handle) | ||
151 | { | ||
152 | if (!remap_ops || !remap_ops->msi_setup_irq) | ||
153 | return -ENODEV; | ||
154 | |||
155 | return remap_ops->msi_setup_irq(pdev, irq, index, sub_handle); | ||
156 | } | ||
157 | |||
158 | int intr_setup_hpet_msi(unsigned int irq, unsigned int id) | ||
159 | { | ||
160 | if (!remap_ops || !remap_ops->setup_hpet_msi) | ||
161 | return -ENODEV; | ||
162 | |||
163 | return remap_ops->setup_hpet_msi(irq, id); | ||
164 | } | ||
diff --git a/drivers/iommu/intr_remapping.h b/drivers/iommu/intr_remapping.h index 57485539383d..6f4ea0a387b1 100644 --- a/drivers/iommu/intr_remapping.h +++ b/drivers/iommu/intr_remapping.h | |||
@@ -28,6 +28,8 @@ struct IO_APIC_route_entry; | |||
28 | struct io_apic_irq_attr; | 28 | struct io_apic_irq_attr; |
29 | struct irq_data; | 29 | struct irq_data; |
30 | struct cpumask; | 30 | struct cpumask; |
31 | struct pci_dev; | ||
32 | struct msi_msg; | ||
31 | 33 | ||
32 | extern int disable_intremap; | 34 | extern int disable_intremap; |
33 | extern int disable_sourceid_checking; | 35 | extern int disable_sourceid_checking; |
@@ -63,6 +65,20 @@ struct irq_remap_ops { | |||
63 | 65 | ||
64 | /* Free an IRQ */ | 66 | /* Free an IRQ */ |
65 | int (*free_irq)(int); | 67 | int (*free_irq)(int); |
68 | |||
69 | /* Create MSI msg to use for interrupt remapping */ | ||
70 | void (*compose_msi_msg)(struct pci_dev *, | ||
71 | unsigned int, unsigned int, | ||
72 | struct msi_msg *, u8); | ||
73 | |||
74 | /* Allocate remapping resources for MSI */ | ||
75 | int (*msi_alloc_irq)(struct pci_dev *, int, int); | ||
76 | |||
77 | /* Setup the remapped MSI irq */ | ||
78 | int (*msi_setup_irq)(struct pci_dev *, unsigned int, int, int); | ||
79 | |||
80 | /* Setup interrupt remapping for an HPET MSI */ | ||
81 | int (*setup_hpet_msi)(unsigned int, unsigned int); | ||
66 | }; | 82 | }; |
67 | 83 | ||
68 | extern struct irq_remap_ops intel_irq_remap_ops; | 84 | extern struct irq_remap_ops intel_irq_remap_ops; |