Quoting Kuogee Hsieh (2020-10-02 15:09:19)
Connection state is set incorrectly happen at either failure of link
train
or cable plugged in while suspended. This patch fixes these problems.
This patch also replace ST_SUSPEND_PENDING with ST_DISPLAY_OFF.
Signed-off-by: Kuogee Hsieh <khsieh@xxxxxxxxxxxxxx>
Any Fixes: tag?
---
drivers/gpu/drm/msm/dp/dp_display.c | 52
++++++++++++++---------------
drivers/gpu/drm/msm/dp/dp_panel.c | 5 +++
2 files changed, 31 insertions(+), 26 deletions(-)
diff --git a/drivers/gpu/drm/msm/dp/dp_display.c
b/drivers/gpu/drm/msm/dp/dp_display.c
index 431dff9de797..898c6cc1643a 100644
--- a/drivers/gpu/drm/msm/dp/dp_display.c
+++ b/drivers/gpu/drm/msm/dp/dp_display.c
@@ -340,8 +340,6 @@ static int dp_display_process_hpd_high(struct
dp_display_private *dp)
}
dp_add_event(dp, EV_USER_NOTIFICATION, true, 0);
-
-
end:
return rc;
}
Not sure we need this hunk
@@ -1186,19 +1180,19 @@ static int dp_pm_resume(struct device *dev)
dp = container_of(dp_display, struct dp_display_private,
dp_display);
+ /* start from dis connection state */
disconnection? Or disconnected state?
+ atomic_set(&dp->hpd_state, ST_DISCONNECTED);
+
dp_display_host_init(dp);
dp_catalog_ctrl_hpd_config(dp->catalog);
status = dp_catalog_hpd_get_state_status(dp->catalog);
- if (status) {
+ if (status)
dp->dp_display.is_connected = true;
- } else {
+ else
dp->dp_display.is_connected = false;
- /* make sure next resume host_init be called */
- dp->core_initialized = false;
- }
return 0;
}
@@ -1214,6 +1208,9 @@ static int dp_pm_suspend(struct device *dev)
if (dp_display->power_on == true)
dp_display_disable(dp, 0);
+ /* host_init will be called at pm_resume */
+ dp->core_initialized = false;
+
atomic_set(&dp->hpd_state, ST_SUSPENDED);
return 0;
@@ -1343,6 +1340,9 @@ int msm_dp_display_enable(struct msm_dp *dp,
struct drm_encoder *encoder)
mutex_lock(&dp_display->event_mutex);
+ /* delete sentinel checking */
Stop sentinel checking?
+ dp_del_event(dp_display, EV_CONNECT_PENDING_TIMEOUT);
+
rc = dp_display_set_mode(dp, &dp_display->dp_mode);
if (rc) {
DRM_ERROR("Failed to perform a mode set, rc=%d\n",
rc);
@@ -1368,9 +1368,8 @@ int msm_dp_display_enable(struct msm_dp *dp,
struct drm_encoder *encoder)
dp_display_unprepare(dp);
}
- dp_del_event(dp_display, EV_CONNECT_PENDING_TIMEOUT);
-
- if (state == ST_SUSPEND_PENDING)
+ /* manual kick off plug event to train link */
+ if (state == ST_DISPLAY_OFF)
dp_add_event(dp_display, EV_IRQ_HPD_INT, 0, 0);
/* completed connection */
@@ -1402,20 +1401,21 @@ int msm_dp_display_disable(struct msm_dp *dp,
struct drm_encoder *encoder)
mutex_lock(&dp_display->event_mutex);
+ /* delete sentinel checking */
Stop sentinel checking?
+ dp_del_event(dp_display, EV_DISCONNECT_PENDING_TIMEOUT);
+
dp_display_disable(dp_display, 0);
rc = dp_display_unprepare(dp);
if (rc)
DRM_ERROR("DP display unprepare failed, rc=%d\n", rc);
- dp_del_event(dp_display, EV_DISCONNECT_PENDING_TIMEOUT);
-
state = atomic_read(&dp_display->hpd_state);
if (state == ST_DISCONNECT_PENDING) {
I don't understand the atomic nature of this hpd_state variable. Why is
it an atomic variable? Is taking a spinlock bad? What is to prevent the
atomic read here to not be interrupted and then this if condition check
be invalid because the variable has been updated somewhere else?