main.c 60.3 KB
Newer Older
1
/*
2
 * Copyright (c) 2008-2011 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>
18
#include <linux/delay.h>
Sujith's avatar
Sujith committed
19
#include "ath9k.h"
20
#include "btcoex.h"
21

22
u8 ath9k_parse_mpdudensity(u8 mpdudensity)
Sujith's avatar
Sujith committed
23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56
{
	/*
	 * 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;
	}
}

57 58 59 60 61 62
static bool ath9k_has_pending_frames(struct ath_softc *sc, struct ath_txq *txq)
{
	bool pending = false;

	spin_lock_bh(&txq->axq_lock);

63
	if (txq->axq_depth)
64 65
		pending = true;

66 67 68 69 70 71 72
	if (txq->mac80211_qnum >= 0) {
		struct list_head *list;

		list = &sc->cur_chan->acq[txq->mac80211_qnum];
		if (!list_empty(list))
			pending = true;
	}
73 74 75 76
	spin_unlock_bh(&txq->axq_lock);
	return pending;
}

77
static bool ath9k_setpower(struct ath_softc *sc, enum ath9k_power_mode mode)
78 79 80 81
{
	unsigned long flags;
	bool ret;

82 83 84
	spin_lock_irqsave(&sc->sc_pm_lock, flags);
	ret = ath9k_hw_setpower(sc->sc_ah, mode);
	spin_unlock_irqrestore(&sc->sc_pm_lock, flags);
85 86 87 88

	return ret;
}

89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104
void ath_ps_full_sleep(unsigned long data)
{
	struct ath_softc *sc = (struct ath_softc *) data;
	struct ath_common *common = ath9k_hw_common(sc->sc_ah);
	bool reset;

	spin_lock(&common->cc_lock);
	ath_hw_cycle_counters_update(common);
	spin_unlock(&common->cc_lock);

	ath9k_hw_setrxabort(sc->sc_ah, 1);
	ath9k_hw_stopdmarecv(sc->sc_ah, &reset);

	ath9k_hw_setpower(sc->sc_ah, ATH9K_PM_FULL_SLEEP);
}

105 106
void ath9k_ps_wakeup(struct ath_softc *sc)
{
107
	struct ath_common *common = ath9k_hw_common(sc->sc_ah);
108
	unsigned long flags;
109
	enum ath9k_power_mode power_mode;
110 111 112 113 114

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

115
	del_timer_sync(&sc->sleep_timer);
116
	power_mode = sc->sc_ah->power_mode;
117
	ath9k_hw_setpower(sc->sc_ah, ATH9K_PM_AWAKE);
118

119 120 121 122 123
	/*
	 * While the hardware is asleep, the cycle counters contain no
	 * useful data. Better clear them now so that they don't mess up
	 * survey data results.
	 */
124 125 126 127
	if (power_mode != ATH9K_PM_AWAKE) {
		spin_lock(&common->cc_lock);
		ath_hw_cycle_counters_update(common);
		memset(&common->cc_survey, 0, sizeof(common->cc_survey));
128
		memset(&common->cc_ani, 0, sizeof(common->cc_ani));
129 130
		spin_unlock(&common->cc_lock);
	}
131

132 133 134 135 136 137
 unlock:
	spin_unlock_irqrestore(&sc->sc_pm_lock, flags);
}

void ath9k_ps_restore(struct ath_softc *sc)
{
138
	struct ath_common *common = ath9k_hw_common(sc->sc_ah);
139
	enum ath9k_power_mode mode;
140 141 142 143 144 145
	unsigned long flags;

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

Sujith Manoharan's avatar
Sujith Manoharan committed
146
	if (sc->ps_idle) {
147 148 149 150 151
		mod_timer(&sc->sleep_timer, jiffies + HZ / 10);
		goto unlock;
	}

	if (sc->ps_enabled &&
Sujith Manoharan's avatar
Sujith Manoharan committed
152 153 154
		   !(sc->ps_flags & (PS_WAIT_FOR_BEACON |
				     PS_WAIT_FOR_CAB |
				     PS_WAIT_FOR_PSPOLL_DATA |
155 156
				     PS_WAIT_FOR_TX_ACK |
				     PS_WAIT_FOR_ANI))) {
157
		mode = ATH9K_PM_NETWORK_SLEEP;
158 159
		if (ath9k_hw_btcoex_is_enabled(sc->sc_ah))
			ath9k_btcoex_stop_gen_timer(sc);
Sujith Manoharan's avatar
Sujith Manoharan committed
160
	} else {
161
		goto unlock;
Sujith Manoharan's avatar
Sujith Manoharan committed
162
	}
163 164 165 166 167

	spin_lock(&common->cc_lock);
	ath_hw_cycle_counters_update(common);
	spin_unlock(&common->cc_lock);

168
	ath9k_hw_setpower(sc->sc_ah, mode);
169 170 171 172 173

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

174
static void __ath_cancel_work(struct ath_softc *sc)
Sujith's avatar
Sujith committed
175
{
176 177
	cancel_work_sync(&sc->paprd_work);
	cancel_delayed_work_sync(&sc->tx_complete_work);
178
	cancel_delayed_work_sync(&sc->hw_pll_work);
Sujith Manoharan's avatar
Sujith Manoharan committed
179

180
#ifdef CONFIG_ATH9K_BTCOEX_SUPPORT
Sujith Manoharan's avatar
Sujith Manoharan committed
181 182
	if (ath9k_hw_mci_is_enabled(sc->sc_ah))
		cancel_work_sync(&sc->mci_work);
183
#endif
184
}
185

Sujith Manoharan's avatar
Sujith Manoharan committed
186
void ath_cancel_work(struct ath_softc *sc)
187 188 189 190
{
	__ath_cancel_work(sc);
	cancel_work_sync(&sc->hw_reset_work);
}
191

Sujith Manoharan's avatar
Sujith Manoharan committed
192
void ath_restart_work(struct ath_softc *sc)
Sujith Manoharan's avatar
Sujith Manoharan committed
193 194 195
{
	ieee80211_queue_delayed_work(sc->hw, &sc->tx_complete_work, 0);

196
	if (AR_SREV_9340(sc->sc_ah) || AR_SREV_9330(sc->sc_ah))
Sujith Manoharan's avatar
Sujith Manoharan committed
197 198 199
		ieee80211_queue_delayed_work(sc->hw, &sc->hw_pll_work,
				     msecs_to_jiffies(ATH_PLL_WORK_INTERVAL));

Sujith Manoharan's avatar
Sujith Manoharan committed
200
	ath_start_ani(sc);
Sujith Manoharan's avatar
Sujith Manoharan committed
201 202
}

203
static bool ath_prepare_reset(struct ath_softc *sc)
204 205
{
	struct ath_hw *ah = sc->sc_ah;
206
	bool ret = true;
207

208
	ieee80211_stop_queues(sc->hw);
Sujith Manoharan's avatar
Sujith Manoharan committed
209
	ath_stop_ani(sc);
210
	ath9k_hw_disable_interrupts(ah);
211

212
	if (!ath_drain_all_txq(sc))
213
		ret = false;
214

Felix Fietkau's avatar
Felix Fietkau committed
215
	if (!ath_stoprecv(sc))
216 217
		ret = false;

218 219
	return ret;
}
Sujith's avatar
Sujith committed
220

221 222 223 224
static bool ath_complete_reset(struct ath_softc *sc, bool start)
{
	struct ath_hw *ah = sc->sc_ah;
	struct ath_common *common = ath9k_hw_common(ah);
225
	unsigned long flags;
226

227
	ath9k_calculate_summary_state(sc, sc->cur_chan);
Sujith Manoharan's avatar
Sujith Manoharan committed
228
	ath_startrecv(sc);
229
	ath9k_cmn_update_txpow(ah, sc->curtxpow,
230
			       sc->cur_chan->txpower, &sc->curtxpow);
231
	clear_bit(ATH_OP_HW_RESET, &common->op_flags);
232

233
	if (!sc->cur_chan->offchannel && start) {
234 235 236 237 238 239 240 241 242 243
		/* restore per chanctx TSF timer */
		if (sc->cur_chan->tsf_val) {
			u32 offset;

			offset = ath9k_hw_get_tsf_offset(&sc->cur_chan->tsf_ts,
							 NULL);
			ath9k_hw_settsf64(ah, sc->cur_chan->tsf_val + offset);
		}


244
		if (!test_bit(ATH_OP_BEACONS, &common->op_flags))
245 246 247
			goto work;

		if (ah->opmode == NL80211_IFTYPE_STATION &&
248
		    test_bit(ATH_OP_PRIM_STA_VIF, &common->op_flags)) {
249 250 251
			spin_lock_irqsave(&sc->sc_pm_lock, flags);
			sc->ps_flags |= PS_BEACON_SYNC | PS_WAIT_FOR_BEACON;
			spin_unlock_irqrestore(&sc->sc_pm_lock, flags);
252 253
		} else {
			ath9k_set_beacon(sc);
254 255
		}
	work:
Sujith Manoharan's avatar
Sujith Manoharan committed
256
		ath_restart_work(sc);
257
		ath_txq_schedule_all(sc);
258 259
	}

260
	sc->gtt_cnt = 0;
261 262 263 264

	ath9k_hw_set_interrupts(ah);
	ath9k_hw_enable_interrupts(ah);

265
	if (!ath9k_is_chanctx_enabled())
266
		ieee80211_wake_queues(sc->hw);
267 268
	else
		ath9k_chanctx_wake_queues(sc);
269

270 271
	ath9k_p2p_ps_timer(sc);

272 273 274
	return true;
}

275
int ath_reset_internal(struct ath_softc *sc, struct ath9k_channel *hchan)
276 277 278 279 280 281 282 283 284
{
	struct ath_hw *ah = sc->sc_ah;
	struct ath_common *common = ath9k_hw_common(ah);
	struct ath9k_hw_cal_data *caldata = NULL;
	bool fastcc = true;
	int r;

	__ath_cancel_work(sc);

285
	tasklet_disable(&sc->intr_tq);
286
	spin_lock_bh(&sc->sc_pcu_lock);
287

288
	if (!sc->cur_chan->offchannel) {
289
		fastcc = false;
290
		caldata = &sc->cur_chan->caldata;
291 292 293 294 295 296 297
	}

	if (!hchan) {
		fastcc = false;
		hchan = ah->curchan;
	}

298
	if (!ath_prepare_reset(sc))
299 300
		fastcc = false;

301 302 303
	if (ath9k_is_chanctx_enabled())
		fastcc = false;

304 305 306
	spin_lock_bh(&sc->chan_lock);
	sc->cur_chandef = sc->cur_chan->chandef;
	spin_unlock_bh(&sc->chan_lock);
307

308
	ath_dbg(common, CONFIG, "Reset to %u MHz, HT40: %d fastcc: %d\n",
309
		hchan->channel, IS_CHAN_HT40(hchan), fastcc);
310 311 312 313 314

	r = ath9k_hw_reset(ah, hchan, caldata, fastcc);
	if (r) {
		ath_err(common,
			"Unable to reset channel, reset status %d\n", r);
315 316 317 318

		ath9k_hw_enable_interrupts(ah);
		ath9k_queue_reset(sc, RESET_TYPE_BB_HANG);

319 320 321
		goto out;
	}

322
	if (ath9k_hw_mci_is_enabled(sc->sc_ah) &&
323
	    sc->cur_chan->offchannel)
324 325
		ath9k_mci_set_txpower(sc, true, false);

326 327 328 329
	if (!ath_complete_reset(sc, true))
		r = -EIO;

out:
330
	spin_unlock_bh(&sc->sc_pcu_lock);
331 332
	tasklet_enable(&sc->intr_tq);

333 334 335
	return r;
}

336 337
static void ath_node_attach(struct ath_softc *sc, struct ieee80211_sta *sta,
			    struct ieee80211_vif *vif)
Sujith's avatar
Sujith committed
338 339 340 341
{
	struct ath_node *an;
	an = (struct ath_node *)sta->drv_priv;

342
	an->sc = sc;
343
	an->sta = sta;
344
	an->vif = vif;
345
	memset(&an->key_idx, 0, sizeof(an->key_idx));
346

347
	ath_tx_node_init(sc, an);
348 349

	ath_dynack_node_init(sc->sc_ah, an);
Sujith's avatar
Sujith committed
350 351 352 353 354
}

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

	ath_dynack_node_deinit(sc->sc_ah, an);
Sujith's avatar
Sujith committed
358 359
}

