diff options
author | Felix Fietkau <nbd@openwrt.org> | 2011-01-24 13:23:16 -0500 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2011-01-28 15:41:59 -0500 |
commit | 7545daf498c43e548506212310e6c75382d2731d (patch) | |
tree | ee200bd829e29e41875c2576792c186bdde88264 | |
parent | 34302397e5b980ce561366b63504e9d82948e8b8 (diff) |
ath9k: remove support for virtual wiphys
Signed-off-by: Felix Fietkau <nbd@openwrt.org>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
-rw-r--r-- | drivers/net/wireless/ath/ath9k/Makefile | 1 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ath9k/ahb.c | 1 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ath9k/ath9k.h | 41 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ath9k/beacon.c | 9 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ath9k/init.c | 19 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ath9k/main.c | 141 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ath9k/pci.c | 2 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ath9k/recv.c | 63 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ath9k/virtual.c | 669 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ath9k/xmit.c | 28 |
10 files changed, 23 insertions, 951 deletions
diff --git a/drivers/net/wireless/ath/ath9k/Makefile b/drivers/net/wireless/ath/ath9k/Makefile index aca01621c205..4d66ca8042eb 100644 --- a/drivers/net/wireless/ath/ath9k/Makefile +++ b/drivers/net/wireless/ath/ath9k/Makefile | |||
@@ -4,7 +4,6 @@ ath9k-y += beacon.o \ | |||
4 | main.o \ | 4 | main.o \ |
5 | recv.o \ | 5 | recv.o \ |
6 | xmit.o \ | 6 | xmit.o \ |
7 | virtual.o \ | ||
8 | 7 | ||
9 | ath9k-$(CONFIG_ATH9K_RATE_CONTROL) += rc.o | 8 | ath9k-$(CONFIG_ATH9K_RATE_CONTROL) += rc.o |
10 | ath9k-$(CONFIG_PCI) += pci.o | 9 | ath9k-$(CONFIG_PCI) += pci.o |
diff --git a/drivers/net/wireless/ath/ath9k/ahb.c b/drivers/net/wireless/ath/ath9k/ahb.c index 25a6e4417cdb..72f430e956ec 100644 --- a/drivers/net/wireless/ath/ath9k/ahb.c +++ b/drivers/net/wireless/ath/ath9k/ahb.c | |||
@@ -107,7 +107,6 @@ static int ath_ahb_probe(struct platform_device *pdev) | |||
107 | sc = (struct ath_softc *) (aphy + 1); | 107 | sc = (struct ath_softc *) (aphy + 1); |
108 | aphy->sc = sc; | 108 | aphy->sc = sc; |
109 | aphy->hw = hw; | 109 | aphy->hw = hw; |
110 | sc->pri_wiphy = aphy; | ||
111 | sc->hw = hw; | 110 | sc->hw = hw; |
112 | sc->dev = &pdev->dev; | 111 | sc->dev = &pdev->dev; |
113 | sc->mem = mem; | 112 | sc->mem = mem; |
diff --git a/drivers/net/wireless/ath/ath9k/ath9k.h b/drivers/net/wireless/ath/ath9k/ath9k.h index 6636f3c6dcf9..6204f7b46f43 100644 --- a/drivers/net/wireless/ath/ath9k/ath9k.h +++ b/drivers/net/wireless/ath/ath9k/ath9k.h | |||
@@ -388,7 +388,6 @@ struct ath_beacon { | |||
388 | u32 ast_be_xmit; | 388 | u32 ast_be_xmit; |
389 | u64 bc_tstamp; | 389 | u64 bc_tstamp; |
390 | struct ieee80211_vif *bslot[ATH_BCBUF]; | 390 | struct ieee80211_vif *bslot[ATH_BCBUF]; |
391 | struct ath_wiphy *bslot_aphy[ATH_BCBUF]; | ||
392 | int slottime; | 391 | int slottime; |
393 | int slotupdate; | 392 | int slotupdate; |
394 | struct ath9k_tx_queue_info beacon_qi; | 393 | struct ath9k_tx_queue_info beacon_qi; |
@@ -585,20 +584,8 @@ struct ath_softc { | |||
585 | struct ieee80211_hw *hw; | 584 | struct ieee80211_hw *hw; |
586 | struct device *dev; | 585 | struct device *dev; |
587 | 586 | ||
588 | spinlock_t wiphy_lock; /* spinlock to protect ath_wiphy data */ | ||
589 | struct ath_wiphy *pri_wiphy; | ||
590 | struct ath_wiphy **sec_wiphy; /* secondary wiphys (virtual radios); may | ||
591 | * have NULL entries */ | ||
592 | int num_sec_wiphy; /* number of sec_wiphy pointers in the array */ | ||
593 | int chan_idx; | 587 | int chan_idx; |
594 | int chan_is_ht; | 588 | int chan_is_ht; |
595 | struct ath_wiphy *next_wiphy; | ||
596 | struct work_struct chan_work; | ||
597 | int wiphy_select_failures; | ||
598 | unsigned long wiphy_select_first_fail; | ||
599 | struct delayed_work wiphy_work; | ||
600 | unsigned long wiphy_scheduler_int; | ||
601 | int wiphy_scheduler_index; | ||
602 | struct survey_info *cur_survey; | 589 | struct survey_info *cur_survey; |
603 | struct survey_info survey[ATH9K_NUM_CHANNELS]; | 590 | struct survey_info survey[ATH9K_NUM_CHANNELS]; |
604 | 591 | ||
@@ -665,16 +652,6 @@ struct ath_wiphy { | |||
665 | struct ath_softc *sc; /* shared for all virtual wiphys */ | 652 | struct ath_softc *sc; /* shared for all virtual wiphys */ |
666 | struct ieee80211_hw *hw; | 653 | struct ieee80211_hw *hw; |
667 | struct ath9k_hw_cal_data caldata; | 654 | struct ath9k_hw_cal_data caldata; |
668 | enum ath_wiphy_state { | ||
669 | ATH_WIPHY_INACTIVE, | ||
670 | ATH_WIPHY_ACTIVE, | ||
671 | ATH_WIPHY_PAUSING, | ||
672 | ATH_WIPHY_PAUSED, | ||
673 | ATH_WIPHY_SCAN, | ||
674 | } state; | ||
675 | bool idle; | ||
676 | int chan_idx; | ||
677 | int chan_is_ht; | ||
678 | int last_rssi; | 655 | int last_rssi; |
679 | }; | 656 | }; |
680 | 657 | ||
@@ -731,24 +708,6 @@ void ath9k_ps_restore(struct ath_softc *sc); | |||
731 | u8 ath_txchainmask_reduction(struct ath_softc *sc, u8 chainmask, u32 rate); | 708 | u8 ath_txchainmask_reduction(struct ath_softc *sc, u8 chainmask, u32 rate); |
732 | 709 | ||
733 | void ath9k_set_bssid_mask(struct ieee80211_hw *hw, struct ieee80211_vif *vif); | 710 | void ath9k_set_bssid_mask(struct ieee80211_hw *hw, struct ieee80211_vif *vif); |
734 | int ath9k_wiphy_add(struct ath_softc *sc); | ||
735 | int ath9k_wiphy_del(struct ath_wiphy *aphy); | ||
736 | void ath9k_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb, int ftype); | ||
737 | int ath9k_wiphy_pause(struct ath_wiphy *aphy); | ||
738 | int ath9k_wiphy_unpause(struct ath_wiphy *aphy); | ||
739 | int ath9k_wiphy_select(struct ath_wiphy *aphy); | ||
740 | void ath9k_wiphy_set_scheduler(struct ath_softc *sc, unsigned int msec_int); | ||
741 | void ath9k_wiphy_chan_work(struct work_struct *work); | ||
742 | bool ath9k_wiphy_started(struct ath_softc *sc); | ||
743 | void ath9k_wiphy_pause_all_forced(struct ath_softc *sc, | ||
744 | struct ath_wiphy *selected); | ||
745 | bool ath9k_wiphy_scanning(struct ath_softc *sc); | ||
746 | void ath9k_wiphy_work(struct work_struct *work); | ||
747 | bool ath9k_all_wiphys_idle(struct ath_softc *sc); | ||
748 | void ath9k_set_wiphy_idle(struct ath_wiphy *aphy, bool idle); | ||
749 | |||
750 | void ath_mac80211_stop_queue(struct ath_softc *sc, u16 skb_queue); | ||
751 | bool ath_mac80211_start_queue(struct ath_softc *sc, u16 skb_queue); | ||
752 | 711 | ||
753 | void ath_start_rfkill_poll(struct ath_softc *sc); | 712 | void ath_start_rfkill_poll(struct ath_softc *sc); |
754 | extern void ath9k_rfkill_poll_state(struct ieee80211_hw *hw); | 713 | extern void ath9k_rfkill_poll_state(struct ieee80211_hw *hw); |
diff --git a/drivers/net/wireless/ath/ath9k/beacon.c b/drivers/net/wireless/ath/ath9k/beacon.c index ab8c05cf62f3..77c8e70db0a0 100644 --- a/drivers/net/wireless/ath/ath9k/beacon.c +++ b/drivers/net/wireless/ath/ath9k/beacon.c | |||
@@ -142,9 +142,6 @@ static struct ath_buf *ath_beacon_generate(struct ieee80211_hw *hw, | |||
142 | struct ieee80211_tx_info *info; | 142 | struct ieee80211_tx_info *info; |
143 | int cabq_depth; | 143 | int cabq_depth; |
144 | 144 | ||
145 | if (aphy->state != ATH_WIPHY_ACTIVE) | ||
146 | return NULL; | ||
147 | |||
148 | avp = (void *)vif->drv_priv; | 145 | avp = (void *)vif->drv_priv; |
149 | cabq = sc->beacon.cabq; | 146 | cabq = sc->beacon.cabq; |
150 | 147 | ||
@@ -261,7 +258,6 @@ int ath_beacon_alloc(struct ath_wiphy *aphy, struct ieee80211_vif *vif) | |||
261 | } | 258 | } |
262 | BUG_ON(sc->beacon.bslot[avp->av_bslot] != NULL); | 259 | BUG_ON(sc->beacon.bslot[avp->av_bslot] != NULL); |
263 | sc->beacon.bslot[avp->av_bslot] = vif; | 260 | sc->beacon.bslot[avp->av_bslot] = vif; |
264 | sc->beacon.bslot_aphy[avp->av_bslot] = aphy; | ||
265 | sc->nbcnvifs++; | 261 | sc->nbcnvifs++; |
266 | } | 262 | } |
267 | } | 263 | } |
@@ -332,7 +328,6 @@ void ath_beacon_return(struct ath_softc *sc, struct ath_vif *avp) | |||
332 | 328 | ||
333 | if (avp->av_bslot != -1) { | 329 | if (avp->av_bslot != -1) { |
334 | sc->beacon.bslot[avp->av_bslot] = NULL; | 330 | sc->beacon.bslot[avp->av_bslot] = NULL; |
335 | sc->beacon.bslot_aphy[avp->av_bslot] = NULL; | ||
336 | sc->nbcnvifs--; | 331 | sc->nbcnvifs--; |
337 | } | 332 | } |
338 | 333 | ||
@@ -358,7 +353,6 @@ void ath_beacon_tasklet(unsigned long data) | |||
358 | struct ath_common *common = ath9k_hw_common(ah); | 353 | struct ath_common *common = ath9k_hw_common(ah); |
359 | struct ath_buf *bf = NULL; | 354 | struct ath_buf *bf = NULL; |
360 | struct ieee80211_vif *vif; | 355 | struct ieee80211_vif *vif; |
361 | struct ath_wiphy *aphy; | ||
362 | int slot; | 356 | int slot; |
363 | u32 bfaddr, bc = 0, tsftu; | 357 | u32 bfaddr, bc = 0, tsftu; |
364 | u64 tsf; | 358 | u64 tsf; |
@@ -416,7 +410,6 @@ void ath_beacon_tasklet(unsigned long data) | |||
416 | */ | 410 | */ |
417 | slot = ATH_BCBUF - slot - 1; | 411 | slot = ATH_BCBUF - slot - 1; |
418 | vif = sc->beacon.bslot[slot]; | 412 | vif = sc->beacon.bslot[slot]; |
419 | aphy = sc->beacon.bslot_aphy[slot]; | ||
420 | 413 | ||
421 | ath_dbg(common, ATH_DBG_BEACON, | 414 | ath_dbg(common, ATH_DBG_BEACON, |
422 | "slot %d [tsf %llu tsftu %u intval %u] vif %p\n", | 415 | "slot %d [tsf %llu tsftu %u intval %u] vif %p\n", |
@@ -424,7 +417,7 @@ void ath_beacon_tasklet(unsigned long data) | |||
424 | 417 | ||
425 | bfaddr = 0; | 418 | bfaddr = 0; |
426 | if (vif) { | 419 | if (vif) { |
427 | bf = ath_beacon_generate(aphy->hw, vif); | 420 | bf = ath_beacon_generate(sc->hw, vif); |
428 | if (bf != NULL) { | 421 | if (bf != NULL) { |
429 | bfaddr = bf->bf_daddr; | 422 | bfaddr = bf->bf_daddr; |
430 | bc = 1; | 423 | bc = 1; |
diff --git a/drivers/net/wireless/ath/ath9k/init.c b/drivers/net/wireless/ath/ath9k/init.c index 5279653c90c7..88ff39940e92 100644 --- a/drivers/net/wireless/ath/ath9k/init.c +++ b/drivers/net/wireless/ath/ath9k/init.c | |||
@@ -517,10 +517,8 @@ static void ath9k_init_misc(struct ath_softc *sc) | |||
517 | 517 | ||
518 | sc->beacon.slottime = ATH9K_SLOT_TIME_9; | 518 | sc->beacon.slottime = ATH9K_SLOT_TIME_9; |
519 | 519 | ||
520 | for (i = 0; i < ARRAY_SIZE(sc->beacon.bslot); i++) { | 520 | for (i = 0; i < ARRAY_SIZE(sc->beacon.bslot); i++) |
521 | sc->beacon.bslot[i] = NULL; | 521 | sc->beacon.bslot[i] = NULL; |
522 | sc->beacon.bslot_aphy[i] = NULL; | ||
523 | } | ||
524 | 522 | ||
525 | if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_ANT_DIV_COMB) | 523 | if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_ANT_DIV_COMB) |
526 | sc->ant_comb.count = ATH_ANT_DIV_COMB_INIT_COUNT; | 524 | sc->ant_comb.count = ATH_ANT_DIV_COMB_INIT_COUNT; |
@@ -556,7 +554,6 @@ static int ath9k_init_softc(u16 devid, struct ath_softc *sc, u16 subsysid, | |||
556 | common->btcoex_enabled = ath9k_btcoex_enable == 1; | 554 | common->btcoex_enabled = ath9k_btcoex_enable == 1; |
557 | spin_lock_init(&common->cc_lock); | 555 | spin_lock_init(&common->cc_lock); |
558 | 556 | ||
559 | spin_lock_init(&sc->wiphy_lock); | ||
560 | spin_lock_init(&sc->sc_serial_rw); | 557 | spin_lock_init(&sc->sc_serial_rw); |
561 | spin_lock_init(&sc->sc_pm_lock); | 558 | spin_lock_init(&sc->sc_pm_lock); |
562 | mutex_init(&sc->mutex); | 559 | mutex_init(&sc->mutex); |
@@ -762,9 +759,6 @@ int ath9k_init_device(u16 devid, struct ath_softc *sc, u16 subsysid, | |||
762 | 759 | ||
763 | INIT_WORK(&sc->hw_check_work, ath_hw_check); | 760 | INIT_WORK(&sc->hw_check_work, ath_hw_check); |
764 | INIT_WORK(&sc->paprd_work, ath_paprd_calibrate); | 761 | INIT_WORK(&sc->paprd_work, ath_paprd_calibrate); |
765 | INIT_WORK(&sc->chan_work, ath9k_wiphy_chan_work); | ||
766 | INIT_DELAYED_WORK(&sc->wiphy_work, ath9k_wiphy_work); | ||
767 | sc->wiphy_scheduler_int = msecs_to_jiffies(500); | ||
768 | aphy->last_rssi = ATH_RSSI_DUMMY_MARKER; | 762 | aphy->last_rssi = ATH_RSSI_DUMMY_MARKER; |
769 | 763 | ||
770 | ath_init_leds(sc); | 764 | ath_init_leds(sc); |
@@ -823,28 +817,17 @@ static void ath9k_deinit_softc(struct ath_softc *sc) | |||
823 | void ath9k_deinit_device(struct ath_softc *sc) | 817 | void ath9k_deinit_device(struct ath_softc *sc) |
824 | { | 818 | { |
825 | struct ieee80211_hw *hw = sc->hw; | 819 | struct ieee80211_hw *hw = sc->hw; |
826 | int i = 0; | ||
827 | 820 | ||
828 | ath9k_ps_wakeup(sc); | 821 | ath9k_ps_wakeup(sc); |
829 | 822 | ||
830 | wiphy_rfkill_stop_polling(sc->hw->wiphy); | 823 | wiphy_rfkill_stop_polling(sc->hw->wiphy); |
831 | ath_deinit_leds(sc); | 824 | ath_deinit_leds(sc); |
832 | 825 | ||
833 | for (i = 0; i < sc->num_sec_wiphy; i++) { | ||
834 | struct ath_wiphy *aphy = sc->sec_wiphy[i]; | ||
835 | if (aphy == NULL) | ||
836 | continue; | ||
837 | sc->sec_wiphy[i] = NULL; | ||
838 | ieee80211_unregister_hw(aphy->hw); | ||
839 | ieee80211_free_hw(aphy->hw); | ||
840 | } | ||
841 | |||
842 | ieee80211_unregister_hw(hw); | 826 | ieee80211_unregister_hw(hw); |
843 | pm_qos_remove_request(&sc->pm_qos_req); | 827 | pm_qos_remove_request(&sc->pm_qos_req); |
844 | ath_rx_cleanup(sc); | 828 | ath_rx_cleanup(sc); |
845 | ath_tx_cleanup(sc); | 829 | ath_tx_cleanup(sc); |
846 | ath9k_deinit_softc(sc); | 830 | ath9k_deinit_softc(sc); |
847 | kfree(sc->sec_wiphy); | ||
848 | } | 831 | } |
849 | 832 | ||
850 | void ath_descdma_cleanup(struct ath_softc *sc, | 833 | void ath_descdma_cleanup(struct ath_softc *sc, |
diff --git a/drivers/net/wireless/ath/ath9k/main.c b/drivers/net/wireless/ath/ath9k/main.c index 2b27c81b06c8..2d9951080864 100644 --- a/drivers/net/wireless/ath/ath9k/main.c +++ b/drivers/net/wireless/ath/ath9k/main.c | |||
@@ -1089,29 +1089,7 @@ static int ath9k_start(struct ieee80211_hw *hw) | |||
1089 | 1089 | ||
1090 | mutex_lock(&sc->mutex); | 1090 | mutex_lock(&sc->mutex); |
1091 | 1091 | ||
1092 | if (ath9k_wiphy_started(sc)) { | ||
1093 | if (sc->chan_idx == curchan->hw_value) { | ||
1094 | /* | ||
1095 | * Already on the operational channel, the new wiphy | ||
1096 | * can be marked active. | ||
1097 | */ | ||
1098 | aphy->state = ATH_WIPHY_ACTIVE; | ||
1099 | ieee80211_wake_queues(hw); | ||
1100 | } else { | ||
1101 | /* | ||
1102 | * Another wiphy is on another channel, start the new | ||
1103 | * wiphy in paused state. | ||
1104 | */ | ||
1105 | aphy->state = ATH_WIPHY_PAUSED; | ||
1106 | ieee80211_stop_queues(hw); | ||
1107 | } | ||
1108 | mutex_unlock(&sc->mutex); | ||
1109 | return 0; | ||
1110 | } | ||
1111 | aphy->state = ATH_WIPHY_ACTIVE; | ||
1112 | |||
1113 | /* setup initial channel */ | 1092 | /* setup initial channel */ |
1114 | |||
1115 | sc->chan_idx = curchan->hw_value; | 1093 | sc->chan_idx = curchan->hw_value; |
1116 | 1094 | ||
1117 | init_channel = ath_get_curchannel(sc, hw); | 1095 | init_channel = ath_get_curchannel(sc, hw); |
@@ -1221,13 +1199,6 @@ static int ath9k_tx(struct ieee80211_hw *hw, | |||
1221 | struct ath_tx_control txctl; | 1199 | struct ath_tx_control txctl; |
1222 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; | 1200 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; |
1223 | 1201 | ||
1224 | if (aphy->state != ATH_WIPHY_ACTIVE && aphy->state != ATH_WIPHY_SCAN) { | ||
1225 | ath_dbg(common, ATH_DBG_XMIT, | ||
1226 | "ath9k: %s: TX in unexpected wiphy state %d\n", | ||
1227 | wiphy_name(hw->wiphy), aphy->state); | ||
1228 | goto exit; | ||
1229 | } | ||
1230 | |||
1231 | if (sc->ps_enabled) { | 1202 | if (sc->ps_enabled) { |
1232 | /* | 1203 | /* |
1233 | * mac80211 does not set PM field for normal data frames, so we | 1204 | * mac80211 does not set PM field for normal data frames, so we |
@@ -1290,12 +1261,9 @@ static void ath9k_stop(struct ieee80211_hw *hw) | |||
1290 | struct ath_softc *sc = aphy->sc; | 1261 | struct ath_softc *sc = aphy->sc; |
1291 | struct ath_hw *ah = sc->sc_ah; | 1262 | struct ath_hw *ah = sc->sc_ah; |
1292 | struct ath_common *common = ath9k_hw_common(ah); | 1263 | struct ath_common *common = ath9k_hw_common(ah); |
1293 | int i; | ||
1294 | 1264 | ||
1295 | mutex_lock(&sc->mutex); | 1265 | mutex_lock(&sc->mutex); |
1296 | 1266 | ||
1297 | aphy->state = ATH_WIPHY_INACTIVE; | ||
1298 | |||
1299 | if (led_blink) | 1267 | if (led_blink) |
1300 | cancel_delayed_work_sync(&sc->ath_led_blink_work); | 1268 | cancel_delayed_work_sync(&sc->ath_led_blink_work); |
1301 | 1269 | ||
@@ -1303,27 +1271,12 @@ static void ath9k_stop(struct ieee80211_hw *hw) | |||
1303 | cancel_work_sync(&sc->paprd_work); | 1271 | cancel_work_sync(&sc->paprd_work); |
1304 | cancel_work_sync(&sc->hw_check_work); | 1272 | cancel_work_sync(&sc->hw_check_work); |
1305 | 1273 | ||
1306 | for (i = 0; i < sc->num_sec_wiphy; i++) { | ||
1307 | if (sc->sec_wiphy[i]) | ||
1308 | break; | ||
1309 | } | ||
1310 | |||
1311 | if (i == sc->num_sec_wiphy) { | ||
1312 | cancel_delayed_work_sync(&sc->wiphy_work); | ||
1313 | cancel_work_sync(&sc->chan_work); | ||
1314 | } | ||
1315 | |||
1316 | if (sc->sc_flags & SC_OP_INVALID) { | 1274 | if (sc->sc_flags & SC_OP_INVALID) { |
1317 | ath_dbg(common, ATH_DBG_ANY, "Device not present\n"); | 1275 | ath_dbg(common, ATH_DBG_ANY, "Device not present\n"); |
1318 | mutex_unlock(&sc->mutex); | 1276 | mutex_unlock(&sc->mutex); |
1319 | return; | 1277 | return; |
1320 | } | 1278 | } |
1321 | 1279 | ||
1322 | if (ath9k_wiphy_started(sc)) { | ||
1323 | mutex_unlock(&sc->mutex); | ||
1324 | return; /* another wiphy still in use */ | ||
1325 | } | ||
1326 | |||
1327 | /* Ensure HW is awake when we try to shut it down. */ | 1280 | /* Ensure HW is awake when we try to shut it down. */ |
1328 | ath9k_ps_wakeup(sc); | 1281 | ath9k_ps_wakeup(sc); |
1329 | 1282 | ||
@@ -1355,7 +1308,6 @@ static void ath9k_stop(struct ieee80211_hw *hw) | |||
1355 | ath9k_ps_restore(sc); | 1308 | ath9k_ps_restore(sc); |
1356 | 1309 | ||
1357 | sc->ps_idle = true; | 1310 | sc->ps_idle = true; |
1358 | ath9k_set_wiphy_idle(aphy, true); | ||
1359 | ath_radio_disable(sc, hw); | 1311 | ath_radio_disable(sc, hw); |
1360 | 1312 | ||
1361 | sc->sc_flags |= SC_OP_INVALID; | 1313 | sc->sc_flags |= SC_OP_INVALID; |
@@ -1445,7 +1397,6 @@ void ath9k_calculate_iter_data(struct ieee80211_hw *hw, | |||
1445 | struct ath_softc *sc = aphy->sc; | 1397 | struct ath_softc *sc = aphy->sc; |
1446 | struct ath_hw *ah = sc->sc_ah; | 1398 | struct ath_hw *ah = sc->sc_ah; |
1447 | struct ath_common *common = ath9k_hw_common(ah); | 1399 | struct ath_common *common = ath9k_hw_common(ah); |
1448 | int i; | ||
1449 | 1400 | ||
1450 | /* | 1401 | /* |
1451 | * Use the hardware MAC address as reference, the hardware uses it | 1402 | * Use the hardware MAC address as reference, the hardware uses it |
@@ -1459,16 +1410,8 @@ void ath9k_calculate_iter_data(struct ieee80211_hw *hw, | |||
1459 | ath9k_vif_iter(iter_data, vif->addr, vif); | 1410 | ath9k_vif_iter(iter_data, vif->addr, vif); |
1460 | 1411 | ||
1461 | /* Get list of all active MAC addresses */ | 1412 | /* Get list of all active MAC addresses */ |
1462 | spin_lock_bh(&sc->wiphy_lock); | ||
1463 | ieee80211_iterate_active_interfaces_atomic(sc->hw, ath9k_vif_iter, | 1413 | ieee80211_iterate_active_interfaces_atomic(sc->hw, ath9k_vif_iter, |
1464 | iter_data); | 1414 | iter_data); |
1465 | for (i = 0; i < sc->num_sec_wiphy; i++) { | ||
1466 | if (sc->sec_wiphy[i] == NULL) | ||
1467 | continue; | ||
1468 | ieee80211_iterate_active_interfaces_atomic( | ||
1469 | sc->sec_wiphy[i]->hw, ath9k_vif_iter, iter_data); | ||
1470 | } | ||
1471 | spin_unlock_bh(&sc->wiphy_lock); | ||
1472 | } | 1415 | } |
1473 | 1416 | ||
1474 | /* Called with sc->mutex held. */ | 1417 | /* Called with sc->mutex held. */ |
@@ -1722,7 +1665,7 @@ static int ath9k_config(struct ieee80211_hw *hw, u32 changed) | |||
1722 | struct ath_hw *ah = sc->sc_ah; | 1665 | struct ath_hw *ah = sc->sc_ah; |
1723 | struct ath_common *common = ath9k_hw_common(ah); | 1666 | struct ath_common *common = ath9k_hw_common(ah); |
1724 | struct ieee80211_conf *conf = &hw->conf; | 1667 | struct ieee80211_conf *conf = &hw->conf; |
1725 | bool disable_radio; | 1668 | bool disable_radio = false; |
1726 | 1669 | ||
1727 | mutex_lock(&sc->mutex); | 1670 | mutex_lock(&sc->mutex); |
1728 | 1671 | ||
@@ -1733,29 +1676,13 @@ static int ath9k_config(struct ieee80211_hw *hw, u32 changed) | |||
1733 | * the end. | 1676 | * the end. |
1734 | */ | 1677 | */ |
1735 | if (changed & IEEE80211_CONF_CHANGE_IDLE) { | 1678 | if (changed & IEEE80211_CONF_CHANGE_IDLE) { |
1736 | bool enable_radio; | 1679 | sc->ps_idle = !!(conf->flags & IEEE80211_CONF_IDLE); |
1737 | bool all_wiphys_idle; | 1680 | if (!sc->ps_idle) { |
1738 | bool idle = !!(conf->flags & IEEE80211_CONF_IDLE); | ||
1739 | |||
1740 | spin_lock_bh(&sc->wiphy_lock); | ||
1741 | all_wiphys_idle = ath9k_all_wiphys_idle(sc); | ||
1742 | ath9k_set_wiphy_idle(aphy, idle); | ||
1743 | |||
1744 | enable_radio = (!idle && all_wiphys_idle); | ||
1745 | |||
1746 | /* | ||
1747 | * After we unlock here its possible another wiphy | ||
1748 | * can be re-renabled so to account for that we will | ||
1749 | * only disable the radio toward the end of this routine | ||
1750 | * if by then all wiphys are still idle. | ||
1751 | */ | ||
1752 | spin_unlock_bh(&sc->wiphy_lock); | ||
1753 | |||
1754 | if (enable_radio) { | ||
1755 | sc->ps_idle = false; | ||
1756 | ath_radio_enable(sc, hw); | 1681 | ath_radio_enable(sc, hw); |
1757 | ath_dbg(common, ATH_DBG_CONFIG, | 1682 | ath_dbg(common, ATH_DBG_CONFIG, |
1758 | "not-idle: enabling radio\n"); | 1683 | "not-idle: enabling radio\n"); |
1684 | } else { | ||
1685 | disable_radio = true; | ||
1759 | } | 1686 | } |
1760 | } | 1687 | } |
1761 | 1688 | ||
@@ -1796,24 +1723,11 @@ static int ath9k_config(struct ieee80211_hw *hw, u32 changed) | |||
1796 | if (ah->curchan) | 1723 | if (ah->curchan) |
1797 | old_pos = ah->curchan - &ah->channels[0]; | 1724 | old_pos = ah->curchan - &ah->channels[0]; |
1798 | 1725 | ||
1799 | aphy->chan_idx = pos; | ||
1800 | aphy->chan_is_ht = conf_is_ht(conf); | ||
1801 | if (hw->conf.flags & IEEE80211_CONF_OFFCHANNEL) | 1726 | if (hw->conf.flags & IEEE80211_CONF_OFFCHANNEL) |
1802 | sc->sc_flags |= SC_OP_OFFCHANNEL; | 1727 | sc->sc_flags |= SC_OP_OFFCHANNEL; |
1803 | else | 1728 | else |
1804 | sc->sc_flags &= ~SC_OP_OFFCHANNEL; | 1729 | sc->sc_flags &= ~SC_OP_OFFCHANNEL; |
1805 | 1730 | ||
1806 | if (aphy->state == ATH_WIPHY_SCAN || | ||
1807 | aphy->state == ATH_WIPHY_ACTIVE) | ||
1808 | ath9k_wiphy_pause_all_forced(sc, aphy); | ||
1809 | else { | ||
1810 | /* | ||
1811 | * Do not change operational channel based on a paused | ||
1812 | * wiphy changes. | ||
1813 | */ | ||
1814 | goto skip_chan_change; | ||
1815 | } | ||
1816 | |||
1817 | ath_dbg(common, ATH_DBG_CONFIG, "Set channel: %d MHz\n", | 1731 | ath_dbg(common, ATH_DBG_CONFIG, "Set channel: %d MHz\n", |
1818 | curchan->center_freq); | 1732 | curchan->center_freq); |
1819 | 1733 | ||
@@ -1860,19 +1774,13 @@ static int ath9k_config(struct ieee80211_hw *hw, u32 changed) | |||
1860 | ath_update_survey_nf(sc, old_pos); | 1774 | ath_update_survey_nf(sc, old_pos); |
1861 | } | 1775 | } |
1862 | 1776 | ||
1863 | skip_chan_change: | ||
1864 | if (changed & IEEE80211_CONF_CHANGE_POWER) { | 1777 | if (changed & IEEE80211_CONF_CHANGE_POWER) { |
1865 | sc->config.txpowlimit = 2 * conf->power_level; | 1778 | sc->config.txpowlimit = 2 * conf->power_level; |
1866 | ath_update_txpow(sc); | 1779 | ath_update_txpow(sc); |
1867 | } | 1780 | } |
1868 | 1781 | ||
1869 | spin_lock_bh(&sc->wiphy_lock); | ||
1870 | disable_radio = ath9k_all_wiphys_idle(sc); | ||
1871 | spin_unlock_bh(&sc->wiphy_lock); | ||
1872 | |||
1873 | if (disable_radio) { | 1782 | if (disable_radio) { |
1874 | ath_dbg(common, ATH_DBG_CONFIG, "idle: disabling radio\n"); | 1783 | ath_dbg(common, ATH_DBG_CONFIG, "idle: disabling radio\n"); |
1875 | sc->ps_idle = true; | ||
1876 | ath_radio_disable(sc, hw); | 1784 | ath_radio_disable(sc, hw); |
1877 | } | 1785 | } |
1878 | 1786 | ||
@@ -2263,43 +2171,6 @@ static int ath9k_get_survey(struct ieee80211_hw *hw, int idx, | |||
2263 | return 0; | 2171 | return 0; |
2264 | } | 2172 | } |
2265 | 2173 | ||
2266 | static void ath9k_sw_scan_start(struct ieee80211_hw *hw) | ||
2267 | { | ||
2268 | struct ath_wiphy *aphy = hw->priv; | ||
2269 | struct ath_softc *sc = aphy->sc; | ||
2270 | |||
2271 | mutex_lock(&sc->mutex); | ||
2272 | if (ath9k_wiphy_scanning(sc)) { | ||
2273 | /* | ||
2274 | * There is a race here in mac80211 but fixing it requires | ||
2275 | * we revisit how we handle the scan complete callback. | ||
2276 | * After mac80211 fixes we will not have configured hardware | ||
2277 | * to the home channel nor would we have configured the RX | ||
2278 | * filter yet. | ||
2279 | */ | ||
2280 | mutex_unlock(&sc->mutex); | ||
2281 | return; | ||
2282 | } | ||
2283 | |||
2284 | aphy->state = ATH_WIPHY_SCAN; | ||
2285 | ath9k_wiphy_pause_all_forced(sc, aphy); | ||
2286 | mutex_unlock(&sc->mutex); | ||
2287 | } | ||
2288 | |||
2289 | /* | ||
2290 | * XXX: this requires a revisit after the driver | ||
2291 | * scan_complete gets moved to another place/removed in mac80211. | ||
2292 | */ | ||
2293 | static void ath9k_sw_scan_complete(struct ieee80211_hw *hw) | ||
2294 | { | ||
2295 | struct ath_wiphy *aphy = hw->priv; | ||
2296 | struct ath_softc *sc = aphy->sc; | ||
2297 | |||
2298 | mutex_lock(&sc->mutex); | ||
2299 | aphy->state = ATH_WIPHY_ACTIVE; | ||
2300 | mutex_unlock(&sc->mutex); | ||
2301 | } | ||
2302 | |||
2303 | static void ath9k_set_coverage_class(struct ieee80211_hw *hw, u8 coverage_class) | 2174 | static void ath9k_set_coverage_class(struct ieee80211_hw *hw, u8 coverage_class) |
2304 | { | 2175 | { |
2305 | struct ath_wiphy *aphy = hw->priv; | 2176 | struct ath_wiphy *aphy = hw->priv; |
@@ -2331,8 +2202,6 @@ struct ieee80211_ops ath9k_ops = { | |||
2331 | .reset_tsf = ath9k_reset_tsf, | 2202 | .reset_tsf = ath9k_reset_tsf, |
2332 | .ampdu_action = ath9k_ampdu_action, | 2203 | .ampdu_action = ath9k_ampdu_action, |
2333 | .get_survey = ath9k_get_survey, | 2204 | .get_survey = ath9k_get_survey, |
2334 | .sw_scan_start = ath9k_sw_scan_start, | ||
2335 | .sw_scan_complete = ath9k_sw_scan_complete, | ||
2336 | .rfkill_poll = ath9k_rfkill_poll_state, | 2205 | .rfkill_poll = ath9k_rfkill_poll_state, |
2337 | .set_coverage_class = ath9k_set_coverage_class, | 2206 | .set_coverage_class = ath9k_set_coverage_class, |
2338 | }; | 2207 | }; |
diff --git a/drivers/net/wireless/ath/ath9k/pci.c b/drivers/net/wireless/ath/ath9k/pci.c index 78ef1f13386f..1f60b8c47d2f 100644 --- a/drivers/net/wireless/ath/ath9k/pci.c +++ b/drivers/net/wireless/ath/ath9k/pci.c | |||
@@ -213,7 +213,6 @@ static int ath_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id) | |||
213 | sc = (struct ath_softc *) (aphy + 1); | 213 | sc = (struct ath_softc *) (aphy + 1); |
214 | aphy->sc = sc; | 214 | aphy->sc = sc; |
215 | aphy->hw = hw; | 215 | aphy->hw = hw; |
216 | sc->pri_wiphy = aphy; | ||
217 | sc->hw = hw; | 216 | sc->hw = hw; |
218 | sc->dev = &pdev->dev; | 217 | sc->dev = &pdev->dev; |
219 | sc->mem = mem; | 218 | sc->mem = mem; |
@@ -320,7 +319,6 @@ static int ath_pci_resume(struct device *device) | |||
320 | ath9k_ps_restore(sc); | 319 | ath9k_ps_restore(sc); |
321 | 320 | ||
322 | sc->ps_idle = true; | 321 | sc->ps_idle = true; |
323 | ath9k_set_wiphy_idle(aphy, true); | ||
324 | ath_radio_disable(sc, hw); | 322 | ath_radio_disable(sc, hw); |
325 | 323 | ||
326 | return 0; | 324 | return 0; |
diff --git a/drivers/net/wireless/ath/ath9k/recv.c b/drivers/net/wireless/ath/ath9k/recv.c index 116f0582af24..c84a675c6912 100644 --- a/drivers/net/wireless/ath/ath9k/recv.c +++ b/drivers/net/wireless/ath/ath9k/recv.c | |||
@@ -34,27 +34,6 @@ static inline bool ath9k_check_auto_sleep(struct ath_softc *sc) | |||
34 | (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_AUTOSLEEP); | 34 | (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_AUTOSLEEP); |
35 | } | 35 | } |
36 | 36 | ||
37 | static struct ieee80211_hw * ath_get_virt_hw(struct ath_softc *sc, | ||
38 | struct ieee80211_hdr *hdr) | ||
39 | { | ||
40 | struct ieee80211_hw *hw = sc->pri_wiphy->hw; | ||
41 | int i; | ||
42 | |||
43 | spin_lock_bh(&sc->wiphy_lock); | ||
44 | for (i = 0; i < sc->num_sec_wiphy; i++) { | ||
45 | struct ath_wiphy *aphy = sc->sec_wiphy[i]; | ||
46 | if (aphy == NULL) | ||
47 | continue; | ||
48 | if (compare_ether_addr(hdr->addr1, aphy->hw->wiphy->perm_addr) | ||
49 | == 0) { | ||
50 | hw = aphy->hw; | ||
51 | break; | ||
52 | } | ||
53 | } | ||
54 | spin_unlock_bh(&sc->wiphy_lock); | ||
55 | return hw; | ||
56 | } | ||
57 | |||
58 | /* | 37 | /* |
59 | * Setup and link descriptors. | 38 | * Setup and link descriptors. |
60 | * | 39 | * |
@@ -463,8 +442,7 @@ u32 ath_calcrxfilter(struct ath_softc *sc) | |||
463 | if (conf_is_ht(&sc->hw->conf)) | 442 | if (conf_is_ht(&sc->hw->conf)) |
464 | rfilt |= ATH9K_RX_FILTER_COMP_BAR; | 443 | rfilt |= ATH9K_RX_FILTER_COMP_BAR; |
465 | 444 | ||
466 | if (sc->sec_wiphy || (sc->nvifs > 1) || | 445 | if (sc->nvifs > 1 || (sc->rx.rxfilter & FIF_OTHER_BSS)) { |
467 | (sc->rx.rxfilter & FIF_OTHER_BSS)) { | ||
468 | /* The following may also be needed for other older chips */ | 446 | /* The following may also be needed for other older chips */ |
469 | if (sc->sc_ah->hw_version.macVersion == AR_SREV_VERSION_9160) | 447 | if (sc->sc_ah->hw_version.macVersion == AR_SREV_VERSION_9160) |
470 | rfilt |= ATH9K_RX_FILTER_PROM; | 448 | rfilt |= ATH9K_RX_FILTER_PROM; |
@@ -668,37 +646,6 @@ static void ath_rx_ps(struct ath_softc *sc, struct sk_buff *skb) | |||
668 | } | 646 | } |
669 | } | 647 | } |
670 | 648 | ||
671 | static void ath_rx_send_to_mac80211(struct ieee80211_hw *hw, | ||
672 | struct ath_softc *sc, struct sk_buff *skb) | ||
673 | { | ||
674 | struct ieee80211_hdr *hdr; | ||
675 | |||
676 | hdr = (struct ieee80211_hdr *)skb->data; | ||
677 | |||
678 | /* Send the frame to mac80211 */ | ||
679 | if (is_multicast_ether_addr(hdr->addr1)) { | ||
680 | int i; | ||
681 | /* | ||
682 | * Deliver broadcast/multicast frames to all suitable | ||
683 | * virtual wiphys. | ||
684 | */ | ||
685 | /* TODO: filter based on channel configuration */ | ||
686 | for (i = 0; i < sc->num_sec_wiphy; i++) { | ||
687 | struct ath_wiphy *aphy = sc->sec_wiphy[i]; | ||
688 | struct sk_buff *nskb; | ||
689 | if (aphy == NULL) | ||
690 | continue; | ||
691 | nskb = skb_copy(skb, GFP_ATOMIC); | ||
692 | if (!nskb) | ||
693 | continue; | ||
694 | ieee80211_rx(aphy->hw, nskb); | ||
695 | } | ||
696 | ieee80211_rx(sc->hw, skb); | ||
697 | } else | ||
698 | /* Deliver unicast frames based on receiver address */ | ||
699 | ieee80211_rx(hw, skb); | ||
700 | } | ||
701 | |||
702 | static bool ath_edma_get_buffers(struct ath_softc *sc, | 649 | static bool ath_edma_get_buffers(struct ath_softc *sc, |
703 | enum ath9k_rx_qtype qtype) | 650 | enum ath9k_rx_qtype qtype) |
704 | { | 651 | { |
@@ -1644,7 +1591,7 @@ int ath_rx_tasklet(struct ath_softc *sc, int flush, bool hp) | |||
1644 | * virtual wiphy so to account for that we iterate over the active | 1591 | * virtual wiphy so to account for that we iterate over the active |
1645 | * wiphys and find the appropriate wiphy and therefore hw. | 1592 | * wiphys and find the appropriate wiphy and therefore hw. |
1646 | */ | 1593 | */ |
1647 | struct ieee80211_hw *hw = NULL; | 1594 | struct ieee80211_hw *hw = sc->hw; |
1648 | struct ieee80211_hdr *hdr; | 1595 | struct ieee80211_hdr *hdr; |
1649 | int retval; | 1596 | int retval; |
1650 | bool decrypt_error = false; | 1597 | bool decrypt_error = false; |
@@ -1689,8 +1636,6 @@ int ath_rx_tasklet(struct ath_softc *sc, int flush, bool hp) | |||
1689 | hdr = (struct ieee80211_hdr *) (skb->data + rx_status_len); | 1636 | hdr = (struct ieee80211_hdr *) (skb->data + rx_status_len); |
1690 | rxs = IEEE80211_SKB_RXCB(skb); | 1637 | rxs = IEEE80211_SKB_RXCB(skb); |
1691 | 1638 | ||
1692 | hw = ath_get_virt_hw(sc, hdr); | ||
1693 | |||
1694 | ath_debug_stat_rx(sc, &rs); | 1639 | ath_debug_stat_rx(sc, &rs); |
1695 | 1640 | ||
1696 | /* | 1641 | /* |
@@ -1748,7 +1693,7 @@ int ath_rx_tasklet(struct ath_softc *sc, int flush, bool hp) | |||
1748 | bf->bf_mpdu = NULL; | 1693 | bf->bf_mpdu = NULL; |
1749 | bf->bf_buf_addr = 0; | 1694 | bf->bf_buf_addr = 0; |
1750 | ath_err(common, "dma_mapping_error() on RX\n"); | 1695 | ath_err(common, "dma_mapping_error() on RX\n"); |
1751 | ath_rx_send_to_mac80211(hw, sc, skb); | 1696 | ieee80211_rx(hw, skb); |
1752 | break; | 1697 | break; |
1753 | } | 1698 | } |
1754 | 1699 | ||
@@ -1775,7 +1720,7 @@ int ath_rx_tasklet(struct ath_softc *sc, int flush, bool hp) | |||
1775 | if (ah->caps.hw_caps & ATH9K_HW_CAP_ANT_DIV_COMB) | 1720 | if (ah->caps.hw_caps & ATH9K_HW_CAP_ANT_DIV_COMB) |
1776 | ath_ant_comb_scan(sc, &rs); | 1721 | ath_ant_comb_scan(sc, &rs); |
1777 | 1722 | ||
1778 | ath_rx_send_to_mac80211(hw, sc, skb); | 1723 | ieee80211_rx(hw, skb); |
1779 | 1724 | ||
1780 | requeue: | 1725 | requeue: |
1781 | if (edma) { | 1726 | if (edma) { |
diff --git a/drivers/net/wireless/ath/ath9k/virtual.c b/drivers/net/wireless/ath/ath9k/virtual.c deleted file mode 100644 index d205c66cd972..000000000000 --- a/drivers/net/wireless/ath/ath9k/virtual.c +++ /dev/null | |||
@@ -1,669 +0,0 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2008-2009 Atheros Communications 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 <linux/slab.h> | ||
18 | |||
19 | #include "ath9k.h" | ||
20 | |||
21 | int ath9k_wiphy_add(struct ath_softc *sc) | ||
22 | { | ||
23 | int i, error; | ||
24 | struct ath_wiphy *aphy; | ||
25 | struct ath_common *common = ath9k_hw_common(sc->sc_ah); | ||
26 | struct ieee80211_hw *hw; | ||
27 | u8 addr[ETH_ALEN]; | ||
28 | |||
29 | hw = ieee80211_alloc_hw(sizeof(struct ath_wiphy), &ath9k_ops); | ||
30 | if (hw == NULL) | ||
31 | return -ENOMEM; | ||
32 | |||
33 | spin_lock_bh(&sc->wiphy_lock); | ||
34 | for (i = 0; i < sc->num_sec_wiphy; i++) { | ||
35 | if (sc->sec_wiphy[i] == NULL) | ||
36 | break; | ||
37 | } | ||
38 | |||
39 | if (i == sc->num_sec_wiphy) { | ||
40 | /* No empty slot available; increase array length */ | ||
41 | struct ath_wiphy **n; | ||
42 | n = krealloc(sc->sec_wiphy, | ||
43 | (sc->num_sec_wiphy + 1) * | ||
44 | sizeof(struct ath_wiphy *), | ||
45 | GFP_ATOMIC); | ||
46 | if (n == NULL) { | ||
47 | spin_unlock_bh(&sc->wiphy_lock); | ||
48 | ieee80211_free_hw(hw); | ||
49 | return -ENOMEM; | ||
50 | } | ||
51 | n[i] = NULL; | ||
52 | sc->sec_wiphy = n; | ||
53 | sc->num_sec_wiphy++; | ||
54 | } | ||
55 | |||
56 | SET_IEEE80211_DEV(hw, sc->dev); | ||
57 | |||
58 | aphy = hw->priv; | ||
59 | aphy->sc = sc; | ||
60 | aphy->hw = hw; | ||
61 | sc->sec_wiphy[i] = aphy; | ||
62 | aphy->last_rssi = ATH_RSSI_DUMMY_MARKER; | ||
63 | spin_unlock_bh(&sc->wiphy_lock); | ||
64 | |||
65 | memcpy(addr, common->macaddr, ETH_ALEN); | ||
66 | addr[0] |= 0x02; /* Locally managed address */ | ||
67 | /* | ||
68 | * XOR virtual wiphy index into the least significant bits to generate | ||
69 | * a different MAC address for each virtual wiphy. | ||
70 | */ | ||
71 | addr[5] ^= i & 0xff; | ||
72 | addr[4] ^= (i & 0xff00) >> 8; | ||
73 | addr[3] ^= (i & 0xff0000) >> 16; | ||
74 | |||
75 | SET_IEEE80211_PERM_ADDR(hw, addr); | ||
76 | |||
77 | ath9k_set_hw_capab(sc, hw); | ||
78 | |||
79 | error = ieee80211_register_hw(hw); | ||
80 | |||
81 | if (error == 0) { | ||
82 | /* Make sure wiphy scheduler is started (if enabled) */ | ||
83 | ath9k_wiphy_set_scheduler(sc, sc->wiphy_scheduler_int); | ||
84 | } | ||
85 | |||
86 | return error; | ||
87 | } | ||
88 | |||
89 | int ath9k_wiphy_del(struct ath_wiphy *aphy) | ||
90 | { | ||
91 | struct ath_softc *sc = aphy->sc; | ||
92 | int i; | ||
93 | |||
94 | spin_lock_bh(&sc->wiphy_lock); | ||
95 | for (i = 0; i < sc->num_sec_wiphy; i++) { | ||
96 | if (aphy == sc->sec_wiphy[i]) { | ||
97 | sc->sec_wiphy[i] = NULL; | ||
98 | spin_unlock_bh(&sc->wiphy_lock); | ||
99 | ieee80211_unregister_hw(aphy->hw); | ||
100 | ieee80211_free_hw(aphy->hw); | ||
101 | return 0; | ||
102 | } | ||
103 | } | ||
104 | spin_unlock_bh(&sc->wiphy_lock); | ||
105 | return -ENOENT; | ||
106 | } | ||
107 | |||
108 | static int ath9k_send_nullfunc(struct ath_wiphy *aphy, | ||
109 | struct ieee80211_vif *vif, const u8 *bssid, | ||
110 | int ps) | ||
111 | { | ||
112 | struct ath_softc *sc = aphy->sc; | ||
113 | struct ath_tx_control txctl; | ||
114 | struct sk_buff *skb; | ||
115 | struct ieee80211_hdr *hdr; | ||
116 | __le16 fc; | ||
117 | struct ieee80211_tx_info *info; | ||
118 | |||
119 | skb = dev_alloc_skb(24); | ||
120 | if (skb == NULL) | ||
121 | return -ENOMEM; | ||
122 | hdr = (struct ieee80211_hdr *) skb_put(skb, 24); | ||
123 | memset(hdr, 0, 24); | ||
124 | fc = cpu_to_le16(IEEE80211_FTYPE_DATA | IEEE80211_STYPE_NULLFUNC | | ||
125 | IEEE80211_FCTL_TODS); | ||
126 | if (ps) | ||
127 | fc |= cpu_to_le16(IEEE80211_FCTL_PM); | ||
128 | hdr->frame_control = fc; | ||
129 | memcpy(hdr->addr1, bssid, ETH_ALEN); | ||
130 | memcpy(hdr->addr2, aphy->hw->wiphy->perm_addr, ETH_ALEN); | ||
131 | memcpy(hdr->addr3, bssid, ETH_ALEN); | ||
132 | |||
133 | info = IEEE80211_SKB_CB(skb); | ||
134 | memset(info, 0, sizeof(*info)); | ||
135 | info->flags = IEEE80211_TX_CTL_REQ_TX_STATUS; | ||
136 | info->control.vif = vif; | ||
137 | info->control.rates[0].idx = 0; | ||
138 | info->control.rates[0].count = 4; | ||
139 | info->control.rates[1].idx = -1; | ||
140 | |||
141 | memset(&txctl, 0, sizeof(struct ath_tx_control)); | ||
142 | txctl.txq = sc->tx.txq_map[WME_AC_VO]; | ||
143 | txctl.frame_type = ps ? ATH9K_IFT_PAUSE : ATH9K_IFT_UNPAUSE; | ||
144 | |||
145 | if (ath_tx_start(aphy->hw, skb, &txctl) != 0) | ||
146 | goto exit; | ||
147 | |||
148 | return 0; | ||
149 | exit: | ||
150 | dev_kfree_skb_any(skb); | ||
151 | return -1; | ||
152 | } | ||
153 | |||
154 | static bool __ath9k_wiphy_pausing(struct ath_softc *sc) | ||
155 | { | ||
156 | int i; | ||
157 | if (sc->pri_wiphy->state == ATH_WIPHY_PAUSING) | ||
158 | return true; | ||
159 | for (i = 0; i < sc->num_sec_wiphy; i++) { | ||
160 | if (sc->sec_wiphy[i] && | ||
161 | sc->sec_wiphy[i]->state == ATH_WIPHY_PAUSING) | ||
162 | return true; | ||
163 | } | ||
164 | return false; | ||
165 | } | ||
166 | |||
167 | static bool ath9k_wiphy_pausing(struct ath_softc *sc) | ||
168 | { | ||
169 | bool ret; | ||
170 | spin_lock_bh(&sc->wiphy_lock); | ||
171 | ret = __ath9k_wiphy_pausing(sc); | ||
172 | spin_unlock_bh(&sc->wiphy_lock); | ||
173 | return ret; | ||
174 | } | ||
175 | |||
176 | static bool __ath9k_wiphy_scanning(struct ath_softc *sc) | ||
177 | { | ||
178 | int i; | ||
179 | if (sc->pri_wiphy->state == ATH_WIPHY_SCAN) | ||
180 | return true; | ||
181 | for (i = 0; i < sc->num_sec_wiphy; i++) { | ||
182 | if (sc->sec_wiphy[i] && | ||
183 | sc->sec_wiphy[i]->state == ATH_WIPHY_SCAN) | ||
184 | return true; | ||
185 | } | ||
186 | return false; | ||
187 | } | ||
188 | |||
189 | bool ath9k_wiphy_scanning(struct ath_softc *sc) | ||
190 | { | ||
191 | bool ret; | ||
192 | spin_lock_bh(&sc->wiphy_lock); | ||
193 | ret = __ath9k_wiphy_scanning(sc); | ||
194 | spin_unlock_bh(&sc->wiphy_lock); | ||
195 | return ret; | ||
196 | } | ||
197 | |||
198 | static int __ath9k_wiphy_unpause(struct ath_wiphy *aphy); | ||
199 | |||
200 | /* caller must hold wiphy_lock */ | ||
201 | static void __ath9k_wiphy_unpause_ch(struct ath_wiphy *aphy) | ||
202 | { | ||
203 | if (aphy == NULL) | ||
204 | return; | ||
205 | if (aphy->chan_idx != aphy->sc->chan_idx) | ||
206 | return; /* wiphy not on the selected channel */ | ||
207 | __ath9k_wiphy_unpause(aphy); | ||
208 | } | ||
209 | |||
210 | static void ath9k_wiphy_unpause_channel(struct ath_softc *sc) | ||
211 | { | ||
212 | int i; | ||
213 | spin_lock_bh(&sc->wiphy_lock); | ||
214 | __ath9k_wiphy_unpause_ch(sc->pri_wiphy); | ||
215 | for (i = 0; i < sc->num_sec_wiphy; i++) | ||
216 | __ath9k_wiphy_unpause_ch(sc->sec_wiphy[i]); | ||
217 | spin_unlock_bh(&sc->wiphy_lock); | ||
218 | } | ||
219 | |||
220 | void ath9k_wiphy_chan_work(struct work_struct *work) | ||
221 | { | ||
222 | struct ath_softc *sc = container_of(work, struct ath_softc, chan_work); | ||
223 | struct ath_common *common = ath9k_hw_common(sc->sc_ah); | ||
224 | struct ath_wiphy *aphy = sc->next_wiphy; | ||
225 | |||
226 | if (aphy == NULL) | ||
227 | return; | ||
228 | |||
229 | /* | ||
230 | * All pending interfaces paused; ready to change | ||
231 | * channels. | ||
232 | */ | ||
233 | |||
234 | /* Change channels */ | ||
235 | mutex_lock(&sc->mutex); | ||
236 | /* XXX: remove me eventually */ | ||
237 | ath9k_update_ichannel(sc, aphy->hw, | ||
238 | &sc->sc_ah->channels[sc->chan_idx]); | ||
239 | |||
240 | /* sync hw configuration for hw code */ | ||
241 | common->hw = aphy->hw; | ||
242 | |||
243 | if (ath_set_channel(sc, aphy->hw, | ||
244 | &sc->sc_ah->channels[sc->chan_idx]) < 0) { | ||
245 | printk(KERN_DEBUG "ath9k: Failed to set channel for new " | ||
246 | "virtual wiphy\n"); | ||
247 | mutex_unlock(&sc->mutex); | ||
248 | return; | ||
249 | } | ||
250 | mutex_unlock(&sc->mutex); | ||
251 | |||
252 | ath9k_wiphy_unpause_channel(sc); | ||
253 | } | ||
254 | |||
255 | /* | ||
256 | * ath9k version of ieee80211_tx_status() for TX frames that are generated | ||
257 | * internally in the driver. | ||
258 | */ | ||
259 | void ath9k_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb, int ftype) | ||
260 | { | ||
261 | struct ath_wiphy *aphy = hw->priv; | ||
262 | struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb); | ||
263 | |||
264 | if (ftype == ATH9K_IFT_PAUSE && aphy->state == ATH_WIPHY_PAUSING) { | ||
265 | if (!(tx_info->flags & IEEE80211_TX_STAT_ACK)) { | ||
266 | printk(KERN_DEBUG "ath9k: %s: no ACK for pause " | ||
267 | "frame\n", wiphy_name(hw->wiphy)); | ||
268 | /* | ||
269 | * The AP did not reply; ignore this to allow us to | ||
270 | * continue. | ||
271 | */ | ||
272 | } | ||
273 | aphy->state = ATH_WIPHY_PAUSED; | ||
274 | if (!ath9k_wiphy_pausing(aphy->sc)) { | ||
275 | /* | ||
276 | * Drop from tasklet to work to allow mutex for channel | ||
277 | * change. | ||
278 | */ | ||
279 | ieee80211_queue_work(aphy->sc->hw, | ||
280 | &aphy->sc->chan_work); | ||
281 | } | ||
282 | } | ||
283 | |||
284 | dev_kfree_skb(skb); | ||
285 | } | ||
286 | |||
287 | static void ath9k_mark_paused(struct ath_wiphy *aphy) | ||
288 | { | ||
289 | struct ath_softc *sc = aphy->sc; | ||
290 | aphy->state = ATH_WIPHY_PAUSED; | ||
291 | if (!__ath9k_wiphy_pausing(sc)) | ||
292 | ieee80211_queue_work(sc->hw, &sc->chan_work); | ||
293 | } | ||
294 | |||
295 | static void ath9k_pause_iter(void *data, u8 *mac, struct ieee80211_vif *vif) | ||
296 | { | ||
297 | struct ath_wiphy *aphy = data; | ||
298 | struct ath_vif *avp = (void *) vif->drv_priv; | ||
299 | |||
300 | switch (vif->type) { | ||
301 | case NL80211_IFTYPE_STATION: | ||
302 | if (!vif->bss_conf.assoc) { | ||
303 | ath9k_mark_paused(aphy); | ||
304 | break; | ||
305 | } | ||
306 | /* TODO: could avoid this if already in PS mode */ | ||
307 | if (ath9k_send_nullfunc(aphy, vif, avp->bssid, 1)) { | ||
308 | printk(KERN_DEBUG "%s: failed to send PS nullfunc\n", | ||
309 | __func__); | ||
310 | ath9k_mark_paused(aphy); | ||
311 | } | ||
312 | break; | ||
313 | case NL80211_IFTYPE_AP: | ||
314 | /* Beacon transmission is paused by aphy->state change */ | ||
315 | ath9k_mark_paused(aphy); | ||
316 | break; | ||
317 | default: | ||
318 | break; | ||
319 | } | ||
320 | } | ||
321 | |||
322 | /* caller must hold wiphy_lock */ | ||
323 | static int __ath9k_wiphy_pause(struct ath_wiphy *aphy) | ||
324 | { | ||
325 | ieee80211_stop_queues(aphy->hw); | ||
326 | aphy->state = ATH_WIPHY_PAUSING; | ||
327 | /* | ||
328 | * TODO: handle PAUSING->PAUSED for the case where there are multiple | ||
329 | * active vifs (now we do it on the first vif getting ready; should be | ||
330 | * on the last) | ||
331 | */ | ||
332 | ieee80211_iterate_active_interfaces_atomic(aphy->hw, ath9k_pause_iter, | ||
333 | aphy); | ||
334 | return 0; | ||
335 | } | ||
336 | |||
337 | int ath9k_wiphy_pause(struct ath_wiphy *aphy) | ||
338 | { | ||
339 | int ret; | ||
340 | spin_lock_bh(&aphy->sc->wiphy_lock); | ||
341 | ret = __ath9k_wiphy_pause(aphy); | ||
342 | spin_unlock_bh(&aphy->sc->wiphy_lock); | ||
343 | return ret; | ||
344 | } | ||
345 | |||
346 | static void ath9k_unpause_iter(void *data, u8 *mac, struct ieee80211_vif *vif) | ||
347 | { | ||
348 | struct ath_wiphy *aphy = data; | ||
349 | struct ath_vif *avp = (void *) vif->drv_priv; | ||
350 | |||
351 | switch (vif->type) { | ||
352 | case NL80211_IFTYPE_STATION: | ||
353 | if (!vif->bss_conf.assoc) | ||
354 | break; | ||
355 | ath9k_send_nullfunc(aphy, vif, avp->bssid, 0); | ||
356 | break; | ||
357 | case NL80211_IFTYPE_AP: | ||
358 | /* Beacon transmission is re-enabled by aphy->state change */ | ||
359 | break; | ||
360 | default: | ||
361 | break; | ||
362 | } | ||
363 | } | ||
364 | |||
365 | /* caller must hold wiphy_lock */ | ||
366 | static int __ath9k_wiphy_unpause(struct ath_wiphy *aphy) | ||
367 | { | ||
368 | ieee80211_iterate_active_interfaces_atomic(aphy->hw, | ||
369 | ath9k_unpause_iter, aphy); | ||
370 | aphy->state = ATH_WIPHY_ACTIVE; | ||
371 | ieee80211_wake_queues(aphy->hw); | ||
372 | return 0; | ||
373 | } | ||
374 | |||
375 | int ath9k_wiphy_unpause(struct ath_wiphy *aphy) | ||
376 | { | ||
377 | int ret; | ||
378 | spin_lock_bh(&aphy->sc->wiphy_lock); | ||
379 | ret = __ath9k_wiphy_unpause(aphy); | ||
380 | spin_unlock_bh(&aphy->sc->wiphy_lock); | ||
381 | return ret; | ||
382 | } | ||
383 | |||
384 | static void __ath9k_wiphy_mark_all_paused(struct ath_softc *sc) | ||
385 | { | ||
386 | int i; | ||
387 | if (sc->pri_wiphy->state != ATH_WIPHY_INACTIVE) | ||
388 | sc->pri_wiphy->state = ATH_WIPHY_PAUSED; | ||
389 | for (i = 0; i < sc->num_sec_wiphy; i++) { | ||
390 | if (sc->sec_wiphy[i] && | ||
391 | sc->sec_wiphy[i]->state != ATH_WIPHY_INACTIVE) | ||
392 | sc->sec_wiphy[i]->state = ATH_WIPHY_PAUSED; | ||
393 | } | ||
394 | } | ||
395 | |||
396 | /* caller must hold wiphy_lock */ | ||
397 | static void __ath9k_wiphy_pause_all(struct ath_softc *sc) | ||
398 | { | ||
399 | int i; | ||
400 | if (sc->pri_wiphy->state == ATH_WIPHY_ACTIVE) | ||
401 | __ath9k_wiphy_pause(sc->pri_wiphy); | ||
402 | for (i = 0; i < sc->num_sec_wiphy; i++) { | ||
403 | if (sc->sec_wiphy[i] && | ||
404 | sc->sec_wiphy[i]->state == ATH_WIPHY_ACTIVE) | ||
405 | __ath9k_wiphy_pause(sc->sec_wiphy[i]); | ||
406 | } | ||
407 | } | ||
408 | |||
409 | int ath9k_wiphy_select(struct ath_wiphy *aphy) | ||
410 | { | ||
411 | struct ath_softc *sc = aphy->sc; | ||
412 | bool now; | ||
413 | |||
414 | spin_lock_bh(&sc->wiphy_lock); | ||
415 | if (__ath9k_wiphy_scanning(sc)) { | ||
416 | /* | ||
417 | * For now, we are using mac80211 sw scan and it expects to | ||
418 | * have full control over channel changes, so avoid wiphy | ||
419 | * scheduling during a scan. This could be optimized if the | ||
420 | * scanning control were moved into the driver. | ||
421 | */ | ||
422 | spin_unlock_bh(&sc->wiphy_lock); | ||
423 | return -EBUSY; | ||
424 | } | ||
425 | if (__ath9k_wiphy_pausing(sc)) { | ||
426 | if (sc->wiphy_select_failures == 0) | ||
427 | sc->wiphy_select_first_fail = jiffies; | ||
428 | sc->wiphy_select_failures++; | ||
429 | if (time_after(jiffies, sc->wiphy_select_first_fail + HZ / 2)) | ||
430 | { | ||
431 | printk(KERN_DEBUG "ath9k: Previous wiphy select timed " | ||
432 | "out; disable/enable hw to recover\n"); | ||
433 | __ath9k_wiphy_mark_all_paused(sc); | ||
434 | /* | ||
435 | * TODO: this workaround to fix hardware is unlikely to | ||
436 | * be specific to virtual wiphy changes. It can happen | ||
437 | * on normal channel change, too, and as such, this | ||
438 | * should really be made more generic. For example, | ||
439 | * tricker radio disable/enable on GTT interrupt burst | ||
440 | * (say, 10 GTT interrupts received without any TX | ||
441 | * frame being completed) | ||
442 | */ | ||
443 | spin_unlock_bh(&sc->wiphy_lock); | ||
444 | ath_radio_disable(sc, aphy->hw); | ||
445 | ath_radio_enable(sc, aphy->hw); | ||
446 | /* Only the primary wiphy hw is used for queuing work */ | ||
447 | ieee80211_queue_work(aphy->sc->hw, | ||
448 | &aphy->sc->chan_work); | ||
449 | return -EBUSY; /* previous select still in progress */ | ||
450 | } | ||
451 | spin_unlock_bh(&sc->wiphy_lock); | ||
452 | return -EBUSY; /* previous select still in progress */ | ||
453 | } | ||
454 | sc->wiphy_select_failures = 0; | ||
455 | |||
456 | /* Store the new channel */ | ||
457 | sc->chan_idx = aphy->chan_idx; | ||
458 | sc->chan_is_ht = aphy->chan_is_ht; | ||
459 | sc->next_wiphy = aphy; | ||
460 | |||
461 | __ath9k_wiphy_pause_all(sc); | ||
462 | now = !__ath9k_wiphy_pausing(aphy->sc); | ||
463 | spin_unlock_bh(&sc->wiphy_lock); | ||
464 | |||
465 | if (now) { | ||
466 | /* Ready to request channel change immediately */ | ||
467 | ieee80211_queue_work(aphy->sc->hw, &aphy->sc->chan_work); | ||
468 | } | ||
469 | |||
470 | /* | ||
471 | * wiphys will be unpaused in ath9k_tx_status() once channel has been | ||
472 | * changed if any wiphy needs time to become paused. | ||
473 | */ | ||
474 | |||
475 | return 0; | ||
476 | } | ||
477 | |||
478 | bool ath9k_wiphy_started(struct ath_softc *sc) | ||
479 | { | ||
480 | int i; | ||
481 | spin_lock_bh(&sc->wiphy_lock); | ||
482 | if (sc->pri_wiphy->state != ATH_WIPHY_INACTIVE) { | ||
483 | spin_unlock_bh(&sc->wiphy_lock); | ||
484 | return true; | ||
485 | } | ||
486 | for (i = 0; i < sc->num_sec_wiphy; i++) { | ||
487 | if (sc->sec_wiphy[i] && | ||
488 | sc->sec_wiphy[i]->state != ATH_WIPHY_INACTIVE) { | ||
489 | spin_unlock_bh(&sc->wiphy_lock); | ||
490 | return true; | ||
491 | } | ||
492 | } | ||
493 | spin_unlock_bh(&sc->wiphy_lock); | ||
494 | return false; | ||
495 | } | ||
496 | |||
497 | static void ath9k_wiphy_pause_chan(struct ath_wiphy *aphy, | ||
498 | struct ath_wiphy *selected) | ||
499 | { | ||
500 | if (selected->state == ATH_WIPHY_SCAN) { | ||
501 | if (aphy == selected) | ||
502 | return; | ||
503 | /* | ||
504 | * Pause all other wiphys for the duration of the scan even if | ||
505 | * they are on the current channel now. | ||
506 | */ | ||
507 | } else if (aphy->chan_idx == selected->chan_idx) | ||
508 | return; | ||
509 | aphy->state = ATH_WIPHY_PAUSED; | ||
510 | ieee80211_stop_queues(aphy->hw); | ||
511 | } | ||
512 | |||
513 | void ath9k_wiphy_pause_all_forced(struct ath_softc *sc, | ||
514 | struct ath_wiphy *selected) | ||
515 | { | ||
516 | int i; | ||
517 | spin_lock_bh(&sc->wiphy_lock); | ||
518 | if (sc->pri_wiphy->state == ATH_WIPHY_ACTIVE) | ||
519 | ath9k_wiphy_pause_chan(sc->pri_wiphy, selected); | ||
520 | for (i = 0; i < sc->num_sec_wiphy; i++) { | ||
521 | if (sc->sec_wiphy[i] && | ||
522 | sc->sec_wiphy[i]->state == ATH_WIPHY_ACTIVE) | ||
523 | ath9k_wiphy_pause_chan(sc->sec_wiphy[i], selected); | ||
524 | } | ||
525 | spin_unlock_bh(&sc->wiphy_lock); | ||
526 | } | ||
527 | |||
528 | void ath9k_wiphy_work(struct work_struct *work) | ||
529 | { | ||
530 | struct ath_softc *sc = container_of(work, struct ath_softc, | ||
531 | wiphy_work.work); | ||
532 | struct ath_wiphy *aphy = NULL; | ||
533 | bool first = true; | ||
534 | |||
535 | spin_lock_bh(&sc->wiphy_lock); | ||
536 | |||
537 | if (sc->wiphy_scheduler_int == 0) { | ||
538 | /* wiphy scheduler is disabled */ | ||
539 | spin_unlock_bh(&sc->wiphy_lock); | ||
540 | return; | ||
541 | } | ||
542 | |||
543 | try_again: | ||
544 | sc->wiphy_scheduler_index++; | ||
545 | while (sc->wiphy_scheduler_index <= sc->num_sec_wiphy) { | ||
546 | aphy = sc->sec_wiphy[sc->wiphy_scheduler_index - 1]; | ||
547 | if (aphy && aphy->state != ATH_WIPHY_INACTIVE) | ||
548 | break; | ||
549 | |||
550 | sc->wiphy_scheduler_index++; | ||
551 | aphy = NULL; | ||
552 | } | ||
553 | if (aphy == NULL) { | ||
554 | sc->wiphy_scheduler_index = 0; | ||
555 | if (sc->pri_wiphy->state == ATH_WIPHY_INACTIVE) { | ||
556 | if (first) { | ||
557 | first = false; | ||
558 | goto try_again; | ||
559 | } | ||
560 | /* No wiphy is ready to be scheduled */ | ||
561 | } else | ||
562 | aphy = sc->pri_wiphy; | ||
563 | } | ||
564 | |||
565 | spin_unlock_bh(&sc->wiphy_lock); | ||
566 | |||
567 | if (aphy && | ||
568 | aphy->state != ATH_WIPHY_ACTIVE && aphy->state != ATH_WIPHY_SCAN && | ||
569 | ath9k_wiphy_select(aphy)) { | ||
570 | printk(KERN_DEBUG "ath9k: Failed to schedule virtual wiphy " | ||
571 | "change\n"); | ||
572 | } | ||
573 | |||
574 | ieee80211_queue_delayed_work(sc->hw, | ||
575 | &sc->wiphy_work, | ||
576 | sc->wiphy_scheduler_int); | ||
577 | } | ||
578 | |||
579 | void ath9k_wiphy_set_scheduler(struct ath_softc *sc, unsigned int msec_int) | ||
580 | { | ||
581 | cancel_delayed_work_sync(&sc->wiphy_work); | ||
582 | sc->wiphy_scheduler_int = msecs_to_jiffies(msec_int); | ||
583 | if (sc->wiphy_scheduler_int) | ||
584 | ieee80211_queue_delayed_work(sc->hw, &sc->wiphy_work, | ||
585 | sc->wiphy_scheduler_int); | ||
586 | } | ||
587 | |||
588 | /* caller must hold wiphy_lock */ | ||
589 | bool ath9k_all_wiphys_idle(struct ath_softc *sc) | ||
590 | { | ||
591 | unsigned int i; | ||
592 | if (!sc->pri_wiphy->idle) | ||
593 | return false; | ||
594 | for (i = 0; i < sc->num_sec_wiphy; i++) { | ||
595 | struct ath_wiphy *aphy = sc->sec_wiphy[i]; | ||
596 | if (!aphy) | ||
597 | continue; | ||
598 | if (!aphy->idle) | ||
599 | return false; | ||
600 | } | ||
601 | return true; | ||
602 | } | ||
603 | |||
604 | /* caller must hold wiphy_lock */ | ||
605 | void ath9k_set_wiphy_idle(struct ath_wiphy *aphy, bool idle) | ||
606 | { | ||
607 | struct ath_softc *sc = aphy->sc; | ||
608 | |||
609 | aphy->idle = idle; | ||
610 | ath_dbg(ath9k_hw_common(sc->sc_ah), ATH_DBG_CONFIG, | ||
611 | "Marking %s as %sidle\n", | ||
612 | wiphy_name(aphy->hw->wiphy), idle ? "" : "not-"); | ||
613 | } | ||
614 | /* Only bother starting a queue on an active virtual wiphy */ | ||
615 | bool ath_mac80211_start_queue(struct ath_softc *sc, u16 skb_queue) | ||
616 | { | ||
617 | struct ieee80211_hw *hw = sc->pri_wiphy->hw; | ||
618 | unsigned int i; | ||
619 | bool txq_started = false; | ||
620 | |||
621 | spin_lock_bh(&sc->wiphy_lock); | ||
622 | |||
623 | /* Start the primary wiphy */ | ||
624 | if (sc->pri_wiphy->state == ATH_WIPHY_ACTIVE) { | ||
625 | ieee80211_wake_queue(hw, skb_queue); | ||
626 | txq_started = true; | ||
627 | goto unlock; | ||
628 | } | ||
629 | |||
630 | /* Now start the secondary wiphy queues */ | ||
631 | for (i = 0; i < sc->num_sec_wiphy; i++) { | ||
632 | struct ath_wiphy *aphy = sc->sec_wiphy[i]; | ||
633 | if (!aphy) | ||
634 | continue; | ||
635 | if (aphy->state != ATH_WIPHY_ACTIVE) | ||
636 | continue; | ||
637 | |||
638 | hw = aphy->hw; | ||
639 | ieee80211_wake_queue(hw, skb_queue); | ||
640 | txq_started = true; | ||
641 | break; | ||
642 | } | ||
643 | |||
644 | unlock: | ||
645 | spin_unlock_bh(&sc->wiphy_lock); | ||
646 | return txq_started; | ||
647 | } | ||
648 | |||
649 | /* Go ahead and propagate information to all virtual wiphys, it won't hurt */ | ||
650 | void ath_mac80211_stop_queue(struct ath_softc *sc, u16 skb_queue) | ||
651 | { | ||
652 | struct ieee80211_hw *hw = sc->pri_wiphy->hw; | ||
653 | unsigned int i; | ||
654 | |||
655 | spin_lock_bh(&sc->wiphy_lock); | ||
656 | |||
657 | /* Stop the primary wiphy */ | ||
658 | ieee80211_stop_queue(hw, skb_queue); | ||
659 | |||
660 | /* Now stop the secondary wiphy queues */ | ||
661 | for (i = 0; i < sc->num_sec_wiphy; i++) { | ||
662 | struct ath_wiphy *aphy = sc->sec_wiphy[i]; | ||
663 | if (!aphy) | ||
664 | continue; | ||
665 | hw = aphy->hw; | ||
666 | ieee80211_stop_queue(hw, skb_queue); | ||
667 | } | ||
668 | spin_unlock_bh(&sc->wiphy_lock); | ||
669 | } | ||
diff --git a/drivers/net/wireless/ath/ath9k/xmit.c b/drivers/net/wireless/ath/ath9k/xmit.c index 3445389a49ef..07fdfa314759 100644 --- a/drivers/net/wireless/ath/ath9k/xmit.c +++ b/drivers/net/wireless/ath/ath9k/xmit.c | |||
@@ -1819,7 +1819,7 @@ int ath_tx_start(struct ieee80211_hw *hw, struct sk_buff *skb, | |||
1819 | spin_lock_bh(&txq->axq_lock); | 1819 | spin_lock_bh(&txq->axq_lock); |
1820 | if (txq == sc->tx.txq_map[q] && | 1820 | if (txq == sc->tx.txq_map[q] && |
1821 | ++txq->pending_frames > ATH_MAX_QDEPTH && !txq->stopped) { | 1821 | ++txq->pending_frames > ATH_MAX_QDEPTH && !txq->stopped) { |
1822 | ath_mac80211_stop_queue(sc, q); | 1822 | ieee80211_stop_queue(sc->hw, q); |
1823 | txq->stopped = 1; | 1823 | txq->stopped = 1; |
1824 | } | 1824 | } |
1825 | spin_unlock_bh(&txq->axq_lock); | 1825 | spin_unlock_bh(&txq->axq_lock); |
@@ -1877,24 +1877,20 @@ static void ath_tx_complete(struct ath_softc *sc, struct sk_buff *skb, | |||
1877 | PS_WAIT_FOR_TX_ACK)); | 1877 | PS_WAIT_FOR_TX_ACK)); |
1878 | } | 1878 | } |
1879 | 1879 | ||
1880 | if (unlikely(ftype)) | 1880 | q = skb_get_queue_mapping(skb); |
1881 | ath9k_tx_status(hw, skb, ftype); | 1881 | if (txq == sc->tx.txq_map[q]) { |
1882 | else { | 1882 | spin_lock_bh(&txq->axq_lock); |
1883 | q = skb_get_queue_mapping(skb); | 1883 | if (WARN_ON(--txq->pending_frames < 0)) |
1884 | if (txq == sc->tx.txq_map[q]) { | 1884 | txq->pending_frames = 0; |
1885 | spin_lock_bh(&txq->axq_lock); | ||
1886 | if (WARN_ON(--txq->pending_frames < 0)) | ||
1887 | txq->pending_frames = 0; | ||
1888 | 1885 | ||
1889 | if (txq->stopped && txq->pending_frames < ATH_MAX_QDEPTH) { | 1886 | if (txq->stopped && txq->pending_frames < ATH_MAX_QDEPTH) { |
1890 | if (ath_mac80211_start_queue(sc, q)) | 1887 | ieee80211_wake_queue(sc->hw, q); |
1891 | txq->stopped = 0; | 1888 | txq->stopped = 0; |
1892 | } | ||
1893 | spin_unlock_bh(&txq->axq_lock); | ||
1894 | } | 1889 | } |
1895 | 1890 | spin_unlock_bh(&txq->axq_lock); | |
1896 | ieee80211_tx_status(hw, skb); | ||
1897 | } | 1891 | } |
1892 | |||
1893 | ieee80211_tx_status(hw, skb); | ||
1898 | } | 1894 | } |
1899 | 1895 | ||
1900 | static void ath_tx_complete_buf(struct ath_softc *sc, struct ath_buf *bf, | 1896 | static void ath_tx_complete_buf(struct ath_softc *sc, struct ath_buf *bf, |