tegra: platform: dce: Fix race condition on fgpa

Resolve race condition where DCE Firmware could
potentially send an IVC signal before even CPU
driver starts listening for it.

This fix makes sure that the driver need not wait
if it has been signalled already by Firmware.

Jira TDS-6381

Change-Id: I3d6dd1f93ce36f9e44b7157f70c0aad099f2d561
Signed-off-by: Arun Swain <arswain@nvidia.com>
Reviewed-on: https://git-master.nvidia.com/r/c/linux-t23x/+/2394468
Tested-by: Santosh Galma <galmar@nvidia.com>
Tested-by: mobile promotions <svcmobile_promotions@nvidia.com>
Reviewed-by: Santosh Galma <galmar@nvidia.com>
Reviewed-by: Automatic_Commit_Validation_User
Reviewed-by: Mahesh Kumar <mahkumar@nvidia.com>
Reviewed-by: mobile promotions <svcmobile_promotions@nvidia.com>
GVS: Gerrit_Virtual_Submit
This commit is contained in:
Arun Swain
2020-08-04 23:18:31 -07:00
committed by Laxman Dewangan
parent ef3f18c398
commit ea84c95dbf
2 changed files with 14 additions and 17 deletions

View File

@@ -174,7 +174,7 @@ static void dce_ipc_signal_target(struct ivc *ivc)
ch->signal.notify(ch->d, &ch->signal.to_d);
}
static int dce_ipc_wait(struct tegra_dce *d, u32 w_type, u32 ch_type)
static int _dce_ipc_wait(struct tegra_dce *d, u32 w_type, u32 ch_type)
{
int ret = 0;
struct dce_ipc_channel *ch;
@@ -191,8 +191,6 @@ static int dce_ipc_wait(struct tegra_dce *d, u32 w_type, u32 ch_type)
goto out;
}
dce_mutex_lock(&ch->lock);
ch->w_type = w_type;
dce_mutex_unlock(&ch->lock);
@@ -207,7 +205,6 @@ static int dce_ipc_wait(struct tegra_dce *d, u32 w_type, u32 ch_type)
ch->w_type = DCE_IPC_WAIT_TYPE_INVALID;
out:
dce_mutex_unlock(&ch->lock);
return ret;
}
@@ -429,11 +426,7 @@ void dce_ipc_channel_reset(struct tegra_dce *d, u32 ch_type)
ch->flags &= ~DCE_IPC_CHANNEL_SYNCED;
dce_mutex_unlock(&ch->lock);
dce_ipc_wait(ch->d, DCE_IPC_WAIT_TYPE_SYNC, ch_type);
dce_mutex_lock(&ch->lock);
_dce_ipc_wait(ch->d, DCE_IPC_WAIT_TYPE_SYNC, ch_type);
ch->flags |= DCE_IPC_CHANNEL_SYNCED;
@@ -651,7 +644,9 @@ int dce_ipc_send_message_sync(struct tegra_dce *d, u32 ch_type,
goto done;
}
ret = dce_ipc_wait(ch->d, DCE_IPC_WAIT_TYPE_RPC, ch_type);
dce_mutex_lock(&ch->lock);
ret = _dce_ipc_wait(ch->d, DCE_IPC_WAIT_TYPE_RPC, ch_type);
dce_mutex_unlock(&ch->lock);
if (ret) {
dce_err(ch->d, "Error in waiting for ack");
goto done;

View File

@@ -53,8 +53,12 @@ void dce_worker_thread_wait(struct tegra_dce *d,
enum dce_worker_state new_state;
struct dce_worker_info *w = &d->wrk_info;
dce_mutex_lock(&w->lock);
if (w->state_changed == true) {
w->state_changed = false;
dce_warn(d, "Unexpected state_changed value");
dce_mutex_unlock(&w->lock);
return;
}
@@ -81,13 +85,14 @@ void dce_worker_thread_wait(struct tegra_dce *d,
return;
}
dce_mutex_lock(&w->lock);
w->c_state = new_state;
dce_mutex_unlock(&w->lock);
if (new_state == STATE_DCE_WORKER_BOOT_WAIT)
timeout_val_ms = 1000;
dce_mutex_unlock(&w->lock);
ret = DCE_COND_WAIT_INTERRUPTIBLE(&w->cond,
dce_worker_wakeup_cond(d),
timeout_val_ms);
@@ -119,18 +124,16 @@ void dce_worker_thread_wakeup(struct tegra_dce *d,
struct dce_worker_info *w = &d->wrk_info;
enum dce_worker_state new_state = w->c_state;
if (w->state_changed == true) {
dce_mutex_lock(&w->lock);
if (w->state_changed == true)
dce_warn(d, "Unexpected state_changed value");
dce_mutex_unlock(&w->lock);
return;
}
switch (event) {
case EVENT_ID_DCE_IPC_SIGNAL_RECEIVED:
if (w->c_state != STATE_DCE_WORKER_WFI) {
dce_warn(d, "Unexpected wakeup event rcvd: [%d]. Cur State: [%d]",
event, w->c_state);
return;
}
new_state = STATE_DCE_WORKER_IDLE;
break;
@@ -160,7 +163,6 @@ void dce_worker_thread_wakeup(struct tegra_dce *d,
return;
}
dce_mutex_lock(&w->lock);
w->c_state = new_state;
w->state_changed = true;
dce_mutex_unlock(&w->lock);