diff options
Diffstat (limited to 'drivers/char/mem.c')
-rw-r--r-- | drivers/char/mem.c | 42 |
1 files changed, 30 insertions, 12 deletions
diff --git a/drivers/char/mem.c b/drivers/char/mem.c index 91dd669273e0..5b2d18035073 100644 --- a/drivers/char/mem.c +++ b/drivers/char/mem.c | |||
@@ -101,6 +101,11 @@ static inline int valid_phys_addr_range(unsigned long addr, size_t *count) | |||
101 | 101 | ||
102 | return 1; | 102 | return 1; |
103 | } | 103 | } |
104 | |||
105 | static inline int valid_mmap_phys_addr_range(unsigned long addr, size_t *size) | ||
106 | { | ||
107 | return 1; | ||
108 | } | ||
104 | #endif | 109 | #endif |
105 | 110 | ||
106 | /* | 111 | /* |
@@ -228,26 +233,36 @@ static ssize_t write_mem(struct file * file, const char __user * buf, | |||
228 | return written; | 233 | return written; |
229 | } | 234 | } |
230 | 235 | ||
236 | #ifndef __HAVE_PHYS_MEM_ACCESS_PROT | ||
237 | static pgprot_t phys_mem_access_prot(struct file *file, unsigned long pfn, | ||
238 | unsigned long size, pgprot_t vma_prot) | ||
239 | { | ||
240 | #ifdef pgprot_noncached | ||
241 | unsigned long offset = pfn << PAGE_SHIFT; | ||
242 | |||
243 | if (uncached_access(file, offset)) | ||
244 | return pgprot_noncached(vma_prot); | ||
245 | #endif | ||
246 | return vma_prot; | ||
247 | } | ||
248 | #endif | ||
249 | |||
231 | static int mmap_mem(struct file * file, struct vm_area_struct * vma) | 250 | static int mmap_mem(struct file * file, struct vm_area_struct * vma) |
232 | { | 251 | { |
233 | #if defined(__HAVE_PHYS_MEM_ACCESS_PROT) | 252 | size_t size = vma->vm_end - vma->vm_start; |
253 | |||
254 | if (!valid_mmap_phys_addr_range(vma->vm_pgoff << PAGE_SHIFT, &size)) | ||
255 | return -EINVAL; | ||
256 | |||
234 | vma->vm_page_prot = phys_mem_access_prot(file, vma->vm_pgoff, | 257 | vma->vm_page_prot = phys_mem_access_prot(file, vma->vm_pgoff, |
235 | vma->vm_end - vma->vm_start, | 258 | size, |
236 | vma->vm_page_prot); | 259 | vma->vm_page_prot); |
237 | #elif defined(pgprot_noncached) | ||
238 | unsigned long offset = vma->vm_pgoff << PAGE_SHIFT; | ||
239 | int uncached; | ||
240 | |||
241 | uncached = uncached_access(file, offset); | ||
242 | if (uncached) | ||
243 | vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot); | ||
244 | #endif | ||
245 | 260 | ||
246 | /* Remap-pfn-range will mark the range VM_IO and VM_RESERVED */ | 261 | /* Remap-pfn-range will mark the range VM_IO and VM_RESERVED */ |
247 | if (remap_pfn_range(vma, | 262 | if (remap_pfn_range(vma, |
248 | vma->vm_start, | 263 | vma->vm_start, |
249 | vma->vm_pgoff, | 264 | vma->vm_pgoff, |
250 | vma->vm_end-vma->vm_start, | 265 | size, |
251 | vma->vm_page_prot)) | 266 | vma->vm_page_prot)) |
252 | return -EAGAIN; | 267 | return -EAGAIN; |
253 | return 0; | 268 | return 0; |
@@ -817,7 +832,7 @@ static ssize_t kmsg_write(struct file * file, const char __user * buf, | |||
817 | size_t count, loff_t *ppos) | 832 | size_t count, loff_t *ppos) |
818 | { | 833 | { |
819 | char *tmp; | 834 | char *tmp; |
820 | int ret; | 835 | ssize_t ret; |
821 | 836 | ||
822 | tmp = kmalloc(count + 1, GFP_KERNEL); | 837 | tmp = kmalloc(count + 1, GFP_KERNEL); |
823 | if (tmp == NULL) | 838 | if (tmp == NULL) |
@@ -826,6 +841,9 @@ static ssize_t kmsg_write(struct file * file, const char __user * buf, | |||
826 | if (!copy_from_user(tmp, buf, count)) { | 841 | if (!copy_from_user(tmp, buf, count)) { |
827 | tmp[count] = 0; | 842 | tmp[count] = 0; |
828 | ret = printk("%s", tmp); | 843 | ret = printk("%s", tmp); |
844 | if (ret > count) | ||
845 | /* printk can add a prefix */ | ||
846 | ret = count; | ||
829 | } | 847 | } |
830 | kfree(tmp); | 848 | kfree(tmp); |
831 | return ret; | 849 | return ret; |