Patchwork Fix BSR to allow mmap of small BSR on 64k kernel

login
register
mail settings
Submitter Sonny Rao
Date Nov. 17, 2008, 7:26 a.m.
Message ID <20081117072613.GO16240@us.ibm.com>
Download mbox | patch
Permalink /patch/9073/
State Changes Requested
Headers show

Comments

Sonny Rao - Nov. 17, 2008, 7:26 a.m.
On Fri, Nov 07, 2008 at 04:28:29PM +1100, Paul Mackerras wrote:
> Sonny Rao writes:
> 
> > Fix the BSR driver to allow small BSR devices, which are limited to a
> > single 4k space, on a 64k page kernel.  Previously the driver would
> > reject the mmap since the size was smaller than PAGESIZE (or because
> > the size was greater than the size of the device).  Now, we check for
> > this case use remap_4k_pfn(). Also, take out code to set vm_flags,
> > as the remap_pfn functions will do this for us.
> 
> Thanks.
> 
> Do we know that the BSR size will always be 4k if it's not a multiple
> of 64k?  Is it possible that we could get 8k, 16k or 32k or BSRs?
> If it is possible, what does the user need to be able to do?  Do they
> just want to map 4k, or might then want to map the whole thing?


Hi Paul, I took a look at changing the driver to reject a request for
mapping more than a single 4k page, however the only indication we get
of the requested size in the mmap function is the vma size, and this
is always one page at minimum.  So, it's not possible to determine if
the user wants one 4k page or more.  As I noted in my first response,
there is only one case where this is even possible and I don't think
it is a significant concern.

I did notice that I left out the check to see if the user is trying to
map more than the device length, so I fixed that.  Here's the revised
patch.

--------

Fix the BSR driver to allow small BSR devices on a 64k page kernel.  
Previously the driver would reject the mmap since the size was smaller
than PAGESIZE. This patch adds a  check for this case and uses remap_4k_pfn().

Also, take out code to set vm_flags, as the remap_pfn functions will
do this for us.

Signed-off-by: Sonny Rao <sonnyrao@us.ibm.com>
Paul Mackerras - Nov. 19, 2008, 4:07 a.m.
Sonny Rao writes:

> -	if (io_remap_pfn_range(vma, vma->vm_start, dev->bsr_addr >> PAGE_SHIFT,
> -			       size, vma->vm_page_prot))
> +	/* check for the case of a small BSR device and map one 4k page for it*/
> +	if (dev->bsr_len < PAGE_SIZE && size == PAGE_SIZE)
> +		ret = remap_4k_pfn(vma, vma->vm_start, dev->bsr_addr >> 12,
> +				   vma->vm_page_prot);

I think we should be checking that dev->bsr_len == 4096 here.

Paul.
Sonny Rao - Nov. 19, 2008, 5:04 p.m.
On Wed, Nov 19, 2008 at 03:07:04PM +1100, Paul Mackerras wrote:
> Sonny Rao writes:
> 
> > -	if (io_remap_pfn_range(vma, vma->vm_start, dev->bsr_addr >> PAGE_SHIFT,
> > -			       size, vma->vm_page_prot))
> > +	/* check for the case of a small BSR device and map one 4k page for it*/
> > +	if (dev->bsr_len < PAGE_SIZE && size == PAGE_SIZE)
> > +		ret = remap_4k_pfn(vma, vma->vm_start, dev->bsr_addr >> 12,
> > +				   vma->vm_page_prot);
> 
> I think we should be checking that dev->bsr_len == 4096 here.
> 
> Paul.

Well, dev->bsr_len could be 4096 or 8192
Paul Mackerras - Nov. 19, 2008, 10:54 p.m.
Sonny Rao writes:

> On Wed, Nov 19, 2008 at 03:07:04PM +1100, Paul Mackerras wrote:
> > I think we should be checking that dev->bsr_len == 4096 here.
> > 
> > Paul.
> 
> Well, dev->bsr_len could be 4096 or 8192

Isn't the dev->bsr_len == 8192 case the one where we'll only map 4096
bytes and therefore not do what the user expected?  Sounds to me like
we want to return an error for that case.

Paul.
Sonny Rao - Nov. 20, 2008, 7:20 p.m.
On Thu, Nov 20, 2008 at 09:54:21AM +1100, Paul Mackerras wrote:
> Sonny Rao writes:
> 
> > On Wed, Nov 19, 2008 at 03:07:04PM +1100, Paul Mackerras wrote:
> > > I think we should be checking that dev->bsr_len == 4096 here.
> > > 
> > > Paul.
> > 
> > Well, dev->bsr_len could be 4096 or 8192
> 
> Isn't the dev->bsr_len == 8192 case the one where we'll only map 4096
> bytes and therefore not do what the user expected?  Sounds to me like
> we want to return an error for that case.

Well, the problem is that we can't tell if the user asked for 4k or
8k (since we only know the size of the VMA).  

If we fail whenever dev->bsr_len is 8k then the user could never
map that device on a 64k page kernel. Is that what we want?

Patch

Index: linux/drivers/char/bsr.c
===================================================================
--- linux.orig/drivers/char/bsr.c	2008-11-17 00:29:23.000000000 -0600
+++ linux/drivers/char/bsr.c	2008-11-17 00:59:57.000000000 -0600
@@ -27,6 +27,7 @@ 
 #include <linux/cdev.h>
 #include <linux/list.h>
 #include <linux/mm.h>
+#include <asm/pgtable.h>
 #include <asm/io.h>
 
 /*
@@ -115,15 +116,22 @@ 
 {
 	unsigned long size   = vma->vm_end - vma->vm_start;
 	struct bsr_dev *dev = filp->private_data;
+	int ret;
 
-	if (size > dev->bsr_len || (size & (PAGE_SIZE-1)))
-		return -EINVAL;
-
-	vma->vm_flags |= (VM_IO | VM_DONTEXPAND);
 	vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
 
-	if (io_remap_pfn_range(vma, vma->vm_start, dev->bsr_addr >> PAGE_SHIFT,
-			       size, vma->vm_page_prot))
+	/* check for the case of a small BSR device and map one 4k page for it*/
+	if (dev->bsr_len < PAGE_SIZE && size == PAGE_SIZE)
+		ret = remap_4k_pfn(vma, vma->vm_start, dev->bsr_addr >> 12,
+				   vma->vm_page_prot);
+	else if (size <= dev->bsr_len)
+		ret = io_remap_pfn_range(vma, vma->vm_start,
+					 dev->bsr_addr >> PAGE_SHIFT,
+					 size, vma->vm_page_prot);
+	else
+		return -EINVAL;
+
+	if (ret)
 		return -EAGAIN;
 
 	return 0;