Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 5640b08e authored by Sujith's avatar Sujith Committed by John W. Linville
Browse files

ath9k: Revamp VAP management



Remove the internal VAP management routines
and embed ath_vap in mac80211's driver private area
provided in ieee80211_vif.

Signed-off-by: default avatarSujith <Sujith.Manoharan@atheros.com>
Signed-off-by: default avatarJohn W. Linville <linville@tuxdriver.com>
parent a37c2c79
Loading
Loading
Loading
Loading
+27 −13
Original line number Diff line number Diff line
@@ -152,12 +152,14 @@ static struct ath_buf *ath_beacon_generate(struct ath_softc *sc, int if_id)
	struct ath_vap *avp;
	struct sk_buff *skb;
	struct ath_txq *cabq;
	struct ieee80211_vif *vif;
	struct ieee80211_tx_info *info;
	int cabq_depth;

	avp = sc->sc_vaps[if_id];
	ASSERT(avp);
	vif = sc->sc_vaps[if_id];
	ASSERT(vif);

	avp = (void *)vif->drv_priv;
	cabq = sc->sc_cabq;

	if (avp->av_bcbuf == NULL) {
@@ -174,7 +176,7 @@ static struct ath_buf *ath_beacon_generate(struct ath_softc *sc, int if_id)
				 PCI_DMA_TODEVICE);
	}

	skb = ieee80211_beacon_get(sc->hw, avp->av_if_data);
	skb = ieee80211_beacon_get(sc->hw, vif);
	bf->bf_mpdu = skb;
	if (skb == NULL)
		return NULL;
@@ -196,7 +198,7 @@ static struct ath_buf *ath_beacon_generate(struct ath_softc *sc, int if_id)
			       skb_end_pointer(skb) - skb->head,
			       PCI_DMA_TODEVICE);

	skb = ieee80211_get_buffered_bc(sc->hw, avp->av_if_data);
	skb = ieee80211_get_buffered_bc(sc->hw, vif);

	/*
	 * if the CABQ traffic from previous DTIM is pending and the current
@@ -232,7 +234,7 @@ static struct ath_buf *ath_beacon_generate(struct ath_softc *sc, int if_id)
	 */
	while (skb) {
		ath_tx_cabq(sc, skb);
		skb = ieee80211_get_buffered_bc(sc->hw, avp->av_if_data);
		skb = ieee80211_get_buffered_bc(sc->hw, vif);
	}

	return bf;
