diff options
Diffstat (limited to 'package/mac80211')
| -rw-r--r-- | package/mac80211/patches/300-pending_work.patch | 496 | 
1 files changed, 482 insertions, 14 deletions
| diff --git a/package/mac80211/patches/300-pending_work.patch b/package/mac80211/patches/300-pending_work.patch index a609c9a5e..a4bfb99b4 100644 --- a/package/mac80211/patches/300-pending_work.patch +++ b/package/mac80211/patches/300-pending_work.patch @@ -634,7 +634,16 @@   	rt2x00dev->hw->wiphy->flags |= WIPHY_FLAG_IBSS_RSN;  --- a/net/mac80211/rc80211_minstrel_ht.c  +++ b/net/mac80211/rc80211_minstrel_ht.c -@@ -26,11 +26,11 @@ +@@ -17,8 +17,6 @@ + #include "rc80211_minstrel_ht.h" +  + #define AVG_PKT_SIZE	1200 +-#define SAMPLE_COLUMNS	10 +-#define EWMA_LEVEL		75 +  + /* Number of bits for an average sized packet */ + #define MCS_NBITS (AVG_PKT_SIZE << 3) +@@ -26,11 +24,11 @@   /* Number of symbols for a packet with (bps) bits per symbol */   #define MCS_NSYMS(bps) ((MCS_NBITS + (bps) - 1) / (bps)) @@ -649,7 +658,7 @@   	)   /* Transmit duration for the raw data part of an average sized packet */ -@@ -64,9 +64,9 @@ +@@ -64,9 +62,9 @@   }   #define CCK_DURATION(_bitrate, _short, _len)		\ @@ -661,7 +670,23 @@   #define CCK_ACK_DURATION(_bitrate, _short)			\   	(CCK_DURATION((_bitrate > 10 ? 20 : 10), false, 60) +	\ -@@ -211,20 +211,32 @@ static void +@@ -129,15 +127,6 @@ const struct mcs_group minstrel_mcs_grou + static u8 sample_table[SAMPLE_COLUMNS][MCS_GROUP_RATES]; +  + /* +- * Perform EWMA (Exponentially Weighted Moving Average) calculation +- */ +-static int +-minstrel_ewma(int old, int new, int weight) +-{ +-	return (new * (100 - weight) + old * weight) / 100; +-} +- +-/* +  * Look up an MCS group index based on mac80211 rate information +  */ + static int +@@ -211,20 +200,32 @@ static void   minstrel_ht_calc_tp(struct minstrel_ht_sta *mi, int group, int rate)   {   	struct minstrel_rate_stats *mr; @@ -689,17 +714,17 @@   	if (group != MINSTREL_CCK_GROUP)  -		usecs = mi->overhead / MINSTREL_TRUNC(mi->avg_ampdu_len);  +		nsecs = 1000 * mi->overhead / MINSTREL_TRUNC(mi->avg_ampdu_len); ++ ++	nsecs += minstrel_mcs_groups[group].duration[rate]; ++	tp = 1000000 * ((mr->probability * 1000) / nsecs);  -	usecs += minstrel_mcs_groups[group].duration[rate];  -	mr->cur_tp = MINSTREL_TRUNC((1000000 / usecs) * mr->probability); -+	nsecs += minstrel_mcs_groups[group].duration[rate]; -+	tp = 1000000 * ((mr->probability * 1000) / nsecs); -+  +	mr->cur_tp = MINSTREL_TRUNC(tp);   }   /* -@@ -308,8 +320,8 @@ minstrel_ht_update_stats(struct minstrel +@@ -308,8 +309,8 @@ minstrel_ht_update_stats(struct minstrel   		}   	} @@ -710,7 +735,7 @@   	cur_prob = 0;   	cur_prob_tp = 0; -@@ -320,20 +332,13 @@ minstrel_ht_update_stats(struct minstrel +@@ -320,20 +321,13 @@ minstrel_ht_update_stats(struct minstrel   		if (!mg->supported)   			continue; @@ -732,7 +757,7 @@   		}   		mr = minstrel_get_ratestats(mi, mg->max_tp_rate2); -@@ -343,6 +348,23 @@ minstrel_ht_update_stats(struct minstrel +@@ -343,6 +337,23 @@ minstrel_ht_update_stats(struct minstrel   		}   	} @@ -756,7 +781,7 @@   	mi->stats_update = jiffies;   } -@@ -467,7 +489,7 @@ minstrel_ht_tx_status(void *priv, struct +@@ -467,7 +478,7 @@ minstrel_ht_tx_status(void *priv, struct   	if (!mi->sample_wait && !mi->sample_tries && mi->sample_count > 0) {   		mi->sample_wait = 16 + 2 * MINSTREL_TRUNC(mi->avg_ampdu_len); @@ -765,7 +790,7 @@   		mi->sample_count--;   	} -@@ -536,7 +558,7 @@ minstrel_calc_retransmit(struct minstrel +@@ -536,7 +547,7 @@ minstrel_calc_retransmit(struct minstrel   	mr->retry_updated = true;   	group = &minstrel_mcs_groups[index / MCS_GROUP_RATES]; @@ -774,7 +799,7 @@   	/* Contention time for first 2 tries */   	ctime = (t_slot * cw) >> 1; -@@ -616,6 +638,7 @@ minstrel_get_sample_rate(struct minstrel +@@ -616,6 +627,7 @@ minstrel_get_sample_rate(struct minstrel   {   	struct minstrel_rate_stats *mr;   	struct minstrel_mcs_group_data *mg; @@ -782,7 +807,7 @@   	int sample_idx = 0;   	if (mi->sample_wait > 0) { -@@ -626,39 +649,46 @@ minstrel_get_sample_rate(struct minstrel +@@ -626,39 +638,46 @@ minstrel_get_sample_rate(struct minstrel   	if (!mi->sample_tries)   		return -1; @@ -840,7 +865,19 @@   }  --- a/net/mac80211/rc80211_minstrel_ht.h  +++ b/net/mac80211/rc80211_minstrel_ht.h -@@ -85,6 +85,7 @@ struct minstrel_ht_sta { +@@ -16,11 +16,6 @@ + #define MINSTREL_MAX_STREAMS	3 + #define MINSTREL_STREAM_GROUPS	4 +  +-/* scaled fraction values */ +-#define MINSTREL_SCALE	16 +-#define MINSTREL_FRAC(val, div) (((val) << MINSTREL_SCALE) / div) +-#define MINSTREL_TRUNC(val) ((val) >> MINSTREL_SCALE) +- + #define MCS_GROUP_RATES	8 +  + struct mcs_group { +@@ -85,6 +80,7 @@ struct minstrel_ht_sta {   	/* best probability rate */   	unsigned int max_prob_rate; @@ -1161,3 +1198,434 @@   	if (ifmgd->auth_data && !ifmgd->auth_data->done) {   		err = -EBUSY; +--- a/net/mac80211/rc80211_minstrel.c ++++ b/net/mac80211/rc80211_minstrel.c +@@ -55,7 +55,6 @@ + #include "rate.h" + #include "rc80211_minstrel.h" +  +-#define SAMPLE_COLUMNS	10 + #define SAMPLE_TBL(_mi, _idx, _col) \ + 		_mi->sample_table[(_idx * SAMPLE_COLUMNS) + _col] +  +@@ -70,16 +69,31 @@ rix_to_ndx(struct minstrel_sta_info *mi, + 	return i; + } +  ++/* find & sort topmost throughput rates */ ++static inline void ++minstrel_sort_best_tp_rates(struct minstrel_sta_info *mi, int i, u8 *tp_list) ++{ ++	int j = MAX_THR_RATES; ++ ++	while (j > 0 && mi->r[i].cur_tp > mi->r[tp_list[j - 1]].cur_tp) ++		j--; ++	if (j < MAX_THR_RATES - 1) ++		memmove(&tp_list[j + 1], &tp_list[j], MAX_THR_RATES - (j + 1)); ++	if (j < MAX_THR_RATES) ++		tp_list[j] = i; ++} ++ + static void + minstrel_update_stats(struct minstrel_priv *mp, struct minstrel_sta_info *mi) + { +-	u32 max_tp = 0, index_max_tp = 0, index_max_tp2 = 0; +-	u32 max_prob = 0, index_max_prob = 0; ++	u8 tmp_tp_rate[MAX_THR_RATES]; ++	u8 tmp_prob_rate = 0; + 	u32 usecs; +-	u32 p; + 	int i; +  +-	mi->stats_update = jiffies; ++	for (i=0; i < MAX_THR_RATES; i++) ++	    tmp_tp_rate[i] = 0; ++ + 	for (i = 0; i < mi->n_rates; i++) { + 		struct minstrel_rate *mr = &mi->r[i]; +  +@@ -87,27 +101,32 @@ minstrel_update_stats(struct minstrel_pr + 		if (!usecs) + 			usecs = 1000000; +  +-		/* To avoid rounding issues, probabilities scale from 0 (0%) +-		 * to 18000 (100%) */ +-		if (mr->attempts) { +-			p = (mr->success * 18000) / mr->attempts; ++		if (unlikely(mr->attempts > 0)) { ++			mr->sample_skipped = 0; ++			mr->cur_prob = MINSTREL_FRAC(mr->success, mr->attempts); + 			mr->succ_hist += mr->success; + 			mr->att_hist += mr->attempts; +-			mr->cur_prob = p; +-			p = ((p * (100 - mp->ewma_level)) + (mr->probability * +-				mp->ewma_level)) / 100; +-			mr->probability = p; +-			mr->cur_tp = p * (1000000 / usecs); +-		} ++			mr->probability = minstrel_ewma(mr->probability, ++							mr->cur_prob, ++							EWMA_LEVEL); ++		} else ++			mr->sample_skipped++; +  + 		mr->last_success = mr->success; + 		mr->last_attempts = mr->attempts; + 		mr->success = 0; + 		mr->attempts = 0; +  ++		/* Update throughput per rate, reset thr. below 10% success */ ++		if (mr->probability < MINSTREL_FRAC(10, 100)) ++			mr->cur_tp = 0; ++		else ++			mr->cur_tp = mr->probability * (1000000 / usecs); ++ + 		/* Sample less often below the 10% chance of success. + 		 * Sample less often above the 95% chance of success. */ +-		if ((mr->probability > 17100) || (mr->probability < 1800)) { ++		if (mr->probability > MINSTREL_FRAC(95, 100) || ++		    mr->probability < MINSTREL_FRAC(10, 100)) { + 			mr->adjusted_retry_count = mr->retry_count >> 1; + 			if (mr->adjusted_retry_count > 2) + 				mr->adjusted_retry_count = 2; +@@ -118,35 +137,30 @@ minstrel_update_stats(struct minstrel_pr + 		} + 		if (!mr->adjusted_retry_count) + 			mr->adjusted_retry_count = 2; +-	} +  +-	for (i = 0; i < mi->n_rates; i++) { +-		struct minstrel_rate *mr = &mi->r[i]; +-		if (max_tp < mr->cur_tp) { +-			index_max_tp = i; +-			max_tp = mr->cur_tp; +-		} +-		if (max_prob < mr->probability) { +-			index_max_prob = i; +-			max_prob = mr->probability; ++		minstrel_sort_best_tp_rates(mi, i, tmp_tp_rate); ++ ++		/* To determine the most robust rate (max_prob_rate) used at ++		 * 3rd mmr stage we distinct between two cases: ++		 * (1) if any success probabilitiy >= 95%, out of those rates ++		 * choose the maximum throughput rate as max_prob_rate ++		 * (2) if all success probabilities < 95%, the rate with ++		 * highest success probability is choosen as max_prob_rate */ ++		if (mr->probability >= MINSTREL_FRAC(95,100)) { ++			if (mr->cur_tp >= mi->r[tmp_prob_rate].cur_tp) ++				tmp_prob_rate = i; ++		} else { ++			if (mr->probability >= mi->r[tmp_prob_rate].probability) ++				tmp_prob_rate = i; + 		} + 	} +  +-	max_tp = 0; +-	for (i = 0; i < mi->n_rates; i++) { +-		struct minstrel_rate *mr = &mi->r[i]; +- +-		if (i == index_max_tp) +-			continue; ++	/* Assign the new rate set */ ++	memcpy(mi->max_tp_rate, tmp_tp_rate, sizeof(mi->max_tp_rate)); ++	mi->max_prob_rate = tmp_prob_rate; +  +-		if (max_tp < mr->cur_tp) { +-			index_max_tp2 = i; +-			max_tp = mr->cur_tp; +-		} +-	} +-	mi->max_tp_rate = index_max_tp; +-	mi->max_tp_rate2 = index_max_tp2; +-	mi->max_prob_rate = index_max_prob; ++	/* Reset update timer */ ++	mi->stats_update = jiffies; + } +  + static void +@@ -207,10 +221,10 @@ static int + minstrel_get_next_sample(struct minstrel_sta_info *mi) + { + 	unsigned int sample_ndx; +-	sample_ndx = SAMPLE_TBL(mi, mi->sample_idx, mi->sample_column); +-	mi->sample_idx++; +-	if ((int) mi->sample_idx > (mi->n_rates - 2)) { +-		mi->sample_idx = 0; ++	sample_ndx = SAMPLE_TBL(mi, mi->sample_row, mi->sample_column); ++	mi->sample_row++; ++	if ((int) mi->sample_row >= mi->n_rates) { ++		mi->sample_row = 0; + 		mi->sample_column++; + 		if (mi->sample_column >= SAMPLE_COLUMNS) + 			mi->sample_column = 0; +@@ -228,31 +242,37 @@ minstrel_get_rate(void *priv, struct iee + 	struct minstrel_priv *mp = priv; + 	struct ieee80211_tx_rate *ar = info->control.rates; + 	unsigned int ndx, sample_ndx = 0; +-	bool mrr; +-	bool sample_slower = false; +-	bool sample = false; ++	bool mrr_capable; ++	bool indirect_rate_sampling = false; ++	bool rate_sampling = false; + 	int i, delta; + 	int mrr_ndx[3]; +-	int sample_rate; ++	int sampling_ratio; +  ++	/* management/no-ack frames do not use rate control */ + 	if (rate_control_send_low(sta, priv_sta, txrc)) + 		return; +  +-	mrr = mp->has_mrr && !txrc->rts && !txrc->bss_conf->use_cts_prot; +- +-	ndx = mi->max_tp_rate; +- +-	if (mrr) +-		sample_rate = mp->lookaround_rate_mrr; ++	/* check multi-rate-retry capabilities & adjust lookaround_rate */ ++	mrr_capable = mp->has_mrr && ++		      !txrc->rts && ++		      !txrc->bss_conf->use_cts_prot; ++	if (mrr_capable) ++		sampling_ratio = mp->lookaround_rate_mrr; + 	else +-		sample_rate = mp->lookaround_rate; ++		sampling_ratio = mp->lookaround_rate; ++ ++	/* init rateindex [ndx] with max throughput rate */ ++	ndx = mi->max_tp_rate[0]; +  ++	/* increase sum packet counter */ + 	mi->packet_count++; +-	delta = (mi->packet_count * sample_rate / 100) - ++ ++	delta = (mi->packet_count * sampling_ratio / 100) - + 			(mi->sample_count + mi->sample_deferred / 2); +  + 	/* delta > 0: sampling required */ +-	if ((delta > 0) && (mrr || !mi->prev_sample)) { ++	if ((delta > 0) && (mrr_capable || !mi->prev_sample)) { + 		struct minstrel_rate *msr; + 		if (mi->packet_count >= 10000) { + 			mi->sample_deferred = 0; +@@ -271,21 +291,28 @@ minstrel_get_rate(void *priv, struct iee + 			mi->sample_count += (delta - mi->n_rates * 2); + 		} +  ++		/* get next random rate sample */ + 		sample_ndx = minstrel_get_next_sample(mi); + 		msr = &mi->r[sample_ndx]; +-		sample = true; +-		sample_slower = mrr && (msr->perfect_tx_time > +-			mi->r[ndx].perfect_tx_time); ++		rate_sampling = true; +  +-		if (!sample_slower) { ++		/* Decide if direct ( 1st mrr stage) or indirect (2nd mrr stage) ++		 * rate sampling method should be used. ++		 * Respect such rates that are not sampled for 20 interations. ++		 */ ++		if (mrr_capable && ++		    msr->perfect_tx_time > mi->r[ndx].perfect_tx_time && ++		    msr->sample_skipped < 20) ++				indirect_rate_sampling = true; ++ ++		if (!indirect_rate_sampling) { + 			if (msr->sample_limit != 0) { + 				ndx = sample_ndx; + 				mi->sample_count++; + 				if (msr->sample_limit > 0) + 					msr->sample_limit--; +-			} else { +-				sample = false; +-			} ++			} else ++				rate_sampling = false; + 		} else { + 			/* Only use IEEE80211_TX_CTL_RATE_CTRL_PROBE to mark + 			 * packets that have the sampling rate deferred to the +@@ -297,34 +324,39 @@ minstrel_get_rate(void *priv, struct iee + 			mi->sample_deferred++; + 		} + 	} +-	mi->prev_sample = sample; ++	mi->prev_sample = rate_sampling; +  + 	/* If we're not using MRR and the sampling rate already + 	 * has a probability of >95%, we shouldn't be attempting + 	 * to use it, as this only wastes precious airtime */ +-	if (!mrr && sample && (mi->r[ndx].probability > 17100)) +-		ndx = mi->max_tp_rate; ++	if (!mrr_capable && rate_sampling && ++	   (mi->r[ndx].probability > MINSTREL_FRAC(95, 100))) ++		ndx = mi->max_tp_rate[0]; +  ++	/* mrr setup for 1st stage */ + 	ar[0].idx = mi->r[ndx].rix; + 	ar[0].count = minstrel_get_retry_count(&mi->r[ndx], info); +  +-	if (!mrr) { +-		if (!sample) ++	/* non mrr setup for 2nd stage */ ++	if (!mrr_capable) { ++		if (!rate_sampling) + 			ar[0].count = mp->max_retry; + 		ar[1].idx = mi->lowest_rix; + 		ar[1].count = mp->max_retry; + 		return; + 	} +  +-	/* MRR setup */ +-	if (sample) { +-		if (sample_slower) ++	/* mrr setup for 2nd stage */ ++	if (rate_sampling) { ++		if (indirect_rate_sampling) + 			mrr_ndx[0] = sample_ndx; + 		else +-			mrr_ndx[0] = mi->max_tp_rate; ++			mrr_ndx[0] = mi->max_tp_rate[0]; + 	} else { +-		mrr_ndx[0] = mi->max_tp_rate2; ++		mrr_ndx[0] = mi->max_tp_rate[1]; + 	} ++ ++	/* mrr setup for 3rd & 4th stage */ + 	mrr_ndx[1] = mi->max_prob_rate; + 	mrr_ndx[2] = 0; + 	for (i = 1; i < 4; i++) { +@@ -351,26 +383,21 @@ static void + init_sample_table(struct minstrel_sta_info *mi) + { + 	unsigned int i, col, new_idx; +-	unsigned int n_srates = mi->n_rates - 1; + 	u8 rnd[8]; +  + 	mi->sample_column = 0; +-	mi->sample_idx = 0; +-	memset(mi->sample_table, 0, SAMPLE_COLUMNS * mi->n_rates); ++	mi->sample_row = 0; ++	memset(mi->sample_table, 0xff, SAMPLE_COLUMNS * mi->n_rates); +  + 	for (col = 0; col < SAMPLE_COLUMNS; col++) { +-		for (i = 0; i < n_srates; i++) { ++		for (i = 0; i < mi->n_rates; i++) { + 			get_random_bytes(rnd, sizeof(rnd)); +-			new_idx = (i + rnd[i & 7]) % n_srates; ++			new_idx = (i + rnd[i & 7]) % mi->n_rates; +  +-			while (SAMPLE_TBL(mi, new_idx, col) != 0) +-				new_idx = (new_idx + 1) % n_srates; ++			while (SAMPLE_TBL(mi, new_idx, col) != 0xff) ++				new_idx = (new_idx + 1) % mi->n_rates; +  +-			/* Don't sample the slowest rate (i.e. slowest base +-			 * rate). We must presume that the slowest rate works +-			 * fine, or else other management frames will also be +-			 * failing and the link will break */ +-			SAMPLE_TBL(mi, new_idx, col) = i + 1; ++			SAMPLE_TBL(mi, new_idx, col) = i; + 		} + 	} + } +@@ -542,9 +569,6 @@ minstrel_alloc(struct ieee80211_hw *hw,  + 	mp->lookaround_rate = 5; + 	mp->lookaround_rate_mrr = 10; +  +-	/* moving average weight for EWMA */ +-	mp->ewma_level = 75; +- + 	/* maximum time that the hw is allowed to stay in one MRR segment */ + 	mp->segment_size = 6000; +  +--- a/net/mac80211/rc80211_minstrel.h ++++ b/net/mac80211/rc80211_minstrel.h +@@ -9,6 +9,28 @@ + #ifndef __RC_MINSTREL_H + #define __RC_MINSTREL_H +  ++#define EWMA_LEVEL	75	/* ewma weighting factor [%] */ ++#define SAMPLE_COLUMNS	10	/* number of columns in sample table */ ++ ++ ++/* scaled fraction values */ ++#define MINSTREL_SCALE  16 ++#define MINSTREL_FRAC(val, div) (((val) << MINSTREL_SCALE) / div) ++#define MINSTREL_TRUNC(val) ((val) >> MINSTREL_SCALE) ++ ++/* number of highest throughput rates to consider*/ ++#define MAX_THR_RATES 4 ++ ++/* ++ * Perform EWMA (Exponentially Weighted Moving Average) calculation ++  */ ++static inline int ++minstrel_ewma(int old, int new, int weight) ++{ ++	return (new * (100 - weight) + old * weight) / 100; ++} ++ ++ + struct minstrel_rate { + 	int bitrate; + 	int rix; +@@ -26,6 +48,7 @@ struct minstrel_rate { + 	u32 attempts; + 	u32 last_attempts; + 	u32 last_success; ++	u8 sample_skipped; +  + 	/* parts per thousand */ + 	u32 cur_prob; +@@ -45,14 +68,13 @@ struct minstrel_sta_info { +  + 	unsigned int lowest_rix; +  +-	unsigned int max_tp_rate; +-	unsigned int max_tp_rate2; +-	unsigned int max_prob_rate; ++	u8 max_tp_rate[MAX_THR_RATES]; ++	u8 max_prob_rate; + 	unsigned int packet_count; + 	unsigned int sample_count; + 	int sample_deferred; +  +-	unsigned int sample_idx; ++	unsigned int sample_row; + 	unsigned int sample_column; +  + 	int n_rates; +@@ -73,7 +95,6 @@ struct minstrel_priv { + 	unsigned int cw_min; + 	unsigned int cw_max; + 	unsigned int max_retry; +-	unsigned int ewma_level; + 	unsigned int segment_size; + 	unsigned int update_interval; + 	unsigned int lookaround_rate; +--- a/net/mac80211/rc80211_minstrel_debugfs.c ++++ b/net/mac80211/rc80211_minstrel_debugfs.c +@@ -73,15 +73,17 @@ minstrel_stats_open(struct inode *inode, + 	for (i = 0; i < mi->n_rates; i++) { + 		struct minstrel_rate *mr = &mi->r[i]; +  +-		*(p++) = (i == mi->max_tp_rate) ? 'T' : ' '; +-		*(p++) = (i == mi->max_tp_rate2) ? 't' : ' '; ++		*(p++) = (i == mi->max_tp_rate[0]) ? 'A' : ' '; ++		*(p++) = (i == mi->max_tp_rate[1]) ? 'B' : ' '; ++		*(p++) = (i == mi->max_tp_rate[2]) ? 'C' : ' '; ++		*(p++) = (i == mi->max_tp_rate[3]) ? 'D' : ' '; + 		*(p++) = (i == mi->max_prob_rate) ? 'P' : ' '; + 		p += sprintf(p, "%3u%s", mr->bitrate / 2, + 				(mr->bitrate & 1 ? ".5" : "  ")); +  +-		tp = mr->cur_tp / ((18000 << 10) / 96); +-		prob = mr->cur_prob / 18; +-		eprob = mr->probability / 18; ++		tp = MINSTREL_TRUNC(mr->cur_tp / 10); ++		prob = MINSTREL_TRUNC(mr->cur_prob * 1000); ++		eprob = MINSTREL_TRUNC(mr->probability * 1000); +  + 		p += sprintf(p, "  %6u.%1u   %6u.%1u   %6u.%1u        " + 				"%3u(%3u)   %8llu    %8llu\n", | 
