From ac55136f43d3336c7b40238b779c404008229929 Mon Sep 17 00:00:00 2001 From: Arend Van Spriel Date: Wed, 23 Nov 2016 10:25:22 +0000 Subject: brcmfmac: move pno helper functions in separate source file Introducing new source file for pno related functionality. Moving existing pno functions. Reviewed-by: Hante Meuleman Reviewed-by: Pieter-Paul Giesberts Reviewed-by: Franky Lin Signed-off-by: Arend van Spriel Signed-off-by: Kalle Valo --- .../broadcom/brcm80211/brcmfmac/cfg80211.c | 93 ++-------------------- 1 file changed, 8 insertions(+), 85 deletions(-) (limited to 'drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c') diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c index b3cdc522e389..e030ac4f04fb 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c @@ -32,6 +32,7 @@ #include "fwil_types.h" #include "p2p.h" #include "btcoex.h" +#include "pno.h" #include "cfg80211.h" #include "feature.h" #include "fwil.h" @@ -41,16 +42,6 @@ #include "common.h" #define BRCMF_SCAN_IE_LEN_MAX 2048 -#define BRCMF_PNO_VERSION 2 -#define BRCMF_PNO_TIME 30 -#define BRCMF_PNO_REPEAT 4 -#define BRCMF_PNO_FREQ_EXPO_MAX 3 -#define BRCMF_PNO_MAX_PFN_COUNT 16 -#define BRCMF_PNO_ENABLE_ADAPTSCAN_BIT 6 -#define BRCMF_PNO_HIDDEN_BIT 2 -#define BRCMF_PNO_WPA_AUTH_ANY 0xFFFFFFFF -#define BRCMF_PNO_SCAN_COMPLETE 1 -#define BRCMF_PNO_SCAN_INCOMPLETE 0 #define WPA_OUI "\x00\x50\xF2" /* WPA OUI */ #define WPA_OUI_TYPE 1 @@ -3323,76 +3314,6 @@ out_err: return err; } -static int brcmf_dev_pno_clean(struct net_device *ndev) -{ - int ret; - - /* Disable pfn */ - ret = brcmf_fil_iovar_int_set(netdev_priv(ndev), "pfn", 0); - if (ret == 0) { - /* clear pfn */ - ret = brcmf_fil_iovar_data_set(netdev_priv(ndev), "pfnclear", - NULL, 0); - } - if (ret < 0) - brcmf_err("failed code %d\n", ret); - - return ret; -} - -static int brcmf_dev_pno_config(struct brcmf_if *ifp, - struct cfg80211_sched_scan_request *request) -{ - struct brcmf_pno_param_le pfn_param; - struct brcmf_pno_macaddr_le pfn_mac; - s32 err; - u8 *mac_mask; - int i; - - memset(&pfn_param, 0, sizeof(pfn_param)); - pfn_param.version = cpu_to_le32(BRCMF_PNO_VERSION); - - /* set extra pno params */ - pfn_param.flags = cpu_to_le16(1 << BRCMF_PNO_ENABLE_ADAPTSCAN_BIT); - pfn_param.repeat = BRCMF_PNO_REPEAT; - pfn_param.exp = BRCMF_PNO_FREQ_EXPO_MAX; - - /* set up pno scan fr */ - pfn_param.scan_freq = cpu_to_le32(BRCMF_PNO_TIME); - - err = brcmf_fil_iovar_data_set(ifp, "pfn_set", &pfn_param, - sizeof(pfn_param)); - if (err) { - brcmf_err("pfn_set failed, err=%d\n", err); - return err; - } - - /* Find out if mac randomization should be turned on */ - if (!(request->flags & NL80211_SCAN_FLAG_RANDOM_ADDR)) - return 0; - - pfn_mac.version = BRCMF_PFN_MACADDR_CFG_VER; - pfn_mac.flags = BRCMF_PFN_MAC_OUI_ONLY | BRCMF_PFN_SET_MAC_UNASSOC; - - memcpy(pfn_mac.mac, request->mac_addr, ETH_ALEN); - mac_mask = request->mac_addr_mask; - for (i = 0; i < ETH_ALEN; i++) { - pfn_mac.mac[i] &= mac_mask[i]; - pfn_mac.mac[i] |= get_random_int() & ~(mac_mask[i]); - } - /* Clear multi bit */ - pfn_mac.mac[0] &= 0xFE; - /* Set locally administered */ - pfn_mac.mac[0] |= 0x02; - - err = brcmf_fil_iovar_data_set(ifp, "pfn_macaddr", &pfn_mac, - sizeof(pfn_mac)); - if (err) - brcmf_err("pfn_macaddr failed, err=%d\n", err); - - return err; -} - static int brcmf_cfg80211_sched_scan_start(struct wiphy *wiphy, struct net_device *ndev, @@ -3436,15 +3357,16 @@ brcmf_cfg80211_sched_scan_start(struct wiphy *wiphy, if (request->n_match_sets > 0) { /* clean up everything */ - ret = brcmf_dev_pno_clean(ndev); + ret = brcmf_pno_clean(ifp); if (ret < 0) { brcmf_err("failed error=%d\n", ret); return ret; } /* configure pno */ - if (brcmf_dev_pno_config(ifp, request)) - return -EINVAL; + ret = brcmf_pno_config(ifp, request); + if (ret < 0) + return ret; /* configure each match set */ for (i = 0; i < request->n_match_sets; i++) { @@ -3486,11 +3408,12 @@ static int brcmf_cfg80211_sched_scan_stop(struct wiphy *wiphy, struct net_device *ndev) { struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy); + struct brcmf_if *ifp = netdev_priv(ndev); brcmf_dbg(SCAN, "enter\n"); - brcmf_dev_pno_clean(ndev); + brcmf_pno_clean(ifp); if (cfg->sched_escan) - brcmf_notify_escan_complete(cfg, netdev_priv(ndev), true, true); + brcmf_notify_escan_complete(cfg, ifp, true, true); return 0; } -- cgit v1.2.3 From 3e2e86ab19c2a43953de30089c5411c580ddb5f7 Mon Sep 17 00:00:00 2001 From: Arend Van Spriel Date: Wed, 23 Nov 2016 10:25:23 +0000 Subject: 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 Reviewed-by: Pieter-Paul Giesberts Reviewed-by: Franky Lin Signed-off-by: Arend van Spriel Signed-off-by: Kalle Valo --- .../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(-) (limited to 'drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c') diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c index e030ac4f04fb..3d51e845588c 100644 --- 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 wiphy *wiphy, 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 pno */ - ret = brcmf_pno_config(ifp, request); - if (ret < 0) - return ret; + /* configure each match set */ + for (i = 0; i < req->n_match_sets; i++) { - /* configure each match set */ - for (i = 0; i < request->n_match_sets; i++) { - struct cfg80211_ssid *ssid; - u32 ssid_len; + ssid = &req->match_sets[i].ssid; - ssid = &request->match_sets[i].ssid; - ssid_len = ssid->ssid_len; + if (!ssid->ssid_len) { + brcmf_err("skip broadcast ssid\n"); + continue; + } - 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)); + ret = brcmf_pno_add_ssid(ifp, ssid, + brcmf_is_ssid_active(ssid, req)); + if (ret < 0) 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, diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pno.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pno.c index 2f6a4e0f0b8d..c7967d9e92d7 100644 --- 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 *ifp, 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)); +} + diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pno.h b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pno.h index 08d701e7f6de..a4a23fc9d2c9 100644 --- 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 */ -- cgit v1.2.3 From ab5981c830339b945ddbedc314567a9e5f506d72 Mon Sep 17 00:00:00 2001 From: Arend Van Spriel Date: Wed, 23 Nov 2016 10:25:24 +0000 Subject: brcmfmac: change prototype for brcmf_do_escan() Reduce the number of parameters as the removed ones can be obtained through struct brcmf_if parameter. Reviewed-by: Hante Meuleman Reviewed-by: Pieter-Paul Giesberts Reviewed-by: Franky Lin Signed-off-by: Arend van Spriel Signed-off-by: Kalle Valo --- drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c') diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c index 3d51e845588c..35867c898343 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c @@ -1080,9 +1080,9 @@ exit: } static s32 -brcmf_do_escan(struct brcmf_cfg80211_info *cfg, struct wiphy *wiphy, - struct brcmf_if *ifp, struct cfg80211_scan_request *request) +brcmf_do_escan(struct brcmf_if *ifp, struct cfg80211_scan_request *request) { + struct brcmf_cfg80211_info *cfg = ifp->drvr->config; s32 err; u32 passive_scan; struct brcmf_scan_results *results; @@ -1090,7 +1090,7 @@ brcmf_do_escan(struct brcmf_cfg80211_info *cfg, struct wiphy *wiphy, brcmf_dbg(SCAN, "Enter\n"); escan->ifp = ifp; - escan->wiphy = wiphy; + escan->wiphy = cfg->wiphy; escan->escan_state = WL_ESCAN_STATE_SCANNING; passive_scan = cfg->active_scan ? 0 : 1; err = brcmf_fil_cmd_int_set(ifp, BRCMF_C_SET_PASSIVE_SCAN, @@ -1170,7 +1170,7 @@ brcmf_cfg80211_escan(struct wiphy *wiphy, struct brcmf_cfg80211_vif *vif, if (err) goto scan_out; - err = brcmf_do_escan(cfg, wiphy, vif->ifp, request); + err = brcmf_do_escan(vif->ifp, request); if (err) goto scan_out; } else { @@ -3289,7 +3289,7 @@ brcmf_notify_sched_scan_results(struct brcmf_if *ifp, set_bit(BRCMF_SCAN_STATUS_BUSY, &cfg->scan_status); cfg->escan_info.run = brcmf_run_escan; - err = brcmf_do_escan(cfg, wiphy, ifp, request); + err = brcmf_do_escan(ifp, request); if (err) { clear_bit(BRCMF_SCAN_STATUS_BUSY, &cfg->scan_status); goto out_err; -- cgit v1.2.3 From fa85b30a908455ff25def3a5f319aad272ef4862 Mon Sep 17 00:00:00 2001 From: Arend Van Spriel Date: Wed, 23 Nov 2016 10:25:25 +0000 Subject: brcmfmac: make internal escan more generic For scheduled scan we initiate an escan in firmware to obtain more info missing from the scheduled scan notification we get from firmware. For upcoming functionality this is also required so make it a bit more generic. Reviewed-by: Hante Meuleman Reviewed-by: Pieter-Paul Giesberts Reviewed-by: Franky Lin Signed-off-by: Arend van Spriel Signed-off-by: Kalle Valo --- .../broadcom/brcm80211/brcmfmac/cfg80211.c | 187 ++++++++++++--------- .../broadcom/brcm80211/brcmfmac/cfg80211.h | 4 +- 2 files changed, 109 insertions(+), 82 deletions(-) (limited to 'drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c') diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c index 35867c898343..f9b10bb40fe7 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c @@ -757,12 +757,12 @@ s32 brcmf_notify_escan_complete(struct brcmf_cfg80211_info *cfg, brcmf_scan_config_mpc(ifp, 1); /* - * e-scan can be initiated by scheduled scan + * e-scan can be initiated internally * which takes precedence. */ - if (cfg->sched_escan) { + if (cfg->internal_escan) { brcmf_dbg(SCAN, "scheduled scan completed\n"); - cfg->sched_escan = false; + cfg->internal_escan = false; if (!aborted) cfg80211_sched_scan_results(cfg_to_wiphy(cfg)); } else if (scan_request) { @@ -3013,7 +3013,7 @@ void brcmf_abort_scanning(struct brcmf_cfg80211_info *cfg) struct escan_info *escan = &cfg->escan_info; set_bit(BRCMF_SCAN_STATUS_ABORT, &cfg->scan_status); - if (cfg->scan_request) { + if (cfg->internal_escan || cfg->scan_request) { escan->escan_state = WL_ESCAN_STATE_IDLE; brcmf_notify_escan_complete(cfg, escan->ifp, true, true); } @@ -3036,7 +3036,7 @@ static void brcmf_escan_timeout(unsigned long data) struct brcmf_cfg80211_info *cfg = (struct brcmf_cfg80211_info *)data; - if (cfg->scan_request) { + if (cfg->internal_escan || cfg->scan_request) { brcmf_err("timer expired\n"); schedule_work(&cfg->escan_timeout_work); } @@ -3119,7 +3119,7 @@ brcmf_cfg80211_escan_handler(struct brcmf_if *ifp, if (brcmf_p2p_scan_finding_common_channel(cfg, bss_info_le)) goto exit; - if (!cfg->scan_request) { + if (!cfg->internal_escan && !cfg->scan_request) { brcmf_dbg(SCAN, "result without cfg80211 request\n"); goto exit; } @@ -3165,7 +3165,7 @@ brcmf_cfg80211_escan_handler(struct brcmf_if *ifp, cfg->escan_info.escan_state = WL_ESCAN_STATE_IDLE; if (brcmf_p2p_scan_finding_common_channel(cfg, NULL)) goto exit; - if (cfg->scan_request) { + if (cfg->internal_escan || cfg->scan_request) { brcmf_inform_bss(cfg); aborted = status != BRCMF_E_STATUS_SUCCESS; brcmf_notify_escan_complete(cfg, ifp, aborted, false); @@ -3190,6 +3190,73 @@ static void brcmf_init_escan(struct brcmf_cfg80211_info *cfg) brcmf_cfg80211_escan_timeout_worker); } +static struct cfg80211_scan_request * +brcmf_alloc_internal_escan_request(struct wiphy *wiphy, u32 n_netinfo) { + struct cfg80211_scan_request *req; + size_t req_size; + + req_size = sizeof(*req) + + n_netinfo * sizeof(req->channels[0]) + + n_netinfo * sizeof(*req->ssids); + + req = kzalloc(req_size, GFP_KERNEL); + if (req) { + req->wiphy = wiphy; + req->ssids = (void *)(&req->channels[0]) + + n_netinfo * sizeof(req->channels[0]); + } + return req; +} + +static int brcmf_internal_escan_add_info(struct cfg80211_scan_request *req, + u8 *ssid, u8 ssid_len, u8 channel) +{ + struct ieee80211_channel *chan; + enum nl80211_band band; + int freq; + + if (channel <= CH_MAX_2G_CHANNEL) + band = NL80211_BAND_2GHZ; + else + band = NL80211_BAND_5GHZ; + + freq = ieee80211_channel_to_frequency(channel, band); + if (!freq) + return -EINVAL; + + chan = ieee80211_get_channel(req->wiphy, freq); + if (!chan) + return -EINVAL; + + req->channels[req->n_channels++] = chan; + memcpy(req->ssids[req->n_ssids].ssid, ssid, ssid_len); + req->ssids[req->n_ssids++].ssid_len = ssid_len; + + return 0; +} + +static int brcmf_start_internal_escan(struct brcmf_if *ifp, + struct cfg80211_scan_request *request) +{ + struct brcmf_cfg80211_info *cfg = ifp->drvr->config; + int err; + + if (test_bit(BRCMF_SCAN_STATUS_BUSY, &cfg->scan_status)) { + /* Abort any on-going scan */ + brcmf_abort_scanning(cfg); + } + + set_bit(BRCMF_SCAN_STATUS_BUSY, &cfg->scan_status); + cfg->escan_info.run = brcmf_run_escan; + err = brcmf_do_escan(ifp, request); + if (err) { + clear_bit(BRCMF_SCAN_STATUS_BUSY, &cfg->scan_status); + return err; + } + cfg->internal_escan = true; + return 0; +} + /* PFN result doesn't have all the info which are required by the supplicant * (For e.g IEs) Do a target Escan so that sched scan results are reported * via wl_inform_single_bss in the required format. Escan does require the @@ -3203,12 +3270,8 @@ brcmf_notify_sched_scan_results(struct brcmf_if *ifp, struct brcmf_cfg80211_info *cfg = ifp->drvr->config; struct brcmf_pno_net_info_le *netinfo, *netinfo_start; struct cfg80211_scan_request *request = NULL; - struct cfg80211_ssid *ssid = NULL; - struct ieee80211_channel *channel = NULL; struct wiphy *wiphy = cfg_to_wiphy(cfg); - int err = 0; - int channel_req = 0; - int band = 0; + int i, err = 0; struct brcmf_pno_scanresults_le *pfn_result; u32 result_count; u32 status; @@ -3234,83 +3297,47 @@ brcmf_notify_sched_scan_results(struct brcmf_if *ifp, */ WARN_ON(status != BRCMF_PNO_SCAN_COMPLETE); brcmf_dbg(SCAN, "PFN NET FOUND event. count: %d\n", result_count); - if (result_count > 0) { - int i; - - request = kzalloc(sizeof(*request), GFP_KERNEL); - ssid = kcalloc(result_count, sizeof(*ssid), GFP_KERNEL); - channel = kcalloc(result_count, sizeof(*channel), GFP_KERNEL); - if (!request || !ssid || !channel) { - err = -ENOMEM; - goto out_err; - } - - request->wiphy = wiphy; - data += sizeof(struct brcmf_pno_scanresults_le); - netinfo_start = (struct brcmf_pno_net_info_le *)data; - - for (i = 0; i < result_count; i++) { - netinfo = &netinfo_start[i]; - if (!netinfo) { - brcmf_err("Invalid netinfo ptr. index: %d\n", - i); - err = -EINVAL; - goto out_err; - } - - brcmf_dbg(SCAN, "SSID:%s Channel:%d\n", - netinfo->SSID, netinfo->channel); - memcpy(ssid[i].ssid, netinfo->SSID, netinfo->SSID_len); - ssid[i].ssid_len = netinfo->SSID_len; - request->n_ssids++; - - channel_req = netinfo->channel; - if (channel_req <= CH_MAX_2G_CHANNEL) - band = NL80211_BAND_2GHZ; - else - band = NL80211_BAND_5GHZ; - channel[i].center_freq = - ieee80211_channel_to_frequency(channel_req, - band); - channel[i].band = band; - channel[i].flags |= IEEE80211_CHAN_NO_HT40; - request->channels[i] = &channel[i]; - request->n_channels++; - } + if (!result_count) { + brcmf_err("FALSE PNO Event. (pfn_count == 0)\n"); + goto out_err; + } + request = brcmf_alloc_internal_escan_request(wiphy, + result_count); + if (!request) { + err = -ENOMEM; + goto out_err; + } - /* assign parsed ssid array */ - if (request->n_ssids) - request->ssids = &ssid[0]; + data += sizeof(struct brcmf_pno_scanresults_le); + netinfo_start = (struct brcmf_pno_net_info_le *)data; - if (test_bit(BRCMF_SCAN_STATUS_BUSY, &cfg->scan_status)) { - /* Abort any on-going scan */ - brcmf_abort_scanning(cfg); + for (i = 0; i < result_count; i++) { + netinfo = &netinfo_start[i]; + if (!netinfo) { + brcmf_err("Invalid netinfo ptr. index: %d\n", + i); + err = -EINVAL; + goto out_err; } - set_bit(BRCMF_SCAN_STATUS_BUSY, &cfg->scan_status); - cfg->escan_info.run = brcmf_run_escan; - err = brcmf_do_escan(ifp, request); - if (err) { - clear_bit(BRCMF_SCAN_STATUS_BUSY, &cfg->scan_status); + brcmf_dbg(SCAN, "SSID:%.32s Channel:%d\n", + netinfo->SSID, netinfo->channel); + err = brcmf_internal_escan_add_info(request, + netinfo->SSID, + netinfo->SSID_len, + netinfo->channel); + if (err) goto out_err; - } - cfg->sched_escan = true; - cfg->scan_request = request; - } else { - brcmf_err("FALSE PNO Event. (pfn_count == 0)\n"); - goto out_err; } - kfree(ssid); - kfree(channel); - kfree(request); - return 0; + err = brcmf_start_internal_escan(ifp, request); + if (!err) + goto free_req; out_err: - kfree(ssid); - kfree(channel); - kfree(request); cfg80211_sched_scan_stopped(wiphy); +free_req: + kfree(request); return err; } @@ -3405,7 +3432,7 @@ static int brcmf_cfg80211_sched_scan_stop(struct wiphy *wiphy, brcmf_dbg(SCAN, "enter\n"); brcmf_pno_clean(ifp); - if (cfg->sched_escan) + if (cfg->internal_escan) brcmf_notify_escan_complete(cfg, ifp, true, true); return 0; } diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.h b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.h index 8889832c17e0..0c9a7081fca9 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.h +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.h @@ -271,7 +271,7 @@ struct brcmf_cfg80211_wowl { * @pub: common driver information. * @channel: current channel. * @active_scan: current scan mode. - * @sched_escan: e-scan for scheduled scan support running. + * @internal_escan: indicates internally initiated e-scan is running. * @ibss_starter: indicates this sta is ibss starter. * @pwr_save: indicate whether dongle to support power save mode. * @dongle_up: indicate whether dongle up or not. @@ -303,7 +303,7 @@ struct brcmf_cfg80211_info { struct brcmf_pub *pub; u32 channel; bool active_scan; - bool sched_escan; + bool internal_escan; bool ibss_starter; bool pwr_save; bool dongle_up; -- cgit v1.2.3 From fca6cb2f059e51dec3fcf3589a5abbbcce5b4043 Mon Sep 17 00:00:00 2001 From: Arend Van Spriel Date: Wed, 23 Nov 2016 10:25:26 +0000 Subject: brcmfmac: split up brcmf_pno_config() function The brcmf_pno_config() function handles two configurations in firmware. Split it and have caller sort out what is needed. Reviewed-by: Hante Meuleman Reviewed-by: Pieter-Paul Giesberts Reviewed-by: Franky Lin Signed-off-by: Arend van Spriel Signed-off-by: Kalle Valo --- .../broadcom/brcm80211/brcmfmac/cfg80211.c | 11 +++- .../net/wireless/broadcom/brcm80211/brcmfmac/pno.c | 60 ++++++++++++++++------ .../net/wireless/broadcom/brcm80211/brcmfmac/pno.h | 17 ++++-- 3 files changed, 68 insertions(+), 20 deletions(-) (limited to 'drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c') diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c index f9b10bb40fe7..e77f904d1d37 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c @@ -42,6 +42,7 @@ #include "common.h" #define BRCMF_SCAN_IE_LEN_MAX 2048 +#define BRCMF_SCHED_SCAN_PERIOD 30 #define WPA_OUI "\x00\x50\xF2" /* WPA OUI */ #define WPA_OUI_TYPE 1 @@ -3396,10 +3397,18 @@ brcmf_cfg80211_sched_scan_start(struct wiphy *wiphy, } /* configure pno */ - ret = brcmf_pno_config(ifp, req); + ret = brcmf_pno_config(ifp, BRCMF_SCHED_SCAN_PERIOD, 0, 0); if (ret < 0) return ret; + /* configure random mac */ + if (req->flags & NL80211_SCAN_FLAG_RANDOM_ADDR) { + ret = brcmf_pno_set_random(ifp, req->mac_addr, + req->mac_addr_mask); + if (ret < 0) + return ret; + } + /* configure each match set */ for (i = 0; i < req->n_match_sets; i++) { diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pno.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pno.c index c7967d9e92d7..72d9eef17e22 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pno.c +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pno.c @@ -23,10 +23,12 @@ #include "fwil_types.h" #define BRCMF_PNO_VERSION 2 -#define BRCMF_PNO_TIME 30 #define BRCMF_PNO_REPEAT 4 #define BRCMF_PNO_FREQ_EXPO_MAX 3 +#define BRCMF_PNO_IMMEDIATE_SCAN_BIT 3 +#define BRCMF_PNO_ENABLE_BD_SCAN_BIT 5 #define BRCMF_PNO_ENABLE_ADAPTSCAN_BIT 6 +#define BRCMF_PNO_REPORT_SEPARATELY_BIT 11 #define BRCMF_PNO_SCAN_INCOMPLETE 0 #define BRCMF_PNO_WPA_AUTH_ANY 0xFFFFFFFF #define BRCMF_PNO_HIDDEN_BIT 2 @@ -47,42 +49,68 @@ int brcmf_pno_clean(struct brcmf_if *ifp) return ret; } -int brcmf_pno_config(struct brcmf_if *ifp, - struct cfg80211_sched_scan_request *request) +int brcmf_pno_config(struct brcmf_if *ifp, u32 scan_freq, + u32 mscan, u32 bestn) { struct brcmf_pno_param_le pfn_param; - struct brcmf_pno_macaddr_le pfn_mac; + u16 flags; + u32 pfnmem; s32 err; - u8 *mac_mask; - int i; memset(&pfn_param, 0, sizeof(pfn_param)); pfn_param.version = cpu_to_le32(BRCMF_PNO_VERSION); /* set extra pno params */ - pfn_param.flags = cpu_to_le16(1 << BRCMF_PNO_ENABLE_ADAPTSCAN_BIT); + flags = BIT(BRCMF_PNO_IMMEDIATE_SCAN_BIT) | + BIT(BRCMF_PNO_REPORT_SEPARATELY_BIT) | + BIT(BRCMF_PNO_ENABLE_ADAPTSCAN_BIT); pfn_param.repeat = BRCMF_PNO_REPEAT; pfn_param.exp = BRCMF_PNO_FREQ_EXPO_MAX; /* set up pno scan fr */ - pfn_param.scan_freq = cpu_to_le32(BRCMF_PNO_TIME); + pfn_param.scan_freq = cpu_to_le32(scan_freq); + + if (mscan) { + pfnmem = bestn; + + /* set bestn in firmware */ + err = brcmf_fil_iovar_int_set(ifp, "pfnmem", pfnmem); + if (err < 0) { + brcmf_err("failed to set pfnmem\n"); + goto exit; + } + /* get max mscan which the firmware supports */ + err = brcmf_fil_iovar_int_get(ifp, "pfnmem", &pfnmem); + if (err < 0) { + brcmf_err("failed to get pfnmem\n"); + goto exit; + } + mscan = min_t(u32, mscan, pfnmem); + pfn_param.mscan = mscan; + pfn_param.bestn = bestn; + flags |= BIT(BRCMF_PNO_ENABLE_BD_SCAN_BIT); + brcmf_dbg(INFO, "mscan=%d, bestn=%d\n", mscan, bestn); + } + pfn_param.flags = cpu_to_le16(flags); err = brcmf_fil_iovar_data_set(ifp, "pfn_set", &pfn_param, sizeof(pfn_param)); - if (err) { + if (err) brcmf_err("pfn_set failed, err=%d\n", err); - return err; - } - /* Find out if mac randomization should be turned on */ - if (!(request->flags & NL80211_SCAN_FLAG_RANDOM_ADDR)) - return 0; +exit: + return err; +} + +int brcmf_pno_set_random(struct brcmf_if *ifp, u8 *mac_addr, u8 *mac_mask) +{ + struct brcmf_pno_macaddr_le pfn_mac; + int err, i; pfn_mac.version = BRCMF_PFN_MACADDR_CFG_VER; pfn_mac.flags = BRCMF_PFN_MAC_OUI_ONLY | BRCMF_PFN_SET_MAC_UNASSOC; - memcpy(pfn_mac.mac, request->mac_addr, ETH_ALEN); - mac_mask = request->mac_addr_mask; + memcpy(pfn_mac.mac, mac_addr, ETH_ALEN); for (i = 0; i < ETH_ALEN; i++) { pfn_mac.mac[i] &= mac_mask[i]; pfn_mac.mac[i] |= get_random_int() & ~(mac_mask[i]); diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pno.h b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pno.h index a4a23fc9d2c9..f2c5a53d7b1c 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pno.h +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pno.h @@ -30,10 +30,21 @@ int brcmf_pno_clean(struct brcmf_if *ifp); * brcmf_pno_config - configure pno parameters. * * @ifp: interface object used. - * @request: scheduled scan parameters. + * @scan_freq: scan frequency period in seconds. + * @mscan: maximum number of scans stored in firmware. + * @bestn: maximum number of APs per scan stored in firmware. */ -int brcmf_pno_config(struct brcmf_if *ifp, - struct cfg80211_sched_scan_request *request); +int brcmf_pno_config(struct brcmf_if *ifp, u32 scan_freq, + u32 mscan, u32 bestn); + +/** + * brcmf_pno_set_random - setup randomisation mac address for pno. + * + * @ifp: interface object used. + * @mac_addr: MAC address used with randomisation. + * @mac_mask: MAC address mask used for randomisation. + */ +int brcmf_pno_set_random(struct brcmf_if *ifp, u8 *mac_addr, u8 *mac_mask); /** * brcmf_pno_add_ssid - add ssid for pno in firmware. -- cgit v1.2.3 From 3e48611d31dd333be01576902f2dc11adefc9a06 Mon Sep 17 00:00:00 2001 From: Arend Van Spriel Date: Wed, 23 Nov 2016 10:25:27 +0000 Subject: brcmfmac: move scheduled scan activation to pno source file Rework .sched_scan_start() callback moving actual configuration of the device in pno source file. Reviewed-by: Hante Meuleman Reviewed-by: Pieter-Paul Giesberts Reviewed-by: Franky Lin Signed-off-by: Arend van Spriel Signed-off-by: Kalle Valo --- .../broadcom/brcm80211/brcmfmac/cfg80211.c | 65 +----------- .../net/wireless/broadcom/brcm80211/brcmfmac/pno.c | 110 +++++++++++++++++---- .../net/wireless/broadcom/brcm80211/brcmfmac/pno.h | 29 +----- 3 files changed, 94 insertions(+), 110 deletions(-) (limited to 'drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c') diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c index e77f904d1d37..4fbc473bbc9a 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c @@ -42,7 +42,6 @@ #include "common.h" #define BRCMF_SCAN_IE_LEN_MAX 2048 -#define BRCMF_SCHED_SCAN_PERIOD 30 #define WPA_OUI "\x00\x50\xF2" /* WPA OUI */ #define WPA_OUI_TYPE 1 @@ -3342,24 +3341,6 @@ free_req: 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, @@ -3367,9 +3348,6 @@ brcmf_cfg80211_sched_scan_start(struct wiphy *wiphy, { struct brcmf_if *ifp = netdev_priv(ndev); struct brcmf_cfg80211_info *cfg = wiphy_priv(wiphy); - struct cfg80211_ssid *ssid; - int i; - int ret = 0; brcmf_dbg(SCAN, "Enter n_match_sets:%d n_ssids:%d\n", req->n_match_sets, req->n_ssids); @@ -3389,48 +3367,7 @@ brcmf_cfg80211_sched_scan_start(struct wiphy *wiphy, return -EINVAL; } - /* 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, BRCMF_SCHED_SCAN_PERIOD, 0, 0); - if (ret < 0) - return ret; - - /* configure random mac */ - if (req->flags & NL80211_SCAN_FLAG_RANDOM_ADDR) { - ret = brcmf_pno_set_random(ifp, req->mac_addr, - req->mac_addr_mask); - 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; - } - - ret = brcmf_pno_add_ssid(ifp, ssid, - brcmf_is_ssid_active(ssid, req)); - if (ret < 0) - brcmf_dbg(SCAN, ">>> PNO filter %s for ssid (%s)\n", - ret == 0 ? "set" : "failed", ssid->ssid); - } - /* 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 ret; + return brcmf_pno_start_sched_scan(ifp, req); } static int brcmf_cfg80211_sched_scan_stop(struct wiphy *wiphy, diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pno.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pno.c index 72d9eef17e22..d16e89e8f522 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pno.c +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pno.c @@ -32,25 +32,10 @@ #define BRCMF_PNO_SCAN_INCOMPLETE 0 #define BRCMF_PNO_WPA_AUTH_ANY 0xFFFFFFFF #define BRCMF_PNO_HIDDEN_BIT 2 +#define BRCMF_PNO_SCHED_SCAN_PERIOD 30 -int brcmf_pno_clean(struct brcmf_if *ifp) -{ - int ret; - - /* Disable pfn */ - ret = brcmf_fil_iovar_int_set(ifp, "pfn", 0); - if (ret == 0) { - /* clear pfn */ - ret = brcmf_fil_iovar_data_set(ifp, "pfnclear", NULL, 0); - } - if (ret < 0) - brcmf_err("failed code %d\n", ret); - - return ret; -} - -int brcmf_pno_config(struct brcmf_if *ifp, u32 scan_freq, - u32 mscan, u32 bestn) +static int brcmf_pno_config(struct brcmf_if *ifp, u32 scan_freq, + u32 mscan, u32 bestn) { struct brcmf_pno_param_le pfn_param; u16 flags; @@ -102,7 +87,8 @@ exit: return err; } -int brcmf_pno_set_random(struct brcmf_if *ifp, u8 *mac_addr, u8 *mac_mask) +static int brcmf_pno_set_random(struct brcmf_if *ifp, u8 *mac_addr, + u8 *mac_mask) { struct brcmf_pno_macaddr_le pfn_mac; int err, i; @@ -128,8 +114,8 @@ int brcmf_pno_set_random(struct brcmf_if *ifp, u8 *mac_addr, u8 *mac_mask) return err; } -int brcmf_pno_add_ssid(struct brcmf_if *ifp, struct cfg80211_ssid *ssid, - bool active) +static int brcmf_pno_add_ssid(struct brcmf_if *ifp, struct cfg80211_ssid *ssid, + bool active) { struct brcmf_pno_net_param_le pfn; @@ -144,3 +130,85 @@ int brcmf_pno_add_ssid(struct brcmf_if *ifp, struct cfg80211_ssid *ssid, return brcmf_fil_iovar_data_set(ifp, "pfn_add", &pfn, sizeof(pfn)); } +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; +} + +int brcmf_pno_clean(struct brcmf_if *ifp) +{ + int ret; + + /* Disable pfn */ + ret = brcmf_fil_iovar_int_set(ifp, "pfn", 0); + if (ret == 0) { + /* clear pfn */ + ret = brcmf_fil_iovar_data_set(ifp, "pfnclear", NULL, 0); + } + if (ret < 0) + brcmf_err("failed code %d\n", ret); + + return ret; +} + +int brcmf_pno_start_sched_scan(struct brcmf_if *ifp, + struct cfg80211_sched_scan_request *req) +{ + struct cfg80211_ssid *ssid; + int i, ret; + + /* 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, BRCMF_PNO_SCHED_SCAN_PERIOD, 0, 0); + if (ret < 0) + return ret; + + /* configure random mac */ + if (req->flags & NL80211_SCAN_FLAG_RANDOM_ADDR) { + ret = brcmf_pno_set_random(ifp, req->mac_addr, + req->mac_addr_mask); + 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; + } + + ret = brcmf_pno_add_ssid(ifp, ssid, + brcmf_is_ssid_active(ssid, req)); + if (ret < 0) + brcmf_dbg(SCAN, ">>> PNO filter %s for ssid (%s)\n", + ret == 0 ? "set" : "failed", ssid->ssid); + } + /* 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 ret; +} + diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pno.h b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pno.h index f2c5a53d7b1c..5803a4ca8cc4 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pno.h +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pno.h @@ -27,33 +27,12 @@ int brcmf_pno_clean(struct brcmf_if *ifp); /** - * brcmf_pno_config - configure pno parameters. + * brcmf_pno_start_sched_scan - initiate scheduled scan on device. * * @ifp: interface object used. - * @scan_freq: scan frequency period in seconds. - * @mscan: maximum number of scans stored in firmware. - * @bestn: maximum number of APs per scan stored in firmware. + * @req: configuration parameters for scheduled scan. */ -int brcmf_pno_config(struct brcmf_if *ifp, u32 scan_freq, - u32 mscan, u32 bestn); - -/** - * brcmf_pno_set_random - setup randomisation mac address for pno. - * - * @ifp: interface object used. - * @mac_addr: MAC address used with randomisation. - * @mac_mask: MAC address mask used for randomisation. - */ -int brcmf_pno_set_random(struct brcmf_if *ifp, u8 *mac_addr, u8 *mac_mask); - -/** - * 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); +int brcmf_pno_start_sched_scan(struct brcmf_if *ifp, + struct cfg80211_sched_scan_request *req); #endif /* _BRCMF_PNO_H */ -- cgit v1.2.3 From dfe5b0d52d5880bd9d4b427e1a53c9e9e4c3c820 Mon Sep 17 00:00:00 2001 From: Arend Van Spriel Date: Wed, 23 Nov 2016 10:25:29 +0000 Subject: brcmfmac: remove restriction from .sched_scan_start() callback In the .sched_scan_start() callback a condition was checked whether a normal scan was ongoing. However, there is no need for this check as it is ok to start the scheduled scan irrespective whether or not a normal scan is ongoing. Reviewed-by: Hante Meuleman Reviewed-by: Pieter-Paul Giesberts Reviewed-by: Franky Lin Signed-off-by: Arend van Spriel Signed-off-by: Kalle Valo --- drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) (limited to 'drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c') diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c index 4fbc473bbc9a..75ad8b3d53e2 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c @@ -3351,10 +3351,7 @@ brcmf_cfg80211_sched_scan_start(struct wiphy *wiphy, brcmf_dbg(SCAN, "Enter n_match_sets:%d n_ssids:%d\n", 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; - } + if (test_bit(BRCMF_SCAN_STATUS_SUPPRESS, &cfg->scan_status)) { brcmf_err("Scanning suppressed: status (%lu)\n", cfg->scan_status); -- cgit v1.2.3 From c6989fd55ceb633d2f18c12ffae01b9123125c89 Mon Sep 17 00:00:00 2001 From: Arend Van Spriel Date: Wed, 23 Nov 2016 10:25:30 +0000 Subject: brcmfmac: use requested scan interval in scheduled scan User-space can specify the interval for the scheduled scan. This interval is found in scheduled scan plan. The driver supports only one plan, which is legacy behaviour. Reviewed-by: Hante Meuleman Reviewed-by: Pieter-Paul Giesberts Reviewed-by: Franky Lin Signed-off-by: Arend van Spriel Signed-off-by: Kalle Valo --- drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c | 1 + drivers/net/wireless/broadcom/brcm80211/brcmfmac/pno.c | 6 +++++- drivers/net/wireless/broadcom/brcm80211/brcmfmac/pno.h | 6 ++++-- 3 files changed, 10 insertions(+), 3 deletions(-) (limited to 'drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c') diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c index 75ad8b3d53e2..cc12b14c0f03 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c @@ -6312,6 +6312,7 @@ static void brcmf_wiphy_pno_params(struct wiphy *wiphy) wiphy->max_sched_scan_ssids = BRCMF_PNO_MAX_PFN_COUNT; wiphy->max_match_sets = BRCMF_PNO_MAX_PFN_COUNT; wiphy->max_sched_scan_ie_len = BRCMF_SCAN_IE_LEN_MAX; + wiphy->max_sched_scan_plan_interval = BRCMF_PNO_SCHED_SCAN_MAX_PERIOD; wiphy->flags |= WIPHY_FLAG_SUPPORTS_SCHED_SCAN; } diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pno.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pno.c index bc33bdcabaff..f273cab0da10 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pno.c +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pno.c @@ -63,6 +63,10 @@ static int brcmf_pno_config(struct brcmf_if *ifp, u32 scan_freq, pfn_param.exp = BRCMF_PNO_FREQ_EXPO_MAX; /* set up pno scan fr */ + if (scan_freq < BRCMF_PNO_SCHED_SCAN_MIN_PERIOD) { + brcmf_dbg(SCAN, "scan period too small, using minimum\n"); + scan_freq = BRCMF_PNO_SCHED_SCAN_MIN_PERIOD; + } pfn_param.scan_freq = cpu_to_le32(scan_freq); if (mscan) { @@ -191,7 +195,7 @@ int brcmf_pno_start_sched_scan(struct brcmf_if *ifp, } /* configure pno */ - ret = brcmf_pno_config(ifp, BRCMF_PNO_SCHED_SCAN_PERIOD, 0, 0); + ret = brcmf_pno_config(ifp, req->scan_plans[0].interval, 0, 0); if (ret < 0) return ret; diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pno.h b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pno.h index 5803a4ca8cc4..bae55b2af78c 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pno.h +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pno.h @@ -16,8 +16,10 @@ #ifndef _BRCMF_PNO_H #define _BRCMF_PNO_H -#define BRCMF_PNO_SCAN_COMPLETE 1 -#define BRCMF_PNO_MAX_PFN_COUNT 16 +#define BRCMF_PNO_SCAN_COMPLETE 1 +#define BRCMF_PNO_MAX_PFN_COUNT 16 +#define BRCMF_PNO_SCHED_SCAN_MIN_PERIOD 10 +#define BRCMF_PNO_SCHED_SCAN_MAX_PERIOD 508 /** * brcmf_pno_clean - disable and clear pno in firmware. -- cgit v1.2.3 From 53e3a80d80c80bf50ab64cf6c44fb0fa41aa22d8 Mon Sep 17 00:00:00 2001 From: Arend Van Spriel Date: Wed, 23 Nov 2016 10:25:31 +0000 Subject: brcmfmac: fix scheduled scan result handling for newer chips The scan results for scheduled scan as retrieved from the device have changed. A field has been added which is not needed. However, the appended info is. Luckily they are versioned so check that to find out the location of the appended data. Reviewed-by: Hante Meuleman Reviewed-by: Pieter-Paul Giesberts Reviewed-by: Franky Lin Signed-off-by: Arend van Spriel Signed-off-by: Kalle Valo --- .../broadcom/brcm80211/brcmfmac/cfg80211.c | 24 +++++++++++++++++++++- .../broadcom/brcm80211/brcmfmac/fwil_types.h | 7 +++++++ 2 files changed, 30 insertions(+), 1 deletion(-) (limited to 'drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c') diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c index cc12b14c0f03..f28f03a6fbfb 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c @@ -3257,6 +3257,28 @@ static int brcmf_start_internal_escan(struct brcmf_if *ifp, return 0; } +static struct brcmf_pno_net_info_le * +brcmf_get_netinfo_array(struct brcmf_pno_scanresults_le *pfn_v1) +{ + struct brcmf_pno_scanresults_v2_le *pfn_v2; + struct brcmf_pno_net_info_le *netinfo; + + switch (pfn_v1->version) { + default: + WARN_ON(1); + /* fall-thru */ + case cpu_to_le32(1): + netinfo = (struct brcmf_pno_net_info_le *)(pfn_v1 + 1); + break; + case cpu_to_le32(2): + pfn_v2 = (struct brcmf_pno_scanresults_v2_le *)pfn_v1; + netinfo = (struct brcmf_pno_net_info_le *)(pfn_v2 + 1); + break; + } + + return netinfo; +} + /* PFN result doesn't have all the info which are required by the supplicant * (For e.g IEs) Do a target Escan so that sched scan results are reported * via wl_inform_single_bss in the required format. Escan does require the @@ -3309,7 +3331,7 @@ brcmf_notify_sched_scan_results(struct brcmf_if *ifp, } data += sizeof(struct brcmf_pno_scanresults_le); - netinfo_start = (struct brcmf_pno_net_info_le *)data; + netinfo_start = brcmf_get_netinfo_array(pfn_result); for (i = 0; i < result_count; i++) { netinfo = &netinfo_start[i]; diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwil_types.h b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwil_types.h index 64aed2d0b9ed..9a1eb5ab6c4b 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwil_types.h +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwil_types.h @@ -785,6 +785,13 @@ struct brcmf_pno_scanresults_le { __le32 count; }; +struct brcmf_pno_scanresults_v2_le { + __le32 version; + __le32 status; + __le32 count; + __le32 scan_ch_bucket; +}; + /** * struct brcmf_pno_macaddr_le - to configure PNO macaddr randomization. * -- cgit v1.2.3