--- zzzz-none-000/linux-5.4.213/net/wireless/sme.c 2022-09-15 10:04:56.000000000 +0000 +++ miami-7690-761/linux-5.4.213/net/wireless/sme.c 2024-05-29 11:20:02.000000000 +0000 @@ -753,8 +753,10 @@ return; } - if (WARN_ON(!cr->bss)) + if (!cr->bss) { + pr_warn("%s:bss not found\n", __func__); return; + } wdev->current_bss = bss_from_pub(cr->bss); @@ -784,6 +786,73 @@ kfree(country_ie); } +int cfg80211_update_current_bss(struct net_device *dev, + struct cfg80211_connect_resp_params *cr, + const u8 *ssid, size_t ssid_len) +{ + struct wireless_dev *wdev = dev->ieee80211_ptr; + + ASSERT_WDEV_LOCK(wdev); + + if (!ssid) + return -EINVAL; + + memcpy(wdev->ssid, ssid, ssid_len); + wdev->ssid_len = ssid_len; + + if (WARN_ON(wdev->iftype != NL80211_IFTYPE_STATION && + wdev->iftype != NL80211_IFTYPE_P2P_CLIENT)) { + cfg80211_put_bss(wdev->wiphy, cr->bss); + return -EINVAL; + } + + if (!cr->bss && cr->status == WLAN_STATUS_SUCCESS) { + WARN_ON_ONCE(!wiphy_to_rdev(wdev->wiphy)->ops->connect); + cr->bss = cfg80211_get_bss(wdev->wiphy, NULL, cr->bssid, + wdev->ssid, wdev->ssid_len, + wdev->conn_bss_type, + IEEE80211_PRIVACY_ANY); + } + + if (!cr->bss) { + pr_warn("%s:bss not found\n", __func__); + return -EINVAL; + } + + if (wdev->current_bss) { + cfg80211_unhold_bss(wdev->current_bss); + cfg80211_put_bss(wdev->wiphy, &wdev->current_bss->pub); + wdev->current_bss = NULL; + } + + cfg80211_hold_bss(bss_from_pub(cr->bss)); + wdev->current_bss = bss_from_pub(cr->bss); + + return 0; +} +EXPORT_SYMBOL(cfg80211_update_current_bss); + +int cfg80211_clear_current_bss(struct net_device *dev) +{ + struct wireless_dev *wdev = dev->ieee80211_ptr; + + ASSERT_WDEV_LOCK(wdev); + + if (WARN_ON(wdev->iftype != NL80211_IFTYPE_STATION && + wdev->iftype != NL80211_IFTYPE_P2P_CLIENT)) { + return -EINVAL; + } + + if (wdev->current_bss) { + cfg80211_unhold_bss(wdev->current_bss); + cfg80211_put_bss(wdev->wiphy, &wdev->current_bss->pub); + wdev->current_bss = NULL; + } + + return 0; +} +EXPORT_SYMBOL(cfg80211_clear_current_bss); + /* Consumes bss object one way or another */ void cfg80211_connect_done(struct net_device *dev, struct cfg80211_connect_resp_params *params, @@ -1073,7 +1142,8 @@ EXPORT_SYMBOL(cfg80211_port_authorized); void __cfg80211_disconnected(struct net_device *dev, const u8 *ie, - size_t ie_len, u16 reason, bool from_ap) + size_t ie_len, u16 reason, bool from_ap, + int link_id) { struct wireless_dev *wdev = dev->ieee80211_ptr; struct cfg80211_registered_device *rdev = wiphy_to_rdev(wdev->wiphy); @@ -1088,6 +1158,7 @@ wdev->iftype != NL80211_IFTYPE_P2P_CLIENT)) return; + if (wdev->current_bss) { cfg80211_unhold_bss(wdev->current_bss); cfg80211_put_bss(wdev->wiphy, &wdev->current_bss->pub); @@ -1099,7 +1170,11 @@ kzfree(wdev->connect_keys); wdev->connect_keys = NULL; - nl80211_send_disconnected(rdev, dev, reason, ie, ie_len, from_ap); + if (link_id < 0 || link_id > NL80211_MLD_MAX_NUM_LINKS) + link_id = NL80211_MLO_INVALID_LINK_ID; + + nl80211_send_disconnected(rdev, dev, reason, ie, ie_len, from_ap, + link_id); /* stop critical protocol if supported */ if (rdev->ops->crit_proto_stop && rdev->crit_proto_nlportid) { @@ -1111,9 +1186,16 @@ * Delete all the keys ... pairwise keys can't really * exist any more anyway, but default keys might. */ - if (rdev->ops->del_key) - for (i = 0; i < 6; i++) + if (rdev->ops->del_key) { + int max_key_idx = 5; + + if (wiphy_ext_feature_isset( + wdev->wiphy, + NL80211_EXT_FEATURE_BEACON_PROTECTION)) + max_key_idx = 7; + for (i = 0; i <= max_key_idx; i++) rdev_del_key(rdev, dev, i, false, NULL); + } rdev_set_qos_map(rdev, dev, NULL); @@ -1129,7 +1211,7 @@ void cfg80211_disconnected(struct net_device *dev, u16 reason, const u8 *ie, size_t ie_len, - bool locally_generated, gfp_t gfp) + bool locally_generated, int link_id, gfp_t gfp) { struct wireless_dev *wdev = dev->ieee80211_ptr; struct cfg80211_registered_device *rdev = wiphy_to_rdev(wdev->wiphy); @@ -1146,6 +1228,7 @@ memcpy((void *)ev->dc.ie, ie, ie_len); ev->dc.reason = reason; ev->dc.locally_generated = locally_generated; + ev->dc.link_id = link_id; spin_lock_irqsave(&wdev->event_lock, flags); list_add_tail(&ev->list, &wdev->event_list); @@ -1311,7 +1394,7 @@ break; case NL80211_IFTYPE_AP: case NL80211_IFTYPE_P2P_GO: - __cfg80211_stop_ap(rdev, wdev->netdev, false); + __cfg80211_stop_ap(rdev, wdev->netdev, false, NULL); break; case NL80211_IFTYPE_MESH_POINT: __cfg80211_leave_mesh(rdev, wdev->netdev);