diff options
Diffstat (limited to 'linux-core')
| -rw-r--r-- | linux-core/drm_drv.c | 13 | ||||
| -rw-r--r-- | linux-core/drm_fence.c | 310 | ||||
| -rw-r--r-- | linux-core/drm_objects.h | 10 | 
3 files changed, 331 insertions, 2 deletions
| diff --git a/linux-core/drm_drv.c b/linux-core/drm_drv.c index 55a3435b..6b98f2c1 100644 --- a/linux-core/drm_drv.c +++ b/linux-core/drm_drv.c @@ -117,7 +117,7 @@ static drm_ioctl_desc_t drm_ioctls[] = {  	[DRM_IOCTL_NR(DRM_IOCTL_SG_FREE)] = {drm_sg_free, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY},  	[DRM_IOCTL_NR(DRM_IOCTL_WAIT_VBLANK)] = {drm_wait_vblank, 0}, -	[DRM_IOCTL_NR(DRM_IOCTL_FENCE)] = {drm_fence_ioctl, DRM_AUTH}, +  	[DRM_IOCTL_NR(DRM_IOCTL_BUFOBJ)] = {drm_bo_ioctl, DRM_AUTH},  	[DRM_IOCTL_NR(DRM_IOCTL_UPDATE_DRAW)] = {drm_update_drawable_info, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY}, @@ -131,6 +131,17 @@ static drm_ioctl_desc_t drm_ioctls[] = {  					     DRM_AUTH },  	[DRM_IOCTL_NR(DRM_IOCTL_MM_UNLOCK)] = {drm_mm_unlock_ioctl,   					     DRM_AUTH }, + +	[DRM_IOCTL_NR(DRM_IOCTL_FENCE_CREATE)] = {drm_fence_create_ioctl, DRM_AUTH}, +	[DRM_IOCTL_NR(DRM_IOCTL_FENCE_DESTROY)] = {drm_fence_destroy_ioctl, DRM_AUTH}, +	[DRM_IOCTL_NR(DRM_IOCTL_FENCE_REFERENCE)] = {drm_fence_reference_ioctl, DRM_AUTH}, +	[DRM_IOCTL_NR(DRM_IOCTL_FENCE_UNREFERENCE)] = {drm_fence_unreference_ioctl, DRM_AUTH}, +	[DRM_IOCTL_NR(DRM_IOCTL_FENCE_SIGNALED)] = {drm_fence_signaled_ioctl, DRM_AUTH}, +	[DRM_IOCTL_NR(DRM_IOCTL_FENCE_FLUSH)] = {drm_fence_flush_ioctl, DRM_AUTH}, +	[DRM_IOCTL_NR(DRM_IOCTL_FENCE_WAIT)] = {drm_fence_wait_ioctl, DRM_AUTH}, +	[DRM_IOCTL_NR(DRM_IOCTL_FENCE_EMIT)] = {drm_fence_emit_ioctl, DRM_AUTH}, +	[DRM_IOCTL_NR(DRM_IOCTL_FENCE_BUFFERS)] = {drm_fence_buffers_ioctl, DRM_AUTH}, +  };  #define DRM_CORE_IOCTL_COUNT	ARRAY_SIZE( drm_ioctls ) diff --git a/linux-core/drm_fence.c b/linux-core/drm_fence.c index ce161dc3..fe11e87b 100644 --- a/linux-core/drm_fence.c +++ b/linux-core/drm_fence.c @@ -659,3 +659,313 @@ int drm_fence_ioctl(DRM_IOCTL_ARGS)  	DRM_COPY_TO_USER_IOCTL((void __user *)data, arg, sizeof(arg));  	return ret;  } + +int drm_fence_create_ioctl(DRM_IOCTL_ARGS) +{ +	DRM_DEVICE; +	int ret; +	drm_fence_manager_t *fm = &dev->fm; +	drm_fence_arg_t arg; +	drm_fence_object_t *fence; +	unsigned long flags; +	ret = 0; + +	if (!fm->initialized) { +		DRM_ERROR("The DRM driver does not support fencing.\n"); +		return -EINVAL; +	} + +	DRM_COPY_FROM_USER_IOCTL(arg, (void __user *)data, sizeof(arg)); + +	if (arg.flags & DRM_FENCE_FLAG_EMIT) +		LOCK_TEST_WITH_RETURN(dev, filp); +	ret = drm_fence_object_create(dev, arg.class, +				      arg.type, arg.flags, &fence); +	if (ret) +		return ret; +	ret = drm_fence_add_user_object(priv, fence, +					arg.flags & +					DRM_FENCE_FLAG_SHAREABLE); +	if (ret) { +		drm_fence_usage_deref_unlocked(dev, fence); +		return ret; +	} +	 +	/* +	 * usage > 0. No need to lock dev->struct_mutex; +	 */ +	 +	atomic_inc(&fence->usage); +	arg.handle = fence->base.hash.key; + +	read_lock_irqsave(&fm->lock, flags); +	arg.class = fence->class; +	arg.type = fence->type; +	arg.signaled = fence->signaled; +	read_unlock_irqrestore(&fm->lock, flags); +	drm_fence_usage_deref_unlocked(dev, fence); + +	DRM_COPY_TO_USER_IOCTL((void __user *)data, arg, sizeof(arg)); +	return ret; +} + +int drm_fence_destroy_ioctl(DRM_IOCTL_ARGS) +{ +	DRM_DEVICE; +	int ret; +	drm_fence_manager_t *fm = &dev->fm; +	drm_fence_arg_t arg; +	drm_user_object_t *uo; +	ret = 0; + +	if (!fm->initialized) { +		DRM_ERROR("The DRM driver does not support fencing.\n"); +		return -EINVAL; +	} + +	DRM_COPY_FROM_USER_IOCTL(arg, (void __user *)data, sizeof(arg)); + +	mutex_lock(&dev->struct_mutex); +	uo = drm_lookup_user_object(priv, arg.handle); +	if (!uo || (uo->type != drm_fence_type) || uo->owner != priv) { +		mutex_unlock(&dev->struct_mutex); +		return -EINVAL; +	} +	ret = drm_remove_user_object(priv, uo); +	mutex_unlock(&dev->struct_mutex); +	return ret; +} + + +int drm_fence_reference_ioctl(DRM_IOCTL_ARGS) +{ +	DRM_DEVICE; +	int ret; +	drm_fence_manager_t *fm = &dev->fm; +	drm_fence_arg_t arg; +	drm_fence_object_t *fence; +	drm_user_object_t *uo; +	unsigned long flags; +	ret = 0; + +	if (!fm->initialized) { +		DRM_ERROR("The DRM driver does not support fencing.\n"); +		return -EINVAL; +	} + +	DRM_COPY_FROM_USER_IOCTL(arg, (void __user *)data, sizeof(arg)); +	ret = drm_user_object_ref(priv, arg.handle, drm_fence_type, &uo); +	if (ret) +		return ret; +	fence = drm_lookup_fence_object(priv, arg.handle); + +	read_lock_irqsave(&fm->lock, flags); +	arg.class = fence->class; +	arg.type = fence->type; +	arg.signaled = fence->signaled; +	read_unlock_irqrestore(&fm->lock, flags); +	drm_fence_usage_deref_unlocked(dev, fence); + +	DRM_COPY_TO_USER_IOCTL((void __user *)data, arg, sizeof(arg)); +	return ret; +} + + +int drm_fence_unreference_ioctl(DRM_IOCTL_ARGS) +{ +	DRM_DEVICE; +	int ret; +	drm_fence_manager_t *fm = &dev->fm; +	drm_fence_arg_t arg; +	ret = 0; + +	if (!fm->initialized) { +		DRM_ERROR("The DRM driver does not support fencing.\n"); +		return -EINVAL; +	} + +	DRM_COPY_FROM_USER_IOCTL(arg, (void __user *)data, sizeof(arg)); +	return drm_user_object_unref(priv, arg.handle, drm_fence_type); +} + +int drm_fence_signaled_ioctl(DRM_IOCTL_ARGS) +{ +	DRM_DEVICE; +	int ret; +	drm_fence_manager_t *fm = &dev->fm; +	drm_fence_arg_t arg; +	drm_fence_object_t *fence; +	unsigned long flags; +	ret = 0; + +	if (!fm->initialized) { +		DRM_ERROR("The DRM driver does not support fencing.\n"); +		return -EINVAL; +	} + +	DRM_COPY_FROM_USER_IOCTL(arg, (void __user *)data, sizeof(arg)); + +	fence = drm_lookup_fence_object(priv, arg.handle); +	if (!fence) +		return -EINVAL; + +	read_lock_irqsave(&fm->lock, flags); +	arg.class = fence->class; +	arg.type = fence->type; +	arg.signaled = fence->signaled; +	read_unlock_irqrestore(&fm->lock, flags); +	drm_fence_usage_deref_unlocked(dev, fence); + +	DRM_COPY_TO_USER_IOCTL((void __user *)data, arg, sizeof(arg)); +	return ret; +} + +int drm_fence_flush_ioctl(DRM_IOCTL_ARGS) +{ +	DRM_DEVICE; +	int ret; +	drm_fence_manager_t *fm = &dev->fm; +	drm_fence_arg_t arg; +	drm_fence_object_t *fence; +	unsigned long flags; +	ret = 0; + +	if (!fm->initialized) { +		DRM_ERROR("The DRM driver does not support fencing.\n"); +		return -EINVAL; +	} + +	DRM_COPY_FROM_USER_IOCTL(arg, (void __user *)data, sizeof(arg)); + +	fence = drm_lookup_fence_object(priv, arg.handle); +	if (!fence) +		return -EINVAL; +	ret = drm_fence_object_flush(dev, fence, arg.type); + +	read_lock_irqsave(&fm->lock, flags); +	arg.class = fence->class; +	arg.type = fence->type; +	arg.signaled = fence->signaled; +	read_unlock_irqrestore(&fm->lock, flags); +	drm_fence_usage_deref_unlocked(dev, fence); + +	DRM_COPY_TO_USER_IOCTL((void __user *)data, arg, sizeof(arg)); +	return ret; +} + + +int drm_fence_wait_ioctl(DRM_IOCTL_ARGS) +{ +	DRM_DEVICE; +	int ret; +	drm_fence_manager_t *fm = &dev->fm; +	drm_fence_arg_t arg; +	drm_fence_object_t *fence; +	unsigned long flags; +	ret = 0; + +	if (!fm->initialized) { +		DRM_ERROR("The DRM driver does not support fencing.\n"); +		return -EINVAL; +	} + +	DRM_COPY_FROM_USER_IOCTL(arg, (void __user *)data, sizeof(arg)); + +	fence = drm_lookup_fence_object(priv, arg.handle); +	if (!fence) +		return -EINVAL; +	ret = drm_fence_object_wait(dev, fence, +				    arg.flags & DRM_FENCE_FLAG_WAIT_LAZY, +				    0, arg.type); + +	read_lock_irqsave(&fm->lock, flags); +	arg.class = fence->class; +	arg.type = fence->type; +	arg.signaled = fence->signaled; +	read_unlock_irqrestore(&fm->lock, flags); +	drm_fence_usage_deref_unlocked(dev, fence); + +	DRM_COPY_TO_USER_IOCTL((void __user *)data, arg, sizeof(arg)); +	return ret; +} + + +int drm_fence_emit_ioctl(DRM_IOCTL_ARGS) +{ +	DRM_DEVICE; +	int ret; +	drm_fence_manager_t *fm = &dev->fm; +	drm_fence_arg_t arg; +	drm_fence_object_t *fence; +	unsigned long flags; +	ret = 0; + +	if (!fm->initialized) { +		DRM_ERROR("The DRM driver does not support fencing.\n"); +		return -EINVAL; +	} + +	DRM_COPY_FROM_USER_IOCTL(arg, (void __user *)data, sizeof(arg)); + +	LOCK_TEST_WITH_RETURN(dev, filp); +	fence = drm_lookup_fence_object(priv, arg.handle); +	if (!fence) +		return -EINVAL; +	ret = drm_fence_object_emit(dev, fence, arg.flags, arg.class, +				    arg.type); + +	read_lock_irqsave(&fm->lock, flags); +	arg.class = fence->class; +	arg.type = fence->type; +	arg.signaled = fence->signaled; +	read_unlock_irqrestore(&fm->lock, flags); +	drm_fence_usage_deref_unlocked(dev, fence); + +	DRM_COPY_TO_USER_IOCTL((void __user *)data, arg, sizeof(arg)); +	return ret; +} + +int drm_fence_buffers_ioctl(DRM_IOCTL_ARGS) +{ +	DRM_DEVICE; +	int ret; +	drm_fence_manager_t *fm = &dev->fm; +	drm_fence_arg_t arg; +	drm_fence_object_t *fence; +	unsigned long flags; +	ret = 0; + +	if (!fm->initialized) { +		DRM_ERROR("The DRM driver does not support fencing.\n"); +		return -EINVAL; +	} + +	DRM_COPY_FROM_USER_IOCTL(arg, (void __user *)data, sizeof(arg)); + +	if (!dev->bm.initialized) { +		DRM_ERROR("Buffer object manager is not initialized\n"); +		return -EINVAL; +	} +	LOCK_TEST_WITH_RETURN(dev, filp); +	ret = drm_fence_buffer_objects(priv, NULL, arg.flags, +				       NULL, &fence); +	if (ret) +		return ret; +	ret = drm_fence_add_user_object(priv, fence, +					arg.flags & +					DRM_FENCE_FLAG_SHAREABLE); +	if (ret) +		return ret; +	atomic_inc(&fence->usage); +	arg.handle = fence->base.hash.key; + +	read_lock_irqsave(&fm->lock, flags); +	arg.class = fence->class; +	arg.type = fence->type; +	arg.signaled = fence->signaled; +	read_unlock_irqrestore(&fm->lock, flags); +	drm_fence_usage_deref_unlocked(dev, fence); + +	DRM_COPY_TO_USER_IOCTL((void __user *)data, arg, sizeof(arg)); +	return ret; +} diff --git a/linux-core/drm_objects.h b/linux-core/drm_objects.h index e05b46cc..17338da5 100644 --- a/linux-core/drm_objects.h +++ b/linux-core/drm_objects.h @@ -211,8 +211,16 @@ extern int drm_fence_object_create(struct drm_device *dev, uint32_t type,  				   drm_fence_object_t ** c_fence);  extern int drm_fence_add_user_object(drm_file_t * priv,  				     drm_fence_object_t * fence, int shareable); -extern int drm_fence_ioctl(DRM_IOCTL_ARGS); +extern int drm_fence_create_ioctl(DRM_IOCTL_ARGS); +extern int drm_fence_destroy_ioctl(DRM_IOCTL_ARGS); +extern int drm_fence_reference_ioctl(DRM_IOCTL_ARGS); +extern int drm_fence_unreference_ioctl(DRM_IOCTL_ARGS); +extern int drm_fence_signaled_ioctl(DRM_IOCTL_ARGS); +extern int drm_fence_flush_ioctl(DRM_IOCTL_ARGS); +extern int drm_fence_wait_ioctl(DRM_IOCTL_ARGS); +extern int drm_fence_emit_ioctl(DRM_IOCTL_ARGS); +extern int drm_fence_buffers_ioctl(DRM_IOCTL_ARGS);  /**************************************************   *TTMs   */ | 
