// SPDX-License-Identifier: GPL-2.0-only
/*
 * Scan related functions.
 *
 * Copyright (c) 2017-2020, Silicon Laboratories, Inc.
 * Copyright (c) 2010, ST-Ericsson
 */
#include <net/mac80211.h>

#include "scan.h"
#include "wfx.h"
#include "sta.h"
#include "hif_tx_mib.h"

static void wfx_ieee80211_scan_completed_compat(struct ieee80211_hw *hw, bool aborted)
{
	struct cfg80211_scan_info info = {
		.aborted = aborted,
	};

	ieee80211_scan_completed(hw, &info);
}

static int update_probe_tmpl(struct wfx_vif *wvif, struct cfg80211_scan_request *req)
{
	struct ieee80211_vif *vif = wvif_to_vif(wvif);
	struct sk_buff *skb;

	skb = ieee80211_probereq_get(wvif->wdev->hw, vif->addr, NULL, 0,
				     req->ie_len);
	if (!skb)
		return -ENOMEM;

	skb_put_data(skb, req->ie, req->ie_len);
	wfx_hif_set_template_frame(wvif, skb, HIF_TMPLT_PRBREQ, 0);
	dev_kfree_skb(skb);
	return 0;
}

static int send_scan_req(struct wfx_vif *wvif, struct cfg80211_scan_request *req, int start_idx)
{
	struct ieee80211_vif *vif = wvif_to_vif(wvif);
	struct ieee80211_channel *ch_start, *ch_cur;
	int i, ret;

	for (i = start_idx; i < req->n_channels; i++) {
		ch_start = req->channels[start_idx];
		ch_cur = req->channels[i];
		WARN(ch_cur->band != NL80211_BAND_2GHZ, "band not supported");
		if (ch_cur->max_power != ch_start->max_power)
			break;
		if ((ch_cur->flags ^ ch_start->flags) & IEEE80211_CHAN_NO_IR)
			break;
	}
	wfx_tx_lock_flush(wvif->wdev);
	wvif->scan_abort = false;
	reinit_completion(&wvif->scan_complete);
	ret = wfx_hif_scan(wvif, req, start_idx, i - start_idx);
	if (ret) {
		wfx_tx_unlock(wvif->wdev);
		return -EIO;
	}
	ret = wait_for_completion_timeout(&wvif->scan_complete, 1 * HZ);
	if (!ret) {
		wfx_hif_stop_scan(wvif);
		ret = wait_for_completion_timeout(&wvif->scan_complete, 1 * HZ);
		dev_dbg(wvif->wdev->dev, "scan timeout (%d channels done)\n",
			wvif->scan_nb_chan_done);
	}
	if (!ret) {
		dev_err(wvif->wdev->dev, "scan didn't stop\n");
		ret = -ETIMEDOUT;
	} else if (wvif->scan_abort) {
		dev_notice(wvif->wdev->dev, "scan abort\n");
		ret = -ECONNABORTED;
	} else if (wvif->scan_nb_chan_done > i - start_idx) {
		ret = -EIO;
	} else {
		ret = wvif->scan_nb_chan_done;
	}
	if (req->channels[start_idx]->max_power != vif->bss_conf.txpower)
		wfx_hif_set_output_power(wvif, vif->bss_conf.txpower);
	wfx_tx_unlock(wvif->wdev);
	return ret;
}

/* It is not really necessary to run scan request asynchronously. However,
 * there is a bug in "iw scan" when ieee80211_scan_completed() is called before
 * wfx_hw_scan() return
 */
void wfx_hw_scan_work(struct work_struct *work)
{
	struct wfx_vif *wvif = container_of(work, struct wfx_vif, scan_work);
	struct ieee80211_scan_request *hw_req = wvif->scan_req;
	int chan_cur, ret, err;

	mutex_lock(&wvif->wdev->conf_mutex);
	mutex_lock(&wvif->scan_lock);
	if (wvif->join_in_progress) {
		dev_info(wvif->wdev->dev, "abort in-progress REQ_JOIN");
		wfx_reset(wvif);
	}
	update_probe_tmpl(wvif, &hw_req->req);
	chan_cur = 0;
	err = 0;
	do {
		ret = send_scan_req(wvif, &hw_req->req, chan_cur);
		if (ret > 0) {
			chan_cur += ret;
			err = 0;
		}
		if (!ret)
			err++;
		if (err > 2) {
			dev_err(wvif->wdev->dev, "scan has not been able to start\n");
			ret = -ETIMEDOUT;
		}
	} while (ret >= 0 && chan_cur < hw_req->req.n_channels);
	mutex_unlock(&wvif->scan_lock);
	mutex_unlock(&wvif->wdev->conf_mutex);
	wfx_ieee80211_scan_completed_compat(wvif->wdev->hw, ret < 0);
}

int wfx_hw_scan(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
		struct ieee80211_scan_request *hw_req)
{
	struct wfx_vif *wvif = (struct wfx_vif *)vif->drv_priv;

	WARN_ON(hw_req->req.n_channels > HIF_API_MAX_NB_CHANNELS);
	wvif->scan_req = hw_req;
	schedule_work(&wvif->scan_work);
	return 0;
}

void wfx_cancel_hw_scan(struct ieee80211_hw *hw, struct ieee80211_vif *vif)
{
	struct wfx_vif *wvif = (struct wfx_vif *)vif->drv_priv;

	wvif->scan_abort = true;
	wfx_hif_stop_scan(wvif);
}

void wfx_scan_complete(struct wfx_vif *wvif, int nb_chan_done)
{
	wvif->scan_nb_chan_done = nb_chan_done;
	complete(&wvif->scan_complete);
}
