diff options
Diffstat (limited to 'drivers/net')
-rw-r--r-- | drivers/net/wireless/ath9k/ath9k.h | 2 | ||||
-rw-r--r-- | drivers/net/wireless/ath9k/main.c | 35 | ||||
-rw-r--r-- | drivers/net/wireless/ath9k/virtual.c | 41 |
3 files changed, 68 insertions, 10 deletions
diff --git a/drivers/net/wireless/ath9k/ath9k.h b/drivers/net/wireless/ath9k/ath9k.h index 4fc054e4354f..983f53daa1cc 100644 --- a/drivers/net/wireless/ath9k/ath9k.h +++ b/drivers/net/wireless/ath9k/ath9k.h | |||
@@ -633,6 +633,7 @@ struct ath_wiphy { | |||
633 | ATH_WIPHY_ACTIVE, | 633 | ATH_WIPHY_ACTIVE, |
634 | ATH_WIPHY_PAUSING, | 634 | ATH_WIPHY_PAUSING, |
635 | ATH_WIPHY_PAUSED, | 635 | ATH_WIPHY_PAUSED, |
636 | ATH_WIPHY_SCAN, | ||
636 | } state; | 637 | } state; |
637 | int chan_idx; | 638 | int chan_idx; |
638 | int chan_is_ht; | 639 | int chan_is_ht; |
@@ -716,5 +717,6 @@ void ath9k_wiphy_chan_work(struct work_struct *work); | |||
716 | bool ath9k_wiphy_started(struct ath_softc *sc); | 717 | bool ath9k_wiphy_started(struct ath_softc *sc); |
717 | void ath9k_wiphy_pause_all_forced(struct ath_softc *sc, | 718 | void ath9k_wiphy_pause_all_forced(struct ath_softc *sc, |
718 | struct ath_wiphy *selected); | 719 | struct ath_wiphy *selected); |
720 | bool ath9k_wiphy_scanning(struct ath_softc *sc); | ||
719 | 721 | ||
720 | #endif /* ATH9K_H */ | 722 | #endif /* ATH9K_H */ |
diff --git a/drivers/net/wireless/ath9k/main.c b/drivers/net/wireless/ath9k/main.c index bb6e1ddb4a57..626392241d43 100644 --- a/drivers/net/wireless/ath9k/main.c +++ b/drivers/net/wireless/ath9k/main.c | |||
@@ -2077,7 +2077,7 @@ static int ath9k_tx(struct ieee80211_hw *hw, | |||
2077 | struct ath_tx_control txctl; | 2077 | struct ath_tx_control txctl; |
2078 | int hdrlen, padsize; | 2078 | int hdrlen, padsize; |
2079 | 2079 | ||
2080 | if (aphy->state != ATH_WIPHY_ACTIVE) { | 2080 | if (aphy->state != ATH_WIPHY_ACTIVE && aphy->state != ATH_WIPHY_SCAN) { |
2081 | printk(KERN_DEBUG "ath9k: %s: TX in unexpected wiphy state " | 2081 | printk(KERN_DEBUG "ath9k: %s: TX in unexpected wiphy state " |
2082 | "%d\n", wiphy_name(hw->wiphy), aphy->state); | 2082 | "%d\n", wiphy_name(hw->wiphy), aphy->state); |
2083 | goto exit; | 2083 | goto exit; |
@@ -2348,14 +2348,16 @@ static int ath9k_config(struct ieee80211_hw *hw, u32 changed) | |||
2348 | aphy->chan_idx = pos; | 2348 | aphy->chan_idx = pos; |
2349 | aphy->chan_is_ht = conf_is_ht(conf); | 2349 | aphy->chan_is_ht = conf_is_ht(conf); |
2350 | 2350 | ||
2351 | /* TODO: do not change operation channel immediately if there | 2351 | if (aphy->state == ATH_WIPHY_SCAN || |
2352 | * are other virtual wiphys that use another channel. For now, | 2352 | aphy->state == ATH_WIPHY_ACTIVE) |
2353 | * we do the change immediately to allow mac80211-operated scan | 2353 | ath9k_wiphy_pause_all_forced(sc, aphy); |
2354 | * to work. Once the scan operation is moved into ath9k, we can | 2354 | else { |
2355 | * just move the current aphy in PAUSED state if the channel is | 2355 | /* |
2356 | * changed into something different from the current operation | 2356 | * Do not change operational channel based on a paused |
2357 | * channel. */ | 2357 | * wiphy changes. |
2358 | ath9k_wiphy_pause_all_forced(sc, aphy); | 2358 | */ |
2359 | goto skip_chan_change; | ||
2360 | } | ||
2359 | 2361 | ||
2360 | DPRINTF(sc, ATH_DBG_CONFIG, "Set channel: %d MHz\n", | 2362 | DPRINTF(sc, ATH_DBG_CONFIG, "Set channel: %d MHz\n", |
2361 | curchan->center_freq); | 2363 | curchan->center_freq); |
@@ -2372,6 +2374,7 @@ static int ath9k_config(struct ieee80211_hw *hw, u32 changed) | |||
2372 | } | 2374 | } |
2373 | } | 2375 | } |
2374 | 2376 | ||
2377 | skip_chan_change: | ||
2375 | if (changed & IEEE80211_CONF_CHANGE_POWER) | 2378 | if (changed & IEEE80211_CONF_CHANGE_POWER) |
2376 | sc->config.txpowlimit = 2 * conf->power_level; | 2379 | sc->config.txpowlimit = 2 * conf->power_level; |
2377 | 2380 | ||
@@ -2731,6 +2734,19 @@ static void ath9k_sw_scan_start(struct ieee80211_hw *hw) | |||
2731 | struct ath_wiphy *aphy = hw->priv; | 2734 | struct ath_wiphy *aphy = hw->priv; |
2732 | struct ath_softc *sc = aphy->sc; | 2735 | struct ath_softc *sc = aphy->sc; |
2733 | 2736 | ||
2737 | if (ath9k_wiphy_scanning(sc)) { | ||
2738 | printk(KERN_DEBUG "ath9k: Two wiphys trying to scan at the " | ||
2739 | "same time\n"); | ||
2740 | /* | ||
2741 | * Do not allow the concurrent scanning state for now. This | ||
2742 | * could be improved with scanning control moved into ath9k. | ||
2743 | */ | ||
2744 | return; | ||
2745 | } | ||
2746 | |||
2747 | aphy->state = ATH_WIPHY_SCAN; | ||
2748 | ath9k_wiphy_pause_all_forced(sc, aphy); | ||
2749 | |||
2734 | mutex_lock(&sc->mutex); | 2750 | mutex_lock(&sc->mutex); |
2735 | sc->sc_flags |= SC_OP_SCANNING; | 2751 | sc->sc_flags |= SC_OP_SCANNING; |
2736 | mutex_unlock(&sc->mutex); | 2752 | mutex_unlock(&sc->mutex); |
@@ -2742,6 +2758,7 @@ static void ath9k_sw_scan_complete(struct ieee80211_hw *hw) | |||
2742 | struct ath_softc *sc = aphy->sc; | 2758 | struct ath_softc *sc = aphy->sc; |
2743 | 2759 | ||
2744 | mutex_lock(&sc->mutex); | 2760 | mutex_lock(&sc->mutex); |
2761 | aphy->state = ATH_WIPHY_ACTIVE; | ||
2745 | sc->sc_flags &= ~SC_OP_SCANNING; | 2762 | sc->sc_flags &= ~SC_OP_SCANNING; |
2746 | mutex_unlock(&sc->mutex); | 2763 | mutex_unlock(&sc->mutex); |
2747 | } | 2764 | } |
diff --git a/drivers/net/wireless/ath9k/virtual.c b/drivers/net/wireless/ath9k/virtual.c index 913d2043d23e..2b545319408d 100644 --- a/drivers/net/wireless/ath9k/virtual.c +++ b/drivers/net/wireless/ath9k/virtual.c | |||
@@ -244,6 +244,28 @@ static bool ath9k_wiphy_pausing(struct ath_softc *sc) | |||
244 | return ret; | 244 | return ret; |
245 | } | 245 | } |
246 | 246 | ||
247 | static bool __ath9k_wiphy_scanning(struct ath_softc *sc) | ||
248 | { | ||
249 | int i; | ||
250 | if (sc->pri_wiphy->state == ATH_WIPHY_SCAN) | ||
251 | return true; | ||
252 | for (i = 0; i < sc->num_sec_wiphy; i++) { | ||
253 | if (sc->sec_wiphy[i] && | ||
254 | sc->sec_wiphy[i]->state == ATH_WIPHY_SCAN) | ||
255 | return true; | ||
256 | } | ||
257 | return false; | ||
258 | } | ||
259 | |||
260 | bool ath9k_wiphy_scanning(struct ath_softc *sc) | ||
261 | { | ||
262 | bool ret; | ||
263 | spin_lock_bh(&sc->wiphy_lock); | ||
264 | ret = __ath9k_wiphy_scanning(sc); | ||
265 | spin_unlock_bh(&sc->wiphy_lock); | ||
266 | return ret; | ||
267 | } | ||
268 | |||
247 | static int __ath9k_wiphy_unpause(struct ath_wiphy *aphy); | 269 | static int __ath9k_wiphy_unpause(struct ath_wiphy *aphy); |
248 | 270 | ||
249 | /* caller must hold wiphy_lock */ | 271 | /* caller must hold wiphy_lock */ |
@@ -463,6 +485,16 @@ int ath9k_wiphy_select(struct ath_wiphy *aphy) | |||
463 | bool now; | 485 | bool now; |
464 | 486 | ||
465 | spin_lock_bh(&sc->wiphy_lock); | 487 | spin_lock_bh(&sc->wiphy_lock); |
488 | if (__ath9k_wiphy_scanning(sc)) { | ||
489 | /* | ||
490 | * For now, we are using mac80211 sw scan and it expects to | ||
491 | * have full control over channel changes, so avoid wiphy | ||
492 | * scheduling during a scan. This could be optimized if the | ||
493 | * scanning control were moved into the driver. | ||
494 | */ | ||
495 | spin_unlock_bh(&sc->wiphy_lock); | ||
496 | return -EBUSY; | ||
497 | } | ||
466 | if (__ath9k_wiphy_pausing(sc)) { | 498 | if (__ath9k_wiphy_pausing(sc)) { |
467 | if (sc->wiphy_select_failures == 0) | 499 | if (sc->wiphy_select_failures == 0) |
468 | sc->wiphy_select_first_fail = jiffies; | 500 | sc->wiphy_select_first_fail = jiffies; |
@@ -537,7 +569,14 @@ bool ath9k_wiphy_started(struct ath_softc *sc) | |||
537 | static void ath9k_wiphy_pause_chan(struct ath_wiphy *aphy, | 569 | static void ath9k_wiphy_pause_chan(struct ath_wiphy *aphy, |
538 | struct ath_wiphy *selected) | 570 | struct ath_wiphy *selected) |
539 | { | 571 | { |
540 | if (aphy->chan_idx == selected->chan_idx) | 572 | if (selected->state == ATH_WIPHY_SCAN) { |
573 | if (aphy == selected) | ||
574 | return; | ||
575 | /* | ||
576 | * Pause all other wiphys for the duration of the scan even if | ||
577 | * they are on the current channel now. | ||
578 | */ | ||
579 | } else if (aphy->chan_idx == selected->chan_idx) | ||
541 | return; | 580 | return; |
542 | aphy->state = ATH_WIPHY_PAUSED; | 581 | aphy->state = ATH_WIPHY_PAUSED; |
543 | ieee80211_stop_queues(aphy->hw); | 582 | ieee80211_stop_queues(aphy->hw); |