qcacmn: Modify MLO disconnect handling
Modify MLO disconnect handling to issue disconnect on all links in parallel Also modify connect resp to accommodate ml info in connect resp Change-Id: I57575c6ce7c8ebff7770f862dc81e7dfd20aa42d
This commit is contained in:

committato da
Madan Koyyalamudi

parent
7581cd6d12
commit
b21d96305e
@@ -26,6 +26,7 @@
|
||||
#include <wlan_cm_api.h>
|
||||
#include <wlan_mlo_mgr_cmn.h>
|
||||
#include <wlan_scan_api.h>
|
||||
#include <scheduler_api.h>
|
||||
|
||||
#ifdef WLAN_FEATURE_11BE_MLO
|
||||
/**
|
||||
@@ -195,6 +196,29 @@ bool ucfg_mlo_is_mld_disconnected(struct wlan_objmgr_vdev *vdev)
|
||||
return mlo_is_mld_disconnected(vdev);
|
||||
}
|
||||
|
||||
static inline
|
||||
void mlo_mld_clear_mlo_cap(struct wlan_objmgr_vdev *vdev)
|
||||
{
|
||||
struct wlan_mlo_dev_context *mlo_dev_ctx = vdev->mlo_dev_ctx;
|
||||
uint8_t i = 0;
|
||||
|
||||
if (!mlo_dev_ctx || !wlan_vdev_mlme_is_mlo_vdev(vdev))
|
||||
return;
|
||||
|
||||
for (i = 0; i < WLAN_UMAC_MLO_MAX_VDEVS; i++) {
|
||||
if (!mlo_dev_ctx->wlan_vdev_list[i])
|
||||
continue;
|
||||
wlan_vdev_mlme_feat_ext2_cap_clear(
|
||||
mlo_dev_ctx->wlan_vdev_list[i],
|
||||
WLAN_VDEV_FEXT2_MLO);
|
||||
}
|
||||
}
|
||||
|
||||
void ucfg_mlo_mld_clear_mlo_cap(struct wlan_objmgr_vdev *vdev)
|
||||
{
|
||||
mlo_mld_clear_mlo_cap(vdev);
|
||||
}
|
||||
|
||||
static void
|
||||
mlo_cm_handle_connect_in_disconnection_state(struct wlan_objmgr_vdev *vdev,
|
||||
struct wlan_cm_connect_req *req)
|
||||
@@ -500,39 +524,117 @@ mlo_update_connected_links_bmap(struct wlan_mlo_dev_context *mlo_dev_ctx,
|
||||
}
|
||||
}
|
||||
|
||||
static QDF_STATUS ml_activate_disconnect_req_sched_cb(struct scheduler_msg *msg)
|
||||
{
|
||||
struct wlan_objmgr_vdev *vdev = msg->bodyptr;
|
||||
|
||||
if (!vdev) {
|
||||
mlme_err("Null input vdev");
|
||||
return QDF_STATUS_E_INVAL;
|
||||
}
|
||||
|
||||
mlo_disconnect(vdev, CM_OSIF_DISCONNECT,
|
||||
REASON_UNSPEC_FAILURE, NULL);
|
||||
|
||||
wlan_objmgr_vdev_release_ref(vdev, WLAN_MLO_MGR_ID);
|
||||
return QDF_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
static QDF_STATUS ml_activate_disconnect_req_flush_cb(struct scheduler_msg *msg)
|
||||
{
|
||||
struct wlan_objmgr_vdev *vdev = msg->bodyptr;
|
||||
|
||||
if (!vdev) {
|
||||
mlme_err("Null input vdev");
|
||||
return QDF_STATUS_E_INVAL;
|
||||
}
|
||||
|
||||
wlan_objmgr_vdev_release_ref(vdev, WLAN_MLO_MGR_ID);
|
||||
return QDF_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
#ifdef WLAN_FEATURE_11BE_MLO_ADV_FEATURE
|
||||
static inline
|
||||
QDF_STATUS mlo_post_disconnect_msg(struct scheduler_msg *msg)
|
||||
{
|
||||
return scheduler_post_message(
|
||||
QDF_MODULE_ID_SYS,
|
||||
QDF_MODULE_ID_SYS,
|
||||
QDF_MODULE_ID_SYS,
|
||||
msg);
|
||||
}
|
||||
#else
|
||||
static inline
|
||||
QDF_STATUS mlo_post_disconnect_msg(struct scheduler_msg *msg)
|
||||
{
|
||||
return scheduler_post_message(
|
||||
QDF_MODULE_ID_MLME,
|
||||
QDF_MODULE_ID_MLME,
|
||||
QDF_MODULE_ID_MLME,
|
||||
msg);
|
||||
}
|
||||
#endif
|
||||
|
||||
static inline
|
||||
void mlo_handle_sta_link_connect_failure(struct wlan_objmgr_vdev *vdev,
|
||||
struct wlan_cm_connect_resp *rsp)
|
||||
{
|
||||
struct wlan_mlo_dev_context *mlo_dev_ctx = vdev->mlo_dev_ctx;
|
||||
struct wlan_mlo_sta *sta_ctx = NULL;
|
||||
struct scheduler_msg msg = {0};
|
||||
QDF_STATUS ret;
|
||||
|
||||
if (vdev == mlo_get_assoc_link_vdev(mlo_dev_ctx)) {
|
||||
sta_ctx = mlo_dev_ctx->sta_ctx;
|
||||
if (sta_ctx->orig_conn_req) {
|
||||
mlo_free_connect_ies(
|
||||
sta_ctx->orig_conn_req);
|
||||
qdf_mem_free(sta_ctx->orig_conn_req);
|
||||
sta_ctx->orig_conn_req = NULL;
|
||||
}
|
||||
} else {
|
||||
mlo_update_connected_links(vdev, 0);
|
||||
if (rsp->reason == CM_NO_CANDIDATE_FOUND ||
|
||||
rsp->reason == CM_HW_MODE_FAILURE ||
|
||||
rsp->reason == CM_SER_FAILURE) {
|
||||
ret = wlan_objmgr_vdev_try_get_ref(
|
||||
vdev, WLAN_MLO_MGR_ID);
|
||||
if (QDF_IS_STATUS_ERROR(ret)) {
|
||||
mlo_err("Failed to get ref vdev_id %d",
|
||||
wlan_vdev_get_id(vdev));
|
||||
return;
|
||||
}
|
||||
/* Since these failures happen in same context. use
|
||||
* scheduler to avoid deadlock by deferring context
|
||||
*/
|
||||
msg.bodyptr = vdev;
|
||||
msg.callback = ml_activate_disconnect_req_sched_cb;
|
||||
msg.flush_callback =
|
||||
ml_activate_disconnect_req_flush_cb;
|
||||
mlo_post_disconnect_msg(&msg);
|
||||
if (QDF_IS_STATUS_ERROR(ret)) {
|
||||
wlan_objmgr_vdev_release_ref(
|
||||
vdev,
|
||||
WLAN_MLO_MGR_ID);
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
mlo_disconnect(vdev, CM_OSIF_DISCONNECT,
|
||||
REASON_UNSPEC_FAILURE, NULL);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void mlo_sta_link_connect_notify(struct wlan_objmgr_vdev *vdev,
|
||||
struct wlan_cm_connect_resp *rsp)
|
||||
{
|
||||
struct wlan_mlo_dev_context *mlo_dev_ctx = vdev->mlo_dev_ctx;
|
||||
struct wlan_mlo_sta *sta_ctx = NULL;
|
||||
|
||||
if (mlo_dev_ctx) {
|
||||
mlo_debug("Vdev: %d", wlan_vdev_get_id(vdev));
|
||||
if (wlan_cm_is_vdev_disconnected(vdev)) {
|
||||
// Connect Failure
|
||||
if (vdev == mlo_get_assoc_link_vdev(mlo_dev_ctx)) {
|
||||
sta_ctx = mlo_dev_ctx->sta_ctx;
|
||||
if (sta_ctx->orig_conn_req) {
|
||||
mlo_free_connect_ies(
|
||||
sta_ctx->orig_conn_req);
|
||||
qdf_mem_free(sta_ctx->orig_conn_req);
|
||||
sta_ctx->orig_conn_req = NULL;
|
||||
}
|
||||
return;
|
||||
} else {
|
||||
mlo_update_connected_links(vdev, 0);
|
||||
if (rsp->reason == CM_NO_CANDIDATE_FOUND ||
|
||||
rsp->reason == CM_HW_MODE_FAILURE ||
|
||||
rsp->reason == CM_SER_FAILURE)
|
||||
mlo_disconnect_no_lock(
|
||||
vdev, CM_OSIF_DISCONNECT,
|
||||
REASON_UNSPEC_FAILURE, NULL);
|
||||
else
|
||||
mlo_disconnect(
|
||||
vdev, CM_OSIF_DISCONNECT,
|
||||
REASON_UNSPEC_FAILURE, NULL);
|
||||
return;
|
||||
}
|
||||
mlo_handle_sta_link_connect_failure(vdev, rsp);
|
||||
return;
|
||||
} else if (!wlan_cm_is_vdev_connected(vdev)) {
|
||||
/* If vdev is not in disconnected or connected state,
|
||||
* then the event is received due to connect req being
|
||||
@@ -569,32 +671,6 @@ void mlo_sta_link_connect_notify(struct wlan_objmgr_vdev *vdev,
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* mlo_get_connected_link_vdev - API to get 1st connected link vdev
|
||||
*
|
||||
* @mlo_dev_ctx: mlo dev ctx
|
||||
*
|
||||
* Return: 1st connected link vdev in ML dev, NULL if none of the link vdev
|
||||
* is connected
|
||||
*/
|
||||
static struct wlan_objmgr_vdev
|
||||
*mlo_get_connected_link_vdev(struct wlan_mlo_dev_context *mlo_dev_ctx)
|
||||
{
|
||||
uint8_t i = 0;
|
||||
|
||||
for (i = 0; i < WLAN_UMAC_MLO_MAX_VDEVS; i++) {
|
||||
if (!mlo_dev_ctx->wlan_vdev_list[i])
|
||||
continue;
|
||||
|
||||
if ((mlo_dev_ctx->wlan_vdev_list[i] !=
|
||||
mlo_get_assoc_link_vdev(mlo_dev_ctx)) &&
|
||||
wlan_cm_is_vdev_connected(mlo_dev_ctx->wlan_vdev_list[i]))
|
||||
return mlo_dev_ctx->wlan_vdev_list[i];
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* mlo_send_link_disconnect- Issue the disconnect request on MLD links
|
||||
*
|
||||
@@ -605,7 +681,6 @@ static struct wlan_objmgr_vdev
|
||||
*
|
||||
* Return: QDF_STATUS
|
||||
*/
|
||||
#ifdef WLAN_FEATURE_11BE_MLO_ADV_FEATURE
|
||||
static QDF_STATUS
|
||||
mlo_send_link_disconnect(struct wlan_mlo_dev_context *mlo_dev_ctx,
|
||||
enum wlan_cm_source source,
|
||||
@@ -630,6 +705,16 @@ mlo_send_link_disconnect(struct wlan_mlo_dev_context *mlo_dev_ctx,
|
||||
return QDF_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
* mlo_send_link_disconnect- Issue sync the disconnect request on MLD links
|
||||
*
|
||||
* @mlo_dev_ctx: pointer to mlo dev context
|
||||
* @source: disconnect source
|
||||
* @reason_code: disconnect reason
|
||||
* @bssid: bssid of AP to disconnect, can be null if not known
|
||||
*
|
||||
* Return: QDF_STATUS
|
||||
*/
|
||||
static QDF_STATUS
|
||||
mlo_send_link_disconnect_sync(struct wlan_mlo_dev_context *mlo_dev_ctx,
|
||||
enum wlan_cm_source source,
|
||||
@@ -652,68 +737,6 @@ mlo_send_link_disconnect_sync(struct wlan_mlo_dev_context *mlo_dev_ctx,
|
||||
source, reason_code);
|
||||
return QDF_STATUS_SUCCESS;
|
||||
}
|
||||
#else
|
||||
static QDF_STATUS
|
||||
mlo_send_link_disconnect(struct wlan_mlo_dev_context *mlo_dev_ctx,
|
||||
enum wlan_cm_source source,
|
||||
enum wlan_reason_code reason_code,
|
||||
struct qdf_mac_addr *bssid)
|
||||
{
|
||||
uint8_t i = 0;
|
||||
QDF_STATUS status = QDF_STATUS_E_ALREADY;
|
||||
|
||||
for (i = 0; i < WLAN_UMAC_MLO_MAX_VDEVS; i++) {
|
||||
if (!mlo_dev_ctx->wlan_vdev_list[i])
|
||||
continue;
|
||||
|
||||
if (qdf_test_bit(i, mlo_dev_ctx->sta_ctx->wlan_connected_links)) {
|
||||
if (wlan_cm_is_vdev_connecting(
|
||||
mlo_dev_ctx->wlan_vdev_list[i]) ||
|
||||
wlan_cm_is_vdev_disconnecting(
|
||||
mlo_dev_ctx->wlan_vdev_list[i]) ||
|
||||
wlan_cm_is_vdev_roaming(
|
||||
mlo_dev_ctx->wlan_vdev_list[i])) {
|
||||
wlan_cm_disconnect(mlo_dev_ctx->wlan_vdev_list[i],
|
||||
source, reason_code, NULL);
|
||||
return QDF_STATUS_SUCCESS;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
static QDF_STATUS
|
||||
mlo_send_link_disconnect_sync(struct wlan_mlo_dev_context *mlo_dev_ctx,
|
||||
enum wlan_cm_source source,
|
||||
enum wlan_reason_code reason_code,
|
||||
struct qdf_mac_addr *bssid)
|
||||
{
|
||||
uint8_t i = 0;
|
||||
QDF_STATUS status = QDF_STATUS_E_ALREADY;
|
||||
|
||||
for (i = 0; i < WLAN_UMAC_MLO_MAX_VDEVS; i++) {
|
||||
if (!mlo_dev_ctx->wlan_vdev_list[i])
|
||||
continue;
|
||||
|
||||
if (qdf_test_bit(i, mlo_dev_ctx->sta_ctx->wlan_connected_links)) {
|
||||
if (wlan_cm_is_vdev_connecting(
|
||||
mlo_dev_ctx->wlan_vdev_list[i]) ||
|
||||
wlan_cm_is_vdev_disconnecting(
|
||||
mlo_dev_ctx->wlan_vdev_list[i]) ||
|
||||
wlan_cm_is_vdev_roaming(
|
||||
mlo_dev_ctx->wlan_vdev_list[i])) {
|
||||
wlan_cm_disconnect_sync(
|
||||
mlo_dev_ctx->wlan_vdev_list[i],
|
||||
source, reason_code);
|
||||
return QDF_STATUS_SUCCESS;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
#endif
|
||||
|
||||
static QDF_STATUS mlo_disconnect_no_lock(struct wlan_objmgr_vdev *vdev,
|
||||
enum wlan_cm_source source,
|
||||
@@ -721,7 +744,6 @@ static QDF_STATUS mlo_disconnect_no_lock(struct wlan_objmgr_vdev *vdev,
|
||||
struct qdf_mac_addr *bssid)
|
||||
{
|
||||
struct wlan_mlo_dev_context *mlo_dev_ctx = vdev->mlo_dev_ctx;
|
||||
struct wlan_objmgr_vdev *tmp_vdev = vdev;
|
||||
struct wlan_mlo_sta *sta_ctx = NULL;
|
||||
QDF_STATUS status = QDF_STATUS_SUCCESS;
|
||||
|
||||
@@ -744,22 +766,6 @@ static QDF_STATUS mlo_disconnect_no_lock(struct wlan_objmgr_vdev *vdev,
|
||||
|
||||
status = mlo_send_link_disconnect(mlo_dev_ctx, source,
|
||||
reason_code, bssid);
|
||||
|
||||
if (QDF_IS_STATUS_SUCCESS(status))
|
||||
return status;
|
||||
|
||||
tmp_vdev = mlo_get_connected_link_vdev(mlo_dev_ctx);
|
||||
if (tmp_vdev) {
|
||||
status = wlan_cm_disconnect(tmp_vdev, source,
|
||||
reason_code, NULL);
|
||||
return status;
|
||||
}
|
||||
tmp_vdev = mlo_get_assoc_link_vdev(mlo_dev_ctx);
|
||||
if (tmp_vdev) {
|
||||
status = wlan_cm_disconnect(tmp_vdev, source,
|
||||
reason_code, NULL);
|
||||
return status;
|
||||
}
|
||||
}
|
||||
|
||||
return status;
|
||||
@@ -770,11 +776,14 @@ QDF_STATUS mlo_disconnect(struct wlan_objmgr_vdev *vdev,
|
||||
enum wlan_reason_code reason_code,
|
||||
struct qdf_mac_addr *bssid)
|
||||
{
|
||||
struct wlan_mlo_dev_context *mlo_dev_ctx = vdev->mlo_dev_ctx;
|
||||
struct wlan_objmgr_vdev *tmp_vdev = NULL;
|
||||
struct wlan_mlo_dev_context *mlo_dev_ctx = NULL;
|
||||
struct wlan_mlo_sta *sta_ctx = NULL;
|
||||
QDF_STATUS status = QDF_STATUS_SUCCESS;
|
||||
|
||||
if (!vdev)
|
||||
return QDF_STATUS_E_FAILURE;
|
||||
|
||||
mlo_dev_ctx = vdev->mlo_dev_ctx;
|
||||
if (mlo_dev_ctx)
|
||||
sta_ctx = mlo_dev_ctx->sta_ctx;
|
||||
if (sta_ctx && sta_ctx->orig_conn_req) {
|
||||
@@ -793,26 +802,6 @@ QDF_STATUS mlo_disconnect(struct wlan_objmgr_vdev *vdev,
|
||||
|
||||
status = mlo_send_link_disconnect(mlo_dev_ctx, source,
|
||||
reason_code, bssid);
|
||||
|
||||
if (QDF_IS_STATUS_SUCCESS(status)) {
|
||||
mlo_dev_lock_release(mlo_dev_ctx);
|
||||
return status;
|
||||
}
|
||||
|
||||
tmp_vdev = mlo_get_connected_link_vdev(mlo_dev_ctx);
|
||||
if (tmp_vdev) {
|
||||
status = wlan_cm_disconnect(tmp_vdev, source,
|
||||
reason_code, NULL);
|
||||
mlo_dev_lock_release(mlo_dev_ctx);
|
||||
return status;
|
||||
}
|
||||
tmp_vdev = mlo_get_assoc_link_vdev(mlo_dev_ctx);
|
||||
if (tmp_vdev) {
|
||||
status = wlan_cm_disconnect(tmp_vdev, source,
|
||||
reason_code, NULL);
|
||||
mlo_dev_lock_release(mlo_dev_ctx);
|
||||
return status;
|
||||
}
|
||||
mlo_dev_lock_release(mlo_dev_ctx);
|
||||
return status;
|
||||
}
|
||||
@@ -825,11 +814,14 @@ QDF_STATUS mlo_sync_disconnect(struct wlan_objmgr_vdev *vdev,
|
||||
enum wlan_reason_code reason_code,
|
||||
struct qdf_mac_addr *bssid)
|
||||
{
|
||||
struct wlan_mlo_dev_context *mlo_dev_ctx = vdev->mlo_dev_ctx;
|
||||
struct wlan_objmgr_vdev *tmp_vdev = NULL;
|
||||
struct wlan_mlo_dev_context *mlo_dev_ctx = NULL;
|
||||
struct wlan_mlo_sta *sta_ctx = NULL;
|
||||
QDF_STATUS status = QDF_STATUS_SUCCESS;
|
||||
|
||||
if (!vdev)
|
||||
return QDF_STATUS_E_FAILURE;
|
||||
|
||||
mlo_dev_ctx = vdev->mlo_dev_ctx;
|
||||
if (mlo_dev_ctx)
|
||||
sta_ctx = mlo_dev_ctx->sta_ctx;
|
||||
if (sta_ctx && sta_ctx->orig_conn_req) {
|
||||
@@ -848,21 +840,6 @@ QDF_STATUS mlo_sync_disconnect(struct wlan_objmgr_vdev *vdev,
|
||||
status = mlo_send_link_disconnect_sync(mlo_dev_ctx, source,
|
||||
reason_code, bssid);
|
||||
|
||||
if (QDF_IS_STATUS_SUCCESS(status))
|
||||
return status;
|
||||
|
||||
tmp_vdev = mlo_get_connected_link_vdev(mlo_dev_ctx);
|
||||
if (tmp_vdev) {
|
||||
status = wlan_cm_disconnect_sync(tmp_vdev, source,
|
||||
reason_code);
|
||||
return status;
|
||||
}
|
||||
tmp_vdev = mlo_get_assoc_link_vdev(mlo_dev_ctx);
|
||||
if (tmp_vdev) {
|
||||
status = wlan_cm_disconnect_sync(tmp_vdev, source,
|
||||
reason_code);
|
||||
return status;
|
||||
}
|
||||
return status;
|
||||
}
|
||||
return wlan_cm_disconnect_sync(vdev, source,
|
||||
@@ -911,42 +888,120 @@ void mlo_handle_disconnect_resp(struct wlan_mlo_dev_context *mlo_dev_ctx,
|
||||
static
|
||||
void mlo_handle_disconnect_resp(struct wlan_mlo_dev_context *mlo_dev_ctx,
|
||||
struct wlan_cm_discon_rsp *resp)
|
||||
{ }
|
||||
#endif
|
||||
|
||||
static QDF_STATUS ml_activate_connect_req_sched_cb(struct scheduler_msg *msg)
|
||||
{
|
||||
struct wlan_objmgr_vdev *assoc_vdev = NULL;
|
||||
enum wlan_cm_source source;
|
||||
enum wlan_reason_code reason_code;
|
||||
struct wlan_objmgr_vdev *vdev = msg->bodyptr;
|
||||
struct wlan_mlo_dev_context *mlo_dev_ctx = NULL;
|
||||
struct wlan_mlo_sta *sta_ctx = NULL;
|
||||
|
||||
if (!vdev) {
|
||||
mlme_err("Null input vdev");
|
||||
return QDF_STATUS_E_INVAL;
|
||||
}
|
||||
|
||||
mlo_dev_ctx = vdev->mlo_dev_ctx;
|
||||
if (!mlo_dev_ctx) {
|
||||
wlan_objmgr_vdev_release_ref(vdev, WLAN_MLO_MGR_ID);
|
||||
return QDF_STATUS_E_INVAL;
|
||||
}
|
||||
|
||||
sta_ctx = mlo_dev_ctx->sta_ctx;
|
||||
if (!sta_ctx) {
|
||||
wlan_objmgr_vdev_release_ref(vdev, WLAN_MLO_MGR_ID);
|
||||
return QDF_STATUS_E_INVAL;
|
||||
}
|
||||
|
||||
mlo_connect(vdev, sta_ctx->connect_req);
|
||||
mlo_free_connect_ies(sta_ctx->connect_req);
|
||||
qdf_mem_free(sta_ctx->connect_req);
|
||||
sta_ctx->connect_req = NULL;
|
||||
|
||||
wlan_objmgr_vdev_release_ref(vdev, WLAN_MLO_MGR_ID);
|
||||
return QDF_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
static QDF_STATUS ml_activate_connect_req_flush_cb(struct scheduler_msg *msg)
|
||||
{
|
||||
struct wlan_objmgr_vdev *vdev = msg->bodyptr;
|
||||
|
||||
if (!vdev) {
|
||||
mlme_err("Null input vdev");
|
||||
return QDF_STATUS_E_INVAL;
|
||||
}
|
||||
|
||||
wlan_objmgr_vdev_release_ref(vdev, WLAN_MLO_MGR_ID);
|
||||
return QDF_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
#ifdef WLAN_FEATURE_11BE_MLO_ADV_FEATURE
|
||||
static inline
|
||||
void mlo_sta_link_handle_pending_connect(struct wlan_objmgr_vdev *vdev)
|
||||
{ }
|
||||
#else
|
||||
static inline
|
||||
void mlo_sta_link_handle_pending_connect(struct wlan_objmgr_vdev *vdev)
|
||||
{
|
||||
struct wlan_mlo_dev_context *mlo_dev_ctx = vdev->mlo_dev_ctx;
|
||||
struct wlan_objmgr_vdev *tmp_vdev;
|
||||
struct scheduler_msg msg = {0};
|
||||
QDF_STATUS ret;
|
||||
struct wlan_mlo_sta *sta_ctx = NULL;
|
||||
uint8_t i = 0;
|
||||
struct mlo_partner_info partner_info;
|
||||
struct mlo_link_info partner_link_info;
|
||||
|
||||
mlo_dev_lock_acquire(mlo_dev_ctx);
|
||||
for (i = 0; i < WLAN_UMAC_MLO_MAX_VDEVS; i++) {
|
||||
if (!mlo_dev_ctx->wlan_vdev_list[i])
|
||||
continue;
|
||||
sta_ctx = mlo_dev_ctx->sta_ctx;
|
||||
ret = wlan_objmgr_vdev_try_get_ref(
|
||||
vdev,
|
||||
WLAN_MLO_MGR_ID);
|
||||
if (QDF_IS_STATUS_ERROR(ret)) {
|
||||
mlo_free_connect_ies(sta_ctx->connect_req);
|
||||
qdf_mem_free(sta_ctx->connect_req);
|
||||
sta_ctx->connect_req = NULL;
|
||||
return;
|
||||
}
|
||||
msg.bodyptr = vdev;
|
||||
msg.callback = ml_activate_connect_req_sched_cb;
|
||||
msg.flush_callback = ml_activate_connect_req_flush_cb;
|
||||
|
||||
if (qdf_test_bit(i, mlo_dev_ctx->sta_ctx->wlan_connected_links)) {
|
||||
if (wlan_cm_is_vdev_connected(
|
||||
mlo_dev_ctx->wlan_vdev_list[i])) {
|
||||
if (wlan_vdev_mlme_is_mlo_link_vdev(
|
||||
mlo_dev_ctx->wlan_vdev_list[i])) {
|
||||
source = resp->req.req.source;
|
||||
reason_code = resp->req.req.reason_code;
|
||||
wlan_cm_disconnect(mlo_dev_ctx->wlan_vdev_list[i],
|
||||
source, reason_code, NULL);
|
||||
mlo_dev_lock_release(mlo_dev_ctx);
|
||||
return;
|
||||
}
|
||||
ret = scheduler_post_message(QDF_MODULE_ID_MLME,
|
||||
QDF_MODULE_ID_MLME,
|
||||
QDF_MODULE_ID_MLME, &msg);
|
||||
if (QDF_IS_STATUS_ERROR(ret)) {
|
||||
mlo_free_connect_ies(sta_ctx->connect_req);
|
||||
qdf_mem_free(sta_ctx->connect_req);
|
||||
sta_ctx->connect_req = NULL;
|
||||
wlan_objmgr_vdev_release_ref(vdev,
|
||||
WLAN_MLO_MGR_ID);
|
||||
return;
|
||||
}
|
||||
|
||||
if (sta_ctx->connect_req->ml_parnter_info.num_partner_links) {
|
||||
partner_info = sta_ctx->connect_req->ml_parnter_info;
|
||||
wlan_vdev_mlme_feat_ext2_cap_set(vdev, WLAN_VDEV_FEXT2_MLO);
|
||||
mlo_clear_connect_req_links_bmap(vdev);
|
||||
mlo_update_connect_req_links(vdev, 1);
|
||||
for (i = 0; i < partner_info.num_partner_links; i++) {
|
||||
partner_link_info = partner_info.partner_link_info[i];
|
||||
tmp_vdev = mlo_get_ml_vdev_by_mac(
|
||||
vdev,
|
||||
&partner_link_info.link_addr);
|
||||
if (tmp_vdev) {
|
||||
mlo_update_connect_req_links(tmp_vdev, 1);
|
||||
wlan_vdev_mlme_feat_ext2_cap_set(
|
||||
tmp_vdev, WLAN_VDEV_FEXT2_MLO);
|
||||
wlan_vdev_mlme_feat_ext2_cap_set(
|
||||
tmp_vdev,
|
||||
WLAN_VDEV_FEXT2_MLO_STA_LINK);
|
||||
wlan_vdev_set_link_id(
|
||||
tmp_vdev,
|
||||
partner_link_info.link_id);
|
||||
}
|
||||
}
|
||||
}
|
||||
assoc_vdev = mlo_get_assoc_link_vdev(mlo_dev_ctx);
|
||||
if (assoc_vdev && wlan_cm_is_vdev_connected(assoc_vdev)) {
|
||||
source = resp->req.req.source;
|
||||
reason_code = resp->req.req.reason_code;
|
||||
wlan_cm_disconnect(assoc_vdev,
|
||||
source, reason_code, NULL);
|
||||
mlo_dev_lock_release(mlo_dev_ctx);
|
||||
return;
|
||||
}
|
||||
mlo_dev_lock_release(mlo_dev_ctx);
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -955,6 +1010,7 @@ void mlo_sta_link_disconn_notify(struct wlan_objmgr_vdev *vdev,
|
||||
{
|
||||
struct wlan_mlo_dev_context *mlo_dev_ctx = vdev->mlo_dev_ctx;
|
||||
struct wlan_mlo_sta *sta_ctx = NULL;
|
||||
struct wlan_objmgr_vdev *assoc_vdev = NULL;
|
||||
|
||||
if (!mlo_dev_ctx || !(wlan_vdev_mlme_is_mlo_vdev(vdev)))
|
||||
return;
|
||||
@@ -967,15 +1023,11 @@ void mlo_sta_link_disconn_notify(struct wlan_objmgr_vdev *vdev,
|
||||
return;
|
||||
|
||||
mlo_update_connected_links(vdev, 0);
|
||||
if (vdev == mlo_get_assoc_link_vdev(mlo_dev_ctx)) {
|
||||
if (mlo_is_mld_disconnected(vdev)) {
|
||||
if (sta_ctx->connect_req) {
|
||||
mlo_connect(mlo_get_assoc_link_vdev(mlo_dev_ctx),
|
||||
sta_ctx->connect_req);
|
||||
mlo_free_connect_ies(sta_ctx->connect_req);
|
||||
qdf_mem_free(sta_ctx->connect_req);
|
||||
sta_ctx->connect_req = NULL;
|
||||
assoc_vdev = mlo_get_assoc_link_vdev(mlo_dev_ctx);
|
||||
mlo_sta_link_handle_pending_connect(assoc_vdev);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
mlo_handle_disconnect_resp(mlo_dev_ctx, resp);
|
||||
|
Fai riferimento in un nuovo problema
Block a user