Sophie

Sophie

distrib > Scientific%20Linux > 5x > x86_64 > media > main-src > by-pkgid > d0a35cd31c1125e2132804d68547073d > files > 2850

kernel-2.6.18-194.26.1.el5.src.rpm

From: Don Dutile <ddutile@redhat.com>
Date: Fri, 15 May 2009 10:21:22 -0400
Subject: [pci] IOMMU phys_addr cleanup
Message-id: 4A0D7A62.7090201@redhat.com
O-Subject: [RHEL5.4 PATCH 3/3] IOMMU phys_addr cleanup
Bugzilla: 500901
RH-Acked-by: Rik van Riel <riel@redhat.com>
RH-Acked-by: Justin M. Forbes <jforbes@redhat.com>
RH-Acked-by: Chris Wright <chrisw@redhat.com>

BZ 500901

Chris Wright's review of the VTd support for RHEL5.4
had feedback that the phys_addr implementation was less
than ideal.
The VT-d support was included in 5.4 build before a
refresh of the patch could be done to implement
the recommended cleanup.

Since the phys_addr cleanup affect the IOMMU
API, the AMD IOMMU support had to be (minimally) tweaked
as well.

  arch/x86_64/kernel/amd_iommu.c |    9 +++----
  drivers/base/iommu.c           |    4 +-
  drivers/pci/dmar.c             |    2 +-
  drivers/pci/intel-iommu.c      |   51 +++++++++++++++++++--------------------
  include/asm-x86_64/types.h     |    1 +
  include/linux/intel-iommu.h    |    7 -----
  include/linux/iommu.h          |   12 ++++----
  7 files changed, 39 insertions(+), 47 deletions(-)

Please review & ack.
Note: this bz is a beta blocker for 5.4.

- Don

