diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa_client.c b/drivers/platform/msm/ipa/ipa_v3/ipa_client.c index 26bd180624f1..00bfbf84c75a 100644 --- a/drivers/platform/msm/ipa/ipa_v3/ipa_client.c +++ b/drivers/platform/msm/ipa/ipa_v3/ipa_client.c @@ -1474,7 +1474,7 @@ static int ipa3_is_xdci_channel_empty(struct ipa3_ep_context *ep, return 0; } -static int ipa3_enable_force_clear(u32 request_id, bool throttle_source, +int ipa3_enable_force_clear(u32 request_id, bool throttle_source, u32 source_pipe_bitmask) { struct ipa_enable_force_clear_datapath_req_msg_v01 req; @@ -1497,7 +1497,7 @@ static int ipa3_enable_force_clear(u32 request_id, bool throttle_source, return 0; } -static int ipa3_disable_force_clear(u32 request_id) +int ipa3_disable_force_clear(u32 request_id) { struct ipa_disable_force_clear_datapath_req_msg_v01 req; int result; diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa_i.h b/drivers/platform/msm/ipa/ipa_v3/ipa_i.h index b4f447f56d1c..8aeaad612065 100644 --- a/drivers/platform/msm/ipa/ipa_v3/ipa_i.h +++ b/drivers/platform/msm/ipa/ipa_v3/ipa_i.h @@ -1917,6 +1917,9 @@ int ipa3_alloc_rule_id(struct idr *rule_ids); int ipa3_id_alloc(void *ptr); void *ipa3_id_find(u32 id); void ipa3_id_remove(u32 id); +int ipa3_enable_force_clear(u32 request_id, bool throttle_source, + u32 source_pipe_bitmask); +int ipa3_disable_force_clear(u32 request_id); int ipa3_set_required_perf_profile(enum ipa_voltage_level floor_voltage, u32 bandwidth_mbps); diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa_uc_wdi.c b/drivers/platform/msm/ipa/ipa_v3/ipa_uc_wdi.c index 8cb6935cd720..41bb8651f69c 100644 --- a/drivers/platform/msm/ipa/ipa_v3/ipa_uc_wdi.c +++ b/drivers/platform/msm/ipa/ipa_v3/ipa_uc_wdi.c @@ -1370,6 +1370,7 @@ int ipa3_disable_wdi_pipe(u32 clnt_hdl) u32 prod_hdl; int i; u32 rx_door_bell_value; + u32 source_pipe_bitmask = 0; if (clnt_hdl >= ipa3_ctx->ipa_num_pipes || ipa3_ctx->ep[clnt_hdl].valid == 0) { @@ -1405,6 +1406,17 @@ int ipa3_disable_wdi_pipe(u32 clnt_hdl) * holb on IPA Producer pipe */ if (IPA_CLIENT_IS_PROD(ep->client)) { + /* enable force clear */ + IPADBG("Stopping PROD channel - hdl=%d clnt=%d\n", + clnt_hdl, ep->client); + source_pipe_bitmask = 1 << + ipa3_get_ep_mapping(ep->client); + result = ipa3_enable_force_clear(clnt_hdl, false, + source_pipe_bitmask); + if (result) + goto uc_timeout; + + /* remove delay on wlan-prod pipe*/ memset(&ep_cfg_ctrl, 0 , sizeof(struct ipa_ep_cfg_ctrl)); ipa3_cfg_ep_ctrl(clnt_hdl, &ep_cfg_ctrl); @@ -1437,7 +1449,7 @@ int ipa3_disable_wdi_pipe(u32 clnt_hdl) rx_door_bell_value, *ipa3_ctx->uc_ctx.rdy_ring_rp_va, *ipa3_ctx->uc_ctx.rdy_comp_ring_wp_va); - if (rx_door_bell_value != + if (*ipa3_ctx->uc_ctx.rdy_ring_rp_va != *ipa3_ctx->uc_ctx.rdy_comp_ring_wp_va) { usleep_range(IPA_UC_WAIT_MIN_SLEEP, IPA_UC_WAII_MAX_SLEEP); @@ -1470,11 +1482,14 @@ int ipa3_disable_wdi_pipe(u32 clnt_hdl) memset(&ep_cfg_ctrl, 0, sizeof(struct ipa_ep_cfg_ctrl)); ep_cfg_ctrl.ipa_ep_delay = true; ipa3_cfg_ep_ctrl(clnt_hdl, &ep_cfg_ctrl); + /* disable force clear */ + ipa3_disable_force_clear(clnt_hdl); } IPA_ACTIVE_CLIENTS_DEC_EP(ipa3_get_client_mapping(clnt_hdl)); ep->uc_offload_state &= ~IPA_WDI_ENABLED; IPADBG("client (ep: %d) disabled\n", clnt_hdl); + uc_timeout: return result; }