Sujith's avatar
Sujith committed
360
void ath9k_tasklet(unsigned long data)
Sujith's avatar
Sujith committed
361 362
{
	struct ath_softc *sc = (struct ath_softc *)data;
363
	struct ath_hw *ah = sc->sc_ah;
364
	struct ath_common *common = ath9k_hw_common(ah);
365
	enum ath_reset_type type;
366
	unsigned long flags;
Sujith's avatar
Sujith committed
367
	u32 status = sc->intrstatus;
Felix Fietkau's avatar
Felix Fietkau committed
368
	u32 rxmask;
Sujith's avatar
Sujith committed
369

370 371 372
	ath9k_ps_wakeup(sc);
	spin_lock(&sc->sc_pcu_lock);

373 374
	if (status & ATH9K_INT_FATAL) {
		type = RESET_TYPE_FATAL_INT;
375
		ath9k_queue_reset(sc, type);
376 377 378 379 380 381

		/*
		 * Increment the ref. counter here so that
		 * interrupts are enabled in the reset routine.
		 */
		atomic_inc(&ah->intr_ref_cnt);
382
		ath_dbg(common, RESET, "FATAL: Skipping interrupts\n");
383
		goto out;
384
	}
Sujith's avatar
Sujith committed
385

386 387
	if ((ah->config.hw_hang_checks & HW_BB_WATCHDOG) &&
	    (status & ATH9K_INT_BB_WATCHDOG)) {
388 389 390 391 392
		spin_lock(&common->cc_lock);
		ath_hw_cycle_counters_update(common);
		ar9003_hw_bb_watchdog_dbg_info(ah);
		spin_unlock(&common->cc_lock);

393 394 395 396 397 398 399 400 401
		if (ar9003_hw_bb_watchdog_check(ah)) {
			type = RESET_TYPE_BB_WATCHDOG;
			ath9k_queue_reset(sc, type);

			/*
			 * Increment the ref. counter here so that
			 * interrupts are enabled in the reset routine.
			 */
			atomic_inc(&ah->intr_ref_cnt);
402
			ath_dbg(common, RESET,
403 404 405 406 407
				"BB_WATCHDOG: Skipping interrupts\n");
			goto out;
		}
	}

408 409 410 411 412 413 414
	if (status & ATH9K_INT_GTT) {
		sc->gtt_cnt++;

		if ((sc->gtt_cnt >= MAX_GTT_CNT) && !ath9k_hw_check_alive(ah)) {
			type = RESET_TYPE_TX_GTT;
			ath9k_queue_reset(sc, type);
			atomic_inc(&ah->intr_ref_cnt);
415
			ath_dbg(common, RESET,
416 417 418 419 420
				"GTT: Skipping interrupts\n");
			goto out;
		}
	}

421
	spin_lock_irqsave(&sc->sc_pm_lock, flags);
422 423 424 425 426
	if ((status & ATH9K_INT_TSFOOR) && sc->ps_enabled) {
		/*
		 * TSF sync does not look correct; remain awake to sync with
		 * the next Beacon.
		 */
427
		ath_dbg(common, PS, "TSFOOR - Sync with next Beacon\n");
428
		sc->ps_flags |= PS_WAIT_FOR_BEACON | PS_BEACON_SYNC;
429
	}
430
	spin_unlock_irqrestore(&sc->sc_pm_lock, flags);
431

Felix Fietkau's avatar
Felix Fietkau committed
432 433 434 435 436 437 438 439 440 441 442 443 444
	if (ah->caps.hw_caps & ATH9K_HW_CAP_EDMA)
		rxmask = (ATH9K_INT_RXHP | ATH9K_INT_RXLP | ATH9K_INT_RXEOL |
			  ATH9K_INT_RXORN);
	else
		rxmask = (ATH9K_INT_RX | ATH9K_INT_RXEOL | ATH9K_INT_RXORN);

	if (status & rxmask) {
		/* Check for high priority Rx first */
		if ((ah->caps.hw_caps & ATH9K_HW_CAP_EDMA) &&
		    (status & ATH9K_INT_RXHP))
			ath_rx_tasklet(sc, 0, true);

		ath_rx_tasklet(sc, 0, false);
Sujith's avatar
Sujith committed
445 446
	}

447
	if (status & ATH9K_INT_TX) {
448 449 450 451 452 453 454
		if (ah->caps.hw_caps & ATH9K_HW_CAP_EDMA) {
			/*
			 * For EDMA chips, TX completion is enabled for the
			 * beacon queue, so if a beacon has been transmitted
			 * successfully after a GTT interrupt, the GTT counter
			 * gets reset to zero here.
			 */
Sujith Manoharan's avatar
Sujith Manoharan committed
455
			sc->gtt_cnt = 0;
456

457
			ath_tx_edma_tasklet(sc);
458
		} else {
459
			ath_tx_tasklet(sc);
460
		}
Felix Fietkau's avatar
Felix Fietkau committed
461 462

		wake_up(&sc->tx_wait);
463
	}
464

465 466 467
	if (status & ATH9K_INT_GENTIMER)
		ath_gen_timer_isr(sc->sc_ah);

468
	ath9k_btcoex_handle_interrupt(sc, status);
469

Sujith's avatar
Sujith committed
470
	/* re-enable hardware interrupt */
471
	ath9k_hw_enable_interrupts(ah);
472
out:
473
	spin_unlock(&sc->sc_pcu_lock);
474
	ath9k_ps_restore(sc);
Sujith's avatar
Sujith committed
475 476
}

477
irqreturn_t ath_isr(int irq, void *dev)
Sujith's avatar
Sujith committed
478
{
479 480
#define SCHED_INTR (				\
		ATH9K_INT_FATAL |		\
481
		ATH9K_INT_BB_WATCHDOG |		\
482 483 484
		ATH9K_INT_RXORN |		\
		ATH9K_INT_RXEOL |		\
		ATH9K_INT_RX |			\
Felix Fietkau's avatar
Felix Fietkau committed
485 486
		ATH9K_INT_RXLP |		\
		ATH9K_INT_RXHP |		\
487 488 489
		ATH9K_INT_TX |			\
		ATH9K_INT_BMISS |		\
		ATH9K_INT_CST |			\
490
		ATH9K_INT_GTT |			\
491
		ATH9K_INT_TSFOOR |		\
492 493
		ATH9K_INT_GENTIMER |		\
		ATH9K_INT_MCI)
494

Sujith's avatar
Sujith committed
495
	struct ath_softc *sc = dev;
496
	struct ath_hw *ah = sc->sc_ah;
497
	struct ath_common *common = ath9k_hw_common(ah);
Sujith's avatar
Sujith committed
498
	enum ath9k_int status;
499
	u32 sync_cause = 0;
Sujith's avatar
Sujith committed
500 501
	bool sched = false;

502 503 504 505 506
	/*
	 * The hardware is not ready/present, don't
	 * touch anything. Note this can happen early
	 * on if the IRQ is shared.
	 */
507
	if (test_bit(ATH_OP_INVALID, &common->op_flags))
508
		return IRQ_NONE;
Sujith's avatar
Sujith committed
509

510 511
	/* shared irq, not for us */

512
	if (!ath9k_hw_intrpend(ah))
513 514
		return IRQ_NONE;

515
	if (test_bit(ATH_OP_HW_RESET, &common->op_flags)) {
516
		ath9k_hw_kill_interrupts(ah);
517
		return IRQ_HANDLED;
518
	}
519

520 521 522 523 524 525
	/*
	 * 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.
	 */
526 527
	ath9k_hw_getisr(ah, &status, &sync_cause); /* NB: clears ISR too */
	ath9k_debug_sync_cause(sc, sync_cause);
Pavel Roskin's avatar
Pavel Roskin committed
528
	status &= ah->imask;	/* discard unasked-for bits */
Sujith's avatar
Sujith committed
529

530 531 532 533
	/*
	 * If there are no status bits set, then this interrupt was not
	 * for me (should have been caught above).
	 */
534
	if (!status)
535
		return IRQ_NONE;
Sujith's avatar
Sujith committed
536

537 538 539 540 541 542 543 544 545 546
	/* 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.
	 */
Felix Fietkau's avatar
Felix Fietkau committed
547 548
	if ((status & ATH9K_INT_FATAL) || ((status & ATH9K_INT_RXORN) &&
	    !(ah->caps.hw_caps & ATH9K_HW_CAP_EDMA)))
549 550
		goto chip_reset;

551
	if ((ah->config.hw_hang_checks & HW_BB_WATCHDOG) &&
552
	    (status & ATH9K_INT_BB_WATCHDOG))
553
		goto chip_reset;
Sujith Manoharan's avatar
Sujith Manoharan committed
554 555

#ifdef CONFIG_ATH9K_WOW
556 557 558 559 560 561 562
	if (status & ATH9K_INT_BMISS) {
		if (atomic_read(&sc->wow_sleep_proc_intr) == 0) {
			atomic_inc(&sc->wow_got_bmiss_intr);
			atomic_dec(&sc->wow_sleep_proc_intr);
		}
	}
#endif
Sujith Manoharan's avatar
Sujith Manoharan committed
563

564 565 566 567 568 569
	if (status & ATH9K_INT_SWBA)
		tasklet_schedule(&sc->bcon_tasklet);

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

570 571
	if (status & ATH9K_INT_RXEOL) {
		ah->imask &= ~(ATH9K_INT_RXEOL | ATH9K_INT_RXORN);
572
		ath9k_hw_set_interrupts(ah);
Felix Fietkau's avatar
Felix Fietkau committed
573 574
	}

575 576
	if (!(ah->caps.hw_caps & ATH9K_HW_CAP_AUTOSLEEP))
		if (status & ATH9K_INT_TIM_TIMER) {
577 578
			if (ATH_DBG_WARN_ON_ONCE(sc->ps_idle))
				goto chip_reset;
579 580
			/* Clear RxAbort bit so that we can
			 * receive frames */
581
			ath9k_setpower(sc, ATH9K_PM_AWAKE);
582
			spin_lock(&sc->sc_pm_lock);
583
			ath9k_hw_setrxabort(sc->sc_ah, 0);
Sujith's avatar
Sujith committed
584
			sc->ps_flags |= PS_WAIT_FOR_BEACON;
585
			spin_unlock(&sc->sc_pm_lock);
Sujith's avatar
Sujith committed
586
		}
587 588

chip_reset:
Sujith's avatar
Sujith committed
589

590 591
	ath_debug_stat_interrupt(sc, status);

Sujith's avatar
Sujith committed
592
	if (sched) {
593 594
		/* turn off every interrupt */
		ath9k_hw_disable_interrupts(ah);
Sujith's avatar
Sujith committed
595 596 597 598
		tasklet_schedule(&sc->intr_tq);
	}

	return IRQ_HANDLED;
599 600

#undef SCHED_INTR
Sujith's avatar
Sujith committed
601 602
}

603
int ath_reset(struct ath_softc *sc)
Sujith's avatar
Sujith committed
604
{
605
	int r;
Sujith's avatar
Sujith committed
606

607
	ath9k_ps_wakeup(sc);
608
	r = ath_reset_internal(sc, NULL);
609
	ath9k_ps_restore(sc);
Sujith's avatar
Sujith committed
610

611
	return r;
Sujith's avatar
Sujith committed
612 613
}

614 615
void ath9k_queue_reset(struct ath_softc *sc, enum ath_reset_type type)
{
616
	struct ath_common *common = ath9k_hw_common(sc->sc_ah);
617 618 619
#ifdef CONFIG_ATH9K_DEBUGFS
	RESET_STAT_INC(sc, type);
#endif
620
	set_bit(ATH_OP_HW_RESET, &common->op_flags);
621 622 623
	ieee80211_queue_work(sc->hw, &sc->hw_reset_work);
}

624 625 626 627
void ath_reset_work(struct work_struct *work)
{
	struct ath_softc *sc = container_of(work, struct ath_softc, hw_reset_work);

628
	ath_reset(sc);
629 630
}

Sujith's avatar
Sujith committed
631 632 633 634
/**********************/
/* mac80211 callbacks */
/**********************/

635
static int ath9k_start(struct ieee80211_hw *hw)
636
{
637
	struct ath_softc *sc = hw->priv;
638
	struct ath_hw *ah = sc->sc_ah;
639
	struct ath_common *common = ath9k_hw_common(ah);
640
	struct ieee80211_channel *curchan = sc->cur_chan->chandef.chan;
641
	struct ath_chanctx *ctx = sc->cur_chan;
Sujith's avatar
Sujith committed
642
	struct ath9k_channel *init_channel;
643
	int r;
644

645
	ath_dbg(common, CONFIG,
646 647
		"Starting driver with initial channel: %d MHz\n",
		curchan->center_freq);
648

649
	ath9k_ps_wakeup(sc);
650 651
	mutex_lock(&sc->mutex);

652
	init_channel = ath9k_cmn_get_channel(hw, ah, &ctx->chandef);
653
	sc->cur_chandef = hw->conf.chandef;
Sujith's avatar
Sujith committed
654 655

	/* Reset SERDES registers */
656
	ath9k_hw_configpcipowersave(ah, false);
Sujith's avatar
Sujith committed
657 658 659 660 661 662 663 664

	/*
	 * The basic interface to setting the hardware in a good
	 * state is ``reset''.  On return the hardware is known to
	 * be powered up and with interrupts disabled.  This must
	 * be followed by initialization of the appropriate bits
	 * and then setup of the interrupt mask.
	 */
665
	spin_lock_bh(&sc->sc_pcu_lock);
666 667 668

	atomic_set(&ah->intr_ref_cnt, -1);

669
	r = ath9k_hw_reset(ah, init_channel, ah->caldata, false);
670
	if (r) {
671 672 673
		ath_err(common,
			"Unable to reset hardware; reset status %d (freq %u MHz)\n",
			r, curchan->center_freq);
674
		ah->reset_power_on = false;
Sujith's avatar
Sujith committed
675 676 677
	}

	/* Setup our intr mask. */
Felix Fietkau's avatar
Felix Fietkau committed
678 679 680 681 682
	ah->imask = ATH9K_INT_TX | ATH9K_INT_RXEOL |
		    ATH9K_INT_RXORN | ATH9K_INT_FATAL |
		    ATH9K_INT_GLOBAL;

	if (ah->caps.hw_caps & ATH9K_HW_CAP_EDMA)
683
		ah->imask |= ATH9K_INT_RXHP |
684
			     ATH9K_INT_RXLP;
Felix Fietkau's avatar
Felix Fietkau committed
685 686
	else
		ah->imask |= ATH9K_INT_RX;
Sujith's avatar
Sujith committed
687

688 689 690
	if (ah->config.hw_hang_checks & HW_BB_WATCHDOG)
		ah->imask |= ATH9K_INT_BB_WATCHDOG;

691 692 693 694 695 696
	/*
	 * Enable GTT interrupts only for AR9003/AR9004 chips
	 * for now.
	 */
	if (AR_SREV_9300_20_OR_LATER(ah))
		ah->imask |= ATH9K_INT_GTT;
Sujith's avatar
Sujith committed
697

698
	if (ah->caps.hw_caps & ATH9K_HW_CAP_HT)
Pavel Roskin's avatar
Pavel Roskin committed
699
		ah->imask |= ATH9K_INT_CST;
Sujith's avatar
Sujith committed
700

701
	ath_mci_enable(sc);
702

703
	clear_bit(ATH_OP_INVALID, &common->op_flags);
704
	sc->sc_ah->is_monitoring = false;
Sujith's avatar
Sujith committed
705

706 707
	if (!ath_complete_reset(sc, false))
		ah->reset_power_on = false;
Sujith's avatar
Sujith committed
708

709 710 711 712 713 714 715 716 717 718 719 720
	if (ah->led_pin >= 0) {
		ath9k_hw_cfg_output(ah, ah->led_pin,
				    AR_GPIO_OUTPUT_MUX_AS_OUTPUT);
		ath9k_hw_set_gpio(ah, ah->led_pin, 0);
	}

	/*
	 * Reset key cache to sane defaults (all entries cleared) instead of
	 * semi-random values after suspend/resume.
	 */
	ath9k_cmn_init_crypto(sc->sc_ah);

721 722
	ath9k_hw_reset_tsf(ah);

723
	spin_unlock_bh(&sc->sc_pcu_lock);
724

725 726
	mutex_unlock(&sc->mutex);

727 728
	ath9k_ps_restore(sc);

729
	return 0;
730 731
}

