iPXE
|
00001 /* 00002 * Copyright (c) 2008-2011 Atheros Communications Inc. 00003 * 00004 * Modified for iPXE by Scott K Logan <logans@cottsay.net> July 2011 00005 * Original from Linux kernel 3.0.1 00006 * 00007 * Permission to use, copy, modify, and/or distribute this software for any 00008 * purpose with or without fee is hereby granted, provided that the above 00009 * copyright notice and this permission notice appear in all copies. 00010 * 00011 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 00012 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 00013 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 00014 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 00015 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 00016 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 00017 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 00018 */ 00019 00020 #include <ipxe/io.h> 00021 00022 #include "ath9k.h" 00023 00024 static void ath9k_bss_info_changed(struct net80211_device *dev, u32 changed); 00025 00026 int ath9k_setpower(struct ath_softc *sc, enum ath9k_power_mode mode) 00027 { 00028 int ret; 00029 00030 ret = ath9k_hw_setpower(sc->sc_ah, mode); 00031 00032 return ret; 00033 } 00034 00035 static void ath_start_ani(struct ath_common *common) 00036 { 00037 struct ath_hw *ah = common->ah; 00038 unsigned long timestamp = ( currticks() * 1000 ) / TICKS_PER_SEC; 00039 struct ath_softc *sc = (struct ath_softc *) common->priv; 00040 00041 if (!(sc->sc_flags & SC_OP_ANI_RUN)) 00042 return; 00043 00044 if (sc->sc_flags & SC_OP_OFFCHANNEL) 00045 return; 00046 00047 common->ani.longcal_timer = timestamp; 00048 common->ani.shortcal_timer = timestamp; 00049 common->ani.checkani_timer = timestamp; 00050 00051 common->ani.timer = timestamp + ah->config.ani_poll_interval; 00052 } 00053 00054 static void ath_update_survey_nf(struct ath_softc *sc, int channel) 00055 { 00056 struct ath_hw *ah = sc->sc_ah; 00057 struct ath9k_channel *chan = &ah->channels[channel]; 00058 struct survey_info *survey = &sc->survey[channel]; 00059 00060 if (chan->noisefloor) { 00061 survey->filled |= SURVEY_INFO_NOISE_DBM; 00062 survey->noise = chan->noisefloor; 00063 } 00064 } 00065 00066 /* 00067 * Updates the survey statistics and returns the busy time since last 00068 * update in %, if the measurement duration was long enough for the 00069 * result to be useful, -1 otherwise. 00070 */ 00071 static int ath_update_survey_stats(struct ath_softc *sc) 00072 { 00073 struct ath_hw *ah = sc->sc_ah; 00074 struct ath_common *common = ath9k_hw_common(ah); 00075 int pos = ah->curchan - &ah->channels[0]; 00076 struct survey_info *survey = &sc->survey[pos]; 00077 struct ath_cycle_counters *cc = &common->cc_survey; 00078 unsigned int div = common->clockrate * 1000; 00079 int ret = 0; 00080 00081 if (!ah->curchan) 00082 return -1; 00083 00084 if (ah->power_mode == ATH9K_PM_AWAKE) 00085 ath_hw_cycle_counters_update(common); 00086 00087 if (cc->cycles > 0) { 00088 survey->filled |= SURVEY_INFO_CHANNEL_TIME | 00089 SURVEY_INFO_CHANNEL_TIME_BUSY | 00090 SURVEY_INFO_CHANNEL_TIME_RX | 00091 SURVEY_INFO_CHANNEL_TIME_TX; 00092 survey->channel_time += cc->cycles / div; 00093 survey->channel_time_busy += cc->rx_busy / div; 00094 survey->channel_time_rx += cc->rx_frame / div; 00095 survey->channel_time_tx += cc->tx_frame / div; 00096 } 00097 00098 if (cc->cycles < div) 00099 return -1; 00100 00101 if (cc->cycles > 0) 00102 ret = cc->rx_busy * 100 / cc->cycles; 00103 00104 memset(cc, 0, sizeof(*cc)); 00105 00106 ath_update_survey_nf(sc, pos); 00107 00108 return ret; 00109 } 00110 00111 /* 00112 * Set/change channels. If the channel is really being changed, it's done 00113 * by reseting the chip. To accomplish this we must first cleanup any pending 00114 * DMA, then restart stuff. 00115 */ 00116 int ath_set_channel(struct ath_softc *sc, struct net80211_device *dev, 00117 struct ath9k_channel *hchan) 00118 { 00119 struct ath_hw *ah = sc->sc_ah; 00120 struct ath_common *common = ath9k_hw_common(ah); 00121 int fastcc __unused = 1, stopped __unused; 00122 struct net80211_channel *channel = dev->channels + dev->channel; 00123 struct ath9k_hw_cal_data *caldata = NULL; 00124 int r; 00125 00126 if (sc->sc_flags & SC_OP_INVALID) 00127 return -EIO; 00128 00129 sc->hw_busy_count = 0; 00130 00131 common->ani.timer = 0; 00132 sc->tx_complete_work_timer = 0; 00133 sc->hw_pll_work_timer = 0; 00134 00135 /* 00136 * This is only performed if the channel settings have 00137 * actually changed. 00138 * 00139 * To switch channels clear any pending DMA operations; 00140 * wait long enough for the RX fifo to drain, reset the 00141 * hardware at the new frequency, and then re-enable 00142 * the relevant bits of the h/w. 00143 */ 00144 ath9k_hw_disable_interrupts(ah); 00145 stopped = ath_drain_all_txq(sc, 0); 00146 00147 if (!ath_stoprecv(sc)) 00148 stopped = 0; 00149 00150 if (!ath9k_hw_check_alive(ah)) 00151 stopped = 0; 00152 00153 /* XXX: do not flush receive queue here. We don't want 00154 * to flush data frames already in queue because of 00155 * changing channel. */ 00156 00157 if (!(sc->sc_flags & SC_OP_OFFCHANNEL)) 00158 caldata = &sc->caldata; 00159 00160 DBG2("ath9k: " 00161 "(%d MHz) -> (%d MHz)\n", 00162 sc->sc_ah->curchan->channel, 00163 channel->center_freq); 00164 00165 r = ath9k_hw_reset(ah, hchan, caldata, fastcc); 00166 if (r) { 00167 DBG("ath9k: " 00168 "Unable to reset channel (%d MHz), reset status %d\n", 00169 channel->center_freq, r); 00170 goto ps_restore; 00171 } 00172 00173 if (ath_startrecv(sc) != 0) { 00174 DBG("ath9k: Unable to restart recv logic\n"); 00175 r = -EIO; 00176 goto ps_restore; 00177 } 00178 00179 ath9k_cmn_update_txpow(ah, sc->curtxpow, 00180 sc->config.txpowlimit, &sc->curtxpow); 00181 ath9k_hw_set_interrupts(ah, ah->imask); 00182 00183 if (!(sc->sc_flags & (SC_OP_OFFCHANNEL))) { 00184 sc->tx_complete_work(sc); 00185 sc->hw_pll_work_timer = (currticks() * 1000 ) / TICKS_PER_SEC + 500; 00186 ath_start_ani(common); 00187 } 00188 00189 ps_restore: 00190 return r; 00191 } 00192 00193 /* 00194 * This routine performs the periodic noise floor calibration function 00195 * that is used to adjust and optimize the chip performance. This 00196 * takes environmental changes (location, temperature) into account. 00197 * When the task is complete, it reschedules itself depending on the 00198 * appropriate interval that was calculated. 00199 */ 00200 void ath_ani_calibrate(struct ath_softc *sc) 00201 { 00202 struct ath_hw *ah = sc->sc_ah; 00203 struct ath_common *common = ath9k_hw_common(ah); 00204 int longcal = 0; 00205 int shortcal = 0; 00206 int aniflag = 0; 00207 unsigned int timestamp = (currticks() * 1000 ) / TICKS_PER_SEC; 00208 u32 cal_interval, short_cal_interval, long_cal_interval; 00209 00210 if (ah->caldata && ah->caldata->nfcal_interference) 00211 long_cal_interval = ATH_LONG_CALINTERVAL_INT; 00212 else 00213 long_cal_interval = ATH_LONG_CALINTERVAL; 00214 00215 short_cal_interval = ATH_STA_SHORT_CALINTERVAL; 00216 00217 /* Only calibrate if awake */ 00218 if (sc->sc_ah->power_mode != ATH9K_PM_AWAKE) 00219 goto set_timer; 00220 00221 /* Long calibration runs independently of short calibration. */ 00222 if ((timestamp - common->ani.longcal_timer) >= long_cal_interval) { 00223 longcal = 1; 00224 DBG2("ath9k: longcal @%d\n", timestamp); 00225 common->ani.longcal_timer = timestamp; 00226 } 00227 00228 /* Short calibration applies only while caldone is false */ 00229 if (!common->ani.caldone) { 00230 if ((timestamp - common->ani.shortcal_timer) >= short_cal_interval) { 00231 shortcal = 1; 00232 DBG2("ath9k: " 00233 "shortcal @%d\n", timestamp); 00234 common->ani.shortcal_timer = timestamp; 00235 common->ani.resetcal_timer = timestamp; 00236 } 00237 } else { 00238 if ((timestamp - common->ani.resetcal_timer) >= 00239 ATH_RESTART_CALINTERVAL) { 00240 common->ani.caldone = ath9k_hw_reset_calvalid(ah); 00241 if (common->ani.caldone) 00242 common->ani.resetcal_timer = timestamp; 00243 } 00244 } 00245 00246 /* Verify whether we must check ANI */ 00247 if ((timestamp - common->ani.checkani_timer) >= 00248 ah->config.ani_poll_interval) { 00249 aniflag = 1; 00250 common->ani.checkani_timer = timestamp; 00251 } 00252 00253 /* Skip all processing if there's nothing to do. */ 00254 if (longcal || shortcal || aniflag) { 00255 /* Call ANI routine if necessary */ 00256 if (aniflag) { 00257 ath9k_hw_ani_monitor(ah, ah->curchan); 00258 ath_update_survey_stats(sc); 00259 } 00260 00261 /* Perform calibration if necessary */ 00262 if (longcal || shortcal) { 00263 common->ani.caldone = 00264 ath9k_hw_calibrate(ah, 00265 ah->curchan, 00266 common->rx_chainmask, 00267 longcal); 00268 } 00269 } 00270 00271 set_timer: 00272 /* 00273 * Set timer interval based on previous results. 00274 * The interval must be the shortest necessary to satisfy ANI, 00275 * short calibration and long calibration. 00276 */ 00277 cal_interval = ATH_LONG_CALINTERVAL; 00278 if (sc->sc_ah->config.enable_ani) 00279 cal_interval = min(cal_interval, 00280 (u32)ah->config.ani_poll_interval); 00281 if (!common->ani.caldone) 00282 cal_interval = min(cal_interval, (u32)short_cal_interval); 00283 00284 common->ani.timer = timestamp + cal_interval; 00285 } 00286 00287 void ath_hw_check(struct ath_softc *sc) 00288 { 00289 int busy; 00290 00291 if (ath9k_hw_check_alive(sc->sc_ah)) 00292 goto out; 00293 00294 busy = ath_update_survey_stats(sc); 00295 00296 DBG("ath9k: Possible baseband hang, " 00297 "busy=%d (try %d)\n", busy, sc->hw_busy_count + 1); 00298 if (busy >= 99) { 00299 if (++sc->hw_busy_count >= 3) 00300 ath_reset(sc, 1); 00301 } else if (busy >= 0) 00302 sc->hw_busy_count = 0; 00303 00304 out: 00305 return; 00306 } 00307 00308 static void ath_hw_pll_rx_hang_check(struct ath_softc *sc, u32 pll_sqsum) 00309 { 00310 static int count; 00311 00312 if (pll_sqsum >= 0x40000) { 00313 count++; 00314 if (count == 3) { 00315 /* Rx is hung for more than 500ms. Reset it */ 00316 DBG("ath9k: " 00317 "Possible RX hang, resetting"); 00318 ath_reset(sc, 1); 00319 count = 0; 00320 } 00321 } else 00322 count = 0; 00323 } 00324 00325 void ath_hw_pll_work(struct ath_softc *sc) 00326 { 00327 u32 pll_sqsum; 00328 00329 if (AR_SREV_9485(sc->sc_ah)) { 00330 pll_sqsum = ar9003_get_pll_sqsum_dvc(sc->sc_ah); 00331 00332 ath_hw_pll_rx_hang_check(sc, pll_sqsum); 00333 00334 sc->hw_pll_work_timer = (currticks() * 1000 ) / TICKS_PER_SEC + 200; 00335 } 00336 } 00337 00338 00339 void ath9k_tasklet(struct ath_softc *sc) 00340 { 00341 struct ath_hw *ah = sc->sc_ah; 00342 00343 u32 status = sc->intrstatus; 00344 u32 rxmask; 00345 00346 if ((status & ATH9K_INT_FATAL) || 00347 (status & ATH9K_INT_BB_WATCHDOG)) { 00348 ath_reset(sc, 1); 00349 return; 00350 } 00351 00352 rxmask = (ATH9K_INT_RX | ATH9K_INT_RXEOL | ATH9K_INT_RXORN); 00353 00354 if (status & rxmask) { 00355 ath_rx_tasklet(sc, 0, 0); 00356 } 00357 00358 if (status & ATH9K_INT_TX) { 00359 ath_tx_tasklet(sc); 00360 } 00361 00362 /* re-enable hardware interrupt */ 00363 ath9k_hw_enable_interrupts(ah); 00364 } 00365 00366 void ath_isr(struct net80211_device *dev) 00367 { 00368 #define SCHED_INTR ( \ 00369 ATH9K_INT_FATAL | \ 00370 ATH9K_INT_BB_WATCHDOG | \ 00371 ATH9K_INT_RXORN | \ 00372 ATH9K_INT_RXEOL | \ 00373 ATH9K_INT_RX | \ 00374 ATH9K_INT_RXLP | \ 00375 ATH9K_INT_RXHP | \ 00376 ATH9K_INT_TX | \ 00377 ATH9K_INT_BMISS | \ 00378 ATH9K_INT_CST | \ 00379 ATH9K_INT_TSFOOR | \ 00380 ATH9K_INT_GENTIMER) 00381 00382 struct ath_softc *sc = dev->priv; 00383 struct ath_hw *ah = sc->sc_ah; 00384 struct ath_common *common = ath9k_hw_common(ah); 00385 enum ath9k_int status; 00386 unsigned long timestamp = (currticks() * 1000 ) / TICKS_PER_SEC; 00387 int sched = 0; 00388 00389 /* 00390 * The hardware is not ready/present, don't 00391 * touch anything. Note this can happen early 00392 * on if the IRQ is shared. 00393 */ 00394 if (sc->sc_flags & SC_OP_INVALID) 00395 return; 00396 00397 00398 /* Check calibration */ 00399 if(timestamp >= (unsigned int)common->ani.timer && common->ani.timer) 00400 ath_ani_calibrate(sc); 00401 00402 /* Check tx_complete_work */ 00403 if(timestamp >= (unsigned int)sc->tx_complete_work_timer && sc->tx_complete_work_timer) 00404 sc->tx_complete_work(sc); 00405 00406 /* Check hw_pll_work */ 00407 if(timestamp >= (unsigned int)sc->hw_pll_work_timer && sc->hw_pll_work_timer) 00408 sc->hw_pll_work(sc); 00409 00410 /* shared irq, not for us */ 00411 00412 if (!ath9k_hw_intrpend(ah)) 00413 return; 00414 00415 /* 00416 * Figure out the reason(s) for the interrupt. Note 00417 * that the hal returns a pseudo-ISR that may include 00418 * bits we haven't explicitly enabled so we mask the 00419 * value to insure we only process bits we requested. 00420 */ 00421 ath9k_hw_getisr(ah, &status); /* NB: clears ISR too */ 00422 status &= ah->imask; /* discard unasked-for bits */ 00423 00424 /* 00425 * If there are no status bits set, then this interrupt was not 00426 * for me (should have been caught above). 00427 */ 00428 if (!status) 00429 return; 00430 00431 /* Cache the status */ 00432 sc->intrstatus = status; 00433 00434 if (status & SCHED_INTR) 00435 sched = 1; 00436 00437 /* 00438 * If a FATAL or RXORN interrupt is received, we have to reset the 00439 * chip immediately. 00440 */ 00441 if ((status & ATH9K_INT_FATAL) || (status & ATH9K_INT_RXORN)) 00442 goto chip_reset; 00443 00444 if (status & ATH9K_INT_TXURN) 00445 ath9k_hw_updatetxtriglevel(ah, 1); 00446 00447 if (!(ah->caps.hw_caps & ATH9K_HW_CAP_AUTOSLEEP)) 00448 if (status & ATH9K_INT_TIM_TIMER) { 00449 if (sc->ps_idle) 00450 goto chip_reset; 00451 /* Clear RxAbort bit so that we can 00452 * receive frames */ 00453 ath9k_setpower(sc, ATH9K_PM_AWAKE); 00454 ath9k_hw_setrxabort(sc->sc_ah, 0); 00455 sc->ps_flags |= PS_WAIT_FOR_BEACON; 00456 } 00457 00458 chip_reset: 00459 00460 if (sched) { 00461 /* turn off every interrupt */ 00462 ath9k_hw_disable_interrupts(ah); 00463 sc->intr_tq(sc); 00464 } 00465 00466 return; 00467 00468 #undef SCHED_INTR 00469 } 00470 00471 void ath_radio_disable(struct ath_softc *sc, struct net80211_device *dev) 00472 { 00473 struct ath_hw *ah = sc->sc_ah; 00474 struct net80211_channel *channel = dev->channels + dev->channel; 00475 int r; 00476 00477 sc->hw_pll_work_timer = 0; 00478 00479 /* 00480 * Keep the LED on when the radio is disabled 00481 * during idle unassociated state. 00482 */ 00483 if (!sc->ps_idle) { 00484 ath9k_hw_set_gpio(ah, ah->led_pin, 1); 00485 ath9k_hw_cfg_gpio_input(ah, ah->led_pin); 00486 } 00487 00488 /* Disable interrupts */ 00489 ath9k_hw_disable_interrupts(ah); 00490 00491 ath_drain_all_txq(sc, 0); /* clear pending tx frames */ 00492 00493 ath_stoprecv(sc); /* turn off frame recv */ 00494 ath_flushrecv(sc); /* flush recv queue */ 00495 00496 if (!ah->curchan) 00497 ah->curchan = ath9k_cmn_get_curchannel(dev, ah); 00498 00499 r = ath9k_hw_reset(ah, ah->curchan, ah->caldata, 0); 00500 if (r) { 00501 DBG("ath9k: " 00502 "Unable to reset channel (%d MHz), reset status %d\n", 00503 channel->center_freq, r); 00504 } 00505 00506 ath9k_hw_phy_disable(ah); 00507 00508 ath9k_hw_configpcipowersave(ah, 1, 1); 00509 } 00510 00511 int ath_reset(struct ath_softc *sc, int retry_tx) 00512 { 00513 struct ath_hw *ah = sc->sc_ah; 00514 struct ath_common *common = ath9k_hw_common(ah); 00515 int r; 00516 00517 sc->hw_busy_count = 0; 00518 00519 /* Stop ANI */ 00520 common->ani.timer = 0; 00521 00522 ath9k_hw_disable_interrupts(ah); 00523 ath_drain_all_txq(sc, retry_tx); 00524 00525 ath_stoprecv(sc); 00526 ath_flushrecv(sc); 00527 00528 r = ath9k_hw_reset(ah, sc->sc_ah->curchan, ah->caldata, 0); 00529 if (r) 00530 DBG("ath9k: " 00531 "Unable to reset hardware; reset status %d\n", r); 00532 00533 if (ath_startrecv(sc) != 0) 00534 DBG("ath9k: Unable to start recv logic\n"); 00535 00536 /* 00537 * We may be doing a reset in response to a request 00538 * that changes the channel so update any state that 00539 * might change as a result. 00540 */ 00541 ath9k_cmn_update_txpow(ah, sc->curtxpow, 00542 sc->config.txpowlimit, &sc->curtxpow); 00543 00544 ath9k_hw_set_interrupts(ah, ah->imask); 00545 00546 if (retry_tx) { 00547 int i; 00548 for (i = 0; i < ATH9K_NUM_TX_QUEUES; i++) { 00549 if (ATH_TXQ_SETUP(sc, i)) { 00550 ath_txq_schedule(sc, &sc->tx.txq[i]); 00551 } 00552 } 00553 } 00554 00555 /* Start ANI */ 00556 ath_start_ani(common); 00557 00558 return r; 00559 } 00560 00561 /**********************/ 00562 /* mac80211 callbacks */ 00563 /**********************/ 00564 00565 static int ath9k_start(struct net80211_device *dev) 00566 { 00567 struct ath_softc *sc = dev->priv; 00568 struct ath_hw *ah = sc->sc_ah; 00569 struct ath_common *common = ath9k_hw_common(ah); 00570 struct net80211_channel *curchan = dev->channels + dev->channel; 00571 struct ath9k_channel *init_channel; 00572 int r; 00573 00574 DBG("ath9k: " 00575 "Starting driver with initial channel: %d MHz\n", 00576 curchan->center_freq); 00577 00578 /* setup initial channel */ 00579 sc->chan_idx = curchan->hw_value; 00580 00581 init_channel = ath9k_cmn_get_curchannel(dev, ah); 00582 00583 /* Reset SERDES registers */ 00584 ath9k_hw_configpcipowersave(ah, 0, 0); 00585 00586 /* 00587 * The basic interface to setting the hardware in a good 00588 * state is ``reset''. On return the hardware is known to 00589 * be powered up and with interrupts disabled. This must 00590 * be followed by initialization of the appropriate bits 00591 * and then setup of the interrupt mask. 00592 */ 00593 r = ath9k_hw_reset(ah, init_channel, ah->caldata, 0); 00594 if (r) { 00595 DBG("ath9k: " 00596 "Unable to reset hardware; reset status %d (freq %d MHz)\n", 00597 r, curchan->center_freq); 00598 goto mutex_unlock; 00599 } 00600 00601 /* 00602 * This is needed only to setup initial state 00603 * but it's best done after a reset. 00604 */ 00605 ath9k_cmn_update_txpow(ah, sc->curtxpow, 00606 sc->config.txpowlimit, &sc->curtxpow); 00607 00608 /* 00609 * Setup the hardware after reset: 00610 * The receive engine is set going. 00611 * Frame transmit is handled entirely 00612 * in the frame output path; there's nothing to do 00613 * here except setup the interrupt mask. 00614 */ 00615 if (ath_startrecv(sc) != 0) { 00616 DBG("ath9k: Unable to start recv logic\n"); 00617 r = -EIO; 00618 goto mutex_unlock; 00619 } 00620 00621 /* Setup our intr mask. */ 00622 ah->imask = ATH9K_INT_TX | ATH9K_INT_RXEOL | 00623 ATH9K_INT_RXORN | ATH9K_INT_FATAL | 00624 ATH9K_INT_GLOBAL; 00625 00626 ah->imask |= ATH9K_INT_RX; 00627 00628 sc->sc_flags &= ~SC_OP_INVALID; 00629 sc->sc_ah->is_monitoring = 0; 00630 00631 ath9k_hw_set_interrupts(ah, ah->imask); 00632 00633 sc->tx_complete_work(sc); 00634 00635 if (ah->caps.pcie_lcr_extsync_en && common->bus_ops->extn_synch_en) 00636 common->bus_ops->extn_synch_en(common); 00637 00638 mutex_unlock: 00639 return r; 00640 } 00641 00642 static int ath9k_tx(struct net80211_device *dev, struct io_buffer *iob) 00643 { 00644 struct ath_softc *sc = dev->priv; 00645 struct ath_tx_control txctl; 00646 int ret = 0; 00647 00648 memset(&txctl, 0, sizeof(struct ath_tx_control)); 00649 txctl.txq = sc->tx.txq_map[0]; 00650 00651 DBGIO("ath9k: transmitting packet, iob: %p\n", iob); 00652 00653 ret = ath_tx_start(dev, iob, &txctl); 00654 if (ret) { 00655 DBG("ath9k: TX failed\n"); 00656 goto exit; 00657 } 00658 00659 return ret; 00660 exit: 00661 free_iob(iob); 00662 return ret; 00663 } 00664 00665 static void ath9k_stop(struct net80211_device *dev) 00666 { 00667 struct ath_softc *sc = dev->priv; 00668 struct ath_hw *ah = sc->sc_ah; 00669 00670 sc->tx_complete_work_timer = 0; 00671 sc->hw_pll_work_timer = 0; 00672 00673 if (sc->sc_flags & SC_OP_INVALID) { 00674 DBG("ath9k: Device not present\n"); 00675 return; 00676 } 00677 00678 /* prevent tasklets to enable interrupts once we disable them */ 00679 ah->imask &= ~ATH9K_INT_GLOBAL; 00680 00681 /* make sure h/w will not generate any interrupt 00682 * before setting the invalid flag. */ 00683 ath9k_hw_disable_interrupts(ah); 00684 00685 if (!(sc->sc_flags & SC_OP_INVALID)) { 00686 ath_drain_all_txq(sc, 0); 00687 ath_stoprecv(sc); 00688 ath9k_hw_phy_disable(ah); 00689 } else 00690 sc->rx.rxlink = NULL; 00691 00692 if (sc->rx.frag) { 00693 free_iob(sc->rx.frag); 00694 sc->rx.frag = NULL; 00695 } 00696 00697 /* disable HAL and put h/w to sleep */ 00698 ath9k_hw_disable(ah); 00699 ath9k_hw_configpcipowersave(ah, 1, 1); 00700 00701 ath_radio_disable(sc, dev); 00702 00703 sc->sc_flags |= SC_OP_INVALID; 00704 00705 DBG("ath9k: Driver halt\n"); 00706 } 00707 00708 static int ath9k_config(struct net80211_device *dev, int changed) 00709 { 00710 struct ath_softc *sc = dev->priv; 00711 struct ath_hw *ah = sc->sc_ah; 00712 00713 if ((changed & NET80211_CFG_RATE) || 00714 (changed & NET80211_CFG_PHY_PARAMS)) { 00715 int spmbl = (sc->sc_flags & SC_OP_PREAMBLE_SHORT) ? IEEE80211_TX_RC_USE_SHORT_PREAMBLE : 0; 00716 u16 rate = dev->rates[dev->rate]; 00717 u16 slowrate = dev->rates[dev->rtscts_rate]; 00718 int i; 00719 00720 for (i = 0; i < NET80211_MAX_RATES; i++) { 00721 if (sc->rates[i].bitrate == rate && 00722 (sc->rates[i].flags & spmbl)) 00723 sc->hw_rix = i; 00724 00725 if (sc->rates[i].bitrate == slowrate && 00726 (sc->rates[i].flags & spmbl)) 00727 sc->hw_rix = i; 00728 } 00729 } 00730 00731 ath9k_bss_info_changed(dev, changed); 00732 00733 if (changed & NET80211_CFG_CHANNEL) { 00734 struct net80211_channel *curchan = dev->channels + dev->channel; 00735 int pos = curchan->hw_value; 00736 int old_pos = -1; 00737 00738 if (ah->curchan) 00739 old_pos = ah->curchan - &ah->channels[0]; 00740 00741 sc->sc_flags &= ~SC_OP_OFFCHANNEL; 00742 00743 DBG2("ath9k: " 00744 "Set channel: %d MHz\n", 00745 curchan->center_freq); 00746 00747 ath9k_cmn_update_ichannel(&sc->sc_ah->channels[pos], 00748 curchan); 00749 00750 /* update survey stats for the old channel before switching */ 00751 ath_update_survey_stats(sc); 00752 00753 /* 00754 * If the operating channel changes, change the survey in-use flags 00755 * along with it. 00756 * Reset the survey data for the new channel, unless we're switching 00757 * back to the operating channel from an off-channel operation. 00758 */ 00759 if (sc->cur_survey != &sc->survey[pos]) { 00760 00761 if (sc->cur_survey) 00762 sc->cur_survey->filled &= ~SURVEY_INFO_IN_USE; 00763 00764 sc->cur_survey = &sc->survey[pos]; 00765 00766 memset(sc->cur_survey, 0, sizeof(struct survey_info)); 00767 sc->cur_survey->filled |= SURVEY_INFO_IN_USE; 00768 } else if (!(sc->survey[pos].filled & SURVEY_INFO_IN_USE)) { 00769 memset(&sc->survey[pos], 0, sizeof(struct survey_info)); 00770 } 00771 00772 if (ath_set_channel(sc, dev, &sc->sc_ah->channels[pos]) < 0) { 00773 DBG("ath9k: Unable to set channel\n"); 00774 return -EINVAL; 00775 } 00776 00777 /* 00778 * The most recent snapshot of channel->noisefloor for the old 00779 * channel is only available after the hardware reset. Copy it to 00780 * the survey stats now. 00781 */ 00782 if (old_pos >= 0) 00783 ath_update_survey_nf(sc, old_pos); 00784 } 00785 00786 if (changed & NET80211_CFG_CHANNEL) { 00787 DBG2("ath9k: " 00788 "Set power: %d\n", (dev->channels + dev->channel)->maxpower); 00789 sc->config.txpowlimit = 2 * (dev->channels + dev->channel)->maxpower; 00790 ath9k_cmn_update_txpow(ah, sc->curtxpow, 00791 sc->config.txpowlimit, &sc->curtxpow); 00792 } 00793 00794 return 0; 00795 } 00796 00797 static void ath9k_bss_iter(struct ath_softc *sc) 00798 { 00799 struct ath_common *common = ath9k_hw_common(sc->sc_ah); 00800 00801 if (common->dev->state & NET80211_ASSOCIATED) { 00802 sc->sc_flags |= SC_OP_PRIM_STA_VIF; 00803 memcpy(common->curbssid, common->dev->bssid, ETH_ALEN); 00804 common->curaid = common->dev->aid; 00805 ath9k_hw_write_associd(sc->sc_ah); 00806 DBG("ath9k: " 00807 "Bss Info ASSOC %d, bssid: %pM\n", 00808 common->dev->aid, common->curbssid); 00809 00810 /* 00811 * Request a re-configuration of Beacon related timers 00812 * on the receipt of the first Beacon frame (i.e., 00813 * after time sync with the AP). 00814 */ 00815 sc->ps_flags |= PS_BEACON_SYNC | PS_WAIT_FOR_BEACON; 00816 /* Reset rssi stats */ 00817 sc->last_rssi = ATH_RSSI_DUMMY_MARKER; 00818 sc->sc_ah->stats.avgbrssi = ATH_RSSI_DUMMY_MARKER; 00819 00820 sc->sc_flags |= SC_OP_ANI_RUN; 00821 ath_start_ani(common); 00822 } 00823 } 00824 00825 static void ath9k_config_bss(struct ath_softc *sc) 00826 { 00827 struct ath_common *common = ath9k_hw_common(sc->sc_ah); 00828 struct net80211_device *dev = common->dev; 00829 00830 /* Reconfigure bss info */ 00831 if (!(dev->state & NET80211_ASSOCIATED)) { 00832 DBG2("ath9k: " 00833 "ath9k: Bss Info DISASSOC %d, bssid %pM\n", 00834 common->curaid, common->curbssid); 00835 sc->sc_flags &= ~(SC_OP_PRIM_STA_VIF | SC_OP_BEACONS); 00836 memset(common->curbssid, 0, ETH_ALEN); 00837 common->curaid = 0; 00838 } 00839 00840 ath9k_bss_iter(sc); 00841 00842 /* 00843 * None of station vifs are associated. 00844 * Clear bssid & aid 00845 */ 00846 if (!(sc->sc_flags & SC_OP_PRIM_STA_VIF)) { 00847 ath9k_hw_write_associd(sc->sc_ah); 00848 /* Stop ANI */ 00849 sc->sc_flags &= ~SC_OP_ANI_RUN; 00850 common->ani.timer = 0; 00851 } 00852 } 00853 00854 static void ath9k_bss_info_changed(struct net80211_device *dev, 00855 u32 changed) 00856 { 00857 struct ath_softc *sc = dev->priv; 00858 struct ath_hw *ah = sc->sc_ah; 00859 struct ath_common *common = ath9k_hw_common(ah); 00860 int slottime; 00861 00862 if (changed & NET80211_CFG_ASSOC) { 00863 ath9k_config_bss(sc); 00864 00865 DBG2("ath9k: BSSID: %pM aid: 0x%x\n", 00866 common->curbssid, common->curaid); 00867 } 00868 00869 if (changed & NET80211_CFG_PHY_PARAMS) { 00870 if (dev->phy_flags & NET80211_PHY_USE_PROTECTION) 00871 slottime = 9; 00872 else 00873 slottime = 20; 00874 ah->slottime = slottime; 00875 ath9k_hw_init_global_settings(ah); 00876 00877 DBG2("ath9k: BSS Changed PREAMBLE %d\n", 00878 !!(dev->phy_flags & NET80211_PHY_USE_SHORT_PREAMBLE)); 00879 if (dev->phy_flags & NET80211_PHY_USE_SHORT_PREAMBLE) 00880 sc->sc_flags |= SC_OP_PREAMBLE_SHORT; 00881 else 00882 sc->sc_flags &= ~SC_OP_PREAMBLE_SHORT; 00883 00884 DBG2("ath9k: BSS Changed CTS PROT %d\n", 00885 !!(dev->phy_flags & NET80211_PHY_USE_PROTECTION)); 00886 if ((dev->phy_flags & NET80211_PHY_USE_PROTECTION) && 00887 (dev->channels + dev->channel)->band != NET80211_BAND_5GHZ) 00888 sc->sc_flags |= SC_OP_PROTECT_ENABLE; 00889 else 00890 sc->sc_flags &= ~SC_OP_PROTECT_ENABLE; 00891 } 00892 } 00893 00894 static void ath9k_poll(struct net80211_device *dev) 00895 { 00896 ath_isr(dev); 00897 } 00898 00899 static void ath9k_irq(struct net80211_device *dev, int enable) 00900 { 00901 struct ath_softc *sc = dev->priv; 00902 struct ath_hw *ah = sc->sc_ah; 00903 00904 ah->ah_ier = enable ? AR_IER_ENABLE : AR_IER_DISABLE; 00905 00906 ath9k_hw_set_interrupts(ah, ah->imask); 00907 } 00908 00909 struct net80211_device_operations ath9k_ops = { 00910 .transmit = ath9k_tx, 00911 .open = ath9k_start, 00912 .close = ath9k_stop, 00913 .config = ath9k_config, 00914 .poll = ath9k_poll, 00915 .irq = ath9k_irq, 00916 };