diff options
-rw-r--r-- | drivers/pci/intel-iommu.c | 95 | ||||
-rw-r--r-- | include/linux/intel-iommu.h | 8 |
2 files changed, 53 insertions, 50 deletions
diff --git a/drivers/pci/intel-iommu.c b/drivers/pci/intel-iommu.c index fc5f2dbf5323..509470419130 100644 --- a/drivers/pci/intel-iommu.c +++ b/drivers/pci/intel-iommu.c | |||
@@ -567,27 +567,6 @@ static int __iommu_flush_context(struct intel_iommu *iommu, | |||
567 | return 0; | 567 | return 0; |
568 | } | 568 | } |
569 | 569 | ||
570 | static int inline iommu_flush_context_global(struct intel_iommu *iommu, | ||
571 | int non_present_entry_flush) | ||
572 | { | ||
573 | return __iommu_flush_context(iommu, 0, 0, 0, DMA_CCMD_GLOBAL_INVL, | ||
574 | non_present_entry_flush); | ||
575 | } | ||
576 | |||
577 | static int inline iommu_flush_context_domain(struct intel_iommu *iommu, u16 did, | ||
578 | int non_present_entry_flush) | ||
579 | { | ||
580 | return __iommu_flush_context(iommu, did, 0, 0, DMA_CCMD_DOMAIN_INVL, | ||
581 | non_present_entry_flush); | ||
582 | } | ||
583 | |||
584 | static int inline iommu_flush_context_device(struct intel_iommu *iommu, | ||
585 | u16 did, u16 source_id, u8 function_mask, int non_present_entry_flush) | ||
586 | { | ||
587 | return __iommu_flush_context(iommu, did, source_id, function_mask, | ||
588 | DMA_CCMD_DEVICE_INVL, non_present_entry_flush); | ||
589 | } | ||
590 | |||
591 | /* return value determine if we need a write buffer flush */ | 570 | /* return value determine if we need a write buffer flush */ |
592 | static int __iommu_flush_iotlb(struct intel_iommu *iommu, u16 did, | 571 | static int __iommu_flush_iotlb(struct intel_iommu *iommu, u16 did, |
593 | u64 addr, unsigned int size_order, u64 type, | 572 | u64 addr, unsigned int size_order, u64 type, |
@@ -660,20 +639,6 @@ static int __iommu_flush_iotlb(struct intel_iommu *iommu, u16 did, | |||
660 | return 0; | 639 | return 0; |
661 | } | 640 | } |
662 | 641 | ||
663 | static int inline iommu_flush_iotlb_global(struct intel_iommu *iommu, | ||
664 | int non_present_entry_flush) | ||
665 | { | ||
666 | return __iommu_flush_iotlb(iommu, 0, 0, 0, DMA_TLB_GLOBAL_FLUSH, | ||
667 | non_present_entry_flush); | ||
668 | } | ||
669 | |||
670 | static int inline iommu_flush_iotlb_dsi(struct intel_iommu *iommu, u16 did, | ||
671 | int non_present_entry_flush) | ||
672 | { | ||
673 | return __iommu_flush_iotlb(iommu, did, 0, 0, DMA_TLB_DSI_FLUSH, | ||
674 | non_present_entry_flush); | ||
675 | } | ||
676 | |||
677 | static int iommu_flush_iotlb_psi(struct intel_iommu *iommu, u16 did, | 642 | static int iommu_flush_iotlb_psi(struct intel_iommu *iommu, u16 did, |
678 | u64 addr, unsigned int pages, int non_present_entry_flush) | 643 | u64 addr, unsigned int pages, int non_present_entry_flush) |
679 | { | 644 | { |
@@ -684,8 +649,9 @@ static int iommu_flush_iotlb_psi(struct intel_iommu *iommu, u16 did, | |||
684 | 649 | ||
685 | /* Fallback to domain selective flush if no PSI support */ | 650 | /* Fallback to domain selective flush if no PSI support */ |
686 | if (!cap_pgsel_inv(iommu->cap)) | 651 | if (!cap_pgsel_inv(iommu->cap)) |
687 | return iommu_flush_iotlb_dsi(iommu, did, | 652 | return iommu->flush.flush_iotlb(iommu, did, 0, 0, |
688 | non_present_entry_flush); | 653 | DMA_TLB_DSI_FLUSH, |
654 | non_present_entry_flush); | ||
689 | 655 | ||
690 | /* | 656 | /* |
691 | * PSI requires page size to be 2 ^ x, and the base address is naturally | 657 | * PSI requires page size to be 2 ^ x, and the base address is naturally |
@@ -694,11 +660,12 @@ static int iommu_flush_iotlb_psi(struct intel_iommu *iommu, u16 did, | |||
694 | mask = ilog2(__roundup_pow_of_two(pages)); | 660 | mask = ilog2(__roundup_pow_of_two(pages)); |
695 | /* Fallback to domain selective flush if size is too big */ | 661 | /* Fallback to domain selective flush if size is too big */ |
696 | if (mask > cap_max_amask_val(iommu->cap)) | 662 | if (mask > cap_max_amask_val(iommu->cap)) |
697 | return iommu_flush_iotlb_dsi(iommu, did, | 663 | return iommu->flush.flush_iotlb(iommu, did, 0, 0, |
698 | non_present_entry_flush); | 664 | DMA_TLB_DSI_FLUSH, non_present_entry_flush); |
699 | 665 | ||
700 | return __iommu_flush_iotlb(iommu, did, addr, mask, | 666 | return iommu->flush.flush_iotlb(iommu, did, addr, mask, |
701 | DMA_TLB_PSI_FLUSH, non_present_entry_flush); | 667 | DMA_TLB_PSI_FLUSH, |
668 | non_present_entry_flush); | ||
702 | } | 669 | } |
703 | 670 | ||
704 | static void iommu_disable_protect_mem_regions(struct intel_iommu *iommu) | 671 | static void iommu_disable_protect_mem_regions(struct intel_iommu *iommu) |
@@ -1204,11 +1171,13 @@ static int domain_context_mapping_one(struct dmar_domain *domain, | |||
1204 | __iommu_flush_cache(iommu, context, sizeof(*context)); | 1171 | __iommu_flush_cache(iommu, context, sizeof(*context)); |
1205 | 1172 | ||
1206 | /* it's a non-present to present mapping */ | 1173 | /* it's a non-present to present mapping */ |
1207 | if (iommu_flush_context_device(iommu, domain->id, | 1174 | if (iommu->flush.flush_context(iommu, domain->id, |
1208 | (((u16)bus) << 8) | devfn, DMA_CCMD_MASK_NOBIT, 1)) | 1175 | (((u16)bus) << 8) | devfn, DMA_CCMD_MASK_NOBIT, |
1176 | DMA_CCMD_DEVICE_INVL, 1)) | ||
1209 | iommu_flush_write_buffer(iommu); | 1177 | iommu_flush_write_buffer(iommu); |
1210 | else | 1178 | else |
1211 | iommu_flush_iotlb_dsi(iommu, 0, 0); | 1179 | iommu->flush.flush_iotlb(iommu, 0, 0, 0, DMA_TLB_DSI_FLUSH, 0); |
1180 | |||
1212 | spin_unlock_irqrestore(&iommu->lock, flags); | 1181 | spin_unlock_irqrestore(&iommu->lock, flags); |
1213 | return 0; | 1182 | return 0; |
1214 | } | 1183 | } |
@@ -1310,8 +1279,10 @@ domain_page_mapping(struct dmar_domain *domain, dma_addr_t iova, | |||
1310 | static void detach_domain_for_dev(struct dmar_domain *domain, u8 bus, u8 devfn) | 1279 | static void detach_domain_for_dev(struct dmar_domain *domain, u8 bus, u8 devfn) |
1311 | { | 1280 | { |
1312 | clear_context_table(domain->iommu, bus, devfn); | 1281 | clear_context_table(domain->iommu, bus, devfn); |
1313 | iommu_flush_context_global(domain->iommu, 0); | 1282 | domain->iommu->flush.flush_context(domain->iommu, 0, 0, 0, |
1314 | iommu_flush_iotlb_global(domain->iommu, 0); | 1283 | DMA_CCMD_GLOBAL_INVL, 0); |
1284 | domain->iommu->flush.flush_iotlb(domain->iommu, 0, 0, 0, | ||
1285 | DMA_TLB_GLOBAL_FLUSH, 0); | ||
1315 | } | 1286 | } |
1316 | 1287 | ||
1317 | static void domain_remove_dev_info(struct dmar_domain *domain) | 1288 | static void domain_remove_dev_info(struct dmar_domain *domain) |
@@ -1662,6 +1633,28 @@ int __init init_dmars(void) | |||
1662 | } | 1633 | } |
1663 | } | 1634 | } |
1664 | 1635 | ||
1636 | for_each_drhd_unit(drhd) { | ||
1637 | if (drhd->ignored) | ||
1638 | continue; | ||
1639 | |||
1640 | iommu = drhd->iommu; | ||
1641 | if (dmar_enable_qi(iommu)) { | ||
1642 | /* | ||
1643 | * Queued Invalidate not enabled, use Register Based | ||
1644 | * Invalidate | ||
1645 | */ | ||
1646 | iommu->flush.flush_context = __iommu_flush_context; | ||
1647 | iommu->flush.flush_iotlb = __iommu_flush_iotlb; | ||
1648 | printk(KERN_INFO "IOMMU 0x%Lx: using Register based " | ||
1649 | "invalidation\n", drhd->reg_base_addr); | ||
1650 | } else { | ||
1651 | iommu->flush.flush_context = qi_flush_context; | ||
1652 | iommu->flush.flush_iotlb = qi_flush_iotlb; | ||
1653 | printk(KERN_INFO "IOMMU 0x%Lx: using Queued " | ||
1654 | "invalidation\n", drhd->reg_base_addr); | ||
1655 | } | ||
1656 | } | ||
1657 | |||
1665 | /* | 1658 | /* |
1666 | * For each rmrr | 1659 | * For each rmrr |
1667 | * for each dev attached to rmrr | 1660 | * for each dev attached to rmrr |
@@ -1714,9 +1707,10 @@ int __init init_dmars(void) | |||
1714 | 1707 | ||
1715 | iommu_set_root_entry(iommu); | 1708 | iommu_set_root_entry(iommu); |
1716 | 1709 | ||
1717 | iommu_flush_context_global(iommu, 0); | 1710 | iommu->flush.flush_context(iommu, 0, 0, 0, DMA_CCMD_GLOBAL_INVL, |
1718 | iommu_flush_iotlb_global(iommu, 0); | 1711 | 0); |
1719 | 1712 | iommu->flush.flush_iotlb(iommu, 0, 0, 0, DMA_TLB_GLOBAL_FLUSH, | |
1713 | 0); | ||
1720 | iommu_disable_protect_mem_regions(iommu); | 1714 | iommu_disable_protect_mem_regions(iommu); |
1721 | 1715 | ||
1722 | ret = iommu_enable_translation(iommu); | 1716 | ret = iommu_enable_translation(iommu); |
@@ -1891,7 +1885,8 @@ static void flush_unmaps(void) | |||
1891 | struct intel_iommu *iommu = | 1885 | struct intel_iommu *iommu = |
1892 | deferred_flush[i].domain[0]->iommu; | 1886 | deferred_flush[i].domain[0]->iommu; |
1893 | 1887 | ||
1894 | iommu_flush_iotlb_global(iommu, 0); | 1888 | iommu->flush.flush_iotlb(iommu, 0, 0, 0, |
1889 | DMA_TLB_GLOBAL_FLUSH, 0); | ||
1895 | for (j = 0; j < deferred_flush[i].next; j++) { | 1890 | for (j = 0; j < deferred_flush[i].next; j++) { |
1896 | __free_iova(&deferred_flush[i].domain[j]->iovad, | 1891 | __free_iova(&deferred_flush[i].domain[j]->iovad, |
1897 | deferred_flush[i].iova[j]); | 1892 | deferred_flush[i].iova[j]); |
diff --git a/include/linux/intel-iommu.h b/include/linux/intel-iommu.h index 0c5f5e49107b..afb0d2a5b7cd 100644 --- a/include/linux/intel-iommu.h +++ b/include/linux/intel-iommu.h | |||
@@ -278,6 +278,13 @@ struct ir_table { | |||
278 | }; | 278 | }; |
279 | #endif | 279 | #endif |
280 | 280 | ||
281 | struct iommu_flush { | ||
282 | int (*flush_context)(struct intel_iommu *iommu, u16 did, u16 sid, u8 fm, | ||
283 | u64 type, int non_present_entry_flush); | ||
284 | int (*flush_iotlb)(struct intel_iommu *iommu, u16 did, u64 addr, | ||
285 | unsigned int size_order, u64 type, int non_present_entry_flush); | ||
286 | }; | ||
287 | |||
281 | struct intel_iommu { | 288 | struct intel_iommu { |
282 | void __iomem *reg; /* Pointer to hardware regs, virtual addr */ | 289 | void __iomem *reg; /* Pointer to hardware regs, virtual addr */ |
283 | u64 cap; | 290 | u64 cap; |
@@ -297,6 +304,7 @@ struct intel_iommu { | |||
297 | unsigned char name[7]; /* Device Name */ | 304 | unsigned char name[7]; /* Device Name */ |
298 | struct msi_msg saved_msg; | 305 | struct msi_msg saved_msg; |
299 | struct sys_device sysdev; | 306 | struct sys_device sysdev; |
307 | struct iommu_flush flush; | ||
300 | #endif | 308 | #endif |
301 | struct q_inval *qi; /* Queued invalidation info */ | 309 | struct q_inval *qi; /* Queued invalidation info */ |
302 | #ifdef CONFIG_INTR_REMAP | 310 | #ifdef CONFIG_INTR_REMAP |