Browse Source

disp: msm: sde: avoid race condition at vm release

This change acquires the vm lock before pre-releasing the
dependent drivers. This avoids any race condition on any
parallel async commands transfers scheduled on connector
drivers. Additionally the main irq line is only disabled
after the pre-release to allow any ongoing transfers
to complete.

Change-Id: Ic0bffc93ebb1b69fbd8d1f096b320a86ad84c857
Signed-off-by: Abhijit Kulkarni <[email protected]>
Abhijit Kulkarni 3 years ago
parent
commit
fb15930280
1 changed files with 10 additions and 6 deletions
  1. 10 6
      msm/sde/sde_kms.c

+ 10 - 6
msm/sde/sde_kms.c

@@ -1,4 +1,5 @@
 /*
 /*
+ * Copyright (c) 2021 Qualcomm Innovation Center, Inc. All rights reserved.
  * Copyright (c) 2014-2021, The Linux Foundation. All rights reserved.
  * Copyright (c) 2014-2021, The Linux Foundation. All rights reserved.
  * Copyright (C) 2013 Red Hat
  * Copyright (C) 2013 Red Hat
  * Author: Rob Clark <[email protected]>
  * Author: Rob Clark <[email protected]>
@@ -1340,9 +1341,11 @@ int sde_kms_vm_pre_release(struct sde_kms *sde_kms,
 	/* if vm_req is enabled, once CRTC on the commit is guaranteed */
 	/* if vm_req is enabled, once CRTC on the commit is guaranteed */
 	sde_kms_wait_for_frame_transfer_complete(&sde_kms->base, crtc);
 	sde_kms_wait_for_frame_transfer_complete(&sde_kms->base, crtc);
 
 
+	sde_dbg_set_hw_ownership_status(false);
+
 	sde_kms_cancel_delayed_work(crtc);
 	sde_kms_cancel_delayed_work(crtc);
 
 
-	/* disable SDE irq's */
+	/* disable SDE encoder irq's */
 	drm_for_each_encoder_mask(encoder, crtc->dev,
 	drm_for_each_encoder_mask(encoder, crtc->dev,
 					crtc->state->encoder_mask) {
 					crtc->state->encoder_mask) {
 		if (sde_encoder_in_clone_mode(encoder))
 		if (sde_encoder_in_clone_mode(encoder))
@@ -1352,8 +1355,6 @@ int sde_kms_vm_pre_release(struct sde_kms *sde_kms,
 	}
 	}
 
 
 	if (is_primary) {
 	if (is_primary) {
-		/* disable IRQ line */
-		sde_irq_update(&sde_kms->base, false);
 
 
 		/* disable vblank events */
 		/* disable vblank events */
 		drm_crtc_vblank_off(crtc);
 		drm_crtc_vblank_off(crtc);
@@ -1362,8 +1363,6 @@ int sde_kms_vm_pre_release(struct sde_kms *sde_kms,
 		sde_crtc_reset_sw_state(crtc);
 		sde_crtc_reset_sw_state(crtc);
 	}
 	}
 
 
-	sde_dbg_set_hw_ownership_status(false);
-
 	return rc;
 	return rc;
 }
 }
 
 
@@ -1447,17 +1446,22 @@ int sde_kms_vm_primary_post_commit(struct sde_kms *sde_kms,
 	/* properly handoff color processing features */
 	/* properly handoff color processing features */
 	sde_cp_crtc_vm_primary_handoff(crtc);
 	sde_cp_crtc_vm_primary_handoff(crtc);
 
 
+	sde_vm_lock(sde_kms);
+
 	/* handle non-SDE clients pre-release */
 	/* handle non-SDE clients pre-release */
 	if (vm_ops->vm_client_pre_release) {
 	if (vm_ops->vm_client_pre_release) {
 		rc = vm_ops->vm_client_pre_release(sde_kms);
 		rc = vm_ops->vm_client_pre_release(sde_kms);
 		if (rc) {
 		if (rc) {
 			SDE_ERROR("sde vm client pre_release failed, rc=%d\n",
 			SDE_ERROR("sde vm client pre_release failed, rc=%d\n",
 					rc);
 					rc);
+			sde_vm_unlock(sde_kms);
 			goto exit;
 			goto exit;
 		}
 		}
 	}
 	}
 
 
-	sde_vm_lock(sde_kms);
+	/* disable IRQ line */
+	sde_irq_update(&sde_kms->base, false);
+
 	/* release HW */
 	/* release HW */
 	if (vm_ops->vm_release) {
 	if (vm_ops->vm_release) {
 		rc = vm_ops->vm_release(sde_kms);
 		rc = vm_ops->vm_release(sde_kms);