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 #include <sys/param.h> 39 #include <sys/types.h> 40 #include <sys/signal.h> 41 #include <sys/stream.h> 42 #include <sys/termio.h> 43 #include <sys/errno.h> 44 #include <sys/file.h> 45 #include <sys/cmn_err.h> 46 #include <sys/stropts.h> 47 #include <sys/strsubr.h> 48 #include <sys/strtty.h> 49 #include <sys/kbio.h> 50 #include <sys/cred.h> 51 #include <sys/stat.h> 52 #include <sys/consdev.h> 53 #include <sys/kmem.h> 54 #include <sys/modctl.h> 55 #include <sys/ddi.h> 56 #include <sys/sunddi.h> 57 #include <sys/pci.h> 58 #include <sys/errno.h> 59 #include <sys/dlpi.h> 60 #include <sys/ethernet.h> 61 #include <sys/list.h> 62 #include <sys/byteorder.h> 63 #include <sys/strsun.h> 64 #include <inet/common.h> 65 #include <inet/nd.h> 66 #include <inet/mi.h> 67 #include <inet/wifi_ioctl.h> 68 #include "ath_hal.h" 69 #include "ath_impl.h" 70 #include "ath_rate.h" 71 72 void 73 ath_rate_update(ath_t *asc, struct ieee80211_node *in, int32_t rate) 74 { 75 struct ath_node *an = ATH_NODE(in); 76 const HAL_RATE_TABLE *rt = asc->asc_currates; 77 uint8_t rix; 78 79 ASSERT(rt != NULL); 80 81 in->in_txrate = rate; 82 83 /* management/control frames always go at the lowest speed */ 84 an->an_tx_mgtrate = rt->info[0].rateCode; 85 an->an_tx_mgtratesp = an->an_tx_mgtrate | rt->info[0].shortPreamble; 86 ATH_DEBUG((ATH_DBG_RATE, "ath: ath_rate_update(): " 87 "mgtrate=%d mgtratesp=%d\n", 88 an->an_tx_mgtrate, an->an_tx_mgtratesp)); 89 /* 90 * Before associating a node has no rate set setup 91 * so we can't calculate any transmit codes to use. 92 * This is ok since we should never be sending anything 93 * but management frames and those always go at the 94 * lowest hardware rate. 95 */ 96 if (in->in_rates.ir_nrates == 0) 97 goto done; 98 an->an_tx_rix0 = asc->asc_rixmap[ 99 in->in_rates.ir_rates[rate] & IEEE80211_RATE_VAL]; 100 an->an_tx_rate0 = rt->info[an->an_tx_rix0].rateCode; 101 an->an_tx_rate0sp = an->an_tx_rate0 | 102 rt->info[an->an_tx_rix0].shortPreamble; 103 if (asc->asc_mrretry) { 104 /* 105 * Hardware supports multi-rate retry; setup two 106 * step-down retry rates and make the lowest rate 107 * be the ``last chance''. We use 4, 2, 2, 2 tries 108 * respectively (4 is set here, the rest are fixed 109 * in the xmit routine). 110 */ 111 an->an_tx_try0 = 1 + 3; /* 4 tries at rate 0 */ 112 if (--rate >= 0) { 113 rix = asc->asc_rixmap[ 114 in->in_rates.ir_rates[rate]&IEEE80211_RATE_VAL]; 115 an->an_tx_rate1 = rt->info[rix].rateCode; 116 an->an_tx_rate1sp = an->an_tx_rate1 | 117 rt->info[rix].shortPreamble; 118 } else { 119 an->an_tx_rate1 = an->an_tx_rate1sp = 0; 120 } 121 if (--rate >= 0) { 122 rix = asc->asc_rixmap[ 123 in->in_rates.ir_rates[rate]&IEEE80211_RATE_VAL]; 124 an->an_tx_rate2 = rt->info[rix].rateCode; 125 an->an_tx_rate2sp = an->an_tx_rate2 | 126 rt->info[rix].shortPreamble; 127 } else { 128 an->an_tx_rate2 = an->an_tx_rate2sp = 0; 129 } 130 if (rate > 0) { 131 an->an_tx_rate3 = rt->info[0].rateCode; 132 an->an_tx_rate3sp = 133 an->an_tx_mgtrate | rt->info[0].shortPreamble; 134 } else { 135 an->an_tx_rate3 = an->an_tx_rate3sp = 0; 136 } 137 } else { 138 an->an_tx_try0 = ATH_TXMAXTRY; /* max tries at rate 0 */ 139 an->an_tx_rate1 = an->an_tx_rate1sp = 0; 140 an->an_tx_rate2 = an->an_tx_rate2sp = 0; 141 an->an_tx_rate3 = an->an_tx_rate3sp = 0; 142 } 143 done: 144 an->an_tx_ok = an->an_tx_err = an->an_tx_retr = an->an_tx_upper = 0; 145 } 146 147 148 /* 149 * Set the starting transmit rate for a node. 150 */ 151 void 152 ath_rate_ctl_start(ath_t *asc, struct ieee80211_node *in) 153 { 154 ieee80211com_t *ic = (ieee80211com_t *)asc; 155 int32_t srate; 156 157 if (ic->ic_fixed_rate == IEEE80211_FIXED_RATE_NONE) { 158 /* 159 * No fixed rate is requested. For 11b start with 160 * the highest negotiated rate; otherwise, for 11g 161 * and 11a, we start "in the middle" at 24Mb or 36Mb. 162 */ 163 srate = in->in_rates.ir_nrates - 1; 164 if (asc->asc_curmode != IEEE80211_MODE_11B) { 165 /* 166 * Scan the negotiated rate set to find the 167 * closest rate. 168 */ 169 /* NB: the rate set is assumed sorted */ 170 for (; srate >= 0 && IEEE80211_RATE(srate) > 72; 171 srate--) {} 172 } 173 } else { 174 /* 175 * A fixed rate is to be used; We know the rate is 176 * there because the rate set is checked when the 177 * station associates. 178 */ 179 /* NB: the rate set is assumed sorted */ 180 srate = in->in_rates.ir_nrates - 1; 181 for (; srate >= 0 && IEEE80211_RATE(srate) != ic->ic_fixed_rate; 182 srate--) {} 183 } 184 ATH_DEBUG((ATH_DBG_RATE, "ath: ath_rate_ctl_start(): " 185 "srate=%d rate=%d\n", srate, IEEE80211_RATE(srate))); 186 ath_rate_update(asc, in, srate); 187 } 188 189 void 190 ath_rate_cb(void *arg, struct ieee80211_node *in) 191 { 192 ath_rate_update((ath_t *)arg, in, 0); 193 } 194 195 /* 196 * Reset the rate control state for each 802.11 state transition. 197 */ 198 void 199 ath_rate_ctl_reset(ath_t *asc, enum ieee80211_state state) 200 { 201 ieee80211com_t *ic = (ieee80211com_t *)asc; 202 struct ieee80211_node *in; 203 204 if (ic->ic_opmode == IEEE80211_M_STA) { 205 /* 206 * Reset local xmit state; this is really only 207 * meaningful when operating in station mode. 208 */ 209 in = (struct ieee80211_node *)ic->ic_bss; 210 if (state == IEEE80211_S_RUN) { 211 ath_rate_ctl_start(asc, in); 212 } else { 213 ath_rate_update(asc, in, 0); 214 } 215 } else { 216 /* 217 * When operating as a station the node table holds 218 * the AP's that were discovered during scanning. 219 * For any other operating mode we want to reset the 220 * tx rate state of each node. 221 */ 222 ieee80211_iterate_nodes(&ic->ic_sta, ath_rate_cb, asc); 223 ath_rate_update(asc, ic->ic_bss, 0); 224 } 225 } 226 227 228 /* 229 * Examine and potentially adjust the transmit rate. 230 */ 231 void 232 ath_rate_ctl(void *arg, struct ieee80211_node *in) 233 { 234 ath_t *asc = arg; 235 struct ath_node *an = ATH_NODE(in); 236 struct ieee80211_rateset *rs = &in->in_rates; 237 int32_t mod = 0, nrate, enough; 238 239 /* 240 * Rate control(very primitive version). 241 */ 242 asc->asc_stats.ast_rate_calls++; 243 244 enough = (an->an_tx_ok + an->an_tx_err >= 10); 245 246 /* no packet reached -> down */ 247 if (an->an_tx_err > 0 && an->an_tx_ok == 0) 248 mod = -1; 249 250 /* all packets needs retry in average -> down */ 251 if (enough && an->an_tx_ok < an->an_tx_retr) 252 mod = -1; 253 254 /* no error and less than 10% of packets needs retry -> up */ 255 if (enough && an->an_tx_err == 0 && an->an_tx_ok > an->an_tx_retr * 10) 256 mod = 1; 257 258 nrate = in->in_txrate; 259 switch (mod) { 260 case 0: 261 if (enough && an->an_tx_upper > 0) 262 an->an_tx_upper--; 263 break; 264 case -1: 265 if (nrate > 0) { 266 nrate--; 267 asc->asc_stats.ast_rate_drop++; 268 } 269 an->an_tx_upper = 0; 270 break; 271 case 1: 272 if (++an->an_tx_upper < 10) 273 break; 274 an->an_tx_upper = 0; 275 if (nrate + 1 < rs->ir_nrates) { 276 nrate++; 277 asc->asc_stats.ast_rate_raise++; 278 } 279 break; 280 } 281 282 if (nrate != in->in_txrate) { 283 ATH_DEBUG((ATH_DBG_RATE, "ath: ath_rate_ctl(): %dM -> %dM " 284 "(%d ok, %d err, %d retr)\n", 285 (rs->ir_rates[in->in_txrate] & IEEE80211_RATE_VAL) / 2, 286 (rs->ir_rates[nrate] & IEEE80211_RATE_VAL) / 2, 287 an->an_tx_ok, an->an_tx_err, an->an_tx_retr)); 288 ath_rate_update(asc, in, nrate); 289 } else if (enough) 290 an->an_tx_ok = an->an_tx_err = an->an_tx_retr = 0; 291 } 292 293 294 /* 295 * Read rate table from the HAL, and then 296 * copy the table to the driver's data structure. 297 */ 298 void 299 ath_rate_setup(ath_t *asc, uint32_t mode) 300 { 301 int32_t i; 302 uint8_t maxrates; 303 struct ieee80211_rateset *rs; 304 struct ath_hal *ah = asc->asc_ah; 305 ieee80211com_t *ic = (ieee80211com_t *)asc; 306 const HAL_RATE_TABLE *rt; 307 308 switch (mode) { 309 case IEEE80211_MODE_11A: 310 asc->asc_rates[mode] = ATH_HAL_GETRATETABLE(ah, HAL_MODE_11A); 311 break; 312 case IEEE80211_MODE_11B: 313 asc->asc_rates[mode] = ATH_HAL_GETRATETABLE(ah, HAL_MODE_11B); 314 break; 315 case IEEE80211_MODE_11G: 316 asc->asc_rates[mode] = ATH_HAL_GETRATETABLE(ah, HAL_MODE_11G); 317 break; 318 case IEEE80211_MODE_TURBO_A: 319 asc->asc_rates[mode] = ATH_HAL_GETRATETABLE(ah, HAL_MODE_TURBO); 320 break; 321 case IEEE80211_MODE_TURBO_G: 322 asc->asc_rates[mode] = ATH_HAL_GETRATETABLE(ah, HAL_MODE_108G); 323 break; 324 default: 325 ATH_DEBUG((ATH_DBG_RATE, "ath: ath_rate_setup(): " 326 "invalid mode %u\n", mode)); 327 return; 328 } 329 330 rt = asc->asc_rates[mode]; 331 if (rt == NULL) 332 return; 333 if (rt->rateCount > IEEE80211_RATE_MAXSIZE) { 334 ATH_DEBUG((ATH_DBG_RATE, "ath: ath_rate_setup(): " 335 "rate table too small (%u > %u)\n", 336 rt->rateCount, IEEE80211_RATE_MAXSIZE)); 337 maxrates = IEEE80211_RATE_MAXSIZE; 338 } else 339 maxrates = rt->rateCount; 340 rs = &ic->ic_sup_rates[mode]; 341 for (i = 0; i < maxrates; i++) 342 rs->ir_rates[i] = rt->info[i].dot11Rate; 343 rs->ir_nrates = maxrates; 344 } 345