|
@@ -3684,7 +3684,7 @@ lim_match_link_info(uint8_t req_link_id,
|
|
|
return false;
|
|
|
}
|
|
|
|
|
|
-static void
|
|
|
+static QDF_STATUS
|
|
|
lim_add_bcn_probe(struct wlan_objmgr_vdev *vdev, uint8_t *bcn_probe,
|
|
|
uint32_t len, qdf_freq_t freq, int32_t rssi)
|
|
|
{
|
|
@@ -3694,18 +3694,19 @@ lim_add_bcn_probe(struct wlan_objmgr_vdev *vdev, uint8_t *bcn_probe,
|
|
|
struct mgmt_rx_event_params rx_param = {0};
|
|
|
struct wlan_frame_hdr *hdr;
|
|
|
enum mgmt_frame_type frm_type = MGMT_BEACON;
|
|
|
+ QDF_STATUS status = QDF_STATUS_SUCCESS;
|
|
|
|
|
|
vdev_id = wlan_vdev_get_id(vdev);
|
|
|
if (!bcn_probe || !len || (len < sizeof(*hdr))) {
|
|
|
pe_err("bcn_probe is null or invalid len %d",
|
|
|
len);
|
|
|
- return;
|
|
|
+ return QDF_STATUS_E_FAILURE;
|
|
|
}
|
|
|
|
|
|
pdev = wlan_vdev_get_pdev(vdev);
|
|
|
if (!pdev) {
|
|
|
pe_err("Failed to find pdev");
|
|
|
- return;
|
|
|
+ return QDF_STATUS_E_FAILURE;
|
|
|
}
|
|
|
|
|
|
hdr = (struct wlan_frame_hdr *)bcn_probe;
|
|
@@ -3723,7 +3724,7 @@ lim_add_bcn_probe(struct wlan_objmgr_vdev *vdev, uint8_t *bcn_probe,
|
|
|
|
|
|
buf = qdf_nbuf_alloc(NULL, qdf_roundup(len, 4), 0, 4, false);
|
|
|
if (!buf)
|
|
|
- return;
|
|
|
+ return QDF_STATUS_E_FAILURE;
|
|
|
|
|
|
qdf_nbuf_put_tail(buf, len);
|
|
|
qdf_nbuf_set_protocol(buf, ETH_P_CONTROL);
|
|
@@ -3733,8 +3734,10 @@ lim_add_bcn_probe(struct wlan_objmgr_vdev *vdev, uint8_t *bcn_probe,
|
|
|
|
|
|
pe_debug("MLO: add prb rsp to scan db");
|
|
|
/* buf will be freed by scan module in error or success case */
|
|
|
- wlan_scan_process_bcn_probe_rx_sync(wlan_pdev_get_psoc(pdev), buf,
|
|
|
- &rx_param, frm_type);
|
|
|
+ status = wlan_scan_process_bcn_probe_rx_sync(wlan_pdev_get_psoc(pdev), buf,
|
|
|
+ &rx_param, frm_type);
|
|
|
+
|
|
|
+ return status;
|
|
|
}
|
|
|
|
|
|
#ifdef WLAN_FEATURE_11BE_MLO
|
|
@@ -3819,11 +3822,139 @@ lim_clear_ml_partner_info(struct pe_session *session_entry)
|
|
|
}
|
|
|
partner_info->num_partner_links = 0;
|
|
|
}
|
|
|
+
|
|
|
+static QDF_STATUS
|
|
|
+lim_compare_scan_entry_partner_info_with_join_req(struct mlo_partner_info
|
|
|
+ *partner_info,
|
|
|
+ struct partner_link_info
|
|
|
+ *partner_link)
|
|
|
+{
|
|
|
+ int i;
|
|
|
+ int j;
|
|
|
+ struct mlo_link_info *partner_link_info;
|
|
|
+ struct partner_link_info *scan_info;
|
|
|
+ int num_matching_links = 0;
|
|
|
+ QDF_STATUS status = QDF_STATUS_E_FAILURE;
|
|
|
+
|
|
|
+ for (i = 0; i < WLAN_UMAC_MLO_MAX_VDEVS; i++) {
|
|
|
+ partner_link_info = &partner_info->partner_link_info[i];
|
|
|
+ for (j = 0; j < MLD_MAX_LINKS - 1; j++) {
|
|
|
+ scan_info = &partner_link[j];
|
|
|
+ if (!scan_info)
|
|
|
+ continue;
|
|
|
+ /*
|
|
|
+ * do not compare if both have freq as zero
|
|
|
+ */
|
|
|
+ if (scan_info->freq == 0)
|
|
|
+ continue;
|
|
|
+
|
|
|
+ if (scan_info->freq == partner_link_info->chan_freq) {
|
|
|
+ qdf_mem_cmp(partner_link_info->link_addr.bytes,
|
|
|
+ scan_info->link_addr.bytes,
|
|
|
+ QDF_MAC_ADDR_SIZE);
|
|
|
+ num_matching_links += 1;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ if (partner_info->num_partner_links == num_matching_links) {
|
|
|
+ pe_debug("num of matching partner links %d",
|
|
|
+ num_matching_links);
|
|
|
+ status = QDF_STATUS_SUCCESS;
|
|
|
+ }
|
|
|
+
|
|
|
+ return status;
|
|
|
+}
|
|
|
+
|
|
|
+static QDF_STATUS
|
|
|
+lim_check_scan_db_for_join_req_partner_info(struct pe_session *session_entry,
|
|
|
+ struct mac_context *mac_ctx)
|
|
|
+{
|
|
|
+ struct join_req *lim_join_req;
|
|
|
+ struct wlan_objmgr_pdev *pdev;
|
|
|
+ struct partner_link_info *partner_link = NULL;
|
|
|
+ struct qdf_mac_addr qdf_bssid;
|
|
|
+ QDF_STATUS status = QDF_STATUS_E_FAILURE;
|
|
|
+ struct mlo_partner_info *partner_info;
|
|
|
+ uint16_t join_req_freq = 0;
|
|
|
+ struct scan_cache_entry cache_entry;
|
|
|
+
|
|
|
+ if (!session_entry) {
|
|
|
+ pe_err("session entry is NULL");
|
|
|
+ return QDF_STATUS_E_NULL_VALUE;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (!mac_ctx) {
|
|
|
+ pe_err("mac context is NULL");
|
|
|
+ return QDF_STATUS_E_NULL_VALUE;
|
|
|
+ }
|
|
|
+
|
|
|
+ lim_join_req = session_entry->lim_join_req;
|
|
|
+ if (!lim_join_req) {
|
|
|
+ pe_err("join req is NULL");
|
|
|
+ return QDF_STATUS_E_NULL_VALUE;
|
|
|
+ }
|
|
|
+
|
|
|
+ pdev = mac_ctx->pdev;
|
|
|
+ if (!pdev) {
|
|
|
+ pe_err("pdev is NULL");
|
|
|
+ return QDF_STATUS_E_NULL_VALUE;
|
|
|
+ }
|
|
|
+
|
|
|
+ partner_link = qdf_mem_malloc(sizeof(struct partner_link_info) *
|
|
|
+ (MLD_MAX_LINKS - 1));
|
|
|
+
|
|
|
+ if (!partner_link)
|
|
|
+ return QDF_STATUS_E_FAILURE;
|
|
|
+
|
|
|
+ qdf_mem_copy(&qdf_bssid,
|
|
|
+ &(lim_join_req->bssDescription.bssId),
|
|
|
+ QDF_MAC_ADDR_SIZE);
|
|
|
+
|
|
|
+ join_req_freq = lim_join_req->bssDescription.chan_freq;
|
|
|
+
|
|
|
+ status = wlan_scan_get_scan_entry_by_mac_freq(pdev,
|
|
|
+ &qdf_bssid,
|
|
|
+ join_req_freq,
|
|
|
+ &cache_entry);
|
|
|
+
|
|
|
+ if (!QDF_IS_STATUS_SUCCESS(status)) {
|
|
|
+ pe_err("failed to get partner link info by mac addr");
|
|
|
+ status = QDF_STATUS_E_FAILURE;
|
|
|
+ goto free_mem;
|
|
|
+ }
|
|
|
+
|
|
|
+ qdf_mem_copy(partner_link, cache_entry.ml_info.link_info,
|
|
|
+ sizeof(struct partner_link_info) * (MLD_MAX_LINKS - 1));
|
|
|
+
|
|
|
+ partner_info = &lim_join_req->partner_info;
|
|
|
+
|
|
|
+ status = lim_compare_scan_entry_partner_info_with_join_req(
|
|
|
+ partner_info, partner_link);
|
|
|
+
|
|
|
+ if (!QDF_IS_STATUS_SUCCESS(status)) {
|
|
|
+ pe_err("failed to match num of partner links in scan entry");
|
|
|
+ status = QDF_STATUS_E_FAILURE;
|
|
|
+ goto free_mem;
|
|
|
+ }
|
|
|
+
|
|
|
+free_mem:
|
|
|
+ qdf_mem_free(partner_link);
|
|
|
+ return status;
|
|
|
+}
|
|
|
#else
|
|
|
static inline void
|
|
|
lim_clear_ml_partner_info(struct pe_session *session_entry)
|
|
|
{
|
|
|
}
|
|
|
+
|
|
|
+static QDF_STATUS
|
|
|
+lim_check_db_for_join_req_partner_info(struct pe_session *session_entry,
|
|
|
+ struct mac_context *mac_ctx)
|
|
|
+{
|
|
|
+
|
|
|
+ return QDF_STATUS_E_FAILURE;
|
|
|
+}
|
|
|
#endif
|
|
|
|
|
|
QDF_STATUS lim_check_for_ml_probe_req(struct pe_session *session)
|
|
@@ -3847,7 +3978,7 @@ lim_gen_link_specific_probe_rsp(struct mac_context *mac_ctx,
|
|
|
{
|
|
|
struct element_info link_probe_rsp = {0};
|
|
|
struct qdf_mac_addr sta_link_addr;
|
|
|
- QDF_STATUS status = QDF_STATUS_SUCCESS;
|
|
|
+ QDF_STATUS status = QDF_STATUS_E_FAILURE;
|
|
|
struct mlo_link_info *link_info = NULL;
|
|
|
struct mlo_partner_info *partner_info;
|
|
|
uint8_t chan;
|
|
@@ -3876,8 +4007,12 @@ lim_gen_link_specific_probe_rsp(struct mac_context *mac_ctx,
|
|
|
probe_rsp_len);
|
|
|
|
|
|
if (QDF_IS_STATUS_ERROR(status)) {
|
|
|
- lim_clear_ml_partner_info(session_entry);
|
|
|
- goto end;
|
|
|
+ if(QDF_IS_STATUS_ERROR(
|
|
|
+ lim_check_scan_db_for_join_req_partner_info(
|
|
|
+ session_entry,
|
|
|
+ mac_ctx)))
|
|
|
+ lim_clear_ml_partner_info(session_entry);
|
|
|
+ return status;
|
|
|
}
|
|
|
|
|
|
/*
|
|
@@ -3896,8 +4031,14 @@ lim_gen_link_specific_probe_rsp(struct mac_context *mac_ctx,
|
|
|
gen_frame_len = MAX_MGMT_MPDU_LEN;
|
|
|
|
|
|
link_probe_rsp.ptr = qdf_mem_malloc(gen_frame_len);
|
|
|
- if (!link_probe_rsp.ptr)
|
|
|
+ if (!link_probe_rsp.ptr) {
|
|
|
+ if(QDF_IS_STATUS_ERROR(
|
|
|
+ lim_check_scan_db_for_join_req_partner_info(
|
|
|
+ session_entry,
|
|
|
+ mac_ctx)))
|
|
|
+ lim_clear_ml_partner_info(session_entry);
|
|
|
return QDF_STATUS_E_NOMEM;
|
|
|
+ }
|
|
|
|
|
|
qdf_mem_copy(&sta_link_addr, session_entry->self_mac_addr,
|
|
|
QDF_MAC_ADDR_SIZE);
|
|
@@ -3909,11 +4050,17 @@ lim_gen_link_specific_probe_rsp(struct mac_context *mac_ctx,
|
|
|
(qdf_size_t *)&link_probe_rsp.len);
|
|
|
|
|
|
if (QDF_IS_STATUS_ERROR(status)) {
|
|
|
- pe_err("MLO: Link probe response generation failed %d", status);
|
|
|
- lim_clear_ml_partner_info(session_entry);
|
|
|
- status = QDF_STATUS_E_FAILURE;
|
|
|
+ pe_err("MLO: Link probe response generation failed %d",
|
|
|
+ status);
|
|
|
+ if(QDF_IS_STATUS_ERROR(
|
|
|
+ lim_check_scan_db_for_join_req_partner_info(
|
|
|
+ session_entry,
|
|
|
+ mac_ctx)))
|
|
|
+ lim_clear_ml_partner_info(session_entry);
|
|
|
+
|
|
|
goto end;
|
|
|
}
|
|
|
+
|
|
|
pe_debug("MLO: link probe rsp size:%u original probe rsp :%u",
|
|
|
link_probe_rsp.len, probe_rsp_len);
|
|
|
|
|
@@ -3932,15 +4079,41 @@ lim_gen_link_specific_probe_rsp(struct mac_context *mac_ctx,
|
|
|
pe_err("Invalid link id %d link mac: " QDF_MAC_ADDR_FMT,
|
|
|
link_info->link_id,
|
|
|
QDF_MAC_ADDR_REF(link_info->link_addr.bytes));
|
|
|
+ if(QDF_IS_STATUS_ERROR(
|
|
|
+ lim_check_scan_db_for_join_req_partner_info(
|
|
|
+ session_entry,
|
|
|
+ mac_ctx)))
|
|
|
+ lim_clear_ml_partner_info(session_entry);
|
|
|
+
|
|
|
status = QDF_STATUS_E_FAILURE;
|
|
|
goto end;
|
|
|
}
|
|
|
chan_freq = wlan_reg_chan_opclass_to_freq(chan, op_class,
|
|
|
true);
|
|
|
|
|
|
- lim_add_bcn_probe(session_entry->vdev, link_probe_rsp.ptr,
|
|
|
- link_probe_rsp.len,
|
|
|
- chan_freq, rssi);
|
|
|
+ status = lim_add_bcn_probe(session_entry->vdev,
|
|
|
+ link_probe_rsp.ptr,
|
|
|
+ link_probe_rsp.len,
|
|
|
+ chan_freq, rssi);
|
|
|
+ if (QDF_IS_STATUS_ERROR(status)) {
|
|
|
+ pe_err("failed to add bcn probe %d", status);
|
|
|
+ if(QDF_IS_STATUS_ERROR(
|
|
|
+ lim_check_scan_db_for_join_req_partner_info(
|
|
|
+ session_entry,
|
|
|
+ mac_ctx)))
|
|
|
+ lim_clear_ml_partner_info(session_entry);
|
|
|
+
|
|
|
+ goto end;
|
|
|
+ }
|
|
|
+ } else if (session_entry->lim_join_req->is_ml_probe_req_sent &&
|
|
|
+ !rcvd_probe_resp->mlo_ie.mlo_ie_present) {
|
|
|
+ if(QDF_IS_STATUS_ERROR(lim_check_scan_db_for_join_req_partner_info(
|
|
|
+ session_entry,
|
|
|
+ mac_ctx)))
|
|
|
+ lim_clear_ml_partner_info(session_entry);
|
|
|
+
|
|
|
+ status = QDF_STATUS_E_FAILURE;
|
|
|
+ return status;
|
|
|
} else {
|
|
|
return status;
|
|
|
}
|