audio: fix earc rx crash warning [1/1]
PD#SWPL-198561
PD#OTT-71761
Problem:
Call trace:
dump_backtrace+0x0/0x1e4
show_stack+0x24/0x34
dump_stack+0xbc/0x108
___might_sleep+0x100/0x110
__might_sleep+0x54/0x98
mutex_lock+0x2c/0x68
snd_pcm_stop_xrun+0x2c/0xb0
earcrx_timer_func+0x94/0xac [snd_soc]
call_timer_fn+0xc0/0x1ac
expire_timers+0x74/0x164
root cause: in spin lock irqsave section code, there is mutex called.
Solution:
1.keep nonatomic as true.
2.trigger xrun in work task, not in timer function.
Verify:
sc2
Change-Id: Idde8f3bce545c55f6a9bf20a6a5903feac290f9e
Signed-off-by: jian zhou <jian.zhou@amlogic.com>
diff --git a/sound/soc/amlogic/auge/earc.c b/sound/soc/amlogic/auge/earc.c
index d0d8d86..084f28f 100644
--- a/sound/soc/amlogic/auge/earc.c
+++ b/sound/soc/amlogic/auge/earc.c
@@ -181,6 +181,7 @@
/* do analog auto calibration when bootup */
struct work_struct work;
struct work_struct rx_dmac_int_work;
+ struct work_struct rx_xrun_work;
struct work_struct tx_hold_bus_work;
struct work_struct earctx_reg_init_work;
struct delayed_work tx_resume_work;
@@ -1088,7 +1089,6 @@
dev_err(dev, "failed to claim toddr\n");
goto err_ddr;
}
- substream->pcm->nonatomic = 0;
}
runtime->private_data = p_earc;
@@ -3282,6 +3282,17 @@
mute, p_earc->stream_stable);
}
+static void rx_xrun_work_func(struct work_struct *p_work)
+{
+ struct earc *p_earc = container_of(p_work, struct earc, rx_xrun_work);
+
+ earcrx_pll_refresh(p_earc->rx_top_map, RST_BY_SELF, true, p_earc->chipinfo->rx_pll_new);
+
+ snd_pcm_stop_xrun(p_earc->substreams[SNDRV_PCM_STREAM_CAPTURE]);
+
+ dev_info(p_earc->dev, "reset pll and trigger xrun\n");
+}
+
static void earcrx_timer_func(struct timer_list *t)
{
struct earc *p_earc = from_timer(p_earc, t, rx_detect_point_timer);
@@ -3297,14 +3308,8 @@
goto exit;
cur_addr = aml_toddr_get_position(p_earc->tddr);
- if (p_earc->rx_position_addr == cur_addr) {
- earcrx_pll_refresh(p_earc->rx_top_map, RST_BY_SELF, true,
- p_earc->chipinfo->rx_pll_new);
-
- snd_pcm_stop_xrun(p_earc->substreams[SNDRV_PCM_STREAM_CAPTURE]);
-
- dev_info(p_earc->dev, "reset pll and trigger xrun\n");
- }
+ if (p_earc->rx_position_addr == cur_addr)
+ schedule_work(&p_earc->rx_xrun_work);
p_earc->rx_position_addr = cur_addr;
@@ -3536,6 +3541,7 @@
if (earcrx_cmdc_get_attended_type(p_earc->rx_cmdc_map) == ATNDTYP_EARC)
earcrx_cmdc_set_cds(p_earc->rx_cmdc_map, p_earc->rx_cds_data);
INIT_WORK(&p_earc->rx_dmac_int_work, valid_auto_work_func);
+ INIT_WORK(&p_earc->rx_xrun_work, rx_xrun_work_func);
INIT_DELAYED_WORK(&p_earc->rx_stable_work, rx_stable_work_func);
INIT_DELAYED_WORK(&p_earc->rx_pll_detect_work, rx_pll_detect_work_func);
INIT_DELAYED_WORK(&p_earc->hdmitx_5v_work, hdmitx_5v_work_func);