Print this page
7154 arn(7D) walks out of bounds when byteswapping the 4K eeprom
7152 weird condition in arn(7D) needs clarification
7153 delete unused code in arn(7D)
7155 arn(7D) should include the mac fields in the eeprom enumeration
Split |
Close |
Expand all |
Collapse all |
--- old/usr/src/uts/common/io/arn/arn_beacon.c
+++ new/usr/src/uts/common/io/arn/arn_beacon.c
1 1 /*
2 2 * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
3 3 * Use is subject to license terms.
4 4 */
5 5
6 6 /*
7 7 * Copyright (c) 2008 Atheros Communications Inc.
8 8 *
9 9 * Permission to use, copy, modify, and/or distribute this software for any
10 10 * purpose with or without fee is hereby granted, provided that the above
11 11 * copyright notice and this permission notice appear in all copies.
12 12 *
13 13 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
14 14 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
15 15 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
16 16 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
17 17 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
18 18 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
19 19 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
20 20 */
21 21
↓ open down ↓ |
21 lines elided |
↑ open up ↑ |
22 22 #include <sys/param.h>
23 23 #include <sys/strsun.h>
24 24 #include <inet/common.h>
25 25 #include <inet/nd.h>
26 26 #include <inet/mi.h>
27 27 #include <inet/wifi_ioctl.h>
28 28
29 29 #include "arn_core.h"
30 30
31 31 /*
32 - * This function will modify certain transmit queue properties depending on
33 - * the operating mode of the station (AP or AdHoc). Parameters are AIFS
34 - * settings and channel width min/max
35 - */
36 -
37 -static int
38 -/* LINTED E_STATIC_UNUSED */
39 -arn_beaconq_config(struct arn_softc *sc)
40 -{
41 - struct ath_hal *ah = sc->sc_ah;
42 - struct ath9k_tx_queue_info qi;
43 -
44 - (void) ath9k_hw_get_txq_props(ah, sc->sc_beaconq, &qi);
45 - if (sc->sc_ah->ah_opmode == ATH9K_M_HOSTAP) {
46 - /* Always burst out beacon and CAB traffic. */
47 - qi.tqi_aifs = 1;
48 - qi.tqi_cwmin = 0;
49 - qi.tqi_cwmax = 0;
50 - } else {
51 - /* Adhoc mode; important thing is to use 2x cwmin. */
52 - qi.tqi_aifs = sc->sc_beacon_qi.tqi_aifs;
53 - qi.tqi_cwmin = 2*sc->sc_beacon_qi.tqi_cwmin;
54 - qi.tqi_cwmax = sc->sc_beacon_qi.tqi_cwmax;
55 - }
56 -
57 - if (!ath9k_hw_set_txq_props(ah, sc->sc_beaconq, &qi)) {
58 - arn_problem("unable to update h/w beacon queue parameters\n");
59 - return (0);
60 - } else {
61 - /* push to h/w */
62 - (void) ath9k_hw_resettxqueue(ah, sc->sc_beaconq);
63 - return (1);
64 - }
65 -}
66 -
67 -/*
68 32 * Associates the beacon frame buffer with a transmit descriptor. Will set
69 33 * up all required antenna switch parameters, rate codes, and channel flags.
70 34 * Beacons are always sent out at the lowest rate, and are not retried.
71 35 */
72 36 #ifdef ARN_IBSS
73 37 static void
74 38 arn_beacon_setup(struct arn_softc *sc, struct ath_buf *bf)
75 39 {
76 40 #define USE_SHPREAMBLE(_ic) \
77 41 (((_ic)->ic_flags & (IEEE80211_F_SHPREAMBLE | IEEE80211_F_USEBARKER))\
78 42 == IEEE80211_F_SHPREAMBLE)
79 43 mblk_t *mp = bf->bf_m;
80 44 struct ath_hal *ah = sc->sc_ah;
81 45 struct ath_desc *ds;
82 46 /* LINTED E_FUNC_SET_NOT_USED */
83 47 int flags, antenna = 0;
84 48 struct ath_rate_table *rt;
85 49 uint8_t rix, rate;
86 50 struct ath9k_11n_rate_series series[4];
87 51 int ctsrate = 0;
88 52 int ctsduration = 0;
89 53
90 54 /* set up descriptors */
91 55 ds = bf->bf_desc;
92 56
93 57 flags = ATH9K_TXDESC_NOACK;
94 58 if (sc->sc_ah->ah_opmode == ATH9K_M_IBSS &&
95 59 (ah->ah_caps.hw_caps & ATH9K_HW_CAP_VEOL)) {
96 60 ds->ds_link = bf->bf_daddr; /* self-linked */
97 61 flags |= ATH9K_TXDESC_VEOL;
98 62 /*
99 63 * Let hardware handle antenna switching.
100 64 */
101 65 antenna = 0;
102 66 } else {
103 67 ds->ds_link = 0;
104 68 /*
105 69 * Switch antenna every 4 beacons.
106 70 * NB: assumes two antenna
107 71 */
108 72 antenna = ((sc->ast_be_xmit / sc->sc_nbcnvaps) & 1 ? 2 : 1);
109 73 }
110 74
111 75 ds->ds_data = bf->bf_dma.cookie.dmac_address;
112 76 /*
113 77 * Calculate rate code.
114 78 * XXX everything at min xmit rate
115 79 */
116 80 rix = 0;
117 81 rt = sc->hw_rate_table[sc->sc_curmode];
118 82 rate = rt->info[rix].ratecode;
119 83 if (sc->sc_flags & SC_OP_PREAMBLE_SHORT)
120 84 rate |= rt->info[rix].short_preamble;
121 85
122 86 ath9k_hw_set11n_txdesc(ah, ds,
123 87 MBLKL(mp) + IEEE80211_CRC_LEN, /* frame length */
124 88 ATH9K_PKT_TYPE_BEACON, /* Atheros packet type */
125 89 MAX_RATE_POWER, /* FIXME */
126 90 ATH9K_TXKEYIX_INVALID, /* no encryption */
127 91 ATH9K_KEY_TYPE_CLEAR, /* no encryption */
128 92 flags); /* no ack, veol for beacons */
129 93
130 94 /* NB: beacon's BufLen must be a multiple of 4 bytes */
131 95 (void) ath9k_hw_filltxdesc(ah, ds,
132 96 roundup(MBLKL(mp), 4), /* buffer length */
133 97 B_TRUE, /* first segment */
134 98 B_TRUE, /* last segment */
135 99 ds); /* first descriptor */
136 100
137 101 (void) memset(series, 0, sizeof (struct ath9k_11n_rate_series) * 4);
138 102 series[0].Tries = 1;
139 103 series[0].Rate = rate;
140 104 series[0].ChSel = sc->sc_tx_chainmask;
141 105 series[0].RateFlags = (ctsrate) ? ATH9K_RATESERIES_RTS_CTS : 0;
142 106 ath9k_hw_set11n_ratescenario(ah, ds, ds, 0,
143 107 ctsrate, ctsduration, series, 4, 0);
144 108 #undef USE_SHPREAMBLE
↓ open down ↓ |
67 lines elided |
↑ open up ↑ |
145 109 }
146 110 #endif
147 111
148 112 /*
149 113 * Startup beacon transmission for adhoc mode when they are sent entirely
150 114 * by the hardware using the self-linked descriptor + veol trick.
151 115 */
152 116 #ifdef ARN_IBSS
153 117 static void
154 118 arn_beacon_start_adhoc(struct arn_softc *sc)
155 -
156 119 {
157 120 struct ath_buf *bf = list_head(&sc->sc_bcbuf_list);
158 121 struct ieee80211_node *in = bf->bf_in;
159 122 struct ieee80211com *ic = in->in_ic;
160 123 struct ath_hal *ah = sc->sc_ah;
161 124 mblk_t *mp;
162 125
163 126 mp = bf->bf_m;
164 127 if (ieee80211_beacon_update(ic, bf->bf_in, &sc->asc_boff, mp, 0))
165 128 bcopy(mp->b_rptr, bf->bf_dma.mem_va, MBLKL(mp));
166 129
167 130 /* Construct tx descriptor. */
168 131 arn_beacon_setup(sc, bf);
169 132
170 133 /*
171 134 * Stop any current dma and put the new frame on the queue.
172 135 * This should never fail since we check above that no frames
173 136 * are still pending on the queue.
174 137 */
175 138 if (!ath9k_hw_stoptxdma(ah, sc->sc_beaconq)) {
176 139 arn_problem("ath: beacon queue %d did not stop?\n",
177 140 sc->sc_beaconq);
178 141 }
179 142 ARN_DMA_SYNC(bf->bf_dma, DDI_DMA_SYNC_FORDEV);
180 143
181 144 /* NB: caller is known to have already stopped tx dma */
182 145 (void) ath9k_hw_puttxbuf(ah, sc->sc_beaconq, bf->bf_daddr);
183 146 (void) ath9k_hw_txstart(ah, sc->sc_beaconq);
184 147
185 148 ARN_DBG((ARN_DBG_BEACON, "arn: arn_bstuck_process(): "
186 149 "TXDP%u = %llx (%p)\n", sc->sc_beaconq,
187 150 ito64(bf->bf_daddr), bf->bf_desc));
188 151 }
189 152 #endif /* ARN_IBSS */
190 153
191 154 uint32_t
192 155 arn_beaconq_setup(struct ath_hal *ah)
193 156 {
194 157 struct ath9k_tx_queue_info qi;
195 158
196 159 (void) memset(&qi, 0, sizeof (qi));
197 160 qi.tqi_aifs = 1;
198 161 qi.tqi_cwmin = 0;
199 162 qi.tqi_cwmax = 0;
200 163 /* NB: don't enable any interrupts */
201 164 return (ath9k_hw_setuptxqueue(ah, ATH9K_TX_QUEUE_BEACON, &qi));
202 165 }
203 166
204 167 int
205 168 arn_beacon_alloc(struct arn_softc *sc, struct ieee80211_node *in)
206 169 {
207 170 ieee80211com_t *ic = in->in_ic;
208 171 struct ath_buf *bf;
209 172 mblk_t *mp;
210 173
211 174 mutex_enter(&sc->sc_bcbuflock);
212 175 bf = list_head(&sc->sc_bcbuf_list);
213 176 if (bf == NULL) {
214 177 arn_problem("arn: arn_beacon_alloc():"
215 178 "no dma buffers");
216 179 mutex_exit(&sc->sc_bcbuflock);
217 180 return (ENOMEM);
218 181 }
219 182
220 183 mp = ieee80211_beacon_alloc(ic, in, &sc->asc_boff);
221 184 if (mp == NULL) {
222 185 arn_problem("ath: arn_beacon_alloc():"
223 186 "cannot get mbuf\n");
224 187 mutex_exit(&sc->sc_bcbuflock);
225 188 return (ENOMEM);
226 189 }
227 190 ASSERT(mp->b_cont == NULL);
228 191 bf->bf_m = mp;
229 192 bcopy(mp->b_rptr, bf->bf_dma.mem_va, MBLKL(mp));
230 193 bf->bf_in = ieee80211_ref_node(in);
231 194 mutex_exit(&sc->sc_bcbuflock);
232 195
233 196 return (0);
234 197 }
235 198
236 199
237 200 void
238 201 arn_beacon_return(struct arn_softc *sc)
239 202 {
240 203 struct ath_buf *bf;
241 204
242 205 mutex_enter(&sc->sc_bcbuflock);
243 206 bf = list_head(&sc->sc_bcbuf_list);
244 207 while (bf != NULL) {
245 208 if (bf->bf_m != NULL) {
246 209 freemsg(bf->bf_m);
247 210 bf->bf_m = NULL;
248 211 }
249 212 if (bf->bf_in != NULL) {
↓ open down ↓ |
84 lines elided |
↑ open up ↑ |
250 213 ieee80211_free_node(bf->bf_in);
251 214 bf->bf_in = NULL;
252 215 }
253 216 bf = list_next(&sc->sc_bcbuf_list, bf);
254 217 }
255 218 mutex_exit(&sc->sc_bcbuflock);
256 219 }
257 220
258 221 void
259 222 arn_beacon_config(struct arn_softc *sc)
260 -
261 223 {
262 224 struct ath_beacon_config conf;
263 225 ieee80211com_t *ic = (ieee80211com_t *)sc;
264 226 struct ieee80211_node *in = ic->ic_bss;
265 227
266 228 /* New added */
267 229 struct ath9k_beacon_state bs;
268 230 int dtimperiod, dtimcount, sleepduration;
269 231 int cfpperiod, cfpcount;
270 232 uint32_t nexttbtt = 0, intval, tsftu;
271 233 uint64_t tsf;
272 234
273 235 (void) memset(&conf, 0, sizeof (struct ath_beacon_config));
274 236
275 237 /* XXX fix me */
276 238 conf.beacon_interval = in->in_intval ?
277 239 in->in_intval : ATH_DEFAULT_BINTVAL;
278 240 ARN_DBG((ARN_DBG_BEACON, "arn: arn_beacon_config():"
279 241 "conf.beacon_interval = %d\n", conf.beacon_interval));
280 242 conf.listen_interval = 1;
281 243 conf.dtim_period = conf.beacon_interval;
282 244 conf.dtim_count = 1;
283 245 conf.bmiss_timeout = ATH_DEFAULT_BMISS_LIMIT * conf.beacon_interval;
284 246
285 247 (void) memset(&bs, 0, sizeof (bs));
286 248 intval = conf.beacon_interval & ATH9K_BEACON_PERIOD;
287 249
288 250 /*
289 251 * Setup dtim and cfp parameters according to
290 252 * last beacon we received (which may be none).
291 253 */
292 254 dtimperiod = conf.dtim_period;
293 255 if (dtimperiod <= 0) /* NB: 0 if not known */
294 256 dtimperiod = 1;
295 257 dtimcount = conf.dtim_count;
296 258 if (dtimcount >= dtimperiod) /* NB: sanity check */
297 259 dtimcount = 0;
298 260 cfpperiod = 1; /* NB: no PCF support yet */
299 261 cfpcount = 0;
300 262
301 263 sleepduration = conf.listen_interval * intval;
302 264 if (sleepduration <= 0)
303 265 sleepduration = intval;
304 266
305 267 /*
306 268 * Pull nexttbtt forward to reflect the current
307 269 * TSF and calculate dtim+cfp state for the result.
308 270 */
309 271 tsf = ath9k_hw_gettsf64(sc->sc_ah);
310 272 tsftu = TSF_TO_TU(tsf>>32, tsf) + FUDGE;
311 273 do {
312 274 nexttbtt += intval;
313 275 if (--dtimcount < 0) {
314 276 dtimcount = dtimperiod - 1;
315 277 if (--cfpcount < 0)
316 278 cfpcount = cfpperiod - 1;
317 279 }
318 280 } while (nexttbtt < tsftu);
319 281
320 282 bs.bs_intval = intval;
321 283 bs.bs_nexttbtt = nexttbtt;
322 284 bs.bs_dtimperiod = dtimperiod*intval;
323 285 bs.bs_nextdtim = bs.bs_nexttbtt + dtimcount*intval;
324 286 bs.bs_cfpperiod = cfpperiod*bs.bs_dtimperiod;
325 287 bs.bs_cfpnext = bs.bs_nextdtim + cfpcount*bs.bs_dtimperiod;
↓ open down ↓ |
55 lines elided |
↑ open up ↑ |
326 288 bs.bs_cfpmaxduration = 0;
327 289
328 290 /*
329 291 * Calculate the number of consecutive beacons to miss* before taking
330 292 * a BMISS interrupt. The configuration is specified in TU so we only
331 293 * need calculate based on the beacon interval. Note that we clamp the
332 294 * result to at most 15 beacons.
333 295 */
334 296 if (sleepduration > intval) {
335 297 bs.bs_bmissthreshold = conf.listen_interval *
336 - ATH_DEFAULT_BMISS_LIMIT / 2;
298 + ATH_DEFAULT_BMISS_LIMIT / 2;
337 299 } else {
338 300 bs.bs_bmissthreshold = DIV_ROUND_UP(conf.bmiss_timeout, intval);
339 301 if (bs.bs_bmissthreshold > 15)
340 302 bs.bs_bmissthreshold = 15;
341 303 else if (bs.bs_bmissthreshold == 0)
342 304 bs.bs_bmissthreshold = 1;
343 305 }
344 306
345 307 /*
346 308 * Calculate sleep duration. The configuration is given in ms.
347 309 * We ensure a multiple of the beacon period is used. Also, if the sleep
348 310 * duration is greater than the DTIM period then it makes senses
349 311 * to make it a multiple of that.
350 312 *
351 313 * XXX fixed at 100ms
352 314 */
353 315
354 316 bs.bs_sleepduration = roundup(IEEE80211_MS_TO_TU(100), sleepduration);
355 317 if (bs.bs_sleepduration > bs.bs_dtimperiod)
356 318 bs.bs_sleepduration = bs.bs_dtimperiod;
357 319
358 320 /* TSF out of range threshold fixed at 1 second */
359 321 bs.bs_tsfoor_threshold = ATH9K_TSFOOR_THRESHOLD;
360 322
361 323 ARN_DBG((ARN_DBG_BEACON, "arn: arn_beacon_config(): "
362 324 "tsf %llu "
363 325 "tsf:tu %u "
364 326 "intval %u "
365 327 "nexttbtt %u "
366 328 "dtim %u "
367 329 "nextdtim %u "
368 330 "bmiss %u "
369 331 "sleep %u "
370 332 "cfp:period %u "
371 333 "maxdur %u "
372 334 "next %u "
373 335 "timoffset %u\n",
374 336 (unsigned long long)tsf, tsftu,
375 337 bs.bs_intval,
376 338 bs.bs_nexttbtt,
377 339 bs.bs_dtimperiod,
378 340 bs.bs_nextdtim,
379 341 bs.bs_bmissthreshold,
380 342 bs.bs_sleepduration,
381 343 bs.bs_cfpperiod,
382 344 bs.bs_cfpmaxduration,
383 345 bs.bs_cfpnext,
384 346 bs.bs_timoffset));
385 347
386 348 /* Set the computed STA beacon timers */
387 349
388 350 (void) ath9k_hw_set_interrupts(sc->sc_ah, 0);
389 351 ath9k_hw_set_sta_beacon_timers(sc->sc_ah, &bs);
390 352 sc->sc_imask |= ATH9K_INT_BMISS;
391 353 (void) ath9k_hw_set_interrupts(sc->sc_ah, sc->sc_imask);
392 354 }
393 355
394 356 void
395 357 ath_beacon_sync(struct arn_softc *sc)
396 358 {
397 359 /*
398 360 * Resync beacon timers using the tsf of the
399 361 * beacon frame we just received.
400 362 */
401 363 arn_beacon_config(sc);
402 364 sc->sc_flags |= SC_OP_BEACONS;
403 365 }
404 366
405 367 void
406 368 arn_bmiss_proc(void *arg)
407 369 {
408 370 struct arn_softc *sc = (struct arn_softc *)arg;
409 371 ieee80211com_t *ic = (ieee80211com_t *)sc;
410 372 uint64_t tsf, lastrx;
411 373 uint_t bmisstimeout;
412 374
413 375 if (ic->ic_opmode != IEEE80211_M_STA ||
414 376 ic->ic_state != IEEE80211_S_RUN) {
415 377 return;
416 378 }
417 379
418 380 ARN_LOCK(sc);
419 381 lastrx = sc->sc_lastrx;
420 382 tsf = ath9k_hw_gettsf64(sc->sc_ah);
421 383 bmisstimeout = ic->ic_bmissthreshold * ic->ic_bss->in_intval * 1024;
422 384
423 385 ARN_DBG((ARN_DBG_BEACON, "arn_bmiss_proc():"
424 386 " tsf %llu, lastrx %llu (%lld), bmiss %u\n",
425 387 (unsigned long long)tsf, (unsigned long long)sc->sc_lastrx,
426 388 (long long)(tsf - lastrx), bmisstimeout));
427 389 ARN_UNLOCK(sc);
428 390
429 391 /* temp workaround */
430 392 if ((tsf - lastrx) > bmisstimeout)
431 393 ieee80211_beacon_miss(ic);
432 394 }
↓ open down ↓ |
86 lines elided |
↑ open up ↑ |
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX