diff options
Diffstat (limited to 'drivers/net/wireless/mwifiex/cmdevt.c')
-rw-r--r-- | drivers/net/wireless/mwifiex/cmdevt.c | 194 |
1 files changed, 75 insertions, 119 deletions
diff --git a/drivers/net/wireless/mwifiex/cmdevt.c b/drivers/net/wireless/mwifiex/cmdevt.c index a9aeb31..776146a 100644 --- a/drivers/net/wireless/mwifiex/cmdevt.c +++ b/drivers/net/wireless/mwifiex/cmdevt.c @@ -36,11 +36,12 @@ static void mwifiex_init_cmd_node(struct mwifiex_private *priv, struct cmd_ctrl_node *cmd_node, - u32 cmd_oid, void *wait_queue, void *data_buf) + u32 cmd_oid, void *data_buf) { cmd_node->priv = priv; cmd_node->cmd_oid = cmd_oid; - cmd_node->wq_buf = wait_queue; + cmd_node->wait_q_enabled = priv->adapter->cmd_wait_q_required; + priv->adapter->cmd_wait_q_required = false; cmd_node->data_buf = data_buf; cmd_node->cmd_skb = cmd_node->skb; } @@ -86,39 +87,13 @@ mwifiex_clean_cmd_node(struct mwifiex_adapter *adapter, { cmd_node->cmd_oid = 0; cmd_node->cmd_flag = 0; - cmd_node->wq_buf = NULL; cmd_node->data_buf = NULL; + cmd_node->wait_q_enabled = false; if (cmd_node->resp_skb) { mwifiex_recv_complete(adapter, cmd_node->resp_skb, 0); cmd_node->resp_skb = NULL; } - - return; -} - -/* - * This function returns a command node from the pending queue which - * matches the given IOCTL request. - */ -static struct cmd_ctrl_node * -mwifiex_get_pending_ioctl_cmd(struct mwifiex_adapter *adapter, - struct mwifiex_wait_queue *wait_queue) -{ - unsigned long flags; - struct cmd_ctrl_node *cmd_node; - - spin_lock_irqsave(&adapter->cmd_pending_q_lock, flags); - list_for_each_entry(cmd_node, &adapter->cmd_pending_q, list) { - if (cmd_node->wq_buf == wait_queue) { - spin_unlock_irqrestore(&adapter->cmd_pending_q_lock, - flags); - return cmd_node; - } - } - spin_unlock_irqrestore(&adapter->cmd_pending_q_lock, flags); - - return NULL; } /* @@ -155,7 +130,6 @@ static int mwifiex_dnld_cmd_to_fw(struct mwifiex_private *priv, struct mwifiex_adapter *adapter = priv->adapter; int ret = 0; struct host_cmd_ds_command *host_cmd; - struct mwifiex_wait_queue *wait_queue = NULL; uint16_t cmd_code; uint16_t cmd_size; struct timeval tstamp; @@ -165,15 +139,13 @@ static int mwifiex_dnld_cmd_to_fw(struct mwifiex_private *priv, return -1; host_cmd = (struct host_cmd_ds_command *) (cmd_node->cmd_skb->data); - if (cmd_node->wq_buf) - wait_queue = (struct mwifiex_wait_queue *) cmd_node->wq_buf; /* Sanity test */ if (host_cmd == NULL || host_cmd->size == 0) { dev_err(adapter->dev, "DNLD_CMD: host_cmd is null" " or cmd size is 0, not sending\n"); - if (wait_queue) - wait_queue->status = MWIFIEX_ERROR_CMD_DNLD_FAIL; + if (cmd_node->wait_q_enabled) + adapter->cmd_wait_q.status = -1; mwifiex_insert_cmd_to_free_q(adapter, cmd_node); return -1; } @@ -206,10 +178,12 @@ static int mwifiex_dnld_cmd_to_fw(struct mwifiex_private *priv, cmd_node->cmd_skb->data, cmd_node->cmd_skb->len, NULL); + skb_pull(cmd_node->cmd_skb, INTF_HEADER_LEN); + if (ret == -1) { dev_err(adapter->dev, "DNLD_CMD: host to card failed\n"); - if (wait_queue) - wait_queue->status = MWIFIEX_ERROR_CMD_DNLD_FAIL; + if (cmd_node->wait_q_enabled) + adapter->cmd_wait_q.status = -1; mwifiex_insert_cmd_to_free_q(adapter, adapter->curr_cmd); spin_lock_irqsave(&adapter->mwifiex_cmd_lock, flags); @@ -435,7 +409,31 @@ int mwifiex_process_event(struct mwifiex_adapter *adapter) } /* - * This function prepares a command before sending it to the firmware. + * This function is used to send synchronous command to the firmware. + * + * it allocates a wait queue for the command and wait for the command + * response. + */ +int mwifiex_send_cmd_sync(struct mwifiex_private *priv, uint16_t cmd_no, + u16 cmd_action, u32 cmd_oid, void *data_buf) +{ + int ret = 0; + struct mwifiex_adapter *adapter = priv->adapter; + + adapter->cmd_wait_q_required = true; + adapter->cmd_wait_q.condition = false; + + ret = mwifiex_send_cmd_async(priv, cmd_no, cmd_action, cmd_oid, + data_buf); + if (!ret) + ret = mwifiex_wait_queue_complete(adapter); + + return ret; +} + + +/* + * This function prepares a command and asynchronously send it to the firmware. * * Preparation includes - * - Sanity tests to make sure the card is still present or the FW @@ -445,9 +443,8 @@ int mwifiex_process_event(struct mwifiex_adapter *adapter) * - Fill up the non-default parameters and buffer pointers * - Add the command to pending queue */ -int mwifiex_prepare_cmd(struct mwifiex_private *priv, uint16_t cmd_no, - u16 cmd_action, u32 cmd_oid, - void *wait_queue, void *data_buf) +int mwifiex_send_cmd_async(struct mwifiex_private *priv, uint16_t cmd_no, + u16 cmd_action, u32 cmd_oid, void *data_buf) { int ret = 0; struct mwifiex_adapter *adapter = priv->adapter; @@ -485,7 +482,7 @@ int mwifiex_prepare_cmd(struct mwifiex_private *priv, uint16_t cmd_no, } /* Initialize the command node */ - mwifiex_init_cmd_node(priv, cmd_node, cmd_oid, wait_queue, data_buf); + mwifiex_init_cmd_node(priv, cmd_node, cmd_oid, data_buf); if (!cmd_node->cmd_skb) { dev_err(adapter->dev, "PREP_CMD: no free cmd buf\n"); @@ -535,18 +532,13 @@ void mwifiex_insert_cmd_to_free_q(struct mwifiex_adapter *adapter, struct cmd_ctrl_node *cmd_node) { - struct mwifiex_wait_queue *wait_queue = NULL; unsigned long flags; - if (cmd_node == NULL) + if (!cmd_node) return; - if (cmd_node->wq_buf) { - wait_queue = (struct mwifiex_wait_queue *) cmd_node->wq_buf; - if (wait_queue->status != MWIFIEX_ERROR_NO_ERROR) - mwifiex_ioctl_complete(adapter, wait_queue, -1); - else - mwifiex_ioctl_complete(adapter, wait_queue, 0); - } + + if (cmd_node->wait_q_enabled) + mwifiex_complete_cmd(adapter); /* Clean the node */ mwifiex_clean_cmd_node(adapter, cmd_node); @@ -554,8 +546,6 @@ mwifiex_insert_cmd_to_free_q(struct mwifiex_adapter *adapter, spin_lock_irqsave(&adapter->cmd_free_q_lock, flags); list_add_tail(&cmd_node->list, &adapter->cmd_free_q); spin_unlock_irqrestore(&adapter->cmd_free_q_lock, flags); - - return; } /* @@ -600,8 +590,6 @@ mwifiex_insert_cmd_to_pending_q(struct mwifiex_adapter *adapter, spin_unlock_irqrestore(&adapter->cmd_pending_q_lock, flags); dev_dbg(adapter->dev, "cmd: QUEUE_CMD: cmd=%#x is queued\n", command); - - return; } /* @@ -692,7 +680,6 @@ int mwifiex_process_cmdresp(struct mwifiex_adapter *adapter) uint16_t orig_cmdresp_no; uint16_t cmdresp_no; uint16_t cmdresp_result; - struct mwifiex_wait_queue *wait_queue = NULL; struct timeval tstamp; unsigned long flags; @@ -706,10 +693,6 @@ int mwifiex_process_cmdresp(struct mwifiex_adapter *adapter) return -1; } - if (adapter->curr_cmd->wq_buf) - wait_queue = (struct mwifiex_wait_queue *) - adapter->curr_cmd->wq_buf; - adapter->num_cmd_timeout = 0; resp = (struct host_cmd_ds_command *) adapter->curr_cmd->resp_skb->data; @@ -764,8 +747,8 @@ int mwifiex_process_cmdresp(struct mwifiex_adapter *adapter) if (!(orig_cmdresp_no & HostCmd_RET_BIT)) { dev_err(adapter->dev, "CMD_RESP: invalid cmd resp\n"); - if (wait_queue) - wait_queue->status = MWIFIEX_ERROR_FW_CMDRESP; + if (adapter->curr_cmd->wait_q_enabled) + adapter->cmd_wait_q.status = -1; mwifiex_insert_cmd_to_free_q(adapter, adapter->curr_cmd); spin_lock_irqsave(&adapter->mwifiex_cmd_lock, flags); @@ -781,8 +764,7 @@ int mwifiex_process_cmdresp(struct mwifiex_adapter *adapter) ret = mwifiex_ret_802_11_hs_cfg(priv, resp); } else { /* handle response */ - ret = mwifiex_process_sta_cmdresp(priv, cmdresp_no, resp, - wait_queue); + ret = mwifiex_process_sta_cmdresp(priv, cmdresp_no, resp); } /* Check init command response */ @@ -797,10 +779,10 @@ int mwifiex_process_cmdresp(struct mwifiex_adapter *adapter) } if (adapter->curr_cmd) { - if (wait_queue && (!ret)) - wait_queue->status = MWIFIEX_ERROR_NO_ERROR; - else if (wait_queue && (ret == -1)) - wait_queue->status = MWIFIEX_ERROR_CMD_RESP_FAIL; + if (adapter->curr_cmd->wait_q_enabled && (!ret)) + adapter->cmd_wait_q.status = 0; + else if (adapter->curr_cmd->wait_q_enabled && (ret == -1)) + adapter->cmd_wait_q.status = -1; /* Clean up and put current command back to cmd_free_q */ mwifiex_insert_cmd_to_free_q(adapter, adapter->curr_cmd); @@ -824,7 +806,6 @@ mwifiex_cmd_timeout_func(unsigned long function_context) struct mwifiex_adapter *adapter = (struct mwifiex_adapter *) function_context; struct cmd_ctrl_node *cmd_node = NULL; - struct mwifiex_wait_queue *wait_queue = NULL; struct timeval tstamp; adapter->num_cmd_timeout++; @@ -834,10 +815,8 @@ mwifiex_cmd_timeout_func(unsigned long function_context) return; } cmd_node = adapter->curr_cmd; - if (cmd_node->wq_buf) { - wait_queue = (struct mwifiex_wait_queue *) cmd_node->wq_buf; - wait_queue->status = MWIFIEX_ERROR_CMD_TIMEOUT; - } + if (cmd_node->wait_q_enabled) + adapter->cmd_wait_q.status = -ETIMEDOUT; if (cmd_node) { adapter->dbg.timeout_cmd_id = @@ -886,8 +865,6 @@ mwifiex_cmd_timeout_func(unsigned long function_context) } if (adapter->hw_status == MWIFIEX_HW_STATUS_INITIALIZING) mwifiex_init_fw_complete(adapter); - - return; } /* @@ -901,18 +878,15 @@ void mwifiex_cancel_all_pending_cmd(struct mwifiex_adapter *adapter) { struct cmd_ctrl_node *cmd_node = NULL, *tmp_node = NULL; - struct mwifiex_wait_queue *wait_queue = NULL; unsigned long flags; /* Cancel current cmd */ - if ((adapter->curr_cmd) && (adapter->curr_cmd->wq_buf)) { - wait_queue = - (struct mwifiex_wait_queue *) adapter->curr_cmd->wq_buf; + if ((adapter->curr_cmd) && (adapter->curr_cmd->wait_q_enabled)) { spin_lock_irqsave(&adapter->mwifiex_cmd_lock, flags); - adapter->curr_cmd->wq_buf = NULL; + adapter->curr_cmd->wait_q_enabled = false; spin_unlock_irqrestore(&adapter->mwifiex_cmd_lock, flags); - wait_queue->status = MWIFIEX_ERROR_CMD_CANCEL; - mwifiex_ioctl_complete(adapter, wait_queue, -1); + adapter->cmd_wait_q.status = -1; + mwifiex_complete_cmd(adapter); } /* Cancel all pending command */ spin_lock_irqsave(&adapter->cmd_pending_q_lock, flags); @@ -921,12 +895,10 @@ mwifiex_cancel_all_pending_cmd(struct mwifiex_adapter *adapter) list_del(&cmd_node->list); spin_unlock_irqrestore(&adapter->cmd_pending_q_lock, flags); - if (cmd_node->wq_buf) { - wait_queue = - (struct mwifiex_wait_queue *) cmd_node->wq_buf; - wait_queue->status = MWIFIEX_ERROR_CMD_CANCEL; - mwifiex_ioctl_complete(adapter, wait_queue, -1); - cmd_node->wq_buf = NULL; + if (cmd_node->wait_q_enabled) { + adapter->cmd_wait_q.status = -1; + mwifiex_complete_cmd(adapter); + cmd_node->wait_q_enabled = false; } mwifiex_insert_cmd_to_free_q(adapter, cmd_node); spin_lock_irqsave(&adapter->cmd_pending_q_lock, flags); @@ -940,7 +912,7 @@ mwifiex_cancel_all_pending_cmd(struct mwifiex_adapter *adapter) list_del(&cmd_node->list); spin_unlock_irqrestore(&adapter->scan_pending_q_lock, flags); - cmd_node->wq_buf = NULL; + cmd_node->wait_q_enabled = false; mwifiex_insert_cmd_to_free_q(adapter, cmd_node); spin_lock_irqsave(&adapter->scan_pending_q_lock, flags); } @@ -962,8 +934,7 @@ mwifiex_cancel_all_pending_cmd(struct mwifiex_adapter *adapter) * are cancelled. */ void -mwifiex_cancel_pending_ioctl(struct mwifiex_adapter *adapter, - struct mwifiex_wait_queue *wait_queue) +mwifiex_cancel_pending_ioctl(struct mwifiex_adapter *adapter) { struct cmd_ctrl_node *cmd_node = NULL, *tmp_node = NULL; unsigned long cmd_flags; @@ -972,45 +943,33 @@ mwifiex_cancel_pending_ioctl(struct mwifiex_adapter *adapter, uint16_t cancel_scan_cmd = false; if ((adapter->curr_cmd) && - (adapter->curr_cmd->wq_buf == wait_queue)) { + (adapter->curr_cmd->wait_q_enabled)) { spin_lock_irqsave(&adapter->mwifiex_cmd_lock, cmd_flags); cmd_node = adapter->curr_cmd; - cmd_node->wq_buf = NULL; + cmd_node->wait_q_enabled = false; cmd_node->cmd_flag |= CMD_F_CANCELED; - spin_unlock_irqrestore(&adapter->mwifiex_cmd_lock, cmd_flags); - } - - spin_lock_irqsave(&adapter->mwifiex_cmd_lock, cmd_flags); - while (1) { - cmd_node = mwifiex_get_pending_ioctl_cmd(adapter, wait_queue); - if (!cmd_node) - break; - spin_lock_irqsave(&adapter->cmd_pending_q_lock, cmd_pending_q_flags); list_del(&cmd_node->list); spin_unlock_irqrestore(&adapter->cmd_pending_q_lock, cmd_pending_q_flags); - - cmd_node->wq_buf = NULL; mwifiex_insert_cmd_to_free_q(adapter, cmd_node); + spin_unlock_irqrestore(&adapter->mwifiex_cmd_lock, cmd_flags); } - spin_unlock_irqrestore(&adapter->mwifiex_cmd_lock, cmd_flags); + /* Cancel all pending scan command */ spin_lock_irqsave(&adapter->scan_pending_q_lock, scan_pending_q_flags); list_for_each_entry_safe(cmd_node, tmp_node, &adapter->scan_pending_q, list) { - if (cmd_node->wq_buf == wait_queue) { - list_del(&cmd_node->list); - spin_unlock_irqrestore(&adapter->scan_pending_q_lock, - scan_pending_q_flags); - cmd_node->wq_buf = NULL; - mwifiex_insert_cmd_to_free_q(adapter, cmd_node); - spin_lock_irqsave(&adapter->scan_pending_q_lock, - scan_pending_q_flags); - cancel_scan_cmd = true; - } + list_del(&cmd_node->list); + spin_unlock_irqrestore(&adapter->scan_pending_q_lock, + scan_pending_q_flags); + cmd_node->wait_q_enabled = false; + mwifiex_insert_cmd_to_free_q(adapter, cmd_node); + spin_lock_irqsave(&adapter->scan_pending_q_lock, + scan_pending_q_flags); + cancel_scan_cmd = true; } spin_unlock_irqrestore(&adapter->scan_pending_q_lock, scan_pending_q_flags); @@ -1020,10 +979,8 @@ mwifiex_cancel_pending_ioctl(struct mwifiex_adapter *adapter, adapter->scan_processing = false; spin_unlock_irqrestore(&adapter->mwifiex_cmd_lock, cmd_flags); } - wait_queue->status = MWIFIEX_ERROR_CMD_CANCEL; - mwifiex_ioctl_complete(adapter, wait_queue, -1); - - return; + adapter->cmd_wait_q.status = -1; + mwifiex_complete_cmd(adapter); } /* @@ -1127,7 +1084,6 @@ mwifiex_process_hs_config(struct mwifiex_adapter *adapter) adapter->is_hs_configured = false; mwifiex_hs_activated_event(mwifiex_get_priv(adapter, MWIFIEX_BSS_ROLE_ANY), false); - return; } /* |