History

nl80211: allow multiple active scheduled scan requests

This patch implements the idea to have multiple scheduled scan requests running concurrently. It mainly illustrates how to deal with the incoming request from user-space in terms of backward compatibility. In order to use multiple scheduled scans user-space needs to provide a flag attribute NL80211_ATTR_SCHED_SCAN_MULTI to indicate support. If not the request is treated as a legacy scan. Drivers currently supporting scheduled scan are now indicating they support a single scheduled scan request. This obsoletes WIPHY_FLAG_SUPPORTS_SCHED_SCAN.

Arend Van Spriel committed 9 years ago

Commit ca986ad1 parent ab8100713 files · +205 −64Browse files

Unified · Split

13 files
  1. drivers/net/wireless/ath/ath6kl/cfg80211.c +1 −1
  2. drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c +1 −1
  3. drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c +1 −1
  4. drivers/net/wireless/marvell/mwifiex/cfg80211.c +1 −1
  5. drivers/net/wireless/ti/wlcore/main.c +1 −1
  6. include/net/cfg80211.h +8 −1
  7. include/uapi/linux/nl80211.h +11 −1
  8. net/wireless/core.c +17 −12
  9. net/wireless/core.h +9 −2
  10. net/wireless/nl80211.c +46 −17
  11. net/wireless/rdev-ops.h +1 −1
  12. net/wireless/scan.c +96 −19
  13. net/wireless/trace.h +12 −6
