linux-wireless.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH 1/5] mac80211: make rate control tx status API more extensible
@ 2017-04-26 15:11 Felix Fietkau
  2017-04-26 15:11 ` [PATCH 2/5] mac80211: move ieee80211_tx_status_noskb below ieee80211_tx_status Felix Fietkau
                   ` (4 more replies)
  0 siblings, 5 replies; 6+ messages in thread
From: Felix Fietkau @ 2017-04-26 15:11 UTC (permalink / raw)
  To: linux-wireless; +Cc: johannes, thomas

Rename .tx_status_noskb to .tx_status_ext and pass a new on-stack
struct ieee80211_tx_status instead of struct ieee80211_tx_info.

This struct can be used to pass extra information, e.g. for dynamic tx
power control

Signed-off-by: Felix Fietkau <nbd@nbd.name>
---
 include/net/mac80211.h             | 20 +++++++++++++----
 net/mac80211/rate.c                | 22 +++++++++++++++++++
 net/mac80211/rate.h                | 44 +++-----------------------------------
 net/mac80211/rc80211_minstrel.c    |  6 +++---
 net/mac80211/rc80211_minstrel_ht.c | 10 ++++-----
 net/mac80211/status.c              | 11 ++++++++--
 6 files changed, 58 insertions(+), 55 deletions(-)

