summaryrefslogtreecommitdiff
path: root/net/mac80211
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2017-07-05 12:31:59 -0700
committerLinus Torvalds <torvalds@linux-foundation.org>2017-07-05 12:31:59 -0700
commit5518b69b76680a4f2df96b1deca260059db0c2de (patch)
treef33cd1519c8efb4590500f2f9617400be233238c /net/mac80211
parent8ad06e56dcbc1984ef0ff8f6e3c19982c5809f73 (diff)
parent0e72582270c07850b92cac351c8b97d4f9c123b9 (diff)
Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net-next
Pull networking updates from David Miller: "Reasonably busy this cycle, but perhaps not as busy as in the 4.12 merge window: 1) Several optimizations for UDP processing under high load from Paolo Abeni. 2) Support pacing internally in TCP when using the sch_fq packet scheduler for this is not practical. From Eric Dumazet. 3) Support mutliple filter chains per qdisc, from Jiri Pirko. 4) Move to 1ms TCP timestamp clock, from Eric Dumazet. 5) Add batch dequeueing to vhost_net, from Jason Wang. 6) Flesh out more completely SCTP checksum offload support, from Davide Caratti. 7) More plumbing of extended netlink ACKs, from David Ahern, Pablo Neira Ayuso, and Matthias Schiffer. 8) Add devlink support to nfp driver, from Simon Horman. 9) Add RTM_F_FIB_MATCH flag to RTM_GETROUTE queries, from Roopa Prabhu. 10) Add stack depth tracking to BPF verifier and use this information in the various eBPF JITs. From Alexei Starovoitov. 11) Support XDP on qed device VFs, from Yuval Mintz. 12) Introduce BPF PROG ID for better introspection of installed BPF programs. From Martin KaFai Lau. 13) Add bpf_set_hash helper for TC bpf programs, from Daniel Borkmann. 14) For loads, allow narrower accesses in bpf verifier checking, from Yonghong Song. 15) Support MIPS in the BPF selftests and samples infrastructure, the MIPS eBPF JIT will be merged in via the MIPS GIT tree. From David Daney. 16) Support kernel based TLS, from Dave Watson and others. 17) Remove completely DST garbage collection, from Wei Wang. 18) Allow installing TCP MD5 rules using prefixes, from Ivan Delalande. 19) Add XDP support to Intel i40e driver, from Björn Töpel 20) Add support for TC flower offload in nfp driver, from Simon Horman, Pieter Jansen van Vuuren, Benjamin LaHaise, Jakub Kicinski, and Bert van Leeuwen. 21) IPSEC offloading support in mlx5, from Ilan Tayari. 22) Add HW PTP support to macb driver, from Rafal Ozieblo. 23) Networking refcount_t conversions, From Elena Reshetova. 24) Add sock_ops support to BPF, from Lawrence Brako. This is useful for tuning the TCP sockopt settings of a group of applications, currently via CGROUPs" * git://git.kernel.org/pub/scm/linux/kernel/git/davem/net-next: (1899 commits) net: phy: dp83867: add workaround for incorrect RX_CTRL pin strap dt-bindings: phy: dp83867: provide a workaround for incorrect RX_CTRL pin strap cxgb4: Support for get_ts_info ethtool method cxgb4: Add PTP Hardware Clock (PHC) support cxgb4: time stamping interface for PTP nfp: default to chained metadata prepend format nfp: remove legacy MAC address lookup nfp: improve order of interfaces in breakout mode net: macb: remove extraneous return when MACB_EXT_DESC is defined bpf: add missing break in for the TCP_BPF_SNDCWND_CLAMP case bpf: fix return in load_bpf_file mpls: fix rtm policy in mpls_getroute net, ax25: convert ax25_cb.refcount from atomic_t to refcount_t net, ax25: convert ax25_route.refcount from atomic_t to refcount_t net, ax25: convert ax25_uid_assoc.refcount from atomic_t to refcount_t net, sctp: convert sctp_ep_common.refcnt from atomic_t to refcount_t net, sctp: convert sctp_transport.refcnt from atomic_t to refcount_t net, sctp: convert sctp_chunk.refcnt from atomic_t to refcount_t net, sctp: convert sctp_datamsg.refcnt from atomic_t to refcount_t net, sctp: convert sctp_auth_bytes.refcnt from atomic_t to refcount_t ...
Diffstat (limited to 'net/mac80211')
-rw-r--r--net/mac80211/agg-rx.c50
-rw-r--r--net/mac80211/agg-tx.c6
-rw-r--r--net/mac80211/cfg.c5
-rw-r--r--net/mac80211/debugfs_netdev.c5
-rw-r--r--net/mac80211/debugfs_sta.c6
-rw-r--r--net/mac80211/ht.c17
-rw-r--r--net/mac80211/ibss.c3
-rw-r--r--net/mac80211/ieee80211_i.h16
-rw-r--r--net/mac80211/iface.c25
-rw-r--r--net/mac80211/mesh.c98
-rw-r--r--net/mac80211/mesh_hwmp.c6
-rw-r--r--net/mac80211/mesh_plink.c6
-rw-r--r--net/mac80211/mesh_ps.c4
-rw-r--r--net/mac80211/mlme.c19
-rw-r--r--net/mac80211/offchannel.c3
-rw-r--r--net/mac80211/rate.c3
-rw-r--r--net/mac80211/rx.c11
-rw-r--r--net/mac80211/spectmgmt.c10
-rw-r--r--net/mac80211/sta_info.c32
-rw-r--r--net/mac80211/sta_info.h14
-rw-r--r--net/mac80211/status.c6
-rw-r--r--net/mac80211/tdls.c49
-rw-r--r--net/mac80211/trace.h11
-rw-r--r--net/mac80211/tx.c49
-rw-r--r--net/mac80211/util.c48
-rw-r--r--net/mac80211/wpa.c6
26 files changed, 298 insertions, 210 deletions
diff --git a/net/mac80211/agg-rx.c b/net/mac80211/agg-rx.c
index 1b7a4daf283c..8708cbe8af5b 100644
--- a/net/mac80211/agg-rx.c
+++ b/net/mac80211/agg-rx.c
@@ -213,8 +213,7 @@ static void ieee80211_send_addba_resp(struct ieee80211_sub_if_data *sdata, u8 *d
return;
skb_reserve(skb, local->hw.extra_tx_headroom);
- mgmt = (struct ieee80211_mgmt *) skb_put(skb, 24);
- memset(mgmt, 0, 24);
+ mgmt = skb_put_zero(skb, 24);
memcpy(mgmt->da, da, ETH_ALEN);
memcpy(mgmt->sa, sdata->vif.addr, ETH_ALEN);
if (sdata->vif.type == NL80211_IFTYPE_AP ||
@@ -449,44 +448,21 @@ void ieee80211_process_addba_request(struct ieee80211_local *local,
buf_size, true, false);
}
-void ieee80211_start_rx_ba_session_offl(struct ieee80211_vif *vif,
- const u8 *addr, u16 tid)
+void ieee80211_manage_rx_ba_offl(struct ieee80211_vif *vif,
+ const u8 *addr, unsigned int bit)
{
struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif);
struct ieee80211_local *local = sdata->local;
- struct ieee80211_rx_agg *rx_agg;
- struct sk_buff *skb = dev_alloc_skb(0);
-
- if (unlikely(!skb))
- return;
-
- rx_agg = (struct ieee80211_rx_agg *) &skb->cb;
- memcpy(&rx_agg->addr, addr, ETH_ALEN);
- rx_agg->tid = tid;
-
- skb->pkt_type = IEEE80211_SDATA_QUEUE_RX_AGG_START;
- skb_queue_tail(&sdata->skb_queue, skb);
- ieee80211_queue_work(&local->hw, &sdata->work);
-}
-EXPORT_SYMBOL(ieee80211_start_rx_ba_session_offl);
-
-void ieee80211_stop_rx_ba_session_offl(struct ieee80211_vif *vif,
- const u8 *addr, u16 tid)
-{
- struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif);
- struct ieee80211_local *local = sdata->local;
- struct ieee80211_rx_agg *rx_agg;
- struct sk_buff *skb = dev_alloc_skb(0);
-
- if (unlikely(!skb))
- return;
+ struct sta_info *sta;
- rx_agg = (struct ieee80211_rx_agg *) &skb->cb;
- memcpy(&rx_agg->addr, addr, ETH_ALEN);
- rx_agg->tid = tid;
+ rcu_read_lock();
+ sta = sta_info_get_bss(sdata, addr);
+ if (!sta)
+ goto unlock;
- skb->pkt_type = IEEE80211_SDATA_QUEUE_RX_AGG_STOP;
- skb_queue_tail(&sdata->skb_queue, skb);
- ieee80211_queue_work(&local->hw, &sdata->work);
+ set_bit(bit, sta->ampdu_mlme.tid_rx_manage_offl);
+ ieee80211_queue_work(&local->hw, &sta->ampdu_mlme.work);
+ unlock:
+ rcu_read_unlock();
}
-EXPORT_SYMBOL(ieee80211_stop_rx_ba_session_offl);
+EXPORT_SYMBOL(ieee80211_manage_rx_ba_offl);
diff --git a/net/mac80211/agg-tx.c b/net/mac80211/agg-tx.c
index cf2392b2ac71..cbd48762256c 100644
--- a/net/mac80211/agg-tx.c
+++ b/net/mac80211/agg-tx.c
@@ -76,8 +76,7 @@ static void ieee80211_send_addba_request(struct ieee80211_sub_if_data *sdata,
return;
skb_reserve(skb, local->hw.extra_tx_headroom);
- mgmt = (struct ieee80211_mgmt *) skb_put(skb, 24);
- memset(mgmt, 0, 24);
+ mgmt = skb_put_zero(skb, 24);
memcpy(mgmt->da, da, ETH_ALEN);
memcpy(mgmt->sa, sdata->vif.addr, ETH_ALEN);
if (sdata->vif.type == NL80211_IFTYPE_AP ||
@@ -125,8 +124,7 @@ void ieee80211_send_bar(struct ieee80211_vif *vif, u8 *ra, u16 tid, u16 ssn)
return;
skb_reserve(skb, local->hw.extra_tx_headroom);
- bar = (struct ieee80211_bar *)skb_put(skb, sizeof(*bar));
- memset(bar, 0, sizeof(*bar));
+ bar = skb_put_zero(skb, sizeof(*bar));
bar->frame_control = cpu_to_le16(IEEE80211_FTYPE_CTL |
IEEE80211_STYPE_BACK_REQ);
memcpy(bar->ra, ra, ETH_ALEN);
diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c
index 4a388fe8c2d1..a354f1939e49 100644
--- a/net/mac80211/cfg.c
+++ b/net/mac80211/cfg.c
@@ -1107,7 +1107,7 @@ static void ieee80211_send_layer2_update(struct sta_info *sta)
skb = dev_alloc_skb(sizeof(*msg));
if (!skb)
return;
- msg = (struct iapp_layer2_update *)skb_put(skb, sizeof(*msg));
+ msg = skb_put(skb, sizeof(*msg));
/* 802.2 Type 1 Logical Link Control (LLC) Exchange Identifier (XID)
* Update response frame; IEEE Std 802.2-1998, 5.4.1.2.1 */
@@ -1876,6 +1876,7 @@ static int copy_mesh_setup(struct ieee80211_if_mesh *ifmsh,
ifmsh->user_mpm = setup->user_mpm;
ifmsh->mesh_auth_id = setup->auth_id;
ifmsh->security = IEEE80211_MESH_SEC_NONE;
+ ifmsh->userspace_handles_dfs = setup->userspace_handles_dfs;
if (setup->is_authenticated)
ifmsh->security |= IEEE80211_MESH_SEC_AUTHED;
if (setup->is_secure)
@@ -3413,7 +3414,7 @@ static int ieee80211_probe_client(struct wiphy *wiphy, struct net_device *dev,
skb_reserve(skb, local->hw.extra_tx_headroom);
- nullfunc = (void *) skb_put(skb, size);
+ nullfunc = skb_put(skb, size);
nullfunc->frame_control = fc;
nullfunc->duration_id = 0;
memcpy(nullfunc->addr1, sta->sta.addr, ETH_ALEN);
diff --git a/net/mac80211/debugfs_netdev.c b/net/mac80211/debugfs_netdev.c
index 8f5fff8b2040..c813207bb123 100644
--- a/net/mac80211/debugfs_netdev.c
+++ b/net/mac80211/debugfs_netdev.c
@@ -330,8 +330,7 @@ static ssize_t ieee80211_if_parse_tkip_mic_test(
return -ENOMEM;
skb_reserve(skb, local->hw.extra_tx_headroom);
- hdr = (struct ieee80211_hdr *) skb_put(skb, 24);
- memset(hdr, 0, 24);
+ hdr = skb_put_zero(skb, 24);
fc = cpu_to_le16(IEEE80211_FTYPE_DATA | IEEE80211_STYPE_DATA);
switch (sdata->vif.type) {
@@ -367,7 +366,7 @@ static ssize_t ieee80211_if_parse_tkip_mic_test(
* The exact contents does not matter since the recipient is required
* to drop this because of the Michael MIC failure.
*/
- memset(skb_put(skb, 50), 0, 50);
+ skb_put_zero(skb, 50);
IEEE80211_SKB_CB(skb)->flags |= IEEE80211_TX_INTFL_TKIP_MIC_FAILURE;
diff --git a/net/mac80211/debugfs_sta.c b/net/mac80211/debugfs_sta.c
index 42601820db20..b15412c21ac9 100644
--- a/net/mac80211/debugfs_sta.c
+++ b/net/mac80211/debugfs_sta.c
@@ -154,6 +154,12 @@ static ssize_t sta_aqm_read(struct file *file, char __user *userbuf,
p += scnprintf(p,
bufsz+buf-p,
+ "target %uus interval %uus ecn %s\n",
+ codel_time_to_us(sta->cparams.target),
+ codel_time_to_us(sta->cparams.interval),
+ sta->cparams.ecn ? "yes" : "no");
+ p += scnprintf(p,
+ bufsz+buf-p,
"tid ac backlog-bytes backlog-packets new-flows drops marks overlimit collisions tx-bytes tx-packets\n");
for (i = 0; i < IEEE80211_NUM_TIDS; i++) {
diff --git a/net/mac80211/ht.c b/net/mac80211/ht.c
index 6ca5442b1e03..c92df492e898 100644
--- a/net/mac80211/ht.c
+++ b/net/mac80211/ht.c
@@ -331,6 +331,18 @@ void ieee80211_ba_session_work(struct work_struct *work)
sta, tid, WLAN_BACK_RECIPIENT,
WLAN_REASON_UNSPECIFIED, true);
+ if (test_and_clear_bit(tid,
+ sta->ampdu_mlme.tid_rx_manage_offl))
+ __ieee80211_start_rx_ba_session(sta, 0, 0, 0, 1, tid,
+ IEEE80211_MAX_AMPDU_BUF,
+ false, true);
+
+ if (test_and_clear_bit(tid + IEEE80211_NUM_TIDS,
+ sta->ampdu_mlme.tid_rx_manage_offl))
+ ___ieee80211_stop_rx_ba_session(
+ sta, tid, WLAN_BACK_RECIPIENT,
+ 0, false);
+
spin_lock_bh(&sta->lock);
tid_tx = sta->ampdu_mlme.tid_start_tx[tid];
@@ -382,8 +394,7 @@ void ieee80211_send_delba(struct ieee80211_sub_if_data *sdata,
return;
skb_reserve(skb, local->hw.extra_tx_headroom);
- mgmt = (struct ieee80211_mgmt *) skb_put(skb, 24);
- memset(mgmt, 0, 24);
+ mgmt = skb_put_zero(skb, 24);
memcpy(mgmt->da, da, ETH_ALEN);
memcpy(mgmt->sa, sdata->vif.addr, ETH_ALEN);
if (sdata->vif.type == NL80211_IFTYPE_AP ||
@@ -448,7 +459,7 @@ int ieee80211_send_smps_action(struct ieee80211_sub_if_data *sdata,
return -ENOMEM;
skb_reserve(skb, local->hw.extra_tx_headroom);
- action_frame = (void *)skb_put(skb, 27);
+ action_frame = skb_put(skb, 27);
memcpy(action_frame->da, da, ETH_ALEN);
memcpy(action_frame->sa, sdata->dev->dev_addr, ETH_ALEN);
memcpy(action_frame->bssid, bssid, ETH_ALEN);
diff --git a/net/mac80211/ibss.c b/net/mac80211/ibss.c
index 364d4e137649..e9c6aa3ed05b 100644
--- a/net/mac80211/ibss.c
+++ b/net/mac80211/ibss.c
@@ -808,7 +808,6 @@ ieee80211_ibss_process_chanswitch(struct ieee80211_sub_if_data *sdata,
}
memset(&params, 0, sizeof(params));
- memset(&csa_ie, 0, sizeof(csa_ie));
err = ieee80211_parse_ch_switch_ie(sdata, elems,
ifibss->chandef.chan->band,
sta_flags, ifibss->bssid, &csa_ie);
@@ -1570,7 +1569,7 @@ static void ieee80211_rx_mgmt_probe_req(struct ieee80211_sub_if_data *sdata,
return;
skb_reserve(skb, local->tx_headroom);
- memcpy(skb_put(skb, presp->head_len), presp->head, presp->head_len);
+ skb_put_data(skb, presp->head, presp->head_len);
memcpy(((struct ieee80211_mgmt *) skb->data)->da, mgmt->sa, ETH_ALEN);
ibss_dbg(sdata, "Sending ProbeResp to %pM\n", mgmt->sa);
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h
index 5e002f62c235..2197c62a0a6e 100644
--- a/net/mac80211/ieee80211_i.h
+++ b/net/mac80211/ieee80211_i.h
@@ -643,6 +643,8 @@ struct ieee80211_if_mesh {
unsigned long wrkq_flags;
unsigned long mbss_changed;
+ bool userspace_handles_dfs;
+
u8 mesh_id[IEEE80211_MAX_MESH_ID_LEN];
size_t mesh_id_len;
/* Active Path Selection Protocol Identifier */
@@ -1029,17 +1031,6 @@ ieee80211_vif_get_shift(struct ieee80211_vif *vif)
return shift;
}
-struct ieee80211_rx_agg {
- u8 addr[ETH_ALEN];
- u16 tid;
-};
-
-enum sdata_queue_type {
- IEEE80211_SDATA_QUEUE_TYPE_FRAME = 0,
- IEEE80211_SDATA_QUEUE_RX_AGG_START = 3,
- IEEE80211_SDATA_QUEUE_RX_AGG_STOP = 4,
-};
-
enum {
IEEE80211_RX_MSG = 1,
IEEE80211_TX_STATUS_MSG = 2,
@@ -1432,6 +1423,7 @@ struct ieee80211_csa_ie {
u8 count;
u8 ttl;
u16 pre_value;
+ u16 reason_code;
};
/* Parsed Information Elements */
@@ -2057,6 +2049,8 @@ u8 *ieee80211_ie_build_ht_cap(u8 *pos, struct ieee80211_sta_ht_cap *ht_cap,
u8 *ieee80211_ie_build_ht_oper(u8 *pos, struct ieee80211_sta_ht_cap *ht_cap,
const struct cfg80211_chan_def *chandef,
u16 prot_mode, bool rifs_mode);
+void ieee80211_ie_build_wide_bw_cs(u8 *pos,
+ const struct cfg80211_chan_def *chandef);
u8 *ieee80211_ie_build_vht_cap(u8 *pos, struct ieee80211_sta_vht_cap *vht_cap,
u32 cap);
u8 *ieee80211_ie_build_vht_oper(u8 *pos, struct ieee80211_sta_vht_cap *vht_cap,
diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c
index f5f50150ba1c..9228ac73c429 100644
--- a/net/mac80211/iface.c
+++ b/net/mac80211/iface.c
@@ -1237,7 +1237,6 @@ static void ieee80211_iface_work(struct work_struct *work)
struct ieee80211_local *local = sdata->local;
struct sk_buff *skb;
struct sta_info *sta;
- struct ieee80211_rx_agg *rx_agg;
if (!ieee80211_sdata_running(sdata))
return;
@@ -1252,28 +1251,8 @@ static void ieee80211_iface_work(struct work_struct *work)
while ((skb = skb_dequeue(&sdata->skb_queue))) {
struct ieee80211_mgmt *mgmt = (void *)skb->data;
- if (skb->pkt_type == IEEE80211_SDATA_QUEUE_RX_AGG_START) {
- rx_agg = (void *)&skb->cb;
- mutex_lock(&local->sta_mtx);
- sta = sta_info_get_bss(sdata, rx_agg->addr);
- if (sta)
- __ieee80211_start_rx_ba_session(sta,
- 0, 0, 0, 1, rx_agg->tid,
- IEEE80211_MAX_AMPDU_BUF,
- false, true);
- mutex_unlock(&local->sta_mtx);
- } else if (skb->pkt_type == IEEE80211_SDATA_QUEUE_RX_AGG_STOP) {
- rx_agg = (void *)&skb->cb;
- mutex_lock(&local->sta_mtx);
- sta = sta_info_get_bss(sdata, rx_agg->addr);
- if (sta)
- __ieee80211_stop_rx_ba_session(sta,
- rx_agg->tid,
- WLAN_BACK_RECIPIENT, 0,
- false);
- mutex_unlock(&local->sta_mtx);
- } else if (ieee80211_is_action(mgmt->frame_control) &&
- mgmt->u.action.category == WLAN_CATEGORY_BACK) {
+ if (ieee80211_is_action(mgmt->frame_control) &&
+ mgmt->u.action.category == WLAN_CATEGORY_BACK) {
int len = skb->len;
mutex_lock(&local->sta_mtx);
diff --git a/net/mac80211/mesh.c b/net/mac80211/mesh.c
index 737e1f082b0d..a550c707cd8a 100644
--- a/net/mac80211/mesh.c
+++ b/net/mac80211/mesh.c
@@ -345,7 +345,7 @@ int mesh_add_vendor_ies(struct ieee80211_sub_if_data *sdata,
data = ifmsh->ie + offset;
if (skb_tailroom(skb) < len)
return -ENOMEM;
- memcpy(skb_put(skb, len), data, len);
+ skb_put_data(skb, data, len);
}
return 0;
@@ -369,7 +369,7 @@ int mesh_add_rsn_ie(struct ieee80211_sub_if_data *sdata, struct sk_buff *skb)
if (skb_tailroom(skb) < len)
return -ENOMEM;
- memcpy(skb_put(skb, len), data, len);
+ skb_put_data(skb, data, len);
return 0;
}
@@ -690,6 +690,9 @@ ieee80211_mesh_build_beacon(struct ieee80211_if_mesh *ifmsh)
2 + sizeof(struct ieee80211_channel_sw_ie) +
/* Mesh Channel Switch Parameters */
2 + sizeof(struct ieee80211_mesh_chansw_params_ie) +
+ /* Channel Switch Wrapper + Wide Bandwidth CSA IE */
+ 2 + 2 + sizeof(struct ieee80211_wide_bw_chansw_ie) +
+ 2 + sizeof(struct ieee80211_sec_chan_offs_ie) +
2 + 8 + /* supported rates */
2 + 3; /* DS params */
tail_len = 2 + (IEEE80211_MAX_SUPP_RATES - 8) +
@@ -716,8 +719,7 @@ ieee80211_mesh_build_beacon(struct ieee80211_if_mesh *ifmsh)
bcn->head = ((u8 *) bcn) + sizeof(*bcn);
/* fill in the head */
- mgmt = (struct ieee80211_mgmt *) skb_put(skb, hdr_len);
- memset(mgmt, 0, hdr_len);
+ mgmt = skb_put_zero(skb, hdr_len);
mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT |
IEEE80211_STYPE_BEACON);
eth_broadcast_addr(mgmt->da);
@@ -736,8 +738,12 @@ ieee80211_mesh_build_beacon(struct ieee80211_if_mesh *ifmsh)
rcu_read_lock();
csa = rcu_dereference(ifmsh->csa);
if (csa) {
- pos = skb_put(skb, 13);
- memset(pos, 0, 13);
+ enum nl80211_channel_type ct;
+ struct cfg80211_chan_def *chandef;
+ int ie_len = 2 + sizeof(struct ieee80211_channel_sw_ie) +
+ 2 + sizeof(struct ieee80211_mesh_chansw_params_ie);
+
+ pos = skb_put_zero(skb, ie_len);
*pos++ = WLAN_EID_CHANNEL_SWITCH;
*pos++ = 3;
*pos++ = 0x0;
@@ -760,6 +766,37 @@ ieee80211_mesh_build_beacon(struct ieee80211_if_mesh *ifmsh)
pos += 2;
put_unaligned_le16(ifmsh->pre_value, pos);
pos += 2;
+
+ switch (csa->settings.chandef.width) {
+ case NL80211_CHAN_WIDTH_40:
+ ie_len = 2 + sizeof(struct ieee80211_sec_chan_offs_ie);
+ pos = skb_put_zero(skb, ie_len);
+
+ *pos++ = WLAN_EID_SECONDARY_CHANNEL_OFFSET; /* EID */
+ *pos++ = 1; /* len */
+ ct = cfg80211_get_chandef_type(&csa->settings.chandef);
+ if (ct == NL80211_CHAN_HT40PLUS)
+ *pos++ = IEEE80211_HT_PARAM_CHA_SEC_ABOVE;
+ else
+ *pos++ = IEEE80211_HT_PARAM_CHA_SEC_BELOW;
+ break;
+ case NL80211_CHAN_WIDTH_80:
+ case NL80211_CHAN_WIDTH_80P80:
+ case NL80211_CHAN_WIDTH_160:
+ /* Channel Switch Wrapper + Wide Bandwidth CSA IE */
+ ie_len = 2 + 2 +
+ sizeof(struct ieee80211_wide_bw_chansw_ie);
+ pos = skb_put_zero(skb, ie_len);
+
+ *pos++ = WLAN_EID_CHANNEL_SWITCH_WRAPPER; /* EID */
+ *pos++ = 5; /* len */
+ /* put sub IE */
+ chandef = &csa->settings.chandef;
+ ieee80211_ie_build_wide_bw_cs(pos, chandef);
+ break;
+ default:
+ break;
+ }
}
rcu_read_unlock();
@@ -916,6 +953,21 @@ void ieee80211_stop_mesh(struct ieee80211_sub_if_data *sdata)
ieee80211_configure_filter(local);
}
+static void ieee80211_mesh_csa_mark_radar(struct ieee80211_sub_if_data *sdata)
+{
+ int err;
+
+ /* if the current channel is a DFS channel, mark the channel as
+ * unavailable.
+ */
+ err = cfg80211_chandef_dfs_required(sdata->local->hw.wiphy,
+ &sdata->vif.bss_conf.chandef,
+ NL80211_IFTYPE_MESH_POINT);
+ if (err > 0)
+ cfg80211_radar_event(sdata->local->hw.wiphy,
+ &sdata->vif.bss_conf.chandef, GFP_ATOMIC);
+}
+
static bool
ieee80211_mesh_process_chnswitch(struct ieee80211_sub_if_data *sdata,
struct ieee802_11_elems *elems, bool beacon)
@@ -933,19 +985,20 @@ ieee80211_mesh_process_chnswitch(struct ieee80211_sub_if_data *sdata,
if (!sband)
return false;
- sta_flags = IEEE80211_STA_DISABLE_VHT;
+ sta_flags = 0;
switch (sdata->vif.bss_conf.chandef.width) {
case NL80211_CHAN_WIDTH_20_NOHT:
sta_flags |= IEEE80211_STA_DISABLE_HT;
case NL80211_CHAN_WIDTH_20:
sta_flags |= IEEE80211_STA_DISABLE_40MHZ;
+ case NL80211_CHAN_WIDTH_40:
+ sta_flags |= IEEE80211_STA_DISABLE_VHT;
break;
default:
break;
}
memset(&params, 0, sizeof(params));
- memset(&csa_ie, 0, sizeof(csa_ie));
err = ieee80211_parse_ch_switch_ie(sdata, elems, sband->band,
sta_flags, sdata->vif.addr,
&csa_ie);
@@ -954,11 +1007,19 @@ ieee80211_mesh_process_chnswitch(struct ieee80211_sub_if_data *sdata,
if (err)
return false;
+ /* Mark the channel unavailable if the reason for the switch is
+ * regulatory.
+ */
+ if (csa_ie.reason_code == WLAN_REASON_MESH_CHAN_REGULATORY)
+ ieee80211_mesh_csa_mark_radar(sdata);
+
params.chandef = csa_ie.chandef;
params.count = csa_ie.count;
if (!cfg80211_chandef_usable(sdata->local->hw.wiphy, &params.chandef,
- IEEE80211_CHAN_DISABLED)) {
+ IEEE80211_CHAN_DISABLED) ||
+ !cfg80211_reg_can_beacon(sdata->local->hw.wiphy, &params.chandef,
+ NL80211_IFTYPE_MESH_POINT)) {
sdata_info(sdata,
"mesh STA %pM switches to unsupported channel (%d MHz, width:%d, CF1/2: %d/%d MHz), aborting\n",
sdata->vif.addr,
@@ -974,9 +1035,16 @@ ieee80211_mesh_process_chnswitch(struct ieee80211_sub_if_data *sdata,
NL80211_IFTYPE_MESH_POINT);
if (err < 0)
return false;
- if (err > 0)
- /* TODO: DFS not (yet) supported */
+ if (err > 0 && !ifmsh->userspace_handles_dfs) {
+ sdata_info(sdata,
+ "mesh STA %pM switches to channel requiring DFS (%d MHz, width:%d, CF1/2: %d/%d MHz), aborting\n",
+ sdata->vif.addr,
+ params.chandef.chan->center_freq,
+ params.chandef.width,
+ params.chandef.center_freq1,
+ params.chandef.center_freq2);
return false;
+ }
params.radar_required = err;
@@ -1057,8 +1125,8 @@ ieee80211_mesh_rx_probe_req(struct ieee80211_sub_if_data *sdata,
goto out;
skb_reserve(presp, local->tx_headroom);
- memcpy(skb_put(presp, bcn->head_len), bcn->head, bcn->head_len);
- memcpy(skb_put(presp, bcn->tail_len), bcn->tail, bcn->tail_len);
+ skb_put_data(presp, bcn->head, bcn->head_len);
+ skb_put_data(presp, bcn->tail, bcn->tail_len);
hdr = (struct ieee80211_mgmt *) presp->data;
hdr->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT |
IEEE80211_STYPE_PROBE_RESP);
@@ -1197,7 +1265,7 @@ static int mesh_fwd_csa_frame(struct ieee80211_sub_if_data *sdata,
if (!skb)
return -ENOMEM;
skb_reserve(skb, local->tx_headroom);
- mgmt_fwd = (struct ieee80211_mgmt *) skb_put(skb, len);
+ mgmt_fwd = skb_put(skb, len);
/* offset_ttl is based on whether the secondary channel
* offset is available or not. Subtract 1 from the mesh TTL
@@ -1233,7 +1301,7 @@ static void mesh_rx_csa_frame(struct ieee80211_sub_if_data *sdata,
pos = mgmt->u.action.u.chan_switch.variable;
baselen = offsetof(struct ieee80211_mgmt,
u.action.u.chan_switch.variable);
- ieee802_11_parse_elems(pos, len - baselen, false, &elems);
+ ieee802_11_parse_elems(pos, len - baselen, true, &elems);
ifmsh->chsw_ttl = elems.mesh_chansw_params_ie->mesh_ttl;
if (!--ifmsh->chsw_ttl)
diff --git a/net/mac80211/mesh_hwmp.c b/net/mac80211/mesh_hwmp.c
index 4005edd71fe8..d8bbd0d2225a 100644
--- a/net/mac80211/mesh_hwmp.c
+++ b/net/mac80211/mesh_hwmp.c
@@ -120,8 +120,7 @@ static int mesh_path_sel_frame_tx(enum mpath_frame_type action, u8 flags,
if (!skb)
return -1;
skb_reserve(skb, local->tx_headroom);
- mgmt = (struct ieee80211_mgmt *) skb_put(skb, hdr_len);
- memset(mgmt, 0, hdr_len);
+ mgmt = skb_put_zero(skb, hdr_len);
mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT |
IEEE80211_STYPE_ACTION);
@@ -257,8 +256,7 @@ int mesh_path_error_tx(struct ieee80211_sub_if_data *sdata,
if (!skb)
return -1;
skb_reserve(skb, local->tx_headroom + sdata->encrypt_headroom);
- mgmt = (struct ieee80211_mgmt *) skb_put(skb, hdr_len);
- memset(mgmt, 0, hdr_len);
+ mgmt = skb_put_zero(skb, hdr_len);
mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT |
IEEE80211_STYPE_ACTION);
diff --git a/net/mac80211/mesh_plink.c b/net/mac80211/mesh_plink.c
index 1131cd504a15..f69c6c38ca43 100644
--- a/net/mac80211/mesh_plink.c
+++ b/net/mac80211/mesh_plink.c
@@ -242,8 +242,7 @@ static int mesh_plink_frame_tx(struct ieee80211_sub_if_data *sdata,
return err;
info = IEEE80211_SKB_CB(skb);
skb_reserve(skb, local->tx_headroom);
- mgmt = (struct ieee80211_mgmt *) skb_put(skb, hdr_len);
- memset(mgmt, 0, hdr_len);
+ mgmt = skb_put_zero(skb, hdr_len);
mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT |
IEEE80211_STYPE_ACTION);
memcpy(mgmt->da, da, ETH_ALEN);
@@ -264,8 +263,7 @@ static int mesh_plink_frame_tx(struct ieee80211_sub_if_data *sdata,
band = sband->band;
/* capability info */
- pos = skb_put(skb, 2);
- memset(pos, 0, 2);
+ pos = skb_put_zero(skb, 2);
if (action == WLAN_SP_MESH_PEERING_CONFIRM) {
/* AID */
pos = skb_put(skb, 2);
diff --git a/net/mac80211/mesh_ps.c b/net/mac80211/mesh_ps.c
index 90a268abea17..d8cd91424175 100644
--- a/net/mac80211/mesh_ps.c
+++ b/net/mac80211/mesh_ps.c
@@ -30,7 +30,7 @@ static struct sk_buff *mps_qos_null_get(struct sta_info *sta)
return NULL;
skb_reserve(skb, local->hw.extra_tx_headroom);
- nullfunc = (struct ieee80211_hdr *) skb_put(skb, size);
+ nullfunc = skb_put(skb, size);
fc = cpu_to_le16(IEEE80211_FTYPE_DATA | IEEE80211_STYPE_QOS_NULLFUNC);
ieee80211_fill_mesh_addresses(nullfunc, &fc, sta->sta.addr,
sdata->vif.addr);
@@ -39,7 +39,7 @@ static struct sk_buff *mps_qos_null_get(struct sta_info *sta)
nullfunc->seq_ctrl = 0;
/* no address resolution for this frame -> set addr 1 immediately */
memcpy(nullfunc->addr1, sta->sta.addr, ETH_ALEN);
- memset(skb_put(skb, 2), 0, 2); /* append QoS control field */
+ skb_put_zero(skb, 2); /* append QoS control field */
ieee80211_mps_set_frame_flags(sdata, sta, nullfunc);
return skb;
diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c
index cc8e6ea1b27e..b588e593b0ec 100644
--- a/net/mac80211/mlme.c
+++ b/net/mac80211/mlme.c
@@ -674,8 +674,7 @@ static void ieee80211_send_assoc(struct ieee80211_sub_if_data *sdata)
if (ifmgd->flags & IEEE80211_STA_ENABLE_RRM)
capab |= WLAN_CAPABILITY_RADIO_MEASURE;
- mgmt = (struct ieee80211_mgmt *) skb_put(skb, 24);
- memset(mgmt, 0, 24);
+ mgmt = skb_put_zero(skb, 24);
memcpy(mgmt->da, assoc_data->bss->bssid, ETH_ALEN);
memcpy(mgmt->sa, sdata->vif.addr, ETH_ALEN);
memcpy(mgmt->bssid, assoc_data->bss->bssid, ETH_ALEN);
@@ -797,8 +796,7 @@ static void ieee80211_send_assoc(struct ieee80211_sub_if_data *sdata)
after_ric,
ARRAY_SIZE(after_ric),
offset);
- pos = skb_put(skb, noffset - offset);
- memcpy(pos, assoc_data->ie + offset, noffset - offset);
+ skb_put_data(skb, assoc_data->ie + offset, noffset - offset);
offset = noffset;
}
@@ -835,8 +833,7 @@ static void ieee80211_send_assoc(struct ieee80211_sub_if_data *sdata)
noffset = ieee80211_ie_split(assoc_data->ie, assoc_data->ie_len,
before_vht, ARRAY_SIZE(before_vht),
offset);
- pos = skb_put(skb, noffset - offset);
- memcpy(pos, assoc_data->ie + offset, noffset - offset);
+ skb_put_data(skb, assoc_data->ie + offset, noffset - offset);
offset = noffset;
}
@@ -849,8 +846,7 @@ static void ieee80211_send_assoc(struct ieee80211_sub_if_data *sdata)
noffset = ieee80211_ie_split_vendor(assoc_data->ie,
assoc_data->ie_len,
offset);
- pos = skb_put(skb, noffset - offset);
- memcpy(pos, assoc_data->ie + offset, noffset - offset);
+ skb_put_data(skb, assoc_data->ie + offset, noffset - offset);
offset = noffset;
}
@@ -869,8 +865,7 @@ static void ieee80211_send_assoc(struct ieee80211_sub_if_data *sdata)
/* add any remaining custom (i.e. vendor specific here) IEs */
if (assoc_data->ie_len) {
noffset = assoc_data->ie_len;
- pos = skb_put(skb, noffset - offset);
- memcpy(pos, assoc_data->ie + offset, noffset - offset);
+ skb_put_data(skb, assoc_data->ie + offset, noffset - offset);
}
if (assoc_data->fils_kek_len &&
@@ -949,8 +944,7 @@ static void ieee80211_send_4addr_nullfunc(struct ieee80211_local *local,
skb_reserve(skb, local->hw.extra_tx_headroom);
- nullfunc = (struct ieee80211_hdr *) skb_put(skb, 30);
- memset(nullfunc, 0, 30);
+ nullfunc = skb_put_zero(skb, 30);
fc = cpu_to_le16(IEEE80211_FTYPE_DATA | IEEE80211_STYPE_NULLFUNC |
IEEE80211_FCTL_FROMDS | IEEE80211_FCTL_TODS);
nullfunc->frame_control = fc;
@@ -1122,7 +1116,6 @@ ieee80211_sta_process_chanswitch(struct ieee80211_sub_if_data *sdata,
return;
current_band = cbss->channel->band;
- memset(&csa_ie, 0, sizeof(csa_ie));
res = ieee80211_parse_ch_switch_ie(sdata, elems, current_band,
ifmgd->flags,
ifmgd->associated->bssid, &csa_ie);
diff --git a/net/mac80211/offchannel.c b/net/mac80211/offchannel.c
index eede5c6db8d5..f8e7a8bbc618 100644
--- a/net/mac80211/offchannel.c
+++ b/net/mac80211/offchannel.c
@@ -885,8 +885,7 @@ int ieee80211_mgmt_tx(struct wiphy *wiphy, struct wireless_dev *wdev,
}
skb_reserve(skb, local->hw.extra_tx_headroom);
- data = skb_put(skb, params->len);
- memcpy(data, params->buf, params->len);
+ data = skb_put_data(skb, params->buf, params->len);
/* Update CSA counters */
if (sdata->vif.csa_active &&
diff --git a/net/mac80211/rate.c b/net/mac80211/rate.c
index ea1f4315c521..76f303fda3ed 100644
--- a/net/mac80211/rate.c
+++ b/net/mac80211/rate.c
@@ -943,6 +943,8 @@ int rate_control_set_rates(struct ieee80211_hw *hw,
drv_sta_rate_tbl_update(hw_to_local(hw), sta->sdata, pubsta);
+ ieee80211_sta_set_expected_throughput(pubsta, sta_get_expected_throughput(sta));
+
return 0;
}
EXPORT_SYMBOL(rate_control_set_rates);
@@ -991,4 +993,3 @@ void rate_control_deinitialize(struct ieee80211_local *local)
local->rate_ctrl = NULL;
rate_control_free(local, ref);
}
-
diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c
index 3674fe3d67dc..70e9d2ca8bbe 100644
--- a/net/mac80211/rx.c
+++ b/net/mac80211/rx.c
@@ -237,7 +237,6 @@ static void ieee80211_handle_mu_mimo_mon(struct ieee80211_sub_if_data *sdata,
if (!skb)
return;
- skb->pkt_type = IEEE80211_SDATA_QUEUE_TYPE_FRAME;
skb_queue_tail(&sdata->skb_queue, skb);
ieee80211_queue_work(&sdata->local->hw, &sdata->work);
}
@@ -274,7 +273,7 @@ ieee80211_add_rx_radiotap_header(struct ieee80211_local *local,
if (!(has_fcs && ieee80211_hw_check(&local->hw, RX_INCLUDES_FCS)))
mpdulen += FCS_LEN;
- rthdr = (struct ieee80211_radiotap_header *)skb_push(skb, rtap_len);
+ rthdr = skb_push(skb, rtap_len);
memset(rthdr, 0, rtap_len - rtap.len - rtap.pad);
it_present = &rthdr->it_present;
@@ -1217,7 +1216,6 @@ static void ieee80211_rx_reorder_ampdu(struct ieee80211_rx_data *rx,
/* if this mpdu is fragmented - terminate rx aggregation session */
sc = le16_to_cpu(hdr->seq_ctrl);
if (sc & IEEE80211_SCTL_FRAG) {
- skb->pkt_type = IEEE80211_SDATA_QUEUE_TYPE_FRAME;
skb_queue_tail(&rx->sdata->skb_queue, skb);
ieee80211_queue_work(&local->hw, &rx->sdata->work);
return;
@@ -2100,7 +2098,7 @@ ieee80211_rx_h_defragment(struct ieee80211_rx_data *rx)
}
}
while ((skb = __skb_dequeue(&entry->skb_list))) {
- memcpy(skb_put(rx->skb, skb->len), skb->data, skb->len);
+ skb_put_data(rx->skb, skb->data, skb->len);
dev_kfree_skb(skb);
}
@@ -2762,8 +2760,7 @@ static void ieee80211_process_sa_query_req(struct ieee80211_sub_if_data *sdata,
return;
skb_reserve(skb, local->hw.extra_tx_headroom);
- resp = (struct ieee80211_mgmt *) skb_put(skb, 24);
- memset(resp, 0, 24);
+ resp = skb_put_zero(skb, 24);
memcpy(resp->da, mgmt->sa, ETH_ALEN);
memcpy(resp->sa, sdata->vif.addr, ETH_ALEN);
memcpy(resp->bssid, sdata->u.mgd.bssid, ETH_ALEN);
@@ -3104,7 +3101,6 @@ ieee80211_rx_h_action(struct ieee80211_rx_data *rx)
return RX_QUEUED;
queue:
- rx->skb->pkt_type = IEEE80211_SDATA_QUEUE_TYPE_FRAME;
skb_queue_tail(&sdata->skb_queue, rx->skb);
ieee80211_queue_work(&local->hw, &sdata->work);
if (rx->sta)
@@ -3250,7 +3246,6 @@ ieee80211_rx_h_mgmt(struct ieee80211_rx_data *rx)
}
/* queue up frame and kick off work to process it */
- rx->skb->pkt_type = IEEE80211_SDATA_QUEUE_TYPE_FRAME;
skb_queue_tail(&sdata->skb_queue, rx->skb);
ieee80211_queue_work(&rx->local->hw, &sdata->work);
if (rx->sta)
diff --git a/net/mac80211/spectmgmt.c b/net/mac80211/spectmgmt.c
index 0782e486fe89..ee0181778a42 100644
--- a/net/mac80211/spectmgmt.c
+++ b/net/mac80211/spectmgmt.c
@@ -36,6 +36,8 @@ int ieee80211_parse_ch_switch_ie(struct ieee80211_sub_if_data *sdata,
const struct ieee80211_wide_bw_chansw_ie *wide_bw_chansw_ie;
int secondary_channel_offset = -1;
+ memset(csa_ie, 0, sizeof(*csa_ie));
+
sec_chan_offs = elems->sec_chan_offs;
wide_bw_chansw_ie = elems->wide_bw_chansw_ie;
@@ -76,6 +78,11 @@ int ieee80211_parse_ch_switch_ie(struct ieee80211_sub_if_data *sdata,
csa_ie->mode = elems->mesh_chansw_params_ie->mesh_flags;
csa_ie->pre_value = le16_to_cpu(
elems->mesh_chansw_params_ie->mesh_pre_value);
+
+ if (elems->mesh_chansw_params_ie->mesh_flags &
+ WLAN_EID_CHAN_SWITCH_PARAM_REASON)
+ csa_ie->reason_code = le16_to_cpu(
+ elems->mesh_chansw_params_ie->mesh_reason);
}
new_freq = ieee80211_channel_to_frequency(new_chan_no, new_band);
@@ -186,8 +193,7 @@ static void ieee80211_send_refuse_measurement_request(struct ieee80211_sub_if_da
return;
skb_reserve(skb, local->hw.extra_tx_headroom);
- msr_report = (struct ieee80211_mgmt *)skb_put(skb, 24);
- memset(msr_report, 0, 24);
+ msr_report = skb_put_zero(skb, 24);
memcpy(msr_report->da, da, ETH_ALEN);
memcpy(msr_report->sa, sdata->vif.addr, ETH_ALEN);
memcpy(msr_report->bssid, bssid, ETH_ALEN);
diff --git a/net/mac80211/sta_info.c b/net/mac80211/sta_info.c
index 403e3cc58b57..69615016d5bf 100644
--- a/net/mac80211/sta_info.c
+++ b/net/mac80211/sta_info.c
@@ -20,6 +20,7 @@
#include <linux/timer.h>
#include <linux/rtnetlink.h>
+#include <net/codel.h>
#include <net/mac80211.h>
#include "ieee80211_i.h"
#include "driver-ops.h"
@@ -425,6 +426,11 @@ struct sta_info *sta_info_alloc(struct ieee80211_sub_if_data *sdata,
sta->sta.max_rc_amsdu_len = IEEE80211_MAX_MPDU_LEN_HT_BA;
+ sta->cparams.ce_threshold = CODEL_DISABLED_THRESHOLD;
+ sta->cparams.target = MS2TIME(20);
+ sta->cparams.interval = MS2TIME(100);
+ sta->cparams.ecn = true;
+
sta_dbg(sdata, "Allocated STA %pM\n", sta->sta.addr);
return sta;
@@ -1306,7 +1312,7 @@ static void ieee80211_send_null_response(struct sta_info *sta, int tid,
skb_reserve(skb, local->hw.extra_tx_headroom);
- nullfunc = (void *) skb_put(skb, size);
+ nullfunc = skb_put(skb, size);
nullfunc->frame_control = fc;
nullfunc->duration_id = 0;
memcpy(nullfunc->addr1, sta->sta.addr, ETH_ALEN);
@@ -2310,3 +2316,27 @@ unsigned long ieee80211_sta_last_active(struct sta_info *sta)
return stats->last_rx;
return sta->status_stats.last_ack;
}
+
+static void sta_update_codel_params(struct sta_info *sta, u32 thr)
+{
+ if (!sta->sdata->local->ops->wake_tx_queue)
+ return;
+
+ if (thr && thr < STA_SLOW_THRESHOLD * sta->local->num_sta) {
+ sta->cparams.target = MS2TIME(50);
+ sta->cparams.interval = MS2TIME(300);
+ sta->cparams.ecn = false;
+ } else {
+ sta->cparams.target = MS2TIME(20);
+ sta->cparams.interval = MS2TIME(100);
+ sta->cparams.ecn = true;
+ }
+}
+
+void ieee80211_sta_set_expected_throughput(struct ieee80211_sta *pubsta,
+ u32 thr)
+{
+ struct sta_info *sta = container_of(pubsta, struct sta_info, sta);
+
+ sta_update_codel_params(sta, thr);
+}
diff --git a/net/mac80211/sta_info.h b/net/mac80211/sta_info.h
index ea0747d6a6da..3acbdfa9f649 100644
--- a/net/mac80211/sta_info.h
+++ b/net/mac80211/sta_info.h
@@ -233,6 +233,8 @@ struct tid_ampdu_rx {
* RX timer expired until the work for it runs
* @tid_rx_stop_requested: bitmap indicating which BA sessions per TID the
* driver requested to close until the work for it runs
+ * @tid_rx_manage_offl: bitmap indicating which BA sessions were requested
+ * to be treated as started/stopped due to offloading
* @agg_session_valid: bitmap indicating which TID has a rx BA session open on
* @unexpected_agg: bitmap indicating which TID already sent a delBA due to
* unexpected aggregation related frames outside a session
@@ -250,6 +252,7 @@ struct sta_ampdu_mlme {
u8 tid_rx_token[IEEE80211_NUM_TIDS];
unsigned long tid_rx_timer_expired[BITS_TO_LONGS(IEEE80211_NUM_TIDS)];
unsigned long tid_rx_stop_requested[BITS_TO_LONGS(IEEE80211_NUM_TIDS)];
+ unsigned long tid_rx_manage_offl[BITS_TO_LONGS(2 * IEEE80211_NUM_TIDS)];
unsigned long agg_session_valid[BITS_TO_LONGS(IEEE80211_NUM_TIDS)];
unsigned long unexpected_agg[BITS_TO_LONGS(IEEE80211_NUM_TIDS)];
/* tx */
@@ -396,6 +399,14 @@ struct ieee80211_sta_rx_stats {
};
/**
+ * The bandwidth threshold below which the per-station CoDel parameters will be
+ * scaled to be more lenient (to prevent starvation of slow stations). This
+ * value will be scaled by the number of active stations when it is being
+ * applied.
+ */
+#define STA_SLOW_THRESHOLD 6000 /* 6 Mbps */
+
+/**
* struct sta_info - STA information
*
* This structure collects information about a station that
@@ -448,6 +459,7 @@ struct ieee80211_sta_rx_stats {
* @known_smps_mode: the smps_mode the client thinks we are in. Relevant for
* AP only.
* @cipher_scheme: optional cipher scheme for this station
+ * @cparams: CoDel parameters for this station.
* @reserved_tid: reserved TID (if any, otherwise IEEE80211_TID_UNRESERVED)
* @fast_tx: TX fastpath information
* @fast_rx: RX fastpath information
@@ -551,6 +563,8 @@ struct sta_info {
enum ieee80211_smps_mode known_smps_mode;
const struct ieee80211_cipher_scheme *cipher_scheme;
+ struct codel_params cparams;
+
u8 reserved_tid;
struct cfg80211_chan_def tdls_chandef;
diff --git a/net/mac80211/status.c b/net/mac80211/status.c
index be47ac5cd8c8..da7427a41529 100644
--- a/net/mac80211/status.c
+++ b/net/mac80211/status.c
@@ -288,7 +288,7 @@ ieee80211_add_tx_radiotap_header(struct ieee80211_local *local,
unsigned char *pos;
u16 txflags;
- rthdr = (struct ieee80211_radiotap_header *) skb_push(skb, rtap_len);
+ rthdr = skb_push(skb, rtap_len);
memset(rthdr, 0, rtap_len);
rthdr->it_len = cpu_to_le16(rtap_len);
@@ -546,6 +546,8 @@ static void ieee80211_report_used_skb(struct ieee80211_local *local,
skb->wifi_acked_valid = 1;
skb->wifi_acked = acked;
}
+
+ ieee80211_led_tx(local);
}
/*
@@ -823,8 +825,6 @@ static void __ieee80211_tx_status(struct ieee80211_hw *hw,
}
}
- ieee80211_led_tx(local);
-
/* SNMP counters
* Fragments are passed to low-level drivers as separate skbs, so these
* are actually fragments, not frames. Update frame counters only for
diff --git a/net/mac80211/tdls.c b/net/mac80211/tdls.c
index f20dcf1b1830..91093d4a2f84 100644
--- a/net/mac80211/tdls.c
+++ b/net/mac80211/tdls.c
@@ -49,7 +49,7 @@ static void ieee80211_tdls_add_ext_capab(struct ieee80211_sub_if_data *sdata,
!ifmgd->tdls_wider_bw_prohibited;
struct ieee80211_supported_band *sband = ieee80211_get_sband(sdata);
bool vht = sband && sband->vht_cap.vht_supported;
- u8 *pos = (void *)skb_put(skb, 10);
+ u8 *pos = skb_put(skb, 10);
*pos++ = WLAN_EID_EXT_CAPABILITY;
*pos++ = 8; /* len */
@@ -168,7 +168,7 @@ static void ieee80211_tdls_add_oper_classes(struct ieee80211_sub_if_data *sdata,
static void ieee80211_tdls_add_bss_coex_ie(struct sk_buff *skb)
{
- u8 *pos = (void *)skb_put(skb, 3);
+ u8 *pos = skb_put(skb, 3);
*pos++ = WLAN_EID_BSS_COEX_2040;
*pos++ = 1; /* len */
@@ -209,7 +209,7 @@ static void ieee80211_tdls_add_link_ie(struct ieee80211_sub_if_data *sdata,
rsp_addr = sdata->vif.addr;
}
- lnkid = (void *)skb_put(skb, sizeof(struct ieee80211_tdls_lnkie));
+ lnkid = skb_put(skb, sizeof(struct ieee80211_tdls_lnkie));
lnkid->ie_type = WLAN_EID_LINK_ID;
lnkid->ie_len = sizeof(struct ieee80211_tdls_lnkie) - 2;
@@ -223,7 +223,7 @@ static void
ieee80211_tdls_add_aid(struct ieee80211_sub_if_data *sdata, struct sk_buff *skb)
{
struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
- u8 *pos = (void *)skb_put(skb, 4);
+ u8 *pos = skb_put(skb, 4);
*pos++ = WLAN_EID_AID;
*pos++ = 2; /* len */
@@ -271,8 +271,7 @@ static void ieee80211_tdls_add_wmm_param_ie(struct ieee80211_sub_if_data *sdata,
struct ieee80211_tx_queue_params *txq;
int i;
- wmm = (void *)skb_put(skb, sizeof(*wmm));
- memset(wmm, 0, sizeof(*wmm));
+ wmm = skb_put_zero(skb, sizeof(*wmm));
wmm->element_id = WLAN_EID_VENDOR_SPECIFIC;
wmm->len = sizeof(*wmm) - 2;
@@ -389,8 +388,7 @@ ieee80211_tdls_add_setup_start_ies(struct ieee80211_sub_if_data *sdata,
before_ext_cap,
ARRAY_SIZE(before_ext_cap),
offset);
- pos = skb_put(skb, noffset - offset);
- memcpy(pos, extra_ies + offset, noffset - offset);
+ skb_put_data(skb, extra_ies + offset, noffset - offset);
offset = noffset;
}
@@ -419,8 +417,7 @@ ieee80211_tdls_add_setup_start_ies(struct ieee80211_sub_if_data *sdata,
before_ht_cap,
ARRAY_SIZE(before_ht_cap),
offset);
- pos = skb_put(skb, noffset - offset);
- memcpy(pos, extra_ies + offset, noffset - offset);
+ skb_put_data(skb, extra_ies + offset, noffset - offset);
offset = noffset;
}
@@ -491,8 +488,7 @@ ieee80211_tdls_add_setup_start_ies(struct ieee80211_sub_if_data *sdata,
before_vht_cap,
ARRAY_SIZE(before_vht_cap),
offset);
- pos = skb_put(skb, noffset - offset);
- memcpy(pos, extra_ies + offset, noffset - offset);
+ skb_put_data(skb, extra_ies + offset, noffset - offset);
offset = noffset;
}
@@ -533,8 +529,7 @@ ieee80211_tdls_add_setup_start_ies(struct ieee80211_sub_if_data *sdata,
/* add any remaining IEs */
if (extra_ies_len) {
noffset = extra_ies_len;
- pos = skb_put(skb, noffset - offset);
- memcpy(pos, extra_ies + offset, noffset - offset);
+ skb_put_data(skb, extra_ies + offset, noffset - offset);
}
}
@@ -576,8 +571,7 @@ ieee80211_tdls_add_setup_cfm_ies(struct ieee80211_sub_if_data *sdata,
before_qos,
ARRAY_SIZE(before_qos),
offset);
- pos = skb_put(skb, noffset - offset);
- memcpy(pos, extra_ies + offset, noffset - offset);
+ skb_put_data(skb, extra_ies + offset, noffset - offset);
offset = noffset;
}
@@ -597,8 +591,7 @@ ieee80211_tdls_add_setup_cfm_ies(struct ieee80211_sub_if_data *sdata,
before_ht_op,
ARRAY_SIZE(before_ht_op),
offset);
- pos = skb_put(skb, noffset - offset);
- memcpy(pos, extra_ies + offset, noffset - offset);
+ skb_put_data(skb, extra_ies + offset, noffset - offset);
offset = noffset;
}
@@ -639,8 +632,7 @@ ieee80211_tdls_add_setup_cfm_ies(struct ieee80211_sub_if_data *sdata,
/* add any remaining IEs */
if (extra_ies_len) {
noffset = extra_ies_len;
- pos = skb_put(skb, noffset - offset);
- memcpy(pos, extra_ies + offset, noffset - offset);
+ skb_put_data(skb, extra_ies + offset, noffset - offset);
}
}
@@ -653,7 +645,6 @@ ieee80211_tdls_add_chan_switch_req_ies(struct ieee80211_sub_if_data *sdata,
{
struct ieee80211_tdls_data *tf;
size_t offset = 0, noffset;
- u8 *pos;
if (WARN_ON_ONCE(!chandef))
return;
@@ -671,8 +662,7 @@ ieee80211_tdls_add_chan_switch_req_ies(struct ieee80211_sub_if_data *sdata,
before_lnkie,
ARRAY_SIZE(before_lnkie),
offset);
- pos = skb_put(skb, noffset - offset);
- memcpy(pos, extra_ies + offset, noffset - offset);
+ skb_put_data(skb, extra_ies + offset, noffset - offset);
offset = noffset;
}
@@ -681,8 +671,7 @@ ieee80211_tdls_add_chan_switch_req_ies(struct ieee80211_sub_if_data *sdata,
/* add any remaining IEs */
if (extra_ies_len) {
noffset = extra_ies_len;
- pos = skb_put(skb, noffset - offset);
- memcpy(pos, extra_ies + offset, noffset - offset);
+ skb_put_data(skb, extra_ies + offset, noffset - offset);
}
}
@@ -697,7 +686,7 @@ ieee80211_tdls_add_chan_switch_resp_ies(struct ieee80211_sub_if_data *sdata,
ieee80211_tdls_add_link_ie(sdata, skb, peer, initiator);
if (extra_ies_len)
- memcpy(skb_put(skb, extra_ies_len), extra_ies, extra_ies_len);
+ skb_put_data(skb, extra_ies, extra_ies_len);
}
static void ieee80211_tdls_add_ies(struct ieee80211_sub_if_data *sdata,
@@ -727,8 +716,7 @@ static void ieee80211_tdls_add_ies(struct ieee80211_sub_if_data *sdata,
case WLAN_TDLS_TEARDOWN:
case WLAN_TDLS_DISCOVERY_REQUEST:
if (extra_ies_len)
- memcpy(skb_put(skb, extra_ies_len), extra_ies,
- extra_ies_len);
+ skb_put_data(skb, extra_ies, extra_ies_len);
if (status_code == 0 || action_code == WLAN_TDLS_TEARDOWN)
ieee80211_tdls_add_link_ie(sdata, skb, peer, initiator);
break;
@@ -756,7 +744,7 @@ ieee80211_prep_tdls_encap_data(struct wiphy *wiphy, struct net_device *dev,
struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
struct ieee80211_tdls_data *tf;
- tf = (void *)skb_put(skb, offsetof(struct ieee80211_tdls_data, u));
+ tf = skb_put(skb, offsetof(struct ieee80211_tdls_data, u));
memcpy(tf->da, peer, ETH_ALEN);
memcpy(tf->sa, sdata->vif.addr, ETH_ALEN);
@@ -838,8 +826,7 @@ ieee80211_prep_tdls_direct(struct wiphy *wiphy, struct net_device *dev,
struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
struct ieee80211_mgmt *mgmt;
- mgmt = (void *)skb_put(skb, 24);
- memset(mgmt, 0, 24);
+ mgmt = skb_put_zero(skb, 24);
memcpy(mgmt->da, peer, ETH_ALEN);
memcpy(mgmt->sa, sdata->vif.addr, ETH_ALEN);
memcpy(mgmt->bssid, sdata->u.mgd.bssid, ETH_ALEN);
diff --git a/net/mac80211/trace.h b/net/mac80211/trace.h
index 0d645bc148d0..3d9ac17af407 100644
--- a/net/mac80211/trace.h
+++ b/net/mac80211/trace.h
@@ -92,16 +92,19 @@
__field(u16, ssn) \
__field(u8, buf_size) \
__field(bool, amsdu) \
- __field(u16, timeout)
+ __field(u16, timeout) \
+ __field(u16, action)
#define AMPDU_ACTION_ASSIGN STA_NAMED_ASSIGN(params->sta); \
__entry->tid = params->tid; \
__entry->ssn = params->ssn; \
__entry->buf_size = params->buf_size; \
__entry->amsdu = params->amsdu; \
- __entry->timeout = params->timeout;
-#define AMPDU_ACTION_PR_FMT STA_PR_FMT " tid %d, ssn %d, buf_size %u, amsdu %d, timeout %d"
+ __entry->timeout = params->timeout; \
+ __entry->action = params->action;
+#define AMPDU_ACTION_PR_FMT STA_PR_FMT " tid %d, ssn %d, buf_size %u, amsdu %d, timeout %d action %d"
#define AMPDU_ACTION_PR_ARG STA_PR_ARG, __entry->tid, __entry->ssn, \
- __entry->buf_size, __entry->amsdu, __entry->timeout
+ __entry->buf_size, __entry->amsdu, __entry->timeout, \
+ __entry->action
/*
* Tracing for driver callbacks.
diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c
index 04b22f8982fe..8858f4f185e9 100644
--- a/net/mac80211/tx.c
+++ b/net/mac80211/tx.c
@@ -903,8 +903,8 @@ static int ieee80211_fragment(struct ieee80211_tx_data *tx,
tmp->dev = skb->dev;
/* copy header and data */
- memcpy(skb_put(tmp, hdrlen), skb->data, hdrlen);
- memcpy(skb_put(tmp, fraglen), skb->data + pos, fraglen);
+ skb_put_data(tmp, skb->data, hdrlen);
+ skb_put_data(tmp, skb->data + pos, fraglen);
pos += fraglen;
}
@@ -1340,9 +1340,16 @@ static struct sk_buff *fq_tin_dequeue_func(struct fq *fq,
local = container_of(fq, struct ieee80211_local, fq);
txqi = container_of(tin, struct txq_info, tin);
- cparams = &local->cparams;
cstats = &txqi->cstats;
+ if (txqi->txq.sta) {
+ struct sta_info *sta = container_of(txqi->txq.sta,
+ struct sta_info, sta);
+ cparams = &sta->cparams;
+ } else {
+ cparams = &local->cparams;
+ }
+
if (flow == &txqi->def_flow)
cvars = &txqi->def_cvars;
else
@@ -2701,7 +2708,7 @@ static struct sk_buff *ieee80211_build_hdr(struct ieee80211_sub_if_data *sdata,
if (ieee80211_is_data_qos(fc)) {
__le16 *qos_control;
- qos_control = (__le16 *) skb_push(skb, 2);
+ qos_control = skb_push(skb, 2);
memcpy(skb_push(skb, hdrlen - 2), &hdr, hdrlen - 2);
/*
* Maybe we could actually set some fields here, for now just
@@ -3037,7 +3044,7 @@ static bool ieee80211_amsdu_realloc_pad(struct ieee80211_local *local,
if (padding) {
*subframe_len += padding;
- memset(skb_put(skb, padding), 0, padding);
+ skb_put_zero(skb, padding);
}
return true;
@@ -3340,7 +3347,7 @@ static bool ieee80211_xmit_fast(struct ieee80211_sub_if_data *sdata,
}
memcpy(&eth, skb->data, ETH_HLEN - 2);
- hdr = (void *)skb_push(skb, extra_head);
+ hdr = skb_push(skb, extra_head);
memcpy(skb->data, fast_tx->hdr, fast_tx->hdr_len);
memcpy(skb->data + fast_tx->da_offs, eth.h_dest, ETH_ALEN);
memcpy(skb->data + fast_tx->sa_offs, eth.h_source, ETH_ALEN);
@@ -3867,7 +3874,7 @@ static void __ieee80211_beacon_add_tim(struct ieee80211_sub_if_data *sdata,
ps->dtim_count--;
}
- tim = pos = (u8 *) skb_put(skb, 6);
+ tim = pos = skb_put(skb, 6);
*pos++ = WLAN_EID_TIM;
*pos++ = 4;
*pos++ = ps->dtim_count;
@@ -4125,8 +4132,7 @@ __ieee80211_beacon_get(struct ieee80211_hw *hw,
goto out;
skb_reserve(skb, local->tx_headroom);
- memcpy(skb_put(skb, beacon->head_len), beacon->head,
- beacon->head_len);
+ skb_put_data(skb, beacon->head, beacon->head_len);
ieee80211_beacon_add_tim(sdata, &ap->ps, skb,
is_template);
@@ -4140,8 +4146,8 @@ __ieee80211_beacon_get(struct ieee80211_hw *hw,
}
if (beacon->tail)
- memcpy(skb_put(skb, beacon->tail_len),
- beacon->tail, beacon->tail_len);
+ skb_put_data(skb, beacon->tail,
+ beacon->tail_len);
} else
goto out;
} else if (sdata->vif.type == NL80211_IFTYPE_ADHOC) {
@@ -4164,8 +4170,7 @@ __ieee80211_beacon_get(struct ieee80211_hw *hw,
if (!skb)
goto out;
skb_reserve(skb, local->tx_headroom);
- memcpy(skb_put(skb, beacon->head_len), beacon->head,
- beacon->head_len);
+ skb_put_data(skb, beacon->head, beacon->head_len);
hdr = (struct ieee80211_hdr *) skb->data;
hdr->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT |
@@ -4200,8 +4205,7 @@ __ieee80211_beacon_get(struct ieee80211_hw *hw,
if (!skb)
goto out;
skb_reserve(skb, local->tx_headroom);
- memcpy(skb_put(skb, beacon->head_len), beacon->head,
- beacon->head_len);
+ skb_put_data(skb, beacon->head, beacon->head_len);
ieee80211_beacon_add_tim(sdata, &ifmsh->ps, skb, is_template);
if (offs) {
@@ -4209,8 +4213,7 @@ __ieee80211_beacon_get(struct ieee80211_hw *hw,
offs->tim_length = skb->len - beacon->head_len;
}
- memcpy(skb_put(skb, beacon->tail_len), beacon->tail,
- beacon->tail_len);
+ skb_put_data(skb, beacon->tail, beacon->tail_len);
} else {
WARN_ON(1);
goto out;
@@ -4330,7 +4333,7 @@ struct sk_buff *ieee80211_proberesp_get(struct ieee80211_hw *hw,
if (!skb)
goto out;
- memcpy(skb_put(skb, presp->len), presp->data, presp->len);
+ skb_put_data(skb, presp->data, presp->len);
hdr = (struct ieee80211_hdr *) skb->data;
memset(hdr->addr1, 0, sizeof(hdr->addr1));
@@ -4363,8 +4366,7 @@ struct sk_buff *ieee80211_pspoll_get(struct ieee80211_hw *hw,
skb_reserve(skb, local->hw.extra_tx_headroom);
- pspoll = (struct ieee80211_pspoll *) skb_put(skb, sizeof(*pspoll));
- memset(pspoll, 0, sizeof(*pspoll));
+ pspoll = skb_put_zero(skb, sizeof(*pspoll));
pspoll->frame_control = cpu_to_le16(IEEE80211_FTYPE_CTL |
IEEE80211_STYPE_PSPOLL);
pspoll->aid = cpu_to_le16(ifmgd->aid);
@@ -4401,9 +4403,7 @@ struct sk_buff *ieee80211_nullfunc_get(struct ieee80211_hw *hw,
skb_reserve(skb, local->hw.extra_tx_headroom);
- nullfunc = (struct ieee80211_hdr_3addr *) skb_put(skb,
- sizeof(*nullfunc));
- memset(nullfunc, 0, sizeof(*nullfunc));
+ nullfunc = skb_put_zero(skb, sizeof(*nullfunc));
nullfunc->frame_control = cpu_to_le16(IEEE80211_FTYPE_DATA |
IEEE80211_STYPE_NULLFUNC |
IEEE80211_FCTL_TODS);
@@ -4435,8 +4435,7 @@ struct sk_buff *ieee80211_probereq_get(struct ieee80211_hw *hw,
skb_reserve(skb, local->hw.extra_tx_headroom);
- hdr = (struct ieee80211_hdr_3addr *) skb_put(skb, sizeof(*hdr));
- memset(hdr, 0, sizeof(*hdr));
+ hdr = skb_put_zero(skb, sizeof(*hdr));
hdr->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT |
IEEE80211_STYPE_PROBE_REQ);
eth_broadcast_addr(hdr->addr1);
diff --git a/net/mac80211/util.c b/net/mac80211/util.c
index ac9ac6c35594..259698de569f 100644
--- a/net/mac80211/util.c
+++ b/net/mac80211/util.c
@@ -1242,8 +1242,7 @@ void ieee80211_send_auth(struct ieee80211_sub_if_data *sdata,
skb_reserve(skb, local->hw.extra_tx_headroom + IEEE80211_WEP_IV_LEN);
- mgmt = (struct ieee80211_mgmt *) skb_put(skb, 24 + 6);
- memset(mgmt, 0, 24 + 6);
+ mgmt = skb_put_zero(skb, 24 + 6);
mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT |
IEEE80211_STYPE_AUTH);
memcpy(mgmt->da, da, ETH_ALEN);
@@ -1253,7 +1252,7 @@ void ieee80211_send_auth(struct ieee80211_sub_if_data *sdata,
mgmt->u.auth.auth_transaction = cpu_to_le16(transaction);
mgmt->u.auth.status_code = cpu_to_le16(status);
if (extra)
- memcpy(skb_put(skb, extra_len), extra, extra_len);
+ skb_put_data(skb, extra, extra_len);
if (auth_alg == WLAN_AUTH_SHARED_KEY && transaction == 3) {
mgmt->frame_control |= cpu_to_le16(IEEE80211_FCTL_PROTECTED);
@@ -1293,8 +1292,7 @@ void ieee80211_send_deauth_disassoc(struct ieee80211_sub_if_data *sdata,
skb_reserve(skb, local->hw.extra_tx_headroom);
/* copy in frame */
- memcpy(skb_put(skb, IEEE80211_DEAUTH_FRAME_LEN),
- mgmt, IEEE80211_DEAUTH_FRAME_LEN);
+ skb_put_data(skb, mgmt, IEEE80211_DEAUTH_FRAME_LEN);
if (sdata->vif.type != NL80211_IFTYPE_STATION ||
!(sdata->u.mgd.flags & IEEE80211_STA_MFP_ENABLED))
@@ -2414,6 +2412,35 @@ u8 *ieee80211_ie_build_ht_oper(u8 *pos, struct ieee80211_sta_ht_cap *ht_cap,
return pos + sizeof(struct ieee80211_ht_operation);
}
+void ieee80211_ie_build_wide_bw_cs(u8 *pos,
+ const struct cfg80211_chan_def *chandef)
+{
+ *pos++ = WLAN_EID_WIDE_BW_CHANNEL_SWITCH; /* EID */
+ *pos++ = 3; /* IE length */
+ /* New channel width */
+ switch (chandef->width) {
+ case NL80211_CHAN_WIDTH_80:
+ *pos++ = IEEE80211_VHT_CHANWIDTH_80MHZ;
+ break;
+ case NL80211_CHAN_WIDTH_160:
+ *pos++ = IEEE80211_VHT_CHANWIDTH_160MHZ;
+ break;
+ case NL80211_CHAN_WIDTH_80P80:
+ *pos++ = IEEE80211_VHT_CHANWIDTH_80P80MHZ;
+ break;
+ default:
+ *pos++ = IEEE80211_VHT_CHANWIDTH_USE_HT;
+ }
+
+ /* new center frequency segment 0 */
+ *pos++ = ieee80211_frequency_to_channel(chandef->center_freq1);
+ /* new center frequency segment 1 */
+ if (chandef->center_freq2)
+ *pos++ = ieee80211_frequency_to_channel(chandef->center_freq2);
+ else
+ *pos++ = 0;
+}
+
u8 *ieee80211_ie_build_vht_oper(u8 *pos, struct ieee80211_sta_vht_cap *vht_cap,
const struct cfg80211_chan_def *chandef)
{
@@ -2964,13 +2991,13 @@ int ieee80211_send_action_csa(struct ieee80211_sub_if_data *sdata,
skb = dev_alloc_skb(local->tx_headroom + hdr_len +
5 + /* channel switch announcement element */
3 + /* secondary channel offset element */
+ 5 + /* wide bandwidth channel switch announcement */
8); /* mesh channel switch parameters element */
if (!skb)
return -ENOMEM;
skb_reserve(skb, local->tx_headroom);
- mgmt = (struct ieee80211_mgmt *)skb_put(skb, hdr_len);
- memset(mgmt, 0, hdr_len);
+ mgmt = skb_put_zero(skb, hdr_len);
mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT |
IEEE80211_STYPE_ACTION);
@@ -3022,6 +3049,13 @@ int ieee80211_send_action_csa(struct ieee80211_sub_if_data *sdata,
pos += 2;
}
+ if (csa_settings->chandef.width == NL80211_CHAN_WIDTH_80 ||
+ csa_settings->chandef.width == NL80211_CHAN_WIDTH_80P80 ||
+ csa_settings->chandef.width == NL80211_CHAN_WIDTH_160) {
+ skb_put(skb, 5);
+ ieee80211_ie_build_wide_bw_cs(pos, &csa_settings->chandef);
+ }
+
ieee80211_tx_skb(sdata, skb);
return 0;
}
diff --git a/net/mac80211/wpa.c b/net/mac80211/wpa.c
index cc19614ff4e6..0d722ea98a1b 100644
--- a/net/mac80211/wpa.c
+++ b/net/mac80211/wpa.c
@@ -949,7 +949,7 @@ ieee80211_crypto_aes_cmac_encrypt(struct ieee80211_tx_data *tx)
if (WARN_ON(skb_tailroom(skb) < sizeof(*mmie)))
return TX_DROP;
- mmie = (struct ieee80211_mmie *) skb_put(skb, sizeof(*mmie));
+ mmie = skb_put(skb, sizeof(*mmie));
mmie->element_id = WLAN_EID_MMIE;
mmie->length = sizeof(*mmie) - 2;
mmie->key_id = cpu_to_le16(key->conf.keyidx);
@@ -993,7 +993,7 @@ ieee80211_crypto_aes_cmac_256_encrypt(struct ieee80211_tx_data *tx)
if (WARN_ON(skb_tailroom(skb) < sizeof(*mmie)))
return TX_DROP;
- mmie = (struct ieee80211_mmie_16 *)skb_put(skb, sizeof(*mmie));
+ mmie = skb_put(skb, sizeof(*mmie));
mmie->element_id = WLAN_EID_MMIE;
mmie->length = sizeof(*mmie) - 2;
mmie->key_id = cpu_to_le16(key->conf.keyidx);
@@ -1138,7 +1138,7 @@ ieee80211_crypto_aes_gmac_encrypt(struct ieee80211_tx_data *tx)
if (WARN_ON(skb_tailroom(skb) < sizeof(*mmie)))
return TX_DROP;
- mmie = (struct ieee80211_mmie_16 *)skb_put(skb, sizeof(*mmie));
+ mmie = skb_put(skb, sizeof(*mmie));
mmie->element_id = WLAN_EID_MMIE;
mmie->length = sizeof(*mmie) - 2;
mmie->key_id = cpu_to_le16(key->conf.keyidx);