aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAmitkumar Karwar <akarwar@marvell.com>2011-10-12 23:28:06 -0400
committerJohn W. Linville <linville@tuxdriver.com>2011-10-14 14:48:20 -0400
commitefaaa8b8414e0ab4ba09aaaf79ab92a34b75797b (patch)
treefb5680389af8de71154859c468adc83c04b7c1e4
parent207ae4a3733686df2aabd2dd6feefbde4e69cdd5 (diff)
mwifiex: use separate wait condition for each command node
Currently global wait condition (adapter->cmd_wait_q.condition) is used while sending synchronous commands to FW. When two threads enter in mwifiex_send_cmd_sync() routine at the same time, both the threads wait for their command responses. Since wait condition is same for both, they wake up simultaneously after getting response of 1st command. After this when a thread is waiting for command response of 3rd command, it wakes up after getting response of 2nd command and so on. Therefore we don't wait for the response of last command(0xaa) during unload. Hence while next time loading the driver command time out is seen for INIT command. This problem is resolved by having separate wait condition flag for each command(except scan command). Since scan command is treated differently (by maintaining scan pending q etc.), newly defined flag (scan_wait_q_woken) is used as a scan wait condition. Signed-off-by: Amitkumar Karwar <akarwar@marvell.com> Signed-off-by: Yogesh Ashok Powar <yogeshp@marvell.com> Signed-off-by: Bing Zhao <bzhao@marvell.com> Signed-off-by: John W. Linville <linville@tuxdriver.com>
-rw-r--r--drivers/net/wireless/mwifiex/cmdevt.c23
-rw-r--r--drivers/net/wireless/mwifiex/decl.h1
-rw-r--r--drivers/net/wireless/mwifiex/main.c2
-rw-r--r--drivers/net/wireless/mwifiex/main.h7
-rw-r--r--drivers/net/wireless/mwifiex/scan.c8
-rw-r--r--drivers/net/wireless/mwifiex/sta_ioctl.c6
-rw-r--r--drivers/net/wireless/mwifiex/util.c5
7 files changed, 33 insertions, 19 deletions
diff --git a/drivers/net/wireless/mwifiex/cmdevt.c b/drivers/net/wireless/mwifiex/cmdevt.c
index 508de7f6d9c1..ac278156d390 100644
--- a/drivers/net/wireless/mwifiex/cmdevt.c
+++ b/drivers/net/wireless/mwifiex/cmdevt.c
@@ -40,8 +40,12 @@ mwifiex_init_cmd_node(struct mwifiex_private *priv,
40{ 40{
41 cmd_node->priv = priv; 41 cmd_node->priv = priv;
42 cmd_node->cmd_oid = cmd_oid; 42 cmd_node->cmd_oid = cmd_oid;
43 cmd_node->wait_q_enabled = priv->adapter->cmd_wait_q_required; 43 if (priv->adapter->cmd_wait_q_required) {
44 priv->adapter->cmd_wait_q_required = false; 44 cmd_node->wait_q_enabled = priv->adapter->cmd_wait_q_required;
45 priv->adapter->cmd_wait_q_required = false;
46 cmd_node->cmd_wait_q_woken = false;
47 cmd_node->condition = &cmd_node->cmd_wait_q_woken;
48 }
45 cmd_node->data_buf = data_buf; 49 cmd_node->data_buf = data_buf;
46 cmd_node->cmd_skb = cmd_node->skb; 50 cmd_node->cmd_skb = cmd_node->skb;
47} 51}
@@ -418,7 +422,6 @@ int mwifiex_send_cmd_sync(struct mwifiex_private *priv, uint16_t cmd_no,
418 struct mwifiex_adapter *adapter = priv->adapter; 422 struct mwifiex_adapter *adapter = priv->adapter;
419 423
420 adapter->cmd_wait_q_required = true; 424 adapter->cmd_wait_q_required = true;
421 adapter->cmd_wait_q.condition = false;
422 425
423 ret = mwifiex_send_cmd_async(priv, cmd_no, cmd_action, cmd_oid, 426 ret = mwifiex_send_cmd_async(priv, cmd_no, cmd_action, cmd_oid,
424 data_buf); 427 data_buf);
@@ -511,10 +514,12 @@ int mwifiex_send_cmd_async(struct mwifiex_private *priv, uint16_t cmd_no,
511 } 514 }
512 515
513 /* Send command */ 516 /* Send command */
514 if (cmd_no == HostCmd_CMD_802_11_SCAN) 517 if (cmd_no == HostCmd_CMD_802_11_SCAN) {
515 mwifiex_queue_scan_cmd(priv, cmd_node); 518 mwifiex_queue_scan_cmd(priv, cmd_node);
516 else 519 } else {
520 adapter->cmd_queued = cmd_node;
517 mwifiex_insert_cmd_to_pending_q(adapter, cmd_node, true); 521 mwifiex_insert_cmd_to_pending_q(adapter, cmd_node, true);
522 }
518 523
519 return ret; 524 return ret;
520} 525}
@@ -535,7 +540,7 @@ mwifiex_insert_cmd_to_free_q(struct mwifiex_adapter *adapter,
535 return; 540 return;
536 541
537 if (cmd_node->wait_q_enabled) 542 if (cmd_node->wait_q_enabled)
538 mwifiex_complete_cmd(adapter); 543 mwifiex_complete_cmd(adapter, cmd_node);
539 /* Clean the node */ 544 /* Clean the node */
540 mwifiex_clean_cmd_node(adapter, cmd_node); 545 mwifiex_clean_cmd_node(adapter, cmd_node);
541 546
@@ -882,7 +887,7 @@ mwifiex_cancel_all_pending_cmd(struct mwifiex_adapter *adapter)
882 adapter->curr_cmd->wait_q_enabled = false; 887 adapter->curr_cmd->wait_q_enabled = false;
883 spin_unlock_irqrestore(&adapter->mwifiex_cmd_lock, flags); 888 spin_unlock_irqrestore(&adapter->mwifiex_cmd_lock, flags);
884 adapter->cmd_wait_q.status = -1; 889 adapter->cmd_wait_q.status = -1;
885 mwifiex_complete_cmd(adapter); 890 mwifiex_complete_cmd(adapter, adapter->curr_cmd);
886 } 891 }
887 /* Cancel all pending command */ 892 /* Cancel all pending command */
888 spin_lock_irqsave(&adapter->cmd_pending_q_lock, flags); 893 spin_lock_irqsave(&adapter->cmd_pending_q_lock, flags);
@@ -893,7 +898,7 @@ mwifiex_cancel_all_pending_cmd(struct mwifiex_adapter *adapter)
893 898
894 if (cmd_node->wait_q_enabled) { 899 if (cmd_node->wait_q_enabled) {
895 adapter->cmd_wait_q.status = -1; 900 adapter->cmd_wait_q.status = -1;
896 mwifiex_complete_cmd(adapter); 901 mwifiex_complete_cmd(adapter, cmd_node);
897 cmd_node->wait_q_enabled = false; 902 cmd_node->wait_q_enabled = false;
898 } 903 }
899 mwifiex_insert_cmd_to_free_q(adapter, cmd_node); 904 mwifiex_insert_cmd_to_free_q(adapter, cmd_node);
@@ -976,7 +981,7 @@ mwifiex_cancel_pending_ioctl(struct mwifiex_adapter *adapter)
976 spin_unlock_irqrestore(&adapter->mwifiex_cmd_lock, cmd_flags); 981 spin_unlock_irqrestore(&adapter->mwifiex_cmd_lock, cmd_flags);
977 } 982 }
978 adapter->cmd_wait_q.status = -1; 983 adapter->cmd_wait_q.status = -1;
979 mwifiex_complete_cmd(adapter); 984 mwifiex_complete_cmd(adapter, adapter->curr_cmd);
980} 985}
981 986
982/* 987/*
diff --git a/drivers/net/wireless/mwifiex/decl.h b/drivers/net/wireless/mwifiex/decl.h
index 6ca62c809cb9..ae17ce02a3d0 100644
--- a/drivers/net/wireless/mwifiex/decl.h
+++ b/drivers/net/wireless/mwifiex/decl.h
@@ -98,7 +98,6 @@ struct mwifiex_802_11_ssid {
98 98
99struct mwifiex_wait_queue { 99struct mwifiex_wait_queue {
100 wait_queue_head_t wait; 100 wait_queue_head_t wait;
101 u16 condition;
102 int status; 101 int status;
103}; 102};
104 103
diff --git a/drivers/net/wireless/mwifiex/main.c b/drivers/net/wireless/mwifiex/main.c
index 849144d9c94e..25ce86bef8e5 100644
--- a/drivers/net/wireless/mwifiex/main.c
+++ b/drivers/net/wireless/mwifiex/main.c
@@ -685,8 +685,8 @@ mwifiex_add_card(void *card, struct semaphore *sem,
685 init_waitqueue_head(&adapter->hs_activate_wait_q); 685 init_waitqueue_head(&adapter->hs_activate_wait_q);
686 adapter->cmd_wait_q_required = false; 686 adapter->cmd_wait_q_required = false;
687 init_waitqueue_head(&adapter->cmd_wait_q.wait); 687 init_waitqueue_head(&adapter->cmd_wait_q.wait);
688 adapter->cmd_wait_q.condition = false;
689 adapter->cmd_wait_q.status = 0; 688 adapter->cmd_wait_q.status = 0;
689 adapter->scan_wait_q_woken = false;
690 690
691 adapter->workqueue = create_workqueue("MWIFIEX_WORK_QUEUE"); 691 adapter->workqueue = create_workqueue("MWIFIEX_WORK_QUEUE");
692 if (!adapter->workqueue) 692 if (!adapter->workqueue)
diff --git a/drivers/net/wireless/mwifiex/main.h b/drivers/net/wireless/mwifiex/main.h
index ec45607c5f91..7db20dbf486d 100644
--- a/drivers/net/wireless/mwifiex/main.h
+++ b/drivers/net/wireless/mwifiex/main.h
@@ -520,6 +520,8 @@ struct cmd_ctrl_node {
520 void *data_buf; 520 void *data_buf;
521 u32 wait_q_enabled; 521 u32 wait_q_enabled;
522 struct sk_buff *skb; 522 struct sk_buff *skb;
523 u8 *condition;
524 u8 cmd_wait_q_woken;
523}; 525};
524 526
525struct mwifiex_if_ops { 527struct mwifiex_if_ops {
@@ -651,6 +653,8 @@ struct mwifiex_adapter {
651 u32 arp_filter_size; 653 u32 arp_filter_size;
652 u16 cmd_wait_q_required; 654 u16 cmd_wait_q_required;
653 struct mwifiex_wait_queue cmd_wait_q; 655 struct mwifiex_wait_queue cmd_wait_q;
656 u8 scan_wait_q_woken;
657 struct cmd_ctrl_node *cmd_queued;
654}; 658};
655 659
656int mwifiex_init_lock_list(struct mwifiex_adapter *adapter); 660int mwifiex_init_lock_list(struct mwifiex_adapter *adapter);
@@ -670,7 +674,8 @@ int mwifiex_recv_packet(struct mwifiex_adapter *, struct sk_buff *skb);
670 674
671int mwifiex_process_event(struct mwifiex_adapter *adapter); 675int mwifiex_process_event(struct mwifiex_adapter *adapter);
672 676
673int mwifiex_complete_cmd(struct mwifiex_adapter *adapter); 677int mwifiex_complete_cmd(struct mwifiex_adapter *adapter,
678 struct cmd_ctrl_node *cmd_node);
674 679
675int mwifiex_send_cmd_async(struct mwifiex_private *priv, uint16_t cmd_no, 680int mwifiex_send_cmd_async(struct mwifiex_private *priv, uint16_t cmd_no,
676 u16 cmd_action, u32 cmd_oid, void *data_buf); 681 u16 cmd_action, u32 cmd_oid, void *data_buf);
diff --git a/drivers/net/wireless/mwifiex/scan.c b/drivers/net/wireless/mwifiex/scan.c
index ca3761965e85..5456dcbf037c 100644
--- a/drivers/net/wireless/mwifiex/scan.c
+++ b/drivers/net/wireless/mwifiex/scan.c
@@ -185,7 +185,7 @@ int mwifiex_set_user_scan_ioctl(struct mwifiex_private *priv,
185{ 185{
186 int status; 186 int status;
187 187
188 priv->adapter->cmd_wait_q.condition = false; 188 priv->adapter->scan_wait_q_woken = false;
189 189
190 status = mwifiex_scan_networks(priv, scan_req); 190 status = mwifiex_scan_networks(priv, scan_req);
191 if (!status) 191 if (!status)
@@ -1380,6 +1380,7 @@ int mwifiex_scan_networks(struct mwifiex_private *priv,
1380 list_del(&cmd_node->list); 1380 list_del(&cmd_node->list);
1381 spin_unlock_irqrestore(&adapter->scan_pending_q_lock, 1381 spin_unlock_irqrestore(&adapter->scan_pending_q_lock,
1382 flags); 1382 flags);
1383 adapter->cmd_queued = cmd_node;
1383 mwifiex_insert_cmd_to_pending_q(adapter, cmd_node, 1384 mwifiex_insert_cmd_to_pending_q(adapter, cmd_node,
1384 true); 1385 true);
1385 } else { 1386 } else {
@@ -1788,7 +1789,7 @@ int mwifiex_ret_802_11_scan(struct mwifiex_private *priv,
1788 /* Need to indicate IOCTL complete */ 1789 /* Need to indicate IOCTL complete */
1789 if (adapter->curr_cmd->wait_q_enabled) { 1790 if (adapter->curr_cmd->wait_q_enabled) {
1790 adapter->cmd_wait_q.status = 0; 1791 adapter->cmd_wait_q.status = 0;
1791 mwifiex_complete_cmd(adapter); 1792 mwifiex_complete_cmd(adapter, adapter->curr_cmd);
1792 } 1793 }
1793 if (priv->report_scan_result) 1794 if (priv->report_scan_result)
1794 priv->report_scan_result = false; 1795 priv->report_scan_result = false;
@@ -1845,6 +1846,7 @@ mwifiex_queue_scan_cmd(struct mwifiex_private *priv,
1845 unsigned long flags; 1846 unsigned long flags;
1846 1847
1847 cmd_node->wait_q_enabled = true; 1848 cmd_node->wait_q_enabled = true;
1849 cmd_node->condition = &adapter->scan_wait_q_woken;
1848 spin_lock_irqsave(&adapter->scan_pending_q_lock, flags); 1850 spin_lock_irqsave(&adapter->scan_pending_q_lock, flags);
1849 list_add_tail(&cmd_node->list, &adapter->scan_pending_q); 1851 list_add_tail(&cmd_node->list, &adapter->scan_pending_q);
1850 spin_unlock_irqrestore(&adapter->scan_pending_q_lock, flags); 1852 spin_unlock_irqrestore(&adapter->scan_pending_q_lock, flags);
@@ -1911,7 +1913,7 @@ int mwifiex_request_scan(struct mwifiex_private *priv,
1911 } 1913 }
1912 priv->scan_pending_on_block = true; 1914 priv->scan_pending_on_block = true;
1913 1915
1914 priv->adapter->cmd_wait_q.condition = false; 1916 priv->adapter->scan_wait_q_woken = false;
1915 1917
1916 if (req_ssid && req_ssid->ssid_len != 0) 1918 if (req_ssid && req_ssid->ssid_len != 0)
1917 /* Specific SSID scan */ 1919 /* Specific SSID scan */
diff --git a/drivers/net/wireless/mwifiex/sta_ioctl.c b/drivers/net/wireless/mwifiex/sta_ioctl.c
index f20550a7c525..d39bb72896f1 100644
--- a/drivers/net/wireless/mwifiex/sta_ioctl.c
+++ b/drivers/net/wireless/mwifiex/sta_ioctl.c
@@ -55,7 +55,9 @@ int mwifiex_wait_queue_complete(struct mwifiex_adapter *adapter)
55{ 55{
56 bool cancel_flag = false; 56 bool cancel_flag = false;
57 int status = adapter->cmd_wait_q.status; 57 int status = adapter->cmd_wait_q.status;
58 struct cmd_ctrl_node *cmd_queued = adapter->cmd_queued;
58 59
60 adapter->cmd_queued = NULL;
59 dev_dbg(adapter->dev, "cmd pending\n"); 61 dev_dbg(adapter->dev, "cmd pending\n");
60 atomic_inc(&adapter->cmd_pending); 62 atomic_inc(&adapter->cmd_pending);
61 63
@@ -64,8 +66,8 @@ int mwifiex_wait_queue_complete(struct mwifiex_adapter *adapter)
64 66
65 /* Wait for completion */ 67 /* Wait for completion */
66 wait_event_interruptible(adapter->cmd_wait_q.wait, 68 wait_event_interruptible(adapter->cmd_wait_q.wait,
67 adapter->cmd_wait_q.condition); 69 *(cmd_queued->condition));
68 if (!adapter->cmd_wait_q.condition) 70 if (!*(cmd_queued->condition))
69 cancel_flag = true; 71 cancel_flag = true;
70 72
71 if (cancel_flag) { 73 if (cancel_flag) {
diff --git a/drivers/net/wireless/mwifiex/util.c b/drivers/net/wireless/mwifiex/util.c
index d41291529bc0..06976f517f66 100644
--- a/drivers/net/wireless/mwifiex/util.c
+++ b/drivers/net/wireless/mwifiex/util.c
@@ -185,13 +185,14 @@ int mwifiex_recv_packet(struct mwifiex_adapter *adapter, struct sk_buff *skb)
185 * corresponding waiting function. Otherwise, it processes the 185 * corresponding waiting function. Otherwise, it processes the
186 * IOCTL response and frees the response buffer. 186 * IOCTL response and frees the response buffer.
187 */ 187 */
188int mwifiex_complete_cmd(struct mwifiex_adapter *adapter) 188int mwifiex_complete_cmd(struct mwifiex_adapter *adapter,
189 struct cmd_ctrl_node *cmd_node)
189{ 190{
190 atomic_dec(&adapter->cmd_pending); 191 atomic_dec(&adapter->cmd_pending);
191 dev_dbg(adapter->dev, "cmd completed: status=%d\n", 192 dev_dbg(adapter->dev, "cmd completed: status=%d\n",
192 adapter->cmd_wait_q.status); 193 adapter->cmd_wait_q.status);
193 194
194 adapter->cmd_wait_q.condition = true; 195 *(cmd_node->condition) = true;
195 196
196 if (adapter->cmd_wait_q.status == -ETIMEDOUT) 197 if (adapter->cmd_wait_q.status == -ETIMEDOUT)
197 dev_err(adapter->dev, "cmd timeout\n"); 198 dev_err(adapter->dev, "cmd timeout\n");