diff options
author | Zhaoyang Liu <liuzy@marvell.com> | 2015-03-13 08:07:57 -0400 |
---|---|---|
committer | Kalle Valo <kvalo@codeaurora.org> | 2015-03-16 12:12:33 -0400 |
commit | e35000ead491d71e59ab6f7458971321e06150a0 (patch) | |
tree | 3eb58299075b684e4a3865debecce6aacafb7c6d /drivers/net/wireless/mwifiex | |
parent | 690e792cb9d78c3bcaf4a6a8387dbbfbafad579f (diff) |
mwifiex: preprocess packets from TX queue
During profiling, we discovered that driver remains idle for time
when pakcet is downloaded to FW but no TX_DONE has been received
i.e. while data_sent is true.
This patch adds enhancement to TX routine where we preprocess
packets from TX queue, make them ready for TX and add them to
separate TX queue.
Signed-off-by: Zhaoyang Liu <liuzy@marvell.com>
Signed-off-by: Marc Yang <yangyang@marvell.com>
Signed-off-by: Chin-ran Lo <crlo@marvell.com>
Reviewed-by: Cathy Luo <cluo@marvell.com>
Reviewed-by: Amitkumar Karwar <akarwar@marvell.com>
Reviewed-by: Avinash Patil <patila@marvell.com>
Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
Diffstat (limited to 'drivers/net/wireless/mwifiex')
-rw-r--r-- | drivers/net/wireless/mwifiex/11n_aggr.c | 16 | ||||
-rw-r--r-- | drivers/net/wireless/mwifiex/decl.h | 2 | ||||
-rw-r--r-- | drivers/net/wireless/mwifiex/init.c | 5 | ||||
-rw-r--r-- | drivers/net/wireless/mwifiex/main.c | 21 | ||||
-rw-r--r-- | drivers/net/wireless/mwifiex/main.h | 6 | ||||
-rw-r--r-- | drivers/net/wireless/mwifiex/txrx.c | 125 | ||||
-rw-r--r-- | drivers/net/wireless/mwifiex/wmm.c | 21 |
7 files changed, 185 insertions, 11 deletions
diff --git a/drivers/net/wireless/mwifiex/11n_aggr.c b/drivers/net/wireless/mwifiex/11n_aggr.c index 9b983b5cebbd..6183e255e62a 100644 --- a/drivers/net/wireless/mwifiex/11n_aggr.c +++ b/drivers/net/wireless/mwifiex/11n_aggr.c | |||
@@ -170,7 +170,7 @@ mwifiex_11n_aggregate_pkt(struct mwifiex_private *priv, | |||
170 | struct mwifiex_adapter *adapter = priv->adapter; | 170 | struct mwifiex_adapter *adapter = priv->adapter; |
171 | struct sk_buff *skb_aggr, *skb_src; | 171 | struct sk_buff *skb_aggr, *skb_src; |
172 | struct mwifiex_txinfo *tx_info_aggr, *tx_info_src; | 172 | struct mwifiex_txinfo *tx_info_aggr, *tx_info_src; |
173 | int pad = 0, ret; | 173 | int pad = 0, aggr_num = 0, ret; |
174 | struct mwifiex_tx_param tx_param; | 174 | struct mwifiex_tx_param tx_param; |
175 | struct txpd *ptx_pd = NULL; | 175 | struct txpd *ptx_pd = NULL; |
176 | struct timeval tv; | 176 | struct timeval tv; |
@@ -184,7 +184,8 @@ mwifiex_11n_aggregate_pkt(struct mwifiex_private *priv, | |||
184 | } | 184 | } |
185 | 185 | ||
186 | tx_info_src = MWIFIEX_SKB_TXCB(skb_src); | 186 | tx_info_src = MWIFIEX_SKB_TXCB(skb_src); |
187 | skb_aggr = dev_alloc_skb(adapter->tx_buf_size); | 187 | skb_aggr = mwifiex_alloc_dma_align_buf(adapter->tx_buf_size, |
188 | GFP_ATOMIC | GFP_DMA); | ||
188 | if (!skb_aggr) { | 189 | if (!skb_aggr) { |
189 | dev_err(adapter->dev, "%s: alloc skb_aggr\n", __func__); | 190 | dev_err(adapter->dev, "%s: alloc skb_aggr\n", __func__); |
190 | spin_unlock_irqrestore(&priv->wmm.ra_list_spinlock, | 191 | spin_unlock_irqrestore(&priv->wmm.ra_list_spinlock, |
@@ -200,6 +201,7 @@ mwifiex_11n_aggregate_pkt(struct mwifiex_private *priv, | |||
200 | 201 | ||
201 | if (tx_info_src->flags & MWIFIEX_BUF_FLAG_TDLS_PKT) | 202 | if (tx_info_src->flags & MWIFIEX_BUF_FLAG_TDLS_PKT) |
202 | tx_info_aggr->flags |= MWIFIEX_BUF_FLAG_TDLS_PKT; | 203 | tx_info_aggr->flags |= MWIFIEX_BUF_FLAG_TDLS_PKT; |
204 | tx_info_aggr->flags |= MWIFIEX_BUF_FLAG_AGGR_PKT; | ||
203 | skb_aggr->priority = skb_src->priority; | 205 | skb_aggr->priority = skb_src->priority; |
204 | 206 | ||
205 | do_gettimeofday(&tv); | 207 | do_gettimeofday(&tv); |
@@ -211,11 +213,9 @@ mwifiex_11n_aggregate_pkt(struct mwifiex_private *priv, | |||
211 | break; | 213 | break; |
212 | 214 | ||
213 | skb_src = skb_dequeue(&pra_list->skb_head); | 215 | skb_src = skb_dequeue(&pra_list->skb_head); |
214 | |||
215 | pra_list->total_pkt_count--; | 216 | pra_list->total_pkt_count--; |
216 | |||
217 | atomic_dec(&priv->wmm.tx_pkts_queued); | 217 | atomic_dec(&priv->wmm.tx_pkts_queued); |
218 | 218 | aggr_num++; | |
219 | spin_unlock_irqrestore(&priv->wmm.ra_list_spinlock, | 219 | spin_unlock_irqrestore(&priv->wmm.ra_list_spinlock, |
220 | ra_list_flags); | 220 | ra_list_flags); |
221 | mwifiex_11n_form_amsdu_pkt(skb_aggr, skb_src, &pad); | 221 | mwifiex_11n_form_amsdu_pkt(skb_aggr, skb_src, &pad); |
@@ -251,6 +251,12 @@ mwifiex_11n_aggregate_pkt(struct mwifiex_private *priv, | |||
251 | ptx_pd = (struct txpd *)skb_aggr->data; | 251 | ptx_pd = (struct txpd *)skb_aggr->data; |
252 | 252 | ||
253 | skb_push(skb_aggr, headroom); | 253 | skb_push(skb_aggr, headroom); |
254 | tx_info_aggr->aggr_num = aggr_num * 2; | ||
255 | if (adapter->data_sent || adapter->tx_lock_flag) { | ||
256 | atomic_add(aggr_num * 2, &adapter->tx_queued); | ||
257 | skb_queue_tail(&adapter->tx_data_q, skb_aggr); | ||
258 | return 0; | ||
259 | } | ||
254 | 260 | ||
255 | if (adapter->iface_type == MWIFIEX_USB) { | 261 | if (adapter->iface_type == MWIFIEX_USB) { |
256 | adapter->data_sent = true; | 262 | adapter->data_sent = true; |
diff --git a/drivers/net/wireless/mwifiex/decl.h b/drivers/net/wireless/mwifiex/decl.h index cf2fa110e251..6ce19bed0e91 100644 --- a/drivers/net/wireless/mwifiex/decl.h +++ b/drivers/net/wireless/mwifiex/decl.h | |||
@@ -83,6 +83,7 @@ | |||
83 | #define MWIFIEX_BUF_FLAG_TDLS_PKT BIT(2) | 83 | #define MWIFIEX_BUF_FLAG_TDLS_PKT BIT(2) |
84 | #define MWIFIEX_BUF_FLAG_EAPOL_TX_STATUS BIT(3) | 84 | #define MWIFIEX_BUF_FLAG_EAPOL_TX_STATUS BIT(3) |
85 | #define MWIFIEX_BUF_FLAG_ACTION_TX_STATUS BIT(4) | 85 | #define MWIFIEX_BUF_FLAG_ACTION_TX_STATUS BIT(4) |
86 | #define MWIFIEX_BUF_FLAG_AGGR_PKT BIT(5) | ||
86 | 87 | ||
87 | #define MWIFIEX_BRIDGED_PKTS_THR_HIGH 1024 | 88 | #define MWIFIEX_BRIDGED_PKTS_THR_HIGH 1024 |
88 | #define MWIFIEX_BRIDGED_PKTS_THR_LOW 128 | 89 | #define MWIFIEX_BRIDGED_PKTS_THR_LOW 128 |
@@ -179,6 +180,7 @@ struct mwifiex_txinfo { | |||
179 | u8 flags; | 180 | u8 flags; |
180 | u8 bss_num; | 181 | u8 bss_num; |
181 | u8 bss_type; | 182 | u8 bss_type; |
183 | u8 aggr_num; | ||
182 | u32 pkt_len; | 184 | u32 pkt_len; |
183 | u8 ack_frame_id; | 185 | u8 ack_frame_id; |
184 | u64 cookie; | 186 | u64 cookie; |
diff --git a/drivers/net/wireless/mwifiex/init.c b/drivers/net/wireless/mwifiex/init.c index 0153ce6d5879..6936de8c8a94 100644 --- a/drivers/net/wireless/mwifiex/init.c +++ b/drivers/net/wireless/mwifiex/init.c | |||
@@ -481,6 +481,7 @@ int mwifiex_init_lock_list(struct mwifiex_adapter *adapter) | |||
481 | spin_lock_init(&adapter->rx_proc_lock); | 481 | spin_lock_init(&adapter->rx_proc_lock); |
482 | 482 | ||
483 | skb_queue_head_init(&adapter->rx_data_q); | 483 | skb_queue_head_init(&adapter->rx_data_q); |
484 | skb_queue_head_init(&adapter->tx_data_q); | ||
484 | 485 | ||
485 | for (i = 0; i < adapter->priv_num; ++i) { | 486 | for (i = 0; i < adapter->priv_num; ++i) { |
486 | INIT_LIST_HEAD(&adapter->bss_prio_tbl[i].bss_prio_head); | 487 | INIT_LIST_HEAD(&adapter->bss_prio_tbl[i].bss_prio_head); |
@@ -688,6 +689,10 @@ mwifiex_shutdown_drv(struct mwifiex_adapter *adapter) | |||
688 | } | 689 | } |
689 | } | 690 | } |
690 | 691 | ||
692 | atomic_set(&adapter->tx_queued, 0); | ||
693 | while ((skb = skb_dequeue(&adapter->tx_data_q))) | ||
694 | mwifiex_write_data_complete(adapter, skb, 0, 0); | ||
695 | |||
691 | spin_lock_irqsave(&adapter->rx_proc_lock, flags); | 696 | spin_lock_irqsave(&adapter->rx_proc_lock, flags); |
692 | 697 | ||
693 | while ((skb = skb_dequeue(&adapter->rx_data_q))) { | 698 | while ((skb = skb_dequeue(&adapter->rx_data_q))) { |
diff --git a/drivers/net/wireless/mwifiex/main.c b/drivers/net/wireless/mwifiex/main.c index d96d60a7ae7c..b242c3e8df3f 100644 --- a/drivers/net/wireless/mwifiex/main.c +++ b/drivers/net/wireless/mwifiex/main.c | |||
@@ -262,6 +262,7 @@ process_start: | |||
262 | (adapter->pm_wakeup_card_req && | 262 | (adapter->pm_wakeup_card_req && |
263 | !adapter->pm_wakeup_fw_try) && | 263 | !adapter->pm_wakeup_fw_try) && |
264 | (is_command_pending(adapter) || | 264 | (is_command_pending(adapter) || |
265 | !skb_queue_empty(&adapter->tx_data_q) || | ||
265 | !mwifiex_wmm_lists_empty(adapter))) { | 266 | !mwifiex_wmm_lists_empty(adapter))) { |
266 | adapter->pm_wakeup_fw_try = true; | 267 | adapter->pm_wakeup_fw_try = true; |
267 | mod_timer(&adapter->wakeup_timer, jiffies + (HZ*3)); | 268 | mod_timer(&adapter->wakeup_timer, jiffies + (HZ*3)); |
@@ -286,7 +287,8 @@ process_start: | |||
286 | 287 | ||
287 | if ((!adapter->scan_chan_gap_enabled && | 288 | if ((!adapter->scan_chan_gap_enabled && |
288 | adapter->scan_processing) || adapter->data_sent || | 289 | adapter->scan_processing) || adapter->data_sent || |
289 | mwifiex_wmm_lists_empty(adapter)) { | 290 | (mwifiex_wmm_lists_empty(adapter) && |
291 | skb_queue_empty(&adapter->tx_data_q))) { | ||
290 | if (adapter->cmd_sent || adapter->curr_cmd || | 292 | if (adapter->cmd_sent || adapter->curr_cmd || |
291 | (!is_command_pending(adapter))) | 293 | (!is_command_pending(adapter))) |
292 | break; | 294 | break; |
@@ -338,6 +340,20 @@ process_start: | |||
338 | 340 | ||
339 | if ((adapter->scan_chan_gap_enabled || | 341 | if ((adapter->scan_chan_gap_enabled || |
340 | !adapter->scan_processing) && | 342 | !adapter->scan_processing) && |
343 | !adapter->data_sent && | ||
344 | !skb_queue_empty(&adapter->tx_data_q)) { | ||
345 | mwifiex_process_tx_queue(adapter); | ||
346 | if (adapter->hs_activated) { | ||
347 | adapter->is_hs_configured = false; | ||
348 | mwifiex_hs_activated_event | ||
349 | (mwifiex_get_priv | ||
350 | (adapter, MWIFIEX_BSS_ROLE_ANY), | ||
351 | false); | ||
352 | } | ||
353 | } | ||
354 | |||
355 | if ((adapter->scan_chan_gap_enabled || | ||
356 | !adapter->scan_processing) && | ||
341 | !adapter->data_sent && !mwifiex_wmm_lists_empty(adapter)) { | 357 | !adapter->data_sent && !mwifiex_wmm_lists_empty(adapter)) { |
342 | mwifiex_wmm_process_tx(adapter); | 358 | mwifiex_wmm_process_tx(adapter); |
343 | if (adapter->hs_activated) { | 359 | if (adapter->hs_activated) { |
@@ -351,7 +367,8 @@ process_start: | |||
351 | 367 | ||
352 | if (adapter->delay_null_pkt && !adapter->cmd_sent && | 368 | if (adapter->delay_null_pkt && !adapter->cmd_sent && |
353 | !adapter->curr_cmd && !is_command_pending(adapter) && | 369 | !adapter->curr_cmd && !is_command_pending(adapter) && |
354 | mwifiex_wmm_lists_empty(adapter)) { | 370 | (mwifiex_wmm_lists_empty(adapter) && |
371 | skb_queue_empty(&adapter->tx_data_q))) { | ||
355 | if (!mwifiex_send_null_packet | 372 | if (!mwifiex_send_null_packet |
356 | (mwifiex_get_priv(adapter, MWIFIEX_BSS_ROLE_STA), | 373 | (mwifiex_get_priv(adapter, MWIFIEX_BSS_ROLE_STA), |
357 | MWIFIEX_TxPD_POWER_MGMT_NULL_PACKET | | 374 | MWIFIEX_TxPD_POWER_MGMT_NULL_PACKET | |
diff --git a/drivers/net/wireless/mwifiex/main.h b/drivers/net/wireless/mwifiex/main.h index 439db1734904..11db09c73e85 100644 --- a/drivers/net/wireless/mwifiex/main.h +++ b/drivers/net/wireless/mwifiex/main.h | |||
@@ -59,6 +59,8 @@ enum { | |||
59 | 59 | ||
60 | #define MWIFIEX_MAX_AP 64 | 60 | #define MWIFIEX_MAX_AP 64 |
61 | 61 | ||
62 | #define MWIFIEX_MAX_PKTS_TXQ 16 | ||
63 | |||
62 | #define MWIFIEX_DEFAULT_WATCHDOG_TIMEOUT (5 * HZ) | 64 | #define MWIFIEX_DEFAULT_WATCHDOG_TIMEOUT (5 * HZ) |
63 | 65 | ||
64 | #define MWIFIEX_TIMER_10S 10000 | 66 | #define MWIFIEX_TIMER_10S 10000 |
@@ -819,6 +821,8 @@ struct mwifiex_adapter { | |||
819 | spinlock_t scan_pending_q_lock; | 821 | spinlock_t scan_pending_q_lock; |
820 | /* spin lock for RX processing routine */ | 822 | /* spin lock for RX processing routine */ |
821 | spinlock_t rx_proc_lock; | 823 | spinlock_t rx_proc_lock; |
824 | struct sk_buff_head tx_data_q; | ||
825 | atomic_t tx_queued; | ||
822 | u32 scan_processing; | 826 | u32 scan_processing; |
823 | u16 region_code; | 827 | u16 region_code; |
824 | struct mwifiex_802_11d_domain_reg domain_reg; | 828 | struct mwifiex_802_11d_domain_reg domain_reg; |
@@ -905,6 +909,8 @@ struct mwifiex_adapter { | |||
905 | bool auto_tdls; | 909 | bool auto_tdls; |
906 | }; | 910 | }; |
907 | 911 | ||
912 | void mwifiex_process_tx_queue(struct mwifiex_adapter *adapter); | ||
913 | |||
908 | int mwifiex_init_lock_list(struct mwifiex_adapter *adapter); | 914 | int mwifiex_init_lock_list(struct mwifiex_adapter *adapter); |
909 | 915 | ||
910 | void mwifiex_set_trans_start(struct net_device *dev); | 916 | void mwifiex_set_trans_start(struct net_device *dev); |
diff --git a/drivers/net/wireless/mwifiex/txrx.c b/drivers/net/wireless/mwifiex/txrx.c index ea4549f0e0b9..4d43371583cf 100644 --- a/drivers/net/wireless/mwifiex/txrx.c +++ b/drivers/net/wireless/mwifiex/txrx.c | |||
@@ -92,6 +92,12 @@ int mwifiex_process_tx(struct mwifiex_private *priv, struct sk_buff *skb, | |||
92 | else | 92 | else |
93 | head_ptr = mwifiex_process_sta_txpd(priv, skb); | 93 | head_ptr = mwifiex_process_sta_txpd(priv, skb); |
94 | 94 | ||
95 | if ((adapter->data_sent || adapter->tx_lock_flag) && head_ptr) { | ||
96 | skb_queue_tail(&adapter->tx_data_q, skb); | ||
97 | atomic_inc(&adapter->tx_queued); | ||
98 | return 0; | ||
99 | } | ||
100 | |||
95 | if (head_ptr) { | 101 | if (head_ptr) { |
96 | if (GET_BSS_ROLE(priv) == MWIFIEX_BSS_ROLE_STA) | 102 | if (GET_BSS_ROLE(priv) == MWIFIEX_BSS_ROLE_STA) |
97 | local_tx_pd = (struct txpd *)(head_ptr + hroom); | 103 | local_tx_pd = (struct txpd *)(head_ptr + hroom); |
@@ -142,6 +148,123 @@ int mwifiex_process_tx(struct mwifiex_private *priv, struct sk_buff *skb, | |||
142 | return ret; | 148 | return ret; |
143 | } | 149 | } |
144 | 150 | ||
151 | static int mwifiex_host_to_card(struct mwifiex_adapter *adapter, | ||
152 | struct sk_buff *skb, | ||
153 | struct mwifiex_tx_param *tx_param) | ||
154 | { | ||
155 | struct txpd *local_tx_pd = NULL; | ||
156 | u8 *head_ptr = skb->data; | ||
157 | int ret = 0; | ||
158 | struct mwifiex_private *priv; | ||
159 | struct mwifiex_txinfo *tx_info; | ||
160 | |||
161 | tx_info = MWIFIEX_SKB_TXCB(skb); | ||
162 | priv = mwifiex_get_priv_by_id(adapter, tx_info->bss_num, | ||
163 | tx_info->bss_type); | ||
164 | if (!priv) { | ||
165 | dev_err(adapter->dev, "data: priv not found. Drop TX packet\n"); | ||
166 | adapter->dbg.num_tx_host_to_card_failure++; | ||
167 | mwifiex_write_data_complete(adapter, skb, 0, 0); | ||
168 | return ret; | ||
169 | } | ||
170 | if (GET_BSS_ROLE(priv) == MWIFIEX_BSS_ROLE_STA) { | ||
171 | if (adapter->iface_type == MWIFIEX_USB) | ||
172 | local_tx_pd = (struct txpd *)head_ptr; | ||
173 | else | ||
174 | local_tx_pd = (struct txpd *) (head_ptr + | ||
175 | INTF_HEADER_LEN); | ||
176 | } | ||
177 | |||
178 | if (adapter->iface_type == MWIFIEX_USB) { | ||
179 | adapter->data_sent = true; | ||
180 | ret = adapter->if_ops.host_to_card(adapter, | ||
181 | MWIFIEX_USB_EP_DATA, | ||
182 | skb, NULL); | ||
183 | } else { | ||
184 | ret = adapter->if_ops.host_to_card(adapter, | ||
185 | MWIFIEX_TYPE_DATA, | ||
186 | skb, tx_param); | ||
187 | } | ||
188 | switch (ret) { | ||
189 | case -ENOSR: | ||
190 | dev_err(adapter->dev, "data: -ENOSR is returned\n"); | ||
191 | break; | ||
192 | case -EBUSY: | ||
193 | if ((GET_BSS_ROLE(priv) == MWIFIEX_BSS_ROLE_STA) && | ||
194 | (adapter->pps_uapsd_mode) && | ||
195 | (adapter->tx_lock_flag)) { | ||
196 | priv->adapter->tx_lock_flag = false; | ||
197 | if (local_tx_pd) | ||
198 | local_tx_pd->flags = 0; | ||
199 | } | ||
200 | skb_queue_head(&adapter->tx_data_q, skb); | ||
201 | if (tx_info->flags & MWIFIEX_BUF_FLAG_AGGR_PKT) | ||
202 | atomic_add(tx_info->aggr_num, &adapter->tx_queued); | ||
203 | else | ||
204 | atomic_inc(&adapter->tx_queued); | ||
205 | dev_dbg(adapter->dev, "data: -EBUSY is returned\n"); | ||
206 | break; | ||
207 | case -1: | ||
208 | if (adapter->iface_type != MWIFIEX_PCIE) | ||
209 | adapter->data_sent = false; | ||
210 | dev_err(adapter->dev, "mwifiex_write_data_async failed: 0x%X\n", | ||
211 | ret); | ||
212 | adapter->dbg.num_tx_host_to_card_failure++; | ||
213 | mwifiex_write_data_complete(adapter, skb, 0, ret); | ||
214 | break; | ||
215 | case -EINPROGRESS: | ||
216 | if (adapter->iface_type != MWIFIEX_PCIE) | ||
217 | adapter->data_sent = false; | ||
218 | break; | ||
219 | case 0: | ||
220 | mwifiex_write_data_complete(adapter, skb, 0, ret); | ||
221 | break; | ||
222 | default: | ||
223 | break; | ||
224 | } | ||
225 | return ret; | ||
226 | } | ||
227 | |||
228 | static int | ||
229 | mwifiex_dequeue_tx_queue(struct mwifiex_adapter *adapter) | ||
230 | { | ||
231 | struct sk_buff *skb, *skb_next; | ||
232 | struct mwifiex_txinfo *tx_info; | ||
233 | struct mwifiex_tx_param tx_param; | ||
234 | |||
235 | skb = skb_dequeue(&adapter->tx_data_q); | ||
236 | if (!skb) | ||
237 | return -1; | ||
238 | |||
239 | tx_info = MWIFIEX_SKB_TXCB(skb); | ||
240 | if (tx_info->flags & MWIFIEX_BUF_FLAG_AGGR_PKT) | ||
241 | atomic_sub(tx_info->aggr_num, &adapter->tx_queued); | ||
242 | else | ||
243 | atomic_dec(&adapter->tx_queued); | ||
244 | |||
245 | if (!skb_queue_empty(&adapter->tx_data_q)) | ||
246 | skb_next = skb_peek(&adapter->tx_data_q); | ||
247 | else | ||
248 | skb_next = NULL; | ||
249 | tx_param.next_pkt_len = ((skb_next) ? skb_next->len : 0); | ||
250 | if (!tx_param.next_pkt_len) { | ||
251 | if (!mwifiex_wmm_lists_empty(adapter)) | ||
252 | tx_param.next_pkt_len = 1; | ||
253 | } | ||
254 | return mwifiex_host_to_card(adapter, skb, &tx_param); | ||
255 | } | ||
256 | |||
257 | void | ||
258 | mwifiex_process_tx_queue(struct mwifiex_adapter *adapter) | ||
259 | { | ||
260 | do { | ||
261 | if (adapter->data_sent || adapter->tx_lock_flag) | ||
262 | break; | ||
263 | if (mwifiex_dequeue_tx_queue(adapter)) | ||
264 | break; | ||
265 | } while (!skb_queue_empty(&adapter->tx_data_q)); | ||
266 | } | ||
267 | |||
145 | /* | 268 | /* |
146 | * Packet send completion callback handler. | 269 | * Packet send completion callback handler. |
147 | * | 270 | * |
@@ -181,6 +304,8 @@ int mwifiex_write_data_complete(struct mwifiex_adapter *adapter, | |||
181 | 304 | ||
182 | if (tx_info->flags & MWIFIEX_BUF_FLAG_BRIDGED_PKT) | 305 | if (tx_info->flags & MWIFIEX_BUF_FLAG_BRIDGED_PKT) |
183 | atomic_dec_return(&adapter->pending_bridged_pkts); | 306 | atomic_dec_return(&adapter->pending_bridged_pkts); |
307 | if (tx_info->flags & MWIFIEX_BUF_FLAG_AGGR_PKT) | ||
308 | goto done; | ||
184 | 309 | ||
185 | if (aggr) | 310 | if (aggr) |
186 | /* For skb_aggr, do not wake up tx queue */ | 311 | /* For skb_aggr, do not wake up tx queue */ |
diff --git a/drivers/net/wireless/mwifiex/wmm.c b/drivers/net/wireless/mwifiex/wmm.c index a6db12cae769..b2e99569a0f8 100644 --- a/drivers/net/wireless/mwifiex/wmm.c +++ b/drivers/net/wireless/mwifiex/wmm.c | |||
@@ -1174,6 +1174,14 @@ mwifiex_send_processed_packet(struct mwifiex_private *priv, | |||
1174 | 1174 | ||
1175 | skb = skb_dequeue(&ptr->skb_head); | 1175 | skb = skb_dequeue(&ptr->skb_head); |
1176 | 1176 | ||
1177 | if (adapter->data_sent || adapter->tx_lock_flag) { | ||
1178 | spin_unlock_irqrestore(&priv->wmm.ra_list_spinlock, | ||
1179 | ra_list_flags); | ||
1180 | skb_queue_tail(&adapter->tx_data_q, skb); | ||
1181 | atomic_inc(&adapter->tx_queued); | ||
1182 | return; | ||
1183 | } | ||
1184 | |||
1177 | if (!skb_queue_empty(&ptr->skb_head)) | 1185 | if (!skb_queue_empty(&ptr->skb_head)) |
1178 | skb_next = skb_peek(&ptr->skb_head); | 1186 | skb_next = skb_peek(&ptr->skb_head); |
1179 | else | 1187 | else |
@@ -1324,11 +1332,16 @@ void | |||
1324 | mwifiex_wmm_process_tx(struct mwifiex_adapter *adapter) | 1332 | mwifiex_wmm_process_tx(struct mwifiex_adapter *adapter) |
1325 | { | 1333 | { |
1326 | do { | 1334 | do { |
1327 | /* Check if busy */ | ||
1328 | if (adapter->data_sent || adapter->tx_lock_flag) | ||
1329 | break; | ||
1330 | |||
1331 | if (mwifiex_dequeue_tx_packet(adapter)) | 1335 | if (mwifiex_dequeue_tx_packet(adapter)) |
1332 | break; | 1336 | break; |
1337 | if (adapter->iface_type != MWIFIEX_SDIO) { | ||
1338 | if (adapter->data_sent || | ||
1339 | adapter->tx_lock_flag) | ||
1340 | break; | ||
1341 | } else { | ||
1342 | if (atomic_read(&adapter->tx_queued) >= | ||
1343 | MWIFIEX_MAX_PKTS_TXQ) | ||
1344 | break; | ||
1345 | } | ||
1333 | } while (!mwifiex_wmm_lists_empty(adapter)); | 1346 | } while (!mwifiex_wmm_lists_empty(adapter)); |
1334 | } | 1347 | } |