diff --git a/include/net/mac80211.h b/include/net/mac80211.h
index b1ac872dc88a..380700e61d3b 100644
--- a/include/net/mac80211.h
+++ b/include/net/mac80211.h
@@ -949,6 +949,19 @@ struct ieee80211_tx_info {
 };
 
 /**
+ * struct ieee80211_tx_status - extended tx staus info for rate control
+ *
+ * @sta: Station that the packet was transmitted for
+ * @info: Basic tx status information
+ * @skb: Packet skb (can be NULL if not provided by the driver)
+ */
+struct ieee80211_tx_status {
+	struct ieee80211_sta *sta;
+	struct ieee80211_tx_info *info;
+	struct sk_buff *skb;
+};
+
+/**
  * struct ieee80211_scan_ies - descriptors for different blocks of IEs
  *
  * This structure is used to point to different blocks of IEs in HW scan
@@ -5476,10 +5489,9 @@ 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_ext)(void *priv,
+			      struct ieee80211_supported_band *sband,
+			      void *priv_sta, struct ieee80211_tx_status *st);
 	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.c b/net/mac80211/rate.c
index 9d7a1cd949fb..b387c07b8b47 100644
--- a/net/mac80211/rate.c
+++ b/net/mac80211/rate.c
@@ -62,6 +62,28 @@ void rate_control_rate_init(struct sta_info *sta)
 	set_sta_flag(sta, WLAN_STA_RATE_CONTROL);
 }
 
+void rate_control_tx_status(struct ieee80211_local *local,
+			    struct ieee80211_supported_band *sband,
+			    struct ieee80211_tx_status *st)
+{
+	struct rate_control_ref *ref = local->rate_ctrl;
+	struct sta_info *sta = container_of(st->sta, struct sta_info, sta);
+	void *priv_sta = sta->rate_ctrl_priv;
+
+	if (!ref || !test_sta_flag(sta, WLAN_STA_RATE_CONTROL))
+		return;
+
+	spin_lock_bh(&sta->rate_ctrl_lock);
+	if (ref->ops->tx_status_ext)
+		ref->ops->tx_status_ext(ref->priv, sband, priv_sta, st);
+	else if (st->skb)
+		ref->ops->tx_status(ref->priv, sband, st->sta, priv_sta, st->skb);
+	else
+		WARN_ON_ONCE(1);
+
+	spin_unlock_bh(&sta->rate_ctrl_lock);
+}
+
 void rate_control_rate_update(struct ieee80211_local *local,
 				    struct ieee80211_supported_band *sband,
 				    struct sta_info *sta, u32 changed)
diff --git a/net/mac80211/rate.h b/net/mac80211/rate.h
index f7825ef5f871..8212bfeb71d6 100644
--- a/net/mac80211/rate.h
+++ b/net/mac80211/rate.h
@@ -28,47 +28,9 @@ void rate_control_get_rate(struct ieee80211_sub_if_data *sdata,
 			   struct sta_info *sta,
 			   struct ieee80211_tx_rate_control *txrc);
 
-static inline void rate_control_tx_status(struct ieee80211_local *local,
-					  struct ieee80211_supported_band *sband,
-					  struct sta_info *sta,
-					  struct sk_buff *skb)
-{
-	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;
-
-	spin_lock_bh(&sta->rate_ctrl_lock);
-	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);
-	spin_unlock_bh(&sta->rate_ctrl_lock);
-}
-
-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;
-
-	spin_lock_bh(&sta->rate_ctrl_lock);
-	ref->ops->tx_status_noskb(ref->priv, sband, ista, priv_sta, info);
-	spin_unlock_bh(&sta->rate_ctrl_lock);
-}
+void rate_control_tx_status(struct ieee80211_local *local,
+			    struct ieee80211_supported_band *sband,
+			    struct ieee80211_tx_status *st);
 
 void rate_control_rate_init(struct sta_info *sta);
 void rate_control_rate_update(struct ieee80211_local *local,
diff --git a/net/mac80211/rc80211_minstrel.c b/net/mac80211/rc80211_minstrel.c
index 3ebe4405a2d4..9766c1cc4b0a 100644
--- a/net/mac80211/rc80211_minstrel.c
+++ b/net/mac80211/rc80211_minstrel.c
@@ -264,9 +264,9 @@ 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 ieee80211_tx_info *info)
+		   void *priv_sta, struct ieee80211_tx_status *st)
 {
+	struct ieee80211_tx_info *info = st->info;
 	struct minstrel_priv *mp = priv;
 	struct minstrel_sta_info *mi = priv_sta;
 	struct ieee80211_tx_rate *ar = info->status.rates;
@@ -726,7 +726,7 @@ static u32 minstrel_get_expected_throughput(void *priv_sta)
 
 const struct rate_control_ops mac80211_minstrel = {
 	.name = "minstrel",
-	.tx_status_noskb = minstrel_tx_status,
+	.tx_status_ext = minstrel_tx_status,
 	.get_rate = minstrel_get_rate,
 	.rate_init = minstrel_rate_init,
 	.alloc = minstrel_alloc,
diff --git a/net/mac80211/rc80211_minstrel_ht.c b/net/mac80211/rc80211_minstrel_ht.c
index 8e783e197e93..4a5bdad9f303 100644
--- a/net/mac80211/rc80211_minstrel_ht.c
+++ b/net/mac80211/rc80211_minstrel_ht.c
@@ -678,9 +678,9 @@ 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 ieee80211_tx_info *info)
+                      void *priv_sta, struct ieee80211_tx_status *st)
 {
+	struct ieee80211_tx_info *info = st->info;
 	struct minstrel_ht_sta_priv *msp = priv_sta;
 	struct minstrel_ht_sta *mi = &msp->ht;
 	struct ieee80211_tx_rate *ar = info->status.rates;
@@ -690,8 +690,8 @@ minstrel_ht_tx_status(void *priv, struct ieee80211_supported_band *sband,
 	int i;
 
 	if (!msp->is_ht)
-		return mac80211_minstrel.tx_status_noskb(priv, sband, sta,
-							 &msp->legacy, info);
+		return mac80211_minstrel.tx_status_ext(priv, sband,
+						       &msp->legacy, st);
 
 	/* This packet was aggregated but doesn't carry status info */
 	if ((info->flags & IEEE80211_TX_CTL_AMPDU) &&
@@ -1374,7 +1374,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_noskb = minstrel_ht_tx_status,
+	.tx_status_ext = 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/net/mac80211/status.c b/net/mac80211/status.c
index fac191d6dcb7..e655b3abb84a 100644
--- a/net/mac80211/status.c
+++ b/net/mac80211/status.c
@@ -637,6 +637,7 @@ void ieee80211_tx_status_noskb(struct ieee80211_hw *hw,
 {
 	struct ieee80211_local *local = hw_to_local(hw);
 	struct ieee80211_supported_band *sband;
+	struct ieee80211_tx_status status = {};
 	int retry_count;
 	bool acked, noack_success;
 
@@ -669,7 +670,9 @@ void ieee80211_tx_status_noskb(struct ieee80211_hw *hw,
 			ieee80211_lost_packet(sta, info);
 		}
 
-		rate_control_tx_status_noskb(local, sband, sta, info);
+		status.sta = pubsta;
+		status.info = info;
+		rate_control_tx_status(local, sband, &status);
 	}
 
 	if (acked || noack_success) {
@@ -748,6 +751,7 @@ void ieee80211_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb)
 	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);
+	struct ieee80211_tx_status status = {};
 	__le16 fc;
 	struct ieee80211_supported_band *sband;
 	struct rhlist_head *tmp;
@@ -857,7 +861,10 @@ void ieee80211_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb)
 			}
 		}
 
