From 1ffe84d34e3bfd53e5b0d2fcac3e57e5c2ada6f8 Mon Sep 17 00:00:00 2001 From: nbd Date: Tue, 18 Nov 2014 22:20:45 +0000 Subject: [PATCH] mac80211: add support for reporting tx status without attached skb Signed-off-by: Felix Fietkau git-svn-id: svn://svn.openwrt.org/openwrt/trunk@43297 3c298f89-4303-0410-b956-a3cf2f4a3e73 --- ...nstrel_ht-add-a-small-optimization-to-min.patch | 33 ++++ ...nstrel_ht-move-aggregation-check-to-.get_.patch | 33 ++++ ...1-add-tx_status_noskb-to-rate_control_ops.patch | 43 ++++ ...80211-minstrel-switch-to-.tx_status_noskb.patch | 31 +++ ...11-minstrel_ht-switch-to-.tx_status_noskb.patch | 41 ++++ ...18-mac80211-add-ieee80211_tx_status_noskb.patch | 219 +++++++++++++++++++++ 6 files changed, 400 insertions(+) create mode 100644 package/kernel/mac80211/patches/313-mac80211-minstrel_ht-add-a-small-optimization-to-min.patch create mode 100644 package/kernel/mac80211/patches/314-mac80211-minstrel_ht-move-aggregation-check-to-.get_.patch create mode 100644 package/kernel/mac80211/patches/315-mac80211-add-tx_status_noskb-to-rate_control_ops.patch create mode 100644 package/kernel/mac80211/patches/316-mac80211-minstrel-switch-to-.tx_status_noskb.patch create mode 100644 package/kernel/mac80211/patches/317-mac80211-minstrel_ht-switch-to-.tx_status_noskb.patch create mode 100644 package/kernel/mac80211/patches/318-mac80211-add-ieee80211_tx_status_noskb.patch diff --git a/package/kernel/mac80211/patches/313-mac80211-minstrel_ht-add-a-small-optimization-to-min.patch b/package/kernel/mac80211/patches/313-mac80211-minstrel_ht-add-a-small-optimization-to-min.patch new file mode 100644 index 0000000000..ba2ce1eb8d --- /dev/null +++ b/package/kernel/mac80211/patches/313-mac80211-minstrel_ht-add-a-small-optimization-to-min.patch @@ -0,0 +1,33 @@ +From: Felix Fietkau +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 +--- + +--- 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); + } + diff --git a/package/kernel/mac80211/patches/314-mac80211-minstrel_ht-move-aggregation-check-to-.get_.patch b/package/kernel/mac80211/patches/314-mac80211-minstrel_ht-move-aggregation-check-to-.get_.patch new file mode 100644 index 0000000000..38e867ffac --- /dev/null +++ b/package/kernel/mac80211/patches/314-mac80211-minstrel_ht-move-aggregation-check-to-.get_.patch @@ -0,0 +1,33 @@ +From: Felix Fietkau +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 +--- + +--- 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); + diff --git a/package/kernel/mac80211/patches/315-mac80211-add-tx_status_noskb-to-rate_control_ops.patch b/package/kernel/mac80211/patches/315-mac80211-add-tx_status_noskb-to-rate_control_ops.patch new file mode 100644 index 0000000000..8a939709b4 --- /dev/null +++ b/package/kernel/mac80211/patches/315-mac80211-add-tx_status_noskb-to-rate_control_ops.patch @@ -0,0 +1,43 @@ +From: Felix Fietkau +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 +--- + +--- 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); + } + + diff --git a/package/kernel/mac80211/patches/316-mac80211-minstrel-switch-to-.tx_status_noskb.patch b/package/kernel/mac80211/patches/316-mac80211-minstrel-switch-to-.tx_status_noskb.patch new file mode 100644 index 0000000000..b32e410954 --- /dev/null +++ b/package/kernel/mac80211/patches/316-mac80211-minstrel-switch-to-.tx_status_noskb.patch @@ -0,0 +1,31 @@ +From: Felix Fietkau +Date: Sat, 15 Nov 2014 22:38:07 +0100 +Subject: [PATCH] mac80211: minstrel: switch to .tx_status_noskb + +Signed-off-by: Felix Fietkau +--- + +--- 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, diff --git a/package/kernel/mac80211/patches/317-mac80211-minstrel_ht-switch-to-.tx_status_noskb.patch b/package/kernel/mac80211/patches/317-mac80211-minstrel_ht-switch-to-.tx_status_noskb.patch new file mode 100644 index 0000000000..6900005d1d --- /dev/null +++ b/package/kernel/mac80211/patches/317-mac80211-minstrel_ht-switch-to-.tx_status_noskb.patch @@ -0,0 +1,41 @@ +From: Felix Fietkau +Date: Sat, 15 Nov 2014 22:38:21 +0100 +Subject: [PATCH] mac80211: minstrel_ht: switch to .tx_status_noskb + +Signed-off-by: Felix Fietkau +--- + +--- 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, diff --git a/package/kernel/mac80211/patches/318-mac80211-add-ieee80211_tx_status_noskb.patch b/package/kernel/mac80211/patches/318-mac80211-add-ieee80211_tx_status_noskb.patch new file mode 100644 index 0000000000..18d3905597 --- /dev/null +++ b/package/kernel/mac80211/patches/318-mac80211-add-ieee80211_tx_status_noskb.patch @@ -0,0 +1,219 @@ +From: Felix Fietkau +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 +--- + +--- 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); + } + } + -- 2.11.0