summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--drivers/platform/msm/ipa/ipa_v3/ipa_uc_wdi.c97
-rw-r--r--drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal_reg.c17
-rw-r--r--drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal_reg.h11
-rw-r--r--drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal_reg_i.h6
4 files changed, 62 insertions, 69 deletions
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 24b61880f95d..57fa2465c9ea 100644
--- a/drivers/platform/msm/ipa/ipa_v3/ipa_uc_wdi.c
+++ b/drivers/platform/msm/ipa/ipa_v3/ipa_uc_wdi.c
@@ -1356,33 +1356,6 @@ uc_timeout:
return result;
}
-static int ipa3_wait_for_prod_empty(void)
-{
- int i;
- u32 rx_door_bell_value;
-
- for (i = 0; i < IPA_UC_FINISH_MAX; i++) {
- rx_door_bell_value = ipahal_read_reg_mn(
- IPA_UC_MAILBOX_m_n,
- IPA_HW_WDI_RX_MBOX_START_INDEX / 32,
- IPA_HW_WDI_RX_MBOX_START_INDEX % 32);
- IPADBG("(%d)rx_DB(%u)rp(%u),comp_wp(%u)\n",
- i,
- rx_door_bell_value,
- *ipa3_ctx->uc_ctx.rdy_ring_rp_va,
- *ipa3_ctx->uc_ctx.rdy_comp_ring_wp_va);
- 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);
- } else {
- return 0;
- }
- }
-
- return -ETIME;
-}
-
/**
* ipa3_disable_wdi_pipe() - WDI client disable
* @clnt_hdl: [in] opaque client handle assigned by IPA to client
@@ -1399,9 +1372,6 @@ int ipa3_disable_wdi_pipe(u32 clnt_hdl)
struct ipa_ep_cfg_ctrl ep_cfg_ctrl;
u32 prod_hdl;
- u32 source_pipe_bitmask = 0;
- bool disable_force_clear = false;
-
if (clnt_hdl >= ipa3_ctx->ipa_num_pipes ||
ipa3_ctx->ep[clnt_hdl].valid == 0) {
IPAERR("bad parm, %d\n", clnt_hdl);
@@ -1456,40 +1426,6 @@ int ipa3_disable_wdi_pipe(u32 clnt_hdl)
usleep_range(IPA_UC_POLL_SLEEP_USEC * IPA_UC_POLL_SLEEP_USEC,
IPA_UC_POLL_SLEEP_USEC * IPA_UC_POLL_SLEEP_USEC);
- /*
- * checking rdy_ring_rp_pa matches the
- * rdy_comp_ring_wp_pa on WDI2.0
- */
- if (ipa3_ctx->ipa_wdi2) {
- result = ipa3_wait_for_prod_empty();
- if (result) {
- IPADBG("prod not empty\n");
- /*
- * In case ipa_uc still haven't processed all
- * pending descriptors, ask modem to drain
- */
- source_pipe_bitmask = 1 <<
- ipa3_get_ep_mapping(ep->client);
- result = ipa3_enable_force_clear(clnt_hdl,
- false, source_pipe_bitmask);
- if (result) {
- IPAERR("failed to force clear %d\n",
- result);
- } else {
- disable_force_clear = true;
- }
-
- /*
- * In case ipa_uc still haven't processed all
- * pending descriptors, we have to assert
- */
- result = ipa3_wait_for_prod_empty();
- if (result) {
- IPAERR("prod still not empty\n");
- ipa_assert();
- }
- }
- }
}
disable.params.ipa_pipe_number = clnt_hdl;
@@ -1508,8 +1444,6 @@ 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);
- if (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;
@@ -1595,6 +1529,9 @@ int ipa3_suspend_wdi_pipe(u32 clnt_hdl)
struct ipa3_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;
+ struct ipahal_ep_cfg_ctrl_scnd ep_ctrl_scnd = { 0 };
if (clnt_hdl >= ipa3_ctx->ipa_num_pipes ||
ipa3_ctx->ep[clnt_hdl].valid == 0) {
@@ -1619,6 +1556,31 @@ int ipa3_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 (ipa3_ctx->ipa_wdi2) {
+ source_pipe_bitmask = 1 <<
+ ipa3_get_ep_mapping(ep->client);
+ result = ipa3_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");
+ ep_ctrl_scnd.endp_delay = false;
+ ipahal_write_reg_n_fields(
+ IPA_ENDP_INIT_CTRL_SCND_n, clnt_hdl,
+ &ep_ctrl_scnd);
+ } 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 = ipa3_uc_send_cmd(suspend.raw32b,
@@ -1663,6 +1625,9 @@ int ipa3_suspend_wdi_pipe(u32 clnt_hdl)
}
}
+ if (disable_force_clear)
+ ipa3_disable_force_clear(clnt_hdl);
+
ipa3_ctx->tag_process_before_gating = true;
IPA_ACTIVE_CLIENTS_DEC_EP(ipa3_get_client_mapping(clnt_hdl));
ep->uc_offload_state &= ~IPA_WDI_RESUMED;
diff --git a/drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal_reg.c b/drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal_reg.c
index 347a8c418ebb..1da867024447 100644
--- a/drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal_reg.c
+++ b/drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal_reg.c
@@ -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
@@ -44,6 +44,7 @@ static const char *ipareg_name_to_str[IPA_REG_MAX] = {
__stringify(IPA_ENDP_INIT_MODE_n),
__stringify(IPA_ENDP_INIT_NAT_n),
__stringify(IPA_ENDP_INIT_CTRL_n),
+ __stringify(IPA_ENDP_INIT_CTRL_SCND_n),
__stringify(IPA_ENDP_INIT_HOL_BLOCK_EN_n),
__stringify(IPA_ENDP_INIT_HOL_BLOCK_TIMER_n),
__stringify(IPA_ENDP_INIT_DEAGGR_n),
@@ -645,6 +646,17 @@ static void ipareg_construct_endp_init_ctrl_n(enum ipahal_reg_name reg,
IPA_ENDP_INIT_CTRL_n_ENDP_DELAY_BMSK);
}
+static void ipareg_construct_endp_init_ctrl_scnd_n(enum ipahal_reg_name reg,
+ const void *fields, u32 *val)
+{
+ struct ipahal_ep_cfg_ctrl_scnd *ep_ctrl_scnd =
+ (struct ipahal_ep_cfg_ctrl_scnd *)fields;
+
+ IPA_SETFIELD_IN_REG(*val, ep_ctrl_scnd->endp_delay,
+ IPA_ENDP_INIT_CTRL_SCND_n_ENDP_DELAY_SHFT,
+ IPA_ENDP_INIT_CTRL_SCND_n_ENDP_DELAY_BMSK);
+}
+
static void ipareg_construct_endp_init_nat_n(enum ipahal_reg_name reg,
const void *fields, u32 *val)
{
@@ -1008,6 +1020,9 @@ static struct ipahal_reg_obj ipahal_reg_objs[IPA_HW_MAX][IPA_REG_MAX] = {
[IPA_HW_v3_0][IPA_ENDP_INIT_CTRL_n] = {
ipareg_construct_endp_init_ctrl_n, ipareg_parse_dummy,
0x00000800, 0x70},
+ [IPA_HW_v3_0][IPA_ENDP_INIT_CTRL_SCND_n] = {
+ ipareg_construct_endp_init_ctrl_scnd_n, ipareg_parse_dummy,
+ 0x00000804, 0x70 },
[IPA_HW_v3_0][IPA_ENDP_INIT_HOL_BLOCK_EN_n] = {
ipareg_construct_endp_init_hol_block_en_n,
ipareg_parse_dummy,
diff --git a/drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal_reg.h b/drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal_reg.h
index 5f1e3fe410b1..239eb54e517f 100644
--- a/drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal_reg.h
+++ b/drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal_reg.h
@@ -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
@@ -47,6 +47,7 @@ enum ipahal_reg_name {
IPA_ENDP_INIT_MODE_n,
IPA_ENDP_INIT_NAT_n,
IPA_ENDP_INIT_CTRL_n,
+ IPA_ENDP_INIT_CTRL_SCND_n,
IPA_ENDP_INIT_HOL_BLOCK_EN_n,
IPA_ENDP_INIT_HOL_BLOCK_TIMER_n,
IPA_ENDP_INIT_DEAGGR_n,
@@ -330,6 +331,14 @@ struct ipahal_reg_tx_cfg {
};
/*
+ * struct ipa_ep_cfg_ctrl_scnd - PA_ENDP_INIT_CTRL_SCND_n register
+ * @endp_delay: delay endpoint
+ */
+struct ipahal_ep_cfg_ctrl_scnd {
+ bool endp_delay;
+};
+
+/*
* ipahal_reg_name_str() - returns string that represent the register
* @reg_name: [in] register name
*/
diff --git a/drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal_reg_i.h b/drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal_reg_i.h
index 1606a2ff41c7..ac97e5ac0494 100644
--- a/drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal_reg_i.h
+++ b/drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal_reg_i.h
@@ -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
@@ -122,6 +122,10 @@ int ipahal_reg_init(enum ipa_hw_type ipa_hw_type);
#define IPA_ENDP_INIT_CTRL_n_ENDP_DELAY_BMSK 0x2
#define IPA_ENDP_INIT_CTRL_n_ENDP_DELAY_SHFT 0x1
+/* IPA_ENDP_INIT_CTRL_SCND_n register */
+#define IPA_ENDP_INIT_CTRL_SCND_n_ENDP_DELAY_BMSK 0x2
+#define IPA_ENDP_INIT_CTRL_SCND_n_ENDP_DELAY_SHFT 0x1
+
/* IPA_ENDP_INIT_HOL_BLOCK_EN_n register */
#define IPA_ENDP_INIT_HOL_BLOCK_EN_n_RMSK 0x1
#define IPA_ENDP_INIT_HOL_BLOCK_EN_n_MAX 19