aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
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
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')
-rw-r--r--drivers/net/wireless/ath9k/ath9k.h15
-rw-r--r--drivers/net/wireless/ath9k/beacon.c21
-rw-r--r--drivers/net/wireless/ath9k/main.c65
-rw-r--r--drivers/net/wireless/ath9k/rc.h1
-rw-r--r--drivers/net/wireless/ath9k/recv.c41
-rw-r--r--drivers/net/wireless/ath9k/virtual.c90
-rw-r--r--drivers/net/wireless/ath9k/xmit.c20
7 files changed, 212 insertions, 41 deletions
diff --git a/drivers/net/wireless/ath9k/ath9k.h b/drivers/net/wireless/ath9k/ath9k.h
index 41eeac42a80c..386b93622e58 100644
--- a/drivers/net/wireless/ath9k/ath9k.h
+++ b/drivers/net/wireless/ath9k/ath9k.h
@@ -373,10 +373,10 @@ int ath_tx_cleanup(struct ath_softc *sc);
373struct ath_txq *ath_test_get_txq(struct ath_softc *sc, struct sk_buff *skb); 373struct ath_txq *ath_test_get_txq(struct ath_softc *sc, struct sk_buff *skb);
374int ath_txq_update(struct ath_softc *sc, int qnum, 374int ath_txq_update(struct ath_softc *sc, int qnum,
375 struct ath9k_tx_queue_info *q); 375 struct ath9k_tx_queue_info *q);
376int ath_tx_start(struct ath_softc *sc, struct sk_buff *skb, 376int ath_tx_start(struct ieee80211_hw *hw, struct sk_buff *skb,
377 struct ath_tx_control *txctl); 377 struct ath_tx_control *txctl);
378void ath_tx_tasklet(struct ath_softc *sc); 378void ath_tx_tasklet(struct ath_softc *sc);
379void ath_tx_cabq(struct ath_softc *sc, struct sk_buff *skb); 379void ath_tx_cabq(struct ieee80211_hw *hw, struct sk_buff *skb);
380bool ath_tx_aggr_check(struct ath_softc *sc, struct ath_node *an, u8 tidno); 380bool ath_tx_aggr_check(struct ath_softc *sc, struct ath_node *an, u8 tidno);
381int ath_tx_aggr_start(struct ath_softc *sc, struct ieee80211_sta *sta, 381int ath_tx_aggr_start(struct ath_softc *sc, struct ieee80211_sta *sta,
382 u16 tid, u16 *ssn); 382 u16 tid, u16 *ssn);
@@ -429,6 +429,7 @@ struct ath_beacon {
429 u32 ast_be_xmit; 429 u32 ast_be_xmit;
430 u64 bc_tstamp; 430 u64 bc_tstamp;
431 struct ieee80211_vif *bslot[ATH_BCBUF]; 431 struct ieee80211_vif *bslot[ATH_BCBUF];
432 struct ath_wiphy *bslot_aphy[ATH_BCBUF];
432 int slottime; 433 int slottime;
433 int slotupdate; 434 int slotupdate;
434 struct ath9k_tx_queue_info beacon_qi; 435 struct ath9k_tx_queue_info beacon_qi;
@@ -440,7 +441,7 @@ struct ath_beacon {
440void ath_beacon_tasklet(unsigned long data); 441void ath_beacon_tasklet(unsigned long data);
441void ath_beacon_config(struct ath_softc *sc, struct ieee80211_vif *vif); 442void ath_beacon_config(struct ath_softc *sc, struct ieee80211_vif *vif);
442int ath_beaconq_setup(struct ath_hw *ah); 443int ath_beaconq_setup(struct ath_hw *ah);
443int ath_beacon_alloc(struct ath_softc *sc, struct ieee80211_vif *vif); 444int ath_beacon_alloc(struct ath_wiphy *aphy, struct ieee80211_vif *vif);
444void ath_beacon_return(struct ath_softc *sc, struct ath_vif *avp); 445void ath_beacon_return(struct ath_softc *sc, struct ath_vif *avp);
445 446
446/*******/ 447/*******/
@@ -554,7 +555,12 @@ struct ath_wiphy;
554struct ath_softc { 555struct ath_softc {
555 struct ieee80211_hw *hw; 556 struct ieee80211_hw *hw;
556 struct device *dev; 557 struct device *dev;
558
559 spinlock_t wiphy_lock; /* spinlock to protect ath_wiphy data */
557 struct ath_wiphy *pri_wiphy; 560 struct ath_wiphy *pri_wiphy;
561 struct ath_wiphy **sec_wiphy; /* secondary wiphys (virtual radios); may
562 * have NULL entries */
563 int num_sec_wiphy; /* number of sec_wiphy pointers in the array */
558 struct tasklet_struct intr_tq; 564 struct tasklet_struct intr_tq;
559 struct tasklet_struct bcon_tasklet; 565 struct tasklet_struct bcon_tasklet;
560 struct ath_hw *sc_ah; 566 struct ath_hw *sc_ah;
@@ -638,6 +644,7 @@ int ath_attach(u16 devid, struct ath_softc *sc);
638void ath_detach(struct ath_softc *sc); 644void ath_detach(struct ath_softc *sc);
639const char *ath_mac_bb_name(u32 mac_bb_version); 645const char *ath_mac_bb_name(u32 mac_bb_version);
640const char *ath_rf_name(u16 rf_version); 646const char *ath_rf_name(u16 rf_version);
647void ath_set_hw_capab(struct ath_softc *sc, struct ieee80211_hw *hw);
641 648
642#ifdef CONFIG_PCI 649#ifdef CONFIG_PCI
643int ath_pci_init(void); 650int ath_pci_init(void);
@@ -675,5 +682,7 @@ static inline void ath9k_ps_restore(struct ath_softc *sc)
675 682
676 683
677void ath9k_set_bssid_mask(struct ieee80211_hw *hw); 684void ath9k_set_bssid_mask(struct ieee80211_hw *hw);
685int ath9k_wiphy_add(struct ath_softc *sc);
686int ath9k_wiphy_del(struct ath_wiphy *aphy);
678 687
679#endif /* ATH9K_H */ 688#endif /* ATH9K_H */
diff --git a/drivers/net/wireless/ath9k/beacon.c b/drivers/net/wireless/ath9k/beacon.c
index 357d797e79c1..760f5b80f79e 100644
--- a/drivers/net/wireless/ath9k/beacon.c
+++ b/drivers/net/wireless/ath9k/beacon.c
@@ -113,9 +113,11 @@ static void ath_beacon_setup(struct ath_softc *sc, struct ath_vif *avp,
113 series, 4, 0); 113 series, 4, 0);
114} 114}
115 115
116static struct ath_buf *ath_beacon_generate(struct ath_softc *sc, 116static struct ath_buf *ath_beacon_generate(struct ieee80211_hw *hw,
117 struct ieee80211_vif *vif) 117 struct ieee80211_vif *vif)
118{ 118{
119 struct ath_wiphy *aphy = hw->priv;
120 struct ath_softc *sc = aphy->sc;
119 struct ath_buf *bf; 121 struct ath_buf *bf;
120 struct ath_vif *avp; 122 struct ath_vif *avp;
121 struct sk_buff *skb; 123 struct sk_buff *skb;
@@ -144,7 +146,7 @@ static struct ath_buf *ath_beacon_generate(struct ath_softc *sc,
144 146
145 /* Get a new beacon from mac80211 */ 147 /* Get a new beacon from mac80211 */
146 148
147 skb = ieee80211_beacon_get(sc->hw, vif); 149 skb = ieee80211_beacon_get(hw, vif);
148 bf->bf_mpdu = skb; 150 bf->bf_mpdu = skb;
149 if (skb == NULL) 151 if (skb == NULL)
150 return NULL; 152 return NULL;
@@ -171,7 +173,7 @@ static struct ath_buf *ath_beacon_generate(struct ath_softc *sc,
171 return NULL; 173 return NULL;
172 } 174 }
173 175
174 skb = ieee80211_get_buffered_bc(sc->hw, vif); 176 skb = ieee80211_get_buffered_bc(hw, vif);
175 177
176 /* 178 /*
177 * if the CABQ traffic from previous DTIM is pending and the current 179 * if the CABQ traffic from previous DTIM is pending and the current
@@ -196,8 +198,8 @@ static struct ath_buf *ath_beacon_generate(struct ath_softc *sc,
196 ath_beacon_setup(sc, avp, bf); 198 ath_beacon_setup(sc, avp, bf);
197 199
198 while (skb) { 200 while (skb) {
199 ath_tx_cabq(sc, skb); 201 ath_tx_cabq(hw, skb);
200 skb = ieee80211_get_buffered_bc(sc->hw, vif); 202 skb = ieee80211_get_buffered_bc(hw, vif);
201 } 203 }
202 204
203 return bf; 205 return bf;
@@ -244,8 +246,9 @@ int ath_beaconq_setup(struct ath_hw *ah)
244 return ath9k_hw_setuptxqueue(ah, ATH9K_TX_QUEUE_BEACON, &qi); 246 return ath9k_hw_setuptxqueue(ah, ATH9K_TX_QUEUE_BEACON, &qi);
245} 247}
246 248
247int ath_beacon_alloc(struct ath_softc *sc, struct ieee80211_vif *vif) 249int ath_beacon_alloc(struct ath_wiphy *aphy, struct ieee80211_vif *vif)
248{ 250{
251 struct ath_softc *sc = aphy->sc;
249 struct ath_vif *avp; 252 struct ath_vif *avp;
250 struct ieee80211_hdr *hdr; 253 struct ieee80211_hdr *hdr;
251 struct ath_buf *bf; 254 struct ath_buf *bf;
@@ -286,6 +289,7 @@ int ath_beacon_alloc(struct ath_softc *sc, struct ieee80211_vif *vif)
286 } 289 }
287 BUG_ON(sc->beacon.bslot[avp->av_bslot] != NULL); 290 BUG_ON(sc->beacon.bslot[avp->av_bslot] != NULL);
288 sc->beacon.bslot[avp->av_bslot] = vif; 291 sc->beacon.bslot[avp->av_bslot] = vif;
292 sc->beacon.bslot_aphy[avp->av_bslot] = aphy;
289 sc->nbcnvifs++; 293 sc->nbcnvifs++;
290 } 294 }
291 } 295 }
@@ -368,6 +372,7 @@ void ath_beacon_return(struct ath_softc *sc, struct ath_vif *avp)
368 372
369 if (avp->av_bslot != -1) { 373 if (avp->av_bslot != -1) {
370 sc->beacon.bslot[avp->av_bslot] = NULL; 374 sc->beacon.bslot[avp->av_bslot] = NULL;
375 sc->beacon.bslot_aphy[avp->av_bslot] = NULL;
371 sc->nbcnvifs--; 376 sc->nbcnvifs--;
372 } 377 }
373 378
@@ -391,6 +396,7 @@ void ath_beacon_tasklet(unsigned long data)
391 struct ath_hw *ah = sc->sc_ah; 396 struct ath_hw *ah = sc->sc_ah;
392 struct ath_buf *bf = NULL; 397 struct ath_buf *bf = NULL;
393 struct ieee80211_vif *vif; 398 struct ieee80211_vif *vif;
399 struct ath_wiphy *aphy;
394 int slot; 400 int slot;
395 u32 bfaddr, bc = 0, tsftu; 401 u32 bfaddr, bc = 0, tsftu;
396 u64 tsf; 402 u64 tsf;
@@ -439,6 +445,7 @@ void ath_beacon_tasklet(unsigned long data)
439 tsftu = TSF_TO_TU(tsf>>32, tsf); 445 tsftu = TSF_TO_TU(tsf>>32, tsf);
440 slot = ((tsftu % intval) * ATH_BCBUF) / intval; 446 slot = ((tsftu % intval) * ATH_BCBUF) / intval;
441 vif = sc->beacon.bslot[(slot + 1) % ATH_BCBUF]; 447 vif = sc->beacon.bslot[(slot + 1) % ATH_BCBUF];
448 aphy = sc->beacon.bslot_aphy[(slot + 1) % ATH_BCBUF];
442 449
443 DPRINTF(sc, ATH_DBG_BEACON, 450 DPRINTF(sc, ATH_DBG_BEACON,
444 "slot %d [tsf %llu tsftu %u intval %u] vif %p\n", 451 "slot %d [tsf %llu tsftu %u intval %u] vif %p\n",
@@ -446,7 +453,7 @@ void ath_beacon_tasklet(unsigned long data)
446 453
447 bfaddr = 0; 454 bfaddr = 0;
448 if (vif) { 455 if (vif) {
449 bf = ath_beacon_generate(sc, vif); 456 bf = ath_beacon_generate(aphy->hw, vif);
450 if (bf != NULL) { 457 if (bf != NULL) {
451 bfaddr = bf->bf_daddr; 458 bfaddr = bf->bf_daddr;
452 bc = 1; 459 bc = 1;
diff --git a/drivers/net/wireless/ath9k/main.c b/drivers/net/wireless/ath9k/main.c
index 0c0e587d7942..433a11c41838 100644
--- a/drivers/net/wireless/ath9k/main.c
+++ b/drivers/net/wireless/ath9k/main.c
@@ -1307,6 +1307,7 @@ void ath_cleanup(struct ath_softc *sc)
1307 ath_detach(sc); 1307 ath_detach(sc);
1308 free_irq(sc->irq, sc); 1308 free_irq(sc->irq, sc);
1309 ath_bus_cleanup(sc); 1309 ath_bus_cleanup(sc);
1310 kfree(sc->sec_wiphy);
1310 ieee80211_free_hw(sc->hw); 1311 ieee80211_free_hw(sc->hw);
1311} 1312}
1312 1313
@@ -1324,6 +1325,14 @@ void ath_detach(struct ath_softc *sc)
1324#endif 1325#endif
1325 ath_deinit_leds(sc); 1326 ath_deinit_leds(sc);
1326 1327
1328 for (i = 0; i < sc->num_sec_wiphy; i++) {
1329 struct ath_wiphy *aphy = sc->sec_wiphy[i];
1330 if (aphy == NULL)
1331 continue;
1332 sc->sec_wiphy[i] = NULL;
1333 ieee80211_unregister_hw(aphy->hw);
1334 ieee80211_free_hw(aphy->hw);
1335 }
1327 ieee80211_unregister_hw(hw); 1336 ieee80211_unregister_hw(hw);
1328 ath_rx_cleanup(sc); 1337 ath_rx_cleanup(sc);
1329 ath_tx_cleanup(sc); 1338 ath_tx_cleanup(sc);
@@ -1357,6 +1366,7 @@ static int ath_init(u16 devid, struct ath_softc *sc)
1357 if (ath9k_init_debug(sc) < 0) 1366 if (ath9k_init_debug(sc) < 0)
1358 printk(KERN_ERR "Unable to create debugfs files\n"); 1367 printk(KERN_ERR "Unable to create debugfs files\n");
1359 1368
1369 spin_lock_init(&sc->wiphy_lock);
1360 spin_lock_init(&sc->sc_resetlock); 1370 spin_lock_init(&sc->sc_resetlock);
1361 mutex_init(&sc->mutex); 1371 mutex_init(&sc->mutex);
1362 tasklet_init(&sc->intr_tq, ath9k_tasklet, (unsigned long)sc); 1372 tasklet_init(&sc->intr_tq, ath9k_tasklet, (unsigned long)sc);
@@ -1520,8 +1530,10 @@ static int ath_init(u16 devid, struct ath_softc *sc)
1520 sc->beacon.slottime = ATH9K_SLOT_TIME_9; /* default to short slot time */ 1530 sc->beacon.slottime = ATH9K_SLOT_TIME_9; /* default to short slot time */
1521 1531
1522 /* initialize beacon slots */ 1532 /* initialize beacon slots */
1523 for (i = 0; i < ARRAY_SIZE(sc->beacon.bslot); i++) 1533 for (i = 0; i < ARRAY_SIZE(sc->beacon.bslot); i++) {
1524 sc->beacon.bslot[i] = NULL; 1534 sc->beacon.bslot[i] = NULL;
1535 sc->beacon.bslot_aphy[i] = NULL;
1536 }
1525 1537
1526 /* save MISC configurations */ 1538 /* save MISC configurations */
1527 sc->config.swBeaconProcess = 1; 1539 sc->config.swBeaconProcess = 1;
@@ -1561,22 +1573,8 @@ bad:
1561 return error; 1573 return error;
1562} 1574}
1563 1575
1564int ath_attach(u16 devid, struct ath_softc *sc) 1576void ath_set_hw_capab(struct ath_softc *sc, struct ieee80211_hw *hw)
1565{ 1577{
1566 struct ieee80211_hw *hw = sc->hw;
1567 const struct ieee80211_regdomain *regd;
1568 int error = 0, i;
1569
1570 DPRINTF(sc, ATH_DBG_CONFIG, "Attach ATH hw\n");
1571
1572 error = ath_init(devid, sc);
1573 if (error != 0)
1574 return error;
1575
1576 /* get mac address from hardware and set in mac80211 */
1577
1578 SET_IEEE80211_PERM_ADDR(hw, sc->sc_ah->macaddr);
1579
1580 hw->flags = IEEE80211_HW_RX_INCLUDES_FCS | 1578 hw->flags = IEEE80211_HW_RX_INCLUDES_FCS |
1581 IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING | 1579 IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING |
1582 IEEE80211_HW_SIGNAL_DBM | 1580 IEEE80211_HW_SIGNAL_DBM |
@@ -1604,17 +1602,37 @@ int ath_attach(u16 devid, struct ath_softc *sc)
1604 1602
1605 hw->rate_control_algorithm = "ath9k_rate_control"; 1603 hw->rate_control_algorithm = "ath9k_rate_control";
1606 1604
1605 hw->wiphy->bands[IEEE80211_BAND_2GHZ] =
1606 &sc->sbands[IEEE80211_BAND_2GHZ];
1607 if (test_bit(ATH9K_MODE_11A, sc->sc_ah->caps.wireless_modes))
1608 hw->wiphy->bands[IEEE80211_BAND_5GHZ] =
1609 &sc->sbands[IEEE80211_BAND_5GHZ];
1610}
1611
1612int ath_attach(u16 devid, struct ath_softc *sc)
1613{
1614 struct ieee80211_hw *hw = sc->hw;
1615 const struct ieee80211_regdomain *regd;
1616 int error = 0, i;
1617
1618 DPRINTF(sc, ATH_DBG_CONFIG, "Attach ATH hw\n");
1619
1620 error = ath_init(devid, sc);
1621 if (error != 0)
1622 return error;
1623
1624 /* get mac address from hardware and set in mac80211 */
1625
1626 SET_IEEE80211_PERM_ADDR(hw, sc->sc_ah->macaddr);
1627
1628 ath_set_hw_capab(sc, hw);
1629
1607 if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_HT) { 1630 if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_HT) {
1608 setup_ht_cap(sc, &sc->sbands[IEEE80211_BAND_2GHZ].ht_cap); 1631 setup_ht_cap(sc, &sc->sbands[IEEE80211_BAND_2GHZ].ht_cap);
1609 if (test_bit(ATH9K_MODE_11A, sc->sc_ah->caps.wireless_modes)) 1632 if (test_bit(ATH9K_MODE_11A, sc->sc_ah->caps.wireless_modes))
1610 setup_ht_cap(sc, &sc->sbands[IEEE80211_BAND_5GHZ].ht_cap); 1633 setup_ht_cap(sc, &sc->sbands[IEEE80211_BAND_5GHZ].ht_cap);
1611 } 1634 }
1612 1635
1613 hw->wiphy->bands[IEEE80211_BAND_2GHZ] = &sc->sbands[IEEE80211_BAND_2GHZ];
1614 if (test_bit(ATH9K_MODE_11A, sc->sc_ah->caps.wireless_modes))
1615 hw->wiphy->bands[IEEE80211_BAND_5GHZ] =
1616 &sc->sbands[IEEE80211_BAND_5GHZ];
1617
1618 /* initialize tx/rx engine */ 1636 /* initialize tx/rx engine */
1619 error = ath_tx_init(sc, ATH_TXBUF); 1637 error = ath_tx_init(sc, ATH_TXBUF);
1620 if (error != 0) 1638 if (error != 0)
@@ -2067,7 +2085,7 @@ static int ath9k_tx(struct ieee80211_hw *hw,
2067 2085
2068 DPRINTF(sc, ATH_DBG_XMIT, "transmitting packet, skb: %p\n", skb); 2086 DPRINTF(sc, ATH_DBG_XMIT, "transmitting packet, skb: %p\n", skb);
2069 2087
2070 if (ath_tx_start(sc, skb, &txctl) != 0) { 2088 if (ath_tx_start(hw, skb, &txctl) != 0) {
2071 DPRINTF(sc, ATH_DBG_XMIT, "TX failed\n"); 2089 DPRINTF(sc, ATH_DBG_XMIT, "TX failed\n");
2072 goto exit; 2090 goto exit;
2073 } 2091 }
@@ -2247,6 +2265,7 @@ static void ath9k_remove_interface(struct ieee80211_hw *hw,
2247 printk(KERN_DEBUG "%s: vif had allocated beacon " 2265 printk(KERN_DEBUG "%s: vif had allocated beacon "
2248 "slot\n", __func__); 2266 "slot\n", __func__);
2249 sc->beacon.bslot[i] = NULL; 2267 sc->beacon.bslot[i] = NULL;
2268 sc->beacon.bslot_aphy[i] = NULL;
2250 } 2269 }
2251 } 2270 }
2252 2271
@@ -2388,7 +2407,7 @@ static int ath9k_config_interface(struct ieee80211_hw *hw,
2388 */ 2407 */
2389 ath9k_hw_stoptxdma(sc->sc_ah, sc->beacon.beaconq); 2408 ath9k_hw_stoptxdma(sc->sc_ah, sc->beacon.beaconq);
2390 2409
2391 error = ath_beacon_alloc(sc, vif); 2410 error = ath_beacon_alloc(aphy, vif);
2392 if (error != 0) { 2411 if (error != 0) {
2393 mutex_unlock(&sc->mutex); 2412 mutex_unlock(&sc->mutex);
2394 return error; 2413 return error;
diff --git a/drivers/net/wireless/ath9k/rc.h b/drivers/net/wireless/ath9k/rc.h
index a6dc82d92612..0584122341ad 100644
--- a/drivers/net/wireless/ath9k/rc.h
+++ b/drivers/net/wireless/ath9k/rc.h
@@ -195,6 +195,7 @@ struct ath_rate_priv {
195}; 195};
196 196
197struct ath_tx_info_priv { 197struct ath_tx_info_priv {
198 struct ath_wiphy *aphy;
198 struct ath_tx_status tx; 199 struct ath_tx_status tx;
199 int n_frames; 200 int n_frames;
200 int n_bad_frames; 201 int n_bad_frames;
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;
diff --git a/drivers/net/wireless/ath9k/virtual.c b/drivers/net/wireless/ath9k/virtual.c
index a91f2f1c911b..67bcb9343ca6 100644
--- a/drivers/net/wireless/ath9k/virtual.c
+++ b/drivers/net/wireless/ath9k/virtual.c
@@ -57,8 +57,16 @@ void ath9k_set_bssid_mask(struct ieee80211_hw *hw)
57 iter_data.count = 0; 57 iter_data.count = 0;
58 58
59 /* Get list of all active MAC addresses */ 59 /* Get list of all active MAC addresses */
60 ieee80211_iterate_active_interfaces_atomic(hw, ath9k_vif_iter, 60 spin_lock_bh(&sc->wiphy_lock);
61 ieee80211_iterate_active_interfaces_atomic(sc->hw, ath9k_vif_iter,
61 &iter_data); 62 &iter_data);
63 for (i = 0; i < sc->num_sec_wiphy; i++) {
64 if (sc->sec_wiphy[i] == NULL)
65 continue;
66 ieee80211_iterate_active_interfaces_atomic(
67 sc->sec_wiphy[i]->hw, ath9k_vif_iter, &iter_data);
68 }
69 spin_unlock_bh(&sc->wiphy_lock);
62 70
63 /* Generate an address mask to cover all active addresses */ 71 /* Generate an address mask to cover all active addresses */
64 memset(mask, 0, ETH_ALEN); 72 memset(mask, 0, ETH_ALEN);
@@ -87,3 +95,83 @@ void ath9k_set_bssid_mask(struct ieee80211_hw *hw)
87 95
88 ath9k_hw_setbssidmask(sc); 96 ath9k_hw_setbssidmask(sc);
89} 97}
98
99int ath9k_wiphy_add(struct ath_softc *sc)
100{
101 int i, error;
102 struct ath_wiphy *aphy;
103 struct ieee80211_hw *hw;
104 u8 addr[ETH_ALEN];
105
106 hw = ieee80211_alloc_hw(sizeof(struct ath_wiphy), &ath9k_ops);
107 if (hw == NULL)
108 return -ENOMEM;
109
110 spin_lock_bh(&sc->wiphy_lock);
111 for (i = 0; i < sc->num_sec_wiphy; i++) {
112 if (sc->sec_wiphy[i] == NULL)
113 break;
114 }
115
116 if (i == sc->num_sec_wiphy) {
117 /* No empty slot available; increase array length */
118 struct ath_wiphy **n;
119 n = krealloc(sc->sec_wiphy,
120 (sc->num_sec_wiphy + 1) *
121 sizeof(struct ath_wiphy *),
122 GFP_ATOMIC);
123 if (n == NULL) {
124 spin_unlock_bh(&sc->wiphy_lock);
125 ieee80211_free_hw(hw);
126 return -ENOMEM;
127 }
128 n[i] = NULL;
129 sc->sec_wiphy = n;
130 sc->num_sec_wiphy++;
131 }
132
133 SET_IEEE80211_DEV(hw, sc->dev);
134
135 aphy = hw->priv;
136 aphy->sc = sc;
137 aphy->hw = hw;
138 sc->sec_wiphy[i] = aphy;
139 spin_unlock_bh(&sc->wiphy_lock);
140
141 memcpy(addr, sc->sc_ah->macaddr, ETH_ALEN);
142 addr[0] |= 0x02; /* Locally managed address */
143 /*
144 * XOR virtual wiphy index into the least significant bits to generate
145 * a different MAC address for each virtual wiphy.
146 */
147 addr[5] ^= i & 0xff;
148 addr[4] ^= (i & 0xff00) >> 8;
149 addr[3] ^= (i & 0xff0000) >> 16;
150
151 SET_IEEE80211_PERM_ADDR(hw, addr);
152
153 ath_set_hw_capab(sc, hw);
154
155 error = ieee80211_register_hw(hw);
156
157 return error;
158}
159
160int ath9k_wiphy_del(struct ath_wiphy *aphy)
161{
162 struct ath_softc *sc = aphy->sc;
163 int i;
164
165 spin_lock_bh(&sc->wiphy_lock);
166 for (i = 0; i < sc->num_sec_wiphy; i++) {
167 if (aphy == sc->sec_wiphy[i]) {
168 sc->sec_wiphy[i] = NULL;
169 spin_unlock_bh(&sc->wiphy_lock);
170 ieee80211_unregister_hw(aphy->hw);
171 ieee80211_free_hw(aphy->hw);
172 return 0;
173 }
174 }
175 spin_unlock_bh(&sc->wiphy_lock);
176 return -ENOENT;
177}
diff --git a/drivers/net/wireless/ath9k/xmit.c b/drivers/net/wireless/ath9k/xmit.c
index 363bb2a94d99..3c48fa5646f5 100644
--- a/drivers/net/wireless/ath9k/xmit.c
+++ b/drivers/net/wireless/ath9k/xmit.c
@@ -1497,10 +1497,12 @@ static void ath_buf_set_rate(struct ath_softc *sc, struct ath_buf *bf)
1497 ath9k_hw_set11n_burstduration(sc->sc_ah, bf->bf_desc, 8192); 1497 ath9k_hw_set11n_burstduration(sc->sc_ah, bf->bf_desc, 8192);
1498} 1498}
1499 1499
1500static int ath_tx_setup_buffer(struct ath_softc *sc, struct ath_buf *bf, 1500static int ath_tx_setup_buffer(struct ieee80211_hw *hw, struct ath_buf *bf,
1501 struct sk_buff *skb, 1501 struct sk_buff *skb,
1502 struct ath_tx_control *txctl) 1502 struct ath_tx_control *txctl)
1503{ 1503{
1504 struct ath_wiphy *aphy = hw->priv;
1505 struct ath_softc *sc = aphy->sc;
1504 struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb); 1506 struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb);
1505 struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; 1507 struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
1506 struct ath_tx_info_priv *tx_info_priv; 1508 struct ath_tx_info_priv *tx_info_priv;
@@ -1511,6 +1513,7 @@ static int ath_tx_setup_buffer(struct ath_softc *sc, struct ath_buf *bf,
1511 if (unlikely(!tx_info_priv)) 1513 if (unlikely(!tx_info_priv))
1512 return -ENOMEM; 1514 return -ENOMEM;
1513 tx_info->rate_driver_data[0] = tx_info_priv; 1515 tx_info->rate_driver_data[0] = tx_info_priv;
1516 tx_info_priv->aphy = aphy;
1514 hdrlen = ieee80211_get_hdrlen_from_skb(skb); 1517 hdrlen = ieee80211_get_hdrlen_from_skb(skb);
1515 fc = hdr->frame_control; 1518 fc = hdr->frame_control;
1516 1519
@@ -1614,9 +1617,11 @@ static void ath_tx_start_dma(struct ath_softc *sc, struct ath_buf *bf,
1614} 1617}
1615 1618
1616/* Upon failure caller should free skb */ 1619/* Upon failure caller should free skb */
1617int ath_tx_start(struct ath_softc *sc, struct sk_buff *skb, 1620int ath_tx_start(struct ieee80211_hw *hw, struct sk_buff *skb,
1618 struct ath_tx_control *txctl) 1621 struct ath_tx_control *txctl)
1619{ 1622{
1623 struct ath_wiphy *aphy = hw->priv;
1624 struct ath_softc *sc = aphy->sc;
1620 struct ath_buf *bf; 1625 struct ath_buf *bf;
1621 int r; 1626 int r;
1622 1627
@@ -1626,7 +1631,7 @@ int ath_tx_start(struct ath_softc *sc, struct sk_buff *skb,
1626 return -1; 1631 return -1;
1627 } 1632 }
1628 1633
1629 r = ath_tx_setup_buffer(sc, bf, skb, txctl); 1634 r = ath_tx_setup_buffer(hw, bf, skb, txctl);
1630 if (unlikely(r)) { 1635 if (unlikely(r)) {
1631 struct ath_txq *txq = txctl->txq; 1636 struct ath_txq *txq = txctl->txq;
1632 1637
@@ -1656,8 +1661,10 @@ int ath_tx_start(struct ath_softc *sc, struct sk_buff *skb,
1656 return 0; 1661 return 0;
1657} 1662}
1658 1663
1659void ath_tx_cabq(struct ath_softc *sc, struct sk_buff *skb) 1664void ath_tx_cabq(struct ieee80211_hw *hw, struct sk_buff *skb)
1660{ 1665{
1666 struct ath_wiphy *aphy = hw->priv;
1667 struct ath_softc *sc = aphy->sc;
1661 int hdrlen, padsize; 1668 int hdrlen, padsize;
1662 struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); 1669 struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
1663 struct ath_tx_control txctl; 1670 struct ath_tx_control txctl;
@@ -1694,7 +1701,7 @@ void ath_tx_cabq(struct ath_softc *sc, struct sk_buff *skb)
1694 1701
1695 DPRINTF(sc, ATH_DBG_XMIT, "transmitting CABQ packet, skb: %p\n", skb); 1702 DPRINTF(sc, ATH_DBG_XMIT, "transmitting CABQ packet, skb: %p\n", skb);
1696 1703
1697 if (ath_tx_start(sc, skb, &txctl) != 0) { 1704 if (ath_tx_start(hw, skb, &txctl) != 0) {
1698 DPRINTF(sc, ATH_DBG_XMIT, "CABQ TX failed\n"); 1705 DPRINTF(sc, ATH_DBG_XMIT, "CABQ TX failed\n");
1699 goto exit; 1706 goto exit;
1700 } 1707 }
@@ -1718,6 +1725,9 @@ static void ath_tx_complete(struct ath_softc *sc, struct sk_buff *skb,
1718 1725
1719 DPRINTF(sc, ATH_DBG_XMIT, "TX complete: skb: %p\n", skb); 1726 DPRINTF(sc, ATH_DBG_XMIT, "TX complete: skb: %p\n", skb);
1720 1727
1728 if (tx_info_priv)
1729 hw = tx_info_priv->aphy->hw;
1730
1721 if (tx_info->flags & IEEE80211_TX_CTL_NO_ACK || 1731 if (tx_info->flags & IEEE80211_TX_CTL_NO_ACK ||
1722 tx_info->flags & IEEE80211_TX_STAT_TX_FILTERED) { 1732 tx_info->flags & IEEE80211_TX_STAT_TX_FILTERED) {
1723 kfree(tx_info_priv); 1733 kfree(tx_info_priv);