diff options
Diffstat (limited to 'drivers/net/wireless/broadcom/brcm80211/brcmfmac/pno.c')
-rw-r--r-- | drivers/net/wireless/broadcom/brcm80211/brcmfmac/pno.c | 110 |
1 files changed, 89 insertions, 21 deletions
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; +} + |