Пример #1
0
/**
 *   @brief This function processes the received buffer
 *     
 *   @param pmadapter A pointer to mlan_adapter
 *   @param pmbuf     A pointer to the received buffer
 *
 *   @return        MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
 */
mlan_status
wlan_handle_rx_packet(pmlan_adapter pmadapter, pmlan_buffer pmbuf)
{
    mlan_status ret = MLAN_STATUS_SUCCESS;
    pmlan_private priv = wlan_get_priv(pmadapter, MLAN_BSS_ROLE_ANY);
    RxPD *prx_pd;
#ifdef DEBUG_LEVEL1
    t_u32 sec, usec;
#endif

    ENTER();

    prx_pd = (RxPD *) (pmbuf->pbuf + pmbuf->data_offset);
    /* Get the BSS number from RxPD, get corresponding priv */
    priv =
        wlan_get_priv_by_id(pmadapter, prx_pd->bss_num & BSS_NUM_MASK,
                            prx_pd->bss_type);
    if (!priv)
        priv = wlan_get_priv(pmadapter, MLAN_BSS_ROLE_ANY);
    pmbuf->bss_index = priv->bss_index;
    PRINTM_GET_SYS_TIME(MDATA, &sec, &usec);
    PRINTM_NETINTF(MDATA, priv);
    PRINTM(MDATA, "%lu.%06lu : Data <= FW\n", sec, usec);
    ret = priv->ops.process_rx_packet(pmadapter, pmbuf);

    LEAVE();
    return ret;
}
/** 
 *  @brief This function handles events generated by firmware
 *  
 *  @param pmadapter		A pointer to mlan_adapter structure
 *
 *  @return		MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
 */
mlan_status
wlan_process_event(pmlan_adapter pmadapter)
{
    mlan_status ret = MLAN_STATUS_SUCCESS;
    pmlan_private priv = wlan_get_priv(pmadapter, MLAN_BSS_TYPE_ANY);
    pmlan_buffer pmbuf = pmadapter->pmlan_buffer_event;
    t_u32 eventcause = pmadapter->event_cause;
    t_u32 bss_num = 0;
    t_u32 in_ts_sec;
    t_u32 in_ts_usec;
    ENTER();

    /* Save the last event to debug log */
    pmadapter->dbg.last_event_index =
        (pmadapter->dbg.last_event_index + 1) % DBG_CMD_NUM;
    pmadapter->dbg.last_event[pmadapter->dbg.last_event_index] = eventcause;

    /* Get BSS number and corresponding priv */
    bss_num = EVENT_GET_BSS_NUM((t_u16) eventcause);
    priv = pmadapter->priv[bss_num];
    if (!priv) {
        bss_num = 0;
        priv = wlan_get_priv(pmadapter, MLAN_BSS_TYPE_ANY);
    }
    /* Clear BSS_NO_BITS from event */
    eventcause &= EVENT_ID_MASK;
    if (pmbuf)
        pmbuf->bss_num = bss_num;

    if (eventcause != EVENT_PS_SLEEP && eventcause != EVENT_PS_AWAKE) {
        pmadapter->callbacks.moal_get_system_time(&in_ts_sec, &in_ts_usec);
        PRINTM(MEVENT, "%lu.%lu : Event: 0x%x\n", in_ts_sec, in_ts_usec,
               eventcause);
    }

    ret = priv->ops.process_event(priv);

    pmadapter->event_cause = 0;
    pmadapter->pmlan_buffer_event = MNULL;

    if (pmbuf) {
        pmadapter->callbacks.moal_recv_complete(pmadapter->pmoal_handle, pmbuf,
                                                0, MLAN_STATUS_SUCCESS);
    }

    LEAVE();
    return ret;
}
/**
 *  @brief The main process
 *
 *  @param pmlan_adapter	A pointer to mlan_adapter structure
 *
 *  @return			MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
 */
mlan_status
mlan_rx_process(IN t_void * pmlan_adapter)
{
    mlan_status ret = MLAN_STATUS_SUCCESS;
    mlan_adapter *pmadapter = (mlan_adapter *) pmlan_adapter;
    pmlan_callbacks pcb;
    pmlan_buffer pmbuf;

    ENTER();

    MASSERT(pmlan_adapter);
    pcb = &pmadapter->callbacks;
    pcb->moal_spin_lock(pmadapter->pmoal_handle, pmadapter->prx_proc_lock);
    if (pmadapter->mlan_rx_processing || pmadapter->rx_lock_flag) {
        pcb->moal_spin_unlock(pmadapter->pmoal_handle,
                              pmadapter->prx_proc_lock);
        goto exit_rx_proc;
    } else {
        pmadapter->mlan_rx_processing = MTRUE;
        pcb->moal_spin_unlock(pmadapter->pmoal_handle,
                              pmadapter->prx_proc_lock);
    }
    /* Check for Rx data */
    while ((pmbuf =
                (pmlan_buffer) util_dequeue_list(pmadapter->pmoal_handle,
                        &pmadapter->rx_data_queue,
                        pmadapter->callbacks.
                        moal_spin_lock,
                        pmadapter->callbacks.
                        moal_spin_unlock))) {
        util_scalar_decrement(pmadapter->pmoal_handle,
                              &pmadapter->rx_pkts_queued,
                              pmadapter->callbacks.moal_spin_lock,
                              pmadapter->callbacks.moal_spin_unlock);
        if (pmadapter->delay_task_flag &&
                (util_scalar_read
                 (pmadapter->pmoal_handle, &pmadapter->rx_pkts_queued,
                  pmadapter->callbacks.moal_spin_lock,
                  pmadapter->callbacks.moal_spin_unlock) <
                 LOW_RX_PENDING)) {
            PRINTM(MEVENT, "Run\n");
            pmadapter->delay_task_flag = MFALSE;
            wlan_recv_event(wlan_get_priv
                            (pmadapter, MLAN_BSS_ROLE_ANY),
                            MLAN_EVENT_ID_DRV_DEFER_HANDLING,
                            MNULL);
        }
        wlan_handle_rx_packet(pmadapter, pmbuf);
    }
    pcb->moal_spin_lock(pmadapter->pmoal_handle, pmadapter->prx_proc_lock);
    pmadapter->mlan_rx_processing = MFALSE;
    pcb->moal_spin_unlock(pmadapter->pmoal_handle,
                          pmadapter->prx_proc_lock);
exit_rx_proc:
    LEAVE();
    return ret;
}
/**
 *  @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 Perform hs related activities on receving the power up interrupt
 *  
 *  @param pmadapter  A pointer to the adapter structure
 *  @return           N/A
 */
t_void
wlan_process_hs_config(pmlan_adapter pmadapter)
{
    PRINTM(MINFO,
           "Auto Cancelling host sleep since there is some interrupt from the firmware\n");
    wlan_pm_wakeup_card(pmadapter);
    pmadapter->hs_activated = MFALSE;
    pmadapter->is_hs_configured = MFALSE;
    wlan_host_sleep_activated_event(wlan_get_priv(pmadapter, MLAN_BSS_TYPE_STA),
                                    MFALSE);
    return;
}
Пример #6
0
/**
 *   @brief This function processes the received buffer
 *     
 *   @param pmadapter A pointer to mlan_adapter
 *   @param pmbuf     A pointer to the received buffer
 *
 *   @return        MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
 */
mlan_status
wlan_handle_rx_packet(pmlan_adapter pmadapter, pmlan_buffer pmbuf)
{
    mlan_status ret = MLAN_STATUS_SUCCESS;
    pmlan_private priv = wlan_get_priv(pmadapter, MLAN_BSS_ROLE_ANY);
    RxPD *prx_pd;

    ENTER();

    prx_pd = (RxPD *) (pmbuf->pbuf + pmbuf->data_offset);
    /* Get the BSS number from RxPD, get corresponding priv */
    priv =
        wlan_get_priv_by_id(pmadapter, prx_pd->bss_num & (MLAN_MAX_BSS_NUM - 1),
                            prx_pd->bss_type);
    if (!priv)
        priv = wlan_get_priv(pmadapter, MLAN_BSS_ROLE_ANY);
    pmbuf->bss_num = priv->bss_index;
    ret = priv->ops.process_rx_packet(pmadapter, pmbuf);

    LEAVE();
    return ret;
}
Пример #7
0
/**
 *  @brief This function Checks if channel txpwr is learned from AP/IBSS
 *
 *  @param pmadapter            A pointer to mlan_adapter structure
 *  @param band                 Band number
 *  @param chan                 Channel number
 *  @param parsed_region_chan   Pointer to parsed_region_chan_11d_t
 *
 *  @return                     MTRUE or MFALSE
 */
static t_u8
wlan_11d_channel_known(pmlan_adapter pmadapter,
		       t_u8 band,
		       t_u8 chan, parsed_region_chan_11d_t * parsed_region_chan)
{
	chan_power_11d_t *pchan_pwr = parsed_region_chan->chan_pwr;
	t_u8 no_of_chan = parsed_region_chan->no_of_chan;
	t_u8 i = 0;
	t_u8 ret = MFALSE;
	mlan_private *pmpriv;

	ENTER();

	HEXDUMP("11D: parsed_region_chan", (t_u8 *) pchan_pwr,
		sizeof(chan_power_11d_t) * no_of_chan);

	/* Search channel */
	for (i = 0; i < no_of_chan; i++) {
		if (chan == pchan_pwr[i].chan && band == pchan_pwr[i].band) {
			PRINTM(MINFO, "11D: Found channel:%d (band:%d)\n", chan,
			       band);
			ret = MTRUE;

			if (band & BAND_A) {
				/* If chan is a DFS channel, we need to see an
				   AP on it */
				pmpriv = wlan_get_priv(pmadapter,
						       MLAN_BSS_ROLE_STA);
				if (pmpriv &&
				    wlan_11h_radar_detect_required(pmpriv,
								   chan)) {
					PRINTM(MINFO,
					       "11H: DFS channel %d, and ap_seen=%d\n",
					       chan, pchan_pwr[i].ap_seen);
					ret = pchan_pwr[i].ap_seen;
				}
			}

			LEAVE();
			return ret;
		}
	}

	PRINTM(MINFO, "11D: Could not find channel:%d (band:%d)\n", chan, band);
	LEAVE();
	return ret;
}
Пример #8
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;
}
/**
 *  @brief This function initializes the adapter structure
 *  		and sets default values to the members of adapter.
 *  
 *  @param pmadapter	A pointer to mlan_adapter structure
 *
 *  @return		N/A
 */
