ASoC: wcd9310: force slimbus ports to disconnect during error cases
With shared data channel architecture, SLIMBUS driver
only removes slimbus channel when all clients vote to
have channel removed. In case of subsystem restart,
client such as MDM can go down without withdrawing
vote. During CODEC path shutdown, CODEC driver will
receive slimbus slave interrupt in time indicating
port disconnection because slimbus channel has not
be been voted off. Then, CODEC driver blindly
shutdown rest of CODEC path. This results in
overflow error on Rx path and underflow error on
Tx path. In case of time out waiting for port disconnect
interrupts to arrive, force ports to disconnect
Signed-off-by: SathishKumar Mani <smani@codeaurora.org>
BUG-ID: 7313016
diff --git a/sound/soc/codecs/wcd9310.c b/sound/soc/codecs/wcd9310.c
index 1bdf167..b8d2c32 100644
--- a/sound/soc/codecs/wcd9310.c
+++ b/sound/soc/codecs/wcd9310.c
@@ -4503,8 +4503,8 @@
pr_err("%s: Slim close tx/rx wait timeout\n",
__func__);
ret = -EINVAL;
- }
- ret = 0;
+ } else
+ ret = 0;
break;
}
return ret;
@@ -4517,7 +4517,7 @@
struct snd_soc_codec *codec = w->codec;
struct tabla_priv *tabla_p = snd_soc_codec_get_drvdata(codec);
u32 j = 0;
- u32 ret = 0;
+ int ret = 0;
codec->control_data = dev_get_drvdata(codec->dev->parent);
tabla = codec->control_data;
@@ -4574,13 +4574,22 @@
ret = wcd9xxx_close_slim_sch_rx(tabla,
tabla_p->dai[j].ch_num,
tabla_p->dai[j].ch_tot);
- tabla_p->dai[j].rate = 0;
- memset(tabla_p->dai[j].ch_num, 0, (sizeof(u32)*
- tabla_p->dai[j].ch_tot));
- tabla_p->dai[j].ch_tot = 0;
ret = tabla_codec_enable_chmask(tabla_p,
SND_SOC_DAPM_POST_PMD,
j);
+ if (ret < 0) {
+ ret = wcd9xxx_disconnect_port(tabla,
+ tabla_p->dai[j].ch_num,
+ tabla_p->dai[j].ch_tot,
+ 1);
+ pr_info("%s: Disconnect RX port ret = %d\n",
+ __func__, ret);
+ }
+ tabla_p->dai[j].rate = 0;
+ memset(tabla_p->dai[j].ch_num, 0, (sizeof(u32)*
+ tabla_p->dai[j].ch_tot));
+ tabla_p->dai[j].ch_tot = 0;
+
if ((tabla != NULL) &&
(tabla->dev != NULL) &&
(tabla->dev->parent != NULL)) {
@@ -4600,7 +4609,7 @@
struct tabla_priv *tabla_p = snd_soc_codec_get_drvdata(codec);
/* index to the DAI ID, for now hardcoding */
u32 j = 0;
- u32 ret = 0;
+ int ret = 0;
codec->control_data = dev_get_drvdata(codec->dev->parent);
tabla = codec->control_data;
@@ -4657,13 +4666,21 @@
ret = wcd9xxx_close_slim_sch_tx(tabla,
tabla_p->dai[j].ch_num,
tabla_p->dai[j].ch_tot);
+ ret = tabla_codec_enable_chmask(tabla_p,
+ SND_SOC_DAPM_POST_PMD,
+ j);
+ if (ret < 0) {
+ ret = wcd9xxx_disconnect_port(tabla,
+ tabla_p->dai[j].ch_num,
+ tabla_p->dai[j].ch_tot, 0);
+ pr_info("%s: Disconnect TX port, ret = %d\n",
+ __func__, ret);
+ }
+
tabla_p->dai[j].rate = 0;
memset(tabla_p->dai[j].ch_num, 0, (sizeof(u32)*
tabla_p->dai[j].ch_tot));
tabla_p->dai[j].ch_tot = 0;
- ret = tabla_codec_enable_chmask(tabla_p,
- SND_SOC_DAPM_POST_PMD,
- j);
if ((tabla != NULL) &&
(tabla->dev != NULL) &&
(tabla->dev->parent != NULL)) {