diff options
author | Avinash Patil <patila@marvell.com> | 2012-11-01 21:44:16 -0400 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2012-11-14 14:55:37 -0500 |
commit | 47411a06c0c44b3c9dc2feffb0d97785ec9aaa68 (patch) | |
tree | 4464ca983493e93fb688eb471d7c28ec0be78fa6 | |
parent | d31ab3577eca0f74126ceb1d406710e620a155a0 (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.c | 8 | ||||
-rw-r--r-- | drivers/net/wireless/mwifiex/cfg80211.c | 7 | ||||
-rw-r--r-- | drivers/net/wireless/mwifiex/debugfs.c | 10 | ||||
-rw-r--r-- | drivers/net/wireless/mwifiex/init.c | 20 | ||||
-rw-r--r-- | drivers/net/wireless/mwifiex/join.c | 6 | ||||
-rw-r--r-- | drivers/net/wireless/mwifiex/main.c | 85 | ||||
-rw-r--r-- | drivers/net/wireless/mwifiex/main.h | 3 | ||||
-rw-r--r-- | drivers/net/wireless/mwifiex/sta_event.c | 9 | ||||
-rw-r--r-- | drivers/net/wireless/mwifiex/sta_ioctl.c | 6 | ||||
-rw-r--r-- | drivers/net/wireless/mwifiex/txrx.c | 28 | ||||
-rw-r--r-- | drivers/net/wireless/mwifiex/uap_event.c | 7 | ||||
-rw-r--r-- | drivers/net/wireless/mwifiex/usb.c | 2 | ||||
-rw-r--r-- | drivers/net/wireless/mwifiex/wmm.c | 12 | ||||
-rw-r--r-- | drivers/net/wireless/mwifiex/wmm.h | 2 |
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 | */ | ||
421 | static void | ||
422 | mwifiex_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 | */ |
489 | int mwifiex_queue_tx_pkt(struct mwifiex_private *priv, struct sk_buff *skb) | 446 | int 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 | ||
606 | static u16 | ||
607 | mwifiex_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 */ |
634 | static const struct net_device_ops mwifiex_netdev_ops = { | 614 | static 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); |
790 | int mwifiex_send_null_packet(struct mwifiex_private *priv, u8 flags); | 791 | int mwifiex_send_null_packet(struct mwifiex_private *priv, u8 flags); |
791 | int mwifiex_write_data_complete(struct mwifiex_adapter *adapter, | 792 | int mwifiex_write_data_complete(struct mwifiex_adapter *adapter, |
792 | struct sk_buff *skb, int status); | 793 | struct sk_buff *skb, int aggr, int status); |
793 | void mwifiex_clean_txrx(struct mwifiex_private *priv); | 794 | void mwifiex_clean_txrx(struct mwifiex_private *priv); |
794 | u8 mwifiex_check_last_packet_indication(struct mwifiex_private *priv); | 795 | u8 mwifiex_check_last_packet_indication(struct mwifiex_private *priv); |
795 | void mwifiex_check_ps_cond(struct mwifiex_adapter *adapter); | 796 | void 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 | */ |
146 | int mwifiex_write_data_complete(struct mwifiex_adapter *adapter, | 146 | int 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 | } |
185 | done: | 191 | done: |
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 | ||
34 | static 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 | */ |