Wed Jul 24 03:55:17 2013 UTC ()
Manage an opencount for each drm device to block drm_detach.


(riastradh)
diff -r1.1.2.14 -r1.1.2.15 src/sys/external/bsd/drm2/drm/drm_drv.c

cvs diff -r1.1.2.14 -r1.1.2.15 src/sys/external/bsd/drm2/drm/Attic/drm_drv.c (expand / switch to unified diff)

--- src/sys/external/bsd/drm2/drm/Attic/drm_drv.c 2013/07/24 03:55:00 1.1.2.14
+++ src/sys/external/bsd/drm2/drm/Attic/drm_drv.c 2013/07/24 03:55:17 1.1.2.15
@@ -1,14 +1,14 @@ @@ -1,14 +1,14 @@
1/* $NetBSD: drm_drv.c,v 1.1.2.14 2013/07/24 03:55:00 riastradh Exp $ */ 1/* $NetBSD: drm_drv.c,v 1.1.2.15 2013/07/24 03:55:17 riastradh Exp $ */
2 2
3/*- 3/*-
4 * Copyright (c) 2013 The NetBSD Foundation, Inc. 4 * Copyright (c) 2013 The NetBSD Foundation, Inc.
5 * All rights reserved. 5 * All rights reserved.
6 * 6 *
7 * This code is derived from software contributed to The NetBSD Foundation 7 * This code is derived from software contributed to The NetBSD Foundation
8 * by Taylor R. Campbell. 8 * by Taylor R. Campbell.
9 * 9 *
10 * Redistribution and use in source and binary forms, with or without 10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions 11 * modification, are permitted provided that the following conditions
12 * are met: 12 * are met:
13 * 1. Redistributions of source code must retain the above copyright 13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer. 14 * notice, this list of conditions and the following disclaimer.
@@ -20,27 +20,27 @@ @@ -20,27 +20,27 @@
20 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 20 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29 * POSSIBILITY OF SUCH DAMAGE. 29 * POSSIBILITY OF SUCH DAMAGE.
30 */ 30 */
31 31
32#include <sys/cdefs.h> 32#include <sys/cdefs.h>
33__KERNEL_RCSID(0, "$NetBSD: drm_drv.c,v 1.1.2.14 2013/07/24 03:55:00 riastradh Exp $"); 33__KERNEL_RCSID(0, "$NetBSD: drm_drv.c,v 1.1.2.15 2013/07/24 03:55:17 riastradh Exp $");
34 34
35#include <sys/param.h> 35#include <sys/param.h>
36#include <sys/types.h> 36#include <sys/types.h>
37#include <sys/conf.h> 37#include <sys/conf.h>
38#include <sys/device.h> 38#include <sys/device.h>
39#include <sys/file.h> 39#include <sys/file.h>
40#include <sys/filedesc.h> 40#include <sys/filedesc.h>
41#include <sys/ioccom.h> 41#include <sys/ioccom.h>
42#include <sys/kauth.h> 42#include <sys/kauth.h>
43#if 0 /* XXX drm event poll */ 43#if 0 /* XXX drm event poll */
44#include <sys/poll.h> 44#include <sys/poll.h>
45#include <sys/select.h> 45#include <sys/select.h>
46#endif 46#endif
@@ -48,26 +48,27 @@ __KERNEL_RCSID(0, "$NetBSD: drm_drv.c,v  @@ -48,26 +48,27 @@ __KERNEL_RCSID(0, "$NetBSD: drm_drv.c,v
48#include <drm/drmP.h> 48#include <drm/drmP.h>
49 49
50static int drm_minor_types[] = { 50static int drm_minor_types[] = {
51 DRM_MINOR_LEGACY, 51 DRM_MINOR_LEGACY,
52 DRM_MINOR_CONTROL, 52 DRM_MINOR_CONTROL,
53#if 0 /* XXX Nothing seems to use this? */ 53#if 0 /* XXX Nothing seems to use this? */
54 DRM_MINOR_RENDER, 54 DRM_MINOR_RENDER,
55#endif 55#endif
56}; 56};
57 57
58struct drm_softc { 58struct drm_softc {
59 struct drm_device *sc_drm_dev; 59 struct drm_device *sc_drm_dev;
60 struct drm_minor sc_minor[__arraycount(drm_minor_types)]; 60 struct drm_minor sc_minor[__arraycount(drm_minor_types)];
 61 unsigned int sc_opencount;
61}; 62};
62 63
63static int drm_match(device_t, cfdata_t, void *); 64static int drm_match(device_t, cfdata_t, void *);
64static void drm_attach(device_t, device_t, void *); 65static void drm_attach(device_t, device_t, void *);
65static int drm_detach(device_t, int); 66static int drm_detach(device_t, int);
66 67
67static struct drm_softc *drm_dev_softc(dev_t); 68static struct drm_softc *drm_dev_softc(dev_t);
68static struct drm_minor *drm_dev_minor(dev_t); 69static struct drm_minor *drm_dev_minor(dev_t);
69 70
70static dev_type_open(drm_open); 71static dev_type_open(drm_open);
71 72
72static int drm_close(struct file *); 73static int drm_close(struct file *);
73static int drm_read(struct file *, off_t *, struct uio *, kauth_cred_t, 74static int drm_read(struct file *, off_t *, struct uio *, kauth_cred_t,
@@ -249,26 +250,27 @@ drm_attach(device_t parent, device_t sel @@ -249,26 +250,27 @@ drm_attach(device_t parent, device_t sel
249 struct drm_softc *sc = device_private(self); 250 struct drm_softc *sc = device_private(self);
250 struct drm_device *dev = aux; 251 struct drm_device *dev = aux;
251 unsigned int i; 252 unsigned int i;
252 int error; 253 int error;
253 254
254 KASSERT(sc != NULL); 255 KASSERT(sc != NULL);
255 KASSERT(dev != NULL); 256 KASSERT(dev != NULL);
256 KASSERT(dev->driver != NULL); 257 KASSERT(dev->driver != NULL);
257 KASSERT(device_unit(self) >= 0); 258 KASSERT(device_unit(self) >= 0);
258 259
259 aprint_normal("\n"); 260 aprint_normal("\n");
260 261
261 sc->sc_drm_dev = dev; 262 sc->sc_drm_dev = dev;
 263 sc->sc_opencount = 0;
262 264
263 if (device_unit(self) >= 64) { /* XXX Need to do something here! */ 265 if (device_unit(self) >= 64) { /* XXX Need to do something here! */
264 aprint_error_dev(self, "can't handle >=64 drm devices!"); 266 aprint_error_dev(self, "can't handle >=64 drm devices!");
265 return; 267 return;
266 } 268 }
267 269
268 for (i = 0; i < __arraycount(drm_minor_types); i++) { 270 for (i = 0; i < __arraycount(drm_minor_types); i++) {
269 sc->sc_minor[i].index = (i * 64) + device_unit(self); 271 sc->sc_minor[i].index = (i * 64) + device_unit(self);
270 sc->sc_minor[i].type = drm_minor_types[i]; 272 sc->sc_minor[i].type = drm_minor_types[i];
271 sc->sc_minor[i].device = 273 sc->sc_minor[i].device =
272 makedev(cdevsw_lookup_major(&drm_cdevsw), 274 makedev(cdevsw_lookup_major(&drm_cdevsw),
273 sc->sc_minor[i].index); 275 sc->sc_minor[i].index);
274 sc->sc_minor[i].kdev = self; 276 sc->sc_minor[i].kdev = self;
@@ -295,26 +297,29 @@ drm_attach(device_t parent, device_t sel @@ -295,26 +297,29 @@ drm_attach(device_t parent, device_t sel
295#endif 297#endif
296} 298}
297 299
298static int 300static int
299drm_detach(device_t self, int flags) 301drm_detach(device_t self, int flags)
300{ 302{
301 struct drm_softc *const sc = device_private(self); 303 struct drm_softc *const sc = device_private(self);
302 KASSERT(sc != NULL); 304 KASSERT(sc != NULL);
303 struct drm_device *const dev = sc->sc_drm_dev; 305 struct drm_device *const dev = sc->sc_drm_dev;
304 KASSERT(dev != NULL); 306 KASSERT(dev != NULL);
305 const struct drm_driver *const driver = dev->driver; 307 const struct drm_driver *const driver = dev->driver;
306 KASSERT(driver != NULL); 308 KASSERT(driver != NULL);
307 309
 310 if (sc->sc_opencount != 0)
 311 return EBUSY;
 312
308 /* 313 /*
309 * XXX Synchronize with drm_fill_in_dev, perhaps with reference 314 * XXX Synchronize with drm_fill_in_dev, perhaps with reference
310 * to drm_put_dev. 315 * to drm_put_dev.
311 */ 316 */
312 317
313 if (ISSET(driver->driver_features, DRIVER_GEM)) 318 if (ISSET(driver->driver_features, DRIVER_GEM))
314 drm_gem_destroy(dev); 319 drm_gem_destroy(dev);
315 320
316 drm_ctxbitmap_cleanup(dev); 321 drm_ctxbitmap_cleanup(dev);
317 322
318 /* XXX Move to dev->driver->bus->agp_destroy. */ 323 /* XXX Move to dev->driver->bus->agp_destroy. */
319 if (drm_core_has_MTRR(dev) && 324 if (drm_core_has_MTRR(dev) &&
320 drm_core_has_AGP(dev) && 325 drm_core_has_AGP(dev) &&
@@ -349,69 +354,83 @@ drm_dev_minor(dev_t d) @@ -349,69 +354,83 @@ drm_dev_minor(dev_t d)
349 if (sc == NULL) 354 if (sc == NULL)
350 return NULL; 355 return NULL;
351 356
352 const unsigned int i = minor(d) / 64; 357 const unsigned int i = minor(d) / 64;
353 if (i >= __arraycount(drm_minor_types)) 358 if (i >= __arraycount(drm_minor_types))
354 return NULL; 359 return NULL;
355 360
356 return &sc->sc_minor[i]; 361 return &sc->sc_minor[i];
357} 362}
358 363
359static int 364static int
360drm_open(dev_t d, int flags, int fmt, struct lwp *l) 365drm_open(dev_t d, int flags, int fmt, struct lwp *l)
361{ 366{
 367 struct drm_softc *const sc = drm_dev_softc(d);
362 struct drm_minor *const dminor = drm_dev_minor(d); 368 struct drm_minor *const dminor = drm_dev_minor(d);
363 int fd; 369 int fd;
364 struct file *fp; 370 struct file *fp;
 371 unsigned int opencount;
365 int error; 372 int error;
366 373
367 if (dminor == NULL) { 374 if (dminor == NULL) {
368 error = ENXIO; 375 error = ENXIO;
369 goto fail0; 376 goto fail0;
370 } 377 }
371 378
372 if (flags & O_EXCL) { 379 if (flags & O_EXCL) {
373 error = EBUSY; 380 error = EBUSY;
374 goto fail0; 381 goto fail0;
375 } 382 }
376 383
377 if (dminor->dev->switch_power_state != DRM_SWITCH_POWER_ON) { 384 if (dminor->dev->switch_power_state != DRM_SWITCH_POWER_ON) {
378 error = EINVAL; 385 error = EINVAL;
379 goto fail0; 386 goto fail0;
380 } 387 }
381 388
 389 do {
 390 opencount = sc->sc_opencount;
 391 if (opencount == UINT_MAX) {
 392 error = EBUSY;
 393 goto fail0;
 394 }
 395 } while (atomic_cas_uint(&sc->sc_opencount, opencount, (opencount + 1))
 396 != opencount);
 397
382 error = fd_allocfile(&fp, &fd); 398 error = fd_allocfile(&fp, &fd);
383 if (error) 399 if (error)
384 goto fail0; 400 goto fail1;
385 401
386 struct drm_file *const file = kmem_zalloc(sizeof(*file), KM_SLEEP); 402 struct drm_file *const file = kmem_zalloc(sizeof(*file), KM_SLEEP);
387 403
388 /* XXX errno Linux->NetBSD */ 404 /* XXX errno Linux->NetBSD */
389 error = -drm_open_file(file, fp, dminor); 405 error = -drm_open_file(file, fp, dminor);
390 if (error) 406 if (error)
391 goto fail2; 407 goto fail3;
392 408
393 error = fd_clone(fp, fd, flags, &drm_fileops, file); 409 error = fd_clone(fp, fd, flags, &drm_fileops, file);
394 KASSERT(error == EMOVEFD); /* XXX */ 410 KASSERT(error == EMOVEFD); /* XXX */
395 411
396 /* Success! (But error has to be EMOVEFD, not 0.) */ 412 /* Success! (But error has to be EMOVEFD, not 0.) */
397 return error; 413 return error;
398 414
399fail2: 415fail3:
400 kmem_free(file, sizeof(*file)); 416 kmem_free(file, sizeof(*file));
401 417
402fail1: __unused 418fail2: __unused
403 fd_abort(curproc, fp, fd); 419 fd_abort(curproc, fp, fd);
404 420
 421fail1:
 422 atomic_dec_uint(&sc->sc_opencount);
 423
405fail0: 424fail0:
406 return error; 425 return error;
407} 426}
408 427
409static int 428static int
410drm_close(struct file *fp) 429drm_close(struct file *fp)
411{ 430{
412 struct drm_file *const file = fp->f_data; 431 struct drm_file *const file = fp->f_data;
413 432
414 /* XXX errno Linux->NetBSD */ 433 /* XXX errno Linux->NetBSD */
415 return -drm_close_file(file); 434 return -drm_close_file(file);
416} 435}
417 436