Skip to contentSkip to conversation

Add support for ACS offload for AP

PATCH In review Ahmad Masri 3 participants 6 messages Dec 16, 2018 – Dec 17, 2018

Subsystems (2)
lore
Share & tools
lore
#0 lore raw

cover Add support for ACS offload for AP

The following set of patches add support for Automatic Channel Selection (ACS) offload for AP in cfg80211 and an implementation in wil6210 driver.

Ahmad Masri (2):
cfg80211: Add Automatic Channel Selection (ACS) offload for AP
wil6210: add implementation of acs cfg80211_ops

 drivers/net/wireless/ath/wil6210/cfg80211.c | 140 ++++++++++++++++++++-
 drivers/net/wireless/ath/wil6210/debugfs.c  | 154 +++++++++++++++++++++++
 drivers/net/wireless/ath/wil6210/main.c     |   5 +
 drivers/net/wireless/ath/wil6210/wil6210.h  |  15 +++
 drivers/net/wireless/ath/wil6210/wmi.c      |  76 ++++++++++++
 drivers/net/wireless/ath/wil6210/wmi.h      |   3 +-
 include/net/cfg80211.h                      |  33 +++++
 include/uapi/linux/nl80211.h                |  65 ++++++++++
 net/wireless/mlme.c                         |  31 +++++
 net/wireless/nl80211.c                      | 182 ++++++++++++++++++++++++++++
 net/wireless/nl80211.h                      |   6 +
 net/wireless/rdev-ops.h                     |  12 ++
 net/wireless/trace.h                        |  23 ++++
 13 files changed, 742 insertions(+), 3 deletions(-)
Signature · 1 line
1.9.1
#1 lore raw

PATCH 1/2 cfg80211: Add Automatic Channel Selection (ACS) offload for AP

Add ACS offload to let the device select a channel for AP from a list of channels that the user-space provides. ACS can customize the method of AP channel selection and add parameters like traffic load, number of APs on channel and more.

Change-Id I18cb8460b9418512ac7ac9f76fe8f7f379f2478b
---
 include/net/cfg80211.h       |  33 ++++++++
 include/uapi/linux/nl80211.h |  65 ++++++++++++++++
 net/wireless/mlme.c          |  31 ++++++++
 net/wireless/nl80211.c       | 182 +++++++++++++++++++++++++++++++++++++++++++
 net/wireless/nl80211.h       |   6 ++
 net/wireless/rdev-ops.h      |  12 +++
 net/wireless/trace.h         |  23 ++++++
 7 files changed, 352 insertions(+)
include/net/cfg80211.h +33 -0
index ede7fcd..c3faa48 100644
@@ -715,6 +715,17 @@ struct survey_info {
 	s8 noise;
 };
 
