[PATCH 5/5] drm/amd/display: Make DMUB auto-load failures fatal

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Realistically when these happen the driver is in a pretty bad state.
Future calls later in the driver such as dm_read_reg_func() can hang
causing soft lockups on CPUs and never letting the module load
finish.

If one of these problems happens abort the hw init or resume sequence.

Signed-off-by: Mario Limonciello <mario.limonciello@xxxxxxx>
---
 .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 41 ++++++++++++-------
 1 file changed, 27 insertions(+), 14 deletions(-)

diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
index 95807d035a153..e7ebc26070d6b 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
@@ -1291,8 +1291,10 @@ static int dm_dmub_hw_init(struct amdgpu_device *adev)
 
 	/* Wait for firmware load to finish. */
 	status = dmub_srv_wait_for_auto_load(dmub_srv, 100000);
-	if (status != DMUB_STATUS_OK)
-		DRM_WARN("Wait for DMUB auto-load failed: %d\n", status);
+	if (status != DMUB_STATUS_OK) {
+		drm_err(adev->dm.ddev, "Wait for DMUB auto-load failed: %d\n", status);
+		return -EINVAL;
+	}
 
 	/* Init DMCU and ABM if available. */
 	if (dmcu && abm) {
@@ -1336,7 +1338,7 @@ static int dm_dmub_hw_init(struct amdgpu_device *adev)
 	return 0;
 }
 
-static void dm_dmub_hw_resume(struct amdgpu_device *adev)
+static int dm_dmub_hw_resume(struct amdgpu_device *adev)
 {
 	struct dmub_srv *dmub_srv = adev->dm.dmub_srv;
 	enum dmub_status status;
@@ -1345,24 +1347,30 @@ static void dm_dmub_hw_resume(struct amdgpu_device *adev)
 
 	if (!dmub_srv) {
 		/* DMUB isn't supported on the ASIC. */
-		return;
+		return 0;
 	}
 
 	status = dmub_srv_is_hw_init(dmub_srv, &init);
 	if (status != DMUB_STATUS_OK)
-		DRM_WARN("DMUB hardware init check failed: %d\n", status);
+		drm_warn(adev->dm.ddev, "DMUB hardware init check failed: %d\n", status);
 
 	if (status == DMUB_STATUS_OK && init) {
 		/* Wait for firmware load to finish. */
 		status = dmub_srv_wait_for_auto_load(dmub_srv, 100000);
-		if (status != DMUB_STATUS_OK)
-			DRM_WARN("Wait for DMUB auto-load failed: %d\n", status);
-	} else {
-		/* Perform the full hardware initialization. */
-		r = dm_dmub_hw_init(adev);
-		if (r)
-			DRM_ERROR("DMUB interface failed to initialize: status=%d\n", r);
+		if (status != DMUB_STATUS_OK) {
+			drm_err(adev->dm.ddev, "Wait for DMUB auto-load failed: %d\n", status);
+			return -EINVAL;
+		}
+
+		return 0;
 	}
+
+	/* Perform the full hardware initialization. */
+	r = dm_dmub_hw_init(adev);
+	if (r)
+		drm_err(adev->dm.ddev, "DMUB interface failed to initialize: status=%d\n", r);
+
+	return r;
 }
 
 static void mmhub_read_system_context(struct amdgpu_device *adev, struct dc_phy_addr_space_config *pa_config)
@@ -3244,9 +3252,12 @@ static int dm_resume(struct amdgpu_ip_block *ip_block)
 		link_enc_cfg_copy(adev->dm.dc->current_state, dc_state);
 
 		r = dm_dmub_hw_init(adev);
-		if (r)
+
+		if (r) {
 			drm_err(adev->dm.ddev,
 				"DMUB interface failed to initialize: status=%d\n", r);
+			return r;
+		}
 
 		dc_dmub_srv_set_power_state(dm->dc->ctx->dmub_srv, DC_ACPI_CM_POWER_STATE_D0);
 		dc_set_power_state(dm->dc, DC_ACPI_CM_POWER_STATE_D0);
@@ -3292,7 +3303,9 @@ static int dm_resume(struct amdgpu_ip_block *ip_block)
 	/* TODO: Remove dc_state->dccg, use dc->dccg directly. */
 
 	/* Before powering on DC we need to re-initialize DMUB. */
-	dm_dmub_hw_resume(adev);
+	r = dm_dmub_hw_resume(adev);
+	if (r)
+		return r;
 
 	/* Re-enable outbox interrupts for DPIA. */
 	if (dc_is_dmub_outbox_supported(adev->dm.dc)) {
-- 
2.43.0




[Index of Archives]     [Linux USB Devel]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]

  Powered by Linux