| /****************************************************************************** |
| * |
| * This file is provided under a dual license. When you use or |
| * distribute this software, you may choose to be licensed under |
| * version 2 of the GNU General Public License ("GPLv2 License") |
| * or BSD License. |
| * |
| * GPLv2 License |
| * |
| * Copyright(C) 2016 MediaTek Inc. |
| * |
| * This program is free software; you can redistribute it and/or modify |
| * it under the terms of version 2 of the GNU General Public License as |
| * published by the Free Software Foundation. |
| * |
| * This program is distributed in the hope that it will be useful, but |
| * WITHOUT ANY WARRANTY; without even the implied warranty of |
| * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. |
| * See http://www.gnu.org/licenses/gpl-2.0.html for more details. |
| * |
| * BSD LICENSE |
| * |
| * Copyright(C) 2016 MediaTek Inc. All rights reserved. |
| * |
| * Redistribution and use in source and binary forms, with or without |
| * modification, are permitted provided that the following conditions |
| * are met: |
| * |
| * * Redistributions of source code must retain the above copyright |
| * notice, this list of conditions and the following disclaimer. |
| * * Redistributions in binary form must reproduce the above copyright |
| * notice, this list of conditions and the following disclaimer in |
| * the documentation and/or other materials provided with the |
| * distribution. |
| * * Neither the name of the copyright holder nor the names of its |
| * contributors may be used to endorse or promote products derived |
| * from this software without specific prior written permission. |
| * |
| * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
| * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
| * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
| * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
| * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
| * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
| * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
| * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
| * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
| * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
| * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| * |
| *****************************************************************************/ |
| /****************************************************************************** |
| *[File] hif_api.c |
| *[Version] v1.0 |
| *[Revision Date] 2015-09-08 |
| *[Author] |
| *[Description] |
| * The program provides USB HIF APIs |
| *[Copyright] |
| * Copyright (C) 2015 MediaTek Incorporation. All Rights Reserved. |
| ******************************************************************************/ |
| |
| /******************************************************************************* |
| * C O M P I L E R F L A G S |
| ******************************************************************************** |
| */ |
| |
| /******************************************************************************* |
| * E X T E R N A L R E F E R E N C E S |
| ******************************************************************************** |
| */ |
| #include "precomp.h" |
| |
| #include <linux/usb.h> |
| #include <linux/mutex.h> |
| |
| #include <linux/mm.h> |
| #ifndef CONFIG_X86 |
| #include <asm/memory.h> |
| #endif |
| |
| #include "mt66xx_reg.h" |
| |
| /******************************************************************************* |
| * C O N S T A N T S |
| ******************************************************************************** |
| */ |
| |
| /******************************************************************************* |
| * D A T A T Y P E S |
| ******************************************************************************** |
| */ |
| |
| /******************************************************************************* |
| * P U B L I C D A T A |
| ******************************************************************************** |
| */ |
| |
| /******************************************************************************* |
| * P R I V A T E D A T A |
| ******************************************************************************** |
| */ |
| static const UINT_16 arTcToUSBEP[USB_TC_NUM] = { |
| USB_DATA_BULK_OUT_EP4, |
| USB_DATA_BULK_OUT_EP5, |
| USB_DATA_BULK_OUT_EP6, |
| USB_DATA_BULK_OUT_EP7, |
| USB_DATA_BULK_OUT_EP8, |
| USB_DATA_BULK_OUT_EP4, |
| USB_DATA_BULK_OUT_EP9, |
| |
| /* Second HW queue */ |
| #if NIC_TX_ENABLE_SECOND_HW_QUEUE |
| USB_DATA_BULK_OUT_EP9, |
| USB_DATA_BULK_OUT_EP9, |
| USB_DATA_BULK_OUT_EP9, |
| USB_DATA_BULK_OUT_EP9, |
| #endif |
| }; |
| |
| /******************************************************************************* |
| * M A C R O S |
| ******************************************************************************** |
| */ |
| |
| /******************************************************************************* |
| * F U N C T I O N D E C L A R A T I O N S |
| ******************************************************************************** |
| */ |
| |
| /******************************************************************************* |
| * F U N C T I O N S |
| ******************************************************************************** |
| */ |
| |
| /*----------------------------------------------------------------------------*/ |
| /*! |
| * @brief Verify the CHIP ID |
| * |
| * @param prAdapter a pointer to adapter private data structure. |
| * |
| * |
| * @retval TRUE CHIP ID is the same as the setting compiled |
| * @retval FALSE CHIP ID is different from the setting compiled |
| */ |
| /*----------------------------------------------------------------------------*/ |
| BOOL halVerifyChipID(IN P_ADAPTER_T prAdapter) |
| { |
| UINT_32 u4CIR = 0; |
| struct mt66xx_chip_info *prChipInfo; |
| |
| ASSERT(prAdapter); |
| |
| if (prAdapter->fgIsReadRevID) |
| return TRUE; |
| |
| prChipInfo = prAdapter->chip_info; |
| |
| HAL_MCR_RD(prAdapter, TOP_HCR, &u4CIR); |
| DBGLOG(INIT, TRACE, "Chip ID: 0x%lx\n", u4CIR); |
| |
| if (u4CIR != prChipInfo->chip_id) |
| return FALSE; |
| |
| HAL_MCR_RD(prAdapter, TOP_HVR, &u4CIR); |
| DBGLOG(INIT, TRACE, "Revision ID: 0x%lx\n", u4CIR); |
| |
| prAdapter->ucRevID = (UINT_8) (u4CIR & 0xF); |
| prAdapter->fgIsReadRevID = TRUE; |
| return TRUE; |
| } |
| |
| WLAN_STATUS |
| halRxWaitResponse(IN P_ADAPTER_T prAdapter, IN UINT_8 ucPortIdx, OUT PUINT_8 pucRspBuffer, |
| IN UINT_32 u4MaxRespBufferLen, OUT PUINT_32 pu4Length) |
| { |
| P_GL_HIF_INFO_T prHifInfo = &prAdapter->prGlueInfo->rHifInfo; |
| WLAN_STATUS u4Status = WLAN_STATUS_SUCCESS; |
| P_RX_CTRL_T prRxCtrl; |
| BOOL ret = FALSE; |
| |
| DEBUGFUNC("halRxWaitResponse"); |
| |
| ASSERT(prAdapter); |
| ASSERT(pucRspBuffer); |
| |
| prRxCtrl = &prAdapter->rRxCtrl; |
| |
| if (prHifInfo->fgEventEpDetected == FALSE) { |
| /* NOTE: This is temporary compatiable code with old/new CR4 FW to detect which EVENT endpoint that |
| * CR4 FW is using. If the new EP4IN-using CR4 FW works without any issue for a while, |
| * this code block will be removed. |
| */ |
| if (prAdapter->fgIsCr4FwDownloaded) { |
| ucPortIdx = USB_DATA_EP_IN; |
| ret = kalDevPortRead(prAdapter->prGlueInfo, ucPortIdx, |
| ALIGN_4(u4MaxRespBufferLen) + LEN_USB_RX_PADDING_CSO, |
| prRxCtrl->pucRxCoalescingBufPtr, HIF_RX_COALESCING_BUFFER_SIZE); |
| |
| if (ret == TRUE) { |
| prHifInfo->eEventEpType = EVENT_EP_TYPE_DATA_EP; |
| } else { |
| ucPortIdx = USB_EVENT_EP_IN; |
| ret = kalDevPortRead(prAdapter->prGlueInfo, ucPortIdx, |
| ALIGN_4(u4MaxRespBufferLen) + LEN_USB_RX_PADDING_CSO, |
| prRxCtrl->pucRxCoalescingBufPtr, HIF_RX_COALESCING_BUFFER_SIZE); |
| } |
| prHifInfo->fgEventEpDetected = TRUE; |
| |
| kalMemCopy(pucRspBuffer, prRxCtrl->pucRxCoalescingBufPtr, u4MaxRespBufferLen); |
| *pu4Length = u4MaxRespBufferLen; |
| |
| if (ret == FALSE) |
| u4Status = WLAN_STATUS_FAILURE; |
| return u4Status; |
| } |
| |
| ucPortIdx = USB_EVENT_EP_IN; |
| } else { |
| if (prHifInfo->eEventEpType == EVENT_EP_TYPE_DATA_EP) |
| if (prAdapter->fgIsCr4FwDownloaded) |
| ucPortIdx = USB_DATA_EP_IN; |
| else |
| ucPortIdx = USB_EVENT_EP_IN; |
| else |
| ucPortIdx = USB_EVENT_EP_IN; |
| |
| } |
| ret = kalDevPortRead(prAdapter->prGlueInfo, ucPortIdx, |
| ALIGN_4(u4MaxRespBufferLen) + LEN_USB_RX_PADDING_CSO, |
| prRxCtrl->pucRxCoalescingBufPtr, HIF_RX_COALESCING_BUFFER_SIZE); |
| |
| kalMemCopy(pucRspBuffer, prRxCtrl->pucRxCoalescingBufPtr, u4MaxRespBufferLen); |
| *pu4Length = u4MaxRespBufferLen; |
| |
| if (ret == FALSE) |
| u4Status = WLAN_STATUS_FAILURE; |
| |
| return u4Status; |
| } |
| |
| WLAN_STATUS halTxUSBSendCmd(IN P_GLUE_INFO_T prGlueInfo, IN UINT_8 ucTc, IN P_CMD_INFO_T prCmdInfo) |
| { |
| P_GL_HIF_INFO_T prHifInfo = &prGlueInfo->rHifInfo; |
| WLAN_STATUS u4Status = WLAN_STATUS_SUCCESS; |
| P_USB_REQ_T prUsbReq; |
| P_BUF_CTRL_T prBufCtrl; |
| UINT_16 u2OverallBufferLength = 0; |
| unsigned long flags; |
| P_HW_MAC_TX_DESC_T prTxDesc; |
| UINT_8 ucQueIdx; |
| |
| if (prHifInfo->state != USB_STATE_LINK_UP && |
| !(prHifInfo->state == USB_STATE_PRE_RESUME && prCmdInfo->ucCID == 0)) |
| return WLAN_STATUS_FAILURE; |
| |
| prUsbReq = glUsbDequeueReq(prHifInfo, &prHifInfo->rTxCmdFreeQ, &prHifInfo->rTxCmdQLock); |
| if (prUsbReq == NULL) |
| return WLAN_STATUS_RESOURCES; |
| |
| prBufCtrl = prUsbReq->prBufCtrl; |
| |
| if ((TFCB_FRAME_PAD_TO_DW(prCmdInfo->u4TxdLen + prCmdInfo->u4TxpLen) + LEN_USB_UDMA_TX_TERMINATOR) > |
| prBufCtrl->u4BufSize) { |
| DBGLOG(HAL, ERROR, "Command TX buffer underflow!\n"); |
| return WLAN_STATUS_RESOURCES; |
| } |
| |
| DBGLOG(HAL, INFO, "TX URB[0x%p]\n", prUsbReq->prUrb); |
| |
| if (prCmdInfo->u4TxdLen) { |
| memcpy((prBufCtrl->pucBuf + u2OverallBufferLength), prCmdInfo->pucTxd, prCmdInfo->u4TxdLen); |
| u2OverallBufferLength += prCmdInfo->u4TxdLen; |
| } |
| |
| if (prCmdInfo->u4TxpLen) { |
| memcpy((prBufCtrl->pucBuf + u2OverallBufferLength), prCmdInfo->pucTxp, prCmdInfo->u4TxpLen); |
| u2OverallBufferLength += prCmdInfo->u4TxpLen; |
| } |
| |
| prTxDesc = (P_HW_MAC_TX_DESC_T)prBufCtrl->pucBuf; |
| ucQueIdx = HAL_MAC_TX_DESC_GET_QUEUE_INDEX(prTxDesc); |
| /* For H2CDMA Tx CMD mapping */ |
| /* Mapping port1 queue0~3 to queue28~31, and CR4 will unmask this */ |
| HAL_MAC_TX_DESC_SET_QUEUE_INDEX(prTxDesc, (ucQueIdx | USB_TX_CMD_QUEUE_MASK)); |
| |
| /* DBGLOG_MEM32(SW4, INFO, prBufCtrl->pucBuf, 32); */ |
| |
| memset(prBufCtrl->pucBuf + u2OverallBufferLength, 0, |
| ((TFCB_FRAME_PAD_TO_DW(u2OverallBufferLength) - u2OverallBufferLength) + LEN_USB_UDMA_TX_TERMINATOR)); |
| prBufCtrl->u4WrIdx = TFCB_FRAME_PAD_TO_DW(u2OverallBufferLength) + LEN_USB_UDMA_TX_TERMINATOR; |
| |
| prUsbReq->prPriv = (PVOID) prCmdInfo; |
| usb_fill_bulk_urb(prUsbReq->prUrb, |
| prHifInfo->udev, |
| usb_sndbulkpipe(prHifInfo->udev, arTcToUSBEP[ucTc]), |
| (void *)prUsbReq->prBufCtrl->pucBuf, |
| prBufCtrl->u4WrIdx, halTxUSBSendCmdComplete, (void *)prUsbReq); |
| |
| #if CFG_USB_CONSISTENT_DMA |
| prUsbReq->prUrb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; |
| #endif |
| spin_lock_irqsave(&prHifInfo->rTxCmdQLock, flags); |
| u4Status = usb_submit_urb(prUsbReq->prUrb, GFP_ATOMIC); |
| if (u4Status) { |
| DBGLOG(HAL, ERROR, "usb_submit_urb() reports error (%d)\n", u4Status); |
| /* glUsbEnqueueReq(prHifInfo, &prHifInfo->rTxCmdFreeQ, &prHifInfo->rTxCmdQLock, prUsbReq); */ |
| list_add_tail(&prUsbReq->list, &prHifInfo->rTxCmdFreeQ); |
| spin_unlock_irqrestore(&prHifInfo->rTxCmdQLock, flags); |
| return WLAN_STATUS_FAILURE; |
| } |
| |
| /* glUsbEnqueueReq(prHifInfo, &prHifInfo->rTxCmdSendingQ, &prHifInfo->rTxCmdQLock, prUsbReq); */ |
| list_add_tail(&prUsbReq->list, &prHifInfo->rTxCmdSendingQ); |
| spin_unlock_irqrestore(&prHifInfo->rTxCmdQLock, flags); |
| |
| if (wlanIsChipRstRecEnabled(prGlueInfo->prAdapter) |
| && wlanIsChipNoAck(prGlueInfo->prAdapter)) { |
| wlanChipRstPreAct(prGlueInfo->prAdapter); |
| DBGLOG(HAL, ERROR, "usb trigger whole reset\n"); |
| HAL_WIFI_FUNC_CHIP_RESET(prGlueInfo->prAdapter); |
| } |
| return u4Status; |
| } |
| |
| VOID halTxUSBSendCmdComplete(struct urb *urb) |
| { |
| P_USB_REQ_T prUsbReq = urb->context; |
| P_GL_HIF_INFO_T prHifInfo = prUsbReq->prHifInfo; |
| P_GLUE_INFO_T prGlueInfo = prHifInfo->prGlueInfo; |
| unsigned long flags; |
| |
| #if CFG_USB_TX_HANDLE_IN_HIF_THREAD |
| spin_lock_irqsave(&prHifInfo->rTxCmdQLock, flags); |
| list_del_init(&prUsbReq->list); |
| list_add_tail(&prUsbReq->list, &prHifInfo->rTxCmdCompleteQ); |
| spin_unlock_irqrestore(&prHifInfo->rTxCmdQLock, flags); |
| |
| kalSetIntEvent(prGlueInfo); |
| #else |
| spin_lock_irqsave(&prHifInfo->rTxCmdQLock, flags); |
| list_del_init(&prUsbReq->list); |
| spin_unlock_irqrestore(&prHifInfo->rTxCmdQLock, flags); |
| |
| halTxUSBProcessCmdComplete(prGlueInfo->prAdapter, prUsbReq); |
| #endif |
| } |
| |
| VOID halTxUSBProcessCmdComplete(IN P_ADAPTER_T prAdapter, P_USB_REQ_T prUsbReq) |
| { |
| struct urb *urb = prUsbReq->prUrb; |
| UINT_32 u4SentDataSize; |
| P_GL_HIF_INFO_T prHifInfo = prUsbReq->prHifInfo; |
| |
| if (urb->status != 0) { |
| DBGLOG(TX, ERROR, "[%s] send CMD fail (status = %d)\n", __func__, urb->status); |
| /* TODO: handle error */ |
| } |
| |
| DBGLOG(HAL, INFO, "TX CMD DONE: URB[0x%p]\n", urb); |
| |
| glUsbEnqueueReq(prHifInfo, &prHifInfo->rTxCmdFreeQ, prUsbReq, &prHifInfo->rTxCmdQLock, FALSE); |
| |
| u4SentDataSize = urb->actual_length - LEN_USB_UDMA_TX_TERMINATOR; |
| nicTxReleaseResource(prAdapter, TC4_INDEX, nicTxGetPageCount(u4SentDataSize, TRUE), TRUE); |
| } |
| |
| VOID halTxCancelSendingCmd(IN P_ADAPTER_T prAdapter, IN P_CMD_INFO_T prCmdInfo) |
| { |
| P_USB_REQ_T prUsbReq, prNext; |
| unsigned long flags; |
| struct urb *urb = NULL; |
| P_GL_HIF_INFO_T prHifInfo = &prAdapter->prGlueInfo->rHifInfo; |
| |
| spin_lock_irqsave(&prHifInfo->rTxCmdQLock, flags); |
| list_for_each_entry_safe(prUsbReq, prNext, &prHifInfo->rTxCmdSendingQ, list) { |
| if (prUsbReq->prPriv == (PVOID) prCmdInfo) { |
| list_del_init(&prUsbReq->list); |
| urb = prUsbReq->prUrb; |
| break; |
| } |
| } |
| spin_unlock_irqrestore(&prHifInfo->rTxCmdQLock, flags); |
| |
| if (urb) { |
| prCmdInfo->pfHifTxCmdDoneCb = NULL; |
| usb_kill_urb(urb); |
| } |
| } |
| |
| VOID halTxCancelAllSending(IN P_ADAPTER_T prAdapter) |
| { |
| P_GLUE_INFO_T prGlueInfo; |
| P_USB_REQ_T prUsbReq, prUsbReqNext; |
| P_GL_HIF_INFO_T prHifInfo; |
| #if CFG_USB_TX_AGG |
| UINT_8 ucTc; |
| #endif |
| |
| ASSERT(prAdapter); |
| prGlueInfo = prAdapter->prGlueInfo; |
| prHifInfo = &prGlueInfo->rHifInfo; |
| |
| list_for_each_entry_safe(prUsbReq, prUsbReqNext, &prHifInfo->rTxCmdSendingQ, list) { |
| usb_kill_urb(prUsbReq->prUrb); |
| } |
| |
| #if CFG_USB_TX_AGG |
| for (ucTc = 0; ucTc < USB_TC_NUM; ++ucTc) { |
| usb_kill_anchored_urbs(&prHifInfo->rTxDataAnchor[ucTc]); |
| } |
| #else |
| usb_kill_anchored_urbs(&prHifInfo->rTxDataAnchor); |
| #endif |
| } |
| |
| #if CFG_USB_TX_AGG |
| WLAN_STATUS halTxUSBSendAggData(IN P_GL_HIF_INFO_T prHifInfo, IN UINT_8 ucTc, IN P_USB_REQ_T prUsbReq) |
| { |
| P_GLUE_INFO_T prGlueInfo = prHifInfo->prGlueInfo; |
| P_BUF_CTRL_T prBufCtrl = prUsbReq->prBufCtrl; |
| WLAN_STATUS u4Status = WLAN_STATUS_SUCCESS; |
| |
| memset(prBufCtrl->pucBuf + prBufCtrl->u4WrIdx, 0, LEN_USB_UDMA_TX_TERMINATOR); |
| prBufCtrl->u4WrIdx += LEN_USB_UDMA_TX_TERMINATOR; |
| |
| if (prHifInfo->state != USB_STATE_LINK_UP) { |
| list_del_init(&prUsbReq->list); |
| list_add_tail(&prUsbReq->list, &prHifInfo->rTxDataCompleteQ); |
| |
| #if CFG_USB_TX_HANDLE_IN_HIF_THREAD |
| kalSetIntEvent(prGlueInfo); |
| #else |
| /*tasklet_hi_schedule(&prGlueInfo->rTxCompleteTask);*/ |
| tasklet_schedule(&prGlueInfo->rTxCompleteTask); |
| #endif |
| return WLAN_STATUS_FAILURE; |
| } |
| |
| list_del_init(&prUsbReq->list); |
| |
| usb_fill_bulk_urb(prUsbReq->prUrb, |
| prHifInfo->udev, |
| usb_sndbulkpipe(prHifInfo->udev, arTcToUSBEP[ucTc]), |
| (void *)prBufCtrl->pucBuf, prBufCtrl->u4WrIdx, halTxUSBSendDataComplete, (void *)prUsbReq); |
| #if CFG_USB_CONSISTENT_DMA |
| prUsbReq->prUrb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; |
| #endif |
| |
| usb_anchor_urb(prUsbReq->prUrb, &prHifInfo->rTxDataAnchor[ucTc]); |
| u4Status = usb_submit_urb(prUsbReq->prUrb, GFP_ATOMIC); |
| if (u4Status) { |
| DBGLOG(HAL, ERROR, "usb_submit_urb() reports error (%d) [%s]\n", u4Status, __func__); |
| halTxUSBProcessMsduDone(prHifInfo->prGlueInfo, prUsbReq); |
| prBufCtrl->u4WrIdx = 0; |
| usb_unanchor_urb(prUsbReq->prUrb); |
| list_add_tail(&prUsbReq->list, &prHifInfo->rTxDataFreeQ[ucTc]); |
| return WLAN_STATUS_FAILURE; |
| } |
| |
| return u4Status; |
| } |
| #endif |
| |
| WLAN_STATUS halTxUSBSendData(IN P_GLUE_INFO_T prGlueInfo, IN P_MSDU_INFO_T prMsduInfo) |
| { |
| P_GL_HIF_INFO_T prHifInfo = &prGlueInfo->rHifInfo; |
| WLAN_STATUS u4Status = WLAN_STATUS_SUCCESS; |
| P_USB_REQ_T prUsbReq; |
| P_BUF_CTRL_T prBufCtrl; |
| UINT_32 u4PaddingLength; |
| struct sk_buff *skb; |
| UINT_8 ucTc; |
| UINT_8 *pucBuf; |
| UINT_32 u4Length; |
| #if CFG_USB_TX_AGG |
| unsigned long flags; |
| #endif |
| |
| skb = (struct sk_buff *)prMsduInfo->prPacket; |
| pucBuf = skb->data; |
| u4Length = skb->len; |
| ucTc = USB_TRANS_MSDU_TC(prMsduInfo); |
| #if CFG_USB_TX_AGG |
| spin_lock_irqsave(&prHifInfo->rTxDataFreeQLock, flags); |
| |
| if (list_empty(&prHifInfo->rTxDataFreeQ[ucTc])) { |
| spin_unlock_irqrestore(&prHifInfo->rTxDataFreeQLock, flags); |
| DBGLOG(HAL, ERROR, "run out of rTxDataFreeQ #1!!\n"); |
| wlanProcessQueuedMsduInfo(prGlueInfo->prAdapter, prMsduInfo); |
| return WLAN_STATUS_RESOURCES; |
| } |
| prUsbReq = list_entry(prHifInfo->rTxDataFreeQ[ucTc].next, struct _USB_REQ_T, list); |
| prBufCtrl = prUsbReq->prBufCtrl; |
| |
| if (prHifInfo->u4AggRsvSize < ALIGN_4(u4Length)) |
| DBGLOG(HAL, ERROR, "u4AggRsvSize count FAIL (%u, %u)\n", prHifInfo->u4AggRsvSize, u4Length); |
| prHifInfo->u4AggRsvSize -= ALIGN_4(u4Length); |
| |
| if (prBufCtrl->u4WrIdx + ALIGN_4(u4Length) + LEN_USB_UDMA_TX_TERMINATOR > prBufCtrl->u4BufSize) { |
| halTxUSBSendAggData(prHifInfo, ucTc, prUsbReq); |
| |
| if (list_empty(&prHifInfo->rTxDataFreeQ[ucTc])) { |
| spin_unlock_irqrestore(&prHifInfo->rTxDataFreeQLock, flags); |
| DBGLOG(HAL, ERROR, "run out of rTxDataFreeQ #2!!\n"); |
| wlanProcessQueuedMsduInfo(prGlueInfo->prAdapter, prMsduInfo); |
| return WLAN_STATUS_FAILURE; |
| } |
| |
| prUsbReq = list_entry(prHifInfo->rTxDataFreeQ[ucTc].next, struct _USB_REQ_T, list); |
| prBufCtrl = prUsbReq->prBufCtrl; |
| } |
| |
| memcpy(prBufCtrl->pucBuf + prBufCtrl->u4WrIdx, pucBuf, u4Length); |
| prBufCtrl->u4WrIdx += u4Length; |
| |
| u4PaddingLength = (ALIGN_4(u4Length) - u4Length); |
| if (u4PaddingLength) { |
| memset(prBufCtrl->pucBuf + prBufCtrl->u4WrIdx, 0, u4PaddingLength); |
| prBufCtrl->u4WrIdx += u4PaddingLength; |
| } |
| |
| if (!prMsduInfo->pfTxDoneHandler) |
| QUEUE_INSERT_TAIL(&prUsbReq->rSendingDataMsduInfoList, (P_QUE_ENTRY_T) prMsduInfo); |
| |
| if (usb_anchor_empty(&prHifInfo->rTxDataAnchor[ucTc])) |
| halTxUSBSendAggData(prHifInfo, ucTc, prUsbReq); |
| |
| spin_unlock_irqrestore(&prHifInfo->rTxDataFreeQLock, flags); |
| #else |
| prUsbReq = glUsbDequeueReq(prHifInfo, &prHifInfo->rTxDataFreeQ, &prHifInfo->rTxDataFreeQLock); |
| if (prUsbReq == NULL) { |
| DBGLOG(HAL, ERROR, "run out of rTxDataFreeQ!!\n"); |
| wlanProcessQueuedMsduInfo(prGlueInfo->prAdapter, prMsduInfo); |
| return WLAN_STATUS_RESOURCES; |
| } |
| |
| prBufCtrl = prUsbReq->prBufCtrl; |
| prBufCtrl->u4WrIdx = 0; |
| |
| memcpy(prBufCtrl->pucBuf, pucBuf, u4Length); |
| prBufCtrl->u4WrIdx += u4Length; |
| |
| u4PaddingLength = (ALIGN_4(u4Length) - u4Length); |
| if (u4PaddingLength) { |
| memset(prBufCtrl->pucBuf + prBufCtrl->u4WrIdx, 0, u4PaddingLength); |
| prBufCtrl->u4WrIdx += u4PaddingLength; |
| } |
| |
| memset(prBufCtrl->pucBuf + prBufCtrl->u4WrIdx, 0, LEN_USB_UDMA_TX_TERMINATOR); |
| prBufCtrl->u4WrIdx += LEN_USB_UDMA_TX_TERMINATOR; |
| |
| if (!prMsduInfo->pfTxDoneHandler) |
| QUEUE_INSERT_TAIL(&prUsbReq->rSendingDataMsduInfoList, (P_QUE_ENTRY_T) prMsduInfo); |
| |
| *((PUINT_8)&prUsbReq->prPriv) = ucTc; |
| usb_fill_bulk_urb(prUsbReq->prUrb, |
| prHifInfo->udev, |
| usb_sndbulkpipe(prHifInfo->udev, arTcToUSBEP[ucTc]), |
| (void *)prUsbReq->prBufCtrl->pucBuf, |
| prBufCtrl->u4WrIdx, halTxUSBSendDataComplete, (void *)prUsbReq); |
| #if CFG_USB_CONSISTENT_DMA |
| prUsbReq->prUrb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; |
| #endif |
| |
| usb_anchor_urb(prUsbReq->prUrb, &prHifInfo->rTxDataAnchor); |
| u4Status = usb_submit_urb(prUsbReq->prUrb, GFP_ATOMIC); |
| if (u4Status) { |
| DBGLOG(HAL, ERROR, "usb_submit_urb() reports error (%d) [%s]\n", u4Status, __func__); |
| halTxUSBProcessMsduDone(prHifInfo->prGlueInfo, prUsbReq); |
| prBufCtrl->u4WrIdx = 0; |
| usb_unanchor_urb(prUsbReq->prUrb); |
| glUsbEnqueueReq(prHifInfo, &prHifInfo->rTxDataFreeQ, prUsbReq, &prHifInfo->rTxDataFreeQLock, FALSE); |
| return WLAN_STATUS_FAILURE; |
| } |
| #endif |
| |
| if (wlanIsChipRstRecEnabled(prGlueInfo->prAdapter) |
| && wlanIsChipNoAck(prGlueInfo->prAdapter)) { |
| wlanChipRstPreAct(prGlueInfo->prAdapter); |
| DBGLOG(HAL, ERROR, "usb trigger whole reset\n"); |
| HAL_WIFI_FUNC_CHIP_RESET(prGlueInfo->prAdapter); |
| } |
| return u4Status; |
| } |
| |
| WLAN_STATUS halTxUSBKickData(IN P_GLUE_INFO_T prGlueInfo) |
| { |
| #if CFG_USB_TX_AGG |
| P_GL_HIF_INFO_T prHifInfo = &prGlueInfo->rHifInfo; |
| P_USB_REQ_T prUsbReq; |
| P_BUF_CTRL_T prBufCtrl; |
| UINT_8 ucTc; |
| unsigned long flags; |
| |
| spin_lock_irqsave(&prHifInfo->rTxDataFreeQLock, flags); |
| |
| for (ucTc = TC0_INDEX; ucTc < USB_TC_NUM; ucTc++) { |
| if (list_empty(&prHifInfo->rTxDataFreeQ[ucTc])) |
| continue; |
| |
| prUsbReq = list_entry(prHifInfo->rTxDataFreeQ[ucTc].next, struct _USB_REQ_T, list); |
| prBufCtrl = prUsbReq->prBufCtrl; |
| |
| if (prBufCtrl->u4WrIdx) |
| halTxUSBSendAggData(prHifInfo, ucTc, prUsbReq); |
| } |
| |
| spin_unlock_irqrestore(&prHifInfo->rTxDataFreeQLock, flags); |
| #endif |
| |
| return WLAN_STATUS_SUCCESS; |
| } |
| |
| VOID halTxUSBSendDataComplete(struct urb *urb) |
| { |
| P_USB_REQ_T prUsbReq = urb->context; |
| P_GL_HIF_INFO_T prHifInfo = prUsbReq->prHifInfo; |
| P_GLUE_INFO_T prGlueInfo = prHifInfo->prGlueInfo; |
| |
| glUsbEnqueueReq(prHifInfo, &prHifInfo->rTxDataCompleteQ, prUsbReq, &prHifInfo->rTxDataQLock, FALSE); |
| |
| #if CFG_USB_TX_HANDLE_IN_HIF_THREAD |
| kalSetIntEvent(prGlueInfo); |
| #else |
| /*tasklet_hi_schedule(&prGlueInfo->rTxCompleteTask);*/ |
| tasklet_schedule(&prGlueInfo->rTxCompleteTask); |
| #endif |
| } |
| |
| VOID halTxUSBProcessMsduDone(IN P_GLUE_INFO_T prGlueInfo, P_USB_REQ_T prUsbReq) |
| { |
| UINT_8 ucTc; |
| QUE_T rFreeQueue; |
| P_QUE_T prFreeQueue; |
| struct urb *urb = prUsbReq->prUrb; |
| UINT_32 u4SentDataSize; |
| |
| ucTc = *((PUINT_8)&prUsbReq->prPriv); |
| |
| prFreeQueue = &rFreeQueue; |
| QUEUE_INITIALIZE(prFreeQueue); |
| QUEUE_MOVE_ALL((prFreeQueue), (&(prUsbReq->rSendingDataMsduInfoList))); |
| if (g_pfTxDataDoneCb) |
| g_pfTxDataDoneCb(prGlueInfo, prFreeQueue); |
| |
| u4SentDataSize = urb->actual_length - LEN_USB_UDMA_TX_TERMINATOR; |
| nicTxReleaseResource(prGlueInfo->prAdapter, ucTc, nicTxGetPageCount(u4SentDataSize, TRUE), TRUE); |
| } |
| |
| VOID halTxUSBProcessDataComplete(IN P_ADAPTER_T prAdapter, P_USB_REQ_T prUsbReq) |
| { |
| UINT_8 ucTc; |
| struct urb *urb = prUsbReq->prUrb; |
| P_GL_HIF_INFO_T prHifInfo = prUsbReq->prHifInfo; |
| #if CFG_USB_TX_AGG |
| P_BUF_CTRL_T prBufCtrl = prUsbReq->prBufCtrl; |
| #endif |
| unsigned long flags; |
| |
| ucTc = *((PUINT_8)&prUsbReq->prPriv); |
| |
| if (urb->status != 0) { |
| DBGLOG(TX, ERROR, "[%s] send DATA fail (status = %d)\n", __func__, urb->status); |
| /* TODO: handle error */ |
| } |
| |
| halTxUSBProcessMsduDone(prAdapter->prGlueInfo, prUsbReq); |
| |
| spin_lock_irqsave(&prHifInfo->rTxDataFreeQLock, flags); |
| #if CFG_USB_TX_AGG |
| prBufCtrl->u4WrIdx = 0; |
| |
| list_add_tail(&prUsbReq->list, &prHifInfo->rTxDataFreeQ[ucTc]); |
| |
| if (usb_anchor_empty(&prHifInfo->rTxDataAnchor[ucTc])) { |
| prUsbReq = list_entry(prHifInfo->rTxDataFreeQ[ucTc].next, struct _USB_REQ_T, list); |
| prBufCtrl = prUsbReq->prBufCtrl; |
| |
| if (prBufCtrl->u4WrIdx != 0) |
| halTxUSBSendAggData(prHifInfo, ucTc, prUsbReq); /* TODO */ |
| } |
| #else |
| list_add_tail(&prUsbReq->list, &prHifInfo->rTxDataFreeQ); |
| #endif |
| spin_unlock_irqrestore(&prHifInfo->rTxDataFreeQLock, flags); |
| |
| if (kalGetTxPendingCmdCount(prAdapter->prGlueInfo) > 0 || wlanGetTxPendingFrameCount(prAdapter) > 0) |
| kalSetEvent(prAdapter->prGlueInfo); |
| kalSetTxEvent2Hif(prAdapter->prGlueInfo); |
| } |
| |
| UINT_32 halRxUSBEnqueueRFB(IN P_ADAPTER_T prAdapter, IN PUINT_8 pucBuf, IN UINT_32 u4Length, |
| IN UINT_32 u4MinRfbCnt) |
| { |
| P_GLUE_INFO_T prGlueInfo = prAdapter->prGlueInfo; |
| P_RX_CTRL_T prRxCtrl = &prAdapter->rRxCtrl; |
| P_SW_RFB_T prSwRfb = (P_SW_RFB_T) NULL; |
| P_HW_MAC_RX_DESC_T prRxStatus; |
| UINT_32 u4RemainCount; |
| UINT_16 u2RxByteCount; |
| UINT_8 *pucRxFrame; |
| UINT_32 u4EnqCnt = 0; |
| |
| KAL_SPIN_LOCK_DECLARATION(); |
| |
| pucRxFrame = pucBuf; |
| u4RemainCount = u4Length; |
| while (u4RemainCount > 4) { |
| u2RxByteCount = HAL_RX_STATUS_GET_RX_BYTE_CNT((P_HW_MAC_RX_DESC_T) pucRxFrame); |
| u2RxByteCount = ALIGN_4(u2RxByteCount) + LEN_USB_RX_PADDING_CSO; |
| |
| if (u2RxByteCount <= CFG_RX_MAX_PKT_SIZE) { |
| prSwRfb = NULL; |
| KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_RX_FREE_QUE); |
| if (prRxCtrl->rFreeSwRfbList.u4NumElem > u4MinRfbCnt) |
| QUEUE_REMOVE_HEAD(&prRxCtrl->rFreeSwRfbList, prSwRfb, P_SW_RFB_T); |
| KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_RX_FREE_QUE); |
| |
| if (!prSwRfb) { |
| return (u4Length - u4RemainCount); |
| } |
| |
| kalMemCopy(prSwRfb->pucRecvBuff, pucRxFrame, u2RxByteCount); |
| |
| prRxStatus = prSwRfb->prRxStatus; |
| ASSERT(prRxStatus); |
| |
| prSwRfb->ucPacketType = (UINT_8) HAL_RX_STATUS_GET_PKT_TYPE(prRxStatus); |
| /* DBGLOG(RX, TRACE, ("ucPacketType = %d\n", prSwRfb->ucPacketType)); */ |
| #if DBG |
| DBGLOG(RX, TRACE, "Rx status flag = %x wlan index = %d SecMode = %d\n", |
| prRxStatus->u2StatusFlag, prRxStatus->ucWlanIdx, HAL_RX_STATUS_GET_SEC_MODE(prRxStatus)); |
| #endif |
| KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_RX_QUE); |
| QUEUE_INSERT_TAIL(&prRxCtrl->rReceivedRfbList, &prSwRfb->rQueEntry); |
| KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_RX_QUE); |
| u4EnqCnt++; |
| |
| RX_INC_CNT(prRxCtrl, RX_MPDU_TOTAL_COUNT); |
| } else { |
| DBGLOG(RX, WARN, "Rx byte count:%u exceeds SW_RFB max length:%u\n!", |
| u2RxByteCount, CFG_RX_MAX_PKT_SIZE); |
| DBGLOG_MEM32(RX, WARN, pucRxFrame, sizeof(HW_MAC_RX_DESC_T)); |
| break; |
| } |
| |
| u4RemainCount -= u2RxByteCount; |
| pucRxFrame += u2RxByteCount; |
| } |
| |
| if (u4EnqCnt) { |
| set_bit(GLUE_FLAG_RX_BIT, &(prGlueInfo->ulFlag)); |
| wake_up_interruptible(&(prGlueInfo->waitq)); |
| } |
| |
| return u4Length; |
| } |
| |
| WLAN_STATUS halRxUSBReceiveEvent(IN P_ADAPTER_T prAdapter, IN BOOLEAN fgFillUrb) |
| { |
| P_GLUE_INFO_T prGlueInfo = prAdapter->prGlueInfo; |
| P_GL_HIF_INFO_T prHifInfo = &prGlueInfo->rHifInfo; |
| P_USB_REQ_T prUsbReq; |
| WLAN_STATUS u4Status = WLAN_STATUS_SUCCESS; |
| |
| if (/*prGlueInfo->ulFlag & GLUE_FLAG_HALT || */prHifInfo->state != USB_STATE_LINK_UP) |
| return WLAN_STATUS_FAILURE; |
| |
| while (1) { |
| prUsbReq = glUsbDequeueReq(prHifInfo, &prHifInfo->rRxEventFreeQ, &prHifInfo->rRxEventQLock); |
| if (prUsbReq == NULL) |
| return WLAN_STATUS_RESOURCES; |
| |
| usb_anchor_urb(prUsbReq->prUrb, &prHifInfo->rRxEventAnchor); |
| |
| prUsbReq->prPriv = NULL; |
| prUsbReq->prBufCtrl->u4ReadSize = 0; |
| if (prHifInfo->eEventEpType == EVENT_EP_TYPE_INTR && fgFillUrb) { |
| usb_fill_int_urb(prUsbReq->prUrb, |
| prHifInfo->udev, |
| usb_rcvintpipe(prHifInfo->udev, USB_EVENT_EP_IN), |
| (void *)prUsbReq->prBufCtrl->pucBuf, prUsbReq->prBufCtrl->u4BufSize, |
| halRxUSBReceiveEventComplete, (void *)prUsbReq, 1); |
| } else if (prHifInfo->eEventEpType == EVENT_EP_TYPE_BULK) { |
| usb_fill_bulk_urb(prUsbReq->prUrb, |
| prHifInfo->udev, |
| usb_rcvbulkpipe(prHifInfo->udev, USB_EVENT_EP_IN), |
| (void *)prUsbReq->prBufCtrl->pucBuf, prUsbReq->prBufCtrl->u4BufSize, |
| halRxUSBReceiveEventComplete, (void *)prUsbReq); |
| } |
| u4Status = usb_submit_urb(prUsbReq->prUrb, GFP_ATOMIC); |
| |
| if (u4Status) { |
| DBGLOG(HAL, ERROR, "usb_submit_urb() reports error (%d) [%s]\n", u4Status, __func__); |
| usb_unanchor_urb(prUsbReq->prUrb); |
| glUsbEnqueueReq(prHifInfo, &prHifInfo->rRxEventFreeQ, prUsbReq, |
| &prHifInfo->rRxEventQLock, FALSE); |
| break; |
| } |
| } |
| |
| return u4Status; |
| } |
| |
| VOID halRxUSBReceiveEventComplete(struct urb *urb) |
| { |
| P_USB_REQ_T prUsbReq = urb->context; |
| P_GL_HIF_INFO_T prHifInfo = prUsbReq->prHifInfo; |
| P_GLUE_INFO_T prGlueInfo = prHifInfo->prGlueInfo; |
| |
| if (/*prGlueInfo->ulFlag & GLUE_FLAG_HALT || */prHifInfo->state != USB_STATE_LINK_UP) { |
| glUsbEnqueueReq(prHifInfo, &prHifInfo->rRxEventFreeQ, prUsbReq, &prHifInfo->rRxEventQLock, FALSE); |
| return; |
| } |
| |
| /* Hif power off wifi, drop rx packets and continue polling RX packets until RX path empty */ |
| if (prGlueInfo->ulFlag & GLUE_FLAG_HALT) { |
| glUsbEnqueueReq(prHifInfo, &prHifInfo->rRxEventFreeQ, prUsbReq, &prHifInfo->rRxEventQLock, FALSE); |
| halRxUSBReceiveEvent(prGlueInfo->prAdapter, FALSE); |
| return; |
| } |
| |
| if (urb->status == -ESHUTDOWN || urb->status == -ENOENT) { |
| glUsbEnqueueReq(prHifInfo, &prHifInfo->rRxEventFreeQ, prUsbReq, &prHifInfo->rRxEventQLock, FALSE); |
| DBGLOG(RX, ERROR, "USB device shutdown skip Rx [%s]\n", __func__); |
| return; |
| } |
| |
| #if CFG_USB_RX_HANDLE_IN_HIF_THREAD |
| DBGLOG(RX, TRACE, "[%s] Rx URB[0x%p] Len[%u] Sts[%u]\n", __func__, urb, urb->actual_length, urb->status); |
| |
| glUsbEnqueueReq(prHifInfo, &prHifInfo->rRxEventCompleteQ, prUsbReq, &prHifInfo->rRxEventQLock, FALSE); |
| |
| kalSetIntEvent(prGlueInfo); |
| #else |
| if (urb->status == 0) { |
| glUsbEnqueueReq(prHifInfo, &prHifInfo->rRxEventCompleteQ, prUsbReq, &prHifInfo->rRxEventQLock, FALSE); |
| |
| /*tasklet_hi_schedule(&prGlueInfo->rRxTask);*/ |
| tasklet_schedule(&prGlueInfo->rRxTask); |
| } else { |
| DBGLOG(RX, ERROR, "[%s] receive EVENT fail (status = %d)\n", __func__, urb->status); |
| glUsbEnqueueReq(prHifInfo, &prHifInfo->rRxEventFreeQ, prUsbReq, &prHifInfo->rRxEventQLock, FALSE); |
| |
| halRxUSBReceiveEvent(prGlueInfo->prAdapter, FALSE); |
| } |
| #endif |
| } |
| |
| WLAN_STATUS halRxUSBReceiveData(IN P_ADAPTER_T prAdapter) |
| { |
| P_GLUE_INFO_T prGlueInfo = prAdapter->prGlueInfo; |
| P_GL_HIF_INFO_T prHifInfo = &prGlueInfo->rHifInfo; |
| P_USB_REQ_T prUsbReq; |
| WLAN_STATUS u4Status = WLAN_STATUS_SUCCESS; |
| |
| if (/*prGlueInfo->ulFlag & GLUE_FLAG_HALT || */prHifInfo->state != USB_STATE_LINK_UP) |
| return WLAN_STATUS_FAILURE; |
| |
| while (1) { |
| prUsbReq = glUsbDequeueReq(prHifInfo, &prHifInfo->rRxDataFreeQ, &prHifInfo->rRxDataQLock); |
| if (prUsbReq == NULL) |
| return WLAN_STATUS_RESOURCES; |
| |
| usb_anchor_urb(prUsbReq->prUrb, &prHifInfo->rRxDataAnchor); |
| |
| prUsbReq->prPriv = NULL; |
| prUsbReq->prBufCtrl->u4ReadSize = 0; |
| usb_fill_bulk_urb(prUsbReq->prUrb, |
| prHifInfo->udev, |
| usb_rcvbulkpipe(prHifInfo->udev, USB_DATA_EP_IN), |
| (void *)prUsbReq->prBufCtrl->pucBuf, |
| prUsbReq->prBufCtrl->u4BufSize, halRxUSBReceiveDataComplete, (void *)prUsbReq); |
| u4Status = usb_submit_urb(prUsbReq->prUrb, GFP_ATOMIC); |
| if (u4Status) { |
| DBGLOG(HAL, ERROR, "usb_submit_urb() reports error (%d) [%s]\n", u4Status, __func__); |
| usb_unanchor_urb(prUsbReq->prUrb); |
| glUsbEnqueueReq(prHifInfo, &prHifInfo->rRxDataFreeQ, prUsbReq, &prHifInfo->rRxDataQLock, FALSE); |
| break; |
| } |
| } |
| |
| return u4Status; |
| } |
| |
| VOID halRxUSBReceiveDataComplete(struct urb *urb) |
| { |
| P_USB_REQ_T prUsbReq = urb->context; |
| P_GL_HIF_INFO_T prHifInfo = prUsbReq->prHifInfo; |
| P_GLUE_INFO_T prGlueInfo = prHifInfo->prGlueInfo; |
| |
| if (/*prGlueInfo->ulFlag & GLUE_FLAG_HALT || */prHifInfo->state != USB_STATE_LINK_UP) { |
| glUsbEnqueueReq(prHifInfo, &prHifInfo->rRxDataFreeQ, prUsbReq, &prHifInfo->rRxDataQLock, FALSE); |
| return; |
| } |
| |
| /* Hif power off wifi, drop rx packets and continue polling RX packets until RX path empty */ |
| if (prGlueInfo->ulFlag & GLUE_FLAG_HALT) { |
| glUsbEnqueueReq(prHifInfo, &prHifInfo->rRxDataFreeQ, prUsbReq, &prHifInfo->rRxDataQLock, FALSE); |
| halRxUSBReceiveData(prGlueInfo->prAdapter); |
| return; |
| } |
| |
| if (urb->status == -ESHUTDOWN || urb->status == -ENOENT) { |
| glUsbEnqueueReq(prHifInfo, &prHifInfo->rRxDataFreeQ, prUsbReq, &prHifInfo->rRxDataQLock, FALSE); |
| DBGLOG(RX, ERROR, "USB device shutdown skip Rx [%s]\n", __func__); |
| return; |
| } |
| |
| #if CFG_USB_RX_HANDLE_IN_HIF_THREAD |
| glUsbEnqueueReq(prHifInfo, &prHifInfo->rRxDataCompleteQ, prUsbReq, FALSE); |
| |
| kalSetIntEvent(prGlueInfo); |
| #else |
| if (urb->status == 0) { |
| glUsbEnqueueReq(prHifInfo, &prHifInfo->rRxDataCompleteQ, prUsbReq, &prHifInfo->rRxDataQLock, FALSE); |
| |
| /*tasklet_hi_schedule(&prGlueInfo->rRxTask);*/ |
| tasklet_schedule(&prGlueInfo->rRxTask); |
| } else { |
| DBGLOG(RX, ERROR, "[%s] receive DATA fail (status = %d)\n", __func__, urb->status); |
| glUsbEnqueueReq(prHifInfo, &prHifInfo->rRxDataFreeQ, prUsbReq, &prHifInfo->rRxDataQLock, FALSE); |
| |
| halRxUSBReceiveData(prGlueInfo->prAdapter); |
| } |
| #endif |
| } |
| |
| VOID halRxUSBProcessEventDataComplete(IN P_ADAPTER_T prAdapter, |
| struct list_head *prCompleteQ, struct list_head *prFreeQ, UINT_32 u4MinRfbCnt) |
| { |
| P_USB_REQ_T prUsbReq; |
| struct urb *prUrb; |
| P_BUF_CTRL_T prBufCtrl; |
| P_GLUE_INFO_T prGlueInfo = prAdapter->prGlueInfo; |
| P_GL_HIF_INFO_T prHifInfo = &prGlueInfo->rHifInfo; |
| PUINT_8 pucBufAddr; |
| UINT_32 u4BufLen; |
| static BOOL s_fgOutOfSwRfb = FALSE; |
| static UINT_32 s_u4OutOfSwRfbPrintLimit; |
| |
| /* Process complete event/data */ |
| prUsbReq = glUsbDequeueReq(prHifInfo, prCompleteQ, &prHifInfo->rRxEventQLock); |
| while (prUsbReq) { |
| prUrb = prUsbReq->prUrb; |
| prBufCtrl = prUsbReq->prBufCtrl; |
| |
| DBGLOG(RX, LOUD, "[%s] Rx URB[0x%p] Len[%u] Sts[%u]\n", __func__, |
| prUrb, prUrb->actual_length, prUrb->status); |
| |
| if (prUrb->status != 0) { |
| DBGLOG(RX, ERROR, "[%s] receive EVENT/DATA fail (status = %d)\n", __func__, prUrb->status); |
| |
| glUsbEnqueueReq(prHifInfo, prFreeQ, prUsbReq, &prHifInfo->rRxEventQLock, FALSE); |
| prUsbReq = glUsbDequeueReq(prHifInfo, prCompleteQ, &prHifInfo->rRxEventQLock); |
| continue; |
| } |
| |
| pucBufAddr = prBufCtrl->pucBuf + prBufCtrl->u4ReadSize; |
| u4BufLen = prUrb->actual_length - prBufCtrl->u4ReadSize; |
| |
| prBufCtrl->u4ReadSize += halRxUSBEnqueueRFB(prAdapter, pucBufAddr, u4BufLen, u4MinRfbCnt); |
| |
| if (unlikely(prUrb->actual_length - prBufCtrl->u4ReadSize > 4)) { |
| if (s_fgOutOfSwRfb == FALSE) { |
| if ((long)jiffies - (long)s_u4OutOfSwRfbPrintLimit > 0) { |
| DBGLOG(RX, WARN, "Out of SwRfb!\n"); |
| s_u4OutOfSwRfbPrintLimit = jiffies + MSEC_TO_JIFFIES(SW_RFB_LOG_LIMIT_MS); |
| } |
| s_fgOutOfSwRfb = TRUE; |
| } |
| glUsbEnqueueReq(prHifInfo, prCompleteQ, prUsbReq, &prHifInfo->rRxEventQLock, TRUE); |
| |
| set_bit(GLUE_FLAG_RX_BIT, &prGlueInfo->ulFlag); |
| wake_up_interruptible(&prGlueInfo->waitq); |
| |
| schedule_delayed_work(&prGlueInfo->rRxPktDeAggWork, MSEC_TO_JIFFIES(SW_RFB_RECHECK_MS)); |
| break; |
| } |
| |
| if (unlikely(s_fgOutOfSwRfb == TRUE)) |
| s_fgOutOfSwRfb = FALSE; |
| |
| glUsbEnqueueReq(prHifInfo, prFreeQ, prUsbReq, &prHifInfo->rRxEventQLock, FALSE); |
| prUsbReq = glUsbDequeueReq(prHifInfo, prCompleteQ, &prHifInfo->rRxEventQLock); |
| } |
| } |
| |
| /*----------------------------------------------------------------------------*/ |
| /*! |
| * @brief enable global interrupt |
| * |
| * @param prAdapter pointer to the Adapter handler |
| * |
| * @return (none) |
| */ |
| /*----------------------------------------------------------------------------*/ |
| VOID halEnableInterrupt(IN P_ADAPTER_T prAdapter) |
| { |
| P_GLUE_INFO_T prGlueInfo; |
| P_GL_HIF_INFO_T prHifInfo; |
| |
| ASSERT(prAdapter); |
| |
| prGlueInfo = prAdapter->prGlueInfo; |
| prHifInfo = &prGlueInfo->rHifInfo; |
| |
| halRxUSBReceiveData(prAdapter); |
| if (prHifInfo->eEventEpType != EVENT_EP_TYPE_DATA_EP) |
| halRxUSBReceiveEvent(prAdapter, TRUE); |
| |
| glUdmaRxAggEnable(prGlueInfo, TRUE); |
| } /* end of halEnableInterrupt() */ |
| |
| /*----------------------------------------------------------------------------*/ |
| /*! |
| * @brief disable global interrupt |
| * |
| * @param prAdapter pointer to the Adapter handler |
| * |
| * @return (none) |
| */ |
| /*----------------------------------------------------------------------------*/ |
| VOID halDisableInterrupt(IN P_ADAPTER_T prAdapter) |
| { |
| P_GLUE_INFO_T prGlueInfo; |
| P_GL_HIF_INFO_T prHifInfo; |
| |
| ASSERT(prAdapter); |
| prGlueInfo = prAdapter->prGlueInfo; |
| prHifInfo = &prGlueInfo->rHifInfo; |
| |
| usb_kill_anchored_urbs(&prHifInfo->rRxDataAnchor); |
| usb_kill_anchored_urbs(&prHifInfo->rRxEventAnchor); |
| |
| glUdmaRxAggEnable(prGlueInfo, FALSE); |
| prAdapter->fgIsIntEnable = FALSE; |
| } |
| |
| /*----------------------------------------------------------------------------*/ |
| /*! |
| * \brief This routine is used to process the POWER OFF procedure. |
| * |
| * \param[in] pvAdapter Pointer to the Adapter structure. |
| * |
| * \return (none) |
| */ |
| /*----------------------------------------------------------------------------*/ |
| BOOLEAN halSetDriverOwn(IN P_ADAPTER_T prAdapter) |
| { |
| return TRUE; |
| } |
| |
| /*----------------------------------------------------------------------------*/ |
| /*! |
| * \brief This routine is used to process the POWER ON procedure. |
| * |
| * \param[in] pvAdapter Pointer to the Adapter structure. |
| * |
| * \return (none) |
| */ |
| /*----------------------------------------------------------------------------*/ |
| VOID halSetFWOwn(IN P_ADAPTER_T prAdapter, IN BOOLEAN fgEnableGlobalInt) |
| { |
| } |
| |
| VOID halWakeUpWiFi(IN P_ADAPTER_T prAdapter) |
| { |
| BOOLEAN fgResult; |
| UINT_8 ucCount = 0; |
| |
| #if CFG_SUPPORT_PMIC_SPI_CLOCK_SWITCH |
| UINT_32 u4Value = 0; |
| /*E1 PMIC clock workaround*/ |
| HAL_MCR_RD(prAdapter, TOP_CKGEN2_CR_PMIC_CK_MANUAL, &u4Value); |
| |
| if ((TOP_CKGEN2_CR_PMIC_CK_MANUAL_MASK & u4Value) == 0) |
| HAL_MCR_WR(prAdapter, TOP_CKGEN2_CR_PMIC_CK_MANUAL, (TOP_CKGEN2_CR_PMIC_CK_MANUAL_MASK|u4Value)); |
| HAL_MCR_RD(prAdapter, TOP_CKGEN2_CR_PMIC_CK_MANUAL, &u4Value); |
| DBGLOG(INIT, INFO, "PMIC SPI clock switch = %s\n", |
| (TOP_CKGEN2_CR_PMIC_CK_MANUAL_MASK&u4Value)?"SUCCESS":"FAIL"); |
| #endif |
| |
| DBGLOG(INIT, INFO, "Power on Wi-Fi....\n"); |
| |
| HAL_WIFI_FUNC_READY_CHECK(prAdapter, WIFI_FUNC_INIT_DONE, &fgResult); |
| |
| while (!fgResult) { |
| HAL_WIFI_FUNC_POWER_ON(prAdapter); |
| kalMdelay(50); |
| HAL_WIFI_FUNC_READY_CHECK(prAdapter, WIFI_FUNC_INIT_DONE, &fgResult); |
| |
| ucCount++; |
| |
| if (ucCount >= 5) { |
| DBGLOG(INIT, WARN, "Power on failed!!!\n"); |
| break; |
| } |
| } |
| |
| prAdapter->fgIsFwOwn = FALSE; |
| } |
| |
| VOID halEnableFWDownload(IN P_ADAPTER_T prAdapter, IN BOOL fgEnable) |
| { |
| #if (CFG_UMAC_GENERATION >= 0x20) |
| |
| UINT_32 u4Value = 0; |
| |
| ASSERT(prAdapter); |
| |
| { |
| HAL_MCR_RD(prAdapter, UDMA_TX_QSEL, &u4Value); |
| |
| if (fgEnable) |
| u4Value |= FW_DL_EN; |
| else |
| u4Value &= ~FW_DL_EN; |
| |
| HAL_MCR_WR(prAdapter, UDMA_TX_QSEL, u4Value); |
| } |
| #endif |
| } |
| |
| VOID halDevInit(IN P_ADAPTER_T prAdapter) |
| { |
| P_GLUE_INFO_T prGlueInfo; |
| |
| ASSERT(prAdapter); |
| prGlueInfo = prAdapter->prGlueInfo; |
| |
| glUdmaRxAggEnable(prGlueInfo, FALSE); |
| glUdmaTxRxEnable(prGlueInfo, TRUE); |
| } |
| |
| BOOLEAN halTxIsDataBufEnough(IN P_ADAPTER_T prAdapter, IN P_MSDU_INFO_T prMsduInfo) |
| { |
| P_GLUE_INFO_T prGlueInfo = prAdapter->prGlueInfo; |
| P_GL_HIF_INFO_T prHifInfo = &prGlueInfo->rHifInfo; |
| #if CFG_USB_TX_AGG |
| P_USB_REQ_T prUsbReq; |
| P_BUF_CTRL_T prBufCtrl; |
| #endif |
| UINT_8 ucTc; |
| struct sk_buff *skb; |
| UINT_32 u4Length; |
| |
| unsigned long flags; |
| |
| skb = (struct sk_buff *)prMsduInfo->prPacket; |
| u4Length = skb->len; |
| ucTc = USB_TRANS_MSDU_TC(prMsduInfo); |
| |
| spin_lock_irqsave(&prHifInfo->rTxDataFreeQLock, flags); |
| |
| #if CFG_USB_TX_AGG |
| if (list_empty(&prHifInfo->rTxDataFreeQ[ucTc])) { |
| spin_unlock_irqrestore(&prHifInfo->rTxDataFreeQLock, flags); |
| |
| return FALSE; |
| } |
| |
| prUsbReq = list_entry(prHifInfo->rTxDataFreeQ[ucTc].next, struct _USB_REQ_T, list); |
| prBufCtrl = prUsbReq->prBufCtrl; |
| |
| if (prHifInfo->rTxDataFreeQ[ucTc].next->next == &prHifInfo->rTxDataFreeQ[ucTc]) { |
| /* length of rTxDataFreeQ equals 1 */ |
| if (prBufCtrl->u4WrIdx + ALIGN_4(u4Length) > |
| prBufCtrl->u4BufSize - prHifInfo->u4AggRsvSize - LEN_USB_UDMA_TX_TERMINATOR) { |
| /* Buffer is not enough */ |
| spin_unlock_irqrestore(&prHifInfo->rTxDataFreeQLock, flags); |
| return FALSE; |
| } |
| } |
| prHifInfo->u4AggRsvSize += ALIGN_4(u4Length); |
| #else |
| if (list_empty(&prHifInfo->rTxDataFreeQ)) { |
| spin_unlock_irqrestore(&prHifInfo->rTxDataFreeQLock, flags); |
| |
| return FALSE; |
| } |
| #endif |
| |
| spin_unlock_irqrestore(&prHifInfo->rTxDataFreeQLock, flags); |
| return TRUE; |
| } |
| |
| VOID halProcessTxInterrupt(IN P_ADAPTER_T prAdapter) |
| { |
| #if CFG_USB_TX_HANDLE_IN_HIF_THREAD |
| P_USB_REQ_T prUsbReq; |
| P_GL_HIF_INFO_T prHifInfo = &prAdapter->prGlueInfo->rHifInfo; |
| |
| /* Process complete Tx cmd */ |
| prUsbReq = glUsbDequeueReq(prHifInfo, &prHifInfo->rTxCmdCompleteQ, &prHifInfo->rTxCmdQLock); |
| while (prUsbReq) { |
| halTxUSBProcessCmdComplete(prAdapter, prUsbReq); |
| prUsbReq = glUsbDequeueReq(prHifInfo, &prHifInfo->rTxCmdCompleteQ, &prHifInfo->rTxCmdQLock); |
| } |
| |
| /* Process complete Tx data */ |
| prUsbReq = glUsbDequeueReq(prHifInfo, &prHifInfo->rTxDataCompleteQ, &prHifInfo->rTxCmdQLock); |
| while (prUsbReq) { |
| halTxUSBProcessDataComplete(prAdapter, prUsbReq); |
| prUsbReq = glUsbDequeueReq(prHifInfo, &prHifInfo->rTxDataCompleteQ, &prHifInfo->rTxCmdQLock); |
| } |
| #endif |
| } |
| |
| VOID halHifSwInfoInit(IN P_ADAPTER_T prAdapter) |
| { |
| |
| } |
| |
| VOID halRxProcessMsduReport(IN P_ADAPTER_T prAdapter, IN OUT P_SW_RFB_T prSwRfb) |
| { |
| |
| } |
| |
| UINT_32 halTxGetPageCount(IN UINT_32 u4FrameLength, IN BOOLEAN fgIncludeDesc) |
| { |
| #if CFG_USB_TX_AGG |
| UINT_32 u4RequiredBufferSize; |
| UINT_32 u4PageCount; |
| |
| /* Frame Buffer |
| * |<--Tx Descriptor-->|<--Tx descriptor padding-->| |
| * <--802.3/802.11 Header-->|<--Header padding-->|<--Payload-->| |
| */ |
| |
| if (fgIncludeDesc) |
| u4RequiredBufferSize = u4FrameLength; |
| else |
| u4RequiredBufferSize = NIC_TX_HEAD_ROOM + u4FrameLength; |
| |
| u4RequiredBufferSize = ALIGN_4(u4RequiredBufferSize); |
| |
| if (NIC_TX_PAGE_SIZE_IS_POWER_OF_2) |
| u4PageCount = (u4RequiredBufferSize + (NIC_TX_PAGE_SIZE - 1)) >> NIC_TX_PAGE_SIZE_IN_POWER_OF_2; |
| else |
| u4PageCount = (u4RequiredBufferSize + (NIC_TX_PAGE_SIZE - 1)) / NIC_TX_PAGE_SIZE; |
| |
| return u4PageCount; |
| #else |
| return 1; |
| #endif |
| } |
| |
| WLAN_STATUS halTxPollingResource(IN P_ADAPTER_T prAdapter, IN UINT_8 ucTC) |
| { |
| return WLAN_STATUS_SUCCESS; |
| } |
| |
| VOID halSerHifReset(IN P_ADAPTER_T prAdapter) |
| { |
| } |
| |
| VOID halProcessRxInterrupt(IN P_ADAPTER_T prAdapter) |
| { |
| P_GL_HIF_INFO_T prHifInfo = &prAdapter->prGlueInfo->rHifInfo; |
| |
| /* Process complete data */ |
| halRxUSBProcessEventDataComplete(prAdapter, &prHifInfo->rRxDataCompleteQ, |
| &prHifInfo->rRxDataFreeQ, USB_RX_DATA_RFB_RSV_CNT); |
| halRxUSBReceiveData(prAdapter); |
| |
| if (prHifInfo->eEventEpType != EVENT_EP_TYPE_DATA_EP) { |
| /* Process complete event */ |
| halRxUSBProcessEventDataComplete(prAdapter, &prHifInfo->rRxEventCompleteQ, |
| &prHifInfo->rRxEventFreeQ, USB_RX_EVENT_RFB_RSV_CNT); |
| halRxUSBReceiveEvent(prAdapter, FALSE); |
| } |
| } |
| |
| UINT_32 halDumpHifStatus(IN P_ADAPTER_T prAdapter, IN PUINT_8 pucBuf, IN UINT_32 u4Max) |
| { |
| UINT_32 u4CpuIdx, u4DmaIdx, u4Int, u4GloCfg, u4Reg; |
| UINT_32 u4Len = 0; |
| P_GLUE_INFO_T prGlueInfo = prAdapter->prGlueInfo; |
| UCHAR pBuffer[512] = {0}; |
| |
| HAL_MCR_RD(prAdapter, 0x820b0118, &u4CpuIdx); |
| HAL_MCR_RD(prAdapter, 0x820b011c, &u4DmaIdx); |
| HAL_MCR_RD(prAdapter, 0x820b0220, &u4Int); |
| HAL_MCR_RD(prAdapter, 0x820b0204, &u4GloCfg); |
| |
| LOGBUF(pucBuf, u4Max, u4Len, "\n"); |
| LOGBUF(pucBuf, u4Max, u4Len, "PDMA1R1 CPU[%u] DMA[%u] INT[0x%08x] CFG[0x%08x]\n", u4CpuIdx, |
| u4DmaIdx, u4Int, u4GloCfg); |
| |
| HAL_MCR_RD(prAdapter, UDMA_WLCFG_0, &u4Reg); |
| |
| LOGBUF(pucBuf, u4Max, u4Len, "UDMA WLCFG[0x%08x]\n", u4Reg); |
| |
| LOGBUF(pucBuf, u4Max, u4Len, "\n"); |
| LOGBUF(pucBuf, u4Max, u4Len, "VenderID: %04x\n", |
| glGetUsbDeviceVendorId(prGlueInfo->rHifInfo.udev)); |
| LOGBUF(pucBuf, u4Max, u4Len, "ProductID: %04x\n", |
| glGetUsbDeviceProductId(prGlueInfo->rHifInfo.udev)); |
| |
| glGetUsbDeviceManufacturerName(prGlueInfo->rHifInfo.udev, pBuffer, |
| sizeof(pBuffer)); |
| LOGBUF(pucBuf, u4Max, u4Len, "Manufacturer: %s\n", |
| pBuffer); |
| |
| glGetUsbDeviceProductName(prGlueInfo->rHifInfo.udev, pBuffer, |
| sizeof(pBuffer)); |
| LOGBUF(pucBuf, u4Max, u4Len, "Product: %s\n", pBuffer); |
| |
| glGetUsbDeviceSerialNumber(prGlueInfo->rHifInfo.udev, pBuffer, |
| sizeof(pBuffer)); |
| LOGBUF(pucBuf, u4Max, u4Len, "SerialNumber: %s\n", |
| pBuffer); |
| |
| return u4Len; |
| } |
| |
| VOID halGetCompleteStatus(IN P_ADAPTER_T prAdapter, OUT PUINT_32 pu4IntStatus) |
| { |
| #if CFG_USB_RX_HANDLE_IN_HIF_THREAD || CFG_USB_TX_HANDLE_IN_HIF_THREAD |
| P_GL_HIF_INFO_T prHifInfo = &prAdapter->prGlueInfo->rHifInfo; |
| #endif |
| |
| *pu4IntStatus = 0; |
| |
| #if CFG_USB_RX_HANDLE_IN_HIF_THREAD |
| if (!list_empty(&prHifInfo->rRxDataCompleteQ) || !list_empty(&prHifInfo->rRxEventCompleteQ)) |
| *pu4IntStatus |= WHISR_RX0_DONE_INT; |
| #endif |
| |
| #if CFG_USB_TX_HANDLE_IN_HIF_THREAD |
| if (!list_empty(&prHifInfo->rTxDataCompleteQ) || !list_empty(&prHifInfo->rTxCmdCompleteQ)) |
| *pu4IntStatus |= WHISR_TX_DONE_INT; |
| #endif |
| } |
| |
| BOOLEAN halIsPendingRx(IN P_ADAPTER_T prAdapter) |
| { |
| #if CFG_USB_RX_HANDLE_IN_HIF_THREAD |
| P_GL_HIF_INFO_T prHifInfo = &prAdapter->prGlueInfo->rHifInfo; |
| |
| if (!list_empty(&prHifInfo->rRxDataCompleteQ) || !list_empty(&prHifInfo->rRxEventCompleteQ)) |
| return TRUE; |
| else |
| return FALSE; |
| #else |
| return FALSE; |
| #endif |
| } |
| |
| VOID halUSBPreSuspendCmd(IN P_ADAPTER_T prAdapter) |
| { |
| CMD_HIF_CTRL_T rCmdHifCtrl; |
| WLAN_STATUS rStatus; |
| |
| rCmdHifCtrl.ucHifType = ENUM_HIF_TYPE_USB; |
| rCmdHifCtrl.ucHifDirection = ENUM_HIF_TX; |
| rCmdHifCtrl.ucHifStop = 1; |
| #if 0 |
| rStatus = wlanSendSetQueryCmd(prAdapter, /* prAdapter */ |
| CMD_ID_HIF_CTRL, /* ucCID */ |
| FALSE, /* fgSetQuery */ |
| TRUE, /* fgNeedResp */ |
| FALSE, /* fgIsOid */ |
| usbPreSuspendDone, /* pfCmdDoneHandler */ |
| usbPreSuspendTimeout, /* pfCmdTimeoutHandler */ |
| sizeof(CMD_HIF_CTRL_T), /* u4SetQueryInfoLen */ |
| (PUINT_8)&rCmdHifCtrl, /* pucInfoBuffer */ |
| NULL, /* pvSetQueryBuffer */ |
| 0 /* u4SetQueryBufferLen */ |
| ); |
| #else |
| rStatus = wlanSendSetQueryCmd(prAdapter, /* prAdapter */ |
| CMD_ID_HIF_CTRL, /* ucCID */ |
| TRUE, /* fgSetQuery */ |
| FALSE, /* fgNeedResp */ |
| FALSE, /* fgIsOid */ |
| NULL, /* pfCmdDoneHandler */ |
| NULL, /* pfCmdTimeoutHandler */ |
| sizeof(CMD_HIF_CTRL_T), /* u4SetQueryInfoLen */ |
| (PUINT_8)&rCmdHifCtrl, /* pucInfoBuffer */ |
| NULL, /* pvSetQueryBuffer */ |
| 0 /* u4SetQueryBufferLen */ |
| ); |
| #endif |
| |
| ASSERT(rStatus == WLAN_STATUS_PENDING); |
| } |
| |
| VOID halUSBPreSuspendDone(IN P_ADAPTER_T prAdapter, IN P_CMD_INFO_T prCmdInfo, IN PUINT_8 pucEventBuf) |
| { |
| ASSERT(prAdapter); |
| |
| prAdapter->prGlueInfo->rHifInfo.state = USB_STATE_PRE_SUSPEND_DONE; |
| } |
| |
| VOID halUSBPreSuspendTimeout(IN P_ADAPTER_T prAdapter, IN P_CMD_INFO_T prCmdInfo) |
| { |
| ASSERT(prAdapter); |
| |
| prAdapter->prGlueInfo->rHifInfo.state = USB_STATE_PRE_SUSPEND_FAIL; |
| } |
| |
| WLAN_STATUS halAllocateIOBuffer(IN P_ADAPTER_T prAdapter) |
| { |
| return WLAN_STATUS_SUCCESS; |
| } |
| |
| WLAN_STATUS halReleaseIOBuffer(IN P_ADAPTER_T prAdapter) |
| { |
| return WLAN_STATUS_SUCCESS; |
| } |
| |
| VOID halProcessSoftwareInterrupt(IN P_ADAPTER_T prAdapter) |
| { |
| |
| } |
| |
| VOID halDeAggRxPktWorker(struct work_struct *work) |
| { |
| P_GLUE_INFO_T prGlueInfo = ENTRY_OF(work, GLUE_INFO_T, rRxPktDeAggWork); |
| |
| /*tasklet_hi_schedule(&prGlueInfo->rRxTask);*/ |
| tasklet_schedule(&prGlueInfo->rRxTask); |
| } |
| |
| VOID halRxTasklet(unsigned long data) |
| { |
| P_GLUE_INFO_T prGlueInfo = (P_GLUE_INFO_T)data; |
| |
| halProcessRxInterrupt(prGlueInfo->prAdapter); |
| } |
| |
| VOID halTxCompleteTasklet(unsigned long data) |
| { |
| P_GLUE_INFO_T prGlueInfo = (P_GLUE_INFO_T)data; |
| P_GL_HIF_INFO_T prHifInfo = &prGlueInfo->rHifInfo; |
| P_USB_REQ_T prUsbReq; |
| |
| /* Process complete Tx data */ |
| prUsbReq = glUsbDequeueReq(prHifInfo, &prHifInfo->rTxDataCompleteQ, &prHifInfo->rTxDataQLock); |
| while (prUsbReq) { |
| halTxUSBProcessDataComplete(prGlueInfo->prAdapter, prUsbReq); |
| prUsbReq = glUsbDequeueReq(prHifInfo, &prHifInfo->rTxDataCompleteQ, &prHifInfo->rTxDataQLock); |
| } |
| } |
| |
| /* Hif power off wifi */ |
| WLAN_STATUS halHifPowerOffWifi(IN P_ADAPTER_T prAdapter) |
| { |
| WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; |
| |
| DBGLOG(INIT, INFO, "Power off Wi-Fi!\n"); |
| |
| /* Power off Wi-Fi */ |
| wlanSendNicPowerCtrlCmd(prAdapter, TRUE); |
| |
| rStatus = wlanCheckWifiFunc(prAdapter, FALSE); |
| |
| prAdapter->prGlueInfo->rHifInfo.state = USB_STATE_WIFI_OFF; |
| |
| nicDisableInterrupt(prAdapter); |
| |
| wlanClearPendingInterrupt(prAdapter); |
| |
| halTxCancelAllSending(prAdapter); |
| |
| return rStatus; |
| } |
| |
| VOID halPrintHifDbgInfo(IN P_ADAPTER_T prAdapter) |
| { |
| |
| } |
| |
| BOOLEAN halIsTxResourceControlEn(IN P_ADAPTER_T prAdapter) |
| { |
| return FALSE; |
| } |
| |