diff options
author | Jouni Malinen <jouni.malinen@atheros.com> | 2009-03-03 12:23:26 -0500 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2009-03-05 14:39:44 -0500 |
commit | 2c3db3d51ee1fcf84f5828788905a4c091b9ae27 (patch) | |
tree | 44df855975d0848f15821cc285cbd5d7c8bf3feb /drivers/net/wireless/ath9k/main.c | |
parent | 860559fe686b44a533c83c79fe5d1ad41bf9e090 (diff) |
ath9k: Cleanup multiple VIF processing
Replace the internal sc_vaps array and index values by using vif
pointer from mac80211. Allow multiple VIPs to be registered. Though,
number of beaconing VIFs is still limited by ATH_BCBUF (currently
1). Multiple virtual STAs support is not yet complete, but at least
the data structures should now be able to handle this.
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 | 54 |
1 files changed, 32 insertions, 22 deletions
diff --git a/drivers/net/wireless/ath9k/main.c b/drivers/net/wireless/ath9k/main.c index b7a3523e6ed8..e43cee7907b2 100644 --- a/drivers/net/wireless/ath9k/main.c +++ b/drivers/net/wireless/ath9k/main.c | |||
@@ -800,13 +800,10 @@ static int ath_key_config(struct ath_softc *sc, | |||
800 | * need to change with virtual interfaces. */ | 800 | * need to change with virtual interfaces. */ |
801 | idx = key->keyidx; | 801 | idx = key->keyidx; |
802 | } else if (key->keyidx) { | 802 | } else if (key->keyidx) { |
803 | struct ieee80211_vif *vif; | ||
804 | |||
805 | if (WARN_ON(!sta)) | 803 | if (WARN_ON(!sta)) |
806 | return -EOPNOTSUPP; | 804 | return -EOPNOTSUPP; |
807 | mac = sta->addr; | 805 | mac = sta->addr; |
808 | 806 | ||
809 | vif = sc->vifs[0]; | ||
810 | if (vif->type != NL80211_IFTYPE_AP) { | 807 | if (vif->type != NL80211_IFTYPE_AP) { |
811 | /* Only keyidx 0 should be used with unicast key, but | 808 | /* Only keyidx 0 should be used with unicast key, but |
812 | * allow this for client mode for now. */ | 809 | * allow this for client mode for now. */ |
@@ -915,7 +912,7 @@ static void ath9k_bss_assoc_info(struct ath_softc *sc, | |||
915 | } | 912 | } |
916 | 913 | ||
917 | /* Configure the beacon */ | 914 | /* Configure the beacon */ |
918 | ath_beacon_config(sc, 0); | 915 | ath_beacon_config(sc, vif); |
919 | 916 | ||
920 | /* Reset rssi stats */ | 917 | /* Reset rssi stats */ |
921 | sc->nodestats.ns_avgbrssi = ATH_RSSI_DUMMY_MARKER; | 918 | sc->nodestats.ns_avgbrssi = ATH_RSSI_DUMMY_MARKER; |
@@ -1120,7 +1117,7 @@ static void ath_radio_enable(struct ath_softc *sc) | |||
1120 | } | 1117 | } |
1121 | 1118 | ||
1122 | if (sc->sc_flags & SC_OP_BEACONS) | 1119 | if (sc->sc_flags & SC_OP_BEACONS) |
1123 | ath_beacon_config(sc, ATH_IF_ID_ANY); /* restart beacons */ | 1120 | ath_beacon_config(sc, NULL); /* restart beacons */ |
1124 | 1121 | ||
1125 | /* Re-Enable interrupts */ | 1122 | /* Re-Enable interrupts */ |
1126 | ath9k_hw_set_interrupts(ah, sc->imask); | 1123 | ath9k_hw_set_interrupts(ah, sc->imask); |
@@ -1527,7 +1524,7 @@ static int ath_init(u16 devid, struct ath_softc *sc) | |||
1527 | 1524 | ||
1528 | /* initialize beacon slots */ | 1525 | /* initialize beacon slots */ |
1529 | for (i = 0; i < ARRAY_SIZE(sc->beacon.bslot); i++) | 1526 | for (i = 0; i < ARRAY_SIZE(sc->beacon.bslot); i++) |
1530 | sc->beacon.bslot[i] = ATH_IF_ID_ANY; | 1527 | sc->beacon.bslot[i] = NULL; |
1531 | 1528 | ||
1532 | /* save MISC configurations */ | 1529 | /* save MISC configurations */ |
1533 | sc->config.swBeaconProcess = 1; | 1530 | sc->config.swBeaconProcess = 1; |
@@ -1715,7 +1712,7 @@ int ath_reset(struct ath_softc *sc, bool retry_tx) | |||
1715 | ath_update_txpow(sc); | 1712 | ath_update_txpow(sc); |
1716 | 1713 | ||
1717 | if (sc->sc_flags & SC_OP_BEACONS) | 1714 | if (sc->sc_flags & SC_OP_BEACONS) |
1718 | ath_beacon_config(sc, ATH_IF_ID_ANY); /* restart beacons */ | 1715 | ath_beacon_config(sc, NULL); /* restart beacons */ |
1719 | 1716 | ||
1720 | ath9k_hw_set_interrupts(ah, sc->imask); | 1717 | ath9k_hw_set_interrupts(ah, sc->imask); |
1721 | 1718 | ||
@@ -2127,11 +2124,7 @@ static int ath9k_add_interface(struct ieee80211_hw *hw, | |||
2127 | struct ath_softc *sc = hw->priv; | 2124 | struct ath_softc *sc = hw->priv; |
2128 | struct ath_vif *avp = (void *)conf->vif->drv_priv; | 2125 | struct ath_vif *avp = (void *)conf->vif->drv_priv; |
2129 | enum nl80211_iftype ic_opmode = NL80211_IFTYPE_UNSPECIFIED; | 2126 | enum nl80211_iftype ic_opmode = NL80211_IFTYPE_UNSPECIFIED; |
2130 | 2127 | int ret = 0; | |
2131 | /* Support only vif for now */ | ||
2132 | |||
2133 | if (sc->nvifs) | ||
2134 | return -ENOBUFS; | ||
2135 | 2128 | ||
2136 | mutex_lock(&sc->mutex); | 2129 | mutex_lock(&sc->mutex); |
2137 | 2130 | ||
@@ -2140,16 +2133,24 @@ static int ath9k_add_interface(struct ieee80211_hw *hw, | |||
2140 | ic_opmode = NL80211_IFTYPE_STATION; | 2133 | ic_opmode = NL80211_IFTYPE_STATION; |
2141 | break; | 2134 | break; |
2142 | case NL80211_IFTYPE_ADHOC: | 2135 | case NL80211_IFTYPE_ADHOC: |
2136 | if (sc->nbcnvifs >= ATH_BCBUF) { | ||
2137 | ret = -ENOBUFS; | ||
2138 | goto out; | ||
2139 | } | ||
2143 | ic_opmode = NL80211_IFTYPE_ADHOC; | 2140 | ic_opmode = NL80211_IFTYPE_ADHOC; |
2144 | break; | 2141 | break; |
2145 | case NL80211_IFTYPE_AP: | 2142 | case NL80211_IFTYPE_AP: |
2143 | if (sc->nbcnvifs >= ATH_BCBUF) { | ||
2144 | ret = -ENOBUFS; | ||
2145 | goto out; | ||
2146 | } | ||
2146 | ic_opmode = NL80211_IFTYPE_AP; | 2147 | ic_opmode = NL80211_IFTYPE_AP; |
2147 | break; | 2148 | break; |
2148 | default: | 2149 | default: |
2149 | DPRINTF(sc, ATH_DBG_FATAL, | 2150 | DPRINTF(sc, ATH_DBG_FATAL, |
2150 | "Interface type %d not yet supported\n", conf->type); | 2151 | "Interface type %d not yet supported\n", conf->type); |
2151 | mutex_unlock(&sc->mutex); | 2152 | ret = -EOPNOTSUPP; |
2152 | return -EOPNOTSUPP; | 2153 | goto out; |
2153 | } | 2154 | } |
2154 | 2155 | ||
2155 | DPRINTF(sc, ATH_DBG_CONFIG, "Attach a VIF of type: %d\n", ic_opmode); | 2156 | DPRINTF(sc, ATH_DBG_CONFIG, "Attach a VIF of type: %d\n", ic_opmode); |
@@ -2158,14 +2159,15 @@ static int ath9k_add_interface(struct ieee80211_hw *hw, | |||
2158 | avp->av_opmode = ic_opmode; | 2159 | avp->av_opmode = ic_opmode; |
2159 | avp->av_bslot = -1; | 2160 | avp->av_bslot = -1; |
2160 | 2161 | ||
2162 | sc->nvifs++; | ||
2163 | if (sc->nvifs > 1) | ||
2164 | goto out; /* skip global settings for secondary vif */ | ||
2165 | |||
2161 | if (ic_opmode == NL80211_IFTYPE_AP) { | 2166 | if (ic_opmode == NL80211_IFTYPE_AP) { |
2162 | ath9k_hw_set_tsfadjust(sc->sc_ah, 1); | 2167 | ath9k_hw_set_tsfadjust(sc->sc_ah, 1); |
2163 | sc->sc_flags |= SC_OP_TSF_RESET; | 2168 | sc->sc_flags |= SC_OP_TSF_RESET; |
2164 | } | 2169 | } |
2165 | 2170 | ||
2166 | sc->vifs[0] = conf->vif; | ||
2167 | sc->nvifs++; | ||
2168 | |||
2169 | /* Set the device opmode */ | 2171 | /* Set the device opmode */ |
2170 | sc->sc_ah->opmode = ic_opmode; | 2172 | sc->sc_ah->opmode = ic_opmode; |
2171 | 2173 | ||
@@ -2200,9 +2202,9 @@ static int ath9k_add_interface(struct ieee80211_hw *hw, | |||
2200 | jiffies + msecs_to_jiffies(ATH_ANI_POLLINTERVAL)); | 2202 | jiffies + msecs_to_jiffies(ATH_ANI_POLLINTERVAL)); |
2201 | } | 2203 | } |
2202 | 2204 | ||
2205 | out: | ||
2203 | mutex_unlock(&sc->mutex); | 2206 | mutex_unlock(&sc->mutex); |
2204 | 2207 | return ret; | |
2205 | return 0; | ||
2206 | } | 2208 | } |
2207 | 2209 | ||
2208 | static void ath9k_remove_interface(struct ieee80211_hw *hw, | 2210 | static void ath9k_remove_interface(struct ieee80211_hw *hw, |
@@ -2210,6 +2212,7 @@ static void ath9k_remove_interface(struct ieee80211_hw *hw, | |||
2210 | { | 2212 | { |
2211 | struct ath_softc *sc = hw->priv; | 2213 | struct ath_softc *sc = hw->priv; |
2212 | struct ath_vif *avp = (void *)conf->vif->drv_priv; | 2214 | struct ath_vif *avp = (void *)conf->vif->drv_priv; |
2215 | int i; | ||
2213 | 2216 | ||
2214 | DPRINTF(sc, ATH_DBG_CONFIG, "Detach Interface\n"); | 2217 | DPRINTF(sc, ATH_DBG_CONFIG, "Detach Interface\n"); |
2215 | 2218 | ||
@@ -2227,7 +2230,14 @@ static void ath9k_remove_interface(struct ieee80211_hw *hw, | |||
2227 | 2230 | ||
2228 | sc->sc_flags &= ~SC_OP_BEACONS; | 2231 | sc->sc_flags &= ~SC_OP_BEACONS; |
2229 | 2232 | ||
2230 | sc->vifs[0] = NULL; | 2233 | for (i = 0; i < ARRAY_SIZE(sc->beacon.bslot); i++) { |
2234 | if (sc->beacon.bslot[i] == conf->vif) { | ||
2235 | printk(KERN_DEBUG "%s: vif had allocated beacon " | ||
2236 | "slot\n", __func__); | ||
2237 | sc->beacon.bslot[i] = NULL; | ||
2238 | } | ||
2239 | } | ||
2240 | |||
2231 | sc->nvifs--; | 2241 | sc->nvifs--; |
2232 | 2242 | ||
2233 | mutex_unlock(&sc->mutex); | 2243 | mutex_unlock(&sc->mutex); |
@@ -2364,13 +2374,13 @@ static int ath9k_config_interface(struct ieee80211_hw *hw, | |||
2364 | */ | 2374 | */ |
2365 | ath9k_hw_stoptxdma(sc->sc_ah, sc->beacon.beaconq); | 2375 | ath9k_hw_stoptxdma(sc->sc_ah, sc->beacon.beaconq); |
2366 | 2376 | ||
2367 | error = ath_beacon_alloc(sc, 0); | 2377 | error = ath_beacon_alloc(sc, vif); |
2368 | if (error != 0) { | 2378 | if (error != 0) { |
2369 | mutex_unlock(&sc->mutex); | 2379 | mutex_unlock(&sc->mutex); |
2370 | return error; | 2380 | return error; |
2371 | } | 2381 | } |
2372 | 2382 | ||
2373 | ath_beacon_config(sc, 0); | 2383 | ath_beacon_config(sc, vif); |
2374 | } | 2384 | } |
2375 | } | 2385 | } |
2376 | 2386 | ||