aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/pci/intr_remapping.c40
1 files changed, 26 insertions, 14 deletions
diff --git a/drivers/pci/intr_remapping.c b/drivers/pci/intr_remapping.c
index 1e83c8c5f985..44025a0c2bb6 100644
--- a/drivers/pci/intr_remapping.c
+++ b/drivers/pci/intr_remapping.c
@@ -314,7 +314,8 @@ int modify_irte(int irq, struct irte *irte_modified)
314 index = irq_iommu->irte_index + irq_iommu->sub_handle; 314 index = irq_iommu->irte_index + irq_iommu->sub_handle;
315 irte = &iommu->ir_table->base[index]; 315 irte = &iommu->ir_table->base[index];
316 316
317 set_64bit((unsigned long *)irte, irte_modified->low); 317 set_64bit((unsigned long *)&irte->low, irte_modified->low);
318 set_64bit((unsigned long *)&irte->high, irte_modified->high);
318 __iommu_flush_cache(iommu, irte, sizeof(*irte)); 319 __iommu_flush_cache(iommu, irte, sizeof(*irte));
319 320
320 rc = qi_flush_iec(iommu, index, 0); 321 rc = qi_flush_iec(iommu, index, 0);
@@ -369,12 +370,32 @@ struct intel_iommu *map_dev_to_ir(struct pci_dev *dev)
369 return drhd->iommu; 370 return drhd->iommu;
370} 371}
371 372
373static int clear_entries(struct irq_2_iommu *irq_iommu)
374{
375 struct irte *start, *entry, *end;
376 struct intel_iommu *iommu;
377 int index;
378
379 if (irq_iommu->sub_handle)
380 return 0;
381
382 iommu = irq_iommu->iommu;
383 index = irq_iommu->irte_index + irq_iommu->sub_handle;
384
385 start = iommu->ir_table->base + index;
386 end = start + (1 << irq_iommu->irte_mask);
387
388 for (entry = start; entry < end; entry++) {
389 set_64bit((unsigned long *)&entry->low, 0);
390 set_64bit((unsigned long *)&entry->high, 0);
391 }
392
393 return qi_flush_iec(iommu, index, irq_iommu->irte_mask);
394}
395
372int free_irte(int irq) 396int free_irte(int irq)
373{ 397{
374 int rc = 0; 398 int rc = 0;
375 int index, i;
376 struct irte *irte;
377 struct intel_iommu *iommu;
378 struct irq_2_iommu *irq_iommu; 399 struct irq_2_iommu *irq_iommu;
379 unsigned long flags; 400 unsigned long flags;
380 401
@@ -385,16 +406,7 @@ int free_irte(int irq)
385 return -1; 406 return -1;
386 } 407 }
387 408
388 iommu = irq_iommu->iommu; 409 rc = clear_entries(irq_iommu);
389
390 index = irq_iommu->irte_index + irq_iommu->sub_handle;
391 irte = &iommu->ir_table->base[index];
392
393 if (!irq_iommu->sub_handle) {
394 for (i = 0; i < (1 << irq_iommu->irte_mask); i++)
395 set_64bit((unsigned long *)(irte + i), 0);
396 rc = qi_flush_iec(iommu, index, irq_iommu->irte_mask);
397 }
398 410
399 irq_iommu->iommu = NULL; 411 irq_iommu->iommu = NULL;
400 irq_iommu->irte_index = 0; 412 irq_iommu->irte_index = 0;