1 /* 2 * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 3 * Use is subject to license terms. 4 */ 5 6 /* 7 * Copyright (c) 2008 Atheros Communications Inc. 8 * 9 * Permission to use, copy, modify, and/or distribute this software for any 10 * purpose with or without fee is hereby granted, provided that the above 11 * copyright notice and this permission notice appear in all copies. 12 * 13 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 14 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 15 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 16 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 17 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 18 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 19 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 20 */ 21 22 #include <sys/byteorder.h> 23 24 #include "arn_core.h" 25 26 void 27 arn_setdefantenna(struct arn_softc *sc, uint32_t antenna) 28 { 29 /* XXX block beacon interrupts */ 30 ath9k_hw_setantenna(sc->sc_ah, antenna); 31 sc->sc_defant = (uint8_t)antenna; /* LINT */ 32 sc->sc_rxotherant = 0; 33 } 34 35 /* 36 * Extend 15-bit time stamp from rx descriptor to 37 * a full 64-bit TSF using the current h/w TSF. 38 */ 39 40 static uint64_t 41 arn_extend_tsf(struct arn_softc *sc, uint32_t rstamp) 42 { 43 uint64_t tsf; 44 45 tsf = ath9k_hw_gettsf64(sc->sc_ah); 46 if ((tsf & 0x7fff) < rstamp) 47 tsf -= 0x8000; 48 return ((tsf & ~0x7fff) | rstamp); 49 } 50 51 static void 52 arn_opmode_init(struct arn_softc *sc) 53 { 54 struct ath_hal *ah = sc->sc_ah; 55 uint32_t rfilt; 56 uint32_t mfilt[2]; 57 ieee80211com_t *ic = (ieee80211com_t *)sc; 58 59 /* configure rx filter */ 60 rfilt = arn_calcrxfilter(sc); 61 ath9k_hw_setrxfilter(ah, rfilt); 62 63 /* configure bssid mask */ 64 if (ah->ah_caps.hw_caps & ATH9K_HW_CAP_BSSIDMASK) 65 (void) ath9k_hw_setbssidmask(ah, sc->sc_bssidmask); 66 67 /* configure operational mode */ 68 ath9k_hw_setopmode(ah); 69 70 /* Handle any link-level address change. */ 71 (void) ath9k_hw_setmac(ah, sc->sc_myaddr); 72 73 /* calculate and install multicast filter */ 74 mfilt[0] = ~((uint32_t)0); /* LINT */ 75 mfilt[1] = ~((uint32_t)0); /* LINT */ 76 77 ath9k_hw_setmcastfilter(ah, mfilt[0], mfilt[1]); 78 79 ARN_DBG((ARN_DBG_RECV, "arn: arn_opmode_init(): " 80 "mode = %d RX filter 0x%x, MC filter %08x:%08x\n", 81 ic->ic_opmode, rfilt, mfilt[0], mfilt[1])); 82 } 83 84 /* 85 * Calculate the receive filter according to the 86 * operating mode and state: 87 * 88 * o always accept unicast, broadcast, and multicast traffic 89 * o maintain current state of phy error reception (the hal 90 * may enable phy error frames for noise immunity work) 91 * o probe request frames are accepted only when operating in 92 * hostap, adhoc, or monitor modes 93 * o enable promiscuous mode according to the interface state 94 * o accept beacons: 95 * - when operating in adhoc mode so the 802.11 layer creates 96 * node table entries for peers, 97 * - when operating in station mode for collecting rssi data when 98 * the station is otherwise quiet, or 99 * - when operating as a repeater so we see repeater-sta beacons 100 * - when scanning 101 */ 102 103 uint32_t 104 arn_calcrxfilter(struct arn_softc *sc) 105 { 106 #define RX_FILTER_PRESERVE (ATH9K_RX_FILTER_PHYERR | \ 107 ATH9K_RX_FILTER_PHYRADAR) 108 109 uint32_t rfilt; 110 111 rfilt = (ath9k_hw_getrxfilter(sc->sc_ah) & RX_FILTER_PRESERVE) | 112 ATH9K_RX_FILTER_UCAST | ATH9K_RX_FILTER_BCAST | 113 ATH9K_RX_FILTER_MCAST; 114 115 /* If not a STA, enable processing of Probe Requests */ 116 if (sc->sc_ah->ah_opmode != ATH9K_M_STA) 117 rfilt |= ATH9K_RX_FILTER_PROBEREQ; 118 119 /* Can't set HOSTAP into promiscous mode */ 120 if (((sc->sc_ah->ah_opmode != ATH9K_M_HOSTAP) && 121 (sc->sc_promisc)) || 122 (sc->sc_ah->ah_opmode == ATH9K_M_MONITOR)) { 123 rfilt |= ATH9K_RX_FILTER_PROM; 124 /* ??? To prevent from sending ACK */ 125 rfilt &= ~ATH9K_RX_FILTER_UCAST; 126 } 127 128 if (sc->sc_ah->ah_opmode == ATH9K_M_STA || 129 sc->sc_ah->ah_opmode == ATH9K_M_IBSS) 130 rfilt |= ATH9K_RX_FILTER_BEACON; 131 132 /* 133 * If in HOSTAP mode, want to enable reception of PSPOLL 134 * frames & beacon frames 135 */ 136 if (sc->sc_ah->ah_opmode == ATH9K_M_HOSTAP) 137 rfilt |= (ATH9K_RX_FILTER_BEACON | ATH9K_RX_FILTER_PSPOLL); 138 139 return (rfilt); 140 141 #undef RX_FILTER_PRESERVE 142 } 143 144 int 145 arn_startrecv(struct arn_softc *sc) 146 { 147 struct ath_hal *ah = sc->sc_ah; 148 struct ath_buf *bf; 149 150 /* clean up rx link firstly */ 151 sc->sc_rxlink = NULL; 152 153 /* rx descriptor link set up */ 154 bf = list_head(&sc->sc_rxbuf_list); 155 while (bf != NULL) { 156 arn_rx_buf_link(sc, bf); 157 bf = list_next(&sc->sc_rxbuf_list, bf); 158 } 159 160 bf = list_head(&sc->sc_rxbuf_list); 161 162 ath9k_hw_putrxbuf(ah, bf->bf_daddr); 163 ath9k_hw_rxena(ah); 164 165 arn_opmode_init(sc); 166 ath9k_hw_startpcureceive(ah); 167 168 return (0); 169 } 170 171 boolean_t 172 arn_stoprecv(struct arn_softc *sc) 173 { 174 struct ath_hal *ah = sc->sc_ah; 175 boolean_t stopped; 176 177 ath9k_hw_stoppcurecv(ah); 178 ath9k_hw_setrxfilter(ah, 0); 179 stopped = ath9k_hw_stopdmarecv(ah); 180 181 /* 3ms is long enough for 1 frame ??? */ 182 drv_usecwait(3000); 183 184 sc->sc_rxlink = NULL; 185 186 return (stopped); 187 } 188 189 /* 190 * Intercept management frames to collect beacon rssi data 191 * and to do ibss merges. 192 */ 193 194 void 195 arn_recv_mgmt(struct ieee80211com *ic, mblk_t *mp, struct ieee80211_node *in, 196 int subtype, int rssi, uint32_t rstamp) 197 { 198 struct arn_softc *sc = (struct arn_softc *)ic; 199 200 /* 201 * Call up first so subsequent work can use information 202 * potentially stored in the node (e.g. for ibss merge). 203 */ 204 sc->sc_recv_mgmt(ic, mp, in, subtype, rssi, rstamp); 205 206 ARN_LOCK(sc); 207 switch (subtype) { 208 case IEEE80211_FC0_SUBTYPE_BEACON: 209 /* update rssi statistics */ 210 if (sc->sc_bsync && in == ic->ic_bss && 211 ic->ic_state == IEEE80211_S_RUN) { 212 /* 213 * Resync beacon timers using the tsf of the beacon 214 * frame we just received. 215 */ 216 arn_beacon_config(sc); 217 } 218 /* FALLTHRU */ 219 case IEEE80211_FC0_SUBTYPE_PROBE_RESP: 220 if (ic->ic_opmode == IEEE80211_M_IBSS && 221 ic->ic_state == IEEE80211_S_RUN && 222 (in->in_capinfo & IEEE80211_CAPINFO_IBSS)) { 223 uint64_t tsf = arn_extend_tsf(sc, rstamp); 224 /* 225 * Handle ibss merge as needed; check the tsf on the 226 * frame before attempting the merge. The 802.11 spec 227 * says the station should change it's bssid to match 228 * the oldest station with the same ssid, where oldest 229 * is determined by the tsf. Note that hardware 230 * reconfiguration happens through callback to 231 * ath_newstate as the state machine will go from 232 * RUN -> RUN when this happens. 233 */ 234 if (LE_64(in->in_tstamp.tsf) >= tsf) { 235 ARN_DBG((ARN_DBG_BEACON, "arn: arn_recv_mgmt:" 236 "ibss merge, rstamp %u tsf %lu " 237 "tstamp %lu\n", rstamp, tsf, 238 in->in_tstamp.tsf)); 239 ARN_UNLOCK(sc); 240 ARN_DBG((ARN_DBG_BEACON, "arn_recv_mgmt():" 241 "ibss_merge: rstamp=%d in_tstamp=%02x %02x" 242 " %02x %02x %02x %02x %02x %02x\n", 243 rstamp, in->in_tstamp.data[0], 244 in->in_tstamp.data[1], 245 in->in_tstamp.data[2], 246 in->in_tstamp.data[3], 247 in->in_tstamp.data[4], 248 in->in_tstamp.data[5], 249 in->in_tstamp.data[6], 250 in->in_tstamp.data[7])); 251 (void) ieee80211_ibss_merge(in); 252 return; 253 } 254 } 255 break; 256 } 257 ARN_UNLOCK(sc); 258 } 259 260 static void 261 arn_printrxbuf(struct ath_buf *bf, int32_t done) 262 { 263 struct ath_desc *ds = bf->bf_desc; 264 const struct ath_rx_status *rs = &ds->ds_rxstat; 265 266 ARN_DBG((ARN_DBG_RECV, "arn: R (%p %p) %08x %08x %08x " 267 "%08x %08x %08x %c\n", 268 ds, bf->bf_daddr, 269 ds->ds_link, ds->ds_data, 270 ds->ds_ctl0, ds->ds_ctl1, 271 ds->ds_hw[0], ds->ds_hw[1], 272 !done ? ' ' : (rs->rs_status == 0) ? '*' : '!')); 273 } 274 275 static void 276 arn_rx_handler(struct arn_softc *sc) 277 { 278 #define PA2DESC(_sc, _pa) \ 279 ((struct ath_desc *)((caddr_t)(_sc)->sc_desc + \ 280 ((_pa) - (_sc)->sc_desc_dma.cookie.dmac_address))) 281 282 ieee80211com_t *ic = (ieee80211com_t *)sc; 283 struct ath_buf *bf; 284 struct ath_hal *ah = sc->sc_ah; 285 struct ath_desc *ds; 286 struct ath_rx_status *rs; 287 mblk_t *rx_mp; 288 struct ieee80211_frame *wh; 289 int32_t len, ngood, loop = 1; 290 uint8_t phyerr; 291 int status; 292 struct ieee80211_node *in; 293 294 ngood = 0; 295 do { 296 mutex_enter(&sc->sc_rxbuflock); 297 bf = list_head(&sc->sc_rxbuf_list); 298 if (bf == NULL) { 299 ARN_DBG((ARN_DBG_RECV, "arn: arn_rx_handler(): " 300 "no buffer\n")); 301 mutex_exit(&sc->sc_rxbuflock); 302 break; 303 } 304 ASSERT(bf->bf_dma.cookie.dmac_address != NULL); 305 ds = bf->bf_desc; 306 if (ds->ds_link == bf->bf_daddr) { 307 /* 308 * Never process the self-linked entry at the end, 309 * this may be met at heavy load. 310 */ 311 mutex_exit(&sc->sc_rxbuflock); 312 break; 313 } 314 315 /* 316 * Must provide the virtual address of the current 317 * descriptor, the physical address, and the virtual 318 * address of the next descriptor in the h/w chain. 319 * This allows the HAL to look ahead to see if the 320 * hardware is done with a descriptor by checking the 321 * done bit in the following descriptor and the address 322 * of the current descriptor the DMA engine is working 323 * on. All this is necessary because of our use of 324 * a self-linked list to avoid rx overruns. 325 */ 326 status = ath9k_hw_rxprocdesc(ah, ds, 327 bf->bf_daddr, 328 PA2DESC(sc, ds->ds_link), 0); 329 if (status == EINPROGRESS) { 330 mutex_exit(&sc->sc_rxbuflock); 331 break; 332 } 333 list_remove(&sc->sc_rxbuf_list, bf); 334 mutex_exit(&sc->sc_rxbuflock); 335 336 rs = &ds->ds_rxstat; 337 if (rs->rs_status != 0) { 338 if (rs->rs_status & ATH9K_RXERR_CRC) { 339 sc->sc_stats.ast_rx_crcerr++; 340 } 341 if (rs->rs_status & ATH9K_RXERR_FIFO) { 342 sc->sc_stats.ast_rx_fifoerr++; 343 } 344 if (rs->rs_status & ATH9K_RXERR_DECRYPT) { 345 sc->sc_stats.ast_rx_badcrypt++; 346 } 347 if (rs->rs_status & ATH9K_RXERR_PHY) { 348 sc->sc_stats.ast_rx_phyerr++; 349 phyerr = rs->rs_phyerr & 0x1f; 350 sc->sc_stats.ast_rx_phy[phyerr]++; 351 } 352 goto rx_next; 353 } 354 len = rs->rs_datalen; 355 356 /* less than sizeof(struct ieee80211_frame) */ 357 if (len < 20) { 358 sc->sc_stats.ast_rx_tooshort++; 359 goto rx_next; 360 } 361 362 if ((rx_mp = allocb(sc->sc_dmabuf_size, BPRI_MED)) == NULL) { 363 arn_problem("arn: arn_rx_handler(): " 364 "allocing mblk buffer failed.\n"); 365 return; 366 } 367 368 ARN_DMA_SYNC(bf->bf_dma, DDI_DMA_SYNC_FORCPU); 369 bcopy(bf->bf_dma.mem_va, rx_mp->b_rptr, len); 370 371 rx_mp->b_wptr += len; 372 wh = (struct ieee80211_frame *)rx_mp->b_rptr; 373 374 if ((wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK) == 375 IEEE80211_FC0_TYPE_CTL) { 376 /* 377 * Ignore control frame received in promisc mode. 378 */ 379 freemsg(rx_mp); 380 goto rx_next; 381 } 382 /* Remove the CRC at the end of IEEE80211 frame */ 383 rx_mp->b_wptr -= IEEE80211_CRC_LEN; 384 385 #ifdef DEBUG 386 arn_printrxbuf(bf, status == 0); 387 #endif 388 389 /* 390 * Locate the node for sender, track state, and then 391 * pass the (referenced) node up to the 802.11 layer 392 * for its use. 393 */ 394 in = ieee80211_find_rxnode(ic, wh); 395 396 /* 397 * Send the frame to net80211 for processing 398 */ 399 (void) ieee80211_input(ic, rx_mp, in, 400 rs->rs_rssi, rs->rs_tstamp); 401 402 /* release node */ 403 ieee80211_free_node(in); 404 405 /* 406 * Arrange to update the last rx timestamp only for 407 * frames from our ap when operating in station mode. 408 * This assumes the rx key is always setup when associated. 409 */ 410 if (ic->ic_opmode == IEEE80211_M_STA && 411 rs->rs_keyix != ATH9K_RXKEYIX_INVALID) { 412 ngood++; 413 } 414 415 /* 416 * change the default rx antenna if rx diversity chooses the 417 * other antenna 3 times in a row. 418 */ 419 if (sc->sc_defant != ds->ds_rxstat.rs_antenna) { 420 if (++sc->sc_rxotherant >= 3) { 421 ath9k_hw_setantenna(sc->sc_ah, 422 ds->ds_rxstat.rs_antenna); 423 sc->sc_defant = ds->ds_rxstat.rs_antenna; 424 sc->sc_rxotherant = 0; 425 } 426 } else { 427 sc->sc_rxotherant = 0; 428 } 429 430 rx_next: 431 mutex_enter(&sc->sc_rxbuflock); 432 list_insert_tail(&sc->sc_rxbuf_list, bf); 433 mutex_exit(&sc->sc_rxbuflock); 434 arn_rx_buf_link(sc, bf); 435 } while (loop); 436 437 if (ngood) 438 sc->sc_lastrx = ath9k_hw_gettsf64(ah); 439 440 #undef PA2DESC 441 } 442 443 uint_t 444 arn_softint_handler(caddr_t data) 445 { 446 struct arn_softc *sc = (struct arn_softc *)data; 447 448 ARN_LOCK(sc); 449 450 if (sc->sc_rx_pend) { 451 /* Soft interrupt for this driver */ 452 sc->sc_rx_pend = 0; 453 ARN_UNLOCK(sc); 454 arn_rx_handler(sc); 455 return (DDI_INTR_CLAIMED); 456 } 457 458 ARN_UNLOCK(sc); 459 460 return (DDI_INTR_UNCLAIMED); 461 } 462