Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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>

+83 -38
+3 -1
include/uapi/linux/nl80211.h
··· 1772 1772 * 1773 1773 * @NL80211_ATTR_OPMODE_NOTIF: Operating mode field from Operating Mode 1774 1774 * Notification Element based on association request when used with 1775 - * %NL80211_CMD_NEW_STATION; u8 attribute. 1775 + * %NL80211_CMD_NEW_STATION or %NL80211_CMD_SET_STATION (only when 1776 + * %NL80211_FEATURE_FULL_AP_CLIENT_STATE is supported, or with TDLS); 1777 + * u8 attribute. 1776 1778 * 1777 1779 * @NL80211_ATTR_VENDOR_ID: The vendor ID, either a 24-bit OUI or, if 1778 1780 * %NL80211_VENDOR_ID_IS_LINUX is set, a special Linux ID (not used yet)
-3
net/mac80211/chan.c
··· 231 231 !(sta->sdata->bss && sta->sdata->bss == sdata->bss)) 232 232 continue; 233 233 234 - if (!sta->uploaded || !test_sta_flag(sta, WLAN_STA_ASSOC)) 235 - continue; 236 - 237 234 max_bw = max(max_bw, ieee80211_get_sta_bw(&sta->sta)); 238 235 } 239 236 rcu_read_unlock();
+21
net/mac80211/iface.c
··· 6 6 * Copyright (c) 2006 Jiri Benc <jbenc@suse.cz> 7 7 * Copyright 2008, Johannes Berg <johannes@sipsolutions.net> 8 8 * Copyright 2013-2014 Intel Mobile Communications GmbH 9 + * Copyright (c) 2016 Intel Deutschland GmbH 9 10 * 10 11 * This program is free software; you can redistribute it and/or modify 11 12 * it under the terms of the GNU General Public License version 2 as ··· 1296 1295 } else if (ieee80211_is_action(mgmt->frame_control) && 1297 1296 mgmt->u.action.category == WLAN_CATEGORY_VHT) { 1298 1297 switch (mgmt->u.action.u.vht_group_notif.action_code) { 1298 + case WLAN_VHT_ACTION_OPMODE_NOTIF: { 1299 + struct ieee80211_rx_status *status; 1300 + enum nl80211_band band; 1301 + u8 opmode; 1302 + 1303 + status = IEEE80211_SKB_RXCB(skb); 1304 + band = status->band; 1305 + opmode = mgmt->u.action.u.vht_opmode_notif.operating_mode; 1306 + 1307 + mutex_lock(&local->sta_mtx); 1308 + sta = sta_info_get_bss(sdata, mgmt->sa); 1309 + 1310 + if (sta) 1311 + ieee80211_vht_handle_opmode(sdata, sta, 1312 + opmode, 1313 + band); 1314 + 1315 + mutex_unlock(&local->sta_mtx); 1316 + break; 1317 + } 1299 1318 case WLAN_VHT_ACTION_GROUPID_MGMT: 1300 1319 ieee80211_process_mu_groups(sdata, mgmt); 1301 1320 break;
+9 -4
net/mac80211/main.c
··· 913 913 supp_ht = supp_ht || sband->ht_cap.ht_supported; 914 914 supp_vht = supp_vht || sband->vht_cap.vht_supported; 915 915 916 - if (sband->ht_cap.ht_supported) 917 - local->rx_chains = 918 - max(ieee80211_mcs_to_chains(&sband->ht_cap.mcs), 919 - local->rx_chains); 916 + if (!sband->ht_cap.ht_supported) 917 + continue; 920 918 921 919 /* TODO: consider VHT for RX chains, hopefully it's the same */ 920 + local->rx_chains = 921 + max(ieee80211_mcs_to_chains(&sband->ht_cap.mcs), 922 + local->rx_chains); 923 + 924 + /* no need to mask, SM_PS_DISABLED has all bits set */ 925 + sband->ht_cap.cap |= WLAN_HT_CAP_SM_PS_DISABLED << 926 + IEEE80211_HT_CAP_SM_PS_SHIFT; 922 927 } 923 928 924 929 /* if low-level driver supports AP, we also support VLAN */
+2
net/mac80211/rate.c
··· 40 40 41 41 ieee80211_sta_set_rx_nss(sta); 42 42 43 + ieee80211_recalc_min_chandef(sta->sdata); 44 + 43 45 if (!ref) 44 46 return; 45 47
+21 -17
net/mac80211/rx.c
··· 2472 2472 if (!ifmsh->mshcfg.dot11MeshForwarding) 2473 2473 goto out; 2474 2474 2475 - fwd_skb = skb_copy_expand(skb, local->tx_headroom, 0, GFP_ATOMIC); 2475 + fwd_skb = skb_copy_expand(skb, local->tx_headroom + 2476 + sdata->encrypt_headroom, 0, GFP_ATOMIC); 2476 2477 if (!fwd_skb) { 2477 2478 net_info_ratelimited("%s: failed to clone mesh frame\n", 2478 2479 sdata->name); ··· 2881 2880 2882 2881 switch (mgmt->u.action.u.vht_opmode_notif.action_code) { 2883 2882 case WLAN_VHT_ACTION_OPMODE_NOTIF: { 2884 - u8 opmode; 2885 - 2886 2883 /* verify opmode is present */ 2887 2884 if (len < IEEE80211_MIN_ACTION_SIZE + 2) 2888 2885 goto invalid; 2889 - 2890 - opmode = mgmt->u.action.u.vht_opmode_notif.operating_mode; 2891 - 2892 - ieee80211_vht_handle_opmode(rx->sdata, rx->sta, 2893 - opmode, status->band); 2894 - goto handled; 2886 + goto queue; 2895 2887 } 2896 2888 case WLAN_VHT_ACTION_GROUPID_MGMT: { 2897 2889 if (len < IEEE80211_MIN_ACTION_SIZE + 25) ··· 3936 3942 u64_stats_update_end(&stats->syncp); 3937 3943 3938 3944 if (fast_rx->internal_forward) { 3939 - struct sta_info *dsta = sta_info_get(rx->sdata, skb->data); 3945 + struct sk_buff *xmit_skb = NULL; 3946 + bool multicast = is_multicast_ether_addr(skb->data); 3940 3947 3941 - if (dsta) { 3948 + if (multicast) { 3949 + xmit_skb = skb_copy(skb, GFP_ATOMIC); 3950 + } else if (sta_info_get(rx->sdata, skb->data)) { 3951 + xmit_skb = skb; 3952 + skb = NULL; 3953 + } 3954 + 3955 + if (xmit_skb) { 3942 3956 /* 3943 3957 * Send to wireless media and increase priority by 256 3944 3958 * to keep the received priority instead of 3945 3959 * reclassifying the frame (see cfg80211_classify8021d). 3946 3960 */ 3947 - skb->priority += 256; 3948 - skb->protocol = htons(ETH_P_802_3); 3949 - skb_reset_network_header(skb); 3950 - skb_reset_mac_header(skb); 3951 - dev_queue_xmit(skb); 3952 - return true; 3961 + xmit_skb->priority += 256; 3962 + xmit_skb->protocol = htons(ETH_P_802_3); 3963 + skb_reset_network_header(xmit_skb); 3964 + skb_reset_mac_header(xmit_skb); 3965 + dev_queue_xmit(xmit_skb); 3953 3966 } 3967 + 3968 + if (!skb) 3969 + return true; 3954 3970 } 3955 3971 3956 3972 /* deliver to local stack */
+2 -2
net/mac80211/sta_info.c
··· 1501 1501 1502 1502 /* This will evaluate to 1, 3, 5 or 7. */ 1503 1503 for (ac = IEEE80211_AC_VO; ac < IEEE80211_NUM_ACS; ac++) 1504 - if (ignored_acs & BIT(ac)) 1505 - continue; 1504 + if (!(ignored_acs & ieee80211_ac_to_qos_mask[ac])) 1505 + break; 1506 1506 tid = 7 - 2 * ac; 1507 1507 1508 1508 ieee80211_send_null_response(sta, tid, reason, true, false);
+7 -10
net/mac80211/tx.c
··· 1243 1243 1244 1244 static struct txq_info *ieee80211_get_txq(struct ieee80211_local *local, 1245 1245 struct ieee80211_vif *vif, 1246 - struct ieee80211_sta *pubsta, 1246 + struct sta_info *sta, 1247 1247 struct sk_buff *skb) 1248 1248 { 1249 1249 struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; ··· 1257 1257 if (!ieee80211_is_data(hdr->frame_control)) 1258 1258 return NULL; 1259 1259 1260 - if (pubsta) { 1260 + if (sta) { 1261 1261 u8 tid = skb->priority & IEEE80211_QOS_CTL_TID_MASK; 1262 1262 1263 - txq = pubsta->txq[tid]; 1263 + if (!sta->uploaded) 1264 + return NULL; 1265 + 1266 + txq = sta->sta.txq[tid]; 1264 1267 } else if (vif) { 1265 1268 txq = vif->txq; 1266 1269 } ··· 1506 1503 struct fq *fq = &local->fq; 1507 1504 struct ieee80211_vif *vif; 1508 1505 struct txq_info *txqi; 1509 - struct ieee80211_sta *pubsta; 1510 1506 1511 1507 if (!local->ops->wake_tx_queue || 1512 1508 sdata->vif.type == NL80211_IFTYPE_MONITOR) 1513 1509 return false; 1514 - 1515 - if (sta && sta->uploaded) 1516 - pubsta = &sta->sta; 1517 - else 1518 - pubsta = NULL; 1519 1510 1520 1511 if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN) 1521 1512 sdata = container_of(sdata->bss, 1522 1513 struct ieee80211_sub_if_data, u.ap); 1523 1514 1524 1515 vif = &sdata->vif; 1525 - txqi = ieee80211_get_txq(local, vif, pubsta, skb); 1516 + txqi = ieee80211_get_txq(local, vif, sta, skb); 1526 1517 1527 1518 if (!txqi) 1528 1519 return false;
+3 -1
net/mac80211/vht.c
··· 527 527 528 528 u32 changed = __ieee80211_vht_handle_opmode(sdata, sta, opmode, band); 529 529 530 - if (changed > 0) 530 + if (changed > 0) { 531 + ieee80211_recalc_min_chandef(sdata); 531 532 rate_control_rate_update(local, sband, sta, changed); 533 + } 532 534 } 533 535 534 536 void ieee80211_get_vht_mask_from_cap(__le16 vht_cap,
+15
net/wireless/nl80211.c
··· 4615 4615 break; 4616 4616 } 4617 4617 4618 + /* 4619 + * Older kernel versions ignored this attribute entirely, so don't 4620 + * reject attempts to update it but mark it as unused instead so the 4621 + * driver won't look at the data. 4622 + */ 4623 + if (statype != CFG80211_STA_AP_CLIENT_UNASSOC && 4624 + statype != CFG80211_STA_TDLS_PEER_SETUP) 4625 + params->opmode_notif_used = false; 4626 + 4618 4627 return 0; 4619 4628 } 4620 4629 EXPORT_SYMBOL(cfg80211_check_station_change); ··· 4861 4852 return -EINVAL; 4862 4853 4863 4854 params.local_pm = pm; 4855 + } 4856 + 4857 + if (info->attrs[NL80211_ATTR_OPMODE_NOTIF]) { 4858 + params.opmode_notif_used = true; 4859 + params.opmode_notif = 4860 + nla_get_u8(info->attrs[NL80211_ATTR_OPMODE_NOTIF]); 4864 4861 } 4865 4862 4866 4863 /* Include parameters for TDLS peer (will check later) */