+/**
+ * struct cfg80211_acs_params - ACS parameters
+ * @n_channels: total number of channels for ACS
+ * @channels: list of chan_def to run ACS on
+ */
+struct cfg80211_acs_params {
+	u32 n_channels;
+	/* keep last */
+	struct cfg80211_chan_def channels[0];
+};
+
 #define CFG80211_MAX_WEP_KEYS	4
 
 /**
@@ -3377,6 +3388,11 @@ struct cfg80211_pmsr_request {
  *	Statistics should be cumulative, currently no way to reset is provided.
  * @start_pmsr: start peer measurement (e.g. FTM)
  * @abort_pmsr: abort peer measurement
+ * @acs: run automatic channel selection offload measurement to find the best
+ *	channel to start the AP on. Userspace provide a list of chan_defs, the
+ *	driver should perform ACS on the provided list and select best channel.
+ *	driver should call cfg80211_acs_result to complete this operation.
+ *	(invoked with the wireless_dev mutex held)
  */
 struct cfg80211_ops {
 	int	(*suspend)(struct wiphy *wiphy, struct cfg80211_wowlan *wow);
@@ -3691,6 +3707,8 @@ struct cfg80211_ops {
 			      struct cfg80211_pmsr_request *request);
 	void	(*abort_pmsr)(struct wiphy *wiphy, struct wireless_dev *wdev,
 			      struct cfg80211_pmsr_request *request);
+	int	(*acs)(struct wiphy *wiphy, struct net_device *dev,
+		       struct cfg80211_acs_params *params);
 };
 
 /*
@@ -4662,6 +4680,7 @@ struct wireless_dev {
 	unsigned long cac_start_time;
 	unsigned int cac_time_ms;
 
+	bool acs_started;
 #ifdef CONFIG_CFG80211_WEXT
 	/* wext data */
 	struct {
@@ -6362,6 +6381,20 @@ void cfg80211_cac_event(struct net_device *netdev,
 
 
 /**
+ * cfg80211_acs_result - ACS result notification
+ * @netdev: network device
+ * @chandef: chandef for the selected channel, NULL on unsuccessful operation
+ * @status: ACS status as specified in &enum nl80211_acs_status
+ * @gfp: context flags
+ *
+ * This function is called when ACS measurement is finished or aborted.
+ * This must be called to notify the completion of a ACS process.
+ */
+void cfg80211_acs_result(struct net_device *netdev,
+			 const struct cfg80211_chan_def *chandef,
+			 enum nl80211_acs_status status, gfp_t gfp);
+
+/**
  * cfg80211_gtk_rekey_notify - notify userspace about driver rekeying
  * @dev: network device
  * @bssid: BSSID of AP (to avoid races)
include/uapi/linux/nl80211.h +65 -0

113 lines not on this page · raw message

net/wireless/mlme.c +31 -0
index 1615e50..ed36d91 100644
@@ -903,3 +903,34 @@ void cfg80211_cac_event(struct net_device *netdev,
 	nl80211_radar_notify(rdev, chandef, event, netdev, gfp);
 }
 EXPORT_SYMBOL(cfg80211_cac_event);
+
+void cfg80211_acs_result(struct net_device *netdev,
+			 const struct cfg80211_chan_def *chandef,
+			 enum nl80211_acs_status status, gfp_t gfp)
+{
+	struct wireless_dev *wdev = netdev->ieee80211_ptr;
+	struct wiphy *wiphy = wdev->wiphy;
+	struct cfg80211_registered_device *rdev = wiphy_to_rdev(wiphy);
+
+	if (WARN_ON(!wdev->acs_started))
+		return;
+
+	switch (status) {
+	case NL80211_ACS_SUCCESS:
+		if (!chandef) {
+			WARN_ON(1);
+			goto out;
+		}
+	case NL80211_ACS_FAILED:
+		break;
+	default:
+		WARN_ON(1);
+		goto out;
+	}
+	nl80211_acs_notify(rdev, chandef, status, netdev, gfp);
+
+out:
+	wdev->acs_started = false;
+	dev_put(netdev);
+}
+EXPORT_SYMBOL(cfg80211_acs_result);
net/wireless/nl80211.c +182 -0

218 lines not on this page · raw message

net/wireless/nl80211.h +6 -0
index 531c82d..e406592 100644
@@ -119,6 +119,12 @@ int nl80211_send_mgmt(struct cfg80211_registered_device *rdev,
 		     enum nl80211_radar_event event,
 		     struct net_device *netdev, gfp_t gfp);
 
+void
+nl80211_acs_notify(struct cfg80211_registered_device *rdev,
+		   const struct cfg80211_chan_def *chandef,
+		   enum nl80211_acs_status status,
+		   struct net_device *netdev, gfp_t gfp);
+
 void nl80211_send_ap_stopped(struct wireless_dev *wdev);
 
 void cfg80211_rdev_free_coalesce(struct cfg80211_registered_device *rdev);
net/wireless/rdev-ops.h +12 -0
index 5cb48d1..ebd9576 100644
@@ -1272,4 +1272,16 @@ static inline int rdev_del_pmk(struct cfg80211_registered_device *rdev,
 	trace_rdev_return_void(&rdev->wiphy);
 }
 
+static inline int rdev_acs(struct cfg80211_registered_device *rdev,
+			   struct net_device *dev,
+			   struct cfg80211_acs_params *params)
+{
+	int ret;
+
+	trace_rdev_acs(&rdev->wiphy, dev, params);
+	ret = rdev->ops->acs(&rdev->wiphy, dev, params);
+	trace_rdev_return_int(&rdev->wiphy, ret);
+	return ret;
+}
+
 #endif /* __CFG80211_RDEV_OPS */
net/wireless/trace.h +23 -0
index 44b2ce1..c841873 100644
@@ -2530,6 +2530,29 @@
 	TP_ARGS(wiphy, wdev, cookie)
 );
 
+TRACE_EVENT(rdev_acs,
+	TP_PROTO(struct wiphy *wiphy, struct net_device *netdev,
+		 struct cfg80211_acs_params *params),
+
+	TP_ARGS(wiphy, netdev, params),
+
+	TP_STRUCT__entry(
+		WIPHY_ENTRY
+		NETDEV_ENTRY
+		__field(u32, n_channels)
+	),
+
+	TP_fast_assign(
+		WIPHY_ASSIGN;
+		NETDEV_ASSIGN;
+		__entry->n_channels = params->n_channels;
+	),
+
+	TP_printk(WIPHY_PR_FMT ", " NETDEV_PR_FMT
+		  ", num of channels: %u", WIPHY_PR_ARG, NETDEV_PR_ARG,
+		  __entry->n_channels)
+);
+
 /*************************************************************
  *	     cfg80211 exported functions traces		     *
  *************************************************************/
Signature · 1 line
1.9.1
#2 lore raw

Re: [PATCH 1/2] cfg80211: Add Automatic Channel Selection (ACS) offload for AP

Quoted 7 lines · Ahmad Masri

Add ACS offload to let the device select a channel for AP from a list of channels that the user-space provides. ACS can customize the method of AP channel selection and add parameters like traffic load, number of APs on channel and more.

Change-Id I18cb8460b9418512ac7ac9f76fe8f7f379f2478b

No Change-Id, please.

include/net/cfg80211.h struct wireless_dev { · line 4684

Quoted 6 lines
include/net/cfg80211.h +1 -0
@@ -4662,6 +4680,7 @@ struct wireless_dev {
 	unsigned long cac_start_time;
 	unsigned int cac_time_ms;
 
+	bool acs_started;
 #ifdef CONFIG_CFG80211_WEXT

Empty line before ifdef? Just like it had before your patch.

Quoted 7 lines
net/wireless/mlme.c +7 -0
+void cfg80211_acs_result(struct net_device *netdev,
+			 const struct cfg80211_chan_def *chandef,
+			 enum nl80211_acs_status status, gfp_t gfp)
+{
+	struct wireless_dev *wdev = netdev->ieee80211_ptr;
+	struct wiphy *wiphy = wdev->wiphy;
+	struct cfg80211_registered_device *rdev = wiphy_to_rdev(wiphy);

net/wireless/mlme.c void cfg80211_cac_event(struct net_device *netdev, · line 923

Quoted 10 lines
net/wireless/mlme.c +10 -0
+
+	if (WARN_ON(!wdev->acs_started))
+		return;
+
+	switch (status) {
+	case NL80211_ACS_SUCCESS:
+		if (!chandef) {
+			WARN_ON(1);
+			goto out;
+		}

if (WARN_ON(!chandef))

	goto out;
Signature · 1 line
Kalle Valo
maintainer
#3 lore raw

Re: [PATCH 1/2] cfg80211: Add Automatic Channel Selection (ACS) offload for AP

In reply to Ahmad Masri

Setting aside Kalle's question for a second (though you should address them, probably before mine!)...

Quoted 5 lines

+ * @NL80211_ATTR_CHAN_DEF: attribute for nesting chan_def parameters
+ * as defined in &enum nl80211_ch_def_attr. The new attribute allows
+ * userspace to send a list of struct cfg80211_chan_def. For example, ACS
+ * command uses this attribute for sending a list of channels, for more
+ * details see &NL80211_CMD_ACS.

I don't think this makes sense. Just have an NL80211_ATTR_CHANNEL_LIST or so, which is like a NLA_POLICY_NESTED_ARRAY, and then inside we can reuse the existing top-level attributes for how to define a channel.

That'll save you most of the parsing code too.

Quoted 10 lines

/**
+ * enum nl80211_acs_status - ACS status
+ *
+ * status to be used to inform userspace about the result of the ACS offloaded
+ * measurement.
+ *
+ * @NL80211_ACS_SUCCESS: The ACS operation finished successfully
+ * @NL80211_ACS_FAILED: Failed to run the ACS. Userspace should choose a channel
+ * by itself.
+ */

include/uapi/linux/nl80211.h enum nl80211_dfs_state { · line 5626

Quoted 4 lines
include/uapi/linux/nl80211.h +4 -0
+enum nl80211_acs_status {
+	NL80211_ACS_SUCCESS,
+	NL80211_ACS_FAILED,
+};

It seems like a "successful" flag attribute would be sufficient.

net/wireless/nl80211.c static int nl80211_get_ftm_responder_stats(struct sk_buff *skb, · line 13264

Quoted 3 lines
net/wireless/nl80211.c +2 -0
+	dev_put(netdev);
 
+	dev_hold(dev);

Don't do that. Need to cancel the operation if the netdev is removed instead.

johannes

#4 lore raw

PATCH 2/2 wil6210: add implementation of acs cfg80211_ops

In reply to Ahmad Masri

Add ACS to cfg80211 operations that the device handles and performs. wil6210 reports NL80211_EXT_FEATURE_ACS_OFFLOAD indicating a support for acs operation through cfg80211_ops.

ACS is performed by the driver and the FW. Once ACS operation is called the driver builds a WMI command with the requested channels and sends the command to the FW. The FW performs ACS scan on the channels and reports for each channel the following:
1- Number of beacon received on channel
2- channel busy time
3- transmit time
4- receive time
5- noise level
The driver uses the above information to select the best channel to start the AP, and reports it to the host.

User may use debugfs acs_ch_weight to set a different weights for the channels.

Change-Id I8e13296fad0c9fa8b15788fd37c23d825d41d8e5
---
 drivers/net/wireless/ath/wil6210/cfg80211.c | 140 ++++++++++++++++++++++++-
 drivers/net/wireless/ath/wil6210/debugfs.c  | 154 ++++++++++++++++++++++++++++
 drivers/net/wireless/ath/wil6210/main.c     |   5 +
 drivers/net/wireless/ath/wil6210/wil6210.h  |  15 +++
 drivers/net/wireless/ath/wil6210/wmi.c      |  76 ++++++++++++++
 drivers/net/wireless/ath/wil6210/wmi.h      |   3 +-
 6 files changed, 390 insertions(+), 3 deletions(-)
drivers/net/wireless/ath/wil6210/cfg80211.c +138 -2
index 9b2f9f5..62abfb5 100644
@@ -35,6 +35,14 @@
 };
 #endif
 
+/* in case of channels' noise values all zero, applying weights will not work.
+ * to avoid such a case, we will add some small positive value to
+ * all channels' noise calculation
+ */
+#define ACS_CH_NOISE_INIT_VAL (100)
+
+#define ACS_DEFAULT_BEST_CHANNEL 2
+
 #define CHAN60G(_channel, _flags) {				\
 	.band			= NL80211_BAND_60GHZ,		\
 	.center_freq		= 56160 + (2160 * (_channel)),	\
@@ -44,7 +52,7 @@
 	.max_power		= 40,				\
 }
 
-static struct ieee80211_channel wil_60ghz_channels[] = {
+static struct ieee80211_channel wil_60ghz_channels[WIL_MAX_CHANNELS] = {
 	CHAN60G(1, 0),
 	CHAN60G(2, 0),
 	CHAN60G(3, 0),
@@ -64,7 +72,7 @@
 	}
 }
 
-static int wil_num_supported_channels(struct wil6210_priv *wil)
+int wil_num_supported_channels(struct wil6210_priv *wil)
 {
 	int num_channels = ARRAY_SIZE(wil_60ghz_channels);
 
@@ -2358,6 +2366,132 @@ static int wil_cfg80211_resume(struct wiphy *wiphy)
 	return rc;
 }
 
+static u8 wil_acs_calc_channel(struct wil6210_priv *wil)
+{
+	int i, best_channel = ACS_DEFAULT_BEST_CHANNEL - 1;
+	struct scan_acs_info *ch;
+	u64 dwell_time = le32_to_cpu(wil->survey_reply.evt.dwell_time);
+	u16 filled = le16_to_cpu(wil->survey_reply.evt.filled);
+	u8 num_channels = wil->survey_reply.evt.num_scanned_channels;
+	u64 busy_time, tx_time;
+	u64 min_i_ch = (u64)-1, cur_i_ch;
+	u8 p_min = 0, ch_noise;
+
+	wil_dbg_misc(wil,
+		     "acs_calc_channel: filled info: 0x%04X, for %u channels\n",
+		     filled, num_channels);
+
+	if (!num_channels) {
+		wil_err(wil, "received results with no channel info\n");
+		return 0;
+	}
+
+	/* find P_min */
+	if (filled & WMI_ACS_INFO_BITMASK_NOISE) {
+		p_min = wil->survey_reply.ch_info[0].noise;
+
+		for (i = 1; i < num_channels; i++)
+			p_min = min(p_min, wil->survey_reply.ch_info[i].noise);
+	}
+
+	wil_dbg_misc(wil, "acs_calc_channel: p_min is %u\n", p_min);
+
+	/* Choosing channel according to the following formula:
+	 * 16 bit fixed point math
+	 * I_ch = { [ (T_busy - T_tx) << 16 ] /
+	 *        (T_dwell - T_tx) } * 2^(P_rx - P_min)
+	 */
+	for (i = 0; i < num_channels; i++) {
+		ch = &wil->survey_reply.ch_info[i];
+
+		busy_time = filled & WMI_ACS_INFO_BITMASK_BUSY_TIME ?
+				le16_to_cpu(ch->busy_time) : 0;
+
+		tx_time = filled & WMI_ACS_INFO_BITMASK_TX_TIME ?
+				le16_to_cpu(ch->tx_time) : 0;
+
+		ch_noise = filled & WMI_ACS_INFO_BITMASK_NOISE ? ch->noise : 0;
+
+		wil_dbg_misc(wil,
+			     "acs_calc_channel: Ch[%d]: busy %llu, tx %llu, noise %u, dwell %llu\n",
+			     ch->channel + 1, busy_time, tx_time, ch_noise,
+			     dwell_time);
+
+		if (dwell_time == tx_time) {
+			wil_err(wil,
+				"Ch[%d] dwell_time == tx_time: %llu\n",
+				ch->channel + 1, dwell_time);
+			continue;
+		}
+
+		cur_i_ch = (busy_time - tx_time) << 16;
+		do_div(cur_i_ch,
+		       ((dwell_time - tx_time) << (ch_noise - p_min)));
+
+		/* Apply channel priority */
+		cur_i_ch = (cur_i_ch + ACS_CH_NOISE_INIT_VAL) *
+			   wil->acs_ch_weight[ch->channel];
+		do_div(cur_i_ch, 100);
+
+		wil_dbg_misc(wil, "acs_calc_channel: Ch[%d] w %u, I_ch %llu\n",
+			     ch->channel + 1, wil->acs_ch_weight[ch->channel],
+			     cur_i_ch);
+
+		if (i == 0 || cur_i_ch < min_i_ch) {
+			min_i_ch = cur_i_ch;
+			best_channel = ch->channel;
+		}
+	}
+
+	wil_dbg_misc(wil,
+		     "acs_calc_channel: best channel %d with I_ch of %llu\n",
+		     best_channel + 1, min_i_ch);
+
+	return best_channel;
+}
+
+static void wil_acs_notify(struct wiphy *wiphy, struct net_device *dev,
+			   u32 status)
+{
+	struct wil6210_priv *wil = wiphy_to_wil(wiphy);
+	u8 ch = wil_acs_calc_channel(wil);
+	u32 freq = ieee80211_channel_to_frequency(ch + 1, NL80211_BAND_60GHZ);
+	struct ieee80211_channel *channel = ieee80211_get_channel(wiphy, freq);
+	struct cfg80211_chan_def chandef = {0};
+
+	if (channel) {
+		cfg80211_chandef_create(&chandef, channel, NL80211_CHAN_NO_HT);
+	} else {
+		wil_err(wil, "Invalid freq %d\n", freq);
+		status = NL80211_ACS_FAILED;
+	}
+
+	cfg80211_acs_result(dev, &chandef, status, GFP_KERNEL);
+}
+
+static int
+wil_cfg80211_acs(struct wiphy *wiphy, struct net_device *dev,
+		 struct cfg80211_acs_params *params)
+{
+	struct wil6210_priv *wil = wiphy_to_wil(wiphy);
+	enum nl80211_acs_status status = NL80211_ACS_SUCCESS;
+	int rc;
+
+	if (params->n_channels == 0) {
+		wil_err(wil, "acs: No valid channels for ACS\n");
+		return -EINVAL;
+	}
+
+	rc = wil_start_acs_survey(wil, WMI_SCAN_DWELL_TIME_MS,
+				  params->channels, params->n_channels);
+	if (rc)
+		status = NL80211_ACS_FAILED;
+
+	wil_acs_notify(wiphy, dev, status);
+
+	return 0;
+}
+
 static const struct cfg80211_ops wil_cfg80211_ops = {
 	.add_virtual_intf = wil_cfg80211_add_iface,
 	.del_virtual_intf = wil_cfg80211_del_iface,
@@ -2394,6 +2528,7 @@ static int wil_cfg80211_resume(struct wiphy *wiphy)
 	.sched_scan_start = wil_cfg80211_sched_scan_start,
 	.sched_scan_stop = wil_cfg80211_sched_scan_stop,
 	.update_ft_ies = wil_cfg80211_update_ft_ies,
+	.acs = wil_cfg80211_acs,
 };
 
 static void wil_wiphy_init(struct wiphy *wiphy)
@@ -2436,6 +2571,7 @@ static void wil_wiphy_init(struct wiphy *wiphy)
 #ifdef CONFIG_PM
 	wiphy->wowlan = &wil_wowlan_support;
 #endif
+	wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_ACS_OFFLOAD);
 }
 
 int wil_cfg80211_iface_combinations_from_fw(
drivers/net/wireless/ath/wil6210/debugfs.c +154 -0

178 lines not on this page · raw message

drivers/net/wireless/ath/wil6210/main.c +5 -0
index ba6a2ee..f20ced0 100644
@@ -750,6 +750,11 @@ int wil_priv_init(struct wil6210_priv *wil)
 
 	wil->amsdu_en = 1;
 
+	/* ACS related */
+	wil->acs_ch_weight[0] = 120;
+	for (i = 1; i < WIL_MAX_CHANNELS; i++)
+		wil->acs_ch_weight[i] = 100;
+
 	return 0;
 
 out_wmi_wq:
drivers/net/wireless/ath/wil6210/wil6210.h +15 -0
index 0f3be3ff..c286750 100644
@@ -67,6 +67,8 @@
  */
 #define WIL_MAX_VIFS 4
 
+#define WIL_MAX_CHANNELS 4 /* max supported channels */
+
 /**
  * extract bits [@b0:@b1] (inclusive) from the value @x
  * it should be @b0 <= @b1, or result is incorrect
@@ -1045,6 +1047,15 @@ struct wil6210_priv {
 
 	u32 max_agg_wsize;
 	u32 max_ampdu_size;
+
+	/* ACS related */
+	unsigned short acs_ch_weight[WIL_MAX_CHANNELS];
+	bool survey_ready;
+	struct {
+		struct wmi_cmd_hdr wmi;
+		struct wmi_acs_passive_scan_complete_event evt;
+		struct scan_acs_info ch_info[WIL_MAX_CHANNELS];
+	} __packed survey_reply;
 };
 
 #define wil_to_wiphy(i) (i->wiphy)
@@ -1252,6 +1263,9 @@ int wil_addba_rx_request(struct wil6210_priv *wil, u8 mid,
 			 u8 cidxtid, u8 dialog_token, __le16 ba_param_set,
 			 __le16 ba_timeout, __le16 ba_seq_ctrl);
 int wil_addba_tx_request(struct wil6210_priv *wil, u8 ringid, u16 wsize);
+int wil_start_acs_survey(struct wil6210_priv *wil, uint dwell_time,
+			 struct cfg80211_chan_def channels[],
+			 u8 num_channels);
 
 void wil6210_clear_irq(struct wil6210_priv *wil);
 int wil6210_init_irq(struct wil6210_priv *wil, int irq);
@@ -1402,4 +1416,5 @@ int wmi_addba_rx_resp_edma(struct wil6210_priv *wil, u8 mid, u8 cid,
 
 void update_supported_bands(struct wil6210_priv *wil);
 
+int wil_num_supported_channels(struct wil6210_priv *wil);
 #endif /* __WIL6210_H__ */
drivers/net/wireless/ath/wil6210/wmi.c +76 -0

79 lines not on this page · raw message

drivers/net/wireless/ath/wil6210/wmi.h +2 -1
index b668758..5a71e98 100644
@@ -2444,7 +2444,8 @@ struct wmi_acs_passive_scan_complete_event {
 	 */
 	__le16 filled;
 	u8 num_scanned_channels;
-	u8 reserved;
+	/* enum scan_status */
+	u8 status;
 	struct scan_acs_info scan_info_list[0];
 } __packed;
 
Signature · 1 line
1.9.1
#5 lore raw

Re: [PATCH 2/2] wil6210: add implementation of acs cfg80211_ops

Quoted 4 lines · Ahmad Masri

Add ACS to cfg80211 operations that the device handles and performs. wil6210 reports NL80211_EXT_FEATURE_ACS_OFFLOAD indicating a support for acs operation through cfg80211_ops.

Quoted 11 lines

ACS is performed by the driver and the FW. Once ACS operation is called the driver builds a WMI command with the requested channels and sends the command to the FW. The FW performs ACS scan on the channels and reports for each channel the following:
1- Number of beacon received on channel
2- channel busy time
3- transmit time
4- receive time
5- noise level
The driver uses the above information to select the best channel to start the AP, and reports it to the host.

What's the point? Why is it better that wil6210 makes the decision instead of hostapd?

Quoted 2 lines

User may use debugfs acs_ch_weight to set a different weights for the channels.

Debugfs does not sound like the best interface for that, shouldn't it go via nl80211?

Quoted 1 line

Change-Id: I8e13296fad0c9fa8b15788fd37c23d825d41d8e5

No Change-Id, please.

Signature · 1 line
Kalle Valo