diff options
Diffstat (limited to 'package/kernel/mac80211/patches/357-0006-brcmfmac-make-internal-escan-more-generic.patch')
-rw-r--r-- | package/kernel/mac80211/patches/357-0006-brcmfmac-make-internal-escan-more-generic.patch | 306 |
1 files changed, 306 insertions, 0 deletions
diff --git a/package/kernel/mac80211/patches/357-0006-brcmfmac-make-internal-escan-more-generic.patch b/package/kernel/mac80211/patches/357-0006-brcmfmac-make-internal-escan-more-generic.patch new file mode 100644 index 0000000000..84a69f0739 --- /dev/null +++ b/package/kernel/mac80211/patches/357-0006-brcmfmac-make-internal-escan-more-generic.patch @@ -0,0 +1,306 @@ +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; |