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
ath_rate_update(ath_t * asc,struct ieee80211_node * in,int32_t rate)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
ath_rate_ctl_start(ath_t * asc,struct ieee80211_node * in)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
ath_rate_cb(void * arg,struct ieee80211_node * in)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
ath_rate_ctl_reset(ath_t * asc,enum ieee80211_state state)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
ath_rate_ctl(void * arg,struct ieee80211_node * in)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
ath_rate_setup(ath_t * asc,uint32_t mode)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