2014-11-19 19:08:16

by Felix Fietkau

[permalink] [raw]
Subject: [PATCH v2 1/7] 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]>
---
net/mac80211/rc80211_minstrel_ht.c | 7 ++++---
1 file changed, 4 insertions(+), 3 deletions(-)

diff --git a/net/mac80211/rc80211_minstrel_ht.c b/net/mac80211/rc80211_minstrel_ht.c
index 62ff7cf..2641dc8 100644
--- 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 ieee80211_supported_band *sband,
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 ieee80211_sta *sta, void *priv_sta,
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);

--
2.1.2



2014-11-19 19:08:16

by Felix Fietkau

[permalink] [raw]
Subject: [PATCH v2 2/7] 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]>
---
include/net/mac80211.h | 4 ++++
net/mac80211/rate.h | 6 +++++-
2 files changed, 9 insertions(+), 1 deletion(-)

diff --git a/include/net/mac80211.h b/include/net/mac80211.h
index 5f203a6..32a779c 100644
--- 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);
diff --git a/net/mac80211/rate.h b/net/mac80211/rate.h
index 18babe3..dd25964 100644
--- a/net/mac80211/rate.h
+++ b/net/mac80211/rate.h
@@ -37,11 +37,15 @@ static inline void rate_control_tx_status(struct ieee80211_local *local,
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);
}


--
2.1.2


2014-11-19 19:08:16

by Felix Fietkau

[permalink] [raw]
Subject: [PATCH v2 3/7] mac80211: minstrel: switch to .tx_status_noskb

Signed-off-by: Felix Fietkau <[email protected]>
---
net/mac80211/rc80211_minstrel.c | 5 ++---
1 file changed, 2 insertions(+), 3 deletions(-)

diff --git a/net/mac80211/rc80211_minstrel.c b/net/mac80211/rc80211_minstrel.c
index c2b91bf..d51f6b1 100644
--- a/net/mac80211/rc80211_minstrel.c
+++ b/net/mac80211/rc80211_minstrel.c
@@ -223,11 +223,10 @@ minstrel_update_stats(struct minstrel_priv *mp, struct minstrel_sta_info *mi)
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_throughput(void *priv_sta)

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,
--
2.1.2


2014-11-19 19:08:16

by Felix Fietkau

[permalink] [raw]
Subject: [PATCH v2 6/7] mac0211: add a helper function for fixing up tx status rates

Signed-off-by: Felix Fietkau <[email protected]>
---
net/mac80211/status.c | 52 ++++++++++++++++++++++++++++++++-------------------
1 file changed, 33 insertions(+), 19 deletions(-)

diff --git a/net/mac80211/status.c b/net/mac80211/status.c
index ba35a44..249ca3a 100644
--- a/net/mac80211/status.c
+++ b/net/mac80211/status.c
@@ -570,24 +570,13 @@ static void ieee80211_lost_packet(struct sta_info *sta,
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) &&
@@ -605,12 +594,37 @@ void ieee80211_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb)
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(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();

--
2.1.2


2014-11-28 14:02:42

by Johannes Berg

[permalink] [raw]
Subject: Re: [PATCH v2 1/7] mac80211: minstrel_ht: move aggregation check to .get_rate()

On Wed, 2014-11-19 at 20:08 +0100, Felix Fietkau wrote:
> Preparation for adding a no-skb tx status path

Looks fine, applied all 7.

johannes


2014-11-19 19:08:16

by Felix Fietkau

[permalink] [raw]
Subject: [PATCH v2 5/7] mac80211: pass tx info to ieee80211_lost_packet instead of an skb

Signed-off-by: Felix Fietkau <[email protected]>
---
net/mac80211/status.c | 7 +++----
1 file changed, 3 insertions(+), 4 deletions(-)

diff --git a/net/mac80211/status.c b/net/mac80211/status.c
index 9612d89..ba35a44 100644
--- a/net/mac80211/status.c
+++ b/net/mac80211/status.c
@@ -541,10 +541,9 @@ static void ieee80211_tx_latency_end_msrmnt(struct ieee80211_local *local,
#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))
@@ -716,7 +715,7 @@ void ieee80211_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb)
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.1.2


2014-11-19 19:08:16

by Felix Fietkau

[permalink] [raw]
Subject: [PATCH v2 7/7] 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]>
---
include/net/mac80211.h | 20 +++++++++++++++++++
net/mac80211/rate.h | 18 +++++++++++++++++
net/mac80211/status.c | 54 ++++++++++++++++++++++++++++++++++++++++++++++++++
3 files changed, 92 insertions(+)

diff --git a/include/net/mac80211.h b/include/net/mac80211.h
index 32a779c..6150e72 100644
--- a/include/net/mac80211.h
+++ b/include/net/mac80211.h
@@ -3517,6 +3517,26 @@ void ieee80211_tx_status(struct ieee80211_hw *hw,
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.
+ *
+ * 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.
+ *
+ * @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.
diff --git a/net/mac80211/rate.h b/net/mac80211/rate.h
index dd25964..38652f0 100644
--- a/net/mac80211/rate.h
+++ b/net/mac80211/rate.h
@@ -48,6 +48,24 @@ static inline void rate_control_tx_status(struct ieee80211_local *local,
ref->ops->tx_status_noskb(ref->priv, sband, ista, priv_sta, info);
}

+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;
+
+ if (WARN_ON_ONCE(!ref->ops->tx_status_noskb))
+ return;
+
+ ref->ops->tx_status_noskb(ref->priv, sband, ista, priv_sta, info);
+}

static inline void rate_control_rate_init(struct sta_info *sta)
{
diff --git a/net/mac80211/status.c b/net/mac80211/status.c
index 249ca3a..84d6f6c 100644
--- a/net/mac80211/status.c
+++ b/net/mac80211/status.c
@@ -605,6 +605,60 @@ static int ieee80211_tx_get_rates(struct ieee80211_hw *hw,
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 (!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;
--
2.1.2


2014-11-19 19:08:16

by Felix Fietkau

[permalink] [raw]
Subject: [PATCH v2 4/7] mac80211: minstrel_ht: switch to .tx_status_noskb

Signed-off-by: Felix Fietkau <[email protected]>
---
net/mac80211/rc80211_minstrel_ht.c | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/net/mac80211/rc80211_minstrel_ht.c b/net/mac80211/rc80211_minstrel_ht.c
index 2641dc8..b52996a 100644
--- a/net/mac80211/rc80211_minstrel_ht.c
+++ b/net/mac80211/rc80211_minstrel_ht.c
@@ -709,11 +709,10 @@ minstrel_aggr_check(struct ieee80211_sta *pubsta, struct sk_buff *skb)
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 ieee80211_supported_band *sband,
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_throughput(void *priv_sta)

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,
--
2.1.2