Merge "msm: ipa: changes to suspend/disable for WDI 2"
This commit is contained in:
commit
7997223a2d
4 changed files with 85 additions and 26 deletions
|
@ -1,4 +1,4 @@
|
|||
/* 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
|
||||
|
@ -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;
|
||||
|
|
|
@ -1803,6 +1803,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);
|
||||
|
|
|
@ -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);
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
|
|
@ -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");
|
||||
|
@ -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)
|
||||
BUG();
|
||||
}
|
||||
|
||||
IPADBG("ep=%d\n", clnt_hdl);
|
||||
|
||||
ep = &ipa_ctx->ep[clnt_hdl];
|
||||
|
@ -1468,6 +1445,11 @@ 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);
|
||||
|
||||
|
@ -1594,6 +1576,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");
|
||||
|
@ -1623,6 +1607,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,
|
||||
|
@ -1667,6 +1676,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…
Add table
Reference in a new issue