qcacmn: Add connect path logic after serialization

Add connect logic after serialization in connection manager.

Change-Id: I6aabc956d4ade20379aec000f566ccbfcfdcfd23
CRs-Fixed: 2776348
This commit is contained in:
gaurank kathpalia 2020-09-14 19:34:06 +05:30 • committed by snandini
commit 4af3739c3d
9 changed files with 328 additions and 36 deletions

View file

@ -62,7 +62,7 @@ cm_ser_connect_cb(struct wlan_serialization_command *cmd,
QDF_ASSERT(0);
break;
case WLAN_SER_CB_RELEASE_MEM_CMD:
/* command completed. Release reference of vdev */
cm_reset_active_cm_id(vdev, cmd->cmd_id);
wlan_objmgr_vdev_release_ref(vdev, WLAN_MLME_CM_ID);
break;
default:
@ -420,25 +420,187 @@ connect_err:
return cm_send_connect_start_fail(cm_ctx, cm_req, reason);
}
QDF_STATUS cm_connect_active(struct cnx_mgr *cm_ctx, wlan_cm_id *cm_id)
#ifdef WLAN_FEATURE_INTERFACE_MGR
static QDF_STATUS cm_validate_candidate(struct cnx_mgr *cm_ctx,
struct scan_cache_entry *scan_entry)
{
struct if_mgr_event_data event_data = {0};
event_data.validate_bss_info.chan_freq = scan_entry->channel.chan_freq;
qdf_copy_macaddr(&event_data.validate_bss_info.peer_addr,
&scan_entry->bssid);
return if_mgr_deliver_event(cm_ctx->vdev,
WLAN_IF_MGR_EV_VALIDATE_CANDIDATE,
&event_data);
}
#else
static inline
QDF_STATUS cm_validate_candidate(struct cnx_mgr *cm_ctx,
struct scan_cache_entry *scan_entry)
{
/*
* get first valid candidate, create bss peer.
* fill vdev crypto for the peer.
* call vdev sm to start connect for the candidate.
*/
return QDF_STATUS_SUCCESS;
}
#endif
/**
* cm_get_valid_candidate() - This API will be called to get the next valid
* candidate
* @cm_ctx: connection manager context
* @cm_req: Connect request.
*
* This function return a valid candidate to try connection. It return failure
* if no valid candidate is present or all valid candidate are tried.
*
* Return: QDF status
*/
static QDF_STATUS cm_get_valid_candidate(struct cnx_mgr *cm_ctx,
struct cm_req *cm_req)
{
struct scan_cache_node *scan_node = NULL;
qdf_list_node_t *cur_node = NULL, *next_node = NULL;
struct scan_cache_node *cur_candidate;
QDF_STATUS status = QDF_STATUS_SUCCESS;
if (cm_req->connect_req.connect_attempts >=
CM_MAX_CANDIDATE_TO_BE_TRIED) {
mlme_info("Max %d candidates tried for the conenction",
cm_req->connect_req.connect_attempts);
return QDF_STATUS_E_FAILURE;
}
cur_candidate = cm_req->connect_req.cur_candidate;
/*
* Get next candidate if cur_candidate is not NULL, else get
* the first candidate
*/
if (cur_candidate)
qdf_list_peek_next(cm_req->connect_req.candidate_list,
&cur_candidate->node, &cur_node);
else
qdf_list_peek_front(cm_req->connect_req.candidate_list,
&cur_node);
while (cur_node) {
qdf_list_peek_next(cm_req->connect_req.candidate_list,
cur_node, &next_node);
scan_node = qdf_container_of(cur_node, struct scan_cache_node,
node);
status = cm_validate_candidate(cm_ctx, scan_node->entry);
if (QDF_IS_STATUS_SUCCESS(status)) {
cur_candidate = scan_node;
break;
}
cur_node = next_node;
next_node = NULL;
}
/*
* If cur_node is NULL cur candidate was last to be tried so no more
* candidates left for connect now.
*/
if (!cur_node) {
mlme_debug("No more candidates left");
cm_req->connect_req.cur_candidate = NULL;
return QDF_STATUS_E_FAILURE;
}
cm_req->connect_req.connect_attempts++;
cm_req->connect_req.cur_candidate = cur_candidate;
return QDF_STATUS_SUCCESS;
}
static void cm_create_bss_peer(struct cnx_mgr *cm_ctx,
struct cm_connect_req *req)
{
QDF_STATUS status;
struct qdf_mac_addr *bssid;
bssid = &req->cur_candidate->entry->bssid;
status = mlme_cm_bss_peer_create_req(cm_ctx->vdev, bssid);
if (QDF_IS_STATUS_ERROR(status)) {
struct wlan_cm_connect_rsp *resp;
/* In case of failure try with next candidate */
mlme_err("peer create request failed %d", status);
resp = qdf_mem_malloc(sizeof(*resp));
if (!resp)
return;
resp->connect_status = status;
resp->cm_id = req->cm_id;
resp->vdev_id = wlan_vdev_get_id(cm_ctx->vdev);
resp->reason = CM_JOIN_FAILED;
cm_sm_deliver_event_sync(cm_ctx,
WLAN_CM_SM_EV_CONNECT_GET_NEXT_CANDIDATE,
sizeof(*resp), resp);
qdf_mem_free(resp);
}
}
QDF_STATUS cm_try_next_candidate(struct cnx_mgr *cm_ctx,
struct wlan_cm_connect_rsp *resp)
{
QDF_STATUS status;
struct cm_req *cm_req;
cm_req = cm_get_req_by_cm_id(cm_ctx, resp->cm_id);
if (!cm_req) {
mlme_err("cm req NULL connect fail");
goto connect_err;
}
status = cm_get_valid_candidate(cm_ctx, cm_req);
if (QDF_IS_STATUS_ERROR(status))
goto connect_err;
mlme_cm_osif_failed_candidate_ind(cm_ctx->vdev, resp);
cm_create_bss_peer(cm_ctx, &cm_req->connect_req);
return QDF_STATUS_SUCCESS;
connect_err:
return cm_send_connect_start_fail(cm_ctx, &cm_req->connect_req,
CM_JOIN_FAILED);
}
QDF_STATUS cm_connect_active(struct cnx_mgr *cm_ctx, wlan_cm_id *cm_id)
{
struct cm_req *cm_req;
QDF_STATUS status;
cm_req = cm_get_req_by_cm_id(cm_ctx, *cm_id);
if (!cm_req) {
mlme_err("cm req NULL connect fail");
return QDF_STATUS_E_INVAL;
}
cm_ctx->active_cm_id = *cm_id;
status = cm_get_valid_candidate(cm_ctx, cm_req);
if (QDF_IS_STATUS_ERROR(status))
goto connect_err;
cm_create_bss_peer(cm_ctx, &cm_req->connect_req);
return QDF_STATUS_SUCCESS;
connect_err:
return cm_send_connect_start_fail(cm_ctx,
&cm_req->connect_req, CM_JOIN_FAILED);
}
QDF_STATUS
cm_resume_connect_after_peer_create(struct cnx_mgr *cm_ctx, wlan_cm_id *cm_id)
{
/*
* get next valid candidate, if no candidate left, post
* WLAN_CM_SM_EV_CONNECT_FAILURE to SM, inform osif about failure for
* the candidate if its not last one. and initiate the connect for
* next candidate.
* fill vdev crypto for the peer.
* call vdev sm to start connect for the candidate.
*/
return QDF_STATUS_SUCCESS;
}
@ -477,6 +639,67 @@ QDF_STATUS cm_add_connect_req_to_list(struct cnx_mgr *cm_ctx,
return status;
}
QDF_STATUS cm_bss_peer_create_rsp(struct wlan_objmgr_vdev *vdev,
QDF_STATUS status,
struct qdf_mac_addr *peer_mac)
{
struct cnx_mgr *cm_ctx;
QDF_STATUS qdf_status;
struct wlan_cm_connect_rsp *resp;
wlan_cm_id cm_id;
uint32_t prefix;
cm_ctx = cm_get_cm_ctx(vdev);
if (!cm_ctx) {
mlme_err("cm ctx NULL");
return QDF_STATUS_E_INVAL;
}
cm_id = cm_ctx->active_cm_id;
prefix = CM_ID_GET_PREFIX(cm_id);
if (prefix != CONNECT_REQ_PREFIX) {
mlme_err("Active req %x is not connect req", cm_id);
/* Delete peer if create was success */
return QDF_STATUS_E_INVAL;
}
if (QDF_IS_STATUS_SUCCESS(status)) {
qdf_status =
cm_sm_deliver_event(vdev,
WLAN_CM_EV_BSS_CREATE_PEER_SUCCESS,
sizeof(wlan_cm_id), &cm_id);
if (QDF_IS_STATUS_SUCCESS(qdf_status))
return qdf_status;
goto post_err;
}
resp = qdf_mem_malloc(sizeof(*resp));
if (!resp)
goto post_err;
resp->connect_status = status;
resp->cm_id = cm_id;
resp->vdev_id = wlan_vdev_get_id(vdev);
resp->reason = CM_JOIN_FAILED;
/* In case of failure try with next candidate */
qdf_status =
cm_sm_deliver_event(vdev,
WLAN_CM_SM_EV_CONNECT_GET_NEXT_CANDIDATE,
sizeof(*resp), resp);
qdf_mem_free(resp);
if (QDF_IS_STATUS_SUCCESS(qdf_status))
return qdf_status;
post_err:
/*
* handle post error i.e. STATE is not connect active, so
* do cleanup of req.
*/
return qdf_status;
}
QDF_STATUS cm_connect_start_req(struct wlan_objmgr_vdev *vdev,
struct wlan_cm_connect_req *req)
{

View file

@ -57,7 +57,7 @@ cm_ser_disconnect_cb(struct wlan_serialization_command *cmd,
QDF_ASSERT(0);
break;
case WLAN_SER_CB_RELEASE_MEM_CMD:
/* command completed. Release reference of vdev */
cm_reset_active_cm_id(vdev, cmd->cmd_id);
wlan_objmgr_vdev_release_ref(vdev, WLAN_MLME_CM_ID);
break;
default:
@ -133,6 +133,16 @@ QDF_STATUS cm_disconnect_start(struct cnx_mgr *cm_ctx,
QDF_STATUS cm_disconnect_active(struct cnx_mgr *cm_ctx, wlan_cm_id *cm_id)
{
struct cm_req *cm_req;
cm_req = cm_get_req_by_cm_id(cm_ctx, *cm_id);
if (!cm_req) {
mlme_err("cm req NULL connect fail");
return QDF_STATUS_E_INVAL;
}
cm_ctx->active_cm_id = *cm_id;
/*
* call vdev sm to start disconnect.
*/

View file

@ -99,6 +99,7 @@ struct cm_state_sm {
* @rsn_ie: rsn_ie in connect req
* @candidate_list: candidate list
* @cur_candidate: current candidate
* @connect_attempts: number of connect attempts tried
*/
struct cm_connect_req {
wlan_cm_id cm_id;
@ -109,6 +110,7 @@ struct cm_connect_req {
struct element_info rsn_ie;
qdf_list_t *candidate_list;
struct scan_cache_node *cur_candidate;
uint8_t connect_attempts;
};
/**
@ -157,6 +159,7 @@ struct connect_ies {
* struct cnx_mgr - connect manager req
* @vdev: vdev back pointer
* @sm: state machine
* @active_cm_id: cm_id of the active command, if any active command present
* @req_list: connect/disconnect req list
* @cm_req_lock: lock to manupulate/read the cm req list
* @disconnect_count: disconnect count
@ -170,6 +173,7 @@ struct connect_ies {
struct cnx_mgr {
struct wlan_objmgr_vdev *vdev;
struct cm_state_sm sm;
wlan_cm_id active_cm_id;
qdf_list_t req_list;
#ifdef WLAN_CM_USE_SPINLOCK
qdf_spinlock_t cm_req_lock;

View file

@ -26,6 +26,15 @@
#include "wlan_cm_main.h"
#include "wlan_cm_sm.h"
#include <include/wlan_mlme_cmn.h>
#ifdef WLAN_FEATURE_INTERFACE_MGR
#include <wlan_if_mgr_api.h>
#endif
#define CONNECT_REQ_PREFIX 0x00C00000
#define DISCONNECT_REQ_PREFIX 0x00D00000
#define CM_ID_MASK 0x0000FFFF
#define CM_ID_GET_PREFIX(cm_id) cm_id & 0xFFFF0000
/*************** CONNECT APIs ****************/
@ -92,6 +101,28 @@ QDF_STATUS cm_try_next_candidate(struct cnx_mgr *cm_ctx,
*/
QDF_STATUS cm_connect_cmd_timeout(struct cnx_mgr *cm_ctx, wlan_cm_id cm_id);
/**
* cm_resume_connect_after_peer_create() - Called after bss create rsp
* @cm_ctx: connection manager context
* @cm_id: Connection mgr ID assigned to this connect request.
*
* Return: QDF status
*/
QDF_STATUS
cm_resume_connect_after_peer_create(struct cnx_mgr *cm_ctx, wlan_cm_id *cm_id);
/**
* cm_bss_peer_create_rsp() - handle bss peer create response
* @vdev: vdev
* @status: bss peer create status
* @peer_mac: peer mac
*
* Return: QDF status
*/
QDF_STATUS cm_bss_peer_create_rsp(struct wlan_objmgr_vdev *vdev,
QDF_STATUS status,
struct qdf_mac_addr *peer_mac);
/**
* cm_connect_complete() - This API would be called after connect complete
* request from the serialization.
@ -232,6 +263,16 @@ wlan_cm_id cm_get_cm_id(struct cnx_mgr *cm_ctx, enum wlan_cm_source source);
*/
struct cnx_mgr *cm_get_cm_ctx(struct wlan_objmgr_vdev *vdev);
/**
* cm_reset_active_cm_id() - Reset active cm_id from cm context, if its same as
* passed cm_id
* @vdev: vdev object pointer
* @cm_id: cmid to match
*
* Return: void
*/
void cm_reset_active_cm_id(struct wlan_objmgr_vdev *vdev, wlan_cm_id cm_id);
/**
* cm_check_cmid_match_list_head() - check if list head command matches the
* given cm_id

View file

@ -551,6 +551,10 @@ static bool cm_subst_join_active_event(void *ctx, uint16_t event,
cm_sm_deliver_event_sync(cm_ctx, event, data_len, data);
status = true;
break;
case WLAN_CM_EV_BSS_CREATE_PEER_SUCCESS:
cm_resume_connect_after_peer_create(cm_ctx, data);
status = true;
break;
default:
status = false;
break;
@ -722,6 +726,7 @@ static const char *cm_sm_event_names[] = {
"EV_CONNECT_START",
"EV_CONNECT_ACTIVE",
"EV_CONNECT_SUCCESS",
"EV_BSS_CREATE_PEER_SUCCESS"
"EV_CONNECT_GET_NXT_CANDIDATE",
"EV_CONNECT_FAILURE",
"EV_DISCONNECT_REQ",

View file

@ -37,6 +37,7 @@
* @WLAN_CM_SM_EV_CONNECT_START: Connect start process initiate
* @WLAN_CM_SM_EV_CONNECT_ACTIVE: Connect request is activated
* @WLAN_CM_SM_EV_CONNECT_SUCCESS: Connect success
* @WLAN_CM_EV_BSS_CREATE_PEER_SUCCESS: BSS peer create success
* @WLAN_CM_SM_EV_CONNECT_GET_NEXT_CANDIDATE: Get next candidate for connection
* @WLAN_CM_SM_EV_CONNECT_FAILURE: Connect failed for all candidate
* @WLAN_CM_SM_EV_DISCONNECT_REQ: Disconnect request event from
@ -67,23 +68,24 @@ enum wlan_cm_sm_evt {
WLAN_CM_SM_EV_CONNECT_START = 6,
WLAN_CM_SM_EV_CONNECT_ACTIVE = 7,
WLAN_CM_SM_EV_CONNECT_SUCCESS = 8,
WLAN_CM_SM_EV_CONNECT_GET_NEXT_CANDIDATE = 9,
WLAN_CM_SM_EV_CONNECT_FAILURE = 10,
WLAN_CM_SM_EV_DISCONNECT_REQ = 11,
WLAN_CM_SM_EV_DISCONNECT_START = 12,
WLAN_CM_SM_EV_DISCONNECT_ACTIVE = 13,
WLAN_CM_SM_EV_DISCONNECT_DONE = 14,
WLAN_CM_SM_EV_ROAM_START = 15,
WLAN_CM_SM_EV_ROAM_SYNC = 16,
WLAN_CM_SM_EV_ROAM_INVOKE_FAIL = 17,
WLAN_CM_SM_EV_ROAM_HO_FAIL = 18,
WLAN_CM_SM_EV_PREAUTH_DONE = 19,
WLAN_CM_SM_EV_GET_NEXT_PREAUTH_AP = 20,
WLAN_CM_SM_EV_PREAUTH_FAIL = 21,
WLAN_CM_SM_EV_START_REASSOC = 22,
WLAN_CM_SM_EV_REASSOC_DONE = 23,
WLAN_CM_SM_EV_REASSOC_FAILURE = 24,
WLAN_CM_SM_EV_ROAM_COMPLETE = 25,
WLAN_CM_EV_BSS_CREATE_PEER_SUCCESS = 9,
WLAN_CM_SM_EV_CONNECT_GET_NEXT_CANDIDATE = 10,
WLAN_CM_SM_EV_CONNECT_FAILURE = 11,
WLAN_CM_SM_EV_DISCONNECT_REQ = 12,
WLAN_CM_SM_EV_DISCONNECT_START = 13,
WLAN_CM_SM_EV_DISCONNECT_ACTIVE = 14,
WLAN_CM_SM_EV_DISCONNECT_DONE = 15,
WLAN_CM_SM_EV_ROAM_START = 16,
WLAN_CM_SM_EV_ROAM_SYNC = 17,
WLAN_CM_SM_EV_ROAM_INVOKE_FAIL = 18,
WLAN_CM_SM_EV_ROAM_HO_FAIL = 19,
WLAN_CM_SM_EV_PREAUTH_DONE = 20,
WLAN_CM_SM_EV_GET_NEXT_PREAUTH_AP = 21,
WLAN_CM_SM_EV_PREAUTH_FAIL = 22,
WLAN_CM_SM_EV_START_REASSOC = 23,
WLAN_CM_SM_EV_REASSOC_DONE = 24,
WLAN_CM_SM_EV_REASSOC_FAILURE = 25,
WLAN_CM_SM_EV_ROAM_COMPLETE = 26,
WLAN_CM_SM_EV_MAX,
};

View file

@ -22,12 +22,6 @@
#include "wlan_scan_api.h"
#include "wlan_cm_public_struct.h"
#define CONNECT_REQ_PREFIX 0x00C00000
#define DISCONNECT_REQ_PREFIX 0x00D00000
#define CM_ID_MASK 0x0000FFFF
#define CM_ID_GET_PREFIX(cm_id) cm_id & 0xFFFF0000
static uint32_t cm_get_prefix_for_cm_id(enum wlan_cm_source source) {
switch (source) {
case CM_OSIF_CONNECT:
@ -63,6 +57,19 @@ struct cnx_mgr *cm_get_cm_ctx(struct wlan_objmgr_vdev *vdev)
return vdev_mlme->cnx_mgr_ctx;
}
void cm_reset_active_cm_id(struct wlan_objmgr_vdev *vdev, wlan_cm_id cm_id)
{
struct cnx_mgr *cm_ctx;
cm_ctx = cm_get_cm_ctx(vdev);
if (!cm_ctx)
return;
/* Reset active cm id if cm id match */
if (cm_ctx->active_cm_id == cm_id)
cm_ctx->active_cm_id = CM_ID_INVALID;
}
#ifdef WLAN_CM_USE_SPINLOCK
/**

View file

@ -55,7 +55,7 @@ QDF_STATUS wlan_cm_start_disconnect(struct wlan_objmgr_vdev *vdev,
* Return: QDF_STATUS
*/
QDF_STATUS wlan_cm_bss_peer_create_rsp(struct wlan_objmgr_vdev *vdev,
uint32_t status,
QDF_STATUS status,
struct qdf_mac_addr *peer_mac);
/**

View file

@ -36,10 +36,10 @@ QDF_STATUS wlan_cm_start_disconnect(struct wlan_objmgr_vdev *vdev,
}
QDF_STATUS wlan_cm_bss_peer_create_rsp(struct wlan_objmgr_vdev *vdev,
uint32_t status,
QDF_STATUS status,
struct qdf_mac_addr *peer_mac)
{
return QDF_STATUS_SUCCESS;
return cm_bss_peer_create_rsp(vdev, status, peer_mac);
}
QDF_STATUS wlan_cm_connect_rsp(struct wlan_objmgr_vdev *vdev,