mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2024-09-05 18:39:59 +00:00
wifi: rtw89: split scan including lots of channels
The size limit of H2C commands is 2048. With regulatory that enables U-NII-6 ~ UNII-8 channels, channel list length combining with channel info length will exceed that. Split the channel list to parts and do scan multiple times to workaround that. Signed-off-by: Po-Hao Huang <phhuang@realtek.com> Signed-off-by: Ping-Ke Shih <pkshih@realtek.com> Signed-off-by: Kalle Valo <kvalo@kernel.org> Link: https://lore.kernel.org/r/20220908051257.25353-10-pkshih@realtek.com
This commit is contained in:
parent
3a1e7cb16d
commit
bd1056d48a
4 changed files with 38 additions and 5 deletions
|
@ -3318,6 +3318,7 @@ struct rtw89_hw_scan_info {
|
|||
u8 op_chan;
|
||||
u8 op_bw;
|
||||
u8 op_band;
|
||||
u32 last_chan_idx;
|
||||
};
|
||||
|
||||
enum rtw89_phy_bb_gain_band {
|
||||
|
@ -3744,6 +3745,16 @@ static inline struct ieee80211_vif *rtwvif_to_vif(struct rtw89_vif *rtwvif)
|
|||
return container_of(p, struct ieee80211_vif, drv_priv);
|
||||
}
|
||||
|
||||
static inline struct ieee80211_vif *rtwvif_to_vif_safe(struct rtw89_vif *rtwvif)
|
||||
{
|
||||
return rtwvif ? rtwvif_to_vif(rtwvif) : NULL;
|
||||
}
|
||||
|
||||
static inline struct rtw89_vif *vif_to_rtwvif_safe(struct ieee80211_vif *vif)
|
||||
{
|
||||
return vif ? (struct rtw89_vif *)vif->drv_priv : NULL;
|
||||
}
|
||||
|
||||
static inline struct ieee80211_sta *rtwsta_to_sta(struct rtw89_sta *rtwsta)
|
||||
{
|
||||
void *p = rtwsta;
|
||||
|
|
|
@ -2451,13 +2451,16 @@ static int rtw89_hw_scan_add_chan_list(struct rtw89_dev *rtwdev,
|
|||
struct ieee80211_channel *channel;
|
||||
struct list_head chan_list;
|
||||
bool random_seq = req->flags & NL80211_SCAN_FLAG_RANDOM_SN;
|
||||
int list_len = req->n_channels, off_chan_time = 0;
|
||||
int list_len, off_chan_time = 0;
|
||||
enum rtw89_chan_type type;
|
||||
int ret = 0, i;
|
||||
int ret = 0;
|
||||
u32 idx;
|
||||
|
||||
INIT_LIST_HEAD(&chan_list);
|
||||
for (i = 0; i < req->n_channels; i++) {
|
||||
channel = req->channels[i];
|
||||
for (idx = rtwdev->scan_info.last_chan_idx, list_len = 0;
|
||||
idx < req->n_channels && list_len < RTW89_SCAN_LIST_LIMIT;
|
||||
idx++, list_len++) {
|
||||
channel = req->channels[idx];
|
||||
ch_info = kzalloc(sizeof(*ch_info), GFP_KERNEL);
|
||||
if (!ch_info) {
|
||||
ret = -ENOMEM;
|
||||
|
@ -2498,6 +2501,7 @@ static int rtw89_hw_scan_add_chan_list(struct rtw89_dev *rtwdev,
|
|||
list_add_tail(&ch_info->list, &chan_list);
|
||||
off_chan_time += ch_info->period;
|
||||
}
|
||||
rtwdev->scan_info.last_chan_idx = idx;
|
||||
ret = rtw89_fw_h2c_scan_list_offload(rtwdev, list_len, &chan_list);
|
||||
|
||||
out:
|
||||
|
@ -2532,6 +2536,7 @@ void rtw89_hw_scan_start(struct rtw89_dev *rtwdev, struct ieee80211_vif *vif,
|
|||
u8 mac_addr[ETH_ALEN];
|
||||
|
||||
rtwdev->scan_info.scanning_vif = vif;
|
||||
rtwdev->scan_info.last_chan_idx = 0;
|
||||
rtwvif->scan_ies = &scan_req->ies;
|
||||
rtwvif->scan_req = req;
|
||||
ieee80211_stop_queues(rtwdev->hw);
|
||||
|
@ -2579,6 +2584,7 @@ void rtw89_hw_scan_complete(struct rtw89_dev *rtwdev, struct ieee80211_vif *vif,
|
|||
rtwvif = (struct rtw89_vif *)vif->drv_priv;
|
||||
rtwvif->scan_req = NULL;
|
||||
rtwvif->scan_ies = NULL;
|
||||
rtwdev->scan_info.last_chan_idx = 0;
|
||||
rtwdev->scan_info.scanning_vif = NULL;
|
||||
|
||||
if (rtwvif->net_type != RTW89_NET_TYPE_NO_LINK)
|
||||
|
|
|
@ -188,6 +188,7 @@ struct rtw89_h2creg_sch_tx_en {
|
|||
u16 rsvd:15;
|
||||
} __packed;
|
||||
|
||||
#define RTW89_H2C_MAX_SIZE 2048
|
||||
#define RTW89_CHANNEL_TIME 45
|
||||
#define RTW89_DFS_CHAN_TIME 105
|
||||
#define RTW89_OFF_CHAN_TIME 100
|
||||
|
@ -198,6 +199,9 @@ struct rtw89_h2creg_sch_tx_en {
|
|||
#define RTW89_SCANOFLD_PKT_NONE 0xFF
|
||||
#define RTW89_SCANOFLD_DEBUG_MASK 0x1F
|
||||
#define RTW89_MAC_CHINFO_SIZE 24
|
||||
#define RTW89_SCAN_LIST_GUARD 4
|
||||
#define RTW89_SCAN_LIST_LIMIT \
|
||||
((RTW89_H2C_MAX_SIZE / RTW89_MAC_CHINFO_SIZE) - RTW89_SCAN_LIST_GUARD)
|
||||
|
||||
struct rtw89_mac_chinfo {
|
||||
u8 period;
|
||||
|
|
|
@ -3734,9 +3734,12 @@ rtw89_mac_c2h_scanofld_rsp(struct rtw89_dev *rtwdev, struct sk_buff *c2h,
|
|||
u32 len)
|
||||
{
|
||||
struct ieee80211_vif *vif = rtwdev->scan_info.scanning_vif;
|
||||
struct rtw89_vif *rtwvif = vif_to_rtwvif_safe(vif);
|
||||
struct rtw89_chan new;
|
||||
u8 reason, status, tx_fail, band, actual_period;
|
||||
u32 last_chan = rtwdev->scan_info.last_chan_idx;
|
||||
u16 chan;
|
||||
int ret;
|
||||
|
||||
tx_fail = RTW89_GET_MAC_C2H_SCANOFLD_TX_FAIL(c2h->data);
|
||||
status = RTW89_GET_MAC_C2H_SCANOFLD_STATUS(c2h->data);
|
||||
|
@ -3758,7 +3761,16 @@ rtw89_mac_c2h_scanofld_rsp(struct rtw89_dev *rtwdev, struct sk_buff *c2h,
|
|||
ieee80211_stop_queues(rtwdev->hw);
|
||||
return;
|
||||
case RTW89_SCAN_END_SCAN_NOTIFY:
|
||||
rtw89_hw_scan_complete(rtwdev, vif, false);
|
||||
if (rtwvif && rtwvif->scan_req &&
|
||||
last_chan < rtwvif->scan_req->n_channels) {
|
||||
ret = rtw89_hw_scan_offload(rtwdev, vif, true);
|
||||
if (ret) {
|
||||
rtw89_hw_scan_abort(rtwdev, vif);
|
||||
rtw89_warn(rtwdev, "HW scan failed: %d\n", ret);
|
||||
}
|
||||
} else {
|
||||
rtw89_hw_scan_complete(rtwdev, vif, false);
|
||||
}
|
||||
break;
|
||||
case RTW89_SCAN_ENTER_CH_NOTIFY:
|
||||
rtw89_chan_create(&new, chan, chan, band, RTW89_CHANNEL_WIDTH_20);
|
||||
|
|
Loading…
Reference in a new issue