diff options
author | Thomas Gleixner <tglx@linutronix.de> | 2016-01-12 05:01:12 -0500 |
---|---|---|
committer | Thomas Gleixner <tglx@linutronix.de> | 2016-01-12 05:01:12 -0500 |
commit | 1f16f116b01c110db20ab808562c8b8bc3ee3d6e (patch) | |
tree | 44db563f64cf5f8d62af8f99a61e2b248c44ea3a /net/mac80211 | |
parent | 03724ac3d48f8f0e3caf1d30fa134f8fd96c94e2 (diff) | |
parent | f9eccf24615672896dc13251410c3f2f33a14f95 (diff) |
Merge branches 'clockevents/4.4-fixes' and 'clockevents/4.5-fixes' of http://git.linaro.org/people/daniel.lezcano/linux into timers/urgent
Pull in fixes from Daniel Lezcano:
- Fix the vt8500 timer leading to a system lock up when dealing with too
small delta (Roman Volkov)
- Select the CLKSRC_MMIO when the fsl_ftm_timer is enabled with COMPILE_TEST
(Daniel Lezcano)
- Prevent to compile timers using the 'iomem' API when the architecture has
not HAS_IOMEM set (Richard Weinberger)
Diffstat (limited to 'net/mac80211')
-rw-r--r-- | net/mac80211/agg-tx.c | 3 | ||||
-rw-r--r-- | net/mac80211/cfg.c | 11 | ||||
-rw-r--r-- | net/mac80211/ieee80211_i.h | 4 | ||||
-rw-r--r-- | net/mac80211/iface.c | 5 | ||||
-rw-r--r-- | net/mac80211/main.c | 3 | ||||
-rw-r--r-- | net/mac80211/mesh_pathtbl.c | 8 | ||||
-rw-r--r-- | net/mac80211/mlme.c | 17 | ||||
-rw-r--r-- | net/mac80211/rx.c | 3 | ||||
-rw-r--r-- | net/mac80211/scan.c | 9 | ||||
-rw-r--r-- | net/mac80211/util.c | 113 | ||||
-rw-r--r-- | net/mac80211/vht.c | 10 |
11 files changed, 102 insertions, 84 deletions
diff --git a/net/mac80211/agg-tx.c b/net/mac80211/agg-tx.c index a758eb84e8f0..ff757181b0a8 100644 --- a/net/mac80211/agg-tx.c +++ b/net/mac80211/agg-tx.c | |||
@@ -500,7 +500,7 @@ void ieee80211_tx_ba_session_handle_start(struct sta_info *sta, int tid) | |||
500 | /* send AddBA request */ | 500 | /* send AddBA request */ |
501 | ieee80211_send_addba_request(sdata, sta->sta.addr, tid, | 501 | ieee80211_send_addba_request(sdata, sta->sta.addr, tid, |
502 | tid_tx->dialog_token, start_seq_num, | 502 | tid_tx->dialog_token, start_seq_num, |
503 | local->hw.max_tx_aggregation_subframes, | 503 | IEEE80211_MAX_AMPDU_BUF, |
504 | tid_tx->timeout); | 504 | tid_tx->timeout); |
505 | } | 505 | } |
506 | 506 | ||
@@ -926,6 +926,7 @@ void ieee80211_process_addba_resp(struct ieee80211_local *local, | |||
926 | amsdu = capab & IEEE80211_ADDBA_PARAM_AMSDU_MASK; | 926 | amsdu = capab & IEEE80211_ADDBA_PARAM_AMSDU_MASK; |
927 | tid = (capab & IEEE80211_ADDBA_PARAM_TID_MASK) >> 2; | 927 | tid = (capab & IEEE80211_ADDBA_PARAM_TID_MASK) >> 2; |
928 | buf_size = (capab & IEEE80211_ADDBA_PARAM_BUF_SIZE_MASK) >> 6; | 928 | buf_size = (capab & IEEE80211_ADDBA_PARAM_BUF_SIZE_MASK) >> 6; |
929 | buf_size = min(buf_size, local->hw.max_tx_aggregation_subframes); | ||
929 | 930 | ||
930 | mutex_lock(&sta->ampdu_mlme.mtx); | 931 | mutex_lock(&sta->ampdu_mlme.mtx); |
931 | 932 | ||
diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c index c2bd1b6a6922..c12f348138ac 100644 --- a/net/mac80211/cfg.c +++ b/net/mac80211/cfg.c | |||
@@ -1169,8 +1169,7 @@ static int sta_apply_parameters(struct ieee80211_local *local, | |||
1169 | * rc isn't initialized here yet, so ignore it | 1169 | * rc isn't initialized here yet, so ignore it |
1170 | */ | 1170 | */ |
1171 | __ieee80211_vht_handle_opmode(sdata, sta, | 1171 | __ieee80211_vht_handle_opmode(sdata, sta, |
1172 | params->opmode_notif, | 1172 | params->opmode_notif, band); |
1173 | band, false); | ||
1174 | } | 1173 | } |
1175 | 1174 | ||
1176 | if (ieee80211_vif_is_mesh(&sdata->vif)) | 1175 | if (ieee80211_vif_is_mesh(&sdata->vif)) |
@@ -3454,8 +3453,12 @@ static int ieee80211_mgmt_tx(struct wiphy *wiphy, struct wireless_dev *wdev, | |||
3454 | goto out_unlock; | 3453 | goto out_unlock; |
3455 | } | 3454 | } |
3456 | } else { | 3455 | } else { |
3457 | /* for cookie below */ | 3456 | /* Assign a dummy non-zero cookie, it's not sent to |
3458 | ack_skb = skb; | 3457 | * userspace in this case but we rely on its value |
3458 | * internally in the need_offchan case to distinguish | ||
3459 | * mgmt-tx from remain-on-channel. | ||
3460 | */ | ||
3461 | *cookie = 0xffffffff; | ||
3459 | } | 3462 | } |
3460 | 3463 | ||
3461 | if (!need_offchan) { | 3464 | if (!need_offchan) { |
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h index d832bd59236b..5322b4c71630 100644 --- a/net/mac80211/ieee80211_i.h +++ b/net/mac80211/ieee80211_i.h | |||
@@ -1709,10 +1709,10 @@ enum ieee80211_sta_rx_bandwidth ieee80211_sta_cur_vht_bw(struct sta_info *sta); | |||
1709 | void ieee80211_sta_set_rx_nss(struct sta_info *sta); | 1709 | void ieee80211_sta_set_rx_nss(struct sta_info *sta); |
1710 | u32 __ieee80211_vht_handle_opmode(struct ieee80211_sub_if_data *sdata, | 1710 | u32 __ieee80211_vht_handle_opmode(struct ieee80211_sub_if_data *sdata, |
1711 | struct sta_info *sta, u8 opmode, | 1711 | struct sta_info *sta, u8 opmode, |
1712 | enum ieee80211_band band, bool nss_only); | 1712 | enum ieee80211_band band); |
1713 | void ieee80211_vht_handle_opmode(struct ieee80211_sub_if_data *sdata, | 1713 | void ieee80211_vht_handle_opmode(struct ieee80211_sub_if_data *sdata, |
1714 | struct sta_info *sta, u8 opmode, | 1714 | struct sta_info *sta, u8 opmode, |
1715 | enum ieee80211_band band, bool nss_only); | 1715 | enum ieee80211_band band); |
1716 | void ieee80211_apply_vhtcap_overrides(struct ieee80211_sub_if_data *sdata, | 1716 | void ieee80211_apply_vhtcap_overrides(struct ieee80211_sub_if_data *sdata, |
1717 | struct ieee80211_sta_vht_cap *vht_cap); | 1717 | struct ieee80211_sta_vht_cap *vht_cap); |
1718 | void ieee80211_get_vht_mask_from_cap(__le16 vht_cap, | 1718 | void ieee80211_get_vht_mask_from_cap(__le16 vht_cap, |
diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c index d0dc1bfaeec2..c9e325d2e120 100644 --- a/net/mac80211/iface.c +++ b/net/mac80211/iface.c | |||
@@ -76,7 +76,8 @@ bool __ieee80211_recalc_txpower(struct ieee80211_sub_if_data *sdata) | |||
76 | void ieee80211_recalc_txpower(struct ieee80211_sub_if_data *sdata, | 76 | void ieee80211_recalc_txpower(struct ieee80211_sub_if_data *sdata, |
77 | bool update_bss) | 77 | bool update_bss) |
78 | { | 78 | { |
79 | if (__ieee80211_recalc_txpower(sdata) || update_bss) | 79 | if (__ieee80211_recalc_txpower(sdata) || |
80 | (update_bss && ieee80211_sdata_running(sdata))) | ||
80 | ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_TXPOWER); | 81 | ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_TXPOWER); |
81 | } | 82 | } |
82 | 83 | ||
@@ -1861,6 +1862,7 @@ void ieee80211_if_remove(struct ieee80211_sub_if_data *sdata) | |||
1861 | unregister_netdevice(sdata->dev); | 1862 | unregister_netdevice(sdata->dev); |
1862 | } else { | 1863 | } else { |
1863 | cfg80211_unregister_wdev(&sdata->wdev); | 1864 | cfg80211_unregister_wdev(&sdata->wdev); |
1865 | ieee80211_teardown_sdata(sdata); | ||
1864 | kfree(sdata); | 1866 | kfree(sdata); |
1865 | } | 1867 | } |
1866 | } | 1868 | } |
@@ -1870,7 +1872,6 @@ void ieee80211_sdata_stop(struct ieee80211_sub_if_data *sdata) | |||
1870 | if (WARN_ON_ONCE(!test_bit(SDATA_STATE_RUNNING, &sdata->state))) | 1872 | if (WARN_ON_ONCE(!test_bit(SDATA_STATE_RUNNING, &sdata->state))) |
1871 | return; | 1873 | return; |
1872 | ieee80211_do_stop(sdata, true); | 1874 | ieee80211_do_stop(sdata, true); |
1873 | ieee80211_teardown_sdata(sdata); | ||
1874 | } | 1875 | } |
1875 | 1876 | ||
1876 | void ieee80211_remove_interfaces(struct ieee80211_local *local) | 1877 | void ieee80211_remove_interfaces(struct ieee80211_local *local) |
diff --git a/net/mac80211/main.c b/net/mac80211/main.c index 858f6b1cb149..175ffcf7fb06 100644 --- a/net/mac80211/main.c +++ b/net/mac80211/main.c | |||
@@ -541,8 +541,7 @@ struct ieee80211_hw *ieee80211_alloc_hw_nm(size_t priv_data_len, | |||
541 | NL80211_FEATURE_HT_IBSS | | 541 | NL80211_FEATURE_HT_IBSS | |
542 | NL80211_FEATURE_VIF_TXPOWER | | 542 | NL80211_FEATURE_VIF_TXPOWER | |
543 | NL80211_FEATURE_MAC_ON_CREATE | | 543 | NL80211_FEATURE_MAC_ON_CREATE | |
544 | NL80211_FEATURE_USERSPACE_MPM | | 544 | NL80211_FEATURE_USERSPACE_MPM; |
545 | NL80211_FEATURE_FULL_AP_CLIENT_STATE; | ||
546 | 545 | ||
547 | if (!ops->hw_scan) | 546 | if (!ops->hw_scan) |
548 | wiphy->features |= NL80211_FEATURE_LOW_PRIORITY_SCAN | | 547 | wiphy->features |= NL80211_FEATURE_LOW_PRIORITY_SCAN | |
diff --git a/net/mac80211/mesh_pathtbl.c b/net/mac80211/mesh_pathtbl.c index b890e225a8f1..b3b44a5dd375 100644 --- a/net/mac80211/mesh_pathtbl.c +++ b/net/mac80211/mesh_pathtbl.c | |||
@@ -779,10 +779,8 @@ void mesh_plink_broken(struct sta_info *sta) | |||
779 | static void mesh_path_node_reclaim(struct rcu_head *rp) | 779 | static void mesh_path_node_reclaim(struct rcu_head *rp) |
780 | { | 780 | { |
781 | struct mpath_node *node = container_of(rp, struct mpath_node, rcu); | 781 | struct mpath_node *node = container_of(rp, struct mpath_node, rcu); |
782 | struct ieee80211_sub_if_data *sdata = node->mpath->sdata; | ||
783 | 782 | ||
784 | del_timer_sync(&node->mpath->timer); | 783 | del_timer_sync(&node->mpath->timer); |
785 | atomic_dec(&sdata->u.mesh.mpaths); | ||
786 | kfree(node->mpath); | 784 | kfree(node->mpath); |
787 | kfree(node); | 785 | kfree(node); |
788 | } | 786 | } |
@@ -790,8 +788,9 @@ static void mesh_path_node_reclaim(struct rcu_head *rp) | |||
790 | /* needs to be called with the corresponding hashwlock taken */ | 788 | /* needs to be called with the corresponding hashwlock taken */ |
791 | static void __mesh_path_del(struct mesh_table *tbl, struct mpath_node *node) | 789 | static void __mesh_path_del(struct mesh_table *tbl, struct mpath_node *node) |
792 | { | 790 | { |
793 | struct mesh_path *mpath; | 791 | struct mesh_path *mpath = node->mpath; |
794 | mpath = node->mpath; | 792 | struct ieee80211_sub_if_data *sdata = node->mpath->sdata; |
793 | |||
795 | spin_lock(&mpath->state_lock); | 794 | spin_lock(&mpath->state_lock); |
796 | mpath->flags |= MESH_PATH_RESOLVING; | 795 | mpath->flags |= MESH_PATH_RESOLVING; |
797 | if (mpath->is_gate) | 796 | if (mpath->is_gate) |
@@ -799,6 +798,7 @@ static void __mesh_path_del(struct mesh_table *tbl, struct mpath_node *node) | |||
799 | hlist_del_rcu(&node->list); | 798 | hlist_del_rcu(&node->list); |
800 | call_rcu(&node->rcu, mesh_path_node_reclaim); | 799 | call_rcu(&node->rcu, mesh_path_node_reclaim); |
801 | spin_unlock(&mpath->state_lock); | 800 | spin_unlock(&mpath->state_lock); |
801 | atomic_dec(&sdata->u.mesh.mpaths); | ||
802 | atomic_dec(&tbl->entries); | 802 | atomic_dec(&tbl->entries); |
803 | } | 803 | } |
804 | 804 | ||
diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index b140cc6651f4..3aa04344942b 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c | |||
@@ -1379,21 +1379,26 @@ static u32 ieee80211_handle_pwr_constr(struct ieee80211_sub_if_data *sdata, | |||
1379 | */ | 1379 | */ |
1380 | if (has_80211h_pwr && | 1380 | if (has_80211h_pwr && |
1381 | (!has_cisco_pwr || pwr_level_80211h <= pwr_level_cisco)) { | 1381 | (!has_cisco_pwr || pwr_level_80211h <= pwr_level_cisco)) { |
1382 | new_ap_level = pwr_level_80211h; | ||
1383 | |||
1384 | if (sdata->ap_power_level == new_ap_level) | ||
1385 | return 0; | ||
1386 | |||
1382 | sdata_dbg(sdata, | 1387 | sdata_dbg(sdata, |
1383 | "Limiting TX power to %d (%d - %d) dBm as advertised by %pM\n", | 1388 | "Limiting TX power to %d (%d - %d) dBm as advertised by %pM\n", |
1384 | pwr_level_80211h, chan_pwr, pwr_reduction_80211h, | 1389 | pwr_level_80211h, chan_pwr, pwr_reduction_80211h, |
1385 | sdata->u.mgd.bssid); | 1390 | sdata->u.mgd.bssid); |
1386 | new_ap_level = pwr_level_80211h; | ||
1387 | } else { /* has_cisco_pwr is always true here. */ | 1391 | } else { /* has_cisco_pwr is always true here. */ |
1392 | new_ap_level = pwr_level_cisco; | ||
1393 | |||
1394 | if (sdata->ap_power_level == new_ap_level) | ||
1395 | return 0; | ||
1396 | |||
1388 | sdata_dbg(sdata, | 1397 | sdata_dbg(sdata, |
1389 | "Limiting TX power to %d dBm as advertised by %pM\n", | 1398 | "Limiting TX power to %d dBm as advertised by %pM\n", |
1390 | pwr_level_cisco, sdata->u.mgd.bssid); | 1399 | pwr_level_cisco, sdata->u.mgd.bssid); |
1391 | new_ap_level = pwr_level_cisco; | ||
1392 | } | 1400 | } |
1393 | 1401 | ||
1394 | if (sdata->ap_power_level == new_ap_level) | ||
1395 | return 0; | ||
1396 | |||
1397 | sdata->ap_power_level = new_ap_level; | 1402 | sdata->ap_power_level = new_ap_level; |
1398 | if (__ieee80211_recalc_txpower(sdata)) | 1403 | if (__ieee80211_recalc_txpower(sdata)) |
1399 | return BSS_CHANGED_TXPOWER; | 1404 | return BSS_CHANGED_TXPOWER; |
@@ -3575,7 +3580,7 @@ static void ieee80211_rx_mgmt_beacon(struct ieee80211_sub_if_data *sdata, | |||
3575 | 3580 | ||
3576 | if (sta && elems.opmode_notif) | 3581 | if (sta && elems.opmode_notif) |
3577 | ieee80211_vht_handle_opmode(sdata, sta, *elems.opmode_notif, | 3582 | ieee80211_vht_handle_opmode(sdata, sta, *elems.opmode_notif, |
3578 | rx_status->band, true); | 3583 | rx_status->band); |
3579 | mutex_unlock(&local->sta_mtx); | 3584 | mutex_unlock(&local->sta_mtx); |
3580 | 3585 | ||
3581 | changed |= ieee80211_handle_pwr_constr(sdata, chan, mgmt, | 3586 | changed |= ieee80211_handle_pwr_constr(sdata, chan, mgmt, |
diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c index 8bae5de0dc44..82af407fea7a 100644 --- a/net/mac80211/rx.c +++ b/net/mac80211/rx.c | |||
@@ -2736,8 +2736,7 @@ ieee80211_rx_h_action(struct ieee80211_rx_data *rx) | |||
2736 | opmode = mgmt->u.action.u.vht_opmode_notif.operating_mode; | 2736 | opmode = mgmt->u.action.u.vht_opmode_notif.operating_mode; |
2737 | 2737 | ||
2738 | ieee80211_vht_handle_opmode(rx->sdata, rx->sta, | 2738 | ieee80211_vht_handle_opmode(rx->sdata, rx->sta, |
2739 | opmode, status->band, | 2739 | opmode, status->band); |
2740 | false); | ||
2741 | goto handled; | 2740 | goto handled; |
2742 | } | 2741 | } |
2743 | default: | 2742 | default: |
diff --git a/net/mac80211/scan.c b/net/mac80211/scan.c index 4aeca4b0c3cb..a413e52f7691 100644 --- a/net/mac80211/scan.c +++ b/net/mac80211/scan.c | |||
@@ -597,8 +597,8 @@ static int __ieee80211_start_scan(struct ieee80211_sub_if_data *sdata, | |||
597 | /* We need to ensure power level is at max for scanning. */ | 597 | /* We need to ensure power level is at max for scanning. */ |
598 | ieee80211_hw_config(local, 0); | 598 | ieee80211_hw_config(local, 0); |
599 | 599 | ||
600 | if ((req->channels[0]->flags & | 600 | if ((req->channels[0]->flags & (IEEE80211_CHAN_NO_IR | |
601 | IEEE80211_CHAN_NO_IR) || | 601 | IEEE80211_CHAN_RADAR)) || |
602 | !req->n_ssids) { | 602 | !req->n_ssids) { |
603 | next_delay = IEEE80211_PASSIVE_CHANNEL_TIME; | 603 | next_delay = IEEE80211_PASSIVE_CHANNEL_TIME; |
604 | } else { | 604 | } else { |
@@ -645,7 +645,7 @@ ieee80211_scan_get_channel_time(struct ieee80211_channel *chan) | |||
645 | * TODO: channel switching also consumes quite some time, | 645 | * TODO: channel switching also consumes quite some time, |
646 | * add that delay as well to get a better estimation | 646 | * add that delay as well to get a better estimation |
647 | */ | 647 | */ |
648 | if (chan->flags & IEEE80211_CHAN_NO_IR) | 648 | if (chan->flags & (IEEE80211_CHAN_NO_IR | IEEE80211_CHAN_RADAR)) |
649 | return IEEE80211_PASSIVE_CHANNEL_TIME; | 649 | return IEEE80211_PASSIVE_CHANNEL_TIME; |
650 | return IEEE80211_PROBE_DELAY + IEEE80211_CHANNEL_TIME; | 650 | return IEEE80211_PROBE_DELAY + IEEE80211_CHANNEL_TIME; |
651 | } | 651 | } |
@@ -777,7 +777,8 @@ static void ieee80211_scan_state_set_channel(struct ieee80211_local *local, | |||
777 | * | 777 | * |
778 | * In any case, it is not necessary for a passive scan. | 778 | * In any case, it is not necessary for a passive scan. |
779 | */ | 779 | */ |
780 | if (chan->flags & IEEE80211_CHAN_NO_IR || !scan_req->n_ssids) { | 780 | if ((chan->flags & (IEEE80211_CHAN_NO_IR | IEEE80211_CHAN_RADAR)) || |
781 | !scan_req->n_ssids) { | ||
781 | *next_delay = IEEE80211_PASSIVE_CHANNEL_TIME; | 782 | *next_delay = IEEE80211_PASSIVE_CHANNEL_TIME; |
782 | local->next_scan_state = SCAN_DECISION; | 783 | local->next_scan_state = SCAN_DECISION; |
783 | return; | 784 | return; |
diff --git a/net/mac80211/util.c b/net/mac80211/util.c index 74058020b7d6..33344f5a66a8 100644 --- a/net/mac80211/util.c +++ b/net/mac80211/util.c | |||
@@ -1641,6 +1641,29 @@ void ieee80211_stop_device(struct ieee80211_local *local) | |||
1641 | drv_stop(local); | 1641 | drv_stop(local); |
1642 | } | 1642 | } |
1643 | 1643 | ||
1644 | static void ieee80211_flush_completed_scan(struct ieee80211_local *local, | ||
1645 | bool aborted) | ||
1646 | { | ||
1647 | /* It's possible that we don't handle the scan completion in | ||
1648 | * time during suspend, so if it's still marked as completed | ||
1649 | * here, queue the work and flush it to clean things up. | ||
1650 | * Instead of calling the worker function directly here, we | ||
1651 | * really queue it to avoid potential races with other flows | ||
1652 | * scheduling the same work. | ||
1653 | */ | ||
1654 | if (test_bit(SCAN_COMPLETED, &local->scanning)) { | ||
1655 | /* If coming from reconfiguration failure, abort the scan so | ||
1656 | * we don't attempt to continue a partial HW scan - which is | ||
1657 | * possible otherwise if (e.g.) the 2.4 GHz portion was the | ||
1658 | * completed scan, and a 5 GHz portion is still pending. | ||
1659 | */ | ||
1660 | if (aborted) | ||
1661 | set_bit(SCAN_ABORTED, &local->scanning); | ||
1662 | ieee80211_queue_delayed_work(&local->hw, &local->scan_work, 0); | ||
1663 | flush_delayed_work(&local->scan_work); | ||
1664 | } | ||
1665 | } | ||
1666 | |||
1644 | static void ieee80211_handle_reconfig_failure(struct ieee80211_local *local) | 1667 | static void ieee80211_handle_reconfig_failure(struct ieee80211_local *local) |
1645 | { | 1668 | { |
1646 | struct ieee80211_sub_if_data *sdata; | 1669 | struct ieee80211_sub_if_data *sdata; |
@@ -1660,6 +1683,8 @@ static void ieee80211_handle_reconfig_failure(struct ieee80211_local *local) | |||
1660 | local->suspended = false; | 1683 | local->suspended = false; |
1661 | local->in_reconfig = false; | 1684 | local->in_reconfig = false; |
1662 | 1685 | ||
1686 | ieee80211_flush_completed_scan(local, true); | ||
1687 | |||
1663 | /* scheduled scan clearly can't be running any more, but tell | 1688 | /* scheduled scan clearly can't be running any more, but tell |
1664 | * cfg80211 and clear local state | 1689 | * cfg80211 and clear local state |
1665 | */ | 1690 | */ |
@@ -1698,6 +1723,27 @@ static void ieee80211_assign_chanctx(struct ieee80211_local *local, | |||
1698 | mutex_unlock(&local->chanctx_mtx); | 1723 | mutex_unlock(&local->chanctx_mtx); |
1699 | } | 1724 | } |
1700 | 1725 | ||
1726 | static void ieee80211_reconfig_stations(struct ieee80211_sub_if_data *sdata) | ||
1727 | { | ||
1728 | struct ieee80211_local *local = sdata->local; | ||
1729 | struct sta_info *sta; | ||
1730 | |||
1731 | /* add STAs back */ | ||
1732 | mutex_lock(&local->sta_mtx); | ||
1733 | list_for_each_entry(sta, &local->sta_list, list) { | ||
1734 | enum ieee80211_sta_state state; | ||
1735 | |||
1736 | if (!sta->uploaded || sta->sdata != sdata) | ||
1737 | continue; | ||
1738 | |||
1739 | for (state = IEEE80211_STA_NOTEXIST; | ||
1740 | state < sta->sta_state; state++) | ||
1741 | WARN_ON(drv_sta_state(local, sta->sdata, sta, state, | ||
1742 | state + 1)); | ||
1743 | } | ||
1744 | mutex_unlock(&local->sta_mtx); | ||
1745 | } | ||
1746 | |||
1701 | int ieee80211_reconfig(struct ieee80211_local *local) | 1747 | int ieee80211_reconfig(struct ieee80211_local *local) |
1702 | { | 1748 | { |
1703 | struct ieee80211_hw *hw = &local->hw; | 1749 | struct ieee80211_hw *hw = &local->hw; |
@@ -1833,50 +1879,11 @@ int ieee80211_reconfig(struct ieee80211_local *local) | |||
1833 | WARN_ON(drv_add_chanctx(local, ctx)); | 1879 | WARN_ON(drv_add_chanctx(local, ctx)); |
1834 | mutex_unlock(&local->chanctx_mtx); | 1880 | mutex_unlock(&local->chanctx_mtx); |
1835 | 1881 | ||
1836 | list_for_each_entry(sdata, &local->interfaces, list) { | ||
1837 | if (!ieee80211_sdata_running(sdata)) | ||
1838 | continue; | ||
1839 | ieee80211_assign_chanctx(local, sdata); | ||
1840 | } | ||
1841 | |||
1842 | sdata = rtnl_dereference(local->monitor_sdata); | 1882 | sdata = rtnl_dereference(local->monitor_sdata); |
1843 | if (sdata && ieee80211_sdata_running(sdata)) | 1883 | if (sdata && ieee80211_sdata_running(sdata)) |
1844 | ieee80211_assign_chanctx(local, sdata); | 1884 | ieee80211_assign_chanctx(local, sdata); |
1845 | } | 1885 | } |
1846 | 1886 | ||
1847 | /* add STAs back */ | ||
1848 | mutex_lock(&local->sta_mtx); | ||
1849 | list_for_each_entry(sta, &local->sta_list, list) { | ||
1850 | enum ieee80211_sta_state state; | ||
1851 | |||
1852 | if (!sta->uploaded) | ||
1853 | continue; | ||
1854 | |||
1855 | /* AP-mode stations will be added later */ | ||
1856 | if (sta->sdata->vif.type == NL80211_IFTYPE_AP) | ||
1857 | continue; | ||
1858 | |||
1859 | for (state = IEEE80211_STA_NOTEXIST; | ||
1860 | state < sta->sta_state; state++) | ||
1861 | WARN_ON(drv_sta_state(local, sta->sdata, sta, state, | ||
1862 | state + 1)); | ||
1863 | } | ||
1864 | mutex_unlock(&local->sta_mtx); | ||
1865 | |||
1866 | /* reconfigure tx conf */ | ||
1867 | if (hw->queues >= IEEE80211_NUM_ACS) { | ||
1868 | list_for_each_entry(sdata, &local->interfaces, list) { | ||
1869 | if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN || | ||
1870 | sdata->vif.type == NL80211_IFTYPE_MONITOR || | ||
1871 | !ieee80211_sdata_running(sdata)) | ||
1872 | continue; | ||
1873 | |||
1874 | for (i = 0; i < IEEE80211_NUM_ACS; i++) | ||
1875 | drv_conf_tx(local, sdata, i, | ||
1876 | &sdata->tx_conf[i]); | ||
1877 | } | ||
1878 | } | ||
1879 | |||
1880 | /* reconfigure hardware */ | 1887 | /* reconfigure hardware */ |
1881 | ieee80211_hw_config(local, ~0); | 1888 | ieee80211_hw_config(local, ~0); |
1882 | 1889 | ||
@@ -1889,6 +1896,22 @@ int ieee80211_reconfig(struct ieee80211_local *local) | |||
1889 | if (!ieee80211_sdata_running(sdata)) | 1896 | if (!ieee80211_sdata_running(sdata)) |
1890 | continue; | 1897 | continue; |
1891 | 1898 | ||
1899 | ieee80211_assign_chanctx(local, sdata); | ||
1900 | |||
1901 | switch (sdata->vif.type) { | ||
1902 | case NL80211_IFTYPE_AP_VLAN: | ||
1903 | case NL80211_IFTYPE_MONITOR: | ||
1904 | break; | ||
1905 | default: | ||
1906 | ieee80211_reconfig_stations(sdata); | ||
1907 | /* fall through */ | ||
1908 | case NL80211_IFTYPE_AP: /* AP stations are handled later */ | ||
1909 | for (i = 0; i < IEEE80211_NUM_ACS; i++) | ||
1910 | drv_conf_tx(local, sdata, i, | ||
1911 | &sdata->tx_conf[i]); | ||
1912 | break; | ||
1913 | } | ||
1914 | |||
1892 | /* common change flags for all interface types */ | 1915 | /* common change flags for all interface types */ |
1893 | changed = BSS_CHANGED_ERP_CTS_PROT | | 1916 | changed = BSS_CHANGED_ERP_CTS_PROT | |
1894 | BSS_CHANGED_ERP_PREAMBLE | | 1917 | BSS_CHANGED_ERP_PREAMBLE | |
@@ -2074,17 +2097,7 @@ int ieee80211_reconfig(struct ieee80211_local *local) | |||
2074 | mb(); | 2097 | mb(); |
2075 | local->resuming = false; | 2098 | local->resuming = false; |
2076 | 2099 | ||
2077 | /* It's possible that we don't handle the scan completion in | 2100 | ieee80211_flush_completed_scan(local, false); |
2078 | * time during suspend, so if it's still marked as completed | ||
2079 | * here, queue the work and flush it to clean things up. | ||
2080 | * Instead of calling the worker function directly here, we | ||
2081 | * really queue it to avoid potential races with other flows | ||
2082 | * scheduling the same work. | ||
2083 | */ | ||
2084 | if (test_bit(SCAN_COMPLETED, &local->scanning)) { | ||
2085 | ieee80211_queue_delayed_work(&local->hw, &local->scan_work, 0); | ||
2086 | flush_delayed_work(&local->scan_work); | ||
2087 | } | ||
2088 | 2101 | ||
2089 | if (local->open_count && !reconfig_due_to_wowlan) | 2102 | if (local->open_count && !reconfig_due_to_wowlan) |
2090 | drv_reconfig_complete(local, IEEE80211_RECONFIG_TYPE_SUSPEND); | 2103 | drv_reconfig_complete(local, IEEE80211_RECONFIG_TYPE_SUSPEND); |
diff --git a/net/mac80211/vht.c b/net/mac80211/vht.c index ff1c798921a6..c38b2f07a919 100644 --- a/net/mac80211/vht.c +++ b/net/mac80211/vht.c | |||
@@ -378,7 +378,7 @@ void ieee80211_sta_set_rx_nss(struct sta_info *sta) | |||
378 | 378 | ||
379 | u32 __ieee80211_vht_handle_opmode(struct ieee80211_sub_if_data *sdata, | 379 | u32 __ieee80211_vht_handle_opmode(struct ieee80211_sub_if_data *sdata, |
380 | struct sta_info *sta, u8 opmode, | 380 | struct sta_info *sta, u8 opmode, |
381 | enum ieee80211_band band, bool nss_only) | 381 | enum ieee80211_band band) |
382 | { | 382 | { |
383 | struct ieee80211_local *local = sdata->local; | 383 | struct ieee80211_local *local = sdata->local; |
384 | struct ieee80211_supported_band *sband; | 384 | struct ieee80211_supported_band *sband; |
@@ -401,9 +401,6 @@ u32 __ieee80211_vht_handle_opmode(struct ieee80211_sub_if_data *sdata, | |||
401 | changed |= IEEE80211_RC_NSS_CHANGED; | 401 | changed |= IEEE80211_RC_NSS_CHANGED; |
402 | } | 402 | } |
403 | 403 | ||
404 | if (nss_only) | ||
405 | return changed; | ||
406 | |||
407 | switch (opmode & IEEE80211_OPMODE_NOTIF_CHANWIDTH_MASK) { | 404 | switch (opmode & IEEE80211_OPMODE_NOTIF_CHANWIDTH_MASK) { |
408 | case IEEE80211_OPMODE_NOTIF_CHANWIDTH_20MHZ: | 405 | case IEEE80211_OPMODE_NOTIF_CHANWIDTH_20MHZ: |
409 | sta->cur_max_bandwidth = IEEE80211_STA_RX_BW_20; | 406 | sta->cur_max_bandwidth = IEEE80211_STA_RX_BW_20; |
@@ -430,13 +427,12 @@ u32 __ieee80211_vht_handle_opmode(struct ieee80211_sub_if_data *sdata, | |||
430 | 427 | ||
431 | void ieee80211_vht_handle_opmode(struct ieee80211_sub_if_data *sdata, | 428 | void ieee80211_vht_handle_opmode(struct ieee80211_sub_if_data *sdata, |
432 | struct sta_info *sta, u8 opmode, | 429 | struct sta_info *sta, u8 opmode, |
433 | enum ieee80211_band band, bool nss_only) | 430 | enum ieee80211_band band) |
434 | { | 431 | { |
435 | struct ieee80211_local *local = sdata->local; | 432 | struct ieee80211_local *local = sdata->local; |
436 | struct ieee80211_supported_band *sband = local->hw.wiphy->bands[band]; | 433 | struct ieee80211_supported_band *sband = local->hw.wiphy->bands[band]; |
437 | 434 | ||
438 | u32 changed = __ieee80211_vht_handle_opmode(sdata, sta, opmode, | 435 | u32 changed = __ieee80211_vht_handle_opmode(sdata, sta, opmode, band); |
439 | band, nss_only); | ||
440 | 436 | ||
441 | if (changed > 0) | 437 | if (changed > 0) |
442 | rate_control_rate_update(local, sband, sta, changed); | 438 | rate_control_rate_update(local, sband, sta, changed); |