diff options
author | Jouni Malinen <jouni.malinen@atheros.com> | 2009-03-03 12:23:29 -0500 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2009-03-05 14:39:45 -0500 |
commit | c52f33d05e5f8d59f02722fbc308f5f391575ca5 (patch) | |
tree | 19c6d56f3594e8b43d725b5d919bb775921fde38 /drivers/net/wireless/ath9k/main.c | |
parent | bce048d77dff3dcfd75d54dc38580c81baa95853 (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/main.c')
-rw-r--r-- | drivers/net/wireless/ath9k/main.c | 65 |
1 files changed, 42 insertions, 23 deletions
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 | ||
1564 | int ath_attach(u16 devid, struct ath_softc *sc) | 1576 | void 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 | |||
1612 | int 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; |