732 733 734
static void ath9k_tx(struct ieee80211_hw *hw,
		     struct ieee80211_tx_control *control,
		     struct sk_buff *skb)
735
{
736
	struct ath_softc *sc = hw->priv;
737
	struct ath_common *common = ath9k_hw_common(sc->sc_ah);
Sujith's avatar
Sujith committed
738
	struct ath_tx_control txctl;
739
	struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
740
	unsigned long flags;
Sujith's avatar
Sujith committed
741

742
	if (sc->ps_enabled) {
743 744 745 746 747 748 749
		/*
		 * mac80211 does not set PM field for normal data frames, so we
		 * need to update that based on the current PS mode.
		 */
		if (ieee80211_is_data(hdr->frame_control) &&
		    !ieee80211_is_nullfunc(hdr->frame_control) &&
		    !ieee80211_has_pm(hdr->frame_control)) {
750
			ath_dbg(common, PS,
751
				"Add PM=1 for a TX frame while in PS mode\n");
752 753 754 755
			hdr->frame_control |= cpu_to_le16(IEEE80211_FCTL_PM);
		}
	}

Sujith Manoharan's avatar
Sujith Manoharan committed
756
	if (unlikely(sc->sc_ah->power_mode == ATH9K_PM_NETWORK_SLEEP)) {
757 758 759 760 761 762
		/*
		 * We are using PS-Poll and mac80211 can request TX while in
		 * power save mode. Need to wake up hardware for the TX to be
		 * completed and if needed, also for RX of buffered frames.
		 */
		ath9k_ps_wakeup(sc);
763
		spin_lock_irqsave(&sc->sc_pm_lock, flags);
764 765
		if (!(sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_AUTOSLEEP))
			ath9k_hw_setrxabort(sc->sc_ah, 0);
766
		if (ieee80211_is_pspoll(hdr->frame_control)) {
767
			ath_dbg(common, PS,
768
				"Sending PS-Poll to pick a buffered frame\n");
Sujith's avatar
Sujith committed
769
			sc->ps_flags |= PS_WAIT_FOR_PSPOLL_DATA;
770
		} else {
771
			ath_dbg(common, PS, "Wake up to complete TX\n");
Sujith's avatar
Sujith committed
772
			sc->ps_flags |= PS_WAIT_FOR_TX_ACK;
773 774 775
		}
		/*
		 * The actual restore operation will happen only after
Sujith Manoharan's avatar
Sujith Manoharan committed
776
		 * the ps_flags bit is cleared. We are just dropping
777 778
		 * the ps_usecount here.
		 */
779
		spin_unlock_irqrestore(&sc->sc_pm_lock, flags);
780 781 782
		ath9k_ps_restore(sc);
	}

Sujith Manoharan's avatar
Sujith Manoharan committed
783 784 785 786 787 788 789 790 791
	/*
	 * Cannot tx while the hardware is in full sleep, it first needs a full
	 * chip reset to recover from that
	 */
	if (unlikely(sc->sc_ah->power_mode == ATH9K_PM_FULL_SLEEP)) {
		ath_err(common, "TX while HW is in FULL_SLEEP mode\n");
		goto exit;
	}

Sujith's avatar
Sujith committed
792
	memset(&txctl, 0, sizeof(struct ath_tx_control));
793
	txctl.txq = sc->tx.txq_map[skb_get_queue_mapping(skb)];
794
	txctl.sta = control->sta;
Sujith's avatar
Sujith committed
795

796
	ath_dbg(common, XMIT, "transmitting packet, skb: %p\n", skb);
797

798
	if (ath_tx_start(hw, skb, &txctl) != 0) {
799
		ath_dbg(common, XMIT, "TX failed\n");
Ben Greear's avatar
Ben Greear committed
800
		TX_STAT_INC(txctl.txq->axq_qnum, txfailed);
Sujith's avatar
Sujith committed
801
		goto exit;
802 803
	}

804
	return;
Sujith's avatar
Sujith committed
805
exit:
806
	ieee80211_free_txskb(hw, skb);
807 808
}

809
static void ath9k_stop(struct ieee80211_hw *hw)
810
{
811
	struct ath_softc *sc = hw->priv;
812
	struct ath_hw *ah = sc->sc_ah;
813
	struct ath_common *common = ath9k_hw_common(ah);
814
	bool prev_idle;
815

816 817
	ath9k_deinit_channel_context(sc);

Sujith's avatar
Sujith committed
818 819
	mutex_lock(&sc->mutex);

820
	ath_cancel_work(sc);
821

822
	if (test_bit(ATH_OP_INVALID, &common->op_flags)) {
823
		ath_dbg(common, ANY, "Device not present\n");
Sujith's avatar
Sujith committed
824
		mutex_unlock(&sc->mutex);
Sujith's avatar
Sujith committed
825 826
		return;
	}
827

828 829 830
	/* Ensure HW is awake when we try to shut it down. */
	ath9k_ps_wakeup(sc);

831 832
	spin_lock_bh(&sc->sc_pcu_lock);

833 834 835
	/* prevent tasklets to enable interrupts once we disable them */
	ah->imask &= ~ATH9K_INT_GLOBAL;

Sujith's avatar
Sujith committed
836 837
	/* make sure h/w will not generate any interrupt
	 * before setting the invalid flag. */
838
	ath9k_hw_disable_interrupts(ah);
Sujith's avatar
Sujith committed
839

840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857
	spin_unlock_bh(&sc->sc_pcu_lock);

	/* we can now sync irq and kill any running tasklets, since we already
	 * disabled interrupts and not holding a spin lock */
	synchronize_irq(sc->irq);
	tasklet_kill(&sc->intr_tq);
	tasklet_kill(&sc->bcon_tasklet);

	prev_idle = sc->ps_idle;
	sc->ps_idle = true;

	spin_lock_bh(&sc->sc_pcu_lock);

	if (ah->led_pin >= 0) {
		ath9k_hw_set_gpio(ah, ah->led_pin, 1);
		ath9k_hw_cfg_gpio_input(ah, ah->led_pin);
	}

858
	ath_prepare_reset(sc);
Sujith's avatar
Sujith committed
859

860 861 862 863 864
	if (sc->rx.frag) {
		dev_kfree_skb_any(sc->rx.frag);
		sc->rx.frag = NULL;
	}

865
	if (!ah->curchan)
866 867
		ah->curchan = ath9k_cmn_get_channel(hw, ah,
						    &sc->cur_chan->chandef);
868

869 870
	ath9k_hw_reset(ah, ah->curchan, ah->caldata, false);
	ath9k_hw_phy_disable(ah);
871

872
	ath9k_hw_configpcipowersave(ah, true);
873

874
	spin_unlock_bh(&sc->sc_pcu_lock);
875

876
	ath9k_ps_restore(sc);
Sujith's avatar
Sujith committed
877

878
	set_bit(ATH_OP_INVALID, &common->op_flags);
879
	sc->ps_idle = prev_idle;
880

881 882
	mutex_unlock(&sc->mutex);

883
	ath_dbg(common, CONFIG, "Driver halt\n");
884 885
}

886
static bool ath9k_uses_beacons(int type)
887 888 889 890 891 892 893 894 895 896 897
{
	switch (type) {
	case NL80211_IFTYPE_AP:
	case NL80211_IFTYPE_ADHOC:
	case NL80211_IFTYPE_MESH_POINT:
		return true;
	default:
		return false;
	}
}

898 899
static void ath9k_vif_iter(struct ath9k_vif_iter_data *iter_data,
			   u8 *mac, struct ieee80211_vif *vif)
900
{
901
	struct ath_vif *avp = (struct ath_vif *)vif->drv_priv;
902 903
	int i;

904
	if (iter_data->has_hw_macaddr) {
905 906 907
		for (i = 0; i < ETH_ALEN; i++)
			iter_data->mask[i] &=
				~(iter_data->hw_macaddr[i] ^ mac[i]);
908 909 910 911
	} else {
		memcpy(iter_data->hw_macaddr, mac, ETH_ALEN);
		iter_data->has_hw_macaddr = true;
	}
912

913 914 915
	if (!vif->bss_conf.use_short_slot)
		iter_data->slottime = ATH9K_SLOT_TIME_20;

916
	switch (vif->type) {
917 918
	case NL80211_IFTYPE_AP:
		iter_data->naps++;
919
		break;
920 921
	case NL80211_IFTYPE_STATION:
		iter_data->nstations++;
922
		if (avp->assoc && !iter_data->primary_sta)
923
			iter_data->primary_sta = vif;
924
		break;
925
	case NL80211_IFTYPE_ADHOC:
926
		iter_data->nadhocs++;
927 928
		if (vif->bss_conf.enable_beacon)
			iter_data->beacons = true;
929
		break;
930
	case NL80211_IFTYPE_MESH_POINT:
931
		iter_data->nmeshes++;
932 933
		if (vif->bss_conf.enable_beacon)
			iter_data->beacons = true;
934 935 936
		break;
	case NL80211_IFTYPE_WDS:
		iter_data->nwds++;
937 938
		break;
	default:
939
		break;
940
	}
941
}
942

943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970
static void ath9k_update_bssid_mask(struct ath_softc *sc,
				    struct ath_chanctx *ctx,
				    struct ath9k_vif_iter_data *iter_data)
{
	struct ath_common *common = ath9k_hw_common(sc->sc_ah);
	struct ath_vif *avp;
	int i;

	if (!ath9k_is_chanctx_enabled())
		return;

	list_for_each_entry(avp, &ctx->vifs, list) {
		if (ctx->nvifs_assigned != 1)
			continue;

		if (!avp->vif->p2p || !iter_data->has_hw_macaddr)
			continue;

		ether_addr_copy(common->curbssid, avp->bssid);

		/* perm_addr will be used as the p2p device address. */
		for (i = 0; i < ETH_ALEN; i++)
			iter_data->mask[i] &=
				~(iter_data->hw_macaddr[i] ^
				  sc->hw->wiphy->perm_addr[i]);
	}
}

971
/* Called with sc->mutex held. */
972 973
void ath9k_calculate_iter_data(struct ath_softc *sc,
			       struct ath_chanctx *ctx,
974 975
			       struct ath9k_vif_iter_data *iter_data)
{
976
	struct ath_vif *avp;
977

978
	/*
979 980 981
	 * Pick the MAC address of the first interface as the new hardware
	 * MAC address. The hardware will use it together with the BSSID mask
	 * when matching addresses.
982 983 984
	 */
	memset(iter_data, 0, sizeof(*iter_data));
	memset(&iter_data->mask, 0xff, ETH_ALEN);
985 986 987 988
	iter_data->slottime = ATH9K_SLOT_TIME_9;

	list_for_each_entry(avp, &ctx->vifs, list)
		ath9k_vif_iter(iter_data, avp->vif->addr, avp->vif);
989 990

	ath9k_update_bssid_mask(sc, ctx, iter_data);
991 992 993 994 995 996
}

static void ath9k_set_assoc_state(struct ath_softc *sc,
				  struct ieee80211_vif *vif, bool changed)
{
	struct ath_common *common = ath9k_hw_common(sc->sc_ah);
997
	struct ath_vif *avp = (struct ath_vif *)vif->drv_priv;
998 999 1000 1001
	unsigned long flags;

	set_bit(ATH_OP_PRIM_STA_VIF, &common->op_flags);

1002 1003
	ether_addr_copy(common->curbssid, avp->bssid);
	common->curaid = avp->aid;
1004 1005 1006 1007 1008
	ath9k_hw_write_associd(sc->sc_ah);

