mirror of
https://github.com/edk2-porting/linux-next.git
synced 2024-12-15 08:44:14 +08:00
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>
This commit is contained in:
parent
d43c6b6e6f
commit
43552be1da
@ -232,6 +232,7 @@ struct ieee80211_rx_data {
|
||||
struct beacon_data {
|
||||
u8 *head, *tail;
|
||||
int head_len, tail_len;
|
||||
struct ieee80211_meshconf_ie *meshconf;
|
||||
struct rcu_head rcu_head;
|
||||
};
|
||||
|
||||
@ -540,7 +541,10 @@ struct ieee80211_mesh_sync_ops {
|
||||
struct ieee80211_mgmt *mgmt,
|
||||
struct ieee802_11_elems *elems,
|
||||
struct ieee80211_rx_status *rx_status);
|
||||
void (*adjust_tbtt)(struct ieee80211_sub_if_data *sdata);
|
||||
|
||||
/* should be called with beacon_data under RCU read lock */
|
||||
void (*adjust_tbtt)(struct ieee80211_sub_if_data *sdata,
|
||||
struct beacon_data *beacon);
|
||||
/* add other framework functions here */
|
||||
};
|
||||
|
||||
@ -614,6 +618,9 @@ struct ieee80211_if_mesh {
|
||||
bool chsw_init;
|
||||
u8 chsw_ttl;
|
||||
u16 pre_value;
|
||||
|
||||
/* offset from skb->data while building IE */
|
||||
int meshconf_offset;
|
||||
};
|
||||
|
||||
#ifdef CONFIG_MAC80211_MESH
|
||||
|
@ -259,6 +259,9 @@ int mesh_add_meshconf_ie(struct ieee80211_sub_if_data *sdata,
|
||||
*pos++ = WLAN_EID_MESH_CONFIG;
|
||||
*pos++ = meshconf_len;
|
||||
|
||||
/* save a pointer for quick updates in pre-tbtt */
|
||||
ifmsh->meshconf_offset = pos - skb->data;
|
||||
|
||||
/* Active path selection protocol ID */
|
||||
*pos++ = ifmsh->mesh_pp_id;
|
||||
/* Active path selection metric ID */
|
||||
@ -723,6 +726,8 @@ ieee80211_mesh_build_beacon(struct ieee80211_if_mesh *ifmsh)
|
||||
|
||||
bcn->tail_len = skb->len;
|
||||
memcpy(bcn->tail, skb->data, bcn->tail_len);
|
||||
bcn->meshconf = (struct ieee80211_meshconf_ie *)
|
||||
(bcn->tail + ifmsh->meshconf_offset);
|
||||
|
||||
dev_kfree_skb(skb);
|
||||
rcu_assign_pointer(ifmsh->beacon, bcn);
|
||||
|
@ -164,12 +164,15 @@ no_sync:
|
||||
rcu_read_unlock();
|
||||
}
|
||||
|
||||
static void mesh_sync_offset_adjust_tbtt(struct ieee80211_sub_if_data *sdata)
|
||||
static void mesh_sync_offset_adjust_tbtt(struct ieee80211_sub_if_data *sdata,
|
||||
struct beacon_data *beacon)
|
||||
{
|
||||
struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh;
|
||||
u8 cap;
|
||||
|
||||
WARN_ON(ifmsh->mesh_sp_id != IEEE80211_SYNC_METHOD_NEIGHBOR_OFFSET);
|
||||
BUG_ON(!rcu_read_lock_held());
|
||||
cap = beacon->meshconf->meshconf_cap;
|
||||
|
||||
spin_lock_bh(&ifmsh->sync_offset_lock);
|
||||
|
||||
@ -194,6 +197,10 @@ static void mesh_sync_offset_adjust_tbtt(struct ieee80211_sub_if_data *sdata)
|
||||
ifmsh->adjusting_tbtt = false;
|
||||
}
|
||||
spin_unlock_bh(&ifmsh->sync_offset_lock);
|
||||
|
||||
beacon->meshconf->meshconf_cap = ifmsh->adjusting_tbtt ?
|
||||
IEEE80211_MESHCONF_CAPAB_TBTT_ADJUSTING | cap :
|
||||
~IEEE80211_MESHCONF_CAPAB_TBTT_ADJUSTING & cap;
|
||||
}
|
||||
|
||||
static const struct sync_method sync_methods[] = {
|
||||
|
@ -2604,8 +2604,7 @@ struct sk_buff *ieee80211_beacon_get_tim(struct ieee80211_hw *hw,
|
||||
ieee80211_update_csa(sdata, bcn);
|
||||
|
||||
if (ifmsh->sync_ops)
|
||||
ifmsh->sync_ops->adjust_tbtt(
|
||||
sdata);
|
||||
ifmsh->sync_ops->adjust_tbtt(sdata, bcn);
|
||||
|
||||
skb = dev_alloc_skb(local->tx_headroom +
|
||||
bcn->head_len +
|
||||
|
Loading…
Reference in New Issue
Block a user