main.c 83.3 KB
Newer Older
1
/*
2
 * Copyright (c) 2008-2009 Atheros Communications Inc.
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
 *
 * Permission to use, copy, modify, and/or distribute this software for any
 * purpose with or without fee is hereby granted, provided that the above
 * copyright notice and this permission notice appear in all copies.
 *
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 */

#include <linux/nl80211.h>
Sujith's avatar
Sujith committed
18
#include "ath9k.h"
19
#include "btcoex.h"
20
21
22
23
24
25
26
27

static char *dev_info = "ath9k";

MODULE_AUTHOR("Atheros Communications");
MODULE_DESCRIPTION("Support for Atheros 802.11n wireless LAN cards.");
MODULE_SUPPORTED_DEVICE("Atheros 802.11n WLAN cards");
MODULE_LICENSE("Dual BSD/GPL");

28
29
30
31
static int modparam_nohwcrypt;
module_param_named(nohwcrypt, modparam_nohwcrypt, int, 0444);
MODULE_PARM_DESC(nohwcrypt, "Disable hardware encryption");

32
33
34
35
36
/* We use the hw_value as an index into our private channel structure */

#define CHAN2G(_freq, _idx)  { \
	.center_freq = (_freq), \
	.hw_value = (_idx), \
37
	.max_power = 20, \
38
39
40
41
42
43
}

#define CHAN5G(_freq, _idx) { \
	.band = IEEE80211_BAND_5GHZ, \
	.center_freq = (_freq), \
	.hw_value = (_idx), \
44
	.max_power = 20, \
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
}

/* Some 2 GHz radios are actually tunable on 2312-2732
 * on 5 MHz steps, we support the channels which we know
 * we have calibration data for all cards though to make
 * this static */
static struct ieee80211_channel ath9k_2ghz_chantable[] = {
	CHAN2G(2412, 0), /* Channel 1 */
	CHAN2G(2417, 1), /* Channel 2 */
	CHAN2G(2422, 2), /* Channel 3 */
	CHAN2G(2427, 3), /* Channel 4 */
	CHAN2G(2432, 4), /* Channel 5 */
	CHAN2G(2437, 5), /* Channel 6 */
	CHAN2G(2442, 6), /* Channel 7 */
	CHAN2G(2447, 7), /* Channel 8 */
	CHAN2G(2452, 8), /* Channel 9 */
	CHAN2G(2457, 9), /* Channel 10 */
	CHAN2G(2462, 10), /* Channel 11 */
	CHAN2G(2467, 11), /* Channel 12 */
	CHAN2G(2472, 12), /* Channel 13 */
	CHAN2G(2484, 13), /* Channel 14 */
};

/* Some 5 GHz radios are actually tunable on XXXX-YYYY
 * on 5 MHz steps, we support the channels which we know
 * we have calibration data for all cards though to make
 * this static */
static struct ieee80211_channel ath9k_5ghz_chantable[] = {
	/* _We_ call this UNII 1 */
	CHAN5G(5180, 14), /* Channel 36 */
	CHAN5G(5200, 15), /* Channel 40 */
	CHAN5G(5220, 16), /* Channel 44 */
	CHAN5G(5240, 17), /* Channel 48 */
	/* _We_ call this UNII 2 */
	CHAN5G(5260, 18), /* Channel 52 */
	CHAN5G(5280, 19), /* Channel 56 */
	CHAN5G(5300, 20), /* Channel 60 */
	CHAN5G(5320, 21), /* Channel 64 */
	/* _We_ call this "Middle band" */
	CHAN5G(5500, 22), /* Channel 100 */
	CHAN5G(5520, 23), /* Channel 104 */
	CHAN5G(5540, 24), /* Channel 108 */
	CHAN5G(5560, 25), /* Channel 112 */
	CHAN5G(5580, 26), /* Channel 116 */
	CHAN5G(5600, 27), /* Channel 120 */
	CHAN5G(5620, 28), /* Channel 124 */
	CHAN5G(5640, 29), /* Channel 128 */
	CHAN5G(5660, 30), /* Channel 132 */
	CHAN5G(5680, 31), /* Channel 136 */
	CHAN5G(5700, 32), /* Channel 140 */
	/* _We_ call this UNII 3 */
	CHAN5G(5745, 33), /* Channel 149 */
	CHAN5G(5765, 34), /* Channel 153 */
	CHAN5G(5785, 35), /* Channel 157 */
	CHAN5G(5805, 36), /* Channel 161 */
	CHAN5G(5825, 37), /* Channel 165 */
};

103
104
static void ath_cache_conf_rate(struct ath_softc *sc,
				struct ieee80211_conf *conf)
Sujith's avatar
Sujith committed
105
{
106
107
108
109
110
111
112
113
114
115
116
	switch (conf->channel->band) {
	case IEEE80211_BAND_2GHZ:
		if (conf_is_ht20(conf))
			sc->cur_rate_table =
			  sc->hw_rate_table[ATH9K_MODE_11NG_HT20];
		else if (conf_is_ht40_minus(conf))
			sc->cur_rate_table =
			  sc->hw_rate_table[ATH9K_MODE_11NG_HT40MINUS];
		else if (conf_is_ht40_plus(conf))
			sc->cur_rate_table =
			  sc->hw_rate_table[ATH9K_MODE_11NG_HT40PLUS];
117
		else
118
119
120
121
122
123
124
125
126
127
128
129
130
131
			sc->cur_rate_table =
			  sc->hw_rate_table[ATH9K_MODE_11G];
		break;
	case IEEE80211_BAND_5GHZ:
		if (conf_is_ht20(conf))
			sc->cur_rate_table =
			  sc->hw_rate_table[ATH9K_MODE_11NA_HT20];
		else if (conf_is_ht40_minus(conf))
			sc->cur_rate_table =
			  sc->hw_rate_table[ATH9K_MODE_11NA_HT40MINUS];
		else if (conf_is_ht40_plus(conf))
			sc->cur_rate_table =
			  sc->hw_rate_table[ATH9K_MODE_11NA_HT40PLUS];
		else
132
133
			sc->cur_rate_table =
			  sc->hw_rate_table[ATH9K_MODE_11A];
134
135
		break;
	default:
136
		BUG_ON(1);
137
138
		break;
	}
Sujith's avatar
Sujith committed
139
140
141
142
}

static void ath_update_txpow(struct ath_softc *sc)
{
143
	struct ath_hw *ah = sc->sc_ah;
Sujith's avatar
Sujith committed
144
145
	u32 txpow;

Sujith's avatar
Sujith committed
146
147
	if (sc->curtxpow != sc->config.txpowlimit) {
		ath9k_hw_set_txpowerlimit(ah, sc->config.txpowlimit);
Sujith's avatar
Sujith committed
148
149
		/* read back in case value is clamped */
		ath9k_hw_getcapability(ah, ATH9K_CAP_TXPOW, 1, &txpow);
Sujith's avatar
Sujith committed
150
		sc->curtxpow = txpow;
Sujith's avatar
Sujith committed
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
	}
}

static u8 parse_mpdudensity(u8 mpdudensity)
{
	/*
	 * 802.11n D2.0 defined values for "Minimum MPDU Start Spacing":
	 *   0 for no restriction
	 *   1 for 1/4 us
	 *   2 for 1/2 us
	 *   3 for 1 us
	 *   4 for 2 us
	 *   5 for 4 us
	 *   6 for 8 us
	 *   7 for 16 us
	 */
	switch (mpdudensity) {
	case 0:
		return 0;
	case 1:
	case 2:
	case 3:
		/* Our lower layer calculations limit our precision to
		   1 microsecond */
		return 1;
	case 4:
		return 2;
	case 5:
		return 4;
	case 6:
		return 8;
	case 7:
		return 16;
	default:
		return 0;
	}
}

static void ath_setup_rates(struct ath_softc *sc, enum ieee80211_band band)
{
191
	const struct ath_rate_table *rate_table = NULL;
Sujith's avatar
Sujith committed
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
	struct ieee80211_supported_band *sband;
	struct ieee80211_rate *rate;
	int i, maxrates;

	switch (band) {
	case IEEE80211_BAND_2GHZ:
		rate_table = sc->hw_rate_table[ATH9K_MODE_11G];
		break;
	case IEEE80211_BAND_5GHZ:
		rate_table = sc->hw_rate_table[ATH9K_MODE_11A];
		break;
	default:
		break;
	}

	if (rate_table == NULL)
		return;

	sband = &sc->sbands[band];
	rate = sc->rates[band];

	if (rate_table->rate_cnt > ATH_RATE_MAX)
		maxrates = ATH_RATE_MAX;
	else
		maxrates = rate_table->rate_cnt;

	for (i = 0; i < maxrates; i++) {
		rate[i].bitrate = rate_table->info[i].ratekbps / 100;
		rate[i].hw_value = rate_table->info[i].ratecode;
221
222
223
224
225
		if (rate_table->info[i].short_preamble) {
			rate[i].hw_value_short = rate_table->info[i].ratecode |
				rate_table->info[i].short_preamble;
			rate[i].flags = IEEE80211_RATE_SHORT_PREAMBLE;
		}
Sujith's avatar
Sujith committed
226
		sband->n_bitrates++;
227

228
229
230
		ath_print(ath9k_hw_common(sc->sc_ah), ATH_DBG_CONFIG,
			  "Rate: %2dMbps, ratecode: %2d\n",
			  rate[i].bitrate / 10, rate[i].hw_value);
Sujith's avatar
Sujith committed
231
232
233
	}
}

234
235
236
237
238
239
240
241
242
243
244
245
246
static struct ath9k_channel *ath_get_curchannel(struct ath_softc *sc,
						struct ieee80211_hw *hw)
{
	struct ieee80211_channel *curchan = hw->conf.channel;
	struct ath9k_channel *channel;
	u8 chan_idx;

	chan_idx = curchan->hw_value;
	channel = &sc->sc_ah->channels[chan_idx];
	ath9k_update_ichannel(sc, hw, channel);
	return channel;
}

247
static bool ath9k_setpower(struct ath_softc *sc, enum ath9k_power_mode mode)
248
249
250
251
{
	unsigned long flags;
	bool ret;

252
253
254
	spin_lock_irqsave(&sc->sc_pm_lock, flags);
	ret = ath9k_hw_setpower(sc->sc_ah, mode);
	spin_unlock_irqrestore(&sc->sc_pm_lock, flags);
255
256
257
258

	return ret;
}

259
260
261
262
263
264
265
266
void ath9k_ps_wakeup(struct ath_softc *sc)
{
	unsigned long flags;

	spin_lock_irqsave(&sc->sc_pm_lock, flags);
	if (++sc->ps_usecount != 1)
		goto unlock;

267
	ath9k_hw_setpower(sc->sc_ah, ATH9K_PM_AWAKE);
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285

 unlock:
	spin_unlock_irqrestore(&sc->sc_pm_lock, flags);
}

void ath9k_ps_restore(struct ath_softc *sc)
{
	unsigned long flags;

	spin_lock_irqsave(&sc->sc_pm_lock, flags);
	if (--sc->ps_usecount != 0)
		goto unlock;

	if (sc->ps_enabled &&
	    !(sc->sc_flags & (SC_OP_WAIT_FOR_BEACON |
			      SC_OP_WAIT_FOR_CAB |
			      SC_OP_WAIT_FOR_PSPOLL_DATA |
			      SC_OP_WAIT_FOR_TX_ACK)))
286
		ath9k_hw_setpower(sc->sc_ah, ATH9K_PM_NETWORK_SLEEP);
287
288
289
290
291

 unlock:
	spin_unlock_irqrestore(&sc->sc_pm_lock, flags);
}

Sujith's avatar
Sujith committed
292
293
294
295
296
/*
 * Set/change channels.  If the channel is really being changed, it's done
 * by reseting the chip.  To accomplish this we must first cleanup any pending
 * DMA, then restart stuff.
*/
297
298
int ath_set_channel(struct ath_softc *sc, struct ieee80211_hw *hw,
		    struct ath9k_channel *hchan)
Sujith's avatar
Sujith committed
299
{
300
	struct ath_hw *ah = sc->sc_ah;
301
	struct ath_common *common = ath9k_hw_common(ah);
302
	struct ieee80211_conf *conf = &common->hw->conf;
Sujith's avatar
Sujith committed
303
	bool fastcc = true, stopped;
304
305
	struct ieee80211_channel *channel = hw->conf.channel;
	int r;
Sujith's avatar
Sujith committed
306
307
308
309

	if (sc->sc_flags & SC_OP_INVALID)
		return -EIO;

310
311
	ath9k_ps_wakeup(sc);

312
313
314
315
316
317
318
319
320
321
	/*
	 * This is only performed if the channel settings have
	 * actually changed.
	 *
	 * To switch channels clear any pending DMA operations;
	 * wait long enough for the RX fifo to drain, reset the
	 * hardware at the new frequency, and then re-enable
	 * the relevant bits of the h/w.
	 */
	ath9k_hw_set_interrupts(ah, 0);
Sujith's avatar
Sujith committed
322
	ath_drain_all_txq(sc, false);
323
	stopped = ath_stoprecv(sc);
Sujith's avatar
Sujith committed
324

325
326
327
	/* XXX: do not flush receive queue here. We don't want
	 * to flush data frames already in queue because of
	 * changing channel. */
Sujith's avatar
Sujith committed
328

329
330
331
	if (!stopped || (sc->sc_flags & SC_OP_FULL_RESET))
		fastcc = false;

332
	ath_print(common, ATH_DBG_CONFIG,
333
		  "(%u MHz) -> (%u MHz), conf_is_ht40: %d\n",
334
		  sc->sc_ah->curchan->channel,
335
		  channel->center_freq, conf_is_ht40(conf));
Sujith's avatar
Sujith committed
336

337
338
339
340
	spin_lock_bh(&sc->sc_resetlock);

	r = ath9k_hw_reset(ah, hchan, fastcc);
	if (r) {
341
342
343
344
		ath_print(common, ATH_DBG_FATAL,
			  "Unable to reset channel (%u Mhz) "
			  "reset status %d\n",
			  channel->center_freq, r);
345
		spin_unlock_bh(&sc->sc_resetlock);
346
		goto ps_restore;
Sujith's avatar
Sujith committed
347
	}
348
349
350
351
352
	spin_unlock_bh(&sc->sc_resetlock);

	sc->sc_flags &= ~SC_OP_FULL_RESET;

	if (ath_startrecv(sc) != 0) {
353
354
		ath_print(common, ATH_DBG_FATAL,
			  "Unable to restart recv logic\n");
355
356
		r = -EIO;
		goto ps_restore;
357
358
359
360
	}

	ath_cache_conf_rate(sc, &hw->conf);
	ath_update_txpow(sc);
Sujith's avatar
Sujith committed
361
	ath9k_hw_set_interrupts(ah, sc->imask);
362
363

 ps_restore:
364
	ath9k_ps_restore(sc);
365
	return r;
Sujith's avatar
Sujith committed
366
367
368
369
370
371
372
373
374
375
376
}

/*
 *  This routine performs the periodic noise floor calibration function
 *  that is used to adjust and optimize the chip performance.  This
 *  takes environmental changes (location, temperature) into account.
 *  When the task is complete, it reschedules itself depending on the
 *  appropriate interval that was calculated.
 */
static void ath_ani_calibrate(unsigned long data)
{
377
378
	struct ath_softc *sc = (struct ath_softc *)data;
	struct ath_hw *ah = sc->sc_ah;
379
	struct ath_common *common = ath9k_hw_common(ah);
Sujith's avatar
Sujith committed
380
381
382
383
	bool longcal = false;
	bool shortcal = false;
	bool aniflag = false;
	unsigned int timestamp = jiffies_to_msecs(jiffies);
384
	u32 cal_interval, short_cal_interval;
Sujith's avatar
Sujith committed
385

386
387
	short_cal_interval = (ah->opmode == NL80211_IFTYPE_AP) ?
		ATH_AP_SHORT_CALINTERVAL : ATH_STA_SHORT_CALINTERVAL;
Sujith's avatar
Sujith committed
388
389
390
391
392

	/*
	* don't calibrate when we're scanning.
	* we are most likely not on our home channel.
	*/
393
	spin_lock(&sc->ani_lock);
394
	if (sc->sc_flags & SC_OP_SCANNING)
395
		goto set_timer;
Sujith's avatar
Sujith committed
396

397
398
399
400
401
402
	/* Only calibrate if awake */
	if (sc->sc_ah->power_mode != ATH9K_PM_AWAKE)
		goto set_timer;

	ath9k_ps_wakeup(sc);

Sujith's avatar
Sujith committed
403
	/* Long calibration runs independently of short calibration. */
Sujith's avatar
Sujith committed
404
	if ((timestamp - sc->ani.longcal_timer) >= ATH_LONG_CALINTERVAL) {
Sujith's avatar
Sujith committed
405
		longcal = true;
406
		ath_print(common, ATH_DBG_ANI, "longcal @%lu\n", jiffies);
Sujith's avatar
Sujith committed
407
		sc->ani.longcal_timer = timestamp;
Sujith's avatar
Sujith committed
408
409
	}

Sujith's avatar
Sujith committed
410
411
	/* Short calibration applies only while caldone is false */
	if (!sc->ani.caldone) {
412
		if ((timestamp - sc->ani.shortcal_timer) >= short_cal_interval) {
Sujith's avatar
Sujith committed
413
			shortcal = true;
414
415
			ath_print(common, ATH_DBG_ANI,
				  "shortcal @%lu\n", jiffies);
Sujith's avatar
Sujith committed
416
417
			sc->ani.shortcal_timer = timestamp;
			sc->ani.resetcal_timer = timestamp;
Sujith's avatar
Sujith committed
418
419
		}
	} else {
Sujith's avatar
Sujith committed
420
		if ((timestamp - sc->ani.resetcal_timer) >=
Sujith's avatar
Sujith committed
421
		    ATH_RESTART_CALINTERVAL) {
Sujith's avatar
Sujith committed
422
423
424
			sc->ani.caldone = ath9k_hw_reset_calvalid(ah);
			if (sc->ani.caldone)
				sc->ani.resetcal_timer = timestamp;
Sujith's avatar
Sujith committed
425
426
427
428
		}
	}

	/* Verify whether we must check ANI */
429
	if ((timestamp - sc->ani.checkani_timer) >= ATH_ANI_POLLINTERVAL) {
Sujith's avatar
Sujith committed
430
		aniflag = true;
Sujith's avatar
Sujith committed
431
		sc->ani.checkani_timer = timestamp;
Sujith's avatar
Sujith committed
432
433
434
435
436
437
	}

	/* Skip all processing if there's nothing to do. */
	if (longcal || shortcal || aniflag) {
		/* Call ANI routine if necessary */
		if (aniflag)
438
			ath9k_hw_ani_monitor(ah, ah->curchan);
Sujith's avatar
Sujith committed
439
440
441

		/* Perform calibration if necessary */
		if (longcal || shortcal) {
442
443
444
445
446
			sc->ani.caldone =
				ath9k_hw_calibrate(ah,
						   ah->curchan,
						   common->rx_chainmask,
						   longcal);
Sujith's avatar
Sujith committed
447
448
449
450
451

			if (longcal)
				sc->ani.noise_floor = ath9k_hw_getchan_noise(ah,
								     ah->curchan);

452
453
454
455
456
			ath_print(common, ATH_DBG_ANI,
				  " calibrate chan %u/%x nf: %d\n",
				  ah->curchan->channel,
				  ah->curchan->channelFlags,
				  sc->ani.noise_floor);
Sujith's avatar
Sujith committed
457
458
459
		}
	}

460
461
	ath9k_ps_restore(sc);

462
set_timer:
463
	spin_unlock(&sc->ani_lock);
Sujith's avatar
Sujith committed
464
465
466
467
468
	/*
	* Set timer interval based on previous results.
	* The interval must be the shortest necessary to satisfy ANI,
	* short calibration and long calibration.
	*/
469
	cal_interval = ATH_LONG_CALINTERVAL;
470
	if (sc->sc_ah->config.enable_ani)
471
		cal_interval = min(cal_interval, (u32)ATH_ANI_POLLINTERVAL);
Sujith's avatar
Sujith committed
472
	if (!sc->ani.caldone)
473
		cal_interval = min(cal_interval, (u32)short_cal_interval);
Sujith's avatar
Sujith committed
474

Sujith's avatar
Sujith committed
475
	mod_timer(&sc->ani.timer, jiffies + msecs_to_jiffies(cal_interval));
Sujith's avatar
Sujith committed
476
477
}