t_void
wlan_init_adapter(pmlan_adapter pmadapter)
{
    int i;
    opt_sleep_confirm_buffer *sleep_cfm_buf =
        (opt_sleep_confirm_buffer *) (pmadapter->psleep_cfm->pbuf +
                                      pmadapter->psleep_cfm->data_offset);

    ENTER();

    pmadapter->cmd_sent = MFALSE;
    pmadapter->data_sent = MTRUE;
    pmadapter->mp_rd_bitmap = 0;
    pmadapter->mp_wr_bitmap = 0;
    pmadapter->curr_rd_port = 1;
    pmadapter->curr_wr_port = 1;
    for (i = 0; i < MAX_NUM_TID; i++) {
        pmadapter->tx_eligibility[i] = 1;
    }

#ifdef SDIO_MULTI_PORT_TX_AGGR
    pmadapter->mpa_tx.buf_len = 0;
    pmadapter->mpa_tx.pkt_cnt = 0;
    pmadapter->mpa_tx.start_port = 0;

    pmadapter->mpa_tx.enabled = 1;
    pmadapter->mpa_tx.pkt_aggr_limit = SDIO_MP_AGGR_DEF_PKT_LIMIT;
#endif /* SDIO_MULTI_PORT_TX_AGGR */

#ifdef SDIO_MULTI_PORT_RX_AGGR
    pmadapter->mpa_rx.buf_len = 0;
    pmadapter->mpa_rx.pkt_cnt = 0;
    pmadapter->mpa_rx.start_port = 0;

    pmadapter->mpa_rx.enabled = 1;
    pmadapter->mpa_rx.pkt_aggr_limit = SDIO_MP_AGGR_DEF_PKT_LIMIT;
#endif /* SDIO_MULTI_PORT_RX_AGGR */

    pmadapter->cmd_resp_received = MFALSE;
    pmadapter->event_received = MFALSE;
    pmadapter->data_received = MFALSE;

    pmadapter->cmd_timer_is_set = MFALSE;

    /* PnP and power profile */
    pmadapter->surprise_removed = MFALSE;

    /* Status variables */
    pmadapter->hw_status = WlanHardwareStatusInitializing;

    pmadapter->ps_mode = Wlan802_11PowerModeCAM;
    pmadapter->ps_state = PS_STATE_AWAKE;
    pmadapter->need_to_wakeup = MFALSE;

    /* Scan type */
    pmadapter->scan_type = HostCmd_SCAN_TYPE_ACTIVE;
    /* Scan mode */
    pmadapter->scan_mode = HostCmd_BSS_MODE_ANY;
    /* Scan time */
    pmadapter->specific_scan_time = MRVDRV_SPECIFIC_SCAN_CHAN_TIME;
    pmadapter->active_scan_time = MRVDRV_ACTIVE_SCAN_CHAN_TIME;
    pmadapter->passive_scan_time = MRVDRV_PASSIVE_SCAN_CHAN_TIME;

    pmadapter->num_in_scan_table = 0;
    memset(pmadapter->pscan_table, 0,
           (sizeof(BSSDescriptor_t) * MRVDRV_MAX_BSSID_LIST));
    pmadapter->scan_probes = 0;

    memset(pmadapter->bcn_buf, 0, sizeof(pmadapter->bcn_buf));
    pmadapter->pbcn_buf_end = pmadapter->bcn_buf;

    pmadapter->radio_on = RADIO_ON;
    pmadapter->multiple_dtim = MRVDRV_DEFAULT_MULTIPLE_DTIM;

    pmadapter->local_listen_interval = 0;       /* default value in firmware
                                                   will be used */
    pmadapter->fw_wakeup_method = WAKEUP_FW_UNCHANGED;

    pmadapter->is_deep_sleep = MFALSE;

    pmadapter->delay_null_pkt = MFALSE;
    pmadapter->delay_to_ps = 100;

    pmadapter->pm_wakeup_card_req = MFALSE;

    pmadapter->pm_wakeup_fw_try = MFALSE;

    pmadapter->max_tx_buf_size = MLAN_TX_DATA_BUF_SIZE_2K;
    pmadapter->tx_buf_size = MLAN_TX_DATA_BUF_SIZE_2K;

    pmadapter->is_hs_configured = MFALSE;
    pmadapter->hs_cfg.params.hs_config.conditions = HOST_SLEEP_CFG_CANCEL;
    pmadapter->hs_cfg.params.hs_config.gpio = 0;
    pmadapter->hs_cfg.params.hs_config.gap = 0;
    pmadapter->hs_activated = MFALSE;

    memset(pmadapter->event_body, 0, sizeof(pmadapter->event_body));
    pmadapter->hw_dot_11n_dev_cap = 0;
    pmadapter->hw_dev_mcs_support = 0;
    pmadapter->usr_dot_11n_dev_cap = 0;
    pmadapter->usr_dev_mcs_support = 0;
    pmadapter->chan_offset = 0;

    /* Initialize 802.11d */
    wlan_11d_init(pmadapter);

    wlan_wmm_init(pmadapter);

    pmadapter->psleep_cfm->buf_type = MLAN_BUF_TYPE_CMD;

    if ((wlan_get_priv(pmadapter, MLAN_BSS_TYPE_ANY))->bss_type ==
        MLAN_BSS_TYPE_STA) {
        pmadapter->psleep_cfm->data_len = sizeof(HostCmd_DS_COMMAND);
        memset(&sleep_cfm_buf->ps_cfm_sleep, 0, sizeof(HostCmd_DS_COMMAND));
        sleep_cfm_buf->ps_cfm_sleep.command =
            wlan_cpu_to_le16(HostCmd_CMD_802_11_PS_MODE_ENH);
        sleep_cfm_buf->ps_cfm_sleep.size =
            wlan_cpu_to_le16(sizeof(HostCmd_DS_COMMAND));
        sleep_cfm_buf->ps_cfm_sleep.result = 0;
        sleep_cfm_buf->ps_cfm_sleep.params.psmode_enh.action =
            wlan_cpu_to_le16(SLEEP_CONFIRM);
    }

    memset(&pmadapter->sleep_params, 0, sizeof(pmadapter->sleep_params));
    memset(&pmadapter->sleep_period, 0, sizeof(pmadapter->sleep_period));
    pmadapter->tx_lock_flag = MFALSE;
    pmadapter->null_pkt_interval = 0;
    pmadapter->fw_bands = 0;
    pmadapter->config_bands = 0;
    pmadapter->adhoc_start_band = 0;
    pmadapter->pscan_channels = MNULL;
    pmadapter->fw_release_number = 0;
    pmadapter->fw_cap_info = 0;
    memset(&pmadapter->upld_buf, 0, sizeof(pmadapter->upld_buf));
    pmadapter->upld_len = 0;
    pmadapter->event_cause = 0;
    memset(&pmadapter->region_channel, 0, sizeof(pmadapter->region_channel));
    pmadapter->region_code = 0;
    pmadapter->bcn_miss_time_out = DEFAULT_BCN_MISS_TIMEOUT;
    memset(&pmadapter->arp_filter, 0, sizeof(pmadapter->arp_filter));
    pmadapter->arp_filter_size = 0;

    LEAVE();
    return;
}
Пример #10
0
/** 
 *  @brief This function allocates buffer for the members of adapter
 *  		structure like command buffer and BSSID list.
 *  
 *  @param pmadapter A pointer to mlan_adapter structure
 *
 *  @return        MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
 */
