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
This commit is contained in:
Sravan Kumar Kairam 2018-06-15 15:07:11 +05:30 committed by nshrivas
parent fc2181bcb6
commit ce792eb7f6
7 changed files with 206 additions and 12 deletions

View File

@ -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_ */

View File

@ -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_ */

View File

@ -22,6 +22,7 @@
#include <ol_txrx.h>
#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);
}

View File

@ -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);
}

View File

@ -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_ */

View File

@ -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);
}

View File

@ -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 */