From 9d01a66a5e15c88bfdb1736a450c3920fbd6e26a Mon Sep 17 00:00:00 2001 From: Abhishek Singh Date: Mon, 5 Oct 2020 12:32:38 +0530 Subject: [PATCH] qcacmn: Add disconnect sync API to wait for disconnect to complete Add sync API for disconnect to wait for disconnect to complete. This can be used during vdev delete sequence to move the vdev and connection manager SM to init state before VDEV is marked logically deleted. Change-Id: Id562e444cf1995d800b8268f906f811f143d0fc9 CRs-Fixed: 2790885 --- os_if/linux/mlme/inc/osif_cm_req.h | 16 +++-- os_if/linux/mlme/src/osif_cm_disconnect_rsp.c | 2 + os_if/linux/mlme/src/osif_cm_req.c | 65 +++++++++++++++---- os_if/linux/mlme/src/osif_cm_util.c | 17 ++++- os_if/linux/wlan_osif_priv.h | 3 + .../core/src/wlan_cm_disconnect.c | 2 - .../dispatcher/inc/wlan_cm_public_struct.h | 6 ++ 7 files changed, 91 insertions(+), 20 deletions(-) diff --git a/os_if/linux/mlme/inc/osif_cm_req.h b/os_if/linux/mlme/inc/osif_cm_req.h index 0abdf04fb4..a88397e957 100644 --- a/os_if/linux/mlme/inc/osif_cm_req.h +++ b/os_if/linux/mlme/inc/osif_cm_req.h @@ -38,8 +38,7 @@ * * Return: int */ -int osif_cm_connect(struct net_device *dev, - struct wlan_objmgr_vdev *vdev, +int osif_cm_connect(struct net_device *dev, struct wlan_objmgr_vdev *vdev, struct cfg80211_connect_params *req); /** @@ -50,8 +49,17 @@ int osif_cm_connect(struct net_device *dev, * * Return: int */ -int osif_cm_disconnect(struct net_device *dev, - struct wlan_objmgr_vdev *vdev, +int osif_cm_disconnect(struct net_device *dev, struct wlan_objmgr_vdev *vdev, uint16_t reason); + +/** + * osif_cm_disconnect_sync() - Disconnect vdev and wait for it to complete + * @vdev: vdev pointer + * @reason: disconnect reason + * + * Return: int + */ +int osif_cm_disconnect_sync(struct wlan_objmgr_vdev *vdev, uint16_t reason); + #endif #endif /* __OSIF_CM_REQ_H */ diff --git a/os_if/linux/mlme/src/osif_cm_disconnect_rsp.c b/os_if/linux/mlme/src/osif_cm_disconnect_rsp.c index fd7f47f04a..fe9ce5a68a 100644 --- a/os_if/linux/mlme/src/osif_cm_disconnect_rsp.c +++ b/os_if/linux/mlme/src/osif_cm_disconnect_rsp.c @@ -150,5 +150,7 @@ QDF_STATUS osif_disconnect_handler(struct wlan_objmgr_vdev *vdev, locally_generated, rsp->ap_discon_ie.ptr, rsp->ap_discon_ie.len, GFP_KERNEL); + qdf_event_set(&osif_priv->cm_info.disconnect_complete); + return status; } diff --git a/os_if/linux/mlme/src/osif_cm_req.c b/os_if/linux/mlme/src/osif_cm_req.c index 5f151e06b1..07278d10a5 100644 --- a/os_if/linux/mlme/src/osif_cm_req.c +++ b/os_if/linux/mlme/src/osif_cm_req.c @@ -21,6 +21,7 @@ * request apis. */ +#include "wlan_osif_priv.h" #include "osif_cm_req.h" #include "wlan_cm_ucfg_api.h" #include "wlan_nl_to_crypto_params.h" @@ -395,16 +396,11 @@ connect_start_fail: return qdf_status_to_os_return(status); } -int osif_cm_disconnect(struct net_device *dev, struct wlan_objmgr_vdev *vdev, - uint16_t reason) +static QDF_STATUS osif_cm_send_disconnect(struct wlan_objmgr_vdev *vdev, + uint16_t reason) { - struct wlan_cm_disconnect_req *req; - uint8_t vdev_id = vdev->vdev_objmgr.vdev_id; QDF_STATUS status; - - osif_info("%s(vdevid-%d): Received Disconnect reason:%d %s", - dev->name, vdev_id, reason, - ucfg_cm_reason_code_to_str(reason)); + struct wlan_cm_disconnect_req *req; status = osif_cm_reset_id_and_src(vdev); if (QDF_IS_STATUS_ERROR(status)) @@ -412,17 +408,62 @@ int osif_cm_disconnect(struct net_device *dev, struct wlan_objmgr_vdev *vdev, req = qdf_mem_malloc(sizeof(*req)); if (!req) - return -ENOMEM; + return QDF_STATUS_E_NOMEM; - req->vdev_id = vdev_id; + req->vdev_id = wlan_vdev_get_id(vdev); req->source = CM_OSIF_DISCONNECT; req->reason_code = reason; status = ucfg_cm_start_disconnect(vdev, req); + qdf_mem_free(req); + + return status; +} + +int osif_cm_disconnect(struct net_device *dev, struct wlan_objmgr_vdev *vdev, + uint16_t reason) +{ + uint8_t vdev_id = wlan_vdev_get_id(vdev); + QDF_STATUS status; + + osif_info("%s(vdevid-%d): Received Disconnect reason:%d %s", + dev->name, vdev_id, reason, + ucfg_cm_reason_code_to_str(reason)); + + status = osif_cm_send_disconnect(vdev, reason); if (QDF_IS_STATUS_ERROR(status)) osif_err("Disconnect failed with status %d", status); - qdf_mem_free(req); - return qdf_status_to_os_return(status); } +int osif_cm_disconnect_sync(struct wlan_objmgr_vdev *vdev, uint16_t reason) +{ + uint8_t vdev_id = wlan_vdev_get_id(vdev); + struct vdev_osif_priv *osif_priv = wlan_vdev_get_ospriv(vdev); + QDF_STATUS status; + + if (ucfg_cm_is_vdev_disconnected(vdev)) + return 0; + + if (!osif_priv) { + osif_err("vdev %d invalid vdev osif priv", vdev_id); + return -EINVAL; + } + + osif_info("vdevid-%d: Received Disconnect reason:%d %s", + vdev_id, reason, ucfg_cm_reason_code_to_str(reason)); + + qdf_event_reset(&osif_priv->cm_info.disconnect_complete); + status = osif_cm_send_disconnect(vdev, reason); + if (QDF_IS_STATUS_ERROR(status)) { + osif_err("Disconnect failed with status %d", status); + return qdf_status_to_os_return(status); + } + + status = qdf_wait_single_event(&osif_priv->cm_info.disconnect_complete, + CM_DISCONNECT_CMD_TIMEOUT); + if (QDF_IS_STATUS_ERROR(status)) + osif_err("Disconnect timeout with status %d", status); + + return qdf_status_to_os_return(status); +} diff --git a/os_if/linux/mlme/src/osif_cm_util.c b/os_if/linux/mlme/src/osif_cm_util.c index c6c440a643..8b675698e6 100644 --- a/os_if/linux/mlme/src/osif_cm_util.c +++ b/os_if/linux/mlme/src/osif_cm_util.c @@ -261,6 +261,7 @@ QDF_STATUS osif_cm_osif_priv_init(struct wlan_objmgr_vdev *vdev) { struct vdev_osif_priv *osif_priv = wlan_vdev_get_ospriv(vdev); enum QDF_OPMODE mode = wlan_vdev_mlme_get_opmode(vdev); + QDF_STATUS status; if (mode != QDF_STA_MODE && mode != QDF_P2P_CLIENT_MODE) return QDF_STATUS_SUCCESS; @@ -272,7 +273,19 @@ QDF_STATUS osif_cm_osif_priv_init(struct wlan_objmgr_vdev *vdev) qdf_spinlock_create(&osif_priv->cm_info.cmd_id_lock); - return QDF_STATUS_SUCCESS; + status = qdf_event_create(&osif_priv->cm_info.disconnect_complete); + if (QDF_IS_STATUS_ERROR(status)) { + osif_err("failed to create disconnect complete event fro vdev %d", + wlan_vdev_get_id(vdev)); + goto event_create_fail; + } + + return status; + +event_create_fail: + qdf_spinlock_destroy(&osif_priv->cm_info.cmd_id_lock); + + return status; } QDF_STATUS osif_cm_osif_priv_deinit(struct wlan_objmgr_vdev *vdev) @@ -287,7 +300,7 @@ QDF_STATUS osif_cm_osif_priv_deinit(struct wlan_objmgr_vdev *vdev) osif_err("Invalid vdev osif priv"); return QDF_STATUS_E_INVAL; } - + qdf_event_destroy(&osif_priv->cm_info.disconnect_complete); qdf_spinlock_destroy(&osif_priv->cm_info.cmd_id_lock); return QDF_STATUS_SUCCESS; diff --git a/os_if/linux/wlan_osif_priv.h b/os_if/linux/wlan_osif_priv.h index ff4bd6c2b1..30d7bcf19e 100644 --- a/os_if/linux/wlan_osif_priv.h +++ b/os_if/linux/wlan_osif_priv.h @@ -21,6 +21,7 @@ #define _WLAN_OSIF_PRIV_H_ #include "qdf_net_if.h" +#include #include "wlan_cm_public_struct.h" #include @@ -49,6 +50,7 @@ struct pdev_osif_priv { * @cmd_id_lock: lock to update and read last command source * @last_disconnect_reason: last disconnect reason to be indicated in get * station + * @disconnect_complete: disconnect completion wait event * @ext_priv: legacy data pointer. */ struct osif_cm_info { @@ -56,6 +58,7 @@ struct osif_cm_info { wlan_cm_id last_id; struct qdf_spinlock cmd_id_lock; enum qca_disconnect_reason_codes last_disconnect_reason; + qdf_event_t disconnect_complete; void *ext_priv; }; #endif diff --git a/umac/mlme/connection_mgr/core/src/wlan_cm_disconnect.c b/umac/mlme/connection_mgr/core/src/wlan_cm_disconnect.c index c788e0250d..343e83f547 100644 --- a/umac/mlme/connection_mgr/core/src/wlan_cm_disconnect.c +++ b/umac/mlme/connection_mgr/core/src/wlan_cm_disconnect.c @@ -117,8 +117,6 @@ cm_ser_disconnect_cb(struct wlan_serialization_command *cmd, return status; } -#define DISCONNECT_TIMEOUT STOP_RESPONSE_TIMER + DELETE_RESPONSE_TIMER + 1000 - static QDF_STATUS cm_ser_disconnect_req(struct wlan_objmgr_pdev *pdev, struct cnx_mgr *cm_ctx, struct cm_disconnect_req *req) diff --git a/umac/mlme/connection_mgr/dispatcher/inc/wlan_cm_public_struct.h b/umac/mlme/connection_mgr/dispatcher/inc/wlan_cm_public_struct.h index 27e109440a..2a04115b14 100644 --- a/umac/mlme/connection_mgr/dispatcher/inc/wlan_cm_public_struct.h +++ b/umac/mlme/connection_mgr/dispatcher/inc/wlan_cm_public_struct.h @@ -31,6 +31,12 @@ #define CM_ID_INVALID 0xFFFFFFFF typedef uint32_t wlan_cm_id; +/* Diconnect active timeout */ +#define DISCONNECT_TIMEOUT STOP_RESPONSE_TIMER + DELETE_RESPONSE_TIMER + 1000 + +/* Diconnect command wait timeout */ +#define CM_DISCONNECT_CMD_TIMEOUT DISCONNECT_TIMEOUT + 2000 + /** * struct wlan_cm_wep_key_params - store wep key info * @key: key info