diff --git a/components/mlme/core/inc/wlan_mlme_main.h b/components/mlme/core/inc/wlan_mlme_main.h index 7d0574144c..2dbf2e8544 100644 --- a/components/mlme/core/inc/wlan_mlme_main.h +++ b/components/mlme/core/inc/wlan_mlme_main.h @@ -66,7 +66,7 @@ #define mlme_legacy_warn(params...) QDF_TRACE_WARN(QDF_MODULE_ID_MLME, params) #define mlme_legacy_info(params...) QDF_TRACE_INFO(QDF_MODULE_ID_MLME, params) #define mlme_legacy_debug(params...) QDF_TRACE_DEBUG(QDF_MODULE_ID_MLME, params) - +#define MAC_B_PR_SSID_OFFSET 12 enum size_of_len_field { ONE_BYTE = 1, TWO_BYTE = 2 diff --git a/components/mlme/core/src/wlan_mlme_vdev_mgr_interface.c b/components/mlme/core/src/wlan_mlme_vdev_mgr_interface.c index 767cb2d113..3f946cf971 100644 --- a/components/mlme/core/src/wlan_mlme_vdev_mgr_interface.c +++ b/components/mlme/core/src/wlan_mlme_vdev_mgr_interface.c @@ -35,7 +35,7 @@ #include "csr_api.h" #include #include "target_if_cm_roam_event.h" - +#include "wlan_cm_roam_api.h" #ifdef WLAN_FEATURE_11BE_MLO #include #include @@ -303,8 +303,13 @@ QDF_STATUS sta_mlme_vdev_notify_roam_start(struct vdev_mlme_obj *vdev_mlme, { mlme_legacy_debug("vdev id = %d ", vdev_mlme->vdev->vdev_objmgr.vdev_id); +#ifdef ROAM_TARGET_IF_CONVERGENCE + return wlan_cm_sta_mlme_vdev_roam_notify(vdev_mlme, event_data_len, + event_data); +#else return wma_sta_mlme_vdev_roam_notify(vdev_mlme, event_data_len, event_data); +#endif } /** diff --git a/components/target_if/connection_mgr/src/target_if_cm_roam_event.c b/components/target_if/connection_mgr/src/target_if_cm_roam_event.c index 8c10f5e97a..cc9c49a901 100644 --- a/components/target_if/connection_mgr/src/target_if_cm_roam_event.c +++ b/components/target_if/connection_mgr/src/target_if_cm_roam_event.c @@ -91,7 +91,7 @@ target_if_cm_roam_sync_frame_event(ol_scn_t scn, frame_ind_ptr = qdf_mem_malloc(sizeof(*frame_ind_ptr)); if (!frame_ind_ptr) - return -EINVAL; + return -ENOMEM; qdf_status = wmi_extract_roam_sync_frame_event(wmi_handle, event, len, @@ -128,8 +128,8 @@ int target_if_cm_roam_sync_event(ol_scn_t scn, uint8_t *event, struct wmi_unified *wmi_handle; struct wlan_objmgr_psoc *psoc; struct wlan_cm_roam_rx_ops *roam_rx_ops; + struct roam_offload_synch_ind *sync_ind = NULL; int status = 0; - uint8_t vdev_id; psoc = target_if_get_psoc_from_scn_hdl(scn); if (!psoc) { @@ -144,10 +144,11 @@ int target_if_cm_roam_sync_event(ol_scn_t scn, uint8_t *event, } status = wmi_extract_roam_sync_event(wmi_handle, event, - len, &vdev_id); + len, &sync_ind); if (QDF_IS_STATUS_ERROR(status)) { target_if_err("parsing of event failed, %d", status); - return -EINVAL; + status = -EINVAL; + goto err; } roam_rx_ops = target_if_cm_get_roam_rx_ops(psoc); @@ -159,14 +160,18 @@ int target_if_cm_roam_sync_event(ol_scn_t scn, uint8_t *event, } qdf_status = roam_rx_ops->roam_sync_event(psoc, - event, - len, - vdev_id); + event, + len, + sync_ind); if (QDF_IS_STATUS_ERROR(qdf_status)) status = -EINVAL; err: + if (sync_ind && sync_ind->ric_tspec_data) + qdf_mem_free(sync_ind->ric_tspec_data); + if (sync_ind) + qdf_mem_free(sync_ind); return status; } diff --git a/components/umac/mlme/connection_mgr/core/src/wlan_cm_roam_fw_sync.c b/components/umac/mlme/connection_mgr/core/src/wlan_cm_roam_fw_sync.c index 0c09155e05..08347a0c39 100644 --- a/components/umac/mlme/connection_mgr/core/src/wlan_cm_roam_fw_sync.c +++ b/components/umac/mlme/connection_mgr/core/src/wlan_cm_roam_fw_sync.c @@ -45,7 +45,7 @@ #include "connection_mgr/core/src/wlan_cm_sm.h" QDF_STATUS cm_fw_roam_sync_req(struct wlan_objmgr_psoc *psoc, uint8_t vdev_id, - uint8_t *event, uint32_t event_data_len) + void *event, uint32_t event_data_len) { QDF_STATUS status; struct wlan_objmgr_vdev *vdev; @@ -117,7 +117,7 @@ error: QDF_STATUS cm_fw_roam_sync_start_ind(struct wlan_objmgr_vdev *vdev, - struct roam_offload_synch_ind *roam_synch_data) + uint8_t roam_reason) { QDF_STATUS status; struct wlan_objmgr_pdev *pdev; @@ -138,7 +138,7 @@ cm_fw_roam_sync_start_ind(struct wlan_objmgr_vdev *vdev, wlan_blm_update_bssid_connect_params(pdev, connected_bssid, BLM_AP_DISCONNECTED); - if (IS_ROAM_REASON_STA_KICKOUT(roam_synch_data->roam_reason)) { + if (IS_ROAM_REASON_STA_KICKOUT(roam_reason)) { struct reject_ap_info ap_info; ap_info.bssid = connected_bssid; @@ -1159,7 +1159,7 @@ rel_ref: #endif /* WLAN_FEATURE_FIPS */ #ifdef ROAM_TARGET_IF_CONVERGENCE -QDF_STATUS cm_free_roam_synch_frame_ind(struct rso_config *rso_cfg) +QDF_STATUS wlan_cm_free_roam_synch_frame_ind(struct rso_config *rso_cfg) { struct roam_synch_frame_ind *frame_ind; diff --git a/components/umac/mlme/connection_mgr/core/src/wlan_cm_roam_i.h b/components/umac/mlme/connection_mgr/core/src/wlan_cm_roam_i.h index fd36babab1..355540b508 100644 --- a/components/umac/mlme/connection_mgr/core/src/wlan_cm_roam_i.h +++ b/components/umac/mlme/connection_mgr/core/src/wlan_cm_roam_i.h @@ -110,12 +110,12 @@ QDF_STATUS cm_abort_fw_roam(struct cnx_mgr *cm_ctx, * Return: QDF_STATUS */ QDF_STATUS cm_fw_roam_sync_req(struct wlan_objmgr_psoc *psoc, uint8_t vdev_id, - uint8_t *event, uint32_t event_data_len); + void *event, uint32_t event_data_len); /** * cm_fw_roam_sync_start_ind() - Handle roam sync req * @vdev: Vdev objmgr - * @roam_synch_data: Roam sync data ptr + * @roam_reason: Roam reason * * This function handles roam sync event to connection manager * state machine @@ -124,7 +124,7 @@ QDF_STATUS cm_fw_roam_sync_req(struct wlan_objmgr_psoc *psoc, uint8_t vdev_id, */ QDF_STATUS cm_fw_roam_sync_start_ind(struct wlan_objmgr_vdev *vdev, - struct roam_offload_synch_ind *roam_synch_data); + uint8_t roam_reason); /** * cm_fw_roam_sync_propagation() - Post roam sync propagation to CM SM @@ -187,54 +187,7 @@ cm_roam_pmkid_req_ind(struct wlan_objmgr_psoc *psoc, return QDF_STATUS_SUCCESS; } #endif /* WLAN_FEATURE_FIPS */ -#ifdef ROAM_TARGET_IF_CONVERGENCE -/** - * cm_free_roam_synch_frame_ind() - Free the bcn_probe_rsp, reassoc_req, - * reassoc_rsp received as part of the ROAM_SYNC_FRAME event - * - * @vdev - vdev obj mgr ptr - * - * This API is used to free the buffer allocated during the ROAM_SYNC_FRAME - * event - * - * Return: QDF_STATUS - */ -QDF_STATUS cm_free_roam_synch_frame_ind(struct rso_config *rso_cfg); - -/** - * cm_roam_sync_event_handler() - CM handler for roam sync event - * - * @psoc - psoc objmgr ptr - * @event - event ptr - * @len - event buff length - * @vdev_id - vdev id - * - * This API is used to handle the buffer allocated during the ROAM_SYNC_EVENT - * event - * - * Return: QDF_STATUS - */ -QDF_STATUS cm_roam_sync_event_handler(struct wlan_objmgr_psoc *psoc, - uint8_t *event, - uint32_t len, - uint8_t vdev_id); - -/** - * cm_roam_sync_frame_event_handler() - CM handler for roam sync frame event - * - * @psoc - psoc objmgr ptr - * @frame_ind - ptr to roam sync frame struct - * - * This API is used to handle the buffer allocated during the ROAM_SYNC_FRAME - * event - * - * Return: QDF_STATUS - */ -QDF_STATUS -cm_roam_sync_frame_event_handler(struct wlan_objmgr_psoc *psoc, - struct roam_synch_frame_ind *frame_ind); -#endif /* ROAM_TARGET_IF_CONVERGENCE */ -#else /* WLAN_FEATURE_ROAM_OFFLOAD */ +#else /*WLAN_FEATURE_ROAM_OFFLOAD */ static inline QDF_STATUS cm_fw_roam_invoke_fail(struct wlan_objmgr_psoc *psoc, uint8_t vdev_id) diff --git a/components/umac/mlme/connection_mgr/core/src/wlan_cm_roam_offload_event.c b/components/umac/mlme/connection_mgr/core/src/wlan_cm_roam_offload_event.c index a9260c24ea..1c25fa2962 100644 --- a/components/umac/mlme/connection_mgr/core/src/wlan_cm_roam_offload_event.c +++ b/components/umac/mlme/connection_mgr/core/src/wlan_cm_roam_offload_event.c @@ -35,6 +35,7 @@ #include "connection_mgr/core/src/wlan_cm_roam.h" #include "connection_mgr/core/src/wlan_cm_sm.h" #include "connection_mgr/core/src/wlan_cm_main_api.h" +#include "wlan_roam_debug.h" #define FW_ROAM_SYNC_TIMEOUT 7000 @@ -339,9 +340,10 @@ QDF_STATUS cm_roam_sync_event_handler(struct wlan_objmgr_psoc *psoc, uint8_t *event, uint32_t len, - uint8_t vdev_id) + struct roam_offload_synch_ind *sync_ind) { - return cm_fw_roam_sync_req(psoc, vdev_id, event, len); + return cm_fw_roam_sync_req(psoc, sync_ind->roamed_vdev_id, + sync_ind, sizeof(sync_ind)); } QDF_STATUS @@ -377,7 +379,7 @@ cm_roam_sync_frame_event_handler(struct wlan_objmgr_psoc *psoc, if (MLME_IS_ROAM_SYNCH_IN_PROGRESS(psoc, vdev_id)) { mlme_err("Ignoring this event as it is unexpected"); - cm_free_roam_synch_frame_ind(rso_cfg); + wlan_cm_free_roam_synch_frame_ind(rso_cfg); status = QDF_STATUS_E_FAILURE; goto err; } @@ -396,7 +398,7 @@ cm_roam_sync_frame_event_handler(struct wlan_objmgr_psoc *psoc, qdf_mem_malloc(roam_synch_frame_ind->bcn_probe_rsp_len); if (!roam_synch_frame_ind->bcn_probe_rsp) { QDF_ASSERT(roam_synch_frame_ind->bcn_probe_rsp); - cm_free_roam_synch_frame_ind(rso_cfg); + wlan_cm_free_roam_synch_frame_ind(rso_cfg); status = QDF_STATUS_E_NOMEM; goto err; } @@ -415,7 +417,7 @@ cm_roam_sync_frame_event_handler(struct wlan_objmgr_psoc *psoc, qdf_mem_malloc(roam_synch_frame_ind->reassoc_req_len); if (!roam_synch_frame_ind->reassoc_req) { QDF_ASSERT(roam_synch_frame_ind->reassoc_req); - cm_free_roam_synch_frame_ind(rso_cfg); + wlan_cm_free_roam_synch_frame_ind(rso_cfg); status = QDF_STATUS_E_NOMEM; goto err; } @@ -435,7 +437,7 @@ cm_roam_sync_frame_event_handler(struct wlan_objmgr_psoc *psoc, qdf_mem_malloc(roam_synch_frame_ind->reassoc_rsp_len); if (!roam_synch_frame_ind->reassoc_rsp) { QDF_ASSERT(roam_synch_frame_ind->reassoc_rsp); - cm_free_roam_synch_frame_ind(rso_cfg); + wlan_cm_free_roam_synch_frame_ind(rso_cfg); status = QDF_STATUS_E_NOMEM; goto err; } @@ -448,4 +450,101 @@ err: wlan_objmgr_vdev_release_ref(vdev, WLAN_MLME_SB_ID); return status; } + +QDF_STATUS cm_roam_sync_event_handler_cb(struct wlan_objmgr_vdev *vdev, + uint8_t *event, + uint32_t len) +{ + struct roam_offload_synch_ind *sync_ind = NULL; + struct wlan_objmgr_psoc *psoc = NULL; + QDF_STATUS status = QDF_STATUS_SUCCESS; + struct rso_config *rso_cfg; + uint16_t ie_len = 0; + + sync_ind = (struct roam_offload_synch_ind *)event; + + if (!sync_ind) { + mlme_err("Roam Sync ind ptr is NULL"); + return QDF_STATUS_E_NULL_VALUE; + } + + if (!vdev) { + mlme_err("Vdev is NULL"); + return QDF_STATUS_E_NULL_VALUE; + } + + psoc = wlan_vdev_get_psoc(vdev); + if (!psoc) { + mlme_err("Psoc is NULL"); + return QDF_STATUS_E_NULL_VALUE; + } + + rso_cfg = wlan_cm_get_rso_config(vdev); + if (!rso_cfg) + return QDF_STATUS_E_NULL_VALUE; + + wlan_roam_debug_log(sync_ind->roamed_vdev_id, DEBUG_ROAM_SYNCH_IND, + DEBUG_INVALID_PEER_ID, sync_ind->bssid.bytes, NULL, + 0, + 0); + DPTRACE(qdf_dp_trace_record_event(QDF_DP_TRACE_EVENT_RECORD, + sync_ind->roamed_vdev_id, + QDF_TRACE_DEFAULT_PDEV_ID, + QDF_PROTO_TYPE_EVENT, + QDF_ROAM_SYNCH)); + + if (MLME_IS_ROAM_SYNCH_IN_PROGRESS(psoc, sync_ind->roamed_vdev_id)) { + mlme_err("Ignoring RSI since one is already in progress"); + status = QDF_STATUS_E_FAILURE; + goto err; + } + + if (!QDF_IS_STATUS_SUCCESS(cm_fw_roam_sync_start_ind(vdev, + sync_ind->roam_reason))) { + mlme_err("LFR3: CSR Roam synch cb failed"); + wlan_cm_free_roam_synch_frame_ind(rso_cfg); + goto err; + } + + /* 24 byte MAC header and 12 byte to ssid IE */ + if (sync_ind->beaconProbeRespLength > + (QDF_IEEE80211_3ADDR_HDR_LEN + MAC_B_PR_SSID_OFFSET)) { + ie_len = sync_ind->beaconProbeRespLength - + (QDF_IEEE80211_3ADDR_HDR_LEN + MAC_B_PR_SSID_OFFSET); + } else { + mlme_err("LFR3: Invalid Beacon Length"); + goto err; + } + + if (QDF_IS_STATUS_ERROR(cm_roam_pe_sync_callback(sync_ind, + ie_len))) { + mlme_err("LFR3: PE roam synch cb failed"); + status = QDF_STATUS_E_BUSY; + goto err; + } + + cm_roam_update_vdev(sync_ind); + /* + * update phy_mode in wma to avoid mismatch in phymode between host and + * firmware. The phymode stored in peer->peer_mlme.phymode is + * sent to firmware as part of opmode update during either - vht opmode + * action frame received or during opmode change detected while + * processing beacon. Any mismatch of this value with firmware phymode + * results in firmware assert. + */ + cm_update_phymode_on_roam(sync_ind->roamed_vdev_id, + sync_ind->bssid.bytes, + &sync_ind->chan); + cm_fw_roam_sync_propagation(psoc, + sync_ind->roamed_vdev_id, + sync_ind); + +err: + if (QDF_IS_STATUS_ERROR(status)) { + cm_fw_roam_abort_req(psoc, sync_ind->roamed_vdev_id); + cm_roam_stop_req(psoc, sync_ind->roamed_vdev_id, + REASON_ROAM_SYNCH_FAILED); + } + return status; +} #endif /* ROAM_TARGET_IF_CONVERGENCE */ diff --git a/components/umac/mlme/connection_mgr/dispatcher/inc/wlan_cm_roam_api.h b/components/umac/mlme/connection_mgr/dispatcher/inc/wlan_cm_roam_api.h index 4f71ad198a..d4b56b558f 100644 --- a/components/umac/mlme/connection_mgr/dispatcher/inc/wlan_cm_roam_api.h +++ b/components/umac/mlme/connection_mgr/dispatcher/inc/wlan_cm_roam_api.h @@ -679,6 +679,16 @@ static inline QDF_STATUS wlan_cm_host_roam_start(struct scheduler_msg *msg) #endif #ifdef WLAN_FEATURE_ROAM_OFFLOAD +/** + * wlan_cm_fw_roam_abort_req() - roam abort request handling + * @psoc: psoc pointer + * @vdev_id: vdev id + * + * Return: QDF_STATUS + */ +QDF_STATUS +wlan_cm_fw_roam_abort_req(struct wlan_objmgr_psoc *psoc, uint8_t vdev_id); + /** * wlan_cm_roam_extract_btm_response() - Extract BTM rsp stats * @wmi: wmi handle @@ -905,7 +915,6 @@ cm_akm_roam_allowed(struct wlan_objmgr_psoc *psoc, struct wlan_objmgr_vdev *vdev); #ifdef ROAM_TARGET_IF_CONVERGENCE - /** * cm_invalid_roam_reason_handler() - Handler for invalid roam reason * @vdev_id: vdev id @@ -935,7 +944,71 @@ cm_handle_roam_reason_ho_failed(uint8_t vdev_id, struct qdf_mac_addr bssid, */ QDF_STATUS cm_handle_scan_ch_list_data(struct cm_roam_scan_ch_resp *data); -#endif + +/** + * wlan_cm_free_roam_synch_frame_ind() - Free the bcn_probe_rsp, reassoc_req, + * reassoc_rsp received as part of the ROAM_SYNC_FRAME event + * + * @vdev - vdev obj mgr ptr + * + * This API is used to free the buffer allocated during the ROAM_SYNC_FRAME + * event + * + * Return: QDF_STATUS + */ +QDF_STATUS wlan_cm_free_roam_synch_frame_ind(struct rso_config *rso_cfg); + +/** + * cm_roam_sync_event_handler() - CM handler for roam sync event + * + * @psoc - psoc objmgr ptr + * @event - event ptr + * @len - event buff length + * @vdev_id - vdev id + * + * This API is used to handle the buffer allocated during the ROAM_SYNC_EVENT + * event + * + * Return: QDF_STATUS + */ +QDF_STATUS cm_roam_sync_event_handler(struct wlan_objmgr_psoc *psoc, + uint8_t *event, + uint32_t len, + struct roam_offload_synch_ind *sync_ind); + +/** + * cm_roam_sync_frame_event_handler() - CM handler for roam sync frame event + * + * @psoc - psoc objmgr ptr + * @frame_ind - ptr to roam sync frame struct + * + * This API is used to handle the buffer allocated during the ROAM_SYNC_FRAME + * event + * + * Return: QDF_STATUS + */ +QDF_STATUS +cm_roam_sync_frame_event_handler(struct wlan_objmgr_psoc *psoc, + struct roam_synch_frame_ind *frame_ind); + +/** + * cm_roam_sync_event_handler_cb() - CM callback handler for roam + * sync event + * + * @vdev - vdev objmgr ptr + * @event - event ptr + * @len - event data len + * + * This API is used to handle the buffer allocated during the ROAM_SYNC + * event + * + * Return: QDF_STATUS + */ +QDF_STATUS cm_roam_sync_event_handler_cb(struct wlan_objmgr_vdev *vdev, + uint8_t *event, + uint32_t len); +#endif /* ROAM_TARGET_IF_CONVERGENCE */ + #else static inline void wlan_cm_roam_activate_pcl_per_vdev(struct wlan_objmgr_psoc *psoc, @@ -1063,7 +1136,7 @@ cm_handle_scan_ch_list_data(struct cm_roam_scan_ch_resp *data) return QDF_STATUS_E_NOSUPPORT; } #endif -#endif /* FEATURE_ROAM_OFFLOAD */ +#endif /* WLAN_FEATURE_ROAM_OFFLOAD */ /** * wlan_get_chan_by_bssid_from_rnr: get chan from rnr through bssid @@ -1213,5 +1286,79 @@ cm_handle_disconnect_reason(struct vdev_disconnect_event_data *data); */ QDF_STATUS cm_roam_scan_ch_list_event_handler(struct cm_roam_scan_ch_resp *data); -#endif + +/** + * cm_roam_update_vdev() - Update the STA and BSS + * @sync_ind: Information needed for roam sync propagation + * + * This function will perform all the vdev related operations with + * respect to the self sta and the peer after roaming and completes + * the roam synch propagation with respect to WMA layer. + * + * Return: None + */ +void cm_roam_update_vdev(struct roam_offload_synch_ind *sync_ind); + +/** + * cm_roam_pe_sync_callback() - Callback registered at pe, gets invoked when + * ROAM SYNCH event is received from firmware + * @sync_ind: Structure with roam synch parameters + * @len: length for bss_description + * + * This is a PE level callback called from CM to complete the roam synch + * propagation at PE level and also fill the BSS descriptor which will be + * helpful further to complete the roam synch propagation. + * + * Return: QDF_STATUS + */ +QDF_STATUS +cm_roam_pe_sync_callback(struct roam_offload_synch_ind *sync_ind, + uint16_t len); + +/** + * cm_update_phymode_on_roam() - Update new phymode after + * ROAM SYNCH event is received from firmware + * @vdev_id: roamed vdev id + * @bssid: bssid + * @chan: wmi channel + * + * This api will update the phy mode after roam sync is received. + * + * Return: none + */ +void cm_update_phymode_on_roam(uint8_t vdev_id, uint8_t *bssid, + wmi_channel *chan); + +/** + * wlan_cm_fw_to_host_phymode() - Convert fw phymode to host + * @phymode: wmi phymode + * + * This api will convert the phy mode from fw to host type. + * + * Return: wlan phymode + */ +enum wlan_phymode +wlan_cm_fw_to_host_phymode(WMI_HOST_WLAN_PHY_MODE phymode); + +/** + * wlan_cm_sta_mlme_vdev_roam_notify() - STA mlme vdev roam nottify + * + * @sync_ind: Information needed for roam sync propagation + * + * This function will invokes CM roam callback api to continue + * the roam synch propagation. + * + * Return: None + */ +QDF_STATUS +wlan_cm_sta_mlme_vdev_roam_notify(struct vdev_mlme_obj *vdev_mlme, + uint16_t data_len, void *data); +#else +static inline QDF_STATUS +wlan_cm_sta_mlme_vdev_roam_notify(struct vdev_mlme_obj *vdev_mlme, + uint16_t data_len, void *data) +{ + return QDF_STATUS_E_NOSUPPORT; +} +#endif /* ROAM_TARGET_IF_CONVERGENCE */ #endif /* WLAN_CM_ROAM_API_H__ */ diff --git a/components/umac/mlme/connection_mgr/dispatcher/inc/wlan_cm_roam_public_struct.h b/components/umac/mlme/connection_mgr/dispatcher/inc/wlan_cm_roam_public_struct.h index 46c84a9021..deb0cef580 100644 --- a/components/umac/mlme/connection_mgr/dispatcher/inc/wlan_cm_roam_public_struct.h +++ b/components/umac/mlme/connection_mgr/dispatcher/inc/wlan_cm_roam_public_struct.h @@ -28,6 +28,7 @@ #include "wmi_unified_param.h" #include "wmi_unified_sta_param.h" #include "wlan_cm_public_struct.h" +#include "wmi_unified.h" #define ROAM_SCAN_OFFLOAD_START 1 #define ROAM_SCAN_OFFLOAD_STOP 2 @@ -1913,34 +1914,6 @@ struct wlan_cm_roam_tx_ops { QDF_STATUS (*send_roam_sync_complete_cmd)(struct wlan_objmgr_vdev *vdev); }; -/** - * wlan_cm_roam_rx_ops - structure of rx function pointers for - * roaming related commands - * @roam_sync_event: RX ops function pointer for roam sync event - * @roam_sync_frame_event: Rx ops function pointer for roam sync frame event - * @roam_event_rx: Rx ops function pointer for roam info event - * @btm_blacklist_event: Rx ops function pointer for btm blacklist event - * @vdev_disconnect_event: Rx ops function pointer for vdev disconnect event - * @roam_scan_chan_list_event: Rx ops function pointer for roam scan ch event - */ -struct wlan_cm_roam_rx_ops { - QDF_STATUS (*roam_sync_event)(struct wlan_objmgr_psoc *psoc, - uint8_t *event, - uint32_t len, - uint8_t vdev_id); - QDF_STATUS (*roam_sync_frame_event)(struct wlan_objmgr_psoc *psoc, - struct roam_synch_frame_ind *frm); - QDF_STATUS (*roam_event_rx)(struct roam_offload_roam_event roam_event); -#ifdef ROAM_TARGET_IF_CONVERGENCE - QDF_STATUS (*btm_blacklist_event)(struct wlan_objmgr_psoc *psoc, - struct roam_blacklist_event *list); - QDF_STATUS - (*vdev_disconnect_event)(struct vdev_disconnect_event_data *data); - QDF_STATUS - (*roam_scan_chan_list_event)(struct cm_roam_scan_ch_resp *data); -#endif -}; - /** * enum roam_scan_freq_scheme - Scan mode for triggering roam * ROAM_SCAN_FREQ_SCHEME_NO_SCAN: Indicates the fw to not scan. @@ -2080,5 +2053,34 @@ struct roam_offload_synch_ind { uint8_t hlp_data[FILS_MAX_HLP_DATA_LEN]; bool is_ft_im_roam; enum wlan_phymode phy_mode; /*phy mode sent by fw */ + wmi_channel chan; +}; + +/** + * wlan_cm_roam_rx_ops - structure of rx function pointers for + * roaming related commands + * @roam_sync_event: RX ops function pointer for roam sync event + * @roam_sync_frame_event: Rx ops function pointer for roam sync frame event + * @roam_event_rx: Rx ops function pointer for roam info event + * @btm_blacklist_event: Rx ops function pointer for btm blacklist event + * @vdev_disconnect_event: Rx ops function pointer for vdev disconnect event + * @roam_scan_chan_list_event: Rx ops function pointer for roam scan ch event + */ +struct wlan_cm_roam_rx_ops { + QDF_STATUS (*roam_sync_event)(struct wlan_objmgr_psoc *psoc, + uint8_t *event, + uint32_t len, + struct roam_offload_synch_ind *sync_ind); + QDF_STATUS (*roam_sync_frame_event)(struct wlan_objmgr_psoc *psoc, + struct roam_synch_frame_ind *frm); + QDF_STATUS (*roam_event_rx)(struct roam_offload_roam_event roam_event); +#ifdef ROAM_TARGET_IF_CONVERGENCE + QDF_STATUS (*btm_blacklist_event)(struct wlan_objmgr_psoc *psoc, + struct roam_blacklist_event *list); + QDF_STATUS + (*vdev_disconnect_event)(struct vdev_disconnect_event_data *data); + QDF_STATUS + (*roam_scan_chan_list_event)(struct cm_roam_scan_ch_resp *data); +#endif }; #endif diff --git a/components/umac/mlme/connection_mgr/dispatcher/src/wlan_cm_roam_api.c b/components/umac/mlme/connection_mgr/dispatcher/src/wlan_cm_roam_api.c index 82d8ba6c77..8f0f82aa45 100644 --- a/components/umac/mlme/connection_mgr/dispatcher/src/wlan_cm_roam_api.c +++ b/components/umac/mlme/connection_mgr/dispatcher/src/wlan_cm_roam_api.c @@ -31,6 +31,8 @@ #include "connection_mgr/core/src/wlan_cm_roam.h" #include "wlan_cm_roam_api.h" #include "wlan_blm_api.h" +#include <../../core/src/wlan_cm_roam_i.h> + /* Support for "Fast roaming" (i.e., ESE, LFR, or 802.11r.) */ #define BG_SCAN_OCCUPIED_CHANNEL_LIST_LEN 15 @@ -320,6 +322,12 @@ QDF_STATUS wlan_cm_roam_stop_req(struct wlan_objmgr_psoc *psoc, uint8_t vdev_id, } #ifdef WLAN_FEATURE_ROAM_OFFLOAD +QDF_STATUS +wlan_cm_fw_roam_abort_req(struct wlan_objmgr_psoc *psoc, uint8_t vdev_id) +{ + return cm_fw_roam_abort_req(psoc, vdev_id); +} + QDF_STATUS wlan_cm_roam_extract_btm_response(wmi_unified_t wmi, void *evt_buf, struct roam_btm_response_data *dst, @@ -2055,6 +2063,20 @@ QDF_STATUS wlan_get_chan_by_link_id_from_rnr(struct wlan_objmgr_vdev *vdev, } #endif +#ifdef ROAM_TARGET_IF_CONVERGENCE +QDF_STATUS wlan_cm_sta_mlme_vdev_roam_notify(struct vdev_mlme_obj *vdev_mlme, + uint16_t data_len, void *data) +{ + QDF_STATUS status = QDF_STATUS_SUCCESS; +#ifdef WLAN_FEATURE_ROAM_OFFLOAD + status = cm_roam_sync_event_handler_cb(vdev_mlme->vdev, data, data_len); + if (QDF_IS_STATUS_ERROR(status)) + mlme_err("Failed to process roam synch event"); +#endif + return status; +} +#endif + #ifdef ROAM_TARGET_IF_CONVERGENCE #ifdef WLAN_FEATURE_ROAM_OFFLOAD static void diff --git a/components/wmi/inc/wmi_unified_roam_api.h b/components/wmi/inc/wmi_unified_roam_api.h index a1eb229a49..07db03f867 100644 --- a/components/wmi/inc/wmi_unified_roam_api.h +++ b/components/wmi/inc/wmi_unified_roam_api.h @@ -243,13 +243,19 @@ QDF_STATUS wmi_unified_vdev_set_pcl_cmd(wmi_unified_t wmi_handle, * wmi_extract_roam_sync_event - Extract roam sync event * @wmi_handle: WMI handle * @evt_buf: Event buffer + * @len: evt buffer data len + * @synd_ind: roam sync ptr + * + * This api will allocate memory for roam sync info, extract + * the information sent by FW and pass to CM.The memory will be + * freed by target_if_cm_roam_sync_event. * * Return: QDF_STATUS */ QDF_STATUS wmi_extract_roam_sync_event(wmi_unified_t wmi_handle, void *evt_buf, uint32_t len, - uint8_t *vdev_id); + struct roam_offload_synch_ind **sync_ind); /** * wmi_extract_roam_sync_frame_event - Extract roam sync frame event diff --git a/components/wmi/src/wmi_unified_roam_api.c b/components/wmi/src/wmi_unified_roam_api.c index 1f943c3b60..5b71f5de94 100644 --- a/components/wmi/src/wmi_unified_roam_api.c +++ b/components/wmi/src/wmi_unified_roam_api.c @@ -341,13 +341,13 @@ QDF_STATUS wmi_unified_set_roam_triggers(wmi_unified_t wmi_handle, #ifdef ROAM_TARGET_IF_CONVERGENCE QDF_STATUS wmi_extract_roam_sync_event(wmi_unified_t wmi_handle, void *evt_buf, uint32_t len, - uint8_t *vdev_id) + struct roam_offload_synch_ind **sync_ind) { if (wmi_handle->ops->extract_roam_sync_event) return wmi_handle->ops->extract_roam_sync_event(wmi_handle, evt_buf, len, - vdev_id); + sync_ind); return QDF_STATUS_E_FAILURE; } diff --git a/components/wmi/src/wmi_unified_roam_tlv.c b/components/wmi/src/wmi_unified_roam_tlv.c index d82118ab5c..5219b7d7d2 100644 --- a/components/wmi/src/wmi_unified_roam_tlv.c +++ b/components/wmi/src/wmi_unified_roam_tlv.c @@ -24,6 +24,7 @@ #include "wmi.h" #include "wlan_roam_debug.h" #include "ol_defines.h" +#include "wlan_cm_roam_api.h" #define WMI_MAC_TO_PDEV_MAP(x) ((x) + (1)) #define WMI_PDEV_TO_MAC_MAP(x) ((x) - (1)) @@ -1668,41 +1669,389 @@ extract_roam_msg_info_tlv(wmi_unified_t wmi_handle, void *evt_buf, } #ifdef ROAM_TARGET_IF_CONVERGENCE +static void +wmi_extract_pdev_hw_mode_trans_ind( + wmi_pdev_hw_mode_transition_event_fixed_param *fixed_param, + wmi_pdev_set_hw_mode_response_vdev_mac_entry *vdev_mac_entry, + struct cm_hw_mode_trans_ind *hw_mode_trans_ind) +{ + uint32_t i; + + if (fixed_param->num_vdev_mac_entries > MAX_VDEV_SUPPORTED) { + wmi_err("Number of Vdev mac entries %d exceeded max vdev supported %d", + fixed_param->num_vdev_mac_entries, + MAX_VDEV_SUPPORTED); + return; + } + hw_mode_trans_ind->old_hw_mode_index = fixed_param->old_hw_mode_index; + hw_mode_trans_ind->new_hw_mode_index = fixed_param->new_hw_mode_index; + hw_mode_trans_ind->num_vdev_mac_entries = + fixed_param->num_vdev_mac_entries; + wmi_debug("old_hw_mode_index:%d new_hw_mode_index:%d entries=%d", + fixed_param->old_hw_mode_index, + fixed_param->new_hw_mode_index, + fixed_param->num_vdev_mac_entries); + + if (!vdev_mac_entry) { + wmi_err("Invalid vdev_mac_entry"); + return; + } + + /* Store the vdev-mac map in WMA and send to policy manager */ + for (i = 0; i < fixed_param->num_vdev_mac_entries; i++) { + uint32_t vdev_id, mac_id, pdev_id; + + vdev_id = vdev_mac_entry[i].vdev_id; + pdev_id = vdev_mac_entry[i].pdev_id; + + if (pdev_id == OL_TXRX_PDEV_ID) { + wmi_err("soc level id received for mac id"); + return; + } + if (vdev_id >= WLAN_MAX_VDEVS) { + wmi_err("vdev_id: %d is invalid, max_bssid: %d", + vdev_id, WLAN_MAX_VDEVS); + return; + } + + mac_id = WMI_PDEV_TO_MAC_MAP(vdev_mac_entry[i].pdev_id); + + hw_mode_trans_ind->vdev_mac_map[i].vdev_id = vdev_id; + hw_mode_trans_ind->vdev_mac_map[i].mac_id = mac_id; + + wmi_debug("vdev_id:%d mac_id:%d", vdev_id, mac_id); + } +} + +/** + * wmi_fill_data_synch_frame_event() - Fill the the roam sync data buffer using + * synch frame event data + * @wma: Global WMA Handle + * @roam_sync_ind: Buffer to be filled + * @param_buf: Source buffer + * + * Firmware sends all the required information required for roam + * synch propagation as TLV's and stored in param_buf. These + * parameters are parsed and filled into the roam synch indication + * buffer which will be used at different layers for propagation. + * + * Return: None + */ +static void +wmi_fill_data_synch_frame_event(struct rso_config *rso_cfg, + struct roam_offload_synch_ind *roam_sync_ind) +{ + uint8_t *bcn_probersp_ptr; + uint8_t *reassoc_rsp_ptr; + uint8_t *reassoc_req_ptr; + + /* Beacon/Probe Rsp data */ + roam_sync_ind->beaconProbeRespOffset = + sizeof(struct roam_offload_synch_ind); + bcn_probersp_ptr = (uint8_t *)roam_sync_ind + + roam_sync_ind->beaconProbeRespOffset; + roam_sync_ind->beaconProbeRespLength = + rso_cfg->roam_sync_frame_ind.bcn_probe_rsp_len; + qdf_mem_copy(bcn_probersp_ptr, + rso_cfg->roam_sync_frame_ind.bcn_probe_rsp, + roam_sync_ind->beaconProbeRespLength); + qdf_mem_free(rso_cfg->roam_sync_frame_ind.bcn_probe_rsp); + rso_cfg->roam_sync_frame_ind.bcn_probe_rsp = NULL; + + /* ReAssoc Rsp data */ + roam_sync_ind->reassocRespOffset = + sizeof(struct roam_offload_synch_ind) + + roam_sync_ind->beaconProbeRespLength; + roam_sync_ind->reassocRespLength = + rso_cfg->roam_sync_frame_ind.reassoc_rsp_len; + reassoc_rsp_ptr = (uint8_t *)roam_sync_ind + + roam_sync_ind->reassocRespOffset; + qdf_mem_copy(reassoc_rsp_ptr, + rso_cfg->roam_sync_frame_ind.reassoc_rsp, + roam_sync_ind->reassocRespLength); + qdf_mem_free(rso_cfg->roam_sync_frame_ind.reassoc_rsp); + rso_cfg->roam_sync_frame_ind.reassoc_rsp = NULL; + + /* ReAssoc Req data */ + roam_sync_ind->reassoc_req_offset = + sizeof(struct roam_offload_synch_ind) + + roam_sync_ind->beaconProbeRespLength + + roam_sync_ind->reassocRespLength; + roam_sync_ind->reassoc_req_length = + rso_cfg->roam_sync_frame_ind.reassoc_req_len; + reassoc_req_ptr = (uint8_t *)roam_sync_ind + + roam_sync_ind->reassoc_req_offset; + qdf_mem_copy(reassoc_req_ptr, + rso_cfg->roam_sync_frame_ind.reassoc_req, + roam_sync_ind->reassoc_req_length); + qdf_mem_free(rso_cfg->roam_sync_frame_ind.reassoc_req); + rso_cfg->roam_sync_frame_ind.reassoc_req = NULL; +} + +/** + * wmi_fill_data_synch_event() - Fill the the roam sync data buffer + * using synch event data + * @wma: Global WMA Handle + * @roam_sync_ind: Buffer to be filled + * @param_buf: Source buffer + * + * Firmware sends all the required information required for roam + * synch propagation as TLV's and stored in param_buf. These + * parameters are parsed and filled into the roam synch indication + * buffer which will be used at different layers for propagation. + * + * Return: None + */ +static void +wmi_fill_data_synch_event(struct roam_offload_synch_ind *roam_sync_ind, + WMI_ROAM_SYNCH_EVENTID_param_tlvs *param_buf) +{ + uint8_t *bcn_probersp_ptr; + uint8_t *reassoc_rsp_ptr; + uint8_t *reassoc_req_ptr; + wmi_roam_synch_event_fixed_param *synch_event; + + synch_event = param_buf->fixed_param; + + /* Beacon/Probe Rsp data */ + roam_sync_ind->beaconProbeRespOffset = + sizeof(struct roam_offload_synch_ind); + bcn_probersp_ptr = (uint8_t *)roam_sync_ind + + roam_sync_ind->beaconProbeRespOffset; + roam_sync_ind->beaconProbeRespLength = + synch_event->bcn_probe_rsp_len; + qdf_mem_copy(bcn_probersp_ptr, param_buf->bcn_probe_rsp_frame, + roam_sync_ind->beaconProbeRespLength); + /* ReAssoc Rsp data */ + roam_sync_ind->reassocRespOffset = + sizeof(struct roam_offload_synch_ind) + + roam_sync_ind->beaconProbeRespLength; + roam_sync_ind->reassocRespLength = synch_event->reassoc_rsp_len; + reassoc_rsp_ptr = (uint8_t *)roam_sync_ind + + roam_sync_ind->reassocRespOffset; + qdf_mem_copy(reassoc_rsp_ptr, + param_buf->reassoc_rsp_frame, + roam_sync_ind->reassocRespLength); + + /* ReAssoc Req data */ + roam_sync_ind->reassoc_req_offset = + sizeof(struct roam_offload_synch_ind) + + roam_sync_ind->beaconProbeRespLength + + roam_sync_ind->reassocRespLength; + roam_sync_ind->reassoc_req_length = synch_event->reassoc_req_len; + reassoc_req_ptr = (uint8_t *)roam_sync_ind + + roam_sync_ind->reassoc_req_offset; + qdf_mem_copy(reassoc_req_ptr, param_buf->reassoc_req_frame, + roam_sync_ind->reassoc_req_length); +} + +static QDF_STATUS +wmi_fill_roam_sync_buffer(struct wlan_objmgr_vdev *vdev, + struct rso_config *rso_cfg, + struct roam_offload_synch_ind *roam_sync_ind, + WMI_ROAM_SYNCH_EVENTID_param_tlvs *param_buf) +{ + wmi_roam_synch_event_fixed_param *synch_event; + wmi_channel *chan; + wmi_key_material *key; + wmi_key_material_ext *key_ft; + wmi_roam_fils_synch_tlv_param *fils_info; + wmi_roam_pmk_cache_synch_tlv_param *pmk_cache_info; + QDF_STATUS status = QDF_STATUS_E_FAILURE; + uint8_t kck_len; + uint8_t kek_len; + + synch_event = param_buf->fixed_param; + roam_sync_ind->roamed_vdev_id = synch_event->vdev_id; + roam_sync_ind->auth_status = synch_event->auth_status; + roam_sync_ind->roam_reason = synch_event->roam_reason; + roam_sync_ind->rssi = synch_event->rssi; + + WMI_MAC_ADDR_TO_CHAR_ARRAY(&synch_event->bssid, + roam_sync_ind->bssid.bytes); + wmi_debug("roamedVdevId %d authStatus %d roamReason %d rssi %d isBeacon %d", + roam_sync_ind->roamed_vdev_id, + roam_sync_ind->auth_status, + roam_sync_ind->roam_reason, + roam_sync_ind->rssi, + roam_sync_ind->isBeacon); + + /* + * If lengths of bcn_probe_rsp, reassoc_req and reassoc_rsp are zero in + * synch_event driver would have received bcn_probe_rsp, reassoc_req + * and reassoc_rsp via the event WMI_ROAM_SYNCH_FRAME_EVENTID + */ + if ((!synch_event->bcn_probe_rsp_len) && + (!synch_event->reassoc_req_len) && + (!synch_event->reassoc_rsp_len)) { + if (!rso_cfg->roam_sync_frame_ind.bcn_probe_rsp) { + wmi_err("LFR3: bcn_probe_rsp is NULL"); + QDF_ASSERT(rso_cfg->roam_sync_frame_ind.bcn_probe_rsp); + wlan_cm_free_roam_synch_frame_ind(rso_cfg); + return status; + } + if (!rso_cfg->roam_sync_frame_ind.reassoc_rsp) { + wmi_err("LFR3: reassoc_rsp is NULL"); + QDF_ASSERT(rso_cfg->roam_sync_frame_ind.reassoc_rsp); + wlan_cm_free_roam_synch_frame_ind(rso_cfg); + return status; + } + if (!rso_cfg->roam_sync_frame_ind.reassoc_req) { + wmi_err("LFR3: reassoc_req is NULL"); + QDF_ASSERT(rso_cfg->roam_sync_frame_ind.reassoc_req); + wlan_cm_free_roam_synch_frame_ind(rso_cfg); + return status; + } + wmi_fill_data_synch_frame_event(rso_cfg, roam_sync_ind); + } else { + wmi_fill_data_synch_event(roam_sync_ind, param_buf); + } + chan = param_buf->chan; + if (chan) { + roam_sync_ind->chan_freq = chan->mhz; + roam_sync_ind->phy_mode = + wlan_cm_fw_to_host_phymode(WMI_GET_CHANNEL_MODE(chan)); + } else { + roam_sync_ind->phy_mode = WLAN_PHYMODE_AUTO; + } + roam_sync_ind->chan = *chan; + + key = param_buf->key; + key_ft = param_buf->key_ext; + if (key) { + roam_sync_ind->kck_len = KCK_KEY_LEN; + qdf_mem_copy(roam_sync_ind->kck, key->kck, + KCK_KEY_LEN); + roam_sync_ind->kek_len = KEK_KEY_LEN; + qdf_mem_copy(roam_sync_ind->kek, key->kek, + KEK_KEY_LEN); + qdf_mem_copy(roam_sync_ind->replay_ctr, + key->replay_counter, REPLAY_CTR_LEN); + } else if (key_ft) { + /* + * For AKM 00:0F:AC (FT suite-B-SHA384) + * KCK-bits:192 KEK-bits:256 + * Firmware sends wmi_key_material_ext tlv now only if + * auth is FT Suite-B SHA-384 auth. If further new suites + * are added, add logic to get kck, kek bits based on + * akm protocol + */ + kck_len = KCK_192BIT_KEY_LEN; + kek_len = KEK_256BIT_KEY_LEN; + + roam_sync_ind->kck_len = kck_len; + qdf_mem_copy(roam_sync_ind->kck, + key_ft->key_buffer, kck_len); + + roam_sync_ind->kek_len = kek_len; + qdf_mem_copy(roam_sync_ind->kek, + (key_ft->key_buffer + kck_len), + kek_len); + + qdf_mem_copy(roam_sync_ind->replay_ctr, + (key_ft->key_buffer + kek_len + kck_len), + REPLAY_CTR_LEN); + } + + if (param_buf->hw_mode_transition_fixed_param) + wmi_extract_pdev_hw_mode_trans_ind( + param_buf->hw_mode_transition_fixed_param, + param_buf->wmi_pdev_set_hw_mode_response_vdev_mac_mapping, + &roam_sync_ind->hw_mode_trans_ind); + else + wmi_debug("hw_mode transition fixed param is NULL"); + + fils_info = param_buf->roam_fils_synch_info; + if (fils_info) { + if ((fils_info->kek_len > MAX_KEK_LENGTH) || + (fils_info->pmk_len > MAX_PMK_LEN)) { + wmi_err("Invalid kek_len %d or pmk_len %d", + fils_info->kek_len, + fils_info->pmk_len); + wlan_cm_free_roam_synch_frame_ind(rso_cfg); + return status; + } + + roam_sync_ind->kek_len = fils_info->kek_len; + qdf_mem_copy(roam_sync_ind->kek, fils_info->kek, + fils_info->kek_len); + + roam_sync_ind->pmk_len = fils_info->pmk_len; + qdf_mem_copy(roam_sync_ind->pmk, fils_info->pmk, + fils_info->pmk_len); + + qdf_mem_copy(roam_sync_ind->pmkid, fils_info->pmkid, + PMKID_LEN); + + roam_sync_ind->update_erp_next_seq_num = + fils_info->update_erp_next_seq_num; + roam_sync_ind->next_erp_seq_num = + fils_info->next_erp_seq_num; + + wmi_debug("Update ERP Seq Num %d, Next ERP Seq Num %d", + roam_sync_ind->update_erp_next_seq_num, + roam_sync_ind->next_erp_seq_num); + } + + pmk_cache_info = param_buf->roam_pmk_cache_synch_info; + if (pmk_cache_info && (pmk_cache_info->pmk_len)) { + if (pmk_cache_info->pmk_len > MAX_PMK_LEN) { + wmi_err("Invalid pmk_len %d", + pmk_cache_info->pmk_len); + wlan_cm_free_roam_synch_frame_ind(rso_cfg); + return status; + } + + roam_sync_ind->pmk_len = pmk_cache_info->pmk_len; + qdf_mem_copy(roam_sync_ind->pmk, + pmk_cache_info->pmk, pmk_cache_info->pmk_len); + qdf_mem_copy(roam_sync_ind->pmkid, + pmk_cache_info->pmkid, PMKID_LEN); + } + wlan_cm_free_roam_synch_frame_ind(rso_cfg); + return QDF_STATUS_SUCCESS; +} + /** * extract_roam_sync_event_tlv() - Extract the roam sync event * from the wmi_roam_synch_event_id * @wmi_handle: wmi handle * @evt_buf: Pointer to the event buffer * @len: Data length - * @vdev_id: Vdev Id + * @roam_sync_ind: Ptr to roam offload sync struct */ static QDF_STATUS extract_roam_sync_event_tlv(wmi_unified_t wmi_handle, void *evt_buf, uint32_t len, - uint8_t *vdev_id) + struct roam_offload_synch_ind **roam_sync_ind) { QDF_STATUS status = QDF_STATUS_SUCCESS; wmi_roam_synch_event_fixed_param *synch_event = NULL; WMI_ROAM_SYNCH_EVENTID_param_tlvs *param_buf = NULL; + struct roam_offload_synch_ind *roam_sync = NULL; + struct wlan_objmgr_vdev *vdev = NULL; + struct wlan_objmgr_psoc *psoc = NULL; + struct rso_config *rso_cfg; + uint32_t roam_synch_data_len; + uint32_t bcn_probe_rsp_len; + uint32_t reassoc_rsp_len; + uint32_t reassoc_req_len; if (!evt_buf) { wmi_debug("Empty roam_sync_event param buf"); - status = QDF_STATUS_E_FAILURE; - goto end; + return QDF_STATUS_E_FAILURE; } param_buf = (WMI_ROAM_SYNCH_EVENTID_param_tlvs *)evt_buf; if (!param_buf) { wmi_debug("received null buf from target"); - status = QDF_STATUS_E_FAILURE; - goto end; + return QDF_STATUS_E_FAILURE; } synch_event = param_buf->fixed_param; if (!synch_event) { wmi_debug("received null event data from target"); - status = QDF_STATUS_E_FAILURE; - goto end; + return QDF_STATUS_E_FAILURE; } if (synch_event->vdev_id >= WLAN_MAX_VDEVS) { @@ -1711,9 +2060,121 @@ extract_roam_sync_event_tlv(wmi_unified_t wmi_handle, void *evt_buf, return QDF_STATUS_E_FAILURE; } - *vdev_id = synch_event->vdev_id; + if (synch_event->bcn_probe_rsp_len > + param_buf->num_bcn_probe_rsp_frame || + synch_event->reassoc_req_len > + param_buf->num_reassoc_req_frame || + synch_event->reassoc_rsp_len > + param_buf->num_reassoc_rsp_frame) { + wmi_debug("Invalid sync payload: LEN bcn:%d, req:%d, rsp:%d, vdev:%d", + synch_event->bcn_probe_rsp_len, + synch_event->reassoc_req_len, + synch_event->reassoc_rsp_len, + synch_event->vdev_id); + status = QDF_STATUS_E_FAILURE; + goto abort_roam; + } + + psoc = wmi_handle->soc->wmi_psoc; + vdev = wlan_objmgr_get_vdev_by_id_from_psoc(psoc, synch_event->vdev_id, + WLAN_MLME_SB_ID); + if (!vdev) { + wmi_err("For vdev:%d object is NULL", synch_event->vdev_id); + status = QDF_STATUS_E_FAILURE; + goto abort_roam; + } + + rso_cfg = wlan_cm_get_rso_config(vdev); + if (!rso_cfg) { + status = QDF_STATUS_E_FAILURE; + goto end; + } + + /* + * All below length fields are unsigned and hence positive numbers. + * Maximum number during the addition would be (3 * MAX_LIMIT(UINT32) + + * few fixed fields). + */ + wmi_debug("synch payload: LEN bcn:%d, req:%d, rsp:%d", + synch_event->bcn_probe_rsp_len, + synch_event->reassoc_req_len, + synch_event->reassoc_rsp_len); + + /* + * If lengths of bcn_probe_rsp, reassoc_req and reassoc_rsp are zero in + * synch_event driver would have received bcn_probe_rsp, reassoc_req + * and reassoc_rsp via the event WMI_ROAM_SYNCH_FRAME_EVENTID + */ + if ((!synch_event->bcn_probe_rsp_len) && + (!synch_event->reassoc_req_len) && + (!synch_event->reassoc_rsp_len)) { + bcn_probe_rsp_len = rso_cfg->roam_sync_frame_ind.bcn_probe_rsp_len; + reassoc_req_len = rso_cfg->roam_sync_frame_ind.reassoc_req_len; + reassoc_rsp_len = rso_cfg->roam_sync_frame_ind.reassoc_rsp_len; + + roam_synch_data_len = bcn_probe_rsp_len + reassoc_rsp_len + + reassoc_req_len + sizeof(struct roam_offload_synch_ind); + + wmi_debug("Updated synch payload: LEN bcn:%d, req:%d, rsp:%d", + bcn_probe_rsp_len, + reassoc_req_len, + reassoc_rsp_len); + } else { + bcn_probe_rsp_len = synch_event->bcn_probe_rsp_len; + reassoc_req_len = synch_event->reassoc_req_len; + reassoc_rsp_len = synch_event->reassoc_rsp_len; + + if (synch_event->bcn_probe_rsp_len > WMI_SVC_MSG_MAX_SIZE) { + status = QDF_STATUS_E_FAILURE; + goto end; + } + if (synch_event->reassoc_rsp_len > + (WMI_SVC_MSG_MAX_SIZE - synch_event->bcn_probe_rsp_len)) { + status = QDF_STATUS_E_FAILURE; + goto end; + } + if (synch_event->reassoc_req_len > + WMI_SVC_MSG_MAX_SIZE - (synch_event->bcn_probe_rsp_len + + synch_event->reassoc_rsp_len)) { + status = QDF_STATUS_E_FAILURE; + goto end; + } + roam_synch_data_len = bcn_probe_rsp_len + + reassoc_rsp_len + reassoc_req_len; + + /* + * Below is the check for the entire size of the message + * received from the firmware. + */ + if (roam_synch_data_len > WMI_SVC_MSG_MAX_SIZE - + (sizeof(*synch_event) + sizeof(wmi_channel) + + sizeof(wmi_key_material) + sizeof(uint32_t))) { + status = QDF_STATUS_E_FAILURE; + goto end; + } + roam_synch_data_len += sizeof(struct roam_offload_synch_ind); + } + + roam_sync = qdf_mem_malloc(roam_synch_data_len); + if (!roam_sync) { + QDF_ASSERT(roam_sync); + status = QDF_STATUS_E_NOMEM; + goto end; + } + + *roam_sync_ind = roam_sync; + status = wmi_fill_roam_sync_buffer(vdev, rso_cfg, + roam_sync, param_buf); end: + wlan_objmgr_vdev_release_ref(vdev, WLAN_MLME_SB_ID); +abort_roam: + if (QDF_IS_STATUS_ERROR(status)) { + wmi_err("%d Failed to extract roam sync ind", status); + wlan_cm_fw_roam_abort_req(psoc, synch_event->vdev_id); + wlan_cm_roam_stop_req(psoc, synch_event->vdev_id, + REASON_ROAM_SYNCH_FAILED); + } return status; } @@ -1866,60 +2327,6 @@ static char *wmi_get_roam_event_reason_string(uint32_t reason) return "Invalid"; } -static void -wmi_extract_pdev_hw_mode_trans_ind( - wmi_pdev_hw_mode_transition_event_fixed_param *fixed_param, - wmi_pdev_set_hw_mode_response_vdev_mac_entry *vdev_mac_entry, - struct cm_hw_mode_trans_ind *hw_mode_trans_ind) -{ - uint32_t i; - - if (fixed_param->num_vdev_mac_entries > MAX_VDEV_SUPPORTED) { - wmi_err("Number of Vdev mac entries %d exceeded max vdev supported %d", - fixed_param->num_vdev_mac_entries, - MAX_VDEV_SUPPORTED); - return; - } - hw_mode_trans_ind->old_hw_mode_index = fixed_param->old_hw_mode_index; - hw_mode_trans_ind->new_hw_mode_index = fixed_param->new_hw_mode_index; - hw_mode_trans_ind->num_vdev_mac_entries = - fixed_param->num_vdev_mac_entries; - wmi_debug("old_hw_mode_index:%d new_hw_mode_index:%d entries=%d", - fixed_param->old_hw_mode_index, - fixed_param->new_hw_mode_index, - fixed_param->num_vdev_mac_entries); - - if (!vdev_mac_entry) { - wmi_err("Invalid vdev_mac_entry"); - return; - } - - /* Store the vdev-mac map in WMA and send to policy manager */ - for (i = 0; i < fixed_param->num_vdev_mac_entries; i++) { - uint32_t vdev_id, mac_id, pdev_id; - - vdev_id = vdev_mac_entry[i].vdev_id; - pdev_id = vdev_mac_entry[i].pdev_id; - - if (pdev_id == OL_TXRX_PDEV_ID) { - wmi_err("soc level id received for mac id"); - return; - } - if (vdev_id >= WLAN_MAX_VDEVS) { - wmi_err("vdev_id: %d is invalid, max_bssid: %d", - vdev_id, WLAN_MAX_VDEVS); - return; - } - - mac_id = WMI_PDEV_TO_MAC_MAP(vdev_mac_entry[i].pdev_id); - - hw_mode_trans_ind->vdev_mac_map[i].vdev_id = vdev_id; - hw_mode_trans_ind->vdev_mac_map[i].mac_id = mac_id; - - wmi_debug("vdev_id:%d mac_id:%d", vdev_id, mac_id); - } -} - static enum roam_reason wmi_convert_fw_reason_to_cm_reason(uint32_t reason) { @@ -2302,7 +2709,8 @@ extract_roam_msg_info_tlv(wmi_unified_t wmi_handle, void *evt_buf, #ifdef ROAM_TARGET_IF_CONVERGENCE static inline QDF_STATUS extract_roam_sync_event(wmi_unified_t wmi_handle, void *evt_buf, - struct roam_msg_info *dst, uint8_t idx) + uint32_t len, + struct roam_offload_synch_ind **roam_sync_ind) { return QDF_STATUS_E_NOSUPPORT; } diff --git a/core/mac/inc/sir_api.h b/core/mac/inc/sir_api.h index b8ce0627f3..8486a9aba4 100644 --- a/core/mac/inc/sir_api.h +++ b/core/mac/inc/sir_api.h @@ -123,12 +123,8 @@ typedef uint8_t tSirVersionString[SIR_VERSION_STRING_LEN]; #define SIR_SAP_MAX_NUM_PEERS 32 #endif -#define KCK_192BIT_KEY_LEN 24 -#define KCK_256BIT_KEY_LEN 32 - #define SIR_KEK_KEY_LEN 16 #define SIR_KEK_KEY_LEN_FILS 64 -#define KEK_256BIT_KEY_LEN 32 #define SIR_REPLAY_CTR_LEN 8 #ifdef WLAN_FEATURE_ROAM_OFFLOAD @@ -539,8 +535,7 @@ struct roam_pmkid_req_event; * typedef pe_roam_synch_fn_t - PE roam synch callback routine pointer * @mac_ctx: Global MAC context * @roam_sync_ind_ptr: Structure with roam synch parameters - * @bss_desc_ptr: bss_description pointer for new bss to which the firmware has - * started roaming + * @ie_len: ie length * @reason: Reason for calling the callback * * This type is for callbacks registered with WMA to complete the roam synch @@ -552,7 +547,7 @@ struct roam_pmkid_req_event; typedef QDF_STATUS (*pe_roam_synch_fn_t)(struct mac_context *mac_ctx, struct roam_offload_synch_ind *roam_sync_ind_ptr, - struct bss_description *bss_desc_ptr, + uint16_t ie_len, enum sir_roam_op_code reason); /** diff --git a/core/mac/src/pe/include/lim_api.h b/core/mac/src/pe/include/lim_api.h index abec09358a..6ab00e7493 100644 --- a/core/mac/src/pe/include/lim_api.h +++ b/core/mac/src/pe/include/lim_api.h @@ -280,8 +280,7 @@ tMgmtFrmDropReason lim_is_pkt_candidate_for_drop(struct mac_context *mac, * ROAM SYNCH event is received from firmware * @mac_ctx: global mac context * @roam_sync_ind_ptr: Structure with roam synch parameters - * @bss_desc_ptr: bss_description pointer for new bss to which the firmware has - * started roaming + * @ie_len: ie length * @reason: Operation to be done by the callback * * This is a PE level callback called from WMA to complete the roam synch @@ -293,7 +292,7 @@ tMgmtFrmDropReason lim_is_pkt_candidate_for_drop(struct mac_context *mac, QDF_STATUS pe_roam_synch_callback(struct mac_context *mac_ctx, struct roam_offload_synch_ind *roam_sync_ind_ptr, - struct bss_description *bss_desc_ptr, + uint16_t ie_len, enum sir_roam_op_code reason); void @@ -322,7 +321,7 @@ pe_disconnect_callback(struct mac_context *mac, uint8_t vdev_id, static inline QDF_STATUS pe_roam_synch_callback(struct mac_context *mac_ctx, struct roam_offload_synch_ind *roam_sync_ind_ptr, - struct bss_description *bss_desc_ptr, + uint16_t ie_len, enum sir_roam_op_code reason) { return QDF_STATUS_E_NOSUPPORT; diff --git a/core/mac/src/pe/lim/lim_api.c b/core/mac/src/pe/lim/lim_api.c index 29d663d464..f8efd6f3a4 100644 --- a/core/mac/src/pe/lim/lim_api.c +++ b/core/mac/src/pe/lim/lim_api.c @@ -2510,7 +2510,7 @@ lim_get_assoc_resp_from_roam_sync( QDF_STATUS pe_roam_synch_callback(struct mac_context *mac_ctx, struct roam_offload_synch_ind *roam_sync_ind_ptr, - struct bss_description *bss_desc, + uint16_t ie_len, enum sir_roam_op_code reason) { struct pe_session *session_ptr; @@ -2521,6 +2521,7 @@ pe_roam_synch_callback(struct mac_context *mac_ctx, uint16_t aid; struct bss_params *add_bss_params; QDF_STATUS status = QDF_STATUS_E_FAILURE; + struct bss_description *bss_desc = NULL; uint16_t ric_tspec_len; tpSirAssocRsp assoc_rsp; @@ -2580,9 +2581,18 @@ pe_roam_synch_callback(struct mac_context *mac_ctx, pe_err("LFR3: Not in Link est state"); return status; } + + bss_desc = qdf_mem_malloc(sizeof(struct bss_description) + ie_len); + if (!bss_desc) { + QDF_ASSERT(bss_desc); + status = -QDF_STATUS_E_NOMEM; + return status; + } + status = lim_roam_fill_bss_descr(mac_ctx, roam_sync_ind_ptr, bss_desc); if (!QDF_IS_STATUS_SUCCESS(status)) { pe_err("LFR3:Failed to fill Bss Descr"); + qdf_mem_free(bss_desc); return status; } status = QDF_STATUS_E_FAILURE; @@ -2594,6 +2604,7 @@ pe_roam_synch_callback(struct mac_context *mac_ctx, if (!ft_session_ptr) { pe_err("LFR3:Cannot create PE Session"); lim_print_mac_addr(mac_ctx, bss_desc->bssId, LOGE); + qdf_mem_free(bss_desc); return status; } /* Update the beacon/probe filter in mac_ctx */ @@ -2618,8 +2629,11 @@ pe_roam_synch_callback(struct mac_context *mac_ctx, assoc_rsp); pe_set_rmf_caps(mac_ctx, ft_session_ptr, roam_sync_ind_ptr); /* Next routine may update nss based on dot11Mode */ + lim_ft_prepare_add_bss_req(mac_ctx, ft_session_ptr, bss_desc, assoc_rsp); + qdf_mem_free(bss_desc); + if (session_ptr->is11Rconnection) lim_fill_fils_ft(session_ptr, ft_session_ptr); @@ -2653,7 +2667,6 @@ pe_roam_synch_callback(struct mac_context *mac_ctx, return status; } - if (roam_sync_ind_ptr->auth_status == ROAM_AUTH_STATUS_AUTHENTICATED) { ft_session_ptr->is_key_installed = true; diff --git a/core/wma/inc/wma.h b/core/wma/inc/wma.h index a20faa3e1f..e068e760d0 100644 --- a/core/wma/inc/wma.h +++ b/core/wma/inc/wma.h @@ -992,7 +992,7 @@ typedef struct { struct qdf_mac_addr bssid); QDF_STATUS (*pe_roam_synch_cb)(struct mac_context *mac, struct roam_offload_synch_ind *roam_synch_data, - struct bss_description *bss_desc_ptr, + uint16_t ie_len, enum sir_roam_op_code reason); QDF_STATUS (*pe_disconnect_cb) (struct mac_context *mac, uint8_t vdev_id, diff --git a/core/wma/inc/wma_api.h b/core/wma/inc/wma_api.h index c6e1f676bb..b0b14b660c 100644 --- a/core/wma/inc/wma_api.h +++ b/core/wma/inc/wma_api.h @@ -566,6 +566,7 @@ bool wma_get_channel_switch_in_progress(struct wma_txrx_node *iface); QDF_STATUS wma_sta_mlme_vdev_start_continue(struct vdev_mlme_obj *vdev_mlme, uint16_t data_len, void *data); +#ifndef ROAM_TARGET_IF_CONVERGENCE /** * wma_sta_mlme_vdev_roam_notify() - VDEV roam notify handling * @vdev_mlme_obj: VDEV MLME comp object @@ -579,7 +580,7 @@ QDF_STATUS wma_sta_mlme_vdev_start_continue(struct vdev_mlme_obj *vdev_mlme, */ QDF_STATUS wma_sta_mlme_vdev_roam_notify(struct vdev_mlme_obj *vdev_mlme, uint16_t data_len, void *data); - +#endif /** * wma_ap_mlme_vdev_start_continue() - VDEV start response handling * @vdev_mlme_obj: VDEV MLME comp object diff --git a/core/wma/inc/wma_internal.h b/core/wma/inc/wma_internal.h index 2d9e43f2c2..7d3676dbbf 100644 --- a/core/wma/inc/wma_internal.h +++ b/core/wma/inc/wma_internal.h @@ -247,7 +247,7 @@ int wma_roam_auth_offload_event_handler(WMA_HANDLE handle, uint8_t *event, */ int wma_roam_stats_event_handler(WMA_HANDLE handle, uint8_t *event, uint32_t len); - +#ifndef ROAM_TARGET_IF_CONVERGENCE /** * wma_mlme_roam_synch_event_handler_cb() - roam synch event handler * @handle: wma handle @@ -262,7 +262,6 @@ int wma_roam_stats_event_handler(WMA_HANDLE handle, uint8_t *event, int wma_mlme_roam_synch_event_handler_cb(void *handle, uint8_t *event, uint32_t len); -#ifndef ROAM_TARGET_IF_CONVERGENCE /** * wma_roam_synch_frame_event_handler() - roam synch frame event handler * @handle: wma handle diff --git a/core/wma/src/wma_scan_roam.c b/core/wma/src/wma_scan_roam.c index 50d3fa0818..4041f77021 100644 --- a/core/wma/src/wma_scan_roam.c +++ b/core/wma/src/wma_scan_roam.c @@ -86,7 +86,7 @@ #include "host_diag_core_log.h" #endif /* FEATURE_WLAN_DIAG_SUPPORT */ #include <../../core/src/wlan_cm_roam_i.h> - +#include "wlan_cm_roam_api.h" #ifdef FEATURE_WLAN_EXTSCAN #define WMA_EXTSCAN_CYCLE_WAKE_LOCK_DURATION WAKELOCK_DURATION_RECOMMENDED @@ -543,6 +543,7 @@ wma_send_roam_preauth_status(tp_wma_handle wma_handle, #endif #ifdef WLAN_FEATURE_ROAM_OFFLOAD +#ifndef ROAM_TARGET_IF_CONVERGENCE /** * wma_free_roam_synch_frame_ind() - Free the bcn_probe_rsp, reassoc_req, * reassoc_rsp received as part of the ROAM_SYNC_FRAME event @@ -739,7 +740,7 @@ static int wma_fill_roam_synch_buffer(tp_wma_handle wma, if (!QDF_IS_STATUS_SUCCESS( cm_fw_roam_sync_start_ind(iface->vdev, - roam_synch_ind_ptr))) + roam_synch_ind_ptr->roam_reason))) { wma_err("LFR3: CSR Roam synch cb failed"); wma_free_roam_synch_frame_ind(iface); @@ -883,7 +884,7 @@ static int wma_fill_roam_synch_buffer(tp_wma_handle wma, wma_free_roam_synch_frame_ind(iface); return 0; } - +#endif /* ROAM_TARGET_IF_CONVERGENCE */ /** * wma_roam_update_vdev() - Update the STA and BSS * @wma: Global WMA Handle @@ -1005,6 +1006,7 @@ static void wma_update_phymode_on_roam(tp_wma_handle wma, uint8_t *bssid, des_chan->ch_cfreq1, des_chan->ch_cfreq2); } +#ifndef ROAM_TARGET_IF_CONVERGENCE int wma_mlme_roam_synch_event_handler_cb(void *handle, uint8_t *event, uint32_t len) { @@ -1012,7 +1014,6 @@ int wma_mlme_roam_synch_event_handler_cb(void *handle, uint8_t *event, wmi_roam_synch_event_fixed_param *synch_event = NULL; tp_wma_handle wma = (tp_wma_handle) handle; struct roam_offload_synch_ind *roam_synch_ind_ptr = NULL; - struct bss_description *bss_desc_ptr = NULL; uint16_t ie_len = 0; int status = -EINVAL; qdf_time_t roam_synch_received = qdf_get_system_timestamp(); @@ -1159,15 +1160,8 @@ int wma_mlme_roam_synch_event_handler_cb(void *handle, uint8_t *event, wma_err("LFR3: Invalid Beacon Length"); goto cleanup_label; } - bss_desc_ptr = qdf_mem_malloc(sizeof(struct bss_description) + ie_len); - if (!bss_desc_ptr) { - QDF_ASSERT(bss_desc_ptr); - status = -ENOMEM; - goto cleanup_label; - } - qdf_mem_zero(bss_desc_ptr, sizeof(struct bss_description) + ie_len); if (QDF_IS_STATUS_ERROR(wma->pe_roam_synch_cb(wma->mac_context, - roam_synch_ind_ptr, bss_desc_ptr, + roam_synch_ind_ptr, ie_len, SIR_ROAM_SYNCH_PROPAGATION))) { wma_err("LFR3: PE roam synch cb failed"); status = -EBUSY; @@ -1214,13 +1208,10 @@ cleanup_label: qdf_mem_free(roam_synch_ind_ptr->ric_tspec_data); if (roam_synch_ind_ptr) qdf_mem_free(roam_synch_ind_ptr); - if (bss_desc_ptr) - qdf_mem_free(bss_desc_ptr); return status; } -#ifndef ROAM_TARGET_IF_CONVERGENCE int wma_roam_synch_frame_event_handler(void *handle, uint8_t *event, uint32_t len) { @@ -4140,7 +4131,7 @@ static void wma_invalid_roam_reason_handler(tp_wma_handle wma_handle, roam_synch_data->roamed_vdev_id = vdev_id; if (notif != CM_ROAM_NOTIF_ROAM_START) wma_handle->pe_roam_synch_cb(wma_handle->mac_context, - roam_synch_data, NULL, op_code); + roam_synch_data, 0, op_code); if (notif == CM_ROAM_NOTIF_ROAM_START) cm_fw_roam_start_req(wma_handle->psoc, vdev_id); @@ -4933,3 +4924,42 @@ int wma_roam_pmkid_request_event_handler(void *handle, uint8_t *event, return 0; } #endif + +#ifdef WLAN_FEATURE_ROAM_OFFLOAD +#ifdef ROAM_TARGET_IF_CONVERGENCE +void cm_roam_update_vdev(struct roam_offload_synch_ind *sync_ind) +{ + tp_wma_handle wma = cds_get_context(QDF_MODULE_ID_WMA); + + wma_roam_update_vdev(wma, sync_ind); +} + +QDF_STATUS +cm_roam_pe_sync_callback(struct roam_offload_synch_ind *sync_ind, + uint16_t ie_len) +{ + tp_wma_handle wma = cds_get_context(QDF_MODULE_ID_WMA); + QDF_STATUS status; + + status = wma->pe_roam_synch_cb(wma->mac_context, + sync_ind, ie_len, + SIR_ROAM_SYNCH_PROPAGATION); + + return status; +} + +void cm_update_phymode_on_roam(uint8_t vdev_id, uint8_t *bssid, + wmi_channel *chan) +{ + tp_wma_handle wma = cds_get_context(QDF_MODULE_ID_WMA); + + wma_update_phymode_on_roam(wma, bssid, chan, &wma->interfaces[vdev_id]); +} + +enum wlan_phymode +wlan_cm_fw_to_host_phymode(WMI_HOST_WLAN_PHY_MODE phymode) +{ + return wma_fw_to_host_phymode(phymode); +} +#endif /* ROAM_TARGET_IF_CONVERGENCE */ +#endif diff --git a/core/wma/src/wma_utils.c b/core/wma/src/wma_utils.c index 5eeb96e265..04392b38b4 100644 --- a/core/wma/src/wma_utils.c +++ b/core/wma/src/wma_utils.c @@ -4285,6 +4285,7 @@ QDF_STATUS wma_sta_mlme_vdev_start_continue(struct vdev_mlme_obj *vdev_mlme, return QDF_STATUS_SUCCESS; } +#ifndef ROAM_TARGET_IF_CONVERGENCE QDF_STATUS wma_sta_mlme_vdev_roam_notify(struct vdev_mlme_obj *vdev_mlme, uint16_t data_len, void *data) { @@ -4304,6 +4305,7 @@ QDF_STATUS wma_sta_mlme_vdev_roam_notify(struct vdev_mlme_obj *vdev_mlme, return status; } +#endif QDF_STATUS wma_ap_mlme_vdev_start_continue(struct vdev_mlme_obj *vdev_mlme, uint16_t data_len, void *data)