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

Commit 699cb58c authored by Johannes Berg's avatar Johannes Berg
Browse files

mac80211: manage RX BA session offload without SKB queue



Instead of using the SKB queue with the fake pkt_type for the
offloaded RX BA session management, also handle this with the
normal aggregation state machine worker. This also makes the
use of this more reliable since it gets rid of the allocation
of the fake skb.

Combined with the previous patch, this finally allows us to
get rid of the pkt_type hack entirely, so do that as well.

Signed-off-by: default avatarJohannes Berg <johannes.berg@intel.com>
parent a43e6184
Loading
Loading
Loading
Loading
+17 −4
Original line number Diff line number Diff line
@@ -5452,6 +5452,9 @@ void ieee80211_mark_rx_ba_filtered_frames(struct ieee80211_sta *pubsta, u8 tid,
 */
void ieee80211_send_bar(struct ieee80211_vif *vif, u8 *ra, u16 tid, u16 ssn);

void ieee80211_manage_rx_ba_offl(struct ieee80211_vif *vif, const u8 *addr,
				 unsigned int bit);

/**
 * ieee80211_start_rx_ba_session_offl - start a Rx BA session
 *
@@ -5466,8 +5469,13 @@ void ieee80211_send_bar(struct ieee80211_vif *vif, u8 *ra, u16 tid, u16 ssn);
 * @addr: station mac address
 * @tid: the rx tid
 */
void ieee80211_start_rx_ba_session_offl(struct ieee80211_vif *vif,
					const u8 *addr, u16 tid);
static inline void ieee80211_start_rx_ba_session_offl(struct ieee80211_vif *vif,
						      const u8 *addr, u16 tid)
{
	if (WARN_ON(tid >= IEEE80211_NUM_TIDS))
		return;
	ieee80211_manage_rx_ba_offl(vif, addr, tid);
}

/**
 * ieee80211_stop_rx_ba_session_offl - stop a Rx BA session
@@ -5483,8 +5491,13 @@ void ieee80211_start_rx_ba_session_offl(struct ieee80211_vif *vif,
 * @addr: station mac address
 * @tid: the rx tid
 */
void ieee80211_stop_rx_ba_session_offl(struct ieee80211_vif *vif,
				       const u8 *addr, u16 tid);
static inline void ieee80211_stop_rx_ba_session_offl(struct ieee80211_vif *vif,
						     const u8 *addr, u16 tid)
{
	if (WARN_ON(tid >= IEEE80211_NUM_TIDS))
		return;
	ieee80211_manage_rx_ba_offl(vif, addr, tid + IEEE80211_NUM_TIDS);
}

/* Rate control API */

+12 −35
Original line number Diff line number Diff line
@@ -449,44 +449,21 @@ void ieee80211_process_addba_request(struct ieee80211_local *local,
					buf_size, true, false);
}

void ieee80211_start_rx_ba_session_offl(struct ieee80211_vif *vif,
					const u8 *addr, u16 tid)
void ieee80211_manage_rx_ba_offl(struct ieee80211_vif *vif,
				 const u8 *addr, unsigned int bit)
{
	struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif);
	struct ieee80211_local *local = sdata->local;
	struct ieee80211_rx_agg *rx_agg;
	struct sk_buff *skb = dev_alloc_skb(0);

	if (unlikely(!skb))
		return;

	rx_agg = (struct ieee80211_rx_agg *) &skb->cb;
	memcpy(&rx_agg->addr, addr, ETH_ALEN);
	rx_agg->tid = tid;

	skb->pkt_type = IEEE80211_SDATA_QUEUE_RX_AGG_START;
	skb_queue_tail(&sdata->skb_queue, skb);
	ieee80211_queue_work(&local->hw, &sdata->work);
}
EXPORT_SYMBOL(ieee80211_start_rx_ba_session_offl);

