All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 0/3] Add support for new channels on 60GHz band
@ 2018-08-13 12:32 Alexei Avshalom Lazar
  2018-08-13 12:33 ` [PATCH 1/3] cfg80211: Add support for 60GHz band channels 5 and 6 Alexei Avshalom Lazar
                   ` (2 more replies)
  0 siblings, 3 replies; 7+ messages in thread
From: Alexei Avshalom Lazar @ 2018-08-13 12:32 UTC (permalink / raw)
  To: Johannes Berg; +Cc: Alexei Avshalom Lazar, linux-wireless, wil6210

The following set of patches add support for new channels on
60GHz band and EDMG channels:
-Support new channels 5 and 6
-Support EDMG channels

Alexei Avshalom Lazar (3):
  cfg80211: Add support for 60GHz band channels 5 and 6
  nl80211: Add support for EDMG channels
  wil6210: Add EDMG channel support

 drivers/net/wireless/ath/wil6210/cfg80211.c  | 194 +++++++++++++++++++++++++--
 drivers/net/wireless/ath/wil6210/debugfs.c   |   2 +-
 drivers/net/wireless/ath/wil6210/main.c      |   3 +
 drivers/net/wireless/ath/wil6210/txrx_edma.c |   2 +
 drivers/net/wireless/ath/wil6210/txrx_edma.h |   6 +
 drivers/net/wireless/ath/wil6210/wil6210.h   |   6 +-
 drivers/net/wireless/ath/wil6210/wmi.c       |   5 +-
 drivers/net/wireless/ath/wil6210/wmi.h       |  43 +++++-
 include/net/cfg80211.h                       |  50 ++++++-
 include/uapi/linux/nl80211.h                 |  14 +-
 net/wireless/chan.c                          |  88 ++++++++++++
 net/wireless/nl80211.c                       |  33 +++++
 net/wireless/reg.c                           |   2 +-
 net/wireless/trace.h                         |   2 +-
 net/wireless/util.c                          |  48 ++++++-
 15 files changed, 468 insertions(+), 30 deletions(-)

-- 
1.9.1

^ permalink raw reply	[flat|nested] 7+ messages in thread

* [PATCH 1/3] cfg80211: Add support for 60GHz band channels 5 and 6
  2018-08-13 12:32 [PATCH 0/3] Add support for new channels on 60GHz band Alexei Avshalom Lazar
@ 2018-08-13 12:33 ` Alexei Avshalom Lazar
  2018-08-28  9:25   ` Johannes Berg
  2018-08-13 12:33 ` [PATCH 2/3] nl80211: Add support for EDMG channels Alexei Avshalom Lazar
  2018-08-13 12:33 ` [PATCH 3/3] wil6210: Add EDMG channel support Alexei Avshalom Lazar
  2 siblings, 1 reply; 7+ messages in thread
From: Alexei Avshalom Lazar @ 2018-08-13 12:33 UTC (permalink / raw)
  To: Johannes Berg; +Cc: Alexei Avshalom Lazar, linux-wireless, wil6210

The current support in the 60GHz band is for channels 1-4.
Add support for channels 5 and 6.
This requires enlarging ieee80211_channel.center_freq from u16 to u32.

Signed-off-by: Alexei Avshalom Lazar <ailizaro@codeaurora.org>
---
 drivers/net/wireless/ath/wil6210/debugfs.c | 2 +-
 include/net/cfg80211.h                     | 2 +-
 include/uapi/linux/nl80211.h               | 2 +-
 net/wireless/reg.c                         | 2 +-
 net/wireless/trace.h                       | 2 +-
 net/wireless/util.c                        | 6 +++---
 6 files changed, 8 insertions(+), 8 deletions(-)