	if (changed) {
		common->last_rssi = ATH_RSSI_DUMMY_MARKER;
		sc->sc_ah->stats.avgbrssi = ATH_RSSI_DUMMY_MARKER;
Sujith's avatar
Sujith committed
1009

1010 1011 1012 1013
		spin_lock_irqsave(&sc->sc_pm_lock, flags);
		sc->ps_flags |= PS_BEACON_SYNC | PS_WAIT_FOR_BEACON;
		spin_unlock_irqrestore(&sc->sc_pm_lock, flags);
	}
1014

1015 1016
	if (ath9k_hw_mci_is_enabled(sc->sc_ah))
		ath9k_mci_update_wlan_channels(sc, false);
1017

1018 1019 1020
	ath_dbg(common, CONFIG,
		"Primary Station interface: %pM, BSSID: %pM\n",
		vif->addr, common->curbssid);
1021
}
1022

1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059
#ifdef CONFIG_ATH9K_CHANNEL_CONTEXT
static void ath9k_set_offchannel_state(struct ath_softc *sc)
{
	struct ath_hw *ah = sc->sc_ah;
	struct ath_common *common = ath9k_hw_common(ah);
	struct ieee80211_vif *vif = NULL;

	ath9k_ps_wakeup(sc);

	if (sc->offchannel.state < ATH_OFFCHANNEL_ROC_START)
		vif = sc->offchannel.scan_vif;
	else
		vif = sc->offchannel.roc_vif;

	if (WARN_ON(!vif))
		goto exit;

	eth_zero_addr(common->curbssid);
	eth_broadcast_addr(common->bssidmask);
	ether_addr_copy(common->macaddr, vif->addr);
	common->curaid = 0;
	ah->opmode = vif->type;
	ah->imask &= ~ATH9K_INT_SWBA;
	ah->imask &= ~ATH9K_INT_TSFOOR;
	ah->slottime = ATH9K_SLOT_TIME_9;

	ath_hw_setbssidmask(common);
	ath9k_hw_setopmode(ah);
	ath9k_hw_write_associd(sc->sc_ah);
	ath9k_hw_set_interrupts(ah);
	ath9k_hw_init_global_settings(ah);

exit:
	ath9k_ps_restore(sc);
}
#endif

1060
/* Called with sc->mutex held. */
1061 1062
void ath9k_calculate_summary_state(struct ath_softc *sc,
				   struct ath_chanctx *ctx)
1063 1064 1065 1066
{
	struct ath_hw *ah = sc->sc_ah;
	struct ath_common *common = ath9k_hw_common(ah);
	struct ath9k_vif_iter_data iter_data;
1067
	struct ath_beacon_config *cur_conf;
1068

1069 1070 1071 1072 1073
	ath_chanctx_check_active(sc, ctx);

	if (ctx != sc->cur_chan)
		return;

1074 1075 1076 1077 1078
#ifdef CONFIG_ATH9K_CHANNEL_CONTEXT
	if (ctx == &sc->offchannel.chan)
		return ath9k_set_offchannel_state(sc);
#endif

1079 1080 1081 1082 1083
	ath9k_ps_wakeup(sc);
	ath9k_calculate_iter_data(sc, ctx, &iter_data);

	if (iter_data.has_hw_macaddr)
		ether_addr_copy(common->macaddr, iter_data.hw_macaddr);
1084

1085 1086 1087 1088
	memcpy(common->bssidmask, iter_data.mask, ETH_ALEN);
	ath_hw_setbssidmask(common);

	if (iter_data.naps > 0) {
1089
		cur_conf = &ctx->beacon;
1090
		ath9k_hw_set_tsfadjust(ah, true);
1091
		ah->opmode = NL80211_IFTYPE_AP;
1092 1093
		if (cur_conf->enable_beacon)
			iter_data.beacons = true;
1094
	} else {
1095
		ath9k_hw_set_tsfadjust(ah, false);
Sujith's avatar
Sujith committed
1096

1097 1098 1099
		if (iter_data.nmeshes)
			ah->opmode = NL80211_IFTYPE_MESH_POINT;
		else if (iter_data.nwds)
1100 1101 1102 1103 1104 1105
			ah->opmode = NL80211_IFTYPE_AP;
		else if (iter_data.nadhocs)
			ah->opmode = NL80211_IFTYPE_ADHOC;
		else
			ah->opmode = NL80211_IFTYPE_STATION;
	}
Sujith's avatar
Sujith committed
1106

1107 1108
	ath9k_hw_setopmode(ah);

1109
	ctx->switch_after_beacon = false;
1110
	if ((iter_data.nstations + iter_data.nadhocs + iter_data.nmeshes) > 0)
Pavel Roskin's avatar
Pavel Roskin committed
1111
		ah->imask |= ATH9K_INT_TSFOOR;
1112
	else {
1113
		ah->imask &= ~ATH9K_INT_TSFOOR;
1114 1115 1116
		if (iter_data.naps == 1 && iter_data.beacons)
			ctx->switch_after_beacon = true;
	}
1117

1118 1119 1120 1121 1122
	ah->imask &= ~ATH9K_INT_SWBA;
	if (ah->opmode == NL80211_IFTYPE_STATION) {
		bool changed = (iter_data.primary_sta != ctx->primary_sta);

		if (iter_data.primary_sta) {
1123
			iter_data.beacons = true;
1124 1125
			ath9k_set_assoc_state(sc, iter_data.primary_sta,
					      changed);
1126
			ctx->primary_sta = iter_data.primary_sta;
1127 1128 1129 1130 1131 1132 1133 1134 1135 1136 1137
		} else {
			ctx->primary_sta = NULL;
			memset(common->curbssid, 0, ETH_ALEN);
			common->curaid = 0;
			ath9k_hw_write_associd(sc->sc_ah);
			if (ath9k_hw_mci_is_enabled(sc->sc_ah))
				ath9k_mci_update_wlan_channels(sc, true);
		}
	} else if (iter_data.beacons) {
		ah->imask |= ATH9K_INT_SWBA;
	}
1138
	ath9k_hw_set_interrupts(ah);
1139

1140 1141 1142 1143 1144 1145 1146 1147
	if (iter_data.beacons)
		set_bit(ATH_OP_BEACONS, &common->op_flags);
	else
		clear_bit(ATH_OP_BEACONS, &common->op_flags);

	if (ah->slottime != iter_data.slottime) {
		ah->slottime = iter_data.slottime;
		ath9k_hw_init_global_settings(ah);
1148
	}
1149 1150 1151 1152 1153 1154

	if (iter_data.primary_sta)
		set_bit(ATH_OP_PRIM_STA_VIF, &common->op_flags);
	else
		clear_bit(ATH_OP_PRIM_STA_VIF, &common->op_flags);

1155 1156 1157 1158
	ath_dbg(common, CONFIG,
		"macaddr: %pM, bssid: %pM, bssidmask: %pM\n",
		common->macaddr, common->curbssid, common->bssidmask);

1159
	ath9k_ps_restore(sc);
1160
}
1161

1162 1163 1164 1165 1166 1167 1168 1169 1170 1171 1172 1173 1174 1175
static void ath9k_assign_hw_queues(struct ieee80211_hw *hw,
				   struct ieee80211_vif *vif)
{
	int i;

	for (i = 0; i < IEEE80211_NUM_ACS; i++)
		vif->hw_queue[i] = i;

	if (vif->type == NL80211_IFTYPE_AP)
		vif->cab_queue = hw->queues - 2;
	else
		vif->cab_queue = IEEE80211_INVAL_HW_QUEUE;
}

1176 1177
static int ath9k_add_interface(struct ieee80211_hw *hw,
			       struct ieee80211_vif *vif)
1178
{
1179
	struct ath_softc *sc = hw->priv;
1180 1181
	struct ath_hw *ah = sc->sc_ah;
	struct ath_common *common = ath9k_hw_common(ah);
1182 1183
	struct ath_vif *avp = (void *)vif->drv_priv;
	struct ath_node *an = &avp->mcast_node;
1184

1185
	mutex_lock(&sc->mutex);
1186

Luis R. Rodriguez's avatar
Luis R. Rodriguez committed
1187
	if (config_enabled(CONFIG_ATH9K_TX99)) {
1188
		if (sc->cur_chan->nvifs >= 1) {
Luis R. Rodriguez's avatar
Luis R. Rodriguez committed
1189 1190 1191 1192 1193 1194
			mutex_unlock(&sc->mutex);
			return -EOPNOTSUPP;
		}
		sc->tx99_vif = vif;
	}

1195
	ath_dbg(common, CONFIG, "Attach a VIF of type: %d\n", vif->type);
1196
	sc->cur_chan->nvifs++;
1197

Sujith Manoharan's avatar
Sujith Manoharan committed
1198 1199 1200
	if (ath9k_uses_beacons(vif->type))
		ath9k_beacon_assign_slot(sc, vif);

1201
	avp->vif = vif;
1202
	if (!ath9k_is_chanctx_enabled()) {
1203
		avp->chanctx = sc->cur_chan;
1204 1205
		list_add_tail(&avp->list, &avp->chanctx->vifs);
	}
1206 1207

	ath9k_assign_hw_queues(hw, vif);
1208

1209 1210 1211 1212 1213 1214
	an->sc = sc;
	an->sta = NULL;
	an->vif = vif;
	an->no_ps_filter = true;
	ath_tx_node_init(sc, an);

1215
	mutex_unlock(&sc->mutex);
1216
	return 0;
1217 1218 1219 1220 1221 1222 1223
}

static int ath9k_change_interface(struct ieee80211_hw *hw,
				  struct ieee80211_vif *vif,
				  enum nl80211_iftype new_type,
				  bool p2p)
{
1224
	struct ath_softc *sc = hw->priv;
1225
	struct ath_common *common = ath9k_hw_common(sc->sc_ah);
1226
	struct ath_vif *avp = (void *)vif->drv_priv;
1227 1228

	mutex_lock(&sc->mutex);
1229

Luis R. Rodriguez's avatar
Luis R. Rodriguez committed
1230 1231 1232 1233 1234 1235 1236
	if (config_enabled(CONFIG_ATH9K_TX99)) {
		mutex_unlock(&sc->mutex);
		return -EOPNOTSUPP;
	}

	ath_dbg(common, CONFIG, "Change Interface\n");

1237
	if (ath9k_uses_beacons(vif->type))
Sujith Manoharan's avatar
Sujith Manoharan committed
1238
		ath9k_beacon_remove_slot(sc, vif);
1239

1240 1241 1242
	vif->type = new_type;
	vif->p2p = p2p;

Sujith Manoharan's avatar
Sujith Manoharan committed
1243 1244
	if (ath9k_uses_beacons(vif->type))
		ath9k_beacon_assign_slot(sc, vif);
1245

1246
	ath9k_assign_hw_queues(hw, vif);
1247
	ath9k_calculate_summary_state(sc, avp->chanctx);
Sujith Manoharan's avatar
Sujith Manoharan committed
1248

1249
	mutex_unlock(&sc->mutex);
1250
	return 0;
1251 1252
}

1253
static void ath9k_remove_interface(struct ieee80211_hw *hw,
1254
				   struct ieee80211_vif *vif)
1255
{
1256
	struct ath_softc *sc = hw->priv;
1257
	struct ath_common *common = ath9k_hw_common(sc->sc_ah);
1258
	struct ath_vif *avp = (void *)vif->drv_priv;
1259

1260
	ath_dbg(common, CONFIG, "Detach Interface\n");
1261

1262 1263
	mutex_lock(&sc->mutex);

1264
	ath9k_p2p_remove_vif(sc, vif);
1265

1266
	sc->cur_chan->nvifs--;
Luis R. Rodriguez's avatar
Luis R. Rodriguez committed
1267
	sc->tx99_vif = NULL;
1268
	if (!ath9k_is_chanctx_enabled())
1269
		list_del(&avp->list);
Jouni Malinen's avatar
Jouni Malinen committed
1270

1271
	if (ath9k_uses_beacons(vif->type))
Sujith Manoharan's avatar
Sujith Manoharan committed
1272
		ath9k_beacon_remove_slot(sc, vif);
1273

1274 1275
	ath_tx_node_cleanup(sc, &avp->mcast_node);

1276
	mutex_unlock(&sc->mutex);
1277 1278
}

1279
static void ath9k_enable_ps(struct ath_softc *sc)
1280
{
Pavel Roskin's avatar
Pavel Roskin committed
1281
	struct ath_hw *ah = sc->sc_ah;
Sujith Manoharan's avatar
Sujith Manoharan committed
1282
	struct ath_common *common = ath9k_hw_common(ah);
Pavel Roskin's avatar
Pavel Roskin committed
1283

Luis R. Rodriguez's avatar
Luis R. Rodriguez committed
1284 1285 1286
	if (config_enabled(CONFIG_ATH9K_TX99))
		return;

1287
	sc->ps_enabled = true;
Pavel Roskin's avatar
Pavel Roskin committed
1288 1289 1290
	if (!(ah->caps.hw_caps & ATH9K_HW_CAP_AUTOSLEEP)) {
		if ((ah->imask & ATH9K_INT_TIM_TIMER) == 0) {
			ah->imask |= ATH9K_INT_TIM_TIMER;
1291
			ath9k_hw_set_interrupts(ah);
1292
		}
1293
		ath9k_hw_setrxabort(ah, 1);
1294
	}
Sujith Manoharan's avatar
Sujith Manoharan committed
1295
	ath_dbg(common, PS, "PowerSave enabled\n");
1296 1297
}

