/*
 * Copyright (c) 2012-2017 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.
 */

#include "cds_api.h"
#include "sir_common.h"

#include "wni_cfg.h"
#include "ani_global.h"
#include "cfg_api.h"
#include "lim_api.h"
#include "lim_send_messages.h"

#include "sch_api.h"

/* / Minimum beacon interval allowed (in Kus) */
#define SCH_BEACON_INTERVAL_MIN  10

/* / Maximum beacon interval allowed (in Kus) */
#define SCH_BEACON_INTERVAL_MAX  10000

/* / convert the CW values into a uint16_t */
#define GET_CW(pCw) ((uint16_t) ((*(pCw) << 8) + *((pCw) + 1)))

/* local functions */
static tSirRetStatus get_wmm_local_params(tpAniSirGlobal pMac,
					  uint32_t
					  params[]
					  [WNI_CFG_EDCA_ANI_ACBK_LOCAL_LEN]);
static void set_sch_edca_params(tpAniSirGlobal pMac,
				uint32_t params[][WNI_CFG_EDCA_ANI_ACBK_LOCAL_LEN],
				tpPESession psessionEntry);

/* -------------------------------------------------------------------- */
/**
 * sch_set_beacon_interval
 *
 * FUNCTION:
 *
 * LOGIC:
 *
 * ASSUMPTIONS:
 *
 * NOTE:
 *
 * @param None
 * @return None
 */

void sch_set_beacon_interval(tpAniSirGlobal pMac, tpPESession psessionEntry)
{
	uint32_t bi;

	bi = psessionEntry->beaconParams.beaconInterval;

	if (bi < SCH_BEACON_INTERVAL_MIN || bi > SCH_BEACON_INTERVAL_MAX) {
		pe_debug("Invalid beacon interval %d (should be [%d,%d]", bi,
			SCH_BEACON_INTERVAL_MIN, SCH_BEACON_INTERVAL_MAX);
		return;
	}

	pMac->sch.schObject.gSchBeaconInterval = (uint16_t) bi;
}

static void sch_edca_profile_update_all(tpAniSirGlobal pmac)
{
	uint32_t i;
	tpPESession psession_entry;

	for (i = 0; i < pmac->lim.maxBssId; i++) {
		psession_entry = &pmac->lim.gpSession[i];
		if (psession_entry->valid)
			sch_edca_profile_update(pmac, psession_entry);
	}
}

/* -------------------------------------------------------------------- */
/**
 * sch_process_message
 *
 * FUNCTION:
 *
 * LOGIC:
 *
 * ASSUMPTIONS:
 *
 * NOTE:
 *
 * @param None
 * @return None
 */

void sch_process_message(tpAniSirGlobal pMac, struct scheduler_msg *pSchMsg)
{
	tpPESession psessionEntry = &pMac->lim.gpSession[0];

	switch (pSchMsg->type) {
	case SIR_CFG_PARAM_UPDATE_IND:
		switch (pSchMsg->bodyval) {
		case WNI_CFG_BEACON_INTERVAL:
			/* What to do for IBSS ?? - TBD */
			if (LIM_IS_AP_ROLE(psessionEntry))
				sch_set_beacon_interval(pMac, psessionEntry);
			break;

		case WNI_CFG_COUNTRY_CODE:
			pe_debug("sch: WNI_CFG_COUNTRY_CODE changed");
			sch_edca_profile_update_all(pMac);
			break;

		case WNI_CFG_EDCA_PROFILE:
			sch_edca_profile_update(pMac, psessionEntry);
			break;

		case WNI_CFG_EDCA_ANI_ACBK_LOCAL:
		case WNI_CFG_EDCA_ANI_ACBE_LOCAL:
		case WNI_CFG_EDCA_ANI_ACVI_LOCAL:
		case WNI_CFG_EDCA_ANI_ACVO_LOCAL:
		case WNI_CFG_EDCA_WME_ACBK_LOCAL:
		case WNI_CFG_EDCA_WME_ACBE_LOCAL:
		case WNI_CFG_EDCA_WME_ACVI_LOCAL:
		case WNI_CFG_EDCA_WME_ACVO_LOCAL:
			if (LIM_IS_AP_ROLE(psessionEntry))
				sch_qos_update_local(pMac, psessionEntry);
			break;

		case WNI_CFG_EDCA_ANI_ACBK:
		case WNI_CFG_EDCA_ANI_ACBE:
		case WNI_CFG_EDCA_ANI_ACVI:
		case WNI_CFG_EDCA_ANI_ACVO:
		case WNI_CFG_EDCA_WME_ACBK:
		case WNI_CFG_EDCA_WME_ACBE:
		case WNI_CFG_EDCA_WME_ACVI:
		case WNI_CFG_EDCA_WME_ACVO:
			if (LIM_IS_AP_ROLE(psessionEntry)) {
				sch_qos_update_broadcast(pMac, psessionEntry);
			}
			break;

		default:
			pe_err("Cfg param %d indication not handled",
				pSchMsg->bodyval);
		}
		break;

	default:
		pe_err("Unknown message in schMsgQ type %d", pSchMsg->type);
	}

}

