drm/msm/dp: validate audio ops in cable disconnect path

There is possiblity for accessing invalid audio ops when
hpd unplug is processed in between dp_display_enable
and dp_display_post_enable functions. This change adds
the validation for audio ops before accessing them and
clears audio_supported variable after processing
dp_audio_off functionality to initialize the variable to
correct state.

CRs-Fixed: 2243808
Change-Id: I103329ec5a922e5a16ce45388b3c09165b97b757
Signed-off-by: Govinda Rajulu Chenna <gchenna@codeaurora.org>
tirimbino
Govinda Rajulu Chenna 7 years ago
parent 7c90861d7f
commit 951f1eabd3
  1. 29
      drivers/gpu/drm/msm/dp/dp_audio.c
  2. 9
      drivers/gpu/drm/msm/dp/dp_display.c

@ -669,6 +669,9 @@ static int dp_audio_notify(struct dp_audio_private *audio, u32 state)
int rc = 0;
struct msm_ext_disp_init_data *ext = &audio->ext_audio_data;
if (!ext->intf_ops.audio_notify)
goto end;
rc = ext->intf_ops.audio_notify(audio->ext_pdev,
&ext->codec, state);
if (rc) {
@ -710,12 +713,14 @@ static int dp_audio_on(struct dp_audio *dp_audio)
audio->session_on = true;
rc = ext->intf_ops.audio_config(audio->ext_pdev,
&ext->codec,
EXT_DISPLAY_CABLE_CONNECT);
if (rc) {
pr_err("failed to config audio, err=%d\n", rc);
goto end;
if (ext->intf_ops.audio_config) {
rc = ext->intf_ops.audio_config(audio->ext_pdev,
&ext->codec,
EXT_DISPLAY_CABLE_CONNECT);
if (rc) {
pr_err("failed to config audio, err=%d\n", rc);
goto end;
}
}
rc = dp_audio_notify(audio, EXT_DISPLAY_CABLE_CONNECT);
@ -752,11 +757,13 @@ static int dp_audio_off(struct dp_audio *dp_audio)
pr_debug("success\n");
end:
rc = ext->intf_ops.audio_config(audio->ext_pdev,
&ext->codec,
EXT_DISPLAY_CABLE_DISCONNECT);
if (rc)
pr_err("failed to config audio, err=%d\n", rc);
if (ext->intf_ops.audio_config) {
rc = ext->intf_ops.audio_config(audio->ext_pdev,
&ext->codec,
EXT_DISPLAY_CABLE_DISCONNECT);
if (rc)
pr_err("failed to config audio, err=%d\n", rc);
}
audio->session_on = false;
audio->engine_on = false;

@ -632,8 +632,11 @@ static int dp_display_process_hpd_low(struct dp_display_private *dp)
int rc = 0, idx;
struct dp_panel *dp_panel;
mutex_lock(&dp->session_lock);
if (!dp->dp_display.is_connected) {
pr_debug("HPD already off\n");
mutex_unlock(&dp->session_lock);
return 0;
}
@ -646,10 +649,14 @@ static int dp_display_process_hpd_low(struct dp_display_private *dp)
dp_panel = dp->active_panels[idx];
if (dp_panel->audio_supported)
if (dp_panel->audio_supported) {
dp_panel->audio->off(dp_panel->audio);
dp_panel->audio_supported = false;
}
}
mutex_unlock(&dp->session_lock);
dp_display_process_mst_hpd_low(dp);
rc = dp_display_send_hpd_notification(dp, false);

Loading…
Cancel
Save