summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authormillerliang <millerliang@google.com>2023-06-06 15:05:24 +0800
committerMiller Liang <millerliang@google.com>2023-06-08 04:50:45 +0000
commit4beb16aca994bea699e98f9e6309965486898b54 (patch)
tree92c8d84b43d2ac6a26131868efd528ed9b1d9e75
parenta6d92518e59f1b02b5238fa5a3a5c3df434d00ff (diff)
downloadaoc-4beb16aca994bea699e98f9e6309965486898b54.tar.gz
Do not queue a work if the cancel_work_sync is in progress. Bug: 284055134 Change-Id: I7e2a5b12ccd6cc28b23f15ea65fe4d66fe379b25 Signed-off-by: millerliang <millerliang@google.com>
-rw-r--r--alsa/aoc_alsa.h1
-rw-r--r--alsa/aoc_alsa_incall.c20
-rw-r--r--alsa/aoc_alsa_pcm.c17
-rw-r--r--alsa/aoc_alsa_voip.c19
4 files changed, 51 insertions, 6 deletions
diff --git a/alsa/aoc_alsa.h b/alsa/aoc_alsa.h
index 9c3e6cb..9ebd338 100644
--- a/alsa/aoc_alsa.h
+++ b/alsa/aoc_alsa.h
@@ -294,6 +294,7 @@ struct aoc_alsa_stream {
int entry_point_idx; /* Index of entry point, same as idx in playback */
int stream_type; /* Normal pcm, incall, mmap, hifi, compr */
int isr_type; /* timer, interrupt */
+ atomic_t cancel_work_active;
int channels; /* Number of channels in audio */
int params_rate; /* Sampling rate */
diff --git a/alsa/aoc_alsa_incall.c b/alsa/aoc_alsa_incall.c
index 4c64ab7..72a2636 100644
--- a/alsa/aoc_alsa_incall.c
+++ b/alsa/aoc_alsa_incall.c
@@ -86,7 +86,20 @@ static enum hrtimer_restart aoc_incall_hifi_irq_process(struct aoc_alsa_stream *
alsa_stream->pos = (consumed - alsa_stream->hw_ptr_base) % alsa_stream->buffer_size;
}
- schedule_work(&alsa_stream->pcm_period_work);
+ /* Do not queue a work if the cancel_work is active */
+ if (atomic_read(&alsa_stream->cancel_work_active) > 0)
+ return HRTIMER_RESTART;
+
+ if (!queue_work(system_highpri_wq, &alsa_stream->pcm_period_work)) {
+ wake_up(&alsa_stream->substream->runtime->sleep);
+ wake_up(&alsa_stream->substream->runtime->tsleep);
+ alsa_stream->wq_busy_count++;
+
+ if (!(alsa_stream->wq_busy_count % 5))
+ pr_warn("incall/hifi period work busy count = %d\n",
+ alsa_stream->wq_busy_count);
+ } else
+ alsa_stream->wq_busy_count = 0;
return HRTIMER_RESTART;
}
@@ -183,6 +196,9 @@ static int snd_aoc_pcm_open(struct snd_soc_component *component,
alsa_stream->dev = dev;
alsa_stream->idx = idx;
alsa_stream->stream_type = aoc_pcm_device_to_stream_type(idx);
+ alsa_stream->wq_busy_count = 0;
+ atomic_set(&alsa_stream->cancel_work_active, 0);
+
INIT_WORK(&alsa_stream->pcm_period_work, aoc_pcm_period_work_handler);
/* Ring buffer will be flushed at prepare() before playback/capture */
@@ -244,8 +260,10 @@ static int snd_aoc_pcm_close(struct snd_soc_component *component,
dev_dbg(component->dev, "name %s substream %pK", rtd->dai_link->name, substream);
aoc_timer_stop_sync(alsa_stream);
+ atomic_set(&alsa_stream->cancel_work_active, 1);
audio_free_isr(alsa_stream->dev);
cancel_work_sync(&alsa_stream->pcm_period_work);
+ atomic_set(&alsa_stream->cancel_work_active, 0);
if (mutex_lock_interruptible(&chip->audio_mutex)) {
dev_err(component->dev, "ERR: interrupted while waiting for lock\n");
diff --git a/alsa/aoc_alsa_pcm.c b/alsa/aoc_alsa_pcm.c
index ff2df69..2734651 100644
--- a/alsa/aoc_alsa_pcm.c
+++ b/alsa/aoc_alsa_pcm.c
@@ -33,8 +33,10 @@ static void free_aoc_service_work_handler(struct work_struct *work)
return;
aoc_timer_stop_sync(alsa_stream);
+ atomic_set(&alsa_stream->cancel_work_active, 1);
audio_free_isr(alsa_stream->dev);
cancel_work_sync(&alsa_stream->pcm_period_work);
+ atomic_set(&alsa_stream->cancel_work_active, 0);
if (mutex_lock_interruptible(&chip->audio_mutex)) {
pr_err("ERR: interrupted while waiting for lock\n");
@@ -201,15 +203,19 @@ static enum hrtimer_restart aoc_pcm_irq_process(struct aoc_alsa_stream *alsa_str
alsa_stream->pos = (consumed - alsa_stream->hw_ptr_base) % alsa_stream->buffer_size;
}
+ /* Do not queue a work if the cancel_work is active */
+ if (atomic_read(&alsa_stream->cancel_work_active) > 0)
+ return HRTIMER_RESTART;
+
if (!queue_work(system_highpri_wq, &alsa_stream->pcm_period_work)) {
wake_up(&alsa_stream->substream->runtime->sleep);
wake_up(&alsa_stream->substream->runtime->tsleep);
- alsa_stream->wq_busy_count ++;
- } else {
- if (alsa_stream->wq_busy_count > 5)
+ alsa_stream->wq_busy_count++;
+
+ if (!(alsa_stream->wq_busy_count % 5))
pr_warn("period work busy count = %d\n", alsa_stream->wq_busy_count);
+ } else
alsa_stream->wq_busy_count = 0;
- }
return HRTIMER_RESTART;
}
@@ -304,6 +310,7 @@ static int snd_aoc_pcm_open(struct snd_soc_component *component,
alsa_stream->idx = idx;
alsa_stream->stream_type = aoc_pcm_device_to_stream_type(idx);
alsa_stream->wq_busy_count = 0;
+ atomic_set(&alsa_stream->cancel_work_active, 0);
INIT_WORK(&alsa_stream->free_aoc_service_work, free_aoc_service_work_handler);
INIT_WORK(&alsa_stream->pcm_period_work, aoc_pcm_period_work_handler);
@@ -384,8 +391,10 @@ static int snd_aoc_pcm_close(struct snd_soc_component *component,
pr_debug("%s: name %s substream %p", __func__, rtd->dai_link->name, substream);
aoc_timer_stop_sync(alsa_stream);
+ atomic_set(&alsa_stream->cancel_work_active, 1);
audio_free_isr(alsa_stream->dev);
cancel_work_sync(&alsa_stream->pcm_period_work);
+ atomic_set(&alsa_stream->cancel_work_active, 0);
if (mutex_lock_interruptible(&chip->audio_mutex)) {
pr_err("ERR: interrupted while waiting for lock\n");
diff --git a/alsa/aoc_alsa_voip.c b/alsa/aoc_alsa_voip.c
index a719bb6..cf98d16 100644
--- a/alsa/aoc_alsa_voip.c
+++ b/alsa/aoc_alsa_voip.c
@@ -85,7 +85,19 @@ static enum hrtimer_restart aoc_voip_irq_process(struct aoc_alsa_stream *alsa_st
alsa_stream->pos = (consumed - alsa_stream->hw_ptr_base) % alsa_stream->buffer_size;
}
- schedule_work(&alsa_stream->pcm_period_work);
+ /* Do not queue a work if the cancel_work is active */
+ if (atomic_read(&alsa_stream->cancel_work_active) > 0)
+ return HRTIMER_RESTART;
+
+ if (!queue_work(system_highpri_wq, &alsa_stream->pcm_period_work)) {
+ wake_up(&alsa_stream->substream->runtime->sleep);
+ wake_up(&alsa_stream->substream->runtime->tsleep);
+ alsa_stream->wq_busy_count++;
+
+ if (!(alsa_stream->wq_busy_count % 5))
+ pr_warn("voip period work busy count = %d\n", alsa_stream->wq_busy_count);
+ } else
+ alsa_stream->wq_busy_count = 0;
return HRTIMER_RESTART;
}
@@ -182,6 +194,9 @@ static int snd_aoc_pcm_open(struct snd_soc_component *component,
alsa_stream->cstream = NULL;
alsa_stream->dev = dev;
alsa_stream->idx = idx;
+ alsa_stream->wq_busy_count = 0;
+ atomic_set(&alsa_stream->cancel_work_active, 0);
+
INIT_WORK(&alsa_stream->pcm_period_work, aoc_pcm_period_work_handler);
/* Ring buffer will be flushed at prepare() before playback/capture */
@@ -243,8 +258,10 @@ static int snd_aoc_pcm_close(struct snd_soc_component *component,
dev_dbg(component->dev, "name %s substream %pK", rtd->dai_link->name, substream);
aoc_timer_stop_sync(alsa_stream);
+ atomic_set(&alsa_stream->cancel_work_active, 1);
audio_free_isr(alsa_stream->dev);
cancel_work_sync(&alsa_stream->pcm_period_work);
+ atomic_set(&alsa_stream->cancel_work_active, 0);
if (mutex_lock_interruptible(&chip->audio_mutex)) {
dev_err(component->dev, "ERR: interrupted while waiting for lock\n");