Adds preliminary VHT (802.11ac) support to ath10k.

Signed-off-by: Kalle Valo <kv...@qca.qualcomm.com>
---
 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 {

_______________________________________________
ath9k-devel mailing list
ath9k-devel@lists.ath9k.org
https://lists.ath9k.org/mailman/listinfo/ath9k-devel

Reply via email to