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
* 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);
* 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;
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);
* 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;
}
}
write_unlock_irqrestore(&fm->lock, flags);
- driver->poke_flush(dev);
+ driver->poke_flush(dev, fence->class);
return 0;
}
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;
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.
*/
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 = 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;
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);
}
}
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;
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;
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;
+}