1 /* 2 * Copyright 2008 Sun Microsystems, Inc. All rights reserved. 3 * Use is subject to license terms. 4 */ 5 6 /* 7 * Copyright (c) 2002-2004 Sam Leffler, Errno Consulting 8 * All rights reserved. 9 * 10 * Redistribution and use in source and binary forms, with or without 11 * modification, are permitted provided that the following conditions 12 * are met: 13 * 1. Redistributions of source code must retain the above copyright 14 * notice, this list of conditions and the following disclaimer, 15 * without modification. 16 * 2. Redistributions in binary form must reproduce at minimum a disclaimer 17 * similar to the "NO WARRANTY" disclaimer below ("Disclaimer") and any 18 * redistribution must be conditioned upon including a substantially 19 * similar Disclaimer requirement for further binary redistribution. 20 * 3. Neither the names of the above-listed copyright holders nor the names 21 * of any contributors may be used to endorse or promote products derived 22 * from this software without specific prior written permission. 23 * 24 * NO WARRANTY 25 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 26 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 27 * LIMITED TO, THE IMPLIED WARRANTIES OF NONINFRINGEMENT, MERCHANTIBILITY 28 * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL 29 * THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, 30 * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 31 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 32 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER 33 * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 34 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF 35 * THE POSSIBILITY OF SUCH DAMAGES. 36 */ 37 38 #pragma ident "%Z%%M% %I% %E% SMI" 39 40 #include <sys/param.h> 41 #include <sys/types.h> 42 #include <sys/signal.h> 43 #include <sys/stream.h> 44 #include <sys/termio.h> 45 #include <sys/errno.h> 46 #include <sys/file.h> 47 #include <sys/cmn_err.h> 48 #include <sys/stropts.h> 49 #include <sys/strsubr.h> 50 #include <sys/strtty.h> 51 #include <sys/kbio.h> 52 #include <sys/cred.h> 53 #include <sys/stat.h> 54 #include <sys/consdev.h> 55 #include <sys/kmem.h> 56 #include <sys/modctl.h> 57 #include <sys/ddi.h> 58 #include <sys/sunddi.h> 59 #include <sys/pci.h> 60 #include <sys/errno.h> 61 #include <sys/dlpi.h> 62 #include <sys/ethernet.h> 63 #include <sys/list.h> 64 #include <sys/byteorder.h> 65 #include <sys/strsun.h> 66 #include <inet/common.h> 67 #include <inet/nd.h> 68 #include <inet/mi.h> 69 #include <inet/wifi_ioctl.h> 70 #include "ath_hal.h" 71 #include "ath_impl.h" 72 #include "ath_rate.h" 73 74 void 75 ath_rate_update(ath_t *asc, struct ieee80211_node *in, int32_t rate) 76 { 77 struct ath_node *an = ATH_NODE(in); 78 const HAL_RATE_TABLE *rt = asc->asc_currates; 79 uint8_t rix; 80 81 in->in_txrate = rate; 82 /* management/control frames always go at the lowest speed */ 83 an->an_tx_mgtrate = rt->info[0].rateCode; 84 an->an_tx_mgtratesp = an->an_tx_mgtrate | rt->info[0].shortPreamble; 85 ATH_DEBUG((ATH_DBG_RATE, "ath: ath_rate_update(): " 86 "mgtrate=%d mgtratesp=%d\n", 87 an->an_tx_mgtrate, an->an_tx_mgtratesp)); 88 /* 89 * Before associating a node has no rate set setup 90 * so we can't calculate any transmit codes to use. 91 * This is ok since we should never be sending anything 92 * but management frames and those always go at the 93 * lowest hardware rate. 94 */ 95 if (in->in_rates.ir_nrates == 0) 96 goto done; 97 an->an_tx_rix0 = asc->asc_rixmap[ 98 in->in_rates.ir_rates[rate] & IEEE80211_RATE_VAL]; 99 an->an_tx_rate0 = rt->info[an->an_tx_rix0].rateCode; 100 an->an_tx_rate0sp = an->an_tx_rate0 | 101 rt->info[an->an_tx_rix0].shortPreamble; 102 if (asc->asc_mrretry) { 103 /* 104 * Hardware supports multi-rate retry; setup two 105 * step-down retry rates and make the lowest rate 106 * be the ``last chance''. We use 4, 2, 2, 2 tries 107 * respectively (4 is set here, the rest are fixed 108 * in the xmit routine). 109 */ 110 an->an_tx_try0 = 1 + 3; /* 4 tries at rate 0 */ 111 if (--rate >= 0) { 112 rix = asc->asc_rixmap[ 113 in->in_rates.ir_rates[rate]&IEEE80211_RATE_VAL]; 114 an->an_tx_rate1 = rt->info[rix].rateCode; 115 an->an_tx_rate1sp = an->an_tx_rate1 | 116 rt->info[rix].shortPreamble; 117 } else { 118 an->an_tx_rate1 = an->an_tx_rate1sp = 0; 119 } 120 if (--rate >= 0) { 121 rix = asc->asc_rixmap[ 122 in->in_rates.ir_rates[rate]&IEEE80211_RATE_VAL]; 123 an->an_tx_rate2 = rt->info[rix].rateCode; 124 an->an_tx_rate2sp = an->an_tx_rate2 | 125 rt->info[rix].shortPreamble; 126 } else { 127 an->an_tx_rate2 = an->an_tx_rate2sp = 0; 128 } 129 if (rate > 0) { 130 an->an_tx_rate3 = rt->info[0].rateCode; 131 an->an_tx_rate3sp = 132 an->an_tx_mgtrate | rt->info[0].shortPreamble; 133 } else { 134 an->an_tx_rate3 = an->an_tx_rate3sp = 0; 135 } 136 } else { 137 an->an_tx_try0 = ATH_TXMAXTRY; /* max tries at rate 0 */ 138 an->an_tx_rate1 = an->an_tx_rate1sp = 0; 139 an->an_tx_rate2 = an->an_tx_rate2sp = 0; 140 an->an_tx_rate3 = an->an_tx_rate3sp = 0; 141 } 142 done: 143 an->an_tx_ok = an->an_tx_err = an->an_tx_retr = an->an_tx_upper = 0; 144 } 145 146 147 /* 148 * Set the starting transmit rate for a node. 149 */ 150 void 151 ath_rate_ctl_start(ath_t *asc, struct ieee80211_node *in) 152 { 153 ieee80211com_t *ic = (ieee80211com_t *)asc; 154 int32_t srate; 155 156 if (ic->ic_fixed_rate == IEEE80211_FIXED_RATE_NONE) { 157 /* 158 * No fixed rate is requested. For 11b start with 159 * the highest negotiated rate; otherwise, for 11g 160 * and 11a, we start "in the middle" at 24Mb or 36Mb. 161 */ 162 srate = in->in_rates.ir_nrates - 1; 163 if (asc->asc_curmode != IEEE80211_MODE_11B) { 164 /* 165 * Scan the negotiated rate set to find the 166 * closest rate. 167 */ 168 /* NB: the rate set is assumed sorted */ 169 for (; srate >= 0 && IEEE80211_RATE(srate) > 72; 170 srate--) {} 171 } 172 } else { 173 /* 174 * A fixed rate is to be used; We know the rate is 175 * there because the rate set is checked when the 176 * station associates. 177 */ 178 /* NB: the rate set is assumed sorted */ 179 srate = in->in_rates.ir_nrates - 1; 180 for (; srate >= 0 && IEEE80211_RATE(srate) != ic->ic_fixed_rate; 181 srate--) {} 182 } 183 ATH_DEBUG((ATH_DBG_RATE, "ath: ath_rate_ctl_start(): " 184 "srate=%d rate=%d\n", srate, IEEE80211_RATE(srate))); 185 ath_rate_update(asc, in, srate); 186 } 187 188 void 189 ath_rate_cb(void *arg, struct ieee80211_node *in) 190 { 191 ath_rate_update((ath_t *)arg, in, 0); 192 } 193 194 /* 195 * Reset the rate control state for each 802.11 state transition. 196 */ 197 void 198 ath_rate_ctl_reset(ath_t *asc, enum ieee80211_state state) 199 { 200 ieee80211com_t *ic = (ieee80211com_t *)asc; 201 struct ieee80211_node *in; 202 203 if (ic->ic_opmode == IEEE80211_M_STA) { 204 /* 205 * Reset local xmit state; this is really only 206 * meaningful when operating in station mode. 207 */ 208 in = (struct ieee80211_node *)ic->ic_bss; 209 if (state == IEEE80211_S_RUN) { 210 ath_rate_ctl_start(asc, in); 211 } else { 212 ath_rate_update(asc, in, 0); 213 } 214 } else { 215 /* 216 * When operating as a station the node table holds 217 * the AP's that were discovered during scanning. 218 * For any other operating mode we want to reset the 219 * tx rate state of each node. 220 */ 221 ieee80211_iterate_nodes(&ic->ic_sta, ath_rate_cb, asc); 222 ath_rate_update(asc, ic->ic_bss, 0); 223 } 224 } 225 226 227 /* 228 * Examine and potentially adjust the transmit rate. 229 */ 230 void 231 ath_rate_ctl(ieee80211com_t *isc, struct ieee80211_node *in) 232 { 233 ath_t *asc = (ath_t *)isc; 234 struct ath_node *an = ATH_NODE(in); 235 struct ieee80211_rateset *rs = &in->in_rates; 236 int32_t mod = 0, nrate, enough; 237 238 /* 239 * Rate control(very primitive version). 240 */ 241 asc->asc_stats.ast_rate_calls++; 242 243 enough = (an->an_tx_ok + an->an_tx_err >= 10); 244 245 /* no packet reached -> down */ 246 if (an->an_tx_err > 0 && an->an_tx_ok == 0) 247 mod = -1; 248 249 /* all packets needs retry in average -> down */ 250 if (enough && an->an_tx_ok < an->an_tx_retr) 251 mod = -1; 252 253 /* no error and less than 10% of packets needs retry -> up */ 254 if (enough && an->an_tx_err == 0 && an->an_tx_ok > an->an_tx_retr * 10) 255 mod = 1; 256 257 nrate = in->in_txrate; 258 switch (mod) { 259 case 0: 260 if (enough && an->an_tx_upper > 0) 261 an->an_tx_upper--; 262 break; 263 case -1: 264 if (nrate > 0) { 265 nrate--; 266 asc->asc_stats.ast_rate_drop++; 267 } 268 an->an_tx_upper = 0; 269 break; 270 case 1: 271 if (++an->an_tx_upper < 10) 272 break; 273 an->an_tx_upper = 0; 274 if (nrate + 1 < rs->ir_nrates) { 275 nrate++; 276 asc->asc_stats.ast_rate_raise++; 277 } 278 break; 279 } 280 281 if (nrate != in->in_txrate) { 282 ATH_DEBUG((ATH_DBG_RATE, "ath: ath_rate_ctl(): %dM -> %dM " 283 "(%d ok, %d err, %d retr)\n", 284 (rs->ir_rates[in->in_txrate] & IEEE80211_RATE_VAL) / 2, 285 (rs->ir_rates[nrate] & IEEE80211_RATE_VAL) / 2, 286 an->an_tx_ok, an->an_tx_err, an->an_tx_retr)); 287 ath_rate_update(asc, in, nrate); 288 } else if (enough) 289 an->an_tx_ok = an->an_tx_err = an->an_tx_retr = 0; 290 } 291 292 293 /* 294 * Read rate table from the HAL, and then 295 * copy the table to the driver's data structure. 296 */ 297 void 298 ath_rate_setup(ath_t *asc, uint32_t mode) 299 { 300 int32_t i; 301 uint8_t maxrates; 302 struct ieee80211_rateset *rs; 303 struct ath_hal *ah = asc->asc_ah; 304 ieee80211com_t *ic = (ieee80211com_t *)asc; 305 const HAL_RATE_TABLE *rt; 306 307 switch (mode) { 308 case IEEE80211_MODE_11A: 309 asc->asc_rates[mode] = ATH_HAL_GETRATETABLE(ah, HAL_MODE_11A); 310 break; 311 case IEEE80211_MODE_11B: 312 asc->asc_rates[mode] = ATH_HAL_GETRATETABLE(ah, HAL_MODE_11B); 313 break; 314 case IEEE80211_MODE_11G: 315 asc->asc_rates[mode] = ATH_HAL_GETRATETABLE(ah, HAL_MODE_11G); 316 break; 317 case IEEE80211_MODE_TURBO_A: 318 asc->asc_rates[mode] = ATH_HAL_GETRATETABLE(ah, HAL_MODE_TURBO); 319 break; 320 case IEEE80211_MODE_TURBO_G: 321 asc->asc_rates[mode] = ATH_HAL_GETRATETABLE(ah, HAL_MODE_108G); 322 break; 323 default: 324 ATH_DEBUG((ATH_DBG_RATE, "ath: ath_rate_setup(): " 325 "invalid mode %u\n", mode)); 326 return; 327 } 328 329 rt = asc->asc_rates[mode]; 330 if (rt == NULL) 331 return; 332 if (rt->rateCount > IEEE80211_RATE_MAXSIZE) { 333 ATH_DEBUG((ATH_DBG_RATE, "ath: ath_rate_setup(): " 334 "rate table too small (%u > %u)\n", 335 rt->rateCount, IEEE80211_RATE_MAXSIZE)); 336 maxrates = IEEE80211_RATE_MAXSIZE; 337 } else 338 maxrates = rt->rateCount; 339 rs = &ic->ic_sup_rates[mode]; 340 for (i = 0; i < maxrates; i++) 341 rs->ir_rates[i] = rt->info[i].dot11Rate; 342 rs->ir_nrates = maxrates; 343 } 344