Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 4b215175 authored by Sara Sharon's avatar Sara Sharon Committed by Connor O'Brien
Browse files

UPSTREAM: cfg80211: Move Multiple BSS info to struct cfg80211_bss to be visible



Previously the transmitted BSS and the non-trasmitted BSS list were
defined in struct cfg80211_internal_bss. Move them to struct cfg80211_bss
since mac80211 needs this info.

Signed-off-by: default avatarSara Sharon <sara.sharon@intel.com>
Signed-off-by: default avatarJohannes Berg <johannes.berg@intel.com>
(cherry picked from commit 7011ba583f425780ab1ee52f41161a0171197365)
Bug: 154523213
Signed-off-by: default avatarConnor O'Brien <connoro@google.com>
Change-Id: I8d0780eb2dde7d858b2f57cf001c3d58aa68212e
parent 00ac69ac
Loading
Loading
Loading
Loading
+3 −1
Original line number Diff line number Diff line
@@ -6,7 +6,7 @@
 * Copyright 2006-2010	Johannes Berg <johannes@sipsolutions.net>
 * Copyright 2013-2014 Intel Mobile Communications GmbH
 * Copyright 2015-2017	Intel Deutschland GmbH
 * Copyright (C) 2018 Intel Corporation
 * Copyright (C) 2018-2019 Intel Corporation
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 as
@@ -2089,6 +2089,8 @@ struct cfg80211_bss {
	const struct cfg80211_bss_ies __rcu *proberesp_ies;

	struct cfg80211_bss *hidden_beacon_bss;
	struct cfg80211_bss *transmitted_bss;
	struct list_head nontrans_list;

	s32 signal;

+4 −6
Original line number Diff line number Diff line
@@ -141,8 +141,6 @@ extern int cfg80211_rdev_list_generation;
struct cfg80211_internal_bss {
	struct list_head list;
	struct list_head hidden_list;
	struct list_head nontrans_list;
	struct cfg80211_bss *transmitted_bss;
	struct rb_node rbn;
	u64 ts_boottime;
	unsigned long ts;
@@ -173,8 +171,8 @@ static inline struct cfg80211_internal_bss *bss_from_pub(struct cfg80211_bss *pu
static inline void cfg80211_hold_bss(struct cfg80211_internal_bss *bss)
{
	atomic_inc(&bss->hold);
	if (bss->transmitted_bss) {
		bss = container_of(bss->transmitted_bss,
	if (bss->pub.transmitted_bss) {
		bss = container_of(bss->pub.transmitted_bss,
				   struct cfg80211_internal_bss, pub);
		atomic_inc(&bss->hold);
	}
@@ -184,8 +182,8 @@ static inline void cfg80211_unhold_bss(struct cfg80211_internal_bss *bss)
{
	int r = atomic_dec_return(&bss->hold);
	WARN_ON(r < 0);
	if (bss->transmitted_bss) {
		bss = container_of(bss->transmitted_bss,
	if (bss->pub.transmitted_bss) {
		bss = container_of(bss->pub.transmitted_bss,
				   struct cfg80211_internal_bss, pub);
		r = atomic_dec_return(&bss->hold);
		WARN_ON(r < 0);
+39 −41
Original line number Diff line number Diff line
@@ -110,8 +110,8 @@ static inline void bss_ref_get(struct cfg80211_registered_device *rdev,
				   pub);
		bss->refcount++;
	}
	if (bss->transmitted_bss) {
		bss = container_of(bss->transmitted_bss,
	if (bss->pub.transmitted_bss) {
		bss = container_of(bss->pub.transmitted_bss,
				   struct cfg80211_internal_bss,
				   pub);
		bss->refcount++;
@@ -133,10 +133,10 @@ static inline void bss_ref_put(struct cfg80211_registered_device *rdev,
			bss_free(hbss);
	}

	if (bss->transmitted_bss) {
	if (bss->pub.transmitted_bss) {
		struct cfg80211_internal_bss *tbss;

		tbss = container_of(bss->transmitted_bss,
		tbss = container_of(bss->pub.transmitted_bss,
				    struct cfg80211_internal_bss,
				    pub);
		tbss->refcount--;
@@ -169,7 +169,7 @@ static bool __cfg80211_unlink_bss(struct cfg80211_registered_device *rdev,
	}

	list_del_init(&bss->list);
	list_del_init(&bss->nontrans_list);
	list_del_init(&bss->pub.nontrans_list);
	rb_erase(&bss->rbn, &rdev->bss_tree);
	rdev->bss_entries--;
	WARN_ONCE((rdev->bss_entries == 0) ^ list_empty(&rdev->bss_list),
@@ -317,15 +317,15 @@ static bool is_bss(struct cfg80211_bss *a, const u8 *bssid,
}

static int
cfg80211_add_nontrans_list(struct cfg80211_internal_bss *trans_bss,
			   struct cfg80211_internal_bss *nontrans_bss)
cfg80211_add_nontrans_list(struct cfg80211_bss *trans_bss,
			   struct cfg80211_bss *nontrans_bss)
{
	const u8 *ssid;
	size_t ssid_len;
	struct cfg80211_internal_bss *bss = NULL;
	struct cfg80211_bss *bss = NULL;

	rcu_read_lock();
	ssid = ieee80211_bss_get_ie(&nontrans_bss->pub, WLAN_EID_SSID);
	ssid = ieee80211_bss_get_ie(nontrans_bss, WLAN_EID_SSID);
	if (!ssid) {
		rcu_read_unlock();
		return -EINVAL;
@@ -336,7 +336,7 @@ cfg80211_add_nontrans_list(struct cfg80211_internal_bss *trans_bss,

	/* check if nontrans_bss is in the list */
	list_for_each_entry(bss, &trans_bss->nontrans_list, nontrans_list) {
		if (is_bss(&bss->pub, nontrans_bss->pub.bssid, ssid, ssid_len))
		if (is_bss(bss, nontrans_bss->bssid, ssid, ssid_len))
			return 0;
	}

@@ -1171,7 +1171,7 @@ cfg80211_bss_update(struct cfg80211_registered_device *rdev,
		memcpy(new, tmp, sizeof(*new));
		new->refcount = 1;
		INIT_LIST_HEAD(&new->hidden_list);
		INIT_LIST_HEAD(&new->nontrans_list);
		INIT_LIST_HEAD(&new->pub.nontrans_list);

		if (rcu_access_pointer(tmp->pub.proberesp_ies)) {
			hidden = rb_find_bss(rdev, tmp, BSS_CMP_HIDE_ZLEN);
@@ -1212,7 +1212,7 @@ cfg80211_bss_update(struct cfg80211_registered_device *rdev,
					     struct cfg80211_internal_bss,
					     pub);

			new->transmitted_bss = trans_bss;
			new->pub.transmitted_bss = trans_bss;
			bss_ref_get(rdev, pbss);
		}

@@ -1316,7 +1316,7 @@ cfg80211_inform_single_bss_data(struct wiphy *wiphy,
	struct cfg80211_registered_device *rdev = wiphy_to_rdev(wiphy);
	struct cfg80211_bss_ies *ies;
	struct ieee80211_channel *channel;
	struct cfg80211_internal_bss tmp = {}, *res, *trans_internal;
	struct cfg80211_internal_bss tmp = {}, *res;
	int bss_type;
	bool signal_valid;

@@ -1390,10 +1390,7 @@ cfg80211_inform_single_bss_data(struct wiphy *wiphy,
		/* this is a nontransmitting bss, we need to add it to
		 * transmitting bss' list if it is not there
		 */
		trans_internal = container_of(trans_bss,
					      struct cfg80211_internal_bss,
					      pub);
		if (cfg80211_add_nontrans_list(trans_internal, res)) {
		if (cfg80211_add_nontrans_list(trans_bss, &res->pub)) {
			if (__cfg80211_unlink_bss(rdev, res))
				rdev->bss_generation++;
		}
@@ -1528,7 +1525,7 @@ cfg80211_parse_mbssid_frame_data(struct wiphy *wiphy,

static void
cfg80211_update_notlisted_nontrans(struct wiphy *wiphy,
				   struct cfg80211_internal_bss *nontrans_bss,
				   struct cfg80211_bss *nontrans_bss,
				   struct ieee80211_mgmt *mgmt, size_t len,
				   gfp_t gfp)
{
@@ -1553,7 +1550,7 @@ cfg80211_update_notlisted_nontrans(struct wiphy *wiphy,
		return;
	new_ie_len -= mbssid[1];
	rcu_read_lock();
	nontrans_ssid = ieee80211_bss_get_ie(&nontrans_bss->pub, WLAN_EID_SSID);
	nontrans_ssid = ieee80211_bss_get_ie(nontrans_bss, WLAN_EID_SSID);
	if (!nontrans_ssid) {
		rcu_read_unlock();
		return;
@@ -1594,15 +1591,15 @@ cfg80211_update_notlisted_nontrans(struct wiphy *wiphy,
	new_ies->from_beacon = ieee80211_is_beacon(mgmt->frame_control);
	memcpy(new_ies->data, new_ie, new_ie_len);
	if (ieee80211_is_probe_resp(mgmt->frame_control)) {
		old = rcu_access_pointer(nontrans_bss->pub.proberesp_ies);
		rcu_assign_pointer(nontrans_bss->pub.proberesp_ies, new_ies);
		rcu_assign_pointer(nontrans_bss->pub.ies, new_ies);
		old = rcu_access_pointer(nontrans_bss->proberesp_ies);
		rcu_assign_pointer(nontrans_bss->proberesp_ies, new_ies);
		rcu_assign_pointer(nontrans_bss->ies, new_ies);
		if (old)
			kfree_rcu((struct cfg80211_bss_ies *)old, rcu_head);
	} else {
		old = rcu_access_pointer(nontrans_bss->pub.beacon_ies);
		rcu_assign_pointer(nontrans_bss->pub.beacon_ies, new_ies);
		rcu_assign_pointer(nontrans_bss->pub.ies, new_ies);
		old = rcu_access_pointer(nontrans_bss->beacon_ies);
		rcu_assign_pointer(nontrans_bss->beacon_ies, new_ies);
		rcu_assign_pointer(nontrans_bss->ies, new_ies);
		if (old)
			kfree_rcu((struct cfg80211_bss_ies *)old, rcu_head);
	}
@@ -1701,8 +1698,7 @@ cfg80211_inform_bss_frame_data(struct wiphy *wiphy,
			       struct ieee80211_mgmt *mgmt, size_t len,
			       gfp_t gfp)
{
	struct cfg80211_bss *res;
	struct cfg80211_internal_bss *trans_bss, *tmp_bss;
	struct cfg80211_bss *res, *tmp_bss;
	const u8 *ie = mgmt->u.probe_resp.variable;
	const struct cfg80211_bss_ies *ies1, *ies2;
	size_t ielen = len - offsetof(struct ieee80211_mgmt,
@@ -1720,17 +1716,14 @@ cfg80211_inform_bss_frame_data(struct wiphy *wiphy,
	 * in MBSSID IE
	 */
	ies1 = rcu_access_pointer(res->ies);
	trans_bss = container_of(res, struct cfg80211_internal_bss, pub);
	if (!trans_bss)
		return res;

	/* go through nontrans_list, if the timestamp of the BSS is
	 * earlier than the timestamp of the transmitting BSS then
	 * update it
	 */
	list_for_each_entry(tmp_bss, &trans_bss->nontrans_list,
	list_for_each_entry(tmp_bss, &res->nontrans_list,
			    nontrans_list) {
		ies2 = rcu_access_pointer(tmp_bss->pub.ies);
		ies2 = rcu_access_pointer(tmp_bss->ies);
		if (ies2->tsf < ies1->tsf)
			cfg80211_update_notlisted_nontrans(wiphy, tmp_bss,
							   mgmt, len, gfp);
@@ -1775,7 +1768,8 @@ 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, *nontrans_bss, *tmp;
	struct cfg80211_internal_bss *bss, *tmp1;
	struct cfg80211_bss *nontrans_bss, *tmp;

	if (WARN_ON(!pub))
		return;
@@ -1783,17 +1777,21 @@ 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)) {
	if (list_empty(&bss->list))
		goto out;

	list_for_each_entry_safe(nontrans_bss, tmp,
					 &bss->nontrans_list,
				 &pub->nontrans_list,
				 nontrans_list) {
			if (__cfg80211_unlink_bss(rdev, nontrans_bss))
		tmp1 = container_of(nontrans_bss,
				    struct cfg80211_internal_bss, pub);
		if (__cfg80211_unlink_bss(rdev, tmp1))
			rdev->bss_generation++;
	}

	if (__cfg80211_unlink_bss(rdev, bss))
		rdev->bss_generation++;
	}
out:
	spin_unlock_bh(&rdev->bss_lock);
}
EXPORT_SYMBOL(cfg80211_unlink_bss);