aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/ath9k/recv.c
diff options
context:
space:
mode:
authorJouni Malinen <jouni.malinen@atheros.com>2009-03-03 12:23:29 -0500
committerJohn W. Linville <linville@tuxdriver.com>2009-03-05 14:39:45 -0500
commitc52f33d05e5f8d59f02722fbc308f5f391575ca5 (patch)
tree19c6d56f3594e8b43d725b5d919bb775921fde38 /drivers/net/wireless/ath9k/recv.c
parentbce048d77dff3dcfd75d54dc38580c81baa95853 (diff)
ath9k: Add support for multiple secondary virtual wiphys
The new struct ath_softc::sec_wiphy array is used to store information about virtual wiphys and select which wiphy is used in calls to mac80211. Each virtual wiphy will be assigned a different MAC address based on the virtual wiphy index. Signed-off-by: Jouni Malinen <jouni.malinen@atheros.com> Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'drivers/net/wireless/ath9k/recv.c')
-rw-r--r--drivers/net/wireless/ath9k/recv.c41
1 files changed, 39 insertions, 2 deletions
diff --git a/drivers/net/wireless/ath9k/recv.c b/drivers/net/wireless/ath9k/recv.c
index ec535834f961..a9a55df500a4 100644
--- a/drivers/net/wireless/ath9k/recv.c
+++ b/drivers/net/wireless/ath9k/recv.c
@@ -19,7 +19,22 @@
19static struct ieee80211_hw * ath_get_virt_hw(struct ath_softc *sc, 19static struct ieee80211_hw * ath_get_virt_hw(struct ath_softc *sc,
20 struct ieee80211_hdr *hdr) 20 struct ieee80211_hdr *hdr)
21{ 21{
22 return sc->pri_wiphy->hw; 22 struct ieee80211_hw *hw = sc->pri_wiphy->hw;
23 int i;
24
25 spin_lock_bh(&sc->wiphy_lock);
26 for (i = 0; i < sc->num_sec_wiphy; i++) {
27 struct ath_wiphy *aphy = sc->sec_wiphy[i];
28 if (aphy == NULL)
29 continue;
30 if (compare_ether_addr(hdr->addr1, aphy->hw->wiphy->perm_addr)
31 == 0) {
32 hw = aphy->hw;
33 break;
34 }
35 }
36 spin_unlock_bh(&sc->wiphy_lock);
37 return hw;
23} 38}
24 39
25/* 40/*
@@ -611,7 +626,29 @@ int ath_rx_tasklet(struct ath_softc *sc, int flush)
611 } 626 }
612 627
613 /* Send the frame to mac80211 */ 628 /* Send the frame to mac80211 */
614 __ieee80211_rx(ath_get_virt_hw(sc, hdr), skb, &rx_status); 629 if (hdr->addr1[5] & 0x01) {
630 int i;
631 /*
632 * Deliver broadcast/multicast frames to all suitable
633 * virtual wiphys.
634 */
635 /* TODO: filter based on channel configuration */
636 for (i = 0; i < sc->num_sec_wiphy; i++) {
637 struct ath_wiphy *aphy = sc->sec_wiphy[i];
638 struct sk_buff *nskb;
639 if (aphy == NULL)
640 continue;
641 nskb = skb_copy(skb, GFP_ATOMIC);
642 if (nskb)
643 __ieee80211_rx(aphy->hw, nskb,
644 &rx_status);
645 }
646 __ieee80211_rx(sc->hw, skb, &rx_status);
647 } else {
648 /* Deliver unicast frames based on receiver address */
649 __ieee80211_rx(ath_get_virt_hw(sc, hdr), skb,
650 &rx_status);
651 }
615 652
616 /* We will now give hardware our shiny new allocated skb */ 653 /* We will now give hardware our shiny new allocated skb */
617 bf->bf_mpdu = requeue_skb; 654 bf->bf_mpdu = requeue_skb;