Sujith's avatar
Sujith committed
478
479
480
481
482
483
484
485
486
487
488
489
static void ath_start_ani(struct ath_softc *sc)
{
	unsigned long timestamp = jiffies_to_msecs(jiffies);

	sc->ani.longcal_timer = timestamp;
	sc->ani.shortcal_timer = timestamp;
	sc->ani.checkani_timer = timestamp;

	mod_timer(&sc->ani.timer,
		  jiffies + msecs_to_jiffies(ATH_ANI_POLLINTERVAL));
}

Sujith's avatar
Sujith committed
490
491
492
/*
 * Update tx/rx chainmask. For legacy association,
 * hard code chainmask to 1x1, for 11n association, use
493
494
 * the chainmask configuration, for bt coexistence, use
 * the chainmask configuration even in legacy mode.
Sujith's avatar
Sujith committed
495
 */
496
void ath_update_chainmask(struct ath_softc *sc, int is_ht)
Sujith's avatar
Sujith committed
497
{
498
	struct ath_hw *ah = sc->sc_ah;
499
	struct ath_common *common = ath9k_hw_common(ah);
500

501
	if ((sc->sc_flags & SC_OP_SCANNING) || is_ht ||
502
	    (ah->btcoex_hw.scheme != ATH_BTCOEX_CFG_NONE)) {
503
504
		common->tx_chainmask = ah->caps.tx_chainmask;
		common->rx_chainmask = ah->caps.rx_chainmask;
Sujith's avatar
Sujith committed
505
	} else {
506
507
		common->tx_chainmask = 1;
		common->rx_chainmask = 1;
Sujith's avatar
Sujith committed
508
509
	}

510
	ath_print(common, ATH_DBG_CONFIG,
511
		  "tx chmask: %d, rx chmask: %d\n",
512
513
		  common->tx_chainmask,
		  common->rx_chainmask);
Sujith's avatar
Sujith committed
514
515
516
517
518
519
520
521
}

static void ath_node_attach(struct ath_softc *sc, struct ieee80211_sta *sta)
{
	struct ath_node *an;

	an = (struct ath_node *)sta->drv_priv;

522
	if (sc->sc_flags & SC_OP_TXAGGR) {
Sujith's avatar
Sujith committed
523
		ath_tx_node_init(sc, an);
Sujith's avatar
Sujith committed
524
		an->maxampdu = 1 << (IEEE80211_HT_MAX_AMPDU_FACTOR +
525
526
				     sta->ht_cap.ampdu_factor);
		an->mpdudensity = parse_mpdudensity(sta->ht_cap.ampdu_density);
527
		an->last_rssi = ATH_RSSI_DUMMY_MARKER;
528
	}
Sujith's avatar
Sujith committed
529
530
531
532
533
534
535
536
537
538
539
540
541
}

static void ath_node_detach(struct ath_softc *sc, struct ieee80211_sta *sta)
{
	struct ath_node *an = (struct ath_node *)sta->drv_priv;

	if (sc->sc_flags & SC_OP_TXAGGR)
		ath_tx_node_cleanup(sc, an);
}

static void ath9k_tasklet(unsigned long data)
{
	struct ath_softc *sc = (struct ath_softc *)data;
542
	struct ath_hw *ah = sc->sc_ah;
543
	struct ath_common *common = ath9k_hw_common(ah);
544

Sujith's avatar
Sujith committed
545
	u32 status = sc->intrstatus;
Sujith's avatar
Sujith committed
546

547
548
	ath9k_ps_wakeup(sc);

Sujith's avatar
Sujith committed
549
550
	if (status & ATH9K_INT_FATAL) {
		ath_reset(sc, false);
551
		ath9k_ps_restore(sc);
Sujith's avatar
Sujith committed
552
		return;
553
	}
Sujith's avatar
Sujith committed
554

555
556
557
558
	if (status & (ATH9K_INT_RX | ATH9K_INT_RXEOL | ATH9K_INT_RXORN)) {
		spin_lock_bh(&sc->rx.rxflushlock);
		ath_rx_tasklet(sc, 0);
		spin_unlock_bh(&sc->rx.rxflushlock);
Sujith's avatar
Sujith committed
559
560
	}

561
562
563
	if (status & ATH9K_INT_TX)
		ath_tx_tasklet(sc);

564
	if ((status & ATH9K_INT_TSFOOR) && sc->ps_enabled) {
565
566
567
568
		/*
		 * TSF sync does not look correct; remain awake to sync with
		 * the next Beacon.
		 */
569
570
		ath_print(common, ATH_DBG_PS,
			  "TSFOOR - Sync with next Beacon\n");
571
		sc->sc_flags |= SC_OP_WAIT_FOR_BEACON | SC_OP_BEACON_SYNC;
572
573
	}

574
	if (ah->btcoex_hw.scheme == ATH_BTCOEX_CFG_3WIRE)
575
576
577
		if (status & ATH9K_INT_GENTIMER)
			ath_gen_timer_isr(sc->sc_ah);

Sujith's avatar
Sujith committed
578
	/* re-enable hardware interrupt */
579
	ath9k_hw_set_interrupts(ah, sc->imask);
580
	ath9k_ps_restore(sc);
Sujith's avatar
Sujith committed
581
582
}

