forked from Minki/linux
We have a number of fixes, in part because I was late
in actually sending them out - will try to do better in the future: * handle VHT opmode properly when hostapd is controlling full station state * two fixes for minimum channel width in mac80211 * don't leave SMPS set to junk in HT capabilities * fix headroom when forwarding mesh packets, recently broken by another fix that failed to take into account frame encryption * fix the TID in null-data packets indicating EOSP (end of service period) in U-APSD * prevent attempting to use (and then failing which results in crashes) TXQs on stations that aren't added to the driver yet -----BEGIN PGP SIGNATURE----- iQIcBAABCgAGBQJYeNveAAoJEGt7eEactAAdCjgP+gIIUjpH08MazRE9Nl6gqRGW G6EAoaQDQ8AjiVo8nIJ33X2jmHRIPcyelyfMhdww3AtMJRrvl9wVhQvwKWI4+l6D o8UVMBu66fq2luQA6AtOkkU6SkKwC7Se72Mdx6OA/zvdZz4/9Y4nZpOFPVwCbxqL UJRzjrhnbS51YgL/Y0s0Vp+7Rv7IYCuH9JORNarMO5sYxaVpLWihJhbShX1bOshw uFTHOjNRseImLhM4GOvVA7fSUiK8jxEuMECmlDKQB/6nVxMskE54yLOqMB5Ys6va 2CKjp5xqM4FfqB4LMNp7soJAXUOXvqk25JXAAbkVNo4VRd2Y4GoJ7XdBPqd4kfKb rPlr+UP2xaSQsfqIoe+uFr/lVUmm4oCTrS/Mo7YVrjSMU7fntYwZccr9aw5jrQFW YU+1QTF25HEb1SL18FH9JNWpoTlOlpB3bwpbAW4BHzsqDYc76CE/oyDLdZ6zQYlu z92cLuycGTwgNhi1zDNThxB81zhZsWH1Jbh9ppZBdDPxo6E4DMK71okreGAXBEMJ IdFZZqJbYW4I/TsUtse4atozk6oXlTEFY/pX4Qm0gwGwmqQx+wfSNLbymsD7gR42 OkL+bZ701HBl2gJUWuICrM2lFWtD4/o6oWpaW2I7QUAQhjvUr4ld9kthVMF2vdlt w316EIfZQzBKw7Z7zjZI =GU6q -----END PGP SIGNATURE----- Merge tag 'mac80211-for-davem-2017-01-13' of git://git.kernel.org/pub/scm/linux/kernel/git/jberg/mac80211 Johannes Berg says: ==================== We have a number of fixes, in part because I was late in actually sending them out - will try to do better in the future: * handle VHT opmode properly when hostapd is controlling full station state * two fixes for minimum channel width in mac80211 * don't leave SMPS set to junk in HT capabilities * fix headroom when forwarding mesh packets, recently broken by another fix that failed to take into account frame encryption * fix the TID in null-data packets indicating EOSP (end of service period) in U-APSD * prevent attempting to use (and then failing which results in crashes) TXQs on stations that aren't added to the driver yet ==================== Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
commit
1a717fcf8b
@ -1772,7 +1772,9 @@ enum nl80211_commands {
|
||||
*
|
||||
* @NL80211_ATTR_OPMODE_NOTIF: Operating mode field from Operating Mode
|
||||
* Notification Element based on association request when used with
|
||||
* %NL80211_CMD_NEW_STATION; u8 attribute.
|
||||
* %NL80211_CMD_NEW_STATION or %NL80211_CMD_SET_STATION (only when
|
||||
* %NL80211_FEATURE_FULL_AP_CLIENT_STATE is supported, or with TDLS);
|
||||
* u8 attribute.
|
||||
*
|
||||
* @NL80211_ATTR_VENDOR_ID: The vendor ID, either a 24-bit OUI or, if
|
||||
* %NL80211_VENDOR_ID_IS_LINUX is set, a special Linux ID (not used yet)
|
||||
|
@ -231,9 +231,6 @@ ieee80211_get_max_required_bw(struct ieee80211_sub_if_data *sdata)
|
||||
!(sta->sdata->bss && sta->sdata->bss == sdata->bss))
|
||||
continue;
|
||||
|
||||
if (!sta->uploaded || !test_sta_flag(sta, WLAN_STA_ASSOC))
|
||||
continue;
|
||||
|
||||
max_bw = max(max_bw, ieee80211_get_sta_bw(&sta->sta));
|
||||
}
|
||||
rcu_read_unlock();
|
||||
|
@ -6,6 +6,7 @@
|
||||
* Copyright (c) 2006 Jiri Benc <jbenc@suse.cz>
|
||||
* Copyright 2008, Johannes Berg <johannes@sipsolutions.net>
|
||||
* Copyright 2013-2014 Intel Mobile Communications GmbH
|
||||
* Copyright (c) 2016 Intel Deutschland GmbH
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
@ -1295,6 +1296,26 @@ static void ieee80211_iface_work(struct work_struct *work)
|
||||
} else if (ieee80211_is_action(mgmt->frame_control) &&
|
||||
mgmt->u.action.category == WLAN_CATEGORY_VHT) {
|
||||
switch (mgmt->u.action.u.vht_group_notif.action_code) {
|
||||
case WLAN_VHT_ACTION_OPMODE_NOTIF: {
|
||||
struct ieee80211_rx_status *status;
|
||||
enum nl80211_band band;
|
||||
u8 opmode;
|
||||
|
||||
status = IEEE80211_SKB_RXCB(skb);
|
||||
band = status->band;
|
||||
opmode = mgmt->u.action.u.vht_opmode_notif.operating_mode;
|
||||
|
||||
mutex_lock(&local->sta_mtx);
|
||||
sta = sta_info_get_bss(sdata, mgmt->sa);
|
||||
|
||||
if (sta)
|
||||
ieee80211_vht_handle_opmode(sdata, sta,
|
||||
opmode,
|
||||
band);
|
||||
|
||||
mutex_unlock(&local->sta_mtx);
|
||||
break;
|
||||
}
|
||||
case WLAN_VHT_ACTION_GROUPID_MGMT:
|
||||
ieee80211_process_mu_groups(sdata, mgmt);
|
||||
break;
|
||||
|
@ -913,12 +913,17 @@ int ieee80211_register_hw(struct ieee80211_hw *hw)
|
||||
supp_ht = supp_ht || sband->ht_cap.ht_supported;
|
||||
supp_vht = supp_vht || sband->vht_cap.vht_supported;
|
||||
|
||||
if (sband->ht_cap.ht_supported)
|
||||
local->rx_chains =
|
||||
max(ieee80211_mcs_to_chains(&sband->ht_cap.mcs),
|
||||
local->rx_chains);
|
||||
if (!sband->ht_cap.ht_supported)
|
||||
continue;
|
||||
|
||||
/* TODO: consider VHT for RX chains, hopefully it's the same */
|
||||
local->rx_chains =
|
||||
max(ieee80211_mcs_to_chains(&sband->ht_cap.mcs),
|
||||
local->rx_chains);
|
||||
|
||||
/* no need to mask, SM_PS_DISABLED has all bits set */
|
||||
sband->ht_cap.cap |= WLAN_HT_CAP_SM_PS_DISABLED <<
|
||||
IEEE80211_HT_CAP_SM_PS_SHIFT;
|
||||
}
|
||||
|
||||
/* if low-level driver supports AP, we also support VLAN */
|
||||
|
@ -40,6 +40,8 @@ void rate_control_rate_init(struct sta_info *sta)
|
||||
|
||||
ieee80211_sta_set_rx_nss(sta);
|
||||
|
||||
ieee80211_recalc_min_chandef(sta->sdata);
|
||||
|
||||
if (!ref)
|
||||
return;
|
||||
|
||||
|
@ -2472,7 +2472,8 @@ ieee80211_rx_h_mesh_fwding(struct ieee80211_rx_data *rx)
|
||||
if (!ifmsh->mshcfg.dot11MeshForwarding)
|
||||
goto out;
|
||||
|
||||
fwd_skb = skb_copy_expand(skb, local->tx_headroom, 0, GFP_ATOMIC);
|
||||
fwd_skb = skb_copy_expand(skb, local->tx_headroom +
|
||||
sdata->encrypt_headroom, 0, GFP_ATOMIC);
|
||||
if (!fwd_skb) {
|
||||
net_info_ratelimited("%s: failed to clone mesh frame\n",
|
||||
sdata->name);
|
||||
@ -2880,17 +2881,10 @@ ieee80211_rx_h_action(struct ieee80211_rx_data *rx)
|
||||
|
||||
switch (mgmt->u.action.u.vht_opmode_notif.action_code) {
|
||||
case WLAN_VHT_ACTION_OPMODE_NOTIF: {
|
||||
u8 opmode;
|
||||
|
||||
/* verify opmode is present */
|
||||
if (len < IEEE80211_MIN_ACTION_SIZE + 2)
|
||||
goto invalid;
|
||||
|
||||
opmode = mgmt->u.action.u.vht_opmode_notif.operating_mode;
|
||||
|
||||
ieee80211_vht_handle_opmode(rx->sdata, rx->sta,
|
||||
opmode, status->band);
|
||||
goto handled;
|
||||
goto queue;
|
||||
}
|
||||
case WLAN_VHT_ACTION_GROUPID_MGMT: {
|
||||
if (len < IEEE80211_MIN_ACTION_SIZE + 25)
|
||||
@ -3942,21 +3936,31 @@ static bool ieee80211_invoke_fast_rx(struct ieee80211_rx_data *rx,
|
||||
u64_stats_update_end(&stats->syncp);
|
||||
|
||||
if (fast_rx->internal_forward) {
|
||||
struct sta_info *dsta = sta_info_get(rx->sdata, skb->data);
|
||||
struct sk_buff *xmit_skb = NULL;
|
||||
bool multicast = is_multicast_ether_addr(skb->data);
|
||||
|
||||
if (dsta) {
|
||||
if (multicast) {
|
||||
xmit_skb = skb_copy(skb, GFP_ATOMIC);
|
||||
} else if (sta_info_get(rx->sdata, skb->data)) {
|
||||
xmit_skb = skb;
|
||||
skb = NULL;
|
||||
}
|
||||
|
||||
if (xmit_skb) {
|
||||
/*
|
||||
* Send to wireless media and increase priority by 256
|
||||
* to keep the received priority instead of
|
||||
* reclassifying the frame (see cfg80211_classify8021d).
|
||||
*/
|
||||
skb->priority += 256;
|
||||
skb->protocol = htons(ETH_P_802_3);
|
||||
skb_reset_network_header(skb);
|
||||
skb_reset_mac_header(skb);
|
||||
dev_queue_xmit(skb);
|
||||
return true;
|
||||
xmit_skb->priority += 256;
|
||||
xmit_skb->protocol = htons(ETH_P_802_3);
|
||||
skb_reset_network_header(xmit_skb);
|
||||
skb_reset_mac_header(xmit_skb);
|
||||
dev_queue_xmit(xmit_skb);
|
||||
}
|
||||
|
||||
if (!skb)
|
||||
return true;
|
||||
}
|
||||
|
||||
/* deliver to local stack */
|
||||
|
@ -1501,8 +1501,8 @@ ieee80211_sta_ps_deliver_response(struct sta_info *sta,
|
||||
|
||||
/* This will evaluate to 1, 3, 5 or 7. */
|
||||
for (ac = IEEE80211_AC_VO; ac < IEEE80211_NUM_ACS; ac++)
|
||||
if (ignored_acs & BIT(ac))
|
||||
continue;
|
||||
if (!(ignored_acs & ieee80211_ac_to_qos_mask[ac]))
|
||||
break;
|
||||
tid = 7 - 2 * ac;
|
||||
|
||||
ieee80211_send_null_response(sta, tid, reason, true, false);
|
||||
|
@ -1243,7 +1243,7 @@ ieee80211_tx_prepare(struct ieee80211_sub_if_data *sdata,
|
||||
|
||||
static struct txq_info *ieee80211_get_txq(struct ieee80211_local *local,
|
||||
struct ieee80211_vif *vif,
|
||||
struct ieee80211_sta *pubsta,
|
||||
struct sta_info *sta,
|
||||
struct sk_buff *skb)
|
||||
{
|
||||
struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
|
||||
@ -1257,10 +1257,13 @@ static struct txq_info *ieee80211_get_txq(struct ieee80211_local *local,
|
||||
if (!ieee80211_is_data(hdr->frame_control))
|
||||
return NULL;
|
||||
|
||||
if (pubsta) {
|
||||
if (sta) {
|
||||
u8 tid = skb->priority & IEEE80211_QOS_CTL_TID_MASK;
|
||||
|
||||
txq = pubsta->txq[tid];
|
||||
if (!sta->uploaded)
|
||||
return NULL;
|
||||
|
||||
txq = sta->sta.txq[tid];
|
||||
} else if (vif) {
|
||||
txq = vif->txq;
|
||||
}
|
||||
@ -1503,23 +1506,17 @@ static bool ieee80211_queue_skb(struct ieee80211_local *local,
|
||||
struct fq *fq = &local->fq;
|
||||
struct ieee80211_vif *vif;
|
||||
struct txq_info *txqi;
|
||||
struct ieee80211_sta *pubsta;
|
||||
|
||||
if (!local->ops->wake_tx_queue ||
|
||||
sdata->vif.type == NL80211_IFTYPE_MONITOR)
|
||||
return false;
|
||||
|
||||
if (sta && sta->uploaded)
|
||||
pubsta = &sta->sta;
|
||||
else
|
||||
pubsta = NULL;
|
||||
|
||||
if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN)
|
||||
sdata = container_of(sdata->bss,
|
||||
struct ieee80211_sub_if_data, u.ap);
|
||||
|
||||
vif = &sdata->vif;
|
||||
txqi = ieee80211_get_txq(local, vif, pubsta, skb);
|
||||
txqi = ieee80211_get_txq(local, vif, sta, skb);
|
||||
|
||||
if (!txqi)
|
||||
return false;
|
||||
|
@ -527,8 +527,10 @@ void ieee80211_vht_handle_opmode(struct ieee80211_sub_if_data *sdata,
|
||||
|
||||
u32 changed = __ieee80211_vht_handle_opmode(sdata, sta, opmode, band);
|
||||
|
||||
if (changed > 0)
|
||||
if (changed > 0) {
|
||||
ieee80211_recalc_min_chandef(sdata);
|
||||
rate_control_rate_update(local, sband, sta, changed);
|
||||
}
|
||||
}
|
||||
|
||||
void ieee80211_get_vht_mask_from_cap(__le16 vht_cap,
|
||||
|
@ -4615,6 +4615,15 @@ int cfg80211_check_station_change(struct wiphy *wiphy,
|
||||
break;
|
||||
}
|
||||
|
||||
/*
|
||||
* Older kernel versions ignored this attribute entirely, so don't
|
||||
* reject attempts to update it but mark it as unused instead so the
|
||||
* driver won't look at the data.
|
||||
*/
|
||||
if (statype != CFG80211_STA_AP_CLIENT_UNASSOC &&
|
||||
statype != CFG80211_STA_TDLS_PEER_SETUP)
|
||||
params->opmode_notif_used = false;
|
||||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(cfg80211_check_station_change);
|
||||
@ -4854,6 +4863,12 @@ static int nl80211_set_station(struct sk_buff *skb, struct genl_info *info)
|
||||
params.local_pm = pm;
|
||||
}
|
||||
|
||||
if (info->attrs[NL80211_ATTR_OPMODE_NOTIF]) {
|
||||
params.opmode_notif_used = true;
|
||||
params.opmode_notif =
|
||||
nla_get_u8(info->attrs[NL80211_ATTR_OPMODE_NOTIF]);
|
||||
}
|
||||
|
||||
/* Include parameters for TDLS peer (will check later) */
|
||||
err = nl80211_set_station_tdls(info, ¶ms);
|
||||
if (err)
|
||||
|
Loading…
Reference in New Issue
Block a user