/** * @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 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 timeout of command sending. * It will re-send the same command again. * * @param function_context A pointer to function_context * @return n/a */ t_void wlan_cmd_timeout_func(t_void * function_context) { mlan_adapter *pmadapter = (mlan_adapter *) function_context; cmd_ctrl_node *pcmd_node = MNULL; mlan_ioctl_req *pioctl_buf = MNULL; t_u32 sec, usec; t_u8 i; ENTER(); pmadapter->cmd_timer_is_set = MFALSE; pmadapter->num_cmd_timeout++; pmadapter->dbg.num_cmd_timeout++; if (!pmadapter->curr_cmd) { PRINTM(MWARN, "CurCmd Empty\n"); goto exit; } pcmd_node = pmadapter->curr_cmd; if (pcmd_node->pioctl_buf != MNULL) { pioctl_buf = (mlan_ioctl_req *) pcmd_node->pioctl_buf; pioctl_buf->status_code = MLAN_ERROR_CMD_TIMEOUT; } if (pcmd_node) { pmadapter->dbg.timeout_cmd_id = pmadapter->dbg.last_cmd_id[pmadapter->dbg.last_cmd_index]; pmadapter->dbg.timeout_cmd_act = pmadapter->dbg.last_cmd_act[pmadapter->dbg.last_cmd_index]; pmadapter->callbacks.moal_get_system_time(&sec, &usec); PRINTM(MERROR, "Timeout cmd id (%lu.%lu) = 0x%x, act = 0x%x \n", sec, usec, pmadapter->dbg.timeout_cmd_id, pmadapter->dbg.timeout_cmd_act); PRINTM(MERROR, "num_data_h2c_failure = %d\n", pmadapter->dbg.num_tx_host_to_card_failure); PRINTM(MERROR, "num_cmd_h2c_failure = %d\n", pmadapter->dbg.num_cmd_host_to_card_failure); PRINTM(MERROR, "num_cmd_timeout = %d\n", pmadapter->dbg.num_cmd_timeout); PRINTM(MERROR, "num_tx_timeout = %d\n", pmadapter->dbg.num_tx_timeout); PRINTM(MERROR, "last_cmd_index = %d\n", pmadapter->dbg.last_cmd_index); PRINTM(MERROR, "last_cmd_id = "); for (i = 0; i < DBG_CMD_NUM; i++) { PRINTM(MERROR, "0x%x ", pmadapter->dbg.last_cmd_id[i]); } PRINTM(MMSG, "\n"); PRINTM(MERROR, "last_cmd_act = "); for (i = 0; i < DBG_CMD_NUM; i++) { PRINTM(MERROR, "0x%x ", pmadapter->dbg.last_cmd_act[i]); } PRINTM(MMSG, "\n"); PRINTM(MERROR, "last_cmd_resp_index = %d\n", pmadapter->dbg.last_cmd_resp_index); PRINTM(MERROR, "last_cmd_resp_id = "); for (i = 0; i < DBG_CMD_NUM; i++) { PRINTM(MERROR, "0x%x ", pmadapter->dbg.last_cmd_resp_id[i]); } PRINTM(MMSG, "\n"); PRINTM(MERROR, "last_event_index = %d\n", pmadapter->dbg.last_event_index); PRINTM(MERROR, "last_event = "); for (i = 0; i < DBG_CMD_NUM; i++) { PRINTM(MERROR, "0x%x ", pmadapter->dbg.last_event[i]); } PRINTM(MMSG, "\n"); PRINTM(MERROR, "data_sent=%d cmd_sent=%d\n", pmadapter->data_sent, pmadapter->cmd_sent); PRINTM(MERROR, "ps_mode=%d ps_state=%d\n", pmadapter->ps_mode, pmadapter->ps_state); } if (pmadapter->hw_status == WlanHardwareStatusInitializing) wlan_init_fw_complete(pmadapter); exit: LEAVE(); return; }