@@ -446,12 +446,23 @@ int __cfg80211_mlme_assoc(struct cfg8021
struct cfg80211_assoc_request req;
struct cfg80211_internal_bss *bss;
int i, err, slot = -1;
+ bool was_connected = false;
ASSERT_WDEV_LOCK(wdev);
memset(&req, 0, sizeof(req));
- if (wdev->current_bss)
+ if (wdev->current_bss && prev_bssid &&
+ memcmp(wdev->current_bss->pub.bssid, prev_bssid, ETH_ALEN) == 0) {
+ /*
+ * Trying to reassociate: Allow this to proceed and let the old
+ * association to be dropped when the new one is completed.
+ */
+ if (wdev->sme_state == CFG80211_SME_CONNECTED) {
+ was_connected = true;
+ wdev->sme_state = CFG80211_SME_CONNECTING;
+ }
+ } else if (wdev->current_bss)
return -EALREADY;
req.ie = ie;
@@ -461,8 +472,11 @@ int __cfg80211_mlme_assoc(struct cfg8021
req.prev_bssid = prev_bssid;
req.bss = cfg80211_get_bss(&rdev->wiphy, chan, bssid, ssid, ssid_len,
WLAN_CAPABILITY_ESS, WLAN_CAPABILITY_ESS);
- if (!req.bss)
+ if (!req.bss) {
+ if (was_connected)
+ wdev->sme_state = CFG80211_SME_CONNECTED;
return -ENOENT;
+ }
bss = bss_from_pub(req.bss);
@@ -480,6 +494,8 @@ int __cfg80211_mlme_assoc(struct cfg8021
err = rdev->ops->assoc(&rdev->wiphy, dev, &req);
out:
+ if (err && was_connected)
+ wdev->sme_state = CFG80211_SME_CONNECTED;
/* still a reference in wdev->auth_bsses[slot] */
cfg80211_put_bss(req.bss);
return err;