void ar6000_dtimexpiry_event(void *dev) { #if 0 //bluebird A_BOOL isMcastQueued = FALSE; struct sk_buff *skb = NULL; /* If there are no associated STAs, ignore the DTIM expiry event. * There can be potential race conditions where the last associated * STA may disconnect & before the host could clear the 'Indicate DTIM' * request to the firmware, the firmware would have just indicated a DTIM * expiry event. The race is between 'clear DTIM expiry cmd' going * from the host to the firmware & the DTIM expiry event happening from * the firmware to the host. */ if (ar->sta_list_index == 0) { return; } A_MUTEX_LOCK(&ar->mcastpsqLock); isMcastQueued = A_NETBUF_QUEUE_EMPTY(&ar->mcastpsq); A_MUTEX_UNLOCK(&ar->mcastpsqLock); A_ASSERT(isMcastQueued == FALSE); /* Flush the mcast psq to the target */ /* Set the STA flag to DTIMExpired, so that the frame will go out */ ar->DTIMExpired = TRUE; A_MUTEX_LOCK(&ar->mcastpsqLock); while (!A_NETBUF_QUEUE_EMPTY(&ar->mcastpsq)) { skb = A_NETBUF_DEQUEUE(&ar->mcastpsq); A_MUTEX_UNLOCK(&ar->mcastpsqLock); ar6000_data_tx(skb, ar->arNetDev); A_MUTEX_LOCK(&ar->mcastpsqLock); } A_MUTEX_UNLOCK(&ar->mcastpsqLock); /* Reset the DTIMExpired flag back to 0 */ ar->DTIMExpired = FALSE; /* Clear the LSB of the BitMapCtl field of the TIM IE */ wmi_set_pvb_cmd(ar->arWmi, MCAST_AID, 0); #else NDIS_DEBUG_PRINTF(DBG_TRACE, " %s() is not ready yet~ \r\n", __FUNCTION__); #endif }
bool CAsyncIOConnection::Connect(const ASOCK_ADDR& sa) { bool bRet; A_MUTEX_LOCK(&m_mtxLock); ZION_ASSERT(!m_pSendBuf); ZION_ASSERT(!m_hConn); ZION_ASSERT(!m_bConnecting); if(m_hConn || m_bConnecting) { bRet = false; } else { m_pSendBuf = NULL; m_bConnecting = true; bRet = Zion::Connect(sa, g_client_handler, CAsyncIOInit::Get().m_iopool, CAsyncIOInit::Get().m_workers, this); if(!bRet) m_bConnecting = false; } A_MUTEX_UNLOCK(&m_mtxLock); return bRet; }
void CStressManager::DisconnectAll() { Zion::Map<_U32, CStressClient*>::iterator i; _U32 count = 1; while(count>0) { count = 0; A_MUTEX_LOCK(&m_mtxLocker); for(i=m_mapClients.begin(); i!=m_mapClients.end(); i++) { i->second->Logout(); if(i->second->GetClient()->GetState()!=CClient::STATE_NA && i->second->GetClient()->GetState()!=CClient::STATE_FAILED) count++; } A_MUTEX_UNLOCK(&m_mtxLocker); SwitchToThread(); if(!CClientApp::GetDefault()->IsThread()) { CClientApp::GetDefault()->Tick(); } } for(i=m_mapClients.begin(); i!=m_mapClients.end(); i++) { delete i->second; } m_mapClients.clear(); }
void a_module_debug_support_cleanup(void) { ATH_DEBUG_MODULE_DBG_INFO *pInfo = g_pModuleInfoHead; ATH_DEBUG_MODULE_DBG_INFO *pCur; if (!g_ModuleDebugInit) { return; } g_ModuleDebugInit = FALSE; A_MUTEX_LOCK(&g_ModuleListLock); while (pInfo != NULL) { pCur = pInfo; pInfo = pInfo->pNext; pCur->pNext = NULL; /* clear registered flag */ pCur->Flags &= ~ATH_DEBUG_INFO_FLAGS_REGISTERED; } A_MUTEX_UNLOCK(&g_ModuleListLock); A_MUTEX_DELETE(&g_ModuleListLock); g_pModuleInfoHead = NULL; }
void Abf_WlanStackNotificationDeInit(ATH_BT_FILTER_INSTANCE *pInstance) { ATHBT_FILTER_INFO *pInfo = (ATHBT_FILTER_INFO *)pInstance->pContext; ABF_WLAN_INFO *pAbfWlanInfo = pInfo->pWlanInfo; if (!pAbfWlanInfo) return; /* Terminate and wait for the WLAN Event Handler task to finish */ A_MUTEX_LOCK(&pAbfWlanInfo->hWaitEventLock); if (pAbfWlanInfo->Loop) { pAbfWlanInfo->Loop = FALSE; A_COND_WAIT(&pAbfWlanInfo->hWaitEvent, &pAbfWlanInfo->hWaitEventLock, WAITFOREVER); } A_MUTEX_UNLOCK(&pAbfWlanInfo->hWaitEventLock); /* Flush all the BT actions from the filter core */ HandleAdapterEvent(pInfo, ATH_ADAPTER_REMOVED); pInfo->pWlanInfo = NULL; A_MUTEX_DEINIT(&pAbfWlanInfo->hWaitEventLock); A_COND_DEINIT(&pAbfWlanInfo->hWaitEvent); A_MEMZERO(pAbfWlanInfo, sizeof(ABF_WLAN_INFO)); A_FREE(pAbfWlanInfo); A_INFO("WLAN Stack Notification de-init complete\n"); }
const Zion::String CStressClient::GetInfo() { Zion::String ret; A_MUTEX_LOCK(&m_pClient->m_mtxClient); ret = m_Info; A_MUTEX_UNLOCK(&m_pClient->m_mtxClient); return ret; }
void CClientApp::QueueTask(CClient* pClient, CClientTask* pTask) { ZION_ASSERT(!m_bThread); CLIENTAPP_ITEM i = { 4, pClient, 0, 0, 0, NULL }; A_MUTEX_LOCK(&m_mtxQueue); m_Queue.push_back(i); A_MUTEX_UNLOCK(&m_mtxQueue); }
_U32 CStressManager::NewClient() { _U32 index = A_ATOM_INC(&m_nIDSeq); CStressClient* pClient = ZION_NEW CStressClient(index, CClientApp::GetDefault()->NewClient()); A_MUTEX_LOCK(&m_mtxLocker); m_mapClients[index] = pClient; A_MUTEX_UNLOCK(&m_mtxLocker); return index; }
void ar6000_pspoll_event(void *dev,A_UINT8 aid) { #if 0 //bluebird sta_t *conn=NULL; A_BOOL isPsqEmpty = FALSE; conn = ieee80211_find_conn_for_aid(ar, aid); /* If the PS q for this STA is not empty, dequeue and send a pkt from * the head of the q. Also update the More data bit in the WMI_DATA_HDR * if there are more pkts for this STA in the PS q. If there are no more * pkts for this STA, update the PVB for this STA. */ A_MUTEX_LOCK(&conn->psqLock); isPsqEmpty = A_NETBUF_QUEUE_EMPTY(&conn->psq); A_MUTEX_UNLOCK(&conn->psqLock); if (isPsqEmpty) { /* TODO:No buffered pkts for this STA. Send out a NULL data frame */ } else { struct sk_buff *skb = NULL; A_MUTEX_LOCK(&conn->psqLock); skb = A_NETBUF_DEQUEUE(&conn->psq); A_MUTEX_UNLOCK(&conn->psqLock); /* Set the STA flag to PSPolled, so that the frame will go out */ STA_SET_PS_POLLED(conn); ar6000_data_tx(skb, ar->arNetDev); STA_CLR_PS_POLLED(conn); /* Clear the PVB for this STA if the queue has become empty */ A_MUTEX_LOCK(&conn->psqLock); isPsqEmpty = A_NETBUF_QUEUE_EMPTY(&conn->psq); A_MUTEX_UNLOCK(&conn->psqLock); if (isPsqEmpty) { wmi_set_pvb_cmd(ar->arWmi, conn->aid, 0); } } #else NDIS_DEBUG_PRINTF(DBG_TRACE, " %s() is not ready yet~ \r\n", __FUNCTION__); #endif //bluebird }
void CAsyncIOConnection::OnRawConnected(HCONNECT hConn) { A_MUTEX_LOCK(&m_mtxLock); ZION_ASSERT(!m_hConn); m_hConn = hConn; m_bConnecting = false; A_MUTEX_UNLOCK(&m_mtxLock); CClientConnection::OnRawConnected(); }
CStressClient* CStressManager::GetClient(_U32 id) { CStressClient* pClient; Zion::Map<_U32, CStressClient*>::iterator i; A_MUTEX_LOCK(&m_mtxLocker); i = m_mapClients.find(id); pClient = (i==m_mapClients.end()?NULL:i->second); A_MUTEX_UNLOCK(&m_mtxLocker); return pClient; }
void CStressManager::GetClients(Zion::Array<_U32>& clients) { clients.clear(); Zion::Map<_U32, CStressClient*>::iterator i; A_MUTEX_LOCK(&m_mtxLocker); for(i=m_mapClients.begin(); i!=m_mapClients.end(); i++) { clients.push_back(i->first); } A_MUTEX_UNLOCK(&m_mtxLocker); }
void CStressClient::Tick() { A_MUTEX_LOCK(&m_pClient->m_mtxClient); Zion::Map<Zion::String, CStressCase*>::iterator i; for(i=m_Cases.begin(); i!=m_Cases.end(); i++) { i->second->OnTick(); } A_MUTEX_UNLOCK(&m_pClient->m_mtxClient); }
void CAsyncIOConnection::OnRawDisconnected() { A_MUTEX_LOCK(&m_mtxLock); if(m_pSendBuf) { UnlockIoBuffer(m_pSendBuf); m_pSendBuf = NULL; } m_hConn = NULL; A_MUTEX_UNLOCK(&m_mtxLock); CClientConnection::OnRawDisconnected(); }
void CClientApp::QueueDisconnected(CClient* pClient) { if(m_bThread) { pClient->OnDisconnected(); return; } CLIENTAPP_ITEM i = { 2, pClient, 0, 0, 0, NULL }; A_MUTEX_LOCK(&m_mtxQueue); m_Queue.push_back(i); A_MUTEX_UNLOCK(&m_mtxQueue); }
void CClientApp::QueueLoginDone(CClient* pClient) { if(m_bThread) { pClient->OnLoginDone(); return; } CLIENTAPP_ITEM i = { 0, pClient, 0, 0, 0, NULL }; A_MUTEX_LOCK(&m_mtxQueue); m_Queue.push_back(i); A_MUTEX_UNLOCK(&m_mtxQueue); }
void CStressManager::UpdateAll() { A_MUTEX_LOCK(&m_mtxLocker); Zion::Map<_U32, CStressClient*>::iterator it = m_mapClients.begin(); while(it != m_mapClients.end()) { it->second->Tick(); ++it; } A_MUTEX_UNLOCK(&m_mtxLocker); }
void CClientApp::QueueData(CClient* pClient, _U16 iid, _U16 fid, _U32 len, const _U8* data) { if(m_bThread) { pClient->OnData(iid, fid, len, data); return; } CLIENTAPP_ITEM i = { 3, pClient, iid, fid, len, NULL }; i.data = (_U8*)ZION_ALLOC(len); memcpy(i.data, data, len); A_MUTEX_LOCK(&m_mtxQueue); m_Queue.push_back(i); A_MUTEX_UNLOCK(&m_mtxQueue); }
bool CClientApp::Tick(_U32 nTime) { if(m_bThread) return false; bool bQuit = false, bRet = false; CLIENTAPP_ITEM i; while(!bQuit) { A_MUTEX_LOCK(&m_mtxQueue); if(m_Queue.size()==0) { bQuit = true; A_MUTEX_UNLOCK(&m_mtxQueue); break; } i = m_Queue.front(); m_Queue.pop_front(); bRet = true; A_MUTEX_UNLOCK(&m_mtxQueue); switch(i.nCode) { case 0: i.pClient->OnLoginDone(); break; case 1: i.pClient->OnLoginFailed(); break; case 2: i.pClient->OnDisconnected(); break; case 3: i.pClient->OnData(i.iid, i.fid, i.len, i.data); ZION_FREE(i.data); break; } } Zion::Set<CClient*>::iterator it; for(it=m_Clients.begin(); it!=m_Clients.end(); it++) { (*it)->Tick(); } return bRet; }
void a_register_module_debug_info(ATH_DEBUG_MODULE_DBG_INFO *pInfo) { if (!g_ModuleDebugInit) { return; } A_MUTEX_LOCK(&g_ModuleListLock); if (!(pInfo->Flags & ATH_DEBUG_INFO_FLAGS_REGISTERED)) { if (g_pModuleInfoHead == NULL) { g_pModuleInfoHead = pInfo; } else { pInfo->pNext = g_pModuleInfoHead; g_pModuleInfoHead = pInfo; } pInfo->Flags |= ATH_DEBUG_INFO_FLAGS_REGISTERED; } A_MUTEX_UNLOCK(&g_ModuleListLock); }
CStressCase* CStressClient::NewStressCase(const char* name) { CStressCase* pCase = NULL; A_MUTEX_LOCK(&m_pClient->m_mtxClient); Zion::Map<Zion::String, CStressCase*>::iterator i; i = m_Cases.find(name); if(i==m_Cases.end()) { pCase = CStressManager::Get().CreateCase(name); if(pCase) { CaseAttach(pCase); } } A_MUTEX_UNLOCK(&m_pClient->m_mtxClient); return pCase; }
void CAsyncIOConnection::SendData(_U32 len, const _U8* data, bool bPending) { A_MUTEX_LOCK(&m_mtxLock); HIOPOOL pool = HIOPoolOf(m_hConn); _U32 blen = GetIoBufferSize(pool); _U32 dolen; while(len>0) { if(!m_pSendBuf) { m_pSendBuf = LockIoBuffer(pool); m_nSendBufLen = 0; } dolen = (len>blen-m_nSendBufLen)?blen-m_nSendBufLen:len; memcpy(m_pSendBuf+m_nSendBufLen, data, dolen); len -= dolen; data += dolen; m_nSendBufLen += dolen; if(m_nSendBufLen==blen) { Send(m_hConn, m_nSendBufLen, m_pSendBuf); m_pSendBuf = NULL; } } if(!bPending && m_pSendBuf!=NULL && m_nSendBufLen>0) { Send(m_hConn, m_nSendBufLen, m_pSendBuf); m_pSendBuf = NULL; } A_MUTEX_UNLOCK(&m_mtxLock); }
void htcServiceCounterInterrupt(HTC_TARGET *target) { A_STATUS status; A_UINT32 address; HIF_REQUEST request; HTC_ENDPOINT *endPoint; HTC_ENDPOINT_ID endPointId; A_UINT8 counter_int_status; A_UINT8 reset_credit_int_status; A_UINT8 update_credit_int_status; HTC_REG_REQUEST_ELEMENT *element; HTC_DEBUG_PRINTF(ATH_LOG_INF, "Counter Interrupt\n"); counter_int_status = target->table.counter_int_status & target->table.counter_int_status_enable; AR_DEBUG_ASSERT(counter_int_status); HTC_DEBUG_PRINTF(ATH_LOG_INF, "Valid interrupt source(s) in COUNTER_INT_STATUS: 0x%x\n", counter_int_status); /* Service the reset credit counter interrupt */ reset_credit_int_status = (counter_int_status & 0x0F); while(reset_credit_int_status) { endPointId = htcGetBitNumSet(reset_credit_int_status); endPoint = &target->endPoint[endPointId]; AR_DEBUG_ASSERT(endPoint != NULL); HTC_DEBUG_PRINTF(ATH_LOG_INF, "endPoint(%d): %p\n", endPointId, endPoint); /* Initialize the number of credits available to zero */ HTC_DEBUG_PRINTF(ATH_LOG_SYNC, "Critical Section (credit): LOCK at line %d in file %s\n", __LINE__, __FILE__); A_MUTEX_LOCK(&creditCS); SET_TX_CREDITS_AVAILABLE(endPoint, 0); HTC_DEBUG_PRINTF(ATH_LOG_SYNC, "Critical Section (credit): UNLOCK at line %d in file %s\n", __LINE__, __FILE__); A_MUTEX_UNLOCK(&creditCS); /* Clear the interrupt */ HIF_FRAME_REQUEST(&request, HIF_READ, HIF_EXTENDED_IO, HIF_ASYNCHRONOUS, HIF_BYTE_BASIS, HIF_FIXED_ADDRESS); address = getRegAddr(TX_CREDIT_COUNTER_RESET_REG, endPointId); element = allocateRegRequestElement(target); AR_DEBUG_ASSERT(element != NULL); FILL_REG_BUFFER(element, &endPoint->txCreditsAvailable[1], sizeof(endPoint->txCreditsAvailable[1]), TX_CREDIT_COUNTER_RESET_REG, endPointId); status = HIFReadWrite(target->device, address, (A_UCHAR *)&endPoint->txCreditsAvailable[1], sizeof(endPoint->txCreditsAvailable[1]), &request, element); #ifndef HTC_SYNC AR_DEBUG_ASSERT(status == A_OK); #else AR_DEBUG_ASSERT(status == A_OK || status == A_PENDING); if (status == A_OK) { /* Enable the Tx credit counter interrupt so that we can get the * credits posted by the target */ htcEnableCreditCounterInterrupt(target, endPointId); } #endif reset_credit_int_status &= ~(1 << htcGetBitNumSet(reset_credit_int_status)); } /* Disable the credit counter interrupt */ htcDisableCreditCounterInterrupt(target, ENDPOINT_UNUSED); /* Service the credit counter interrupt */ update_credit_int_status = counter_int_status & 0xF0; while(update_credit_int_status) { endPointId = htcGetBitNumSet(update_credit_int_status) - HTC_MAILBOX_NUM_MAX; endPoint = &target->endPoint[endPointId]; AR_DEBUG_ASSERT(endPoint != NULL); /* This is the minimum number of credits that we would have got */ AR_DEBUG_ASSERT(GET_TX_CREDITS_AVAILABLE(endPoint) == 0); HTC_DEBUG_PRINTF(ATH_LOG_SYNC, "Critical Section (credit): LOCK at line %d in file %s\n", __LINE__, __FILE__); A_MUTEX_LOCK(&creditCS); SET_TX_CREDITS_AVAILABLE(endPoint, 1); HTC_DEBUG_PRINTF(ATH_LOG_SYNC, "Critical Section (credit): UNLOCK at line %d in file %s\n", __LINE__, __FILE__); A_MUTEX_UNLOCK(&creditCS); #ifdef DEBUG txcreditsavailable[endPointId] = GET_TX_CREDITS_AVAILABLE(endPoint); txcreditintrenable[endPointId] -= 1; #endif /* DEBUG */ HTC_DEBUG_PRINTF(ATH_LOG_INF, "Tx Credits Available: %d\n", GET_TX_CREDITS_AVAILABLE(endPoint)); if (!target->ready) { htcSendBlkSize(endPoint); } else { htcSendFrame(endPoint); } update_credit_int_status &= ~(1 << htcGetBitNumSet(update_credit_int_status)); } }
/* Internal functions */ static void * WlanEventThread(void *arg) { int left, ret, sd; struct timeval tv; socklen_t fromlen; struct nlmsghdr *h; fd_set readfds, tempfds; char buf[WLAN_EVENT_SIZE_MAX]; struct sockaddr_nl from, local; ABF_WLAN_INFO *pAbfWlanInfo = (ABF_WLAN_INFO *)arg; ATHBT_FILTER_INFO *pInfo = pAbfWlanInfo->pInfo; ATH_BT_FILTER_INSTANCE *pInstance = pInfo->pInstance; A_STATUS status; A_INFO("Starting the WLAN Event Handler task\n"); A_INFO("Checking WLAN adapter on startup .. \n"); if (!pInstance->pWlanAdapterName) { Abf_WlanCheckSettings(pAbfWlanInfo->IfName, NULL); if (pAbfWlanInfo->IfName[0]) { pAbfWlanInfo->IfIndex = if_nametoindex(pAbfWlanInfo->IfName); } } status = AcquireWlanAdapter(pAbfWlanInfo); if (A_FAILED(status)) { A_INFO("No WLAN adapter on startup (OKAY) \n"); }else { /* Communicate this to the Filter task */ HandleAdapterEvent(pInfo, ATH_ADAPTER_ARRIVED); A_INFO("WLAN Adapter Added\n"); } do { sd = socket(PF_NETLINK, SOCK_RAW, NETLINK_ROUTE); if (sd < 0) { A_ERR("[%s] socket(PF_NETLINK,SOCK_RAW,NETLINK_ROUTE): %d\n", __FUNCTION__, sd); break; } A_MEMZERO(&local, sizeof(struct sockaddr_nl)); local.nl_family = AF_NETLINK; local.nl_groups = RTMGRP_LINK; if ((ret = bind(sd, (struct sockaddr *) &local, sizeof(local))) < 0) { A_ERR("[%s] bind(netlink): %d\n", __FUNCTION__, ret); close(sd); break; } FD_ZERO(&readfds); FD_SET(sd, &readfds); while (pAbfWlanInfo->Loop) { A_MEMCPY(&tempfds, &readfds, sizeof(fd_set)); tv.tv_sec = 1; tv.tv_usec = 0; ret = select(sd+1, &tempfds, NULL, NULL, &tv); if ((ret < 0) && (errno != EINTR)) { A_ERR("[%s] select failed: %d\n", __FUNCTION__, ret); break; } else if ((ret > 0) && (FD_ISSET(sd, &tempfds))) { fromlen = sizeof(from); do { left = recvfrom(sd, buf, sizeof(buf), 0, (struct sockaddr *) &from, &fromlen); } while (left == -1 && errno == EINTR); if (left < 0) { A_ERR("[%s] recvfrom(netlink)\n", __FUNCTION__); continue; // break; } h = (struct nlmsghdr *) buf; while (left >= sizeof(*h)) { int len, plen; len = h->nlmsg_len; plen = len - sizeof(*h); if (len > left || plen < 0) { A_ERR("[%s] malformed netlink message\n", __FUNCTION__); continue; } //A_DEBUG("RTM Message Type: %s\n", // ((h->nlmsg_type == RTM_NEWLINK) ? // "RTM_NEWLINK" : ((h->nlmsg_type == RTM_DELLINK) ? // "RTM_DELLINK" : "RTM_OTHER"))); switch (h->nlmsg_type) { case RTM_NEWLINK: NewLinkEvent(pInstance, h, plen); break; case RTM_DELLINK: DelLinkEvent(pInstance, h, plen); break; default: break; } len = NLMSG_ALIGN(len); left -= len; h = (struct nlmsghdr *) ((char *) h + len); } } } close(sd); } while (FALSE); /* Clean up the resources allocated in this task */ A_INFO("Terminating the WLAN Event Handler task\n"); A_MUTEX_LOCK(&pAbfWlanInfo->hWaitEventLock); pAbfWlanInfo->Loop = FALSE; A_COND_SIGNAL(&pAbfWlanInfo->hWaitEvent); A_MUTEX_UNLOCK(&pAbfWlanInfo->hWaitEventLock); return NULL; }
void CAsyncIOConnection::Disconnect() { A_MUTEX_LOCK(&m_mtxLock); if(m_hConn) Zion::Disconnect(m_hConn); A_MUTEX_UNLOCK(&m_mtxLock); }
A_STATUS htcRegCompletionCB(HTC_REG_REQUEST_ELEMENT *element, A_STATUS status) { A_STATUS ret; HTC_TARGET *target; HTC_ENDPOINT *endPoint; HTC_REG_BUFFER *regBuffer; #ifdef ONLY_16BIT A_UINT16 txCreditsConsumed; A_UINT16 txCreditsAvailable; #else A_UINT8 txCreditsConsumed; A_UINT8 txCreditsAvailable; #endif HTC_ENDPOINT_ID endPointId; HTC_DEBUG_PRINTF(ATH_LOG_TRC | ATH_LOG_SEND | ATH_LOG_RECV, "htcRegCompletion - Enter\n"); AR_DEBUG_ASSERT(status == A_OK); /* Get the context */ AR_DEBUG_ASSERT(element != NULL); regBuffer = GET_REG_BUFFER(element); AR_DEBUG_ASSERT(regBuffer != NULL); target = regBuffer->target; AR_DEBUG_ASSERT(target != NULL); /* Identify the register and the operation responsible for the callback */ ret = A_OK; switch(regBuffer->base) { case TX_CREDIT_COUNTER_DECREMENT_REG: HTC_DEBUG_PRINTF(ATH_LOG_INF, "TX_CREDIT_COUNTER_DECREMENT_REG\n"); endPointId = regBuffer->offset; endPoint = &target->endPoint[endPointId]; HTC_DEBUG_PRINTF(ATH_LOG_SYNC, "Critical Section (credit): LOCK at line %d in file %s\n", __LINE__, __FILE__); A_MUTEX_LOCK(&creditCS); /* Calculate the number of credits available */ #ifdef ONLY_16BIT AR_DEBUG_ASSERT((GET_TX_CREDITS_CONSUMED(endPoint)*2) == regBuffer->length); #else AR_DEBUG_ASSERT(GET_TX_CREDITS_CONSUMED(endPoint) == regBuffer->length); #endif AR_DEBUG_ASSERT(regBuffer->buffer[0] >= GET_TX_CREDITS_CONSUMED(endPoint)); SET_TX_CREDITS_AVAILABLE(endPoint, regBuffer->buffer[0] - GET_TX_CREDITS_CONSUMED(endPoint)); SET_TX_CREDITS_CONSUMED(endPoint, 0); txCreditsAvailable = GET_TX_CREDITS_AVAILABLE(endPoint); txCreditsConsumed = GET_TX_CREDITS_CONSUMED(endPoint); HTC_DEBUG_PRINTF(ATH_LOG_SYNC, "Critical Section (credit): UNLOCK at line %d in file %s\n", __LINE__, __FILE__); A_MUTEX_UNLOCK(&creditCS); HTC_DEBUG_PRINTF(ATH_LOG_INF | ATH_LOG_SEND, "Pulling %d tx credits from the target\n", txCreditsAvailable); #ifdef DEBUG txcreditsavailable[endPointId] = txCreditsAvailable; txcreditsconsumed[endPointId] = txCreditsConsumed; #endif /* DEBUG */ if (txCreditsAvailable) { htcSendFrame(endPoint); } else { /* * Enable the Tx credit counter interrupt so that we can get the * credits posted by the target. */ htcEnableCreditCounterInterrupt(target, endPointId); #ifdef DEBUG txcreditintrenable[endPointId] += 1; txcreditintrenableaggregate[endPointId] += 1; #endif /* DEBUG */ } break; case TX_CREDIT_COUNTER_RESET_REG: HTC_DEBUG_PRINTF(ATH_LOG_INF, "TX_CREDIT_COUNTER_RESET_REG\n"); endPointId = regBuffer->offset; /* * Enable the Tx credit counter interrupt so that we can get the * credits posted by the target. */ htcEnableCreditCounterInterrupt(target, endPointId); #ifdef DEBUG txcreditintrenable[endPointId] += 1; txcreditintrenableaggregate[endPointId] += 1; #endif /* DEBUG */ break; case COUNTER_INT_STATUS_ENABLE_REG: HTC_DEBUG_PRINTF(ATH_LOG_INF, "COUNTER_INT_STATUS_ENABLE: 0x%x\n", target->table.counter_int_status_enable); break; case COUNTER_INT_STATUS_DISABLE_REG: HTC_DEBUG_PRINTF(ATH_LOG_INF, "COUNTER_INT_STATUS_DISABLE:0x%x\n", target->table.counter_int_status_enable); HIFAckInterrupt(target->device); HTC_DEBUG_PRINTF(ATH_LOG_TRC, "htcDSRHandler - ACK\n"); break; case INT_WLAN_REG: HTC_DEBUG_PRINTF(ATH_LOG_INF, "INT_WLAN: 0x%x\n", target->table.int_wlan); target->table.int_wlan = 0; /* Mark the target state as ready and signal the waiting sem */ target->ready = TRUE; A_WAKE_UP(&htcEvent); break; case INT_STATUS_ENABLE_REG: HTC_DEBUG_PRINTF(ATH_LOG_INF, "INT_STATUS_ENABLE: 0x%x\n", target->table.int_status_enable); break; default: HTC_DEBUG_PRINTF(ATH_LOG_ERR, "Invalid register address: %d\n", regBuffer->base); } /* Free the register request structure */ freeRegRequestElement(element); HTC_DEBUG_PRINTF(ATH_LOG_TRC, "htcRegCompletion - Exit\n"); return ret; }
void htcDisableCreditCounterInterrupt(HTC_TARGET *target, HTC_ENDPOINT_ID unused) { A_STATUS status; A_UINT32 address; HIF_REQUEST request; HTC_ENDPOINT *endPoint; HTC_ENDPOINT_ID endPointId; A_UINT8 update_credit_int_status; HTC_REG_REQUEST_ELEMENT *element; #ifdef ONLY_16BIT A_UINT16 counter_int_enable16; #endif A_UCHAR counter_int_enable; A_MUTEX_LOCK(&counterCS); /* The Tx credit counter update bits are reflected in the upper nibble */ update_credit_int_status = target->table.counter_int_status & 0xF0; while(update_credit_int_status) { endPointId = htcGetBitNumSet(update_credit_int_status) - HTC_MAILBOX_NUM_MAX; endPoint = &target->endPoint[endPointId]; AR_DEBUG_ASSERT(endPoint != NULL); HTC_DEBUG_PRINTF(ATH_LOG_INF, "endPoint(%d): %p\n", endPointId, endPoint); /* Disable the tx credit interrupt */ endPoint->txCreditsIntrEnable = FALSE; update_credit_int_status &= ~(1 << htcGetBitNumSet(update_credit_int_status)); } HIF_FRAME_REQUEST(&request, HIF_WRITE, HIF_EXTENDED_IO, HIF_ASYNCHRONOUS, HIF_BYTE_BASIS, HIF_FIXED_ADDRESS); element = allocateRegRequestElement(target); AR_DEBUG_ASSERT(element != NULL); counter_int_enable = ((target->endPoint[0].txCreditsIntrEnable << (4)) | (target->endPoint[1].txCreditsIntrEnable << (5)) | (target->endPoint[2].txCreditsIntrEnable << (6)) | (target->endPoint[3].txCreditsIntrEnable << (7)) | 0x0F); #ifdef ONLY_16BIT counter_int_enable16 = (counter_int_enable << 8) | target->table.error_status_enable; FILL_REG_BUFFER(element, NULL, 2, COUNTER_INT_STATUS_DISABLE_REG, counter_int_enable16); address = getRegAddr(ERROR_STATUS_ENABLE_REG, ENDPOINT_UNUSED); status = HIFReadWrite(target->device, address, (A_UCHAR *)&((GET_REG_BUFFER(element))->offset), 2, &request, element); #else FILL_REG_BUFFER(element, NULL, 1, COUNTER_INT_STATUS_DISABLE_REG, counter_int_enable); address = getRegAddr(COUNTER_INT_STATUS_DISABLE_REG, ENDPOINT_UNUSED); status = HIFReadWrite(target->device, address, (A_UCHAR *)&((GET_REG_BUFFER(element))->offset), 1, &request, element); #endif #ifndef HTC_SYNC AR_DEBUG_ASSERT(status == A_OK); #else AR_DEBUG_ASSERT(status == A_OK || status == A_PENDING); if ( status == A_OK ) { element->completionCB(element, status); } #endif A_MUTEX_UNLOCK(&counterCS); }
void htcEnableCreditCounterInterrupt(HTC_TARGET *target, HTC_ENDPOINT_ID endPointId) { A_STATUS status; A_UINT32 address; HIF_REQUEST request; HTC_ENDPOINT *endPoint; HTC_REG_REQUEST_ELEMENT *element; #ifdef ONLY_16BIT A_UINT16 counter_int_enable16; #endif A_UCHAR counter_int_enable; endPoint = &target->endPoint[endPointId]; AR_DEBUG_ASSERT(endPoint != NULL); A_MUTEX_LOCK(&counterCS); endPoint->txCreditsIntrEnable = TRUE; HIF_FRAME_REQUEST(&request, HIF_WRITE, HIF_EXTENDED_IO, HIF_ASYNCHRONOUS, HIF_BYTE_BASIS, HIF_FIXED_ADDRESS); element = allocateRegRequestElement(target); AR_DEBUG_ASSERT(element != NULL); counter_int_enable = ((target->endPoint[0].txCreditsIntrEnable << (4)) | (target->endPoint[1].txCreditsIntrEnable << (5)) | (target->endPoint[2].txCreditsIntrEnable << (6)) | (target->endPoint[3].txCreditsIntrEnable << (7)) | 0x0F); #ifdef ONLY_16BIT counter_int_enable16 = (counter_int_enable << 8) | target->table.error_status_enable; FILL_REG_BUFFER(element, NULL, 2, COUNTER_INT_STATUS_ENABLE_REG, counter_int_enable16); address = getRegAddr(ERROR_STATUS_ENABLE_REG, ENDPOINT_UNUSED); status = HIFReadWrite(target->device, address, (A_UCHAR *)&((GET_REG_BUFFER(element))->offset), 2, &request, element); #else FILL_REG_BUFFER(element, NULL, 1, COUNTER_INT_STATUS_ENABLE_REG, counter_int_enable); address = getRegAddr(COUNTER_INT_STATUS_ENABLE_REG, ENDPOINT_UNUSED); status = HIFReadWrite(target->device, address, (A_UCHAR *)&((GET_REG_BUFFER(element))->offset), 1, &request, element); #endif #ifndef HTC_SYNC AR_DEBUG_ASSERT(status == A_OK); #else AR_DEBUG_ASSERT(status == A_OK || status == A_PENDING); if (status == A_OK) { element->completionCB(element, status); } #endif A_MUTEX_UNLOCK(&counterCS); }