7a1306a70fee0e017a445bde1dcfd1997f691cf4xc/*
ff3124eff995e6cd8ebd8c6543648e0670920034ff * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc * Use is subject to license terms.
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc */
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc/*
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc * Copyright (c) 2002-2004 Sam Leffler, Errno Consulting
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc * All rights reserved.
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc *
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc * Redistribution and use in source and binary forms, with or without
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc * modification, are permitted provided that the following conditions
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc * are met:
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc * 1. Redistributions of source code must retain the above copyright
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc * notice, this list of conditions and the following disclaimer,
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc * without modification.
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc * 2. Redistributions in binary form must reproduce at minimum a disclaimer
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc * similar to the "NO WARRANTY" disclaimer below ("Disclaimer") and any
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc * redistribution must be conditioned upon including a substantially
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc * similar Disclaimer requirement for further binary redistribution.
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc * 3. Neither the names of the above-listed copyright holders nor the names
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc * of any contributors may be used to endorse or promote products derived
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc * from this software without specific prior written permission.
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc *
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc * NO WARRANTY
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc * LIMITED TO, THE IMPLIED WARRANTIES OF NONINFRINGEMENT, MERCHANTIBILITY
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc * THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY,
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc * THE POSSIBILITY OF SUCH DAMAGES.
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc */
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc#include <sys/param.h>
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc#include <sys/types.h>
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc#include <sys/signal.h>
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc#include <sys/stream.h>
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc#include <sys/termio.h>
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc#include <sys/errno.h>
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc#include <sys/file.h>
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc#include <sys/cmn_err.h>
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc#include <sys/stropts.h>
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc#include <sys/strsubr.h>
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc#include <sys/strtty.h>
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc#include <sys/kbio.h>
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc#include <sys/cred.h>
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc#include <sys/stat.h>
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc#include <sys/consdev.h>
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc#include <sys/kmem.h>
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc#include <sys/modctl.h>
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc#include <sys/ddi.h>
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc#include <sys/sunddi.h>
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc#include <sys/pci.h>
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc#include <sys/errno.h>
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc#include <sys/dlpi.h>
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc#include <sys/ethernet.h>
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc#include <sys/list.h>
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc#include <sys/byteorder.h>
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc#include <sys/strsun.h>
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc#include <inet/common.h>
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc#include <inet/nd.h>
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc#include <inet/mi.h>
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc#include <inet/wifi_ioctl.h>
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc#include "ath_hal.h"
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc#include "ath_impl.h"
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc#include "ath_rate.h"
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc
7a1306a70fee0e017a445bde1dcfd1997f691cf4xcvoid
7a1306a70fee0e017a445bde1dcfd1997f691cf4xcath_rate_update(ath_t *asc, struct ieee80211_node *in, int32_t rate)
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc{
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc struct ath_node *an = ATH_NODE(in);
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc const HAL_RATE_TABLE *rt = asc->asc_currates;
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc uint8_t rix;
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc
129d67acdc2d029d3d6cff4022c0c26c81c76f89lin wang - Sun Microsystems - Beijing China ASSERT(rt != NULL);
129d67acdc2d029d3d6cff4022c0c26c81c76f89lin wang - Sun Microsystems - Beijing China
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc in->in_txrate = rate;
129d67acdc2d029d3d6cff4022c0c26c81c76f89lin wang - Sun Microsystems - Beijing China
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc /* management/control frames always go at the lowest speed */
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc an->an_tx_mgtrate = rt->info[0].rateCode;
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc an->an_tx_mgtratesp = an->an_tx_mgtrate | rt->info[0].shortPreamble;
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc ATH_DEBUG((ATH_DBG_RATE, "ath: ath_rate_update(): "
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc "mgtrate=%d mgtratesp=%d\n",
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc an->an_tx_mgtrate, an->an_tx_mgtratesp));
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc /*
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc * Before associating a node has no rate set setup
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc * so we can't calculate any transmit codes to use.
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc * This is ok since we should never be sending anything
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc * but management frames and those always go at the
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc * lowest hardware rate.
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc */
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc if (in->in_rates.ir_nrates == 0)
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc goto done;
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc an->an_tx_rix0 = asc->asc_rixmap[
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc in->in_rates.ir_rates[rate] & IEEE80211_RATE_VAL];
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc an->an_tx_rate0 = rt->info[an->an_tx_rix0].rateCode;
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc an->an_tx_rate0sp = an->an_tx_rate0 |
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc rt->info[an->an_tx_rix0].shortPreamble;
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc if (asc->asc_mrretry) {
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc /*
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc * Hardware supports multi-rate retry; setup two
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc * step-down retry rates and make the lowest rate
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc * be the ``last chance''. We use 4, 2, 2, 2 tries
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc * respectively (4 is set here, the rest are fixed
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc * in the xmit routine).
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc */
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc an->an_tx_try0 = 1 + 3; /* 4 tries at rate 0 */
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc if (--rate >= 0) {
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc rix = asc->asc_rixmap[
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc in->in_rates.ir_rates[rate]&IEEE80211_RATE_VAL];
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc an->an_tx_rate1 = rt->info[rix].rateCode;
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc an->an_tx_rate1sp = an->an_tx_rate1 |
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc rt->info[rix].shortPreamble;
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc } else {
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc an->an_tx_rate1 = an->an_tx_rate1sp = 0;
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc }
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc if (--rate >= 0) {
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc rix = asc->asc_rixmap[
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc in->in_rates.ir_rates[rate]&IEEE80211_RATE_VAL];
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc an->an_tx_rate2 = rt->info[rix].rateCode;
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc an->an_tx_rate2sp = an->an_tx_rate2 |
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc rt->info[rix].shortPreamble;
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc } else {
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc an->an_tx_rate2 = an->an_tx_rate2sp = 0;
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc }
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc if (rate > 0) {
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc an->an_tx_rate3 = rt->info[0].rateCode;
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc an->an_tx_rate3sp =
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc an->an_tx_mgtrate | rt->info[0].shortPreamble;
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc } else {
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc an->an_tx_rate3 = an->an_tx_rate3sp = 0;
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc }
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc } else {
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc an->an_tx_try0 = ATH_TXMAXTRY; /* max tries at rate 0 */
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc an->an_tx_rate1 = an->an_tx_rate1sp = 0;
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc an->an_tx_rate2 = an->an_tx_rate2sp = 0;
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc an->an_tx_rate3 = an->an_tx_rate3sp = 0;
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc }
7a1306a70fee0e017a445bde1dcfd1997f691cf4xcdone:
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc an->an_tx_ok = an->an_tx_err = an->an_tx_retr = an->an_tx_upper = 0;
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc}
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc/*
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc * Set the starting transmit rate for a node.
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc */
7a1306a70fee0e017a445bde1dcfd1997f691cf4xcvoid
7a1306a70fee0e017a445bde1dcfd1997f691cf4xcath_rate_ctl_start(ath_t *asc, struct ieee80211_node *in)
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc{
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc ieee80211com_t *ic = (ieee80211com_t *)asc;
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc int32_t srate;
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc if (ic->ic_fixed_rate == IEEE80211_FIXED_RATE_NONE) {
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc /*
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc * No fixed rate is requested. For 11b start with
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc * the highest negotiated rate; otherwise, for 11g
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc * and 11a, we start "in the middle" at 24Mb or 36Mb.
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc */
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc srate = in->in_rates.ir_nrates - 1;
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc if (asc->asc_curmode != IEEE80211_MODE_11B) {
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc /*
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc * Scan the negotiated rate set to find the
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc * closest rate.
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc */
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc /* NB: the rate set is assumed sorted */
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc for (; srate >= 0 && IEEE80211_RATE(srate) > 72;
ff3124eff995e6cd8ebd8c6543648e0670920034ff srate--) {}
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc }
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc } else {
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc /*
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc * A fixed rate is to be used; We know the rate is
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc * there because the rate set is checked when the
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc * station associates.
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc */
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc /* NB: the rate set is assumed sorted */
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc srate = in->in_rates.ir_nrates - 1;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc for (; srate >= 0 && IEEE80211_RATE(srate) != ic->ic_fixed_rate;
ff3124eff995e6cd8ebd8c6543648e0670920034ff srate--) {}
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc }
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc ATH_DEBUG((ATH_DBG_RATE, "ath: ath_rate_ctl_start(): "
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc "srate=%d rate=%d\n", srate, IEEE80211_RATE(srate)));
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc ath_rate_update(asc, in, srate);
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc}
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxcvoid
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxcath_rate_cb(void *arg, struct ieee80211_node *in)
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc{
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc ath_rate_update((ath_t *)arg, in, 0);
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc}
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc/*
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc * Reset the rate control state for each 802.11 state transition.
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc */
7a1306a70fee0e017a445bde1dcfd1997f691cf4xcvoid
7a1306a70fee0e017a445bde1dcfd1997f691cf4xcath_rate_ctl_reset(ath_t *asc, enum ieee80211_state state)
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc{
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc ieee80211com_t *ic = (ieee80211com_t *)asc;
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc struct ieee80211_node *in;
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc if (ic->ic_opmode == IEEE80211_M_STA) {
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc /*
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc * Reset local xmit state; this is really only
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc * meaningful when operating in station mode.
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc */
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc in = (struct ieee80211_node *)ic->ic_bss;
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc if (state == IEEE80211_S_RUN) {
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc ath_rate_ctl_start(asc, in);
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc } else {
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc ath_rate_update(asc, in, 0);
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc }
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc } else {
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc /*
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc * When operating as a station the node table holds
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc * the AP's that were discovered during scanning.
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc * For any other operating mode we want to reset the
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc * tx rate state of each node.
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc */
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc ieee80211_iterate_nodes(&ic->ic_sta, ath_rate_cb, asc);
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc ath_rate_update(asc, ic->ic_bss, 0);
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc }
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc}
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc/*
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc * Examine and potentially adjust the transmit rate.
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc */
7a1306a70fee0e017a445bde1dcfd1997f691cf4xcvoid
129d67acdc2d029d3d6cff4022c0c26c81c76f89lin wang - Sun Microsystems - Beijing Chinaath_rate_ctl(void *arg, struct ieee80211_node *in)
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc{
129d67acdc2d029d3d6cff4022c0c26c81c76f89lin wang - Sun Microsystems - Beijing China ath_t *asc = arg;
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc struct ath_node *an = ATH_NODE(in);
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc struct ieee80211_rateset *rs = &in->in_rates;
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc int32_t mod = 0, nrate, enough;
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc /*
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc * Rate control(very primitive version).
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc */
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc asc->asc_stats.ast_rate_calls++;
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc enough = (an->an_tx_ok + an->an_tx_err >= 10);
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc /* no packet reached -> down */
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc if (an->an_tx_err > 0 && an->an_tx_ok == 0)
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc mod = -1;
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc /* all packets needs retry in average -> down */
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc if (enough && an->an_tx_ok < an->an_tx_retr)
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc mod = -1;
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc /* no error and less than 10% of packets needs retry -> up */
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc if (enough && an->an_tx_err == 0 && an->an_tx_ok > an->an_tx_retr * 10)
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc mod = 1;
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc nrate = in->in_txrate;
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc switch (mod) {
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc case 0:
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc if (enough && an->an_tx_upper > 0)
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc an->an_tx_upper--;
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc break;
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc case -1:
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc if (nrate > 0) {
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc nrate--;
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc asc->asc_stats.ast_rate_drop++;
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc }
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc an->an_tx_upper = 0;
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc break;
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc case 1:
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc if (++an->an_tx_upper < 10)
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc break;
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc an->an_tx_upper = 0;
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc if (nrate + 1 < rs->ir_nrates) {
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc nrate++;
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc asc->asc_stats.ast_rate_raise++;
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc }
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc break;
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc }
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc if (nrate != in->in_txrate) {
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc ATH_DEBUG((ATH_DBG_RATE, "ath: ath_rate_ctl(): %dM -> %dM "
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc "(%d ok, %d err, %d retr)\n",
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc (rs->ir_rates[in->in_txrate] & IEEE80211_RATE_VAL) / 2,
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc (rs->ir_rates[nrate] & IEEE80211_RATE_VAL) / 2,
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc an->an_tx_ok, an->an_tx_err, an->an_tx_retr));
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc ath_rate_update(asc, in, nrate);
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc } else if (enough)
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc an->an_tx_ok = an->an_tx_err = an->an_tx_retr = 0;
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc}
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc/*
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc * Read rate table from the HAL, and then
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc * copy the table to the driver's data structure.
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc */
7a1306a70fee0e017a445bde1dcfd1997f691cf4xcvoid
7a1306a70fee0e017a445bde1dcfd1997f691cf4xcath_rate_setup(ath_t *asc, uint32_t mode)
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc{
ff3124eff995e6cd8ebd8c6543648e0670920034ff int32_t i;
ff3124eff995e6cd8ebd8c6543648e0670920034ff uint8_t maxrates;
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc struct ieee80211_rateset *rs;
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc struct ath_hal *ah = asc->asc_ah;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc ieee80211com_t *ic = (ieee80211com_t *)asc;
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc const HAL_RATE_TABLE *rt;
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc switch (mode) {
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc case IEEE80211_MODE_11A:
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc asc->asc_rates[mode] = ATH_HAL_GETRATETABLE(ah, HAL_MODE_11A);
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc break;
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc case IEEE80211_MODE_11B:
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc asc->asc_rates[mode] = ATH_HAL_GETRATETABLE(ah, HAL_MODE_11B);
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc break;
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc case IEEE80211_MODE_11G:
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc asc->asc_rates[mode] = ATH_HAL_GETRATETABLE(ah, HAL_MODE_11G);
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc break;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc case IEEE80211_MODE_TURBO_A:
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc asc->asc_rates[mode] = ATH_HAL_GETRATETABLE(ah, HAL_MODE_TURBO);
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc break;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc case IEEE80211_MODE_TURBO_G:
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc asc->asc_rates[mode] = ATH_HAL_GETRATETABLE(ah, HAL_MODE_108G);
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc break;
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc default:
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc ATH_DEBUG((ATH_DBG_RATE, "ath: ath_rate_setup(): "
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc "invalid mode %u\n", mode));
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc return;
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc }
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc rt = asc->asc_rates[mode];
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc if (rt == NULL)
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc return;
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc if (rt->rateCount > IEEE80211_RATE_MAXSIZE) {
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc ATH_DEBUG((ATH_DBG_RATE, "ath: ath_rate_setup(): "
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc "rate table too small (%u > %u)\n",
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc rt->rateCount, IEEE80211_RATE_MAXSIZE));
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc maxrates = IEEE80211_RATE_MAXSIZE;
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc } else
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc maxrates = rt->rateCount;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc rs = &ic->ic_sup_rates[mode];
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc for (i = 0; i < maxrates; i++)
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc rs->ir_rates[i] = rt->info[i].dot11Rate;
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc rs->ir_nrates = maxrates;
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc}