aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAmitkumar Karwar <akarwar@marvell.com>2012-06-07 00:12:41 -0400
committerJohn W. Linville <linville@tuxdriver.com>2012-06-11 14:59:43 -0400
commit3249ba7376caa93af387d8e6b5e41b290934f88c (patch)
tree7c4c762095bbb0e77261b9b1399d688aea04eeb4
parent38e8b7d977786b0059c02744e4b96bc1e206d891 (diff)
mwifiex: fix simultaneous scan and Tx traffic problem
If scan operation is started when Tx traffic is already running, driver locks Tx queue until it gets completed. With this logic there is a delay for Tx packets. This patch implements new approach to give Tx path higher priority in this case. Driver internally sends multiple synchronous scan commands to firmware when scan is requested by user. Now we will make sure that Tx queue is empty everytime before sending next scan command. If Tx queue isn't empty scan command will be postponsed by 20msec. This rule will be followed until Tx queue becomes empty or timeout of 1 second happens. In case of timeout scan operation will be aborted. Signed-off-by: Amitkumar Karwar <akarwar@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/init.c65
-rw-r--r--drivers/net/wireless/mwifiex/main.c4
-rw-r--r--drivers/net/wireless/mwifiex/main.h5
-rw-r--r--drivers/net/wireless/mwifiex/scan.c25
4 files changed, 89 insertions, 10 deletions
diff --git a/drivers/net/wireless/mwifiex/init.c b/drivers/net/wireless/mwifiex/init.c
index c1cb004db913..0f18ef6a30c8 100644
--- a/drivers/net/wireless/mwifiex/init.c
+++ b/drivers/net/wireless/mwifiex/init.c
@@ -57,6 +57,68 @@ static int mwifiex_add_bss_prio_tbl(struct mwifiex_private *priv)
57 return 0; 57 return 0;
58} 58}
59 59
60static void scan_delay_timer_fn(unsigned long data)
61{
62 struct mwifiex_private *priv = (struct mwifiex_private *)data;
63 struct mwifiex_adapter *adapter = priv->adapter;
64 struct cmd_ctrl_node *cmd_node, *tmp_node;
65 unsigned long flags;
66
67 if (!mwifiex_wmm_lists_empty(adapter)) {
68 if (adapter->scan_delay_cnt == MWIFIEX_MAX_SCAN_DELAY_CNT) {
69 /*
70 * Abort scan operation by cancelling all pending scan
71 * command
72 */
73 spin_lock_irqsave(&adapter->scan_pending_q_lock, flags);
74 list_for_each_entry_safe(cmd_node, tmp_node,
75 &adapter->scan_pending_q,
76 list) {
77 list_del(&cmd_node->list);
78 cmd_node->wait_q_enabled = false;
79 mwifiex_insert_cmd_to_free_q(adapter, cmd_node);
80 }
81 spin_unlock_irqrestore(&adapter->scan_pending_q_lock,
82 flags);
83
84 spin_lock_irqsave(&adapter->mwifiex_cmd_lock, flags);
85 adapter->scan_processing = false;
86 spin_unlock_irqrestore(&adapter->mwifiex_cmd_lock,
87 flags);
88
89 if (priv->user_scan_cfg) {
90 dev_dbg(priv->adapter->dev,
91 "info: %s: scan aborted\n", __func__);
92 cfg80211_scan_done(priv->scan_request, 1);
93 priv->scan_request = NULL;
94 kfree(priv->user_scan_cfg);
95 priv->user_scan_cfg = NULL;
96 }
97 } else {
98 /*
99 * Tx data queue is still not empty, delay scan
100 * operation further by 20msec.
101 */
102 mod_timer(&priv->scan_delay_timer, jiffies +
103 msecs_to_jiffies(MWIFIEX_SCAN_DELAY_MSEC));
104 adapter->scan_delay_cnt++;
105 }
106 } else {
107 /*
108 * Tx data queue is empty. Get scan command from scan_pending_q
109 * and put to cmd_pending_q to resume scan operation
110 */
111 adapter->scan_delay_cnt = 0;
112 spin_lock_irqsave(&adapter->scan_pending_q_lock, flags);
113 cmd_node = list_first_entry(&adapter->scan_pending_q,
114 struct cmd_ctrl_node, list);
115 list_del(&cmd_node->list);
116 spin_unlock_irqrestore(&adapter->scan_pending_q_lock, flags);
117
118 mwifiex_insert_cmd_to_pending_q(adapter, cmd_node, true);
119 }
120}
121
60/* 122/*
61 * This function initializes the private structure and sets default 123 * This function initializes the private structure and sets default
62 * values to the members. 124 * values to the members.
@@ -136,6 +198,9 @@ static int mwifiex_init_priv(struct mwifiex_private *priv)
136 198
137 priv->scan_block = false; 199 priv->scan_block = false;
138 200
201 setup_timer(&priv->scan_delay_timer, scan_delay_timer_fn,
202 (unsigned long)priv);
203
139 return mwifiex_add_bss_prio_tbl(priv); 204 return mwifiex_add_bss_prio_tbl(priv);
140} 205}
141 206
diff --git a/drivers/net/wireless/mwifiex/main.c b/drivers/net/wireless/mwifiex/main.c
index 3192855c31c0..0f06f07a70e6 100644
--- a/drivers/net/wireless/mwifiex/main.c
+++ b/drivers/net/wireless/mwifiex/main.c
@@ -244,8 +244,8 @@ process_start:
244 } 244 }
245 } 245 }
246 246
247 if (!adapter->scan_processing && !adapter->data_sent && 247 if ((!adapter->scan_processing || adapter->scan_delay_cnt) &&
248 !mwifiex_wmm_lists_empty(adapter)) { 248 !adapter->data_sent && !mwifiex_wmm_lists_empty(adapter)) {
249 mwifiex_wmm_process_tx(adapter); 249 mwifiex_wmm_process_tx(adapter);
250 if (adapter->hs_activated) { 250 if (adapter->hs_activated) {
251 adapter->is_hs_configured = false; 251 adapter->is_hs_configured = false;
diff --git a/drivers/net/wireless/mwifiex/main.h b/drivers/net/wireless/mwifiex/main.h
index cbad00d7eb11..5b32221077c4 100644
--- a/drivers/net/wireless/mwifiex/main.h
+++ b/drivers/net/wireless/mwifiex/main.h
@@ -87,6 +87,9 @@ enum {
87 87
88#define MWIFIEX_MAX_TOTAL_SCAN_TIME (MWIFIEX_TIMER_10S - MWIFIEX_TIMER_1S) 88#define MWIFIEX_MAX_TOTAL_SCAN_TIME (MWIFIEX_TIMER_10S - MWIFIEX_TIMER_1S)
89 89
90#define MWIFIEX_MAX_SCAN_DELAY_CNT 50
91#define MWIFIEX_SCAN_DELAY_MSEC 20
92
90#define RSN_GTK_OUI_OFFSET 2 93#define RSN_GTK_OUI_OFFSET 2
91 94
92#define MWIFIEX_OUI_NOT_PRESENT 0 95#define MWIFIEX_OUI_NOT_PRESENT 0
@@ -482,6 +485,7 @@ struct mwifiex_private {
482 u16 proberesp_idx; 485 u16 proberesp_idx;
483 u16 assocresp_idx; 486 u16 assocresp_idx;
484 u16 rsn_idx; 487 u16 rsn_idx;
488 struct timer_list scan_delay_timer;
485}; 489};
486 490
487enum mwifiex_ba_status { 491enum mwifiex_ba_status {
@@ -686,6 +690,7 @@ struct mwifiex_adapter {
686 struct completion fw_load; 690 struct completion fw_load;
687 u8 country_code[IEEE80211_COUNTRY_STRING_LEN]; 691 u8 country_code[IEEE80211_COUNTRY_STRING_LEN];
688 u16 max_mgmt_ie_index; 692 u16 max_mgmt_ie_index;
693 u8 scan_delay_cnt;
689}; 694};
690 695
691int mwifiex_init_lock_list(struct mwifiex_adapter *adapter); 696int mwifiex_init_lock_list(struct mwifiex_adapter *adapter);
diff --git a/drivers/net/wireless/mwifiex/scan.c b/drivers/net/wireless/mwifiex/scan.c
index 74f045715723..ea2f1bdef8a2 100644
--- a/drivers/net/wireless/mwifiex/scan.c
+++ b/drivers/net/wireless/mwifiex/scan.c
@@ -1772,14 +1772,23 @@ int mwifiex_ret_802_11_scan(struct mwifiex_private *priv,
1772 priv->user_scan_cfg = NULL; 1772 priv->user_scan_cfg = NULL;
1773 } 1773 }
1774 } else { 1774 } else {
1775 /* Get scan command from scan_pending_q and put to 1775 if (!mwifiex_wmm_lists_empty(adapter)) {
1776 cmd_pending_q */ 1776 spin_unlock_irqrestore(&adapter->scan_pending_q_lock,
1777 cmd_node = list_first_entry(&adapter->scan_pending_q, 1777 flags);
1778 struct cmd_ctrl_node, list); 1778 adapter->scan_delay_cnt = 1;
1779 list_del(&cmd_node->list); 1779 mod_timer(&priv->scan_delay_timer, jiffies +
1780 spin_unlock_irqrestore(&adapter->scan_pending_q_lock, flags); 1780 msecs_to_jiffies(MWIFIEX_SCAN_DELAY_MSEC));
1781 1781 } else {
1782 mwifiex_insert_cmd_to_pending_q(adapter, cmd_node, true); 1782 /* Get scan command from scan_pending_q and put to
1783 cmd_pending_q */
1784 cmd_node = list_first_entry(&adapter->scan_pending_q,
1785 struct cmd_ctrl_node, list);
1786 list_del(&cmd_node->list);
1787 spin_unlock_irqrestore(&adapter->scan_pending_q_lock,
1788 flags);
1789 mwifiex_insert_cmd_to_pending_q(adapter, cmd_node,
1790 true);
1791 }
1783 } 1792 }
1784 1793
1785done: 1794done: