drm2: Port d_mmap_single() from FreeBSD
authorJohannes Hofmann <johannes.hofmann@gmx.de>
Wed, 24 Apr 2013 17:31:38 +0000 (19:31 +0200)
committerFran├žois Tigeot <ftigeot@wolfpond.org>
Tue, 30 Jul 2013 15:00:10 +0000 (17:00 +0200)
sys/dev/drm2/drmP.h
sys/dev/drm2/drm_drv.c
sys/dev/drm2/drm_vm.c
sys/kern/kern_device.c
sys/sys/device.h
sys/vm/vm_mmap.c

index 38c624d..14ce6b6 100644 (file)
@@ -995,6 +995,7 @@ d_close_t drm_close;
 d_read_t drm_read;
 d_kqfilter_t drm_kqfilter;
 d_mmap_t drm_mmap;
+d_mmap_single_t drm_mmap_single;
 extern drm_local_map_t *drm_getsarea(struct drm_device *dev);
 
 void drm_event_wakeup(struct drm_pending_event *e);
index 24f360e..2e81fdb 100644 (file)
@@ -189,6 +189,7 @@ static struct dev_ops drm_cdevsw = {
        .d_ioctl =      drm_ioctl,
        .d_kqfilter =   drm_kqfilter,
        .d_mmap =       drm_mmap,
+       .d_mmap_single =        drm_mmap_single,
 };
 
 static int drm_msi = 1;        /* Enable by default. */
index 2d21d6a..1d6475d 100644 (file)
@@ -141,3 +141,11 @@ drm_mmap(struct dev_mmap_args *ap)
        return 0;
 }
 
+int
+drm_mmap_single(struct dev_mmap_single_args *ap)
+{
+       struct cdev *kdev = ap->a_head.a_dev;
+
+       return drm_gem_mmap_single(kdev, ap->a_offset, ap->a_size,
+                               ap->a_object, ap->a_nprot);
+}
index 0804285..54a7e83 100644 (file)
@@ -90,6 +90,7 @@ DEVOP_DESC_INIT(ioctl);
 DEVOP_DESC_INIT(dump);
 DEVOP_DESC_INIT(psize);
 DEVOP_DESC_INIT(mmap);
+DEVOP_DESC_INIT(mmap_single);
 DEVOP_DESC_INIT(strategy);
 DEVOP_DESC_INIT(kqfilter);
 DEVOP_DESC_INIT(revoke);
@@ -109,6 +110,7 @@ struct dev_ops default_dev_ops = {
        .d_write = nowrite,
        .d_ioctl = noioctl,
        .d_mmap = nommap,
+       .d_mmap_single = nommap_single,
        .d_strategy = nostrategy,
        .d_dump = nodump,
        .d_psize = nopsize,
@@ -269,6 +271,30 @@ dev_dmmap(cdev_t dev, vm_offset_t offset, int nprot)
        return(-1);
 }
 
+int
+dev_dmmap_single(cdev_t dev, vm_ooffset_t *offset, vm_size_t size,
+                 struct vm_object **object, int nprot)
+{
+       struct dev_mmap_single_args ap;
+       int needmplock = dev_needmplock(dev);
+       int error;
+
+       ap.a_head.a_desc = &dev_mmap_single_desc;
+       ap.a_head.a_dev = dev;
+       ap.a_offset = offset;
+       ap.a_size = size;
+       ap.a_object = object;
+       ap.a_nprot = nprot;
+
+       if (needmplock)
+               get_mplock();
+       error = dev->si_ops->d_mmap_single(&ap);
+       if (needmplock)
+               rel_mplock();
+
+       return(error);
+}
+
 int
 dev_dclone(cdev_t dev)
 {
@@ -694,6 +720,12 @@ nommap(struct dev_mmap_args *ap)
        return (ENODEV);
 }
 
