Loading drivers/platform/msm/ipa/ipa_v2/ipa_client.c +41 −1 Original line number Diff line number Diff line /* Copyright (c) 2012-2016, The Linux Foundation. All rights reserved. /* Copyright (c) 2012-2017, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and Loading Loading @@ -95,6 +95,46 @@ int ipa_disable_data_path(u32 clnt_hdl) return res; } int ipa2_enable_force_clear(u32 request_id, bool throttle_source, u32 source_pipe_bitmask) { struct ipa_enable_force_clear_datapath_req_msg_v01 req; int result; memset(&req, 0, sizeof(req)); req.request_id = request_id; req.source_pipe_bitmask = source_pipe_bitmask; if (throttle_source) { req.throttle_source_valid = 1; req.throttle_source = 1; } result = qmi_enable_force_clear_datapath_send(&req); if (result) { IPAERR("qmi_enable_force_clear_datapath_send failed %d\n", result); return result; } return 0; } int ipa2_disable_force_clear(u32 request_id) { struct ipa_disable_force_clear_datapath_req_msg_v01 req; int result; memset(&req, 0, sizeof(req)); req.request_id = request_id; result = qmi_disable_force_clear_datapath_send(&req); if (result) { IPAERR("qmi_disable_force_clear_datapath_send failed %d\n", result); return result; } return 0; } static int ipa2_smmu_map_peer_bam(unsigned long dev) { phys_addr_t base; Loading drivers/platform/msm/ipa/ipa_v2/ipa_i.h +3 −0 Original line number Diff line number Diff line Loading @@ -1772,6 +1772,9 @@ void ipa_delete_dflt_flt_rules(u32 ipa_ep_idx); int ipa_enable_data_path(u32 clnt_hdl); int ipa_disable_data_path(u32 clnt_hdl); int ipa2_enable_force_clear(u32 request_id, bool throttle_source, u32 source_pipe_bitmask); int ipa2_disable_force_clear(u32 request_id); int ipa_id_alloc(void *ptr); void *ipa_id_find(u32 id); void ipa_id_remove(u32 id); Loading drivers/platform/msm/ipa/ipa_v2/ipa_qmi_service.c +6 −2 Original line number Diff line number Diff line Loading @@ -39,6 +39,8 @@ #define QMI_SEND_STATS_REQ_TIMEOUT_MS 5000 #define QMI_SEND_REQ_TIMEOUT_MS 60000 #define QMI_IPA_FORCE_CLEAR_DATAPATH_TIMEOUT_MS 1000 static struct qmi_handle *ipa_svc_handle; static void ipa_a5_svc_recv_msg(struct work_struct *work); static DECLARE_DELAYED_WORK(work_recv_msg, ipa_a5_svc_recv_msg); Loading Loading @@ -583,7 +585,8 @@ int qmi_enable_force_clear_datapath_send( &req_desc, req, sizeof(*req), &resp_desc, &resp, sizeof(resp), 0); &resp_desc, &resp, sizeof(resp), QMI_IPA_FORCE_CLEAR_DATAPATH_TIMEOUT_MS); if (rc < 0) { IPAWANERR("send req failed %d\n", rc); return rc; Loading Loading @@ -628,7 +631,8 @@ int qmi_disable_force_clear_datapath_send( &req_desc, req, sizeof(*req), &resp_desc, &resp, sizeof(resp), 0); &resp_desc, &resp, sizeof(resp), QMI_IPA_FORCE_CLEAR_DATAPATH_TIMEOUT_MS); if (rc < 0) { IPAWANERR("send req failed %d\n", rc); return rc; Loading drivers/platform/msm/ipa/ipa_v2/ipa_uc_wdi.c +36 −23 Original line number Diff line number Diff line Loading @@ -1404,7 +1404,6 @@ int ipa2_disable_wdi_pipe(u32 clnt_hdl) union IpaHwWdiCommonChCmdData_t disable; struct ipa_ep_cfg_ctrl ep_cfg_ctrl; u32 prod_hdl; int i; if (unlikely(!ipa_ctx)) { IPAERR("IPA driver was not initialized\n"); Loading @@ -1421,28 +1420,6 @@ int ipa2_disable_wdi_pipe(u32 clnt_hdl) if (result) return result; /* checking rdy_ring_rp_pa matches the rdy_comp_ring_wp_pa on WDI2.0 */ if (ipa_ctx->ipa_wdi2) { for (i = 0; i < IPA_UC_FINISH_MAX; i++) { IPADBG("(%d) rp_value(%u), comp_wp_value(%u)\n", i, *ipa_ctx->uc_ctx.rdy_ring_rp_va, *ipa_ctx->uc_ctx.rdy_comp_ring_wp_va); if (*ipa_ctx->uc_ctx.rdy_ring_rp_va != *ipa_ctx->uc_ctx.rdy_comp_ring_wp_va) { usleep_range(IPA_UC_WAIT_MIN_SLEEP, IPA_UC_WAII_MAX_SLEEP); } else { break; } } /* In case ipa_uc still haven't processed all * pending descriptors, we have to assert */ if (i == IPA_UC_FINISH_MAX) ipa_assert(); } IPADBG("ep=%d\n", clnt_hdl); ep = &ipa_ctx->ep[clnt_hdl]; Loading @@ -1468,7 +1445,13 @@ int ipa2_disable_wdi_pipe(u32 clnt_hdl) * holb on IPA Producer pipe */ if (IPA_CLIENT_IS_PROD(ep->client)) { IPADBG("Stopping PROD channel - hdl=%d clnt=%d\n", clnt_hdl, ep->client); /* remove delay on wlan-prod pipe*/ memset(&ep_cfg_ctrl, 0, sizeof(struct ipa_ep_cfg_ctrl)); ipa2_cfg_ep_ctrl(clnt_hdl, &ep_cfg_ctrl); prod_hdl = ipa2_get_ep_mapping(IPA_CLIENT_WLAN1_CONS); Loading Loading @@ -1594,6 +1577,8 @@ int ipa2_suspend_wdi_pipe(u32 clnt_hdl) struct ipa_ep_context *ep; union IpaHwWdiCommonChCmdData_t suspend; struct ipa_ep_cfg_ctrl ep_cfg_ctrl; u32 source_pipe_bitmask = 0; bool disable_force_clear = false; if (unlikely(!ipa_ctx)) { IPAERR("IPA driver was not initialized\n"); Loading Loading @@ -1623,6 +1608,31 @@ int ipa2_suspend_wdi_pipe(u32 clnt_hdl) suspend.params.ipa_pipe_number = clnt_hdl; if (IPA_CLIENT_IS_PROD(ep->client)) { /* * For WDI 2.0 need to ensure pipe will be empty before suspend * as IPA uC will fail to suspend the pipe otherwise. */ if (ipa_ctx->ipa_wdi2) { source_pipe_bitmask = 1 << ipa_get_ep_mapping(ep->client); result = ipa2_enable_force_clear(clnt_hdl, false, source_pipe_bitmask); if (result) { /* * assuming here modem SSR, AP can remove * the delay in this case */ IPAERR("failed to force clear %d\n", result); IPAERR("remove delay from SCND reg\n"); memset(&ep_cfg_ctrl, 0, sizeof(struct ipa_ep_cfg_ctrl)); ep_cfg_ctrl.ipa_ep_delay = false; ep_cfg_ctrl.ipa_ep_suspend = false; ipa2_cfg_ep_ctrl(clnt_hdl, &ep_cfg_ctrl); } else { disable_force_clear = true; } } IPADBG("Post suspend event first for IPA Producer\n"); IPADBG("Client: %d clnt_hdl: %d\n", ep->client, clnt_hdl); result = ipa_uc_send_cmd(suspend.raw32b, Loading Loading @@ -1667,6 +1677,9 @@ int ipa2_suspend_wdi_pipe(u32 clnt_hdl) } } if (disable_force_clear) ipa2_disable_force_clear(clnt_hdl); ipa_ctx->tag_process_before_gating = true; IPA_ACTIVE_CLIENTS_DEC_EP(ipa2_get_client_mapping(clnt_hdl)); ep->uc_offload_state &= ~IPA_WDI_RESUMED; Loading Loading
drivers/platform/msm/ipa/ipa_v2/ipa_client.c +41 −1 Original line number Diff line number Diff line /* Copyright (c) 2012-2016, The Linux Foundation. All rights reserved. /* Copyright (c) 2012-2017, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and Loading Loading @@ -95,6 +95,46 @@ int ipa_disable_data_path(u32 clnt_hdl) return res; } int ipa2_enable_force_clear(u32 request_id, bool throttle_source, u32 source_pipe_bitmask) { struct ipa_enable_force_clear_datapath_req_msg_v01 req; int result; memset(&req, 0, sizeof(req)); req.request_id = request_id; req.source_pipe_bitmask = source_pipe_bitmask; if (throttle_source) { req.throttle_source_valid = 1; req.throttle_source = 1; } result = qmi_enable_force_clear_datapath_send(&req); if (result) { IPAERR("qmi_enable_force_clear_datapath_send failed %d\n", result); return result; } return 0; } int ipa2_disable_force_clear(u32 request_id) { struct ipa_disable_force_clear_datapath_req_msg_v01 req; int result; memset(&req, 0, sizeof(req)); req.request_id = request_id; result = qmi_disable_force_clear_datapath_send(&req); if (result) { IPAERR("qmi_disable_force_clear_datapath_send failed %d\n", result); return result; } return 0; } static int ipa2_smmu_map_peer_bam(unsigned long dev) { phys_addr_t base; Loading
drivers/platform/msm/ipa/ipa_v2/ipa_i.h +3 −0 Original line number Diff line number Diff line Loading @@ -1772,6 +1772,9 @@ void ipa_delete_dflt_flt_rules(u32 ipa_ep_idx); int ipa_enable_data_path(u32 clnt_hdl); int ipa_disable_data_path(u32 clnt_hdl); int ipa2_enable_force_clear(u32 request_id, bool throttle_source, u32 source_pipe_bitmask); int ipa2_disable_force_clear(u32 request_id); int ipa_id_alloc(void *ptr); void *ipa_id_find(u32 id); void ipa_id_remove(u32 id); Loading
drivers/platform/msm/ipa/ipa_v2/ipa_qmi_service.c +6 −2 Original line number Diff line number Diff line Loading @@ -39,6 +39,8 @@ #define QMI_SEND_STATS_REQ_TIMEOUT_MS 5000 #define QMI_SEND_REQ_TIMEOUT_MS 60000 #define QMI_IPA_FORCE_CLEAR_DATAPATH_TIMEOUT_MS 1000 static struct qmi_handle *ipa_svc_handle; static void ipa_a5_svc_recv_msg(struct work_struct *work); static DECLARE_DELAYED_WORK(work_recv_msg, ipa_a5_svc_recv_msg); Loading Loading @@ -583,7 +585,8 @@ int qmi_enable_force_clear_datapath_send( &req_desc, req, sizeof(*req), &resp_desc, &resp, sizeof(resp), 0); &resp_desc, &resp, sizeof(resp), QMI_IPA_FORCE_CLEAR_DATAPATH_TIMEOUT_MS); if (rc < 0) { IPAWANERR("send req failed %d\n", rc); return rc; Loading Loading @@ -628,7 +631,8 @@ int qmi_disable_force_clear_datapath_send( &req_desc, req, sizeof(*req), &resp_desc, &resp, sizeof(resp), 0); &resp_desc, &resp, sizeof(resp), QMI_IPA_FORCE_CLEAR_DATAPATH_TIMEOUT_MS); if (rc < 0) { IPAWANERR("send req failed %d\n", rc); return rc; Loading
drivers/platform/msm/ipa/ipa_v2/ipa_uc_wdi.c +36 −23 Original line number Diff line number Diff line Loading @@ -1404,7 +1404,6 @@ int ipa2_disable_wdi_pipe(u32 clnt_hdl) union IpaHwWdiCommonChCmdData_t disable; struct ipa_ep_cfg_ctrl ep_cfg_ctrl; u32 prod_hdl; int i; if (unlikely(!ipa_ctx)) { IPAERR("IPA driver was not initialized\n"); Loading @@ -1421,28 +1420,6 @@ int ipa2_disable_wdi_pipe(u32 clnt_hdl) if (result) return result; /* checking rdy_ring_rp_pa matches the rdy_comp_ring_wp_pa on WDI2.0 */ if (ipa_ctx->ipa_wdi2) { for (i = 0; i < IPA_UC_FINISH_MAX; i++) { IPADBG("(%d) rp_value(%u), comp_wp_value(%u)\n", i, *ipa_ctx->uc_ctx.rdy_ring_rp_va, *ipa_ctx->uc_ctx.rdy_comp_ring_wp_va); if (*ipa_ctx->uc_ctx.rdy_ring_rp_va != *ipa_ctx->uc_ctx.rdy_comp_ring_wp_va) { usleep_range(IPA_UC_WAIT_MIN_SLEEP, IPA_UC_WAII_MAX_SLEEP); } else { break; } } /* In case ipa_uc still haven't processed all * pending descriptors, we have to assert */ if (i == IPA_UC_FINISH_MAX) ipa_assert(); } IPADBG("ep=%d\n", clnt_hdl); ep = &ipa_ctx->ep[clnt_hdl]; Loading @@ -1468,7 +1445,13 @@ int ipa2_disable_wdi_pipe(u32 clnt_hdl) * holb on IPA Producer pipe */ if (IPA_CLIENT_IS_PROD(ep->client)) { IPADBG("Stopping PROD channel - hdl=%d clnt=%d\n", clnt_hdl, ep->client); /* remove delay on wlan-prod pipe*/ memset(&ep_cfg_ctrl, 0, sizeof(struct ipa_ep_cfg_ctrl)); ipa2_cfg_ep_ctrl(clnt_hdl, &ep_cfg_ctrl); prod_hdl = ipa2_get_ep_mapping(IPA_CLIENT_WLAN1_CONS); Loading Loading @@ -1594,6 +1577,8 @@ int ipa2_suspend_wdi_pipe(u32 clnt_hdl) struct ipa_ep_context *ep; union IpaHwWdiCommonChCmdData_t suspend; struct ipa_ep_cfg_ctrl ep_cfg_ctrl; u32 source_pipe_bitmask = 0; bool disable_force_clear = false; if (unlikely(!ipa_ctx)) { IPAERR("IPA driver was not initialized\n"); Loading Loading @@ -1623,6 +1608,31 @@ int ipa2_suspend_wdi_pipe(u32 clnt_hdl) suspend.params.ipa_pipe_number = clnt_hdl; if (IPA_CLIENT_IS_PROD(ep->client)) { /* * For WDI 2.0 need to ensure pipe will be empty before suspend * as IPA uC will fail to suspend the pipe otherwise. */ if (ipa_ctx->ipa_wdi2) { source_pipe_bitmask = 1 << ipa_get_ep_mapping(ep->client); result = ipa2_enable_force_clear(clnt_hdl, false, source_pipe_bitmask); if (result) { /* * assuming here modem SSR, AP can remove * the delay in this case */ IPAERR("failed to force clear %d\n", result); IPAERR("remove delay from SCND reg\n"); memset(&ep_cfg_ctrl, 0, sizeof(struct ipa_ep_cfg_ctrl)); ep_cfg_ctrl.ipa_ep_delay = false; ep_cfg_ctrl.ipa_ep_suspend = false; ipa2_cfg_ep_ctrl(clnt_hdl, &ep_cfg_ctrl); } else { disable_force_clear = true; } } IPADBG("Post suspend event first for IPA Producer\n"); IPADBG("Client: %d clnt_hdl: %d\n", ep->client, clnt_hdl); result = ipa_uc_send_cmd(suspend.raw32b, Loading Loading @@ -1667,6 +1677,9 @@ int ipa2_suspend_wdi_pipe(u32 clnt_hdl) } } if (disable_force_clear) ipa2_disable_force_clear(clnt_hdl); ipa_ctx->tag_process_before_gating = true; IPA_ACTIVE_CLIENTS_DEC_EP(ipa2_get_client_mapping(clnt_hdl)); ep->uc_offload_state &= ~IPA_WDI_RESUMED; Loading