From: Sara Sharon <[email protected]>

Free the list inside __cfg80211_unlink_bss and not in
cfg80211_unlink_bss, since not all paths call the later.

Signed-off-by: Sara Sharon <[email protected]>
Signed-off-by: Johannes Berg <[email protected]>
---
 net/wireless/scan.c | 40 +++++++++++++++++++++++++---------------
 1 file changed, 25 insertions(+), 15 deletions(-)

diff --git a/net/wireless/scan.c b/net/wireless/scan.c
index 1e95b46e84e2..1f5535ec4b01 100644
--- a/net/wireless/scan.c
+++ b/net/wireless/scan.c
@@ -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);
-- 
2.17.2

Reply via email to