aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/ath9k
diff options
context:
space:
mode:
authorJouni Malinen <jouni.malinen@atheros.com>2009-03-03 12:23:26 -0500
committerJohn W. Linville <linville@tuxdriver.com>2009-03-05 14:39:44 -0500
commit2c3db3d51ee1fcf84f5828788905a4c091b9ae27 (patch)
tree44df855975d0848f15821cc285cbd5d7c8bf3feb /drivers/net/wireless/ath9k
parent860559fe686b44a533c83c79fe5d1ad41bf9e090 (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')
-rw-r--r--drivers/net/wireless/ath9k/ath9k.h8
-rw-r--r--drivers/net/wireless/ath9k/beacon.c54
-rw-r--r--drivers/net/wireless/ath9k/main.c54
3 files changed, 59 insertions, 57 deletions
diff --git a/drivers/net/wireless/ath9k/ath9k.h b/drivers/net/wireless/ath9k/ath9k.h
index ec1bf174c706..09b2b008feba 100644
--- a/drivers/net/wireless/ath9k/ath9k.h
+++ b/drivers/net/wireless/ath9k/ath9k.h
@@ -439,7 +439,7 @@ struct ath_beacon {
439 u32 bmisscnt; 439 u32 bmisscnt;
440 u32 ast_be_xmit; 440 u32 ast_be_xmit;
441 u64 bc_tstamp; 441 u64 bc_tstamp;
442 int bslot[ATH_BCBUF]; 442 struct ieee80211_vif *bslot[ATH_BCBUF];
443 int slottime; 443 int slottime;
444 int slotupdate; 444 int slotupdate;
445 struct ath9k_tx_queue_info beacon_qi; 445 struct ath9k_tx_queue_info beacon_qi;
@@ -449,9 +449,9 @@ struct ath_beacon {
449}; 449};
450 450
451void ath_beacon_tasklet(unsigned long data); 451void ath_beacon_tasklet(unsigned long data);
452void ath_beacon_config(struct ath_softc *sc, int if_id); 452void ath_beacon_config(struct ath_softc *sc, struct ieee80211_vif *vif);
453int ath_beaconq_setup(struct ath_hw *ah); 453int ath_beaconq_setup(struct ath_hw *ah);
454int ath_beacon_alloc(struct ath_softc *sc, int if_id); 454int ath_beacon_alloc(struct ath_softc *sc, struct ieee80211_vif *vif);
455void ath_beacon_return(struct ath_softc *sc, struct ath_vif *avp); 455void ath_beacon_return(struct ath_softc *sc, struct ath_vif *avp);
456 456
457/*******/ 457/*******/
@@ -532,7 +532,6 @@ struct ath_rfkill {
532 */ 532 */
533#define ATH_KEYMAX 128 /* max key cache size we handle */ 533#define ATH_KEYMAX 128 /* max key cache size we handle */
534 534
535#define ATH_IF_ID_ANY 0xff
536#define ATH_TXPOWER_MAX 100 /* .5 dBm units */ 535#define ATH_TXPOWER_MAX 100 /* .5 dBm units */
537#define ATH_RSSI_DUMMY_MARKER 0x127 536#define ATH_RSSI_DUMMY_MARKER 0x127
538#define ATH_RATE_DUMMY_MARKER 0 537#define ATH_RATE_DUMMY_MARKER 0
@@ -595,7 +594,6 @@ struct ath_softc {
595 struct ath_rx rx; 594 struct ath_rx rx;
596 struct ath_tx tx; 595 struct ath_tx tx;
597 struct ath_beacon beacon; 596 struct ath_beacon beacon;
598 struct ieee80211_vif *vifs[ATH_BCBUF];
599 struct ieee80211_rate rates[IEEE80211_NUM_BANDS][ATH_RATE_MAX]; 597 struct ieee80211_rate rates[IEEE80211_NUM_BANDS][ATH_RATE_MAX];
600 struct ath_rate_table *hw_rate_table[ATH9K_MODE_MAX]; 598 struct ath_rate_table *hw_rate_table[ATH9K_MODE_MAX];
601 struct ath_rate_table *cur_rate_table; 599 struct ath_rate_table *cur_rate_table;
diff --git a/drivers/net/wireless/ath9k/beacon.c b/drivers/net/wireless/ath9k/beacon.c
index d1365726d2f3..357d797e79c1 100644
--- a/drivers/net/wireless/ath9k/beacon.c
+++ b/drivers/net/wireless/ath9k/beacon.c
@@ -113,17 +113,16 @@ 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, int if_id) 116static struct ath_buf *ath_beacon_generate(struct ath_softc *sc,
117 struct ieee80211_vif *vif)
117{ 118{
118 struct ath_buf *bf; 119 struct ath_buf *bf;
119 struct ath_vif *avp; 120 struct ath_vif *avp;
120 struct sk_buff *skb; 121 struct sk_buff *skb;
121 struct ath_txq *cabq; 122 struct ath_txq *cabq;
122 struct ieee80211_vif *vif;
123 struct ieee80211_tx_info *info; 123 struct ieee80211_tx_info *info;
124 int cabq_depth; 124 int cabq_depth;
125 125
126 vif = sc->vifs[if_id];
127 avp = (void *)vif->drv_priv; 126 avp = (void *)vif->drv_priv;
128 cabq = sc->beacon.cabq; 127 cabq = sc->beacon.cabq;
129 128
@@ -208,15 +207,14 @@ static struct ath_buf *ath_beacon_generate(struct ath_softc *sc, int if_id)
208 * Startup beacon transmission for adhoc mode when they are sent entirely 207 * Startup beacon transmission for adhoc mode when they are sent entirely
209 * by the hardware using the self-linked descriptor + veol trick. 208 * by the hardware using the self-linked descriptor + veol trick.
210*/ 209*/
211static void ath_beacon_start_adhoc(struct ath_softc *sc, int if_id) 210static void ath_beacon_start_adhoc(struct ath_softc *sc,
211 struct ieee80211_vif *vif)
212{ 212{
213 struct ieee80211_vif *vif;
214 struct ath_hw *ah = sc->sc_ah; 213 struct ath_hw *ah = sc->sc_ah;
215 struct ath_buf *bf; 214 struct ath_buf *bf;
216 struct ath_vif *avp; 215 struct ath_vif *avp;
217 struct sk_buff *skb; 216 struct sk_buff *skb;
218 217
219 vif = sc->vifs[if_id];
220 avp = (void *)vif->drv_priv; 218 avp = (void *)vif->drv_priv;
221 219
222 if (avp->av_bcbuf == NULL) 220 if (avp->av_bcbuf == NULL)
@@ -246,16 +244,14 @@ int ath_beaconq_setup(struct ath_hw *ah)
246 return ath9k_hw_setuptxqueue(ah, ATH9K_TX_QUEUE_BEACON, &qi); 244 return ath9k_hw_setuptxqueue(ah, ATH9K_TX_QUEUE_BEACON, &qi);
247} 245}
248 246
249int ath_beacon_alloc(struct ath_softc *sc, int if_id) 247int ath_beacon_alloc(struct ath_softc *sc, struct ieee80211_vif *vif)
250{ 248{
251 struct ieee80211_vif *vif;
252 struct ath_vif *avp; 249 struct ath_vif *avp;
253 struct ieee80211_hdr *hdr; 250 struct ieee80211_hdr *hdr;
254 struct ath_buf *bf; 251 struct ath_buf *bf;
255 struct sk_buff *skb; 252 struct sk_buff *skb;
256 __le64 tstamp; 253 __le64 tstamp;
257 254
258 vif = sc->vifs[if_id];
259 avp = (void *)vif->drv_priv; 255 avp = (void *)vif->drv_priv;
260 256
261 /* Allocate a beacon descriptor if we haven't done so. */ 257 /* Allocate a beacon descriptor if we haven't done so. */
@@ -275,22 +271,21 @@ int ath_beacon_alloc(struct ath_softc *sc, int if_id)
275 */ 271 */
276 avp->av_bslot = 0; 272 avp->av_bslot = 0;
277 for (slot = 0; slot < ATH_BCBUF; slot++) 273 for (slot = 0; slot < ATH_BCBUF; slot++)
278 if (sc->beacon.bslot[slot] == ATH_IF_ID_ANY) { 274 if (sc->beacon.bslot[slot] == NULL) {
279 /* 275 /*
280 * XXX hack, space out slots to better 276 * XXX hack, space out slots to better
281 * deal with misses 277 * deal with misses
282 */ 278 */
283 if (slot+1 < ATH_BCBUF && 279 if (slot+1 < ATH_BCBUF &&
284 sc->beacon.bslot[slot+1] == 280 sc->beacon.bslot[slot+1] == NULL) {
285 ATH_IF_ID_ANY) {
286 avp->av_bslot = slot+1; 281 avp->av_bslot = slot+1;
287 break; 282 break;
288 } 283 }
289 avp->av_bslot = slot; 284 avp->av_bslot = slot;
290 /* NB: keep looking for a double slot */ 285 /* NB: keep looking for a double slot */
291 } 286 }
292 BUG_ON(sc->beacon.bslot[avp->av_bslot] != ATH_IF_ID_ANY); 287 BUG_ON(sc->beacon.bslot[avp->av_bslot] != NULL);
293 sc->beacon.bslot[avp->av_bslot] = if_id; 288 sc->beacon.bslot[avp->av_bslot] = vif;
294 sc->nbcnvifs++; 289 sc->nbcnvifs++;
295 } 290 }
296 } 291 }
@@ -372,7 +367,7 @@ void ath_beacon_return(struct ath_softc *sc, struct ath_vif *avp)
372 struct ath_buf *bf; 367 struct ath_buf *bf;
373 368
374 if (avp->av_bslot != -1) { 369 if (avp->av_bslot != -1) {
375 sc->beacon.bslot[avp->av_bslot] = ATH_IF_ID_ANY; 370 sc->beacon.bslot[avp->av_bslot] = NULL;
376 sc->nbcnvifs--; 371 sc->nbcnvifs--;
377 } 372 }
378 373
@@ -395,7 +390,8 @@ void ath_beacon_tasklet(unsigned long data)
395 struct ath_softc *sc = (struct ath_softc *)data; 390 struct ath_softc *sc = (struct ath_softc *)data;
396 struct ath_hw *ah = sc->sc_ah; 391 struct ath_hw *ah = sc->sc_ah;
397 struct ath_buf *bf = NULL; 392 struct ath_buf *bf = NULL;
398 int slot, if_id; 393 struct ieee80211_vif *vif;
394 int slot;
399 u32 bfaddr, bc = 0, tsftu; 395 u32 bfaddr, bc = 0, tsftu;
400 u64 tsf; 396 u64 tsf;
401 u16 intval; 397 u16 intval;
@@ -442,15 +438,15 @@ void ath_beacon_tasklet(unsigned long data)
442 tsf = ath9k_hw_gettsf64(ah); 438 tsf = ath9k_hw_gettsf64(ah);
443 tsftu = TSF_TO_TU(tsf>>32, tsf); 439 tsftu = TSF_TO_TU(tsf>>32, tsf);
444 slot = ((tsftu % intval) * ATH_BCBUF) / intval; 440 slot = ((tsftu % intval) * ATH_BCBUF) / intval;
445 if_id = sc->beacon.bslot[(slot + 1) % ATH_BCBUF]; 441 vif = sc->beacon.bslot[(slot + 1) % ATH_BCBUF];
446 442
447 DPRINTF(sc, ATH_DBG_BEACON, 443 DPRINTF(sc, ATH_DBG_BEACON,
448 "slot %d [tsf %llu tsftu %u intval %u] if_id %d\n", 444 "slot %d [tsf %llu tsftu %u intval %u] vif %p\n",
449 slot, tsf, tsftu, intval, if_id); 445 slot, tsf, tsftu, intval, vif);
450 446
451 bfaddr = 0; 447 bfaddr = 0;
452 if (if_id != ATH_IF_ID_ANY) { 448 if (vif) {
453 bf = ath_beacon_generate(sc, if_id); 449 bf = ath_beacon_generate(sc, vif);
454 if (bf != NULL) { 450 if (bf != NULL) {
455 bfaddr = bf->bf_daddr; 451 bfaddr = bf->bf_daddr;
456 bc = 1; 452 bc = 1;
@@ -652,7 +648,8 @@ static void ath_beacon_config_sta(struct ath_softc *sc,
652 648
653static void ath_beacon_config_adhoc(struct ath_softc *sc, 649static void ath_beacon_config_adhoc(struct ath_softc *sc,
654 struct ath_beacon_config *conf, 650 struct ath_beacon_config *conf,
655 struct ath_vif *avp) 651 struct ath_vif *avp,
652 struct ieee80211_vif *vif)
656{ 653{
657 u64 tsf; 654 u64 tsf;
658 u32 tsftu, intval, nexttbtt; 655 u32 tsftu, intval, nexttbtt;
@@ -696,14 +693,12 @@ static void ath_beacon_config_adhoc(struct ath_softc *sc,
696 ath9k_hw_set_interrupts(sc->sc_ah, sc->imask); 693 ath9k_hw_set_interrupts(sc->sc_ah, sc->imask);
697 694
698 if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_VEOL) 695 if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_VEOL)
699 ath_beacon_start_adhoc(sc, 0); 696 ath_beacon_start_adhoc(sc, vif);
700} 697}
701 698
702void ath_beacon_config(struct ath_softc *sc, int if_id) 699void ath_beacon_config(struct ath_softc *sc, struct ieee80211_vif *vif)
703{ 700{
704 struct ath_beacon_config conf; 701 struct ath_beacon_config conf;
705 struct ath_vif *avp;
706 struct ieee80211_vif *vif;
707 702
708 /* Setup the beacon configuration parameters */ 703 /* Setup the beacon configuration parameters */
709 704
@@ -715,16 +710,15 @@ void ath_beacon_config(struct ath_softc *sc, int if_id)
715 conf.dtim_count = 1; 710 conf.dtim_count = 1;
716 conf.bmiss_timeout = ATH_DEFAULT_BMISS_LIMIT * conf.beacon_interval; 711 conf.bmiss_timeout = ATH_DEFAULT_BMISS_LIMIT * conf.beacon_interval;
717 712
718 if (if_id != ATH_IF_ID_ANY) { 713 if (vif) {
719 vif = sc->vifs[if_id]; 714 struct ath_vif *avp = (struct ath_vif *)vif->drv_priv;
720 avp = (struct ath_vif *)vif->drv_priv;
721 715
722 switch(avp->av_opmode) { 716 switch(avp->av_opmode) {
723 case NL80211_IFTYPE_AP: 717 case NL80211_IFTYPE_AP:
724 ath_beacon_config_ap(sc, &conf, avp); 718 ath_beacon_config_ap(sc, &conf, avp);
725 break; 719 break;
726 case NL80211_IFTYPE_ADHOC: 720 case NL80211_IFTYPE_ADHOC:
727 ath_beacon_config_adhoc(sc, &conf, avp); 721 ath_beacon_config_adhoc(sc, &conf, avp, vif);
728 break; 722 break;
729 case NL80211_IFTYPE_STATION: 723 case NL80211_IFTYPE_STATION:
730 ath_beacon_config_sta(sc, &conf, avp); 724 ath_beacon_config_sta(sc, &conf, avp);
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
2205out:
2203 mutex_unlock(&sc->mutex); 2206 mutex_unlock(&sc->mutex);
2204 2207 return ret;
2205 return 0;
2206} 2208}
2207 2209
2208static void ath9k_remove_interface(struct ieee80211_hw *hw, 2210static 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