diff options
Diffstat (limited to 'sys/dev/pci/drm')
-rw-r--r-- | sys/dev/pci/drm/drmP.h | 6 | ||||
-rw-r--r-- | sys/dev/pci/drm/drm_drv.c | 115 | ||||
-rw-r--r-- | sys/dev/pci/drm/i915/i915_drv.c | 15 | ||||
-rw-r--r-- | sys/dev/pci/drm/radeon/radeon_kms.c | 11 |
4 files changed, 126 insertions, 21 deletions
diff --git a/sys/dev/pci/drm/drmP.h b/sys/dev/pci/drm/drmP.h index 4e8281f82cf..2de65ae06e6 100644 --- a/sys/dev/pci/drm/drmP.h +++ b/sys/dev/pci/drm/drmP.h @@ -1,4 +1,4 @@ -/* $OpenBSD: drmP.h,v 1.169 2014/03/09 07:42:29 jsg Exp $ */ +/* $OpenBSD: drmP.h,v 1.170 2014/03/13 12:45:04 kettenis Exp $ */ /* drmP.h -- Private header for Direct Rendering Manager -*- linux-c -*- * Created: Mon Jan 4 10:05:05 1999 by faith@precisioninsight.com */ @@ -785,6 +785,10 @@ struct drm_device { bus_dma_tag_t dmat; bus_space_tag_t bst; + struct mutex quiesce_mtx; + int quiesce; + int quiesce_count; + char *unique; /* Unique identifier: e.g., busid */ int unique_len; /* Length of unique field */ diff --git a/sys/dev/pci/drm/drm_drv.c b/sys/dev/pci/drm/drm_drv.c index 5db10f52c4e..31b4812ce66 100644 --- a/sys/dev/pci/drm/drm_drv.c +++ b/sys/dev/pci/drm/drm_drv.c @@ -1,4 +1,4 @@ -/* $OpenBSD: drm_drv.c,v 1.124 2014/03/09 07:42:29 jsg Exp $ */ +/* $OpenBSD: drm_drv.c,v 1.125 2014/03/13 12:45:04 kettenis Exp $ */ /*- * Copyright 2007-2009 Owain G. Ainsworth <oga@openbsd.org> * Copyright © 2008 Intel Corporation @@ -63,8 +63,12 @@ int drm_lastclose(struct drm_device *); void drm_attach(struct device *, struct device *, void *); int drm_probe(struct device *, void *, void *); int drm_detach(struct device *, int); +void drm_quiesce(struct drm_device *); +void drm_wakeup(struct drm_device *); +int drm_activate(struct device *, int); int drmprint(void *, const char *); int drmsubmatch(struct device *, void *, void *); +int drm_do_ioctl(struct drm_device *, int, u_long, caddr_t); int drm_dequeue_event(struct drm_device *, struct drm_file *, size_t, struct drm_pending_event **); @@ -212,6 +216,7 @@ drm_attach(struct device *parent, struct device *self, void *aux) rw_init(&dev->dev_lock, "drmdevlk"); mtx_init(&dev->event_lock, IPL_TTY); + mtx_init(&dev->quiesce_mtx, IPL_NONE); TAILQ_INIT(&dev->maplist); SPLAY_INIT(&dev->files); @@ -293,9 +298,47 @@ drm_detach(struct device *self, int flags) return 0; } +void +drm_quiesce(struct drm_device *dev) +{ + mtx_enter(&dev->quiesce_mtx); + dev->quiesce = 1; + while (dev->quiesce_count > 0) { + msleep(&dev->quiesce_count, &dev->quiesce_mtx, + PZERO, "drmqui", 0); + } + mtx_leave(&dev->quiesce_mtx); +} + +void +drm_wakeup(struct drm_device *dev) +{ + mtx_enter(&dev->quiesce_mtx); + dev->quiesce = 0; + wakeup(&dev->quiesce); + mtx_leave(&dev->quiesce_mtx); +} + +int +drm_activate(struct device *self, int act) +{ + struct drm_device *dev = (struct drm_device *)self; + + switch (act) { + case DVACT_QUIESCE: + drm_quiesce(dev); + break; + case DVACT_WAKEUP: + drm_wakeup(dev); + break; + } + + return (0); +} + struct cfattach drm_ca = { sizeof(struct drm_device), drm_probe, drm_attach, - drm_detach + drm_detach, drm_activate }; struct cfdriver drm_cd = { @@ -540,20 +583,13 @@ done: return (retcode); } -/* drmioctl is called whenever a process performs an ioctl on /dev/drm. - */ int -drmioctl(dev_t kdev, u_long cmd, caddr_t data, int flags, - struct proc *p) +drm_do_ioctl(struct drm_device *dev, int minor, u_long cmd, caddr_t data) { - struct drm_device *dev = drm_get_device_from_kdev(kdev); struct drm_file *file_priv; - if (dev == NULL) - return ENODEV; - DRM_LOCK(); - file_priv = drm_find_file_by_minor(dev, minor(kdev)); + file_priv = drm_find_file_by_minor(dev, minor); DRM_UNLOCK(); if (file_priv == NULL) { DRM_ERROR("can't find authenticator\n"); @@ -715,6 +751,34 @@ drmioctl(dev_t kdev, u_long cmd, caddr_t data, int flags, return (EINVAL); } +/* drmioctl is called whenever a process performs an ioctl on /dev/drm. + */ +int +drmioctl(dev_t kdev, u_long cmd, caddr_t data, int flags, struct proc *p) +{ + struct drm_device *dev = drm_get_device_from_kdev(kdev); + int error; + + if (dev == NULL) + return ENODEV; + + mtx_enter(&dev->quiesce_mtx); + while (dev->quiesce) + msleep(&dev->quiesce, &dev->quiesce_mtx, PZERO, "drmioc", 0); + dev->quiesce_count++; + mtx_leave(&dev->quiesce_mtx); + + error = drm_do_ioctl(dev, minor(kdev), cmd, data); + + mtx_enter(&dev->quiesce_mtx); + dev->quiesce_count--; + if (dev->quiesce) + wakeup(&dev->quiesce_count); + mtx_leave(&dev->quiesce_mtx); + + return (error); +} + int drmread(dev_t kdev, struct uio *uio, int ioflag) { @@ -1224,10 +1288,39 @@ drm_fault(struct uvm_faultinfo *ufi, vaddr_t vaddr, vm_page_t *pps, return(VM_PAGER_ERROR); } + /* + * We could end up here as the result of a copyin(9) or + * copyout(9) while handling an ioctl. So we must be careful + * not to deadlock. Therefore we only block if the quiesce + * count is zero, which guarantees we didn't enter from within + * an ioctl code path. + */ + mtx_enter(&dev->quiesce_mtx); + if (dev->quiesce && dev->quiesce_count == 0) { + mtx_leave(&dev->quiesce_mtx); + uvmfault_unlockall(ufi, ufi->entry->aref.ar_amap, uobj, NULL); + mtx_enter(&dev->quiesce_mtx); + while (dev->quiesce) { + msleep(&dev->quiesce, &dev->quiesce_mtx, + PZERO, "drmflt", 0); + } + mtx_leave(&dev->quiesce_mtx); + return(VM_PAGER_REFAULT); + } + dev->quiesce_count++; + mtx_leave(&dev->quiesce_mtx); + /* Call down into driver to do the magic */ ret = dev->driver->gem_fault(obj, ufi, entry->offset + (vaddr - entry->start), vaddr, pps, npages, centeridx, access_type, flags); + + mtx_enter(&dev->quiesce_mtx); + dev->quiesce_count--; + if (dev->quiesce) + wakeup(&dev->quiesce_count); + mtx_leave(&dev->quiesce_mtx); + return (ret); } diff --git a/sys/dev/pci/drm/i915/i915_drv.c b/sys/dev/pci/drm/i915/i915_drv.c index 12a9d7cbffa..5ec94840747 100644 --- a/sys/dev/pci/drm/i915/i915_drv.c +++ b/sys/dev/pci/drm/i915/i915_drv.c @@ -1,4 +1,4 @@ -/* $OpenBSD: i915_drv.c,v 1.63 2014/02/23 09:36:52 kettenis Exp $ */ +/* $OpenBSD: i915_drv.c,v 1.64 2014/03/13 12:45:04 kettenis Exp $ */ /* * Copyright (c) 2008-2009 Owain G. Ainsworth <oga@openbsd.org> * @@ -1113,24 +1113,29 @@ inteldrm_detach(struct device *self, int flags) } int -inteldrm_activate(struct device *arg, int act) +inteldrm_activate(struct device *self, int act) { - struct inteldrm_softc *dev_priv = (struct inteldrm_softc *)arg; - struct drm_device *dev = (struct drm_device *)dev_priv->drmdev; + struct inteldrm_softc *dev_priv = (struct inteldrm_softc *)self; + struct drm_device *dev = (struct drm_device *)dev_priv->drmdev; + int rv = 0; switch (act) { case DVACT_QUIESCE: + rv = config_activate_children(self, act); i915_drm_freeze(dev); break; case DVACT_SUSPEND: break; + case DVACT_RESUME: + break; case DVACT_WAKEUP: i915_drm_thaw(dev); intel_fb_restore_mode(dev); + rv = config_activate_children(self, act); break; } - return (0); + return (rv); } struct cfattach inteldrm_ca = { diff --git a/sys/dev/pci/drm/radeon/radeon_kms.c b/sys/dev/pci/drm/radeon/radeon_kms.c index 5d895ec56ad..67c42ac8a70 100644 --- a/sys/dev/pci/drm/radeon/radeon_kms.c +++ b/sys/dev/pci/drm/radeon/radeon_kms.c @@ -1,4 +1,4 @@ -/* $OpenBSD: radeon_kms.c,v 1.24 2014/02/25 00:03:38 kettenis Exp $ */ +/* $OpenBSD: radeon_kms.c,v 1.25 2014/03/13 12:45:04 kettenis Exp $ */ /* * Copyright 2008 Advanced Micro Devices, Inc. * Copyright 2008 Red Hat Inc. @@ -750,12 +750,14 @@ radeondrm_attachhook(void *xsc) } int -radeondrm_activate_kms(struct device *arg, int act) +radeondrm_activate_kms(struct device *self, int act) { - struct radeon_device *rdev = (struct radeon_device *)arg; + struct radeon_device *rdev = (struct radeon_device *)self; + int rv = 0; switch (act) { case DVACT_QUIESCE: + rv = config_activate_children(self, act); radeon_suspend_kms(rdev->ddev); break; case DVACT_SUSPEND: @@ -764,10 +766,11 @@ radeondrm_activate_kms(struct device *arg, int act) break; case DVACT_WAKEUP: radeon_resume_kms(rdev->ddev); + rv = config_activate_children(self, act); break; } - return (0); + return (rv); } /** |