2023-10-04 17:29:09

by Jérôme Pouiller

[permalink] [raw]
Subject: [PATCH v3 0/8] wfx: implement Remain On Channel

Hello,

Apart from the 3 first patch, this series implements Remain On Channel for
WF200 chips. The implementation is a bit twisted (I hijack the scan feature
to implements RoC). However, it has been extensively tested with
DPP/EasyConnect and I have not noticed any issue.

v3:
- Patch 5 and 6 has been squashed.
- Reordered patches 5 to 9. It was not so easy, but I guarantee the final
code is the same and every patch compile.
v2:
- Rebase on last stable tree

Jérôme Pouiller (8):
wifi: wfx: fix power_save setting when AP is stopped
wifi: wfx: relocate wfx_rate_mask_to_hw()
wifi: wfx: move wfx_skb_*() out of the header file
wifi: wfx: introduce hif_scan_uniq()
wifi: wfx: simplify exclusion between scan and Rx filters
wifi: wfx: scan_lock is global to the device
wifi: wfx: allow to send frames during ROC
wifi: wfx: implement wfx_remain_on_channel()

drivers/net/wireless/silabs/wfx/data_tx.c | 54 ++++++++++++++++---
drivers/net/wireless/silabs/wfx/data_tx.h | 21 ++------
drivers/net/wireless/silabs/wfx/hif_tx.c | 43 +++++++++++++++
drivers/net/wireless/silabs/wfx/hif_tx.h | 1 +
drivers/net/wireless/silabs/wfx/main.c | 5 ++
drivers/net/wireless/silabs/wfx/queue.c | 38 ++++++++++---
drivers/net/wireless/silabs/wfx/queue.h | 1 +
drivers/net/wireless/silabs/wfx/scan.c | 66 ++++++++++++++++++++++-
drivers/net/wireless/silabs/wfx/scan.h | 6 +++
drivers/net/wireless/silabs/wfx/sta.c | 41 +++++---------
drivers/net/wireless/silabs/wfx/sta.h | 1 -
drivers/net/wireless/silabs/wfx/wfx.h | 8 +--
12 files changed, 218 insertions(+), 67 deletions(-)

--
2.39.2


2023-10-04 17:29:12

by Jérôme Pouiller

[permalink] [raw]
Subject: [PATCH v3 1/8] wifi: wfx: fix power_save setting when AP is stopped

The WF200 allow to start two network interfaces (one AP, one station) on
two different channels. Since magic does not exist, it only works if the
station interface enables power save.

Thus, the driver detects this case and enforce power save as necessary.

This patch fixes the case where the AP interface is stopped and it is no
more necessary to enforce power saving on the station interface.

Signed-off-by: Jérôme Pouiller <[email protected]>
---
drivers/net/wireless/silabs/wfx/sta.c | 5 +++++
1 file changed, 5 insertions(+)

diff --git a/drivers/net/wireless/silabs/wfx/sta.c b/drivers/net/wireless/silabs/wfx/sta.c
index 626dfb4b7a55d..9c0a11c277e97 100644
--- a/drivers/net/wireless/silabs/wfx/sta.c
+++ b/drivers/net/wireless/silabs/wfx/sta.c
@@ -402,7 +402,12 @@ void wfx_stop_ap(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
struct ieee80211_bss_conf *link_conf)
{
struct wfx_vif *wvif = (struct wfx_vif *)vif->drv_priv;
+ struct wfx_dev *wdev = wvif->wdev;

+ wvif = NULL;
+ while ((wvif = wvif_iterate(wdev, wvif)) != NULL)
+ wfx_update_pm(wvif);
+ wvif = (struct wfx_vif *)vif->drv_priv;
wfx_reset(wvif);
}

--
2.39.2

2023-10-04 17:29:17

by Jérôme Pouiller

[permalink] [raw]
Subject: [PATCH v3 3/8] wifi: wfx: move wfx_skb_*() out of the header file

There is no real reasons to keep these function in the header file.

