Home | History | Annotate | Line # | Download | only in ic
athrate-sample.c revision 1.7
      1  1.7  xtraeme /*	$NetBSD: athrate-sample.c,v 1.7 2006/02/05 06:03:26 xtraeme Exp $ */
      2  1.7  xtraeme 
      3  1.1   dyoung /*-
      4  1.1   dyoung  * Copyright (c) 2005 John Bicket
      5  1.1   dyoung  * All rights reserved.
      6  1.1   dyoung  *
      7  1.1   dyoung  * Redistribution and use in source and binary forms, with or without
      8  1.1   dyoung  * modification, are permitted provided that the following conditions
      9  1.1   dyoung  * are met:
     10  1.1   dyoung  * 1. Redistributions of source code must retain the above copyright
     11  1.1   dyoung  *    notice, this list of conditions and the following disclaimer,
     12  1.1   dyoung  *    without modification.
     13  1.1   dyoung  * 2. Redistributions in binary form must reproduce at minimum a disclaimer
     14  1.1   dyoung  *    similar to the "NO WARRANTY" disclaimer below ("Disclaimer") and any
     15  1.1   dyoung  *    redistribution must be conditioned upon including a substantially
     16  1.1   dyoung  *    similar Disclaimer requirement for further binary redistribution.
     17  1.1   dyoung  * 3. Neither the names of the above-listed copyright holders nor the names
     18  1.1   dyoung  *    of any contributors may be used to endorse or promote products derived
     19  1.1   dyoung  *    from this software without specific prior written permission.
     20  1.1   dyoung  *
     21  1.1   dyoung  * Alternatively, this software may be distributed under the terms of the
     22  1.1   dyoung  * GNU General Public License ("GPL") version 2 as published by the Free
     23  1.1   dyoung  * Software Foundation.
     24  1.1   dyoung  *
     25  1.1   dyoung  * NO WARRANTY
     26  1.1   dyoung  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
     27  1.1   dyoung  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
     28  1.1   dyoung  * LIMITED TO, THE IMPLIED WARRANTIES OF NONINFRINGEMENT, MERCHANTIBILITY
     29  1.1   dyoung  * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
     30  1.1   dyoung  * THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY,
     31  1.1   dyoung  * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
     32  1.1   dyoung  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
     33  1.1   dyoung  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
     34  1.1   dyoung  * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
     35  1.1   dyoung  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
     36  1.1   dyoung  * THE POSSIBILITY OF SUCH DAMAGES.
     37  1.1   dyoung  */
     38  1.1   dyoung 
     39  1.1   dyoung #include <sys/cdefs.h>
     40  1.3   dyoung #ifdef __FreeBSD__
     41  1.5    skrll __FBSDID("$FreeBSD: src/sys/dev/ath/ath_rate/sample/sample.c,v 1.9 2005/07/22 16:50:17 sam Exp $");
     42  1.3   dyoung #endif
     43  1.3   dyoung #ifdef __NetBSD__
     44  1.7  xtraeme __KERNEL_RCSID(0, "$NetBSD: athrate-sample.c,v 1.7 2006/02/05 06:03:26 xtraeme Exp $");
     45  1.3   dyoung #endif
     46  1.3   dyoung 
     47  1.1   dyoung 
     48  1.1   dyoung /*
     49  1.1   dyoung  * John Bicket's SampleRate control algorithm.
     50  1.1   dyoung  */
     51  1.1   dyoung #include "opt_inet.h"
     52  1.1   dyoung 
     53  1.1   dyoung #include <sys/param.h>
     54  1.1   dyoung #include <sys/systm.h>
     55  1.1   dyoung #include <sys/sysctl.h>
     56  1.1   dyoung #include <sys/kernel.h>
     57  1.1   dyoung #include <sys/lock.h>
     58  1.1   dyoung #include <sys/errno.h>
     59  1.4   martin #include <sys/device.h>
     60  1.1   dyoung 
     61  1.1   dyoung #include <machine/bus.h>
     62  1.1   dyoung 
     63  1.1   dyoung #include <sys/socket.h>
     64  1.1   dyoung 
     65  1.1   dyoung #include <net/if.h>
     66  1.1   dyoung #include <net/if_media.h>
     67  1.1   dyoung #include <net/if_arp.h>
     68  1.3   dyoung #include <net/if_ether.h>		/* XXX for ether_sprintf */
     69  1.1   dyoung 
     70  1.1   dyoung #include <net80211/ieee80211_var.h>
     71  1.1   dyoung 
     72  1.1   dyoung #include <net/bpf.h>
     73  1.1   dyoung 
     74  1.1   dyoung #ifdef INET
     75  1.1   dyoung #include <netinet/in.h>
     76  1.1   dyoung #endif
     77  1.1   dyoung 
     78  1.2   dyoung #include <dev/ic/athvar.h>
     79  1.2   dyoung #include <dev/ic/athrate-sample.h>
     80  1.2   dyoung #include <contrib/dev/ic/athhal_desc.h>
     81  1.1   dyoung 
     82  1.1   dyoung #define	SAMPLE_DEBUG
     83  1.1   dyoung #ifdef SAMPLE_DEBUG
     84  1.1   dyoung enum {
     85  1.1   dyoung 	ATH_DEBUG_RATE		= 0x00000010,	/* rate control */
     86  1.1   dyoung };
     87  1.1   dyoung #define	DPRINTF(sc, _fmt, ...) do {				\
     88  1.1   dyoung 	if (sc->sc_debug & ATH_DEBUG_RATE)			\
     89  1.1   dyoung 		printf(_fmt, __VA_ARGS__);			\
     90  1.1   dyoung } while (0)
     91  1.1   dyoung #else
     92  1.1   dyoung #define	DPRINTF(sc, _fmt, ...)
     93  1.1   dyoung #endif
     94  1.1   dyoung 
     95  1.1   dyoung /*
     96  1.1   dyoung  * This file is an implementation of the SampleRate algorithm
     97  1.1   dyoung  * in "Bit-rate Selection in Wireless Networks"
     98  1.1   dyoung  * (http://www.pdos.lcs.mit.edu/papers/jbicket-ms.ps)
     99  1.1   dyoung  *
    100  1.1   dyoung  * SampleRate chooses the bit-rate it predicts will provide the most
    101  1.1   dyoung  * throughput based on estimates of the expected per-packet
    102  1.1   dyoung  * transmission time for each bit-rate.  SampleRate periodically sends
    103  1.1   dyoung  * packets at bit-rates other than the current one to estimate when
    104  1.1   dyoung  * another bit-rate will provide better performance. SampleRate
    105  1.1   dyoung  * switches to another bit-rate when its estimated per-packet
    106  1.1   dyoung  * transmission time becomes smaller than the current bit-rate's.
    107  1.1   dyoung  * SampleRate reduces the number of bit-rates it must sample by
    108  1.1   dyoung  * eliminating those that could not perform better than the one
    109  1.1   dyoung  * currently being used.  SampleRate also stops probing at a bit-rate
    110  1.1   dyoung  * if it experiences several successive losses.
    111  1.1   dyoung  *
    112  1.1   dyoung  * The difference between the algorithm in the thesis and the one in this
    113  1.1   dyoung  * file is that the one in this file uses a ewma instead of a window.
    114  1.1   dyoung  *
    115  1.1   dyoung  */
    116  1.1   dyoung 
    117  1.1   dyoung #define STALE_FAILURE_TIMEOUT_MS 10000
    118  1.1   dyoung 
    119  1.1   dyoung static void	ath_rate_ctl_reset(struct ath_softc *, struct ieee80211_node *);
    120  1.1   dyoung 
    121  1.6    perry static inline int size_to_bin(int size)
    122  1.1   dyoung {
    123  1.1   dyoung 	int x = 0;
    124  1.1   dyoung 	for (x = 0; x < NUM_PACKET_SIZE_BINS; x++) {
    125  1.1   dyoung 		if (size <= packet_size_bins[x]) {
    126  1.1   dyoung 			return x;
    127  1.1   dyoung 		}
    128  1.1   dyoung 	}
    129  1.1   dyoung 	return NUM_PACKET_SIZE_BINS-1;
    130  1.1   dyoung }
    131  1.6    perry static inline int bin_to_size(int index) {
    132  1.1   dyoung 	return packet_size_bins[index];
    133  1.1   dyoung }
    134  1.1   dyoung 
    135  1.6    perry static inline int rate_to_ndx(struct sample_node *sn, int rate) {
    136  1.1   dyoung 	int x = 0;
    137  1.1   dyoung 	for (x = 0; x < sn->num_rates; x++) {
    138  1.1   dyoung 		if (sn->rates[x].rate == rate) {
    139  1.1   dyoung 			return x;
    140  1.1   dyoung 		}
    141  1.1   dyoung 	}
    142  1.1   dyoung 	return -1;
    143  1.1   dyoung }
    144  1.1   dyoung 
    145  1.1   dyoung /*
    146  1.1   dyoung  * Setup rate codes for management/control frames.  We force
    147  1.1   dyoung  * all such frames to the lowest rate.
    148  1.1   dyoung  */
    149  1.1   dyoung static void
    150  1.1   dyoung ath_rate_setmgtrates(struct ath_softc *sc, struct ath_node *an)
    151  1.1   dyoung {
    152  1.1   dyoung 	const HAL_RATE_TABLE *rt = sc->sc_currates;
    153  1.1   dyoung 
    154  1.1   dyoung 	/* setup rates for management frames */
    155  1.1   dyoung 	/* XXX management/control frames always go at lowest speed */
    156  1.1   dyoung 	an->an_tx_mgtrate = rt->info[0].rateCode;
    157  1.1   dyoung 	an->an_tx_mgtratesp = an->an_tx_mgtrate
    158  1.1   dyoung 			    | rt->info[0].shortPreamble;
    159  1.1   dyoung }
    160  1.1   dyoung 
    161  1.1   dyoung void
    162  1.1   dyoung ath_rate_node_init(struct ath_softc *sc, struct ath_node *an)
    163  1.1   dyoung {
    164  1.1   dyoung 	DPRINTF(sc, "%s:\n", __func__);
    165  1.1   dyoung 	/* NB: assumed to be zero'd by caller */
    166  1.1   dyoung 	ath_rate_setmgtrates(sc, an);
    167  1.1   dyoung }
    168  1.1   dyoung 
    169  1.1   dyoung void
    170  1.1   dyoung ath_rate_node_cleanup(struct ath_softc *sc, struct ath_node *an)
    171  1.1   dyoung {
    172  1.1   dyoung 	DPRINTF(sc, "%s:\n", __func__);
    173  1.1   dyoung }
    174  1.1   dyoung 
    175  1.1   dyoung 
    176  1.1   dyoung /*
    177  1.1   dyoung  * returns the ndx with the lowest average_tx_time,
    178  1.1   dyoung  * or -1 if all the average_tx_times are 0.
    179  1.1   dyoung  */
    180  1.6    perry static inline int best_rate_ndx(struct sample_node *sn, int size_bin,
    181  1.1   dyoung 				  int require_acked_before)
    182  1.1   dyoung {
    183  1.1   dyoung 	int x = 0;
    184  1.3   dyoung         int best_ndx = 0;
    185  1.1   dyoung         int best_rate_tt = 0;
    186  1.1   dyoung         for (x = 0; x < sn->num_rates; x++) {
    187  1.1   dyoung 		int tt = sn->stats[size_bin][x].average_tx_time;
    188  1.1   dyoung 		if (tt <= 0 || (require_acked_before &&
    189  1.1   dyoung 				!sn->stats[size_bin][x].packets_acked)) {
    190  1.1   dyoung 			continue;
    191  1.1   dyoung 		}
    192  1.1   dyoung 		if (!best_rate_tt || best_rate_tt > tt) {
    193  1.1   dyoung 			best_rate_tt = tt;
    194  1.3   dyoung 			best_ndx = x;
    195  1.1   dyoung 		}
    196  1.1   dyoung         }
    197  1.3   dyoung         return (best_rate_tt) ? best_ndx : -1;
    198  1.1   dyoung }
    199  1.1   dyoung 
    200  1.1   dyoung /*
    201  1.1   dyoung  * pick a ndx s.t. the perfect_tx_time
    202  1.1   dyoung  * is less than the best bit-rate's average_tx_time
    203  1.1   dyoung  * and the ndx has not had four successive failures.
    204  1.1   dyoung  */
    205  1.6    perry static inline int pick_sample_ndx(struct sample_node *sn, int size_bin)
    206  1.1   dyoung {
    207  1.1   dyoung 	int x = 0;
    208  1.1   dyoung 	int current_ndx = 0;
    209  1.1   dyoung 	unsigned current_tt = 0;
    210  1.1   dyoung 
    211  1.1   dyoung 	current_ndx = sn->current_rate[size_bin];
    212  1.1   dyoung 	if (current_ndx < 0) {
    213  1.1   dyoung 		/* no successes yet, send at the lowest bit-rate */
    214  1.1   dyoung 		return 0;
    215  1.1   dyoung 	}
    216  1.1   dyoung 
    217  1.1   dyoung 	current_tt = sn->stats[size_bin][current_ndx].average_tx_time;
    218  1.1   dyoung 
    219  1.1   dyoung 	for (x = 0; x < sn->num_rates; x++) {
    220  1.1   dyoung 		int ndx = (sn->last_sample_ndx[size_bin] + 1 + x) % sn->num_rates;
    221  1.1   dyoung 		/*
    222  1.1   dyoung 		 * clear any stale stuff out.
    223  1.1   dyoung 		 */
    224  1.1   dyoung 		if (ticks - sn->stats[size_bin][ndx].last_tx > ((hz * STALE_FAILURE_TIMEOUT_MS)/1000)) {
    225  1.1   dyoung 			sn->stats[size_bin][ndx].average_tx_time = sn->stats[size_bin][ndx].perfect_tx_time;
    226  1.1   dyoung 			sn->stats[size_bin][ndx].successive_failures = 0;
    227  1.1   dyoung 			sn->stats[size_bin][ndx].tries = 0;
    228  1.1   dyoung 			sn->stats[size_bin][ndx].total_packets = 0;
    229  1.1   dyoung 			sn->stats[size_bin][ndx].packets_acked = 0;
    230  1.1   dyoung 		}
    231  1.1   dyoung 
    232  1.1   dyoung 		if (ndx != current_ndx &&
    233  1.1   dyoung 		    sn->stats[size_bin][ndx].perfect_tx_time < current_tt &&
    234  1.1   dyoung 		    sn->stats[size_bin][ndx].successive_failures < 4) {
    235  1.1   dyoung 			sn->last_sample_ndx[size_bin] = ndx;
    236  1.1   dyoung 			return ndx;
    237  1.1   dyoung 		}
    238  1.1   dyoung 	}
    239  1.1   dyoung 	return current_ndx;
    240  1.1   dyoung }
    241  1.1   dyoung 
    242  1.1   dyoung void
    243  1.1   dyoung ath_rate_findrate(struct ath_softc *sc, struct ath_node *an,
    244  1.1   dyoung 		  int shortPreamble, size_t frameLen,
    245  1.1   dyoung 		  u_int8_t *rix, int *try0, u_int8_t *txrate)
    246  1.1   dyoung {
    247  1.1   dyoung 	struct sample_node *sn = ATH_NODE_SAMPLE(an);
    248  1.1   dyoung 	struct sample_softc *ssc = ATH_SOFTC_SAMPLE(sc);
    249  1.1   dyoung 	struct ieee80211com *ic = &sc->sc_ic;
    250  1.1   dyoung 	int ndx, size_bin, mrr, best_ndx;
    251  1.1   dyoung 	unsigned average_tx_time;
    252  1.1   dyoung 
    253  1.1   dyoung 	mrr = sc->sc_mrretry && !(ic->ic_flags & IEEE80211_F_USEPROT) &&
    254  1.1   dyoung 		!(frameLen > ic->ic_rtsthreshold);
    255  1.1   dyoung 	size_bin = size_to_bin(frameLen);
    256  1.1   dyoung 	best_ndx = best_rate_ndx(sn, size_bin, !mrr);
    257  1.1   dyoung 
    258  1.1   dyoung 	if (best_ndx >= 0) {
    259  1.1   dyoung 		average_tx_time = sn->stats[size_bin][best_ndx].average_tx_time;
    260  1.1   dyoung 	} else {
    261  1.1   dyoung 		average_tx_time = 0;
    262  1.1   dyoung 	}
    263  1.1   dyoung 	if (sn->static_rate_ndx != -1) {
    264  1.1   dyoung 		ndx = sn->static_rate_ndx;
    265  1.1   dyoung 		*try0 = ATH_TXMAXTRY;
    266  1.1   dyoung 	} else {
    267  1.1   dyoung 		ndx = 0;
    268  1.1   dyoung 		*try0 = mrr ? 2 : ATH_TXMAXTRY;
    269  1.1   dyoung 
    270  1.1   dyoung 		DPRINTF(sc, "%s: %s size %d mrr %d packets_sent %d best_ndx %d "
    271  1.1   dyoung 			"sample tt %d packets since %d\n"
    272  1.1   dyoung 			, __func__, ether_sprintf(an->an_node.ni_macaddr)
    273  1.1   dyoung 			, packet_size_bins[size_bin]
    274  1.1   dyoung 			, mrr
    275  1.1   dyoung 			, sn->packets_sent[size_bin]
    276  1.1   dyoung 			, best_ndx
    277  1.1   dyoung 			, sn->sample_tt[size_bin]
    278  1.1   dyoung 			, sn->packets_since_sample[size_bin]
    279  1.1   dyoung 		);
    280  1.1   dyoung 		if (!sn->packets_sent[size_bin]) {
    281  1.1   dyoung 			/* no packets sent */
    282  1.1   dyoung 			if (best_ndx == -1) {
    283  1.1   dyoung 				ndx = sn->num_rates - 1;
    284  1.1   dyoung 				if (sc->sc_curmode != IEEE80211_MODE_11B) {
    285  1.1   dyoung 					for (; ndx >= 0 && sn->rates[ndx].rate > 72; ndx--)
    286  1.1   dyoung 						;
    287  1.1   dyoung 
    288  1.1   dyoung 				}
    289  1.1   dyoung 			} else {
    290  1.1   dyoung 				ndx = best_ndx;
    291  1.1   dyoung 			}
    292  1.1   dyoung 		} else if (best_ndx == -1) {
    293  1.1   dyoung 			/* no packet has succeeded yet */
    294  1.1   dyoung 			if (mrr) {
    295  1.1   dyoung 				/*
    296  1.1   dyoung 				 * no packet has succeeded, try the
    297  1.1   dyoung 				 * highest bitrate that hasn't failed
    298  1.1   dyoung 				 */
    299  1.1   dyoung 				for (ndx = sn->num_rates-1; ndx >= 0; ndx--) {
    300  1.1   dyoung 					if (sn->stats[size_bin][ndx].successive_failures == 0) {
    301  1.1   dyoung 						break;
    302  1.1   dyoung 					}
    303  1.1   dyoung 				}
    304  1.1   dyoung 			} else {
    305  1.1   dyoung 				ndx = sn->num_rates - 1;
    306  1.1   dyoung 				if (sc->sc_curmode != IEEE80211_MODE_11B) {
    307  1.1   dyoung 					for (; ndx >= 0 && sn->rates[ndx].rate > 72; ndx--)
    308  1.1   dyoung 						;
    309  1.1   dyoung 
    310  1.1   dyoung 				}
    311  1.1   dyoung 			}
    312  1.1   dyoung 		} else if (sn->sample_tt[size_bin] < (sn->packets_since_sample[size_bin]*ssc->ath_sample_rate/100) * average_tx_time &&
    313  1.1   dyoung 			   sn->packets_since_sample[size_bin] > 15) {
    314  1.1   dyoung 			/*
    315  1.1   dyoung 			 * we want to limit the time measuring the performance
    316  1.1   dyoung 			 * of other bit-rates to ath_sample_rate% of the
    317  1.1   dyoung 			 * total transmission time.
    318  1.1   dyoung 			 */
    319  1.1   dyoung 			ndx = pick_sample_ndx(sn, size_bin);
    320  1.1   dyoung 			if (ndx != sn->current_rate[size_bin]) {
    321  1.1   dyoung 				DPRINTF(sc, "%s: %s size %d last sample tt %d sampling %d packets since %d\n",
    322  1.1   dyoung 					__func__,
    323  1.1   dyoung 					ether_sprintf(an->an_node.ni_macaddr),
    324  1.1   dyoung 					packet_size_bins[size_bin],
    325  1.1   dyoung 					sn->sample_tt[size_bin],
    326  1.1   dyoung 					sn->rates[ndx].rate,
    327  1.1   dyoung 					sn->packets_since_sample[size_bin]);
    328  1.1   dyoung 				sn->current_sample_ndx[size_bin] = ndx;
    329  1.1   dyoung 			} else {
    330  1.1   dyoung 				sn->current_sample_ndx[size_bin] = -1;
    331  1.1   dyoung 			}
    332  1.1   dyoung 			sn->packets_since_sample[size_bin] = 0;
    333  1.1   dyoung 
    334  1.1   dyoung 		} else {
    335  1.1   dyoung 			sn->packets_since_sample[size_bin]++;
    336  1.1   dyoung 			/*
    337  1.1   dyoung 			 * don't switch bit-rates every packet.  only
    338  1.1   dyoung 			 * switch during the first few packets we send
    339  1.1   dyoung 			 * or after 100 packets, or if the current
    340  1.1   dyoung 			 * bit-rate begins to perform twice as bad as
    341  1.1   dyoung 			 * another one.
    342  1.1   dyoung 			 */
    343  1.1   dyoung 			if (sn->packets_sent[size_bin] < 20 ||
    344  1.1   dyoung 			    ticks - ((hz*2000)/1000) > sn->jiffies_since_switch[size_bin] ||
    345  1.1   dyoung 			    average_tx_time * 2 < sn->stats[size_bin][sn->current_rate[size_bin]].average_tx_time ) {
    346  1.1   dyoung 				if (sn->packets_sent[size_bin] > 20) {
    347  1.1   dyoung 					DPRINTF(sc, "%s: %s size %d switch rate %d (%d/%d) -> %d (%d/%d) after %d packets mmr %d\n",
    348  1.1   dyoung 						__func__,
    349  1.1   dyoung 						ether_sprintf(an->an_node.ni_macaddr),
    350  1.1   dyoung 						packet_size_bins[size_bin],
    351  1.1   dyoung 						sn->rates[sn->current_rate[size_bin]].rate,
    352  1.1   dyoung 						sn->stats[size_bin][sn->current_rate[size_bin]].average_tx_time,
    353  1.1   dyoung 						sn->stats[size_bin][sn->current_rate[size_bin]].perfect_tx_time,
    354  1.1   dyoung 						sn->rates[best_ndx].rate,
    355  1.1   dyoung 						sn->stats[size_bin][best_ndx].average_tx_time,
    356  1.1   dyoung 						sn->stats[size_bin][best_ndx].perfect_tx_time,
    357  1.1   dyoung 						sn->packets_since_switch[size_bin],
    358  1.1   dyoung 						mrr);
    359  1.1   dyoung 				}
    360  1.1   dyoung 				sn->packets_since_switch[size_bin] = 0;
    361  1.1   dyoung 				sn->current_rate[size_bin] = best_ndx;
    362  1.1   dyoung 				sn->jiffies_since_switch[size_bin] = ticks;
    363  1.1   dyoung 			}
    364  1.1   dyoung 			ndx = sn->current_rate[size_bin];
    365  1.1   dyoung 			sn->packets_since_switch[size_bin]++;
    366  1.1   dyoung 		}
    367  1.1   dyoung 
    368  1.1   dyoung 	}
    369  1.1   dyoung 
    370  1.1   dyoung 	if (ndx < 0) {
    371  1.1   dyoung 		ndx = 0;
    372  1.1   dyoung 	}
    373  1.1   dyoung 	*rix = sn->rates[ndx].rix;
    374  1.1   dyoung 	if (shortPreamble) {
    375  1.1   dyoung 		*txrate = sn->rates[ndx].shortPreambleRateCode;
    376  1.1   dyoung 	} else {
    377  1.1   dyoung 		*txrate = sn->rates[ndx].rateCode;
    378  1.1   dyoung 	}
    379  1.1   dyoung 	sn->packets_sent[size_bin]++;
    380  1.1   dyoung 	an->an_node.ni_txrate = ndx;
    381  1.1   dyoung }
    382  1.1   dyoung 
    383  1.1   dyoung void
    384  1.1   dyoung ath_rate_setupxtxdesc(struct ath_softc *sc, struct ath_node *an,
    385  1.1   dyoung 		      struct ath_desc *ds, int shortPreamble, u_int8_t rix)
    386  1.1   dyoung {
    387  1.1   dyoung 	struct sample_node *sn = ATH_NODE_SAMPLE(an);
    388  1.1   dyoung 	int rateCode = -1;
    389  1.1   dyoung 	int frame_size, size_bin, best_ndx, ndx;
    390  1.1   dyoung 
    391  1.1   dyoung 	frame_size = ds->ds_ctl0 & 0x0fff; /* low-order 12 bits of ds_ctl0 */
    392  1.1   dyoung 	KASSERT(frame_size != 0, ("no frame size"));
    393  1.1   dyoung 	size_bin = size_to_bin(frame_size);
    394  1.1   dyoung 	best_ndx = best_rate_ndx(sn, size_bin, 0);
    395  1.1   dyoung 
    396  1.1   dyoung 	if (best_ndx == -1 || !sn->stats[size_bin][best_ndx].packets_acked) {
    397  1.1   dyoung 		/*
    398  1.1   dyoung 		 * no packet has succeeded, so also try at the
    399  1.1   dyoung 		 * lowest bitate.
    400  1.1   dyoung 		 */
    401  1.1   dyoung 		ndx = 0;
    402  1.1   dyoung 	} else {
    403  1.1   dyoung 		/*
    404  1.1   dyoung 		 * we're trying a different bit-rate, and it could be lossy,
    405  1.1   dyoung 		 * so if it fails try at the best bit-rate.
    406  1.1   dyoung 		 */
    407  1.1   dyoung 		ndx = best_ndx;
    408  1.1   dyoung 	}
    409  1.1   dyoung 	KASSERT(0 <= ndx && ndx < IEEE80211_RATE_MAXSIZE,
    410  1.1   dyoung 		("invalid ndx %d", ndx));
    411  1.1   dyoung 	if (shortPreamble) {
    412  1.1   dyoung 		rateCode = sn->rates[ndx].shortPreambleRateCode;
    413  1.1   dyoung 	} else {
    414  1.1   dyoung 		rateCode = sn->rates[ndx].rateCode;
    415  1.1   dyoung 	}
    416  1.1   dyoung 	ath_hal_setupxtxdesc(sc->sc_ah, ds
    417  1.1   dyoung 			     , rateCode, 3	        /* series 1 */
    418  1.1   dyoung 			     , sn->rates[0].rateCode, 3	/* series 2 */
    419  1.1   dyoung 			     , 0, 0	                /* series 3 */
    420  1.1   dyoung 			     );
    421  1.1   dyoung }
    422  1.1   dyoung 
    423  1.1   dyoung static void
    424  1.1   dyoung update_stats(struct ath_softc *sc, struct ath_node *an,
    425  1.1   dyoung 		  int frame_size,
    426  1.1   dyoung 		  int ndx0, int tries0,
    427  1.1   dyoung 		  int ndx1, int tries1,
    428  1.1   dyoung 		  int ndx2, int tries2,
    429  1.1   dyoung 		  int ndx3, int tries3,
    430  1.1   dyoung 		  int short_tries, int tries, int status)
    431  1.1   dyoung {
    432  1.1   dyoung 	struct sample_node *sn = ATH_NODE_SAMPLE(an);
    433  1.1   dyoung 	struct sample_softc *ssc = ATH_SOFTC_SAMPLE(sc);
    434  1.1   dyoung 	int tt = 0;
    435  1.1   dyoung 	int tries_so_far = 0;
    436  1.1   dyoung 	int size_bin = 0;
    437  1.1   dyoung 	int size = 0;
    438  1.1   dyoung 	int rate = 0;
    439  1.1   dyoung 
    440  1.1   dyoung 	size_bin = size_to_bin(frame_size);
    441  1.1   dyoung 	size = bin_to_size(size_bin);
    442  1.1   dyoung 	rate = sn->rates[ndx0].rate;
    443  1.1   dyoung 
    444  1.1   dyoung 	tt += calc_usecs_unicast_packet(sc, size, sn->rates[ndx0].rix,
    445  1.1   dyoung 					short_tries-1,
    446  1.1   dyoung 					MIN(tries0, tries) - 1);
    447  1.1   dyoung 	tries_so_far += tries0;
    448  1.1   dyoung 	if (tries1 && tries0 < tries) {
    449  1.1   dyoung 		tt += calc_usecs_unicast_packet(sc, size, sn->rates[ndx1].rix,
    450  1.1   dyoung 						short_tries-1,
    451  1.1   dyoung 						MIN(tries1 + tries_so_far, tries) - tries_so_far - 1);
    452  1.1   dyoung 	}
    453  1.1   dyoung 	tries_so_far += tries1;
    454  1.1   dyoung 
    455  1.1   dyoung 	if (tries2 && tries0 + tries1 < tries) {
    456  1.1   dyoung 		tt += calc_usecs_unicast_packet(sc, size, sn->rates[ndx2].rix,
    457  1.1   dyoung 					       short_tries-1,
    458  1.1   dyoung 						MIN(tries2 + tries_so_far, tries) - tries_so_far - 1);
    459  1.1   dyoung 	}
    460  1.1   dyoung 
    461  1.1   dyoung 	tries_so_far += tries2;
    462  1.1   dyoung 
    463  1.1   dyoung 	if (tries3 && tries0 + tries1 + tries2 < tries) {
    464  1.1   dyoung 		tt += calc_usecs_unicast_packet(sc, size, sn->rates[ndx3].rix,
    465  1.1   dyoung 						short_tries-1,
    466  1.1   dyoung 						MIN(tries3 + tries_so_far, tries) - tries_so_far - 1);
    467  1.1   dyoung 	}
    468  1.1   dyoung #ifdef SAMPLE_DEBUG
    469  1.1   dyoung 	if (short_tries + tries > 3 || status) {
    470  1.1   dyoung 		DPRINTF(sc, "%s: %s size %d rate %d ndx %d tries (%d/%d) tries0 %d tt %d avg_tt %d perfect_tt %d status %d\n",
    471  1.1   dyoung 			__func__, ether_sprintf(an->an_node.ni_macaddr),
    472  1.1   dyoung 			size,
    473  1.1   dyoung 			rate, ndx0, short_tries, tries, tries0, tt,
    474  1.1   dyoung 			sn->stats[size_bin][ndx0].average_tx_time,
    475  1.1   dyoung 			sn->stats[size_bin][ndx0].perfect_tx_time,
    476  1.1   dyoung 			status);
    477  1.1   dyoung 	}
    478  1.1   dyoung #endif /* SAMPLE_DEBUG */
    479  1.1   dyoung 	if (sn->stats[size_bin][ndx0].total_packets < (100 / (100 - ssc->ath_smoothing_rate))) {
    480  1.1   dyoung 		/* just average the first few packets */
    481  1.1   dyoung 		int avg_tx = sn->stats[size_bin][ndx0].average_tx_time;
    482  1.1   dyoung 		int packets = sn->stats[size_bin][ndx0].total_packets;
    483  1.1   dyoung 		sn->stats[size_bin][ndx0].average_tx_time = (tt+(avg_tx*packets))/(packets+1);
    484  1.1   dyoung 	} else {
    485  1.1   dyoung 		/* use a ewma */
    486  1.1   dyoung 		sn->stats[size_bin][ndx0].average_tx_time =
    487  1.1   dyoung 			((sn->stats[size_bin][ndx0].average_tx_time * ssc->ath_smoothing_rate) +
    488  1.1   dyoung 			 (tt * (100 - ssc->ath_smoothing_rate))) / 100;
    489  1.1   dyoung 	}
    490  1.1   dyoung 
    491  1.1   dyoung 	if (status) {
    492  1.1   dyoung 		/*
    493  1.1   dyoung 		 * this packet failed - count this as a failure
    494  1.1   dyoung 		 * for larger packets also, since we assume
    495  1.1   dyoung 		 * if a small packet fails at a lower bit-rate
    496  1.1   dyoung 		 * then a larger one will also.
    497  1.1   dyoung 		 */
    498  1.1   dyoung 		int y;
    499  1.1   dyoung 		for (y = size_bin; y < NUM_PACKET_SIZE_BINS; y++) {
    500  1.1   dyoung 			sn->stats[y][ndx0].successive_failures++;
    501  1.1   dyoung 			sn->stats[y][ndx0].last_tx = ticks;
    502  1.1   dyoung 		}
    503  1.1   dyoung 	} else {
    504  1.1   dyoung 		sn->stats[size_bin][ndx0].packets_acked++;
    505  1.1   dyoung 		sn->stats[size_bin][ndx0].successive_failures = 0;
    506  1.1   dyoung 	}
    507  1.1   dyoung 	sn->stats[size_bin][ndx0].tries += tries;
    508  1.1   dyoung 	sn->stats[size_bin][ndx0].last_tx = ticks;
    509  1.1   dyoung 	sn->stats[size_bin][ndx0].total_packets++;
    510  1.1   dyoung 
    511  1.1   dyoung 
    512  1.1   dyoung 	if (ndx0 == sn->current_sample_ndx[size_bin]) {
    513  1.1   dyoung 		DPRINTF(sc, "%s: %s size %d sample rate %d tries (%d/%d) tt %d avg_tt (%d/%d) status %d\n",
    514  1.1   dyoung 			__func__, ether_sprintf(an->an_node.ni_macaddr),
    515  1.1   dyoung 			size, rate, short_tries, tries, tt,
    516  1.1   dyoung 			sn->stats[size_bin][ndx0].average_tx_time,
    517  1.1   dyoung 			sn->stats[size_bin][ndx0].perfect_tx_time,
    518  1.1   dyoung 			status);
    519  1.1   dyoung 		sn->sample_tt[size_bin] = tt;
    520  1.1   dyoung 		sn->current_sample_ndx[size_bin] = -1;
    521  1.1   dyoung 	}
    522  1.1   dyoung }
    523  1.1   dyoung 
    524  1.1   dyoung void
    525  1.1   dyoung ath_rate_tx_complete(struct ath_softc *sc, struct ath_node *an,
    526  1.1   dyoung 	const struct ath_desc *ds, const struct ath_desc *ds0)
    527  1.1   dyoung {
    528  1.1   dyoung 	struct sample_node *sn = ATH_NODE_SAMPLE(an);
    529  1.1   dyoung 	const struct ar5212_desc *ads = (const struct ar5212_desc *)&ds->ds_ctl0;
    530  1.1   dyoung 	int final_rate, short_tries, long_tries, frame_size;
    531  1.1   dyoung 	int ndx = -1;
    532  1.1   dyoung 
    533  1.1   dyoung 	final_rate = sc->sc_hwmap[ds->ds_txstat.ts_rate &~ HAL_TXSTAT_ALTRATE].ieeerate;
    534  1.1   dyoung 	short_tries = ds->ds_txstat.ts_shortretry + 1;
    535  1.1   dyoung 	long_tries = ds->ds_txstat.ts_longretry + 1;
    536  1.1   dyoung 	frame_size = ds0->ds_ctl0 & 0x0fff; /* low-order 12 bits of ds_ctl0 */
    537  1.1   dyoung 	if (frame_size == 0)		    /* NB: should not happen */
    538  1.1   dyoung 		frame_size = 1500;
    539  1.1   dyoung 
    540  1.1   dyoung 	if (sn->num_rates <= 0) {
    541  1.1   dyoung 		DPRINTF(sc, "%s: %s size %d status %d rate/try %d/%d "
    542  1.1   dyoung 			"no rates yet\n",
    543  1.1   dyoung 			__func__, ether_sprintf(an->an_node.ni_macaddr),
    544  1.1   dyoung 			bin_to_size(size_to_bin(frame_size)),
    545  1.1   dyoung 			ds->ds_txstat.ts_status,
    546  1.1   dyoung 			short_tries, long_tries);
    547  1.1   dyoung 		return;
    548  1.1   dyoung 	}
    549  1.1   dyoung 
    550  1.1   dyoung 	if (sc->sc_mrretry && ds->ds_txstat.ts_status) {
    551  1.1   dyoung 		/* this packet failed */
    552  1.1   dyoung 		DPRINTF(sc, "%s: %s size %d rate/try %d/%d %d/%d %d/%d %d/%d status %s retries (%d/%d)\n",
    553  1.1   dyoung 			__func__,
    554  1.1   dyoung 			ether_sprintf(an->an_node.ni_macaddr),
    555  1.1   dyoung 			bin_to_size(size_to_bin(frame_size)),
    556  1.1   dyoung 			sc->sc_hwmap[ads->xmit_rate0].ieeerate,
    557  1.1   dyoung 				ads->xmit_tries0,
    558  1.1   dyoung 			sc->sc_hwmap[ads->xmit_rate1].ieeerate,
    559  1.1   dyoung 				ads->xmit_tries1,
    560  1.1   dyoung 			sc->sc_hwmap[ads->xmit_rate2].ieeerate,
    561  1.1   dyoung 				ads->xmit_tries2,
    562  1.1   dyoung 			sc->sc_hwmap[ads->xmit_rate3].ieeerate,
    563  1.1   dyoung 				ads->xmit_tries3,
    564  1.1   dyoung 			ds->ds_txstat.ts_status ? "FAIL" : "OK",
    565  1.1   dyoung 			short_tries,
    566  1.1   dyoung 			long_tries);
    567  1.1   dyoung 	}
    568  1.1   dyoung 
    569  1.1   dyoung 	if (!(ds->ds_txstat.ts_rate & HAL_TXSTAT_ALTRATE)) {
    570  1.1   dyoung 		/* only one rate was used */
    571  1.1   dyoung 		ndx = rate_to_ndx(sn, final_rate);
    572  1.1   dyoung 		DPRINTF(sc, "%s: %s size %d status %d rate/try %d/%d/%d\n",
    573  1.1   dyoung 			__func__, ether_sprintf(an->an_node.ni_macaddr),
    574  1.1   dyoung 			bin_to_size(size_to_bin(frame_size)),
    575  1.1   dyoung 			ds->ds_txstat.ts_status,
    576  1.1   dyoung 			ndx, short_tries, long_tries);
    577  1.1   dyoung 		if (ndx >= 0 && ndx < sn->num_rates) {
    578  1.1   dyoung 			update_stats(sc, an, frame_size,
    579  1.1   dyoung 				     ndx, long_tries,
    580  1.1   dyoung 				     0, 0,
    581  1.1   dyoung 				     0, 0,
    582  1.1   dyoung 				     0, 0,
    583  1.1   dyoung 				     short_tries, long_tries, ds->ds_txstat.ts_status);
    584  1.1   dyoung 		}
    585  1.1   dyoung 	} else {
    586  1.1   dyoung 		int rate0, tries0, ndx0;
    587  1.1   dyoung 		int rate1, tries1, ndx1;
    588  1.1   dyoung 		int rate2, tries2, ndx2;
    589  1.1   dyoung 		int rate3, tries3, ndx3;
    590  1.1   dyoung 		int finalTSIdx = ads->final_ts_index;
    591  1.1   dyoung 
    592  1.1   dyoung 		/*
    593  1.1   dyoung 		 * Process intermediate rates that failed.
    594  1.1   dyoung 		 */
    595  1.1   dyoung 
    596  1.1   dyoung 		rate0 = sc->sc_hwmap[ads->xmit_rate0].ieeerate;
    597  1.1   dyoung 		tries0 = ads->xmit_tries0;
    598  1.1   dyoung 		ndx0 = rate_to_ndx(sn, rate0);
    599  1.1   dyoung 
    600  1.1   dyoung 		rate1 = sc->sc_hwmap[ads->xmit_rate1].ieeerate;
    601  1.1   dyoung 		tries1 = ads->xmit_tries1;
    602  1.1   dyoung 		ndx1 = rate_to_ndx(sn, rate1);
    603  1.1   dyoung 
    604  1.1   dyoung 		rate2 = sc->sc_hwmap[ads->xmit_rate2].ieeerate;
    605  1.1   dyoung 		tries2 = ads->xmit_tries2;
    606  1.1   dyoung 		ndx2 = rate_to_ndx(sn, rate2);
    607  1.1   dyoung 
    608  1.1   dyoung 		rate3 = sc->sc_hwmap[ads->xmit_rate3].ieeerate;
    609  1.1   dyoung 		tries3 = ads->xmit_tries3;
    610  1.1   dyoung 		ndx3 = rate_to_ndx(sn, rate3);
    611  1.1   dyoung 
    612  1.1   dyoung #if 1
    613  1.1   dyoung 		DPRINTF(sc, "%s: %s size %d finaltsidx %d tries %d status %d rate/try %d/%d %d/%d %d/%d %d/%d\n",
    614  1.1   dyoung 			__func__, ether_sprintf(an->an_node.ni_macaddr),
    615  1.1   dyoung 			bin_to_size(size_to_bin(frame_size)),
    616  1.1   dyoung 			finalTSIdx,
    617  1.1   dyoung 			long_tries,
    618  1.1   dyoung 			ds->ds_txstat.ts_status,
    619  1.1   dyoung 			rate0, tries0,
    620  1.1   dyoung 			rate1, tries1,
    621  1.1   dyoung 			rate2, tries2,
    622  1.1   dyoung 			rate3, tries3);
    623  1.1   dyoung #endif
    624  1.1   dyoung 
    625  1.1   dyoung 		if (tries0) {
    626  1.1   dyoung 			update_stats(sc, an, frame_size,
    627  1.1   dyoung 				     ndx0, tries0,
    628  1.1   dyoung 				     ndx1, tries1,
    629  1.1   dyoung 				     ndx2, tries2,
    630  1.1   dyoung 				     ndx3, tries3,
    631  1.1   dyoung 				     short_tries, ds->ds_txstat.ts_longretry + 1,
    632  1.1   dyoung 				     ds->ds_txstat.ts_status);
    633  1.1   dyoung 		}
    634  1.1   dyoung 
    635  1.1   dyoung 		if (tries1 && finalTSIdx > 0) {
    636  1.1   dyoung 			update_stats(sc, an, frame_size,
    637  1.1   dyoung 				     ndx1, tries1,
    638  1.1   dyoung 				     ndx2, tries2,
    639  1.1   dyoung 				     ndx3, tries3,
    640  1.1   dyoung 				     0, 0,
    641  1.1   dyoung 				     short_tries, ds->ds_txstat.ts_longretry + 1 - tries0,
    642  1.1   dyoung 				     ds->ds_txstat.ts_status);
    643  1.1   dyoung 		}
    644  1.1   dyoung 
    645  1.1   dyoung 		if (tries2 && finalTSIdx > 1) {
    646  1.1   dyoung 			update_stats(sc, an, frame_size,
    647  1.1   dyoung 				     ndx2, tries2,
    648  1.1   dyoung 				     ndx3, tries3,
    649  1.1   dyoung 				     0, 0,
    650  1.1   dyoung 				     0, 0,
    651  1.1   dyoung 				     short_tries, ds->ds_txstat.ts_longretry + 1 - tries0 - tries1,
    652  1.1   dyoung 				     ds->ds_txstat.ts_status);
    653  1.1   dyoung 		}
    654  1.1   dyoung 
    655  1.1   dyoung 		if (tries3 && finalTSIdx > 2) {
    656  1.1   dyoung 			update_stats(sc, an, frame_size,
    657  1.1   dyoung 				     ndx3, tries3,
    658  1.1   dyoung 				     0, 0,
    659  1.1   dyoung 				     0, 0,
    660  1.1   dyoung 				     0, 0,
    661  1.1   dyoung 				     short_tries, ds->ds_txstat.ts_longretry + 1 - tries0 - tries1 - tries2,
    662  1.1   dyoung 				     ds->ds_txstat.ts_status);
    663  1.1   dyoung 		}
    664  1.1   dyoung 	}
    665  1.1   dyoung }
    666  1.1   dyoung 
    667  1.1   dyoung void
    668  1.1   dyoung ath_rate_newassoc(struct ath_softc *sc, struct ath_node *an, int isnew)
    669  1.1   dyoung {
    670  1.1   dyoung 	DPRINTF(sc, "%s: %s isnew %d\n", __func__,
    671  1.1   dyoung 		ether_sprintf(an->an_node.ni_macaddr), isnew);
    672  1.1   dyoung 	if (isnew)
    673  1.1   dyoung 		ath_rate_ctl_reset(sc, &an->an_node);
    674  1.1   dyoung }
    675  1.1   dyoung 
    676  1.1   dyoung /*
    677  1.1   dyoung  * Initialize the tables for a node.
    678  1.1   dyoung  */
    679  1.1   dyoung static void
    680  1.1   dyoung ath_rate_ctl_reset(struct ath_softc *sc, struct ieee80211_node *ni)
    681  1.1   dyoung {
    682  1.1   dyoung #define	RATE(_ix)	(ni->ni_rates.rs_rates[(_ix)] & IEEE80211_RATE_VAL)
    683  1.1   dyoung 	struct ieee80211com *ic = &sc->sc_ic;
    684  1.1   dyoung 	struct ath_node *an = ATH_NODE(ni);
    685  1.1   dyoung 	struct sample_node *sn = ATH_NODE_SAMPLE(an);
    686  1.1   dyoung 	const HAL_RATE_TABLE *rt = sc->sc_currates;
    687  1.1   dyoung 	int x, y, srate;
    688  1.1   dyoung 
    689  1.1   dyoung 	KASSERT(rt != NULL, ("no rate table, mode %u", sc->sc_curmode));
    690  1.1   dyoung         sn->static_rate_ndx = -1;
    691  1.5    skrll 	if (ic->ic_fixed_rate != IEEE80211_FIXED_RATE_NONE) {
    692  1.1   dyoung 		/*
    693  1.1   dyoung 		 * A fixed rate is to be used; ic_fixed_rate is an
    694  1.1   dyoung 		 * index into the supported rate set.  Convert this
    695  1.1   dyoung 		 * to the index into the negotiated rate set for
    696  1.1   dyoung 		 * the node.  We know the rate is there because the
    697  1.1   dyoung 		 * rate set is checked when the station associates.
    698  1.1   dyoung 		 */
    699  1.1   dyoung 		const struct ieee80211_rateset *rs =
    700  1.1   dyoung 			&ic->ic_sup_rates[ic->ic_curmode];
    701  1.1   dyoung 		int r = rs->rs_rates[ic->ic_fixed_rate] & IEEE80211_RATE_VAL;
    702  1.1   dyoung 		/* NB: the rate set is assumed sorted */
    703  1.1   dyoung 		srate = ni->ni_rates.rs_nrates - 1;
    704  1.1   dyoung 		for (; srate >= 0 && RATE(srate) != r; srate--)
    705  1.1   dyoung 			;
    706  1.1   dyoung 		KASSERT(srate >= 0,
    707  1.1   dyoung 			("fixed rate %d not in rate set", ic->ic_fixed_rate));
    708  1.1   dyoung                 sn->static_rate_ndx = srate;
    709  1.1   dyoung 	}
    710  1.1   dyoung 
    711  1.1   dyoung         DPRINTF(sc, "%s: %s size 1600 rate/tt", __func__, ether_sprintf(ni->ni_macaddr));
    712  1.1   dyoung 
    713  1.1   dyoung 	sn->num_rates = ni->ni_rates.rs_nrates;
    714  1.1   dyoung         for (x = 0; x < ni->ni_rates.rs_nrates; x++) {
    715  1.1   dyoung 		sn->rates[x].rate = ni->ni_rates.rs_rates[x] & IEEE80211_RATE_VAL;
    716  1.1   dyoung 		sn->rates[x].rix = sc->sc_rixmap[sn->rates[x].rate];
    717  1.1   dyoung 		sn->rates[x].rateCode = rt->info[sn->rates[x].rix].rateCode;
    718  1.1   dyoung 		sn->rates[x].shortPreambleRateCode =
    719  1.1   dyoung 			rt->info[sn->rates[x].rix].rateCode |
    720  1.1   dyoung 			rt->info[sn->rates[x].rix].shortPreamble;
    721  1.1   dyoung 
    722  1.1   dyoung 		DPRINTF(sc, " %d/%d", sn->rates[x].rate,
    723  1.1   dyoung 			calc_usecs_unicast_packet(sc, 1600, sn->rates[x].rix,
    724  1.1   dyoung 						  0,0));
    725  1.1   dyoung 	}
    726  1.1   dyoung 	DPRINTF(sc, "%s\n", "");
    727  1.1   dyoung 
    728  1.1   dyoung 	/* set the visible bit-rate to the lowest one available */
    729  1.1   dyoung 	ni->ni_txrate = 0;
    730  1.1   dyoung 	sn->num_rates = ni->ni_rates.rs_nrates;
    731  1.1   dyoung 
    732  1.1   dyoung 	for (y = 0; y < NUM_PACKET_SIZE_BINS; y++) {
    733  1.1   dyoung 		int size = bin_to_size(y);
    734  1.1   dyoung 		sn->packets_sent[y] = 0;
    735  1.1   dyoung 		sn->current_sample_ndx[y] = -1;
    736  1.1   dyoung 		sn->last_sample_ndx[y] = 0;
    737  1.1   dyoung 
    738  1.1   dyoung 		for (x = 0; x < ni->ni_rates.rs_nrates; x++) {
    739  1.1   dyoung 			sn->stats[y][x].successive_failures = 0;
    740  1.1   dyoung 			sn->stats[y][x].tries = 0;
    741  1.1   dyoung 			sn->stats[y][x].total_packets = 0;
    742  1.1   dyoung 			sn->stats[y][x].packets_acked = 0;
    743  1.1   dyoung 			sn->stats[y][x].last_tx = 0;
    744  1.1   dyoung 
    745  1.1   dyoung 			sn->stats[y][x].perfect_tx_time =
    746  1.1   dyoung 				calc_usecs_unicast_packet(sc, size,
    747  1.1   dyoung 							  sn->rates[x].rix,
    748  1.1   dyoung 							  0, 0);
    749  1.1   dyoung 			sn->stats[y][x].average_tx_time = sn->stats[y][x].perfect_tx_time;
    750  1.1   dyoung 		}
    751  1.1   dyoung 	}
    752  1.1   dyoung #undef RATE
    753  1.1   dyoung }
    754  1.1   dyoung 
    755  1.1   dyoung static void
    756  1.1   dyoung rate_cb(void *arg, struct ieee80211_node *ni)
    757  1.1   dyoung {
    758  1.1   dyoung 	struct ath_softc *sc = arg;
    759  1.1   dyoung 
    760  1.1   dyoung 	ath_rate_newassoc(sc, ATH_NODE(ni), 1);
    761  1.1   dyoung }
    762  1.1   dyoung 
    763  1.1   dyoung /*
    764  1.1   dyoung  * Reset the rate control state for each 802.11 state transition.
    765  1.1   dyoung  */
    766  1.1   dyoung void
    767  1.1   dyoung ath_rate_newstate(struct ath_softc *sc, enum ieee80211_state state)
    768  1.1   dyoung {
    769  1.1   dyoung 	struct ieee80211com *ic = &sc->sc_ic;
    770  1.1   dyoung 
    771  1.1   dyoung 	if (state == IEEE80211_S_RUN) {
    772  1.1   dyoung 		if (ic->ic_opmode != IEEE80211_M_STA) {
    773  1.1   dyoung 			/*
    774  1.1   dyoung 			 * Sync rates for associated stations and neighbors.
    775  1.1   dyoung 			 */
    776  1.1   dyoung 			ieee80211_iterate_nodes(&ic->ic_sta, rate_cb, sc);
    777  1.1   dyoung 		}
    778  1.1   dyoung 		ath_rate_newassoc(sc, ATH_NODE(ic->ic_bss), 1);
    779  1.1   dyoung 	}
    780  1.1   dyoung }
    781  1.1   dyoung 
    782  1.1   dyoung static void
    783  1.1   dyoung ath_rate_sysctlattach(struct ath_softc *sc, struct sample_softc *osc)
    784  1.1   dyoung {
    785  1.3   dyoung 	int rc;
    786  1.3   dyoung 	struct sysctllog **log = &sc->sc_sysctllog;
    787  1.3   dyoung 	const struct sysctlnode *cnode, *rnode;
    788  1.3   dyoung 
    789  1.3   dyoung 	if ((rnode = ath_sysctl_instance(sc->sc_dev.dv_xname, log)) == NULL)
    790  1.3   dyoung 		return;
    791  1.1   dyoung 
    792  1.1   dyoung 	/* XXX bounds check [0..100] */
    793  1.3   dyoung 	if ((rc = SYSCTL_PFX_INT(osc->ath_, CTLFLAG_READWRITE, smoothing_rate,
    794  1.3   dyoung 	    "rate control: retry threshold to credit rate raise (%%)")) != 0)
    795  1.3   dyoung 		goto err;
    796  1.3   dyoung 
    797  1.1   dyoung 	/* XXX bounds check [2..100] */
    798  1.3   dyoung 	if ((rc = SYSCTL_PFX_INT(osc->ath_, CTLFLAG_READWRITE, sample_rate,
    799  1.3   dyoung 	    "rate control: # good periods before raising rate")) != 0)
    800  1.3   dyoung 		goto err;
    801  1.3   dyoung 
    802  1.3   dyoung 	return;
    803  1.3   dyoung err:
    804  1.3   dyoung 	printf("%s: sysctl_createv failed, rc = %d\n", __func__, rc);
    805  1.1   dyoung }
    806  1.1   dyoung 
    807  1.1   dyoung struct ath_ratectrl *
    808  1.1   dyoung ath_rate_attach(struct ath_softc *sc)
    809  1.1   dyoung {
    810  1.1   dyoung 	struct sample_softc *osc;
    811  1.1   dyoung 
    812  1.1   dyoung 	DPRINTF(sc, "%s:\n", __func__);
    813  1.1   dyoung 	osc = malloc(sizeof(struct sample_softc), M_DEVBUF, M_NOWAIT|M_ZERO);
    814  1.1   dyoung 	if (osc == NULL)
    815  1.1   dyoung 		return NULL;
    816  1.1   dyoung 	osc->arc.arc_space = sizeof(struct sample_node);
    817  1.1   dyoung 	osc->ath_smoothing_rate = 95;	/* ewma percentage (out of 100) */
    818  1.1   dyoung 	osc->ath_sample_rate = 10;	/* send a different bit-rate 1/X packets */
    819  1.1   dyoung 	ath_rate_sysctlattach(sc, osc);
    820  1.1   dyoung 	return &osc->arc;
    821  1.1   dyoung }
    822  1.1   dyoung 
    823  1.1   dyoung void
    824  1.1   dyoung ath_rate_detach(struct ath_ratectrl *arc)
    825  1.1   dyoung {
    826  1.1   dyoung 	struct sample_softc *osc = (struct sample_softc *) arc;
    827  1.1   dyoung 
    828  1.1   dyoung 	free(osc, M_DEVBUF);
    829  1.1   dyoung }
    830