1298 1299 1300
static void ath9k_disable_ps(struct ath_softc *sc)
{
	struct ath_hw *ah = sc->sc_ah;
Sujith Manoharan's avatar
Sujith Manoharan committed
1301
	struct ath_common *common = ath9k_hw_common(ah);
1302

Luis R. Rodriguez's avatar
Luis R. Rodriguez committed
1303 1304 1305
	if (config_enabled(CONFIG_ATH9K_TX99))
		return;

1306 1307 1308 1309 1310 1311 1312 1313 1314 1315
	sc->ps_enabled = false;
	ath9k_hw_setpower(ah, ATH9K_PM_AWAKE);
	if (!(ah->caps.hw_caps & ATH9K_HW_CAP_AUTOSLEEP)) {
		ath9k_hw_setrxabort(ah, 0);
		sc->ps_flags &= ~(PS_WAIT_FOR_BEACON |
				  PS_WAIT_FOR_CAB |
				  PS_WAIT_FOR_PSPOLL_DATA |
				  PS_WAIT_FOR_TX_ACK);
		if (ah->imask & ATH9K_INT_TIM_TIMER) {
			ah->imask &= ~ATH9K_INT_TIM_TIMER;
1316
			ath9k_hw_set_interrupts(ah);
1317 1318
		}
	}
Sujith Manoharan's avatar
Sujith Manoharan committed
1319
	ath_dbg(common, PS, "PowerSave disabled\n");
1320 1321
}

1322 1323 1324 1325 1326 1327 1328
void ath9k_spectral_scan_trigger(struct ieee80211_hw *hw)
{
	struct ath_softc *sc = hw->priv;
	struct ath_hw *ah = sc->sc_ah;
	struct ath_common *common = ath9k_hw_common(ah);
	u32 rxfilter;

Luis R. Rodriguez's avatar
Luis R. Rodriguez committed
1329 1330 1331
	if (config_enabled(CONFIG_ATH9K_TX99))
		return;

1332 1333 1334 1335 1336 1337 1338 1339 1340 1341 1342 1343 1344 1345 1346 1347 1348 1349 1350 1351 1352 1353 1354 1355 1356 1357 1358 1359 1360 1361 1362 1363 1364 1365 1366
	if (!ath9k_hw_ops(ah)->spectral_scan_trigger) {
		ath_err(common, "spectrum analyzer not implemented on this hardware\n");
		return;
	}

	ath9k_ps_wakeup(sc);
	rxfilter = ath9k_hw_getrxfilter(ah);
	ath9k_hw_setrxfilter(ah, rxfilter |
				 ATH9K_RX_FILTER_PHYRADAR |
				 ATH9K_RX_FILTER_PHYERR);

	/* TODO: usually this should not be neccesary, but for some reason
	 * (or in some mode?) the trigger must be called after the
	 * configuration, otherwise the register will have its values reset
	 * (on my ar9220 to value 0x01002310)
	 */
	ath9k_spectral_scan_config(hw, sc->spectral_mode);
	ath9k_hw_ops(ah)->spectral_scan_trigger(ah);
	ath9k_ps_restore(sc);
}

int ath9k_spectral_scan_config(struct ieee80211_hw *hw,
			       enum spectral_mode spectral_mode)
{
	struct ath_softc *sc = hw->priv;
	struct ath_hw *ah = sc->sc_ah;
	struct ath_common *common = ath9k_hw_common(ah);

	if (!ath9k_hw_ops(ah)->spectral_scan_trigger) {
		ath_err(common, "spectrum analyzer not implemented on this hardware\n");
		return -1;
	}

	switch (spectral_mode) {
	case SPECTRAL_DISABLED:
1367
		sc->spec_config.enabled = 0;
1368 1369 1370 1371 1372
		break;
	case SPECTRAL_BACKGROUND:
		/* send endless samples.
		 * TODO: is this really useful for "background"?
		 */
1373 1374
		sc->spec_config.endless = 1;
		sc->spec_config.enabled = 1;
1375 1376 1377
		break;
	case SPECTRAL_CHANSCAN:
	case SPECTRAL_MANUAL:
1378 1379
		sc->spec_config.endless = 0;
		sc->spec_config.enabled = 1;
1380 1381 1382 1383 1384 1385
		break;
	default:
		return -1;
	}

	ath9k_ps_wakeup(sc);
1386
	ath9k_hw_ops(ah)->spectral_scan_config(ah, &sc->spec_config);
1387 1388 1389 1390 1391 1392 1393
	ath9k_ps_restore(sc);

	sc->spectral_mode = spectral_mode;

	return 0;
}

1394
static int ath9k_config(struct ieee80211_hw *hw, u32 changed)
1395
{
1396
	struct ath_softc *sc = hw->priv;
1397 1398
	struct ath_hw *ah = sc->sc_ah;
	struct ath_common *common = ath9k_hw_common(ah);
1399
	struct ieee80211_conf *conf = &hw->conf;
1400
	struct ath_chanctx *ctx = sc->cur_chan;
1401

1402
	ath9k_ps_wakeup(sc);
1403
	mutex_lock(&sc->mutex);
1404

1405
	if (changed & IEEE80211_CONF_CHANGE_IDLE) {
1406
		sc->ps_idle = !!(conf->flags & IEEE80211_CONF_IDLE);
1407
		if (sc->ps_idle) {
1408
			ath_cancel_work(sc);
1409 1410 1411
			ath9k_stop_btcoex(sc);
		} else {
			ath9k_start_btcoex(sc);
1412 1413 1414 1415
			/*
			 * The chip needs a reset to properly wake up from
			 * full sleep
			 */
1416
			ath_chanctx_set_channel(sc, ctx, &ctx->chandef);
1417
		}
1418
	}
1419

1420 1421 1422 1423 1424 1425
	/*
	 * We just prepare to enable PS. We have to wait until our AP has
	 * ACK'd our null data frame to disable RX otherwise we'll ignore
	 * those ACKs and end up retransmitting the same null data frames.
	 * IEEE80211_CONF_CHANGE_PS is only passed by mac80211 for STA mode.
	 */
1426
	if (changed & IEEE80211_CONF_CHANGE_PS) {
1427 1428
		unsigned long flags;
		spin_lock_irqsave(&sc->sc_pm_lock, flags);
1429 1430
		if (conf->flags & IEEE80211_CONF_PS)
			ath9k_enable_ps(sc);
1431 1432
		else
			ath9k_disable_ps(sc);
1433
		spin_unlock_irqrestore(&sc->sc_pm_lock, flags);
1434 1435
	}

Sujith's avatar
Sujith committed
1436 1437
	if (changed & IEEE80211_CONF_CHANGE_MONITOR) {
		if (conf->flags & IEEE80211_CONF_MONITOR) {
1438
			ath_dbg(common, CONFIG, "Monitor mode is enabled\n");
1439 1440
			sc->sc_ah->is_monitoring = true;
		} else {
1441
			ath_dbg(common, CONFIG, "Monitor mode is disabled\n");
1442
			sc->sc_ah->is_monitoring = false;
Sujith's avatar
Sujith committed
1443 1444 1445
		}
	}

1446
	if (!ath9k_is_chanctx_enabled() && (changed & IEEE80211_CONF_CHANGE_CHANNEL)) {
1447
		ctx->offchannel = !!(conf->flags & IEEE80211_CONF_OFFCHANNEL);
1448
		ath_chanctx_set_channel(sc, ctx, &hw->conf.chandef);
Sujith's avatar
Sujith committed
1449
	}
1450

1451
	if (changed & IEEE80211_CONF_CHANGE_POWER) {
1452
		ath_dbg(common, CONFIG, "Set power: %d\n", conf->power_level);
1453
		sc->cur_chan->txpower = 2 * conf->power_level;
1454
		ath9k_cmn_update_txpow(ah, sc->curtxpow,
1455
				       sc->cur_chan->txpower, &sc->curtxpow);
1456 1457
	}

1458
	mutex_unlock(&sc->mutex);
1459
	ath9k_ps_restore(sc);
1460

1461 1462 1463
	return 0;
}

1464 1465 1466 1467
#define SUPPORTED_FILTERS			\
	(FIF_PROMISC_IN_BSS |			\
	FIF_ALLMULTI |				\
	FIF_CONTROL |				\
1468
	FIF_PSPOLL |				\
1469 1470
	FIF_OTHER_BSS |				\
	FIF_BCN_PRBRESP_PROMISC |		\
1471
	FIF_PROBE_REQ |				\
1472
	FIF_FCSFAIL)
1473

1474 1475 1476 1477
/* FIXME: sc->sc_full_reset ? */
static void ath9k_configure_filter(struct ieee80211_hw *hw,
				   unsigned int changed_flags,
				   unsigned int *total_flags,
1478
				   u64 multicast)
1479
{
1480
	struct ath_softc *sc = hw->priv;
1481
	u32 rfilt;
1482

1483 1484
	changed_flags &= SUPPORTED_FILTERS;
	*total_flags &= SUPPORTED_FILTERS;
1485

1486 1487 1488 1489
	spin_lock_bh(&sc->chan_lock);
	sc->cur_chan->rxfilter = *total_flags;
	spin_unlock_bh(&sc->chan_lock);

1490
	ath9k_ps_wakeup(sc);
1491 1492
	rfilt = ath_calcrxfilter(sc);
	ath9k_hw_setrxfilter(sc->sc_ah, rfilt);
1493
	ath9k_ps_restore(sc);
1494

1495 1496
	ath_dbg(ath9k_hw_common(sc->sc_ah), CONFIG, "Set HW RX filter: 0x%x\n",
		rfilt);
1497
}
1498

1499 1500 1501
static int ath9k_sta_add(struct ieee80211_hw *hw,
			 struct ieee80211_vif *vif,
			 struct ieee80211_sta *sta)
1502
{
1503
	struct ath_softc *sc = hw->priv;
1504 1505 1506
	struct ath_common *common = ath9k_hw_common(sc->sc_ah);
	struct ath_node *an = (struct ath_node *) sta->drv_priv;
	struct ieee80211_key_conf ps_key = { };
1507
	int key;
1508

1509
	ath_node_attach(sc, sta, vif);
1510 1511 1512 1513 1514

	if (vif->type != NL80211_IFTYPE_AP &&
	    vif->type != NL80211_IFTYPE_AP_VLAN)
		return 0;

1515
	key = ath_key_config(common, vif, sta, &ps_key);
1516
	if (key > 0) {
1517
		an->ps_key = key;
1518 1519
		an->key_idx[0] = key;
	}
1520 1521 1522 1523

	return 0;
}

1524 1525 1526 1527 1528 1529 1530 1531 1532 1533 1534 1535
static void ath9k_del_ps_key(struct ath_softc *sc,
			     struct ieee80211_vif *vif,
			     struct ieee80211_sta *sta)
{
	struct ath_common *common = ath9k_hw_common(sc->sc_ah);
	struct ath_node *an = (struct ath_node *) sta->drv_priv;
	struct ieee80211_key_conf ps_key = { .hw_key_idx = an->ps_key };

	if (!an->ps_key)
	    return;

	ath_key_delete(common, &ps_key);
1536
	an->ps_key = 0;
1537
	an->key_idx[0] = 0;
1538 1539
}

1540 1541 1542 1543
static int ath9k_sta_remove(struct ieee80211_hw *hw,
			    struct ieee80211_vif *vif,
			    struct ieee80211_sta *sta)
{
1544
	struct ath_softc *sc = hw->priv;
1545

1546
	ath9k_del_ps_key(sc, vif, sta);
1547 1548 1549
	ath_node_detach(sc, sta);

	return 0;
1550 1551
}

1552 1553 1554 1555 1556 1557 1558 1559 1560 1561 1562 1563 1564
static void ath9k_sta_set_tx_filter(struct ath_hw *ah,
				    struct ath_node *an,
				    bool set)
{
	int i;

	for (i = 0; i < ARRAY_SIZE(an->key_idx); i++) {
		if (!an->key_idx[i])
			continue;
		ath9k_hw_set_tx_filter(ah, an->key_idx[i], set);
	}
}

1565 1566 1567 1568 1569 1570 1571 1572 1573 1574 1575
static void ath9k_sta_notify(struct ieee80211_hw *hw,
			 struct ieee80211_vif *vif,
			 enum sta_notify_cmd cmd,
			 struct ieee80211_sta *sta)
{
	struct ath_softc *sc = hw->priv;
	struct ath_node *an = (struct ath_node *) sta->drv_priv;

	switch (cmd) {
	case STA_NOTIFY_SLEEP:
		an->sleeping = true;
1576
		ath_tx_aggr_sleep(sta, sc, an);
1577
		ath9k_sta_set_tx_filter(sc->sc_ah, an, true);
1578 1579
		break;
	case STA_NOTIFY_AWAKE:
1580
		ath9k_sta_set_tx_filter(sc->sc_ah, an, false);
1581 1582 1583 1584 1585 1586
		an->sleeping = false;
		ath_tx_aggr_wakeup(sc, an);
		break;
	}
}

1587 1588
static int ath9k_conf_tx(struct ieee80211_hw *hw,
			 struct ieee80211_vif *vif, u16 queue,
1589
			 const struct ieee80211_tx_queue_params *params)
