Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 12 additions & 0 deletions sound/soc/sof/core.c
Original file line number Diff line number Diff line change
Expand Up @@ -696,6 +696,12 @@ int snd_sof_device_probe(struct device *dev, struct snd_sof_pdata *plat_data)
mutex_init(&sdev->client_event_handler_mutex);
mutex_init(&sdev->dsp_fw_boot_mutex);

/* Create high-priority workqueue for PCM period elapsed work */
sdev->pcm_period_wq = alloc_workqueue("sof_pcm_wq", WQ_HIGHPRI | WQ_UNBOUND, 0);
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you describe how this can happen?
If the system workqueue is that much congested then how can anything work?

We use threaded irq as well and that is also using system queue afaik, I'm not sure how this helps.

if (!sdev->pcm_period_wq) {
dev_err(dev, "error: failed to create sof_pcm_wq\n");
}

/* set default timeouts if none provided */
if (plat_data->desc->ipc_timeout == 0)
sdev->ipc_timeout = TIMEOUT_DEFAULT_IPC_MS;
Expand Down Expand Up @@ -797,6 +803,12 @@ int snd_sof_device_remove(struct device *dev)
/* release firmware */
snd_sof_fw_unload(sdev);

/* Destroy the PCM workqueue */
if (sdev->pcm_period_wq) {
destroy_workqueue(sdev->pcm_period_wq);
sdev->pcm_period_wq = NULL;
}

return 0;
}
EXPORT_SYMBOL(snd_sof_device_remove);
Expand Down
8 changes: 7 additions & 1 deletion sound/soc/sof/pcm.c
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ void snd_sof_pcm_period_elapsed(struct snd_pcm_substream *substream)
struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream);
struct snd_soc_component *component =
snd_soc_rtdcom_lookup(rtd, SOF_AUDIO_PCM_DRV_NAME);
struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(component);
struct snd_sof_pcm *spcm;

spcm = snd_sof_find_spcm_dai(component, rtd);
Expand All @@ -62,7 +63,12 @@ void snd_sof_pcm_period_elapsed(struct snd_pcm_substream *substream)
* To avoid sending IPC before the previous IPC is handled, we
* schedule delayed work here to call the snd_pcm_period_elapsed().
*/
schedule_work(&spcm->stream[substream->stream].period_elapsed_work);
if (sdev->pcm_period_wq) {
queue_work(sdev->pcm_period_wq, &spcm->stream[substream->stream].period_elapsed_work);
} else {
// Fallback to system workqueue
schedule_work(&spcm->stream[substream->stream].period_elapsed_work);
}
}
EXPORT_SYMBOL(snd_sof_pcm_period_elapsed);

Expand Down
2 changes: 2 additions & 0 deletions sound/soc/sof/sof-priv.h
Original file line number Diff line number Diff line change
Expand Up @@ -701,6 +701,8 @@ struct snd_sof_dev {
/* used to store the FW filename and path passed from userspace for DSP ops testing */
struct sof_loadable_file_profile test_profile;

struct workqueue_struct *pcm_period_wq; /* WQ for PCM period elapsed */

void *private; /* core does not touch this */
};

Expand Down
Loading