diff --git a/ipa/core/inc/wlan_ipa_core.h b/ipa/core/inc/wlan_ipa_core.h index f07284184d..fc2d87d593 100644 --- a/ipa/core/inc/wlan_ipa_core.h +++ b/ipa/core/inc/wlan_ipa_core.h @@ -1,6 +1,6 @@ /* * Copyright (c) 2013-2021 The Linux Foundation. All rights reserved. - * Copyright (c) 2021 Qualcomm Innovation Center, Inc. All rights reserved. + * Copyright (c) 2021-2022 Qualcomm Innovation Center, Inc. All rights reserved. * * Permission to use, copy, modify, and/or distribute this software for * any purpose with or without fee is hereby granted, provided that the @@ -770,7 +770,8 @@ static inline void wlan_ipa_mcc_work_handler(void *data) QDF_STATUS wlan_ipa_wlan_evt(qdf_netdev_t net_dev, uint8_t device_mode, uint8_t session_id, enum wlan_ipa_wlan_event ipa_event_type, - uint8_t *mac_addr, bool is_2g_iface); + uint8_t *mac_addr, bool is_2g_iface, + struct wlan_ipa_priv *ipa_obj); /** * wlan_ipa_uc_smmu_map() - Map / Unmap DMA buffer to IPA UC diff --git a/ipa/core/inc/wlan_ipa_main.h b/ipa/core/inc/wlan_ipa_main.h index 3459818af6..19b788204e 100644 --- a/ipa/core/inc/wlan_ipa_main.h +++ b/ipa/core/inc/wlan_ipa_main.h @@ -1,6 +1,6 @@ /* * Copyright (c) 2018-2021 The Linux Foundation. All rights reserved. - * Copyright (c) 2021 Qualcomm Innovation Center, Inc. All rights reserved. + * Copyright (c) 2021-2022 Qualcomm Innovation Center, Inc. All rights reserved. * * Permission to use, copy, modify, and/or distribute this software for * any purpose with or without fee is hereby granted, provided that the @@ -31,6 +31,9 @@ #include #include +/* Declare a variable for IPA instancess added based on pdev */ +extern uint8_t g_instances_added; +#define IPA_INVALID_HDL 0xFF #define ipa_fatal(params...) \ QDF_TRACE_FATAL(QDF_MODULE_ID_IPA, params) #define ipa_err(params...) \ diff --git a/ipa/core/inc/wlan_ipa_priv.h b/ipa/core/inc/wlan_ipa_priv.h index c19f385c93..b5bfe61466 100644 --- a/ipa/core/inc/wlan_ipa_priv.h +++ b/ipa/core/inc/wlan_ipa_priv.h @@ -516,11 +516,13 @@ struct uc_rm_work_struct { * @work: uC OP work * @msg: OP message * @osdev: poiner to qdf net device, used by osif_psoc_sync_trans_start_wait + * @ipa_priv_bp: back pointer to ipa_obj */ struct uc_op_work_struct { qdf_work_t work; struct op_msg_type *msg; qdf_device_t osdev; + struct wlan_ipa_priv *ipa_priv_bp; }; /** @@ -734,6 +736,9 @@ struct wlan_ipa_priv { qdf_atomic_t stats_quota; uint8_t curr_bw_level; qdf_atomic_t deinit_in_prog; + uint8_t instance_id; + bool handle_initialized; + qdf_ipa_wdi_hdl_t hdl; }; #define WLAN_IPA_WLAN_FRAG_HEADER sizeof(struct frag_header) diff --git a/ipa/core/src/wlan_ipa_core.c b/ipa/core/src/wlan_ipa_core.c index 3f50e64a9b..ba4ef16cf4 100644 --- a/ipa/core/src/wlan_ipa_core.c +++ b/ipa/core/src/wlan_ipa_core.c @@ -37,6 +37,8 @@ #include #define IPA_SPS_DESC_SIZE 8 +#define IPA_DEFAULT_HDL 0 + static struct wlan_ipa_priv *gp_ipa; static void wlan_ipa_set_pending_tx_timer(struct wlan_ipa_priv *ipa_ctx); static void wlan_ipa_reset_pending_tx_timer(struct wlan_ipa_priv *ipa_ctx); @@ -542,7 +544,7 @@ wlan_ipa_wdi_setup(struct wlan_ipa_priv *ipa_ctx, &ipa_ctx->tx_pipe_handle, &ipa_ctx->rx_pipe_handle, wlan_ipa_wdi_is_smmu_enabled(ipa_ctx, osdev), - sys_in, ipa_ctx->over_gsi); + sys_in, ipa_ctx->over_gsi, ipa_ctx->hdl); qdf_mem_free(sys_in); @@ -590,6 +592,7 @@ static inline QDF_STATUS wlan_ipa_wdi_init(struct wlan_ipa_priv *ipa_ctx) QDF_IPA_WDI_INIT_IN_PARAMS_WDI_VERSION(&in) = ipa_ctx->wdi_version; QDF_IPA_WDI_INIT_IN_PARAMS_NOTIFY(&in) = wlan_ipa_uc_loaded_uc_cb; QDF_IPA_WDI_INIT_IN_PARAMS_PRIV(&in) = ipa_ctx; + QDF_IPA_WDI_INIT_IN_PARAMS_INSTANCE_ID(&in) = ipa_ctx->instance_id; wlan_ipa_wdi_init_metering(ipa_ctx, &in); ret = qdf_ipa_wdi_init(&in, &out); @@ -602,8 +605,10 @@ static inline QDF_STATUS wlan_ipa_wdi_init(struct wlan_ipa_priv *ipa_ctx) QDF_IPA_WDI_INIT_OUT_PARAMS_IS_OVER_GSI(&out); ipa_ctx->is_smmu_enabled = QDF_IPA_WDI_INIT_OUT_PARAMS_IS_SMMU_ENABLED(&out); - ipa_info("ipa_over_gsi: %d, is_smmu_enabled: %d", - ipa_ctx->over_gsi, ipa_ctx->is_smmu_enabled); + ipa_ctx->hdl = QDF_IPA_WDI_INIT_OUT_PARAMS_HANDLE(&out); + + ipa_info("ipa_over_gsi: %d, is_smmu_enabled: %d, handle: %d", + ipa_ctx->over_gsi, ipa_ctx->is_smmu_enabled, ipa_ctx->hdl); if (QDF_IPA_WDI_INIT_OUT_PARAMS_IS_UC_READY(&out)) { ipa_debug("IPA uC READY"); @@ -616,11 +621,11 @@ static inline QDF_STATUS wlan_ipa_wdi_init(struct wlan_ipa_priv *ipa_ctx) return QDF_STATUS_SUCCESS; } -static inline int wlan_ipa_wdi_cleanup(void) +static inline int wlan_ipa_wdi_cleanup(qdf_ipa_wdi_hdl_t hdl) { int ret; - ret = qdf_ipa_wdi_cleanup(); + ret = qdf_ipa_wdi_cleanup(hdl); if (ret) ipa_info("ipa_wdi_cleanup failed ret=%d", ret); return ret; @@ -697,11 +702,18 @@ int wlan_ipa_uc_smmu_map(bool map, uint32_t num_buf, qdf_mem_info_t *buf_arr) ipa_info("No buffers to map/unmap"); return 0; } - + /** + * This API will compile for prelithium chipset + * where we have only one soc so passing default + * handle to IPA which is 0. + */ if (map) - return qdf_ipa_wdi_create_smmu_mapping(num_buf, buf_arr); + return qdf_ipa_wdi_create_smmu_mapping(IPA_DEFAULT_HDL, + num_buf, buf_arr); else - return qdf_ipa_wdi_release_smmu_mapping(num_buf, buf_arr); + return qdf_ipa_wdi_release_smmu_mapping(IPA_DEFAULT_HDL, + num_buf, buf_arr); + return 0; } #ifdef MDM_PLATFORM @@ -945,9 +957,12 @@ int wlan_ipa_uc_smmu_map(bool map, uint32_t num_buf, qdf_mem_info_t *buf_arr) } if (map) - return qdf_ipa_wdi_create_smmu_mapping(num_buf, buf_arr); + return qdf_ipa_wdi_create_smmu_mapping(IPA_DEFAULT_HDL, + num_buf, buf_arr); else - return qdf_ipa_wdi_release_smmu_mapping(num_buf, buf_arr); + return qdf_ipa_wdi_release_smmu_mapping(IPA_DEFAULT_HDL, + num_buf, buf_arr); + return 0; } static enum wlan_ipa_forward_type @@ -976,10 +991,14 @@ wlan_ipa_rx_intrabss_fwd(struct wlan_ipa_priv *ipa_ctx, static int wlan_ipa_send_sta_eapol_to_nw(qdf_nbuf_t skb, struct wlan_objmgr_pdev *pdev) { - struct wlan_ipa_priv *ipa_ctx = gp_ipa; + struct wlan_ipa_priv *ipa_ctx; struct ethhdr *eh; struct wlan_objmgr_vdev *vdev = NULL; + ipa_ctx = ipa_pdev_get_priv_obj(pdev); + if (!ipa_ctx) + return -EINVAL; + eh = (struct ethhdr *)qdf_nbuf_data(skb); vdev = wlan_objmgr_get_vdev_by_macaddr_from_pdev( pdev, eh->h_dest, WLAN_IPA_ID); @@ -1019,7 +1038,9 @@ static void wlan_ipa_send_skb_to_network(qdf_nbuf_t skb, struct wlan_ipa_iface_context *iface_ctx) { - struct wlan_ipa_priv *ipa_ctx = gp_ipa; + struct wlan_ipa_priv *ipa_ctx; + + ipa_ctx = iface_ctx->ipa_ctx; if (!iface_ctx->dev) { ipa_debug_rl("Invalid interface"); @@ -1513,7 +1534,8 @@ QDF_STATUS wlan_ipa_uc_enable_pipes(struct wlan_ipa_priv *ipa_ctx) if (qdf_atomic_read(&ipa_ctx->pipes_disabled)) { result = cdp_ipa_enable_pipes(ipa_ctx->dp_soc, - ipa_ctx->dp_pdev_id); + ipa_ctx->dp_pdev_id, + ipa_ctx->hdl); if (result) { ipa_err("Enable IPA WDI PIPE failed: ret=%d", result); qdf_status = QDF_STATUS_E_FAILURE; @@ -1573,7 +1595,8 @@ wlan_ipa_uc_disable_pipes(struct wlan_ipa_priv *ipa_ctx, bool force_disable) wlan_ipa_set_pending_tx_timer(ipa_ctx); } else { qdf_status = cdp_ipa_disable_pipes(ipa_ctx->dp_soc, - ipa_ctx->dp_pdev_id); + ipa_ctx->dp_pdev_id, + ipa_ctx->hdl); if (QDF_IS_STATUS_ERROR(qdf_status)) { ipa_err("Disable IPA WDI PIPE failed: ret=%u", qdf_status); @@ -1715,7 +1738,8 @@ static void wlan_ipa_cleanup_iface(struct wlan_ipa_iface_context *iface_context, if (cdp_ipa_cleanup_iface(ipa_ctx->dp_soc, iface_context->dev->name, - wlan_ipa_is_ipv6_enabled(ipa_ctx->config))) { + wlan_ipa_is_ipv6_enabled(ipa_ctx->config), + ipa_ctx->hdl)) { ipa_err("ipa_cleanup_iface failed"); } @@ -1944,7 +1968,8 @@ static QDF_STATUS wlan_ipa_setup_iface(struct wlan_ipa_priv *ipa_ctx, iface_context->cons_client, wlan_ipa_set_session_id(session_id, is_2g_iface), - wlan_ipa_is_ipv6_enabled(ipa_ctx->config)); + wlan_ipa_is_ipv6_enabled(ipa_ctx->config), + ipa_ctx->hdl); if (status != QDF_STATUS_SUCCESS) goto end; @@ -2450,9 +2475,10 @@ wlan_ipa_save_bssid_iface_ctx(struct wlan_ipa_priv *ipa_ctx, uint8_t iface_id, static QDF_STATUS __wlan_ipa_wlan_evt(qdf_netdev_t net_dev, uint8_t device_mode, uint8_t session_id, qdf_ipa_wlan_event type, - uint8_t *mac_addr, bool is_2g_iface) + uint8_t *mac_addr, bool is_2g_iface, + struct wlan_ipa_priv *ipa_obj) { - struct wlan_ipa_priv *ipa_ctx = gp_ipa; + struct wlan_ipa_priv *ipa_ctx; struct wlan_ipa_iface_context *iface_ctx = NULL; qdf_ipa_msg_meta_t meta; qdf_ipa_wlan_msg_t *msg; @@ -2470,6 +2496,7 @@ static QDF_STATUS __wlan_ipa_wlan_evt(qdf_netdev_t net_dev, uint8_t device_mode, if (type >= QDF_IPA_WLAN_EVENT_MAX) return QDF_STATUS_E_INVAL; + ipa_ctx = ipa_obj; if (wlan_ipa_uc_is_enabled(ipa_ctx->config) && !wlan_ipa_uc_sta_is_enabled(ipa_ctx->config) && (device_mode != QDF_SAP_MODE)) { @@ -3174,7 +3201,8 @@ static uint8_t wlan_ipa_device_mode_switch(uint8_t device_mode) QDF_STATUS wlan_ipa_wlan_evt(qdf_netdev_t net_dev, uint8_t device_mode, uint8_t session_id, enum wlan_ipa_wlan_event ipa_event_type, - uint8_t *mac_addr, bool is_2g_iface) + uint8_t *mac_addr, bool is_2g_iface, + struct wlan_ipa_priv *ipa_obj) { qdf_ipa_wlan_event type = wlan_host_to_ipa_wlan_event(ipa_event_type); QDF_STATUS status = QDF_STATUS_SUCCESS; @@ -3186,7 +3214,7 @@ QDF_STATUS wlan_ipa_wlan_evt(qdf_netdev_t net_dev, uint8_t device_mode, (device_mode == QDF_SAP_MODE)) status = __wlan_ipa_wlan_evt(net_dev, device_mode, session_id, type, mac_addr, - is_2g_iface); + is_2g_iface, ipa_obj); return status; } @@ -3226,7 +3254,7 @@ wlan_ipa_uc_proc_pending_event(struct wlan_ipa_priv *ipa_ctx, bool is_loading) pending_event->session_id, pending_event->type, pending_event->mac_addr, - pending_event->is_2g_iface); + pending_event->is_2g_iface, ipa_ctx); } if (vdev) @@ -3427,7 +3455,8 @@ static inline uint8_t wlan_ipa_get_rx_ipa_client(struct wlan_ipa_priv *ipa_ctx) * * Return: QDF_STATUS */ -static QDF_STATUS wlan_ipa_uc_send_wdi_control_msg(bool ctrl) +static QDF_STATUS wlan_ipa_uc_send_wdi_control_msg(struct wlan_ipa_priv *ipa_ctx, + bool ctrl) { return QDF_STATUS_SUCCESS; } @@ -3438,9 +3467,10 @@ static inline uint8_t wlan_ipa_get_rx_ipa_client(struct wlan_ipa_priv *ipa_ctx) return IPA_CLIENT_WLAN1_PROD; } -static QDF_STATUS wlan_ipa_uc_send_wdi_control_msg(bool ctrl) +static QDF_STATUS wlan_ipa_uc_send_wdi_control_msg(struct wlan_ipa_priv *ipa_ctx, + bool ctrl) { - struct wlan_ipa_priv *ipa_ctx = gp_ipa; + struct wlan_ipa_priv *ipa_obj = ipa_ctx; qdf_ipa_msg_meta_t meta; qdf_ipa_wlan_msg_t *ipa_msg; int ret = 0; @@ -3453,10 +3483,10 @@ static QDF_STATUS wlan_ipa_uc_send_wdi_control_msg(bool ctrl) if (ctrl) { QDF_IPA_SET_META_MSG_TYPE(&meta, QDF_WDI_ENABLE); - ipa_ctx->stats.event[QDF_WDI_ENABLE]++; + ipa_obj->stats.event[QDF_WDI_ENABLE]++; } else { QDF_IPA_SET_META_MSG_TYPE(&meta, QDF_WDI_DISABLE); - ipa_ctx->stats.event[QDF_WDI_DISABLE]++; + ipa_obj->stats.event[QDF_WDI_DISABLE]++; } ipa_debug("ipa_send_msg(Evt:%d)", QDF_IPA_MSG_META_MSG_TYPE(&meta)); @@ -3729,7 +3759,7 @@ QDF_STATUS wlan_ipa_setup(struct wlan_ipa_priv *ipa_ctx, ipa_ctx); } } else if (status == QDF_STATUS_E_BUSY) { - ret = wlan_ipa_uc_send_wdi_control_msg(false); + ret = wlan_ipa_uc_send_wdi_control_msg(ipa_ctx, false); if (ret) { ipa_err("IPA WDI msg send failed: ret=%d", ret); goto ipa_wdi_destroy; @@ -3835,7 +3865,7 @@ QDF_STATUS wlan_ipa_cleanup(struct wlan_ipa_priv *ipa_ctx) } if (wlan_ipa_uc_is_enabled(ipa_ctx->config)) { - wlan_ipa_wdi_cleanup(); + wlan_ipa_wdi_cleanup(ipa_ctx->hdl); qdf_mutex_destroy(&ipa_ctx->event_lock); qdf_mutex_destroy(&ipa_ctx->ipa_lock); qdf_list_destroy(&ipa_ctx->pending_event); @@ -3844,6 +3874,15 @@ QDF_STATUS wlan_ipa_cleanup(struct wlan_ipa_priv *ipa_ctx) gp_ipa = NULL; + /* Acquire lock */ + ipa_init_deinit_lock(); + if (g_instances_added) + g_instances_added--; + /* Unlock */ + ipa_init_deinit_unlock(); + + ipa_ctx->handle_initialized = false; + return QDF_STATUS_SUCCESS; } @@ -3969,7 +4008,7 @@ static void wlan_ipa_uc_loaded_handler(struct wlan_ipa_priv *ipa_ctx) return; smmu_map_fail: - qdf_ipa_wdi_disconn_pipes(); + qdf_ipa_wdi_disconn_pipes(ipa_ctx->hdl); connect_pipe_fail: if (wlan_ipa_uc_sta_is_enabled(ipa_ctx->config)) { @@ -4014,7 +4053,7 @@ static void wlan_ipa_uc_op_cb(struct op_msg_type *op_msg, 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) + if (wlan_ipa_uc_send_wdi_control_msg(ipa_ctx, true) == 0) wlan_ipa_send_mcc_scc_msg(ipa_ctx, ipa_ctx->mcc_mode); } @@ -4103,7 +4142,7 @@ 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; + struct wlan_ipa_priv *ipa_ctx = uc_op_work->ipa_priv_bp; msg = uc_op_work->msg; uc_op_work->msg = NULL; @@ -4198,6 +4237,7 @@ QDF_STATUS wlan_ipa_uc_ol_init(struct wlan_ipa_priv *ipa_ctx, for (i = 0; i < WLAN_IPA_UC_OPCODE_MAX; i++) { ipa_ctx->uc_op_work[i].osdev = osdev; ipa_ctx->uc_op_work[i].msg = NULL; + ipa_ctx->uc_op_work[i].ipa_priv_bp = ipa_ctx; qdf_create_work(0, &ipa_ctx->uc_op_work[i].work, wlan_ipa_uc_fw_op_event_handler, &ipa_ctx->uc_op_work[i]); @@ -4288,7 +4328,7 @@ QDF_STATUS wlan_ipa_uc_ol_deinit(struct wlan_ipa_priv *ipa_ctx) status = cdp_ipa_cleanup(ipa_ctx->dp_soc, ipa_ctx->dp_pdev_id, ipa_ctx->tx_pipe_handle, - ipa_ctx->rx_pipe_handle); + ipa_ctx->rx_pipe_handle, ipa_ctx->hdl); if (status) ipa_err("Failure to cleanup IPA pipes (status=%d)", status); @@ -4314,12 +4354,18 @@ QDF_STATUS wlan_ipa_uc_ol_deinit(struct wlan_ipa_priv *ipa_ctx) */ static QDF_STATUS wlan_ipa_uc_send_evt(qdf_netdev_t net_dev, qdf_ipa_wlan_event type, - uint8_t *mac_addr) + uint8_t *mac_addr, + struct wlan_ipa_priv *ipa_priv) { - struct wlan_ipa_priv *ipa_ctx = gp_ipa; + struct wlan_ipa_priv *ipa_ctx; qdf_ipa_msg_meta_t meta; qdf_ipa_wlan_msg_t *msg; + if (!ipa_priv) + return QDF_STATUS_E_INVAL; + + ipa_ctx = ipa_priv; + QDF_IPA_MSG_META_MSG_LEN(&meta) = sizeof(qdf_ipa_wlan_msg_t); msg = qdf_mem_malloc(QDF_IPA_MSG_META_MSG_LEN(&meta)); if (!msg) @@ -4357,7 +4403,7 @@ void wlan_ipa_uc_cleanup_sta(struct wlan_ipa_priv *ipa_ctx, if (iface_ctx && iface_ctx->device_mode == QDF_STA_MODE && iface_ctx->dev && iface_ctx->dev == net_dev) { wlan_ipa_uc_send_evt(net_dev, QDF_IPA_STA_DISCONNECT, - net_dev->dev_addr); + net_dev->dev_addr, ipa_ctx); wlan_ipa_cleanup_iface(iface_ctx, NULL); } } @@ -4376,7 +4422,7 @@ QDF_STATUS wlan_ipa_uc_disconnect_ap(struct wlan_ipa_priv *ipa_ctx, iface_ctx = wlan_ipa_get_iface(ipa_ctx, QDF_SAP_MODE); if (iface_ctx) status = wlan_ipa_uc_send_evt(net_dev, QDF_IPA_AP_DISCONNECT, - net_dev->dev_addr); + net_dev->dev_addr, ipa_ctx); else return QDF_STATUS_E_INVAL; @@ -4413,11 +4459,13 @@ void wlan_ipa_uc_ssr_cleanup(struct wlan_ipa_priv *ipa_ctx) if (iface->device_mode == QDF_SAP_MODE) wlan_ipa_uc_send_evt(iface->dev, QDF_IPA_AP_DISCONNECT, - iface->dev->dev_addr); + iface->dev->dev_addr, + ipa_ctx); else if (iface->device_mode == QDF_STA_MODE) wlan_ipa_uc_send_evt(iface->dev, QDF_IPA_STA_DISCONNECT, - iface->dev->dev_addr); + iface->dev->dev_addr, + ipa_ctx); wlan_ipa_cleanup_iface(iface, NULL); } } diff --git a/ipa/core/src/wlan_ipa_main.c b/ipa/core/src/wlan_ipa_main.c index 4d0b57dfd7..81fb8d117a 100644 --- a/ipa/core/src/wlan_ipa_main.c +++ b/ipa/core/src/wlan_ipa_main.c @@ -1,6 +1,6 @@ /* * Copyright (c) 2018-2021 The Linux Foundation. All rights reserved. - * Copyright (c) 2021 Qualcomm Innovation Center, Inc. All rights reserved. + * Copyright (c) 2021-2022 Qualcomm Innovation Center, Inc. All rights reserved. * * Permission to use, copy, modify, and/or distribute this software for * any purpose with or without fee is hereby granted, provided that the @@ -621,7 +621,8 @@ QDF_STATUS ipa_uc_ol_deinit(struct wlan_objmgr_pdev *pdev) status = wlan_ipa_uc_ol_deinit(ipa_obj); ipa_obj_cleanup(ipa_obj); - ipa_disable_register_cb(); + if (!g_instances_added) + ipa_disable_register_cb(); out: ipa_init_deinit_unlock(); @@ -667,7 +668,8 @@ QDF_STATUS ipa_wlan_evt(struct wlan_objmgr_pdev *pdev, qdf_netdev_t net_dev, } return wlan_ipa_wlan_evt(net_dev, device_mode, session_id, - ipa_event_type, mac_addr, is_2g_iface); + ipa_event_type, mac_addr, is_2g_iface, + ipa_obj); } int ipa_uc_smmu_map(bool map, uint32_t num_buf, qdf_mem_info_t *buf_arr) diff --git a/ipa/core/src/wlan_ipa_rm.c b/ipa/core/src/wlan_ipa_rm.c index 811a2dc8f5..1411b99f56 100644 --- a/ipa/core/src/wlan_ipa_rm.c +++ b/ipa/core/src/wlan_ipa_rm.c @@ -1,5 +1,6 @@ /* * Copyright (c) 2013-2021 The Linux Foundation. All rights reserved. + * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved. * * Permission to use, copy, modify, and/or distribute this software for * any purpose with or without fee is hereby granted, provided that the @@ -47,7 +48,7 @@ QDF_STATUS wlan_ipa_set_perf_level(struct wlan_ipa_priv *ipa_ctx, ipa_ctx->curr_cons_bw, next_bw); ret = cdp_ipa_set_perf_level(ipa_ctx->dp_soc, QDF_IPA_CLIENT_WLAN1_CONS, - next_bw); + next_bw, ipa_ctx->hdl); if (ret) { ipa_err("RM CONS set perf profile failed: %d", ret); @@ -55,7 +56,7 @@ QDF_STATUS wlan_ipa_set_perf_level(struct wlan_ipa_priv *ipa_ctx, } ret = cdp_ipa_set_perf_level(ipa_ctx->dp_soc, QDF_IPA_CLIENT_WLAN1_PROD, - next_bw); + next_bw, ipa_ctx->hdl); if (ret) { ipa_err("RM PROD set perf profile failed: %d", ret); return QDF_STATUS_E_FAILURE; @@ -80,7 +81,7 @@ QDF_STATUS wlan_ipa_init_perf_level(struct wlan_ipa_priv *ipa_ctx) ret = cdp_ipa_set_perf_level(ipa_ctx->dp_soc, QDF_IPA_CLIENT_WLAN1_CONS, - WLAN_IPA_MAX_BANDWIDTH); + WLAN_IPA_MAX_BANDWIDTH, ipa_ctx->hdl); if (ret) { ipa_err("CONS set perf profile failed: %d", ret); return QDF_STATUS_E_FAILURE; @@ -88,7 +89,7 @@ QDF_STATUS wlan_ipa_init_perf_level(struct wlan_ipa_priv *ipa_ctx) ret = cdp_ipa_set_perf_level(ipa_ctx->dp_soc, QDF_IPA_CLIENT_WLAN1_PROD, - WLAN_IPA_MAX_BANDWIDTH); + WLAN_IPA_MAX_BANDWIDTH, ipa_ctx->hdl); if (ret) { ipa_err("PROD set perf profile failed: %d", ret); return QDF_STATUS_E_FAILURE; diff --git a/ipa/core/src/wlan_ipa_stats.c b/ipa/core/src/wlan_ipa_stats.c index 31752f6eb0..7e06ee0217 100644 --- a/ipa/core/src/wlan_ipa_stats.c +++ b/ipa/core/src/wlan_ipa_stats.c @@ -1,5 +1,6 @@ /* * Copyright (c) 2013-2021 The Linux Foundation. All rights reserved. + * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved. * * Permission to use, copy, modify, and/or distribute this software for * any purpose with or without fee is hereby granted, provided that the @@ -127,6 +128,10 @@ static void wlan_ipa_uc_rt_debug_handler(void *ctext) void wlan_ipa_uc_rt_debug_destructor(qdf_nbuf_t nbuff) { + /* Make change to get the ipa_ctx on per pdev basis + * Currently storing the debug count only in global ipa_ctx + * or to the last enumerated radio ipa_ctx + */ struct wlan_ipa_priv *ipa_ctx = wlan_ipa_get_obj_context(); if (!ipa_ctx) { diff --git a/ipa/dispatcher/inc/wlan_ipa_obj_mgmt_api.h b/ipa/dispatcher/inc/wlan_ipa_obj_mgmt_api.h index 31b93aaa7f..d33147bad4 100644 --- a/ipa/dispatcher/inc/wlan_ipa_obj_mgmt_api.h +++ b/ipa/dispatcher/inc/wlan_ipa_obj_mgmt_api.h @@ -1,5 +1,6 @@ /* * Copyright (c) 2018, 2020-2021 The Linux Foundation. All rights reserved. + * Copyright (c) 2021-2022 Qualcomm Innovation Center, Inc. All rights reserved. * * Permission to use, copy, modify, and/or distribute this software for * any purpose with or without fee is hereby granted, provided that the @@ -69,6 +70,15 @@ static inline bool wlan_ipa_config_is_enabled(void) return ipa_config_is_enabled(); } +/** + * wlan_ipa_get_hdl() - Get ipa hdl set by IPA driver + * @psoc: void psoc object + * @pdev_id: pdev id + * + * Return: IPA handle + */ +qdf_ipa_wdi_hdl_t wlan_ipa_get_hdl(void *soc, uint8_t pdev_id); + #else static inline QDF_STATUS ipa_init(void) @@ -95,7 +105,6 @@ static inline bool wlan_ipa_config_is_enabled(void) { return false; } - #endif /* IPA_OFFLOAD */ #endif /* _WLAN_IPA_OBJ_MGMT_H_ */ diff --git a/ipa/dispatcher/src/wlan_ipa_obj_mgmt_api.c b/ipa/dispatcher/src/wlan_ipa_obj_mgmt_api.c index d9a8ebb1cc..5655625fd8 100644 --- a/ipa/dispatcher/src/wlan_ipa_obj_mgmt_api.c +++ b/ipa/dispatcher/src/wlan_ipa_obj_mgmt_api.c @@ -1,6 +1,6 @@ /* * Copyright (c) 2018, 2020-2021 The Linux Foundation. All rights reserved. - * Copyright (c) 2021 Qualcomm Innovation Center, Inc. All rights reserved. + * Copyright (c) 2021-2022 Qualcomm Innovation Center, Inc. All rights reserved. * * Permission to use, copy, modify, and/or distribute this software for * any purpose with or without fee is hereby granted, provided that the @@ -23,13 +23,19 @@ #include "wlan_ipa_obj_mgmt_api.h" #include "wlan_ipa_main.h" #include "wlan_objmgr_global_obj.h" +#include #include "target_if_ipa.h" #include "wlan_ipa_ucfg_api.h" #include "qdf_platform.h" #include "qdf_module.h" +/* This is as per IPA capbility */ +#define MAX_INSTANCES_SUPPORTED 2 + +uint8_t g_instances_added; static bool g_ipa_is_ready; -static qdf_mutex_t g_init_deinit_lock; +qdf_mutex_t g_init_deinit_lock; + bool ipa_cb_is_ready(void) { return g_ipa_is_ready; @@ -136,17 +142,24 @@ ipa_pdev_obj_create_notification(struct wlan_objmgr_pdev *pdev, static void ipa_register_ready_cb(void *user_data) { QDF_STATUS status = QDF_STATUS_SUCCESS; - struct wlan_ipa_priv *ipa_obj = (struct wlan_ipa_priv *)user_data; + struct wlan_ipa_priv *ipa_obj; struct wlan_objmgr_pdev *pdev; struct wlan_objmgr_psoc *psoc; qdf_device_t qdf_dev; + qdf_ipa_wdi_capabilities_out_params_t out_param; + uint8_t obj_id; + uint8_t pdev_id; + uint8_t pdev_count; + uint8_t instances_supported = 0; + uint8_t instances_processed = 0; if (!ipa_config_is_enabled()) { ipa_info("IPA config is disabled"); return; } - if (!ipa_obj) { - ipa_err("IPA object is NULL"); + + if (!user_data) { + ipa_err("User_data object is NULL"); return; } @@ -166,31 +179,77 @@ static void ipa_register_ready_cb(void *user_data) ipa_err("Driver modules stop in-progress/done, releasing lock"); goto out; } - pdev = ipa_priv_obj_get_pdev(ipa_obj); - psoc = wlan_pdev_get_psoc(pdev); - qdf_dev = wlan_psoc_get_qdf_dev(psoc); - if (!qdf_dev) { - ipa_err("QDF device context is NULL"); - goto out; - } g_ipa_is_ready = true; ipa_info("IPA ready callback invoked: ipa_register_ready_cb"); - status = ipa_obj_setup(ipa_obj); - if (QDF_IS_STATUS_ERROR(status)) { - ipa_err("Failed to setup ipa component"); - wlan_objmgr_pdev_component_obj_detach(pdev, - WLAN_UMAC_COMP_IPA, - ipa_obj); - qdf_mem_free(ipa_obj); - ipa_disable_register_cb(); - goto out; - } - if (ucfg_ipa_uc_ol_init(pdev, qdf_dev)) { - ipa_err("IPA ucfg_ipa_uc_ol_init failed"); - goto out; - } + /* Make call to get num_instances supported by IPA */ + qdf_ipa_wdi_get_capabilities(&out_param); + instances_supported = + QDF_IPA_WDI_CAPABILITIES_OUT_PARAMS_NUM_INSTANCES(&out_param); + ipa_info("Max instances supported by IPA is %d", instances_supported); + + for (obj_id = 0; obj_id < WLAN_OBJMGR_MAX_DEVICES; obj_id++) { + /* Get Psoc from global umac obj */ + psoc = g_umac_glb_obj->psoc[obj_id]; + if (!psoc) + continue; + + pdev_count = psoc->soc_objmgr.wlan_pdev_count; + for (pdev_id = 0; pdev_id < pdev_count && + instances_processed < instances_supported && + instances_processed < g_instances_added; + pdev_id++, instances_processed++) { + pdev = wlan_objmgr_get_pdev_by_id(psoc, pdev_id, + WLAN_IPA_ID); + + if (!pdev) { + qdf_err("Pdev is NULL for pdev_id[%d]", pdev_id); + continue; + } + + /* Get IPA obj from pdev obj */ + ipa_obj = ipa_pdev_get_priv_obj(pdev); + + if (!ipa_obj) { + ipa_err("ipa_obj is NULL for pdev_id[%d]", + pdev_id); + wlan_objmgr_pdev_release_ref(pdev, WLAN_IPA_ID); + continue; + } + + if (ipa_obj->handle_initialized) { + ipa_info("ipa_obj hdl is true for pdev_id %d", pdev_id); + wlan_objmgr_pdev_release_ref(pdev, WLAN_IPA_ID); + continue; + } + /* Update instace_id for current pdev */ + ipa_obj->instance_id = instances_processed; + qdf_dev = wlan_psoc_get_qdf_dev(psoc); + if (!qdf_dev) { + ipa_err("QDF device context is NULL"); + wlan_objmgr_pdev_release_ref(pdev, WLAN_IPA_ID); + continue; + } + + status = ipa_obj_setup(ipa_obj); + if (QDF_IS_STATUS_ERROR(status)) { + ipa_err("Failed to setup ipa component"); + wlan_objmgr_pdev_component_obj_detach(pdev, WLAN_UMAC_COMP_IPA, + ipa_obj); + qdf_mem_free(ipa_obj); + wlan_objmgr_pdev_release_ref(pdev, WLAN_IPA_ID); + continue; + } + if (ucfg_ipa_uc_ol_init(pdev, qdf_dev)) { + ipa_err("IPA ucfg_ipa_uc_ol_init failed"); + wlan_objmgr_pdev_release_ref(pdev, WLAN_IPA_ID); + continue; + } + ipa_obj->handle_initialized = true; + wlan_objmgr_pdev_release_ref(pdev, WLAN_IPA_ID); + } + } out: ipa_init_deinit_unlock(); } @@ -211,6 +270,13 @@ QDF_STATUS ipa_register_is_ipa_ready(struct wlan_objmgr_pdev *pdev) return QDF_STATUS_E_FAILURE; } + /* Acquire lock */ + ipa_init_deinit_lock(); + g_instances_added++; + ipa_info("No. of instances added for IPA is %d", g_instances_added); + /* Unlock */ + ipa_init_deinit_unlock(); + ret = qdf_ipa_register_ipa_ready_cb(ipa_register_ready_cb, (void *)ipa_obj); if (ret == -EEXIST) { @@ -294,3 +360,31 @@ QDF_STATUS ipa_deinit(void) return status; } + +qdf_ipa_wdi_hdl_t wlan_ipa_get_hdl(void *soc, uint8_t pdev_id) +{ + struct wlan_objmgr_psoc *psoc = (struct wlan_objmgr_psoc *)soc; + struct wlan_objmgr_pdev *pdev; + struct wlan_ipa_priv *ipa_obj; + qdf_ipa_wdi_hdl_t hdl; + + pdev = wlan_objmgr_get_pdev_by_id(psoc, pdev_id, WLAN_IPA_ID); + + if (!pdev) { + ipa_err("Failed to get pdev handle"); + return IPA_INVALID_HDL; + } + + ipa_obj = ipa_pdev_get_priv_obj(pdev); + if (!ipa_obj) { + ipa_err("IPA object is NULL for pdev_id[%d]", pdev_id); + wlan_objmgr_pdev_release_ref(pdev, WLAN_IPA_ID); + return IPA_INVALID_HDL; + } + hdl = ipa_obj->hdl; + + wlan_objmgr_pdev_release_ref(pdev, WLAN_IPA_ID); + return hdl; +} + +qdf_export_symbol(wlan_ipa_get_hdl);