diff options
Diffstat (limited to 'linux-core')
| -rw-r--r-- | linux-core/drmP.h | 8 | ||||
| -rw-r--r-- | linux-core/drm_fence.c | 92 | ||||
| -rw-r--r-- | linux-core/i915_drv.c | 1 | ||||
| -rw-r--r-- | linux-core/i915_fence.c | 22 | 
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; +} | 
