Module: xenomai-head
Branch: master
Commit: 8c05ad4fbbbd72ab0d02fff21319f0ccd0a93492
URL:    
http://git.xenomai.org/?p=xenomai-head.git;a=commit;h=8c05ad4fbbbd72ab0d02fff21319f0ccd0a93492

Author: Philippe Gerum <r...@xenomai.org>
Date:   Wed Jun 16 10:25:24 2010 +0200

rtdm: fix memory mapping services for nommu platforms

This patch is a follow-up to ada72009a, fixing the
rtdm_mmap/iomap_to_user() services, in the nommu case.

The rationale for it is that backing devices on nommu must have direct
mapping capabilities to support shared mapping requests (MAP_SHARED),
which are not available from /dev/zero.

We fix this by using /dev/rtheap instead of /dev/zero for issuing
non-anonymous mapping requests from rtdm_do_mmap(), since default caps
for character-based devices include BDI_CAP_MAP_DIRECT. In the same
move, we provide the missing .get_unmapped_area helper.

---

 include/compat/linux/err.h |    2 +
 ksrc/skins/rtdm/drvlib.c   |   62 +++++++++++++++++++++++++++++++++----------
 2 files changed, 49 insertions(+), 15 deletions(-)

diff --git a/include/compat/linux/err.h b/include/compat/linux/err.h
index ae980db..81a6134 100644
--- a/include/compat/linux/err.h
+++ b/include/compat/linux/err.h
@@ -23,4 +23,6 @@
 
 #include <linux/fs.h>
 
+#define IS_ERR_VALUE(value) IS_ERR((void *)value)
+
 #endif /* _XENO_COMPAT_LINUX_ERR_H */
diff --git a/ksrc/skins/rtdm/drvlib.c b/ksrc/skins/rtdm/drvlib.c
index 68a661c..3495e63 100644
--- a/ksrc/skins/rtdm/drvlib.c
+++ b/ksrc/skins/rtdm/drvlib.c
@@ -37,6 +37,7 @@
 #include <asm/io.h>
 #include <asm/pgtable.h>
 #include <linux/highmem.h>
+#include <linux/err.h>
 
 #include <rtdm/rtdm_driver.h>
 
@@ -1808,9 +1809,8 @@ static int rtdm_mmap_buffer(struct file *filp, struct 
vm_area_struct *vma)
 
        vaddr = (unsigned long)mmap_data->src_vaddr;
        paddr = mmap_data->src_paddr;
-       if (!paddr)
-               /* kmalloc memory */
-               paddr = virt_to_phys((void *)vaddr);
+       if (paddr == 0) /* kmalloc memory? */
+               paddr = __pa(vaddr);
 
        maddr = vma->vm_start;
        size = vma->vm_end - vma->vm_start;
@@ -1834,6 +1834,8 @@ static int rtdm_mmap_buffer(struct file *filp, struct 
vm_area_struct *vma)
                xnarch_fault_range(vma);
                ret = 0;
        } else
+#else
+       vma->vm_pgoff = paddr >> PAGE_SHIFT;
 #endif /* CONFIG_MMU */
        if (mmap_data->src_paddr)
                ret = xnarch_remap_io_page_range(filp, vma, maddr, paddr,
@@ -1848,22 +1850,43 @@ static int rtdm_mmap_buffer(struct file *filp, struct 
vm_area_struct *vma)
        return ret;
 }
 
+#ifndef CONFIG_MMU
+static unsigned long rtdm_unmapped_area(struct file *file,
+                                       unsigned long addr,
+                                       unsigned long len,
+                                       unsigned long pgoff,
+                                       unsigned long flags)
+{
+       struct rtdm_mmap_data *mmap_data = file->private_data;
+       unsigned long pa;
+
+       pa = mmap_data->src_paddr;
+       if (pa == 0)
+               pa = __pa(mmap_data->src_vaddr);
+
+       return pa;
+}
+#else
+#define rtdm_unmapped_area  NULL
+#endif
+
 static struct file_operations rtdm_mmap_fops = {
        .mmap = rtdm_mmap_buffer,
+       .get_unmapped_area = rtdm_unmapped_area
 };
 
 static int rtdm_do_mmap(rtdm_user_info_t *user_info,
                        struct rtdm_mmap_data *mmap_data,
                        size_t len, int prot, void **pptr)
 {
-       struct file *filp;
        const struct file_operations *old_fops;
+       unsigned long u_addr;
        void *old_priv_data;
-       void *user_ptr;
+       struct file *filp;
 
        XENO_ASSERT(RTDM, xnpod_root_p(), return -EPERM;);
 
-       filp = filp_open("/dev/zero", O_RDWR, 0);
+       filp = filp_open(XNHEAP_DEV_NAME, O_RDWR, 0);
        if (IS_ERR(filp))
                return PTR_ERR(filp);
 
@@ -1874,8 +1897,8 @@ static int rtdm_do_mmap(rtdm_user_info_t *user_info,
        filp->private_data = mmap_data;
 
        down_write(&user_info->mm->mmap_sem);
-       user_ptr = (void *)do_mmap(filp, (unsigned long)*pptr, len, prot,
-                                  MAP_SHARED, 0);
+       u_addr = do_mmap(filp, (unsigned long)*pptr, len, prot,
+                        MAP_SHARED, 0);
        up_write(&user_info->mm->mmap_sem);
 
        filp->f_op = (typeof(filp->f_op))old_fops;
@@ -1883,10 +1906,11 @@ static int rtdm_do_mmap(rtdm_user_info_t *user_info,
 
        filp_close(filp, user_info->files);
 
-       if (IS_ERR(user_ptr))
-               return PTR_ERR(user_ptr);
+       if (IS_ERR_VALUE(u_addr))
+               return (int)u_addr;
+
+       *pptr = (void *)u_addr;
 
-       *pptr = user_ptr;
        return 0;
 }
 
@@ -1950,8 +1974,12 @@ int rtdm_mmap_to_user(rtdm_user_info_t *user_info,
                      struct vm_operations_struct *vm_ops,
                      void *vm_private_data)
 {
-       struct rtdm_mmap_data mmap_data =
-               { src_addr, 0, vm_ops, vm_private_data };
+       struct rtdm_mmap_data mmap_data = {
+               .src_vaddr = src_addr,
+               .src_paddr = 0,
+               .vm_ops = vm_ops,
+               .vm_private_data = vm_private_data
+       };
 
        return rtdm_do_mmap(user_info, &mmap_data, len, prot, pptr);
 }
@@ -2014,8 +2042,12 @@ int rtdm_iomap_to_user(rtdm_user_info_t *user_info,
                       struct vm_operations_struct *vm_ops,
                       void *vm_private_data)
 {
-       struct rtdm_mmap_data mmap_data =
-               { NULL, src_addr, vm_ops, vm_private_data };
+       struct rtdm_mmap_data mmap_data = {
+               .src_vaddr = NULL,
+               .src_paddr = src_addr,
+               .vm_ops = vm_ops,
+               .vm_private_data = vm_private_data
+       };
 
        return rtdm_do_mmap(user_info, &mmap_data, len, prot, pptr);
 }


_______________________________________________
Xenomai-git mailing list
Xenomai-git@gna.org
https://mail.gna.org/listinfo/xenomai-git

Reply via email to