tegra-alt: adsp: reset handler on close

Set message handler to NULL on stream close.
Acquire lock when calling msg handler to avoid
race condition.

Bug 200121246

Change-Id: Ia1182a787f00c2ee9b092a9822a6d5c8404e3b12
Reviewed-on: http://git-master/r/768309
(cherry picked from commit 116260c46c2c0aa077bf2ca57ea2227a56ebd718)
Reviewed-on: http://git-master/r/770473
(cherry picked from commit 2100a3c5f70877dd566c201ffd6c4d033ed819e1)
Signed-off-by: Viraj Karandikar <vkarandikar@nvidia.com>
Reviewed-on: http://git-master/r/781737
Reviewed-by: Sumit Bhattacharya <sumitb@nvidia.com>
This commit is contained in:
Viraj Karandikar
2015-07-08 17:48:44 +05:30
committed by Sameer Pujar
parent 47cc203e9c
commit 1b05a7ad2c

View File

@@ -88,6 +88,7 @@ struct tegra210_adsp_app {
uint32_t connect:1; /* if app is connected to a source */ uint32_t connect:1; /* if app is connected to a source */
uint32_t priority; /* Valid for only APM app */ uint32_t priority; /* Valid for only APM app */
uint32_t min_adsp_clock; /* Min ADSP clock required in MHz */ uint32_t min_adsp_clock; /* Min ADSP clock required in MHz */
spinlock_t lock;
void *private_data; void *private_data;
int (*msg_handler)(struct tegra210_adsp_app *, apm_msg_t *); int (*msg_handler)(struct tegra210_adsp_app *, apm_msg_t *);
}; };
@@ -543,6 +544,8 @@ static int tegra210_adsp_app_init(struct tegra210_adsp *adsp,
return -ENODEV; return -ENODEV;
} }
spin_lock_init(&app->lock);
app->plugin = PLUGIN_SHARED_MEM(app->info->mem.shared); app->plugin = PLUGIN_SHARED_MEM(app->info->mem.shared);
if (IS_APM_IN(app->reg)) { if (IS_APM_IN(app->reg)) {
uint32_t apm_out_reg = APM_OUT_START + uint32_t apm_out_reg = APM_OUT_START +
@@ -819,9 +822,12 @@ static int tegra210_adsp_remove_connection(struct tegra210_adsp *adsp,
static status_t tegra210_adsp_msg_handler(uint32_t msg, void *data) static status_t tegra210_adsp_msg_handler(uint32_t msg, void *data)
{ {
struct tegra210_adsp_app *app = data; struct tegra210_adsp_app *app = data;
unsigned long flags;
apm_msg_t apm_msg; apm_msg_t apm_msg;
int ret = 0; int ret = 0;
spin_lock_irqsave(&app->lock, flags);
switch (msg) { switch (msg) {
case apm_cmd_msg_ready: { case apm_cmd_msg_ready: {
ret = tegra210_adsp_get_msg(app->apm, &apm_msg); ret = tegra210_adsp_get_msg(app->apm, &apm_msg);
@@ -831,13 +837,15 @@ static status_t tegra210_adsp_msg_handler(uint32_t msg, void *data)
} }
if (app->msg_handler) if (app->msg_handler)
return app->msg_handler(app, &apm_msg); ret = app->msg_handler(app, &apm_msg);
} }
break; break;
default: default:
pr_err("Unsupported mailbox msg %d.", msg); pr_err("Unsupported mailbox msg %d.", msg);
} }
return 0;
spin_unlock_irqrestore(&app->lock, flags);
return ret;
} }
static int tegra210_adsp_pcm_msg_handler(struct tegra210_adsp_app *app, static int tegra210_adsp_pcm_msg_handler(struct tegra210_adsp_app *app,
@@ -943,6 +951,7 @@ static int tegra210_adsp_compr_open(struct snd_compr_stream *cstream)
static int tegra210_adsp_compr_free(struct snd_compr_stream *cstream) static int tegra210_adsp_compr_free(struct snd_compr_stream *cstream)
{ {
struct tegra210_adsp_compr_rtd *prtd = cstream->runtime->private_data; struct tegra210_adsp_compr_rtd *prtd = cstream->runtime->private_data;
unsigned long flags;
if (!prtd) if (!prtd)
return -ENODEV; return -ENODEV;
@@ -954,6 +963,13 @@ static int tegra210_adsp_compr_free(struct snd_compr_stream *cstream)
tegra210_adsp_deallocate_dma_buffer(&prtd->buf); tegra210_adsp_deallocate_dma_buffer(&prtd->buf);
spin_lock_irqsave(&prtd->fe_apm->lock, flags);
/* Reset msg handler to disable msg processing */
prtd->fe_apm->msg_handler = NULL;
spin_unlock_irqrestore(&prtd->fe_apm->lock, flags);
prtd->fe_apm->fe = 0; prtd->fe_apm->fe = 0;
cstream->runtime->private_data = NULL; cstream->runtime->private_data = NULL;
devm_kfree(prtd->dev, prtd); devm_kfree(prtd->dev, prtd);
@@ -1276,6 +1292,7 @@ static int tegra210_adsp_pcm_open(struct snd_pcm_substream *substream)
static int tegra210_adsp_pcm_close(struct snd_pcm_substream *substream) static int tegra210_adsp_pcm_close(struct snd_pcm_substream *substream)
{ {
struct tegra210_adsp_pcm_rtd *prtd = substream->runtime->private_data; struct tegra210_adsp_pcm_rtd *prtd = substream->runtime->private_data;
unsigned long flags;
dev_vdbg(prtd->dev, "%s", __func__); dev_vdbg(prtd->dev, "%s", __func__);
@@ -1283,6 +1300,13 @@ static int tegra210_adsp_pcm_close(struct snd_pcm_substream *substream)
tegra210_adsp_send_reset_msg(prtd->fe_apm, tegra210_adsp_send_reset_msg(prtd->fe_apm,
TEGRA210_ADSP_MSG_FLAG_SEND); TEGRA210_ADSP_MSG_FLAG_SEND);
spin_lock_irqsave(&prtd->fe_apm->lock, flags);
/* Reset msg handler to disable msg processing */
prtd->fe_apm->msg_handler = NULL;
spin_unlock_irqrestore(&prtd->fe_apm->lock, flags);
prtd->fe_apm->fe = 1; prtd->fe_apm->fe = 1;
substream->runtime->private_data = NULL; substream->runtime->private_data = NULL;
devm_kfree(prtd->dev, prtd); devm_kfree(prtd->dev, prtd);