qcacmn: Remove the assumption of assoc link's presence post connection

With MLO link removal, AP can remove a link that happens to be the assoc
link for a given Non-AP MLD. So far, the Non-AP MLD has been using the
assoc link to interact with other layers and make various decisions.
Change those behaviors on a case-by-case basis.

CRs-Fixed: 3577559
Change-Id: Iaa001bdd2571bce424a953caa3197a99a6f84180
This commit is contained in:
Shiva Krishna Pittala
2023-08-08 14:15:00 +05:30
committed by Rahul Choudhary
parent 2c0fb4ffc6
commit f796368068
2 changed files with 37 additions and 24 deletions

View File

@@ -164,11 +164,20 @@ osif_cm_indicate_disconnect(struct wlan_objmgr_vdev *vdev,
} }
if (ucfg_mlo_is_mld_disconnected(vdev)) { if (ucfg_mlo_is_mld_disconnected(vdev)) {
/**
* Kernel maintains some extra state on the assoc netdev.
* If the assoc vdev exists, send disconnected event on the
* assoc netdev so that kernel cleans up the extra state.
* If the assoc vdev was already removed, kernel would have
* already cleaned up the extra state while processing the
* disconnected event sent as part of the link removal.
*/
assoc_vdev = ucfg_mlo_get_assoc_link_vdev(vdev); assoc_vdev = ucfg_mlo_get_assoc_link_vdev(vdev);
if (!assoc_vdev) if (assoc_vdev) {
return; osif_priv = wlan_vdev_get_ospriv(assoc_vdev);
osif_priv = wlan_vdev_get_ospriv(assoc_vdev); netdev = osif_priv->wdev->netdev;
netdev = osif_priv->wdev->netdev; }
osif_cm_indicate_disconnect_result( osif_cm_indicate_disconnect_result(
netdev, reason, netdev, reason,
ie, ie_len, ie, ie_len,

View File

@@ -295,8 +295,8 @@ mlo_send_link_disconnect(struct wlan_objmgr_vdev *vdev,
mlo_release_vdev_ref(wlan_vdev_list[i]); mlo_release_vdev_ref(wlan_vdev_list[i]);
} }
wlan_cm_disconnect(assoc_vdev, if (assoc_vdev)
source, reason_code, NULL); wlan_cm_disconnect(assoc_vdev, source, reason_code, NULL);
return QDF_STATUS_SUCCESS; return QDF_STATUS_SUCCESS;
} }
@@ -517,8 +517,6 @@ static QDF_STATUS mlo_disconnect_no_lock(struct wlan_objmgr_vdev *vdev,
return QDF_STATUS_E_FAILURE; return QDF_STATUS_E_FAILURE;
assoc_vdev = mlo_get_assoc_link_vdev(mlo_dev_ctx); assoc_vdev = mlo_get_assoc_link_vdev(mlo_dev_ctx);
if (!assoc_vdev)
return QDF_STATUS_E_FAILURE;
if (sta_ctx->connect_req) { if (sta_ctx->connect_req) {
wlan_cm_free_connect_req(sta_ctx->connect_req); wlan_cm_free_connect_req(sta_ctx->connect_req);
@@ -545,8 +543,9 @@ static QDF_STATUS mlo_disconnect_no_lock(struct wlan_objmgr_vdev *vdev,
NULL); NULL);
} }
wlan_cm_disconnect(assoc_vdev, if (assoc_vdev)
source, reason_code, NULL); wlan_cm_disconnect(assoc_vdev, source,
reason_code, NULL);
} }
return status; return status;
@@ -1290,28 +1289,33 @@ mlo_send_link_disconnect_sync(struct wlan_mlo_dev_context *mlo_dev_ctx,
struct qdf_mac_addr *bssid) struct qdf_mac_addr *bssid)
{ {
uint8_t i; uint8_t i;
struct wlan_objmgr_vdev *assoc_vdev = struct wlan_objmgr_vdev *sync_vdev =
mlo_get_assoc_link_vdev(mlo_dev_ctx); mlo_get_assoc_link_vdev(mlo_dev_ctx);
if (!assoc_vdev)
return QDF_STATUS_E_FAILURE;
for (i = 0; i < WLAN_UMAC_MLO_MAX_VDEVS; i++) { for (i = 0; i < WLAN_UMAC_MLO_MAX_VDEVS; i++) {
if (!mlo_dev_ctx->wlan_vdev_list[i]) if (!mlo_dev_ctx->wlan_vdev_list[i])
continue; continue;
/* /**
* To initiate disconnect on all links at once, no need to use * If the assoc vdev isn't present, use the first link dev as
* sync API for link Vdev * sync candidate.
*/ */
if (mlo_dev_ctx->wlan_vdev_list[i] != if (!sync_vdev) {
mlo_get_assoc_link_vdev(mlo_dev_ctx)) sync_vdev = mlo_dev_ctx->wlan_vdev_list[i];
wlan_cm_disconnect(mlo_dev_ctx->wlan_vdev_list[i], continue;
source, reason_code, NULL); }
/**
* To initiate disconnect on all links at once, no need to use
* sync API for all link vdevs.
*/
wlan_cm_disconnect(mlo_dev_ctx->wlan_vdev_list[i],
source, reason_code, NULL);
} }
wlan_cm_disconnect_sync(assoc_vdev, if (sync_vdev)
source, reason_code); wlan_cm_disconnect_sync(sync_vdev, source, reason_code);
return QDF_STATUS_SUCCESS; return QDF_STATUS_SUCCESS;
} }