diff options
author | Ingo Molnar <mingo@kernel.org> | 2015-03-05 14:52:18 -0500 |
---|---|---|
committer | Ingo Molnar <mingo@kernel.org> | 2015-03-05 14:52:18 -0500 |
commit | 33ca8a53f262b4af40611bea331b8c87d133af72 (patch) | |
tree | d6468c820a556c4915bcb5b761204a0fb19e8225 /net/mac80211/util.c | |
parent | db2dcb4f91d5fec5c346a82c309187ee821e2495 (diff) | |
parent | 13a7a6ac0a11197edcd0f756a035f472b42cdf8b (diff) |
Merge tag 'v4.0-rc2' into irq/core, to refresh the tree before applying new changes
Signed-off-by: Ingo Molnar <mingo@kernel.org>
Diffstat (limited to 'net/mac80211/util.c')
-rw-r--r-- | net/mac80211/util.c | 83 |
1 files changed, 54 insertions, 29 deletions
diff --git a/net/mac80211/util.c b/net/mac80211/util.c index 974ebe70f5b0..8428f4a95479 100644 --- a/net/mac80211/util.c +++ b/net/mac80211/util.c | |||
@@ -578,7 +578,7 @@ ieee80211_get_vif_queues(struct ieee80211_local *local, | |||
578 | 578 | ||
579 | void __ieee80211_flush_queues(struct ieee80211_local *local, | 579 | void __ieee80211_flush_queues(struct ieee80211_local *local, |
580 | struct ieee80211_sub_if_data *sdata, | 580 | struct ieee80211_sub_if_data *sdata, |
581 | unsigned int queues) | 581 | unsigned int queues, bool drop) |
582 | { | 582 | { |
583 | if (!local->ops->flush) | 583 | if (!local->ops->flush) |
584 | return; | 584 | return; |
@@ -594,7 +594,7 @@ void __ieee80211_flush_queues(struct ieee80211_local *local, | |||
594 | IEEE80211_QUEUE_STOP_REASON_FLUSH, | 594 | IEEE80211_QUEUE_STOP_REASON_FLUSH, |
595 | false); | 595 | false); |
596 | 596 | ||
597 | drv_flush(local, sdata, queues, false); | 597 | drv_flush(local, sdata, queues, drop); |
598 | 598 | ||
599 | ieee80211_wake_queues_by_reason(&local->hw, queues, | 599 | ieee80211_wake_queues_by_reason(&local->hw, queues, |
600 | IEEE80211_QUEUE_STOP_REASON_FLUSH, | 600 | IEEE80211_QUEUE_STOP_REASON_FLUSH, |
@@ -602,9 +602,9 @@ void __ieee80211_flush_queues(struct ieee80211_local *local, | |||
602 | } | 602 | } |
603 | 603 | ||
604 | void ieee80211_flush_queues(struct ieee80211_local *local, | 604 | void ieee80211_flush_queues(struct ieee80211_local *local, |
605 | struct ieee80211_sub_if_data *sdata) | 605 | struct ieee80211_sub_if_data *sdata, bool drop) |
606 | { | 606 | { |
607 | __ieee80211_flush_queues(local, sdata, 0); | 607 | __ieee80211_flush_queues(local, sdata, 0, drop); |
608 | } | 608 | } |
609 | 609 | ||
610 | void ieee80211_stop_vif_queues(struct ieee80211_local *local, | 610 | void ieee80211_stop_vif_queues(struct ieee80211_local *local, |
@@ -744,16 +744,19 @@ EXPORT_SYMBOL_GPL(wdev_to_ieee80211_vif); | |||
744 | 744 | ||
745 | /* | 745 | /* |
746 | * Nothing should have been stuffed into the workqueue during | 746 | * Nothing should have been stuffed into the workqueue during |
747 | * the suspend->resume cycle. If this WARN is seen then there | 747 | * the suspend->resume cycle. Since we can't check each caller |
748 | * is a bug with either the driver suspend or something in | 748 | * of this function if we are already quiescing / suspended, |
749 | * mac80211 stuffing into the workqueue which we haven't yet | 749 | * check here and don't WARN since this can actually happen when |
750 | * cleared during mac80211's suspend cycle. | 750 | * the rx path (for example) is racing against __ieee80211_suspend |
751 | * and suspending / quiescing was set after the rx path checked | ||
752 | * them. | ||
751 | */ | 753 | */ |
752 | static bool ieee80211_can_queue_work(struct ieee80211_local *local) | 754 | static bool ieee80211_can_queue_work(struct ieee80211_local *local) |
753 | { | 755 | { |
754 | if (WARN(local->suspended && !local->resuming, | 756 | if (local->quiescing || (local->suspended && !local->resuming)) { |
755 | "queueing ieee80211 work while going to suspend\n")) | 757 | pr_warn("queueing ieee80211 work while going to suspend\n"); |
756 | return false; | 758 | return false; |
759 | } | ||
757 | 760 | ||
758 | return true; | 761 | return true; |
759 | } | 762 | } |
@@ -1470,10 +1473,12 @@ static int ieee80211_build_preq_ies_band(struct ieee80211_local *local, | |||
1470 | 1473 | ||
1471 | /* Check if any channel in this sband supports at least 80 MHz */ | 1474 | /* Check if any channel in this sband supports at least 80 MHz */ |
1472 | for (i = 0; i < sband->n_channels; i++) { | 1475 | for (i = 0; i < sband->n_channels; i++) { |
1473 | if (!(sband->channels[i].flags & IEEE80211_CHAN_NO_80MHZ)) { | 1476 | if (sband->channels[i].flags & (IEEE80211_CHAN_DISABLED | |
1474 | have_80mhz = true; | 1477 | IEEE80211_CHAN_NO_80MHZ)) |
1475 | break; | 1478 | continue; |
1476 | } | 1479 | |
1480 | have_80mhz = true; | ||
1481 | break; | ||
1477 | } | 1482 | } |
1478 | 1483 | ||
1479 | if (sband->vht_cap.vht_supported && have_80mhz) { | 1484 | if (sband->vht_cap.vht_supported && have_80mhz) { |
@@ -1735,6 +1740,10 @@ int ieee80211_reconfig(struct ieee80211_local *local) | |||
1735 | struct cfg80211_sched_scan_request *sched_scan_req; | 1740 | struct cfg80211_sched_scan_request *sched_scan_req; |
1736 | bool sched_scan_stopped = false; | 1741 | bool sched_scan_stopped = false; |
1737 | 1742 | ||
1743 | /* nothing to do if HW shouldn't run */ | ||
1744 | if (!local->open_count) | ||
1745 | goto wake_up; | ||
1746 | |||
1738 | #ifdef CONFIG_PM | 1747 | #ifdef CONFIG_PM |
1739 | if (local->suspended) | 1748 | if (local->suspended) |
1740 | local->resuming = true; | 1749 | local->resuming = true; |
@@ -1756,9 +1765,6 @@ int ieee80211_reconfig(struct ieee80211_local *local) | |||
1756 | reconfig_due_to_wowlan = true; | 1765 | reconfig_due_to_wowlan = true; |
1757 | } | 1766 | } |
1758 | #endif | 1767 | #endif |
1759 | /* everything else happens only if HW was up & running */ | ||
1760 | if (!local->open_count) | ||
1761 | goto wake_up; | ||
1762 | 1768 | ||
1763 | /* | 1769 | /* |
1764 | * Upon resume hardware can sometimes be goofy due to | 1770 | * Upon resume hardware can sometimes be goofy due to |
@@ -2042,7 +2048,7 @@ int ieee80211_reconfig(struct ieee80211_local *local) | |||
2042 | * If this is for hw restart things are still running. | 2048 | * If this is for hw restart things are still running. |
2043 | * We may want to change that later, however. | 2049 | * We may want to change that later, however. |
2044 | */ | 2050 | */ |
2045 | if (!local->suspended || reconfig_due_to_wowlan) | 2051 | if (local->open_count && (!local->suspended || reconfig_due_to_wowlan)) |
2046 | drv_reconfig_complete(local, IEEE80211_RECONFIG_TYPE_RESTART); | 2052 | drv_reconfig_complete(local, IEEE80211_RECONFIG_TYPE_RESTART); |
2047 | 2053 | ||
2048 | if (!local->suspended) | 2054 | if (!local->suspended) |
@@ -2054,7 +2060,19 @@ int ieee80211_reconfig(struct ieee80211_local *local) | |||
2054 | mb(); | 2060 | mb(); |
2055 | local->resuming = false; | 2061 | local->resuming = false; |
2056 | 2062 | ||
2057 | if (!reconfig_due_to_wowlan) | 2063 | /* It's possible that we don't handle the scan completion in |
2064 | * time during suspend, so if it's still marked as completed | ||
2065 | * here, queue the work and flush it to clean things up. | ||
2066 | * Instead of calling the worker function directly here, we | ||
2067 | * really queue it to avoid potential races with other flows | ||
2068 | * scheduling the same work. | ||
2069 | */ | ||
2070 | if (test_bit(SCAN_COMPLETED, &local->scanning)) { | ||
2071 | ieee80211_queue_delayed_work(&local->hw, &local->scan_work, 0); | ||
2072 | flush_delayed_work(&local->scan_work); | ||
2073 | } | ||
2074 | |||
2075 | if (local->open_count && !reconfig_due_to_wowlan) | ||
2058 | drv_reconfig_complete(local, IEEE80211_RECONFIG_TYPE_SUSPEND); | 2076 | drv_reconfig_complete(local, IEEE80211_RECONFIG_TYPE_SUSPEND); |
2059 | 2077 | ||
2060 | list_for_each_entry(sdata, &local->interfaces, list) { | 2078 | list_for_each_entry(sdata, &local->interfaces, list) { |
@@ -2538,7 +2556,9 @@ u64 ieee80211_calculate_rx_timestamp(struct ieee80211_local *local, | |||
2538 | ri.mcs = status->rate_idx; | 2556 | ri.mcs = status->rate_idx; |
2539 | ri.flags |= RATE_INFO_FLAGS_MCS; | 2557 | ri.flags |= RATE_INFO_FLAGS_MCS; |
2540 | if (status->flag & RX_FLAG_40MHZ) | 2558 | if (status->flag & RX_FLAG_40MHZ) |
2541 | ri.flags |= RATE_INFO_FLAGS_40_MHZ_WIDTH; | 2559 | ri.bw = RATE_INFO_BW_40; |
2560 | else | ||
2561 | ri.bw = RATE_INFO_BW_20; | ||
2542 | if (status->flag & RX_FLAG_SHORT_GI) | 2562 | if (status->flag & RX_FLAG_SHORT_GI) |
2543 | ri.flags |= RATE_INFO_FLAGS_SHORT_GI; | 2563 | ri.flags |= RATE_INFO_FLAGS_SHORT_GI; |
2544 | } else if (status->flag & RX_FLAG_VHT) { | 2564 | } else if (status->flag & RX_FLAG_VHT) { |
@@ -2546,13 +2566,13 @@ u64 ieee80211_calculate_rx_timestamp(struct ieee80211_local *local, | |||
2546 | ri.mcs = status->rate_idx; | 2566 | ri.mcs = status->rate_idx; |
2547 | ri.nss = status->vht_nss; | 2567 | ri.nss = status->vht_nss; |
2548 | if (status->flag & RX_FLAG_40MHZ) | 2568 | if (status->flag & RX_FLAG_40MHZ) |
2549 | ri.flags |= RATE_INFO_FLAGS_40_MHZ_WIDTH; | 2569 | ri.bw = RATE_INFO_BW_40; |
2550 | if (status->vht_flag & RX_VHT_FLAG_80MHZ) | 2570 | else if (status->vht_flag & RX_VHT_FLAG_80MHZ) |
2551 | ri.flags |= RATE_INFO_FLAGS_80_MHZ_WIDTH; | 2571 | ri.bw = RATE_INFO_BW_80; |
2552 | if (status->vht_flag & RX_VHT_FLAG_80P80MHZ) | 2572 | else if (status->vht_flag & RX_VHT_FLAG_160MHZ) |
2553 | ri.flags |= RATE_INFO_FLAGS_80P80_MHZ_WIDTH; | 2573 | ri.bw = RATE_INFO_BW_160; |
2554 | if (status->vht_flag & RX_VHT_FLAG_160MHZ) | 2574 | else |
2555 | ri.flags |= RATE_INFO_FLAGS_160_MHZ_WIDTH; | 2575 | ri.bw = RATE_INFO_BW_20; |
2556 | if (status->flag & RX_FLAG_SHORT_GI) | 2576 | if (status->flag & RX_FLAG_SHORT_GI) |
2557 | ri.flags |= RATE_INFO_FLAGS_SHORT_GI; | 2577 | ri.flags |= RATE_INFO_FLAGS_SHORT_GI; |
2558 | } else { | 2578 | } else { |
@@ -2560,10 +2580,15 @@ u64 ieee80211_calculate_rx_timestamp(struct ieee80211_local *local, | |||
2560 | int shift = 0; | 2580 | int shift = 0; |
2561 | int bitrate; | 2581 | int bitrate; |
2562 | 2582 | ||
2563 | if (status->flag & RX_FLAG_10MHZ) | 2583 | if (status->flag & RX_FLAG_10MHZ) { |
2564 | shift = 1; | 2584 | shift = 1; |
2565 | if (status->flag & RX_FLAG_5MHZ) | 2585 | ri.bw = RATE_INFO_BW_10; |
2586 | } else if (status->flag & RX_FLAG_5MHZ) { | ||
2566 | shift = 2; | 2587 | shift = 2; |
2588 | ri.bw = RATE_INFO_BW_5; | ||
2589 | } else { | ||
2590 | ri.bw = RATE_INFO_BW_20; | ||
2591 | } | ||
2567 | 2592 | ||
2568 | sband = local->hw.wiphy->bands[status->band]; | 2593 | sband = local->hw.wiphy->bands[status->band]; |
2569 | bitrate = sband->bitrates[status->rate_idx].bitrate; | 2594 | bitrate = sband->bitrates[status->rate_idx].bitrate; |