/*---------------------------------------------------------------------------- @brief TM Level Change handler Received Tm Level changed notification @param dev : Device context changedTmLevel : Changed new TM level @return ----------------------------------------------------------------------------*/ void hddDevTmLevelChangedHandler(struct device *dev, int changedTmLevel) { hdd_context_t *pHddCtx = NULL; WLAN_TmLevelEnumType newTmLevel = changedTmLevel; hdd_adapter_t *staAdapater; pHddCtx = (hdd_context_t*)wcnss_wlan_get_drvdata(dev); if((pHddCtx->tmInfo.currentTmLevel == newTmLevel) || (!pHddCtx->cfg_ini->thermalMitigationEnable)) { VOS_TRACE(VOS_MODULE_ID_HDD,VOS_TRACE_LEVEL_WARN, "%s: TM Not enabled %d or Level does not changed %d", __func__, pHddCtx->cfg_ini->thermalMitigationEnable, newTmLevel); /* TM Level does not changed, * Or feature does not enabled * do nothing */ return; } sme_SetTmLevel(pHddCtx->hHal, changedTmLevel, 0); if(mutex_lock_interruptible(&pHddCtx->tmInfo.tmOperationLock)) { VOS_TRACE(VOS_MODULE_ID_HDD,VOS_TRACE_LEVEL_ERROR, "%s: Aquire lock fail", __func__); return; } pHddCtx->tmInfo.currentTmLevel = changedTmLevel; pHddCtx->tmInfo.txFrameCount = 0; vos_mem_copy(&pHddCtx->tmInfo.tmAction, &thermalMigrationAction[newTmLevel], sizeof(hdd_tmLevelAction_t)); if(pHddCtx->tmInfo.tmAction.enterImps) { staAdapater = hdd_get_adapter(pHddCtx, WLAN_HDD_INFRA_STATION); if(staAdapater) { if(hdd_connIsConnected(WLAN_HDD_GET_STATION_CTX_PTR(staAdapater))) { sme_RoamDisconnect(pHddCtx->hHal, staAdapater->sessionId, eCSR_DISCONNECT_REASON_UNSPECIFIED); } } } mutex_unlock(&pHddCtx->tmInfo.tmOperationLock); return; }
/** * hdd_state_info_dump() - prints state information of hdd layer */ static void hdd_state_info_dump(void) { v_CONTEXT_t vos_ctx_ptr; hdd_context_t *hdd_ctx_ptr = NULL; hdd_adapter_list_node_t *adapter_node = NULL, *next = NULL; VOS_STATUS status; hdd_station_ctx_t *hdd_sta_ctx = NULL; hdd_adapter_t *adapter =NULL; /* get the global voss context */ vos_ctx_ptr = vos_get_global_context(VOS_MODULE_ID_VOSS, NULL); if (NULL != vos_ctx_ptr) { hdd_ctx_ptr = vos_get_context(VOS_MODULE_ID_HDD, vos_ctx_ptr); } else { VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, "%s: Invalid Global VOSS Context", __func__); VOS_ASSERT(0); return; } hddLog(LOG1, FL("mScanPending %d isWlanSuspended %d disable_dfs_flag %d"), hdd_ctx_ptr->scan_info.mScanPending, hdd_ctx_ptr->isWlanSuspended, hdd_ctx_ptr->disable_dfs_flag); status = hdd_get_front_adapter(hdd_ctx_ptr, &adapter_node); while (NULL != adapter_node && VOS_STATUS_SUCCESS == status) { adapter = adapter_node->pAdapter; if (adapter->dev) hddLog(LOG1, FL("device name: %s"), adapter->dev->name); switch (adapter->device_mode) { case WLAN_HDD_INFRA_STATION: case WLAN_HDD_P2P_CLIENT: hdd_sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(adapter); hddLog(LOG1, FL("connState: %d device_mode: %d"), hdd_sta_ctx->conn_info.connState, adapter->device_mode); break; default: break; } status = hdd_get_next_adapter(hdd_ctx_ptr, adapter_node, &next); adapter_node = next; } }
static int wlan_hdd_cfg80211_set_auth_type(hdd_adapter_t *pAdapter, enum nl80211_auth_type auth_type) { hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter); hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter); ENTER(); /*set authentication type*/ switch (auth_type) { case NL80211_AUTHTYPE_OPEN_SYSTEM: case NL80211_AUTHTYPE_AUTOMATIC: hddLog(VOS_TRACE_LEVEL_INFO, "%s: set authentication type to OPEN", __func__); pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_OPEN_SYSTEM; break; case NL80211_AUTHTYPE_SHARED_KEY: hddLog(VOS_TRACE_LEVEL_INFO, "%s: set authentication type to SHARED", __func__); pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_SHARED_KEY; break; #ifdef FEATURE_WLAN_CCX case NL80211_AUTHTYPE_NETWORK_EAP: hddLog(VOS_TRACE_LEVEL_INFO, "%s: set authentication type to CCKM WPA", __func__); pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_CCKM_WPA;//eCSR_AUTH_TYPE_CCKM_RSN needs to be handled as well if required. break; #endif default: hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Unsupported authentication type %d", __func__, auth_type); pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_UNKNOWN; return -EINVAL; } pWextState->roamProfile.AuthType.authType[0] = pHddStaCtx->conn_info.authType; return 0; }
/**============================================================================ @brief hdd_tx_low_resource_cbk() - Callback function invoked in the case where VOS packets are not available at the time of the call to get packets. This callback function is invoked by VOS when packets are available. @param pVosPacket : [in] pointer to VOS packet @param userData : [in] opaque user data that was passed initially @return : VOS_STATUS_E_FAILURE if any errors encountered, : VOS_STATUS_SUCCESS otherwise =============================================================================*/ VOS_STATUS hdd_tx_low_resource_cbk( vos_pkt_t *pVosPacket, v_VOID_t *userData ) { VOS_STATUS status; v_SINT_t i = 0; v_SIZE_t size = 0; hdd_adapter_t* pAdapter = (hdd_adapter_t *)userData; if(pAdapter == NULL) { VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,"%s: HDD adapter context is Null", __FUNCTION__); return VOS_STATUS_E_FAILURE; } //Return the packet to VOS. We just needed to know that VOS is out of low resource //situation. Here we will only signal TL that there is a pending data for a STA. //VOS packet will be requested (if needed) when TL comes back to fetch data. vos_pkt_return_packet( pVosPacket ); pAdapter->isVosOutOfResource = VOS_FALSE; //Indicate to TL that there is pending data if a queue is non empty for( i=NUM_TX_QUEUES-1; i>=0; --i ) { size = 0; hdd_list_size( &pAdapter->wmm_tx_queue[i], &size ); if ( size > 0 ) { status = WLANTL_STAPktPending( (WLAN_HDD_GET_CTX(pAdapter))->pvosContext, (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.staId [0], (WLANTL_ACEnumType)i ); if( !VOS_IS_STATUS_SUCCESS( status ) ) { VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,"%s: Failure in indicating pkt to TL for ac=%d", __FUNCTION__,i); } } } return VOS_STATUS_SUCCESS; }
static ssize_t wcnss_patterngen_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos) { hdd_adapter_t *pAdapter = (hdd_adapter_t *)file->private_data; hdd_context_t *pHddCtx; tSirAddPeriodicTxPtrn *addPeriodicTxPtrnParams; tSirDelPeriodicTxPtrn *delPeriodicTxPtrnParams; char *cmd, *sptr, *token; v_U8_t pattern_idx = 0; v_U8_t pattern_duration = 0; char *pattern_buf; v_U16_t pattern_len = 0; v_U16_t i = 0; if ((NULL == pAdapter) || (WLAN_HDD_ADAPTER_MAGIC != pAdapter->magic)) { VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, "%s: Invalid adapter or adapter has invalid magic.", __func__); return -EINVAL; } pHddCtx = WLAN_HDD_GET_CTX(pAdapter); if (!sme_IsFeatureSupportedByFW(WLAN_PERIODIC_TX_PTRN)) { VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, "%s: Periodic Tx Pattern Offload feature is not supported " "in firmware!", __func__); return -EINVAL; } if (count < MAX_USER_COMMAND_SIZE_FRAME) cmd = vos_mem_malloc(count + 1); else { VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, "%s: Command length is larger than d% bytes.", __func__, MAX_USER_COMMAND_SIZE_FRAME); return -EINVAL; } if (!cmd) { VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, "%s: Memory allocation for cmd failed!", __func__); return -EFAULT; } if (copy_from_user(cmd, buf, count)) { vos_mem_free(cmd); return -EFAULT; } cmd[count] = '\0'; sptr = cmd; token = strsep(&sptr, " "); if (!token) goto failure; if (kstrtou8(token, 0, &pattern_idx)) goto failure; if (pattern_idx > (MAXNUM_PERIODIC_TX_PTRNS - 1)) { VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, "%s: Pattern index %d is not in the range (0 ~ %d).", __func__, pattern_idx, MAXNUM_PERIODIC_TX_PTRNS - 1); goto failure; } token = strsep(&sptr, " "); if (!token) goto failure; if (kstrtou8(token, 0, &pattern_duration)) goto failure; if (!pattern_duration) { delPeriodicTxPtrnParams = vos_mem_malloc(sizeof(tSirDelPeriodicTxPtrn)); if (!delPeriodicTxPtrnParams) { VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, "%s: Memory allocation for delPeriodicTxPtrnParams " "failed!", __func__); vos_mem_free(cmd); return -EFAULT; } delPeriodicTxPtrnParams->ucPatternIdBitmap = 1 << pattern_idx; vos_mem_copy(delPeriodicTxPtrnParams->macAddress, pAdapter->macAddressCurrent.bytes, 6); if (eHAL_STATUS_SUCCESS != sme_DelPeriodicTxPtrn(pHddCtx->hHal, delPeriodicTxPtrnParams)) { VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, "%s: sme_DelPeriodicTxPtrn() failed!", __func__); vos_mem_free(delPeriodicTxPtrnParams); goto failure; } vos_mem_free(delPeriodicTxPtrnParams); vos_mem_free(cmd); return count; } if (!hdd_connIsConnected(WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))) { VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, "%s: Not in Connected state!", __func__); goto failure; } token = strsep(&sptr, " "); if (!token) goto failure; pattern_buf = token; pattern_buf[strlen(pattern_buf) - 1] = '\0'; pattern_len = strlen(pattern_buf); if (pattern_len % 2) { VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, "%s: Malformed pattern!", __func__); goto failure; } else pattern_len >>= 1; if (pattern_len < 14 || pattern_len > PERIODIC_TX_PTRN_MAX_SIZE) { VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, "%s: Not an 802.3 frame!", __func__); goto failure; } addPeriodicTxPtrnParams = vos_mem_malloc(sizeof(tSirAddPeriodicTxPtrn)); if (!addPeriodicTxPtrnParams) { VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, "%s: Memory allocation for addPeriodicTxPtrnParams " "failed!", __func__); vos_mem_free(cmd); return -EFAULT; } addPeriodicTxPtrnParams->ucPtrnId = pattern_idx; addPeriodicTxPtrnParams->usPtrnIntervalMs = pattern_duration * 500; addPeriodicTxPtrnParams->ucPtrnSize = pattern_len; vos_mem_copy(addPeriodicTxPtrnParams->macAddress, pAdapter->macAddressCurrent.bytes, 6); for(i = 0; i < addPeriodicTxPtrnParams->ucPtrnSize; i++) { addPeriodicTxPtrnParams->ucPattern[i] = (hdd_parse_hex(pattern_buf[0]) << 4) + hdd_parse_hex(pattern_buf[1]); pattern_buf += 2; } if (eHAL_STATUS_SUCCESS != sme_AddPeriodicTxPtrn(pHddCtx->hHal, addPeriodicTxPtrnParams)) { VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, "%s: sme_AddPeriodicTxPtrn() failed!", __func__); vos_mem_free(addPeriodicTxPtrnParams); goto failure; } vos_mem_free(addPeriodicTxPtrnParams); vos_mem_free(cmd); return count; failure: vos_mem_free(cmd); return -EINVAL; }
/**============================================================================ @brief hdd_tx_fetch_packet_cbk() - Callback function invoked by TL to fetch a packet for transmission. @param vosContext : [in] pointer to VOS context @param staId : [in] Station for which TL is requesting a pkt @param ac : [in] access category requested by TL @param pVosPacket : [out] pointer to VOS packet packet pointer @param pPktMetaInfo : [out] pointer to meta info for the pkt @return : VOS_STATUS_E_EMPTY if no packets to transmit : VOS_STATUS_E_FAILURE if any errors encountered : VOS_STATUS_SUCCESS otherwise ===========================================================================*/ VOS_STATUS hdd_tx_fetch_packet_cbk( v_VOID_t *vosContext, v_U8_t *pStaId, WLANTL_ACEnumType ac, vos_pkt_t **ppVosPacket, WLANTL_MetaInfoType *pPktMetaInfo ) { VOS_STATUS status = VOS_STATUS_E_FAILURE; hdd_adapter_t *pAdapter = NULL; hdd_context_t *pHddCtx = NULL; hdd_list_node_t *anchor = NULL; skb_list_node_t *pktNode = NULL; struct sk_buff *skb = NULL; vos_pkt_t *pVosPacket = NULL; v_MACADDR_t* pDestMacAddress = NULL; v_TIME_t timestamp; WLANTL_ACEnumType newAc; v_SIZE_t size = 0; tANI_U8 acAdmitted, i; //Sanity check on inputs if ( ( NULL == vosContext ) || ( NULL == pStaId ) || ( NULL == ppVosPacket ) || ( NULL == pPktMetaInfo ) ) { VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,"%s: Null Params being passed", __FUNCTION__); return VOS_STATUS_E_FAILURE; } //Get the HDD context. pHddCtx = (hdd_context_t *)vos_get_context( VOS_MODULE_ID_HDD, vosContext ); if(pHddCtx == NULL) { VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,"%s: HDD adapter context is Null", __FUNCTION__); return VOS_STATUS_E_FAILURE; } pAdapter = pHddCtx->sta_to_adapter[*pStaId]; if( NULL == pAdapter ) { VOS_ASSERT(0); return VOS_STATUS_E_FAILURE; } ++pAdapter->hdd_stats.hddTxRxStats.txFetched; *ppVosPacket = NULL; //Make sure the AC being asked for is sane if( ac >= WLANTL_MAX_AC || ac < 0) { VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,"%s: Invalid AC %d passed by TL", __FUNCTION__, ac); return VOS_STATUS_E_FAILURE; } ++pAdapter->hdd_stats.hddTxRxStats.txFetchedAC[ac]; #ifdef HDD_WMM_DEBUG VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,"%s: AC %d passed by TL", __FUNCTION__, ac); #endif // HDD_WMM_DEBUG // We find an AC with packets // or we determine we have no more packets to send // HDD is not allowed to change AC. // has this AC been admitted? or // To allow EAPOL packets when not authenticated if (unlikely((0==pAdapter->hddWmmStatus.wmmAcStatus[ac].wmmAcAccessAllowed) && (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.uIsAuthenticated)) { ++pAdapter->hdd_stats.hddTxRxStats.txFetchEmpty; #ifdef HDD_WMM_DEBUG VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, "%s: no packets pending", __FUNCTION__); #endif // HDD_WMM_DEBUG return VOS_STATUS_E_FAILURE; } // do we have any packets pending in this AC? hdd_list_size( &pAdapter->wmm_tx_queue[ac], &size ); if( size > 0 ) { // yes, so process it #ifdef HDD_WMM_DEBUG VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, "%s: AC %d has packets pending", __FUNCTION__, ac); #endif // HDD_WMM_DEBUG } else { ++pAdapter->hdd_stats.hddTxRxStats.txFetchEmpty; #ifdef HDD_WMM_DEBUG VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, "%s: no packets pending", __FUNCTION__); #endif // HDD_WMM_DEBUG return VOS_STATUS_E_FAILURE; } //Get the vos packet. I don't want to dequeue and enqueue again if we are out of VOS resources //This simplifies the locking and unlocking of Tx queue status = vos_pkt_wrap_data_packet( &pVosPacket, VOS_PKT_TYPE_TX_802_3_DATA, NULL, //OS Pkt is not being passed hdd_tx_low_resource_cbk, pAdapter ); if (status == VOS_STATUS_E_ALREADY || status == VOS_STATUS_E_RESOURCES) { //Remember VOS is in a low resource situation pAdapter->isVosOutOfResource = VOS_TRUE; ++pAdapter->hdd_stats.hddTxRxStats.txFetchLowResources; VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN,"%s: VOSS in Low Resource scenario", __FUNCTION__); //TL will now think we have no more packets in this AC return VOS_STATUS_E_FAILURE; } //Remove the packet from the queue spin_lock_bh(&pAdapter->wmm_tx_queue[ac].lock); status = hdd_list_remove_front( &pAdapter->wmm_tx_queue[ac], &anchor ); spin_unlock_bh(&pAdapter->wmm_tx_queue[ac].lock); if(VOS_STATUS_SUCCESS == status) { //If success then we got a valid packet from some AC pktNode = list_entry(anchor, skb_list_node_t, anchor); skb = pktNode->skb; } else { ++pAdapter->hdd_stats.hddTxRxStats.txFetchDequeueError; VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN, "%s: Error in de-queuing " "skb from Tx queue status = %d", __FUNCTION__, status ); vos_pkt_return_packet(pVosPacket); return VOS_STATUS_E_FAILURE; } //Attach skb to VOS packet. status = vos_pkt_set_os_packet( pVosPacket, skb ); if (status != VOS_STATUS_SUCCESS) { VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN,"%s: Error attaching skb", __FUNCTION__); vos_pkt_return_packet(pVosPacket); ++pAdapter->stats.tx_dropped; ++pAdapter->hdd_stats.hddTxRxStats.txFetchDequeueError; kfree_skb(skb); return VOS_STATUS_E_FAILURE; } //Just being paranoid. To be removed later if(pVosPacket == NULL) { VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN,"%s: VOS packet returned by VOSS is NULL", __FUNCTION__); ++pAdapter->stats.tx_dropped; ++pAdapter->hdd_stats.hddTxRxStats.txFetchDequeueError; kfree_skb(skb); return VOS_STATUS_E_FAILURE; } //Return VOS packet to TL; *ppVosPacket = pVosPacket; //Fill out the meta information needed by TL //FIXME This timestamp is really the time stamp of wrap_data_packet vos_pkt_get_timestamp( pVosPacket, ×tamp ); pPktMetaInfo->usTimeStamp = (v_U16_t)timestamp; if(pAdapter->sessionCtx.station.conn_info.uIsAuthenticated == VOS_TRUE) pPktMetaInfo->ucIsEapol = 0; else pPktMetaInfo->ucIsEapol = hdd_IsEAPOLPacket( pVosPacket ) ? 1 : 0; #ifdef FEATURE_WLAN_WAPI // Override usIsEapol value when its zero for WAPI case pPktMetaInfo->ucIsWai = hdd_IsWAIPacket( pVosPacket ) ? 1 : 0; #endif /* FEATURE_WLAN_WAPI */ if ((HDD_WMM_USER_MODE_NO_QOS == pHddCtx->cfg_ini->WmmMode) || (!pAdapter->hddWmmStatus.wmmQap)) { // either we don't want QoS or the AP doesn't support QoS pPktMetaInfo->ucUP = 0; pPktMetaInfo->ucTID = 0; } else { /* 1. Check if ACM is set for this AC * 2. If set, check if this AC had already admitted * 3. If not already admitted, downgrade the UP to next best UP */ if(!pAdapter->hddWmmStatus.wmmAcStatus[ac].wmmAcAccessRequired || pAdapter->hddWmmStatus.wmmAcStatus[ac].wmmAcTspecValid) { pPktMetaInfo->ucUP = pktNode->userPriority; pPktMetaInfo->ucTID = pPktMetaInfo->ucUP; } else { //Downgrade the UP acAdmitted = pAdapter->hddWmmStatus.wmmAcStatus[ac].wmmAcTspecValid; newAc = WLANTL_AC_BK; for (i=ac-1; i>0; i--) { if (pAdapter->hddWmmStatus.wmmAcStatus[i].wmmAcAccessRequired == 0) { newAc = i; break; } } pPktMetaInfo->ucUP = hddWmmAcToHighestUp[newAc]; pPktMetaInfo->ucTID = pPktMetaInfo->ucUP; VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_LOW,"Downgrading UP %d to UP %d ", pktNode->userPriority, pPktMetaInfo->ucUP); } } pPktMetaInfo->ucType = 0; //FIXME Don't know what this is pPktMetaInfo->ucDisableFrmXtl = 0; //802.3 frame so we need to xlate if ( 1 < size ) { pPktMetaInfo->bMorePackets = 1; //HDD has more packets to send } else { pPktMetaInfo->bMorePackets = 0; } //Extract the destination address from ethernet frame pDestMacAddress = (v_MACADDR_t*)skb->data; pPktMetaInfo->ucBcast = vos_is_macaddr_broadcast( pDestMacAddress ) ? 1 : 0; pPktMetaInfo->ucMcast = vos_is_macaddr_group( pDestMacAddress ) ? 1 : 0; // if we are in a backpressure situation see if we can turn the hose back on if ( (pAdapter->isTxSuspended[ac]) && (size <= HDD_TX_QUEUE_LOW_WATER_MARK) ) { ++pAdapter->hdd_stats.hddTxRxStats.txFetchDePressured; ++pAdapter->hdd_stats.hddTxRxStats.txFetchDePressuredAC[ac]; VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN, "%s: TX queue[%d] re-enabled", __FUNCTION__, ac); pAdapter->isTxSuspended[ac] = VOS_FALSE; netif_tx_wake_queue(netdev_get_tx_queue(pAdapter->dev, skb_get_queue_mapping(skb) )); } // We're giving the packet to TL so consider it transmitted from // a statistics perspective. We account for it here instead of // when the packet is returned for two reasons. First, TL will // manipulate the skb to the point where the len field is not // accurate, leading to inaccurate byte counts if we account for // it later. Second, TL does not provide any feedback as to // whether or not the packet was successfully sent over the air, // so the packet counts will be the same regardless of where we // account for them pAdapter->stats.tx_bytes += skb->len; ++pAdapter->stats.tx_packets; ++pAdapter->hdd_stats.hddTxRxStats.txFetchDequeued; ++pAdapter->hdd_stats.hddTxRxStats.txFetchDequeuedAC[ac]; if(pHddCtx->cfg_ini->thermalMitigationEnable) { if(mutex_lock_interruptible(&pHddCtx->tmInfo.tmOperationLock)) { VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, "%s: Tm Lock fail", __FUNCTION__); return VOS_STATUS_E_FAILURE; } if(WLAN_HDD_TM_LEVEL_1 < pHddCtx->tmInfo.currentTmLevel) { if(0 == pHddCtx->tmInfo.txFrameCount) { /* Just recovered from sleep timeout */ pHddCtx->tmInfo.lastOpenTs = timestamp; } if(((timestamp - pHddCtx->tmInfo.lastOpenTs) > (pHddCtx->tmInfo.tmAction.txOperationDuration / 10)) && (pHddCtx->tmInfo.txFrameCount >= pHddCtx->tmInfo.tmAction.txBlockFrameCountThreshold)) { spin_lock(&pAdapter->wmm_tx_queue[ac].lock); /* During TX open duration, TX frame count is larger than threshold * Block TX during Sleep time */ netif_tx_stop_all_queues(pAdapter->dev); spin_unlock(&pAdapter->wmm_tx_queue[ac].lock); pHddCtx->tmInfo.lastblockTs = timestamp; if(VOS_TIMER_STATE_STOPPED == vos_timer_getCurrentState(&pHddCtx->tmInfo.txSleepTimer)) { vos_timer_start(&pHddCtx->tmInfo.txSleepTimer, pHddCtx->tmInfo.tmAction.txSleepDuration); } } else if(((timestamp - pHddCtx->tmInfo.lastOpenTs) > (pHddCtx->tmInfo.tmAction.txOperationDuration / 10)) && (pHddCtx->tmInfo.txFrameCount < pHddCtx->tmInfo.tmAction.txBlockFrameCountThreshold)) { /* During TX open duration, TX frame count is less than threshold * Reset count and timestamp to prepare next cycle */ pHddCtx->tmInfo.lastOpenTs = timestamp; pHddCtx->tmInfo.txFrameCount = 0; } else { /* Do Nothing */ } pHddCtx->tmInfo.txFrameCount++; } mutex_unlock(&pHddCtx->tmInfo.tmOperationLock); } #ifdef HDD_WMM_DEBUG VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,"%s: Valid VOS PKT returned to TL", __FUNCTION__); #endif // HDD_WMM_DEBUG return status; }