mirror of https://gitee.com/openkylin/linux.git
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) -----BEGIN PGP SIGNATURE----- iQIcBAABCgAGBQJYLrKJAAoJEGt7eEactAAdshYP/Rwi/k9WZ0RKQIA1QA0fnmwv TbUUvPHQ4LA39Czs0JwOPDIbter7TBzFXV5EK0y39jGm8St4a/oHuN072kzBYvob YbBzM0YKV2uQCAjH3AjWjS3RPOlTzfUqSRWgEqtgUTC5VZrpNfhd2r0q+jfwpQ7s +qUsdwqvVJMZKfOEngIXzNXdI95N1d8tpGwzkUqDbOJ+7amdriiJKyTsKEOMqREA 0Mdhu6roEcMDVO+xt5ZkilmpLZOUEHAzaWkwm7d6VToWi7k3pwMiEZ4fthvHZHEZ 6K2bn1UMLdKAExRcQBE3wrmn5jFfUbts1mhmoN1drHocI12epcgw5I4ZjEbfpqMB IBkOM+2hbSdUVfE4KVH6iubqiJwtHB8YSTdKFmMO4jPx7UshPF7YCny6XWC+EqQm ktjyG/lhlXJ0HaOKC/MAwd/KSzfH0eJWGNBDV5s/FIWiqu2oWn+ZIX7vGTpp4K1Z Rery/ZUiJGzVITNG1ka+GXq2tUvDXfkMApr+jFH4G6zioWovxB6+4uyMEeclvC5q zjgYEpZhbn2wQUNEJ8btDDgXkyDGh3UPjy93fO8fMEvv8d9CCOKTQkIUpjPp6jbZ EoLCTW0NNjnAmQRiUFF3vO2O7e3ZTJ4hyNEVkc7mJ2X3DllXRSelTIFSfZVHpb2k P+gY7uC0cAPZ4s6q8GSb =q2mI -----END PGP SIGNATURE----- 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>
This commit is contained in:
commit
87305c4cd2
|
@ -826,7 +826,7 @@ static void mac80211_hwsim_set_tsf(struct ieee80211_hw *hw,
|
|||
data->bcn_delta = do_div(delta, bcn_int);
|
||||
} else {
|
||||
data->tsf_offset -= delta;
|
||||
data->bcn_delta = -do_div(delta, bcn_int);
|
||||
data->bcn_delta = -(s64)do_div(delta, bcn_int);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -688,7 +688,7 @@ static void __sta_info_recalc_tim(struct sta_info *sta, bool ignore_pending)
|
|||
}
|
||||
|
||||
/* No need to do anything if the driver does all */
|
||||
if (!local->ops->set_tim)
|
||||
if (ieee80211_hw_check(&local->hw, AP_LINK_PS))
|
||||
return;
|
||||
|
||||
if (sta->dead)
|
||||
|
|
|
@ -1501,7 +1501,6 @@ static bool ieee80211_queue_skb(struct ieee80211_local *local,
|
|||
struct sta_info *sta,
|
||||
struct sk_buff *skb)
|
||||
{
|
||||
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
|
||||
struct fq *fq = &local->fq;
|
||||
struct ieee80211_vif *vif;
|
||||
struct txq_info *txqi;
|
||||
|
@ -1526,8 +1525,6 @@ static bool ieee80211_queue_skb(struct ieee80211_local *local,
|
|||
if (!txqi)
|
||||
return false;
|
||||
|
||||
info->control.vif = vif;
|
||||
|
||||
spin_lock_bh(&fq->lock);
|
||||
ieee80211_txq_enqueue(local, txqi, skb);
|
||||
spin_unlock_bh(&fq->lock);
|
||||
|
@ -3213,7 +3210,6 @@ static void ieee80211_xmit_fast_finish(struct ieee80211_sub_if_data *sdata,
|
|||
|
||||
if (hdr->frame_control & cpu_to_le16(IEEE80211_STYPE_QOS_DATA)) {
|
||||
tid = skb->priority & IEEE80211_QOS_CTL_TAG1D_MASK;
|
||||
*ieee80211_get_qos_ctl(hdr) = tid;
|
||||
hdr->seq_ctrl = ieee80211_tx_next_seq(sta, tid);
|
||||
} else {
|
||||
info->flags |= IEEE80211_TX_CTL_ASSIGN_SEQ;
|
||||
|
@ -3338,6 +3334,11 @@ static bool ieee80211_xmit_fast(struct ieee80211_sub_if_data *sdata,
|
|||
(tid_tx ? IEEE80211_TX_CTL_AMPDU : 0);
|
||||
info->control.flags = IEEE80211_TX_CTRL_FAST_XMIT;
|
||||
|
||||
if (hdr->frame_control & cpu_to_le16(IEEE80211_STYPE_QOS_DATA)) {
|
||||
tid = skb->priority & IEEE80211_QOS_CTL_TAG1D_MASK;
|
||||
*ieee80211_get_qos_ctl(hdr) = tid;
|
||||
}
|
||||
|
||||
__skb_queue_head_init(&tx.skbs);
|
||||
|
||||
tx.flags = IEEE80211_TX_UNICAST;
|
||||
|
@ -3426,6 +3427,11 @@ struct sk_buff *ieee80211_tx_dequeue(struct ieee80211_hw *hw,
|
|||
goto begin;
|
||||
}
|
||||
|
||||
if (test_bit(IEEE80211_TXQ_AMPDU, &txqi->flags))
|
||||
info->flags |= IEEE80211_TX_CTL_AMPDU;
|
||||
else
|
||||
info->flags &= ~IEEE80211_TX_CTL_AMPDU;
|
||||
|
||||
if (info->control.flags & IEEE80211_TX_CTRL_FAST_XMIT) {
|
||||
struct sta_info *sta = container_of(txq->sta, struct sta_info,
|
||||
sta);
|
||||
|
|
|
@ -270,6 +270,22 @@ ieee80211_vht_cap_ie_to_sta_vht_cap(struct ieee80211_sub_if_data *sdata,
|
|||
vht_cap->vht_mcs.tx_mcs_map |= cpu_to_le16(peer_tx << i * 2);
|
||||
}
|
||||
|
||||
/*
|
||||
* This is a workaround for VHT-enabled STAs which break the spec
|
||||
* and have the VHT-MCS Rx map filled in with value 3 for all eight
|
||||
* spacial streams, an example is AR9462.
|
||||
*
|
||||
* As per spec, in section 22.1.1 Introduction to the VHT PHY
|
||||
* A VHT STA shall support at least single spactial stream VHT-MCSs
|
||||
* 0 to 7 (transmit and receive) in all supported channel widths.
|
||||
*/
|
||||
if (vht_cap->vht_mcs.rx_mcs_map == cpu_to_le16(0xFFFF)) {
|
||||
vht_cap->vht_supported = false;
|
||||
sdata_info(sdata, "Ignoring VHT IE from %pM due to invalid rx_mcs_map\n",
|
||||
sta->addr);
|
||||
return;
|
||||
}
|
||||
|
||||
/* finally set up the bandwidth */
|
||||
switch (vht_cap->cap & IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_MASK) {
|
||||
case IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160MHZ:
|
||||
|
|
|
@ -71,6 +71,7 @@ struct cfg80211_registered_device {
|
|||
struct list_head bss_list;
|
||||
struct rb_root bss_tree;
|
||||
u32 bss_generation;
|
||||
u32 bss_entries;
|
||||
struct cfg80211_scan_request *scan_req; /* protected by RTNL */
|
||||
struct sk_buff *scan_msg;
|
||||
struct cfg80211_sched_scan_request __rcu *sched_scan_req;
|
||||
|
|
|
@ -57,6 +57,19 @@
|
|||
* also linked into the probe response struct.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Limit the number of BSS entries stored in mac80211. Each one is
|
||||
* a bit over 4k at most, so this limits to roughly 4-5M of memory.
|
||||
* If somebody wants to really attack this though, they'd likely
|
||||
* use small beacons, and only one type of frame, limiting each of
|
||||
* the entries to a much smaller size (in order to generate more
|
||||
* entries in total, so overhead is bigger.)
|
||||
*/
|
||||
static int bss_entries_limit = 1000;
|
||||
module_param(bss_entries_limit, int, 0644);
|
||||
MODULE_PARM_DESC(bss_entries_limit,
|
||||
"limit to number of scan BSS entries (per wiphy, default 1000)");
|
||||
|
||||
#define IEEE80211_SCAN_RESULT_EXPIRE (30 * HZ)
|
||||
|
||||
static void bss_free(struct cfg80211_internal_bss *bss)
|
||||
|
@ -137,6 +150,10 @@ static bool __cfg80211_unlink_bss(struct cfg80211_registered_device *rdev,
|
|||
|
||||
list_del_init(&bss->list);
|
||||
rb_erase(&bss->rbn, &rdev->bss_tree);
|
||||
rdev->bss_entries--;
|
||||
WARN_ONCE((rdev->bss_entries == 0) ^ list_empty(&rdev->bss_list),
|
||||
"rdev bss entries[%d]/list[empty:%d] corruption\n",
|
||||
rdev->bss_entries, list_empty(&rdev->bss_list));
|
||||
bss_ref_put(rdev, bss);
|
||||
return true;
|
||||
}
|
||||
|
@ -163,6 +180,40 @@ static void __cfg80211_bss_expire(struct cfg80211_registered_device *rdev,
|
|||
rdev->bss_generation++;
|
||||
}
|
||||
|
||||
static bool cfg80211_bss_expire_oldest(struct cfg80211_registered_device *rdev)
|
||||
{
|
||||
struct cfg80211_internal_bss *bss, *oldest = NULL;
|
||||
bool ret;
|
||||
|
||||
lockdep_assert_held(&rdev->bss_lock);
|
||||
|
||||
list_for_each_entry(bss, &rdev->bss_list, list) {
|
||||
if (atomic_read(&bss->hold))
|
||||
continue;
|
||||
|
||||
if (!list_empty(&bss->hidden_list) &&
|
||||
!bss->pub.hidden_beacon_bss)
|
||||
continue;
|
||||
|
||||
if (oldest && time_before(oldest->ts, bss->ts))
|
||||
continue;
|
||||
oldest = bss;
|
||||
}
|
||||
|
||||
if (WARN_ON(!oldest))
|
||||
return false;
|
||||
|
||||
/*
|
||||
* The callers make sure to increase rdev->bss_generation if anything
|
||||
* gets removed (and a new entry added), so there's no need to also do
|
||||
* it here.
|
||||
*/
|
||||
|
||||
ret = __cfg80211_unlink_bss(rdev, oldest);
|
||||
WARN_ON(!ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
void ___cfg80211_scan_done(struct cfg80211_registered_device *rdev,
|
||||
bool send_message)
|
||||
{
|
||||
|
@ -689,6 +740,7 @@ static bool cfg80211_combine_bsses(struct cfg80211_registered_device *rdev,
|
|||
const u8 *ie;
|
||||
int i, ssidlen;
|
||||
u8 fold = 0;
|
||||
u32 n_entries = 0;
|
||||
|
||||
ies = rcu_access_pointer(new->pub.beacon_ies);
|
||||
if (WARN_ON(!ies))
|
||||
|
@ -712,6 +764,12 @@ static bool cfg80211_combine_bsses(struct cfg80211_registered_device *rdev,
|
|||
/* This is the bad part ... */
|
||||
|
||||
list_for_each_entry(bss, &rdev->bss_list, list) {
|
||||
/*
|
||||
* we're iterating all the entries anyway, so take the
|
||||
* opportunity to validate the list length accounting
|
||||
*/
|
||||
n_entries++;
|
||||
|
||||
if (!ether_addr_equal(bss->pub.bssid, new->pub.bssid))
|
||||
continue;
|
||||
if (bss->pub.channel != new->pub.channel)
|
||||
|
@ -740,6 +798,10 @@ static bool cfg80211_combine_bsses(struct cfg80211_registered_device *rdev,
|
|||
new->pub.beacon_ies);
|
||||
}
|
||||
|
||||
WARN_ONCE(n_entries != rdev->bss_entries,
|
||||
"rdev bss entries[%d]/list[len:%d] corruption\n",
|
||||
rdev->bss_entries, n_entries);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -894,7 +956,14 @@ cfg80211_bss_update(struct cfg80211_registered_device *rdev,
|
|||
}
|
||||
}
|
||||
|
||||
if (rdev->bss_entries >= bss_entries_limit &&
|
||||
!cfg80211_bss_expire_oldest(rdev)) {
|
||||
kfree(new);
|
||||
goto drop;
|
||||
}
|
||||
|
||||
list_add_tail(&new->list, &rdev->bss_list);
|
||||
rdev->bss_entries++;
|
||||
rb_insert_bss(rdev, new);
|
||||
found = new;
|
||||
}
|
||||
|
|
|
@ -1158,7 +1158,8 @@ static u32 cfg80211_calculate_bitrate_vht(struct rate_info *rate)
|
|||
58500000,
|
||||
65000000,
|
||||
78000000,
|
||||
0,
|
||||
/* not in the spec, but some devices use this: */
|
||||
86500000,
|
||||
},
|
||||
{ 13500000,
|
||||
27000000,
|
||||
|
|
Loading…
Reference in New Issue