summaryrefslogtreecommitdiff
path: root/linux-core
diff options
context:
space:
mode:
Diffstat (limited to 'linux-core')
-rw-r--r--linux-core/drmP.h8
-rw-r--r--linux-core/drm_fence.c92
-rw-r--r--linux-core/i915_drv.c1
-rw-r--r--linux-core/i915_fence.c22
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;
+}