-		rate_control_tx_status(local, sband, sta, skb);
+		status.sta = &sta->sta;
+		status.skb = skb;
+		status.info = info;
+		rate_control_tx_status(local, sband, &status);
 		if (ieee80211_vif_is_mesh(&sta->sdata->vif))
 			ieee80211s_update_metric(local, sta, skb);
 
-- 
2.11.0

^ permalink raw reply related	[flat|nested] 6+ messages in thread

* [PATCH 2/5] mac80211: move ieee80211_tx_status_noskb below ieee80211_tx_status
  2017-04-26 15:11 [PATCH 1/5] mac80211: make rate control tx status API more extensible Felix Fietkau
@ 2017-04-26 15:11 ` Felix Fietkau
  2017-04-26 15:11 ` [PATCH 3/5] mac80211: add ieee80211_tx_status_ext Felix Fietkau
                   ` (3 subsequent siblings)
  4 siblings, 0 replies; 6+ messages in thread
From: Felix Fietkau @ 2017-04-26 15:11 UTC (permalink / raw)
  To: linux-wireless; +Cc: johannes, thomas

Makes further cleanups more readable

Signed-off-by: Felix Fietkau <nbd@nbd.name>
---
 net/mac80211/status.c | 116 +++++++++++++++++++++++++-------------------------
 1 file changed, 58 insertions(+), 58 deletions(-)

diff --git a/net/mac80211/status.c b/net/mac80211/status.c
index e655b3abb84a..2b3f02f56db3 100644
--- a/net/mac80211/status.c
+++ b/net/mac80211/status.c
@@ -631,64 +631,6 @@ 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;
-	struct ieee80211_tx_status status = {};
-	int retry_count;
-	bool acked, noack_success;
-
-	ieee80211_tx_get_rates(hw, info, &retry_count);
-
-	sband = hw->wiphy->bands[info->band];
-
-	acked = !!(info->flags & IEEE80211_TX_STAT_ACK);
-	noack_success = !!(info->flags & IEEE80211_TX_STAT_NOACK_TRANSMITTED);
-
-	if (pubsta) {
-		struct sta_info *sta;
-
-		sta = container_of(pubsta, struct sta_info, sta);
-
-		if (!acked)
-			sta->status_stats.retry_failed++;
-		sta->status_stats.retry_count += retry_count;
-
-		if (acked) {
-			sta->status_stats.last_ack = jiffies;
-
-			if (sta->status_stats.lost_packets)
-				sta->status_stats.lost_packets = 0;
-
-			/* Track when last TDLS packet was ACKed */
-			if (test_sta_flag(sta, WLAN_STA_TDLS_PEER_AUTH))
-				sta->status_stats.last_tdls_pkt_time = jiffies;
-		} else {
-			ieee80211_lost_packet(sta, info);
-		}
-
-		status.sta = pubsta;
-		status.info = info;
-		rate_control_tx_status(local, sband, &status);
-	}
-
-	if (acked || noack_success) {
-		I802_DEBUG_INC(local->dot11TransmittedFrameCount);
-		if (!pubsta)
-			I802_DEBUG_INC(local->dot11MulticastTransmittedFrameCount);
-		if (retry_count > 0)
-			I802_DEBUG_INC(local->dot11RetryCount);
-		if (retry_count > 1)
-			I802_DEBUG_INC(local->dot11MultipleRetryCount);
-	} else {
-		I802_DEBUG_INC(local->dot11FailedCount);
-	}
-}
-EXPORT_SYMBOL(ieee80211_tx_status_noskb);
-
 void ieee80211_tx_monitor(struct ieee80211_local *local, struct sk_buff *skb,
 			  struct ieee80211_supported_band *sband,
 			  int retry_count, int shift, bool send_to_cooked)
@@ -959,6 +901,64 @@ void ieee80211_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb)
 }
 EXPORT_SYMBOL(ieee80211_tx_status);
 
+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;
+	struct ieee80211_tx_status status = {};
+	int retry_count;
+	bool acked, noack_success;
+
+	ieee80211_tx_get_rates(hw, info, &retry_count);
+
+	sband = hw->wiphy->bands[info->band];
+
+	acked = !!(info->flags & IEEE80211_TX_STAT_ACK);
+	noack_success = !!(info->flags & IEEE80211_TX_STAT_NOACK_TRANSMITTED);
+
+	if (pubsta) {
+		struct sta_info *sta;
+
+		sta = container_of(pubsta, struct sta_info, sta);
+
+		if (!acked)
+			sta->status_stats.retry_failed++;
+		sta->status_stats.retry_count += retry_count;
+
+		if (acked) {
+			sta->status_stats.last_ack = jiffies;
+
+			if (sta->status_stats.lost_packets)
+				sta->status_stats.lost_packets = 0;
+
+			/* Track when last TDLS packet was ACKed */
+			if (test_sta_flag(sta, WLAN_STA_TDLS_PEER_AUTH))
+				sta->status_stats.last_tdls_pkt_time = jiffies;
+		} else {
+			ieee80211_lost_packet(sta, info);
+		}
+
+		status.sta = pubsta;
+		status.info = info;
+		rate_control_tx_status(local, sband, &status);
+	}
+
+	if (acked || noack_success) {
+		I802_DEBUG_INC(local->dot11TransmittedFrameCount);
+		if (!pubsta)
+			I802_DEBUG_INC(local->dot11MulticastTransmittedFrameCount);
+		if (retry_count > 0)
+			I802_DEBUG_INC(local->dot11RetryCount);
+		if (retry_count > 1)
+			I802_DEBUG_INC(local->dot11MultipleRetryCount);
+	} else {
+		I802_DEBUG_INC(local->dot11FailedCount);
+	}
+}
+EXPORT_SYMBOL(ieee80211_tx_status_noskb);
+
 void ieee80211_report_low_ack(struct ieee80211_sta *pubsta, u32 num_packets)
 {
 	struct sta_info *sta = container_of(pubsta, struct sta_info, sta);
-- 
2.11.0

^ permalink raw reply related	[flat|nested] 6+ messages in thread

* [PATCH 3/5] mac80211: add ieee80211_tx_status_ext
  2017-04-26 15:11 [PATCH 1/5] mac80211: make rate control tx status API more extensible Felix Fietkau
  2017-04-26 15:11 ` [PATCH 2/5] mac80211: move ieee80211_tx_status_noskb below ieee80211_tx_status Felix Fietkau
