mac80211: support S1G STA capabilities
authorThomas Pedersen <thomas@adapt-ip.com>
Tue, 22 Sep 2020 02:28:05 +0000 (19:28 -0700)
committerJohannes Berg <johannes.berg@intel.com>
Mon, 28 Sep 2020 11:53:05 +0000 (13:53 +0200)
Include the S1G Capabilities element in an association
request, and support the cfg80211 capability overrides.

Signed-off-by: Thomas Pedersen <thomas@adapt-ip.com>
Link: https://lore.kernel.org/r/20200922022818.15855-5-thomas@adapt-ip.com
[pass skb to ieee80211_add_s1g_capab_ie(), small code style edits]
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
net/mac80211/ieee80211_i.h
net/mac80211/mlme.c
net/mac80211/util.c

index db9af4a..3084417 100644 (file)
@@ -544,6 +544,8 @@ struct ieee80211_if_managed {
        struct ieee80211_ht_cap ht_capa_mask; /* Valid parts of ht_capa */
        struct ieee80211_vht_cap vht_capa; /* configured VHT overrides */
        struct ieee80211_vht_cap vht_capa_mask; /* Valid parts of vht_capa */
+       struct ieee80211_s1g_cap s1g_capa; /* configured S1G overrides */
+       struct ieee80211_s1g_cap s1g_capa_mask; /* valid s1g_capa bits */
 
        /* TDLS support */
        u8 tdls_peer[ETH_ALEN] __aligned(2);
@@ -2203,6 +2205,9 @@ int ieee80211_add_ext_srates_ie(struct ieee80211_sub_if_data *sdata,
                                struct sk_buff *skb, bool need_basic,
                                enum nl80211_band band);
 u8 *ieee80211_add_wmm_info_ie(u8 *buf, u8 qosinfo);
+void ieee80211_add_s1g_capab_ie(struct ieee80211_sub_if_data *sdata,
+                               struct ieee80211_sta_s1g_cap *caps,
+                               struct sk_buff *skb);
 
 /* channel management */
 bool ieee80211_chandef_ht_oper(const struct ieee80211_ht_operation *ht_oper,
index 2489c6c..b69fab1 100644 (file)
@@ -1018,6 +1018,9 @@ static void ieee80211_send_assoc(struct ieee80211_sub_if_data *sdata)
                pos = ieee80211_add_wmm_info_ie(skb_put(skb, 9), qos_info);
        }
 
+       if (sband->band == NL80211_BAND_S1GHZ)
+               ieee80211_add_s1g_capab_ie(sdata, &sband->s1g_cap, skb);
+
        /* add any remaining custom (i.e. vendor specific here) IEs */
        if (assoc_data->ie_len) {
                noffset = assoc_data->ie_len;
@@ -5456,6 +5459,10 @@ int ieee80211_mgd_assoc(struct ieee80211_sub_if_data *sdata,
        memcpy(&ifmgd->vht_capa_mask, &req->vht_capa_mask,
               sizeof(ifmgd->vht_capa_mask));
 
+       memcpy(&ifmgd->s1g_capa, &req->s1g_capa, sizeof(ifmgd->s1g_capa));
+       memcpy(&ifmgd->s1g_capa_mask, &req->s1g_capa_mask,
+              sizeof(ifmgd->s1g_capa_mask));
+
        if (req->ie && req->ie_len) {
                memcpy(assoc_data->ie, req->ie, req->ie_len);
                assoc_data->ie_len = req->ie_len;
index 8d3bfc0..5802275 100644 (file)
@@ -4277,6 +4277,48 @@ int ieee80211_max_num_channels(struct ieee80211_local *local)
        return max_num_different_channels;
 }
 
+void ieee80211_add_s1g_capab_ie(struct ieee80211_sub_if_data *sdata,
+                               struct ieee80211_sta_s1g_cap *caps,
+                               struct sk_buff *skb)
+{
+       struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
+       struct ieee80211_s1g_cap s1g_capab;
+       u8 *pos;
+       int i;
+
+       if (WARN_ON(sdata->vif.type != NL80211_IFTYPE_STATION))
+               return;
+
+       if (!caps->s1g)
+               return;
+
+       memcpy(s1g_capab.capab_info, caps->cap, sizeof(caps->cap));
+       memcpy(s1g_capab.supp_mcs_nss, caps->nss_mcs, sizeof(caps->nss_mcs));
+
+       /* override the capability info */
+       for (i = 0; i < sizeof(ifmgd->s1g_capa.capab_info); i++) {
+               u8 mask = ifmgd->s1g_capa_mask.capab_info[i];
+
+               s1g_capab.capab_info[i] &= ~mask;
+               s1g_capab.capab_info[i] |= ifmgd->s1g_capa.capab_info[i] & mask;
+       }
+
+       /* then MCS and NSS set */
+       for (i = 0; i < sizeof(ifmgd->s1g_capa.supp_mcs_nss); i++) {
+               u8 mask = ifmgd->s1g_capa_mask.supp_mcs_nss[i];
+
+               s1g_capab.supp_mcs_nss[i] &= ~mask;
+               s1g_capab.supp_mcs_nss[i] |=
+                       ifmgd->s1g_capa.supp_mcs_nss[i] & mask;
+       }
+
+       pos = skb_put(skb, 2 + sizeof(s1g_capab));
+       *pos++ = WLAN_EID_S1G_CAPABILITIES;
+       *pos++ = sizeof(s1g_capab);
+
+       memcpy(pos, &s1g_capab, sizeof(s1g_capab));
+}
+
 u8 *ieee80211_add_wmm_info_ie(u8 *buf, u8 qosinfo)
 {
        *buf++ = WLAN_EID_VENDOR_SPECIFIC;