1590
{
1591
	struct ath_softc *sc = hw->priv;
1592
	struct ath_common *common = ath9k_hw_common(sc->sc_ah);
1593
	struct ath_txq *txq;
1594
	struct ath9k_tx_queue_info qi;
1595
	int ret = 0;
1596

1597
	if (queue >= IEEE80211_NUM_ACS)
1598
		return 0;
1599

1600 1601
	txq = sc->tx.txq_map[queue];

1602
	ath9k_ps_wakeup(sc);
1603 1604
	mutex_lock(&sc->mutex);

1605 1606
	memset(&qi, 0, sizeof(struct ath9k_tx_queue_info));

1607 1608 1609
	qi.tqi_aifs = params->aifs;
	qi.tqi_cwmin = params->cw_min;
	qi.tqi_cwmax = params->cw_max;
1610
	qi.tqi_burstTime = params->txop * 32;
1611

1612
	ath_dbg(common, CONFIG,
1613 1614 1615
		"Configure tx [queue/halq] [%d/%d], aifs: %d, cw_min: %d, cw_max: %d, txop: %d\n",
		queue, txq->axq_qnum, params->aifs, params->cw_min,
		params->cw_max, params->txop);
1616

1617
	ath_update_max_aggr_framelen(sc, queue, qi.tqi_burstTime);
1618
	ret = ath_txq_update(sc, txq->axq_qnum, &qi);
1619
	if (ret)
1620
		ath_err(common, "TXQ Update failed\n");
1621

1622
	mutex_unlock(&sc->mutex);
1623
	ath9k_ps_restore(sc);
1624

1625 1626
	return ret;
}
1627

1628 1629
static int ath9k_set_key(struct ieee80211_hw *hw,
			 enum set_key_cmd cmd,
1630 1631
			 struct ieee80211_vif *vif,
			 struct ieee80211_sta *sta,
1632 1633
			 struct ieee80211_key_conf *key)
{
1634
	struct ath_softc *sc = hw->priv;
1635
	struct ath_common *common = ath9k_hw_common(sc->sc_ah);
1636 1637
	struct ath_node *an = NULL;
	int ret = 0, i;
1638

1639
	if (ath9k_modparam_nohwcrypt)
1640 1641
		return -ENOSPC;

Chun-Yeow Yeoh's avatar
Chun-Yeow Yeoh committed
1642 1643
	if ((vif->type == NL80211_IFTYPE_ADHOC ||
	     vif->type == NL80211_IFTYPE_MESH_POINT) &&
Jouni Malinen's avatar
Jouni Malinen committed
1644 1645 1646 1647 1648 1649 1650 1651 1652 1653 1654 1655 1656
	    (key->cipher == WLAN_CIPHER_SUITE_TKIP ||
	     key->cipher == WLAN_CIPHER_SUITE_CCMP) &&
	    !(key->flags & IEEE80211_KEY_FLAG_PAIRWISE)) {
		/*
		 * For now, disable hw crypto for the RSN IBSS group keys. This
		 * could be optimized in the future to use a modified key cache
		 * design to support per-STA RX GTK, but until that gets
		 * implemented, use of software crypto for group addressed
		 * frames is a acceptable to allow RSN IBSS to be used.
		 */
		return -EOPNOTSUPP;
	}

1657
	mutex_lock(&sc->mutex);
1658
	ath9k_ps_wakeup(sc);
1659 1660 1661
	ath_dbg(common, CONFIG, "Set HW Key %d\n", cmd);
	if (sta)
		an = (struct ath_node *)sta->drv_priv;
1662

1663 1664
	switch (cmd) {
	case SET_KEY:
1665 1666 1667
		if (sta)
			ath9k_del_ps_key(sc, vif, sta);

1668
		key->hw_key_idx = 0;
1669
		ret = ath_key_config(common, vif, sta, key);
1670 1671
		if (ret >= 0) {
			key->hw_key_idx = ret;
1672 1673
			/* push IV and Michael MIC generation to stack */
			key->flags |= IEEE80211_KEY_FLAG_GENERATE_IV;
1674
			if (key->cipher == WLAN_CIPHER_SUITE_TKIP)
1675
				key->flags |= IEEE80211_KEY_FLAG_GENERATE_MMIC;
1676 1677
			if (sc->sc_ah->sw_mgmt_crypto &&
			    key->cipher == WLAN_CIPHER_SUITE_CCMP)
1678
				key->flags |= IEEE80211_KEY_FLAG_SW_MGMT_TX;
1679
			ret = 0;
1680
		}
1681 1682 1683 1684 1685 1686 1687 1688 1689
		if (an && key->hw_key_idx) {
			for (i = 0; i < ARRAY_SIZE(an->key_idx); i++) {
				if (an->key_idx[i])
					continue;
				an->key_idx[i] = key->hw_key_idx;
				break;
			}
			WARN_ON(i == ARRAY_SIZE(an->key_idx));
		}
1690 1691
		break;
	case DISABLE_KEY:
1692
		ath_key_delete(common, key);
1693 1694 1695 1696 1697 1698 1699 1700 1701
		if (an) {
			for (i = 0; i < ARRAY_SIZE(an->key_idx); i++) {
				if (an->key_idx[i] != key->hw_key_idx)
					continue;
				an->key_idx[i] = 0;
				break;
			}
		}
		key->hw_key_idx = 0;
1702 1703 1704 1705
		break;
	default:
		ret = -EINVAL;
	}
1706

1707
	ath9k_ps_restore(sc);
1708 1709
	mutex_unlock(&sc->mutex);

1710 1711
	return ret;
}
1712

1713 1714 1715 1716 1717
static void ath9k_bss_info_changed(struct ieee80211_hw *hw,
				   struct ieee80211_vif *vif,
				   struct ieee80211_bss_conf *bss_conf,
				   u32 changed)
{
Sujith Manoharan's avatar
Sujith Manoharan committed
1718 1719 1720 1721 1722
#define CHECK_ANI				\
	(BSS_CHANGED_ASSOC |			\
	 BSS_CHANGED_IBSS |			\
	 BSS_CHANGED_BEACON_ENABLED)

1723
	struct ath_softc *sc = hw->priv;
1724
	struct ath_hw *ah = sc->sc_ah;
1725
	struct ath_common *common = ath9k_hw_common(ah);
1726
	struct ath_vif *avp = (void *)vif->drv_priv;
1727
	int slottime;
1728

1729
	ath9k_ps_wakeup(sc);
1730 1731
	mutex_lock(&sc->mutex);

1732
	if (changed & BSS_CHANGED_ASSOC) {
1733 1734 1735
		ath_dbg(common, CONFIG, "BSSID %pM Changed ASSOC %d\n",
			bss_conf->bssid, bss_conf->assoc);

1736 1737 1738 1739
		ether_addr_copy(avp->bssid, bss_conf->bssid);
		avp->aid = bss_conf->aid;
		avp->assoc = bss_conf->assoc;

1740
		ath9k_calculate_summary_state(sc, avp->chanctx);
1741 1742 1743 1744 1745 1746

		if (ath9k_is_chanctx_enabled()) {
			if (bss_conf->assoc)
				ath_chanctx_event(sc, vif,
						  ATH_CHANCTX_EVENT_ASSOC);
		}
1747
	}
1748

1749 1750 1751 1752 1753 1754
	if (changed & BSS_CHANGED_IBSS) {
		memcpy(common->curbssid, bss_conf->bssid, ETH_ALEN);
		common->curaid = bss_conf->aid;
		ath9k_hw_write_associd(sc->sc_ah);
	}

Sujith Manoharan's avatar
Sujith Manoharan committed
1755
	if ((changed & BSS_CHANGED_BEACON_ENABLED) ||
1756 1757
	    (changed & BSS_CHANGED_BEACON_INT) ||
	    (changed & BSS_CHANGED_BEACON_INFO)) {
1758
		ath9k_beacon_config(sc, vif, changed);
1759 1760 1761
		if (changed & BSS_CHANGED_BEACON_ENABLED)
			ath9k_calculate_summary_state(sc, avp->chanctx);
	}
1762

1763 1764
	if ((avp->chanctx == sc->cur_chan) &&
	    (changed & BSS_CHANGED_ERP_SLOT)) {
1765 1766 1767 1768 1769 1770 1771 1772 1773 1774 1775 1776 1777 1778 1779 1780
		if (bss_conf->use_short_slot)
			slottime = 9;
		else
			slottime = 20;
		if (vif->type == NL80211_IFTYPE_AP) {
			/*
			 * Defer update, so that connected stations can adjust
			 * their settings at the same time.
			 * See beacon.c for more details
			 */
			sc->beacon.slottime = slottime;
			sc->beacon.updateslot = UPDATE;
		} else {
			ah->slottime = slottime;
			ath9k_hw_init_global_settings(ah);
		}
1781 1782
	}

1783 1784
	if (changed & BSS_CHANGED_P2P_PS)
		ath9k_p2p_bss_info_changed(sc, vif);
1785

Sujith Manoharan's avatar
Sujith Manoharan committed
1786 1787 1788
	if (changed & CHECK_ANI)
		ath_check_ani(sc);

1789
	mutex_unlock(&sc->mutex);
1790
	ath9k_ps_restore(sc);
Sujith Manoharan's avatar
Sujith Manoharan committed
1791 1792

#undef CHECK_ANI
1793
}
1794

1795
static u64 ath9k_get_tsf(struct ieee80211_hw *hw, struct ieee80211_vif *vif)
1796
{
1797
	struct ath_softc *sc = hw->priv;
1798
	u64 tsf;
1799

1800
	mutex_lock(&sc->mutex);
1801
	ath9k_ps_wakeup(sc);
1802
	tsf = ath9k_hw_gettsf64(sc->sc_ah);
1803
	ath9k_ps_restore(sc);
1804
	mutex_unlock(&sc->mutex);
1805

1806 1807
	return tsf;
}
1808

1809 1810 1811
static void ath9k_set_tsf(struct ieee80211_hw *hw,
			  struct ieee80211_vif *vif,
			  u64 tsf)
1812
{
1813
	struct ath_softc *sc = hw->priv;
1814

1815
	mutex_lock(&sc->mutex);
1816
	ath9k_ps_wakeup(sc);
1817
	ath9k_hw_settsf64(sc->sc_ah, tsf);
1818
	ath9k_ps_restore(sc);
1819
	mutex_unlock(&sc->mutex);
1820 1821
}

1822
static void ath9k_reset_tsf(struct ieee80211_hw *hw, struct ieee80211_vif *vif)
1823
{
1824
	struct ath_softc *sc = hw->priv;
1825

1826
	mutex_lock(&sc->mutex);
1827 1828

	ath9k_ps_wakeup(sc);
1829
	ath9k_hw_reset_tsf(sc->sc_ah);
1830 1831
	ath9k_ps_restore(sc);

1832
	mutex_unlock(&sc->mutex);
1833
}
1834

1835
static int ath9k_ampdu_action(struct ieee80211_hw *hw,
1836
			      struct ieee80211_vif *vif,
1837 1838
			      enum ieee80211_ampdu_mlme_action action,
			      struct ieee80211_sta *sta,
1839
			      u16 tid, u16 *ssn, u8 buf_size)
1840
{
1841
	struct ath_softc *sc = hw->priv;
1842
	bool flush = false;
1843
	int ret = 0;
1844

1845
	mutex_lock(&sc->mutex);
1846

1847 1848 1849 1850 1851 1852
	switch (action) {
	case IEEE80211_AMPDU_RX_START:
		break;
	case IEEE80211_AMPDU_RX_STOP:
		break;
	case IEEE80211_AMPDU_TX_START:
1853
		ath9k_ps_wakeup(sc);
1854 1855 1856
		ret = ath_tx_aggr_start(sc, sta, tid, ssn);
		if (!ret)
			ieee80211_start_tx_ba_cb_irqsafe(vif, sta->addr, tid);
1857
		ath9k_ps_restore(sc);
1858
		break;
1859 1860
	case IEEE80211_AMPDU_TX_STOP_FLUSH:
	case IEEE80211_AMPDU_TX_STOP_FLUSH_CONT:
1861 1862
		flush = true;
	case IEEE80211_AMPDU_TX_STOP_CONT:
1863
		ath9k_ps_wakeup(sc);
Sujith's avatar
Sujith committed
1864
		ath_tx_aggr_stop(sc, sta, tid);
1865
		if (!flush)
1866
			ieee80211_stop_tx_ba_cb_irqsafe(vif, sta->addr, tid);
1867
		ath9k_ps_restore(sc);
1868
		break;
1869
	case IEEE80211_AMPDU_TX_OPERATIONAL:
1870
		ath9k_ps_wakeup(sc);
1871
		ath_tx_aggr_resume(sc, sta, tid);
1872
		ath9k_ps_restore(sc);
1873
		break;
1874
	default:
1875
		ath_err(ath9k_hw_common(sc->sc_ah), "Unknown AMPDU action\n");
1876 1877
	}

1878
	mutex_unlock(&sc->mutex);
1879

1880
	return ret;
1881 1882
}

1883 1884 1885
static int ath9k_get_survey(struct ieee80211_hw *hw, int idx,
			     struct survey_info *survey)
{
1886
	struct ath_softc *sc = hw->priv;
1887
	struct ath_common *common = ath9k_hw_common(sc->sc_ah);
1888
	struct ieee80211_supported_band *sband;
1889 1890 1891
	struct ieee80211_channel *chan;
	int pos;

Luis R. Rodriguez's avatar
Luis R. Rodriguez committed
1892 1893 1894
	if (config_enabled(CONFIG_ATH9K_TX99))
		return -EOPNOTSUPP;

Sujith Manoharan's avatar
Sujith Manoharan committed
1895
	spin_lock_bh(&common->cc_lock);
1896 1897
	if (idx == 0)
		ath_update_survey_stats(sc);
1898 1899 1900 1901 1902 1903

