diff options
| author | Jakub Kicinski <kuba@kernel.org> | 2022-05-03 17:27:49 -0700 |
|---|---|---|
| committer | Jakub Kicinski <kuba@kernel.org> | 2022-05-03 17:27:51 -0700 |
| commit | f43f0cd2d9b07caf38d744701b0b54d4244da8cc (patch) | |
| tree | 8d542627e712f320b6b4d4c2670a1af529e04001 /drivers/net/wireless/silabs/wfx/scan.c | |
| parent | 58caed3dacb4354a25a1aa8d2febc3e9648ba1f4 (diff) | |
| parent | f39af96d352dd4f36a4a43601ea90561e17e5ca6 (diff) | |
Merge tag 'wireless-next-2022-05-03' of git://git.kernel.org/pub/scm/linux/kernel/git/wireless/wireless-next
Kalle Valo says:
====================
wireless-next patches for v5.19
First set of patches for v5.19 and this is a big one. We have two new
drivers, a change in mac80211 STA API affecting most drivers and
ath11k getting support for WCN6750. And as usual lots of fixes and
cleanups all over.
Major changes:
new drivers
- wfx: silicon labs devices
- plfxlc: pureLiFi X, XL, XC devices
mac80211
- host based BSS color collision detection
- prepare sta handling for IEEE 802.11be Multi-Link Operation (MLO) support
rtw88
- support TP-Link T2E devices
rtw89
- support firmware crash simulation
- preparation for 8852ce hardware support
ath11k
- Wake-on-WLAN support for QCA6390 and WCN6855
- device recovery (firmware restart) support for QCA6390 and WCN6855
- support setting Specific Absorption Rate (SAR) for WCN6855
- read country code from SMBIOS for WCN6855/QCA6390
- support for WCN6750
wcn36xx
- support for transmit rate reporting to user space
* tag 'wireless-next-2022-05-03' of git://git.kernel.org/pub/scm/linux/kernel/git/wireless/wireless-next: (228 commits)
rtw89: 8852c: rfk: add DPK
rtw89: 8852c: rfk: add IQK
rtw89: 8852c: rfk: add RX DCK
rtw89: 8852c: rfk: add RCK
rtw89: 8852c: rfk: add TSSI
rtw89: 8852c: rfk: add LCK
rtw89: 8852c: rfk: add DACK
rtw89: 8852c: rfk: add RFK tables
plfxlc: fix le16_to_cpu warning for beacon_interval
rtw88: remove a copy of the NAPI_POLL_WEIGHT define
carl9170: tx: fix an incorrect use of list iterator
wil6210: use NAPI_POLL_WEIGHT for napi budget
ath10k: remove a copy of the NAPI_POLL_WEIGHT define
ath11k: Add support for WCN6750 device
ath11k: Datapath changes to support WCN6750
ath11k: HAL changes to support WCN6750
ath11k: Add QMI changes for WCN6750
ath11k: Fetch device information via QMI for WCN6750
ath11k: Add register access logic for WCN6750
ath11k: Add HW params for WCN6750
...
====================
Link: https://lore.kernel.org/r/20220503153622.C1671C385A4@smtp.kernel.org
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
Diffstat (limited to 'drivers/net/wireless/silabs/wfx/scan.c')
| -rw-r--r-- | drivers/net/wireless/silabs/wfx/scan.c | 144 |
1 files changed, 144 insertions, 0 deletions
diff --git a/drivers/net/wireless/silabs/wfx/scan.c b/drivers/net/wireless/silabs/wfx/scan.c new file mode 100644 index 000000000000..7f34f0d322f9 --- /dev/null +++ b/drivers/net/wireless/silabs/wfx/scan.c @@ -0,0 +1,144 @@ +// 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 sk_buff *skb; + + skb = ieee80211_probereq_get(wvif->wdev->hw, wvif->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) +{ + int i, ret; + struct ieee80211_channel *ch_start, *ch_cur; + + 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 != wvif->vif->bss_conf.txpower) + wfx_hif_set_output_power(wvif, 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); +} |