2 * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
3 * Use is subject to license terms.
7 * Copyright (c) 2002-2004 Sam Leffler, Errno Consulting
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
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.
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.
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>
45 #include <sys/cmn_err.h>
46 #include <sys/stropts.h>
47 #include <sys/strsubr.h>
48 #include <sys/strtty.h>
52 #include <sys/consdev.h>
54 #include <sys/modctl.h>
56 #include <sys/sunddi.h>
58 #include <sys/errno.h>
60 #include <sys/ethernet.h>
62 #include <sys/byteorder.h>
63 #include <sys/strsun.h>
64 #include <inet/common.h>
67 #include <inet/wifi_ioctl.h>
73 ath_rate_update(ath_t
*asc
, struct ieee80211_node
*in
, int32_t rate
)
75 struct ath_node
*an
= ATH_NODE(in
);
76 const HAL_RATE_TABLE
*rt
= asc
->asc_currates
;
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
));
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.
96 if (in
->in_rates
.ir_nrates
== 0)
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
) {
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).
111 an
->an_tx_try0
= 1 + 3; /* 4 tries at 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
;
119 an
->an_tx_rate1
= an
->an_tx_rate1sp
= 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
;
128 an
->an_tx_rate2
= an
->an_tx_rate2sp
= 0;
131 an
->an_tx_rate3
= rt
->info
[0].rateCode
;
133 an
->an_tx_mgtrate
| rt
->info
[0].shortPreamble
;
135 an
->an_tx_rate3
= an
->an_tx_rate3sp
= 0;
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;
144 an
->an_tx_ok
= an
->an_tx_err
= an
->an_tx_retr
= an
->an_tx_upper
= 0;
149 * Set the starting transmit rate for a node.
152 ath_rate_ctl_start(ath_t
*asc
, struct ieee80211_node
*in
)
154 ieee80211com_t
*ic
= (ieee80211com_t
*)asc
;
157 if (ic
->ic_fixed_rate
== IEEE80211_FIXED_RATE_NONE
) {
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.
163 srate
= in
->in_rates
.ir_nrates
- 1;
164 if (asc
->asc_curmode
!= IEEE80211_MODE_11B
) {
166 * Scan the negotiated rate set to find the
169 /* NB: the rate set is assumed sorted */
170 for (; srate
>= 0 && IEEE80211_RATE(srate
) > 72;
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.
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
;
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
);
190 ath_rate_cb(void *arg
, struct ieee80211_node
*in
)
192 ath_rate_update((ath_t
*)arg
, in
, 0);
196 * Reset the rate control state for each 802.11 state transition.
199 ath_rate_ctl_reset(ath_t
*asc
, enum ieee80211_state state
)
201 ieee80211com_t
*ic
= (ieee80211com_t
*)asc
;
202 struct ieee80211_node
*in
;
204 if (ic
->ic_opmode
== IEEE80211_M_STA
) {
206 * Reset local xmit state; this is really only
207 * meaningful when operating in station mode.
209 in
= (struct ieee80211_node
*)ic
->ic_bss
;
210 if (state
== IEEE80211_S_RUN
) {
211 ath_rate_ctl_start(asc
, in
);
213 ath_rate_update(asc
, in
, 0);
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.
222 ieee80211_iterate_nodes(&ic
->ic_sta
, ath_rate_cb
, asc
);
223 ath_rate_update(asc
, ic
->ic_bss
, 0);
229 * Examine and potentially adjust the transmit rate.
232 ath_rate_ctl(void *arg
, struct ieee80211_node
*in
)
235 struct ath_node
*an
= ATH_NODE(in
);
236 struct ieee80211_rateset
*rs
= &in
->in_rates
;
237 int32_t mod
= 0, nrate
, enough
;
240 * Rate control(very primitive version).
242 asc
->asc_stats
.ast_rate_calls
++;
244 enough
= (an
->an_tx_ok
+ an
->an_tx_err
>= 10);
246 /* no packet reached -> down */
247 if (an
->an_tx_err
> 0 && an
->an_tx_ok
== 0)
250 /* all packets needs retry in average -> down */
251 if (enough
&& an
->an_tx_ok
< an
->an_tx_retr
)
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)
258 nrate
= in
->in_txrate
;
261 if (enough
&& an
->an_tx_upper
> 0)
267 asc
->asc_stats
.ast_rate_drop
++;
272 if (++an
->an_tx_upper
< 10)
275 if (nrate
+ 1 < rs
->ir_nrates
) {
277 asc
->asc_stats
.ast_rate_raise
++;
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
);
290 an
->an_tx_ok
= an
->an_tx_err
= an
->an_tx_retr
= 0;
295 * Read rate table from the HAL, and then
296 * copy the table to the driver's data structure.
299 ath_rate_setup(ath_t
*asc
, uint32_t mode
)
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
;
309 case IEEE80211_MODE_11A
:
310 asc
->asc_rates
[mode
] = ATH_HAL_GETRATETABLE(ah
, HAL_MODE_11A
);
312 case IEEE80211_MODE_11B
:
313 asc
->asc_rates
[mode
] = ATH_HAL_GETRATETABLE(ah
, HAL_MODE_11B
);
315 case IEEE80211_MODE_11G
:
316 asc
->asc_rates
[mode
] = ATH_HAL_GETRATETABLE(ah
, HAL_MODE_11G
);
318 case IEEE80211_MODE_TURBO_A
:
319 asc
->asc_rates
[mode
] = ATH_HAL_GETRATETABLE(ah
, HAL_MODE_TURBO
);
321 case IEEE80211_MODE_TURBO_G
:
322 asc
->asc_rates
[mode
] = ATH_HAL_GETRATETABLE(ah
, HAL_MODE_108G
);
325 ATH_DEBUG((ATH_DBG_RATE
, "ath: ath_rate_setup(): "
326 "invalid mode %u\n", mode
));
330 rt
= asc
->asc_rates
[mode
];
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
;
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
;