mirror of
https://github.com/BobTheBlinker/android_kernel_motorola_sm6375.git
synced 2026-10-08 12:58:12 -04:00
Merge "msm: ipa3: Fix to race condition in updating current polling state"
This commit is contained in:
commit
4c92e30fe3
2 changed files with 92 additions and 36 deletions
|
|
@ -769,6 +769,26 @@ static int ipa3_handle_rx_core(struct ipa3_sys_context *sys, bool process_all,
|
|||
return cnt;
|
||||
}
|
||||
|
||||
/**
|
||||
* __ipa3_update_curr_poll_state -> update current polling for default wan and
|
||||
* coalescing pipe.
|
||||
* In RSC/RSB enabled cases using common event ring, so both the pipe
|
||||
* polling state should be in sync.
|
||||
*/
|
||||
void __ipa3_update_curr_poll_state(enum ipa_client_type client, int state)
|
||||
{
|
||||
int ep_idx = IPA_EP_NOT_ALLOCATED;
|
||||
|
||||
if (client == IPA_CLIENT_APPS_WAN_COAL_CONS)
|
||||
ep_idx = ipa3_get_ep_mapping(IPA_CLIENT_APPS_WAN_CONS);
|
||||
if (client == IPA_CLIENT_APPS_WAN_CONS)
|
||||
ep_idx = ipa3_get_ep_mapping(IPA_CLIENT_APPS_WAN_COAL_CONS);
|
||||
|
||||
if (ep_idx != IPA_EP_NOT_ALLOCATED && ipa3_ctx->ep[ep_idx].sys)
|
||||
atomic_set(&ipa3_ctx->ep[ep_idx].sys->curr_polling_state,
|
||||
state);
|
||||
}
|
||||
|
||||
/**
|
||||
* ipa3_rx_switch_to_intr_mode() - Operate the Rx data path in interrupt mode
|
||||
*/
|
||||
|
|
@ -777,6 +797,8 @@ static int ipa3_rx_switch_to_intr_mode(struct ipa3_sys_context *sys)
|
|||
int ret;
|
||||
|
||||
atomic_set(&sys->curr_polling_state, 0);
|
||||
__ipa3_update_curr_poll_state(sys->ep->client, 0);
|
||||
|
||||
ipa3_dec_release_wakelock();
|
||||
ret = gsi_config_channel_mode(sys->ep->gsi_chan_hdl,
|
||||
GSI_CHAN_MODE_CALLBACK);
|
||||
|
|
@ -785,8 +807,10 @@ static int ipa3_rx_switch_to_intr_mode(struct ipa3_sys_context *sys)
|
|||
if (ret == -GSI_STATUS_PENDING_IRQ) {
|
||||
ipa3_inc_acquire_wakelock();
|
||||
atomic_set(&sys->curr_polling_state, 1);
|
||||
__ipa3_update_curr_poll_state(sys->ep->client, 1);
|
||||
} else {
|
||||
IPAERR("Failed to switch to intr mode.\n");
|
||||
IPAERR("Failed to switch to intr mode %d ch_id %d\n",
|
||||
sys->curr_polling_state, sys->ep->gsi_chan_hdl);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -4290,6 +4314,8 @@ void __ipa_gsi_irq_rx_scedule_poll(struct ipa3_sys_context *sys)
|
|||
bool clk_off;
|
||||
|
||||
atomic_set(&sys->curr_polling_state, 1);
|
||||
__ipa3_update_curr_poll_state(sys->ep->client, 1);
|
||||
|
||||
ipa3_inc_acquire_wakelock();
|
||||
|
||||
/*
|
||||
|
|
|
|||
|
|
@ -7988,7 +7988,7 @@ int ipa3_stop_gsi_channel(u32 clnt_hdl)
|
|||
|
||||
static int _ipa_suspend_resume_pipe(enum ipa_client_type client, bool suspend)
|
||||
{
|
||||
int ipa_ep_idx;
|
||||
int ipa_ep_idx, coal_ep_idx;
|
||||
struct ipa3_ep_context *ep;
|
||||
int res;
|
||||
|
||||
|
|
@ -8007,16 +8007,16 @@ static int _ipa_suspend_resume_pipe(enum ipa_client_type client, bool suspend)
|
|||
if (!ep->valid)
|
||||
return 0;
|
||||
|
||||
coal_ep_idx = ipa3_get_ep_mapping(IPA_CLIENT_APPS_WAN_COAL_CONS);
|
||||
|
||||
IPADBG("%s pipe %d\n", suspend ? "suspend" : "unsuspend", ipa_ep_idx);
|
||||
|
||||
/*
|
||||
* move the channel to callback mode.
|
||||
* This needs to happen before starting the channel to make
|
||||
* sure we don't loose any interrupt
|
||||
* Configure the callback mode only one time after starting the channel
|
||||
* otherwise observing IEOB interrupt received before configure callmode
|
||||
* second time. It was leading race condition in updating current
|
||||
* polling state.
|
||||
*/
|
||||
if (!suspend && !atomic_read(&ep->sys->curr_polling_state) &&
|
||||
!IPA_CLIENT_IS_APPS_PROD(client))
|
||||
gsi_config_channel_mode(ep->gsi_chan_hdl,
|
||||
GSI_CHAN_MODE_CALLBACK);
|
||||
|
||||
if (suspend) {
|
||||
res = __ipa3_stop_gsi_channel(ipa_ep_idx);
|
||||
|
|
@ -8033,7 +8033,17 @@ static int _ipa_suspend_resume_pipe(enum ipa_client_type client, bool suspend)
|
|||
}
|
||||
|
||||
/* Apps prod pipes use common event ring so cannot configure mode*/
|
||||
if (IPA_CLIENT_IS_APPS_PROD(client))
|
||||
|
||||
/*
|
||||
* Skipping to configure mode for default wan pipe,
|
||||
* as both pipes using commong event ring. if both pipes
|
||||
* configure same event ring observing race condition in
|
||||
* updating current polling state.
|
||||
*/
|
||||
|
||||
if (IPA_CLIENT_IS_APPS_PROD(client) ||
|
||||
(client == IPA_CLIENT_APPS_WAN_CONS &&
|
||||
coal_ep_idx != IPA_EP_NOT_ALLOCATED))
|
||||
return 0;
|
||||
|
||||
if (suspend) {
|
||||
|
|
@ -8089,18 +8099,29 @@ void ipa3_force_close_coal(void)
|
|||
int ipa3_suspend_apps_pipes(bool suspend)
|
||||
{
|
||||
int res;
|
||||
enum ipa_client_type client;
|
||||
|
||||
if (suspend)
|
||||
ipa3_force_close_coal();
|
||||
|
||||
for (client = 0; client < IPA_CLIENT_MAX; client++) {
|
||||
if (IPA_CLIENT_IS_APPS_CONS(client)) {
|
||||
res = _ipa_suspend_resume_pipe(client, suspend);
|
||||
if (res)
|
||||
goto undo_cons;
|
||||
}
|
||||
}
|
||||
/* As per HPG first need start/stop coalescing channel
|
||||
* then default one. Coalescing client number was greater then
|
||||
* default one so starting the last client.
|
||||
*/
|
||||
res = _ipa_suspend_resume_pipe(IPA_CLIENT_APPS_WAN_COAL_CONS, suspend);
|
||||
if (res == -EAGAIN)
|
||||
goto undo_coal_cons;
|
||||
|
||||
res = _ipa_suspend_resume_pipe(IPA_CLIENT_APPS_WAN_CONS, suspend);
|
||||
if (res == -EAGAIN)
|
||||
goto undo_wan_cons;
|
||||
|
||||
res = _ipa_suspend_resume_pipe(IPA_CLIENT_APPS_LAN_CONS, suspend);
|
||||
if (res == -EAGAIN)
|
||||
goto undo_lan_cons;
|
||||
|
||||
res = _ipa_suspend_resume_pipe(IPA_CLIENT_ODL_DPL_CONS, suspend);
|
||||
if (res == -EAGAIN)
|
||||
goto undo_odl_cons;
|
||||
|
||||
if (suspend) {
|
||||
struct ipahal_reg_tx_wrapper tx;
|
||||
|
|
@ -8116,7 +8137,7 @@ int ipa3_suspend_apps_pipes(bool suspend)
|
|||
IPADBG("COAL frame is open 0x%x\n",
|
||||
tx.coal_slave_open_frame);
|
||||
res = -EAGAIN;
|
||||
goto undo_cons;
|
||||
goto undo_odl_cons;
|
||||
}
|
||||
|
||||
usleep_range(IPA_TAG_SLEEP_MIN_USEC, IPA_TAG_SLEEP_MAX_USEC);
|
||||
|
|
@ -8125,28 +8146,37 @@ int ipa3_suspend_apps_pipes(bool suspend)
|
|||
ipa3_ctx->ee);
|
||||
if (res) {
|
||||
IPADBG("suspend irq is pending 0x%x\n", res);
|
||||
goto undo_cons;
|
||||
goto undo_odl_cons;
|
||||
}
|
||||
}
|
||||
do_prod:
|
||||
for (client = 0; client < IPA_CLIENT_MAX; client++) {
|
||||
if (IPA_CLIENT_IS_APPS_PROD(client)) {
|
||||
res = _ipa_suspend_resume_pipe(client, suspend);
|
||||
if (res)
|
||||
goto undo_prod;
|
||||
}
|
||||
}
|
||||
res = _ipa_suspend_resume_pipe(IPA_CLIENT_APPS_LAN_PROD, suspend);
|
||||
if (res == -EAGAIN)
|
||||
goto undo_lan_prod;
|
||||
res = _ipa_suspend_resume_pipe(IPA_CLIENT_APPS_WAN_PROD, suspend);
|
||||
if (res == -EAGAIN)
|
||||
goto undo_wan_prod;
|
||||
|
||||
return 0;
|
||||
undo_prod:
|
||||
for (; client <= IPA_CLIENT_MAX && client >= 0; client--)
|
||||
if (IPA_CLIENT_IS_APPS_PROD(client))
|
||||
_ipa_suspend_resume_pipe(client, !suspend);
|
||||
client = IPA_CLIENT_MAX;
|
||||
undo_cons:
|
||||
for (; client <= IPA_CLIENT_MAX && client >= 0; client--)
|
||||
if (IPA_CLIENT_IS_APPS_CONS(client))
|
||||
_ipa_suspend_resume_pipe(client, !suspend);
|
||||
|
||||
undo_wan_prod:
|
||||
_ipa_suspend_resume_pipe(IPA_CLIENT_APPS_WAN_PROD, !suspend);
|
||||
|
||||
undo_lan_prod:
|
||||
_ipa_suspend_resume_pipe(IPA_CLIENT_APPS_LAN_PROD, !suspend);
|
||||
|
||||
undo_odl_cons:
|
||||
_ipa_suspend_resume_pipe(IPA_CLIENT_ODL_DPL_CONS, !suspend);
|
||||
undo_lan_cons:
|
||||
_ipa_suspend_resume_pipe(IPA_CLIENT_APPS_LAN_CONS, !suspend);
|
||||
undo_wan_cons:
|
||||
_ipa_suspend_resume_pipe(IPA_CLIENT_APPS_WAN_COAL_CONS, !suspend);
|
||||
_ipa_suspend_resume_pipe(IPA_CLIENT_APPS_WAN_CONS, !suspend);
|
||||
return res;
|
||||
|
||||
undo_coal_cons:
|
||||
_ipa_suspend_resume_pipe(IPA_CLIENT_APPS_WAN_COAL_CONS, !suspend);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue