+/*
+ * Copyright (c) 2013 Qualcomm Atheros, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted (subject to the limitations in the
+ * disclaimer below) provided that the following conditions are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the
+ * distribution.
+ *
+ * * Neither the name of Qualcomm Atheros nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE
+ * GRANTED BY THIS LICENSE. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT
+ * HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
#include <adf_os_types.h>
#include <adf_os_dma.h>
#include <adf_os_timer.h>
#include <adf_os_atomic.h>
#include <adf_nbuf.h>
#include <adf_net.h>
-#include <adf_net_types.h>
#include <ieee80211_var.h>
#include "ratectrl.h"
#include "ratectrl11n.h"
-INLINE A_RSSI median(A_RSSI a, A_RSSI b, A_RSSI c);
-
static void ath_rate_newassoc_11n(struct ath_softc_tgt *sc, struct ath_node_target *an, int isnew,
unsigned int capflag, struct ieee80211_rate *rs);
}
-static INLINE A_BOOL
-rcIsValidTxMask(TX_RATE_CTRL *pRc, A_UINT8 index)
-{
- ASSERT(index < pRc->rateTableSize);
- return (pRc->validRateIndex[index]);
-}
-
/* Iterators for validTxRateMask */
static INLINE A_BOOL
rcGetNextValidTxRate(const RATE_TABLE_11N *pRateTable, TX_RATE_CTRL *pRc,
A_UINT8 i, j, hi = 0;
A_UINT8 singleStream = (capflag & WLAN_RC_DS_FLAG) ? 0 : 1;
A_UINT32 valid;
- struct atheros_node *pSib = ATH_NODE_ATHEROS(an);
/* Use intersection of working rates and valid rates */
for (i = 0; i < pRateSet->rs_nrates; i++) {
for (j = 0; j < pRateTable->rateCount; j++) {
A_UINT32 phy = pRateTable->info[j].phy;
-
#ifdef MAGPIE_MERLIN
+ struct atheros_node *pSib = ATH_NODE_ATHEROS(an);
+
if (pSib->stbc) {
valid = pRateTable->info[j].validSTBC;
} else if (singleStream) {
A_UINT8 i, j, hi = 0;
A_UINT8 singleStream = (capflag & WLAN_RC_DS_FLAG) ? 0 : 1;
A_UINT8 valid;
- struct atheros_node *pSib = ATH_NODE_ATHEROS(an);
/* Use intersection of working rates and valid rates */
for (i = 0; i < ((struct ieee80211_rateset *)pMcsSet)->rs_nrates; i++) {
for (j = 0; j < pRateTable->rateCount; j++) {
A_UINT32 phy = pRateTable->info[j].phy;
-
#ifdef MAGPIE_MERLIN
+ struct atheros_node *pSib = ATH_NODE_ATHEROS(an);
+
if (pSib->stbc) {
valid = pRateTable->info[j].validSTBC;
} else if (singleStream) {
rcSortValidRates(pRateTable, pRc);
}
-void
-rcSibUpdate_11n(struct ath_softc_tgt *sc, struct ath_node_target *pSib,
- A_UINT32 capflag, A_BOOL keepState, struct ieee80211_rate *pRateSet)
-{
- rcSibUpdate_ht(sc,
- pSib,
- ((capflag & ATH_RC_DS_FLAG) ? WLAN_RC_DS_FLAG : 0) |
- ((capflag & ATH_RC_HT40_SGI_FLAG) ? WLAN_RC_HT40_SGI_FLAG : 0) |
- ((capflag & ATH_RC_HT_FLAG) ? WLAN_RC_HT_FLAG : 0) |
- ((capflag & ATH_RC_CW40_FLAG) ? WLAN_RC_40_FLAG : 0) |
- ((capflag & ATH_RC_TX_STBC_FLAG) ? WLAN_RC_STBC_FLAG : 0),
- keepState,
- pRateSet);
-}
-
-/*
- * Return the median of three numbers
- */
-INLINE A_RSSI median(A_RSSI a, A_RSSI b, A_RSSI c)
-{
- if (a >= b) {
- if (b >= c) {
- return b;
- } else if (a > c) {
- return c;
- } else {
- return a;
- }
- } else {
- if (a >= c) {
- return a;
- } else if (b >= c) {
- return c;
- } else {
- return b;
- }
- }
-}
-
static A_UINT8
rcRateFind_ht(struct ath_softc_tgt *sc, struct atheros_node *pSib,
const RATE_TABLE_11N *pRateTable, A_BOOL probeAllowed, A_BOOL *isProbing)
A_UINT32 bestThruput, thisThruput;
A_UINT32 nowMsec;
A_UINT8 rate, nextRate, bestRate;
- A_RSSI rssiLast, rssiReduce = 0;
A_UINT8 maxIndex, minIndex;
A_INT8 index;
TX_RATE_CTRL *pRc = NULL;
struct atheros_node *asn = ATH_NODE_ATHEROS(an);
A_UINT8 rix, nrix;
A_UINT8 dot11Rate;
- A_UINT8 rateCode;
WLAN_PHY phy;
rix = rcRateFind_ht(sc, asn, pRateTable, (rcflag & ATH_RC_PROBE_ALLOWED) ? 1 : 0,
{
TX_RATE_CTRL *pRc;
A_UINT32 nowMsec = A_MS_TICKGET();
- A_BOOL stateChange = FALSE;
A_UINT8 lastPer;
int rate,count;
struct atheros_node *pSib = ATH_NODE_ATHEROS(an);
struct atheros_softc *asc = (struct atheros_softc*)sc->sc_rc;
RATE_TABLE_11N *pRateTable = (RATE_TABLE_11N *)asc->hwRateTable[sc->sc_curmode];
- u_int32_t txRateKbps;
static A_UINT32 nRetry2PerLookup[10] = {
100 * 0 / 1, // 0
return &asc->arc;
}
-void
-ath_rate_detach(struct ath_ratectrl *rc)
-{
- adf_os_mem_free(rc);
-}
-
void
ath_rate_findrate(struct ath_softc_tgt *sc,
struct ath_node_target *an,
struct ath_rc_series series[],
int *isProbe)
{
- struct ieee80211vap *vap = an->ni.ni_vap;
- struct atheros_node *oan = ATH_NODE_ATHEROS(an);
- struct atheros_softc *asc = (struct atheros_softc *) sc->sc_rc;
- RATE_TABLE *pRateTable = (RATE_TABLE *)asc->hwRateTable[sc->sc_curmode];
- u_int32_t *retrySched;
-
*isProbe = 0;
if (!numRates || !numTries) {
struct ath_rc_series rcs[],
int nframes, int nbad)
{
- struct atheros_softc *asc = (struct atheros_softc *) sc->sc_rc;
- const RATE_TABLE *pRateTable = (RATE_TABLE *)asc->hwRateTable[sc->sc_curmode];
- u_int8_t txRate = ds->ds_txstat.ts_rate &~ HAL_TXSTAT_ALTRATE;
-
ath_rate_tx_complete_11n(sc, an, ds, rcs, nframes, nbad);
}
struct atheros_softc *asc = (struct atheros_softc *) sc->sc_rc;
asc->tx_chainmask = sc->sc_ic.ic_tx_chainmask;
- ath_rate_newassoc(sc, ni, 1, capflag, rs);
+ ath_rate_newassoc(sc, ATH_NODE_TARGET(ni), 1, capflag, rs);
}
static void
struct ath_rc_series series[],
int *isProbe)
{
- struct ieee80211vap *vap = an->ni.ni_vap;
- struct atheros_node *oan = ATH_NODE_ATHEROS(an);
-
*isProbe = 0;
if (!numRates || !numTries) {
return;
ath_rate_newassoc_11n(struct ath_softc_tgt *sc, struct ath_node_target *an, int isnew,
unsigned int capflag, struct ieee80211_rate *rs)
{
- struct ieee80211vap *vap = an->ni.ni_vap;
-
if (isnew) {
- struct atheros_node *oan = ATH_NODE_ATHEROS(an);
-
- oan->htcap = ((capflag & ATH_RC_DS_FLAG) ? WLAN_RC_DS_FLAG : 0) |
- ((capflag & ATH_RC_HT40_SGI_FLAG) ? WLAN_RC_HT40_SGI_FLAG : 0) |
- ((capflag & ATH_RC_HT_FLAG) ? WLAN_RC_HT_FLAG : 0) |
- ((capflag & ATH_RC_CW40_FLAG) ? WLAN_RC_40_FLAG : 0) |
- ((capflag & ATH_RC_WEP_TKIP_FLAG) ? WLAN_RC_WEP_TKIP_FLAG : 0);
-
#ifdef MAGPIE_MERLIN
- /* Rx STBC is a 2-bit mask. Needs to convert from ath definition to wlan definition. */
-
- oan->htcap |= (((capflag & ATH_RC_RX_STBC_FLAG) >> ATH_RC_RX_STBC_FLAG_S)
- << WLAN_RC_STBC_FLAG_S);
-
- /* If only one chain is enabled, do not do stbc. */
- if (sc->sc_txstbcsupport) {
- oan->stbc = (capflag & ATH_RC_RX_STBC_FLAG) >> ATH_RC_RX_STBC_FLAG_S;
- } else {
- oan->stbc = 0;
- }
-
+ struct atheros_node *oan = ATH_NODE_ATHEROS(an);
+ /* Only MERLIN can send STBC */
+ oan->stbc = (capflag & ATH_RC_TX_STBC_FLAG) ? 1 : 0;
#endif
- rcSibUpdate_11n(sc, an, oan->htcap, 0, rs);
+ rcSibUpdate_ht(sc, an, capflag, 0, rs);
}
}
-
-void ath_rate_mcs2rate(struct ath_softc_tgt *sc,a_uint8_t sgi, a_uint8_t ht40,
- a_uint8_t rateCode, a_uint32_t *txrate, a_uint32_t *rxrate)
-{
- int idx;
- struct atheros_softc *asc = (struct atheros_softc*)sc->sc_rc;
- RATE_TABLE_11N *pRateTable = (RATE_TABLE_11N *)asc->hwRateTable[sc->sc_curmode];
- a_uint32_t rateKbps = 0;
-
- *txrate = asc->currentTxRateKbps;
-
- /* look 11NA table for rateKbps*/
- for (idx = 0; idx < pRateTable->rateCount && !rateKbps; ++idx) {
- if (pRateTable->info[idx].rateCode == rateCode) {
- if(ht40 && sgi) {
- if(pRateTable->info[idx].valid == TRUE_40 &&
- pRateTable->info[idx].phy == WLAN_RC_PHY_HT_40_DS_HGI)
- rateKbps = pRateTable->info[idx].rateKbps;
- } else if (ht40) {
- if (pRateTable->info[idx].valid == TRUE_40)/* HT40 only*/
- rateKbps = pRateTable->info[idx].rateKbps;
- } else {
- if (pRateTable->info[idx].valid != FALSE)
- rateKbps = pRateTable->info[idx].rateKbps;
- }
- }
- }
-
- *rxrate = rateKbps;
-}