From 6962d602056c88ce470f991a265a33132fb95232 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Mon, 23 Jul 2012 14:29:21 +0200 Subject: mac80211: use oper_channel in mesh Using hw.conf.channel is wrong as it could be the temporary channel if any function like the beacon get function is called while scanning or during other temporary out-of-channel activities. Use oper_channel instead. Signed-off-by: Johannes Berg --- net/mac80211/mesh.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'net/mac80211/mesh.c') diff --git a/net/mac80211/mesh.c b/net/mac80211/mesh.c index 6fac18c0423f..03f1696d7d98 100644 --- a/net/mac80211/mesh.c +++ b/net/mac80211/mesh.c @@ -349,17 +349,18 @@ int mesh_add_ds_params_ie(struct sk_buff *skb, { struct ieee80211_local *local = sdata->local; struct ieee80211_supported_band *sband; + struct ieee80211_channel *chan = local->oper_channel; u8 *pos; if (skb_tailroom(skb) < 3) return -ENOMEM; - sband = local->hw.wiphy->bands[local->hw.conf.channel->band]; + sband = local->hw.wiphy->bands[chan->band]; if (sband->band == IEEE80211_BAND_2GHZ) { pos = skb_put(skb, 2 + 1); *pos++ = WLAN_EID_DS_PARAMS; *pos++ = 1; - *pos++ = ieee80211_frequency_to_channel(local->hw.conf.channel->center_freq); + *pos++ = ieee80211_frequency_to_channel(chan->center_freq); } return 0; @@ -603,7 +604,7 @@ void ieee80211_start_mesh(struct ieee80211_sub_if_data *sdata) sdata->vif.bss_conf.beacon_int = MESH_DEFAULT_BEACON_INTERVAL; sdata->vif.bss_conf.basic_rates = ieee80211_mandatory_rates(sdata->local, - sdata->local->hw.conf.channel->band); + sdata->local->oper_channel->band); ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_BEACON | BSS_CHANGED_BEACON_ENABLED | BSS_CHANGED_HT | -- cgit v1.2.3 From c405c6298eacd423098afacf6020ddbda1b0378b Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Mon, 30 Jul 2012 19:44:12 +0200 Subject: mac80211: manage carrier state in mesh Instead of assuming the carrier is on all the time in mesh manage it with joining and leaving the mesh. Signed-off-by: Johannes Berg --- net/mac80211/iface.c | 12 ++++++++---- net/mac80211/mesh.c | 4 ++++ 2 files changed, 12 insertions(+), 4 deletions(-) (limited to 'net/mac80211/mesh.c') diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c index fc8ba83e2c33..c65a03ba809f 100644 --- a/net/mac80211/iface.c +++ b/net/mac80211/iface.c @@ -539,12 +539,16 @@ static int ieee80211_do_open(struct net_device *dev, bool coming_up) changed |= ieee80211_reset_erp_info(sdata); ieee80211_bss_info_change_notify(sdata, changed); - if (sdata->vif.type == NL80211_IFTYPE_STATION || - sdata->vif.type == NL80211_IFTYPE_ADHOC || - sdata->vif.type == NL80211_IFTYPE_AP) + switch (sdata->vif.type) { + case NL80211_IFTYPE_STATION: + case NL80211_IFTYPE_ADHOC: + case NL80211_IFTYPE_AP: + case NL80211_IFTYPE_MESH_POINT: netif_carrier_off(dev); - else + break; + default: netif_carrier_on(dev); + } /* * set default queue parameters so drivers don't diff --git a/net/mac80211/mesh.c b/net/mac80211/mesh.c index 03f1696d7d98..571d5183060e 100644 --- a/net/mac80211/mesh.c +++ b/net/mac80211/mesh.c @@ -610,6 +610,8 @@ void ieee80211_start_mesh(struct ieee80211_sub_if_data *sdata) BSS_CHANGED_HT | BSS_CHANGED_BASIC_RATES | BSS_CHANGED_BEACON_INT); + + netif_carrier_on(sdata->dev); } void ieee80211_stop_mesh(struct ieee80211_sub_if_data *sdata) @@ -617,6 +619,8 @@ void ieee80211_stop_mesh(struct ieee80211_sub_if_data *sdata) struct ieee80211_local *local = sdata->local; struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh; + netif_carrier_off(sdata->dev); + ifmsh->mesh_id_len = 0; ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_BEACON_ENABLED); sta_info_flush(local, NULL); -- cgit v1.2.3 From 0d466b9c6798d431141ab15ae6d5ea413b4d09b2 Mon Sep 17 00:00:00 2001 From: Thomas Pedersen Date: Fri, 3 Aug 2012 12:21:32 -0700 Subject: mac80211: improve cleanup when leaving mesh It is not necessary to stop the mesh beacon in the mac80211 ndo_stop handler, since cfg80211 has already left the mesh on NETDEV_GOING_DOWN notification. Also some improvements to ieee80211_stop_mesh(): - flush mpath entries. - flush sta entries per-sdata so we don't remove entries belonging to other vifs on the same hw. Signed-off-by: Thomas Pedersen Signed-off-by: Johannes Berg --- net/mac80211/iface.c | 8 -------- net/mac80211/mesh.c | 6 +++++- 2 files changed, 5 insertions(+), 9 deletions(-) (limited to 'net/mac80211/mesh.c') diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c index 2d6ac78971ea..5a81577879ed 100644 --- a/net/mac80211/iface.c +++ b/net/mac80211/iface.c @@ -777,14 +777,6 @@ static void ieee80211_do_stop(struct ieee80211_sub_if_data *sdata, synchronize_rcu(); skb_queue_purge(&sdata->skb_queue); - /* - * Disable beaconing here for mesh only, AP and IBSS - * are already taken care of. - */ - if (sdata->vif.type == NL80211_IFTYPE_MESH_POINT) - ieee80211_bss_info_change_notify(sdata, - BSS_CHANGED_BEACON_ENABLED); - /* * Free all remaining keys, there shouldn't be any, * except maybe group keys in AP more or WDS? diff --git a/net/mac80211/mesh.c b/net/mac80211/mesh.c index 571d5183060e..035cd0c8ce33 100644 --- a/net/mac80211/mesh.c +++ b/net/mac80211/mesh.c @@ -621,9 +621,13 @@ void ieee80211_stop_mesh(struct ieee80211_sub_if_data *sdata) netif_carrier_off(sdata->dev); + /* stop the beacon */ ifmsh->mesh_id_len = 0; ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_BEACON_ENABLED); - sta_info_flush(local, NULL); + + /* flush STAs and mpaths on this iface */ + sta_info_flush(sdata->local, sdata); + mesh_path_flush_by_iface(sdata); del_timer_sync(&sdata->u.mesh.housekeeping_timer); del_timer_sync(&sdata->u.mesh.mesh_path_root_timer); -- cgit v1.2.3 From 466f310d100ff54f346c1be481af9935c42467b3 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Wed, 25 Jul 2012 13:51:49 +0200 Subject: mac80211: mesh: don't use global channel type Using local->_oper_channel_type in the mesh code is completely wrong as this value is the combination of the various interface channel types and can be a different value from the mesh interface in case there are multiple virtual interfaces. Use sdata->vif.bss_conf.channel_type instead as it tracks the per-vif channel type. Signed-off-by: Johannes Berg --- net/mac80211/mesh.c | 11 ++++++----- net/mac80211/mesh_plink.c | 7 ++++--- 2 files changed, 10 insertions(+), 8 deletions(-) (limited to 'net/mac80211/mesh.c') diff --git a/net/mac80211/mesh.c b/net/mac80211/mesh.c index 035cd0c8ce33..f2d0d213bcfb 100644 --- a/net/mac80211/mesh.c +++ b/net/mac80211/mesh.c @@ -109,11 +109,11 @@ bool mesh_matches_local(struct ieee80211_sub_if_data *sdata, /* Disallow HT40+/- mismatch */ if (ie->ht_operation && - (local->_oper_channel_type == NL80211_CHAN_HT40MINUS || - local->_oper_channel_type == NL80211_CHAN_HT40PLUS) && + (sdata->vif.bss_conf.channel_type == NL80211_CHAN_HT40MINUS || + sdata->vif.bss_conf.channel_type == NL80211_CHAN_HT40PLUS) && (sta_channel_type == NL80211_CHAN_HT40MINUS || sta_channel_type == NL80211_CHAN_HT40PLUS) && - local->_oper_channel_type != sta_channel_type) + sdata->vif.bss_conf.channel_type != sta_channel_type) goto mismatch; return true; @@ -375,7 +375,7 @@ int mesh_add_ht_cap_ie(struct sk_buff *skb, sband = local->hw.wiphy->bands[local->oper_channel->band]; if (!sband->ht_cap.ht_supported || - local->_oper_channel_type == NL80211_CHAN_NO_HT) + sdata->vif.bss_conf.channel_type == NL80211_CHAN_NO_HT) return 0; if (skb_tailroom(skb) < 2 + sizeof(struct ieee80211_ht_cap)) @@ -392,7 +392,8 @@ int mesh_add_ht_oper_ie(struct sk_buff *skb, { struct ieee80211_local *local = sdata->local; struct ieee80211_channel *channel = local->oper_channel; - enum nl80211_channel_type channel_type = local->_oper_channel_type; + enum nl80211_channel_type channel_type = + sdata->vif.bss_conf.channel_type; struct ieee80211_supported_band *sband = local->hw.wiphy->bands[channel->band]; struct ieee80211_sta_ht_cap *ht_cap = &sband->ht_cap; diff --git a/net/mac80211/mesh_plink.c b/net/mac80211/mesh_plink.c index 5fd1250f7866..54ce1af491eb 100644 --- a/net/mac80211/mesh_plink.c +++ b/net/mac80211/mesh_plink.c @@ -117,7 +117,7 @@ static u32 mesh_set_ht_prot_mode(struct ieee80211_sub_if_data *sdata) u16 ht_opmode; bool non_ht_sta = false, ht20_sta = false; - if (local->_oper_channel_type == NL80211_CHAN_NO_HT) + if (sdata->vif.bss_conf.channel_type == NL80211_CHAN_NO_HT) return 0; rcu_read_lock(); @@ -147,7 +147,8 @@ out: if (non_ht_sta) ht_opmode = IEEE80211_HT_OP_MODE_PROTECTION_NONHT_MIXED; - else if (ht20_sta && local->_oper_channel_type > NL80211_CHAN_HT20) + else if (ht20_sta && + sdata->vif.bss_conf.channel_type > NL80211_CHAN_HT20) ht_opmode = IEEE80211_HT_OP_MODE_PROTECTION_20MHZ; else ht_opmode = IEEE80211_HT_OP_MODE_PROTECTION_NONE; @@ -379,7 +380,7 @@ static struct sta_info *mesh_peer_init(struct ieee80211_sub_if_data *sdata, sta->sta.supp_rates[band] = rates; if (elems->ht_cap_elem && - sdata->local->_oper_channel_type != NL80211_CHAN_NO_HT) + sdata->vif.bss_conf.channel_type != NL80211_CHAN_NO_HT) ieee80211_ht_cap_ie_to_sta_ht_cap(sdata, sband, elems->ht_cap_elem, &sta->sta.ht_cap); -- cgit v1.2.3