Prechádzať zdrojové kódy

asoc: codecs: avoid crash after diconnecting DP cable

Fix the null pointer access of DP callback
functions.

Change-Id: If4cc48a2471c2cbd1c46ea49cffaa01315673bde
Signed-off-by: Harshal Ahire <[email protected]>
Harshal Ahire 5 rokov pred
rodič
commit
42adadc24f
1 zmenil súbory, kde vykonal 27 pridanie a 10 odobranie
  1. 27 10
      asoc/codecs/msm_hdmi_codec_rx.c

+ 27 - 10
asoc/codecs/msm_hdmi_codec_rx.c

@@ -29,8 +29,6 @@
 	codec_info.type = EXT_DISPLAY_TYPE_DP; \
 	codec_info.ctrl_id = codec_data->ctl[dai_id]; \
 	codec_info.stream_id = codec_data->stream[dai_id]; \
-	msm_ext_disp_select_audio_codec(codec_data->ext_disp_core_pdev, \
-				&codec_info)
 
 enum {
         DP_CONTROLLER0 = 0,
@@ -94,7 +92,9 @@ static int msm_ext_disp_edid_ctl_info(struct snd_kcontrol *kcontrol,
 
 	mutex_lock(&codec_data->dp_ops_lock);
 	SWITCH_DP_CODEC(codec_info, codec_data, dai_id);
-	if (!codec_data->ext_disp_ops.get_audio_edid_blk) {
+	rc = msm_ext_disp_select_audio_codec(codec_data->ext_disp_core_pdev,
+						 &codec_info);
+	if (!codec_data->ext_disp_ops.get_audio_edid_blk || rc) {
 		dev_dbg(component->dev, "%s: get_audio_edid_blk() is NULL\n",
 			__func__);
 		uinfo->type = SNDRV_CTL_ELEM_TYPE_BYTES;
@@ -139,7 +139,9 @@ static int msm_ext_disp_edid_get(struct snd_kcontrol *kcontrol,
 
 	mutex_lock(&codec_data->dp_ops_lock);
 	SWITCH_DP_CODEC(codec_info, codec_data, dai_id);
-	if (!codec_data->ext_disp_ops.get_audio_edid_blk) {
+	rc = msm_ext_disp_select_audio_codec(codec_data->ext_disp_core_pdev,
+						 &codec_info);
+	if (!codec_data->ext_disp_ops.get_audio_edid_blk || rc) {
 		dev_err(component->dev, "%s: codec_data or get_audio_edid_blk() is NULL\n",
 			__func__);
 		mutex_unlock(&codec_data->dp_ops_lock);
@@ -199,9 +201,11 @@ static int msm_ext_disp_audio_type_get(struct snd_kcontrol *kcontrol,
 
 	mutex_lock(&codec_data->dp_ops_lock);
 	SWITCH_DP_CODEC(codec_info, codec_data, dai_id);
+	rc = msm_ext_disp_select_audio_codec(codec_data->ext_disp_core_pdev,
+						 &codec_info);
 
 	if (!codec_data->ext_disp_ops.get_audio_edid_blk ||
-	    !codec_data->ext_disp_ops.get_intf_id) {
+	    !codec_data->ext_disp_ops.get_intf_id || rc) {
 		dev_err(component->dev, "%s: get_audio_edid_blk() or get_intf_id is NULL\n",
 			__func__);
 		rc = -EINVAL;
@@ -284,8 +288,10 @@ static int msm_ext_disp_audio_ack_set(struct snd_kcontrol *kcontrol,
 
 	mutex_lock(&codec_data->dp_ops_lock);
 	SWITCH_DP_CODEC(codec_info, codec_data, dai_id);
+	rc = msm_ext_disp_select_audio_codec(codec_data->ext_disp_core_pdev,
+						 &codec_info);
 
-	if (!codec_data->ext_disp_ops.acknowledge) {
+	if (!codec_data->ext_disp_ops.acknowledge || rc) {
 		dev_err(component->dev,
 			"%s: codec_data ops acknowledge() is NULL\n",
 			__func__);
@@ -460,7 +466,7 @@ static int msm_ext_disp_audio_codec_rx_dai_startup(
 		struct snd_pcm_substream *substream,
 		struct snd_soc_dai *dai)
 {
-	int ret = 0;
+	int ret = 0, rc = 0;
 	struct msm_ext_disp_codec_id codec_info;
 	struct msm_ext_disp_audio_codec_rx_data *codec_data =
 			dev_get_drvdata(dai->component->dev);
@@ -477,8 +483,10 @@ static int msm_ext_disp_audio_codec_rx_dai_startup(
 
 	mutex_lock(&codec_data->dp_ops_lock);
 	SWITCH_DP_CODEC(codec_info, codec_data, dai->id);
+	rc = msm_ext_disp_select_audio_codec(codec_data->ext_disp_core_pdev,
+						 &codec_info);
 
-	if (!codec_data->ext_disp_ops.cable_status) {
+	if (!codec_data->ext_disp_ops.cable_status || rc) {
 		dev_err(dai->dev, "%s() cable_status is null\n",
 			__func__);
 		mutex_unlock(&codec_data->dp_ops_lock);
@@ -532,8 +540,10 @@ static int msm_ext_disp_audio_codec_rx_dai_hw_params(
 
 	mutex_lock(&codec_data->dp_ops_lock);
 	SWITCH_DP_CODEC(codec_info, codec_data, dai->id);
+	rc = msm_ext_disp_select_audio_codec(codec_data->ext_disp_core_pdev,
+						 &codec_info);
 
-	if (!codec_data->ext_disp_ops.audio_info_setup) {
+	if (!codec_data->ext_disp_ops.audio_info_setup || rc) {
 		dev_err(dai->dev, "%s: audio_info_setup is null\n",
 			__func__);
 		mutex_unlock(&codec_data->dp_ops_lock);
@@ -600,8 +610,13 @@ static int msm_ext_disp_audio_codec_rx_dai_hw_params(
 
 	mutex_lock(&codec_data->dp_ops_lock);
 	SWITCH_DP_CODEC(codec_info, codec_data, dai->id);
+	rc = msm_ext_disp_select_audio_codec(codec_data->ext_disp_core_pdev,
+						 &codec_info);
+	if (rc)
+		goto end;
 	rc = codec_data->ext_disp_ops.audio_info_setup(
 			codec_data->ext_disp_core_pdev, &audio_setup_params);
+end:
 	mutex_unlock(&codec_data->dp_ops_lock);
 	if (rc < 0) {
 		dev_err_ratelimited(dai->dev,
@@ -634,9 +649,11 @@ static void msm_ext_disp_audio_codec_rx_dai_shutdown(
 
 	mutex_lock(&codec_data->dp_ops_lock);
 	SWITCH_DP_CODEC(codec_info, codec_data, dai->id);
+	rc = msm_ext_disp_select_audio_codec(codec_data->ext_disp_core_pdev,
+						 &codec_info);
 
 	if (!codec_data->ext_disp_ops.teardown_done ||
-	    !codec_data->ext_disp_ops.cable_status) {
+	    !codec_data->ext_disp_ops.cable_status || rc) {
 		dev_err(dai->dev, "%s: teardown_done or cable_status is null\n",
 			__func__);
 		mutex_unlock(&codec_data->dp_ops_lock);