diff --git a/arch/x86_64/kernel/amd_iommu.c b/arch/x86_64/kernel/amd_iommu.c
index bccdb78..dab0ff5 100644
--- a/arch/x86_64/kernel/amd_iommu.c
+++ b/arch/x86_64/kernel/amd_iommu.c
@@ -1851,11 +1851,10 @@ static int amd_iommu_attach_device(struct iommu_domain *dom,
 }
 
 static int amd_iommu_map_range(struct iommu_domain *dom,
-			       unsigned long iova, void *addr,
+			       unsigned long iova, phys_addr_t paddr,
 			       size_t size, int iommu_prot)
 {
 	struct protection_domain *domain = dom->priv;
-	unsigned long paddr = (unsigned long)addr;
 	unsigned long i,  npages = iommu_num_pages(paddr, size, PAGE_SIZE);
 	int prot = 0;
 	int ret;
@@ -1897,13 +1896,13 @@ static void amd_iommu_unmap_range(struct iommu_domain *dom,
 	iommu_flush_domain(domain->id);
 }
 
-static void *
+static phys_addr_t
 amd_iommu_iova_to_phys(struct iommu_domain *dom,
 		       unsigned long iova)
 {
 	struct protection_domain *domain = dom->priv;
 	unsigned long offset = iova & ~PAGE_MASK;
-	unsigned long paddr;
+	phys_addr_t paddr;
 	u64 *pte;
 
 	pte = &domain->pt_root[IOMMU_PTE_L2_INDEX(iova)];
@@ -1926,7 +1925,7 @@ amd_iommu_iova_to_phys(struct iommu_domain *dom,
 	paddr  = *pte & IOMMU_PAGE_MASK;
 	paddr |= offset;
 
-	return (void *)paddr;
+	return paddr;
 }
 
 static struct iommu_ops amd_iommu_ops = {
diff --git a/drivers/base/iommu.c b/drivers/base/iommu.c
index d4ce2de..b60ecbe 100644
--- a/drivers/base/iommu.c
+++ b/drivers/base/iommu.c
@@ -80,7 +80,7 @@ void iommu_detach_device(struct iommu_domain *domain, struct device *dev)
 EXPORT_SYMBOL_GPL(iommu_detach_device);
 
 int iommu_map_range(struct iommu_domain *domain, unsigned long iova,
-		    void *paddr, size_t size, int prot)
+		    phys_addr_t paddr, size_t size, int prot)
 {
 	return iommu_ops->map(domain, iova, paddr, size, prot);
 }
@@ -93,7 +93,7 @@ void iommu_unmap_range(struct iommu_domain *domain, unsigned long iova,
 }
 EXPORT_SYMBOL_GPL(iommu_unmap_range);
 
-void *iommu_iova_to_phys(struct iommu_domain *domain,
+phys_addr_t iommu_iova_to_phys(struct iommu_domain *domain,
 			       unsigned long iova)
 {
 	return iommu_ops->iova_to_phys(domain, iova);
diff --git a/drivers/pci/dmar.c b/drivers/pci/dmar.c
index 51a587e..e87ebbd 100644
--- a/drivers/pci/dmar.c
+++ b/drivers/pci/dmar.c
@@ -974,7 +974,7 @@ static int dmar_fault_do_one(struct intel_iommu *iommu, int type,
 #define PRIMARY_FAULT_REG_LEN (16)
 irqreturn_t dmar_fault(int irq, void *dev_id, struct pt_regs *regs)
 {
-	struct intel_iommu *iommu = (struct intel_iommu *)dev_id;
+	struct intel_iommu *iommu = dev_id;
 	int reg, fault_index;
 	u32 fault_status;
 	unsigned long flag;
diff --git a/drivers/pci/intel-iommu.c b/drivers/pci/intel-iommu.c
index ae1f4d2..b6fbb16 100644
--- a/drivers/pci/intel-iommu.c
+++ b/drivers/pci/intel-iommu.c
@@ -2149,7 +2149,7 @@ static dma_addr_t __intel_map_single(struct device *hwdev, phys_addr_t paddr,
 
 	BUG_ON(dir == DMA_NONE);
 	if (pdev->iommu == DUMMY_DEVICE_DOMAIN_INFO)
-		return (dma_addr_t)paddr;
+		return paddr;
 
 	domain = get_valid_domain_for_dev(pdev);
 	if (!domain)
@@ -2162,7 +2162,7 @@ static dma_addr_t __intel_map_single(struct device *hwdev, phys_addr_t paddr,
 	if (!iova)
 		goto error;
 
-	start_paddr = (phys_addr_t)((unsigned long)iova->pfn_lo << PAGE_SHIFT);
+	start_paddr = (phys_addr_t)iova->pfn_lo << PAGE_SHIFT;
 
 	/*
 	 * Check if DMAR supports zero-length reads on write only
@@ -2179,31 +2179,31 @@ static dma_addr_t __intel_map_single(struct device *hwdev, phys_addr_t paddr,
 	 * might have two guest_addr mapping to the same host paddr, but this
 	 * is not a big problem
 	 */
-	ret = domain_page_mapping(domain, (dma_addr_t)start_paddr,
+	ret = domain_page_mapping(domain, start_paddr,
 		((u64)paddr) & PAGE_MASK, size, prot);
 	if (ret)
 		goto error;
 
 	/* it's a non-present to present mapping */
 	ret = iommu_flush_iotlb_psi(iommu, domain->id,
-			(u64)start_paddr, size >> VTD_PAGE_SHIFT, 1);
+			start_paddr, size >> VTD_PAGE_SHIFT, 1);
 	if (ret)
 		iommu_flush_write_buffer(iommu);
 
-	return (dma_addr_t)start_paddr + ((u64)paddr & (~PAGE_MASK));
+	return start_paddr + ((u64)paddr & (~PAGE_MASK));
 
 error:
 	if (iova)
 		__free_iova(&domain->iovad, iova);
-	printk(KERN_ERR"Device %s request: %lx@%llx dir %d --- failed\n",
+	printk(KERN_ERR"Device %s request: %zx@%llx dir %d --- failed\n",
 		pci_name(pdev), size, (unsigned long long)paddr, dir);
 	return 0;
 }
 
-dma_addr_t intel_map_single(struct device *hwdev, void *vaddr,
+static dma_addr_t intel_map_single(struct device *hwdev, void *vaddr,
 			    size_t size, int dir)
 {
-	return __intel_map_single(hwdev, (phys_addr_t)(virt_to_phys(vaddr)),
+	return __intel_map_single(hwdev, virt_to_phys(vaddr),
 				  size, dir, to_pci_dev(hwdev)->dma_mask);
 }
 
@@ -2268,7 +2268,7 @@ static void add_unmap(struct dmar_domain *dom, struct iova *iova)
 	spin_unlock_irqrestore(&async_umap_flush_lock, flags);
 }
 
-void intel_unmap_single(struct device *dev, dma_addr_t dev_addr, size_t size,
+static void intel_unmap_single(struct device *dev, dma_addr_t dev_addr, size_t size,
 			int dir)
 {
 	struct pci_dev *pdev = to_pci_dev(dev);
@@ -2313,7 +2313,7 @@ void intel_unmap_single(struct device *dev, dma_addr_t dev_addr, size_t size,
 	}
 }
 
-void *intel_alloc_coherent(struct device *hwdev, size_t size,
+static void *intel_alloc_coherent(struct device *hwdev, size_t size,
 			   dma_addr_t *dma_handle, gfp_t flags)
 {
 	void *vaddr;
@@ -2328,9 +2328,7 @@ void *intel_alloc_coherent(struct device *hwdev, size_t size,
 		return NULL;
 	memset(vaddr, 0, size);
 
-	*dma_handle = __intel_map_single(hwdev, 
-					 (phys_addr_t)(virt_to_phys(vaddr)), 
-					 size,
+	*dma_handle = __intel_map_single(hwdev, virt_to_phys(vaddr), size,
 					 DMA_BIDIRECTIONAL,
 					 hwdev->coherent_dma_mask);
 	if (*dma_handle)
@@ -2351,10 +2349,13 @@ static void intel_free_coherent(struct device *hwdev, size_t size, void *vaddr,
 	free_pages((unsigned long)vaddr, order);
 }
 
-#define SG_ENT_VIRT_ADDRESS(sg)	(page_address((sg)->page) + (sg)->offset)
+static inline struct page *sg_page(struct scatterlist *sg)
+{
+	return sg->page;
+}
 
 static void intel_unmap_sg(struct device *hwdev, struct scatterlist *sglist,
-		    int nelems, int dir)
+			   int nelems, int dir)
 {
 	int i;
 	struct pci_dev *pdev = to_pci_dev(hwdev);
@@ -2362,7 +2363,7 @@ static void intel_unmap_sg(struct device *hwdev, struct scatterlist *sglist,
 	unsigned long start_addr;
 	struct iova *iova;
 	size_t size = 0;
-	void *addr;
+	phys_addr_t addr;
 	struct scatterlist *sg;
 	struct intel_iommu *iommu;
 
@@ -2378,7 +2379,7 @@ static void intel_unmap_sg(struct device *hwdev, struct scatterlist *sglist,
 	if (!iova)
 		return;
 	for_each_sg(sglist, sg, nelems, i) {
-		addr = SG_ENT_VIRT_ADDRESS(sg);
+		addr = page_to_phys(sg_page(sg)) + sg->offset;
 		size += aligned_size((u64)addr, sg->length);
 	}
 
@@ -2404,8 +2405,8 @@ static int intel_nontranslate_map_sg(struct device *hddev,
 	struct scatterlist *sg;
 
 	for_each_sg(sglist, sg, nelems, i) {
-		BUG_ON(!sg->page);
-		sg->dma_address = virt_to_bus(SG_ENT_VIRT_ADDRESS(sg));
+		BUG_ON(!sg_page(sg));
+		sg->dma_address = page_to_phys(sg_page(sg)) + sg->offset;
 		sg->dma_length = sg->length;
 	}
 	return nelems;
@@ -2414,7 +2415,7 @@ static int intel_nontranslate_map_sg(struct device *hddev,
 static int intel_map_sg(struct device *hwdev, struct scatterlist *sglist, int nelems,
 		 int dir)
 {
-	void *addr;
+	phys_addr_t addr;
 	int i;
 	struct pci_dev *pdev = to_pci_dev(hwdev);
 	struct dmar_domain *domain;
@@ -2438,8 +2439,7 @@ static int intel_map_sg(struct device *hwdev, struct scatterlist *sglist, int ne
 	iommu = domain_get_iommu(domain);
 
 	for_each_sg(sglist, sg, nelems, i) {
-		addr = SG_ENT_VIRT_ADDRESS(sg);
-		addr = (void *)virt_to_phys(addr);
+		addr = page_to_phys(sg_page(sg)) + sg->offset;
 		size += aligned_size((u64)addr, sg->length);
 	}
 
@@ -2462,8 +2462,7 @@ static int intel_map_sg(struct device *hwdev, struct scatterlist *sglist, int ne
 	start_addr = iova->pfn_lo << PAGE_SHIFT;
 	offset = 0;
 	for_each_sg(sglist, sg, nelems, i) {
-		addr = SG_ENT_VIRT_ADDRESS(sg);
-		addr = (void *)virt_to_phys(addr);
+		addr = page_to_phys(sg_page(sg)) + sg->offset;
 		size = aligned_size((u64)addr, sg->length);
 		ret = domain_page_mapping(domain, start_addr + offset,
 			((u64)addr) & PAGE_MASK,
@@ -3195,7 +3194,7 @@ static int intel_iommu_map_range(struct iommu_domain *domain,
 		dmar_domain->max_addr = max_addr;
 	}
 
-	ret = domain_page_mapping(dmar_domain, iova, (u64)hpa, size, prot);
+	ret = domain_page_mapping(dmar_domain, iova, hpa, size, prot);
 	return ret;
 }
 
@@ -3225,7 +3224,7 @@ static phys_addr_t intel_iommu_iova_to_phys(struct iommu_domain *domain,
 	if (pte)
 		phys = dma_pte_addr(pte);
 
-	return (phys_addr_t)phys;
+	return phys;
 }
 
 static int intel_iommu_domain_has_cap(struct iommu_domain *domain,
diff --git a/include/asm-x86_64/types.h b/include/asm-x86_64/types.h
index c86c2e6..f8cdbe9 100644
--- a/include/asm-x86_64/types.h
+++ b/include/asm-x86_64/types.h
@@ -47,6 +47,7 @@ typedef unsigned long long u64;
 
 typedef u64 dma64_addr_t;
 typedef u64 dma_addr_t;
+typedef u64 phys_addr_t;
 
 typedef u64 sector_t;
 #define HAVE_SECTOR_T
diff --git a/include/linux/intel-iommu.h b/include/linux/intel-iommu.h
index 37e9f76..ac578e9 100644
--- a/include/linux/intel-iommu.h
+++ b/include/linux/intel-iommu.h
@@ -29,13 +29,6 @@
 #include <asm/cacheflush.h>
 #include <asm/proto.h>
 
-/* 
- * in linux/types.h upstream
- */
-#ifndef CONFIG_PHYS_ADDR_T_64BIT
-typedef void*  phys_addr_t;
-#endif
-
 /* in linux/scatterlist.h upstream */
 /*
  * Loop over each sg element, following the pointer to a new list if necessary
diff --git a/include/linux/iommu.h b/include/linux/iommu.h
index 1e2ebbc..3af4ffd 100644
--- a/include/linux/iommu.h
+++ b/include/linux/iommu.h
@@ -37,10 +37,10 @@ struct iommu_ops {
 	int (*attach_dev)(struct iommu_domain *domain, struct device *dev);
 	void (*detach_dev)(struct iommu_domain *domain, struct device *dev);
 	int (*map)(struct iommu_domain *domain, unsigned long iova,
-		   void *paddr, size_t size, int prot);
+		   phys_addr_t paddr, size_t size, int prot);
 	void (*unmap)(struct iommu_domain *domain, unsigned long iova,
 		      size_t size);
-	void *(*iova_to_phys)(struct iommu_domain *domain,
+	phys_addr_t (*iova_to_phys)(struct iommu_domain *domain,
 				    unsigned long iova);
 	int (*domain_has_cap)(struct iommu_domain *domain,
 			      unsigned long cap);
@@ -57,10 +57,10 @@ extern int iommu_attach_device(struct iommu_domain *domain,
 extern void iommu_detach_device(struct iommu_domain *domain,
 				struct device *dev);
 extern int iommu_map_range(struct iommu_domain *domain, unsigned long iova,
-			   void *paddr, size_t size, int prot);
+			   phys_addr_t paddr, size_t size, int prot);
 extern void iommu_unmap_range(struct iommu_domain *domain, unsigned long iova,
 			      size_t size);
-extern void *iommu_iova_to_phys(struct iommu_domain *domain,
+extern phys_addr_t iommu_iova_to_phys(struct iommu_domain *domain,
 				      unsigned long iova);
 extern int iommu_domain_has_cap(struct iommu_domain *domain,
 				unsigned long cap);
@@ -97,7 +97,7 @@ static inline void iommu_detach_device(struct iommu_domain *domain,
 }
 
 static inline int iommu_map_range(struct iommu_domain *domain,
-				  unsigned long iova, void *paddr,
+				  unsigned long iova, phys_addr_t paddr,
 				  size_t size, int prot)
 {
 	return -ENODEV;
@@ -108,7 +108,7 @@ static inline void iommu_unmap_range(struct iommu_domain *domain,
 {
 }
 
-static inline void *iommu_iova_to_phys(struct iommu_domain *domain,
+static inline phys_addr_t iommu_iova_to_phys(struct iommu_domain *domain,
 					     unsigned long iova)
 {
 	return 0;