From ce792eb7f6adc731db34794b731f975436d29782 Mon Sep 17 00:00:00 2001 From: Sravan Kumar Kairam Date: Fri, 15 Jun 2018 15:07:11 +0530 Subject: [PATCH] qcacld-3.0: Clean up IPA interface when SAP stop bss fails In case of rmmod if stop bss fails SAP IPA interface is not deleted. So again at next driver load IPA will be holding the stale IPA header and new IPA header will not be added at IPA interface creation. In this change clean IPA interface when SAP stop bss fails. Change-Id: I3a1bf891752308ba1a29d6768f24880d8514d5bf CRs-Fixed: 2224307 --- components/ipa/core/inc/wlan_ipa_core.h | 22 +++++ components/ipa/core/inc/wlan_ipa_main.h | 23 +++++ components/ipa/core/src/wlan_ipa_core.c | 86 +++++++++++++++++-- components/ipa/core/src/wlan_ipa_main.c | 34 ++++++-- .../ipa/dispatcher/inc/wlan_ipa_ucfg_api.h | 35 ++++++++ .../ipa/dispatcher/src/wlan_ipa_ucfg_api.c | 12 +++ core/hdd/src/wlan_hdd_hostapd.c | 6 ++ 7 files changed, 206 insertions(+), 12 deletions(-) diff --git a/components/ipa/core/inc/wlan_ipa_core.h b/components/ipa/core/inc/wlan_ipa_core.h index be6e77a4b63e..25eb58342424 100644 --- a/components/ipa/core/inc/wlan_ipa_core.h +++ b/components/ipa/core/inc/wlan_ipa_core.h @@ -620,5 +620,27 @@ int wlan_ipa_uc_smmu_map(bool map, uint32_t num_buf, qdf_mem_info_t *buf_arr); * Return: true if FW WDI actived, false otherwise */ bool wlan_ipa_is_fw_wdi_activated(struct wlan_ipa_priv *ipa_ctx); + +/** + * wlan_ipa_uc_disconnect_ap() - send ap disconnect event + * @ipa_ctx: IPA context + * @net_dev: Interface net device + * + * Send disconnect ap event to IPA driver + * + * Return: QDF_STATUS + */ +QDF_STATUS wlan_ipa_uc_disconnect_ap(struct wlan_ipa_priv *ipa_ctx, + qdf_netdev_t net_dev); + +/** + * wlan_ipa_cleanup_dev_iface() - Clean up net dev IPA interface + * @ipa_ctx: IPA context + * @net_dev: Interface net device + * + * Return: None + */ +void wlan_ipa_cleanup_dev_iface(struct wlan_ipa_priv *ipa_ctx, + qdf_netdev_t net_dev); #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 d65df3927ab8..1f766d8e2171 100644 --- a/components/ipa/core/inc/wlan_ipa_main.h +++ b/components/ipa/core/inc/wlan_ipa_main.h @@ -367,5 +367,28 @@ int ipa_uc_smmu_map(bool map, uint32_t num_buf, qdf_mem_info_t *buf_arr); * Return: true if FW WDI activated, false otherwise */ bool ipa_is_fw_wdi_activated(struct wlan_objmgr_pdev *pdev); + +/** + * ipa_uc_disconnect_ap() - send ap disconnect event + * @pdev: pdev obj + * @net_dev: Interface net device + * + * Send disconnect ap event to IPA driver + * + * Return: QDF_STATUS + */ +QDF_STATUS ipa_uc_disconnect_ap(struct wlan_objmgr_pdev *pdev, + qdf_netdev_t net_dev); + +/** + * ipa_cleanup_dev_iface() - Clean up net dev IPA interface + * @pdev: pdev obj + * @net_dev: Interface net device + * + * + * Return: None + */ +void ipa_cleanup_dev_iface(struct wlan_objmgr_pdev *pdev, + qdf_netdev_t net_dev); #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 33be842cdd30..56af3ba0d2b8 100644 --- a/components/ipa/core/src/wlan_ipa_core.c +++ b/components/ipa/core/src/wlan_ipa_core.c @@ -22,6 +22,7 @@ #include #include "cdp_txrx_ipa.h" #include "wal_rx_desc.h" +#include "qdf_str.h" static struct wlan_ipa_priv *gp_ipa; @@ -2765,14 +2766,87 @@ QDF_STATUS wlan_ipa_uc_ol_deinit(struct wlan_ipa_priv *ipa_ctx) return status; } -/** - * wlan_ipa_is_fw_wdi_activated() - Is FW WDI actived? - * @ipa_ctx: IPA contex - * - * Return: true if FW WDI actived, false otherwise - */ bool wlan_ipa_is_fw_wdi_activated(struct wlan_ipa_priv *ipa_ctx) { return (WLAN_IPA_UC_NUM_WDI_PIPE == ipa_ctx->activated_fw_pipe); } +/** + * wlan_ipa_uc_send_evt() - send event to ipa + * @net_dev: Interface net device + * @type: event type + * @mac_addr: pointer to mac address + * + * Send event to IPA driver + * + * Return: QDF_STATUS + */ +static QDF_STATUS wlan_ipa_uc_send_evt(qdf_netdev_t net_dev, + qdf_ipa_wlan_event type, + uint8_t *mac_addr) +{ + struct wlan_ipa_priv *ipa_ctx = gp_ipa; + qdf_ipa_msg_meta_t meta; + qdf_ipa_wlan_msg_t *msg; + + 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) { + ipa_err("msg allocation failed"); + return QDF_STATUS_E_NOMEM; + } + + QDF_IPA_SET_META_MSG_TYPE(&meta, type); + qdf_str_lcopy(QDF_IPA_WLAN_MSG_NAME(msg), net_dev->name, + IPA_RESOURCE_NAME_MAX); + qdf_mem_copy(QDF_IPA_WLAN_MSG_MAC_ADDR(msg), mac_addr, QDF_NET_ETH_LEN); + + if (qdf_ipa_send_msg(&meta, msg, wlan_ipa_msg_free_fn)) { + ipa_err("%s: Evt: %d fail", + QDF_IPA_WLAN_MSG_NAME(msg), + QDF_IPA_MSG_META_MSG_TYPE(&meta)); + qdf_mem_free(msg); + + return QDF_STATUS_E_FAILURE; + } + + ipa_ctx->stats.num_send_msg++; + + return QDF_STATUS_SUCCESS; +} + +QDF_STATUS wlan_ipa_uc_disconnect_ap(struct wlan_ipa_priv *ipa_ctx, + qdf_netdev_t net_dev) +{ + struct wlan_ipa_iface_context *iface_ctx; + QDF_STATUS status; + + ipa_debug("enter"); + + 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); + else + return QDF_STATUS_E_INVAL; + + ipa_debug("exit :%d", status); + + return status; +} + +void wlan_ipa_cleanup_dev_iface(struct wlan_ipa_priv *ipa_ctx, + qdf_netdev_t net_dev) +{ + struct wlan_ipa_iface_context *iface_ctx; + int i; + + for (i = 0; i < WLAN_IPA_MAX_IFACE; i++) { + iface_ctx = &ipa_ctx->iface_context[i]; + if (iface_ctx->dev == net_dev) + break; + } + + if (iface_ctx) + wlan_ipa_cleanup_iface(iface_ctx); +} diff --git a/components/ipa/core/src/wlan_ipa_main.c b/components/ipa/core/src/wlan_ipa_main.c index 0a12a3331ced..80edf6ed31fd 100644 --- a/components/ipa/core/src/wlan_ipa_main.c +++ b/components/ipa/core/src/wlan_ipa_main.c @@ -531,12 +531,6 @@ int ipa_uc_smmu_map(bool map, uint32_t num_buf, qdf_mem_info_t *buf_arr) return wlan_ipa_uc_smmu_map(map, num_buf, buf_arr); } -/** - * ipa_is_fw_wdi_activated - Is FW WDI activated? - * @pdev: pdev obj - * - * Return: true if FW WDI activated, false otherwise - */ bool ipa_is_fw_wdi_activated(struct wlan_objmgr_pdev *pdev) { struct wlan_ipa_priv *ipa_obj; @@ -554,3 +548,31 @@ bool ipa_is_fw_wdi_activated(struct wlan_objmgr_pdev *pdev) return wlan_ipa_is_fw_wdi_activated(ipa_obj); } + +QDF_STATUS ipa_uc_disconnect_ap(struct wlan_objmgr_pdev *pdev, + qdf_netdev_t net_dev) +{ + struct wlan_ipa_priv *ipa_obj; + + 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_uc_disconnect_ap(ipa_obj, net_dev); +} + +void ipa_cleanup_dev_iface(struct wlan_objmgr_pdev *pdev, + qdf_netdev_t net_dev) +{ + struct wlan_ipa_priv *ipa_obj; + + ipa_obj = ipa_pdev_get_priv_obj(pdev); + if (!ipa_obj) { + ipa_err("IPA object is NULL"); + return; + } + + return wlan_ipa_cleanup_dev_iface(ipa_obj, net_dev); +} diff --git a/components/ipa/dispatcher/inc/wlan_ipa_ucfg_api.h b/components/ipa/dispatcher/inc/wlan_ipa_ucfg_api.h index 8f41a93e8aef..84b874c9374b 100644 --- a/components/ipa/dispatcher/inc/wlan_ipa_ucfg_api.h +++ b/components/ipa/dispatcher/inc/wlan_ipa_ucfg_api.h @@ -290,6 +290,28 @@ int ucfg_ipa_uc_smmu_map(bool map, uint32_t num_buf, qdf_mem_info_t *buf_arr); */ bool ucfg_ipa_is_fw_wdi_activated(struct wlan_objmgr_pdev *pdev); +/** + * ucfg_ipa_uc_disconnect_ap() - send ap disconnect event + * @pdev: pdev obj + * @net_dev: Interface net device + * + * Send disconnect ap event to IPA driver during SSR + * + * Return: QDF_STATUS + */ +QDF_STATUS ucfg_ipa_uc_disconnect_ap(struct wlan_objmgr_pdev *pdev, + qdf_netdev_t net_dev); + +/** + * ucfg_ipa_cleanup_dev_iface() - Clean up net dev IPA interface + * @pdev: pdev obj + * @net_dev: Interface net device + * + * + * Return: None + */ +void ucfg_ipa_cleanup_dev_iface(struct wlan_objmgr_pdev *pdev, + qdf_netdev_t net_dev); #else static inline bool ucfg_ipa_is_present(void) @@ -452,5 +474,18 @@ bool ucfg_ipa_is_fw_wdi_activated(struct wlan_objmgr_pdev *pdev) { return false; } + +static inline +QDF_STATUS ucfg_ipa_uc_disconnect_ap(struct wlan_objmgr_pdev *pdev, + qdf_netdev_t net_dev) +{ + return QDF_STATUS_SUCCESS; +} + +static inline +void ucfg_ipa_cleanup_dev_iface(struct wlan_objmgr_pdev *pdev, + qdf_netdev_t net_dev) +{ +} #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 4433db007cd6..2df81efba43a 100644 --- a/components/ipa/dispatcher/src/wlan_ipa_ucfg_api.c +++ b/components/ipa/dispatcher/src/wlan_ipa_ucfg_api.c @@ -174,3 +174,15 @@ bool ucfg_ipa_is_fw_wdi_activated(struct wlan_objmgr_pdev *pdev) { return ipa_is_fw_wdi_activated(pdev); } + +QDF_STATUS ucfg_ipa_uc_disconnect_ap(struct wlan_objmgr_pdev *pdev, + qdf_netdev_t net_dev) +{ + return ipa_uc_disconnect_ap(pdev, net_dev); +} + +void ucfg_ipa_cleanup_dev_iface(struct wlan_objmgr_pdev *pdev, + qdf_netdev_t net_dev) +{ + return ipa_cleanup_dev_iface(pdev, net_dev); +} diff --git a/core/hdd/src/wlan_hdd_hostapd.c b/core/hdd/src/wlan_hdd_hostapd.c index 413234711508..4f1724a6e9ae 100644 --- a/core/hdd/src/wlan_hdd_hostapd.c +++ b/core/hdd/src/wlan_hdd_hostapd.c @@ -2522,6 +2522,12 @@ stopbss: if (!QDF_IS_STATUS_SUCCESS(qdf_status)) { hdd_warn("hdd_softap_stop_bss failed %d", qdf_status); + if (ucfg_ipa_is_enabled()) { + ucfg_ipa_uc_disconnect_ap(hdd_ctx->hdd_pdev, + adapter->dev); + ucfg_ipa_cleanup_dev_iface(hdd_ctx->hdd_pdev, + adapter->dev); + } } /* notify userspace that the BSS has stopped */