583
irqreturn_t ath_isr(int irq, void *dev)
Sujith's avatar
Sujith committed
584
{
585
586
587
588
589
590
591
592
#define SCHED_INTR (				\
		ATH9K_INT_FATAL |		\
		ATH9K_INT_RXORN |		\
		ATH9K_INT_RXEOL |		\
		ATH9K_INT_RX |			\
		ATH9K_INT_TX |			\
		ATH9K_INT_BMISS |		\
		ATH9K_INT_CST |			\
593
594
		ATH9K_INT_TSFOOR |		\
		ATH9K_INT_GENTIMER)
595

Sujith's avatar
Sujith committed
596
	struct ath_softc *sc = dev;
597
	struct ath_hw *ah = sc->sc_ah;
Sujith's avatar
Sujith committed
598
599
600
	enum ath9k_int status;
	bool sched = false;

601
602
603
604
605
606
607
	/*
	 * The hardware is not ready/present, don't
	 * touch anything. Note this can happen early
	 * on if the IRQ is shared.
	 */
	if (sc->sc_flags & SC_OP_INVALID)
		return IRQ_NONE;
Sujith's avatar
Sujith committed
608

609
610
611

	/* shared irq, not for us */

612
	if (!ath9k_hw_intrpend(ah))
613
614
615
616
617
618
619
620
621
622
		return IRQ_NONE;

	/*
	 * Figure out the reason(s) for the interrupt.  Note
	 * that the hal returns a pseudo-ISR that may include
	 * bits we haven't explicitly enabled so we mask the
	 * value to insure we only process bits we requested.
	 */
	ath9k_hw_getisr(ah, &status);	/* NB: clears ISR too */
	status &= sc->imask;	/* discard unasked-for bits */
Sujith's avatar
Sujith committed
623

624
625
626
627
	/*
	 * If there are no status bits set, then this interrupt was not
	 * for me (should have been caught above).
	 */
628
	if (!status)
629
		return IRQ_NONE;
Sujith's avatar
Sujith committed
630

631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
	/* Cache the status */
	sc->intrstatus = status;

	if (status & SCHED_INTR)
		sched = true;

	/*
	 * If a FATAL or RXORN interrupt is received, we have to reset the
	 * chip immediately.
	 */
	if (status & (ATH9K_INT_FATAL | ATH9K_INT_RXORN))
		goto chip_reset;

	if (status & ATH9K_INT_SWBA)
		tasklet_schedule(&sc->bcon_tasklet);

	if (status & ATH9K_INT_TXURN)
		ath9k_hw_updatetxtriglevel(ah, true);

	if (status & ATH9K_INT_MIB) {
Sujith's avatar
Sujith committed
651
		/*
652
653
654
		 * Disable interrupts until we service the MIB
		 * interrupt; otherwise it will continue to
		 * fire.
Sujith's avatar
Sujith committed
655
		 */
656
657
658
659
660
661
		ath9k_hw_set_interrupts(ah, 0);
		/*
		 * Let the hal handle the event. We assume
		 * it will clear whatever condition caused
		 * the interrupt.
		 */
662
		ath9k_hw_procmibevent(ah);
663
664
		ath9k_hw_set_interrupts(ah, sc->imask);
	}
Sujith's avatar
Sujith committed
665

666
667
	if (!(ah->caps.hw_caps & ATH9K_HW_CAP_AUTOSLEEP))
		if (status & ATH9K_INT_TIM_TIMER) {
668
669
			/* Clear RxAbort bit so that we can
			 * receive frames */
670
			ath9k_setpower(sc, ATH9K_PM_AWAKE);
671
			ath9k_hw_setrxabort(sc->sc_ah, 0);
672
			sc->sc_flags |= SC_OP_WAIT_FOR_BEACON;
Sujith's avatar
Sujith committed
673
		}
674
675

chip_reset:
Sujith's avatar
Sujith committed
676

677
678
	ath_debug_stat_interrupt(sc, status);

Sujith's avatar
Sujith committed
679
680
	if (sched) {
		/* turn off every interrupt except SWBA */
Sujith's avatar
Sujith committed
681
		ath9k_hw_set_interrupts(ah, (sc->imask & ATH9K_INT_SWBA));
Sujith's avatar
Sujith committed
682
683
684
685
		tasklet_schedule(&sc->intr_tq);
	}

	return IRQ_HANDLED;
686
687

#undef SCHED_INTR
Sujith's avatar
Sujith committed
688
689
}

690
static u32 ath_get_extchanmode(struct ath_softc *sc,
691
			       struct ieee80211_channel *chan,
Sujith's avatar
Sujith committed
692
			       enum nl80211_channel_type channel_type)
693
694
695
696
697
{
	u32 chanmode = 0;

	switch (chan->band) {
	case IEEE80211_BAND_2GHZ:
Sujith's avatar
Sujith committed
698
699
700
		switch(channel_type) {
		case NL80211_CHAN_NO_HT:
		case NL80211_CHAN_HT20:
701
			chanmode = CHANNEL_G_HT20;
Sujith's avatar
Sujith committed
702
703
			break;
		case NL80211_CHAN_HT40PLUS:
704
			chanmode = CHANNEL_G_HT40PLUS;
Sujith's avatar
Sujith committed
705
706
			break;
		case NL80211_CHAN_HT40MINUS:
707
			chanmode = CHANNEL_G_HT40MINUS;
Sujith's avatar
Sujith committed
708
709
			break;
		}
710
711
		break;
	case IEEE80211_BAND_5GHZ:
Sujith's avatar
Sujith committed
712
713
714
		switch(channel_type) {
		case NL80211_CHAN_NO_HT:
		case NL80211_CHAN_HT20:
715
			chanmode = CHANNEL_A_HT20;
Sujith's avatar
Sujith committed
716
717
			break;
		case NL80211_CHAN_HT40PLUS:
718
			chanmode = CHANNEL_A_HT40PLUS;
Sujith's avatar
Sujith committed
719
720
			break;
		case NL80211_CHAN_HT40MINUS:
721
			chanmode = CHANNEL_A_HT40MINUS;
Sujith's avatar
Sujith committed
722
723
			break;
		}
724
725
726
727
728
729
730
731
		break;
	default:
		break;
	}

	return chanmode;
}

