VOID kalP2PIndicateMgmtTxStatus ( IN P_GLUE_INFO_T prGlueInfo, IN UINT_64 u8Cookie, IN BOOLEAN fgIsAck, IN PUINT_8 pucFrameBuf, IN UINT_32 u4FrameLen ) { P_GL_P2P_INFO_T prGlueP2pInfo = (P_GL_P2P_INFO_T)NULL; do { if ((prGlueInfo == NULL) || (pucFrameBuf == NULL) || (u4FrameLen == 0)) { DBGLOG(P2P, TRACE, ("Unexpected pointer PARAM. 0x%lx, 0x%lx, %ld.", prGlueInfo, pucFrameBuf, u4FrameLen)); ASSERT(FALSE); break; } prGlueP2pInfo = prGlueInfo->prP2PInfo; cfg80211_mgmt_tx_status(prGlueP2pInfo->prDevHandler, //struct net_device * dev, u8Cookie, pucFrameBuf, u4FrameLen, fgIsAck, GFP_KERNEL); } while (FALSE); } /* kalP2PIndicateMgmtTxStatus */
VOID kalP2PIndicateMgmtTxStatus(IN P_GLUE_INFO_T prGlueInfo, IN UINT_64 u8Cookie, IN BOOLEAN fgIsAck, IN PUINT_8 pucFrameBuf, IN UINT_32 u4FrameLen) { P_GL_P2P_INFO_T prGlueP2pInfo = (P_GL_P2P_INFO_T) NULL; do { if ((prGlueInfo == NULL) || (pucFrameBuf == NULL) || (u4FrameLen == 0)) { DBGLOG(P2P, TRACE, ("Unexpected pointer PARAM. 0x%p, 0x%p, %lu", prGlueInfo, pucFrameBuf, u4FrameLen)); ASSERT(FALSE); break; } prGlueP2pInfo = prGlueInfo->prP2PInfo; #if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 8, 0) cfg80211_mgmt_tx_status(&prGlueP2pInfo->wdev, /* struct net_device * dev, */ #else cfg80211_mgmt_tx_status(prGlueP2pInfo->prDevHandler, /* struct net_device * dev, */ #endif /* LINUX_VERSION_CODE */ u8Cookie, pucFrameBuf, u4FrameLen, fgIsAck, GFP_KERNEL); } while (FALSE); } /* kalP2PIndicateMgmtTxStatus */
void mwifiex_parse_tx_status_event(struct mwifiex_private *priv, void *event_body) { struct tx_status_event *tx_status = (void *)priv->adapter->event_body; struct sk_buff *ack_skb; unsigned long flags; struct mwifiex_txinfo *tx_info; if (!tx_status->tx_token_id) return; spin_lock_irqsave(&priv->ack_status_lock, flags); ack_skb = idr_find(&priv->ack_status_frames, tx_status->tx_token_id); if (ack_skb) idr_remove(&priv->ack_status_frames, tx_status->tx_token_id); spin_unlock_irqrestore(&priv->ack_status_lock, flags); if (ack_skb) { tx_info = MWIFIEX_SKB_TXCB(ack_skb); if (tx_info->flags & MWIFIEX_BUF_FLAG_EAPOL_TX_STATUS) { /* consumes ack_skb */ skb_complete_wifi_ack(ack_skb, !tx_status->status); } else { cfg80211_mgmt_tx_status(&priv->wdev, tx_info->cookie, ack_skb->data, ack_skb->len, !tx_status->status, GFP_ATOMIC); dev_kfree_skb_any(ack_skb); } } }
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); }
VOID kalP2PIndicateMgmtTxStatus ( IN P_GLUE_INFO_T prGlueInfo, IN P_MSDU_INFO_T prMsduInfo, IN BOOLEAN fgIsAck ) { P_GL_P2P_INFO_T prGlueP2pInfo = (P_GL_P2P_INFO_T)NULL; PUINT_64 pu8GlCookie = (PUINT_64)NULL; struct net_device *prNetdevice = (struct net_device *)NULL; do { if ((prGlueInfo == NULL) || (prMsduInfo == NULL)) { DBGLOG(P2P, WARN, ("Unexpected pointer PARAM. 0x%lx, 0x%lx.\n", prGlueInfo, prMsduInfo)); ASSERT(FALSE); break; } prGlueP2pInfo = prGlueInfo->prP2PInfo; pu8GlCookie = (PUINT_64)((UINT_32)prMsduInfo->prPacket + (UINT_32)prMsduInfo->u2FrameLength + MAC_TX_RESERVED_FIELD); if (prMsduInfo->ucBssIndex == P2P_DEV_BSS_INDEX) { prNetdevice = prGlueP2pInfo->prDevHandler; } else { P_BSS_INFO_T prP2pBssInfo = GET_BSS_INFO_BY_INDEX(prGlueInfo->prAdapter, prMsduInfo->ucBssIndex); prNetdevice = prGlueP2pInfo->aprRoleHandler[prP2pBssInfo->u4PrivateData]; } #if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 8, 0) cfg80211_mgmt_tx_status(&prGlueP2pInfo->wdev, //struct net_device * dev, #else cfg80211_mgmt_tx_status(prGlueP2pInfo->prDevHandler, //struct net_device * dev, #endif /* LINUX_VERSION_CODE */ *pu8GlCookie, (PUINT_8)((UINT_32)prMsduInfo->prPacket + MAC_TX_RESERVED_FIELD), prMsduInfo->u2FrameLength, fgIsAck, GFP_KERNEL); } while (FALSE); } /* kalP2PIndicateMgmtTxStatus */
int wil_cfg80211_mgmt_tx(struct wiphy *wiphy, struct wireless_dev *wdev, struct ieee80211_channel *chan, bool offchan, unsigned int wait, const u8 *buf, size_t len, bool no_cck, bool dont_wait_for_ack, u64 *cookie) { struct wil6210_priv *wil = wiphy_to_wil(wiphy); int rc; bool tx_status = false; struct ieee80211_mgmt *mgmt_frame = (void *)buf; struct wmi_sw_tx_req_cmd *cmd; struct { struct wil6210_mbox_hdr_wmi wmi; struct wmi_sw_tx_complete_event evt; } __packed evt; cmd = kmalloc(sizeof(*cmd) + len, GFP_KERNEL); if (!cmd) { rc = -ENOMEM; goto out; } memcpy(cmd->dst_mac, mgmt_frame->da, WMI_MAC_LEN); cmd->len = cpu_to_le16(len); memcpy(cmd->payload, buf, len); rc = wmi_call(wil, WMI_SW_TX_REQ_CMDID, cmd, sizeof(*cmd) + len, WMI_SW_TX_COMPLETE_EVENTID, &evt, sizeof(evt), 2000); if (rc == 0) tx_status = !evt.evt.status; kfree(cmd); out: cfg80211_mgmt_tx_status(wdev, cookie ? *cookie : 0, buf, len, tx_status, GFP_KERNEL); return rc; }
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; }
/** * @brief This function removes an virtual interface. * * @param wiphy A pointer to the wiphy structure * @param dev A pointer to the net_device structure * * @return 0 -- success, otherwise fail */ int woal_cfg80211_del_virt_if(struct wiphy *wiphy, struct net_device *dev) { int ret = 0; int i = 0; moal_private *priv = NULL; moal_private *vir_priv = NULL; moal_private *remain_priv = NULL; moal_handle *handle = (moal_handle *)woal_get_wiphy_priv(wiphy); unsigned long flags; priv = (moal_private *)woal_get_priv_bss_type(handle, MLAN_BSS_TYPE_WIFIDIRECT); if (!priv) return ret; for (i = 0; i < priv->phandle->priv_num; i++) { vir_priv = priv->phandle->priv[i]; if (vir_priv) { if (vir_priv->netdev == dev) { PRINTM(MMSG, "Del virtual interface %s, index=%d\n", dev->name, i); break; } } } if (vir_priv && vir_priv->netdev == dev) { woal_stop_queue(dev); netif_carrier_off(dev); netif_device_detach(dev); if (handle->is_remain_timer_set) { woal_cancel_timer(&handle->remain_timer); woal_remain_timer_func(handle); } spin_lock_irqsave(&vir_priv->tx_stat_lock, flags); if (vir_priv->last_tx_buf && vir_priv->last_tx_cookie) { #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 37) || defined(COMPAT_WIRELESS) #if LINUX_VERSION_CODE < KERNEL_VERSION(3, 6, 0) cfg80211_mgmt_tx_status(vir_priv->netdev, vir_priv->last_tx_cookie, vir_priv->last_tx_buf, vir_priv->last_tx_buf_len, true, GFP_ATOMIC); #else cfg80211_mgmt_tx_status(vir_priv->wdev, vir_priv->last_tx_cookie, vir_priv->last_tx_buf, vir_priv->last_tx_buf_len, true, GFP_ATOMIC); #endif #endif kfree(vir_priv->last_tx_buf); vir_priv->last_tx_buf = NULL; vir_priv->last_tx_cookie = 0; } spin_unlock_irqrestore(&vir_priv->tx_stat_lock, flags); /* cancel previous remain on channel to avoid firmware hang */ if (priv->phandle->remain_on_channel) { t_u8 channel_status; remain_priv = priv->phandle->priv[priv->phandle-> remain_bss_index]; if (remain_priv) { if (woal_cfg80211_remain_on_channel_cfg (remain_priv, MOAL_IOCTL_WAIT, MTRUE, &channel_status, NULL, 0, 0)) PRINTM(MERROR, "del_virt_if: Fail to cancel remain on channel\n"); if (priv->phandle->cookie) { cfg80211_remain_on_channel_expired( #if LINUX_VERSION_CODE < KERNEL_VERSION(3, 6, 0) remain_priv-> netdev, #else remain_priv-> wdev, #endif priv-> phandle-> cookie, &priv-> phandle-> chan, #if LINUX_VERSION_CODE < KERNEL_VERSION(3, 8, 0) priv-> phandle-> channel_type, #endif GFP_ATOMIC); priv->phandle->cookie = 0; } priv->phandle->remain_on_channel = MFALSE; } } woal_clear_all_mgmt_ies(vir_priv, MOAL_IOCTL_WAIT); woal_cfg80211_deinit_p2p(vir_priv); woal_bss_remove(vir_priv); #ifdef CONFIG_PROC_FS #ifdef PROC_DEBUG /* Remove proc debug */ woal_debug_remove(vir_priv); #endif /* PROC_DEBUG */ woal_proc_remove(vir_priv); #endif /* CONFIG_PROC_FS */ /* Last reference is our one */ #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 37) PRINTM(MINFO, "refcnt = %d\n", atomic_read(&dev->refcnt)); #else PRINTM(MINFO, "refcnt = %d\n", netdev_refcnt_read(dev)); #endif PRINTM(MINFO, "netdev_finish_unregister: %s\n", dev->name); /* Clear the priv in handle */ vir_priv->phandle->priv[vir_priv->bss_index] = NULL; priv->phandle->priv_num--; if (dev->reg_state == NETREG_REGISTERED) unregister_netdevice(dev); } return ret; }