863a06b0a4
Signed-off-by: Rafał Miłecki <rafal@milecki.pl>
306 lines
9.4 KiB
Diff
306 lines
9.4 KiB
Diff
From fa85b30a908455ff25def3a5f319aad272ef4862 Mon Sep 17 00:00:00 2001
|
|
From: Arend Van Spriel <arend.vanspriel@broadcom.com>
|
|
Date: Wed, 23 Nov 2016 10:25:25 +0000
|
|
Subject: [PATCH] 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 <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 | 187 ++++++++++++---------
|
|
.../broadcom/brcm80211/brcmfmac/cfg80211.h | 4 +-
|
|
2 files changed, 109 insertions(+), 82 deletions(-)
|
|
|
|
--- 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 b
|
|
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_c
|
|
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
|
|
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 brcm
|
|
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 brcm
|
|
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 brcm
|
|
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 b
|
|
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 b
|
|
*/
|
|
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;
|
|
- }
|
|
+ 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;
|
|
+ }
|
|
|
|
- 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;
|
|
- }
|
|
+ data += sizeof(struct brcmf_pno_scanresults_le);
|
|
+ netinfo_start = (struct brcmf_pno_net_info_le *)data;
|
|
|
|
- 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++;
|
|
- }
|
|
-
|
|
- /* assign parsed ssid array */
|
|
- if (request->n_ssids)
|
|
- request->ssids = &ssid[0];
|
|
-
|
|
- 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_sto
|
|
|
|
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;
|
|
}
|
|
--- 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;
|