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