diff options
author | David S. Miller <davem@davemloft.net> | 2015-10-22 10:28:41 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2015-10-22 10:28:41 -0400 |
commit | e9829b9745b6e1683fd2a90842da498a2197299e (patch) | |
tree | 088466771298ed5d92b1b1b30a52204d37c2f4ff | |
parent | c7fc9eb79a89049214f9870a6cf978050aaea43a (diff) | |
parent | e5a9f8d04660da7ef3a98260aa74c3976f9cb4cd (diff) |
Merge tag 'mac80211-next-for-davem-2015-10-21' of git://git.kernel.org/pub/scm/linux/kernel/git/jberg/mac80211-next
Johannes Berg says:
====================
Here's another set of patches for the current cycle:
* I merged net-next back to avoid a conflict with the
* cfg80211 scheduled scan API extensions
* preparations for better scan result timestamping
* regulatory cleanups
* mac80211 statistics cleanups
* a few other small cleanups and fixes
====================
Signed-off-by: David S. Miller <davem@davemloft.net>
41 files changed, 910 insertions, 659 deletions
diff --git a/Documentation/DocBook/80211.tmpl b/Documentation/DocBook/80211.tmpl index aac9357d4866..f9b9ad7894f5 100644 --- a/Documentation/DocBook/80211.tmpl +++ b/Documentation/DocBook/80211.tmpl | |||
@@ -154,8 +154,9 @@ | |||
154 | !Finclude/net/cfg80211.h cfg80211_scan_request | 154 | !Finclude/net/cfg80211.h cfg80211_scan_request |
155 | !Finclude/net/cfg80211.h cfg80211_scan_done | 155 | !Finclude/net/cfg80211.h cfg80211_scan_done |
156 | !Finclude/net/cfg80211.h cfg80211_bss | 156 | !Finclude/net/cfg80211.h cfg80211_bss |
157 | !Finclude/net/cfg80211.h cfg80211_inform_bss_width_frame | 157 | !Finclude/net/cfg80211.h cfg80211_inform_bss |
158 | !Finclude/net/cfg80211.h cfg80211_inform_bss_width | 158 | !Finclude/net/cfg80211.h cfg80211_inform_bss_frame_data |
159 | !Finclude/net/cfg80211.h cfg80211_inform_bss_data | ||
159 | !Finclude/net/cfg80211.h cfg80211_unlink_bss | 160 | !Finclude/net/cfg80211.h cfg80211_unlink_bss |
160 | !Finclude/net/cfg80211.h cfg80211_find_ie | 161 | !Finclude/net/cfg80211.h cfg80211_find_ie |
161 | !Finclude/net/cfg80211.h ieee80211_bss_get_ie | 162 | !Finclude/net/cfg80211.h ieee80211_bss_get_ie |
diff --git a/drivers/net/wireless/ath/ath6kl/cfg80211.c b/drivers/net/wireless/ath/ath6kl/cfg80211.c index a511ef3614b9..3fda750db2a9 100644 --- a/drivers/net/wireless/ath/ath6kl/cfg80211.c +++ b/drivers/net/wireless/ath/ath6kl/cfg80211.c | |||
@@ -3312,7 +3312,7 @@ static int ath6kl_cfg80211_sscan_start(struct wiphy *wiphy, | |||
3312 | } | 3312 | } |
3313 | 3313 | ||
3314 | /* fw uses seconds, also make sure that it's >0 */ | 3314 | /* fw uses seconds, also make sure that it's >0 */ |
3315 | interval = max_t(u16, 1, request->interval / 1000); | 3315 | interval = max_t(u16, 1, request->scan_plans[0].interval); |
3316 | 3316 | ||
3317 | ath6kl_wmi_scanparams_cmd(ar->wmi, vif->fw_vif_idx, | 3317 | ath6kl_wmi_scanparams_cmd(ar->wmi, vif->fw_vif_idx, |
3318 | interval, interval, | 3318 | interval, interval, |
diff --git a/drivers/net/wireless/iwlwifi/mvm/ops.c b/drivers/net/wireless/iwlwifi/mvm/ops.c index 7fcd2c24a0a4..13c97f665ba8 100644 --- a/drivers/net/wireless/iwlwifi/mvm/ops.c +++ b/drivers/net/wireless/iwlwifi/mvm/ops.c | |||
@@ -630,6 +630,7 @@ static void iwl_op_mode_mvm_stop(struct iwl_op_mode *op_mode) | |||
630 | kfree(mvm->d3_resume_sram); | 630 | kfree(mvm->d3_resume_sram); |
631 | if (mvm->nd_config) { | 631 | if (mvm->nd_config) { |
632 | kfree(mvm->nd_config->match_sets); | 632 | kfree(mvm->nd_config->match_sets); |
633 | kfree(mvm->nd_config->scan_plans); | ||
633 | kfree(mvm->nd_config); | 634 | kfree(mvm->nd_config); |
634 | mvm->nd_config = NULL; | 635 | mvm->nd_config = NULL; |
635 | } | 636 | } |
diff --git a/drivers/net/wireless/iwlwifi/mvm/scan.c b/drivers/net/wireless/iwlwifi/mvm/scan.c index 4a1f9af63bf0..cee4f267ca66 100644 --- a/drivers/net/wireless/iwlwifi/mvm/scan.c +++ b/drivers/net/wireless/iwlwifi/mvm/scan.c | |||
@@ -1271,12 +1271,12 @@ int iwl_mvm_sched_scan_start(struct iwl_mvm *mvm, | |||
1271 | 1271 | ||
1272 | params.type = iwl_mvm_get_scan_type(mvm, vif, ¶ms); | 1272 | params.type = iwl_mvm_get_scan_type(mvm, vif, ¶ms); |
1273 | 1273 | ||
1274 | if (req->interval > U16_MAX) { | 1274 | if (req->scan_plans[0].interval > U16_MAX) { |
1275 | IWL_DEBUG_SCAN(mvm, | 1275 | IWL_DEBUG_SCAN(mvm, |
1276 | "interval value is > 16-bits, set to max possible\n"); | 1276 | "interval value is > 16-bits, set to max possible\n"); |
1277 | params.interval = U16_MAX; | 1277 | params.interval = U16_MAX; |
1278 | } else { | 1278 | } else { |
1279 | params.interval = req->interval / MSEC_PER_SEC; | 1279 | params.interval = req->scan_plans[0].interval; |
1280 | } | 1280 | } |
1281 | 1281 | ||
1282 | /* In theory, LMAC scans can handle a 32-bit delay, but since | 1282 | /* In theory, LMAC scans can handle a 32-bit delay, but since |
diff --git a/drivers/net/wireless/rt2x00/rt2x00config.c b/drivers/net/wireless/rt2x00/rt2x00config.c index 48a2cad29477..7e8bb1198ae9 100644 --- a/drivers/net/wireless/rt2x00/rt2x00config.c +++ b/drivers/net/wireless/rt2x00/rt2x00config.c | |||
@@ -266,7 +266,7 @@ void rt2x00lib_config(struct rt2x00_dev *rt2x00dev, | |||
266 | if (beacon_diff > beacon_int) | 266 | if (beacon_diff > beacon_int) |
267 | beacon_diff = 0; | 267 | beacon_diff = 0; |
268 | 268 | ||
269 | autowake_timeout = (conf->max_sleep_period * beacon_int) - beacon_diff; | 269 | autowake_timeout = (conf->ps_dtim_period * beacon_int) - beacon_diff; |
270 | queue_delayed_work(rt2x00dev->workqueue, | 270 | queue_delayed_work(rt2x00dev->workqueue, |
271 | &rt2x00dev->autowakeup_work, | 271 | &rt2x00dev->autowakeup_work, |
272 | autowake_timeout - 15); | 272 | autowake_timeout - 15); |
diff --git a/drivers/net/wireless/ti/wl12xx/scan.c b/drivers/net/wireless/ti/wl12xx/scan.c index 7c355fff2c5e..ebed13af9852 100644 --- a/drivers/net/wireless/ti/wl12xx/scan.c +++ b/drivers/net/wireless/ti/wl12xx/scan.c | |||
@@ -350,7 +350,8 @@ int wl1271_scan_sched_scan_config(struct wl1271 *wl, | |||
350 | cfg->bss_type = SCAN_BSS_TYPE_ANY; | 350 | cfg->bss_type = SCAN_BSS_TYPE_ANY; |
351 | /* currently NL80211 supports only a single interval */ | 351 | /* currently NL80211 supports only a single interval */ |
352 | for (i = 0; i < SCAN_MAX_CYCLE_INTERVALS; i++) | 352 | for (i = 0; i < SCAN_MAX_CYCLE_INTERVALS; i++) |
353 | cfg->intervals[i] = cpu_to_le32(req->interval); | 353 | cfg->intervals[i] = cpu_to_le32(req->scan_plans[0].interval * |
354 | MSEC_PER_SEC); | ||
354 | 355 | ||
355 | cfg->ssid_len = 0; | 356 | cfg->ssid_len = 0; |
356 | ret = wlcore_scan_sched_scan_ssid_list(wl, wlvif, req); | 357 | ret = wlcore_scan_sched_scan_ssid_list(wl, wlvif, req); |
diff --git a/drivers/net/wireless/ti/wl18xx/scan.c b/drivers/net/wireless/ti/wl18xx/scan.c index c938c494c785..bc15aa2c3efa 100644 --- a/drivers/net/wireless/ti/wl18xx/scan.c +++ b/drivers/net/wireless/ti/wl18xx/scan.c | |||
@@ -228,13 +228,15 @@ int wl18xx_scan_sched_scan_config(struct wl1271 *wl, | |||
228 | wl18xx_adjust_channels(cmd, cmd_channels); | 228 | wl18xx_adjust_channels(cmd, cmd_channels); |
229 | 229 | ||
230 | if (c->num_short_intervals && c->long_interval && | 230 | if (c->num_short_intervals && c->long_interval && |
231 | c->long_interval > req->interval) { | 231 | c->long_interval > req->scan_plans[0].interval * MSEC_PER_SEC) { |
232 | cmd->short_cycles_msec = cpu_to_le16(req->interval); | 232 | cmd->short_cycles_msec = |
233 | cpu_to_le16(req->scan_plans[0].interval * MSEC_PER_SEC); | ||
233 | cmd->long_cycles_msec = cpu_to_le16(c->long_interval); | 234 | cmd->long_cycles_msec = cpu_to_le16(c->long_interval); |
234 | cmd->short_cycles_count = c->num_short_intervals; | 235 | cmd->short_cycles_count = c->num_short_intervals; |
235 | } else { | 236 | } else { |
236 | cmd->short_cycles_msec = 0; | 237 | cmd->short_cycles_msec = 0; |
237 | cmd->long_cycles_msec = cpu_to_le16(req->interval); | 238 | cmd->long_cycles_msec = |
239 | cpu_to_le16(req->scan_plans[0].interval * MSEC_PER_SEC); | ||
238 | cmd->short_cycles_count = 0; | 240 | cmd->short_cycles_count = 0; |
239 | } | 241 | } |
240 | wl1271_debug(DEBUG_SCAN, "short_interval: %d, long_interval: %d, num_short: %d", | 242 | wl1271_debug(DEBUG_SCAN, "short_interval: %d, long_interval: %d, num_short: %d", |
diff --git a/include/linux/ieee80211.h b/include/linux/ieee80211.h index dcfb2f43d316..452c0b0d2f32 100644 --- a/include/linux/ieee80211.h +++ b/include/linux/ieee80211.h | |||
@@ -1932,6 +1932,8 @@ enum ieee80211_category { | |||
1932 | WLAN_CATEGORY_HT = 7, | 1932 | WLAN_CATEGORY_HT = 7, |
1933 | WLAN_CATEGORY_SA_QUERY = 8, | 1933 | WLAN_CATEGORY_SA_QUERY = 8, |
1934 | WLAN_CATEGORY_PROTECTED_DUAL_OF_ACTION = 9, | 1934 | WLAN_CATEGORY_PROTECTED_DUAL_OF_ACTION = 9, |
1935 | WLAN_CATEGORY_WNM = 10, | ||
1936 | WLAN_CATEGORY_WNM_UNPROTECTED = 11, | ||
1935 | WLAN_CATEGORY_TDLS = 12, | 1937 | WLAN_CATEGORY_TDLS = 12, |
1936 | WLAN_CATEGORY_MESH_ACTION = 13, | 1938 | WLAN_CATEGORY_MESH_ACTION = 13, |
1937 | WLAN_CATEGORY_MULTIHOP_ACTION = 14, | 1939 | WLAN_CATEGORY_MULTIHOP_ACTION = 14, |
@@ -2396,7 +2398,10 @@ static inline bool _ieee80211_is_robust_mgmt_frame(struct ieee80211_hdr *hdr) | |||
2396 | category = ((u8 *) hdr) + 24; | 2398 | category = ((u8 *) hdr) + 24; |
2397 | return *category != WLAN_CATEGORY_PUBLIC && | 2399 | return *category != WLAN_CATEGORY_PUBLIC && |
2398 | *category != WLAN_CATEGORY_HT && | 2400 | *category != WLAN_CATEGORY_HT && |
2401 | *category != WLAN_CATEGORY_WNM_UNPROTECTED && | ||
2399 | *category != WLAN_CATEGORY_SELF_PROTECTED && | 2402 | *category != WLAN_CATEGORY_SELF_PROTECTED && |
2403 | *category != WLAN_CATEGORY_UNPROT_DMG && | ||
2404 | *category != WLAN_CATEGORY_VHT && | ||
2400 | *category != WLAN_CATEGORY_VENDOR_SPECIFIC; | 2405 | *category != WLAN_CATEGORY_VENDOR_SPECIFIC; |
2401 | } | 2406 | } |
2402 | 2407 | ||
diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h index 90332a1838cc..48155be5db7f 100644 --- a/include/net/cfg80211.h +++ b/include/net/cfg80211.h | |||
@@ -5,6 +5,7 @@ | |||
5 | * | 5 | * |
6 | * Copyright 2006-2010 Johannes Berg <johannes@sipsolutions.net> | 6 | * Copyright 2006-2010 Johannes Berg <johannes@sipsolutions.net> |
7 | * Copyright 2013-2014 Intel Mobile Communications GmbH | 7 | * Copyright 2013-2014 Intel Mobile Communications GmbH |
8 | * Copyright 2015 Intel Deutschland GmbH | ||
8 | * | 9 | * |
9 | * This program is free software; you can redistribute it and/or modify | 10 | * This program is free software; you can redistribute it and/or modify |
10 | * it under the terms of the GNU General Public License version 2 as | 11 | * it under the terms of the GNU General Public License version 2 as |
@@ -1501,13 +1502,26 @@ struct cfg80211_match_set { | |||
1501 | }; | 1502 | }; |
1502 | 1503 | ||
1503 | /** | 1504 | /** |
1505 | * struct cfg80211_sched_scan_plan - scan plan for scheduled scan | ||
1506 | * | ||
1507 | * @interval: interval between scheduled scan iterations. In seconds. | ||
1508 | * @iterations: number of scan iterations in this scan plan. Zero means | ||
1509 | * infinite loop. | ||
1510 | * The last scan plan will always have this parameter set to zero, | ||
1511 | * all other scan plans will have a finite number of iterations. | ||
1512 | */ | ||
1513 | struct cfg80211_sched_scan_plan { | ||
1514 | u32 interval; | ||
1515 | u32 iterations; | ||
1516 | }; | ||
1517 | |||
1518 | /** | ||
1504 | * struct cfg80211_sched_scan_request - scheduled scan request description | 1519 | * struct cfg80211_sched_scan_request - scheduled scan request description |
1505 | * | 1520 | * |
1506 | * @ssids: SSIDs to scan for (passed in the probe_reqs in active scans) | 1521 | * @ssids: SSIDs to scan for (passed in the probe_reqs in active scans) |
1507 | * @n_ssids: number of SSIDs | 1522 | * @n_ssids: number of SSIDs |
1508 | * @n_channels: total number of channels to scan | 1523 | * @n_channels: total number of channels to scan |
1509 | * @scan_width: channel width for scanning | 1524 | * @scan_width: channel width for scanning |
1510 | * @interval: interval between each scheduled scan cycle | ||
1511 | * @ie: optional information element(s) to add into Probe Request or %NULL | 1525 | * @ie: optional information element(s) to add into Probe Request or %NULL |
1512 | * @ie_len: length of ie in octets | 1526 | * @ie_len: length of ie in octets |
1513 | * @flags: bit field of flags controlling operation | 1527 | * @flags: bit field of flags controlling operation |
@@ -1526,6 +1540,9 @@ struct cfg80211_match_set { | |||
1526 | * @mac_addr_mask: MAC address mask used with randomisation, bits that | 1540 | * @mac_addr_mask: MAC address mask used with randomisation, bits that |
1527 | * are 0 in the mask should be randomised, bits that are 1 should | 1541 | * are 0 in the mask should be randomised, bits that are 1 should |
1528 | * be taken from the @mac_addr | 1542 | * be taken from the @mac_addr |
1543 | * @scan_plans: scan plans to be executed in this scheduled scan. Lowest | ||
1544 | * index must be executed first. | ||
1545 | * @n_scan_plans: number of scan plans, at least 1. | ||
1529 | * @rcu_head: RCU callback used to free the struct | 1546 | * @rcu_head: RCU callback used to free the struct |
1530 | * @owner_nlportid: netlink portid of owner (if this should is a request | 1547 | * @owner_nlportid: netlink portid of owner (if this should is a request |
1531 | * owned by a particular socket) | 1548 | * owned by a particular socket) |
@@ -1539,7 +1556,6 @@ struct cfg80211_sched_scan_request { | |||
1539 | int n_ssids; | 1556 | int n_ssids; |
1540 | u32 n_channels; | 1557 | u32 n_channels; |
1541 | enum nl80211_bss_scan_width scan_width; | 1558 | enum nl80211_bss_scan_width scan_width; |
1542 | u32 interval; | ||
1543 | const u8 *ie; | 1559 | const u8 *ie; |
1544 | size_t ie_len; | 1560 | size_t ie_len; |
1545 | u32 flags; | 1561 | u32 flags; |
@@ -1547,6 +1563,8 @@ struct cfg80211_sched_scan_request { | |||
1547 | int n_match_sets; | 1563 | int n_match_sets; |
1548 | s32 min_rssi_thold; | 1564 | s32 min_rssi_thold; |
1549 | u32 delay; | 1565 | u32 delay; |
1566 | struct cfg80211_sched_scan_plan *scan_plans; | ||
1567 | int n_scan_plans; | ||
1550 | 1568 | ||
1551 | u8 mac_addr[ETH_ALEN] __aligned(2); | 1569 | u8 mac_addr[ETH_ALEN] __aligned(2); |
1552 | u8 mac_addr_mask[ETH_ALEN] __aligned(2); | 1570 | u8 mac_addr_mask[ETH_ALEN] __aligned(2); |
@@ -1576,6 +1594,26 @@ enum cfg80211_signal_type { | |||
1576 | }; | 1594 | }; |
1577 | 1595 | ||
1578 | /** | 1596 | /** |
1597 | * struct cfg80211_inform_bss - BSS inform data | ||
1598 | * @chan: channel the frame was received on | ||
1599 | * @scan_width: scan width that was used | ||
1600 | * @signal: signal strength value, according to the wiphy's | ||
1601 | * signal type | ||
1602 | * @boottime_ns: timestamp (CLOCK_BOOTTIME) when the information was | ||
1603 | * received; should match the time when the frame was actually | ||
1604 | * received by the device (not just by the host, in case it was | ||
1605 | * buffered on the device) and be accurate to about 10ms. | ||
1606 | * If the frame isn't buffered, just passing the return value of | ||
1607 | * ktime_get_boot_ns() is likely appropriate. | ||
1608 | */ | ||
1609 | struct cfg80211_inform_bss { | ||
1610 | struct ieee80211_channel *chan; | ||
1611 | enum nl80211_bss_scan_width scan_width; | ||
1612 | s32 signal; | ||
1613 | u64 boottime_ns; | ||
1614 | }; | ||
1615 | |||
1616 | /** | ||
1579 | * struct cfg80211_bss_ie_data - BSS entry IE data | 1617 | * struct cfg80211_bss_ie_data - BSS entry IE data |
1580 | * @tsf: TSF contained in the frame that carried these IEs | 1618 | * @tsf: TSF contained in the frame that carried these IEs |
1581 | * @rcu_head: internal use, for freeing | 1619 | * @rcu_head: internal use, for freeing |
@@ -3056,6 +3094,12 @@ struct wiphy_vendor_command { | |||
3056 | * include fixed IEs like supported rates | 3094 | * include fixed IEs like supported rates |
3057 | * @max_sched_scan_ie_len: same as max_scan_ie_len, but for scheduled | 3095 | * @max_sched_scan_ie_len: same as max_scan_ie_len, but for scheduled |
3058 | * scans | 3096 | * scans |
3097 | * @max_sched_scan_plans: maximum number of scan plans (scan interval and number | ||
3098 | * of iterations) for scheduled scan supported by the device. | ||
3099 | * @max_sched_scan_plan_interval: maximum interval (in seconds) for a | ||
3100 | * single scan plan supported by the device. | ||
3101 | * @max_sched_scan_plan_iterations: maximum number of iterations for a single | ||
3102 | * scan plan supported by the device. | ||
3059 | * @coverage_class: current coverage class | 3103 | * @coverage_class: current coverage class |
3060 | * @fw_version: firmware version for ethtool reporting | 3104 | * @fw_version: firmware version for ethtool reporting |
3061 | * @hw_version: hardware version for ethtool reporting | 3105 | * @hw_version: hardware version for ethtool reporting |
@@ -3163,6 +3207,9 @@ struct wiphy { | |||
3163 | u8 max_match_sets; | 3207 | u8 max_match_sets; |
3164 | u16 max_scan_ie_len; | 3208 | u16 max_scan_ie_len; |
3165 | u16 max_sched_scan_ie_len; | 3209 | u16 max_sched_scan_ie_len; |
3210 | u32 max_sched_scan_plans; | ||
3211 | u32 max_sched_scan_plan_interval; | ||
3212 | u32 max_sched_scan_plan_iterations; | ||
3166 | 3213 | ||
3167 | int n_cipher_suites; | 3214 | int n_cipher_suites; |
3168 | const u32 *cipher_suites; | 3215 | const u32 *cipher_suites; |
@@ -3958,14 +4005,11 @@ void cfg80211_sched_scan_stopped(struct wiphy *wiphy); | |||
3958 | void cfg80211_sched_scan_stopped_rtnl(struct wiphy *wiphy); | 4005 | void cfg80211_sched_scan_stopped_rtnl(struct wiphy *wiphy); |
3959 | 4006 | ||
3960 | /** | 4007 | /** |
3961 | * cfg80211_inform_bss_width_frame - inform cfg80211 of a received BSS frame | 4008 | * cfg80211_inform_bss_frame_data - inform cfg80211 of a received BSS frame |
3962 | * | ||
3963 | * @wiphy: the wiphy reporting the BSS | 4009 | * @wiphy: the wiphy reporting the BSS |
3964 | * @rx_channel: The channel the frame was received on | 4010 | * @data: the BSS metadata |
3965 | * @scan_width: width of the control channel | ||
3966 | * @mgmt: the management frame (probe response or beacon) | 4011 | * @mgmt: the management frame (probe response or beacon) |
3967 | * @len: length of the management frame | 4012 | * @len: length of the management frame |
3968 | * @signal: the signal strength, type depends on the wiphy's signal_type | ||
3969 | * @gfp: context flags | 4013 | * @gfp: context flags |
3970 | * | 4014 | * |
3971 | * This informs cfg80211 that BSS information was found and | 4015 | * This informs cfg80211 that BSS information was found and |
@@ -3975,11 +4019,26 @@ void cfg80211_sched_scan_stopped_rtnl(struct wiphy *wiphy); | |||
3975 | * Or %NULL on error. | 4019 | * Or %NULL on error. |
3976 | */ | 4020 | */ |
3977 | struct cfg80211_bss * __must_check | 4021 | struct cfg80211_bss * __must_check |
4022 | cfg80211_inform_bss_frame_data(struct wiphy *wiphy, | ||
4023 | struct cfg80211_inform_bss *data, | ||
4024 | struct ieee80211_mgmt *mgmt, size_t len, | ||
4025 | gfp_t gfp); | ||
4026 | |||
4027 | static inline struct cfg80211_bss * __must_check | ||
3978 | cfg80211_inform_bss_width_frame(struct wiphy *wiphy, | 4028 | cfg80211_inform_bss_width_frame(struct wiphy *wiphy, |
3979 | struct ieee80211_channel *rx_channel, | 4029 | struct ieee80211_channel *rx_channel, |
3980 | enum nl80211_bss_scan_width scan_width, | 4030 | enum nl80211_bss_scan_width scan_width, |
3981 | struct ieee80211_mgmt *mgmt, size_t len, | 4031 | struct ieee80211_mgmt *mgmt, size_t len, |
3982 | s32 signal, gfp_t gfp); | 4032 | s32 signal, gfp_t gfp) |
4033 | { | ||
4034 | struct cfg80211_inform_bss data = { | ||
4035 | .chan = rx_channel, | ||
4036 | .scan_width = scan_width, | ||
4037 | .signal = signal, | ||
4038 | }; | ||
4039 | |||
4040 | return cfg80211_inform_bss_frame_data(wiphy, &data, mgmt, len, gfp); | ||
4041 | } | ||
3983 | 4042 | ||
3984 | static inline struct cfg80211_bss * __must_check | 4043 | static inline struct cfg80211_bss * __must_check |
3985 | cfg80211_inform_bss_frame(struct wiphy *wiphy, | 4044 | cfg80211_inform_bss_frame(struct wiphy *wiphy, |
@@ -3987,9 +4046,13 @@ cfg80211_inform_bss_frame(struct wiphy *wiphy, | |||
3987 | struct ieee80211_mgmt *mgmt, size_t len, | 4046 | struct ieee80211_mgmt *mgmt, size_t len, |
3988 | s32 signal, gfp_t gfp) | 4047 | s32 signal, gfp_t gfp) |
3989 | { | 4048 | { |
3990 | return cfg80211_inform_bss_width_frame(wiphy, rx_channel, | 4049 | struct cfg80211_inform_bss data = { |
3991 | NL80211_BSS_CHAN_WIDTH_20, | 4050 | .chan = rx_channel, |
3992 | mgmt, len, signal, gfp); | 4051 | .scan_width = NL80211_BSS_CHAN_WIDTH_20, |
4052 | .signal = signal, | ||
4053 | }; | ||
4054 | |||
4055 | return cfg80211_inform_bss_frame_data(wiphy, &data, mgmt, len, gfp); | ||
3993 | } | 4056 | } |
3994 | 4057 | ||
3995 | /** | 4058 | /** |
@@ -4006,11 +4069,10 @@ enum cfg80211_bss_frame_type { | |||
4006 | }; | 4069 | }; |
4007 | 4070 | ||
4008 | /** | 4071 | /** |
4009 | * cfg80211_inform_bss_width - inform cfg80211 of a new BSS | 4072 | * cfg80211_inform_bss_data - inform cfg80211 of a new BSS |
4010 | * | 4073 | * |
4011 | * @wiphy: the wiphy reporting the BSS | 4074 | * @wiphy: the wiphy reporting the BSS |
4012 | * @rx_channel: The channel the frame was received on | 4075 | * @data: the BSS metadata |
4013 | * @scan_width: width of the control channel | ||
4014 | * @ftype: frame type (if known) | 4076 | * @ftype: frame type (if known) |
4015 | * @bssid: the BSSID of the BSS | 4077 | * @bssid: the BSSID of the BSS |
4016 | * @tsf: the TSF sent by the peer in the beacon/probe response (or 0) | 4078 | * @tsf: the TSF sent by the peer in the beacon/probe response (or 0) |
@@ -4018,7 +4080,6 @@ enum cfg80211_bss_frame_type { | |||
4018 | * @beacon_interval: the beacon interval announced by the peer | 4080 | * @beacon_interval: the beacon interval announced by the peer |
4019 | * @ie: additional IEs sent by the peer | 4081 | * @ie: additional IEs sent by the peer |
4020 | * @ielen: length of the additional IEs | 4082 | * @ielen: length of the additional IEs |
4021 | * @signal: the signal strength, type depends on the wiphy's signal_type | ||
4022 | * @gfp: context flags | 4083 | * @gfp: context flags |
4023 | * | 4084 | * |
4024 | * This informs cfg80211 that BSS information was found and | 4085 | * This informs cfg80211 that BSS information was found and |
@@ -4028,13 +4089,32 @@ enum cfg80211_bss_frame_type { | |||
4028 | * Or %NULL on error. | 4089 | * Or %NULL on error. |
4029 | */ | 4090 | */ |
4030 | struct cfg80211_bss * __must_check | 4091 | struct cfg80211_bss * __must_check |
4092 | cfg80211_inform_bss_data(struct wiphy *wiphy, | ||
4093 | struct cfg80211_inform_bss *data, | ||
4094 | enum cfg80211_bss_frame_type ftype, | ||
4095 | const u8 *bssid, u64 tsf, u16 capability, | ||
4096 | u16 beacon_interval, const u8 *ie, size_t ielen, | ||
4097 | gfp_t gfp); | ||
4098 | |||
4099 | static inline struct cfg80211_bss * __must_check | ||
4031 | cfg80211_inform_bss_width(struct wiphy *wiphy, | 4100 | cfg80211_inform_bss_width(struct wiphy *wiphy, |
4032 | struct ieee80211_channel *rx_channel, | 4101 | struct ieee80211_channel *rx_channel, |
4033 | enum nl80211_bss_scan_width scan_width, | 4102 | enum nl80211_bss_scan_width scan_width, |
4034 | enum cfg80211_bss_frame_type ftype, | 4103 | enum cfg80211_bss_frame_type ftype, |
4035 | const u8 *bssid, u64 tsf, u16 capability, | 4104 | const u8 *bssid, u64 tsf, u16 capability, |
4036 | u16 beacon_interval, const u8 *ie, size_t ielen, | 4105 | u16 beacon_interval, const u8 *ie, size_t ielen, |
4037 | s32 signal, gfp_t gfp); | 4106 | s32 signal, gfp_t gfp) |
4107 | { | ||
4108 | struct cfg80211_inform_bss data = { | ||
4109 | .chan = rx_channel, | ||
4110 | .scan_width = scan_width, | ||
4111 | .signal = signal, | ||
4112 | }; | ||
4113 | |||
4114 | return cfg80211_inform_bss_data(wiphy, &data, ftype, bssid, tsf, | ||
4115 | capability, beacon_interval, ie, ielen, | ||
4116 | gfp); | ||
4117 | } | ||
4038 | 4118 | ||
4039 | static inline struct cfg80211_bss * __must_check | 4119 | static inline struct cfg80211_bss * __must_check |
4040 | cfg80211_inform_bss(struct wiphy *wiphy, | 4120 | cfg80211_inform_bss(struct wiphy *wiphy, |
@@ -4044,11 +4124,15 @@ cfg80211_inform_bss(struct wiphy *wiphy, | |||
4044 | u16 beacon_interval, const u8 *ie, size_t ielen, | 4124 | u16 beacon_interval, const u8 *ie, size_t ielen, |
4045 | s32 signal, gfp_t gfp) | 4125 | s32 signal, gfp_t gfp) |
4046 | { | 4126 | { |
4047 | return cfg80211_inform_bss_width(wiphy, rx_channel, | 4127 | struct cfg80211_inform_bss data = { |
4048 | NL80211_BSS_CHAN_WIDTH_20, ftype, | 4128 | .chan = rx_channel, |
4049 | bssid, tsf, capability, | 4129 | .scan_width = NL80211_BSS_CHAN_WIDTH_20, |
4050 | beacon_interval, ie, ielen, signal, | 4130 | .signal = signal, |
4051 | gfp); | 4131 | }; |
4132 | |||
4133 | return cfg80211_inform_bss_data(wiphy, &data, ftype, bssid, tsf, | ||
4134 | capability, beacon_interval, ie, ielen, | ||
4135 | gfp); | ||
4052 | } | 4136 | } |
4053 | 4137 | ||
4054 | struct cfg80211_bss *cfg80211_get_bss(struct wiphy *wiphy, | 4138 | struct cfg80211_bss *cfg80211_get_bss(struct wiphy *wiphy, |
diff --git a/include/net/mac80211.h b/include/net/mac80211.h index 4ec6fedeb220..4b9dd070aeb9 100644 --- a/include/net/mac80211.h +++ b/include/net/mac80211.h | |||
@@ -1241,11 +1241,6 @@ enum ieee80211_smps_mode { | |||
1241 | * @flags: configuration flags defined above | 1241 | * @flags: configuration flags defined above |
1242 | * | 1242 | * |
1243 | * @listen_interval: listen interval in units of beacon interval | 1243 | * @listen_interval: listen interval in units of beacon interval |
1244 | * @max_sleep_period: the maximum number of beacon intervals to sleep for | ||
1245 | * before checking the beacon for a TIM bit (managed mode only); this | ||
1246 | * value will be only achievable between DTIM frames, the hardware | ||
1247 | * needs to check for the multicast traffic bit in DTIM beacons. | ||
1248 | * This variable is valid only when the CONF_PS flag is set. | ||
1249 | * @ps_dtim_period: The DTIM period of the AP we're connected to, for use | 1244 | * @ps_dtim_period: The DTIM period of the AP we're connected to, for use |
1250 | * in power saving. Power saving will not be enabled until a beacon | 1245 | * in power saving. Power saving will not be enabled until a beacon |
1251 | * has been received and the DTIM period is known. | 1246 | * has been received and the DTIM period is known. |
@@ -1275,7 +1270,6 @@ enum ieee80211_smps_mode { | |||
1275 | struct ieee80211_conf { | 1270 | struct ieee80211_conf { |
1276 | u32 flags; | 1271 | u32 flags; |
1277 | int power_level, dynamic_ps_timeout; | 1272 | int power_level, dynamic_ps_timeout; |
1278 | int max_sleep_period; | ||
1279 | 1273 | ||
1280 | u16 listen_interval; | 1274 | u16 listen_interval; |
1281 | u8 ps_dtim_period; | 1275 | u8 ps_dtim_period; |
@@ -1683,6 +1677,7 @@ struct ieee80211_sta_rates { | |||
1683 | * @tdls: indicates whether the STA is a TDLS peer | 1677 | * @tdls: indicates whether the STA is a TDLS peer |
1684 | * @tdls_initiator: indicates the STA is an initiator of the TDLS link. Only | 1678 | * @tdls_initiator: indicates the STA is an initiator of the TDLS link. Only |
1685 | * valid if the STA is a TDLS peer in the first place. | 1679 | * valid if the STA is a TDLS peer in the first place. |
1680 | * @mfp: indicates whether the STA uses management frame protection or not. | ||
1686 | * @txq: per-TID data TX queues (if driver uses the TXQ abstraction) | 1681 | * @txq: per-TID data TX queues (if driver uses the TXQ abstraction) |
1687 | */ | 1682 | */ |
1688 | struct ieee80211_sta { | 1683 | struct ieee80211_sta { |
@@ -1700,6 +1695,7 @@ struct ieee80211_sta { | |||
1700 | struct ieee80211_sta_rates __rcu *rates; | 1695 | struct ieee80211_sta_rates __rcu *rates; |
1701 | bool tdls; | 1696 | bool tdls; |
1702 | bool tdls_initiator; | 1697 | bool tdls_initiator; |
1698 | bool mfp; | ||
1703 | 1699 | ||
1704 | struct ieee80211_txq *txq[IEEE80211_NUM_TIDS]; | 1700 | struct ieee80211_txq *txq[IEEE80211_NUM_TIDS]; |
1705 | 1701 | ||
diff --git a/include/uapi/linux/nl80211.h b/include/uapi/linux/nl80211.h index c0ab6b0a3919..1f0b4cf5dd03 100644 --- a/include/uapi/linux/nl80211.h +++ b/include/uapi/linux/nl80211.h | |||
@@ -10,6 +10,7 @@ | |||
10 | * Copyright 2008, 2009 Luis R. Rodriguez <lrodriguez@atheros.com> | 10 | * Copyright 2008, 2009 Luis R. Rodriguez <lrodriguez@atheros.com> |
11 | * Copyright 2008 Jouni Malinen <jouni.malinen@atheros.com> | 11 | * Copyright 2008 Jouni Malinen <jouni.malinen@atheros.com> |
12 | * Copyright 2008 Colin McCabe <colin@cozybit.com> | 12 | * Copyright 2008 Colin McCabe <colin@cozybit.com> |
13 | * Copyright 2015 Intel Deutschland GmbH | ||
13 | * | 14 | * |
14 | * Permission to use, copy, modify, and/or distribute this software for any | 15 | * Permission to use, copy, modify, and/or distribute this software for any |
15 | * purpose with or without fee is hereby granted, provided that the above | 16 | * purpose with or without fee is hereby granted, provided that the above |
@@ -328,7 +329,15 @@ | |||
328 | * partial scan results may be available | 329 | * partial scan results may be available |
329 | * | 330 | * |
330 | * @NL80211_CMD_START_SCHED_SCAN: start a scheduled scan at certain | 331 | * @NL80211_CMD_START_SCHED_SCAN: start a scheduled scan at certain |
331 | * intervals, as specified by %NL80211_ATTR_SCHED_SCAN_INTERVAL. | 332 | * intervals and certain number of cycles, as specified by |
333 | * %NL80211_ATTR_SCHED_SCAN_PLANS. If %NL80211_ATTR_SCHED_SCAN_PLANS is | ||
334 | * not specified and only %NL80211_ATTR_SCHED_SCAN_INTERVAL is specified, | ||
335 | * scheduled scan will run in an infinite loop with the specified interval. | ||
336 | * These attributes are mutually exculsive, | ||
337 | * i.e. NL80211_ATTR_SCHED_SCAN_INTERVAL must not be passed if | ||
338 | * NL80211_ATTR_SCHED_SCAN_PLANS is defined. | ||
339 | * If for some reason scheduled scan is aborted by the driver, all scan | ||
340 | * plans are canceled (including scan plans that did not start yet). | ||
332 | * Like with normal scans, if SSIDs (%NL80211_ATTR_SCAN_SSIDS) | 341 | * Like with normal scans, if SSIDs (%NL80211_ATTR_SCAN_SSIDS) |
333 | * are passed, they are used in the probe requests. For | 342 | * are passed, they are used in the probe requests. For |
334 | * broadcast, a broadcast SSID must be passed (ie. an empty | 343 | * broadcast, a broadcast SSID must be passed (ie. an empty |
@@ -1761,6 +1770,19 @@ enum nl80211_commands { | |||
1761 | * @NL80211_ATTR_REG_INDOOR: flag attribute, if set indicates that the device | 1770 | * @NL80211_ATTR_REG_INDOOR: flag attribute, if set indicates that the device |
1762 | * is operating in an indoor environment. | 1771 | * is operating in an indoor environment. |
1763 | * | 1772 | * |
1773 | * @NL80211_ATTR_MAX_NUM_SCHED_SCAN_PLANS: maximum number of scan plans for | ||
1774 | * scheduled scan supported by the device (u32), a wiphy attribute. | ||
1775 | * @NL80211_ATTR_MAX_SCAN_PLAN_INTERVAL: maximum interval (in seconds) for | ||
1776 | * a scan plan (u32), a wiphy attribute. | ||
1777 | * @NL80211_ATTR_MAX_SCAN_PLAN_ITERATIONS: maximum number of iterations in | ||
1778 | * a scan plan (u32), a wiphy attribute. | ||
1779 | * @NL80211_ATTR_SCHED_SCAN_PLANS: a list of scan plans for scheduled scan. | ||
1780 | * Each scan plan defines the number of scan iterations and the interval | ||
1781 | * between scans. The last scan plan will always run infinitely, | ||
1782 | * thus it must not specify the number of iterations, only the interval | ||
1783 | * between scans. The scan plans are executed sequentially. | ||
1784 | * Each scan plan is a nested attribute of &enum nl80211_sched_scan_plan. | ||
1785 | * | ||
1764 | * @NUM_NL80211_ATTR: total number of nl80211_attrs available | 1786 | * @NUM_NL80211_ATTR: total number of nl80211_attrs available |
1765 | * @NL80211_ATTR_MAX: highest attribute number currently defined | 1787 | * @NL80211_ATTR_MAX: highest attribute number currently defined |
1766 | * @__NL80211_ATTR_AFTER_LAST: internal use | 1788 | * @__NL80211_ATTR_AFTER_LAST: internal use |
@@ -2130,6 +2152,11 @@ enum nl80211_attrs { | |||
2130 | 2152 | ||
2131 | NL80211_ATTR_REG_INDOOR, | 2153 | NL80211_ATTR_REG_INDOOR, |
2132 | 2154 | ||
2155 | NL80211_ATTR_MAX_NUM_SCHED_SCAN_PLANS, | ||
2156 | NL80211_ATTR_MAX_SCAN_PLAN_INTERVAL, | ||
2157 | NL80211_ATTR_MAX_SCAN_PLAN_ITERATIONS, | ||
2158 | NL80211_ATTR_SCHED_SCAN_PLANS, | ||
2159 | |||
2133 | /* add attributes here, update the policy in nl80211.c */ | 2160 | /* add attributes here, update the policy in nl80211.c */ |
2134 | 2161 | ||
2135 | __NL80211_ATTR_AFTER_LAST, | 2162 | __NL80211_ATTR_AFTER_LAST, |
@@ -3364,6 +3391,9 @@ enum nl80211_bss_scan_width { | |||
3364 | * (not present if no beacon frame has been received yet) | 3391 | * (not present if no beacon frame has been received yet) |
3365 | * @NL80211_BSS_PRESP_DATA: the data in @NL80211_BSS_INFORMATION_ELEMENTS and | 3392 | * @NL80211_BSS_PRESP_DATA: the data in @NL80211_BSS_INFORMATION_ELEMENTS and |
3366 | * @NL80211_BSS_TSF is known to be from a probe response (flag attribute) | 3393 | * @NL80211_BSS_TSF is known to be from a probe response (flag attribute) |
3394 | * @NL80211_BSS_LAST_SEEN_BOOTTIME: CLOCK_BOOTTIME timestamp when this entry | ||
3395 | * was last updated by a received frame. The value is expected to be | ||
3396 | * accurate to about 10ms. (u64, nanoseconds) | ||
3367 | * @__NL80211_BSS_AFTER_LAST: internal | 3397 | * @__NL80211_BSS_AFTER_LAST: internal |
3368 | * @NL80211_BSS_MAX: highest BSS attribute | 3398 | * @NL80211_BSS_MAX: highest BSS attribute |
3369 | */ | 3399 | */ |
@@ -3383,6 +3413,7 @@ enum nl80211_bss { | |||
3383 | NL80211_BSS_CHAN_WIDTH, | 3413 | NL80211_BSS_CHAN_WIDTH, |
3384 | NL80211_BSS_BEACON_TSF, | 3414 | NL80211_BSS_BEACON_TSF, |
3385 | NL80211_BSS_PRESP_DATA, | 3415 | NL80211_BSS_PRESP_DATA, |
3416 | NL80211_BSS_LAST_SEEN_BOOTTIME, | ||
3386 | 3417 | ||
3387 | /* keep last */ | 3418 | /* keep last */ |
3388 | __NL80211_BSS_AFTER_LAST, | 3419 | __NL80211_BSS_AFTER_LAST, |
@@ -4589,4 +4620,28 @@ enum nl80211_tdls_peer_capability { | |||
4589 | NL80211_TDLS_PEER_WMM = 1<<2, | 4620 | NL80211_TDLS_PEER_WMM = 1<<2, |
4590 | }; | 4621 | }; |
4591 | 4622 | ||
4623 | /** | ||
4624 | * enum nl80211_sched_scan_plan - scanning plan for scheduled scan | ||
4625 | * @__NL80211_SCHED_SCAN_PLAN_INVALID: attribute number 0 is reserved | ||
4626 | * @NL80211_SCHED_SCAN_PLAN_INTERVAL: interval between scan iterations. In | ||
4627 | * seconds (u32). | ||
4628 | * @NL80211_SCHED_SCAN_PLAN_ITERATIONS: number of scan iterations in this | ||
4629 | * scan plan (u32). The last scan plan must not specify this attribute | ||
4630 | * because it will run infinitely. A value of zero is invalid as it will | ||
4631 | * make the scan plan meaningless. | ||
4632 | * @NL80211_SCHED_SCAN_PLAN_MAX: highest scheduled scan plan attribute number | ||
4633 | * currently defined | ||
4634 | * @__NL80211_SCHED_SCAN_PLAN_AFTER_LAST: internal use | ||
4635 | */ | ||
4636 | enum nl80211_sched_scan_plan { | ||
4637 | __NL80211_SCHED_SCAN_PLAN_INVALID, | ||
4638 | NL80211_SCHED_SCAN_PLAN_INTERVAL, | ||
4639 | NL80211_SCHED_SCAN_PLAN_ITERATIONS, | ||
4640 | |||
4641 | /* keep last */ | ||
4642 | __NL80211_SCHED_SCAN_PLAN_AFTER_LAST, | ||
4643 | NL80211_SCHED_SCAN_PLAN_MAX = | ||
4644 | __NL80211_SCHED_SCAN_PLAN_AFTER_LAST - 1 | ||
4645 | }; | ||
4646 | |||
4592 | #endif /* __LINUX_NL80211_H */ | 4647 | #endif /* __LINUX_NL80211_H */ |
diff --git a/net/mac80211/Makefile b/net/mac80211/Makefile index 783e891b7525..f9137a8341f4 100644 --- a/net/mac80211/Makefile +++ b/net/mac80211/Makefile | |||
@@ -27,7 +27,6 @@ mac80211-y := \ | |||
27 | key.o \ | 27 | key.o \ |
28 | util.o \ | 28 | util.o \ |
29 | wme.o \ | 29 | wme.o \ |
30 | event.o \ | ||
31 | chan.o \ | 30 | chan.o \ |
32 | trace.o mlme.o \ | 31 | trace.o mlme.o \ |
33 | tdls.o \ | 32 | tdls.o \ |
diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c index 68e551e263c6..713cdbf6fb3c 100644 --- a/net/mac80211/cfg.c +++ b/net/mac80211/cfg.c | |||
@@ -17,7 +17,6 @@ | |||
17 | #include <net/cfg80211.h> | 17 | #include <net/cfg80211.h> |
18 | #include "ieee80211_i.h" | 18 | #include "ieee80211_i.h" |
19 | #include "driver-ops.h" | 19 | #include "driver-ops.h" |
20 | #include "cfg.h" | ||
21 | #include "rate.h" | 20 | #include "rate.h" |
22 | #include "mesh.h" | 21 | #include "mesh.h" |
23 | #include "wme.h" | 22 | #include "wme.h" |
@@ -469,45 +468,6 @@ void sta_set_rate_info_tx(struct sta_info *sta, | |||
469 | rinfo->flags |= RATE_INFO_FLAGS_SHORT_GI; | 468 | rinfo->flags |= RATE_INFO_FLAGS_SHORT_GI; |
470 | } | 469 | } |
471 | 470 | ||
472 | void sta_set_rate_info_rx(struct sta_info *sta, struct rate_info *rinfo) | ||
473 | { | ||
474 | rinfo->flags = 0; | ||
475 | |||
476 | if (sta->last_rx_rate_flag & RX_FLAG_HT) { | ||
477 | rinfo->flags |= RATE_INFO_FLAGS_MCS; | ||
478 | rinfo->mcs = sta->last_rx_rate_idx; | ||
479 | } else if (sta->last_rx_rate_flag & RX_FLAG_VHT) { | ||
480 | rinfo->flags |= RATE_INFO_FLAGS_VHT_MCS; | ||
481 | rinfo->nss = sta->last_rx_rate_vht_nss; | ||
482 | rinfo->mcs = sta->last_rx_rate_idx; | ||
483 | } else { | ||
484 | struct ieee80211_supported_band *sband; | ||
485 | int shift = ieee80211_vif_get_shift(&sta->sdata->vif); | ||
486 | u16 brate; | ||
487 | |||
488 | sband = sta->local->hw.wiphy->bands[ | ||
489 | ieee80211_get_sdata_band(sta->sdata)]; | ||
490 | brate = sband->bitrates[sta->last_rx_rate_idx].bitrate; | ||
491 | rinfo->legacy = DIV_ROUND_UP(brate, 1 << shift); | ||
492 | } | ||
493 | |||
494 | if (sta->last_rx_rate_flag & RX_FLAG_SHORT_GI) | ||
495 | rinfo->flags |= RATE_INFO_FLAGS_SHORT_GI; | ||
496 | |||
497 | if (sta->last_rx_rate_flag & RX_FLAG_5MHZ) | ||
498 | rinfo->bw = RATE_INFO_BW_5; | ||
499 | else if (sta->last_rx_rate_flag & RX_FLAG_10MHZ) | ||
500 | rinfo->bw = RATE_INFO_BW_10; | ||
501 | else if (sta->last_rx_rate_flag & RX_FLAG_40MHZ) | ||
502 | rinfo->bw = RATE_INFO_BW_40; | ||
503 | else if (sta->last_rx_rate_vht_flag & RX_VHT_FLAG_80MHZ) | ||
504 | rinfo->bw = RATE_INFO_BW_80; | ||
505 | else if (sta->last_rx_rate_vht_flag & RX_VHT_FLAG_160MHZ) | ||
506 | rinfo->bw = RATE_INFO_BW_160; | ||
507 | else | ||
508 | rinfo->bw = RATE_INFO_BW_20; | ||
509 | } | ||
510 | |||
511 | static int ieee80211_dump_station(struct wiphy *wiphy, struct net_device *dev, | 471 | static int ieee80211_dump_station(struct wiphy *wiphy, struct net_device *dev, |
512 | int idx, u8 *mac, struct station_info *sinfo) | 472 | int idx, u8 *mac, struct station_info *sinfo) |
513 | { | 473 | { |
@@ -1138,6 +1098,7 @@ static int sta_apply_parameters(struct ieee80211_local *local, | |||
1138 | } | 1098 | } |
1139 | 1099 | ||
1140 | if (mask & BIT(NL80211_STA_FLAG_MFP)) { | 1100 | if (mask & BIT(NL80211_STA_FLAG_MFP)) { |
1101 | sta->sta.mfp = !!(set & BIT(NL80211_STA_FLAG_MFP)); | ||
1141 | if (set & BIT(NL80211_STA_FLAG_MFP)) | 1102 | if (set & BIT(NL80211_STA_FLAG_MFP)) |
1142 | set_sta_flag(sta, WLAN_STA_MFP); | 1103 | set_sta_flag(sta, WLAN_STA_MFP); |
1143 | else | 1104 | else |
@@ -1427,7 +1388,7 @@ static int ieee80211_change_station(struct wiphy *wiphy, | |||
1427 | 1388 | ||
1428 | if (sdata->vif.type == NL80211_IFTYPE_STATION && | 1389 | if (sdata->vif.type == NL80211_IFTYPE_STATION && |
1429 | params->sta_flags_mask & BIT(NL80211_STA_FLAG_AUTHORIZED)) { | 1390 | params->sta_flags_mask & BIT(NL80211_STA_FLAG_AUTHORIZED)) { |
1430 | ieee80211_recalc_ps(local, -1); | 1391 | ieee80211_recalc_ps(local); |
1431 | ieee80211_recalc_ps_vif(sdata); | 1392 | ieee80211_recalc_ps_vif(sdata); |
1432 | } | 1393 | } |
1433 | 1394 | ||
@@ -2462,7 +2423,7 @@ static int ieee80211_set_power_mgmt(struct wiphy *wiphy, struct net_device *dev, | |||
2462 | if (ieee80211_hw_check(&local->hw, SUPPORTS_DYNAMIC_PS)) | 2423 | if (ieee80211_hw_check(&local->hw, SUPPORTS_DYNAMIC_PS)) |
2463 | ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_PS); | 2424 | ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_PS); |
2464 | 2425 | ||
2465 | ieee80211_recalc_ps(local, -1); | 2426 | ieee80211_recalc_ps(local); |
2466 | ieee80211_recalc_ps_vif(sdata); | 2427 | ieee80211_recalc_ps_vif(sdata); |
2467 | 2428 | ||
2468 | return 0; | 2429 | return 0; |
diff --git a/net/mac80211/cfg.h b/net/mac80211/cfg.h deleted file mode 100644 index 2d51f62dc76c..000000000000 --- a/net/mac80211/cfg.h +++ /dev/null | |||
@@ -1,9 +0,0 @@ | |||
1 | /* | ||
2 | * mac80211 configuration hooks for cfg80211 | ||
3 | */ | ||
4 | #ifndef __CFG_H | ||
5 | #define __CFG_H | ||
6 | |||
7 | extern const struct cfg80211_ops mac80211_config_ops; | ||
8 | |||
9 | #endif /* __CFG_H */ | ||
diff --git a/net/mac80211/debugfs_sta.c b/net/mac80211/debugfs_sta.c index 06d52935036d..a39512f09f9e 100644 --- a/net/mac80211/debugfs_sta.c +++ b/net/mac80211/debugfs_sta.c | |||
@@ -50,7 +50,6 @@ static const struct file_operations sta_ ##name## _ops = { \ | |||
50 | STA_OPS(name) | 50 | STA_OPS(name) |
51 | 51 | ||
52 | STA_FILE(aid, sta.aid, D); | 52 | STA_FILE(aid, sta.aid, D); |
53 | STA_FILE(last_ack_signal, last_ack_signal, D); | ||
54 | 53 | ||
55 | static ssize_t sta_flags_read(struct file *file, char __user *userbuf, | 54 | static ssize_t sta_flags_read(struct file *file, char __user *userbuf, |
56 | size_t count, loff_t *ppos) | 55 | size_t count, loff_t *ppos) |
@@ -366,11 +365,10 @@ void ieee80211_sta_debugfs_add(struct sta_info *sta) | |||
366 | DEBUGFS_ADD(agg_status); | 365 | DEBUGFS_ADD(agg_status); |
367 | DEBUGFS_ADD(ht_capa); | 366 | DEBUGFS_ADD(ht_capa); |
368 | DEBUGFS_ADD(vht_capa); | 367 | DEBUGFS_ADD(vht_capa); |
369 | DEBUGFS_ADD(last_ack_signal); | ||
370 | 368 | ||
371 | DEBUGFS_ADD_COUNTER(rx_duplicates, num_duplicates); | 369 | DEBUGFS_ADD_COUNTER(rx_duplicates, rx_stats.num_duplicates); |
372 | DEBUGFS_ADD_COUNTER(rx_fragments, rx_fragments); | 370 | DEBUGFS_ADD_COUNTER(rx_fragments, rx_stats.fragments); |
373 | DEBUGFS_ADD_COUNTER(tx_filtered, tx_filtered_count); | 371 | DEBUGFS_ADD_COUNTER(tx_filtered, status_stats.filtered); |
374 | 372 | ||
375 | if (sizeof(sta->driver_buffered_tids) == sizeof(u32)) | 373 | if (sizeof(sta->driver_buffered_tids) == sizeof(u32)) |
376 | debugfs_create_x32("driver_buffered_tids", 0400, | 374 | debugfs_create_x32("driver_buffered_tids", 0400, |
diff --git a/net/mac80211/ethtool.c b/net/mac80211/ethtool.c index 188faab11c24..9cc986deda61 100644 --- a/net/mac80211/ethtool.c +++ b/net/mac80211/ethtool.c | |||
@@ -40,7 +40,7 @@ static const char ieee80211_gstrings_sta_stats[][ETH_GSTRING_LEN] = { | |||
40 | "rx_duplicates", "rx_fragments", "rx_dropped", | 40 | "rx_duplicates", "rx_fragments", "rx_dropped", |
41 | "tx_packets", "tx_bytes", | 41 | "tx_packets", "tx_bytes", |
42 | "tx_filtered", "tx_retry_failed", "tx_retries", | 42 | "tx_filtered", "tx_retry_failed", "tx_retries", |
43 | "beacon_loss", "sta_state", "txrate", "rxrate", "signal", | 43 | "sta_state", "txrate", "rxrate", "signal", |
44 | "channel", "noise", "ch_time", "ch_time_busy", | 44 | "channel", "noise", "ch_time", "ch_time_busy", |
45 | "ch_time_ext_busy", "ch_time_rx", "ch_time_tx" | 45 | "ch_time_ext_busy", "ch_time_rx", "ch_time_tx" |
46 | }; | 46 | }; |
@@ -77,20 +77,19 @@ static void ieee80211_get_stats(struct net_device *dev, | |||
77 | 77 | ||
78 | memset(data, 0, sizeof(u64) * STA_STATS_LEN); | 78 | memset(data, 0, sizeof(u64) * STA_STATS_LEN); |
79 | 79 | ||
80 | #define ADD_STA_STATS(sta) \ | 80 | #define ADD_STA_STATS(sta) \ |
81 | do { \ | 81 | do { \ |
82 | data[i++] += sta->rx_packets; \ | 82 | data[i++] += sta->rx_stats.packets; \ |
83 | data[i++] += sta->rx_bytes; \ | 83 | data[i++] += sta->rx_stats.bytes; \ |
84 | data[i++] += sta->num_duplicates; \ | 84 | data[i++] += sta->rx_stats.num_duplicates; \ |
85 | data[i++] += sta->rx_fragments; \ | 85 | data[i++] += sta->rx_stats.fragments; \ |
86 | data[i++] += sta->rx_dropped; \ | 86 | data[i++] += sta->rx_stats.dropped; \ |
87 | \ | 87 | \ |
88 | data[i++] += sinfo.tx_packets; \ | 88 | data[i++] += sinfo.tx_packets; \ |
89 | data[i++] += sinfo.tx_bytes; \ | 89 | data[i++] += sinfo.tx_bytes; \ |
90 | data[i++] += sta->tx_filtered_count; \ | 90 | data[i++] += sta->status_stats.filtered; \ |
91 | data[i++] += sta->tx_retry_failed; \ | 91 | data[i++] += sta->status_stats.retry_failed; \ |
92 | data[i++] += sta->tx_retry_count; \ | 92 | data[i++] += sta->status_stats.retry_count; \ |
93 | data[i++] += sta->beacon_loss_count; \ | ||
94 | } while (0) | 93 | } while (0) |
95 | 94 | ||
96 | /* For Managed stations, find the single station based on BSSID | 95 | /* For Managed stations, find the single station based on BSSID |
diff --git a/net/mac80211/event.c b/net/mac80211/event.c deleted file mode 100644 index 01ae759518f6..000000000000 --- a/net/mac80211/event.c +++ /dev/null | |||
@@ -1,27 +0,0 @@ | |||
1 | /* | ||
2 | * Copyright 2007 Johannes Berg <johannes@sipsolutions.net> | ||
3 | * | ||
4 | * This program is free software; you can redistribute it and/or modify | ||
5 | * it under the terms of the GNU General Public License version 2 as | ||
6 | * published by the Free Software Foundation. | ||
7 | * | ||
8 | * mac80211 - events | ||
9 | */ | ||
10 | #include <net/cfg80211.h> | ||
11 | #include "ieee80211_i.h" | ||
12 | |||
13 | /* | ||
14 | * Indicate a failed Michael MIC to userspace. If the caller knows the TSC of | ||
15 | * the frame that generated the MIC failure (i.e., if it was provided by the | ||
16 | * driver or is still in the frame), it should provide that information. | ||
17 | */ | ||
18 | void mac80211_ev_michael_mic_failure(struct ieee80211_sub_if_data *sdata, int keyidx, | ||
19 | struct ieee80211_hdr *hdr, const u8 *tsc, | ||
20 | gfp_t gfp) | ||
21 | { | ||
22 | cfg80211_michael_mic_failure(sdata->dev, hdr->addr2, | ||
23 | (hdr->addr1[0] & 0x01) ? | ||
24 | NL80211_KEYTYPE_GROUP : | ||
25 | NL80211_KEYTYPE_PAIRWISE, | ||
26 | keyidx, tsc, gfp); | ||
27 | } | ||
diff --git a/net/mac80211/ibss.c b/net/mac80211/ibss.c index 7f72bc9bae2e..2001555d49cb 100644 --- a/net/mac80211/ibss.c +++ b/net/mac80211/ibss.c | |||
@@ -229,7 +229,7 @@ static void __ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata, | |||
229 | struct cfg80211_chan_def chandef; | 229 | struct cfg80211_chan_def chandef; |
230 | struct ieee80211_channel *chan; | 230 | struct ieee80211_channel *chan; |
231 | struct beacon_data *presp; | 231 | struct beacon_data *presp; |
232 | enum nl80211_bss_scan_width scan_width; | 232 | struct cfg80211_inform_bss bss_meta = {}; |
233 | bool have_higher_than_11mbit; | 233 | bool have_higher_than_11mbit; |
234 | bool radar_required; | 234 | bool radar_required; |
235 | int err; | 235 | int err; |
@@ -383,10 +383,11 @@ static void __ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata, | |||
383 | mod_timer(&ifibss->timer, | 383 | mod_timer(&ifibss->timer, |
384 | round_jiffies(jiffies + IEEE80211_IBSS_MERGE_INTERVAL)); | 384 | round_jiffies(jiffies + IEEE80211_IBSS_MERGE_INTERVAL)); |
385 | 385 | ||
386 | scan_width = cfg80211_chandef_to_scan_width(&chandef); | 386 | bss_meta.chan = chan; |
387 | bss = cfg80211_inform_bss_width_frame(local->hw.wiphy, chan, | 387 | bss_meta.scan_width = cfg80211_chandef_to_scan_width(&chandef); |
388 | scan_width, mgmt, | 388 | bss = cfg80211_inform_bss_frame_data(local->hw.wiphy, &bss_meta, mgmt, |
389 | presp->head_len, 0, GFP_KERNEL); | 389 | presp->head_len, GFP_KERNEL); |
390 | |||
390 | cfg80211_put_bss(local->hw.wiphy, bss); | 391 | cfg80211_put_bss(local->hw.wiphy, bss); |
391 | netif_carrier_on(sdata->dev); | 392 | netif_carrier_on(sdata->dev); |
392 | cfg80211_ibss_joined(sdata->dev, ifibss->bssid, chan, GFP_KERNEL); | 393 | cfg80211_ibss_joined(sdata->dev, ifibss->bssid, chan, GFP_KERNEL); |
@@ -646,7 +647,7 @@ ieee80211_ibss_add_sta(struct ieee80211_sub_if_data *sdata, const u8 *bssid, | |||
646 | return NULL; | 647 | return NULL; |
647 | } | 648 | } |
648 | 649 | ||
649 | sta->last_rx = jiffies; | 650 | sta->rx_stats.last_rx = jiffies; |
650 | 651 | ||
651 | /* make sure mandatory rates are always added */ | 652 | /* make sure mandatory rates are always added */ |
652 | sband = local->hw.wiphy->bands[band]; | 653 | sband = local->hw.wiphy->bands[band]; |
@@ -668,7 +669,8 @@ static int ieee80211_sta_active_ibss(struct ieee80211_sub_if_data *sdata) | |||
668 | 669 | ||
669 | list_for_each_entry_rcu(sta, &local->sta_list, list) { | 670 | list_for_each_entry_rcu(sta, &local->sta_list, list) { |
670 | if (sta->sdata == sdata && | 671 | if (sta->sdata == sdata && |
671 | time_after(sta->last_rx + IEEE80211_IBSS_MERGE_INTERVAL, | 672 | time_after(sta->rx_stats.last_rx + |
673 | IEEE80211_IBSS_MERGE_INTERVAL, | ||
672 | jiffies)) { | 674 | jiffies)) { |
673 | active++; | 675 | active++; |
674 | break; | 676 | break; |
@@ -1234,7 +1236,7 @@ void ieee80211_ibss_rx_no_sta(struct ieee80211_sub_if_data *sdata, | |||
1234 | if (!sta) | 1236 | if (!sta) |
1235 | return; | 1237 | return; |
1236 | 1238 | ||
1237 | sta->last_rx = jiffies; | 1239 | sta->rx_stats.last_rx = jiffies; |
1238 | 1240 | ||
1239 | /* make sure mandatory rates are always added */ | 1241 | /* make sure mandatory rates are always added */ |
1240 | sband = local->hw.wiphy->bands[band]; | 1242 | sband = local->hw.wiphy->bands[band]; |
@@ -1252,7 +1254,7 @@ static void ieee80211_ibss_sta_expire(struct ieee80211_sub_if_data *sdata) | |||
1252 | struct ieee80211_local *local = sdata->local; | 1254 | struct ieee80211_local *local = sdata->local; |
1253 | struct sta_info *sta, *tmp; | 1255 | struct sta_info *sta, *tmp; |
1254 | unsigned long exp_time = IEEE80211_IBSS_INACTIVITY_LIMIT; | 1256 | unsigned long exp_time = IEEE80211_IBSS_INACTIVITY_LIMIT; |
1255 | unsigned long exp_rsn_time = IEEE80211_IBSS_RSN_INACTIVITY_LIMIT; | 1257 | unsigned long exp_rsn = IEEE80211_IBSS_RSN_INACTIVITY_LIMIT; |
1256 | 1258 | ||
1257 | mutex_lock(&local->sta_mtx); | 1259 | mutex_lock(&local->sta_mtx); |
1258 | 1260 | ||
@@ -1260,8 +1262,8 @@ static void ieee80211_ibss_sta_expire(struct ieee80211_sub_if_data *sdata) | |||
1260 | if (sdata != sta->sdata) | 1262 | if (sdata != sta->sdata) |
1261 | continue; | 1263 | continue; |
1262 | 1264 | ||
1263 | if (time_after(jiffies, sta->last_rx + exp_time) || | 1265 | if (time_after(jiffies, sta->rx_stats.last_rx + exp_time) || |
1264 | (time_after(jiffies, sta->last_rx + exp_rsn_time) && | 1266 | (time_after(jiffies, sta->rx_stats.last_rx + exp_rsn) && |
1265 | sta->sta_state != IEEE80211_STA_AUTHORIZED)) { | 1267 | sta->sta_state != IEEE80211_STA_AUTHORIZED)) { |
1266 | sta_dbg(sta->sdata, "expiring inactive %sSTA %pM\n", | 1268 | sta_dbg(sta->sdata, "expiring inactive %sSTA %pM\n", |
1267 | sta->sta_state != IEEE80211_STA_AUTHORIZED ? | 1269 | sta->sta_state != IEEE80211_STA_AUTHORIZED ? |
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h index f9605f13def9..62f2a97cd2a6 100644 --- a/net/mac80211/ieee80211_i.h +++ b/net/mac80211/ieee80211_i.h | |||
@@ -34,6 +34,8 @@ | |||
34 | #include "sta_info.h" | 34 | #include "sta_info.h" |
35 | #include "debug.h" | 35 | #include "debug.h" |
36 | 36 | ||
37 | extern const struct cfg80211_ops mac80211_config_ops; | ||
38 | |||
37 | struct ieee80211_local; | 39 | struct ieee80211_local; |
38 | 40 | ||
39 | /* Maximum number of broadcast/multicast frames to buffer when some of the | 41 | /* Maximum number of broadcast/multicast frames to buffer when some of the |
@@ -501,6 +503,9 @@ struct ieee80211_if_managed { | |||
501 | */ | 503 | */ |
502 | unsigned int count_beacon_signal; | 504 | unsigned int count_beacon_signal; |
503 | 505 | ||
506 | /* Number of times beacon loss was invoked. */ | ||
507 | unsigned int beacon_loss_count; | ||
508 | |||
504 | /* | 509 | /* |
505 | * Last Beacon frame signal strength average (ave_beacon_signal / 16) | 510 | * Last Beacon frame signal strength average (ave_beacon_signal / 16) |
506 | * that triggered a cqm event. 0 indicates that no event has been | 511 | * that triggered a cqm event. 0 indicates that no event has been |
@@ -1305,7 +1310,6 @@ struct ieee80211_local { | |||
1305 | struct work_struct dynamic_ps_enable_work; | 1310 | struct work_struct dynamic_ps_enable_work; |
1306 | struct work_struct dynamic_ps_disable_work; | 1311 | struct work_struct dynamic_ps_disable_work; |
1307 | struct timer_list dynamic_ps_timer; | 1312 | struct timer_list dynamic_ps_timer; |
1308 | struct notifier_block network_latency_notifier; | ||
1309 | struct notifier_block ifa_notifier; | 1313 | struct notifier_block ifa_notifier; |
1310 | struct notifier_block ifa6_notifier; | 1314 | struct notifier_block ifa6_notifier; |
1311 | 1315 | ||
@@ -1491,10 +1495,8 @@ int ieee80211_mgd_disassoc(struct ieee80211_sub_if_data *sdata, | |||
1491 | struct cfg80211_disassoc_request *req); | 1495 | struct cfg80211_disassoc_request *req); |
1492 | void ieee80211_send_pspoll(struct ieee80211_local *local, | 1496 | void ieee80211_send_pspoll(struct ieee80211_local *local, |
1493 | struct ieee80211_sub_if_data *sdata); | 1497 | struct ieee80211_sub_if_data *sdata); |
1494 | void ieee80211_recalc_ps(struct ieee80211_local *local, s32 latency); | 1498 | void ieee80211_recalc_ps(struct ieee80211_local *local); |
1495 | void ieee80211_recalc_ps_vif(struct ieee80211_sub_if_data *sdata); | 1499 | void ieee80211_recalc_ps_vif(struct ieee80211_sub_if_data *sdata); |
1496 | int ieee80211_max_network_latency(struct notifier_block *nb, | ||
1497 | unsigned long data, void *dummy); | ||
1498 | int ieee80211_set_arp_filter(struct ieee80211_sub_if_data *sdata); | 1500 | int ieee80211_set_arp_filter(struct ieee80211_sub_if_data *sdata); |
1499 | void ieee80211_sta_work(struct ieee80211_sub_if_data *sdata); | 1501 | void ieee80211_sta_work(struct ieee80211_sub_if_data *sdata); |
1500 | void ieee80211_sta_rx_queued_mgmt(struct ieee80211_sub_if_data *sdata, | 1502 | void ieee80211_sta_rx_queued_mgmt(struct ieee80211_sub_if_data *sdata, |
@@ -1766,9 +1768,6 @@ extern const void *const mac80211_wiphy_privid; /* for wiphy privid */ | |||
1766 | int ieee80211_frame_duration(enum ieee80211_band band, size_t len, | 1768 | int ieee80211_frame_duration(enum ieee80211_band band, size_t len, |
1767 | int rate, int erp, int short_preamble, | 1769 | int rate, int erp, int short_preamble, |
1768 | int shift); | 1770 | int shift); |
1769 | void mac80211_ev_michael_mic_failure(struct ieee80211_sub_if_data *sdata, int keyidx, | ||
1770 | struct ieee80211_hdr *hdr, const u8 *tsc, | ||
1771 | gfp_t gfp); | ||
1772 | void ieee80211_set_wmm_default(struct ieee80211_sub_if_data *sdata, | 1771 | void ieee80211_set_wmm_default(struct ieee80211_sub_if_data *sdata, |
1773 | bool bss_notify); | 1772 | bool bss_notify); |
1774 | void ieee80211_xmit(struct ieee80211_sub_if_data *sdata, | 1773 | void ieee80211_xmit(struct ieee80211_sub_if_data *sdata, |
diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c index 42d7f0f65bd6..f848c75518a2 100644 --- a/net/mac80211/iface.c +++ b/net/mac80211/iface.c | |||
@@ -709,7 +709,7 @@ int ieee80211_do_open(struct wireless_dev *wdev, bool coming_up) | |||
709 | if (hw_reconf_flags) | 709 | if (hw_reconf_flags) |
710 | ieee80211_hw_config(local, hw_reconf_flags); | 710 | ieee80211_hw_config(local, hw_reconf_flags); |
711 | 711 | ||
712 | ieee80211_recalc_ps(local, -1); | 712 | ieee80211_recalc_ps(local); |
713 | 713 | ||
714 | if (sdata->vif.type == NL80211_IFTYPE_MONITOR || | 714 | if (sdata->vif.type == NL80211_IFTYPE_MONITOR || |
715 | sdata->vif.type == NL80211_IFTYPE_AP_VLAN) { | 715 | sdata->vif.type == NL80211_IFTYPE_AP_VLAN) { |
@@ -1016,7 +1016,7 @@ static void ieee80211_do_stop(struct ieee80211_sub_if_data *sdata, | |||
1016 | drv_remove_interface(local, sdata); | 1016 | drv_remove_interface(local, sdata); |
1017 | } | 1017 | } |
1018 | 1018 | ||
1019 | ieee80211_recalc_ps(local, -1); | 1019 | ieee80211_recalc_ps(local); |
1020 | 1020 | ||
1021 | if (cancel_scan) | 1021 | if (cancel_scan) |
1022 | flush_delayed_work(&local->scan_work); | 1022 | flush_delayed_work(&local->scan_work); |
diff --git a/net/mac80211/main.c b/net/mac80211/main.c index 9b813a2f3a75..273c96de4910 100644 --- a/net/mac80211/main.c +++ b/net/mac80211/main.c | |||
@@ -20,7 +20,6 @@ | |||
20 | #include <linux/if_arp.h> | 20 | #include <linux/if_arp.h> |
21 | #include <linux/rtnetlink.h> | 21 | #include <linux/rtnetlink.h> |
22 | #include <linux/bitmap.h> | 22 | #include <linux/bitmap.h> |
23 | #include <linux/pm_qos.h> | ||
24 | #include <linux/inetdevice.h> | 23 | #include <linux/inetdevice.h> |
25 | #include <net/net_namespace.h> | 24 | #include <net/net_namespace.h> |
26 | #include <net/cfg80211.h> | 25 | #include <net/cfg80211.h> |
@@ -32,7 +31,6 @@ | |||
32 | #include "mesh.h" | 31 | #include "mesh.h" |
33 | #include "wep.h" | 32 | #include "wep.h" |
34 | #include "led.h" | 33 | #include "led.h" |
35 | #include "cfg.h" | ||
36 | #include "debugfs.h" | 34 | #include "debugfs.h" |
37 | 35 | ||
38 | void ieee80211_configure_filter(struct ieee80211_local *local) | 36 | void ieee80211_configure_filter(struct ieee80211_local *local) |
@@ -1083,13 +1081,6 @@ int ieee80211_register_hw(struct ieee80211_hw *hw) | |||
1083 | 1081 | ||
1084 | rtnl_unlock(); | 1082 | rtnl_unlock(); |
1085 | 1083 | ||
1086 | local->network_latency_notifier.notifier_call = | ||
1087 | ieee80211_max_network_latency; | ||
1088 | result = pm_qos_add_notifier(PM_QOS_NETWORK_LATENCY, | ||
1089 | &local->network_latency_notifier); | ||
1090 | if (result) | ||
1091 | goto fail_pm_qos; | ||
1092 | |||
1093 | #ifdef CONFIG_INET | 1084 | #ifdef CONFIG_INET |
1094 | local->ifa_notifier.notifier_call = ieee80211_ifa_changed; | 1085 | local->ifa_notifier.notifier_call = ieee80211_ifa_changed; |
1095 | result = register_inetaddr_notifier(&local->ifa_notifier); | 1086 | result = register_inetaddr_notifier(&local->ifa_notifier); |
@@ -1114,10 +1105,7 @@ int ieee80211_register_hw(struct ieee80211_hw *hw) | |||
1114 | #endif | 1105 | #endif |
1115 | #if defined(CONFIG_INET) || defined(CONFIG_IPV6) | 1106 | #if defined(CONFIG_INET) || defined(CONFIG_IPV6) |
1116 | fail_ifa: | 1107 | fail_ifa: |
1117 | pm_qos_remove_notifier(PM_QOS_NETWORK_LATENCY, | ||
1118 | &local->network_latency_notifier); | ||
1119 | #endif | 1108 | #endif |
1120 | fail_pm_qos: | ||
1121 | rtnl_lock(); | 1109 | rtnl_lock(); |
1122 | rate_control_deinitialize(local); | 1110 | rate_control_deinitialize(local); |
1123 | ieee80211_remove_interfaces(local); | 1111 | ieee80211_remove_interfaces(local); |
@@ -1143,8 +1131,6 @@ void ieee80211_unregister_hw(struct ieee80211_hw *hw) | |||
1143 | tasklet_kill(&local->tx_pending_tasklet); | 1131 | tasklet_kill(&local->tx_pending_tasklet); |
1144 | tasklet_kill(&local->tasklet); | 1132 | tasklet_kill(&local->tasklet); |
1145 | 1133 | ||
1146 | pm_qos_remove_notifier(PM_QOS_NETWORK_LATENCY, | ||
1147 | &local->network_latency_notifier); | ||
1148 | #ifdef CONFIG_INET | 1134 | #ifdef CONFIG_INET |
1149 | unregister_inetaddr_notifier(&local->ifa_notifier); | 1135 | unregister_inetaddr_notifier(&local->ifa_notifier); |
1150 | #endif | 1136 | #endif |
diff --git a/net/mac80211/mesh_hwmp.c b/net/mac80211/mesh_hwmp.c index d80e0a4c16cf..c6be0b4f4058 100644 --- a/net/mac80211/mesh_hwmp.c +++ b/net/mac80211/mesh_hwmp.c | |||
@@ -329,7 +329,7 @@ static u32 airtime_link_metric_get(struct ieee80211_local *local, | |||
329 | if (sta->mesh->fail_avg >= 100) | 329 | if (sta->mesh->fail_avg >= 100) |
330 | return MAX_METRIC; | 330 | return MAX_METRIC; |
331 | 331 | ||
332 | sta_set_rate_info_tx(sta, &sta->last_tx_rate, &rinfo); | 332 | sta_set_rate_info_tx(sta, &sta->tx_stats.last_rate, &rinfo); |
333 | rate = cfg80211_calculate_bitrate(&rinfo); | 333 | rate = cfg80211_calculate_bitrate(&rinfo); |
334 | if (WARN_ON(!rate)) | 334 | if (WARN_ON(!rate)) |
335 | return MAX_METRIC; | 335 | return MAX_METRIC; |
diff --git a/net/mac80211/mesh_plink.c b/net/mac80211/mesh_plink.c index a360b24b7df8..c1f889270484 100644 --- a/net/mac80211/mesh_plink.c +++ b/net/mac80211/mesh_plink.c | |||
@@ -60,7 +60,9 @@ static bool rssi_threshold_check(struct ieee80211_sub_if_data *sdata, | |||
60 | { | 60 | { |
61 | s32 rssi_threshold = sdata->u.mesh.mshcfg.rssi_threshold; | 61 | s32 rssi_threshold = sdata->u.mesh.mshcfg.rssi_threshold; |
62 | return rssi_threshold == 0 || | 62 | return rssi_threshold == 0 || |
63 | (sta && (s8) -ewma_signal_read(&sta->avg_signal) > rssi_threshold); | 63 | (sta && |
64 | (s8)-ewma_signal_read(&sta->rx_stats.avg_signal) > | ||
65 | rssi_threshold); | ||
64 | } | 66 | } |
65 | 67 | ||
66 | /** | 68 | /** |
@@ -390,7 +392,7 @@ static void mesh_sta_info_init(struct ieee80211_sub_if_data *sdata, | |||
390 | rates = ieee80211_sta_get_rates(sdata, elems, band, &basic_rates); | 392 | rates = ieee80211_sta_get_rates(sdata, elems, band, &basic_rates); |
391 | 393 | ||
392 | spin_lock_bh(&sta->mesh->plink_lock); | 394 | spin_lock_bh(&sta->mesh->plink_lock); |
393 | sta->last_rx = jiffies; | 395 | sta->rx_stats.last_rx = jiffies; |
394 | 396 | ||
395 | /* rates and capabilities don't change during peering */ | 397 | /* rates and capabilities don't change during peering */ |
396 | if (sta->mesh->plink_state == NL80211_PLINK_ESTAB && | 398 | if (sta->mesh->plink_state == NL80211_PLINK_ESTAB && |
diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index 56ef9a8e151c..ded4b976bb48 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c | |||
@@ -20,7 +20,6 @@ | |||
20 | #include <linux/etherdevice.h> | 20 | #include <linux/etherdevice.h> |
21 | #include <linux/moduleparam.h> | 21 | #include <linux/moduleparam.h> |
22 | #include <linux/rtnetlink.h> | 22 | #include <linux/rtnetlink.h> |
23 | #include <linux/pm_qos.h> | ||
24 | #include <linux/crc32.h> | 23 | #include <linux/crc32.h> |
25 | #include <linux/slab.h> | 24 | #include <linux/slab.h> |
26 | #include <linux/export.h> | 25 | #include <linux/export.h> |
@@ -1476,7 +1475,7 @@ static bool ieee80211_powersave_allowed(struct ieee80211_sub_if_data *sdata) | |||
1476 | } | 1475 | } |
1477 | 1476 | ||
1478 | /* need to hold RTNL or interface lock */ | 1477 | /* need to hold RTNL or interface lock */ |
1479 | void ieee80211_recalc_ps(struct ieee80211_local *local, s32 latency) | 1478 | void ieee80211_recalc_ps(struct ieee80211_local *local) |
1480 | { | 1479 | { |
1481 | struct ieee80211_sub_if_data *sdata, *found = NULL; | 1480 | struct ieee80211_sub_if_data *sdata, *found = NULL; |
1482 | int count = 0; | 1481 | int count = 0; |
@@ -1505,48 +1504,23 @@ void ieee80211_recalc_ps(struct ieee80211_local *local, s32 latency) | |||
1505 | } | 1504 | } |
1506 | 1505 | ||
1507 | if (count == 1 && ieee80211_powersave_allowed(found)) { | 1506 | if (count == 1 && ieee80211_powersave_allowed(found)) { |
1507 | u8 dtimper = found->u.mgd.dtim_period; | ||
1508 | s32 beaconint_us; | 1508 | s32 beaconint_us; |
1509 | 1509 | ||
1510 | if (latency < 0) | ||
1511 | latency = pm_qos_request(PM_QOS_NETWORK_LATENCY); | ||
1512 | |||
1513 | beaconint_us = ieee80211_tu_to_usec( | 1510 | beaconint_us = ieee80211_tu_to_usec( |
1514 | found->vif.bss_conf.beacon_int); | 1511 | found->vif.bss_conf.beacon_int); |
1515 | 1512 | ||
1516 | timeout = local->dynamic_ps_forced_timeout; | 1513 | timeout = local->dynamic_ps_forced_timeout; |
1517 | if (timeout < 0) { | 1514 | if (timeout < 0) |
1518 | /* | 1515 | timeout = 100; |
1519 | * Go to full PSM if the user configures a very low | ||
1520 | * latency requirement. | ||
1521 | * The 2000 second value is there for compatibility | ||
1522 | * until the PM_QOS_NETWORK_LATENCY is configured | ||
1523 | * with real values. | ||
1524 | */ | ||
1525 | if (latency > (1900 * USEC_PER_MSEC) && | ||
1526 | latency != (2000 * USEC_PER_SEC)) | ||
1527 | timeout = 0; | ||
1528 | else | ||
1529 | timeout = 100; | ||
1530 | } | ||
1531 | local->hw.conf.dynamic_ps_timeout = timeout; | 1516 | local->hw.conf.dynamic_ps_timeout = timeout; |
1532 | 1517 | ||
1533 | if (beaconint_us > latency) { | 1518 | /* If the TIM IE is invalid, pretend the value is 1 */ |
1534 | local->ps_sdata = NULL; | 1519 | if (!dtimper) |
1535 | } else { | 1520 | dtimper = 1; |
1536 | int maxslp = 1; | 1521 | |
1537 | u8 dtimper = found->u.mgd.dtim_period; | 1522 | local->hw.conf.ps_dtim_period = dtimper; |
1538 | 1523 | local->ps_sdata = found; | |
1539 | /* If the TIM IE is invalid, pretend the value is 1 */ | ||
1540 | if (!dtimper) | ||
1541 | dtimper = 1; | ||
1542 | else if (dtimper > 1) | ||
1543 | maxslp = min_t(int, dtimper, | ||
1544 | latency / beaconint_us); | ||
1545 | |||
1546 | local->hw.conf.max_sleep_period = maxslp; | ||
1547 | local->hw.conf.ps_dtim_period = dtimper; | ||
1548 | local->ps_sdata = found; | ||
1549 | } | ||
1550 | } else { | 1524 | } else { |
1551 | local->ps_sdata = NULL; | 1525 | local->ps_sdata = NULL; |
1552 | } | 1526 | } |
@@ -1997,7 +1971,7 @@ static void ieee80211_set_associated(struct ieee80211_sub_if_data *sdata, | |||
1997 | ieee80211_bss_info_change_notify(sdata, bss_info_changed); | 1971 | ieee80211_bss_info_change_notify(sdata, bss_info_changed); |
1998 | 1972 | ||
1999 | mutex_lock(&local->iflist_mtx); | 1973 | mutex_lock(&local->iflist_mtx); |
2000 | ieee80211_recalc_ps(local, -1); | 1974 | ieee80211_recalc_ps(local); |
2001 | mutex_unlock(&local->iflist_mtx); | 1975 | mutex_unlock(&local->iflist_mtx); |
2002 | 1976 | ||
2003 | ieee80211_recalc_smps(sdata); | 1977 | ieee80211_recalc_smps(sdata); |
@@ -2165,7 +2139,7 @@ static void ieee80211_reset_ap_probe(struct ieee80211_sub_if_data *sdata) | |||
2165 | __ieee80211_stop_poll(sdata); | 2139 | __ieee80211_stop_poll(sdata); |
2166 | 2140 | ||
2167 | mutex_lock(&local->iflist_mtx); | 2141 | mutex_lock(&local->iflist_mtx); |
2168 | ieee80211_recalc_ps(local, -1); | 2142 | ieee80211_recalc_ps(local); |
2169 | mutex_unlock(&local->iflist_mtx); | 2143 | mutex_unlock(&local->iflist_mtx); |
2170 | 2144 | ||
2171 | if (ieee80211_hw_check(&sdata->local->hw, CONNECTION_MONITOR)) | 2145 | if (ieee80211_hw_check(&sdata->local->hw, CONNECTION_MONITOR)) |
@@ -2341,7 +2315,7 @@ static void ieee80211_mgd_probe_ap(struct ieee80211_sub_if_data *sdata, | |||
2341 | goto out; | 2315 | goto out; |
2342 | 2316 | ||
2343 | mutex_lock(&sdata->local->iflist_mtx); | 2317 | mutex_lock(&sdata->local->iflist_mtx); |
2344 | ieee80211_recalc_ps(sdata->local, -1); | 2318 | ieee80211_recalc_ps(sdata->local); |
2345 | mutex_unlock(&sdata->local->iflist_mtx); | 2319 | mutex_unlock(&sdata->local->iflist_mtx); |
2346 | 2320 | ||
2347 | ifmgd->probe_send_count = 0; | 2321 | ifmgd->probe_send_count = 0; |
@@ -2446,15 +2420,9 @@ static void ieee80211_beacon_connection_loss_work(struct work_struct *work) | |||
2446 | container_of(work, struct ieee80211_sub_if_data, | 2420 | container_of(work, struct ieee80211_sub_if_data, |
2447 | u.mgd.beacon_connection_loss_work); | 2421 | u.mgd.beacon_connection_loss_work); |
2448 | struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; | 2422 | struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; |
2449 | struct sta_info *sta; | ||
2450 | 2423 | ||
2451 | if (ifmgd->associated) { | 2424 | if (ifmgd->associated) |
2452 | rcu_read_lock(); | 2425 | ifmgd->beacon_loss_count++; |
2453 | sta = sta_info_get(sdata, ifmgd->bssid); | ||
2454 | if (sta) | ||
2455 | sta->beacon_loss_count++; | ||
2456 | rcu_read_unlock(); | ||
2457 | } | ||
2458 | 2426 | ||
2459 | if (ifmgd->connection_loss) { | 2427 | if (ifmgd->connection_loss) { |
2460 | sdata_info(sdata, "Connection to AP %pM lost\n", | 2428 | sdata_info(sdata, "Connection to AP %pM lost\n", |
@@ -3044,8 +3012,12 @@ static bool ieee80211_assoc_success(struct ieee80211_sub_if_data *sdata, | |||
3044 | 3012 | ||
3045 | rate_control_rate_init(sta); | 3013 | rate_control_rate_init(sta); |
3046 | 3014 | ||
3047 | if (ifmgd->flags & IEEE80211_STA_MFP_ENABLED) | 3015 | if (ifmgd->flags & IEEE80211_STA_MFP_ENABLED) { |
3048 | set_sta_flag(sta, WLAN_STA_MFP); | 3016 | set_sta_flag(sta, WLAN_STA_MFP); |
3017 | sta->sta.mfp = true; | ||
3018 | } else { | ||
3019 | sta->sta.mfp = false; | ||
3020 | } | ||
3049 | 3021 | ||
3050 | sta->sta.wme = elems.wmm_param && local->hw.queues >= IEEE80211_NUM_ACS; | 3022 | sta->sta.wme = elems.wmm_param && local->hw.queues >= IEEE80211_NUM_ACS; |
3051 | 3023 | ||
@@ -3544,7 +3516,7 @@ static void ieee80211_rx_mgmt_beacon(struct ieee80211_sub_if_data *sdata, | |||
3544 | ifmgd->have_beacon = true; | 3516 | ifmgd->have_beacon = true; |
3545 | 3517 | ||
3546 | mutex_lock(&local->iflist_mtx); | 3518 | mutex_lock(&local->iflist_mtx); |
3547 | ieee80211_recalc_ps(local, -1); | 3519 | ieee80211_recalc_ps(local); |
3548 | mutex_unlock(&local->iflist_mtx); | 3520 | mutex_unlock(&local->iflist_mtx); |
3549 | 3521 | ||
3550 | ieee80211_recalc_ps_vif(sdata); | 3522 | ieee80211_recalc_ps_vif(sdata); |
@@ -4148,21 +4120,6 @@ void ieee80211_mlme_notify_scan_completed(struct ieee80211_local *local) | |||
4148 | rcu_read_unlock(); | 4120 | rcu_read_unlock(); |
4149 | } | 4121 | } |
4150 | 4122 | ||
4151 | int ieee80211_max_network_latency(struct notifier_block *nb, | ||
4152 | unsigned long data, void *dummy) | ||
4153 | { | ||
4154 | s32 latency_usec = (s32) data; | ||
4155 | struct ieee80211_local *local = | ||
4156 | container_of(nb, struct ieee80211_local, | ||
4157 | network_latency_notifier); | ||
4158 | |||
4159 | mutex_lock(&local->iflist_mtx); | ||
4160 | ieee80211_recalc_ps(local, latency_usec); | ||
4161 | mutex_unlock(&local->iflist_mtx); | ||
4162 | |||
4163 | return NOTIFY_OK; | ||
4164 | } | ||
4165 | |||
4166 | static u8 ieee80211_ht_vht_rx_chains(struct ieee80211_sub_if_data *sdata, | 4123 | static u8 ieee80211_ht_vht_rx_chains(struct ieee80211_sub_if_data *sdata, |
4167 | struct cfg80211_bss *cbss) | 4124 | struct cfg80211_bss *cbss) |
4168 | { | 4125 | { |
diff --git a/net/mac80211/ocb.c b/net/mac80211/ocb.c index 573b81a1fb2d..0be0aadfc559 100644 --- a/net/mac80211/ocb.c +++ b/net/mac80211/ocb.c | |||
@@ -75,7 +75,7 @@ void ieee80211_ocb_rx_no_sta(struct ieee80211_sub_if_data *sdata, | |||
75 | if (!sta) | 75 | if (!sta) |
76 | return; | 76 | return; |
77 | 77 | ||
78 | sta->last_rx = jiffies; | 78 | sta->rx_stats.last_rx = jiffies; |
79 | 79 | ||
80 | /* Add only mandatory rates for now */ | 80 | /* Add only mandatory rates for now */ |
81 | sband = local->hw.wiphy->bands[band]; | 81 | sband = local->hw.wiphy->bands[band]; |
diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c index 5bc0b88d9eb1..8bae5de0dc44 100644 --- a/net/mac80211/rx.c +++ b/net/mac80211/rx.c | |||
@@ -1113,16 +1113,16 @@ ieee80211_rx_h_check_dup(struct ieee80211_rx_data *rx) | |||
1113 | is_multicast_ether_addr(hdr->addr1)) | 1113 | is_multicast_ether_addr(hdr->addr1)) |
1114 | return RX_CONTINUE; | 1114 | return RX_CONTINUE; |
1115 | 1115 | ||
1116 | if (rx->sta) { | 1116 | if (!rx->sta) |
1117 | if (unlikely(ieee80211_has_retry(hdr->frame_control) && | 1117 | return RX_CONTINUE; |
1118 | rx->sta->last_seq_ctrl[rx->seqno_idx] == | 1118 | |
1119 | hdr->seq_ctrl)) { | 1119 | if (unlikely(ieee80211_has_retry(hdr->frame_control) && |
1120 | I802_DEBUG_INC(rx->local->dot11FrameDuplicateCount); | 1120 | rx->sta->last_seq_ctrl[rx->seqno_idx] == hdr->seq_ctrl)) { |
1121 | rx->sta->num_duplicates++; | 1121 | I802_DEBUG_INC(rx->local->dot11FrameDuplicateCount); |
1122 | return RX_DROP_UNUSABLE; | 1122 | rx->sta->rx_stats.num_duplicates++; |
1123 | } else if (!(status->flag & RX_FLAG_AMSDU_MORE)) { | 1123 | return RX_DROP_UNUSABLE; |
1124 | rx->sta->last_seq_ctrl[rx->seqno_idx] = hdr->seq_ctrl; | 1124 | } else if (!(status->flag & RX_FLAG_AMSDU_MORE)) { |
1125 | } | 1125 | rx->sta->last_seq_ctrl[rx->seqno_idx] = hdr->seq_ctrl; |
1126 | } | 1126 | } |
1127 | 1127 | ||
1128 | return RX_CONTINUE; | 1128 | return RX_CONTINUE; |
@@ -1396,51 +1396,56 @@ ieee80211_rx_h_sta_process(struct ieee80211_rx_data *rx) | |||
1396 | NL80211_IFTYPE_ADHOC); | 1396 | NL80211_IFTYPE_ADHOC); |
1397 | if (ether_addr_equal(bssid, rx->sdata->u.ibss.bssid) && | 1397 | if (ether_addr_equal(bssid, rx->sdata->u.ibss.bssid) && |
1398 | test_sta_flag(sta, WLAN_STA_AUTHORIZED)) { | 1398 | test_sta_flag(sta, WLAN_STA_AUTHORIZED)) { |
1399 | sta->last_rx = jiffies; | 1399 | sta->rx_stats.last_rx = jiffies; |
1400 | if (ieee80211_is_data(hdr->frame_control) && | 1400 | if (ieee80211_is_data(hdr->frame_control) && |
1401 | !is_multicast_ether_addr(hdr->addr1)) { | 1401 | !is_multicast_ether_addr(hdr->addr1)) { |
1402 | sta->last_rx_rate_idx = status->rate_idx; | 1402 | sta->rx_stats.last_rate_idx = |
1403 | sta->last_rx_rate_flag = status->flag; | 1403 | status->rate_idx; |
1404 | sta->last_rx_rate_vht_flag = status->vht_flag; | 1404 | sta->rx_stats.last_rate_flag = |
1405 | sta->last_rx_rate_vht_nss = status->vht_nss; | 1405 | status->flag; |
1406 | sta->rx_stats.last_rate_vht_flag = | ||
1407 | status->vht_flag; | ||
1408 | sta->rx_stats.last_rate_vht_nss = | ||
1409 | status->vht_nss; | ||
1406 | } | 1410 | } |
1407 | } | 1411 | } |
1408 | } else if (rx->sdata->vif.type == NL80211_IFTYPE_OCB) { | 1412 | } else if (rx->sdata->vif.type == NL80211_IFTYPE_OCB) { |
1409 | sta->last_rx = jiffies; | 1413 | sta->rx_stats.last_rx = jiffies; |
1410 | } else if (!is_multicast_ether_addr(hdr->addr1)) { | 1414 | } else if (!is_multicast_ether_addr(hdr->addr1)) { |
1411 | /* | 1415 | /* |
1412 | * Mesh beacons will update last_rx when if they are found to | 1416 | * Mesh beacons will update last_rx when if they are found to |
1413 | * match the current local configuration when processed. | 1417 | * match the current local configuration when processed. |
1414 | */ | 1418 | */ |
1415 | sta->last_rx = jiffies; | 1419 | sta->rx_stats.last_rx = jiffies; |
1416 | if (ieee80211_is_data(hdr->frame_control)) { | 1420 | if (ieee80211_is_data(hdr->frame_control)) { |
1417 | sta->last_rx_rate_idx = status->rate_idx; | 1421 | sta->rx_stats.last_rate_idx = status->rate_idx; |
1418 | sta->last_rx_rate_flag = status->flag; | 1422 | sta->rx_stats.last_rate_flag = status->flag; |
1419 | sta->last_rx_rate_vht_flag = status->vht_flag; | 1423 | sta->rx_stats.last_rate_vht_flag = status->vht_flag; |
1420 | sta->last_rx_rate_vht_nss = status->vht_nss; | 1424 | sta->rx_stats.last_rate_vht_nss = status->vht_nss; |
1421 | } | 1425 | } |
1422 | } | 1426 | } |
1423 | 1427 | ||
1424 | if (rx->sdata->vif.type == NL80211_IFTYPE_STATION) | 1428 | if (rx->sdata->vif.type == NL80211_IFTYPE_STATION) |
1425 | ieee80211_sta_rx_notify(rx->sdata, hdr); | 1429 | ieee80211_sta_rx_notify(rx->sdata, hdr); |
1426 | 1430 | ||
1427 | sta->rx_fragments++; | 1431 | sta->rx_stats.fragments++; |
1428 | sta->rx_bytes += rx->skb->len; | 1432 | sta->rx_stats.bytes += rx->skb->len; |
1429 | if (!(status->flag & RX_FLAG_NO_SIGNAL_VAL)) { | 1433 | if (!(status->flag & RX_FLAG_NO_SIGNAL_VAL)) { |
1430 | sta->last_signal = status->signal; | 1434 | sta->rx_stats.last_signal = status->signal; |
1431 | ewma_signal_add(&sta->avg_signal, -status->signal); | 1435 | ewma_signal_add(&sta->rx_stats.avg_signal, -status->signal); |
1432 | } | 1436 | } |
1433 | 1437 | ||
1434 | if (status->chains) { | 1438 | if (status->chains) { |
1435 | sta->chains = status->chains; | 1439 | sta->rx_stats.chains = status->chains; |
1436 | for (i = 0; i < ARRAY_SIZE(status->chain_signal); i++) { | 1440 | for (i = 0; i < ARRAY_SIZE(status->chain_signal); i++) { |
1437 | int signal = status->chain_signal[i]; | 1441 | int signal = status->chain_signal[i]; |
1438 | 1442 | ||
1439 | if (!(status->chains & BIT(i))) | 1443 | if (!(status->chains & BIT(i))) |
1440 | continue; | 1444 | continue; |
1441 | 1445 | ||
1442 | sta->chain_signal_last[i] = signal; | 1446 | sta->rx_stats.chain_signal_last[i] = signal; |
1443 | ewma_signal_add(&sta->chain_signal_avg[i], -signal); | 1447 | ewma_signal_add(&sta->rx_stats.chain_signal_avg[i], |
1448 | -signal); | ||
1444 | } | 1449 | } |
1445 | } | 1450 | } |
1446 | 1451 | ||
@@ -1500,7 +1505,7 @@ ieee80211_rx_h_sta_process(struct ieee80211_rx_data *rx) | |||
1500 | * Update counter and free packet here to avoid | 1505 | * Update counter and free packet here to avoid |
1501 | * counting this as a dropped packed. | 1506 | * counting this as a dropped packed. |
1502 | */ | 1507 | */ |
1503 | sta->rx_packets++; | 1508 | sta->rx_stats.packets++; |
1504 | dev_kfree_skb(rx->skb); | 1509 | dev_kfree_skb(rx->skb); |
1505 | return RX_QUEUED; | 1510 | return RX_QUEUED; |
1506 | } | 1511 | } |
@@ -1922,7 +1927,7 @@ ieee80211_rx_h_defragment(struct ieee80211_rx_data *rx) | |||
1922 | ieee80211_led_rx(rx->local); | 1927 | ieee80211_led_rx(rx->local); |
1923 | out_no_led: | 1928 | out_no_led: |
1924 | if (rx->sta) | 1929 | if (rx->sta) |
1925 | rx->sta->rx_packets++; | 1930 | rx->sta->rx_stats.packets++; |
1926 | return RX_CONTINUE; | 1931 | return RX_CONTINUE; |
1927 | } | 1932 | } |
1928 | 1933 | ||
@@ -2376,7 +2381,7 @@ ieee80211_rx_h_data(struct ieee80211_rx_data *rx) | |||
2376 | * for non-QoS-data frames. Here we know it's a data | 2381 | * for non-QoS-data frames. Here we know it's a data |
2377 | * frame, so count MSDUs. | 2382 | * frame, so count MSDUs. |
2378 | */ | 2383 | */ |
2379 | rx->sta->rx_msdu[rx->seqno_idx]++; | 2384 | rx->sta->rx_stats.msdu[rx->seqno_idx]++; |
2380 | } | 2385 | } |
2381 | 2386 | ||
2382 | /* | 2387 | /* |
@@ -2413,7 +2418,7 @@ ieee80211_rx_h_data(struct ieee80211_rx_data *rx) | |||
2413 | skb_queue_tail(&local->skb_queue_tdls_chsw, rx->skb); | 2418 | skb_queue_tail(&local->skb_queue_tdls_chsw, rx->skb); |
2414 | schedule_work(&local->tdls_chsw_work); | 2419 | schedule_work(&local->tdls_chsw_work); |
2415 | if (rx->sta) | 2420 | if (rx->sta) |
2416 | rx->sta->rx_packets++; | 2421 | rx->sta->rx_stats.packets++; |
2417 | 2422 | ||
2418 | return RX_QUEUED; | 2423 | return RX_QUEUED; |
2419 | } | 2424 | } |
@@ -2875,7 +2880,7 @@ ieee80211_rx_h_action(struct ieee80211_rx_data *rx) | |||
2875 | 2880 | ||
2876 | handled: | 2881 | handled: |
2877 | if (rx->sta) | 2882 | if (rx->sta) |
2878 | rx->sta->rx_packets++; | 2883 | rx->sta->rx_stats.packets++; |
2879 | dev_kfree_skb(rx->skb); | 2884 | dev_kfree_skb(rx->skb); |
2880 | return RX_QUEUED; | 2885 | return RX_QUEUED; |
2881 | 2886 | ||
@@ -2884,7 +2889,7 @@ ieee80211_rx_h_action(struct ieee80211_rx_data *rx) | |||
2884 | skb_queue_tail(&sdata->skb_queue, rx->skb); | 2889 | skb_queue_tail(&sdata->skb_queue, rx->skb); |
2885 | ieee80211_queue_work(&local->hw, &sdata->work); | 2890 | ieee80211_queue_work(&local->hw, &sdata->work); |
2886 | if (rx->sta) | 2891 | if (rx->sta) |
2887 | rx->sta->rx_packets++; | 2892 | rx->sta->rx_stats.packets++; |
2888 | return RX_QUEUED; | 2893 | return RX_QUEUED; |
2889 | } | 2894 | } |
2890 | 2895 | ||
@@ -2911,7 +2916,7 @@ ieee80211_rx_h_userspace_mgmt(struct ieee80211_rx_data *rx) | |||
2911 | if (cfg80211_rx_mgmt(&rx->sdata->wdev, status->freq, sig, | 2916 | if (cfg80211_rx_mgmt(&rx->sdata->wdev, status->freq, sig, |
2912 | rx->skb->data, rx->skb->len, 0)) { | 2917 | rx->skb->data, rx->skb->len, 0)) { |
2913 | if (rx->sta) | 2918 | if (rx->sta) |
2914 | rx->sta->rx_packets++; | 2919 | rx->sta->rx_stats.packets++; |
2915 | dev_kfree_skb(rx->skb); | 2920 | dev_kfree_skb(rx->skb); |
2916 | return RX_QUEUED; | 2921 | return RX_QUEUED; |
2917 | } | 2922 | } |
@@ -3030,7 +3035,7 @@ ieee80211_rx_h_mgmt(struct ieee80211_rx_data *rx) | |||
3030 | skb_queue_tail(&sdata->skb_queue, rx->skb); | 3035 | skb_queue_tail(&sdata->skb_queue, rx->skb); |
3031 | ieee80211_queue_work(&rx->local->hw, &sdata->work); | 3036 | ieee80211_queue_work(&rx->local->hw, &sdata->work); |
3032 | if (rx->sta) | 3037 | if (rx->sta) |
3033 | rx->sta->rx_packets++; | 3038 | rx->sta->rx_stats.packets++; |
3034 | 3039 | ||
3035 | return RX_QUEUED; | 3040 | return RX_QUEUED; |
3036 | } | 3041 | } |
@@ -3112,7 +3117,7 @@ static void ieee80211_rx_handlers_result(struct ieee80211_rx_data *rx, | |||
3112 | case RX_DROP_MONITOR: | 3117 | case RX_DROP_MONITOR: |
3113 | I802_DEBUG_INC(rx->sdata->local->rx_handlers_drop); | 3118 | I802_DEBUG_INC(rx->sdata->local->rx_handlers_drop); |
3114 | if (rx->sta) | 3119 | if (rx->sta) |
3115 | rx->sta->rx_dropped++; | 3120 | rx->sta->rx_stats.dropped++; |
3116 | /* fall through */ | 3121 | /* fall through */ |
3117 | case RX_CONTINUE: { | 3122 | case RX_CONTINUE: { |
3118 | struct ieee80211_rate *rate = NULL; | 3123 | struct ieee80211_rate *rate = NULL; |
@@ -3132,7 +3137,7 @@ static void ieee80211_rx_handlers_result(struct ieee80211_rx_data *rx, | |||
3132 | case RX_DROP_UNUSABLE: | 3137 | case RX_DROP_UNUSABLE: |
3133 | I802_DEBUG_INC(rx->sdata->local->rx_handlers_drop); | 3138 | I802_DEBUG_INC(rx->sdata->local->rx_handlers_drop); |
3134 | if (rx->sta) | 3139 | if (rx->sta) |
3135 | rx->sta->rx_dropped++; | 3140 | rx->sta->rx_stats.dropped++; |
3136 | dev_kfree_skb(rx->skb); | 3141 | dev_kfree_skb(rx->skb); |
3137 | break; | 3142 | break; |
3138 | case RX_QUEUED: | 3143 | case RX_QUEUED: |
diff --git a/net/mac80211/scan.c b/net/mac80211/scan.c index 11d0901ebb7b..b64fd2b2d95a 100644 --- a/net/mac80211/scan.c +++ b/net/mac80211/scan.c | |||
@@ -16,7 +16,6 @@ | |||
16 | #include <linux/if_arp.h> | 16 | #include <linux/if_arp.h> |
17 | #include <linux/etherdevice.h> | 17 | #include <linux/etherdevice.h> |
18 | #include <linux/rtnetlink.h> | 18 | #include <linux/rtnetlink.h> |
19 | #include <linux/pm_qos.h> | ||
20 | #include <net/sch_generic.h> | 19 | #include <net/sch_generic.h> |
21 | #include <linux/slab.h> | 20 | #include <linux/slab.h> |
22 | #include <linux/export.h> | 21 | #include <linux/export.h> |
@@ -67,24 +66,23 @@ ieee80211_bss_info_update(struct ieee80211_local *local, | |||
67 | struct cfg80211_bss *cbss; | 66 | struct cfg80211_bss *cbss; |
68 | struct ieee80211_bss *bss; | 67 | struct ieee80211_bss *bss; |
69 | int clen, srlen; | 68 | int clen, srlen; |
70 | enum nl80211_bss_scan_width scan_width; | 69 | struct cfg80211_inform_bss bss_meta = {}; |
71 | s32 signal = 0; | ||
72 | bool signal_valid; | 70 | bool signal_valid; |
73 | 71 | ||
74 | if (ieee80211_hw_check(&local->hw, SIGNAL_DBM)) | 72 | if (ieee80211_hw_check(&local->hw, SIGNAL_DBM)) |
75 | signal = rx_status->signal * 100; | 73 | bss_meta.signal = rx_status->signal * 100; |
76 | else if (ieee80211_hw_check(&local->hw, SIGNAL_UNSPEC)) | 74 | else if (ieee80211_hw_check(&local->hw, SIGNAL_UNSPEC)) |
77 | signal = (rx_status->signal * 100) / local->hw.max_signal; | 75 | bss_meta.signal = (rx_status->signal * 100) / local->hw.max_signal; |
78 | 76 | ||
79 | scan_width = NL80211_BSS_CHAN_WIDTH_20; | 77 | bss_meta.scan_width = NL80211_BSS_CHAN_WIDTH_20; |
80 | if (rx_status->flag & RX_FLAG_5MHZ) | 78 | if (rx_status->flag & RX_FLAG_5MHZ) |
81 | scan_width = NL80211_BSS_CHAN_WIDTH_5; | 79 | bss_meta.scan_width = NL80211_BSS_CHAN_WIDTH_5; |
82 | if (rx_status->flag & RX_FLAG_10MHZ) | 80 | if (rx_status->flag & RX_FLAG_10MHZ) |
83 | scan_width = NL80211_BSS_CHAN_WIDTH_10; | 81 | bss_meta.scan_width = NL80211_BSS_CHAN_WIDTH_10; |
84 | 82 | ||
85 | cbss = cfg80211_inform_bss_width_frame(local->hw.wiphy, channel, | 83 | bss_meta.chan = channel; |
86 | scan_width, mgmt, len, signal, | 84 | cbss = cfg80211_inform_bss_frame_data(local->hw.wiphy, &bss_meta, |
87 | GFP_ATOMIC); | 85 | mgmt, len, GFP_ATOMIC); |
88 | if (!cbss) | 86 | if (!cbss) |
89 | return NULL; | 87 | return NULL; |
90 | /* In case the signal is invalid update the status */ | 88 | /* In case the signal is invalid update the status */ |
diff --git a/net/mac80211/sta_info.c b/net/mac80211/sta_info.c index c3644458e2ee..f91d1873218c 100644 --- a/net/mac80211/sta_info.c +++ b/net/mac80211/sta_info.c | |||
@@ -331,7 +331,7 @@ struct sta_info *sta_info_alloc(struct ieee80211_sub_if_data *sdata, | |||
331 | memcpy(sta->sta.addr, addr, ETH_ALEN); | 331 | memcpy(sta->sta.addr, addr, ETH_ALEN); |
332 | sta->local = local; | 332 | sta->local = local; |
333 | sta->sdata = sdata; | 333 | sta->sdata = sdata; |
334 | sta->last_rx = jiffies; | 334 | sta->rx_stats.last_rx = jiffies; |
335 | 335 | ||
336 | sta->sta_state = IEEE80211_STA_NONE; | 336 | sta->sta_state = IEEE80211_STA_NONE; |
337 | 337 | ||
@@ -339,9 +339,9 @@ struct sta_info *sta_info_alloc(struct ieee80211_sub_if_data *sdata, | |||
339 | sta->reserved_tid = IEEE80211_TID_UNRESERVED; | 339 | sta->reserved_tid = IEEE80211_TID_UNRESERVED; |
340 | 340 | ||
341 | sta->last_connected = ktime_get_seconds(); | 341 | sta->last_connected = ktime_get_seconds(); |
342 | ewma_signal_init(&sta->avg_signal); | 342 | ewma_signal_init(&sta->rx_stats.avg_signal); |
343 | for (i = 0; i < ARRAY_SIZE(sta->chain_signal_avg); i++) | 343 | for (i = 0; i < ARRAY_SIZE(sta->rx_stats.chain_signal_avg); i++) |
344 | ewma_signal_init(&sta->chain_signal_avg[i]); | 344 | ewma_signal_init(&sta->rx_stats.chain_signal_avg[i]); |
345 | 345 | ||
346 | if (local->ops->wake_tx_queue) { | 346 | if (local->ops->wake_tx_queue) { |
347 | void *txq_data; | 347 | void *txq_data; |
@@ -1066,7 +1066,7 @@ void ieee80211_sta_expire(struct ieee80211_sub_if_data *sdata, | |||
1066 | if (sdata != sta->sdata) | 1066 | if (sdata != sta->sdata) |
1067 | continue; | 1067 | continue; |
1068 | 1068 | ||
1069 | if (time_after(jiffies, sta->last_rx + exp_time)) { | 1069 | if (time_after(jiffies, sta->rx_stats.last_rx + exp_time)) { |
1070 | sta_dbg(sta->sdata, "expiring inactive STA %pM\n", | 1070 | sta_dbg(sta->sdata, "expiring inactive STA %pM\n", |
1071 | sta->sta.addr); | 1071 | sta->sta.addr); |
1072 | 1072 | ||
@@ -1806,6 +1806,45 @@ u8 sta_info_tx_streams(struct sta_info *sta) | |||
1806 | >> IEEE80211_HT_MCS_TX_MAX_STREAMS_SHIFT) + 1; | 1806 | >> IEEE80211_HT_MCS_TX_MAX_STREAMS_SHIFT) + 1; |
1807 | } | 1807 | } |
1808 | 1808 | ||
1809 | static void sta_set_rate_info_rx(struct sta_info *sta, struct rate_info *rinfo) | ||
1810 | { | ||
1811 | rinfo->flags = 0; | ||
1812 | |||
1813 | if (sta->rx_stats.last_rate_flag & RX_FLAG_HT) { | ||
1814 | rinfo->flags |= RATE_INFO_FLAGS_MCS; | ||
1815 | rinfo->mcs = sta->rx_stats.last_rate_idx; | ||
1816 | } else if (sta->rx_stats.last_rate_flag & RX_FLAG_VHT) { | ||
1817 | rinfo->flags |= RATE_INFO_FLAGS_VHT_MCS; | ||
1818 | rinfo->nss = sta->rx_stats.last_rate_vht_nss; | ||
1819 | rinfo->mcs = sta->rx_stats.last_rate_idx; | ||
1820 | } else { | ||
1821 | struct ieee80211_supported_band *sband; | ||
1822 | int shift = ieee80211_vif_get_shift(&sta->sdata->vif); | ||
1823 | u16 brate; | ||
1824 | |||
1825 | sband = sta->local->hw.wiphy->bands[ | ||
1826 | ieee80211_get_sdata_band(sta->sdata)]; | ||
1827 | brate = sband->bitrates[sta->rx_stats.last_rate_idx].bitrate; | ||
1828 | rinfo->legacy = DIV_ROUND_UP(brate, 1 << shift); | ||
1829 | } | ||
1830 | |||
1831 | if (sta->rx_stats.last_rate_flag & RX_FLAG_SHORT_GI) | ||
1832 | rinfo->flags |= RATE_INFO_FLAGS_SHORT_GI; | ||
1833 | |||
1834 | if (sta->rx_stats.last_rate_flag & RX_FLAG_5MHZ) | ||
1835 | rinfo->bw = RATE_INFO_BW_5; | ||
1836 | else if (sta->rx_stats.last_rate_flag & RX_FLAG_10MHZ) | ||
1837 | rinfo->bw = RATE_INFO_BW_10; | ||
1838 | else if (sta->rx_stats.last_rate_flag & RX_FLAG_40MHZ) | ||
1839 | rinfo->bw = RATE_INFO_BW_40; | ||
1840 | else if (sta->rx_stats.last_rate_vht_flag & RX_VHT_FLAG_80MHZ) | ||
1841 | rinfo->bw = RATE_INFO_BW_80; | ||
1842 | else if (sta->rx_stats.last_rate_vht_flag & RX_VHT_FLAG_160MHZ) | ||
1843 | rinfo->bw = RATE_INFO_BW_160; | ||
1844 | else | ||
1845 | rinfo->bw = RATE_INFO_BW_20; | ||
1846 | } | ||
1847 | |||
1809 | void sta_set_sinfo(struct sta_info *sta, struct station_info *sinfo) | 1848 | void sta_set_sinfo(struct sta_info *sta, struct station_info *sinfo) |
1810 | { | 1849 | { |
1811 | struct ieee80211_sub_if_data *sdata = sta->sdata; | 1850 | struct ieee80211_sub_if_data *sdata = sta->sdata; |
@@ -1832,50 +1871,54 @@ void sta_set_sinfo(struct sta_info *sta, struct station_info *sinfo) | |||
1832 | BIT(NL80211_STA_INFO_STA_FLAGS) | | 1871 | BIT(NL80211_STA_INFO_STA_FLAGS) | |
1833 | BIT(NL80211_STA_INFO_BSS_PARAM) | | 1872 | BIT(NL80211_STA_INFO_BSS_PARAM) | |
1834 | BIT(NL80211_STA_INFO_CONNECTED_TIME) | | 1873 | BIT(NL80211_STA_INFO_CONNECTED_TIME) | |
1835 | BIT(NL80211_STA_INFO_RX_DROP_MISC) | | 1874 | BIT(NL80211_STA_INFO_RX_DROP_MISC); |
1836 | BIT(NL80211_STA_INFO_BEACON_LOSS); | 1875 | |
1876 | if (sdata->vif.type == NL80211_IFTYPE_STATION) { | ||
1877 | sinfo->beacon_loss_count = sdata->u.mgd.beacon_loss_count; | ||
1878 | sinfo->filled |= BIT(NL80211_STA_INFO_BEACON_LOSS); | ||
1879 | } | ||
1837 | 1880 | ||
1838 | sinfo->connected_time = ktime_get_seconds() - sta->last_connected; | 1881 | sinfo->connected_time = ktime_get_seconds() - sta->last_connected; |
1839 | sinfo->inactive_time = jiffies_to_msecs(jiffies - sta->last_rx); | 1882 | sinfo->inactive_time = |
1883 | jiffies_to_msecs(jiffies - sta->rx_stats.last_rx); | ||
1840 | 1884 | ||
1841 | if (!(sinfo->filled & (BIT(NL80211_STA_INFO_TX_BYTES64) | | 1885 | if (!(sinfo->filled & (BIT(NL80211_STA_INFO_TX_BYTES64) | |
1842 | BIT(NL80211_STA_INFO_TX_BYTES)))) { | 1886 | BIT(NL80211_STA_INFO_TX_BYTES)))) { |
1843 | sinfo->tx_bytes = 0; | 1887 | sinfo->tx_bytes = 0; |
1844 | for (ac = 0; ac < IEEE80211_NUM_ACS; ac++) | 1888 | for (ac = 0; ac < IEEE80211_NUM_ACS; ac++) |
1845 | sinfo->tx_bytes += sta->tx_bytes[ac]; | 1889 | sinfo->tx_bytes += sta->tx_stats.bytes[ac]; |
1846 | sinfo->filled |= BIT(NL80211_STA_INFO_TX_BYTES64); | 1890 | sinfo->filled |= BIT(NL80211_STA_INFO_TX_BYTES64); |
1847 | } | 1891 | } |
1848 | 1892 | ||
1849 | if (!(sinfo->filled & BIT(NL80211_STA_INFO_TX_PACKETS))) { | 1893 | if (!(sinfo->filled & BIT(NL80211_STA_INFO_TX_PACKETS))) { |
1850 | sinfo->tx_packets = 0; | 1894 | sinfo->tx_packets = 0; |
1851 | for (ac = 0; ac < IEEE80211_NUM_ACS; ac++) | 1895 | for (ac = 0; ac < IEEE80211_NUM_ACS; ac++) |
1852 | sinfo->tx_packets += sta->tx_packets[ac]; | 1896 | sinfo->tx_packets += sta->tx_stats.packets[ac]; |
1853 | sinfo->filled |= BIT(NL80211_STA_INFO_TX_PACKETS); | 1897 | sinfo->filled |= BIT(NL80211_STA_INFO_TX_PACKETS); |
1854 | } | 1898 | } |
1855 | 1899 | ||
1856 | if (!(sinfo->filled & (BIT(NL80211_STA_INFO_RX_BYTES64) | | 1900 | if (!(sinfo->filled & (BIT(NL80211_STA_INFO_RX_BYTES64) | |
1857 | BIT(NL80211_STA_INFO_RX_BYTES)))) { | 1901 | BIT(NL80211_STA_INFO_RX_BYTES)))) { |
1858 | sinfo->rx_bytes = sta->rx_bytes; | 1902 | sinfo->rx_bytes = sta->rx_stats.bytes; |
1859 | sinfo->filled |= BIT(NL80211_STA_INFO_RX_BYTES64); | 1903 | sinfo->filled |= BIT(NL80211_STA_INFO_RX_BYTES64); |
1860 | } | 1904 | } |
1861 | 1905 | ||
1862 | if (!(sinfo->filled & BIT(NL80211_STA_INFO_RX_PACKETS))) { | 1906 | if (!(sinfo->filled & BIT(NL80211_STA_INFO_RX_PACKETS))) { |
1863 | sinfo->rx_packets = sta->rx_packets; | 1907 | sinfo->rx_packets = sta->rx_stats.packets; |
1864 | sinfo->filled |= BIT(NL80211_STA_INFO_RX_PACKETS); | 1908 | sinfo->filled |= BIT(NL80211_STA_INFO_RX_PACKETS); |
1865 | } | 1909 | } |
1866 | 1910 | ||
1867 | if (!(sinfo->filled & BIT(NL80211_STA_INFO_TX_RETRIES))) { | 1911 | if (!(sinfo->filled & BIT(NL80211_STA_INFO_TX_RETRIES))) { |
1868 | sinfo->tx_retries = sta->tx_retry_count; | 1912 | sinfo->tx_retries = sta->status_stats.retry_count; |
1869 | sinfo->filled |= BIT(NL80211_STA_INFO_TX_RETRIES); | 1913 | sinfo->filled |= BIT(NL80211_STA_INFO_TX_RETRIES); |
1870 | } | 1914 | } |
1871 | 1915 | ||
1872 | if (!(sinfo->filled & BIT(NL80211_STA_INFO_TX_FAILED))) { | 1916 | if (!(sinfo->filled & BIT(NL80211_STA_INFO_TX_FAILED))) { |
1873 | sinfo->tx_failed = sta->tx_retry_failed; | 1917 | sinfo->tx_failed = sta->status_stats.retry_failed; |
1874 | sinfo->filled |= BIT(NL80211_STA_INFO_TX_FAILED); | 1918 | sinfo->filled |= BIT(NL80211_STA_INFO_TX_FAILED); |
1875 | } | 1919 | } |
1876 | 1920 | ||
1877 | sinfo->rx_dropped_misc = sta->rx_dropped; | 1921 | sinfo->rx_dropped_misc = sta->rx_stats.dropped; |
1878 | sinfo->beacon_loss_count = sta->beacon_loss_count; | ||
1879 | 1922 | ||
1880 | if (sdata->vif.type == NL80211_IFTYPE_STATION && | 1923 | if (sdata->vif.type == NL80211_IFTYPE_STATION && |
1881 | !(sdata->vif.driver_flags & IEEE80211_VIF_BEACON_FILTER)) { | 1924 | !(sdata->vif.driver_flags & IEEE80211_VIF_BEACON_FILTER)) { |
@@ -1887,33 +1930,35 @@ void sta_set_sinfo(struct sta_info *sta, struct station_info *sinfo) | |||
1887 | if (ieee80211_hw_check(&sta->local->hw, SIGNAL_DBM) || | 1930 | if (ieee80211_hw_check(&sta->local->hw, SIGNAL_DBM) || |
1888 | ieee80211_hw_check(&sta->local->hw, SIGNAL_UNSPEC)) { | 1931 | ieee80211_hw_check(&sta->local->hw, SIGNAL_UNSPEC)) { |
1889 | if (!(sinfo->filled & BIT(NL80211_STA_INFO_SIGNAL))) { | 1932 | if (!(sinfo->filled & BIT(NL80211_STA_INFO_SIGNAL))) { |
1890 | sinfo->signal = (s8)sta->last_signal; | 1933 | sinfo->signal = (s8)sta->rx_stats.last_signal; |
1891 | sinfo->filled |= BIT(NL80211_STA_INFO_SIGNAL); | 1934 | sinfo->filled |= BIT(NL80211_STA_INFO_SIGNAL); |
1892 | } | 1935 | } |
1893 | 1936 | ||
1894 | if (!(sinfo->filled & BIT(NL80211_STA_INFO_SIGNAL_AVG))) { | 1937 | if (!(sinfo->filled & BIT(NL80211_STA_INFO_SIGNAL_AVG))) { |
1895 | sinfo->signal_avg = | 1938 | sinfo->signal_avg = |
1896 | (s8) -ewma_signal_read(&sta->avg_signal); | 1939 | -ewma_signal_read(&sta->rx_stats.avg_signal); |
1897 | sinfo->filled |= BIT(NL80211_STA_INFO_SIGNAL_AVG); | 1940 | sinfo->filled |= BIT(NL80211_STA_INFO_SIGNAL_AVG); |
1898 | } | 1941 | } |
1899 | } | 1942 | } |
1900 | 1943 | ||
1901 | if (sta->chains && | 1944 | if (sta->rx_stats.chains && |
1902 | !(sinfo->filled & (BIT(NL80211_STA_INFO_CHAIN_SIGNAL) | | 1945 | !(sinfo->filled & (BIT(NL80211_STA_INFO_CHAIN_SIGNAL) | |
1903 | BIT(NL80211_STA_INFO_CHAIN_SIGNAL_AVG)))) { | 1946 | BIT(NL80211_STA_INFO_CHAIN_SIGNAL_AVG)))) { |
1904 | sinfo->filled |= BIT(NL80211_STA_INFO_CHAIN_SIGNAL) | | 1947 | sinfo->filled |= BIT(NL80211_STA_INFO_CHAIN_SIGNAL) | |
1905 | BIT(NL80211_STA_INFO_CHAIN_SIGNAL_AVG); | 1948 | BIT(NL80211_STA_INFO_CHAIN_SIGNAL_AVG); |
1906 | 1949 | ||
1907 | sinfo->chains = sta->chains; | 1950 | sinfo->chains = sta->rx_stats.chains; |
1908 | for (i = 0; i < ARRAY_SIZE(sinfo->chain_signal); i++) { | 1951 | for (i = 0; i < ARRAY_SIZE(sinfo->chain_signal); i++) { |
1909 | sinfo->chain_signal[i] = sta->chain_signal_last[i]; | 1952 | sinfo->chain_signal[i] = |
1953 | sta->rx_stats.chain_signal_last[i]; | ||
1910 | sinfo->chain_signal_avg[i] = | 1954 | sinfo->chain_signal_avg[i] = |
1911 | (s8) -ewma_signal_read(&sta->chain_signal_avg[i]); | 1955 | -ewma_signal_read(&sta->rx_stats.chain_signal_avg[i]); |
1912 | } | 1956 | } |
1913 | } | 1957 | } |
1914 | 1958 | ||
1915 | if (!(sinfo->filled & BIT(NL80211_STA_INFO_TX_BITRATE))) { | 1959 | if (!(sinfo->filled & BIT(NL80211_STA_INFO_TX_BITRATE))) { |
1916 | sta_set_rate_info_tx(sta, &sta->last_tx_rate, &sinfo->txrate); | 1960 | sta_set_rate_info_tx(sta, &sta->tx_stats.last_rate, |
1961 | &sinfo->txrate); | ||
1917 | sinfo->filled |= BIT(NL80211_STA_INFO_TX_BITRATE); | 1962 | sinfo->filled |= BIT(NL80211_STA_INFO_TX_BITRATE); |
1918 | } | 1963 | } |
1919 | 1964 | ||
@@ -1928,12 +1973,12 @@ void sta_set_sinfo(struct sta_info *sta, struct station_info *sinfo) | |||
1928 | 1973 | ||
1929 | if (!(tidstats->filled & BIT(NL80211_TID_STATS_RX_MSDU))) { | 1974 | if (!(tidstats->filled & BIT(NL80211_TID_STATS_RX_MSDU))) { |
1930 | tidstats->filled |= BIT(NL80211_TID_STATS_RX_MSDU); | 1975 | tidstats->filled |= BIT(NL80211_TID_STATS_RX_MSDU); |
1931 | tidstats->rx_msdu = sta->rx_msdu[i]; | 1976 | tidstats->rx_msdu = sta->rx_stats.msdu[i]; |
1932 | } | 1977 | } |
1933 | 1978 | ||
1934 | if (!(tidstats->filled & BIT(NL80211_TID_STATS_TX_MSDU))) { | 1979 | if (!(tidstats->filled & BIT(NL80211_TID_STATS_TX_MSDU))) { |
1935 | tidstats->filled |= BIT(NL80211_TID_STATS_TX_MSDU); | 1980 | tidstats->filled |= BIT(NL80211_TID_STATS_TX_MSDU); |
1936 | tidstats->tx_msdu = sta->tx_msdu[i]; | 1981 | tidstats->tx_msdu = sta->tx_stats.msdu[i]; |
1937 | } | 1982 | } |
1938 | 1983 | ||
1939 | if (!(tidstats->filled & | 1984 | if (!(tidstats->filled & |
@@ -1941,7 +1986,8 @@ void sta_set_sinfo(struct sta_info *sta, struct station_info *sinfo) | |||
1941 | ieee80211_hw_check(&local->hw, REPORTS_TX_ACK_STATUS)) { | 1986 | ieee80211_hw_check(&local->hw, REPORTS_TX_ACK_STATUS)) { |
1942 | tidstats->filled |= | 1987 | tidstats->filled |= |
1943 | BIT(NL80211_TID_STATS_TX_MSDU_RETRIES); | 1988 | BIT(NL80211_TID_STATS_TX_MSDU_RETRIES); |
1944 | tidstats->tx_msdu_retries = sta->tx_msdu_retries[i]; | 1989 | tidstats->tx_msdu_retries = |
1990 | sta->status_stats.msdu_retries[i]; | ||
1945 | } | 1991 | } |
1946 | 1992 | ||
1947 | if (!(tidstats->filled & | 1993 | if (!(tidstats->filled & |
@@ -1949,7 +1995,8 @@ void sta_set_sinfo(struct sta_info *sta, struct station_info *sinfo) | |||
1949 | ieee80211_hw_check(&local->hw, REPORTS_TX_ACK_STATUS)) { | 1995 | ieee80211_hw_check(&local->hw, REPORTS_TX_ACK_STATUS)) { |
1950 | tidstats->filled |= | 1996 | tidstats->filled |= |
1951 | BIT(NL80211_TID_STATS_TX_MSDU_FAILED); | 1997 | BIT(NL80211_TID_STATS_TX_MSDU_FAILED); |
1952 | tidstats->tx_msdu_failed = sta->tx_msdu_failed[i]; | 1998 | tidstats->tx_msdu_failed = |
1999 | sta->status_stats.msdu_failed[i]; | ||
1953 | } | 2000 | } |
1954 | } | 2001 | } |
1955 | 2002 | ||
diff --git a/net/mac80211/sta_info.h b/net/mac80211/sta_info.h index d5ded8749ac4..2cafb21b422f 100644 --- a/net/mac80211/sta_info.h +++ b/net/mac80211/sta_info.h | |||
@@ -344,12 +344,6 @@ DECLARE_EWMA(signal, 1024, 8) | |||
344 | * @rate_ctrl_lock: spinlock used to protect rate control data | 344 | * @rate_ctrl_lock: spinlock used to protect rate control data |
345 | * (data inside the algorithm, so serializes calls there) | 345 | * (data inside the algorithm, so serializes calls there) |
346 | * @rate_ctrl_priv: rate control private per-STA pointer | 346 | * @rate_ctrl_priv: rate control private per-STA pointer |
347 | * @last_tx_rate: rate used for last transmit, to report to userspace as | ||
348 | * "the" transmit rate | ||
349 | * @last_rx_rate_idx: rx status rate index of the last data packet | ||
350 | * @last_rx_rate_flag: rx status flag of the last data packet | ||
351 | * @last_rx_rate_vht_flag: rx status vht flag of the last data packet | ||
352 | * @last_rx_rate_vht_nss: rx status nss of last data packet | ||
353 | * @lock: used for locking all fields that require locking, see comments | 347 | * @lock: used for locking all fields that require locking, see comments |
354 | * in the header file. | 348 | * in the header file. |
355 | * @drv_deliver_wk: used for delivering frames after driver PS unblocking | 349 | * @drv_deliver_wk: used for delivering frames after driver PS unblocking |
@@ -364,23 +358,9 @@ DECLARE_EWMA(signal, 1024, 8) | |||
364 | * the station when it leaves powersave or polls for frames | 358 | * the station when it leaves powersave or polls for frames |
365 | * @driver_buffered_tids: bitmap of TIDs the driver has data buffered on | 359 | * @driver_buffered_tids: bitmap of TIDs the driver has data buffered on |
366 | * @txq_buffered_tids: bitmap of TIDs that mac80211 has txq data buffered on | 360 | * @txq_buffered_tids: bitmap of TIDs that mac80211 has txq data buffered on |
367 | * @rx_packets: Number of MSDUs received from this STA | ||
368 | * @rx_bytes: Number of bytes received from this STA | ||
369 | * @last_rx: time (in jiffies) when last frame was received from this STA | ||
370 | * @last_connected: time (in seconds) when a station got connected | 361 | * @last_connected: time (in seconds) when a station got connected |
371 | * @num_duplicates: number of duplicate frames received from this STA | ||
372 | * @rx_fragments: number of received MPDUs | ||
373 | * @rx_dropped: number of dropped MPDUs from this STA | ||
374 | * @last_signal: signal of last received frame from this STA | ||
375 | * @avg_signal: moving average of signal of received frames from this STA | ||
376 | * @last_ack_signal: signal of last received Ack frame from this STA | ||
377 | * @last_seq_ctrl: last received seq/frag number from this STA (per TID | 362 | * @last_seq_ctrl: last received seq/frag number from this STA (per TID |
378 | * plus one for non-QoS frames) | 363 | * plus one for non-QoS frames) |
379 | * @tx_filtered_count: number of frames the hardware filtered for this STA | ||
380 | * @tx_retry_failed: number of frames that failed retry | ||
381 | * @tx_retry_count: total number of retries for frames to this STA | ||
382 | * @tx_packets: number of RX/TX MSDUs | ||
383 | * @tx_bytes: number of bytes transmitted to this STA | ||
384 | * @tid_seq: per-TID sequence numbers for sending to this STA | 364 | * @tid_seq: per-TID sequence numbers for sending to this STA |
385 | * @ampdu_mlme: A-MPDU state machine state | 365 | * @ampdu_mlme: A-MPDU state machine state |
386 | * @timer_to_tid: identity mapping to ID timers | 366 | * @timer_to_tid: identity mapping to ID timers |
@@ -388,32 +368,22 @@ DECLARE_EWMA(signal, 1024, 8) | |||
388 | * @debugfs: debug filesystem info | 368 | * @debugfs: debug filesystem info |
389 | * @dead: set to true when sta is unlinked | 369 | * @dead: set to true when sta is unlinked |
390 | * @uploaded: set to true when sta is uploaded to the driver | 370 | * @uploaded: set to true when sta is uploaded to the driver |
391 | * @lost_packets: number of consecutive lost packets | ||
392 | * @sta: station information we share with the driver | 371 | * @sta: station information we share with the driver |
393 | * @sta_state: duplicates information about station state (for debug) | 372 | * @sta_state: duplicates information about station state (for debug) |
394 | * @beacon_loss_count: number of times beacon loss has triggered | 373 | * @beacon_loss_count: number of times beacon loss has triggered |
395 | * @rcu_head: RCU head used for freeing this station struct | 374 | * @rcu_head: RCU head used for freeing this station struct |
396 | * @cur_max_bandwidth: maximum bandwidth to use for TX to the station, | 375 | * @cur_max_bandwidth: maximum bandwidth to use for TX to the station, |
397 | * taken from HT/VHT capabilities or VHT operating mode notification | 376 | * taken from HT/VHT capabilities or VHT operating mode notification |
398 | * @chains: chains ever used for RX from this station | ||
399 | * @chain_signal_last: last signal (per chain) | ||
400 | * @chain_signal_avg: signal average (per chain) | ||
401 | * @known_smps_mode: the smps_mode the client thinks we are in. Relevant for | 377 | * @known_smps_mode: the smps_mode the client thinks we are in. Relevant for |
402 | * AP only. | 378 | * AP only. |
403 | * @cipher_scheme: optional cipher scheme for this station | 379 | * @cipher_scheme: optional cipher scheme for this station |
404 | * @last_tdls_pkt_time: holds the time in jiffies of last TDLS pkt ACKed | ||
405 | * @reserved_tid: reserved TID (if any, otherwise IEEE80211_TID_UNRESERVED) | 380 | * @reserved_tid: reserved TID (if any, otherwise IEEE80211_TID_UNRESERVED) |
406 | * @tx_msdu: MSDUs transmitted to this station, using IEEE80211_NUM_TID | ||
407 | * entry for non-QoS frames | ||
408 | * @tx_msdu_retries: MSDU retries for transmissions to to this station, | ||
409 | * using IEEE80211_NUM_TID entry for non-QoS frames | ||
410 | * @tx_msdu_failed: MSDU failures for transmissions to to this station, | ||
411 | * using IEEE80211_NUM_TID entry for non-QoS frames | ||
412 | * @rx_msdu: MSDUs received from this station, using IEEE80211_NUM_TID | ||
413 | * entry for non-QoS frames | ||
414 | * @fast_tx: TX fastpath information | 381 | * @fast_tx: TX fastpath information |
415 | * @tdls_chandef: a TDLS peer can have a wider chandef that is compatible to | 382 | * @tdls_chandef: a TDLS peer can have a wider chandef that is compatible to |
416 | * the BSS one. | 383 | * the BSS one. |
384 | * @tx_stats: TX statistics | ||
385 | * @rx_stats: RX statistics | ||
386 | * @status_stats: TX status statistics | ||
417 | */ | 387 | */ |
418 | struct sta_info { | 388 | struct sta_info { |
419 | /* General information, mostly static */ | 389 | /* General information, mostly static */ |
@@ -457,42 +427,49 @@ struct sta_info { | |||
457 | unsigned long driver_buffered_tids; | 427 | unsigned long driver_buffered_tids; |
458 | unsigned long txq_buffered_tids; | 428 | unsigned long txq_buffered_tids; |
459 | 429 | ||
460 | /* Updated from RX path only, no locking requirements */ | ||
461 | unsigned long rx_packets; | ||
462 | u64 rx_bytes; | ||
463 | unsigned long last_rx; | ||
464 | long last_connected; | 430 | long last_connected; |
465 | unsigned long num_duplicates; | ||
466 | unsigned long rx_fragments; | ||
467 | unsigned long rx_dropped; | ||
468 | int last_signal; | ||
469 | struct ewma_signal avg_signal; | ||
470 | int last_ack_signal; | ||
471 | 431 | ||
472 | u8 chains; | 432 | /* Updated from RX path only, no locking requirements */ |
473 | s8 chain_signal_last[IEEE80211_MAX_CHAINS]; | 433 | struct { |
474 | struct ewma_signal chain_signal_avg[IEEE80211_MAX_CHAINS]; | 434 | unsigned long packets; |
435 | u64 bytes; | ||
436 | unsigned long last_rx; | ||
437 | unsigned long num_duplicates; | ||
438 | unsigned long fragments; | ||
439 | unsigned long dropped; | ||
440 | int last_signal; | ||
441 | struct ewma_signal avg_signal; | ||
442 | u8 chains; | ||
443 | s8 chain_signal_last[IEEE80211_MAX_CHAINS]; | ||
444 | struct ewma_signal chain_signal_avg[IEEE80211_MAX_CHAINS]; | ||
445 | int last_rate_idx; | ||
446 | u32 last_rate_flag; | ||
447 | u32 last_rate_vht_flag; | ||
448 | u8 last_rate_vht_nss; | ||
449 | u64 msdu[IEEE80211_NUM_TIDS + 1]; | ||
450 | } rx_stats; | ||
475 | 451 | ||
476 | /* Plus 1 for non-QoS frames */ | 452 | /* Plus 1 for non-QoS frames */ |
477 | __le16 last_seq_ctrl[IEEE80211_NUM_TIDS + 1]; | 453 | __le16 last_seq_ctrl[IEEE80211_NUM_TIDS + 1]; |
478 | 454 | ||
479 | /* Updated from TX status path only, no locking requirements */ | 455 | /* Updated from TX status path only, no locking requirements */ |
480 | unsigned long tx_filtered_count; | 456 | struct { |
481 | unsigned long tx_retry_failed, tx_retry_count; | 457 | unsigned long filtered; |
458 | unsigned long retry_failed, retry_count; | ||
459 | unsigned int lost_packets; | ||
460 | unsigned long last_tdls_pkt_time; | ||
461 | u64 msdu_retries[IEEE80211_NUM_TIDS + 1]; | ||
462 | u64 msdu_failed[IEEE80211_NUM_TIDS + 1]; | ||
463 | } status_stats; | ||
482 | 464 | ||
483 | /* Updated from TX path only, no locking requirements */ | 465 | /* Updated from TX path only, no locking requirements */ |
484 | u64 tx_packets[IEEE80211_NUM_ACS]; | 466 | struct { |
485 | u64 tx_bytes[IEEE80211_NUM_ACS]; | 467 | u64 packets[IEEE80211_NUM_ACS]; |
486 | struct ieee80211_tx_rate last_tx_rate; | 468 | u64 bytes[IEEE80211_NUM_ACS]; |
487 | int last_rx_rate_idx; | 469 | struct ieee80211_tx_rate last_rate; |
488 | u32 last_rx_rate_flag; | 470 | u64 msdu[IEEE80211_NUM_TIDS + 1]; |
489 | u32 last_rx_rate_vht_flag; | 471 | } tx_stats; |
490 | u8 last_rx_rate_vht_nss; | ||
491 | u16 tid_seq[IEEE80211_QOS_CTL_TID_MASK + 1]; | 472 | u16 tid_seq[IEEE80211_QOS_CTL_TID_MASK + 1]; |
492 | u64 tx_msdu[IEEE80211_NUM_TIDS + 1]; | ||
493 | u64 tx_msdu_retries[IEEE80211_NUM_TIDS + 1]; | ||
494 | u64 tx_msdu_failed[IEEE80211_NUM_TIDS + 1]; | ||
495 | u64 rx_msdu[IEEE80211_NUM_TIDS + 1]; | ||
496 | 473 | ||
497 | /* | 474 | /* |
498 | * Aggregation information, locked with lock. | 475 | * Aggregation information, locked with lock. |
@@ -509,15 +486,9 @@ struct sta_info { | |||
509 | 486 | ||
510 | enum ieee80211_sta_rx_bandwidth cur_max_bandwidth; | 487 | enum ieee80211_sta_rx_bandwidth cur_max_bandwidth; |
511 | 488 | ||
512 | unsigned int lost_packets; | ||
513 | unsigned int beacon_loss_count; | ||
514 | |||
515 | enum ieee80211_smps_mode known_smps_mode; | 489 | enum ieee80211_smps_mode known_smps_mode; |
516 | const struct ieee80211_cipher_scheme *cipher_scheme; | 490 | const struct ieee80211_cipher_scheme *cipher_scheme; |
517 | 491 | ||
518 | /* TDLS timeout data */ | ||
519 | unsigned long last_tdls_pkt_time; | ||
520 | |||
521 | u8 reserved_tid; | 492 | u8 reserved_tid; |
522 | 493 | ||
523 | struct cfg80211_chan_def tdls_chandef; | 494 | struct cfg80211_chan_def tdls_chandef; |
@@ -688,8 +659,6 @@ static inline int sta_info_flush(struct ieee80211_sub_if_data *sdata) | |||
688 | void sta_set_rate_info_tx(struct sta_info *sta, | 659 | void sta_set_rate_info_tx(struct sta_info *sta, |
689 | const struct ieee80211_tx_rate *rate, | 660 | const struct ieee80211_tx_rate *rate, |
690 | struct rate_info *rinfo); | 661 | struct rate_info *rinfo); |
691 | void sta_set_rate_info_rx(struct sta_info *sta, | ||
692 | struct rate_info *rinfo); | ||
693 | void sta_set_sinfo(struct sta_info *sta, struct station_info *sinfo); | 662 | void sta_set_sinfo(struct sta_info *sta, struct station_info *sinfo); |
694 | 663 | ||
695 | void ieee80211_sta_expire(struct ieee80211_sub_if_data *sdata, | 664 | void ieee80211_sta_expire(struct ieee80211_sub_if_data *sdata, |
diff --git a/net/mac80211/status.c b/net/mac80211/status.c index 9169ccc36534..5bad05e9af90 100644 --- a/net/mac80211/status.c +++ b/net/mac80211/status.c | |||
@@ -67,7 +67,7 @@ static void ieee80211_handle_filtered_frame(struct ieee80211_local *local, | |||
67 | IEEE80211_TX_INTFL_RETRANSMISSION; | 67 | IEEE80211_TX_INTFL_RETRANSMISSION; |
68 | info->flags &= ~IEEE80211_TX_TEMPORARY_FLAGS; | 68 | info->flags &= ~IEEE80211_TX_TEMPORARY_FLAGS; |
69 | 69 | ||
70 | sta->tx_filtered_count++; | 70 | sta->status_stats.filtered++; |
71 | 71 | ||
72 | /* | 72 | /* |
73 | * Clear more-data bit on filtered frames, it might be set | 73 | * Clear more-data bit on filtered frames, it might be set |
@@ -183,7 +183,7 @@ static void ieee80211_frame_acked(struct sta_info *sta, struct sk_buff *skb) | |||
183 | struct ieee80211_sub_if_data *sdata = sta->sdata; | 183 | struct ieee80211_sub_if_data *sdata = sta->sdata; |
184 | 184 | ||
185 | if (ieee80211_hw_check(&local->hw, REPORTS_TX_ACK_STATUS)) | 185 | if (ieee80211_hw_check(&local->hw, REPORTS_TX_ACK_STATUS)) |
186 | sta->last_rx = jiffies; | 186 | sta->rx_stats.last_rx = jiffies; |
187 | 187 | ||
188 | if (ieee80211_is_data_qos(mgmt->frame_control)) { | 188 | if (ieee80211_is_data_qos(mgmt->frame_control)) { |
189 | struct ieee80211_hdr *hdr = (void *) skb->data; | 189 | struct ieee80211_hdr *hdr = (void *) skb->data; |
@@ -557,8 +557,9 @@ static void ieee80211_lost_packet(struct sta_info *sta, | |||
557 | !(info->flags & IEEE80211_TX_STAT_AMPDU)) | 557 | !(info->flags & IEEE80211_TX_STAT_AMPDU)) |
558 | return; | 558 | return; |
559 | 559 | ||
560 | sta->lost_packets++; | 560 | sta->status_stats.lost_packets++; |
561 | if (!sta->sta.tdls && sta->lost_packets < STA_LOST_PKT_THRESHOLD) | 561 | if (!sta->sta.tdls && |
562 | sta->status_stats.lost_packets < STA_LOST_PKT_THRESHOLD) | ||
562 | return; | 563 | return; |
563 | 564 | ||
564 | /* | 565 | /* |
@@ -568,14 +569,15 @@ static void ieee80211_lost_packet(struct sta_info *sta, | |||
568 | * mechanism. | 569 | * mechanism. |
569 | */ | 570 | */ |
570 | if (sta->sta.tdls && | 571 | if (sta->sta.tdls && |
571 | (sta->lost_packets < STA_LOST_TDLS_PKT_THRESHOLD || | 572 | (sta->status_stats.lost_packets < STA_LOST_TDLS_PKT_THRESHOLD || |
572 | time_before(jiffies, | 573 | time_before(jiffies, |
573 | sta->last_tdls_pkt_time + STA_LOST_TDLS_PKT_TIME))) | 574 | sta->status_stats.last_tdls_pkt_time + |
575 | STA_LOST_TDLS_PKT_TIME))) | ||
574 | return; | 576 | return; |
575 | 577 | ||
576 | cfg80211_cqm_pktloss_notify(sta->sdata->dev, sta->sta.addr, | 578 | cfg80211_cqm_pktloss_notify(sta->sdata->dev, sta->sta.addr, |
577 | sta->lost_packets, GFP_ATOMIC); | 579 | sta->status_stats.lost_packets, GFP_ATOMIC); |
578 | sta->lost_packets = 0; | 580 | sta->status_stats.lost_packets = 0; |
579 | } | 581 | } |
580 | 582 | ||
581 | static int ieee80211_tx_get_rates(struct ieee80211_hw *hw, | 583 | static int ieee80211_tx_get_rates(struct ieee80211_hw *hw, |
@@ -636,18 +638,18 @@ void ieee80211_tx_status_noskb(struct ieee80211_hw *hw, | |||
636 | sta = container_of(pubsta, struct sta_info, sta); | 638 | sta = container_of(pubsta, struct sta_info, sta); |
637 | 639 | ||
638 | if (!acked) | 640 | if (!acked) |
639 | sta->tx_retry_failed++; | 641 | sta->status_stats.retry_failed++; |
640 | sta->tx_retry_count += retry_count; | 642 | sta->status_stats.retry_count += retry_count; |
641 | 643 | ||
642 | if (acked) { | 644 | if (acked) { |
643 | sta->last_rx = jiffies; | 645 | sta->rx_stats.last_rx = jiffies; |
644 | 646 | ||
645 | if (sta->lost_packets) | 647 | if (sta->status_stats.lost_packets) |
646 | sta->lost_packets = 0; | 648 | sta->status_stats.lost_packets = 0; |
647 | 649 | ||
648 | /* Track when last TDLS packet was ACKed */ | 650 | /* Track when last TDLS packet was ACKed */ |
649 | if (test_sta_flag(sta, WLAN_STA_TDLS_PEER_AUTH)) | 651 | if (test_sta_flag(sta, WLAN_STA_TDLS_PEER_AUTH)) |
650 | sta->last_tdls_pkt_time = jiffies; | 652 | sta->status_stats.last_tdls_pkt_time = jiffies; |
651 | } else { | 653 | } else { |
652 | ieee80211_lost_packet(sta, info); | 654 | ieee80211_lost_packet(sta, info); |
653 | } | 655 | } |
@@ -784,7 +786,8 @@ void ieee80211_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb) | |||
784 | if (ieee80211_hw_check(&local->hw, HAS_RATE_CONTROL) && | 786 | if (ieee80211_hw_check(&local->hw, HAS_RATE_CONTROL) && |
785 | (ieee80211_is_data(hdr->frame_control)) && | 787 | (ieee80211_is_data(hdr->frame_control)) && |
786 | (rates_idx != -1)) | 788 | (rates_idx != -1)) |
787 | sta->last_tx_rate = info->status.rates[rates_idx]; | 789 | sta->tx_stats.last_rate = |
790 | info->status.rates[rates_idx]; | ||
788 | 791 | ||
789 | if ((info->flags & IEEE80211_TX_STAT_AMPDU_NO_BACK) && | 792 | if ((info->flags & IEEE80211_TX_STAT_AMPDU_NO_BACK) && |
790 | (ieee80211_is_data_qos(fc))) { | 793 | (ieee80211_is_data_qos(fc))) { |
@@ -830,13 +833,15 @@ void ieee80211_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb) | |||
830 | return; | 833 | return; |
831 | } else { | 834 | } else { |
832 | if (!acked) | 835 | if (!acked) |
833 | sta->tx_retry_failed++; | 836 | sta->status_stats.retry_failed++; |
834 | sta->tx_retry_count += retry_count; | 837 | sta->status_stats.retry_count += retry_count; |
835 | 838 | ||
836 | if (ieee80211_is_data_present(fc)) { | 839 | if (ieee80211_is_data_present(fc)) { |
837 | if (!acked) | 840 | if (!acked) |
838 | sta->tx_msdu_failed[tid]++; | 841 | sta->status_stats.msdu_failed[tid]++; |
839 | sta->tx_msdu_retries[tid] += retry_count; | 842 | |
843 | sta->status_stats.msdu_retries[tid] += | ||
844 | retry_count; | ||
840 | } | 845 | } |
841 | } | 846 | } |
842 | 847 | ||
@@ -854,19 +859,17 @@ void ieee80211_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb) | |||
854 | 859 | ||
855 | if (ieee80211_hw_check(&local->hw, REPORTS_TX_ACK_STATUS)) { | 860 | if (ieee80211_hw_check(&local->hw, REPORTS_TX_ACK_STATUS)) { |
856 | if (info->flags & IEEE80211_TX_STAT_ACK) { | 861 | if (info->flags & IEEE80211_TX_STAT_ACK) { |
857 | if (sta->lost_packets) | 862 | if (sta->status_stats.lost_packets) |
858 | sta->lost_packets = 0; | 863 | sta->status_stats.lost_packets = 0; |
859 | 864 | ||
860 | /* Track when last TDLS packet was ACKed */ | 865 | /* Track when last TDLS packet was ACKed */ |
861 | if (test_sta_flag(sta, WLAN_STA_TDLS_PEER_AUTH)) | 866 | if (test_sta_flag(sta, WLAN_STA_TDLS_PEER_AUTH)) |
862 | sta->last_tdls_pkt_time = jiffies; | 867 | sta->status_stats.last_tdls_pkt_time = |
868 | jiffies; | ||
863 | } else { | 869 | } else { |
864 | ieee80211_lost_packet(sta, info); | 870 | ieee80211_lost_packet(sta, info); |
865 | } | 871 | } |
866 | } | 872 | } |
867 | |||
868 | if (acked) | ||
869 | sta->last_ack_signal = info->status.ack_signal; | ||
870 | } | 873 | } |
871 | 874 | ||
872 | rcu_read_unlock(); | 875 | rcu_read_unlock(); |
diff --git a/net/mac80211/trace.h b/net/mac80211/trace.h index 314e3bd7fbdb..5cf8f4ea077f 100644 --- a/net/mac80211/trace.h +++ b/net/mac80211/trace.h | |||
@@ -325,7 +325,6 @@ TRACE_EVENT(drv_config, | |||
325 | __field(u32, flags) | 325 | __field(u32, flags) |
326 | __field(int, power_level) | 326 | __field(int, power_level) |
327 | __field(int, dynamic_ps_timeout) | 327 | __field(int, dynamic_ps_timeout) |
328 | __field(int, max_sleep_period) | ||
329 | __field(u16, listen_interval) | 328 | __field(u16, listen_interval) |
330 | __field(u8, long_frame_max_tx_count) | 329 | __field(u8, long_frame_max_tx_count) |
331 | __field(u8, short_frame_max_tx_count) | 330 | __field(u8, short_frame_max_tx_count) |
@@ -339,7 +338,6 @@ TRACE_EVENT(drv_config, | |||
339 | __entry->flags = local->hw.conf.flags; | 338 | __entry->flags = local->hw.conf.flags; |
340 | __entry->power_level = local->hw.conf.power_level; | 339 | __entry->power_level = local->hw.conf.power_level; |
341 | __entry->dynamic_ps_timeout = local->hw.conf.dynamic_ps_timeout; | 340 | __entry->dynamic_ps_timeout = local->hw.conf.dynamic_ps_timeout; |
342 | __entry->max_sleep_period = local->hw.conf.max_sleep_period; | ||
343 | __entry->listen_interval = local->hw.conf.listen_interval; | 341 | __entry->listen_interval = local->hw.conf.listen_interval; |
344 | __entry->long_frame_max_tx_count = | 342 | __entry->long_frame_max_tx_count = |
345 | local->hw.conf.long_frame_max_tx_count; | 343 | local->hw.conf.long_frame_max_tx_count; |
diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c index 3478a83187e5..bdc224d5053a 100644 --- a/net/mac80211/tx.c +++ b/net/mac80211/tx.c | |||
@@ -757,9 +757,9 @@ ieee80211_tx_h_rate_ctrl(struct ieee80211_tx_data *tx) | |||
757 | if (txrc.reported_rate.idx < 0) { | 757 | if (txrc.reported_rate.idx < 0) { |
758 | txrc.reported_rate = tx->rate; | 758 | txrc.reported_rate = tx->rate; |
759 | if (tx->sta && ieee80211_is_data(hdr->frame_control)) | 759 | if (tx->sta && ieee80211_is_data(hdr->frame_control)) |
760 | tx->sta->last_tx_rate = txrc.reported_rate; | 760 | tx->sta->tx_stats.last_rate = txrc.reported_rate; |
761 | } else if (tx->sta) | 761 | } else if (tx->sta) |
762 | tx->sta->last_tx_rate = txrc.reported_rate; | 762 | tx->sta->tx_stats.last_rate = txrc.reported_rate; |
763 | 763 | ||
764 | if (ratetbl) | 764 | if (ratetbl) |
765 | return TX_CONTINUE; | 765 | return TX_CONTINUE; |
@@ -824,7 +824,7 @@ ieee80211_tx_h_sequence(struct ieee80211_tx_data *tx) | |||
824 | hdr->seq_ctrl = cpu_to_le16(tx->sdata->sequence_number); | 824 | hdr->seq_ctrl = cpu_to_le16(tx->sdata->sequence_number); |
825 | tx->sdata->sequence_number += 0x10; | 825 | tx->sdata->sequence_number += 0x10; |
826 | if (tx->sta) | 826 | if (tx->sta) |
827 | tx->sta->tx_msdu[IEEE80211_NUM_TIDS]++; | 827 | tx->sta->tx_stats.msdu[IEEE80211_NUM_TIDS]++; |
828 | return TX_CONTINUE; | 828 | return TX_CONTINUE; |
829 | } | 829 | } |
830 | 830 | ||
@@ -840,7 +840,7 @@ ieee80211_tx_h_sequence(struct ieee80211_tx_data *tx) | |||
840 | 840 | ||
841 | qc = ieee80211_get_qos_ctl(hdr); | 841 | qc = ieee80211_get_qos_ctl(hdr); |
842 | tid = *qc & IEEE80211_QOS_CTL_TID_MASK; | 842 | tid = *qc & IEEE80211_QOS_CTL_TID_MASK; |
843 | tx->sta->tx_msdu[tid]++; | 843 | tx->sta->tx_stats.msdu[tid]++; |
844 | 844 | ||
845 | if (!tx->sta->sta.txq[0]) | 845 | if (!tx->sta->sta.txq[0]) |
846 | hdr->seq_ctrl = ieee80211_tx_next_seq(tx->sta, tid); | 846 | hdr->seq_ctrl = ieee80211_tx_next_seq(tx->sta, tid); |
@@ -994,10 +994,10 @@ ieee80211_tx_h_stats(struct ieee80211_tx_data *tx) | |||
994 | 994 | ||
995 | skb_queue_walk(&tx->skbs, skb) { | 995 | skb_queue_walk(&tx->skbs, skb) { |
996 | ac = skb_get_queue_mapping(skb); | 996 | ac = skb_get_queue_mapping(skb); |
997 | tx->sta->tx_bytes[ac] += skb->len; | 997 | tx->sta->tx_stats.bytes[ac] += skb->len; |
998 | } | 998 | } |
999 | if (ac >= 0) | 999 | if (ac >= 0) |
1000 | tx->sta->tx_packets[ac]++; | 1000 | tx->sta->tx_stats.packets[ac]++; |
1001 | 1001 | ||
1002 | return TX_CONTINUE; | 1002 | return TX_CONTINUE; |
1003 | } | 1003 | } |
@@ -2779,10 +2779,10 @@ static bool ieee80211_xmit_fast(struct ieee80211_sub_if_data *sdata, | |||
2779 | } | 2779 | } |
2780 | 2780 | ||
2781 | if (skb_shinfo(skb)->gso_size) | 2781 | if (skb_shinfo(skb)->gso_size) |
2782 | sta->tx_msdu[tid] += | 2782 | sta->tx_stats.msdu[tid] += |
2783 | DIV_ROUND_UP(skb->len, skb_shinfo(skb)->gso_size); | 2783 | DIV_ROUND_UP(skb->len, skb_shinfo(skb)->gso_size); |
2784 | else | 2784 | else |
2785 | sta->tx_msdu[tid]++; | 2785 | sta->tx_stats.msdu[tid]++; |
2786 | 2786 | ||
2787 | info->hw_queue = sdata->vif.hw_queue[skb_get_queue_mapping(skb)]; | 2787 | info->hw_queue = sdata->vif.hw_queue[skb_get_queue_mapping(skb)]; |
2788 | 2788 | ||
@@ -2813,8 +2813,8 @@ static bool ieee80211_xmit_fast(struct ieee80211_sub_if_data *sdata, | |||
2813 | /* statistics normally done by ieee80211_tx_h_stats (but that | 2813 | /* statistics normally done by ieee80211_tx_h_stats (but that |
2814 | * has to consider fragmentation, so is more complex) | 2814 | * has to consider fragmentation, so is more complex) |
2815 | */ | 2815 | */ |
2816 | sta->tx_bytes[skb_get_queue_mapping(skb)] += skb->len; | 2816 | sta->tx_stats.bytes[skb_get_queue_mapping(skb)] += skb->len; |
2817 | sta->tx_packets[skb_get_queue_mapping(skb)]++; | 2817 | sta->tx_stats.packets[skb_get_queue_mapping(skb)]++; |
2818 | 2818 | ||
2819 | if (fast_tx->pn_offs) { | 2819 | if (fast_tx->pn_offs) { |
2820 | u64 pn; | 2820 | u64 pn; |
diff --git a/net/mac80211/util.c b/net/mac80211/util.c index 60c4dbf92625..8274c86296f9 100644 --- a/net/mac80211/util.c +++ b/net/mac80211/util.c | |||
@@ -1951,7 +1951,7 @@ int ieee80211_reconfig(struct ieee80211_local *local) | |||
1951 | } | 1951 | } |
1952 | } | 1952 | } |
1953 | 1953 | ||
1954 | ieee80211_recalc_ps(local, -1); | 1954 | ieee80211_recalc_ps(local); |
1955 | 1955 | ||
1956 | /* | 1956 | /* |
1957 | * The sta might be in psm against the ap (e.g. because | 1957 | * The sta might be in psm against the ap (e.g. because |
@@ -2042,9 +2042,13 @@ int ieee80211_reconfig(struct ieee80211_local *local) | |||
2042 | if (sched_scan_sdata && sched_scan_req) | 2042 | if (sched_scan_sdata && sched_scan_req) |
2043 | /* | 2043 | /* |
2044 | * Sched scan stopped, but we don't want to report it. Instead, | 2044 | * Sched scan stopped, but we don't want to report it. Instead, |
2045 | * we're trying to reschedule. | 2045 | * we're trying to reschedule. However, if more than one scan |
2046 | * plan was set, we cannot reschedule since we don't know which | ||
2047 | * scan plan was currently running (and some scan plans may have | ||
2048 | * already finished). | ||
2046 | */ | 2049 | */ |
2047 | if (__ieee80211_request_sched_scan_start(sched_scan_sdata, | 2050 | if (sched_scan_req->n_scan_plans > 1 || |
2051 | __ieee80211_request_sched_scan_start(sched_scan_sdata, | ||
2048 | sched_scan_req)) | 2052 | sched_scan_req)) |
2049 | sched_scan_stopped = true; | 2053 | sched_scan_stopped = true; |
2050 | mutex_unlock(&local->mtx); | 2054 | mutex_unlock(&local->mtx); |
@@ -3301,9 +3305,11 @@ void ieee80211_init_tx_queue(struct ieee80211_sub_if_data *sdata, | |||
3301 | if (sta) { | 3305 | if (sta) { |
3302 | txqi->txq.sta = &sta->sta; | 3306 | txqi->txq.sta = &sta->sta; |
3303 | sta->sta.txq[tid] = &txqi->txq; | 3307 | sta->sta.txq[tid] = &txqi->txq; |
3308 | txqi->txq.tid = tid; | ||
3304 | txqi->txq.ac = ieee802_1d_to_ac[tid & 7]; | 3309 | txqi->txq.ac = ieee802_1d_to_ac[tid & 7]; |
3305 | } else { | 3310 | } else { |
3306 | sdata->vif.txq = &txqi->txq; | 3311 | sdata->vif.txq = &txqi->txq; |
3312 | txqi->txq.tid = 0; | ||
3307 | txqi->txq.ac = IEEE80211_AC_BE; | 3313 | txqi->txq.ac = IEEE80211_AC_BE; |
3308 | } | 3314 | } |
3309 | } | 3315 | } |
diff --git a/net/mac80211/wpa.c b/net/mac80211/wpa.c index feb547dc8643..d824c38971ed 100644 --- a/net/mac80211/wpa.c +++ b/net/mac80211/wpa.c | |||
@@ -174,9 +174,12 @@ mic_fail_no_key: | |||
174 | * a driver that supports HW encryption. Send up the key idx only if | 174 | * a driver that supports HW encryption. Send up the key idx only if |
175 | * the key is set. | 175 | * the key is set. |
176 | */ | 176 | */ |
177 | mac80211_ev_michael_mic_failure(rx->sdata, | 177 | cfg80211_michael_mic_failure(rx->sdata->dev, hdr->addr2, |
178 | rx->key ? rx->key->conf.keyidx : -1, | 178 | is_multicast_ether_addr(hdr->addr1) ? |
179 | (void *) skb->data, NULL, GFP_ATOMIC); | 179 | NL80211_KEYTYPE_GROUP : |
180 | NL80211_KEYTYPE_PAIRWISE, | ||
181 | rx->key ? rx->key->conf.keyidx : -1, | ||
182 | NULL, GFP_ATOMIC); | ||
180 | return RX_DROP_UNUSABLE; | 183 | return RX_DROP_UNUSABLE; |
181 | } | 184 | } |
182 | 185 | ||
diff --git a/net/wireless/Kconfig b/net/wireless/Kconfig index 4f5543dd2524..da72ed32f143 100644 --- a/net/wireless/Kconfig +++ b/net/wireless/Kconfig | |||
@@ -174,6 +174,16 @@ config CFG80211_INTERNAL_REGDB | |||
174 | 174 | ||
175 | Most distributions have a CRDA package. So if unsure, say N. | 175 | Most distributions have a CRDA package. So if unsure, say N. |
176 | 176 | ||
177 | config CFG80211_CRDA_SUPPORT | ||
178 | bool "support CRDA" if CFG80211_INTERNAL_REGDB | ||
179 | default y | ||
180 | depends on CFG80211 | ||
181 | help | ||
182 | You should enable this option unless you know for sure you have no | ||
183 | need for it, for example when using internal regdb (above.) | ||
184 | |||
185 | If unsure, say Y. | ||
186 | |||
177 | config CFG80211_WEXT | 187 | config CFG80211_WEXT |
178 | bool "cfg80211 wireless extensions compatibility" if !CFG80211_WEXT_EXPORT | 188 | bool "cfg80211 wireless extensions compatibility" if !CFG80211_WEXT_EXPORT |
179 | depends on CFG80211 | 189 | depends on CFG80211 |
diff --git a/net/wireless/core.c b/net/wireless/core.c index f223026ddb03..b0915515640e 100644 --- a/net/wireless/core.c +++ b/net/wireless/core.c | |||
@@ -461,6 +461,9 @@ use_default_name: | |||
461 | 461 | ||
462 | rdev->wiphy.max_num_csa_counters = 1; | 462 | rdev->wiphy.max_num_csa_counters = 1; |
463 | 463 | ||
464 | rdev->wiphy.max_sched_scan_plans = 1; | ||
465 | rdev->wiphy.max_sched_scan_plan_interval = U32_MAX; | ||
466 | |||
464 | return &rdev->wiphy; | 467 | return &rdev->wiphy; |
465 | } | 468 | } |
466 | EXPORT_SYMBOL(wiphy_new_nm); | 469 | EXPORT_SYMBOL(wiphy_new_nm); |
@@ -636,7 +639,7 @@ int wiphy_register(struct wiphy *wiphy) | |||
636 | if (WARN_ON(!sband->n_channels)) | 639 | if (WARN_ON(!sband->n_channels)) |
637 | return -EINVAL; | 640 | return -EINVAL; |
638 | /* | 641 | /* |
639 | * on 60gHz band, there are no legacy rates, so | 642 | * on 60GHz band, there are no legacy rates, so |
640 | * n_bitrates is 0 | 643 | * n_bitrates is 0 |
641 | */ | 644 | */ |
642 | if (WARN_ON(band != IEEE80211_BAND_60GHZ && | 645 | if (WARN_ON(band != IEEE80211_BAND_60GHZ && |
diff --git a/net/wireless/core.h b/net/wireless/core.h index b9d5bc8c148d..a618b4b86fa4 100644 --- a/net/wireless/core.h +++ b/net/wireless/core.h | |||
@@ -137,6 +137,7 @@ struct cfg80211_internal_bss { | |||
137 | struct list_head list; | 137 | struct list_head list; |
138 | struct list_head hidden_list; | 138 | struct list_head hidden_list; |
139 | struct rb_node rbn; | 139 | struct rb_node rbn; |
140 | u64 ts_boottime; | ||
140 | unsigned long ts; | 141 | unsigned long ts; |
141 | unsigned long refcount; | 142 | unsigned long refcount; |
142 | atomic_t hold; | 143 | atomic_t hold; |
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c index f05ba8b7af61..d693c9d031fc 100644 --- a/net/wireless/nl80211.c +++ b/net/wireless/nl80211.c | |||
@@ -479,6 +479,12 @@ nl80211_match_policy[NL80211_SCHED_SCAN_MATCH_ATTR_MAX + 1] = { | |||
479 | [NL80211_SCHED_SCAN_MATCH_ATTR_RSSI] = { .type = NLA_U32 }, | 479 | [NL80211_SCHED_SCAN_MATCH_ATTR_RSSI] = { .type = NLA_U32 }, |
480 | }; | 480 | }; |
481 | 481 | ||
482 | static const struct nla_policy | ||
483 | nl80211_plan_policy[NL80211_SCHED_SCAN_PLAN_MAX + 1] = { | ||
484 | [NL80211_SCHED_SCAN_PLAN_INTERVAL] = { .type = NLA_U32 }, | ||
485 | [NL80211_SCHED_SCAN_PLAN_ITERATIONS] = { .type = NLA_U32 }, | ||
486 | }; | ||
487 | |||
482 | static int nl80211_prepare_wdev_dump(struct sk_buff *skb, | 488 | static int nl80211_prepare_wdev_dump(struct sk_buff *skb, |
483 | struct netlink_callback *cb, | 489 | struct netlink_callback *cb, |
484 | struct cfg80211_registered_device **rdev, | 490 | struct cfg80211_registered_device **rdev, |
@@ -1304,7 +1310,13 @@ static int nl80211_send_wiphy(struct cfg80211_registered_device *rdev, | |||
1304 | nla_put_u16(msg, NL80211_ATTR_MAX_SCHED_SCAN_IE_LEN, | 1310 | nla_put_u16(msg, NL80211_ATTR_MAX_SCHED_SCAN_IE_LEN, |
1305 | rdev->wiphy.max_sched_scan_ie_len) || | 1311 | rdev->wiphy.max_sched_scan_ie_len) || |
1306 | nla_put_u8(msg, NL80211_ATTR_MAX_MATCH_SETS, | 1312 | nla_put_u8(msg, NL80211_ATTR_MAX_MATCH_SETS, |
1307 | rdev->wiphy.max_match_sets)) | 1313 | rdev->wiphy.max_match_sets) || |
1314 | nla_put_u32(msg, NL80211_ATTR_MAX_NUM_SCHED_SCAN_PLANS, | ||
1315 | rdev->wiphy.max_sched_scan_plans) || | ||
1316 | nla_put_u32(msg, NL80211_ATTR_MAX_SCAN_PLAN_INTERVAL, | ||
1317 | rdev->wiphy.max_sched_scan_plan_interval) || | ||
1318 | nla_put_u32(msg, NL80211_ATTR_MAX_SCAN_PLAN_ITERATIONS, | ||
1319 | rdev->wiphy.max_sched_scan_plan_iterations)) | ||
1308 | goto nla_put_failure; | 1320 | goto nla_put_failure; |
1309 | 1321 | ||
1310 | if ((rdev->wiphy.flags & WIPHY_FLAG_IBSS_RSN) && | 1322 | if ((rdev->wiphy.flags & WIPHY_FLAG_IBSS_RSN) && |
@@ -4932,56 +4944,6 @@ static int nl80211_set_bss(struct sk_buff *skb, struct genl_info *info) | |||
4932 | return err; | 4944 | return err; |
4933 | } | 4945 | } |
4934 | 4946 | ||
4935 | static const struct nla_policy reg_rule_policy[NL80211_REG_RULE_ATTR_MAX + 1] = { | ||
4936 | [NL80211_ATTR_REG_RULE_FLAGS] = { .type = NLA_U32 }, | ||
4937 | [NL80211_ATTR_FREQ_RANGE_START] = { .type = NLA_U32 }, | ||
4938 | [NL80211_ATTR_FREQ_RANGE_END] = { .type = NLA_U32 }, | ||
4939 | [NL80211_ATTR_FREQ_RANGE_MAX_BW] = { .type = NLA_U32 }, | ||
4940 | [NL80211_ATTR_POWER_RULE_MAX_ANT_GAIN] = { .type = NLA_U32 }, | ||
4941 | [NL80211_ATTR_POWER_RULE_MAX_EIRP] = { .type = NLA_U32 }, | ||
4942 | [NL80211_ATTR_DFS_CAC_TIME] = { .type = NLA_U32 }, | ||
4943 | }; | ||
4944 | |||
4945 | static int parse_reg_rule(struct nlattr *tb[], | ||
4946 | struct ieee80211_reg_rule *reg_rule) | ||
4947 | { | ||
4948 | struct ieee80211_freq_range *freq_range = ®_rule->freq_range; | ||
4949 | struct ieee80211_power_rule *power_rule = ®_rule->power_rule; | ||
4950 | |||
4951 | if (!tb[NL80211_ATTR_REG_RULE_FLAGS]) | ||
4952 | return -EINVAL; | ||
4953 | if (!tb[NL80211_ATTR_FREQ_RANGE_START]) | ||
4954 | return -EINVAL; | ||
4955 | if (!tb[NL80211_ATTR_FREQ_RANGE_END]) | ||
4956 | return -EINVAL; | ||
4957 | if (!tb[NL80211_ATTR_FREQ_RANGE_MAX_BW]) | ||
4958 | return -EINVAL; | ||
4959 | if (!tb[NL80211_ATTR_POWER_RULE_MAX_EIRP]) | ||
4960 | return -EINVAL; | ||
4961 | |||
4962 | reg_rule->flags = nla_get_u32(tb[NL80211_ATTR_REG_RULE_FLAGS]); | ||
4963 | |||
4964 | freq_range->start_freq_khz = | ||
4965 | nla_get_u32(tb[NL80211_ATTR_FREQ_RANGE_START]); | ||
4966 | freq_range->end_freq_khz = | ||
4967 | nla_get_u32(tb[NL80211_ATTR_FREQ_RANGE_END]); | ||
4968 | freq_range->max_bandwidth_khz = | ||
4969 | nla_get_u32(tb[NL80211_ATTR_FREQ_RANGE_MAX_BW]); | ||
4970 | |||
4971 | power_rule->max_eirp = | ||
4972 | nla_get_u32(tb[NL80211_ATTR_POWER_RULE_MAX_EIRP]); | ||
4973 | |||
4974 | if (tb[NL80211_ATTR_POWER_RULE_MAX_ANT_GAIN]) | ||
4975 | power_rule->max_antenna_gain = | ||
4976 | nla_get_u32(tb[NL80211_ATTR_POWER_RULE_MAX_ANT_GAIN]); | ||
4977 | |||
4978 | if (tb[NL80211_ATTR_DFS_CAC_TIME]) | ||
4979 | reg_rule->dfs_cac_ms = | ||
4980 | nla_get_u32(tb[NL80211_ATTR_DFS_CAC_TIME]); | ||
4981 | |||
4982 | return 0; | ||
4983 | } | ||
4984 | |||
4985 | static int nl80211_req_set_reg(struct sk_buff *skb, struct genl_info *info) | 4947 | static int nl80211_req_set_reg(struct sk_buff *skb, struct genl_info *info) |
4986 | { | 4948 | { |
4987 | char *data = NULL; | 4949 | char *data = NULL; |
@@ -5613,6 +5575,57 @@ out_err: | |||
5613 | return err; | 5575 | return err; |
5614 | } | 5576 | } |
5615 | 5577 | ||
5578 | #ifdef CONFIG_CFG80211_CRDA_SUPPORT | ||
5579 | static const struct nla_policy reg_rule_policy[NL80211_REG_RULE_ATTR_MAX + 1] = { | ||
5580 | [NL80211_ATTR_REG_RULE_FLAGS] = { .type = NLA_U32 }, | ||
5581 | [NL80211_ATTR_FREQ_RANGE_START] = { .type = NLA_U32 }, | ||
5582 | [NL80211_ATTR_FREQ_RANGE_END] = { .type = NLA_U32 }, | ||
5583 | [NL80211_ATTR_FREQ_RANGE_MAX_BW] = { .type = NLA_U32 }, | ||
5584 | [NL80211_ATTR_POWER_RULE_MAX_ANT_GAIN] = { .type = NLA_U32 }, | ||
5585 | [NL80211_ATTR_POWER_RULE_MAX_EIRP] = { .type = NLA_U32 }, | ||
5586 | [NL80211_ATTR_DFS_CAC_TIME] = { .type = NLA_U32 }, | ||
5587 | }; | ||
5588 | |||
5589 | static int parse_reg_rule(struct nlattr *tb[], | ||
5590 | struct ieee80211_reg_rule *reg_rule) | ||
5591 | { | ||
5592 | struct ieee80211_freq_range *freq_range = ®_rule->freq_range; | ||
5593 | struct ieee80211_power_rule *power_rule = ®_rule->power_rule; | ||
5594 | |||
5595 | if (!tb[NL80211_ATTR_REG_RULE_FLAGS]) | ||
5596 | return -EINVAL; | ||
5597 | if (!tb[NL80211_ATTR_FREQ_RANGE_START]) | ||
5598 | return -EINVAL; | ||
5599 | if (!tb[NL80211_ATTR_FREQ_RANGE_END]) | ||
5600 | return -EINVAL; | ||
5601 | if (!tb[NL80211_ATTR_FREQ_RANGE_MAX_BW]) | ||
5602 | return -EINVAL; | ||
5603 | if (!tb[NL80211_ATTR_POWER_RULE_MAX_EIRP]) | ||
5604 | return -EINVAL; | ||
5605 | |||
5606 | reg_rule->flags = nla_get_u32(tb[NL80211_ATTR_REG_RULE_FLAGS]); | ||
5607 | |||
5608 | freq_range->start_freq_khz = | ||
5609 | nla_get_u32(tb[NL80211_ATTR_FREQ_RANGE_START]); | ||
5610 | freq_range->end_freq_khz = | ||
5611 | nla_get_u32(tb[NL80211_ATTR_FREQ_RANGE_END]); | ||
5612 | freq_range->max_bandwidth_khz = | ||
5613 | nla_get_u32(tb[NL80211_ATTR_FREQ_RANGE_MAX_BW]); | ||
5614 | |||
5615 | power_rule->max_eirp = | ||
5616 | nla_get_u32(tb[NL80211_ATTR_POWER_RULE_MAX_EIRP]); | ||
5617 | |||
5618 | if (tb[NL80211_ATTR_POWER_RULE_MAX_ANT_GAIN]) | ||
5619 | power_rule->max_antenna_gain = | ||
5620 | nla_get_u32(tb[NL80211_ATTR_POWER_RULE_MAX_ANT_GAIN]); | ||
5621 | |||
5622 | if (tb[NL80211_ATTR_DFS_CAC_TIME]) | ||
5623 | reg_rule->dfs_cac_ms = | ||
5624 | nla_get_u32(tb[NL80211_ATTR_DFS_CAC_TIME]); | ||
5625 | |||
5626 | return 0; | ||
5627 | } | ||
5628 | |||
5616 | static int nl80211_set_reg(struct sk_buff *skb, struct genl_info *info) | 5629 | static int nl80211_set_reg(struct sk_buff *skb, struct genl_info *info) |
5617 | { | 5630 | { |
5618 | struct nlattr *tb[NL80211_REG_RULE_ATTR_MAX + 1]; | 5631 | struct nlattr *tb[NL80211_REG_RULE_ATTR_MAX + 1]; |
@@ -5689,6 +5702,7 @@ static int nl80211_set_reg(struct sk_buff *skb, struct genl_info *info) | |||
5689 | kfree(rd); | 5702 | kfree(rd); |
5690 | return r; | 5703 | return r; |
5691 | } | 5704 | } |
5705 | #endif /* CONFIG_CFG80211_CRDA_SUPPORT */ | ||
5692 | 5706 | ||
5693 | static int validate_scan_freqs(struct nlattr *freqs) | 5707 | static int validate_scan_freqs(struct nlattr *freqs) |
5694 | { | 5708 | { |
@@ -5974,14 +5988,100 @@ static int nl80211_trigger_scan(struct sk_buff *skb, struct genl_info *info) | |||
5974 | return err; | 5988 | return err; |
5975 | } | 5989 | } |
5976 | 5990 | ||
5991 | static int | ||
5992 | nl80211_parse_sched_scan_plans(struct wiphy *wiphy, int n_plans, | ||
5993 | struct cfg80211_sched_scan_request *request, | ||
5994 | struct nlattr **attrs) | ||
5995 | { | ||
5996 | int tmp, err, i = 0; | ||
5997 | struct nlattr *attr; | ||
5998 | |||
5999 | if (!attrs[NL80211_ATTR_SCHED_SCAN_PLANS]) { | ||
6000 | u32 interval; | ||
6001 | |||
6002 | /* | ||
6003 | * If scan plans are not specified, | ||
6004 | * %NL80211_ATTR_SCHED_SCAN_INTERVAL must be specified. In this | ||
6005 | * case one scan plan will be set with the specified scan | ||
6006 | * interval and infinite number of iterations. | ||
6007 | */ | ||
6008 | if (!attrs[NL80211_ATTR_SCHED_SCAN_INTERVAL]) | ||
6009 | return -EINVAL; | ||
6010 | |||
6011 | interval = nla_get_u32(attrs[NL80211_ATTR_SCHED_SCAN_INTERVAL]); | ||
6012 | if (!interval) | ||
6013 | return -EINVAL; | ||
6014 | |||
6015 | request->scan_plans[0].interval = | ||
6016 | DIV_ROUND_UP(interval, MSEC_PER_SEC); | ||
6017 | if (!request->scan_plans[0].interval) | ||
6018 | return -EINVAL; | ||
6019 | |||
6020 | if (request->scan_plans[0].interval > | ||
6021 | wiphy->max_sched_scan_plan_interval) | ||
6022 | request->scan_plans[0].interval = | ||
6023 | wiphy->max_sched_scan_plan_interval; | ||
6024 | |||
6025 | return 0; | ||
6026 | } | ||
6027 | |||
6028 | nla_for_each_nested(attr, attrs[NL80211_ATTR_SCHED_SCAN_PLANS], tmp) { | ||
6029 | struct nlattr *plan[NL80211_SCHED_SCAN_PLAN_MAX + 1]; | ||
6030 | |||
6031 | if (WARN_ON(i >= n_plans)) | ||
6032 | return -EINVAL; | ||
6033 | |||
6034 | err = nla_parse(plan, NL80211_SCHED_SCAN_PLAN_MAX, | ||
6035 | nla_data(attr), nla_len(attr), | ||
6036 | nl80211_plan_policy); | ||
6037 | if (err) | ||
6038 | return err; | ||
6039 | |||
6040 | if (!plan[NL80211_SCHED_SCAN_PLAN_INTERVAL]) | ||
6041 | return -EINVAL; | ||
6042 | |||
6043 | request->scan_plans[i].interval = | ||
6044 | nla_get_u32(plan[NL80211_SCHED_SCAN_PLAN_INTERVAL]); | ||
6045 | if (!request->scan_plans[i].interval || | ||
6046 | request->scan_plans[i].interval > | ||
6047 | wiphy->max_sched_scan_plan_interval) | ||
6048 | return -EINVAL; | ||
6049 | |||
6050 | if (plan[NL80211_SCHED_SCAN_PLAN_ITERATIONS]) { | ||
6051 | request->scan_plans[i].iterations = | ||
6052 | nla_get_u32(plan[NL80211_SCHED_SCAN_PLAN_ITERATIONS]); | ||
6053 | if (!request->scan_plans[i].iterations || | ||
6054 | (request->scan_plans[i].iterations > | ||
6055 | wiphy->max_sched_scan_plan_iterations)) | ||
6056 | return -EINVAL; | ||
6057 | } else if (i < n_plans - 1) { | ||
6058 | /* | ||
6059 | * All scan plans but the last one must specify | ||
6060 | * a finite number of iterations | ||
6061 | */ | ||
6062 | return -EINVAL; | ||
6063 | } | ||
6064 | |||
6065 | i++; | ||
6066 | } | ||
6067 | |||
6068 | /* | ||
6069 | * The last scan plan must not specify the number of | ||
6070 | * iterations, it is supposed to run infinitely | ||
6071 | */ | ||
6072 | if (request->scan_plans[n_plans - 1].iterations) | ||
6073 | return -EINVAL; | ||
6074 | |||
6075 | return 0; | ||
6076 | } | ||
6077 | |||
5977 | static struct cfg80211_sched_scan_request * | 6078 | static struct cfg80211_sched_scan_request * |
5978 | nl80211_parse_sched_scan(struct wiphy *wiphy, struct wireless_dev *wdev, | 6079 | nl80211_parse_sched_scan(struct wiphy *wiphy, struct wireless_dev *wdev, |
5979 | struct nlattr **attrs) | 6080 | struct nlattr **attrs) |
5980 | { | 6081 | { |
5981 | struct cfg80211_sched_scan_request *request; | 6082 | struct cfg80211_sched_scan_request *request; |
5982 | struct nlattr *attr; | 6083 | struct nlattr *attr; |
5983 | int err, tmp, n_ssids = 0, n_match_sets = 0, n_channels, i; | 6084 | int err, tmp, n_ssids = 0, n_match_sets = 0, n_channels, i, n_plans = 0; |
5984 | u32 interval; | ||
5985 | enum ieee80211_band band; | 6085 | enum ieee80211_band band; |
5986 | size_t ie_len; | 6086 | size_t ie_len; |
5987 | struct nlattr *tb[NL80211_SCHED_SCAN_MATCH_ATTR_MAX + 1]; | 6087 | struct nlattr *tb[NL80211_SCHED_SCAN_MATCH_ATTR_MAX + 1]; |
@@ -5990,13 +6090,6 @@ nl80211_parse_sched_scan(struct wiphy *wiphy, struct wireless_dev *wdev, | |||
5990 | if (!is_valid_ie_attr(attrs[NL80211_ATTR_IE])) | 6090 | if (!is_valid_ie_attr(attrs[NL80211_ATTR_IE])) |
5991 | return ERR_PTR(-EINVAL); | 6091 | return ERR_PTR(-EINVAL); |
5992 | 6092 | ||
5993 | if (!attrs[NL80211_ATTR_SCHED_SCAN_INTERVAL]) | ||
5994 | return ERR_PTR(-EINVAL); | ||
5995 | |||
5996 | interval = nla_get_u32(attrs[NL80211_ATTR_SCHED_SCAN_INTERVAL]); | ||
5997 | if (interval == 0) | ||
5998 | return ERR_PTR(-EINVAL); | ||
5999 | |||
6000 | if (attrs[NL80211_ATTR_SCAN_FREQUENCIES]) { | 6093 | if (attrs[NL80211_ATTR_SCAN_FREQUENCIES]) { |
6001 | n_channels = validate_scan_freqs( | 6094 | n_channels = validate_scan_freqs( |
6002 | attrs[NL80211_ATTR_SCAN_FREQUENCIES]); | 6095 | attrs[NL80211_ATTR_SCAN_FREQUENCIES]); |
@@ -6060,9 +6153,37 @@ nl80211_parse_sched_scan(struct wiphy *wiphy, struct wireless_dev *wdev, | |||
6060 | if (ie_len > wiphy->max_sched_scan_ie_len) | 6153 | if (ie_len > wiphy->max_sched_scan_ie_len) |
6061 | return ERR_PTR(-EINVAL); | 6154 | return ERR_PTR(-EINVAL); |
6062 | 6155 | ||
6156 | if (attrs[NL80211_ATTR_SCHED_SCAN_PLANS]) { | ||
6157 | /* | ||
6158 | * NL80211_ATTR_SCHED_SCAN_INTERVAL must not be specified since | ||
6159 | * each scan plan already specifies its own interval | ||
6160 | */ | ||
6161 | if (attrs[NL80211_ATTR_SCHED_SCAN_INTERVAL]) | ||
6162 | return ERR_PTR(-EINVAL); | ||
6163 | |||
6164 | nla_for_each_nested(attr, | ||
6165 | attrs[NL80211_ATTR_SCHED_SCAN_PLANS], tmp) | ||
6166 | n_plans++; | ||
6167 | } else { | ||
6168 | /* | ||
6169 | * The scan interval attribute is kept for backward | ||
6170 | * compatibility. If no scan plans are specified and sched scan | ||
6171 | * interval is specified, one scan plan will be set with this | ||
6172 | * scan interval and infinite number of iterations. | ||
6173 | */ | ||
6174 | if (!attrs[NL80211_ATTR_SCHED_SCAN_INTERVAL]) | ||
6175 | return ERR_PTR(-EINVAL); | ||
6176 | |||
6177 | n_plans = 1; | ||
6178 | } | ||
6179 | |||
6180 | if (!n_plans || n_plans > wiphy->max_sched_scan_plans) | ||
6181 | return ERR_PTR(-EINVAL); | ||
6182 | |||
6063 | request = kzalloc(sizeof(*request) | 6183 | request = kzalloc(sizeof(*request) |
6064 | + sizeof(*request->ssids) * n_ssids | 6184 | + sizeof(*request->ssids) * n_ssids |
6065 | + sizeof(*request->match_sets) * n_match_sets | 6185 | + sizeof(*request->match_sets) * n_match_sets |
6186 | + sizeof(*request->scan_plans) * n_plans | ||
6066 | + sizeof(*request->channels) * n_channels | 6187 | + sizeof(*request->channels) * n_channels |
6067 | + ie_len, GFP_KERNEL); | 6188 | + ie_len, GFP_KERNEL); |
6068 | if (!request) | 6189 | if (!request) |
@@ -6090,6 +6211,18 @@ nl80211_parse_sched_scan(struct wiphy *wiphy, struct wireless_dev *wdev, | |||
6090 | } | 6211 | } |
6091 | request->n_match_sets = n_match_sets; | 6212 | request->n_match_sets = n_match_sets; |
6092 | 6213 | ||
6214 | if (n_match_sets) | ||
6215 | request->scan_plans = (void *)(request->match_sets + | ||
6216 | n_match_sets); | ||
6217 | else if (request->ie) | ||
6218 | request->scan_plans = (void *)(request->ie + ie_len); | ||
6219 | else if (n_ssids) | ||
6220 | request->scan_plans = (void *)(request->ssids + n_ssids); | ||
6221 | else | ||
6222 | request->scan_plans = (void *)(request->channels + n_channels); | ||
6223 | |||
6224 | request->n_scan_plans = n_plans; | ||
6225 | |||
6093 | i = 0; | 6226 | i = 0; |
6094 | if (attrs[NL80211_ATTR_SCAN_FREQUENCIES]) { | 6227 | if (attrs[NL80211_ATTR_SCAN_FREQUENCIES]) { |
6095 | /* user specified, bail out if channel not found */ | 6228 | /* user specified, bail out if channel not found */ |
@@ -6252,7 +6385,10 @@ nl80211_parse_sched_scan(struct wiphy *wiphy, struct wireless_dev *wdev, | |||
6252 | request->delay = | 6385 | request->delay = |
6253 | nla_get_u32(attrs[NL80211_ATTR_SCHED_SCAN_DELAY]); | 6386 | nla_get_u32(attrs[NL80211_ATTR_SCHED_SCAN_DELAY]); |
6254 | 6387 | ||
6255 | request->interval = interval; | 6388 | err = nl80211_parse_sched_scan_plans(wiphy, n_plans, request, attrs); |
6389 | if (err) | ||
6390 | goto out_free; | ||
6391 | |||
6256 | request->scan_start = jiffies; | 6392 | request->scan_start = jiffies; |
6257 | 6393 | ||
6258 | return request; | 6394 | return request; |
@@ -6605,6 +6741,11 @@ static int nl80211_send_bss(struct sk_buff *msg, struct netlink_callback *cb, | |||
6605 | jiffies_to_msecs(jiffies - intbss->ts))) | 6741 | jiffies_to_msecs(jiffies - intbss->ts))) |
6606 | goto nla_put_failure; | 6742 | goto nla_put_failure; |
6607 | 6743 | ||
6744 | if (intbss->ts_boottime && | ||
6745 | nla_put_u64(msg, NL80211_BSS_LAST_SEEN_BOOTTIME, | ||
6746 | intbss->ts_boottime)) | ||
6747 | goto nla_put_failure; | ||
6748 | |||
6608 | switch (rdev->wiphy.signal_type) { | 6749 | switch (rdev->wiphy.signal_type) { |
6609 | case CFG80211_SIGNAL_TYPE_MBM: | 6750 | case CFG80211_SIGNAL_TYPE_MBM: |
6610 | if (nla_put_u32(msg, NL80211_BSS_SIGNAL_MBM, res->signal)) | 6751 | if (nla_put_u32(msg, NL80211_BSS_SIGNAL_MBM, res->signal)) |
@@ -8845,7 +8986,7 @@ static int nl80211_send_wowlan_tcp(struct sk_buff *msg, | |||
8845 | static int nl80211_send_wowlan_nd(struct sk_buff *msg, | 8986 | static int nl80211_send_wowlan_nd(struct sk_buff *msg, |
8846 | struct cfg80211_sched_scan_request *req) | 8987 | struct cfg80211_sched_scan_request *req) |
8847 | { | 8988 | { |
8848 | struct nlattr *nd, *freqs, *matches, *match; | 8989 | struct nlattr *nd, *freqs, *matches, *match, *scan_plans, *scan_plan; |
8849 | int i; | 8990 | int i; |
8850 | 8991 | ||
8851 | if (!req) | 8992 | if (!req) |
@@ -8855,7 +8996,9 @@ static int nl80211_send_wowlan_nd(struct sk_buff *msg, | |||
8855 | if (!nd) | 8996 | if (!nd) |
8856 | return -ENOBUFS; | 8997 | return -ENOBUFS; |
8857 | 8998 | ||
8858 | if (nla_put_u32(msg, NL80211_ATTR_SCHED_SCAN_INTERVAL, req->interval)) | 8999 | if (req->n_scan_plans == 1 && |
9000 | nla_put_u32(msg, NL80211_ATTR_SCHED_SCAN_INTERVAL, | ||
9001 | req->scan_plans[0].interval * 1000)) | ||
8859 | return -ENOBUFS; | 9002 | return -ENOBUFS; |
8860 | 9003 | ||
8861 | if (nla_put_u32(msg, NL80211_ATTR_SCHED_SCAN_DELAY, req->delay)) | 9004 | if (nla_put_u32(msg, NL80211_ATTR_SCHED_SCAN_DELAY, req->delay)) |
@@ -8882,6 +9025,23 @@ static int nl80211_send_wowlan_nd(struct sk_buff *msg, | |||
8882 | nla_nest_end(msg, matches); | 9025 | nla_nest_end(msg, matches); |
8883 | } | 9026 | } |
8884 | 9027 | ||
9028 | scan_plans = nla_nest_start(msg, NL80211_ATTR_SCHED_SCAN_PLANS); | ||
9029 | if (!scan_plans) | ||
9030 | return -ENOBUFS; | ||
9031 | |||
9032 | for (i = 0; i < req->n_scan_plans; i++) { | ||
9033 | scan_plan = nla_nest_start(msg, i + 1); | ||
9034 | if (!scan_plan || | ||
9035 | nla_put_u32(msg, NL80211_SCHED_SCAN_PLAN_INTERVAL, | ||
9036 | req->scan_plans[i].interval) || | ||
9037 | (req->scan_plans[i].iterations && | ||
9038 | nla_put_u32(msg, NL80211_SCHED_SCAN_PLAN_ITERATIONS, | ||
9039 | req->scan_plans[i].iterations))) | ||
9040 | return -ENOBUFS; | ||
9041 | nla_nest_end(msg, scan_plan); | ||
9042 | } | ||
9043 | nla_nest_end(msg, scan_plans); | ||
9044 | |||
8885 | nla_nest_end(msg, nd); | 9045 | nla_nest_end(msg, nd); |
8886 | 9046 | ||
8887 | return 0; | 9047 | return 0; |
@@ -10737,6 +10897,7 @@ static const struct genl_ops nl80211_ops[] = { | |||
10737 | .internal_flags = NL80211_FLAG_NEED_RTNL, | 10897 | .internal_flags = NL80211_FLAG_NEED_RTNL, |
10738 | /* can be retrieved by unprivileged users */ | 10898 | /* can be retrieved by unprivileged users */ |
10739 | }, | 10899 | }, |
10900 | #ifdef CONFIG_CFG80211_CRDA_SUPPORT | ||
10740 | { | 10901 | { |
10741 | .cmd = NL80211_CMD_SET_REG, | 10902 | .cmd = NL80211_CMD_SET_REG, |
10742 | .doit = nl80211_set_reg, | 10903 | .doit = nl80211_set_reg, |
@@ -10744,6 +10905,7 @@ static const struct genl_ops nl80211_ops[] = { | |||
10744 | .flags = GENL_ADMIN_PERM, | 10905 | .flags = GENL_ADMIN_PERM, |
10745 | .internal_flags = NL80211_FLAG_NEED_RTNL, | 10906 | .internal_flags = NL80211_FLAG_NEED_RTNL, |
10746 | }, | 10907 | }, |
10908 | #endif | ||
10747 | { | 10909 | { |
10748 | .cmd = NL80211_CMD_REQ_SET_REG, | 10910 | .cmd = NL80211_CMD_REQ_SET_REG, |
10749 | .doit = nl80211_req_set_reg, | 10911 | .doit = nl80211_req_set_reg, |
diff --git a/net/wireless/reg.c b/net/wireless/reg.c index 7258246b7458..2e8d6f39ed56 100644 --- a/net/wireless/reg.c +++ b/net/wireless/reg.c | |||
@@ -135,10 +135,7 @@ static spinlock_t reg_indoor_lock; | |||
135 | /* Used to track the userspace process controlling the indoor setting */ | 135 | /* Used to track the userspace process controlling the indoor setting */ |
136 | static u32 reg_is_indoor_portid; | 136 | static u32 reg_is_indoor_portid; |
137 | 137 | ||
138 | /* Max number of consecutive attempts to communicate with CRDA */ | 138 | static void restore_regulatory_settings(bool reset_user); |
139 | #define REG_MAX_CRDA_TIMEOUTS 10 | ||
140 | |||
141 | static u32 reg_crda_timeouts; | ||
142 | 139 | ||
143 | static const struct ieee80211_regdomain *get_cfg80211_regdom(void) | 140 | static const struct ieee80211_regdomain *get_cfg80211_regdom(void) |
144 | { | 141 | { |
@@ -226,9 +223,6 @@ static DECLARE_DELAYED_WORK(reg_check_chans, reg_check_chans_work); | |||
226 | static void reg_todo(struct work_struct *work); | 223 | static void reg_todo(struct work_struct *work); |
227 | static DECLARE_WORK(reg_work, reg_todo); | 224 | static DECLARE_WORK(reg_work, reg_todo); |
228 | 225 | ||
229 | static void reg_timeout_work(struct work_struct *work); | ||
230 | static DECLARE_DELAYED_WORK(reg_timeout, reg_timeout_work); | ||
231 | |||
232 | /* We keep a static world regulatory domain in case of the absence of CRDA */ | 226 | /* We keep a static world regulatory domain in case of the absence of CRDA */ |
233 | static const struct ieee80211_regdomain world_regdom = { | 227 | static const struct ieee80211_regdomain world_regdom = { |
234 | .n_reg_rules = 8, | 228 | .n_reg_rules = 8, |
@@ -262,7 +256,7 @@ static const struct ieee80211_regdomain world_regdom = { | |||
262 | REG_RULE(5745-10, 5825+10, 80, 6, 20, | 256 | REG_RULE(5745-10, 5825+10, 80, 6, 20, |
263 | NL80211_RRF_NO_IR), | 257 | NL80211_RRF_NO_IR), |
264 | 258 | ||
265 | /* IEEE 802.11ad (60gHz), channels 1..3 */ | 259 | /* IEEE 802.11ad (60GHz), channels 1..3 */ |
266 | REG_RULE(56160+2160*1-1080, 56160+2160*3+1080, 2160, 0, 0, 0), | 260 | REG_RULE(56160+2160*1-1080, 56160+2160*3+1080, 2160, 0, 0, 0), |
267 | } | 261 | } |
268 | }; | 262 | }; |
@@ -279,6 +273,9 @@ MODULE_PARM_DESC(ieee80211_regdom, "IEEE 802.11 regulatory domain code"); | |||
279 | 273 | ||
280 | static void reg_free_request(struct regulatory_request *request) | 274 | static void reg_free_request(struct regulatory_request *request) |
281 | { | 275 | { |
276 | if (request == &core_request_world) | ||
277 | return; | ||
278 | |||
282 | if (request != get_last_request()) | 279 | if (request != get_last_request()) |
283 | kfree(request); | 280 | kfree(request); |
284 | } | 281 | } |
@@ -453,68 +450,70 @@ reg_copy_regd(const struct ieee80211_regdomain *src_regd) | |||
453 | } | 450 | } |
454 | 451 | ||
455 | #ifdef CONFIG_CFG80211_INTERNAL_REGDB | 452 | #ifdef CONFIG_CFG80211_INTERNAL_REGDB |
456 | struct reg_regdb_search_request { | 453 | struct reg_regdb_apply_request { |
457 | char alpha2[2]; | ||
458 | struct list_head list; | 454 | struct list_head list; |
455 | const struct ieee80211_regdomain *regdom; | ||
459 | }; | 456 | }; |
460 | 457 | ||
461 | static LIST_HEAD(reg_regdb_search_list); | 458 | static LIST_HEAD(reg_regdb_apply_list); |
462 | static DEFINE_MUTEX(reg_regdb_search_mutex); | 459 | static DEFINE_MUTEX(reg_regdb_apply_mutex); |
463 | 460 | ||
464 | static void reg_regdb_search(struct work_struct *work) | 461 | static void reg_regdb_apply(struct work_struct *work) |
465 | { | 462 | { |
466 | struct reg_regdb_search_request *request; | 463 | struct reg_regdb_apply_request *request; |
467 | const struct ieee80211_regdomain *curdom, *regdom = NULL; | ||
468 | int i; | ||
469 | 464 | ||
470 | rtnl_lock(); | 465 | rtnl_lock(); |
471 | 466 | ||
472 | mutex_lock(®_regdb_search_mutex); | 467 | mutex_lock(®_regdb_apply_mutex); |
473 | while (!list_empty(®_regdb_search_list)) { | 468 | while (!list_empty(®_regdb_apply_list)) { |
474 | request = list_first_entry(®_regdb_search_list, | 469 | request = list_first_entry(®_regdb_apply_list, |
475 | struct reg_regdb_search_request, | 470 | struct reg_regdb_apply_request, |
476 | list); | 471 | list); |
477 | list_del(&request->list); | 472 | list_del(&request->list); |
478 | 473 | ||
479 | for (i = 0; i < reg_regdb_size; i++) { | 474 | set_regdom(request->regdom, REGD_SOURCE_INTERNAL_DB); |
480 | curdom = reg_regdb[i]; | ||
481 | |||
482 | if (alpha2_equal(request->alpha2, curdom->alpha2)) { | ||
483 | regdom = reg_copy_regd(curdom); | ||
484 | break; | ||
485 | } | ||
486 | } | ||
487 | |||
488 | kfree(request); | 475 | kfree(request); |
489 | } | 476 | } |
490 | mutex_unlock(®_regdb_search_mutex); | 477 | mutex_unlock(®_regdb_apply_mutex); |
491 | |||
492 | if (!IS_ERR_OR_NULL(regdom)) | ||
493 | set_regdom(regdom, REGD_SOURCE_INTERNAL_DB); | ||
494 | 478 | ||
495 | rtnl_unlock(); | 479 | rtnl_unlock(); |
496 | } | 480 | } |
497 | 481 | ||
498 | static DECLARE_WORK(reg_regdb_work, reg_regdb_search); | 482 | static DECLARE_WORK(reg_regdb_work, reg_regdb_apply); |
499 | 483 | ||
500 | static void reg_regdb_query(const char *alpha2) | 484 | static int reg_query_builtin(const char *alpha2) |
501 | { | 485 | { |
502 | struct reg_regdb_search_request *request; | 486 | const struct ieee80211_regdomain *regdom = NULL; |
487 | struct reg_regdb_apply_request *request; | ||
488 | unsigned int i; | ||
503 | 489 | ||
504 | if (!alpha2) | 490 | for (i = 0; i < reg_regdb_size; i++) { |
505 | return; | 491 | if (alpha2_equal(alpha2, reg_regdb[i]->alpha2)) { |
492 | regdom = reg_regdb[i]; | ||
493 | break; | ||
494 | } | ||
495 | } | ||
496 | |||
497 | if (!regdom) | ||
498 | return -ENODATA; | ||
506 | 499 | ||
507 | request = kzalloc(sizeof(struct reg_regdb_search_request), GFP_KERNEL); | 500 | request = kzalloc(sizeof(struct reg_regdb_apply_request), GFP_KERNEL); |
508 | if (!request) | 501 | if (!request) |
509 | return; | 502 | return -ENOMEM; |
510 | 503 | ||
511 | memcpy(request->alpha2, alpha2, 2); | 504 | request->regdom = reg_copy_regd(regdom); |
505 | if (IS_ERR_OR_NULL(request->regdom)) { | ||
506 | kfree(request); | ||
507 | return -ENOMEM; | ||
508 | } | ||
512 | 509 | ||
513 | mutex_lock(®_regdb_search_mutex); | 510 | mutex_lock(®_regdb_apply_mutex); |
514 | list_add_tail(&request->list, ®_regdb_search_list); | 511 | list_add_tail(&request->list, ®_regdb_apply_list); |
515 | mutex_unlock(®_regdb_search_mutex); | 512 | mutex_unlock(®_regdb_apply_mutex); |
516 | 513 | ||
517 | schedule_work(®_regdb_work); | 514 | schedule_work(®_regdb_work); |
515 | |||
516 | return 0; | ||
518 | } | 517 | } |
519 | 518 | ||
520 | /* Feel free to add any other sanity checks here */ | 519 | /* Feel free to add any other sanity checks here */ |
@@ -525,9 +524,45 @@ static void reg_regdb_size_check(void) | |||
525 | } | 524 | } |
526 | #else | 525 | #else |
527 | static inline void reg_regdb_size_check(void) {} | 526 | static inline void reg_regdb_size_check(void) {} |
528 | static inline void reg_regdb_query(const char *alpha2) {} | 527 | static inline int reg_query_builtin(const char *alpha2) |
528 | { | ||
529 | return -ENODATA; | ||
530 | } | ||
529 | #endif /* CONFIG_CFG80211_INTERNAL_REGDB */ | 531 | #endif /* CONFIG_CFG80211_INTERNAL_REGDB */ |
530 | 532 | ||
533 | #ifdef CONFIG_CFG80211_CRDA_SUPPORT | ||
534 | /* Max number of consecutive attempts to communicate with CRDA */ | ||
535 | #define REG_MAX_CRDA_TIMEOUTS 10 | ||
536 | |||
537 | static u32 reg_crda_timeouts; | ||
538 | |||
539 | static void crda_timeout_work(struct work_struct *work); | ||
540 | static DECLARE_DELAYED_WORK(crda_timeout, crda_timeout_work); | ||
541 | |||
542 | static void crda_timeout_work(struct work_struct *work) | ||
543 | { | ||
544 | REG_DBG_PRINT("Timeout while waiting for CRDA to reply, restoring regulatory settings\n"); | ||
545 | rtnl_lock(); | ||
546 | reg_crda_timeouts++; | ||
547 | restore_regulatory_settings(true); | ||
548 | rtnl_unlock(); | ||
549 | } | ||
550 | |||
551 | static void cancel_crda_timeout(void) | ||
552 | { | ||
553 | cancel_delayed_work(&crda_timeout); | ||
554 | } | ||
555 | |||
556 | static void cancel_crda_timeout_sync(void) | ||
557 | { | ||
558 | cancel_delayed_work_sync(&crda_timeout); | ||
559 | } | ||
560 | |||
561 | static void reset_crda_timeouts(void) | ||
562 | { | ||
563 | reg_crda_timeouts = 0; | ||
564 | } | ||
565 | |||
531 | /* | 566 | /* |
532 | * This lets us keep regulatory code which is updated on a regulatory | 567 | * This lets us keep regulatory code which is updated on a regulatory |
533 | * basis in userspace. | 568 | * basis in userspace. |
@@ -536,13 +571,11 @@ static int call_crda(const char *alpha2) | |||
536 | { | 571 | { |
537 | char country[12]; | 572 | char country[12]; |
538 | char *env[] = { country, NULL }; | 573 | char *env[] = { country, NULL }; |
574 | int ret; | ||
539 | 575 | ||
540 | snprintf(country, sizeof(country), "COUNTRY=%c%c", | 576 | snprintf(country, sizeof(country), "COUNTRY=%c%c", |
541 | alpha2[0], alpha2[1]); | 577 | alpha2[0], alpha2[1]); |
542 | 578 | ||
543 | /* query internal regulatory database (if it exists) */ | ||
544 | reg_regdb_query(alpha2); | ||
545 | |||
546 | if (reg_crda_timeouts > REG_MAX_CRDA_TIMEOUTS) { | 579 | if (reg_crda_timeouts > REG_MAX_CRDA_TIMEOUTS) { |
547 | pr_debug("Exceeded CRDA call max attempts. Not calling CRDA\n"); | 580 | pr_debug("Exceeded CRDA call max attempts. Not calling CRDA\n"); |
548 | return -EINVAL; | 581 | return -EINVAL; |
@@ -554,18 +587,34 @@ static int call_crda(const char *alpha2) | |||
554 | else | 587 | else |
555 | pr_debug("Calling CRDA to update world regulatory domain\n"); | 588 | pr_debug("Calling CRDA to update world regulatory domain\n"); |
556 | 589 | ||
557 | return kobject_uevent_env(®_pdev->dev.kobj, KOBJ_CHANGE, env); | 590 | ret = kobject_uevent_env(®_pdev->dev.kobj, KOBJ_CHANGE, env); |
591 | if (ret) | ||
592 | return ret; | ||
593 | |||
594 | queue_delayed_work(system_power_efficient_wq, | ||
595 | &crda_timeout, msecs_to_jiffies(3142)); | ||
596 | return 0; | ||
597 | } | ||
598 | #else | ||
599 | static inline void cancel_crda_timeout(void) {} | ||
600 | static inline void cancel_crda_timeout_sync(void) {} | ||
601 | static inline void reset_crda_timeouts(void) {} | ||
602 | static inline int call_crda(const char *alpha2) | ||
603 | { | ||
604 | return -ENODATA; | ||
558 | } | 605 | } |
606 | #endif /* CONFIG_CFG80211_CRDA_SUPPORT */ | ||
559 | 607 | ||
560 | static enum reg_request_treatment | 608 | static bool reg_query_database(struct regulatory_request *request) |
561 | reg_call_crda(struct regulatory_request *request) | ||
562 | { | 609 | { |
563 | if (call_crda(request->alpha2)) | 610 | /* query internal regulatory database (if it exists) */ |
564 | return REG_REQ_IGNORE; | 611 | if (reg_query_builtin(request->alpha2) == 0) |
612 | return true; | ||
565 | 613 | ||
566 | queue_delayed_work(system_power_efficient_wq, | 614 | if (call_crda(request->alpha2) == 0) |
567 | ®_timeout, msecs_to_jiffies(3142)); | 615 | return true; |
568 | return REG_REQ_OK; | 616 | |
617 | return false; | ||
569 | } | 618 | } |
570 | 619 | ||
571 | bool reg_is_valid_request(const char *alpha2) | 620 | bool reg_is_valid_request(const char *alpha2) |
@@ -1081,11 +1130,11 @@ const char *reg_initiator_name(enum nl80211_reg_initiator initiator) | |||
1081 | } | 1130 | } |
1082 | EXPORT_SYMBOL(reg_initiator_name); | 1131 | EXPORT_SYMBOL(reg_initiator_name); |
1083 | 1132 | ||
1084 | #ifdef CONFIG_CFG80211_REG_DEBUG | ||
1085 | static void chan_reg_rule_print_dbg(const struct ieee80211_regdomain *regd, | 1133 | static void chan_reg_rule_print_dbg(const struct ieee80211_regdomain *regd, |
1086 | struct ieee80211_channel *chan, | 1134 | struct ieee80211_channel *chan, |
1087 | const struct ieee80211_reg_rule *reg_rule) | 1135 | const struct ieee80211_reg_rule *reg_rule) |
1088 | { | 1136 | { |
1137 | #ifdef CONFIG_CFG80211_REG_DEBUG | ||
1089 | const struct ieee80211_power_rule *power_rule; | 1138 | const struct ieee80211_power_rule *power_rule; |
1090 | const struct ieee80211_freq_range *freq_range; | 1139 | const struct ieee80211_freq_range *freq_range; |
1091 | char max_antenna_gain[32], bw[32]; | 1140 | char max_antenna_gain[32], bw[32]; |
@@ -1096,7 +1145,7 @@ static void chan_reg_rule_print_dbg(const struct ieee80211_regdomain *regd, | |||
1096 | if (!power_rule->max_antenna_gain) | 1145 | if (!power_rule->max_antenna_gain) |
1097 | snprintf(max_antenna_gain, sizeof(max_antenna_gain), "N/A"); | 1146 | snprintf(max_antenna_gain, sizeof(max_antenna_gain), "N/A"); |
1098 | else | 1147 | else |
1099 | snprintf(max_antenna_gain, sizeof(max_antenna_gain), "%d", | 1148 | snprintf(max_antenna_gain, sizeof(max_antenna_gain), "%d mBi", |
1100 | power_rule->max_antenna_gain); | 1149 | power_rule->max_antenna_gain); |
1101 | 1150 | ||
1102 | if (reg_rule->flags & NL80211_RRF_AUTO_BW) | 1151 | if (reg_rule->flags & NL80211_RRF_AUTO_BW) |
@@ -1110,19 +1159,12 @@ static void chan_reg_rule_print_dbg(const struct ieee80211_regdomain *regd, | |||
1110 | REG_DBG_PRINT("Updating information on frequency %d MHz with regulatory rule:\n", | 1159 | REG_DBG_PRINT("Updating information on frequency %d MHz with regulatory rule:\n", |
1111 | chan->center_freq); | 1160 | chan->center_freq); |
1112 | 1161 | ||
1113 | REG_DBG_PRINT("%d KHz - %d KHz @ %s), (%s mBi, %d mBm)\n", | 1162 | REG_DBG_PRINT("(%d KHz - %d KHz @ %s), (%s, %d mBm)\n", |
1114 | freq_range->start_freq_khz, freq_range->end_freq_khz, | 1163 | freq_range->start_freq_khz, freq_range->end_freq_khz, |
1115 | bw, max_antenna_gain, | 1164 | bw, max_antenna_gain, |
1116 | power_rule->max_eirp); | 1165 | power_rule->max_eirp); |
1117 | } | ||
1118 | #else | ||
1119 | static void chan_reg_rule_print_dbg(const struct ieee80211_regdomain *regd, | ||
1120 | struct ieee80211_channel *chan, | ||
1121 | const struct ieee80211_reg_rule *reg_rule) | ||
1122 | { | ||
1123 | return; | ||
1124 | } | ||
1125 | #endif | 1166 | #endif |
1167 | } | ||
1126 | 1168 | ||
1127 | /* | 1169 | /* |
1128 | * Note that right now we assume the desired channel bandwidth | 1170 | * Note that right now we assume the desired channel bandwidth |
@@ -1311,7 +1353,8 @@ static bool reg_dev_ignore_cell_hint(struct wiphy *wiphy) | |||
1311 | return !(wiphy->features & NL80211_FEATURE_CELL_BASE_REG_HINTS); | 1353 | return !(wiphy->features & NL80211_FEATURE_CELL_BASE_REG_HINTS); |
1312 | } | 1354 | } |
1313 | #else | 1355 | #else |
1314 | static int reg_ignore_cell_hint(struct regulatory_request *pending_request) | 1356 | static enum reg_request_treatment |
1357 | reg_ignore_cell_hint(struct regulatory_request *pending_request) | ||
1315 | { | 1358 | { |
1316 | return REG_REQ_IGNORE; | 1359 | return REG_REQ_IGNORE; |
1317 | } | 1360 | } |
@@ -1846,7 +1889,7 @@ static void reg_set_request_processed(void) | |||
1846 | need_more_processing = true; | 1889 | need_more_processing = true; |
1847 | spin_unlock(®_requests_lock); | 1890 | spin_unlock(®_requests_lock); |
1848 | 1891 | ||
1849 | cancel_delayed_work(®_timeout); | 1892 | cancel_crda_timeout(); |
1850 | 1893 | ||
1851 | if (need_more_processing) | 1894 | if (need_more_processing) |
1852 | schedule_work(®_work); | 1895 | schedule_work(®_work); |
@@ -1858,19 +1901,18 @@ static void reg_set_request_processed(void) | |||
1858 | * | 1901 | * |
1859 | * The wireless subsystem can use this function to process | 1902 | * The wireless subsystem can use this function to process |
1860 | * a regulatory request issued by the regulatory core. | 1903 | * a regulatory request issued by the regulatory core. |
1861 | * | ||
1862 | * Returns one of the different reg request treatment values. | ||
1863 | */ | 1904 | */ |
1864 | static enum reg_request_treatment | 1905 | static enum reg_request_treatment |
1865 | reg_process_hint_core(struct regulatory_request *core_request) | 1906 | reg_process_hint_core(struct regulatory_request *core_request) |
1866 | { | 1907 | { |
1908 | if (reg_query_database(core_request)) { | ||
1909 | core_request->intersect = false; | ||
1910 | core_request->processed = false; | ||
1911 | reg_update_last_request(core_request); | ||
1912 | return REG_REQ_OK; | ||
1913 | } | ||
1867 | 1914 | ||
1868 | core_request->intersect = false; | 1915 | return REG_REQ_IGNORE; |
1869 | core_request->processed = false; | ||
1870 | |||
1871 | reg_update_last_request(core_request); | ||
1872 | |||
1873 | return reg_call_crda(core_request); | ||
1874 | } | 1916 | } |
1875 | 1917 | ||
1876 | static enum reg_request_treatment | 1918 | static enum reg_request_treatment |
@@ -1915,8 +1957,6 @@ __reg_process_hint_user(struct regulatory_request *user_request) | |||
1915 | * | 1957 | * |
1916 | * The wireless subsystem can use this function to process | 1958 | * The wireless subsystem can use this function to process |
1917 | * a regulatory request initiated by userspace. | 1959 | * a regulatory request initiated by userspace. |
1918 | * | ||
1919 | * Returns one of the different reg request treatment values. | ||
1920 | */ | 1960 | */ |
1921 | static enum reg_request_treatment | 1961 | static enum reg_request_treatment |
1922 | reg_process_hint_user(struct regulatory_request *user_request) | 1962 | reg_process_hint_user(struct regulatory_request *user_request) |
@@ -1925,20 +1965,20 @@ reg_process_hint_user(struct regulatory_request *user_request) | |||
1925 | 1965 | ||
1926 | treatment = __reg_process_hint_user(user_request); | 1966 | treatment = __reg_process_hint_user(user_request); |
1927 | if (treatment == REG_REQ_IGNORE || | 1967 | if (treatment == REG_REQ_IGNORE || |
1928 | treatment == REG_REQ_ALREADY_SET) { | 1968 | treatment == REG_REQ_ALREADY_SET) |
1929 | reg_free_request(user_request); | 1969 | return REG_REQ_IGNORE; |
1930 | return treatment; | ||
1931 | } | ||
1932 | 1970 | ||
1933 | user_request->intersect = treatment == REG_REQ_INTERSECT; | 1971 | user_request->intersect = treatment == REG_REQ_INTERSECT; |
1934 | user_request->processed = false; | 1972 | user_request->processed = false; |
1935 | 1973 | ||
1936 | reg_update_last_request(user_request); | 1974 | if (reg_query_database(user_request)) { |
1937 | 1975 | reg_update_last_request(user_request); | |
1938 | user_alpha2[0] = user_request->alpha2[0]; | 1976 | user_alpha2[0] = user_request->alpha2[0]; |
1939 | user_alpha2[1] = user_request->alpha2[1]; | 1977 | user_alpha2[1] = user_request->alpha2[1]; |
1978 | return REG_REQ_OK; | ||
1979 | } | ||
1940 | 1980 | ||
1941 | return reg_call_crda(user_request); | 1981 | return REG_REQ_IGNORE; |
1942 | } | 1982 | } |
1943 | 1983 | ||
1944 | static enum reg_request_treatment | 1984 | static enum reg_request_treatment |
@@ -1986,16 +2026,12 @@ reg_process_hint_driver(struct wiphy *wiphy, | |||
1986 | case REG_REQ_OK: | 2026 | case REG_REQ_OK: |
1987 | break; | 2027 | break; |
1988 | case REG_REQ_IGNORE: | 2028 | case REG_REQ_IGNORE: |
1989 | reg_free_request(driver_request); | 2029 | return REG_REQ_IGNORE; |
1990 | return treatment; | ||
1991 | case REG_REQ_INTERSECT: | 2030 | case REG_REQ_INTERSECT: |
1992 | /* fall through */ | ||
1993 | case REG_REQ_ALREADY_SET: | 2031 | case REG_REQ_ALREADY_SET: |
1994 | regd = reg_copy_regd(get_cfg80211_regdom()); | 2032 | regd = reg_copy_regd(get_cfg80211_regdom()); |
1995 | if (IS_ERR(regd)) { | 2033 | if (IS_ERR(regd)) |
1996 | reg_free_request(driver_request); | ||
1997 | return REG_REQ_IGNORE; | 2034 | return REG_REQ_IGNORE; |
1998 | } | ||
1999 | 2035 | ||
2000 | tmp = get_wiphy_regdom(wiphy); | 2036 | tmp = get_wiphy_regdom(wiphy); |
2001 | rcu_assign_pointer(wiphy->regd, regd); | 2037 | rcu_assign_pointer(wiphy->regd, regd); |
@@ -2006,8 +2042,6 @@ reg_process_hint_driver(struct wiphy *wiphy, | |||
2006 | driver_request->intersect = treatment == REG_REQ_INTERSECT; | 2042 | driver_request->intersect = treatment == REG_REQ_INTERSECT; |
2007 | driver_request->processed = false; | 2043 | driver_request->processed = false; |
2008 | 2044 | ||
2009 | reg_update_last_request(driver_request); | ||
2010 | |||
2011 | /* | 2045 | /* |
2012 | * Since CRDA will not be called in this case as we already | 2046 | * Since CRDA will not be called in this case as we already |
2013 | * have applied the requested regulatory domain before we just | 2047 | * have applied the requested regulatory domain before we just |
@@ -2015,11 +2049,17 @@ reg_process_hint_driver(struct wiphy *wiphy, | |||
2015 | */ | 2049 | */ |
2016 | if (treatment == REG_REQ_ALREADY_SET) { | 2050 | if (treatment == REG_REQ_ALREADY_SET) { |
2017 | nl80211_send_reg_change_event(driver_request); | 2051 | nl80211_send_reg_change_event(driver_request); |
2052 | reg_update_last_request(driver_request); | ||
2018 | reg_set_request_processed(); | 2053 | reg_set_request_processed(); |
2019 | return treatment; | 2054 | return REG_REQ_ALREADY_SET; |
2020 | } | 2055 | } |
2021 | 2056 | ||
2022 | return reg_call_crda(driver_request); | 2057 | if (reg_query_database(driver_request)) { |
2058 | reg_update_last_request(driver_request); | ||
2059 | return REG_REQ_OK; | ||
2060 | } | ||
2061 | |||
2062 | return REG_REQ_IGNORE; | ||
2023 | } | 2063 | } |
2024 | 2064 | ||
2025 | static enum reg_request_treatment | 2065 | static enum reg_request_treatment |
@@ -2085,12 +2125,11 @@ reg_process_hint_country_ie(struct wiphy *wiphy, | |||
2085 | case REG_REQ_OK: | 2125 | case REG_REQ_OK: |
2086 | break; | 2126 | break; |
2087 | case REG_REQ_IGNORE: | 2127 | case REG_REQ_IGNORE: |
2088 | /* fall through */ | 2128 | return REG_REQ_IGNORE; |
2089 | case REG_REQ_ALREADY_SET: | 2129 | case REG_REQ_ALREADY_SET: |
2090 | reg_free_request(country_ie_request); | 2130 | reg_free_request(country_ie_request); |
2091 | return treatment; | 2131 | return REG_REQ_ALREADY_SET; |
2092 | case REG_REQ_INTERSECT: | 2132 | case REG_REQ_INTERSECT: |
2093 | reg_free_request(country_ie_request); | ||
2094 | /* | 2133 | /* |
2095 | * This doesn't happen yet, not sure we | 2134 | * This doesn't happen yet, not sure we |
2096 | * ever want to support it for this case. | 2135 | * ever want to support it for this case. |
@@ -2102,9 +2141,12 @@ reg_process_hint_country_ie(struct wiphy *wiphy, | |||
2102 | country_ie_request->intersect = false; | 2141 | country_ie_request->intersect = false; |
2103 | country_ie_request->processed = false; | 2142 | country_ie_request->processed = false; |
2104 | 2143 | ||
2105 | reg_update_last_request(country_ie_request); | 2144 | if (reg_query_database(country_ie_request)) { |
2145 | reg_update_last_request(country_ie_request); | ||
2146 | return REG_REQ_OK; | ||
2147 | } | ||
2106 | 2148 | ||
2107 | return reg_call_crda(country_ie_request); | 2149 | return REG_REQ_IGNORE; |
2108 | } | 2150 | } |
2109 | 2151 | ||
2110 | /* This processes *all* regulatory hints */ | 2152 | /* This processes *all* regulatory hints */ |
@@ -2118,11 +2160,11 @@ static void reg_process_hint(struct regulatory_request *reg_request) | |||
2118 | 2160 | ||
2119 | switch (reg_request->initiator) { | 2161 | switch (reg_request->initiator) { |
2120 | case NL80211_REGDOM_SET_BY_CORE: | 2162 | case NL80211_REGDOM_SET_BY_CORE: |
2121 | reg_process_hint_core(reg_request); | 2163 | treatment = reg_process_hint_core(reg_request); |
2122 | return; | 2164 | break; |
2123 | case NL80211_REGDOM_SET_BY_USER: | 2165 | case NL80211_REGDOM_SET_BY_USER: |
2124 | reg_process_hint_user(reg_request); | 2166 | treatment = reg_process_hint_user(reg_request); |
2125 | return; | 2167 | break; |
2126 | case NL80211_REGDOM_SET_BY_DRIVER: | 2168 | case NL80211_REGDOM_SET_BY_DRIVER: |
2127 | if (!wiphy) | 2169 | if (!wiphy) |
2128 | goto out_free; | 2170 | goto out_free; |
@@ -2138,6 +2180,12 @@ static void reg_process_hint(struct regulatory_request *reg_request) | |||
2138 | goto out_free; | 2180 | goto out_free; |
2139 | } | 2181 | } |
2140 | 2182 | ||
2183 | if (treatment == REG_REQ_IGNORE) | ||
2184 | goto out_free; | ||
2185 | |||
2186 | WARN(treatment != REG_REQ_OK && treatment != REG_REQ_ALREADY_SET, | ||
2187 | "unexpected treatment value %d\n", treatment); | ||
2188 | |||
2141 | /* This is required so that the orig_* parameters are saved. | 2189 | /* This is required so that the orig_* parameters are saved. |
2142 | * NOTE: treatment must be set for any case that reaches here! | 2190 | * NOTE: treatment must be set for any case that reaches here! |
2143 | */ | 2191 | */ |
@@ -2345,7 +2393,7 @@ int regulatory_hint_user(const char *alpha2, | |||
2345 | request->user_reg_hint_type = user_reg_hint_type; | 2393 | request->user_reg_hint_type = user_reg_hint_type; |
2346 | 2394 | ||
2347 | /* Allow calling CRDA again */ | 2395 | /* Allow calling CRDA again */ |
2348 | reg_crda_timeouts = 0; | 2396 | reset_crda_timeouts(); |
2349 | 2397 | ||
2350 | queue_regulatory_request(request); | 2398 | queue_regulatory_request(request); |
2351 | 2399 | ||
@@ -2417,7 +2465,7 @@ int regulatory_hint(struct wiphy *wiphy, const char *alpha2) | |||
2417 | request->initiator = NL80211_REGDOM_SET_BY_DRIVER; | 2465 | request->initiator = NL80211_REGDOM_SET_BY_DRIVER; |
2418 | 2466 | ||
2419 | /* Allow calling CRDA again */ | 2467 | /* Allow calling CRDA again */ |
2420 | reg_crda_timeouts = 0; | 2468 | reset_crda_timeouts(); |
2421 | 2469 | ||
2422 | queue_regulatory_request(request); | 2470 | queue_regulatory_request(request); |
2423 | 2471 | ||
@@ -2473,7 +2521,7 @@ void regulatory_hint_country_ie(struct wiphy *wiphy, enum ieee80211_band band, | |||
2473 | request->country_ie_env = env; | 2521 | request->country_ie_env = env; |
2474 | 2522 | ||
2475 | /* Allow calling CRDA again */ | 2523 | /* Allow calling CRDA again */ |
2476 | reg_crda_timeouts = 0; | 2524 | reset_crda_timeouts(); |
2477 | 2525 | ||
2478 | queue_regulatory_request(request); | 2526 | queue_regulatory_request(request); |
2479 | request = NULL; | 2527 | request = NULL; |
@@ -2874,11 +2922,8 @@ static int reg_set_rd_driver(const struct ieee80211_regdomain *rd, | |||
2874 | } | 2922 | } |
2875 | 2923 | ||
2876 | request_wiphy = wiphy_idx_to_wiphy(driver_request->wiphy_idx); | 2924 | request_wiphy = wiphy_idx_to_wiphy(driver_request->wiphy_idx); |
2877 | if (!request_wiphy) { | 2925 | if (!request_wiphy) |
2878 | queue_delayed_work(system_power_efficient_wq, | ||
2879 | ®_timeout, 0); | ||
2880 | return -ENODEV; | 2926 | return -ENODEV; |
2881 | } | ||
2882 | 2927 | ||
2883 | if (!driver_request->intersect) { | 2928 | if (!driver_request->intersect) { |
2884 | if (request_wiphy->regd) | 2929 | if (request_wiphy->regd) |
@@ -2935,11 +2980,8 @@ static int reg_set_rd_country_ie(const struct ieee80211_regdomain *rd, | |||
2935 | } | 2980 | } |
2936 | 2981 | ||
2937 | request_wiphy = wiphy_idx_to_wiphy(country_ie_request->wiphy_idx); | 2982 | request_wiphy = wiphy_idx_to_wiphy(country_ie_request->wiphy_idx); |
2938 | if (!request_wiphy) { | 2983 | if (!request_wiphy) |
2939 | queue_delayed_work(system_power_efficient_wq, | ||
2940 | ®_timeout, 0); | ||
2941 | return -ENODEV; | 2984 | return -ENODEV; |
2942 | } | ||
2943 | 2985 | ||
2944 | if (country_ie_request->intersect) | 2986 | if (country_ie_request->intersect) |
2945 | return -EINVAL; | 2987 | return -EINVAL; |
@@ -2966,7 +3008,7 @@ int set_regdom(const struct ieee80211_regdomain *rd, | |||
2966 | } | 3008 | } |
2967 | 3009 | ||
2968 | if (regd_src == REGD_SOURCE_CRDA) | 3010 | if (regd_src == REGD_SOURCE_CRDA) |
2969 | reg_crda_timeouts = 0; | 3011 | reset_crda_timeouts(); |
2970 | 3012 | ||
2971 | lr = get_last_request(); | 3013 | lr = get_last_request(); |
2972 | 3014 | ||
@@ -3123,15 +3165,6 @@ void wiphy_regulatory_deregister(struct wiphy *wiphy) | |||
3123 | lr->country_ie_env = ENVIRON_ANY; | 3165 | lr->country_ie_env = ENVIRON_ANY; |
3124 | } | 3166 | } |
3125 | 3167 | ||
3126 | static void reg_timeout_work(struct work_struct *work) | ||
3127 | { | ||
3128 | REG_DBG_PRINT("Timeout while waiting for CRDA to reply, restoring regulatory settings\n"); | ||
3129 | rtnl_lock(); | ||
3130 | reg_crda_timeouts++; | ||
3131 | restore_regulatory_settings(true); | ||
3132 | rtnl_unlock(); | ||
3133 | } | ||
3134 | |||
3135 | /* | 3168 | /* |
3136 | * See http://www.fcc.gov/document/5-ghz-unlicensed-spectrum-unii, for | 3169 | * See http://www.fcc.gov/document/5-ghz-unlicensed-spectrum-unii, for |
3137 | * UNII band definitions | 3170 | * UNII band definitions |
@@ -3217,7 +3250,7 @@ void regulatory_exit(void) | |||
3217 | struct reg_beacon *reg_beacon, *btmp; | 3250 | struct reg_beacon *reg_beacon, *btmp; |
3218 | 3251 | ||
3219 | cancel_work_sync(®_work); | 3252 | cancel_work_sync(®_work); |
3220 | cancel_delayed_work_sync(®_timeout); | 3253 | cancel_crda_timeout_sync(); |
3221 | cancel_delayed_work_sync(®_check_chans); | 3254 | cancel_delayed_work_sync(®_check_chans); |
3222 | 3255 | ||
3223 | /* Lock to suppress warnings */ | 3256 | /* Lock to suppress warnings */ |
diff --git a/net/wireless/scan.c b/net/wireless/scan.c index 3a50aa2553bf..14d5369eb778 100644 --- a/net/wireless/scan.c +++ b/net/wireless/scan.c | |||
@@ -266,8 +266,7 @@ void __cfg80211_sched_scan_results(struct work_struct *wk) | |||
266 | spin_lock_bh(&rdev->bss_lock); | 266 | spin_lock_bh(&rdev->bss_lock); |
267 | __cfg80211_bss_expire(rdev, request->scan_start); | 267 | __cfg80211_bss_expire(rdev, request->scan_start); |
268 | spin_unlock_bh(&rdev->bss_lock); | 268 | spin_unlock_bh(&rdev->bss_lock); |
269 | request->scan_start = | 269 | request->scan_start = jiffies; |
270 | jiffies + msecs_to_jiffies(request->interval); | ||
271 | } | 270 | } |
272 | nl80211_send_sched_scan_results(rdev, request->dev); | 271 | nl80211_send_sched_scan_results(rdev, request->dev); |
273 | } | 272 | } |
@@ -839,6 +838,7 @@ cfg80211_bss_update(struct cfg80211_registered_device *rdev, | |||
839 | found->pub.signal = tmp->pub.signal; | 838 | found->pub.signal = tmp->pub.signal; |
840 | found->pub.capability = tmp->pub.capability; | 839 | found->pub.capability = tmp->pub.capability; |
841 | found->ts = tmp->ts; | 840 | found->ts = tmp->ts; |
841 | found->ts_boottime = tmp->ts_boottime; | ||
842 | } else { | 842 | } else { |
843 | struct cfg80211_internal_bss *new; | 843 | struct cfg80211_internal_bss *new; |
844 | struct cfg80211_internal_bss *hidden; | 844 | struct cfg80211_internal_bss *hidden; |
@@ -938,14 +938,13 @@ cfg80211_get_bss_channel(struct wiphy *wiphy, const u8 *ie, size_t ielen, | |||
938 | } | 938 | } |
939 | 939 | ||
940 | /* Returned bss is reference counted and must be cleaned up appropriately. */ | 940 | /* Returned bss is reference counted and must be cleaned up appropriately. */ |
941 | struct cfg80211_bss* | 941 | struct cfg80211_bss * |
942 | cfg80211_inform_bss_width(struct wiphy *wiphy, | 942 | cfg80211_inform_bss_data(struct wiphy *wiphy, |
943 | struct ieee80211_channel *rx_channel, | 943 | struct cfg80211_inform_bss *data, |
944 | enum nl80211_bss_scan_width scan_width, | 944 | enum cfg80211_bss_frame_type ftype, |
945 | enum cfg80211_bss_frame_type ftype, | 945 | const u8 *bssid, u64 tsf, u16 capability, |
946 | const u8 *bssid, u64 tsf, u16 capability, | 946 | u16 beacon_interval, const u8 *ie, size_t ielen, |
947 | u16 beacon_interval, const u8 *ie, size_t ielen, | 947 | gfp_t gfp) |
948 | s32 signal, gfp_t gfp) | ||
949 | { | 948 | { |
950 | struct cfg80211_bss_ies *ies; | 949 | struct cfg80211_bss_ies *ies; |
951 | struct ieee80211_channel *channel; | 950 | struct ieee80211_channel *channel; |
@@ -957,19 +956,21 @@ cfg80211_inform_bss_width(struct wiphy *wiphy, | |||
957 | return NULL; | 956 | return NULL; |
958 | 957 | ||
959 | if (WARN_ON(wiphy->signal_type == CFG80211_SIGNAL_TYPE_UNSPEC && | 958 | if (WARN_ON(wiphy->signal_type == CFG80211_SIGNAL_TYPE_UNSPEC && |
960 | (signal < 0 || signal > 100))) | 959 | (data->signal < 0 || data->signal > 100))) |
961 | return NULL; | 960 | return NULL; |
962 | 961 | ||
963 | channel = cfg80211_get_bss_channel(wiphy, ie, ielen, rx_channel); | 962 | channel = cfg80211_get_bss_channel(wiphy, ie, ielen, data->chan); |
964 | if (!channel) | 963 | if (!channel) |
965 | return NULL; | 964 | return NULL; |
966 | 965 | ||
967 | memcpy(tmp.pub.bssid, bssid, ETH_ALEN); | 966 | memcpy(tmp.pub.bssid, bssid, ETH_ALEN); |
968 | tmp.pub.channel = channel; | 967 | tmp.pub.channel = channel; |
969 | tmp.pub.scan_width = scan_width; | 968 | tmp.pub.scan_width = data->scan_width; |
970 | tmp.pub.signal = signal; | 969 | tmp.pub.signal = data->signal; |
971 | tmp.pub.beacon_interval = beacon_interval; | 970 | tmp.pub.beacon_interval = beacon_interval; |
972 | tmp.pub.capability = capability; | 971 | tmp.pub.capability = capability; |
972 | tmp.ts_boottime = data->boottime_ns; | ||
973 | |||
973 | /* | 974 | /* |
974 | * If we do not know here whether the IEs are from a Beacon or Probe | 975 | * If we do not know here whether the IEs are from a Beacon or Probe |
975 | * Response frame, we need to pick one of the options and only use it | 976 | * Response frame, we need to pick one of the options and only use it |
@@ -999,7 +1000,7 @@ cfg80211_inform_bss_width(struct wiphy *wiphy, | |||
999 | } | 1000 | } |
1000 | rcu_assign_pointer(tmp.pub.ies, ies); | 1001 | rcu_assign_pointer(tmp.pub.ies, ies); |
1001 | 1002 | ||
1002 | signal_valid = abs(rx_channel->center_freq - channel->center_freq) <= | 1003 | signal_valid = abs(data->chan->center_freq - channel->center_freq) <= |
1003 | wiphy->max_adj_channel_rssi_comp; | 1004 | wiphy->max_adj_channel_rssi_comp; |
1004 | res = cfg80211_bss_update(wiphy_to_rdev(wiphy), &tmp, signal_valid); | 1005 | res = cfg80211_bss_update(wiphy_to_rdev(wiphy), &tmp, signal_valid); |
1005 | if (!res) | 1006 | if (!res) |
@@ -1019,15 +1020,15 @@ cfg80211_inform_bss_width(struct wiphy *wiphy, | |||
1019 | /* cfg80211_bss_update gives us a referenced result */ | 1020 | /* cfg80211_bss_update gives us a referenced result */ |
1020 | return &res->pub; | 1021 | return &res->pub; |
1021 | } | 1022 | } |
1022 | EXPORT_SYMBOL(cfg80211_inform_bss_width); | 1023 | EXPORT_SYMBOL(cfg80211_inform_bss_data); |
1023 | 1024 | ||
1024 | /* Returned bss is reference counted and must be cleaned up appropriately. */ | 1025 | /* cfg80211_inform_bss_width_frame helper */ |
1025 | struct cfg80211_bss * | 1026 | struct cfg80211_bss * |
1026 | cfg80211_inform_bss_width_frame(struct wiphy *wiphy, | 1027 | cfg80211_inform_bss_frame_data(struct wiphy *wiphy, |
1027 | struct ieee80211_channel *rx_channel, | 1028 | struct cfg80211_inform_bss *data, |
1028 | enum nl80211_bss_scan_width scan_width, | 1029 | struct ieee80211_mgmt *mgmt, size_t len, |
1029 | struct ieee80211_mgmt *mgmt, size_t len, | 1030 | gfp_t gfp) |
1030 | s32 signal, gfp_t gfp) | 1031 | |
1031 | { | 1032 | { |
1032 | struct cfg80211_internal_bss tmp = {}, *res; | 1033 | struct cfg80211_internal_bss tmp = {}, *res; |
1033 | struct cfg80211_bss_ies *ies; | 1034 | struct cfg80211_bss_ies *ies; |
@@ -1040,8 +1041,7 @@ cfg80211_inform_bss_width_frame(struct wiphy *wiphy, | |||
1040 | BUILD_BUG_ON(offsetof(struct ieee80211_mgmt, u.probe_resp.variable) != | 1041 | BUILD_BUG_ON(offsetof(struct ieee80211_mgmt, u.probe_resp.variable) != |
1041 | offsetof(struct ieee80211_mgmt, u.beacon.variable)); | 1042 | offsetof(struct ieee80211_mgmt, u.beacon.variable)); |
1042 | 1043 | ||
1043 | trace_cfg80211_inform_bss_width_frame(wiphy, rx_channel, scan_width, mgmt, | 1044 | trace_cfg80211_inform_bss_frame(wiphy, data, mgmt, len); |
1044 | len, signal); | ||
1045 | 1045 | ||
1046 | if (WARN_ON(!mgmt)) | 1046 | if (WARN_ON(!mgmt)) |
1047 | return NULL; | 1047 | return NULL; |
@@ -1050,14 +1050,14 @@ cfg80211_inform_bss_width_frame(struct wiphy *wiphy, | |||
1050 | return NULL; | 1050 | return NULL; |
1051 | 1051 | ||
1052 | if (WARN_ON(wiphy->signal_type == CFG80211_SIGNAL_TYPE_UNSPEC && | 1052 | if (WARN_ON(wiphy->signal_type == CFG80211_SIGNAL_TYPE_UNSPEC && |
1053 | (signal < 0 || signal > 100))) | 1053 | (data->signal < 0 || data->signal > 100))) |
1054 | return NULL; | 1054 | return NULL; |
1055 | 1055 | ||
1056 | if (WARN_ON(len < offsetof(struct ieee80211_mgmt, u.probe_resp.variable))) | 1056 | if (WARN_ON(len < offsetof(struct ieee80211_mgmt, u.probe_resp.variable))) |
1057 | return NULL; | 1057 | return NULL; |
1058 | 1058 | ||
1059 | channel = cfg80211_get_bss_channel(wiphy, mgmt->u.beacon.variable, | 1059 | channel = cfg80211_get_bss_channel(wiphy, mgmt->u.beacon.variable, |
1060 | ielen, rx_channel); | 1060 | ielen, data->chan); |
1061 | if (!channel) | 1061 | if (!channel) |
1062 | return NULL; | 1062 | return NULL; |
1063 | 1063 | ||
@@ -1077,12 +1077,13 @@ cfg80211_inform_bss_width_frame(struct wiphy *wiphy, | |||
1077 | 1077 | ||
1078 | memcpy(tmp.pub.bssid, mgmt->bssid, ETH_ALEN); | 1078 | memcpy(tmp.pub.bssid, mgmt->bssid, ETH_ALEN); |
1079 | tmp.pub.channel = channel; | 1079 | tmp.pub.channel = channel; |
1080 | tmp.pub.scan_width = scan_width; | 1080 | tmp.pub.scan_width = data->scan_width; |
1081 | tmp.pub.signal = signal; | 1081 | tmp.pub.signal = data->signal; |
1082 | tmp.pub.beacon_interval = le16_to_cpu(mgmt->u.probe_resp.beacon_int); | 1082 | tmp.pub.beacon_interval = le16_to_cpu(mgmt->u.probe_resp.beacon_int); |
1083 | tmp.pub.capability = le16_to_cpu(mgmt->u.probe_resp.capab_info); | 1083 | tmp.pub.capability = le16_to_cpu(mgmt->u.probe_resp.capab_info); |
1084 | tmp.ts_boottime = data->boottime_ns; | ||
1084 | 1085 | ||
1085 | signal_valid = abs(rx_channel->center_freq - channel->center_freq) <= | 1086 | signal_valid = abs(data->chan->center_freq - channel->center_freq) <= |
1086 | wiphy->max_adj_channel_rssi_comp; | 1087 | wiphy->max_adj_channel_rssi_comp; |
1087 | res = cfg80211_bss_update(wiphy_to_rdev(wiphy), &tmp, signal_valid); | 1088 | res = cfg80211_bss_update(wiphy_to_rdev(wiphy), &tmp, signal_valid); |
1088 | if (!res) | 1089 | if (!res) |
@@ -1102,7 +1103,7 @@ cfg80211_inform_bss_width_frame(struct wiphy *wiphy, | |||
1102 | /* cfg80211_bss_update gives us a referenced result */ | 1103 | /* cfg80211_bss_update gives us a referenced result */ |
1103 | return &res->pub; | 1104 | return &res->pub; |
1104 | } | 1105 | } |
1105 | EXPORT_SYMBOL(cfg80211_inform_bss_width_frame); | 1106 | EXPORT_SYMBOL(cfg80211_inform_bss_frame_data); |
1106 | 1107 | ||
1107 | void cfg80211_ref_bss(struct wiphy *wiphy, struct cfg80211_bss *pub) | 1108 | void cfg80211_ref_bss(struct wiphy *wiphy, struct cfg80211_bss *pub) |
1108 | { | 1109 | { |
diff --git a/net/wireless/trace.h b/net/wireless/trace.h index a808279a432a..0c392d36781b 100644 --- a/net/wireless/trace.h +++ b/net/wireless/trace.h | |||
@@ -2670,30 +2670,30 @@ TRACE_EVENT(cfg80211_get_bss, | |||
2670 | __entry->privacy) | 2670 | __entry->privacy) |
2671 | ); | 2671 | ); |
2672 | 2672 | ||
2673 | TRACE_EVENT(cfg80211_inform_bss_width_frame, | 2673 | TRACE_EVENT(cfg80211_inform_bss_frame, |
2674 | TP_PROTO(struct wiphy *wiphy, struct ieee80211_channel *channel, | 2674 | TP_PROTO(struct wiphy *wiphy, struct cfg80211_inform_bss *data, |
2675 | enum nl80211_bss_scan_width scan_width, | 2675 | struct ieee80211_mgmt *mgmt, size_t len), |
2676 | struct ieee80211_mgmt *mgmt, size_t len, | 2676 | TP_ARGS(wiphy, data, mgmt, len), |
2677 | s32 signal), | ||
2678 | TP_ARGS(wiphy, channel, scan_width, mgmt, len, signal), | ||
2679 | TP_STRUCT__entry( | 2677 | TP_STRUCT__entry( |
2680 | WIPHY_ENTRY | 2678 | WIPHY_ENTRY |
2681 | CHAN_ENTRY | 2679 | CHAN_ENTRY |
2682 | __field(enum nl80211_bss_scan_width, scan_width) | 2680 | __field(enum nl80211_bss_scan_width, scan_width) |
2683 | __dynamic_array(u8, mgmt, len) | 2681 | __dynamic_array(u8, mgmt, len) |
2684 | __field(s32, signal) | 2682 | __field(s32, signal) |
2683 | __field(u64, ts_boottime) | ||
2685 | ), | 2684 | ), |
2686 | TP_fast_assign( | 2685 | TP_fast_assign( |
2687 | WIPHY_ASSIGN; | 2686 | WIPHY_ASSIGN; |
2688 | CHAN_ASSIGN(channel); | 2687 | CHAN_ASSIGN(data->chan); |
2689 | __entry->scan_width = scan_width; | 2688 | __entry->scan_width = data->scan_width; |
2690 | if (mgmt) | 2689 | if (mgmt) |
2691 | memcpy(__get_dynamic_array(mgmt), mgmt, len); | 2690 | memcpy(__get_dynamic_array(mgmt), mgmt, len); |
2692 | __entry->signal = signal; | 2691 | __entry->signal = data->signal; |
2692 | __entry->ts_boottime = data->boottime_ns; | ||
2693 | ), | 2693 | ), |
2694 | TP_printk(WIPHY_PR_FMT ", " CHAN_PR_FMT "(scan_width: %d) signal: %d", | 2694 | TP_printk(WIPHY_PR_FMT ", " CHAN_PR_FMT "(scan_width: %d) signal: %d, tsb:%llu", |
2695 | WIPHY_PR_ARG, CHAN_PR_ARG, __entry->scan_width, | 2695 | WIPHY_PR_ARG, CHAN_PR_ARG, __entry->scan_width, |
2696 | __entry->signal) | 2696 | __entry->signal, (unsigned long long)__entry->ts_boottime) |
2697 | ); | 2697 | ); |
2698 | 2698 | ||
2699 | DECLARE_EVENT_CLASS(cfg80211_bss_evt, | 2699 | DECLARE_EVENT_CLASS(cfg80211_bss_evt, |