diff options
| -rw-r--r-- | drivers/platform/msm/ipa/ipa_v3/ipa_uc_wdi.c | 97 | ||||
| -rw-r--r-- | drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal_reg.c | 17 | ||||
| -rw-r--r-- | drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal_reg.h | 11 | ||||
| -rw-r--r-- | drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal_reg_i.h | 6 |
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 |