diff --git a/drivers/net/wireless/ath/wil6210/debugfs.c b/drivers/net/wireless/ath/wil6210/debugfs.c
index 58ce044..4b329d1 100644
--- a/drivers/net/wireless/ath/wil6210/debugfs.c
+++ b/drivers/net/wireless/ath/wil6210/debugfs.c
@@ -1435,7 +1435,7 @@ static int wil_freq_debugfs_show(struct seq_file *s, void *data)
 {
 	struct wil6210_priv *wil = s->private;
 	struct wireless_dev *wdev = wil->main_ndev->ieee80211_ptr;
-	u16 freq = wdev->chandef.chan ? wdev->chandef.chan->center_freq : 0;
+	u32 freq = wdev->chandef.chan ? wdev->chandef.chan->center_freq : 0;
 
 	seq_printf(s, "Freq = %d\n", freq);
 
diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h
index 9a85097..73ca446 100644
--- a/include/net/cfg80211.h
+++ b/include/net/cfg80211.h
@@ -149,7 +149,7 @@ enum ieee80211_channel_flags {
  */
 struct ieee80211_channel {
 	enum nl80211_band band;
-	u16 center_freq;
+	u32 center_freq;
 	u16 hw_value;
 	u32 flags;
 	int max_antenna_gain;
diff --git a/include/uapi/linux/nl80211.h b/include/uapi/linux/nl80211.h
index 7acc16f..0239896 100644
--- a/include/uapi/linux/nl80211.h
+++ b/include/uapi/linux/nl80211.h
@@ -4338,7 +4338,7 @@ enum nl80211_txrate_gi {
  * enum nl80211_band - Frequency band
  * @NL80211_BAND_2GHZ: 2.4 GHz ISM band
  * @NL80211_BAND_5GHZ: around 5 GHz band (4.9 - 5.7 GHz)
- * @NL80211_BAND_60GHZ: around 60 GHz band (58.32 - 64.80 GHz)
+ * @NL80211_BAND_60GHZ: around 60 GHz band (58.32 - 69.12 GHz)
  * @NUM_NL80211_BANDS: number of bands, avoid using this in userspace
  *	since newer kernel versions may support more bands
  */
diff --git a/net/wireless/reg.c b/net/wireless/reg.c
index 4fc66a1..2f8e01a 100644
--- a/net/wireless/reg.c
+++ b/net/wireless/reg.c
@@ -3255,7 +3255,7 @@ void regulatory_hint_disconnect(void)
 	restore_regulatory_settings(false);
 }
 
-static bool freq_is_chan_12_13_14(u16 freq)
+static bool freq_is_chan_12_13_14(u32 freq)
 {
 	if (freq == ieee80211_channel_to_frequency(12, NL80211_BAND_2GHZ) ||
 	    freq == ieee80211_channel_to_frequency(13, NL80211_BAND_2GHZ) ||
diff --git a/net/wireless/trace.h b/net/wireless/trace.h
index 7c73510..5e7eec8 100644
--- a/net/wireless/trace.h
+++ b/net/wireless/trace.h
@@ -112,7 +112,7 @@
 	} while (0)
 
 #define CHAN_ENTRY __field(enum nl80211_band, band) \
-		   __field(u16, center_freq)
+		   __field(u32, center_freq)
 #define CHAN_ASSIGN(chan)					  \
 	do {							  \
 		if (chan) {					  \
diff --git a/net/wireless/util.c b/net/wireless/util.c
index e0825a0..a450736 100644
--- a/net/wireless/util.c
+++ b/net/wireless/util.c
@@ -88,7 +88,7 @@ int ieee80211_channel_to_frequency(int chan, enum nl80211_band band)
 			return 5000 + chan * 5;
 		break;
 	case NL80211_BAND_60GHZ:
-		if (chan < 5)
+		if (chan < 7)
 			return 56160 + chan * 2160;
 		break;
 	default:
@@ -109,7 +109,7 @@ int ieee80211_frequency_to_channel(int freq)
 		return (freq - 4000) / 5;
 	else if (freq <= 45000) /* DMG band lower limit */
 		return (freq - 5000) / 5;
-	else if (freq >= 58320 && freq <= 64800)
+	else if (freq >= 58320 && freq <= 70200)
 		return (freq - 56160) / 2160;
 	else
 		return 0;
@@ -1568,7 +1568,7 @@ bool ieee80211_chandef_to_operating_class(struct cfg80211_chan_def *chandef,
 	}
 
 	/* 56.16 GHz, channel 1..4 */
-	if (freq >= 56160 + 2160 * 1 && freq <= 56160 + 2160 * 4) {
+	if (freq >= 56160 + 2160 * 1 && freq <= 56160 + 2160 * 6) {
 		if (chandef->width >= NL80211_CHAN_WIDTH_40)
 			return false;
 
-- 
1.9.1

^ permalink raw reply related	[flat|nested] 7+ messages in thread

* [PATCH 2/3] nl80211: Add support for EDMG channels
  2018-08-13 12:32 [PATCH 0/3] Add support for new channels on 60GHz band Alexei Avshalom Lazar
  2018-08-13 12:33 ` [PATCH 1/3] cfg80211: Add support for 60GHz band channels 5 and 6 Alexei Avshalom Lazar
@ 2018-08-13 12:33 ` Alexei Avshalom Lazar
  2018-08-28  9:33   ` Johannes Berg
  2018-08-13 12:33 ` [PATCH 3/3] wil6210: Add EDMG channel support Alexei Avshalom Lazar
  2 siblings, 1 reply; 7+ messages in thread
From: Alexei Avshalom Lazar @ 2018-08-13 12:33 UTC (permalink / raw)
  To: Johannes Berg; +Cc: Alexei Avshalom Lazar, linux-wireless, wil6210

802.11ay specification defines Enhanced Directional Multi-Gigabit
(EDMG) STA and SAP which allow channel bonding of 2 channels and more.
Introduce NL80211_BAND_ATTR_EDMG, NL80211_BAND_ATTR_EDMG_SUPPORTED_CHAN,
NL80211_ATTR_WIPHY_EDMG, NL80211_ATTR_WIPHY_EDMG_CHANNEL and
RATE_INFO_FLAGS_EDMG that needed for enabling and configuring
EDMG support.
Driver is expected to report its EDMG capabilities: whether EDMG
is supported and the supported EDMG channels.
Bitrate calculation is enhanced to take into account EDMG support
according to the 802.11ay specification.
The kernel uses NL80211_BAND_ATTR_EDMG and
NL80211_BAND_ATTR_EDMG_SUPPORTED_CHAN attributes in order to publish
the EDMG capabilities to the userspace, NL80211_BAND_ATTR_EDMG is set
if EDMG is supported and NL80211_BAND_ATTR_EDMG_SUPPORTED_CHAN
contains list of supported EDMG channels.
NL80211_ATTR_WIPHY_EDMG and NL80211_ATTR_WIPHY_EDMG_CHANNEL will be
used by the userspace for AP configuration and connect command.

Signed-off-by: Alexei Avshalom Lazar <ailizaro@codeaurora.org>
---
 drivers/net/wireless/ath/wil6210/cfg80211.c |  2 +-
 include/net/cfg80211.h                      | 48 +++++++++++++++-
 include/uapi/linux/nl80211.h                | 12 ++++
 net/wireless/chan.c                         | 88 +++++++++++++++++++++++++++++
 net/wireless/nl80211.c                      | 33 +++++++++++
 net/wireless/util.c                         | 42 +++++++++++++-
 6 files changed, 219 insertions(+), 6 deletions(-)

diff --git a/drivers/net/wireless/ath/wil6210/cfg80211.c b/drivers/net/wireless/ath/wil6210/cfg80211.c
index e63b078..4740b53 100644
--- a/drivers/net/wireless/ath/wil6210/cfg80211.c
+++ b/drivers/net/wireless/ath/wil6210/cfg80211.c
@@ -311,7 +311,7 @@ int wil_cid_fill_sinfo(struct wil6210_vif *vif, int cid,
 			BIT_ULL(NL80211_STA_INFO_RX_DROP_MISC) |
 			BIT_ULL(NL80211_STA_INFO_TX_FAILED);
 
-	sinfo->txrate.flags = RATE_INFO_FLAGS_60G;
+	sinfo->txrate.flags = RATE_INFO_FLAGS_DMG;
 	sinfo->txrate.mcs = le16_to_cpu(reply.evt.bf_mcs);
 	sinfo->rxrate.mcs = stats->last_mcs_rx;
 	sinfo->rx_bytes = stats->rx_bytes;
diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h
index 73ca446..10f9d76 100644
--- a/include/net/cfg80211.h
+++ b/include/net/cfg80211.h
@@ -321,6 +321,24 @@ struct ieee80211_sband_iftype_data {
 };
 
 /**
+ * struct ieee80211_sta_edmg_cap - EDMG capabilities
+ *
+ * This structure describes most essential parameters needed
+ * to describe 802.11ay EDMG capabilities
+ *
+ * @supported: is EDMG supported, Device may support EDMG
+ *	without supporting channel bonding. In this case
+ *	supported would be TRUE with n_channels = 0
+ * @channels: supported ieee EDMG channel numbers
+ * @n_channels: Number of channels in @channels
+ */
+struct ieee80211_sta_edmg_cap {
+	bool supported;
+	u8 *channels;
+	int n_channels;
+};
+
+/**
  * struct ieee80211_supported_band - frequency band definition
  *
  * This structure describes a frequency band a wiphy
@@ -336,6 +354,7 @@ struct ieee80211_sband_iftype_data {
  * @n_bitrates: Number of bitrates in @bitrates
  * @ht_cap: HT capabilities in this band
  * @vht_cap: VHT capabilities in this band
+ * @edmg_cap: EDMG capabilities in this band
  * @n_iftype_data: number of iftype data entries
  * @iftype_data: interface type data entries.  Note that the bits in
  *	@types_mask inside this structure cannot overlap (i.e. only
@@ -350,6 +369,7 @@ struct ieee80211_supported_band {
 	int n_bitrates;
 	struct ieee80211_sta_ht_cap ht_cap;
 	struct ieee80211_sta_vht_cap vht_cap;
+	struct ieee80211_sta_edmg_cap edmg_cap;
 	u16 n_iftype_data;
 	const struct ieee80211_sband_iftype_data *iftype_data;
 };
@@ -501,12 +521,16 @@ struct key_params {
  * @center_freq1: center frequency of first segment
  * @center_freq2: center frequency of second segment
  *	(only with 80+80 MHz)
+ * @edmg_mode: if defined, edmg supported and primary channel is EDMG
+ * @edmg_channel: the EDMG channel
  */
 struct cfg80211_chan_def {
 	struct ieee80211_channel *chan;
 	enum nl80211_chan_width width;
 	u32 center_freq1;
 	u32 center_freq2;
+	bool edmg_mode;
+	u8 edmg_channel;
 };
 
 /**
@@ -658,6 +682,18 @@ int cfg80211_chandef_dfs_required(struct wiphy *wiphy,
 }
 
 /**
+ * cfg80211_edmg_usable - check if the EDMG channel can be used
+ * @wiphy: the wiphy
+ * @edmg_cap: EDMG capabilities in this band
+ * @edmg_channel: the EDMG channel that need to be verified
+ * @primary_channel: The primary channel for the EDMG channel
+ * Return: %true the EDMG channel is usable. %false otherwise.
+ */
+bool cfg80211_edmg_usable(struct wiphy *wiphy,
+			  struct ieee80211_sta_edmg_cap *edmg_cap,
+			  u8 edmg_channel, int primary_channel);
+
+/**
  * enum survey_info_flags - survey information flags
  *
  * @SURVEY_INFO_NOISE_DBM: noise (in dBm) was filled in
@@ -1090,15 +1126,17 @@ int cfg80211_check_station_change(struct wiphy *wiphy,
  * @RATE_INFO_FLAGS_MCS: mcs field filled with HT MCS
  * @RATE_INFO_FLAGS_VHT_MCS: mcs field filled with VHT MCS
  * @RATE_INFO_FLAGS_SHORT_GI: 400ns guard interval
- * @RATE_INFO_FLAGS_60G: 60GHz MCS
+ * @RATE_INFO_FLAGS_DMG: 60GHz MCS
  * @RATE_INFO_FLAGS_HE_MCS: HE MCS information
+ * @RATE_INFO_FLAGS_EDMG: 60GHz MCS in EDMG mode
  */
 enum rate_info_flags {
 	RATE_INFO_FLAGS_MCS			= BIT(0),
 	RATE_INFO_FLAGS_VHT_MCS			= BIT(1),
 	RATE_INFO_FLAGS_SHORT_GI		= BIT(2),
-	RATE_INFO_FLAGS_60G			= BIT(3),
+	RATE_INFO_FLAGS_DMG			= BIT(3),
 	RATE_INFO_FLAGS_HE_MCS			= BIT(4),
+	RATE_INFO_FLAGS_EDMG			= BIT(5),
 };
 
 /**
@@ -1138,6 +1176,7 @@ enum rate_info_bw {
  * @he_dcm: HE DCM value
  * @he_ru_alloc: HE RU allocation (from &enum nl80211_he_ru_alloc,
  *	only valid if bw is %RATE_INFO_BW_HE_RU)
+ * @n_bonded_ch: In case of EDMG the number of bonded channels (1-4)
  */
 struct rate_info {
 	u8 flags;
@@ -1148,6 +1187,7 @@ struct rate_info {
 	u8 he_gi;
 	u8 he_dcm;
 	u8 he_ru_alloc;
+	u8 n_bonded_ch;
 };
 
 /**
@@ -2285,6 +2325,8 @@ struct cfg80211_bss_selection {
  * @fils_erp_rrk_len: Length of @fils_erp_rrk in octets.
  * @want_1x: indicates user-space supports and wants to use 802.1X driver
  *	offload of 4-way handshake.
+ * @edmg: enable EDMG mode.
+ * @edmg_channel: The EDMG channel to use.
  */
 struct cfg80211_connect_params {
 	struct ieee80211_channel *channel;
@@ -2318,6 +2360,8 @@ struct cfg80211_connect_params {
 	const u8 *fils_erp_rrk;
 	size_t fils_erp_rrk_len;
 	bool want_1x;
+	bool edmg;
+	u8 edmg_channel;
 };
 
 /**
diff --git a/include/uapi/linux/nl80211.h b/include/uapi/linux/nl80211.h
index 0239896..31b1312 100644
--- a/include/uapi/linux/nl80211.h
+++ b/include/uapi/linux/nl80211.h
@@ -2240,6 +2240,9 @@ enum nl80211_commands {
  * @NL80211_ATTR_HE_CAPABILITY: HE Capability information element (from
  *	association request when used with NL80211_CMD_NEW_STATION). Can be set
  *	only if %NL80211_STA_FLAG_WME is set.
+ * @NL80211_ATTR_WIPHY_EDMG: flag attribute. If set it means EDMG mode supported
+ * @NL80211_ATTR_WIPHY_EDMG_CHANNEL: EDMG channel to be used for AP
+ *      configuration and connect command.
  *
  * @NUM_NL80211_ATTR: total number of nl80211_attrs available
  * @NL80211_ATTR_MAX: highest attribute number currently defined
@@ -2682,6 +2685,9 @@ enum nl80211_attrs {
 
 	NL80211_ATTR_HE_CAPABILITY,
 
+	NL80211_ATTR_WIPHY_EDMG,
+	NL80211_ATTR_WIPHY_EDMG_CHANNEL,
+
 	/* add attributes here, update the policy in nl80211.c */
 
 	__NL80211_ATTR_AFTER_LAST,
@@ -3265,6 +3271,9 @@ enum nl80211_band_iftype_attr {
  * @NL80211_BAND_ATTR_VHT_CAPA: VHT capabilities, as in the HT information IE
  * @NL80211_BAND_ATTR_IFTYPE_DATA: nested array attribute, with each entry using
  *	attributes from &enum nl80211_band_iftype_attr
+ * @NL80211_BAND_ATTR_EDMG: flag attribute. If set it means EDMG mode supported
+ * @NL80211_BAND_ATTR_EDMG_SUPPORTED_CHAN: array of supported EDMG channels in
+ *	this band
  * @NL80211_BAND_ATTR_MAX: highest band attribute currently defined
  * @__NL80211_BAND_ATTR_AFTER_LAST: internal use
  */
@@ -3282,6 +3291,9 @@ enum nl80211_band_attr {
 	NL80211_BAND_ATTR_VHT_CAPA,
 	NL80211_BAND_ATTR_IFTYPE_DATA,
 
+	NL80211_BAND_ATTR_EDMG,
+	NL80211_BAND_ATTR_EDMG_SUPPORTED_CHAN,
+
 	/* keep last */
 	__NL80211_BAND_ATTR_AFTER_LAST,
 	NL80211_BAND_ATTR_MAX = __NL80211_BAND_ATTR_AFTER_LAST - 1
diff --git a/net/wireless/chan.c b/net/wireless/chan.c
index 2db713d..681f434 100644
--- a/net/wireless/chan.c
+++ b/net/wireless/chan.c
@@ -720,12 +720,94 @@ static bool cfg80211_secondary_chans_ok(struct wiphy *wiphy,
 	return true;
 }
 
+static const struct edmg_chan_table {
+	/* the edmg channel - 9,10,11... */
+	u8 edmg_chan;
+	/* the sub channels represented as a bitfield where the bit-index
+	 * corresponds to the legacy channel (bit 0 not used).
+	 */
+	u8 sub_chans;
+} cfg80211_edmg_table[] = {
+	{9, 0x06},	/* channels 1,2 */
+	{10, 0x0c},	/* channels 2,3 */
+	{11, 0x18},	/* channels 3,4 */
+	{12, 0x30},	/* channels 4,5 */
+	{13, 0x60},	/* channels 5,6 */
+	{17, 0x0e},	/* channels 1,2,3 */
+	{18, 0x1c},	/* channels 2,3,4 */
+	{19, 0x38},	/* channels 3,4,5 */
+	{20, 0x70},	/* channels 4,5,6 */
+	{25, 0x1e},	/* channels 1,2,3,4 */
+	{26, 0x3c},	/* channels 2,3,4,5 */
+	{27, 0x78},	/* channels 3,4,5,6 */
+};
+
+static u8 cfg80211_get_edmg_sub_chans(u8 edmg_channel)
+{
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(cfg80211_edmg_table); i++)
+		if (cfg80211_edmg_table[i].edmg_chan == edmg_channel)
+			return cfg80211_edmg_table[i].sub_chans;
+
+	return 0;
+}
+
+static bool cfg80211_check_edmg_sub_ch(struct wiphy *wiphy,
+				       u8 edmg_channel,
+				       int primary_channel)
+{
+	struct ieee80211_channel *chan;
+	int i, freq;
+	u8 sub_channels;
+
+	sub_channels = cfg80211_get_edmg_sub_chans(edmg_channel);
+	if (!sub_channels)
+		return false;
+
+	if (!(sub_channels & BIT(primary_channel)))
+		return false;
+
+	/* 60GHz channels 1..6 */
+	for (i = 1; i <= 6; i++) {
+		if (!(sub_channels & BIT(i)))
+			continue;
+
+		freq = ieee80211_channel_to_frequency(i, NL80211_BAND_60GHZ);
+		chan = ieee80211_get_channel(wiphy, freq);
+		if (!chan || chan->flags & IEEE80211_CHAN_DISABLED)
+			return false;
+	}
+
+	return true;
+}
+
+bool cfg80211_edmg_usable(struct wiphy *wiphy,
+			  struct ieee80211_sta_edmg_cap *edmg_cap,
+			  u8 edmg_channel, int primary_channel)
+{
+	int i;
+
+	if (!edmg_channel)
+		return true;
+
+	for (i = 0; i < edmg_cap->n_channels; i++)
+		if (edmg_channel == edmg_cap->channels[i])
+			break;
+
+	if (i == edmg_cap->n_channels)
+		return false;
+
+	return cfg80211_check_edmg_sub_ch(wiphy, edmg_channel, primary_channel);
+}
+
 bool cfg80211_chandef_usable(struct wiphy *wiphy,
 			     const struct cfg80211_chan_def *chandef,
 			     u32 prohibited_flags)
 {
 	struct ieee80211_sta_ht_cap *ht_cap;
 	struct ieee80211_sta_vht_cap *vht_cap;
+	struct ieee80211_sta_edmg_cap *edmg_cap;
 	u32 width, control_freq, cap;
 
 	if (WARN_ON(!cfg80211_chandef_valid(chandef)))
@@ -733,6 +815,12 @@ bool cfg80211_chandef_usable(struct wiphy *wiphy,
 
 	ht_cap = &wiphy->bands[chandef->chan->band]->ht_cap;
 	vht_cap = &wiphy->bands[chandef->chan->band]->vht_cap;
+	edmg_cap = &wiphy->bands[chandef->chan->band]->edmg_cap;
+
+	if (edmg_cap->supported &&
+	    !cfg80211_edmg_usable(wiphy, edmg_cap, chandef->edmg_channel,
+				  chandef->chan->hw_value))
+		return false;
 
 	control_freq = chandef->chan->center_freq;
 
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index 5fb9b7d..043b46f 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -209,6 +209,8 @@ enum nl80211_multicast_groups {
 
 	[NL80211_ATTR_WIPHY_FREQ] = { .type = NLA_U32 },
 	[NL80211_ATTR_WIPHY_CHANNEL_TYPE] = { .type = NLA_U32 },
+	[NL80211_ATTR_WIPHY_EDMG] = { .type = NLA_FLAG },
+	[NL80211_ATTR_WIPHY_EDMG_CHANNEL] = { .type = NLA_U8 },
 	[NL80211_ATTR_CHANNEL_WIDTH] = { .type = NLA_U32 },
 	[NL80211_ATTR_CENTER_FREQ1] = { .type = NLA_U32 },
 	[NL80211_ATTR_CENTER_FREQ2] = { .type = NLA_U32 },
@@ -1409,6 +1411,13 @@ static int nl80211_send_band_rateinfo(struct sk_buff *msg,
 		nla_nest_end(msg, nl_iftype_data);
 	}
 
+	/* add EDMG info */
+	if (sband->edmg_cap.supported &&
+	    (nla_put_flag(msg, NL80211_BAND_ATTR_EDMG) ||
+	     nla_put(msg, NL80211_BAND_ATTR_EDMG_SUPPORTED_CHAN,
+		     sband->edmg_cap.n_channels, sband->edmg_cap.channels)))
+		return -ENOBUFS;
+
 	/* add bitrates */
 	nl_rates = nla_nest_start(msg, NL80211_BAND_ATTR_RATES);
 	if (!nl_rates)
@@ -2303,6 +2312,8 @@ static int nl80211_parse_chandef(struct cfg80211_registered_device *rdev,
 	chandef->width = NL80211_CHAN_WIDTH_20_NOHT;
 	chandef->center_freq1 = control_freq;
 	chandef->center_freq2 = 0;
+	chandef->edmg_mode = 0;
+	chandef->edmg_channel = 0;
 
 	/* Primary channel not allowed */
 	if (!chandef->chan || chandef->chan->flags & IEEE80211_CHAN_DISABLED)
@@ -2347,6 +2358,14 @@ static int nl80211_parse_chandef(struct cfg80211_registered_device *rdev,
 					info->attrs[NL80211_ATTR_CENTER_FREQ2]);
 	}
 
+	if (info->attrs[NL80211_ATTR_WIPHY_EDMG])
+		chandef->edmg_mode =
+			nla_get_flag(info->attrs[NL80211_ATTR_WIPHY_EDMG]);
+
+	if (info->attrs[NL80211_ATTR_WIPHY_EDMG_CHANNEL])
+		chandef->edmg_channel =
+		       nla_get_u8(info->attrs[NL80211_ATTR_WIPHY_EDMG_CHANNEL]);
+
 	if (!cfg80211_chandef_valid(chandef))
 		return -EINVAL;
 
@@ -9302,6 +9321,7 @@ static int nl80211_connect(struct sk_buff *skb, struct genl_info *info)
 	struct cfg80211_connect_params connect;
 	struct wiphy *wiphy;
 	struct cfg80211_cached_keys *connkeys = NULL;
+	struct ieee80211_sta_edmg_cap *edmg_cap;
 	int err;
 
 	memset(&connect, 0, sizeof(connect));
@@ -9392,6 +9412,19 @@ static int nl80211_connect(struct sk_buff *skb, struct genl_info *info)
 			return -EINVAL;
 	}
 
+	if (info->attrs[NL80211_ATTR_WIPHY_EDMG]) {
+		connect.edmg =
+			nla_get_flag(info->attrs[NL80211_ATTR_WIPHY_EDMG]);
+		if (info->attrs[NL80211_ATTR_WIPHY_EDMG_CHANNEL])
+			connect.edmg_channel =
+		       nla_get_u8(info->attrs[NL80211_ATTR_WIPHY_EDMG_CHANNEL]);
+		edmg_cap = &rdev->wiphy.bands[NL80211_BAND_60GHZ]->edmg_cap;
+		if (edmg_cap && connect.edmg &&
+		    !cfg80211_edmg_usable(wiphy, edmg_cap, connect.edmg_channel,
+					  connect.channel->hw_value))
+			connect.edmg_channel = 0;
+	}
+
 	if (connect.privacy && info->attrs[NL80211_ATTR_KEYS]) {
 		connkeys = nl80211_parse_connkeys(rdev, info, NULL);
 		if (IS_ERR(connkeys))
diff --git a/net/wireless/util.c b/net/wireless/util.c
index a450736..08b43a2 100644
--- a/net/wireless/util.c
+++ b/net/wireless/util.c
@@ -1009,7 +1009,7 @@ static u32 cfg80211_calculate_bitrate_ht(struct rate_info *rate)
 	return (bitrate + 50000) / 100000;
 }
 
-static u32 cfg80211_calculate_bitrate_60g(struct rate_info *rate)
+static u32 cfg80211_calculate_bitrate_dmg(struct rate_info *rate)
 {
 	static const u32 __mcs2bitrate[] = {
 		/* control PHY */
@@ -1056,6 +1056,40 @@ static u32 cfg80211_calculate_bitrate_60g(struct rate_info *rate)
 	return __mcs2bitrate[rate->mcs];
 }
 
+static u32 cfg80211_calculate_bitrate_edmg(struct rate_info *rate)
+{
+	static const u32 __mcs2bitrate[] = {
+		/* control PHY */
+		[0] =   275,
+		/* SC PHY */
+		[1] =  3850,
+		[2] =  7700,
+		[3] =  9625,
+		[4] = 11550,
+		[5] = 12512, /* 1251.25 mbps */
+		[6] = 13475,
+		[7] = 15400,
+		[8] = 19250,
+		[9] = 23100,
+		[10] = 25025,
+		[11] = 26950,
+		[12] = 30800,
+		[13] = 38500,
+		[14] = 46200,
+		[15] = 50050,
+		[16] = 53900,
+		[17] = 57750,
+		[18] = 69300,
+		[19] = 75075,
+		[20] = 80850,
+	};
+
+	if (WARN_ON_ONCE(rate->mcs >= ARRAY_SIZE(__mcs2bitrate)))
+		return 0;
+
+	return __mcs2bitrate[rate->mcs] * rate->n_bonded_ch;
+}
+
 static u32 cfg80211_calculate_bitrate_vht(struct rate_info *rate)
 {
 	static const u32 base[4][10] = {
@@ -1226,8 +1260,10 @@ u32 cfg80211_calculate_bitrate(struct rate_info *rate)
 {
 	if (rate->flags & RATE_INFO_FLAGS_MCS)
 		return cfg80211_calculate_bitrate_ht(rate);
-	if (rate->flags & RATE_INFO_FLAGS_60G)
-		return cfg80211_calculate_bitrate_60g(rate);
+	if (rate->flags & RATE_INFO_FLAGS_DMG)
+		return cfg80211_calculate_bitrate_dmg(rate);
+	if (rate->flags & RATE_INFO_FLAGS_EDMG)
+		return cfg80211_calculate_bitrate_edmg(rate);
 	if (rate->flags & RATE_INFO_FLAGS_VHT_MCS)
 		return cfg80211_calculate_bitrate_vht(rate);
 	if (rate->flags & RATE_INFO_FLAGS_HE_MCS)
-- 
1.9.1

^ permalink raw reply related	[flat|nested] 7+ messages in thread

* [PATCH 3/3] wil6210: Add EDMG channel support
  2018-08-13 12:32 [PATCH 0/3] Add support for new channels on 60GHz band Alexei Avshalom Lazar
  2018-08-13 12:33 ` [PATCH 1/3] cfg80211: Add support for 60GHz band channels 5 and 6 Alexei Avshalom Lazar
  2018-08-13 12:33 ` [PATCH 2/3] nl80211: Add support for EDMG channels Alexei Avshalom Lazar
@ 2018-08-13 12:33 ` Alexei Avshalom Lazar
  2 siblings, 0 replies; 7+ messages in thread
From: Alexei Avshalom Lazar @ 2018-08-13 12:33 UTC (permalink / raw)
  To: Johannes Berg; +Cc: Alexei Avshalom Lazar, linux-wireless, wil6210

Add support for Enhanced Directional Multi-Gigabit (EDMG) channels 9-11.
wil6210 reports it's EDMG capabilities (that are also based on FW
capability) to cfg80211 by filling
wiphy->bands[NL80211_BAND_60GHZ]->edmg_cap.
wil6210 handles edmg_channel requested in connect and start_ap
operations.

Signed-off-by: Alexei Avshalom Lazar <ailizaro@codeaurora.org>
---
 drivers/net/wireless/ath/wil6210/cfg80211.c  | 194 +++++++++++++++++++++++++--
 drivers/net/wireless/ath/wil6210/main.c      |   3 +
 drivers/net/wireless/ath/wil6210/txrx_edma.c |   2 +
 drivers/net/wireless/ath/wil6210/txrx_edma.h |   6 +
 drivers/net/wireless/ath/wil6210/wil6210.h   |   6 +-
 drivers/net/wireless/ath/wil6210/wmi.c       |   5 +-
 drivers/net/wireless/ath/wil6210/wmi.h       |  43 +++++-
 7 files changed, 242 insertions(+), 17 deletions(-)

diff --git a/drivers/net/wireless/ath/wil6210/cfg80211.c b/drivers/net/wireless/ath/wil6210/cfg80211.c
index 4740b53..63c8f44 100644
--- a/drivers/net/wireless/ath/wil6210/cfg80211.c
+++ b/drivers/net/wireless/ath/wil6210/cfg80211.c
@@ -51,6 +51,52 @@
 /* channel 4 not supported yet */
 };
 
+/* supported EDMG channels */
+static u8 wil_edmg_channels[] = {9, 10};
+
+/* Rx channel bonding mode */
+enum wil_rx_cb_mode {
+	WIL_RX_CB_MODE_DMG,
+	WIL_RX_CB_MODE_EDMG,
+	WIL_RX_CB_MODE_WIDE,
+};
+
+static int wil_rx_cb_mode_to_n_bonded(u8 cb_mode)
+{
+	switch (cb_mode) {
+	case WIL_RX_CB_MODE_DMG:
+	case WIL_RX_CB_MODE_EDMG:
+		return 1;
+	case WIL_RX_CB_MODE_WIDE:
+		return 2;
+	default:
+		return 1;
+	}
+}
+
+static int wil_tx_cb_mode_to_n_bonded(u8 cb_mode)
+{
+	switch (cb_mode) {
+	case WMI_TX_MODE_DMG:
+	case WMI_TX_MODE_EDMG_CB1:
+		return 1;
+	case WMI_TX_MODE_EDMG_CB2:
+		return 2;
+	default:
+		return 1;
+	}
+}
+
+void wil_update_supported_bands(struct wil6210_priv *wil)
+{
+	struct wiphy *wiphy = wil_to_wiphy(wil);
+
+	wiphy->bands[NL80211_BAND_60GHZ]->edmg_cap.channels = wil_edmg_channels;
+	wiphy->bands[NL80211_BAND_60GHZ]->edmg_cap.n_channels =
+						ARRAY_SIZE(wil_edmg_channels);
+	wiphy->bands[NL80211_BAND_60GHZ]->edmg_cap.supported = true;
+}
+
 /* Vendor id to be used in vendor specific command and events
  * to user space.
  * NOTE: The authoritative place for definition of QCA_NL80211_VENDOR_ID,
@@ -261,6 +307,86 @@ int wil_iftype_nl2wmi(enum nl80211_iftype type)
 	return -EOPNOTSUPP;
 }
 
+int wil_spec2wmi_ch(u8 spec_ch, u8 *wmi_ch)
+{
+	switch (spec_ch) {
+	case 1:
+		*wmi_ch = WMI_CHANNEL_1;
+		break;
+	case 2:
+		*wmi_ch = WMI_CHANNEL_2;
+		break;
+	case 3:
+		*wmi_ch = WMI_CHANNEL_3;
+		break;
+	case 4:
+		*wmi_ch = WMI_CHANNEL_4;
+		break;
+	case 5:
+		*wmi_ch = WMI_CHANNEL_5;
+		break;
+	case 6:
+		*wmi_ch = WMI_CHANNEL_6;
+		break;
+	case 9:
+		*wmi_ch = WMI_CHANNEL_9;
+		break;
+	case 10:
+		*wmi_ch = WMI_CHANNEL_10;
+		break;
+	case 11:
+		*wmi_ch = WMI_CHANNEL_11;
+		break;
+	case 12:
+		*wmi_ch = WMI_CHANNEL_12;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+int wil_wmi2spec_ch(u8 wmi_ch, u8 *spec_ch)
+{
+	switch (wmi_ch) {
+	case WMI_CHANNEL_1:
+		*spec_ch = 1;
+		break;
+	case WMI_CHANNEL_2:
+		*spec_ch = 2;
+		break;
+	case WMI_CHANNEL_3:
+		*spec_ch = 3;
+		break;
+	case WMI_CHANNEL_4:
+		*spec_ch = 4;
+		break;
+	case WMI_CHANNEL_5:
+		*spec_ch = 5;
+		break;
+	case WMI_CHANNEL_6:
+		*spec_ch = 6;
+		break;
+	case WMI_CHANNEL_9:
+		*spec_ch = 9;
+		break;
+	case WMI_CHANNEL_10:
+		*spec_ch = 10;
+		break;
+	case WMI_CHANNEL_11:
+		*spec_ch = 11;
+		break;
+	case WMI_CHANNEL_12:
+		*spec_ch = 12;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
 int wil_cid_fill_sinfo(struct wil6210_vif *vif, int cid,
 		       struct station_info *sinfo)
 {
@@ -275,6 +401,7 @@ int wil_cid_fill_sinfo(struct wil6210_vif *vif, int cid,
 	} __packed reply;
 	struct wil_net_stats *stats = &wil->sta[cid].stats;
 	int rc;
+	u8 txflag = RATE_INFO_FLAGS_DMG;
 
 	memset(&reply, 0, sizeof(reply));
 
@@ -287,7 +414,8 @@ int wil_cid_fill_sinfo(struct wil6210_vif *vif, int cid,
 		    "  MCS %d TSF 0x%016llx\n"
 		    "  BF status 0x%08x RSSI %d SQI %d%%\n"
 		    "  Tx Tpt %d goodput %d Rx goodput %d\n"
-		    "  Sectors(rx:tx) my %d:%d peer %d:%d\n""}\n",
+		    "  Sectors(rx:tx) my %d:%d peer %d:%d\n"
+		    "  Tx mode %d}\n",
 		    cid, vif->mid, le16_to_cpu(reply.evt.bf_mcs),
 		    le64_to_cpu(reply.evt.tsf), reply.evt.status,
 		    reply.evt.rssi,
@@ -298,7 +426,8 @@ int wil_cid_fill_sinfo(struct wil6210_vif *vif, int cid,
 		    le16_to_cpu(reply.evt.my_rx_sector),
 		    le16_to_cpu(reply.evt.my_tx_sector),
 		    le16_to_cpu(reply.evt.other_rx_sector),
-		    le16_to_cpu(reply.evt.other_tx_sector));
+		    le16_to_cpu(reply.evt.other_tx_sector),
+		    reply.evt.tx_mode);
 
 	sinfo->generation = wil->sinfo_gen;
 
@@ -311,9 +440,16 @@ int wil_cid_fill_sinfo(struct wil6210_vif *vif, int cid,
 			BIT_ULL(NL80211_STA_INFO_RX_DROP_MISC) |
 			BIT_ULL(NL80211_STA_INFO_TX_FAILED);
 
-	sinfo->txrate.flags = RATE_INFO_FLAGS_DMG;
+	if (wil->use_enhanced_dma_hw && reply.evt.tx_mode != WMI_TX_MODE_DMG)
+		txflag = RATE_INFO_FLAGS_EDMG;
+
+	sinfo->txrate.flags = txflag;
 	sinfo->txrate.mcs = le16_to_cpu(reply.evt.bf_mcs);
 	sinfo->rxrate.mcs = stats->last_mcs_rx;
+	sinfo->txrate.n_bonded_ch =
+				wil_tx_cb_mode_to_n_bonded(reply.evt.tx_mode);
+	sinfo->rxrate.n_bonded_ch =
+			wil_rx_cb_mode_to_n_bonded(stats->last_cb_mode_rx);
 	sinfo->rx_bytes = stats->rx_bytes;
 	sinfo->rx_packets = stats->rx_packets;
 	sinfo->rx_dropped_misc = stats->rx_dropped;
@@ -888,6 +1024,30 @@ static void wil_print_connect_params(struct wil6210_priv *wil,
 	wil_print_crypto(wil, &sme->crypto);
 }
 
+static int wil_get_wmi_edmg_channel(struct wil6210_priv *wil, u8 edmg_channel,
+				    u8 *wmi_ch)
+{
+	int rc;
+
+	if (!test_bit(WMI_FW_CAPABILITY_CHANNEL_BONDING,
+		      wil->fw_capabilities) && edmg_channel)
+		return -EOPNOTSUPP;
+
+	if (edmg_channel) {
+		rc = wil_spec2wmi_ch(edmg_channel, wmi_ch);
+		if (rc) {
+			wil_err(wil, "wmi channel for spec channel %d not found\n",
+				edmg_channel);
+			return rc;
+		}
+		wil_dbg_misc(wil, "Set WMI channel %d\n", *wmi_ch);
+	} else {
+		wmi_ch = 0;
+	}
+
+	return 0;
+}
+
 static int wil_cfg80211_connect(struct wiphy *wiphy,
 				struct net_device *ndev,
 				struct cfg80211_connect_params *sme)
@@ -1007,6 +1167,11 @@ static int wil_cfg80211_connect(struct wiphy *wiphy,
 	}
 	conn.channel = ch - 1;
 
+	rc = wil_get_wmi_edmg_channel(wil, sme->edmg_channel,
+				      &conn.edmg_channel);
+	if (rc)
+		return rc;
+
 	ether_addr_copy(conn.bssid, bss->bssid);
 	ether_addr_copy(conn.dst_mac, bss->bssid);
 
@@ -1482,7 +1647,7 @@ static int _wil_cfg80211_set_ies(struct wil6210_vif *vif,
 static int _wil_cfg80211_start_ap(struct wiphy *wiphy,
 				  struct net_device *ndev,
 				  const u8 *ssid, size_t ssid_len, u32 privacy,
-				  int bi, u8 chan,
+				  int bi, u8 chan, u8 edmg_channel,
 				  struct cfg80211_beacon_data *bcon,
 				  u8 hidden_ssid, u32 pbss)
 {
@@ -1492,6 +1657,7 @@ static int _wil_cfg80211_start_ap(struct wiphy *wiphy,
 	struct wireless_dev *wdev = ndev->ieee80211_ptr;
 	u8 wmi_nettype = wil_iftype_nl2wmi(wdev->iftype);
 	u8 is_go = (wdev->iftype == NL80211_IFTYPE_P2P_GO);
+	u8 wmi_edmg_chan;
 
 	if (pbss)
 		wmi_nettype = WMI_NETTYPE_P2P;
@@ -1521,8 +1687,13 @@ static int _wil_cfg80211_start_ap(struct wiphy *wiphy,
 	if (rc)
 		goto out;
 
+	rc = wil_get_wmi_edmg_channel(wil, edmg_channel, &wmi_edmg_chan);
+	if (rc)
+		goto out;
+
 	vif->privacy = privacy;
 	vif->channel = chan;
+	vif->edmg_channel = edmg_channel;
 	vif->hidden_ssid = hidden_ssid;
 	vif->pbss = pbss;
 
@@ -1530,7 +1701,8 @@ static int _wil_cfg80211_start_ap(struct wiphy *wiphy,
 	if (!wil_has_other_active_ifaces(wil, ndev, false, true))
 		wil6210_bus_request(wil, WIL_MAX_BUS_REQUEST_KBPS);
 
-	rc = wmi_pcp_start(vif, bi, wmi_nettype, chan, hidden_ssid, is_go);
+	rc = wmi_pcp_start(vif, bi, wmi_nettype, chan, wmi_edmg_chan,
+			   hidden_ssid, is_go);
 	if (rc)
 		goto err_pcp_start;
 
@@ -1578,7 +1750,8 @@ static int wil_cfg80211_change_beacon(struct wiphy *wiphy,
 		rc = _wil_cfg80211_start_ap(wiphy, ndev, wdev->ssid,
 					    wdev->ssid_len, privacy,
 					    wdev->beacon_interval,
-					    vif->channel, bcon,
+					    vif->channel,
+					    vif->edmg_channel, bcon,
 					    vif->hidden_ssid,
 					    vif->pbss);
 	} else {
@@ -1597,6 +1770,7 @@ static int wil_cfg80211_start_ap(struct wiphy *wiphy,
 	struct ieee80211_channel *channel = info->chandef.chan;
 	struct cfg80211_beacon_data *bcon = &info->beacon;
 	struct cfg80211_crypto_settings *crypto = &info->crypto;
+	u8 edmg_channel = info->chandef.edmg_channel;
 	u8 hidden_ssid;
 
 	wil_dbg_misc(wil, "start_ap\n");
@@ -1637,10 +1811,10 @@ static int wil_cfg80211_start_ap(struct wiphy *wiphy,
 	wil_print_bcon_data(bcon);
 	wil_print_crypto(wil, crypto);
 
-	rc = _wil_cfg80211_start_ap(wiphy, ndev,
-				    info->ssid, info->ssid_len, info->privacy,
-				    info->beacon_interval, channel->hw_value,
-				    bcon, hidden_ssid, info->pbss);
+	rc = _wil_cfg80211_start_ap(wiphy, ndev, info->ssid, info->ssid_len,
+				    info->privacy, info->beacon_interval,
+				    channel->hw_value, edmg_channel, bcon,
+				    hidden_ssid, info->pbss);
 
 	return rc;
 }
diff --git a/drivers/net/wireless/ath/wil6210/main.c b/drivers/net/wireless/ath/wil6210/main.c
index 4de19bd..7e2fcf3 100644
--- a/drivers/net/wireless/ath/wil6210/main.c
+++ b/drivers/net/wireless/ath/wil6210/main.c
@@ -1137,6 +1137,9 @@ void wil_refresh_fw_capabilities(struct wil6210_priv *wil)
 
 		wil->platform_ops.set_features(wil->platform_handle, features);
 	}
+
+	if (test_bit(WMI_FW_CAPABILITY_CHANNEL_BONDING, wil->fw_capabilities))
+		wil_update_supported_bands(wil);
 }
 
 void wil_mbox_ring_le2cpus(struct wil6210_mbox_ring *r)
diff --git a/drivers/net/wireless/ath/wil6210/txrx_edma.c b/drivers/net/wireless/ath/wil6210/txrx_edma.c
index 95f38e6..64bc0fb 100644
--- a/drivers/net/wireless/ath/wil6210/txrx_edma.c
+++ b/drivers/net/wireless/ath/wil6210/txrx_edma.c
@@ -1002,6 +1002,8 @@ static struct sk_buff *wil_sring_reap_rx_edma(struct wil6210_priv *wil,
 			stats->rx_per_mcs[stats->last_mcs_rx]++;
 	}
 
+	stats->last_cb_mode_rx  = wil_rx_status_get_cb_mode(msg);
+
 	if (!wil->use_rx_hw_reordering && !wil->use_compressed_rx_status &&
 	    wil_check_bar(wil, msg, cid, skb, stats) == -EAGAIN) {
 		kfree_skb(skb);
diff --git a/drivers/net/wireless/ath/wil6210/txrx_edma.h b/drivers/net/wireless/ath/wil6210/txrx_edma.h
index e86fc2d..e7afa8b 100644
--- a/drivers/net/wireless/ath/wil6210/txrx_edma.h
+++ b/drivers/net/wireless/ath/wil6210/txrx_edma.h
@@ -366,6 +366,12 @@ static inline u8 wil_rx_status_get_mcs(void *msg)
 			    16, 21);
 }
 
+static inline u8 wil_rx_status_get_cb_mode(void *msg)
+{
+	return WIL_GET_BITS(((struct wil_rx_status_compressed *)msg)->d1,
+			    22, 23);
+}
+
 static inline u16 wil_rx_status_get_flow_id(void *msg)
 {
 	return WIL_GET_BITS(((struct wil_rx_status_compressed *)msg)->d0,
diff --git a/drivers/net/wireless/ath/wil6210/wil6210.h b/drivers/net/wireless/ath/wil6210/wil6210.h
index d963c76..6baf5db 100644
--- a/drivers/net/wireless/ath/wil6210/wil6210.h
+++ b/drivers/net/wireless/ath/wil6210/wil6210.h
@@ -690,6 +690,7 @@ struct wil_net_stats {
 	unsigned long	rx_key_error; /* eDMA specific */
 	unsigned long	rx_amsdu_error; /* eDMA specific */
 	u16 last_mcs_rx;
+	u8 last_cb_mode_rx;
 	u64 rx_per_mcs[WIL_MCS_MAX + 1];
 };
 
@@ -803,6 +804,7 @@ struct wil6210_vif {
 	DECLARE_BITMAP(status, wil_vif_status_last);
 	u32 privacy; /* secure connection? */
 	u16 channel; /* relevant in AP mode */
+	u8 edmg_channel; /* relevant in AP mode */
 	u8 hidden_ssid; /* relevant in AP mode */
 	u32 ap_isolate; /* no intra-BSS communication */
 	bool pbss;
@@ -1236,7 +1238,7 @@ int wil_cid_fill_sinfo(struct wil6210_vif *vif, int cid,
 
 int wmi_set_mac_address(struct wil6210_priv *wil, void *addr);
 int wmi_pcp_start(struct wil6210_vif *vif, int bi, u8 wmi_nettype, u8 chan,
-		  u8 hidden_ssid, u8 is_go);
+		  u8 edmg_chan, u8 hidden_ssid, u8 is_go);
 int wmi_pcp_stop(struct wil6210_vif *vif);
 int wmi_led_cfg(struct wil6210_priv *wil, bool enable);
 int wmi_abort_scan(struct wil6210_vif *vif);
@@ -1305,6 +1307,8 @@ int wmi_start_sched_scan(struct wil6210_priv *wil,
 int wmi_stop_sched_scan(struct wil6210_priv *wil);
 int wmi_mgmt_tx(struct wil6210_vif *vif, const u8 *buf, size_t len);
 
+void wil_update_supported_bands(struct wil6210_priv *wil);
+
 int reverse_memcmp(const void *cs, const void *ct, size_t count);
 
 /* WMI for enhanced DMA */
diff --git a/drivers/net/wireless/ath/wil6210/wmi.c b/drivers/net/wireless/ath/wil6210/wmi.c
index 71056c8..77f0e6c 100644
--- a/drivers/net/wireless/ath/wil6210/wmi.c
+++ b/drivers/net/wireless/ath/wil6210/wmi.c
@@ -1628,8 +1628,8 @@ int wmi_led_cfg(struct wil6210_priv *wil, bool enable)
 	return rc;
 }
 
-int wmi_pcp_start(struct wil6210_vif *vif,
-		  int bi, u8 wmi_nettype, u8 chan, u8 hidden_ssid, u8 is_go)
+int wmi_pcp_start(struct wil6210_vif *vif, int bi, u8 wmi_nettype,
+		  u8 chan, u8 edmg_chan, u8 hidden_ssid, u8 is_go)
 {
 	struct wil6210_priv *wil = vif_to_wil(vif);
 	int rc;
@@ -1639,6 +1639,7 @@ int wmi_pcp_start(struct wil6210_vif *vif,
 		.network_type = wmi_nettype,
 		.disable_sec_offload = 1,
 		.channel = chan - 1,
+		.edmg_channel = edmg_chan,
 		.pcp_max_assoc_sta = max_assoc_sta,
 		.hidden_ssid = hidden_ssid,
 		.is_go = is_go,
diff --git a/drivers/net/wireless/ath/wil6210/wmi.h b/drivers/net/wireless/ath/wil6210/wmi.h
index abf6f05..2018014 100644
--- a/drivers/net/wireless/ath/wil6210/wmi.h
+++ b/drivers/net/wireless/ath/wil6210/wmi.h
@@ -84,6 +84,7 @@ enum wmi_fw_capability {
 	WMI_FW_CAPABILITY_SET_SILENT_RSSI_TABLE		= 13,
 	WMI_FW_CAPABILITY_LO_POWER_CALIB_FROM_OTP	= 14,
 	WMI_FW_CAPABILITY_PNO				= 15,
+	WMI_FW_CAPABILITY_CHANNEL_BONDING		= 17,
 	WMI_FW_CAPABILITY_REF_CLOCK_CONTROL		= 18,
 	WMI_FW_CAPABILITY_AP_SME_OFFLOAD_NONE		= 19,
 	WMI_FW_CAPABILITY_AMSDU				= 23,
@@ -313,6 +314,19 @@ enum wmi_connect_ctrl_flag_bits {
 
 #define WMI_MAX_SSID_LEN	(32)
 
+enum wmi_channel {
+	WMI_CHANNEL_1	= 0x00,
+	WMI_CHANNEL_2	= 0x01,
+	WMI_CHANNEL_3	= 0x02,
+	WMI_CHANNEL_4	= 0x03,
+	WMI_CHANNEL_5	= 0x04,
+	WMI_CHANNEL_6	= 0x05,
+	WMI_CHANNEL_9	= 0x06,
+	WMI_CHANNEL_10	= 0x07,
+	WMI_CHANNEL_11	= 0x08,
+	WMI_CHANNEL_12	= 0x09,
+};
+
 /* WMI_CONNECT_CMDID */
 struct wmi_connect_cmd {
 	u8 network_type;
@@ -324,8 +338,12 @@ struct wmi_connect_cmd {
 	u8 group_crypto_len;
 	u8 ssid_len;
 	u8 ssid[WMI_MAX_SSID_LEN];
+	/* enum wmi_channel WMI_CHANNEL_1..WMI_CHANNEL_6; for EDMG this is
+	 * the primary channel number
+	 */
 	u8 channel;
-	u8 reserved0;
+	/* enum wmi_channel WMI_CHANNEL_9..WMI_CHANNEL_12 */
+	u8 edmg_channel;
 	u8 bssid[WMI_MAC_LEN];
 	__le32 ctrl_flags;
 	u8 dst_mac[WMI_MAC_LEN];
@@ -643,7 +661,9 @@ struct wmi_pcp_start_cmd {
 	u8 pcp_max_assoc_sta;
 	u8 hidden_ssid;
 	u8 is_go;
-	u8 reserved0[5];
+	/* enum wmi_channel WMI_CHANNEL_9..WMI_CHANNEL_12 */
+	u8 edmg_channel;
+	u8 reserved0[4];
 	/* A-BFT length override if non-0 */
 	u8 abft_len;
 	/* enum wmi_ap_sme_offload_mode_e */
@@ -1876,13 +1896,24 @@ struct wmi_ready_event {
 	u8 reserved[2];
 } __packed;
 
+enum wmi_edmg_tx_mode {
+	WMI_TX_MODE_DMG			= 0x0,
+	WMI_TX_MODE_EDMG_CB1		= 0x1,
+	WMI_TX_MODE_EDMG_CB2		= 0x2,
+	WMI_TX_MODE_EDMG_CB1_LONG_LDPC	= 0x3,
+	WMI_TX_MODE_EDMG_CB2_LONG_LDPC	= 0x4,
+	WMI_TX_MODE_MAX,
+};
+
 /* WMI_NOTIFY_REQ_DONE_EVENTID */
 struct wmi_notify_req_done_event {
 	/* beamforming status, 0: fail; 1: OK; 2: retrying */
 	__le32 status;
 	__le64 tsf;
 	s8 rssi;
-	u8 reserved0[3];
+	/* enum wmi_edmg_tx_mode */
+	u8 tx_mode;
+	u8 reserved0[2];
 	__le32 tx_tpt;
 	__le32 tx_goodput;
 	__le32 rx_goodput;
@@ -1898,8 +1929,12 @@ struct wmi_notify_req_done_event {
 
 /* WMI_CONNECT_EVENTID */
 struct wmi_connect_event {
+	/* enum wmi_channel WMI_CHANNEL_1..WMI_CHANNEL_6; for EDMG this is
+	 * the primary channel number
+	 */
 	u8 channel;
-	u8 reserved0;
+	/* enum wmi_channel WMI_CHANNEL_9..WMI_CHANNEL_12 */
+	u8 edmg_channel;
 	u8 bssid[WMI_MAC_LEN];
 	__le16 listen_interval;
 	__le16 beacon_interval;
-- 
1.9.1

^ permalink raw reply related	[flat|nested] 7+ messages in thread

* Re: [PATCH 1/3] cfg80211: Add support for 60GHz band channels 5 and 6
  2018-08-13 12:33 ` [PATCH 1/3] cfg80211: Add support for 60GHz band channels 5 and 6 Alexei Avshalom Lazar
@ 2018-08-28  9:25   ` Johannes Berg
  0 siblings, 0 replies; 7+ messages in thread
From: Johannes Berg @ 2018-08-28  9:25 UTC (permalink / raw)
  To: Alexei Avshalom Lazar; +Cc: linux-wireless, wil6210

On Mon, 2018-08-13 at 15:33 +0300, Alexei Avshalom Lazar wrote:
> The current support in the 60GHz band is for channels 1-4.
> Add support for channels 5 and 6.
> This requires enlarging ieee80211_channel.center_freq from u16 to u32.

Applied.

johannes

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [PATCH 2/3] nl80211: Add support for EDMG channels
  2018-08-13 12:33 ` [PATCH 2/3] nl80211: Add support for EDMG channels Alexei Avshalom Lazar
@ 2018-08-28  9:33   ` Johannes Berg
  2019-05-13 14:38     ` Alexei Avshalom Lazar
  0 siblings, 1 reply; 7+ messages in thread
From: Johannes Berg @ 2018-08-28  9:33 UTC (permalink / raw)
  To: Alexei Avshalom Lazar; +Cc: linux-wireless, wil6210

On Mon, 2018-08-13 at 15:33 +0300, Alexei Avshalom Lazar wrote:
> 
>  /**
> + * struct ieee80211_sta_edmg_cap - EDMG capabilities
> + *
> + * This structure describes most essential parameters needed
> + * to describe 802.11ay EDMG capabilities
> + *
> + * @supported: is EDMG supported, Device may support EDMG
> + *	without supporting channel bonding. In this case
> + *	supported would be TRUE with n_channels = 0

TRUE -> %true

> + * @channels: supported ieee EDMG channel numbers

IEEE

> + * @n_channels: Number of channels in @channels
> + */
> +struct ieee80211_sta_edmg_cap {
> +	bool supported;
> +	u8 *channels;

const?

But really this is pointless - there are *two* channels here (6 and 7),
and so at most you point to a 2-byte array? Just make it

	u8 channels[2];

or something and save the whole pointering?

Ok, no, there are 9-25 or something, so I guess more than that...

Uh. Why do we bother though? Do we need the channel number anywhere? Why
not just let userspace specify the bitmap to start with?

Would there really be devices that base their support for channels on
anything other than support for the underlying DMG channels?


>   * @center_freq1: center frequency of first segment
>   * @center_freq2: center frequency of second segment
>   *	(only with 80+80 MHz)
> + * @edmg_mode: if defined, edmg supported and primary channel is EDMG
> + * @edmg_channel: the EDMG channel
>   */
>  struct cfg80211_chan_def {
>  	struct ieee80211_channel *chan;
>  	enum nl80211_chan_width width;
>  	u32 center_freq1;
>  	u32 center_freq2;
> +	bool edmg_mode;
> +	u8 edmg_channel;

This seems odd. What do you put into chan_width if it's EDMG then? What
do you put into the chan pointer?

> + * @NL80211_ATTR_WIPHY_EDMG_CHANNEL: EDMG channel to be used for AP
> + *      configuration and connect command.

u8 is intended, I assume?

But why do you need this anyhow? The EDMG channel has a frequency just
like all other channels, no? Can't we continue to use the existing
attributes?

> +static const struct edmg_chan_table {
> +	/* the edmg channel - 9,10,11... */
> +	u8 edmg_chan;
> +	/* the sub channels represented as a bitfield where the bit-index
> +	 * corresponds to the legacy channel (bit 0 not used).
> +	 */
> +	u8 sub_chans;

Uh, ok, so I guess it's more complicated?

I'm not familiar with 802.11ay ... I guess a short primer should be in
the patch set here somewhere :)

> +} cfg80211_edmg_table[] = {
> +	{9, 0x06},	/* channels 1,2 */

BIT(1) | BIT(2) ? then you don't really need the comments ...

> +	{10, 0x0c},	/* channels 2,3 */
> +	{11, 0x18},	/* channels 3,4 */
> +	{12, 0x30},	/* channels 4,5 */
> +	{13, 0x60},	/* channels 5,6 */
> +	{17, 0x0e},	/* channels 1,2,3 */
> +	{18, 0x1c},	/* channels 2,3,4 */
> +	{19, 0x38},	/* channels 3,4,5 */
> +	{20, 0x70},	/* channels 4,5,6 */

What happened to 21-24?

> +	{25, 0x1e},	/* channels 1,2,3,4 */

> +static u8 cfg80211_get_edmg_sub_chans(u8 edmg_channel)
> +{
> +	int i;
> +
> +	for (i = 0; i < ARRAY_SIZE(cfg80211_edmg_table); i++)
> +		if (cfg80211_edmg_table[i].edmg_chan == edmg_channel)
> +			return cfg80211_edmg_table[i].sub_chans;

Maybe just index the array at "edmg_channel - 9", add dummies for 21-24
and save the whole loop? I guess it doesn't matter so much though.

johannes

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [PATCH 2/3] nl80211: Add support for EDMG channels
  2018-08-28  9:33   ` Johannes Berg
@ 2019-05-13 14:38     ` Alexei Avshalom Lazar
  0 siblings, 0 replies; 7+ messages in thread
From: Alexei Avshalom Lazar @ 2019-05-13 14:38 UTC (permalink / raw)
  To: Johannes Berg; +Cc: linux-wireless, wil6210



On 8/28/2018 12:33 PM, Johannes Berg wrote:
> On Mon, 2018-08-13 at 15:33 +0300, Alexei Avshalom Lazar wrote:
>>

Hi Johannes

The implementation has been updated according to the latest spec draft, 
Draft P802.11ay_D3.0
Most of the code that you commented has been updated in the new patch 
and your comments were taken into consideration where applicable.
I will upload an updated version of the patches shortly.

>>   /**
>> + * struct ieee80211_sta_edmg_cap - EDMG capabilities
>> + *
>> + * This structure describes most essential parameters needed
>> + * to describe 802.11ay EDMG capabilities
>> + *
>> + * @supported: is EDMG supported, Device may support EDMG
>> + *	without supporting channel bonding. In this case
>> + *	supported would be TRUE with n_channels = 0
> 
> TRUE -> %true

Not relevant with new patch.

> 
>> + * @channels: supported ieee EDMG channel numbers
> 
> IEEE

Not relevant with new patch.

> 
>> + * @n_channels: Number of channels in @channels
>> + */
>> +struct ieee80211_sta_edmg_cap {
>> +	bool supported;
>> +	u8 *channels;
> 
> const?
> 
> But really this is pointless - there are *two* channels here (6 and 7),
> and so at most you point to a 2-byte array? Just make it
> 
> 	u8 channels[2];
> 
> or something and save the whole pointering?
> 
> Ok, no, there are 9-25 or something, so I guess more than that...
> 
> Uh. Why do we bother though? Do we need the channel number anywhere? Why
> not just let userspace specify the bitmap to start with?
> 
> Would there really be devices that base their support for channels on
> anything other than support for the underlying DMG channels?

Devices will base their support on the combination of EDMG CB1 channels 
with the allowed bandwidth, for example if channels 1-3 are supported it 
doesn’t necessarily mean that CB3 (channel bonding of 3 channels) is 
supported. It is possible that device supports only CB2 (bonding of 2 
channels).
Please notice that the representation of the capabilities has been 
updated in the new patch.

> 
> 
>>    * @center_freq1: center frequency of first segment
>>    * @center_freq2: center frequency of second segment
>>    *	(only with 80+80 MHz)
>> + * @edmg_mode: if defined, edmg supported and primary channel is EDMG
>> + * @edmg_channel: the EDMG channel
>>    */
>>   struct cfg80211_chan_def {
>>   	struct ieee80211_channel *chan;
>>   	enum nl80211_chan_width width;
>>   	u32 center_freq1;
>>   	u32 center_freq2;
>> +	bool edmg_mode;
>> +	u8 edmg_channel;
> 
> This seems odd. What do you put into chan_width if it's EDMG then? What
> do you put into the chan pointer?

chan_width is not used today for the 11ad and cannot be used for channel 
bonding because the 11ay bandwidth configuration can have more than one 
option, for example - bandwidth configuration #13 means device can 
choose to associate on 2.16 or 4.32 or 2.16+2.16 channel width.
For the 11ay purposes the chan pointer has the information for the 
primary channel, band,  c_freq, hw_value (same as DMG case).

> 
>> + * @NL80211_ATTR_WIPHY_EDMG_CHANNEL: EDMG channel to be used for AP
>> + *      configuration and connect command.
> 
> u8 is intended, I assume?
> 
> But why do you need this anyhow? The EDMG channel has a frequency just
> like all other channels, no? Can't we continue to use the existing
> attributes?

This has been updated to bitmap of the legacy channel and the bandwidth 
configuration.
frequency attribute will be meaningless because they won't represent the 
relevant possibilities that defined by the spec, for example if the AP 
support CB2 and CB3 we won't be able to represent it with the frequencies.

> 
>> +static const struct edmg_chan_table {
>> +	/* the edmg channel - 9,10,11... */
>> +	u8 edmg_chan;
>> +	/* the sub channels represented as a bitfield where the bit-index
>> +	 * corresponds to the legacy channel (bit 0 not used).
>> +	 */
>> +	u8 sub_chans;
> 
> Uh, ok, so I guess it's more complicated?
> 
> I'm not familiar with 802.11ay ... I guess a short primer should be in
> the patch set here somewhere :)
> 
>> +} cfg80211_edmg_table[] = {
>> +	{9, 0x06},	/* channels 1,2 */
> 
> BIT(1) | BIT(2) ? then you don't really need the comments ...

Agree but not relevant with new patch.

> 
>> +	{10, 0x0c},	/* channels 2,3 */
>> +	{11, 0x18},	/* channels 3,4 */
>> +	{12, 0x30},	/* channels 4,5 */
>> +	{13, 0x60},	/* channels 5,6 */
>> +	{17, 0x0e},	/* channels 1,2,3 */
>> +	{18, 0x1c},	/* channels 2,3,4 */
>> +	{19, 0x38},	/* channels 3,4,5 */
>> +	{20, 0x70},	/* channels 4,5,6 */
> 
> What happened to 21-24?

The spec doesn’t define contiguous channel numbers so 21-24 are not 
defined, same for 14-16.

> 
>> +	{25, 0x1e},	/* channels 1,2,3,4 */
> 
>> +static u8 cfg80211_get_edmg_sub_chans(u8 edmg_channel)
>> +{
>> +	int i;
>> +
>> +	for (i = 0; i < ARRAY_SIZE(cfg80211_edmg_table); i++)
>> +		if (cfg80211_edmg_table[i].edmg_chan == edmg_channel)
>> +			return cfg80211_edmg_table[i].sub_chans;
> 
> Maybe just index the array at "edmg_channel - 9", add dummies for 21-24
> and save the whole loop? I guess it doesn't matter so much though.

Not relevant with new patch.

> 
> johannes
> 

-- 
Alexei Lazar
Qualcomm Israel, on behalf of Qualcomm Innovation Center, Inc.
The Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum a 
Linux Foundation Collaborative Project

^ permalink raw reply	[flat|nested] 7+ messages in thread

end of thread, other threads:[~2019-05-13 14:38 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2018-08-13 12:32 [PATCH 0/3] Add support for new channels on 60GHz band Alexei Avshalom Lazar
2018-08-13 12:33 ` [PATCH 1/3] cfg80211: Add support for 60GHz band channels 5 and 6 Alexei Avshalom Lazar
2018-08-28  9:25   ` Johannes Berg
2018-08-13 12:33 ` [PATCH 2/3] nl80211: Add support for EDMG channels Alexei Avshalom Lazar
2018-08-28  9:33   ` Johannes Berg
2019-05-13 14:38     ` Alexei Avshalom Lazar
2018-08-13 12:33 ` [PATCH 3/3] wil6210: Add EDMG channel support Alexei Avshalom Lazar

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.