/*--------------------------------------------------------------------------- wpalPacketGetLength – Get number of bytes in a wpt_packet. It include the bytes in a BD if it exist. Param: pPkt - pointer to a packet to be freed. Return: Length of the data include layer-2 headers. For example, if the frame is 802.3, the length includes the ethernet header. ---------------------------------------------------------------------------*/ wpt_uint32 wpalPacketGetLength(wpt_packet *pPkt) { v_U16_t len = 0, pktLen = 0; // Validate the parameter pointers if (unlikely(NULL == pPkt)) { WPAL_TRACE(eWLAN_MODULE_PAL, eWLAN_PAL_TRACE_LEVEL_ERROR, "%s : NULL packet pointer", __func__); return eWLAN_PAL_STATUS_E_INVAL; } if( WPAL_PACKET_GET_BD_POINTER(pPkt) ) { len = WPAL_PACKET_GET_BD_LENGTH(pPkt); } if( VOS_IS_STATUS_SUCCESS(vos_pkt_get_packet_length(WPAL_TO_VOS_PKT(pPkt), &pktLen)) ) { len += pktLen; } else { WPAL_TRACE(eWLAN_MODULE_PAL, eWLAN_PAL_TRACE_LEVEL_ERROR, "%s failed", __func__); } return ((wpt_uint32)len); }/*wpalPacketGetLength*/
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*/
/*--------------------------------------------------------------------------- wpalPacketSetRxLength – Set the valid data length on a RX packet. This function must be called once per RX packet per receiving. It indicates the available data length from the start of the buffer. Param: pPkt - pointer to a wpt_packet. Return: NULL - fail. Otherwise the address of the starting of the buffer ---------------------------------------------------------------------------*/ wpt_status wpalPacketSetRxLength(wpt_packet *pPkt, wpt_uint32 len) { // Validate the parameter pointers if (unlikely(NULL == pPkt)) { WPAL_TRACE(eWLAN_MODULE_PAL, eWLAN_PAL_TRACE_LEVEL_ERROR, "%s : NULL packet pointer", __func__); return eWLAN_PAL_STATUS_E_INVAL; } /*Only allowed for RX Raw packets */ if( (eWLAN_PAL_PKT_TYPE_RX_RAW != WPAL_PACKET_GET_TYPE(pPkt))) { WPAL_TRACE(eWLAN_MODULE_PAL, eWLAN_PAL_TRACE_LEVEL_ERROR, "%s Invalid packet type(%d)", __func__, WPAL_PACKET_GET_TYPE(pPkt)); return eWLAN_PAL_STATUS_E_INVAL; } if(VOS_IS_STATUS_SUCCESS(vos_pkt_set_rx_length(WPAL_TO_VOS_PKT(pPkt), len))) { return eWLAN_PAL_STATUS_SUCCESS; } else { return eWLAN_PAL_STATUS_E_INVAL; } }/*wpalPacketSetRxLength*/
/*--------------------------------------------------------------------------- wpalPacketRawTrimTail – reduce the length of the packet. Param: pPkt - pointer to a wpt_packet. size – number of bytes to take of the packet length Return: eWLAN_PAL_STATUS_SUCCESS – success. Otherwise fail. ---------------------------------------------------------------------------*/ wpt_status wpalPacketRawTrimTail(wpt_packet *pPkt, wpt_uint32 size) { wpt_status status = eWLAN_PAL_STATUS_SUCCESS; // Validate the parameter pointers if (unlikely(NULL == pPkt)) { WPAL_TRACE(eWLAN_MODULE_PAL, eWLAN_PAL_TRACE_LEVEL_ERROR, "%s : NULL packet pointer", __func__); return eWLAN_PAL_STATUS_E_INVAL; } if ((eWLAN_PAL_PKT_TYPE_TX_802_11_MGMT == WPAL_PACKET_GET_TYPE(pPkt)) || (eWLAN_PAL_PKT_TYPE_RX_RAW == WPAL_PACKET_GET_TYPE(pPkt))) { // Continue to trim the packet } else { WPAL_TRACE(eWLAN_MODULE_PAL, eWLAN_PAL_TRACE_LEVEL_ERROR, "%s : neither 80211 managment packet nor RAW packet", __func__); VOS_ASSERT(0); return eWLAN_PAL_STATUS_E_INVAL; } if( !VOS_IS_STATUS_SUCCESS(vos_pkt_trim_tail(WPAL_TO_VOS_PKT(pPkt), (v_SIZE_t)size)) ) { WPAL_TRACE(eWLAN_MODULE_PAL, eWLAN_PAL_TRACE_LEVEL_ERROR, "%s Invalid trim(%d)", __func__, size); status = eWLAN_PAL_STATUS_E_INVAL; } return status; }/*wpalPacketRawTrimTail*/
/*--------------------------------------------------------------------------- wpalPacketFree – Free a wpt_packet chain for one particular type. For our legacy UMAC, it is not needed because vos_packet contains pal_packet. Param: pPkt – pointer to a wpt_packet Return: eWLAN_PAL_STATUS_SUCCESS - success ---------------------------------------------------------------------------*/ wpt_status wpalPacketFree(wpt_packet *pPkt) { VOS_STATUS vosStatus; if(NULL != pPkt->pInternalData) { wpalMemoryFree(pPkt->pInternalData); } vosStatus = vos_pkt_return_packet(WPAL_TO_VOS_PKT(pPkt)); //With VOSS support, we can cast between wpt_status and VOS_STATUS return (wpt_status)vosStatus; }/*wpalPacketFree*/
wpt_status wpalPacketFree(wpt_packet *pPkt) { VOS_STATUS vosStatus; if(NULL != pPkt->pInternalData) { wpalMemoryFree(pPkt->pInternalData); } vosStatus = vos_pkt_return_packet(WPAL_TO_VOS_PKT(pPkt)); // return (wpt_status)vosStatus; }/* */
/* 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 ); } }/* */
/*--------------------------------------------------------------------------- wpalPacketGetRawBuf – Return the starting buffer virtual address for the RAW flat buffer It is inline in hope of faster implementation for certain platform. For Winxp, it will be slow. Param: pPkt - pointer to a wpt_packet. Return: NULL - fail. Otherwise the address of the starting of the buffer ---------------------------------------------------------------------------*/ wpt_uint8 *wpalPacketGetRawBuf(wpt_packet *pPkt) { wpt_uint8 *pRet = NULL; // Validate the parameter pointers if (unlikely(NULL == pPkt)) { WPAL_TRACE(eWLAN_MODULE_PAL, eWLAN_PAL_TRACE_LEVEL_ERROR, "%s : NULL packet pointer", __func__); return NULL; } //Since it is a flat buffer, all we need is to get one byte of offset 0 if( (eWLAN_PAL_PKT_TYPE_RX_RAW == WPAL_PACKET_GET_TYPE(pPkt)) || (eWLAN_PAL_PKT_TYPE_TX_802_11_MGMT == WPAL_PACKET_GET_TYPE(pPkt)) ) { vos_pkt_peek_data(WPAL_TO_VOS_PKT(pPkt), 0, (v_VOID_t**)&pRet, 1); WPAL_ASSERT(NULL != pRet); } return pRet; }/*wpalPacketGetRawBuf*/
wpt_uint8 *wpalPacketGetRawBuf(wpt_packet *pPkt) { wpt_uint8 *pRet = NULL; // if (unlikely(NULL == pPkt)) { WPAL_TRACE(eWLAN_MODULE_PAL, eWLAN_PAL_TRACE_LEVEL_ERROR, "%s : NULL packet pointer", __func__); return NULL; } // if( (eWLAN_PAL_PKT_TYPE_RX_RAW == WPAL_PACKET_GET_TYPE(pPkt)) || (eWLAN_PAL_PKT_TYPE_TX_802_11_MGMT == WPAL_PACKET_GET_TYPE(pPkt)) ) { vos_pkt_peek_data(WPAL_TO_VOS_PKT(pPkt), 0, (v_VOID_t**)&pRet, 1); WPAL_ASSERT(NULL != pRet); } return pRet; }/* */
/*--------------------------------------------------------------------------- wpalLockPacketForTransfer – Map the data buffer from dma so that the data is commited from cache and the cpu relinquishes ownership of the buffer Param: pPacket – pointer to a wpt_packet Return: eWLAN_PAL_STATUS_SUCCESS - success ---------------------------------------------------------------------------*/ wpt_status wpalLockPacketForTransfer( wpt_packet *pPacket) { void* pPhyData = NULL; wpt_iterator_info* pInfo = NULL; v_U16_t uLenData = 0; // Validate the parameter pointers if (unlikely(NULL == pPacket)) { WPAL_TRACE(eWLAN_MODULE_PAL, eWLAN_PAL_TRACE_LEVEL_ERROR, "%s : NULL input pointer", __func__); return eWLAN_PAL_STATUS_E_INVAL; } switch(WPAL_PACKET_GET_TYPE(pPacket)) { /* For management frames, BD is allocated by WDI, header is in raw buffer, rest of the frame is also in raw buffer */ case eWLAN_PAL_PKT_TYPE_TX_802_11_MGMT: { /*TX Packets need to be DMA-ed to the device, perform DMA mapping accordingly */ pPhyData = (void*)itGetOSPktAddrForDevice( pPacket ); } break; /* Data packets - BD (allocated by WDI), header (in VOSS header), rest of the packet (DSM items) */ case eWLAN_PAL_PKT_TYPE_TX_802_11_DATA: case eWLAN_PAL_PKT_TYPE_TX_802_3_DATA: { /*TX Packets need to be DMA-ed to the device, perform DMA mapping accordingly */ pPhyData = (void*)itGetOSPktAddrForDevice( pPacket ); } break; /* For Raw RX, BD + header + rest of the packet is all contained in the raw buffer */ case eWLAN_PAL_PKT_TYPE_RX_RAW: { /*RX Packets need to be DMA-ed from the device, perform DMA mapping accordingly */ pPhyData = (void*)itGetOSPktAddrFromDevice( pPacket ); } break; default: { WPAL_TRACE(eWLAN_MODULE_PAL, eWLAN_PAL_TRACE_LEVEL_ERROR, " WLAN_PAL: %s: Invalid packet type %d!", __func__, WPAL_PACKET_GET_TYPE(pPacket) ); WPAL_ASSERT(0); return eWLAN_PAL_STATUS_E_FAILURE; } } /*Get packet length*/ vos_pkt_get_packet_length(WPAL_TO_VOS_PKT(pPacket),&uLenData); /*Allocate memory for the current info*/ pInfo = wpalMemoryAllocate( sizeof(wpt_iterator_info) ); // Validate the memory allocation if (unlikely(NULL == pInfo)) { WPAL_TRACE(eWLAN_MODULE_PAL, eWLAN_PAL_TRACE_LEVEL_ERROR, "%s : Failed to allocate memory ", __func__); return eWLAN_PAL_STATUS_E_INVAL; } pInfo->pPhyAddr = pPhyData; pInfo->uLen = uLenData; pPacket->pInternalData = pInfo; return eWLAN_PAL_STATUS_SUCCESS; }/*wpalLockPacketForTransfer*/
wpt_status wpalLockPacketForTransfer( wpt_packet *pPacket) { void* pPhyData = NULL; wpt_iterator_info* pInfo = NULL; v_U16_t uLenData = 0; // if (unlikely(NULL == pPacket)) { WPAL_TRACE(eWLAN_MODULE_PAL, eWLAN_PAL_TRACE_LEVEL_ERROR, "%s : NULL input pointer", __func__); return eWLAN_PAL_STATUS_E_INVAL; } switch(WPAL_PACKET_GET_TYPE(pPacket)) { /* */ case eWLAN_PAL_PKT_TYPE_TX_802_11_MGMT: { /* */ pPhyData = (void*)itGetOSPktAddrForDevice( pPacket ); } break; /* */ case eWLAN_PAL_PKT_TYPE_TX_802_11_DATA: case eWLAN_PAL_PKT_TYPE_TX_802_3_DATA: { /* */ pPhyData = (void*)itGetOSPktAddrForDevice( pPacket ); } break; /* */ case eWLAN_PAL_PKT_TYPE_RX_RAW: { /* */ pPhyData = (void*)itGetOSPktAddrFromDevice( pPacket ); } break; default: { WPAL_TRACE(eWLAN_MODULE_PAL, eWLAN_PAL_TRACE_LEVEL_ERROR, " WLAN_PAL: %s: Invalid packet type %d!", __func__, WPAL_PACKET_GET_TYPE(pPacket) ); WPAL_ASSERT(0); return eWLAN_PAL_STATUS_E_FAILURE; } } /* */ vos_pkt_get_packet_length(WPAL_TO_VOS_PKT(pPacket),&uLenData); /* */ pInfo = wpalMemoryAllocate( sizeof(wpt_iterator_info) ); // if (unlikely(NULL == pInfo)) { WPAL_TRACE(eWLAN_MODULE_PAL, eWLAN_PAL_TRACE_LEVEL_ERROR, "%s : Failed to allocate memory ", __func__); return eWLAN_PAL_STATUS_E_INVAL; } pInfo->pPhyAddr = pPhyData; pInfo->uLen = uLenData; pPacket->pInternalData = pInfo; return eWLAN_PAL_STATUS_SUCCESS; }/* */