/*---------------------------------------------------------------------------- @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; }
void hdd_sendActionCnf( hdd_adapter_t *pAdapter, tANI_BOOLEAN actionSendSuccess ) { hdd_cfg80211_state_t *cfgState = WLAN_HDD_GET_CFG_STATE_PTR( pAdapter ); cfgState->actionFrmState = HDD_IDLE; hddLog( LOG1, "Send Action cnf, actionSendSuccess %d", actionSendSuccess); if( NULL == cfgState->buf ) { return; } /* If skb is NULL it means this packet was received on CFG80211 interface * else it was received on Monitor interface */ if( cfgState->skb == NULL ) { /* * buf is the same pointer it passed us to send. Since we are sending * it through control path, we use different buffers. * In case of mac80211, they just push it to the skb and pass the same * data while sending tx ack status. * */ cfg80211_mgmt_tx_status( pAdapter->dev, cfgState->action_cookie, cfgState->buf, cfgState->len, actionSendSuccess, GFP_KERNEL ); vos_mem_free( cfgState->buf ); cfgState->buf = NULL; } else { hdd_adapter_t* pMonAdapter = hdd_get_adapter( pAdapter->pHddCtx, WLAN_HDD_MONITOR ); if( pMonAdapter == NULL ) { hddLog( LOGE, "Not able to get Monitor Adapter"); cfgState->skb = NULL; vos_mem_free( cfgState->buf ); cfgState->buf = NULL; complete(&pAdapter->tx_action_cnf_event); return; } /* Send TX completion feedback over monitor interface. */ hdd_wlan_tx_complete( pMonAdapter, cfgState, actionSendSuccess ); cfgState->skb = NULL; vos_mem_free( cfgState->buf ); cfgState->buf = NULL; /* Look for the next Mgmt packet to TX */ hdd_mon_tx_mgmt_pkt(pAdapter); } complete(&pAdapter->tx_action_cnf_event); }
/**============================================================================ @brief hdd_tx_complete_cbk() - Callback function invoked by TL to indicate that a packet has been transmitted across the SDIO bus succesfully. OS packet resources can be released after this cbk. @param vosContext : [in] pointer to VOS context @param pVosPacket : [in] pointer to VOS packet (containing skb) @param vosStatusIn : [in] status of the transmission @return : VOS_STATUS_E_FAILURE if any errors encountered : VOS_STATUS_SUCCESS otherwise ===========================================================================*/ VOS_STATUS hdd_tx_complete_cbk( v_VOID_t *vosContext, vos_pkt_t *pVosPacket, VOS_STATUS vosStatusIn ) { VOS_STATUS status = VOS_STATUS_SUCCESS; hdd_adapter_t *pAdapter = NULL; hdd_context_t *pHddCtx = NULL; void* pOsPkt = NULL; if( ( NULL == vosContext ) || ( NULL == pVosPacket ) ) { VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,"%s: Null params being passed", __FUNCTION__); return VOS_STATUS_E_FAILURE; } //Return the skb to the OS status = vos_pkt_get_os_packet( pVosPacket, &pOsPkt, VOS_TRUE ); if(!VOS_IS_STATUS_SUCCESS( status )) { //This is bad but still try to free the VOSS resources if we can VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,"%s: Failure extracting skb from vos pkt", __FUNCTION__); vos_pkt_return_packet( pVosPacket ); return VOS_STATUS_E_FAILURE; } //Get the HDD context. pHddCtx = (hdd_context_t *)vos_get_context( VOS_MODULE_ID_HDD, vosContext ); //Get the Adapter context. pAdapter = hdd_get_adapter(pHddCtx,WLAN_HDD_INFRA_STATION); if(pAdapter == NULL) { VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,"%s: HDD adapter context is Null", __FUNCTION__); } else { ++pAdapter->hdd_stats.hddTxRxStats.txCompleted; } kfree_skb((struct sk_buff *)pOsPkt); //Return the VOS packet resources. status = vos_pkt_return_packet( pVosPacket ); if(!VOS_IS_STATUS_SUCCESS( status )) { VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,"%s: Could not return VOS packet to the pool", __FUNCTION__); } return status; }
/*---------------------------------------------------------------------------- @brief TX frame block timeout handler Resume TX, and reset TX frame count @param hdd_context_t pHddCtx Global hdd context @return NONE ----------------------------------------------------------------------------*/ void hddDevTmTxBlockTimeoutHandler(void *usrData) { hdd_context_t *pHddCtx = (hdd_context_t *)usrData; hdd_adapter_t *staAdapater; /* Sanity, This should not happen */ if(NULL == pHddCtx) { VOS_TRACE(VOS_MODULE_ID_HDD,VOS_TRACE_LEVEL_ERROR, "%s: NULL Context", __func__); VOS_ASSERT(0); return; } staAdapater = hdd_get_adapter(pHddCtx, WLAN_HDD_INFRA_STATION); if(NULL == staAdapater) { VOS_TRACE(VOS_MODULE_ID_HDD,VOS_TRACE_LEVEL_ERROR, "%s: NULL Adapter", __func__); VOS_ASSERT(0); return; } if(mutex_lock_interruptible(&pHddCtx->tmInfo.tmOperationLock)) { VOS_TRACE(VOS_MODULE_ID_HDD,VOS_TRACE_LEVEL_ERROR, "%s: Acquire lock fail", __func__); return; } pHddCtx->tmInfo.txFrameCount = 0; /* Resume TX flow */ netif_tx_wake_all_queues(staAdapater->dev); pHddCtx->tmInfo.qBlocked = VOS_FALSE; mutex_unlock(&pHddCtx->tmInfo.tmOperationLock); return; }
void hdd_mon_tx_mgmt_pkt(hdd_adapter_t* pAdapter) { hdd_cfg80211_state_t *cfgState; struct sk_buff* skb; hdd_adapter_t* pMonAdapter = NULL; struct ieee80211_hdr *hdr; if (pAdapter == NULL ) { VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, "%s: pAdapter is NULL", __func__); return; } pMonAdapter = hdd_get_adapter( pAdapter->pHddCtx, WLAN_HDD_MONITOR ); cfgState = WLAN_HDD_GET_CFG_STATE_PTR( pAdapter ); if( NULL != cfgState->buf ) { VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, "%s: Already one MGMT packet Tx going on", __func__); return; } skb = hdd_mon_tx_fetch_pkt(pMonAdapter); if (NULL == skb) { VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, "%s: No Packet Pending", __func__); return; } cfgState->buf = vos_mem_malloc( skb->len ); //buf; if( cfgState->buf == NULL ) { VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, "%s: Failed to Allocate memory", __func__); goto fail; } cfgState->len = skb->len; vos_mem_copy( cfgState->buf, skb->data, skb->len); cfgState->skb = skb; //buf; cfgState->action_cookie = (tANI_U32)cfgState->buf; hdr = (struct ieee80211_hdr *)skb->data; if( (hdr->frame_control & HDD_FRAME_TYPE_MASK) == HDD_FRAME_TYPE_MGMT ) { if( (hdr->frame_control & HDD_FRAME_SUBTYPE_MASK) == HDD_FRAME_SUBTYPE_DEAUTH ) { hdd_softap_sta_deauth( pAdapter, hdr->addr1 ); goto mgmt_handled; } else if( (hdr->frame_control & HDD_FRAME_SUBTYPE_MASK) == HDD_FRAME_SUBTYPE_DISASSOC ) { hdd_softap_sta_disassoc( pAdapter, hdr->addr1 ); goto mgmt_handled; } } VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s: Sending action frame to SAP to TX, Len %d", __func__, skb->len); if (VOS_STATUS_SUCCESS != WLANSAP_SendAction( (WLAN_HDD_GET_CTX(pAdapter))->pvosContext, skb->data, skb->len, 0) ) { VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, "%s: WLANSAP_SendAction returned fail", __func__); hdd_sendActionCnf( pAdapter, FALSE ); } return; mgmt_handled: hdd_sendActionCnf( pAdapter, TRUE ); return; fail: kfree_skb(pAdapter->skb_to_tx); pAdapter->skb_to_tx = NULL; return; }
int wlan_hdd_action( struct wiphy *wiphy, struct net_device *dev, struct ieee80211_channel *chan, enum nl80211_channel_type channel_type, bool channel_type_valid, const u8 *buf, size_t len, u64 *cookie ) #endif //LINUX_VERSION_CODE { hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( dev ); hdd_cfg80211_state_t *cfgState = WLAN_HDD_GET_CFG_STATE_PTR( pAdapter ); tANI_U16 extendedWait = 0; tANI_U8 type = WLAN_HDD_GET_TYPE_FRM_FC(buf[0]); tANI_U8 subType = WLAN_HDD_GET_SUBTYPE_FRM_FC(buf[0]); tActionFrmType actionFrmType; bool noack = 0; #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38)) hdd_adapter_t *goAdapter; #endif #ifdef WLAN_FEATURE_P2P_DEBUG if ((type == SIR_MAC_MGMT_FRAME) && (subType == SIR_MAC_MGMT_ACTION) && (buf[WLAN_HDD_PUBLIC_ACTION_FRAME_OFFSET] == WLAN_HDD_PUBLIC_ACTION_FRAME)) { actionFrmType = buf[WLAN_HDD_PUBLIC_ACTION_FRAME_TYPE_OFFSET]; if(actionFrmType > MAX_P2P_ACTION_FRAME_TYPE) { hddLog(VOS_TRACE_LEVEL_ERROR,"[P2P] unknown[%d] ---> OTA", actionFrmType); } else { hddLog(VOS_TRACE_LEVEL_ERROR,"[P2P] %s ---> OTA", p2p_action_frame_type[actionFrmType]); if( (actionFrmType == WLAN_HDD_PROV_DIS_REQ) && (globalP2PConnectionStatus == P2P_NOT_ACTIVE) ) { globalP2PConnectionStatus = P2P_GO_NEG_PROCESS; hddLog(LOGE,"[P2P State]Inactive state to " "GO negotation progress state"); } else if( (actionFrmType == WLAN_HDD_GO_NEG_CNF) && (globalP2PConnectionStatus == P2P_GO_NEG_PROCESS) ) { globalP2PConnectionStatus = P2P_GO_NEG_COMPLETED; hddLog(LOGE,"[P2P State]GO nego progress to GO nego" " completed state"); } } } #endif #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,3,0)) noack = dont_wait_for_ack; #endif //If the wait is coming as 0 with off channel set //then set the wait to 200 ms if (offchan && !wait) wait = ACTION_FRAME_DEFAULT_WAIT; hddLog(VOS_TRACE_LEVEL_INFO, "%s: device_mode = %d", __func__,pAdapter->device_mode); //Call sme API to send out a action frame. // OR can we send it directly through data path?? // After tx completion send tx status back. if ( ( WLAN_HDD_SOFTAP == pAdapter->device_mode ) || ( WLAN_HDD_P2P_GO == pAdapter->device_mode ) ) { if (type == SIR_MAC_MGMT_FRAME) { if (subType == SIR_MAC_MGMT_PROBE_RSP) { /* Drop Probe response recieved from supplicant, as for GO and SAP PE itself sends probe response */ goto err_rem_channel; } else if ((subType == SIR_MAC_MGMT_DISASSOC) || (subType == SIR_MAC_MGMT_DEAUTH)) { /* During EAP failure or P2P Group Remove supplicant * is sending del_station command to driver. From * del_station function, Driver will send deauth frame to * p2p client. No need to send disassoc frame from here. * so Drop the frame here and send tx indication back to * supplicant. */ tANI_U8 dstMac[ETH_ALEN] = {0}; memcpy(&dstMac, &buf[WLAN_HDD_80211_FRM_DA_OFFSET], ETH_ALEN); hddLog(VOS_TRACE_LEVEL_INFO, "%s: Deauth/Disassoc received for STA:" "%02x:%02x:%02x:%02x:%02x:%02x", __func__, dstMac[0], dstMac[1], dstMac[2], dstMac[3], dstMac[4], dstMac[5]); goto err_rem_channel; } } } if( NULL != cfgState->buf ) return -EBUSY; hddLog( LOG1, "Action frame tx request"); #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38)) goAdapter = hdd_get_adapter( pAdapter->pHddCtx, WLAN_HDD_P2P_GO ); //If GO adapter exists and operating on same frequency //then we will not request remain on channel if( goAdapter && ( ieee80211_frequency_to_channel(chan->center_freq) == goAdapter->sessionCtx.ap.operatingChannel ) ) { goto send_frame; } #endif #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38)) if( offchan && wait) { int status; // In case of P2P Client mode if we are already // on the same channel then send the frame directly if((cfgState->remain_on_chan_ctx != NULL) && (cfgState->current_freq == chan->center_freq) ) { hddLog(LOG1,"action frame: extending the wait time\n"); extendedWait = (tANI_U16)wait; goto send_frame; } INIT_COMPLETION(pAdapter->offchannel_tx_event); status = wlan_hdd_request_remain_on_channel(wiphy, dev, chan, channel_type, wait, cookie, OFF_CHANNEL_ACTION_TX); if(0 != status) { if( (-EBUSY == status) && (cfgState->current_freq == chan->center_freq) ) { goto send_frame; } goto err_rem_channel; } /* Wait for driver to be ready on the requested channel */ status = wait_for_completion_interruptible_timeout( &pAdapter->offchannel_tx_event, msecs_to_jiffies(WAIT_CHANGE_CHANNEL_FOR_OFFCHANNEL_TX)); if(!status) { hddLog( LOGE, "Not able to complete remain on channel request" " within timeout period"); goto err_rem_channel; } } else if ( offchan ) { /* Check before sending action frame whether we already remain on channel */ if(NULL == cfgState->remain_on_chan_ctx) { goto err_rem_channel; } } send_frame: #endif if(!noack) { cfgState->buf = vos_mem_malloc( len ); //buf; if( cfgState->buf == NULL ) return -ENOMEM; cfgState->len = len; vos_mem_copy( cfgState->buf, buf, len); #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38)) if( cfgState->remain_on_chan_ctx ) { cfgState->action_cookie = cfgState->remain_on_chan_ctx->cookie; *cookie = cfgState->action_cookie; } else { #endif *cookie = (tANI_U32) cfgState->buf; cfgState->action_cookie = *cookie; #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38)) } #endif } if ( (WLAN_HDD_INFRA_STATION == pAdapter->device_mode) || (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode) || ( WLAN_HDD_P2P_DEVICE == pAdapter->device_mode ) ) { tANI_U8 sessionId = pAdapter->sessionId; if ((type == SIR_MAC_MGMT_FRAME) && (subType == SIR_MAC_MGMT_ACTION) && (buf[WLAN_HDD_PUBLIC_ACTION_FRAME_OFFSET] == WLAN_HDD_PUBLIC_ACTION_FRAME)) { actionFrmType = buf[WLAN_HDD_PUBLIC_ACTION_FRAME_TYPE_OFFSET]; hddLog(LOG1, "Tx Action Frame %u \n", actionFrmType); if (actionFrmType == WLAN_HDD_PROV_DIS_REQ) { cfgState->actionFrmState = HDD_PD_REQ_ACK_PENDING; hddLog(LOG1, "%s: HDD_PD_REQ_ACK_PENDING \n", __func__); } else if (actionFrmType == WLAN_HDD_GO_NEG_REQ) { cfgState->actionFrmState = HDD_GO_NEG_REQ_ACK_PENDING; hddLog(LOG1, "%s: HDD_GO_NEG_REQ_ACK_PENDING \n", __func__); } } if (eHAL_STATUS_SUCCESS != sme_sendAction( WLAN_HDD_GET_HAL_CTX(pAdapter), sessionId, buf, len, extendedWait, noack)) { VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, "%s: sme_sendAction returned fail", __func__); goto err; } } else if( ( WLAN_HDD_SOFTAP== pAdapter->device_mode ) || ( WLAN_HDD_P2P_GO == pAdapter->device_mode ) ) { if( VOS_STATUS_SUCCESS != WLANSAP_SendAction( (WLAN_HDD_GET_CTX(pAdapter))->pvosContext, buf, len, 0 ) ) { VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, "%s: WLANSAP_SendAction returned fail", __func__); goto err; } } return 0; err: if(!noack) { hdd_sendActionCnf( pAdapter, FALSE ); } return 0; err_rem_channel: *cookie = (tANI_U32)cfgState; cfg80211_mgmt_tx_status( pAdapter->dev, *cookie, buf, len, FALSE, GFP_KERNEL ); return 0; }
int wlan_hdd_add_virtual_intf( struct wiphy *wiphy, char *name, enum nl80211_iftype type, u32 *flags, struct vif_params *params ) #endif { hdd_context_t *pHddCtx = (hdd_context_t*) wiphy_priv(wiphy); hdd_adapter_t* pAdapter = NULL; ENTER(); if(hdd_get_adapter(pHddCtx, wlan_hdd_get_session_type(type)) != NULL) { hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Interface type %d already exists. Two" "interfaces of same type are not supported currently.",__func__, type); return NULL; } if (pHddCtx->isLogpInProgress) { VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, "%s:LOGP in Progress. Ignore!!!", __func__); #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38)) return NULL; #else return -EAGAIN; #endif } if ( pHddCtx->cfg_ini->isP2pDeviceAddrAdministrated ) { if( (NL80211_IFTYPE_P2P_GO == type) || (NL80211_IFTYPE_P2P_CLIENT == type) ) { /* Generate the P2P Interface Address. this address must be * different from the P2P Device Address. */ v_MACADDR_t p2pDeviceAddress = pHddCtx->p2pDeviceAddress; p2pDeviceAddress.bytes[4] ^= 0x80; pAdapter = hdd_open_adapter( pHddCtx, wlan_hdd_get_session_type(type), name, p2pDeviceAddress.bytes, VOS_TRUE ); } } else { pAdapter = hdd_open_adapter( pHddCtx, wlan_hdd_get_session_type(type), name, wlan_hdd_get_intf_addr(pHddCtx), VOS_TRUE ); } if( NULL == pAdapter) { hddLog(VOS_TRACE_LEVEL_ERROR,"%s: hdd_open_adapter failed",__func__); #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38)) return NULL; #else return -EINVAL; #endif } EXIT(); #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38)) return pAdapter->dev; #else return 0; #endif }