+int
+nommap_single(struct dev_mmap_single_args *ap)
+{
+       return (ENODEV);
+}
+
 int
 nostrategy(struct dev_strategy_args *ap)
 {
index e548387..bf5341f 100644 (file)
@@ -119,6 +119,18 @@ struct dev_mmap_args {
        int             a_result;       /* page number */
 };
 
+/*
+ * int d_mmap_single(cdev_t dev, vm_ooffset_t *offset, vm_size_t size,
+ *                   struct vm_object **object, int nprot)
+ */
+struct dev_mmap_single_args {
+       struct dev_generic_args a_head;
+       vm_ooffset_t    *a_offset;
+       vm_size_t               a_size;
+       struct vm_object **a_object;
+       int             a_nprot;
+};
+
 /*
  * void d_strategy(cdev_t dev, struct bio *bio)
  */
@@ -189,6 +201,7 @@ typedef int d_read_t (struct dev_read_args *ap);
 typedef int d_write_t (struct dev_write_args *ap);
 typedef int d_ioctl_t (struct dev_ioctl_args *ap);
 typedef int d_mmap_t (struct dev_mmap_args *ap);
+typedef int d_mmap_single_t (struct dev_mmap_single_args *ap);
 typedef int d_strategy_t (struct dev_strategy_args *ap);
 typedef int d_dump_t (struct dev_dump_args *ap);
 typedef int d_psize_t (struct dev_psize_args *ap);
@@ -219,6 +232,7 @@ struct dev_ops {
        d_write_t       *d_write;
        d_ioctl_t       *d_ioctl;
        d_mmap_t        *d_mmap;
+       d_mmap_single_t *d_mmap_single;
        d_strategy_t    *d_strategy;
        d_dump_t        *d_dump;
        d_psize_t       *d_psize;
@@ -307,6 +321,8 @@ int dev_dread(cdev_t dev, struct uio *uio, int ioflag);
 int dev_dwrite(cdev_t dev, struct uio *uio, int ioflag);
 int dev_dkqfilter(cdev_t dev, struct knote *kn);
 int dev_dmmap(cdev_t dev, vm_offset_t offset, int nprot);
+int dev_dmmap_single(cdev_t dev, vm_ooffset_t *offset, vm_size_t size,
+                       struct vm_object **object, int nprot);
 int dev_dclone(cdev_t dev);
 int dev_drevoke(cdev_t dev);
 
@@ -324,6 +340,7 @@ d_read_t    noread;
 d_write_t      nowrite;
 d_ioctl_t      noioctl;
 d_mmap_t       nommap;
+d_mmap_single_t        nommap_single;
 d_strategy_t   nostrategy;
 d_dump_t       nodump;
 d_psize_t      nopsize;
@@ -343,6 +360,7 @@ extern struct syslink_desc dev_ioctl_desc;
 extern struct syslink_desc dev_dump_desc;
 extern struct syslink_desc dev_psize_desc;
 extern struct syslink_desc dev_mmap_desc;
+extern struct syslink_desc dev_mmap_single_desc;
 extern struct syslink_desc dev_strategy_desc;
 extern struct syslink_desc dev_kqfilter_desc;
 extern struct syslink_desc dev_clone_desc;
index 615a3a6..6252b69 100644 (file)
@@ -1193,6 +1193,7 @@ vm_mmap(vm_map_t map, vm_offset_t *addr, vm_size_t size, vm_prot_t prot,
        int rv = KERN_SUCCESS;
        off_t objsize;
        int docow;
+       int error;
 
        if (size == 0)
                return (0);
@@ -1309,11 +1310,16 @@ vm_mmap(vm_map_t map, vm_offset_t *addr, vm_size_t size, vm_prot_t prot,
                         * Device mappings (device size unknown?).
                         * Force them to be shared.
                         */
-                       handle = (void *)(intptr_t)vp->v_rdev;
-                       object = dev_pager_alloc(handle, objsize, prot, foff);
-                       if (object == NULL) {
-                               lwkt_reltoken(&map->token);
-                               return(EINVAL);
+                       error = dev_dmmap_single(vp->v_rdev, &foff, objsize,
+                                               &object, prot);
+
+                       if (error == ENODEV) {
+                               handle = (void *)(intptr_t)vp->v_rdev;
+                               object = dev_pager_alloc(handle, objsize, prot, foff);
+                               if (object == NULL) {
+                                       lwkt_reltoken(&map->token);
+                                       return(EINVAL);
+                               }
                        }
                        docow = MAP_PREFAULT_PARTIAL;
                        flags &= ~(MAP_PRIVATE|MAP_COPY);