diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2015-11-04 09:41:05 -0800 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2015-11-04 09:41:05 -0800 |
commit | b0f85fa11aefc4f3e03306b4cd47f113bd57dcba (patch) | |
tree | 1333d36d99fde3f97210795941fc246f0ad08a75 /drivers/net/wireless/iwlwifi/mvm/scan.c | |
parent | ccc9d4a6d640cbde05d519edeb727881646cf71b (diff) | |
parent | f32bfb9a8ca083f8d148ea90ae5ba66f4831836e (diff) | |
download | linux-b0f85fa11aefc4f3e03306b4cd47f113bd57dcba.tar.bz2 |
Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net-next
Pull networking updates from David Miller:
Changes of note:
1) Allow to schedule ICMP packets in IPVS, from Alex Gartrell.
2) Provide FIB table ID in ipv4 route dumps just as ipv6 does, from
David Ahern.
3) Allow the user to ask for the statistics to be filtered out of
ipv4/ipv6 address netlink dumps. From Sowmini Varadhan.
4) More work to pass the network namespace context around deep into
various packet path APIs, starting with the netfilter hooks. From
Eric W Biederman.
5) Add layer 2 TX/RX checksum offloading to qeth driver, from Thomas
Richter.
6) Use usec resolution for SYN/ACK RTTs in TCP, from Yuchung Cheng.
7) Support Very High Throughput in wireless MESH code, from Bob
Copeland.
8) Allow setting the ageing_time in switchdev/rocker. From Scott
Feldman.
9) Properly autoload L2TP type modules, from Stephen Hemminger.
10) Fix and enable offload features by default in 8139cp driver, from
David Woodhouse.
11) Support both ipv4 and ipv6 sockets in a single vxlan device, from
Jiri Benc.
12) Fix CWND limiting of thin streams in TCP, from Bendik Rønning
Opstad.
13) Fix IPSEC flowcache overflows on large systems, from Steffen
Klassert.
14) Convert bridging to track VLANs using rhashtable entries rather than
a bitmap. From Nikolay Aleksandrov.
15) Make TCP listener handling completely lockless, this is a major
accomplishment. Incoming request sockets now live in the
established hash table just like any other socket too.
From Eric Dumazet.
15) Provide more bridging attributes to netlink, from Nikolay
Aleksandrov.
16) Use hash based algorithm for ipv4 multipath routing, this was very
long overdue. From Peter Nørlund.
17) Several y2038 cures, mostly avoiding timespec. From Arnd Bergmann.
18) Allow non-root execution of EBPF programs, from Alexei Starovoitov.
19) Support SO_INCOMING_CPU as setsockopt, from Eric Dumazet. This
influences the port binding selection logic used by SO_REUSEPORT.
20) Add ipv6 support to VRF, from David Ahern.
21) Add support for Mellanox Spectrum switch ASIC, from Jiri Pirko.
22) Add rtl8xxxu Realtek wireless driver, from Jes Sorensen.
23) Implement RACK loss recovery in TCP, from Yuchung Cheng.
24) Support multipath routes in MPLS, from Roopa Prabhu.
25) Fix POLLOUT notification for listening sockets in AF_UNIX, from Eric
Dumazet.
26) Add new QED Qlogic river, from Yuval Mintz, Manish Chopra, and
Sudarsana Kalluru.
27) Don't fetch timestamps on AF_UNIX sockets, from Hannes Frederic
Sowa.
28) Support ipv6 geneve tunnels, from John W Linville.
29) Add flood control support to switchdev layer, from Ido Schimmel.
30) Fix CHECKSUM_PARTIAL handling of potentially fragmented frames, from
Hannes Frederic Sowa.
31) Support persistent maps and progs in bpf, from Daniel Borkmann.
* git://git.kernel.org/pub/scm/linux/kernel/git/davem/net-next: (1790 commits)
sh_eth: use DMA barriers
switchdev: respect SKIP_EOPNOTSUPP flag in case there is no recursion
net: sched: kill dead code in sch_choke.c
irda: Delete an unnecessary check before the function call "irlmp_unregister_service"
net: dsa: mv88e6xxx: include DSA ports in VLANs
net: dsa: mv88e6xxx: disable SA learning for DSA and CPU ports
net/core: fix for_each_netdev_feature
vlan: Invoke driver vlan hooks only if device is present
arcnet/com20020: add LEDS_CLASS dependency
bpf, verifier: annotate verbose printer with __printf
dp83640: Only wait for timestamps for packets with timestamping enabled.
ptp: Change ptp_class to a proper bitmask
dp83640: Prune rx timestamp list before reading from it
dp83640: Delay scheduled work.
dp83640: Include hash in timestamp/packet matching
ipv6: fix tunnel error handling
net/mlx5e: Fix LSO vlan insertion
net/mlx5e: Re-eanble client vlan TX acceleration
net/mlx5e: Return error in case mlx5e_set_features() fails
net/mlx5e: Don't allow more than max supported channels
...
Diffstat (limited to 'drivers/net/wireless/iwlwifi/mvm/scan.c')
-rw-r--r-- | drivers/net/wireless/iwlwifi/mvm/scan.c | 122 |
1 files changed, 69 insertions, 53 deletions
diff --git a/drivers/net/wireless/iwlwifi/mvm/scan.c b/drivers/net/wireless/iwlwifi/mvm/scan.c index 56559d4d34ad..d6e0c1b5c20c 100644 --- a/drivers/net/wireless/iwlwifi/mvm/scan.c +++ b/drivers/net/wireless/iwlwifi/mvm/scan.c @@ -131,7 +131,6 @@ struct iwl_mvm_scan_params { int n_ssids; struct cfg80211_ssid *ssids; struct ieee80211_channel **channels; - u16 interval; /* interval between scans (in secs) */ u32 flags; u8 *mac_addr; u8 *mac_addr_mask; @@ -140,7 +139,8 @@ struct iwl_mvm_scan_params { int n_match_sets; struct iwl_scan_probe_req preq; struct cfg80211_match_set *match_sets; - u8 iterations[2]; + int n_scan_plans; + struct cfg80211_sched_scan_plan *scan_plans; }; static u8 iwl_mvm_scan_rx_ant(struct iwl_mvm *mvm) @@ -474,7 +474,7 @@ iwl_mvm_config_sched_scan_profiles(struct iwl_mvm *mvm, int ret; if (WARN_ON(req->n_match_sets > IWL_SCAN_MAX_PROFILES)) - return -EIO; + return -EIO; if (mvm->fw->ucode_capa.flags & IWL_UCODE_TLV_FLAGS_SHORT_BL) blacklist_len = IWL_SCAN_SHORT_BLACKLIST_LEN; @@ -737,8 +737,7 @@ static inline bool iwl_mvm_scan_fits(struct iwl_mvm *mvm, int n_ssids, } static inline bool iwl_mvm_scan_use_ebs(struct iwl_mvm *mvm, - struct ieee80211_vif *vif, - int n_iterations) + struct ieee80211_vif *vif) { const struct iwl_ucode_capabilities *capa = &mvm->fw->ucode_capa; @@ -750,16 +749,9 @@ static inline bool iwl_mvm_scan_use_ebs(struct iwl_mvm *mvm, */ return ((capa->flags & IWL_UCODE_TLV_FLAGS_EBS_SUPPORT) && mvm->last_ebs_successful && - (n_iterations > 1 || - fw_has_api(capa, IWL_UCODE_TLV_API_SINGLE_SCAN_EBS)) && vif->type != NL80211_IFTYPE_P2P_DEVICE); } -static int iwl_mvm_scan_total_iterations(struct iwl_mvm_scan_params *params) -{ - return params->iterations[0] + params->iterations[1]; -} - static int iwl_mvm_scan_lmac_flags(struct iwl_mvm *mvm, struct iwl_mvm_scan_params *params) { @@ -798,12 +790,15 @@ static int iwl_mvm_scan_lmac(struct iwl_mvm *mvm, struct ieee80211_vif *vif, (void *)(cmd->data + sizeof(struct iwl_scan_channel_cfg_lmac) * mvm->fw->ucode_capa.n_scan_channels); u32 ssid_bitmap = 0; - int n_iterations = iwl_mvm_scan_total_iterations(params); + int i; lockdep_assert_held(&mvm->mutex); memset(cmd, 0, ksize(cmd)); + if (WARN_ON(params->n_scan_plans > IWL_MAX_SCHED_SCAN_PLANS)) + return -EINVAL; + iwl_mvm_scan_lmac_dwell(mvm, cmd, params); cmd->rx_chain_select = iwl_mvm_scan_rx_chain(mvm); @@ -823,14 +818,26 @@ static int iwl_mvm_scan_lmac(struct iwl_mvm *mvm, struct ieee80211_vif *vif, /* this API uses bits 1-20 instead of 0-19 */ ssid_bitmap <<= 1; - cmd->schedule[0].delay = cpu_to_le16(params->interval); - cmd->schedule[0].iterations = params->iterations[0]; - cmd->schedule[0].full_scan_mul = 1; - cmd->schedule[1].delay = cpu_to_le16(params->interval); - cmd->schedule[1].iterations = params->iterations[1]; - cmd->schedule[1].full_scan_mul = 1; + for (i = 0; i < params->n_scan_plans; i++) { + struct cfg80211_sched_scan_plan *scan_plan = + ¶ms->scan_plans[i]; + + cmd->schedule[i].delay = + cpu_to_le16(scan_plan->interval); + cmd->schedule[i].iterations = scan_plan->iterations; + cmd->schedule[i].full_scan_mul = 1; + } + + /* + * If the number of iterations of the last scan plan is set to + * zero, it should run infinitely. However, this is not always the case. + * For example, when regular scan is requested the driver sets one scan + * plan with one iteration. + */ + if (!cmd->schedule[i - 1].iterations) + cmd->schedule[i - 1].iterations = 0xff; - if (iwl_mvm_scan_use_ebs(mvm, vif, n_iterations)) { + if (iwl_mvm_scan_use_ebs(mvm, vif)) { cmd->channel_opt[0].flags = cpu_to_le16(IWL_SCAN_CHANNEL_FLAG_EBS | IWL_SCAN_CHANNEL_FLAG_EBS_ACCURATE | @@ -894,7 +901,6 @@ static __le32 iwl_mvm_scan_config_rates(struct iwl_mvm *mvm) int iwl_mvm_config_scan(struct iwl_mvm *mvm) { - struct iwl_scan_config *scan_config; struct ieee80211_supported_band *band; int num_channels = @@ -970,6 +976,12 @@ static int iwl_mvm_scan_uid_by_status(struct iwl_mvm *mvm, int status) return -ENOENT; } +static inline bool iwl_mvm_is_regular_scan(struct iwl_mvm_scan_params *params) +{ + return params->n_scan_plans == 1 && + params->scan_plans[0].iterations == 1; +} + static void iwl_mvm_scan_umac_dwell(struct iwl_mvm *mvm, struct iwl_scan_req_umac *cmd, struct iwl_mvm_scan_params *params) @@ -982,7 +994,7 @@ static void iwl_mvm_scan_umac_dwell(struct iwl_mvm *mvm, cmd->scan_priority = iwl_mvm_scan_priority(mvm, IWL_SCAN_PRIORITY_EXT_6); - if (iwl_mvm_scan_total_iterations(params) == 1) + if (iwl_mvm_is_regular_scan(params)) cmd->ooc_priority = iwl_mvm_scan_priority(mvm, IWL_SCAN_PRIORITY_EXT_6); else @@ -1029,7 +1041,7 @@ static u32 iwl_mvm_scan_umac_flags(struct iwl_mvm *mvm, else flags |= IWL_UMAC_SCAN_GEN_FLAGS_MATCH; - if (iwl_mvm_scan_total_iterations(params) > 1) + if (!iwl_mvm_is_regular_scan(params)) flags |= IWL_UMAC_SCAN_GEN_FLAGS_PERIODIC; #ifdef CONFIG_IWLWIFI_DEBUGFS @@ -1047,12 +1059,14 @@ static int iwl_mvm_scan_umac(struct iwl_mvm *mvm, struct ieee80211_vif *vif, struct iwl_scan_req_umac_tail *sec_part = (void *)&cmd->data + sizeof(struct iwl_scan_channel_cfg_umac) * mvm->fw->ucode_capa.n_scan_channels; - int uid; + int uid, i; u32 ssid_bitmap = 0; - int n_iterations = iwl_mvm_scan_total_iterations(params); lockdep_assert_held(&mvm->mutex); + if (WARN_ON(params->n_scan_plans > IWL_MAX_SCHED_SCAN_PLANS)) + return -EINVAL; + uid = iwl_mvm_scan_uid_by_status(mvm, 0); if (uid < 0) return uid; @@ -1069,7 +1083,7 @@ static int iwl_mvm_scan_umac(struct iwl_mvm *mvm, struct ieee80211_vif *vif, if (type == IWL_MVM_SCAN_SCHED) cmd->flags = cpu_to_le32(IWL_UMAC_SCAN_FLAG_PREEMPTIVE); - if (iwl_mvm_scan_use_ebs(mvm, vif, n_iterations)) + if (iwl_mvm_scan_use_ebs(mvm, vif)) cmd->channel_flags = IWL_SCAN_CHANNEL_FLAG_EBS | IWL_SCAN_CHANNEL_FLAG_EBS_ACCURATE | IWL_SCAN_CHANNEL_FLAG_CACHE_ADD; @@ -1081,12 +1095,23 @@ static int iwl_mvm_scan_umac(struct iwl_mvm *mvm, struct ieee80211_vif *vif, iwl_mvm_umac_scan_cfg_channels(mvm, params->channels, params->n_channels, ssid_bitmap, cmd); - /* With UMAC we use only one schedule for now, so use the sum - * of the iterations (with a a maximum of 255). + for (i = 0; i < params->n_scan_plans; i++) { + struct cfg80211_sched_scan_plan *scan_plan = + ¶ms->scan_plans[i]; + + sec_part->schedule[i].iter_count = scan_plan->iterations; + sec_part->schedule[i].interval = + cpu_to_le16(scan_plan->interval); + } + + /* + * If the number of iterations of the last scan plan is set to + * zero, it should run infinitely. However, this is not always the case. + * For example, when regular scan is requested the driver sets one scan + * plan with one iteration. */ - sec_part->schedule[0].iter_count = - (n_iterations > 255) ? 255 : n_iterations; - sec_part->schedule[0].interval = cpu_to_le16(params->interval); + if (!sec_part->schedule[i - 1].iter_count) + sec_part->schedule[i - 1].iter_count = 0xff; sec_part->delay = cpu_to_le16(params->delay); sec_part->preq = params->preq; @@ -1152,6 +1177,7 @@ int iwl_mvm_reg_scan_start(struct iwl_mvm *mvm, struct ieee80211_vif *vif, }; struct iwl_mvm_scan_params params = {}; int ret; + struct cfg80211_sched_scan_plan scan_plan = { .iterations = 1 }; lockdep_assert_held(&mvm->mutex); @@ -1164,8 +1190,6 @@ int iwl_mvm_reg_scan_start(struct iwl_mvm *mvm, struct ieee80211_vif *vif, if (ret) return ret; - iwl_mvm_ref(mvm, IWL_MVM_REF_SCAN); - /* we should have failed registration if scan_cmd was NULL */ if (WARN_ON(!mvm->scan_cmd)) return -ENOMEM; @@ -1177,7 +1201,6 @@ int iwl_mvm_reg_scan_start(struct iwl_mvm *mvm, struct ieee80211_vif *vif, params.flags = req->flags; params.n_channels = req->n_channels; params.delay = 0; - params.interval = 0; params.ssids = req->ssids; params.channels = req->channels; params.mac_addr = req->mac_addr; @@ -1187,8 +1210,8 @@ int iwl_mvm_reg_scan_start(struct iwl_mvm *mvm, struct ieee80211_vif *vif, params.n_match_sets = 0; params.match_sets = NULL; - params.iterations[0] = 1; - params.iterations[1] = 0; + params.scan_plans = &scan_plan; + params.n_scan_plans = 1; params.type = iwl_mvm_get_scan_type(mvm, vif, ¶ms); @@ -1207,21 +1230,20 @@ int iwl_mvm_reg_scan_start(struct iwl_mvm *mvm, struct ieee80211_vif *vif, return ret; ret = iwl_mvm_send_cmd(mvm, &hcmd); - if (!ret) { - IWL_DEBUG_SCAN(mvm, "Scan request was sent successfully\n"); - mvm->scan_status |= IWL_MVM_SCAN_REGULAR; - } else { + if (ret) { /* If the scan failed, it usually means that the FW was unable * to allocate the time events. Warn on it, but maybe we * should try to send the command again with different params. */ IWL_ERR(mvm, "Scan failed! ret %d\n", ret); + return ret; } - if (ret) - iwl_mvm_unref(mvm, IWL_MVM_REF_SCAN); + IWL_DEBUG_SCAN(mvm, "Scan request was sent successfully\n"); + mvm->scan_status |= IWL_MVM_SCAN_REGULAR; + iwl_mvm_ref(mvm, IWL_MVM_REF_SCAN); - return ret; + return 0; } int iwl_mvm_sched_scan_start(struct iwl_mvm *mvm, @@ -1267,20 +1289,14 @@ int iwl_mvm_sched_scan_start(struct iwl_mvm *mvm, params.pass_all = iwl_mvm_scan_pass_all(mvm, req); params.n_match_sets = req->n_match_sets; params.match_sets = req->match_sets; + if (!req->n_scan_plans) + return -EINVAL; - params.iterations[0] = 0; - params.iterations[1] = 0xff; + params.n_scan_plans = req->n_scan_plans; + params.scan_plans = req->scan_plans; params.type = iwl_mvm_get_scan_type(mvm, vif, ¶ms); - if (req->interval > U16_MAX) { - IWL_DEBUG_SCAN(mvm, - "interval value is > 16-bits, set to max possible\n"); - params.interval = U16_MAX; - } else { - params.interval = req->interval / MSEC_PER_SEC; - } - /* In theory, LMAC scans can handle a 32-bit delay, but since * waiting for over 18 hours to start the scan is a bit silly * and to keep it aligned with UMAC scans (which only support |