Remove an intel-specific hack and replace it with a fence driver callback.

This commit is contained in:
Thomas Hellstrom 2007-02-14 13:31:35 +01:00
parent 04760563b8
commit 5c9a7b0f94
5 changed files with 80 additions and 51 deletions

View file

@ -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);

View file

@ -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) {
/*
* We use IRQ wait for EXE fence if available to gain
* CPU in some cases.
*/
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;
ret = drm_fence_lazy_wait(dev, fence, ignore_signals, mask);
if (ret)
return ((ret == -EINTR) ? -EAGAIN : ret);
}
return ret;
} else {
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;

View file

@ -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

View file

@ -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;
}

View file

@ -178,10 +178,12 @@ extern void i915_mem_release(drm_device_t * dev,
extern void i915_fence_handler(drm_device_t *dev);
extern int i915_fence_emit_sequence(drm_device_t *dev, uint32_t flags,
extern int i915_fence_emit_sequence(drm_device_t *dev, uint32_t class,
uint32_t flags,
uint32_t *sequence,
uint32_t *native_type);
extern void i915_poke_flush(drm_device_t *dev);
extern void i915_poke_flush(drm_device_t *dev, uint32_t class);
extern int i915_fence_has_irq(drm_device_t *dev, uint32_t class, uint32_t flags);
#endif
#ifdef I915_HAVE_BUFFER