int wlan_queue_fw_log_pkt_for_app(vos_pkt_t *pPacket) { unsigned long flags; vos_pkt_t *next_pkt; vos_pkt_t *free_pkt; VOS_STATUS status = VOS_STATUS_E_FAILURE; spin_lock_irqsave(&gwlan_logging.fw_log_pkt_lock, flags); if (gwlan_logging.fw_log_pkt_qcnt >= LOGGER_MAX_FW_LOG_PKT_Q_LEN) { status = vos_pkt_walk_packet_chain( gwlan_logging.fw_log_pkt_queue, &next_pkt, TRUE); /*both "success" and "empty" are acceptable results*/ if (!((status == VOS_STATUS_SUCCESS) || (status == VOS_STATUS_E_EMPTY))) { ++gwlan_logging.fw_log_pkt_drop_cnt; spin_unlock_irqrestore( &gwlan_logging.fw_log_pkt_lock, flags); pr_err("%s: Failure walking packet chain", __func__); /*keep returning pkts to avoid low resource cond*/ vos_pkt_return_packet(pPacket); return VOS_STATUS_E_FAILURE; } free_pkt = gwlan_logging.fw_log_pkt_queue; gwlan_logging.fw_log_pkt_queue = next_pkt; /*returning head of pkt queue. latest pkts are important*/ --gwlan_logging.fw_log_pkt_qcnt; spin_unlock_irqrestore(&gwlan_logging.fw_log_pkt_lock, flags); vos_pkt_return_packet(free_pkt); } else { spin_unlock_irqrestore(&gwlan_logging.fw_log_pkt_lock, flags); } spin_lock_irqsave(&gwlan_logging.fw_log_pkt_lock, flags); if (gwlan_logging.fw_log_pkt_queue) { vos_pkt_chain_packet(gwlan_logging.fw_log_pkt_queue, pPacket, TRUE); } else { gwlan_logging.fw_log_pkt_queue = pPacket; } ++gwlan_logging.fw_log_pkt_qcnt; spin_unlock_irqrestore(&gwlan_logging.fw_log_pkt_lock, flags); set_bit(LOGGER_FW_LOG_PKT_POST, &gwlan_logging.event_flag); wake_up_interruptible(&gwlan_logging.wait_queue); return VOS_STATUS_SUCCESS; }
VOS_STATUS WDA_DS_TxFrames ( v_PVOID_t pvosGCtx ) { VOS_STATUS vosStatus; vos_pkt_t *pTxMgmtChain = NULL; vos_pkt_t *pTxDataChain = NULL; vos_pkt_t *pTxPacket = NULL; v_BOOL_t bUrgent; wpt_uint32 ucTxResReq; WDI_Status wdiStatus; tWDA_CbContext *wdaContext = NULL; v_U32_t uMgmtAvailRes; v_U32_t uDataAvailRes; WLANTL_TxCompCBType pfnTxComp = NULL; v_U32_t uTxFailCount = 0; wdaContext = (tWDA_CbContext *)vos_get_context(VOS_MODULE_ID_WDA, pvosGCtx); if ( NULL == wdaContext ) { VOS_TRACE( VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_ERROR, "WDA:Invalid wda context pointer from pvosGCtx on WDA_DS_TxFrames" ); return VOS_STATUS_E_FAULT; } /*------------------------------------------------------------------------- Need to fetch separatelly for Mgmt and Data frames because TL is not aware of separate resource management at the lower levels -------------------------------------------------------------------------*/ /*Mgmt tx*/ uMgmtAvailRes = WDI_GetAvailableResCount(wdaContext->pWdiContext, WDI_MGMT_POOL_ID); ucTxResReq = WLANTL_GetFrames( pvosGCtx, &pTxMgmtChain, uMgmtAvailRes, (wdaContext->uTxFlowMask & WDA_HI_FLOW_MASK), &bUrgent ); // We need to initialize vsoStatus in case we don't enter the "while" // loop. If we don't enter the loop, it means that there are no packets, // available, and that is considered success. If we enter the loop, // vosStatus will be set appropriately inside the loop vosStatus = VOS_STATUS_SUCCESS; while ( NULL != pTxMgmtChain ) { /* Walk the chain and unchain the packet */ pTxPacket = pTxMgmtChain; vosStatus = vos_pkt_walk_packet_chain( pTxMgmtChain, &pTxMgmtChain, VOS_TRUE ); if( (VOS_STATUS_SUCCESS != vosStatus) && (VOS_STATUS_E_EMPTY != vosStatus) ) { VOS_TRACE( VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_ERROR, "WDA Walking packet chain returned status : %d", vosStatus ); VOS_ASSERT( 0 ); vosStatus = VOS_STATUS_E_FAILURE; break; } if ( VOS_STATUS_E_EMPTY == vosStatus ) { vosStatus = VOS_STATUS_SUCCESS; } wdiStatus = WDI_DS_TxPacket( wdaContext->pWdiContext, (wpt_packet*)pTxPacket, 0 /* more */ ); if ( WDI_STATUS_SUCCESS != wdiStatus ) { VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_WARN, "WDA : Pushing a packet to WDI failed." ); if ( WDI_STATUS_E_NOT_ALLOWED != wdiStatus ) { uTxFailCount++; } VOS_ASSERT( wdiStatus == WDI_STATUS_E_NOT_ALLOWED ); //We need to free the packet here vos_pkt_get_user_data_ptr(pTxPacket, VOS_PKT_USER_DATA_ID_TL, (void **)&pfnTxComp); if(pfnTxComp) { pfnTxComp(pvosGCtx, pTxPacket, VOS_STATUS_E_FAILURE); } } }; if ( uTxFailCount ) { VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR, "WDA : Tx fail count for mgmt pkts: %d.", uTxFailCount); uTxFailCount = 0; } /*Data tx*/ uDataAvailRes = WDI_GetAvailableResCount(wdaContext->pWdiContext, WDI_DATA_POOL_ID); ucTxResReq = WLANTL_GetFrames( pvosGCtx, &pTxDataChain, /*WDA_DS_DXE_RES_COUNT*/ uDataAvailRes, (wdaContext->uTxFlowMask & WDA_LO_FLOW_MASK), &bUrgent ); // We need to initialize vsoStatus in case we don't enter the "while" // loop. If we don't enter the loop, it means that there are no packets, // available, and that is considered success. If we enter the loop, // vosStatus will be set appropriately inside the loop vosStatus = VOS_STATUS_SUCCESS; while ( NULL != pTxDataChain ) { /* Walk the chain and unchain the packet */ pTxPacket = pTxDataChain; vosStatus = vos_pkt_walk_packet_chain( pTxDataChain, &pTxDataChain, VOS_TRUE ); if( (VOS_STATUS_SUCCESS != vosStatus) && (VOS_STATUS_E_EMPTY != vosStatus) ) { VOS_TRACE( VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_ERROR, "WDA Walking packet chain returned status : %d", vosStatus ); VOS_ASSERT( 0 ); vosStatus = VOS_STATUS_E_FAILURE; break; } if ( VOS_STATUS_E_EMPTY == vosStatus ) { vosStatus = VOS_STATUS_SUCCESS; } wdiStatus = WDI_DS_TxPacket( wdaContext->pWdiContext, (wpt_packet*)pTxPacket, 0 /* more */ ); if ( WDI_STATUS_SUCCESS != wdiStatus ) { VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_WARN, "WDA : Pushing a packet to WDI failed." ); if ( WDI_STATUS_E_NOT_ALLOWED != wdiStatus ) { uTxFailCount++; } VOS_ASSERT( wdiStatus == WDI_STATUS_E_NOT_ALLOWED ); //We need to free the packet here vos_pkt_get_user_data_ptr(pTxPacket, VOS_PKT_USER_DATA_ID_TL, (void **)&pfnTxComp); if(pfnTxComp) { pfnTxComp(pvosGCtx, pTxPacket, VOS_STATUS_E_FAILURE); } } }; if ( uTxFailCount ) { VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR, "WDA : Tx fail count for data pkts: %d.", uTxFailCount); } WDI_DS_TxComplete(wdaContext->pWdiContext, ucTxResReq); return vosStatus; }
/**============================================================================ @brief hdd_rx_packet_cbk() - Receive callback registered with TL. TL will call this to notify the HDD when one or more packets were received for a registered STA. @param vosContext : [in] pointer to VOS context @param pVosPacketChain : [in] pointer to VOS packet chain @param staId : [in] Station Id @param pRxMetaInfo : [in] pointer to meta info for the received pkt(s) @return : VOS_STATUS_E_FAILURE if any errors encountered, : VOS_STATUS_SUCCESS otherwise ===========================================================================*/ VOS_STATUS hdd_rx_packet_cbk( v_VOID_t *vosContext, vos_pkt_t *pVosPacketChain, v_U8_t staId, WLANTL_RxMetaInfoType* pRxMetaInfo ) { hdd_adapter_t *pAdapter = NULL; hdd_context_t *pHddCtx = NULL; VOS_STATUS status = VOS_STATUS_E_FAILURE; int rxstat; struct sk_buff *skb = NULL; vos_pkt_t* pVosPacket; vos_pkt_t* pNextVosPacket; //Sanity check on inputs if ( ( NULL == vosContext ) || ( NULL == pVosPacketChain ) || ( NULL == pRxMetaInfo ) ) { VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,"%s: Null params being passed", __FUNCTION__); return VOS_STATUS_E_FAILURE; } pHddCtx = (hdd_context_t *)vos_get_context( VOS_MODULE_ID_HDD, vosContext ); if ( NULL == pHddCtx ) { 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[staId]; if( NULL == pAdapter ) { VOS_ASSERT(0); return VOS_STATUS_E_FAILURE; } ++pAdapter->hdd_stats.hddTxRxStats.rxChains; // walk the chain until all are processed pVosPacket = pVosPacketChain; do { // get the pointer to the next packet in the chain // (but don't unlink the packet since we free the entire chain later) status = vos_pkt_walk_packet_chain( pVosPacket, &pNextVosPacket, VOS_FALSE); // both "success" and "empty" are acceptable results if (!((status == VOS_STATUS_SUCCESS) || (status == VOS_STATUS_E_EMPTY))) { ++pAdapter->hdd_stats.hddTxRxStats.rxDropped; VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,"%s: Failure walking packet chain", __FUNCTION__); return VOS_STATUS_E_FAILURE; } // Extract the OS packet (skb). // Tell VOS to detach the OS packet from the VOS packet status = vos_pkt_get_os_packet( pVosPacket, (v_VOID_t **)&skb, VOS_TRUE ); if(!VOS_IS_STATUS_SUCCESS( status )) { ++pAdapter->hdd_stats.hddTxRxStats.rxDropped; VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,"%s: Failure extracting skb from vos pkt", __FUNCTION__); return VOS_STATUS_E_FAILURE; } if (WLAN_HDD_ADAPTER_MAGIC != pAdapter->magic) { VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, "Magic cookie(%x) for adapter sanity verification is invalid", pAdapter->magic); return eHAL_STATUS_FAILURE; } skb->dev = pAdapter->dev; skb->protocol = eth_type_trans(skb, skb->dev); skb->ip_summed = CHECKSUM_NONE; ++pAdapter->hdd_stats.hddTxRxStats.rxPackets; ++pAdapter->stats.rx_packets; pAdapter->stats.rx_bytes += skb->len; #ifdef WLAN_FEATURE_HOLD_RX_WAKELOCK wake_lock_timeout(&pHddCtx->rx_wake_lock, HDD_WAKE_LOCK_DURATION); #endif rxstat = netif_rx_ni(skb); if (NET_RX_SUCCESS == rxstat) { ++pAdapter->hdd_stats.hddTxRxStats.rxDelivered; } else { ++pAdapter->hdd_stats.hddTxRxStats.rxRefused; } // now process the next packet in the chain pVosPacket = pNextVosPacket; } while (pVosPacket); //Return the entire VOS packet chain to the resource pool status = vos_pkt_return_packet( pVosPacketChain ); if(!VOS_IS_STATUS_SUCCESS( status )) { VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,"%s: Failure returning vos pkt", __FUNCTION__); } pAdapter->dev->last_rx = jiffies; return status; }
static int send_data_mgmt_log_pkt_to_user(void) { int ret = -1; int extra_header_len, nl_payload_len; struct sk_buff *skb = NULL; static int nlmsg_seq; vos_pkt_t *current_pkt; vos_pkt_t *next_pkt; VOS_STATUS status = VOS_STATUS_E_FAILURE; unsigned long flags; tAniNlLogHdr msg_header; do { spin_lock_irqsave(&gwlan_logging.data_mgmt_pkt_lock, flags); if (!gwlan_logging.data_mgmt_pkt_queue) { spin_unlock_irqrestore( &gwlan_logging.data_mgmt_pkt_lock, flags); return -EIO; } /* pick first pkt from queued chain */ current_pkt = gwlan_logging.data_mgmt_pkt_queue; /* get the pointer to the next packet in the chain */ status = vos_pkt_walk_packet_chain(current_pkt, &next_pkt, TRUE); /* both "success" and "empty" are acceptable results */ if (!((status == VOS_STATUS_SUCCESS) || (status == VOS_STATUS_E_EMPTY))) { ++gwlan_logging.pkt_drop_cnt; spin_unlock_irqrestore( &gwlan_logging.data_mgmt_pkt_lock, flags); pr_err("%s: Failure walking packet chain", __func__); return -EIO; } /* update queue head with next pkt ptr which could be NULL */ gwlan_logging.data_mgmt_pkt_queue = next_pkt; --gwlan_logging.data_mgmt_pkt_qcnt; spin_unlock_irqrestore(&gwlan_logging.data_mgmt_pkt_lock, flags); status = vos_pkt_get_os_packet(current_pkt, (v_VOID_t **)&skb, TRUE); if (!VOS_IS_STATUS_SUCCESS(status)) { ++gwlan_logging.pkt_drop_cnt; pr_err("%s: Failure extracting skb from vos pkt", __func__); return -EIO; } /*return vos pkt since skb is already detached */ vos_pkt_return_packet(current_pkt); extra_header_len = sizeof(msg_header.radio) + sizeof(tAniHdr) + sizeof(msg_header.frameSize); nl_payload_len = NLMSG_ALIGN(extra_header_len + skb->len); msg_header.nlh.nlmsg_type = ANI_NL_MSG_LOG; msg_header.nlh.nlmsg_len = nl_payload_len; msg_header.nlh.nlmsg_flags = NLM_F_REQUEST; msg_header.nlh.nlmsg_pid = 0; msg_header.nlh.nlmsg_seq = nlmsg_seq++; msg_header.radio = 0; msg_header.wmsg.type = ANI_NL_MSG_LOG_PKT_TYPE; msg_header.wmsg.length = skb->len + sizeof(uint32); msg_header.frameSize = WLAN_MGMT_LOGGING_FRAMESIZE_128BYTES; if (unlikely(skb_headroom(skb) < sizeof(msg_header))) { pr_err("VPKT [%d]: Insufficient headroom, head[%p]," " data[%p], req[%zu]", __LINE__, skb->head, skb->data, sizeof(msg_header)); return -EIO; } vos_mem_copy(skb_push(skb, sizeof(msg_header)), &msg_header, sizeof(msg_header)); ret = nl_srv_bcast(skb); if (ret < 0) { pr_info("%s: Send Failed %d drop_count = %u\n", __func__, ret, ++gwlan_logging.pkt_drop_cnt); } else { ret = 0; } } while (next_pkt); return ret; }