732
static int ath_setkey_tkip(struct ath_softc *sc, u16 keyix, const u8 *key,
733
734
			   struct ath9k_keyval *hk, const u8 *addr,
			   bool authenticator)
735
{
736
737
	const u8 *key_rxmic;
	const u8 *key_txmic;
738

739
740
	key_txmic = key + NL80211_TKIP_DATA_OFFSET_TX_MIC_KEY;
	key_rxmic = key + NL80211_TKIP_DATA_OFFSET_RX_MIC_KEY;
741
742

	if (addr == NULL) {
743
744
745
746
747
		/*
		 * Group key installation - only two key cache entries are used
		 * regardless of splitmic capability since group key is only
		 * used either for TX or RX.
		 */
748
749
750
751
752
753
754
		if (authenticator) {
			memcpy(hk->kv_mic, key_txmic, sizeof(hk->kv_mic));
			memcpy(hk->kv_txmic, key_txmic, sizeof(hk->kv_mic));
		} else {
			memcpy(hk->kv_mic, key_rxmic, sizeof(hk->kv_mic));
			memcpy(hk->kv_txmic, key_rxmic, sizeof(hk->kv_mic));
		}
755
		return ath9k_hw_set_keycache_entry(sc->sc_ah, keyix, hk, addr);
756
	}
Sujith's avatar
Sujith committed
757
	if (!sc->splitmic) {
758
		/* TX and RX keys share the same key cache entry. */
759
760
		memcpy(hk->kv_mic, key_rxmic, sizeof(hk->kv_mic));
		memcpy(hk->kv_txmic, key_txmic, sizeof(hk->kv_txmic));
761
		return ath9k_hw_set_keycache_entry(sc->sc_ah, keyix, hk, addr);
762
	}
763
764
765
766

	/* Separate key cache entries for TX and RX */

	/* TX key goes at first index, RX key at +32. */
767
	memcpy(hk->kv_mic, key_txmic, sizeof(hk->kv_mic));
768
769
	if (!ath9k_hw_set_keycache_entry(sc->sc_ah, keyix, hk, NULL)) {
		/* TX MIC entry failed. No need to proceed further */
770
771
		ath_print(ath9k_hw_common(sc->sc_ah), ATH_DBG_FATAL,
			  "Setting TX MIC Key Failed\n");
772
773
774
775
776
		return 0;
	}

	memcpy(hk->kv_mic, key_rxmic, sizeof(hk->kv_mic));
	/* XXX delete tx key on failure? */
777
	return ath9k_hw_set_keycache_entry(sc->sc_ah, keyix + 32, hk, addr);
778
779
780
781
782
783
}

static int ath_reserve_key_cache_slot_tkip(struct ath_softc *sc)
{
	int i;

Sujith's avatar
Sujith committed
784
785
786
	for (i = IEEE80211_WEP_NKID; i < sc->keymax / 2; i++) {
		if (test_bit(i, sc->keymap) ||
		    test_bit(i + 64, sc->keymap))
787
			continue; /* At least one part of TKIP key allocated */
Sujith's avatar
Sujith committed
788
789
790
		if (sc->splitmic &&
		    (test_bit(i + 32, sc->keymap) ||
		     test_bit(i + 64 + 32, sc->keymap)))
791
792
793
794
795
796
797
798
799
800
801
802
803
			continue; /* At least one part of TKIP key allocated */

		/* Found a free slot for a TKIP key */
		return i;
	}
	return -1;
}

static int ath_reserve_key_cache_slot(struct ath_softc *sc)
{
	int i;

	/* First, try to find slots that would not be available for TKIP. */
Sujith's avatar
Sujith committed
804
805
806
807
808
809
	if (sc->splitmic) {
		for (i = IEEE80211_WEP_NKID; i < sc->keymax / 4; i++) {
			if (!test_bit(i, sc->keymap) &&
			    (test_bit(i + 32, sc->keymap) ||
			     test_bit(i + 64, sc->keymap) ||
			     test_bit(i + 64 + 32, sc->keymap)))
810
				return i;
Sujith's avatar
Sujith committed
811
812
813
814
			if (!test_bit(i + 32, sc->keymap) &&
			    (test_bit(i, sc->keymap) ||
			     test_bit(i + 64, sc->keymap) ||
			     test_bit(i + 64 + 32, sc->keymap)))
815
				return i + 32;
Sujith's avatar
Sujith committed
816
817
818
819
			if (!test_bit(i + 64, sc->keymap) &&
			    (test_bit(i , sc->keymap) ||
			     test_bit(i + 32, sc->keymap) ||
			     test_bit(i + 64 + 32, sc->keymap)))
820
				return i + 64;
Sujith's avatar
Sujith committed
821
822
823
824
			if (!test_bit(i + 64 + 32, sc->keymap) &&
			    (test_bit(i, sc->keymap) ||
			     test_bit(i + 32, sc->keymap) ||
			     test_bit(i + 64, sc->keymap)))
825
				return i + 64 + 32;
826
827
		}
	} else {
Sujith's avatar
Sujith committed
828
829
830
		for (i = IEEE80211_WEP_NKID; i < sc->keymax / 2; i++) {
			if (!test_bit(i, sc->keymap) &&
			    test_bit(i + 64, sc->keymap))
831
				return i;
Sujith's avatar
Sujith committed
832
833
			if (test_bit(i, sc->keymap) &&
			    !test_bit(i + 64, sc->keymap))
834
835
836
837
838
				return i + 64;
		}
	}

	/* No partially used TKIP slots, pick any available slot */
Sujith's avatar
Sujith committed
839
	for (i = IEEE80211_WEP_NKID; i < sc->keymax; i++) {
840
841
842
843
844
		/* Do not allow slots that could be needed for TKIP group keys
		 * to be used. This limitation could be removed if we know that
		 * TKIP will not be used. */
		if (i >= 64 && i < 64 + IEEE80211_WEP_NKID)
			continue;
Sujith's avatar
Sujith committed
845
		if (sc->splitmic) {
846
847
848
849
850
851
			if (i >= 32 && i < 32 + IEEE80211_WEP_NKID)
				continue;
			if (i >= 64 + 32 && i < 64 + 32 + IEEE80211_WEP_NKID)
				continue;
		}

Sujith's avatar
Sujith committed
852
		if (!test_bit(i, sc->keymap))
853
854
855
856
857
			return i; /* Found a free slot for a key */
	}

	/* No free slot found */
	return -1;
858
859
860
}

