/** * @brief Cancel all pending cmd. * * @param pmadapter A pointer to mlan_adapter * * @return N/A */ void wlan_cancel_all_pending_cmd(pmlan_adapter pmadapter) { cmd_ctrl_node *pcmd_node = MNULL; pmlan_callbacks pcb = &pmadapter->callbacks; mlan_ioctl_req *pioctl_buf = MNULL; /* Cancel current cmd */ if ((pmadapter->curr_cmd) && (pmadapter->curr_cmd->pioctl_buf)) { pioctl_buf = (mlan_ioctl_req *) pmadapter->curr_cmd->pioctl_buf; wlan_request_cmd_lock(pmadapter); pmadapter->curr_cmd->pioctl_buf = MNULL; wlan_release_cmd_lock(pmadapter); pioctl_buf->status_code = MLAN_ERROR_CMD_CANCEL; pcb->moal_ioctl_complete(pmadapter->pmoal_handle, pioctl_buf, MLAN_STATUS_FAILURE); } /* Cancel all pending command */ while ((pcmd_node = (cmd_ctrl_node *) util_peek_list(&pmadapter->cmd_pending_q, pcb->moal_spin_lock, pcb->moal_spin_unlock))) { util_unlink_list(&pmadapter->cmd_pending_q, (pmlan_linked_list) pcmd_node, pcb->moal_spin_lock, pcb->moal_spin_unlock); if (pcmd_node->pioctl_buf) { pioctl_buf = (mlan_ioctl_req *) pcmd_node->pioctl_buf; pioctl_buf->status_code = MLAN_ERROR_CMD_CANCEL; pcb->moal_ioctl_complete(pmadapter->pmoal_handle, pioctl_buf, MLAN_STATUS_FAILURE); pcmd_node->pioctl_buf = MNULL; } wlan_insert_cmd_to_free_q(pmadapter, pcmd_node); } /* Cancel all pending scan command */ while ((pcmd_node = (cmd_ctrl_node *) util_peek_list(&pmadapter->scan_pending_q, pcb->moal_spin_lock, pcb->moal_spin_unlock))) { util_unlink_list(&pmadapter->scan_pending_q, (pmlan_linked_list) pcmd_node, pcb->moal_spin_lock, pcb->moal_spin_unlock); pcmd_node->pioctl_buf = MNULL; wlan_insert_cmd_to_free_q(pmadapter, pcmd_node); } wlan_request_cmd_lock(pmadapter); pmadapter->scan_processing = MFALSE; wlan_release_cmd_lock(pmadapter); }
/** * @brief This function will return the pointer to the first entry in * pending cmd which matches the given pioctl_req * * @param pmadapter A pointer to mlan_adapter * @param pioctl_req A pointer to mlan_ioctl_req buf * * @return A pointer to first entry match pioctl_req */ cmd_ctrl_node * wlan_get_pending_ioctl_cmd(pmlan_adapter pmadapter, pmlan_ioctl_req pioctl_req) { cmd_ctrl_node *pcmd_node = MNULL; ENTER(); if (! (pcmd_node = (cmd_ctrl_node *) util_peek_list(&pmadapter->cmd_pending_q, pmadapter->callbacks.moal_spin_lock, pmadapter->callbacks. moal_spin_unlock))) { LEAVE(); return MNULL; } while (pcmd_node != (cmd_ctrl_node *) & pmadapter->cmd_pending_q) { if (pcmd_node->pioctl_buf == pioctl_req) { LEAVE(); return pcmd_node; } pcmd_node = pcmd_node->pnext; } LEAVE(); return MNULL; }
/** * @brief This function will resend addba request to all * the peer in the TxBAStreamTbl * * @param priv A pointer to mlan_private * * @return N/A */ void wlan_11n_update_addba_request(mlan_private * priv) { TxBAStreamTbl *ptx_tbl; ENTER(); if (! (ptx_tbl = (TxBAStreamTbl *) util_peek_list(priv->adapter->pmoal_handle, &priv->tx_ba_stream_tbl_ptr, priv->adapter->callbacks. moal_spin_lock, priv->adapter->callbacks. moal_spin_unlock))) { LEAVE(); return; } while (ptx_tbl != (TxBAStreamTbl *) & priv->tx_ba_stream_tbl_ptr) { wlan_send_addba(priv, ptx_tbl->tid, ptx_tbl->ra); ptx_tbl = ptx_tbl->pnext; } mlan_main_process(priv->adapter); LEAVE(); return; }
/** * @brief This function will return the pointer to a entry in BA Stream * table which matches the ba_status requested * * @param priv A pointer to mlan_private * @param ba_status Current status of the BA stream * * @return A pointer to first entry matching status in BA stream */ TxBAStreamTbl * wlan_11n_get_txbastream_status(mlan_private * priv, baStatus_e ba_status) { TxBAStreamTbl *ptx_tbl; ENTER(); if (! (ptx_tbl = (TxBAStreamTbl *) util_peek_list(priv->adapter->pmoal_handle, &priv->tx_ba_stream_tbl_ptr, priv->adapter->callbacks. moal_spin_lock, priv->adapter->callbacks. moal_spin_unlock))) { LEAVE(); return MNULL; } while (ptx_tbl != (TxBAStreamTbl *) & priv->tx_ba_stream_tbl_ptr) { if (ptx_tbl->ba_status == ba_status) { LEAVE(); return ptx_tbl; } ptx_tbl = ptx_tbl->pnext; } LEAVE(); return MNULL; }
/** * @brief This function gets a free command node if available in * command free queue. * * @param pmadapter A pointer to mlan_adapter structure * * @return cmd_ctrl_node A pointer to cmd_ctrl_node structure or MNULL */ cmd_ctrl_node * wlan_get_cmd_node(mlan_adapter * pmadapter) { cmd_ctrl_node *pcmd_node; ENTER(); if (pmadapter == MNULL) { LEAVE(); return MNULL; } if (util_peek_list(&pmadapter->cmd_free_q, pmadapter->callbacks.moal_spin_lock, pmadapter->callbacks.moal_spin_unlock)) { pcmd_node = (cmd_ctrl_node *) util_dequeue_list(&pmadapter->cmd_free_q, pmadapter->callbacks. moal_spin_lock, pmadapter->callbacks. moal_spin_unlock); } else { PRINTM(MERROR, "GET_CMD_NODE: cmd_ctrl_node is not available\n"); pcmd_node = MNULL; } LEAVE(); return pcmd_node; }
/** * @brief This function checks if the given pointer is valid entry of * Tx BA Stream table * * @param priv Pointer to mlan_private * @param ptxtblptr Pointer to tx ba stream entry * * @return MTRUE or MFALSE */ int wlan_is_txbastreamptr_valid(mlan_private * priv, TxBAStreamTbl * ptxtblptr) { TxBAStreamTbl *ptx_tbl; ENTER(); if (! (ptx_tbl = (TxBAStreamTbl *) util_peek_list(priv->adapter->pmoal_handle, &priv->tx_ba_stream_tbl_ptr, MNULL, MNULL))) { LEAVE(); return MFALSE; } while (ptx_tbl != (TxBAStreamTbl *) & priv->tx_ba_stream_tbl_ptr) { if (ptx_tbl == ptxtblptr) { LEAVE(); return MTRUE; } ptx_tbl = ptx_tbl->pnext; } LEAVE(); return MFALSE; }
/** * @brief This function will return the pointer to a entry in rx reordering * table which matches the give TA/TID pair * * @param priv A pointer to mlan_private * @param ta ta to find in reordering table * @param tid tid to find in reordering table * * @return A pointer to structure RxReorderTbl */ RxReorderTbl * wlan_11n_get_rxreorder_tbl(mlan_private * priv, int tid, t_u8 * ta) { RxReorderTbl *rx_reor_tbl_ptr; ENTER(); if (! (rx_reor_tbl_ptr = (RxReorderTbl *) util_peek_list(&priv->rx_reorder_tbl_ptr, priv->adapter->callbacks. moal_spin_lock, priv->adapter->callbacks. moal_spin_unlock))) { LEAVE(); return MNULL; } while (rx_reor_tbl_ptr != (RxReorderTbl *) & priv->rx_reorder_tbl_ptr) { if ((!memcmp(rx_reor_tbl_ptr->ta, ta, MLAN_MAC_ADDR_LENGTH)) && (rx_reor_tbl_ptr->tid == tid)) { LEAVE(); return rx_reor_tbl_ptr; } rx_reor_tbl_ptr = rx_reor_tbl_ptr->pnext; } LEAVE(); return MNULL; }
/** * @brief Get transmit BA stream table * * @param priv A pointer to mlan_private structure * @param buf A pointer to tx_ba_stream_tbl structure * @return number of ba stream table entry */ int wlan_get_txbastream_tbl(mlan_private * priv, tx_ba_stream_tbl * buf) { TxBAStreamTbl *ptxtbl; tx_ba_stream_tbl *ptbl = buf; int count = 0; ENTER(); if (!(ptxtbl = (TxBAStreamTbl *) util_peek_list(priv->adapter->pmoal_handle, &priv->tx_ba_stream_tbl_ptr, priv->adapter->callbacks. moal_spin_lock, priv->adapter->callbacks. moal_spin_unlock))) { LEAVE(); return count; } while (ptxtbl != (TxBAStreamTbl *) & priv->tx_ba_stream_tbl_ptr) { ptbl->tid = (t_u16) ptxtbl->tid; PRINTM(MINFO, "tid=%d\n", ptbl->tid); memcpy(priv->adapter, ptbl->ra, ptxtbl->ra, MLAN_MAC_ADDR_LENGTH); ptxtbl = ptxtbl->pnext; ptbl++; count++; } LEAVE(); return count; }
/** * @brief This function deletes the BSS priority table * * @param priv A pointer to mlan_private structure * * @return N/A */ static t_void wlan_delete_bsspriotbl(pmlan_private priv) { int i; pmlan_adapter pmadapter = priv->adapter; mlan_bssprio_node *pbssprio_node = MNULL, *ptmp_node = MNULL, **ppcur = MNULL; pmlan_list_head phead; ENTER(); for (i = 0; i < pmadapter->priv_num; ++i) { phead = &pmadapter->bssprio_tbl[i].bssprio_head; ppcur = &pmadapter->bssprio_tbl[i].bssprio_cur; PRINTM(MINFO, "Delete BSS priority table, index = %d, i = %d, phead = %p, pcur = %p\n", priv->bss_index, i, phead, *ppcur); if (*ppcur) { pbssprio_node = (mlan_bssprio_node *) util_peek_list(pmadapter-> pmoal_handle, phead, pmadapter-> callbacks. moal_spin_lock, pmadapter-> callbacks. moal_spin_unlock); while (pbssprio_node && ((pmlan_list_head) pbssprio_node != phead)) { ptmp_node = pbssprio_node->pnext; if (pbssprio_node->priv == priv) { PRINTM(MINFO, "Delete node, pnode = %p, pnext = %p\n", pbssprio_node, ptmp_node); util_unlink_list(pmadapter-> pmoal_handle, phead, (pmlan_linked_list) pbssprio_node, pmadapter->callbacks. moal_spin_lock, pmadapter->callbacks. moal_spin_unlock); pmadapter->callbacks. moal_mfree(pmadapter-> pmoal_handle, (t_u8 *) pbssprio_node); } pbssprio_node = ptmp_node; } *ppcur = (mlan_bssprio_node *) phead; } } LEAVE(); }
/** * @brief Cancel pending ioctl cmd. * * @param pmadapter A pointer to mlan_adapter * @param pioctl_req A pointer to mlan_ioctl_req buf * * @return N/A */ void wlan_cancel_pending_ioctl(pmlan_adapter pmadapter, pmlan_ioctl_req pioctl_req) { pmlan_callbacks pcb = &pmadapter->callbacks; cmd_ctrl_node *pcmd_node = MNULL; ENTER(); PRINTM(MCMND, "MOAL Cancel IOCTL: 0x%x sub_id=0x%x action=%d\n", pioctl_req->req_id, *((t_u32 *) pioctl_req->pbuf), (int) pioctl_req->action); if ((pmadapter->curr_cmd) && (pmadapter->curr_cmd->pioctl_buf == pioctl_req)) { wlan_request_cmd_lock(pmadapter); pcmd_node = pmadapter->curr_cmd; pcmd_node->pioctl_buf = MNULL; wlan_release_cmd_lock(pmadapter); } wlan_request_cmd_lock(pmadapter); while ((pcmd_node = wlan_get_pending_ioctl_cmd(pmadapter, pioctl_req)) != MNULL) { util_unlink_list(&pmadapter->cmd_pending_q, (pmlan_linked_list) pcmd_node, pmadapter->callbacks.moal_spin_lock, pmadapter->callbacks.moal_spin_unlock); pcmd_node->pioctl_buf = MNULL; wlan_insert_cmd_to_free_q(pmadapter, pcmd_node); } wlan_release_cmd_lock(pmadapter); if (pioctl_req->req_id == MLAN_IOCTL_SCAN) { /* Cancel all pending scan command */ while ((pcmd_node = (cmd_ctrl_node *) util_peek_list(&pmadapter->scan_pending_q, pcb->moal_spin_lock, pcb->moal_spin_unlock))) { util_unlink_list(&pmadapter->scan_pending_q, (pmlan_linked_list) pcmd_node, pcb->moal_spin_lock, pcb->moal_spin_unlock); pcmd_node->pioctl_buf = MNULL; wlan_insert_cmd_to_free_q(pmadapter, pcmd_node); } wlan_request_cmd_lock(pmadapter); pmadapter->scan_processing = MFALSE; wlan_release_cmd_lock(pmadapter); } pioctl_req->status_code = MLAN_ERROR_CMD_CANCEL; pcb->moal_ioctl_complete(pmadapter->pmoal_handle, pioctl_req, MLAN_STATUS_FAILURE); LEAVE(); return; }
/** * @brief This function initializes firmware * * @param pmadapter A pointer to mlan_adapter * * @return MLAN_STATUS_SUCCESS, MLAN_STATUS_PENDING or MLAN_STATUS_FAILURE */ mlan_status wlan_init_fw(IN pmlan_adapter pmadapter) { mlan_status ret = MLAN_STATUS_SUCCESS; pmlan_private priv = MNULL; t_u8 i = 0; ENTER(); /* Initialize adapter structure */ wlan_init_adapter(pmadapter); for (i = 0; i < pmadapter->priv_num; i++) { if (pmadapter->priv[i]) { priv = pmadapter->priv[i]; /* Initialize private structure */ ret = wlan_init_priv(priv); if (ret) { ret = MLAN_STATUS_FAILURE; goto done; } } } #ifdef MFG_CMD_SUPPORT if (pmadapter->mfg_mode != MTRUE) { #endif /* Issue firmware initialize commands for first BSS, for other interfaces it will be called after getting the last init command response of previous interface */ priv = wlan_get_priv(pmadapter, MLAN_BSS_ROLE_ANY); ret = priv->ops.init_cmd(priv, MTRUE); if (ret == MLAN_STATUS_FAILURE) goto done; #ifdef MFG_CMD_SUPPORT } #endif if (util_peek_list(pmadapter->pmoal_handle, &pmadapter->cmd_pending_q, pmadapter->callbacks.moal_spin_lock, pmadapter->callbacks.moal_spin_unlock)) { /* Send the first command in queue and return */ if (mlan_main_process(pmadapter) == MLAN_STATUS_FAILURE) ret = MLAN_STATUS_FAILURE; else ret = MLAN_STATUS_PENDING; } else { pmadapter->hw_status = WlanHardwareStatusReady; } done: LEAVE(); return ret; }
/** * @brief Check if packets are available in Bypass TX queue * * @param pmadapter Pointer to the mlan_adapter driver data struct * * @return MFALSE if not empty; MTRUE if empty */ INLINE t_u8 wlan_bypass_tx_list_empty(mlan_adapter * pmadapter) { t_u8 q_empty = MTRUE; pmlan_callbacks pcb = &pmadapter->callbacks; ENTER(); q_empty = (util_peek_list(pmadapter->pmoal_handle, &pmadapter->bypass_txq, pcb->moal_spin_lock, pcb->moal_spin_unlock)) ? MFALSE : MTRUE; LEAVE(); return q_empty; }
/** * @brief This function cleans up reorder tbl * * @param priv A pointer to mlan_private * * @return N/A */ void wlan_11n_cleanup_reorder_tbl(mlan_private * priv) { RxReorderTbl *del_tbl_ptr; ENTER(); while ((del_tbl_ptr = (RxReorderTbl *) util_peek_list(&priv->rx_reorder_tbl_ptr, priv->adapter->callbacks.moal_spin_lock, priv->adapter->callbacks.moal_spin_unlock))) { wlan_11n_delete_rxreorder_tbl_entry(priv, del_tbl_ptr); } util_init_list((pmlan_linked_list) & priv->rx_reorder_tbl_ptr); LEAVE(); }
/** * @brief Clean up the By-pass TX queue * * @param priv Pointer to the mlan_private data struct * * @return N/A */ t_void wlan_cleanup_bypass_txq(mlan_private * priv) { pmlan_buffer pmbuf; mlan_adapter *pmadapter = priv->adapter; ENTER(); pmadapter->callbacks.moal_spin_lock(pmadapter->pmoal_handle, priv->wmm.ra_list_spinlock); while ((pmbuf = (pmlan_buffer) util_peek_list(pmadapter->pmoal_handle, &priv->bypass_txq, MNULL, MNULL))) { util_unlink_list(pmadapter->pmoal_handle, &priv->bypass_txq, (pmlan_linked_list) pmbuf, MNULL, MNULL); wlan_write_data_complete(pmadapter, pmbuf, MLAN_STATUS_FAILURE); pmadapter->bypass_pkt_count--; } pmadapter->callbacks.moal_spin_unlock(pmadapter->pmoal_handle, priv->wmm.ra_list_spinlock); LEAVE(); }
/** * @brief Get Rx reordering table * * @param priv A pointer to mlan_private structure * @param buf A pointer to rx_reorder_tbl structure * @return number of rx reorder table entry */ int wlan_get_rxreorder_tbl(mlan_private * priv, rx_reorder_tbl * buf) { int i; rx_reorder_tbl *ptbl = buf; RxReorderTbl *rxReorderTblPtr; int count = 0; ENTER(); if (! (rxReorderTblPtr = (RxReorderTbl *) util_peek_list(priv->adapter->pmoal_handle, &priv->rx_reorder_tbl_ptr, priv->adapter->callbacks. moal_spin_lock, priv->adapter->callbacks. moal_spin_unlock))) { LEAVE(); return count; } while (rxReorderTblPtr != (RxReorderTbl *) & priv->rx_reorder_tbl_ptr) { ptbl->tid = (t_u16) rxReorderTblPtr->tid; memcpy(priv->adapter, ptbl->ta, rxReorderTblPtr->ta, MLAN_MAC_ADDR_LENGTH); ptbl->start_win = rxReorderTblPtr->start_win; ptbl->win_size = rxReorderTblPtr->win_size; for (i = 0; i < rxReorderTblPtr->win_size; ++i) { if (rxReorderTblPtr->rx_reorder_ptr[i]) ptbl->buffer[i] = MTRUE; else ptbl->buffer[i] = MFALSE; } rxReorderTblPtr = rxReorderTblPtr->pnext; ptbl++; count++; if (count >= MLAN_MAX_RX_BASTREAM_SUPPORTED) break; } LEAVE(); return count; }
/** * @brief This function send the tdls teardown request event. * * @param priv A pointer to mlan_private * * @return N/A */ void wlan_send_tdls_tear_down_request(pmlan_private priv) { t_u8 event_buf[100]; mlan_event *ptdls_event = (mlan_event *)event_buf; tdls_tear_down_event *tdls_evt = (tdls_tear_down_event *)ptdls_event->event_buf; sta_node *sta_ptr = MNULL; ENTER(); sta_ptr = (sta_node *)util_peek_list(priv->adapter->pmoal_handle, &priv->sta_list, priv->adapter->callbacks. moal_spin_lock, priv->adapter->callbacks. moal_spin_unlock); if (!sta_ptr) { LEAVE(); return; } while (sta_ptr != (sta_node *)&priv->sta_list) { if (sta_ptr->external_tdls) { ptdls_event->bss_index = priv->bss_index; ptdls_event->event_id = MLAN_EVENT_ID_DRV_TDLS_TEARDOWN_REQ; ptdls_event->event_len = sizeof(tdls_tear_down_event); memcpy(priv->adapter, (t_u8 *)tdls_evt->peer_mac_addr, sta_ptr->mac_addr, MLAN_MAC_ADDR_LENGTH); tdls_evt->reason_code = MLAN_REASON_TDLS_TEARDOWN_UNSPECIFIED; wlan_recv_event(priv, MLAN_EVENT_ID_DRV_TDLS_TEARDOWN_REQ, ptdls_event); } sta_ptr = sta_ptr->pnext; } LEAVE(); return; }
/** * @brief This function deletes the BSS priority table * * @param priv A pointer to mlan_private structure * * @return N/A */ t_void wlan_delete_bsspriotbl(pmlan_private priv) { int i; pmlan_adapter pmadapter = priv->adapter; mlan_bssprio_node *pbssprio_node, *ptmp_node; pmlan_list_head phead; ENTER(); for (i = 0; i < MLAN_MAX_BSS_NUM; ++i) { phead = &pmadapter->bssprio_tbl[i].bssprio_head; if (phead) { pbssprio_node = (mlan_bssprio_node *) util_peek_list(pmadapter->pmoal_handle, phead, pmadapter->callbacks. moal_spin_lock, pmadapter->callbacks. moal_spin_unlock); while (pbssprio_node && ((pmlan_list_head) pbssprio_node != phead)) { ptmp_node = pbssprio_node->pnext; if (pbssprio_node->priv == priv) { util_unlink_list(pmadapter->pmoal_handle, phead, (pmlan_linked_list) pbssprio_node, pmadapter->callbacks.moal_spin_lock, pmadapter->callbacks.moal_spin_unlock); pmadapter->callbacks.moal_mfree(pmadapter->pmoal_handle, (t_u8 *) pbssprio_node); } pbssprio_node = ptmp_node; } } } LEAVE(); }
/** * @brief Clean up the By-pass TX queue * * @param pmadapter Pointer to the mlan_adapter driver data struct * * @return N/A */ t_void wlan_cleanup_bypass_txq(mlan_adapter * pmadapter) { pmlan_buffer pmbuf; ENTER(); pmadapter->callbacks.moal_spin_lock(pmadapter->pmoal_handle, pmadapter->bypass_txq.plock); while ((pmbuf = (pmlan_buffer) util_peek_list(pmadapter->pmoal_handle, &pmadapter->bypass_txq, MNULL, MNULL)) != 0) { util_unlink_list(pmadapter->pmoal_handle, &pmadapter->bypass_txq, (pmlan_linked_list) pmbuf, MNULL, MNULL); wlan_write_data_complete(pmadapter, pmbuf, MLAN_STATUS_FAILURE); } pmadapter->callbacks.moal_spin_unlock(pmadapter->pmoal_handle, pmadapter->bypass_txq.plock); LEAVE(); }
/** * @brief Check if packets are available in Bypass TX queue * * @param pmadapter Pointer to the mlan_adapter driver data struct * * @return MFALSE if not empty; MTRUE if empty */ INLINE t_u8 wlan_bypass_tx_list_empty(mlan_adapter * pmadapter) { t_u8 q_empty = MTRUE; pmlan_callbacks pcb = &pmadapter->callbacks; pmlan_private pmpriv = MNULL; ENTER(); if (!(pmpriv = wlan_get_priv(pmadapter, MLAN_BSS_ROLE_STA))) { goto end; } if (pmpriv->port_ctrl_mode == MTRUE) { q_empty = (util_peek_list (pmadapter->pmoal_handle, &pmadapter->bypass_txq, pcb->moal_spin_lock, pcb->moal_spin_unlock)) ? MFALSE : MTRUE; } end: LEAVE(); return q_empty; }
/** * @brief This function will delete all the entries in Tx BA Stream table * * @param priv A pointer to mlan_private * * @return N/A */ void wlan_11n_deleteall_txbastream_tbl(mlan_private * priv) { int i; TxBAStreamTbl *del_tbl_ptr = MNULL; ENTER(); while ((del_tbl_ptr = (TxBAStreamTbl *) util_peek_list(priv->adapter->pmoal_handle, &priv->tx_ba_stream_tbl_ptr, priv->adapter->callbacks.moal_spin_lock, priv->adapter->callbacks.moal_spin_unlock))) { wlan_11n_delete_txbastream_tbl_entry(priv, del_tbl_ptr); } util_init_list((pmlan_linked_list) & priv->tx_ba_stream_tbl_ptr); for (i = 0; i < MAX_NUM_TID; ++i) { priv->aggr_prio_tbl[i].ampdu_ap = priv->aggr_prio_tbl[i].ampdu_user; } LEAVE(); }
/** * @brief This function will return the pointer to a entry in BA Stream * table which matches the give RA/TID pair * * @param priv A pointer to mlan_private * @param tid TID to find in reordering table * @param ra RA to find in reordering table * * @return A pointer to first entry matching RA/TID in BA stream */ TxBAStreamTbl * wlan_11n_get_txbastream_tbl(mlan_private * priv, int tid, t_u8 * ra) { TxBAStreamTbl *ptx_tbl; pmlan_adapter pmadapter = priv->adapter; ENTER(); if (!(ptx_tbl = (TxBAStreamTbl *) util_peek_list(pmadapter->pmoal_handle, &priv-> tx_ba_stream_tbl_ptr, pmadapter->callbacks. moal_spin_lock, pmadapter->callbacks. moal_spin_unlock))) { LEAVE(); return MNULL; } while (ptx_tbl != (TxBAStreamTbl *) & priv->tx_ba_stream_tbl_ptr) { PRINTM(MDAT_D, "get_txbastream_tbl TID %d\n", ptx_tbl->tid); DBG_HEXDUMP(MDAT_D, "RA", ptx_tbl->ra, MLAN_MAC_ADDR_LENGTH); if ((!memcmp(pmadapter, ptx_tbl->ra, ra, MLAN_MAC_ADDR_LENGTH)) && (ptx_tbl->tid == tid)) { LEAVE(); return ptx_tbl; } ptx_tbl = ptx_tbl->pnext; } LEAVE(); return MNULL; }
/** * @brief The main process * * @param pmlan_adapter A pointer to mlan_adapter structure * * @return MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE */ mlan_status mlan_main_process(IN t_void * pmlan_adapter) { mlan_status ret = MLAN_STATUS_SUCCESS; mlan_adapter *pmadapter = (mlan_adapter *) pmlan_adapter; pmlan_callbacks pcb; ENTER(); MASSERT(pmlan_adapter); pcb = &pmadapter->callbacks; pcb->moal_spin_lock(pmadapter->pmoal_handle, pmadapter->pmain_proc_lock); /* Check if already processing */ if (pmadapter->mlan_processing) { pmadapter->more_task_flag = MTRUE; pcb->moal_spin_unlock(pmadapter->pmoal_handle, pmadapter->pmain_proc_lock); goto exit_main_proc; } else { pmadapter->mlan_processing = MTRUE; pcb->moal_spin_unlock(pmadapter->pmoal_handle, pmadapter->pmain_proc_lock); } process_start: do { pcb->moal_spin_lock(pmadapter->pmoal_handle, pmadapter->pmain_proc_lock); pmadapter->more_task_flag = MFALSE; pcb->moal_spin_unlock(pmadapter->pmoal_handle, pmadapter->pmain_proc_lock); /* Is MLAN shutting down or not ready? */ if ((pmadapter->hw_status == WlanHardwareStatusClosing) || (pmadapter->hw_status == WlanHardwareStatusNotReady)) break; if (util_scalar_read (pmadapter->pmoal_handle, &pmadapter->rx_pkts_queued, pmadapter->callbacks.moal_spin_lock, pmadapter->callbacks.moal_spin_unlock) > HIGH_RX_PENDING) { PRINTM(MEVENT, "Pause\n"); pmadapter->delay_task_flag = MTRUE; break; } /* Handle pending SDIO interrupts if any */ if (pmadapter->sdio_ireg) { if (pmadapter->hs_activated == MTRUE) wlan_process_hs_config(pmadapter); wlan_process_int_status(pmadapter); if (pmadapter->data_received && pmadapter->rx_work_flag) wlan_recv_event(wlan_get_priv (pmadapter, MLAN_BSS_ROLE_ANY), MLAN_EVENT_ID_DRV_DEFER_RX_WORK, MNULL); } /* Need to wake up the card ? */ if ((pmadapter->ps_state == PS_STATE_SLEEP) && (pmadapter->pm_wakeup_card_req && !pmadapter->pm_wakeup_fw_try) && (util_peek_list (pmadapter->pmoal_handle, &pmadapter->cmd_pending_q, pcb->moal_spin_lock, pcb->moal_spin_unlock) || !wlan_bypass_tx_list_empty(pmadapter) || !wlan_wmm_lists_empty(pmadapter) )) { wlan_pm_wakeup_card(pmadapter); pmadapter->pm_wakeup_fw_try = MTRUE; continue; } if (IS_CARD_RX_RCVD(pmadapter)) { pmadapter->data_received = MFALSE; if (pmadapter->hs_activated == MTRUE) { pmadapter->is_hs_configured = MFALSE; wlan_host_sleep_activated_event(wlan_get_priv (pmadapter, MLAN_BSS_ROLE_ANY), MFALSE); } pmadapter->pm_wakeup_fw_try = MFALSE; if (pmadapter->ps_state == PS_STATE_SLEEP) pmadapter->ps_state = PS_STATE_AWAKE; } else { /* We have tried to wakeup the card already */ if (pmadapter->pm_wakeup_fw_try) break; if (pmadapter->ps_state != PS_STATE_AWAKE || (pmadapter->tx_lock_flag == MTRUE)) break; if (pmadapter->scan_processing || pmadapter->data_sent || (wlan_bypass_tx_list_empty(pmadapter) && wlan_wmm_lists_empty(pmadapter)) || wlan_11h_radar_detected_tx_blocked(pmadapter) ) { if (pmadapter->cmd_sent || pmadapter->curr_cmd || (!util_peek_list (pmadapter->pmoal_handle, &pmadapter->cmd_pending_q, pcb->moal_spin_lock, pcb->moal_spin_unlock))) { break; } } } /* Check for Cmd Resp */ if (pmadapter->cmd_resp_received) { pmadapter->cmd_resp_received = MFALSE; wlan_process_cmdresp(pmadapter); /* call moal back when init_fw is done */ if (pmadapter->hw_status == WlanHardwareStatusInitdone) { pmadapter->hw_status = WlanHardwareStatusReady; wlan_init_fw_complete(pmadapter); } } /* Check for event */ if (pmadapter->event_received) { pmadapter->event_received = MFALSE; wlan_process_event(pmadapter); } /* Check if we need to confirm Sleep Request received previously */ if (pmadapter->ps_state == PS_STATE_PRE_SLEEP) { if (!pmadapter->cmd_sent && !pmadapter->curr_cmd) { wlan_check_ps_cond(pmadapter); } } /* * The ps_state may have been changed during processing of * Sleep Request event. */ if ((pmadapter->ps_state == PS_STATE_SLEEP) || (pmadapter->ps_state == PS_STATE_PRE_SLEEP) || (pmadapter->ps_state == PS_STATE_SLEEP_CFM) || (pmadapter->tx_lock_flag == MTRUE) ) continue; if (!pmadapter->cmd_sent && !pmadapter->curr_cmd) { if (wlan_exec_next_cmd(pmadapter) == MLAN_STATUS_FAILURE) { ret = MLAN_STATUS_FAILURE; break; } } if (!pmadapter->scan_processing && !pmadapter->data_sent && !wlan_11h_radar_detected_tx_blocked(pmadapter) && !wlan_bypass_tx_list_empty(pmadapter)) { PRINTM(MINFO, "mlan_send_pkt(): deq(bybass_txq)\n"); wlan_process_bypass_tx(pmadapter); if (pmadapter->hs_activated == MTRUE) { pmadapter->is_hs_configured = MFALSE; wlan_host_sleep_activated_event(wlan_get_priv (pmadapter, MLAN_BSS_ROLE_ANY), MFALSE); } } if (!pmadapter->scan_processing && !pmadapter->data_sent && !wlan_wmm_lists_empty(pmadapter) && !wlan_11h_radar_detected_tx_blocked(pmadapter) ) { wlan_wmm_process_tx(pmadapter); if (pmadapter->hs_activated == MTRUE) { pmadapter->is_hs_configured = MFALSE; wlan_host_sleep_activated_event(wlan_get_priv (pmadapter, MLAN_BSS_ROLE_ANY), MFALSE); } } #ifdef STA_SUPPORT if (pmadapter->delay_null_pkt && !pmadapter->cmd_sent && !pmadapter->curr_cmd && !IS_COMMAND_PENDING(pmadapter) && wlan_bypass_tx_list_empty(pmadapter) && wlan_wmm_lists_empty(pmadapter)) { if (wlan_send_null_packet (wlan_get_priv(pmadapter, MLAN_BSS_ROLE_STA), MRVDRV_TxPD_POWER_MGMT_NULL_PACKET | MRVDRV_TxPD_POWER_MGMT_LAST_PACKET) == MLAN_STATUS_SUCCESS) { pmadapter->delay_null_pkt = MFALSE; } break; } #endif } while (MTRUE); pcb->moal_spin_lock(pmadapter->pmoal_handle, pmadapter->pmain_proc_lock); if (pmadapter->more_task_flag == MTRUE) { pcb->moal_spin_unlock(pmadapter->pmoal_handle, pmadapter->pmain_proc_lock); goto process_start; } pmadapter->mlan_processing = MFALSE; pcb->moal_spin_unlock(pmadapter->pmoal_handle, pmadapter->pmain_proc_lock); exit_main_proc: if (pmadapter->hw_status == WlanHardwareStatusClosing) mlan_shutdown_fw(pmadapter); LEAVE(); return ret; }
/** * @brief Aggregate multiple packets into one single AMSDU packet * * @param priv A pointer to mlan_private structure * @param pra_list Pointer to the RA List table containing the pointers * to packets. * @param headroom Any interface specific headroom that may be need. TxPD * will be formed leaving this headroom. * @param ptrindex Pointer index * * @return Final packet size or MLAN_STATUS_FAILURE */ int wlan_11n_aggregate_pkt(mlan_private * priv, raListTbl * pra_list, int headroom, int ptrindex) { int pkt_size = 0; pmlan_adapter pmadapter = priv->adapter; mlan_buffer *pmbuf_aggr, *pmbuf_src; t_u8 *data; int pad = 0; mlan_status ret = MLAN_STATUS_SUCCESS; #ifdef DEBUG_LEVEL1 t_u32 sec = 0, usec = 0; #endif mlan_tx_param tx_param; #ifdef STA_SUPPORT TxPD *ptx_pd = MNULL; #endif t_u32 max_amsdu_size = MIN(pra_list->max_amsdu, pmadapter->tx_buf_size); ENTER(); PRINTM(MDAT_D, "Handling Aggr packet\n"); pmbuf_src = (pmlan_buffer) util_peek_list(pmadapter->pmoal_handle, &pra_list->buf_head, MNULL, MNULL); if (pmbuf_src) { pmbuf_aggr = wlan_alloc_mlan_buffer(pmadapter, pmadapter->tx_buf_size, 0, MOAL_MALLOC_BUFFER); if (!pmbuf_aggr) { PRINTM(MERROR, "Error allocating mlan_buffer\n"); pmadapter->callbacks.moal_spin_unlock(pmadapter-> pmoal_handle, priv->wmm. ra_list_spinlock); LEAVE(); return MLAN_STATUS_FAILURE; } data = pmbuf_aggr->pbuf + headroom; pmbuf_aggr->bss_index = pmbuf_src->bss_index; pmbuf_aggr->buf_type = pmbuf_src->buf_type; pmbuf_aggr->priority = pmbuf_src->priority; pmbuf_aggr->pbuf = data; pmbuf_aggr->data_offset = 0; pmbuf_aggr->in_ts_sec = pmbuf_src->in_ts_sec; pmbuf_aggr->in_ts_usec = pmbuf_src->in_ts_usec; if (pmbuf_src->flags & MLAN_BUF_FLAG_TDLS) pmbuf_aggr->flags |= MLAN_BUF_FLAG_TDLS; /* Form AMSDU */ wlan_11n_form_amsdu_txpd(priv, pmbuf_aggr); pkt_size = sizeof(TxPD); #ifdef STA_SUPPORT if (GET_BSS_ROLE(priv) == MLAN_BSS_ROLE_STA) ptx_pd = (TxPD *) pmbuf_aggr->pbuf; #endif } else { pmadapter->callbacks.moal_spin_unlock(pmadapter->pmoal_handle, priv->wmm. ra_list_spinlock); goto exit; } while (pmbuf_src && ((pkt_size + (pmbuf_src->data_len + LLC_SNAP_LEN) + headroom) <= max_amsdu_size)) { pmbuf_src = (pmlan_buffer) util_dequeue_list(pmadapter->pmoal_handle, &pra_list->buf_head, MNULL, MNULL); pra_list->total_pkts--; /* decrement for every PDU taken from the list */ priv->wmm.pkts_queued[ptrindex]--; util_scalar_decrement(pmadapter->pmoal_handle, &priv->wmm.tx_pkts_queued, MNULL, MNULL); pmadapter->callbacks.moal_spin_unlock(pmadapter->pmoal_handle, priv->wmm. ra_list_spinlock); if (pmbuf_src->flags & MLAN_BUF_FLAG_TCP_ACK) pmadapter->callbacks.moal_tcp_ack_tx_ind(pmadapter-> pmoal_handle, pmbuf_src); pkt_size += wlan_11n_form_amsdu_pkt(pmadapter, (data + pkt_size), pmbuf_src->pbuf + pmbuf_src->data_offset, pmbuf_src->data_len, &pad); DBG_HEXDUMP(MDAT_D, "pmbuf_src", pmbuf_src, sizeof(mlan_buffer)); wlan_write_data_complete(pmadapter, pmbuf_src, MLAN_STATUS_SUCCESS); pmadapter->callbacks.moal_spin_lock(pmadapter->pmoal_handle, priv->wmm.ra_list_spinlock); if (!wlan_is_ralist_valid(priv, pra_list, ptrindex)) { pmadapter->callbacks.moal_spin_unlock(pmadapter-> pmoal_handle, priv->wmm. ra_list_spinlock); LEAVE(); return MLAN_STATUS_FAILURE; } pmbuf_src = (pmlan_buffer) util_peek_list(pmadapter->pmoal_handle, &pra_list->buf_head, MNULL, MNULL); } pmadapter->callbacks.moal_spin_unlock(pmadapter->pmoal_handle, priv->wmm.ra_list_spinlock); /* Last AMSDU packet does not need padding */ pkt_size -= pad; pmbuf_aggr->data_len = pkt_size; wlan_11n_update_pktlen_amsdu_txpd(priv, pmbuf_aggr); pmbuf_aggr->data_len += headroom; pmbuf_aggr->pbuf = data - headroom; tx_param.next_pkt_len = ((pmbuf_src) ? pmbuf_src->data_len + sizeof(TxPD) : 0); ret = wlan_sdio_host_to_card(pmadapter, MLAN_TYPE_DATA, pmbuf_aggr, &tx_param); switch (ret) { case MLAN_STATUS_RESOURCE: pmadapter->callbacks.moal_spin_lock(pmadapter->pmoal_handle, priv->wmm.ra_list_spinlock); if (!wlan_is_ralist_valid(priv, pra_list, ptrindex)) { pmadapter->callbacks.moal_spin_unlock(pmadapter-> pmoal_handle, priv->wmm. ra_list_spinlock); pmbuf_aggr->status_code = MLAN_ERROR_PKT_INVALID; wlan_write_data_complete(pmadapter, pmbuf_aggr, MLAN_STATUS_FAILURE); LEAVE(); return MLAN_STATUS_FAILURE; } #ifdef STA_SUPPORT /* reset tx_lock_flag */ if ((GET_BSS_ROLE(priv) == MLAN_BSS_ROLE_STA) && pmadapter->pps_uapsd_mode && (pmadapter->tx_lock_flag == MTRUE)) { pmadapter->tx_lock_flag = MFALSE; ptx_pd->flags = 0; } #endif util_enqueue_list_head(pmadapter->pmoal_handle, &pra_list->buf_head, (pmlan_linked_list) pmbuf_aggr, MNULL, MNULL); pra_list->total_pkts++; /* add back only one: aggregated packet is requeued as one */ priv->wmm.pkts_queued[ptrindex]++; util_scalar_increment(pmadapter->pmoal_handle, &priv->wmm.tx_pkts_queued, MNULL, MNULL); pmbuf_aggr->flags |= MLAN_BUF_FLAG_REQUEUED_PKT; pmadapter->callbacks.moal_spin_unlock(pmadapter->pmoal_handle, priv->wmm. ra_list_spinlock); PRINTM(MINFO, "MLAN_STATUS_RESOURCE is returned\n"); pmbuf_aggr->status_code = MLAN_ERROR_PKT_INVALID; break; case MLAN_STATUS_FAILURE: pmadapter->data_sent = MFALSE; PRINTM(MERROR, "Error: host_to_card failed: 0x%X\n", ret); pmbuf_aggr->status_code = MLAN_ERROR_DATA_TX_FAIL; pmadapter->dbg.num_tx_host_to_card_failure++; wlan_write_data_complete(pmadapter, pmbuf_aggr, ret); goto exit; case MLAN_STATUS_PENDING: break; case MLAN_STATUS_SUCCESS: wlan_write_data_complete(pmadapter, pmbuf_aggr, ret); break; default: break; } if (ret != MLAN_STATUS_RESOURCE) { pmadapter->callbacks.moal_spin_lock(pmadapter->pmoal_handle, priv->wmm.ra_list_spinlock); if (wlan_is_ralist_valid(priv, pra_list, ptrindex)) { priv->wmm.packets_out[ptrindex]++; priv->wmm.tid_tbl_ptr[ptrindex].ra_list_curr = pra_list; } pmadapter->bssprio_tbl[priv->bss_priority].bssprio_cur = pmadapter->bssprio_tbl[priv->bss_priority].bssprio_cur-> pnext; pmadapter->callbacks.moal_spin_unlock(pmadapter->pmoal_handle, priv->wmm. ra_list_spinlock); } PRINTM_GET_SYS_TIME(MDATA, &sec, &usec); PRINTM_NETINTF(MDATA, priv); PRINTM(MDATA, "%lu.%06lu : Data => FW\n", sec, usec); exit: LEAVE(); return pkt_size + headroom; }
/** * @brief This function initializes firmware * * @param pmadapter A pointer to mlan_adapter * * @return MLAN_STATUS_SUCCESS or error code */ mlan_status wlan_init_fw(IN pmlan_adapter pmadapter) { mlan_status ret = MLAN_STATUS_SUCCESS; pmlan_private priv = MNULL; t_s32 i = 0; t_u8 first_sta = MTRUE; ENTER(); /* Allocate memory for member of adapter structure */ ret = wlan_allocate_adapter(pmadapter); if (ret) { ret = MLAN_STATUS_FAILURE; goto done; } /* Initialize adapter structure */ wlan_init_adapter(pmadapter); for (i = 0; i < MLAN_MAX_BSS_NUM; i++) { if (pmadapter->priv[i]) { priv = pmadapter->priv[i]; /* Initialize private structure */ wlan_init_priv(priv); if ((ret = wlan_add_bsspriotbl(pmadapter, i))) { ret = MLAN_STATUS_FAILURE; goto done; } } } #ifdef MFG_CMD_SUPPORT if (pmadapter->mfg_mode != MTRUE) { #endif for (i = 0; i < MLAN_MAX_BSS_NUM; i++) { if (pmadapter->priv[i]) { ret = pmadapter->priv[i]->ops.init_cmd(pmadapter->priv[i], first_sta); if (ret == MLAN_STATUS_FAILURE) goto done; first_sta = MFALSE; } } #ifdef MFG_CMD_SUPPORT } #endif if (util_peek_list(&pmadapter->cmd_pending_q, pmadapter->callbacks.moal_spin_lock, pmadapter->callbacks.moal_spin_unlock)) { /* Send the first command in queue and return */ if (mlan_main_process(pmadapter) == MLAN_STATUS_FAILURE) ret = MLAN_STATUS_FAILURE; else ret = MLAN_STATUS_PENDING; } else { pmadapter->hw_status = WlanHardwareStatusReady; } done: LEAVE(); return ret; }
/** * @brief This function executes next command in command * pending queue. It will put firmware back to PS mode * if applicable. * * @param pmadapter A pointer to mlan_adapter structure * * @return MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE */ mlan_status wlan_exec_next_cmd(mlan_adapter * pmadapter) { mlan_private *priv = MNULL; cmd_ctrl_node *pcmd_node = MNULL; mlan_status ret = MLAN_STATUS_SUCCESS; HostCmd_DS_COMMAND *pcmd; ENTER(); /* Sanity test */ if (pmadapter == MNULL) { PRINTM(MERROR, "EXEC_NEXT_CMD: pmadapter is MNULL\n"); ret = MLAN_STATUS_FAILURE; goto done; } /* Check if already in processing */ if (pmadapter->curr_cmd) { PRINTM(MERROR, "EXEC_NEXT_CMD: there is command in processing!\n"); ret = MLAN_STATUS_FAILURE; goto done; } wlan_request_cmd_lock(pmadapter); /* Check if any command is pending */ pcmd_node = (cmd_ctrl_node *) util_peek_list(&pmadapter->cmd_pending_q, pmadapter->callbacks. moal_spin_lock, pmadapter->callbacks. moal_spin_unlock); if (pcmd_node) { pcmd = (HostCmd_DS_COMMAND *) (pcmd_node->cmdbuf->pbuf + pcmd_node->cmdbuf->data_offset); priv = pcmd_node->priv; if (pmadapter->ps_state != PS_STATE_AWAKE) { PRINTM(MERROR, "Cannot send command in sleep state, this should not happen\n"); wlan_release_cmd_lock(pmadapter); goto done; } util_unlink_list(&pmadapter->cmd_pending_q, (pmlan_linked_list) pcmd_node, pmadapter->callbacks.moal_spin_lock, pmadapter->callbacks.moal_spin_unlock); wlan_release_cmd_lock(pmadapter); ret = wlan_dnld_cmd_to_fw(priv, pcmd_node); priv = wlan_get_priv(pmadapter, MLAN_BSS_TYPE_STA); /* Any command sent to the firmware when host is in sleep mode, should de-configure host sleep */ /* We should skip the host sleep configuration command itself though */ if (priv && (pcmd->command != wlan_cpu_to_le16(HostCmd_CMD_802_11_HS_CFG_ENH))) { if (pmadapter->hs_activated == MTRUE) { pmadapter->is_hs_configured = MFALSE; wlan_host_sleep_activated_event(priv, MFALSE); } } goto done; } else { wlan_release_cmd_lock(pmadapter); } ret = MLAN_STATUS_SUCCESS; done: LEAVE(); return ret; }