aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorThomas Pedersen <thomas@cozybit.com>2013-12-15 16:14:16 -0500
committerJohannes Berg <johannes.berg@intel.com>2013-12-16 08:21:22 -0500
commit43552be1da3c420931c89727b6115b7fa35368f8 (patch)
tree5dafd30e0d92be9bbf526cf5caec1f78558fe249
parentd43c6b6e6f2fcaebf198c499716e5e24d878fdd2 (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.h9
-rw-r--r--net/mac80211/mesh.c5
-rw-r--r--net/mac80211/mesh_sync.c9
-rw-r--r--net/mac80211/tx.c3
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 {
232struct beacon_data { 232struct 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
167static void mesh_sync_offset_adjust_tbtt(struct ieee80211_sub_if_data *sdata) 167static 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
199static const struct sync_method sync_methods[] = { 206static 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 +