aboutsummaryrefslogtreecommitdiffstats
path: root/package/kernel
diff options
context:
space:
mode:
authorFelix Fietkau <nbd@openwrt.org>2014-11-18 22:20:45 +0000
committerFelix Fietkau <nbd@openwrt.org>2014-11-18 22:20:45 +0000
commit9cd492b3e19ba211791e4433cd25c6ec84288ff6 (patch)
treebccf96000877b7f02f2b2b36475a55fe3718af20 /package/kernel
parent7b0b8556d8f19bbcb7e0d2ce0e913ab3129eb781 (diff)
downloadupstream-9cd492b3e19ba211791e4433cd25c6ec84288ff6.tar.gz
upstream-9cd492b3e19ba211791e4433cd25c6ec84288ff6.tar.bz2
upstream-9cd492b3e19ba211791e4433cd25c6ec84288ff6.zip
mac80211: add support for reporting tx status without attached skb
Signed-off-by: Felix Fietkau <nbd@openwrt.org> SVN-Revision: 43297
Diffstat (limited to 'package/kernel')
-rw-r--r--package/kernel/mac80211/patches/313-mac80211-minstrel_ht-add-a-small-optimization-to-min.patch33
-rw-r--r--package/kernel/mac80211/patches/314-mac80211-minstrel_ht-move-aggregation-check-to-.get_.patch33
-rw-r--r--package/kernel/mac80211/patches/315-mac80211-add-tx_status_noskb-to-rate_control_ops.patch43
-rw-r--r--package/kernel/mac80211/patches/316-mac80211-minstrel-switch-to-.tx_status_noskb.patch31
-rw-r--r--package/kernel/mac80211/patches/317-mac80211-minstrel_ht-switch-to-.tx_status_noskb.patch41
-rw-r--r--package/kernel/mac80211/patches/318-mac80211-add-ieee80211_tx_status_noskb.patch219
6 files changed, 400 insertions, 0 deletions
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 <nbd@openwrt.org>
+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 <nbd@openwrt.org>
+---
+
+--- 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 <nbd@openwrt.org>
+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 <nbd@openwrt.org>
+---
+
+--- 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 <nbd@openwrt.org>
+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 <nbd@openwrt.org>
+---
+
+--- 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 <nbd@openwrt.org>
+Date: Sat, 15 Nov 2014 22:38:07 +0100
+Subject: [PATCH] mac80211: minstrel: switch to .tx_status_noskb
+
+Signed-off-by: Felix Fietkau <nbd@openwrt.org>
+---
+
+--- 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 <nbd@openwrt.org>
+Date: Sat, 15 Nov 2014 22:38:21 +0100
+Subject: [PATCH] mac80211: minstrel_ht: switch to .tx_status_noskb
+
+Signed-off-by: Felix Fietkau <nbd@openwrt.org>
+---
+
+--- 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 <nbd@openwrt.org>
+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 <nbd@openwrt.org>
+---
+
+--- 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);
+ }
+ }
+