From eb8c172da818256a3f444a08944f791cc42e2d23 Mon Sep 17 00:00:00 2001 From: Ashok Vuyyuru Date: Tue, 3 Jul 2018 18:14:19 -0700 Subject: [PATCH 1/2] msm: ipa: allow abort for disable_clks If a GSI channel is not quite clock cannot be devoted. This change introduces the capability to "abort and retry" clock devote operation. Change-Id: I6e591435bbc3de81dce39e3ad5a0ae0f87c9a783 Signed-off-by: Ashok Vuyyuru --- drivers/platform/msm/ipa/ipa_v3/ipa.c | 20 ++- drivers/platform/msm/ipa/ipa_v3/ipa_i.h | 2 +- drivers/platform/msm/ipa/ipa_v3/ipa_utils.c | 182 +++++++------------- 3 files changed, 75 insertions(+), 129 deletions(-) diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa.c b/drivers/platform/msm/ipa/ipa_v3/ipa.c index 8ac349495933..fd0cbc6cb6c5 100644 --- a/drivers/platform/msm/ipa/ipa_v3/ipa.c +++ b/drivers/platform/msm/ipa/ipa_v3/ipa.c @@ -54,6 +54,8 @@ #include "ipa_trace.h" #include "ipa_odl.h" +#define IPA_SUSPEND_BUSY_TIMEOUT (msecs_to_jiffies(10)) + /* * The following for adding code (ie. for EMULATION) not found on x86. */ @@ -117,7 +119,7 @@ static void ipa3_load_ipa_fw(struct work_struct *work); static DECLARE_WORK(ipa3_fw_loading_work, ipa3_load_ipa_fw); static void ipa_dec_clients_disable_clks_on_wq(struct work_struct *work); -static DECLARE_WORK(ipa_dec_clients_disable_clks_on_wq_work, +static DECLARE_DELAYED_WORK(ipa_dec_clients_disable_clks_on_wq_work, ipa_dec_clients_disable_clks_on_wq); static int ipa3_ioctl_add_rt_rule_v2(unsigned long arg); @@ -4815,8 +4817,16 @@ static void __ipa3_dec_client_disable_clks(void) ret = atomic_sub_return(1, &ipa3_ctx->ipa3_active_clients.cnt); if (ret > 0) goto unlock_mutex; - ipa3_suspend_apps_pipes(true); - ipa3_disable_clks(); + ret = ipa3_suspend_apps_pipes(true); + if (ret) { + /* HW is busy, retry after some time */ + atomic_inc(&ipa3_ctx->ipa3_active_clients.cnt); + queue_delayed_work(ipa3_ctx->power_mgmt_wq, + &ipa_dec_clients_disable_clks_on_wq_work, + IPA_SUSPEND_BUSY_TIMEOUT); + } else { + ipa3_disable_clks(); + } unlock_mutex: mutex_unlock(&ipa3_ctx->ipa3_active_clients.mutex); @@ -4869,8 +4879,8 @@ void ipa3_dec_client_disable_clks_no_block( } /* seems like this is the only client holding the clocks */ - queue_work(ipa3_ctx->power_mgmt_wq, - &ipa_dec_clients_disable_clks_on_wq_work); + queue_delayed_work(ipa3_ctx->power_mgmt_wq, + &ipa_dec_clients_disable_clks_on_wq_work, 0); } /** diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa_i.h b/drivers/platform/msm/ipa/ipa_v3/ipa_i.h index 1cc20312e1e1..5072ee47625d 100644 --- a/drivers/platform/msm/ipa/ipa_v3/ipa_i.h +++ b/drivers/platform/msm/ipa/ipa_v3/ipa_i.h @@ -2915,7 +2915,7 @@ int ipa3_create_wdi_mapping(u32 num_buffers, struct ipa_wdi_buffer_info *info); int ipa3_set_flt_tuple_mask(int pipe_idx, struct ipahal_reg_hash_tuple *tuple); int ipa3_set_rt_tuple_mask(int tbl_idx, struct ipahal_reg_hash_tuple *tuple); void ipa3_set_resorce_groups_min_max_limits(void); -void ipa3_suspend_apps_pipes(bool suspend); +int ipa3_suspend_apps_pipes(bool suspend); int ipa3_flt_read_tbl_from_hw(u32 pipe_idx, enum ipa_ip_type ip_type, bool hashable, diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa_utils.c b/drivers/platform/msm/ipa/ipa_v3/ipa_utils.c index aea7a5a5fe89..763385965f3b 100644 --- a/drivers/platform/msm/ipa/ipa_v3/ipa_utils.c +++ b/drivers/platform/msm/ipa/ipa_v3/ipa_utils.c @@ -7484,12 +7484,10 @@ void ipa3_set_resorce_groups_min_max_limits(void) IPADBG("EXIT\n"); } -static void ipa3_gsi_poll_after_suspend(struct ipa3_ep_context *ep) +static bool ipa3_gsi_channel_is_quite(struct ipa3_ep_context *ep) { bool empty; - IPADBG("switch ch %ld to poll\n", ep->gsi_chan_hdl); - gsi_config_channel_mode(ep->gsi_chan_hdl, GSI_CHAN_MODE_POLL); gsi_is_channel_empty(ep->gsi_chan_hdl, &empty); if (!empty) { IPADBG("ch %ld not empty\n", ep->gsi_chan_hdl); @@ -7498,6 +7496,7 @@ static void ipa3_gsi_poll_after_suspend(struct ipa3_ep_context *ep) if (!atomic_read(&ep->sys->curr_polling_state)) __ipa_gsi_irq_rx_scedule_poll(ep->sys); } + return empty; } static int __ipa3_stop_gsi_channel(u32 clnt_hdl) @@ -7623,141 +7622,78 @@ int ipa3_stop_gsi_channel(u32 clnt_hdl) return res; } -void ipa3_suspend_apps_pipes(bool suspend) +static int _ipa_suspend_pipe(enum ipa_client_type client, bool suspend) { - struct ipa_ep_cfg_ctrl cfg; int ipa_ep_idx; struct ipa3_ep_context *ep; int res; - memset(&cfg, 0, sizeof(cfg)); - cfg.ipa_ep_suspend = suspend; + if (ipa3_ctx->ipa_hw_type < IPA_HW_v4_0) { + IPAERR("not supported\n"); + return -EPERM; + } - ipa_ep_idx = ipa3_get_ep_mapping(IPA_CLIENT_APPS_LAN_CONS); + ipa_ep_idx = ipa3_get_ep_mapping(client); if (ipa_ep_idx < 0) { - IPAERR("IPA client mapping failed\n"); - ipa_assert(); - return; + IPADBG("client %d not configured\n", client); + return 0; } - ep = &ipa3_ctx->ep[ipa_ep_idx]; - if (ep->valid) { - IPADBG("%s pipe %d\n", suspend ? "suspend" : "unsuspend", - ipa_ep_idx); - /* - * move the channel to callback mode. - * This needs to happen before starting the channel to make - * sure we don't loose any interrupt - */ - if (!suspend && !atomic_read(&ep->sys->curr_polling_state)) - gsi_config_channel_mode(ep->gsi_chan_hdl, - GSI_CHAN_MODE_CALLBACK); - if (ipa3_ctx->ipa_hw_type >= IPA_HW_v4_0) { - if (suspend) { - res = __ipa3_stop_gsi_channel(ipa_ep_idx); - if (res) { - IPAERR("failed to stop LAN channel\n"); - ipa_assert(); - } - } else { - res = gsi_start_channel(ep->gsi_chan_hdl); - if (res) { - IPAERR("failed to start LAN channel\n"); - ipa_assert(); - } - } - } else { - ipa3_cfg_ep_ctrl(ipa_ep_idx, &cfg); + ep = &ipa3_ctx->ep[ipa_ep_idx]; + if (!ep->valid) + return 0; + + IPADBG("%s pipe %d\n", suspend ? "suspend" : "unsuspend", ipa_ep_idx); + /* + * move the channel to callback mode. + * This needs to happen before starting the channel to make + * sure we don't loose any interrupt + */ + if (!suspend && !atomic_read(&ep->sys->curr_polling_state)) + gsi_config_channel_mode(ep->gsi_chan_hdl, + GSI_CHAN_MODE_CALLBACK); + + if (suspend) { + res = __ipa3_stop_gsi_channel(ipa_ep_idx); + if (res) { + IPAERR("failed to stop LAN channel\n"); + ipa_assert(); } - if (suspend) - ipa3_gsi_poll_after_suspend(ep); - } - - ipa_ep_idx = ipa_get_ep_mapping(IPA_CLIENT_APPS_WAN_CONS); - /* Considering the case for SSR. */ - if (ipa_ep_idx == -1) { - IPADBG("Invalid mapping for IPA_CLIENT_APPS_WAN_CONS\n"); - return; - } - ep = &ipa3_ctx->ep[ipa_ep_idx]; - if (ep->valid) { - IPADBG("%s pipe %d\n", suspend ? "suspend" : "unsuspend", - ipa_ep_idx); - /* - * move the channel to callback mode. - * This needs to happen before starting the channel to make - * sure we don't loose any interrupt - */ - if (!suspend && !atomic_read(&ep->sys->curr_polling_state)) - gsi_config_channel_mode(ep->gsi_chan_hdl, - GSI_CHAN_MODE_CALLBACK); - if (ipa3_ctx->ipa_hw_type >= IPA_HW_v4_0) { - if (suspend) { - res = __ipa3_stop_gsi_channel(ipa_ep_idx); - if (res) { - IPAERR("failed to stop WAN channel\n"); - ipa_assert(); - } - } else if (!atomic_read(&ipa3_ctx->is_ssr)) { - /* If SSR was alreday started not required to - * start WAN channel,Because in SSR will stop - * channel and reset the channel. - */ - res = gsi_start_channel(ep->gsi_chan_hdl); - if (res) { - IPAERR("failed to start WAN channel\n"); - ipa_assert(); - } - } - } else { - ipa3_cfg_ep_ctrl(ipa_ep_idx, &cfg); + } else { + res = gsi_start_channel(ep->gsi_chan_hdl); + if (res) { + IPAERR("failed to start LAN channel\n"); + ipa_assert(); } - if (suspend) - ipa3_gsi_poll_after_suspend(ep); } - ipa_ep_idx = ipa_get_ep_mapping(IPA_CLIENT_ODL_DPL_CONS); - /* Considering the case for SSR. */ - if (ipa_ep_idx == -1) { - IPADBG("Invalid mapping for IPA_CLIENT_ODL_DPL_CONS\n"); - return; - } - ep = &ipa3_ctx->ep[ipa_ep_idx]; - if (ep->valid) { - IPADBG("%s pipe %d\n", suspend ? "suspend" : "unsuspend", - ipa_ep_idx); - /* - * move the channel to callback mode. - * This needs to happen before starting the channel to make - * sure we don't loose any interrupt - */ - if (!suspend && !atomic_read(&ep->sys->curr_polling_state)) - gsi_config_channel_mode(ep->gsi_chan_hdl, + if (suspend) { + IPADBG("switch ch %ld to poll\n", ep->gsi_chan_hdl); + gsi_config_channel_mode(ep->gsi_chan_hdl, GSI_CHAN_MODE_POLL); + if (!ipa3_gsi_channel_is_quite(ep)) + return -EAGAIN; + } else if (!atomic_read(&ep->sys->curr_polling_state)) { + IPADBG("switch ch %ld to callback\n", ep->gsi_chan_hdl); + gsi_config_channel_mode(ep->gsi_chan_hdl, GSI_CHAN_MODE_CALLBACK); - if (ipa3_ctx->ipa_hw_type >= IPA_HW_v4_0) { - if (suspend) { - res = __ipa3_stop_gsi_channel(ipa_ep_idx); - if (res) { - IPAERR("failed to stop ODL channel\n"); - ipa_assert(); - } - } else if (!atomic_read(&ipa3_ctx->is_ssr)) { - /* If SSR was alreday started not required to - * start WAN channel,Because in SSR will stop - * channel and reset the channel. - */ - res = gsi_start_channel(ep->gsi_chan_hdl); - if (res) { - IPAERR("failed to start ODL channel\n"); - ipa_assert(); - } - } - } else { - ipa3_cfg_ep_ctrl(ipa_ep_idx, &cfg); - } - if (suspend) - ipa3_gsi_poll_after_suspend(ep); } + + return 0; +} + +int ipa3_suspend_apps_pipes(bool suspend) +{ + int res; + + res = _ipa_suspend_pipe(IPA_CLIENT_APPS_LAN_CONS, suspend); + if (res) + return res; + + res = _ipa_suspend_pipe(IPA_CLIENT_APPS_WAN_CONS, suspend); + if (res) + return res; + + return 0; } int ipa3_allocate_dma_task_for_gsi(void) From 40e62ce36a09308b11e3eebdd4da6508c30640b3 Mon Sep 17 00:00:00 2001 From: Praveen Kurapati Date: Tue, 21 Aug 2018 18:14:41 -0700 Subject: [PATCH 2/2] msm: ipa4: support coalescing pipe suspend Add changes to support coalescing pipe suspend. Change-Id: I403db535b88da917d43ac52f26ea3fff9b617be5 Signed-off-by: Praveen Kurapati Signed-off-by: Ashok Vuyyuru --- drivers/platform/msm/gsi/gsi.c | 6 +- drivers/platform/msm/ipa/ipa_v3/ipa_utils.c | 105 ++++++++++++++-- .../msm/ipa/ipa_v3/ipahal/ipahal_reg.c | 112 ++++++++++++++++++ .../msm/ipa/ipa_v3/ipahal/ipahal_reg.h | 21 ++++ .../msm/ipa/ipa_v3/ipahal/ipahal_reg_i.h | 47 ++++++++ 5 files changed, 280 insertions(+), 11 deletions(-) diff --git a/drivers/platform/msm/gsi/gsi.c b/drivers/platform/msm/gsi/gsi.c index 6c300f3eabd0..7af997b30f3a 100644 --- a/drivers/platform/msm/gsi/gsi.c +++ b/drivers/platform/msm/gsi/gsi.c @@ -3719,7 +3719,7 @@ int gsi_config_channel_mode(unsigned long chan_hdl, enum gsi_chan_mode mode) curr = GSI_CHAN_MODE_CALLBACK; if (mode == curr) { - GSIERR("already in requested mode %u chan_hdl=%lu\n", + GSIDBG("already in requested mode %u chan_hdl=%lu\n", curr, chan_hdl); return -GSI_STATUS_UNSUPPORTED_OP; } @@ -3730,7 +3730,7 @@ int gsi_config_channel_mode(unsigned long chan_hdl, enum gsi_chan_mode mode) gsi_writel(1 << ctx->evtr->id, gsi_ctx->base + GSI_EE_n_CNTXT_SRC_IEOB_IRQ_CLR_OFFS(gsi_ctx->per.ee)); atomic_set(&ctx->poll_mode, mode); - if (ctx->props.prot == GSI_CHAN_PROT_GCI) + if ((ctx->props.prot == GSI_CHAN_PROT_GCI) && ctx->evtr->chan) atomic_set(&ctx->evtr->chan->poll_mode, mode); GSIDBG("set gsi_ctx evtr_id %d to %d mode\n", ctx->evtr->id, mode); @@ -3740,7 +3740,7 @@ int gsi_config_channel_mode(unsigned long chan_hdl, enum gsi_chan_mode mode) if (curr == GSI_CHAN_MODE_POLL && mode == GSI_CHAN_MODE_CALLBACK) { atomic_set(&ctx->poll_mode, mode); - if (ctx->props.prot == GSI_CHAN_PROT_GCI) + if ((ctx->props.prot == GSI_CHAN_PROT_GCI) && ctx->evtr->chan) atomic_set(&ctx->evtr->chan->poll_mode, mode); __gsi_config_ieob_irq(gsi_ctx->per.ee, 1 << ctx->evtr->id, ~0); GSIDBG("set gsi_ctx evtr_id %d to %d mode\n", diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa_utils.c b/drivers/platform/msm/ipa/ipa_v3/ipa_utils.c index 763385965f3b..75532d655e4d 100644 --- a/drivers/platform/msm/ipa/ipa_v3/ipa_utils.c +++ b/drivers/platform/msm/ipa/ipa_v3/ipa_utils.c @@ -7622,7 +7622,7 @@ int ipa3_stop_gsi_channel(u32 clnt_hdl) return res; } -static int _ipa_suspend_pipe(enum ipa_client_type client, bool suspend) +static int _ipa_suspend_resume_pipe(enum ipa_client_type client, bool suspend) { int ipa_ep_idx; struct ipa3_ep_context *ep; @@ -7649,7 +7649,8 @@ static int _ipa_suspend_pipe(enum ipa_client_type client, bool suspend) * This needs to happen before starting the channel to make * sure we don't loose any interrupt */ - if (!suspend && !atomic_read(&ep->sys->curr_polling_state)) + if (!suspend && !atomic_read(&ep->sys->curr_polling_state) && + !IPA_CLIENT_IS_APPS_PROD(client)) gsi_config_channel_mode(ep->gsi_chan_hdl, GSI_CHAN_MODE_CALLBACK); @@ -7667,6 +7668,10 @@ static int _ipa_suspend_pipe(enum ipa_client_type client, bool suspend) } } + /* Apps prod pipes use common event ring so cannot configure mode*/ + if (IPA_CLIENT_IS_APPS_PROD(client)) + return 0; + if (suspend) { IPADBG("switch ch %ld to poll\n", ep->gsi_chan_hdl); gsi_config_channel_mode(ep->gsi_chan_hdl, GSI_CHAN_MODE_POLL); @@ -7681,19 +7686,103 @@ static int _ipa_suspend_pipe(enum ipa_client_type client, bool suspend) return 0; } +void ipa3_force_close_coal(void) +{ + struct ipahal_imm_cmd_pyld *cmd_pyld = NULL; + struct ipahal_imm_cmd_register_write reg_write_cmd = { 0 }; + struct ipahal_reg_valmask valmask; + struct ipa3_desc desc; + int ep_idx; + + ep_idx = ipa3_get_ep_mapping(IPA_CLIENT_APPS_WAN_COAL_CONS); + if (ep_idx == IPA_EP_NOT_ALLOCATED || (!ipa3_ctx->ep[ep_idx].valid)) + return; + + reg_write_cmd.skip_pipeline_clear = false; + reg_write_cmd.pipeline_clear_options = IPAHAL_HPS_CLEAR; + reg_write_cmd.offset = ipahal_get_reg_ofst(IPA_AGGR_FORCE_CLOSE); + ipahal_get_aggr_force_close_valmask(ep_idx, &valmask); + reg_write_cmd.value = valmask.val; + reg_write_cmd.value_mask = valmask.mask; + cmd_pyld = ipahal_construct_imm_cmd(IPA_IMM_CMD_REGISTER_WRITE, + ®_write_cmd, false); + if (!cmd_pyld) { + IPAERR("fail construct register_write imm cmd\n"); + ipa_assert(); + return; + } + ipa3_init_imm_cmd_desc(&desc, cmd_pyld); + + IPADBG("Sending 1 descriptor for coal force close\n"); + if (ipa3_send_cmd_timeout(1, &desc, + IPA_DMA_TASK_FOR_GSI_TIMEOUT_MSEC)) { + IPAERR("ipa3_send_cmd failed\n"); + ipa_assert(); + } + ipahal_destroy_imm_cmd(cmd_pyld); +} + int ipa3_suspend_apps_pipes(bool suspend) { int res; + enum ipa_client_type client; - res = _ipa_suspend_pipe(IPA_CLIENT_APPS_LAN_CONS, suspend); - if (res) - return res; + if (suspend) + ipa3_force_close_coal(); - res = _ipa_suspend_pipe(IPA_CLIENT_APPS_WAN_CONS, suspend); - if (res) - return res; + for (client = 0; client < IPA_CLIENT_MAX; client++) { + if (IPA_CLIENT_IS_APPS_CONS(client)) { + res = _ipa_suspend_resume_pipe(client, suspend); + if (res) + goto undo_cons; + } + } + + if (suspend) { + struct ipahal_reg_tx_wrapper tx; + int ep_idx; + + ep_idx = ipa3_get_ep_mapping(IPA_CLIENT_APPS_WAN_COAL_CONS); + if (ep_idx == IPA_EP_NOT_ALLOCATED || + (!ipa3_ctx->ep[ep_idx].valid)) + goto do_prod; + + ipahal_read_reg_fields(IPA_STATE_TX_WRAPPER, &tx); + if (tx.coal_slave_open_frame != 0) { + IPADBG("COAL frame is open 0x%x\n", + tx.coal_slave_open_frame); + goto undo_cons; + } + + usleep_range(IPA_TAG_SLEEP_MIN_USEC, IPA_TAG_SLEEP_MAX_USEC); + + res = ipahal_read_reg_n(IPA_SUSPEND_IRQ_INFO_EE_n, + ipa3_ctx->ee); + if (res) { + IPADBG("suspend irq is pending 0x%x\n", res); + goto undo_cons; + } + } +do_prod: + for (client = 0; client < IPA_CLIENT_MAX; client++) { + if (IPA_CLIENT_IS_APPS_PROD(client)) { + res = _ipa_suspend_resume_pipe(client, suspend); + if (res) + goto undo_prod; + } + } return 0; +undo_prod: + for (client--; client < IPA_CLIENT_MAX && client >= 0; client--) + if (IPA_CLIENT_IS_APPS_PROD(client)) + _ipa_suspend_resume_pipe(client, !suspend); + client = IPA_CLIENT_MAX; +undo_cons: + for (client--; client < IPA_CLIENT_MAX && client >= 0; client--) + if (IPA_CLIENT_IS_APPS_CONS(client)) + _ipa_suspend_resume_pipe(client, !suspend); + return res; } int ipa3_allocate_dma_task_for_gsi(void) 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 6bf24c86c80b..440788fa0b25 100644 --- a/drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal_reg.c +++ b/drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal_reg.c @@ -1180,6 +1180,112 @@ static void ipareg_parse_comp_cfg_v4_5( IPA_COMP_CFG_IPA_FULL_FLUSH_WAIT_RSC_CLOSURE_EN_BMSK_v4_5); } +static void ipareg_parse_state_tx_wrapper_v4_5( + enum ipahal_reg_name reg, void *fields, u32 val) +{ + struct ipahal_reg_tx_wrapper *tx = + (struct ipahal_reg_tx_wrapper *)fields; + + tx->tx0_idle = IPA_GETFIELD_FROM_REG(val, + IPA_STATE_TX_WRAPPER_TX0_IDLE_SHFT, + IPA_STATE_TX_WRAPPER_TX0_IDLE_BMSK); + + tx->tx1_idle = IPA_GETFIELD_FROM_REG(val, + IPA_STATE_TX_WRAPPER_TX1_IDLE_SHFT, + IPA_STATE_TX_WRAPPER_TX1_IDLE_BMSK); + + tx->ipa_prod_ackmngr_db_empty = IPA_GETFIELD_FROM_REG(val, + IPA_STATE_TX_WRAPPER_IPA_PROD_ACKMNGR_DB_EMPTY_SHFT, + IPA_STATE_TX_WRAPPER_IPA_PROD_ACKMNGR_DB_EMPTY_BMSK); + + tx->ipa_prod_ackmngr_state_idle = IPA_GETFIELD_FROM_REG(val, + IPA_STATE_TX_WRAPPER_IPA_PROD_ACKMNGR_STATE_IDLE_SHFT, + IPA_STATE_TX_WRAPPER_IPA_PROD_ACKMNGR_STATE_IDLE_BMSK); + + tx->ipa_prod_prod_bresp_empty = IPA_GETFIELD_FROM_REG(val, + IPA_STATE_TX_WRAPPER_IPA_PROD_BRESP_EMPTY_SHFT, + IPA_STATE_TX_WRAPPER_IPA_PROD_BRESP_EMPTY_BMSK); + + tx->ipa_prod_prod_bresp_toggle_idle = IPA_GETFIELD_FROM_REG(val, + IPA_STATE_TX_WRAPPER_IPA_PROD_BRESP_EMPTY_SHFT, + IPA_STATE_TX_WRAPPER_IPA_PROD_BRESP_EMPTY_BMSK); + + tx->ipa_mbim_pkt_fms_idle = IPA_GETFIELD_FROM_REG(val, + IPA_STATE_TX_WRAPPER_IPA_MBIM_PKT_FMS_IDLE_SHFT, + IPA_STATE_TX_WRAPPER_IPA_MBIM_PKT_FMS_IDLE_BMSK); + + tx->mbim_direct_dma = IPA_GETFIELD_FROM_REG(val, + IPA_STATE_TX_WRAPPER_MBIM_DIRECT_DMA_SHFT, + IPA_STATE_TX_WRAPPER_MBIM_DIRECT_DMA_BMSK); + + tx->trnseq_force_valid = IPA_GETFIELD_FROM_REG(val, + IPA_STATE_TX_WRAPPER_TRNSEQ_FORCE_VALID_SHFT, + IPA_STATE_TX_WRAPPER_TRNSEQ_FORCE_VALID_BMSK); + + tx->pkt_drop_cnt_idle = IPA_GETFIELD_FROM_REG(val, + IPA_STATE_TX_WRAPPER_PKT_DROP_CNT_IDLE_SHFT, + IPA_STATE_TX_WRAPPER_PKT_DROP_CNT_IDLE_BMSK); + + tx->nlo_direct_dma = IPA_GETFIELD_FROM_REG(val, + IPA_STATE_TX_WRAPPER_NLO_DIRECT_DMA_SHFT, + IPA_STATE_TX_WRAPPER_NLO_DIRECT_DMA_BMSK); + + tx->coal_direct_dma = IPA_GETFIELD_FROM_REG(val, + IPA_STATE_TX_WRAPPER_COAL_DIRECT_DMA_SHFT, + IPA_STATE_TX_WRAPPER_COAL_DIRECT_DMA_BMSK); + + tx->coal_slave_idle = IPA_GETFIELD_FROM_REG(val, + IPA_STATE_TX_WRAPPER_COAL_SLAVE_IDLE_SHFT, + IPA_STATE_TX_WRAPPER_COAL_SLAVE_IDLE_BMSK); + + tx->coal_slave_ctx_idle = IPA_GETFIELD_FROM_REG(val, + IPA_STATE_TX_WRAPPER_COAL_SLAVE_CTX_IDLE_SHFT, + IPA_STATE_TX_WRAPPER_COAL_SLAVE_CTX_IDLE_BMSK); + + tx->coal_slave_open_frame = IPA_GETFIELD_FROM_REG(val, + IPA_STATE_TX_WRAPPER_COAL_SLAVE_OPEN_FRAME_SHFT, + IPA_STATE_TX_WRAPPER_COAL_SLAVE_OPEN_FRAME_BMSK); +} + +static void ipareg_parse_state_tx_wrapper_v4_7( + enum ipahal_reg_name reg, void *fields, u32 val) +{ + struct ipahal_reg_tx_wrapper *tx = + (struct ipahal_reg_tx_wrapper *)fields; + + tx->tx0_idle = IPA_GETFIELD_FROM_REG(val, + IPA_STATE_TX_WRAPPER_TX0_IDLE_SHFT_v4_7, + IPA_STATE_TX_WRAPPER_TX0_IDLE_BMSK_v4_7); + + tx->tx1_idle = IPA_GETFIELD_FROM_REG(val, + IPA_STATE_TX_WRAPPER_TX1_IDLE_SHFT_v4_7, + IPA_STATE_TX_WRAPPER_TX1_IDLE_BMSK_v4_7); + + tx->ipa_prod_ackmngr_db_empty = IPA_GETFIELD_FROM_REG(val, + IPA_STATE_TX_WRAPPER_IPA_PROD_ACKMNGR_DB_EMPTY_SHFT_v4_7, + IPA_STATE_TX_WRAPPER_IPA_PROD_ACKMNGR_DB_EMPTY_BMSK_v4_7); + + tx->ipa_prod_ackmngr_state_idle = IPA_GETFIELD_FROM_REG(val, + IPA_STATE_TX_WRAPPER_IPA_PROD_ACKMNGR_STATE_IDLE_SHFT_v4_7, + IPA_STATE_TX_WRAPPER_IPA_PROD_ACKMNGR_STATE_IDLE_BMSK_v4_7); + + tx->ipa_prod_prod_bresp_empty = IPA_GETFIELD_FROM_REG(val, + IPA_STATE_TX_WRAPPER_IPA_PROD_BRESP_EMPTY_SHFT_v4_7, + IPA_STATE_TX_WRAPPER_IPA_PROD_BRESP_EMPTY_BMSK_v4_7); + + tx->coal_slave_idle = IPA_GETFIELD_FROM_REG(val, + IPA_STATE_TX_WRAPPER_COAL_SLAVE_IDLE_SHFT_v4_7, + IPA_STATE_TX_WRAPPER_COAL_SLAVE_IDLE_BMSK_v4_7); + + tx->coal_slave_ctx_idle = IPA_GETFIELD_FROM_REG(val, + IPA_STATE_TX_WRAPPER_COAL_SLAVE_CTX_IDLE_SHFT_v4_7, + IPA_STATE_TX_WRAPPER_COAL_SLAVE_CTX_IDLE_BMSK_v4_7); + + tx->coal_slave_open_frame = IPA_GETFIELD_FROM_REG(val, + IPA_STATE_TX_WRAPPER_COAL_SLAVE_OPEN_FRAME_SHFT_v4_7, + IPA_STATE_TX_WRAPPER_COAL_SLAVE_OPEN_FRAME_BMSK_v4_7); +} + static void ipareg_construct_qcncm( enum ipahal_reg_name reg, const void *fields, u32 *val) { @@ -2968,6 +3074,9 @@ static struct ipahal_reg_obj ipahal_reg_objs[IPA_HW_MAX][IPA_REG_MAX] = { [IPA_HW_v4_5][IPA_COMP_CFG] = { ipareg_construct_comp_cfg_v4_5, ipareg_parse_comp_cfg_v4_5, 0x0000003C, 0, 0, 0, 0}, + [IPA_HW_v4_5][IPA_STATE_TX_WRAPPER] = { + ipareg_construct_dummy, ipareg_parse_state_tx_wrapper_v4_5, + 0x00000090, 0, 0, 0, 1 }, [IPA_HW_v4_5][IPA_STATE_FETCHER_MASK] = { ipareg_construct_dummy, ipareg_parse_dummy, -1, 0, 0, 0, 0}, @@ -3167,6 +3276,9 @@ static struct ipahal_reg_obj ipahal_reg_objs[IPA_HW_MAX][IPA_REG_MAX] = { [IPA_HW_v4_5][IPA_COAL_QMAP_CFG] = { ipareg_construct_coal_qmap_cfg, ipareg_parse_coal_qmap_cfg, 0x00001810, 0, 0, 0, 0}, + [IPA_HW_v4_7][IPA_STATE_TX_WRAPPER] = { + ipareg_construct_dummy, ipareg_parse_state_tx_wrapper_v4_7, + 0x00000090, 0, 0, 0, 1 }, }; /* 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 bbe2f303791c..4a1059ad930b 100644 --- a/drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal_reg.h +++ b/drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal_reg.h @@ -379,6 +379,27 @@ struct ipahal_reg_comp_cfg { bool enable; }; +/* + * struct ipahal_reg_tx_wrapper- IPA TX Wrapper state information + */ +struct ipahal_reg_tx_wrapper { + bool tx0_idle; + bool tx1_idle; + bool ipa_prod_ackmngr_db_empty; + bool ipa_prod_ackmngr_state_idle; + bool ipa_prod_prod_bresp_empty; + bool ipa_prod_prod_bresp_toggle_idle; + bool ipa_mbim_pkt_fms_idle; + u8 mbim_direct_dma; + bool trnseq_force_valid; + bool pkt_drop_cnt_idle; + u8 nlo_direct_dma; + u8 coal_direct_dma; + bool coal_slave_idle; + bool coal_slave_ctx_idle; + u8 coal_slave_open_frame; +}; + /* * struct ipa_hash_tuple - Hash tuple members for flt and rt * the fields tells if to be masked or not 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 43c30234546f..64737923a381 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 @@ -626,5 +626,52 @@ int ipahal_reg_init(enum ipa_hw_type ipa_hw_type); #define IPA_COAL_QMAP_CFG_BMSK 0x1 #define IPA_COAL_QMAP_CFG_SHFT 0 +#define IPA_STATE_TX_WRAPPER_COAL_SLAVE_OPEN_FRAME_BMSK 0xf0000000 +#define IPA_STATE_TX_WRAPPER_COAL_SLAVE_OPEN_FRAME_SHFT 0x1f +#define IPA_STATE_TX_WRAPPER_COAL_SLAVE_CTX_IDLE_BMSK 0x100000 +#define IPA_STATE_TX_WRAPPER_COAL_SLAVE_CTX_IDLE_SHFT 0x10 +#define IPA_STATE_TX_WRAPPER_COAL_SLAVE_IDLE_BMSK 0x8000 +#define IPA_STATE_TX_WRAPPER_COAL_SLAVE_IDLE_SHFT 0xf +#define IPA_STATE_TX_WRAPPER_COAL_DIRECT_DMA_BMSK 0x6000 +#define IPA_STATE_TX_WRAPPER_COAL_DIRECT_DMA_SHFT 0xd +#define IPA_STATE_TX_WRAPPER_NLO_DIRECT_DMA_BMSK 0x1800 +#define IPA_STATE_TX_WRAPPER_NLO_DIRECT_DMA_SHFT 0xb +#define IPA_STATE_TX_WRAPPER_PKT_DROP_CNT_IDLE_BMSK 0x400 +#define IPA_STATE_TX_WRAPPER_PKT_DROP_CNT_IDLE_SHFT 0xa +#define IPA_STATE_TX_WRAPPER_TRNSEQ_FORCE_VALID_BMSK 0x200 +#define IPA_STATE_TX_WRAPPER_TRNSEQ_FORCE_VALID_SHFT 0x9 +#define IPA_STATE_TX_WRAPPER_MBIM_DIRECT_DMA_BMSK 0x180 +#define IPA_STATE_TX_WRAPPER_MBIM_DIRECT_DMA_SHFT 0x7 +#define IPA_STATE_TX_WRAPPER_IPA_MBIM_PKT_FMS_IDLE_BMSK 0x40 +#define IPA_STATE_TX_WRAPPER_IPA_MBIM_PKT_FMS_IDLE_SHFT 0x6 +#define IPA_STATE_TX_WRAPPER_IPA_PROD_BRESP_TOGGLE_IDLE_BMSK 0x20 +#define IPA_STATE_TX_WRAPPER_IPA_PROD_BRESP_TOGGLE_IDLE_SHFT 0x5 +#define IPA_STATE_TX_WRAPPER_IPA_PROD_BRESP_EMPTY_BMSK 0x10 +#define IPA_STATE_TX_WRAPPER_IPA_PROD_BRESP_EMPTY_SHFT 0x4 +#define IPA_STATE_TX_WRAPPER_IPA_PROD_ACKMNGR_STATE_IDLE_BMSK 0x8 +#define IPA_STATE_TX_WRAPPER_IPA_PROD_ACKMNGR_STATE_IDLE_SHFT 0x3 +#define IPA_STATE_TX_WRAPPER_IPA_PROD_ACKMNGR_DB_EMPTY_BMSK 0x4 +#define IPA_STATE_TX_WRAPPER_IPA_PROD_ACKMNGR_DB_EMPTY_SHFT 0x2 +#define IPA_STATE_TX_WRAPPER_TX1_IDLE_BMSK 0x2 +#define IPA_STATE_TX_WRAPPER_TX1_IDLE_SHFT 0x1 +#define IPA_STATE_TX_WRAPPER_TX0_IDLE_BMSK 0x1 +#define IPA_STATE_TX_WRAPPER_TX0_IDLE_SHFT 0x0 + +#define IPA_STATE_TX_WRAPPER_COAL_SLAVE_OPEN_FRAME_BMSK_v4_7 0xf0000000 +#define IPA_STATE_TX_WRAPPER_COAL_SLAVE_OPEN_FRAME_SHFT_v4_7 28 +#define IPA_STATE_TX_WRAPPER_COAL_SLAVE_CTX_IDLE_BMSK_v4_7 0x80000 +#define IPA_STATE_TX_WRAPPER_COAL_SLAVE_CTX_IDLE_SHFT_v4_7 19 +#define IPA_STATE_TX_WRAPPER_COAL_SLAVE_IDLE_BMSK_v4_7 0x40000 +#define IPA_STATE_TX_WRAPPER_COAL_SLAVE_IDLE_SHFT_v4_7 18 +#define IPA_STATE_TX_WRAPPER_IPA_PROD_BRESP_EMPTY_BMSK_v4_7 0x10 +#define IPA_STATE_TX_WRAPPER_IPA_PROD_BRESP_EMPTY_SHFT_v4_7 4 +#define IPA_STATE_TX_WRAPPER_IPA_PROD_ACKMNGR_STATE_IDLE_BMSK_v4_7 0x8 +#define IPA_STATE_TX_WRAPPER_IPA_PROD_ACKMNGR_STATE_IDLE_SHFT_v4_7 3 +#define IPA_STATE_TX_WRAPPER_IPA_PROD_ACKMNGR_DB_EMPTY_BMSK_v4_7 0x4 +#define IPA_STATE_TX_WRAPPER_IPA_PROD_ACKMNGR_DB_EMPTY_SHFT_v4_7 2 +#define IPA_STATE_TX_WRAPPER_TX1_IDLE_BMSK_v4_7 0x2 +#define IPA_STATE_TX_WRAPPER_TX1_IDLE_SHFT_v4_7 1 +#define IPA_STATE_TX_WRAPPER_TX0_IDLE_BMSK_v4_7 0x1 +#define IPA_STATE_TX_WRAPPER_TX0_IDLE_SHFT_v4_7 0 #endif /* _IPAHAL_REG_I_H_ */