static int ath_key_config(struct ath_softc *sc,
861
			  struct ieee80211_vif *vif,
862
			  struct ieee80211_sta *sta,
863
864
865
866
867
			  struct ieee80211_key_conf *key)
{
	struct ath9k_keyval hk;
	const u8 *mac = NULL;
	int ret = 0;
868
	int idx;
869
870
871
872
873
874
875
876
877
878
879
880
881
882

	memset(&hk, 0, sizeof(hk));

	switch (key->alg) {
	case ALG_WEP:
		hk.kv_type = ATH9K_CIPHER_WEP;
		break;
	case ALG_TKIP:
		hk.kv_type = ATH9K_CIPHER_TKIP;
		break;
	case ALG_CCMP:
		hk.kv_type = ATH9K_CIPHER_AES_CCM;
		break;
	default:
Jouni Malinen's avatar
Jouni Malinen committed
883
		return -EOPNOTSUPP;
884
885
	}

886
	hk.kv_len = key->keylen;
887
888
	memcpy(hk.kv_val, key->key, key->keylen);

889
890
891
892
893
	if (!(key->flags & IEEE80211_KEY_FLAG_PAIRWISE)) {
		/* For now, use the default keys for broadcast keys. This may
		 * need to change with virtual interfaces. */
		idx = key->keyidx;
	} else if (key->keyidx) {
894
895
896
897
		if (WARN_ON(!sta))
			return -EOPNOTSUPP;
		mac = sta->addr;

898
899
900
901
902
903
		if (vif->type != NL80211_IFTYPE_AP) {
			/* Only keyidx 0 should be used with unicast key, but
			 * allow this for client mode for now. */
			idx = key->keyidx;
		} else
			return -EIO;
904
	} else {
905
906
907
908
		if (WARN_ON(!sta))
			return -EOPNOTSUPP;
		mac = sta->addr;

909
910
911
912
913
		if (key->alg == ALG_TKIP)
			idx = ath_reserve_key_cache_slot_tkip(sc);
		else
			idx = ath_reserve_key_cache_slot(sc);
		if (idx < 0)
Jouni Malinen's avatar
Jouni Malinen committed
914
			return -ENOSPC; /* no free key cache entries */
915
916
917
	}

	if (key->alg == ALG_TKIP)
918
919
		ret = ath_setkey_tkip(sc, idx, key->key, &hk, mac,
				      vif->type == NL80211_IFTYPE_AP);
920
	else
921
		ret = ath9k_hw_set_keycache_entry(sc->sc_ah, idx, &hk, mac);
922
923
924
925

	if (!ret)
		return -EIO;

Sujith's avatar
Sujith committed
926
	set_bit(idx, sc->keymap);
927
	if (key->alg == ALG_TKIP) {
Sujith's avatar
Sujith committed
928
929
930
931
		set_bit(idx + 64, sc->keymap);
		if (sc->splitmic) {
			set_bit(idx + 32, sc->keymap);
			set_bit(idx + 64 + 32, sc->keymap);
932
933
934
935
		}
	}

	return idx;
936
937
938
939
}

static void ath_key_delete(struct ath_softc *sc, struct ieee80211_key_conf *key)
{
940
941
942
943
	ath9k_hw_keyreset(sc->sc_ah, key->hw_key_idx);
	if (key->hw_key_idx < IEEE80211_WEP_NKID)
		return;

Sujith's avatar
Sujith committed
944
	clear_bit(key->hw_key_idx, sc->keymap);
945
946
	if (key->alg != ALG_TKIP)
		return;
947

Sujith's avatar
Sujith committed
948
949
950
951
	clear_bit(key->hw_key_idx + 64, sc->keymap);
	if (sc->splitmic) {
		clear_bit(key->hw_key_idx + 32, sc->keymap);
		clear_bit(key->hw_key_idx + 64 + 32, sc->keymap);
952
	}
953
954
}

955
956
static void setup_ht_cap(struct ath_softc *sc,
			 struct ieee80211_sta_ht_cap *ht_info)
957
{
958
	struct ath_common *common = ath9k_hw_common(sc->sc_ah);
959
	u8 tx_streams, rx_streams;
960

961
962
963
964
965
	ht_info->ht_supported = true;
	ht_info->cap = IEEE80211_HT_CAP_SUP_WIDTH_20_40 |
		       IEEE80211_HT_CAP_SM_PS |
		       IEEE80211_HT_CAP_SGI_40 |
		       IEEE80211_HT_CAP_DSSSCCK40;
966

Sujith's avatar
Sujith committed
967
968
	ht_info->ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K;
	ht_info->ampdu_density = IEEE80211_HT_MPDU_DENSITY_8;
969

970
971
	/* set up supported mcs set */
	memset(&ht_info->mcs, 0, sizeof(ht_info->mcs));
972
973
974
975
	tx_streams = !(common->tx_chainmask & (common->tx_chainmask - 1)) ?
		     1 : 2;
	rx_streams = !(common->rx_chainmask & (common->rx_chainmask - 1)) ?
		     1 : 2;
976
977

	if (tx_streams != rx_streams) {
978
		ath_print(common, ATH_DBG_CONFIG,
979
980
			  "TX streams %d, RX streams: %d\n",
			  tx_streams, rx_streams);
981
982
983
984
		ht_info->mcs.tx_params |= IEEE80211_HT_MCS_TX_RX_DIFF;
		ht_info->mcs.tx_params |= ((tx_streams - 1) <<
				IEEE80211_HT_MCS_TX_MAX_STREAMS_SHIFT);
	}
985

986
987
	ht_info->mcs.rx_mask[0] = 0xff;
	if (rx_streams >= 2)
988
989
		ht_info->mcs.rx_mask[1] = 0xff;

990
	ht_info->mcs.tx_params |= IEEE80211_HT_MCS_TX_DEFINED;
991
992
}

