if (!dev)
goto out;
- WARN_ON(request != wiphy_to_dev(request->wiphy)->scan_req);
- wiphy_to_dev(request->wiphy)->scan_req = NULL;
+ /*
+ * This must be before sending the other events!
+ * Otherwise, wpa_supplicant gets completely confused with
+ * wext events.
+ */
+ cfg80211_sme_scan_done(dev);
if (aborted)
nl80211_send_scan_aborted(wiphy_to_dev(request->wiphy), dev);
else
nl80211_send_scan_done(wiphy_to_dev(request->wiphy), dev);
+ wiphy_to_dev(request->wiphy)->scan_req = NULL;
+
#ifdef CONFIG_WIRELESS_EXT
if (!aborted) {
memset(&wrqu, 0, sizeof(wrqu));
if (bss->ies_allocated)
kfree(bss->pub.information_elements);
+ BUG_ON(atomic_read(&bss->hold));
+
kfree(bss);
}
bool expired = false;
list_for_each_entry_safe(bss, tmp, &dev->bss_list, list) {
- if (bss->hold ||
- !time_after(jiffies, bss->ts + IEEE80211_SCAN_RESULT_EXPIRE))
+ if (atomic_read(&bss->hold))
+ continue;
+ if (!time_after(jiffies, bss->ts + IEEE80211_SCAN_RESULT_EXPIRE))
continue;
list_del(&bss->list);
rb_erase(&bss->rbn, &dev->bss_tree);
found = rb_find_bss(dev, res);
if (found) {
- kref_get(&found->ref);
found->pub.beacon_interval = res->pub.beacon_interval;
found->pub.tsf = res->pub.tsf;
found->pub.signal = res->pub.signal;
size_t used = dev->wiphy.bss_priv_size + sizeof(*res);
size_t ielen = res->pub.len_information_elements;
- if (ksize(found) >= used + ielen) {
+ if (!found->ies_allocated && ksize(found) >= used + ielen) {
memcpy(found->pub.information_elements,
res->pub.information_elements, ielen);
found->pub.len_information_elements = ielen;
} else {
u8 *ies = found->pub.information_elements;
- if (found->ies_allocated) {
- if (ksize(ies) < ielen)
- ies = krealloc(ies, ielen,
- GFP_ATOMIC);
- } else
+ if (found->ies_allocated)
+ ies = krealloc(ies, ielen, GFP_ATOMIC);
+ else
ies = kmalloc(ielen, GFP_ATOMIC);
if (ies) {
return found;
}
+struct cfg80211_bss*
+cfg80211_inform_bss(struct wiphy *wiphy,
+ struct ieee80211_channel *channel,
+ const u8 *bssid,
+ u64 timestamp, u16 capability, u16 beacon_interval,
+ const u8 *ie, size_t ielen,
+ s32 signal, gfp_t gfp)
+{
+ struct cfg80211_internal_bss *res;
+ size_t privsz;
+
+ if (WARN_ON(!wiphy))
+ return NULL;
+
+ privsz = wiphy->bss_priv_size;
+
+ if (WARN_ON(wiphy->signal_type == NL80211_BSS_SIGNAL_UNSPEC &&
+ (signal < 0 || signal > 100)))
+ return NULL;
+
+ res = kzalloc(sizeof(*res) + privsz + ielen, gfp);
+ if (!res)
+ return NULL;
+
+ memcpy(res->pub.bssid, bssid, ETH_ALEN);
+ res->pub.channel = channel;
+ res->pub.signal = signal;
+ res->pub.tsf = timestamp;
+ res->pub.beacon_interval = beacon_interval;
+ res->pub.capability = capability;
+ /* point to after the private area */
+ res->pub.information_elements = (u8 *)res + sizeof(*res) + privsz;
+ memcpy(res->pub.information_elements, ie, ielen);
+ res->pub.len_information_elements = ielen;
+
+ kref_init(&res->ref);
+
+ res = cfg80211_bss_update(wiphy_to_dev(wiphy), res, 0);
+ if (!res)
+ return NULL;
+
+ if (res->pub.capability & WLAN_CAPABILITY_ESS)
+ regulatory_hint_found_beacon(wiphy, channel, gfp);
+
+ /* cfg80211_bss_update gives us a referenced result */
+ return &res->pub;
+}
+EXPORT_SYMBOL(cfg80211_inform_bss);
+
struct cfg80211_bss *
cfg80211_inform_bss_frame(struct wiphy *wiphy,
struct ieee80211_channel *channel,
}
EXPORT_SYMBOL(cfg80211_unlink_bss);
-void cfg80211_hold_bss(struct cfg80211_bss *pub)
-{
- struct cfg80211_internal_bss *bss;
-
- if (!pub)
- return;
-
- bss = container_of(pub, struct cfg80211_internal_bss, pub);
- bss->hold = true;
-}
-EXPORT_SYMBOL(cfg80211_hold_bss);
-
-void cfg80211_unhold_bss(struct cfg80211_bss *pub)
-{
- struct cfg80211_internal_bss *bss;
-
- if (!pub)
- return;
-
- bss = container_of(pub, struct cfg80211_internal_bss, pub);
- bss->hold = false;
-}
-EXPORT_SYMBOL(cfg80211_unhold_bss);
-
#ifdef CONFIG_WIRELESS_EXT
int cfg80211_wext_siwscan(struct net_device *dev,
struct iw_request_info *info,
if (err) {
rdev->scan_req = NULL;
kfree(creq);
- }
+ } else
+ nl80211_send_scan_start(rdev, dev);
out:
- cfg80211_put_dev(rdev);
+ cfg80211_unlock_rdev(rdev);
return err;
}
-EXPORT_SYMBOL(cfg80211_wext_siwscan);
+EXPORT_SYMBOL_GPL(cfg80211_wext_siwscan);
static void ieee80211_scan_add_ies(struct iw_request_info *info,
struct cfg80211_bss *bss,
}
out:
- cfg80211_put_dev(rdev);
+ cfg80211_unlock_rdev(rdev);
return res;
}
-EXPORT_SYMBOL(cfg80211_wext_giwscan);
+EXPORT_SYMBOL_GPL(cfg80211_wext_giwscan);
#endif