diff options
author | David Woodhouse <David.Woodhouse@intel.com> | 2009-06-29 07:30:54 -0400 |
---|---|---|
committer | David Woodhouse <David.Woodhouse@intel.com> | 2009-06-29 22:53:31 -0400 |
commit | 9051aa0268dc1c3e42cd79a802b0af1f2bfcadae (patch) | |
tree | 2439a585889486158728d3d16587738112b67a36 /drivers/pci | |
parent | e1605495c716ef4eebdb7606bcd1b593f28e2837 (diff) |
intel-iommu: Combine domain_pfn_mapping() and domain_sg_mapping()
Signed-off-by: David Woodhouse <David.Woodhouse@intel.com>
Diffstat (limited to 'drivers/pci')
-rw-r--r-- | drivers/pci/intel-iommu.c | 62 |
1 files changed, 22 insertions, 40 deletions
diff --git a/drivers/pci/intel-iommu.c b/drivers/pci/intel-iommu.c index 28bd5f2d78fc..14308533b1cb 100644 --- a/drivers/pci/intel-iommu.c +++ b/drivers/pci/intel-iommu.c | |||
@@ -1635,14 +1635,14 @@ static int domain_context_mapped(struct pci_dev *pdev) | |||
1635 | tmp->devfn); | 1635 | tmp->devfn); |
1636 | } | 1636 | } |
1637 | 1637 | ||
1638 | static int domain_sg_mapping(struct dmar_domain *domain, unsigned long iov_pfn, | 1638 | static int __domain_mapping(struct dmar_domain *domain, unsigned long iov_pfn, |
1639 | struct scatterlist *sg, unsigned long nr_pages, | 1639 | struct scatterlist *sg, unsigned long phys_pfn, |
1640 | int prot) | 1640 | unsigned long nr_pages, int prot) |
1641 | { | 1641 | { |
1642 | struct dma_pte *first_pte = NULL, *pte = NULL; | 1642 | struct dma_pte *first_pte = NULL, *pte = NULL; |
1643 | uint64_t pteval; | 1643 | phys_addr_t uninitialized_var(pteval); |
1644 | int addr_width = agaw_to_width(domain->agaw) - VTD_PAGE_SHIFT; | 1644 | int addr_width = agaw_to_width(domain->agaw) - VTD_PAGE_SHIFT; |
1645 | unsigned long sg_res = 0; | 1645 | unsigned long sg_res; |
1646 | 1646 | ||
1647 | BUG_ON(addr_width < BITS_PER_LONG && (iov_pfn + nr_pages - 1) >> addr_width); | 1647 | BUG_ON(addr_width < BITS_PER_LONG && (iov_pfn + nr_pages - 1) >> addr_width); |
1648 | 1648 | ||
@@ -1651,6 +1651,13 @@ static int domain_sg_mapping(struct dmar_domain *domain, unsigned long iov_pfn, | |||
1651 | 1651 | ||
1652 | prot &= DMA_PTE_READ | DMA_PTE_WRITE | DMA_PTE_SNP; | 1652 | prot &= DMA_PTE_READ | DMA_PTE_WRITE | DMA_PTE_SNP; |
1653 | 1653 | ||
1654 | if (sg) | ||
1655 | sg_res = 0; | ||
1656 | else { | ||
1657 | sg_res = nr_pages + 1; | ||
1658 | pteval = ((phys_addr_t)phys_pfn << VTD_PAGE_SHIFT) | prot; | ||
1659 | } | ||
1660 | |||
1654 | while (nr_pages--) { | 1661 | while (nr_pages--) { |
1655 | if (!sg_res) { | 1662 | if (!sg_res) { |
1656 | sg_res = (sg->offset + sg->length + VTD_PAGE_SIZE - 1) >> VTD_PAGE_SHIFT; | 1663 | sg_res = (sg->offset + sg->length + VTD_PAGE_SIZE - 1) >> VTD_PAGE_SHIFT; |
@@ -1685,43 +1692,18 @@ static int domain_sg_mapping(struct dmar_domain *domain, unsigned long iov_pfn, | |||
1685 | return 0; | 1692 | return 0; |
1686 | } | 1693 | } |
1687 | 1694 | ||
1688 | static int domain_pfn_mapping(struct dmar_domain *domain, unsigned long iov_pfn, | 1695 | static inline int domain_sg_mapping(struct dmar_domain *domain, unsigned long iov_pfn, |
1689 | unsigned long phys_pfn, unsigned long nr_pages, | 1696 | struct scatterlist *sg, unsigned long nr_pages, |
1690 | int prot) | 1697 | int prot) |
1691 | { | 1698 | { |
1692 | struct dma_pte *first_pte = NULL, *pte = NULL; | 1699 | return __domain_mapping(domain, iov_pfn, sg, 0, nr_pages, prot); |
1693 | int addr_width = agaw_to_width(domain->agaw) - VTD_PAGE_SHIFT; | 1700 | } |
1694 | |||
1695 | BUG_ON(addr_width < BITS_PER_LONG && (iov_pfn + nr_pages - 1) >> addr_width); | ||
1696 | |||
1697 | if ((prot & (DMA_PTE_READ|DMA_PTE_WRITE)) == 0) | ||
1698 | return -EINVAL; | ||
1699 | |||
1700 | prot &= DMA_PTE_READ | DMA_PTE_WRITE | DMA_PTE_SNP; | ||
1701 | 1701 | ||
1702 | while (nr_pages--) { | 1702 | static inline int domain_pfn_mapping(struct dmar_domain *domain, unsigned long iov_pfn, |
1703 | if (!pte) { | 1703 | unsigned long phys_pfn, unsigned long nr_pages, |
1704 | first_pte = pte = pfn_to_dma_pte(domain, iov_pfn); | 1704 | int prot) |
1705 | if (!pte) | 1705 | { |
1706 | return -ENOMEM; | 1706 | return __domain_mapping(domain, iov_pfn, NULL, phys_pfn, nr_pages, prot); |
1707 | } | ||
1708 | /* We don't need lock here, nobody else | ||
1709 | * touches the iova range | ||
1710 | */ | ||
1711 | BUG_ON(dma_pte_addr(pte)); | ||
1712 | pte->val = (phys_pfn << VTD_PAGE_SHIFT) | prot; | ||
1713 | pte++; | ||
1714 | if (!nr_pages || | ||
1715 | (unsigned long)pte >> VTD_PAGE_SHIFT != | ||
1716 | (unsigned long)first_pte >> VTD_PAGE_SHIFT) { | ||
1717 | domain_flush_cache(domain, first_pte, | ||
1718 | (void *)pte - (void *)first_pte); | ||
1719 | pte = NULL; | ||
1720 | } | ||
1721 | iov_pfn++; | ||
1722 | phys_pfn++; | ||
1723 | } | ||
1724 | return 0; | ||
1725 | } | 1707 | } |
1726 | 1708 | ||
1727 | static void iommu_detach_dev(struct intel_iommu *iommu, u8 bus, u8 devfn) | 1709 | static void iommu_detach_dev(struct intel_iommu *iommu, u8 bus, u8 devfn) |