Browse Source

mac80211: add support for reporting tx status without attached skb

Signed-off-by: Felix Fietkau <[email protected]>

SVN-Revision: 43297
Felix Fietkau 11 years ago
parent
commit
9cd492b3e1

+ 33 - 0
package/kernel/mac80211/patches/313-mac80211-minstrel_ht-add-a-small-optimization-to-min.patch

@@ -0,0 +1,33 @@
+From: Felix Fietkau <[email protected]>
+Date: Sat, 15 Nov 2014 22:13:38 +0100
+Subject: [PATCH] mac80211: minstrel_ht: add a small optimization to
+ minstrel_aggr_check
+
+Check the queue mapping earlier, skb->queue_mapping is more likely than
+skb->data to still be in d-cache.
+
+Signed-off-by: Felix Fietkau <[email protected]>
+---
+
+--- a/net/mac80211/rc80211_minstrel_ht.c
++++ b/net/mac80211/rc80211_minstrel_ht.c
+@@ -690,6 +690,9 @@ minstrel_aggr_check(struct ieee80211_sta
+ 	struct sta_info *sta = container_of(pubsta, struct sta_info, sta);
+ 	u16 tid;
+ 
++	if (skb_get_queue_mapping(skb) == IEEE80211_AC_VO)
++		return;
++
+ 	if (unlikely(!ieee80211_is_data_qos(hdr->frame_control)))
+ 		return;
+ 
+@@ -700,9 +703,6 @@ minstrel_aggr_check(struct ieee80211_sta
+ 	if (likely(sta->ampdu_mlme.tid_tx[tid]))
+ 		return;
+ 
+-	if (skb_get_queue_mapping(skb) == IEEE80211_AC_VO)
+-		return;
+-
+ 	ieee80211_start_tx_ba_session(pubsta, tid, 5000);
+ }
+ 

+ 33 - 0
package/kernel/mac80211/patches/314-mac80211-minstrel_ht-move-aggregation-check-to-.get_.patch

@@ -0,0 +1,33 @@
+From: Felix Fietkau <[email protected]>
+Date: Sat, 15 Nov 2014 22:16:36 +0100
+Subject: [PATCH] mac80211: minstrel_ht: move aggregation check to
+ .get_rate()
+
+Preparation for adding a no-skb tx status path
+
+Signed-off-by: Felix Fietkau <[email protected]>
+---
+
+--- a/net/mac80211/rc80211_minstrel_ht.c
++++ b/net/mac80211/rc80211_minstrel_ht.c
+@@ -782,9 +782,6 @@ minstrel_ht_tx_status(void *priv, struct
+ 	if (time_after(jiffies, mi->stats_update + (mp->update_interval / 2 * HZ) / 1000)) {
+ 		update = true;
+ 		minstrel_ht_update_stats(mp, mi);
+-		if (!(info->flags & IEEE80211_TX_CTL_AMPDU) &&
+-		    mi->max_prob_rate / MCS_GROUP_RATES != MINSTREL_CCK_GROUP)
+-			minstrel_aggr_check(sta, skb);
+ 	}
+ 
+ 	if (update)
+@@ -1026,6 +1023,10 @@ minstrel_ht_get_rate(void *priv, struct 
+ 	if (!msp->is_ht)
+ 		return mac80211_minstrel.get_rate(priv, sta, &msp->legacy, txrc);
+ 
++	if (!(info->flags & IEEE80211_TX_CTL_AMPDU) &&
++		mi->max_prob_rate / MCS_GROUP_RATES != MINSTREL_CCK_GROUP)
++		minstrel_aggr_check(sta, txrc->skb);
++
+ 	info->flags |= mi->tx_flags;
+ 	minstrel_ht_check_cck_shortpreamble(mp, mi, txrc->short_preamble);
+ 

+ 43 - 0
package/kernel/mac80211/patches/315-mac80211-add-tx_status_noskb-to-rate_control_ops.patch

@@ -0,0 +1,43 @@
+From: Felix Fietkau <[email protected]>
+Date: Sat, 15 Nov 2014 22:23:44 +0100
+Subject: [PATCH] mac80211: add tx_status_noskb to rate_control_ops
+
+This op works like .tx_status, except it does not need access to the
+skb. This will be used by drivers that cannot match tx status
+information to specific packets.
+
+Signed-off-by: Felix Fietkau <[email protected]>
+---
+
+--- a/include/net/mac80211.h
++++ b/include/net/mac80211.h
+@@ -4727,6 +4727,10 @@ struct rate_control_ops {
+ 	void (*free_sta)(void *priv, struct ieee80211_sta *sta,
+ 			 void *priv_sta);
+ 
++	void (*tx_status_noskb)(void *priv,
++				struct ieee80211_supported_band *sband,
++				struct ieee80211_sta *sta, void *priv_sta,
++				struct ieee80211_tx_info *info);
+ 	void (*tx_status)(void *priv, struct ieee80211_supported_band *sband,
+ 			  struct ieee80211_sta *sta, void *priv_sta,
+ 			  struct sk_buff *skb);
+--- a/net/mac80211/rate.h
++++ b/net/mac80211/rate.h
+@@ -37,11 +37,15 @@ static inline void rate_control_tx_statu
+ 	struct rate_control_ref *ref = local->rate_ctrl;
+ 	struct ieee80211_sta *ista = &sta->sta;
+ 	void *priv_sta = sta->rate_ctrl_priv;
++	struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
+ 
+ 	if (!ref || !test_sta_flag(sta, WLAN_STA_RATE_CONTROL))
+ 		return;
+ 
+-	ref->ops->tx_status(ref->priv, sband, ista, priv_sta, skb);
++	if (ref->ops->tx_status)
++		ref->ops->tx_status(ref->priv, sband, ista, priv_sta, skb);
++	else
++		ref->ops->tx_status_noskb(ref->priv, sband, ista, priv_sta, info);
+ }
+ 
+ 

+ 31 - 0
package/kernel/mac80211/patches/316-mac80211-minstrel-switch-to-.tx_status_noskb.patch

@@ -0,0 +1,31 @@
+From: Felix Fietkau <[email protected]>
+Date: Sat, 15 Nov 2014 22:38:07 +0100
+Subject: [PATCH] mac80211: minstrel: switch to .tx_status_noskb
+
+Signed-off-by: Felix Fietkau <[email protected]>
+---
+
+--- a/net/mac80211/rc80211_minstrel.c
++++ b/net/mac80211/rc80211_minstrel.c
+@@ -223,11 +223,10 @@ minstrel_update_stats(struct minstrel_pr
+ static void
+ minstrel_tx_status(void *priv, struct ieee80211_supported_band *sband,
+ 		   struct ieee80211_sta *sta, void *priv_sta,
+-		   struct sk_buff *skb)
++		   struct ieee80211_tx_info *info)
+ {
+ 	struct minstrel_priv *mp = priv;
+ 	struct minstrel_sta_info *mi = priv_sta;
+-	struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
+ 	struct ieee80211_tx_rate *ar = info->status.rates;
+ 	int i, ndx;
+ 	int success;
+@@ -674,7 +673,7 @@ static u32 minstrel_get_expected_through
+ 
+ const struct rate_control_ops mac80211_minstrel = {
+ 	.name = "minstrel",
+-	.tx_status = minstrel_tx_status,
++	.tx_status_noskb = minstrel_tx_status,
+ 	.get_rate = minstrel_get_rate,
+ 	.rate_init = minstrel_rate_init,
+ 	.alloc = minstrel_alloc,

+ 41 - 0
package/kernel/mac80211/patches/317-mac80211-minstrel_ht-switch-to-.tx_status_noskb.patch

@@ -0,0 +1,41 @@
+From: Felix Fietkau <[email protected]>
+Date: Sat, 15 Nov 2014 22:38:21 +0100
+Subject: [PATCH] mac80211: minstrel_ht: switch to .tx_status_noskb
+
+Signed-off-by: Felix Fietkau <[email protected]>
+---
+
+--- a/net/mac80211/rc80211_minstrel_ht.c
++++ b/net/mac80211/rc80211_minstrel_ht.c
+@@ -709,11 +709,10 @@ minstrel_aggr_check(struct ieee80211_sta
+ static void
+ minstrel_ht_tx_status(void *priv, struct ieee80211_supported_band *sband,
+                       struct ieee80211_sta *sta, void *priv_sta,
+-                      struct sk_buff *skb)
++                      struct ieee80211_tx_info *info)
+ {
+ 	struct minstrel_ht_sta_priv *msp = priv_sta;
+ 	struct minstrel_ht_sta *mi = &msp->ht;
+-	struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
+ 	struct ieee80211_tx_rate *ar = info->status.rates;
+ 	struct minstrel_rate_stats *rate, *rate2;
+ 	struct minstrel_priv *mp = priv;
+@@ -721,7 +720,8 @@ minstrel_ht_tx_status(void *priv, struct
+ 	int i;
+ 
+ 	if (!msp->is_ht)
+-		return mac80211_minstrel.tx_status(priv, sband, sta, &msp->legacy, skb);
++		return mac80211_minstrel.tx_status_noskb(priv, sband, sta,
++							 &msp->legacy, info);
+ 
+ 	/* This packet was aggregated but doesn't carry status info */
+ 	if ((info->flags & IEEE80211_TX_CTL_AMPDU) &&
+@@ -1343,7 +1343,7 @@ static u32 minstrel_ht_get_expected_thro
+ 
+ static const struct rate_control_ops mac80211_minstrel_ht = {
+ 	.name = "minstrel_ht",
+-	.tx_status = minstrel_ht_tx_status,
++	.tx_status_noskb = minstrel_ht_tx_status,
+ 	.get_rate = minstrel_ht_get_rate,
+ 	.rate_init = minstrel_ht_rate_init,
+ 	.rate_update = minstrel_ht_rate_update,

+ 219 - 0
package/kernel/mac80211/patches/318-mac80211-add-ieee80211_tx_status_noskb.patch

@@ -0,0 +1,219 @@
+From: Felix Fietkau <[email protected]>
+Date: Sat, 15 Nov 2014 23:50:27 +0100
+Subject: [PATCH] mac80211: add ieee80211_tx_status_noskb
+
+This can be used by drivers that cannot reliably map tx status
+information onto specific skbs.
+
+Signed-off-by: Felix Fietkau <[email protected]>
+---
+
+--- a/include/net/mac80211.h
++++ b/include/net/mac80211.h
+@@ -3517,6 +3517,28 @@ void ieee80211_tx_status(struct ieee8021
+ 			 struct sk_buff *skb);
+ 
+ /**
++ * ieee80211_tx_status_noskb - transmit status callback without skb
++ *
++ * This function can be used as a replacement for ieee80211_tx_status
++ * in drivers that cannot reliably map tx status information back to
++ * specific skbs.
++ *
++ * This function may not be called in IRQ context. Calls to this function
++ * for a single hardware must be synchronized against each other. Calls
++ * to this function, ieee80211_tx_status_ni() and ieee80211_tx_status_irqsafe()
++ * may not be mixed for a single hardware. Must not run concurrently with
++ * ieee80211_rx() or ieee80211_rx_ni().
++ *
++ * @hw: the hardware the frame was transmitted by
++ * @sta: the receiver station to which this packet is sent
++ *	(NULL for multicast packets)
++ * @info: tx status information
++ */
++void ieee80211_tx_status_noskb(struct ieee80211_hw *hw,
++			       struct ieee80211_sta *sta,
++			       struct ieee80211_tx_info *info);
++
++/**
+  * ieee80211_tx_status_ni - transmit status callback (in process context)
+  *
+  * Like ieee80211_tx_status() but can be called in process context.
+--- a/net/mac80211/rate.h
++++ b/net/mac80211/rate.h
+@@ -49,6 +49,23 @@ static inline void rate_control_tx_statu
+ }
+ 
+ 
++static inline void
++rate_control_tx_status_noskb(struct ieee80211_local *local,
++			     struct ieee80211_supported_band *sband,
++			     struct sta_info *sta,
++			     struct ieee80211_tx_info *info)
++{
++	struct rate_control_ref *ref = local->rate_ctrl;
++	struct ieee80211_sta *ista = &sta->sta;
++	void *priv_sta = sta->rate_ctrl_priv;
++
++	if (!ref || !test_sta_flag(sta, WLAN_STA_RATE_CONTROL))
++		return;
++
++	ref->ops->tx_status_noskb(ref->priv, sband, ista, priv_sta, info);
++}
++
++
+ static inline void rate_control_rate_init(struct sta_info *sta)
+ {
+ 	struct ieee80211_local *local = sta->sdata->local;
+--- a/net/mac80211/status.c
++++ b/net/mac80211/status.c
+@@ -541,10 +541,9 @@ static void ieee80211_tx_latency_end_msr
+ #define STA_LOST_TDLS_PKT_THRESHOLD	10
+ #define STA_LOST_TDLS_PKT_TIME		(10*HZ) /* 10secs since last ACK */
+ 
+-static void ieee80211_lost_packet(struct sta_info *sta, struct sk_buff *skb)
++static void ieee80211_lost_packet(struct sta_info *sta,
++				  struct ieee80211_tx_info *info)
+ {
+-	struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
+-
+ 	/* This packet was aggregated but doesn't carry status info */
+ 	if ((info->flags & IEEE80211_TX_CTL_AMPDU) &&
+ 	    !(info->flags & IEEE80211_TX_STAT_AMPDU))
+@@ -571,24 +570,13 @@ static void ieee80211_lost_packet(struct
+ 	sta->lost_packets = 0;
+ }
+ 
+-void ieee80211_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb)
++static int ieee80211_tx_get_rates(struct ieee80211_hw *hw,
++				  struct ieee80211_tx_info *info,
++				  int *retry_count)
+ {
+-	struct sk_buff *skb2;
+-	struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
+-	struct ieee80211_local *local = hw_to_local(hw);
+-	struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
+-	__le16 fc;
+-	struct ieee80211_supported_band *sband;
+-	struct ieee80211_sub_if_data *sdata;
+-	struct net_device *prev_dev = NULL;
+-	struct sta_info *sta, *tmp;
+-	int retry_count = -1, i;
+ 	int rates_idx = -1;
+-	bool send_to_cooked;
+-	bool acked;
+-	struct ieee80211_bar *bar;
+-	int rtap_len;
+-	int shift = 0;
++	int count = -1;
++	int i;
+ 
+ 	for (i = 0; i < IEEE80211_TX_MAX_RATES; i++) {
+ 		if ((info->flags & IEEE80211_TX_CTL_AMPDU) &&
+@@ -606,12 +594,94 @@ void ieee80211_tx_status(struct ieee8021
+ 			break;
+ 		}
+ 
+-		retry_count += info->status.rates[i].count;
++		count += info->status.rates[i].count;
+ 	}
+ 	rates_idx = i - 1;
+ 
+-	if (retry_count < 0)
+-		retry_count = 0;
++	if (count < 0)
++		count = 0;
++
++	*retry_count = count;
++	return rates_idx;
++}
++
++void ieee80211_tx_status_noskb(struct ieee80211_hw *hw,
++			       struct ieee80211_sta *pubsta,
++			       struct ieee80211_tx_info *info)
++{
++	struct ieee80211_local *local = hw_to_local(hw);
++	struct ieee80211_supported_band *sband;
++	int retry_count;
++	int rates_idx;
++	bool acked;
++
++	rates_idx = ieee80211_tx_get_rates(hw, info, &retry_count);
++
++	sband = hw->wiphy->bands[info->band];
++
++	acked = !!(info->flags & IEEE80211_TX_STAT_ACK);
++	if (pubsta) {
++		struct sta_info *sta;
++
++		sta = container_of(pubsta, struct sta_info, sta);
++
++		if (info->flags & IEEE80211_TX_STATUS_EOSP)
++			clear_sta_flag(sta, WLAN_STA_SP);
++
++		if (!acked)
++			sta->tx_retry_failed++;
++		sta->tx_retry_count += retry_count;
++
++		if (acked) {
++			sta->last_rx = jiffies;
++
++			if (sta->lost_packets)
++				sta->lost_packets = 0;
++
++			/* Track when last TDLS packet was ACKed */
++			if (test_sta_flag(sta, WLAN_STA_TDLS_PEER_AUTH))
++				sta->last_tdls_pkt_time = jiffies;
++		} else {
++			ieee80211_lost_packet(sta, info);
++		}
++
++		rate_control_tx_status_noskb(local, sband, sta, info);
++	}
++
++	if (acked) {
++		    local->dot11TransmittedFrameCount++;
++		    if (!pubsta)
++			    local->dot11MulticastTransmittedFrameCount++;
++		    if (retry_count > 0)
++			    local->dot11RetryCount++;
++		    if (retry_count > 1)
++			    local->dot11MultipleRetryCount++;
++	} else {
++		local->dot11FailedCount++;
++	}
++}
++EXPORT_SYMBOL(ieee80211_tx_status_noskb);
++
++void ieee80211_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb)
++{
++	struct sk_buff *skb2;
++	struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
++	struct ieee80211_local *local = hw_to_local(hw);
++	struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
++	__le16 fc;
++	struct ieee80211_supported_band *sband;
++	struct ieee80211_sub_if_data *sdata;
++	struct net_device *prev_dev = NULL;
++	struct sta_info *sta, *tmp;
++	int retry_count;
++	int rates_idx;
++	bool send_to_cooked;
++	bool acked;
++	struct ieee80211_bar *bar;
++	int rtap_len;
++	int shift = 0;
++
++	rates_idx = ieee80211_tx_get_rates(hw, info, &retry_count);
+ 
+ 	rcu_read_lock();
+ 
+@@ -716,7 +786,7 @@ void ieee80211_tx_status(struct ieee8021
+ 				if (test_sta_flag(sta, WLAN_STA_TDLS_PEER_AUTH))
+ 					sta->last_tdls_pkt_time = jiffies;
+ 			} else {
+-				ieee80211_lost_packet(sta, skb);
++				ieee80211_lost_packet(sta, info);
+ 			}
+ 		}
+