@@ -152,6 +152,9 @@ static inline void bss_ref_put(struct cfg80211_registered_device *rdev,
static bool __cfg80211_unlink_bss(struct cfg80211_registered_device *rdev,
struct cfg80211_internal_bss *bss)
{
+ struct cfg80211_bss *nontrans_bss, *tmp;
+ struct cfg80211_internal_bss *tmp1;
+
lockdep_assert_held(&rdev->bss_lock);
if (!list_empty(&bss->hidden_list)) {
@@ -168,8 +171,26 @@ static bool __cfg80211_unlink_bss(struct cfg80211_registered_device *rdev,
list_del_init(&bss->hidden_list);
}
- list_del_init(&bss->list);
+ /*
+ * If the deleted entry is a non-transmitting BSS, just remove it
+ * from the list.
+ * if it is the transmitting BSS - free the entire list.
+ */
+ if (!bss->pub.transmitted_bss &&
+ !list_empty(&bss->pub.nontrans_list)) {
+ list_for_each_entry_safe(nontrans_bss, tmp,
+ &bss->pub.nontrans_list,
+ nontrans_list) {
+ tmp1 = container_of(nontrans_bss,
+ struct cfg80211_internal_bss, pub);
+ if (__cfg80211_unlink_bss(rdev, tmp1))
+ rdev->bss_generation++;
+ }
+ }
list_del_init(&bss->pub.nontrans_list);
+
+ list_del_init(&bss->list);
+
rb_erase(&bss->rbn, &rdev->bss_tree);
rdev->bss_entries--;
WARN_ONCE((rdev->bss_entries == 0) ^ list_empty(&rdev->bss_list),
@@ -1787,8 +1808,7 @@ EXPORT_SYMBOL(cfg80211_put_bss);
void cfg80211_unlink_bss(struct wiphy *wiphy, struct cfg80211_bss *pub)
{
struct cfg80211_registered_device *rdev = wiphy_to_rdev(wiphy);
- struct cfg80211_internal_bss *bss, *tmp1;
- struct cfg80211_bss *nontrans_bss, *tmp;
+ struct cfg80211_internal_bss *bss;
if (WARN_ON(!pub))
return;
@@ -1796,21 +1816,11 @@ void cfg80211_unlink_bss(struct wiphy *wiphy, struct cfg80211_bss *pub)
bss = container_of(pub, struct cfg80211_internal_bss, pub);
spin_lock_bh(&rdev->bss_lock);
- if (list_empty(&bss->list))
- goto out;
- list_for_each_entry_safe(nontrans_bss, tmp,
- &pub->nontrans_list,
- nontrans_list) {
- tmp1 = container_of(nontrans_bss,
- struct cfg80211_internal_bss, pub);
- if (__cfg80211_unlink_bss(rdev, tmp1))
+ if (!list_empty(&bss->list))
+ if (__cfg80211_unlink_bss(rdev, bss))
rdev->bss_generation++;
- }
- if (__cfg80211_unlink_bss(rdev, bss))
- rdev->bss_generation++;
-out:
spin_unlock_bh(&rdev->bss_lock);
}
EXPORT_SYMBOL(cfg80211_unlink_bss);