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 fce583bd5a..aff0f7b4e0 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 @@ -181,6 +181,11 @@ target_if_free_roam_synch_frame_ind(struct roam_synch_frame_ind *frame_ind) frame_ind->bcn_probe_rsp_len = 0; frame_ind->bcn_probe_rsp = NULL; } + if (frame_ind->link_bcn_probe_rsp) { + qdf_mem_free(frame_ind->link_bcn_probe_rsp); + frame_ind->link_bcn_probe_rsp_len = 0; + frame_ind->link_bcn_probe_rsp = NULL; + } if (frame_ind->reassoc_req) { qdf_mem_free(frame_ind->reassoc_req); frame_ind->reassoc_req_len = 0; 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 ed0c70eeff..612a6ba43e 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 @@ -298,6 +298,22 @@ cm_populate_connect_ies(struct roam_offload_synch_ind *roam_synch_data, connect_ies->bcn_probe_rsp.len); } + /* Beacon/Probe Rsp frame */ + if (roam_synch_data->link_beacon_probe_resp_length) { + connect_ies->link_bcn_probe_rsp.len = + roam_synch_data->link_beacon_probe_resp_length; + bcn_probe_rsp_ptr = (uint8_t *)roam_synch_data + + roam_synch_data->link_beacon_probe_resp_offset; + + connect_ies->link_bcn_probe_rsp.ptr = + qdf_mem_malloc(connect_ies->link_bcn_probe_rsp.len); + if (!connect_ies->link_bcn_probe_rsp.ptr) + return QDF_STATUS_E_NOMEM; + qdf_mem_copy(connect_ies->link_bcn_probe_rsp.ptr, + bcn_probe_rsp_ptr, + connect_ies->link_bcn_probe_rsp.len); + } + /* ReAssoc Rsp IE data */ if (roam_synch_data->reassocRespLength > sizeof(struct wlan_frame_hdr)) { @@ -792,21 +808,49 @@ end: static void cm_update_scan_db_on_roam_success(struct wlan_objmgr_vdev *vdev, struct wlan_cm_connect_resp *resp, - struct roam_offload_synch_ind *roam_synch_data, + struct roam_offload_synch_ind *roam_synch_ind, wlan_cm_id cm_id) { struct cnx_mgr *cm_ctx; + qdf_freq_t link_freq; + struct wlan_connect_rsp_ies *ies = &resp->connect_ies; cm_ctx = cm_get_cm_ctx(vdev); if (!cm_ctx) return; - cm_inform_bcn_probe(cm_ctx, - resp->connect_ies.bcn_probe_rsp.ptr, - resp->connect_ies.bcn_probe_rsp.len, - resp->freq, - roam_synch_data->rssi, - cm_id); + link_freq = mlo_roam_get_chan_freq(wlan_vdev_get_id(vdev), + roam_synch_ind); + if (roam_synch_ind->auth_status == ROAM_AUTH_STATUS_CONNECTED) { + if (ies->link_bcn_probe_rsp.len) + cm_inform_bcn_probe(cm_ctx, + ies->link_bcn_probe_rsp.ptr, + ies->link_bcn_probe_rsp.len, + link_freq, + roam_synch_ind->rssi, + cm_id); + cm_inform_bcn_probe(cm_ctx, + ies->bcn_probe_rsp.ptr, + ies->bcn_probe_rsp.len, + resp->freq, + roam_synch_ind->rssi, + cm_id); + } else if (wlan_vdev_mlme_is_mlo_link_vdev(vdev)) { + if (ies->link_bcn_probe_rsp.len) + cm_inform_bcn_probe(cm_ctx, + ies->link_bcn_probe_rsp.ptr, + ies->link_bcn_probe_rsp.len, + link_freq, + roam_synch_ind->rssi, + cm_id); + } else { + cm_inform_bcn_probe(cm_ctx, + ies->bcn_probe_rsp.ptr, + ies->bcn_probe_rsp.len, + resp->freq, + roam_synch_ind->rssi, + cm_id); + } cm_update_scan_mlme_on_roam(vdev, &resp->bssid, SCAN_ENTRY_CON_STATE_ASSOC); @@ -1306,6 +1350,11 @@ QDF_STATUS wlan_cm_free_roam_synch_frame_ind(struct rso_config *rso_cfg) frame_ind->bcn_probe_rsp_len = 0; frame_ind->bcn_probe_rsp = NULL; } + if (frame_ind->link_bcn_probe_rsp) { + qdf_mem_free(frame_ind->link_bcn_probe_rsp); + frame_ind->link_bcn_probe_rsp_len = 0; + frame_ind->link_bcn_probe_rsp = NULL; + } if (frame_ind->reassoc_req) { qdf_mem_free(frame_ind->reassoc_req); frame_ind->reassoc_req_len = 0; 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 38607e4d2d..ce29d33a72 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 @@ -422,6 +422,17 @@ cm_roam_sync_frame_event_handler(struct wlan_objmgr_psoc *psoc, sync_frame_ind->bcn_probe_rsp; } + if (sync_frame_ind->link_bcn_probe_rsp_len) { + roam_synch_frame_ind->link_bcn_probe_rsp_len = + sync_frame_ind->link_bcn_probe_rsp_len; + roam_synch_frame_ind->is_link_beacon = + sync_frame_ind->is_link_beacon; + if (roam_synch_frame_ind->link_bcn_probe_rsp) + qdf_mem_free(roam_synch_frame_ind->link_bcn_probe_rsp); + roam_synch_frame_ind->link_bcn_probe_rsp = + sync_frame_ind->link_bcn_probe_rsp; + } + if (sync_frame_ind->reassoc_req_len) { roam_synch_frame_ind->reassoc_req_len = sync_frame_ind->reassoc_req_len; @@ -504,7 +515,18 @@ QDF_STATUS cm_roam_sync_event_handler_cb(struct wlan_objmgr_vdev *vdev, } /* 24 byte MAC header and 12 byte to ssid IE */ - if (sync_ind->beaconProbeRespLength > + if (wlan_vdev_mlme_is_mlo_link_vdev(vdev) && + sync_ind->link_beacon_probe_resp_length) { + if (sync_ind->link_beacon_probe_resp_length > + (QDF_IEEE80211_3ADDR_HDR_LEN + MAC_B_PR_SSID_OFFSET)) { + ie_len = sync_ind->link_beacon_probe_resp_length - + (QDF_IEEE80211_3ADDR_HDR_LEN + + MAC_B_PR_SSID_OFFSET); + } else { + mlme_err("LFR3: MLO: Invalid link Beacon Length"); + goto err; + } + } else 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); diff --git a/components/umac/mlme/connection_mgr/core/src/wlan_cm_vdev_connect.c b/components/umac/mlme/connection_mgr/core/src/wlan_cm_vdev_connect.c index 6310f0ab3d..6b37d390a5 100644 --- a/components/umac/mlme/connection_mgr/core/src/wlan_cm_vdev_connect.c +++ b/components/umac/mlme/connection_mgr/core/src/wlan_cm_vdev_connect.c @@ -1671,6 +1671,7 @@ void wlan_cm_free_connect_rsp(struct cm_vdev_join_rsp *rsp) qdf_mem_free(connect_ie->assoc_req.ptr); qdf_mem_free(connect_ie->bcn_probe_rsp.ptr); + qdf_mem_free(connect_ie->link_bcn_probe_rsp.ptr); qdf_mem_free(connect_ie->assoc_rsp.ptr); cm_free_fils_ie(connect_ie); cm_free_tspec_ie(rsp); 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 142a4dc3be..2a49aa8a0a 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 @@ -440,6 +440,9 @@ struct roam_synch_frame_ind { uint32_t bcn_probe_rsp_len; uint8_t *bcn_probe_rsp; uint8_t is_beacon; + uint32_t link_bcn_probe_rsp_len; + uint8_t *link_bcn_probe_rsp; + uint8_t is_link_beacon; uint32_t reassoc_req_len; uint8_t *reassoc_req; uint32_t reassoc_rsp_len; @@ -2588,6 +2591,9 @@ struct roam_offload_synch_ind { uint8_t is_assoc; enum wlan_phymode phy_mode; /*phy mode sent by fw */ wmi_channel chan; + uint16_t link_beacon_probe_resp_offset; + uint16_t link_beacon_probe_resp_length; + uint8_t is_link_beacon; #ifdef WLAN_FEATURE_11BE_MLO uint8_t num_setup_links; struct ml_setup_link_param ml_link[WLAN_UMAC_MLO_MAX_VDEVS]; diff --git a/components/umac/mlme/mlo_mgr/inc/wlan_mlo_mgr_roam.h b/components/umac/mlme/mlo_mgr/inc/wlan_mlo_mgr_roam.h index 31216a27a7..248cc195e6 100644 --- a/components/umac/mlme/mlo_mgr/inc/wlan_mlo_mgr_roam.h +++ b/components/umac/mlme/mlo_mgr/inc/wlan_mlo_mgr_roam.h @@ -91,6 +91,20 @@ uint32_t mlo_roam_get_chan_freq(uint8_t vdev_id, struct roam_offload_synch_ind *sync_ind); +/** + * mlo_roam_get_link_freq - get given link frequency + * + * @vdev_id: vdev id + * @sync_ind: roam sync ind pointer + * + * This api will be called to get the link frequency. + * + * Return: channel frequency + */ +uint32_t +mlo_roam_get_link_freq(uint8_t vdev_id, + struct roam_offload_synch_ind *sync_ind); + /** * mlo_roam_get_link_id - get link id * diff --git a/components/umac/mlme/mlo_mgr/src/wlan_mlo_mgr_roam.c b/components/umac/mlme/mlo_mgr/src/wlan_mlo_mgr_roam.c index 4f1d1721cd..0f966fd8c8 100644 --- a/components/umac/mlme/mlo_mgr/src/wlan_mlo_mgr_roam.c +++ b/components/umac/mlme/mlo_mgr/src/wlan_mlo_mgr_roam.c @@ -396,6 +396,23 @@ bool is_multi_link_roam(struct roam_offload_synch_ind *sync_ind) return false; } +uint32_t +mlo_roam_get_link_freq(uint8_t vdev_id, + struct roam_offload_synch_ind *sync_ind) +{ + uint8_t i; + + if (!sync_ind || !sync_ind->num_setup_links) + return 0; + + for (i = 0; i < sync_ind->num_setup_links; i++) { + if (sync_ind->ml_link[i].vdev_id != vdev_id) + return sync_ind->ml_link[i].channel.mhz; + } + + return 0; +} + QDF_STATUS mlo_enable_rso(struct wlan_objmgr_pdev *pdev, struct wlan_objmgr_vdev *vdev, struct wlan_cm_connect_resp *rsp) @@ -440,7 +457,7 @@ mlo_roam_copy_partner_info(struct wlan_cm_connect_resp *connect_rsp, for (i = 0; i < sync_ind->num_setup_links; i++) { partner_info->partner_link_info[i].link_id = sync_ind->ml_link[i].link_id; - partner_info->partner_link_info[i].vdev_id = + partner_info->partner_link_info[i].vdev_id = sync_ind->ml_link[i].vdev_id; qdf_copy_macaddr( diff --git a/components/wmi/src/wmi_unified_roam_tlv.c b/components/wmi/src/wmi_unified_roam_tlv.c index 0be3bff8c3..a9071b93d5 100644 --- a/components/wmi/src/wmi_unified_roam_tlv.c +++ b/components/wmi/src/wmi_unified_roam_tlv.c @@ -2102,7 +2102,7 @@ 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 *bcn_probersp_ptr, *link_bcn_probersp_ptr; uint8_t *reassoc_rsp_ptr; uint8_t *reassoc_req_ptr; @@ -2119,10 +2119,29 @@ wmi_fill_data_synch_frame_event(struct rso_config *rso_cfg, qdf_mem_free(rso_cfg->roam_sync_frame_ind.bcn_probe_rsp); rso_cfg->roam_sync_frame_ind.bcn_probe_rsp = NULL; + /* Link beacon/probe rsp data */ + if (rso_cfg->roam_sync_frame_ind.link_bcn_probe_rsp) { + roam_sync_ind->link_beacon_probe_resp_offset = + sizeof(struct roam_offload_synch_ind) + + roam_sync_ind->beaconProbeRespLength; + roam_sync_ind->link_beacon_probe_resp_length = + rso_cfg->roam_sync_frame_ind.link_bcn_probe_rsp_len; + roam_sync_ind->is_link_beacon = + rso_cfg->roam_sync_frame_ind.is_link_beacon; + link_bcn_probersp_ptr = (uint8_t *)roam_sync_ind + + roam_sync_ind->link_beacon_probe_resp_offset; + qdf_mem_copy(link_bcn_probersp_ptr, + rso_cfg->roam_sync_frame_ind.link_bcn_probe_rsp, + roam_sync_ind->link_beacon_probe_resp_length); + qdf_mem_free(rso_cfg->roam_sync_frame_ind.link_bcn_probe_rsp); + rso_cfg->roam_sync_frame_ind.link_bcn_probe_rsp = NULL; + } + /* ReAssoc Rsp data */ roam_sync_ind->reassocRespOffset = sizeof(struct roam_offload_synch_ind) + - roam_sync_ind->beaconProbeRespLength; + roam_sync_ind->beaconProbeRespLength + + roam_sync_ind->link_beacon_probe_resp_length; roam_sync_ind->reassocRespLength = rso_cfg->roam_sync_frame_ind.reassoc_rsp_len; reassoc_rsp_ptr = (uint8_t *)roam_sync_ind + @@ -2137,6 +2156,7 @@ wmi_fill_data_synch_frame_event(struct rso_config *rso_cfg, roam_sync_ind->reassoc_req_offset = sizeof(struct roam_offload_synch_ind) + roam_sync_ind->beaconProbeRespLength + + roam_sync_ind->link_beacon_probe_resp_length + roam_sync_ind->reassocRespLength; roam_sync_ind->reassoc_req_length = rso_cfg->roam_sync_frame_ind.reassoc_req_len; @@ -2183,6 +2203,10 @@ wmi_fill_data_synch_event(struct roam_offload_synch_ind *roam_sync_ind, synch_event->bcn_probe_rsp_len; qdf_mem_copy(bcn_probersp_ptr, param_buf->bcn_probe_rsp_frame, roam_sync_ind->beaconProbeRespLength); + /* + * Firmware doesn't support link beacon/Probe Rsp data in roam sync + * event. It's always sent in sync_frame event + */ /* ReAssoc Rsp data */ roam_sync_ind->reassocRespOffset = sizeof(struct roam_offload_synch_ind) + @@ -2208,7 +2232,8 @@ wmi_fill_data_synch_event(struct roam_offload_synch_ind *roam_sync_ind, #ifdef WLAN_FEATURE_11BE_MLO static QDF_STATUS -wmi_fill_roam_mlo_info(WMI_ROAM_SYNCH_EVENTID_param_tlvs *param_buf, +wmi_fill_roam_mlo_info(wmi_unified_t wmi_handle, + WMI_ROAM_SYNCH_EVENTID_param_tlvs *param_buf, struct roam_offload_synch_ind *roam_sync_ind) { uint8_t i; @@ -2262,7 +2287,8 @@ wmi_fill_roam_mlo_info(WMI_ROAM_SYNCH_EVENTID_param_tlvs *param_buf, } #else static QDF_STATUS -wmi_fill_roam_mlo_info(WMI_ROAM_SYNCH_EVENTID_param_tlvs *param_buf, +wmi_fill_roam_mlo_info(wmi_unified_t wmi_handle, + WMI_ROAM_SYNCH_EVENTID_param_tlvs *param_buf, struct roam_offload_synch_ind *roam_sync_ind) { return QDF_STATUS_SUCCESS; @@ -2270,7 +2296,8 @@ wmi_fill_roam_mlo_info(WMI_ROAM_SYNCH_EVENTID_param_tlvs *param_buf, #endif static QDF_STATUS -wmi_fill_roam_sync_buffer(struct wlan_objmgr_vdev *vdev, +wmi_fill_roam_sync_buffer(wmi_unified_t wmi_handle, + 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) @@ -2318,6 +2345,7 @@ wmi_fill_roam_sync_buffer(struct wlan_objmgr_vdev *vdev, 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); @@ -2439,7 +2467,7 @@ wmi_fill_roam_sync_buffer(struct wlan_objmgr_vdev *vdev, pmk_cache_info->pmkid, PMKID_LEN); } - status = wmi_fill_roam_mlo_info(param_buf, roam_sync_ind); + status = wmi_fill_roam_mlo_info(wmi_handle, param_buf, roam_sync_ind); if (QDF_IS_STATUS_ERROR(status)) { wmi_err("Failed to fill roam mlo info"); return status; @@ -2469,7 +2497,7 @@ extract_roam_sync_event_tlv(wmi_unified_t wmi_handle, void *evt_buf, 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 bcn_probe_rsp_len, link_bcn_probe_rsp_len; uint32_t reassoc_rsp_len; uint32_t reassoc_req_len; wmi_pdev_hw_mode_transition_event_fixed_param *hw_mode_trans_param; @@ -2554,15 +2582,21 @@ extract_roam_sync_event_tlv(wmi_unified_t wmi_handle, void *evt_buf, 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; + bcn_probe_rsp_len = + rso_cfg->roam_sync_frame_ind.bcn_probe_rsp_len; + link_bcn_probe_rsp_len = + rso_cfg->roam_sync_frame_ind.link_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); + roam_synch_data_len = + bcn_probe_rsp_len + link_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", + wmi_debug("Updated synch payload: LEN bcn:%d, link bcn: %d req:%d, rsp:%d", bcn_probe_rsp_len, + link_bcn_probe_rsp_len, reassoc_req_len, reassoc_rsp_len); } else { @@ -2609,7 +2643,7 @@ extract_roam_sync_event_tlv(wmi_unified_t wmi_handle, void *evt_buf, } *roam_sync_ind = roam_sync; - status = wmi_fill_roam_sync_buffer(vdev, rso_cfg, + status = wmi_fill_roam_sync_buffer(wmi_handle, vdev, rso_cfg, roam_sync, param_buf); end: @@ -2638,8 +2672,8 @@ extract_roam_sync_frame_event_tlv(wmi_unified_t wmi_handle, void *event, struct roam_synch_frame_ind *frame_ptr) { WMI_ROAM_SYNCH_FRAME_EVENTID_param_tlvs *param_buf = NULL; - struct roam_synch_frame_ind *roam_sync_frame_ind; - wmi_roam_synch_frame_event_fixed_param *synch_frame_event; + struct roam_synch_frame_ind *frame_ind; + wmi_roam_synch_frame_event_fixed_param *frame_evt; if (!event) { wmi_err("Event param null"); @@ -2652,16 +2686,14 @@ extract_roam_sync_frame_event_tlv(wmi_unified_t wmi_handle, void *event, return QDF_STATUS_E_NULL_VALUE; } - synch_frame_event = param_buf->fixed_param; - - if (!synch_frame_event) { + frame_evt = param_buf->fixed_param; + if (!frame_evt) { wmi_err("received null event data from target"); return QDF_STATUS_E_NULL_VALUE; } - if (synch_frame_event->vdev_id >= WLAN_MAX_VDEVS) { - wmi_err("received invalid vdev_id %d", - synch_frame_event->vdev_id); + if (frame_evt->vdev_id >= WLAN_MAX_VDEVS) { + wmi_err("received invalid vdev_id %d", frame_evt->vdev_id); return QDF_STATUS_E_FAILURE; } @@ -2670,82 +2702,95 @@ extract_roam_sync_frame_event_tlv(wmi_unified_t wmi_handle, void *event, * driver. So Bcn_prb_rsp_len/reassoc_req_len/reassoc_rsp_len can be 0 * in some of the events. */ - if (synch_frame_event->bcn_probe_rsp_len > - param_buf->num_bcn_probe_rsp_frame || - synch_frame_event->reassoc_req_len > - param_buf->num_reassoc_req_frame || - synch_frame_event->reassoc_rsp_len > - param_buf->num_reassoc_rsp_frame || - (synch_frame_event->bcn_probe_rsp_len && - synch_frame_event->bcn_probe_rsp_len < sizeof(struct wlan_frame_hdr)) || - (synch_frame_event->reassoc_req_len && - synch_frame_event->reassoc_req_len < sizeof(struct wlan_frame_hdr)) || - (synch_frame_event->reassoc_rsp_len && - synch_frame_event->reassoc_rsp_len < sizeof(struct wlan_frame_hdr))) { + if (frame_evt->bcn_probe_rsp_len > param_buf->num_bcn_probe_rsp_frame || + frame_evt->reassoc_req_len > param_buf->num_reassoc_req_frame || + frame_evt->reassoc_rsp_len > param_buf->num_reassoc_rsp_frame || + (frame_evt->bcn_probe_rsp_len && + frame_evt->bcn_probe_rsp_len < sizeof(struct wlan_frame_hdr)) || + (frame_evt->reassoc_req_len && + frame_evt->reassoc_req_len < sizeof(struct wlan_frame_hdr)) || + (frame_evt->reassoc_rsp_len && + frame_evt->reassoc_rsp_len < sizeof(struct wlan_frame_hdr))) { wmi_err("fixed/actual len err: bcn:%d/%d req:%d/%d rsp:%d/%d", - synch_frame_event->bcn_probe_rsp_len, + frame_evt->bcn_probe_rsp_len, param_buf->num_bcn_probe_rsp_frame, - synch_frame_event->reassoc_req_len, + frame_evt->reassoc_req_len, param_buf->num_reassoc_req_frame, - synch_frame_event->reassoc_rsp_len, + frame_evt->reassoc_rsp_len, param_buf->num_reassoc_rsp_frame); return QDF_STATUS_E_FAILURE; } - roam_sync_frame_ind = frame_ptr; - roam_sync_frame_ind->vdev_id = synch_frame_event->vdev_id; + frame_ind = frame_ptr; + frame_ind->vdev_id = frame_evt->vdev_id; - wmi_debug("synch frame payload: LEN bcn:%d, req:%d, rsp:%d", - synch_frame_event->bcn_probe_rsp_len, - synch_frame_event->reassoc_req_len, - synch_frame_event->reassoc_rsp_len); + wmi_debug("synch frame payload: LEN %s bcn:%d, req:%d, rsp:%d", + frame_evt->reassoc_rsp_len ? "Assoc" : "Link", + frame_evt->bcn_probe_rsp_len, + frame_evt->reassoc_req_len, + frame_evt->reassoc_rsp_len); - if (synch_frame_event->bcn_probe_rsp_len) { - roam_sync_frame_ind->bcn_probe_rsp_len = - synch_frame_event->bcn_probe_rsp_len; + if (frame_evt->bcn_probe_rsp_len && + frame_evt->reassoc_rsp_len) { + frame_ind->bcn_probe_rsp_len = frame_evt->bcn_probe_rsp_len; - roam_sync_frame_ind->is_beacon = - synch_frame_event->is_beacon; + frame_ind->is_beacon = frame_evt->is_beacon; - roam_sync_frame_ind->bcn_probe_rsp = - qdf_mem_malloc(roam_sync_frame_ind->bcn_probe_rsp_len); - if (!roam_sync_frame_ind->bcn_probe_rsp) { - QDF_ASSERT(roam_sync_frame_ind->bcn_probe_rsp); + frame_ind->bcn_probe_rsp = + qdf_mem_malloc(frame_ind->bcn_probe_rsp_len); + if (!frame_ind->bcn_probe_rsp) { + QDF_ASSERT(frame_ind->bcn_probe_rsp); return QDF_STATUS_E_NOMEM; } - qdf_mem_copy(roam_sync_frame_ind->bcn_probe_rsp, + qdf_mem_copy(frame_ind->bcn_probe_rsp, param_buf->bcn_probe_rsp_frame, - roam_sync_frame_ind->bcn_probe_rsp_len); - } + frame_ind->bcn_probe_rsp_len); + } else if (frame_evt->bcn_probe_rsp_len) { + frame_ind->link_bcn_probe_rsp_len = + frame_evt->bcn_probe_rsp_len; - if (synch_frame_event->reassoc_req_len) { - roam_sync_frame_ind->reassoc_req_len = - synch_frame_event->reassoc_req_len; + frame_ind->is_link_beacon = frame_evt->is_beacon; - roam_sync_frame_ind->reassoc_req = - qdf_mem_malloc(roam_sync_frame_ind->reassoc_req_len); - if (!roam_sync_frame_ind->reassoc_req) { - QDF_ASSERT(roam_sync_frame_ind->reassoc_req); + if (frame_ind->link_bcn_probe_rsp) + qdf_mem_free(frame_ind->bcn_probe_rsp); + + frame_ind->link_bcn_probe_rsp = + qdf_mem_malloc(frame_ind->link_bcn_probe_rsp_len); + if (!frame_ind->link_bcn_probe_rsp) { + QDF_ASSERT(frame_ind->link_bcn_probe_rsp); return QDF_STATUS_E_NOMEM; } - qdf_mem_copy(roam_sync_frame_ind->reassoc_req, + qdf_mem_copy(frame_ind->link_bcn_probe_rsp, + param_buf->bcn_probe_rsp_frame, + frame_ind->link_bcn_probe_rsp_len); + } + + if (frame_evt->reassoc_req_len) { + frame_ind->reassoc_req_len = frame_evt->reassoc_req_len; + + frame_ind->reassoc_req = + qdf_mem_malloc(frame_ind->reassoc_req_len); + if (!frame_ind->reassoc_req) { + QDF_ASSERT(frame_ind->reassoc_req); + return QDF_STATUS_E_NOMEM; + } + qdf_mem_copy(frame_ind->reassoc_req, param_buf->reassoc_req_frame, - roam_sync_frame_ind->reassoc_req_len); + frame_ind->reassoc_req_len); } - if (synch_frame_event->reassoc_rsp_len) { - roam_sync_frame_ind->reassoc_rsp_len = - synch_frame_event->reassoc_rsp_len; + if (frame_evt->reassoc_rsp_len) { + frame_ind->reassoc_rsp_len = frame_evt->reassoc_rsp_len; - roam_sync_frame_ind->reassoc_rsp = - qdf_mem_malloc(roam_sync_frame_ind->reassoc_rsp_len); - if (!roam_sync_frame_ind->reassoc_rsp) { - QDF_ASSERT(roam_sync_frame_ind->reassoc_rsp); + frame_ind->reassoc_rsp = + qdf_mem_malloc(frame_ind->reassoc_rsp_len); + if (!frame_ind->reassoc_rsp) { + QDF_ASSERT(frame_ind->reassoc_rsp); return QDF_STATUS_E_NOMEM; } - qdf_mem_copy(roam_sync_frame_ind->reassoc_rsp, + qdf_mem_copy(frame_ind->reassoc_rsp, param_buf->reassoc_rsp_frame, - roam_sync_frame_ind->reassoc_rsp_len); + frame_ind->reassoc_rsp_len); } return QDF_STATUS_SUCCESS; diff --git a/core/mac/src/pe/include/lim_api.h b/core/mac/src/pe/include/lim_api.h index 6438d0d01b..8348a9020e 100644 --- a/core/mac/src/pe/include/lim_api.h +++ b/core/mac/src/pe/include/lim_api.h @@ -595,6 +595,19 @@ lim_gen_link_specific_probe_rsp(struct mac_context *mac_ctx, * Return qdf status */ QDF_STATUS lim_check_for_ml_probe_req(struct pe_session *session); + +/** + * lim_gen_link_probe_rsp_roam() - Generate link prb rsp from assoc link prb rsp + * @mac_ctx: Pointer to mac context + * @session_entry: pe session + * @roam_sync_ind_ptr: Roam synch parameters + * + * Return qdf status + */ +QDF_STATUS +lim_gen_link_probe_rsp_roam(struct mac_context *mac_ctx, + struct pe_session *session_entry, + struct roam_offload_synch_ind *roam_sync_ind); #else static inline QDF_STATUS lim_gen_link_specific_probe_rsp(struct mac_context *mac_ctx, @@ -612,6 +625,14 @@ lim_check_for_ml_probe_req(struct pe_session *session) { return QDF_STATUS_E_NOSUPPORT; } + +static inline QDF_STATUS +lim_gen_link_probe_rsp_roam(struct mac_context *mac_ctx, + struct pe_session *session_entry, + struct roam_offload_synch_ind *roam_sync_ind) +{ + return QDF_STATUS_E_NOSUPPORT; +} #endif #ifdef WLAN_FEATURE_SR diff --git a/core/mac/src/pe/lim/lim_api.c b/core/mac/src/pe/lim/lim_api.c index b2963662fb..afb0832a86 100644 --- a/core/mac/src/pe/lim/lim_api.c +++ b/core/mac/src/pe/lim/lim_api.c @@ -2073,18 +2073,18 @@ error: static QDF_STATUS lim_roam_gen_beacon_descr(struct mac_context *mac, + uint8_t *bcn_prb_ptr, + uint16_t bcn_prb_len, bool is_mlo_link, struct roam_offload_synch_ind *roam_ind, tpSirProbeRespBeacon parsed_frm, uint8_t **ie, uint32_t *ie_len, struct qdf_mac_addr *bssid) { QDF_STATUS status; - uint8_t *bcn_prb_ptr; tpSirMacMgmtHdr mac_hdr; uint8_t ie_offset; + bool is_beacon; - bcn_prb_ptr = (uint8_t *)roam_ind + - roam_ind->beaconProbeRespOffset; mac_hdr = (tpSirMacMgmtHdr)bcn_prb_ptr; ie_offset = SIR_MAC_HDR_LEN_3A + SIR_MAC_B_PR_SSID_OFFSET; @@ -2096,6 +2096,8 @@ lim_roam_gen_beacon_descr(struct mac_context *mac, sizeof(tSirMacAddr)); } + is_beacon = is_mlo_link ? roam_ind->is_link_beacon : roam_ind->isBeacon; + if ((!is_multi_link_roam(roam_ind)) && (qdf_mem_cmp(bssid->bytes, &mac_hdr->bssId, QDF_MAC_ADDR_SIZE) != 0)) { @@ -2116,32 +2118,32 @@ lim_roam_gen_beacon_descr(struct mac_context *mac, return QDF_STATUS_E_FAILURE; } } else { - if (roam_ind->isBeacon) { + if (is_beacon) { if (sir_parse_beacon_ie(mac, parsed_frm, &bcn_prb_ptr[SIR_MAC_HDR_LEN_3A + SIR_MAC_B_PR_SSID_OFFSET], - roam_ind->beaconProbeRespLength - - SIR_MAC_HDR_LEN_3A) != QDF_STATUS_SUCCESS || - !parsed_frm->ssidPresent) { + bcn_prb_len - SIR_MAC_HDR_LEN_3A) != + QDF_STATUS_SUCCESS || + !parsed_frm->ssidPresent) { pe_err("Parse error Beacon, length: %d", - roam_ind->beaconProbeRespLength); + bcn_prb_len); return QDF_STATUS_E_FAILURE; } } else { if (sir_convert_probe_frame2_struct(mac, &bcn_prb_ptr[SIR_MAC_HDR_LEN_3A], - roam_ind->beaconProbeRespLength - + bcn_prb_len - SIR_MAC_HDR_LEN_3A, parsed_frm) != QDF_STATUS_SUCCESS || !parsed_frm->ssidPresent) { pe_err("Parse error ProbeResponse, length: %d", - roam_ind->beaconProbeRespLength); + bcn_prb_len); return QDF_STATUS_E_FAILURE; } } /* 24 byte MAC header and 12 byte to ssid IE */ - if (roam_ind->beaconProbeRespLength > ie_offset) { - *ie_len = roam_ind->beaconProbeRespLength - ie_offset; + if (bcn_prb_len > ie_offset) { + *ie_len = bcn_prb_len - ie_offset; *ie = qdf_mem_malloc(*ie_len); if (!*ie) return QDF_STATUS_E_NOMEM; @@ -2153,7 +2155,7 @@ lim_roam_gen_beacon_descr(struct mac_context *mac, * For probe response, unpack core parses beacon interval, capabilities, * timestamp. For beacon IEs, these fields are not parsed. */ - if (roam_ind->isBeacon) + if (is_beacon) sir_parse_bcn_fixed_fields(mac, parsed_frm, &bcn_prb_ptr[SIR_MAC_HDR_LEN_3A]); @@ -2164,29 +2166,70 @@ static QDF_STATUS lim_roam_fill_bss_descr(struct mac_context *mac, struct roam_offload_synch_ind *roam_synch_ind_ptr, struct bss_description *bss_desc_ptr, - uint8_t vdev_id) + struct pe_session *session) { uint32_t ie_len = 0; - tpSirProbeRespBeacon parsed_frm_ptr; + tpSirProbeRespBeacon parsed_frm_ptr = NULL; tpSirMacMgmtHdr mac_hdr; - uint8_t *bcn_proberesp_ptr; - QDF_STATUS status; + uint8_t *bcn_proberesp_ptr = NULL; + uint16_t bcn_proberesp_len = 0; + QDF_STATUS status = QDF_STATUS_SUCCESS; uint8_t *ie = NULL; struct qdf_mac_addr bssid; + bool is_mlo_link = false; + uint8_t vdev_id = session->vdev_id; + struct element_info frame; + + frame.ptr = NULL; + frame.len = 0; + if (is_multi_link_roam(roam_synch_ind_ptr) && + wlan_vdev_mlme_get_is_mlo_link(mac->psoc, vdev_id)) { + if (roam_synch_ind_ptr->link_beacon_probe_resp_length) { + bcn_proberesp_ptr = (uint8_t *)roam_synch_ind_ptr + + roam_synch_ind_ptr->link_beacon_probe_resp_offset; + bcn_proberesp_len = + roam_synch_ind_ptr->link_beacon_probe_resp_length; + } else { + /* + * This indicates that firmware hasn't sent link beacon, + * which means assoc probe rsp is an ML probe rsp. + * Extract the link probe rsp also from that. + */ + status = lim_gen_link_probe_rsp_roam(mac, + session, roam_synch_ind_ptr); + if (QDF_IS_STATUS_ERROR(status)) + return status; + mlo_get_sta_link_mac_addr(vdev_id, roam_synch_ind_ptr, + &bssid); + status = wlan_scan_get_entry_by_mac_addr(mac->pdev, + &bssid, &frame); + if (QDF_IS_STATUS_ERROR(status) && !frame.len) { + pe_err("Failed to get scan entry for " QDF_MAC_ADDR_FMT, + QDF_MAC_ADDR_REF(bssid.bytes)); + return status; + } + bcn_proberesp_ptr = frame.ptr; + bcn_proberesp_len = frame.len; + } + is_mlo_link = true; + } else { + bcn_proberesp_ptr = (uint8_t *)roam_synch_ind_ptr + + roam_synch_ind_ptr->beaconProbeRespOffset; + bcn_proberesp_len = roam_synch_ind_ptr->beaconProbeRespLength; + } - bcn_proberesp_ptr = (uint8_t *)roam_synch_ind_ptr + - roam_synch_ind_ptr->beaconProbeRespOffset; mac_hdr = (tpSirMacMgmtHdr)bcn_proberesp_ptr; parsed_frm_ptr = qdf_mem_malloc(sizeof(tSirProbeRespBeacon)); - if (!parsed_frm_ptr) - return QDF_STATUS_E_NOMEM; + if (!parsed_frm_ptr) { + status = QDF_STATUS_E_NOMEM; + goto done; + } - if (roam_synch_ind_ptr->beaconProbeRespLength <= - SIR_MAC_HDR_LEN_3A) { - pe_err("very few bytes in synchInd beacon / probe resp frame! length: %d", - roam_synch_ind_ptr->beaconProbeRespLength); - qdf_mem_free(parsed_frm_ptr); - return QDF_STATUS_E_FAILURE; + if (bcn_proberesp_len <= SIR_MAC_HDR_LEN_3A) { + pe_err("very few bytes in synchInd %s beacon / probe resp frame! length: %d", + is_mlo_link ? "link" : "", bcn_proberesp_len); + status = QDF_STATUS_E_FAILURE; + goto done; } if (is_multi_link_roam(roam_synch_ind_ptr)) @@ -2196,23 +2239,24 @@ lim_roam_fill_bss_descr(struct mac_context *mac, pe_debug("LFR3:Beacon/Prb Rsp: %d bssid " QDF_MAC_ADDR_FMT " beacon " QDF_MAC_ADDR_FMT, - roam_synch_ind_ptr->isBeacon, + is_mlo_link ? roam_synch_ind_ptr->is_link_beacon : + roam_synch_ind_ptr->isBeacon, QDF_MAC_ADDR_REF(bssid.bytes), QDF_MAC_ADDR_REF(mac_hdr->bssId)); QDF_TRACE_HEX_DUMP(QDF_MODULE_ID_PE, QDF_TRACE_LEVEL_DEBUG, bcn_proberesp_ptr, - roam_synch_ind_ptr->beaconProbeRespLength); + bcn_proberesp_len); - status = lim_roam_gen_beacon_descr(mac, - roam_synch_ind_ptr, - parsed_frm_ptr, + status = lim_roam_gen_beacon_descr(mac, bcn_proberesp_ptr, + bcn_proberesp_len, is_mlo_link, + roam_synch_ind_ptr, parsed_frm_ptr, &ie, &ie_len, &bssid); if (QDF_IS_STATUS_ERROR(status)) { pe_err("Failed to parse beacon"); - qdf_mem_free(parsed_frm_ptr); - return QDF_STATUS_E_FAILURE; + status = QDF_STATUS_E_FAILURE; + goto done; } /* @@ -2231,7 +2275,9 @@ lim_roam_fill_bss_descr(struct mac_context *mac, ieFields[0]) - sizeof(bss_desc_ptr->length) + ie_len); - bss_desc_ptr->fProbeRsp = !roam_synch_ind_ptr->isBeacon; + bss_desc_ptr->fProbeRsp = !(is_mlo_link ? + roam_synch_ind_ptr->is_link_beacon : + roam_synch_ind_ptr->isBeacon); bss_desc_ptr->rssi = roam_synch_ind_ptr->rssi; /* Copy Timestamp */ bss_desc_ptr->scansystimensec = qdf_get_monotonic_boottime_ns(); @@ -2290,16 +2336,19 @@ lim_roam_fill_bss_descr(struct mac_context *mac, bss_desc_ptr->chan_freq, bss_desc_ptr->rssi, ie_len); - qdf_mem_free(parsed_frm_ptr); if (ie_len) { qdf_mem_copy(&bss_desc_ptr->ieFields, ie, ie_len); qdf_mem_free(ie); } else { pe_err("Beacon/Probe rsp doesn't have any IEs"); - return QDF_STATUS_E_FAILURE; + status = QDF_STATUS_E_FAILURE; + goto done; } - return QDF_STATUS_SUCCESS; +done: + qdf_mem_free(frame.ptr); + qdf_mem_free(parsed_frm_ptr); + return status; } #if defined(WLAN_FEATURE_FILS_SK) @@ -2741,7 +2790,7 @@ pe_roam_synch_callback(struct mac_context *mac_ctx, } status = lim_roam_fill_bss_descr(mac_ctx, roam_sync_ind_ptr, - bss_desc, vdev_id); + bss_desc, session_ptr); if (!QDF_IS_STATUS_SUCCESS(status)) { pe_err("LFR3:Failed to fill Bss Descr"); qdf_mem_free(bss_desc); @@ -3313,8 +3362,8 @@ lim_cm_fill_link_session(struct mac_context *mac_ctx, sir_copy_mac_addr(pe_session->bssId, sync_ind->bssid.bytes); - pe_session->lim_join_req = qdf_mem_malloc(sizeof(*pe_session->lim_join_req) + - bss_len); + pe_session->lim_join_req = + qdf_mem_malloc(sizeof(*pe_session->lim_join_req) + bss_len); if (!pe_session->lim_join_req) return QDF_STATUS_E_NOMEM; @@ -3328,7 +3377,8 @@ lim_cm_fill_link_session(struct mac_context *mac_ctx, goto end; } - status = lim_roam_fill_bss_descr(mac_ctx, sync_ind, bss_desc, vdev_id); + status = lim_roam_fill_bss_descr(mac_ctx, sync_ind, bss_desc, + pe_session); if (!QDF_IS_STATUS_SUCCESS(status)) { pe_err("LFR3:Failed to fill Bss Descr"); qdf_mem_free(bss_desc); @@ -3781,6 +3831,94 @@ end: link_probe_rsp.len = 0; return status; } + +QDF_STATUS +lim_gen_link_probe_rsp_roam(struct mac_context *mac_ctx, + struct pe_session *session, + struct roam_offload_synch_ind *roam_sync_ind) +{ + struct element_info link_probe_rsp; + struct qdf_mac_addr sta_link_addr; + QDF_STATUS status = QDF_STATUS_SUCCESS; + tSirProbeRespBeacon *probe_rsp; + uint8_t *frame; + uint32_t frame_len; + struct wlan_frame_hdr *hdr; + + if (!session || !roam_sync_ind) + return QDF_STATUS_E_NULL_VALUE; + + if (!roam_sync_ind->num_setup_links) + return status; + + if (roam_sync_ind->link_beacon_probe_resp_length) { + pe_debug("Firmware sent link beacon also. No need to generate a new one from assoc bcn/prb rsp"); + return QDF_STATUS_SUCCESS; + } + frame_len = roam_sync_ind->beaconProbeRespLength; + frame = (uint8_t *)roam_sync_ind + + roam_sync_ind->beaconProbeRespOffset; + + frame = (uint8_t *)(frame + sizeof(*hdr)); + frame_len -= sizeof(*hdr); + QDF_TRACE_HEX_DUMP(QDF_MODULE_ID_PE, QDF_TRACE_LEVEL_DEBUG, + frame, frame_len); + + probe_rsp = qdf_mem_malloc(sizeof(tSirProbeRespBeacon)); + if (!probe_rsp) + return QDF_STATUS_E_NOMEM; + + probe_rsp->ssId.length = 0; + probe_rsp->wpa.length = 0; + /* Enforce Mandatory IEs */ + if ((sir_convert_probe_frame2_struct(mac_ctx, + frame, frame_len, probe_rsp) == QDF_STATUS_E_FAILURE) || + !probe_rsp->ssidPresent) { + pe_err("Parse error ProbeResponse, length=%d", frame_len); + qdf_mem_free(probe_rsp); + return QDF_STATUS_E_INVAL; + } + + if (probe_rsp->mlo_ie.mlo_ie_present) { + link_probe_rsp.ptr = qdf_mem_malloc(frame_len); + if (!link_probe_rsp.ptr) + return QDF_STATUS_E_NOMEM; + + /* + * It's ok to keep assoc vdev mac address as DA as link vdev + * is just cleanedup and it may not be an ML vdev till the + * flags are set again + */ + qdf_mem_copy(&sta_link_addr, session->self_mac_addr, + QDF_MAC_ADDR_SIZE); + + link_probe_rsp.len = frame_len; + status = util_gen_link_probe_rsp(frame, frame_len, + sta_link_addr, link_probe_rsp.ptr, + frame_len, (qdf_size_t *)&link_probe_rsp.len); + if (QDF_IS_STATUS_ERROR(status)) { + pe_err("MLO: Link probe response generation failed %d", + status); + status = QDF_STATUS_E_FAILURE; + goto end; + } + + lim_add_bcn_probe(session->vdev, link_probe_rsp.ptr, + link_probe_rsp.len, + mlo_roam_get_link_freq(session->vdev_id, + roam_sync_ind), + roam_sync_ind->rssi); + } else { + qdf_mem_free(probe_rsp); + return status; + } +end: + if (link_probe_rsp.ptr) + qdf_mem_free(link_probe_rsp.ptr); + link_probe_rsp.len = 0; + qdf_mem_free(probe_rsp); + return status; +} #endif #ifdef WLAN_FEATURE_SR diff --git a/core/wma/src/wma_scan_roam.c b/core/wma/src/wma_scan_roam.c index 2c04a61538..30aa7544e7 100644 --- a/core/wma/src/wma_scan_roam.c +++ b/core/wma/src/wma_scan_roam.c @@ -560,11 +560,17 @@ wma_roam_update_vdev(tp_wma_handle wma, vdev_id = roamed_vdev_id; wma->interfaces[vdev_id].nss = roam_synch_ind_ptr->nss; - /* update freq and channel width */ - wma->interfaces[vdev_id].ch_freq = - roam_synch_ind_ptr->chan_freq; + + /* update channel width */ wma->interfaces[vdev_id].chan_width = roam_synch_ind_ptr->chan_width; + /* Fill link freq from roam_synch_ind */ + if (is_multi_link_roam(roam_synch_ind_ptr)) + wma->interfaces[vdev_id].ch_freq = + mlo_roam_get_chan_freq(vdev_id, roam_synch_ind_ptr); + else + wma->interfaces[vdev_id].ch_freq = + roam_synch_ind_ptr->chan_freq; del_sta_params = qdf_mem_malloc(sizeof(*del_sta_params)); if (!del_sta_params) {