diff options
Diffstat (limited to 'drivers/gpu/drm/msm/msm_submitqueue.c')
| -rw-r--r-- | drivers/gpu/drm/msm/msm_submitqueue.c | 73 | 
1 files changed, 59 insertions, 14 deletions
| diff --git a/drivers/gpu/drm/msm/msm_submitqueue.c b/drivers/gpu/drm/msm/msm_submitqueue.c index 32a55d81b58b..7cb158bcbcf6 100644 --- a/drivers/gpu/drm/msm/msm_submitqueue.c +++ b/drivers/gpu/drm/msm/msm_submitqueue.c @@ -7,6 +7,24 @@  #include "msm_gpu.h" +void __msm_file_private_destroy(struct kref *kref) +{ +	struct msm_file_private *ctx = container_of(kref, +		struct msm_file_private, ref); +	int i; + +	for (i = 0; i < ARRAY_SIZE(ctx->entities); i++) { +		if (!ctx->entities[i]) +			continue; + +		drm_sched_entity_destroy(ctx->entities[i]); +		kfree(ctx->entities[i]); +	} + +	msm_gem_address_space_put(ctx->aspace); +	kfree(ctx); +} +  void msm_submitqueue_destroy(struct kref *kref)  {  	struct msm_gpu_submitqueue *queue = container_of(kref, @@ -14,8 +32,6 @@ void msm_submitqueue_destroy(struct kref *kref)  	idr_destroy(&queue->fence_idr); -	drm_sched_entity_destroy(&queue->entity); -  	msm_file_private_put(queue->ctx);  	kfree(queue); @@ -61,13 +77,48 @@ void msm_submitqueue_close(struct msm_file_private *ctx)  	}  } +static struct drm_sched_entity * +get_sched_entity(struct msm_file_private *ctx, struct msm_ringbuffer *ring, +		 unsigned ring_nr, enum drm_sched_priority sched_prio) +{ +	static DEFINE_MUTEX(entity_lock); +	unsigned idx = (ring_nr * NR_SCHED_PRIORITIES) + sched_prio; + +	/* We should have already validated that the requested priority is +	 * valid by the time we get here. +	 */ +	if (WARN_ON(idx >= ARRAY_SIZE(ctx->entities))) +		return ERR_PTR(-EINVAL); + +	mutex_lock(&entity_lock); + +	if (!ctx->entities[idx]) { +		struct drm_sched_entity *entity; +		struct drm_gpu_scheduler *sched = &ring->sched; +		int ret; + +		entity = kzalloc(sizeof(*ctx->entities[idx]), GFP_KERNEL); + +		ret = drm_sched_entity_init(entity, sched_prio, &sched, 1, NULL); +		if (ret) { +			mutex_unlock(&entity_lock); +			kfree(entity); +			return ERR_PTR(ret); +		} + +		ctx->entities[idx] = entity; +	} + +	mutex_unlock(&entity_lock); + +	return ctx->entities[idx]; +} +  int msm_submitqueue_create(struct drm_device *drm, struct msm_file_private *ctx,  		u32 prio, u32 flags, u32 *id)  {  	struct msm_drm_private *priv = drm->dev_private;  	struct msm_gpu_submitqueue *queue; -	struct msm_ringbuffer *ring; -	struct drm_gpu_scheduler *sched;  	enum drm_sched_priority sched_prio;  	unsigned ring_nr;  	int ret; @@ -91,12 +142,10 @@ int msm_submitqueue_create(struct drm_device *drm, struct msm_file_private *ctx,  	queue->flags = flags;  	queue->ring_nr = ring_nr; -	ring = priv->gpu->rb[ring_nr]; -	sched = &ring->sched; - -	ret = drm_sched_entity_init(&queue->entity, -			sched_prio, &sched, 1, NULL); -	if (ret) { +	queue->entity = get_sched_entity(ctx, priv->gpu->rb[ring_nr], +					 ring_nr, sched_prio); +	if (IS_ERR(queue->entity)) { +		ret = PTR_ERR(queue->entity);  		kfree(queue);  		return ret;  	} @@ -140,10 +189,6 @@ int msm_submitqueue_init(struct drm_device *drm, struct msm_file_private *ctx)  	 */  	default_prio = DIV_ROUND_UP(max_priority, 2); -	INIT_LIST_HEAD(&ctx->submitqueues); - -	rwlock_init(&ctx->queuelock); -  	return msm_submitqueue_create(drm, ctx, default_prio, 0, NULL);  } |