Add AQL support for HE drivers. Improve assumed aggregation length based on tx rate Signed-off-by: Felix Fietkau <nbd@nbd.name>
		
			
				
	
	
		
			152 lines
		
	
	
		
			4.2 KiB
		
	
	
	
		
			Diff
		
	
	
	
	
	
			
		
		
	
	
			152 lines
		
	
	
		
			4.2 KiB
		
	
	
	
		
			Diff
		
	
	
	
	
	
| From: Felix Fietkau <nbd@nbd.name>
 | |
| Date: Wed, 12 Aug 2020 17:04:22 +0200
 | |
| Subject: [PATCH] mac80211: use rate provided via status->rate on
 | |
|  ieee80211_tx_status_ext for AQL
 | |
| 
 | |
| Since ieee80211_tx_info does not have enough room to encode HE rates, HE
 | |
| drivers use status->rate to provide rate info.
 | |
| Store it in struct sta_info and use it for AQL.
 | |
| 
 | |
| Signed-off-by: Felix Fietkau <nbd@nbd.name>
 | |
| ---
 | |
| 
 | |
| --- a/net/mac80211/airtime.c
 | |
| +++ b/net/mac80211/airtime.c
 | |
| @@ -487,14 +487,61 @@ u32 ieee80211_calc_rx_airtime(struct iee
 | |
|  }
 | |
|  EXPORT_SYMBOL_GPL(ieee80211_calc_rx_airtime);
 | |
|  
 | |
| +static bool ieee80211_fill_rate_info(struct ieee80211_hw *hw,
 | |
| +				     struct ieee80211_rx_status *stat, u8 band,
 | |
| +				     struct rate_info *ri)
 | |
| +{
 | |
| +	struct ieee80211_supported_band *sband = hw->wiphy->bands[band];
 | |
| +	int i;
 | |
| +
 | |
| +	if (!ri || !sband)
 | |
| +	    return false;
 | |
| +
 | |
| +	stat->bw = ri->bw;
 | |
| +	stat->nss = ri->nss;
 | |
| +	stat->rate_idx = ri->mcs;
 | |
| +
 | |
| +	if (ri->flags & RATE_INFO_FLAGS_HE_MCS)
 | |
| +		stat->encoding = RX_ENC_HE;
 | |
| +	else if (ri->flags & RATE_INFO_FLAGS_VHT_MCS)
 | |
| +		stat->encoding = RX_ENC_VHT;
 | |
| +	else if (ri->flags & RATE_INFO_FLAGS_MCS)
 | |
| +		stat->encoding = RX_ENC_HT;
 | |
| +	else
 | |
| +		stat->encoding = RX_ENC_LEGACY;
 | |
| +
 | |
| +	if (ri->flags & RATE_INFO_FLAGS_SHORT_GI)
 | |
| +		stat->enc_flags |= RX_ENC_FLAG_SHORT_GI;
 | |
| +
 | |
| +	stat->he_gi = ri->he_gi;
 | |
| +
 | |
| +	if (stat->encoding != RX_ENC_LEGACY)
 | |
| +		return true;
 | |
| +
 | |
| +	stat->rate_idx = 0;
 | |
| +	for (i = 0; i < sband->n_bitrates; i++) {
 | |
| +		if (ri->legacy != sband->bitrates[i].bitrate)
 | |
| +			continue;
 | |
| +
 | |
| +		stat->rate_idx = i;
 | |
| +		return true;
 | |
| +	}
 | |
| +
 | |
| +	return false;
 | |
| +}
 | |
| +
 | |
|  static u32 ieee80211_calc_tx_airtime_rate(struct ieee80211_hw *hw,
 | |
|  					  struct ieee80211_tx_rate *rate,
 | |
| +					  struct rate_info *ri,
 | |
|  					  u8 band, int len)
 | |
|  {
 | |
|  	struct ieee80211_rx_status stat = {
 | |
|  		.band = band,
 | |
|  	};
 | |
|  
 | |
| +	if (ieee80211_fill_rate_info(hw, &stat, band, ri))
 | |
| +		goto out;
 | |
| +
 | |
|  	if (rate->idx < 0 || !rate->count)
 | |
|  		return 0;
 | |
|  
 | |
| @@ -522,6 +569,7 @@ static u32 ieee80211_calc_tx_airtime_rat
 | |
|  		stat.encoding = RX_ENC_LEGACY;
 | |
|  	}
 | |
