From 6412ec5011468b8a273b0a18490944fe843fd424 Mon Sep 17 00:00:00 2001 From: Mohammed Javid Date: Sat, 16 Sep 2017 00:39:46 +0530 Subject: [PATCH] msm: ipa: Set ep delay on rmnet/mbim tether pipe As soon we start a gsi channel, there is a chance of getting packets from USB to IPA before even we setup flt/rt fules. To avoid this race condition set ep delay before start of gsi channel in case of rmnet/mbim tether. This delay should be cleared by Q6 once required flt/rt rules in place. Change-Id: Iac16ba067d4454ffd3f191009ea6eb5998473977 Signed-off-by: Mohammed Javid --- drivers/platform/msm/ipa/ipa_v3/ipa_client.c | 61 ++++++++++++++++++++++++++-- drivers/platform/msm/ipa/ipa_v3/ipa_i.h | 1 + 2 files changed, 59 insertions(+), 3 deletions(-) diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa_client.c b/drivers/platform/msm/ipa/ipa_v3/ipa_client.c index 8c6bd48cfb2c..97b9f04f51de 100644 --- a/drivers/platform/msm/ipa/ipa_v3/ipa_client.c +++ b/drivers/platform/msm/ipa/ipa_v3/ipa_client.c @@ -1353,6 +1353,7 @@ int ipa3_set_usb_max_packet_size( return 0; } +/* This function called as part of usb pipe resume */ int ipa3_xdci_connect(u32 clnt_hdl) { int result; @@ -1392,11 +1393,14 @@ exit: return result; } + +/* This function called as part of usb pipe connect */ int ipa3_xdci_start(u32 clnt_hdl, u8 xferrscidx, bool xferrscidx_valid) { struct ipa3_ep_context *ep; int result = -EFAULT; enum gsi_status gsi_res; + struct ipa_ep_cfg_ctrl ep_cfg_ctrl; IPADBG("entry\n"); if (clnt_hdl >= ipa3_ctx->ipa_num_pipes || @@ -1418,6 +1422,22 @@ int ipa3_xdci_start(u32 clnt_hdl, u8 xferrscidx, bool xferrscidx_valid) goto write_chan_scratch_fail; } } + + if (IPA_CLIENT_IS_PROD(ep->client) && ep->skip_ep_cfg) { + memset(&ep_cfg_ctrl, 0, sizeof(struct ipa_ep_cfg_ctrl)); + ep_cfg_ctrl.ipa_ep_delay = true; + ep->ep_delay_set = true; + + result = ipa3_cfg_ep_ctrl(clnt_hdl, &ep_cfg_ctrl); + if (result) + IPAERR("client (ep: %d) failed result=%d\n", + clnt_hdl, result); + else + IPADBG("client (ep: %d) success\n", clnt_hdl); + } else { + ep->ep_delay_set = false; + } + gsi_res = gsi_start_channel(ep->gsi_chan_hdl); if (gsi_res != GSI_STATUS_SUCCESS) { IPAERR("Error starting channel: %d\n", gsi_res); @@ -1622,13 +1642,15 @@ static int ipa3_xdci_stop_gsi_ch_brute_force(u32 clnt_hdl, /* Clocks should be voted for before invoking this function */ static int ipa3_stop_ul_chan_with_data_drain(u32 qmi_req_id, - u32 source_pipe_bitmask, bool should_force_clear, u32 clnt_hdl) + u32 source_pipe_bitmask, bool should_force_clear, u32 clnt_hdl, + bool remove_delay) { int result; bool is_empty = false; int i; bool stop_in_proc; struct ipa3_ep_context *ep; + struct ipa_ep_cfg_ctrl ep_cfg_ctrl; if (clnt_hdl >= ipa3_ctx->ipa_num_pipes || ipa3_ctx->ep[clnt_hdl].valid == 0) { @@ -1649,6 +1671,22 @@ static int ipa3_stop_ul_chan_with_data_drain(u32 qmi_req_id, if (!stop_in_proc) goto exit; + if (remove_delay && ep->ep_delay_set == true) { + memset(&ep_cfg_ctrl, 0, sizeof(struct ipa_ep_cfg_ctrl)); + ep_cfg_ctrl.ipa_ep_delay = false; + result = ipa3_cfg_ep_ctrl(clnt_hdl, + &ep_cfg_ctrl); + if (result) { + IPAERR + ("client (ep: %d) failed to remove delay result=%d\n", + clnt_hdl, result); + } else { + IPADBG("client (ep: %d) delay removed\n", + clnt_hdl); + ep->ep_delay_set = false; + } + } + /* if stop_in_proc, lets wait for emptiness */ for (i = 0; i < IPA_POLL_FOR_EMPTINESS_NUM; i++) { result = ipa3_is_xdci_channel_empty(ep, &is_empty); @@ -1714,6 +1752,21 @@ disable_force_clear_and_exit: if (should_force_clear) ipa3_disable_force_clear(qmi_req_id); exit: + if (remove_delay && ep->ep_delay_set == true) { + memset(&ep_cfg_ctrl, 0, sizeof(struct ipa_ep_cfg_ctrl)); + ep_cfg_ctrl.ipa_ep_delay = false; + result = ipa3_cfg_ep_ctrl(clnt_hdl, + &ep_cfg_ctrl); + if (result) { + IPAERR + ("client (ep: %d) failed to remove delay result=%d\n", + clnt_hdl, result); + } else { + IPADBG("client (ep: %d) delay removed\n", + clnt_hdl); + ep->ep_delay_set = false; + } + } return result; } @@ -1743,7 +1796,8 @@ int ipa3_xdci_disconnect(u32 clnt_hdl, bool should_force_clear, u32 qmi_req_id) source_pipe_bitmask = 1 << ipa3_get_ep_mapping(ep->client); result = ipa3_stop_ul_chan_with_data_drain(qmi_req_id, - source_pipe_bitmask, should_force_clear, clnt_hdl); + source_pipe_bitmask, should_force_clear, clnt_hdl, + true); if (result) { IPAERR("Fail to stop UL channel with data drain\n"); WARN_ON(1); @@ -1918,7 +1972,8 @@ int ipa3_xdci_suspend(u32 ul_clnt_hdl, u32 dl_clnt_hdl, if (!is_dpl) { source_pipe_bitmask = 1 << ipa3_get_ep_mapping(ul_ep->client); result = ipa3_stop_ul_chan_with_data_drain(qmi_req_id, - source_pipe_bitmask, should_force_clear, ul_clnt_hdl); + source_pipe_bitmask, should_force_clear, ul_clnt_hdl, + false); if (result) { IPAERR("Error stopping UL channel: result = %d\n", result); diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa_i.h b/drivers/platform/msm/ipa/ipa_v3/ipa_i.h index 89c7b66b98d6..8e6db8f63fc1 100644 --- a/drivers/platform/msm/ipa/ipa_v3/ipa_i.h +++ b/drivers/platform/msm/ipa/ipa_v3/ipa_i.h @@ -577,6 +577,7 @@ struct ipa3_ep_context { bool switch_to_intr; int inactive_cycles; u32 eot_in_poll_err; + bool ep_delay_set; /* sys MUST be the last element of this struct */ struct ipa3_sys_context *sys; -- 2.11.0