Message ID | 1416094080-49220-6-git-send-email-nbd@openwrt.org (mailing list archive) |
---|---|
State | Not Applicable, archived |
Headers | show |
> /** > + * 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(). None of that seems very likely. Did you just copy/paste it? :) > +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); > +} Oh, so you're adding another one ... I guess I understand better now. > + > + two blank lines? > -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); > - some of this refactoring might better be in a separate patch. > /* 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_info *sta, struct sk_buff *skb) > 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; ditto - too big for here. > + 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); That doesn't seem reasonable really - if you're reporting out of band then don't report it as TX status but rather with the eosp() call. johannes -- To unsubscribe from this list: send the line "unsubscribe linux-wireless" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
On 2014-11-19 19:38, Johannes Berg wrote: > >> /** >> + * 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(). > > None of that seems very likely. Did you just copy/paste it? :) Yes, I copy/pasted it. I wasn't sure if these requirements would be necessary for the no-skb status as well, just figured it'd be safe to leave them in. >> +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); >> +} > > Oh, so you're adding another one ... I guess I understand better now. > >> + >> + > > two blank lines? Will fix that. >> -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); >> - > > some of this refactoring might better be in a separate patch. > >> /* 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_info *sta, struct sk_buff *skb) >> 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; > > ditto - too big for here. OK. >> + 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); > > That doesn't seem reasonable really - if you're reporting out of band > then don't report it as TX status but rather with the eosp() call. OK. - Felix -- To unsubscribe from this list: send the line "unsubscribe linux-wireless" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
On Wed, 2014-11-19 at 19:47 +0100, Felix Fietkau wrote: > >> + * 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(). > > > > None of that seems very likely. Did you just copy/paste it? :) > Yes, I copy/pasted it. I wasn't sure if these requirements would be > necessary for the no-skb status as well, just figured it'd be safe to > leave them in. I think if you move the eosp() that leaves you pretty much with only things that are safe? johannes -- To unsubscribe from this list: send the line "unsubscribe linux-wireless" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
diff --git a/include/net/mac80211.h b/include/net/mac80211.h index 32a779c..28ea999 100644 --- a/include/net/mac80211.h +++ b/include/net/mac80211.h @@ -3517,6 +3517,28 @@ 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. + * + * 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. diff --git a/net/mac80211/rate.h b/net/mac80211/rate.h index dd25964..a0b18a8 100644 --- a/net/mac80211/rate.h +++ b/net/mac80211/rate.h @@ -49,6 +49,23 @@ static inline void rate_control_tx_status(struct ieee80211_local *local, } +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; diff --git a/net/mac80211/status.c b/net/mac80211/status.c index 9612d89..8a6d3ad 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)) @@ -571,24 +570,13 @@ static void ieee80211_lost_packet(struct sta_info *sta, struct sk_buff *skb) 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 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_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 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); } }
This can be used by drivers that cannot reliably map tx status information onto specific skbs. Signed-off-by: Felix Fietkau <nbd@openwrt.org> --- include/net/mac80211.h | 22 ++++++++++ net/mac80211/rate.h | 17 ++++++++ net/mac80211/status.c | 116 +++++++++++++++++++++++++++++++++++++++---------- 3 files changed, 132 insertions(+), 23 deletions(-)