WPT_STATIC WPT_INLINE void* itGetOSPktAddrFromDevice( wpt_packet *pPacket ) { struct sk_buff *skb; /*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ if ( VOS_STATUS_SUCCESS != vos_pkt_get_os_packet(WPAL_TO_VOS_PKT(pPacket), (void**)&skb, VOS_FALSE )) { return NULL; } else { if(skb->data == skb->tail) { #ifdef WLAN_BUG_ON_SKB_ERROR wpalDevicePanic(); #else WPAL_TRACE(eWLAN_MODULE_PAL, eWLAN_PAL_TRACE_LEVEL_FATAL, "%s: skb->data == skb->tail. Attempting recovery " "skb:%p, head:%p, tail:%p, data:%p", __func__, skb, skb->head, skb->tail, skb->data); skb->data = skb->head; #endif } /*Map skb data into dma-able memory (changes will be commited from cache) */ return (void*)dma_map_single( NULL, skb->data, skb->len, DMA_FROM_DEVICE ); } }/*itGetOSPktAddrFromDevice*/
/**============================================================================ @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; }
/* Set of helper functions that will prepare packet for DMA transfer, based on the type of transfer : - to and from the device - following these calls the packet will be locked for DMA only, CPU will not be able to modify it => the packet must be explicitly returned to the CPU once the DMA transfer is complete */ WPT_STATIC WPT_INLINE void* itGetOSPktAddrForDevice( wpt_packet *pPacket ) { struct sk_buff *skb; /*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ if ( VOS_STATUS_SUCCESS != vos_pkt_get_os_packet(WPAL_TO_VOS_PKT(pPacket), (void**)&skb, VOS_FALSE )) { return NULL; } else { /*Map skb data into dma-able memory (changes will be commited from cache) */ return (void*)dma_map_single( NULL, skb->data, skb->len, DMA_TO_DEVICE ); } }/*itGetOSPktAddrForDevice*/
WPT_STATIC WPT_INLINE void* itGetOSPktAddrForDevice( wpt_packet *pPacket ) { struct sk_buff *skb; /* */ if ( VOS_STATUS_SUCCESS != vos_pkt_get_os_packet(WPAL_TO_VOS_PKT(pPacket), (void**)&skb, VOS_FALSE )) { return NULL; } else { /* */ return (void*)dma_map_single( NULL, skb->data, skb->len, DMA_TO_DEVICE ); } }/* */
/**============================================================================ @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; }