@ 2017-04-26 15:11 ` Felix Fietkau
  2017-04-26 15:11 ` [PATCH 4/5] mac80211: add per-packet transmit power to rate tables Felix Fietkau
                   ` (2 subsequent siblings)
  4 siblings, 0 replies; 6+ messages in thread
From: Felix Fietkau @ 2017-04-26 15:11 UTC (permalink / raw)
  To: linux-wireless; +Cc: johannes, thomas

This allows the driver to pass in struct ieee80211_tx_status directly.
Make ieee80211_tx_status_noskb a wrapper around it.

As with ieee80211_tx_status_noskb, there is no _ni variant of this call,
because it probably won't be needed.

Even if the driver won't provide any extra status info other than what's
in struct ieee80211_tx_info already, it can optimize status reporting
this way by passing in the station pointer.

Signed-off-by: Felix Fietkau <nbd@nbd.name>
---
 include/net/mac80211.h | 30 ++++++++++++++++++--
 net/mac80211/status.c  | 74 +++++++++++++++++++++++++++++++-------------------
 2 files changed, 73 insertions(+), 31 deletions(-)

diff --git a/include/net/mac80211.h b/include/net/mac80211.h
index 380700e61d3b..1b81f0c90068 100644
--- a/include/net/mac80211.h
+++ b/include/net/mac80211.h
@@ -4219,6 +4219,23 @@ void ieee80211_tx_status(struct ieee80211_hw *hw,
 			 struct sk_buff *skb);
 
 /**
+ * ieee80211_tx_status_ext - extended transmit status callback
+ *
+ * This function can be used as a replacement for ieee80211_tx_status
+ * in drivers that may want to provide extra information that does not
+ * fit into &struct ieee80211_tx_info.
+ *
+ * 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
+ * @status: tx status information
+ */
+void ieee80211_tx_status_ext(struct ieee80211_hw *hw,
+			     struct ieee80211_tx_status *status);
+
+/**
  * ieee80211_tx_status_noskb - transmit status callback without skb
  *
  * This function can be used as a replacement for ieee80211_tx_status
@@ -4234,9 +4251,16 @@ void ieee80211_tx_status(struct ieee80211_hw *hw,
  *	(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);
+static inline void ieee80211_tx_status_noskb(struct ieee80211_hw *hw,
+					     struct ieee80211_sta *sta,
+					     struct ieee80211_tx_info *info)
+{
+	struct ieee80211_tx_status status = {};
+
+	status.sta = sta;
+	status.info = info;
+	ieee80211_tx_status_ext(hw, &status);
+}
 
 /**
  * ieee80211_tx_status_ni - transmit status callback (in process context)
diff --git a/net/mac80211/status.c b/net/mac80211/status.c
index 2b3f02f56db3..35b226ac2fee 100644
--- a/net/mac80211/status.c
+++ b/net/mac80211/status.c
@@ -688,16 +688,16 @@ void ieee80211_tx_monitor(struct ieee80211_local *local, struct sk_buff *skb,
 	dev_kfree_skb(skb);
 }
 
-void ieee80211_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb)
+static void __ieee80211_tx_status(struct ieee80211_hw *hw,
+				  struct ieee80211_tx_status *status)
 {
+	struct sk_buff *skb = status->skb;
 	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);
-	struct ieee80211_tx_status status = {};
+	struct ieee80211_tx_info *info = status->info;
+	struct sta_info *sta;
 	__le16 fc;
 	struct ieee80211_supported_band *sband;
-	struct rhlist_head *tmp;
-	struct sta_info *sta;
 	int retry_count;
 	int rates_idx;
 	bool send_to_cooked;
@@ -708,16 +708,11 @@ void ieee80211_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb)
 
 	rates_idx = ieee80211_tx_get_rates(hw, info, &retry_count);
 
-	rcu_read_lock();
-
 	sband = local->hw.wiphy->bands[info->band];
 	fc = hdr->frame_control;
 
-	for_each_sta_info(local, hdr->addr1, sta, tmp) {
-		/* skip wrong virtual interface */
-		if (!ether_addr_equal(hdr->addr2, sta->sdata->vif.addr))
-			continue;
-
+	if (status->sta) {
+		sta = container_of(status->sta, struct sta_info, sta);
 		shift = ieee80211_vif_get_shift(&sta->sdata->vif);
 
 		if (info->flags & IEEE80211_TX_STATUS_EOSP)
@@ -737,7 +732,6 @@ void ieee80211_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb)
 			 * that this TX packet failed because of that.
 			 */
 			ieee80211_handle_filtered_frame(local, sta, skb);
-			rcu_read_unlock();
 			return;
 		}
 
@@ -787,7 +781,6 @@ void ieee80211_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb)
 
 		if (info->flags & IEEE80211_TX_STAT_TX_FILTERED) {
 			ieee80211_handle_filtered_frame(local, sta, skb);
-			rcu_read_unlock();
 			return;
 		} else {
 			if (!acked)
@@ -803,10 +796,7 @@ void ieee80211_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb)
 			}
 		}
 
-		status.sta = &sta->sta;
-		status.skb = skb;
-		status.info = info;
-		rate_control_tx_status(local, sband, &status);
+		rate_control_tx_status(local, sband, status);
 		if (ieee80211_vif_is_mesh(&sta->sdata->vif))
 			ieee80211s_update_metric(local, sta, skb);
 
@@ -833,8 +823,6 @@ void ieee80211_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb)
 		}
 	}
 
-	rcu_read_unlock();
-
 	ieee80211_led_tx(local);
 
 	/* SNMP counters
@@ -899,18 +887,50 @@ void ieee80211_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb)
 	/* send to monitor interfaces */
 	ieee80211_tx_monitor(local, skb, sband, retry_count, shift, send_to_cooked);
 }
+
+void ieee80211_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb)
+{
+	struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
+	struct ieee80211_local *local = hw_to_local(hw);
+	struct ieee80211_tx_status status = {};
+	struct rhlist_head *tmp;
+	struct sta_info *sta;
+
+	status.skb = skb;
+	status.info = IEEE80211_SKB_CB(skb);
+
+	rcu_read_lock();
+
+	for_each_sta_info(local, hdr->addr1, sta, tmp) {
+		/* skip wrong virtual interface */
+		if (!ether_addr_equal(hdr->addr2, sta->sdata->vif.addr))
+			continue;
+
+		status.sta = &sta->sta;
+		break;
+	}
+
+	__ieee80211_tx_status(hw, &status);
+	rcu_read_unlock();
+}
 EXPORT_SYMBOL(ieee80211_tx_status);
 
-void ieee80211_tx_status_noskb(struct ieee80211_hw *hw,
-			       struct ieee80211_sta *pubsta,
-			       struct ieee80211_tx_info *info)
+void ieee80211_tx_status_ext(struct ieee80211_hw *hw,
+			     struct ieee80211_tx_status *status)
 {
 	struct ieee80211_local *local = hw_to_local(hw);
+	struct ieee80211_tx_info *info = status->info;
+	struct ieee80211_sta *pubsta = status->sta;
 	struct ieee80211_supported_band *sband;
-	struct ieee80211_tx_status status = {};
 	int retry_count;
 	bool acked, noack_success;
 
+	if (status->skb)
+		return __ieee80211_tx_status(hw, status);
+
+	if (!status->sta)
+		return;
+
 	ieee80211_tx_get_rates(hw, info, &retry_count);
 
 	sband = hw->wiphy->bands[info->band];
@@ -940,9 +960,7 @@ void ieee80211_tx_status_noskb(struct ieee80211_hw *hw,
 			ieee80211_lost_packet(sta, info);
 		}
 
-		status.sta = pubsta;
-		status.info = info;
-		rate_control_tx_status(local, sband, &status);
+		rate_control_tx_status(local, sband, status);
 	}
 
 	if (acked || noack_success) {
@@ -957,7 +975,7 @@ void ieee80211_tx_status_noskb(struct ieee80211_hw *hw,
 		I802_DEBUG_INC(local->dot11FailedCount);
 	}
 }
-EXPORT_SYMBOL(ieee80211_tx_status_noskb);
+EXPORT_SYMBOL(ieee80211_tx_status_ext);
 
 void ieee80211_report_low_ack(struct ieee80211_sta *pubsta, u32 num_packets)
 {
-- 
2.11.0

^ permalink raw reply related	[flat|nested] 6+ messages in thread

* [PATCH 4/5] mac80211: add per-packet transmit power to rate tables
  2017-04-26 15:11 [PATCH 1/5] mac80211: make rate control tx status API more extensible Felix Fietkau
  2017-04-26 15:11 ` [PATCH 2/5] mac80211: move ieee80211_tx_status_noskb below ieee80211_tx_status Felix Fietkau
  2017-04-26 15:11 ` [PATCH 3/5] mac80211: add ieee80211_tx_status_ext Felix Fietkau
@ 2017-04-26 15:11 ` Felix Fietkau
  2017-04-26 15:11 ` [PATCH 5/5] mac80211: add txpower to the new tx_status_ext Felix Fietkau
  2017-04-28  9:10 ` [PATCH 1/5] mac80211: make rate control tx status API more extensible Johannes Berg
  4 siblings, 0 replies; 6+ messages in thread