993
static void ath9k_bss_assoc_info(struct ath_softc *sc,
Sujith's avatar
Sujith committed
994
				 struct ieee80211_vif *vif,
995
				 struct ieee80211_bss_conf *bss_conf)
996
{
997
	struct ath_hw *ah = sc->sc_ah;
998
	struct ath_common *common = ath9k_hw_common(ah);
999

1000
	if (bss_conf->assoc) {
1001
1002
1003
		ath_print(common, ATH_DBG_CONFIG,
			  "Bss Info ASSOC %d, bssid: %pM\n",
			   bss_conf->aid, common->curbssid);
1004

1005
		/* New association, store aid */
1006
		common->curaid = bss_conf->aid;
1007
		ath9k_hw_write_associd(ah);
1008
1009
1010
1011
1012
1013
1014

		/*
		 * Request a re-configuration of Beacon related timers
		 * on the receipt of the first Beacon frame (i.e.,
		 * after time sync with the AP).
		 */
		sc->sc_flags |= SC_OP_BEACON_SYNC;
1015

1016
		/* Configure the beacon */
1017
		ath_beacon_config(sc, vif);
1018

1019
		/* Reset rssi stats */
1020
		sc->sc_ah->stats.avgbrssi = ATH_RSSI_DUMMY_MARKER;
1021

Sujith's avatar
Sujith committed
1022
		ath_start_ani(sc);
1023
	} else {
1024
		ath_print(common, ATH_DBG_CONFIG, "Bss Info DISASSOC\n");
1025
		common->curaid = 0;
1026
1027
		/* Stop ANI */
		del_timer_sync(&sc->ani.timer);
1028
	}
1029
}
1030

1031
1032
1033
/********************************/
/*	 LED functions		*/
/********************************/
1034

1035
1036
1037
1038
1039
1040
1041
static void ath_led_blink_work(struct work_struct *work)
{
	struct ath_softc *sc = container_of(work, struct ath_softc,
					    ath_led_blink_work.work);

	if (!(sc->sc_flags & SC_OP_LED_ASSOCIATED))
		return;
1042
1043
1044

	if ((sc->led_on_duration == ATH_LED_ON_DURATION_IDLE) ||
	    (sc->led_off_duration == ATH_LED_OFF_DURATION_IDLE))
1045
		ath9k_hw_set_gpio(sc->sc_ah, sc->sc_ah->led_pin, 0);
1046
	else
1047
		ath9k_hw_set_gpio(sc->sc_ah, sc->sc_ah->led_pin,
1048
				  (sc->sc_flags & SC_OP_LED_ON) ? 1 : 0);
1049

1050
1051
1052
1053
1054
	ieee80211_queue_delayed_work(sc->hw,
				     &sc->ath_led_blink_work,
				     (sc->sc_flags & SC_OP_LED_ON) ?
					msecs_to_jiffies(sc->led_off_duration) :
					msecs_to_jiffies(sc->led_on_duration));
1055

1056
1057
1058
1059
1060
1061
	sc->led_on_duration = sc->led_on_cnt ?
			max((ATH_LED_ON_DURATION_IDLE - sc->led_on_cnt), 25) :
			ATH_LED_ON_DURATION_IDLE;
	sc->led_off_duration = sc->led_off_cnt ?
			max((ATH_LED_OFF_DURATION_IDLE - sc->led_off_cnt), 10) :
			ATH_LED_OFF_DURATION_IDLE;
1062
1063
1064
1065
1066
1067
1068
	sc->led_on_cnt = sc->led_off_cnt = 0;
	if (sc->sc_flags & SC_OP_LED_ON)
		sc->sc_flags &= ~SC_OP_LED_ON;
	else
		sc->sc_flags |= SC_OP_LED_ON;
}

1069
1070
1071
1072
1073
static void ath_led_brightness(struct led_classdev *led_cdev,
			       enum led_brightness brightness)
{
	struct ath_led *led = container_of(led_cdev, struct ath_led, led_cdev);
	struct ath_softc *sc = led->sc;
1074

1075
1076
1077
	switch (brightness) {
	case LED_OFF:
		if (led->led_type == ATH_LED_ASSOC ||
1078
		    led->led_type == ATH_LED_RADIO) {
1079
			ath9k_hw_set_gpio(sc->sc_ah, sc->sc_ah->led_pin,
1080
				(led->led_type == ATH_LED_RADIO));
1081
			sc->sc_flags &= ~SC_OP_LED_ASSOCIATED;
1082
1083
1084
1085
1086
			if (led->led_type == ATH_LED_RADIO)
				sc->sc_flags &= ~SC_OP_LED_ON;
		} else {
			sc->led_off_cnt++;
		}
1087
1088
		break;
	case LED_FULL:
1089
		if (led->led_type == ATH_LED_ASSOC) {
1090
			sc->sc_flags |= SC_OP_LED_ASSOCIATED;
1091
1092
			ieee80211_queue_delayed_work(sc->hw,
						     &sc->ath_led_blink_work, 0);
1093
		} else if (led->led_type == ATH_LED_RADIO) {
1094
			ath9k_hw_set_gpio(sc->sc_ah, sc->sc_ah->led_pin, 0);
1095
1096
1097
1098
			sc->sc_flags |= SC_OP_LED_ON;
		} else {
			sc->led_on_cnt++;
		}
1099
1100
1101
		break;
	default:
		break;
1102
	}
1103
}
1104

1105
1106
1107
1108
static int ath_register_led(struct ath_softc *sc, struct ath_led *led,
			    char *trigger)
{
	int ret;
1109

1110
1111
1112
1113
	led->sc = sc;
	led->led_cdev.name = led->name;
	led->led_cdev.default_trigger = trigger;
	led->led_cdev.brightness_set = ath_led_brightness;
1114

1115
1116
	ret = led_classdev_register(wiphy_dev(sc->hw->wiphy), &led->led_cdev);
	if (ret)