/**
 *  @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;
}
Exemplo n.º 3
0
/**
 *  @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;
}
Exemplo n.º 4
0
/**
 *  @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;
}
Exemplo n.º 6
0
/**
 *  @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;
}
Exemplo n.º 8
0
/** 
 *  @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;
}
Exemplo n.º 12
0
/**
 *  @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();
}
Exemplo n.º 14
0
/**
 *  @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();
}
Exemplo n.º 15
0
/** 
 *  @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;
}
Exemplo n.º 17
0
/**
 *  @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();
}
Exemplo n.º 18
0
/**
 *  @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();
}
Exemplo n.º 19
0
/**
 *  @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;
}
Exemplo n.º 20
0
/**
 *  @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();
}
Exemplo n.º 21
0
/**
 *  @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;
}
Exemplo n.º 22
0
/**
 *  @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;
}
Exemplo n.º 23
0
/**
 *  @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;
}
Exemplo n.º 24
0
/**
 *  @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;
}