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

Commit 39886b61 authored by Thomas Pedersen's avatar Thomas Pedersen Committed by Johannes Berg
Browse files

mac80211: consolidate MBSS change notification



A few mesh utility functions will call
ieee80211_bss_info_change_notify(), and then the caller
might notify the driver of the same change again. Avoid
this redundancy by propagating the BSS changes and
generally calling bss_info_change_notify() once per
change.

Signed-off-by: default avatarThomas Pedersen <thomas@cozybit.com>
Signed-off-by: default avatarJohannes Berg <johannes.berg@intel.com>
parent de74a1d9
Loading
Loading
Loading
Loading
+11 −9
Original line number Original line Diff line number Diff line
@@ -1262,9 +1262,8 @@ static int sta_apply_parameters(struct ieee80211_local *local,


	if (ieee80211_vif_is_mesh(&sdata->vif)) {
	if (ieee80211_vif_is_mesh(&sdata->vif)) {
#ifdef CONFIG_MAC80211_MESH
#ifdef CONFIG_MAC80211_MESH
		if (sdata->u.mesh.security & IEEE80211_MESH_SEC_SECURED) {
		u32 changed = 0;
		u32 changed = 0;

		if (sdata->u.mesh.security & IEEE80211_MESH_SEC_SECURED) {
			switch (params->plink_state) {
			switch (params->plink_state) {
			case NL80211_PLINK_ESTAB:
			case NL80211_PLINK_ESTAB:
				if (sta->plink_state != NL80211_PLINK_ESTAB)
				if (sta->plink_state != NL80211_PLINK_ESTAB)
@@ -1273,7 +1272,7 @@ static int sta_apply_parameters(struct ieee80211_local *local,
				sta->plink_state = params->plink_state;
				sta->plink_state = params->plink_state;


				ieee80211_mps_sta_status_update(sta);
				ieee80211_mps_sta_status_update(sta);
				ieee80211_mps_set_sta_local_pm(sta,
				changed |= ieee80211_mps_set_sta_local_pm(sta,
					      sdata->u.mesh.mshcfg.power_mode);
					      sdata->u.mesh.mshcfg.power_mode);
				break;
				break;
			case NL80211_PLINK_LISTEN:
			case NL80211_PLINK_LISTEN:
@@ -1288,26 +1287,29 @@ static int sta_apply_parameters(struct ieee80211_local *local,
				sta->plink_state = params->plink_state;
				sta->plink_state = params->plink_state;


				ieee80211_mps_sta_status_update(sta);
				ieee80211_mps_sta_status_update(sta);
				changed |=
				      ieee80211_mps_local_status_update(sdata);
				      ieee80211_mps_local_status_update(sdata);
				break;
				break;
			default:
			default:
				/*  nothing  */
				/*  nothing  */
				break;
				break;
			}
			}
			ieee80211_bss_info_change_notify(sdata, changed);
		} else {
		} else {
			switch (params->plink_action) {
			switch (params->plink_action) {
			case PLINK_ACTION_OPEN:
			case PLINK_ACTION_OPEN:
				mesh_plink_open(sta);
				changed |= mesh_plink_open(sta);
				break;
				break;
			case PLINK_ACTION_BLOCK:
			case PLINK_ACTION_BLOCK:
				mesh_plink_block(sta);
				changed |= mesh_plink_block(sta);
				break;
				break;
			}
			}
		}
		}


		if (params->local_pm)
		if (params->local_pm)
			ieee80211_mps_set_sta_local_pm(sta, params->local_pm);
			changed |=
			      ieee80211_mps_set_sta_local_pm(sta,
							     params->local_pm);
		ieee80211_bss_info_change_notify(sdata, changed);
#endif
#endif
	}
	}


+1 −1
Original line number Original line Diff line number Diff line
@@ -675,7 +675,7 @@ void ieee80211_start_mesh(struct ieee80211_sub_if_data *sdata)
	sdata->vif.bss_conf.basic_rates =
	sdata->vif.bss_conf.basic_rates =
		ieee80211_mandatory_rates(local, band);
		ieee80211_mandatory_rates(local, band);


	ieee80211_mps_local_status_update(sdata);
	changed |= ieee80211_mps_local_status_update(sdata);


	ieee80211_bss_info_change_notify(sdata, changed);
	ieee80211_bss_info_change_notify(sdata, changed);


+5 −5
Original line number Original line Diff line number Diff line
@@ -245,8 +245,8 @@ void ieee80211_mesh_root_setup(struct ieee80211_if_mesh *ifmsh);
const struct ieee80211_mesh_sync_ops *ieee80211_mesh_sync_ops_get(u8 method);
const struct ieee80211_mesh_sync_ops *ieee80211_mesh_sync_ops_get(u8 method);


/* mesh power save */
/* mesh power save */
void ieee80211_mps_local_status_update(struct ieee80211_sub_if_data *sdata);
u32 ieee80211_mps_local_status_update(struct ieee80211_sub_if_data *sdata);
void ieee80211_mps_set_sta_local_pm(struct sta_info *sta,
u32 ieee80211_mps_set_sta_local_pm(struct sta_info *sta,
				   enum nl80211_mesh_power_mode pm);
				   enum nl80211_mesh_power_mode pm);
void ieee80211_mps_set_frame_flags(struct ieee80211_sub_if_data *sdata,
void ieee80211_mps_set_frame_flags(struct ieee80211_sub_if_data *sdata,
				   struct sta_info *sta,
				   struct sta_info *sta,
@@ -289,8 +289,8 @@ bool mesh_peer_accepts_plinks(struct ieee802_11_elems *ie);
u32 mesh_accept_plinks_update(struct ieee80211_sub_if_data *sdata);
u32 mesh_accept_plinks_update(struct ieee80211_sub_if_data *sdata);
void mesh_plink_broken(struct sta_info *sta);
void mesh_plink_broken(struct sta_info *sta);
u32 mesh_plink_deactivate(struct sta_info *sta);
u32 mesh_plink_deactivate(struct sta_info *sta);
int mesh_plink_open(struct sta_info *sta);
u32 mesh_plink_open(struct sta_info *sta);
void mesh_plink_block(struct sta_info *sta);
u32 mesh_plink_block(struct sta_info *sta);
void mesh_rx_plink_frame(struct ieee80211_sub_if_data *sdata,
void mesh_rx_plink_frame(struct ieee80211_sub_if_data *sdata,
			 struct ieee80211_mgmt *mgmt, size_t len,
			 struct ieee80211_mgmt *mgmt, size_t len,
			 struct ieee80211_rx_status *rx_status);
			 struct ieee80211_rx_status *rx_status);
+18 −15
Original line number Original line Diff line number Diff line
@@ -202,7 +202,7 @@ static u32 __mesh_plink_deactivate(struct sta_info *sta)
	mesh_path_flush_by_nexthop(sta);
	mesh_path_flush_by_nexthop(sta);


	ieee80211_mps_sta_status_update(sta);
	ieee80211_mps_sta_status_update(sta);
	ieee80211_mps_local_status_update(sdata);
	changed |= ieee80211_mps_local_status_update(sdata);


	return changed;
	return changed;
}
}
@@ -494,6 +494,7 @@ void mesh_neighbour_update(struct ieee80211_sub_if_data *sdata,
			   struct ieee802_11_elems *elems)
			   struct ieee802_11_elems *elems)
{
{
	struct sta_info *sta;
	struct sta_info *sta;
	u32 changed = 0;


	sta = mesh_sta_info_get(sdata, hw_addr, elems);
	sta = mesh_sta_info_get(sdata, hw_addr, elems);
	if (!sta)
	if (!sta)
@@ -504,11 +505,12 @@ void mesh_neighbour_update(struct ieee80211_sub_if_data *sdata,
	    sdata->u.mesh.accepting_plinks &&
	    sdata->u.mesh.accepting_plinks &&
	    sdata->u.mesh.mshcfg.auto_open_plinks &&
	    sdata->u.mesh.mshcfg.auto_open_plinks &&
	    rssi_threshold_check(sta, sdata))
	    rssi_threshold_check(sta, sdata))
		mesh_plink_open(sta);
		changed = mesh_plink_open(sta);


	ieee80211_mps_frame_release(sta, elems);
	ieee80211_mps_frame_release(sta, elems);
out:
out:
	rcu_read_unlock();
	rcu_read_unlock();
	ieee80211_bss_info_change_notify(sdata, changed);
}
}


static void mesh_plink_timer(unsigned long data)
static void mesh_plink_timer(unsigned long data)
@@ -621,13 +623,14 @@ static inline void mesh_plink_timer_set(struct sta_info *sta, int timeout)
	add_timer(&sta->plink_timer);
	add_timer(&sta->plink_timer);
}
}