drivers/net/wireless/ath/ath6kl/cfg80211.c+1−1
@@ -3973,7 +3973,7 @@ int ath6kl_cfg80211_init(struct ath6kl *ar) · 3972 unmodified lines
39733973 WIPHY_FLAG_AP_PROBE_RESP_OFFLOAD;
39743974
39753975 if (test_bit(ATH6KL_FW_CAPABILITY_SCHED_SCAN_V2, ar->fw_capabilities))
3976− ar->wiphy->flags |= WIPHY_FLAG_SUPPORTS_SCHED_SCAN;
3976+ ar->wiphy->max_sched_scan_reqs = 1;
39773977
39783978 if (test_bit(ATH6KL_FW_CAPABILITY_INACTIVITY_TIMEOUT,
39793979 ar->fw_capabilities))
drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c+1−1
@@ -6374,11 +6374,11 @@ err: · 6373 unmodified lines
63746374 static void brcmf_wiphy_pno_params(struct wiphy *wiphy)
63756375 {
63766376 /* scheduled scan settings */
6377+ wiphy->max_sched_scan_reqs = 1;
63776378 wiphy->max_sched_scan_ssids = BRCMF_PNO_MAX_PFN_COUNT;
63786379 wiphy->max_match_sets = BRCMF_PNO_MAX_PFN_COUNT;
63796380 wiphy->max_sched_scan_ie_len = BRCMF_SCAN_IE_LEN_MAX;
63806381 wiphy->max_sched_scan_plan_interval = BRCMF_PNO_SCHED_SCAN_MAX_PERIOD;
6381− wiphy->flags |= WIPHY_FLAG_SUPPORTS_SCHED_SCAN;
63826382 }
63836383
63846384 #ifdef CONFIG_PM
drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c+1−1
@@ -620,7 +620,7 @@ int iwl_mvm_mac_setup_register(struct iwl_mvm *mvm) · 619 unmodified lines
620620 else
621621 hw->wiphy->flags &= ~WIPHY_FLAG_PS_ON_BY_DEFAULT;
622622
623− hw->wiphy->flags |= WIPHY_FLAG_SUPPORTS_SCHED_SCAN;
623+ hw->wiphy->max_sched_scan_reqs = 1;
624624 hw->wiphy->max_sched_scan_ssids = PROBE_OPTION_MAX;
625625 hw->wiphy->max_match_sets = IWL_SCAN_MAX_PROFILES;
626626 /* we create the 802.11 header and zero length SSID IE. */
drivers/net/wireless/marvell/mwifiex/cfg80211.c+1−1
@@ -4297,7 +4297,6 @@ int mwifiex_register_cfg80211(struct mwifiex_adapter *adapter) · 4296 unmodified lines
42974297 wiphy->flags |= WIPHY_FLAG_HAVE_AP_SME |
42984298 WIPHY_FLAG_AP_PROBE_RESP_OFFLOAD |
42994299 WIPHY_FLAG_AP_UAPSD |
4300− WIPHY_FLAG_SUPPORTS_SCHED_SCAN |
43014300 WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL |
43024301 WIPHY_FLAG_HAS_CHANNEL_SWITCH |
43034302 WIPHY_FLAG_PS_ON_BY_DEFAULT;
@@ -4316,6 +4315,7 @@ int mwifiex_register_cfg80211(struct mwifiex_adapter *adapter) · 12 unmodified lines
43164315 NL80211_PROBE_RESP_OFFLOAD_SUPPORT_WPS2 |
43174316 NL80211_PROBE_RESP_OFFLOAD_SUPPORT_P2P;
43184317
4318+ wiphy->max_sched_scan_reqs = 1;
43194319 wiphy->max_sched_scan_ssids = MWIFIEX_MAX_SSID_LIST_LENGTH;
43204320 wiphy->max_sched_scan_ie_len = MWIFIEX_MAX_VSIE_LEN;
43214321 wiphy->max_match_sets = MWIFIEX_MAX_SSID_LIST_LENGTH;
drivers/net/wireless/ti/wlcore/main.c+1−1
@@ -6128,6 +6128,7 @@ static int wl1271_init_ieee80211(struct wl1271 *wl) · 6127 unmodified lines
61286128 wl->hw->wiphy->max_scan_ie_len = WL1271_CMD_TEMPL_MAX_SIZE -
61296129 sizeof(struct ieee80211_header);
61306130
6131+ wl->hw->wiphy->max_sched_scan_reqs = 1;
61316132 wl->hw->wiphy->max_sched_scan_ie_len = WL1271_CMD_TEMPL_MAX_SIZE -
61326133 sizeof(struct ieee80211_header);
61336134
@@ -6135,7 +6136,6 @@ static int wl1271_init_ieee80211(struct wl1271 *wl) · 1 unmodified line
61356136
61366137 wl->hw->wiphy->flags |= WIPHY_FLAG_AP_UAPSD |
61376138 WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL |
6138− WIPHY_FLAG_SUPPORTS_SCHED_SCAN |
61396139 WIPHY_FLAG_HAS_CHANNEL_SWITCH;
61406140
61416141 wl->hw->wiphy->features |= NL80211_FEATURE_AP_SCAN;
include/net/cfg80211.h+8−1
@@ -1678,6 +1678,8 @@ struct cfg80211_bss_select_adjust { · 1677 unmodified lines
16781678 * @rcu_head: RCU callback used to free the struct
16791679 * @owner_nlportid: netlink portid of owner (if this should is a request
16801680 * owned by a particular socket)
1681+ * @nl_owner_dead: netlink owner socket was closed - this request be freed
1682+ * @list: for keeping list of requests.
16811683 * @delay: delay in seconds to use before starting the first scan
16821684 * cycle. The driver may ignore this parameter and start
16831685 * immediately (or at any other time), if this feature is not
@@ -1722,6 +1724,8 @@ struct cfg80211_sched_scan_request { · 38 unmodified lines
17221724 unsigned long scan_start;
17231725 struct rcu_head rcu_head;
17241726 u32 owner_nlportid;
1727+ bool nl_owner_dead;
1728+ struct list_head list;
17251729
17261730 /* keep last */
17271731 struct ieee80211_channel *channels[0];
@@ -3213,7 +3217,7 @@ enum wiphy_flags { · 1485 unmodified lines
32133217 WIPHY_FLAG_CONTROL_PORT_PROTOCOL = BIT(7),
32143218 WIPHY_FLAG_IBSS_RSN = BIT(8),
32153219 WIPHY_FLAG_MESH_AUTH = BIT(10),
3216− WIPHY_FLAG_SUPPORTS_SCHED_SCAN = BIT(11),
3220+ /* use hole at 11 */
32173221 /* use hole at 12 */
32183222 WIPHY_FLAG_SUPPORTS_FW_ROAM = BIT(13),
32193223 WIPHY_FLAG_AP_UAPSD = BIT(14),
@@ -3551,6 +3555,8 @@ struct wiphy_iftype_ext_capab { · 331 unmodified lines
35513555 * this variable determines its size
35523556 * @max_scan_ssids: maximum number of SSIDs the device can scan for in
35533557 * any given scan
3558+ * @max_sched_scan_reqs: maximum number of scheduled scan requests that
3559+ * the device can run concurrently.
35543560 * @max_sched_scan_ssids: maximum number of SSIDs the device can scan
35553561 * for in any given scheduled scan
35563562 * @max_match_sets: maximum number of match sets the device can handle
@@ -3687,6 +3693,7 @@ struct wiphy { · 130 unmodified lines
36873693
36883694 int bss_priv_size;
36893695 u8 max_scan_ssids;
3696+ u8 max_sched_scan_reqs;
36903697 u8 max_sched_scan_ssids;
36913698 u8 max_match_sets;
36923699 u16 max_scan_ie_len;
include/uapi/linux/nl80211.h+11−1
@@ -387,7 +387,9 @@ · 386 unmodified lines
387387 * are used. Extra IEs can also be passed from the userspace by
388388 * using the %NL80211_ATTR_IE attribute. The first cycle of the
389389 * scheduled scan can be delayed by %NL80211_ATTR_SCHED_SCAN_DELAY
390− * is supplied.
390+ * is supplied. If the device supports multiple concurrent scheduled
391+ * scans, it will allow such when the caller provides the flag attribute
392+ * %NL80211_ATTR_SCHED_SCAN_MULTI to indicate user-space support for it.
391393 * @NL80211_CMD_STOP_SCHED_SCAN: stop a scheduled scan. Returns -ENOENT if
392394 * scheduled scan is not running. The caller may assume that as soon
393395 * as the call returns, it is safe to start a new scheduled scan again.
@@ -2081,6 +2083,11 @@ enum nl80211_commands { · 1687 unmodified lines
20812083 * @NL80211_ATTR_PMK: PMK for the PMKSA identified by %NL80211_ATTR_PMKID.
20822084 * This is used with @NL80211_CMD_SET_PMKSA.
20832085 *
2086+ * @NL80211_ATTR_SCHED_SCAN_MULTI: flag attribute which user-space shall use to
2087+ * indicate that it supports multiple active scheduled scan requests.
2088+ * @NL80211_ATTR_SCHED_SCAN_MAX_REQS: indicates maximum number of scheduled
2089+ * scan request that may be active for the device (u32).
2090+ *
20842091 * @NUM_NL80211_ATTR: total number of nl80211_attrs available
20852092 * @NL80211_ATTR_MAX: highest attribute number currently defined
20862093 * @__NL80211_ATTR_AFTER_LAST: internal use
@@ -2500,6 +2507,9 @@ enum nl80211_attrs { · 413 unmodified lines
25002507
25012508 NL80211_ATTR_PMK,
25022509
2510+ NL80211_ATTR_SCHED_SCAN_MULTI,
2511+ NL80211_ATTR_SCHED_SCAN_MAX_REQS,
2512+
25032513 /* add attributes here, update the policy in nl80211.c */
25042514
25052515 __NL80211_ATTR_AFTER_LAST,
net/wireless/core.c+17−12
@@ -330,14 +330,16 @@ static void cfg80211_destroy_iface_wk(struct work_struct *work) · 329 unmodified lines
330330 static void cfg80211_sched_scan_stop_wk(struct work_struct *work)
331331 {
332332 struct cfg80211_registered_device *rdev;
333+ struct cfg80211_sched_scan_request *req, *tmp;
333334
334335 rdev = container_of(work, struct cfg80211_registered_device,
335336 sched_scan_stop_wk);
336337
337338 rtnl_lock();
338−
339− __cfg80211_stop_sched_scan(rdev, false);
340−
339+ list_for_each_entry_safe(req, tmp, &rdev->sched_scan_req_list, list) {
340+ if (req->nl_owner_dead)
341+ cfg80211_stop_sched_scan_req(rdev, req, false);
342+ }
341343 rtnl_unlock();
342344 }
343345
@@ -452,6 +454,7 @@ use_default_name: · 108 unmodified lines
452454 spin_lock_init(&rdev->beacon_registrations_lock);
453455 spin_lock_init(&rdev->bss_lock);
454456 INIT_LIST_HEAD(&rdev->bss_list);
457+ INIT_LIST_HEAD(&rdev->sched_scan_req_list);
455458 INIT_WORK(&rdev->scan_done_wk, __cfg80211_scan_done);
456459 INIT_WORK(&rdev->sched_scan_results_wk, __cfg80211_sched_scan_results);
457460 INIT_LIST_HEAD(&rdev->mlme_unreg);
@@ -1028,7 +1031,7 @@ void __cfg80211_leave(struct cfg80211_registered_device *rdev, · 570 unmodified lines
10281031 struct wireless_dev *wdev)
10291032 {
10301033 struct net_device *dev = wdev->netdev;
1031− struct cfg80211_sched_scan_request *sched_scan_req;
1034+ struct cfg80211_sched_scan_request *pos, *tmp;
10321035
10331036 ASSERT_RTNL();
10341037 ASSERT_WDEV_LOCK(wdev);
@@ -1039,9 +1042,11 @@ void __cfg80211_leave(struct cfg80211_registered_device *rdev, · 4 unmodified lines
10391042 break;
10401043 case NL80211_IFTYPE_P2P_CLIENT:
10411044 case NL80211_IFTYPE_STATION:
1042− sched_scan_req = rtnl_dereference(rdev->sched_scan_req);
1043− if (sched_scan_req && dev == sched_scan_req->dev)
1044− __cfg80211_stop_sched_scan(rdev, false);
1045+ list_for_each_entry_safe(pos, tmp, &rdev->sched_scan_req_list,
1046+ list) {
1047+ if (dev == pos->dev)
1048+ cfg80211_stop_sched_scan_req(rdev, pos, false);
1049+ }
10451050
10461051 #ifdef CONFIG_CFG80211_WEXT
10471052 kfree(wdev->wext.ie);
@@ -1116,7 +1121,7 @@ static int cfg80211_netdev_notifier_call(struct notifier_block *nb, · 68 unmodified lines
11161121 struct net_device *dev = netdev_notifier_info_to_dev(ptr);
11171122 struct wireless_dev *wdev = dev->ieee80211_ptr;
11181123 struct cfg80211_registered_device *rdev;
1119− struct cfg80211_sched_scan_request *sched_scan_req;
1124+ struct cfg80211_sched_scan_request *pos, *tmp;
11201125
11211126 if (!wdev)
11221127 return NOTIFY_DONE;
@@ -1193,10 +1198,10 @@ static int cfg80211_netdev_notifier_call(struct notifier_block *nb, · 70 unmodified lines
11931198 ___cfg80211_scan_done(rdev, false);
11941199 }
11951200
1196− sched_scan_req = rtnl_dereference(rdev->sched_scan_req);
1197− if (WARN_ON(sched_scan_req &&
1198− sched_scan_req->dev == wdev->netdev)) {
1199− __cfg80211_stop_sched_scan(rdev, false);
1201+ list_for_each_entry_safe(pos, tmp,
1202+ &rdev->sched_scan_req_list, list) {
1203+ if (WARN_ON(pos && pos->dev == wdev->netdev))
1204+ cfg80211_stop_sched_scan_req(rdev, pos, false);
12001205 }
12011206
12021207 rdev->opencount--;
net/wireless/core.h+9−2
@@ -74,7 +74,7 @@ struct cfg80211_registered_device { · 73 unmodified lines
7474 u32 bss_entries;
7575 struct cfg80211_scan_request *scan_req; /* protected by RTNL */
7676 struct sk_buff *scan_msg;
77− struct cfg80211_sched_scan_request __rcu *sched_scan_req;
77+ struct list_head sched_scan_req_list;
7878 unsigned long suspend_at;
7979 struct work_struct scan_done_wk;
8080 struct work_struct sched_scan_results_wk;
@@ -416,9 +416,16 @@ int cfg80211_validate_key_settings(struct cfg80211_registered_device *rdev, · 335 unmodified lines
416416 void __cfg80211_scan_done(struct work_struct *wk);
417417 void ___cfg80211_scan_done(struct cfg80211_registered_device *rdev,
418418 bool send_message);
419+void cfg80211_add_sched_scan_req(struct cfg80211_registered_device *rdev,
420+ struct cfg80211_sched_scan_request *req);
421+int cfg80211_sched_scan_req_possible(struct cfg80211_registered_device *rdev,
422+ bool want_multi);
419423 void __cfg80211_sched_scan_results(struct work_struct *wk);
424+int cfg80211_stop_sched_scan_req(struct cfg80211_registered_device *rdev,
425+ struct cfg80211_sched_scan_request *req,
426+ bool driver_initiated);
420427 int __cfg80211_stop_sched_scan(struct cfg80211_registered_device *rdev,
421− bool driver_initiated);
428+ u64 reqid, bool driver_initiated);
422429 void cfg80211_upload_connect_keys(struct wireless_dev *wdev);
423430 int cfg80211_change_iface(struct cfg80211_registered_device *rdev,
424431 struct net_device *dev, enum nl80211_iftype ntype,
net/wireless/nl80211.c+46−17
@@ -419,6 +419,7 @@ static const struct nla_policy nl80211_policy[NUM_NL80211_ATTR] = { · 418 unmodified lines
419419 .len = FILS_ERP_MAX_RRK_LEN },
420420 [NL80211_ATTR_FILS_CACHE_ID] = { .len = 2 },
421421 [NL80211_ATTR_PMK] = { .type = NLA_BINARY, .len = PMK_MAX_LEN },
422+ [NL80211_ATTR_SCHED_SCAN_MULTI] = { .type = NLA_FLAG },
422423 };
423424
424425 /* policy for the key attributes */
@@ -1376,7 +1377,7 @@ static int nl80211_add_commands_unsplit(struct cfg80211_registered_device *rdev, · 951 unmodified lines
13761377 CMD(tdls_mgmt, TDLS_MGMT);
13771378 CMD(tdls_oper, TDLS_OPER);
13781379 }
1379− if (rdev->wiphy.flags & WIPHY_FLAG_SUPPORTS_SCHED_SCAN)
1380+ if (rdev->wiphy.max_sched_scan_reqs)
13801381 CMD(sched_scan_start, START_SCHED_SCAN);
13811382 CMD(probe_client, PROBE_CLIENT);
13821383 CMD(set_noack_map, SET_NOACK_MAP);
@@ -1815,6 +1816,11 @@ static int nl80211_send_wiphy(struct cfg80211_registered_device *rdev, · 432 unmodified lines
18151816 nla_put_flag(msg, NL80211_ATTR_WIPHY_SELF_MANAGED_REG))
18161817 goto nla_put_failure;
18171818
1819+ if (rdev->wiphy.max_sched_scan_reqs &&
1820+ nla_put_u32(msg, NL80211_ATTR_SCHED_SCAN_MAX_REQS,
1821+ rdev->wiphy.max_sched_scan_reqs))
1822+ goto nla_put_failure;
1823+
18181824 if (nla_put(msg, NL80211_ATTR_EXT_FEATURES,
18191825 sizeof(rdev->wiphy.ext_features),
18201826 rdev->wiphy.ext_features))
@@ -7336,14 +7342,16 @@ static int nl80211_start_sched_scan(struct sk_buff *skb, · 5515 unmodified lines
73367342 struct net_device *dev = info->user_ptr[1];
73377343 struct wireless_dev *wdev = dev->ieee80211_ptr;
73387344 struct cfg80211_sched_scan_request *sched_scan_req;
7345+ bool want_multi;
73397346 int err;
73407347
7341− if (!(rdev->wiphy.flags & WIPHY_FLAG_SUPPORTS_SCHED_SCAN) ||
7342− !rdev->ops->sched_scan_start)
7348+ if (!rdev->wiphy.max_sched_scan_reqs || !rdev->ops->sched_scan_start)
73437349 return -EOPNOTSUPP;
73447350
7345− if (rdev->sched_scan_req)
7346− return -EINPROGRESS;
7351+ want_multi = info->attrs[NL80211_ATTR_SCHED_SCAN_MULTI];
7352+ err = cfg80211_sched_scan_req_possible(rdev, want_multi);
7353+ if (err)
7354+ return err;
73477355
73487356 sched_scan_req = nl80211_parse_sched_scan(&rdev->wiphy, wdev,
73497357 info->attrs,
@@ -7353,6 +7361,14 @@ static int nl80211_start_sched_scan(struct sk_buff *skb, · 3 unmodified lines
73537361 if (err)
73547362 goto out_err;
73557363
7364+ /* leave request id zero for legacy request
7365+ * or if driver does not support multi-scheduled scan
7366+ */
7367+ if (want_multi && rdev->wiphy.max_sched_scan_reqs > 1) {
7368+ while (!sched_scan_req->reqid)
7369+ sched_scan_req->reqid = rdev->wiphy.cookie_counter++;
7370+ }
7371+
73567372 err = rdev_sched_scan_start(rdev, dev, sched_scan_req);
73577373 if (err)
73587374 goto out_free;
@@ -7363,7 +7379,7 @@ static int nl80211_start_sched_scan(struct sk_buff *skb, · 4 unmodified lines
73637379 if (info->attrs[NL80211_ATTR_SOCKET_OWNER])
73647380 sched_scan_req->owner_nlportid = info->snd_portid;
73657381
7366− rcu_assign_pointer(rdev->sched_scan_req, sched_scan_req);
7382+ cfg80211_add_sched_scan_req(rdev, sched_scan_req);
73677383
73687384 nl80211_send_sched_scan(sched_scan_req, NL80211_CMD_START_SCHED_SCAN);
73697385 return 0;
@@ -7377,13 +7393,27 @@ out_err: · 7 unmodified lines
73777393 static int nl80211_stop_sched_scan(struct sk_buff *skb,
73787394 struct genl_info *info)
73797395 {
7396+ struct cfg80211_sched_scan_request *req;
73807397 struct cfg80211_registered_device *rdev = info->user_ptr[0];
7398+ u64 cookie;
73817399
7382− if (!(rdev->wiphy.flags & WIPHY_FLAG_SUPPORTS_SCHED_SCAN) ||
7383− !rdev->ops->sched_scan_stop)
7400+ if (!rdev->wiphy.max_sched_scan_reqs || !rdev->ops->sched_scan_stop)
73847401 return -EOPNOTSUPP;
73857402
7386− return __cfg80211_stop_sched_scan(rdev, false);
7403+ if (info->attrs[NL80211_ATTR_COOKIE]) {
7404+ cookie = nla_get_u64(info->attrs[NL80211_ATTR_COOKIE]);
7405+ return __cfg80211_stop_sched_scan(rdev, cookie, false);
7406+ }
7407+
7408+ req = list_first_or_null_rcu(&rdev->sched_scan_req_list,
7409+ struct cfg80211_sched_scan_request,
7410+ list);
7411+ if (!req || req->reqid ||
7412+ (req->owner_nlportid &&
7413+ req->owner_nlportid != info->snd_portid))
7414+ return -ENOENT;
7415+
7416+ return cfg80211_stop_sched_scan_req(rdev, req, false);
73877417 }
73887418
73897419 static int nl80211_start_radar_detection(struct sk_buff *skb,
@@ -14883,16 +14913,15 @@ static int nl80211_netlink_notify(struct notifier_block * nb, · 7493 unmodified lines
1488314913 rcu_read_lock();
1488414914
1488514915 list_for_each_entry_rcu(rdev, &cfg80211_rdev_list, list) {
14886− struct cfg80211_sched_scan_request *sched_scan_req =
14887− rcu_dereference(rdev->sched_scan_req);
14888−
14889− if (sched_scan_req && notify->portid &&
14890− sched_scan_req->owner_nlportid == notify->portid) {
14891− sched_scan_req->owner_nlportid = 0;
14916+ struct cfg80211_sched_scan_request *sched_scan_req;
1489214917
14893− if (rdev->ops->sched_scan_stop &&
14894− rdev->wiphy.flags & WIPHY_FLAG_SUPPORTS_SCHED_SCAN)
14918+ list_for_each_entry_rcu(sched_scan_req,
14919+ &rdev->sched_scan_req_list,
14920+ list) {
14921+ if (sched_scan_req->owner_nlportid == notify->portid) {
14922+ sched_scan_req->nl_owner_dead = true;
1489514923 schedule_work(&rdev->sched_scan_stop_wk);
14924+ }
1489614925 }
1489714926
1489814927 list_for_each_entry_rcu(wdev, &rdev->wiphy.wdev_list, list) {
net/wireless/rdev-ops.h+1−1
@@ -813,7 +813,7 @@ rdev_sched_scan_start(struct cfg80211_registered_device *rdev, · 812 unmodified lines
813813 struct cfg80211_sched_scan_request *request)
814814 {
815815 int ret;
816− trace_rdev_sched_scan_start(&rdev->wiphy, dev, request);
816+ trace_rdev_sched_scan_start(&rdev->wiphy, dev, request->reqid);
817817 ret = rdev->ops->sched_scan_start(&rdev->wiphy, dev, request);
818818 trace_rdev_return_int(&rdev->wiphy, ret);
819819 return ret;
net/wireless/scan.c+96−19
@@ -300,6 +300,70 @@ void cfg80211_scan_done(struct cfg80211_scan_request *request, · 299 unmodified lines
300300 }
301301 EXPORT_SYMBOL(cfg80211_scan_done);
302302
303+void cfg80211_add_sched_scan_req(struct cfg80211_registered_device *rdev,
304+ struct cfg80211_sched_scan_request *req)
305+{
306+ ASSERT_RTNL();
307+
308+ list_add_rcu(&req->list, &rdev->sched_scan_req_list);
309+}
310+
311+static void cfg80211_del_sched_scan_req(struct cfg80211_registered_device *rdev,
312+ struct cfg80211_sched_scan_request *req)
313+{
314+ ASSERT_RTNL();
315+
316+ list_del_rcu(&req->list);
317+ kfree_rcu(req, rcu_head);
318+}
319+
320+static struct cfg80211_sched_scan_request *
321+cfg80211_find_sched_scan_req(struct cfg80211_registered_device *rdev, u64 reqid)
322+{
323+ struct cfg80211_sched_scan_request *pos;
324+
325+ ASSERT_RTNL();
326+
327+ list_for_each_entry(pos, &rdev->sched_scan_req_list, list) {
328+ if (pos->reqid == reqid)
329+ return pos;
330+ }
331+ return ERR_PTR(-ENOENT);
332+}
333+
334+/*
335+ * Determines if a scheduled scan request can be handled. When a legacy
336+ * scheduled scan is running no other scheduled scan is allowed regardless
337+ * whether the request is for legacy or multi-support scan. When a multi-support
338+ * scheduled scan is running a request for legacy scan is not allowed. In this
339+ * case a request for multi-support scan can be handled if resources are
340+ * available, ie. struct wiphy::max_sched_scan_reqs limit is not yet reached.
341+ */
342+int cfg80211_sched_scan_req_possible(struct cfg80211_registered_device *rdev,
343+ bool want_multi)
344+{
345+ struct cfg80211_sched_scan_request *pos;
346+ int i = 0;
347+
348+ list_for_each_entry(pos, &rdev->sched_scan_req_list, list) {
349+ /* request id zero means legacy in progress */
350+ if (!i && !pos->reqid)
351+ return -EINPROGRESS;
352+ i++;
353+ }
354+
355+ if (i) {
356+ /* no legacy allowed when multi request(s) are active */
357+ if (!want_multi)
358+ return -EINPROGRESS;
359+
360+ /* resource limit reached */
361+ if (i == rdev->wiphy.max_sched_scan_reqs)
362+ return -ENOSPC;
363+ }
364+ return 0;
365+}
366+
303367 void __cfg80211_sched_scan_results(struct work_struct *wk)
304368 {
305369 struct cfg80211_registered_device *rdev;
@@ -310,10 +374,10 @@ void __cfg80211_sched_scan_results(struct work_struct *wk) · 4 unmodified lines
310374
311375 rtnl_lock();
312376
313− request = rtnl_dereference(rdev->sched_scan_req);
377+ request = cfg80211_find_sched_scan_req(rdev, 0);
314378
315379 /* we don't have sched_scan_req anymore if the scan is stopping */
316− if (request) {
380+ if (!IS_ERR(request)) {
317381 if (request->flags & NL80211_SCAN_FLAG_FLUSH) {
318382 /* flush entries from previous scans */
319383 spin_lock_bh(&rdev->bss_lock);
@@ -329,10 +393,17 @@ void __cfg80211_sched_scan_results(struct work_struct *wk) · 9 unmodified lines
329393
330394 void cfg80211_sched_scan_results(struct wiphy *wiphy)
331395 {
396+ struct cfg80211_registered_device *rdev = wiphy_to_rdev(wiphy);
397+ struct cfg80211_sched_scan_request *request;
398+
332399 trace_cfg80211_sched_scan_results(wiphy);
333400 /* ignore if we're not scanning */
334401
335− if (rcu_access_pointer(wiphy_to_rdev(wiphy)->sched_scan_req))
402+ rtnl_lock();
403+ request = cfg80211_find_sched_scan_req(rdev, 0);
404+ rtnl_unlock();
405+
406+ if (!IS_ERR(request))
336407 queue_work(cfg80211_wq,
337408 &wiphy_to_rdev(wiphy)->sched_scan_results_wk);
338409 }
@@ -346,7 +417,7 @@ void cfg80211_sched_scan_stopped_rtnl(struct wiphy *wiphy) · 7 unmodified lines
346417
347418 trace_cfg80211_sched_scan_stopped(wiphy);
348419
349− __cfg80211_stop_sched_scan(rdev, true);
420+ __cfg80211_stop_sched_scan(rdev, 0, true);
350421 }
351422 EXPORT_SYMBOL(cfg80211_sched_scan_stopped_rtnl);
352423
@@ -358,34 +429,40 @@ void cfg80211_sched_scan_stopped(struct wiphy *wiphy) · 5 unmodified lines
358429 }
359430 EXPORT_SYMBOL(cfg80211_sched_scan_stopped);
360431
361−int __cfg80211_stop_sched_scan(struct cfg80211_registered_device *rdev,
362− bool driver_initiated)
432+int cfg80211_stop_sched_scan_req(struct cfg80211_registered_device *rdev,
433+ struct cfg80211_sched_scan_request *req,
434+ bool driver_initiated)
363435 {
364− struct cfg80211_sched_scan_request *sched_scan_req;
365− struct net_device *dev;
366−
367436 ASSERT_RTNL();
368437
369− if (!rdev->sched_scan_req)
370− return -ENOENT;
371−
372− sched_scan_req = rtnl_dereference(rdev->sched_scan_req);
373− dev = sched_scan_req->dev;
374−
375438 if (!driver_initiated) {
376− int err = rdev_sched_scan_stop(rdev, dev);
439+ int err = rdev_sched_scan_stop(rdev, req->dev);
377440 if (err)
378441 return err;
379442 }
380443
381− nl80211_send_sched_scan(sched_scan_req, NL80211_CMD_SCHED_SCAN_STOPPED);
444+ nl80211_send_sched_scan(req, NL80211_CMD_SCHED_SCAN_STOPPED);
382445
383− RCU_INIT_POINTER(rdev->sched_scan_req, NULL);
384− kfree_rcu(sched_scan_req, rcu_head);
446+ cfg80211_del_sched_scan_req(rdev, req);
385447
386448 return 0;
387449 }
388450
451+int __cfg80211_stop_sched_scan(struct cfg80211_registered_device *rdev,
452+ u64 reqid, bool driver_initiated)
453+{
454+ struct cfg80211_sched_scan_request *sched_scan_req;
455+
456+ ASSERT_RTNL();
457+
458+ sched_scan_req = cfg80211_find_sched_scan_req(rdev, reqid);
459+ if (IS_ERR(sched_scan_req))
460+ return PTR_ERR(sched_scan_req);
461+
462+ return cfg80211_stop_sched_scan_req(rdev, sched_scan_req,
463+ driver_initiated);
464+}
465+
389466 void cfg80211_bss_age(struct cfg80211_registered_device *rdev,
390467 unsigned long age_secs)
391468 {
net/wireless/trace.h+12−6
@@ -1610,20 +1610,26 @@ DEFINE_EVENT(tx_rx_evt, rdev_set_antenna, · 1609 unmodified lines
16101610 TP_ARGS(wiphy, rx, tx)
16111611 );
16121612
1613−TRACE_EVENT(rdev_sched_scan_start,
1614− TP_PROTO(struct wiphy *wiphy, struct net_device *netdev,
1615− struct cfg80211_sched_scan_request *request),
1616− TP_ARGS(wiphy, netdev, request),
1613+DECLARE_EVENT_CLASS(wiphy_netdev_id_evt,
1614+ TP_PROTO(struct wiphy *wiphy, struct net_device *netdev, u64 id),
1615+ TP_ARGS(wiphy, netdev, id),
16171616 TP_STRUCT__entry(
16181617 WIPHY_ENTRY
16191618 NETDEV_ENTRY
1619+ __field(u64, id)
16201620 ),
16211621 TP_fast_assign(
16221622 WIPHY_ASSIGN;
16231623 NETDEV_ASSIGN;
1624+ __entry->id = id;
16241625 ),
1625− TP_printk(WIPHY_PR_FMT ", " NETDEV_PR_FMT,
1626− WIPHY_PR_ARG, NETDEV_PR_ARG)
1626+ TP_printk(WIPHY_PR_FMT ", " NETDEV_PR_FMT ", id: %llu",
1627+ WIPHY_PR_ARG, NETDEV_PR_ARG, __entry->id)
1628+);
1629+
1630+DEFINE_EVENT(wiphy_netdev_id_evt, rdev_sched_scan_start,
1631+ TP_PROTO(struct wiphy *wiphy, struct net_device *netdev, u64 id),
1632+ TP_ARGS(wiphy, netdev, id)
16271633 );
16281634
16291635 TRACE_EVENT(rdev_tdls_mgmt,

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t