diff options
-rw-r--r-- | drivers/char/bsr.c | 25 |
1 files changed, 19 insertions, 6 deletions
diff --git a/drivers/char/bsr.c b/drivers/char/bsr.c index 7d9fd8a8dfd0..c02db01f736e 100644 --- a/drivers/char/bsr.c +++ b/drivers/char/bsr.c | |||
@@ -27,6 +27,7 @@ | |||
27 | #include <linux/cdev.h> | 27 | #include <linux/cdev.h> |
28 | #include <linux/list.h> | 28 | #include <linux/list.h> |
29 | #include <linux/mm.h> | 29 | #include <linux/mm.h> |
30 | #include <asm/pgtable.h> | ||
30 | #include <asm/io.h> | 31 | #include <asm/io.h> |
31 | 32 | ||
32 | /* | 33 | /* |
@@ -118,15 +119,22 @@ static int bsr_mmap(struct file *filp, struct vm_area_struct *vma) | |||
118 | { | 119 | { |
119 | unsigned long size = vma->vm_end - vma->vm_start; | 120 | unsigned long size = vma->vm_end - vma->vm_start; |
120 | struct bsr_dev *dev = filp->private_data; | 121 | struct bsr_dev *dev = filp->private_data; |
122 | int ret; | ||
121 | 123 | ||
122 | if (size > dev->bsr_len || (size & (PAGE_SIZE-1))) | ||
123 | return -EINVAL; | ||
124 | |||
125 | vma->vm_flags |= (VM_IO | VM_DONTEXPAND); | ||
126 | vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot); | 124 | vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot); |
127 | 125 | ||
128 | if (io_remap_pfn_range(vma, vma->vm_start, dev->bsr_addr >> PAGE_SHIFT, | 126 | /* check for the case of a small BSR device and map one 4k page for it*/ |
129 | size, vma->vm_page_prot)) | 127 | if (dev->bsr_len < PAGE_SIZE && size == PAGE_SIZE) |
128 | ret = remap_4k_pfn(vma, vma->vm_start, dev->bsr_addr >> 12, | ||
129 | vma->vm_page_prot); | ||
130 | else if (size <= dev->bsr_len) | ||
131 | ret = io_remap_pfn_range(vma, vma->vm_start, | ||
132 | dev->bsr_addr >> PAGE_SHIFT, | ||
133 | size, vma->vm_page_prot); | ||
134 | else | ||
135 | return -EINVAL; | ||
136 | |||
137 | if (ret) | ||
130 | return -EAGAIN; | 138 | return -EAGAIN; |
131 | 139 | ||
132 | return 0; | 140 | return 0; |
@@ -206,6 +214,11 @@ static int bsr_add_node(struct device_node *bn) | |||
206 | cur->bsr_stride = bsr_stride[i]; | 214 | cur->bsr_stride = bsr_stride[i]; |
207 | cur->bsr_dev = MKDEV(bsr_major, i + total_bsr_devs); | 215 | cur->bsr_dev = MKDEV(bsr_major, i + total_bsr_devs); |
208 | 216 | ||
217 | /* if we have a bsr_len of > 4k and less then PAGE_SIZE (64k pages) */ | ||
218 | /* we can only map 4k of it, so only advertise the 4k in sysfs */ | ||
219 | if (cur->bsr_len > 4096 && cur->bsr_len < PAGE_SIZE) | ||
220 | cur->bsr_len = 4096; | ||
221 | |||
209 | switch(cur->bsr_bytes) { | 222 | switch(cur->bsr_bytes) { |
210 | case 8: | 223 | case 8: |
211 | cur->bsr_type = BSR_8; | 224 | cur->bsr_type = BSR_8; |