int mesh_plink_open(struct sta_info *sta)
u32 mesh_plink_open(struct sta_info *sta)
{
{
	__le16 llid;
	__le16 llid;
	struct ieee80211_sub_if_data *sdata = sta->sdata;
	struct ieee80211_sub_if_data *sdata = sta->sdata;
	u32 changed;


	if (!test_sta_flag(sta, WLAN_STA_AUTH))
	if (!test_sta_flag(sta, WLAN_STA_AUTH))
		return -EPERM;
		return 0;


	spin_lock_bh(&sta->lock);
	spin_lock_bh(&sta->lock);
	get_random_bytes(&llid, 2);
	get_random_bytes(&llid, 2);
@@ -635,7 +638,7 @@ int mesh_plink_open(struct sta_info *sta)
	if (sta->plink_state != NL80211_PLINK_LISTEN &&
	if (sta->plink_state != NL80211_PLINK_LISTEN &&
	    sta->plink_state != NL80211_PLINK_BLOCKED) {
	    sta->plink_state != NL80211_PLINK_BLOCKED) {
		spin_unlock_bh(&sta->lock);
		spin_unlock_bh(&sta->lock);
		return -EBUSY;
		return 0;
	}
	}
	sta->plink_state = NL80211_PLINK_OPN_SNT;
	sta->plink_state = NL80211_PLINK_OPN_SNT;
	mesh_plink_timer_set(sta, sdata->u.mesh.mshcfg.dot11MeshRetryTimeout);
	mesh_plink_timer_set(sta, sdata->u.mesh.mshcfg.dot11MeshRetryTimeout);
@@ -645,15 +648,15 @@ int mesh_plink_open(struct sta_info *sta)
		sta->sta.addr);
		sta->sta.addr);


	/* set the non-peer mode to active during peering */
	/* set the non-peer mode to active during peering */
	ieee80211_mps_local_status_update(sdata);
	changed = ieee80211_mps_local_status_update(sdata);


	return mesh_plink_frame_tx(sdata, WLAN_SP_MESH_PEERING_OPEN,
	mesh_plink_frame_tx(sdata, WLAN_SP_MESH_PEERING_OPEN,
			    sta->sta.addr, llid, 0, 0);
			    sta->sta.addr, llid, 0, 0);
	return changed;
}
}


