From mboxrd@z Thu Jan 1 00:00:00 1970 From: Kalle Valo Date: Mon, 20 May 2013 16:37:12 +0300 Subject: [ath9k-devel] [PATCH 6/6] ath10k: preliminary VHT support In-Reply-To: <20130520133551.6961.55701.stgit@localhost6.localdomain6> References: <20130520133551.6961.55701.stgit@localhost6.localdomain6> Message-ID: <20130520133712.6961.76158.stgit@localhost6.localdomain6> List-Id: MIME-Version: 1.0 Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit To: ath9k-devel@lists.ath9k.org Adds preliminary VHT (802.11ac) support to ath10k. Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath10k/mac.c | 66 +++++++++++++++++++++++++++++++++ drivers/net/wireless/ath/ath10k/wmi.c | 13 ++++++- drivers/net/wireless/ath/ath10k/wmi.h | 10 +++++ 3 files changed, 88 insertions(+), 1 deletion(-) diff --git a/drivers/net/wireless/ath/ath10k/mac.c b/drivers/net/wireless/ath/ath10k/mac.c index 3d4e574..ad5a015 100644 --- a/drivers/net/wireless/ath/ath10k/mac.c +++ b/drivers/net/wireless/ath/ath10k/mac.c @@ -256,6 +256,8 @@ chan_to_phymode(const struct cfg80211_chan_def *chandef) phymode = MODE_11NA_HT40; break; case NL80211_CHAN_WIDTH_80: + phymode = MODE_11AC_VHT80; + break; case NL80211_CHAN_WIDTH_80P80: case NL80211_CHAN_WIDTH_160: phymode = MODE_UNKNOWN; @@ -958,6 +960,34 @@ static void ath10k_peer_assoc_h_qos_sta(struct ath10k *ar, arg->peer_flags |= WMI_PEER_QOS; } +static void ath10k_peer_assoc_h_vht(struct ath10k *ar, + struct ieee80211_sta *sta, + struct wmi_peer_assoc_complete_arg *arg) +{ + const struct ieee80211_sta_vht_cap *vht_cap = &sta->vht_cap; + + if (!vht_cap->vht_supported) + return; + + arg->peer_flags |= WMI_PEER_VHT; + + arg->peer_vht_caps = vht_cap->cap; + + if (sta->bandwidth == IEEE80211_STA_RX_BW_80) + arg->peer_flags |= WMI_PEER_80MHZ; + + arg->peer_vht_rates.rx_max_rate = + __le16_to_cpu(vht_cap->vht_mcs.rx_highest); + arg->peer_vht_rates.rx_mcs_set = + __le16_to_cpu(vht_cap->vht_mcs.rx_mcs_map); + arg->peer_vht_rates.tx_max_rate = + __le16_to_cpu(vht_cap->vht_mcs.tx_highest); + arg->peer_vht_rates.tx_mcs_set = + __le16_to_cpu(vht_cap->vht_mcs.tx_mcs_map); + + ath10k_dbg(ATH10K_DBG_MAC, "mac vht peer\n"); +} + static void ath10k_peer_assoc_h_qos(struct ath10k *ar, struct ath10k_vif *arvif, struct ieee80211_sta *sta, @@ -983,6 +1013,8 @@ static void ath10k_peer_assoc_h_phymode(struct ath10k *ar, { enum wmi_phy_mode phymode = MODE_UNKNOWN; + /* FIXME: add VHT */ + switch (ar->hw->conf.chandef.chan->band) { case IEEE80211_BAND_2GHZ: if (sta->ht_cap.ht_supported) { @@ -1027,6 +1059,7 @@ static int ath10k_peer_assoc(struct ath10k *ar, ath10k_peer_assoc_h_crypto(ar, arvif, &arg); ath10k_peer_assoc_h_rates(ar, sta, &arg); ath10k_peer_assoc_h_ht(ar, sta, &arg); + ath10k_peer_assoc_h_vht(ar, sta, &arg); ath10k_peer_assoc_h_qos(ar, arvif, sta, bss_conf, &arg); ath10k_peer_assoc_h_phymode(ar, arvif, sta, &arg); @@ -1194,6 +1227,9 @@ static int ath10k_update_channel_list(struct ath10k *ar) ch->allow_ht = true; + /* FIXME: when should we really allow VHT? */ + ch->allow_vht = true; + ch->allow_ibss = !(channel->flags & IEEE80211_CHAN_NO_IBSS); @@ -2741,6 +2777,30 @@ static const struct ieee80211_iface_combination ath10k_if_comb = { .beacon_int_infra_match = true, }; +static struct ieee80211_sta_vht_cap ath10k_create_vht_cap(struct ath10k *ar) +{ + struct ieee80211_sta_vht_cap vht_cap = {0}; + u16 mcs_map; + + vht_cap.vht_supported = 1; + vht_cap.cap = ar->vht_cap_info; + + /* FIXME: check dynamically how many streams board supports */ + mcs_map = IEEE80211_VHT_MCS_SUPPORT_0_9 << 0 | + IEEE80211_VHT_MCS_SUPPORT_0_9 << 2 | + IEEE80211_VHT_MCS_SUPPORT_0_9 << 4 | + IEEE80211_VHT_MCS_NOT_SUPPORTED << 6 | + IEEE80211_VHT_MCS_NOT_SUPPORTED << 8 | + IEEE80211_VHT_MCS_NOT_SUPPORTED << 10 | + IEEE80211_VHT_MCS_NOT_SUPPORTED << 12 | + IEEE80211_VHT_MCS_NOT_SUPPORTED << 14; + + vht_cap.vht_mcs.rx_mcs_map = cpu_to_le16(mcs_map); + vht_cap.vht_mcs.tx_mcs_map = cpu_to_le16(mcs_map); + + return vht_cap; +} + static struct ieee80211_sta_ht_cap ath10k_get_ht_cap(struct ath10k *ar) { int i; @@ -2839,6 +2899,7 @@ struct ath10k_vif *ath10k_get_arvif(struct ath10k *ar, u32 vdev_id) int ath10k_mac_register(struct ath10k *ar) { struct ieee80211_supported_band *band; + struct ieee80211_sta_vht_cap vht_cap; struct ieee80211_sta_ht_cap ht_cap; void *channels; int ret; @@ -2848,6 +2909,7 @@ int ath10k_mac_register(struct ath10k *ar) SET_IEEE80211_DEV(ar->hw, ar->dev); ht_cap = ath10k_get_ht_cap(ar); + vht_cap = ath10k_create_vht_cap(ar); if (ar->phy_capability & WHAL_WLAN_11G_CAPABILITY) { channels = kmemdup(ath10k_2ghz_channels, @@ -2862,6 +2924,9 @@ int ath10k_mac_register(struct ath10k *ar) band->n_bitrates = ath10k_g_rates_size; band->bitrates = ath10k_g_rates; band->ht_cap = ht_cap; + + /* vht is not supported in 2.4 GHz */ + ar->hw->wiphy->bands[IEEE80211_BAND_2GHZ] = band; } @@ -2883,6 +2948,7 @@ int ath10k_mac_register(struct ath10k *ar) band->n_bitrates = ath10k_a_rates_size; band->bitrates = ath10k_a_rates; band->ht_cap = ht_cap; + band->vht_cap = vht_cap; ar->hw->wiphy->bands[IEEE80211_BAND_5GHZ] = band; } diff --git a/drivers/net/wireless/ath/ath10k/wmi.c b/drivers/net/wireless/ath/ath10k/wmi.c index 31ddd1a..adb17fb 100644 --- a/drivers/net/wireless/ath/ath10k/wmi.c +++ b/drivers/net/wireless/ath/ath10k/wmi.c @@ -1942,6 +1942,8 @@ int ath10k_wmi_scan_chan_list(struct ath10k *ar, flags |= WMI_CHAN_FLAG_ADHOC_ALLOWED; if (ch->allow_ht) flags |= WMI_CHAN_FLAG_ALLOW_HT; + if (ch->allow_vht) + flags |= WMI_CHAN_FLAG_ALLOW_VHT; if (ch->ht40plus) flags |= WMI_CHAN_FLAG_HT40_PLUS; @@ -1991,8 +1993,8 @@ int ath10k_wmi_peer_assoc(struct ath10k *ar, cmd->peer_mpdu_density = __cpu_to_le32(arg->peer_mpdu_density); cmd->peer_rate_caps = __cpu_to_le32(arg->peer_rate_caps); cmd->peer_nss = __cpu_to_le32(arg->peer_num_spatial_streams); + cmd->peer_vht_caps = __cpu_to_le32(arg->peer_vht_caps); cmd->peer_phymode = __cpu_to_le32(arg->peer_phymode); - /* FIXME: we dont touch VHT options */ memcpy(cmd->peer_macaddr.addr, arg->addr, ETH_ALEN); @@ -2006,6 +2008,15 @@ int ath10k_wmi_peer_assoc(struct ath10k *ar, memcpy(cmd->peer_ht_rates.rates, arg->peer_ht_rates.rates, arg->peer_ht_rates.num_rates); + cmd->peer_vht_rates.rx_max_rate = + __cpu_to_le32(arg->peer_vht_rates.rx_max_rate); + cmd->peer_vht_rates.rx_mcs_set = + __cpu_to_le32(arg->peer_vht_rates.rx_mcs_set); + cmd->peer_vht_rates.tx_max_rate = + __cpu_to_le32(arg->peer_vht_rates.tx_max_rate); + cmd->peer_vht_rates.tx_mcs_set = + __cpu_to_le32(arg->peer_vht_rates.tx_mcs_set); + return ath10k_wmi_cmd_send(ar, skb, WMI_PEER_ASSOC_CMDID); } diff --git a/drivers/net/wireless/ath/ath10k/wmi.h b/drivers/net/wireless/ath/ath10k/wmi.h index ccab87e..601a432 100644 --- a/drivers/net/wireless/ath/ath10k/wmi.h +++ b/drivers/net/wireless/ath/ath10k/wmi.h @@ -540,6 +540,7 @@ struct wmi_channel_arg { bool passive; bool allow_ibss; bool allow_ht; + bool allow_vht; bool ht40plus; /* note: power unit is 1/4th of dBm */ u32 min_power; @@ -2785,6 +2786,13 @@ struct wmi_vht_rate_set { __le32 tx_mcs_set; /* Negotiated TX VHT rates */ } __packed; +struct wmi_vht_rate_set_arg { + u32 rx_max_rate; + u32 rx_mcs_set; + u32 tx_max_rate; + u32 tx_mcs_set; +}; + struct wmi_peer_set_rates_cmd { /* peer MAC address */ struct wmi_mac_addr peer_macaddr; @@ -2878,7 +2886,9 @@ struct wmi_peer_assoc_complete_arg { struct wmi_rate_set_arg peer_legacy_rates; struct wmi_rate_set_arg peer_ht_rates; u32 peer_num_spatial_streams; + u32 peer_vht_caps; enum wmi_phy_mode peer_phymode; + struct wmi_vht_rate_set_arg peer_vht_rates; }; struct wmi_peer_add_wds_entry_cmd {