	sband = hw->wiphy->bands[IEEE80211_BAND_2GHZ];
	if (sband && idx >= sband->n_channels) {
		idx -= sband->n_channels;
		sband = NULL;
	}
1904

1905 1906
	if (!sband)
		sband = hw->wiphy->bands[IEEE80211_BAND_5GHZ];
1907

1908
	if (!sband || idx >= sband->n_channels) {
Sujith Manoharan's avatar
Sujith Manoharan committed
1909
		spin_unlock_bh(&common->cc_lock);
1910
		return -ENOENT;
1911
	}
1912

1913 1914 1915 1916
	chan = &sband->channels[idx];
	pos = chan->hw_value;
	memcpy(survey, &sc->survey[pos], sizeof(*survey));
	survey->channel = chan;
Sujith Manoharan's avatar
Sujith Manoharan committed
1917
	spin_unlock_bh(&common->cc_lock);
1918

1919 1920 1921
	return 0;
}

1922 1923 1924 1925 1926 1927 1928 1929 1930 1931 1932 1933 1934 1935
static void ath9k_enable_dynack(struct ath_softc *sc)
{
#ifdef CONFIG_ATH9K_DYNACK
	u32 rfilt;
	struct ath_hw *ah = sc->sc_ah;

	ath_dynack_reset(ah);

	ah->dynack.enabled = true;
	rfilt = ath_calcrxfilter(sc);
	ath9k_hw_setrxfilter(ah, rfilt);
#endif
}

1936 1937
static void ath9k_set_coverage_class(struct ieee80211_hw *hw,
				     s16 coverage_class)
1938
{
1939
	struct ath_softc *sc = hw->priv;
1940 1941
	struct ath_hw *ah = sc->sc_ah;

Luis R. Rodriguez's avatar
Luis R. Rodriguez committed
1942 1943 1944
	if (config_enabled(CONFIG_ATH9K_TX99))
		return;

1945
	mutex_lock(&sc->mutex);
1946

1947 1948 1949 1950 1951 1952 1953 1954 1955 1956 1957 1958 1959 1960 1961
	if (coverage_class >= 0) {
		ah->coverage_class = coverage_class;
		if (ah->dynack.enabled) {
			u32 rfilt;

			ah->dynack.enabled = false;
			rfilt = ath_calcrxfilter(sc);
			ath9k_hw_setrxfilter(ah, rfilt);
		}
		ath9k_ps_wakeup(sc);
		ath9k_hw_init_global_settings(ah);
		ath9k_ps_restore(sc);
	} else if (!ah->dynack.enabled) {
		ath9k_enable_dynack(sc);
	}
1962

1963 1964 1965
	mutex_unlock(&sc->mutex);
}

Felix Fietkau's avatar
Felix Fietkau committed
1966 1967
static bool ath9k_has_tx_pending(struct ath_softc *sc)
{
1968
	int i, npend = 0;
Felix Fietkau's avatar
Felix Fietkau committed
1969 1970 1971 1972 1973 1974 1975 1976 1977 1978 1979 1980 1981 1982 1983 1984

	for (i = 0; i < ATH9K_NUM_TX_QUEUES; i++) {
		if (!ATH_TXQ_SETUP(sc, i))
			continue;

		if (!sc->tx.txq[i].axq_depth)
			continue;

		npend = ath9k_has_pending_frames(sc, &sc->tx.txq[i]);
		if (npend)
			break;
	}

	return !!npend;
}

1985 1986
static void ath9k_flush(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
			u32 queues, bool drop)
1987 1988 1989 1990 1991 1992 1993 1994 1995
{
	struct ath_softc *sc = hw->priv;

	mutex_lock(&sc->mutex);
	__ath9k_flush(hw, queues, drop);
	mutex_unlock(&sc->mutex);
}

void __ath9k_flush(struct ieee80211_hw *hw, u32 queues, bool drop)
1996 1997
{
	struct ath_softc *sc = hw->priv;
1998 1999
	struct ath_hw *ah = sc->sc_ah;
	struct ath_common *common = ath9k_hw_common(ah);
Felix Fietkau's avatar
Felix Fietkau committed
2000
	int timeout = HZ / 5; /* 200 ms */
2001
	bool drain_txq;
2002
	int i;
2003 2004 2005

	cancel_delayed_work_sync(&sc->tx_complete_work);

2006
	if (ah->ah_flags & AH_UNPLUGGED) {
2007
		ath_dbg(common, ANY, "Device has been unplugged!\n");
2008 2009 2010
		return;
	}

2011
	if (test_bit(ATH_OP_INVALID, &common->op_flags)) {
2012
		ath_dbg(common, ANY, "Device not present\n");
2013 2014 2015
		return;
	}

Felix Fietkau's avatar
Felix Fietkau committed
2016 2017 2018
	if (wait_event_timeout(sc->tx_wait, !ath9k_has_tx_pending(sc),
			       timeout) > 0)
		drop = false;
2019

2020 2021 2022
	if (drop) {
		ath9k_ps_wakeup(sc);
		spin_lock_bh(&sc->sc_pcu_lock);
2023
		drain_txq = ath_drain_all_txq(sc);
2024
		spin_unlock_bh(&sc->sc_pcu_lock);
2025

2026
		if (!drain_txq)
2027
			ath_reset(sc);
2028

2029
		ath9k_ps_restore(sc);
2030 2031 2032 2033
		for (i = 0; i < IEEE80211_NUM_ACS; i++) {
			ieee80211_wake_queue(sc->hw,
					     sc->cur_chan->hw_queue_base + i);
		}
2034
	}
2035

2036 2037 2038
	ieee80211_queue_delayed_work(hw, &sc->tx_complete_work, 0);
}

2039 2040 2041 2042 2043 2044 2045 2046 2047 2048 2049 2050 2051 2052 2053
static bool ath9k_tx_frames_pending(struct ieee80211_hw *hw)
{
	struct ath_softc *sc = hw->priv;
	int i;

	for (i = 0; i < ATH9K_NUM_TX_QUEUES; i++) {
		if (!ATH_TXQ_SETUP(sc, i))
			continue;

		if (ath9k_has_pending_frames(sc, &sc->tx.txq[i]))
			return true;
	}
	return false;
}

2054
static int ath9k_tx_last_beacon(struct ieee80211_hw *hw)
2055 2056 2057 2058 2059 2060 2061
{
	struct ath_softc *sc = hw->priv;
	struct ath_hw *ah = sc->sc_ah;
	struct ieee80211_vif *vif;
	struct ath_vif *avp;
	struct ath_buf *bf;
	struct ath_tx_status ts;
2062
	bool edma = !!(ah->caps.hw_caps & ATH9K_HW_CAP_EDMA);
2063 2064 2065 2066 2067 2068
	int status;

	vif = sc->beacon.bslot[0];
	if (!vif)
		return 0;

2069
	if (!vif->bss_conf.enable_beacon)
2070 2071
		return 0;

2072 2073
	avp = (void *)vif->drv_priv;

2074
	if (!sc->beacon.tx_processed && !edma) {
2075 2076 2077 2078 2079 2080 2081 2082 2083 2084 2085 2086 2087 2088 2089 2090 2091 2092 2093 2094
		tasklet_disable(&sc->bcon_tasklet);

		bf = avp->av_bcbuf;
		if (!bf || !bf->bf_mpdu)
			goto skip;

		status = ath9k_hw_txprocdesc(ah, bf->bf_desc, &ts);
		if (status == -EINPROGRESS)
			goto skip;

		sc->beacon.tx_processed = true;
		sc->beacon.tx_last = !(ts.ts_status & ATH9K_TXERR_MASK);

skip:
		tasklet_enable(&sc->bcon_tasklet);
	}

	return sc->beacon.tx_last;
}

2095 2096 2097 2098 2099 2100 2101 2102 2103 2104 2105 2106 2107 2108
static int ath9k_get_stats(struct ieee80211_hw *hw,
			   struct ieee80211_low_level_stats *stats)
{
	struct ath_softc *sc = hw->priv;
	struct ath_hw *ah = sc->sc_ah;
	struct ath9k_mib_stats *mib_stats = &ah->ah_mibStats;

	stats->dot11ACKFailureCount = mib_stats->ackrcv_bad;
	stats->dot11RTSFailureCount = mib_stats->rts_bad;
	stats->dot11FCSErrorCount = mib_stats->fcs_bad;
	stats->dot11RTSSuccessCount = mib_stats->rts_good;
	return 0;
}

2109 2110 2111 2112 2113 2114 2115 2116 2117 2118 2119 2120 2121 2122 2123 2124 2125 2126
static u32 fill_chainmask(u32 cap, u32 new)
{
	u32 filled = 0;
	int i;

	for (i = 0; cap && new; i++, cap >>= 1) {
		if (!(cap & BIT(0)))
			continue;

		if (new & BIT(0))
			filled |= BIT(i);

		new >>= 1;
	}

	return filled;
}

2127 2128
static bool validate_antenna_mask(struct ath_hw *ah, u32 val)
{
2129 2130 2131
	if (AR_SREV_9300_20_OR_LATER(ah))
		return true;

2132 2133 2134 2135 2136 2137 2138 2139 2140 2141 2142 2143
	switch (val & 0x7) {
	case 0x1:
	case 0x3:
	case 0x7:
		return true;
	case 0x2:
		return (ah->caps.rx_chainmask == 1);
	default:
		return false;
	}
}

2144 2145 2146 2147 2148
static int ath9k_set_antenna(struct ieee80211_hw *hw, u32 tx_ant, u32 rx_ant)
{
	struct ath_softc *sc = hw->priv;
	struct ath_hw *ah = sc->sc_ah;

2149 2150 2151 2152
	if (ah->caps.rx_chainmask != 1)
		rx_ant |= tx_ant;

	if (!validate_antenna_mask(ah, rx_ant) || !tx_ant)
2153 2154 2155 2156 2157 2158 2159 2160 2161 2162 2163 2164 2165 2166 2167
		return -EINVAL;

	sc->ant_rx = rx_ant;
	sc->ant_tx = tx_ant;

	if (ah->caps.rx_chainmask == 1)
		return 0;

	/* AR9100 runs into calibration issues if not all rx chains are enabled */
	if (AR_SREV_9100(ah))
		ah->rxchainmask = 0x7;
	else
		ah->rxchainmask = fill_chainmask(ah->caps.rx_chainmask, rx_ant);

	ah->txchainmask = fill_chainmask(ah->caps.tx_chainmask, tx_ant);
2168
	ath9k_cmn_reload_chainmask(ah);
2169 2170 2171 2172 2173 2174 2175 2176 2177 2178 2179 2180 2181

	return 0;
}

static int ath9k_get_antenna(struct ieee80211_hw *hw, u32 *tx_ant, u32 *rx_ant)
{
	struct ath_softc *sc = hw->priv;

	*tx_ant = sc->ant_tx;
	*rx_ant = sc->ant_rx;
	return 0;
}

2182 2183 2184
static void ath9k_sw_scan_start(struct ieee80211_hw *hw)
{
	struct ath_softc *sc = hw->priv;
2185 2186
	struct ath_common *common = ath9k_hw_common(sc->sc_ah);
	set_bit(ATH_OP_SCANNING, &common->op_flags);
2187 2188 2189 2190 2191
}

static void ath9k_sw_scan_complete(struct ieee80211_hw *hw)
{
	struct ath_softc *sc = hw->priv;
2192 2193
	struct ath_common *common = ath9k_hw_common(sc->sc_ah);
	clear_bit(ATH_OP_SCANNING, &common->op_flags);
2194
}
2195

2196 2197
#ifdef CONFIG_ATH9K_CHANNEL_CONTEXT

2198
static int ath9k_hw_scan(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
2199
			 struct ieee80211_scan_request *hw_req)
2200
{
2201
	struct cfg80211_scan_request *req = &hw_req->req;
2202 2203 2204 2205 2206 2207 2208 2209 2210 2211 2212 2213 2214 2215 2216 2217 2218
	struct ath_softc *sc = hw->priv;
	struct ath_common *common = ath9k_hw_common(sc->sc_ah);
	int ret = 0;

	mutex_lock(&sc->mutex);

	if (WARN_ON(sc->offchannel.scan_req)) {
		ret = -EBUSY;
		goto out;
	}

	ath9k_ps_wakeup(sc);
	set_bit(ATH_OP_SCANNING, &common->op_flags);
	sc->offchannel.scan_vif = vif;
	sc->offchannel.scan_req = req;
	sc->offchannel.scan_idx = 0;

2219 2220 2221 2222 2223
	ath_dbg(common, CHAN_CTX, "HW scan request received on vif: %pM\n",
		vif->addr);

	if (sc->offchannel.state == ATH_OFFCHANNEL_IDLE) {
		ath_dbg(common, CHAN_CTX, "Starting HW scan\n");
2224
		ath_offchannel_next(sc);
2225
	}
2226 2227 2228 2229 2230 2231 2232 2233 2234 2235 2236

out:
	mutex_unlock(&sc->mutex);

	return ret;
}

static void ath9k_cancel_hw_scan(struct ieee80211_hw *hw,
				 struct ieee80211_vif *vif)
{
	struct ath_softc *sc = hw->priv;
2237 2238 2239
	struct ath_common *common = ath9k_hw_common(sc->sc_ah);

