summaryrefslogtreecommitdiff
path: root/drivers/net/wireless/ath9k
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/wireless/ath9k')
-rw-r--r--drivers/net/wireless/ath9k/beacon.c145
-rw-r--r--drivers/net/wireless/ath9k/core.c3
-rw-r--r--drivers/net/wireless/ath9k/core.h1
-rw-r--r--drivers/net/wireless/ath9k/hw.c18
-rw-r--r--drivers/net/wireless/ath9k/rc.c98
5 files changed, 127 insertions, 138 deletions
diff --git a/drivers/net/wireless/ath9k/beacon.c b/drivers/net/wireless/ath9k/beacon.c
index c43fd5861163..eedb465d25d3 100644
--- a/drivers/net/wireless/ath9k/beacon.c
+++ b/drivers/net/wireless/ath9k/beacon.c
@@ -16,7 +16,6 @@
/* Implementation of beacon processing. */
-#include <asm/unaligned.h>
#include "core.h"
/*
@@ -26,7 +25,6 @@
* the operating mode of the station (AP or AdHoc). Parameters are AIFS
* settings and channel width min/max
*/
-
static int ath_beaconq_config(struct ath_softc *sc)
{
struct ath_hal *ah = sc->sc_ah;
@@ -63,19 +61,18 @@ static int ath_beaconq_config(struct ath_softc *sc)
* up all required antenna switch parameters, rate codes, and channel flags.
* Beacons are always sent out at the lowest rate, and are not retried.
*/
-
static void ath_beacon_setup(struct ath_softc *sc,
- struct ath_vap *avp, struct ath_buf *bf)
+ struct ath_vap *avp, struct ath_buf *bf)
{
struct sk_buff *skb = (struct sk_buff *)bf->bf_mpdu;
struct ath_hal *ah = sc->sc_ah;
struct ath_desc *ds;
- int flags, antenna;
+ struct ath9k_11n_rate_series series[4];
const struct ath9k_rate_table *rt;
+ int flags, antenna;
u8 rix, rate;
int ctsrate = 0;
int ctsduration = 0;
- struct ath9k_11n_rate_series series[4];
DPRINTF(sc, ATH_DBG_BEACON, "%s: m %p len %u\n",
__func__, skb, skb->len);
@@ -115,20 +112,21 @@ static void ath_beacon_setup(struct ath_softc *sc,
rate |= rt->info[rix].shortPreamble;
ath9k_hw_set11n_txdesc(ah, ds,
- skb->len + FCS_LEN, /* frame length */
- ATH9K_PKT_TYPE_BEACON, /* Atheros packet type */
+ skb->len + FCS_LEN, /* frame length */
+ ATH9K_PKT_TYPE_BEACON, /* Atheros packet type */
avp->av_btxctl.txpower, /* txpower XXX */
- ATH9K_TXKEYIX_INVALID, /* no encryption */
- ATH9K_KEY_TYPE_CLEAR, /* no encryption */
- flags /* no ack, veol for beacons */
+ ATH9K_TXKEYIX_INVALID, /* no encryption */
+ ATH9K_KEY_TYPE_CLEAR, /* no encryption */
+ flags /* no ack,
+ veol for beacons */
);
/* NB: beacon's BufLen must be a multiple of 4 bytes */
ath9k_hw_filltxdesc(ah, ds,
roundup(skb->len, 4), /* buffer length */
- true, /* first segment */
- true, /* last segment */
- ds /* first descriptor */
+ true, /* first segment */
+ true, /* last segment */
+ ds /* first descriptor */
);
memzero(series, sizeof(struct ath9k_11n_rate_series) * 4);
@@ -153,22 +151,23 @@ static struct ath_buf *ath_beacon_generate(struct ath_softc *sc, int if_id)
struct ath_buf *bf;
struct ath_vap *avp;
struct sk_buff *skb;
- int cabq_depth;
struct ath_txq *cabq;
struct ieee80211_tx_info *info;
+ int cabq_depth;
+
avp = sc->sc_vaps[if_id];
+ ASSERT(avp);
cabq = sc->sc_cabq;
- ASSERT(avp);
-
if (avp->av_bcbuf == NULL) {
DPRINTF(sc, ATH_DBG_BEACON, "%s: avp=%p av_bcbuf=%p\n",
__func__, avp, avp->av_bcbuf);
return NULL;
}
+
bf = avp->av_bcbuf;
- skb = (struct sk_buff *) bf->bf_mpdu;
+ skb = (struct sk_buff *)bf->bf_mpdu;
if (skb) {
pci_unmap_single(sc->pdev, bf->bf_dmacontext,
skb_end_pointer(skb) - skb->head,
@@ -179,17 +178,19 @@ static struct ath_buf *ath_beacon_generate(struct ath_softc *sc, int if_id)
bf->bf_mpdu = skb;
if (skb == NULL)
return NULL;
+
info = IEEE80211_SKB_CB(skb);
if (info->flags & IEEE80211_TX_CTL_ASSIGN_SEQ) {
/*
* TODO: make sure the seq# gets assigned properly (vs. other
* TX frames)
*/
- struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
+ struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
sc->seq_no += 0x10;
hdr->seq_ctrl &= cpu_to_le16(IEEE80211_SCTL_FRAG);
hdr->seq_ctrl |= cpu_to_le16(sc->seq_no);
}
+
bf->bf_buf_addr = bf->bf_dmacontext =
pci_map_single(sc->pdev, skb->data,
skb_end_pointer(skb) - skb->head,
@@ -241,7 +242,6 @@ 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
* by the hardware using the self-linked descriptor + veol trick.
*/
-
static void ath_beacon_start_adhoc(struct ath_softc *sc, int if_id)
{
struct ath_hal *ah = sc->sc_ah;
@@ -278,7 +278,6 @@ static void ath_beacon_start_adhoc(struct ath_softc *sc, int if_id)
* min/max, and enable aifs). The info structure does not need to be
* persistant.
*/
-
int ath_beaconq_setup(struct ath_hal *ah)
{
struct ath9k_tx_queue_info qi;
@@ -299,26 +298,24 @@ int ath_beaconq_setup(struct ath_hal *ah)
* the ATH interface. This routine also calculates the beacon "slot" for
* staggared beacons in the mBSSID case.
*/
-
int ath_beacon_alloc(struct ath_softc *sc, int if_id)
{
struct ath_vap *avp;
- struct ieee80211_hdr *wh;
+ struct ieee80211_hdr *hdr;
struct ath_buf *bf;
struct sk_buff *skb;
+ __le64 tstamp;
avp = sc->sc_vaps[if_id];
ASSERT(avp);
/* Allocate a beacon descriptor if we haven't done so. */
if (!avp->av_bcbuf) {
- /*
- * Allocate beacon state for hostap/ibss. We know
- * a buffer is available.
- */
+ /* Allocate beacon state for hostap/ibss. We know
+ * a buffer is available. */
avp->av_bcbuf = list_first_entry(&sc->sc_bbuf,
- struct ath_buf, list);
+ struct ath_buf, list);
list_del(&avp->av_bcbuf->list);
if (sc->sc_ah->ah_opmode == ATH9K_M_HOSTAP ||
@@ -362,9 +359,7 @@ int ath_beacon_alloc(struct ath_softc *sc, int if_id)
}
/*
- * NB: the beacon data buffer must be 32-bit aligned;
- * we assume the wbuf routines will return us something
- * with this alignment (perhaps should assert).
+ * NB: the beacon data buffer must be 32-bit aligned.
* FIXME: Fill avp->av_btxctl.txpower and
* avp->av_btxctl.shortPreamble
*/
@@ -375,6 +370,9 @@ int ath_beacon_alloc(struct ath_softc *sc, int if_id)
return -ENOMEM;
}
+ tstamp = ((struct ieee80211_mgmt *)skb->data)->u.beacon.timestamp;
+ sc->bc_tstamp = le64_to_cpu(tstamp);
+
/*
* Calculate a TSF adjustment factor required for
* staggered beacons. Note that we assume the format
@@ -408,8 +406,8 @@ int ath_beacon_alloc(struct ath_softc *sc, int if_id)
__func__, "stagger",
avp->av_bslot, intval, (unsigned long long)tsfadjust);
- wh = (struct ieee80211_hdr *)skb->data;
- memcpy(&wh[1], &val, sizeof(val));
+ hdr = (struct ieee80211_hdr *)skb->data;
+ memcpy(&hdr[1], &val, sizeof(val));
}
bf->bf_buf_addr = bf->bf_dmacontext =
@@ -425,9 +423,8 @@ int ath_beacon_alloc(struct ath_softc *sc, int if_id)
* Reclaim beacon resources and return buffer to the pool.
*
* Checks the VAP to put the beacon frame buffer back to the ATH object
- * queue, and de-allocates any wbuf frames that were sent as CAB traffic.
+ * queue, and de-allocates any skbs that were sent as CAB traffic.
*/
-
void ath_beacon_return(struct ath_softc *sc, struct ath_vap *avp)
{
if (avp->av_bcbuf != NULL) {
@@ -459,10 +456,7 @@ void ath_beacon_return(struct ath_softc *sc, struct ath_vap *avp)
* Transmit one or more beacon frames at SWBA. Dynamic updates to the frame
* contents are done as needed and the slot time is also adjusted based on
* current state.
- *
- * This tasklet is not scheduled, it's called in ISR context.
*/
-
void ath9k_beacon_tasklet(unsigned long data)
{
struct ath_softc *sc = (struct ath_softc *)data;
@@ -490,6 +484,8 @@ void ath9k_beacon_tasklet(unsigned long data)
* and wait for the next. Missed beacons indicate
* a problem and should not occur. If we miss too
* many consecutive beacons reset the device.
+ *
+ * FIXME: Clean up this mess !!
*/
if (ath9k_hw_numtxpending(ah, sc->sc_bhalq) != 0) {
sc->sc_bmisscount++;
@@ -505,19 +501,16 @@ void ath9k_beacon_tasklet(unsigned long data)
__func__, sc->sc_bmisscount);
if (show_cycles) {
/*
- * Display cycle counter stats
- * from HW to aide in debug of
- * stickiness.
+ * Display cycle counter stats from HW
+ * to aide in debug of stickiness.
*/
- DPRINTF(sc,
- ATH_DBG_BEACON,
+ DPRINTF(sc, ATH_DBG_BEACON,
"%s: busy times: rx_clear=%d, "
"rx_frame=%d, tx_frame=%d\n",
__func__, rx_clear, rx_frame,
tx_frame);
} else {
- DPRINTF(sc,
- ATH_DBG_BEACON,
+ DPRINTF(sc, ATH_DBG_BEACON,
"%s: unable to obtain "
"busy times\n", __func__);
}
@@ -529,8 +522,7 @@ void ath9k_beacon_tasklet(unsigned long data)
} else if (sc->sc_bmisscount >= BSTUCK_THRESH) {
if (sc->sc_flags & SC_OP_NO_RESET) {
if (sc->sc_bmisscount == BSTUCK_THRESH) {
- DPRINTF(sc,
- ATH_DBG_BEACON,
+ DPRINTF(sc, ATH_DBG_BEACON,
"%s: beacon is officially "
"stuck\n", __func__);
ath9k_hw_dmaRegDump(ah);
@@ -542,13 +534,12 @@ void ath9k_beacon_tasklet(unsigned long data)
ath_bstuck_process(sc);
}
}
-
return;
}
+
if (sc->sc_bmisscount != 0) {
if (sc->sc_flags & SC_OP_NO_RESET) {
- DPRINTF(sc,
- ATH_DBG_BEACON,
+ DPRINTF(sc, ATH_DBG_BEACON,
"%s: resume beacon xmit after %u misses\n",
__func__, sc->sc_bmisscount);
} else {
@@ -572,10 +563,12 @@ void ath9k_beacon_tasklet(unsigned long data)
tsftu = TSF_TO_TU(tsf>>32, tsf);
slot = ((tsftu % intval) * ATH_BCBUF) / intval;
if_id = sc->sc_bslot[(slot + 1) % ATH_BCBUF];
+
DPRINTF(sc, ATH_DBG_BEACON,
- "%s: slot %d [tsf %llu tsftu %u intval %u] if_id %d\n",
- __func__, slot, (unsigned long long) tsf, tsftu,
- intval, if_id);
+ "%s: slot %d [tsf %llu tsftu %u intval %u] if_id %d\n",
+ __func__, slot, (unsigned long long)tsf, tsftu,
+ intval, if_id);
+
bfaddr = 0;
if (if_id != ATH_IF_ID_ANY) {
bf = ath_beacon_generate(sc, if_id);
@@ -632,9 +625,8 @@ void ath9k_beacon_tasklet(unsigned long data)
* Tasklet for Beacon Stuck processing
*
* Processing for Beacon Stuck.
- * Basically calls the ath_internal_reset function to reset the chip.
+ * Basically resets the chip.
*/
-
void ath_bstuck_process(struct ath_softc *sc)
{
DPRINTF(sc, ATH_DBG_BEACON,
@@ -658,13 +650,12 @@ void ath_bstuck_process(struct ath_softc *sc)
* interrupt when we stop seeing beacons from the AP
* we've associated with.
*/
-
void ath_beacon_config(struct ath_softc *sc, int if_id)
{
struct ath_hal *ah = sc->sc_ah;
- u32 nexttbtt, intval;
struct ath_beacon_config conf;
enum ath9k_opmode av_opmode;
+ u32 nexttbtt, intval;
if (if_id != ATH_IF_ID_ANY)
av_opmode = sc->sc_vaps[if_id]->av_opmode;
@@ -673,12 +664,6 @@ void ath_beacon_config(struct ath_softc *sc, int if_id)
memzero(&conf, sizeof(struct ath_beacon_config));
- /* FIXME: Use default values for now - Sujith */
- /* Query beacon configuration first */
- /*
- * Protocol stack doesn't support dynamic beacon configuration,
- * use default configurations.
- */
conf.beacon_interval = sc->hw->conf.beacon_int ?
sc->hw->conf.beacon_int : ATH_DEFAULT_BINTVAL;
conf.listen_interval = 1;
@@ -687,8 +672,8 @@ void ath_beacon_config(struct ath_softc *sc, int if_id)
conf.bmiss_timeout = ATH_DEFAULT_BMISS_LIMIT * conf.beacon_interval;
/* extract tstamp from last beacon and convert to TU */
- nexttbtt = TSF_TO_TU(get_unaligned_le32(conf.u.last_tstamp + 4),
- get_unaligned_le32(conf.u.last_tstamp));
+ nexttbtt = TSF_TO_TU(sc->bc_tstamp >> 32, sc->bc_tstamp);
+
/* XXX conditionalize multi-bss support? */
if (sc->sc_ah->ah_opmode == ATH9K_M_HOSTAP) {
/*
@@ -704,12 +689,14 @@ void ath_beacon_config(struct ath_softc *sc, int if_id)
intval = conf.beacon_interval & ATH9K_BEACON_PERIOD;
}
- if (nexttbtt == 0) /* e.g. for ap mode */
+ if (nexttbtt == 0) /* e.g. for ap mode */
nexttbtt = intval;
- else if (intval) /* NB: can be 0 for monitor mode */
+ else if (intval) /* NB: can be 0 for monitor mode */
nexttbtt = roundup(nexttbtt, intval);
+
DPRINTF(sc, ATH_DBG_BEACON, "%s: nexttbtt %u intval %u (%u)\n",
__func__, nexttbtt, intval, conf.beacon_interval);
+
/* Check for ATH9K_M_HOSTAP and sc_nostabeacons for WDS client */
if (sc->sc_ah->ah_opmode == ATH9K_M_STA) {
struct ath9k_beacon_state bs;
@@ -723,19 +710,19 @@ void ath_beacon_config(struct ath_softc *sc, int if_id)
* last beacon we received (which may be none).
*/
dtimperiod = conf.dtim_period;
- if (dtimperiod <= 0) /* NB: 0 if not known */
+ if (dtimperiod <= 0) /* NB: 0 if not known */
dtimperiod = 1;
dtimcount = conf.dtim_count;
- if (dtimcount >= dtimperiod) /* NB: sanity check */
- dtimcount = 0; /* XXX? */
- cfpperiod = 1; /* NB: no PCF support yet */
+ if (dtimcount >= dtimperiod) /* NB: sanity check */
+ dtimcount = 0;
+ cfpperiod = 1; /* NB: no PCF support yet */
cfpcount = 0;
sleepduration = conf.listen_interval * intval;
if (sleepduration <= 0)
sleepduration = intval;
-#define FUDGE 2
+#define FUDGE 2
/*
* Pull nexttbtt forward to reflect the current
* TSF and calculate dtim+cfp state for the result.
@@ -759,6 +746,7 @@ void ath_beacon_config(struct ath_softc *sc, int if_id)
bs.bs_cfpperiod = cfpperiod*bs.bs_dtimperiod;
bs.bs_cfpnext = bs.bs_nextdtim + cfpcount*bs.bs_dtimperiod;
bs.bs_cfpmaxduration = 0;
+
/*
* Calculate the number of consecutive beacons to miss
* before taking a BMISS interrupt. The configuration
@@ -767,9 +755,8 @@ void ath_beacon_config(struct ath_softc *sc, int if_id)
* result to at most 15 beacons.
*/
if (sleepduration > intval) {
- bs.bs_bmissthreshold =
- conf.listen_interval *
- ATH_DEFAULT_BMISS_LIMIT / 2;
+ bs.bs_bmissthreshold = conf.listen_interval *
+ ATH_DEFAULT_BMISS_LIMIT / 2;
} else {
bs.bs_bmissthreshold =
DIV_ROUND_UP(conf.bmiss_timeout, intval);
@@ -789,8 +776,8 @@ void ath_beacon_config(struct ath_softc *sc, int if_id)
* XXX fixed at 100ms
*/
- bs.bs_sleepduration =
- roundup(IEEE80211_MS_TO_TU(100), sleepduration);
+ bs.bs_sleepduration = roundup(IEEE80211_MS_TO_TU(100),
+ sleepduration);
if (bs.bs_sleepduration > bs.bs_dtimperiod)
bs.bs_sleepduration = bs.bs_dtimperiod;
@@ -834,9 +821,9 @@ void ath_beacon_config(struct ath_softc *sc, int if_id)
if (sc->sc_ah->ah_opmode == ATH9K_M_IBSS) {
/*
* Pull nexttbtt forward to reflect the current
- * TSF .
+ * TSF
*/
-#define FUDGE 2
+#define FUDGE 2
if (!(intval & ATH9K_BEACON_RESET_TSF)) {
tsf = ath9k_hw_gettsf64(ah);
tsftu = TSF_TO_TU((u32)(tsf>>32),
diff --git a/drivers/net/wireless/ath9k/core.c b/drivers/net/wireless/ath9k/core.c
index c262ef279ff3..690f7c56af3d 100644
--- a/drivers/net/wireless/ath9k/core.c
+++ b/drivers/net/wireless/ath9k/core.c
@@ -534,7 +534,8 @@ int ath_vap_attach(struct ath_softc *sc,
avp->av_opmode = opmode;
avp->av_bslot = -1;
- ath9k_hw_set_tsfadjust(sc->sc_ah, 1);
+ if (opmode == ATH9K_M_HOSTAP)
+ ath9k_hw_set_tsfadjust(sc->sc_ah, 1);
sc->sc_vaps[if_id] = avp;
sc->sc_nvaps++;
diff --git a/drivers/net/wireless/ath9k/core.h b/drivers/net/wireless/ath9k/core.h
index b66de29cf662..6ff3befe39f7 100644
--- a/drivers/net/wireless/ath9k/core.h
+++ b/drivers/net/wireless/ath9k/core.h
@@ -1001,6 +1001,7 @@ struct ath_softc {
u32 sc_bhalq;
u32 sc_bmisscount;
u32 ast_be_xmit; /* beacons transmitted */
+ u64 bc_tstamp;
/* Rate */
struct ieee80211_rate rates[IEEE80211_NUM_BANDS][ATH_RATE_MAX];
diff --git a/drivers/net/wireless/ath9k/hw.c b/drivers/net/wireless/ath9k/hw.c
index 0251e59f2f84..272c75816609 100644
--- a/drivers/net/wireless/ath9k/hw.c
+++ b/drivers/net/wireless/ath9k/hw.c
@@ -2526,6 +2526,11 @@ static void ath9k_ani_reset(struct ath_hal *ah)
}
}
+/*
+ * Process a MIB interrupt. We may potentially be invoked because
+ * any of the MIB counters overflow/trigger so don't assume we're
+ * here because a PHY error counter triggered.
+ */
void ath9k_hw_procmibevent(struct ath_hal *ah,
const struct ath9k_node_stats *stats)
{
@@ -2533,18 +2538,20 @@ void ath9k_hw_procmibevent(struct ath_hal *ah,
u32 phyCnt1, phyCnt2;
DPRINTF(ah->ah_sc, ATH_DBG_ANI, "Processing Mib Intr\n");
-
+ /* Reset these counters regardless */
REG_WRITE(ah, AR_FILT_OFDM, 0);
REG_WRITE(ah, AR_FILT_CCK, 0);
if (!(REG_READ(ah, AR_SLP_MIB_CTRL) & AR_SLP_MIB_PENDING))
REG_WRITE(ah, AR_SLP_MIB_CTRL, AR_SLP_MIB_CLEAR);
+ /* Clear the mib counters and save them in the stats */
ath9k_hw_update_mibstats(ah, &ahp->ah_mibStats);
ahp->ah_stats.ast_nodestats = *stats;
if (!DO_ANI(ah))
return;
+ /* NB: these are not reset-on-read */
phyCnt1 = REG_READ(ah, AR_PHY_ERR_1);
phyCnt2 = REG_READ(ah, AR_PHY_ERR_2);
if (((phyCnt1 & AR_MIBCNT_INTRMASK) == AR_MIBCNT_INTRMASK) ||
@@ -2552,6 +2559,7 @@ void ath9k_hw_procmibevent(struct ath_hal *ah,
struct ar5416AniState *aniState = ahp->ah_curani;
u32 ofdmPhyErrCnt, cckPhyErrCnt;
+ /* NB: only use ast_ani_*errs with AH_PRIVATE_DIAG */
ofdmPhyErrCnt = phyCnt1 - aniState->ofdmPhyErrBase;
ahp->ah_stats.ast_ani_ofdmerrs +=
ofdmPhyErrCnt - aniState->ofdmPhyErrCount;
@@ -2562,11 +2570,17 @@ void ath9k_hw_procmibevent(struct ath_hal *ah,
cckPhyErrCnt - aniState->cckPhyErrCount;
aniState->cckPhyErrCount = cckPhyErrCnt;
+ /*
+ * NB: figure out which counter triggered. If both
+ * trigger we'll only deal with one as the processing
+ * clobbers the error counter so the trigger threshold
+ * check will never be true.
+ */
if (aniState->ofdmPhyErrCount > aniState->ofdmTrigHigh)
ath9k_hw_ani_ofdm_err_trigger(ah);
if (aniState->cckPhyErrCount > aniState->cckTrigHigh)
ath9k_hw_ani_cck_err_trigger(ah);
-
+ /* NB: always restart to insure the h/w counters are reset */
ath9k_ani_restart(ah);
}
}
diff --git a/drivers/net/wireless/ath9k/rc.c b/drivers/net/wireless/ath9k/rc.c
index 1cc9daf44550..cca2fc5b0765 100644
--- a/drivers/net/wireless/ath9k/rc.c
+++ b/drivers/net/wireless/ath9k/rc.c
@@ -20,6 +20,7 @@
*/
#include "core.h"
+/* FIXME: remove this include! */
#include "../net/mac80211/rate.h"
static u32 tx_triglevel_max;
@@ -1812,20 +1813,18 @@ static void ath_rc_sib_init(struct ath_rate_node *ath_rc_priv)
}
-static void ath_setup_rates(struct ieee80211_local *local, struct sta_info *sta)
+static void ath_setup_rates(struct ath_softc *sc,
+ struct ieee80211_supported_band *sband,
+ struct ieee80211_sta *sta,
+ struct ath_rate_node *rc_priv)
{
- struct ieee80211_supported_band *sband;
- struct ieee80211_hw *hw = local_to_hw(local);
- struct ath_softc *sc = hw->priv;
- struct ath_rate_node *rc_priv = sta->rate_ctrl_priv;
int i, j = 0;
DPRINTF(sc, ATH_DBG_RATE, "%s\n", __func__);
- sband = local->hw.wiphy->bands[local->hw.conf.channel->band];
for (i = 0; i < sband->n_bitrates; i++) {
- if (sta->sta.supp_rates[local->hw.conf.channel->band] & BIT(i)) {
+ if (sta->supp_rates[sband->band] & BIT(i)) {
rc_priv->neg_rates.rs_rates[j]
= (sband->bitrates[i].bitrate * 2) / 10;
j++;
@@ -1852,19 +1851,17 @@ void ath_rc_node_update(struct ieee80211_hw *hw, struct ath_rate_node *rc_priv)
}
/* Rate Control callbacks */
-static void ath_tx_status(void *priv, struct net_device *dev,
+static void ath_tx_status(void *priv, struct ieee80211_supported_band *sband,
+ struct ieee80211_sta *sta, void *priv_sta,
struct sk_buff *skb)
{
struct ath_softc *sc = priv;
struct ath_tx_info_priv *tx_info_priv;
struct ath_node *an;
- struct sta_info *sta;
- struct ieee80211_local *local;
struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb);
struct ieee80211_hdr *hdr;
__le16 fc;
- local = hw_to_local(sc->hw);
hdr = (struct ieee80211_hdr *)skb->data;
fc = hdr->frame_control;
tx_info_priv = (struct ath_tx_info_priv *)tx_info->driver_data[0];
@@ -1873,8 +1870,7 @@ static void ath_tx_status(void *priv, struct net_device *dev,
an = ath_node_find(sc, hdr->addr1);
spin_unlock_bh(&sc->node_lock);
- sta = sta_info_get(local, hdr->addr1);
- if (!an || !sta || !ieee80211_is_data(fc)) {
+ if (!an || !priv_sta || !ieee80211_is_data(fc)) {
if (tx_info->driver_data[0] != NULL) {
kfree(tx_info->driver_data[0]);
tx_info->driver_data[0] = NULL;
@@ -1882,24 +1878,22 @@ static void ath_tx_status(void *priv, struct net_device *dev,
return;
}
if (tx_info->driver_data[0] != NULL) {
- ath_rate_tx_complete(sc, an, sta->rate_ctrl_priv, tx_info_priv);
+ ath_rate_tx_complete(sc, an, priv_sta, tx_info_priv);
kfree(tx_info->driver_data[0]);
tx_info->driver_data[0] = NULL;
}
}
static void ath_tx_aggr_resp(struct ath_softc *sc,
- struct sta_info *sta,
+ struct ieee80211_supported_band *sband,
+ struct ieee80211_sta *sta,
struct ath_node *an,
u8 tidno)
{
- struct ieee80211_hw *hw = sc->hw;
- struct ieee80211_local *local;
struct ath_atx_tid *txtid;
- struct ieee80211_supported_band *sband;
u16 buffersize = 0;
int state;
- DECLARE_MAC_BUF(mac);
+ struct sta_info *si;
if (!(sc->sc_flags & SC_OP_TXAGGR))
return;
@@ -1908,11 +1902,16 @@ static void ath_tx_aggr_resp(struct ath_softc *sc,
if (!txtid->paused)
return;
- local = hw_to_local(sc->hw);
- sband = hw->wiphy->bands[hw->conf.channel->band];
+ /*
+ * XXX: This is entirely busted, we aren't supposed to
+ * access the sta from here because it's internal
+ * to mac80211, and looking at the state without
+ * locking is wrong too.
+ */
+ si = container_of(sta, struct sta_info, sta);
buffersize = IEEE80211_MIN_AMPDU_BUF <<
sband->ht_info.ampdu_factor; /* FIXME */
- state = sta->ampdu_mlme.tid_state_tx[tidno];
+ state = si->ampdu_mlme.tid_state_tx[tidno];
if (state & HT_ADDBA_RECEIVED_MSK) {
txtid->addba_exchangecomplete = 1;
@@ -1928,18 +1927,15 @@ static void ath_tx_aggr_resp(struct ath_softc *sc,
}
}
-static void ath_get_rate(void *priv, struct net_device *dev,
- struct ieee80211_supported_band *sband,
- struct sk_buff *skb,
- struct rate_selection *sel)
+static void ath_get_rate(void *priv, struct ieee80211_supported_band *sband,
+ struct ieee80211_sta *sta, void *priv_sta,
+ struct sk_buff *skb, struct rate_selection *sel)
{
struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
- struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
- struct sta_info *sta;
- struct ath_softc *sc = (struct ath_softc *)priv;
+ struct ath_softc *sc = priv;
struct ieee80211_hw *hw = sc->hw;
struct ath_tx_info_priv *tx_info_priv;
- struct ath_rate_node *ath_rc_priv;
+ struct ath_rate_node *ath_rc_priv = priv_sta;
struct ath_node *an;
struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb);
int is_probe = FALSE, chk, ret;
@@ -1955,8 +1951,7 @@ static void ath_get_rate(void *priv, struct net_device *dev,
ASSERT(tx_info->driver_data[0] != NULL);
tx_info_priv = (struct ath_tx_info_priv *)tx_info->driver_data[0];
- sta = sta_info_get(local, hdr->addr1);
- lowest_idx = rate_lowest_index(local, sband, sta);
+ lowest_idx = rate_lowest_index(sband, sta);
tx_info_priv->min_rate = (sband->bitrates[lowest_idx].bitrate * 2) / 10;
/* lowest rate for management and multicast/broadcast frames */
if (!ieee80211_is_data(fc) ||
@@ -1965,8 +1960,6 @@ static void ath_get_rate(void *priv, struct net_device *dev,
return;
}
- ath_rc_priv = sta->rate_ctrl_priv;
-
/* Find tx rate for unicast frames */
ath_rate_findrate(sc, ath_rc_priv,
ATH_11N_TXMAXTRY, 4,
@@ -1975,8 +1968,7 @@ static void ath_get_rate(void *priv, struct net_device *dev,
&is_probe,
false);
if (is_probe)
- sel->probe_idx = ((struct ath_tx_ratectrl *)
- sta->rate_ctrl_priv)->probe_rate;
+ sel->probe_idx = ath_rc_priv->tx_ratectrl.probe_rate;
/* Ratecontrol sometimes returns invalid rate index */
if (tx_info_priv->rcs[0].rix != 0xff)
@@ -2020,37 +2012,31 @@ static void ath_get_rate(void *priv, struct net_device *dev,
__func__,
print_mac(mac, hdr->addr1));
} else if (chk == AGGR_EXCHANGE_PROGRESS)
- ath_tx_aggr_resp(sc, sta, an, tid);
+ ath_tx_aggr_resp(sc, sband, sta, an, tid);
}
}
}
-static void ath_rate_init(void *priv, void *priv_sta,
- struct ieee80211_local *local,
- struct sta_info *sta)
+static void ath_rate_init(void *priv, struct ieee80211_supported_band *sband,
+ struct ieee80211_sta *sta, void *priv_sta)
{
- struct ieee80211_supported_band *sband;
- struct ieee80211_hw *hw = local_to_hw(local);
- struct ieee80211_conf *conf = &local->hw.conf;
- struct ath_softc *sc = hw->priv;
+ struct ath_softc *sc = priv;
struct ath_rate_node *ath_rc_priv = priv_sta;
int i, j = 0;
DPRINTF(sc, ATH_DBG_RATE, "%s\n", __func__);
- sband = local->hw.wiphy->bands[local->hw.conf.channel->band];
-
- ath_setup_rates(local, sta);
- if (conf->flags & IEEE80211_CONF_SUPPORT_HT_MODE) {
+ ath_setup_rates(sc, sband, sta, ath_rc_priv);
+ if (sc->hw->conf.flags & IEEE80211_CONF_SUPPORT_HT_MODE) {
for (i = 0; i < MCS_SET_SIZE; i++) {
- if (conf->ht_conf.supp_mcs_set[i/8] & (1<<(i%8)))
+ if (sc->hw->conf.ht_conf.supp_mcs_set[i/8] & (1<<(i%8)))
ath_rc_priv->neg_ht_rates.rs_rates[j++] = i;
if (j == ATH_RATE_MAX)
break;
}
ath_rc_priv->neg_ht_rates.rs_nrates = j;
}
- ath_rc_node_update(hw, priv_sta);
+ ath_rc_node_update(sc->hw, priv_sta);
}
static void ath_rate_clear(void *priv)
@@ -2058,13 +2044,12 @@ static void ath_rate_clear(void *priv)
return;
}
-static void *ath_rate_alloc(struct ieee80211_local *local)
+static void *ath_rate_alloc(struct ieee80211_hw *hw, struct dentry *debugfsdir)
{
- struct ieee80211_hw *hw = local_to_hw(local);
struct ath_softc *sc = hw->priv;
DPRINTF(sc, ATH_DBG_RATE, "%s\n", __func__);
- return local->hw.priv;
+ return hw->priv;
}
static void ath_rate_free(void *priv)
@@ -2072,7 +2057,7 @@ static void ath_rate_free(void *priv)
return;
}
-static void *ath_rate_alloc_sta(void *priv, gfp_t gfp)
+static void *ath_rate_alloc_sta(void *priv, struct ieee80211_sta *sta, gfp_t gfp)
{
struct ath_softc *sc = priv;
struct ath_vap *avp = sc->sc_vaps[0];
@@ -2092,7 +2077,8 @@ static void *ath_rate_alloc_sta(void *priv, gfp_t gfp)
return rate_priv;
}
-static void ath_rate_free_sta(void *priv, void *priv_sta)
+static void ath_rate_free_sta(void *priv, struct ieee80211_sta *sta,
+ void *priv_sta)
{
struct ath_rate_node *rate_priv = priv_sta;
struct ath_softc *sc = priv;
@@ -2111,7 +2097,7 @@ static struct rate_control_ops ath_rate_ops = {
.alloc = ath_rate_alloc,
.free = ath_rate_free,
.alloc_sta = ath_rate_alloc_sta,
- .free_sta = ath_rate_free_sta
+ .free_sta = ath_rate_free_sta,
};
int ath_rate_control_register(void)