void mesh_plink_block(struct sta_info *sta)
u32 mesh_plink_block(struct sta_info *sta)
{
{
	struct ieee80211_sub_if_data *sdata = sta->sdata;
	u32 changed;
	u32 changed;


	spin_lock_bh(&sta->lock);
	spin_lock_bh(&sta->lock);
@@ -661,7 +664,7 @@ void mesh_plink_block(struct sta_info *sta)
	sta->plink_state = NL80211_PLINK_BLOCKED;
	sta->plink_state = NL80211_PLINK_BLOCKED;
	spin_unlock_bh(&sta->lock);
	spin_unlock_bh(&sta->lock);


	ieee80211_bss_info_change_notify(sdata, changed);
	return changed;
}
}




@@ -882,7 +885,7 @@ void mesh_rx_plink_frame(struct ieee80211_sub_if_data *sdata, struct ieee80211_m
					     mshcfg->dot11MeshRetryTimeout);
					     mshcfg->dot11MeshRetryTimeout);


			/* set the non-peer mode to active during peering */
			/* set the non-peer mode to active during peering */
			ieee80211_mps_local_status_update(sdata);
			changed |= ieee80211_mps_local_status_update(sdata);


			spin_unlock_bh(&sta->lock);
			spin_unlock_bh(&sta->lock);
			mesh_plink_frame_tx(sdata,
			mesh_plink_frame_tx(sdata,
@@ -978,7 +981,7 @@ void mesh_rx_plink_frame(struct ieee80211_sub_if_data *sdata, struct ieee80211_m
			mpl_dbg(sdata, "Mesh plink with %pM ESTABLISHED\n",
			mpl_dbg(sdata, "Mesh plink with %pM ESTABLISHED\n",
				sta->sta.addr);
				sta->sta.addr);
			ieee80211_mps_sta_status_update(sta);
			ieee80211_mps_sta_status_update(sta);
			ieee80211_mps_set_sta_local_pm(sta,
			changed |= ieee80211_mps_set_sta_local_pm(sta,
						       mshcfg->power_mode);
						       mshcfg->power_mode);
			break;
			break;
		default:
		default:
@@ -1020,7 +1023,7 @@ void mesh_rx_plink_frame(struct ieee80211_sub_if_data *sdata, struct ieee80211_m
					    WLAN_SP_MESH_PEERING_CONFIRM,
					    WLAN_SP_MESH_PEERING_CONFIRM,
					    sta->sta.addr, llid, plid, 0);
					    sta->sta.addr, llid, plid, 0);
			ieee80211_mps_sta_status_update(sta);
			ieee80211_mps_sta_status_update(sta);
			ieee80211_mps_set_sta_local_pm(sta,
			changed |= ieee80211_mps_set_sta_local_pm(sta,
							mshcfg->power_mode);
							mshcfg->power_mode);
			break;
			break;
		default:
		default:
+20 −7
Original line number Original line Diff line number Diff line
@@ -74,14 +74,17 @@ static void mps_qos_null_tx(struct sta_info *sta)
 * @sdata: local mesh subif
 * @sdata: local mesh subif
 *
 *
 * sets the non-peer power mode and triggers the driver PS (re-)configuration
 * sets the non-peer power mode and triggers the driver PS (re-)configuration
 * Return BSS_CHANGED_BEACON if a beacon update is necessary.
 */
 */
void ieee80211_mps_local_status_update(struct ieee80211_sub_if_data *sdata)
u32 ieee80211_mps_local_status_update(struct ieee80211_sub_if_data *sdata)
{
{
	struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh;
	struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh;
	struct sta_info *sta;
	struct sta_info *sta;
	bool peering = false;
	bool peering = false;
	int light_sleep_cnt = 0;
	int light_sleep_cnt = 0;
	int deep_sleep_cnt = 0;
	int deep_sleep_cnt = 0;
	u32 changed = 0;
	enum nl80211_mesh_power_mode nonpeer_pm;


	rcu_read_lock();
	rcu_read_lock();
	list_for_each_entry_rcu(sta, &sdata->local->sta_list, list) {
	list_for_each_entry_rcu(sta, &sdata->local->sta_list, list) {
@@ -115,17 +118,26 @@ void ieee80211_mps_local_status_update(struct ieee80211_sub_if_data *sdata)
	 */
	 */
	if (peering) {
	if (peering) {
		mps_dbg(sdata, "setting non-peer PM to active for peering\n");
		mps_dbg(sdata, "setting non-peer PM to active for peering\n");
		ifmsh->nonpeer_pm = NL80211_MESH_POWER_ACTIVE;
		nonpeer_pm = NL80211_MESH_POWER_ACTIVE;
	} else if (light_sleep_cnt || deep_sleep_cnt) {
	} else if (light_sleep_cnt || deep_sleep_cnt) {
		mps_dbg(sdata, "setting non-peer PM to deep sleep\n");
		mps_dbg(sdata, "setting non-peer PM to deep sleep\n");
		ifmsh->nonpeer_pm = NL80211_MESH_POWER_DEEP_SLEEP;
		nonpeer_pm = NL80211_MESH_POWER_DEEP_SLEEP;
	} else {
	} else {
		mps_dbg(sdata, "setting non-peer PM to user value\n");
		mps_dbg(sdata, "setting non-peer PM to user value\n");
		ifmsh->nonpeer_pm = ifmsh->mshcfg.power_mode;
		nonpeer_pm = ifmsh->mshcfg.power_mode;
	}
	}


	/* need update if sleep counts move between 0 and non-zero */
	if (ifmsh->nonpeer_pm != nonpeer_pm ||
	    !ifmsh->ps_peers_light_sleep != !light_sleep_cnt ||
	    !ifmsh->ps_peers_deep_sleep != !deep_sleep_cnt)
		changed = BSS_CHANGED_BEACON;

	ifmsh->nonpeer_pm = nonpeer_pm;
	ifmsh->ps_peers_light_sleep = light_sleep_cnt;
	ifmsh->ps_peers_light_sleep = light_sleep_cnt;
	ifmsh->ps_peers_deep_sleep = deep_sleep_cnt;
	ifmsh->ps_peers_deep_sleep = deep_sleep_cnt;

	return changed;
}
}


/**
/**
@@ -133,8 +145,9 @@ void ieee80211_mps_local_status_update(struct ieee80211_sub_if_data *sdata)
 *
 *
 * @sta: mesh STA
 * @sta: mesh STA
 * @pm: the power mode to set
 * @pm: the power mode to set
 * Return BSS_CHANGED_BEACON if a beacon update is in order.
 */
 */
void ieee80211_mps_set_sta_local_pm(struct sta_info *sta,
u32 ieee80211_mps_set_sta_local_pm(struct sta_info *sta,
				   enum nl80211_mesh_power_mode pm)
				   enum nl80211_mesh_power_mode pm)
{
{
	struct ieee80211_sub_if_data *sdata = sta->sdata;
	struct ieee80211_sub_if_data *sdata = sta->sdata;
@@ -151,7 +164,7 @@ void ieee80211_mps_set_sta_local_pm(struct sta_info *sta,
	if (sta->plink_state == NL80211_PLINK_ESTAB)
	if (sta->plink_state == NL80211_PLINK_ESTAB)
		mps_qos_null_tx(sta);
		mps_qos_null_tx(sta);


	ieee80211_mps_local_status_update(sdata);
	return ieee80211_mps_local_status_update(sdata);
}
}


/**
/**