diff --git a/os_if/linux/mlme/src/osif_cm_util.c b/os_if/linux/mlme/src/osif_cm_util.c index 6b918ac2e5..c114748c65 100644 --- a/os_if/linux/mlme/src/osif_cm_util.c +++ b/os_if/linux/mlme/src/osif_cm_util.c @@ -266,8 +266,9 @@ void osif_cm_unlink_bss(struct wlan_objmgr_vdev *vdev, struct wiphy *wiphy = osif_priv->wdev->wiphy; struct scan_filter *filter; - __wlan_cfg80211_unlink_bss_list(wiphy, bssid->bytes, - ssid_len ? ssid : NULL, ssid_len); + __wlan_cfg80211_unlink_bss_list(wiphy, wlan_vdev_get_pdev(vdev), + bssid->bytes, ssid_len ? ssid : NULL, + ssid_len); filter = qdf_mem_malloc(sizeof(*filter)); if (!filter) return; diff --git a/os_if/linux/scan/inc/wlan_cfg80211_scan.h b/os_if/linux/scan/inc/wlan_cfg80211_scan.h index 0b3d506f3a..25f8bb0fd7 100644 --- a/os_if/linux/scan/inc/wlan_cfg80211_scan.h +++ b/os_if/linux/scan/inc/wlan_cfg80211_scan.h @@ -298,14 +298,17 @@ void wlan_cfg80211_inform_bss_frame(struct wlan_objmgr_pdev *pdev, /** * __wlan_cfg80211_unlink_bss_list() - flush bss from the kernel cache * @wiphy: wiphy + * @pdev: pdev object * @bssid: bssid of the BSS to find * @ssid: ssid of the BSS to find * @ssid_len: ssid len of of the BSS to find * - * Return: None + * Return: QDF_STATUS */ -void __wlan_cfg80211_unlink_bss_list(struct wiphy *wiphy, uint8_t *bssid, - uint8_t *ssid, uint8_t ssid_len); +QDF_STATUS __wlan_cfg80211_unlink_bss_list(struct wiphy *wiphy, + struct wlan_objmgr_pdev *pdev, + uint8_t *bssid, uint8_t *ssid, + uint8_t ssid_len); /** * wlan_cfg80211_get_bss() - Get the bss entry matching the chan, bssid and ssid diff --git a/os_if/linux/scan/src/wlan_cfg80211_scan.c b/os_if/linux/scan/src/wlan_cfg80211_scan.c index 074bcad85d..6a4fd095da 100644 --- a/os_if/linux/scan/src/wlan_cfg80211_scan.c +++ b/os_if/linux/scan/src/wlan_cfg80211_scan.c @@ -2055,10 +2055,96 @@ struct cfg80211_bss *wlan_cfg80211_get_bss(struct wiphy *wiphy, } #endif -void __wlan_cfg80211_unlink_bss_list(struct wiphy *wiphy, uint8_t *bssid, - uint8_t *ssid, uint8_t ssid_len) +/** + * struct wlan_check_bssid_context - bssid check context + * @bssid: bssid to be checked + * @connected: connected by vdev or not + * @vdev_id: vdev id of connected vdev + */ +struct wlan_check_bssid_context { + struct qdf_mac_addr bssid; + bool connected; + uint8_t vdev_id; +}; + +/** + * wlan_get_connected_vdev_handler() - check vdev connected on bssid + * @psoc: psoc object + * @obj: vdev object + * @args: handler context + * + * This function will check whether vdev is connected on bssid or not and + * update the result to handler context accordingly. + * + * Return: void + */ +static void wlan_get_connected_vdev_handler(struct wlan_objmgr_psoc *psoc, + void *obj, void *args) +{ + struct wlan_objmgr_vdev *vdev = (struct wlan_objmgr_vdev *)obj; + struct wlan_check_bssid_context *context = + (struct wlan_check_bssid_context *)args; + struct qdf_mac_addr bss_peer_mac; + enum QDF_OPMODE op_mode; + + if (context->connected) + return; + op_mode = wlan_vdev_mlme_get_opmode(vdev); + if (op_mode != QDF_STA_MODE && op_mode != QDF_P2P_CLIENT_MODE) + return; + if (wlan_vdev_is_up(vdev) != QDF_STATUS_SUCCESS) + return; + if (wlan_vdev_get_bss_peer_mac(vdev, &bss_peer_mac) != + QDF_STATUS_SUCCESS) + return; + if (qdf_is_macaddr_equal(&bss_peer_mac, &context->bssid)) { + context->connected = true; + context->vdev_id = wlan_vdev_get_id(vdev); + } +} + +/** + * wlan_get_connected_vdev_by_bssid() - check/get any vdev connected on bssid + * @pdev: pdev object + * @bssid: bssid to be checked + * @vdev_id: vdev id + * + * This function will loop through all the vdev in psoc and find/return the + * vdev which is connected to bssid provided. + * + * Return: bool + */ +static bool wlan_get_connected_vdev_by_bssid(struct wlan_objmgr_pdev *pdev, + uint8_t *bssid, uint8_t *vdev_id) +{ + struct wlan_objmgr_psoc *psoc; + struct wlan_check_bssid_context context; + + psoc = wlan_pdev_get_psoc(pdev); + qdf_mem_zero(&context, sizeof(struct wlan_check_bssid_context)); + qdf_mem_copy(context.bssid.bytes, bssid, QDF_MAC_ADDR_SIZE); + wlan_objmgr_iterate_obj_list_all(psoc, WLAN_VDEV_OP, + wlan_get_connected_vdev_handler, + &context, true, WLAN_OSIF_SCAN_ID); + if (context.connected) + *vdev_id = context.vdev_id; + + return context.connected; +} + +QDF_STATUS __wlan_cfg80211_unlink_bss_list(struct wiphy *wiphy, + struct wlan_objmgr_pdev *pdev, + uint8_t *bssid, uint8_t *ssid, + uint8_t ssid_len) { struct cfg80211_bss *bss = NULL; + uint8_t vdev_id; + + if (bssid && wlan_get_connected_vdev_by_bssid(pdev, bssid, &vdev_id)) { + osif_debug("BSS "QDF_MAC_ADDR_FMT" connected on vdev %d dont unlink", + QDF_MAC_ADDR_REF(bssid), vdev_id); + return QDF_STATUS_E_FAILURE; + } bss = wlan_cfg80211_get_bss(wiphy, NULL, bssid, ssid, ssid_len); @@ -2093,6 +2179,8 @@ void __wlan_cfg80211_unlink_bss_list(struct wiphy *wiphy, uint8_t *bssid, /* cfg80211_get_bss get bss with ref count so release it */ wlan_cfg80211_put_bss(wiphy, bss); } + + return QDF_STATUS_SUCCESS; } void wlan_cfg80211_unlink_bss_list(struct wlan_objmgr_pdev *pdev, struct scan_cache_entry *scan_entry) @@ -2107,7 +2195,7 @@ void wlan_cfg80211_unlink_bss_list(struct wlan_objmgr_pdev *pdev, wiphy = pdev_ospriv->wiphy; - __wlan_cfg80211_unlink_bss_list(wiphy, scan_entry->bssid.bytes, + __wlan_cfg80211_unlink_bss_list(wiphy, pdev, scan_entry->bssid.bytes, scan_entry->ssid.ssid, scan_entry->ssid.length); }