Add qemu 2.4.0
[kvmfornfv.git] / qemu / roms / ipxe / src / drivers / net / ath / ath9k / ath9k_main.c
1 /*
2  * Copyright (c) 2008-2011 Atheros Communications Inc.
3  *
4  * Modified for iPXE by Scott K Logan <logans@cottsay.net> July 2011
5  * Original from Linux kernel 3.0.1
6  *
7  * Permission to use, copy, modify, and/or distribute this software for any
8  * purpose with or without fee is hereby granted, provided that the above
9  * copyright notice and this permission notice appear in all copies.
10  *
11  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
12  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
13  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
14  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
15  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
16  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
17  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
18  */
19
20 #include <ipxe/io.h>
21
22 #include "ath9k.h"
23
24 static void ath9k_bss_info_changed(struct net80211_device *dev, u32 changed);
25
26 int ath9k_setpower(struct ath_softc *sc, enum ath9k_power_mode mode)
27 {
28         int ret;
29
30         ret = ath9k_hw_setpower(sc->sc_ah, mode);
31
32         return ret;
33 }
34
35 static void ath_start_ani(struct ath_common *common)
36 {
37         struct ath_hw *ah = common->ah;
38         unsigned long timestamp = ( currticks() * 1000 ) / TICKS_PER_SEC;
39         struct ath_softc *sc = (struct ath_softc *) common->priv;
40
41         if (!(sc->sc_flags & SC_OP_ANI_RUN))
42                 return;
43
44         if (sc->sc_flags & SC_OP_OFFCHANNEL)
45                 return;
46
47         common->ani.longcal_timer = timestamp;
48         common->ani.shortcal_timer = timestamp;
49         common->ani.checkani_timer = timestamp;
50
51         common->ani.timer = timestamp + ah->config.ani_poll_interval;
52 }
53
54 static void ath_update_survey_nf(struct ath_softc *sc, int channel)
55 {
56         struct ath_hw *ah = sc->sc_ah;
57         struct ath9k_channel *chan = &ah->channels[channel];
58         struct survey_info *survey = &sc->survey[channel];
59
60         if (chan->noisefloor) {
61                 survey->filled |= SURVEY_INFO_NOISE_DBM;
62                 survey->noise = chan->noisefloor;
63         }
64 }
65
66 /*
67  * Updates the survey statistics and returns the busy time since last
68  * update in %, if the measurement duration was long enough for the
69  * result to be useful, -1 otherwise.
70  */
71 static int ath_update_survey_stats(struct ath_softc *sc)
72 {
73         struct ath_hw *ah = sc->sc_ah;
74         struct ath_common *common = ath9k_hw_common(ah);
75         int pos = ah->curchan - &ah->channels[0];
76         struct survey_info *survey = &sc->survey[pos];
77         struct ath_cycle_counters *cc = &common->cc_survey;
78         unsigned int div = common->clockrate * 1000;
79         int ret = 0;
80
81         if (!ah->curchan)
82                 return -1;
83
84         if (ah->power_mode == ATH9K_PM_AWAKE)
85                 ath_hw_cycle_counters_update(common);
86
87         if (cc->cycles > 0) {
88                 survey->filled |= SURVEY_INFO_CHANNEL_TIME |
89                         SURVEY_INFO_CHANNEL_TIME_BUSY |
90                         SURVEY_INFO_CHANNEL_TIME_RX |
91                         SURVEY_INFO_CHANNEL_TIME_TX;
92                 survey->channel_time += cc->cycles / div;
93                 survey->channel_time_busy += cc->rx_busy / div;
94                 survey->channel_time_rx += cc->rx_frame / div;
95                 survey->channel_time_tx += cc->tx_frame / div;
96         }
97
98         if (cc->cycles < div)
99                 return -1;
100
101         if (cc->cycles > 0)
102                 ret = cc->rx_busy * 100 / cc->cycles;
103
104         memset(cc, 0, sizeof(*cc));
105
106         ath_update_survey_nf(sc, pos);
107
108         return ret;
109 }
110
111 /*
112  * Set/change channels.  If the channel is really being changed, it's done
113  * by reseting the chip.  To accomplish this we must first cleanup any pending
114  * DMA, then restart stuff.
115 */
116 int ath_set_channel(struct ath_softc *sc, struct net80211_device *dev,
117                     struct ath9k_channel *hchan)
118 {
119         struct ath_hw *ah = sc->sc_ah;
120         struct ath_common *common = ath9k_hw_common(ah);
121         int fastcc __unused = 1, stopped __unused;
122         struct net80211_channel *channel = dev->channels + dev->channel;
123         struct ath9k_hw_cal_data *caldata = NULL;
124         int r;
125
126         if (sc->sc_flags & SC_OP_INVALID)
127                 return -EIO;
128
129         sc->hw_busy_count = 0;
130
131         common->ani.timer = 0;
132         sc->tx_complete_work_timer = 0;
133         sc->hw_pll_work_timer = 0;
134
135         /*
136          * This is only performed if the channel settings have
137          * actually changed.
138          *
139          * To switch channels clear any pending DMA operations;
140          * wait long enough for the RX fifo to drain, reset the
141          * hardware at the new frequency, and then re-enable
142          * the relevant bits of the h/w.
143          */
144         ath9k_hw_disable_interrupts(ah);
145         stopped = ath_drain_all_txq(sc, 0);
146
147         if (!ath_stoprecv(sc))
148                 stopped = 0;
149
150         if (!ath9k_hw_check_alive(ah))
151                 stopped = 0;
152
153         /* XXX: do not flush receive queue here. We don't want
154          * to flush data frames already in queue because of
155          * changing channel. */
156
157         if (!(sc->sc_flags & SC_OP_OFFCHANNEL))
158                 caldata = &sc->caldata;
159
160         DBG2("ath9k: "
161                 "(%d MHz) -> (%d MHz)\n",
162                 sc->sc_ah->curchan->channel,
163                 channel->center_freq);
164
165         r = ath9k_hw_reset(ah, hchan, caldata, fastcc);
166         if (r) {
167                 DBG("ath9k: "
168                         "Unable to reset channel (%d MHz), reset status %d\n",
169                         channel->center_freq, r);
170                 goto ps_restore;
171         }
172
173         if (ath_startrecv(sc) != 0) {
174                 DBG("ath9k: Unable to restart recv logic\n");
175                 r = -EIO;
176                 goto ps_restore;
177         }
178
179         ath9k_cmn_update_txpow(ah, sc->curtxpow,
180                                sc->config.txpowlimit, &sc->curtxpow);
181         ath9k_hw_set_interrupts(ah, ah->imask);
182
183         if (!(sc->sc_flags & (SC_OP_OFFCHANNEL))) {
184                 sc->tx_complete_work(sc);
185                 sc->hw_pll_work_timer = (currticks() * 1000 ) / TICKS_PER_SEC + 500;
186                 ath_start_ani(common);
187         }
188
189  ps_restore:
190         return r;
191 }
192
193 /*
194  *  This routine performs the periodic noise floor calibration function
195  *  that is used to adjust and optimize the chip performance.  This
196  *  takes environmental changes (location, temperature) into account.
197  *  When the task is complete, it reschedules itself depending on the
198  *  appropriate interval that was calculated.
199  */
200 void ath_ani_calibrate(struct ath_softc *sc)
201 {
202         struct ath_hw *ah = sc->sc_ah;
203         struct ath_common *common = ath9k_hw_common(ah);
204         int longcal = 0;
205         int shortcal = 0;
206         int aniflag = 0;
207         unsigned int timestamp = (currticks() * 1000 ) / TICKS_PER_SEC;
208         u32 cal_interval, short_cal_interval, long_cal_interval;
209
210         if (ah->caldata && ah->caldata->nfcal_interference)
211                 long_cal_interval = ATH_LONG_CALINTERVAL_INT;
212         else
213                 long_cal_interval = ATH_LONG_CALINTERVAL;
214
215         short_cal_interval = ATH_STA_SHORT_CALINTERVAL;
216
217         /* Only calibrate if awake */
218         if (sc->sc_ah->power_mode != ATH9K_PM_AWAKE)
219                 goto set_timer;
220
221         /* Long calibration runs independently of short calibration. */
222         if ((timestamp - common->ani.longcal_timer) >= long_cal_interval) {
223                 longcal = 1;
224                 DBG2("ath9k: longcal @%d\n", timestamp);
225                 common->ani.longcal_timer = timestamp;
226         }
227
228         /* Short calibration applies only while caldone is false */
229         if (!common->ani.caldone) {
230                 if ((timestamp - common->ani.shortcal_timer) >= short_cal_interval) {
231                         shortcal = 1;
232                         DBG2("ath9k: "
233                                 "shortcal @%d\n", timestamp);
234                         common->ani.shortcal_timer = timestamp;
235                         common->ani.resetcal_timer = timestamp;
236                 }
237         } else {
238                 if ((timestamp - common->ani.resetcal_timer) >=
239                     ATH_RESTART_CALINTERVAL) {
240                         common->ani.caldone = ath9k_hw_reset_calvalid(ah);
241                         if (common->ani.caldone)
242                                 common->ani.resetcal_timer = timestamp;
243                 }
244         }
245
246         /* Verify whether we must check ANI */
247         if ((timestamp - common->ani.checkani_timer) >=
248              ah->config.ani_poll_interval) {
249                 aniflag = 1;
250                 common->ani.checkani_timer = timestamp;
251         }
252
253         /* Skip all processing if there's nothing to do. */
254         if (longcal || shortcal || aniflag) {
255                 /* Call ANI routine if necessary */
256                 if (aniflag) {
257                         ath9k_hw_ani_monitor(ah, ah->curchan);
258                         ath_update_survey_stats(sc);
259                 }
260
261                 /* Perform calibration if necessary */
262                 if (longcal || shortcal) {
263                         common->ani.caldone =
264                                 ath9k_hw_calibrate(ah,
265                                                    ah->curchan,
266                                                    common->rx_chainmask,
267                                                    longcal);
268                 }
269         }
270
271 set_timer:
272         /*
273         * Set timer interval based on previous results.
274         * The interval must be the shortest necessary to satisfy ANI,
275         * short calibration and long calibration.
276         */
277         cal_interval = ATH_LONG_CALINTERVAL;
278         if (sc->sc_ah->config.enable_ani)
279                 cal_interval = min(cal_interval,
280                                    (u32)ah->config.ani_poll_interval);
281         if (!common->ani.caldone)
282                 cal_interval = min(cal_interval, (u32)short_cal_interval);
283
284         common->ani.timer = timestamp + cal_interval;
285 }
286
287 void ath_hw_check(struct ath_softc *sc)
288 {
289         int busy;
290
291         if (ath9k_hw_check_alive(sc->sc_ah))
292                 goto out;
293
294         busy = ath_update_survey_stats(sc);
295
296         DBG("ath9k: Possible baseband hang, "
297                 "busy=%d (try %d)\n", busy, sc->hw_busy_count + 1);
298         if (busy >= 99) {
299                 if (++sc->hw_busy_count >= 3)
300                         ath_reset(sc, 1);
301         } else if (busy >= 0)
302                 sc->hw_busy_count = 0;
303
304 out:
305         return;
306 }
307
308 static void ath_hw_pll_rx_hang_check(struct ath_softc *sc, u32 pll_sqsum)
309 {
310         static int count;
311
312         if (pll_sqsum >= 0x40000) {
313                 count++;
314                 if (count == 3) {
315                         /* Rx is hung for more than 500ms. Reset it */
316                         DBG("ath9k: "
317                                 "Possible RX hang, resetting");
318                         ath_reset(sc, 1);
319                         count = 0;
320                 }
321         } else
322                 count = 0;
323 }
324
325 void ath_hw_pll_work(struct ath_softc *sc)
326 {
327         u32 pll_sqsum;
328
329         if (AR_SREV_9485(sc->sc_ah)) {
330                 pll_sqsum = ar9003_get_pll_sqsum_dvc(sc->sc_ah);
331
332                 ath_hw_pll_rx_hang_check(sc, pll_sqsum);
333
334                 sc->hw_pll_work_timer = (currticks() * 1000 ) / TICKS_PER_SEC + 200;
335         }
336 }
337
338
339 void ath9k_tasklet(struct ath_softc *sc)
340 {
341         struct ath_hw *ah = sc->sc_ah;
342
343         u32 status = sc->intrstatus;
344         u32 rxmask;
345
346         if ((status & ATH9K_INT_FATAL) ||
347             (status & ATH9K_INT_BB_WATCHDOG)) {
348                 ath_reset(sc, 1);
349                 return;
350         }
351
352         rxmask = (ATH9K_INT_RX | ATH9K_INT_RXEOL | ATH9K_INT_RXORN);
353
354         if (status & rxmask) {
355                 ath_rx_tasklet(sc, 0, 0);
356         }
357
358         if (status & ATH9K_INT_TX) {
359                 ath_tx_tasklet(sc);
360         }
361
362         /* re-enable hardware interrupt */
363         ath9k_hw_enable_interrupts(ah);
364 }
365
366 void ath_isr(struct net80211_device *dev)
367 {
368 #define SCHED_INTR (                            \
369                 ATH9K_INT_FATAL |               \
370                 ATH9K_INT_BB_WATCHDOG |         \
371                 ATH9K_INT_RXORN |               \
372                 ATH9K_INT_RXEOL |               \
373                 ATH9K_INT_RX |                  \
374                 ATH9K_INT_RXLP |                \
375                 ATH9K_INT_RXHP |                \
376                 ATH9K_INT_TX |                  \
377                 ATH9K_INT_BMISS |               \
378                 ATH9K_INT_CST |                 \
379                 ATH9K_INT_TSFOOR |              \
380                 ATH9K_INT_GENTIMER)
381
382         struct ath_softc *sc = dev->priv;
383         struct ath_hw *ah = sc->sc_ah;
384         struct ath_common *common = ath9k_hw_common(ah);
385         enum ath9k_int status;
386         unsigned long timestamp = (currticks() * 1000 ) / TICKS_PER_SEC;
387         int sched = 0;
388
389         /*
390          * The hardware is not ready/present, don't
391          * touch anything. Note this can happen early
392          * on if the IRQ is shared.
393          */
394         if (sc->sc_flags & SC_OP_INVALID)
395                 return;
396
397
398         /* Check calibration */
399         if(timestamp >= (unsigned int)common->ani.timer && common->ani.timer)
400                 ath_ani_calibrate(sc);
401
402         /* Check tx_complete_work */
403         if(timestamp >= (unsigned int)sc->tx_complete_work_timer && sc->tx_complete_work_timer)
404                 sc->tx_complete_work(sc);
405
406         /* Check hw_pll_work */
407         if(timestamp >= (unsigned int)sc->hw_pll_work_timer && sc->hw_pll_work_timer)
408                 sc->hw_pll_work(sc);
409
410         /* shared irq, not for us */
411
412         if (!ath9k_hw_intrpend(ah))
413                 return;
414
415         /*
416          * Figure out the reason(s) for the interrupt.  Note
417          * that the hal returns a pseudo-ISR that may include
418          * bits we haven't explicitly enabled so we mask the
419          * value to insure we only process bits we requested.
420          */
421         ath9k_hw_getisr(ah, &status);   /* NB: clears ISR too */
422         status &= ah->imask;    /* discard unasked-for bits */
423
424         /*
425          * If there are no status bits set, then this interrupt was not
426          * for me (should have been caught above).
427          */
428         if (!status)
429                 return;
430
431         /* Cache the status */
432         sc->intrstatus = status;
433
434         if (status & SCHED_INTR)
435                 sched = 1;
436
437         /*
438          * If a FATAL or RXORN interrupt is received, we have to reset the
439          * chip immediately.
440          */
441         if ((status & ATH9K_INT_FATAL) || (status & ATH9K_INT_RXORN))
442                 goto chip_reset;
443
444         if (status & ATH9K_INT_TXURN)
445                 ath9k_hw_updatetxtriglevel(ah, 1);
446
447         if (!(ah->caps.hw_caps & ATH9K_HW_CAP_AUTOSLEEP))
448                 if (status & ATH9K_INT_TIM_TIMER) {
449                         if (sc->ps_idle)
450                                 goto chip_reset;
451                         /* Clear RxAbort bit so that we can
452                          * receive frames */
453                         ath9k_setpower(sc, ATH9K_PM_AWAKE);
454                         ath9k_hw_setrxabort(sc->sc_ah, 0);
455                         sc->ps_flags |= PS_WAIT_FOR_BEACON;
456                 }
457
458 chip_reset:
459
460         if (sched) {
461                 /* turn off every interrupt */
462                 ath9k_hw_disable_interrupts(ah);
463                 sc->intr_tq(sc);
464         }
465
466         return;
467
468 #undef SCHED_INTR
469 }
470
471 void ath_radio_disable(struct ath_softc *sc, struct net80211_device *dev)
472 {
473         struct ath_hw *ah = sc->sc_ah;
474         struct net80211_channel *channel = dev->channels + dev->channel;
475         int r;
476
477         sc->hw_pll_work_timer = 0;
478
479         /*
480          * Keep the LED on when the radio is disabled
481          * during idle unassociated state.
482          */
483         if (!sc->ps_idle) {
484                 ath9k_hw_set_gpio(ah, ah->led_pin, 1);
485                 ath9k_hw_cfg_gpio_input(ah, ah->led_pin);
486         }
487
488         /* Disable interrupts */
489         ath9k_hw_disable_interrupts(ah);
490
491         ath_drain_all_txq(sc, 0);       /* clear pending tx frames */
492
493         ath_stoprecv(sc);               /* turn off frame recv */
494         ath_flushrecv(sc);              /* flush recv queue */
495
496         if (!ah->curchan)
497                 ah->curchan = ath9k_cmn_get_curchannel(dev, ah);
498
499         r = ath9k_hw_reset(ah, ah->curchan, ah->caldata, 0);
500         if (r) {
501                 DBG("ath9k: "
502                         "Unable to reset channel (%d MHz), reset status %d\n",
503                         channel->center_freq, r);
504         }
505
506         ath9k_hw_phy_disable(ah);
507
508         ath9k_hw_configpcipowersave(ah, 1, 1);
509 }
510
511 int ath_reset(struct ath_softc *sc, int retry_tx)
512 {
513         struct ath_hw *ah = sc->sc_ah;
514         struct ath_common *common = ath9k_hw_common(ah);
515         int r;
516
517         sc->hw_busy_count = 0;
518
519         /* Stop ANI */
520         common->ani.timer = 0;
521
522         ath9k_hw_disable_interrupts(ah);
523         ath_drain_all_txq(sc, retry_tx);
524
525         ath_stoprecv(sc);
526         ath_flushrecv(sc);
527
528         r = ath9k_hw_reset(ah, sc->sc_ah->curchan, ah->caldata, 0);
529         if (r)
530                 DBG("ath9k: "
531                         "Unable to reset hardware; reset status %d\n", r);
532
533         if (ath_startrecv(sc) != 0)
534                 DBG("ath9k: Unable to start recv logic\n");
535
536         /*
537          * We may be doing a reset in response to a request
538          * that changes the channel so update any state that
539          * might change as a result.
540          */
541         ath9k_cmn_update_txpow(ah, sc->curtxpow,
542                                sc->config.txpowlimit, &sc->curtxpow);
543
544         ath9k_hw_set_interrupts(ah, ah->imask);
545
546         if (retry_tx) {
547                 int i;
548                 for (i = 0; i < ATH9K_NUM_TX_QUEUES; i++) {
549                         if (ATH_TXQ_SETUP(sc, i)) {
550                                 ath_txq_schedule(sc, &sc->tx.txq[i]);
551                         }
552                 }
553         }
554
555         /* Start ANI */
556         ath_start_ani(common);
557
558         return r;
559 }
560
561 /**********************/
562 /* mac80211 callbacks */
563 /**********************/
564
565 static int ath9k_start(struct net80211_device *dev)
566 {
567         struct ath_softc *sc = dev->priv;
568         struct ath_hw *ah = sc->sc_ah;
569         struct ath_common *common = ath9k_hw_common(ah);
570         struct net80211_channel *curchan = dev->channels + dev->channel;
571         struct ath9k_channel *init_channel;
572         int r;
573
574         DBG("ath9k: "
575                 "Starting driver with initial channel: %d MHz\n",
576                 curchan->center_freq);
577
578         /* setup initial channel */
579         sc->chan_idx = curchan->hw_value;
580
581         init_channel = ath9k_cmn_get_curchannel(dev, ah);
582
583         /* Reset SERDES registers */
584         ath9k_hw_configpcipowersave(ah, 0, 0);
585
586         /*
587          * The basic interface to setting the hardware in a good
588          * state is ``reset''.  On return the hardware is known to
589          * be powered up and with interrupts disabled.  This must
590          * be followed by initialization of the appropriate bits
591          * and then setup of the interrupt mask.
592          */
593         r = ath9k_hw_reset(ah, init_channel, ah->caldata, 0);
594         if (r) {
595                 DBG("ath9k: "
596                         "Unable to reset hardware; reset status %d (freq %d MHz)\n",
597                         r, curchan->center_freq);
598                 goto mutex_unlock;
599         }
600
601         /*
602          * This is needed only to setup initial state
603          * but it's best done after a reset.
604          */
605         ath9k_cmn_update_txpow(ah, sc->curtxpow,
606                         sc->config.txpowlimit, &sc->curtxpow);
607
608         /*
609          * Setup the hardware after reset:
610          * The receive engine is set going.
611          * Frame transmit is handled entirely
612          * in the frame output path; there's nothing to do
613          * here except setup the interrupt mask.
614          */
615         if (ath_startrecv(sc) != 0) {
616                 DBG("ath9k: Unable to start recv logic\n");
617                 r = -EIO;
618                 goto mutex_unlock;
619         }
620
621         /* Setup our intr mask. */
622         ah->imask = ATH9K_INT_TX | ATH9K_INT_RXEOL |
623                     ATH9K_INT_RXORN | ATH9K_INT_FATAL |
624                     ATH9K_INT_GLOBAL;
625
626         ah->imask |= ATH9K_INT_RX;
627
628         sc->sc_flags &= ~SC_OP_INVALID;
629         sc->sc_ah->is_monitoring = 0;
630
631         ath9k_hw_set_interrupts(ah, ah->imask);
632
633         sc->tx_complete_work(sc);
634
635         if (ah->caps.pcie_lcr_extsync_en && common->bus_ops->extn_synch_en)
636                 common->bus_ops->extn_synch_en(common);
637
638 mutex_unlock:
639         return r;
640 }
641
642 static int ath9k_tx(struct net80211_device *dev, struct io_buffer *iob)
643 {
644         struct ath_softc *sc = dev->priv;
645         struct ath_tx_control txctl;
646         int ret = 0;
647
648         memset(&txctl, 0, sizeof(struct ath_tx_control));
649         txctl.txq = sc->tx.txq_map[0];
650
651         DBGIO("ath9k: transmitting packet, iob: %p\n", iob);
652
653         ret = ath_tx_start(dev, iob, &txctl);
654         if (ret) {
655                 DBG("ath9k: TX failed\n");
656                 goto exit;
657         }
658
659         return ret;
660 exit:
661         free_iob(iob);
662         return ret;
663 }
664
665 static void ath9k_stop(struct net80211_device *dev)
666 {
667         struct ath_softc *sc = dev->priv;
668         struct ath_hw *ah = sc->sc_ah;
669
670         sc->tx_complete_work_timer = 0;
671         sc->hw_pll_work_timer = 0;
672
673         if (sc->sc_flags & SC_OP_INVALID) {
674                 DBG("ath9k: Device not present\n");
675                 return;
676         }
677
678         /* prevent tasklets to enable interrupts once we disable them */
679         ah->imask &= ~ATH9K_INT_GLOBAL;
680
681         /* make sure h/w will not generate any interrupt
682          * before setting the invalid flag. */
683         ath9k_hw_disable_interrupts(ah);
684
685         if (!(sc->sc_flags & SC_OP_INVALID)) {
686                 ath_drain_all_txq(sc, 0);
687                 ath_stoprecv(sc);
688                 ath9k_hw_phy_disable(ah);
689         } else
690                 sc->rx.rxlink = NULL;
691
692         if (sc->rx.frag) {
693                 free_iob(sc->rx.frag);
694                 sc->rx.frag = NULL;
695         }
696
697         /* disable HAL and put h/w to sleep */
698         ath9k_hw_disable(ah);
699         ath9k_hw_configpcipowersave(ah, 1, 1);
700
701         ath_radio_disable(sc, dev);
702
703         sc->sc_flags |= SC_OP_INVALID;
704
705         DBG("ath9k: Driver halt\n");
706 }
707
708 static int ath9k_config(struct net80211_device *dev, int changed)
709 {
710         struct ath_softc *sc = dev->priv;
711         struct ath_hw *ah = sc->sc_ah;
712
713         if ((changed & NET80211_CFG_RATE) ||
714                         (changed & NET80211_CFG_PHY_PARAMS)) {
715                 int spmbl = (sc->sc_flags & SC_OP_PREAMBLE_SHORT) ? IEEE80211_TX_RC_USE_SHORT_PREAMBLE : 0;
716                 u16 rate = dev->rates[dev->rate];
717                 u16 slowrate = dev->rates[dev->rtscts_rate];
718                 int i;
719
720                 for (i = 0; i < NET80211_MAX_RATES; i++) {
721                         if (sc->rates[i].bitrate == rate &&
722                             (sc->rates[i].flags & spmbl))
723                                 sc->hw_rix = i;
724
725                         if (sc->rates[i].bitrate == slowrate &&
726                             (sc->rates[i].flags & spmbl))
727                                 sc->hw_rix = i;
728                 }
729         }
730
731         ath9k_bss_info_changed(dev, changed);
732
733         if (changed & NET80211_CFG_CHANNEL) {
734                 struct net80211_channel *curchan = dev->channels + dev->channel;
735                 int pos = curchan->hw_value;
736                 int old_pos = -1;
737
738                 if (ah->curchan)
739                         old_pos = ah->curchan - &ah->channels[0];
740
741                 sc->sc_flags &= ~SC_OP_OFFCHANNEL;
742
743                 DBG2("ath9k: "
744                         "Set channel: %d MHz\n",
745                         curchan->center_freq);
746
747                 ath9k_cmn_update_ichannel(&sc->sc_ah->channels[pos],
748                                           curchan);
749
750                 /* update survey stats for the old channel before switching */
751                 ath_update_survey_stats(sc);
752
753                 /*
754                  * If the operating channel changes, change the survey in-use flags
755                  * along with it.
756                  * Reset the survey data for the new channel, unless we're switching
757                  * back to the operating channel from an off-channel operation.
758                  */
759                 if (sc->cur_survey != &sc->survey[pos]) {
760
761                         if (sc->cur_survey)
762                                 sc->cur_survey->filled &= ~SURVEY_INFO_IN_USE;
763
764                         sc->cur_survey = &sc->survey[pos];
765
766                         memset(sc->cur_survey, 0, sizeof(struct survey_info));
767                         sc->cur_survey->filled |= SURVEY_INFO_IN_USE;
768                 } else if (!(sc->survey[pos].filled & SURVEY_INFO_IN_USE)) {
769                         memset(&sc->survey[pos], 0, sizeof(struct survey_info));
770                 }
771
772                 if (ath_set_channel(sc, dev, &sc->sc_ah->channels[pos]) < 0) {
773                         DBG("ath9k: Unable to set channel\n");
774                         return -EINVAL;
775                 }
776
777                 /*
778                  * The most recent snapshot of channel->noisefloor for the old
779                  * channel is only available after the hardware reset. Copy it to
780                  * the survey stats now.
781                  */
782                 if (old_pos >= 0)
783                         ath_update_survey_nf(sc, old_pos);
784         }
785
786         if (changed & NET80211_CFG_CHANNEL) {
787                 DBG2("ath9k: "
788                         "Set power: %d\n", (dev->channels + dev->channel)->maxpower);
789                 sc->config.txpowlimit = 2 * (dev->channels + dev->channel)->maxpower;
790                 ath9k_cmn_update_txpow(ah, sc->curtxpow,
791                                        sc->config.txpowlimit, &sc->curtxpow);
792         }
793
794         return 0;
795 }
796
797 static void ath9k_bss_iter(struct ath_softc *sc)
798 {
799         struct ath_common *common = ath9k_hw_common(sc->sc_ah);
800
801         if (common->dev->state & NET80211_ASSOCIATED) {
802                 sc->sc_flags |= SC_OP_PRIM_STA_VIF;
803                 memcpy(common->curbssid, common->dev->bssid, ETH_ALEN);
804                 common->curaid = common->dev->aid;
805                 ath9k_hw_write_associd(sc->sc_ah);
806                 DBG("ath9k: "
807                         "Bss Info ASSOC %d, bssid: %pM\n",
808                         common->dev->aid, common->curbssid);
809
810                 /*
811                  * Request a re-configuration of Beacon related timers
812                  * on the receipt of the first Beacon frame (i.e.,
813                  * after time sync with the AP).
814                  */
815                 sc->ps_flags |= PS_BEACON_SYNC | PS_WAIT_FOR_BEACON;
816                 /* Reset rssi stats */
817                 sc->last_rssi = ATH_RSSI_DUMMY_MARKER;
818                 sc->sc_ah->stats.avgbrssi = ATH_RSSI_DUMMY_MARKER;
819
820                 sc->sc_flags |= SC_OP_ANI_RUN;
821                 ath_start_ani(common);
822         }
823 }
824
825 static void ath9k_config_bss(struct ath_softc *sc)
826 {
827         struct ath_common *common = ath9k_hw_common(sc->sc_ah);
828         struct net80211_device *dev = common->dev;
829
830         /* Reconfigure bss info */
831         if (!(dev->state & NET80211_ASSOCIATED)) {
832                 DBG2("ath9k: "
833                         "ath9k: Bss Info DISASSOC %d, bssid %pM\n",
834                         common->curaid, common->curbssid);
835                 sc->sc_flags &= ~(SC_OP_PRIM_STA_VIF | SC_OP_BEACONS);
836                 memset(common->curbssid, 0, ETH_ALEN);
837                 common->curaid = 0;
838         }
839
840         ath9k_bss_iter(sc);
841
842         /*
843          * None of station vifs are associated.
844          * Clear bssid & aid
845          */
846         if (!(sc->sc_flags & SC_OP_PRIM_STA_VIF)) {
847                 ath9k_hw_write_associd(sc->sc_ah);
848                 /* Stop ANI */
849                 sc->sc_flags &= ~SC_OP_ANI_RUN;
850                 common->ani.timer = 0;
851         }
852 }
853
854 static void ath9k_bss_info_changed(struct net80211_device *dev,
855                                    u32 changed)
856 {
857         struct ath_softc *sc = dev->priv;
858         struct ath_hw *ah = sc->sc_ah;
859         struct ath_common *common = ath9k_hw_common(ah);
860         int slottime;
861
862         if (changed & NET80211_CFG_ASSOC) {
863                 ath9k_config_bss(sc);
864
865                 DBG2("ath9k: BSSID: %pM aid: 0x%x\n",
866                         common->curbssid, common->curaid);
867         }
868
869         if (changed & NET80211_CFG_PHY_PARAMS) {
870                 if (dev->phy_flags & NET80211_PHY_USE_PROTECTION)
871                         slottime = 9;
872                 else
873                         slottime = 20;
874                 ah->slottime = slottime;
875                 ath9k_hw_init_global_settings(ah);
876
877                 DBG2("ath9k: BSS Changed PREAMBLE %d\n",
878                                 !!(dev->phy_flags & NET80211_PHY_USE_SHORT_PREAMBLE));
879                 if (dev->phy_flags & NET80211_PHY_USE_SHORT_PREAMBLE)
880                         sc->sc_flags |= SC_OP_PREAMBLE_SHORT;
881                 else
882                         sc->sc_flags &= ~SC_OP_PREAMBLE_SHORT;
883
884                 DBG2("ath9k: BSS Changed CTS PROT %d\n",
885                         !!(dev->phy_flags & NET80211_PHY_USE_PROTECTION));
886                 if ((dev->phy_flags & NET80211_PHY_USE_PROTECTION) &&
887                     (dev->channels + dev->channel)->band != NET80211_BAND_5GHZ)
888                         sc->sc_flags |= SC_OP_PROTECT_ENABLE;
889                 else
890                         sc->sc_flags &= ~SC_OP_PROTECT_ENABLE;
891         }
892 }
893
894 static void ath9k_poll(struct net80211_device *dev)
895 {
896         ath_isr(dev);
897 }
898
899 static void ath9k_irq(struct net80211_device *dev, int enable)
900 {
901         struct ath_softc *sc = dev->priv;
902         struct ath_hw *ah = sc->sc_ah;
903
904         ah->ah_ier = enable ? AR_IER_ENABLE : AR_IER_DISABLE;
905
906         ath9k_hw_set_interrupts(ah, ah->imask);
907 }
908
909 struct net80211_device_operations ath9k_ops = {
910         .transmit       = ath9k_tx,
911         .open           = ath9k_start,
912         .close          = ath9k_stop,
913         .config         = ath9k_config,
914         .poll           = ath9k_poll,
915         .irq            = ath9k_irq,
916 };