Remove tasklet for it may cause the reset operation
can't be handled immediately, then there will be
endless xrun interrupt.
Fixes: 7ccafa2b3879 ("ASoC: fsl_esai: recover the channel swap after xrun")
Signed-off-by: Shengjiu Wang <[email protected]>
---
sound/soc/fsl/fsl_esai.c | 15 ++++-----------
1 file changed, 4 insertions(+), 11 deletions(-)
diff --git a/sound/soc/fsl/fsl_esai.c b/sound/soc/fsl/fsl_esai.c
index c7a49d03463a..1ad0859da5e2 100644
--- a/sound/soc/fsl/fsl_esai.c
+++ b/sound/soc/fsl/fsl_esai.c
@@ -32,7 +32,6 @@
* @extalclk: esai clock source to derive HCK, SCK and FS
* @fsysclk: system clock source to derive HCK, SCK and FS
* @spbaclk: SPBA clock (optional, depending on SoC design)
- * @task: tasklet to handle the reset operation
* @lock: spin lock between hw_reset() and trigger()
* @fifo_depth: depth of tx/rx FIFO
* @slot_width: width of each DAI slot
@@ -56,7 +55,6 @@ struct fsl_esai {
struct clk *extalclk;
struct clk *fsysclk;
struct clk *spbaclk;
- struct tasklet_struct task;
spinlock_t lock; /* Protect hw_reset and trigger */
u32 fifo_depth;
u32 slot_width;
@@ -74,6 +72,8 @@ struct fsl_esai {
char name[32];
};
+static void fsl_esai_hw_reset(struct fsl_esai *esai_priv);
+
static irqreturn_t esai_isr(int irq, void *devid)
{
struct fsl_esai *esai_priv = (struct fsl_esai *)devid;
@@ -87,7 +87,7 @@ static irqreturn_t esai_isr(int irq, void *devid)
if ((saisr & (ESAI_SAISR_TUE | ESAI_SAISR_ROE)) &&
esai_priv->reset_at_xrun) {
dev_dbg(&pdev->dev, "reset module for xrun\n");
- tasklet_schedule(&esai_priv->task);
+ fsl_esai_hw_reset(esai_priv);
}
if (esr & ESAI_ESR_TINIT_MASK)
@@ -674,9 +674,8 @@ static void fsl_esai_trigger_stop(struct fsl_esai *esai_priv, bool tx)
ESAI_xFCR_xFR, 0);
}
-static void fsl_esai_hw_reset(unsigned long arg)
+static void fsl_esai_hw_reset(struct fsl_esai *esai_priv)
{
- struct fsl_esai *esai_priv = (struct fsl_esai *)arg;
bool tx = true, rx = false, enabled[2];
unsigned long lock_flags;
u32 tfcr, rfcr;
@@ -1034,9 +1033,6 @@ static int fsl_esai_probe(struct platform_device *pdev)
return ret;
}
- tasklet_init(&esai_priv->task, fsl_esai_hw_reset,
- (unsigned long)esai_priv);
-
pm_runtime_enable(&pdev->dev);
regcache_cache_only(esai_priv->regmap, true);
@@ -1050,10 +1046,7 @@ static int fsl_esai_probe(struct platform_device *pdev)
static int fsl_esai_remove(struct platform_device *pdev)
{
- struct fsl_esai *esai_priv = platform_get_drvdata(pdev);
-
pm_runtime_disable(&pdev->dev);
- tasklet_kill(&esai_priv->task);
return 0;
}
--
2.21.0
On Fri, Apr 24, 2020 at 02:54:06PM +0800, Shengjiu Wang wrote:
> Remove tasklet for it may cause the reset operation
> can't be handled immediately, then there will be
> endless xrun interrupt.
The reset routine is really long and expensive, so not sure
if it'd be good to do it completely inside HW ISR. Have you
tried to clear xEIE bits to disable xrun interrupts, before
scheduling the tasklet? If that does not solve the problem,
we may go for this change.
On Fri, Apr 24, 2020 at 5:17 PM Nicolin Chen <[email protected]> wrote:
>
> On Fri, Apr 24, 2020 at 02:54:06PM +0800, Shengjiu Wang wrote:
> > Remove tasklet for it may cause the reset operation
> > can't be handled immediately, then there will be
> > endless xrun interrupt.
>
> The reset routine is really long and expensive, so not sure
> if it'd be good to do it completely inside HW ISR. Have you
> tried to clear xEIE bits to disable xrun interrupts, before
> scheduling the tasklet? If that does not solve the problem,
> we may go for this change.
Good idea, will send v2
best regards
wang shengjiu