diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa_dp.c b/drivers/platform/msm/ipa/ipa_v3/ipa_dp.c index dcf0b6a006a6..4f88f4732168 100644 --- a/drivers/platform/msm/ipa/ipa_v3/ipa_dp.c +++ b/drivers/platform/msm/ipa/ipa_v3/ipa_dp.c @@ -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(); /* diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa_utils.c b/drivers/platform/msm/ipa/ipa_v3/ipa_utils.c index a36b94f92050..491c15263612 100644 --- a/drivers/platform/msm/ipa/ipa_v3/ipa_utils.c +++ b/drivers/platform/msm/ipa/ipa_v3/ipa_utils.c @@ -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; }