|
@@ -1,5 +1,6 @@
|
|
|
/*
|
|
|
* Copyright (c) 2017-2020 The Linux Foundation. All rights reserved.
|
|
|
+ * Copyright (c) 2023 Qualcomm Innovation Center, Inc. All rights reserved.
|
|
|
*
|
|
|
* Permission to use, copy, modify, and/or distribute this software for
|
|
|
* any purpose with or without fee is hereby granted, provided that the
|
|
@@ -30,6 +31,9 @@
|
|
|
#include "wlan_tdls_ct.h"
|
|
|
#include "wlan_tdls_cmds_process.h"
|
|
|
#include "wlan_tdls_mgmt.h"
|
|
|
+#include "wlan_policy_mgr_api.h"
|
|
|
+#include <wlan_reg_services_api.h>
|
|
|
+#include <wlan_mlo_mgr_sta.h>
|
|
|
|
|
|
static
|
|
|
const char *const tdls_action_frames_type[] = { "TDLS Setup Request",
|
|
@@ -77,6 +81,347 @@ QDF_STATUS tdls_set_rssi(struct wlan_objmgr_vdev *vdev,
|
|
|
return QDF_STATUS_SUCCESS;
|
|
|
}
|
|
|
|
|
|
+#ifdef WLAN_FEATURE_11BE_MLO
|
|
|
+struct wlan_objmgr_vdev *
|
|
|
+tdls_mlo_get_tdls_link_vdev(struct wlan_objmgr_vdev *vdev)
|
|
|
+{
|
|
|
+ return wlan_mlo_get_tdls_link_vdev(vdev);
|
|
|
+}
|
|
|
+
|
|
|
+QDF_STATUS
|
|
|
+tdls_process_mlo_cal_tdls_link_score(struct wlan_objmgr_vdev *vdev)
|
|
|
+{
|
|
|
+ struct wlan_mlo_dev_context *mlo_dev_ctx;
|
|
|
+ struct wlan_objmgr_vdev *mlo_vdev;
|
|
|
+ struct tdls_vdev_priv_obj *tdls_vdev;
|
|
|
+ struct tdls_rx_mgmt_frame *rx_mgmt;
|
|
|
+ uint32_t score;
|
|
|
+ int i;
|
|
|
+ QDF_STATUS status = QDF_STATUS_E_FAILURE;
|
|
|
+
|
|
|
+ mlo_dev_ctx = vdev->mlo_dev_ctx;
|
|
|
+ for (i = 0; i < WLAN_UMAC_MLO_MAX_VDEVS; i++) {
|
|
|
+ score = 0;
|
|
|
+ mlo_vdev = mlo_dev_ctx->wlan_vdev_list[i];
|
|
|
+ if (!mlo_vdev)
|
|
|
+ continue;
|
|
|
+ tdls_vdev =
|
|
|
+ wlan_objmgr_vdev_get_comp_private_obj(mlo_vdev,
|
|
|
+ WLAN_UMAC_COMP_TDLS);
|
|
|
+ tdls_vdev->link_score = 0;
|
|
|
+ rx_mgmt = tdls_vdev->rx_mgmt;
|
|
|
+ if (!rx_mgmt)
|
|
|
+ continue;
|
|
|
+
|
|
|
+ switch (wlan_reg_freq_to_band(rx_mgmt->rx_freq)) {
|
|
|
+ case REG_BAND_2G:
|
|
|
+ score += 50;
|
|
|
+ break;
|
|
|
+ case REG_BAND_5G:
|
|
|
+ score += 70;
|
|
|
+ break;
|
|
|
+ case REG_BAND_6G:
|
|
|
+ score += 80;
|
|
|
+ break;
|
|
|
+ default:
|
|
|
+ score += 40;
|
|
|
+ break;
|
|
|
+ }
|
|
|
+
|
|
|
+ tdls_vdev->link_score = score;
|
|
|
+ status = QDF_STATUS_SUCCESS;
|
|
|
+ }
|
|
|
+
|
|
|
+ return status;
|
|
|
+}
|
|
|
+
|
|
|
+struct wlan_objmgr_vdev *
|
|
|
+tdls_process_mlo_choice_tdls_vdev(struct wlan_objmgr_vdev *vdev)
|
|
|
+{
|
|
|
+ struct wlan_mlo_dev_context *mlo_dev_ctx;
|
|
|
+ struct wlan_objmgr_vdev *mlo_vdev;
|
|
|
+ struct wlan_objmgr_vdev *select_vdev = NULL;
|
|
|
+ struct tdls_vdev_priv_obj *tdls_vdev;
|
|
|
+ uint32_t score = 0;
|
|
|
+ int i;
|
|
|
+
|
|
|
+ mlo_dev_ctx = vdev->mlo_dev_ctx;
|
|
|
+ for (i = 0; i < WLAN_UMAC_MLO_MAX_VDEVS; i++) {
|
|
|
+ mlo_vdev = mlo_dev_ctx->wlan_vdev_list[i];
|
|
|
+ if (!mlo_vdev)
|
|
|
+ continue;
|
|
|
+ tdls_vdev =
|
|
|
+ wlan_objmgr_vdev_get_comp_private_obj(mlo_vdev,
|
|
|
+ WLAN_UMAC_COMP_TDLS);
|
|
|
+ if (score < tdls_vdev->link_score) {
|
|
|
+ select_vdev = mlo_vdev;
|
|
|
+ score = tdls_vdev->link_score;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /* free the memory except the choice one */
|
|
|
+ for (i = 0; i < WLAN_UMAC_MLO_MAX_VDEVS; i++) {
|
|
|
+ mlo_vdev = mlo_dev_ctx->wlan_vdev_list[i];
|
|
|
+ if (!mlo_vdev || mlo_vdev == select_vdev)
|
|
|
+ continue;
|
|
|
+
|
|
|
+ tdls_vdev =
|
|
|
+ wlan_objmgr_vdev_get_comp_private_obj(mlo_vdev,
|
|
|
+ WLAN_UMAC_COMP_TDLS);
|
|
|
+ qdf_mem_free(tdls_vdev->rx_mgmt);
|
|
|
+ tdls_vdev->rx_mgmt = NULL;
|
|
|
+ tdls_vdev->link_score = 0;
|
|
|
+ }
|
|
|
+
|
|
|
+ return select_vdev;
|
|
|
+}
|
|
|
+
|
|
|
+static struct tdls_vdev_priv_obj
|
|
|
+*tdls_get_correct_vdev(struct tdls_vdev_priv_obj *tdls_vdev,
|
|
|
+ struct tdls_rx_mgmt_frame *rx_mgmt)
|
|
|
+{
|
|
|
+ struct wlan_objmgr_pdev *pdev;
|
|
|
+ struct wlan_objmgr_vdev *vdev;
|
|
|
+ struct tdls_link_identifier *linkid_ie;
|
|
|
+ uint8_t vdev_id;
|
|
|
+ uint8_t *ies;
|
|
|
+ uint32_t ie_len;
|
|
|
+ uint8_t elem_id_param = WLAN_ELEMID_LINK_IDENTIFIER;
|
|
|
+
|
|
|
+ if (!tdls_vdev || !rx_mgmt)
|
|
|
+ return NULL;
|
|
|
+
|
|
|
+ ies = &rx_mgmt->buf[TDLS_PUBLIC_ACTION_FRAME_TDLS_IE_OFFSET];
|
|
|
+ ie_len = rx_mgmt->frame_len - TDLS_PUBLIC_ACTION_FRAME_TDLS_IE_OFFSET;
|
|
|
+
|
|
|
+ linkid_ie =
|
|
|
+ (struct tdls_link_identifier *)wlan_get_ie_ptr_from_eid(elem_id_param,
|
|
|
+ ies, ie_len);
|
|
|
+ if (!linkid_ie)
|
|
|
+ return tdls_vdev;
|
|
|
+
|
|
|
+ pdev = wlan_vdev_get_pdev(tdls_vdev->vdev);
|
|
|
+ if (!pdev)
|
|
|
+ return tdls_vdev;
|
|
|
+
|
|
|
+ if (!wlan_get_connected_vdev_by_bssid(pdev,
|
|
|
+ linkid_ie->bssid, &vdev_id))
|
|
|
+ return tdls_vdev;
|
|
|
+
|
|
|
+ vdev = wlan_objmgr_get_vdev_by_id_from_pdev(pdev, vdev_id,
|
|
|
+ WLAN_TDLS_NB_ID);
|
|
|
+ if (!vdev)
|
|
|
+ return tdls_vdev;
|
|
|
+
|
|
|
+ tdls_vdev = wlan_objmgr_vdev_get_comp_private_obj(vdev,
|
|
|
+ WLAN_UMAC_COMP_TDLS);
|
|
|
+ rx_mgmt->vdev_id = vdev_id;
|
|
|
+
|
|
|
+ wlan_objmgr_vdev_release_ref(vdev, WLAN_TDLS_NB_ID);
|
|
|
+ tdls_debug("received discovery response on vdev %d", rx_mgmt->vdev_id);
|
|
|
+
|
|
|
+ return tdls_vdev;
|
|
|
+}
|
|
|
+
|
|
|
+static bool tdls_check_peer_mlo_dev(struct wlan_objmgr_vdev *vdev,
|
|
|
+ struct tdls_rx_mgmt_frame *rx_mgmt)
|
|
|
+{
|
|
|
+ uint8_t *ies;
|
|
|
+ const uint8_t *ie;
|
|
|
+ uint32_t ie_len;
|
|
|
+ const uint8_t ext_id_param = WLAN_EXTN_ELEMID_MULTI_LINK;
|
|
|
+ uint8_t elem_id_param = WLAN_ELEMID_LINK_IDENTIFIER;
|
|
|
+
|
|
|
+ if (!vdev || !rx_mgmt)
|
|
|
+ return QDF_STATUS_E_INVAL;
|
|
|
+
|
|
|
+ ies = &rx_mgmt->buf[TDLS_PUBLIC_ACTION_FRAME_TDLS_IE_OFFSET];
|
|
|
+ ie_len = rx_mgmt->frame_len - TDLS_PUBLIC_ACTION_FRAME_TDLS_IE_OFFSET;
|
|
|
+
|
|
|
+ ie = wlan_get_ie_ptr_from_eid(elem_id_param, ies, ie_len);
|
|
|
+ if (ie)
|
|
|
+ qdf_trace_hex_dump(QDF_MODULE_ID_TDLS, QDF_TRACE_LEVEL_DEBUG,
|
|
|
+ (void *)&ie[0], ie[1] + 2);
|
|
|
+
|
|
|
+ ie = wlan_get_ext_ie_ptr_from_ext_id(&ext_id_param,
|
|
|
+ 1, ies, ie_len);
|
|
|
+ if (ie)
|
|
|
+ return true;
|
|
|
+
|
|
|
+ return false;
|
|
|
+}
|
|
|
+
|
|
|
+static QDF_STATUS
|
|
|
+tdls_process_mlo_rx_mgmt_sync(struct tdls_soc_priv_obj *tdls_soc,
|
|
|
+ struct tdls_vdev_priv_obj *tdls_vdev,
|
|
|
+ struct tdls_rx_mgmt_frame *rx_mgmt)
|
|
|
+{
|
|
|
+ QDF_STATUS status;
|
|
|
+ struct wlan_objmgr_vdev *vdev;
|
|
|
+ struct wlan_objmgr_vdev *mlo_vdev;
|
|
|
+ struct wlan_mlo_dev_context *mlo_dev_ctx;
|
|
|
+ bool peer_mlo;
|
|
|
+ uint8_t i;
|
|
|
+
|
|
|
+ vdev = tdls_vdev->vdev;
|
|
|
+ peer_mlo = tdls_check_peer_mlo_dev(vdev, rx_mgmt);
|
|
|
+ if (!peer_mlo) {
|
|
|
+ mlo_dev_ctx = vdev->mlo_dev_ctx;
|
|
|
+ /* stop all timers */
|
|
|
+ for (i = 0; i < WLAN_UMAC_MLO_MAX_VDEVS; i++) {
|
|
|
+ mlo_vdev = mlo_dev_ctx->wlan_vdev_list[i];
|
|
|
+ if (!mlo_vdev)
|
|
|
+ continue;
|
|
|
+
|
|
|
+ tdls_vdev =
|
|
|
+ wlan_objmgr_vdev_get_comp_private_obj(mlo_vdev,
|
|
|
+ WLAN_UMAC_COMP_TDLS);
|
|
|
+ tdls_vdev->discovery_sent_cnt = 0;
|
|
|
+ if (QDF_TIMER_STATE_RUNNING ==
|
|
|
+ qdf_mc_timer_get_current_state(
|
|
|
+ &tdls_vdev->peer_discovery_timer)) {
|
|
|
+ qdf_mc_timer_stop(
|
|
|
+ &tdls_vdev->peer_discovery_timer);
|
|
|
+ qdf_atomic_dec(&tdls_soc->timer_cnt);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ tdls_debug("peer is legacy device, timer_cnt %d",
|
|
|
+ qdf_atomic_read(&tdls_soc->timer_cnt));
|
|
|
+
|
|
|
+ status = QDF_STATUS_E_INVAL;
|
|
|
+ } else {
|
|
|
+ tdls_debug("peer is mlo device, timer_cnt %d",
|
|
|
+ qdf_atomic_read(&tdls_soc->timer_cnt));
|
|
|
+
|
|
|
+ /* If peer is MLD, it uses ml mac address to send the
|
|
|
+ * disconvery response, it needs to find out the
|
|
|
+ * corresponding vdev per the bssid in link identifier ie.
|
|
|
+ */
|
|
|
+ tdls_vdev = tdls_get_correct_vdev(tdls_vdev, rx_mgmt);
|
|
|
+ status = QDF_STATUS_TDLS_MLO_SYNC;
|
|
|
+ if (!tdls_vdev || tdls_vdev->rx_mgmt) {
|
|
|
+ tdls_err("rx dup tdls discovery resp on same vdev.");
|
|
|
+ goto exit;
|
|
|
+ }
|
|
|
+
|
|
|
+ tdls_vdev->discovery_sent_cnt = 0;
|
|
|
+ qdf_mc_timer_stop(&tdls_vdev->peer_discovery_timer);
|
|
|
+ qdf_atomic_dec(&tdls_soc->timer_cnt);
|
|
|
+
|
|
|
+ tdls_vdev->rx_mgmt = qdf_mem_malloc_atomic(sizeof(*rx_mgmt) +
|
|
|
+ rx_mgmt->frame_len);
|
|
|
+ if (tdls_vdev->rx_mgmt) {
|
|
|
+ tdls_vdev->rx_mgmt->frame_len = rx_mgmt->frame_len;
|
|
|
+ tdls_vdev->rx_mgmt->rx_freq = rx_mgmt->rx_freq;
|
|
|
+ tdls_vdev->rx_mgmt->vdev_id = rx_mgmt->vdev_id;
|
|
|
+ tdls_vdev->rx_mgmt->frm_type = rx_mgmt->frm_type;
|
|
|
+ tdls_vdev->rx_mgmt->rx_rssi = rx_mgmt->rx_rssi;
|
|
|
+ qdf_mem_copy(tdls_vdev->rx_mgmt->buf,
|
|
|
+ rx_mgmt->buf, rx_mgmt->frame_len);
|
|
|
+ } else {
|
|
|
+ tdls_err("alloc rx mgmt buf error");
|
|
|
+ }
|
|
|
+
|
|
|
+ if (qdf_atomic_read(&tdls_soc->timer_cnt) == 0) {
|
|
|
+ tdls_process_mlo_cal_tdls_link_score(vdev);
|
|
|
+ status = QDF_STATUS_SUCCESS;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+exit:
|
|
|
+ return status;
|
|
|
+}
|
|
|
+
|
|
|
+void tdls_set_no_force_vdev(struct wlan_objmgr_vdev *vdev, bool flag)
|
|
|
+{
|
|
|
+ uint8_t i, count = 0;
|
|
|
+ struct wlan_objmgr_psoc *psoc;
|
|
|
+ struct wlan_objmgr_vdev *mlo_vdev;
|
|
|
+ struct wlan_mlo_dev_context *mlo_dev_ctx;
|
|
|
+ uint8_t mlo_vdev_lst[WLAN_UMAC_MLO_MAX_VDEVS];
|
|
|
+ bool is_mlo_vdev;
|
|
|
+
|
|
|
+ if (!vdev)
|
|
|
+ return;
|
|
|
+
|
|
|
+ is_mlo_vdev = wlan_vdev_mlme_is_mlo_vdev(vdev);
|
|
|
+ if (!is_mlo_vdev)
|
|
|
+ return;
|
|
|
+
|
|
|
+ psoc = wlan_vdev_get_psoc(vdev);
|
|
|
+ if (!psoc)
|
|
|
+ return;
|
|
|
+
|
|
|
+ mlo_dev_ctx = vdev->mlo_dev_ctx;
|
|
|
+ for (i = 0; i < WLAN_UMAC_MLO_MAX_VDEVS; i++) {
|
|
|
+ mlo_vdev = mlo_dev_ctx->wlan_vdev_list[i];
|
|
|
+
|
|
|
+ /* flag: true means no force all vdevs,
|
|
|
+ * false means except the current one
|
|
|
+ */
|
|
|
+ if (!flag && (mlo_vdev == vdev))
|
|
|
+ continue;
|
|
|
+ mlo_vdev_lst[count] = wlan_vdev_get_id(mlo_vdev);
|
|
|
+ count++;
|
|
|
+ }
|
|
|
+
|
|
|
+ policy_mgr_mlo_sta_set_link(psoc, MLO_LINK_FORCE_REASON_TDLS,
|
|
|
+ MLO_LINK_FORCE_MODE_NO_FORCE,
|
|
|
+ count, mlo_vdev_lst);
|
|
|
+}
|
|
|
+#else
|
|
|
+struct wlan_objmgr_vdev *
|
|
|
+tdls_mlo_get_tdls_link_vdev(struct wlan_objmgr_vdev *vdev)
|
|
|
+{
|
|
|
+ return NULL;
|
|
|
+}
|
|
|
+
|
|
|
+QDF_STATUS
|
|
|
+tdls_process_mlo_cal_tdls_link_score(struct wlan_objmgr_vdev *vdev)
|
|
|
+{
|
|
|
+ return QDF_STATUS_SUCCESS;
|
|
|
+}
|
|
|
+
|
|
|
+struct wlan_objmgr_vdev *
|
|
|
+tdls_process_mlo_choice_tdls_vdev(struct wlan_objmgr_vdev *vdev)
|
|
|
+{
|
|
|
+ return NULL;
|
|
|
+}
|
|
|
+
|
|
|
+static struct tdls_vdev_priv_obj
|
|
|
+*tdls_get_correct_vdev(struct tdls_vdev_priv_obj *tdls_vdev,
|
|
|
+ struct tdls_rx_mgmt_frame *rx_mgmt)
|
|
|
+{
|
|
|
+ return NULL;
|
|
|
+}
|
|
|
+
|
|
|
+static QDF_STATUS
|
|
|
+tdls_process_mlo_rx_mgmt_sync(struct tdls_soc_priv_obj *tdls_soc,
|
|
|
+ struct tdls_vdev_priv_obj *tdls_vdev,
|
|
|
+ struct tdls_rx_mgmt_frame *rx_mgmt)
|
|
|
+{
|
|
|
+ return QDF_STATUS_SUCCESS;
|
|
|
+}
|
|
|
+
|
|
|
+void tdls_set_no_force_vdev(struct wlan_objmgr_vdev *vdev, bool flag)
|
|
|
+{
|
|
|
+}
|
|
|
+#endif
|
|
|
+
|
|
|
+static bool
|
|
|
+tdls_needs_wait_discovery_response(struct wlan_objmgr_vdev *vdev,
|
|
|
+ struct tdls_soc_priv_obj *tdls_soc)
|
|
|
+{
|
|
|
+ bool is_mlo_vdev;
|
|
|
+ bool wait = false;
|
|
|
+
|
|
|
+ is_mlo_vdev = wlan_vdev_mlme_is_mlo_vdev(vdev);
|
|
|
+ if (is_mlo_vdev && qdf_atomic_read(&tdls_soc->timer_cnt))
|
|
|
+ wait = true;
|
|
|
+
|
|
|
+ return wait;
|
|
|
+}
|
|
|
+
|
|
|
/**
|
|
|
* tdls_process_rx_mgmt() - process tdls rx mgmt frames
|
|
|
* @rx_mgmt_event: tdls rx mgmt event
|
|
@@ -92,6 +437,10 @@ static QDF_STATUS tdls_process_rx_mgmt(
|
|
|
struct tdls_soc_priv_obj *tdls_soc_obj;
|
|
|
uint8_t *mac;
|
|
|
enum tdls_actioncode action_frame_type;
|
|
|
+ struct wlan_objmgr_vdev *vdev;
|
|
|
+ struct wlan_objmgr_vdev *tdls_link_vdev;
|
|
|
+ bool tdls_vdev_select = false;
|
|
|
+ QDF_STATUS status = QDF_STATUS_E_INVAL;
|
|
|
|
|
|
if (!rx_mgmt_event)
|
|
|
return QDF_STATUS_E_INVAL;
|
|
@@ -104,19 +453,66 @@ static QDF_STATUS tdls_process_rx_mgmt(
|
|
|
return QDF_STATUS_E_INVAL;
|
|
|
}
|
|
|
|
|
|
+ vdev = tdls_vdev->vdev;
|
|
|
+ tdls_debug("received mgmt on vdev %d", wlan_vdev_get_id(vdev));
|
|
|
tdls_debug("soc:%pK, frame_len:%d, rx_freq:%d, vdev_id:%d, frm_type:%d, rx_rssi:%d, buf:%pK",
|
|
|
tdls_soc_obj->soc, rx_mgmt->frame_len,
|
|
|
rx_mgmt->rx_freq, rx_mgmt->vdev_id, rx_mgmt->frm_type,
|
|
|
rx_mgmt->rx_rssi, rx_mgmt->buf);
|
|
|
|
|
|
if (rx_mgmt->buf[TDLS_PUBLIC_ACTION_FRAME_OFFSET + 1] ==
|
|
|
- TDLS_PUBLIC_ACTION_DISC_RESP) {
|
|
|
+ TDLS_PUBLIC_ACTION_DISC_RESP) {
|
|
|
+ if (tdls_needs_wait_discovery_response(vdev, tdls_soc_obj)) {
|
|
|
+ status = tdls_process_mlo_rx_mgmt_sync(tdls_soc_obj,
|
|
|
+ tdls_vdev,
|
|
|
+ rx_mgmt);
|
|
|
+ if (status == QDF_STATUS_TDLS_MLO_SYNC) {
|
|
|
+ return QDF_STATUS_SUCCESS;
|
|
|
+ } else if (status == QDF_STATUS_SUCCESS) {
|
|
|
+ vdev = tdls_process_mlo_choice_tdls_vdev(vdev);
|
|
|
+ tdls_vdev =
|
|
|
+ wlan_objmgr_vdev_get_comp_private_obj(vdev,
|
|
|
+ WLAN_UMAC_COMP_TDLS);
|
|
|
+ rx_mgmt = tdls_vdev->rx_mgmt;
|
|
|
+ tdls_vdev_select = true;
|
|
|
+ tdls_debug("choice vdev %d as tdls vdev",
|
|
|
+ wlan_vdev_get_id(vdev));
|
|
|
+ } else {
|
|
|
+ tdls_vdev = tdls_get_correct_vdev(tdls_vdev,
|
|
|
+ rx_mgmt);
|
|
|
+ if (!tdls_vdev)
|
|
|
+ return QDF_STATUS_SUCCESS;
|
|
|
+ vdev = tdls_vdev->vdev;
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ if (wlan_vdev_mlme_is_mlo_vdev(vdev)) {
|
|
|
+ tdls_link_vdev =
|
|
|
+ tdls_mlo_get_tdls_link_vdev(vdev);
|
|
|
+ tdls_vdev =
|
|
|
+ tdls_get_correct_vdev(tdls_vdev, rx_mgmt);
|
|
|
+ if (!tdls_link_vdev || !tdls_vdev) {
|
|
|
+ tdls_debug("not expected frame");
|
|
|
+ return QDF_STATUS_SUCCESS;
|
|
|
+ }
|
|
|
+ if (tdls_link_vdev != tdls_vdev->vdev) {
|
|
|
+ tdls_debug("not forward to userspace");
|
|
|
+ return QDF_STATUS_SUCCESS;
|
|
|
+ }
|
|
|
+ rx_mgmt->vdev_id =
|
|
|
+ wlan_vdev_get_id(tdls_link_vdev);
|
|
|
+ vdev = tdls_link_vdev;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /* this is mld mac address for mlo case*/
|
|
|
mac = &rx_mgmt->buf[TDLS_80211_PEER_ADDR_OFFSET];
|
|
|
tdls_notice("[TDLS] TDLS Discovery Response,"
|
|
|
- QDF_MAC_ADDR_FMT " RSSI[%d] <--- OTA",
|
|
|
- QDF_MAC_ADDR_REF(mac), rx_mgmt->rx_rssi);
|
|
|
- tdls_recv_discovery_resp(tdls_vdev, mac);
|
|
|
- tdls_set_rssi(tdls_vdev->vdev, mac, rx_mgmt->rx_rssi);
|
|
|
+ QDF_MAC_ADDR_FMT " RSSI[%d] <--- OTA",
|
|
|
+ QDF_MAC_ADDR_REF(mac), rx_mgmt->rx_rssi);
|
|
|
+
|
|
|
+ tdls_debug("discovery resp on vdev %d", wlan_vdev_get_id(vdev));
|
|
|
+ tdls_recv_discovery_resp(tdls_vdev, mac);
|
|
|
+ tdls_set_rssi(tdls_vdev->vdev, mac, rx_mgmt->rx_rssi);
|
|
|
}
|
|
|
|
|
|
if (rx_mgmt->buf[TDLS_PUBLIC_ACTION_FRAME_OFFSET] ==
|
|
@@ -139,6 +535,12 @@ static QDF_STATUS tdls_process_rx_mgmt(
|
|
|
else
|
|
|
tdls_debug("rx mgmt, but no valid up layer callback");
|
|
|
|
|
|
+ if (tdls_vdev_select && tdls_vdev->rx_mgmt) {
|
|
|
+ qdf_mem_free(tdls_vdev->rx_mgmt);
|
|
|
+ tdls_vdev->rx_mgmt = NULL;
|
|
|
+ tdls_vdev->link_score = 0;
|
|
|
+ }
|
|
|
+
|
|
|
return QDF_STATUS_SUCCESS;
|
|
|
}
|
|
|
|