Module Name: src Committed By: riastradh Date: Sun Dec 19 00:57:56 UTC 2021
Modified Files: src/sys/external/bsd/drm2/drm: files.drmkms Added Files: src/sys/external/bsd/drm2/drm: drm_file.c Removed Files: src/sys/external/bsd/drm2/drm: drm_fops.c Log Message: Rename drm_fops.c -> drm_file.c To generate a diff of this commit: cvs rdiff -u -r0 -r1.1 src/sys/external/bsd/drm2/drm/drm_file.c cvs rdiff -u -r1.15 -r0 src/sys/external/bsd/drm2/drm/drm_fops.c cvs rdiff -u -r1.43 -r1.44 src/sys/external/bsd/drm2/drm/files.drmkms 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/drm/files.drmkms diff -u src/sys/external/bsd/drm2/drm/files.drmkms:1.43 src/sys/external/bsd/drm2/drm/files.drmkms:1.44 --- src/sys/external/bsd/drm2/drm/files.drmkms:1.43 Sun Dec 19 00:54:15 2021 +++ src/sys/external/bsd/drm2/drm/files.drmkms Sun Dec 19 00:57:55 2021 @@ -1,4 +1,4 @@ -# $NetBSD: files.drmkms,v 1.43 2021/12/19 00:54:15 riastradh Exp $ +# $NetBSD: files.drmkms,v 1.44 2021/12/19 00:57:55 riastradh Exp $ version 20180827 @@ -126,7 +126,7 @@ file external/bsd/drm2/dist/drm/drm_vma_ file external/bsd/drm2/dist/drm/drm_vm.c drmkms file external/bsd/drm2/dist/drm/drm_writeback.c drmkms file external/bsd/drm2/drm/drm_cache.c drmkms -file external/bsd/drm2/drm/drm_fops.c drmkms +file external/bsd/drm2/drm/drm_file.c drmkms file external/bsd/drm2/drm/drm_gem_framebuffer_helper.c drmkms file external/bsd/drm2/drm/drm_lease.c drmkms file external/bsd/drm2/drm/drm_lock.c drmkms Added files: Index: src/sys/external/bsd/drm2/drm/drm_file.c diff -u /dev/null src/sys/external/bsd/drm2/drm/drm_file.c:1.1 --- /dev/null Sun Dec 19 00:57:56 2021 +++ src/sys/external/bsd/drm2/drm/drm_file.c Sun Dec 19 00:57:55 2021 @@ -0,0 +1,307 @@ +/* $NetBSD: drm_file.c,v 1.1 2021/12/19 00:57:55 riastradh Exp $ */ + +/*- + * Copyright (c) 2013 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Taylor R. Campbell. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include <sys/cdefs.h> +__KERNEL_RCSID(0, "$NetBSD: drm_file.c,v 1.1 2021/12/19 00:57:55 riastradh Exp $"); + +#include <sys/param.h> +#include <sys/select.h> + +#include <drm/drmP.h> +#include <drm/drm_internal.h> +#include <drm/drm_legacy.h> +#include "../dist/drm/drm_legacy.h" + +static int drm_open_file_master(struct drm_file *); + +static void drm_master_release(struct drm_file *); +static void drm_events_release(struct drm_file *); +static void drm_close_file_master(struct drm_file *); + +int +drm_open_file(struct drm_file *file, void *fp, struct drm_minor *minor) +{ + struct drm_device *const dev = minor->dev; + int ret; + + file->authenticated = capable(CAP_SYS_ADMIN); /* XXX */ + file->is_master = false; + file->stereo_allowed = false; + file->universal_planes = false; + file->atomic = false; + file->allowed_master = false; + file->magic = 0; + INIT_LIST_HEAD(&file->lhead); + file->minor = minor; + file->lock_count = 0; + /* file->object_idr is initialized by drm_gem_open. */ + /* file->table_lock is initialized by drm_gem_open. */ + file->filp = fp; + file->driver_priv = NULL; + file->master = NULL; + INIT_LIST_HEAD(&file->fbs); + linux_mutex_init(&file->fbs_lock); + INIT_LIST_HEAD(&file->blobs); + DRM_INIT_WAITQUEUE(&file->event_wait, "drmevent"); + selinit(&file->event_selq); + INIT_LIST_HEAD(&file->event_list); + file->event_space = 0x1000; /* XXX cargo-culted from Linux */ + /* file->prime is initialized by drm_prime_init_file_private. */ + + if (drm_core_check_feature(dev, DRIVER_GEM)) + drm_gem_open(dev, file); + if (drm_core_check_feature(dev, DRIVER_PRIME)) + drm_prime_init_file_private(&file->prime); + + if (dev->driver->open) { + ret = (*dev->driver->open)(dev, file); + if (ret) + goto fail0; + } + + ret = drm_open_file_master(file); + if (ret) + goto fail1; + + mutex_lock(&dev->struct_mutex); + list_add(&file->lhead, &dev->filelist); + mutex_unlock(&dev->struct_mutex); + + /* Success! */ + return 0; + +fail1: /* + * XXX This error branch needs scrutiny, but Linux's error + * branches are incomprehensible and look wronger. + */ + if (dev->driver->preclose) + (*dev->driver->preclose)(dev, file); + if (dev->driver->postclose) + (*dev->driver->postclose)(dev, file); +fail0: + if (drm_core_check_feature(dev, DRIVER_PRIME)) + drm_prime_destroy_file_private(&file->prime); + if (drm_core_check_feature(dev, DRIVER_GEM)) + drm_gem_release(dev, file); + return ret; +} + +int +drm_new_set_master(struct drm_device *dev, struct drm_file *file) +{ + struct drm_master *old_master; + int ret; + + KASSERT(mutex_is_locked(&dev->master_mutex)); + KASSERT(file->minor->type == DRM_MINOR_LEGACY); + KASSERT(file->minor->master == NULL); + + file->minor->master = drm_master_create(file->minor); + if (file->minor->master == NULL) { + ret = -ENOMEM; + goto fail0; + } + + /* + * Save the old master, to drop a reference later if all goes + * well, and get a reference to the new one. + */ + old_master = file->master; + file->master = drm_master_get(file->minor->master); + + /* Invoke the driver callbacks master_create and master_set. */ + if (dev->driver->master_create) { + ret = (*dev->driver->master_create)(dev, file->minor->master); + if (ret) + goto fail1; + } + + if (dev->driver->master_set) { + ret = (*dev->driver->master_set)(dev, file, true); + if (ret) + goto fail1; + } + + /* + * Mark ourselves as an authenticated master, and allowed to + * set a new master. + */ + file->is_master = 1; + file->allowed_master = 1; + file->authenticated = 1; + + /* If there was an old master, release it now. */ + if (old_master) + drm_master_put(&old_master); + + /* Success! */ + return 0; + +fail1: + /* Release the master we just created. */ + drm_master_put(&file->minor->master); + KASSERT(file->minor->master == NULL); + /* Release the reference we just added in the file. */ + drm_master_put(&file->master); + KASSERT(file->master == NULL); + /* Restore the old master if there was one. */ + file->master = old_master; +fail0: KASSERT(ret); + return ret; +} + +static int +drm_open_file_master(struct drm_file *file) +{ + struct drm_device *const dev = file->minor->dev; + int ret; + + /* If this is not the legacy device, there are no masters. */ + if (file->minor->type != DRM_MINOR_LEGACY) + return 0; + + mutex_lock(&dev->master_mutex); + if (file->minor->master != NULL) { + /* + * If the minor already has a master, get a reference + * to it. + */ + file->master = drm_master_get(file->minor->master); + ret = 0; + } else { + /* + * Otherwise, automatically behave as though we had + * just done setmaster. + */ + ret = drm_new_set_master(dev, file); + } + mutex_unlock(&dev->master_mutex); + + return ret; +} + +void +drm_close_file(struct drm_file *file) +{ + struct drm_minor *const minor = file->minor; + struct drm_device *const dev = minor->dev; + + mutex_lock(&dev->struct_mutex); + list_del(&file->lhead); + if (file->magic) + idr_remove(&file->master->magic_map, file->magic); + mutex_unlock(&dev->struct_mutex); + + if (dev->driver->preclose) + (*dev->driver->preclose)(dev, file); + + if (minor->master) + drm_master_release(file); + if (drm_core_check_feature(dev, DRIVER_HAVE_DMA)) + drm_legacy_reclaim_buffers(dev, file); + drm_events_release(file); + if (drm_core_check_feature(dev, DRIVER_MODESET)) { + drm_fb_release(file); + drm_property_destroy_user_blobs(dev, file); + } + if (drm_core_check_feature(dev, DRIVER_GEM)) + drm_gem_release(dev, file); + drm_legacy_ctxbitmap_flush(dev, file); + drm_close_file_master(file); + + if (dev->driver->postclose) + (*dev->driver->postclose)(dev, file); + + if (drm_core_check_feature(dev, DRIVER_PRIME)) + drm_prime_destroy_file_private(&file->prime); + + seldestroy(&file->event_selq); + DRM_DESTROY_WAITQUEUE(&file->event_wait); + linux_mutex_destroy(&file->fbs_lock); +} + +static void +drm_master_release(struct drm_file *file) +{ + + /* + * XXX I think this locking concept is wrong -- we need to hold + * file->master->lock.spinlock across the two calls to + * drm_legacy_i_have_hw_lock and drm_legacy_lock_free. + */ + if (drm_legacy_i_have_hw_lock(file->minor->dev, file)) + drm_legacy_lock_free(&file->master->lock, + _DRM_LOCKING_CONTEXT(file->master->lock.hw_lock->lock)); +} + +static void +drm_events_release(struct drm_file *file) +{ + struct drm_device *const dev = file->minor->dev; + struct drm_pending_vblank_event *vblank, *vblank_next; + struct drm_pending_event *event, *event_next; + unsigned long flags; + + spin_lock_irqsave(&dev->event_lock, flags); + + list_for_each_entry_safe(vblank, vblank_next, &dev->vblank_event_list, + base.link) { + if (vblank->base.file_priv == file) { + list_del(&vblank->base.link); + drm_vblank_put(dev, vblank->pipe); + (*vblank->base.destroy)(&vblank->base); + } + } + list_for_each_entry_safe(event, event_next, &file->event_list, link) { + (*event->destroy)(event); + } + + spin_unlock_irqrestore(&dev->event_lock, flags); +} + +static void +drm_close_file_master(struct drm_file *file) +{ + struct drm_device *const dev = file->minor->dev; + + mutex_lock(&dev->master_mutex); + if (file->is_master) { + if (file->minor->master == file->master) { + if (dev->driver->master_drop) + (*dev->driver->master_drop)(dev, file, true); + drm_master_put(&file->minor->master); + } + } + if (file->master != NULL) + drm_master_put(&file->master); + file->is_master = 0; + mutex_unlock(&dev->master_mutex); +}