summaryrefslogtreecommitdiff
path: root/sys/dev/pci/drm
diff options
context:
space:
mode:
Diffstat (limited to 'sys/dev/pci/drm')
-rw-r--r--sys/dev/pci/drm/drmP.h6
-rw-r--r--sys/dev/pci/drm/drm_drv.c115
-rw-r--r--sys/dev/pci/drm/i915/i915_drv.c15
-rw-r--r--sys/dev/pci/drm/radeon/radeon_kms.c11
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);
}
/**