diff options
author | Thomas Pedersen <thomas@cozybit.com> | 2013-12-15 16:14:16 -0500 |
---|---|---|
committer | Johannes Berg <johannes.berg@intel.com> | 2013-12-16 08:21:22 -0500 |
commit | 43552be1da3c420931c89727b6115b7fa35368f8 (patch) | |
tree | 5dafd30e0d92be9bbf526cf5caec1f78558fe249 | |
parent | d43c6b6e6f2fcaebf198c499716e5e24d878fdd2 (diff) |
mac80211: update adjusting TBTT bit in beacon
This regression was introduced in "mac80211: cache mesh
beacon".
mesh_sync_offset_adjust_tbtt() was assuming that the
beacon would be rebuilt in every single pre-tbtt
interrupt, but now the beacon update happens on the
workqueue, and it must be ready for immediate delivery to
the driver.
Save a pointer to the meshconf IE in the beacon_data (this
works because both the IE pointer and beacon buffer are
protected by the same rcu_{dereference,assign_pointer}())
for quick updates during pre-tbtt. This is faster and a
little prettier than iterating over the elements to find
the meshconf IE every time.
Signed-off-by: Thomas Pedersen <thomas@cozybit.com>
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
-rw-r--r-- | net/mac80211/ieee80211_i.h | 9 | ||||
-rw-r--r-- | net/mac80211/mesh.c | 5 | ||||
-rw-r--r-- | net/mac80211/mesh_sync.c | 9 | ||||
-rw-r--r-- | net/mac80211/tx.c | 3 |
4 files changed, 22 insertions, 4 deletions
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h index ee13c6593b9a..adbff719638c 100644 --- a/net/mac80211/ieee80211_i.h +++ b/net/mac80211/ieee80211_i.h | |||
@@ -232,6 +232,7 @@ struct ieee80211_rx_data { | |||
232 | struct beacon_data { | 232 | struct beacon_data { |
233 | u8 *head, *tail; | 233 | u8 *head, *tail; |
234 | int head_len, tail_len; | 234 | int head_len, tail_len; |
235 | struct ieee80211_meshconf_ie *meshconf; | ||
235 | struct rcu_head rcu_head; | 236 | struct rcu_head rcu_head; |
236 | }; | 237 | }; |
237 | 238 | ||
@@ -540,7 +541,10 @@ struct ieee80211_mesh_sync_ops { | |||
540 | struct ieee80211_mgmt *mgmt, | 541 | struct ieee80211_mgmt *mgmt, |
541 | struct ieee802_11_elems *elems, | 542 | struct ieee802_11_elems *elems, |
542 | struct ieee80211_rx_status *rx_status); | 543 | struct ieee80211_rx_status *rx_status); |
543 | void (*adjust_tbtt)(struct ieee80211_sub_if_data *sdata); | 544 | |
545 | /* should be called with beacon_data under RCU read lock */ | ||
546 | void (*adjust_tbtt)(struct ieee80211_sub_if_data *sdata, | ||
547 | struct beacon_data *beacon); | ||
544 | /* add other framework functions here */ | 548 | /* add other framework functions here */ |
545 | }; | 549 | }; |
546 | 550 | ||
@@ -614,6 +618,9 @@ struct ieee80211_if_mesh { | |||
614 | bool chsw_init; | 618 | bool chsw_init; |
615 | u8 chsw_ttl; | 619 | u8 chsw_ttl; |
616 | u16 pre_value; | 620 | u16 pre_value; |
621 | |||
622 | /* offset from skb->data while building IE */ | ||
623 | int meshconf_offset; | ||
617 | }; | 624 | }; |
618 | 625 | ||
619 | #ifdef CONFIG_MAC80211_MESH | 626 | #ifdef CONFIG_MAC80211_MESH |
diff --git a/net/mac80211/mesh.c b/net/mac80211/mesh.c index 89df62b2b689..5a74b249ba35 100644 --- a/net/mac80211/mesh.c +++ b/net/mac80211/mesh.c | |||
@@ -259,6 +259,9 @@ int mesh_add_meshconf_ie(struct ieee80211_sub_if_data *sdata, | |||
259 | *pos++ = WLAN_EID_MESH_CONFIG; | 259 | *pos++ = WLAN_EID_MESH_CONFIG; |
260 | *pos++ = meshconf_len; | 260 | *pos++ = meshconf_len; |
261 | 261 | ||
262 | /* save a pointer for quick updates in pre-tbtt */ | ||
263 | ifmsh->meshconf_offset = pos - skb->data; | ||
264 | |||
262 | /* Active path selection protocol ID */ | 265 | /* Active path selection protocol ID */ |
263 | *pos++ = ifmsh->mesh_pp_id; | 266 | *pos++ = ifmsh->mesh_pp_id; |
264 | /* Active path selection metric ID */ | 267 | /* Active path selection metric ID */ |
@@ -723,6 +726,8 @@ ieee80211_mesh_build_beacon(struct ieee80211_if_mesh *ifmsh) | |||
723 | 726 | ||
724 | bcn->tail_len = skb->len; | 727 | bcn->tail_len = skb->len; |
725 | memcpy(bcn->tail, skb->data, bcn->tail_len); | 728 | memcpy(bcn->tail, skb->data, bcn->tail_len); |
729 | bcn->meshconf = (struct ieee80211_meshconf_ie *) | ||
730 | (bcn->tail + ifmsh->meshconf_offset); | ||
726 | 731 | ||
727 | dev_kfree_skb(skb); | 732 | dev_kfree_skb(skb); |
728 | rcu_assign_pointer(ifmsh->beacon, bcn); | 733 | rcu_assign_pointer(ifmsh->beacon, bcn); |
diff --git a/net/mac80211/mesh_sync.c b/net/mac80211/mesh_sync.c index d1cf2d553499..2bc5dc25d5ad 100644 --- a/net/mac80211/mesh_sync.c +++ b/net/mac80211/mesh_sync.c | |||
@@ -164,12 +164,15 @@ no_sync: | |||
164 | rcu_read_unlock(); | 164 | rcu_read_unlock(); |
165 | } | 165 | } |
166 | 166 | ||
167 | static void mesh_sync_offset_adjust_tbtt(struct ieee80211_sub_if_data *sdata) | 167 | static void mesh_sync_offset_adjust_tbtt(struct ieee80211_sub_if_data *sdata, |
168 | struct beacon_data *beacon) | ||
168 | { | 169 | { |
169 | struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh; | 170 | struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh; |
171 | u8 cap; | ||
170 | 172 | ||
171 | WARN_ON(ifmsh->mesh_sp_id != IEEE80211_SYNC_METHOD_NEIGHBOR_OFFSET); | 173 | WARN_ON(ifmsh->mesh_sp_id != IEEE80211_SYNC_METHOD_NEIGHBOR_OFFSET); |
172 | BUG_ON(!rcu_read_lock_held()); | 174 | BUG_ON(!rcu_read_lock_held()); |
175 | cap = beacon->meshconf->meshconf_cap; | ||
173 | 176 | ||
174 | spin_lock_bh(&ifmsh->sync_offset_lock); | 177 | spin_lock_bh(&ifmsh->sync_offset_lock); |
175 | 178 | ||
@@ -194,6 +197,10 @@ static void mesh_sync_offset_adjust_tbtt(struct ieee80211_sub_if_data *sdata) | |||
194 | ifmsh->adjusting_tbtt = false; | 197 | ifmsh->adjusting_tbtt = false; |
195 | } | 198 | } |
196 | spin_unlock_bh(&ifmsh->sync_offset_lock); | 199 | spin_unlock_bh(&ifmsh->sync_offset_lock); |
200 | |||
201 | beacon->meshconf->meshconf_cap = ifmsh->adjusting_tbtt ? | ||
202 | IEEE80211_MESHCONF_CAPAB_TBTT_ADJUSTING | cap : | ||
203 | ~IEEE80211_MESHCONF_CAPAB_TBTT_ADJUSTING & cap; | ||
197 | } | 204 | } |
198 | 205 | ||
199 | static const struct sync_method sync_methods[] = { | 206 | static const struct sync_method sync_methods[] = { |
diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c index 002ded2c01f6..2f0e176e7989 100644 --- a/net/mac80211/tx.c +++ b/net/mac80211/tx.c | |||
@@ -2604,8 +2604,7 @@ struct sk_buff *ieee80211_beacon_get_tim(struct ieee80211_hw *hw, | |||
2604 | ieee80211_update_csa(sdata, bcn); | 2604 | ieee80211_update_csa(sdata, bcn); |
2605 | 2605 | ||
2606 | if (ifmsh->sync_ops) | 2606 | if (ifmsh->sync_ops) |
2607 | ifmsh->sync_ops->adjust_tbtt( | 2607 | ifmsh->sync_ops->adjust_tbtt(sdata, bcn); |
2608 | sdata); | ||
2609 | 2608 | ||
2610 | skb = dev_alloc_skb(local->tx_headroom + | 2609 | skb = dev_alloc_skb(local->tx_headroom + |
2611 | bcn->head_len + | 2610 | bcn->head_len + |