static mlan_status
wlan_allocate_adapter(pmlan_adapter pmadapter)
{
    int i;
    mlan_status ret = MLAN_STATUS_SUCCESS;
    t_u32 buf_size;
    BSSDescriptor_t *ptemp_scan_table;
    t_u8 *head_ptr = MNULL;

    ENTER();

    /* Allocate buffer to store the BSSID list */
    buf_size = sizeof(BSSDescriptor_t) * MRVDRV_MAX_BSSID_LIST;
    ret =
        pmadapter->callbacks.moal_malloc(buf_size,
                                         (t_u8 **) & ptemp_scan_table);
    if (ret != MLAN_STATUS_SUCCESS || !ptemp_scan_table) {
        PRINTM(MERROR, "Failed to allocate scan table\n");
        LEAVE();
        return MLAN_STATUS_FAILURE;
    }
    pmadapter->pscan_table = ptemp_scan_table;

    /* Initialize cmd_free_q */
    util_init_list_head(&pmadapter->cmd_free_q, MTRUE,
                        pmadapter->callbacks.moal_init_lock);
    /* Initialize cmd_pending_q */
    util_init_list_head(&pmadapter->cmd_pending_q, MTRUE,
                        pmadapter->callbacks.moal_init_lock);
    /* Initialize scan_pending_q */
    util_init_list_head(&pmadapter->scan_pending_q, MTRUE,
                        pmadapter->callbacks.moal_init_lock);

    /* Allocate command buffer */
    ret = wlan_alloc_cmd_buffer(pmadapter);
    if (ret != MLAN_STATUS_SUCCESS) {
        PRINTM(MERROR, "Failed to allocate command buffer\n");
        LEAVE();
        return MLAN_STATUS_FAILURE;
    }

    for (i = 0; i < MLAN_MAX_BSS_NUM; ++i) {
        util_init_list_head(&pmadapter->bssprio_tbl[i].bssprio_head,
                            MTRUE, pmadapter->callbacks.moal_init_lock);

        pmadapter->bssprio_tbl[i].bssprio_cur = MNULL;
    }
    ret =
        pmadapter->callbacks.moal_malloc(MAX_MP_REGS + HEADER_ALIGNMENT,
                                         (t_u8 **) & pmadapter->mp_regs_buf);
    if (ret != MLAN_STATUS_SUCCESS || !pmadapter->mp_regs_buf) {
        PRINTM(MERROR, "Failed to allocate mp_regs_buf\n");
        LEAVE();
        return MLAN_STATUS_FAILURE;
    }
    pmadapter->mp_regs =
        (t_u8 *) ALIGN_ADDR(pmadapter->mp_regs_buf, HEADER_ALIGNMENT);

    PRINTM(MINFO, "Try to assign mp_regs to handle\n");
    ret =
        pmadapter->callbacks.moal_get_cardregs(pmadapter->pmoal_handle,
                                         pmadapter->mp_regs);
    if (ret != MLAN_STATUS_SUCCESS) {
        PRINTM(MERROR, "Failed to assign mp_regs to handle\n");
        LEAVE();
        return MLAN_STATUS_FAILURE;
    }

#if defined(SDIO_MULTI_PORT_TX_AGGR) || defined(SDIO_MULTI_PORT_RX_AGGR)
    ret = wlan_alloc_sdio_mpa_buffers(pmadapter, SDIO_MP_TX_AGGR_DEF_BUF_SIZE,
                                      SDIO_MP_RX_AGGR_DEF_BUF_SIZE);
    if (ret != MLAN_STATUS_SUCCESS) {
        PRINTM(MERROR, "Failed to allocate sdio mp-a buffers\n");
        LEAVE();
        return MLAN_STATUS_FAILURE;
    }
#endif
    if ((wlan_get_priv(pmadapter, MLAN_BSS_TYPE_ANY))->bss_type ==
        MLAN_BSS_TYPE_STA)
        pmadapter->psleep_cfm =
            wlan_alloc_mlan_buffer(&pmadapter->callbacks,
                                   HEADER_ALIGNMENT +
                                   sizeof(opt_sleep_confirm_buffer));

    if (!pmadapter->psleep_cfm) {
        PRINTM(MERROR, "Failed to allocate sleep confirm buffers\n");
        LEAVE();
        return MLAN_STATUS_FAILURE;
    }
    head_ptr =
        (t_u8 *) ALIGN_ADDR(pmadapter->psleep_cfm->pbuf +
                            pmadapter->psleep_cfm->data_offset,
                            HEADER_ALIGNMENT);
    pmadapter->psleep_cfm->data_offset +=
        head_ptr - (pmadapter->psleep_cfm->pbuf +
                    pmadapter->psleep_cfm->data_offset);

    LEAVE();
    return MLAN_STATUS_SUCCESS;
}
/**
 *  @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 This function handles the command response
 *  
 *  @param pmadapter    A pointer to mlan_adapter structure
 *
 *  @return             MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
 */
