From patchwork Thu May 9 20:15:50 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: John Crispin X-Patchwork-Id: 10937623 X-Patchwork-Delegate: kvalo@adurom.com 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 7900F924 for ; Thu, 9 May 2019 20:16:09 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 69F4D289BC for ; Thu, 9 May 2019 20:16:09 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 5E5FA28A4B; Thu, 9 May 2019 20:16:09 +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=-5.2 required=2.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,MAILING_LIST_MULTI,RCVD_IN_DNSWL_MED autolearn=ham version=3.3.1 Received: from bombadil.infradead.org (bombadil.infradead.org [198.137.202.133]) (using TLSv1.2 with cipher AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.wl.linuxfoundation.org (Postfix) with ESMTPS id B3885289BC for ; Thu, 9 May 2019 20:16:08 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20170209; h=Sender: Content-Transfer-Encoding:Content-Type:MIME-Version:Cc:List-Subscribe: List-Help:List-Post:List-Archive:List-Unsubscribe:List-Id:References: In-Reply-To:Message-Id:Date:Subject:To:From:Reply-To:Content-ID: Content-Description:Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc :Resent-Message-ID:List-Owner; bh=yLq/7dgCBTuBDNPQVIIAHCwi5Qt5qBOLOCgKhvIP4ts=; b=VbKILVeO0bsacxT6s+6s/nEIZO WyHzfbbS444aEf8JTLwH22+2pGI9ZanCP4uGuimaqJZWHuIZ/NXewAsEzXFvgoykL3tt/qbYVDGdf 4HP63c+PJLBvgxSSWpOhdMALR/yjWWIapuHd2uOL0HlwLJs+I2bkDI0D9GO2ag+xCXNiA3yP1/u5i 74Kj14DUT8Fy/y0F6ojs9cBkRm5cXutDNFZdNNNDMHlB3BrbBr48chCTYe5vzKJxpkPvViVB0qzie t+wpzcraHU/BuvYIw1RUrYKcMhOAqsuQtroXgLKv4QaW2mBx5n4eJhgQgoEr9dMHgvJX5ZFfQz2J/ GoTrUP+w==; Received: from localhost ([127.0.0.1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.90_1 #2 (Red Hat Linux)) id 1hOpSZ-0003Y9-TL; Thu, 09 May 2019 20:16:07 +0000 Received: from nbd.name ([2a01:4f8:221:3d45::2]) by bombadil.infradead.org with esmtps (Exim 4.90_1 #2 (Red Hat Linux)) id 1hOpSV-0003Uk-G7 for ath11k@lists.infradead.org; Thu, 09 May 2019 20:16:05 +0000 Received: from p548c83e0.dip0.t-ipconnect.de ([84.140.131.224] helo=bertha.fritz.box) by ds12 with esmtpsa (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.89) (envelope-from ) id 1hOpST-0006sS-HK; Thu, 09 May 2019 22:16:01 +0200 From: John Crispin To: Kalle Valo Subject: [PATCH V4 5/5] ath11k: add HE support Date: Thu, 9 May 2019 22:15:50 +0200 Message-Id: <20190509201550.3977-6-john@phrozen.org> X-Mailer: git-send-email 2.11.0 In-Reply-To: <20190509201550.3977-1-john@phrozen.org> References: <20190509201550.3977-1-john@phrozen.org> X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20190509_131603_699314_A77D6A3C X-CRM114-Status: GOOD ( 19.66 ) X-BeenThere: ath11k@lists.infradead.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Shashidhar Lakkavalli , ath11k@lists.infradead.org, John Crispin MIME-Version: 1.0 Sender: "ath11k" Errors-To: ath11k-bounces+patchwork-ath11k=patchwork.kernel.org@lists.infradead.org X-Virus-Scanned: ClamAV using ClamSMTP Add basic HE support to the driver. The sband_iftype data is generated from the capabilities read from the FW. Things that still need to implemented * ppe_threshold support Signed-off-by: Shashidhar Lakkavalli Signed-off-by: John Crispin --- drivers/net/wireless/ath/ath11k/core.h | 2 + drivers/net/wireless/ath/ath11k/mac.c | 173 +++++++++++++++++++++++++++++++-- drivers/net/wireless/ath/ath11k/wmi.h | 5 +- 3 files changed, 171 insertions(+), 9 deletions(-) diff --git a/drivers/net/wireless/ath/ath11k/core.h b/drivers/net/wireless/ath/ath11k/core.h index 50032e701255..fcb6b1abed09 100644 --- a/drivers/net/wireless/ath/ath11k/core.h +++ b/drivers/net/wireless/ath/ath11k/core.h @@ -439,6 +439,8 @@ struct ath11k { struct { struct ieee80211_supported_band sbands[NUM_NL80211_BANDS]; + struct ieee80211_sband_iftype_data + iftype[NUM_NL80211_BANDS][NUM_NL80211_IFTYPES]; } mac; unsigned int filter_flags; unsigned long monitor_flags; diff --git a/drivers/net/wireless/ath/ath11k/mac.c b/drivers/net/wireless/ath/ath11k/mac.c index cd7fb9a13639..51003ef3cc37 100644 --- a/drivers/net/wireless/ath/ath11k/mac.c +++ b/drivers/net/wireless/ath/ath11k/mac.c @@ -1280,7 +1280,44 @@ static void ath11k_peer_assoc_h_he(struct ath11k *ar, struct ieee80211_sta *sta, struct peer_assoc_params *arg) { - /* TODO: Implementation */ + const struct ieee80211_sta_he_cap *he_cap = &sta->he_cap; + + if (!he_cap->has_he) + return; + + arg->he_flag = true; + + memcpy(&arg->peer_he_cap_macinfo, he_cap->he_cap_elem.mac_cap_info, + sizeof(arg->peer_he_cap_macinfo)); + memcpy(&arg->peer_he_cap_phyinfo, he_cap->he_cap_elem.phy_cap_info, + sizeof(arg->peer_he_cap_phyinfo)); + + if (he_cap->he_cap_elem.mac_cap_info[0] & IEEE80211_HE_MAC_CAP0_TWT_RES) + arg->twt_responder = true; + if (he_cap->he_cap_elem.mac_cap_info[0] & IEEE80211_HE_MAC_CAP0_TWT_REQ) + arg->twt_requester = true; + + /* TODO - peer_ppet and peer_he_ops need to be set */ + + switch (sta->bandwidth) { + /* TODO - add 80p80 support */ + + case IEEE80211_STA_RX_BW_160: + arg->peer_he_rx_mcs_set[WMI_HECAP_TXRX_MCS_NSS_IDX_160] = + he_cap->he_mcs_nss_supp.rx_mcs_160; + arg->peer_he_tx_mcs_set[WMI_HECAP_TXRX_MCS_NSS_IDX_160] = + he_cap->he_mcs_nss_supp.tx_mcs_160; + arg->peer_he_mcs_count++; + /* drop through */ + + default: + arg->peer_he_rx_mcs_set[WMI_HECAP_TXRX_MCS_NSS_IDX_80] = + he_cap->he_mcs_nss_supp.rx_mcs_80; + arg->peer_he_tx_mcs_set[WMI_HECAP_TXRX_MCS_NSS_IDX_80] = + he_cap->he_mcs_nss_supp.tx_mcs_80; + arg->peer_he_mcs_count++; + break; + } } static void ath11k_peer_assoc_h_smps(struct ieee80211_sta *sta, @@ -1447,6 +1484,32 @@ static enum wmi_phy_mode ath11k_mac_get_phymode_vht(struct ath11k *ar, return MODE_UNKNOWN; } +static enum wmi_phy_mode ath11k_mac_get_phymode_he(struct ath11k *ar, + struct ieee80211_sta *sta) +{ + if (sta->bandwidth == IEEE80211_STA_RX_BW_160) { + if (sta->he_cap.he_cap_elem.phy_cap_info[0] & + IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_160MHZ_IN_5G) + return MODE_11AX_HE160; + else if (sta->he_cap.he_cap_elem.phy_cap_info[0] & + IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_80PLUS80_MHZ_IN_5G) + return MODE_11AX_HE80_80; + /* not sure if this is a valid case? */ + return MODE_11AX_HE160; + } + + if (sta->bandwidth == IEEE80211_STA_RX_BW_80) + return MODE_11AX_HE80; + + if (sta->bandwidth == IEEE80211_STA_RX_BW_40) + return MODE_11AX_HE40; + + if (sta->bandwidth == IEEE80211_STA_RX_BW_20) + return MODE_11AX_HE20; + + return MODE_UNKNOWN; +} + static void ath11k_peer_assoc_h_phymode(struct ath11k *ar, struct ieee80211_vif *vif, struct ieee80211_sta *sta, @@ -1468,7 +1531,14 @@ static void ath11k_peer_assoc_h_phymode(struct ath11k *ar, switch (band) { case NL80211_BAND_2GHZ: - if (sta->vht_cap.vht_supported && + if (sta->he_cap.has_he) { + if (sta->bandwidth == IEEE80211_STA_RX_BW_80) + phymode = MODE_11AX_HE80_2G; + else if (sta->bandwidth == IEEE80211_STA_RX_BW_40) + phymode = MODE_11AX_HE40_2G; + else + phymode = MODE_11AX_HE20_2G; + } else if (sta->vht_cap.vht_supported && !ath11k_peer_assoc_h_vht_masked(vht_mcs_mask)) { if (sta->bandwidth == IEEE80211_STA_RX_BW_40) phymode = MODE_11AC_VHT40; @@ -1485,12 +1555,12 @@ static void ath11k_peer_assoc_h_phymode(struct ath11k *ar, } else { phymode = MODE_11B; } - /* TODO: HE */ - break; case NL80211_BAND_5GHZ: - /* Check VHT first */ - if (sta->vht_cap.vht_supported && + /* Check HE first */ + if (sta->he_cap.has_he) { + phymode = ath11k_mac_get_phymode_he(ar, sta); + } else if (sta->vht_cap.vht_supported && !ath11k_peer_assoc_h_vht_masked(vht_mcs_mask)) { phymode = ath11k_mac_get_phymode_vht(ar, sta); } else if (sta->ht_cap.ht_supported && @@ -1502,7 +1572,6 @@ static void ath11k_peer_assoc_h_phymode(struct ath11k *ar, } else { phymode = MODE_11A; } - /* TODO: HE Phymode */ break; default: break; @@ -3076,6 +3145,92 @@ static int ath11k_check_chain_mask(struct ath11k *ar, u32 ant, bool is_tx_ant) return 0; } +static int ath11k_mac_copy_he_cap(struct ath11k_pdev_cap *cap, + struct ieee80211_sband_iftype_data *data, + int band) +{ + int i, idx = 0; + + for (i = 0; i < NUM_NL80211_IFTYPES; i++) { + struct ieee80211_sta_he_cap *he_cap = &data[idx].he_cap; + struct ath11k_band_cap *band_cap = &cap->band[band]; + struct ieee80211_he_cap_elem *he_cap_elem = + &he_cap->he_cap_elem; + + switch (i) { + case NL80211_IFTYPE_STATION: + case NL80211_IFTYPE_AP: + break; + + default: + continue; + } + + data[idx].types_mask = BIT(i); + he_cap->has_he = true; + memcpy(he_cap_elem->mac_cap_info, band_cap->he_cap_info, + sizeof(he_cap_elem->mac_cap_info)); + memcpy(he_cap_elem->phy_cap_info, band_cap->he_cap_phy_info, + sizeof(he_cap_elem->phy_cap_info)); + + switch (i) { + case NL80211_IFTYPE_STATION: + he_cap_elem->mac_cap_info[0] &= + ~IEEE80211_HE_MAC_CAP0_TWT_RES; + he_cap_elem->mac_cap_info[0] |= + IEEE80211_HE_MAC_CAP0_TWT_REQ; + break; + } + + he_cap->he_mcs_nss_supp.rx_mcs_80 = + cpu_to_le16(band_cap->he_mcs & 0xffff); + he_cap->he_mcs_nss_supp.tx_mcs_80 = + cpu_to_le16(band_cap->he_mcs & 0xffff); + he_cap->he_mcs_nss_supp.rx_mcs_160 = + cpu_to_le16((band_cap->he_mcs >> 16) & 0xffff); + he_cap->he_mcs_nss_supp.tx_mcs_160 = + cpu_to_le16((band_cap->he_mcs >> 16) & 0xffff); + he_cap->he_mcs_nss_supp.rx_mcs_80p80 = + cpu_to_le16((band_cap->he_mcs >> 16) & 0xffff); + he_cap->he_mcs_nss_supp.tx_mcs_80p80 = + cpu_to_le16((band_cap->he_mcs >> 16) & 0xffff); + + /* TODO - disable ppe threshold until we can generate the + * field from the fw capabilities + */ + he_cap_elem->phy_cap_info[6] &= + ~IEEE80211_HE_PHY_CAP6_PPE_THRESHOLD_PRESENT; + idx++; + } + + return idx; +} + +static void ath11k_mac_setup_he_cap(struct ath11k *ar, + struct ath11k_pdev_cap *cap) +{ + struct ieee80211_supported_band *band; + int count = 0; + + if (cap->supported_bands & WMI_HOST_WLAN_2G_CAP) { + count = ath11k_mac_copy_he_cap(cap, + ar->mac.iftype[NL80211_BAND_2GHZ], + NL80211_BAND_2GHZ); + band = &ar->mac.sbands[NL80211_BAND_2GHZ]; + band->iftype_data = ar->mac.iftype[NL80211_BAND_2GHZ]; + } + + if (cap->supported_bands & WMI_HOST_WLAN_5G_CAP) { + count = ath11k_mac_copy_he_cap(cap, + ar->mac.iftype[NL80211_BAND_5GHZ], + NL80211_BAND_5GHZ); + band = &ar->mac.sbands[NL80211_BAND_5GHZ]; + band->iftype_data = ar->mac.iftype[NL80211_BAND_5GHZ]; + } + + band->n_iftype_data = count; +} + static int __ath11k_set_antenna(struct ath11k *ar, u32 tx_ant, u32 rx_ant) { int ret; @@ -3111,8 +3266,9 @@ static int __ath11k_set_antenna(struct ath11k *ar, u32 tx_ant, u32 rx_ant) return ret; } - /* Reload HT/VHT capability */ + /* Reload HT/VHT/HE capability */ ath11k_mac_setup_ht_vht_cap(ar, &ar->pdev->cap, NULL); + ath11k_mac_setup_he_cap(ar, &ar->pdev->cap); return 0; } @@ -4926,6 +5082,7 @@ static int ath11k_mac_register(struct ath11k *ar) goto err_free; ath11k_mac_setup_ht_vht_cap(ar, cap, &ht_cap); + ath11k_mac_setup_he_cap(ar, cap); ar->hw->wiphy->available_antennas_rx = cap->rx_chain_mask; ar->hw->wiphy->available_antennas_tx = cap->tx_chain_mask; diff --git a/drivers/net/wireless/ath/ath11k/wmi.h b/drivers/net/wireless/ath/ath11k/wmi.h index 5d20f57fbacc..7674fa85301a 100644 --- a/drivers/net/wireless/ath/ath11k/wmi.h +++ b/drivers/net/wireless/ath/ath11k/wmi.h @@ -3842,7 +3842,10 @@ struct wmi_vdev_install_key_arg { #define WMI_MAX_SUPPORTED_RATES 128 #define WMI_HOST_MAX_HECAP_PHY_SIZE 3 -#define WMI_HOST_MAX_HE_RATE_SET 1 +#define WMI_HOST_MAX_HE_RATE_SET 3 +#define WMI_HECAP_TXRX_MCS_NSS_IDX_80 0 +#define WMI_HECAP_TXRX_MCS_NSS_IDX_160 1 +#define WMI_HECAP_TXRX_MCS_NSS_IDX_80_80 2 struct wmi_rate_set_arg { u32 num_rates;