Module Name:    src
Committed By:   riastradh
Date:           Mon Aug 27 07:53:52 UTC 2018

Modified Files:
        src/sys/external/bsd/drm2/drm: drm_fops.c

Log Message:
Implement drm_new_set_master in drm_fops.c and use it.


To generate a diff of this commit:
cvs rdiff -u -r1.9 -r1.10 src/sys/external/bsd/drm2/drm/drm_fops.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/drm/drm_fops.c
diff -u src/sys/external/bsd/drm2/drm/drm_fops.c:1.9 src/sys/external/bsd/drm2/drm/drm_fops.c:1.10
--- src/sys/external/bsd/drm2/drm/drm_fops.c:1.9	Mon Aug 27 07:01:15 2018
+++ src/sys/external/bsd/drm2/drm/drm_fops.c	Mon Aug 27 07:53:52 2018
@@ -1,4 +1,4 @@
-/*	$NetBSD: drm_fops.c,v 1.9 2018/08/27 07:01:15 riastradh Exp $	*/
+/*	$NetBSD: drm_fops.c,v 1.10 2018/08/27 07:53:52 riastradh Exp $	*/
 
 /*-
  * Copyright (c) 2013 The NetBSD Foundation, Inc.
@@ -30,7 +30,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: drm_fops.c,v 1.9 2018/08/27 07:01:15 riastradh Exp $");
+__KERNEL_RCSID(0, "$NetBSD: drm_fops.c,v 1.10 2018/08/27 07:53:52 riastradh Exp $");
 
 #include <sys/param.h>
 #include <sys/select.h>
@@ -114,52 +114,100 @@ fail0:
 	return ret;
 }
 
-static int
-drm_open_file_master(struct drm_file *file)
+int
+drm_new_set_master(struct drm_device *dev, struct drm_file *file)
 {
-	struct drm_device *const dev = file->minor->dev;
+	struct drm_master *old_master;
 	int ret;
 
-	mutex_lock(&dev->master_mutex);
-	if (file->minor->master != NULL) {
-		file->master = drm_master_get(file->minor->master);
-	} else {
-		file->minor->master = drm_master_create(file->minor);
-		if (file->minor->master == NULL) {
-			ret = -ENOMEM;
-			goto fail0;
-		}
+	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;
+	}
 
-		file->is_master = 1;
-		file->master = drm_master_get(file->minor->master);
-		file->authenticated = 1;
+	/*
+	 * 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);
 
-		if (dev->driver->master_create) {
-			ret = (*dev->driver->master_create)(dev,
-			    file->minor->master);
-			if (ret)
-				goto fail1;
-		}
+	/* 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;
-		}
+	if (dev->driver->master_set) {
+		ret = (*dev->driver->master_set)(dev, file, true);
+		if (ret)
+			goto fail1;
 	}
-	mutex_unlock(&dev->master_mutex);
+
+	/*
+	 * 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:	mutex_unlock(&dev->master_mutex);
-	/* drm_master_put handles calling master_destroy for us.  */
+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)
 {

Reply via email to