Some fencing cleanup.

main
Thomas Hellstrom 2007-02-22 17:04:20 +01:00
parent a253de2fcf
commit 2b7a9afa09
3 changed files with 57 additions and 43 deletions

View File

@ -152,6 +152,13 @@ static __inline__ void *kcalloc(size_t nmemb, size_t size, int flags)
(tmp);})
#endif
#ifndef list_for_each_entry_safe_reverse
#define list_for_each_entry_safe_reverse(pos, n, head, member) \
for (pos = list_entry((head)->prev, typeof(*pos), member), \
n = list_entry(pos->member.prev, typeof(*pos), member); \
&pos->member != (head); \
pos = n, n = list_entry(n->member.prev, typeof(*n), member))
#endif
#include <linux/mm.h>
#include <asm/page.h>

View File

@ -43,10 +43,29 @@ void drm_fence_handler(drm_device_t * dev, uint32_t class,
drm_fence_manager_t *fm = &dev->fm;
drm_fence_class_manager_t *fc = &fm->class[class];
drm_fence_driver_t *driver = dev->driver->fence_driver;
struct list_head *list, *prev;
drm_fence_object_t *fence;
struct list_head *head;
drm_fence_object_t *fence, *next;
int found = 0;
int is_exe = (type & DRM_FENCE_TYPE_EXE);
int ge_last_exe;
diff = (sequence - fc->exe_flush_sequence) & driver->sequence_mask;
if (fc->pending_exe_flush && is_exe && diff < driver->wrap_diff)
fc->pending_exe_flush = 0;
diff = (sequence - fc->last_exe_flush) & driver->sequence_mask;
ge_last_exe = diff < driver->wrap_diff;
if (ge_last_exe)
fc->pending_flush &= ~type;
if (is_exe && ge_last_exe) {
fc->last_exe_flush = sequence;
}
if (list_empty(&fc->ring))
return;
@ -58,11 +77,11 @@ void drm_fence_handler(drm_device_t * dev, uint32_t class,
}
}
list = (found) ? fence->ring.prev : fc->ring.prev;
prev = list->prev;
head = (found) ? &fence->ring : &fc->ring;
for (; list != &fc->ring; list = prev, prev = list->prev) {
fence = list_entry(list, drm_fence_object_t, ring);
list_for_each_entry_safe_reverse(fence, next, head, ring) {
if (&fence->ring == &fc->ring)
break;
type |= fence->native_type;
relevant = type & fence->type;
@ -90,12 +109,7 @@ void drm_fence_handler(drm_device_t * dev, uint32_t class,
}
}
fc->pending_flush &= ~type;
if (fc->pending_exe_flush && (type & DRM_FENCE_TYPE_EXE) &&
((sequence - fc->exe_flush_sequence) < driver->wrap_diff))
fc->pending_exe_flush = 0;
if (wake) {
DRM_WAKEUP(&fc->fence_queue);
}
@ -178,24 +192,6 @@ static void drm_fence_flush_exe(drm_fence_class_manager_t * fc,
uint32_t diff;
if (!fc->pending_exe_flush) {
struct list_head *list;
/*
* Last_exe_flush is invalid. Find oldest sequence.
*/
list = &fc->ring;
if (list_empty(list)) {
return;
} else {
drm_fence_object_t *fence =
list_entry(list->next, drm_fence_object_t, ring);
fc->last_exe_flush = (fence->sequence - 1) &
driver->sequence_mask;
}
diff = (sequence - fc->last_exe_flush) & driver->sequence_mask;
if (diff >= driver->wrap_diff)
return;
fc->exe_flush_sequence = sequence;
fc->pending_exe_flush = 1;
} else {
@ -261,14 +257,24 @@ void drm_fence_flush_old(drm_device_t * dev, uint32_t class, uint32_t sequence)
drm_fence_object_t *fence;
uint32_t diff;
write_lock_irqsave(&fm->lock, flags);
old_sequence = (sequence - driver->flush_diff) & driver->sequence_mask;
diff = (old_sequence - fc->last_exe_flush) & driver->sequence_mask;
if ((diff < driver->wrap_diff) && !fc->pending_exe_flush) {
fc->pending_exe_flush = 1;
fc->exe_flush_sequence = sequence - (driver->flush_diff / 2);
}
write_unlock_irqrestore(&fm->lock, flags);
mutex_lock(&dev->struct_mutex);
read_lock_irqsave(&fm->lock, flags);
if (fc->ring.next == &fc->ring) {
if (list_empty(&fc->ring)) {
read_unlock_irqrestore(&fm->lock, flags);
mutex_unlock(&dev->struct_mutex);
return;
}
old_sequence = (sequence - driver->flush_diff) & driver->sequence_mask;
fence = list_entry(fc->ring.next, drm_fence_object_t, ring);
atomic_inc(&fence->usage);
mutex_unlock(&dev->struct_mutex);
@ -384,6 +390,7 @@ int drm_fence_object_emit(drm_device_t * dev, drm_fence_object_t * fence,
{
drm_fence_manager_t *fm = &dev->fm;
drm_fence_driver_t *driver = dev->driver->fence_driver;
drm_fence_class_manager_t *fc = &fm->class[fence->class];
unsigned long flags;
uint32_t sequence;
uint32_t native_type;
@ -402,7 +409,9 @@ int drm_fence_object_emit(drm_device_t * dev, drm_fence_object_t * fence,
fence->signaled = 0x00;
fence->sequence = sequence;
fence->native_type = native_type;
list_add_tail(&fence->ring, &fm->class[class].ring);
if (list_empty(&fc->ring))
fc->last_exe_flush = sequence - 1;
list_add_tail(&fence->ring, &fc->ring);
write_unlock_irqrestore(&fm->lock, flags);
return 0;
}

View File

@ -49,6 +49,7 @@ static void i915_perform_flush(drm_device_t * dev)
uint32_t i_status;
uint32_t diff;
uint32_t sequence;
int rwflush;
if (!dev_priv)
return;
@ -65,14 +66,10 @@ static void i915_perform_flush(drm_device_t * dev)
drm_fence_handler(dev, 0, sequence, DRM_FENCE_TYPE_EXE);
}
diff = sequence - fc->exe_flush_sequence;
if (diff < driver->wrap_diff) {
fc->pending_exe_flush = 0;
if (dev_priv->fence_irq_on) {
i915_user_irq_off(dev_priv);
dev_priv->fence_irq_on = 0;
}
} else if (!dev_priv->fence_irq_on) {
if (dev_priv->fence_irq_on && !fc->pending_exe_flush) {
i915_user_irq_off(dev_priv);
dev_priv->fence_irq_on = 0;
} else if (!dev_priv->fence_irq_on && fc->pending_exe_flush) {
i915_user_irq_on(dev_priv);
dev_priv->fence_irq_on = 1;
}
@ -89,13 +86,14 @@ static void i915_perform_flush(drm_device_t * dev)
}
}
if (fc->pending_flush && !dev_priv->flush_pending) {
rwflush = fc->pending_flush & DRM_I915_FENCE_TYPE_RW;
if (rwflush && !dev_priv->flush_pending) {
dev_priv->flush_sequence = (uint32_t) READ_BREADCRUMB(dev_priv);
dev_priv->flush_flags = fc->pending_flush;
dev_priv->saved_flush_status = READ_HWSP(dev_priv, 0);
I915_WRITE(I915REG_INSTPM, (1 << 5) | (1 << 21));
dev_priv->flush_pending = 1;
fc->pending_flush = 0;
fc->pending_flush &= ~DRM_I915_FENCE_TYPE_RW;
}
if (dev_priv->flush_pending) {