mlan_status
wlan_process_cmdresp(mlan_adapter * pmadapter)
{
    HostCmd_DS_COMMAND *resp = MNULL;
    mlan_private *pmpriv = wlan_get_priv(pmadapter, MLAN_BSS_TYPE_ANY);
    mlan_status ret = MLAN_STATUS_SUCCESS;
    t_u16 orig_cmdresp_no;
    t_u16 cmdresp_no;
    t_u16 cmdresp_result;
    mlan_ioctl_req *pioctl_buf = MNULL;
    mlan_callbacks *pcb = (mlan_callbacks *) & pmadapter->callbacks;
    t_u32 sec, usec;

    ENTER();

    /* Now we got response from FW, cancel the command timer */
    if (pmadapter->cmd_timer_is_set) {
        /* Cancel command timeout timer */
        pcb->moal_stop_timer(pmadapter->pmlan_cmd_timer);
        /* Cancel command timeout timer */
        pmadapter->cmd_timer_is_set = MFALSE;
    }

    if (!pmadapter->curr_cmd || !pmadapter->curr_cmd->respbuf) {
        resp = (HostCmd_DS_COMMAND *) pmadapter->upld_buf;
        resp->command = wlan_le16_to_cpu(resp->command);
        PRINTM(MERROR, "CMD_RESP: MNULL curr_cmd, 0x%x\n", resp->command);
        ret = MLAN_STATUS_FAILURE;
        goto done;
    }

    if (pmadapter->curr_cmd->pioctl_buf != MNULL) {
        pioctl_buf = (mlan_ioctl_req *) pmadapter->curr_cmd->pioctl_buf;
    }

    pmadapter->num_cmd_timeout = 0;

    DBG_HEXDUMP(MCMD_D, "CMD_RESP",
                pmadapter->curr_cmd->respbuf->pbuf +
                pmadapter->curr_cmd->respbuf->data_offset, pmadapter->upld_len);

    resp =
        (HostCmd_DS_COMMAND *) (pmadapter->curr_cmd->respbuf->pbuf +
                                pmadapter->curr_cmd->respbuf->data_offset);
    if (pmadapter->curr_cmd->cmd_flag & CMD_F_HOSTCMD) {
        /* Copy original response back to response buffer */
        wlan_ret_host_cmd(pmpriv, resp, pioctl_buf);
    }
    resp->command = wlan_le16_to_cpu(resp->command);
    resp->size = wlan_le16_to_cpu(resp->size);
    resp->seq_num = wlan_le16_to_cpu(resp->seq_num);
    resp->result = wlan_le16_to_cpu(resp->result);

    orig_cmdresp_no = resp->command;
    cmdresp_result = resp->result;

    /* Save the last command response to debug log */
    pmadapter->dbg.last_cmd_resp_index =
        (pmadapter->dbg.last_cmd_resp_index + 1) % DBG_CMD_NUM;
    pmadapter->dbg.last_cmd_resp_id[pmadapter->dbg.last_cmd_resp_index] =
        orig_cmdresp_no;

    pmadapter->callbacks.moal_get_system_time(&sec, &usec);
    PRINTM(MCMND, "CMD_RESP (%lu.%lu): 0x%x, result %d, len %d, seqno %d\n",
           sec, usec, orig_cmdresp_no, cmdresp_result, resp->size,
           resp->seq_num);

    if (!(orig_cmdresp_no & HostCmd_RET_BIT)) {
        PRINTM(MERROR, "CMD_RESP: Invalid response to command!");
        if (pioctl_buf) {
            pioctl_buf->status_code = MLAN_ERROR_FW_CMDRESP;
        }
        wlan_insert_cmd_to_free_q(pmadapter, pmadapter->curr_cmd);
        wlan_request_cmd_lock(pmadapter);
        pmadapter->curr_cmd = MNULL;
        wlan_release_cmd_lock(pmadapter);
        ret = MLAN_STATUS_FAILURE;
        goto done;
    }

    /* Get BSS number and corresponding priv */
    pmpriv = pmadapter->priv[HostCmd_GET_BSS_NO(resp->command)];
    if (!pmpriv)
        pmpriv = wlan_get_priv(pmadapter, MLAN_BSS_TYPE_ANY);
    /* Clear RET_BIT & BSS_NO_BITS from HostCmd */
    resp->command &= HostCmd_CMD_ID_MASK;
    cmdresp_no = resp->command;

    if (pmadapter->curr_cmd->cmd_flag & CMD_F_HOSTCMD) {
        pmadapter->curr_cmd->cmd_flag &= ~CMD_F_HOSTCMD;
        if ((cmdresp_result == HostCmd_RESULT_OK)
            && (cmdresp_no == HostCmd_CMD_802_11_HS_CFG_ENH))
            ret = wlan_ret_802_11_hs_cfg(pmpriv, resp, pioctl_buf);
    } else {
        /* handle response */
        ret = pmpriv->ops.process_cmdresp(pmpriv, cmdresp_no, resp, pioctl_buf);
    }

    if ((pmadapter->hw_status == WlanHardwareStatusInitializing) &&
        (pmadapter->last_init_cmd == cmdresp_no)) {
        if (cmdresp_result == HostCmd_RESULT_OK)
            pmadapter->hw_status = WlanHardwareStatusInitdone;
        else
            wlan_init_fw_complete(pmadapter);
    }

    if (pmadapter->curr_cmd) {
        if (pioctl_buf && (ret == MLAN_STATUS_SUCCESS))
            pioctl_buf->status_code = MLAN_ERROR_NO_ERROR;

        /* Clean up and put current command back to cmd_free_q */
        wlan_insert_cmd_to_free_q(pmadapter, pmadapter->curr_cmd);

        wlan_request_cmd_lock(pmadapter);
        pmadapter->curr_cmd = MNULL;
        wlan_release_cmd_lock(pmadapter);
    }

  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;
}
/**
 *  @brief This function sends sleep confirm command to firmware.
 * 
 *  @param pmadapter  A pointer to mlan_adapter structure
 *
 *  @return        MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
 */
