Skip to content

Commit bfb3fcb

Browse files
committed
ASoC: SOF: add elapse work for spcm to fix trigger stop ipc timeout
We do elapse in interrupt context at the moment, this will lead to ipc timeout at trigger stop with some possibility, where the pcm elapse will call trigger stop and the stop ipc will timeout as the ipc interrupt is disabled at this context. Here we introduce a work to do pcm period elapse, and the stress test shows that it fixes this kind of ipc timeout issue. Signed-off-by: Keyon Jie <yang.jie@linux.intel.com>
1 parent 066e6f4 commit bfb3fcb

2 files changed

Lines changed: 41 additions & 0 deletions

File tree

‎sound/soc/sof/pcm.c‎

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,39 @@ static int sof_pcm_dsp_params(struct snd_sof_pcm *spcm, struct snd_pcm_substream
5252
returnret;
5353
}
5454

55+
/*
56+
* sof pcm period elapse work
57+
*/
58+
staticvoidsof_elapsed_work(structwork_struct*work)
59+
{
60+
structsnd_sof_pcm_stream*sps=
61+
container_of(work, structsnd_sof_pcm_stream, elapse_work);
62+
63+
snd_pcm_period_elapsed(sps->substream);
64+
}
65+
66+
/*
67+
* sof pcm period elapse, this might be called at irq context.
68+
*/
69+
voidsnd_sof_pcm_elapsed(structsnd_pcm_substream*substream)
70+
{
71+
structsnd_soc_pcm_runtime*rtd=substream->private_data;
72+
structsnd_soc_component*component=
73+
snd_soc_rtdcom_lookup(rtd, DRV_NAME);
74+
structsnd_sof_dev*sdev=snd_soc_component_get_drvdata(component);
75+
structsnd_sof_pcm*spcm;
76+
77+
spcm=snd_sof_find_spcm_dai(sdev, rtd);
78+
if (!spcm) {
79+
dev_err(sdev->dev,
80+
"error: period elapsed for unknown stream!\n");
81+
return;
82+
}
83+
84+
schedule_work(&spcm->stream[substream->stream].elapse_work);
85+
}
86+
EXPORT_SYMBOL(snd_sof_pcm_elapsed);
87+
5588
/* this may get called several times by oss emulation */
5689
staticintsof_pcm_hw_params(structsnd_pcm_substream*substream,
5790
structsnd_pcm_hw_params*params)
@@ -169,6 +202,9 @@ static int sof_pcm_hw_params(struct snd_pcm_substream *substream,
169202
/* save pcm hw_params */
170203
memcpy(&spcm->params[substream->stream], params, sizeof(*params));
171204

205+
INIT_WORK(&spcm->stream[substream->stream].elapse_work,
206+
sof_elapsed_work);
207+
172208
returnret;
173209
}
174210

@@ -203,6 +239,9 @@ static int sof_pcm_hw_free(struct snd_pcm_substream *substream)
203239
sizeof(stream), &reply, sizeof(reply));
204240

205241
snd_pcm_lib_free_pages(substream);
242+
243+
cancel_work_sync(&spcm->stream[substream->stream].elapse_work);
244+
206245
returnret;
207246
}
208247

‎sound/soc/sof/sof-priv.h‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -274,6 +274,7 @@ struct snd_sof_pcm_stream {
274274
structsnd_dma_bufferpage_table;
275275
structsof_ipc_stream_posnposn;
276276
structsnd_pcm_substream*substream;
277+
structwork_structelapse_work;
277278
};
278279

279280
/* ALSA SOF PCM device */
@@ -495,6 +496,7 @@ struct snd_sof_pcm *snd_sof_find_spcm_comp(struct snd_sof_dev *sdev,
495496
int*direction);
496497
structsnd_sof_pcm*snd_sof_find_spcm_pcm_id(structsnd_sof_dev*sdev,
497498
unsigned intpcm_id);
499+
voidsnd_sof_pcm_elapsed(structsnd_pcm_substream*substream);
498500

499501
/*
500502
* Stream IPC

0 commit comments

Comments
 (0)