cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

scan.c (8341B)


      1// SPDX-License-Identifier: GPL-2.0-only
      2/*
      3 * This file is part of wl18xx
      4 *
      5 * Copyright (C) 2012 Texas Instruments. All rights reserved.
      6 */
      7
      8#include <linux/ieee80211.h>
      9#include "scan.h"
     10#include "../wlcore/debug.h"
     11
     12static void wl18xx_adjust_channels(struct wl18xx_cmd_scan_params *cmd,
     13				   struct wlcore_scan_channels *cmd_channels)
     14{
     15	memcpy(cmd->passive, cmd_channels->passive, sizeof(cmd->passive));
     16	memcpy(cmd->active, cmd_channels->active, sizeof(cmd->active));
     17	cmd->dfs = cmd_channels->dfs;
     18	cmd->passive_active = cmd_channels->passive_active;
     19
     20	memcpy(cmd->channels_2, cmd_channels->channels_2,
     21	       sizeof(cmd->channels_2));
     22	memcpy(cmd->channels_5, cmd_channels->channels_5,
     23	       sizeof(cmd->channels_5));
     24	/* channels_4 are not supported, so no need to copy them */
     25}
     26
     27static int wl18xx_scan_send(struct wl1271 *wl, struct wl12xx_vif *wlvif,
     28			    struct cfg80211_scan_request *req)
     29{
     30	struct wl18xx_cmd_scan_params *cmd;
     31	struct wlcore_scan_channels *cmd_channels = NULL;
     32	int ret;
     33
     34	cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
     35	if (!cmd) {
     36		ret = -ENOMEM;
     37		goto out;
     38	}
     39
     40	/* scan on the dev role if the regular one is not started */
     41	if (wlcore_is_p2p_mgmt(wlvif))
     42		cmd->role_id = wlvif->dev_role_id;
     43	else
     44		cmd->role_id = wlvif->role_id;
     45
     46	if (WARN_ON(cmd->role_id == WL12XX_INVALID_ROLE_ID)) {
     47		ret = -EINVAL;
     48		goto out;
     49	}
     50
     51	cmd->scan_type = SCAN_TYPE_SEARCH;
     52	cmd->rssi_threshold = -127;
     53	cmd->snr_threshold = 0;
     54
     55	cmd->bss_type = SCAN_BSS_TYPE_ANY;
     56
     57	cmd->ssid_from_list = 0;
     58	cmd->filter = 0;
     59	cmd->add_broadcast = 0;
     60
     61	cmd->urgency = 0;
     62	cmd->protect = 0;
     63
     64	cmd->n_probe_reqs = wl->conf.scan.num_probe_reqs;
     65	cmd->terminate_after = 0;
     66
     67	/* configure channels */
     68	WARN_ON(req->n_ssids > 1);
     69
     70	cmd_channels = kzalloc(sizeof(*cmd_channels), GFP_KERNEL);
     71	if (!cmd_channels) {
     72		ret = -ENOMEM;
     73		goto out;
     74	}
     75
     76	wlcore_set_scan_chan_params(wl, cmd_channels, req->channels,
     77				    req->n_channels, req->n_ssids,
     78				    SCAN_TYPE_SEARCH);
     79	wl18xx_adjust_channels(cmd, cmd_channels);
     80
     81	/*
     82	 * all the cycles params (except total cycles) should
     83	 * remain 0 for normal scan
     84	 */
     85	cmd->total_cycles = 1;
     86
     87	if (req->no_cck)
     88		cmd->rate = WL18XX_SCAN_RATE_6;
     89
     90	cmd->tag = WL1271_SCAN_DEFAULT_TAG;
     91
     92	if (req->n_ssids) {
     93		cmd->ssid_len = req->ssids[0].ssid_len;
     94		memcpy(cmd->ssid, req->ssids[0].ssid, cmd->ssid_len);
     95	}
     96
     97	/* TODO: per-band ies? */
     98	if (cmd->active[0]) {
     99		u8 band = NL80211_BAND_2GHZ;
    100		ret = wl12xx_cmd_build_probe_req(wl, wlvif,
    101				 cmd->role_id, band,
    102				 req->ssids ? req->ssids[0].ssid : NULL,
    103				 req->ssids ? req->ssids[0].ssid_len : 0,
    104				 req->ie,
    105				 req->ie_len,
    106				 NULL,
    107				 0,
    108				 false);
    109		if (ret < 0) {
    110			wl1271_error("2.4GHz PROBE request template failed");
    111			goto out;
    112		}
    113	}
    114
    115	if (cmd->active[1] || cmd->dfs) {
    116		u8 band = NL80211_BAND_5GHZ;
    117		ret = wl12xx_cmd_build_probe_req(wl, wlvif,
    118				 cmd->role_id, band,
    119				 req->ssids ? req->ssids[0].ssid : NULL,
    120				 req->ssids ? req->ssids[0].ssid_len : 0,
    121				 req->ie,
    122				 req->ie_len,
    123				 NULL,
    124				 0,
    125				 false);
    126		if (ret < 0) {
    127			wl1271_error("5GHz PROBE request template failed");
    128			goto out;
    129		}
    130	}
    131
    132	wl1271_dump(DEBUG_SCAN, "SCAN: ", cmd, sizeof(*cmd));
    133
    134	ret = wl1271_cmd_send(wl, CMD_SCAN, cmd, sizeof(*cmd), 0);
    135	if (ret < 0) {
    136		wl1271_error("SCAN failed");
    137		goto out;
    138	}
    139
    140out:
    141	kfree(cmd_channels);
    142	kfree(cmd);
    143	return ret;
    144}
    145
    146void wl18xx_scan_completed(struct wl1271 *wl, struct wl12xx_vif *wlvif)
    147{
    148	wl->scan.failed = false;
    149	cancel_delayed_work(&wl->scan_complete_work);
    150	ieee80211_queue_delayed_work(wl->hw, &wl->scan_complete_work,
    151				     msecs_to_jiffies(0));
    152}
    153
    154static
    155int wl18xx_scan_sched_scan_config(struct wl1271 *wl,
    156				  struct wl12xx_vif *wlvif,
    157				  struct cfg80211_sched_scan_request *req,
    158				  struct ieee80211_scan_ies *ies)
    159{
    160	struct wl18xx_cmd_scan_params *cmd;
    161	struct wlcore_scan_channels *cmd_channels = NULL;
    162	struct conf_sched_scan_settings *c = &wl->conf.sched_scan;
    163	int ret;
    164	int filter_type;
    165
    166	wl1271_debug(DEBUG_CMD, "cmd sched_scan scan config");
    167
    168	filter_type = wlcore_scan_sched_scan_ssid_list(wl, wlvif, req);
    169	if (filter_type < 0)
    170		return filter_type;
    171
    172	cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
    173	if (!cmd) {
    174		ret = -ENOMEM;
    175		goto out;
    176	}
    177
    178	cmd->role_id = wlvif->role_id;
    179
    180	if (WARN_ON(cmd->role_id == WL12XX_INVALID_ROLE_ID)) {
    181		ret = -EINVAL;
    182		goto out;
    183	}
    184
    185	cmd->scan_type = SCAN_TYPE_PERIODIC;
    186	cmd->rssi_threshold = c->rssi_threshold;
    187	cmd->snr_threshold = c->snr_threshold;
    188
    189	/* don't filter on BSS type */
    190	cmd->bss_type = SCAN_BSS_TYPE_ANY;
    191
    192	cmd->ssid_from_list = 1;
    193	if (filter_type == SCAN_SSID_FILTER_LIST)
    194		cmd->filter = 1;
    195	cmd->add_broadcast = 0;
    196
    197	cmd->urgency = 0;
    198	cmd->protect = 0;
    199
    200	cmd->n_probe_reqs = c->num_probe_reqs;
    201	/* don't stop scanning automatically when something is found */
    202	cmd->terminate_after = 0;
    203
    204	cmd_channels = kzalloc(sizeof(*cmd_channels), GFP_KERNEL);
    205	if (!cmd_channels) {
    206		ret = -ENOMEM;
    207		goto out;
    208	}
    209
    210	/* configure channels */
    211	wlcore_set_scan_chan_params(wl, cmd_channels, req->channels,
    212				    req->n_channels, req->n_ssids,
    213				    SCAN_TYPE_PERIODIC);
    214	wl18xx_adjust_channels(cmd, cmd_channels);
    215
    216	if (c->num_short_intervals && c->long_interval &&
    217	    c->long_interval > req->scan_plans[0].interval * MSEC_PER_SEC) {
    218		cmd->short_cycles_msec =
    219			cpu_to_le16(req->scan_plans[0].interval * MSEC_PER_SEC);
    220		cmd->long_cycles_msec = cpu_to_le16(c->long_interval);
    221		cmd->short_cycles_count = c->num_short_intervals;
    222	} else {
    223		cmd->short_cycles_msec = 0;
    224		cmd->long_cycles_msec =
    225			cpu_to_le16(req->scan_plans[0].interval * MSEC_PER_SEC);
    226		cmd->short_cycles_count = 0;
    227	}
    228	wl1271_debug(DEBUG_SCAN, "short_interval: %d, long_interval: %d, num_short: %d",
    229		     le16_to_cpu(cmd->short_cycles_msec),
    230		     le16_to_cpu(cmd->long_cycles_msec),
    231		     cmd->short_cycles_count);
    232
    233	cmd->total_cycles = 0;
    234
    235	cmd->tag = WL1271_SCAN_DEFAULT_TAG;
    236
    237	/* create a PERIODIC_SCAN_REPORT_EVENT whenever we've got a match */
    238	cmd->report_threshold = 1;
    239	cmd->terminate_on_report = 0;
    240
    241	if (cmd->active[0]) {
    242		u8 band = NL80211_BAND_2GHZ;
    243		ret = wl12xx_cmd_build_probe_req(wl, wlvif,
    244				 cmd->role_id, band,
    245				 req->ssids ? req->ssids[0].ssid : NULL,
    246				 req->ssids ? req->ssids[0].ssid_len : 0,
    247				 ies->ies[band],
    248				 ies->len[band],
    249				 ies->common_ies,
    250				 ies->common_ie_len,
    251				 true);
    252		if (ret < 0) {
    253			wl1271_error("2.4GHz PROBE request template failed");
    254			goto out;
    255		}
    256	}
    257
    258	if (cmd->active[1] || cmd->dfs) {
    259		u8 band = NL80211_BAND_5GHZ;
    260		ret = wl12xx_cmd_build_probe_req(wl, wlvif,
    261				 cmd->role_id, band,
    262				 req->ssids ? req->ssids[0].ssid : NULL,
    263				 req->ssids ? req->ssids[0].ssid_len : 0,
    264				 ies->ies[band],
    265				 ies->len[band],
    266				 ies->common_ies,
    267				 ies->common_ie_len,
    268				 true);
    269		if (ret < 0) {
    270			wl1271_error("5GHz PROBE request template failed");
    271			goto out;
    272		}
    273	}
    274
    275	wl1271_dump(DEBUG_SCAN, "SCAN: ", cmd, sizeof(*cmd));
    276
    277	ret = wl1271_cmd_send(wl, CMD_SCAN, cmd, sizeof(*cmd), 0);
    278	if (ret < 0) {
    279		wl1271_error("SCAN failed");
    280		goto out;
    281	}
    282
    283out:
    284	kfree(cmd_channels);
    285	kfree(cmd);
    286	return ret;
    287}
    288
    289int wl18xx_sched_scan_start(struct wl1271 *wl, struct wl12xx_vif *wlvif,
    290			    struct cfg80211_sched_scan_request *req,
    291			    struct ieee80211_scan_ies *ies)
    292{
    293	return wl18xx_scan_sched_scan_config(wl, wlvif, req, ies);
    294}
    295
    296static int __wl18xx_scan_stop(struct wl1271 *wl, struct wl12xx_vif *wlvif,
    297			       u8 scan_type)
    298{
    299	struct wl18xx_cmd_scan_stop *stop;
    300	int ret;
    301
    302	wl1271_debug(DEBUG_CMD, "cmd periodic scan stop");
    303
    304	stop = kzalloc(sizeof(*stop), GFP_KERNEL);
    305	if (!stop) {
    306		wl1271_error("failed to alloc memory to send sched scan stop");
    307		return -ENOMEM;
    308	}
    309
    310	stop->role_id = wlvif->role_id;
    311	stop->scan_type = scan_type;
    312
    313	ret = wl1271_cmd_send(wl, CMD_STOP_SCAN, stop, sizeof(*stop), 0);
    314	if (ret < 0) {
    315		wl1271_error("failed to send sched scan stop command");
    316		goto out_free;
    317	}
    318
    319out_free:
    320	kfree(stop);
    321	return ret;
    322}
    323
    324void wl18xx_scan_sched_scan_stop(struct wl1271 *wl, struct wl12xx_vif *wlvif)
    325{
    326	__wl18xx_scan_stop(wl, wlvif, SCAN_TYPE_PERIODIC);
    327}
    328int wl18xx_scan_start(struct wl1271 *wl, struct wl12xx_vif *wlvif,
    329		      struct cfg80211_scan_request *req)
    330{
    331	return wl18xx_scan_send(wl, wlvif, req);
    332}
    333
    334int wl18xx_scan_stop(struct wl1271 *wl, struct wl12xx_vif *wlvif)
    335{
    336	return __wl18xx_scan_stop(wl, wlvif, SCAN_TYPE_SEARCH);
    337}