From f79636806802fac68a554123de35abebcc5b638d Mon Sep 17 00:00:00 2001 From: Shiva Krishna Pittala Date: Tue, 8 Aug 2023 14:15:00 +0530 Subject: [PATCH] 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 --- os_if/linux/mlme/src/osif_cm_disconnect_rsp.c | 17 +++++-- umac/mlo_mgr/src/wlan_mlo_mgr_sta.c | 44 ++++++++++--------- 2 files changed, 37 insertions(+), 24 deletions(-) diff --git a/os_if/linux/mlme/src/osif_cm_disconnect_rsp.c b/os_if/linux/mlme/src/osif_cm_disconnect_rsp.c index 53fac9064b..6c6abdb4f7 100644 --- a/os_if/linux/mlme/src/osif_cm_disconnect_rsp.c +++ b/os_if/linux/mlme/src/osif_cm_disconnect_rsp.c @@ -164,11 +164,20 @@ osif_cm_indicate_disconnect(struct wlan_objmgr_vdev *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); - if (!assoc_vdev) - return; - osif_priv = wlan_vdev_get_ospriv(assoc_vdev); - netdev = osif_priv->wdev->netdev; + if (assoc_vdev) { + osif_priv = wlan_vdev_get_ospriv(assoc_vdev); + netdev = osif_priv->wdev->netdev; + } + osif_cm_indicate_disconnect_result( netdev, reason, ie, ie_len, diff --git a/umac/mlo_mgr/src/wlan_mlo_mgr_sta.c b/umac/mlo_mgr/src/wlan_mlo_mgr_sta.c index fe84d35565..dec9031db9 100644 --- a/umac/mlo_mgr/src/wlan_mlo_mgr_sta.c +++ b/umac/mlo_mgr/src/wlan_mlo_mgr_sta.c @@ -295,8 +295,8 @@ mlo_send_link_disconnect(struct wlan_objmgr_vdev *vdev, mlo_release_vdev_ref(wlan_vdev_list[i]); } - wlan_cm_disconnect(assoc_vdev, - source, reason_code, NULL); + if (assoc_vdev) + wlan_cm_disconnect(assoc_vdev, source, reason_code, NULL); 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; assoc_vdev = mlo_get_assoc_link_vdev(mlo_dev_ctx); - if (!assoc_vdev) - return QDF_STATUS_E_FAILURE; if (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); } - wlan_cm_disconnect(assoc_vdev, - source, reason_code, NULL); + if (assoc_vdev) + wlan_cm_disconnect(assoc_vdev, source, + reason_code, NULL); } return status; @@ -1290,28 +1289,33 @@ mlo_send_link_disconnect_sync(struct wlan_mlo_dev_context *mlo_dev_ctx, struct qdf_mac_addr *bssid) { uint8_t i; - struct wlan_objmgr_vdev *assoc_vdev = - mlo_get_assoc_link_vdev(mlo_dev_ctx); - - if (!assoc_vdev) - return QDF_STATUS_E_FAILURE; + struct wlan_objmgr_vdev *sync_vdev = + mlo_get_assoc_link_vdev(mlo_dev_ctx); for (i = 0; i < WLAN_UMAC_MLO_MAX_VDEVS; i++) { if (!mlo_dev_ctx->wlan_vdev_list[i]) continue; - /* - * To initiate disconnect on all links at once, no need to use - * sync API for link Vdev + /** + * If the assoc vdev isn't present, use the first link dev as + * sync candidate. */ - if (mlo_dev_ctx->wlan_vdev_list[i] != - mlo_get_assoc_link_vdev(mlo_dev_ctx)) - wlan_cm_disconnect(mlo_dev_ctx->wlan_vdev_list[i], - source, reason_code, NULL); + if (!sync_vdev) { + sync_vdev = mlo_dev_ctx->wlan_vdev_list[i]; + continue; + } + + /** + * 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, - source, reason_code); + if (sync_vdev) + wlan_cm_disconnect_sync(sync_vdev, source, reason_code); + return QDF_STATUS_SUCCESS; }