aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAvinash Patil <patila@marvell.com>2012-11-01 21:44:16 -0400
committerJohn W. Linville <linville@tuxdriver.com>2012-11-14 14:55:37 -0500
commit47411a06c0c44b3c9dc2feffb0d97785ec9aaa68 (patch)
tree4464ca983493e93fb688eb471d7c28ec0be78fa6
parentd31ab3577eca0f74126ceb1d406710e620a155a0 (diff)
mwifiex: add multi-queue support
This patch adds support for multiple TX queues inside mwifiex driver. Four different queues according to WMM access categories are defined for each virtual interface. When a packet is received from netdev for transmission, tx pending count for particular queue is incremented and if tx pending count has reached upper water-mark, this queue is stopped instead of stopping all queues. Similarly when a packet is successfully transmitted from device, tx pending count is decremented per queue and if pending count falls below lower water-mark, queue operations are again resumed. This ensures that not all tranmission is blocked if traffic with particular TOS value suddenly increases. Also wake all queues after association/IBSS_join/uAP_BSS_start to enable traffic on all queues. Signed-off-by: Avinash Patil <patila@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/11n_aggr.c8
-rw-r--r--drivers/net/wireless/mwifiex/cfg80211.c7
-rw-r--r--drivers/net/wireless/mwifiex/debugfs.c10
-rw-r--r--drivers/net/wireless/mwifiex/init.c20
-rw-r--r--drivers/net/wireless/mwifiex/join.c6
-rw-r--r--drivers/net/wireless/mwifiex/main.c85
-rw-r--r--drivers/net/wireless/mwifiex/main.h3
-rw-r--r--drivers/net/wireless/mwifiex/sta_event.c9
-rw-r--r--drivers/net/wireless/mwifiex/sta_ioctl.c6
-rw-r--r--drivers/net/wireless/mwifiex/txrx.c28
-rw-r--r--drivers/net/wireless/mwifiex/uap_event.c7
-rw-r--r--drivers/net/wireless/mwifiex/usb.c2
-rw-r--r--drivers/net/wireless/mwifiex/wmm.c12
-rw-r--r--drivers/net/wireless/mwifiex/wmm.h2
14 files changed, 107 insertions, 98 deletions
diff --git a/drivers/net/wireless/mwifiex/11n_aggr.c b/drivers/net/wireless/mwifiex/11n_aggr.c
index 395f1bfd4102..68d52cfc1ebd 100644
--- a/drivers/net/wireless/mwifiex/11n_aggr.c
+++ b/drivers/net/wireless/mwifiex/11n_aggr.c
@@ -197,7 +197,7 @@ mwifiex_11n_aggregate_pkt(struct mwifiex_private *priv,
197 ra_list_flags); 197 ra_list_flags);
198 mwifiex_11n_form_amsdu_pkt(skb_aggr, skb_src, &pad); 198 mwifiex_11n_form_amsdu_pkt(skb_aggr, skb_src, &pad);
199 199
200 mwifiex_write_data_complete(adapter, skb_src, 0); 200 mwifiex_write_data_complete(adapter, skb_src, 0, 0);
201 201
202 spin_lock_irqsave(&priv->wmm.ra_list_spinlock, ra_list_flags); 202 spin_lock_irqsave(&priv->wmm.ra_list_spinlock, ra_list_flags);
203 203
@@ -256,7 +256,7 @@ mwifiex_11n_aggregate_pkt(struct mwifiex_private *priv,
256 if (!mwifiex_is_ralist_valid(priv, pra_list, ptrindex)) { 256 if (!mwifiex_is_ralist_valid(priv, pra_list, ptrindex)) {
257 spin_unlock_irqrestore(&priv->wmm.ra_list_spinlock, 257 spin_unlock_irqrestore(&priv->wmm.ra_list_spinlock,
258 ra_list_flags); 258 ra_list_flags);
259 mwifiex_write_data_complete(adapter, skb_aggr, -1); 259 mwifiex_write_data_complete(adapter, skb_aggr, 1, -1);
260 return -1; 260 return -1;
261 } 261 }
262 if (GET_BSS_ROLE(priv) == MWIFIEX_BSS_ROLE_STA && 262 if (GET_BSS_ROLE(priv) == MWIFIEX_BSS_ROLE_STA &&
@@ -282,13 +282,13 @@ mwifiex_11n_aggregate_pkt(struct mwifiex_private *priv,
282 dev_err(adapter->dev, "%s: host_to_card failed: %#x\n", 282 dev_err(adapter->dev, "%s: host_to_card failed: %#x\n",
283 __func__, ret); 283 __func__, ret);
284 adapter->dbg.num_tx_host_to_card_failure++; 284 adapter->dbg.num_tx_host_to_card_failure++;
285 mwifiex_write_data_complete(adapter, skb_aggr, ret); 285 mwifiex_write_data_complete(adapter, skb_aggr, 1, ret);
286 return 0; 286 return 0;
287 case -EINPROGRESS: 287 case -EINPROGRESS:
288 adapter->data_sent = false; 288 adapter->data_sent = false;
289 break; 289 break;
290 case 0: 290 case 0:
291 mwifiex_write_data_complete(adapter, skb_aggr, ret); 291 mwifiex_write_data_complete(adapter, skb_aggr, 1, ret);
292 break; 292 break;
293 default: 293 default:
294 break; 294 break;
diff --git a/drivers/net/wireless/mwifiex/cfg80211.c b/drivers/net/wireless/mwifiex/cfg80211.c
index fdb1eb861021..e29505c90cce 100644
--- a/drivers/net/wireless/mwifiex/cfg80211.c
+++ b/drivers/net/wireless/mwifiex/cfg80211.c
@@ -2080,8 +2080,8 @@ struct wireless_dev *mwifiex_add_virtual_intf(struct wiphy *wiphy,
2080 return ERR_PTR(-EINVAL); 2080 return ERR_PTR(-EINVAL);
2081 } 2081 }
2082 2082
2083 dev = alloc_netdev_mq(sizeof(struct mwifiex_private *), name, 2083 dev = alloc_netdev_mqs(sizeof(struct mwifiex_private *), name,
2084 ether_setup, 1); 2084 ether_setup, IEEE80211_NUM_ACS, 1);
2085 if (!dev) { 2085 if (!dev) {
2086 wiphy_err(wiphy, "no memory available for netdevice\n"); 2086 wiphy_err(wiphy, "no memory available for netdevice\n");
2087 priv->bss_mode = NL80211_IFTYPE_UNSPECIFIED; 2087 priv->bss_mode = NL80211_IFTYPE_UNSPECIFIED;
@@ -2143,8 +2143,7 @@ int mwifiex_del_virtual_intf(struct wiphy *wiphy, struct wireless_dev *wdev)
2143 mwifiex_dev_debugfs_remove(priv); 2143 mwifiex_dev_debugfs_remove(priv);
2144#endif 2144#endif
2145 2145
2146 if (!netif_queue_stopped(priv->netdev)) 2146 mwifiex_stop_net_dev_queue(priv->netdev, priv->adapter);
2147 netif_stop_queue(priv->netdev);
2148 2147
2149 if (netif_carrier_ok(priv->netdev)) 2148 if (netif_carrier_ok(priv->netdev))
2150 netif_carrier_off(priv->netdev); 2149 netif_carrier_off(priv->netdev);
diff --git a/drivers/net/wireless/mwifiex/debugfs.c b/drivers/net/wireless/mwifiex/debugfs.c
index a870b5885c09..46e34aa65d1c 100644
--- a/drivers/net/wireless/mwifiex/debugfs.c
+++ b/drivers/net/wireless/mwifiex/debugfs.c
@@ -178,6 +178,7 @@ mwifiex_info_read(struct file *file, char __user *ubuf,
178 (struct mwifiex_private *) file->private_data; 178 (struct mwifiex_private *) file->private_data;
179 struct net_device *netdev = priv->netdev; 179 struct net_device *netdev = priv->netdev;
180 struct netdev_hw_addr *ha; 180 struct netdev_hw_addr *ha;
181 struct netdev_queue *txq;
181 unsigned long page = get_zeroed_page(GFP_KERNEL); 182 unsigned long page = get_zeroed_page(GFP_KERNEL);
182 char *p = (char *) page, fmt[64]; 183 char *p = (char *) page, fmt[64];
183 struct mwifiex_bss_info info; 184 struct mwifiex_bss_info info;
@@ -229,8 +230,13 @@ mwifiex_info_read(struct file *file, char __user *ubuf,
229 p += sprintf(p, "num_rx_pkts_err = %lu\n", priv->stats.rx_errors); 230 p += sprintf(p, "num_rx_pkts_err = %lu\n", priv->stats.rx_errors);
230 p += sprintf(p, "carrier %s\n", ((netif_carrier_ok(priv->netdev)) 231 p += sprintf(p, "carrier %s\n", ((netif_carrier_ok(priv->netdev))
231 ? "on" : "off")); 232 ? "on" : "off"));
232 p += sprintf(p, "tx queue %s\n", ((netif_queue_stopped(priv->netdev)) 233 p += sprintf(p, "tx queue");
233 ? "stopped" : "started")); 234 for (i = 0; i < netdev->num_tx_queues; i++) {
235 txq = netdev_get_tx_queue(netdev, i);
236 p += sprintf(p, " %d:%s", i, netif_tx_queue_stopped(txq) ?
237 "stopped" : "started");
238 }
239 p += sprintf(p, "\n");
234 240
235 ret = simple_read_from_buffer(ubuf, count, ppos, (char *) page, 241 ret = simple_read_from_buffer(ubuf, count, ppos, (char *) page,
236 (unsigned long) p - page); 242 (unsigned long) p - page);
diff --git a/drivers/net/wireless/mwifiex/init.c b/drivers/net/wireless/mwifiex/init.c
index 482faace7900..39f03ce5a5b1 100644
--- a/drivers/net/wireless/mwifiex/init.c
+++ b/drivers/net/wireless/mwifiex/init.c
@@ -388,9 +388,17 @@ void mwifiex_wake_up_net_dev_queue(struct net_device *netdev,
388 struct mwifiex_adapter *adapter) 388 struct mwifiex_adapter *adapter)
389{ 389{
390 unsigned long dev_queue_flags; 390 unsigned long dev_queue_flags;
391 unsigned int i;
391 392
392 spin_lock_irqsave(&adapter->queue_lock, dev_queue_flags); 393 spin_lock_irqsave(&adapter->queue_lock, dev_queue_flags);
393 netif_tx_wake_all_queues(netdev); 394
395 for (i = 0; i < netdev->num_tx_queues; i++) {
396 struct netdev_queue *txq = netdev_get_tx_queue(netdev, i);
397
398 if (netif_tx_queue_stopped(txq))
399 netif_tx_wake_queue(txq);
400 }
401
394 spin_unlock_irqrestore(&adapter->queue_lock, dev_queue_flags); 402 spin_unlock_irqrestore(&adapter->queue_lock, dev_queue_flags);
395} 403}
396 404
@@ -401,9 +409,17 @@ void mwifiex_stop_net_dev_queue(struct net_device *netdev,
401 struct mwifiex_adapter *adapter) 409 struct mwifiex_adapter *adapter)
402{ 410{
403 unsigned long dev_queue_flags; 411 unsigned long dev_queue_flags;
412 unsigned int i;
404 413
405 spin_lock_irqsave(&adapter->queue_lock, dev_queue_flags); 414 spin_lock_irqsave(&adapter->queue_lock, dev_queue_flags);
406 netif_tx_stop_all_queues(netdev); 415
416 for (i = 0; i < netdev->num_tx_queues; i++) {
417 struct netdev_queue *txq = netdev_get_tx_queue(netdev, i);
418
419 if (!netif_tx_queue_stopped(txq))
420 netif_tx_stop_queue(txq);
421 }
422
407 spin_unlock_irqrestore(&adapter->queue_lock, dev_queue_flags); 423 spin_unlock_irqrestore(&adapter->queue_lock, dev_queue_flags);
408} 424}
409 425
diff --git a/drivers/net/wireless/mwifiex/join.c b/drivers/net/wireless/mwifiex/join.c
index 7b0858af8f5d..88664ae667ba 100644
--- a/drivers/net/wireless/mwifiex/join.c
+++ b/drivers/net/wireless/mwifiex/join.c
@@ -721,8 +721,7 @@ int mwifiex_ret_802_11_associate(struct mwifiex_private *priv,
721 721
722 if (!netif_carrier_ok(priv->netdev)) 722 if (!netif_carrier_ok(priv->netdev))
723 netif_carrier_on(priv->netdev); 723 netif_carrier_on(priv->netdev);
724 if (netif_queue_stopped(priv->netdev)) 724 mwifiex_wake_up_net_dev_queue(priv->netdev, adapter);
725 netif_wake_queue(priv->netdev);
726 725
727 if (priv->sec_info.wpa_enabled || priv->sec_info.wpa2_enabled) 726 if (priv->sec_info.wpa_enabled || priv->sec_info.wpa2_enabled)
728 priv->scan_block = true; 727 priv->scan_block = true;
@@ -1238,8 +1237,7 @@ int mwifiex_ret_802_11_ad_hoc(struct mwifiex_private *priv,
1238 1237
1239 if (!netif_carrier_ok(priv->netdev)) 1238 if (!netif_carrier_ok(priv->netdev))
1240 netif_carrier_on(priv->netdev); 1239 netif_carrier_on(priv->netdev);
1241 if (netif_queue_stopped(priv->netdev)) 1240 mwifiex_wake_up_net_dev_queue(priv->netdev, adapter);
1242 netif_wake_queue(priv->netdev);
1243 1241
1244 mwifiex_save_curr_bcn(priv); 1242 mwifiex_save_curr_bcn(priv);
1245 1243
diff --git a/drivers/net/wireless/mwifiex/main.c b/drivers/net/wireless/mwifiex/main.c
index 1df767bc8b6e..1afcd404a101 100644
--- a/drivers/net/wireless/mwifiex/main.c
+++ b/drivers/net/wireless/mwifiex/main.c
@@ -412,49 +412,6 @@ static int mwifiex_init_hw_fw(struct mwifiex_adapter *adapter)
412} 412}
413 413
414/* 414/*
415 * This function fills a driver buffer.
416 *
417 * The function associates a given SKB with the provided driver buffer
418 * and also updates some of the SKB parameters, including IP header,
419 * priority and timestamp.
420 */
421static void
422mwifiex_fill_buffer(struct sk_buff *skb)
423{
424 struct ethhdr *eth;
425 struct iphdr *iph;
426 struct timeval tv;
427 u8 tid = 0;
428
429 eth = (struct ethhdr *) skb->data;
430 switch (eth->h_proto) {
431 case __constant_htons(ETH_P_IP):
432 iph = ip_hdr(skb);
433 tid = IPTOS_PREC(iph->tos);
434 pr_debug("data: packet type ETH_P_IP: %04x, tid=%#x prio=%#x\n",
435 eth->h_proto, tid, skb->priority);
436 break;
437 case __constant_htons(ETH_P_ARP):
438 pr_debug("data: ARP packet: %04x\n", eth->h_proto);
439 default:
440 break;
441 }
442/* Offset for TOS field in the IP header */
443#define IPTOS_OFFSET 5
444 tid = (tid >> IPTOS_OFFSET);
445 skb->priority = tid;
446 /* Record the current time the packet was queued; used to
447 determine the amount of time the packet was queued in
448 the driver before it was sent to the firmware.
449 The delay is then sent along with the packet to the
450 firmware for aggregate delay calculation for stats and
451 MSDU lifetime expiry.
452 */
453 do_gettimeofday(&tv);
454 skb->tstamp = timeval_to_ktime(tv);
455}
456
457/*
458 * CFG802.11 network device handler for open. 415 * CFG802.11 network device handler for open.
459 * 416 *
460 * Starts the data queue. 417 * Starts the data queue.
@@ -488,17 +445,23 @@ mwifiex_close(struct net_device *dev)
488 */ 445 */
489int mwifiex_queue_tx_pkt(struct mwifiex_private *priv, struct sk_buff *skb) 446int mwifiex_queue_tx_pkt(struct mwifiex_private *priv, struct sk_buff *skb)
490{ 447{
491 mwifiex_wmm_add_buf_txqueue(priv, skb); 448 struct netdev_queue *txq;
449 int index = mwifiex_1d_to_wmm_queue[skb->priority];
450
451 if (atomic_inc_return(&priv->wmm_tx_pending[index]) >= MAX_TX_PENDING) {
452 txq = netdev_get_tx_queue(priv->netdev, index);
453 if (!netif_tx_queue_stopped(txq)) {
454 netif_tx_stop_queue(txq);
455 dev_dbg(priv->adapter->dev, "stop queue: %d\n", index);
456 }
457 }
458
492 atomic_inc(&priv->adapter->tx_pending); 459 atomic_inc(&priv->adapter->tx_pending);
460 mwifiex_wmm_add_buf_txqueue(priv, skb);
493 461
494 if (priv->adapter->scan_delay_cnt) 462 if (priv->adapter->scan_delay_cnt)
495 atomic_set(&priv->adapter->is_tx_received, true); 463 atomic_set(&priv->adapter->is_tx_received, true);
496 464
497 if (atomic_read(&priv->adapter->tx_pending) >= MAX_TX_PENDING) {
498 mwifiex_set_trans_start(priv->netdev);
499 mwifiex_stop_net_dev_queue(priv->netdev, priv->adapter);
500 }
501
502 queue_work(priv->adapter->workqueue, &priv->adapter->main_work); 465 queue_work(priv->adapter->workqueue, &priv->adapter->main_work);
503 466
504 return 0; 467 return 0;
@@ -513,6 +476,7 @@ mwifiex_hard_start_xmit(struct sk_buff *skb, struct net_device *dev)
513 struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev); 476 struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev);
514 struct sk_buff *new_skb; 477 struct sk_buff *new_skb;
515 struct mwifiex_txinfo *tx_info; 478 struct mwifiex_txinfo *tx_info;
479 struct timeval tv;
516 480
517 dev_dbg(priv->adapter->dev, "data: %lu BSS(%d-%d): Data <= kernel\n", 481 dev_dbg(priv->adapter->dev, "data: %lu BSS(%d-%d): Data <= kernel\n",
518 jiffies, priv->bss_type, priv->bss_num); 482 jiffies, priv->bss_type, priv->bss_num);
@@ -550,7 +514,16 @@ mwifiex_hard_start_xmit(struct sk_buff *skb, struct net_device *dev)
550 tx_info = MWIFIEX_SKB_TXCB(skb); 514 tx_info = MWIFIEX_SKB_TXCB(skb);
551 tx_info->bss_num = priv->bss_num; 515 tx_info->bss_num = priv->bss_num;
552 tx_info->bss_type = priv->bss_type; 516 tx_info->bss_type = priv->bss_type;
553 mwifiex_fill_buffer(skb); 517
518 /* Record the current time the packet was queued; used to
519 * determine the amount of time the packet was queued in
520 * the driver before it was sent to the firmware.
521 * The delay is then sent along with the packet to the
522 * firmware for aggregate delay calculation for stats and
523 * MSDU lifetime expiry.
524 */
525 do_gettimeofday(&tv);
526 skb->tstamp = timeval_to_ktime(tv);
554 527
555 mwifiex_queue_tx_pkt(priv, skb); 528 mwifiex_queue_tx_pkt(priv, skb);
556 529
@@ -630,6 +603,13 @@ static struct net_device_stats *mwifiex_get_stats(struct net_device *dev)
630 return &priv->stats; 603 return &priv->stats;
631} 604}
632 605
606static u16
607mwifiex_netdev_select_wmm_queue(struct net_device *dev, struct sk_buff *skb)
608{
609 skb->priority = cfg80211_classify8021d(skb);
610 return mwifiex_1d_to_wmm_queue[skb->priority];
611}
612
633/* Network device handlers */ 613/* Network device handlers */
634static const struct net_device_ops mwifiex_netdev_ops = { 614static const struct net_device_ops mwifiex_netdev_ops = {
635 .ndo_open = mwifiex_open, 615 .ndo_open = mwifiex_open,
@@ -639,6 +619,7 @@ static const struct net_device_ops mwifiex_netdev_ops = {
639 .ndo_tx_timeout = mwifiex_tx_timeout, 619 .ndo_tx_timeout = mwifiex_tx_timeout,
640 .ndo_get_stats = mwifiex_get_stats, 620 .ndo_get_stats = mwifiex_get_stats,
641 .ndo_set_rx_mode = mwifiex_set_multicast_list, 621 .ndo_set_rx_mode = mwifiex_set_multicast_list,
622 .ndo_select_queue = mwifiex_netdev_select_wmm_queue,
642}; 623};
643 624
644/* 625/*
@@ -838,9 +819,7 @@ int mwifiex_remove_card(struct mwifiex_adapter *adapter, struct semaphore *sem)
838 for (i = 0; i < adapter->priv_num; i++) { 819 for (i = 0; i < adapter->priv_num; i++) {
839 priv = adapter->priv[i]; 820 priv = adapter->priv[i];
840 if (priv && priv->netdev) { 821 if (priv && priv->netdev) {
841 if (!netif_queue_stopped(priv->netdev)) 822 mwifiex_stop_net_dev_queue(priv->netdev, adapter);
842 mwifiex_stop_net_dev_queue(priv->netdev,
843 adapter);
844 if (netif_carrier_ok(priv->netdev)) 823 if (netif_carrier_ok(priv->netdev))
845 netif_carrier_off(priv->netdev); 824 netif_carrier_off(priv->netdev);
846 } 825 }
diff --git a/drivers/net/wireless/mwifiex/main.h b/drivers/net/wireless/mwifiex/main.h
index 68f36462966b..db57dd430e92 100644
--- a/drivers/net/wireless/mwifiex/main.h
+++ b/drivers/net/wireless/mwifiex/main.h
@@ -440,6 +440,7 @@ struct mwifiex_private {
440 u8 wmm_enabled; 440 u8 wmm_enabled;
441 u8 wmm_qosinfo; 441 u8 wmm_qosinfo;
442 struct mwifiex_wmm_desc wmm; 442 struct mwifiex_wmm_desc wmm;
443 atomic_t wmm_tx_pending[IEEE80211_NUM_ACS];
443 struct list_head sta_list; 444 struct list_head sta_list;
444 /* spin lock for associated station list */ 445 /* spin lock for associated station list */
445 spinlock_t sta_list_spinlock; 446 spinlock_t sta_list_spinlock;
@@ -789,7 +790,7 @@ int mwifiex_process_tx(struct mwifiex_private *priv, struct sk_buff *skb,
789 struct mwifiex_tx_param *tx_param); 790 struct mwifiex_tx_param *tx_param);
790int mwifiex_send_null_packet(struct mwifiex_private *priv, u8 flags); 791int mwifiex_send_null_packet(struct mwifiex_private *priv, u8 flags);
791int mwifiex_write_data_complete(struct mwifiex_adapter *adapter, 792int mwifiex_write_data_complete(struct mwifiex_adapter *adapter,
792 struct sk_buff *skb, int status); 793 struct sk_buff *skb, int aggr, int status);
793void mwifiex_clean_txrx(struct mwifiex_private *priv); 794void mwifiex_clean_txrx(struct mwifiex_private *priv);
794u8 mwifiex_check_last_packet_indication(struct mwifiex_private *priv); 795u8 mwifiex_check_last_packet_indication(struct mwifiex_private *priv);
795void mwifiex_check_ps_cond(struct mwifiex_adapter *adapter); 796void mwifiex_check_ps_cond(struct mwifiex_adapter *adapter);
diff --git a/drivers/net/wireless/mwifiex/sta_event.c b/drivers/net/wireless/mwifiex/sta_event.c
index 8132119e1a21..5b0d71969ba7 100644
--- a/drivers/net/wireless/mwifiex/sta_event.c
+++ b/drivers/net/wireless/mwifiex/sta_event.c
@@ -124,8 +124,7 @@ mwifiex_reset_connect_state(struct mwifiex_private *priv, u16 reason_code)
124 } 124 }
125 memset(priv->cfg_bssid, 0, ETH_ALEN); 125 memset(priv->cfg_bssid, 0, ETH_ALEN);
126 126
127 if (!netif_queue_stopped(priv->netdev)) 127 mwifiex_stop_net_dev_queue(priv->netdev, adapter);
128 mwifiex_stop_net_dev_queue(priv->netdev, adapter);
129 if (netif_carrier_ok(priv->netdev)) 128 if (netif_carrier_ok(priv->netdev))
130 netif_carrier_off(priv->netdev); 129 netif_carrier_off(priv->netdev);
131} 130}
@@ -197,8 +196,7 @@ int mwifiex_process_sta_event(struct mwifiex_private *priv)
197 dev_dbg(adapter->dev, "event: LINK_SENSED\n"); 196 dev_dbg(adapter->dev, "event: LINK_SENSED\n");
198 if (!netif_carrier_ok(priv->netdev)) 197 if (!netif_carrier_ok(priv->netdev))
199 netif_carrier_on(priv->netdev); 198 netif_carrier_on(priv->netdev);
200 if (netif_queue_stopped(priv->netdev)) 199 mwifiex_wake_up_net_dev_queue(priv->netdev, adapter);
201 mwifiex_wake_up_net_dev_queue(priv->netdev, adapter);
202 break; 200 break;
203 201
204 case EVENT_DEAUTHENTICATED: 202 case EVENT_DEAUTHENTICATED:
@@ -306,8 +304,7 @@ int mwifiex_process_sta_event(struct mwifiex_private *priv)
306 dev_dbg(adapter->dev, "event: ADHOC_BCN_LOST\n"); 304 dev_dbg(adapter->dev, "event: ADHOC_BCN_LOST\n");
307 priv->adhoc_is_link_sensed = false; 305 priv->adhoc_is_link_sensed = false;
308 mwifiex_clean_txrx(priv); 306 mwifiex_clean_txrx(priv);
309 if (!netif_queue_stopped(priv->netdev)) 307 mwifiex_stop_net_dev_queue(priv->netdev, adapter);
310 mwifiex_stop_net_dev_queue(priv->netdev, adapter);
311 if (netif_carrier_ok(priv->netdev)) 308 if (netif_carrier_ok(priv->netdev))
312 netif_carrier_off(priv->netdev); 309 netif_carrier_off(priv->netdev);
313 break; 310 break;
diff --git a/drivers/net/wireless/mwifiex/sta_ioctl.c b/drivers/net/wireless/mwifiex/sta_ioctl.c
index 552d72ed055a..c8b50c70a03d 100644
--- a/drivers/net/wireless/mwifiex/sta_ioctl.c
+++ b/drivers/net/wireless/mwifiex/sta_ioctl.c
@@ -276,8 +276,7 @@ int mwifiex_bss_start(struct mwifiex_private *priv, struct cfg80211_bss *bss,
276 dev_dbg(adapter->dev, "info: SSID found in scan list ... " 276 dev_dbg(adapter->dev, "info: SSID found in scan list ... "
277 "associating...\n"); 277 "associating...\n");
278 278
279 if (!netif_queue_stopped(priv->netdev)) 279 mwifiex_stop_net_dev_queue(priv->netdev, adapter);
280 mwifiex_stop_net_dev_queue(priv->netdev, adapter);
281 if (netif_carrier_ok(priv->netdev)) 280 if (netif_carrier_ok(priv->netdev))
282 netif_carrier_off(priv->netdev); 281 netif_carrier_off(priv->netdev);
283 282
@@ -318,8 +317,7 @@ int mwifiex_bss_start(struct mwifiex_private *priv, struct cfg80211_bss *bss,
318 317
319 ret = mwifiex_check_network_compatibility(priv, bss_desc); 318 ret = mwifiex_check_network_compatibility(priv, bss_desc);
320 319
321 if (!netif_queue_stopped(priv->netdev)) 320 mwifiex_stop_net_dev_queue(priv->netdev, adapter);
322 mwifiex_stop_net_dev_queue(priv->netdev, adapter);
323 if (netif_carrier_ok(priv->netdev)) 321 if (netif_carrier_ok(priv->netdev))
324 netif_carrier_off(priv->netdev); 322 netif_carrier_off(priv->netdev);
325 323
diff --git a/drivers/net/wireless/mwifiex/txrx.c b/drivers/net/wireless/mwifiex/txrx.c
index 5cb3f7af8749..8c80024c30ff 100644
--- a/drivers/net/wireless/mwifiex/txrx.c
+++ b/drivers/net/wireless/mwifiex/txrx.c
@@ -121,13 +121,13 @@ int mwifiex_process_tx(struct mwifiex_private *priv, struct sk_buff *skb,
121 dev_err(adapter->dev, "mwifiex_write_data_async failed: 0x%X\n", 121 dev_err(adapter->dev, "mwifiex_write_data_async failed: 0x%X\n",
122 ret); 122 ret);
123 adapter->dbg.num_tx_host_to_card_failure++; 123 adapter->dbg.num_tx_host_to_card_failure++;
124 mwifiex_write_data_complete(adapter, skb, ret); 124 mwifiex_write_data_complete(adapter, skb, 0, ret);
125 break; 125 break;
126 case -EINPROGRESS: 126 case -EINPROGRESS:
127 adapter->data_sent = false; 127 adapter->data_sent = false;
128 break; 128 break;
129 case 0: 129 case 0:
130 mwifiex_write_data_complete(adapter, skb, ret); 130 mwifiex_write_data_complete(adapter, skb, 0, ret);
131 break; 131 break;
132 default: 132 default:
133 break; 133 break;
@@ -144,11 +144,12 @@ int mwifiex_process_tx(struct mwifiex_private *priv, struct sk_buff *skb,
144 * wakes up stalled traffic queue if required, and then frees the buffer. 144 * wakes up stalled traffic queue if required, and then frees the buffer.
145 */ 145 */
146int mwifiex_write_data_complete(struct mwifiex_adapter *adapter, 146int mwifiex_write_data_complete(struct mwifiex_adapter *adapter,
147 struct sk_buff *skb, int status) 147 struct sk_buff *skb, int aggr, int status)
148{ 148{
149 struct mwifiex_private *priv, *tpriv; 149 struct mwifiex_private *priv;
150 struct mwifiex_txinfo *tx_info; 150 struct mwifiex_txinfo *tx_info;
151 int i; 151 struct netdev_queue *txq;
152 int index;
152 153
153 if (!skb) 154 if (!skb)
154 return 0; 155 return 0;
@@ -172,15 +173,20 @@ int mwifiex_write_data_complete(struct mwifiex_adapter *adapter,
172 173
173 if (tx_info->flags & MWIFIEX_BUF_FLAG_BRIDGED_PKT) 174 if (tx_info->flags & MWIFIEX_BUF_FLAG_BRIDGED_PKT)
174 atomic_dec_return(&adapter->pending_bridged_pkts); 175 atomic_dec_return(&adapter->pending_bridged_pkts);
175 if (atomic_dec_return(&adapter->tx_pending) >= LOW_TX_PENDING) 176
177 if (aggr)
178 /* For skb_aggr, do not wake up tx queue */
176 goto done; 179 goto done;
177 180
178 for (i = 0; i < adapter->priv_num; i++) { 181 atomic_dec(&adapter->tx_pending);
179 tpriv = adapter->priv[i];
180 182
181 if (tpriv->media_connected && 183 index = mwifiex_1d_to_wmm_queue[skb->priority];
182 netif_queue_stopped(tpriv->netdev)) 184 if (atomic_dec_return(&priv->wmm_tx_pending[index]) < LOW_TX_PENDING) {
183 mwifiex_wake_up_net_dev_queue(tpriv->netdev, adapter); 185 txq = netdev_get_tx_queue(priv->netdev, index);
186 if (netif_tx_queue_stopped(txq)) {
187 netif_tx_wake_queue(txq);
188 dev_dbg(adapter->dev, "wake queue: %d\n", index);
189 }
184 } 190 }
185done: 191done:
186 dev_kfree_skb_any(skb); 192 dev_kfree_skb_any(skb);
diff --git a/drivers/net/wireless/mwifiex/uap_event.c b/drivers/net/wireless/mwifiex/uap_event.c
index a33fa394e349..21c640d3b579 100644
--- a/drivers/net/wireless/mwifiex/uap_event.c
+++ b/drivers/net/wireless/mwifiex/uap_event.c
@@ -235,11 +235,18 @@ int mwifiex_process_uap_event(struct mwifiex_private *priv)
235 break; 235 break;
236 case EVENT_UAP_BSS_IDLE: 236 case EVENT_UAP_BSS_IDLE:
237 priv->media_connected = false; 237 priv->media_connected = false;
238 if (netif_carrier_ok(priv->netdev))
239 netif_carrier_off(priv->netdev);
240 mwifiex_stop_net_dev_queue(priv->netdev, adapter);
241
238 mwifiex_clean_txrx(priv); 242 mwifiex_clean_txrx(priv);
239 mwifiex_del_all_sta_list(priv); 243 mwifiex_del_all_sta_list(priv);
240 break; 244 break;
241 case EVENT_UAP_BSS_ACTIVE: 245 case EVENT_UAP_BSS_ACTIVE:
242 priv->media_connected = true; 246 priv->media_connected = true;
247 if (!netif_carrier_ok(priv->netdev))
248 netif_carrier_on(priv->netdev);
249 mwifiex_wake_up_net_dev_queue(priv->netdev, adapter);
243 break; 250 break;
244 case EVENT_UAP_BSS_START: 251 case EVENT_UAP_BSS_START:
245 dev_dbg(adapter->dev, "AP EVENT: event id: %#x\n", eventcause); 252 dev_dbg(adapter->dev, "AP EVENT: event id: %#x\n", eventcause);
diff --git a/drivers/net/wireless/mwifiex/usb.c b/drivers/net/wireless/mwifiex/usb.c
index 22a5916564b8..bbe1f3518e4b 100644
--- a/drivers/net/wireless/mwifiex/usb.c
+++ b/drivers/net/wireless/mwifiex/usb.c
@@ -238,7 +238,7 @@ static void mwifiex_usb_tx_complete(struct urb *urb)
238 } else { 238 } else {
239 dev_dbg(adapter->dev, "%s: DATA\n", __func__); 239 dev_dbg(adapter->dev, "%s: DATA\n", __func__);
240 atomic_dec(&card->tx_data_urb_pending); 240 atomic_dec(&card->tx_data_urb_pending);
241 mwifiex_write_data_complete(adapter, context->skb, 241 mwifiex_write_data_complete(adapter, context->skb, 0,
242 urb->status ? -1 : 0); 242 urb->status ? -1 : 0);
243 } 243 }
244 244
diff --git a/drivers/net/wireless/mwifiex/wmm.c b/drivers/net/wireless/mwifiex/wmm.c
index 600d8194610e..818f871ae987 100644
--- a/drivers/net/wireless/mwifiex/wmm.c
+++ b/drivers/net/wireless/mwifiex/wmm.c
@@ -483,7 +483,7 @@ mwifiex_wmm_del_pkts_in_ralist_node(struct mwifiex_private *priv,
483 struct sk_buff *skb, *tmp; 483 struct sk_buff *skb, *tmp;
484 484
485 skb_queue_walk_safe(&ra_list->skb_head, skb, tmp) 485 skb_queue_walk_safe(&ra_list->skb_head, skb, tmp)
486 mwifiex_write_data_complete(adapter, skb, -1); 486 mwifiex_write_data_complete(adapter, skb, 0, -1);
487} 487}
488 488
489/* 489/*
@@ -650,7 +650,7 @@ mwifiex_wmm_add_buf_txqueue(struct mwifiex_private *priv,
650 650
651 if (!priv->media_connected && !mwifiex_is_skb_mgmt_frame(skb)) { 651 if (!priv->media_connected && !mwifiex_is_skb_mgmt_frame(skb)) {
652 dev_dbg(adapter->dev, "data: drop packet in disconnect\n"); 652 dev_dbg(adapter->dev, "data: drop packet in disconnect\n");
653 mwifiex_write_data_complete(adapter, skb, -1); 653 mwifiex_write_data_complete(adapter, skb, 0, -1);
654 return; 654 return;
655 } 655 }
656 656
@@ -680,7 +680,7 @@ mwifiex_wmm_add_buf_txqueue(struct mwifiex_private *priv,
680 680
681 if (!ra_list) { 681 if (!ra_list) {
682 spin_unlock_irqrestore(&priv->wmm.ra_list_spinlock, flags); 682 spin_unlock_irqrestore(&priv->wmm.ra_list_spinlock, flags);
683 mwifiex_write_data_complete(adapter, skb, -1); 683 mwifiex_write_data_complete(adapter, skb, 0, -1);
684 return; 684 return;
685 } 685 }
686 686
@@ -1090,7 +1090,7 @@ mwifiex_send_single_packet(struct mwifiex_private *priv,
1090 if (!mwifiex_is_ralist_valid(priv, ptr, ptr_index)) { 1090 if (!mwifiex_is_ralist_valid(priv, ptr, ptr_index)) {
1091 spin_unlock_irqrestore(&priv->wmm.ra_list_spinlock, 1091 spin_unlock_irqrestore(&priv->wmm.ra_list_spinlock,
1092 ra_list_flags); 1092 ra_list_flags);
1093 mwifiex_write_data_complete(adapter, skb, -1); 1093 mwifiex_write_data_complete(adapter, skb, 0, -1);
1094 return; 1094 return;
1095 } 1095 }
1096 1096
@@ -1195,7 +1195,7 @@ mwifiex_send_processed_packet(struct mwifiex_private *priv,
1195 if (!mwifiex_is_ralist_valid(priv, ptr, ptr_index)) { 1195 if (!mwifiex_is_ralist_valid(priv, ptr, ptr_index)) {
1196 spin_unlock_irqrestore(&priv->wmm.ra_list_spinlock, 1196 spin_unlock_irqrestore(&priv->wmm.ra_list_spinlock,
1197 ra_list_flags); 1197 ra_list_flags);
1198 mwifiex_write_data_complete(adapter, skb, -1); 1198 mwifiex_write_data_complete(adapter, skb, 0, -1);
1199 return; 1199 return;
1200 } 1200 }
1201 1201
@@ -1209,7 +1209,7 @@ mwifiex_send_processed_packet(struct mwifiex_private *priv,
1209 adapter->data_sent = false; 1209 adapter->data_sent = false;
1210 dev_err(adapter->dev, "host_to_card failed: %#x\n", ret); 1210 dev_err(adapter->dev, "host_to_card failed: %#x\n", ret);
1211 adapter->dbg.num_tx_host_to_card_failure++; 1211 adapter->dbg.num_tx_host_to_card_failure++;
1212 mwifiex_write_data_complete(adapter, skb, ret); 1212 mwifiex_write_data_complete(adapter, skb, 0, ret);
1213 break; 1213 break;
1214 case -EINPROGRESS: 1214 case -EINPROGRESS:
1215 adapter->data_sent = false; 1215 adapter->data_sent = false;
diff --git a/drivers/net/wireless/mwifiex/wmm.h b/drivers/net/wireless/mwifiex/wmm.h
index ec839952d2e7..b92f39d8963b 100644
--- a/drivers/net/wireless/mwifiex/wmm.h
+++ b/drivers/net/wireless/mwifiex/wmm.h
@@ -31,6 +31,8 @@ enum ieee_types_wmm_ecw_bitmasks {
31 MWIFIEX_ECW_MAX = (BIT(4) | BIT(5) | BIT(6) | BIT(7)), 31 MWIFIEX_ECW_MAX = (BIT(4) | BIT(5) | BIT(6) | BIT(7)),
32}; 32};
33 33
34static const u16 mwifiex_1d_to_wmm_queue[8] = { 1, 0, 0, 1, 2, 2, 3, 3 };
35
34/* 36/*
35 * This function retrieves the TID of the given RA list. 37 * This function retrieves the TID of the given RA list.
36 */ 38 */