diff options
Diffstat (limited to 'linux-core')
-rw-r--r-- | linux-core/drmP.h | 8 | ||||
-rw-r--r-- | linux-core/drm_fence.c | 92 | ||||
-rw-r--r-- | linux-core/i915_drv.c | 1 | ||||
-rw-r--r-- | linux-core/i915_fence.c | 22 |
4 files changed, 75 insertions, 48 deletions
diff --git a/linux-core/drmP.h b/linux-core/drmP.h index e070c073..e0afc508 100644 --- a/linux-core/drmP.h +++ b/linux-core/drmP.h @@ -793,10 +793,11 @@ typedef struct drm_fence_driver{ uint32_t flush_diff; uint32_t sequence_mask; int lazy_capable; - int (*emit) (struct drm_device *dev, uint32_t flags, + int (*has_irq) (struct drm_device *dev, uint32_t class, uint32_t flags); + int (*emit) (struct drm_device *dev, uint32_t class, uint32_t flags, uint32_t *breadcrumb, uint32_t *native_type); - void (*poke_flush) (struct drm_device *dev); + void (*poke_flush) (struct drm_device *dev, uint32_t class); } drm_fence_driver_t; #define _DRM_FENCE_TYPE_EXE 0x00 @@ -1464,7 +1465,8 @@ extern int drm_user_object_unref(drm_file_t *priv, uint32_t user_token, drm_obje * fence objects (drm_fence.c) */ -extern void drm_fence_handler(drm_device_t *dev, uint32_t breadcrumb, uint32_t type); +extern void drm_fence_handler(drm_device_t *dev, uint32_t class, + uint32_t sequence, uint32_t type); extern void drm_fence_manager_init(drm_device_t *dev); extern void drm_fence_manager_takedown(drm_device_t *dev); extern void drm_fence_flush_old(drm_device_t *dev, uint32_t sequence); diff --git a/linux-core/drm_fence.c b/linux-core/drm_fence.c index b4125c6e..dc428949 100644 --- a/linux-core/drm_fence.c +++ b/linux-core/drm_fence.c @@ -34,7 +34,8 @@ * Typically called by the IRQ handler. */ -void drm_fence_handler(drm_device_t * dev, uint32_t sequence, uint32_t type) +void drm_fence_handler(drm_device_t * dev, uint32_t class, + uint32_t sequence, uint32_t type) { int wake = 0; uint32_t diff; @@ -156,7 +157,7 @@ static int fence_signaled(drm_device_t * dev, volatile drm_fence_driver_t *driver = dev->driver->fence_driver; if (poke_flush) - driver->poke_flush(dev); + driver->poke_flush(dev, fence->class); read_lock_irqsave(&fm->lock, flags); signaled = (fence->type & mask & fence->signaled) == (fence->type & mask); @@ -177,7 +178,6 @@ static void drm_fence_flush_exe(drm_fence_manager_t * fm, * Last_exe_flush is invalid. Find oldest sequence. */ -/* list = fm->fence_types[_DRM_FENCE_TYPE_EXE];*/ list = &fm->ring; if (list->next == &fm->ring) { return; @@ -234,7 +234,7 @@ int drm_fence_object_flush(drm_device_t * dev, } } write_unlock_irqrestore(&fm->lock, flags); - driver->poke_flush(dev); + driver->poke_flush(dev, fence->class); return 0; } @@ -273,11 +273,37 @@ void drm_fence_flush_old(drm_device_t * dev, uint32_t sequence) EXPORT_SYMBOL(drm_fence_flush_old); +static int drm_fence_lazy_wait(drm_device_t *dev, + volatile drm_fence_object_t *fence, + int ignore_signals, uint32_t mask) +{ + drm_fence_manager_t *fm = &dev->fm; + unsigned long _end = jiffies + 3*DRM_HZ; + int ret = 0; + + do { + DRM_WAIT_ON(ret, fm->fence_queue, 3 * DRM_HZ, + fence_signaled(dev, fence, mask, 1)); + if (time_after_eq(jiffies, _end)) + break; + } while (ret == -EINTR && ignore_signals); + if (time_after_eq(jiffies, _end) && (ret != 0)) + ret = -EBUSY; + if (ret) { + if (ret == -EBUSY) { + DRM_ERROR("Fence timeout. " + "GPU lockup or fence driver was " + "taken down.\n"); + } + return ((ret == -EINTR) ? -EAGAIN : ret); + } + return 0; +} + int drm_fence_object_wait(drm_device_t * dev, volatile drm_fence_object_t * fence, int lazy, int ignore_signals, uint32_t mask) { - drm_fence_manager_t *fm = &dev->fm; drm_fence_driver_t *driver = dev->driver->fence_driver; int ret = 0; unsigned long _end; @@ -298,46 +324,32 @@ int drm_fence_object_wait(drm_device_t * dev, if (lazy && driver->lazy_capable) { - do { - DRM_WAIT_ON(ret, fm->fence_queue, 3 * DRM_HZ, - fence_signaled(dev, fence, mask, 1)); - if (time_after_eq(jiffies, _end)) - break; - } while (ret == -EINTR && ignore_signals); - if (time_after_eq(jiffies, _end) && (ret != 0)) - ret = -EBUSY; - if (ret) { - if (ret == -EBUSY) { - DRM_ERROR("Fence timeout. " - "GPU lockup or fence driver was " - "taken down.\n"); - } - return ((ret == -EINTR) ? -EAGAIN : ret); - } - } else if ((fence->class == 0) && (mask & DRM_FENCE_TYPE_EXE) && - driver->lazy_capable) { + ret = drm_fence_lazy_wait(dev, fence, ignore_signals, mask); + if (ret) + return ret; - /* - * We use IRQ wait for EXE fence if available to gain - * CPU in some cases. - */ + } else { - do { - DRM_WAIT_ON(ret, fm->fence_queue, 3 * DRM_HZ, - fence_signaled(dev, fence, - DRM_FENCE_TYPE_EXE, 1)); - if (time_after_eq(jiffies, _end)) - break; - } while (ret == -EINTR && ignore_signals); - if (time_after_eq(jiffies, _end) && (ret != 0)) - ret = -EBUSY; - if (ret) - return ((ret == -EINTR) ? -EAGAIN : ret); - } + if (driver->has_irq(dev, fence->class, + DRM_FENCE_TYPE_EXE)) { + ret = drm_fence_lazy_wait(dev, fence, ignore_signals, + DRM_FENCE_TYPE_EXE); + if (ret) + return ret; + } + if (driver->has_irq(dev, fence->class, + mask & ~DRM_FENCE_TYPE_EXE)) { + ret = drm_fence_lazy_wait(dev, fence, ignore_signals, + mask); + if (ret) + return ret; + } + } if (fence_signaled(dev, fence, mask, 0)) return 0; + DRM_ERROR("Busy wait\n"); /* * Avoid kernel-space busy-waits. */ @@ -367,7 +379,7 @@ int drm_fence_object_emit(drm_device_t * dev, drm_fence_object_t * fence, int ret; drm_fence_unring(dev, &fence->ring); - ret = driver->emit(dev, fence_flags, &sequence, &native_type); + ret = driver->emit(dev, fence->class, fence_flags, &sequence, &native_type); if (ret) return ret; diff --git a/linux-core/i915_drv.c b/linux-core/i915_drv.c index 848ffa78..b7bf883c 100644 --- a/linux-core/i915_drv.c +++ b/linux-core/i915_drv.c @@ -47,6 +47,7 @@ static drm_fence_driver_t i915_fence_driver = { .lazy_capable = 1, .emit = i915_fence_emit_sequence, .poke_flush = i915_poke_flush, + .has_irq = i915_fence_has_irq, }; #endif #ifdef I915_HAVE_BUFFER diff --git a/linux-core/i915_fence.c b/linux-core/i915_fence.c index 2182604c..fa2a3d1f 100644 --- a/linux-core/i915_fence.c +++ b/linux-core/i915_fence.c @@ -61,7 +61,7 @@ static void i915_perform_flush(drm_device_t * dev) diff = sequence - fm->last_exe_flush; if (diff < driver->wrap_diff && diff != 0) { - drm_fence_handler(dev, sequence, DRM_FENCE_TYPE_EXE); + drm_fence_handler(dev, 0, sequence, DRM_FENCE_TYPE_EXE); } diff = sequence - fm->exe_flush_sequence; @@ -84,7 +84,7 @@ static void i915_perform_flush(drm_device_t * dev) flush_flags = dev_priv->flush_flags; flush_sequence = dev_priv->flush_sequence; dev_priv->flush_pending = 0; - drm_fence_handler(dev, flush_sequence, flush_flags); + drm_fence_handler(dev, 0, flush_sequence, flush_flags); } } @@ -104,13 +104,13 @@ static void i915_perform_flush(drm_device_t * dev) flush_flags = dev_priv->flush_flags; flush_sequence = dev_priv->flush_sequence; dev_priv->flush_pending = 0; - drm_fence_handler(dev, flush_sequence, flush_flags); + drm_fence_handler(dev, 0, flush_sequence, flush_flags); } } } -void i915_poke_flush(drm_device_t * dev) +void i915_poke_flush(drm_device_t * dev, uint32_t class) { drm_fence_manager_t *fm = &dev->fm; unsigned long flags; @@ -120,7 +120,7 @@ void i915_poke_flush(drm_device_t * dev) write_unlock_irqrestore(&fm->lock, flags); } -int i915_fence_emit_sequence(drm_device_t * dev, uint32_t flags, +int i915_fence_emit_sequence(drm_device_t * dev, uint32_t class, uint32_t flags, uint32_t * sequence, uint32_t * native_type) { drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private; @@ -144,3 +144,15 @@ void i915_fence_handler(drm_device_t * dev) i915_perform_flush(dev); write_unlock(&fm->lock); } + +int i915_fence_has_irq(drm_device_t *dev, uint32_t class, uint32_t flags) +{ + /* + * We have an irq that tells us when we have a new breadcrumb. + */ + + if (class == 0 && flags == DRM_FENCE_TYPE_EXE) + return 1; + + return 0; +} |