aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/staging/wfx/scan.c
diff options
context:
space:
mode:
authorJérôme Pouiller <jerome.pouiller@silabs.com>2019-09-19 14:25:48 +0000
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2019-10-04 10:48:54 +0200
commit40115bbc40e2fd2de0e01ef2a28e0d09a1b5d0d1 (patch)
treed3d7723d90f9ec8ae5c77e30ce61df6ffd523640 /drivers/staging/wfx/scan.c
parentstaging: wfx: implement 802.11 key handling (diff)
downloadlinux-dev-40115bbc40e2fd2de0e01ef2a28e0d09a1b5d0d1.tar.xz
linux-dev-40115bbc40e2fd2de0e01ef2a28e0d09a1b5d0d1.zip
staging: wfx: implement the rest of mac80211 API
Finish to fill struct ieee80211_ops with necessary callbacks. Driver is now ready to be registered to mac80211. Signed-off-by: Jérôme Pouiller <jerome.pouiller@silabs.com> Link: https://lore.kernel.org/r/20190919142527.31797-21-Jerome.Pouiller@silabs.com Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'drivers/staging/wfx/scan.c')
-rw-r--r--drivers/staging/wfx/scan.c40
1 files changed, 40 insertions, 0 deletions
diff --git a/drivers/staging/wfx/scan.c b/drivers/staging/wfx/scan.c
index 207b26ebc9fd..ea5001c915f6 100644
--- a/drivers/staging/wfx/scan.c
+++ b/drivers/staging/wfx/scan.c
@@ -21,11 +21,26 @@ static void __ieee80211_scan_completed_compat(struct ieee80211_hw *hw, bool abor
ieee80211_scan_completed(hw, &info);
}
+static void wfx_scan_restart_delayed(struct wfx_vif *wvif)
+{
+ if (wvif->delayed_unjoin) {
+ wvif->delayed_unjoin = false;
+ if (!schedule_work(&wvif->unjoin_work))
+ wfx_tx_unlock(wvif->wdev);
+ } else if (wvif->delayed_link_loss) {
+ wvif->delayed_link_loss = 0;
+ wfx_cqm_bssloss_sm(wvif, 1, 0, 0);
+ }
+}
+
static int wfx_scan_start(struct wfx_vif *wvif, struct wfx_scan_params *scan)
{
int ret;
int tmo = 500;
+ if (wvif->state == WFX_STATE_PRE_STA)
+ return -EBUSY;
+
tmo += scan->scan_req.num_of_channels *
((20 * (scan->scan_req.max_channel_time)) + 10);
atomic_set(&wvif->scan.in_progress, 1);
@@ -38,6 +53,7 @@ static int wfx_scan_start(struct wfx_vif *wvif, struct wfx_scan_params *scan)
atomic_set(&wvif->scan.in_progress, 0);
atomic_set(&wvif->wdev->scan_in_progress, 0);
cancel_delayed_work_sync(&wvif->scan.timeout);
+ wfx_scan_restart_delayed(wvif);
}
return ret;
}
@@ -56,6 +72,9 @@ int wfx_hw_scan(struct ieee80211_hw *hw,
if (!wvif)
return -EINVAL;
+ if (wvif->state == WFX_STATE_AP)
+ return -EOPNOTSUPP;
+
if (req->n_ssids == 1 && !req->ssids[0].ssid_len)
req->n_ssids = 0;
@@ -121,11 +140,23 @@ void wfx_scan_work(struct work_struct *work)
.scan_req.scan_type.type = 0, /* Foreground */
};
struct ieee80211_channel *first;
+ bool first_run = (wvif->scan.begin == wvif->scan.curr &&
+ wvif->scan.begin != wvif->scan.end);
int i;
down(&wvif->scan.lock);
mutex_lock(&wvif->wdev->conf_mutex);
+ if (first_run) {
+ if (wvif->state == WFX_STATE_STA &&
+ !(wvif->powersave_mode.pm_mode.enter_psm)) {
+ struct hif_req_set_pm_mode pm = wvif->powersave_mode;
+
+ pm.pm_mode.enter_psm = 1;
+ wfx_set_pm(wvif, &pm);
+ }
+ }
+
if (!wvif->scan.req || wvif->scan.curr == wvif->scan.end) {
if (wvif->scan.output_power != wvif->wdev->output_power)
hif_set_output_power(wvif, wvif->wdev->output_power * 10);
@@ -138,10 +169,14 @@ void wfx_scan_work(struct work_struct *work)
dev_dbg(wvif->wdev->dev, "scan canceled\n");
wvif->scan.req = NULL;
+ wfx_scan_restart_delayed(wvif);
wfx_tx_unlock(wvif->wdev);
mutex_unlock(&wvif->wdev->conf_mutex);
__ieee80211_scan_completed_compat(wvif->wdev->hw, wvif->scan.status ? 1 : 0);
up(&wvif->scan.lock);
+ if (wvif->state == WFX_STATE_STA &&
+ !(wvif->powersave_mode.pm_mode.enter_psm))
+ wfx_set_pm(wvif, &wvif->powersave_mode);
return;
}
first = *wvif->scan.curr;
@@ -170,6 +205,11 @@ void wfx_scan_work(struct work_struct *work)
scan.ssids = &wvif->scan.ssids[0];
scan.scan_req.num_of_channels = it - wvif->scan.curr;
scan.scan_req.probe_delay = 100;
+ // FIXME: Check if FW can do active scan while joined.
+ if (wvif->state == WFX_STATE_STA) {
+ scan.scan_req.scan_type.type = 1;
+ scan.scan_req.scan_flags.fbg = 1;
+ }
scan.ch = kcalloc(scan.scan_req.num_of_channels, sizeof(u8), GFP_KERNEL);