| /* |
| * Copyright (c) 2012-2013 The Linux Foundation. All rights reserved. |
| * |
| * Previously licensed under the ISC license by Qualcomm Atheros, Inc. |
| * |
| * |
| * Permission to use, copy, modify, and/or distribute this software for |
| * any purpose with or without fee is hereby granted, provided that the |
| * above copyright notice and this permission notice appear in all |
| * copies. |
| * |
| * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL |
| * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED |
| * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE |
| * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL |
| * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR |
| * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER |
| * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR |
| * PERFORMANCE OF THIS SOFTWARE. |
| */ |
| |
| /* |
| * This file was originally distributed by Qualcomm Atheros, Inc. |
| * under proprietary terms before Copyright ownership was assigned |
| * to the Linux Foundation. |
| */ |
| |
| /* |
| * This file contains TSPEC and STA admit control related functions |
| * NOTE: applies only to AP builds |
| * |
| * Author: Sandesh Goel |
| * Date: 02/25/02 |
| * History:- |
| * Date Modified by Modification Information |
| * -------------------------------------------------------------------- |
| * |
| */ |
| #include "limDebug.h" |
| #include "sysDef.h" |
| #include "limApi.h" |
| #include "cfgApi.h" // wlan_cfgGetInt() |
| #include "limTrace.h" |
| #include "limSendSmeRspMessages.h" |
| #include "limTypes.h" |
| |
| |
| #define ADMIT_CONTROL_LOGLEVEL LOG1 |
| #define ADMIT_CONTROL_POLICY_LOGLEVEL LOG1 |
| #define ADMIT_CONTROL_MIN_INTERVAL 1000 // min acceptable service interval 1mSec |
| |
| /* total available bandwidth in bps in each phy mode |
| * these should be defined in hal or dph - replace these later |
| */ |
| #define LIM_TOTAL_BW_11A 54000000 |
| #define LIM_MIN_BW_11A 6000000 |
| #define LIM_TOTAL_BW_11B 11000000 |
| #define LIM_MIN_BW_11B 1000000 |
| #define LIM_TOTAL_BW_11G LIM_TOTAL_BW_11A |
| #define LIM_MIN_BW_11G LIM_MIN_BW_11B |
| |
| // conversion factors |
| #define LIM_CONVERT_SIZE_BITS(numBytes) ((numBytes) * 8) |
| #define LIM_CONVERT_RATE_MBPS(rate) ((rate)/1000000) |
| |
| /* ANI sta's support enhanced rates, so the effective medium time used is |
| * half that of other stations. This is the same as if they were requesting |
| * half the badnwidth - so we adjust ANI sta's accordingly for bandwidth |
| * calculations. Also enhanced rates apply only in case of non 11B mode. |
| */ |
| #define LIM_STA_BW_ADJUST(aniPeer, phyMode, bw) \ |
| (((aniPeer) && ((phyMode) != WNI_CFG_PHY_MODE_11B)) \ |
| ? ((bw)/2) : (bw)) |
| |
| |
| //------------------------------------------------------------------------------ |
| // local protos |
| |
| static tSirRetStatus |
| limCalculateSvcInt(tpAniSirGlobal, tSirMacTspecIE *, tANI_U32 *); |
| #if 0 //only EDCA is supported now |
| static tSirRetStatus |
| limValidateTspecHcca(tpAniSirGlobal, tSirMacTspecIE *); |
| #endif |
| static tSirRetStatus |
| limValidateTspecEdca(tpAniSirGlobal, tSirMacTspecIE *, tpPESession); |
| static tSirRetStatus |
| limValidateTspec(tpAniSirGlobal, tSirMacTspecIE *, tpPESession); |
| static void |
| limComputeMeanBwUsed(tpAniSirGlobal, tANI_U32 *, tANI_U32, tpLimTspecInfo, tpPESession); |
| static void |
| limGetAvailableBw(tpAniSirGlobal, tANI_U32 *, tANI_U32 *, tANI_U32, tANI_U32); |
| static tSirRetStatus |
| limAdmitPolicyOversubscription(tpAniSirGlobal, tSirMacTspecIE *, tpLimAdmitPolicyInfo, tpLimTspecInfo, tpPESession); |
| static tSirRetStatus |
| limTspecFindByStaAddr(tpAniSirGlobal, tANI_U8 *, tSirMacTspecIE*, tpLimTspecInfo, tpLimTspecInfo *); |
| static tSirRetStatus |
| limValidateAccessPolicy(tpAniSirGlobal, tANI_U8, tANI_U16, tpPESession); |
| |
| |
| /** ------------------------------------------------------------- |
| \fn limCalculateSvcInt |
| \brief TSPEC validation and servcie interval determination |
| \param tpAniSirGlobal pMac |
| \param tSirMacTspecIE *pTspec |
| \param tANI_U32 *pSvcInt |
| \return eSirRetStatus - status of the comparison |
| -------------------------------------------------------------*/ |
| |
| static tSirRetStatus |
| limCalculateSvcInt( |
| tpAniSirGlobal pMac, |
| tSirMacTspecIE *pTspec, |
| tANI_U32 *pSvcInt) |
| { |
| tANI_U32 msduSz, dataRate; |
| *pSvcInt = 0; |
| |
| // if a service interval is already specified, we are done |
| if ((pTspec->minSvcInterval != 0) || (pTspec->maxSvcInterval != 0)) |
| { |
| *pSvcInt = (pTspec->maxSvcInterval != 0) |
| ? pTspec->maxSvcInterval : pTspec->minSvcInterval; |
| return eSIR_SUCCESS; |
| } |
| |
| /* Masking off the fixed bits according to definition of MSDU size |
| * in IEEE 802.11-2007 spec (section 7.3.2.30). Nominal MSDU size |
| * is defined as: Bit[0:14]=Size, Bit[15]=Fixed |
| */ |
| if (pTspec->nomMsduSz != 0) |
| msduSz = (pTspec->nomMsduSz & 0x7fff); |
| else if (pTspec->maxMsduSz != 0) |
| msduSz = pTspec->maxMsduSz; |
| else |
| { |
| PELOGE(limLog(pMac, LOGE, FL("MsduSize not specified"));) |
| return eSIR_FAILURE; |
| } |
| |
| /* need to calculate a reasonable service interval |
| * this is simply the msduSz/meanDataRate |
| */ |
| if (pTspec->meanDataRate != 0) dataRate = pTspec->meanDataRate; |
| else if (pTspec->peakDataRate != 0) dataRate = pTspec->peakDataRate; |
| else if (pTspec->minDataRate != 0) dataRate = pTspec->minDataRate; |
| else |
| { |
| PELOGE(limLog(pMac, LOGE, FL("DataRate not specified"));) |
| return eSIR_FAILURE; |
| } |
| |
| *pSvcInt = LIM_CONVERT_SIZE_BITS(msduSz) / LIM_CONVERT_RATE_MBPS(dataRate); |
| return eSIR_FAILURE; |
| } |
| |
| #if 0 //only EDCA is supported now |
| /** ------------------------------------------------------------- |
| \fn limValidateTspecHcca |
| \brief validate the parameters in the hcca tspec |
| mandatory fields are derived from 11e Annex I (Table I.1) |
| \param tpAniSirGlobal pMac |
| \param tSirMacTspecIE *pTspec |
| \return eSirRetStatus - status |
| -------------------------------------------------------------*/ |
| static tSirRetStatus |
| limValidateTspecHcca( |
| tpAniSirGlobal pMac, |
| tSirMacTspecIE *pTspec) |
| { |
| tANI_U32 maxPhyRate, minPhyRate; |
| tANI_U32 phyMode; |
| |
| tSirRetStatus retval = eSIR_SUCCESS; |
| /* make sure a TSID is being requested */ |
| if (pTspec->tsinfo.traffic.tsid < SIR_MAC_HCCA_TSID_MIN) |
| { |
| limLog(pMac, LOGW, FL("tsid %d must be >%d)"), |
| pTspec->tsinfo.traffic.tsid, SIR_MAC_HCCA_TSID_MIN); |
| retval = eSIR_FAILURE; |
| } |
| /* |
| * With Polaris, there is a limitation in that the tsid cannot be arbitary |
| * but is based on the qid. Thus, we cannot have a tspec which requests |
| * a tsid of 13 and userPrio of 7, the bottom three bits of the tsid must |
| * correspond to the userPrio |
| */ |
| if (pTspec->tsinfo.traffic.userPrio != |
| (pTspec->tsinfo.traffic.tsid - SIR_MAC_HCCA_TSID_MIN)) |
| { |
| limLog(pMac, LOGE, FL("TSid=0x%x, userPrio=%d: is not allowed"), |
| pTspec->tsinfo.traffic.tsid, pTspec->tsinfo.traffic.userPrio); |
| retval = eSIR_FAILURE; |
| } |
| // an inactivity interval is mandatory |
| if (pTspec->inactInterval == 0) |
| { |
| PELOGW(limLog(pMac, LOGW, FL("inactInterval unspecified!"));) |
| retval = eSIR_FAILURE; |
| } |
| // surplus BW must be specified if a delay Bound is specified |
| if ((pTspec->delayBound != 0) && (pTspec->surplusBw == 0)) |
| { |
| limLog(pMac, LOGW, FL("delayBound %d, but surplusBw unspecified!"), |
| pTspec->delayBound); |
| retval = eSIR_FAILURE; |
| } |
| // minPhyRate must always be specified and cannot exceed maximum supported |
| limGetPhyMode(pMac, &phyMode); |
| //limGetAvailableBw(pMac, &maxPhyRate, &minPhyRate, pMac->dph.gDphPhyMode, |
| // 1 /* bandwidth mult factor */); |
| limGetAvailableBw(pMac, &maxPhyRate, &minPhyRate, phyMode, |
| 1 /* bandwidth mult factor */); |
| if ((pTspec->minPhyRate == 0) |
| || (pTspec->minPhyRate > maxPhyRate) |
| || (pTspec->minPhyRate < minPhyRate)) |
| { |
| limLog(pMac, LOGW, FL("minPhyRate (%d) invalid"), |
| pTspec->minPhyRate); |
| retval = eSIR_FAILURE; |
| } |
| /* NOTE: we will require all Tspec's to specify a mean data rate (and so |
| * also the min and peak data rates) |
| */ |
| if ((pTspec->minDataRate == 0) || |
| (pTspec->meanDataRate == 0) || |
| (pTspec->peakDataRate == 0)) |
| { |
| limLog(pMac, LOGW, FL("DataRate must be specified (min %d, mean %d, peak %d)"), |
| pTspec->minDataRate, pTspec->meanDataRate, pTspec->peakDataRate); |
| retval = eSIR_FAILURE; |
| } |
| |
| // mean data rate can't be more than the min phy rate |
| if (pTspec->meanDataRate > pTspec->minPhyRate) |
| { |
| limLog(pMac, LOGW, FL("Data rate (%d) is more than Phyrate %d"), |
| pTspec->meanDataRate, pTspec->minPhyRate); |
| return eSIR_FAILURE; |
| } |
| |
| /* if the tspec specifies a service interval, we won't accept tspec's |
| * with service interval less than our allowed minimum, also either both |
| * min and max must be specified or neither should be specified (in which |
| * case, HC determines the appropriate service interval |
| */ |
| if ((pTspec->minSvcInterval != 0) || (pTspec->maxSvcInterval != 0)) |
| { |
| // max < min is ridiculous |
| if (pTspec->maxSvcInterval < pTspec->minSvcInterval) |
| { |
| limLog(pMac, LOGW, FL("maxSvcInt %d > minSvcInterval %d!!"), |
| pTspec->maxSvcInterval, pTspec->minSvcInterval); |
| retval = eSIR_FAILURE; |
| } |
| if (pTspec->maxSvcInterval < ADMIT_CONTROL_MIN_INTERVAL) |
| { |
| limLog(pMac, LOGW, FL("maxSvcInt %d must be >%d"), |
| pTspec->maxSvcInterval, ADMIT_CONTROL_MIN_INTERVAL); |
| retval = eSIR_FAILURE; |
| } |
| } |
| else // min and max both unspecified |
| { |
| /* no service interval is specified, so make sure the parameters |
| * needed to determine one are specified in the tspec |
| * minPhyRate, meanDataRate and nomMsduSz are needed, only nomMsduSz |
| * must be checked here since the other two are already validated |
| */ |
| if (pTspec->nomMsduSz == 0) |
| { |
| PELOGW(limLog(pMac, LOGW, FL("No svcInt and no MsduSize specified"));) |
| retval = eSIR_FAILURE; |
| } |
| } |
| |
| limLog(pMac, ADMIT_CONTROL_LOGLEVEL, FL("return status %d"), retval); |
| return retval; |
| } |
| |
| #endif //only edca is supported now. |
| |
| /** ------------------------------------------------------------- |
| \fn limValidateTspecEdca |
| \brief validate the parameters in the edca tspec |
| mandatory fields are derived from 11e Annex I (Table I.1) |
| \param tpAniSirGlobal pMac |
| \param tSirMacTspecIE *pTspec |
| \return eSirRetStatus - status |
| -------------------------------------------------------------*/ |
| static tSirRetStatus |
| limValidateTspecEdca( |
| tpAniSirGlobal pMac, |
| tSirMacTspecIE *pTspec, |
| tpPESession psessionEntry) |
| { |
| tANI_U32 maxPhyRate, minPhyRate; |
| tANI_U32 phyMode; |
| tSirRetStatus retval = eSIR_SUCCESS; |
| |
| limGetPhyMode(pMac, &phyMode, psessionEntry); |
| |
| //limGetAvailableBw(pMac, &maxPhyRate, &minPhyRate, pMac->dph.gDphPhyMode, |
| // 1 /* bandwidth mult factor */); |
| limGetAvailableBw(pMac, &maxPhyRate, &minPhyRate, phyMode, |
| 1 /* bandwidth mult factor */); |
| // mandatory fields are derived from 11e Annex I (Table I.1) |
| if ((pTspec->nomMsduSz == 0) || |
| (pTspec->meanDataRate == 0) || |
| (pTspec->surplusBw == 0) || |
| (pTspec->minPhyRate == 0) || |
| (pTspec->minPhyRate > maxPhyRate)) |
| { |
| limLog(pMac, LOGW, FL("Invalid EDCA Tspec: NomMsdu %d, meanDataRate %d, surplusBw %d, minPhyRate %d"), |
| pTspec->nomMsduSz, pTspec->meanDataRate, pTspec->surplusBw, pTspec->minPhyRate); |
| retval = eSIR_FAILURE; |
| } |
| |
| limLog(pMac, ADMIT_CONTROL_LOGLEVEL, FL("return status %d"), retval); |
| return retval; |
| } |
| |
| /** ------------------------------------------------------------- |
| \fn limValidateTspec |
| \brief validate the offered tspec |
| \param tpAniSirGlobal pMac |
| \param tSirMacTspecIE *pTspec |
| \return eSirRetStatus - status |
| -------------------------------------------------------------*/ |
| |
| static tSirRetStatus |
| limValidateTspec( |
| tpAniSirGlobal pMac, |
| tSirMacTspecIE *pTspec, |
| tpPESession psessionEntry) |
| { |
| tSirRetStatus retval = eSIR_SUCCESS; |
| switch (pTspec->tsinfo.traffic.accessPolicy) |
| { |
| case SIR_MAC_ACCESSPOLICY_EDCA: |
| if ((retval = limValidateTspecEdca(pMac, pTspec, psessionEntry)) != eSIR_SUCCESS) |
| PELOGW(limLog(pMac, LOGW, FL("EDCA tspec invalid"));) |
| break; |
| |
| case SIR_MAC_ACCESSPOLICY_HCCA: |
| #if 0 //Not supported right now. |
| if ((retval = limValidateTspecHcca(pMac, pTspec)) != eSIR_SUCCESS) |
| PELOGW(limLog(pMac, LOGW, FL("HCCA tspec invalid"));) |
| break; |
| #endif |
| case SIR_MAC_ACCESSPOLICY_BOTH: |
| // TBD: should we support hybrid tspec as well?? for now, just fall through |
| default: |
| limLog(pMac, LOGW, FL("AccessType %d not supported"), |
| pTspec->tsinfo.traffic.accessPolicy); |
| retval = eSIR_FAILURE; |
| break; |
| } |
| return retval; |
| } |
| |
| //----------------------------------------------------------------------------- |
| // Admit Control Policy |
| |
| |
| /** ------------------------------------------------------------- |
| \fn limComputeMeanBwUsed |
| \brief determime the used/allocated bandwidth |
| \param tpAniSirGlobal pMac |
| \param tANI_U32 *pBw |
| \param tANI_U32 phyMode |
| \param tpLimTspecInfo pTspecInfo |
| \return eSirRetStatus - status |
| -------------------------------------------------------------*/ |
| |
| static void |
| limComputeMeanBwUsed( |
| tpAniSirGlobal pMac, |
| tANI_U32 *pBw, |
| tANI_U32 phyMode, |
| tpLimTspecInfo pTspecInfo, |
| tpPESession psessionEntry) |
| { |
| tANI_U32 ctspec; |
| *pBw = 0; |
| for (ctspec = 0; ctspec < LIM_NUM_TSPEC_MAX; ctspec++, pTspecInfo++) |
| { |
| if (pTspecInfo->inuse) |
| { |
| tpDphHashNode pSta = dphGetHashEntry(pMac, pTspecInfo->assocId, &psessionEntry->dph.dphHashTable); |
| if (pSta == NULL) |
| { |
| // maybe we should delete the tspec?? |
| limLog(pMac, LOGE, FL("Tspec %d (assocId %d): dphNode not found"), |
| ctspec, pTspecInfo->assocId); |
| continue; |
| } |
| //FIXME: need to take care of taurusPeer, titanPeer, 11npeer too. |
| *pBw += LIM_STA_BW_ADJUST(pSta->aniPeer, phyMode, pTspecInfo->tspec.meanDataRate); |
| } |
| } |
| } |
| |
| /** ------------------------------------------------------------- |
| \fn limGetAvailableBw |
| \brief based on the phy mode and the bw_factor, determine the total bandwidth that |
| can be supported |
| \param tpAniSirGlobal pMac |
| \param tANI_U32 *pMaxBw |
| \param tANI_U32 *pMinBw |
| \param tANI_U32 phyMode |
| \param tANI_U32 bw_factor |
| \return eSirRetStatus - status |
| -------------------------------------------------------------*/ |
| |
| static void |
| limGetAvailableBw( |
| tpAniSirGlobal pMac, |
| tANI_U32 *pMaxBw, |
| tANI_U32 *pMinBw, |
| tANI_U32 phyMode, |
| tANI_U32 bw_factor) |
| { |
| switch (phyMode) |
| { |
| case WNI_CFG_PHY_MODE_11B: |
| *pMaxBw = LIM_TOTAL_BW_11B; |
| *pMinBw = LIM_MIN_BW_11B; |
| break; |
| |
| case WNI_CFG_PHY_MODE_11A: |
| *pMaxBw = LIM_TOTAL_BW_11A; |
| *pMinBw = LIM_MIN_BW_11A; |
| break; |
| |
| case WNI_CFG_PHY_MODE_11G: |
| case WNI_CFG_PHY_MODE_NONE: |
| default: |
| *pMaxBw = LIM_TOTAL_BW_11G; |
| *pMinBw = LIM_MIN_BW_11G; |
| break; |
| } |
| *pMaxBw *= bw_factor; |
| } |
| |
| /** ------------------------------------------------------------- |
| \fn limAdmitPolicyOversubscription |
| \brief simple admission control policy based on oversubscription |
| if the total bandwidth of all admitted tspec's exceeds (factor * phy-bw) then |
| reject the tspec, else admit it. The phy-bw is the peak available bw in the |
| current phy mode. The 'factor' is the configured oversubscription factor. |
| \param tpAniSirGlobal pMac |
| \param tSirMacTspecIE *pTspec |
| \param tpLimAdmitPolicyInfo pAdmitPolicy |
| \param tpLimTspecInfo pTspecInfo |
| \return eSirRetStatus - status |
| -------------------------------------------------------------*/ |
| |
| /* |
| * simple admission control policy based on oversubscription |
| * if the total bandwidth of all admitted tspec's exceeds (factor * phy-bw) then |
| * reject the tspec, else admit it. The phy-bw is the peak available bw in the |
| * current phy mode. The 'factor' is the configured oversubscription factor. |
| */ |
| static tSirRetStatus |
| limAdmitPolicyOversubscription( |
| tpAniSirGlobal pMac, |
| tSirMacTspecIE *pTspec, |
| tpLimAdmitPolicyInfo pAdmitPolicy, |
| tpLimTspecInfo pTspecInfo, |
| tpPESession psessionEntry) |
| { |
| tANI_U32 totalbw, minbw, usedbw; |
| tANI_U32 phyMode; |
| |
| // determine total bandwidth used so far |
| limGetPhyMode(pMac, &phyMode, psessionEntry); |
| |
| //limComputeMeanBwUsed(pMac, &usedbw, pMac->dph.gDphPhyMode, pTspecInfo); |
| limComputeMeanBwUsed(pMac, &usedbw, phyMode, pTspecInfo, psessionEntry); |
| |
| // determine how much bandwidth is available based on the current phy mode |
| //limGetAvailableBw(pMac, &totalbw, &minbw, pMac->dph.gDphPhyMode, pAdmitPolicy->bw_factor); |
| limGetAvailableBw(pMac, &totalbw, &minbw, phyMode, pAdmitPolicy->bw_factor); |
| |
| if (usedbw > totalbw) // this can't possibly happen |
| return eSIR_FAILURE; |
| |
| if ((totalbw - usedbw) < pTspec->meanDataRate) |
| { |
| limLog(pMac, ADMIT_CONTROL_POLICY_LOGLEVEL, |
| FL("Total BW %d, Used %d, Tspec request %d not possible"), |
| totalbw, usedbw, pTspec->meanDataRate); |
| return eSIR_FAILURE; |
| } |
| return eSIR_SUCCESS; |
| } |
| |
| /** ------------------------------------------------------------- |
| \fn limAdmitPolicy |
| \brief determine the current admit control policy and apply it for the offered tspec |
| \param tpAniSirGlobal pMac |
| \param tSirMacTspecIE *pTspec |
| \return eSirRetStatus - status |
| -------------------------------------------------------------*/ |
| |
| tSirRetStatus limAdmitPolicy( |
| tpAniSirGlobal pMac, |
| tSirMacTspecIE *pTspec, |
| tpPESession psessionEntry) |
| { |
| tSirRetStatus retval = eSIR_FAILURE; |
| tpLimAdmitPolicyInfo pAdmitPolicy = &pMac->lim.admitPolicyInfo; |
| |
| switch (pAdmitPolicy->type) |
| { |
| case WNI_CFG_ADMIT_POLICY_ADMIT_ALL: |
| retval = eSIR_SUCCESS; |
| break; |
| |
| case WNI_CFG_ADMIT_POLICY_BW_FACTOR: |
| retval = limAdmitPolicyOversubscription(pMac, pTspec, |
| &pMac->lim.admitPolicyInfo, &pMac->lim.tspecInfo[0], psessionEntry); |
| if (retval != eSIR_SUCCESS) |
| PELOGE(limLog(pMac, LOGE, FL("rejected by BWFactor policy"));) |
| break; |
| |
| case WNI_CFG_ADMIT_POLICY_REJECT_ALL: |
| retval = eSIR_FAILURE; |
| break; |
| |
| default: |
| retval = eSIR_SUCCESS; |
| limLog(pMac, LOGE, FL("Admit Policy %d unknown, admitting all traffic"), |
| pAdmitPolicy->type); |
| break; |
| } |
| return retval; |
| } |
| |
| /** ------------------------------------------------------------- |
| \fn limTspecDelete |
| \brief delete the specified tspec |
| \param tpAniSirGlobal pMac |
| \param tpLimTspecInfo pInfo |
| \return eSirRetStatus - status |
| -------------------------------------------------------------*/ |
| |
| //----------------------------------------------------------------------------- |
| // delete the specified tspec |
| void limTspecDelete(tpAniSirGlobal pMac, tpLimTspecInfo pInfo) |
| { |
| if (pInfo == NULL) |
| return; |
| //pierre |
| limLog(pMac, ADMIT_CONTROL_LOGLEVEL, FL("tspec entry = %d"), pInfo->idx); |
| limLog(pMac, ADMIT_CONTROL_LOGLEVEL, FL("delete tspec %p"), pInfo); |
| pInfo->inuse = 0; |
| |
| // clear the hcca/parameterized queue indicator |
| #if 0 |
| if ((pInfo->tspec.tsinfo.traffic.direction == SIR_MAC_DIRECTION_UPLINK) || |
| (pInfo->tspec.tsinfo.traffic.direction == SIR_MAC_DIRECTION_BIDIR)) |
| queue[pInfo->staid][pInfo->tspec.tsinfo.traffic.userPrio][SCH_UL_QUEUE].ts = 0; |
| #endif |
| |
| return; |
| } |
| |
| /** ------------------------------------------------------------- |
| \fn limTspecFindByStaAddr |
| \brief Send halMsg_AddTs to HAL |
| \param tpAniSirGlobal pMac |
| \param \param tANI_U8 *pAddr |
| \param tSirMacTspecIE *pTspecIE |
| \param tpLimTspecInfo pTspecList |
| \param tpLimTspecInfo *ppInfo |
| \return eSirRetStatus - status |
| -------------------------------------------------------------*/ |
| |
| // find the specified tspec in the list |
| static tSirRetStatus |
| limTspecFindByStaAddr( |
| tpAniSirGlobal pMac, |
| tANI_U8 *pAddr, |
| tSirMacTspecIE *pTspecIE, |
| tpLimTspecInfo pTspecList, |
| tpLimTspecInfo *ppInfo) |
| { |
| int ctspec; |
| |
| *ppInfo = NULL; |
| |
| for (ctspec = 0; ctspec < LIM_NUM_TSPEC_MAX; ctspec++, pTspecList++) |
| { |
| if ((pTspecList->inuse) |
| && (vos_mem_compare(pAddr, pTspecList->staAddr, sizeof(pTspecList->staAddr))) |
| && (vos_mem_compare((tANI_U8 *) pTspecIE, (tANI_U8 *) &pTspecList->tspec, |
| sizeof(tSirMacTspecIE)))) |
| { |
| *ppInfo = pTspecList; |
| return eSIR_SUCCESS; |
| } |
| } |
| return eSIR_FAILURE; |
| } |
| |
| /** ------------------------------------------------------------- |
| \fn limTspecFindByAssocId |
| \brief find tspec with matchin staid and Tspec |
| \param tpAniSirGlobal pMac |
| \param tANI_U32 staid |
| \param tSirMacTspecIE *pTspecIE |
| \param tpLimTspecInfo pTspecList |
| \param tpLimTspecInfo *ppInfo |
| \return eSirRetStatus - status |
| -------------------------------------------------------------*/ |
| |
| tSirRetStatus |
| limTspecFindByAssocId( |
| tpAniSirGlobal pMac, |
| tANI_U16 assocId, |
| tSirMacTspecIE *pTspecIE, |
| tpLimTspecInfo pTspecList, |
| tpLimTspecInfo *ppInfo) |
| { |
| int ctspec; |
| |
| *ppInfo = NULL; |
| |
| limLog(pMac, ADMIT_CONTROL_LOGLEVEL, FL("Trying to find tspec entry for assocId = %d"), assocId); |
| limLog(pMac, ADMIT_CONTROL_LOGLEVEL, FL("pTsInfo->traffic.direction = %d, pTsInfo->traffic.tsid = %d"), |
| pTspecIE->tsinfo.traffic.direction, pTspecIE->tsinfo.traffic.tsid); |
| |
| for (ctspec = 0; ctspec < LIM_NUM_TSPEC_MAX; ctspec++, pTspecList++) |
| { |
| if ((pTspecList->inuse) |
| && (assocId == pTspecList->assocId) |
| && (vos_mem_compare((tANI_U8 *)pTspecIE, (tANI_U8 *)&pTspecList->tspec, |
| sizeof(tSirMacTspecIE)))) |
| { |
| *ppInfo = pTspecList; |
| return eSIR_SUCCESS; |
| } |
| } |
| return eSIR_FAILURE; |
| } |
| |
| /** ------------------------------------------------------------- |
| \fn limFindTspec |
| \brief finding a TSPEC entry with assocId, tsinfo.direction and tsinfo.tsid |
| \param tANI_U16 assocId |
| \param tpAniSirGlobal pMac |
| \param tSirMacTSInfo *pTsInfo |
| \param tpLimTspecInfo pTspecList |
| \param tpLimTspecInfo *ppInfo |
| \return eSirRetStatus - status of the comparison |
| -------------------------------------------------------------*/ |
| |
| tSirRetStatus |
| limFindTspec( |
| tpAniSirGlobal pMac, |
| tANI_U16 assocId, |
| tSirMacTSInfo *pTsInfo, |
| tpLimTspecInfo pTspecList, |
| tpLimTspecInfo *ppInfo) |
| { |
| int ctspec; |
| |
| *ppInfo = NULL; |
| |
| limLog(pMac, ADMIT_CONTROL_LOGLEVEL, FL("Trying to find tspec entry for assocId = %d"), assocId); |
| limLog(pMac, ADMIT_CONTROL_LOGLEVEL, FL("pTsInfo->traffic.direction = %d, pTsInfo->traffic.tsid = %d"), |
| pTsInfo->traffic.direction, pTsInfo->traffic.tsid); |
| |
| for (ctspec = 0; ctspec < LIM_NUM_TSPEC_MAX; ctspec++, pTspecList++) |
| { |
| if ((pTspecList->inuse) |
| && (assocId == pTspecList->assocId) |
| && (pTsInfo->traffic.direction == pTspecList->tspec.tsinfo.traffic.direction) |
| && (pTsInfo->traffic.tsid == pTspecList->tspec.tsinfo.traffic.tsid)) |
| { |
| *ppInfo = pTspecList; |
| return eSIR_SUCCESS; |
| } |
| } |
| return eSIR_FAILURE; |
| } |
| |
| /** ------------------------------------------------------------- |
| \fn limTspecAdd |
| \brief add or update the specified tspec to the tspec list |
| \param tpAniSirGlobal pMac |
| \param tANI_U8 *pAddr |
| \param tANI_U16 assocId |
| \param tSirMacTspecIE *pTspec |
| \param tANI_U32 interval |
| \param tpLimTspecInfo *ppInfo |
| |
| \return eSirRetStatus - status of the comparison |
| -------------------------------------------------------------*/ |
| |
| tSirRetStatus limTspecAdd( |
| tpAniSirGlobal pMac, |
| tANI_U8 *pAddr, |
| tANI_U16 assocId, |
| tSirMacTspecIE *pTspec, |
| tANI_U32 interval, |
| tpLimTspecInfo *ppInfo) |
| { |
| tpLimTspecInfo pTspecList = &pMac->lim.tspecInfo[0]; |
| *ppInfo = NULL; |
| |
| // validate the assocId |
| if (assocId >= pMac->lim.maxStation) |
| { |
| PELOGE(limLog(pMac, LOGE, FL("Invalid assocId 0x%x"), assocId);) |
| return eSIR_FAILURE; |
| } |
| |
| //decide whether to add/update |
| { |
| *ppInfo = NULL; |
| |
| if(eSIR_SUCCESS == limFindTspec(pMac, assocId, &pTspec->tsinfo, pTspecList, ppInfo)) |
| { |
| //update this entry. |
| limLog(pMac, ADMIT_CONTROL_LOGLEVEL, FL("updating TSPEC table entry = %d"), |
| (*ppInfo)->idx); |
| } |
| else |
| { |
| /* We didn't find one to update. So find a free slot in the |
| * LIM TSPEC list and add this new entry |
| */ |
| tANI_U8 ctspec = 0; |
| for (ctspec = 0 , pTspecList = &pMac->lim.tspecInfo[0]; ctspec < LIM_NUM_TSPEC_MAX; ctspec++, pTspecList++) |
| { |
| if (! pTspecList->inuse) |
| { |
| limLog(pMac, LOG1, FL("Found free slot in TSPEC list. Add to TSPEC table entry %d"), ctspec); |
| break; |
| } |
| } |
| |
| if (ctspec >= LIM_NUM_TSPEC_MAX) |
| return eSIR_FAILURE; |
| |
| //Record the new index entry |
| pTspecList->idx = ctspec; |
| } |
| } |
| |
| // update the tspec info |
| pTspecList->tspec = *pTspec; |
| pTspecList->assocId = assocId; |
| vos_mem_copy(pTspecList->staAddr, pAddr, sizeof(pTspecList->staAddr)); |
| |
| // for edca tspec's, we are all done |
| if (pTspec->tsinfo.traffic.accessPolicy == SIR_MAC_ACCESSPOLICY_EDCA) |
| { |
| pTspecList->inuse = 1; |
| *ppInfo = pTspecList; |
| limLog(pMac, ADMIT_CONTROL_LOGLEVEL, FL("added entry for EDCA AccessPolicy")); |
| return eSIR_SUCCESS; |
| } |
| |
| /* |
| * for hcca tspec's, must set the parameterized bit in the queues |
| * the 'ts' bit in the queue data structure indicates that the queue is |
| * parameterized (hcca). When the schedule is written this bit is used |
| * in the tsid field (bit 3) and the other three bits (0-2) are simply |
| * filled in as the user priority (or qid). This applies only to uplink |
| * polls where the qos control field must contain the tsid specified in the |
| * tspec. |
| */ |
| #if 0 |
| if ((pTspec->tsinfo.traffic.direction == SIR_MAC_DIRECTION_UPLINK) || |
| (pTspec->tsinfo.traffic.direction == SIR_MAC_DIRECTION_BIDIR)) |
| queue[staid][pTspec->tsinfo.traffic.userPrio][SCH_UL_QUEUE].ts = 1; |
| #endif |
| pTspecList->inuse = 1; |
| *ppInfo = pTspecList; |
| limLog(pMac, ADMIT_CONTROL_LOGLEVEL, FL("added entry for HCCA AccessPolicy")); |
| return eSIR_SUCCESS; |
| } |
| |
| /** ------------------------------------------------------------- |
| \fn limValidateAccessPolicy |
| \brief Validates Access policy |
| \param tpAniSirGlobal pMac |
| \param tANI_U8 accessPolicy |
| \param tANI_U16 assocId |
| \return eSirRetStatus - status |
| -------------------------------------------------------------*/ |
| |
| static tSirRetStatus |
| limValidateAccessPolicy( |
| tpAniSirGlobal pMac, |
| tANI_U8 accessPolicy, |
| tANI_U16 assocId, |
| tpPESession psessionEntry) |
| { |
| tSirRetStatus retval = eSIR_FAILURE; |
| tpDphHashNode pSta = dphGetHashEntry(pMac, assocId, &psessionEntry->dph.dphHashTable); |
| |
| if ((pSta == NULL) || (! pSta->valid)) |
| { |
| PELOGE(limLog(pMac, LOGE, FL("invalid station address passed"));) |
| return eSIR_FAILURE; |
| } |
| |
| switch (accessPolicy) |
| { |
| case SIR_MAC_ACCESSPOLICY_EDCA: |
| if (pSta->wmeEnabled || pSta->lleEnabled) |
| retval = eSIR_SUCCESS; |
| break; |
| |
| case SIR_MAC_ACCESSPOLICY_HCCA: |
| case SIR_MAC_ACCESSPOLICY_BOTH: |
| #if 0 //only EDCA supported for now. |
| // TBD: check wsm doesn't support the hybrid access policy |
| if (pSta->wsmEnabled || pSta->lleEnabled) |
| retval = eSIR_SUCCESS; |
| break; |
| #endif //only EDCA supported for now. |
| default: |
| PELOGE(limLog(pMac, LOGE, FL("Invalid accessPolicy %d"), accessPolicy);) |
| break; |
| } |
| |
| if (retval != eSIR_SUCCESS) |
| limLog(pMac, LOGW, FL("failed (accPol %d, staId %d, lle %d, wme %d, wsm %d)"), |
| accessPolicy, pSta->staIndex, pSta->lleEnabled, pSta->wmeEnabled, pSta->wsmEnabled); |
| |
| return retval; |
| } |
| |
| /** ------------------------------------------------------------- |
| \fn limAdmitControlAddTS |
| \brief Determine if STA with the specified TSPEC can be admitted. If it can, |
| a schedule element is provided |
| \param tpAniSirGlobal pMac |
| \param tANI_U8 *pAddr, |
| \param tSirAddtsReqInfo *pAddts, |
| \param tSirMacQosCapabilityIE *pQos, |
| \param tANI_U16 assocId, // assocId, valid only if alloc==true |
| \param tANI_U8 alloc, // true=>allocate bw for this tspec, |
| // else determine only if space is available |
| \param tSirMacScheduleIE *pSch, |
| \param tANI_U8 *pTspecIdx //index to the lim tspec table. |
| \return eSirRetStatus - status |
| -------------------------------------------------------------*/ |
| |
| tSirRetStatus limAdmitControlAddTS( |
| tpAniSirGlobal pMac, |
| tANI_U8 *pAddr, |
| tSirAddtsReqInfo *pAddts, |
| tSirMacQosCapabilityStaIE *pQos, |
| tANI_U16 assocId, // assocId, valid only if alloc==true |
| tANI_U8 alloc, // true=>allocate bw for this tspec, |
| // else determine only if space is available |
| tSirMacScheduleIE *pSch, |
| tANI_U8 *pTspecIdx, //index to the lim tspec table. |
| tpPESession psessionEntry |
| ) |
| { |
| tpLimTspecInfo pTspecInfo; |
| tSirRetStatus retval; |
| tANI_U32 svcInterval; |
| (void) pQos; |
| |
| // TBD: modify tspec as needed |
| // EDCA: need to fill in the medium time and the minimum phy rate |
| // to be consistent with the desired traffic parameters. |
| |
| limLog(pMac, ADMIT_CONTROL_LOGLEVEL, FL("tsid %d, directn %d, start %d, intvl %d, accPolicy %d, up %d"), |
| pAddts->tspec.tsinfo.traffic.tsid, pAddts->tspec.tsinfo.traffic.direction, |
| pAddts->tspec.svcStartTime, pAddts->tspec.minSvcInterval, |
| pAddts->tspec.tsinfo.traffic.accessPolicy, pAddts->tspec.tsinfo.traffic.userPrio); |
| |
| // check for duplicate tspec |
| retval = (alloc) |
| ? limTspecFindByAssocId(pMac, assocId, &pAddts->tspec, &pMac->lim.tspecInfo[0], &pTspecInfo) |
| : limTspecFindByStaAddr(pMac, pAddr, &pAddts->tspec, &pMac->lim.tspecInfo[0], &pTspecInfo); |
| |
| if (retval == eSIR_SUCCESS) |
| { |
| limLog(pMac, ADMIT_CONTROL_LOGLEVEL, FL("duplicate tspec (index %d)!"), pTspecInfo->idx); |
| return eSIR_FAILURE; |
| } |
| |
| // check that the tspec's are well formed and acceptable |
| if (limValidateTspec(pMac, &pAddts->tspec, psessionEntry) != eSIR_SUCCESS) |
| { |
| PELOGW(limLog(pMac, LOGW, FL("tspec validation failed"));) |
| return eSIR_FAILURE; |
| } |
| |
| // determine a service interval for the tspec |
| if (limCalculateSvcInt(pMac, &pAddts->tspec, &svcInterval) != eSIR_SUCCESS) |
| { |
| PELOGW(limLog(pMac, LOGW, FL("SvcInt calculate failed"));) |
| return eSIR_FAILURE; |
| } |
| |
| // determine if the tspec can be admitted or not based on current policy |
| if (limAdmitPolicy(pMac, &pAddts->tspec, psessionEntry) != eSIR_SUCCESS) |
| { |
| PELOGW(limLog(pMac, LOGW, FL("tspec rejected by admit control policy"));) |
| return eSIR_FAILURE; |
| } |
| |
| // fill in a schedule if requested |
| if (pSch != NULL) |
| { |
| vos_mem_set((tANI_U8 *) pSch, sizeof(*pSch), 0); |
| pSch->svcStartTime = pAddts->tspec.svcStartTime; |
| pSch->svcInterval = svcInterval; |
| pSch->maxSvcDuration = (tANI_U16) pSch->svcInterval; // use SP = SI |
| pSch->specInterval = 0x1000; // fixed for now: TBD |
| |
| pSch->info.direction = pAddts->tspec.tsinfo.traffic.direction; |
| pSch->info.tsid = pAddts->tspec.tsinfo.traffic.tsid; |
| pSch->info.aggregation = 0; // no support for aggregation for now: TBD |
| } |
| |
| // if no allocation is requested, done |
| if (! alloc) |
| return eSIR_SUCCESS; |
| |
| // check that we are in the proper mode to deal with the tspec type |
| if (limValidateAccessPolicy(pMac, (tANI_U8) pAddts->tspec.tsinfo.traffic.accessPolicy, assocId, psessionEntry) != eSIR_SUCCESS) |
| { |
| limLog(pMac, LOGW, FL("AccessPolicy %d is not valid in current mode"), |
| pAddts->tspec.tsinfo.traffic.accessPolicy); |
| return eSIR_FAILURE; |
| } |
| |
| // add tspec to list |
| if (limTspecAdd(pMac, pAddr, assocId, &pAddts->tspec, svcInterval, &pTspecInfo) |
| != eSIR_SUCCESS) |
| { |
| PELOGE(limLog(pMac, LOGE, FL("no space in tspec list"));) |
| return eSIR_FAILURE; |
| } |
| |
| //passing lim tspec table index to the caller |
| *pTspecIdx = pTspecInfo->idx; |
| |
| return eSIR_SUCCESS; |
| } |
| |
| /** ------------------------------------------------------------- |
| \fn limAdmitControlDeleteTS |
| \brief Delete the specified Tspec for the specified STA |
| \param tpAniSirGlobal pMac |
| \param tANI_U16 assocId |
| \param tSirMacTSInfo *pTsInfo |
| \param tANI_U8 *pTsStatus |
| \param tANI_U8 *ptspecIdx |
| \return eSirRetStatus - status |
| -------------------------------------------------------------*/ |
| |
| tSirRetStatus |
| limAdmitControlDeleteTS( |
| tpAniSirGlobal pMac, |
| tANI_U16 assocId, |
| tSirMacTSInfo *pTsInfo, |
| tANI_U8 *pTsStatus, |
| tANI_U8 *ptspecIdx) |
| { |
| tpLimTspecInfo pTspecInfo = NULL; |
| |
| if (pTsStatus != NULL) |
| *pTsStatus = 0; |
| |
| if (limFindTspec(pMac, assocId, pTsInfo, &pMac->lim.tspecInfo[0], &pTspecInfo) == eSIR_SUCCESS) |
| { |
| if(pTspecInfo != NULL) |
| { |
| limLog(pMac, ADMIT_CONTROL_LOGLEVEL, FL("Tspec entry %d found"), pTspecInfo->idx); |
| |
| *ptspecIdx = pTspecInfo->idx; |
| limTspecDelete(pMac, pTspecInfo); |
| return eSIR_SUCCESS; |
| } |
| } |
| return eSIR_FAILURE; |
| } |
| |
| /** ------------------------------------------------------------- |
| \fn limAdmitControlDeleteSta |
| \brief Delete all TSPEC for the specified STA |
| \param tpAniSirGlobal pMac |
| \param tANI_U16 assocId |
| \return eSirRetStatus - status |
| -------------------------------------------------------------*/ |
| |
| tSirRetStatus |
| limAdmitControlDeleteSta( |
| tpAniSirGlobal pMac, |
| tANI_U16 assocId) |
| { |
| tpLimTspecInfo pTspecInfo = &pMac->lim.tspecInfo[0]; |
| int ctspec; |
| |
| for (ctspec = 0; ctspec < LIM_NUM_TSPEC_MAX; ctspec++, pTspecInfo++) |
| { |
| if (assocId == pTspecInfo->assocId) |
| { |
| limTspecDelete(pMac, pTspecInfo); |
| limLog(pMac, ADMIT_CONTROL_LOGLEVEL, FL("Deleting TSPEC %d for assocId %d"), |
| ctspec, assocId); |
| } |
| } |
| limLog(pMac, ADMIT_CONTROL_LOGLEVEL, FL("assocId %d done"), assocId); |
| |
| return eSIR_SUCCESS; |
| } |
| |
| /** ------------------------------------------------------------- |
| \fn limAdmitControlInit |
| \brief init tspec table |
| \param tpAniSirGlobal pMac |
| \return eSirRetStatus - status |
| -------------------------------------------------------------*/ |
| tSirRetStatus limAdmitControlInit(tpAniSirGlobal pMac) |
| { |
| vos_mem_set(pMac->lim.tspecInfo, LIM_NUM_TSPEC_MAX * sizeof(tLimTspecInfo), 0); |
| return eSIR_SUCCESS; |
| } |
| |
| /** ------------------------------------------------------------- |
| \fn limUpdateAdmitPolicy |
| \brief Set the admit control policy based on CFG parameters |
| \param tpAniSirGlobal pMac |
| \return eSirRetStatus - status |
| -------------------------------------------------------------*/ |
| |
| tSirRetStatus limUpdateAdmitPolicy(tpAniSirGlobal pMac) |
| { |
| tANI_U32 val; |
| if (wlan_cfgGetInt(pMac, WNI_CFG_ADMIT_POLICY, &val) != eSIR_SUCCESS) |
| { |
| limLog(pMac, LOGP, FL("Unable to get CFG_ADMIT_POLICY")); |
| return eSIR_FAILURE; |
| } |
| pMac->lim.admitPolicyInfo.type = (tANI_U8) val; |
| if (wlan_cfgGetInt(pMac, WNI_CFG_ADMIT_BWFACTOR, &val) != eSIR_SUCCESS) |
| { |
| limLog(pMac, LOGP, FL("Unable to get CFG_ADMIT_BWFACTOR")); |
| return eSIR_FAILURE; |
| } |
| pMac->lim.admitPolicyInfo.bw_factor = (tANI_U8) val; |
| |
| PELOG1(limLog(pMac, LOG1, FL("LIM: AdmitPolicy %d, bw_factor %d"), |
| pMac->lim.admitPolicyInfo.type, pMac->lim.admitPolicyInfo.bw_factor);) |
| |
| return eSIR_SUCCESS; |
| } |
| |
| |
| /** ------------------------------------------------------------- |
| \fn limSendHalMsgAddTs |
| \brief Send halMsg_AddTs to HAL |
| \param tpAniSirGlobal pMac |
| \param tANI_U16 staIdx |
| \param tANI_U8 tspecIdx |
| \param tSirMacTspecIE tspecIE |
| \param tSirTclasInfo *tclasInfo |
| \param tANI_U8 tclasProc |
| \return eSirRetStatus - status |
| -------------------------------------------------------------*/ |
| |
| tSirRetStatus |
| limSendHalMsgAddTs( |
| tpAniSirGlobal pMac, |
| tANI_U16 staIdx, |
| tANI_U8 tspecIdx, |
| tSirMacTspecIE tspecIE, |
| tANI_U8 sessionId) |
| { |
| tSirMsgQ msg; |
| tpAddTsParams pAddTsParam; |
| |
| pAddTsParam = vos_mem_malloc(sizeof(tAddTsParams)); |
| if (NULL == pAddTsParam) |
| { |
| PELOGW(limLog(pMac, LOGW, FL("AllocateMemory() failed"));) |
| return eSIR_MEM_ALLOC_FAILED; |
| } |
| |
| vos_mem_set((tANI_U8 *)pAddTsParam, sizeof(tAddTsParams), 0); |
| pAddTsParam->staIdx = staIdx; |
| pAddTsParam->tspecIdx = tspecIdx; |
| vos_mem_copy(&pAddTsParam->tspec, &tspecIE, sizeof(tSirMacTspecIE)); |
| pAddTsParam->sessionId = sessionId; |
| |
| msg.type = WDA_ADD_TS_REQ; |
| msg.bodyptr = pAddTsParam; |
| msg.bodyval = 0; |
| |
| /* We need to defer any incoming messages until we get a |
| * WDA_ADD_TS_RSP from HAL. |
| */ |
| SET_LIM_PROCESS_DEFD_MESGS(pMac, false); |
| MTRACE(macTraceMsgTx(pMac, sessionId, msg.type)); |
| |
| if(eSIR_SUCCESS != wdaPostCtrlMsg(pMac, &msg)) |
| { |
| PELOGW(limLog(pMac, LOGW, FL("wdaPostCtrlMsg() failed"));) |
| SET_LIM_PROCESS_DEFD_MESGS(pMac, true); |
| vos_mem_free(pAddTsParam); |
| return eSIR_FAILURE; |
| } |
| return eSIR_SUCCESS; |
| } |
| |
| /** ------------------------------------------------------------- |
| \fn limSendHalMsgDelTs |
| \brief Send halMsg_AddTs to HAL |
| \param tpAniSirGlobal pMac |
| \param tANI_U16 staIdx |
| \param tANI_U8 tspecIdx |
| \param tSirAddtsReqInfo addts |
| \return eSirRetStatus - status |
| -------------------------------------------------------------*/ |
| |
| tSirRetStatus |
| limSendHalMsgDelTs( |
| tpAniSirGlobal pMac, |
| tANI_U16 staIdx, |
| tANI_U8 tspecIdx, |
| tSirDeltsReqInfo delts, |
| tANI_U8 sessionId, |
| tANI_U8 *bssId) |
| { |
| tSirMsgQ msg; |
| tpDelTsParams pDelTsParam; |
| |
| pDelTsParam = vos_mem_malloc(sizeof(tDelTsParams)); |
| if (NULL == pDelTsParam) |
| { |
| limLog(pMac, LOGP, FL("AllocateMemory() failed")); |
| return eSIR_MEM_ALLOC_FAILED; |
| } |
| |
| msg.type = WDA_DEL_TS_REQ; |
| msg.bodyptr = pDelTsParam; |
| msg.bodyval = 0; |
| vos_mem_set((tANI_U8 *)pDelTsParam, sizeof(tDelTsParams), 0); |
| |
| //filling message parameters. |
| pDelTsParam->staIdx = staIdx; |
| pDelTsParam->tspecIdx = tspecIdx; |
| vos_mem_copy(&pDelTsParam->bssId, bssId, sizeof(tSirMacAddr)); |
| |
| PELOGW(limLog(pMac, LOGW, FL("calling wdaPostCtrlMsg()"));) |
| MTRACE(macTraceMsgTx(pMac, sessionId, msg.type)); |
| |
| if(eSIR_SUCCESS != wdaPostCtrlMsg(pMac, &msg)) |
| { |
| PELOGW(limLog(pMac, LOGW, FL("wdaPostCtrlMsg() failed"));) |
| vos_mem_free(pDelTsParam); |
| return eSIR_FAILURE; |
| } |
| return eSIR_SUCCESS; |
| } |
| |
| /** ------------------------------------------------------------- |
| \fn limProcessHalAddTsRsp |
| \brief This function process the WDA_ADD_TS_RSP from HAL. |
| \ If response is successful, then send back SME_ADDTS_RSP. |
| \ Otherwise, send DELTS action frame to peer and then |
| \ then send back SME_ADDTS_RSP. |
| \ |
| \param tpAniSirGlobal pMac |
| \param tpSirMsgQ limMsg |
| -------------------------------------------------------------*/ |
| void limProcessHalAddTsRsp(tpAniSirGlobal pMac, tpSirMsgQ limMsg) |
| { |
| tpAddTsParams pAddTsRspMsg = NULL; |
| tpDphHashNode pSta = NULL; |
| tANI_U16 assocId =0; |
| tSirMacAddr peerMacAddr; |
| tANI_U8 rspReqd = 1; |
| tpPESession psessionEntry = NULL; |
| |
| |
| /* Need to process all the deferred messages enqueued |
| * since sending the WDA_ADD_TS_REQ. |
| */ |
| SET_LIM_PROCESS_DEFD_MESGS(pMac, true); |
| |
| if (NULL == limMsg->bodyptr) |
| { |
| limLog(pMac, LOGP, FL("Received WDA_ADD_TS_RSP with NULL ")); |
| goto end; |
| } |
| |
| pAddTsRspMsg = (tpAddTsParams) (limMsg->bodyptr); |
| |
| // 090803: Use peFindSessionBySessionId() to obtain the PE session context |
| // from the sessionId in the Rsp Msg from HAL |
| psessionEntry = peFindSessionBySessionId(pMac, pAddTsRspMsg->sessionId); |
| |
| if(psessionEntry == NULL) |
| { |
| PELOGE(limLog(pMac, LOGE,FL("Session does Not exist with given sessionId :%d "), pAddTsRspMsg->sessionId);) |
| limSendSmeAddtsRsp(pMac, rspReqd, eSIR_SME_ADDTS_RSP_FAILED, psessionEntry, pAddTsRspMsg->tspec, |
| pMac->lim.gLimAddtsReq.sessionId, pMac->lim.gLimAddtsReq.transactionId); |
| goto end; |
| } |
| |
| if(pAddTsRspMsg->status == eHAL_STATUS_SUCCESS) |
| { |
| limLog(pMac, LOG1, FL("Received successful ADDTS response from HAL ")); |
| // Use the smesessionId and smetransactionId from the PE session context |
| limSendSmeAddtsRsp(pMac, rspReqd, eSIR_SME_SUCCESS, psessionEntry, pAddTsRspMsg->tspec, |
| psessionEntry->smeSessionId, psessionEntry->transactionId); |
| goto end; |
| } |
| else |
| { |
| limLog(pMac, LOG1, FL("Received failure ADDTS response from HAL ")); |
| |
| // Send DELTS action frame to AP |
| // 090803: Get peer MAC addr from session |
| #if 0 |
| cfgLen = sizeof(tSirMacAddr); |
| if (wlan_cfgGetStr(pMac, WNI_CFG_BSSID, peerMacAddr, &cfgLen) != eSIR_SUCCESS) |
| { |
| limLog(pMac, LOGP, FL("Fail to retrieve BSSID ")); |
| goto end; |
| } |
| #endif //TO SUPPORT BT-AMP |
| sirCopyMacAddr(peerMacAddr,psessionEntry->bssId); |
| |
| // 090803: Add the SME Session ID |
| limSendDeltsReqActionFrame(pMac, peerMacAddr, rspReqd, &pAddTsRspMsg->tspec.tsinfo, &pAddTsRspMsg->tspec, |
| //psessionEntry->smeSessionId); |
| psessionEntry); |
| |
| // Delete TSPEC |
| // 090803: Pull the hash table from the session |
| pSta = dphLookupAssocId(pMac, pAddTsRspMsg->staIdx, &assocId, |
| &psessionEntry->dph.dphHashTable); |
| if (pSta != NULL) |
| limAdmitControlDeleteTS(pMac, assocId, &pAddTsRspMsg->tspec.tsinfo, NULL, (tANI_U8 *)&pAddTsRspMsg->tspecIdx); |
| |
| // Send SME_ADDTS_RSP |
| // 090803: Use the smesessionId and smetransactionId from the PE session context |
| limSendSmeAddtsRsp(pMac, rspReqd, eSIR_SME_ADDTS_RSP_FAILED, psessionEntry, pAddTsRspMsg->tspec, |
| psessionEntry->smeSessionId, psessionEntry->transactionId); |
| goto end; |
| } |
| |
| end: |
| if( pAddTsRspMsg != NULL ) |
| vos_mem_free(pAddTsRspMsg); |
| return; |
| } |
| |