aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/ath/ath9k/main.c
diff options
context:
space:
mode:
authorJohn W. Linville <linville@tuxdriver.com>2013-10-17 14:02:07 -0400
committerJohn W. Linville <linville@tuxdriver.com>2013-10-17 14:02:07 -0400
commit9f96da4dd2ccf685b506a21104cb13b1aadd907a (patch)
tree5d9eff61123f096e2434a9d36e6fdbd4cc5c6292 /drivers/net/wireless/ath/ath9k/main.c
parentccdbb6e96beca362db876d820ac1e560ff6d9579 (diff)
parentb6b561c31d51db3dec0cb55412a5d7a1a2397521 (diff)
Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless-next into for-davem
Diffstat (limited to 'drivers/net/wireless/ath/ath9k/main.c')
-rw-r--r--drivers/net/wireless/ath/ath9k/main.c157
1 files changed, 81 insertions, 76 deletions
diff --git a/drivers/net/wireless/ath/ath9k/main.c b/drivers/net/wireless/ath/ath9k/main.c
index cdb3b1e10b95..c42b55c1face 100644
--- a/drivers/net/wireless/ath/ath9k/main.c
+++ b/drivers/net/wireless/ath/ath9k/main.c
@@ -302,17 +302,91 @@ out:
302 * by reseting the chip. To accomplish this we must first cleanup any pending 302 * by reseting the chip. To accomplish this we must first cleanup any pending
303 * DMA, then restart stuff. 303 * DMA, then restart stuff.
304*/ 304*/
305static int ath_set_channel(struct ath_softc *sc, struct ieee80211_hw *hw, 305static int ath_set_channel(struct ath_softc *sc, struct cfg80211_chan_def *chandef)
306 struct ath9k_channel *hchan)
307{ 306{
307 struct ath_hw *ah = sc->sc_ah;
308 struct ath_common *common = ath9k_hw_common(ah);
309 struct ieee80211_hw *hw = sc->hw;
310 struct ath9k_channel *hchan;
311 struct ieee80211_channel *chan = chandef->chan;
312 unsigned long flags;
313 bool offchannel;
314 int pos = chan->hw_value;
315 int old_pos = -1;
308 int r; 316 int r;
309 317
310 if (test_bit(SC_OP_INVALID, &sc->sc_flags)) 318 if (test_bit(SC_OP_INVALID, &sc->sc_flags))
311 return -EIO; 319 return -EIO;
312 320
321 offchannel = !!(hw->conf.flags & IEEE80211_CONF_OFFCHANNEL);
322
323 if (ah->curchan)
324 old_pos = ah->curchan - &ah->channels[0];
325
326 ath_dbg(common, CONFIG, "Set channel: %d MHz width: %d\n",
327 chan->center_freq, chandef->width);
328
329 /* update survey stats for the old channel before switching */
330 spin_lock_irqsave(&common->cc_lock, flags);
331 ath_update_survey_stats(sc);
332 spin_unlock_irqrestore(&common->cc_lock, flags);
333
334 ath9k_cmn_get_channel(hw, ah, chandef);
335
336 /*
337 * If the operating channel changes, change the survey in-use flags
338 * along with it.
339 * Reset the survey data for the new channel, unless we're switching
340 * back to the operating channel from an off-channel operation.
341 */
342 if (!offchannel && sc->cur_survey != &sc->survey[pos]) {
343 if (sc->cur_survey)
344 sc->cur_survey->filled &= ~SURVEY_INFO_IN_USE;
345
346 sc->cur_survey = &sc->survey[pos];
347
348 memset(sc->cur_survey, 0, sizeof(struct survey_info));
349 sc->cur_survey->filled |= SURVEY_INFO_IN_USE;
350 } else if (!(sc->survey[pos].filled & SURVEY_INFO_IN_USE)) {
351 memset(&sc->survey[pos], 0, sizeof(struct survey_info));
352 }
353
354 hchan = &sc->sc_ah->channels[pos];
313 r = ath_reset_internal(sc, hchan); 355 r = ath_reset_internal(sc, hchan);
356 if (r)
357 return r;
314 358
315 return r; 359 /*
360 * The most recent snapshot of channel->noisefloor for the old
361 * channel is only available after the hardware reset. Copy it to
362 * the survey stats now.
363 */
364 if (old_pos >= 0)
365 ath_update_survey_nf(sc, old_pos);
366
367 /*
368 * Enable radar pulse detection if on a DFS channel. Spectral
369 * scanning and radar detection can not be used concurrently.
370 */
371 if (hw->conf.radar_enabled) {
372 u32 rxfilter;
373
374 /* set HW specific DFS configuration */
375 ath9k_hw_set_radar_params(ah);
376 rxfilter = ath9k_hw_getrxfilter(ah);
377 rxfilter |= ATH9K_RX_FILTER_PHYRADAR |
378 ATH9K_RX_FILTER_PHYERR;
379 ath9k_hw_setrxfilter(ah, rxfilter);
380 ath_dbg(common, DFS, "DFS enabled at freq %d\n",
381 chan->center_freq);
382 } else {
383 /* perform spectral scan if requested. */
384 if (test_bit(SC_OP_SCANNING, &sc->sc_flags) &&
385 sc->spectral_mode == SPECTRAL_CHANSCAN)
386 ath9k_spectral_scan_trigger(hw);
387 }
388
389 return 0;
316} 390}
317 391
318static void ath_node_attach(struct ath_softc *sc, struct ieee80211_sta *sta, 392static void ath_node_attach(struct ath_softc *sc, struct ieee80211_sta *sta,
@@ -601,7 +675,7 @@ static int ath9k_start(struct ieee80211_hw *hw)
601 ath9k_ps_wakeup(sc); 675 ath9k_ps_wakeup(sc);
602 mutex_lock(&sc->mutex); 676 mutex_lock(&sc->mutex);
603 677
604 init_channel = ath9k_cmn_get_curchannel(hw, ah); 678 init_channel = ath9k_cmn_get_channel(hw, ah, &hw->conf.chandef);
605 679
606 /* Reset SERDES registers */ 680 /* Reset SERDES registers */
607 ath9k_hw_configpcipowersave(ah, false); 681 ath9k_hw_configpcipowersave(ah, false);
@@ -804,7 +878,7 @@ static void ath9k_stop(struct ieee80211_hw *hw)
804 } 878 }
805 879
806 if (!ah->curchan) 880 if (!ah->curchan)
807 ah->curchan = ath9k_cmn_get_curchannel(hw, ah); 881 ah->curchan = ath9k_cmn_get_channel(hw, ah, &hw->conf.chandef);
808 882
809 ath9k_hw_reset(ah, ah->curchan, ah->caldata, false); 883 ath9k_hw_reset(ah, ah->curchan, ah->caldata, false);
810 ath9k_hw_phy_disable(ah); 884 ath9k_hw_phy_disable(ah);
@@ -823,7 +897,7 @@ static void ath9k_stop(struct ieee80211_hw *hw)
823 ath_dbg(common, CONFIG, "Driver halt\n"); 897 ath_dbg(common, CONFIG, "Driver halt\n");
824} 898}
825 899
826bool ath9k_uses_beacons(int type) 900static bool ath9k_uses_beacons(int type)
827{ 901{
828 switch (type) { 902 switch (type) {
829 case NL80211_IFTYPE_AP: 903 case NL80211_IFTYPE_AP:
@@ -1208,81 +1282,12 @@ static int ath9k_config(struct ieee80211_hw *hw, u32 changed)
1208 } 1282 }
1209 1283
1210 if ((changed & IEEE80211_CONF_CHANGE_CHANNEL) || reset_channel) { 1284 if ((changed & IEEE80211_CONF_CHANGE_CHANNEL) || reset_channel) {
1211 struct ieee80211_channel *curchan = hw->conf.chandef.chan; 1285 if (ath_set_channel(sc, &hw->conf.chandef) < 0) {
1212 int pos = curchan->hw_value;
1213 int old_pos = -1;
1214 unsigned long flags;
1215
1216 if (ah->curchan)
1217 old_pos = ah->curchan - &ah->channels[0];
1218
1219 ath_dbg(common, CONFIG, "Set channel: %d MHz width: %d\n",
1220 curchan->center_freq, hw->conf.chandef.width);
1221
1222 /* update survey stats for the old channel before switching */
1223 spin_lock_irqsave(&common->cc_lock, flags);
1224 ath_update_survey_stats(sc);
1225 spin_unlock_irqrestore(&common->cc_lock, flags);
1226
1227 ath9k_cmn_update_ichannel(&sc->sc_ah->channels[pos],
1228 &conf->chandef);
1229
1230 /*
1231 * If the operating channel changes, change the survey in-use flags
1232 * along with it.
1233 * Reset the survey data for the new channel, unless we're switching
1234 * back to the operating channel from an off-channel operation.
1235 */
1236 if (!(hw->conf.flags & IEEE80211_CONF_OFFCHANNEL) &&
1237 sc->cur_survey != &sc->survey[pos]) {
1238
1239 if (sc->cur_survey)
1240 sc->cur_survey->filled &= ~SURVEY_INFO_IN_USE;
1241
1242 sc->cur_survey = &sc->survey[pos];
1243
1244 memset(sc->cur_survey, 0, sizeof(struct survey_info));
1245 sc->cur_survey->filled |= SURVEY_INFO_IN_USE;
1246 } else if (!(sc->survey[pos].filled & SURVEY_INFO_IN_USE)) {
1247 memset(&sc->survey[pos], 0, sizeof(struct survey_info));
1248 }
1249
1250 if (ath_set_channel(sc, hw, &sc->sc_ah->channels[pos]) < 0) {
1251 ath_err(common, "Unable to set channel\n"); 1286 ath_err(common, "Unable to set channel\n");
1252 mutex_unlock(&sc->mutex); 1287 mutex_unlock(&sc->mutex);
1253 ath9k_ps_restore(sc); 1288 ath9k_ps_restore(sc);
1254 return -EINVAL; 1289 return -EINVAL;
1255 } 1290 }
1256
1257 /*
1258 * The most recent snapshot of channel->noisefloor for the old
1259 * channel is only available after the hardware reset. Copy it to
1260 * the survey stats now.
1261 */
1262 if (old_pos >= 0)
1263 ath_update_survey_nf(sc, old_pos);
1264
1265 /*
1266 * Enable radar pulse detection if on a DFS channel. Spectral
1267 * scanning and radar detection can not be used concurrently.
1268 */
1269 if (hw->conf.radar_enabled) {
1270 u32 rxfilter;
1271
1272 /* set HW specific DFS configuration */
1273 ath9k_hw_set_radar_params(ah);
1274 rxfilter = ath9k_hw_getrxfilter(ah);
1275 rxfilter |= ATH9K_RX_FILTER_PHYRADAR |
1276 ATH9K_RX_FILTER_PHYERR;
1277 ath9k_hw_setrxfilter(ah, rxfilter);
1278 ath_dbg(common, DFS, "DFS enabled at freq %d\n",
1279 curchan->center_freq);
1280 } else {
1281 /* perform spectral scan if requested. */
1282 if (test_bit(SC_OP_SCANNING, &sc->sc_flags) &&
1283 sc->spectral_mode == SPECTRAL_CHANSCAN)
1284 ath9k_spectral_scan_trigger(hw);
1285 }
1286 } 1291 }
1287 1292
1288 if (changed & IEEE80211_CONF_CHANGE_POWER) { 1293 if (changed & IEEE80211_CONF_CHANGE_POWER) {