aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorSimon Wunderlich <simon.wunderlich@s2003.tu-chemnitz.de>2013-08-14 02:01:38 -0400
committerJohn W. Linville <linville@tuxdriver.com>2013-08-16 14:17:50 -0400
commitd074e8d547853cc8b40cf93a460e8fbf9eaa3d00 (patch)
tree9b7285946795fb7ed20336770453ec7b16822db9 /drivers
parent4d70f2fbe12118c5526a1d761f8ef562cecbbc2c (diff)
ath9k: enable CSA functionality in ath9k
CSA is only enabled for one interface, but the same limitation applies for mac80211 too. It checks whether the beacon has been sent (different approaches for non-EDMA-enabled and EDMA-enabled devices), and completes the channel switch after that. Signed-off-by: Simon Wunderlich <siwu@hrz.tu-chemnitz.de> Signed-off-by: Mathias Kretschmer <mathias.kretschmer@fokus.fraunhofer.de> Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/net/wireless/ath/ath9k/ath9k.h2
-rw-r--r--drivers/net/wireless/ath/ath9k/beacon.c21
-rw-r--r--drivers/net/wireless/ath/ath9k/init.c1
-rw-r--r--drivers/net/wireless/ath/ath9k/main.c17
-rw-r--r--drivers/net/wireless/ath/ath9k/xmit.c2
5 files changed, 43 insertions, 0 deletions
diff --git a/drivers/net/wireless/ath/ath9k/ath9k.h b/drivers/net/wireless/ath/ath9k/ath9k.h
index df1c4957e3f0..8519e75a2e79 100644
--- a/drivers/net/wireless/ath/ath9k/ath9k.h
+++ b/drivers/net/wireless/ath/ath9k/ath9k.h
@@ -420,6 +420,7 @@ void ath9k_beacon_assign_slot(struct ath_softc *sc, struct ieee80211_vif *vif);
420void ath9k_beacon_remove_slot(struct ath_softc *sc, struct ieee80211_vif *vif); 420void ath9k_beacon_remove_slot(struct ath_softc *sc, struct ieee80211_vif *vif);
421void ath9k_set_tsfadjust(struct ath_softc *sc, struct ieee80211_vif *vif); 421void ath9k_set_tsfadjust(struct ath_softc *sc, struct ieee80211_vif *vif);
422void ath9k_set_beacon(struct ath_softc *sc); 422void ath9k_set_beacon(struct ath_softc *sc);
423bool ath9k_csa_is_finished(struct ath_softc *sc);
423 424
424/*******************/ 425/*******************/
425/* Link Monitoring */ 426/* Link Monitoring */
@@ -756,6 +757,7 @@ struct ath_softc {
756#endif 757#endif
757 758
758 struct ath_descdma txsdma; 759 struct ath_descdma txsdma;
760 struct ieee80211_vif *csa_vif;
759 761
760 struct ath_ant_comb ant_comb; 762 struct ath_ant_comb ant_comb;
761 u8 ant_tx, ant_rx; 763 u8 ant_tx, ant_rx;
diff --git a/drivers/net/wireless/ath/ath9k/beacon.c b/drivers/net/wireless/ath/ath9k/beacon.c
index 1a17732bb089..b5c16b3a37b9 100644
--- a/drivers/net/wireless/ath/ath9k/beacon.c
+++ b/drivers/net/wireless/ath/ath9k/beacon.c
@@ -291,6 +291,23 @@ void ath9k_set_tsfadjust(struct ath_softc *sc, struct ieee80211_vif *vif)
291 (unsigned long long)tsfadjust, avp->av_bslot); 291 (unsigned long long)tsfadjust, avp->av_bslot);
292} 292}
293 293
294bool ath9k_csa_is_finished(struct ath_softc *sc)
295{
296 struct ieee80211_vif *vif;
297
298 vif = sc->csa_vif;
299 if (!vif || !vif->csa_active)
300 return false;
301
302 if (!ieee80211_csa_is_complete(vif))
303 return false;
304
305 ieee80211_csa_finish(vif);
306
307 sc->csa_vif = NULL;
308 return true;
309}
310
294void ath9k_beacon_tasklet(unsigned long data) 311void ath9k_beacon_tasklet(unsigned long data)
295{ 312{
296 struct ath_softc *sc = (struct ath_softc *)data; 313 struct ath_softc *sc = (struct ath_softc *)data;
@@ -336,6 +353,10 @@ void ath9k_beacon_tasklet(unsigned long data)
336 return; 353 return;
337 } 354 }
338 355
356 /* EDMA devices check that in the tx completion function. */
357 if (!edma && ath9k_csa_is_finished(sc))
358 return;
359
339 slot = ath9k_beacon_choose_slot(sc); 360 slot = ath9k_beacon_choose_slot(sc);
340 vif = sc->beacon.bslot[slot]; 361 vif = sc->beacon.bslot[slot];
341 362
diff --git a/drivers/net/wireless/ath/ath9k/init.c b/drivers/net/wireless/ath/ath9k/init.c
index 60bb4d6f1d82..abf1eb5d97ad 100644
--- a/drivers/net/wireless/ath/ath9k/init.c
+++ b/drivers/net/wireless/ath/ath9k/init.c
@@ -861,6 +861,7 @@ void ath9k_set_hw_capab(struct ath_softc *sc, struct ieee80211_hw *hw)
861 hw->wiphy->flags |= WIPHY_FLAG_SUPPORTS_TDLS; 861 hw->wiphy->flags |= WIPHY_FLAG_SUPPORTS_TDLS;
862 hw->wiphy->flags |= WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL; 862 hw->wiphy->flags |= WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL;
863 hw->wiphy->flags |= WIPHY_FLAG_SUPPORTS_5_10_MHZ; 863 hw->wiphy->flags |= WIPHY_FLAG_SUPPORTS_5_10_MHZ;
864 hw->wiphy->flags |= WIPHY_FLAG_HAS_CHANNEL_SWITCH;
864 865
865#ifdef CONFIG_PM_SLEEP 866#ifdef CONFIG_PM_SLEEP
866 if ((ah->caps.hw_caps & ATH9K_HW_WOW_DEVICE_CAPABLE) && 867 if ((ah->caps.hw_caps & ATH9K_HW_WOW_DEVICE_CAPABLE) &&
diff --git a/drivers/net/wireless/ath/ath9k/main.c b/drivers/net/wireless/ath/ath9k/main.c
index ba382a8c8b9a..ac9f18fa0729 100644
--- a/drivers/net/wireless/ath/ath9k/main.c
+++ b/drivers/net/wireless/ath/ath9k/main.c
@@ -1032,6 +1032,9 @@ static void ath9k_remove_interface(struct ieee80211_hw *hw,
1032 if (ath9k_uses_beacons(vif->type)) 1032 if (ath9k_uses_beacons(vif->type))
1033 ath9k_beacon_remove_slot(sc, vif); 1033 ath9k_beacon_remove_slot(sc, vif);
1034 1034
1035 if (sc->csa_vif == vif)
1036 sc->csa_vif = NULL;
1037
1035 ath9k_ps_wakeup(sc); 1038 ath9k_ps_wakeup(sc);
1036 ath9k_calculate_summary_state(hw, NULL); 1039 ath9k_calculate_summary_state(hw, NULL);
1037 ath9k_ps_restore(sc); 1040 ath9k_ps_restore(sc);
@@ -2318,6 +2321,19 @@ static void ath9k_sw_scan_complete(struct ieee80211_hw *hw)
2318 clear_bit(SC_OP_SCANNING, &sc->sc_flags); 2321 clear_bit(SC_OP_SCANNING, &sc->sc_flags);
2319} 2322}
2320 2323
2324static void ath9k_channel_switch_beacon(struct ieee80211_hw *hw,
2325 struct ieee80211_vif *vif,
2326 struct cfg80211_chan_def *chandef)
2327{
2328 struct ath_softc *sc = hw->priv;
2329
2330 /* mac80211 does not support CSA in multi-if cases (yet) */
2331 if (WARN_ON(sc->csa_vif))
2332 return;
2333
2334 sc->csa_vif = vif;
2335}
2336
2321struct ieee80211_ops ath9k_ops = { 2337struct ieee80211_ops ath9k_ops = {
2322 .tx = ath9k_tx, 2338 .tx = ath9k_tx,
2323 .start = ath9k_start, 2339 .start = ath9k_start,
@@ -2365,4 +2381,5 @@ struct ieee80211_ops ath9k_ops = {
2365#endif 2381#endif
2366 .sw_scan_start = ath9k_sw_scan_start, 2382 .sw_scan_start = ath9k_sw_scan_start,
2367 .sw_scan_complete = ath9k_sw_scan_complete, 2383 .sw_scan_complete = ath9k_sw_scan_complete,
2384 .channel_switch_beacon = ath9k_channel_switch_beacon,
2368}; 2385};
diff --git a/drivers/net/wireless/ath/ath9k/xmit.c b/drivers/net/wireless/ath/ath9k/xmit.c
index 7223e303f3a1..35b515fe3ffa 100644
--- a/drivers/net/wireless/ath/ath9k/xmit.c
+++ b/drivers/net/wireless/ath/ath9k/xmit.c
@@ -2559,6 +2559,8 @@ void ath_tx_edma_tasklet(struct ath_softc *sc)
2559 if (ts.qid == sc->beacon.beaconq) { 2559 if (ts.qid == sc->beacon.beaconq) {
2560 sc->beacon.tx_processed = true; 2560 sc->beacon.tx_processed = true;
2561 sc->beacon.tx_last = !(ts.ts_status & ATH9K_TXERR_MASK); 2561 sc->beacon.tx_last = !(ts.ts_status & ATH9K_TXERR_MASK);
2562
2563 ath9k_csa_is_finished(sc);
2562 continue; 2564 continue;
2563 } 2565 }
2564 2566