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/intel_intr_remapping.c | |
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/intel_intr_remapping.c')
-rw-r--r-- | drivers/iommu/intel_intr_remapping.c | 97 |
1 files changed, 97 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 | }; |