diff options
| author | Thomas Hellstrom <thomas-at-tungstengraphics-dot-com> | 2007-02-22 17:04:20 +0100 | 
|---|---|---|
| committer | Thomas Hellstrom <thomas-at-tungstengraphics-dot-com> | 2007-02-22 17:04:20 +0100 | 
| commit | 2b7a9afa0977d4a8b21db3d436cec66e5a45764d (patch) | |
| tree | b7df3b46a57d3e1ce66211040e318193c6fddc38 /linux-core | |
| parent | a253de2fcfa11abadd4697a9d89137adf3f35f78 (diff) | |
Some fencing cleanup.
Diffstat (limited to 'linux-core')
| -rw-r--r-- | linux-core/drm_compat.h | 7 | ||||
| -rw-r--r-- | linux-core/drm_fence.c | 75 | ||||
| -rw-r--r-- | linux-core/i915_fence.c | 18 | 
3 files changed, 57 insertions, 43 deletions
diff --git a/linux-core/drm_compat.h b/linux-core/drm_compat.h index 9692492d..7741714a 100644 --- a/linux-core/drm_compat.h +++ b/linux-core/drm_compat.h @@ -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> diff --git a/linux-core/drm_fence.c b/linux-core/drm_fence.c index 3e17a16d..6dd04a35 100644 --- a/linux-core/drm_fence.c +++ b/linux-core/drm_fence.c @@ -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;  } diff --git a/linux-core/i915_fence.c b/linux-core/i915_fence.c index 81d9b176..88daa57c 100644 --- a/linux-core/i915_fence.c +++ b/linux-core/i915_fence.c @@ -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) {  | 
