diff options
Diffstat (limited to 'drivers/gpu/drm/msm/msm_atomic.c')
| -rw-r--r-- | drivers/gpu/drm/msm/msm_atomic.c | 62 | 
1 files changed, 44 insertions, 18 deletions
| diff --git a/drivers/gpu/drm/msm/msm_atomic.c b/drivers/gpu/drm/msm/msm_atomic.c index 561bfa48841c..6a326761dc4a 100644 --- a/drivers/gpu/drm/msm/msm_atomic.c +++ b/drivers/gpu/drm/msm/msm_atomic.c @@ -55,16 +55,32 @@ static void vblank_put(struct msm_kms *kms, unsigned crtc_mask)  	}  } +static void lock_crtcs(struct msm_kms *kms, unsigned int crtc_mask) +{ +	struct drm_crtc *crtc; + +	for_each_crtc_mask(kms->dev, crtc, crtc_mask) +		mutex_lock(&kms->commit_lock[drm_crtc_index(crtc)]); +} + +static void unlock_crtcs(struct msm_kms *kms, unsigned int crtc_mask) +{ +	struct drm_crtc *crtc; + +	for_each_crtc_mask_reverse(kms->dev, crtc, crtc_mask) +		mutex_unlock(&kms->commit_lock[drm_crtc_index(crtc)]); +} +  static void msm_atomic_async_commit(struct msm_kms *kms, int crtc_idx)  {  	unsigned crtc_mask = BIT(crtc_idx);  	trace_msm_atomic_async_commit_start(crtc_mask); -	mutex_lock(&kms->commit_lock); +	lock_crtcs(kms, crtc_mask);  	if (!(kms->pending_crtc_mask & crtc_mask)) { -		mutex_unlock(&kms->commit_lock); +		unlock_crtcs(kms, crtc_mask);  		goto out;  	} @@ -79,7 +95,6 @@ static void msm_atomic_async_commit(struct msm_kms *kms, int crtc_idx)  	 */  	trace_msm_atomic_flush_commit(crtc_mask);  	kms->funcs->flush_commit(kms, crtc_mask); -	mutex_unlock(&kms->commit_lock);  	/*  	 * Wait for flush to complete: @@ -90,9 +105,8 @@ static void msm_atomic_async_commit(struct msm_kms *kms, int crtc_idx)  	vblank_put(kms, crtc_mask); -	mutex_lock(&kms->commit_lock);  	kms->funcs->complete_commit(kms, crtc_mask); -	mutex_unlock(&kms->commit_lock); +	unlock_crtcs(kms, crtc_mask);  	kms->funcs->disable_commit(kms);  out: @@ -103,14 +117,13 @@ static enum hrtimer_restart msm_atomic_pending_timer(struct hrtimer *t)  {  	struct msm_pending_timer *timer = container_of(t,  			struct msm_pending_timer, timer); -	struct msm_drm_private *priv = timer->kms->dev->dev_private; -	queue_work(priv->wq, &timer->work); +	kthread_queue_work(timer->worker, &timer->work);  	return HRTIMER_NORESTART;  } -static void msm_atomic_pending_work(struct work_struct *work) +static void msm_atomic_pending_work(struct kthread_work *work)  {  	struct msm_pending_timer *timer = container_of(work,  			struct msm_pending_timer, work); @@ -118,14 +131,30 @@ static void msm_atomic_pending_work(struct work_struct *work)  	msm_atomic_async_commit(timer->kms, timer->crtc_idx);  } -void msm_atomic_init_pending_timer(struct msm_pending_timer *timer, +int msm_atomic_init_pending_timer(struct msm_pending_timer *timer,  		struct msm_kms *kms, int crtc_idx)  {  	timer->kms = kms;  	timer->crtc_idx = crtc_idx;  	hrtimer_init(&timer->timer, CLOCK_MONOTONIC, HRTIMER_MODE_ABS);  	timer->timer.function = msm_atomic_pending_timer; -	INIT_WORK(&timer->work, msm_atomic_pending_work); + +	timer->worker = kthread_create_worker(0, "atomic-worker-%d", crtc_idx); +	if (IS_ERR(timer->worker)) { +		int ret = PTR_ERR(timer->worker); +		timer->worker = NULL; +		return ret; +	} +	sched_set_fifo(timer->worker->task); +	kthread_init_work(&timer->work, msm_atomic_pending_work); + +	return 0; +} + +void msm_atomic_destroy_pending_timer(struct msm_pending_timer *timer) +{ +	if (timer->worker) +		kthread_destroy_worker(timer->worker);  }  static bool can_do_async(struct drm_atomic_state *state, @@ -189,12 +218,11 @@ void msm_atomic_commit_tail(struct drm_atomic_state *state)  	 * Ensure any previous (potentially async) commit has  	 * completed:  	 */ +	lock_crtcs(kms, crtc_mask);  	trace_msm_atomic_wait_flush_start(crtc_mask);  	kms->funcs->wait_flush(kms, crtc_mask);  	trace_msm_atomic_wait_flush_finish(crtc_mask); -	mutex_lock(&kms->commit_lock); -  	/*  	 * Now that there is no in-progress flush, prepare the  	 * current update: @@ -232,8 +260,7 @@ void msm_atomic_commit_tail(struct drm_atomic_state *state)  		}  		kms->funcs->disable_commit(kms); -		mutex_unlock(&kms->commit_lock); - +		unlock_crtcs(kms, crtc_mask);  		/*  		 * At this point, from drm core's perspective, we  		 * are done with the atomic update, so we can just @@ -260,8 +287,7 @@ void msm_atomic_commit_tail(struct drm_atomic_state *state)  	 */  	trace_msm_atomic_flush_commit(crtc_mask);  	kms->funcs->flush_commit(kms, crtc_mask); -	mutex_unlock(&kms->commit_lock); - +	unlock_crtcs(kms, crtc_mask);  	/*  	 * Wait for flush to complete:  	 */ @@ -271,9 +297,9 @@ void msm_atomic_commit_tail(struct drm_atomic_state *state)  	vblank_put(kms, crtc_mask); -	mutex_lock(&kms->commit_lock); +	lock_crtcs(kms, crtc_mask);  	kms->funcs->complete_commit(kms, crtc_mask); -	mutex_unlock(&kms->commit_lock); +	unlock_crtcs(kms, crtc_mask);  	kms->funcs->disable_commit(kms);  	drm_atomic_helper_commit_hw_done(state); | 
