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