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

Commit 43552be1 authored by Thomas Pedersen's avatar Thomas Pedersen Committed by Johannes Berg
Browse files

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: default avatarThomas Pedersen <thomas@cozybit.com>
Signed-off-by: default avatarJohannes Berg <johannes.berg@intel.com>
parent d43c6b6e
Loading
Loading
Loading
Loading
+8 −1
Original line number Original line Diff line number Diff line
@@ -232,6 +232,7 @@ struct ieee80211_rx_data {
struct beacon_data {
struct beacon_data {
	u8 *head, *tail;
	u8 *head, *tail;
	int head_len, tail_len;
	int head_len, tail_len;
	struct ieee80211_meshconf_ie *meshconf;
	struct rcu_head rcu_head;
	struct rcu_head rcu_head;
};
};


@@ -540,7 +541,10 @@ struct ieee80211_mesh_sync_ops {
			     struct ieee80211_mgmt *mgmt,
			     struct ieee80211_mgmt *mgmt,
			     struct ieee802_11_elems *elems,
			     struct ieee802_11_elems *elems,
			     struct ieee80211_rx_status *rx_status);
			     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 */
	/* add other framework functions here */
};
};


@@ -614,6 +618,9 @@ struct ieee80211_if_mesh {
	bool chsw_init;
	bool chsw_init;
	u8 chsw_ttl;
	u8 chsw_ttl;
	u16 pre_value;
	u16 pre_value;

	/* offset from skb->data while building IE */
	int meshconf_offset;
};
};


#ifdef CONFIG_MAC80211_MESH
#ifdef CONFIG_MAC80211_MESH
+5 −0
Original line number Original line Diff line number Diff line
@@ -259,6 +259,9 @@ int mesh_add_meshconf_ie(struct ieee80211_sub_if_data *sdata,
	*pos++ = WLAN_EID_MESH_CONFIG;
	*pos++ = WLAN_EID_MESH_CONFIG;
	*pos++ = meshconf_len;
	*pos++ = meshconf_len;


	/* save a pointer for quick updates in pre-tbtt */
	ifmsh->meshconf_offset = pos - skb->data;

	/* Active path selection protocol ID */
	/* Active path selection protocol ID */
	*pos++ = ifmsh->mesh_pp_id;
	*pos++ = ifmsh->mesh_pp_id;
	/* Active path selection metric ID   */
	/* Active path selection metric ID   */
@@ -723,6 +726,8 @@ ieee80211_mesh_build_beacon(struct ieee80211_if_mesh *ifmsh)


	bcn->tail_len = skb->len;
	bcn->tail_len = skb->len;
	memcpy(bcn->tail, skb->data, bcn->tail_len);
	memcpy(bcn->tail, skb->data, bcn->tail_len);
	bcn->meshconf = (struct ieee80211_meshconf_ie *)
					(bcn->tail + ifmsh->meshconf_offset);


	dev_kfree_skb(skb);
	dev_kfree_skb(skb);
	rcu_assign_pointer(ifmsh->beacon, bcn);
	rcu_assign_pointer(ifmsh->beacon, bcn);
+8 −1
Original line number Original line Diff line number Diff line
@@ -164,12 +164,15 @@ static void mesh_sync_offset_rx_bcn_presp(struct ieee80211_sub_if_data *sdata,
	rcu_read_unlock();
	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;
	struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh;
	u8 cap;


	WARN_ON(ifmsh->mesh_sp_id != IEEE80211_SYNC_METHOD_NEIGHBOR_OFFSET);
	WARN_ON(ifmsh->mesh_sp_id != IEEE80211_SYNC_METHOD_NEIGHBOR_OFFSET);
	BUG_ON(!rcu_read_lock_held());
	BUG_ON(!rcu_read_lock_held());
	cap = beacon->meshconf->meshconf_cap;


	spin_lock_bh(&ifmsh->sync_offset_lock);
	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;
		ifmsh->adjusting_tbtt = false;
	}
	}
	spin_unlock_bh(&ifmsh->sync_offset_lock);
	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[] = {
static const struct sync_method sync_methods[] = {
+1 −2
Original line number Original line Diff line number Diff line
@@ -2604,8 +2604,7 @@ struct sk_buff *ieee80211_beacon_get_tim(struct ieee80211_hw *hw,
			ieee80211_update_csa(sdata, bcn);
			ieee80211_update_csa(sdata, bcn);


		if (ifmsh->sync_ops)
		if (ifmsh->sync_ops)
			ifmsh->sync_ops->adjust_tbtt(
			ifmsh->sync_ops->adjust_tbtt(sdata, bcn);
						sdata);


		skb = dev_alloc_skb(local->tx_headroom +
		skb = dev_alloc_skb(local->tx_headroom +
				    bcn->head_len +
				    bcn->head_len +