summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFlorian Muller <mullerf@google.com>2023-04-26 18:30:53 -0700
committerFlorian Muller <mullerf@google.com>2023-04-28 13:25:37 +0000
commita6bd35aa71f4ef679c997c553ea0df750fe8b7ba (patch)
tree730dfe21f1a3f2299293248ef0bfde301d61a701
parent0830bb409768873a1b1c0e7982d48e6a624c7407 (diff)
downloadexynos-android-exynos-r11-4.19-android11-wear-jr3-qpr2.tar.gz
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.c37
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;
}