863a06b0a4
Signed-off-by: Rafał Miłecki <rafal@milecki.pl>
221 lines
6.6 KiB
Diff
221 lines
6.6 KiB
Diff
From 3e2e86ab19c2a43953de30089c5411c580ddb5f7 Mon Sep 17 00:00:00 2001
|
|
From: Arend Van Spriel <arend.vanspriel@broadcom.com>
|
|
Date: Wed, 23 Nov 2016 10:25:23 +0000
|
|
Subject: [PATCH] brcmfmac: fix handling ssids in .sched_scan_start() callback
|
|
|
|
The ssids list in the scheduled scan request were not properly taken
|
|
into account when configuring in firmware. The hidden bit was set for
|
|
any ssid resulting in active scanning for all. Only set it for ssids
|
|
that are in the ssids list.
|
|
|
|
Reviewed-by: Hante Meuleman <hante.meuleman@broadcom.com>
|
|
Reviewed-by: Pieter-Paul Giesberts <pieter-paul.giesberts@broadcom.com>
|
|
Reviewed-by: Franky Lin <franky.lin@broadcom.com>
|
|
Signed-off-by: Arend van Spriel <arend.vanspriel@broadcom.com>
|
|
Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
|
|
---
|
|
.../broadcom/brcm80211/brcmfmac/cfg80211.c | 103 ++++++++++-----------
|
|
.../net/wireless/broadcom/brcm80211/brcmfmac/pno.c | 18 ++++
|
|
.../net/wireless/broadcom/brcm80211/brcmfmac/pno.h | 12 ++-
|
|
3 files changed, 76 insertions(+), 57 deletions(-)
|
|
|
|
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c
|
|
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c
|
|
@@ -3314,19 +3314,37 @@ out_err:
|
|
return err;
|
|
}
|
|
|
|
+static bool brcmf_is_ssid_active(struct cfg80211_ssid *ssid,
|
|
+ struct cfg80211_sched_scan_request *req)
|
|
+{
|
|
+ int i;
|
|
+
|
|
+ if (!ssid || !req->ssids || !req->n_ssids)
|
|
+ return false;
|
|
+
|
|
+ for (i = 0; i < req->n_ssids; i++) {
|
|
+ if (ssid->ssid_len == req->ssids[i].ssid_len) {
|
|
+ if (!strncmp(ssid->ssid, req->ssids[i].ssid,
|
|
+ ssid->ssid_len))
|
|
+ return true;
|
|
+ }
|
|
+ }
|
|
+ return false;
|
|
+}
|
|
+
|
|
static int
|
|
brcmf_cfg80211_sched_scan_start(struct wiphy *wiphy,
|
|
struct net_device *ndev,
|
|
- struct cfg80211_sched_scan_request *request)
|
|
+ struct cfg80211_sched_scan_request *req)
|
|
{
|
|
struct brcmf_if *ifp = netdev_priv(ndev);
|
|
struct brcmf_cfg80211_info *cfg = wiphy_priv(wiphy);
|
|
- struct brcmf_pno_net_param_le pfn;
|
|
+ struct cfg80211_ssid *ssid;
|
|
int i;
|
|
int ret = 0;
|
|
|
|
brcmf_dbg(SCAN, "Enter n_match_sets:%d n_ssids:%d\n",
|
|
- request->n_match_sets, request->n_ssids);
|
|
+ req->n_match_sets, req->n_ssids);
|
|
if (test_bit(BRCMF_SCAN_STATUS_BUSY, &cfg->scan_status)) {
|
|
brcmf_err("Scanning already: status (%lu)\n", cfg->scan_status);
|
|
return -EAGAIN;
|
|
@@ -3337,71 +3355,46 @@ brcmf_cfg80211_sched_scan_start(struct w
|
|
return -EAGAIN;
|
|
}
|
|
|
|
- if (!request->n_ssids || !request->n_match_sets) {
|
|
- brcmf_dbg(SCAN, "Invalid sched scan req!! n_ssids:%d\n",
|
|
- request->n_ssids);
|
|
+ if (req->n_match_sets <= 0) {
|
|
+ brcmf_dbg(SCAN, "invalid number of matchsets specified: %d\n",
|
|
+ req->n_match_sets);
|
|
return -EINVAL;
|
|
}
|
|
|
|
- if (request->n_ssids > 0) {
|
|
- for (i = 0; i < request->n_ssids; i++) {
|
|
- /* Active scan req for ssids */
|
|
- brcmf_dbg(SCAN, ">>> Active scan req for ssid (%s)\n",
|
|
- request->ssids[i].ssid);
|
|
-
|
|
- /* match_set ssids is a supert set of n_ssid list,
|
|
- * so we need not add these set separately.
|
|
- */
|
|
- }
|
|
+ /* clean up everything */
|
|
+ ret = brcmf_pno_clean(ifp);
|
|
+ if (ret < 0) {
|
|
+ brcmf_err("failed error=%d\n", ret);
|
|
+ return ret;
|
|
}
|
|
|
|
- if (request->n_match_sets > 0) {
|
|
- /* clean up everything */
|
|
- ret = brcmf_pno_clean(ifp);
|
|
- if (ret < 0) {
|
|
- brcmf_err("failed error=%d\n", ret);
|
|
- return ret;
|
|
+ /* configure pno */
|
|
+ ret = brcmf_pno_config(ifp, req);
|
|
+ if (ret < 0)
|
|
+ return ret;
|
|
+
|
|
+ /* configure each match set */
|
|
+ for (i = 0; i < req->n_match_sets; i++) {
|
|
+
|
|
+ ssid = &req->match_sets[i].ssid;
|
|
+
|
|
+ if (!ssid->ssid_len) {
|
|
+ brcmf_err("skip broadcast ssid\n");
|
|
+ continue;
|
|
}
|
|
|
|
- /* configure pno */
|
|
- ret = brcmf_pno_config(ifp, request);
|
|
+ ret = brcmf_pno_add_ssid(ifp, ssid,
|
|
+ brcmf_is_ssid_active(ssid, req));
|
|
if (ret < 0)
|
|
- return ret;
|
|
-
|
|
- /* configure each match set */
|
|
- for (i = 0; i < request->n_match_sets; i++) {
|
|
- struct cfg80211_ssid *ssid;
|
|
- u32 ssid_len;
|
|
-
|
|
- ssid = &request->match_sets[i].ssid;
|
|
- ssid_len = ssid->ssid_len;
|
|
-
|
|
- if (!ssid_len) {
|
|
- brcmf_err("skip broadcast ssid\n");
|
|
- continue;
|
|
- }
|
|
- pfn.auth = cpu_to_le32(WLAN_AUTH_OPEN);
|
|
- pfn.wpa_auth = cpu_to_le32(BRCMF_PNO_WPA_AUTH_ANY);
|
|
- pfn.wsec = cpu_to_le32(0);
|
|
- pfn.infra = cpu_to_le32(1);
|
|
- pfn.flags = cpu_to_le32(1 << BRCMF_PNO_HIDDEN_BIT);
|
|
- pfn.ssid.SSID_len = cpu_to_le32(ssid_len);
|
|
- memcpy(pfn.ssid.SSID, ssid->ssid, ssid_len);
|
|
- ret = brcmf_fil_iovar_data_set(ifp, "pfn_add", &pfn,
|
|
- sizeof(pfn));
|
|
brcmf_dbg(SCAN, ">>> PNO filter %s for ssid (%s)\n",
|
|
ret == 0 ? "set" : "failed", ssid->ssid);
|
|
- }
|
|
- /* Enable the PNO */
|
|
- if (brcmf_fil_iovar_int_set(ifp, "pfn", 1) < 0) {
|
|
- brcmf_err("PNO enable failed!! ret=%d\n", ret);
|
|
- return -EINVAL;
|
|
- }
|
|
- } else {
|
|
- return -EINVAL;
|
|
}
|
|
+ /* Enable the PNO */
|
|
+ ret = brcmf_fil_iovar_int_set(ifp, "pfn", 1);
|
|
+ if (ret < 0)
|
|
+ brcmf_err("PNO enable failed!! ret=%d\n", ret);
|
|
|
|
- return 0;
|
|
+ return ret;
|
|
}
|
|
|
|
static int brcmf_cfg80211_sched_scan_stop(struct wiphy *wiphy,
|
|
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pno.c
|
|
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pno.c
|
|
@@ -28,6 +28,8 @@
|
|
#define BRCMF_PNO_FREQ_EXPO_MAX 3
|
|
#define BRCMF_PNO_ENABLE_ADAPTSCAN_BIT 6
|
|
#define BRCMF_PNO_SCAN_INCOMPLETE 0
|
|
+#define BRCMF_PNO_WPA_AUTH_ANY 0xFFFFFFFF
|
|
+#define BRCMF_PNO_HIDDEN_BIT 2
|
|
|
|
int brcmf_pno_clean(struct brcmf_if *ifp)
|
|
{
|
|
@@ -98,3 +100,19 @@ int brcmf_pno_config(struct brcmf_if *if
|
|
return err;
|
|
}
|
|
|
|
+int brcmf_pno_add_ssid(struct brcmf_if *ifp, struct cfg80211_ssid *ssid,
|
|
+ bool active)
|
|
+{
|
|
+ struct brcmf_pno_net_param_le pfn;
|
|
+
|
|
+ pfn.auth = cpu_to_le32(WLAN_AUTH_OPEN);
|
|
+ pfn.wpa_auth = cpu_to_le32(BRCMF_PNO_WPA_AUTH_ANY);
|
|
+ pfn.wsec = cpu_to_le32(0);
|
|
+ pfn.infra = cpu_to_le32(1);
|
|
+ if (active)
|
|
+ pfn.flags = cpu_to_le32(1 << BRCMF_PNO_HIDDEN_BIT);
|
|
+ pfn.ssid.SSID_len = cpu_to_le32(ssid->ssid_len);
|
|
+ memcpy(pfn.ssid.SSID, ssid->ssid, ssid->ssid_len);
|
|
+ return brcmf_fil_iovar_data_set(ifp, "pfn_add", &pfn, sizeof(pfn));
|
|
+}
|
|
+
|
|
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pno.h
|
|
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pno.h
|
|
@@ -17,8 +17,6 @@
|
|
#define _BRCMF_PNO_H
|
|
|
|
#define BRCMF_PNO_SCAN_COMPLETE 1
|
|
-#define BRCMF_PNO_WPA_AUTH_ANY 0xFFFFFFFF
|
|
-#define BRCMF_PNO_HIDDEN_BIT 2
|
|
#define BRCMF_PNO_MAX_PFN_COUNT 16
|
|
|
|
/**
|
|
@@ -37,4 +35,14 @@ int brcmf_pno_clean(struct brcmf_if *ifp
|
|
int brcmf_pno_config(struct brcmf_if *ifp,
|
|
struct cfg80211_sched_scan_request *request);
|
|
|
|
+/**
|
|
+ * brcmf_pno_add_ssid - add ssid for pno in firmware.
|
|
+ *
|
|
+ * @ifp: interface object used.
|
|
+ * @ssid: ssid information.
|
|
+ * @active: indicate this ssid needs to be actively probed.
|
|
+ */
|
|
+int brcmf_pno_add_ssid(struct brcmf_if *ifp, struct cfg80211_ssid *ssid,
|
|
+ bool active);
|
|
+
|
|
#endif /* _BRCMF_PNO_H */
|