
From: "Randy.Dunlap" <rddunlap@osdl.org>

(from Keir:)
I have audited the drivers/ and sound/ directories. Most uses of
remap_pfn_range are okay, but there are a small handful that are
remapping device memory (mostly AGP and DRM drivers).

Of particular driver is the HPET driver, whose mmap function is broken even
for native (non-Xen) builds.  If nothing else, vmalloc_to_phys should be used
instead of __pa to convert an ioremapped virtual address to a valid physical
address.  The fix in this patch is to remember the original bus address as
probed at boot time and to pass this to io_remap_pfn_range.

Signed-off-by: Keir Fraser <keir@xensource.com>
Signed-off-by: Andrew Morton <akpm@osdl.org>
---

 25-akpm/drivers/char/agp/frontend.c |    4 ++--
 25-akpm/drivers/char/drm/drm_vm.c   |    2 +-
 25-akpm/drivers/char/drm/i810_dma.c |    2 +-
 25-akpm/drivers/char/drm/i830_dma.c |    2 +-
 25-akpm/drivers/char/hpet.c         |    6 ++++--
 25-akpm/drivers/sbus/char/flash.c   |    2 +-
 6 files changed, 10 insertions(+), 8 deletions(-)

diff -puN drivers/char/agp/frontend.c~io_remap_pfn_range-fix-some-callers-for-xen drivers/char/agp/frontend.c
--- 25/drivers/char/agp/frontend.c~io_remap_pfn_range-fix-some-callers-for-xen	2005-03-18 13:50:54.000000000 -0800
+++ 25-akpm/drivers/char/agp/frontend.c	2005-03-18 13:50:54.000000000 -0800
@@ -628,7 +628,7 @@ static int agp_mmap(struct file *file, s
 		DBG("client vm_ops=%p", kerninfo.vm_ops);
 		if (kerninfo.vm_ops) {
 			vma->vm_ops = kerninfo.vm_ops;
-		} else if (remap_pfn_range(vma, vma->vm_start,
+		} else if (io_remap_pfn_range(vma, vma->vm_start,
 				(kerninfo.aper_base + offset) >> PAGE_SHIFT,
 					    size, vma->vm_page_prot)) {
 			goto out_again;
@@ -644,7 +644,7 @@ static int agp_mmap(struct file *file, s
 		DBG("controller vm_ops=%p", kerninfo.vm_ops);
 		if (kerninfo.vm_ops) {
 			vma->vm_ops = kerninfo.vm_ops;
-		} else if (remap_pfn_range(vma, vma->vm_start,
+		} else if (io_remap_pfn_range(vma, vma->vm_start,
 					    kerninfo.aper_base >> PAGE_SHIFT,
 					    size, vma->vm_page_prot)) {
 			goto out_again;
diff -puN drivers/char/drm/drm_vm.c~io_remap_pfn_range-fix-some-callers-for-xen drivers/char/drm/drm_vm.c
--- 25/drivers/char/drm/drm_vm.c~io_remap_pfn_range-fix-some-callers-for-xen	2005-03-18 13:50:54.000000000 -0800
+++ 25-akpm/drivers/char/drm/drm_vm.c	2005-03-18 13:50:54.000000000 -0800
@@ -634,7 +634,7 @@ int drm_mmap(struct file *filp, struct v
 					vma->vm_end - vma->vm_start,
 					vma->vm_page_prot))
 #else
-		if (remap_pfn_range(DRM_RPR_ARG(vma) vma->vm_start,
+		if (io_remap_pfn_range(vma, vma->vm_start,
 				     (VM_OFFSET(vma) + offset) >> PAGE_SHIFT,
 				     vma->vm_end - vma->vm_start,
 				     vma->vm_page_prot))
diff -puN drivers/char/drm/i810_dma.c~io_remap_pfn_range-fix-some-callers-for-xen drivers/char/drm/i810_dma.c
--- 25/drivers/char/drm/i810_dma.c~io_remap_pfn_range-fix-some-callers-for-xen	2005-03-18 13:50:54.000000000 -0800
+++ 25-akpm/drivers/char/drm/i810_dma.c	2005-03-18 13:50:54.000000000 -0800
@@ -119,7 +119,7 @@ int i810_mmap_buffers(struct file *filp,
    	buf_priv->currently_mapped = I810_BUF_MAPPED;
 	unlock_kernel();
 
-	if (remap_pfn_range(DRM_RPR_ARG(vma) vma->vm_start,
+	if (io_remap_pfn_range(vma, vma->vm_start,
 			     VM_OFFSET(vma) >> PAGE_SHIFT,
 			     vma->vm_end - vma->vm_start,
 			     vma->vm_page_prot)) return -EAGAIN;
diff -puN drivers/char/drm/i830_dma.c~io_remap_pfn_range-fix-some-callers-for-xen drivers/char/drm/i830_dma.c
--- 25/drivers/char/drm/i830_dma.c~io_remap_pfn_range-fix-some-callers-for-xen	2005-03-18 13:50:54.000000000 -0800
+++ 25-akpm/drivers/char/drm/i830_dma.c	2005-03-18 13:50:54.000000000 -0800
@@ -121,7 +121,7 @@ int i830_mmap_buffers(struct file *filp,
    	buf_priv->currently_mapped = I830_BUF_MAPPED;
 	unlock_kernel();
 
-	if (remap_pfn_range(DRM_RPR_ARG(vma) vma->vm_start,
+	if (io_remap_pfn_range(vma, vma->vm_start,
 			     VM_OFFSET(vma) >> PAGE_SHIFT,
 			     vma->vm_end - vma->vm_start,
 			     vma->vm_page_prot)) return -EAGAIN;
diff -puN drivers/char/hpet.c~io_remap_pfn_range-fix-some-callers-for-xen drivers/char/hpet.c
--- 25/drivers/char/hpet.c~io_remap_pfn_range-fix-some-callers-for-xen	2005-03-18 13:50:54.000000000 -0800
+++ 25-akpm/drivers/char/hpet.c	2005-03-18 13:50:54.000000000 -0800
@@ -76,6 +76,7 @@ struct hpet_dev {
 struct hpets {
 	struct hpets *hp_next;
 	struct hpet __iomem *hp_hpet;
+	unsigned long hp_hpet_phys;
 	struct time_interpolator *hp_interpolator;
 	unsigned long hp_period;
 	unsigned long hp_delta;
@@ -265,7 +266,7 @@ static int hpet_mmap(struct file *file, 
 		return -EINVAL;
 
 	devp = file->private_data;
-	addr = (unsigned long)devp->hd_hpet;
+	addr = devp->hd_hpets->hp_hpet_phys;
 
 	if (addr & (PAGE_SIZE - 1))
 		return -ENOSYS;
@@ -274,7 +275,7 @@ static int hpet_mmap(struct file *file, 
 	vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
 	addr = __pa(addr);
 
-	if (remap_pfn_range(vma, vma->vm_start, addr >> PAGE_SHIFT,
+	if (io_remap_pfn_range(vma, vma->vm_start, addr >> PAGE_SHIFT,
 					PAGE_SIZE, vma->vm_page_prot)) {
 		printk(KERN_ERR "remap_pfn_range failed in hpet.c\n");
 		return -EAGAIN;
@@ -795,6 +796,7 @@ int hpet_alloc(struct hpet_data *hdp)
 
 	hpetp->hp_which = hpet_nhpet++;
 	hpetp->hp_hpet = hdp->hd_address;
+	hpetp->hp_hpet_phys = hdp->hd_phys_address;
 
 	hpetp->hp_ntimer = hdp->hd_nirqs;
 
diff -puN drivers/sbus/char/flash.c~io_remap_pfn_range-fix-some-callers-for-xen drivers/sbus/char/flash.c
--- 25/drivers/sbus/char/flash.c~io_remap_pfn_range-fix-some-callers-for-xen	2005-03-18 13:50:54.000000000 -0800
+++ 25-akpm/drivers/sbus/char/flash.c	2005-03-18 13:50:54.000000000 -0800
@@ -75,7 +75,7 @@ flash_mmap(struct file *file, struct vm_
 	pgprot_val(vma->vm_page_prot) |= _PAGE_E;
 	vma->vm_flags |= (VM_SHM | VM_LOCKED);
 
-	if (remap_pfn_range(vma, vma->vm_start, addr, size, vma->vm_page_prot))
+	if (io_remap_pfn_range(vma, vma->vm_start, addr, size, vma->vm_page_prot))
 		return -EAGAIN;
 		
 	return 0;
_
