1 /* 2 * Copyright 2005 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/gld.h> 62 #include <sys/dlpi.h> 63 #include <sys/ethernet.h> 64 #include <sys/list.h> 65 #include <sys/byteorder.h> 66 #include <sys/strsun.h> 67 #include <inet/common.h> 68 #include <inet/nd.h> 69 #include <inet/mi.h> 70 #include <inet/wifi_ioctl.h> 71 #include "ath_hal.h" 72 #include "ath_impl.h" 73 #include "ath_ieee80211.h" 74 75 void 76 ath_rate_update(ath_t *asc, struct ieee80211_node *in, int32_t rate) 77 { 78 struct ath_node *an = ATH_NODE(in); 79 const HAL_RATE_TABLE *rt = asc->asc_currates; 80 uint8_t rix; 81 82 in->in_txrate = rate; 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 *isc = (ieee80211com_t *)asc; 155 int32_t srate; 156 157 if (isc->isc_fixed_rate == -1) { 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; ic_fixed_rate is an 176 * index into the supported rate set. Convert this 177 * to the index into the negotiated rate set for 178 * the node. We know the rate is there because the 179 * rate set is checked when the station associates. 180 */ 181 const struct ieee80211_rateset *rs = 182 &isc->isc_sup_rates[isc->isc_curmode]; 183 int32_t r = rs->ir_rates[isc->isc_fixed_rate] & 184 IEEE80211_RATE_VAL; 185 /* NB: the rate set is assumed sorted */ 186 srate = in->in_rates.ir_nrates - 1; 187 for (; srate >= 0 && IEEE80211_RATE(srate) != r; srate--); 188 } 189 ATH_DEBUG((ATH_DBG_RATE, "ath: ath_rate_ctl_start(): " 190 "srate=%d rate=%d\n", srate, IEEE80211_RATE(srate))); 191 ath_rate_update(asc, in, srate); 192 } 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 *isc = (ieee80211com_t *)asc; 202 struct ieee80211_node *in; 203 204 if (isc->isc_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 *)isc->isc_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 in = list_head(&isc->isc_in_list); 223 while (in != NULL) { 224 ath_rate_update(asc, in, 0); 225 in = list_next(&isc->isc_in_list, in); 226 } 227 ath_rate_update(asc, isc->isc_bss, 0); 228 } 229 } 230 231 232 /* 233 * Examine and potentially adjust the transmit rate. 234 */ 235 void 236 ath_rate_ctl(ieee80211com_t *isc, struct ieee80211_node *in) 237 { 238 ath_t *asc = (ath_t *)isc; 239 struct ath_node *an = ATH_NODE(in); 240 struct ieee80211_rateset *rs = &in->in_rates; 241 int32_t mod = 0, nrate, enough; 242 243 /* 244 * Rate control(very primitive version). 245 */ 246 asc->asc_stats.ast_rate_calls++; 247 248 enough = (an->an_tx_ok + an->an_tx_err >= 10); 249 250 /* no packet reached -> down */ 251 if (an->an_tx_err > 0 && an->an_tx_ok == 0) 252 mod = -1; 253 254 /* all packets needs retry in average -> down */ 255 if (enough && an->an_tx_ok < an->an_tx_retr) 256 mod = -1; 257 258 /* no error and less than 10% of packets needs retry -> up */ 259 if (enough && an->an_tx_err == 0 && an->an_tx_ok > an->an_tx_retr * 10) 260 mod = 1; 261 262 nrate = in->in_txrate; 263 switch (mod) { 264 case 0: 265 if (enough && an->an_tx_upper > 0) 266 an->an_tx_upper--; 267 break; 268 case -1: 269 if (nrate > 0) { 270 nrate--; 271 asc->asc_stats.ast_rate_drop++; 272 } 273 an->an_tx_upper = 0; 274 break; 275 case 1: 276 if (++an->an_tx_upper < 10) 277 break; 278 an->an_tx_upper = 0; 279 if (nrate + 1 < rs->ir_nrates) { 280 nrate++; 281 asc->asc_stats.ast_rate_raise++; 282 } 283 break; 284 } 285 286 if (nrate != in->in_txrate) { 287 ATH_DEBUG((ATH_DBG_RATE, "ath: ath_rate_ctl(): %dM -> %dM " 288 "(%d ok, %d err, %d retr)\n", 289 (rs->ir_rates[in->in_txrate] & IEEE80211_RATE_VAL) / 2, 290 (rs->ir_rates[nrate] & IEEE80211_RATE_VAL) / 2, 291 an->an_tx_ok, an->an_tx_err, an->an_tx_retr)); 292 ath_rate_update(asc, in, nrate); 293 } else if (enough) 294 an->an_tx_ok = an->an_tx_err = an->an_tx_retr = 0; 295 } 296 297 298 /* 299 * Read rate table from the HAL, and then 300 * copy the table to the driver's data structure. 301 */ 302 void 303 ath_rate_setup(ath_t *asc, uint32_t mode) 304 { 305 int32_t i, maxrates; 306 struct ieee80211_rateset *rs; 307 struct ath_hal *ah = asc->asc_ah; 308 ieee80211com_t *isc = (ieee80211com_t *)asc; 309 const HAL_RATE_TABLE *rt; 310 311 switch (mode) { 312 case IEEE80211_MODE_11A: 313 asc->asc_rates[mode] = ATH_HAL_GETRATETABLE(ah, HAL_MODE_11A); 314 break; 315 case IEEE80211_MODE_11B: 316 asc->asc_rates[mode] = ATH_HAL_GETRATETABLE(ah, HAL_MODE_11B); 317 break; 318 case IEEE80211_MODE_11G: 319 asc->asc_rates[mode] = ATH_HAL_GETRATETABLE(ah, HAL_MODE_11G); 320 break; 321 case IEEE80211_MODE_TURBO: 322 asc->asc_rates[mode] = ATH_HAL_GETRATETABLE(ah, HAL_MODE_TURBO); 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 = &isc->isc_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