mlan_status
wlan_dnld_sleep_confirm_cmd(mlan_adapter * pmadapter)
{
    mlan_status ret = MLAN_STATUS_SUCCESS;
    static t_u32 i = 0;
    t_u16 cmd_len = 0;
    HostCmd_DS_802_11_PS_MODE_ENH *pps_mode = MNULL;
    opt_sleep_confirm_buffer *sleep_cfm_buf =
        (opt_sleep_confirm_buffer *) (pmadapter->psleep_cfm->pbuf +
                                      pmadapter->psleep_cfm->data_offset);

    ENTER();

    if ((wlan_get_priv(pmadapter, MLAN_BSS_TYPE_ANY))->bss_type ==
        MLAN_BSS_TYPE_STA) {
        cmd_len = sizeof(HostCmd_DS_COMMAND);
        pps_mode = &sleep_cfm_buf->ps_cfm_sleep.params.psmode_enh;
        sleep_cfm_buf->ps_cfm_sleep.seq_num =
            wlan_cpu_to_le16(++pmadapter->seq_num);
        pps_mode->params.sleep_cfm.resp_ctrl = wlan_cpu_to_le16(RESP_NEEDED);
        DBG_HEXDUMP(MCMD_D, "SLEEP_CFM", &sleep_cfm_buf->ps_cfm_sleep, cmd_len);
    }

    /* Send sleep confirm command to firmware */
    pmadapter->psleep_cfm->data_len = cmd_len + INTF_HEADER_LEN;
    ret = wlan_sdio_host_to_card(pmadapter, MLAN_TYPE_CMD,
                                 pmadapter->psleep_cfm, MNULL);
    if (ret == MLAN_STATUS_FAILURE) {
        PRINTM(MERROR, "SLEEP_CFM: failed\n");
        pmadapter->dbg.num_cmd_sleep_cfm_host_to_card_failure++;
        goto done;
    } else {
        if ((wlan_get_priv(pmadapter, MLAN_BSS_TYPE_ANY))->bss_type ==
            MLAN_BSS_TYPE_STA) {
            if (!pps_mode->params.sleep_cfm.resp_ctrl) {
                /* Response is not needed for sleep confirm command */
                pmadapter->ps_state = PS_STATE_SLEEP;
            } else {
                pmadapter->ps_state = PS_STATE_SLEEP_CFM;
            }

            if (pps_mode->params.sleep_cfm.resp_ctrl != RESP_NEEDED
                && (pmadapter->is_hs_configured &&
                    !pmadapter->sleep_period.period)) {
                pmadapter->pm_wakeup_card_req = MTRUE;
                wlan_host_sleep_activated_event(wlan_get_priv
                                                (pmadapter, MLAN_BSS_TYPE_STA),
                                                MTRUE);
            }
        }
#define NUM_SC_PER_LINE         16
        if (++i % NUM_SC_PER_LINE == 0)
            PRINTM(MEVENT, "+\n");
        else
            PRINTM(MEVENT, "+");
    }

  done:
    LEAVE();
    return ret;
}