/* get the local or broadcast parameters based on the profile sepcified in the config */
/* params are delivered in this order: BK, BE, VI, VO */
static tSirRetStatus
sch_get_params(tpAniSirGlobal pMac,
	       uint32_t params[][WNI_CFG_EDCA_ANI_ACBK_LOCAL_LEN],
	       uint8_t local)
{
	uint32_t val;
	uint32_t i, idx;
	uint32_t *prf;
	uint8_t country_code_str[WNI_CFG_COUNTRY_CODE_LEN];
	uint32_t country_code_len = WNI_CFG_COUNTRY_CODE_LEN;
	uint32_t ani_l[] = {
	  WNI_CFG_EDCA_ANI_ACBE_LOCAL, WNI_CFG_EDCA_ANI_ACBK_LOCAL,
	  WNI_CFG_EDCA_ANI_ACVI_LOCAL, WNI_CFG_EDCA_ANI_ACVO_LOCAL};
	uint32_t wme_l[] = {
	  WNI_CFG_EDCA_WME_ACBE_LOCAL, WNI_CFG_EDCA_WME_ACBK_LOCAL,
	  WNI_CFG_EDCA_WME_ACVI_LOCAL, WNI_CFG_EDCA_WME_ACVO_LOCAL};
	uint32_t etsi_l[] = {WNI_CFG_EDCA_ETSI_ACBE_LOCAL,
			WNI_CFG_EDCA_ETSI_ACBK_LOCAL,
			WNI_CFG_EDCA_ETSI_ACVI_LOCAL,
			WNI_CFG_EDCA_ETSI_ACVO_LOCAL};
	uint32_t ani_b[] = { WNI_CFG_EDCA_ANI_ACBE, WNI_CFG_EDCA_ANI_ACBK,
			     WNI_CFG_EDCA_ANI_ACVI, WNI_CFG_EDCA_ANI_ACVO};
	uint32_t wme_b[] = { WNI_CFG_EDCA_WME_ACBE, WNI_CFG_EDCA_WME_ACBK,
			     WNI_CFG_EDCA_WME_ACVI, WNI_CFG_EDCA_WME_ACVO};
	uint32_t etsi_b[] = {WNI_CFG_EDCA_ETSI_ACBE, WNI_CFG_EDCA_ETSI_ACBK,
			WNI_CFG_EDCA_ETSI_ACVI, WNI_CFG_EDCA_ETSI_ACVO};

	if (wlan_cfg_get_str(pMac, WNI_CFG_COUNTRY_CODE, country_code_str,
			     &country_code_len) == eSIR_SUCCESS &&
	    cds_is_etsi_europe_country(country_code_str)) {
		val = WNI_CFG_EDCA_PROFILE_ETSI_EUROPE;
		pe_debug("switch to ETSI EUROPE profile country code %c%c",
			 country_code_str[0], country_code_str[1]);
	} else if (wlan_cfg_get_int(pMac, WNI_CFG_EDCA_PROFILE, &val) !=
		   eSIR_SUCCESS) {
		pe_err("failed to cfg get EDCA_PROFILE id %d",
			WNI_CFG_EDCA_PROFILE);
		return eSIR_FAILURE;
	}

	if (val >= WNI_CFG_EDCA_PROFILE_MAX) {
		pe_warn("Invalid EDCA_PROFILE %d, using %d instead", val,
			WNI_CFG_EDCA_PROFILE_ANI);
		val = WNI_CFG_EDCA_PROFILE_ANI;
	}

	pe_debug("EdcaProfile: Using %d (%s)", val,
		((val == WNI_CFG_EDCA_PROFILE_WMM) ? "WMM" : "HiPerf"));

	if (local) {
		switch (val) {
		case WNI_CFG_EDCA_PROFILE_WMM:
			prf = &wme_l[0];
			break;
		case WNI_CFG_EDCA_PROFILE_ETSI_EUROPE:
			prf = &etsi_l[0];
			break;
		case WNI_CFG_EDCA_PROFILE_ANI:
		default:
			prf = &ani_l[0];
			break;
		}
	} else {
		switch (val) {
		case WNI_CFG_EDCA_PROFILE_WMM:
			prf = &wme_b[0];
			break;
		case WNI_CFG_EDCA_PROFILE_ETSI_EUROPE:
			prf = &etsi_b[0];
			break;
		case WNI_CFG_EDCA_PROFILE_ANI:
		default:
			prf = &ani_b[0];
			break;
		}
	}

	for (i = 0; i < 4; i++) {
		uint8_t data[WNI_CFG_EDCA_ANI_ACBK_LEN];
		uint32_t len = WNI_CFG_EDCA_ANI_ACBK_LOCAL_LEN;
		if (wlan_cfg_get_str
			    (pMac, (uint16_t) prf[i], (uint8_t *) &data[0],
			    &len) != eSIR_SUCCESS) {
			pe_err("cfgGet failed for %d", prf[i]);
			return eSIR_FAILURE;
		}
		if (len > WNI_CFG_EDCA_ANI_ACBK_LOCAL_LEN) {
			pe_err("cfgGet for %d: length is %d instead of %d",
				prf[i], len, WNI_CFG_EDCA_ANI_ACBK_LOCAL_LEN);
			return eSIR_FAILURE;
		}
		for (idx = 0; idx < len; idx++)
			params[i][idx] = (uint32_t) data[idx];
	}
	pe_debug("GetParams: local=%d, profile = %d Done", local, val);

	return eSIR_SUCCESS;
}

/**
 * broadcast_wmm_of_concurrent_sta_session() - broadcasts wmm info
 * @mac_ctx:          mac global context
 * @session:       pesession entry
 *
 * Return: true if wmm param updated, false if wmm param not updated
 */
static bool
broadcast_wmm_of_concurrent_sta_session(tpAniSirGlobal mac_ctx,
					tpPESession session)
{
	uint8_t i, j;
	tpPESession concurrent_session = NULL;

	for (i = 0; i < mac_ctx->lim.maxBssId; i++) {
		/*
		 * Find another INFRA STA AP session on same operating channel.
		 * The session entry passed to this API is for GO/SoftAP session
		 * that is getting added currently
		 */
		if (!((mac_ctx->lim.gpSession[i].valid == true) &&
		    (mac_ctx->lim.gpSession[i].peSessionId !=
		     session->peSessionId)
		    && (mac_ctx->lim.gpSession[i].currentOperChannel ==
			session->currentOperChannel)
		    && (mac_ctx->lim.gpSession[i].limSystemRole
			== eLIM_STA_ROLE)))
			continue;

		concurrent_session = &(mac_ctx->lim.gpSession[i]);
		break;
	}

	if (concurrent_session == NULL)
		return false;

	if (!qdf_mem_cmp(session->gLimEdcaParamsBC,
	   concurrent_session->gLimEdcaParams,
	   sizeof(concurrent_session->gLimEdcaParams)))
		return false;

	/*
	 * Once atleast one concurrent session on same channel is found and WMM
	 * broadcast params for current SoftAP/GO session updated, return
	 */
	for (j = 0; j < MAX_NUM_AC; j++) {
		session->gLimEdcaParamsBC[j].aci.acm =
			concurrent_session->gLimEdcaParams[j].aci.acm;
		session->gLimEdcaParamsBC[j].aci.aifsn =
			concurrent_session->gLimEdcaParams[j].aci.aifsn;
		session->gLimEdcaParamsBC[j].cw.min =
			concurrent_session->gLimEdcaParams[j].cw.min;
		session->gLimEdcaParamsBC[j].cw.max =
			concurrent_session->gLimEdcaParams[j].cw.max;
		session->gLimEdcaParamsBC[j].txoplimit =
			concurrent_session->gLimEdcaParams[j].txoplimit;
		pe_debug("QoSUpdateBCast changed again due to concurrent INFRA STA session: AC :%d: AIFSN: %d, ACM %d, CWmin %d, CWmax %d, TxOp %d",
		       j, session->gLimEdcaParamsBC[j].aci.aifsn,
		       session->gLimEdcaParamsBC[j].aci.acm,
		       session->gLimEdcaParamsBC[j].cw.min,
		       session->gLimEdcaParamsBC[j].cw.max,
		       session->gLimEdcaParamsBC[j].txoplimit);
	}
	return true;
}

void sch_qos_update_broadcast(tpAniSirGlobal pMac, tpPESession psessionEntry)
{
	uint32_t params[4][WNI_CFG_EDCA_ANI_ACBK_LOCAL_LEN];
	uint32_t cwminidx, cwmaxidx, txopidx;
	uint32_t phyMode;
	uint8_t i;
	bool updated = false;

	if (sch_get_params(pMac, params, false) != eSIR_SUCCESS) {
		pe_debug("QosUpdateBroadcast: failed");
		return;
	}
	lim_get_phy_mode(pMac, &phyMode, psessionEntry);

	pe_debug("QosUpdBcast: mode %d", phyMode);

	if (phyMode == WNI_CFG_PHY_MODE_11G) {
		cwminidx = WNI_CFG_EDCA_PROFILE_CWMING_IDX;
		cwmaxidx = WNI_CFG_EDCA_PROFILE_CWMAXG_IDX;
		txopidx = WNI_CFG_EDCA_PROFILE_TXOPG_IDX;
	} else if (phyMode == WNI_CFG_PHY_MODE_11B) {
		cwminidx = WNI_CFG_EDCA_PROFILE_CWMINB_IDX;
		cwmaxidx = WNI_CFG_EDCA_PROFILE_CWMAXB_IDX;
		txopidx = WNI_CFG_EDCA_PROFILE_TXOPB_IDX;
	} else {
		/* This can happen if mode is not set yet, assume 11a mode */
		cwminidx = WNI_CFG_EDCA_PROFILE_CWMINA_IDX;
		cwmaxidx = WNI_CFG_EDCA_PROFILE_CWMAXA_IDX;
		txopidx = WNI_CFG_EDCA_PROFILE_TXOPA_IDX;
	}

	for (i = 0; i < MAX_NUM_AC; i++) {
		if (psessionEntry->gLimEdcaParamsBC[i].aci.acm !=
			(uint8_t) params[i][WNI_CFG_EDCA_PROFILE_ACM_IDX]) {
			psessionEntry->gLimEdcaParamsBC[i].aci.acm =
			(uint8_t) params[i][WNI_CFG_EDCA_PROFILE_ACM_IDX];
			updated = true;
		}
		if (psessionEntry->gLimEdcaParamsBC[i].aci.aifsn !=
			(uint8_t) params[i][WNI_CFG_EDCA_PROFILE_AIFSN_IDX]) {
			psessionEntry->gLimEdcaParamsBC[i].aci.aifsn =
			(uint8_t) params[i][WNI_CFG_EDCA_PROFILE_AIFSN_IDX];
			updated = true;
		}
		if (psessionEntry->gLimEdcaParamsBC[i].cw.min !=
			convert_cw(GET_CW(&params[i][cwminidx]))) {
			psessionEntry->gLimEdcaParamsBC[i].cw.min =
			convert_cw(GET_CW(&params[i][cwminidx]));
			updated = true;
		}
		if (psessionEntry->gLimEdcaParamsBC[i].cw.max !=
			convert_cw(GET_CW(&params[i][cwmaxidx]))) {
			psessionEntry->gLimEdcaParamsBC[i].cw.max =
			convert_cw(GET_CW(&params[i][cwmaxidx]));
			updated = true;
		}
		if (psessionEntry->gLimEdcaParamsBC[i].txoplimit !=
			(uint16_t) params[i][txopidx]) {
			psessionEntry->gLimEdcaParamsBC[i].txoplimit =
			(uint16_t) params[i][txopidx];
			updated = true;
		}

		pe_debug("QoSUpdateBCast: AC :%d: AIFSN: %d, ACM %d, CWmin %d, CWmax %d, TxOp %d",
			       i, psessionEntry->gLimEdcaParamsBC[i].aci.aifsn,
			       psessionEntry->gLimEdcaParamsBC[i].aci.acm,
			       psessionEntry->gLimEdcaParamsBC[i].cw.min,
			       psessionEntry->gLimEdcaParamsBC[i].cw.max,
			       psessionEntry->gLimEdcaParamsBC[i].txoplimit);

	}

	/* If there exists a concurrent STA-AP session, use its WMM params to broadcast in beacons. WFA Wifi Direct test plan 6.1.14 requirement */
	if (broadcast_wmm_of_concurrent_sta_session(pMac, psessionEntry))
		updated = true;
	if (updated)
		psessionEntry->gLimEdcaParamSetCount++;

	if (sch_set_fixed_beacon_fields(pMac, psessionEntry) != eSIR_SUCCESS)
		pe_err("Unable to set beacon fields!");
}

void sch_qos_update_local(tpAniSirGlobal pMac, tpPESession psessionEntry)
{

	uint32_t params[4][WNI_CFG_EDCA_ANI_ACBK_LOCAL_LEN];

	if (sch_get_params(pMac, params, true /*local */) != eSIR_SUCCESS) {
		pe_err("sch_get_params(local) failed");
		return;
	}

	set_sch_edca_params(pMac, params, psessionEntry);

	/* For AP, the bssID is stored in LIM Global context. */
	lim_send_edca_params(pMac, psessionEntry->gLimEdcaParams,
			     psessionEntry->bssIdx);
}

/** ----------------------------------------------------------
   \fn      sch_set_default_edca_params
   \brief   This function sets the gLimEdcaParams to the default
 \        local wmm profile.
   \param   tpAniSirGlobal  pMac
   \return  none
 \ ------------------------------------------------------------ */
void sch_set_default_edca_params(tpAniSirGlobal pMac, tpPESession psessionEntry)
{
	uint32_t params[4][WNI_CFG_EDCA_ANI_ACBK_LOCAL_LEN];

	if (get_wmm_local_params(pMac, params) != eSIR_SUCCESS) {
		pe_err("get_wmm_local_params() failed");
		return;
	}

	set_sch_edca_params(pMac, params, psessionEntry);
	return;
}

/** ----------------------------------------------------------
   \fn      set_sch_edca_params
   \brief   This function fills in the gLimEdcaParams structure
 \        with the given edca params.
   \param   tpAniSirGlobal  pMac
   \return  none
 \ ------------------------------------------------------------ */
static void
set_sch_edca_params(tpAniSirGlobal pMac,
		    uint32_t params[][WNI_CFG_EDCA_ANI_ACBK_LOCAL_LEN],
		    tpPESession psessionEntry)
{
	uint32_t i;
	uint32_t cwminidx, cwmaxidx, txopidx;
	uint32_t phyMode;

	lim_get_phy_mode(pMac, &phyMode, psessionEntry);

	pe_debug("lim_get_phy_mode() = %d", phyMode);
	/* if (pMac->lim.gLimPhyMode == WNI_CFG_PHY_MODE_11G) */
	if (phyMode == WNI_CFG_PHY_MODE_11G) {
		cwminidx = WNI_CFG_EDCA_PROFILE_CWMING_IDX;
		cwmaxidx = WNI_CFG_EDCA_PROFILE_CWMAXG_IDX;
		txopidx = WNI_CFG_EDCA_PROFILE_TXOPG_IDX;
	}
	/* else if (pMac->lim.gLimPhyMode == WNI_CFG_PHY_MODE_11B) */
	else if (phyMode == WNI_CFG_PHY_MODE_11B) {
		cwminidx = WNI_CFG_EDCA_PROFILE_CWMINB_IDX;
		cwmaxidx = WNI_CFG_EDCA_PROFILE_CWMAXB_IDX;
		txopidx = WNI_CFG_EDCA_PROFILE_TXOPB_IDX;
	} else {
		/* This can happen if mode is not set yet, assume 11a mode */
		cwminidx = WNI_CFG_EDCA_PROFILE_CWMINA_IDX;
		cwmaxidx = WNI_CFG_EDCA_PROFILE_CWMAXA_IDX;
		txopidx = WNI_CFG_EDCA_PROFILE_TXOPA_IDX;
	}

	for (i = 0; i < MAX_NUM_AC; i++) {
		psessionEntry->gLimEdcaParams[i].aci.acm =
			(uint8_t) params[i][WNI_CFG_EDCA_PROFILE_ACM_IDX];
		psessionEntry->gLimEdcaParams[i].aci.aifsn =
			(uint8_t) params[i][WNI_CFG_EDCA_PROFILE_AIFSN_IDX];
		psessionEntry->gLimEdcaParams[i].cw.min =
			convert_cw(GET_CW(&params[i][cwminidx]));
		psessionEntry->gLimEdcaParams[i].cw.max =
			convert_cw(GET_CW(&params[i][cwmaxidx]));
		psessionEntry->gLimEdcaParams[i].txoplimit =
			(uint16_t) params[i][txopidx];

		pe_debug("AC :%d: AIFSN: %d, ACM %d, CWmin %d, CWmax %d, TxOp %d",
			       i, psessionEntry->gLimEdcaParams[i].aci.aifsn,
			       psessionEntry->gLimEdcaParams[i].aci.acm,
			       psessionEntry->gLimEdcaParams[i].cw.min,
			       psessionEntry->gLimEdcaParams[i].cw.max,
			       psessionEntry->gLimEdcaParams[i].txoplimit);

	}
	return;
}

/** ----------------------------------------------------------
   \fn      get_wmm_local_params
   \brief   This function gets the WMM local edca parameters.
   \param   tpAniSirGlobal  pMac
   \param   uint32_t params[][WNI_CFG_EDCA_ANI_ACBK_LOCAL_LEN]
   \return  none
 \ ------------------------------------------------------------ */
static tSirRetStatus
get_wmm_local_params(tpAniSirGlobal pMac,
		     uint32_t params[][WNI_CFG_EDCA_ANI_ACBK_LOCAL_LEN])
{
	uint32_t i, idx;
	uint32_t *prf;
	uint32_t wme_l[] = {
	  WNI_CFG_EDCA_WME_ACBE_LOCAL, WNI_CFG_EDCA_WME_ACBK_LOCAL,
	  WNI_CFG_EDCA_WME_ACVI_LOCAL, WNI_CFG_EDCA_WME_ACVO_LOCAL};

	prf = &wme_l[0];
	for (i = 0; i < 4; i++) {
		uint8_t data[WNI_CFG_EDCA_ANI_ACBK_LEN];
		uint32_t len = WNI_CFG_EDCA_ANI_ACBK_LOCAL_LEN;
		if (wlan_cfg_get_str
			    (pMac, (uint16_t) prf[i], (uint8_t *) &data[0],
			    &len) != eSIR_SUCCESS) {
			pe_err("cfgGet failed for %d", prf[i]);
			return eSIR_FAILURE;
		}
		if (len > WNI_CFG_EDCA_ANI_ACBK_LOCAL_LEN) {
			pe_err("cfgGet for %d: length is %d instead of %d",
				prf[i], len, WNI_CFG_EDCA_ANI_ACBK_LOCAL_LEN);
			return eSIR_FAILURE;
		}
		for (idx = 0; idx < len; idx++)
			params[i][idx] = (uint32_t) data[idx];
	}
	return eSIR_SUCCESS;
}

/** ----------------------------------------------------------
   \fn      sch_edca_profile_update
   \brief   This function updates the local and broadcast
 \        EDCA params in the gLimEdcaParams structure. It also
 \        updates the edcaParamSetCount.
   \param   tpAniSirGlobal  pMac
   \return  none
 \ ------------------------------------------------------------ */
void sch_edca_profile_update(tpAniSirGlobal pMac, tpPESession psessionEntry)
{
	if (LIM_IS_AP_ROLE(psessionEntry) ||
	    LIM_IS_IBSS_ROLE(psessionEntry)) {
		sch_qos_update_local(pMac, psessionEntry);
		sch_qos_update_broadcast(pMac, psessionEntry);
	}
}

/* -------------------------------------------------------------------- */
