WDI_Status WDI_STATableDelSta ( WDI_ControlBlockType* pWDICtx, wpt_uint8 ucSTAIdx ) { WDI_StaStruct* pSTATable = (WDI_StaStruct*) pWDICtx->staTable; if(( ucSTAIdx == WDI_STA_INVALID_IDX )|| ( ucSTAIdx >= pWDICtx->ucMaxStations )) { WPAL_TRACE(eWLAN_MODULE_DAL_CTRL, eWLAN_PAL_TRACE_LEVEL_ERROR, "STA Id invalid on Del STA - internal failure"); WDI_ASSERT(0); return WDI_STATUS_E_FAILURE; } wpalMemoryZero(&pSTATable[ucSTAIdx], sizeof(pSTATable[ucSTAIdx])); pSTATable->valid = 0; return WDI_STATUS_SUCCESS; }
/** * @brief wpalDmaMemoryAllocate - Allocate memory ready for DMA. Aligned at 4-byte * @param size number of bytes to allocate * @param ppPhysicalAddr Physical address of the buffer if allocation succeeds * * @return void* A pointer to the allocated memory (virtual address). * NULL - fail to allocate memory */ void *wpalDmaMemoryAllocate(wpt_uint32 size, void **ppPhysicalAddr) { void *pv = NULL; dma_addr_t PhyAddr; wpt_uint32 uAllocLen = size + sizeof(tPalDmaMemInfo); pv = dma_alloc_coherent(NULL, uAllocLen, &PhyAddr, GFP_KERNEL); if ( NULL == pv ) { WPAL_TRACE(eWLAN_MODULE_PAL, eWLAN_PAL_TRACE_LEVEL_ERROR, "%s Unable to allocate DMA buffer\n", __func__); return NULL; } ((tPalDmaMemInfo *)pv)->length = uAllocLen; ((tPalDmaMemInfo *)pv)->phyAddr = PhyAddr; ((tPalDmaMemInfo *)pv)->offset = sizeof(tPalDmaMemInfo); pv = (wpt_byte *)pv + sizeof(tPalDmaMemInfo); *ppPhysicalAddr = (void*)PhyAddr + sizeof(tPalDmaMemInfo); return (pv); }/*wpalDmaMemoryAllocate*/
/** @brief wpalDisableInterrupt provides a mechansim for a client to request that a given interrupt be disabled The DXE interface supports two interrupts, TX Complete and RX Available. This interface provides the mechanism whereby a client can request that the platform-specific adaptation layer not allow a given interrupt to occur. The expectation is that if a given interrupt is not enabled, if the interrupt occurs then the APPS CPU will not be interrupted. @param intType: Enumeration of the interrupt type (TX or RX) @return SUCCESS if the interrupt was disabled */ wpt_status wpalDisableInterrupt ( wpt_uint32 intType ) { switch (intType) { case DXE_INTERRUPT_RX_READY: disable_irq_nosync(gpEnv->rx_irq); break; case DXE_INTERRUPT_TX_COMPLE: disable_irq_nosync(gpEnv->tx_irq); break; default: WPAL_TRACE(eWLAN_MODULE_DAL_DATA, eWLAN_PAL_TRACE_LEVEL_ERROR, "%s: unknown interrupt: %d", __func__, (int)intType); break; } /* on the integrated platform there is no platform-specific interrupt control */ return eWLAN_PAL_STATUS_SUCCESS; }
/** @brief Callback function for serializing WCTS Read processing in the control context @param pWCTSCb WCTS Control Block @see @return void */ static void WCTS_PALReadCallback ( WCTS_ControlBlockType* pWCTSCb ) { void* buffer; int packet_size; int available; int bytes_read; /*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ /*-------------------------------------------------------------------- Sanity check --------------------------------------------------------------------*/ if ((NULL == pWCTSCb) || (WCTS_CB_MAGIC != pWCTSCb->wctsMagic)) { WPAL_TRACE(eWLAN_MODULE_DAL_CTRL, eWLAN_PAL_TRACE_LEVEL_ERROR, "WCTS_PALReadCallback: Invalid parameter received."); return; } /* iterate until no more packets are available */ while (1) { /* check the length of the next packet */ packet_size = smd_cur_packet_size(pWCTSCb->wctsChannel); if (0 == packet_size) { /* No more data to be read */ return; } /* Check how much of the data is available */ available = smd_read_avail(pWCTSCb->wctsChannel); if (available < packet_size) { /* Entire packet not yet ready to be read -- There will be another notification when it is ready */ return; } buffer = wpalMemoryAllocate(packet_size); if (NULL == buffer) { WPAL_TRACE(eWLAN_MODULE_DAL_CTRL, eWLAN_PAL_TRACE_LEVEL_ERROR, "WCTS_PALReadCallback: Memory allocation failure"); WPAL_ASSERT(0); return; } bytes_read = smd_read(pWCTSCb->wctsChannel, buffer, packet_size); if (bytes_read != packet_size) { /*Some problem, do not forward it to WDI.*/ WPAL_TRACE(eWLAN_MODULE_DAL_CTRL, eWLAN_PAL_TRACE_LEVEL_ERROR, "WCTS_PALReadCallback: Failed to read data from SMD"); wpalMemoryFree(buffer); WPAL_ASSERT(0); return; } /* forward the message to the registered handler */ pWCTSCb->wctsRxMsgCB((WCTS_HandleType)pWCTSCb, buffer, packet_size, pWCTSCb->wctsRxMsgCBData); /* Free the allocated buffer*/ wpalMemoryFree(buffer); } } /*WCTS_PALReadCallback*/
WDI_Status WDI_DS_TxPacket(void *pContext, wpt_packet *pFrame, wpt_boolean more) { WDI_DS_ClientDataType *pClientData; wpt_uint8 ucSwFrameTXXlation; wpt_uint8 ucUP; wpt_uint8 ucTypeSubtype; wpt_uint8 isEapol; wpt_uint8 alignment; wpt_uint8 ucTxFlag; wpt_uint8 ucProtMgmtFrame; wpt_uint8* pSTAMACAddress; wpt_uint8* pAddr2MACAddress; WDI_DS_TxMetaInfoType *pTxMetadata; void *physBDHeader, *pvBDHeader; wpt_uint8 ucType; WDI_DS_BdMemPoolType *pMemPool; wpt_uint8 ucBdPoolType; wpt_uint8 staId; WDI_Status wdiStatus; // Do Sanity checks if (NULL == pContext) { return WDI_STATUS_E_FAILURE; } pClientData = (WDI_DS_ClientDataType *) WDI_DS_GetDatapathContext(pContext); if (NULL == pClientData || pClientData->suspend) { return WDI_STATUS_E_FAILURE; } // extract metadata from PAL packet pTxMetadata = WDI_DS_ExtractTxMetaData(pFrame); ucSwFrameTXXlation = pTxMetadata->fdisableFrmXlt; ucTypeSubtype = pTxMetadata->typeSubtype; ucUP = pTxMetadata->fUP; isEapol = pTxMetadata->isEapol; ucTxFlag = pTxMetadata->txFlags; ucProtMgmtFrame = pTxMetadata->fProtMgmtFrame; pSTAMACAddress = &(pTxMetadata->fSTAMACAddress[0]); pAddr2MACAddress = &(pTxMetadata->addr2MACAddress[0]); /*------------------------------------------------------------------------ Get type and subtype of the frame first ------------------------------------------------------------------------*/ ucType = (ucTypeSubtype & WDI_FRAME_TYPE_MASK) >> WDI_FRAME_TYPE_OFFSET; switch(ucType) { case WDI_MAC_DATA_FRAME: #ifdef FEATURE_WLAN_TDLS /* I utilizes TDLS mgmt frame always sent at BD_RATE2. (See limProcessTdls.c) Assumption here is data frame sent by WDA_TxPacket() <- HalTxFrame/HalTxFrameWithComplete() should take managment path. As of today, only TDLS feature has special data frame which needs to be treated as mgmt. */ if((!pTxMetadata->isEapol) && ((pTxMetadata->txFlags & WDI_USE_BD_RATE2_FOR_MANAGEMENT_FRAME) != WDI_USE_BD_RATE2_FOR_MANAGEMENT_FRAME)) #else if(!pTxMetadata->isEapol) #endif { pMemPool = &(pClientData->dataMemPool); ucBdPoolType = WDI_DATA_POOL_ID; break; } // intentional fall-through to handle eapol packet as mgmt case WDI_MAC_MGMT_FRAME: pMemPool = &(pClientData->mgmtMemPool); ucBdPoolType = WDI_MGMT_POOL_ID; break; default: return WDI_STATUS_E_FAILURE; } // Allocate BD header from pool pvBDHeader = WDI_DS_MemPoolAlloc(pMemPool, &physBDHeader, ucBdPoolType); if(NULL == pvBDHeader) return WDI_STATUS_E_FAILURE; WDI_SetBDPointers(pFrame, pvBDHeader, physBDHeader); alignment = 0; WDI_DS_PrepareBDHeader(pFrame, ucSwFrameTXXlation, alignment); if (pTxMetadata->isEapol) { WPAL_TRACE( eWLAN_MODULE_DAL_CTRL, eWLAN_PAL_TRACE_LEVEL_INFO, "Packet Length is %d\n", pTxMetadata->fPktlen); } wdiStatus = WDI_FillTxBd(pContext, ucTypeSubtype, pSTAMACAddress, pAddr2MACAddress, &ucUP, 1, pvBDHeader, ucTxFlag /* No ACK */, ucProtMgmtFrame, 0, isEapol, &staId); if(WDI_STATUS_SUCCESS != wdiStatus) { WDI_DS_MemPoolFree(pMemPool, pvBDHeader, physBDHeader); return wdiStatus; } pTxMetadata->staIdx = staId; // Send packet to transport layer. if(eWLAN_PAL_STATUS_SUCCESS !=WDTS_TxPacket(pContext, pFrame)){ WDI_DS_MemPoolFree(pMemPool, pvBDHeader, physBDHeader); return WDI_STATUS_E_FAILURE; } /* resource count only for data packet */ // EAPOL packet doesn't use data mem pool if being treated as higher priority #ifdef FEATURE_WLAN_TDLS /* I utilizes TDLS mgmt frame always sent at BD_RATE2. (See limProcessTdls.c) Assumption here is data frame sent by WDA_TxPacket() <- HalTxFrame/HalTxFrameWithComplete() should take managment path. As of today, only TDLS feature has special data frame which needs to be treated as mgmt. */ if((WDI_MAC_DATA_FRAME == ucType) && (!pTxMetadata->isEapol) && ((pTxMetadata->txFlags & WDI_USE_BD_RATE2_FOR_MANAGEMENT_FRAME) != WDI_USE_BD_RATE2_FOR_MANAGEMENT_FRAME)) #else if(WDI_MAC_DATA_FRAME == ucType && (!pTxMetadata->isEapol)) #endif { WDI_DS_MemPoolIncreaseReserveCount(pMemPool, staId); } return WDI_STATUS_SUCCESS; }
/*--------------------------------------------------------------------------- wpalUnlockPacket – Unmap the data buffer from dma so that cpu can regain ownership on it Param: pPacket – pointer to a wpt_packet Return: eWLAN_PAL_STATUS_SUCCESS - success ---------------------------------------------------------------------------*/ wpt_status wpalUnlockPacket( wpt_packet *pPacket) { wpt_iterator_info* pInfo; // Validate the parameter pointers if (unlikely(NULL == pPacket)) { WPAL_TRACE(eWLAN_MODULE_PAL, eWLAN_PAL_TRACE_LEVEL_ERROR, "%s : NULL input pointer pPacket", __func__); return eWLAN_PAL_STATUS_E_INVAL; } pInfo = (wpt_iterator_info*)pPacket->pInternalData; // Validate pInfo if (unlikely(NULL == pInfo)) { WPAL_TRACE(eWLAN_MODULE_PAL, eWLAN_PAL_TRACE_LEVEL_FATAL, "%s : NULL input pointer pInfo", __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 */ itReturnOSPktAddrForDevice(pPacket, pInfo->pPhyAddr, pInfo->uLen); } 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 */ itReturnOSPktAddrForDevice(pPacket, pInfo->pPhyAddr, pInfo->uLen); } 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 */ if(NULL == pInfo->pPhyAddr) { WPAL_TRACE(eWLAN_MODULE_PAL, eWLAN_PAL_TRACE_LEVEL_ERROR, " WLAN_PAL: %s: RX frame was not locked properly", __func__); } else { itReturnOSPktAddrFromDevice(pPacket, pInfo->pPhyAddr, pInfo->uLen); } } 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; } } wpalMemoryFree(pInfo); pPacket->pInternalData = NULL; return eWLAN_PAL_STATUS_SUCCESS; }/*wpalUnlockPacket*/
/*--------------------------------------------------------------------------- wpalPacketAlloc – Allocate a wpt_packet from PAL. Param: pktType – specify the type of wpt_packet to allocate nPktSize - packet size Return: A pointer to the wpt_packet. NULL means fail. ---------------------------------------------------------------------------*/ wpt_packet * wpalPacketAlloc(wpt_packet_type pktType, wpt_uint32 nPktSize, wpalPacketLowPacketCB rxLowCB, void *usrData) { VOS_STATUS vosStatus = VOS_STATUS_E_FAILURE; wpt_packet* pPkt = NULL; vos_pkt_t* pVosPkt = NULL; void* pData = NULL; v_U16_t allocLen; /*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ switch (pktType) { case eWLAN_PAL_PKT_TYPE_TX_802_11_MGMT: vosStatus = vos_pkt_get_packet(&pVosPkt, VOS_PKT_TYPE_TX_802_11_MGMT, nPktSize, 1, VOS_FALSE, NULL, NULL /*no callback*/); break; case eWLAN_PAL_PKT_TYPE_RX_RAW: /* Set the wpalPacketAvailableCB before we try to get a VOS * packet from the 'free list' and reset it if vos_pkt_get_packet() * returns a valid packet. This order is required to avoid the * race condition: * 1. The below call to vos_pkt_get_packet() in RX_Thread determines * that no more packets are available in the 'free list' and sets * the low resource callbacks. * 2. in parallel vos_pkt_return_packet() is called in MC_Thread for a * Management frame before wpalPacketAlloc() gets a chance to set * wpalPacketAvailableCB and since the 'low resource callbacks' * are set the callback function - wpalPacketRXLowResourceCB is * executed,but since wpalPacketAvailableCB is still NULL the low * resource recovery fails. */ wpalPacketAvailableCB = rxLowCB; vosStatus = vos_pkt_get_packet(&pVosPkt, VOS_PKT_TYPE_RX_RAW, nPktSize, 1, VOS_FALSE, wpalPacketRXLowResourceCB, usrData); #ifndef FEATURE_R33D /* Reserve the entire raw rx buffer for DXE */ if( vosStatus == VOS_STATUS_SUCCESS ) { wpalPacketAvailableCB = NULL; vosStatus = vos_pkt_reserve_head_fast( pVosPkt, &pData, nPktSize ); } #endif /* FEATURE_R33D */ if((NULL != pVosPkt) && (VOS_STATUS_E_RESOURCES != vosStatus)) { vos_pkt_get_packet_length(pVosPkt, &allocLen); if (nPktSize != allocLen) { WPAL_TRACE(eWLAN_MODULE_PAL, eWLAN_PAL_TRACE_LEVEL_ERROR, "RX packet alloc has problem, discard this frame, Len %d", allocLen); vos_pkt_return_packet(pVosPkt); return NULL; } } break; default: WPAL_TRACE(eWLAN_MODULE_PAL, eWLAN_PAL_TRACE_LEVEL_ERROR, " try to allocate unsupported packet type (%d)", pktType); break; } if(VOS_IS_STATUS_SUCCESS(vosStatus)) { pPkt = (wpt_packet *)pVosPkt; } return pPkt; }/*wpalPacketAlloc*/
/** @brief This function is used by the DAL Core to to send a message over to the WLAN sub-system. Once a buffer has been passed into the Send Message API, CT takes full ownership of it and it is responsible for freeing the associated resources. (This prevents a memcpy in case of a deferred write) The messages transported through the CT on both RX and TX are flat memory buffers that can be accessed and manipulated through standard memory functions. @param wctsHandlehandle: received upon open pMsg: the message to be sent uLen: the length of the message @see @return 0 for success */ wpt_uint32 WCTS_SendMessage ( WCTS_HandleType wctsHandle, void* pMsg, wpt_uint32 uLen ) { WCTS_ControlBlockType* pWCTSCb = (WCTS_ControlBlockType*) wctsHandle; WCTS_BufferType* pBufferQueue; int len; int written = 0; int available; /*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ /*-------------------------------------------------------------------- Sanity check --------------------------------------------------------------------*/ if ((NULL == pWCTSCb) || (WCTS_CB_MAGIC != pWCTSCb->wctsMagic) || (NULL == pMsg) || (0 == uLen) || (0x7fffffff < uLen)) { WPAL_TRACE(eWLAN_MODULE_DAL_CTRL, eWLAN_PAL_TRACE_LEVEL_ERROR, "WCTS_SendMessage: Invalid parameters received."); WPAL_ASSERT(0); if (NULL != pMsg) { wpalMemoryFree(pMsg); } return eWLAN_PAL_STATUS_E_INVAL; } /* the SMD API uses int instead of uint, so change types here */ len = (int)uLen; if (WCTS_STATE_OPEN == pWCTSCb->wctsState) { available = smd_write_avail(pWCTSCb->wctsChannel); if (available >= len) { written = smd_write(pWCTSCb->wctsChannel, pMsg, len); } } else if (WCTS_STATE_DEFERRED == pWCTSCb->wctsState) { WPAL_TRACE(eWLAN_MODULE_DAL_CTRL, eWLAN_PAL_TRACE_LEVEL_INFO, "WCTS_SendMessage: FIFO space not available, the packets will be queued"); } else { WPAL_TRACE(eWLAN_MODULE_DAL_CTRL, eWLAN_PAL_TRACE_LEVEL_ERROR, "WCTS_SendMessage: Channel in illegal state [%d].", pWCTSCb->wctsState); /* force following logic to reclaim the buffer */ written = -1; } if (-1 == written) { /*Something wrong*/ WPAL_TRACE(eWLAN_MODULE_DAL_CTRL, eWLAN_PAL_TRACE_LEVEL_ERROR, "WCTS_SendMessage: Failed to send message over the bus."); wpalMemoryFree(pMsg); WPAL_ASSERT(0); return eWLAN_PAL_STATUS_E_FAILURE; } else if (written == len) { /* Message sent! No deferred state, free the buffer*/ wpalMemoryFree(pMsg); } else { /* This much data cannot be written at this time, queue the rest of the data for later*/ pBufferQueue = wpalMemoryAllocate(sizeof(WCTS_BufferType)); if (NULL == pBufferQueue) { WPAL_TRACE(eWLAN_MODULE_DAL_CTRL, eWLAN_PAL_TRACE_LEVEL_ERROR, "WCTS_SendMessage: Cannot allocate memory for queuing the buffer"); wpalMemoryFree(pMsg); WPAL_ASSERT(0); return eWLAN_PAL_STATUS_E_NOMEM; } pBufferQueue->bufferSize = len; pBufferQueue->pBuffer = pMsg; wpal_list_insert_back(&pWCTSCb->wctsPendingQueue, &pBufferQueue->node); /* if we are not already in the deferred state, then transition to that state. when we do so, we enable the remote read interrupt so that we'll be notified when messages are read from the remote end */ if (WCTS_STATE_DEFERRED != pWCTSCb->wctsState) { /* Mark the state as deferred. Later: We may need to protect wctsState by locks*/ pWCTSCb->wctsState = WCTS_STATE_DEFERRED; smd_enable_read_intr(pWCTSCb->wctsChannel); } /*indicate to client that message was placed in deferred queue*/ return eWLAN_PAL_STATUS_E_RESOURCES; } return eWLAN_PAL_STATUS_SUCCESS; }/*WCTS_SendMessage*/
/** @brief This function is used by the DAL Core to initialize the Control Transport for processing. It must be called prior to calling any other APIs of the Control Transport. @param szName: unique name for the channel that is to be opened uSize: size of the channel that must be opened (should fit the largest size of packet that the Dal Core wishes to send) wctsCBs: a list of callbacks that the CT needs to use to send notification and messages back to DAL @see @return A handle that must be used for further communication with the CTS. This is an opaque structure for the caller and it will be used in all communications to and from the CTS. */ WCTS_HandleType WCTS_OpenTransport ( const wpt_uint8* szName, wpt_uint32 uSize, WCTS_TransportCBsType* wctsCBs ) { WCTS_ControlBlockType* pWCTSCb; wpt_status status; int smdstatus; /*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/ /*--------------------------------------------------------------------- Sanity check ---------------------------------------------------------------------*/ if ((NULL == wctsCBs) || (NULL == szName) || (NULL == wctsCBs->wctsNotifyCB) || (NULL == wctsCBs->wctsRxMsgCB)) { WPAL_TRACE(eWLAN_MODULE_DAL_CTRL, eWLAN_PAL_TRACE_LEVEL_ERROR, "WCTS_OpenTransport: Invalid parameters received."); return NULL; } /* This open is coming after a SSR, we don't need to reopen SMD, * the SMD port was never closed during SSR*/ if (gwctsHandle) { WPAL_TRACE(eWLAN_MODULE_DAL_CTRL, eWLAN_PAL_TRACE_LEVEL_INFO, "WCTS_OpenTransport port is already open\n"); pWCTSCb = gwctsHandle; if (WCTS_CB_MAGIC != pWCTSCb->wctsMagic) { WPAL_TRACE(eWLAN_MODULE_DAL_CTRL, eWLAN_PAL_TRACE_LEVEL_FATAL, "WCTS_OpenTransport: Invalid magic."); return NULL; } pWCTSCb->wctsState = WCTS_STATE_OPEN; pWCTSCb->wctsNotifyCB((WCTS_HandleType)pWCTSCb, WCTS_EVENT_OPEN, pWCTSCb->wctsNotifyCBData); /* we initially don't want read interrupts (we only want them if we get into deferred write mode) */ smd_disable_read_intr(pWCTSCb->wctsChannel); return (WCTS_HandleType)pWCTSCb; } #ifdef FEATURE_R33D if(port_open) { /* Port open before, not need to open again */ /* notified registered client that the channel is open */ ctsCB->wctsState = WCTS_STATE_OPEN; ctsCB->wctsNotifyCB((WCTS_HandleType)ctsCB, WCTS_EVENT_OPEN, ctsCB->wctsNotifyCBData); return (WCTS_HandleType)ctsCB; } #endif /* FEATURE_R33D */ /* allocate a ControlBlock to hold all context */ pWCTSCb = wpalMemoryAllocate(sizeof(*pWCTSCb)); if (NULL == pWCTSCb) { WPAL_TRACE(eWLAN_MODULE_DAL_CTRL, eWLAN_PAL_TRACE_LEVEL_ERROR, "WCTS_OpenTransport: Memory allocation failure."); return NULL; } /* make sure the control block is initialized. in particular we need to make sure the embedded event and list structures are initialized to prevent "magic number" tests from being run against uninitialized values */ wpalMemoryZero(pWCTSCb, sizeof(*pWCTSCb)); #ifdef FEATURE_R33D smd_init(0); port_open = 1; ctsCB = pWCTSCb; #endif /* FEATURE_R33D */ /*Initialise the event*/ wpalEventInit(&pWCTSCb->wctsEvent); /* save the user-supplied information */ pWCTSCb->wctsNotifyCB = wctsCBs->wctsNotifyCB; pWCTSCb->wctsNotifyCBData = wctsCBs->wctsNotifyCBData; pWCTSCb->wctsRxMsgCB = wctsCBs->wctsRxMsgCB; pWCTSCb->wctsRxMsgCBData = wctsCBs->wctsRxMsgCBData; /* initialize the remaining fields */ wpal_list_init(&pWCTSCb->wctsPendingQueue); pWCTSCb->wctsMagic = WCTS_CB_MAGIC; pWCTSCb->wctsState = WCTS_STATE_OPEN_PENDING; pWCTSCb->wctsChannel = NULL; /* since SMD will callback in interrupt context, we will used * canned messages to serialize the SMD events into a thread * context */ pWCTSCb->wctsOpenMsg.callback = WCTS_PALOpenCallback; pWCTSCb->wctsOpenMsg.pContext = pWCTSCb; pWCTSCb->wctsDataMsg.callback = WCTS_PALDataCallback; pWCTSCb->wctsDataMsg.pContext = pWCTSCb; /*--------------------------------------------------------------------- Open the SMD channel ---------------------------------------------------------------------*/ wpalEventReset(&pWCTSCb->wctsEvent); smdstatus = smd_named_open_on_edge(szName, SMD_APPS_WCNSS, &pWCTSCb->wctsChannel, pWCTSCb, WCTS_NotifyCallback); if (0 != smdstatus) { WPAL_TRACE(eWLAN_MODULE_DAL_CTRL, eWLAN_PAL_TRACE_LEVEL_ERROR, "%s: smd_named_open_on_edge failed with status %d", __func__, smdstatus); goto fail; } /* wait for the channel to be fully opened before we proceed */ status = wpalEventWait(&pWCTSCb->wctsEvent, WCTS_SMD_OPEN_TIMEOUT); if (eWLAN_PAL_STATUS_SUCCESS != status) { WPAL_TRACE(eWLAN_MODULE_DAL_CTRL, eWLAN_PAL_TRACE_LEVEL_ERROR, "%s: failed to receive SMD_EVENT_OPEN", __func__); /* since we opened one end of the channel, close it */ smdstatus = smd_close(pWCTSCb->wctsChannel); if (0 != smdstatus) { WPAL_TRACE(eWLAN_MODULE_DAL_CTRL, eWLAN_PAL_TRACE_LEVEL_ERROR, "%s: smd_close failed with status %d", __func__, smdstatus); } goto fail; } /* we initially don't want read interrupts (we only want them if we get into deferred write mode) */ smd_disable_read_intr(pWCTSCb->wctsChannel); /* we have successfully opened the SMD channel */ gwctsHandle = pWCTSCb; return (WCTS_HandleType)pWCTSCb; fail: /* we were unable to open the SMD channel */ pWCTSCb->wctsMagic = 0; wpalMemoryFree(pWCTSCb); return NULL; }/*WCTS_OpenTransport*/
/** @brief wpalEnableInterrupt provides a mechansim for a client to request that a given interrupt be enabled The DXE interface supports two interrupts, TX Complete and RX Available. This interface provides the mechanism whereby a client can request that the platform-specific adaptation layer allows a given interrupt to occur. The expectation is that if a given interrupt is not enabled, if the interrupt occurs then the APPS CPU will not be interrupted. @param intType: Enumeration of the interrupt type (TX or RX) @return SUCCESS if the interrupt was enabled */ wpt_status wpalEnableInterrupt ( wpt_uint32 intType ) { int ret; switch (intType) { case DXE_INTERRUPT_RX_READY: if (!gpEnv->rx_registered) { gpEnv->rx_registered = 1; ret = request_irq(gpEnv->rx_irq, wpalRxIsr, IRQF_TRIGGER_HIGH, "wcnss_wlan", gpEnv); if (ret) { WPAL_TRACE(eWLAN_MODULE_DAL_DATA, eWLAN_PAL_TRACE_LEVEL_ERROR, "%s: RX IRQ request failure", __func__); break; } ret = enable_irq_wake(gpEnv->rx_irq); if (ret) { WPAL_TRACE(eWLAN_MODULE_DAL_DATA, eWLAN_PAL_TRACE_LEVEL_ERROR, "%s: enable_irq_wake failed for RX IRQ", __func__); /* not fatal -- keep on going */ } } else { enable_irq(gpEnv->rx_irq); } break; case DXE_INTERRUPT_TX_COMPLE: if (!gpEnv->tx_registered) { gpEnv->tx_registered = 1; ret = request_irq(gpEnv->tx_irq, wpalTxIsr, IRQF_TRIGGER_HIGH, "wcnss_wlan", gpEnv); if (ret) { WPAL_TRACE(eWLAN_MODULE_DAL_DATA, eWLAN_PAL_TRACE_LEVEL_ERROR, "%s: TX IRQ request failure", __func__); break; } ret = enable_irq_wake(gpEnv->tx_irq); if (ret) { WPAL_TRACE(eWLAN_MODULE_DAL_DATA, eWLAN_PAL_TRACE_LEVEL_ERROR, "%s: enable_irq_wake failed for TX IRQ", __func__); /* not fatal -- keep on going */ } } else { enable_irq(gpEnv->tx_irq); } break; default: WPAL_TRACE(eWLAN_MODULE_DAL_DATA, eWLAN_PAL_TRACE_LEVEL_ERROR, "%s: unknown interrupt: %d", __func__, (int)intType); break; } /* on the integrated platform there is no platform-specific interrupt control */ return eWLAN_PAL_STATUS_SUCCESS; }
wpt_status wpalDeviceInit ( void * deviceCB ) { hdd_context_t *pHddCtx = (hdd_context_t *)deviceCB; struct device *wcnss_device = pHddCtx->parent_dev; struct resource *wcnss_memory; int tx_irq; int rx_irq; if (NULL != gpEnv) { WPAL_TRACE(eWLAN_MODULE_DAL_DATA, eWLAN_PAL_TRACE_LEVEL_ERROR, "%s: invoked after subsystem initialized", __func__); return eWLAN_PAL_STATUS_E_INVAL; } if (NULL == wcnss_device) { WPAL_TRACE(eWLAN_MODULE_DAL_DATA, eWLAN_PAL_TRACE_LEVEL_ERROR, "%s: invalid device", __func__); return eWLAN_PAL_STATUS_E_INVAL; } wcnss_memory = wcnss_wlan_get_memory_map(wcnss_device); if (NULL == wcnss_memory) { WPAL_TRACE(eWLAN_MODULE_DAL_DATA, eWLAN_PAL_TRACE_LEVEL_ERROR, "%s: WCNSS memory map unavailable", __func__); return eWLAN_PAL_STATUS_E_FAILURE; } tx_irq = wcnss_wlan_get_dxe_tx_irq(wcnss_device); if (0 > tx_irq) { WPAL_TRACE(eWLAN_MODULE_DAL_DATA, eWLAN_PAL_TRACE_LEVEL_ERROR, "%s: WCNSS TX IRQ unavailable", __func__); return eWLAN_PAL_STATUS_E_FAILURE; } rx_irq = wcnss_wlan_get_dxe_rx_irq(wcnss_device); if (0 > rx_irq) { WPAL_TRACE(eWLAN_MODULE_DAL_DATA, eWLAN_PAL_TRACE_LEVEL_ERROR, "%s: WCNSS RX IRQ unavailable", __func__); return eWLAN_PAL_STATUS_E_FAILURE; } gpEnv = &gEnv; if (NULL == gpEnv) { WPAL_TRACE(eWLAN_MODULE_DAL_DATA, eWLAN_PAL_TRACE_LEVEL_ERROR, "%s: memory allocation failure", __func__); return eWLAN_PAL_STATUS_E_NOMEM; } memset(gpEnv, 0, sizeof(*gpEnv)); gpEnv->wcnss_memory = wcnss_memory; gpEnv->tx_irq = tx_irq; gpEnv->rx_irq = rx_irq; gpEnv->mmio = ioremap(wcnss_memory->start, resource_size(wcnss_memory)); if (NULL == gpEnv->mmio) { WPAL_TRACE(eWLAN_MODULE_DAL_DATA, eWLAN_PAL_TRACE_LEVEL_ERROR, "%s: memory remap failure", __func__); goto err_ioremap; } gpEnv->tx_registered = 0; gpEnv->rx_registered = 0; return eWLAN_PAL_STATUS_SUCCESS; err_ioremap: gpEnv = NULL; return eWLAN_PAL_STATUS_E_FAILURE; }
/* DTS Rx packet function. * This function should be invoked by the transport device to indicate * reception of a frame. * Parameters: * pContext:Cookie that should be passed back to the caller * pFrame:Refernce to PAL frame. * Return Value: SUCCESS Completed successfully. * FAILURE_XXX Request was rejected due XXX Reason. * */ wpt_status WDTS_RxPacket (void *pContext, wpt_packet *pFrame, WDTS_ChannelType channel) { WDI_DS_ClientDataType *pClientData = (WDI_DS_ClientDataType*)(pContext); wpt_boolean bASF, bFSF, bLSF, bAEF; wpt_uint8 ucMPDUHOffset, ucMPDUHLen, ucTid; wpt_uint8 *pBDHeader; wpt_uint16 usMPDUDOffset, usMPDULen; WDI_DS_RxMetaInfoType *pRxMetadata; wpt_uint8 isFcBd = 0; tpSirMacFrameCtl pMacFrameCtl; // Do Sanity checks if(NULL == pContext || NULL == pFrame){ return eWLAN_PAL_STATUS_E_FAILURE; } /*------------------------------------------------------------------------ Extract BD header and check if valid ------------------------------------------------------------------------*/ pBDHeader = (wpt_uint8*)wpalPacketGetRawBuf(pFrame); if(NULL == pBDHeader) { DTI_TRACE( DTI_TRACE_LEVEL_ERROR, "WLAN TL:BD header received NULL - dropping packet"); wpalPacketFree(pFrame); return eWLAN_PAL_STATUS_E_FAILURE; } WDI_SwapRxBd(pBDHeader); ucMPDUHOffset = (wpt_uint8)WDI_RX_BD_GET_MPDU_H_OFFSET(pBDHeader); usMPDUDOffset = (wpt_uint16)WDI_RX_BD_GET_MPDU_D_OFFSET(pBDHeader); usMPDULen = (wpt_uint16)WDI_RX_BD_GET_MPDU_LEN(pBDHeader); ucMPDUHLen = (wpt_uint8)WDI_RX_BD_GET_MPDU_H_LEN(pBDHeader); ucTid = (wpt_uint8)WDI_RX_BD_GET_TID(pBDHeader); /* If RX thread drain small size of frame from HW too fast * Sometimes HW cannot handle interrupt fast enough * And system crash might happen * To avoid system crash, input 1usec delay each frame draining * within host side, if frame size is smaller that threshold. * This is SW work around, to fix HW problem * Throughput and SnS test done successfully */ if (usMPDULen < DTS_RX_DELAY_FRAMESIZE_THRESHOLD) { wpalBusyWait(1); } /*------------------------------------------------------------------------ Gather AMSDU information ------------------------------------------------------------------------*/ bASF = WDI_RX_BD_GET_ASF(pBDHeader); bAEF = WDI_RX_BD_GET_AEF(pBDHeader); bFSF = WDI_RX_BD_GET_ESF(pBDHeader); bLSF = WDI_RX_BD_GET_LSF(pBDHeader); isFcBd = WDI_RX_FC_BD_GET_FC(pBDHeader); DTI_TRACE( DTI_TRACE_LEVEL_INFO, "WLAN TL:BD header processing data: HO %d DO %d Len %d HLen %d" " Tid %d BD %d", ucMPDUHOffset, usMPDUDOffset, usMPDULen, ucMPDUHLen, ucTid, WDI_RX_BD_HEADER_SIZE); if(!isFcBd) { if(usMPDUDOffset <= ucMPDUHOffset || usMPDULen < ucMPDUHLen) { DTI_TRACE( DTI_TRACE_LEVEL_ERROR, "WLAN TL:BD header corrupted - dropping packet"); /* Drop packet ???? */ wpalPacketFree(pFrame); return eWLAN_PAL_STATUS_SUCCESS; } if((ucMPDUHOffset < WDI_RX_BD_HEADER_SIZE) && (!(bASF && !bFSF))){ /* AMSDU case, ucMPDUHOffset = 0 it should be hancdled seperatly */ /* Drop packet ???? */ wpalPacketFree(pFrame); return eWLAN_PAL_STATUS_SUCCESS; } /* AMSDU frame, but not first sub-frame * No MPDU header, MPDU header offset is 0 * Total frame size is actual frame size + MPDU data offset */ if((ucMPDUHOffset < WDI_RX_BD_HEADER_SIZE) && (bASF && !bFSF)){ ucMPDUHOffset = usMPDUDOffset; } if(VPKT_SIZE_BUFFER_ALIGNED < (usMPDULen+ucMPDUHOffset)){ WPAL_TRACE(eWLAN_MODULE_DAL_DATA, eWLAN_PAL_TRACE_LEVEL_FATAL, "Invalid Frame size, might memory corrupted(%d+%d/%d)", usMPDULen, ucMPDUHOffset, VPKT_SIZE_BUFFER_ALIGNED); /* Size of the packet tranferred by the DMA engine is * greater than the the memory allocated for the skb */ WPAL_BUG(0); wpalPacketFree(pFrame); return eWLAN_PAL_STATUS_SUCCESS; } if(eWLAN_PAL_STATUS_SUCCESS != wpalPacketSetRxLength(pFrame, usMPDULen+ucMPDUHOffset)) { DTI_TRACE( DTI_TRACE_LEVEL_ERROR, "Invalid Frame Length, Frame dropped.."); wpalPacketFree(pFrame); return eWLAN_PAL_STATUS_SUCCESS; } if(eWLAN_PAL_STATUS_SUCCESS != wpalPacketRawTrimHead(pFrame, ucMPDUHOffset)) { DTI_TRACE( DTI_TRACE_LEVEL_ERROR, "Failed to trim Raw Packet Head, Frame dropped.."); wpalPacketFree(pFrame); return eWLAN_PAL_STATUS_SUCCESS; } pRxMetadata = WDI_DS_ExtractRxMetaData(pFrame); pRxMetadata->fc = isFcBd; pRxMetadata->staId = WDI_RX_BD_GET_STA_ID(pBDHeader); pRxMetadata->addr3Idx = WDI_RX_BD_GET_ADDR3_IDX(pBDHeader); pRxMetadata->rxChannel = WDI_RX_BD_GET_RX_CHANNEL(pBDHeader); pRxMetadata->rfBand = WDI_RX_BD_GET_RFBAND(pBDHeader); pRxMetadata->rtsf = WDI_RX_BD_GET_RTSF(pBDHeader); pRxMetadata->bsf = WDI_RX_BD_GET_BSF(pBDHeader); pRxMetadata->scan = WDI_RX_BD_GET_SCAN(pBDHeader); pRxMetadata->dpuSig = WDI_RX_BD_GET_DPU_SIG(pBDHeader); pRxMetadata->ft = WDI_RX_BD_GET_FT(pBDHeader); pRxMetadata->ne = WDI_RX_BD_GET_NE(pBDHeader); pRxMetadata->llcr = WDI_RX_BD_GET_LLCR(pBDHeader); pRxMetadata->bcast = WDI_RX_BD_GET_UB(pBDHeader); pRxMetadata->tid = ucTid; pRxMetadata->dpuFeedback = WDI_RX_BD_GET_DPU_FEEDBACK(pBDHeader); pRxMetadata->rateIndex = WDI_RX_BD_GET_RATEINDEX(pBDHeader); pRxMetadata->rxpFlags = WDI_RX_BD_GET_RXPFLAGS(pBDHeader); pRxMetadata->mclkRxTimestamp = WDI_RX_BD_GET_TIMESTAMP(pBDHeader); #ifdef WLAN_FEATURE_11W pRxMetadata->rmf = WDI_RX_BD_GET_RMF(pBDHeader); #endif #ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD pRxMetadata->offloadScanLearn = WDI_RX_BD_GET_OFFLOADSCANLEARN(pBDHeader); pRxMetadata->roamCandidateInd = WDI_RX_BD_GET_ROAMCANDIDATEIND(pBDHeader); #endif /* typeSubtype in BD doesn't look like correct. Fill from frame ctrl TL does it for Volans but TL does not know BD for Prima. WDI should do it */ if ( 0 == WDI_RX_BD_GET_FT(pBDHeader) ) { if ( bASF ) { pRxMetadata->subtype = WDI_MAC_DATA_QOS_DATA; pRxMetadata->type = WDI_MAC_DATA_FRAME; } else { pMacFrameCtl = (tpSirMacFrameCtl)(((wpt_uint8*)pBDHeader) + ucMPDUHOffset); pRxMetadata->subtype = pMacFrameCtl->subType; pRxMetadata->type = pMacFrameCtl->type; } } else { pMacFrameCtl = (tpSirMacFrameCtl)(((wpt_uint8*)pBDHeader) + WDI_RX_BD_HEADER_SIZE); pRxMetadata->subtype = pMacFrameCtl->subType; pRxMetadata->type = pMacFrameCtl->type; } pRxMetadata->mpduHeaderPtr = pBDHeader + ucMPDUHOffset; pRxMetadata->mpduDataPtr = pBDHeader + usMPDUDOffset; pRxMetadata->mpduLength = usMPDULen; pRxMetadata->mpduHeaderLength = ucMPDUHLen; /*------------------------------------------------------------------------ Gather AMPDU information ------------------------------------------------------------------------*/ pRxMetadata->ampdu_reorderOpcode = (wpt_uint8)WDI_RX_BD_GET_BA_OPCODE(pBDHeader); pRxMetadata->ampdu_reorderSlotIdx = (wpt_uint8)WDI_RX_BD_GET_BA_SI(pBDHeader); pRxMetadata->ampdu_reorderFwdIdx = (wpt_uint8)WDI_RX_BD_GET_BA_FI(pBDHeader); pRxMetadata->currentPktSeqNo = (wpt_uint16)WDI_RX_BD_GET_BA_CSN(pBDHeader); /*------------------------------------------------------------------------ Gather AMSDU information ------------------------------------------------------------------------*/ pRxMetadata->amsdu_asf = bASF; pRxMetadata->amsdu_aef = bAEF; pRxMetadata->amsdu_esf = bFSF; pRxMetadata->amsdu_lsf = bLSF; pRxMetadata->amsdu_size = WDI_RX_BD_GET_AMSDU_SIZE(pBDHeader); pRxMetadata->rssi0 = WDI_RX_BD_GET_RSSI0(pBDHeader); pRxMetadata->rssi1 = WDI_RX_BD_GET_RSSI1(pBDHeader); /* Missing: wpt_uint32 fcSTATxQStatus:8; wpt_uint32 fcSTAThreshIndMask:8; wpt_uint32 fcSTAPwrSaveStateMask:8; wpt_uint32 fcSTAValidMask:8; wpt_uint8 fcSTATxQLen[8]; // one byte per STA. wpt_uint8 fcSTACurTxRate[8]; // current Tx rate for each sta. unknownUcastPkt */ pRxMetadata->replayCount = WDTS_GetReplayCounterFromRxBD(pBDHeader); pRxMetadata->snr = WDI_RX_BD_GET_SNR(pBDHeader); /* * PAL BD pointer information needs to be populated */ WPAL_PACKET_SET_BD_POINTER(pFrame, pBDHeader); WPAL_PACKET_SET_BD_LENGTH(pFrame, sizeof(WDI_RxBdType)); // Invoke Rx complete callback pClientData->receiveFrameCB(pClientData->pCallbackContext, pFrame); } else { wpalPacketSetRxLength(pFrame, usMPDULen+ucMPDUHOffset); wpalPacketRawTrimHead(pFrame, ucMPDUHOffset); pRxMetadata = WDI_DS_ExtractRxMetaData(pFrame); //flow control related pRxMetadata->fc = isFcBd; pRxMetadata->mclkRxTimestamp = WDI_RX_BD_GET_TIMESTAMP(pBDHeader); pRxMetadata->fcStaTxDisabledBitmap = WDI_RX_FC_BD_GET_STA_TX_DISABLED_BITMAP(pBDHeader); pRxMetadata->fcSTAValidMask = WDI_RX_FC_BD_GET_STA_VALID_MASK(pBDHeader); // Invoke Rx complete callback pClientData->receiveFrameCB(pClientData->pCallbackContext, pFrame); } //Log the RX Stats if(gDsTrafficStats.running && pRxMetadata->staId < HAL_NUM_STA) { if(pRxMetadata->rateIndex < WDTS_MAX_RATE_NUM) { if(pRxMetadata->type == WDI_MAC_DATA_FRAME) { gDsTrafficStats.rxStats[pRxMetadata->staId][pRxMetadata->rateIndex].rxBytesRcvd += pRxMetadata->mpduLength; gDsTrafficStats.rxStats[pRxMetadata->staId][pRxMetadata->rateIndex].rxPacketsRcvd++; } } } return eWLAN_PAL_STATUS_SUCCESS; }
wpt_status wpalUnlockPacket( wpt_packet *pPacket) { wpt_iterator_info* pInfo; // if (unlikely(NULL == pPacket)) { WPAL_TRACE(eWLAN_MODULE_PAL, eWLAN_PAL_TRACE_LEVEL_ERROR, "%s : NULL input pointer pPacket", __func__); return eWLAN_PAL_STATUS_E_INVAL; } pInfo = (wpt_iterator_info*)pPacket->pInternalData; // if (unlikely(NULL == pInfo)) { WPAL_TRACE(eWLAN_MODULE_PAL, eWLAN_PAL_TRACE_LEVEL_FATAL, "%s : NULL input pointer pInfo", __func__); return eWLAN_PAL_STATUS_E_INVAL; } switch(WPAL_PACKET_GET_TYPE(pPacket)) { /* */ case eWLAN_PAL_PKT_TYPE_TX_802_11_MGMT: { /* */ itReturnOSPktAddrForDevice(pPacket, pInfo->pPhyAddr, pInfo->uLen); } break; /* */ case eWLAN_PAL_PKT_TYPE_TX_802_11_DATA: case eWLAN_PAL_PKT_TYPE_TX_802_3_DATA: { /* */ itReturnOSPktAddrForDevice(pPacket, pInfo->pPhyAddr, pInfo->uLen); } break; /* */ case eWLAN_PAL_PKT_TYPE_RX_RAW: { /* */ if(NULL == pInfo->pPhyAddr) { WPAL_TRACE(eWLAN_MODULE_PAL, eWLAN_PAL_TRACE_LEVEL_ERROR, " WLAN_PAL: %s: RX frame was not locked properly", __func__); } else { itReturnOSPktAddrFromDevice(pPacket, pInfo->pPhyAddr, pInfo->uLen); } } 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; } } wpalMemoryFree(pInfo); pPacket->pInternalData = NULL; return eWLAN_PAL_STATUS_SUCCESS; }/* */
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; }/* */
wpt_packet * wpalPacketAlloc(wpt_packet_type pktType, wpt_uint32 nPktSize, wpalPacketLowPacketCB rxLowCB, void *usrData) { VOS_STATUS vosStatus = VOS_STATUS_E_FAILURE; wpt_packet* pPkt = NULL; vos_pkt_t* pVosPkt = NULL; void* pData = NULL; v_U16_t allocLen; /* */ switch (pktType) { case eWLAN_PAL_PKT_TYPE_TX_802_11_MGMT: vosStatus = vos_pkt_get_packet(&pVosPkt, VOS_PKT_TYPE_TX_802_11_MGMT, nPktSize, 1, VOS_FALSE, NULL, NULL /* */); break; case eWLAN_PAL_PKT_TYPE_RX_RAW: /* */ wpalPacketAvailableCB = rxLowCB; vosStatus = vos_pkt_get_packet(&pVosPkt, VOS_PKT_TYPE_RX_RAW, nPktSize, 1, VOS_FALSE, wpalPacketRXLowResourceCB, usrData); #ifndef FEATURE_R33D /* */ if( vosStatus == VOS_STATUS_SUCCESS ) { wpalPacketAvailableCB = NULL; vosStatus = vos_pkt_reserve_head_fast( pVosPkt, &pData, nPktSize ); } #endif /* */ if((NULL != pVosPkt) && (VOS_STATUS_E_RESOURCES != vosStatus)) { vos_pkt_get_packet_length(pVosPkt, &allocLen); if (nPktSize != allocLen) { WPAL_TRACE(eWLAN_MODULE_PAL, eWLAN_PAL_TRACE_LEVEL_ERROR, "RX packet alloc has problem, discard this frame, Len %d", allocLen); vos_pkt_return_packet(pVosPkt); return NULL; } } break; default: WPAL_TRACE(eWLAN_MODULE_PAL, eWLAN_PAL_TRACE_LEVEL_ERROR, " try to allocate unsupported packet type (%d)\n", pktType); break; } if(VOS_IS_STATUS_SUCCESS(vosStatus)) { pPkt = (wpt_packet *)pVosPkt; } return pPkt; }/* */
/** @brief Callback function for serializing WCTS Write processing in the control context @param pWCTSCb WCTS Control Block @see @return void */ static void WCTS_PALWriteCallback ( WCTS_ControlBlockType* pWCTSCb ) { wpt_list_node* pNode; WCTS_BufferType* pBufferQueue; void* pBuffer; int len; int available; int written; /*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ /*-------------------------------------------------------------------- Sanity check --------------------------------------------------------------------*/ if ((NULL == pWCTSCb) || (WCTS_CB_MAGIC != pWCTSCb->wctsMagic)) { WPAL_TRACE(eWLAN_MODULE_DAL_CTRL, eWLAN_PAL_TRACE_LEVEL_ERROR, "WCTS_PALWriteCallback: Invalid parameter received."); return; } /* if we are not deferred, then there are no pending packets */ if (WCTS_STATE_DEFERRED != pWCTSCb->wctsState) { return; } /* Keep sending deferred messages as long as there is room in the channel. Note that we initially peek at the head of the list to access the parameters for the next message; we don't actually remove the next message from the deferred list until we know the channel can handle it */ while (eWLAN_PAL_STATUS_SUCCESS == wpal_list_peek_front(&pWCTSCb->wctsPendingQueue, &pNode)) { pBufferQueue = container_of(pNode, WCTS_BufferType, node); pBuffer = pBufferQueue->pBuffer; len = pBufferQueue->bufferSize; available = smd_write_avail(pWCTSCb->wctsChannel); if (available < len) { /* channel has no room for the next packet so we are done */ return; } /* there is room for the next message, so we can now remove it from the deferred message queue and send it */ wpal_list_remove_front(&pWCTSCb->wctsPendingQueue, &pNode); /* note that pNode will be the same as when we peeked, so there is no need to update pBuffer or len */ written = smd_write(pWCTSCb->wctsChannel, pBuffer, len); if (written != len) { /* Something went wrong */ WPAL_TRACE(eWLAN_MODULE_DAL_CTRL, eWLAN_PAL_TRACE_LEVEL_ERROR, "WCTS_PALWriteCallback: channel write failure"); /* we were unable to send the message that was at the head of the deferred list. there is nothing else we can do other than drop it, so we will just fall through to the "success" processing. hopefully the client can recover from this since there is nothing else we can do here */ } /* whether we had success or failure, reclaim all memory */ wpalMemoryFree(pBuffer); wpalMemoryFree(pBufferQueue); /* we'll continue to iterate until the channel is full or all of the deferred messages have been sent */ } /* if we've exited the loop, then we have drained the deferred queue. set the state to indicate we are no longer deferred, and turn off the remote read interrupt */ pWCTSCb->wctsState = WCTS_STATE_OPEN; smd_disable_read_intr(pWCTSCb->wctsChannel); } /*WCTS_PALWriteCallback*/
static void WCTS_NotifyCallback ( void *data, unsigned event ) { wpt_msg *palMsg; WCTS_ControlBlockType* pWCTSCb = (WCTS_ControlBlockType*) data; /*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ /*-------------------------------------------------------------------- Sanity check --------------------------------------------------------------------*/ if (WCTS_CB_MAGIC != pWCTSCb->wctsMagic) { WPAL_TRACE(eWLAN_MODULE_DAL_CTRL, eWLAN_PAL_TRACE_LEVEL_ERROR, "%s: Received unexpected SMD event %u", __func__, event); /* TODO_PRIMA what error recovery options do we have? */ return; } /* Serialize processing in the control thread */ switch (event) { case SMD_EVENT_OPEN: WPAL_TRACE(eWLAN_MODULE_DAL_CTRL, eWLAN_PAL_TRACE_LEVEL_INFO, "%s: received SMD_EVENT_OPEN from SMD", __func__); /* If the prev state was 'remote closed' then it is a Riva 'restart', * subsystem restart re-init */ if (WCTS_STATE_REM_CLOSED == pWCTSCb->wctsState) { WPAL_TRACE(eWLAN_MODULE_DAL_CTRL, eWLAN_PAL_TRACE_LEVEL_INFO, "%s: received SMD_EVENT_OPEN in WCTS_STATE_REM_CLOSED state", __func__); /* call subsystem restart re-init function */ wpalDriverReInit(); return; } palMsg = &pWCTSCb->wctsOpenMsg; break; case SMD_EVENT_DATA: if (WCTS_STATE_REM_CLOSED == pWCTSCb->wctsState) { WPAL_TRACE(eWLAN_MODULE_DAL_CTRL, eWLAN_PAL_TRACE_LEVEL_ERROR, "%s: received SMD data when the state is remote closed ", __func__); /* we should not be getting any data now */ return; } WPAL_TRACE(eWLAN_MODULE_DAL_CTRL, eWLAN_PAL_TRACE_LEVEL_INFO, "%s: received SMD_EVENT_DATA from SMD", __func__); palMsg = &pWCTSCb->wctsDataMsg; break; case SMD_EVENT_CLOSE: WPAL_TRACE(eWLAN_MODULE_DAL_CTRL, eWLAN_PAL_TRACE_LEVEL_INFO, "%s: received SMD_EVENT_CLOSE from SMD", __func__); /* SMD channel was closed from the remote side, * this would happen only when Riva crashed and SMD is * closing the channel on behalf of Riva */ pWCTSCb->wctsState = WCTS_STATE_REM_CLOSED; WPAL_TRACE(eWLAN_MODULE_DAL_CTRL, eWLAN_PAL_TRACE_LEVEL_INFO, "%s: received SMD_EVENT_CLOSE WLAN driver going down now", __func__); /* subsystem restart: shutdown */ wpalDriverShutdown(); return; case SMD_EVENT_STATUS: WPAL_TRACE(eWLAN_MODULE_DAL_CTRL, eWLAN_PAL_TRACE_LEVEL_INFO, "%s: received SMD_EVENT_STATUS from SMD", __func__); return; case SMD_EVENT_REOPEN_READY: WPAL_TRACE(eWLAN_MODULE_DAL_CTRL, eWLAN_PAL_TRACE_LEVEL_ERROR, "%s: received SMD_EVENT_REOPEN_READY from SMD", __func__); /* unlike other events which occur when our kernel threads are running, this one is received when the threads are closed and the rmmod thread is waiting. so just unblock that thread */ wpalEventSet(&pWCTSCb->wctsEvent); return; default: WPAL_TRACE(eWLAN_MODULE_DAL_CTRL, eWLAN_PAL_TRACE_LEVEL_ERROR, "%s: Unexpected event %u received from SMD", __func__, event); return; } /* serialize this event */ wpalPostCtrlMsg(WDI_GET_PAL_CTX(), palMsg); } /*WCTS_NotifyCallback*/
/** @brief wpalDeviceInit provides a mechanism to initialize the DXE platform adaptation @param deviceCB: Implementation-specific device control block @see wpalDeviceClose @return SUCCESS if the DXE abstraction was opened */ wpt_status wpalDeviceInit ( void * deviceCB ) { hdd_context_t *pHddCtx = (hdd_context_t *)deviceCB; struct device *wcnss_device = pHddCtx->parent_dev; struct resource *wcnss_memory; int tx_irq; int rx_irq; if (NULL != gpEnv) { WPAL_TRACE(eWLAN_MODULE_DAL_DATA, eWLAN_PAL_TRACE_LEVEL_ERROR, "%s: invoked after subsystem initialized", __func__); return eWLAN_PAL_STATUS_E_INVAL; } if (NULL == wcnss_device) { WPAL_TRACE(eWLAN_MODULE_DAL_DATA, eWLAN_PAL_TRACE_LEVEL_ERROR, "%s: invalid device", __func__); return eWLAN_PAL_STATUS_E_INVAL; } wcnss_memory = wcnss_wlan_get_memory_map(wcnss_device); if (NULL == wcnss_memory) { WPAL_TRACE(eWLAN_MODULE_DAL_DATA, eWLAN_PAL_TRACE_LEVEL_ERROR, "%s: WCNSS memory map unavailable", __func__); return eWLAN_PAL_STATUS_E_FAILURE; } tx_irq = wcnss_wlan_get_dxe_tx_irq(wcnss_device); if (0 > tx_irq) { WPAL_TRACE(eWLAN_MODULE_DAL_DATA, eWLAN_PAL_TRACE_LEVEL_ERROR, "%s: WCNSS TX IRQ unavailable", __func__); return eWLAN_PAL_STATUS_E_FAILURE; } rx_irq = wcnss_wlan_get_dxe_rx_irq(wcnss_device); if (0 > rx_irq) { WPAL_TRACE(eWLAN_MODULE_DAL_DATA, eWLAN_PAL_TRACE_LEVEL_ERROR, "%s: WCNSS RX IRQ unavailable", __func__); return eWLAN_PAL_STATUS_E_FAILURE; } gpEnv = &gEnv; if (NULL == gpEnv) { WPAL_TRACE(eWLAN_MODULE_DAL_DATA, eWLAN_PAL_TRACE_LEVEL_ERROR, "%s: memory allocation failure", __func__); return eWLAN_PAL_STATUS_E_NOMEM; } memset(gpEnv, 0, sizeof(*gpEnv)); gpEnv->wcnss_memory = wcnss_memory; gpEnv->tx_irq = tx_irq; gpEnv->rx_irq = rx_irq; /* note the we don't invoke request_mem_region(). the memory described by wcnss_memory encompases the entire register space (including BT and FM) and we do not want exclusive access to that memory */ gpEnv->mmio = ioremap(wcnss_memory->start, resource_size(wcnss_memory)); if (NULL == gpEnv->mmio) { WPAL_TRACE(eWLAN_MODULE_DAL_DATA, eWLAN_PAL_TRACE_LEVEL_ERROR, "%s: memory remap failure", __func__); goto err_ioremap; } gpEnv->tx_registered = 0; gpEnv->rx_registered = 0; /* successfully allocated environment, memory and IRQs */ return eWLAN_PAL_STATUS_SUCCESS; err_ioremap: gpEnv = NULL; return eWLAN_PAL_STATUS_E_FAILURE; }
/** @brief This function is used by the DAL Core to close the Control Transport when its services are no longer needed. Full close notification will be receive asynchronously on the notification callback registered on Open @param wctsHandlehandle: received upon open @see @return 0 for success */ wpt_uint32 WCTS_CloseTransport ( WCTS_HandleType wctsHandle ) { WCTS_ControlBlockType* pWCTSCb = (WCTS_ControlBlockType*) wctsHandle; wpt_list_node* pNode = NULL; WCTS_BufferType* pBufferQueue = NULL; void* pBuffer = NULL; wpt_status status; int smdstatus; /*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ if ((NULL == pWCTSCb) || (WCTS_CB_MAGIC != pWCTSCb->wctsMagic)) { WPAL_TRACE(eWLAN_MODULE_DAL_CTRL, eWLAN_PAL_TRACE_LEVEL_ERROR, "WCTS_CloseTransport: Invalid parameters received."); return eWLAN_PAL_STATUS_E_INVAL; } #ifdef FEATURE_R33D /* Not actually close port, just pretend */ /* notified registered client that the channel is closed */ pWCTSCb->wctsState = WCTS_STATE_CLOSED; pWCTSCb->wctsNotifyCB((WCTS_HandleType)pWCTSCb, WCTS_EVENT_CLOSE, pWCTSCb->wctsNotifyCBData); printk(KERN_ERR "R33D Not need to close"); return eWLAN_PAL_STATUS_SUCCESS; #endif /* FEATURE_R33D */ /*Free the buffers in the pending queue.*/ while (eWLAN_PAL_STATUS_SUCCESS == wpal_list_remove_front(&pWCTSCb->wctsPendingQueue, &pNode)) { pBufferQueue = container_of(pNode, WCTS_BufferType, node); pBuffer = pBufferQueue->pBuffer; wpalMemoryFree(pBuffer); wpalMemoryFree(pBufferQueue); } /* Reset the state */ pWCTSCb->wctsState = WCTS_STATE_CLOSED; wpalEventReset(&pWCTSCb->wctsEvent); smdstatus = smd_close(pWCTSCb->wctsChannel); if (0 != smdstatus) { WPAL_TRACE(eWLAN_MODULE_DAL_CTRL, eWLAN_PAL_TRACE_LEVEL_ERROR, "%s: smd_close failed with status %d", __func__, smdstatus); /* SMD did not successfully close the channel, therefore we won't receive an asynchronous close notification so don't bother to wait for an event that won't come */ } else { /* close command was sent -- wait for the callback to complete */ status = wpalEventWait(&pWCTSCb->wctsEvent, WCTS_SMD_CLOSE_TIMEOUT); if (eWLAN_PAL_STATUS_SUCCESS != status) { WPAL_TRACE(eWLAN_MODULE_DAL_CTRL, eWLAN_PAL_TRACE_LEVEL_ERROR, "%s: failed to receive SMD_EVENT_REOPEN_READY", __func__); } /* During the close sequence we deregistered from SMD. As part of deregistration SMD will call back into our driver with an event to let us know the channel is closed. We need to insert a brief delay to allow that thread of execution to exit our module. Otherwise our module may be unloaded while there is still code running within the address space, and that code will crash when the memory is unmapped */ msleep(50); } /* channel has (hopefully) been closed */ pWCTSCb->wctsNotifyCB((WCTS_HandleType)pWCTSCb, WCTS_EVENT_CLOSE, pWCTSCb->wctsNotifyCBData); /* release the resource */ pWCTSCb->wctsMagic = 0; wpalMemoryFree(pWCTSCb); gwctsHandle = NULL; return eWLAN_PAL_STATUS_SUCCESS; }/*WCTS_CloseTransport*/
static void WCTS_PALReadCallback ( WCTS_ControlBlockType* pWCTSCb ) { void* buffer; int packet_size; int available; int bytes_read; if ((NULL == pWCTSCb) || (WCTS_CB_MAGIC != pWCTSCb->wctsMagic)) { WPAL_TRACE(eWLAN_MODULE_DAL_CTRL, eWLAN_PAL_TRACE_LEVEL_ERROR, "WCTS_PALReadCallback: Invalid parameter received."); return; } while (1) { packet_size = smd_cur_packet_size(pWCTSCb->wctsChannel); if (0 == packet_size) { return; } available = smd_read_avail(pWCTSCb->wctsChannel); if (available < packet_size) { return; } buffer = wpalMemoryAllocate(packet_size); if (NULL == buffer) { WPAL_TRACE(eWLAN_MODULE_DAL_CTRL, eWLAN_PAL_TRACE_LEVEL_ERROR, "WCTS_PALReadCallback: Memory allocation failure"); WPAL_ASSERT(0); return; } bytes_read = smd_read(pWCTSCb->wctsChannel, buffer, packet_size); if (bytes_read != packet_size) { WPAL_TRACE(eWLAN_MODULE_DAL_CTRL, eWLAN_PAL_TRACE_LEVEL_ERROR, "WCTS_PALReadCallback: Failed to read data from SMD"); wpalMemoryFree(buffer); WPAL_ASSERT(0); return; } pWCTSCb->wctsRxMsgCB((WCTS_HandleType)pWCTSCb, buffer, packet_size, pWCTSCb->wctsRxMsgCBData); wpalMemoryFree(buffer); } }
WDI_Status WDI_DS_TxPacket(void *pContext, wpt_packet *pFrame, wpt_boolean more) { WDI_DS_ClientDataType *pClientData; wpt_uint8 ucSwFrameTXXlation; wpt_uint8 ucUP; wpt_uint8 ucTypeSubtype; wpt_uint8 isEapol; wpt_uint8 alignment; wpt_uint32 ucTxFlag; wpt_uint8 ucProtMgmtFrame; wpt_uint8* pSTAMACAddress; wpt_uint8* pAddr2MACAddress; WDI_DS_TxMetaInfoType *pTxMetadata; void *physBDHeader, *pvBDHeader; wpt_uint8 ucType; WDI_DS_BdMemPoolType *pMemPool; wpt_uint8 ucBdPoolType; wpt_uint8 staId; WDI_Status wdiStatus; if (NULL == pContext) { return WDI_STATUS_E_FAILURE; } pClientData = (WDI_DS_ClientDataType *) WDI_DS_GetDatapathContext(pContext); if (NULL == pClientData || pClientData->suspend) { return WDI_STATUS_E_FAILURE; } pTxMetadata = WDI_DS_ExtractTxMetaData(pFrame); ucSwFrameTXXlation = pTxMetadata->fdisableFrmXlt; ucTypeSubtype = pTxMetadata->typeSubtype; ucUP = pTxMetadata->fUP; isEapol = pTxMetadata->isEapol; ucTxFlag = pTxMetadata->txFlags; ucProtMgmtFrame = pTxMetadata->fProtMgmtFrame; pSTAMACAddress = &(pTxMetadata->fSTAMACAddress[0]); pAddr2MACAddress = &(pTxMetadata->addr2MACAddress[0]); ucType = (ucTypeSubtype & WDI_FRAME_TYPE_MASK) >> WDI_FRAME_TYPE_OFFSET; switch(ucType) { case WDI_MAC_DATA_FRAME: #ifdef FEATURE_WLAN_TDLS if((!pTxMetadata->isEapol) && ((pTxMetadata->txFlags & WDI_USE_BD_RATE2_FOR_MANAGEMENT_FRAME) != WDI_USE_BD_RATE2_FOR_MANAGEMENT_FRAME)) #else if(!pTxMetadata->isEapol) #endif { pMemPool = &(pClientData->dataMemPool); ucBdPoolType = WDI_DATA_POOL_ID; break; } case WDI_MAC_MGMT_FRAME: pMemPool = &(pClientData->mgmtMemPool); ucBdPoolType = WDI_MGMT_POOL_ID; break; default: return WDI_STATUS_E_FAILURE; } pvBDHeader = WDI_DS_MemPoolAlloc(pMemPool, &physBDHeader, ucBdPoolType); if(NULL == pvBDHeader) return WDI_STATUS_E_FAILURE; WDI_SetBDPointers(pFrame, pvBDHeader, physBDHeader); alignment = 0; WDI_DS_PrepareBDHeader(pFrame, ucSwFrameTXXlation, alignment); if (pTxMetadata->isEapol) { WPAL_TRACE( eWLAN_MODULE_DAL_CTRL, eWLAN_PAL_TRACE_LEVEL_INFO, "Packet Length is %d\n", pTxMetadata->fPktlen); } wdiStatus = WDI_FillTxBd(pContext, ucTypeSubtype, pSTAMACAddress, pAddr2MACAddress, &ucUP, 1, pvBDHeader, ucTxFlag , ucProtMgmtFrame, 0, isEapol, &staId); if(WDI_STATUS_SUCCESS != wdiStatus) { WDI_DS_MemPoolFree(pMemPool, pvBDHeader, physBDHeader); return wdiStatus; } pTxMetadata->staIdx = staId; if(eWLAN_PAL_STATUS_SUCCESS !=WDTS_TxPacket(pContext, pFrame)){ WDI_DS_MemPoolFree(pMemPool, pvBDHeader, physBDHeader); return WDI_STATUS_E_FAILURE; } #ifdef FEATURE_WLAN_TDLS if((WDI_MAC_DATA_FRAME == ucType) && (!pTxMetadata->isEapol) && ((pTxMetadata->txFlags & WDI_USE_BD_RATE2_FOR_MANAGEMENT_FRAME) != WDI_USE_BD_RATE2_FOR_MANAGEMENT_FRAME)) #else if(WDI_MAC_DATA_FRAME == ucType && (!pTxMetadata->isEapol)) #endif { WDI_DS_MemPoolIncreaseReserveCount(pMemPool, staId); } return WDI_STATUS_SUCCESS; }
static void WCTS_NotifyCallback ( void *data, unsigned event ) { wpt_msg *palMsg; WCTS_ControlBlockType* pWCTSCb = (WCTS_ControlBlockType*) data; if (WCTS_CB_MAGIC != pWCTSCb->wctsMagic) { WPAL_TRACE(eWLAN_MODULE_DAL_CTRL, eWLAN_PAL_TRACE_LEVEL_ERROR, "%s: Received unexpected SMD event %u", __func__, event); return; } switch (event) { case SMD_EVENT_OPEN: WPAL_TRACE(eWLAN_MODULE_DAL_CTRL, eWLAN_PAL_TRACE_LEVEL_INFO, "%s: received SMD_EVENT_OPEN from SMD", __func__); if (WCTS_STATE_REM_CLOSED == pWCTSCb->wctsState) { WPAL_TRACE(eWLAN_MODULE_DAL_CTRL, eWLAN_PAL_TRACE_LEVEL_INFO, "%s: received SMD_EVENT_OPEN in WCTS_STATE_REM_CLOSED state", __func__); wpalDriverReInit(); return; } palMsg = &pWCTSCb->wctsOpenMsg; break; case SMD_EVENT_DATA: if (WCTS_STATE_REM_CLOSED == pWCTSCb->wctsState) { WPAL_TRACE(eWLAN_MODULE_DAL_CTRL, eWLAN_PAL_TRACE_LEVEL_ERROR, "%s: received SMD data when the state is remote closed ", __func__); return; } WPAL_TRACE(eWLAN_MODULE_DAL_CTRL, eWLAN_PAL_TRACE_LEVEL_INFO, "%s: received SMD_EVENT_DATA from SMD", __func__); palMsg = &pWCTSCb->wctsDataMsg; break; case SMD_EVENT_CLOSE: WPAL_TRACE(eWLAN_MODULE_DAL_CTRL, eWLAN_PAL_TRACE_LEVEL_INFO, "%s: received SMD_EVENT_CLOSE from SMD", __func__); pWCTSCb->wctsState = WCTS_STATE_REM_CLOSED; WPAL_TRACE(eWLAN_MODULE_DAL_CTRL, eWLAN_PAL_TRACE_LEVEL_INFO, "%s: received SMD_EVENT_CLOSE WLAN driver going down now", __func__); wpalDriverShutdown(); return; case SMD_EVENT_STATUS: WPAL_TRACE(eWLAN_MODULE_DAL_CTRL, eWLAN_PAL_TRACE_LEVEL_INFO, "%s: received SMD_EVENT_STATUS from SMD", __func__); return; case SMD_EVENT_REOPEN_READY: WPAL_TRACE(eWLAN_MODULE_DAL_CTRL, eWLAN_PAL_TRACE_LEVEL_ERROR, "%s: received SMD_EVENT_REOPEN_READY from SMD", __func__); wpalEventSet(&pWCTSCb->wctsEvent); return; default: WPAL_TRACE(eWLAN_MODULE_DAL_CTRL, eWLAN_PAL_TRACE_LEVEL_ERROR, "%s: Unexpected event %u received from SMD", __func__, event); return; } wpalPostCtrlMsg(WDI_GET_PAL_CTX(), palMsg); }
/*--------------------------------------------------------------------------- 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*/
WCTS_HandleType WCTS_OpenTransport ( const wpt_uint8* szName, wpt_uint32 uSize, WCTS_TransportCBsType* wctsCBs ) { WCTS_ControlBlockType* pWCTSCb; wpt_status status; int smdstatus; if ((NULL == wctsCBs) || (NULL == szName) || (NULL == wctsCBs->wctsNotifyCB) || (NULL == wctsCBs->wctsRxMsgCB)) { WPAL_TRACE(eWLAN_MODULE_DAL_CTRL, eWLAN_PAL_TRACE_LEVEL_ERROR, "WCTS_OpenTransport: Invalid parameters received."); return NULL; } if (gwctsHandle) { WPAL_TRACE(eWLAN_MODULE_DAL_CTRL, eWLAN_PAL_TRACE_LEVEL_INFO, "WCTS_OpenTransport port is already open"); pWCTSCb = gwctsHandle; if (WCTS_CB_MAGIC != pWCTSCb->wctsMagic) { WPAL_TRACE(eWLAN_MODULE_DAL_CTRL, eWLAN_PAL_TRACE_LEVEL_FATAL, "WCTS_OpenTransport: Invalid magic."); return NULL; } pWCTSCb->wctsState = WCTS_STATE_OPEN; pWCTSCb->wctsNotifyCB((WCTS_HandleType)pWCTSCb, WCTS_EVENT_OPEN, pWCTSCb->wctsNotifyCBData); smd_disable_read_intr(pWCTSCb->wctsChannel); return (WCTS_HandleType)pWCTSCb; } #ifdef FEATURE_R33D if(port_open) { ctsCB->wctsState = WCTS_STATE_OPEN; ctsCB->wctsNotifyCB((WCTS_HandleType)ctsCB, WCTS_EVENT_OPEN, ctsCB->wctsNotifyCBData); return (WCTS_HandleType)ctsCB; } #endif pWCTSCb = wpalMemoryAllocate(sizeof(*pWCTSCb)); if (NULL == pWCTSCb) { WPAL_TRACE(eWLAN_MODULE_DAL_CTRL, eWLAN_PAL_TRACE_LEVEL_ERROR, "WCTS_OpenTransport: Memory allocation failure."); return NULL; } wpalMemoryZero(pWCTSCb, sizeof(*pWCTSCb)); #ifdef FEATURE_R33D smd_init(0); port_open = 1; ctsCB = pWCTSCb; #endif wpalEventInit(&pWCTSCb->wctsEvent); pWCTSCb->wctsNotifyCB = wctsCBs->wctsNotifyCB; pWCTSCb->wctsNotifyCBData = wctsCBs->wctsNotifyCBData; pWCTSCb->wctsRxMsgCB = wctsCBs->wctsRxMsgCB; pWCTSCb->wctsRxMsgCBData = wctsCBs->wctsRxMsgCBData; wpal_list_init(&pWCTSCb->wctsPendingQueue); pWCTSCb->wctsMagic = WCTS_CB_MAGIC; pWCTSCb->wctsState = WCTS_STATE_OPEN_PENDING; pWCTSCb->wctsChannel = NULL; pWCTSCb->wctsOpenMsg.callback = WCTS_PALOpenCallback; pWCTSCb->wctsOpenMsg.pContext = pWCTSCb; pWCTSCb->wctsOpenMsg.type= WPAL_MC_MSG_SMD_NOTIF_OPEN_SIG; pWCTSCb->wctsDataMsg.callback = WCTS_PALDataCallback; pWCTSCb->wctsDataMsg.pContext = pWCTSCb; pWCTSCb-> wctsDataMsg.type= WPAL_MC_MSG_SMD_NOTIF_DATA_SIG; wpalEventReset(&pWCTSCb->wctsEvent); smdstatus = smd_named_open_on_edge(szName, SMD_APPS_WCNSS, &pWCTSCb->wctsChannel, pWCTSCb, WCTS_NotifyCallback); if (0 != smdstatus) { WPAL_TRACE(eWLAN_MODULE_DAL_CTRL, eWLAN_PAL_TRACE_LEVEL_ERROR, "%s: smd_named_open_on_edge failed with status %d", __func__, smdstatus); goto fail; } status = wpalEventWait(&pWCTSCb->wctsEvent, WCTS_SMD_OPEN_TIMEOUT); if (eWLAN_PAL_STATUS_SUCCESS != status) { WPAL_TRACE(eWLAN_MODULE_DAL_CTRL, eWLAN_PAL_TRACE_LEVEL_ERROR, "%s: failed to receive SMD_EVENT_OPEN", __func__); smdstatus = smd_close(pWCTSCb->wctsChannel); if (0 != smdstatus) { WPAL_TRACE(eWLAN_MODULE_DAL_CTRL, eWLAN_PAL_TRACE_LEVEL_ERROR, "%s: smd_close failed with status %d", __func__, smdstatus); } goto fail; } smd_disable_read_intr(pWCTSCb->wctsChannel); gwctsHandle = pWCTSCb; return (WCTS_HandleType)pWCTSCb; fail: pWCTSCb->wctsMagic = 0; wpalMemoryFree(pWCTSCb); return NULL; }
wpt_uint32 WCTS_CloseTransport ( WCTS_HandleType wctsHandle ) { WCTS_ControlBlockType* pWCTSCb = (WCTS_ControlBlockType*) wctsHandle; wpt_list_node* pNode = NULL; WCTS_BufferType* pBufferQueue = NULL; void* pBuffer = NULL; wpt_status status; int smdstatus; if ((NULL == pWCTSCb) || (WCTS_CB_MAGIC != pWCTSCb->wctsMagic)) { WPAL_TRACE(eWLAN_MODULE_DAL_CTRL, eWLAN_PAL_TRACE_LEVEL_ERROR, "WCTS_CloseTransport: Invalid parameters received."); return eWLAN_PAL_STATUS_E_INVAL; } #ifdef FEATURE_R33D pWCTSCb->wctsState = WCTS_STATE_CLOSED; pWCTSCb->wctsNotifyCB((WCTS_HandleType)pWCTSCb, WCTS_EVENT_CLOSE, pWCTSCb->wctsNotifyCBData); printk(KERN_ERR "R33D Not need to close"); return eWLAN_PAL_STATUS_SUCCESS; #endif while (eWLAN_PAL_STATUS_SUCCESS == wpal_list_remove_front(&pWCTSCb->wctsPendingQueue, &pNode)) { pBufferQueue = container_of(pNode, WCTS_BufferType, node); pBuffer = pBufferQueue->pBuffer; wpalMemoryFree(pBuffer); wpalMemoryFree(pBufferQueue); } pWCTSCb->wctsState = WCTS_STATE_CLOSED; wpalEventReset(&pWCTSCb->wctsEvent); smdstatus = smd_close(pWCTSCb->wctsChannel); if (0 != smdstatus) { WPAL_TRACE(eWLAN_MODULE_DAL_CTRL, eWLAN_PAL_TRACE_LEVEL_ERROR, "%s: smd_close failed with status %d", __func__, smdstatus); } else { status = wpalEventWait(&pWCTSCb->wctsEvent, WCTS_SMD_CLOSE_TIMEOUT); if (eWLAN_PAL_STATUS_SUCCESS != status) { WPAL_TRACE(eWLAN_MODULE_DAL_CTRL, eWLAN_PAL_TRACE_LEVEL_ERROR, "%s: failed to receive SMD_EVENT_REOPEN_READY", __func__); } msleep(50); } pWCTSCb->wctsNotifyCB((WCTS_HandleType)pWCTSCb, WCTS_EVENT_CLOSE, pWCTSCb->wctsNotifyCBData); pWCTSCb->wctsMagic = 0; wpalMemoryFree(pWCTSCb); gwctsHandle = NULL; return eWLAN_PAL_STATUS_SUCCESS; }
wpt_uint32 WCTS_SendMessage ( WCTS_HandleType wctsHandle, void* pMsg, wpt_uint32 uLen ) { WCTS_ControlBlockType* pWCTSCb = (WCTS_ControlBlockType*) wctsHandle; WCTS_BufferType* pBufferQueue; int len; int written = 0; int available; if ((NULL == pWCTSCb) || (WCTS_CB_MAGIC != pWCTSCb->wctsMagic) || (NULL == pMsg) || (0 == uLen) || (0x7fffffff < uLen)) { WPAL_TRACE(eWLAN_MODULE_DAL_CTRL, eWLAN_PAL_TRACE_LEVEL_ERROR, "WCTS_SendMessage: Invalid parameters received."); WPAL_ASSERT(0); if (NULL != pMsg) { wpalMemoryFree(pMsg); } return eWLAN_PAL_STATUS_E_INVAL; } len = (int)uLen; if (WCTS_STATE_OPEN == pWCTSCb->wctsState) { available = smd_write_avail(pWCTSCb->wctsChannel); if (available >= len) { written = smd_write(pWCTSCb->wctsChannel, pMsg, len); } } else if (WCTS_STATE_DEFERRED == pWCTSCb->wctsState) { WPAL_TRACE(eWLAN_MODULE_DAL_CTRL, eWLAN_PAL_TRACE_LEVEL_INFO, "WCTS_SendMessage: FIFO space not available, the packets will be queued"); } else { WPAL_TRACE(eWLAN_MODULE_DAL_CTRL, eWLAN_PAL_TRACE_LEVEL_ERROR, "WCTS_SendMessage: Channel in illegal state [%d].", pWCTSCb->wctsState); written = -1; } if (-1 == written) { WPAL_TRACE(eWLAN_MODULE_DAL_CTRL, eWLAN_PAL_TRACE_LEVEL_ERROR, "WCTS_SendMessage: Failed to send message over the bus."); wpalMemoryFree(pMsg); return eWLAN_PAL_STATUS_E_FAILURE; } else if (written == len) { wpalMemoryFree(pMsg); } else { /* This much data cannot be written at this time, queue the rest of the data for later*/ pBufferQueue = wpalMemoryAllocate(sizeof(WCTS_BufferType)); if (NULL == pBufferQueue) { WPAL_TRACE(eWLAN_MODULE_DAL_CTRL, eWLAN_PAL_TRACE_LEVEL_ERROR, "WCTS_SendMessage: Cannot allocate memory for queuing the buffer"); wpalMemoryFree(pMsg); WPAL_ASSERT(0); return eWLAN_PAL_STATUS_E_NOMEM; } pBufferQueue->bufferSize = len; pBufferQueue->pBuffer = pMsg; wpal_list_insert_back(&pWCTSCb->wctsPendingQueue, &pBufferQueue->node); if (WCTS_STATE_DEFERRED != pWCTSCb->wctsState) { pWCTSCb->wctsState = WCTS_STATE_DEFERRED; smd_enable_read_intr(pWCTSCb->wctsChannel); } return eWLAN_PAL_STATUS_E_RESOURCES; } return eWLAN_PAL_STATUS_SUCCESS; }
/** @brief WDI_STATableAddSta - Function to Add Station @param pWDICtx: pointer to the WLAN DAL context pwdiParam: station parameters @see @return Result of the function call */ WDI_Status WDI_STATableAddSta ( WDI_ControlBlockType* pWDICtx, WDI_AddStaParams* pwdiParam ) { wpt_uint8 ucSTAIdx = 0; WDI_StaStruct* pSTATable = (WDI_StaStruct*) pWDICtx->staTable; /*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ /*----------------------------------------------------------------------- Sanity check - station ids are allocated by the HAL located on RIVA SS - they must always be valid -----------------------------------------------------------------------*/ if (( pwdiParam->ucSTAIdx == WDI_STA_INVALID_IDX) || ( pwdiParam->ucSTAIdx >= pWDICtx->ucMaxStations )) { WPAL_TRACE(eWLAN_MODULE_DAL_CTRL, eWLAN_PAL_TRACE_LEVEL_ERROR, "Station id sent by HAL is invalid - not OK"); WDI_ASSERT(0); return WDI_STATUS_E_FAILURE; } ucSTAIdx = pwdiParam->ucSTAIdx; /*Since we are not the allocator of STA Ids but HAL is - just set flag to valid*/ pSTATable[ucSTAIdx].valid = 1; // Save the STA type - this is used for lookup WDI_STATableSetStaType(pWDICtx, ucSTAIdx, pwdiParam->ucStaType); WDI_STATableSetStaQosEnabled(pWDICtx, ucSTAIdx, (wpt_uint8)(pwdiParam->ucWmmEnabled | pwdiParam->ucHTCapable) ); #ifdef WLAN_PERF pWDICtx->uBdSigSerialNum ++; #endif wpalMemoryCopy(pSTATable[ucSTAIdx].macBSSID, pwdiParam->macBSSID, WDI_MAC_ADDR_LEN); /*------------------------------------------------------------------------ Set DPU Related Information ------------------------------------------------------------------------*/ pSTATable[ucSTAIdx].dpuIndex = pwdiParam->dpuIndex; pSTATable[ucSTAIdx].dpuSig = pwdiParam->dpuSig; pSTATable[ucSTAIdx].bcastDpuIndex = pwdiParam->bcastDpuIndex; pSTATable[ucSTAIdx].bcastDpuSignature = pwdiParam->bcastDpuSignature; pSTATable[ucSTAIdx].bcastMgmtDpuIndex = pwdiParam->bcastMgmtDpuIndex; pSTATable[ucSTAIdx].bcastMgmtDpuSignature = pwdiParam->bcastMgmtDpuSignature; /*Robust Mgmt Frame enabled */ pSTATable[ucSTAIdx].rmfEnabled = pwdiParam->ucRmfEnabled; pSTATable[ucSTAIdx].bssIdx = pwdiParam->ucBSSIdx; /* Now update the STA entry with the new MAC address */ if(WDI_STATUS_SUCCESS != WDI_STATableSetStaAddr( pWDICtx, ucSTAIdx, pwdiParam->staMacAddr)) { WPAL_TRACE(eWLAN_MODULE_DAL_CTRL, eWLAN_PAL_TRACE_LEVEL_ERROR, "Failed to update station entry - internal failure"); WDI_ASSERT(0); return WDI_STATUS_E_FAILURE; } /* Now update the STA entry with the new BSSID address */ if(WDI_STATUS_SUCCESS != WDI_STATableSetBSSID( pWDICtx, ucSTAIdx, pwdiParam->macBSSID)) { WPAL_TRACE(eWLAN_MODULE_DAL_CTRL, eWLAN_PAL_TRACE_LEVEL_ERROR, "Failed to update station entry - internal failure"); WDI_ASSERT(0); return WDI_STATUS_E_FAILURE; } return WDI_STATUS_SUCCESS; }/*WDI_AddSta*/
WDI_Status WDI_STATableAddSta ( WDI_ControlBlockType* pWDICtx, WDI_AddStaParams* pwdiParam ) { wpt_uint8 ucSTAIdx = 0; WDI_StaStruct* pSTATable = (WDI_StaStruct*) pWDICtx->staTable; if (( pwdiParam->ucSTAIdx == WDI_STA_INVALID_IDX) || ( pwdiParam->ucSTAIdx >= pWDICtx->ucMaxStations )) { WPAL_TRACE(eWLAN_MODULE_DAL_CTRL, eWLAN_PAL_TRACE_LEVEL_ERROR, "Station id sent by HAL is invalid - not OK"); WDI_ASSERT(0); return WDI_STATUS_E_FAILURE; } ucSTAIdx = pwdiParam->ucSTAIdx; pSTATable[ucSTAIdx].valid = 1; WDI_STATableSetStaType(pWDICtx, ucSTAIdx, pwdiParam->ucStaType); WDI_STATableSetStaQosEnabled(pWDICtx, ucSTAIdx, (wpt_uint8)(pwdiParam->ucWmmEnabled | pwdiParam->ucHTCapable) ); #ifdef WLAN_PERF pWDICtx->uBdSigSerialNum ++; #endif wpalMemoryCopy(pSTATable[ucSTAIdx].macBSSID, pwdiParam->macBSSID, WDI_MAC_ADDR_LEN); pSTATable[ucSTAIdx].dpuIndex = pwdiParam->dpuIndex; pSTATable[ucSTAIdx].dpuSig = pwdiParam->dpuSig; pSTATable[ucSTAIdx].bcastDpuIndex = pwdiParam->bcastDpuIndex; pSTATable[ucSTAIdx].bcastDpuSignature = pwdiParam->bcastDpuSignature; pSTATable[ucSTAIdx].bcastMgmtDpuIndex = pwdiParam->bcastMgmtDpuIndex; pSTATable[ucSTAIdx].bcastMgmtDpuSignature = pwdiParam->bcastMgmtDpuSignature; pSTATable[ucSTAIdx].rmfEnabled = pwdiParam->ucRmfEnabled; pSTATable[ucSTAIdx].bssIdx = pwdiParam->ucBSSIdx; if(WDI_STATUS_SUCCESS != WDI_STATableSetStaAddr( pWDICtx, ucSTAIdx, pwdiParam->staMacAddr)) { WPAL_TRACE(eWLAN_MODULE_DAL_CTRL, eWLAN_PAL_TRACE_LEVEL_ERROR, "Failed to update station entry - internal failure"); WDI_ASSERT(0); return WDI_STATUS_E_FAILURE; } if(WDI_STATUS_SUCCESS != WDI_STATableSetBSSID( pWDICtx, ucSTAIdx, pwdiParam->macBSSID)) { WPAL_TRACE(eWLAN_MODULE_DAL_CTRL, eWLAN_PAL_TRACE_LEVEL_ERROR, "Failed to update station entry - internal failure"); WDI_ASSERT(0); return WDI_STATUS_E_FAILURE; } return WDI_STATUS_SUCCESS; }