From: Felix Fietkau @ 2017-04-26 15:11 UTC (permalink / raw)
  To: linux-wireless; +Cc: johannes, thomas

This will be used to allow rate control to control per-packet tx power.
Since cb space is tight and minstrel/minstrel_ht uses
info->control.rates only for the sampling rate, the tx power field in
info->control refers to the first rate attempt entry only.

Transmit power for the selected best rate set is stored in struct
ieee80211_sta_rates.

Signed-off-by: Felix Fietkau <nbd@nbd.name>
Signed-off-by: Thomas Huehn <thomas.huehn@evernet-eg.de>
---
 include/net/mac80211.h             | 10 ++++++++--
 net/mac80211/rate.c                |  2 ++
 net/mac80211/rc80211_minstrel.c    |  9 +++++++++
 net/mac80211/rc80211_minstrel_ht.c |  8 ++++++++
 4 files changed, 27 insertions(+), 2 deletions(-)

diff --git a/include/net/mac80211.h b/include/net/mac80211.h
index 1b81f0c90068..d29702601333 100644
--- a/include/net/mac80211.h
+++ b/include/net/mac80211.h
@@ -901,7 +901,12 @@ struct ieee80211_tx_info {
 					u8 use_cts_prot:1;
 					u8 short_preamble:1;
 					u8 skip_table:1;
-					/* 2 bytes free */
+
+					/* txpower field refers to the first
+					 * entry of rates only (if present).
+					 */
+					s8 txpower;
+					/* 1 byte free */
 				};
 				/* only needed before rate control */
 				unsigned long jiffies;
