diff options
Diffstat (limited to 'sys')
-rw-r--r-- | sys/dev/pci/drm/drm_linux.h | 42 | ||||
-rw-r--r-- | sys/dev/pci/drm/i915/i915_drv.c | 4 | ||||
-rw-r--r-- | sys/dev/pci/drm/i915/i915_drv.h | 5 | ||||
-rw-r--r-- | sys/dev/pci/drm/i915/i915_gem.c | 39 | ||||
-rw-r--r-- | sys/dev/pci/drm/i915/i915_irq.c | 9 |
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); /* |