aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/iommu
diff options
context:
space:
mode:
authorJoerg Roedel <joerg.roedel@amd.com>2012-06-26 08:54:17 -0400
committerJoerg Roedel <joerg.roedel@amd.com>2012-09-28 11:43:51 -0400
commit0b4d48cb2240d1686b3f0da234f0c9da18576503 (patch)
tree31dc084d6fbfc220aa465f12d0f508720b0d091e /drivers/iommu
parent5527de744da61f55aaa9b804873923f95272e793 (diff)
iommu/amd: Implement MSI routines for interrupt remapping
Add routines to setup interrupt remapping for MSI interrupts. Signed-off-by: Joerg Roedel <joerg.roedel@amd.com>
Diffstat (limited to 'drivers/iommu')
-rw-r--r--drivers/iommu/amd_iommu.c74
1 files changed, 74 insertions, 0 deletions
diff --git a/drivers/iommu/amd_iommu.c b/drivers/iommu/amd_iommu.c
index 886b4c7fba72..bcf48156868b 100644
--- a/drivers/iommu/amd_iommu.c
+++ b/drivers/iommu/amd_iommu.c
@@ -4126,4 +4126,78 @@ static int free_irq(int irq)
4126 return 0; 4126 return 0;
4127} 4127}
4128 4128
4129static void compose_msi_msg(struct pci_dev *pdev,
4130 unsigned int irq, unsigned int dest,
4131 struct msi_msg *msg, u8 hpet_id)
4132{
4133 struct irq_2_iommu *irte_info;
4134 struct irq_cfg *cfg;
4135 union irte irte;
4136
4137 cfg = irq_get_chip_data(irq);
4138 if (!cfg)
4139 return;
4140
4141 irte_info = &cfg->irq_2_iommu;
4142
4143 irte.val = 0;
4144 irte.fields.vector = cfg->vector;
4145 irte.fields.int_type = apic->irq_delivery_mode;
4146 irte.fields.destination = dest;
4147 irte.fields.dm = apic->irq_dest_mode;
4148 irte.fields.valid = 1;
4149
4150 modify_irte(irte_info->sub_handle, irte_info->irte_index, irte);
4151
4152 msg->address_hi = MSI_ADDR_BASE_HI;
4153 msg->address_lo = MSI_ADDR_BASE_LO;
4154 msg->data = irte_info->irte_index;
4155}
4156
4157static int msi_alloc_irq(struct pci_dev *pdev, int irq, int nvec)
4158{
4159 struct irq_cfg *cfg;
4160 int index;
4161 u16 devid;
4162
4163 if (!pdev)
4164 return -EINVAL;
4165
4166 cfg = irq_get_chip_data(irq);
4167 if (!cfg)
4168 return -EINVAL;
4169
4170 devid = get_device_id(&pdev->dev);
4171 index = alloc_irq_index(cfg, devid, nvec);
4172
4173 return index < 0 ? MAX_IRQS_PER_TABLE : index;
4174}
4175
4176static int msi_setup_irq(struct pci_dev *pdev, unsigned int irq,
4177 int index, int offset)
4178{
4179 struct irq_2_iommu *irte_info;
4180 struct irq_cfg *cfg;
4181 u16 devid;
4182
4183 if (!pdev)
4184 return -EINVAL;
4185
4186 cfg = irq_get_chip_data(irq);
4187 if (!cfg)
4188 return -EINVAL;
4189
4190 if (index >= MAX_IRQS_PER_TABLE)
4191 return 0;
4192
4193 devid = get_device_id(&pdev->dev);
4194 irte_info = &cfg->irq_2_iommu;
4195
4196 irte_info->sub_handle = devid;
4197 irte_info->irte_index = index + offset;
4198 irte_info->iommu = (void *)cfg;
4199
4200 return 0;
4201}
4202
4129#endif 4203#endif