aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/ath/ath9k/virtual.c
diff options
context:
space:
mode:
authorAndrea Bastoni <bastoni@cs.unc.edu>2010-05-30 19:16:45 -0400
committerAndrea Bastoni <bastoni@cs.unc.edu>2010-05-30 19:16:45 -0400
commitada47b5fe13d89735805b566185f4885f5a3f750 (patch)
tree644b88f8a71896307d71438e9b3af49126ffb22b /drivers/net/wireless/ath/ath9k/virtual.c
parent43e98717ad40a4ae64545b5ba047c7b86aa44f4f (diff)
parent3280f21d43ee541f97f8cda5792150d2dbec20d5 (diff)
Merge branch 'wip-2.6.34' into old-private-masterarchived-private-master
Diffstat (limited to 'drivers/net/wireless/ath/ath9k/virtual.c')
-rw-r--r--drivers/net/wireless/ath/ath9k/virtual.c114
1 files changed, 91 insertions, 23 deletions
diff --git a/drivers/net/wireless/ath/ath9k/virtual.c b/drivers/net/wireless/ath/ath9k/virtual.c
index 19b88f8177fd..00c0e21a4af7 100644
--- a/drivers/net/wireless/ath/ath9k/virtual.c
+++ b/drivers/net/wireless/ath/ath9k/virtual.c
@@ -14,6 +14,8 @@
14 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 14 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
15 */ 15 */
16 16
17#include <linux/slab.h>
18
17#include "ath9k.h" 19#include "ath9k.h"
18 20
19struct ath9k_vif_iter_data { 21struct ath9k_vif_iter_data {
@@ -40,6 +42,7 @@ void ath9k_set_bssid_mask(struct ieee80211_hw *hw)
40{ 42{
41 struct ath_wiphy *aphy = hw->priv; 43 struct ath_wiphy *aphy = hw->priv;
42 struct ath_softc *sc = aphy->sc; 44 struct ath_softc *sc = aphy->sc;
45 struct ath_common *common = ath9k_hw_common(sc->sc_ah);
43 struct ath9k_vif_iter_data iter_data; 46 struct ath9k_vif_iter_data iter_data;
44 int i, j; 47 int i, j;
45 u8 mask[ETH_ALEN]; 48 u8 mask[ETH_ALEN];
@@ -51,7 +54,7 @@ void ath9k_set_bssid_mask(struct ieee80211_hw *hw)
51 */ 54 */
52 iter_data.addr = kmalloc(ETH_ALEN, GFP_ATOMIC); 55 iter_data.addr = kmalloc(ETH_ALEN, GFP_ATOMIC);
53 if (iter_data.addr) { 56 if (iter_data.addr) {
54 memcpy(iter_data.addr, sc->sc_ah->macaddr, ETH_ALEN); 57 memcpy(iter_data.addr, common->macaddr, ETH_ALEN);
55 iter_data.count = 1; 58 iter_data.count = 1;
56 } else 59 } else
57 iter_data.count = 0; 60 iter_data.count = 0;
@@ -86,20 +89,21 @@ void ath9k_set_bssid_mask(struct ieee80211_hw *hw)
86 kfree(iter_data.addr); 89 kfree(iter_data.addr);
87 90
88 /* Invert the mask and configure hardware */ 91 /* Invert the mask and configure hardware */
89 sc->bssidmask[0] = ~mask[0]; 92 common->bssidmask[0] = ~mask[0];
90 sc->bssidmask[1] = ~mask[1]; 93 common->bssidmask[1] = ~mask[1];
91 sc->bssidmask[2] = ~mask[2]; 94 common->bssidmask[2] = ~mask[2];
92 sc->bssidmask[3] = ~mask[3]; 95 common->bssidmask[3] = ~mask[3];
93 sc->bssidmask[4] = ~mask[4]; 96 common->bssidmask[4] = ~mask[4];
94 sc->bssidmask[5] = ~mask[5]; 97 common->bssidmask[5] = ~mask[5];
95 98
96 ath9k_hw_setbssidmask(sc); 99 ath_hw_setbssidmask(common);
97} 100}
98 101
99int ath9k_wiphy_add(struct ath_softc *sc) 102int ath9k_wiphy_add(struct ath_softc *sc)
100{ 103{
101 int i, error; 104 int i, error;
102 struct ath_wiphy *aphy; 105 struct ath_wiphy *aphy;
106 struct ath_common *common = ath9k_hw_common(sc->sc_ah);
103 struct ieee80211_hw *hw; 107 struct ieee80211_hw *hw;
104 u8 addr[ETH_ALEN]; 108 u8 addr[ETH_ALEN];
105 109
@@ -138,7 +142,7 @@ int ath9k_wiphy_add(struct ath_softc *sc)
138 sc->sec_wiphy[i] = aphy; 142 sc->sec_wiphy[i] = aphy;
139 spin_unlock_bh(&sc->wiphy_lock); 143 spin_unlock_bh(&sc->wiphy_lock);
140 144
141 memcpy(addr, sc->sc_ah->macaddr, ETH_ALEN); 145 memcpy(addr, common->macaddr, ETH_ALEN);
142 addr[0] |= 0x02; /* Locally managed address */ 146 addr[0] |= 0x02; /* Locally managed address */
143 /* 147 /*
144 * XOR virtual wiphy index into the least significant bits to generate 148 * XOR virtual wiphy index into the least significant bits to generate
@@ -150,7 +154,7 @@ int ath9k_wiphy_add(struct ath_softc *sc)
150 154
151 SET_IEEE80211_PERM_ADDR(hw, addr); 155 SET_IEEE80211_PERM_ADDR(hw, addr);
152 156
153 ath_set_hw_capab(sc, hw); 157 ath9k_set_hw_capab(sc, hw);
154 158
155 error = ieee80211_register_hw(hw); 159 error = ieee80211_register_hw(hw);
156 160
@@ -296,6 +300,7 @@ static void ath9k_wiphy_unpause_channel(struct ath_softc *sc)
296void ath9k_wiphy_chan_work(struct work_struct *work) 300void ath9k_wiphy_chan_work(struct work_struct *work)
297{ 301{
298 struct ath_softc *sc = container_of(work, struct ath_softc, chan_work); 302 struct ath_softc *sc = container_of(work, struct ath_softc, chan_work);
303 struct ath_common *common = ath9k_hw_common(sc->sc_ah);
299 struct ath_wiphy *aphy = sc->next_wiphy; 304 struct ath_wiphy *aphy = sc->next_wiphy;
300 305
301 if (aphy == NULL) 306 if (aphy == NULL)
@@ -311,6 +316,10 @@ void ath9k_wiphy_chan_work(struct work_struct *work)
311 /* XXX: remove me eventually */ 316 /* XXX: remove me eventually */
312 ath9k_update_ichannel(sc, aphy->hw, 317 ath9k_update_ichannel(sc, aphy->hw,
313 &sc->sc_ah->channels[sc->chan_idx]); 318 &sc->sc_ah->channels[sc->chan_idx]);
319
320 /* sync hw configuration for hw code */
321 common->hw = aphy->hw;
322
314 ath_update_chainmask(sc, sc->chan_is_ht); 323 ath_update_chainmask(sc, sc->chan_is_ht);
315 if (ath_set_channel(sc, aphy->hw, 324 if (ath_set_channel(sc, aphy->hw,
316 &sc->sc_ah->channels[sc->chan_idx]) < 0) { 325 &sc->sc_ah->channels[sc->chan_idx]) < 0) {
@@ -331,13 +340,11 @@ void ath9k_wiphy_chan_work(struct work_struct *work)
331void ath9k_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb) 340void ath9k_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb)
332{ 341{
333 struct ath_wiphy *aphy = hw->priv; 342 struct ath_wiphy *aphy = hw->priv;
334 struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
335 struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb); 343 struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb);
336 struct ath_tx_info_priv *tx_info_priv = ATH_TX_INFO_PRIV(tx_info);
337 344
338 if (tx_info_priv && tx_info_priv->frame_type == ATH9K_INT_PAUSE && 345 if ((tx_info->pad[0] & ATH_TX_INFO_FRAME_TYPE_PAUSE) &&
339 aphy->state == ATH_WIPHY_PAUSING) { 346 aphy->state == ATH_WIPHY_PAUSING) {
340 if (!(info->flags & IEEE80211_TX_STAT_ACK)) { 347 if (!(tx_info->flags & IEEE80211_TX_STAT_ACK)) {
341 printk(KERN_DEBUG "ath9k: %s: no ACK for pause " 348 printk(KERN_DEBUG "ath9k: %s: no ACK for pause "
342 "frame\n", wiphy_name(hw->wiphy)); 349 "frame\n", wiphy_name(hw->wiphy));
343 /* 350 /*
@@ -356,9 +363,6 @@ void ath9k_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb)
356 } 363 }
357 } 364 }
358 365
359 kfree(tx_info_priv);
360 tx_info->rate_driver_data[0] = NULL;
361
362 dev_kfree_skb(skb); 366 dev_kfree_skb(skb);
363} 367}
364 368
@@ -519,8 +523,9 @@ int ath9k_wiphy_select(struct ath_wiphy *aphy)
519 * frame being completed) 523 * frame being completed)
520 */ 524 */
521 spin_unlock_bh(&sc->wiphy_lock); 525 spin_unlock_bh(&sc->wiphy_lock);
522 ath_radio_disable(sc); 526 ath_radio_disable(sc, aphy->hw);
523 ath_radio_enable(sc); 527 ath_radio_enable(sc, aphy->hw);
528 /* Only the primary wiphy hw is used for queuing work */
524 ieee80211_queue_work(aphy->sc->hw, 529 ieee80211_queue_work(aphy->sc->hw,
525 &aphy->sc->chan_work); 530 &aphy->sc->chan_work);
526 return -EBUSY; /* previous select still in progress */ 531 return -EBUSY; /* previous select still in progress */
@@ -666,15 +671,78 @@ void ath9k_wiphy_set_scheduler(struct ath_softc *sc, unsigned int msec_int)
666bool ath9k_all_wiphys_idle(struct ath_softc *sc) 671bool ath9k_all_wiphys_idle(struct ath_softc *sc)
667{ 672{
668 unsigned int i; 673 unsigned int i;
669 if (sc->pri_wiphy->state != ATH_WIPHY_INACTIVE) { 674 if (!sc->pri_wiphy->idle)
670 return false; 675 return false;
671 }
672 for (i = 0; i < sc->num_sec_wiphy; i++) { 676 for (i = 0; i < sc->num_sec_wiphy; i++) {
673 struct ath_wiphy *aphy = sc->sec_wiphy[i]; 677 struct ath_wiphy *aphy = sc->sec_wiphy[i];
674 if (!aphy) 678 if (!aphy)
675 continue; 679 continue;
676 if (aphy->state != ATH_WIPHY_INACTIVE) 680 if (!aphy->idle)
677 return false; 681 return false;
678 } 682 }
679 return true; 683 return true;
680} 684}
685
686/* caller must hold wiphy_lock */
687void ath9k_set_wiphy_idle(struct ath_wiphy *aphy, bool idle)
688{
689 struct ath_softc *sc = aphy->sc;
690
691 aphy->idle = idle;
692 ath_print(ath9k_hw_common(sc->sc_ah), ATH_DBG_CONFIG,
693 "Marking %s as %s\n",
694 wiphy_name(aphy->hw->wiphy),
695 idle ? "idle" : "not-idle");
696}
697/* Only bother starting a queue on an active virtual wiphy */
698void ath_mac80211_start_queue(struct ath_softc *sc, u16 skb_queue)
699{
700 struct ieee80211_hw *hw = sc->pri_wiphy->hw;
701 unsigned int i;
702
703 spin_lock_bh(&sc->wiphy_lock);
704
705 /* Start the primary wiphy */
706 if (sc->pri_wiphy->state == ATH_WIPHY_ACTIVE) {
707 ieee80211_wake_queue(hw, skb_queue);
708 goto unlock;
709 }
710
711 /* Now start the secondary wiphy queues */
712 for (i = 0; i < sc->num_sec_wiphy; i++) {
713 struct ath_wiphy *aphy = sc->sec_wiphy[i];
714 if (!aphy)
715 continue;
716 if (aphy->state != ATH_WIPHY_ACTIVE)
717 continue;
718
719 hw = aphy->hw;
720 ieee80211_wake_queue(hw, skb_queue);
721 break;
722 }
723
724unlock:
725 spin_unlock_bh(&sc->wiphy_lock);
726}
727
728/* Go ahead and propagate information to all virtual wiphys, it won't hurt */
729void ath_mac80211_stop_queue(struct ath_softc *sc, u16 skb_queue)
730{
731 struct ieee80211_hw *hw = sc->pri_wiphy->hw;
732 unsigned int i;
733
734 spin_lock_bh(&sc->wiphy_lock);
735
736 /* Stop the primary wiphy */
737 ieee80211_stop_queue(hw, skb_queue);
738
739 /* Now stop the secondary wiphy queues */
740 for (i = 0; i < sc->num_sec_wiphy; i++) {
741 struct ath_wiphy *aphy = sc->sec_wiphy[i];
742 if (!aphy)
743 continue;
744 hw = aphy->hw;
745 ieee80211_stop_queue(hw, skb_queue);
746 }
747 spin_unlock_bh(&sc->wiphy_lock);
748}