Module Name: src Committed By: riastradh Date: Wed Jan 22 16:40:44 UTC 2014
Modified Files: src/sys/external/bsd/drm2/dist/include/drm [riastradh-drm2]: drmP.h src/sys/external/bsd/drm2/drm [riastradh-drm2]: drm_drv.c drm_gem_vm.c drm_vm.c Log Message: Tidy up and reuse the code I had already written for gem mmapping. To generate a diff of this commit: cvs rdiff -u -r1.1.1.1.2.55 -r1.1.1.1.2.56 \ src/sys/external/bsd/drm2/dist/include/drm/drmP.h cvs rdiff -u -r1.1.2.32 -r1.1.2.33 src/sys/external/bsd/drm2/drm/drm_drv.c cvs rdiff -u -r1.1.2.3 -r1.1.2.4 src/sys/external/bsd/drm2/drm/drm_gem_vm.c \ src/sys/external/bsd/drm2/drm/drm_vm.c Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: src/sys/external/bsd/drm2/dist/include/drm/drmP.h diff -u src/sys/external/bsd/drm2/dist/include/drm/drmP.h:1.1.1.1.2.55 src/sys/external/bsd/drm2/dist/include/drm/drmP.h:1.1.1.1.2.56 --- src/sys/external/bsd/drm2/dist/include/drm/drmP.h:1.1.1.1.2.55 Wed Jan 15 21:25:29 2014 +++ src/sys/external/bsd/drm2/dist/include/drm/drmP.h Wed Jan 22 16:40:44 2014 @@ -1494,6 +1494,8 @@ extern int drm_release(struct inode *ino /* Mapping support (drm_vm.h) */ #ifdef __NetBSD__ +extern int drm_mmap_object(struct drm_device *, off_t, size_t, int, + struct uvm_object **); extern paddr_t drm_mmap_paddr(struct drm_device *, off_t, int); #else extern int drm_mmap(struct file *filp, struct vm_area_struct *vma); @@ -1846,7 +1848,7 @@ void drm_gem_object_handle_free(struct d #ifdef __NetBSD__ void drm_gem_pager_reference(struct uvm_object *); void drm_gem_pager_detach(struct uvm_object *); -int drm_gem_mmap_object(struct drm_device *, off_t *, size_t, +int drm_gem_mmap_object(struct drm_device *, off_t, size_t, int, struct uvm_object **); #else void drm_gem_vm_open(struct vm_area_struct *vma); Index: src/sys/external/bsd/drm2/drm/drm_drv.c diff -u src/sys/external/bsd/drm2/drm/drm_drv.c:1.1.2.32 src/sys/external/bsd/drm2/drm/drm_drv.c:1.1.2.33 --- src/sys/external/bsd/drm2/drm/drm_drv.c:1.1.2.32 Wed Jan 22 14:58:47 2014 +++ src/sys/external/bsd/drm2/drm/drm_drv.c Wed Jan 22 16:40:44 2014 @@ -1,4 +1,4 @@ -/* $NetBSD: drm_drv.c,v 1.1.2.32 2014/01/22 14:58:47 riastradh Exp $ */ +/* $NetBSD: drm_drv.c,v 1.1.2.33 2014/01/22 16:40:44 riastradh Exp $ */ /*- * Copyright (c) 2013 The NetBSD Foundation, Inc. @@ -30,7 +30,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: drm_drv.c,v 1.1.2.32 2014/01/22 14:58:47 riastradh Exp $"); +__KERNEL_RCSID(0, "$NetBSD: drm_drv.c,v 1.1.2.33 2014/01/22 16:40:44 riastradh Exp $"); #include <sys/param.h> #include <sys/types.h> @@ -43,13 +43,7 @@ __KERNEL_RCSID(0, "$NetBSD: drm_drv.c,v #include <sys/poll.h> #include <sys/select.h> -#include <uvm/uvm.h> -#include <uvm/uvm_device.h> #include <uvm/uvm_extern.h> -#include <uvm/uvm_fault.h> -#include <uvm/uvm_page.h> -#include <uvm/uvm_pmap.h> -#include <uvm/uvm_prot.h> #include <drm/drmP.h> @@ -104,8 +98,6 @@ static int drm_stat(struct file *, struc static int drm_ioctl(struct file *, unsigned long, void *); static int drm_version_string(char *, size_t *, const char *); static paddr_t drm_mmap(dev_t, off_t, int); -static int drm_do_mmap(struct uvm_object *, vm_prot_t, voff_t, size_t, - vaddr_t *); static drm_ioctl_t drm_version; static drm_ioctl_t drm_mmap_ioctl; @@ -886,101 +878,56 @@ drm_mmap_ioctl(struct drm_device *dev, v const int prot = args->dnm_prot; const int flags = args->dnm_flags; const off_t offset = args->dnm_offset; - struct drm_gem_mm *const mm = dev->mm_private; - struct drm_hash_item *hash; - vm_prot_t vm_prot; - dev_t devno; struct uvm_object *uobj; - vaddr_t vaddr; + const vm_prot_t vm_maxprot = (VM_PROT_READ | VM_PROT_WRITE); + vm_prot_t vm_prot; + int uvmflag; + vaddr_t align, vaddr; int ret; /* XXX Copypasta from drm_gem_mmap. */ if (drm_device_is_unplugged(dev)) return -ENODEV; - if (prot != (PROT_READ | PROT_WRITE)) + if (prot != (prot & (PROT_READ | PROT_WRITE))) return -EACCES; if (flags != MAP_SHARED) return -EINVAL; (void)addr; /* XXX ignore -- no MAP_FIXED for now */ - KASSERT(prot == (PROT_READ | PROT_WRITE)); - vm_prot = (VM_PROT_READ | VM_PROT_WRITE); - - mutex_lock(&dev->struct_mutex); - if (drm_ht_find_item(&mm->offset_hash, atop(offset), &hash) == 0) { - /* GEM object. Map the GEM shared-memory uobj. */ - - struct drm_local_map *const map = - drm_hash_entry(hash, struct drm_map_list, hash)->map; - if ((map == NULL) || - (ISSET(map->flags, _DRM_RESTRICTED) && !DRM_SUSER())) { - ret = -EPERM; - goto out_unlock; - } - if (map->size < size) { - ret = -EINVAL; - goto out_unlock; - } - - struct drm_gem_object *const obj = map->handle; - if (obj->dev->driver->gem_uvm_ops == NULL) { - ret = -EINVAL; - goto out_unlock; - } - - uobj = obj->gemo_shm_uao; - ret = drm_do_mmap(uobj, prot, offset, size, &vaddr); - if (ret) - goto out_unlock; - drm_gem_object_reference(obj); - -out_unlock: mutex_unlock(&dev->struct_mutex); - } else { - /* - * Not a GEM object. Use the old mmap. - * - * XXX Unlocking is wrong here, but the uvm device mmap - * API will call cdev_mmap immediately (where we can - * control whether or not the device is locked) and in - * the fault handler (where the device is unlocked and - * we can't do a thing about it), so we have to unlock - * the device first. The good news is that this should - * only enable a broken application to use paddrs that - * it is allowed to use anyway but that perhaps are not - * the ones it expected. - */ - mutex_unlock(&dev->struct_mutex); - - devno = file->minor->device; - uobj = udv_attach(&devno, prot, offset, size); - if (uobj == NULL) { - ret = -EINVAL; - goto out; - } + /* Try a GEM object mapping first. */ + ret = drm_gem_mmap_object(dev, offset, size, prot, &uobj); + if (ret) + return ret; + if (uobj != NULL) + goto map; - ret = drm_do_mmap(uobj, prot, offset, size, &vaddr); - } + /* Try a traditional DRM mapping second. */ + ret = drm_mmap_object(dev, offset, size, prot, &uobj); + if (ret) + return ret; + if (uobj != NULL) + goto map; -out: if (ret == 0) - args->dnm_addr = (void *)vaddr; + /* Fail. */ return ret; -} -static int -drm_do_mmap(struct uvm_object *uobj, vm_prot_t prot, voff_t offset, - size_t size, vaddr_t *vaddr) -{ - vaddr_t align; - int uvmflag; +map: vm_prot = ((ISSET(prot, PROT_READ)? VM_PROT_READ : 0) | + (ISSET(prot, PROT_WRITE)? VM_PROT_WRITE : 0)); + KASSERT(vm_prot == (vm_prot & vm_maxprot)); + uvmflag = UVM_MAPFLAG(vm_prot, vm_maxprot, UVM_INH_COPY, + UVM_ADV_RANDOM, UVM_FLAG_COPYONW); align = 0; /* XXX */ - uvmflag = UVM_MAPFLAG(prot, prot, UVM_INH_COPY, UVM_ADV_RANDOM, - UVM_FLAG_COPYONW); - - *vaddr = (*curproc->p_emul->e_vm_default_addr)(curproc, + vaddr = (*curproc->p_emul->e_vm_default_addr)(curproc, (vaddr_t)curproc->p_vmspace->vm_daddr, size); /* XXX errno NetBSD->Linux */ - return -uvm_map(&curproc->p_vmspace->vm_map, vaddr, size, uobj, offset, + ret = -uvm_map(&curproc->p_vmspace->vm_map, &vaddr, size, uobj, offset, align, uvmflag); + if (ret) + return ret; + + /* Success! */ + args->dnm_addr = (void *)vaddr; + return 0; } Index: src/sys/external/bsd/drm2/drm/drm_gem_vm.c diff -u src/sys/external/bsd/drm2/drm/drm_gem_vm.c:1.1.2.3 src/sys/external/bsd/drm2/drm/drm_gem_vm.c:1.1.2.4 --- src/sys/external/bsd/drm2/drm/drm_gem_vm.c:1.1.2.3 Sun Sep 8 15:56:32 2013 +++ src/sys/external/bsd/drm2/drm/drm_gem_vm.c Wed Jan 22 16:40:44 2014 @@ -1,4 +1,4 @@ -/* $NetBSD: drm_gem_vm.c,v 1.1.2.3 2013/09/08 15:56:32 riastradh Exp $ */ +/* $NetBSD: drm_gem_vm.c,v 1.1.2.4 2014/01/22 16:40:44 riastradh Exp $ */ /*- * Copyright (c) 2013 The NetBSD Foundation, Inc. @@ -30,7 +30,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: drm_gem_vm.c,v 1.1.2.3 2013/09/08 15:56:32 riastradh Exp $"); +__KERNEL_RCSID(0, "$NetBSD: drm_gem_vm.c,v 1.1.2.4 2014/01/22 16:40:44 riastradh Exp $"); #include <sys/types.h> @@ -38,8 +38,8 @@ __KERNEL_RCSID(0, "$NetBSD: drm_gem_vm.c #include <drm/drmP.h> -static int drm_gem_mmap_object_locked(struct drm_device *, off_t *, - size_t, struct uvm_object **); +static int drm_gem_mmap_object_locked(struct drm_device *, off_t, size_t, + int, struct uvm_object **); void drm_gem_pager_reference(struct uvm_object *uobj) @@ -60,30 +60,31 @@ drm_gem_pager_detach(struct uvm_object * } int -drm_gem_mmap_object(struct drm_device *dev, off_t *byte_offsetp, size_t nbytes, - struct uvm_object **uobjp) +drm_gem_mmap_object(struct drm_device *dev, off_t byte_offset, size_t nbytes, + int prot, struct uvm_object **uobjp) { - int error; + int ret; mutex_lock(&dev->struct_mutex); - error = drm_gem_mmap_object_locked(dev, byte_offsetp, nbytes, uobjp); + ret = drm_gem_mmap_object_locked(dev, byte_offset, nbytes, prot, + uobjp); mutex_unlock(&dev->struct_mutex); - return error; + return ret; } static int -drm_gem_mmap_object_locked(struct drm_device *dev, off_t *byte_offsetp, - size_t nbytes, struct uvm_object **uobjp) +drm_gem_mmap_object_locked(struct drm_device *dev, off_t byte_offset, + size_t nbytes, int prot __unused, struct uvm_object **uobjp) { struct drm_gem_mm *const mm = dev->mm_private; - const off_t byte_offset = *byte_offsetp; const off_t page_offset = (byte_offset >> PAGE_SHIFT); struct drm_hash_item *hash; KASSERT(mutex_is_locked(&dev->struct_mutex)); KASSERT(drm_core_check_feature(dev, DRIVER_GEM)); KASSERT(dev->driver->gem_uvm_ops != NULL); + KASSERT(prot == (prot & (PROT_READ | PROT_WRITE))); if (byte_offset != (byte_offset & ~(PAGE_SIZE-1))) /* XXX kassert? */ return -EINVAL; Index: src/sys/external/bsd/drm2/drm/drm_vm.c diff -u src/sys/external/bsd/drm2/drm/drm_vm.c:1.1.2.3 src/sys/external/bsd/drm2/drm/drm_vm.c:1.1.2.4 --- src/sys/external/bsd/drm2/drm/drm_vm.c:1.1.2.3 Wed Jan 22 14:58:47 2014 +++ src/sys/external/bsd/drm2/drm/drm_vm.c Wed Jan 22 16:40:44 2014 @@ -1,4 +1,4 @@ -/* $NetBSD: drm_vm.c,v 1.1.2.3 2014/01/22 14:58:47 riastradh Exp $ */ +/* $NetBSD: drm_vm.c,v 1.1.2.4 2014/01/22 16:40:44 riastradh Exp $ */ /*- * Copyright (c) 2013 The NetBSD Foundation, Inc. @@ -30,11 +30,13 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: drm_vm.c,v 1.1.2.3 2014/01/22 14:58:47 riastradh Exp $"); +__KERNEL_RCSID(0, "$NetBSD: drm_vm.c,v 1.1.2.4 2014/01/22 16:40:44 riastradh Exp $"); #include <sys/types.h> +#include <sys/conf.h> #include <uvm/uvm_extern.h> +#include <uvm/uvm_device.h> #include <drm/drmP.h> @@ -43,6 +45,23 @@ static paddr_t drm_mmap_dma_paddr(struct static paddr_t drm_mmap_map_paddr(struct drm_device *, struct drm_local_map *, off_t, int); +extern struct cdevsw drm_cdevsw; /* XXX */ + +int +drm_mmap_object(struct drm_device *dev, off_t offset, size_t size, int prot, + struct uvm_object **uobjp) +{ + dev_t devno = cdevsw_lookup_major(&drm_cdevsw); + struct uvm_object *uobj; + + uobj = udv_attach(&devno, prot, offset, size); + if (uobj == NULL) + return -EINVAL; + + *uobjp = uobj; + return 0; +} + paddr_t drm_mmap_paddr(struct drm_device *dev, off_t byte_offset, int prot) {