From 7d931ff37db62e92669424be8ec86039e90d3e22 Mon Sep 17 00:00:00 2001 From: Sravan Kumar Kairam Date: Tue, 13 Mar 2018 09:42:02 +0530 Subject: [PATCH] qcacld-3.0: Move IPA FW OP event handler to IPA component IPA module has been moved to CLD component under the converged driver model. Move the legacy HDD IPA FW OP event handler to the IPA component. Change-Id: Idecf12c33a5b4ab80de50626029ff43b5f9336a2 CRs-Fixed: 2177925 --- components/ipa/core/inc/wlan_ipa_core.h | 19 ++ components/ipa/core/inc/wlan_ipa_main.h | 10 + components/ipa/core/src/wlan_ipa_core.c | 270 ++++++++++++++++++ components/ipa/core/src/wlan_ipa_main.c | 19 ++ .../ipa/dispatcher/inc/wlan_ipa_ucfg_api.h | 16 ++ .../ipa/dispatcher/src/wlan_ipa_ucfg_api.c | 6 + 6 files changed, 340 insertions(+) diff --git a/components/ipa/core/inc/wlan_ipa_core.h b/components/ipa/core/inc/wlan_ipa_core.h index e0369fa3e9d0..c7583d6943c9 100644 --- a/components/ipa/core/inc/wlan_ipa_core.h +++ b/components/ipa/core/inc/wlan_ipa_core.h @@ -513,5 +513,24 @@ QDF_STATUS wlan_ipa_suspend(struct wlan_ipa_priv *ipa_ctx); */ QDF_STATUS wlan_ipa_resume(struct wlan_ipa_priv *ipa_ctx); +#ifndef QCA_LL_TX_FLOW_CONTROL_V2 +/** + * wlan_ipa_send_mcc_scc_msg() - Send IPA WLAN_SWITCH_TO_MCC/SCC message + * @ipa_ctx: IPA context + * @mcc_mode: 0=MCC/1=SCC + * + * Return: QDF STATUS + */ +QDF_STATUS wlan_ipa_send_mcc_scc_msg(struct wlan_ipa_priv *ipa_ctx, + bool mcc_mode); +#else +static inline +QDF_STATUS wlan_ipa_send_mcc_scc_msg(struct wlan_ipa_priv *ipa_ctx, + bool mcc_mode) +{ + return QDF_STATUS_SUCCESS; +} +#endif + #endif /* IPA_OFFLOAD */ #endif /* _WLAN_IPA_CORE_H_ */ diff --git a/components/ipa/core/inc/wlan_ipa_main.h b/components/ipa/core/inc/wlan_ipa_main.h index 068b9da777df..d804b75a5a72 100644 --- a/components/ipa/core/inc/wlan_ipa_main.h +++ b/components/ipa/core/inc/wlan_ipa_main.h @@ -316,5 +316,15 @@ QDF_STATUS ipa_uc_ol_init(struct wlan_objmgr_pdev *pdev, */ QDF_STATUS ipa_uc_ol_deinit(struct wlan_objmgr_pdev *pdev); +/** + * ipa_send_mcc_scc_msg() - Send IPA WLAN_SWITCH_TO_MCC/SCC message + * @pdev: pdev obj + * @mcc_mode: 0=MCC/1=SCC + * + * Return: QDF STATUS + */ +QDF_STATUS ipa_send_mcc_scc_msg(struct wlan_objmgr_pdev *pdev, + bool mcc_mode); + #endif /* IPA_OFFLOAD */ #endif /* end of _WLAN_IPA_MAIN_H_ */ diff --git a/components/ipa/core/src/wlan_ipa_core.c b/components/ipa/core/src/wlan_ipa_core.c index d0d21dbf3852..c9be3aaac779 100644 --- a/components/ipa/core/src/wlan_ipa_core.c +++ b/components/ipa/core/src/wlan_ipa_core.c @@ -1353,6 +1353,240 @@ struct wlan_ipa_iface_context return NULL; } +#ifndef QCA_LL_TX_FLOW_CONTROL_V2 +QDF_STATUS wlan_ipa_send_mcc_scc_msg(struct wlan_ipa_priv *ipa_ctx, + bool mcc_mode) +{ + qdf_ipa_msg_meta_t meta; + qdf_ipa_wlan_msg_t *msg; + int ret; + + if (!wlan_ipa_uc_sta_is_enabled(ipa_ctx->config)) + return QDF_STATUS_SUCCESS; + + /* Send SCC/MCC Switching event to IPA */ + QDF_IPA_MSG_META_MSG_LEN(&meta) = sizeof(*msg); + msg = qdf_mem_malloc(QDF_IPA_MSG_META_MSG_LEN(&meta)); + if (msg == NULL) { + ipa_err("msg allocation failed"); + return QDF_STATUS_E_NOMEM; + } + + QDF_IPA_MSG_META_MSG_TYPE(&meta) = mcc_mode ? + WLAN_SWITCH_TO_MCC : WLAN_SWITCH_TO_SCC; + WLAN_IPA_LOG(QDF_TRACE_LEVEL_DEBUG, + "ipa_send_msg(Evt:%d)", + QDF_IPA_MSG_META_MSG_TYPE(&meta)); + + ret = qdf_ipa_send_msg(&meta, msg, wlan_ipa_msg_free_fn); + + if (ret) { + ipa_err("ipa_send_msg(Evt:%d) - fail=%d", + QDF_IPA_MSG_META_MSG_TYPE(&meta), ret); + qdf_mem_free(msg); + return QDF_STATUS_E_FAILURE; + } + + return QDF_STATUS_SUCCESS; +} +#endif + +/** + * wlan_ipa_uc_loaded_handler() - Process IPA uC loaded indication + * @ipa_ctx: ipa ipa local context + * + * Will handle IPA UC image loaded indication comes from IPA kernel + * + * Return: None + */ +static void wlan_ipa_uc_loaded_handler(struct wlan_ipa_priv *ipa_ctx) +{ + struct wlan_objmgr_pdev *pdev = ipa_ctx->pdev; + struct wlan_objmgr_psoc *psoc = wlan_pdev_get_psoc(pdev); + qdf_device_t qdf_dev = wlan_psoc_get_qdf_dev(psoc); + QDF_STATUS status; + + ipa_info("UC READY"); + if (true == ipa_ctx->uc_loaded) { + ipa_info("UC already loaded"); + return; + } + + ipa_ctx->uc_loaded = true; + + /* Connect pipe */ + status = wlan_ipa_wdi_setup(ipa_ctx, qdf_dev); + if (status) { + ipa_err("Failure to setup IPA pipes (status=%d)", + status); + return; + } + + cdp_ipa_set_doorbell_paddr(ipa_ctx->dp_soc, ipa_ctx->dp_pdev); +} + +/** + * wlan_ipa_uc_op_cb() - IPA uC operation callback + * @op_msg: operation message received from firmware + * @usr_ctxt: user context registered with TL (we register the IPA Global + * context) + * + * Return: None + */ +static void wlan_ipa_uc_op_cb(struct op_msg_type *op_msg, + struct wlan_ipa_priv *ipa_ctx) +{ + struct op_msg_type *msg = op_msg; + struct ipa_uc_fw_stats *uc_fw_stat; + + if (!op_msg) { + ipa_err("INVALID ARG"); + return; + } + + if (msg->op_code >= WLAN_IPA_UC_OPCODE_MAX) { + ipa_err("INVALID OPCODE %d", msg->op_code); + qdf_mem_free(op_msg); + return; + } + + ipa_debug("OPCODE=%d", msg->op_code); + + if ((msg->op_code == WLAN_IPA_UC_OPCODE_TX_RESUME) || + (msg->op_code == WLAN_IPA_UC_OPCODE_RX_RESUME)) { + qdf_mutex_acquire(&ipa_ctx->ipa_lock); + ipa_ctx->activated_fw_pipe++; + if (ipa_ctx->activated_fw_pipe == WLAN_IPA_UC_NUM_WDI_PIPE) { + ipa_ctx->resource_loading = false; + qdf_event_set(&ipa_ctx->ipa_resource_comp); + if (ipa_ctx->wdi_enabled == false) { + ipa_ctx->wdi_enabled = true; + if (wlan_ipa_uc_send_wdi_control_msg(true) == 0) + wlan_ipa_send_mcc_scc_msg(ipa_ctx, + ipa_ctx->mcc_mode); + } + if (ipa_ctx->pending_cons_req) + qdf_ipa_rm_notify_completion( + QDF_IPA_RM_RESOURCE_GRANTED, + QDF_IPA_RM_RESOURCE_WLAN_CONS); + ipa_ctx->pending_cons_req = false; + } + qdf_mutex_release(&ipa_ctx->ipa_lock); + } else if ((msg->op_code == WLAN_IPA_UC_OPCODE_TX_SUSPEND) || + (msg->op_code == WLAN_IPA_UC_OPCODE_RX_SUSPEND)) { + qdf_mutex_acquire(&ipa_ctx->ipa_lock); + ipa_ctx->activated_fw_pipe--; + if (!ipa_ctx->activated_fw_pipe) { + /* + * Async return success from FW + * Disable/suspend all the PIPEs + */ + ipa_ctx->resource_unloading = false; + qdf_event_set(&ipa_ctx->ipa_resource_comp); + wlan_ipa_uc_disable_pipes(ipa_ctx); + if (wlan_ipa_is_rm_enabled(ipa_ctx->config)) + qdf_ipa_rm_release_resource( + QDF_IPA_RM_RESOURCE_WLAN_PROD); + ipa_ctx->pending_cons_req = false; + } + qdf_mutex_release(&ipa_ctx->ipa_lock); + } else if ((msg->op_code == WLAN_IPA_UC_OPCODE_STATS) && + (ipa_ctx->stat_req_reason == WLAN_IPA_UC_STAT_REASON_DEBUG)) { + uc_fw_stat = (struct ipa_uc_fw_stats *) + ((uint8_t *)op_msg + sizeof(struct op_msg_type)); + + /* WLAN FW WDI stats */ + wlan_ipa_print_fw_wdi_stats(ipa_ctx, uc_fw_stat); + } else if ((msg->op_code == WLAN_IPA_UC_OPCODE_STATS) && + (ipa_ctx->stat_req_reason == WLAN_IPA_UC_STAT_REASON_BW_CAL)) { + /* STATs from FW */ + uc_fw_stat = (struct ipa_uc_fw_stats *) + ((uint8_t *)op_msg + sizeof(struct op_msg_type)); + qdf_mutex_acquire(&ipa_ctx->ipa_lock); + ipa_ctx->ipa_tx_packets_diff = BW_GET_DIFF( + uc_fw_stat->tx_pkts_completed, + ipa_ctx->ipa_p_tx_packets); + ipa_ctx->ipa_rx_packets_diff = BW_GET_DIFF( + (uc_fw_stat->rx_num_ind_drop_no_space + + uc_fw_stat->rx_num_ind_drop_no_buf + + uc_fw_stat->rx_num_pkts_indicated), + ipa_ctx->ipa_p_rx_packets); + + ipa_ctx->ipa_p_tx_packets = uc_fw_stat->tx_pkts_completed; + ipa_ctx->ipa_p_rx_packets = + (uc_fw_stat->rx_num_ind_drop_no_space + + uc_fw_stat->rx_num_ind_drop_no_buf + + uc_fw_stat->rx_num_pkts_indicated); + qdf_mutex_release(&ipa_ctx->ipa_lock); + } else if (msg->op_code == WLAN_IPA_UC_OPCODE_UC_READY) { + qdf_mutex_acquire(&ipa_ctx->ipa_lock); + wlan_ipa_uc_loaded_handler(ipa_ctx); + qdf_mutex_release(&ipa_ctx->ipa_lock); + } else if (wlan_ipa_uc_op_metering(ipa_ctx, op_msg)) { + ipa_err("Invalid message: op_code=%d, reason=%d", + msg->op_code, ipa_ctx->stat_req_reason); + } + + qdf_mem_free(op_msg); +} + +/** + * wlan_ipa_uc_fw_op_event_handler - IPA uC FW OPvent handler + * @work: uC OP work + * + * Return: None + */ +static void wlan_ipa_uc_fw_op_event_handler(void *data) +{ + struct op_msg_type *msg; + struct uc_op_work_struct *uc_op_work = + (struct uc_op_work_struct *)data; + struct wlan_ipa_priv *ipa_ctx = gp_ipa; + + msg = uc_op_work->msg; + uc_op_work->msg = NULL; + ipa_debug("posted msg %d", msg->op_code); + + wlan_ipa_uc_op_cb(msg, ipa_ctx); +} + +/** + * wlan_ipa_uc_op_event_handler() - IPA UC OP event handler + * @op_msg: operation message received from firmware + * @ipa_ctx: Global IPA context + * + * Return: None + */ +static void wlan_ipa_uc_op_event_handler(uint8_t *op_msg, void *ctx) +{ + struct wlan_ipa_priv *ipa_ctx = (struct wlan_ipa_priv *)ctx; + struct op_msg_type *msg; + struct uc_op_work_struct *uc_op_work; + + if (!ipa_ctx) + goto end; + + msg = (struct op_msg_type *)op_msg; + + if (msg->op_code >= WLAN_IPA_UC_OPCODE_MAX) { + ipa_err("Invalid OP Code (%d)", msg->op_code); + goto end; + } + + uc_op_work = &ipa_ctx->uc_op_work[msg->op_code]; + if (uc_op_work->msg) { + /* When the same uC OPCODE is already pended, just return */ + goto end; + } + + uc_op_work->msg = msg; + qdf_sched_work(0, &uc_op_work->work); + return; + +end: + qdf_mem_free(op_msg); +} + QDF_STATUS wlan_ipa_uc_ol_init(struct wlan_ipa_priv *ipa_ctx, qdf_device_t osdev) { @@ -1397,14 +1631,40 @@ QDF_STATUS wlan_ipa_uc_ol_init(struct wlan_ipa_priv *ipa_ctx, wlan_ipa_init_metering(ipa_ctx); } + cdp_ipa_register_op_cb(ipa_ctx->dp_soc, ipa_ctx->dp_pdev, + wlan_ipa_uc_op_event_handler, (void *)ipa_ctx); + + for (i = 0; i < WLAN_IPA_UC_OPCODE_MAX; i++) { + qdf_create_work(0, &ipa_ctx->uc_op_work[i].work, + wlan_ipa_uc_fw_op_event_handler, + &ipa_ctx->uc_op_work[i]); + ipa_ctx->uc_op_work[i].msg = NULL; + } + fail_return: ipa_debug("exit: status=%d", status); return status; } +/** + * wlan_ipa_cleanup_pending_event() - Cleanup IPA pending event list + * @ipa_ctx: pointer to IPA IPA struct + * + * Return: none + */ +static void wlan_ipa_cleanup_pending_event(struct wlan_ipa_priv *ipa_ctx) +{ + struct wlan_ipa_uc_pending_event *pending_event = NULL; + + while (qdf_list_remove_front(&ipa_ctx->pending_event, + (qdf_list_node_t **)&pending_event) == QDF_STATUS_SUCCESS) + qdf_mem_free(pending_event); +} + QDF_STATUS wlan_ipa_uc_ol_deinit(struct wlan_ipa_priv *ipa_ctx) { QDF_STATUS status = QDF_STATUS_SUCCESS; + int i; ipa_debug("enter"); @@ -1423,6 +1683,16 @@ QDF_STATUS wlan_ipa_uc_ol_deinit(struct wlan_ipa_priv *ipa_ctx) status); } + qdf_mutex_acquire(&ipa_ctx->ipa_lock); + wlan_ipa_cleanup_pending_event(ipa_ctx); + qdf_mutex_release(&ipa_ctx->ipa_lock); + + for (i = 0; i < WLAN_IPA_UC_OPCODE_MAX; i++) { + qdf_cancel_work(&ipa_ctx->uc_op_work[i].work); + qdf_mem_free(ipa_ctx->uc_op_work[i].msg); + ipa_ctx->uc_op_work[i].msg = NULL; + } + ipa_debug("exit: ret=%d", status); return status; } diff --git a/components/ipa/core/src/wlan_ipa_main.c b/components/ipa/core/src/wlan_ipa_main.c index d109ffba5705..fdfaa2d68c2b 100644 --- a/components/ipa/core/src/wlan_ipa_main.c +++ b/components/ipa/core/src/wlan_ipa_main.c @@ -484,3 +484,22 @@ QDF_STATUS ipa_uc_ol_deinit(struct wlan_objmgr_pdev *pdev) return wlan_ipa_uc_ol_deinit(ipa_obj); } + +QDF_STATUS ipa_send_mcc_scc_msg(struct wlan_objmgr_pdev *pdev, + bool mcc_mode) +{ + struct wlan_ipa_priv *ipa_obj; + + if (!g_ipa_hw_support) { + ipa_info("ipa hw not present"); + return QDF_STATUS_E_FAILURE; + } + + ipa_obj = ipa_pdev_get_priv_obj(pdev); + if (!ipa_obj) { + ipa_err("IPA object is NULL"); + return QDF_STATUS_E_FAILURE; + } + + return wlan_ipa_send_mcc_scc_msg(ipa_obj, mcc_mode); +} diff --git a/components/ipa/dispatcher/inc/wlan_ipa_ucfg_api.h b/components/ipa/dispatcher/inc/wlan_ipa_ucfg_api.h index b30dcb5059a9..80869844ee50 100644 --- a/components/ipa/dispatcher/inc/wlan_ipa_ucfg_api.h +++ b/components/ipa/dispatcher/inc/wlan_ipa_ucfg_api.h @@ -228,6 +228,15 @@ QDF_STATUS ucfg_ipa_uc_ol_init(struct wlan_objmgr_pdev *pdev, */ QDF_STATUS ucfg_ipa_uc_ol_deinit(struct wlan_objmgr_pdev *pdev); +/** + * ucfg_ipa_send_mcc_scc_msg() - Send IPA WLAN_SWITCH_TO_MCC/SCC message + * @mcc_mode: 0=MCC/1=SCC + * + * Return: QDF STATUS + */ +QDF_STATUS ucfg_ipa_send_mcc_scc_msg(struct wlan_objmgr_pdev *pdev, + bool mcc_mode); + #else static inline bool ucfg_ipa_is_present(void) @@ -351,5 +360,12 @@ QDF_STATUS ucfg_ipa_uc_ol_deinit(struct wlan_objmgr_pdev *pdev) { return QDF_STATUS_SUCCESS; } + +static inline +QDF_STATUS ucfg_ipa_send_mcc_scc_msg(struct wlan_objmgr_pdev *pdev, + bool mcc_mode) +{ + return QDF_STATUS_SUCCESS; +} #endif /* IPA_OFFLOAD */ #endif /* _WLAN_IPA_UCFG_API_H_ */ diff --git a/components/ipa/dispatcher/src/wlan_ipa_ucfg_api.c b/components/ipa/dispatcher/src/wlan_ipa_ucfg_api.c index 2b8ce8a7ea2e..61c66bb97122 100644 --- a/components/ipa/dispatcher/src/wlan_ipa_ucfg_api.c +++ b/components/ipa/dispatcher/src/wlan_ipa_ucfg_api.c @@ -138,3 +138,9 @@ QDF_STATUS ucfg_ipa_uc_ol_deinit(struct wlan_objmgr_pdev *pdev) { return ipa_uc_ol_deinit(pdev); } + +QDF_STATUS ucfg_ipa_send_mcc_scc_msg(struct wlan_objmgr_pdev *pdev, + bool mcc_mode) +{ + return ipa_send_mcc_scc_msg(pdev, mcc_mode); +}