|  
 | |
| +out:
 | |
|  	return ieee80211_calc_rx_airtime(hw, &stat, len);
 | |
|  }
 | |
|  
 | |
| @@ -536,7 +584,7 @@ u32 ieee80211_calc_tx_airtime(struct iee
 | |
|  		struct ieee80211_tx_rate *rate = &info->status.rates[i];
 | |
|  		u32 cur_duration;
 | |
|  
 | |
| -		cur_duration = ieee80211_calc_tx_airtime_rate(hw, rate,
 | |
| +		cur_duration = ieee80211_calc_tx_airtime_rate(hw, rate, NULL,
 | |
|  							      info->band, len);
 | |
|  		if (!cur_duration)
 | |
|  			break;
 | |
| @@ -573,6 +621,7 @@ u32 ieee80211_calc_expected_tx_airtime(s
 | |
|  		struct sta_info *sta = container_of(pubsta, struct sta_info,
 | |
|  						    sta);
 | |
|  		struct ieee80211_tx_rate *rate = &sta->tx_stats.last_rate;
 | |
| +		struct rate_info *ri = &sta->tx_stats.last_rate_info;
 | |
|  		u32 airtime;
 | |
|  
 | |
|  		if (!(rate->flags & (IEEE80211_TX_RC_VHT_MCS |
 | |
| @@ -586,7 +635,7 @@ u32 ieee80211_calc_expected_tx_airtime(s
 | |
|  		 * This will not be very accurate, but much better than simply
 | |
|  		 * assuming un-aggregated tx.
 | |
|  		 */
 | |
| -		airtime = ieee80211_calc_tx_airtime_rate(hw, rate, band,
 | |
| +		airtime = ieee80211_calc_tx_airtime_rate(hw, rate, ri, band,
 | |
|  							 ampdu ? len * 16 : len);
 | |
|  		if (ampdu)
 | |
|  			airtime /= 16;
 | |
| --- a/net/mac80211/sta_info.h
 | |
| +++ b/net/mac80211/sta_info.h
 | |
| @@ -609,6 +609,7 @@ struct sta_info {
 | |
|  		u64 packets[IEEE80211_NUM_ACS];
 | |
|  		u64 bytes[IEEE80211_NUM_ACS];
 | |
|  		struct ieee80211_tx_rate last_rate;
 | |
| +		struct rate_info last_rate_info;
 | |
|  		u64 msdu[IEEE80211_NUM_TIDS + 1];
 | |
|  	} tx_stats;
 | |
|  	u16 tid_seq[IEEE80211_QOS_CTL_TID_MASK + 1];
 | |
| --- a/net/mac80211/status.c
 | |
| +++ b/net/mac80211/status.c
 | |
| @@ -1147,9 +1147,17 @@ void ieee80211_tx_status_ext(struct ieee
 | |
|  	struct ieee80211_tx_info *info = status->info;
 | |
|  	struct ieee80211_sta *pubsta = status->sta;
 | |
|  	struct ieee80211_supported_band *sband;
 | |
| +	struct sta_info *sta;
 | |
|  	int retry_count;
 | |
|  	bool acked, noack_success;
 | |
|  
 | |
| +	if (pubsta) {
 | |
| +		sta = container_of(pubsta, struct sta_info, sta);
 | |
| +
 | |
| +		if (status->rate)
 | |
| +			sta->tx_stats.last_rate_info = *status->rate;
 | |
| +	}
 | |
| +
 | |
|  	if (status->skb)
 | |
|  		return __ieee80211_tx_status(hw, status);
 | |
|  
 | |
| @@ -1164,10 +1172,6 @@ void ieee80211_tx_status_ext(struct ieee
 | |
|  	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 && !noack_success)
 | |
|  			sta->status_stats.retry_failed++;
 | |
|  		sta->status_stats.retry_count += retry_count;
 |