From: Jouni Malinen <jouni.malinen@atheros.com>
To: "John W. Linville" <linville@tuxdriver.com>
Cc: linux-wireless@vger.kernel.org,
Jouni Malinen <jouni.malinen@atheros.com>
Subject: [PATCH 01/15] ath9k: Cleanup multiple VIF processing
Date: Tue, 03 Mar 2009 19:23:26 +0200 [thread overview]
Message-ID: <20090303172441.250416741@atheros.com> (raw)
In-Reply-To: 20090303172325.437810138@atheros.com
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>
---
drivers/net/wireless/ath9k/ath9k.h | 8 ++---
drivers/net/wireless/ath9k/beacon.c | 54 ++++++++++++++++--------------------
drivers/net/wireless/ath9k/main.c | 54 +++++++++++++++++++++---------------
3 files changed, 59 insertions(+), 57 deletions(-)
--- wireless-testing.orig/drivers/net/wireless/ath9k/beacon.c 2009-03-03 18:28:59.000000000 +0200
+++ wireless-testing/drivers/net/wireless/ath9k/beacon.c 2009-03-03 18:29:02.000000000 +0200
@@ -113,17 +113,16 @@ static void ath_beacon_setup(struct ath_
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;
@@ -208,15 +207,14 @@ static struct ath_buf *ath_beacon_genera
* 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)
@@ -246,16 +244,14 @@ int ath_beaconq_setup(struct ath_hw *ah)
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. */
@@ -275,22 +271,21 @@ int ath_beacon_alloc(struct ath_softc *s
*/
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++;
}
}
@@ -372,7 +367,7 @@ void ath_beacon_return(struct ath_softc
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--;
}
@@ -395,7 +390,8 @@ void ath_beacon_tasklet(unsigned long da
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;
@@ -442,15 +438,15 @@ void ath_beacon_tasklet(unsigned long da
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;
@@ -652,7 +648,8 @@ static void ath_beacon_config_sta(struct
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;
@@ -696,14 +693,12 @@ static void ath_beacon_config_adhoc(stru
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 */
@@ -715,16 +710,15 @@ void ath_beacon_config(struct ath_softc
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);
--- wireless-testing.orig/drivers/net/wireless/ath9k/main.c 2009-03-03 18:29:02.000000000 +0200
+++ wireless-testing/drivers/net/wireless/ath9k/main.c 2009-03-03 18:29:02.000000000 +0200
@@ -798,13 +798,10 @@ static int ath_key_config(struct ath_sof
* 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. */
@@ -913,7 +910,7 @@ static void ath9k_bss_assoc_info(struct
}
/* Configure the beacon */
- ath_beacon_config(sc, 0);
+ ath_beacon_config(sc, vif);
/* Reset rssi stats */
sc->nodestats.ns_avgbrssi = ATH_RSSI_DUMMY_MARKER;
@@ -1118,7 +1115,7 @@ static void ath_radio_enable(struct ath_
}
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);
@@ -1525,7 +1522,7 @@ static int ath_init(u16 devid, struct at
/* 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;
@@ -1713,7 +1710,7 @@ int ath_reset(struct ath_softc *sc, bool
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);
@@ -2125,11 +2122,7 @@ static int ath9k_add_interface(struct ie
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);
@@ -2138,16 +2131,24 @@ static int ath9k_add_interface(struct ie
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);
@@ -2156,14 +2157,15 @@ static int ath9k_add_interface(struct ie
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;
@@ -2198,9 +2200,9 @@ static int ath9k_add_interface(struct ie
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,
@@ -2208,6 +2210,7 @@ static void ath9k_remove_interface(struc
{
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");
@@ -2225,7 +2228,14 @@ static void ath9k_remove_interface(struc
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);
@@ -2362,13 +2372,13 @@ static int ath9k_config_interface(struct
*/
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);
}
}
--- wireless-testing.orig/drivers/net/wireless/ath9k/ath9k.h 2009-03-03 18:29:01.000000000 +0200
+++ wireless-testing/drivers/net/wireless/ath9k/ath9k.h 2009-03-03 18:29:02.000000000 +0200
@@ -439,7 +439,7 @@ struct ath_beacon {
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;
@@ -449,9 +449,9 @@ struct ath_beacon {
};
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);
/*******/
@@ -532,7 +532,6 @@ struct ath_rfkill {
*/
#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
@@ -595,7 +594,6 @@ struct ath_softc {
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;
--
--
Jouni Malinen PGP id EFC895FA
next prev parent reply other threads:[~2009-03-03 17:24 UTC|newest]
Thread overview: 18+ messages / expand[flat|nested] mbox.gz Atom feed top
2009-03-03 17:23 [PATCH 00/15] ath9k: Virtual interfaces and radios Jouni Malinen
2009-03-03 17:23 ` Jouni Malinen [this message]
2009-03-03 17:23 ` [PATCH 02/15] ath9k: Set BSSID mask based on configured interfaces Jouni Malinen
2009-03-03 17:23 ` [PATCH 03/15] ath9k: Add data structure for supporting virtual radio/wiphy operation Jouni Malinen
2009-03-03 17:23 ` [PATCH 04/15] ath9k: Add support for multiple secondary virtual wiphys Jouni Malinen
2009-03-03 17:23 ` [PATCH 05/15] ath9k: Configure RX filter for multi-BSSID broadcast Jouni Malinen
2009-03-03 17:23 ` [PATCH 06/15] ath9k: Virtual wiphy pause/unpause functionality Jouni Malinen
2009-03-03 17:23 ` [PATCH 07/15] ath9k: Add routines for switching between active virtual wiphys Jouni Malinen
2009-03-03 17:23 ` [PATCH 08/15] ath9k: Make start/stop operations aware of " Jouni Malinen
2009-03-03 17:23 ` [PATCH 09/15] ath9k: Register larger listen interval Jouni Malinen
2009-03-03 17:23 ` [PATCH 10/15] ath9k: Pause other virtual wiphys on channel change Jouni Malinen
2009-03-03 17:23 ` [PATCH 11/15] ath9k: Check virtual wiphy state on tx() Jouni Malinen
2009-03-03 17:23 ` [PATCH 12/15] ath9k: Add workaround to recover from failed channel changes Jouni Malinen
2009-03-03 17:23 ` [PATCH 13/15] ath9k: Special processing for channel changes during scan Jouni Malinen
2009-03-03 17:23 ` [PATCH 14/15] ath9k: Add a simple virtual wiphy scheduler Jouni Malinen
2009-03-03 17:23 ` [PATCH 15/15] ath9k: Add a debugfs interface for controlling virtual wiphys Jouni Malinen
2009-03-07 13:56 ` [PATCH 00/15] ath9k: Virtual interfaces and radios Florian Fainelli
2009-03-12 20:19 ` Jouni Malinen
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20090303172441.250416741@atheros.com \
--to=jouni.malinen@atheros.com \
--cc=linux-wireless@vger.kernel.org \
--cc=linville@tuxdriver.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.