| /* |
| * Copyright (c) 2013-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. |
| */ |
| |
| /* |
| * This file limRMC.c contains the code |
| * for processing RMC messages |
| * |
| */ |
| #include "wniApi.h" |
| #include "wniCfg.h" |
| #include "cfgApi.h" |
| #include "sirApi.h" |
| #include "schApi.h" |
| #include "utilsApi.h" |
| #include "limUtils.h" |
| #include "limTimerUtils.h" |
| #include "limSendMessages.h" |
| #include "limSendMessages.h" |
| #include "limSession.h" |
| #include "limSessionUtils.h" |
| #include "wlan_qct_wda.h" |
| #include "wlan_qct_tli.h" |
| #include "limRMC.h" |
| |
| #ifdef WLAN_FEATURE_RMC |
| |
| static tANI_U8 |
| __rmcGroupHashFunction(tSirMacAddr transmitter) |
| { |
| tANI_U16 hash; |
| |
| /* |
| * Generate a hash using transmitter address |
| */ |
| hash = transmitter[0] + transmitter[1] + transmitter[2] + |
| transmitter[3] + transmitter[4] + transmitter[5]; |
| |
| return hash & (RMC_MCAST_GROUPS_HASH_SIZE - 1); |
| } |
| |
| |
| static tLimRmcGroupContext * |
| __rmcGroupLookupHashEntry(tpAniSirGlobal pMac, tSirMacAddr transmitter) |
| { |
| tANI_U8 index; |
| tLimRmcGroupContext *entry; |
| |
| index = __rmcGroupHashFunction(transmitter); |
| |
| /* Pick the correct hash table based on role */ |
| entry = pMac->rmcContext.rmcGroupRxHashTable[index]; |
| |
| PELOG1(limLog(pMac, LOG1, FL("RMC: Hash Lookup:[%d] transmitter " |
| MAC_ADDRESS_STR ), index, |
| MAC_ADDR_ARRAY(transmitter));) |
| while (entry) |
| { |
| if (vos_mem_compare(transmitter, entry->transmitter, |
| sizeof(v_MACADDR_t))) |
| { |
| return entry; |
| } |
| |
| entry = entry->next; |
| } |
| |
| return NULL; |
| } |
| |
| static tLimRmcGroupContext * |
| __rmcGroupInsertHashEntry(tpAniSirGlobal pMac, tSirMacAddr transmitter) |
| { |
| tANI_U8 index; |
| tLimRmcGroupContext *entry; |
| tLimRmcGroupContext **head; |
| |
| index = __rmcGroupHashFunction(transmitter); |
| |
| PELOG1(limLog(pMac, LOG1, FL("RMC: Hash Insert:[%d] group " MAC_ADDRESS_STR |
| " transmitter " MAC_ADDRESS_STR), index, |
| MAC_ADDR_ARRAY(mcastGroupAddr), |
| MAC_ADDR_ARRAY(transmitter));) |
| |
| head = &pMac->rmcContext.rmcGroupRxHashTable[index]; |
| |
| entry = __rmcGroupLookupHashEntry(pMac, transmitter); |
| |
| if (entry) |
| { |
| /* If the entry exists, return it at the end */ |
| PELOGE(limLog(pMac, LOGE, FL("RMC: Hash Insert:" |
| MAC_ADDRESS_STR "exists"), MAC_ADDR_ARRAY(transmitter));) |
| } |
| else |
| { |
| entry = (tLimRmcGroupContext *)vos_mem_malloc(sizeof(*entry)); |
| |
| PELOG1(limLog(pMac, LOG1, FL("RMC: Hash Insert:new entry %pK"), entry);) |
| |
| if (entry) |
| { |
| vos_mem_copy(entry->transmitter, transmitter, sizeof(tSirMacAddr)); |
| entry->isRuler = eRMC_IS_NOT_A_RULER; |
| |
| /* chain this entry */ |
| entry->next = *head; |
| *head = entry; |
| } |
| else |
| { |
| PELOGE(limLog(pMac, LOGE, FL("RMC: Hash Insert:" MAC_ADDRESS_STR |
| " alloc failed"), MAC_ADDR_ARRAY(transmitter));) |
| } |
| } |
| |
| return entry; |
| } |
| |
| /** |
| * __rmcGroupDeleteHashEntry() |
| * |
| *FUNCTION: |
| * This function is called to delete a RMC group entry |
| * |
| *LOGIC: |
| * |
| *ASSUMPTIONS: |
| * Should be called with lkRmcLock held. |
| * |
| *NOTE: |
| * Make sure (for the transmitter role) that the entry is |
| * not in the Pending Response queue. |
| * |
| * @param transmitter - address of multicast transmitter |
| * |
| * @return status |
| */ |
| static tSirRetStatus |
| __rmcGroupDeleteHashEntry(tpAniSirGlobal pMac, tSirMacAddr transmitter) |
| { |
| tSirRetStatus status = eSIR_FAILURE; |
| tANI_U8 index; |
| tLimRmcGroupContext *entry, *prev, **head; |
| |
| index = __rmcGroupHashFunction(transmitter); |
| |
| head = &pMac->rmcContext.rmcGroupRxHashTable[index]; |
| entry = *head; |
| prev = NULL; |
| |
| while (entry) |
| { |
| if (vos_mem_compare(transmitter, entry->transmitter, |
| sizeof(v_MACADDR_t))) |
| { |
| if (*head == entry) |
| { |
| *head = entry->next; |
| } |
| else |
| { |
| prev->next = entry->next; |
| } |
| |
| PELOG1(limLog(pMac, LOG1, FL("RMC: Hash Delete: entry %pK " |
| " transmitter " MAC_ADDRESS_STR), entry |
| MAC_ADDR_ARRAY(transmitter));) |
| |
| /* free the group entry */ |
| vos_mem_free(entry); |
| |
| status = eSIR_SUCCESS; |
| break; |
| } |
| |
| prev = entry; |
| entry = entry->next; |
| } |
| |
| return status; |
| } |
| |
| static void |
| __rmcGroupDeleteAllEntries(tpAniSirGlobal pMac) |
| { |
| tLimRmcGroupContext *entry, **head; |
| int index; |
| |
| PELOG1(limLog(pMac, LOG1, FL("RMC: Hash_Delete_All"),);) |
| |
| for (index = 0; index < RMC_MCAST_GROUPS_HASH_SIZE; index++) |
| { |
| head = &pMac->rmcContext.rmcGroupRxHashTable[index]; |
| |
| entry = *head; |
| |
| while (entry) |
| { |
| *head = entry->next; |
| /* free the group entry */ |
| vos_mem_free(entry); |
| entry = *head; |
| } |
| } |
| } |
| |
| static void |
| __limPostMsgRulerReq ( tpAniSirGlobal pMac, |
| tANI_U8 cmd, |
| tSirMacAddr mcastTransmitter) |
| { |
| tSirMsgQ msg; |
| tSirRmcRulerReq *pRulerReq; |
| |
| pRulerReq = vos_mem_malloc(sizeof(*pRulerReq)); |
| if (NULL == pRulerReq) |
| { |
| limLog(pMac, LOGE, FL("AllocateMemory() failed")); |
| return; |
| } |
| |
| pRulerReq->cmd = cmd; |
| |
| vos_mem_copy(pRulerReq->mcastTransmitter, mcastTransmitter, |
| sizeof(tSirMacAddr)); |
| |
| /* Initialize black list */ |
| vos_mem_zero(pRulerReq->blacklist, sizeof(pRulerReq->blacklist)); |
| |
| if (eRMC_SUGGEST_RULER_CMD == cmd) |
| { |
| /* TODO - Set the black list. */ |
| } |
| |
| msg.type = WDA_RMC_RULER_REQ; |
| msg.bodyptr = pRulerReq; |
| msg.bodyval = 0; |
| |
| MTRACE(macTraceMsgTx(pMac, NO_SESSION, msg.type)); |
| if (eSIR_SUCCESS != wdaPostCtrlMsg(pMac, &msg)) |
| { |
| vos_mem_free(pRulerReq); |
| limLog(pMac, LOGE, FL("wdaPostCtrlMsg() failed")); |
| } |
| |
| return; |
| } |
| |
| static void |
| __limPostMsgUpdateInd ( tpAniSirGlobal pMac, |
| tANI_U8 indication, |
| tANI_U8 role, |
| tSirMacAddr mcastTransmitter, |
| tSirMacAddr mcastRuler) |
| { |
| tSirMsgQ msg; |
| tSirRmcUpdateInd *pUpdateInd; |
| |
| pUpdateInd = vos_mem_malloc(sizeof(*pUpdateInd)); |
| if ( NULL == pUpdateInd ) |
| { |
| limLog(pMac, LOGE, FL("AllocateMemory() failed")); |
| return; |
| } |
| |
| vos_mem_zero(pUpdateInd, sizeof(*pUpdateInd)); |
| |
| pUpdateInd->indication = indication; |
| pUpdateInd->role = role; |
| |
| vos_mem_copy(pUpdateInd->mcastTransmitter, |
| mcastTransmitter, sizeof(tSirMacAddr)); |
| |
| vos_mem_copy(pUpdateInd->mcastRuler, |
| mcastRuler, sizeof(tSirMacAddr)); |
| |
| msg.type = WDA_RMC_UPDATE_IND; |
| msg.bodyptr = pUpdateInd; |
| msg.bodyval = 0; |
| |
| MTRACE(macTraceMsgTx(pMac, NO_SESSION, msg.type)); |
| if (eSIR_SUCCESS != wdaPostCtrlMsg(pMac, &msg)) |
| { |
| vos_mem_free(pUpdateInd); |
| limLog(pMac, LOGE, FL("wdaPostCtrlMsg() failed")); |
| } |
| |
| return; |
| } |
| |
| static char * |
| __limRulerMessageToString(eRmcMessageType msgType) |
| { |
| switch (msgType) |
| { |
| default: |
| return "Invalid"; |
| case eLIM_RMC_ENABLE_REQ: |
| return "RMC_ENABLE_REQ"; |
| case eLIM_RMC_DISABLE_REQ: |
| return "RMC_DISABLE_REQ"; |
| case eLIM_RMC_RULER_SELECT_RESP: |
| return "RMC_RULER_SELECT_RESP"; |
| case eLIM_RMC_RULER_PICK_NEW: |
| return "RMC_RULER_PICK_NEW"; |
| case eLIM_RMC_OTA_RULER_INFORM_ACK: |
| return "RMC_OTA_RULER_INFORM_ACK"; |
| case eLIM_RMC_OTA_RULER_INFORM_SELECTED: |
| return "RMC_OTA_RULER_INFORM_SELECTED"; |
| case eLIM_RMC_BECOME_RULER_RESP: |
| return "RMC_BECOME_RULER_RESP"; |
| case eLIM_RMC_OTA_RULER_INFORM_CANCELLED: |
| return "RMC_OTA_RULER_INFORM_CANCELLED"; |
| } |
| } |
| |
| static char * |
| __limRulerStateToString(eRmcRulerState state) |
| { |
| switch (state) |
| { |
| default: |
| return "Invalid"; |
| case eRMC_IS_NOT_A_RULER: |
| return "Device Not a Ruler"; |
| case eRMC_RULER_PENDING: |
| return "Pending firmware resp"; |
| case eRMC_IS_A_RULER: |
| return "Device is Ruler"; |
| } |
| } |
| |
| static char * |
| __limMcastTxStateToString(eRmcMcastTxState state) |
| { |
| switch (state) |
| { |
| default: |
| return "Invalid"; |
| case eRMC_RULER_NOT_SELECTED: |
| return "Not Selected"; |
| case eRMC_RULER_ENABLE_REQUESTED: |
| return "Enable Requested"; |
| case eRMC_RULER_OTA_REQUEST_SENT: |
| return "OTA Request Sent"; |
| case eRMC_RULER_ACTIVE: |
| return "Active"; |
| } |
| } |
| |
| /** |
| * __rmcRulerSelectTimerHandler() |
| * |
| *FUNCTION: |
| * This function is called upon timer expiry. |
| * |
| * |
| *ASSUMPTIONS: |
| * NA |
| * |
| *NOTE: |
| * Only one entry is processed for every invocation if this routine. |
| * This allows us to use a single timer and makes sure we do not |
| * timeout a request too early. |
| * |
| * @param param - Message corresponding to the timer that expired |
| * |
| * @return None |
| */ |
| |
| void |
| __rmcRulerSelectTimerHandler(void *pMacGlobal, tANI_U32 param) |
| { |
| tpAniSirGlobal pMac = (tpAniSirGlobal)pMacGlobal; |
| tSirMacAddr zeroMacAddr = { 0, 0, 0, 0, 0, 0 }; |
| tSirRetStatus status; |
| tSirRMCInfo RMC; |
| tpPESession psessionEntry; |
| tANI_U32 cfgValue; |
| |
| /* |
| * This API relies on a single active IBSS session. |
| */ |
| psessionEntry = limIsIBSSSessionActive(pMac); |
| if (NULL == psessionEntry) |
| { |
| PELOGE(limLog(pMac, LOGE, |
| FL("RMC:__rmcRulerSelectTimerHandler:No active IBSS"));) |
| return; |
| } |
| |
| if (wlan_cfgGetInt(pMac, WNI_CFG_RMC_ACTION_PERIOD_FREQUENCY, |
| &cfgValue) != eSIR_SUCCESS) |
| { |
| /** |
| * Could not get Action Period Frequency value |
| * from CFG. Log error. |
| */ |
| limLog(pMac, LOGE, FL("could not retrieve ActionPeriodFrequency")); |
| } |
| |
| cfgValue = SYS_MS_TO_TICKS(cfgValue); |
| |
| if (pMac->rmcContext.rmcTimerValInTicks != cfgValue) |
| { |
| limLog(pMac, LOG1, FL("RMC RulerSelect timer value changed")); |
| if (tx_timer_change(&pMac->rmcContext.gRmcRulerSelectTimer, |
| cfgValue, 0) != TX_SUCCESS) |
| { |
| limLog(pMac, LOGE, |
| FL("Unable to change RulerSelect Timer val")); |
| } |
| pMac->rmcContext.rmcTimerValInTicks = cfgValue; |
| } |
| |
| /* |
| * If we are in the scanning state then we need to return |
| * from this function without any further processing |
| */ |
| if (eLIM_HAL_SCANNING_STATE == pMac->lim.gLimHalScanState) |
| { |
| limLog(pMac, LOG1, FL("In scanning state, can't send action frm")); |
| if (tx_timer_activate(&pMac->rmcContext.gRmcRulerSelectTimer) != |
| TX_SUCCESS) |
| { |
| limLog(pMac, LOGE, FL("In scanning state, " |
| "couldn't activate RMC RulerSelect timer")); |
| } |
| return; |
| } |
| |
| if (!VOS_IS_STATUS_SUCCESS(vos_lock_acquire(&pMac->rmcContext.lkRmcLock))) |
| { |
| limLog(pMac, LOGE, |
| FL("__rmcRulerSelectTimerHandler lock acquire failed")); |
| if (tx_timer_activate(&pMac->rmcContext.gRmcRulerSelectTimer)!= TX_SUCCESS) |
| { |
| limLog(pMac, LOGE, FL("could not activate RMC RulerSelect timer")); |
| } |
| return; |
| } |
| |
| vos_mem_copy(&RMC.mcastRuler, &pMac->rmcContext.ruler, |
| sizeof(tSirMacAddr)); |
| |
| if (VOS_FALSE == vos_mem_compare(&zeroMacAddr, |
| &pMac->rmcContext.ruler, sizeof(tSirMacAddr))) |
| { |
| limLog(pMac, LOG1, |
| FL("RMC Periodic Ruler_Select Ruler " MAC_ADDRESS_STR), |
| MAC_ADDR_ARRAY(pMac->rmcContext.ruler)); |
| /* |
| * Re-arm timer |
| */ |
| if (tx_timer_activate(&pMac->rmcContext.gRmcRulerSelectTimer)!= |
| TX_SUCCESS) |
| { |
| limLog(pMac, LOGE, FL("could not activate RMC Response timer")); |
| } |
| |
| if (!VOS_IS_STATUS_SUCCESS |
| (vos_lock_release(&pMac->rmcContext.lkRmcLock))) |
| { |
| limLog(pMac, LOGE, |
| FL("RMC: __rmcRulerSelectTimerHandler lock release failed")); |
| } |
| } |
| else |
| { |
| limLog(pMac, LOGE, |
| FL("RMC Deactivating timer because no ruler was selected")); |
| |
| if (!VOS_IS_STATUS_SUCCESS |
| (vos_lock_release(&pMac->rmcContext.lkRmcLock))) |
| { |
| limLog(pMac, LOGE, |
| FL("RMC: __rmcRulerSelectTimerHandler lock release failed")); |
| } |
| |
| return; |
| } |
| |
| RMC.dialogToken = 0; |
| RMC.action = SIR_MAC_RMC_RULER_INFORM_SELECTED; |
| |
| status = limSendRMCActionFrame(pMac, |
| SIR_MAC_RMC_MCAST_ADDRESS, |
| &RMC, |
| psessionEntry); |
| |
| if (eSIR_FAILURE == status) |
| { |
| PELOGE(limLog(pMac, LOGE, |
| FL("RMC:__rmcRulerSelectTimerHandler Action frame send failed"));) |
| } |
| |
| return; |
| } |
| |
| static void |
| __limProcessRMCEnableRequest(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) |
| { |
| tSirSetRMCReq *setRmcReq = (tSirSetRMCReq *)pMsgBuf; |
| tpPESession psessionEntry; |
| |
| if (!setRmcReq) |
| { |
| PELOGE(limLog(pMac, LOGE, FL("RMC: Enable:NULL message") );) |
| return; |
| } |
| |
| pMac->rmcContext.rmcEnabled = TRUE; |
| |
| /* |
| * This API relies on a single active IBSS session. |
| */ |
| psessionEntry = limIsIBSSSessionActive(pMac); |
| if (NULL == psessionEntry) |
| { |
| PELOGE(limLog(pMac, LOGE, FL("RMC:Enable RMC request no active IBSS"));) |
| pMac->rmcContext.state = eRMC_RULER_NOT_SELECTED; |
| return; |
| } |
| |
| /* Send RULER_REQ to f/w */ |
| __limPostMsgRulerReq(pMac, eRMC_SUGGEST_RULER_CMD, |
| setRmcReq->mcastTransmitter); |
| |
| pMac->rmcContext.state = eRMC_RULER_ENABLE_REQUESTED; |
| } |
| |
| static void |
| __limProcessRMCDisableRequest(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) |
| { |
| tpPESession psessionEntry; |
| tSirRMCInfo RMC; |
| tSirSetRMCReq *setRmcReq = (tSirSetRMCReq *)pMsgBuf; |
| tSirRetStatus status; |
| v_PVOID_t pvosGCtx; |
| VOS_STATUS vos_status; |
| v_MACADDR_t vosMcastTransmitter; |
| |
| pMac->rmcContext.rmcEnabled = FALSE; |
| |
| /* |
| * This API relies on a single active IBSS session. |
| */ |
| psessionEntry = limIsIBSSSessionActive(pMac); |
| if (NULL == psessionEntry) |
| { |
| PELOGE(limLog(pMac, LOGE, FL("RMC: Disable:No active IBSS"));) |
| return; |
| } |
| |
| if (!setRmcReq) |
| { |
| PELOGE(limLog(pMac, LOGE, FL("RMC: Disable:NULL message") );) |
| return; |
| } |
| |
| /* Cancel pending timer */ |
| tx_timer_deactivate(&pMac->rmcContext.gRmcRulerSelectTimer); |
| |
| vosMcastTransmitter.bytes[0] = psessionEntry->selfMacAddr[0]; |
| vosMcastTransmitter.bytes[1] = psessionEntry->selfMacAddr[1]; |
| vosMcastTransmitter.bytes[2] = psessionEntry->selfMacAddr[2]; |
| vosMcastTransmitter.bytes[3] = psessionEntry->selfMacAddr[3]; |
| vosMcastTransmitter.bytes[4] = psessionEntry->selfMacAddr[4]; |
| vosMcastTransmitter.bytes[5] = psessionEntry->selfMacAddr[5]; |
| |
| pvosGCtx = vos_get_global_context(VOS_MODULE_ID_PE, (v_VOID_t *) pMac); |
| vos_status = WLANTL_DisableRMC(pvosGCtx, &vosMcastTransmitter); |
| |
| if (VOS_STATUS_SUCCESS != vos_status) |
| { |
| PELOGE(limLog(pMac, LOGE, FL("RMC:Disable: TL disable failed"));) |
| } |
| |
| if (pMac->rmcContext.state == eRMC_RULER_ACTIVE) |
| { |
| RMC.dialogToken = 0; |
| RMC.action = SIR_MAC_RMC_RULER_INFORM_CANCELLED; |
| vos_mem_copy(&RMC.mcastRuler, &pMac->rmcContext.ruler, sizeof(tSirMacAddr)); |
| |
| status = limSendRMCActionFrame(pMac, pMac->rmcContext.ruler, |
| &RMC, psessionEntry); |
| if (eSIR_FAILURE == status) |
| { |
| PELOGE(limLog(pMac, LOGE, FL("RMC:Disable: Action frame send failed"));) |
| } |
| |
| pMac->rmcContext.state = eRMC_RULER_NOT_SELECTED; |
| } |
| |
| __limPostMsgUpdateInd(pMac, eRMC_RULER_CANCELLED, eRMC_TRANSMITTER_ROLE, |
| setRmcReq->mcastTransmitter, pMac->rmcContext.ruler); |
| |
| vos_mem_zero(pMac->rmcContext.ruler, sizeof(tSirMacAddr)); |
| |
| } |
| |
| static void |
| __limProcessRMCRulerSelectResponse(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) |
| { |
| tSirRmcRulerSelectInd *pRmcRulerSelectInd; |
| tpPESession psessionEntry; |
| tSirRetStatus status; |
| v_PVOID_t pvosGCtx; |
| VOS_STATUS vos_status; |
| v_MACADDR_t vosMcastTransmitter; |
| tSirRMCInfo RMC; |
| |
| if (NULL == pMsgBuf) |
| { |
| PELOGE(limLog(pMac, LOGE, FL("RMC: Ruler_Select_Resp:NULL message"));) |
| return; |
| } |
| |
| /* |
| * This API relies on a single active IBSS session. |
| */ |
| psessionEntry = limIsIBSSSessionActive(pMac); |
| if (NULL == psessionEntry) |
| { |
| PELOGE(limLog(pMac, LOGE, FL("RMC:Ruler_Select_Resp:No active IBSS"));) |
| pMac->rmcContext.state = eRMC_RULER_NOT_SELECTED; |
| return; |
| } |
| |
| pRmcRulerSelectInd = (tSirRmcRulerSelectInd *)pMsgBuf; |
| |
| if (pMac->rmcContext.state != eRMC_RULER_ENABLE_REQUESTED) |
| { |
| PELOGE(limLog(pMac, LOGE, FL("RMC: Ruler_Select_Resp:Bad state %s"), |
| __limMcastTxStateToString(pMac->rmcContext.state) );) |
| return; |
| } |
| |
| if (pRmcRulerSelectInd->status) |
| { |
| PELOGE(limLog(pMac, LOGE, FL("RMC:Ruler_Select_Resp:FW Status %d"), |
| pRmcRulerSelectInd->status);) |
| pMac->rmcContext.state = eRMC_RULER_NOT_SELECTED; |
| return; |
| } |
| |
| if (!VOS_IS_STATUS_SUCCESS(vos_lock_acquire(&pMac->rmcContext.lkRmcLock))) |
| { |
| limLog(pMac, LOGE, FL("RMC:Ruler_Select_Resp:lock acquire failed")); |
| pMac->rmcContext.state = eRMC_RULER_NOT_SELECTED; |
| return; |
| } |
| |
| vos_mem_copy(&pMac->rmcContext.ruler, &pRmcRulerSelectInd->ruler[0], |
| sizeof(tSirMacAddr)); |
| |
| if (!VOS_IS_STATUS_SUCCESS |
| (vos_lock_release(&pMac->rmcContext.lkRmcLock))) |
| { |
| limLog(pMac, LOGE, FL("RMC: Ruler_Select_Resp: lock release failed")); |
| } |
| |
| RMC.dialogToken = 0; |
| RMC.action = SIR_MAC_RMC_RULER_INFORM_SELECTED; |
| vos_mem_copy(&RMC.mcastRuler, &pRmcRulerSelectInd->ruler[0], |
| sizeof(tSirMacAddr)); |
| |
| PELOG1(limLog(pMac, LOG1, FL("RMC: Ruler_Select :ruler " MAC_ADDRESS_STR), |
| MAC_ADDR_ARRAY(pRmcRulerSelectInd->ruler[0]));) |
| |
| status = limSendRMCActionFrame(pMac, |
| SIR_MAC_RMC_MCAST_ADDRESS, |
| &RMC, |
| psessionEntry); |
| |
| if (eSIR_FAILURE == status) |
| { |
| PELOGE(limLog(pMac, LOGE, |
| FL("RMC: Ruler_Select_Resp: Action send failed"));) |
| } |
| |
| __limPostMsgUpdateInd(pMac, eRMC_RULER_ACCEPTED, eRMC_TRANSMITTER_ROLE, |
| psessionEntry->selfMacAddr, pMac->rmcContext.ruler); |
| |
| vosMcastTransmitter.bytes[0] = psessionEntry->selfMacAddr[0]; |
| vosMcastTransmitter.bytes[1] = psessionEntry->selfMacAddr[1]; |
| vosMcastTransmitter.bytes[2] = psessionEntry->selfMacAddr[2]; |
| vosMcastTransmitter.bytes[3] = psessionEntry->selfMacAddr[3]; |
| vosMcastTransmitter.bytes[4] = psessionEntry->selfMacAddr[4]; |
| vosMcastTransmitter.bytes[5] = psessionEntry->selfMacAddr[5]; |
| |
| /* Enable TL */ |
| pvosGCtx = vos_get_global_context(VOS_MODULE_ID_PE, (v_VOID_t *) pMac); |
| vos_status = WLANTL_EnableRMC(pvosGCtx, &vosMcastTransmitter); |
| |
| pMac->rmcContext.state = eRMC_RULER_ACTIVE; |
| |
| if (tx_timer_activate(&pMac->rmcContext.gRmcRulerSelectTimer)!= TX_SUCCESS) |
| { |
| limLog(pMac, LOGE, |
| FL("Ruler_Select_Resp:Activate RMC Response timer failed")); |
| } |
| } |
| |
| static void |
| __limProcessRMCRulerPickNew(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) |
| { |
| tSirRmcUpdateInd *pRmcUpdateInd; |
| tpPESession psessionEntry; |
| tSirRetStatus status; |
| tSirRMCInfo RMC; |
| v_PVOID_t pvosGCtx; |
| VOS_STATUS vos_status; |
| v_MACADDR_t vosMcastTransmitter; |
| tSirMacAddr zeroMacAddr = { 0, 0, 0, 0, 0, 0 }; |
| |
| if (NULL == pMsgBuf) |
| { |
| PELOGE(limLog(pMac, LOGE, FL("RMC: Ruler_Pick_New:NULL message"));) |
| return; |
| } |
| |
| /* |
| * This API relies on a single active IBSS session. |
| */ |
| psessionEntry = limIsIBSSSessionActive(pMac); |
| if (NULL == psessionEntry) |
| { |
| PELOGE(limLog(pMac, LOGE, FL("RMC: Ruler_Pick_New:No active IBSS"));) |
| return; |
| } |
| |
| pvosGCtx = vos_get_global_context(VOS_MODULE_ID_PE, (v_VOID_t *) pMac); |
| |
| pRmcUpdateInd = (tSirRmcUpdateInd *)pMsgBuf; |
| |
| if (!VOS_IS_STATUS_SUCCESS(vos_lock_acquire(&pMac->rmcContext.lkRmcLock))) |
| { |
| limLog(pMac, LOGE, FL("RMC:Ruler_Pick_New:lock acquire failed")); |
| return; |
| } |
| |
| |
| /* Fill out Action frame parameters */ |
| RMC.dialogToken = 0; |
| |
| if (VOS_FALSE == vos_mem_compare(&zeroMacAddr, |
| &pRmcUpdateInd->mcastRuler, |
| sizeof(tSirMacAddr))) |
| { |
| |
| vos_mem_copy(&RMC.mcastRuler, &pRmcUpdateInd->mcastRuler, |
| sizeof(tSirMacAddr)); |
| |
| RMC.action = SIR_MAC_RMC_RULER_INFORM_CANCELLED; |
| status = limSendRMCActionFrame(pMac, |
| pRmcUpdateInd->mcastRuler, |
| &RMC, psessionEntry); |
| if (eSIR_FAILURE == status) |
| { |
| PELOGE(limLog(pMac, LOGE, |
| FL("RMC:Ruler_Pick_New: Inform_Cancel Action send failed"));) |
| goto done; |
| } |
| |
| vosMcastTransmitter.bytes[0] = psessionEntry->selfMacAddr[0]; |
| vosMcastTransmitter.bytes[1] = psessionEntry->selfMacAddr[1]; |
| vosMcastTransmitter.bytes[2] = psessionEntry->selfMacAddr[2]; |
| vosMcastTransmitter.bytes[3] = psessionEntry->selfMacAddr[3]; |
| vosMcastTransmitter.bytes[4] = psessionEntry->selfMacAddr[4]; |
| vosMcastTransmitter.bytes[5] = psessionEntry->selfMacAddr[5]; |
| |
| vos_status = WLANTL_DisableRMC(pvosGCtx, &vosMcastTransmitter); |
| |
| if (VOS_STATUS_SUCCESS != vos_status) |
| { |
| PELOGE(limLog(pMac, LOGE, |
| FL("RMC:Ruler_Pick_New: TL disable failed"));) |
| } |
| } |
| |
| vos_mem_copy(pMac->rmcContext.ruler, pRmcUpdateInd->ruler[0], |
| sizeof(tSirMacAddr)); |
| |
| pMac->rmcContext.state = eRMC_RULER_NOT_SELECTED; |
| |
| if (VOS_TRUE == vos_mem_compare(&zeroMacAddr, |
| pMac->rmcContext.ruler, |
| sizeof(tSirMacAddr))) |
| { |
| PELOGE(limLog(pMac, LOGE, |
| FL("RMC:Ruler_Pick_New: No candidate rulers available"));) |
| goto done; |
| } |
| |
| |
| RMC.action = SIR_MAC_RMC_RULER_INFORM_SELECTED; |
| vos_mem_copy(&RMC.mcastRuler, &pMac->rmcContext.ruler, |
| sizeof(tSirMacAddr)); |
| status = limSendRMCActionFrame(pMac, SIR_MAC_RMC_MCAST_ADDRESS, |
| &RMC, psessionEntry); |
| if (eSIR_FAILURE == status) |
| { |
| PELOGE(limLog(pMac, LOGE, |
| FL("RMC:Ruler_Pick_New: Inform_Selected Action send failed"));) |
| goto done; |
| } |
| |
| __limPostMsgUpdateInd(pMac, eRMC_RULER_ACCEPTED, eRMC_TRANSMITTER_ROLE, |
| psessionEntry->selfMacAddr, pMac->rmcContext.ruler); |
| |
| vosMcastTransmitter.bytes[0] = psessionEntry->selfMacAddr[0]; |
| vosMcastTransmitter.bytes[1] = psessionEntry->selfMacAddr[1]; |
| vosMcastTransmitter.bytes[2] = psessionEntry->selfMacAddr[2]; |
| vosMcastTransmitter.bytes[3] = psessionEntry->selfMacAddr[3]; |
| vosMcastTransmitter.bytes[4] = psessionEntry->selfMacAddr[4]; |
| vosMcastTransmitter.bytes[5] = psessionEntry->selfMacAddr[5]; |
| |
| /* Enable TL */ |
| vos_status = WLANTL_EnableRMC(pvosGCtx, &vosMcastTransmitter); |
| |
| if (VOS_STATUS_SUCCESS != vos_status) |
| { |
| PELOGE(limLog(pMac, LOGE, |
| FL("RMC:Ruler_Pick_New: TL enable failed"));) |
| goto done; |
| } |
| |
| pMac->rmcContext.state = eRMC_RULER_ACTIVE; |
| |
| if (tx_timer_activate(&pMac->rmcContext.gRmcRulerSelectTimer)!= TX_SUCCESS) |
| { |
| limLog(pMac, LOGE, |
| FL("Ruler_Pick_New:Activate RMC Response timer failed")); |
| } |
| |
| done: |
| if (!VOS_IS_STATUS_SUCCESS(vos_lock_release(&pMac->rmcContext.lkRmcLock))) |
| { |
| limLog(pMac, LOGE, |
| FL("RMC: Ruler_Pick_New: lock release failed")); |
| } |
| } |
| |
| static void |
| __limProcessRMCRulerInformSelected(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) |
| { |
| tpSirMacMgmtHdr pHdr; |
| tANI_U8 *pFrameData; |
| tANI_U32 frameLen; |
| tLimRmcGroupContext *entry; |
| tpPESession psessionEntry; |
| tSirRetStatus status; |
| |
| if (!pMsgBuf) |
| { |
| PELOGE(limLog(pMac, LOGE, FL("RMC: Ruler_Inform:NULL msg"));) |
| return; |
| } |
| |
| /* |
| * This API relies on a single active IBSS session. |
| */ |
| psessionEntry = limIsIBSSSessionActive(pMac); |
| if (NULL == psessionEntry) |
| { |
| PELOGE(limLog(pMac, LOGE, FL("RMC:Become_Ruler_Resp:No active IBSS"));) |
| return; |
| } |
| |
| /* |
| * Get the frame header |
| */ |
| pHdr = WDA_GET_RX_MAC_HEADER((tANI_U8 *)pMsgBuf); |
| |
| frameLen = WDA_GET_RX_PAYLOAD_LEN((tANI_U8 *)pMsgBuf); |
| if (frameLen < sizeof(tSirMacIbssExtNetworkFrameHdr)) |
| { |
| PELOGE(limLog(pMac, LOGE, |
| FL("RMC: Ruler_Inform:Bad length %d "), frameLen);) |
| return; |
| } |
| |
| pFrameData = WDA_GET_RX_MPDU_DATA((tANI_U8 *)pMsgBuf) + |
| sizeof(tSirMacIbssExtNetworkFrameHdr); |
| |
| if (!pFrameData) |
| { |
| PELOGE(limLog(pMac, LOGE, FL("RMC: Ruler_Inform:NULL data"));) |
| return; |
| } |
| |
| if (!VOS_IS_STATUS_SUCCESS(vos_lock_acquire(&pMac->rmcContext.lkRmcLock))) |
| { |
| limLog(pMac, LOGE, FL("RMC:Become_Ruler_Resp:lock acquire failed")); |
| return; |
| } |
| |
| /* |
| * Check if this transmitter exists in our database. |
| */ |
| entry = __rmcGroupLookupHashEntry(pMac, pHdr->sa); |
| |
| if (VOS_FALSE == vos_mem_compare(pFrameData, psessionEntry->selfMacAddr, |
| sizeof(tSirMacAddr))) |
| { |
| if (entry) |
| { |
| PELOG1(limLog(pMac, LOG1, |
| FL("RMC: Ruler_Inform: Ruler Cancelled"));) |
| |
| __limPostMsgUpdateInd(pMac, eRMC_RULER_CANCELLED, |
| eRMC_RULER_ROLE, pHdr->sa, psessionEntry->selfMacAddr); |
| |
| /* |
| * Delete hash entry for this Group address. |
| */ |
| status = __rmcGroupDeleteHashEntry(pMac, pHdr->sa); |
| if (eSIR_FAILURE == status) |
| { |
| PELOGE(limLog(pMac, LOGE, |
| FL("RMC: Ruler_Inform:hash delete failed"));) |
| } |
| } |
| } |
| else |
| { |
| if (NULL == entry) |
| { |
| /* Add the transmitter address to the hash */ |
| entry = __rmcGroupInsertHashEntry(pMac, pHdr->sa); |
| if (entry) |
| { |
| if (entry->isRuler != eRMC_RULER_PENDING) |
| { |
| __limPostMsgRulerReq(pMac, eRMC_BECOME_RULER_CMD, |
| pHdr->sa); |
| entry->isRuler = eRMC_RULER_PENDING; |
| } |
| } |
| else |
| { |
| PELOGE(limLog(pMac, LOGE, |
| FL("RMC: Ruler_Inform:Hash insert failed"));) |
| } |
| |
| } |
| } |
| |
| if (!VOS_IS_STATUS_SUCCESS(vos_lock_release(&pMac->rmcContext.lkRmcLock))) |
| { |
| limLog(pMac, LOGE, |
| FL("RMC: Ruler_Inform: lock release failed")); |
| } |
| |
| } |
| |
| static void |
| __limProcessRMCBecomeRulerResp(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) |
| { |
| tSirRmcBecomeRulerInd *pRmcBecomeRulerInd; |
| tLimRmcGroupContext *entry; |
| tSirRetStatus status = eSIR_SUCCESS; |
| |
| if (NULL == pMsgBuf) |
| { |
| PELOGE(limLog(pMac, LOGE, FL("RMC: Become_Ruler_Resp:NULL message"));) |
| return; |
| } |
| |
| pRmcBecomeRulerInd = (tSirRmcBecomeRulerInd *)pMsgBuf; |
| |
| if (!VOS_IS_STATUS_SUCCESS(vos_lock_acquire(&pMac->rmcContext.lkRmcLock))) |
| { |
| limLog(pMac, LOGE, FL("RMC:Become_Ruler_Resp:lock acquire failed")); |
| return; |
| } |
| |
| /* |
| * Find the entry for this Group Address. |
| */ |
| entry = __rmcGroupLookupHashEntry(pMac, |
| pRmcBecomeRulerInd->mcastTransmitter); |
| if (NULL == entry) |
| { |
| PELOGE(limLog(pMac, LOGE, FL("RMC: Become_Ruler_Resp: No entry"));) |
| goto done; |
| } |
| |
| if (pRmcBecomeRulerInd->status) |
| { |
| PELOGE(limLog(pMac, LOGE, FL("RMC:Become_Ruler_Resp:FW Status %d"), |
| pRmcBecomeRulerInd->status);) |
| status = eSIR_FAILURE; |
| goto done; |
| } |
| |
| if (entry->isRuler != eRMC_RULER_PENDING) |
| { |
| PELOGE(limLog(pMac, LOGE, FL("RMC: Become_Ruler_Resp:Bad state: %s"), |
| __limRulerStateToString(entry->isRuler) );) |
| status = eSIR_FAILURE; |
| goto done; |
| } |
| |
| entry->isRuler = eRMC_IS_A_RULER; |
| |
| done: |
| if (eSIR_FAILURE == status) |
| { |
| status = __rmcGroupDeleteHashEntry(pMac, |
| pRmcBecomeRulerInd->mcastTransmitter); |
| if (eSIR_FAILURE == status) |
| { |
| PELOGE(limLog(pMac, LOGE, |
| FL("RMC: Become_Ruler_Resp:hash delete failed"));) |
| } |
| } |
| |
| if (!VOS_IS_STATUS_SUCCESS(vos_lock_release(&pMac->rmcContext.lkRmcLock))) |
| { |
| limLog(pMac, LOGE, |
| FL("RMC: Become_Ruler_Resp: lock release failed")); |
| } |
| |
| return; |
| } |
| |
| static void |
| __limProcessRMCRulerInformCancelled(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) |
| { |
| tpSirMacMgmtHdr pHdr; |
| tANI_U8 *pFrameData; |
| tANI_U32 frameLen; |
| tSirRetStatus status; |
| tLimRmcGroupContext *entry; |
| tpPESession psessionEntry; |
| |
| if (!pMsgBuf) |
| { |
| PELOGE(limLog(pMac, LOGE, FL("RMC: Ruler_Inform_Cancel:NULL msg"));) |
| return; |
| } |
| |
| /* |
| * This API relies on a single active IBSS session. |
| */ |
| psessionEntry = limIsIBSSSessionActive(pMac); |
| if (NULL == psessionEntry) |
| { |
| PELOGE(limLog(pMac, LOGE, |
| FL("RMC:Ruler_Inform_Cancel:No active IBSS"));) |
| return; |
| } |
| |
| pHdr = WDA_GET_RX_MAC_HEADER((tANI_U8 *)pMsgBuf); |
| |
| frameLen = WDA_GET_RX_PAYLOAD_LEN((tANI_U8 *)pMsgBuf); |
| if (frameLen < sizeof(tSirMacIbssExtNetworkFrameHdr)) |
| { |
| PELOGE(limLog(pMac, LOGE, |
| FL("RMC: Ruler_Inform:Bad length %d "), frameLen);) |
| return; |
| } |
| |
| pFrameData = WDA_GET_RX_MPDU_DATA((tANI_U8 *)pMsgBuf) + |
| sizeof(tSirMacIbssExtNetworkFrameHdr); |
| |
| if (!pFrameData) |
| { |
| PELOGE(limLog(pMac, LOGE, FL("RMC: Ruler_Inform_Cancel:NULL data"));) |
| return; |
| } |
| |
| if (!VOS_IS_STATUS_SUCCESS(vos_lock_acquire(&pMac->rmcContext.lkRmcLock))) |
| { |
| limLog(pMac, LOGE, FL("RMC:Ruler_Inform_Cancel lock acquire failed")); |
| return; |
| } |
| |
| /* |
| * Find the entry for this Group Address. |
| */ |
| entry = __rmcGroupLookupHashEntry(pMac, pHdr->sa); |
| if (NULL == entry) |
| { |
| PELOGE(limLog(pMac, LOGE, FL("RMC: Ruler_Inform_Cancel: No entry"));) |
| goto done; |
| } |
| |
| __limPostMsgUpdateInd(pMac, eRMC_RULER_CANCELLED, |
| eRMC_RULER_ROLE, pHdr->sa, psessionEntry->selfMacAddr); |
| |
| /* |
| * Delete hash entry for this Group address. |
| */ |
| status = __rmcGroupDeleteHashEntry(pMac, pHdr->sa); |
| if (eSIR_FAILURE == status) |
| { |
| PELOGE(limLog(pMac, LOGE, |
| FL("RMC: Ruler_Inform_Cancel:hash delete failed"));) |
| } |
| |
| done: |
| if (!VOS_IS_STATUS_SUCCESS(vos_lock_release(&pMac->rmcContext.lkRmcLock))) |
| { |
| limLog(pMac, LOGE, |
| FL("RMC: Ruler_Inform_Cancel: lock release failed")); |
| } |
| return; |
| } |
| |
| void |
| limProcessRMCMessages(tpAniSirGlobal pMac, eRmcMessageType msgType, |
| tANI_U32 *pMsgBuf) |
| { |
| |
| if (pMsgBuf == NULL) |
| { |
| PELOGE(limLog(pMac, LOGE, FL("RMC: Buffer is Pointing to NULL"));) |
| return; |
| } |
| |
| limLog(pMac, LOG1, FL("RMC: limProcessRMCMessages: %s"), |
| __limRulerMessageToString(msgType)); |
| |
| switch (msgType) |
| { |
| case eLIM_RMC_ENABLE_REQ: |
| __limProcessRMCEnableRequest(pMac, pMsgBuf); |
| break; |
| |
| case eLIM_RMC_DISABLE_REQ: |
| __limProcessRMCDisableRequest(pMac, pMsgBuf); |
| break; |
| |
| case eLIM_RMC_RULER_SELECT_RESP: |
| __limProcessRMCRulerSelectResponse(pMac, pMsgBuf); |
| break; |
| |
| case eLIM_RMC_RULER_PICK_NEW: |
| __limProcessRMCRulerPickNew(pMac, pMsgBuf); |
| break; |
| |
| case eLIM_RMC_OTA_RULER_INFORM_SELECTED: |
| __limProcessRMCRulerInformSelected(pMac, pMsgBuf); |
| break; |
| |
| case eLIM_RMC_BECOME_RULER_RESP: |
| __limProcessRMCBecomeRulerResp(pMac, pMsgBuf); |
| break; |
| |
| case eLIM_RMC_OTA_RULER_INFORM_CANCELLED: |
| __limProcessRMCRulerInformCancelled(pMac, pMsgBuf); |
| break; |
| |
| |
| default: |
| break; |
| } // switch (msgType) |
| return; |
| } /*** end limProcessRMCMessages() ***/ |
| |
| void |
| limRmcInit(tpAniSirGlobal pMac) |
| { |
| tANI_U32 cfgValue; |
| |
| if (wlan_cfgGetInt(pMac, WNI_CFG_RMC_ACTION_PERIOD_FREQUENCY, |
| &cfgValue) != eSIR_SUCCESS) |
| { |
| /** |
| * Could not get Action Period Frequency value |
| * from CFG. Log error. |
| */ |
| limLog(pMac, LOGP, FL("could not retrieve ActionPeriodFrequency")); |
| } |
| |
| cfgValue = SYS_MS_TO_TICKS(cfgValue); |
| |
| vos_mem_zero(&pMac->rmcContext, sizeof(pMac->rmcContext)); |
| |
| if (!VOS_IS_STATUS_SUCCESS(vos_lock_init(&pMac->rmcContext.lkRmcLock))) |
| { |
| PELOGE(limLog(pMac, LOGE, FL("RMC lock init failed!"));) |
| } |
| |
| if (tx_timer_create(&pMac->rmcContext.gRmcRulerSelectTimer, |
| "RMC RSP TIMEOUT", |
| __rmcRulerSelectTimerHandler, |
| 0 /* param */, |
| cfgValue, 0, |
| TX_NO_ACTIVATE) != TX_SUCCESS) |
| { |
| limLog(pMac, LOGE, FL("could not create RMC response timer")); |
| } |
| |
| pMac->rmcContext.rmcTimerValInTicks = cfgValue; |
| } |
| |
| void |
| limRmcCleanup(tpAniSirGlobal pMac) |
| { |
| limRmcIbssDelete(pMac); |
| |
| if (!VOS_IS_STATUS_SUCCESS(vos_lock_destroy(&pMac->rmcContext.lkRmcLock))) |
| { |
| PELOGE(limLog(pMac, LOGE, FL("RMC lock destroy failed!"));) |
| } |
| |
| tx_timer_delete(&pMac->rmcContext.gRmcRulerSelectTimer); |
| } |
| |
| void |
| limRmcTransmitterDelete(tpAniSirGlobal pMac, tSirMacAddr transmitter) |
| { |
| if (!VOS_IS_STATUS_SUCCESS(vos_lock_acquire(&pMac->rmcContext.lkRmcLock))) |
| { |
| limLog(pMac, LOGE, |
| FL("RMC: limRMCTransmitterDelete lock acquire failed")); |
| return; |
| } |
| |
| __rmcGroupDeleteHashEntry(pMac, transmitter); |
| |
| if (!VOS_IS_STATUS_SUCCESS(vos_lock_release(&pMac->rmcContext.lkRmcLock))) |
| { |
| limLog(pMac, LOGE, |
| FL("RMC: limRMCTransmitterDelete lock release failed")); |
| } |
| |
| limLog(pMac, LOG1, FL("RMC: limRmcTransmitterDelete complete")); |
| } |
| |
| void |
| limRmcIbssDelete(tpAniSirGlobal pMac) |
| { |
| tpPESession psessionEntry; |
| tSirMacAddr zeroMacAddr = { 0, 0, 0, 0, 0, 0 }; |
| |
| /* |
| * This API relies on a single active IBSS session. |
| */ |
| psessionEntry = limIsIBSSSessionActive(pMac); |
| if (NULL == psessionEntry) |
| { |
| PELOGE(limLog(pMac, LOGE, FL("RMC: limRmcIbssDelete:No active IBSS"));) |
| return; |
| } |
| |
| if (VOS_FALSE == vos_mem_compare(&zeroMacAddr, |
| &pMac->rmcContext.ruler, sizeof(tSirMacAddr))) |
| { |
| __limPostMsgUpdateInd(pMac, eRMC_RULER_CANCELLED, |
| eRMC_TRANSMITTER_ROLE, psessionEntry->selfMacAddr, |
| pMac->rmcContext.ruler); |
| } |
| |
| if (!VOS_IS_STATUS_SUCCESS(vos_lock_acquire(&pMac->rmcContext.lkRmcLock))) |
| { |
| limLog(pMac, LOGE, |
| FL("RMC: limRmcIbssDelete lock acquire failed")); |
| return; |
| } |
| |
| /* Cancel pending timer */ |
| tx_timer_deactivate(&pMac->rmcContext.gRmcRulerSelectTimer); |
| |
| /* Delete all entries from Ruler database. */ |
| __rmcGroupDeleteAllEntries(pMac); |
| |
| if (!VOS_IS_STATUS_SUCCESS(vos_lock_release(&pMac->rmcContext.lkRmcLock))) |
| { |
| limLog(pMac, LOGE, |
| FL("RMC: limRmcIbssDelete lock release failed")); |
| } |
| |
| limLog(pMac, LOG1, FL("RMC: limRmcIbssDelete complete")); |
| } |
| |
| void |
| limRmcDumpStatus(tpAniSirGlobal pMac) |
| { |
| tLimRmcGroupContext *entry; |
| int index, count; |
| |
| if (!VOS_IS_STATUS_SUCCESS(vos_lock_acquire(&pMac->rmcContext.lkRmcLock))) |
| { |
| limLog(pMac, LOGE, |
| FL("RMC: limRmcDumpStatus lock acquire failed")); |
| return; |
| } |
| |
| |
| limLog(pMac, LOGE, FL(" ----- RMC Transmitter Information ----- \n")); |
| limLog(pMac, LOGE, |
| FL(" Ruler Address | RMC State \n")); |
| |
| if (pMac->rmcContext.state != eRMC_RULER_NOT_SELECTED) |
| { |
| limLog(pMac,LOGE, FL( MAC_ADDRESS_STR " | %s\n"), |
| MAC_ADDR_ARRAY(pMac->rmcContext.ruler), |
| __limMcastTxStateToString(pMac->rmcContext.state)); |
| } |
| |
| limLog( pMac,LOGE, FL(" ----- RMC Ruler Information ----- \n")); |
| limLog( pMac,LOGE, FL(" Transmitter Address\n")); |
| |
| count = 0; |
| for (index = 0; index < RMC_MCAST_GROUPS_HASH_SIZE; index++) |
| { |
| entry = pMac->rmcContext.rmcGroupRxHashTable[index]; |
| |
| while (entry) |
| { |
| count++; |
| limLog( pMac,LOGE, FL("%d. " MAC_ADDRESS_STR " \n"), |
| count, MAC_ADDR_ARRAY(entry->transmitter)); |
| entry = entry->next; |
| } |
| } |
| |
| if (!VOS_IS_STATUS_SUCCESS(vos_lock_release(&pMac->rmcContext.lkRmcLock))) |
| { |
| limLog(pMac, LOGE, |
| FL("RMC: limRmcDumpStatus lock release failed")); |
| } |
| |
| return; |
| |
| } |
| |
| VOS_STATUS |
| limRmcTriggerRulerSelection(tpAniSirGlobal pMac, tSirMacAddr macAddr) |
| { |
| if ((TRUE == pMac->rmcContext.rmcEnabled) && |
| (eRMC_RULER_NOT_SELECTED == pMac->rmcContext.state)) |
| { |
| limLog(pMac, LOG1, |
| FL("Ruler selection trigerred in FW")); |
| |
| __limPostMsgRulerReq(pMac, eRMC_SUGGEST_RULER_CMD, macAddr); |
| |
| pMac->rmcContext.state = eRMC_RULER_ENABLE_REQUESTED; |
| |
| return VOS_STATUS_SUCCESS; |
| } |
| else |
| { |
| limLog(pMac, LOG1, |
| FL("Could not trigger ruler selection: RMC state %d rmcEnabled %d"), |
| pMac->rmcContext.state, pMac->rmcContext.rmcEnabled); |
| |
| return VOS_STATUS_E_FAILURE; |
| } |
| } |
| |
| #endif /* WLAN_FEATURE_RMC */ |