Commit 2c3db3d5 authored by Jouni Malinen's avatar Jouni Malinen Committed by John W. Linville

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: default avatarJouni Malinen <jouni.malinen@atheros.com>
Signed-off-by: default avatarJohn W. Linville <linville@tuxdriver.com>
parent 860559fe
...@@ -439,7 +439,7 @@ struct ath_beacon { ...@@ -439,7 +439,7 @@ struct ath_beacon {
u32 bmisscnt; u32 bmisscnt;
u32 ast_be_xmit; u32 ast_be_xmit;
u64 bc_tstamp; u64 bc_tstamp;
int bslot[ATH_BCBUF]; struct ieee80211_vif *bslot[ATH_BCBUF];
int slottime; int slottime;
int slotupdate; int slotupdate;
struct ath9k_tx_queue_info beacon_qi; struct ath9k_tx_queue_info beacon_qi;
...@@ -449,9 +449,9 @@ struct ath_beacon { ...@@ -449,9 +449,9 @@ struct ath_beacon {
}; };
void ath_beacon_tasklet(unsigned long data); void ath_beacon_tasklet(unsigned long data);
void ath_beacon_config(struct ath_softc *sc, int if_id); void ath_beacon_config(struct ath_softc *sc, struct ieee80211_vif *vif);
int ath_beaconq_setup(struct ath_hw *ah); int ath_beaconq_setup(struct ath_hw *ah);
int ath_beacon_alloc(struct ath_softc *sc, int if_id); int ath_beacon_alloc(struct ath_softc *sc, struct ieee80211_vif *vif);
void ath_beacon_return(struct ath_softc *sc, struct ath_vif *avp); void ath_beacon_return(struct ath_softc *sc, struct ath_vif *avp);
/*******/ /*******/
...@@ -532,7 +532,6 @@ struct ath_rfkill { ...@@ -532,7 +532,6 @@ struct ath_rfkill {
*/ */
#define ATH_KEYMAX 128 /* max key cache size we handle */ #define ATH_KEYMAX 128 /* max key cache size we handle */
#define ATH_IF_ID_ANY 0xff
#define ATH_TXPOWER_MAX 100 /* .5 dBm units */ #define ATH_TXPOWER_MAX 100 /* .5 dBm units */
#define ATH_RSSI_DUMMY_MARKER 0x127 #define ATH_RSSI_DUMMY_MARKER 0x127
#define ATH_RATE_DUMMY_MARKER 0 #define ATH_RATE_DUMMY_MARKER 0
...@@ -595,7 +594,6 @@ struct ath_softc { ...@@ -595,7 +594,6 @@ struct ath_softc {
struct ath_rx rx; struct ath_rx rx;
struct ath_tx tx; struct ath_tx tx;
struct ath_beacon beacon; struct ath_beacon beacon;
struct ieee80211_vif *vifs[ATH_BCBUF];
struct ieee80211_rate rates[IEEE80211_NUM_BANDS][ATH_RATE_MAX]; struct ieee80211_rate rates[IEEE80211_NUM_BANDS][ATH_RATE_MAX];
struct ath_rate_table *hw_rate_table[ATH9K_MODE_MAX]; struct ath_rate_table *hw_rate_table[ATH9K_MODE_MAX];
struct ath_rate_table *cur_rate_table; struct ath_rate_table *cur_rate_table;
......
...@@ -113,17 +113,16 @@ static void ath_beacon_setup(struct ath_softc *sc, struct ath_vif *avp, ...@@ -113,17 +113,16 @@ static void ath_beacon_setup(struct ath_softc *sc, struct ath_vif *avp,
series, 4, 0); series, 4, 0);
} }
static struct ath_buf *ath_beacon_generate(struct ath_softc *sc, int if_id) static struct ath_buf *ath_beacon_generate(struct ath_softc *sc,
struct ieee80211_vif *vif)
{ {
struct ath_buf *bf; struct ath_buf *bf;
struct ath_vif *avp; struct ath_vif *avp;
struct sk_buff *skb; struct sk_buff *skb;
struct ath_txq *cabq; struct ath_txq *cabq;
struct ieee80211_vif *vif;
struct ieee80211_tx_info *info; struct ieee80211_tx_info *info;
int cabq_depth; int cabq_depth;
vif = sc->vifs[if_id];
avp = (void *)vif->drv_priv; avp = (void *)vif->drv_priv;
cabq = sc->beacon.cabq; cabq = sc->beacon.cabq;
...@@ -208,15 +207,14 @@ static struct ath_buf *ath_beacon_generate(struct ath_softc *sc, int if_id) ...@@ -208,15 +207,14 @@ static struct ath_buf *ath_beacon_generate(struct ath_softc *sc, int if_id)
* Startup beacon transmission for adhoc mode when they are sent entirely * Startup beacon transmission for adhoc mode when they are sent entirely
* by the hardware using the self-linked descriptor + veol trick. * by the hardware using the self-linked descriptor + veol trick.
*/ */
static void ath_beacon_start_adhoc(struct ath_softc *sc, int if_id) static void ath_beacon_start_adhoc(struct ath_softc *sc,
struct ieee80211_vif *vif)
{ {
struct ieee80211_vif *vif;
struct ath_hw *ah = sc->sc_ah; struct ath_hw *ah = sc->sc_ah;
struct ath_buf *bf; struct ath_buf *bf;
struct ath_vif *avp; struct ath_vif *avp;
struct sk_buff *skb; struct sk_buff *skb;
vif = sc->vifs[if_id];
avp = (void *)vif->drv_priv; avp = (void *)vif->drv_priv;
if (avp->av_bcbuf == NULL) if (avp->av_bcbuf == NULL)
...@@ -246,16 +244,14 @@ int ath_beaconq_setup(struct ath_hw *ah) ...@@ -246,16 +244,14 @@ int ath_beaconq_setup(struct ath_hw *ah)
return ath9k_hw_setuptxqueue(ah, ATH9K_TX_QUEUE_BEACON, &qi); return ath9k_hw_setuptxqueue(ah, ATH9K_TX_QUEUE_BEACON, &qi);
} }
int ath_beacon_alloc(struct ath_softc *sc, int if_id) int ath_beacon_alloc(struct ath_softc *sc, struct ieee80211_vif *vif)
{ {
struct ieee80211_vif *vif;
struct ath_vif *avp; struct ath_vif *avp;
struct ieee80211_hdr *hdr; struct ieee80211_hdr *hdr;
struct ath_buf *bf; struct ath_buf *bf;
struct sk_buff *skb; struct sk_buff *skb;
__le64 tstamp; __le64 tstamp;
vif = sc->vifs[if_id];
avp = (void *)vif->drv_priv; avp = (void *)vif->drv_priv;
/* Allocate a beacon descriptor if we haven't done so. */ /* 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,22 +271,21 @@ int ath_beacon_alloc(struct ath_softc *sc, int if_id)
*/ */
avp->av_bslot = 0; avp->av_bslot = 0;
for (slot = 0; slot < ATH_BCBUF; slot++) for (slot = 0; slot < ATH_BCBUF; slot++)
if (sc->beacon.bslot[slot] == ATH_IF_ID_ANY) { if (sc->beacon.bslot[slot] == NULL) {
/* /*
* XXX hack, space out slots to better * XXX hack, space out slots to better
* deal with misses * deal with misses
*/ */
if (slot+1 < ATH_BCBUF && if (slot+1 < ATH_BCBUF &&
sc->beacon.bslot[slot+1] == sc->beacon.bslot[slot+1] == NULL) {
ATH_IF_ID_ANY) {
avp->av_bslot = slot+1; avp->av_bslot = slot+1;
break; break;
} }
avp->av_bslot = slot; avp->av_bslot = slot;
/* NB: keep looking for a double slot */ /* NB: keep looking for a double slot */
} }
BUG_ON(sc->beacon.bslot[avp->av_bslot] != ATH_IF_ID_ANY); BUG_ON(sc->beacon.bslot[avp->av_bslot] != NULL);
sc->beacon.bslot[avp->av_bslot] = if_id; sc->beacon.bslot[avp->av_bslot] = vif;
sc->nbcnvifs++; sc->nbcnvifs++;
} }
} }
...@@ -372,7 +367,7 @@ void ath_beacon_return(struct ath_softc *sc, struct ath_vif *avp) ...@@ -372,7 +367,7 @@ void ath_beacon_return(struct ath_softc *sc, struct ath_vif *avp)
struct ath_buf *bf; struct ath_buf *bf;
if (avp->av_bslot != -1) { if (avp->av_bslot != -1) {
sc->beacon.bslot[avp->av_bslot] = ATH_IF_ID_ANY; sc->beacon.bslot[avp->av_bslot] = NULL;
sc->nbcnvifs--; sc->nbcnvifs--;
} }
...@@ -395,7 +390,8 @@ void ath_beacon_tasklet(unsigned long data) ...@@ -395,7 +390,8 @@ void ath_beacon_tasklet(unsigned long data)
struct ath_softc *sc = (struct ath_softc *)data; struct ath_softc *sc = (struct ath_softc *)data;
struct ath_hw *ah = sc->sc_ah; struct ath_hw *ah = sc->sc_ah;
struct ath_buf *bf = NULL; struct ath_buf *bf = NULL;
int slot, if_id; struct ieee80211_vif *vif;
int slot;
u32 bfaddr, bc = 0, tsftu; u32 bfaddr, bc = 0, tsftu;
u64 tsf; u64 tsf;
u16 intval; u16 intval;
...@@ -442,15 +438,15 @@ void ath_beacon_tasklet(unsigned long data) ...@@ -442,15 +438,15 @@ void ath_beacon_tasklet(unsigned long data)
tsf = ath9k_hw_gettsf64(ah); tsf = ath9k_hw_gettsf64(ah);
tsftu = TSF_TO_TU(tsf>>32, tsf); tsftu = TSF_TO_TU(tsf>>32, tsf);
slot = ((tsftu % intval) * ATH_BCBUF) / intval; slot = ((tsftu % intval) * ATH_BCBUF) / intval;
if_id = sc->beacon.bslot[(slot + 1) % ATH_BCBUF]; vif = sc->beacon.bslot[(slot + 1) % ATH_BCBUF];
DPRINTF(sc, ATH_DBG_BEACON, DPRINTF(sc, ATH_DBG_BEACON,
"slot %d [tsf %llu tsftu %u intval %u] if_id %d\n", "slot %d [tsf %llu tsftu %u intval %u] vif %p\n",
slot, tsf, tsftu, intval, if_id); slot, tsf, tsftu, intval, vif);
bfaddr = 0; bfaddr = 0;
if (if_id != ATH_IF_ID_ANY) { if (vif) {
bf = ath_beacon_generate(sc, if_id); bf = ath_beacon_generate(sc, vif);
if (bf != NULL) { if (bf != NULL) {
bfaddr = bf->bf_daddr; bfaddr = bf->bf_daddr;
bc = 1; bc = 1;
...@@ -652,7 +648,8 @@ static void ath_beacon_config_sta(struct ath_softc *sc, ...@@ -652,7 +648,8 @@ static void ath_beacon_config_sta(struct ath_softc *sc,
static void ath_beacon_config_adhoc(struct ath_softc *sc, static void ath_beacon_config_adhoc(struct ath_softc *sc,
struct ath_beacon_config *conf, struct ath_beacon_config *conf,
struct ath_vif *avp) struct ath_vif *avp,
struct ieee80211_vif *vif)
{ {
u64 tsf; u64 tsf;
u32 tsftu, intval, nexttbtt; u32 tsftu, intval, nexttbtt;
...@@ -696,14 +693,12 @@ static void ath_beacon_config_adhoc(struct ath_softc *sc, ...@@ -696,14 +693,12 @@ static void ath_beacon_config_adhoc(struct ath_softc *sc,
ath9k_hw_set_interrupts(sc->sc_ah, sc->imask); ath9k_hw_set_interrupts(sc->sc_ah, sc->imask);
if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_VEOL) if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_VEOL)
ath_beacon_start_adhoc(sc, 0); ath_beacon_start_adhoc(sc, vif);
} }
void ath_beacon_config(struct ath_softc *sc, int if_id) void ath_beacon_config(struct ath_softc *sc, struct ieee80211_vif *vif)
{ {
struct ath_beacon_config conf; struct ath_beacon_config conf;
struct ath_vif *avp;
struct ieee80211_vif *vif;
/* Setup the beacon configuration parameters */ /* Setup the beacon configuration parameters */
...@@ -715,16 +710,15 @@ void ath_beacon_config(struct ath_softc *sc, int if_id) ...@@ -715,16 +710,15 @@ void ath_beacon_config(struct ath_softc *sc, int if_id)
conf.dtim_count = 1; conf.dtim_count = 1;
conf.bmiss_timeout = ATH_DEFAULT_BMISS_LIMIT * conf.beacon_interval; conf.bmiss_timeout = ATH_DEFAULT_BMISS_LIMIT * conf.beacon_interval;
if (if_id != ATH_IF_ID_ANY) { if (vif) {
vif = sc->vifs[if_id]; struct ath_vif *avp = (struct ath_vif *)vif->drv_priv;
avp = (struct ath_vif *)vif->drv_priv;
switch(avp->av_opmode) { switch(avp->av_opmode) {
case NL80211_IFTYPE_AP: case NL80211_IFTYPE_AP:
ath_beacon_config_ap(sc, &conf, avp); ath_beacon_config_ap(sc, &conf, avp);
break; break;
case NL80211_IFTYPE_ADHOC: case NL80211_IFTYPE_ADHOC:
ath_beacon_config_adhoc(sc, &conf, avp); ath_beacon_config_adhoc(sc, &conf, avp, vif);
break; break;
case NL80211_IFTYPE_STATION: case NL80211_IFTYPE_STATION:
ath_beacon_config_sta(sc, &conf, avp); ath_beacon_config_sta(sc, &conf, avp);
......
...@@ -800,13 +800,10 @@ static int ath_key_config(struct ath_softc *sc, ...@@ -800,13 +800,10 @@ static int ath_key_config(struct ath_softc *sc,
* need to change with virtual interfaces. */ * need to change with virtual interfaces. */
idx = key->keyidx; idx = key->keyidx;
} else if (key->keyidx) { } else if (key->keyidx) {
struct ieee80211_vif *vif;
if (WARN_ON(!sta)) if (WARN_ON(!sta))
return -EOPNOTSUPP; return -EOPNOTSUPP;
mac = sta->addr; mac = sta->addr;
vif = sc->vifs[0];
if (vif->type != NL80211_IFTYPE_AP) { if (vif->type != NL80211_IFTYPE_AP) {
/* Only keyidx 0 should be used with unicast key, but /* Only keyidx 0 should be used with unicast key, but
* allow this for client mode for now. */ * allow this for client mode for now. */
...@@ -915,7 +912,7 @@ static void ath9k_bss_assoc_info(struct ath_softc *sc, ...@@ -915,7 +912,7 @@ static void ath9k_bss_assoc_info(struct ath_softc *sc,
} }
/* Configure the beacon */ /* Configure the beacon */
ath_beacon_config(sc, 0); ath_beacon_config(sc, vif);
/* Reset rssi stats */ /* Reset rssi stats */
sc->nodestats.ns_avgbrssi = ATH_RSSI_DUMMY_MARKER; sc->nodestats.ns_avgbrssi = ATH_RSSI_DUMMY_MARKER;
...@@ -1120,7 +1117,7 @@ static void ath_radio_enable(struct ath_softc *sc) ...@@ -1120,7 +1117,7 @@ static void ath_radio_enable(struct ath_softc *sc)
} }
if (sc->sc_flags & SC_OP_BEACONS) if (sc->sc_flags & SC_OP_BEACONS)
ath_beacon_config(sc, ATH_IF_ID_ANY); /* restart beacons */ ath_beacon_config(sc, NULL); /* restart beacons */
/* Re-Enable interrupts */ /* Re-Enable interrupts */
ath9k_hw_set_interrupts(ah, sc->imask); ath9k_hw_set_interrupts(ah, sc->imask);
...@@ -1527,7 +1524,7 @@ static int ath_init(u16 devid, struct ath_softc *sc) ...@@ -1527,7 +1524,7 @@ static int ath_init(u16 devid, struct ath_softc *sc)
/* initialize beacon slots */ /* initialize beacon slots */
for (i = 0; i < ARRAY_SIZE(sc->beacon.bslot); i++) for (i = 0; i < ARRAY_SIZE(sc->beacon.bslot); i++)
sc->beacon.bslot[i] = ATH_IF_ID_ANY; sc->beacon.bslot[i] = NULL;
/* save MISC configurations */ /* save MISC configurations */
sc->config.swBeaconProcess = 1; sc->config.swBeaconProcess = 1;
...@@ -1715,7 +1712,7 @@ int ath_reset(struct ath_softc *sc, bool retry_tx) ...@@ -1715,7 +1712,7 @@ int ath_reset(struct ath_softc *sc, bool retry_tx)
ath_update_txpow(sc); ath_update_txpow(sc);
if (sc->sc_flags & SC_OP_BEACONS) if (sc->sc_flags & SC_OP_BEACONS)
ath_beacon_config(sc, ATH_IF_ID_ANY); /* restart beacons */ ath_beacon_config(sc, NULL); /* restart beacons */
ath9k_hw_set_interrupts(ah, sc->imask); ath9k_hw_set_interrupts(ah, sc->imask);
...@@ -2127,11 +2124,7 @@ static int ath9k_add_interface(struct ieee80211_hw *hw, ...@@ -2127,11 +2124,7 @@ static int ath9k_add_interface(struct ieee80211_hw *hw,
struct ath_softc *sc = hw->priv; struct ath_softc *sc = hw->priv;
struct ath_vif *avp = (void *)conf->vif->drv_priv; struct ath_vif *avp = (void *)conf->vif->drv_priv;
enum nl80211_iftype ic_opmode = NL80211_IFTYPE_UNSPECIFIED; enum nl80211_iftype ic_opmode = NL80211_IFTYPE_UNSPECIFIED;
int ret = 0;
/* Support only vif for now */
if (sc->nvifs)
return -ENOBUFS;
mutex_lock(&sc->mutex); mutex_lock(&sc->mutex);
...@@ -2140,16 +2133,24 @@ static int ath9k_add_interface(struct ieee80211_hw *hw, ...@@ -2140,16 +2133,24 @@ static int ath9k_add_interface(struct ieee80211_hw *hw,
ic_opmode = NL80211_IFTYPE_STATION; ic_opmode = NL80211_IFTYPE_STATION;
break; break;
case NL80211_IFTYPE_ADHOC: case NL80211_IFTYPE_ADHOC:
if (sc->nbcnvifs >= ATH_BCBUF) {
ret = -ENOBUFS;
goto out;
}
ic_opmode = NL80211_IFTYPE_ADHOC; ic_opmode = NL80211_IFTYPE_ADHOC;
break; break;
case NL80211_IFTYPE_AP: case NL80211_IFTYPE_AP:
if (sc->nbcnvifs >= ATH_BCBUF) {
ret = -ENOBUFS;
goto out;
}
ic_opmode = NL80211_IFTYPE_AP; ic_opmode = NL80211_IFTYPE_AP;
break; break;
default: default:
DPRINTF(sc, ATH_DBG_FATAL, DPRINTF(sc, ATH_DBG_FATAL,
"Interface type %d not yet supported\n", conf->type); "Interface type %d not yet supported\n", conf->type);
mutex_unlock(&sc->mutex); ret = -EOPNOTSUPP;
return -EOPNOTSUPP; goto out;
} }
DPRINTF(sc, ATH_DBG_CONFIG, "Attach a VIF of type: %d\n", ic_opmode); 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,14 +2159,15 @@ static int ath9k_add_interface(struct ieee80211_hw *hw,
avp->av_opmode = ic_opmode; avp->av_opmode = ic_opmode;
avp->av_bslot = -1; avp->av_bslot = -1;
sc->nvifs++;
if (sc->nvifs > 1)
goto out; /* skip global settings for secondary vif */
if (ic_opmode == NL80211_IFTYPE_AP) { if (ic_opmode == NL80211_IFTYPE_AP) {
ath9k_hw_set_tsfadjust(sc->sc_ah, 1); ath9k_hw_set_tsfadjust(sc->sc_ah, 1);
sc->sc_flags |= SC_OP_TSF_RESET; sc->sc_flags |= SC_OP_TSF_RESET;
} }
sc->vifs[0] = conf->vif;
sc->nvifs++;
/* Set the device opmode */ /* Set the device opmode */
sc->sc_ah->opmode = ic_opmode; sc->sc_ah->opmode = ic_opmode;
...@@ -2200,9 +2202,9 @@ static int ath9k_add_interface(struct ieee80211_hw *hw, ...@@ -2200,9 +2202,9 @@ static int ath9k_add_interface(struct ieee80211_hw *hw,
jiffies + msecs_to_jiffies(ATH_ANI_POLLINTERVAL)); jiffies + msecs_to_jiffies(ATH_ANI_POLLINTERVAL));
} }
out:
mutex_unlock(&sc->mutex); mutex_unlock(&sc->mutex);
return ret;
return 0;
} }
static void ath9k_remove_interface(struct ieee80211_hw *hw, static void ath9k_remove_interface(struct ieee80211_hw *hw,
...@@ -2210,6 +2212,7 @@ static void ath9k_remove_interface(struct ieee80211_hw *hw, ...@@ -2210,6 +2212,7 @@ static void ath9k_remove_interface(struct ieee80211_hw *hw,
{ {
struct ath_softc *sc = hw->priv; struct ath_softc *sc = hw->priv;
struct ath_vif *avp = (void *)conf->vif->drv_priv; struct ath_vif *avp = (void *)conf->vif->drv_priv;
int i;
DPRINTF(sc, ATH_DBG_CONFIG, "Detach Interface\n"); DPRINTF(sc, ATH_DBG_CONFIG, "Detach Interface\n");
...@@ -2227,7 +2230,14 @@ static void ath9k_remove_interface(struct ieee80211_hw *hw, ...@@ -2227,7 +2230,14 @@ static void ath9k_remove_interface(struct ieee80211_hw *hw,
sc->sc_flags &= ~SC_OP_BEACONS; sc->sc_flags &= ~SC_OP_BEACONS;
sc->vifs[0] = NULL; for (i = 0; i < ARRAY_SIZE(sc->beacon.bslot); i++) {
if (sc->beacon.bslot[i] == conf->vif) {
printk(KERN_DEBUG "%s: vif had allocated beacon "
"slot\n", __func__);
sc->beacon.bslot[i] = NULL;
}
}
sc->nvifs--; sc->nvifs--;
mutex_unlock(&sc->mutex); mutex_unlock(&sc->mutex);
...@@ -2364,13 +2374,13 @@ static int ath9k_config_interface(struct ieee80211_hw *hw, ...@@ -2364,13 +2374,13 @@ static int ath9k_config_interface(struct ieee80211_hw *hw,
*/ */
ath9k_hw_stoptxdma(sc->sc_ah, sc->beacon.beaconq); ath9k_hw_stoptxdma(sc->sc_ah, sc->beacon.beaconq);
error = ath_beacon_alloc(sc, 0); error = ath_beacon_alloc(sc, vif);
if (error != 0) { if (error != 0) {
mutex_unlock(&sc->mutex); mutex_unlock(&sc->mutex);
return error; return error;
} }
ath_beacon_config(sc, 0); ath_beacon_config(sc, vif);
} }
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment