diff options
author | David S. Miller <davem@davemloft.net> | 2016-11-18 14:00:27 -0500 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2016-11-18 14:00:27 -0500 |
commit | 87305c4cd261664a12cff16740d0c40065bbd07f (patch) | |
tree | 5fa9a470f011736d0ff728aa54f9f540b2485724 | |
parent | 06a77b07e3b44aea2b3c0e64de420ea2cfdcbaa9 (diff) | |
parent | 9853a55ef1bb66d7411136046060bbfb69c714fa (diff) |
Merge tag 'mac80211-for-davem-2016-11-18' of git://git.kernel.org/pub/scm/linux/kernel/git/jberg/mac80211
Johannes Berg says:
====================
A few more bugfixes:
* limit # of scan results stored in memory - this is a long-standing bug
Jouni and I only noticed while discussing other things in Santa Fe
* revert AP_LINK_PS patch that was causing issues (Felix)
* various A-MSDU/A-MPDU fixes for TXQ code (Felix)
* interoperability workaround for peers with broken VHT capabilities
(Filip Matusiak)
* add bitrate definition for a VHT MCS that's supposed to be invalid
but gets used by some hardware anyway (Thomas Pedersen)
* beacon timer fix in hwsim (Benjamin Beichler)
====================
Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r-- | drivers/net/wireless/mac80211_hwsim.c | 2 | ||||
-rw-r--r-- | net/mac80211/sta_info.c | 2 | ||||
-rw-r--r-- | net/mac80211/tx.c | 14 | ||||
-rw-r--r-- | net/mac80211/vht.c | 16 | ||||
-rw-r--r-- | net/wireless/core.h | 1 | ||||
-rw-r--r-- | net/wireless/scan.c | 69 | ||||
-rw-r--r-- | net/wireless/util.c | 3 |
7 files changed, 100 insertions, 7 deletions
diff --git a/drivers/net/wireless/mac80211_hwsim.c b/drivers/net/wireless/mac80211_hwsim.c index 431f13b4faf6..d3bad5779376 100644 --- a/drivers/net/wireless/mac80211_hwsim.c +++ b/drivers/net/wireless/mac80211_hwsim.c | |||
@@ -826,7 +826,7 @@ static void mac80211_hwsim_set_tsf(struct ieee80211_hw *hw, | |||
826 | data->bcn_delta = do_div(delta, bcn_int); | 826 | data->bcn_delta = do_div(delta, bcn_int); |
827 | } else { | 827 | } else { |
828 | data->tsf_offset -= delta; | 828 | data->tsf_offset -= delta; |
829 | data->bcn_delta = -do_div(delta, bcn_int); | 829 | data->bcn_delta = -(s64)do_div(delta, bcn_int); |
830 | } | 830 | } |
831 | } | 831 | } |
832 | 832 | ||
diff --git a/net/mac80211/sta_info.c b/net/mac80211/sta_info.c index 78e9ecbc96e6..8e05032689f0 100644 --- a/net/mac80211/sta_info.c +++ b/net/mac80211/sta_info.c | |||
@@ -688,7 +688,7 @@ static void __sta_info_recalc_tim(struct sta_info *sta, bool ignore_pending) | |||
688 | } | 688 | } |
689 | 689 | ||
690 | /* No need to do anything if the driver does all */ | 690 | /* No need to do anything if the driver does all */ |
691 | if (!local->ops->set_tim) | 691 | if (ieee80211_hw_check(&local->hw, AP_LINK_PS)) |
692 | return; | 692 | return; |
693 | 693 | ||
694 | if (sta->dead) | 694 | if (sta->dead) |
diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c index 1c56abc49627..bd5f4be89435 100644 --- a/net/mac80211/tx.c +++ b/net/mac80211/tx.c | |||
@@ -1501,7 +1501,6 @@ static bool ieee80211_queue_skb(struct ieee80211_local *local, | |||
1501 | struct sta_info *sta, | 1501 | struct sta_info *sta, |
1502 | struct sk_buff *skb) | 1502 | struct sk_buff *skb) |
1503 | { | 1503 | { |
1504 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); | ||
1505 | struct fq *fq = &local->fq; | 1504 | struct fq *fq = &local->fq; |
1506 | struct ieee80211_vif *vif; | 1505 | struct ieee80211_vif *vif; |
1507 | struct txq_info *txqi; | 1506 | struct txq_info *txqi; |
@@ -1526,8 +1525,6 @@ static bool ieee80211_queue_skb(struct ieee80211_local *local, | |||
1526 | if (!txqi) | 1525 | if (!txqi) |
1527 | return false; | 1526 | return false; |
1528 | 1527 | ||
1529 | info->control.vif = vif; | ||
1530 | |||
1531 | spin_lock_bh(&fq->lock); | 1528 | spin_lock_bh(&fq->lock); |
1532 | ieee80211_txq_enqueue(local, txqi, skb); | 1529 | ieee80211_txq_enqueue(local, txqi, skb); |
1533 | spin_unlock_bh(&fq->lock); | 1530 | spin_unlock_bh(&fq->lock); |
@@ -3213,7 +3210,6 @@ static void ieee80211_xmit_fast_finish(struct ieee80211_sub_if_data *sdata, | |||
3213 | 3210 | ||
3214 | if (hdr->frame_control & cpu_to_le16(IEEE80211_STYPE_QOS_DATA)) { | 3211 | if (hdr->frame_control & cpu_to_le16(IEEE80211_STYPE_QOS_DATA)) { |
3215 | tid = skb->priority & IEEE80211_QOS_CTL_TAG1D_MASK; | 3212 | tid = skb->priority & IEEE80211_QOS_CTL_TAG1D_MASK; |
3216 | *ieee80211_get_qos_ctl(hdr) = tid; | ||
3217 | hdr->seq_ctrl = ieee80211_tx_next_seq(sta, tid); | 3213 | hdr->seq_ctrl = ieee80211_tx_next_seq(sta, tid); |
3218 | } else { | 3214 | } else { |
3219 | info->flags |= IEEE80211_TX_CTL_ASSIGN_SEQ; | 3215 | info->flags |= IEEE80211_TX_CTL_ASSIGN_SEQ; |
@@ -3338,6 +3334,11 @@ static bool ieee80211_xmit_fast(struct ieee80211_sub_if_data *sdata, | |||
3338 | (tid_tx ? IEEE80211_TX_CTL_AMPDU : 0); | 3334 | (tid_tx ? IEEE80211_TX_CTL_AMPDU : 0); |
3339 | info->control.flags = IEEE80211_TX_CTRL_FAST_XMIT; | 3335 | info->control.flags = IEEE80211_TX_CTRL_FAST_XMIT; |
3340 | 3336 | ||
3337 | if (hdr->frame_control & cpu_to_le16(IEEE80211_STYPE_QOS_DATA)) { | ||
3338 | tid = skb->priority & IEEE80211_QOS_CTL_TAG1D_MASK; | ||
3339 | *ieee80211_get_qos_ctl(hdr) = tid; | ||
3340 | } | ||
3341 | |||
3341 | __skb_queue_head_init(&tx.skbs); | 3342 | __skb_queue_head_init(&tx.skbs); |
3342 | 3343 | ||
3343 | tx.flags = IEEE80211_TX_UNICAST; | 3344 | tx.flags = IEEE80211_TX_UNICAST; |
@@ -3426,6 +3427,11 @@ begin: | |||
3426 | goto begin; | 3427 | goto begin; |
3427 | } | 3428 | } |
3428 | 3429 | ||
3430 | if (test_bit(IEEE80211_TXQ_AMPDU, &txqi->flags)) | ||
3431 | info->flags |= IEEE80211_TX_CTL_AMPDU; | ||
3432 | else | ||
3433 | info->flags &= ~IEEE80211_TX_CTL_AMPDU; | ||
3434 | |||
3429 | if (info->control.flags & IEEE80211_TX_CTRL_FAST_XMIT) { | 3435 | if (info->control.flags & IEEE80211_TX_CTRL_FAST_XMIT) { |
3430 | struct sta_info *sta = container_of(txq->sta, struct sta_info, | 3436 | struct sta_info *sta = container_of(txq->sta, struct sta_info, |
3431 | sta); | 3437 | sta); |
diff --git a/net/mac80211/vht.c b/net/mac80211/vht.c index ee715764a828..6832bf6ab69f 100644 --- a/net/mac80211/vht.c +++ b/net/mac80211/vht.c | |||
@@ -270,6 +270,22 @@ ieee80211_vht_cap_ie_to_sta_vht_cap(struct ieee80211_sub_if_data *sdata, | |||
270 | vht_cap->vht_mcs.tx_mcs_map |= cpu_to_le16(peer_tx << i * 2); | 270 | vht_cap->vht_mcs.tx_mcs_map |= cpu_to_le16(peer_tx << i * 2); |
271 | } | 271 | } |
272 | 272 | ||
273 | /* | ||
274 | * This is a workaround for VHT-enabled STAs which break the spec | ||
275 | * and have the VHT-MCS Rx map filled in with value 3 for all eight | ||
276 | * spacial streams, an example is AR9462. | ||
277 | * | ||
278 | * As per spec, in section 22.1.1 Introduction to the VHT PHY | ||
279 | * A VHT STA shall support at least single spactial stream VHT-MCSs | ||
280 | * 0 to 7 (transmit and receive) in all supported channel widths. | ||
281 | */ | ||
282 | if (vht_cap->vht_mcs.rx_mcs_map == cpu_to_le16(0xFFFF)) { | ||
283 | vht_cap->vht_supported = false; | ||
284 | sdata_info(sdata, "Ignoring VHT IE from %pM due to invalid rx_mcs_map\n", | ||
285 | sta->addr); | ||
286 | return; | ||
287 | } | ||
288 | |||
273 | /* finally set up the bandwidth */ | 289 | /* finally set up the bandwidth */ |
274 | switch (vht_cap->cap & IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_MASK) { | 290 | switch (vht_cap->cap & IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_MASK) { |
275 | case IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160MHZ: | 291 | case IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160MHZ: |
diff --git a/net/wireless/core.h b/net/wireless/core.h index 08d2e948c9ad..f0c0c8a48c92 100644 --- a/net/wireless/core.h +++ b/net/wireless/core.h | |||
@@ -71,6 +71,7 @@ struct cfg80211_registered_device { | |||
71 | struct list_head bss_list; | 71 | struct list_head bss_list; |
72 | struct rb_root bss_tree; | 72 | struct rb_root bss_tree; |
73 | u32 bss_generation; | 73 | u32 bss_generation; |
74 | u32 bss_entries; | ||
74 | struct cfg80211_scan_request *scan_req; /* protected by RTNL */ | 75 | struct cfg80211_scan_request *scan_req; /* protected by RTNL */ |
75 | struct sk_buff *scan_msg; | 76 | struct sk_buff *scan_msg; |
76 | struct cfg80211_sched_scan_request __rcu *sched_scan_req; | 77 | struct cfg80211_sched_scan_request __rcu *sched_scan_req; |
diff --git a/net/wireless/scan.c b/net/wireless/scan.c index b5bd58d0f731..35ad69fd0838 100644 --- a/net/wireless/scan.c +++ b/net/wireless/scan.c | |||
@@ -57,6 +57,19 @@ | |||
57 | * also linked into the probe response struct. | 57 | * also linked into the probe response struct. |
58 | */ | 58 | */ |
59 | 59 | ||
60 | /* | ||
61 | * Limit the number of BSS entries stored in mac80211. Each one is | ||
62 | * a bit over 4k at most, so this limits to roughly 4-5M of memory. | ||
63 | * If somebody wants to really attack this though, they'd likely | ||
64 | * use small beacons, and only one type of frame, limiting each of | ||
65 | * the entries to a much smaller size (in order to generate more | ||
66 | * entries in total, so overhead is bigger.) | ||
67 | */ | ||
68 | static int bss_entries_limit = 1000; | ||
69 | module_param(bss_entries_limit, int, 0644); | ||
70 | MODULE_PARM_DESC(bss_entries_limit, | ||
71 | "limit to number of scan BSS entries (per wiphy, default 1000)"); | ||
72 | |||
60 | #define IEEE80211_SCAN_RESULT_EXPIRE (30 * HZ) | 73 | #define IEEE80211_SCAN_RESULT_EXPIRE (30 * HZ) |
61 | 74 | ||
62 | static void bss_free(struct cfg80211_internal_bss *bss) | 75 | static void bss_free(struct cfg80211_internal_bss *bss) |
@@ -137,6 +150,10 @@ static bool __cfg80211_unlink_bss(struct cfg80211_registered_device *rdev, | |||
137 | 150 | ||
138 | list_del_init(&bss->list); | 151 | list_del_init(&bss->list); |
139 | rb_erase(&bss->rbn, &rdev->bss_tree); | 152 | rb_erase(&bss->rbn, &rdev->bss_tree); |
153 | rdev->bss_entries--; | ||
154 | WARN_ONCE((rdev->bss_entries == 0) ^ list_empty(&rdev->bss_list), | ||
155 | "rdev bss entries[%d]/list[empty:%d] corruption\n", | ||
156 | rdev->bss_entries, list_empty(&rdev->bss_list)); | ||
140 | bss_ref_put(rdev, bss); | 157 | bss_ref_put(rdev, bss); |
141 | return true; | 158 | return true; |
142 | } | 159 | } |
@@ -163,6 +180,40 @@ static void __cfg80211_bss_expire(struct cfg80211_registered_device *rdev, | |||
163 | rdev->bss_generation++; | 180 | rdev->bss_generation++; |
164 | } | 181 | } |
165 | 182 | ||
183 | static bool cfg80211_bss_expire_oldest(struct cfg80211_registered_device *rdev) | ||
184 | { | ||
185 | struct cfg80211_internal_bss *bss, *oldest = NULL; | ||
186 | bool ret; | ||
187 | |||
188 | lockdep_assert_held(&rdev->bss_lock); | ||
189 | |||
190 | list_for_each_entry(bss, &rdev->bss_list, list) { | ||
191 | if (atomic_read(&bss->hold)) | ||
192 | continue; | ||
193 | |||
194 | if (!list_empty(&bss->hidden_list) && | ||
195 | !bss->pub.hidden_beacon_bss) | ||
196 | continue; | ||
197 | |||
198 | if (oldest && time_before(oldest->ts, bss->ts)) | ||
199 | continue; | ||
200 | oldest = bss; | ||
201 | } | ||
202 | |||
203 | if (WARN_ON(!oldest)) | ||
204 | return false; | ||
205 | |||
206 | /* | ||
207 | * The callers make sure to increase rdev->bss_generation if anything | ||
208 | * gets removed (and a new entry added), so there's no need to also do | ||
209 | * it here. | ||
210 | */ | ||
211 | |||
212 | ret = __cfg80211_unlink_bss(rdev, oldest); | ||
213 | WARN_ON(!ret); | ||
214 | return ret; | ||
215 | } | ||
216 | |||
166 | void ___cfg80211_scan_done(struct cfg80211_registered_device *rdev, | 217 | void ___cfg80211_scan_done(struct cfg80211_registered_device *rdev, |
167 | bool send_message) | 218 | bool send_message) |
168 | { | 219 | { |
@@ -689,6 +740,7 @@ static bool cfg80211_combine_bsses(struct cfg80211_registered_device *rdev, | |||
689 | const u8 *ie; | 740 | const u8 *ie; |
690 | int i, ssidlen; | 741 | int i, ssidlen; |
691 | u8 fold = 0; | 742 | u8 fold = 0; |
743 | u32 n_entries = 0; | ||
692 | 744 | ||
693 | ies = rcu_access_pointer(new->pub.beacon_ies); | 745 | ies = rcu_access_pointer(new->pub.beacon_ies); |
694 | if (WARN_ON(!ies)) | 746 | if (WARN_ON(!ies)) |
@@ -712,6 +764,12 @@ static bool cfg80211_combine_bsses(struct cfg80211_registered_device *rdev, | |||
712 | /* This is the bad part ... */ | 764 | /* This is the bad part ... */ |
713 | 765 | ||
714 | list_for_each_entry(bss, &rdev->bss_list, list) { | 766 | list_for_each_entry(bss, &rdev->bss_list, list) { |
767 | /* | ||
768 | * we're iterating all the entries anyway, so take the | ||
769 | * opportunity to validate the list length accounting | ||
770 | */ | ||
771 | n_entries++; | ||
772 | |||
715 | if (!ether_addr_equal(bss->pub.bssid, new->pub.bssid)) | 773 | if (!ether_addr_equal(bss->pub.bssid, new->pub.bssid)) |
716 | continue; | 774 | continue; |
717 | if (bss->pub.channel != new->pub.channel) | 775 | if (bss->pub.channel != new->pub.channel) |
@@ -740,6 +798,10 @@ static bool cfg80211_combine_bsses(struct cfg80211_registered_device *rdev, | |||
740 | new->pub.beacon_ies); | 798 | new->pub.beacon_ies); |
741 | } | 799 | } |
742 | 800 | ||
801 | WARN_ONCE(n_entries != rdev->bss_entries, | ||
802 | "rdev bss entries[%d]/list[len:%d] corruption\n", | ||
803 | rdev->bss_entries, n_entries); | ||
804 | |||
743 | return true; | 805 | return true; |
744 | } | 806 | } |
745 | 807 | ||
@@ -894,7 +956,14 @@ cfg80211_bss_update(struct cfg80211_registered_device *rdev, | |||
894 | } | 956 | } |
895 | } | 957 | } |
896 | 958 | ||
959 | if (rdev->bss_entries >= bss_entries_limit && | ||
960 | !cfg80211_bss_expire_oldest(rdev)) { | ||
961 | kfree(new); | ||
962 | goto drop; | ||
963 | } | ||
964 | |||
897 | list_add_tail(&new->list, &rdev->bss_list); | 965 | list_add_tail(&new->list, &rdev->bss_list); |
966 | rdev->bss_entries++; | ||
898 | rb_insert_bss(rdev, new); | 967 | rb_insert_bss(rdev, new); |
899 | found = new; | 968 | found = new; |
900 | } | 969 | } |
diff --git a/net/wireless/util.c b/net/wireless/util.c index 5ea12afc7706..659b507b347d 100644 --- a/net/wireless/util.c +++ b/net/wireless/util.c | |||
@@ -1158,7 +1158,8 @@ static u32 cfg80211_calculate_bitrate_vht(struct rate_info *rate) | |||
1158 | 58500000, | 1158 | 58500000, |
1159 | 65000000, | 1159 | 65000000, |
1160 | 78000000, | 1160 | 78000000, |
1161 | 0, | 1161 | /* not in the spec, but some devices use this: */ |
1162 | 86500000, | ||
1162 | }, | 1163 | }, |
1163 | { 13500000, | 1164 | { 13500000, |
1164 | 27000000, | 1165 | 27000000, |