diff --git a/components/umac/mlme/connection_mgr/core/src/wlan_cm_roam_offload.c b/components/umac/mlme/connection_mgr/core/src/wlan_cm_roam_offload.c index 91fbe4865f..8e03910fde 100644 --- a/components/umac/mlme/connection_mgr/core/src/wlan_cm_roam_offload.c +++ b/components/umac/mlme/connection_mgr/core/src/wlan_cm_roam_offload.c @@ -5343,8 +5343,14 @@ void cm_roam_result_info_event(struct wmi_roam_result *res, { struct wlan_log_record *log_record = NULL; uint8_t i; + bool ap_found_in_roam_scan = false; bool roam_abort = (res->fail_reason == ROAM_FAIL_REASON_SYNC || - res->fail_reason == ROAM_FAIL_REASON_INTERNAL_ABORT); + res->fail_reason == ROAM_FAIL_REASON_DISCONNECT || + res->fail_reason == ROAM_FAIL_REASON_HOST || + res->fail_reason == + ROAM_FAIL_REASON_INTERNAL_ABORT || + res->fail_reason == + ROAM_FAIL_REASON_UNABLE_TO_START_ROAM_HO); log_record = qdf_mem_malloc(sizeof(*log_record)); if (!log_record) @@ -5352,33 +5358,65 @@ void cm_roam_result_info_event(struct wmi_roam_result *res, log_record->vdev_id = vdev_id; log_record->timestamp_us = qdf_get_time_of_the_day_us(); - if (roam_abort) { - log_record->log_subtype = WLAN_ROAM_CANCEL; - log_record->fw_timestamp_us = log_record->timestamp_us; - log_record->roam_result.roam_fail_reason = res->fail_reason; - } else { - log_record->log_subtype = WLAN_ROAM_RESULT; - log_record->fw_timestamp_us = (uint64_t)res->timestamp * 1000; - log_record->roam_result.roam_fail_reason = res->fail_reason; - log_record->roam_result.is_roam_successful = (res->status == 0); - for (i = 0; i < scan_data->num_ap; i++) { - if (i >= MAX_ROAM_CANDIDATE_AP) - break; + log_record->fw_timestamp_us = (uint64_t)res->timestamp * 1000; - if (scan_data->ap[i].type == WLAN_ROAM_SCAN_ROAMED_AP && - log_record->roam_result.is_roam_successful) { - log_record->bssid = scan_data->ap[i].bssid; - break; - } else if (scan_data->ap[i].type == - WLAN_ROAM_SCAN_CURRENT_AP && - !log_record->roam_result.is_roam_successful) { - log_record->bssid = scan_data->ap[i].bssid; - break; - } + for (i = 0; i < scan_data->num_ap && scan_data->present; i++) { + if (i >= MAX_ROAM_CANDIDATE_AP) + break; + + if (scan_data->ap[i].type == WLAN_ROAM_SCAN_ROAMED_AP || + scan_data->ap[i].type == WLAN_ROAM_SCAN_CANDIDATE_AP) { + ap_found_in_roam_scan = true; + break; + } + } + + log_record->log_subtype = WLAN_ROAM_RESULT; + log_record->roam_result.roam_fail_reason = res->fail_reason; + /* + * Print ROAM if: + * 1. Roaming is successful to AP + * 2. Atleast one candidate AP found during scan + * + * Print NO_ROAM only if: + * 1. No candidate AP found(eventhough other APs are found in scan) + */ + log_record->roam_result.is_roam_successful = + (res->status == 0) || + (ap_found_in_roam_scan && + res->fail_reason != ROAM_FAIL_REASON_NO_CAND_AP_FOUND); + + for (i = 0; i < scan_data->num_ap; i++) { + if (i >= MAX_ROAM_CANDIDATE_AP) + break; + + if (scan_data->ap[i].type == WLAN_ROAM_SCAN_ROAMED_AP && + log_record->roam_result.is_roam_successful) { + log_record->bssid = scan_data->ap[i].bssid; + break; + } else if (scan_data->ap[i].type == + WLAN_ROAM_SCAN_CURRENT_AP && + !log_record->roam_result.is_roam_successful) { + log_record->bssid = scan_data->ap[i].bssid; + break; } } wlan_connectivity_log_enqueue(log_record); + qdf_mem_zero(log_record, sizeof(*log_record)); + + if (roam_abort) { + log_record->vdev_id = vdev_id; + log_record->timestamp_us = qdf_get_time_of_the_day_us(); + log_record->fw_timestamp_us = (uint64_t)res->timestamp * 1000; + + log_record->log_subtype = WLAN_ROAM_CANCEL; + log_record->fw_timestamp_us = log_record->timestamp_us; + log_record->roam_result.roam_fail_reason = res->fail_reason; + + wlan_connectivity_log_enqueue(log_record); + } + qdf_mem_free(log_record); } #endif /* WLAN_FEATURE_CONNECTIVITY_LOGGING */ @@ -5825,10 +5863,12 @@ cm_roam_btm_req_event(struct wmi_roam_btm_trigger_data *btm_data, } QDF_STATUS -cm_roam_mgmt_frame_event(struct roam_frame_info *frame_data, uint8_t vdev_id) +cm_roam_mgmt_frame_event(struct roam_frame_info *frame_data, + struct wmi_roam_scan_data *scan_data, uint8_t vdev_id) { struct wlan_log_record *log_record = NULL; QDF_STATUS status = QDF_STATUS_SUCCESS; + uint8_t i; log_record = qdf_mem_malloc(sizeof(*log_record)); if (!log_record) @@ -5843,12 +5883,26 @@ cm_roam_mgmt_frame_event(struct roam_frame_info *frame_data, uint8_t vdev_id) log_record->pkt_info.tx_status = frame_data->tx_status; log_record->pkt_info.frame_status_code = frame_data->status_code; + if (scan_data->present) { + for (i = 0; i < scan_data->num_ap; i++) { + if (i >= MAX_ROAM_CANDIDATE_AP) + break; + + if (scan_data->ap[i].type == WLAN_ROAM_SCAN_ROAMED_AP) { + log_record->pkt_info.rssi = + (-1) * scan_data->ap[i].rssi; + log_record->bssid = scan_data->ap[i].bssid; + break; + } + } + } + if (frame_data->type == ROAM_FRAME_INFO_FRAME_TYPE_EXT) log_record->log_subtype = cm_roam_get_eapol_tag(frame_data->subtype); else log_record->log_subtype = cm_roam_get_tag(frame_data->subtype, - frame_data->is_req); + !frame_data->is_rsp); status = wlan_connectivity_log_enqueue(log_record); qdf_mem_free(log_record); diff --git a/components/umac/mlme/connection_mgr/core/src/wlan_cm_roam_offload.h b/components/umac/mlme/connection_mgr/core/src/wlan_cm_roam_offload.h index b9faabcb5e..f1fe2bbf15 100644 --- a/components/umac/mlme/connection_mgr/core/src/wlan_cm_roam_offload.h +++ b/components/umac/mlme/connection_mgr/core/src/wlan_cm_roam_offload.h @@ -393,12 +393,14 @@ cm_handle_mlo_rso_state_change(struct wlan_objmgr_pdev *pdev, /** * cm_roam_mgmt_frame_event() - Roam management frame event * @frame_data: frame_data + * @scan_data: Roam scan data * @vdev_id: vdev_id * * Return: QDF_STATUS */ QDF_STATUS -cm_roam_mgmt_frame_event(struct roam_frame_info *frame_data, uint8_t vdev_id); +cm_roam_mgmt_frame_event(struct roam_frame_info *frame_data, + struct wmi_roam_scan_data *scan_data, uint8_t vdev_id); /** * cm_roam_btm_req_event - Send BTM request related logging event @@ -450,7 +452,8 @@ cm_roam_beacon_loss_disconnect_event(struct qdf_mac_addr bssid, int32_t rssi, uint8_t vdev_id); #else static inline QDF_STATUS -cm_roam_mgmt_frame_event(struct roam_frame_info *frame_data, uint8_t vdev_id) +cm_roam_mgmt_frame_event(struct roam_frame_info *frame_data, + struct wmi_roam_scan_data *scan_data, uint8_t vdev_id) { return QDF_STATUS_E_NOSUPPORT; } 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 f2783799fd..f3f6e1bb5e 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 @@ -715,47 +715,6 @@ static inline QDF_STATUS wlan_cm_host_roam_start(struct scheduler_msg *msg) 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 - * @evt_buf: Pointer to the event buffer - * @dst: Pointer to destination structure to fill data - * @idx: TLV id - * - * Return: QDF_STATUS - */ -QDF_STATUS -wlan_cm_roam_extract_btm_response(wmi_unified_t wmi, void *evt_buf, - struct roam_btm_response_data *dst, - uint8_t idx); - -/** - * wlan_cm_roam_extract_roam_initial_info() - Extract Roam Initial stats - * @wmi: wmi handle - * @evt_buf: Pointer to the event buffer - * @dst: Pointer to destination structure to fill data - * @idx: TLV id - * - * Return: QDF_STATUS - */ -QDF_STATUS -wlan_cm_roam_extract_roam_initial_info(wmi_unified_t wmi, void *evt_buf, - struct roam_initial_data *dst, - uint8_t idx); - -/** - * wlan_cm_roam_extract_roam_msg_info() - Extract Roam msg stats - * @wmi: wmi handle - * @evt_buf: Pointer to the event buffer - * @dst: Pointer to destination structure to fill data - * @idx: TLV id - * - * Return: QDF_STATUS - */ -QDF_STATUS -wlan_cm_roam_extract_roam_msg_info(wmi_unified_t wmi, void *evt_buf, - struct roam_msg_info *dst, uint8_t idx); - /** * wlan_cm_get_roam_band_value - Get roam band value from RSO config * @psoc: psoc pointer @@ -766,21 +725,6 @@ wlan_cm_roam_extract_roam_msg_info(wmi_unified_t wmi, void *evt_buf, uint32_t wlan_cm_get_roam_band_value(struct wlan_objmgr_psoc *psoc, struct wlan_objmgr_vdev *vdev); -/** - * wlan_cm_roam_extract_frame_info - Extract the roam frame info TLV - * @wmi: wmi handle - * @evt_buf: Pointer to the event buffer - * @dst: Destination buffer - * @idx: TLV index - * @num_frames: Number of frame info TLVs - * - * Return: QDF_STATUS - */ -QDF_STATUS -wlan_cm_roam_extract_frame_info(wmi_unified_t wmi, void *evt_buf, - struct roam_frame_info *dst, uint8_t idx, - uint8_t num_frames); - /** * wlan_cm_roam_activate_pcl_per_vdev() - Set the PCL command to be sent per * vdev instead of pdev. 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 25c7639614..f0da46724f 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 @@ -1894,7 +1894,7 @@ enum roam_rt_stats_type { * @timestamp: Fw timestamp at which the frame was Tx/Rx'ed * @type: Frame Type * @subtype: Frame subtype - * @is_req: Frame is request frame or response frame + * @is_rsp: True if frame is response frame else false * @seq_num: Frame sequence number from the 802.11 header * @status_code: Status code from 802.11 spec, section 9.4.1.9 * @tx_status: Frame TX status defined by enum qdf_dp_tx_rx_status @@ -1907,7 +1907,7 @@ struct roam_frame_info { uint32_t timestamp; uint8_t type; uint8_t subtype; - uint8_t is_req; + uint8_t is_rsp; enum qdf_dp_tx_rx_status tx_status; uint16_t seq_num; uint16_t status_code; @@ -2158,6 +2158,16 @@ struct roam_offload_roam_event { bool rso_timer_stopped; }; +/** + * struct roam_frame_stats - Roam frame stats + * @num_frame: number of frames + * @frame_info: Roam frame info + */ +struct roam_frame_stats { + uint8_t num_frame; + struct roam_frame_info frame_info[WLAN_ROAM_MAX_FRAME_INFO]; +}; + /** * struct roam_stats_event - Data carried by stats event * @vdev_id: vdev id @@ -2166,6 +2176,7 @@ struct roam_offload_roam_event { * @trigger: Roam trigger related details * @scan: Roam scan event details * @result: Roam result related info + * @frame_stats: Info on frame exchange during roaming * @data_11kv: Neighbor report/BTM request related data * @btm_rsp: BTM response related data * @roam_init_info: Roam initial related data @@ -2179,6 +2190,7 @@ struct roam_stats_event { struct wmi_roam_trigger_info trigger[MAX_ROAM_SCAN_STATS_TLV]; struct wmi_roam_scan_data scan[MAX_ROAM_SCAN_STATS_TLV]; struct wmi_roam_result result[MAX_ROAM_SCAN_STATS_TLV]; + struct roam_frame_stats frame_stats[MAX_ROAM_SCAN_STATS_TLV]; struct wmi_neighbor_report_data data_11kv[MAX_ROAM_SCAN_STATS_TLV]; struct roam_btm_response_data btm_rsp[MAX_ROAM_SCAN_STATS_TLV]; struct roam_initial_data roam_init_info[MAX_ROAM_SCAN_STATS_TLV]; 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 9fd147fe09..160842ea7f 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 @@ -322,40 +322,6 @@ 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, - uint8_t idx) -{ - if (wmi->ops->extract_roam_btm_response_stats) - return wmi->ops->extract_roam_btm_response_stats(wmi, evt_buf, - dst, idx); - - return QDF_STATUS_E_FAILURE; -} - -QDF_STATUS -wlan_cm_roam_extract_roam_initial_info(wmi_unified_t wmi, void *evt_buf, - struct roam_initial_data *dst, - uint8_t idx) -{ - if (wmi->ops->extract_roam_initial_info) - return wmi->ops->extract_roam_initial_info(wmi, evt_buf, - dst, idx); - - return QDF_STATUS_E_FAILURE; -} - -QDF_STATUS -wlan_cm_roam_extract_roam_msg_info(wmi_unified_t wmi, void *evt_buf, - struct roam_msg_info *dst, uint8_t idx) -{ - if (wmi->ops->extract_roam_msg_info) - return wmi->ops->extract_roam_msg_info(wmi, evt_buf, dst, idx); - - return QDF_STATUS_E_FAILURE; -} - uint32_t wlan_cm_get_roam_band_value(struct wlan_objmgr_psoc *psoc, struct wlan_objmgr_vdev *vdev) { @@ -370,18 +336,6 @@ uint32_t wlan_cm_get_roam_band_value(struct wlan_objmgr_psoc *psoc, return band_mask; } -QDF_STATUS -wlan_cm_roam_extract_frame_info(wmi_unified_t wmi, void *evt_buf, - struct roam_frame_info *dst, uint8_t idx, - uint8_t num_frames) -{ - if (wmi->ops->extract_roam_msg_info) - return wmi->ops->extract_roam_frame_info(wmi, evt_buf, - dst, idx, num_frames); - - return QDF_STATUS_E_FAILURE; -} - void wlan_cm_roam_activate_pcl_per_vdev(struct wlan_objmgr_psoc *psoc, uint8_t vdev_id, bool pcl_per_vdev) { @@ -3062,6 +3016,61 @@ cm_roam_stats_print_11kv_info(struct wmi_neighbor_report_data *neigh_rpt, qdf_mem_free(buf); } +static char * +cm_get_frame_subtype_str(enum mgmt_subtype frame_subtype) +{ + switch (frame_subtype) { + case MGMT_SUBTYPE_ASSOC_REQ: + return "ASSOC"; + case MGMT_SUBTYPE_ASSOC_RESP: + return "ASSOC"; + case MGMT_SUBTYPE_REASSOC_REQ: + return "REASSOC"; + case MGMT_SUBTYPE_REASSOC_RESP: + return "REASSOC"; + case MGMT_SUBTYPE_DISASSOC: + return "DISASSOC"; + case MGMT_SUBTYPE_AUTH: + return "AUTH"; + case MGMT_SUBTYPE_DEAUTH: + return "DEAUTH"; + default: + break; + } + + return "Invalid frm"; +} + +static void +cm_roam_print_frame_info(struct roam_frame_stats *frame_data, + struct wmi_roam_scan_data *scan_data, uint8_t vdev_id) +{ + struct roam_frame_info *frame_info; + char time[TIME_STRING_LEN]; + uint8_t i; + + if (!frame_data->num_frame) + return; + + for (i = 0; i < frame_data->num_frame; i++) { + frame_info = &frame_data->frame_info[i]; + qdf_mem_zero(time, TIME_STRING_LEN); + mlme_get_converted_timestamp(frame_info->timestamp, time); + + if (frame_info->type != ROAM_FRAME_INFO_FRAME_TYPE_EXT) + mlme_nofl_info("%s [%s%s] VDEV[%d] status:%d seq_num:%d", + time, + cm_get_frame_subtype_str(frame_info->subtype), + frame_info->subtype == MGMT_SUBTYPE_AUTH ? + (frame_info->is_rsp ? " RX" : " TX") : "", + vdev_id, + frame_info->status_code, + frame_info->seq_num); + + cm_roam_mgmt_frame_event(frame_info, scan_data, vdev_id); + } +} + void cm_report_roam_rt_stats(struct wlan_objmgr_psoc *psoc, uint8_t vdev_id, enum roam_rt_stats_type events, @@ -3172,6 +3181,11 @@ cm_roam_stats_event_handler(struct wlan_objmgr_psoc *psoc, goto err; } + if (stats_info->frame_stats[i].num_frame) + cm_roam_print_frame_info(&stats_info->frame_stats[i], + &stats_info->scan[i], + stats_info->vdev_id); + if (stats_info->data_11kv[i].present) cm_roam_stats_print_11kv_info(&stats_info->data_11kv[i], stats_info->vdev_id); diff --git a/components/wmi/inc/wmi_unified_roam_api.h b/components/wmi/inc/wmi_unified_roam_api.h index da83a1d774..2a6459a30e 100644 --- a/components/wmi/inc/wmi_unified_roam_api.h +++ b/components/wmi/inc/wmi_unified_roam_api.h @@ -382,6 +382,22 @@ wmi_extract_roam_stats_event(wmi_unified_t wmi_handle, uint8_t *event, uint32_t data_len, struct roam_stats_event **stats_info); +/** + * wmi_unified_extract_roam_extract_frame_info() - Extract the roam frame + * info TLV from roam stats event + * @wmi: wmi handle + * @evt_buf: Pointer to the event buffer + * @dst: Pointer to destination structure to fill data + * @idx: Index of the TLV to read + * @num_frames: Number of TLV to read + * + * Return: QDF_STATUS + */ +QDF_STATUS +wmi_unified_extract_roam_extract_frame_info(wmi_unified_t wmi, void *evt_buf, + struct roam_frame_stats *dst, + uint8_t idx, uint8_t num_frames); + /** * wmi_extract_auth_offload_event - Extract auth offload event * @wmi_handle: WMI handle diff --git a/components/wmi/src/wmi_unified_roam_api.c b/components/wmi/src/wmi_unified_roam_api.c index 555e2ac671..4f081dd856 100644 --- a/components/wmi/src/wmi_unified_roam_api.c +++ b/components/wmi/src/wmi_unified_roam_api.c @@ -449,6 +449,18 @@ wmi_unified_extract_roam_msg_info(wmi_unified_t wmi, void *evt_buf, return QDF_STATUS_E_FAILURE; } +QDF_STATUS +wmi_unified_extract_roam_extract_frame_info(wmi_unified_t wmi, void *evt_buf, + struct roam_frame_stats *dst, + uint8_t idx, uint8_t num_frames) +{ + if (wmi->ops->extract_roam_frame_info) + return wmi->ops->extract_roam_frame_info(wmi, evt_buf, + dst, idx, num_frames); + + return QDF_STATUS_E_FAILURE; +} + QDF_STATUS wmi_extract_roam_stats_event(wmi_unified_t wmi_handle, uint8_t *event, uint32_t data_len, diff --git a/components/wmi/src/wmi_unified_roam_tlv.c b/components/wmi/src/wmi_unified_roam_tlv.c index da9c33f29c..aca865fe80 100644 --- a/components/wmi/src/wmi_unified_roam_tlv.c +++ b/components/wmi/src/wmi_unified_roam_tlv.c @@ -1745,6 +1745,7 @@ wmi_get_converted_tx_status( return QDF_TX_RX_STATUS_INVALID; } +#define WLAN_FC0_SUBTYPE_SHIFT 4 /** * extract_roam_frame_info_tlv() - Extract the frame exchanges during roaming * info from the WMI_ROAM_STATS_EVENTID @@ -1756,18 +1757,19 @@ wmi_get_converted_tx_status( */ static QDF_STATUS extract_roam_frame_info_tlv(wmi_unified_t wmi_handle, void *evt_buf, - struct roam_frame_info *dst, uint8_t frame_idx, + struct roam_frame_stats *dst, uint8_t frame_idx, uint8_t num_frames) { WMI_ROAM_STATS_EVENTID_param_tlvs *param_buf; wmi_roam_frame_info *src_data = NULL; + struct roam_frame_info *dst_buf; uint8_t i, subtype; param_buf = (WMI_ROAM_STATS_EVENTID_param_tlvs *)evt_buf; if (!param_buf || !param_buf->roam_frame_info || !param_buf->num_roam_frame_info || - (frame_idx + num_frames) >= param_buf->num_roam_frame_info) { + (frame_idx + num_frames) > param_buf->num_roam_frame_info) { wmi_debug("Empty roam_frame_info param buf frame_idx:%d num_frames:%d", frame_idx, num_frames); return QDF_STATUS_SUCCESS; @@ -1778,31 +1780,35 @@ extract_roam_frame_info_tlv(wmi_unified_t wmi_handle, void *evt_buf, if (num_frames > WLAN_ROAM_MAX_FRAME_INFO) num_frames = WLAN_ROAM_MAX_FRAME_INFO; + dst->num_frame = num_frames; + dst_buf = dst->frame_info; for (i = 0; i < num_frames; i++) { - dst->present = true; - dst->timestamp = src_data->timestamp; - dst->type = WMI_GET_BITS(src_data->frame_info, 0, 2); + dst_buf->timestamp = src_data->timestamp; + dst_buf->type = WMI_GET_BITS(src_data->frame_info, 0, 2); subtype = WMI_GET_BITS(src_data->frame_info, 2, 4); - if (dst->type == WMI_ROAM_FRAME_INFO_FRAME_TYPE_EXT) { - dst->type = ROAM_FRAME_INFO_FRAME_TYPE_EXT; - dst->subtype = + if (dst_buf->type == WMI_ROAM_FRAME_INFO_FRAME_TYPE_EXT) { + dst_buf->type = ROAM_FRAME_INFO_FRAME_TYPE_EXT; + dst_buf->subtype = wmi_get_converted_roam_eapol_subtype(subtype); } else { - dst->subtype = subtype; + dst_buf->subtype = subtype << WLAN_FC0_SUBTYPE_SHIFT; } - dst->is_req = WMI_GET_BITS(src_data->frame_info, 6, 1); - dst->seq_num = WMI_GET_BITS(src_data->frame_info, 7, 16); - dst->status_code = src_data->status_code; - if (dst->is_req) - dst->tx_status = wmi_get_converted_tx_status( + dst_buf->is_rsp = WMI_GET_BITS(src_data->frame_info, 6, 1); + dst_buf->is_rsp &= + (dst_buf->type != WMI_ROAM_FRAME_INFO_FRAME_TYPE_EXT && + dst_buf->subtype == MGMT_SUBTYPE_AUTH); + dst_buf->seq_num = WMI_GET_BITS(src_data->frame_info, 7, 16); + dst_buf->status_code = src_data->status_code; + if (!dst_buf->is_rsp) + dst_buf->tx_status = wmi_get_converted_tx_status( src_data->status_code); - dst->retry_count = src_data->retry_count; - dst->rssi = (-1) * src_data->rssi_dbm_abs; + dst_buf->retry_count = src_data->retry_count; + dst_buf->rssi = (-1) * src_data->rssi_dbm_abs; - dst++; + dst_buf++; src_data++; } @@ -2922,7 +2928,7 @@ extract_roam_stats_event_tlv(wmi_unified_t wmi_handle, uint8_t *evt_buf, wmi_roam_stats_event_fixed_param *fixed_param; struct roam_stats_event *stats_info; struct roam_msg_info *roam_msg_info = NULL; - uint8_t vdev_id, i, num_btm = 0; + uint8_t vdev_id, i, num_btm = 0, num_frames = 0; uint8_t num_tlv = 0, num_chan = 0, num_ap = 0, num_rpt = 0; uint32_t rem_len; QDF_STATUS status; @@ -3025,6 +3031,14 @@ extract_roam_stats_event_tlv(wmi_unified_t wmi_handle, uint8_t *evt_buf, wmi_err_rl("Invalid roam msg info"); return QDF_STATUS_E_INVAL; } + + rem_len -= param_buf->num_roam_msg_info * sizeof(wmi_roam_msg_info); + if (rem_len < + param_buf->num_roam_frame_info * sizeof(wmi_roam_frame_info)) { + wmi_err_rl("Invalid roam frame info"); + return QDF_STATUS_E_INVAL; + } + stats_info = qdf_mem_malloc(sizeof(struct roam_stats_event)); if (!stats_info) { status = QDF_STATUS_E_NOMEM; @@ -3073,6 +3087,7 @@ extract_roam_stats_event_tlv(wmi_unified_t wmi_handle, uint8_t *evt_buf, } num_chan += stats_info->scan[i].num_chan; num_ap += stats_info->scan[i].num_ap; + num_frames = stats_info->scan[i].frame_info_count; /* Roam result - Success/Failure status, failure reason */ status = wmi_unified_extract_roam_result_stats(wmi_handle, @@ -3085,6 +3100,19 @@ extract_roam_stats_event_tlv(wmi_unified_t wmi_handle, uint8_t *evt_buf, goto err; } + if (num_frames) { + status = wmi_unified_extract_roam_extract_frame_info( + wmi_handle, evt_buf, + &stats_info->frame_stats[i], i, + num_frames); + if (QDF_IS_STATUS_ERROR(status)) { + wmi_debug_rl("Roam frame stats extract failed vdev %d at %d iteration", + vdev_id, i); + status = QDF_STATUS_E_INVAL; + goto err; + } + } + /* BTM req/resp or Neighbor report/response info */ status = wmi_unified_extract_roam_11kv_stats( wmi_handle,