@@ -244,13 +246,16 @@ static struct ath_buf *ath_beacon_generate(struct ath_softc *sc, int if_id)
*/
static void ath_beacon_start_adhoc(struct ath_softc *sc, int if_id)
{
	struct ieee80211_vif *vif;
	struct ath_hal *ah = sc->sc_ah;
	struct ath_buf *bf;
	struct ath_vap *avp;
	struct sk_buff *skb;

	avp = sc->sc_vaps[if_id];
	ASSERT(avp);
	vif = sc->sc_vaps[if_id];
	ASSERT(vif);

	avp = (void *)vif->drv_priv;

	if (avp->av_bcbuf == NULL) {
		DPRINTF(sc, ATH_DBG_BEACON, "%s: avp=%p av_bcbuf=%p\n",
@@ -300,14 +305,17 @@ int ath_beaconq_setup(struct ath_hal *ah)
*/
int ath_beacon_alloc(struct ath_softc *sc, int if_id)
{
	struct ieee80211_vif *vif;
	struct ath_vap *avp;
	struct ieee80211_hdr *hdr;
	struct ath_buf *bf;
	struct sk_buff *skb;
	__le64 tstamp;

	avp = sc->sc_vaps[if_id];
	ASSERT(avp);
	vif = sc->sc_vaps[if_id];
	ASSERT(vif);

	avp = (void *)vif->drv_priv;

	/* Allocate a beacon descriptor if we haven't done so. */
	if (!avp->av_bcbuf) {
@@ -363,7 +371,7 @@ int ath_beacon_alloc(struct ath_softc *sc, int if_id)
	 * FIXME: Fill avp->av_btxctl.txpower and
	 * avp->av_btxctl.shortPreamble
	 */
	skb = ieee80211_beacon_get(sc->hw, avp->av_if_data);
	skb = ieee80211_beacon_get(sc->hw, vif);
	if (skb == NULL) {
		DPRINTF(sc, ATH_DBG_BEACON, "%s: cannot get skb\n",
			__func__);
@@ -652,15 +660,21 @@ void ath_bstuck_process(struct ath_softc *sc)
 */
void ath_beacon_config(struct ath_softc *sc, int if_id)
{
	struct ieee80211_vif *vif;
	struct ath_hal *ah = sc->sc_ah;
	struct ath_beacon_config conf;
	struct ath_vap *avp;
	enum ath9k_opmode av_opmode;
	u32 nexttbtt, intval;

	if (if_id != ATH_IF_ID_ANY)
		av_opmode = sc->sc_vaps[if_id]->av_opmode;
	else
	if (if_id != ATH_IF_ID_ANY) {
		vif = sc->sc_vaps[if_id];
		ASSERT(vif);
		avp = (void *)vif->drv_priv;
		av_opmode = avp->av_opmode;
	} else {
		av_opmode = sc->sc_ah->ah_opmode;
	}

	memset(&conf, 0, sizeof(struct ath_beacon_config));

+1 −115
Original line number Diff line number Diff line
@@ -14,8 +14,6 @@
 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 */

 /* Implementation of the main "ATH" layer. */

#include "core.h"
#include "regd.h"

@@ -641,114 +639,6 @@ static void ath_ani_calibrate(unsigned long data)
	mod_timer(&sc->sc_ani.timer, jiffies + msecs_to_jiffies(cal_interval));
}

/******************/
/* VAP management */
/******************/

int ath_vap_attach(struct ath_softc *sc,
		   int if_id,
		   struct ieee80211_vif *if_data,
		   enum ath9k_opmode opmode)
{
	struct ath_vap *avp;

	if (if_id >= ATH_BCBUF || sc->sc_vaps[if_id] != NULL) {
		DPRINTF(sc, ATH_DBG_FATAL,
			"%s: Invalid interface id = %u\n", __func__, if_id);
		return -EINVAL;
	}

	switch (opmode) {
	case ATH9K_M_STA:
	case ATH9K_M_IBSS:
	case ATH9K_M_MONITOR:
		break;
	case ATH9K_M_HOSTAP:
		/* XXX not right, beacon buffer is allocated on RUN trans */
		if (list_empty(&sc->sc_bbuf))
			return -ENOMEM;
		break;
	default:
		return -EINVAL;
	}

	/* create ath_vap */
	avp = kmalloc(sizeof(struct ath_vap), GFP_KERNEL);
	if (avp == NULL)
		return -ENOMEM;

	memset(avp, 0, sizeof(struct ath_vap));
	avp->av_if_data = if_data;
	/* Set the VAP opmode */
	avp->av_opmode = opmode;
	avp->av_bslot = -1;

	if (opmode == ATH9K_M_HOSTAP)
		ath9k_hw_set_tsfadjust(sc->sc_ah, 1);

	sc->sc_vaps[if_id] = avp;
	sc->sc_nvaps++;
	/* Set the device opmode */
	sc->sc_ah->ah_opmode = opmode;

	/* default VAP configuration */
	avp->av_config.av_fixed_rateset = IEEE80211_FIXED_RATE_NONE;
	avp->av_config.av_fixed_retryset = 0x03030303;

	return 0;
}

int ath_vap_detach(struct ath_softc *sc, int if_id)
{
	struct ath_hal *ah = sc->sc_ah;
	struct ath_vap *avp;

	avp = sc->sc_vaps[if_id];
	if (avp == NULL) {
		DPRINTF(sc, ATH_DBG_FATAL, "%s: invalid interface id %u\n",
			__func__, if_id);
		return -EINVAL;
	}

	/*
	 * Quiesce the hardware while we remove the vap.  In
	 * particular we need to reclaim all references to the
	 * vap state by any frames pending on the tx queues.
	 *
	 * XXX can we do this w/o affecting other vap's?
	 */
	ath9k_hw_set_interrupts(ah, 0);	/* disable interrupts */
	ath_draintxq(sc, false);	/* stop xmit side */
	ath_stoprecv(sc);	/* stop recv side */
	ath_flushrecv(sc);	/* flush recv queue */

	kfree(avp);
	sc->sc_vaps[if_id] = NULL;
	sc->sc_nvaps--;

	return 0;
}

int ath_vap_config(struct ath_softc *sc,
	int if_id, struct ath_vap_config *if_config)
{
	struct ath_vap *avp;

	if (if_id >= ATH_BCBUF) {
		DPRINTF(sc, ATH_DBG_FATAL,
			"%s: Invalid interface id = %u\n", __func__, if_id);
		return -EINVAL;
	}

	avp = sc->sc_vaps[if_id];
	ASSERT(avp != NULL);

	if (avp)
		memcpy(&avp->av_config, if_config, sizeof(avp->av_config));

	return 0;
}

/********/
/* Core */
/********/
@@ -1356,14 +1246,10 @@ void ath_deinit(struct ath_softc *sc)
/* Node Management */
/*******************/

void ath_node_attach(struct ath_softc *sc, struct ieee80211_sta *sta, int if_id)
void ath_node_attach(struct ath_softc *sc, struct ieee80211_sta *sta)
{
	struct ath_vap *avp;
	struct ath_node *an;

	avp = sc->sc_vaps[if_id];
	ASSERT(avp != NULL);

	an = (struct ath_node *)sta->drv_priv;

	if (sc->sc_flags & SC_OP_TXAGGR)
+3 −13
Original line number Diff line number Diff line
@@ -635,8 +635,7 @@ int ath_tx_aggr_start(struct ath_softc *sc, struct ieee80211_sta *sta,
int ath_tx_aggr_stop(struct ath_softc *sc, struct ieee80211_sta *sta, u16 tid);
void ath_newassoc(struct ath_softc *sc,
	struct ath_node *node, int isnew, int isuapsd);
void ath_node_attach(struct ath_softc *sc, struct ieee80211_sta *sta,
		     int if_id);
void ath_node_attach(struct ath_softc *sc, struct ieee80211_sta *sta);
void ath_node_detach(struct ath_softc *sc, struct ieee80211_sta *sta);

/*******************/
@@ -701,23 +700,14 @@ struct ath_vap_config {

/* driver-specific vap state */
struct ath_vap {
	struct ieee80211_vif *av_if_data;
	int av_bslot;			/* beacon slot index */
	enum ath9k_opmode av_opmode;	/* VAP operational mode */
	struct ath_buf *av_bcbuf;	/* beacon buffer */
	struct ath_tx_control av_btxctl;  /* txctl information for beacon */
	int av_bslot;			/* beacon slot index */
	struct ath_vap_config av_config;/* vap configuration parameters*/
	struct ath_rate_node *rc_node;
};

int ath_vap_attach(struct ath_softc *sc,
		   int if_id,
		   struct ieee80211_vif *if_data,
		   enum ath9k_opmode opmode);
int ath_vap_detach(struct ath_softc *sc, int if_id);
int ath_vap_config(struct ath_softc *sc,
		   int if_id, struct ath_vap_config *if_config);

/*********************/
/* Antenna diversity */
/*********************/
@@ -925,7 +915,7 @@ struct ath_softc {

	u8 sc_nbcnvaps;			/* # of vaps sending beacons */
	u16 sc_nvaps;			/* # of active virtual ap's */
	struct ath_vap *sc_vaps[ATH_BCBUF];
	struct ieee80211_vif *sc_vaps[ATH_BCBUF];

	u8 sc_mcastantenna;
	u8 sc_defant;			/* current default antenna */
+29 −51
Original line number Diff line number Diff line
@@ -162,7 +162,7 @@ static int ath_key_config(struct ath_softc *sc,
	if (!sc->sc_vaps[0])
		return -EIO;

	vif = sc->sc_vaps[0]->av_if_data;
	vif = sc->sc_vaps[0];
	opmode = vif->type;

	/*
@@ -313,11 +313,12 @@ static void ath9k_ht_conf(struct ath_softc *sc,
}

static void ath9k_bss_assoc_info(struct ath_softc *sc,
				 struct ieee80211_vif *vif,
				 struct ieee80211_bss_conf *bss_conf)
{
	struct ieee80211_hw *hw = sc->hw;
	struct ieee80211_channel *curchan = hw->conf.channel;
	struct ath_vap *avp;
	struct ath_vap *avp = (void *)vif->drv_priv;
	int pos;

	if (bss_conf->assoc) {
@@ -325,13 +326,6 @@ static void ath9k_bss_assoc_info(struct ath_softc *sc,
			__func__,
			bss_conf->aid);

		avp = sc->sc_vaps[0];
		if (avp == NULL) {
			DPRINTF(sc, ATH_DBG_FATAL, "%s: Invalid interface\n",
				__func__);
			return;
		}

		/* New association, store aid */
		if (avp->av_opmode == ATH9K_M_STA) {
			sc->sc_curaid = bss_conf->aid;
@@ -906,6 +900,7 @@ static int ath_attach(u16 devid,

	hw->queues = 4;
	hw->sta_data_size = sizeof(struct ath_node);
	hw->vif_data_size = sizeof(struct ath_vap);

	/* Register rate control */
	hw->rate_control_algorithm = "ath9k_rate_control";
@@ -1091,7 +1086,8 @@ static int ath9k_add_interface(struct ieee80211_hw *hw,
			       struct ieee80211_if_init_conf *conf)
{
	struct ath_softc *sc = hw->priv;
	int error, ic_opmode = 0;
	struct ath_vap *avp = (void *)conf->vif->drv_priv;
	int ic_opmode = 0;

	/* Support only vap for now */

@@ -1119,13 +1115,22 @@ static int ath9k_add_interface(struct ieee80211_hw *hw,
		__func__,
		ic_opmode);

	error = ath_vap_attach(sc, 0, conf->vif, ic_opmode);
	if (error) {
		DPRINTF(sc, ATH_DBG_FATAL,
			"%s: Unable to attach vap, error: %d\n",
			__func__, error);
		return error;
	}
	/* Set the VAP opmode */
	avp->av_opmode = ic_opmode;
	avp->av_bslot = -1;

	if (ic_opmode == ATH9K_M_HOSTAP)
		ath9k_hw_set_tsfadjust(sc->sc_ah, 1);

	sc->sc_vaps[0] = conf->vif;
	sc->sc_nvaps++;

	/* Set the device opmode */
	sc->sc_ah->ah_opmode = ic_opmode;

	/* default VAP configuration */
	avp->av_config.av_fixed_rateset = IEEE80211_FIXED_RATE_NONE;
	avp->av_config.av_fixed_retryset = 0x03030303;

	if (conf->type == NL80211_IFTYPE_AP) {
		/* TODO: is this a suitable place to start ANI for AP mode? */
@@ -1141,27 +1146,16 @@ static void ath9k_remove_interface(struct ieee80211_hw *hw,
				   struct ieee80211_if_init_conf *conf)
{
	struct ath_softc *sc = hw->priv;
	struct ath_vap *avp;
	int error;
	struct ath_vap *avp = (void *)conf->vif->drv_priv;

	DPRINTF(sc, ATH_DBG_CONFIG, "%s: Detach VAP\n", __func__);

	avp = sc->sc_vaps[0];
	if (avp == NULL) {
		DPRINTF(sc, ATH_DBG_FATAL, "%s: Invalid interface\n",
			__func__);
		return;
	}

#ifdef CONFIG_SLOW_ANT_DIV
	ath_slow_ant_div_stop(&sc->sc_antdiv);
#endif
	/* Stop ANI */
	del_timer_sync(&sc->sc_ani.timer);

	/* Update ratectrl */
	ath_rate_newstate(sc, avp);

	/* Reclaim beacon resources */
	if (sc->sc_ah->ah_opmode == ATH9K_M_HOSTAP ||
	    sc->sc_ah->ah_opmode == ATH9K_M_IBSS) {
@@ -1169,16 +1163,10 @@ static void ath9k_remove_interface(struct ieee80211_hw *hw,
		ath_beacon_return(sc, avp);
	}

	/* Set interrupt mask */
	sc->sc_imask &= ~(ATH9K_INT_SWBA | ATH9K_INT_BMISS);
	ath9k_hw_set_interrupts(sc->sc_ah, sc->sc_imask & ~ATH9K_INT_GLOBAL);
	sc->sc_flags &= ~SC_OP_BEACONS;

	error = ath_vap_detach(sc, 0);
	if (error)
		DPRINTF(sc, ATH_DBG_FATAL,
			"%s: Unable to detach vap, error: %d\n",
			__func__, error);
	sc->sc_vaps[0] = NULL;
	sc->sc_nvaps--;
}

static int ath9k_config(struct ieee80211_hw *hw, u32 changed)
@@ -1226,17 +1214,10 @@ static int ath9k_config_interface(struct ieee80211_hw *hw,
{
	struct ath_softc *sc = hw->priv;
	struct ath_hal *ah = sc->sc_ah;
	struct ath_vap *avp;
	struct ath_vap *avp = (void *)vif->drv_priv;
	u32 rfilt = 0;
	int error, i;

	avp = sc->sc_vaps[0];
	if (avp == NULL) {
		DPRINTF(sc, ATH_DBG_FATAL, "%s: Invalid interface\n",
			__func__);
		return -EINVAL;
	}

	/* TODO: Need to decide which hw opmode to use for multi-interface
	 * cases */
	if (vif->type == NL80211_IFTYPE_AP &&
@@ -1317,7 +1298,7 @@ static int ath9k_config_interface(struct ieee80211_hw *hw,
	}

	/* Check for WLAN_CAPABILITY_PRIVACY ? */
	if ((avp->av_opmode != NL80211_IFTYPE_STATION)) {
	if ((avp->av_opmode != ATH9K_M_STA)) {
		for (i = 0; i < IEEE80211_WEP_NKID; i++)
			if (ath9k_hw_keyisvalid(sc->sc_ah, (u16)i))
				ath9k_hw_keysetmac(sc->sc_ah,
@@ -1366,9 +1347,6 @@ static void ath9k_configure_filter(struct ieee80211_hw *hw,
		__func__, sc->rx_filter);
}

/* Only a single interface is currently supported,
   so pass 0 as the interface id to ath_node_attach */

static void ath9k_sta_notify(struct ieee80211_hw *hw,
			     struct ieee80211_vif *vif,
			     enum sta_notify_cmd cmd,
@@ -1378,7 +1356,7 @@ static void ath9k_sta_notify(struct ieee80211_hw *hw,

	switch (cmd) {
	case STA_NOTIFY_ADD:
		ath_node_attach(sc, sta, 0);
		ath_node_attach(sc, sta);
		break;
	case STA_NOTIFY_REMOVE:
		ath_node_detach(sc, sta);
@@ -1496,7 +1474,7 @@ static void ath9k_bss_info_changed(struct ieee80211_hw *hw,
		DPRINTF(sc, ATH_DBG_CONFIG, "%s: BSS Changed ASSOC %d\n",
			__func__,
			bss_conf->assoc);
		ath9k_bss_assoc_info(sc, bss_conf);
		ath9k_bss_assoc_info(sc, vif, bss_conf);
	}
}

+7 −1
Original line number Diff line number Diff line
@@ -2042,12 +2042,18 @@ static void ath_rate_free(void *priv)

static void *ath_rate_alloc_sta(void *priv, struct ieee80211_sta *sta, gfp_t gfp)
{
	struct ieee80211_vif *vif;
	struct ath_softc *sc = priv;
	struct ath_vap *avp = sc->sc_vaps[0];
	struct ath_vap *avp;
	struct ath_rate_node *rate_priv;

	DPRINTF(sc, ATH_DBG_RATE, "%s\n", __func__);

	vif = sc->sc_vaps[0];
	ASSERT(vif);

	avp = (void *)vif->drv_priv;

	rate_priv = ath_rate_node_alloc(avp, sc->sc_rc, gfp);
	if (!rate_priv) {
		DPRINTF(sc, ATH_DBG_FATAL,