adsp: fix tlv read write issues

Change fixes problems caused in tlv read and write
synchronization with other messages
- Add separate spinlock completions for tlv read
- Add separate spinlock completions for tlv write
- Add separate ack for raw (tlv) messages
- Print msgq indexes when queue or dequeue fails

Bug 2420196

Change-Id: I405e3a9939ec804dc65875d900ba635d2dc15ee3
Signed-off-by: Hariharan Sivaraman <hariharans@nvidia.com>
Reviewed-on: https://git-master.nvidia.com/r/1975072
(cherry picked from commit 1df184d908c84c8f4e15b48cdd9ada90da313169)
Signed-off-by: Niranjan Dighe <ndighe@nvidia.com>
Reviewed-on: https://git-master.nvidia.com/r/1986443
Reviewed-by: svc-mobile-coverity <svc-mobile-coverity@nvidia.com>
GVS: Gerrit_Virtual_Submit
Reviewed-by: Uday Gupta <udayg@nvidia.com>
Reviewed-by: Nitin Pai <npai@nvidia.com>
Reviewed-by: mobile promotions <svcmobile_promotions@nvidia.com>
Tested-by: mobile promotions <svcmobile_promotions@nvidia.com>
This commit is contained in:
Niranjan Dighe
2019-03-01 16:10:07 +05:30
committed by Sameer Pujar
parent 4a6ee45df7
commit 503eb55823

View File

@@ -122,6 +122,8 @@ struct tegra210_adsp_app {
apm_shared_state_t *apm; /* For a plugin it stores parent apm data */
struct nvadsp_mbox apm_mbox;
struct completion *msg_complete; /* For ADSP ack wait */
struct completion *raw_msg_read_complete;
struct completion *raw_msg_write_complete;
uint32_t reg;
uint32_t adma_chan; /* Valid for only ADMA app */
uint32_t fe:1; /* Whether the app is used as a FE APM */
@@ -549,6 +551,7 @@ static int tegra210_adsp_send_raw_data_msg(struct tegra210_adsp_app *app,
{
int ret = 0;
struct tegra210_adsp_app *apm = app;
unsigned long flag;
/* Find parent APM to wait for ACK*/
if (!IS_APM_IN(apm->reg)) {
@@ -562,12 +565,15 @@ static int tegra210_adsp_send_raw_data_msg(struct tegra210_adsp_app *app,
return ret;
}
}
reinit_completion(apm->msg_complete);
apm_msg->msg.call_params.method |= NVFX_APM_METHOD_ACK_BIT;
spin_lock_irqsave(&apm->apm_msg_queue_lock, flag);
ret = msgq_queue_message(&app->apm->msgq_recv.msgq, &apm_msg->msgq_msg);
if (ret < 0)
spin_unlock_irqrestore(&apm->apm_msg_queue_lock, flag);
if (ret < 0) {
pr_err("%s failed: msgq full\n", __func__);
return ret;
}
ret = nvadsp_mbox_send(&app->apm_mbox, apm_cmd_raw_data_ready,
NVADSP_MBOX_SMSG, true, 100);
@@ -577,7 +583,7 @@ static int tegra210_adsp_send_raw_data_msg(struct tegra210_adsp_app *app,
}
ret = wait_for_completion_interruptible_timeout(
apm->msg_complete,
apm->raw_msg_write_complete,
msecs_to_jiffies(ADSP_RESPONSE_TIMEOUT));
if (WARN_ON(ret == 0))
pr_err("%s: ACK timed out %d\n", __func__, app->reg);
@@ -873,7 +879,27 @@ static int tegra210_adsp_app_init(struct tegra210_adsp *adsp,
return -ENOMEM;
}
app->raw_msg_read_complete = devm_kzalloc(adsp->dev,
sizeof(struct completion), GFP_KERNEL);
if (app->raw_msg_read_complete == NULL) {
dev_err(adsp->dev,
"Failed to allocate read completion struct.");
return -ENOMEM;
}
app->raw_msg_write_complete = devm_kzalloc(adsp->dev,
sizeof(struct completion), GFP_KERNEL);
if (app->raw_msg_write_complete == NULL) {
dev_err(adsp->dev,
"Failed to allocate read completion struct.");
return -ENOMEM;
}
init_completion(app->msg_complete);
init_completion(app->raw_msg_read_complete);
init_completion(app->raw_msg_write_complete);
ret = nvadsp_app_start(app->info);
if (ret < 0) {
dev_err(adsp->dev, "Failed to start adsp app");
@@ -888,6 +914,8 @@ static int tegra210_adsp_app_init(struct tegra210_adsp *adsp,
apm_out->adsp = app->adsp;
apm_out->apm_mbox = app->apm_mbox;
apm_out->msg_complete = app->msg_complete;
apm_out->raw_msg_read_complete = app->raw_msg_read_complete;
apm_out->raw_msg_write_complete = app->raw_msg_write_complete;
ret = tegra210_adsp_send_app_priority(app);
if (ret < 0) {
@@ -1224,7 +1252,7 @@ static status_t tegra210_adsp_msg_handler(uint32_t msg, void *data)
ret = tegra210_adsp_get_raw_data_msg(app->apm, raw_msg);
if (ret < 0) {
pr_err("Dequeue failed %d.", ret);
pr_err("Dequeue failed raw %d.", ret);
kfree(raw_msg);
break;
}
@@ -1232,7 +1260,7 @@ static status_t tegra210_adsp_msg_handler(uint32_t msg, void *data)
raw_msg->msg.fx_raw_data_params.data,
sizeof(app->read_data.data));
kfree(raw_msg);
complete(app->msg_complete);
complete(app->raw_msg_read_complete);
}
break;
default:
@@ -1250,6 +1278,9 @@ static int tegra210_adsp_app_default_msg_handler(struct tegra210_adsp_app *app,
case nvfx_apm_method_ack:
complete(app->msg_complete);
break;
case nvfx_apm_method_raw_ack:
complete(app->raw_msg_write_complete);
break;
case nvfx_apm_method_fx_error_event:
tegra210_adsp_nl_send_msg(app->adsp,
&apm_msg->msg.fx_error_event_params);
@@ -4008,7 +4039,6 @@ static int tegra210_adsp_tlv_callback(struct snd_kcontrol *kcontrol,
while (!IS_APM_IN(src))
src = tegra210_adsp_get_source(adsp, src);
apm = &adsp->apps[src];
reinit_completion(apm->msg_complete);
ret = pm_runtime_get_sync(adsp->dev);
if (ret < 0) {
dev_err(adsp->dev, "%s pm_runtime_get_sync error 0x%x\n",
@@ -4017,8 +4047,14 @@ static int tegra210_adsp_tlv_callback(struct snd_kcontrol *kcontrol,
}
ret = tegra210_adsp_send_data_request_msg(app, count,
TEGRA210_ADSP_MSG_FLAG_SEND);
if (ret < 0) {
pm_runtime_put(adsp->dev);
dev_err(adsp->dev, "Raw read request dropped\n");
ret = -ETIMEDOUT;
goto end;
}
ret = wait_for_completion_interruptible_timeout(
apm->msg_complete,
apm->raw_msg_read_complete,
msecs_to_jiffies(ADSP_RESPONSE_TIMEOUT));
pm_runtime_put(adsp->dev);
if (ret <= 0) {
@@ -4426,8 +4462,8 @@ static int tegra210_adsp_audio_platform_probe(struct platform_device *pdev)
uint32_t adma_ch_cnt = TEGRA210_ADSP_ADMA_CHANNEL_COUNT;
char plugin_info[20], apm_info[20];
struct netlink_kernel_cfg cfg = {
.input = tegra210_adsp_nl_recv_msg,
};
.input = tegra210_adsp_nl_recv_msg,
};
pr_info("tegra210_adsp_audio_platform_probe: platform probe started\n");