diff options
author | John W. Linville <linville@tuxdriver.com> | 2013-04-10 14:09:54 -0400 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2013-04-10 14:09:54 -0400 |
commit | 655d8e2328a6ef6b6b514609a4c1e33508d3a1da (patch) | |
tree | 144b686bf3fd6512a55987da2d911f739646ce02 /net | |
parent | 6fe5468f452c0c40348ebd4e737758a842286ca8 (diff) | |
parent | ddc4db2e3d5393ede7a9222bb3b7522a603a4678 (diff) |
Merge branch 'for-john' of git://git.kernel.org/pub/scm/linux/kernel/git/jberg/mac80211-next
Conflicts:
drivers/net/wireless/ath/carl9170/debug.c
drivers/net/wireless/ath/carl9170/main.c
net/mac80211/ieee80211_i.h
Diffstat (limited to 'net')
-rw-r--r-- | net/mac80211/cfg.c | 42 | ||||
-rw-r--r-- | net/mac80211/chan.c | 11 | ||||
-rw-r--r-- | net/mac80211/debugfs_netdev.c | 11 | ||||
-rw-r--r-- | net/mac80211/debugfs_sta.c | 2 | ||||
-rw-r--r-- | net/mac80211/ibss.c | 140 | ||||
-rw-r--r-- | net/mac80211/ieee80211_i.h | 35 | ||||
-rw-r--r-- | net/mac80211/iface.c | 116 | ||||
-rw-r--r-- | net/mac80211/main.c | 75 | ||||
-rw-r--r-- | net/mac80211/mesh.c | 2 | ||||
-rw-r--r-- | net/mac80211/mesh.h | 3 | ||||
-rw-r--r-- | net/mac80211/mesh_hwmp.c | 26 | ||||
-rw-r--r-- | net/mac80211/mesh_pathtbl.c | 56 | ||||
-rw-r--r-- | net/mac80211/mlme.c | 128 | ||||
-rw-r--r-- | net/mac80211/offchannel.c | 6 | ||||
-rw-r--r-- | net/mac80211/pm.c | 8 | ||||
-rw-r--r-- | net/mac80211/scan.c | 11 | ||||
-rw-r--r-- | net/mac80211/trace.h | 43 | ||||
-rw-r--r-- | net/mac80211/tx.c | 11 | ||||
-rw-r--r-- | net/mac80211/util.c | 53 |
19 files changed, 406 insertions, 373 deletions
diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c index c50c19402588..764dd9a6a072 100644 --- a/net/mac80211/cfg.c +++ b/net/mac80211/cfg.c | |||
@@ -805,8 +805,7 @@ static int ieee80211_set_monitor_channel(struct wiphy *wiphy, | |||
805 | IEEE80211_CHANCTX_EXCLUSIVE); | 805 | IEEE80211_CHANCTX_EXCLUSIVE); |
806 | } | 806 | } |
807 | } else if (local->open_count == local->monitors) { | 807 | } else if (local->open_count == local->monitors) { |
808 | local->_oper_channel = chandef->chan; | 808 | local->_oper_chandef = *chandef; |
809 | local->_oper_channel_type = cfg80211_get_chandef_type(chandef); | ||
810 | ieee80211_hw_config(local, 0); | 809 | ieee80211_hw_config(local, 0); |
811 | } | 810 | } |
812 | 811 | ||
@@ -965,8 +964,13 @@ static int ieee80211_start_ap(struct wiphy *wiphy, struct net_device *dev, | |||
965 | sdata->vif.bss_conf.hidden_ssid = | 964 | sdata->vif.bss_conf.hidden_ssid = |
966 | (params->hidden_ssid != NL80211_HIDDEN_SSID_NOT_IN_USE); | 965 | (params->hidden_ssid != NL80211_HIDDEN_SSID_NOT_IN_USE); |
967 | 966 | ||
968 | sdata->vif.bss_conf.p2p_ctwindow = params->p2p_ctwindow; | 967 | memset(&sdata->vif.bss_conf.p2p_noa_attr, 0, |
969 | sdata->vif.bss_conf.p2p_oppps = params->p2p_opp_ps; | 968 | sizeof(sdata->vif.bss_conf.p2p_noa_attr)); |
969 | sdata->vif.bss_conf.p2p_noa_attr.oppps_ctwindow = | ||
970 | params->p2p_ctwindow & IEEE80211_P2P_OPPPS_CTWINDOW_MASK; | ||
971 | if (params->p2p_opp_ps) | ||
972 | sdata->vif.bss_conf.p2p_noa_attr.oppps_ctwindow |= | ||
973 | IEEE80211_P2P_OPPPS_ENABLE_BIT; | ||
970 | 974 | ||
971 | err = ieee80211_assign_beacon(sdata, ¶ms->beacon); | 975 | err = ieee80211_assign_beacon(sdata, ¶ms->beacon); |
972 | if (err < 0) | 976 | if (err < 0) |
@@ -1536,7 +1540,6 @@ static int ieee80211_add_mpath(struct wiphy *wiphy, struct net_device *dev, | |||
1536 | struct ieee80211_sub_if_data *sdata; | 1540 | struct ieee80211_sub_if_data *sdata; |
1537 | struct mesh_path *mpath; | 1541 | struct mesh_path *mpath; |
1538 | struct sta_info *sta; | 1542 | struct sta_info *sta; |
1539 | int err; | ||
1540 | 1543 | ||
1541 | sdata = IEEE80211_DEV_TO_SUB_IF(dev); | 1544 | sdata = IEEE80211_DEV_TO_SUB_IF(dev); |
1542 | 1545 | ||
@@ -1547,17 +1550,12 @@ static int ieee80211_add_mpath(struct wiphy *wiphy, struct net_device *dev, | |||
1547 | return -ENOENT; | 1550 | return -ENOENT; |
1548 | } | 1551 | } |
1549 | 1552 | ||
1550 | err = mesh_path_add(sdata, dst); | 1553 | mpath = mesh_path_add(sdata, dst); |
1551 | if (err) { | 1554 | if (IS_ERR(mpath)) { |
1552 | rcu_read_unlock(); | 1555 | rcu_read_unlock(); |
1553 | return err; | 1556 | return PTR_ERR(mpath); |
1554 | } | 1557 | } |
1555 | 1558 | ||
1556 | mpath = mesh_path_lookup(sdata, dst); | ||
1557 | if (!mpath) { | ||
1558 | rcu_read_unlock(); | ||
1559 | return -ENXIO; | ||
1560 | } | ||
1561 | mesh_path_fix_nexthop(mpath, sta); | 1559 | mesh_path_fix_nexthop(mpath, sta); |
1562 | 1560 | ||
1563 | rcu_read_unlock(); | 1561 | rcu_read_unlock(); |
@@ -1961,12 +1959,20 @@ static int ieee80211_change_bss(struct wiphy *wiphy, | |||
1961 | } | 1959 | } |
1962 | 1960 | ||
1963 | if (params->p2p_ctwindow >= 0) { | 1961 | if (params->p2p_ctwindow >= 0) { |
1964 | sdata->vif.bss_conf.p2p_ctwindow = params->p2p_ctwindow; | 1962 | sdata->vif.bss_conf.p2p_noa_attr.oppps_ctwindow &= |
1963 | ~IEEE80211_P2P_OPPPS_CTWINDOW_MASK; | ||
1964 | sdata->vif.bss_conf.p2p_noa_attr.oppps_ctwindow |= | ||
1965 | params->p2p_ctwindow & IEEE80211_P2P_OPPPS_CTWINDOW_MASK; | ||
1965 | changed |= BSS_CHANGED_P2P_PS; | 1966 | changed |= BSS_CHANGED_P2P_PS; |
1966 | } | 1967 | } |
1967 | 1968 | ||
1968 | if (params->p2p_opp_ps >= 0) { | 1969 | if (params->p2p_opp_ps > 0) { |
1969 | sdata->vif.bss_conf.p2p_oppps = params->p2p_opp_ps; | 1970 | sdata->vif.bss_conf.p2p_noa_attr.oppps_ctwindow |= |
1971 | IEEE80211_P2P_OPPPS_ENABLE_BIT; | ||
1972 | changed |= BSS_CHANGED_P2P_PS; | ||
1973 | } else if (params->p2p_opp_ps == 0) { | ||
1974 | sdata->vif.bss_conf.p2p_noa_attr.oppps_ctwindow &= | ||
1975 | ~IEEE80211_P2P_OPPPS_ENABLE_BIT; | ||
1970 | changed |= BSS_CHANGED_P2P_PS; | 1976 | changed |= BSS_CHANGED_P2P_PS; |
1971 | } | 1977 | } |
1972 | 1978 | ||
@@ -3362,9 +3368,7 @@ static int ieee80211_cfg_get_channel(struct wiphy *wiphy, | |||
3362 | if (local->use_chanctx) | 3368 | if (local->use_chanctx) |
3363 | *chandef = local->monitor_chandef; | 3369 | *chandef = local->monitor_chandef; |
3364 | else | 3370 | else |
3365 | cfg80211_chandef_create(chandef, | 3371 | *chandef = local->_oper_chandef; |
3366 | local->_oper_channel, | ||
3367 | local->_oper_channel_type); | ||
3368 | ret = 0; | 3372 | ret = 0; |
3369 | } | 3373 | } |
3370 | rcu_read_unlock(); | 3374 | rcu_read_unlock(); |
diff --git a/net/mac80211/chan.c b/net/mac80211/chan.c index 931be419ab5a..7d0baa89c784 100644 --- a/net/mac80211/chan.c +++ b/net/mac80211/chan.c | |||
@@ -22,7 +22,7 @@ static void ieee80211_change_chanctx(struct ieee80211_local *local, | |||
22 | drv_change_chanctx(local, ctx, IEEE80211_CHANCTX_CHANGE_WIDTH); | 22 | drv_change_chanctx(local, ctx, IEEE80211_CHANCTX_CHANGE_WIDTH); |
23 | 23 | ||
24 | if (!local->use_chanctx) { | 24 | if (!local->use_chanctx) { |
25 | local->_oper_channel_type = cfg80211_get_chandef_type(chandef); | 25 | local->_oper_chandef = *chandef; |
26 | ieee80211_hw_config(local, 0); | 26 | ieee80211_hw_config(local, 0); |
27 | } | 27 | } |
28 | } | 28 | } |
@@ -85,9 +85,7 @@ ieee80211_new_chanctx(struct ieee80211_local *local, | |||
85 | ieee80211_hw_config(local, changed); | 85 | ieee80211_hw_config(local, changed); |
86 | 86 | ||
87 | if (!local->use_chanctx) { | 87 | if (!local->use_chanctx) { |
88 | local->_oper_channel_type = | 88 | local->_oper_chandef = *chandef; |
89 | cfg80211_get_chandef_type(chandef); | ||
90 | local->_oper_channel = chandef->chan; | ||
91 | ieee80211_hw_config(local, 0); | 89 | ieee80211_hw_config(local, 0); |
92 | } else { | 90 | } else { |
93 | err = drv_add_chanctx(local, ctx); | 91 | err = drv_add_chanctx(local, ctx); |
@@ -117,7 +115,10 @@ static void ieee80211_free_chanctx(struct ieee80211_local *local, | |||
117 | WARN_ON_ONCE(ctx->refcount != 0); | 115 | WARN_ON_ONCE(ctx->refcount != 0); |
118 | 116 | ||
119 | if (!local->use_chanctx) { | 117 | if (!local->use_chanctx) { |
120 | local->_oper_channel_type = NL80211_CHAN_NO_HT; | 118 | struct cfg80211_chan_def *chandef = &local->_oper_chandef; |
119 | chandef->width = NL80211_CHAN_WIDTH_20_NOHT; | ||
120 | chandef->center_freq1 = chandef->chan->center_freq; | ||
121 | chandef->center_freq2 = 0; | ||
121 | ieee80211_hw_config(local, 0); | 122 | ieee80211_hw_config(local, 0); |
122 | } else { | 123 | } else { |
123 | drv_remove_chanctx(local, ctx); | 124 | drv_remove_chanctx(local, ctx); |
diff --git a/net/mac80211/debugfs_netdev.c b/net/mac80211/debugfs_netdev.c index ddb426867904..14abcf44f974 100644 --- a/net/mac80211/debugfs_netdev.c +++ b/net/mac80211/debugfs_netdev.c | |||
@@ -124,6 +124,15 @@ static ssize_t ieee80211_if_fmt_##name( \ | |||
124 | return scnprintf(buf, buflen, "%d\n", sdata->field / 16); \ | 124 | return scnprintf(buf, buflen, "%d\n", sdata->field / 16); \ |
125 | } | 125 | } |
126 | 126 | ||
127 | #define IEEE80211_IF_FMT_JIFFIES_TO_MS(name, field) \ | ||
128 | static ssize_t ieee80211_if_fmt_##name( \ | ||
129 | const struct ieee80211_sub_if_data *sdata, \ | ||
130 | char *buf, int buflen) \ | ||
131 | { \ | ||
132 | return scnprintf(buf, buflen, "%d\n", \ | ||
133 | jiffies_to_msecs(sdata->field)); \ | ||
134 | } | ||
135 | |||
127 | #define __IEEE80211_IF_FILE(name, _write) \ | 136 | #define __IEEE80211_IF_FILE(name, _write) \ |
128 | static ssize_t ieee80211_if_read_##name(struct file *file, \ | 137 | static ssize_t ieee80211_if_read_##name(struct file *file, \ |
129 | char __user *userbuf, \ | 138 | char __user *userbuf, \ |
@@ -197,6 +206,7 @@ IEEE80211_IF_FILE(bssid, u.mgd.bssid, MAC); | |||
197 | IEEE80211_IF_FILE(aid, u.mgd.aid, DEC); | 206 | IEEE80211_IF_FILE(aid, u.mgd.aid, DEC); |
198 | IEEE80211_IF_FILE(last_beacon, u.mgd.last_beacon_signal, DEC); | 207 | IEEE80211_IF_FILE(last_beacon, u.mgd.last_beacon_signal, DEC); |
199 | IEEE80211_IF_FILE(ave_beacon, u.mgd.ave_beacon_signal, DEC_DIV_16); | 208 | IEEE80211_IF_FILE(ave_beacon, u.mgd.ave_beacon_signal, DEC_DIV_16); |
209 | IEEE80211_IF_FILE(beacon_timeout, u.mgd.beacon_timeout, JIFFIES_TO_MS); | ||
200 | 210 | ||
201 | static int ieee80211_set_smps(struct ieee80211_sub_if_data *sdata, | 211 | static int ieee80211_set_smps(struct ieee80211_sub_if_data *sdata, |
202 | enum ieee80211_smps_mode smps_mode) | 212 | enum ieee80211_smps_mode smps_mode) |
@@ -542,6 +552,7 @@ static void add_sta_files(struct ieee80211_sub_if_data *sdata) | |||
542 | DEBUGFS_ADD(aid); | 552 | DEBUGFS_ADD(aid); |
543 | DEBUGFS_ADD(last_beacon); | 553 | DEBUGFS_ADD(last_beacon); |
544 | DEBUGFS_ADD(ave_beacon); | 554 | DEBUGFS_ADD(ave_beacon); |
555 | DEBUGFS_ADD(beacon_timeout); | ||
545 | DEBUGFS_ADD_MODE(smps, 0600); | 556 | DEBUGFS_ADD_MODE(smps, 0600); |
546 | DEBUGFS_ADD_MODE(tkip_mic_test, 0200); | 557 | DEBUGFS_ADD_MODE(tkip_mic_test, 0200); |
547 | DEBUGFS_ADD_MODE(uapsd_queues, 0600); | 558 | DEBUGFS_ADD_MODE(uapsd_queues, 0600); |
diff --git a/net/mac80211/debugfs_sta.c b/net/mac80211/debugfs_sta.c index 4f841fe559df..44e201d60a13 100644 --- a/net/mac80211/debugfs_sta.c +++ b/net/mac80211/debugfs_sta.c | |||
@@ -54,6 +54,7 @@ STA_FILE(aid, sta.aid, D); | |||
54 | STA_FILE(dev, sdata->name, S); | 54 | STA_FILE(dev, sdata->name, S); |
55 | STA_FILE(last_signal, last_signal, D); | 55 | STA_FILE(last_signal, last_signal, D); |
56 | STA_FILE(last_ack_signal, last_ack_signal, D); | 56 | STA_FILE(last_ack_signal, last_ack_signal, D); |
57 | STA_FILE(beacon_loss_count, beacon_loss_count, D); | ||
57 | 58 | ||
58 | static ssize_t sta_flags_read(struct file *file, char __user *userbuf, | 59 | static ssize_t sta_flags_read(struct file *file, char __user *userbuf, |
59 | size_t count, loff_t *ppos) | 60 | size_t count, loff_t *ppos) |
@@ -434,6 +435,7 @@ void ieee80211_sta_debugfs_add(struct sta_info *sta) | |||
434 | DEBUGFS_ADD(agg_status); | 435 | DEBUGFS_ADD(agg_status); |
435 | DEBUGFS_ADD(dev); | 436 | DEBUGFS_ADD(dev); |
436 | DEBUGFS_ADD(last_signal); | 437 | DEBUGFS_ADD(last_signal); |
438 | DEBUGFS_ADD(beacon_loss_count); | ||
437 | DEBUGFS_ADD(ht_capa); | 439 | DEBUGFS_ADD(ht_capa); |
438 | DEBUGFS_ADD(vht_capa); | 440 | DEBUGFS_ADD(vht_capa); |
439 | DEBUGFS_ADD(last_ack_signal); | 441 | DEBUGFS_ADD(last_ack_signal); |
diff --git a/net/mac80211/ibss.c b/net/mac80211/ibss.c index 539d4a11b47b..2a0b2186d98f 100644 --- a/net/mac80211/ibss.c +++ b/net/mac80211/ibss.c | |||
@@ -44,7 +44,6 @@ static void __ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata, | |||
44 | struct ieee80211_if_ibss *ifibss = &sdata->u.ibss; | 44 | struct ieee80211_if_ibss *ifibss = &sdata->u.ibss; |
45 | struct ieee80211_local *local = sdata->local; | 45 | struct ieee80211_local *local = sdata->local; |
46 | int rates, i; | 46 | int rates, i; |
47 | struct sk_buff *skb; | ||
48 | struct ieee80211_mgmt *mgmt; | 47 | struct ieee80211_mgmt *mgmt; |
49 | u8 *pos; | 48 | u8 *pos; |
50 | struct ieee80211_supported_band *sband; | 49 | struct ieee80211_supported_band *sband; |
@@ -52,20 +51,14 @@ static void __ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata, | |||
52 | u32 bss_change; | 51 | u32 bss_change; |
53 | u8 supp_rates[IEEE80211_MAX_SUPP_RATES]; | 52 | u8 supp_rates[IEEE80211_MAX_SUPP_RATES]; |
54 | struct cfg80211_chan_def chandef; | 53 | struct cfg80211_chan_def chandef; |
54 | struct beacon_data *presp; | ||
55 | int frame_len; | ||
55 | 56 | ||
56 | lockdep_assert_held(&ifibss->mtx); | 57 | lockdep_assert_held(&ifibss->mtx); |
57 | 58 | ||
58 | /* Reset own TSF to allow time synchronization work. */ | 59 | /* Reset own TSF to allow time synchronization work. */ |
59 | drv_reset_tsf(local, sdata); | 60 | drv_reset_tsf(local, sdata); |
60 | 61 | ||
61 | skb = ifibss->skb; | ||
62 | RCU_INIT_POINTER(ifibss->presp, NULL); | ||
63 | synchronize_rcu(); | ||
64 | skb->data = skb->head; | ||
65 | skb->len = 0; | ||
66 | skb_reset_tail_pointer(skb); | ||
67 | skb_reserve(skb, sdata->local->hw.extra_tx_headroom); | ||
68 | |||
69 | if (!ether_addr_equal(ifibss->bssid, bssid)) | 62 | if (!ether_addr_equal(ifibss->bssid, bssid)) |
70 | sta_info_flush(sdata); | 63 | sta_info_flush(sdata); |
71 | 64 | ||
@@ -73,10 +66,19 @@ static void __ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata, | |||
73 | if (sdata->vif.bss_conf.ibss_joined) { | 66 | if (sdata->vif.bss_conf.ibss_joined) { |
74 | sdata->vif.bss_conf.ibss_joined = false; | 67 | sdata->vif.bss_conf.ibss_joined = false; |
75 | sdata->vif.bss_conf.ibss_creator = false; | 68 | sdata->vif.bss_conf.ibss_creator = false; |
69 | sdata->vif.bss_conf.enable_beacon = false; | ||
76 | netif_carrier_off(sdata->dev); | 70 | netif_carrier_off(sdata->dev); |
77 | ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_IBSS); | 71 | ieee80211_bss_info_change_notify(sdata, |
72 | BSS_CHANGED_IBSS | | ||
73 | BSS_CHANGED_BEACON_ENABLED); | ||
78 | } | 74 | } |
79 | 75 | ||
76 | presp = rcu_dereference_protected(ifibss->presp, | ||
77 | lockdep_is_held(&ifibss->mtx)); | ||
78 | rcu_assign_pointer(ifibss->presp, NULL); | ||
79 | if (presp) | ||
80 | kfree_rcu(presp, rcu_head); | ||
81 | |||
80 | sdata->drop_unencrypted = capability & WLAN_CAPABILITY_PRIVACY ? 1 : 0; | 82 | sdata->drop_unencrypted = capability & WLAN_CAPABILITY_PRIVACY ? 1 : 0; |
81 | 83 | ||
82 | cfg80211_chandef_create(&chandef, chan, ifibss->channel_type); | 84 | cfg80211_chandef_create(&chandef, chan, ifibss->channel_type); |
@@ -98,19 +100,24 @@ static void __ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata, | |||
98 | 100 | ||
99 | sband = local->hw.wiphy->bands[chan->band]; | 101 | sband = local->hw.wiphy->bands[chan->band]; |
100 | 102 | ||
101 | /* build supported rates array */ | ||
102 | pos = supp_rates; | ||
103 | for (i = 0; i < sband->n_bitrates; i++) { | ||
104 | int rate = sband->bitrates[i].bitrate; | ||
105 | u8 basic = 0; | ||
106 | if (basic_rates & BIT(i)) | ||
107 | basic = 0x80; | ||
108 | *pos++ = basic | (u8) (rate / 5); | ||
109 | } | ||
110 | |||
111 | /* Build IBSS probe response */ | 103 | /* Build IBSS probe response */ |
112 | mgmt = (void *) skb_put(skb, 24 + sizeof(mgmt->u.beacon)); | 104 | frame_len = sizeof(struct ieee80211_hdr_3addr) + |
113 | memset(mgmt, 0, 24 + sizeof(mgmt->u.beacon)); | 105 | 12 /* struct ieee80211_mgmt.u.beacon */ + |
106 | 2 + IEEE80211_MAX_SSID_LEN /* max SSID */ + | ||
107 | 2 + 8 /* max Supported Rates */ + | ||
108 | 3 /* max DS params */ + | ||
109 | 4 /* IBSS params */ + | ||
110 | 2 + (IEEE80211_MAX_SUPP_RATES - 8) + | ||
111 | 2 + sizeof(struct ieee80211_ht_cap) + | ||
112 | 2 + sizeof(struct ieee80211_ht_operation) + | ||
113 | ifibss->ie_len; | ||
114 | presp = kzalloc(sizeof(*presp) + frame_len, GFP_KERNEL); | ||
115 | if (!presp) | ||
116 | return; | ||
117 | |||
118 | presp->head = (void *)(presp + 1); | ||
119 | |||
120 | mgmt = (void *) presp->head; | ||
114 | mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT | | 121 | mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT | |
115 | IEEE80211_STYPE_PROBE_RESP); | 122 | IEEE80211_STYPE_PROBE_RESP); |
116 | eth_broadcast_addr(mgmt->da); | 123 | eth_broadcast_addr(mgmt->da); |
@@ -120,27 +127,30 @@ static void __ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata, | |||
120 | mgmt->u.beacon.timestamp = cpu_to_le64(tsf); | 127 | mgmt->u.beacon.timestamp = cpu_to_le64(tsf); |
121 | mgmt->u.beacon.capab_info = cpu_to_le16(capability); | 128 | mgmt->u.beacon.capab_info = cpu_to_le16(capability); |
122 | 129 | ||
123 | pos = skb_put(skb, 2 + ifibss->ssid_len); | 130 | pos = (u8 *)mgmt + offsetof(struct ieee80211_mgmt, u.beacon.variable); |
131 | |||
124 | *pos++ = WLAN_EID_SSID; | 132 | *pos++ = WLAN_EID_SSID; |
125 | *pos++ = ifibss->ssid_len; | 133 | *pos++ = ifibss->ssid_len; |
126 | memcpy(pos, ifibss->ssid, ifibss->ssid_len); | 134 | memcpy(pos, ifibss->ssid, ifibss->ssid_len); |
135 | pos += ifibss->ssid_len; | ||
127 | 136 | ||
128 | rates = sband->n_bitrates; | 137 | rates = min_t(int, 8, sband->n_bitrates); |
129 | if (rates > 8) | ||
130 | rates = 8; | ||
131 | pos = skb_put(skb, 2 + rates); | ||
132 | *pos++ = WLAN_EID_SUPP_RATES; | 138 | *pos++ = WLAN_EID_SUPP_RATES; |
133 | *pos++ = rates; | 139 | *pos++ = rates; |
134 | memcpy(pos, supp_rates, rates); | 140 | for (i = 0; i < rates; i++) { |
141 | int rate = sband->bitrates[i].bitrate; | ||
142 | u8 basic = 0; | ||
143 | if (basic_rates & BIT(i)) | ||
144 | basic = 0x80; | ||
145 | *pos++ = basic | (u8) (rate / 5); | ||
146 | } | ||
135 | 147 | ||
136 | if (sband->band == IEEE80211_BAND_2GHZ) { | 148 | if (sband->band == IEEE80211_BAND_2GHZ) { |
137 | pos = skb_put(skb, 2 + 1); | ||
138 | *pos++ = WLAN_EID_DS_PARAMS; | 149 | *pos++ = WLAN_EID_DS_PARAMS; |
139 | *pos++ = 1; | 150 | *pos++ = 1; |
140 | *pos++ = ieee80211_frequency_to_channel(chan->center_freq); | 151 | *pos++ = ieee80211_frequency_to_channel(chan->center_freq); |
141 | } | 152 | } |
142 | 153 | ||
143 | pos = skb_put(skb, 2 + 2); | ||
144 | *pos++ = WLAN_EID_IBSS_PARAMS; | 154 | *pos++ = WLAN_EID_IBSS_PARAMS; |
145 | *pos++ = 2; | 155 | *pos++ = 2; |
146 | /* FIX: set ATIM window based on scan results */ | 156 | /* FIX: set ATIM window based on scan results */ |
@@ -148,23 +158,25 @@ static void __ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata, | |||
148 | *pos++ = 0; | 158 | *pos++ = 0; |
149 | 159 | ||
150 | if (sband->n_bitrates > 8) { | 160 | if (sband->n_bitrates > 8) { |
151 | rates = sband->n_bitrates - 8; | ||
152 | pos = skb_put(skb, 2 + rates); | ||
153 | *pos++ = WLAN_EID_EXT_SUPP_RATES; | 161 | *pos++ = WLAN_EID_EXT_SUPP_RATES; |
154 | *pos++ = rates; | 162 | *pos++ = sband->n_bitrates - 8; |
155 | memcpy(pos, &supp_rates[8], rates); | 163 | for (i = 8; i < sband->n_bitrates; i++) { |
164 | int rate = sband->bitrates[i].bitrate; | ||
165 | u8 basic = 0; | ||
166 | if (basic_rates & BIT(i)) | ||
167 | basic = 0x80; | ||
168 | *pos++ = basic | (u8) (rate / 5); | ||
169 | } | ||
156 | } | 170 | } |
157 | 171 | ||
158 | if (ifibss->ie_len) | 172 | if (ifibss->ie_len) { |
159 | memcpy(skb_put(skb, ifibss->ie_len), | 173 | memcpy(pos, ifibss->ie, ifibss->ie_len); |
160 | ifibss->ie, ifibss->ie_len); | 174 | pos += ifibss->ie_len; |
175 | } | ||
161 | 176 | ||
162 | /* add HT capability and information IEs */ | 177 | /* add HT capability and information IEs */ |
163 | if (chandef.width != NL80211_CHAN_WIDTH_20_NOHT && | 178 | if (chandef.width != NL80211_CHAN_WIDTH_20_NOHT && |
164 | sband->ht_cap.ht_supported) { | 179 | sband->ht_cap.ht_supported) { |
165 | pos = skb_put(skb, 4 + | ||
166 | sizeof(struct ieee80211_ht_cap) + | ||
167 | sizeof(struct ieee80211_ht_operation)); | ||
168 | pos = ieee80211_ie_build_ht_cap(pos, &sband->ht_cap, | 180 | pos = ieee80211_ie_build_ht_cap(pos, &sband->ht_cap, |
169 | sband->ht_cap.cap); | 181 | sband->ht_cap.cap); |
170 | /* | 182 | /* |
@@ -177,7 +189,6 @@ static void __ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata, | |||
177 | } | 189 | } |
178 | 190 | ||
179 | if (local->hw.queues >= IEEE80211_NUM_ACS) { | 191 | if (local->hw.queues >= IEEE80211_NUM_ACS) { |
180 | pos = skb_put(skb, 9); | ||
181 | *pos++ = WLAN_EID_VENDOR_SPECIFIC; | 192 | *pos++ = WLAN_EID_VENDOR_SPECIFIC; |
182 | *pos++ = 7; /* len */ | 193 | *pos++ = 7; /* len */ |
183 | *pos++ = 0x00; /* Microsoft OUI 00:50:F2 */ | 194 | *pos++ = 0x00; /* Microsoft OUI 00:50:F2 */ |
@@ -189,7 +200,11 @@ static void __ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata, | |||
189 | *pos++ = 0; /* U-APSD no in use */ | 200 | *pos++ = 0; /* U-APSD no in use */ |
190 | } | 201 | } |
191 | 202 | ||
192 | rcu_assign_pointer(ifibss->presp, skb); | 203 | presp->head_len = pos - presp->head; |
204 | if (WARN_ON(presp->head_len > frame_len)) | ||
205 | return; | ||
206 | |||
207 | rcu_assign_pointer(ifibss->presp, presp); | ||
193 | 208 | ||
194 | sdata->vif.bss_conf.enable_beacon = true; | 209 | sdata->vif.bss_conf.enable_beacon = true; |
195 | sdata->vif.bss_conf.beacon_int = beacon_int; | 210 | sdata->vif.bss_conf.beacon_int = beacon_int; |
@@ -227,7 +242,7 @@ static void __ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata, | |||
227 | round_jiffies(jiffies + IEEE80211_IBSS_MERGE_INTERVAL)); | 242 | round_jiffies(jiffies + IEEE80211_IBSS_MERGE_INTERVAL)); |
228 | 243 | ||
229 | bss = cfg80211_inform_bss_frame(local->hw.wiphy, chan, | 244 | bss = cfg80211_inform_bss_frame(local->hw.wiphy, chan, |
230 | mgmt, skb->len, 0, GFP_KERNEL); | 245 | mgmt, presp->head_len, 0, GFP_KERNEL); |
231 | cfg80211_put_bss(local->hw.wiphy, bss); | 246 | cfg80211_put_bss(local->hw.wiphy, bss); |
232 | netif_carrier_on(sdata->dev); | 247 | netif_carrier_on(sdata->dev); |
233 | cfg80211_ibss_joined(sdata->dev, ifibss->bssid, GFP_KERNEL); | 248 | cfg80211_ibss_joined(sdata->dev, ifibss->bssid, GFP_KERNEL); |
@@ -448,7 +463,7 @@ static void ieee80211_rx_bss_info(struct ieee80211_sub_if_data *sdata, | |||
448 | struct ieee80211_supported_band *sband = local->hw.wiphy->bands[band]; | 463 | struct ieee80211_supported_band *sband = local->hw.wiphy->bands[band]; |
449 | bool rates_updated = false; | 464 | bool rates_updated = false; |
450 | 465 | ||
451 | if (elems->ds_params && elems->ds_params_len == 1) | 466 | if (elems->ds_params) |
452 | freq = ieee80211_channel_to_frequency(elems->ds_params[0], | 467 | freq = ieee80211_channel_to_frequency(elems->ds_params[0], |
453 | band); | 468 | band); |
454 | else | 469 | else |
@@ -822,8 +837,7 @@ static void ieee80211_rx_mgmt_probe_req(struct ieee80211_sub_if_data *sdata, | |||
822 | struct ieee80211_local *local = sdata->local; | 837 | struct ieee80211_local *local = sdata->local; |
823 | int tx_last_beacon, len = req->len; | 838 | int tx_last_beacon, len = req->len; |
824 | struct sk_buff *skb; | 839 | struct sk_buff *skb; |
825 | struct ieee80211_mgmt *resp; | 840 | struct beacon_data *presp; |
826 | struct sk_buff *presp; | ||
827 | u8 *pos, *end; | 841 | u8 *pos, *end; |
828 | 842 | ||
829 | lockdep_assert_held(&ifibss->mtx); | 843 | lockdep_assert_held(&ifibss->mtx); |
@@ -864,13 +878,15 @@ static void ieee80211_rx_mgmt_probe_req(struct ieee80211_sub_if_data *sdata, | |||
864 | } | 878 | } |
865 | 879 | ||
866 | /* Reply with ProbeResp */ | 880 | /* Reply with ProbeResp */ |
867 | skb = skb_copy(presp, GFP_KERNEL); | 881 | skb = dev_alloc_skb(local->tx_headroom + presp->head_len); |
868 | if (!skb) | 882 | if (!skb) |
869 | return; | 883 | return; |
870 | 884 | ||
871 | resp = (struct ieee80211_mgmt *) skb->data; | 885 | skb_reserve(skb, local->tx_headroom); |
872 | memcpy(resp->da, mgmt->sa, ETH_ALEN); | 886 | memcpy(skb_put(skb, presp->head_len), presp->head, presp->head_len); |
873 | ibss_dbg(sdata, "Sending ProbeResp to %pM\n", resp->da); | 887 | |
888 | memcpy(((struct ieee80211_mgmt *) skb->data)->da, mgmt->sa, ETH_ALEN); | ||
889 | ibss_dbg(sdata, "Sending ProbeResp to %pM\n", mgmt->sa); | ||
874 | IEEE80211_SKB_CB(skb)->flags |= IEEE80211_TX_INTFL_DONT_ENCRYPT; | 890 | IEEE80211_SKB_CB(skb)->flags |= IEEE80211_TX_INTFL_DONT_ENCRYPT; |
875 | ieee80211_tx_skb(sdata, skb); | 891 | ieee80211_tx_skb(sdata, skb); |
876 | } | 892 | } |
@@ -1020,23 +1036,8 @@ void ieee80211_ibss_notify_scan_completed(struct ieee80211_local *local) | |||
1020 | int ieee80211_ibss_join(struct ieee80211_sub_if_data *sdata, | 1036 | int ieee80211_ibss_join(struct ieee80211_sub_if_data *sdata, |
1021 | struct cfg80211_ibss_params *params) | 1037 | struct cfg80211_ibss_params *params) |
1022 | { | 1038 | { |
1023 | struct sk_buff *skb; | ||
1024 | u32 changed = 0; | 1039 | u32 changed = 0; |
1025 | 1040 | ||
1026 | skb = dev_alloc_skb(sdata->local->hw.extra_tx_headroom + | ||
1027 | sizeof(struct ieee80211_hdr_3addr) + | ||
1028 | 12 /* struct ieee80211_mgmt.u.beacon */ + | ||
1029 | 2 + IEEE80211_MAX_SSID_LEN /* max SSID */ + | ||
1030 | 2 + 8 /* max Supported Rates */ + | ||
1031 | 3 /* max DS params */ + | ||
1032 | 4 /* IBSS params */ + | ||
1033 | 2 + (IEEE80211_MAX_SUPP_RATES - 8) + | ||
1034 | 2 + sizeof(struct ieee80211_ht_cap) + | ||
1035 | 2 + sizeof(struct ieee80211_ht_operation) + | ||
1036 | params->ie_len); | ||
1037 | if (!skb) | ||
1038 | return -ENOMEM; | ||
1039 | |||
1040 | mutex_lock(&sdata->u.ibss.mtx); | 1041 | mutex_lock(&sdata->u.ibss.mtx); |
1041 | 1042 | ||
1042 | if (params->bssid) { | 1043 | if (params->bssid) { |
@@ -1065,7 +1066,6 @@ int ieee80211_ibss_join(struct ieee80211_sub_if_data *sdata, | |||
1065 | sdata->u.ibss.ie_len = params->ie_len; | 1066 | sdata->u.ibss.ie_len = params->ie_len; |
1066 | } | 1067 | } |
1067 | 1068 | ||
1068 | sdata->u.ibss.skb = skb; | ||
1069 | sdata->u.ibss.state = IEEE80211_IBSS_MLME_SEARCH; | 1069 | sdata->u.ibss.state = IEEE80211_IBSS_MLME_SEARCH; |
1070 | sdata->u.ibss.ibss_join_req = jiffies; | 1070 | sdata->u.ibss.ibss_join_req = jiffies; |
1071 | 1071 | ||
@@ -1101,13 +1101,13 @@ int ieee80211_ibss_join(struct ieee80211_sub_if_data *sdata, | |||
1101 | 1101 | ||
1102 | int ieee80211_ibss_leave(struct ieee80211_sub_if_data *sdata) | 1102 | int ieee80211_ibss_leave(struct ieee80211_sub_if_data *sdata) |
1103 | { | 1103 | { |
1104 | struct sk_buff *skb; | ||
1105 | struct ieee80211_if_ibss *ifibss = &sdata->u.ibss; | 1104 | struct ieee80211_if_ibss *ifibss = &sdata->u.ibss; |
1106 | struct ieee80211_local *local = sdata->local; | 1105 | struct ieee80211_local *local = sdata->local; |
1107 | struct cfg80211_bss *cbss; | 1106 | struct cfg80211_bss *cbss; |
1108 | u16 capability; | 1107 | u16 capability; |
1109 | int active_ibss; | 1108 | int active_ibss; |
1110 | struct sta_info *sta; | 1109 | struct sta_info *sta; |
1110 | struct beacon_data *presp; | ||
1111 | 1111 | ||
1112 | mutex_lock(&sdata->u.ibss.mtx); | 1112 | mutex_lock(&sdata->u.ibss.mtx); |
1113 | 1113 | ||
@@ -1153,8 +1153,8 @@ int ieee80211_ibss_leave(struct ieee80211_sub_if_data *sdata) | |||
1153 | 1153 | ||
1154 | /* remove beacon */ | 1154 | /* remove beacon */ |
1155 | kfree(sdata->u.ibss.ie); | 1155 | kfree(sdata->u.ibss.ie); |
1156 | skb = rcu_dereference_protected(sdata->u.ibss.presp, | 1156 | presp = rcu_dereference_protected(ifibss->presp, |
1157 | lockdep_is_held(&sdata->u.ibss.mtx)); | 1157 | lockdep_is_held(&sdata->u.ibss.mtx)); |
1158 | RCU_INIT_POINTER(sdata->u.ibss.presp, NULL); | 1158 | RCU_INIT_POINTER(sdata->u.ibss.presp, NULL); |
1159 | sdata->vif.bss_conf.ibss_joined = false; | 1159 | sdata->vif.bss_conf.ibss_joined = false; |
1160 | sdata->vif.bss_conf.ibss_creator = false; | 1160 | sdata->vif.bss_conf.ibss_creator = false; |
@@ -1163,7 +1163,7 @@ int ieee80211_ibss_leave(struct ieee80211_sub_if_data *sdata) | |||
1163 | ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_BEACON_ENABLED | | 1163 | ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_BEACON_ENABLED | |
1164 | BSS_CHANGED_IBSS); | 1164 | BSS_CHANGED_IBSS); |
1165 | synchronize_rcu(); | 1165 | synchronize_rcu(); |
1166 | kfree_skb(skb); | 1166 | kfree(presp); |
1167 | 1167 | ||
1168 | skb_queue_purge(&sdata->skb_queue); | 1168 | skb_queue_purge(&sdata->skb_queue); |
1169 | 1169 | ||
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h index 0b09716d22ad..135ab463cfd9 100644 --- a/net/mac80211/ieee80211_i.h +++ b/net/mac80211/ieee80211_i.h | |||
@@ -443,7 +443,7 @@ struct ieee80211_if_managed { | |||
443 | 443 | ||
444 | u8 use_4addr; | 444 | u8 use_4addr; |
445 | 445 | ||
446 | u8 p2p_noa_index; | 446 | s16 p2p_noa_index; |
447 | 447 | ||
448 | /* Signal strength from the last Beacon frame in the current BSS. */ | 448 | /* Signal strength from the last Beacon frame in the current BSS. */ |
449 | int last_beacon_signal; | 449 | int last_beacon_signal; |
@@ -509,8 +509,7 @@ struct ieee80211_if_ibss { | |||
509 | 509 | ||
510 | unsigned long ibss_join_req; | 510 | unsigned long ibss_join_req; |
511 | /* probe response/beacon for IBSS */ | 511 | /* probe response/beacon for IBSS */ |
512 | struct sk_buff __rcu *presp; | 512 | struct beacon_data __rcu *presp; |
513 | struct sk_buff *skb; | ||
514 | 513 | ||
515 | spinlock_t incomplete_lock; | 514 | spinlock_t incomplete_lock; |
516 | struct list_head incomplete_stations; | 515 | struct list_head incomplete_stations; |
@@ -1023,8 +1022,7 @@ struct ieee80211_local { | |||
1023 | struct ieee80211_sub_if_data __rcu *scan_sdata; | 1022 | struct ieee80211_sub_if_data __rcu *scan_sdata; |
1024 | struct ieee80211_channel *csa_channel; | 1023 | struct ieee80211_channel *csa_channel; |
1025 | /* For backward compatibility only -- do not use */ | 1024 | /* For backward compatibility only -- do not use */ |
1026 | struct ieee80211_channel *_oper_channel; | 1025 | struct cfg80211_chan_def _oper_chandef; |
1027 | enum nl80211_channel_type _oper_channel_type; | ||
1028 | 1026 | ||
1029 | /* Temporary remain-on-channel for off-channel operations */ | 1027 | /* Temporary remain-on-channel for off-channel operations */ |
1030 | struct ieee80211_channel *tmp_channel; | 1028 | struct ieee80211_channel *tmp_channel; |
@@ -1160,11 +1158,8 @@ struct ieee802_11_elems { | |||
1160 | /* pointers to IEs */ | 1158 | /* pointers to IEs */ |
1161 | const u8 *ssid; | 1159 | const u8 *ssid; |
1162 | const u8 *supp_rates; | 1160 | const u8 *supp_rates; |
1163 | const u8 *fh_params; | ||
1164 | const u8 *ds_params; | 1161 | const u8 *ds_params; |
1165 | const u8 *cf_params; | ||
1166 | const struct ieee80211_tim_ie *tim; | 1162 | const struct ieee80211_tim_ie *tim; |
1167 | const u8 *ibss_params; | ||
1168 | const u8 *challenge; | 1163 | const u8 *challenge; |
1169 | const u8 *rsn; | 1164 | const u8 *rsn; |
1170 | const u8 *erp_info; | 1165 | const u8 *erp_info; |
@@ -1186,21 +1181,15 @@ struct ieee802_11_elems { | |||
1186 | const struct ieee80211_channel_sw_ie *ch_switch_ie; | 1181 | const struct ieee80211_channel_sw_ie *ch_switch_ie; |
1187 | const u8 *country_elem; | 1182 | const u8 *country_elem; |
1188 | const u8 *pwr_constr_elem; | 1183 | const u8 *pwr_constr_elem; |
1189 | const u8 *quiet_elem; /* first quite element */ | 1184 | const struct ieee80211_timeout_interval_ie *timeout_int; |
1190 | const u8 *timeout_int; | ||
1191 | const u8 *opmode_notif; | 1185 | const u8 *opmode_notif; |
1192 | 1186 | ||
1193 | /* length of them, respectively */ | 1187 | /* length of them, respectively */ |
1194 | u8 ssid_len; | 1188 | u8 ssid_len; |
1195 | u8 supp_rates_len; | 1189 | u8 supp_rates_len; |
1196 | u8 fh_params_len; | ||
1197 | u8 ds_params_len; | ||
1198 | u8 cf_params_len; | ||
1199 | u8 tim_len; | 1190 | u8 tim_len; |
1200 | u8 ibss_params_len; | ||
1201 | u8 challenge_len; | 1191 | u8 challenge_len; |
1202 | u8 rsn_len; | 1192 | u8 rsn_len; |
1203 | u8 erp_info_len; | ||
1204 | u8 ext_supp_rates_len; | 1193 | u8 ext_supp_rates_len; |
1205 | u8 wmm_info_len; | 1194 | u8 wmm_info_len; |
1206 | u8 wmm_param_len; | 1195 | u8 wmm_param_len; |
@@ -1210,9 +1199,6 @@ struct ieee802_11_elems { | |||
1210 | u8 prep_len; | 1199 | u8 prep_len; |
1211 | u8 perr_len; | 1200 | u8 perr_len; |
1212 | u8 country_elem_len; | 1201 | u8 country_elem_len; |
1213 | u8 quiet_elem_len; | ||
1214 | u8 num_of_quiet_elem; /* can be more the one */ | ||
1215 | u8 timeout_int_len; | ||
1216 | 1202 | ||
1217 | /* whether a parse error occurred while retrieving these elements */ | 1203 | /* whether a parse error occurred while retrieving these elements */ |
1218 | bool parse_error; | 1204 | bool parse_error; |
@@ -1330,7 +1316,8 @@ void ieee80211_offchannel_stop_vifs(struct ieee80211_local *local); | |||
1330 | void ieee80211_offchannel_return(struct ieee80211_local *local); | 1316 | void ieee80211_offchannel_return(struct ieee80211_local *local); |
1331 | void ieee80211_roc_setup(struct ieee80211_local *local); | 1317 | void ieee80211_roc_setup(struct ieee80211_local *local); |
1332 | void ieee80211_start_next_roc(struct ieee80211_local *local); | 1318 | void ieee80211_start_next_roc(struct ieee80211_local *local); |
1333 | void ieee80211_roc_purge(struct ieee80211_sub_if_data *sdata); | 1319 | void ieee80211_roc_purge(struct ieee80211_local *local, |
1320 | struct ieee80211_sub_if_data *sdata); | ||
1334 | void ieee80211_roc_notify_destroy(struct ieee80211_roc_work *roc, bool free); | 1321 | void ieee80211_roc_notify_destroy(struct ieee80211_roc_work *roc, bool free); |
1335 | void ieee80211_sw_roc_work(struct work_struct *work); | 1322 | void ieee80211_sw_roc_work(struct work_struct *work); |
1336 | void ieee80211_handle_roc_started(struct ieee80211_roc_work *roc); | 1323 | void ieee80211_handle_roc_started(struct ieee80211_roc_work *roc); |
@@ -1351,6 +1338,8 @@ void ieee80211_adjust_monitor_flags(struct ieee80211_sub_if_data *sdata, | |||
1351 | const int offset); | 1338 | const int offset); |
1352 | int ieee80211_do_open(struct wireless_dev *wdev, bool coming_up); | 1339 | int ieee80211_do_open(struct wireless_dev *wdev, bool coming_up); |
1353 | void ieee80211_sdata_stop(struct ieee80211_sub_if_data *sdata); | 1340 | void ieee80211_sdata_stop(struct ieee80211_sub_if_data *sdata); |
1341 | int ieee80211_add_virtual_monitor(struct ieee80211_local *local); | ||
1342 | void ieee80211_del_virtual_monitor(struct ieee80211_local *local); | ||
1354 | 1343 | ||
1355 | bool __ieee80211_recalc_txpower(struct ieee80211_sub_if_data *sdata); | 1344 | bool __ieee80211_recalc_txpower(struct ieee80211_sub_if_data *sdata); |
1356 | void ieee80211_recalc_txpower(struct ieee80211_sub_if_data *sdata); | 1345 | void ieee80211_recalc_txpower(struct ieee80211_sub_if_data *sdata); |
@@ -1505,11 +1494,15 @@ static inline void ieee80211_tx_skb(struct ieee80211_sub_if_data *sdata, | |||
1505 | ieee80211_tx_skb_tid(sdata, skb, 7); | 1494 | ieee80211_tx_skb_tid(sdata, skb, 7); |
1506 | } | 1495 | } |
1507 | 1496 | ||
1508 | void ieee802_11_parse_elems(u8 *start, size_t len, | ||
1509 | struct ieee802_11_elems *elems); | ||
1510 | u32 ieee802_11_parse_elems_crc(u8 *start, size_t len, | 1497 | u32 ieee802_11_parse_elems_crc(u8 *start, size_t len, |
1511 | struct ieee802_11_elems *elems, | 1498 | struct ieee802_11_elems *elems, |
1512 | u64 filter, u32 crc); | 1499 | u64 filter, u32 crc); |
1500 | static inline void ieee802_11_parse_elems(u8 *start, size_t len, | ||
1501 | struct ieee802_11_elems *elems) | ||
1502 | { | ||
1503 | ieee802_11_parse_elems_crc(start, len, elems, 0, 0); | ||
1504 | } | ||
1505 | |||
1513 | u32 ieee80211_mandatory_rates(struct ieee80211_local *local, | 1506 | u32 ieee80211_mandatory_rates(struct ieee80211_local *local, |
1514 | enum ieee80211_band band); | 1507 | enum ieee80211_band band); |
1515 | 1508 | ||
diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c index 69aaba79a9f7..146b1320af4e 100644 --- a/net/mac80211/iface.c +++ b/net/mac80211/iface.c | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * Interface handling (except master interface) | 2 | * Interface handling |
3 | * | 3 | * |
4 | * Copyright 2002-2005, Instant802 Networks, Inc. | 4 | * Copyright 2002-2005, Instant802 Networks, Inc. |
5 | * Copyright 2005-2006, Devicescape Software, Inc. | 5 | * Copyright 2005-2006, Devicescape Software, Inc. |
@@ -346,7 +346,7 @@ static void ieee80211_set_default_queues(struct ieee80211_sub_if_data *sdata) | |||
346 | sdata->vif.cab_queue = IEEE80211_INVAL_HW_QUEUE; | 346 | sdata->vif.cab_queue = IEEE80211_INVAL_HW_QUEUE; |
347 | } | 347 | } |
348 | 348 | ||
349 | static int ieee80211_add_virtual_monitor(struct ieee80211_local *local) | 349 | int ieee80211_add_virtual_monitor(struct ieee80211_local *local) |
350 | { | 350 | { |
351 | struct ieee80211_sub_if_data *sdata; | 351 | struct ieee80211_sub_if_data *sdata; |
352 | int ret; | 352 | int ret; |
@@ -399,7 +399,7 @@ static int ieee80211_add_virtual_monitor(struct ieee80211_local *local) | |||
399 | return 0; | 399 | return 0; |
400 | } | 400 | } |
401 | 401 | ||
402 | static void ieee80211_del_virtual_monitor(struct ieee80211_local *local) | 402 | void ieee80211_del_virtual_monitor(struct ieee80211_local *local) |
403 | { | 403 | { |
404 | struct ieee80211_sub_if_data *sdata; | 404 | struct ieee80211_sub_if_data *sdata; |
405 | 405 | ||
@@ -584,7 +584,8 @@ int ieee80211_do_open(struct wireless_dev *wdev, bool coming_up) | |||
584 | case NL80211_IFTYPE_P2P_DEVICE: | 584 | case NL80211_IFTYPE_P2P_DEVICE: |
585 | break; | 585 | break; |
586 | default: | 586 | default: |
587 | netif_carrier_on(dev); | 587 | /* not reached */ |
588 | WARN_ON(1); | ||
588 | } | 589 | } |
589 | 590 | ||
590 | /* | 591 | /* |
@@ -641,8 +642,28 @@ int ieee80211_do_open(struct wireless_dev *wdev, bool coming_up) | |||
641 | 642 | ||
642 | ieee80211_recalc_ps(local, -1); | 643 | ieee80211_recalc_ps(local, -1); |
643 | 644 | ||
644 | if (dev) | 645 | if (dev) { |
645 | netif_tx_start_all_queues(dev); | 646 | unsigned long flags; |
647 | int n_acs = IEEE80211_NUM_ACS; | ||
648 | int ac; | ||
649 | |||
650 | if (local->hw.queues < IEEE80211_NUM_ACS) | ||
651 | n_acs = 1; | ||
652 | |||
653 | spin_lock_irqsave(&local->queue_stop_reason_lock, flags); | ||
654 | if (sdata->vif.cab_queue == IEEE80211_INVAL_HW_QUEUE || | ||
655 | (local->queue_stop_reasons[sdata->vif.cab_queue] == 0 && | ||
656 | skb_queue_empty(&local->pending[sdata->vif.cab_queue]))) { | ||
657 | for (ac = 0; ac < n_acs; ac++) { | ||
658 | int ac_queue = sdata->vif.hw_queue[ac]; | ||
659 | |||
660 | if (local->queue_stop_reasons[ac_queue] == 0 && | ||
661 | skb_queue_empty(&local->pending[ac_queue])) | ||
662 | netif_start_subqueue(dev, ac); | ||
663 | } | ||
664 | } | ||
665 | spin_unlock_irqrestore(&local->queue_stop_reason_lock, flags); | ||
666 | } | ||
646 | 667 | ||
647 | return 0; | 668 | return 0; |
648 | err_del_interface: | 669 | err_del_interface: |
@@ -696,7 +717,7 @@ static void ieee80211_do_stop(struct ieee80211_sub_if_data *sdata, | |||
696 | if (sdata->dev) | 717 | if (sdata->dev) |
697 | netif_tx_stop_all_queues(sdata->dev); | 718 | netif_tx_stop_all_queues(sdata->dev); |
698 | 719 | ||
699 | ieee80211_roc_purge(sdata); | 720 | ieee80211_roc_purge(local, sdata); |
700 | 721 | ||
701 | if (sdata->vif.type == NL80211_IFTYPE_STATION) | 722 | if (sdata->vif.type == NL80211_IFTYPE_STATION) |
702 | ieee80211_mgd_stop(sdata); | 723 | ieee80211_mgd_stop(sdata); |
@@ -721,12 +742,7 @@ static void ieee80211_do_stop(struct ieee80211_sub_if_data *sdata, | |||
721 | WARN_ON_ONCE((sdata->vif.type != NL80211_IFTYPE_WDS && flushed > 0) || | 742 | WARN_ON_ONCE((sdata->vif.type != NL80211_IFTYPE_WDS && flushed > 0) || |
722 | (sdata->vif.type == NL80211_IFTYPE_WDS && flushed != 1)); | 743 | (sdata->vif.type == NL80211_IFTYPE_WDS && flushed != 1)); |
723 | 744 | ||
724 | /* | 745 | /* don't count this interface for promisc/allmulti while it is down */ |
725 | * Don't count this interface for promisc/allmulti while it | ||
726 | * is down. dev_mc_unsync() will invoke set_multicast_list | ||
727 | * on the master interface which will sync these down to the | ||
728 | * hardware as filter flags. | ||
729 | */ | ||
730 | if (sdata->flags & IEEE80211_SDATA_ALLMULTI) | 746 | if (sdata->flags & IEEE80211_SDATA_ALLMULTI) |
731 | atomic_dec(&local->iff_allmultis); | 747 | atomic_dec(&local->iff_allmultis); |
732 | 748 | ||
@@ -747,8 +763,6 @@ static void ieee80211_do_stop(struct ieee80211_sub_if_data *sdata, | |||
747 | sdata->dev->addr_len); | 763 | sdata->dev->addr_len); |
748 | spin_unlock_bh(&local->filter_lock); | 764 | spin_unlock_bh(&local->filter_lock); |
749 | netif_addr_unlock_bh(sdata->dev); | 765 | netif_addr_unlock_bh(sdata->dev); |
750 | |||
751 | ieee80211_configure_filter(local); | ||
752 | } | 766 | } |
753 | 767 | ||
754 | del_timer_sync(&local->dynamic_ps_timer); | 768 | del_timer_sync(&local->dynamic_ps_timer); |
@@ -759,6 +773,7 @@ static void ieee80211_do_stop(struct ieee80211_sub_if_data *sdata, | |||
759 | cancel_delayed_work_sync(&sdata->dfs_cac_timer_work); | 773 | cancel_delayed_work_sync(&sdata->dfs_cac_timer_work); |
760 | 774 | ||
761 | if (sdata->wdev.cac_started) { | 775 | if (sdata->wdev.cac_started) { |
776 | WARN_ON(local->suspended); | ||
762 | mutex_lock(&local->iflist_mtx); | 777 | mutex_lock(&local->iflist_mtx); |
763 | ieee80211_vif_release_channel(sdata); | 778 | ieee80211_vif_release_channel(sdata); |
764 | mutex_unlock(&local->iflist_mtx); | 779 | mutex_unlock(&local->iflist_mtx); |
@@ -809,14 +824,9 @@ static void ieee80211_do_stop(struct ieee80211_sub_if_data *sdata, | |||
809 | if (local->monitors == 0) { | 824 | if (local->monitors == 0) { |
810 | local->hw.conf.flags &= ~IEEE80211_CONF_MONITOR; | 825 | local->hw.conf.flags &= ~IEEE80211_CONF_MONITOR; |
811 | hw_reconf_flags |= IEEE80211_CONF_CHANGE_MONITOR; | 826 | hw_reconf_flags |= IEEE80211_CONF_CHANGE_MONITOR; |
812 | ieee80211_del_virtual_monitor(local); | ||
813 | } | 827 | } |
814 | 828 | ||
815 | ieee80211_adjust_monitor_flags(sdata, -1); | 829 | ieee80211_adjust_monitor_flags(sdata, -1); |
816 | ieee80211_configure_filter(local); | ||
817 | mutex_lock(&local->mtx); | ||
818 | ieee80211_recalc_idle(local); | ||
819 | mutex_unlock(&local->mtx); | ||
820 | break; | 830 | break; |
821 | case NL80211_IFTYPE_P2P_DEVICE: | 831 | case NL80211_IFTYPE_P2P_DEVICE: |
822 | /* relies on synchronize_rcu() below */ | 832 | /* relies on synchronize_rcu() below */ |
@@ -846,27 +856,10 @@ static void ieee80211_do_stop(struct ieee80211_sub_if_data *sdata, | |||
846 | /* fall through */ | 856 | /* fall through */ |
847 | case NL80211_IFTYPE_AP: | 857 | case NL80211_IFTYPE_AP: |
848 | skb_queue_purge(&sdata->skb_queue); | 858 | skb_queue_purge(&sdata->skb_queue); |
849 | |||
850 | if (going_down) | ||
851 | drv_remove_interface(local, sdata); | ||
852 | } | 859 | } |
853 | 860 | ||
854 | sdata->bss = NULL; | 861 | sdata->bss = NULL; |
855 | 862 | ||
856 | ieee80211_recalc_ps(local, -1); | ||
857 | |||
858 | if (local->open_count == 0) { | ||
859 | ieee80211_clear_tx_pending(local); | ||
860 | ieee80211_stop_device(local); | ||
861 | |||
862 | /* no reconfiguring after stop! */ | ||
863 | hw_reconf_flags = 0; | ||
864 | } | ||
865 | |||
866 | /* do after stop to avoid reconfiguring when we stop anyway */ | ||
867 | if (hw_reconf_flags) | ||
868 | ieee80211_hw_config(local, hw_reconf_flags); | ||
869 | |||
870 | spin_lock_irqsave(&local->queue_stop_reason_lock, flags); | 863 | spin_lock_irqsave(&local->queue_stop_reason_lock, flags); |
871 | for (i = 0; i < IEEE80211_MAX_QUEUES; i++) { | 864 | for (i = 0; i < IEEE80211_MAX_QUEUES; i++) { |
872 | skb_queue_walk_safe(&local->pending[i], skb, tmp) { | 865 | skb_queue_walk_safe(&local->pending[i], skb, tmp) { |
@@ -879,7 +872,54 @@ static void ieee80211_do_stop(struct ieee80211_sub_if_data *sdata, | |||
879 | } | 872 | } |
880 | spin_unlock_irqrestore(&local->queue_stop_reason_lock, flags); | 873 | spin_unlock_irqrestore(&local->queue_stop_reason_lock, flags); |
881 | 874 | ||
882 | if (local->monitors == local->open_count && local->monitors > 0) | 875 | if (local->open_count == 0) |
876 | ieee80211_clear_tx_pending(local); | ||
877 | |||
878 | /* | ||
879 | * If the interface goes down while suspended, presumably because | ||
880 | * the device was unplugged and that happens before our resume, | ||
881 | * then the driver is already unconfigured and the remainder of | ||
882 | * this function isn't needed. | ||
883 | * XXX: what about WoWLAN? If the device has software state, e.g. | ||
884 | * memory allocated, it might expect teardown commands from | ||
885 | * mac80211 here? | ||
886 | */ | ||
887 | if (local->suspended) { | ||
888 | WARN_ON(local->wowlan); | ||
889 | WARN_ON(rtnl_dereference(local->monitor_sdata)); | ||
890 | return; | ||
891 | } | ||
892 | |||
893 | switch (sdata->vif.type) { | ||
894 | case NL80211_IFTYPE_AP_VLAN: | ||
895 | break; | ||
896 | case NL80211_IFTYPE_MONITOR: | ||
897 | if (local->monitors == 0) | ||
898 | ieee80211_del_virtual_monitor(local); | ||
899 | |||
900 | mutex_lock(&local->mtx); | ||
901 | ieee80211_recalc_idle(local); | ||
902 | mutex_unlock(&local->mtx); | ||
903 | break; | ||
904 | default: | ||
905 | if (going_down) | ||
906 | drv_remove_interface(local, sdata); | ||
907 | } | ||
908 | |||
909 | ieee80211_recalc_ps(local, -1); | ||
910 | |||
911 | if (local->open_count == 0) { | ||
912 | ieee80211_stop_device(local); | ||
913 | |||
914 | /* no reconfiguring after stop! */ | ||
915 | return; | ||
916 | } | ||
917 | |||
918 | /* do after stop to avoid reconfiguring when we stop anyway */ | ||
919 | ieee80211_configure_filter(local); | ||
920 | ieee80211_hw_config(local, hw_reconf_flags); | ||
921 | |||
922 | if (local->monitors == local->open_count) | ||
883 | ieee80211_add_virtual_monitor(local); | 923 | ieee80211_add_virtual_monitor(local); |
884 | } | 924 | } |
885 | 925 | ||
diff --git a/net/mac80211/main.c b/net/mac80211/main.c index c6f81ecc36a1..52136fd5ba97 100644 --- a/net/mac80211/main.c +++ b/net/mac80211/main.c | |||
@@ -95,42 +95,47 @@ static void ieee80211_reconfig_filter(struct work_struct *work) | |||
95 | static u32 ieee80211_hw_conf_chan(struct ieee80211_local *local) | 95 | static u32 ieee80211_hw_conf_chan(struct ieee80211_local *local) |
96 | { | 96 | { |
97 | struct ieee80211_sub_if_data *sdata; | 97 | struct ieee80211_sub_if_data *sdata; |
98 | struct ieee80211_channel *chan; | 98 | struct cfg80211_chan_def chandef = {}; |
99 | u32 changed = 0; | 99 | u32 changed = 0; |
100 | int power; | 100 | int power; |
101 | enum nl80211_channel_type channel_type; | ||
102 | u32 offchannel_flag; | 101 | u32 offchannel_flag; |
103 | 102 | ||
104 | offchannel_flag = local->hw.conf.flags & IEEE80211_CONF_OFFCHANNEL; | 103 | offchannel_flag = local->hw.conf.flags & IEEE80211_CONF_OFFCHANNEL; |
104 | |||
105 | if (local->scan_channel) { | 105 | if (local->scan_channel) { |
106 | chan = local->scan_channel; | 106 | chandef.chan = local->scan_channel; |
107 | /* If scanning on oper channel, use whatever channel-type | 107 | /* If scanning on oper channel, use whatever channel-type |
108 | * is currently in use. | 108 | * is currently in use. |
109 | */ | 109 | */ |
110 | if (chan == local->_oper_channel) | 110 | if (chandef.chan == local->_oper_chandef.chan) { |
111 | channel_type = local->_oper_channel_type; | 111 | chandef = local->_oper_chandef; |
112 | else | 112 | } else { |
113 | channel_type = NL80211_CHAN_NO_HT; | 113 | chandef.width = NL80211_CHAN_WIDTH_20_NOHT; |
114 | chandef.center_freq1 = chandef.chan->center_freq; | ||
115 | } | ||
114 | } else if (local->tmp_channel) { | 116 | } else if (local->tmp_channel) { |
115 | chan = local->tmp_channel; | 117 | chandef.chan = local->tmp_channel; |
116 | channel_type = NL80211_CHAN_NO_HT; | 118 | chandef.width = NL80211_CHAN_WIDTH_20_NOHT; |
117 | } else { | 119 | chandef.center_freq1 = chandef.chan->center_freq; |
118 | chan = local->_oper_channel; | 120 | } else |
119 | channel_type = local->_oper_channel_type; | 121 | chandef = local->_oper_chandef; |
120 | } | 122 | |
121 | 123 | WARN(!cfg80211_chandef_valid(&chandef), | |
122 | if (chan != local->_oper_channel || | 124 | "control:%d MHz width:%d center: %d/%d MHz", |
123 | channel_type != local->_oper_channel_type) | 125 | chandef.chan->center_freq, chandef.width, |
126 | chandef.center_freq1, chandef.center_freq2); | ||
127 | |||
128 | if (!cfg80211_chandef_identical(&chandef, &local->_oper_chandef)) | ||
124 | local->hw.conf.flags |= IEEE80211_CONF_OFFCHANNEL; | 129 | local->hw.conf.flags |= IEEE80211_CONF_OFFCHANNEL; |
125 | else | 130 | else |
126 | local->hw.conf.flags &= ~IEEE80211_CONF_OFFCHANNEL; | 131 | local->hw.conf.flags &= ~IEEE80211_CONF_OFFCHANNEL; |
127 | 132 | ||
128 | offchannel_flag ^= local->hw.conf.flags & IEEE80211_CONF_OFFCHANNEL; | 133 | offchannel_flag ^= local->hw.conf.flags & IEEE80211_CONF_OFFCHANNEL; |
129 | 134 | ||
130 | if (offchannel_flag || chan != local->hw.conf.channel || | 135 | if (offchannel_flag || |
131 | channel_type != local->hw.conf.channel_type) { | 136 | !cfg80211_chandef_identical(&local->hw.conf.chandef, |
132 | local->hw.conf.channel = chan; | 137 | &local->_oper_chandef)) { |
133 | local->hw.conf.channel_type = channel_type; | 138 | local->hw.conf.chandef = chandef; |
134 | changed |= IEEE80211_CONF_CHANGE_CHANNEL; | 139 | changed |= IEEE80211_CONF_CHANGE_CHANNEL; |
135 | } | 140 | } |
136 | 141 | ||
@@ -146,7 +151,7 @@ static u32 ieee80211_hw_conf_chan(struct ieee80211_local *local) | |||
146 | changed |= IEEE80211_CONF_CHANGE_SMPS; | 151 | changed |= IEEE80211_CONF_CHANGE_SMPS; |
147 | } | 152 | } |
148 | 153 | ||
149 | power = chan->max_power; | 154 | power = chandef.chan->max_power; |
150 | 155 | ||
151 | rcu_read_lock(); | 156 | rcu_read_lock(); |
152 | list_for_each_entry_rcu(sdata, &local->interfaces, list) { | 157 | list_for_each_entry_rcu(sdata, &local->interfaces, list) { |
@@ -587,6 +592,8 @@ struct ieee80211_hw *ieee80211_alloc_hw(size_t priv_data_len, | |||
587 | IEEE80211_RADIOTAP_MCS_HAVE_BW; | 592 | IEEE80211_RADIOTAP_MCS_HAVE_BW; |
588 | local->hw.radiotap_vht_details = IEEE80211_RADIOTAP_VHT_KNOWN_GI | | 593 | local->hw.radiotap_vht_details = IEEE80211_RADIOTAP_VHT_KNOWN_GI | |
589 | IEEE80211_RADIOTAP_VHT_KNOWN_BANDWIDTH; | 594 | IEEE80211_RADIOTAP_VHT_KNOWN_BANDWIDTH; |
595 | local->hw.uapsd_queues = IEEE80211_DEFAULT_UAPSD_QUEUES; | ||
596 | local->hw.uapsd_max_sp_len = IEEE80211_DEFAULT_MAX_SP_LEN; | ||
590 | local->user_power_level = IEEE80211_UNSET_POWER_LEVEL; | 597 | local->user_power_level = IEEE80211_UNSET_POWER_LEVEL; |
591 | wiphy->ht_capa_mod_mask = &mac80211_ht_capa_mod_mask; | 598 | wiphy->ht_capa_mod_mask = &mac80211_ht_capa_mod_mask; |
592 | wiphy->vht_capa_mod_mask = &mac80211_vht_capa_mod_mask; | 599 | wiphy->vht_capa_mod_mask = &mac80211_vht_capa_mod_mask; |
@@ -738,11 +745,15 @@ int ieee80211_register_hw(struct ieee80211_hw *hw) | |||
738 | sband = local->hw.wiphy->bands[band]; | 745 | sband = local->hw.wiphy->bands[band]; |
739 | if (!sband) | 746 | if (!sband) |
740 | continue; | 747 | continue; |
741 | if (!local->use_chanctx && !local->_oper_channel) { | 748 | if (!local->use_chanctx && !local->_oper_chandef.chan) { |
742 | /* init channel we're on */ | 749 | /* init channel we're on */ |
743 | local->hw.conf.channel = | 750 | struct cfg80211_chan_def chandef = { |
744 | local->_oper_channel = &sband->channels[0]; | 751 | .chan = &sband->channels[0], |
745 | local->hw.conf.channel_type = NL80211_CHAN_NO_HT; | 752 | .width = NL80211_CHAN_NO_HT, |
753 | .center_freq1 = sband->channels[0].center_freq, | ||
754 | .center_freq2 = 0 | ||
755 | }; | ||
756 | local->hw.conf.chandef = local->_oper_chandef = chandef; | ||
746 | } | 757 | } |
747 | cfg80211_chandef_create(&local->monitor_chandef, | 758 | cfg80211_chandef_create(&local->monitor_chandef, |
748 | &sband->channels[0], | 759 | &sband->channels[0], |
@@ -829,22 +840,10 @@ int ieee80211_register_hw(struct ieee80211_hw *hw) | |||
829 | if (supp_ht) | 840 | if (supp_ht) |
830 | local->scan_ies_len += 2 + sizeof(struct ieee80211_ht_cap); | 841 | local->scan_ies_len += 2 + sizeof(struct ieee80211_ht_cap); |
831 | 842 | ||
832 | if (supp_vht) { | 843 | if (supp_vht) |
833 | local->scan_ies_len += | 844 | local->scan_ies_len += |
834 | 2 + sizeof(struct ieee80211_vht_cap); | 845 | 2 + sizeof(struct ieee80211_vht_cap); |
835 | 846 | ||
836 | /* | ||
837 | * (for now at least), drivers wanting to use VHT must | ||
838 | * support channel contexts, as they contain all the | ||
839 | * necessary VHT information and the global hw config | ||
840 | * doesn't (yet) | ||
841 | */ | ||
842 | if (WARN_ON(!local->use_chanctx)) { | ||
843 | result = -EINVAL; | ||
844 | goto fail_wiphy_register; | ||
845 | } | ||
846 | } | ||
847 | |||
848 | if (!local->ops->hw_scan) { | 847 | if (!local->ops->hw_scan) { |
849 | /* For hw_scan, driver needs to set these up. */ | 848 | /* For hw_scan, driver needs to set these up. */ |
850 | local->hw.wiphy->max_scan_ssids = 4; | 849 | local->hw.wiphy->max_scan_ssids = 4; |
diff --git a/net/mac80211/mesh.c b/net/mac80211/mesh.c index 123a300cef57..fd1024ef393b 100644 --- a/net/mac80211/mesh.c +++ b/net/mac80211/mesh.c | |||
@@ -907,7 +907,7 @@ static void ieee80211_mesh_rx_bcn_presp(struct ieee80211_sub_if_data *sdata, | |||
907 | (!elems.rsn && sdata->u.mesh.security != IEEE80211_MESH_SEC_NONE)) | 907 | (!elems.rsn && sdata->u.mesh.security != IEEE80211_MESH_SEC_NONE)) |
908 | return; | 908 | return; |
909 | 909 | ||
910 | if (elems.ds_params && elems.ds_params_len == 1) | 910 | if (elems.ds_params) |
911 | freq = ieee80211_channel_to_frequency(elems.ds_params[0], band); | 911 | freq = ieee80211_channel_to_frequency(elems.ds_params[0], band); |
912 | else | 912 | else |
913 | freq = rx_status->freq; | 913 | freq = rx_status->freq; |
diff --git a/net/mac80211/mesh.h b/net/mac80211/mesh.h index 6ffabbe99c46..da158774eebb 100644 --- a/net/mac80211/mesh.h +++ b/net/mac80211/mesh.h | |||
@@ -275,7 +275,8 @@ void mesh_path_fix_nexthop(struct mesh_path *mpath, struct sta_info *next_hop); | |||
275 | void mesh_path_expire(struct ieee80211_sub_if_data *sdata); | 275 | void mesh_path_expire(struct ieee80211_sub_if_data *sdata); |
276 | void mesh_rx_path_sel_frame(struct ieee80211_sub_if_data *sdata, | 276 | void mesh_rx_path_sel_frame(struct ieee80211_sub_if_data *sdata, |
277 | struct ieee80211_mgmt *mgmt, size_t len); | 277 | struct ieee80211_mgmt *mgmt, size_t len); |
278 | int mesh_path_add(struct ieee80211_sub_if_data *sdata, const u8 *dst); | 278 | struct mesh_path * |
279 | mesh_path_add(struct ieee80211_sub_if_data *sdata, const u8 *dst); | ||
279 | 280 | ||
280 | int mesh_path_add_gate(struct mesh_path *mpath); | 281 | int mesh_path_add_gate(struct mesh_path *mpath); |
281 | int mesh_path_send_to_gates(struct mesh_path *mpath); | 282 | int mesh_path_send_to_gates(struct mesh_path *mpath); |
diff --git a/net/mac80211/mesh_hwmp.c b/net/mac80211/mesh_hwmp.c index bdb8d3b14587..c82d5e6a24c0 100644 --- a/net/mac80211/mesh_hwmp.c +++ b/net/mac80211/mesh_hwmp.c | |||
@@ -144,7 +144,7 @@ static int mesh_path_sel_frame_tx(enum mpath_frame_type action, u8 flags, | |||
144 | *pos++ = WLAN_EID_PREQ; | 144 | *pos++ = WLAN_EID_PREQ; |
145 | break; | 145 | break; |
146 | case MPATH_PREP: | 146 | case MPATH_PREP: |
147 | mhwmp_dbg(sdata, "sending PREP to %pM\n", target); | 147 | mhwmp_dbg(sdata, "sending PREP to %pM\n", orig_addr); |
148 | ie_len = 31; | 148 | ie_len = 31; |
149 | pos = skb_put(skb, 2 + ie_len); | 149 | pos = skb_put(skb, 2 + ie_len); |
150 | *pos++ = WLAN_EID_PREP; | 150 | *pos++ = WLAN_EID_PREP; |
@@ -445,9 +445,8 @@ static u32 hwmp_route_info_get(struct ieee80211_sub_if_data *sdata, | |||
445 | } | 445 | } |
446 | } | 446 | } |
447 | } else { | 447 | } else { |
448 | mesh_path_add(sdata, orig_addr); | 448 | mpath = mesh_path_add(sdata, orig_addr); |
449 | mpath = mesh_path_lookup(sdata, orig_addr); | 449 | if (IS_ERR(mpath)) { |
450 | if (!mpath) { | ||
451 | rcu_read_unlock(); | 450 | rcu_read_unlock(); |
452 | return 0; | 451 | return 0; |
453 | } | 452 | } |
@@ -486,9 +485,8 @@ static u32 hwmp_route_info_get(struct ieee80211_sub_if_data *sdata, | |||
486 | (last_hop_metric > mpath->metric))) | 485 | (last_hop_metric > mpath->metric))) |
487 | fresh_info = false; | 486 | fresh_info = false; |
488 | } else { | 487 | } else { |
489 | mesh_path_add(sdata, ta); | 488 | mpath = mesh_path_add(sdata, ta); |
490 | mpath = mesh_path_lookup(sdata, ta); | 489 | if (IS_ERR(mpath)) { |
491 | if (!mpath) { | ||
492 | rcu_read_unlock(); | 490 | rcu_read_unlock(); |
493 | return 0; | 491 | return 0; |
494 | } | 492 | } |
@@ -661,7 +659,7 @@ static void hwmp_prep_frame_process(struct ieee80211_sub_if_data *sdata, | |||
661 | u32 target_sn, orig_sn, lifetime; | 659 | u32 target_sn, orig_sn, lifetime; |
662 | 660 | ||
663 | mhwmp_dbg(sdata, "received PREP from %pM\n", | 661 | mhwmp_dbg(sdata, "received PREP from %pM\n", |
664 | PREP_IE_ORIG_ADDR(prep_elem)); | 662 | PREP_IE_TARGET_ADDR(prep_elem)); |
665 | 663 | ||
666 | orig_addr = PREP_IE_ORIG_ADDR(prep_elem); | 664 | orig_addr = PREP_IE_ORIG_ADDR(prep_elem); |
667 | if (ether_addr_equal(orig_addr, sdata->vif.addr)) | 665 | if (ether_addr_equal(orig_addr, sdata->vif.addr)) |
@@ -804,9 +802,8 @@ static void hwmp_rann_frame_process(struct ieee80211_sub_if_data *sdata, | |||
804 | 802 | ||
805 | mpath = mesh_path_lookup(sdata, orig_addr); | 803 | mpath = mesh_path_lookup(sdata, orig_addr); |
806 | if (!mpath) { | 804 | if (!mpath) { |
807 | mesh_path_add(sdata, orig_addr); | 805 | mpath = mesh_path_add(sdata, orig_addr); |
808 | mpath = mesh_path_lookup(sdata, orig_addr); | 806 | if (IS_ERR(mpath)) { |
809 | if (!mpath) { | ||
810 | rcu_read_unlock(); | 807 | rcu_read_unlock(); |
811 | sdata->u.mesh.mshstats.dropped_frames_no_route++; | 808 | sdata->u.mesh.mshstats.dropped_frames_no_route++; |
812 | return; | 809 | return; |
@@ -1098,11 +1095,10 @@ int mesh_nexthop_resolve(struct ieee80211_sub_if_data *sdata, | |||
1098 | /* no nexthop found, start resolving */ | 1095 | /* no nexthop found, start resolving */ |
1099 | mpath = mesh_path_lookup(sdata, target_addr); | 1096 | mpath = mesh_path_lookup(sdata, target_addr); |
1100 | if (!mpath) { | 1097 | if (!mpath) { |
1101 | mesh_path_add(sdata, target_addr); | 1098 | mpath = mesh_path_add(sdata, target_addr); |
1102 | mpath = mesh_path_lookup(sdata, target_addr); | 1099 | if (IS_ERR(mpath)) { |
1103 | if (!mpath) { | ||
1104 | mesh_path_discard_frame(sdata, skb); | 1100 | mesh_path_discard_frame(sdata, skb); |
1105 | err = -ENOSPC; | 1101 | err = PTR_ERR(mpath); |
1106 | goto endlookup; | 1102 | goto endlookup; |
1107 | } | 1103 | } |
1108 | } | 1104 | } |
diff --git a/net/mac80211/mesh_pathtbl.c b/net/mac80211/mesh_pathtbl.c index dc7c8df40c2c..89aacfd2756d 100644 --- a/net/mac80211/mesh_pathtbl.c +++ b/net/mac80211/mesh_pathtbl.c | |||
@@ -493,7 +493,8 @@ int mesh_gate_num(struct ieee80211_sub_if_data *sdata) | |||
493 | * | 493 | * |
494 | * State: the initial state of the new path is set to 0 | 494 | * State: the initial state of the new path is set to 0 |
495 | */ | 495 | */ |
496 | int mesh_path_add(struct ieee80211_sub_if_data *sdata, const u8 *dst) | 496 | struct mesh_path *mesh_path_add(struct ieee80211_sub_if_data *sdata, |
497 | const u8 *dst) | ||
497 | { | 498 | { |
498 | struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh; | 499 | struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh; |
499 | struct ieee80211_local *local = sdata->local; | 500 | struct ieee80211_local *local = sdata->local; |
@@ -502,18 +503,33 @@ int mesh_path_add(struct ieee80211_sub_if_data *sdata, const u8 *dst) | |||
502 | struct mpath_node *node, *new_node; | 503 | struct mpath_node *node, *new_node; |
503 | struct hlist_head *bucket; | 504 | struct hlist_head *bucket; |
504 | int grow = 0; | 505 | int grow = 0; |
505 | int err = 0; | 506 | int err; |
506 | u32 hash_idx; | 507 | u32 hash_idx; |
507 | 508 | ||
508 | if (ether_addr_equal(dst, sdata->vif.addr)) | 509 | if (ether_addr_equal(dst, sdata->vif.addr)) |
509 | /* never add ourselves as neighbours */ | 510 | /* never add ourselves as neighbours */ |
510 | return -ENOTSUPP; | 511 | return ERR_PTR(-ENOTSUPP); |
511 | 512 | ||
512 | if (is_multicast_ether_addr(dst)) | 513 | if (is_multicast_ether_addr(dst)) |
513 | return -ENOTSUPP; | 514 | return ERR_PTR(-ENOTSUPP); |
514 | 515 | ||
515 | if (atomic_add_unless(&sdata->u.mesh.mpaths, 1, MESH_MAX_MPATHS) == 0) | 516 | if (atomic_add_unless(&sdata->u.mesh.mpaths, 1, MESH_MAX_MPATHS) == 0) |
516 | return -ENOSPC; | 517 | return ERR_PTR(-ENOSPC); |
518 | |||
519 | read_lock_bh(&pathtbl_resize_lock); | ||
520 | tbl = resize_dereference_mesh_paths(); | ||
521 | |||
522 | hash_idx = mesh_table_hash(dst, sdata, tbl); | ||
523 | bucket = &tbl->hash_buckets[hash_idx]; | ||
524 | |||
525 | spin_lock(&tbl->hashwlock[hash_idx]); | ||
526 | |||
527 | hlist_for_each_entry(node, bucket, list) { | ||
528 | mpath = node->mpath; | ||
529 | if (mpath->sdata == sdata && | ||
530 | ether_addr_equal(dst, mpath->dst)) | ||
531 | goto found; | ||
532 | } | ||
517 | 533 | ||
518 | err = -ENOMEM; | 534 | err = -ENOMEM; |
519 | new_mpath = kzalloc(sizeof(struct mesh_path), GFP_ATOMIC); | 535 | new_mpath = kzalloc(sizeof(struct mesh_path), GFP_ATOMIC); |
@@ -524,7 +540,6 @@ int mesh_path_add(struct ieee80211_sub_if_data *sdata, const u8 *dst) | |||
524 | if (!new_node) | 540 | if (!new_node) |
525 | goto err_node_alloc; | 541 | goto err_node_alloc; |
526 | 542 | ||
527 | read_lock_bh(&pathtbl_resize_lock); | ||
528 | memcpy(new_mpath->dst, dst, ETH_ALEN); | 543 | memcpy(new_mpath->dst, dst, ETH_ALEN); |
529 | eth_broadcast_addr(new_mpath->rann_snd_addr); | 544 | eth_broadcast_addr(new_mpath->rann_snd_addr); |
530 | new_mpath->is_root = false; | 545 | new_mpath->is_root = false; |
@@ -538,21 +553,6 @@ int mesh_path_add(struct ieee80211_sub_if_data *sdata, const u8 *dst) | |||
538 | spin_lock_init(&new_mpath->state_lock); | 553 | spin_lock_init(&new_mpath->state_lock); |
539 | init_timer(&new_mpath->timer); | 554 | init_timer(&new_mpath->timer); |
540 | 555 | ||
541 | tbl = resize_dereference_mesh_paths(); | ||
542 | |||
543 | hash_idx = mesh_table_hash(dst, sdata, tbl); | ||
544 | bucket = &tbl->hash_buckets[hash_idx]; | ||
545 | |||
546 | spin_lock(&tbl->hashwlock[hash_idx]); | ||
547 | |||
548 | err = -EEXIST; | ||
549 | hlist_for_each_entry(node, bucket, list) { | ||
550 | mpath = node->mpath; | ||
551 | if (mpath->sdata == sdata && | ||
552 | ether_addr_equal(dst, mpath->dst)) | ||
553 | goto err_exists; | ||
554 | } | ||
555 | |||
556 | hlist_add_head_rcu(&new_node->list, bucket); | 556 | hlist_add_head_rcu(&new_node->list, bucket); |
557 | if (atomic_inc_return(&tbl->entries) >= | 557 | if (atomic_inc_return(&tbl->entries) >= |
558 | tbl->mean_chain_len * (tbl->hash_mask + 1)) | 558 | tbl->mean_chain_len * (tbl->hash_mask + 1)) |
@@ -560,23 +560,23 @@ int mesh_path_add(struct ieee80211_sub_if_data *sdata, const u8 *dst) | |||
560 | 560 | ||
561 | mesh_paths_generation++; | 561 | mesh_paths_generation++; |
562 | 562 | ||
563 | spin_unlock(&tbl->hashwlock[hash_idx]); | ||
564 | read_unlock_bh(&pathtbl_resize_lock); | ||
565 | if (grow) { | 563 | if (grow) { |
566 | set_bit(MESH_WORK_GROW_MPATH_TABLE, &ifmsh->wrkq_flags); | 564 | set_bit(MESH_WORK_GROW_MPATH_TABLE, &ifmsh->wrkq_flags); |
567 | ieee80211_queue_work(&local->hw, &sdata->work); | 565 | ieee80211_queue_work(&local->hw, &sdata->work); |
568 | } | 566 | } |
569 | return 0; | 567 | mpath = new_mpath; |
570 | 568 | found: | |
571 | err_exists: | ||
572 | spin_unlock(&tbl->hashwlock[hash_idx]); | 569 | spin_unlock(&tbl->hashwlock[hash_idx]); |
573 | read_unlock_bh(&pathtbl_resize_lock); | 570 | read_unlock_bh(&pathtbl_resize_lock); |
574 | kfree(new_node); | 571 | return mpath; |
572 | |||
575 | err_node_alloc: | 573 | err_node_alloc: |
576 | kfree(new_mpath); | 574 | kfree(new_mpath); |
577 | err_path_alloc: | 575 | err_path_alloc: |
578 | atomic_dec(&sdata->u.mesh.mpaths); | 576 | atomic_dec(&sdata->u.mesh.mpaths); |
579 | return err; | 577 | spin_unlock(&tbl->hashwlock[hash_idx]); |
578 | read_unlock_bh(&pathtbl_resize_lock); | ||
579 | return ERR_PTR(err); | ||
580 | } | 580 | } |
581 | 581 | ||
582 | static void mesh_table_free_rcu(struct rcu_head *rcu) | 582 | static void mesh_table_free_rcu(struct rcu_head *rcu) |
diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index e06dbbf8cb4c..9c4968938472 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c | |||
@@ -56,7 +56,10 @@ MODULE_PARM_DESC(max_probe_tries, | |||
56 | * probe on beacon miss before declaring the connection lost | 56 | * probe on beacon miss before declaring the connection lost |
57 | * default to what we want. | 57 | * default to what we want. |
58 | */ | 58 | */ |
59 | #define IEEE80211_BEACON_LOSS_COUNT 7 | 59 | static int beacon_loss_count = 7; |
60 | module_param(beacon_loss_count, int, 0644); | ||
61 | MODULE_PARM_DESC(beacon_loss_count, | ||
62 | "Number of beacon intervals before we decide beacon was lost."); | ||
60 | 63 | ||
61 | /* | 64 | /* |
62 | * Time the connection can be idle before we probe | 65 | * Time the connection can be idle before we probe |
@@ -985,6 +988,7 @@ static void ieee80211_chswitch_work(struct work_struct *work) | |||
985 | { | 988 | { |
986 | struct ieee80211_sub_if_data *sdata = | 989 | struct ieee80211_sub_if_data *sdata = |
987 | container_of(work, struct ieee80211_sub_if_data, u.mgd.chswitch_work); | 990 | container_of(work, struct ieee80211_sub_if_data, u.mgd.chswitch_work); |
991 | struct ieee80211_local *local = sdata->local; | ||
988 | struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; | 992 | struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; |
989 | 993 | ||
990 | if (!ieee80211_sdata_running(sdata)) | 994 | if (!ieee80211_sdata_running(sdata)) |
@@ -994,21 +998,30 @@ static void ieee80211_chswitch_work(struct work_struct *work) | |||
994 | if (!ifmgd->associated) | 998 | if (!ifmgd->associated) |
995 | goto out; | 999 | goto out; |
996 | 1000 | ||
997 | sdata->local->_oper_channel = sdata->local->csa_channel; | 1001 | /* |
998 | if (!sdata->local->ops->channel_switch) { | 1002 | * FIXME: Here we are downgrading to NL80211_CHAN_WIDTH_20_NOHT |
1003 | * and don't adjust our ht/vht settings | ||
1004 | * This is wrong - we should behave according to the CSA params | ||
1005 | */ | ||
1006 | local->_oper_chandef.chan = local->csa_channel; | ||
1007 | local->_oper_chandef.width = NL80211_CHAN_WIDTH_20_NOHT; | ||
1008 | local->_oper_chandef.center_freq1 = | ||
1009 | local->_oper_chandef.chan->center_freq; | ||
1010 | local->_oper_chandef.center_freq2 = 0; | ||
1011 | |||
1012 | if (!local->ops->channel_switch) { | ||
999 | /* call "hw_config" only if doing sw channel switch */ | 1013 | /* call "hw_config" only if doing sw channel switch */ |
1000 | ieee80211_hw_config(sdata->local, | 1014 | ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_CHANNEL); |
1001 | IEEE80211_CONF_CHANGE_CHANNEL); | ||
1002 | } else { | 1015 | } else { |
1003 | /* update the device channel directly */ | 1016 | /* update the device channel directly */ |
1004 | sdata->local->hw.conf.channel = sdata->local->_oper_channel; | 1017 | local->hw.conf.chandef = local->_oper_chandef; |
1005 | } | 1018 | } |
1006 | 1019 | ||
1007 | /* XXX: shouldn't really modify cfg80211-owned data! */ | 1020 | /* XXX: shouldn't really modify cfg80211-owned data! */ |
1008 | ifmgd->associated->channel = sdata->local->_oper_channel; | 1021 | ifmgd->associated->channel = local->_oper_chandef.chan; |
1009 | 1022 | ||
1010 | /* XXX: wait for a beacon first? */ | 1023 | /* XXX: wait for a beacon first? */ |
1011 | ieee80211_wake_queues_by_reason(&sdata->local->hw, | 1024 | ieee80211_wake_queues_by_reason(&local->hw, |
1012 | IEEE80211_MAX_QUEUE_MAP, | 1025 | IEEE80211_MAX_QUEUE_MAP, |
1013 | IEEE80211_QUEUE_STOP_REASON_CSA); | 1026 | IEEE80211_QUEUE_STOP_REASON_CSA); |
1014 | out: | 1027 | out: |
@@ -1430,13 +1443,11 @@ void ieee80211_dynamic_ps_enable_work(struct work_struct *work) | |||
1430 | 1443 | ||
1431 | if ((local->hw.flags & IEEE80211_HW_PS_NULLFUNC_STACK) && | 1444 | if ((local->hw.flags & IEEE80211_HW_PS_NULLFUNC_STACK) && |
1432 | !(ifmgd->flags & IEEE80211_STA_NULLFUNC_ACKED)) { | 1445 | !(ifmgd->flags & IEEE80211_STA_NULLFUNC_ACKED)) { |
1433 | netif_tx_stop_all_queues(sdata->dev); | 1446 | if (drv_tx_frames_pending(local)) { |
1434 | |||
1435 | if (drv_tx_frames_pending(local)) | ||
1436 | mod_timer(&local->dynamic_ps_timer, jiffies + | 1447 | mod_timer(&local->dynamic_ps_timer, jiffies + |
1437 | msecs_to_jiffies( | 1448 | msecs_to_jiffies( |
1438 | local->hw.conf.dynamic_ps_timeout)); | 1449 | local->hw.conf.dynamic_ps_timeout)); |
1439 | else { | 1450 | } else { |
1440 | ieee80211_send_nullfunc(local, sdata, 1); | 1451 | ieee80211_send_nullfunc(local, sdata, 1); |
1441 | /* Flush to get the tx status of nullfunc frame */ | 1452 | /* Flush to get the tx status of nullfunc frame */ |
1442 | ieee80211_flush_queues(local, sdata); | 1453 | ieee80211_flush_queues(local, sdata); |
@@ -1450,9 +1461,6 @@ void ieee80211_dynamic_ps_enable_work(struct work_struct *work) | |||
1450 | local->hw.conf.flags |= IEEE80211_CONF_PS; | 1461 | local->hw.conf.flags |= IEEE80211_CONF_PS; |
1451 | ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_PS); | 1462 | ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_PS); |
1452 | } | 1463 | } |
1453 | |||
1454 | if (local->hw.flags & IEEE80211_HW_PS_NULLFUNC_STACK) | ||
1455 | netif_tx_wake_all_queues(sdata->dev); | ||
1456 | } | 1464 | } |
1457 | 1465 | ||
1458 | void ieee80211_dynamic_ps_timer(unsigned long data) | 1466 | void ieee80211_dynamic_ps_timer(unsigned long data) |
@@ -1645,7 +1653,7 @@ static void ieee80211_set_associated(struct ieee80211_sub_if_data *sdata, | |||
1645 | bss_conf->assoc_capability, bss->has_erp_value, bss->erp_value); | 1653 | bss_conf->assoc_capability, bss->has_erp_value, bss->erp_value); |
1646 | 1654 | ||
1647 | sdata->u.mgd.beacon_timeout = usecs_to_jiffies(ieee80211_tu_to_usec( | 1655 | sdata->u.mgd.beacon_timeout = usecs_to_jiffies(ieee80211_tu_to_usec( |
1648 | IEEE80211_BEACON_LOSS_COUNT * bss_conf->beacon_int)); | 1656 | beacon_loss_count * bss_conf->beacon_int)); |
1649 | 1657 | ||
1650 | sdata->u.mgd.associated = cbss; | 1658 | sdata->u.mgd.associated = cbss; |
1651 | memcpy(sdata->u.mgd.bssid, cbss->bssid, ETH_ALEN); | 1659 | memcpy(sdata->u.mgd.bssid, cbss->bssid, ETH_ALEN); |
@@ -1658,18 +1666,17 @@ static void ieee80211_set_associated(struct ieee80211_sub_if_data *sdata, | |||
1658 | rcu_read_lock(); | 1666 | rcu_read_lock(); |
1659 | ies = rcu_dereference(cbss->ies); | 1667 | ies = rcu_dereference(cbss->ies); |
1660 | if (ies) { | 1668 | if (ies) { |
1661 | u8 noa[2]; | ||
1662 | int ret; | 1669 | int ret; |
1663 | 1670 | ||
1664 | ret = cfg80211_get_p2p_attr( | 1671 | ret = cfg80211_get_p2p_attr( |
1665 | ies->data, ies->len, | 1672 | ies->data, ies->len, |
1666 | IEEE80211_P2P_ATTR_ABSENCE_NOTICE, | 1673 | IEEE80211_P2P_ATTR_ABSENCE_NOTICE, |
1667 | noa, sizeof(noa)); | 1674 | (u8 *) &bss_conf->p2p_noa_attr, |
1675 | sizeof(bss_conf->p2p_noa_attr)); | ||
1668 | if (ret >= 2) { | 1676 | if (ret >= 2) { |
1669 | bss_conf->p2p_oppps = noa[1] & 0x80; | 1677 | sdata->u.mgd.p2p_noa_index = |
1670 | bss_conf->p2p_ctwindow = noa[1] & 0x7f; | 1678 | bss_conf->p2p_noa_attr.index; |
1671 | bss_info_changed |= BSS_CHANGED_P2P_PS; | 1679 | bss_info_changed |= BSS_CHANGED_P2P_PS; |
1672 | sdata->u.mgd.p2p_noa_index = noa[0]; | ||
1673 | } | 1680 | } |
1674 | } | 1681 | } |
1675 | rcu_read_unlock(); | 1682 | rcu_read_unlock(); |
@@ -1713,7 +1720,6 @@ static void ieee80211_set_associated(struct ieee80211_sub_if_data *sdata, | |||
1713 | ieee80211_recalc_smps(sdata); | 1720 | ieee80211_recalc_smps(sdata); |
1714 | ieee80211_recalc_ps_vif(sdata); | 1721 | ieee80211_recalc_ps_vif(sdata); |
1715 | 1722 | ||
1716 | netif_tx_start_all_queues(sdata->dev); | ||
1717 | netif_carrier_on(sdata->dev); | 1723 | netif_carrier_on(sdata->dev); |
1718 | } | 1724 | } |
1719 | 1725 | ||
@@ -1736,22 +1742,6 @@ static void ieee80211_set_disassoc(struct ieee80211_sub_if_data *sdata, | |||
1736 | ieee80211_stop_poll(sdata); | 1742 | ieee80211_stop_poll(sdata); |
1737 | 1743 | ||
1738 | ifmgd->associated = NULL; | 1744 | ifmgd->associated = NULL; |
1739 | |||
1740 | /* | ||
1741 | * we need to commit the associated = NULL change because the | ||
1742 | * scan code uses that to determine whether this iface should | ||
1743 | * go to/wake up from powersave or not -- and could otherwise | ||
1744 | * wake the queues erroneously. | ||
1745 | */ | ||
1746 | smp_mb(); | ||
1747 | |||
1748 | /* | ||
1749 | * Thus, we can only afterwards stop the queues -- to account | ||
1750 | * for the case where another CPU is finishing a scan at this | ||
1751 | * time -- we don't want the scan code to enable queues. | ||
1752 | */ | ||
1753 | |||
1754 | netif_tx_stop_all_queues(sdata->dev); | ||
1755 | netif_carrier_off(sdata->dev); | 1745 | netif_carrier_off(sdata->dev); |
1756 | 1746 | ||
1757 | /* | 1747 | /* |
@@ -1794,8 +1784,9 @@ static void ieee80211_set_disassoc(struct ieee80211_sub_if_data *sdata, | |||
1794 | changed |= BSS_CHANGED_ASSOC; | 1784 | changed |= BSS_CHANGED_ASSOC; |
1795 | sdata->vif.bss_conf.assoc = false; | 1785 | sdata->vif.bss_conf.assoc = false; |
1796 | 1786 | ||
1797 | sdata->vif.bss_conf.p2p_ctwindow = 0; | 1787 | ifmgd->p2p_noa_index = -1; |
1798 | sdata->vif.bss_conf.p2p_oppps = false; | 1788 | memset(&sdata->vif.bss_conf.p2p_noa_attr, 0, |
1789 | sizeof(sdata->vif.bss_conf.p2p_noa_attr)); | ||
1799 | 1790 | ||
1800 | /* on the next assoc, re-program HT/VHT parameters */ | 1791 | /* on the next assoc, re-program HT/VHT parameters */ |
1801 | memset(&ifmgd->ht_capa, 0, sizeof(ifmgd->ht_capa)); | 1792 | memset(&ifmgd->ht_capa, 0, sizeof(ifmgd->ht_capa)); |
@@ -1975,12 +1966,15 @@ static void ieee80211_mgd_probe_ap(struct ieee80211_sub_if_data *sdata, | |||
1975 | goto out; | 1966 | goto out; |
1976 | } | 1967 | } |
1977 | 1968 | ||
1978 | if (beacon) | 1969 | if (beacon) { |
1979 | mlme_dbg_ratelimited(sdata, | 1970 | mlme_dbg_ratelimited(sdata, |
1980 | "detected beacon loss from AP - probing\n"); | 1971 | "detected beacon loss from AP (missed %d beacons) - probing\n", |
1972 | beacon_loss_count); | ||
1981 | 1973 | ||
1982 | ieee80211_cqm_rssi_notify(&sdata->vif, | 1974 | ieee80211_cqm_rssi_notify(&sdata->vif, |
1983 | NL80211_CQM_RSSI_BEACON_LOSS_EVENT, GFP_KERNEL); | 1975 | NL80211_CQM_RSSI_BEACON_LOSS_EVENT, |
1976 | GFP_KERNEL); | ||
1977 | } | ||
1984 | 1978 | ||
1985 | /* | 1979 | /* |
1986 | * The driver/our work has already reported this event or the | 1980 | * The driver/our work has already reported this event or the |
@@ -2613,10 +2607,10 @@ ieee80211_rx_mgmt_assoc_resp(struct ieee80211_sub_if_data *sdata, | |||
2613 | ieee802_11_parse_elems(pos, len - (pos - (u8 *) mgmt), &elems); | 2607 | ieee802_11_parse_elems(pos, len - (pos - (u8 *) mgmt), &elems); |
2614 | 2608 | ||
2615 | if (status_code == WLAN_STATUS_ASSOC_REJECTED_TEMPORARILY && | 2609 | if (status_code == WLAN_STATUS_ASSOC_REJECTED_TEMPORARILY && |
2616 | elems.timeout_int && elems.timeout_int_len == 5 && | 2610 | elems.timeout_int && |
2617 | elems.timeout_int[0] == WLAN_TIMEOUT_ASSOC_COMEBACK) { | 2611 | elems.timeout_int->type == WLAN_TIMEOUT_ASSOC_COMEBACK) { |
2618 | u32 tu, ms; | 2612 | u32 tu, ms; |
2619 | tu = get_unaligned_le32(elems.timeout_int + 1); | 2613 | tu = le32_to_cpu(elems.timeout_int->value); |
2620 | ms = tu * 1024 / 1000; | 2614 | ms = tu * 1024 / 1000; |
2621 | sdata_info(sdata, | 2615 | sdata_info(sdata, |
2622 | "%pM rejected association temporarily; comeback duration %u TU (%u ms)\n", | 2616 | "%pM rejected association temporarily; comeback duration %u TU (%u ms)\n", |
@@ -2679,7 +2673,7 @@ static void ieee80211_rx_bss_info(struct ieee80211_sub_if_data *sdata, | |||
2679 | } | 2673 | } |
2680 | } | 2674 | } |
2681 | 2675 | ||
2682 | if (elems->ds_params && elems->ds_params_len == 1) | 2676 | if (elems->ds_params) |
2683 | freq = ieee80211_channel_to_frequency(elems->ds_params[0], | 2677 | freq = ieee80211_channel_to_frequency(elems->ds_params[0], |
2684 | rx_status->band); | 2678 | rx_status->band); |
2685 | else | 2679 | else |
@@ -2957,22 +2951,30 @@ ieee80211_rx_mgmt_beacon(struct ieee80211_sub_if_data *sdata, | |||
2957 | } | 2951 | } |
2958 | 2952 | ||
2959 | if (sdata->vif.p2p) { | 2953 | if (sdata->vif.p2p) { |
2960 | u8 noa[2]; | 2954 | struct ieee80211_p2p_noa_attr noa = {}; |
2961 | int ret; | 2955 | int ret; |
2962 | 2956 | ||
2963 | ret = cfg80211_get_p2p_attr(mgmt->u.beacon.variable, | 2957 | ret = cfg80211_get_p2p_attr(mgmt->u.beacon.variable, |
2964 | len - baselen, | 2958 | len - baselen, |
2965 | IEEE80211_P2P_ATTR_ABSENCE_NOTICE, | 2959 | IEEE80211_P2P_ATTR_ABSENCE_NOTICE, |
2966 | noa, sizeof(noa)); | 2960 | (u8 *) &noa, sizeof(noa)); |
2967 | if (ret >= 2 && sdata->u.mgd.p2p_noa_index != noa[0]) { | 2961 | if (ret >= 2) { |
2968 | bss_conf->p2p_oppps = noa[1] & 0x80; | 2962 | if (sdata->u.mgd.p2p_noa_index != noa.index) { |
2969 | bss_conf->p2p_ctwindow = noa[1] & 0x7f; | 2963 | /* valid noa_attr and index changed */ |
2964 | sdata->u.mgd.p2p_noa_index = noa.index; | ||
2965 | memcpy(&bss_conf->p2p_noa_attr, &noa, sizeof(noa)); | ||
2966 | changed |= BSS_CHANGED_P2P_PS; | ||
2967 | /* | ||
2968 | * make sure we update all information, the CRC | ||
2969 | * mechanism doesn't look at P2P attributes. | ||
2970 | */ | ||
2971 | ifmgd->beacon_crc_valid = false; | ||
2972 | } | ||
2973 | } else if (sdata->u.mgd.p2p_noa_index != -1) { | ||
2974 | /* noa_attr not found and we had valid noa_attr before */ | ||
2975 | sdata->u.mgd.p2p_noa_index = -1; | ||
2976 | memset(&bss_conf->p2p_noa_attr, 0, sizeof(bss_conf->p2p_noa_attr)); | ||
2970 | changed |= BSS_CHANGED_P2P_PS; | 2977 | changed |= BSS_CHANGED_P2P_PS; |
2971 | sdata->u.mgd.p2p_noa_index = noa[0]; | ||
2972 | /* | ||
2973 | * make sure we update all information, the CRC | ||
2974 | * mechanism doesn't look at P2P attributes. | ||
2975 | */ | ||
2976 | ifmgd->beacon_crc_valid = false; | 2978 | ifmgd->beacon_crc_valid = false; |
2977 | } | 2979 | } |
2978 | } | 2980 | } |
@@ -3014,7 +3016,7 @@ ieee80211_rx_mgmt_beacon(struct ieee80211_sub_if_data *sdata, | |||
3014 | changed |= BSS_CHANGED_DTIM_PERIOD; | 3016 | changed |= BSS_CHANGED_DTIM_PERIOD; |
3015 | } | 3017 | } |
3016 | 3018 | ||
3017 | if (elems.erp_info && elems.erp_info_len >= 1) { | 3019 | if (elems.erp_info) { |
3018 | erp_valid = true; | 3020 | erp_valid = true; |
3019 | erp_value = elems.erp_info[0]; | 3021 | erp_value = elems.erp_info[0]; |
3020 | } else { | 3022 | } else { |
@@ -3513,8 +3515,9 @@ void ieee80211_sta_setup_sdata(struct ieee80211_sub_if_data *sdata) | |||
3513 | 3515 | ||
3514 | ifmgd->flags = 0; | 3516 | ifmgd->flags = 0; |
3515 | ifmgd->powersave = sdata->wdev.ps; | 3517 | ifmgd->powersave = sdata->wdev.ps; |
3516 | ifmgd->uapsd_queues = IEEE80211_DEFAULT_UAPSD_QUEUES; | 3518 | ifmgd->uapsd_queues = sdata->local->hw.uapsd_queues; |
3517 | ifmgd->uapsd_max_sp_len = IEEE80211_DEFAULT_MAX_SP_LEN; | 3519 | ifmgd->uapsd_max_sp_len = sdata->local->hw.uapsd_max_sp_len; |
3520 | ifmgd->p2p_noa_index = -1; | ||
3518 | 3521 | ||
3519 | mutex_init(&ifmgd->mtx); | 3522 | mutex_init(&ifmgd->mtx); |
3520 | 3523 | ||
@@ -4063,7 +4066,8 @@ int ieee80211_mgd_assoc(struct ieee80211_sub_if_data *sdata, | |||
4063 | rcu_read_unlock(); | 4066 | rcu_read_unlock(); |
4064 | 4067 | ||
4065 | if (bss->wmm_used && bss->uapsd_supported && | 4068 | if (bss->wmm_used && bss->uapsd_supported && |
4066 | (sdata->local->hw.flags & IEEE80211_HW_SUPPORTS_UAPSD)) { | 4069 | (sdata->local->hw.flags & IEEE80211_HW_SUPPORTS_UAPSD) && |
4070 | sdata->wmm_acm != 0xff) { | ||
4067 | assoc_data->uapsd = true; | 4071 | assoc_data->uapsd = true; |
4068 | ifmgd->flags |= IEEE80211_STA_UAPSD_ENABLED; | 4072 | ifmgd->flags |= IEEE80211_STA_UAPSD_ENABLED; |
4069 | } else { | 4073 | } else { |
diff --git a/net/mac80211/offchannel.c b/net/mac80211/offchannel.c index cce795871ab1..acd1f71adc03 100644 --- a/net/mac80211/offchannel.c +++ b/net/mac80211/offchannel.c | |||
@@ -445,15 +445,15 @@ void ieee80211_roc_setup(struct ieee80211_local *local) | |||
445 | INIT_LIST_HEAD(&local->roc_list); | 445 | INIT_LIST_HEAD(&local->roc_list); |
446 | } | 446 | } |
447 | 447 | ||
448 | void ieee80211_roc_purge(struct ieee80211_sub_if_data *sdata) | 448 | void ieee80211_roc_purge(struct ieee80211_local *local, |
449 | struct ieee80211_sub_if_data *sdata) | ||
449 | { | 450 | { |
450 | struct ieee80211_local *local = sdata->local; | ||
451 | struct ieee80211_roc_work *roc, *tmp; | 451 | struct ieee80211_roc_work *roc, *tmp; |
452 | LIST_HEAD(tmp_list); | 452 | LIST_HEAD(tmp_list); |
453 | 453 | ||
454 | mutex_lock(&local->mtx); | 454 | mutex_lock(&local->mtx); |
455 | list_for_each_entry_safe(roc, tmp, &local->roc_list, list) { | 455 | list_for_each_entry_safe(roc, tmp, &local->roc_list, list) { |
456 | if (roc->sdata != sdata) | 456 | if (sdata && roc->sdata != sdata) |
457 | continue; | 457 | continue; |
458 | 458 | ||
459 | if (roc->started && local->ops->remain_on_channel) { | 459 | if (roc->started && local->ops->remain_on_channel) { |
diff --git a/net/mac80211/pm.c b/net/mac80211/pm.c index 3d16f4e61743..d1c021b62fe5 100644 --- a/net/mac80211/pm.c +++ b/net/mac80211/pm.c | |||
@@ -19,6 +19,10 @@ int __ieee80211_suspend(struct ieee80211_hw *hw, struct cfg80211_wowlan *wowlan) | |||
19 | 19 | ||
20 | ieee80211_dfs_cac_cancel(local); | 20 | ieee80211_dfs_cac_cancel(local); |
21 | 21 | ||
22 | ieee80211_roc_purge(local, NULL); | ||
23 | |||
24 | ieee80211_del_virtual_monitor(local); | ||
25 | |||
22 | if (hw->flags & IEEE80211_HW_AMPDU_AGGREGATION) { | 26 | if (hw->flags & IEEE80211_HW_AMPDU_AGGREGATION) { |
23 | mutex_lock(&local->sta_mtx); | 27 | mutex_lock(&local->sta_mtx); |
24 | list_for_each_entry(sta, &local->sta_list, list) { | 28 | list_for_each_entry(sta, &local->sta_list, list) { |
@@ -101,10 +105,6 @@ int __ieee80211_suspend(struct ieee80211_hw *hw, struct cfg80211_wowlan *wowlan) | |||
101 | drv_remove_interface(local, sdata); | 105 | drv_remove_interface(local, sdata); |
102 | } | 106 | } |
103 | 107 | ||
104 | sdata = rtnl_dereference(local->monitor_sdata); | ||
105 | if (sdata) | ||
106 | drv_remove_interface(local, sdata); | ||
107 | |||
108 | /* | 108 | /* |
109 | * We disconnected on all interfaces before suspend, all channel | 109 | * We disconnected on all interfaces before suspend, all channel |
110 | * contexts should be released. | 110 | * contexts should be released. |
diff --git a/net/mac80211/scan.c b/net/mac80211/scan.c index cb34cbbaa20c..33fbf1045690 100644 --- a/net/mac80211/scan.c +++ b/net/mac80211/scan.c | |||
@@ -98,9 +98,8 @@ ieee80211_bss_info_update(struct ieee80211_local *local, | |||
98 | } | 98 | } |
99 | 99 | ||
100 | /* save the ERP value so that it is available at association time */ | 100 | /* save the ERP value so that it is available at association time */ |
101 | if (elems->erp_info && elems->erp_info_len >= 1 && | 101 | if (elems->erp_info && (!elems->parse_error || |
102 | (!elems->parse_error || | 102 | !(bss->valid_data & IEEE80211_BSS_VALID_ERP))) { |
103 | !(bss->valid_data & IEEE80211_BSS_VALID_ERP))) { | ||
104 | bss->erp_value = elems->erp_info[0]; | 103 | bss->erp_value = elems->erp_info[0]; |
105 | bss->has_erp_value = true; | 104 | bss->has_erp_value = true; |
106 | if (!elems->parse_error) | 105 | if (!elems->parse_error) |
@@ -384,7 +383,7 @@ static void ieee80211_scan_state_send_probe(struct ieee80211_local *local, | |||
384 | { | 383 | { |
385 | int i; | 384 | int i; |
386 | struct ieee80211_sub_if_data *sdata; | 385 | struct ieee80211_sub_if_data *sdata; |
387 | enum ieee80211_band band = local->hw.conf.channel->band; | 386 | enum ieee80211_band band = local->hw.conf.chandef.chan->band; |
388 | u32 tx_flags; | 387 | u32 tx_flags; |
389 | 388 | ||
390 | tx_flags = IEEE80211_TX_INTFL_OFFCHAN_TX_OK; | 389 | tx_flags = IEEE80211_TX_INTFL_OFFCHAN_TX_OK; |
@@ -401,7 +400,7 @@ static void ieee80211_scan_state_send_probe(struct ieee80211_local *local, | |||
401 | local->scan_req->ssids[i].ssid_len, | 400 | local->scan_req->ssids[i].ssid_len, |
402 | local->scan_req->ie, local->scan_req->ie_len, | 401 | local->scan_req->ie, local->scan_req->ie_len, |
403 | local->scan_req->rates[band], false, | 402 | local->scan_req->rates[band], false, |
404 | tx_flags, local->hw.conf.channel, true); | 403 | tx_flags, local->hw.conf.chandef.chan, true); |
405 | 404 | ||
406 | /* | 405 | /* |
407 | * After sending probe requests, wait for probe responses | 406 | * After sending probe requests, wait for probe responses |
@@ -467,7 +466,7 @@ static int __ieee80211_start_scan(struct ieee80211_sub_if_data *sdata, | |||
467 | if (local->ops->hw_scan) { | 466 | if (local->ops->hw_scan) { |
468 | __set_bit(SCAN_HW_SCANNING, &local->scanning); | 467 | __set_bit(SCAN_HW_SCANNING, &local->scanning); |
469 | } else if ((req->n_channels == 1) && | 468 | } else if ((req->n_channels == 1) && |
470 | (req->channels[0] == local->_oper_channel)) { | 469 | (req->channels[0] == local->_oper_chandef.chan)) { |
471 | /* | 470 | /* |
472 | * If we are scanning only on the operating channel | 471 | * If we are scanning only on the operating channel |
473 | * then we do not need to stop normal activities | 472 | * then we do not need to stop normal activities |
diff --git a/net/mac80211/trace.h b/net/mac80211/trace.h index c5899797a8d4..8286dcef228b 100644 --- a/net/mac80211/trace.h +++ b/net/mac80211/trace.h | |||
@@ -28,27 +28,27 @@ | |||
28 | #define VIF_PR_FMT " vif:%s(%d%s)" | 28 | #define VIF_PR_FMT " vif:%s(%d%s)" |
29 | #define VIF_PR_ARG __get_str(vif_name), __entry->vif_type, __entry->p2p ? "/p2p" : "" | 29 | #define VIF_PR_ARG __get_str(vif_name), __entry->vif_type, __entry->p2p ? "/p2p" : "" |
30 | 30 | ||
31 | #define CHANDEF_ENTRY __field(u32, control_freq) \ | 31 | #define CHANDEF_ENTRY __field(u32, control_freq) \ |
32 | __field(u32, chan_width) \ | 32 | __field(u32, chan_width) \ |
33 | __field(u32, center_freq1) \ | 33 | __field(u32, center_freq1) \ |
34 | __field(u32, center_freq2) | 34 | __field(u32, center_freq2) |
35 | #define CHANDEF_ASSIGN(c) \ | 35 | #define CHANDEF_ASSIGN(c) \ |
36 | __entry->control_freq = (c)->chan->center_freq; \ | 36 | __entry->control_freq = (c)->chan ? (c)->chan->center_freq : 0; \ |
37 | __entry->chan_width = (c)->width; \ | 37 | __entry->chan_width = (c)->width; \ |
38 | __entry->center_freq1 = (c)->center_freq1; \ | 38 | __entry->center_freq1 = (c)->center_freq1; \ |
39 | __entry->center_freq2 = (c)->center_freq2; | 39 | __entry->center_freq2 = (c)->center_freq2; |
40 | #define CHANDEF_PR_FMT " control:%d MHz width:%d center: %d/%d MHz" | 40 | #define CHANDEF_PR_FMT " control:%d MHz width:%d center: %d/%d MHz" |
41 | #define CHANDEF_PR_ARG __entry->control_freq, __entry->chan_width, \ | 41 | #define CHANDEF_PR_ARG __entry->control_freq, __entry->chan_width, \ |
42 | __entry->center_freq1, __entry->center_freq2 | 42 | __entry->center_freq1, __entry->center_freq2 |
43 | 43 | ||
44 | #define CHANCTX_ENTRY CHANDEF_ENTRY \ | 44 | #define CHANCTX_ENTRY CHANDEF_ENTRY \ |
45 | __field(u8, rx_chains_static) \ | 45 | __field(u8, rx_chains_static) \ |
46 | __field(u8, rx_chains_dynamic) | 46 | __field(u8, rx_chains_dynamic) |
47 | #define CHANCTX_ASSIGN CHANDEF_ASSIGN(&ctx->conf.def) \ | 47 | #define CHANCTX_ASSIGN CHANDEF_ASSIGN(&ctx->conf.def) \ |
48 | __entry->rx_chains_static = ctx->conf.rx_chains_static; \ | 48 | __entry->rx_chains_static = ctx->conf.rx_chains_static; \ |
49 | __entry->rx_chains_dynamic = ctx->conf.rx_chains_dynamic | 49 | __entry->rx_chains_dynamic = ctx->conf.rx_chains_dynamic |
50 | #define CHANCTX_PR_FMT CHANDEF_PR_FMT " chains:%d/%d" | 50 | #define CHANCTX_PR_FMT CHANDEF_PR_FMT " chains:%d/%d" |
51 | #define CHANCTX_PR_ARG CHANDEF_PR_ARG, \ | 51 | #define CHANCTX_PR_ARG CHANDEF_PR_ARG, \ |
52 | __entry->rx_chains_static, __entry->rx_chains_dynamic | 52 | __entry->rx_chains_static, __entry->rx_chains_dynamic |
53 | 53 | ||
54 | 54 | ||
@@ -286,8 +286,7 @@ TRACE_EVENT(drv_config, | |||
286 | __field(u16, listen_interval) | 286 | __field(u16, listen_interval) |
287 | __field(u8, long_frame_max_tx_count) | 287 | __field(u8, long_frame_max_tx_count) |
288 | __field(u8, short_frame_max_tx_count) | 288 | __field(u8, short_frame_max_tx_count) |
289 | __field(int, center_freq) | 289 | CHANDEF_ENTRY |
290 | __field(int, channel_type) | ||
291 | __field(int, smps) | 290 | __field(int, smps) |
292 | ), | 291 | ), |
293 | 292 | ||
@@ -303,15 +302,13 @@ TRACE_EVENT(drv_config, | |||
303 | local->hw.conf.long_frame_max_tx_count; | 302 | local->hw.conf.long_frame_max_tx_count; |
304 | __entry->short_frame_max_tx_count = | 303 | __entry->short_frame_max_tx_count = |
305 | local->hw.conf.short_frame_max_tx_count; | 304 | local->hw.conf.short_frame_max_tx_count; |
306 | __entry->center_freq = local->hw.conf.channel ? | 305 | CHANDEF_ASSIGN(&local->hw.conf.chandef) |
307 | local->hw.conf.channel->center_freq : 0; | ||
308 | __entry->channel_type = local->hw.conf.channel_type; | ||
309 | __entry->smps = local->hw.conf.smps_mode; | 306 | __entry->smps = local->hw.conf.smps_mode; |
310 | ), | 307 | ), |
311 | 308 | ||
312 | TP_printk( | 309 | TP_printk( |
313 | LOCAL_PR_FMT " ch:%#x freq:%d", | 310 | LOCAL_PR_FMT " ch:%#x" CHANDEF_PR_FMT, |
314 | LOCAL_PR_ARG, __entry->changed, __entry->center_freq | 311 | LOCAL_PR_ARG, __entry->changed, CHANDEF_PR_ARG |
315 | ) | 312 | ) |
316 | ); | 313 | ); |
317 | 314 | ||
@@ -359,8 +356,7 @@ TRACE_EVENT(drv_bss_info_changed, | |||
359 | __dynamic_array(u8, ssid, info->ssid_len); | 356 | __dynamic_array(u8, ssid, info->ssid_len); |
360 | __field(bool, hidden_ssid); | 357 | __field(bool, hidden_ssid); |
361 | __field(int, txpower) | 358 | __field(int, txpower) |
362 | __field(u8, p2p_ctwindow) | 359 | __field(u8, p2p_oppps_ctwindow) |
363 | __field(bool, p2p_oppps) | ||
364 | ), | 360 | ), |
365 | 361 | ||
366 | TP_fast_assign( | 362 | TP_fast_assign( |
@@ -400,8 +396,7 @@ TRACE_EVENT(drv_bss_info_changed, | |||
400 | memcpy(__get_dynamic_array(ssid), info->ssid, info->ssid_len); | 396 | memcpy(__get_dynamic_array(ssid), info->ssid, info->ssid_len); |
401 | __entry->hidden_ssid = info->hidden_ssid; | 397 | __entry->hidden_ssid = info->hidden_ssid; |
402 | __entry->txpower = info->txpower; | 398 | __entry->txpower = info->txpower; |
403 | __entry->p2p_ctwindow = info->p2p_ctwindow; | 399 | __entry->p2p_oppps_ctwindow = info->p2p_noa_attr.oppps_ctwindow; |
404 | __entry->p2p_oppps = info->p2p_oppps; | ||
405 | ), | 400 | ), |
406 | 401 | ||
407 | TP_printk( | 402 | TP_printk( |
diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c index 2a6ae8030bd9..aad0bf5d8812 100644 --- a/net/mac80211/tx.c +++ b/net/mac80211/tx.c | |||
@@ -1709,7 +1709,7 @@ netdev_tx_t ieee80211_monitor_start_xmit(struct sk_buff *skb, | |||
1709 | if (chanctx_conf) | 1709 | if (chanctx_conf) |
1710 | chan = chanctx_conf->def.chan; | 1710 | chan = chanctx_conf->def.chan; |
1711 | else if (!local->use_chanctx) | 1711 | else if (!local->use_chanctx) |
1712 | chan = local->_oper_channel; | 1712 | chan = local->_oper_chandef.chan; |
1713 | else | 1713 | else |
1714 | goto fail_rcu; | 1714 | goto fail_rcu; |
1715 | 1715 | ||
@@ -1843,7 +1843,7 @@ netdev_tx_t ieee80211_subif_start_xmit(struct sk_buff *skb, | |||
1843 | * This is the exception! WDS style interfaces are prohibited | 1843 | * This is the exception! WDS style interfaces are prohibited |
1844 | * when channel contexts are in used so this must be valid | 1844 | * when channel contexts are in used so this must be valid |
1845 | */ | 1845 | */ |
1846 | band = local->hw.conf.channel->band; | 1846 | band = local->hw.conf.chandef.chan->band; |
1847 | break; | 1847 | break; |
1848 | #ifdef CONFIG_MAC80211_MESH | 1848 | #ifdef CONFIG_MAC80211_MESH |
1849 | case NL80211_IFTYPE_MESH_POINT: | 1849 | case NL80211_IFTYPE_MESH_POINT: |
@@ -2442,14 +2442,17 @@ struct sk_buff *ieee80211_beacon_get_tim(struct ieee80211_hw *hw, | |||
2442 | } else if (sdata->vif.type == NL80211_IFTYPE_ADHOC) { | 2442 | } else if (sdata->vif.type == NL80211_IFTYPE_ADHOC) { |
2443 | struct ieee80211_if_ibss *ifibss = &sdata->u.ibss; | 2443 | struct ieee80211_if_ibss *ifibss = &sdata->u.ibss; |
2444 | struct ieee80211_hdr *hdr; | 2444 | struct ieee80211_hdr *hdr; |
2445 | struct sk_buff *presp = rcu_dereference(ifibss->presp); | 2445 | struct beacon_data *presp = rcu_dereference(ifibss->presp); |
2446 | 2446 | ||
2447 | if (!presp) | 2447 | if (!presp) |
2448 | goto out; | 2448 | goto out; |
2449 | 2449 | ||
2450 | skb = skb_copy(presp, GFP_ATOMIC); | 2450 | skb = dev_alloc_skb(local->tx_headroom + presp->head_len); |
2451 | if (!skb) | 2451 | if (!skb) |
2452 | goto out; | 2452 | goto out; |
2453 | skb_reserve(skb, local->tx_headroom); | ||
2454 | memcpy(skb_put(skb, presp->head_len), presp->head, | ||
2455 | presp->head_len); | ||
2453 | 2456 | ||
2454 | hdr = (struct ieee80211_hdr *) skb->data; | 2457 | hdr = (struct ieee80211_hdr *) skb->data; |
2455 | hdr->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT | | 2458 | hdr->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT | |
diff --git a/net/mac80211/util.c b/net/mac80211/util.c index a7368870c8ee..447e6651e7fa 100644 --- a/net/mac80211/util.c +++ b/net/mac80211/util.c | |||
@@ -738,17 +738,11 @@ u32 ieee802_11_parse_elems_crc(u8 *start, size_t len, | |||
738 | elems->supp_rates = pos; | 738 | elems->supp_rates = pos; |
739 | elems->supp_rates_len = elen; | 739 | elems->supp_rates_len = elen; |
740 | break; | 740 | break; |
741 | case WLAN_EID_FH_PARAMS: | ||
742 | elems->fh_params = pos; | ||
743 | elems->fh_params_len = elen; | ||
744 | break; | ||
745 | case WLAN_EID_DS_PARAMS: | 741 | case WLAN_EID_DS_PARAMS: |
746 | elems->ds_params = pos; | 742 | if (elen >= 1) |
747 | elems->ds_params_len = elen; | 743 | elems->ds_params = pos; |
748 | break; | 744 | else |
749 | case WLAN_EID_CF_PARAMS: | 745 | elem_parse_failed = true; |
750 | elems->cf_params = pos; | ||
751 | elems->cf_params_len = elen; | ||
752 | break; | 746 | break; |
753 | case WLAN_EID_TIM: | 747 | case WLAN_EID_TIM: |
754 | if (elen >= sizeof(struct ieee80211_tim_ie)) { | 748 | if (elen >= sizeof(struct ieee80211_tim_ie)) { |
@@ -757,10 +751,6 @@ u32 ieee802_11_parse_elems_crc(u8 *start, size_t len, | |||
757 | } else | 751 | } else |
758 | elem_parse_failed = true; | 752 | elem_parse_failed = true; |
759 | break; | 753 | break; |
760 | case WLAN_EID_IBSS_PARAMS: | ||
761 | elems->ibss_params = pos; | ||
762 | elems->ibss_params_len = elen; | ||
763 | break; | ||
764 | case WLAN_EID_CHALLENGE: | 754 | case WLAN_EID_CHALLENGE: |
765 | elems->challenge = pos; | 755 | elems->challenge = pos; |
766 | elems->challenge_len = elen; | 756 | elems->challenge_len = elen; |
@@ -790,8 +780,10 @@ u32 ieee802_11_parse_elems_crc(u8 *start, size_t len, | |||
790 | elems->rsn_len = elen; | 780 | elems->rsn_len = elen; |
791 | break; | 781 | break; |
792 | case WLAN_EID_ERP_INFO: | 782 | case WLAN_EID_ERP_INFO: |
793 | elems->erp_info = pos; | 783 | if (elen >= 1) |
794 | elems->erp_info_len = elen; | 784 | elems->erp_info = pos; |
785 | else | ||
786 | elem_parse_failed = true; | ||
795 | break; | 787 | break; |
796 | case WLAN_EID_EXT_SUPP_RATES: | 788 | case WLAN_EID_EXT_SUPP_RATES: |
797 | elems->ext_supp_rates = pos; | 789 | elems->ext_supp_rates = pos; |
@@ -870,13 +862,6 @@ u32 ieee802_11_parse_elems_crc(u8 *start, size_t len, | |||
870 | } | 862 | } |
871 | elems->ch_switch_ie = (void *)pos; | 863 | elems->ch_switch_ie = (void *)pos; |
872 | break; | 864 | break; |
873 | case WLAN_EID_QUIET: | ||
874 | if (!elems->quiet_elem) { | ||
875 | elems->quiet_elem = pos; | ||
876 | elems->quiet_elem_len = elen; | ||
877 | } | ||
878 | elems->num_of_quiet_elem++; | ||
879 | break; | ||
880 | case WLAN_EID_COUNTRY: | 865 | case WLAN_EID_COUNTRY: |
881 | elems->country_elem = pos; | 866 | elems->country_elem = pos; |
882 | elems->country_elem_len = elen; | 867 | elems->country_elem_len = elen; |
@@ -889,8 +874,10 @@ u32 ieee802_11_parse_elems_crc(u8 *start, size_t len, | |||
889 | elems->pwr_constr_elem = pos; | 874 | elems->pwr_constr_elem = pos; |
890 | break; | 875 | break; |
891 | case WLAN_EID_TIMEOUT_INTERVAL: | 876 | case WLAN_EID_TIMEOUT_INTERVAL: |
892 | elems->timeout_int = pos; | 877 | if (elen >= sizeof(struct ieee80211_timeout_interval_ie)) |
893 | elems->timeout_int_len = elen; | 878 | elems->timeout_int = (void *)pos; |
879 | else | ||
880 | elem_parse_failed = true; | ||
894 | break; | 881 | break; |
895 | default: | 882 | default: |
896 | break; | 883 | break; |
@@ -911,12 +898,6 @@ u32 ieee802_11_parse_elems_crc(u8 *start, size_t len, | |||
911 | return crc; | 898 | return crc; |
912 | } | 899 | } |
913 | 900 | ||
914 | void ieee802_11_parse_elems(u8 *start, size_t len, | ||
915 | struct ieee802_11_elems *elems) | ||
916 | { | ||
917 | ieee802_11_parse_elems_crc(start, len, elems, 0, 0); | ||
918 | } | ||
919 | |||
920 | void ieee80211_set_wmm_default(struct ieee80211_sub_if_data *sdata, | 901 | void ieee80211_set_wmm_default(struct ieee80211_sub_if_data *sdata, |
921 | bool bss_notify) | 902 | bool bss_notify) |
922 | { | 903 | { |
@@ -1474,6 +1455,8 @@ int ieee80211_reconfig(struct ieee80211_local *local) | |||
1474 | /* add interfaces */ | 1455 | /* add interfaces */ |
1475 | sdata = rtnl_dereference(local->monitor_sdata); | 1456 | sdata = rtnl_dereference(local->monitor_sdata); |
1476 | if (sdata) { | 1457 | if (sdata) { |
1458 | /* in HW restart it exists already */ | ||
1459 | WARN_ON(local->resuming); | ||
1477 | res = drv_add_interface(local, sdata); | 1460 | res = drv_add_interface(local, sdata); |
1478 | if (WARN_ON(res)) { | 1461 | if (WARN_ON(res)) { |
1479 | rcu_assign_pointer(local->monitor_sdata, NULL); | 1462 | rcu_assign_pointer(local->monitor_sdata, NULL); |
@@ -1663,6 +1646,9 @@ int ieee80211_reconfig(struct ieee80211_local *local) | |||
1663 | local->in_reconfig = false; | 1646 | local->in_reconfig = false; |
1664 | barrier(); | 1647 | barrier(); |
1665 | 1648 | ||
1649 | if (local->monitors == local->open_count && local->monitors > 0) | ||
1650 | ieee80211_add_virtual_monitor(local); | ||
1651 | |||
1666 | /* | 1652 | /* |
1667 | * Clear the WLAN_STA_BLOCK_BA flag so new aggregation | 1653 | * Clear the WLAN_STA_BLOCK_BA flag so new aggregation |
1668 | * sessions can be established after a resume. | 1654 | * sessions can be established after a resume. |
@@ -2056,7 +2042,7 @@ int ieee80211_ave_rssi(struct ieee80211_vif *vif) | |||
2056 | /* non-managed type inferfaces */ | 2042 | /* non-managed type inferfaces */ |
2057 | return 0; | 2043 | return 0; |
2058 | } | 2044 | } |
2059 | return ifmgd->ave_beacon_signal; | 2045 | return ifmgd->ave_beacon_signal / 16; |
2060 | } | 2046 | } |
2061 | EXPORT_SYMBOL_GPL(ieee80211_ave_rssi); | 2047 | EXPORT_SYMBOL_GPL(ieee80211_ave_rssi); |
2062 | 2048 | ||
@@ -2171,8 +2157,7 @@ void ieee80211_dfs_radar_detected_work(struct work_struct *work) | |||
2171 | /* currently not handled */ | 2157 | /* currently not handled */ |
2172 | WARN_ON(1); | 2158 | WARN_ON(1); |
2173 | else { | 2159 | else { |
2174 | cfg80211_chandef_create(&chandef, local->hw.conf.channel, | 2160 | chandef = local->hw.conf.chandef; |
2175 | local->hw.conf.channel_type); | ||
2176 | cfg80211_radar_event(local->hw.wiphy, &chandef, GFP_KERNEL); | 2161 | cfg80211_radar_event(local->hw.wiphy, &chandef, GFP_KERNEL); |
2177 | } | 2162 | } |
2178 | } | 2163 | } |