	ath_dbg(common, CHAN_CTX, "Cancel HW scan on vif: %pM\n", vif->addr);
2240 2241 2242 2243 2244 2245 2246

	mutex_lock(&sc->mutex);
	del_timer_sync(&sc->offchannel.timer);
	ath_scan_complete(sc, true);
	mutex_unlock(&sc->mutex);
}

2247 2248 2249 2250 2251 2252
static int ath9k_remain_on_channel(struct ieee80211_hw *hw,
				   struct ieee80211_vif *vif,
				   struct ieee80211_channel *chan, int duration,
				   enum ieee80211_roc_type type)
{
	struct ath_softc *sc = hw->priv;
2253
	struct ath_common *common = ath9k_hw_common(sc->sc_ah);
2254 2255 2256 2257 2258 2259 2260 2261 2262 2263 2264 2265 2266 2267
	int ret = 0;

	mutex_lock(&sc->mutex);

	if (WARN_ON(sc->offchannel.roc_vif)) {
		ret = -EBUSY;
		goto out;
	}

	ath9k_ps_wakeup(sc);
	sc->offchannel.roc_vif = vif;
	sc->offchannel.roc_chan = chan;
	sc->offchannel.roc_duration = duration;

2268 2269 2270 2271 2272 2273
	ath_dbg(common, CHAN_CTX,
		"RoC request on vif: %pM, type: %d duration: %d\n",
		vif->addr, type, duration);

	if (sc->offchannel.state == ATH_OFFCHANNEL_IDLE) {
		ath_dbg(common, CHAN_CTX, "Starting RoC period\n");
2274
		ath_offchannel_next(sc);
2275
	}
2276 2277 2278 2279 2280 2281 2282 2283 2284 2285

out:
	mutex_unlock(&sc->mutex);

	return ret;
}

static int ath9k_cancel_remain_on_channel(struct ieee80211_hw *hw)
{
	struct ath_softc *sc = hw->priv;
2286
	struct ath_common *common = ath9k_hw_common(sc->sc_ah);
2287 2288 2289

	mutex_lock(&sc->mutex);

2290
	ath_dbg(common, CHAN_CTX, "Cancel RoC\n");
2291 2292 2293 2294 2295 2296 2297 2298 2299 2300 2301 2302
	del_timer_sync(&sc->offchannel.timer);

	if (sc->offchannel.roc_vif) {
		if (sc->offchannel.state >= ATH_OFFCHANNEL_ROC_START)
			ath_roc_complete(sc, true);
	}

	mutex_unlock(&sc->mutex);

	return 0;
}

2303 2304 2305 2306
static int ath9k_add_chanctx(struct ieee80211_hw *hw,
			     struct ieee80211_chanctx_conf *conf)
{
	struct ath_softc *sc = hw->priv;
2307
	struct ath_common *common = ath9k_hw_common(sc->sc_ah);
2308
	struct ath_chanctx *ctx, **ptr;
2309
	int pos;
2310 2311

	mutex_lock(&sc->mutex);
2312 2313 2314 2315 2316 2317 2318 2319

	ath_for_each_chanctx(sc, ctx) {
		if (ctx->assigned)
			continue;

		ptr = (void *) conf->drv_priv;
		*ptr = ctx;
		ctx->assigned = true;
2320 2321
		pos = ctx - &sc->chanctx[0];
		ctx->hw_queue_base = pos * IEEE80211_NUM_ACS;
2322 2323 2324 2325 2326

		ath_dbg(common, CHAN_CTX,
			"Add channel context: %d MHz\n",
			conf->def.chan->center_freq);

2327
		ath_chanctx_set_channel(sc, ctx, &conf->def);
2328 2329
		ath_chanctx_event(sc, NULL, ATH_CHANCTX_EVENT_ASSIGN);

2330
		mutex_unlock(&sc->mutex);
2331
		return 0;
2332
	}
2333

2334
	mutex_unlock(&sc->mutex);
2335
	return -ENOSPC;
2336 2337 2338 2339 2340 2341 2342
}


static void ath9k_remove_chanctx(struct ieee80211_hw *hw,
				 struct ieee80211_chanctx_conf *conf)
{
	struct ath_softc *sc = hw->priv;
2343
	struct ath_common *common = ath9k_hw_common(sc->sc_ah);
2344 2345 2346
	struct ath_chanctx *ctx = ath_chanctx_get(conf);

	mutex_lock(&sc->mutex);
2347 2348 2349 2350 2351

	ath_dbg(common, CHAN_CTX,
		"Remove channel context: %d MHz\n",
		conf->def.chan->center_freq);

2352
	ctx->assigned = false;
2353
	ctx->hw_queue_base = -1;
2354
	ath_chanctx_event(sc, NULL, ATH_CHANCTX_EVENT_UNASSIGN);
2355

2356 2357 2358 2359 2360 2361 2362 2363
	mutex_unlock(&sc->mutex);
}

static void ath9k_change_chanctx(struct ieee80211_hw *hw,
				 struct ieee80211_chanctx_conf *conf,
				 u32 changed)
{
	struct ath_softc *sc = hw->priv;
2364
	struct ath_common *common = ath9k_hw_common(sc->sc_ah);
2365 2366 2367
	struct ath_chanctx *ctx = ath_chanctx_get(conf);

	mutex_lock(&sc->mutex);
2368 2369 2370
	ath_dbg(common, CHAN_CTX,
		"Change channel context: %d MHz\n",
		conf->def.chan->center_freq);
2371 2372 2373 2374 2375 2376 2377 2378 2379
	ath_chanctx_set_channel(sc, ctx, &conf->def);
	mutex_unlock(&sc->mutex);
}

static int ath9k_assign_vif_chanctx(struct ieee80211_hw *hw,
				    struct ieee80211_vif *vif,
				    struct ieee80211_chanctx_conf *conf)
{
	struct ath_softc *sc = hw->priv;
2380
	struct ath_common *common = ath9k_hw_common(sc->sc_ah);
2381 2382
	struct ath_vif *avp = (void *)vif->drv_priv;
	struct ath_chanctx *ctx = ath_chanctx_get(conf);
2383
	int i;
2384 2385

	mutex_lock(&sc->mutex);
2386 2387 2388 2389 2390 2391

	ath_dbg(common, CHAN_CTX,
		"Assign VIF (addr: %pM, type: %d, p2p: %d) to channel context: %d MHz\n",
		vif->addr, vif->type, vif->p2p,
		conf->def.chan->center_freq);

2392
	avp->chanctx = ctx;
2393
	ctx->nvifs_assigned++;
2394
	list_add_tail(&avp->list, &ctx->vifs);
2395
	ath9k_calculate_summary_state(sc, ctx);
2396 2397
	for (i = 0; i < IEEE80211_NUM_ACS; i++)
		vif->hw_queue[i] = ctx->hw_queue_base + i;
2398

2399 2400 2401 2402 2403 2404 2405 2406 2407 2408
	mutex_unlock(&sc->mutex);

	return 0;
}

static void ath9k_unassign_vif_chanctx(struct ieee80211_hw *hw,
				       struct ieee80211_vif *vif,
				       struct ieee80211_chanctx_conf *conf)
{
	struct ath_softc *sc = hw->priv;
2409
	struct ath_common *common = ath9k_hw_common(sc->sc_ah);
2410 2411
	struct ath_vif *avp = (void *)vif->drv_priv;
	struct ath_chanctx *ctx = ath_chanctx_get(conf);
2412
	int ac;
2413 2414

	mutex_lock(&sc->mutex);
2415 2416 2417 2418 2419 2420

	ath_dbg(common, CHAN_CTX,
		"Remove VIF (addr: %pM, type: %d, p2p: %d) from channel context: %d MHz\n",
		vif->addr, vif->type, vif->p2p,
		conf->def.chan->center_freq);

2421
	avp->chanctx = NULL;
2422
	ctx->nvifs_assigned--;
2423
	list_del(&avp->list);
2424
	ath9k_calculate_summary_state(sc, ctx);
2425 2426
	for (ac = 0; ac < IEEE80211_NUM_ACS; ac++)
		vif->hw_queue[ac] = IEEE80211_INVAL_HW_QUEUE;
2427

2428 2429 2430
	mutex_unlock(&sc->mutex);
}

2431 2432 2433 2434 2435 2436 2437 2438 2439 2440 2441 2442 2443 2444 2445 2446 2447 2448 2449 2450 2451
static void ath9k_mgd_prepare_tx(struct ieee80211_hw *hw,
				 struct ieee80211_vif *vif)
{
	struct ath_softc *sc = hw->priv;
	struct ath_common *common = ath9k_hw_common(sc->sc_ah);
	struct ath_vif *avp = (struct ath_vif *) vif->drv_priv;
	bool changed = false;

	if (!test_bit(ATH_OP_MULTI_CHANNEL, &common->op_flags))
		return;

	if (!avp->chanctx)
		return;

	mutex_lock(&sc->mutex);

	spin_lock_bh(&sc->chan_lock);
	if (sc->next_chan || (sc->cur_chan != avp->chanctx)) {
		sc->next_chan = avp->chanctx;
		changed = true;
	}
2452 2453 2454
	ath_dbg(common, CHAN_CTX,
		"%s: Set chanctx state to FORCE_ACTIVE, changed: %d\n",
		__func__, changed);
2455 2456 2457 2458 2459 2460 2461 2462 2463
	sc->sched.state = ATH_CHANCTX_STATE_FORCE_ACTIVE;
	spin_unlock_bh(&sc->chan_lock);

	if (changed)
		ath_chanctx_set_next(sc, true);

	mutex_unlock(&sc->mutex);
}

2464 2465
void ath9k_fill_chanctx_ops(void)
{
2466
	if (!ath9k_is_chanctx_enabled())
2467 2468
		return;

2469 2470 2471
	ath9k_ops.hw_scan                  = ath9k_hw_scan;
	ath9k_ops.cancel_hw_scan           = ath9k_cancel_hw_scan;
	ath9k_ops.remain_on_channel        = ath9k_remain_on_channel;
2472
	ath9k_ops.cancel_remain_on_channel = ath9k_cancel_remain_on_channel;
2473 2474 2475 2476 2477
	ath9k_ops.add_chanctx              = ath9k_add_chanctx;
	ath9k_ops.remove_chanctx           = ath9k_remove_chanctx;
	ath9k_ops.change_chanctx           = ath9k_change_chanctx;
	ath9k_ops.assign_vif_chanctx       = ath9k_assign_vif_chanctx;
	ath9k_ops.unassign_vif_chanctx     = ath9k_unassign_vif_chanctx;
2478
	ath9k_ops.mgd_prepare_tx           = ath9k_mgd_prepare_tx;
2479 2480
}

2481 2482
#endif

2483
struct ieee80211_ops ath9k_ops = {
2484 2485 2486 2487
	.tx 		    = ath9k_tx,
	.start 		    = ath9k_start,
	.stop 		    = ath9k_stop,
	.add_interface 	    = ath9k_add_interface,
2488
	.change_interface   = ath9k_change_interface,
2489 2490 2491
	.remove_interface   = ath9k_remove_interface,
	.config 	    = ath9k_config,
	.configure_filter   = ath9k_configure_filter,
2492 2493
	.sta_add	    = ath9k_sta_add,
	.sta_remove	    = ath9k_sta_remove,
2494
	.sta_notify         = ath9k_sta_notify,
2495 2496 2497 2498
	.conf_tx 	    = ath9k_conf_tx,
	.bss_info_changed   = ath9k_bss_info_changed,
	.set_key            = ath9k_set_key,
	.get_tsf 	    = ath9k_get_tsf,
2499
	.set_tsf 	    = ath9k_set_tsf,
2500
	.reset_tsf 	    = ath9k_reset_tsf,
2501
	.ampdu_action       = ath9k_ampdu_action,
2502
	.get_survey	    = ath9k_get_survey,
Johannes Berg's avatar
Johannes Berg committed
2503
	.rfkill_poll        = ath9k_rfkill_poll_state,
2504
	.set_coverage_class = ath9k_set_coverage_class,
2505
	.flush		    = ath9k_flush,
2506
	.tx_frames_pending  = ath9k_tx_frames_pending,
2507
	.tx_last_beacon     = ath9k_tx_last_beacon,
2508
	.release_buffered_frames = ath9k_release_buffered_frames,
2509
	.get_stats	    = ath9k_get_stats,
2510 2511
	.set_antenna	    = ath9k_set_antenna,
	.get_antenna	    = ath9k_get_antenna,
2512

Sujith Manoharan's avatar
Sujith Manoharan committed
2513
#ifdef CONFIG_ATH9K_WOW
2514 2515 2516 2517 2518
	.suspend	    = ath9k_suspend,
	.resume		    = ath9k_resume,
	.set_wakeup	    = ath9k_set_wakeup,
#endif

2519 2520
#ifdef CONFIG_ATH9K_DEBUGFS
	.get_et_sset_count  = ath9k_get_et_sset_count,
2521 2522 2523 2524
	.get_et_stats       = ath9k_get_et_stats,
	.get_et_strings     = ath9k_get_et_strings,
#endif

2525
#if defined(CONFIG_MAC80211_DEBUGFS) && defined(CONFIG_ATH9K_STATION_STATISTICS)
2526
	.sta_add_debugfs    = ath9k_sta_add_debugfs,
2527
#endif
2528 2529
	.sw_scan_start	    = ath9k_sw_scan_start,
	.sw_scan_complete   = ath9k_sw_scan_complete,
2530
};