/** * \fn twIf_WriteElpReg * \brief write ELP register * * \note * \param pTwIf - The module's object * \param uValue - ELP_CTRL_REG_SLEEP or ELP_CTRL_REG_AWAKE * \return void * \sa */ static void twIf_WriteElpReg (TTwIfObj *pTwIf, TI_UINT32 uValue) { TRACE1(pTwIf->hReport, REPORT_SEVERITY_INFORMATION, "twIf_WriteElpReg: ELP Txn data = 0x%x\n", uValue); /* Send ELP (awake or sleep) transaction to TxnQ */ if (uValue == ELP_CTRL_REG_AWAKE) { txnQ_Transact (pTwIf->hTxnQ, &(pTwIf->tElpTxnAwake.tHdr)); } else { txnQ_Transact (pTwIf->hTxnQ, &(pTwIf->tElpTxnSleep.tHdr)); } }
/** * \fn twIf_WriteElpReg * \brief write ELP register * * \note * \param pTwIf - The module's object * \param uValue - ELP_CTRL_REG_SLEEP or ELP_CTRL_REG_AWAKE * \return void * \sa */ static void twIf_WriteElpReg (TTwIfObj *pTwIf, TI_UINT32 uValue) { /* Send ELP (awake or sleep) transaction to TxnQ */ if (uValue == ELP_CTRL_REG_AWAKE) { txnQ_Transact (pTwIf->hTxnQ, &(pTwIf->tElpTxnAwake.tHdr)); } else { txnQ_Transact (pTwIf->hTxnQ, &(pTwIf->tElpTxnSleep.tHdr)); } }
/** * \fn ifSlpMng_handleRxReady * \brief Interface Sleep Manager state machine for Rx ready event * * Processes receive ready event of Interface Sleep Manager state machine. * Any bytes received in sleep state are treated as awake indication and Rx buffer is cleared. * */ EMcpfRes ifSlpMng_handleRxReady(handle_t hIfSlpMng) { TifSlpMngObj * pIfSlpMng = (TifSlpMngObj *) hIfSlpMng; McpBool stateChanged = MCP_FALSE; MCPF_ENTER_CRIT_SEC (pIfSlpMng->hMcpf); if (pIfSlpMng->eState == IFSLPMNG_STATE_ASLEEP) { pIfSlpMng->eState = IFSLPMNG_STATE_AWAKE; stateChanged = MCP_TRUE; pIfSlpMng->stat.AwakeInd_Rx++; } MCPF_EXIT_CRIT_SEC (pIfSlpMng->hMcpf); if (stateChanged) { MCPF_REPORT_DEBUG_TX(pIfSlpMng->hMcpf,IFSLPMNG_MODULE_LOG, ("ifSlpMng_handleRxReady: Awaking, state=%d\n", pIfSlpMng->eState)); MCP_HAL_PM_TransportWakeup (pIfSlpMng->tChipId, pIfSlpMng->tTransId); busDrv_RxReset (pIfSlpMng->hBusDrv); /* Prepare and send SleepAck request */ TXN_PARAM_SET_IFSLPMNG_OP (pIfSlpMng->pMngTxn, TXN_PARAM_IFSLPMNG_OP_AWAKE_ACK); txnQ_Transact (pIfSlpMng->hTxnQ, pIfSlpMng->pMngTxn); txnQ_Run (pIfSlpMng->hTxnQ, pIfSlpMng->uFuncId); pIfSlpMng->stat.AwakeAck_Tx++; return RES_PENDING; /* indicate the state was sleeping */ } return RES_COMPLETE; }
/** * \fn ifSlpMng_HandleTxEvent * \brief Interface Sleep Manager state machine for Tx event * * Process Tx event of Interface Sleep Manager state machine * */ EMcpfRes ifSlpMng_HandleTxEvent (handle_t hIfSlpMng) { TifSlpMngObj * pIfSlpMng = (TifSlpMngObj *) hIfSlpMng; McpBool stateChanged = MCP_FALSE; MCPF_ENTER_CRIT_SEC (pIfSlpMng->hMcpf); if (pIfSlpMng->eState == IFSLPMNG_STATE_ASLEEP) { pIfSlpMng->eState = IFSLPMNG_STATE_WAIT_FOR_AWAKE_ACK; stateChanged = MCP_TRUE; pIfSlpMng->stat.AwakeInd_Tx++; } MCPF_EXIT_CRIT_SEC (pIfSlpMng->hMcpf); if (stateChanged) { MCP_HAL_PM_TransportWakeup (pIfSlpMng->tChipId, pIfSlpMng->tTransId); /* Prepare and send AwakeInd request */ TXN_PARAM_SET_IFSLPMNG_OP (pIfSlpMng->pMngTxn, TXN_PARAM_IFSLPMNG_OP_AWAKE); MCPF_REPORT_DEBUG_TX(pIfSlpMng->hMcpf, IFSLPMNG_MODULE_LOG, ("ifSlpMng_HandleTxEvent: Send Awake, pIfSlpMng=%p, state=%d\n", pIfSlpMng, pIfSlpMng->eState)); txnQ_Transact (pIfSlpMng->hTxnQ, pIfSlpMng->pMngTxn); } return RES_OK; }
/** * \fn ifSlpMng_HandleTxComplEvent * \brief Interface Sleep Manager state machine for Tx complete event * * Process transaction sending complete event of Interface Sleep Manager state machine * */ EMcpfRes ifSlpMng_HandleTxComplEvent (handle_t hIfSlpMng) { TifSlpMngObj * pIfSlpMng = (TifSlpMngObj *) hIfSlpMng; McpBool stateChanged = MCP_FALSE; McpBool awakeRequired = MCP_FALSE; MCPF_ENTER_CRIT_SEC (pIfSlpMng->hMcpf); if (pIfSlpMng->eState == IFSLPMNG_STATE_WAIT_FOR_SLEEPACK_TX_COMPL) { stateChanged = MCP_TRUE; pIfSlpMng->stat.SleepAckTxCompl++; if (txnQ_IsQueueEmpty (pIfSlpMng->hTxnQ, pIfSlpMng->uFuncId)) { pIfSlpMng->eState = IFSLPMNG_STATE_ASLEEP; } else { pIfSlpMng->eState = IFSLPMNG_STATE_WAIT_FOR_AWAKE_ACK; awakeRequired = MCP_TRUE; pIfSlpMng->stat.AwakeInd_Tx++; } } MCPF_EXIT_CRIT_SEC (pIfSlpMng->hMcpf); if (stateChanged) { if (!awakeRequired) { MCP_HAL_PM_TransportSleep (pIfSlpMng->tChipId, pIfSlpMng->tTransId); MCPF_REPORT_DEBUG_TX(pIfSlpMng->hMcpf, IFSLPMNG_MODULE_LOG, ("ifSlpMng_HandleTxComplEvent: going to sleep, pIfSlpMng=%p, state=%d\n", pIfSlpMng, pIfSlpMng->eState)); } else { /* Prepare and send AwakeInd request */ TXN_PARAM_SET_IFSLPMNG_OP (pIfSlpMng->pMngTxn, TXN_PARAM_IFSLPMNG_OP_AWAKE); txnQ_Transact (pIfSlpMng->hTxnQ, pIfSlpMng->pMngTxn); MCPF_REPORT_DEBUG_TX(pIfSlpMng->hMcpf, IFSLPMNG_MODULE_LOG, ("ifSlpMng_HandleTxComplEvent: Send Awake, pIfSlpMng=%p, state=%d\n", pIfSlpMng, pIfSlpMng->eState)); } } return RES_OK; }
/** * \fn twIf_SendTransaction * \brief Send a transaction to the device * * This method is used by the Xfer modules and the TwIf to send all transaction types to the device. * Send the transaction to the TxnQ and update the SM if needed. * * \note * \param pTwIf - The module's object * \param pTxn - The transaction object * \return COMPLETE if the transaction was completed in this context, PENDING if not, ERROR if failed * \sa */ static ETxnStatus twIf_SendTransaction(TTwIfObj * pTwIf, TTxnStruct * pTxn) { ETxnStatus eStatus; #ifdef TI_DBG TI_UINT32 data = 0; /* Verify that the Txn HW-Address is 4-bytes aligned */ if (pTxn->uHwAddr & 0x3) { TRACE2(pTwIf->hReport, REPORT_SEVERITY_ERROR, "twIf_SendTransaction: Unaligned HwAddr! HwAddr=0x%x, Params=0x%x\n", pTxn->uHwAddr, pTxn->uTxnParams); return TXN_STATUS_ERROR; } #endif context_EnterCriticalSection(pTwIf->hContext); /* increment pending Txn counter */ pTwIf->uPendingTxnCount++; context_LeaveCriticalSection(pTwIf->hContext); /* Send transaction to TxnQ */ eStatus = txnQ_Transact(pTwIf->hTxnQ, pTxn); #ifdef TI_DBG pTwIf->uDbgCountTxn++; if (eStatus == TXN_STATUS_COMPLETE) { pTwIf->uDbgCountTxnComplete++; } else if (eStatus == TXN_STATUS_PENDING) { pTwIf->uDbgCountTxnPending++; } COPY_WLAN_LONG(&data, &(pTxn->aBuf[0])); TRACE8(pTwIf->hReport, REPORT_SEVERITY_INFORMATION, "twIf_SendTransaction: Status = %d, Params=0x%x, HwAddr=0x%x, Len0=%d, Len1=%d, Len2=%d, Len3=%d, Data=0x%x \n", eStatus, pTxn->uTxnParams, pTxn->uHwAddr, pTxn->aLen[0], pTxn->aLen[1], pTxn->aLen[2], pTxn->aLen[3], data); #endif /* If Txn status is PENDING issue Start event to the SM */ if (eStatus == TXN_STATUS_PENDING) { twIf_HandleSmEvent(pTwIf, SM_EVENT_START); } /* Else (COMPLETE or ERROR) */ else { context_EnterCriticalSection(pTwIf->hContext); /* decrement pending Txn counter in case of sync transact */ pTwIf->uPendingTxnCount--; context_LeaveCriticalSection(pTwIf->hContext); /* If Awake not required and no pending transactions in TxnQ, issue Sleep event to SM */ if ((pTwIf->uAwakeReqCount == 0) && (pTwIf->uPendingTxnCount == 0)) { twIf_HandleSmEvent(pTwIf, SM_EVENT_SLEEP); } /* If Txn failed and error CB available, call it to initiate recovery */ if (eStatus == TXN_STATUS_ERROR) { TRACE6(pTwIf->hReport, REPORT_SEVERITY_ERROR, "twIf_SendTransaction: Txn failed!! Params=0x%x, HwAddr=0x%x, Len0=%d, Len1=%d, Len2=%d, Len3=%d\n", pTxn->uTxnParams, pTxn->uHwAddr, pTxn->aLen[0], pTxn->aLen[1], pTxn->aLen[2], pTxn->aLen[3]); if (pTwIf->fErrCb) { pTwIf->fErrCb(pTwIf->hErrCb, BUS_FAILURE); } } } /* Return the Txn status (COMPLETE if completed in this context, PENDING if not, ERROR if failed) */ return eStatus; }
/** * \fn twIf_SendTransaction * \brief Send a transaction to the device * * This method is used by the Xfer modules and the TwIf to send all transaction types to the device. * Send the transaction to the TxnQ and update the SM if needed. * * \note * \param pTwIf - The module's object * \param pTxn - The transaction object * \return COMPLETE if the transaction was completed in this context, PENDING if not, ERROR if failed * \sa */ static ETxnStatus twIf_SendTransaction (TTwIfObj *pTwIf, TTxnStruct *pTxn) { ETxnStatus eStatus; TI_UINT32 data=0; #ifdef TI_DBG /* Verify that the Txn HW-Address is 4-bytes aligned */ if (pTxn->uHwAddr & 0x3) { return TXN_STATUS_ERROR; } #endif context_EnterCriticalSection (pTwIf->hContext); /* increment pending Txn counter */ pTwIf->uPendingTxnCount++; context_LeaveCriticalSection (pTwIf->hContext); /* Send transaction to TxnQ */ eStatus = txnQ_Transact(pTwIf->hTxnQ, pTxn); #ifdef TI_DBG pTwIf->uDbgCountTxn++; if (eStatus == TXN_STATUS_COMPLETE) { pTwIf->uDbgCountTxnComplete++; } else if (eStatus == TXN_STATUS_PENDING ) { pTwIf->uDbgCountTxnPending++; } COPY_WLAN_LONG(&data,&(pTxn->aBuf[0])); #endif /* If Txn status is PENDING issue Start event to the SM */ if (eStatus == TXN_STATUS_PENDING) { twIf_HandleSmEvent (pTwIf, SM_EVENT_START); } /* Else (COMPLETE or ERROR) */ else { context_EnterCriticalSection (pTwIf->hContext); /* decrement pending Txn counter in case of sync transact*/ pTwIf->uPendingTxnCount--; context_LeaveCriticalSection (pTwIf->hContext); /* If Awake not required and no pending transactions in TxnQ, issue Sleep event to SM */ if ((pTwIf->uAwakeReqCount == 0) && (pTwIf->uPendingTxnCount == 0)) { twIf_HandleSmEvent (pTwIf, SM_EVENT_SLEEP); } /* If Txn failed and error CB available, call it to initiate recovery */ if (eStatus == TXN_STATUS_ERROR) { if (pTwIf->fErrCb) { pTwIf->fErrCb (pTwIf->hErrCb, BUS_FAILURE); } } } /* Return the Txn status (COMPLETE if completed in this context, PENDING if not, ERROR if failed) */ return eStatus; }
/** * \fn ifSlpMng_HandleRxEvent * \brief Interface Sleep Manager state machine for Rx event * * Process Rx event of Interface Sleep Manager state machine * */ EIfSlpMngStatus ifSlpMng_HandleRxEvent (handle_t hIfSlpMng, TTxnStruct *pTxn) { TifSlpMngObj * pIfSlpMng = (TifSlpMngObj *) hIfSlpMng; EIfSlpMngStatus eRes = IfSlpMng_ERR; McpBool stateChanged = MCP_FALSE; if (TXN_PARAM_GET_SINGLE_STEP (pTxn)) { /* IfSlpMng transaction is always single step, * get IfSlpMng opcode from transaction structure */ eRes = IfSlpMng_SLP_PKT_TYPE; switch (TXN_PARAM_GET_IFSLPMNG_OP (pTxn)) { case TXN_PARAM_IFSLPMNG_OP_SLEEP: MCPF_REPORT_DEBUG_RX(pIfSlpMng->hMcpf, IFSLPMNG_MODULE_LOG, ("ifSlpMng_HandleRxEvent: SLEEP_IND, state=%d\n",pIfSlpMng->eState)); MCPF_ENTER_CRIT_SEC (pIfSlpMng->hMcpf); if (pIfSlpMng->eState == IFSLPMNG_STATE_AWAKE) { pIfSlpMng->eState = IFSLPMNG_STATE_WAIT_FOR_SLEEPACK_TX_COMPL; stateChanged = MCP_TRUE; } pIfSlpMng->stat.SleepInd_Rx++; MCPF_EXIT_CRIT_SEC (pIfSlpMng->hMcpf); if (stateChanged) { txnQ_Stop (pIfSlpMng->hTxnQ, pIfSlpMng->uFuncId); /* Prepare and send SleepAck request */ TXN_PARAM_SET_IFSLPMNG_OP (pIfSlpMng->pMngTxn, TXN_PARAM_IFSLPMNG_OP_SLEEP_ACK); txnQ_Transact (pIfSlpMng->hTxnQ, pIfSlpMng->pMngTxn); pIfSlpMng->stat.SleepAck_Tx++; } break; case TXN_PARAM_IFSLPMNG_OP_SLEEP_ACK: MCPF_REPORT_ERROR (pIfSlpMng->hMcpf, IFSLPMNG_MODULE_LOG, ("%s: Not expected SleepAck received\n", __FUNCTION__)); pIfSlpMng->stat.SleepAck_Rx++; break; case TXN_PARAM_IFSLPMNG_OP_AWAKE: { EIfSlpMngState oldState; MCPF_REPORT_DEBUG_RX(pIfSlpMng->hMcpf, IFSLPMNG_MODULE_LOG, ("ifSlpMng_HandleRxEvent: AWAKE_IND, state=%d\n",pIfSlpMng->eState)); MCPF_ENTER_CRIT_SEC (pIfSlpMng->hMcpf); oldState = pIfSlpMng->eState; if ((pIfSlpMng->eState == IFSLPMNG_STATE_ASLEEP) || (pIfSlpMng->eState == IFSLPMNG_STATE_WAIT_FOR_AWAKE_ACK)) { pIfSlpMng->eState = IFSLPMNG_STATE_AWAKE; stateChanged = MCP_TRUE; } pIfSlpMng->stat.AwakeInd_Rx++; MCPF_EXIT_CRIT_SEC (pIfSlpMng->hMcpf); if (stateChanged) { switch (oldState) { case IFSLPMNG_STATE_ASLEEP: /* Prepare and send SleepAck request */ TXN_PARAM_SET_IFSLPMNG_OP (pIfSlpMng->pMngTxn, TXN_PARAM_IFSLPMNG_OP_AWAKE_ACK); txnQ_Transact (pIfSlpMng->hTxnQ, pIfSlpMng->pMngTxn); txnQ_Run (pIfSlpMng->hTxnQ, pIfSlpMng->uFuncId); pIfSlpMng->stat.AwakeAck_Tx++; break; case IFSLPMNG_STATE_WAIT_FOR_AWAKE_ACK: txnQ_Run (pIfSlpMng->hTxnQ, pIfSlpMng->uFuncId); break; default: break; } } } break; case TXN_PARAM_IFSLPMNG_OP_AWAKE_ACK: MCPF_REPORT_DEBUG_RX(pIfSlpMng->hMcpf, IFSLPMNG_MODULE_LOG, ("ifSlpMng_HandleRxEvent: AWAKE_ACK, state=%d\n",pIfSlpMng->eState)); MCPF_ENTER_CRIT_SEC (pIfSlpMng->hMcpf); if (pIfSlpMng->eState == IFSLPMNG_STATE_WAIT_FOR_AWAKE_ACK) { pIfSlpMng->eState = IFSLPMNG_STATE_AWAKE; stateChanged = MCP_TRUE; } pIfSlpMng->stat.AwakeAck_Rx++; MCPF_EXIT_CRIT_SEC (pIfSlpMng->hMcpf); if (stateChanged) { txnQ_Run (pIfSlpMng->hTxnQ, pIfSlpMng->uFuncId); } break; default: MCPF_REPORT_ERROR (pIfSlpMng->hMcpf, IFSLPMNG_MODULE_LOG, ("%s: Invalid IfSlpMng opcode=%u\n", __FUNCTION__, TXN_PARAM_GET_IFSLPMNG_OP (pTxn))); eRes = IfSlpMng_ERR; break; } /* Rx IFSLPMNG_OP */ } else { /* Normal packet received */ MCPF_ENTER_CRIT_SEC (pIfSlpMng->hMcpf); if (pIfSlpMng->eState == IFSLPMNG_STATE_ASLEEP) { pIfSlpMng->eState = IFSLPMNG_STATE_AWAKE; stateChanged = MCP_TRUE; pIfSlpMng->stat.AwakeAck_Tx++; } MCPF_EXIT_CRIT_SEC (pIfSlpMng->hMcpf); if (stateChanged) { /* Prepare and send SleepAck request */ TXN_PARAM_SET_IFSLPMNG_OP (pIfSlpMng->pMngTxn, TXN_PARAM_IFSLPMNG_OP_AWAKE_ACK); txnQ_Transact (pIfSlpMng->hTxnQ, pIfSlpMng->pMngTxn); txnQ_Run (pIfSlpMng->hTxnQ, pIfSlpMng->uFuncId); MCPF_REPORT_DEBUG_RX(pIfSlpMng->hMcpf, IFSLPMNG_MODULE_LOG, ("ifSlpMng_HandleRxEvent: Normal RX, state=%d\n",pIfSlpMng->eState)); } eRes = IfSlpMng_OK; } return eRes; }