|
@@ -199,6 +199,15 @@ mlo_validate_connect_req(struct wlan_objmgr_vdev *vdev,
|
|
/* check back to back connect handling */
|
|
/* check back to back connect handling */
|
|
return QDF_STATUS_SUCCESS;
|
|
return QDF_STATUS_SUCCESS;
|
|
}
|
|
}
|
|
|
|
+
|
|
|
|
+static QDF_STATUS
|
|
|
|
+mlo_validate_disconn_req(struct wlan_objmgr_vdev *vdev,
|
|
|
|
+ enum wlan_cm_source source,
|
|
|
|
+ enum wlan_reason_code reason_code,
|
|
|
|
+ struct qdf_mac_addr *bssid)
|
|
|
|
+{
|
|
|
|
+ return QDF_STATUS_SUCCESS;
|
|
|
|
+}
|
|
#else
|
|
#else
|
|
/**
|
|
/**
|
|
* mlo_is_mld_connected - Check whether MLD is connected
|
|
* mlo_is_mld_connected - Check whether MLD is connected
|
|
@@ -380,6 +389,45 @@ mlo_validate_connect_req(struct wlan_objmgr_vdev *vdev,
|
|
}
|
|
}
|
|
return status;
|
|
return status;
|
|
}
|
|
}
|
|
|
|
+
|
|
|
|
+static QDF_STATUS
|
|
|
|
+mlo_validate_disconn_req(struct wlan_objmgr_vdev *vdev,
|
|
|
|
+ enum wlan_cm_source source,
|
|
|
|
+ enum wlan_reason_code reason_code,
|
|
|
|
+ struct qdf_mac_addr *bssid)
|
|
|
|
+{
|
|
|
|
+ struct wlan_mlo_dev_context *mlo_dev = vdev->mlo_dev_ctx;
|
|
|
|
+ struct wlan_mlo_sta *sta_ctx = mlo_dev->sta_ctx;
|
|
|
|
+ uint8_t i = 0;
|
|
|
|
+
|
|
|
|
+ for (i = 0; i < WLAN_UMAC_MLO_MAX_VDEVS; i++) {
|
|
|
|
+ if (!mlo_dev->wlan_vdev_list[i])
|
|
|
|
+ continue;
|
|
|
|
+
|
|
|
|
+ if (wlan_cm_is_vdev_connecting(mlo_dev->wlan_vdev_list[i])) {
|
|
|
|
+ if (!wlan_vdev_mlme_is_mlo_link_vdev(vdev))
|
|
|
|
+ return QDF_STATUS_SUCCESS;
|
|
|
|
+
|
|
|
|
+ if (!sta_ctx->disconn_req)
|
|
|
|
+ sta_ctx->disconn_req =
|
|
|
|
+ qdf_mem_malloc(
|
|
|
|
+ sizeof(struct wlan_cm_disconnect_req));
|
|
|
|
+
|
|
|
|
+ if (!sta_ctx->disconn_req)
|
|
|
|
+ return QDF_STATUS_SUCCESS;
|
|
|
|
+
|
|
|
|
+ sta_ctx->disconn_req->vdev_id =
|
|
|
|
+ wlan_vdev_get_id(vdev);
|
|
|
|
+ sta_ctx->disconn_req->source = source;
|
|
|
|
+ sta_ctx->disconn_req->reason_code = reason_code;
|
|
|
|
+ if (bssid)
|
|
|
|
+ qdf_copy_macaddr(&sta_ctx->disconn_req->bssid,
|
|
|
|
+ bssid);
|
|
|
|
+ return QDF_STATUS_E_BUSY;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ return QDF_STATUS_SUCCESS;
|
|
|
|
+}
|
|
#endif
|
|
#endif
|
|
|
|
|
|
QDF_STATUS mlo_connect(struct wlan_objmgr_vdev *vdev,
|
|
QDF_STATUS mlo_connect(struct wlan_objmgr_vdev *vdev,
|
|
@@ -668,6 +716,43 @@ static QDF_STATUS ml_activate_disconnect_req_flush_cb(struct scheduler_msg *msg)
|
|
return QDF_STATUS_SUCCESS;
|
|
return QDF_STATUS_SUCCESS;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+static QDF_STATUS ml_activate_pend_disconn_req_cb(struct scheduler_msg *msg)
|
|
|
|
+{
|
|
|
|
+ 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;
|
|
|
|
+ sta_ctx = mlo_dev_ctx->sta_ctx;
|
|
|
|
+ mlo_disconnect(vdev, sta_ctx->disconn_req->source,
|
|
|
|
+ sta_ctx->disconn_req->reason_code,
|
|
|
|
+ &sta_ctx->disconn_req->bssid);
|
|
|
|
+
|
|
|
|
+ qdf_mem_free(sta_ctx->disconn_req);
|
|
|
|
+ sta_ctx->disconn_req = NULL;
|
|
|
|
+ wlan_objmgr_vdev_release_ref(vdev, WLAN_MLO_MGR_ID);
|
|
|
|
+ return QDF_STATUS_SUCCESS;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+static QDF_STATUS ml_activate_pend_disconn_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
|
|
#ifdef WLAN_FEATURE_11BE_MLO_ADV_FEATURE
|
|
static inline
|
|
static inline
|
|
QDF_STATUS mlo_post_disconnect_msg(struct scheduler_msg *msg)
|
|
QDF_STATUS mlo_post_disconnect_msg(struct scheduler_msg *msg)
|
|
@@ -736,6 +821,35 @@ void mlo_handle_sta_link_connect_failure(struct wlan_objmgr_vdev *vdev,
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+static inline
|
|
|
|
+void mlo_handle_pending_disconnect(struct wlan_objmgr_vdev *vdev)
|
|
|
|
+{
|
|
|
|
+ struct scheduler_msg msg = {0};
|
|
|
|
+ QDF_STATUS ret;
|
|
|
|
+
|
|
|
|
+ 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;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ msg.bodyptr = vdev;
|
|
|
|
+ msg.callback = ml_activate_pend_disconn_req_cb;
|
|
|
|
+ msg.flush_callback =
|
|
|
|
+ ml_activate_pend_disconn_req_flush_cb;
|
|
|
|
+ ret = mlo_post_disconnect_msg(&msg);
|
|
|
|
+ if (QDF_IS_STATUS_ERROR(ret)) {
|
|
|
|
+ mlo_err("Failed to post scheduler msg");
|
|
|
|
+ wlan_objmgr_vdev_release_ref(
|
|
|
|
+ vdev,
|
|
|
|
+ WLAN_MLO_MGR_ID);
|
|
|
|
+ QDF_BUG(0);
|
|
|
|
+ return;
|
|
|
|
+ }
|
|
|
|
+}
|
|
|
|
+
|
|
void mlo_sta_link_connect_notify(struct wlan_objmgr_vdev *vdev,
|
|
void mlo_sta_link_connect_notify(struct wlan_objmgr_vdev *vdev,
|
|
struct wlan_cm_connect_resp *rsp)
|
|
struct wlan_cm_connect_resp *rsp)
|
|
{
|
|
{
|
|
@@ -749,6 +863,13 @@ void mlo_sta_link_connect_notify(struct wlan_objmgr_vdev *vdev,
|
|
return;
|
|
return;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+ if (sta_ctx && sta_ctx->disconn_req) {
|
|
|
|
+ mlo_debug("Handle pending disocnnect for vdev %d",
|
|
|
|
+ wlan_vdev_get_id(vdev));
|
|
|
|
+ mlo_handle_pending_disconnect(vdev);
|
|
|
|
+ return;
|
|
|
|
+ }
|
|
|
|
+
|
|
if (wlan_cm_is_vdev_disconnected(vdev)) {
|
|
if (wlan_cm_is_vdev_disconnected(vdev)) {
|
|
if (sta_ctx) {
|
|
if (sta_ctx) {
|
|
copied_conn_req_lock_acquire(sta_ctx);
|
|
copied_conn_req_lock_acquire(sta_ctx);
|
|
@@ -874,6 +995,14 @@ QDF_STATUS mlo_disconnect(struct wlan_objmgr_vdev *vdev,
|
|
sta_ctx->connect_req = NULL;
|
|
sta_ctx->connect_req = NULL;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+ status = mlo_validate_disconn_req(vdev, source,
|
|
|
|
+ reason_code, bssid);
|
|
|
|
+ if (QDF_IS_STATUS_ERROR(status)) {
|
|
|
|
+ mlo_debug("Connect in progress, deferring disconnect");
|
|
|
|
+ mlo_dev_lock_release(mlo_dev_ctx);
|
|
|
|
+ return status;
|
|
|
|
+ }
|
|
|
|
+
|
|
status = mlo_send_link_disconnect(mlo_dev_ctx, source,
|
|
status = mlo_send_link_disconnect(mlo_dev_ctx, source,
|
|
reason_code, bssid);
|
|
reason_code, bssid);
|
|
mlo_dev_lock_release(mlo_dev_ctx);
|
|
mlo_dev_lock_release(mlo_dev_ctx);
|