summaryrefslogtreecommitdiff
path: root/sys
diff options
context:
space:
mode:
authorMark Kettenis <kettenis@cvs.openbsd.org>2015-06-26 15:22:24 +0000
committerMark Kettenis <kettenis@cvs.openbsd.org>2015-06-26 15:22:24 +0000
commitdd94006924216ae5b26c9d85766ebeb7bf99d444 (patch)
tree26b32fa538edc8df330a3e30103dc984da7dbc9d /sys
parent5da64cfd908948ac939b78e11c12984256cd0dd2 (diff)
Add Linux completion API and use it.
ok jsg@
Diffstat (limited to 'sys')
-rw-r--r--sys/dev/pci/drm/drm_linux.h42
-rw-r--r--sys/dev/pci/drm/i915/i915_drv.c4
-rw-r--r--sys/dev/pci/drm/i915/i915_drv.h5
-rw-r--r--sys/dev/pci/drm/i915/i915_gem.c39
-rw-r--r--sys/dev/pci/drm/i915/i915_irq.c9
5 files changed, 65 insertions, 34 deletions
diff --git a/sys/dev/pci/drm/drm_linux.h b/sys/dev/pci/drm/drm_linux.h
index 514de9b75d1..34750f93305 100644
--- a/sys/dev/pci/drm/drm_linux.h
+++ b/sys/dev/pci/drm/drm_linux.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: drm_linux.h,v 1.30 2015/06/24 19:01:51 kettenis Exp $ */
+/* $OpenBSD: drm_linux.h,v 1.31 2015/06/26 15:22:23 kettenis Exp $ */
/*
* Copyright (c) 2013, 2014 Mark Kettenis
*
@@ -281,6 +281,46 @@ init_waitqueue_head(wait_queue_head_t *wq)
#define wake_up_all(x) wakeup(x)
#define wake_up_all_locked(x) wakeup(x)
+struct completion {
+ u_int done;
+ wait_queue_head_t wait;
+};
+
+#define INIT_COMPLETION(x) ((x).done = 0)
+
+static inline void
+init_completion(struct completion *x)
+{
+ x->done = 0;
+ mtx_init(&x->wait.lock, IPL_NONE);
+}
+
+static inline u_long
+wait_for_completion_interruptible_timeout(struct completion *x, u_long timo)
+{
+ int ret;
+
+ mtx_enter(&x->wait.lock);
+ while (x->done == 0) {
+ ret = msleep(x, &x->wait.lock, PCATCH, "wfcit", timo);
+ if (ret) {
+ mtx_leave(&x->wait.lock);
+ return (ret == EWOULDBLOCK) ? 0 : -ret;
+ }
+ }
+
+ return 1;
+}
+
+static inline void
+complete_all(struct completion *x)
+{
+ mtx_enter(&x->wait.lock);
+ x->done = 1;
+ mtx_leave(&x->wait.lock);
+ wakeup(x);
+}
+
struct workqueue_struct;
struct work_struct {
diff --git a/sys/dev/pci/drm/i915/i915_drv.c b/sys/dev/pci/drm/i915/i915_drv.c
index d897b6d7046..85a2268a294 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.84 2015/06/24 08:32:39 kettenis Exp $ */
+/* $OpenBSD: i915_drv.c,v 1.85 2015/06/26 15:22:23 kettenis Exp $ */
/*
* Copyright (c) 2008-2009 Owain G. Ainsworth <oga@openbsd.org>
*
@@ -929,7 +929,6 @@ inteldrm_attach(struct device *parent, struct device *self, void *aux)
mtx_init(&dev_priv->dpio_lock, IPL_TTY);
mtx_init(&dev_priv->gt_lock, IPL_TTY);
mtx_init(&mchdev_lock, IPL_TTY);
- mtx_init(&dev_priv->error_completion_lock, IPL_NONE);
rw_init(&dev_priv->rps.hw_lock, "rpshw");
task_set(&dev_priv->switchtask, inteldrm_doswitch, dev_priv);
@@ -988,7 +987,6 @@ inteldrm_attach(struct device *parent, struct device *self, void *aux)
timeout_set(&dev_priv->hangcheck_timer, i915_hangcheck_elapsed, dev_priv);
dev_priv->next_seqno = 1;
dev_priv->mm.suspended = 1;
- dev_priv->error_completion = 0;
if (pci_find_device(&bpa, inteldrm_gmch_match) == 0) {
printf(": can't find GMCH\n");
diff --git a/sys/dev/pci/drm/i915/i915_drv.h b/sys/dev/pci/drm/i915/i915_drv.h
index 55a80060ec9..4ed99ad83b4 100644
--- a/sys/dev/pci/drm/i915/i915_drv.h
+++ b/sys/dev/pci/drm/i915/i915_drv.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: i915_drv.h,v 1.65 2015/06/24 17:59:42 kettenis Exp $ */
+/* $OpenBSD: i915_drv.h,v 1.66 2015/06/26 15:22:23 kettenis Exp $ */
/* i915_drv.h -- Private header for the I915 driver -*- linux-c -*-
*/
/*
@@ -816,8 +816,7 @@ struct inteldrm_softc {
/* Protected by dev->error_lock. */
struct drm_i915_error_state *first_error;
struct work_struct error_work;
- int error_completion;
- struct mutex error_completion_lock;
+ struct completion error_completion;
struct workqueue_struct *wq;
/* number of ioctls + faults in flight */
diff --git a/sys/dev/pci/drm/i915/i915_gem.c b/sys/dev/pci/drm/i915/i915_gem.c
index 283361adc6a..e4edc6581af 100644
--- a/sys/dev/pci/drm/i915/i915_gem.c
+++ b/sys/dev/pci/drm/i915/i915_gem.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: i915_gem.c,v 1.97 2015/06/24 17:59:42 kettenis Exp $ */
+/* $OpenBSD: i915_gem.c,v 1.98 2015/06/26 15:22:23 kettenis Exp $ */
/*
* Copyright (c) 2008-2009 Owain G. Ainsworth <oga@openbsd.org>
*
@@ -110,6 +110,8 @@ static int
i915_gem_wait_for_error(struct drm_device *dev)
{
struct drm_i915_private *dev_priv = dev->dev_private;
+ struct completion *x = &dev_priv->error_completion;
+ unsigned long flags;
int ret;
if (!atomic_read(&dev_priv->mm.wedged))
@@ -120,16 +122,13 @@ i915_gem_wait_for_error(struct drm_device *dev)
* userspace. If it takes that long something really bad is going on and
* we should simply try to bail out and fail as gracefully as possible.
*/
- mtx_enter(&dev_priv->error_completion_lock);
- while (dev_priv->error_completion == 0) {
- ret = -msleep(&dev_priv->error_completion,
- &dev_priv->error_completion_lock, PCATCH, "915wco", 10*hz);
- if (ret) {
- mtx_leave(&dev_priv->error_completion_lock);
- return ret;
- }
+ ret = wait_for_completion_interruptible_timeout(x, 10*HZ);
+ if (ret == 0) {
+ DRM_ERROR("Timed out waiting for the gpu reset to complete\n");
+ return -EIO;
+ } else if (ret < 0) {
+ return ret;
}
- mtx_leave(&dev_priv->error_completion_lock);
if (atomic_read(&dev_priv->mm.wedged)) {
/* GPU is hung, bump the completion count to account for
@@ -137,9 +136,9 @@ i915_gem_wait_for_error(struct drm_device *dev)
* end up waiting upon a subsequent completion event that
* will never happen.
*/
- mtx_enter(&dev_priv->error_completion_lock);
- dev_priv->error_completion++;
- mtx_leave(&dev_priv->error_completion_lock);
+ spin_lock_irqsave(&x->wait.lock, flags);
+ x->done++;
+ spin_unlock_irqrestore(&x->wait.lock, flags);
}
return 0;
}
@@ -978,13 +977,15 @@ i915_gem_check_wedge(struct drm_i915_private *dev_priv,
bool interruptible)
{
if (atomic_read(&dev_priv->mm.wedged)) {
+ struct completion *x = &dev_priv->error_completion;
bool recovery_complete;
+ unsigned long flags;
/* Give the error handler a chance to run. */
- mtx_enter(&dev_priv->error_completion_lock);
- recovery_complete = dev_priv->error_completion > 0;
- mtx_leave(&dev_priv->error_completion_lock);
-
+ spin_lock_irqsave(&x->wait.lock, flags);
+ recovery_complete = x->done > 0;
+ spin_unlock_irqrestore(&x->wait.lock, flags);
+
/* Non-interruptible callers can't handle -EAGAIN, hence return
* -EIO unconditionally for these. */
if (!interruptible)
@@ -4309,11 +4310,7 @@ i915_gem_load(struct drm_device *dev)
INIT_LIST_HEAD(&dev_priv->fence_regs[i].lru_list);
INIT_DELAYED_WORK(&dev_priv->mm.retire_work,
i915_gem_retire_work_handler);
-#if 0
init_completion(&dev_priv->error_completion);
-#else
- dev_priv->error_completion = 0;
-#endif
/* On GEN3 we really need to make sure the ARB C3 LP bit is set */
if (IS_GEN3(dev)) {
diff --git a/sys/dev/pci/drm/i915/i915_irq.c b/sys/dev/pci/drm/i915/i915_irq.c
index d985103e437..24e39a5dfc4 100644
--- a/sys/dev/pci/drm/i915/i915_irq.c
+++ b/sys/dev/pci/drm/i915/i915_irq.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: i915_irq.c,v 1.26 2015/06/24 08:32:39 kettenis Exp $ */
+/* $OpenBSD: i915_irq.c,v 1.27 2015/06/26 15:22:23 kettenis Exp $ */
/* i915_irq.c -- IRQ support for the I915 -*- linux-c -*-
*/
/*
@@ -858,10 +858,7 @@ static void i915_error_work_func(struct work_struct *work)
atomic_set(&dev_priv->mm.wedged, 0);
// kobject_uevent_env(&dev->primary->kdev.kobj, KOBJ_CHANGE, reset_done_event);
}
- mtx_enter(&dev_priv->error_completion_lock);
- dev_priv->error_completion++;
- wakeup(&dev_priv->error_completion);
- mtx_leave(&dev_priv->error_completion_lock);
+ complete_all(&dev_priv->error_completion);
}
}
@@ -1466,7 +1463,7 @@ void i915_handle_error(struct drm_device *dev, bool wedged)
i915_report_and_clear_eir(dev);
if (wedged) {
-// INIT_COMPLETION(dev_priv->error_completion);
+ INIT_COMPLETION(dev_priv->error_completion);
atomic_set(&dev_priv->mm.wedged, 1);
/*