From 99cd25810e326c62f5a51fa6f0dd1e848060680f Mon Sep 17 00:00:00 2001 From: Kirtika Ruchandani Date: Mon, 21 Nov 2016 21:44:24 -0800 Subject: mac80211: Remove unused 'struct ieee80211_rx_status' ptr Commit 554891e63a29 introduced 'struct ieee80211_rx_status' in ieee80211_rx_h_defragment but did not use it. Compiling with W=1 gives the following warning, fix it. net/mac80211/rx.c: In function ‘ieee80211_rx_h_defragment’: net/mac80211/rx.c:1911:30: warning: variable ‘status’ set but not used [-Wunused-but-set-variable] Fixes: 554891e63a29 ("mac80211: move packet flags into packet") Cc: Johannes Berg Cc: John W. Linville Signed-off-by: Kirtika Ruchandani Signed-off-by: Johannes Berg --- net/mac80211/rx.c | 4 ---- 1 file changed, 4 deletions(-) (limited to 'net/mac80211') diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c index eeab7250f4b9..d2a00f2a6efe 100644 --- a/net/mac80211/rx.c +++ b/net/mac80211/rx.c @@ -1908,7 +1908,6 @@ ieee80211_rx_h_defragment(struct ieee80211_rx_data *rx) unsigned int frag, seq; struct ieee80211_fragment_entry *entry; struct sk_buff *skb; - struct ieee80211_rx_status *status; hdr = (struct ieee80211_hdr *)rx->skb->data; fc = hdr->frame_control; @@ -2034,9 +2033,6 @@ ieee80211_rx_h_defragment(struct ieee80211_rx_data *rx) dev_kfree_skb(skb); } - /* Complete frame has been reassembled - process it now */ - status = IEEE80211_SKB_RXCB(rx->skb); - out: ieee80211_led_rx(rx->local); out_no_led: -- cgit v1.2.3 From 872684b1f7de40b95dac51245f3aad208528a6c3 Mon Sep 17 00:00:00 2001 From: Kirtika Ruchandani Date: Mon, 21 Nov 2016 22:04:46 -0800 Subject: mac80211: Remove unused 'rates_idx' variable Commit f027c2aca0cf introduced 'rates_idx' in ieee80211_tx_status_noskb but did not use it. Compiling with W=1 gives the following warning, fix it. mac80211/status.c: In function ‘ieee80211_tx_status_noskb’: mac80211/status.c:636:6: warning: variable ‘rates_idx’ set but not used [-Wunused-but-set-variable] This is a harmless warning, and is only being fixed to reduce the noise generated with W=1. Fixes: f027c2aca0cf ("mac80211: add ieee80211_tx_status_noskb") Cc: Johannes Berg Cc: Felix Fietkau Signed-off-by: Kirtika Ruchandani Signed-off-by: Johannes Berg --- net/mac80211/status.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'net/mac80211') diff --git a/net/mac80211/status.c b/net/mac80211/status.c index ddf71c648cab..f7c5ae597639 100644 --- a/net/mac80211/status.c +++ b/net/mac80211/status.c @@ -633,10 +633,9 @@ void ieee80211_tx_status_noskb(struct ieee80211_hw *hw, struct ieee80211_local *local = hw_to_local(hw); struct ieee80211_supported_band *sband; int retry_count; - int rates_idx; bool acked, noack_success; - rates_idx = ieee80211_tx_get_rates(hw, info, &retry_count); + ieee80211_tx_get_rates(hw, info, &retry_count); sband = hw->wiphy->bands[info->band]; -- cgit v1.2.3 From fb803becb1180d3f940a634f073981e0b72d7030 Mon Sep 17 00:00:00 2001 From: Kirtika Ruchandani Date: Mon, 21 Nov 2016 22:54:16 -0800 Subject: mac80211: Remove unused 'struct rate_control_ref' variable Commit 3b17fbf87d5d introduced sta_get_expected_throughput() leaving variable 'struct rate_control_ref* ref' set but unused. Compiling with W=1 gives the following warning, fix it. net/mac80211/sta_info.c: In function ‘sta_set_sinfo’: net/mac80211/sta_info.c:2052:27: warning: variable ‘ref’ set but not used [-Wunused-but-set-variable] Fixes: 3b17fbf87d5d ("mac80211: mesh: Add support for HW RC implementation") Cc: Johannes Berg Cc: Maxim Altshul Signed-off-by: Kirtika Ruchandani Signed-off-by: Johannes Berg --- net/mac80211/sta_info.c | 4 ---- 1 file changed, 4 deletions(-) (limited to 'net/mac80211') diff --git a/net/mac80211/sta_info.c b/net/mac80211/sta_info.c index 1711bae4abf2..4ab75a9d70c7 100644 --- a/net/mac80211/sta_info.c +++ b/net/mac80211/sta_info.c @@ -2049,16 +2049,12 @@ void sta_set_sinfo(struct sta_info *sta, struct station_info *sinfo) { struct ieee80211_sub_if_data *sdata = sta->sdata; struct ieee80211_local *local = sdata->local; - struct rate_control_ref *ref = NULL; u32 thr = 0; int i, ac, cpu; struct ieee80211_sta_rx_stats *last_rxstats; last_rxstats = sta_get_last_rx_stats(sta); - if (test_sta_flag(sta, WLAN_STA_RATE_CONTROL)) - ref = local->rate_ctrl; - sinfo->generation = sdata->local->sta_generation; /* do before driver, so beacon filtering drivers have a -- cgit v1.2.3 From b7f2405c6bd8ae0125a974308f649637cdc81f80 Mon Sep 17 00:00:00 2001 From: Kirtika Ruchandani Date: Wed, 23 Nov 2016 20:45:36 -0800 Subject: mac80211: Remove unused 'i' variable Commit 5bcae31d9 (mac80211: implement multi-vif in-place reservations) introduced ieee80211_vif_use_reserved_switch() with a counter variable 'i' that is set but not used. Compiling with W=1 gives the following warning, fix it. net/mac80211/chan.c: In function ‘ieee80211_vif_use_reserved_switch’: net/mac80211/chan.c:1273:6: warning: variable ‘i’ set but not used [-Wunused-but-set-variable] This is a harmless warning, and is only being fixed to reduce the noise obtained with W=1 in the kernel. Fixes: 5bcae31d9 ("mac80211: implement multi-vif in-place reservations") Cc: Michal Kazior Cc: Johannes Berg Signed-off-by: Kirtika Ruchandani Signed-off-by: Johannes Berg --- net/mac80211/chan.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) (limited to 'net/mac80211') diff --git a/net/mac80211/chan.c b/net/mac80211/chan.c index e75cbf6ecc26..7550fd264286 100644 --- a/net/mac80211/chan.c +++ b/net/mac80211/chan.c @@ -1270,7 +1270,7 @@ static int ieee80211_vif_use_reserved_switch(struct ieee80211_local *local) struct ieee80211_sub_if_data *sdata, *sdata_tmp; struct ieee80211_chanctx *ctx, *ctx_tmp, *old_ctx; struct ieee80211_chanctx *new_ctx = NULL; - int i, err, n_assigned, n_reserved, n_ready; + int err, n_assigned, n_reserved, n_ready; int n_ctx = 0, n_vifs_switch = 0, n_vifs_assign = 0, n_vifs_ctxless = 0; lockdep_assert_held(&local->mtx); @@ -1391,8 +1391,6 @@ static int ieee80211_vif_use_reserved_switch(struct ieee80211_local *local) * Update all structures, values and pointers to point to new channel * context(s). */ - - i = 0; list_for_each_entry(ctx, &local->chanctx_list, list) { if (ctx->replace_state != IEEE80211_CHANCTX_REPLACES_OTHER) continue; -- cgit v1.2.3 From cd5861bde0299fd5189a6b9e0d1e31e205064fc6 Mon Sep 17 00:00:00 2001 From: Kirtika Ruchandani Date: Wed, 23 Nov 2016 20:45:49 -0800 Subject: mac80211: Remove unused 'len' variable Commit 633e27132625 (mac80211: split sched scan IEs) introduced the len variable to keep track of the return value of ieee80211_build_preq_ies() but did not use it. Compiling with W=1 gives the following warning, fix it. net/mac80211/scan.c: In function ‘__ieee80211_request_sched_scan_start’: net/mac80211/scan.c:1123:9: warning: variable ‘len’ set but not used [-Wunused-but-set-variable] This is a harmless warning and is only being fixed to reduce the noise with W=1 in the kernel. Fixes: 633e27132625 ("mac80211: split sched scan IEs") Cc: David Spinadel Cc: Alexander Bondar Cc: Johannes Berg Signed-off-by: Kirtika Ruchandani Signed-off-by: Johannes Berg --- net/mac80211/scan.c | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) (limited to 'net/mac80211') diff --git a/net/mac80211/scan.c b/net/mac80211/scan.c index 23d8ac829279..faab3c490d2b 100644 --- a/net/mac80211/scan.c +++ b/net/mac80211/scan.c @@ -1120,7 +1120,6 @@ int __ieee80211_request_sched_scan_start(struct ieee80211_sub_if_data *sdata, u32 rate_masks[NUM_NL80211_BANDS] = {}; u8 bands_used = 0; u8 *ie; - size_t len; iebufsz = local->scan_ies_len + req->ie_len; @@ -1145,10 +1144,9 @@ int __ieee80211_request_sched_scan_start(struct ieee80211_sub_if_data *sdata, ieee80211_prepare_scan_chandef(&chandef, req->scan_width); - len = ieee80211_build_preq_ies(local, ie, num_bands * iebufsz, - &sched_scan_ies, req->ie, - req->ie_len, bands_used, - rate_masks, &chandef); + ieee80211_build_preq_ies(local, ie, num_bands * iebufsz, + &sched_scan_ies, req->ie, + req->ie_len, bands_used, rate_masks, &chandef); ret = drv_sched_scan_start(local, sdata, req, &sched_scan_ies); if (ret == 0) { -- cgit v1.2.3 From 148f284b23061b6de4024423a6606437cc427f1c Mon Sep 17 00:00:00 2001 From: Kirtika Ruchandani Date: Wed, 23 Nov 2016 20:46:14 -0800 Subject: mac80211: Remove unused 'sband' and 'local' variables Commit b1bce14a7954 (mac80211: update opmode when adding new station) refactored ieee80211_vht_handle_opmode into __ieee80211_vht_handle_opmode and ieee80211_vht_handle_opmode leaving a set but unused variable (sband) in the former. Compiling with W=1 gives the following warning, fix it. net/mac80211/vht.c: In function ‘__ieee80211_vht_handle_opmode’: net/mac80211/vht.c:424:35: warning: variable ‘sband’ set but not used [-Wunused-but-set-variable] Remove 'struct ieee80211_local* local' as well, it was only used to set sband. This is a harmless warning, and is only being fixed to reduce the noise with W=1 in the kernel. Fixes: b1bce14a7954 ("mac80211: update opmode when adding new station") Cc: Marek Kwaczynski Cc: Johannes Berg Signed-off-by: Kirtika Ruchandani Signed-off-by: Johannes Berg --- net/mac80211/vht.c | 4 ---- 1 file changed, 4 deletions(-) (limited to 'net/mac80211') diff --git a/net/mac80211/vht.c b/net/mac80211/vht.c index 6832bf6ab69f..d5a56e039106 100644 --- a/net/mac80211/vht.c +++ b/net/mac80211/vht.c @@ -436,14 +436,10 @@ u32 __ieee80211_vht_handle_opmode(struct ieee80211_sub_if_data *sdata, struct sta_info *sta, u8 opmode, enum nl80211_band band) { - struct ieee80211_local *local = sdata->local; - struct ieee80211_supported_band *sband; enum ieee80211_sta_rx_bandwidth new_bw; u32 changed = 0; u8 nss; - sband = local->hw.wiphy->bands[band]; - /* ignore - no support for BF yet */ if (opmode & IEEE80211_OPMODE_NOTIF_RX_NSS_TYPE_BF) return 0; -- cgit v1.2.3 From ab7257251cc63eef5fa6702c3c616c6e2524d777 Mon Sep 17 00:00:00 2001 From: Kirtika Ruchandani Date: Wed, 23 Nov 2016 20:46:27 -0800 Subject: mac80211: Remove unused 'beaconint_us' variable Commit 4a733ef1bea7 (mac80211: remove PM-QoS listener) removed all use of 'beaconint_us' from ieee80211_recalc_ps() but left the variable intact. Compiling with W=1 gives the following warning, fix it. net/mac80211/mlme.c: In function ‘ieee80211_recalc_ps’: net/mac80211/mlme.c:1481:7: warning: variable ‘beaconint_us’ set but not used [-Wunused-but-set-variable] iee80211_tu_to_usec has no side-effects and is safe to remove. Fixes: 4a733ef1bea7 ("mac80211: remove PM-QoS listener") Cc: Johannes Berg Signed-off-by: Kirtika Ruchandani Signed-off-by: Johannes Berg --- net/mac80211/mlme.c | 4 ---- 1 file changed, 4 deletions(-) (limited to 'net/mac80211') diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index 098ce9b179ee..8a6344518674 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c @@ -1486,10 +1486,6 @@ void ieee80211_recalc_ps(struct ieee80211_local *local) if (count == 1 && ieee80211_powersave_allowed(found)) { u8 dtimper = found->u.mgd.dtim_period; - s32 beaconint_us; - - beaconint_us = ieee80211_tu_to_usec( - found->vif.bss_conf.beacon_int); timeout = local->dynamic_ps_forced_timeout; if (timeout < 0) -- cgit v1.2.3 From ebceec860fc370b2f4c23e95c51daa932e047913 Mon Sep 17 00:00:00 2001 From: Michael Braun Date: Tue, 22 Nov 2016 11:52:18 +0100 Subject: mac80211: multicast to unicast conversion Add the ability for an AP (and associated VLANs) to perform multicast-to-unicast conversion for ARP, IPv4 and IPv6 frames (possibly within 802.1Q). If enabled, such frames are to be sent to each station separately, with the DA replaced by their own MAC address rather than the group address. Note that this may break certain expectations of the receiver, such as the ability to drop unicast IP packets received within multicast L2 frames, or the ability to not send ICMP destination unreachable messages for packets received in L2 multicast (which is required, but the receiver can't tell the difference if this new option is enabled.) This also doesn't implement the 802.11 DMS (directed multicast service). Signed-off-by: Michael Braun [use true/false, rename label to the correct "multicast", use __be16 for ethertype and network order for constants] Signed-off-by: Johannes Berg --- net/mac80211/cfg.c | 12 +++++ net/mac80211/debugfs_netdev.c | 3 ++ net/mac80211/ieee80211_i.h | 1 + net/mac80211/tx.c | 122 +++++++++++++++++++++++++++++++++++++++++- 4 files changed, 137 insertions(+), 1 deletion(-) (limited to 'net/mac80211') diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c index e91e503bf992..a0be2f6cd121 100644 --- a/net/mac80211/cfg.c +++ b/net/mac80211/cfg.c @@ -3563,6 +3563,17 @@ void ieee80211_nan_func_match(struct ieee80211_vif *vif, } EXPORT_SYMBOL(ieee80211_nan_func_match); +static int ieee80211_set_multicast_to_unicast(struct wiphy *wiphy, + struct net_device *dev, + const bool enabled) +{ + struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); + + sdata->u.ap.multicast_to_unicast = enabled; + + return 0; +} + const struct cfg80211_ops mac80211_config_ops = { .add_virtual_intf = ieee80211_add_iface, .del_virtual_intf = ieee80211_del_iface, @@ -3653,4 +3664,5 @@ const struct cfg80211_ops mac80211_config_ops = { .nan_change_conf = ieee80211_nan_change_conf, .add_nan_func = ieee80211_add_nan_func, .del_nan_func = ieee80211_del_nan_func, + .set_multicast_to_unicast = ieee80211_set_multicast_to_unicast, }; diff --git a/net/mac80211/debugfs_netdev.c b/net/mac80211/debugfs_netdev.c index 1a05f85cb1f0..8f5fff8b2040 100644 --- a/net/mac80211/debugfs_netdev.c +++ b/net/mac80211/debugfs_netdev.c @@ -519,6 +519,8 @@ static ssize_t ieee80211_if_fmt_aqm( } IEEE80211_IF_FILE_R(aqm); +IEEE80211_IF_FILE(multicast_to_unicast, u.ap.multicast_to_unicast, HEX); + /* IBSS attributes */ static ssize_t ieee80211_if_fmt_tsf( const struct ieee80211_sub_if_data *sdata, char *buf, int buflen) @@ -683,6 +685,7 @@ static void add_ap_files(struct ieee80211_sub_if_data *sdata) DEBUGFS_ADD(dtim_count); DEBUGFS_ADD(num_buffered_multicast); DEBUGFS_ADD_MODE(tkip_mic_test, 0200); + DEBUGFS_ADD_MODE(multicast_to_unicast, 0600); } static void add_vlan_files(struct ieee80211_sub_if_data *sdata) diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h index d37a577f63a1..a3af14e3e64d 100644 --- a/net/mac80211/ieee80211_i.h +++ b/net/mac80211/ieee80211_i.h @@ -297,6 +297,7 @@ struct ieee80211_if_ap { driver_smps_mode; /* smps mode request */ struct work_struct request_smps_work; + bool multicast_to_unicast; }; struct ieee80211_if_wds { diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c index 2c21b7039136..a39c0f07021b 100644 --- a/net/mac80211/tx.c +++ b/net/mac80211/tx.c @@ -16,6 +16,7 @@ #include #include #include +#include #include #include #include @@ -3573,6 +3574,115 @@ void __ieee80211_subif_start_xmit(struct sk_buff *skb, rcu_read_unlock(); } +static int ieee80211_change_da(struct sk_buff *skb, struct sta_info *sta) +{ + struct ethhdr *eth; + int err; + + err = skb_ensure_writable(skb, ETH_HLEN); + if (unlikely(err)) + return err; + + eth = (void *)skb->data; + ether_addr_copy(eth->h_dest, sta->sta.addr); + + return 0; +} + +static bool ieee80211_multicast_to_unicast(struct sk_buff *skb, + struct net_device *dev) +{ + struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); + const struct ethhdr *eth = (void *)skb->data; + const struct vlan_ethhdr *ethvlan = (void *)skb->data; + __be16 ethertype; + + if (likely(!is_multicast_ether_addr(eth->h_dest))) + return false; + + switch (sdata->vif.type) { + case NL80211_IFTYPE_AP_VLAN: + if (sdata->u.vlan.sta) + return false; + if (sdata->wdev.use_4addr) + return false; + /* fall through */ + case NL80211_IFTYPE_AP: + /* check runtime toggle for this bss */ + if (!sdata->bss->multicast_to_unicast) + return false; + break; + default: + return false; + } + + /* multicast to unicast conversion only for some payload */ + ethertype = eth->h_proto; + if (ethertype == htons(ETH_P_8021Q) && skb->len >= VLAN_ETH_HLEN) + ethertype = ethvlan->h_vlan_encapsulated_proto; + switch (ethertype) { + case htons(ETH_P_ARP): + case htons(ETH_P_IP): + case htons(ETH_P_IPV6): + break; + default: + return false; + } + + return true; +} + +static void +ieee80211_convert_to_unicast(struct sk_buff *skb, struct net_device *dev, + struct sk_buff_head *queue) +{ + struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); + struct ieee80211_local *local = sdata->local; + const struct ethhdr *eth = (struct ethhdr *)skb->data; + struct sta_info *sta, *first = NULL; + struct sk_buff *cloned_skb; + + rcu_read_lock(); + + list_for_each_entry_rcu(sta, &local->sta_list, list) { + if (sdata != sta->sdata) + /* AP-VLAN mismatch */ + continue; + if (unlikely(ether_addr_equal(eth->h_source, sta->sta.addr))) + /* do not send back to source */ + continue; + if (!first) { + first = sta; + continue; + } + cloned_skb = skb_clone(skb, GFP_ATOMIC); + if (!cloned_skb) + goto multicast; + if (unlikely(ieee80211_change_da(cloned_skb, sta))) { + dev_kfree_skb(cloned_skb); + goto multicast; + } + __skb_queue_tail(queue, cloned_skb); + } + + if (likely(first)) { + if (unlikely(ieee80211_change_da(skb, first))) + goto multicast; + __skb_queue_tail(queue, skb); + } else { + /* no STA connected, drop */ + kfree_skb(skb); + skb = NULL; + } + + goto out; +multicast: + __skb_queue_purge(queue); + __skb_queue_tail(queue, skb); +out: + rcu_read_unlock(); +} + /** * ieee80211_subif_start_xmit - netif start_xmit function for 802.3 vifs * @skb: packet to be sent @@ -3583,7 +3693,17 @@ void __ieee80211_subif_start_xmit(struct sk_buff *skb, netdev_tx_t ieee80211_subif_start_xmit(struct sk_buff *skb, struct net_device *dev) { - __ieee80211_subif_start_xmit(skb, dev, 0); + if (unlikely(ieee80211_multicast_to_unicast(skb, dev))) { + struct sk_buff_head queue; + + __skb_queue_head_init(&queue); + ieee80211_convert_to_unicast(skb, dev, &queue); + while ((skb = __skb_dequeue(&queue))) + __ieee80211_subif_start_xmit(skb, dev, 0); + } else { + __ieee80211_subif_start_xmit(skb, dev, 0); + } + return NETDEV_TX_OK; } -- cgit v1.2.3 From 11197d006bcfabf0173a7820a163fcaac420d10e Mon Sep 17 00:00:00 2001 From: Masashi Honma Date: Wed, 30 Nov 2016 09:06:04 +0900 Subject: mac80211: Suppress NEW_PEER_CANDIDATE event if no room Previously, kernel sends NEW_PEER_CANDIDATE event to user land even if the found peer does not have any room to accept other peer. This causes continuous connection trials. Signed-off-by: Masashi Honma Signed-off-by: Johannes Berg --- net/mac80211/mesh_plink.c | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) (limited to 'net/mac80211') diff --git a/net/mac80211/mesh_plink.c b/net/mac80211/mesh_plink.c index 7fcdcf622655..fcba70e57073 100644 --- a/net/mac80211/mesh_plink.c +++ b/net/mac80211/mesh_plink.c @@ -505,12 +505,14 @@ mesh_sta_info_alloc(struct ieee80211_sub_if_data *sdata, u8 *addr, /* Userspace handles station allocation */ if (sdata->u.mesh.user_mpm || - sdata->u.mesh.security & IEEE80211_MESH_SEC_AUTHED) - cfg80211_notify_new_peer_candidate(sdata->dev, addr, - elems->ie_start, - elems->total_len, - GFP_KERNEL); - else + sdata->u.mesh.security & IEEE80211_MESH_SEC_AUTHED) { + if (mesh_peer_accepts_plinks(elems) && + mesh_plink_availables(sdata)) + cfg80211_notify_new_peer_candidate(sdata->dev, addr, + elems->ie_start, + elems->total_len, + GFP_KERNEL); + } else sta = __mesh_sta_info_alloc(sdata, addr); return sta; -- cgit v1.2.3 From 4a5eccaa93505cd186939a01d7c115568b1881a6 Mon Sep 17 00:00:00 2001 From: Ben Greear Date: Mon, 5 Dec 2016 10:58:30 -0800 Subject: mac80211: Show pending txqlen in debugfs. Could be useful for debugging memory consumption issues, and perhaps power-save as well. Signed-off-by: Ben Greear Signed-off-by: Johannes Berg --- net/mac80211/debugfs.c | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) (limited to 'net/mac80211') diff --git a/net/mac80211/debugfs.c b/net/mac80211/debugfs.c index e02ba42ca827..f62cd0e13c58 100644 --- a/net/mac80211/debugfs.c +++ b/net/mac80211/debugfs.c @@ -243,6 +243,31 @@ static ssize_t hwflags_read(struct file *file, char __user *user_buf, return rv; } +static ssize_t misc_read(struct file *file, char __user *user_buf, + size_t count, loff_t *ppos) +{ + struct ieee80211_local *local = file->private_data; + /* Max len of each line is 16 characters, plus 9 for 'pending:\n' */ + size_t bufsz = IEEE80211_MAX_QUEUES * 16 + 9; + char *buf = kzalloc(bufsz, GFP_KERNEL); + char *pos = buf, *end = buf + bufsz - 1; + ssize_t rv; + int i; + int ln; + + pos += scnprintf(pos, end - pos, "pending:\n"); + + for (i = 0; i < IEEE80211_MAX_QUEUES; i++) { + ln = skb_queue_len(&local->pending[i]); + pos += scnprintf(pos, end - pos, "[%i] %d\n", + i, ln); + } + + rv = simple_read_from_buffer(user_buf, count, ppos, buf, strlen(buf)); + kfree(buf); + return rv; +} + static ssize_t queues_read(struct file *file, char __user *user_buf, size_t count, loff_t *ppos) { @@ -263,6 +288,7 @@ static ssize_t queues_read(struct file *file, char __user *user_buf, DEBUGFS_READONLY_FILE_OPS(hwflags); DEBUGFS_READONLY_FILE_OPS(queues); +DEBUGFS_READONLY_FILE_OPS(misc); /* statistics stuff */ @@ -331,6 +357,7 @@ void debugfs_hw_add(struct ieee80211_local *local) DEBUGFS_ADD(total_ps_buffered); DEBUGFS_ADD(wep_iv); DEBUGFS_ADD(queues); + DEBUGFS_ADD(misc); #ifdef CONFIG_PM DEBUGFS_ADD_MODE(reset, 0200); #endif -- cgit v1.2.3 From 76f43b4c0a9337af22827d78de4f2b8fd5328489 Mon Sep 17 00:00:00 2001 From: Masashi Honma Date: Thu, 8 Dec 2016 10:15:50 +0900 Subject: mac80211: Remove invalid flag operations in mesh TSF synchronization mesh_sync_offset_adjust_tbtt() implements Extensible synchronization framework ([1] 13.13.2 Extensible synchronization framework). It shall not operate the flag "TBTT Adjusting subfield" ([1] 8.4.2.100.8 Mesh Capability), since it is used only for MBCA ([1] 13.13.4 Mesh beacon collision avoidance, see 13.13.4.4.3 TBTT scanning and adjustment procedures for detail). So this patch remove the flag operations. [1] IEEE Std 802.11 2012 Signed-off-by: Masashi Honma [remove adjusting_tbtt entirely, since it's now unused] Signed-off-by: Johannes Berg --- net/mac80211/ieee80211_i.h | 1 - net/mac80211/mesh.c | 3 --- net/mac80211/mesh_sync.c | 11 ----------- 3 files changed, 15 deletions(-) (limited to 'net/mac80211') diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h index a3af14e3e64d..03e3230479f3 100644 --- a/net/mac80211/ieee80211_i.h +++ b/net/mac80211/ieee80211_i.h @@ -689,7 +689,6 @@ struct ieee80211_if_mesh { const struct ieee80211_mesh_sync_ops *sync_ops; s64 sync_offset_clockdrift_max; spinlock_t sync_offset_lock; - bool adjusting_tbtt; /* mesh power save */ enum nl80211_mesh_power_mode nonpeer_pm; int ps_peers_light_sleep; diff --git a/net/mac80211/mesh.c b/net/mac80211/mesh.c index 42120d965263..b9628374dcbd 100644 --- a/net/mac80211/mesh.c +++ b/net/mac80211/mesh.c @@ -279,8 +279,6 @@ int mesh_add_meshconf_ie(struct ieee80211_sub_if_data *sdata, /* Mesh PS mode. See IEEE802.11-2012 8.4.2.100.8 */ *pos |= ifmsh->ps_peers_deep_sleep ? IEEE80211_MESHCONF_CAPAB_POWER_SAVE_LEVEL : 0x00; - *pos++ |= ifmsh->adjusting_tbtt ? - IEEE80211_MESHCONF_CAPAB_TBTT_ADJUSTING : 0x00; *pos++ = 0x00; return 0; @@ -850,7 +848,6 @@ int ieee80211_start_mesh(struct ieee80211_sub_if_data *sdata) ifmsh->mesh_cc_id = 0; /* Disabled */ /* register sync ops from extensible synchronization framework */ ifmsh->sync_ops = ieee80211_mesh_sync_ops_get(ifmsh->mesh_sp_id); - ifmsh->adjusting_tbtt = false; ifmsh->sync_offset_clockdrift_max = 0; set_bit(MESH_WORK_HOUSEKEEPING, &ifmsh->wrkq_flags); ieee80211_mesh_root_setup(ifmsh); diff --git a/net/mac80211/mesh_sync.c b/net/mac80211/mesh_sync.c index faca22cd02b5..75608c07dc7b 100644 --- a/net/mac80211/mesh_sync.c +++ b/net/mac80211/mesh_sync.c @@ -123,7 +123,6 @@ static void mesh_sync_offset_rx_bcn_presp(struct ieee80211_sub_if_data *sdata, */ if (elems->mesh_config && mesh_peer_tbtt_adjusting(elems)) { - clear_sta_flag(sta, WLAN_STA_TOFFSET_KNOWN); msync_dbg(sdata, "STA %pM : is adjusting TBTT\n", sta->sta.addr); goto no_sync; @@ -172,11 +171,9 @@ static void mesh_sync_offset_adjust_tbtt(struct ieee80211_sub_if_data *sdata, struct beacon_data *beacon) { struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh; - u8 cap; WARN_ON(ifmsh->mesh_sp_id != IEEE80211_SYNC_METHOD_NEIGHBOR_OFFSET); WARN_ON(!rcu_read_lock_held()); - cap = beacon->meshconf->meshconf_cap; spin_lock_bh(&ifmsh->sync_offset_lock); @@ -190,21 +187,13 @@ static void mesh_sync_offset_adjust_tbtt(struct ieee80211_sub_if_data *sdata, "TBTT : kicking off TBTT adjustment with clockdrift_max=%lld\n", ifmsh->sync_offset_clockdrift_max); set_bit(MESH_WORK_DRIFT_ADJUST, &ifmsh->wrkq_flags); - - ifmsh->adjusting_tbtt = true; } else { msync_dbg(sdata, "TBTT : max clockdrift=%lld; too small to adjust\n", (long long)ifmsh->sync_offset_clockdrift_max); ifmsh->sync_offset_clockdrift_max = 0; - - ifmsh->adjusting_tbtt = false; } spin_unlock_bh(&ifmsh->sync_offset_lock); - - beacon->meshconf->meshconf_cap = ifmsh->adjusting_tbtt ? - IEEE80211_MESHCONF_CAPAB_TBTT_ADJUSTING | cap : - ~IEEE80211_MESHCONF_CAPAB_TBTT_ADJUSTING & cap; } static const struct sync_method sync_methods[] = { -- cgit v1.2.3 From 445cd452fe5187e676eef02c917c9e5f837c749e Mon Sep 17 00:00:00 2001 From: Masashi Honma Date: Thu, 8 Dec 2016 10:15:51 +0900 Subject: mac80211: Use appropriate name for functions and messages These functions drifts TSF timers, not TBTT. Signed-off-by: Masashi Honma Signed-off-by: Johannes Berg --- net/mac80211/ieee80211_i.h | 4 ++-- net/mac80211/mesh.c | 2 +- net/mac80211/mesh.h | 2 +- net/mac80211/mesh_sync.c | 16 ++++++++-------- net/mac80211/tx.c | 2 +- 5 files changed, 13 insertions(+), 13 deletions(-) (limited to 'net/mac80211') diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h index 03e3230479f3..e5d73118d08f 100644 --- a/net/mac80211/ieee80211_i.h +++ b/net/mac80211/ieee80211_i.h @@ -625,8 +625,8 @@ struct ieee80211_mesh_sync_ops { struct ieee80211_rx_status *rx_status); /* should be called with beacon_data under RCU read lock */ - void (*adjust_tbtt)(struct ieee80211_sub_if_data *sdata, - struct beacon_data *beacon); + void (*adjust_tsf)(struct ieee80211_sub_if_data *sdata, + struct beacon_data *beacon); /* add other framework functions here */ }; diff --git a/net/mac80211/mesh.c b/net/mac80211/mesh.c index b9628374dcbd..cc2a63bd233f 100644 --- a/net/mac80211/mesh.c +++ b/net/mac80211/mesh.c @@ -1346,7 +1346,7 @@ void ieee80211_mesh_work(struct ieee80211_sub_if_data *sdata) ieee80211_mesh_rootpath(sdata); if (test_and_clear_bit(MESH_WORK_DRIFT_ADJUST, &ifmsh->wrkq_flags)) - mesh_sync_adjust_tbtt(sdata); + mesh_sync_adjust_tsf(sdata); if (test_and_clear_bit(MESH_WORK_MBSS_CHANGED, &ifmsh->wrkq_flags)) mesh_bss_info_changed(sdata); diff --git a/net/mac80211/mesh.h b/net/mac80211/mesh.h index 26b9ccbe1fce..7e5f271e3c30 100644 --- a/net/mac80211/mesh.h +++ b/net/mac80211/mesh.h @@ -341,7 +341,7 @@ static inline bool mesh_path_sel_is_hwmp(struct ieee80211_sub_if_data *sdata) } void mesh_path_flush_by_iface(struct ieee80211_sub_if_data *sdata); -void mesh_sync_adjust_tbtt(struct ieee80211_sub_if_data *sdata); +void mesh_sync_adjust_tsf(struct ieee80211_sub_if_data *sdata); void ieee80211s_stop(void); #else static inline bool mesh_path_sel_is_hwmp(struct ieee80211_sub_if_data *sdata) diff --git a/net/mac80211/mesh_sync.c b/net/mac80211/mesh_sync.c index 75608c07dc7b..a435f094a82e 100644 --- a/net/mac80211/mesh_sync.c +++ b/net/mac80211/mesh_sync.c @@ -12,7 +12,7 @@ #include "mesh.h" #include "driver-ops.h" -/* This is not in the standard. It represents a tolerable tbtt drift below +/* This is not in the standard. It represents a tolerable tsf drift below * which we do no TSF adjustment. */ #define TOFFSET_MINIMUM_ADJUSTMENT 10 @@ -46,7 +46,7 @@ static bool mesh_peer_tbtt_adjusting(struct ieee802_11_elems *ie) IEEE80211_MESHCONF_CAPAB_TBTT_ADJUSTING) != 0; } -void mesh_sync_adjust_tbtt(struct ieee80211_sub_if_data *sdata) +void mesh_sync_adjust_tsf(struct ieee80211_sub_if_data *sdata) { struct ieee80211_local *local = sdata->local; struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh; @@ -57,12 +57,12 @@ void mesh_sync_adjust_tbtt(struct ieee80211_sub_if_data *sdata) spin_lock_bh(&ifmsh->sync_offset_lock); if (ifmsh->sync_offset_clockdrift_max < beacon_int_fraction) { - msync_dbg(sdata, "TBTT : max clockdrift=%lld; adjusting\n", + msync_dbg(sdata, "TSF : max clockdrift=%lld; adjusting\n", (long long) ifmsh->sync_offset_clockdrift_max); tsfdelta = -ifmsh->sync_offset_clockdrift_max; ifmsh->sync_offset_clockdrift_max = 0; } else { - msync_dbg(sdata, "TBTT : max clockdrift=%lld; adjusting by %llu\n", + msync_dbg(sdata, "TSF : max clockdrift=%lld; adjusting by %llu\n", (long long) ifmsh->sync_offset_clockdrift_max, (unsigned long long) beacon_int_fraction); tsfdelta = -beacon_int_fraction; @@ -167,7 +167,7 @@ no_sync: rcu_read_unlock(); } -static void mesh_sync_offset_adjust_tbtt(struct ieee80211_sub_if_data *sdata, +static void mesh_sync_offset_adjust_tsf(struct ieee80211_sub_if_data *sdata, struct beacon_data *beacon) { struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh; @@ -184,12 +184,12 @@ static void mesh_sync_offset_adjust_tbtt(struct ieee80211_sub_if_data *sdata, * the tsf adjustment to the mesh tasklet */ msync_dbg(sdata, - "TBTT : kicking off TBTT adjustment with clockdrift_max=%lld\n", + "TSF : kicking off TSF adjustment with clockdrift_max=%lld\n", ifmsh->sync_offset_clockdrift_max); set_bit(MESH_WORK_DRIFT_ADJUST, &ifmsh->wrkq_flags); } else { msync_dbg(sdata, - "TBTT : max clockdrift=%lld; too small to adjust\n", + "TSF : max clockdrift=%lld; too small to adjust\n", (long long)ifmsh->sync_offset_clockdrift_max); ifmsh->sync_offset_clockdrift_max = 0; } @@ -201,7 +201,7 @@ static const struct sync_method sync_methods[] = { .method = IEEE80211_SYNC_METHOD_NEIGHBOR_OFFSET, .ops = { .rx_bcn_presp = &mesh_sync_offset_rx_bcn_presp, - .adjust_tbtt = &mesh_sync_offset_adjust_tbtt, + .adjust_tsf = &mesh_sync_offset_adjust_tsf, } }, }; diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c index a39c0f07021b..058652d000d9 100644 --- a/net/mac80211/tx.c +++ b/net/mac80211/tx.c @@ -4196,7 +4196,7 @@ __ieee80211_beacon_get(struct ieee80211_hw *hw, } if (ifmsh->sync_ops) - ifmsh->sync_ops->adjust_tbtt(sdata, beacon); + ifmsh->sync_ops->adjust_tsf(sdata, beacon); skb = dev_alloc_skb(local->tx_headroom + beacon->head_len + -- cgit v1.2.3 From 0c2e384267b815fb784c415a90de7bdd78da0b66 Mon Sep 17 00:00:00 2001 From: Koen Vandeputte Date: Wed, 14 Dec 2016 17:28:59 +0100 Subject: mac80211: only alloc mem if a station doesn't exist yet This speeds up the function in case a station already exists by avoiding calling an expensive kzalloc just to free it again after the next check. Signed-off-by: Koen Vandeputte Signed-off-by: Johannes Berg --- net/mac80211/sta_info.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) (limited to 'net/mac80211') diff --git a/net/mac80211/sta_info.c b/net/mac80211/sta_info.c index 4ab75a9d70c7..f5a24b742eda 100644 --- a/net/mac80211/sta_info.c +++ b/net/mac80211/sta_info.c @@ -513,23 +513,23 @@ static int sta_info_insert_finish(struct sta_info *sta) __acquires(RCU) { struct ieee80211_local *local = sta->local; struct ieee80211_sub_if_data *sdata = sta->sdata; - struct station_info *sinfo; + struct station_info *sinfo = NULL; int err = 0; lockdep_assert_held(&local->sta_mtx); - sinfo = kzalloc(sizeof(struct station_info), GFP_KERNEL); - if (!sinfo) { - err = -ENOMEM; - goto out_err; - } - /* check if STA exists already */ if (sta_info_get_bss(sdata, sta->sta.addr)) { err = -EEXIST; goto out_err; } + sinfo = kzalloc(sizeof(struct station_info), GFP_KERNEL); + if (!sinfo) { + err = -ENOMEM; + goto out_err; + } + local->num_sta++; local->sta_generation++; smp_mb(); -- cgit v1.2.3 From 41d085835d3d2258633d8959e717198e31d3862e Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Wed, 14 Dec 2016 20:46:54 +0100 Subject: mac80211: minstrel_ht: move supported bitrate mask out of group data Improves dcache footprint by ensuring that fewer cache lines need to be touched. Signed-off-by: Felix Fietkau Signed-off-by: Johannes Berg --- net/mac80211/rc80211_minstrel_ht.c | 30 +++++++++++++++--------------- net/mac80211/rc80211_minstrel_ht.h | 6 +++--- net/mac80211/rc80211_minstrel_ht_debugfs.c | 8 ++++---- 3 files changed, 22 insertions(+), 22 deletions(-) (limited to 'net/mac80211') diff --git a/net/mac80211/rc80211_minstrel_ht.c b/net/mac80211/rc80211_minstrel_ht.c index 30fbabf4bcbc..ed8a34d46e73 100644 --- a/net/mac80211/rc80211_minstrel_ht.c +++ b/net/mac80211/rc80211_minstrel_ht.c @@ -301,7 +301,7 @@ minstrel_ht_get_stats(struct minstrel_priv *mp, struct minstrel_ht_sta *mi, break; /* short preamble */ - if (!(mi->groups[group].supported & BIT(idx))) + if (!(mi->supported[group] & BIT(idx))) idx += 4; } return &mi->groups[group].rates[idx]; @@ -486,7 +486,7 @@ minstrel_ht_prob_rate_reduce_streams(struct minstrel_ht_sta *mi) MCS_GROUP_RATES].streams; for (group = 0; group < ARRAY_SIZE(minstrel_mcs_groups); group++) { mg = &mi->groups[group]; - if (!mg->supported || group == MINSTREL_CCK_GROUP) + if (!mi->supported[group] || group == MINSTREL_CCK_GROUP) continue; tmp_idx = mg->max_group_prob_rate % MCS_GROUP_RATES; @@ -540,7 +540,7 @@ minstrel_ht_update_stats(struct minstrel_priv *mp, struct minstrel_ht_sta *mi) for (group = 0; group < ARRAY_SIZE(minstrel_mcs_groups); group++) { mg = &mi->groups[group]; - if (!mg->supported) + if (!mi->supported[group]) continue; mi->sample_count++; @@ -550,7 +550,7 @@ minstrel_ht_update_stats(struct minstrel_priv *mp, struct minstrel_ht_sta *mi) tmp_group_tp_rate[j] = group; for (i = 0; i < MCS_GROUP_RATES; i++) { - if (!(mg->supported & BIT(i))) + if (!(mi->supported[group] & BIT(i))) continue; index = MCS_GROUP_RATES * group + i; @@ -636,7 +636,7 @@ minstrel_set_next_sample_idx(struct minstrel_ht_sta *mi) mi->sample_group %= ARRAY_SIZE(minstrel_mcs_groups); mg = &mi->groups[mi->sample_group]; - if (!mg->supported) + if (!mi->supported[mi->sample_group]) continue; if (++mg->index >= MCS_GROUP_RATES) { @@ -657,7 +657,7 @@ minstrel_downgrade_rate(struct minstrel_ht_sta *mi, u16 *idx, bool primary) while (group > 0) { group--; - if (!mi->groups[group].supported) + if (!mi->supported[group]) continue; if (minstrel_mcs_groups[group].streams > @@ -994,7 +994,7 @@ minstrel_get_sample_rate(struct minstrel_priv *mp, struct minstrel_ht_sta *mi) sample_idx = sample_table[mg->column][mg->index]; minstrel_set_next_sample_idx(mi); - if (!(mg->supported & BIT(sample_idx))) + if (!(mi->supported[sample_group] & BIT(sample_idx))) return -1; mrs = &mg->rates[sample_idx]; @@ -1052,7 +1052,7 @@ static void minstrel_ht_check_cck_shortpreamble(struct minstrel_priv *mp, struct minstrel_ht_sta *mi, bool val) { - u8 supported = mi->groups[MINSTREL_CCK_GROUP].supported; + u8 supported = mi->supported[MINSTREL_CCK_GROUP]; if (!supported || !mi->cck_supported_short) return; @@ -1061,7 +1061,7 @@ minstrel_ht_check_cck_shortpreamble(struct minstrel_priv *mp, return; supported ^= mi->cck_supported_short | (mi->cck_supported_short << 4); - mi->groups[MINSTREL_CCK_GROUP].supported = supported; + mi->supported[MINSTREL_CCK_GROUP] = supported; } static void @@ -1154,7 +1154,7 @@ minstrel_ht_update_cck(struct minstrel_priv *mp, struct minstrel_ht_sta *mi, mi->cck_supported_short |= BIT(i); } - mi->groups[MINSTREL_CCK_GROUP].supported = mi->cck_supported; + mi->supported[MINSTREL_CCK_GROUP] = mi->cck_supported; } static void @@ -1224,7 +1224,7 @@ minstrel_ht_update_caps(void *priv, struct ieee80211_supported_band *sband, u32 gflags = minstrel_mcs_groups[i].flags; int bw, nss; - mi->groups[i].supported = 0; + mi->supported[i] = 0; if (i == MINSTREL_CCK_GROUP) { minstrel_ht_update_cck(mp, mi, sband, sta); continue; @@ -1256,8 +1256,8 @@ minstrel_ht_update_caps(void *priv, struct ieee80211_supported_band *sband, if (use_vht && minstrel_vht_only) continue; #endif - mi->groups[i].supported = mcs->rx_mask[nss - 1]; - if (mi->groups[i].supported) + mi->supported[i] = mcs->rx_mask[nss - 1]; + if (mi->supported[i]) n_supported++; continue; } @@ -1283,10 +1283,10 @@ minstrel_ht_update_caps(void *priv, struct ieee80211_supported_band *sband, else bw = BW_20; - mi->groups[i].supported = minstrel_get_valid_vht_rates(bw, nss, + mi->supported[i] = minstrel_get_valid_vht_rates(bw, nss, vht_cap->vht_mcs.tx_mcs_map); - if (mi->groups[i].supported) + if (mi->supported[i]) n_supported++; } diff --git a/net/mac80211/rc80211_minstrel_ht.h b/net/mac80211/rc80211_minstrel_ht.h index e8b52a94d24b..de1646c42e82 100644 --- a/net/mac80211/rc80211_minstrel_ht.h +++ b/net/mac80211/rc80211_minstrel_ht.h @@ -52,9 +52,6 @@ struct minstrel_mcs_group_data { u8 index; u8 column; - /* bitfield of supported MCS rates of this group */ - u16 supported; - /* sorted rate set within a MCS group*/ u16 max_group_tp_rate[MAX_THR_RATES]; u16 max_group_prob_rate; @@ -101,6 +98,9 @@ struct minstrel_ht_sta { u8 cck_supported; u8 cck_supported_short; + /* Bitfield of supported MCS rates of all groups */ + u16 supported[MINSTREL_GROUPS_NB]; + /* MCS rate group info and statistics */ struct minstrel_mcs_group_data groups[MINSTREL_GROUPS_NB]; }; diff --git a/net/mac80211/rc80211_minstrel_ht_debugfs.c b/net/mac80211/rc80211_minstrel_ht_debugfs.c index 5320e35ed3d0..1942d4b3cd18 100644 --- a/net/mac80211/rc80211_minstrel_ht_debugfs.c +++ b/net/mac80211/rc80211_minstrel_ht_debugfs.c @@ -24,7 +24,7 @@ minstrel_ht_stats_dump(struct minstrel_ht_sta *mi, int i, char *p) char gimode = 'L'; u32 gflags; - if (!mi->groups[i].supported) + if (!mi->supported[i]) return p; mg = &minstrel_mcs_groups[i]; @@ -42,7 +42,7 @@ minstrel_ht_stats_dump(struct minstrel_ht_sta *mi, int i, char *p) static const int bitrates[4] = { 10, 20, 55, 110 }; int idx = i * MCS_GROUP_RATES + j; - if (!(mi->groups[i].supported & BIT(j))) + if (!(mi->supported[i] & BIT(j))) continue; if (gflags & IEEE80211_TX_RC_MCS) { @@ -170,7 +170,7 @@ minstrel_ht_stats_csv_dump(struct minstrel_ht_sta *mi, int i, char *p) char gimode = 'L'; u32 gflags; - if (!mi->groups[i].supported) + if (!mi->supported[i]) return p; mg = &minstrel_mcs_groups[i]; @@ -188,7 +188,7 @@ minstrel_ht_stats_csv_dump(struct minstrel_ht_sta *mi, int i, char *p) static const int bitrates[4] = { 10, 20, 55, 110 }; int idx = i * MCS_GROUP_RATES + j; - if (!(mi->groups[i].supported & BIT(j))) + if (!(mi->supported[i] & BIT(j))) continue; if (gflags & IEEE80211_TX_RC_MCS) { -- cgit v1.2.3 From 782dda00ab8e9485ddc2a1fb8d8681dcc5136283 Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Wed, 14 Dec 2016 20:46:55 +0100 Subject: mac80211: minstrel_ht: move short preamble check out of get_rate Test short preamble support in minstrel_ht_update_caps instead of looking at the per-packet flag. Makes the code more efficient. Signed-off-by: Felix Fietkau Signed-off-by: Johannes Berg --- net/mac80211/rc80211_minstrel_ht.c | 22 +++++----------------- 1 file changed, 5 insertions(+), 17 deletions(-) (limited to 'net/mac80211') diff --git a/net/mac80211/rc80211_minstrel_ht.c b/net/mac80211/rc80211_minstrel_ht.c index ed8a34d46e73..ae45dcb9d7a7 100644 --- a/net/mac80211/rc80211_minstrel_ht.c +++ b/net/mac80211/rc80211_minstrel_ht.c @@ -14,6 +14,7 @@ #include #include #include "rate.h" +#include "sta_info.h" #include "rc80211_minstrel.h" #include "rc80211_minstrel_ht.h" @@ -1048,22 +1049,6 @@ minstrel_get_sample_rate(struct minstrel_priv *mp, struct minstrel_ht_sta *mi) return sample_idx; } -static void -minstrel_ht_check_cck_shortpreamble(struct minstrel_priv *mp, - struct minstrel_ht_sta *mi, bool val) -{ - u8 supported = mi->supported[MINSTREL_CCK_GROUP]; - - if (!supported || !mi->cck_supported_short) - return; - - if (supported & (mi->cck_supported_short << (val * 4))) - return; - - supported ^= mi->cck_supported_short | (mi->cck_supported_short << 4); - mi->supported[MINSTREL_CCK_GROUP] = supported; -} - static void minstrel_ht_get_rate(void *priv, struct ieee80211_sta *sta, void *priv_sta, struct ieee80211_tx_rate_control *txrc) @@ -1087,7 +1072,6 @@ minstrel_ht_get_rate(void *priv, struct ieee80211_sta *sta, void *priv_sta, minstrel_aggr_check(sta, txrc->skb); info->flags |= mi->tx_flags; - minstrel_ht_check_cck_shortpreamble(mp, mi, txrc->short_preamble); #ifdef CONFIG_MAC80211_DEBUGFS if (mp->fixed_rate_idx != -1) @@ -1168,6 +1152,7 @@ minstrel_ht_update_caps(void *priv, struct ieee80211_supported_band *sband, struct ieee80211_mcs_info *mcs = &sta->ht_cap.mcs; u16 sta_cap = sta->ht_cap.cap; struct ieee80211_sta_vht_cap *vht_cap = &sta->vht_cap; + struct sta_info *sinfo = container_of(sta, struct sta_info, sta); int use_vht; int n_supported = 0; int ack_dur; @@ -1293,6 +1278,9 @@ minstrel_ht_update_caps(void *priv, struct ieee80211_supported_band *sband, if (!n_supported) goto use_legacy; + if (test_sta_flag(sinfo, WLAN_STA_SHORT_PREAMBLE)) + mi->cck_supported_short |= mi->cck_supported_short << 4; + /* create an initial rate table with the lowest supported rates */ minstrel_ht_update_stats(mp, mi); minstrel_ht_update_rates(mp, mi); -- cgit v1.2.3 From 70550df2d354f13ae0544f12aa14b79f094f0de2 Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Wed, 14 Dec 2016 20:46:56 +0100 Subject: mac80211: minstrel_ht: make att_hist and succ_hist u32 instead of u64 They are only used for debugging purposes and take a very long time to overflow. Visibly reduces the size of the per-sta rate control data. Signed-off-by: Felix Fietkau Signed-off-by: Johannes Berg --- net/mac80211/rc80211_minstrel.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'net/mac80211') diff --git a/net/mac80211/rc80211_minstrel.h b/net/mac80211/rc80211_minstrel.h index c230bbe93262..209961cbb7e8 100644 --- a/net/mac80211/rc80211_minstrel.h +++ b/net/mac80211/rc80211_minstrel.h @@ -59,7 +59,7 @@ struct minstrel_rate_stats { u16 success, last_success; /* total attempts/success counters */ - u64 att_hist, succ_hist; + u32 att_hist, succ_hist; /* statistis of packet delivery probability * cur_prob - current prob within last update intervall -- cgit v1.2.3 From 95cd470c75a8822d35fa82a1b276d47da37229d1 Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Wed, 14 Dec 2016 20:46:57 +0100 Subject: mac80211: check for MCS in ieee80211_duration before fetching chanctx Makes the code a bit more efficient Signed-off-by: Felix Fietkau Signed-off-by: Johannes Berg --- net/mac80211/tx.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'net/mac80211') diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c index 058652d000d9..4dea18be385c 100644 --- a/net/mac80211/tx.c +++ b/net/mac80211/tx.c @@ -64,6 +64,10 @@ static __le16 ieee80211_duration(struct ieee80211_tx_data *tx, struct ieee80211_chanctx_conf *chanctx_conf; u32 rate_flags = 0; + /* assume HW handles this */ + if (tx->rate.flags & (IEEE80211_TX_RC_MCS | IEEE80211_TX_RC_VHT_MCS)) + return 0; + rcu_read_lock(); chanctx_conf = rcu_dereference(tx->sdata->vif.chanctx_conf); if (chanctx_conf) { @@ -72,10 +76,6 @@ static __le16 ieee80211_duration(struct ieee80211_tx_data *tx, } rcu_read_unlock(); - /* assume HW handles this */ - if (tx->rate.flags & (IEEE80211_TX_RC_MCS | IEEE80211_TX_RC_VHT_MCS)) - return 0; - /* uh huh? */ if (WARN_ON_ONCE(tx->rate.idx < 0)) return 0; -- cgit v1.2.3 From 1109dc392ea0248f7bfca3537011aa7afaa05cee Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Wed, 14 Dec 2016 20:46:58 +0100 Subject: mac80211: minstrel: remove cur_prob from debugfs This field is redundant, because it is simply last success divided by last attempt count. Removing it from the rate stats struct saves about 1.2 KiB per HT station. Signed-off-by: Felix Fietkau Signed-off-by: Johannes Berg --- net/mac80211/rc80211_minstrel.c | 10 ++++++---- net/mac80211/rc80211_minstrel.h | 2 -- net/mac80211/rc80211_minstrel_debugfs.c | 16 ++++++---------- net/mac80211/rc80211_minstrel_ht_debugfs.c | 16 ++++++---------- 4 files changed, 18 insertions(+), 26 deletions(-) (limited to 'net/mac80211') diff --git a/net/mac80211/rc80211_minstrel.c b/net/mac80211/rc80211_minstrel.c index 14c5ba3a1b1c..a284ea08f048 100644 --- a/net/mac80211/rc80211_minstrel.c +++ b/net/mac80211/rc80211_minstrel.c @@ -159,21 +159,23 @@ minstrel_update_rates(struct minstrel_priv *mp, struct minstrel_sta_info *mi) void minstrel_calc_rate_stats(struct minstrel_rate_stats *mrs) { + unsigned int cur_prob; + if (unlikely(mrs->attempts > 0)) { mrs->sample_skipped = 0; - mrs->cur_prob = MINSTREL_FRAC(mrs->success, mrs->attempts); + cur_prob = MINSTREL_FRAC(mrs->success, mrs->attempts); if (unlikely(!mrs->att_hist)) { - mrs->prob_ewma = mrs->cur_prob; + mrs->prob_ewma = cur_prob; } else { /* update exponential weighted moving variance */ mrs->prob_ewmsd = minstrel_ewmsd(mrs->prob_ewmsd, - mrs->cur_prob, + cur_prob, mrs->prob_ewma, EWMA_LEVEL); /*update exponential weighted moving avarage */ mrs->prob_ewma = minstrel_ewma(mrs->prob_ewma, - mrs->cur_prob, + cur_prob, EWMA_LEVEL); } mrs->att_hist += mrs->attempts; diff --git a/net/mac80211/rc80211_minstrel.h b/net/mac80211/rc80211_minstrel.h index 209961cbb7e8..94b89b1b406c 100644 --- a/net/mac80211/rc80211_minstrel.h +++ b/net/mac80211/rc80211_minstrel.h @@ -62,10 +62,8 @@ struct minstrel_rate_stats { u32 att_hist, succ_hist; /* statistis of packet delivery probability - * cur_prob - current prob within last update intervall * prob_ewma - exponential weighted moving average of prob * prob_ewmsd - exp. weighted moving standard deviation of prob */ - unsigned int cur_prob; unsigned int prob_ewma; u16 prob_ewmsd; diff --git a/net/mac80211/rc80211_minstrel_debugfs.c b/net/mac80211/rc80211_minstrel_debugfs.c index 820b0abc9c0d..ca0bafd6a44e 100644 --- a/net/mac80211/rc80211_minstrel_debugfs.c +++ b/net/mac80211/rc80211_minstrel_debugfs.c @@ -75,7 +75,7 @@ minstrel_stats_open(struct inode *inode, struct file *file) { struct minstrel_sta_info *mi = inode->i_private; struct minstrel_debugfs_info *ms; - unsigned int i, tp_max, tp_avg, prob, eprob; + unsigned int i, tp_max, tp_avg, eprob; char *p; ms = kmalloc(2048, GFP_KERNEL); @@ -86,9 +86,9 @@ minstrel_stats_open(struct inode *inode, struct file *file) p = ms->buf; p += sprintf(p, "\n"); p += sprintf(p, - "best __________rate_________ ________statistics________ ________last_______ ______sum-of________\n"); + "best __________rate_________ ________statistics________ ____last_____ ______sum-of________\n"); p += sprintf(p, - "rate [name idx airtime max_tp] [avg(tp) avg(prob) sd(prob)] [prob.|retry|suc|att] [#success | #attempts]\n"); + "rate [name idx airtime max_tp] [avg(tp) avg(prob) sd(prob)] [retry|suc|att] [#success | #attempts]\n"); for (i = 0; i < mi->n_rates; i++) { struct minstrel_rate *mr = &mi->r[i]; @@ -107,17 +107,15 @@ minstrel_stats_open(struct inode *inode, struct file *file) tp_max = minstrel_get_tp_avg(mr, MINSTREL_FRAC(100,100)); tp_avg = minstrel_get_tp_avg(mr, mrs->prob_ewma); - prob = MINSTREL_TRUNC(mrs->cur_prob * 1000); eprob = MINSTREL_TRUNC(mrs->prob_ewma * 1000); p += sprintf(p, "%4u.%1u %4u.%1u %3u.%1u %3u.%1u" - " %3u.%1u %3u %3u %-3u " + " %3u %3u %-3u " "%9llu %-9llu\n", tp_max / 10, tp_max % 10, tp_avg / 10, tp_avg % 10, eprob / 10, eprob % 10, mrs->prob_ewmsd / 10, mrs->prob_ewmsd % 10, - prob / 10, prob % 10, mrs->retry_count, mrs->last_success, mrs->last_attempts, @@ -148,7 +146,7 @@ minstrel_stats_csv_open(struct inode *inode, struct file *file) { struct minstrel_sta_info *mi = inode->i_private; struct minstrel_debugfs_info *ms; - unsigned int i, tp_max, tp_avg, prob, eprob; + unsigned int i, tp_max, tp_avg, eprob; char *p; ms = kmalloc(2048, GFP_KERNEL); @@ -175,16 +173,14 @@ minstrel_stats_csv_open(struct inode *inode, struct file *file) tp_max = minstrel_get_tp_avg(mr, MINSTREL_FRAC(100,100)); tp_avg = minstrel_get_tp_avg(mr, mrs->prob_ewma); - prob = MINSTREL_TRUNC(mrs->cur_prob * 1000); eprob = MINSTREL_TRUNC(mrs->prob_ewma * 1000); - p += sprintf(p, "%u.%u,%u.%u,%u.%u,%u.%u,%u.%u,%u,%u,%u," + p += sprintf(p, "%u.%u,%u.%u,%u.%u,%u.%u,%u,%u,%u," "%llu,%llu,%d,%d\n", tp_max / 10, tp_max % 10, tp_avg / 10, tp_avg % 10, eprob / 10, eprob % 10, mrs->prob_ewmsd / 10, mrs->prob_ewmsd % 10, - prob / 10, prob % 10, mrs->retry_count, mrs->last_success, mrs->last_attempts, diff --git a/net/mac80211/rc80211_minstrel_ht_debugfs.c b/net/mac80211/rc80211_minstrel_ht_debugfs.c index 1942d4b3cd18..0cecd23bb834 100644 --- a/net/mac80211/rc80211_minstrel_ht_debugfs.c +++ b/net/mac80211/rc80211_minstrel_ht_debugfs.c @@ -19,7 +19,7 @@ static char * minstrel_ht_stats_dump(struct minstrel_ht_sta *mi, int i, char *p) { const struct mcs_group *mg; - unsigned int j, tp_max, tp_avg, prob, eprob, tx_time; + unsigned int j, tp_max, tp_avg, eprob, tx_time; char htmode = '2'; char gimode = 'L'; u32 gflags; @@ -83,17 +83,15 @@ minstrel_ht_stats_dump(struct minstrel_ht_sta *mi, int i, char *p) tp_max = minstrel_ht_get_tp_avg(mi, i, j, MINSTREL_FRAC(100, 100)); tp_avg = minstrel_ht_get_tp_avg(mi, i, j, mrs->prob_ewma); - prob = MINSTREL_TRUNC(mrs->cur_prob * 1000); eprob = MINSTREL_TRUNC(mrs->prob_ewma * 1000); p += sprintf(p, "%4u.%1u %4u.%1u %3u.%1u %3u.%1u" - " %3u.%1u %3u %3u %-3u " + " %3u %3u %-3u " "%9llu %-9llu\n", tp_max / 10, tp_max % 10, tp_avg / 10, tp_avg % 10, eprob / 10, eprob % 10, mrs->prob_ewmsd / 10, mrs->prob_ewmsd % 10, - prob / 10, prob % 10, mrs->retry_count, mrs->last_success, mrs->last_attempts, @@ -130,9 +128,9 @@ minstrel_ht_stats_open(struct inode *inode, struct file *file) p += sprintf(p, "\n"); p += sprintf(p, - " best ____________rate__________ ________statistics________ ________last_______ ______sum-of________\n"); + " best ____________rate__________ ________statistics________ _____last____ ______sum-of________\n"); p += sprintf(p, - "mode guard # rate [name idx airtime max_tp] [avg(tp) avg(prob) sd(prob)] [prob.|retry|suc|att] [#success | #attempts]\n"); + "mode guard # rate [name idx airtime max_tp] [avg(tp) avg(prob) sd(prob)] [retry|suc|att] [#success | #attempts]\n"); p = minstrel_ht_stats_dump(mi, MINSTREL_CCK_GROUP, p); for (i = 0; i < MINSTREL_CCK_GROUP; i++) @@ -165,7 +163,7 @@ static char * minstrel_ht_stats_csv_dump(struct minstrel_ht_sta *mi, int i, char *p) { const struct mcs_group *mg; - unsigned int j, tp_max, tp_avg, prob, eprob, tx_time; + unsigned int j, tp_max, tp_avg, eprob, tx_time; char htmode = '2'; char gimode = 'L'; u32 gflags; @@ -226,16 +224,14 @@ minstrel_ht_stats_csv_dump(struct minstrel_ht_sta *mi, int i, char *p) tp_max = minstrel_ht_get_tp_avg(mi, i, j, MINSTREL_FRAC(100, 100)); tp_avg = minstrel_ht_get_tp_avg(mi, i, j, mrs->prob_ewma); - prob = MINSTREL_TRUNC(mrs->cur_prob * 1000); eprob = MINSTREL_TRUNC(mrs->prob_ewma * 1000); - p += sprintf(p, "%u.%u,%u.%u,%u.%u,%u.%u,%u.%u,%u,%u," + p += sprintf(p, "%u.%u,%u.%u,%u.%u,%u.%u,%u,%u," "%u,%llu,%llu,", tp_max / 10, tp_max % 10, tp_avg / 10, tp_avg % 10, eprob / 10, eprob % 10, mrs->prob_ewmsd / 10, mrs->prob_ewmsd % 10, - prob / 10, prob % 10, mrs->retry_count, mrs->last_success, mrs->last_attempts, -- cgit v1.2.3 From 0217eefa64509d63fbe8d1205310bafb2355cf4d Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Wed, 14 Dec 2016 20:46:59 +0100 Subject: mac80211: minstrel: reduce MINSTREL_SCALE The loss of a bit of extra precision does not hurt the calculation, 12 bits is still enough to calculate probabilities well. Reducing the scale makes it easier to avoid overflows Signed-off-by: Felix Fietkau Signed-off-by: Johannes Berg --- net/mac80211/rc80211_minstrel.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'net/mac80211') diff --git a/net/mac80211/rc80211_minstrel.h b/net/mac80211/rc80211_minstrel.h index 94b89b1b406c..03716fddaf24 100644 --- a/net/mac80211/rc80211_minstrel.h +++ b/net/mac80211/rc80211_minstrel.h @@ -14,7 +14,7 @@ #define SAMPLE_COLUMNS 10 /* number of columns in sample table */ /* scaled fraction values */ -#define MINSTREL_SCALE 16 +#define MINSTREL_SCALE 12 #define MINSTREL_FRAC(val, div) (((val) << MINSTREL_SCALE) / div) #define MINSTREL_TRUNC(val) ((val) >> MINSTREL_SCALE) -- cgit v1.2.3 From 4f0bc9c61bae9c74ffcf5dbdbd241cbf0ec3a44e Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Wed, 14 Dec 2016 20:47:00 +0100 Subject: mac80211: minstrel: store probability variance instead of standard deviation This avoids the costly int_sqrt calls in the statistics update and moves it to the debugfs code instead. This also fixes an overflow in the previous standard deviation calculation. Signed-off-by: Thomas Huehn Signed-off-by: Felix Fietkau Signed-off-by: Johannes Berg --- net/mac80211/rc80211_minstrel.c | 8 ++++---- net/mac80211/rc80211_minstrel.h | 25 ++++++++++++++----------- net/mac80211/rc80211_minstrel_debugfs.c | 8 ++++++-- net/mac80211/rc80211_minstrel_ht_debugfs.c | 8 ++++++-- 4 files changed, 30 insertions(+), 19 deletions(-) (limited to 'net/mac80211') diff --git a/net/mac80211/rc80211_minstrel.c b/net/mac80211/rc80211_minstrel.c index a284ea08f048..11a4cc393a98 100644 --- a/net/mac80211/rc80211_minstrel.c +++ b/net/mac80211/rc80211_minstrel.c @@ -168,10 +168,10 @@ minstrel_calc_rate_stats(struct minstrel_rate_stats *mrs) mrs->prob_ewma = cur_prob; } else { /* update exponential weighted moving variance */ - mrs->prob_ewmsd = minstrel_ewmsd(mrs->prob_ewmsd, - cur_prob, - mrs->prob_ewma, - EWMA_LEVEL); + mrs->prob_ewmv = minstrel_ewmv(mrs->prob_ewmv, + cur_prob, + mrs->prob_ewma, + EWMA_LEVEL); /*update exponential weighted moving avarage */ mrs->prob_ewma = minstrel_ewma(mrs->prob_ewma, diff --git a/net/mac80211/rc80211_minstrel.h b/net/mac80211/rc80211_minstrel.h index 03716fddaf24..ea86e6784154 100644 --- a/net/mac80211/rc80211_minstrel.h +++ b/net/mac80211/rc80211_minstrel.h @@ -36,21 +36,16 @@ minstrel_ewma(int old, int new, int weight) } /* - * Perform EWMSD (Exponentially Weighted Moving Standard Deviation) calculation + * Perform EWMV (Exponentially Weighted Moving Variance) calculation */ static inline int -minstrel_ewmsd(int old_ewmsd, int cur_prob, int prob_ewma, int weight) +minstrel_ewmv(int old_ewmv, int cur_prob, int prob_ewma, int weight) { - int diff, incr, tmp_var; + int diff, incr; - /* calculate exponential weighted moving variance */ - diff = MINSTREL_TRUNC((cur_prob - prob_ewma) * 1000000); + diff = cur_prob - prob_ewma; incr = (EWMA_DIV - weight) * diff / EWMA_DIV; - tmp_var = old_ewmsd * old_ewmsd; - tmp_var = weight * (tmp_var + diff * incr / 1000000) / EWMA_DIV; - - /* return standard deviation */ - return (u16) int_sqrt(tmp_var); + return weight * (old_ewmv + MINSTREL_TRUNC(diff * incr)) / EWMA_DIV; } struct minstrel_rate_stats { @@ -65,7 +60,7 @@ struct minstrel_rate_stats { * prob_ewma - exponential weighted moving average of prob * prob_ewmsd - exp. weighted moving standard deviation of prob */ unsigned int prob_ewma; - u16 prob_ewmsd; + u16 prob_ewmv; /* maximum retry counts */ u8 retry_count; @@ -151,6 +146,14 @@ struct minstrel_debugfs_info { char buf[]; }; +/* Get EWMSD (Exponentially Weighted Moving Standard Deviation) * 10 */ +static inline int +minstrel_get_ewmsd10(struct minstrel_rate_stats *mrs) +{ + unsigned int ewmv = mrs->prob_ewmv; + return int_sqrt(MINSTREL_TRUNC(ewmv * 1000 * 1000)); +} + extern const struct rate_control_ops mac80211_minstrel; void minstrel_add_sta_debugfs(void *priv, void *priv_sta, struct dentry *dir); void minstrel_remove_sta_debugfs(void *priv, void *priv_sta); diff --git a/net/mac80211/rc80211_minstrel_debugfs.c b/net/mac80211/rc80211_minstrel_debugfs.c index ca0bafd6a44e..36fc971deb86 100644 --- a/net/mac80211/rc80211_minstrel_debugfs.c +++ b/net/mac80211/rc80211_minstrel_debugfs.c @@ -93,6 +93,7 @@ minstrel_stats_open(struct inode *inode, struct file *file) for (i = 0; i < mi->n_rates; i++) { struct minstrel_rate *mr = &mi->r[i]; struct minstrel_rate_stats *mrs = &mi->r[i].stats; + unsigned int prob_ewmsd; *(p++) = (i == mi->max_tp_rate[0]) ? 'A' : ' '; *(p++) = (i == mi->max_tp_rate[1]) ? 'B' : ' '; @@ -108,6 +109,7 @@ minstrel_stats_open(struct inode *inode, struct file *file) tp_max = minstrel_get_tp_avg(mr, MINSTREL_FRAC(100,100)); tp_avg = minstrel_get_tp_avg(mr, mrs->prob_ewma); eprob = MINSTREL_TRUNC(mrs->prob_ewma * 1000); + prob_ewmsd = minstrel_get_ewmsd10(mrs); p += sprintf(p, "%4u.%1u %4u.%1u %3u.%1u %3u.%1u" " %3u %3u %-3u " @@ -115,7 +117,7 @@ minstrel_stats_open(struct inode *inode, struct file *file) tp_max / 10, tp_max % 10, tp_avg / 10, tp_avg % 10, eprob / 10, eprob % 10, - mrs->prob_ewmsd / 10, mrs->prob_ewmsd % 10, + prob_ewmsd / 10, prob_ewmsd % 10, mrs->retry_count, mrs->last_success, mrs->last_attempts, @@ -159,6 +161,7 @@ minstrel_stats_csv_open(struct inode *inode, struct file *file) for (i = 0; i < mi->n_rates; i++) { struct minstrel_rate *mr = &mi->r[i]; struct minstrel_rate_stats *mrs = &mi->r[i].stats; + unsigned int prob_ewmsd; p += sprintf(p, "%s" ,((i == mi->max_tp_rate[0]) ? "A" : "")); p += sprintf(p, "%s" ,((i == mi->max_tp_rate[1]) ? "B" : "")); @@ -174,13 +177,14 @@ minstrel_stats_csv_open(struct inode *inode, struct file *file) tp_max = minstrel_get_tp_avg(mr, MINSTREL_FRAC(100,100)); tp_avg = minstrel_get_tp_avg(mr, mrs->prob_ewma); eprob = MINSTREL_TRUNC(mrs->prob_ewma * 1000); + prob_ewmsd = minstrel_get_ewmsd10(mrs); p += sprintf(p, "%u.%u,%u.%u,%u.%u,%u.%u,%u,%u,%u," "%llu,%llu,%d,%d\n", tp_max / 10, tp_max % 10, tp_avg / 10, tp_avg % 10, eprob / 10, eprob % 10, - mrs->prob_ewmsd / 10, mrs->prob_ewmsd % 10, + prob_ewmsd / 10, prob_ewmsd % 10, mrs->retry_count, mrs->last_success, mrs->last_attempts, diff --git a/net/mac80211/rc80211_minstrel_ht_debugfs.c b/net/mac80211/rc80211_minstrel_ht_debugfs.c index 0cecd23bb834..7d969e300fb3 100644 --- a/net/mac80211/rc80211_minstrel_ht_debugfs.c +++ b/net/mac80211/rc80211_minstrel_ht_debugfs.c @@ -41,6 +41,7 @@ minstrel_ht_stats_dump(struct minstrel_ht_sta *mi, int i, char *p) struct minstrel_rate_stats *mrs = &mi->groups[i].rates[j]; static const int bitrates[4] = { 10, 20, 55, 110 }; int idx = i * MCS_GROUP_RATES + j; + unsigned int prob_ewmsd; if (!(mi->supported[i] & BIT(j))) continue; @@ -84,6 +85,7 @@ minstrel_ht_stats_dump(struct minstrel_ht_sta *mi, int i, char *p) tp_max = minstrel_ht_get_tp_avg(mi, i, j, MINSTREL_FRAC(100, 100)); tp_avg = minstrel_ht_get_tp_avg(mi, i, j, mrs->prob_ewma); eprob = MINSTREL_TRUNC(mrs->prob_ewma * 1000); + prob_ewmsd = minstrel_get_ewmsd10(mrs); p += sprintf(p, "%4u.%1u %4u.%1u %3u.%1u %3u.%1u" " %3u %3u %-3u " @@ -91,7 +93,7 @@ minstrel_ht_stats_dump(struct minstrel_ht_sta *mi, int i, char *p) tp_max / 10, tp_max % 10, tp_avg / 10, tp_avg % 10, eprob / 10, eprob % 10, - mrs->prob_ewmsd / 10, mrs->prob_ewmsd % 10, + prob_ewmsd / 10, prob_ewmsd % 10, mrs->retry_count, mrs->last_success, mrs->last_attempts, @@ -185,6 +187,7 @@ minstrel_ht_stats_csv_dump(struct minstrel_ht_sta *mi, int i, char *p) struct minstrel_rate_stats *mrs = &mi->groups[i].rates[j]; static const int bitrates[4] = { 10, 20, 55, 110 }; int idx = i * MCS_GROUP_RATES + j; + unsigned int prob_ewmsd; if (!(mi->supported[i] & BIT(j))) continue; @@ -225,13 +228,14 @@ minstrel_ht_stats_csv_dump(struct minstrel_ht_sta *mi, int i, char *p) tp_max = minstrel_ht_get_tp_avg(mi, i, j, MINSTREL_FRAC(100, 100)); tp_avg = minstrel_ht_get_tp_avg(mi, i, j, mrs->prob_ewma); eprob = MINSTREL_TRUNC(mrs->prob_ewma * 1000); + prob_ewmsd = minstrel_get_ewmsd10(mrs); p += sprintf(p, "%u.%u,%u.%u,%u.%u,%u.%u,%u,%u," "%u,%llu,%llu,", tp_max / 10, tp_max % 10, tp_avg / 10, tp_avg % 10, eprob / 10, eprob % 10, - mrs->prob_ewmsd / 10, mrs->prob_ewmsd % 10, + prob_ewmsd / 10, prob_ewmsd % 10, mrs->retry_count, mrs->last_success, mrs->last_attempts, -- cgit v1.2.3 From 4cae4cd10d058eb4057e20cb72e82fe76ae739af Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Wed, 14 Dec 2016 20:47:01 +0100 Subject: mac80211: minstrel: make prob_ewma u16 instead of u32 Saves about 1.2 KiB memory per station Signed-off-by: Felix Fietkau Signed-off-by: Johannes Berg --- net/mac80211/rc80211_minstrel.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'net/mac80211') diff --git a/net/mac80211/rc80211_minstrel.h b/net/mac80211/rc80211_minstrel.h index ea86e6784154..be6c3f35f48b 100644 --- a/net/mac80211/rc80211_minstrel.h +++ b/net/mac80211/rc80211_minstrel.h @@ -59,7 +59,7 @@ struct minstrel_rate_stats { /* statistis of packet delivery probability * prob_ewma - exponential weighted moving average of prob * prob_ewmsd - exp. weighted moving standard deviation of prob */ - unsigned int prob_ewma; + u16 prob_ewma; u16 prob_ewmv; /* maximum retry counts */ -- cgit v1.2.3 From 73b16589b859130eb8b49882e71c7cd1caa5986d Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Wed, 14 Dec 2016 20:47:02 +0100 Subject: mac80211: minstrel_ht: remove obsolete #if for >= 3 streams This was added during early development when 3x3 hardware was not very common yet. This is completely unnecessary now. Signed-off-by: Felix Fietkau Signed-off-by: Johannes Berg --- net/mac80211/rc80211_minstrel_ht.c | 20 -------------------- 1 file changed, 20 deletions(-) (limited to 'net/mac80211') diff --git a/net/mac80211/rc80211_minstrel_ht.c b/net/mac80211/rc80211_minstrel_ht.c index ae45dcb9d7a7..8e783e197e93 100644 --- a/net/mac80211/rc80211_minstrel_ht.c +++ b/net/mac80211/rc80211_minstrel_ht.c @@ -155,67 +155,47 @@ MODULE_PARM_DESC(minstrel_vht_only, const struct mcs_group minstrel_mcs_groups[] = { MCS_GROUP(1, 0, BW_20), MCS_GROUP(2, 0, BW_20), -#if MINSTREL_MAX_STREAMS >= 3 MCS_GROUP(3, 0, BW_20), -#endif MCS_GROUP(1, 1, BW_20), MCS_GROUP(2, 1, BW_20), -#if MINSTREL_MAX_STREAMS >= 3 MCS_GROUP(3, 1, BW_20), -#endif MCS_GROUP(1, 0, BW_40), MCS_GROUP(2, 0, BW_40), -#if MINSTREL_MAX_STREAMS >= 3 MCS_GROUP(3, 0, BW_40), -#endif MCS_GROUP(1, 1, BW_40), MCS_GROUP(2, 1, BW_40), -#if MINSTREL_MAX_STREAMS >= 3 MCS_GROUP(3, 1, BW_40), -#endif CCK_GROUP, #ifdef CONFIG_MAC80211_RC_MINSTREL_VHT VHT_GROUP(1, 0, BW_20), VHT_GROUP(2, 0, BW_20), -#if MINSTREL_MAX_STREAMS >= 3 VHT_GROUP(3, 0, BW_20), -#endif VHT_GROUP(1, 1, BW_20), VHT_GROUP(2, 1, BW_20), -#if MINSTREL_MAX_STREAMS >= 3 VHT_GROUP(3, 1, BW_20), -#endif VHT_GROUP(1, 0, BW_40), VHT_GROUP(2, 0, BW_40), -#if MINSTREL_MAX_STREAMS >= 3 VHT_GROUP(3, 0, BW_40), -#endif VHT_GROUP(1, 1, BW_40), VHT_GROUP(2, 1, BW_40), -#if MINSTREL_MAX_STREAMS >= 3 VHT_GROUP(3, 1, BW_40), -#endif VHT_GROUP(1, 0, BW_80), VHT_GROUP(2, 0, BW_80), -#if MINSTREL_MAX_STREAMS >= 3 VHT_GROUP(3, 0, BW_80), -#endif VHT_GROUP(1, 1, BW_80), VHT_GROUP(2, 1, BW_80), -#if MINSTREL_MAX_STREAMS >= 3 VHT_GROUP(3, 1, BW_80), #endif -#endif }; static u8 sample_table[SAMPLE_COLUMNS][MCS_GROUP_RATES] __read_mostly; -- cgit v1.2.3 From 38252e9ef68936f104a5791740f4ca2f81510a33 Mon Sep 17 00:00:00 2001 From: Thomas Huehn Date: Wed, 14 Dec 2016 20:47:03 +0100 Subject: mac80211: minstrel: avoid port control frames for sampling Makes connections more reliable Signed-off-by: Thomas Huehn Signed-off-by: Felix Fietkau Signed-off-by: Johannes Berg --- net/mac80211/rc80211_minstrel.c | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'net/mac80211') diff --git a/net/mac80211/rc80211_minstrel.c b/net/mac80211/rc80211_minstrel.c index 11a4cc393a98..3ebe4405a2d4 100644 --- a/net/mac80211/rc80211_minstrel.c +++ b/net/mac80211/rc80211_minstrel.c @@ -367,6 +367,11 @@ minstrel_get_rate(void *priv, struct ieee80211_sta *sta, return; #endif + /* Don't use EAPOL frames for sampling on non-mrr hw */ + if (mp->hw->max_rates == 1 && + (info->control.flags & IEEE80211_TX_CTRL_PORT_CTRL_PROTO)) + return; + delta = (mi->total_packets * sampling_ratio / 100) - (mi->sample_packets + mi->sample_deferred / 2); -- cgit v1.2.3 From 57629915d568c522ac1422df7bba4bee5b5c7a7c Mon Sep 17 00:00:00 2001 From: Ilan peer Date: Mon, 26 Dec 2016 18:17:36 +0200 Subject: mac80211: Fix addition of mesh configuration element The code was setting the capabilities byte to zero, after it was already properly set previously. Fix it. The bug was found while debugging hwsim mesh tests failures that happened since the commit mentioned below. Fixes: 76f43b4c0a93 ("mac80211: Remove invalid flag operations in mesh TSF synchronization") Signed-off-by: Ilan Peer Reviewed-by: Masashi Honma Signed-off-by: Johannes Berg --- net/mac80211/mesh.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'net/mac80211') diff --git a/net/mac80211/mesh.c b/net/mac80211/mesh.c index cc2a63bd233f..9c23172feba0 100644 --- a/net/mac80211/mesh.c +++ b/net/mac80211/mesh.c @@ -279,8 +279,6 @@ int mesh_add_meshconf_ie(struct ieee80211_sub_if_data *sdata, /* Mesh PS mode. See IEEE802.11-2012 8.4.2.100.8 */ *pos |= ifmsh->ps_peers_deep_sleep ? IEEE80211_MESHCONF_CAPAB_POWER_SAVE_LEVEL : 0x00; - *pos++ = 0x00; - return 0; } -- cgit v1.2.3 From cef0acd4d7d4811d2d19cd0195031bf0dfe41249 Mon Sep 17 00:00:00 2001 From: David Spinadel Date: Mon, 21 Nov 2016 16:58:40 +0200 Subject: mac80211: Add RX flag to indicate ICV stripped Add a flag that indicates that the WEP ICV was stripped from an RX packet, allowing the device to not transfer that if it's already checked. Signed-off-by: David Spinadel Signed-off-by: Johannes Berg --- include/net/mac80211.h | 5 ++++- net/mac80211/wep.c | 3 ++- net/mac80211/wpa.c | 3 ++- 3 files changed, 8 insertions(+), 3 deletions(-) (limited to 'net/mac80211') diff --git a/include/net/mac80211.h b/include/net/mac80211.h index 5f5cb194cd78..86967b85dfd0 100644 --- a/include/net/mac80211.h +++ b/include/net/mac80211.h @@ -1017,7 +1017,7 @@ ieee80211_tx_info_clear_status(struct ieee80211_tx_info *info) * @RX_FLAG_DECRYPTED: This frame was decrypted in hardware. * @RX_FLAG_MMIC_STRIPPED: the Michael MIC is stripped off this frame, * verification has been done by the hardware. - * @RX_FLAG_IV_STRIPPED: The IV/ICV are stripped from this frame. + * @RX_FLAG_IV_STRIPPED: The IV and ICV are stripped from this frame. * If this flag is set, the stack cannot do any replay detection * hence the driver or hardware will have to do that. * @RX_FLAG_PN_VALIDATED: Currently only valid for CCMP/GCMP frames, this @@ -1088,6 +1088,8 @@ ieee80211_tx_info_clear_status(struct ieee80211_tx_info *info) * @RX_FLAG_ALLOW_SAME_PN: Allow the same PN as same packet before. * This is used for AMSDU subframes which can have the same PN as * the first subframe. + * @RX_FLAG_ICV_STRIPPED: The ICV is stripped from this frame. CRC checking must + * be done in the hardware. */ enum mac80211_rx_flags { RX_FLAG_MMIC_ERROR = BIT(0), @@ -1123,6 +1125,7 @@ enum mac80211_rx_flags { RX_FLAG_RADIOTAP_VENDOR_DATA = BIT(31), RX_FLAG_MIC_STRIPPED = BIT_ULL(32), RX_FLAG_ALLOW_SAME_PN = BIT_ULL(33), + RX_FLAG_ICV_STRIPPED = BIT_ULL(34), }; #define RX_FLAG_STBC_SHIFT 26 diff --git a/net/mac80211/wep.c b/net/mac80211/wep.c index efa3f48f1ec5..73e8f347802e 100644 --- a/net/mac80211/wep.c +++ b/net/mac80211/wep.c @@ -293,7 +293,8 @@ ieee80211_crypto_wep_decrypt(struct ieee80211_rx_data *rx) return RX_DROP_UNUSABLE; ieee80211_wep_remove_iv(rx->local, rx->skb, rx->key); /* remove ICV */ - if (pskb_trim(rx->skb, rx->skb->len - IEEE80211_WEP_ICV_LEN)) + if (!(status->flag & RX_FLAG_ICV_STRIPPED) && + pskb_trim(rx->skb, rx->skb->len - IEEE80211_WEP_ICV_LEN)) return RX_DROP_UNUSABLE; } diff --git a/net/mac80211/wpa.c b/net/mac80211/wpa.c index 8af6dd388d11..c1ef22df865f 100644 --- a/net/mac80211/wpa.c +++ b/net/mac80211/wpa.c @@ -294,7 +294,8 @@ ieee80211_crypto_tkip_decrypt(struct ieee80211_rx_data *rx) return RX_DROP_UNUSABLE; /* Trim ICV */ - skb_trim(skb, skb->len - IEEE80211_TKIP_ICV_LEN); + if (!(status->flag & RX_FLAG_ICV_STRIPPED)) + skb_trim(skb, skb->len - IEEE80211_TKIP_ICV_LEN); /* Remove IV */ memmove(skb->data + IEEE80211_TKIP_IV_LEN, skb->data, hdrlen); -- cgit v1.2.3 From 2cc6f5a715cf9f7d5ca8fd2bde62130fcfd90b94 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Wed, 19 Oct 2016 15:02:32 +0200 Subject: mac80211: set wifi_acked[_valid] bits for transmitted SKBs There may be situations in which the in-kernel originator of an SKB cares about its wifi transmission status. To have that, set the wifi_acked[_valid] bits before freeing/orphaning the SKB if the destructor is set. The originator can then use it in there. Signed-off-by: Johannes Berg --- net/mac80211/status.c | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'net/mac80211') diff --git a/net/mac80211/status.c b/net/mac80211/status.c index f7c5ae597639..d6a1bfaa7a81 100644 --- a/net/mac80211/status.c +++ b/net/mac80211/status.c @@ -541,6 +541,11 @@ static void ieee80211_report_used_skb(struct ieee80211_local *local, } else if (info->ack_frame_id) { ieee80211_report_ack_skb(local, info, acked, dropped); } + + if (!dropped && skb->destructor) { + skb->wifi_acked_valid = 1; + skb->wifi_acked = acked; + } } /* -- cgit v1.2.3