From patchwork Mon Aug 13 12:33:00 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Alexei Avshalom Lazar X-Patchwork-Id: 10564113 X-Patchwork-Delegate: johannes@sipsolutions.net Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id D9212157B for ; Mon, 13 Aug 2018 12:41:14 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id CA6B4291B5 for ; Mon, 13 Aug 2018 12:41:14 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id BCC69291BA; Mon, 13 Aug 2018 12:41:14 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-7.9 required=2.0 tests=BAYES_00,MAILING_LIST_MULTI, RCVD_IN_DNSWL_HI autolearn=ham version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 5216B291B5 for ; Mon, 13 Aug 2018 12:41:14 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1729657AbeHMPXU (ORCPT ); Mon, 13 Aug 2018 11:23:20 -0400 Received: from alexa-out-ams-01.qualcomm.com ([185.23.61.162]:13468 "EHLO alexa-out-ams-01.qualcomm.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1728509AbeHMPXU (ORCPT ); Mon, 13 Aug 2018 11:23:20 -0400 X-IronPort-AV: E=Sophos;i="5.53,233,1531778400"; d="scan'208";a="958257" Received: from ironmsg01-ams.qualcomm.com ([10.251.56.2]) by alexa-out-ams-01.qualcomm.com with ESMTP; 13 Aug 2018 14:39:08 +0200 X-IronPort-AV: E=McAfee;i="5900,7806,8983"; a="4541028" Received: from unknown (HELO wigig-1329.mea.qualcomm.com) ([10.4.89.235]) by ironmsg01-ams.qualcomm.com with ESMTP; 13 Aug 2018 14:39:07 +0200 From: Alexei Avshalom Lazar To: Johannes Berg Cc: Alexei Avshalom Lazar , linux-wireless@vger.kernel.org, wil6210@qti.qualcomm.com Subject: [PATCH 1/3] cfg80211: Add support for 60GHz band channels 5 and 6 Date: Mon, 13 Aug 2018 15:33:00 +0300 Message-Id: <1534163582-9983-2-git-send-email-ailizaro@codeaurora.org> X-Mailer: git-send-email 1.9.1 In-Reply-To: <1534163582-9983-1-git-send-email-ailizaro@codeaurora.org> References: <1534163582-9983-1-git-send-email-ailizaro@codeaurora.org> Sender: linux-wireless-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-wireless@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP 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 --- 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; From patchwork Mon Aug 13 12:33:01 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Alexei Avshalom Lazar X-Patchwork-Id: 10564115 X-Patchwork-Delegate: johannes@sipsolutions.net Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 32D87157B for ; Mon, 13 Aug 2018 12:41:18 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 23EAB291B5 for ; Mon, 13 Aug 2018 12:41:18 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 17C8E291BA; Mon, 13 Aug 2018 12:41:18 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-7.9 required=2.0 tests=BAYES_00,MAILING_LIST_MULTI, RCVD_IN_DNSWL_HI autolearn=ham version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 0B515291B5 for ; Mon, 13 Aug 2018 12:41:17 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1729687AbeHMPXW (ORCPT ); Mon, 13 Aug 2018 11:23:22 -0400 Received: from alexa-out-ams-01.qualcomm.com ([185.23.61.162]:13468 "EHLO alexa-out-ams-01.qualcomm.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1728509AbeHMPXW (ORCPT ); Mon, 13 Aug 2018 11:23:22 -0400 X-IronPort-AV: E=Sophos;i="5.53,233,1531778400"; d="scan'208";a="958260" Received: from ironmsg01-ams.qualcomm.com ([10.251.56.2]) by alexa-out-ams-01.qualcomm.com with ESMTP; 13 Aug 2018 14:39:10 +0200 X-IronPort-AV: E=McAfee;i="5900,7806,8983"; a="4541029" Received: from unknown (HELO wigig-1329.mea.qualcomm.com) ([10.4.89.235]) by ironmsg01-ams.qualcomm.com with ESMTP; 13 Aug 2018 14:39:09 +0200 From: Alexei Avshalom Lazar To: Johannes Berg Cc: Alexei Avshalom Lazar , linux-wireless@vger.kernel.org, wil6210@qti.qualcomm.com Subject: [PATCH 2/3] nl80211: Add support for EDMG channels Date: Mon, 13 Aug 2018 15:33:01 +0300 Message-Id: <1534163582-9983-3-git-send-email-ailizaro@codeaurora.org> X-Mailer: git-send-email 1.9.1 In-Reply-To: <1534163582-9983-1-git-send-email-ailizaro@codeaurora.org> References: <1534163582-9983-1-git-send-email-ailizaro@codeaurora.org> Sender: linux-wireless-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-wireless@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP 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 --- 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) From patchwork Mon Aug 13 12:33:02 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Alexei Avshalom Lazar X-Patchwork-Id: 10564117 X-Patchwork-Delegate: johannes@sipsolutions.net Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id C4CBC14E2 for ; Mon, 13 Aug 2018 12:41:22 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id B4C55291B5 for ; Mon, 13 Aug 2018 12:41:22 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id A8A8A291BA; Mon, 13 Aug 2018 12:41:22 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-7.9 required=2.0 tests=BAYES_00,MAILING_LIST_MULTI, RCVD_IN_DNSWL_HI autolearn=ham version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 99544291B5 for ; Mon, 13 Aug 2018 12:41:21 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1729741AbeHMPX1 (ORCPT ); Mon, 13 Aug 2018 11:23:27 -0400 Received: from alexa-out-ams-01.qualcomm.com ([185.23.61.162]:13468 "EHLO alexa-out-ams-01.qualcomm.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1728509AbeHMPX1 (ORCPT ); Mon, 13 Aug 2018 11:23:27 -0400 X-IronPort-AV: E=Sophos;i="5.53,233,1531778400"; d="scan'208";a="958261" Received: from ironmsg01-ams.qualcomm.com ([10.251.56.2]) by alexa-out-ams-01.qualcomm.com with ESMTP; 13 Aug 2018 14:39:12 +0200 X-IronPort-AV: E=McAfee;i="5900,7806,8983"; a="4541030" Received: from unknown (HELO wigig-1329.mea.qualcomm.com) ([10.4.89.235]) by ironmsg01-ams.qualcomm.com with ESMTP; 13 Aug 2018 14:39:11 +0200 From: Alexei Avshalom Lazar To: Johannes Berg Cc: Alexei Avshalom Lazar , linux-wireless@vger.kernel.org, wil6210@qti.qualcomm.com Subject: [PATCH 3/3] wil6210: Add EDMG channel support Date: Mon, 13 Aug 2018 15:33:02 +0300 Message-Id: <1534163582-9983-4-git-send-email-ailizaro@codeaurora.org> X-Mailer: git-send-email 1.9.1 In-Reply-To: <1534163582-9983-1-git-send-email-ailizaro@codeaurora.org> References: <1534163582-9983-1-git-send-email-ailizaro@codeaurora.org> Sender: linux-wireless-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-wireless@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP 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 --- 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;