Skip to content

Commit 1a717fc

Browse files
committed
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 <[email protected]>
2 parents 75f01a4 + dbef536 commit 1a717fc

File tree

10 files changed

+83
-38
lines changed

10 files changed

+83
-38
lines changed

include/uapi/linux/nl80211.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1772,7 +1772,9 @@ enum nl80211_commands {
17721772
*
17731773
* @NL80211_ATTR_OPMODE_NOTIF: Operating mode field from Operating Mode
17741774
* 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.
17761778
*
17771779
* @NL80211_ATTR_VENDOR_ID: The vendor ID, either a 24-bit OUI or, if
17781780
* %NL80211_VENDOR_ID_IS_LINUX is set, a special Linux ID (not used yet)

net/mac80211/chan.c

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -231,9 +231,6 @@ ieee80211_get_max_required_bw(struct ieee80211_sub_if_data *sdata)
231231
!(sta->sdata->bss && sta->sdata->bss == sdata->bss))
232232
continue;
233233

234-
if (!sta->uploaded || !test_sta_flag(sta, WLAN_STA_ASSOC))
235-
continue;
236-
237234
max_bw = max(max_bw, ieee80211_get_sta_bw(&sta->sta));
238235
}
239236
rcu_read_unlock();

net/mac80211/iface.c

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
* Copyright (c) 2006 Jiri Benc <[email protected]>
77
* Copyright 2008, Johannes Berg <[email protected]>
88
* Copyright 2013-2014 Intel Mobile Communications GmbH
9+
* Copyright (c) 2016 Intel Deutschland GmbH
910
*
1011
* This program is free software; you can redistribute it and/or modify
1112
* 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)
12951296
} else if (ieee80211_is_action(mgmt->frame_control) &&
12961297
mgmt->u.action.category == WLAN_CATEGORY_VHT) {
12971298
switch (mgmt->u.action.u.vht_group_notif.action_code) {
1299+
case WLAN_VHT_ACTION_OPMODE_NOTIF: {
1300+
struct ieee80211_rx_status *status;
1301+
enum nl80211_band band;
1302+
u8 opmode;
1303+
1304+
status = IEEE80211_SKB_RXCB(skb);
1305+
band = status->band;
1306+
opmode = mgmt->u.action.u.vht_opmode_notif.operating_mode;
1307+
1308+
mutex_lock(&local->sta_mtx);
1309+
sta = sta_info_get_bss(sdata, mgmt->sa);
1310+
1311+
if (sta)
1312+
ieee80211_vht_handle_opmode(sdata, sta,
1313+
opmode,
1314+
band);
1315+
1316+
mutex_unlock(&local->sta_mtx);
1317+
break;
1318+
}
12981319
case WLAN_VHT_ACTION_GROUPID_MGMT:
12991320
ieee80211_process_mu_groups(sdata, mgmt);
13001321
break;

net/mac80211/main.c

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -913,12 +913,17 @@ int ieee80211_register_hw(struct ieee80211_hw *hw)
913913
supp_ht = supp_ht || sband->ht_cap.ht_supported;
914914
supp_vht = supp_vht || sband->vht_cap.vht_supported;
915915

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;
920918

921919
/* 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;
922927
}
923928

924929
/* if low-level driver supports AP, we also support VLAN */

net/mac80211/rate.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,8 @@ void rate_control_rate_init(struct sta_info *sta)
4040

4141
ieee80211_sta_set_rx_nss(sta);
4242

43+
ieee80211_recalc_min_chandef(sta->sdata);
44+
4345
if (!ref)
4446
return;
4547

net/mac80211/rx.c

Lines changed: 21 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -2472,7 +2472,8 @@ ieee80211_rx_h_mesh_fwding(struct ieee80211_rx_data *rx)
24722472
if (!ifmsh->mshcfg.dot11MeshForwarding)
24732473
goto out;
24742474

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);
24762477
if (!fwd_skb) {
24772478
net_info_ratelimited("%s: failed to clone mesh frame\n",
24782479
sdata->name);
@@ -2880,17 +2881,10 @@ ieee80211_rx_h_action(struct ieee80211_rx_data *rx)
28802881

28812882
switch (mgmt->u.action.u.vht_opmode_notif.action_code) {
28822883
case WLAN_VHT_ACTION_OPMODE_NOTIF: {
2883-
u8 opmode;
2884-
28852884
/* verify opmode is present */
28862885
if (len < IEEE80211_MIN_ACTION_SIZE + 2)
28872886
goto invalid;
2888-
2889-
opmode = mgmt->u.action.u.vht_opmode_notif.operating_mode;
2890-
2891-
ieee80211_vht_handle_opmode(rx->sdata, rx->sta,
2892-
opmode, status->band);
2893-
goto handled;
2887+
goto queue;
28942888
}
28952889
case WLAN_VHT_ACTION_GROUPID_MGMT: {
28962890
if (len < IEEE80211_MIN_ACTION_SIZE + 25)
@@ -3942,21 +3936,31 @@ static bool ieee80211_invoke_fast_rx(struct ieee80211_rx_data *rx,
39423936
u64_stats_update_end(&stats->syncp);
39433937

39443938
if (fast_rx->internal_forward) {
3945-
struct sta_info *dsta = sta_info_get(rx->sdata, skb->data);
3939+
struct sk_buff *xmit_skb = NULL;
3940+
bool multicast = is_multicast_ether_addr(skb->data);
3941+
3942+
if (multicast) {
3943+
xmit_skb = skb_copy(skb, GFP_ATOMIC);
3944+
} else if (sta_info_get(rx->sdata, skb->data)) {
3945+
xmit_skb = skb;
3946+
skb = NULL;
3947+
}
39463948

3947-
if (dsta) {
3949+
if (xmit_skb) {
39483950
/*
39493951
* Send to wireless media and increase priority by 256
39503952
* to keep the received priority instead of
39513953
* reclassifying the frame (see cfg80211_classify8021d).
39523954
*/
3953-
skb->priority += 256;
3954-
skb->protocol = htons(ETH_P_802_3);
3955-
skb_reset_network_header(skb);
3956-
skb_reset_mac_header(skb);
3957-
dev_queue_xmit(skb);
3958-
return true;
3955+
xmit_skb->priority += 256;
3956+
xmit_skb->protocol = htons(ETH_P_802_3);
3957+
skb_reset_network_header(xmit_skb);
3958+
skb_reset_mac_header(xmit_skb);
3959+
dev_queue_xmit(xmit_skb);
39593960
}
3961+
3962+
if (!skb)
3963+
return true;
39603964
}
39613965

39623966
/* deliver to local stack */

net/mac80211/sta_info.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1501,8 +1501,8 @@ ieee80211_sta_ps_deliver_response(struct sta_info *sta,
15011501

15021502
/* This will evaluate to 1, 3, 5 or 7. */
15031503
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;
15061506
tid = 7 - 2 * ac;
15071507

15081508
ieee80211_send_null_response(sta, tid, reason, true, false);

net/mac80211/tx.c

Lines changed: 7 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1243,7 +1243,7 @@ ieee80211_tx_prepare(struct ieee80211_sub_if_data *sdata,
12431243

12441244
static struct txq_info *ieee80211_get_txq(struct ieee80211_local *local,
12451245
struct ieee80211_vif *vif,
1246-
struct ieee80211_sta *pubsta,
1246+
struct sta_info *sta,
12471247
struct sk_buff *skb)
12481248
{
12491249
struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
@@ -1257,10 +1257,13 @@ static struct txq_info *ieee80211_get_txq(struct ieee80211_local *local,
12571257
if (!ieee80211_is_data(hdr->frame_control))
12581258
return NULL;
12591259

1260-
if (pubsta) {
1260+
if (sta) {
12611261
u8 tid = skb->priority & IEEE80211_QOS_CTL_TID_MASK;
12621262

1263-
txq = pubsta->txq[tid];
1263+
if (!sta->uploaded)
1264+
return NULL;
1265+
1266+
txq = sta->sta.txq[tid];
12641267
} else if (vif) {
12651268
txq = vif->txq;
12661269
}
@@ -1503,23 +1506,17 @@ static bool ieee80211_queue_skb(struct ieee80211_local *local,
15031506
struct fq *fq = &local->fq;
15041507
struct ieee80211_vif *vif;
15051508
struct txq_info *txqi;
1506-
struct ieee80211_sta *pubsta;
15071509

15081510
if (!local->ops->wake_tx_queue ||
15091511
sdata->vif.type == NL80211_IFTYPE_MONITOR)
15101512
return false;
15111513

1512-
if (sta && sta->uploaded)
1513-
pubsta = &sta->sta;
1514-
else
1515-
pubsta = NULL;
1516-
15171514
if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN)
15181515
sdata = container_of(sdata->bss,
15191516
struct ieee80211_sub_if_data, u.ap);
15201517

15211518
vif = &sdata->vif;
1522-
txqi = ieee80211_get_txq(local, vif, pubsta, skb);
1519+
txqi = ieee80211_get_txq(local, vif, sta, skb);
15231520

15241521
if (!txqi)
15251522
return false;

net/mac80211/vht.c

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -527,8 +527,10 @@ void ieee80211_vht_handle_opmode(struct ieee80211_sub_if_data *sdata,
527527

528528
u32 changed = __ieee80211_vht_handle_opmode(sdata, sta, opmode, band);
529529

530-
if (changed > 0)
530+
if (changed > 0) {
531+
ieee80211_recalc_min_chandef(sdata);
531532
rate_control_rate_update(local, sband, sta, changed);
533+
}
532534
}
533535

534536
void ieee80211_get_vht_mask_from_cap(__le16 vht_cap,

net/wireless/nl80211.c

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4615,6 +4615,15 @@ int cfg80211_check_station_change(struct wiphy *wiphy,
46154615
break;
46164616
}
46174617

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+
46184627
return 0;
46194628
}
46204629
EXPORT_SYMBOL(cfg80211_check_station_change);
@@ -4854,6 +4863,12 @@ static int nl80211_set_station(struct sk_buff *skb, struct genl_info *info)
48544863
params.local_pm = pm;
48554864
}
48564865

4866+
if (info->attrs[NL80211_ATTR_OPMODE_NOTIF]) {
4867+
params.opmode_notif_used = true;
4868+
params.opmode_notif =
4869+
nla_get_u8(info->attrs[NL80211_ATTR_OPMODE_NOTIF]);
4870+
}
4871+
48574872
/* Include parameters for TDLS peer (will check later) */
48584873
err = nl80211_set_station_tdls(info, &params);
48594874
if (err)

0 commit comments

Comments
 (0)