diff options
author | Mark Kettenis <kettenis@cvs.openbsd.org> | 2013-12-01 11:47:14 +0000 |
---|---|---|
committer | Mark Kettenis <kettenis@cvs.openbsd.org> | 2013-12-01 11:47:14 +0000 |
commit | 483949b471e3a9d9cb668b0f697e08635dc74ebb (patch) | |
tree | e630188fd5e7dc345d1dfc3df82f98b38eff4608 | |
parent | fa811ab193cd676f4596308968456c6f42d65c25 (diff) |
Bring back the DRM_IOCTL_I915_GEM_WAIT diff now that I've figured out what
made it fail (WARN_ON() was evaluating its argument multiple times).
This time, also advertise support through I915_PARAM_HAS_WAIT_TIMEOUT.
-rw-r--r-- | sys/dev/pci/drm/i915/i915_dma.c | 5 | ||||
-rw-r--r-- | sys/dev/pci/drm/i915/i915_drv.c | 4 | ||||
-rw-r--r-- | sys/dev/pci/drm/i915/i915_drv.h | 3 | ||||
-rw-r--r-- | sys/dev/pci/drm/i915/i915_gem.c | 171 | ||||
-rw-r--r-- | sys/dev/pci/drm/i915/i915_trace.h | 12 | ||||
-rw-r--r-- | sys/dev/pci/drm/i915/intel_ringbuffer.c | 34 |
6 files changed, 184 insertions, 45 deletions
diff --git a/sys/dev/pci/drm/i915/i915_dma.c b/sys/dev/pci/drm/i915/i915_dma.c index 9b47168dd73..ad2a79e6db8 100644 --- a/sys/dev/pci/drm/i915/i915_dma.c +++ b/sys/dev/pci/drm/i915/i915_dma.c @@ -1,4 +1,4 @@ -/* $OpenBSD: i915_dma.c,v 1.13 2013/11/30 20:03:32 kettenis Exp $ */ +/* $OpenBSD: i915_dma.c,v 1.14 2013/12/01 11:47:13 kettenis Exp $ */ /* i915_dma.c -- DMA support for the I915 -*- linux-c -*- */ /* @@ -123,6 +123,9 @@ i915_getparam(struct drm_device *dev, void *data, struct drm_file *file_priv) case I915_PARAM_HAS_LLC: value = HAS_LLC(dev); break; + case I915_PARAM_HAS_WAIT_TIMEOUT: + value = 1; + break; case I915_PARAM_HAS_SEMAPHORES: value = i915_semaphore_is_enabled(dev); break; diff --git a/sys/dev/pci/drm/i915/i915_drv.c b/sys/dev/pci/drm/i915/i915_drv.c index c732661c90e..fcf89108dce 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.52 2013/11/30 20:13:36 kettenis Exp $ */ +/* $OpenBSD: i915_drv.c,v 1.53 2013/12/01 11:47:13 kettenis Exp $ */ /* * Copyright (c) 2008-2009 Owain G. Ainsworth <oga@openbsd.org> * @@ -1188,6 +1188,8 @@ inteldrm_doioctl(struct drm_device *dev, u_long cmd, caddr_t data, case DRM_IOCTL_I915_GEM_GET_CACHING: return (i915_gem_get_caching_ioctl(dev, data, file_priv)); + case DRM_IOCTL_I915_GEM_WAIT: + return (i915_gem_wait_ioctl(dev, data, file_priv)); case DRM_IOCTL_I915_GEM_CONTEXT_CREATE: return (i915_gem_context_create_ioctl(dev, data, file_priv)); diff --git a/sys/dev/pci/drm/i915/i915_drv.h b/sys/dev/pci/drm/i915/i915_drv.h index b59c18aff62..f8cad545313 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.40 2013/11/30 20:13:36 kettenis Exp $ */ +/* $OpenBSD: i915_drv.h,v 1.41 2013/12/01 11:47:13 kettenis Exp $ */ /* i915_drv.h -- Private header for the I915 driver -*- linux-c -*- */ /* @@ -1143,6 +1143,7 @@ int i915_gem_get_caching_ioctl(struct drm_device *, void *, struct drm_file *); int i915_gem_set_caching_ioctl(struct drm_device *, void *, struct drm_file *); +int i915_gem_wait_ioctl(struct drm_device *, void *, struct drm_file *); /* GEM memory manager functions */ int i915_gem_init_object(struct drm_obj *); diff --git a/sys/dev/pci/drm/i915/i915_gem.c b/sys/dev/pci/drm/i915/i915_gem.c index 9b8148a0bc7..9350f730a20 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.50 2013/11/30 20:13:36 kettenis Exp $ */ +/* $OpenBSD: i915_gem.c,v 1.51 2013/12/01 11:47:13 kettenis Exp $ */ /* * Copyright (c) 2008-2009 Owain G. Ainsworth <oga@openbsd.org> * @@ -52,6 +52,7 @@ #include <sys/queue.h> #include <sys/task.h> +#include <sys/time.h> static void i915_gem_object_flush_gtt_write_domain(struct drm_i915_gem_object *obj); static void i915_gem_object_flush_cpu_write_domain(struct drm_i915_gem_object *obj); @@ -78,6 +79,11 @@ static void i915_gem_shrink_all(struct drm_i915_private *dev_priv); #endif static void i915_gem_object_truncate(struct drm_i915_gem_object *obj); +static inline int timespec_to_jiffies(const struct timespec *); +static inline int timespec_valid(const struct timespec *); +static struct timespec ns_to_timespec(const int64_t); +static inline int64_t timespec_to_ns(const struct timespec *); + extern int ticks; static inline void i915_gem_object_fence_lost(struct drm_i915_gem_object *obj) @@ -1023,31 +1029,99 @@ i915_gem_check_olr(struct intel_ring_buffer *ring, u32 seqno) static int __wait_seqno(struct intel_ring_buffer *ring, u32 seqno, bool interruptible, struct timespec *timeout) { - struct drm_device *dev = ring->dev; - drm_i915_private_t *dev_priv = dev->dev_private; - int ret = 0; + drm_i915_private_t *dev_priv = ring->dev->dev_private; + struct timespec before, now, wait_time={1,0}; + struct timespec sleep_time; + unsigned long timeout_jiffies; + long end; + bool wait_forever = true; + int ret; if (i915_seqno_passed(ring->get_seqno(ring, true), seqno)) return 0; - mtx_enter(&dev_priv->irq_lock); - if (!i915_seqno_passed(ring->get_seqno(ring, true), seqno)) { - ring->irq_get(ring); - while (ret == 0) { - if (i915_seqno_passed(ring->get_seqno(ring, false), - seqno) || dev_priv->mm.wedged) + trace_i915_gem_request_wait_begin(ring, seqno); + + if (timeout != NULL) { + wait_time = *timeout; + wait_forever = false; + } + + timeout_jiffies = timespec_to_jiffies(&wait_time); + + if (WARN_ON(!ring->irq_get(ring))) + return -ENODEV; + + /* Record current time in case interrupted by signal, or wedged * */ + nanouptime(&before); + +#define EXIT_COND \ + (i915_seqno_passed(ring->get_seqno(ring, false), seqno) || \ + atomic_read(&dev_priv->mm.wedged)) + do { + mtx_enter(&dev_priv->irq_lock); + do { + if (EXIT_COND) { + ret = 0; break; - ret = -msleep(ring, &dev_priv->irq_lock, + } + ret = msleep(ring, &dev_priv->irq_lock, PZERO | (interruptible ? PCATCH : 0), - "gemwt", 0); + "gemwt", timeout_jiffies); + nanouptime(&now); + timespecsub(&now, &before, &sleep_time); + timeout_jiffies = timespec_to_jiffies(&wait_time); + timeout_jiffies -= timespec_to_jiffies(&sleep_time); + if (timeout_jiffies <= 0) { + timeout_jiffies = 0; + break; + } + } while (ret == 0); + mtx_leave(&dev_priv->irq_lock); + switch (ret) { + case 0: + end = timeout_jiffies; + break; + case ERESTART: + end = -ERESTARTSYS; + break; + case EWOULDBLOCK: + end = 0; + break; + default: + end = -ret; + break; } - ring->irq_put(ring); - } - mtx_leave(&dev_priv->irq_lock); - if (dev_priv->mm.wedged) - ret = -EIO; - return ret; + ret = i915_gem_check_wedge(dev_priv, interruptible); + if (ret) + end = ret; + } while (end == 0 && wait_forever); + + nanouptime(&now); + + ring->irq_put(ring); + trace_i915_gem_request_wait_end(ring, seqno); +#undef EXIT_COND + + if (timeout) { + timespecsub(&now, &before, &sleep_time); + timespecsub(timeout, &sleep_time, timeout); + } + + switch (end) { + case -EIO: + case -EAGAIN: /* Wedged */ + case -ERESTARTSYS: /* Signal */ + return (int)end; + case 0: /* Timeout */ + if (timeout) + timeout->tv_sec = timeout->tv_nsec = 0; + return -ETIMEDOUT; + default: /* Completed */ + WARN_ON(end < 0); /* We're not aware of other errors */ + return 0; + } } /** @@ -2348,7 +2422,6 @@ i915_gem_object_flush_active(struct drm_i915_gem_object *obj) return 0; } -#ifdef notyet /** * i915_gem_wait_ioctl - implements DRM_IOCTL_I915_GEM_WAIT * @DRM_IOCTL_ARGS: standard ioctl arguments @@ -2392,7 +2465,7 @@ i915_gem_wait_ioctl(struct drm_device *dev, void *data, struct drm_file *file) obj = to_intel_bo(drm_gem_object_lookup(dev, file, args->bo_handle)); if (&obj->base == NULL) { - mutex_unlock(&dev->struct_mutex); + DRM_UNLOCK(); return -ENOENT; } @@ -2413,12 +2486,12 @@ i915_gem_wait_ioctl(struct drm_device *dev, void *data, struct drm_file *file) * on this IOCTL with a 0 timeout (like busy ioctl) */ if (!args->timeout_ns) { - ret = -ETIME; + ret = -ETIMEDOUT; goto out; } drm_gem_object_unreference(&obj->base); - mutex_unlock(&dev->struct_mutex); + DRM_UNLOCK(); ret = __wait_seqno(ring, seqno, true, timeout); if (timeout) { @@ -2429,10 +2502,9 @@ i915_gem_wait_ioctl(struct drm_device *dev, void *data, struct drm_file *file) out: drm_gem_object_unreference(&obj->base); - mutex_unlock(&dev->struct_mutex); + DRM_UNLOCK(); return ret; } -#endif /* notyet */ /** * i915_gem_object_sync - sync an object to a ring. @@ -4490,3 +4562,54 @@ i915_gem_inactive_shrink(struct shrinker *shrinker, struct shrink_control *sc) return cnt; } #endif /* notyet */ + +#define NSEC_PER_SEC 1000000000L + +static inline int64_t +timespec_to_ns(const struct timespec *ts) +{ + return ((ts->tv_sec * NSEC_PER_SEC) + ts->tv_nsec); +} + +static inline int +timespec_to_jiffies(const struct timespec *ts) +{ + long long to_ticks; + + to_ticks = (long long)hz * ts->tv_sec + ts->tv_nsec / (tick * 1000); + if (to_ticks > INT_MAX) + to_ticks = INT_MAX; + + return ((int)to_ticks); +} + +static struct timespec +ns_to_timespec(const int64_t nsec) +{ + struct timespec ts; + int32_t rem; + + if (nsec == 0) { + ts.tv_sec = 0; + ts.tv_nsec = 0; + return (ts); + } + + ts.tv_sec = nsec / NSEC_PER_SEC; + rem = nsec % NSEC_PER_SEC; + if (rem < 0) { + ts.tv_sec--; + rem += NSEC_PER_SEC; + } + ts.tv_nsec = rem; + return (ts); +} + +static inline int +timespec_valid(const struct timespec *ts) +{ + if (ts->tv_sec < 0 || ts->tv_sec > 100000000 || + ts->tv_nsec < 0 || ts->tv_nsec >= 1000000000) + return (0); + return (1); +} diff --git a/sys/dev/pci/drm/i915/i915_trace.h b/sys/dev/pci/drm/i915/i915_trace.h index b84bf3a264c..15503b4e632 100644 --- a/sys/dev/pci/drm/i915/i915_trace.h +++ b/sys/dev/pci/drm/i915/i915_trace.h @@ -1,4 +1,4 @@ -/* $OpenBSD: i915_trace.h,v 1.8 2013/11/30 20:13:36 kettenis Exp $ */ +/* $OpenBSD: i915_trace.h,v 1.9 2013/12/01 11:47:13 kettenis Exp $ */ /* * Copyright (c) 2013 Mark Kettenis <kettenis@openbsd.org> * @@ -31,6 +31,16 @@ trace_i915_gem_request_retire(struct intel_ring_buffer *ring, u32 seqno) } static inline void +trace_i915_gem_request_wait_begin(struct intel_ring_buffer *ring, u32 seqno) +{ +} + +static inline void +trace_i915_gem_request_wait_end(struct intel_ring_buffer *ring, u32 seqno) +{ +} + +static inline void trace_i915_gem_object_change_domain(struct drm_i915_gem_object *obj, u32 old_read, u32 old_write) { diff --git a/sys/dev/pci/drm/i915/intel_ringbuffer.c b/sys/dev/pci/drm/i915/intel_ringbuffer.c index 3d6ad536950..4d0da2268a4 100644 --- a/sys/dev/pci/drm/i915/intel_ringbuffer.c +++ b/sys/dev/pci/drm/i915/intel_ringbuffer.c @@ -1,4 +1,4 @@ -/* $OpenBSD: intel_ringbuffer.c,v 1.13 2013/11/30 20:13:36 kettenis Exp $ */ +/* $OpenBSD: intel_ringbuffer.c,v 1.14 2013/12/01 11:47:13 kettenis Exp $ */ /* * Copyright © 2008-2010 Intel Corporation * @@ -761,13 +761,13 @@ gen5_ring_get_irq(struct intel_ring_buffer *ring) if (!dev->irq_enabled) return false; -// mtx_enter(&dev_priv->irq_lock); + mtx_enter(&dev_priv->irq_lock); if (ring->irq_refcount++ == 0) { dev_priv->gt_irq_mask &= ~ring->irq_enable_mask; I915_WRITE(GTIMR, dev_priv->gt_irq_mask); POSTING_READ(GTIMR); } -// mtx_leave(&dev_priv->irq_lock); + mtx_leave(&dev_priv->irq_lock); return true; } @@ -778,13 +778,13 @@ gen5_ring_put_irq(struct intel_ring_buffer *ring) struct drm_device *dev = ring->dev; drm_i915_private_t *dev_priv = dev->dev_private; -// mtx_enter(&dev_priv->irq_lock); + mtx_enter(&dev_priv->irq_lock); if (--ring->irq_refcount == 0) { dev_priv->gt_irq_mask |= ring->irq_enable_mask; I915_WRITE(GTIMR, dev_priv->gt_irq_mask); POSTING_READ(GTIMR); } -// mtx_leave(&dev_priv->irq_lock); + mtx_leave(&dev_priv->irq_lock); } static bool @@ -796,13 +796,13 @@ i9xx_ring_get_irq(struct intel_ring_buffer *ring) if (!dev->irq_enabled) return false; -// mtx_enter(&dev_priv->irq_lock); + mtx_enter(&dev_priv->irq_lock); if (ring->irq_refcount++ == 0) { dev_priv->irq_mask &= ~ring->irq_enable_mask; I915_WRITE(IMR, dev_priv->irq_mask); POSTING_READ(IMR); } -// mtx_leave(&dev_priv->irq_lock); + mtx_leave(&dev_priv->irq_lock); return true; } @@ -813,13 +813,13 @@ i9xx_ring_put_irq(struct intel_ring_buffer *ring) struct drm_device *dev = ring->dev; drm_i915_private_t *dev_priv = dev->dev_private; -// mtx_enter(&dev_priv->irq_lock); + mtx_enter(&dev_priv->irq_lock); if (--ring->irq_refcount == 0) { dev_priv->irq_mask |= ring->irq_enable_mask; I915_WRITE(IMR, dev_priv->irq_mask); POSTING_READ(IMR); } -// mtx_leave(&dev_priv->irq_lock); + mtx_leave(&dev_priv->irq_lock); } static bool @@ -831,13 +831,13 @@ i8xx_ring_get_irq(struct intel_ring_buffer *ring) if (!dev->irq_enabled) return false; -// mtx_enter(&dev_priv->irq_lock); + mtx_enter(&dev_priv->irq_lock); if (ring->irq_refcount++ == 0) { dev_priv->irq_mask &= ~ring->irq_enable_mask; I915_WRITE16(IMR, dev_priv->irq_mask); POSTING_READ16(IMR); } -// mtx_leave(&dev_priv->irq_lock); + mtx_leave(&dev_priv->irq_lock); return true; } @@ -848,13 +848,13 @@ i8xx_ring_put_irq(struct intel_ring_buffer *ring) struct drm_device *dev = ring->dev; drm_i915_private_t *dev_priv = dev->dev_private; -// mtx_enter(&dev_priv->irq_lock); + mtx_enter(&dev_priv->irq_lock); if (--ring->irq_refcount == 0) { dev_priv->irq_mask |= ring->irq_enable_mask; I915_WRITE16(IMR, dev_priv->irq_mask); POSTING_READ16(IMR); } -// mtx_leave(&dev_priv->irq_lock); + mtx_leave(&dev_priv->irq_lock); } void intel_ring_setup_status_page(struct intel_ring_buffer *ring) @@ -937,7 +937,7 @@ gen6_ring_get_irq(struct intel_ring_buffer *ring) * blt/bsd rings on ivb. */ gen6_gt_force_wake_get(dev_priv); -// mtx_enter(&dev_priv->irq_lock); + mtx_enter(&dev_priv->irq_lock); if (ring->irq_refcount++ == 0) { if (HAS_L3_GPU_CACHE(dev) && ring->id == RCS) I915_WRITE_IMR(ring, ~(ring->irq_enable_mask | @@ -948,7 +948,7 @@ gen6_ring_get_irq(struct intel_ring_buffer *ring) I915_WRITE(GTIMR, dev_priv->gt_irq_mask); POSTING_READ(GTIMR); } -// mtx_leave(&dev_priv->irq_lock); + mtx_leave(&dev_priv->irq_lock); return true; } @@ -959,7 +959,7 @@ gen6_ring_put_irq(struct intel_ring_buffer *ring) struct drm_device *dev = ring->dev; drm_i915_private_t *dev_priv = dev->dev_private; -// mtx_enter(&dev_priv->irq_lock); + mtx_enter(&dev_priv->irq_lock); if (--ring->irq_refcount == 0) { if (HAS_L3_GPU_CACHE(dev) && ring->id == RCS) I915_WRITE_IMR(ring, ~GEN6_RENDER_L3_PARITY_ERROR); @@ -969,7 +969,7 @@ gen6_ring_put_irq(struct intel_ring_buffer *ring) I915_WRITE(GTIMR, dev_priv->gt_irq_mask); POSTING_READ(GTIMR); } -// mtx_leave(&dev_priv->irq_lock); + mtx_leave(&dev_priv->irq_lock); gen6_gt_force_wake_put(dev_priv); } |