u32 bmisscnt;
u32 ast_be_xmit;
u64 bc_tstamp;
- int bslot[ATH_BCBUF];
+ struct ieee80211_vif *bslot[ATH_BCBUF];
int slottime;
int slotupdate;
struct ath9k_tx_queue_info beacon_qi;
};
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_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);
/*******/
*/
#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_RSSI_DUMMY_MARKER 0x127
#define ATH_RATE_DUMMY_MARKER 0
struct ath_rx rx;
struct ath_tx tx;
struct ath_beacon beacon;
- struct ieee80211_vif *vifs[ATH_BCBUF];
struct ieee80211_rate rates[IEEE80211_NUM_BANDS][ATH_RATE_MAX];
struct ath_rate_table *hw_rate_table[ATH9K_MODE_MAX];
struct ath_rate_table *cur_rate_table;
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_vif *avp;
struct sk_buff *skb;
struct ath_txq *cabq;
- struct ieee80211_vif *vif;
struct ieee80211_tx_info *info;
int cabq_depth;
- vif = sc->vifs[if_id];
avp = (void *)vif->drv_priv;
cabq = sc->beacon.cabq;
* Startup beacon transmission for adhoc mode when they are sent entirely
* 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_buf *bf;
struct ath_vif *avp;
struct sk_buff *skb;
- vif = sc->vifs[if_id];
avp = (void *)vif->drv_priv;
if (avp->av_bcbuf == NULL)
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 ieee80211_hdr *hdr;
struct ath_buf *bf;
struct sk_buff *skb;
__le64 tstamp;
- vif = sc->vifs[if_id];
avp = (void *)vif->drv_priv;
/* Allocate a beacon descriptor if we haven't done so. */
*/
avp->av_bslot = 0;
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
* deal with misses
*/
if (slot+1 < ATH_BCBUF &&
- sc->beacon.bslot[slot+1] ==
- ATH_IF_ID_ANY) {
+ sc->beacon.bslot[slot+1] == NULL) {
avp->av_bslot = slot+1;
break;
}
avp->av_bslot = slot;
/* NB: keep looking for a double slot */
}
- BUG_ON(sc->beacon.bslot[avp->av_bslot] != ATH_IF_ID_ANY);
- sc->beacon.bslot[avp->av_bslot] = if_id;
+ BUG_ON(sc->beacon.bslot[avp->av_bslot] != NULL);
+ sc->beacon.bslot[avp->av_bslot] = vif;
sc->nbcnvifs++;
}
}
struct ath_buf *bf;
if (avp->av_bslot != -1) {
- sc->beacon.bslot[avp->av_bslot] = ATH_IF_ID_ANY;
+ sc->beacon.bslot[avp->av_bslot] = NULL;
sc->nbcnvifs--;
}
struct ath_softc *sc = (struct ath_softc *)data;
struct ath_hw *ah = sc->sc_ah;
struct ath_buf *bf = NULL;
- int slot, if_id;
+ struct ieee80211_vif *vif;
+ int slot;
u32 bfaddr, bc = 0, tsftu;
u64 tsf;
u16 intval;
tsf = ath9k_hw_gettsf64(ah);
tsftu = TSF_TO_TU(tsf>>32, tsf);
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,
- "slot %d [tsf %llu tsftu %u intval %u] if_id %d\n",
- slot, tsf, tsftu, intval, if_id);
+ "slot %d [tsf %llu tsftu %u intval %u] vif %p\n",
+ slot, tsf, tsftu, intval, vif);
bfaddr = 0;
- if (if_id != ATH_IF_ID_ANY) {
- bf = ath_beacon_generate(sc, if_id);
+ if (vif) {
+ bf = ath_beacon_generate(sc, vif);
if (bf != NULL) {
bfaddr = bf->bf_daddr;
bc = 1;
static void ath_beacon_config_adhoc(struct ath_softc *sc,
struct ath_beacon_config *conf,
- struct ath_vif *avp)
+ struct ath_vif *avp,
+ struct ieee80211_vif *vif)
{
u64 tsf;
u32 tsftu, intval, nexttbtt;
ath9k_hw_set_interrupts(sc->sc_ah, sc->imask);
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_vif *avp;
- struct ieee80211_vif *vif;
/* Setup the beacon configuration parameters */
conf.dtim_count = 1;
conf.bmiss_timeout = ATH_DEFAULT_BMISS_LIMIT * conf.beacon_interval;
- if (if_id != ATH_IF_ID_ANY) {
- vif = sc->vifs[if_id];
- avp = (struct ath_vif *)vif->drv_priv;
+ if (vif) {
+ struct ath_vif *avp = (struct ath_vif *)vif->drv_priv;
switch(avp->av_opmode) {
case NL80211_IFTYPE_AP:
ath_beacon_config_ap(sc, &conf, avp);
break;
case NL80211_IFTYPE_ADHOC:
- ath_beacon_config_adhoc(sc, &conf, avp);
+ ath_beacon_config_adhoc(sc, &conf, avp, vif);
break;
case NL80211_IFTYPE_STATION:
ath_beacon_config_sta(sc, &conf, avp);
* need to change with virtual interfaces. */
idx = key->keyidx;
} else if (key->keyidx) {
- struct ieee80211_vif *vif;
-
if (WARN_ON(!sta))
return -EOPNOTSUPP;
mac = sta->addr;
- vif = sc->vifs[0];
if (vif->type != NL80211_IFTYPE_AP) {
/* Only keyidx 0 should be used with unicast key, but
* allow this for client mode for now. */
}
/* Configure the beacon */
- ath_beacon_config(sc, 0);
+ ath_beacon_config(sc, vif);
/* Reset rssi stats */
sc->nodestats.ns_avgbrssi = ATH_RSSI_DUMMY_MARKER;
}
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 */
ath9k_hw_set_interrupts(ah, sc->imask);
/* initialize beacon slots */
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 */
sc->config.swBeaconProcess = 1;
ath_update_txpow(sc);
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);
struct ath_softc *sc = hw->priv;
struct ath_vif *avp = (void *)conf->vif->drv_priv;
enum nl80211_iftype ic_opmode = NL80211_IFTYPE_UNSPECIFIED;
-
- /* Support only vif for now */
-
- if (sc->nvifs)
- return -ENOBUFS;
+ int ret = 0;
mutex_lock(&sc->mutex);
ic_opmode = NL80211_IFTYPE_STATION;
break;
case NL80211_IFTYPE_ADHOC:
+ if (sc->nbcnvifs >= ATH_BCBUF) {
+ ret = -ENOBUFS;
+ goto out;
+ }
ic_opmode = NL80211_IFTYPE_ADHOC;
break;
case NL80211_IFTYPE_AP:
+ if (sc->nbcnvifs >= ATH_BCBUF) {
+ ret = -ENOBUFS;
+ goto out;
+ }
ic_opmode = NL80211_IFTYPE_AP;
break;
default:
DPRINTF(sc, ATH_DBG_FATAL,
"Interface type %d not yet supported\n", conf->type);
- mutex_unlock(&sc->mutex);
- return -EOPNOTSUPP;
+ ret = -EOPNOTSUPP;
+ goto out;
}
DPRINTF(sc, ATH_DBG_CONFIG, "Attach a VIF of type: %d\n", ic_opmode);
avp->av_opmode = ic_opmode;
avp->av_bslot = -1;
+ sc->nvifs++;
+ if (sc->nvifs > 1)
+ goto out; /* skip global settings for secondary vif */
+
if (ic_opmode == NL80211_IFTYPE_AP) {
ath9k_hw_set_tsfadjust(sc->sc_ah, 1);
sc->sc_flags |= SC_OP_TSF_RESET;
}
- sc->vifs[0] = conf->vif;
- sc->nvifs++;
-
/* Set the device opmode */
sc->sc_ah->opmode = ic_opmode;
jiffies + msecs_to_jiffies(ATH_ANI_POLLINTERVAL));
}
+out:
mutex_unlock(&sc->mutex);
-
- return 0;
+ return ret;
}
static void ath9k_remove_interface(struct ieee80211_hw *hw,
{
struct ath_softc *sc = hw->priv;
struct ath_vif *avp = (void *)conf->vif->drv_priv;
+ int i;
DPRINTF(sc, ATH_DBG_CONFIG, "Detach Interface\n");
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--;
mutex_unlock(&sc->mutex);
*/
ath9k_hw_stoptxdma(sc->sc_ah, sc->beacon.beaconq);
- error = ath_beacon_alloc(sc, 0);
+ error = ath_beacon_alloc(sc, vif);
if (error != 0) {
mutex_unlock(&sc->mutex);
return error;
}
- ath_beacon_config(sc, 0);
+ ath_beacon_config(sc, vif);
}
}