diff options
author | Erin Yan <xinyey@codeaurora.org> | 2018-08-09 10:21:31 +0800 |
---|---|---|
committer | Gerrit - the friendly Code Review server <code-review@localhost> | 2018-08-14 19:49:31 -0700 |
commit | 2a7de566830b19f3e3e22506f9c0cd936758ac0d (patch) | |
tree | 306d71b5e187b6d3078702c84f66c4ceaddf6333 | |
parent | 2d6cc4c81b1cb69379102c57a9a927c9583ccb8b (diff) |
q6asm: retry asm_open_read and asm_open_loopback when session id conflict
The ADSP asm session ids are managed by the kernel driver. It's all right
for native use cases. But for virtualization use cases, there's no way to
synchronize the session ids' status among virtual machines. Playing back
in one virtual machine is probably failed, because the session id may had
been occupied by a use case in another virtual machine.
The patch allowed audio capture stream and loopback stream to try all
available session ids in case of session id conflict error, to support
concurrent playback from multiple virtual machines.
Change-Id: I01b4da65f3e5716dd14c20c614b53f3c45dd9ea3
Signed-off-by: Erin Yan <xinyey@codeaurora.org>
-rw-r--r-- | include/sound/q6asm-v2.h | 6 | ||||
-rw-r--r-- | sound/soc/msm/qdsp6v2/msm-pcm-loopback-v2.c | 8 | ||||
-rw-r--r-- | sound/soc/msm/qdsp6v2/msm-pcm-q6-v2.c | 8 | ||||
-rw-r--r-- | sound/soc/msm/qdsp6v2/q6asm.c | 68 |
4 files changed, 80 insertions, 10 deletions
diff --git a/include/sound/q6asm-v2.h b/include/sound/q6asm-v2.h index 3523fac586ce..8af49bb6a9fa 100644 --- a/include/sound/q6asm-v2.h +++ b/include/sound/q6asm-v2.h @@ -292,6 +292,9 @@ int q6asm_open_read_v4(struct audio_client *ac, uint32_t format, int q6asm_open_read_v5(struct audio_client *ac, uint32_t format, uint16_t bits_per_sample, bool ts_mode); +int q6asm_open_read_with_retry(struct audio_client *ac, uint32_t format, + uint16_t bits_per_sample, bool ts_mode); + int q6asm_open_write(struct audio_client *ac, uint32_t format /*, uint16_t bits_per_sample*/); @@ -340,6 +343,9 @@ int q6asm_open_read_write_v2(struct audio_client *ac, uint32_t rd_format, int q6asm_open_loopback_v2(struct audio_client *ac, uint16_t bits_per_sample); +int q6asm_open_loopback_with_retry(struct audio_client *ac, + uint16_t bits_per_sample); + int q6asm_open_transcode_loopback(struct audio_client *ac, uint16_t bits_per_sample, uint32_t source_format, uint32_t sink_format); diff --git a/sound/soc/msm/qdsp6v2/msm-pcm-loopback-v2.c b/sound/soc/msm/qdsp6v2/msm-pcm-loopback-v2.c index 9420534d3c5f..4f3f1d25b4a9 100644 --- a/sound/soc/msm/qdsp6v2/msm-pcm-loopback-v2.c +++ b/sound/soc/msm/qdsp6v2/msm-pcm-loopback-v2.c @@ -289,10 +289,12 @@ static int msm_pcm_open(struct snd_pcm_substream *substream) mutex_unlock(&pcm->lock); return -ENOMEM; } - pcm->session_id = pcm->audio_client->session; + pcm->audio_client->perf_mode = pdata->perf_mode; - ret = q6asm_open_loopback_v2(pcm->audio_client, - bits_per_sample); + ret = q6asm_open_loopback_with_retry(pcm->audio_client, + bits_per_sample); + pcm->session_id = pcm->audio_client->session; + if (ret < 0) { dev_err(rtd->platform->dev, "%s: pcm out open failed\n", __func__); diff --git a/sound/soc/msm/qdsp6v2/msm-pcm-q6-v2.c b/sound/soc/msm/qdsp6v2/msm-pcm-q6-v2.c index 1e69ddcc3464..6798b50e682f 100644 --- a/sound/soc/msm/qdsp6v2/msm-pcm-q6-v2.c +++ b/sound/soc/msm/qdsp6v2/msm-pcm-q6-v2.c @@ -498,13 +498,7 @@ static int msm_pcm_capture_prepare(struct snd_pcm_substream *substream) __func__, params_channels(params), prtd->audio_client->perf_mode); - if (q6asm_get_svc_version(APR_SVC_ASM) >= - ADSP_ASM_API_VERSION_V2) - ret = q6asm_open_read_v5(prtd->audio_client, - FORMAT_LINEAR_PCM, - bits_per_sample, false); - else - ret = q6asm_open_read_v4(prtd->audio_client, + ret = q6asm_open_read_with_retry(prtd->audio_client, FORMAT_LINEAR_PCM, bits_per_sample, false); if (ret < 0) { diff --git a/sound/soc/msm/qdsp6v2/q6asm.c b/sound/soc/msm/qdsp6v2/q6asm.c index 0ad15e90bfc6..2f048fddcb08 100644 --- a/sound/soc/msm/qdsp6v2/q6asm.c +++ b/sound/soc/msm/qdsp6v2/q6asm.c @@ -2974,6 +2974,52 @@ int q6asm_open_read_v5(struct audio_client *ac, uint32_t format, } EXPORT_SYMBOL(q6asm_open_read_v5); +static int q6asm_open_read_version_adaptor(struct audio_client *ac, + uint32_t format, uint16_t bits_per_sample, bool ts_mode) +{ + if (q6asm_get_svc_version(APR_SVC_ASM) >= ADSP_ASM_API_VERSION_V2) + return q6asm_open_read_v5(ac, FORMAT_LINEAR_PCM, + bits_per_sample, false); + else + return q6asm_open_read_v4(ac, FORMAT_LINEAR_PCM, + bits_per_sample, false); +} + +/* + * q6asm_open_read_with_retry - Opens audio capture session, with retrying + * in case of session ID conflict + * + * @ac: Client session handle + * @format: encoder format + * @bits_per_sample: bit width of capture session + * @ts_mode: timestamp mode + */ +int q6asm_open_read_with_retry(struct audio_client *ac, uint32_t format, + uint16_t bits_per_sample, bool ts_mode) +{ + int i, rc; + + mutex_lock(&session_lock); + for (i = 0; i < ASM_ACTIVE_STREAMS_ALLOWED; i++) { + rc = q6asm_open_read_version_adaptor(ac, format, + bits_per_sample, ts_mode); + if (rc != -EALREADY) + break; + + pr_debug("%s: session %d is occupied, try next\n", + __func__, ac->session); + q6asm_session_set_ignore(ac->session); + rc = q6asm_session_try_next(ac); + if (rc < 0) + break; + } + q6asm_session_clean_ignore(); + mutex_unlock(&session_lock); + + return rc; +} +EXPORT_SYMBOL(q6asm_open_read_with_retry); + int q6asm_open_write_compressed(struct audio_client *ac, uint32_t format, uint32_t passthrough_flag) { @@ -3667,7 +3713,29 @@ int q6asm_open_loopback_v2(struct audio_client *ac, uint16_t bits_per_sample) fail_cmd: return rc; } +int q6asm_open_loopback_with_retry(struct audio_client *ac, + uint16_t bits_per_sample) +{ + int i, rc; + + mutex_lock(&session_lock); + for (i = 0; i < ASM_ACTIVE_STREAMS_ALLOWED; i++) { + rc = q6asm_open_loopback_v2(ac, bits_per_sample); + if (rc != -EALREADY) + break; + pr_debug("%s: session %d is occupied, try next\n", + __func__, ac->session); + q6asm_session_set_ignore(ac->session); + rc = q6asm_session_try_next(ac); + if (rc < 0) + break; + } + q6asm_session_clean_ignore(); + mutex_unlock(&session_lock); + return rc; +} +EXPORT_SYMBOL(q6asm_open_loopback_with_retry); int q6asm_open_transcode_loopback(struct audio_client *ac, uint16_t bits_per_sample, |