Signed-off-by: Jérôme Pouiller <[email protected]>
---
drivers/net/wireless/silabs/wfx/data_tx.c | 18 ++++++++++++++++++
drivers/net/wireless/silabs/wfx/data_tx.h | 19 ++-----------------
2 files changed, 20 insertions(+), 17 deletions(-)

diff --git a/drivers/net/wireless/silabs/wfx/data_tx.c b/drivers/net/wireless/silabs/wfx/data_tx.c
index 6a5e52a96d183..ce2b5dcfd8d89 100644
--- a/drivers/net/wireless/silabs/wfx/data_tx.c
+++ b/drivers/net/wireless/silabs/wfx/data_tx.c
@@ -208,6 +208,24 @@ static bool wfx_is_action_back(struct ieee80211_hdr *hdr)
return true;
}

+struct wfx_tx_priv *wfx_skb_tx_priv(struct sk_buff *skb)
+{
+ struct ieee80211_tx_info *tx_info;
+
+ if (!skb)
+ return NULL;
+ tx_info = IEEE80211_SKB_CB(skb);
+ return (struct wfx_tx_priv *)tx_info->rate_driver_data;
+}
+
+struct wfx_hif_req_tx *wfx_skb_txreq(struct sk_buff *skb)
+{
+ struct wfx_hif_msg *hif = (struct wfx_hif_msg *)skb->data;
+ struct wfx_hif_req_tx *req = (struct wfx_hif_req_tx *)hif->body;
+
+ return req;
+}
+
static u8 wfx_tx_get_link_id(struct wfx_vif *wvif, struct ieee80211_sta *sta,
struct ieee80211_hdr *hdr)
{
diff --git a/drivers/net/wireless/silabs/wfx/data_tx.h b/drivers/net/wireless/silabs/wfx/data_tx.h
index 983470705e4bb..a5b80eacce39a 100644
--- a/drivers/net/wireless/silabs/wfx/data_tx.h
+++ b/drivers/net/wireless/silabs/wfx/data_tx.h
@@ -45,22 +45,7 @@ void wfx_tx(struct ieee80211_hw *hw, struct ieee80211_tx_control *control, struc
void wfx_tx_confirm_cb(struct wfx_dev *wdev, const struct wfx_hif_cnf_tx *arg);
void wfx_flush(struct ieee80211_hw *hw, struct ieee80211_vif *vif, u32 queues, bool drop);

-static inline struct wfx_tx_priv *wfx_skb_tx_priv(struct sk_buff *skb)
-{
- struct ieee80211_tx_info *tx_info;
-
- if (!skb)
- return NULL;
- tx_info = IEEE80211_SKB_CB(skb);
- return (struct wfx_tx_priv *)tx_info->rate_driver_data;
-}
-
-static inline struct wfx_hif_req_tx *wfx_skb_txreq(struct sk_buff *skb)
-{
- struct wfx_hif_msg *hif = (struct wfx_hif_msg *)skb->data;
- struct wfx_hif_req_tx *req = (struct wfx_hif_req_tx *)hif->body;
-
- return req;
-}
+struct wfx_tx_priv *wfx_skb_tx_priv(struct sk_buff *skb);
+struct wfx_hif_req_tx *wfx_skb_txreq(struct sk_buff *skb);

#endif
--
2.39.2

2023-10-04 17:29:23

by Jérôme Pouiller

[permalink] [raw]
Subject: [PATCH v3 6/8] wifi: wfx: scan_lock is global to the device

Currently, one scan_lock is associated to each vif. However, concurrent
scan on vifs is explicitly prohibited by the device. Currently,
scan_lock is associated with a vif but it is always locked with
conf_mutex (there is a case where conf_mutex is not associated to
scan_lock but scan_lock is tested on all interfaces). So concurrent scan
on vifs cannot happen.

So, this patch relocate scan_lock to the device and simplify the code.

Signed-off-by: Jérôme Pouiller <[email protected]>
---
drivers/net/wireless/silabs/wfx/main.c | 2 ++
drivers/net/wireless/silabs/wfx/scan.c | 4 ++--
drivers/net/wireless/silabs/wfx/sta.c | 11 +++--------
drivers/net/wireless/silabs/wfx/wfx.h | 3 +--
4 files changed, 8 insertions(+), 12 deletions(-)

diff --git a/drivers/net/wireless/silabs/wfx/main.c b/drivers/net/wireless/silabs/wfx/main.c
index ede822d771aaf..4bf16bceb0bbc 100644
--- a/drivers/net/wireless/silabs/wfx/main.c
+++ b/drivers/net/wireless/silabs/wfx/main.c
@@ -246,6 +246,7 @@ static void wfx_free_common(void *data)

mutex_destroy(&wdev->tx_power_loop_info_lock);
mutex_destroy(&wdev->rx_stats_lock);
+ mutex_destroy(&wdev->scan_lock);
mutex_destroy(&wdev->conf_mutex);
ieee80211_free_hw(wdev->hw);
}
@@ -314,6 +315,7 @@ struct wfx_dev *wfx_init_common(struct device *dev, const struct wfx_platform_da
gpiod_set_consumer_name(wdev->pdata.gpio_wakeup, "wfx wakeup");

mutex_init(&wdev->conf_mutex);
+ mutex_init(&wdev->scan_lock);
mutex_init(&wdev->rx_stats_lock);
mutex_init(&wdev->tx_power_loop_info_lock);
init_completion(&wdev->firmware_ready);
diff --git a/drivers/net/wireless/silabs/wfx/scan.c b/drivers/net/wireless/silabs/wfx/scan.c
index 16f619ed22e00..d6f98035f6844 100644
--- a/drivers/net/wireless/silabs/wfx/scan.c
+++ b/drivers/net/wireless/silabs/wfx/scan.c
@@ -95,7 +95,7 @@ void wfx_hw_scan_work(struct work_struct *work)
int chan_cur, ret, err;

mutex_lock(&wvif->wdev->conf_mutex);
- mutex_lock(&wvif->scan_lock);
+ mutex_lock(&wvif->wdev->scan_lock);
if (wvif->join_in_progress) {
dev_info(wvif->wdev->dev, "abort in-progress REQ_JOIN");
wfx_reset(wvif);
@@ -116,7 +116,7 @@ void wfx_hw_scan_work(struct work_struct *work)
ret = -ETIMEDOUT;
}
} while (ret >= 0 && chan_cur < hw_req->req.n_channels);
- mutex_unlock(&wvif->scan_lock);
+ mutex_unlock(&wvif->wdev->scan_lock);
mutex_unlock(&wvif->wdev->conf_mutex);
wfx_ieee80211_scan_completed_compat(wvif->wdev->hw, ret < 0);
}
diff --git a/drivers/net/wireless/silabs/wfx/sta.c b/drivers/net/wireless/silabs/wfx/sta.c
index cb03a5cf7ffa4..8533bad6caeae 100644
--- a/drivers/net/wireless/silabs/wfx/sta.c
+++ b/drivers/net/wireless/silabs/wfx/sta.c
@@ -97,7 +97,7 @@ void wfx_configure_filter(struct ieee80211_hw *hw, unsigned int changed_flags,
FIF_PROBE_REQ | FIF_PSPOLL;

/* Filters are ignored during the scan. No frames are filtered. */
- if (mutex_is_locked(&wvif->scan_lock))
+ if (mutex_is_locked(&wdev->scan_lock))
return;

mutex_lock(&wdev->conf_mutex);
@@ -621,18 +621,14 @@ int wfx_set_tim(struct ieee80211_hw *hw, struct ieee80211_sta *sta, bool set)

void wfx_suspend_resume_mc(struct wfx_vif *wvif, enum sta_notify_cmd notify_cmd)
{
- struct wfx_vif *wvif_it;
-
if (notify_cmd != STA_NOTIFY_AWAKE)
return;

/* Device won't be able to honor CAB if a scan is in progress on any interface. Prefer to
* skip this DTIM and wait for the next one.
*/
- wvif_it = NULL;
- while ((wvif_it = wvif_iterate(wvif->wdev, wvif_it)) != NULL)
- if (mutex_is_locked(&wvif_it->scan_lock))
- return;
+ if (mutex_is_locked(&wvif->wdev->scan_lock))
+ return;

if (!wfx_tx_queues_has_cab(wvif) || wvif->after_dtim_tx_allowed)
dev_warn(wvif->wdev->dev, "incorrect sequence (%d CAB in queue)",
@@ -730,7 +726,6 @@ int wfx_add_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif)
complete(&wvif->set_pm_mode_complete);
INIT_WORK(&wvif->tx_policy_upload_work, wfx_tx_policy_upload_work);

- mutex_init(&wvif->scan_lock);
init_completion(&wvif->scan_complete);
INIT_WORK(&wvif->scan_work, wfx_hw_scan_work);

diff --git a/drivers/net/wireless/silabs/wfx/wfx.h b/drivers/net/wireless/silabs/wfx/wfx.h
index 13ba84b3b2c33..a41b2c35fa415 100644
--- a/drivers/net/wireless/silabs/wfx/wfx.h
+++ b/drivers/net/wireless/silabs/wfx/wfx.h
@@ -43,6 +43,7 @@ struct wfx_dev {
struct delayed_work cooling_timeout_work;
bool poll_irq;
bool chip_frozen;
+ struct mutex scan_lock;
struct mutex conf_mutex;

struct wfx_hif_cmd hif_cmd;
@@ -80,8 +81,6 @@ struct wfx_vif {

unsigned long uapsd_mask;

- /* avoid some operations in parallel with scan */
- struct mutex scan_lock;
struct work_struct scan_work;
struct completion scan_complete;
int scan_nb_chan_done;
--
2.39.2

2023-10-04 17:29:25

by Jérôme Pouiller

[permalink] [raw]
Subject: [PATCH v3 8/8] wifi: wfx: implement wfx_remain_on_channel()

With some conditions, the device is able to send/receive frames during
scan operation. So, it is possible to use it implement the "remain on
channel" feature. We just ask for a passive scan (without sending any
probe request) on one channel.

This architecture allows to leverage some interesting features:
- if the device is AP, the device switches channel just after the next
beacon and the beacons are stopped during the off-channel interval.
- if the device is connected, it advertises it is asleep before to
switch channel (so the AP should stop to try to send data)

Signed-off-by: Jérôme Pouiller <[email protected]>
---
drivers/net/wireless/silabs/wfx/main.c | 3 ++
drivers/net/wireless/silabs/wfx/scan.c | 62 ++++++++++++++++++++++++++
drivers/net/wireless/silabs/wfx/scan.h | 6 +++
drivers/net/wireless/silabs/wfx/sta.c | 1 +
drivers/net/wireless/silabs/wfx/wfx.h | 5 ++-
5 files changed, 76 insertions(+), 1 deletion(-)

diff --git a/drivers/net/wireless/silabs/wfx/main.c b/drivers/net/wireless/silabs/wfx/main.c
index 4bf16bceb0bbc..e7198520bdffc 100644
--- a/drivers/net/wireless/silabs/wfx/main.c
+++ b/drivers/net/wireless/silabs/wfx/main.c
@@ -151,6 +151,8 @@ static const struct ieee80211_ops wfx_ops = {
.change_chanctx = wfx_change_chanctx,
.assign_vif_chanctx = wfx_assign_vif_chanctx,
.unassign_vif_chanctx = wfx_unassign_vif_chanctx,
+ .remain_on_channel = wfx_remain_on_channel,
+ .cancel_remain_on_channel = wfx_cancel_remain_on_channel,
};

bool wfx_api_older_than(struct wfx_dev *wdev, int major, int minor)
@@ -289,6 +291,7 @@ struct wfx_dev *wfx_init_common(struct device *dev, const struct wfx_platform_da
hw->wiphy->features |= NL80211_FEATURE_AP_SCAN;
hw->wiphy->flags |= WIPHY_FLAG_AP_PROBE_RESP_OFFLOAD;
hw->wiphy->flags |= WIPHY_FLAG_AP_UAPSD;
+ hw->wiphy->max_remain_on_channel_duration = 5000;
hw->wiphy->max_ap_assoc_sta = HIF_LINK_ID_MAX;
hw->wiphy->max_scan_ssids = 2;
hw->wiphy->max_scan_ie_len = IEEE80211_MAX_DATA_LEN;
diff --git a/drivers/net/wireless/silabs/wfx/scan.c b/drivers/net/wireless/silabs/wfx/scan.c
index d6f98035f6844..c3c103ff88cce 100644
--- a/drivers/net/wireless/silabs/wfx/scan.c
+++ b/drivers/net/wireless/silabs/wfx/scan.c
@@ -145,3 +145,65 @@ void wfx_scan_complete(struct wfx_vif *wvif, int nb_chan_done)
wvif->scan_nb_chan_done = nb_chan_done;
complete(&wvif->scan_complete);
}
+
+void wfx_remain_on_channel_work(struct work_struct *work)
+{
+ struct wfx_vif *wvif = container_of(work, struct wfx_vif, remain_on_channel_work);
+ struct ieee80211_channel *chan = wvif->remain_on_channel_chan;
+ int duration = wvif->remain_on_channel_duration;
+ int ret;
+
+ /* Hijack scan request to implement Remain-On-Channel */
+ mutex_lock(&wvif->wdev->conf_mutex);
+ mutex_lock(&wvif->wdev->scan_lock);
+ if (wvif->join_in_progress) {
+ dev_info(wvif->wdev->dev, "abort in-progress REQ_JOIN");
+ wfx_reset(wvif);
+ }
+ wfx_tx_flush(wvif->wdev);
+
+ reinit_completion(&wvif->scan_complete);
+ ret = wfx_hif_scan_uniq(wvif, chan, duration);
+ if (ret)
+ goto end;
+ ieee80211_ready_on_channel(wvif->wdev->hw);
+ ret = wait_for_completion_timeout(&wvif->scan_complete,
+ msecs_to_jiffies(duration * 120 / 100));
+ if (!ret) {
+ wfx_hif_stop_scan(wvif);
+ ret = wait_for_completion_timeout(&wvif->scan_complete, 1 * HZ);
+ dev_dbg(wvif->wdev->dev, "roc timeout\n");
+ }
+ if (!ret)
+ dev_err(wvif->wdev->dev, "roc didn't stop\n");
+ ieee80211_remain_on_channel_expired(wvif->wdev->hw);
+end:
+ mutex_unlock(&wvif->wdev->scan_lock);
+ mutex_unlock(&wvif->wdev->conf_mutex);
+ wfx_bh_request_tx(wvif->wdev);
+}
+
+int wfx_remain_on_channel(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
+ struct ieee80211_channel *chan, int duration,
+ enum ieee80211_roc_type type)
+{
+ struct wfx_dev *wdev = hw->priv;
+ struct wfx_vif *wvif = (struct wfx_vif *)vif->drv_priv;
+
+ if (wfx_api_older_than(wdev, 3, 10))
+ return -EOPNOTSUPP;
+
+ wvif->remain_on_channel_duration = duration;
+ wvif->remain_on_channel_chan = chan;
+ schedule_work(&wvif->remain_on_channel_work);
+ return 0;
+}
+
+int wfx_cancel_remain_on_channel(struct ieee80211_hw *hw, struct ieee80211_vif *vif)
+{
+ struct wfx_vif *wvif = (struct wfx_vif *)vif->drv_priv;
+
+ wfx_hif_stop_scan(wvif);
+ flush_work(&wvif->remain_on_channel_work);
+ return 0;
+}
diff --git a/drivers/net/wireless/silabs/wfx/scan.h b/drivers/net/wireless/silabs/wfx/scan.h
index 78e3b984f375c..995ab8c6cb5ef 100644
--- a/drivers/net/wireless/silabs/wfx/scan.h
+++ b/drivers/net/wireless/silabs/wfx/scan.h
@@ -19,4 +19,10 @@ int wfx_hw_scan(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
void wfx_cancel_hw_scan(struct ieee80211_hw *hw, struct ieee80211_vif *vif);
void wfx_scan_complete(struct wfx_vif *wvif, int nb_chan_done);

+void wfx_remain_on_channel_work(struct work_struct *work);
+int wfx_remain_on_channel(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
+ struct ieee80211_channel *chan, int duration,
+ enum ieee80211_roc_type type);
+int wfx_cancel_remain_on_channel(struct ieee80211_hw *hw, struct ieee80211_vif *vif);
+
#endif
diff --git a/drivers/net/wireless/silabs/wfx/sta.c b/drivers/net/wireless/silabs/wfx/sta.c
index 8533bad6caeae..1b6c158457b42 100644
--- a/drivers/net/wireless/silabs/wfx/sta.c
+++ b/drivers/net/wireless/silabs/wfx/sta.c
@@ -728,6 +728,7 @@ int wfx_add_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif)

init_completion(&wvif->scan_complete);
INIT_WORK(&wvif->scan_work, wfx_hw_scan_work);
+ INIT_WORK(&wvif->remain_on_channel_work, wfx_remain_on_channel_work);

wfx_tx_queues_init(wvif);
wfx_tx_policy_init(wvif);
diff --git a/drivers/net/wireless/silabs/wfx/wfx.h b/drivers/net/wireless/silabs/wfx/wfx.h
index a41b2c35fa415..bd0df2e1ea990 100644
--- a/drivers/net/wireless/silabs/wfx/wfx.h
+++ b/drivers/net/wireless/silabs/wfx/wfx.h
@@ -70,6 +70,7 @@ struct wfx_vif {

bool after_dtim_tx_allowed;
bool join_in_progress;
+ struct completion set_pm_mode_complete;

struct delayed_work beacon_loss_work;

@@ -87,7 +88,9 @@ struct wfx_vif {
bool scan_abort;
struct ieee80211_scan_request *scan_req;

- struct completion set_pm_mode_complete;
+ struct ieee80211_channel *remain_on_channel_chan;
+ int remain_on_channel_duration;
+ struct work_struct remain_on_channel_work;
};

static inline struct ieee80211_vif *wvif_to_vif(struct wfx_vif *wvif)
--
2.39.2

2023-10-04 17:29:28

by Jérôme Pouiller

[permalink] [raw]
Subject: [PATCH v3 4/8] wifi: wfx: introduce hif_scan_uniq()

Like hof_scan(), hif_scan_uniq() invoke HIF_SCAN. However, it only
allows to probe one channel and disable probe requests. It works very
well to implement Remain-On-Channel.

Signed-off-by: Jérôme Pouiller <[email protected]>
---
drivers/net/wireless/silabs/wfx/hif_tx.c | 25 ++++++++++++++++++++++++
drivers/net/wireless/silabs/wfx/hif_tx.h | 1 +
2 files changed, 26 insertions(+)

diff --git a/drivers/net/wireless/silabs/wfx/hif_tx.c b/drivers/net/wireless/silabs/wfx/hif_tx.c
index de5a31482df38..9f403d275cb13 100644
--- a/drivers/net/wireless/silabs/wfx/hif_tx.c
+++ b/drivers/net/wireless/silabs/wfx/hif_tx.c
@@ -238,6 +238,31 @@ int wfx_hif_write_mib(struct wfx_dev *wdev, int vif_id, u16 mib_id, void *val, s
return ret;
}

+/* Hijack scan request to implement Remain-On-Channel */
+int wfx_hif_scan_uniq(struct wfx_vif *wvif, struct ieee80211_channel *chan, int duration)
+{
+ int ret;
+ struct wfx_hif_msg *hif;
+ size_t buf_len = sizeof(struct wfx_hif_req_start_scan_alt) + sizeof(u8);
+ struct wfx_hif_req_start_scan_alt *body = wfx_alloc_hif(buf_len, &hif);
+
+ if (!hif)
+ return -ENOMEM;
+ body->num_of_ssids = HIF_API_MAX_NB_SSIDS;
+ body->maintain_current_bss = 1;
+ body->disallow_ps = 1;
+ body->tx_power_level = cpu_to_le32(chan->max_power);
+ body->num_of_channels = 1;
+ body->channel_list[0] = chan->hw_value;
+ body->max_transmit_rate = API_RATE_INDEX_B_1MBPS;
+ body->min_channel_time = cpu_to_le32(duration);
+ body->max_channel_time = cpu_to_le32(duration * 110 / 100);
+ wfx_fill_header(hif, wvif->id, HIF_REQ_ID_START_SCAN, buf_len);
+ ret = wfx_cmd_send(wvif->wdev, hif, NULL, 0, false);
+ kfree(hif);
+ return ret;
+}
+
int wfx_hif_scan(struct wfx_vif *wvif, struct cfg80211_scan_request *req,
int chan_start_idx, int chan_num)
{
diff --git a/drivers/net/wireless/silabs/wfx/hif_tx.h b/drivers/net/wireless/silabs/wfx/hif_tx.h
index 71817a6571f0b..aab54df6aafa6 100644
--- a/drivers/net/wireless/silabs/wfx/hif_tx.h
+++ b/drivers/net/wireless/silabs/wfx/hif_tx.h
@@ -54,6 +54,7 @@ int wfx_hif_beacon_transmit(struct wfx_vif *wvif, bool enable);
int wfx_hif_update_ie_beacon(struct wfx_vif *wvif, const u8 *ies, size_t ies_len);
int wfx_hif_scan(struct wfx_vif *wvif, struct cfg80211_scan_request *req80211,
int chan_start, int chan_num);
+int wfx_hif_scan_uniq(struct wfx_vif *wvif, struct ieee80211_channel *chan, int duration);
int wfx_hif_stop_scan(struct wfx_vif *wvif);
int wfx_hif_configuration(struct wfx_dev *wdev, const u8 *conf, size_t len);
int wfx_hif_shutdown(struct wfx_dev *wdev);
--
2.39.2

2023-10-04 17:29:28

by Jérôme Pouiller

[permalink] [raw]
Subject: [PATCH v3 2/8] wifi: wfx: relocate wfx_rate_mask_to_hw()

wfx_rate_mask_to_hw() is only used in hif_tx.c. So relocate it into
hif_tx.c and mark it static.

Signed-off-by: Jérôme Pouiller <[email protected]>
---
drivers/net/wireless/silabs/wfx/hif_tx.c | 18 ++++++++++++++++++
drivers/net/wireless/silabs/wfx/sta.c | 18 ------------------
drivers/net/wireless/silabs/wfx/sta.h | 1 -
3 files changed, 18 insertions(+), 19 deletions(-)

diff --git a/drivers/net/wireless/silabs/wfx/hif_tx.c b/drivers/net/wireless/silabs/wfx/hif_tx.c
index 9402503fbde3c..de5a31482df38 100644
--- a/drivers/net/wireless/silabs/wfx/hif_tx.c
+++ b/drivers/net/wireless/silabs/wfx/hif_tx.c
@@ -45,6 +45,24 @@ static void *wfx_alloc_hif(size_t body_len, struct wfx_hif_msg **hif)
return NULL;
}

+static u32 wfx_rate_mask_to_hw(struct wfx_dev *wdev, u32 rates)
+{
+ int i;
+ u32 ret = 0;
+ /* The device only supports 2GHz */
+ struct ieee80211_supported_band *sband = wdev->hw->wiphy->bands[NL80211_BAND_2GHZ];
+
+ for (i = 0; i < sband->n_bitrates; i++) {
+ if (rates & BIT(i)) {
+ if (i >= sband->n_bitrates)
+ dev_warn(wdev->dev, "unsupported basic rate\n");
+ else
+ ret |= BIT(sband->bitrates[i].hw_value);
+ }
+ }
+ return ret;
+}
+
int wfx_cmd_send(struct wfx_dev *wdev, struct wfx_hif_msg *request,
void *reply, size_t reply_len, bool no_reply)
{
diff --git a/drivers/net/wireless/silabs/wfx/sta.c b/drivers/net/wireless/silabs/wfx/sta.c
index 9c0a11c277e97..c58db2bcea87b 100644
--- a/drivers/net/wireless/silabs/wfx/sta.c
+++ b/drivers/net/wireless/silabs/wfx/sta.c
@@ -20,24 +20,6 @@

#define HIF_MAX_ARP_IP_ADDRTABLE_ENTRIES 2

-u32 wfx_rate_mask_to_hw(struct wfx_dev *wdev, u32 rates)
-{
- int i;
- u32 ret = 0;
- /* The device only supports 2GHz */
- struct ieee80211_supported_band *sband = wdev->hw->wiphy->bands[NL80211_BAND_2GHZ];
-
- for (i = 0; i < sband->n_bitrates; i++) {
- if (rates & BIT(i)) {
- if (i >= sband->n_bitrates)
- dev_warn(wdev->dev, "unsupported basic rate\n");
- else
- ret |= BIT(sband->bitrates[i].hw_value);
- }
- }
- return ret;
-}
-
void wfx_cooling_timeout_work(struct work_struct *work)
{
struct wfx_dev *wdev = container_of(to_delayed_work(work), struct wfx_dev,
diff --git a/drivers/net/wireless/silabs/wfx/sta.h b/drivers/net/wireless/silabs/wfx/sta.h
index 888db5cd3206b..c478ddcb934bd 100644
--- a/drivers/net/wireless/silabs/wfx/sta.h
+++ b/drivers/net/wireless/silabs/wfx/sta.h
@@ -66,6 +66,5 @@ int wfx_update_pm(struct wfx_vif *wvif);

/* Other Helpers */
void wfx_reset(struct wfx_vif *wvif);
-u32 wfx_rate_mask_to_hw(struct wfx_dev *wdev, u32 rates);

#endif
--
2.39.2

2023-10-09 06:53:55

by Kalle Valo

[permalink] [raw]
Subject: Re: [PATCH v3 1/8] wifi: wfx: fix power_save setting when AP is stopped

Jérôme Pouiller <[email protected]> wrote:

> The WF200 allow to start two network interfaces (one AP, one station) on
> two different channels. Since magic does not exist, it only works if the
> station interface enables power save.
>
> Thus, the driver detects this case and enforce power save as necessary.
>
> This patch fixes the case where the AP interface is stopped and it is no
> more necessary to enforce power saving on the station interface.
>
> Signed-off-by: Jérôme Pouiller <[email protected]>

8 patches applied to wireless-next.git, thanks.

8b27aed225ca wifi: wfx: fix power_save setting when AP is stopped
94c104d51830 wifi: wfx: relocate wfx_rate_mask_to_hw()
cf0cc05c8c23 wifi: wfx: move wfx_skb_*() out of the header file
fc5cb24fd50e wifi: wfx: introduce hif_scan_uniq()
f091bcb62dc6 wifi: wfx: simplify exclusion between scan and Rx filters
04106ec5bb02 wifi: wfx: scan_lock is global to the device
f7385a20249e wifi: wfx: allow to send frames during ROC
fc627dad3f01 wifi: wfx: implement wfx_remain_on_channel()

--
https://patchwork.kernel.org/project/linux-wireless/patch/[email protected]/

https://wireless.wiki.kernel.org/en/developers/documentation/submittingpatches