@@ -1733,13 +1738,14 @@ enum ieee80211_sta_rx_bandwidth {
  * struct ieee80211_sta_rates - station rate selection table
  *
  * @rcu_head: RCU head used for freeing the table on update
- * @rate: transmit rates/flags to be used by default.
+ * @rate: transmit rates/power/flags to be used by default.
  *	Overriding entries per-packet is possible by using cb tx control.
  */
 struct ieee80211_sta_rates {
 	struct rcu_head rcu_head;
 	struct {
 		s8 idx;
+		s8 txpower;
 		u8 count;
 		u8 count_cts;
 		u8 count_rts;
diff --git a/net/mac80211/rate.c b/net/mac80211/rate.c
index b387c07b8b47..394e36570047 100644
--- a/net/mac80211/rate.c
+++ b/net/mac80211/rate.c
@@ -899,6 +899,8 @@ void rate_control_get_rate(struct ieee80211_sub_if_data *sdata,
 		info->control.rates[i].count = 0;
 	}
 
+	info->control.txpower = sdata->vif.bss_conf.txpower;
+
 	if (ieee80211_hw_check(&sdata->local->hw, HAS_RATE_CONTROL))
 		return;
 
diff --git a/net/mac80211/rc80211_minstrel.c b/net/mac80211/rc80211_minstrel.c
index 9766c1cc4b0a..8b82a72b1f01 100644
--- a/net/mac80211/rc80211_minstrel.c
+++ b/net/mac80211/rc80211_minstrel.c
@@ -52,6 +52,7 @@
 #include <linux/ieee80211.h>
 #include <linux/slab.h>
 #include <net/mac80211.h>
+#include "sta_info.h"
 #include "rate.h"
 #include "rc80211_minstrel.h"
 
@@ -125,12 +126,20 @@ static void
 minstrel_update_rates(struct minstrel_priv *mp, struct minstrel_sta_info *mi)
 {
 	struct ieee80211_sta_rates *ratetbl;
+	struct sta_info *sta;
+	s8 txpower;
 	int i = 0;
 
+	sta = container_of(mi->sta, struct sta_info, sta);
+	txpower = sta->sdata->vif.bss_conf.txpower;
+
 	ratetbl = kzalloc(sizeof(*ratetbl), GFP_ATOMIC);
 	if (!ratetbl)
 		return;
 
+	for (i = 0; i < ARRAY_SIZE(ratetbl->rate); i++)
+		ratetbl->rate[i].txpower = txpower;
+
 	/* Start with max_tp_rate */
 	minstrel_set_rate(mi, ratetbl, i++, mi->max_tp_rate[0]);
 
diff --git a/net/mac80211/rc80211_minstrel_ht.c b/net/mac80211/rc80211_minstrel_ht.c
index 4a5bdad9f303..c52c546cce57 100644
--- a/net/mac80211/rc80211_minstrel_ht.c
+++ b/net/mac80211/rc80211_minstrel_ht.c
@@ -921,12 +921,20 @@ static void
 minstrel_ht_update_rates(struct minstrel_priv *mp, struct minstrel_ht_sta *mi)
 {
 	struct ieee80211_sta_rates *rates;
+	struct sta_info *sta;
+	s8 txpower;
 	int i = 0;
 
+	sta = container_of(mi->sta, struct sta_info, sta);
+	txpower = sta->sdata->vif.bss_conf.txpower;
+
 	rates = kzalloc(sizeof(*rates), GFP_ATOMIC);
 	if (!rates)
 		return;
 
+	for (i = 0; i < ARRAY_SIZE(rates->rate); i++)
+		rates->rate[i].txpower = txpower;
+
 	/* Start with max_tp_rate[0] */
 	minstrel_ht_set_rate(mp, mi, rates, i++, mi->max_tp_rate[0]);
 
-- 
2.11.0

^ permalink raw reply related	[flat|nested] 6+ messages in thread

* [PATCH 5/5] mac80211: add txpower to the new tx_status_ext
  2017-04-26 15:11 [PATCH 1/5] mac80211: make rate control tx status API more extensible Felix Fietkau
                   ` (2 preceding siblings ...)
  2017-04-26 15:11 ` [PATCH 4/5] mac80211: add per-packet transmit power to rate tables Felix Fietkau
@ 2017-04-26 15:11 ` Felix Fietkau
  2017-04-28  9:10 ` [PATCH 1/5] mac80211: make rate control tx status API more extensible Johannes Berg
  4 siblings, 0 replies; 6+ messages in thread
From: Felix Fietkau @ 2017-04-26 15:11 UTC (permalink / raw)
  To: linux-wireless; +Cc: johannes, thomas

From: Thomas Huehn <thomas@net.t-labs.tu-berlin.de>

To use the per rate information about which txpower level was
used for a successful or unsuccessful transmission, this new
tx power per multi-rate retry rate annotation in the tx status
path is needed.

Signed-off-by: Thomas Huehn <thomas@net.t-labs.tu-berlin.de>
---
 include/net/mac80211.h | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/include/net/mac80211.h b/include/net/mac80211.h
index d29702601333..bd28c81bc515 100644
--- a/include/net/mac80211.h
+++ b/include/net/mac80211.h
@@ -959,11 +959,13 @@ struct ieee80211_tx_info {
  * @sta: Station that the packet was transmitted for
  * @info: Basic tx status information
  * @skb: Packet skb (can be NULL if not provided by the driver)
+ * @txpower: Txpower per rate status information
  */
 struct ieee80211_tx_status {
 	struct ieee80211_sta *sta;
 	struct ieee80211_tx_info *info;
 	struct sk_buff *skb;
+	s8 txpower[IEEE80211_TX_MAX_RATES];
 };
 
 /**
-- 
2.11.0

^ permalink raw reply related	[flat|nested] 6+ messages in thread

* Re: [PATCH 1/5] mac80211: make rate control tx status API more extensible
  2017-04-26 15:11 [PATCH 1/5] mac80211: make rate control tx status API more extensible Felix Fietkau
                   ` (3 preceding siblings ...)
  2017-04-26 15:11 ` [PATCH 5/5] mac80211: add txpower to the new tx_status_ext Felix Fietkau
@ 2017-04-28  9:10 ` Johannes Berg
  4 siblings, 0 replies; 6+ messages in thread
From: Johannes Berg @ 2017-04-28  9:10 UTC (permalink / raw)
  To: Felix Fietkau, linux-wireless; +Cc: thomas

I've applied patches 1-3.

Patch 5 is missing your S-o-b (since you sent it to me), but regardless
of that I'd like to actually see the usage (in minstrel?) with the API.

johannes

^ permalink raw reply	[flat|nested] 6+ messages in thread

end of thread, other threads:[~2017-04-28  9:10 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2017-04-26 15:11 [PATCH 1/5] mac80211: make rate control tx status API more extensible Felix Fietkau
2017-04-26 15:11 ` [PATCH 2/5] mac80211: move ieee80211_tx_status_noskb below ieee80211_tx_status Felix Fietkau
2017-04-26 15:11 ` [PATCH 3/5] mac80211: add ieee80211_tx_status_ext Felix Fietkau
2017-04-26 15:11 ` [PATCH 4/5] mac80211: add per-packet transmit power to rate tables Felix Fietkau
2017-04-26 15:11 ` [PATCH 5/5] mac80211: add txpower to the new tx_status_ext Felix Fietkau
2017-04-28  9:10 ` [PATCH 1/5] mac80211: make rate control tx status API more extensible Johannes Berg

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).