Module Name:    src
Committed By:   riastradh
Date:           Wed Jul 24 03:55:17 UTC 2013

Modified Files:
        src/sys/external/bsd/drm2/drm [riastradh-drm2]: drm_drv.c

Log Message:
Manage an opencount for each drm device to block drm_detach.


To generate a diff of this commit:
cvs rdiff -u -r1.1.2.14 -r1.1.2.15 src/sys/external/bsd/drm2/drm/drm_drv.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_drv.c
diff -u src/sys/external/bsd/drm2/drm/drm_drv.c:1.1.2.14 src/sys/external/bsd/drm2/drm/drm_drv.c:1.1.2.15
--- src/sys/external/bsd/drm2/drm/drm_drv.c:1.1.2.14	Wed Jul 24 03:55:00 2013
+++ src/sys/external/bsd/drm2/drm/drm_drv.c	Wed Jul 24 03:55:17 2013
@@ -1,4 +1,4 @@
-/*	$NetBSD: drm_drv.c,v 1.1.2.14 2013/07/24 03:55:00 riastradh Exp $	*/
+/*	$NetBSD: drm_drv.c,v 1.1.2.15 2013/07/24 03:55:17 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.14 2013/07/24 03:55:00 riastradh Exp $");
+__KERNEL_RCSID(0, "$NetBSD: drm_drv.c,v 1.1.2.15 2013/07/24 03:55:17 riastradh Exp $");
 
 #include <sys/param.h>
 #include <sys/types.h>
@@ -58,6 +58,7 @@ static int drm_minor_types[] = {
 struct drm_softc {
 	struct drm_device	*sc_drm_dev;
 	struct drm_minor	sc_minor[__arraycount(drm_minor_types)];
+	unsigned int		sc_opencount;
 };
 
 static int	drm_match(device_t, cfdata_t, void *);
@@ -259,6 +260,7 @@ drm_attach(device_t parent, device_t sel
 	aprint_normal("\n");
 
 	sc->sc_drm_dev = dev;
+	sc->sc_opencount = 0;
 
 	if (device_unit(self) >= 64) { /* XXX Need to do something here!  */
 		aprint_error_dev(self, "can't handle >=64 drm devices!");
@@ -305,6 +307,9 @@ drm_detach(device_t self, int flags)
 	const struct drm_driver *const driver = dev->driver;
 	KASSERT(driver != NULL);
 
+	if (sc->sc_opencount != 0)
+		return EBUSY;
+
 	/*
 	 * XXX Synchronize with drm_fill_in_dev, perhaps with reference
 	 * to drm_put_dev.
@@ -359,9 +364,11 @@ drm_dev_minor(dev_t d)
 static int
 drm_open(dev_t d, int flags, int fmt, struct lwp *l)
 {
+	struct drm_softc *const sc = drm_dev_softc(d);
 	struct drm_minor *const dminor = drm_dev_minor(d);
 	int fd;
 	struct file *fp;
+	unsigned int opencount;
 	int error;
 
 	if (dminor == NULL) {
@@ -379,16 +386,25 @@ drm_open(dev_t d, int flags, int fmt, st
 		goto fail0;
 	}
 
+	do {
+		opencount = sc->sc_opencount;
+		if (opencount == UINT_MAX) {
+			error = EBUSY;
+			goto fail0;
+		}
+	} while (atomic_cas_uint(&sc->sc_opencount, opencount, (opencount + 1))
+	    != opencount);
+
 	error = fd_allocfile(&fp, &fd);
 	if (error)
-		goto fail0;
+		goto fail1;
 
 	struct drm_file *const file = kmem_zalloc(sizeof(*file), KM_SLEEP);
 
 	/* XXX errno Linux->NetBSD */
 	error = -drm_open_file(file, fp, dminor);
 	if (error)
-		goto fail2;
+		goto fail3;
 
 	error = fd_clone(fp, fd, flags, &drm_fileops, file);
 	KASSERT(error == EMOVEFD); /* XXX */
@@ -396,12 +412,15 @@ drm_open(dev_t d, int flags, int fmt, st
 	/* Success!  (But error has to be EMOVEFD, not 0.)  */
 	return error;
 
-fail2:
+fail3:
 	kmem_free(file, sizeof(*file));
 
-fail1: __unused
+fail2: __unused
 	fd_abort(curproc, fp, fd);
 
+fail1:
+	atomic_dec_uint(&sc->sc_opencount);
+
 fail0:
 	return error;
 }

Reply via email to