~pmdj/ubuntu/trusty/qemu/2.9+applesmc+fadtv3

« back to all changes in this revision

Viewing changes to roms/ipxe/src/drivers/net/ath/ath9k/ath9k_main.c

  • Committer: Phil Dennis-Jordan
  • Date: 2017-07-21 08:03:43 UTC
  • mfrom: (1.1.1)
  • Revision ID: phil@philjordan.eu-20170721080343-2yr2vdj7713czahv
New upstream release 2.9.0.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
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
};