diff options
author | Florian Muller <mullerf@google.com> | 2023-04-26 18:30:53 -0700 |
---|---|---|
committer | Florian Muller <mullerf@google.com> | 2023-04-28 13:25:37 +0000 |
commit | a6bd35aa71f4ef679c997c553ea0df750fe8b7ba (patch) | |
tree | 730dfe21f1a3f2299293248ef0bfde301d61a701 | |
parent | 0830bb409768873a1b1c0e7982d48e6a624c7407 (diff) | |
download | exynos-android-exynos-r11-4.19-android11-wear-jr3-qpr2.tar.gz |
Add a defense patch in abox_flush_recpandroid-wear-11.0.0_r0.10android-exynos-r11-4.19-android11-wear-jr3-qpr2
If recp is flushed with abox_flush_recp during a WDMA operation, there
is a risk this leads to DMA issues, which then leads to an abox crash.
This patch helps to prevent against this issue.
Test: Manual
Bug: 273604972
Bug: 270742627
Change-Id: I073ecd7a91148d4d7a01410ca02eda05807e672c
Signed-off-by: Florian Muller <mullerf@google.com>
-rw-r--r-- | sound/soc/samsung/abox/abox.c | 37 |
1 files changed, 32 insertions, 5 deletions
diff --git a/sound/soc/samsung/abox/abox.c b/sound/soc/samsung/abox/abox.c index 93efd97c4839..136eb73295f4 100644 --- a/sound/soc/samsung/abox/abox.c +++ b/sound/soc/samsung/abox/abox.c @@ -2065,21 +2065,48 @@ static int abox_flush_sifs2(struct snd_soc_dapm_widget *w, return 0; } +#define MAX_TRY_NUM 30 static int abox_flush_recp(struct snd_soc_dapm_widget *w, struct snd_kcontrol *kcontrol, int event) { struct snd_soc_component *cmpnt = snd_soc_dapm_to_component(w->dapm); struct device *dev = cmpnt->dev; + struct abox_data *data = dev_get_drvdata(dev); + struct abox_dma_data *dma_data = dev_get_drvdata(data->dev_wdma[0]); + u32 stat; + bool prog; + unsigned int count = 0; - dev_dbg(dev, "%s\n", __func__); + if (snd_soc_dapm_connected_output_ep(w, NULL)) + return 0; - if (!snd_soc_dapm_connected_output_ep(w, NULL)) { + dev_info(dev, "%s(%d)\n", __func__, event); + + if (event == SND_SOC_DAPM_PRE_PMU) { dev_info(dev, "%s: flush\n", __func__); - snd_soc_component_update_bits(cmpnt, ABOX_SPUM_CTRL2, - ABOX_SPUM_RECP_FLUSH_MASK, - 1 << ABOX_SPUM_RECP_FLUSH_L); + snd_soc_component_update_bits(cmpnt, + ABOX_SPUM_CTRL2, + ABOX_SPUM_RECP_FLUSH_MASK, + 1 << ABOX_SPUM_RECP_FLUSH_L); + return 0; + } else if (event == SND_SOC_DAPM_POST_PMD) { + while (count++ < MAX_TRY_NUM) { + stat = readl(dma_data->sfr_base + ABOX_WDMA_STATUS); + prog = (stat & ABOX_WDMA_PROGRESS_MASK) ? true : false; + if (!prog) { + dev_info(dev, "%s: flush\n", __func__); + snd_soc_component_update_bits(cmpnt, + ABOX_SPUM_CTRL2, + ABOX_SPUM_RECP_FLUSH_MASK, + 1 << ABOX_SPUM_RECP_FLUSH_L); + return 0; + } + mdelay(1); + } } + dev_info(dev, "%s: flush time out(%d)\n", __func__, count); + return 0; } |