void ieee80211_stop_rx_ba_session_offl(struct ieee80211_vif *vif,
				       const u8 *addr, u16 tid)
{
	struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif);
	struct ieee80211_local *local = sdata->local;
	struct ieee80211_rx_agg *rx_agg;
	struct sk_buff *skb = dev_alloc_skb(0);

	if (unlikely(!skb))
		return;
	struct sta_info *sta;

	rx_agg = (struct ieee80211_rx_agg *) &skb->cb;
	memcpy(&rx_agg->addr, addr, ETH_ALEN);
	rx_agg->tid = tid;
	rcu_read_lock();
	sta = sta_info_get_bss(sdata, addr);
	if (!sta)
		goto unlock;

	skb->pkt_type = IEEE80211_SDATA_QUEUE_RX_AGG_STOP;
	skb_queue_tail(&sdata->skb_queue, skb);
	ieee80211_queue_work(&local->hw, &sdata->work);
	set_bit(bit, sta->ampdu_mlme.tid_rx_manage_offl);
	ieee80211_queue_work(&local->hw, &sta->ampdu_mlme.work);
 unlock:
	rcu_read_unlock();
}
EXPORT_SYMBOL(ieee80211_stop_rx_ba_session_offl);
EXPORT_SYMBOL(ieee80211_manage_rx_ba_offl);
+12 −0
Original line number Diff line number Diff line
@@ -331,6 +331,18 @@ void ieee80211_ba_session_work(struct work_struct *work)
				sta, tid, WLAN_BACK_RECIPIENT,
				WLAN_REASON_UNSPECIFIED, true);

		if (test_and_clear_bit(tid,
				       sta->ampdu_mlme.tid_rx_manage_offl))
			__ieee80211_start_rx_ba_session(sta, 0, 0, 0, 1, tid,
							IEEE80211_MAX_AMPDU_BUF,
							false, true);

		if (test_and_clear_bit(tid + IEEE80211_NUM_TIDS,
				       sta->ampdu_mlme.tid_rx_manage_offl))
			___ieee80211_stop_rx_ba_session(
				sta, tid, WLAN_BACK_RECIPIENT,
				0, false);

		spin_lock_bh(&sta->lock);

		tid_tx = sta->ampdu_mlme.tid_start_tx[tid];
+0 −11
Original line number Diff line number Diff line
@@ -1031,17 +1031,6 @@ ieee80211_vif_get_shift(struct ieee80211_vif *vif)
	return shift;
}

struct ieee80211_rx_agg {
	u8 addr[ETH_ALEN];
	u16 tid;
};

enum sdata_queue_type {
	IEEE80211_SDATA_QUEUE_TYPE_FRAME	= 0,
	IEEE80211_SDATA_QUEUE_RX_AGG_START	= 3,
	IEEE80211_SDATA_QUEUE_RX_AGG_STOP	= 4,
};

enum {
	IEEE80211_RX_MSG	= 1,
	IEEE80211_TX_STATUS_MSG	= 2,
+2 −23
Original line number Diff line number Diff line
@@ -1237,7 +1237,6 @@ static void ieee80211_iface_work(struct work_struct *work)
	struct ieee80211_local *local = sdata->local;
	struct sk_buff *skb;
	struct sta_info *sta;
	struct ieee80211_rx_agg *rx_agg;

	if (!ieee80211_sdata_running(sdata))
		return;
@@ -1252,27 +1251,7 @@ static void ieee80211_iface_work(struct work_struct *work)
	while ((skb = skb_dequeue(&sdata->skb_queue))) {
		struct ieee80211_mgmt *mgmt = (void *)skb->data;

		if (skb->pkt_type == IEEE80211_SDATA_QUEUE_RX_AGG_START) {
			rx_agg = (void *)&skb->cb;
			mutex_lock(&local->sta_mtx);
			sta = sta_info_get_bss(sdata, rx_agg->addr);
			if (sta)
				__ieee80211_start_rx_ba_session(sta,
						0, 0, 0, 1, rx_agg->tid,
						IEEE80211_MAX_AMPDU_BUF,
						false, true);
			mutex_unlock(&local->sta_mtx);
		} else if (skb->pkt_type == IEEE80211_SDATA_QUEUE_RX_AGG_STOP) {
			rx_agg = (void *)&skb->cb;
			mutex_lock(&local->sta_mtx);
			sta = sta_info_get_bss(sdata, rx_agg->addr);
			if (sta)
				__ieee80211_stop_rx_ba_session(sta,
							rx_agg->tid,
							WLAN_BACK_RECIPIENT, 0,
							false);
			mutex_unlock(&local->sta_mtx);
		} else if (ieee80211_is_action(mgmt->frame_control) &&
		if (ieee80211_is_action(mgmt->frame_control) &&
		    mgmt->u.action.category == WLAN_CATEGORY_BACK) {
			int len = skb->len;

Loading