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 (12780B)


      1// SPDX-License-Identifier: GPL-2.0-only
      2/*
      3 * Scan implementation for ST-Ericsson CW1200 mac80211 drivers
      4 *
      5 * Copyright (c) 2010, ST-Ericsson
      6 * Author: Dmitry Tarnyagin <dmitry.tarnyagin@lockless.no>
      7 */
      8
      9#include <linux/sched.h>
     10#include "cw1200.h"
     11#include "scan.h"
     12#include "sta.h"
     13#include "pm.h"
     14
     15static void cw1200_scan_restart_delayed(struct cw1200_common *priv);
     16
     17static int cw1200_scan_start(struct cw1200_common *priv, struct wsm_scan *scan)
     18{
     19	int ret, i;
     20	int tmo = 2000;
     21
     22	switch (priv->join_status) {
     23	case CW1200_JOIN_STATUS_PRE_STA:
     24	case CW1200_JOIN_STATUS_JOINING:
     25		return -EBUSY;
     26	default:
     27		break;
     28	}
     29
     30	wiphy_dbg(priv->hw->wiphy, "[SCAN] hw req, type %d, %d channels, flags: 0x%x.\n",
     31		  scan->type, scan->num_channels, scan->flags);
     32
     33	for (i = 0; i < scan->num_channels; ++i)
     34		tmo += scan->ch[i].max_chan_time + 10;
     35
     36	cancel_delayed_work_sync(&priv->clear_recent_scan_work);
     37	atomic_set(&priv->scan.in_progress, 1);
     38	atomic_set(&priv->recent_scan, 1);
     39	cw1200_pm_stay_awake(&priv->pm_state, msecs_to_jiffies(tmo));
     40	queue_delayed_work(priv->workqueue, &priv->scan.timeout,
     41			   msecs_to_jiffies(tmo));
     42	ret = wsm_scan(priv, scan);
     43	if (ret) {
     44		atomic_set(&priv->scan.in_progress, 0);
     45		cancel_delayed_work_sync(&priv->scan.timeout);
     46		cw1200_scan_restart_delayed(priv);
     47	}
     48	return ret;
     49}
     50
     51int cw1200_hw_scan(struct ieee80211_hw *hw,
     52		   struct ieee80211_vif *vif,
     53		   struct ieee80211_scan_request *hw_req)
     54{
     55	struct cw1200_common *priv = hw->priv;
     56	struct cfg80211_scan_request *req = &hw_req->req;
     57	struct wsm_template_frame frame = {
     58		.frame_type = WSM_FRAME_TYPE_PROBE_REQUEST,
     59	};
     60	int i, ret;
     61
     62	if (!priv->vif)
     63		return -EINVAL;
     64
     65	/* Scan when P2P_GO corrupt firmware MiniAP mode */
     66	if (priv->join_status == CW1200_JOIN_STATUS_AP)
     67		return -EOPNOTSUPP;
     68
     69	if (req->n_ssids == 1 && !req->ssids[0].ssid_len)
     70		req->n_ssids = 0;
     71
     72	wiphy_dbg(hw->wiphy, "[SCAN] Scan request for %d SSIDs.\n",
     73		  req->n_ssids);
     74
     75	if (req->n_ssids > WSM_SCAN_MAX_NUM_OF_SSIDS)
     76		return -EINVAL;
     77
     78	frame.skb = ieee80211_probereq_get(hw, priv->vif->addr, NULL, 0,
     79		req->ie_len);
     80	if (!frame.skb)
     81		return -ENOMEM;
     82
     83	if (req->ie_len)
     84		skb_put_data(frame.skb, req->ie, req->ie_len);
     85
     86	/* will be unlocked in cw1200_scan_work() */
     87	down(&priv->scan.lock);
     88	mutex_lock(&priv->conf_mutex);
     89
     90	ret = wsm_set_template_frame(priv, &frame);
     91	if (!ret) {
     92		/* Host want to be the probe responder. */
     93		ret = wsm_set_probe_responder(priv, true);
     94	}
     95	if (ret) {
     96		mutex_unlock(&priv->conf_mutex);
     97		up(&priv->scan.lock);
     98		dev_kfree_skb(frame.skb);
     99		return ret;
    100	}
    101
    102	wsm_lock_tx(priv);
    103
    104	BUG_ON(priv->scan.req);
    105	priv->scan.req = req;
    106	priv->scan.n_ssids = 0;
    107	priv->scan.status = 0;
    108	priv->scan.begin = &req->channels[0];
    109	priv->scan.curr = priv->scan.begin;
    110	priv->scan.end = &req->channels[req->n_channels];
    111	priv->scan.output_power = priv->output_power;
    112
    113	for (i = 0; i < req->n_ssids; ++i) {
    114		struct wsm_ssid *dst = &priv->scan.ssids[priv->scan.n_ssids];
    115		memcpy(&dst->ssid[0], req->ssids[i].ssid, sizeof(dst->ssid));
    116		dst->length = req->ssids[i].ssid_len;
    117		++priv->scan.n_ssids;
    118	}
    119
    120	mutex_unlock(&priv->conf_mutex);
    121	dev_kfree_skb(frame.skb);
    122	queue_work(priv->workqueue, &priv->scan.work);
    123	return 0;
    124}
    125
    126void cw1200_scan_work(struct work_struct *work)
    127{
    128	struct cw1200_common *priv = container_of(work, struct cw1200_common,
    129							scan.work);
    130	struct ieee80211_channel **it;
    131	struct wsm_scan scan = {
    132		.type = WSM_SCAN_TYPE_FOREGROUND,
    133		.flags = WSM_SCAN_FLAG_SPLIT_METHOD,
    134	};
    135	bool first_run = (priv->scan.begin == priv->scan.curr &&
    136			  priv->scan.begin != priv->scan.end);
    137	int i;
    138
    139	if (first_run) {
    140		/* Firmware gets crazy if scan request is sent
    141		 * when STA is joined but not yet associated.
    142		 * Force unjoin in this case.
    143		 */
    144		if (cancel_delayed_work_sync(&priv->join_timeout) > 0)
    145			cw1200_join_timeout(&priv->join_timeout.work);
    146	}
    147
    148	mutex_lock(&priv->conf_mutex);
    149
    150	if (first_run) {
    151		if (priv->join_status == CW1200_JOIN_STATUS_STA &&
    152		    !(priv->powersave_mode.mode & WSM_PSM_PS)) {
    153			struct wsm_set_pm pm = priv->powersave_mode;
    154			pm.mode = WSM_PSM_PS;
    155			cw1200_set_pm(priv, &pm);
    156		} else if (priv->join_status == CW1200_JOIN_STATUS_MONITOR) {
    157			/* FW bug: driver has to restart p2p-dev mode
    158			 * after scan
    159			 */
    160			cw1200_disable_listening(priv);
    161		}
    162	}
    163
    164	if (!priv->scan.req || (priv->scan.curr == priv->scan.end)) {
    165		struct cfg80211_scan_info info = {
    166			.aborted = priv->scan.status ? 1 : 0,
    167		};
    168
    169		if (priv->scan.output_power != priv->output_power)
    170			wsm_set_output_power(priv, priv->output_power * 10);
    171		if (priv->join_status == CW1200_JOIN_STATUS_STA &&
    172		    !(priv->powersave_mode.mode & WSM_PSM_PS))
    173			cw1200_set_pm(priv, &priv->powersave_mode);
    174
    175		if (priv->scan.status < 0)
    176			wiphy_warn(priv->hw->wiphy,
    177				   "[SCAN] Scan failed (%d).\n",
    178				   priv->scan.status);
    179		else if (priv->scan.req)
    180			wiphy_dbg(priv->hw->wiphy,
    181				  "[SCAN] Scan completed.\n");
    182		else
    183			wiphy_dbg(priv->hw->wiphy,
    184				  "[SCAN] Scan canceled.\n");
    185
    186		priv->scan.req = NULL;
    187		cw1200_scan_restart_delayed(priv);
    188		wsm_unlock_tx(priv);
    189		mutex_unlock(&priv->conf_mutex);
    190		ieee80211_scan_completed(priv->hw, &info);
    191		up(&priv->scan.lock);
    192		return;
    193	} else {
    194		struct ieee80211_channel *first = *priv->scan.curr;
    195		for (it = priv->scan.curr + 1, i = 1;
    196		     it != priv->scan.end && i < WSM_SCAN_MAX_NUM_OF_CHANNELS;
    197		     ++it, ++i) {
    198			if ((*it)->band != first->band)
    199				break;
    200			if (((*it)->flags ^ first->flags) &
    201					IEEE80211_CHAN_NO_IR)
    202				break;
    203			if (!(first->flags & IEEE80211_CHAN_NO_IR) &&
    204			    (*it)->max_power != first->max_power)
    205				break;
    206		}
    207		scan.band = first->band;
    208
    209		if (priv->scan.req->no_cck)
    210			scan.max_tx_rate = WSM_TRANSMIT_RATE_6;
    211		else
    212			scan.max_tx_rate = WSM_TRANSMIT_RATE_1;
    213		scan.num_probes =
    214			(first->flags & IEEE80211_CHAN_NO_IR) ? 0 : 2;
    215		scan.num_ssids = priv->scan.n_ssids;
    216		scan.ssids = &priv->scan.ssids[0];
    217		scan.num_channels = it - priv->scan.curr;
    218		/* TODO: Is it optimal? */
    219		scan.probe_delay = 100;
    220		/* It is not stated in WSM specification, however
    221		 * FW team says that driver may not use FG scan
    222		 * when joined.
    223		 */
    224		if (priv->join_status == CW1200_JOIN_STATUS_STA) {
    225			scan.type = WSM_SCAN_TYPE_BACKGROUND;
    226			scan.flags = WSM_SCAN_FLAG_FORCE_BACKGROUND;
    227		}
    228		scan.ch = kcalloc(it - priv->scan.curr,
    229				  sizeof(struct wsm_scan_ch),
    230				  GFP_KERNEL);
    231		if (!scan.ch) {
    232			priv->scan.status = -ENOMEM;
    233			goto fail;
    234		}
    235		for (i = 0; i < scan.num_channels; ++i) {
    236			scan.ch[i].number = priv->scan.curr[i]->hw_value;
    237			if (priv->scan.curr[i]->flags & IEEE80211_CHAN_NO_IR) {
    238				scan.ch[i].min_chan_time = 50;
    239				scan.ch[i].max_chan_time = 100;
    240			} else {
    241				scan.ch[i].min_chan_time = 10;
    242				scan.ch[i].max_chan_time = 25;
    243			}
    244		}
    245		if (!(first->flags & IEEE80211_CHAN_NO_IR) &&
    246		    priv->scan.output_power != first->max_power) {
    247			priv->scan.output_power = first->max_power;
    248			wsm_set_output_power(priv,
    249					     priv->scan.output_power * 10);
    250		}
    251		priv->scan.status = cw1200_scan_start(priv, &scan);
    252		kfree(scan.ch);
    253		if (priv->scan.status)
    254			goto fail;
    255		priv->scan.curr = it;
    256	}
    257	mutex_unlock(&priv->conf_mutex);
    258	return;
    259
    260fail:
    261	priv->scan.curr = priv->scan.end;
    262	mutex_unlock(&priv->conf_mutex);
    263	queue_work(priv->workqueue, &priv->scan.work);
    264	return;
    265}
    266
    267static void cw1200_scan_restart_delayed(struct cw1200_common *priv)
    268{
    269	/* FW bug: driver has to restart p2p-dev mode after scan. */
    270	if (priv->join_status == CW1200_JOIN_STATUS_MONITOR) {
    271		cw1200_enable_listening(priv);
    272		cw1200_update_filtering(priv);
    273	}
    274
    275	if (priv->delayed_unjoin) {
    276		priv->delayed_unjoin = false;
    277		if (queue_work(priv->workqueue, &priv->unjoin_work) <= 0)
    278			wsm_unlock_tx(priv);
    279	} else if (priv->delayed_link_loss) {
    280			wiphy_dbg(priv->hw->wiphy, "[CQM] Requeue BSS loss.\n");
    281			priv->delayed_link_loss = 0;
    282			cw1200_cqm_bssloss_sm(priv, 1, 0, 0);
    283	}
    284}
    285
    286static void cw1200_scan_complete(struct cw1200_common *priv)
    287{
    288	queue_delayed_work(priv->workqueue, &priv->clear_recent_scan_work, HZ);
    289	if (priv->scan.direct_probe) {
    290		wiphy_dbg(priv->hw->wiphy, "[SCAN] Direct probe complete.\n");
    291		cw1200_scan_restart_delayed(priv);
    292		priv->scan.direct_probe = 0;
    293		up(&priv->scan.lock);
    294		wsm_unlock_tx(priv);
    295	} else {
    296		cw1200_scan_work(&priv->scan.work);
    297	}
    298}
    299
    300void cw1200_scan_failed_cb(struct cw1200_common *priv)
    301{
    302	if (priv->mode == NL80211_IFTYPE_UNSPECIFIED)
    303		/* STA is stopped. */
    304		return;
    305
    306	if (cancel_delayed_work_sync(&priv->scan.timeout) > 0) {
    307		priv->scan.status = -EIO;
    308		queue_delayed_work(priv->workqueue, &priv->scan.timeout, 0);
    309	}
    310}
    311
    312
    313void cw1200_scan_complete_cb(struct cw1200_common *priv,
    314				struct wsm_scan_complete *arg)
    315{
    316	if (priv->mode == NL80211_IFTYPE_UNSPECIFIED)
    317		/* STA is stopped. */
    318		return;
    319
    320	if (cancel_delayed_work_sync(&priv->scan.timeout) > 0) {
    321		priv->scan.status = 1;
    322		queue_delayed_work(priv->workqueue, &priv->scan.timeout, 0);
    323	}
    324}
    325
    326void cw1200_clear_recent_scan_work(struct work_struct *work)
    327{
    328	struct cw1200_common *priv =
    329		container_of(work, struct cw1200_common,
    330			     clear_recent_scan_work.work);
    331	atomic_xchg(&priv->recent_scan, 0);
    332}
    333
    334void cw1200_scan_timeout(struct work_struct *work)
    335{
    336	struct cw1200_common *priv =
    337		container_of(work, struct cw1200_common, scan.timeout.work);
    338	if (atomic_xchg(&priv->scan.in_progress, 0)) {
    339		if (priv->scan.status > 0) {
    340			priv->scan.status = 0;
    341		} else if (!priv->scan.status) {
    342			wiphy_warn(priv->hw->wiphy,
    343				   "Timeout waiting for scan complete notification.\n");
    344			priv->scan.status = -ETIMEDOUT;
    345			priv->scan.curr = priv->scan.end;
    346			wsm_stop_scan(priv);
    347		}
    348		cw1200_scan_complete(priv);
    349	}
    350}
    351
    352void cw1200_probe_work(struct work_struct *work)
    353{
    354	struct cw1200_common *priv =
    355		container_of(work, struct cw1200_common, scan.probe_work.work);
    356	u8 queue_id = cw1200_queue_get_queue_id(priv->pending_frame_id);
    357	struct cw1200_queue *queue = &priv->tx_queue[queue_id];
    358	const struct cw1200_txpriv *txpriv;
    359	struct wsm_tx *wsm;
    360	struct wsm_template_frame frame = {
    361		.frame_type = WSM_FRAME_TYPE_PROBE_REQUEST,
    362	};
    363	struct wsm_ssid ssids[1] = {{
    364		.length = 0,
    365	} };
    366	struct wsm_scan_ch ch[1] = {{
    367		.min_chan_time = 0,
    368		.max_chan_time = 10,
    369	} };
    370	struct wsm_scan scan = {
    371		.type = WSM_SCAN_TYPE_FOREGROUND,
    372		.num_probes = 1,
    373		.probe_delay = 0,
    374		.num_channels = 1,
    375		.ssids = ssids,
    376		.ch = ch,
    377	};
    378	u8 *ies;
    379	size_t ies_len;
    380	int ret;
    381
    382	wiphy_dbg(priv->hw->wiphy, "[SCAN] Direct probe work.\n");
    383
    384	mutex_lock(&priv->conf_mutex);
    385	if (down_trylock(&priv->scan.lock)) {
    386		/* Scan is already in progress. Requeue self. */
    387		schedule();
    388		queue_delayed_work(priv->workqueue, &priv->scan.probe_work,
    389				   msecs_to_jiffies(100));
    390		mutex_unlock(&priv->conf_mutex);
    391		return;
    392	}
    393
    394	/* Make sure we still have a pending probe req */
    395	if (cw1200_queue_get_skb(queue,	priv->pending_frame_id,
    396				 &frame.skb, &txpriv)) {
    397		up(&priv->scan.lock);
    398		mutex_unlock(&priv->conf_mutex);
    399		wsm_unlock_tx(priv);
    400		return;
    401	}
    402	wsm = (struct wsm_tx *)frame.skb->data;
    403	scan.max_tx_rate = wsm->max_tx_rate;
    404	scan.band = (priv->channel->band == NL80211_BAND_5GHZ) ?
    405		WSM_PHY_BAND_5G : WSM_PHY_BAND_2_4G;
    406	if (priv->join_status == CW1200_JOIN_STATUS_STA ||
    407	    priv->join_status == CW1200_JOIN_STATUS_IBSS) {
    408		scan.type = WSM_SCAN_TYPE_BACKGROUND;
    409		scan.flags = WSM_SCAN_FLAG_FORCE_BACKGROUND;
    410	}
    411	ch[0].number = priv->channel->hw_value;
    412
    413	skb_pull(frame.skb, txpriv->offset);
    414
    415	ies = &frame.skb->data[sizeof(struct ieee80211_hdr_3addr)];
    416	ies_len = frame.skb->len - sizeof(struct ieee80211_hdr_3addr);
    417
    418	if (ies_len) {
    419		u8 *ssidie =
    420			(u8 *)cfg80211_find_ie(WLAN_EID_SSID, ies, ies_len);
    421		if (ssidie && ssidie[1] && ssidie[1] <= sizeof(ssids[0].ssid)) {
    422			u8 *nextie = &ssidie[2 + ssidie[1]];
    423			/* Remove SSID from the IE list. It has to be provided
    424			 * as a separate argument in cw1200_scan_start call
    425			 */
    426
    427			/* Store SSID localy */
    428			ssids[0].length = ssidie[1];
    429			memcpy(ssids[0].ssid, &ssidie[2], ssids[0].length);
    430			scan.num_ssids = 1;
    431
    432			/* Remove SSID from IE list */
    433			ssidie[1] = 0;
    434			memmove(&ssidie[2], nextie, &ies[ies_len] - nextie);
    435			skb_trim(frame.skb, frame.skb->len - ssids[0].length);
    436		}
    437	}
    438
    439	/* FW bug: driver has to restart p2p-dev mode after scan */
    440	if (priv->join_status == CW1200_JOIN_STATUS_MONITOR)
    441		cw1200_disable_listening(priv);
    442	ret = wsm_set_template_frame(priv, &frame);
    443	priv->scan.direct_probe = 1;
    444	if (!ret) {
    445		wsm_flush_tx(priv);
    446		ret = cw1200_scan_start(priv, &scan);
    447	}
    448	mutex_unlock(&priv->conf_mutex);
    449
    450	skb_push(frame.skb, txpriv->offset);
    451	if (!ret)
    452		IEEE80211_SKB_CB(frame.skb)->flags |= IEEE80211_TX_STAT_ACK;
    453	BUG_ON(cw1200_queue_remove(queue, priv->pending_frame_id));
    454
    455	if (ret) {
    456		priv->scan.direct_probe = 0;
    457		up(&priv->scan.lock);
    458		wsm_unlock_tx(priv);
    459	}
    460
    461	return;
    462}