From: Sara Sharon <sara.sharon@xxxxxxxxx> 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 <sara.sharon@xxxxxxxxx> Signed-off-by: Johannes Berg <johannes.berg@xxxxxxxxx> --- 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