/** * @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; }
/** * @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; }
/** * @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; }
/** * @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; }
/** * @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; }