And advertise EHT capabilities to user space when supported.
Unified · Split
| @@ -360,6 +360,48 @@ struct ieee80211_sta_he_cap { · 359 unmodified lines | ||
| 360 | 360 | u8 ppe_thres[IEEE80211_HE_PPE_THRES_MAX_LEN]; |
| 361 | 361 | }; |
| 362 | 362 | |
| 363 | +/** | |
| 364 | + * struct ieee80211_eht_mcs_nss_supp - EHT max supported NSS per MCS | |
| 365 | + * | |
| 366 | + * See P802.11be_D1.3 Table 9-401k - "Subfields of the Supported EHT-MCS | |
| 367 | + * and NSS Set field" | |
| 368 | + * | |
| 369 | + * @only_20mhz: MCS/NSS support for 20 MHz-only STA. | |
| 370 | + * @bw._80: MCS/NSS support for BW <= 80 MHz | |
| 371 | + * @bw._160: MCS/NSS support for BW = 160 MHz | |
| 372 | + * @bw._320: MCS/NSS support for BW = 320 MHz | |
| 373 | + */ | |
| 374 | +struct ieee80211_eht_mcs_nss_supp { | |
| 375 | + union { | |
| 376 | + struct ieee80211_eht_mcs_nss_supp_20mhz_only only_20mhz; | |
| 377 | + struct { | |
| 378 | + struct ieee80211_eht_mcs_nss_supp_bw _80; | |
| 379 | + struct ieee80211_eht_mcs_nss_supp_bw _160; | |
| 380 | + struct ieee80211_eht_mcs_nss_supp_bw _320; | |
| 381 | + } __packed bw; | |
| 382 | + } __packed; | |
| 383 | +} __packed; | |
| 384 | + | |
| 385 | +#define IEEE80211_EHT_PPE_THRES_MAX_LEN 32 | |
| 386 | + | |
| 387 | +/** | |
| 388 | + * struct ieee80211_sta_eht_cap - STA's EHT capabilities | |
| 389 | + * | |
| 390 | + * This structure describes most essential parameters needed | |
| 391 | + * to describe 802.11be EHT capabilities for a STA. | |
| 392 | + * | |
| 393 | + * @has_eht: true iff EHT data is valid. | |
| 394 | + * @eht_cap_elem: Fixed portion of the eht capabilities element. | |
| 395 | + * @eht_mcs_nss_supp: The supported NSS/MCS combinations. | |
| 396 | + * @eht_ppe_thres: Holds the PPE Thresholds data. | |
| 397 | + */ | |
| 398 | +struct ieee80211_sta_eht_cap { | |
| 399 | + bool has_eht; | |
| 400 | + struct ieee80211_eht_cap_elem_fixed eht_cap_elem; | |
| 401 | + struct ieee80211_eht_mcs_nss_supp eht_mcs_nss_supp; | |
| 402 | + u8 eht_ppe_thres[IEEE80211_EHT_PPE_THRES_MAX_LEN]; | |
| 403 | +}; | |
| 404 | + | |
| 363 | 405 | /** |
| 364 | 406 | * struct ieee80211_sband_iftype_data - sband data per interface type |
| 365 | 407 | * |
| @@ -379,6 +421,7 @@ struct ieee80211_sband_iftype_data { · 13 unmodified lines | ||
| 379 | 421 | u16 types_mask; |
| 380 | 422 | struct ieee80211_sta_he_cap he_cap; |
| 381 | 423 | struct ieee80211_he_6ghz_capa he_6ghz_capa; |
| 424 | + struct ieee80211_sta_eht_cap eht_cap; | |
| 382 | 425 | struct { |
| 383 | 426 | const u8 *data; |
| 384 | 427 | unsigned int len; |
| @@ -561,6 +604,26 @@ ieee80211_get_he_6ghz_capa(const struct ieee80211_supported_band *sband, · 176 unmodified lines | ||
| 561 | 604 | return data->he_6ghz_capa.capa; |
| 562 | 605 | } |
| 563 | 606 | |
| 607 | +/** | |
| 608 | + * ieee80211_get_eht_iftype_cap - return ETH capabilities for an sband's iftype | |
| 609 | + * @sband: the sband to search for the iftype on | |
| 610 | + * @iftype: enum nl80211_iftype | |
| 611 | + * | |
| 612 | + * Return: pointer to the struct ieee80211_sta_eht_cap, or NULL is none found | |
| 613 | + */ | |
| 614 | +static inline const struct ieee80211_sta_eht_cap * | |
| 615 | +ieee80211_get_eht_iftype_cap(const struct ieee80211_supported_band *sband, | |
| 616 | + enum nl80211_iftype iftype) | |
| 617 | +{ | |
| 618 | + const struct ieee80211_sband_iftype_data *data = | |
| 619 | + ieee80211_get_sband_iftype_data(sband, iftype); | |
| 620 | + | |
| 621 | + if (data && data->eht_cap.has_eht) | |
| 622 | + return &data->eht_cap; | |
| 623 | + | |
| 624 | + return NULL; | |
| 625 | +} | |
| 626 | + | |
| 564 | 627 | /** |
| 565 | 628 | * wiphy_read_of_freq_limits - read frequency limits from device tree |
| 566 | 629 | * |
| @@ -3766,6 +3766,14 @@ enum nl80211_mpath_info { · 3765 unmodified lines | ||
| 3766 | 3766 | * given for all 6 GHz band channels |
| 3767 | 3767 | * @NL80211_BAND_IFTYPE_ATTR_VENDOR_ELEMS: vendor element capabilities that are |
| 3768 | 3768 | * advertised on this band/for this iftype (binary) |
| 3769 | + * @NL80211_BAND_IFTYPE_ATTR_EHT_CAP_MAC: EHT MAC capabilities as in EHT | |
| 3770 | + * capabilities element | |
| 3771 | + * @NL80211_BAND_IFTYPE_ATTR_EHT_CAP_PHY: EHT PHY capabilities as in EHT | |
| 3772 | + * capabilities element | |
| 3773 | + * @NL80211_BAND_IFTYPE_ATTR_EHT_CAP_MCS_SET: EHT supported NSS/MCS as in EHT | |
| 3774 | + * capabilities element | |
| 3775 | + * @NL80211_BAND_IFTYPE_ATTR_EHT_CAP_PPE: EHT PPE thresholds information as | |
| 3776 | + * defined in EHT capabilities element | |
| 3769 | 3777 | * @__NL80211_BAND_IFTYPE_ATTR_AFTER_LAST: internal use |
| 3770 | 3778 | * @NL80211_BAND_IFTYPE_ATTR_MAX: highest band attribute currently defined |
| 3771 | 3779 | */ |
| @@ -3779,6 +3787,10 @@ enum nl80211_band_iftype_attr { · 7 unmodified lines | ||
| 3779 | 3787 | NL80211_BAND_IFTYPE_ATTR_HE_CAP_PPE, |
| 3780 | 3788 | NL80211_BAND_IFTYPE_ATTR_HE_6GHZ_CAPA, |
| 3781 | 3789 | NL80211_BAND_IFTYPE_ATTR_VENDOR_ELEMS, |
| 3790 | + NL80211_BAND_IFTYPE_ATTR_EHT_CAP_MAC, | |
| 3791 | + NL80211_BAND_IFTYPE_ATTR_EHT_CAP_PHY, | |
| 3792 | + NL80211_BAND_IFTYPE_ATTR_EHT_CAP_MCS_SET, | |
| 3793 | + NL80211_BAND_IFTYPE_ATTR_EHT_CAP_PPE, | |
| 3782 | 3794 | |
| 3783 | 3795 | /* keep last */ |
| 3784 | 3796 | __NL80211_BAND_IFTYPE_ATTR_AFTER_LAST, |
| @@ -1737,6 +1737,7 @@ nl80211_send_iftype_data(struct sk_buff *msg, · 1736 unmodified lines | ||
| 1737 | 1737 | const struct ieee80211_sband_iftype_data *iftdata) |
| 1738 | 1738 | { |
| 1739 | 1739 | const struct ieee80211_sta_he_cap *he_cap = &iftdata->he_cap; |
| 1740 | + const struct ieee80211_sta_eht_cap *eht_cap = &iftdata->eht_cap; | |
| 1740 | 1741 | |
| 1741 | 1742 | if (nl80211_put_iftypes(msg, NL80211_BAND_IFTYPE_ATTR_IFTYPES, |
| 1742 | 1743 | iftdata->types_mask)) |
| @@ -1757,6 +1758,32 @@ nl80211_send_iftype_data(struct sk_buff *msg, · 14 unmodified lines | ||
| 1757 | 1758 | return -ENOBUFS; |
| 1758 | 1759 | } |
| 1759 | 1760 | |
| 1761 | + if (eht_cap->has_eht && he_cap->has_he) { | |
| 1762 | + u8 mcs_nss_size, ppe_thresh_size; | |
| 1763 | + u16 ppe_thres_hdr; | |
| 1764 | + | |
| 1765 | + mcs_nss_size = | |
| 1766 | + ieee80211_eht_mcs_nss_size(&he_cap->he_cap_elem, | |
| 1767 | + &eht_cap->eht_cap_elem); | |
| 1768 | + | |
| 1769 | + ppe_thres_hdr = get_unaligned_le16(&eht_cap->eht_ppe_thres[0]); | |
| 1770 | + ppe_thresh_size = | |
| 1771 | + ieee80211_eht_ppe_size(ppe_thres_hdr, | |
| 1772 | + eht_cap->eht_cap_elem.phy_cap_info); | |
| 1773 | + | |
| 1774 | + if (nla_put(msg, NL80211_BAND_IFTYPE_ATTR_EHT_CAP_MAC, | |
| 1775 | + sizeof(eht_cap->eht_cap_elem.mac_cap_info), | |
| 1776 | + eht_cap->eht_cap_elem.mac_cap_info) || | |
| 1777 | + nla_put(msg, NL80211_BAND_IFTYPE_ATTR_EHT_CAP_PHY, | |
| 1778 | + sizeof(eht_cap->eht_cap_elem.phy_cap_info), | |
| 1779 | + eht_cap->eht_cap_elem.phy_cap_info) || | |
| 1780 | + nla_put(msg, NL80211_BAND_IFTYPE_ATTR_EHT_CAP_MCS_SET, | |
| 1781 | + mcs_nss_size, &eht_cap->eht_mcs_nss_supp) || | |
| 1782 | + nla_put(msg, NL80211_BAND_IFTYPE_ATTR_EHT_CAP_PPE, | |
| 1783 | + ppe_thresh_size, eht_cap->eht_ppe_thres)) | |
| 1784 | + return -ENOBUFS; | |
| 1785 | + } | |
| 1786 | + | |
| 1760 | 1787 | if (sband->band == NL80211_BAND_6GHZ && |
| 1761 | 1788 | nla_put(msg, NL80211_BAND_IFTYPE_ATTR_HE_6GHZ_CAPA, |
| 1762 | 1789 | sizeof(iftdata->he_6ghz_capa), |