diff options
-rw-r--r-- | drivers/net/wireless/ath/ath9k/Makefile | 3 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ath9k/ath9k.h | 18 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ath9k/channel.c | 133 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ath9k/init.c | 1 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ath9k/link.c | 2 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ath9k/main.c | 111 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ath9k/recv.c | 4 |
7 files changed, 169 insertions, 103 deletions
diff --git a/drivers/net/wireless/ath/ath9k/Makefile b/drivers/net/wireless/ath/ath9k/Makefile index 8fcd586d1c39..6b4020a57984 100644 --- a/drivers/net/wireless/ath/ath9k/Makefile +++ b/drivers/net/wireless/ath/ath9k/Makefile | |||
@@ -5,7 +5,8 @@ ath9k-y += beacon.o \ | |||
5 | recv.o \ | 5 | recv.o \ |
6 | xmit.o \ | 6 | xmit.o \ |
7 | link.o \ | 7 | link.o \ |
8 | antenna.o | 8 | antenna.o \ |
9 | channel.o | ||
9 | 10 | ||
10 | ath9k-$(CONFIG_ATH9K_BTCOEX_SUPPORT) += mci.o | 11 | ath9k-$(CONFIG_ATH9K_BTCOEX_SUPPORT) += mci.o |
11 | ath9k-$(CONFIG_ATH9K_PCI) += pci.o | 12 | ath9k-$(CONFIG_ATH9K_PCI) += pci.o |
diff --git a/drivers/net/wireless/ath/ath9k/ath9k.h b/drivers/net/wireless/ath/ath9k/ath9k.h index 2ca8f7e06174..8c87eb7fb6de 100644 --- a/drivers/net/wireless/ath/ath9k/ath9k.h +++ b/drivers/net/wireless/ath/ath9k/ath9k.h | |||
@@ -325,6 +325,16 @@ struct ath_rx { | |||
325 | u32 ampdu_ref; | 325 | u32 ampdu_ref; |
326 | }; | 326 | }; |
327 | 327 | ||
328 | struct ath_chanctx { | ||
329 | struct cfg80211_chan_def chandef; | ||
330 | struct list_head vifs; | ||
331 | bool offchannel; | ||
332 | }; | ||
333 | |||
334 | void ath_chanctx_init(struct ath_softc *sc); | ||
335 | int ath_chanctx_set_channel(struct ath_softc *sc, struct ath_chanctx *ctx, | ||
336 | struct cfg80211_chan_def *chandef); | ||
337 | int ath_reset_internal(struct ath_softc *sc, struct ath9k_channel *hchan); | ||
328 | int ath_startrecv(struct ath_softc *sc); | 338 | int ath_startrecv(struct ath_softc *sc); |
329 | bool ath_stoprecv(struct ath_softc *sc); | 339 | bool ath_stoprecv(struct ath_softc *sc); |
330 | u32 ath_calcrxfilter(struct ath_softc *sc); | 340 | u32 ath_calcrxfilter(struct ath_softc *sc); |
@@ -370,12 +380,15 @@ void ath9k_release_buffered_frames(struct ieee80211_hw *hw, | |||
370 | /********/ | 380 | /********/ |
371 | 381 | ||
372 | struct ath_vif { | 382 | struct ath_vif { |
383 | struct list_head list; | ||
384 | |||
373 | struct ieee80211_vif *vif; | 385 | struct ieee80211_vif *vif; |
374 | struct ath_node mcast_node; | 386 | struct ath_node mcast_node; |
375 | int av_bslot; | 387 | int av_bslot; |
376 | bool primary_sta_vif; | 388 | bool primary_sta_vif; |
377 | __le64 tsf_adjust; /* TSF adjustment for staggered beacons */ | 389 | __le64 tsf_adjust; /* TSF adjustment for staggered beacons */ |
378 | struct ath_buf *av_bcbuf; | 390 | struct ath_buf *av_bcbuf; |
391 | struct ath_chanctx *chanctx; | ||
379 | 392 | ||
380 | /* P2P Client */ | 393 | /* P2P Client */ |
381 | struct ieee80211_noa_data noa; | 394 | struct ieee80211_noa_data noa; |
@@ -702,6 +715,8 @@ void ath_ant_comb_scan(struct ath_softc *sc, struct ath_rx_status *rs); | |||
702 | #define PS_BEACON_SYNC BIT(4) | 715 | #define PS_BEACON_SYNC BIT(4) |
703 | #define PS_WAIT_FOR_ANI BIT(5) | 716 | #define PS_WAIT_FOR_ANI BIT(5) |
704 | 717 | ||
718 | #define ATH9K_NUM_CHANCTX 2 /* supports 2 operating channels */ | ||
719 | |||
705 | struct ath_softc { | 720 | struct ath_softc { |
706 | struct ieee80211_hw *hw; | 721 | struct ieee80211_hw *hw; |
707 | struct device *dev; | 722 | struct device *dev; |
@@ -743,6 +758,9 @@ struct ath_softc { | |||
743 | struct ath_tx tx; | 758 | struct ath_tx tx; |
744 | struct ath_beacon beacon; | 759 | struct ath_beacon beacon; |
745 | 760 | ||
761 | struct ath_chanctx chanctx[ATH9K_NUM_CHANCTX]; | ||
762 | struct ath_chanctx *cur_chan; | ||
763 | |||
746 | #ifdef CONFIG_MAC80211_LEDS | 764 | #ifdef CONFIG_MAC80211_LEDS |
747 | bool led_registered; | 765 | bool led_registered; |
748 | char led_name[32]; | 766 | char led_name[32]; |
diff --git a/drivers/net/wireless/ath/ath9k/channel.c b/drivers/net/wireless/ath/ath9k/channel.c new file mode 100644 index 000000000000..aee6cdb4975b --- /dev/null +++ b/drivers/net/wireless/ath/ath9k/channel.c | |||
@@ -0,0 +1,133 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2014 Qualcomm Atheros, Inc. | ||
3 | * | ||
4 | * Permission to use, copy, modify, and/or distribute this software for any | ||
5 | * purpose with or without fee is hereby granted, provided that the above | ||
6 | * copyright notice and this permission notice appear in all copies. | ||
7 | * | ||
8 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | ||
9 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | ||
10 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR | ||
11 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | ||
12 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN | ||
13 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF | ||
14 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | ||
15 | */ | ||
16 | |||
17 | #include "ath9k.h" | ||
18 | |||
19 | /* Set/change channels. If the channel is really being changed, it's done | ||
20 | * by reseting the chip. To accomplish this we must first cleanup any pending | ||
21 | * DMA, then restart stuff. | ||
22 | */ | ||
23 | static int ath_set_channel(struct ath_softc *sc) | ||
24 | { | ||
25 | struct ath_hw *ah = sc->sc_ah; | ||
26 | struct ath_common *common = ath9k_hw_common(ah); | ||
27 | struct ieee80211_hw *hw = sc->hw; | ||
28 | struct ath9k_channel *hchan; | ||
29 | struct cfg80211_chan_def *chandef = &sc->cur_chan->chandef; | ||
30 | struct ieee80211_channel *chan = chandef->chan; | ||
31 | int pos = chan->hw_value; | ||
32 | int old_pos = -1; | ||
33 | int r; | ||
34 | |||
35 | if (test_bit(ATH_OP_INVALID, &common->op_flags)) | ||
36 | return -EIO; | ||
37 | |||
38 | if (ah->curchan) | ||
39 | old_pos = ah->curchan - &ah->channels[0]; | ||
40 | |||
41 | ath_dbg(common, CONFIG, "Set channel: %d MHz width: %d\n", | ||
42 | chan->center_freq, chandef->width); | ||
43 | |||
44 | /* update survey stats for the old channel before switching */ | ||
45 | spin_lock_bh(&common->cc_lock); | ||
46 | ath_update_survey_stats(sc); | ||
47 | spin_unlock_bh(&common->cc_lock); | ||
48 | |||
49 | ath9k_cmn_get_channel(hw, ah, chandef); | ||
50 | |||
51 | /* If the operating channel changes, change the survey in-use flags | ||
52 | * along with it. | ||
53 | * Reset the survey data for the new channel, unless we're switching | ||
54 | * back to the operating channel from an off-channel operation. | ||
55 | */ | ||
56 | if (!sc->cur_chan->offchannel && sc->cur_survey != &sc->survey[pos]) { | ||
57 | if (sc->cur_survey) | ||
58 | sc->cur_survey->filled &= ~SURVEY_INFO_IN_USE; | ||
59 | |||
60 | sc->cur_survey = &sc->survey[pos]; | ||
61 | |||
62 | memset(sc->cur_survey, 0, sizeof(struct survey_info)); | ||
63 | sc->cur_survey->filled |= SURVEY_INFO_IN_USE; | ||
64 | } else if (!(sc->survey[pos].filled & SURVEY_INFO_IN_USE)) { | ||
65 | memset(&sc->survey[pos], 0, sizeof(struct survey_info)); | ||
66 | } | ||
67 | |||
68 | hchan = &sc->sc_ah->channels[pos]; | ||
69 | r = ath_reset_internal(sc, hchan); | ||
70 | if (r) | ||
71 | return r; | ||
72 | |||
73 | /* The most recent snapshot of channel->noisefloor for the old | ||
74 | * channel is only available after the hardware reset. Copy it to | ||
75 | * the survey stats now. | ||
76 | */ | ||
77 | if (old_pos >= 0) | ||
78 | ath_update_survey_nf(sc, old_pos); | ||
79 | |||
80 | /* Enable radar pulse detection if on a DFS channel. Spectral | ||
81 | * scanning and radar detection can not be used concurrently. | ||
82 | */ | ||
83 | if (hw->conf.radar_enabled) { | ||
84 | u32 rxfilter; | ||
85 | |||
86 | /* set HW specific DFS configuration */ | ||
87 | ath9k_hw_set_radar_params(ah); | ||
88 | rxfilter = ath9k_hw_getrxfilter(ah); | ||
89 | rxfilter |= ATH9K_RX_FILTER_PHYRADAR | | ||
90 | ATH9K_RX_FILTER_PHYERR; | ||
91 | ath9k_hw_setrxfilter(ah, rxfilter); | ||
92 | ath_dbg(common, DFS, "DFS enabled at freq %d\n", | ||
93 | chan->center_freq); | ||
94 | } else { | ||
95 | /* perform spectral scan if requested. */ | ||
96 | if (test_bit(ATH_OP_SCANNING, &common->op_flags) && | ||
97 | sc->spectral_mode == SPECTRAL_CHANSCAN) | ||
98 | ath9k_spectral_scan_trigger(hw); | ||
99 | } | ||
100 | |||
101 | return 0; | ||
102 | } | ||
103 | |||
104 | void ath_chanctx_init(struct ath_softc *sc) | ||
105 | { | ||
106 | struct ath_chanctx *ctx; | ||
107 | struct ath_common *common = ath9k_hw_common(sc->sc_ah); | ||
108 | struct ieee80211_supported_band *sband; | ||
109 | struct ieee80211_channel *chan; | ||
110 | int i; | ||
111 | |||
112 | sband = &common->sbands[IEEE80211_BAND_2GHZ]; | ||
113 | if (!sband->n_channels) | ||
114 | sband = &common->sbands[IEEE80211_BAND_5GHZ]; | ||
115 | |||
116 | chan = &sband->channels[0]; | ||
117 | for (i = 0; i < ATH9K_NUM_CHANCTX; i++) { | ||
118 | ctx = &sc->chanctx[i]; | ||
119 | cfg80211_chandef_create(&ctx->chandef, chan, NL80211_CHAN_HT20); | ||
120 | INIT_LIST_HEAD(&ctx->vifs); | ||
121 | } | ||
122 | sc->cur_chan = &sc->chanctx[0]; | ||
123 | } | ||
124 | |||
125 | int ath_chanctx_set_channel(struct ath_softc *sc, struct ath_chanctx *ctx, | ||
126 | struct cfg80211_chan_def *chandef) | ||
127 | { | ||
128 | memcpy(&ctx->chandef, chandef, sizeof(ctx->chandef)); | ||
129 | if (ctx != sc->cur_chan) | ||
130 | return 0; | ||
131 | |||
132 | return ath_set_channel(sc); | ||
133 | } | ||
diff --git a/drivers/net/wireless/ath/ath9k/init.c b/drivers/net/wireless/ath/ath9k/init.c index 0246b990fe87..32d954275d47 100644 --- a/drivers/net/wireless/ath/ath9k/init.c +++ b/drivers/net/wireless/ath/ath9k/init.c | |||
@@ -599,6 +599,7 @@ static int ath9k_init_softc(u16 devid, struct ath_softc *sc, | |||
599 | ath9k_cmn_init_crypto(sc->sc_ah); | 599 | ath9k_cmn_init_crypto(sc->sc_ah); |
600 | ath9k_init_misc(sc); | 600 | ath9k_init_misc(sc); |
601 | ath_fill_led_pin(sc); | 601 | ath_fill_led_pin(sc); |
602 | ath_chanctx_init(sc); | ||
602 | 603 | ||
603 | if (common->bus_ops->aspm_init) | 604 | if (common->bus_ops->aspm_init) |
604 | common->bus_ops->aspm_init(common); | 605 | common->bus_ops->aspm_init(common); |
diff --git a/drivers/net/wireless/ath/ath9k/link.c b/drivers/net/wireless/ath/ath9k/link.c index 72a715fe8f24..6f91974c7b08 100644 --- a/drivers/net/wireless/ath/ath9k/link.c +++ b/drivers/net/wireless/ath/ath9k/link.c | |||
@@ -416,7 +416,7 @@ void ath_start_ani(struct ath_softc *sc) | |||
416 | 416 | ||
417 | if (common->disable_ani || | 417 | if (common->disable_ani || |
418 | !test_bit(ATH_OP_ANI_RUN, &common->op_flags) || | 418 | !test_bit(ATH_OP_ANI_RUN, &common->op_flags) || |
419 | (sc->hw->conf.flags & IEEE80211_CONF_OFFCHANNEL)) | 419 | sc->cur_chan->offchannel) |
420 | return; | 420 | return; |
421 | 421 | ||
422 | common->ani.longcal_timer = timestamp; | 422 | common->ani.longcal_timer = timestamp; |
diff --git a/drivers/net/wireless/ath/ath9k/main.c b/drivers/net/wireless/ath/ath9k/main.c index 62ac95d6bb9d..2e7cce7b1238 100644 --- a/drivers/net/wireless/ath/ath9k/main.c +++ b/drivers/net/wireless/ath/ath9k/main.c | |||
@@ -233,7 +233,7 @@ static bool ath_complete_reset(struct ath_softc *sc, bool start) | |||
233 | ath9k_hw_set_interrupts(ah); | 233 | ath9k_hw_set_interrupts(ah); |
234 | ath9k_hw_enable_interrupts(ah); | 234 | ath9k_hw_enable_interrupts(ah); |
235 | 235 | ||
236 | if (!(sc->hw->conf.flags & IEEE80211_CONF_OFFCHANNEL) && start) { | 236 | if (!sc->cur_chan->offchannel && start) { |
237 | if (!test_bit(ATH_OP_BEACONS, &common->op_flags)) | 237 | if (!test_bit(ATH_OP_BEACONS, &common->op_flags)) |
238 | goto work; | 238 | goto work; |
239 | 239 | ||
@@ -266,7 +266,7 @@ static bool ath_complete_reset(struct ath_softc *sc, bool start) | |||
266 | return true; | 266 | return true; |
267 | } | 267 | } |
268 | 268 | ||
269 | static int ath_reset_internal(struct ath_softc *sc, struct ath9k_channel *hchan) | 269 | int ath_reset_internal(struct ath_softc *sc, struct ath9k_channel *hchan) |
270 | { | 270 | { |
271 | struct ath_hw *ah = sc->sc_ah; | 271 | struct ath_hw *ah = sc->sc_ah; |
272 | struct ath_common *common = ath9k_hw_common(ah); | 272 | struct ath_common *common = ath9k_hw_common(ah); |
@@ -279,7 +279,7 @@ static int ath_reset_internal(struct ath_softc *sc, struct ath9k_channel *hchan) | |||
279 | tasklet_disable(&sc->intr_tq); | 279 | tasklet_disable(&sc->intr_tq); |
280 | spin_lock_bh(&sc->sc_pcu_lock); | 280 | spin_lock_bh(&sc->sc_pcu_lock); |
281 | 281 | ||
282 | if (!(sc->hw->conf.flags & IEEE80211_CONF_OFFCHANNEL)) { | 282 | if (!sc->cur_chan->offchannel) { |
283 | fastcc = false; | 283 | fastcc = false; |
284 | caldata = &sc->caldata; | 284 | caldata = &sc->caldata; |
285 | } | 285 | } |
@@ -307,7 +307,7 @@ static int ath_reset_internal(struct ath_softc *sc, struct ath9k_channel *hchan) | |||
307 | } | 307 | } |
308 | 308 | ||
309 | if (ath9k_hw_mci_is_enabled(sc->sc_ah) && | 309 | if (ath9k_hw_mci_is_enabled(sc->sc_ah) && |
310 | (sc->hw->conf.flags & IEEE80211_CONF_OFFCHANNEL)) | 310 | sc->cur_chan->offchannel) |
311 | ath9k_mci_set_txpower(sc, true, false); | 311 | ath9k_mci_set_txpower(sc, true, false); |
312 | 312 | ||
313 | if (!ath_complete_reset(sc, true)) | 313 | if (!ath_complete_reset(sc, true)) |
@@ -320,98 +320,6 @@ out: | |||
320 | return r; | 320 | return r; |
321 | } | 321 | } |
322 | 322 | ||
323 | |||
324 | /* | ||
325 | * Set/change channels. If the channel is really being changed, it's done | ||
326 | * by reseting the chip. To accomplish this we must first cleanup any pending | ||
327 | * DMA, then restart stuff. | ||
328 | */ | ||
329 | static int ath_set_channel(struct ath_softc *sc, struct cfg80211_chan_def *chandef) | ||
330 | { | ||
331 | struct ath_hw *ah = sc->sc_ah; | ||
332 | struct ath_common *common = ath9k_hw_common(ah); | ||
333 | struct ieee80211_hw *hw = sc->hw; | ||
334 | struct ath9k_channel *hchan; | ||
335 | struct ieee80211_channel *chan = chandef->chan; | ||
336 | bool offchannel; | ||
337 | int pos = chan->hw_value; | ||
338 | int old_pos = -1; | ||
339 | int r; | ||
340 | |||
341 | if (test_bit(ATH_OP_INVALID, &common->op_flags)) | ||
342 | return -EIO; | ||
343 | |||
344 | offchannel = !!(hw->conf.flags & IEEE80211_CONF_OFFCHANNEL); | ||
345 | |||
346 | if (ah->curchan) | ||
347 | old_pos = ah->curchan - &ah->channels[0]; | ||
348 | |||
349 | ath_dbg(common, CONFIG, "Set channel: %d MHz width: %d\n", | ||
350 | chan->center_freq, chandef->width); | ||
351 | |||
352 | /* update survey stats for the old channel before switching */ | ||
353 | spin_lock_bh(&common->cc_lock); | ||
354 | ath_update_survey_stats(sc); | ||
355 | spin_unlock_bh(&common->cc_lock); | ||
356 | |||
357 | ath9k_cmn_get_channel(hw, ah, chandef); | ||
358 | |||
359 | /* | ||
360 | * If the operating channel changes, change the survey in-use flags | ||
361 | * along with it. | ||
362 | * Reset the survey data for the new channel, unless we're switching | ||
363 | * back to the operating channel from an off-channel operation. | ||
364 | */ | ||
365 | if (!offchannel && sc->cur_survey != &sc->survey[pos]) { | ||
366 | if (sc->cur_survey) | ||
367 | sc->cur_survey->filled &= ~SURVEY_INFO_IN_USE; | ||
368 | |||
369 | sc->cur_survey = &sc->survey[pos]; | ||
370 | |||
371 | memset(sc->cur_survey, 0, sizeof(struct survey_info)); | ||
372 | sc->cur_survey->filled |= SURVEY_INFO_IN_USE; | ||
373 | } else if (!(sc->survey[pos].filled & SURVEY_INFO_IN_USE)) { | ||
374 | memset(&sc->survey[pos], 0, sizeof(struct survey_info)); | ||
375 | } | ||
376 | |||
377 | hchan = &sc->sc_ah->channels[pos]; | ||
378 | r = ath_reset_internal(sc, hchan); | ||
379 | if (r) | ||
380 | return r; | ||
381 | |||
382 | /* | ||
383 | * The most recent snapshot of channel->noisefloor for the old | ||
384 | * channel is only available after the hardware reset. Copy it to | ||
385 | * the survey stats now. | ||
386 | */ | ||
387 | if (old_pos >= 0) | ||
388 | ath_update_survey_nf(sc, old_pos); | ||
389 | |||
390 | /* | ||
391 | * Enable radar pulse detection if on a DFS channel. Spectral | ||
392 | * scanning and radar detection can not be used concurrently. | ||
393 | */ | ||
394 | if (hw->conf.radar_enabled) { | ||
395 | u32 rxfilter; | ||
396 | |||
397 | /* set HW specific DFS configuration */ | ||
398 | ath9k_hw_set_radar_params(ah); | ||
399 | rxfilter = ath9k_hw_getrxfilter(ah); | ||
400 | rxfilter |= ATH9K_RX_FILTER_PHYRADAR | | ||
401 | ATH9K_RX_FILTER_PHYERR; | ||
402 | ath9k_hw_setrxfilter(ah, rxfilter); | ||
403 | ath_dbg(common, DFS, "DFS enabled at freq %d\n", | ||
404 | chan->center_freq); | ||
405 | } else { | ||
406 | /* perform spectral scan if requested. */ | ||
407 | if (test_bit(ATH_OP_SCANNING, &common->op_flags) && | ||
408 | sc->spectral_mode == SPECTRAL_CHANSCAN) | ||
409 | ath9k_spectral_scan_trigger(hw); | ||
410 | } | ||
411 | |||
412 | return 0; | ||
413 | } | ||
414 | |||
415 | static void ath_node_attach(struct ath_softc *sc, struct ieee80211_sta *sta, | 323 | static void ath_node_attach(struct ath_softc *sc, struct ieee80211_sta *sta, |
416 | struct ieee80211_vif *vif) | 324 | struct ieee80211_vif *vif) |
417 | { | 325 | { |
@@ -713,6 +621,7 @@ static int ath9k_start(struct ieee80211_hw *hw) | |||
713 | struct ath_hw *ah = sc->sc_ah; | 621 | struct ath_hw *ah = sc->sc_ah; |
714 | struct ath_common *common = ath9k_hw_common(ah); | 622 | struct ath_common *common = ath9k_hw_common(ah); |
715 | struct ieee80211_channel *curchan = hw->conf.chandef.chan; | 623 | struct ieee80211_channel *curchan = hw->conf.chandef.chan; |
624 | struct ath_chanctx *ctx = sc->cur_chan; | ||
716 | struct ath9k_channel *init_channel; | 625 | struct ath9k_channel *init_channel; |
717 | int r; | 626 | int r; |
718 | 627 | ||
@@ -723,7 +632,8 @@ static int ath9k_start(struct ieee80211_hw *hw) | |||
723 | ath9k_ps_wakeup(sc); | 632 | ath9k_ps_wakeup(sc); |
724 | mutex_lock(&sc->mutex); | 633 | mutex_lock(&sc->mutex); |
725 | 634 | ||
726 | init_channel = ath9k_cmn_get_channel(hw, ah, &hw->conf.chandef); | 635 | memcpy(&ctx->chandef, &hw->conf.chandef, sizeof(ctx->chandef)); |
636 | init_channel = ath9k_cmn_get_channel(hw, ah, &ctx->chandef); | ||
727 | 637 | ||
728 | /* Reset SERDES registers */ | 638 | /* Reset SERDES registers */ |
729 | ath9k_hw_configpcipowersave(ah, false); | 639 | ath9k_hw_configpcipowersave(ah, false); |
@@ -934,7 +844,8 @@ static void ath9k_stop(struct ieee80211_hw *hw) | |||
934 | } | 844 | } |
935 | 845 | ||
936 | if (!ah->curchan) | 846 | if (!ah->curchan) |
937 | ah->curchan = ath9k_cmn_get_channel(hw, ah, &hw->conf.chandef); | 847 | ah->curchan = ath9k_cmn_get_channel(hw, ah, |
848 | &sc->cur_chan->chandef); | ||
938 | 849 | ||
939 | ath9k_hw_reset(ah, ah->curchan, ah->caldata, false); | 850 | ath9k_hw_reset(ah, ah->curchan, ah->caldata, false); |
940 | ath9k_hw_phy_disable(ah); | 851 | ath9k_hw_phy_disable(ah); |
@@ -1345,6 +1256,7 @@ static int ath9k_config(struct ieee80211_hw *hw, u32 changed) | |||
1345 | struct ath_hw *ah = sc->sc_ah; | 1256 | struct ath_hw *ah = sc->sc_ah; |
1346 | struct ath_common *common = ath9k_hw_common(ah); | 1257 | struct ath_common *common = ath9k_hw_common(ah); |
1347 | struct ieee80211_conf *conf = &hw->conf; | 1258 | struct ieee80211_conf *conf = &hw->conf; |
1259 | struct ath_chanctx *ctx = sc->cur_chan; | ||
1348 | bool reset_channel = false; | 1260 | bool reset_channel = false; |
1349 | 1261 | ||
1350 | ath9k_ps_wakeup(sc); | 1262 | ath9k_ps_wakeup(sc); |
@@ -1392,7 +1304,8 @@ static int ath9k_config(struct ieee80211_hw *hw, u32 changed) | |||
1392 | } | 1304 | } |
1393 | 1305 | ||
1394 | if ((changed & IEEE80211_CONF_CHANGE_CHANNEL) || reset_channel) { | 1306 | if ((changed & IEEE80211_CONF_CHANGE_CHANNEL) || reset_channel) { |
1395 | if (ath_set_channel(sc, &hw->conf.chandef) < 0) { | 1307 | ctx->offchannel = !!(conf->flags & IEEE80211_CONF_OFFCHANNEL); |
1308 | if (ath_chanctx_set_channel(sc, ctx, &hw->conf.chandef) < 0) { | ||
1396 | ath_err(common, "Unable to set channel\n"); | 1309 | ath_err(common, "Unable to set channel\n"); |
1397 | mutex_unlock(&sc->mutex); | 1310 | mutex_unlock(&sc->mutex); |
1398 | ath9k_ps_restore(sc); | 1311 | ath9k_ps_restore(sc); |
diff --git a/drivers/net/wireless/ath/ath9k/recv.c b/drivers/net/wireless/ath/ath9k/recv.c index 9105a92364f7..de5684a33dd7 100644 --- a/drivers/net/wireless/ath/ath9k/recv.c +++ b/drivers/net/wireless/ath/ath9k/recv.c | |||
@@ -259,7 +259,7 @@ static void ath_edma_start_recv(struct ath_softc *sc) | |||
259 | ath_rx_addbuffer_edma(sc, ATH9K_RX_QUEUE_HP); | 259 | ath_rx_addbuffer_edma(sc, ATH9K_RX_QUEUE_HP); |
260 | ath_rx_addbuffer_edma(sc, ATH9K_RX_QUEUE_LP); | 260 | ath_rx_addbuffer_edma(sc, ATH9K_RX_QUEUE_LP); |
261 | ath_opmode_init(sc); | 261 | ath_opmode_init(sc); |
262 | ath9k_hw_startpcureceive(sc->sc_ah, !!(sc->hw->conf.flags & IEEE80211_CONF_OFFCHANNEL)); | 262 | ath9k_hw_startpcureceive(sc->sc_ah, sc->cur_chan->offchannel); |
263 | } | 263 | } |
264 | 264 | ||
265 | static void ath_edma_stop_recv(struct ath_softc *sc) | 265 | static void ath_edma_stop_recv(struct ath_softc *sc) |
@@ -457,7 +457,7 @@ int ath_startrecv(struct ath_softc *sc) | |||
457 | 457 | ||
458 | start_recv: | 458 | start_recv: |
459 | ath_opmode_init(sc); | 459 | ath_opmode_init(sc); |
460 | ath9k_hw_startpcureceive(ah, !!(sc->hw->conf.flags & IEEE80211_CONF_OFFCHANNEL)); | 460 | ath9k_hw_startpcureceive(ah, sc->cur_chan->offchannel); |
461 | 461 | ||
462 | return 0; | 462 | return 0; |
463 | } | 463 | } |