mirror of
https://git.kernel.org/pub/scm/network/wireless/iwd.git
synced 2024-12-22 13:02:44 +01:00
wiphy: parse HE capabilities from band info
The HE capabilities information is contained in NL80211_BAND_ATTR_IFTYPE_DATA where each entry is a set of attributes which define the rules for one or more interface types. This patch specifically parses the HE PHY and HE MCS data which will be used for data rate estimation. Since the set of info is per-iftype(s) the data is stored in a queue where each entry contains the PHY/MCS info, and a uint32 bit mask where each bit index signifies an interface type.
This commit is contained in:
parent
3d48d147ca
commit
9baaaebd38
180
src/wiphy.c
180
src/wiphy.c
@ -936,6 +936,74 @@ static void wiphy_print_mcs_info(const uint8_t *mcs_map,
|
||||
}
|
||||
}
|
||||
|
||||
static void wiphy_print_he_capabilities(struct band *band,
|
||||
const struct band_he_capabilities *he_cap)
|
||||
{
|
||||
int i;
|
||||
char type_buf[128];
|
||||
char *s = type_buf;
|
||||
uint8_t width_set = bit_field(he_cap->he_phy_capa[0], 1, 7);
|
||||
|
||||
for (i = 0; i < 32; i++) {
|
||||
if (!(he_cap->iftypes & (1 << i)))
|
||||
continue;
|
||||
|
||||
if (L_WARN_ON(s >= type_buf + sizeof(type_buf)))
|
||||
return;
|
||||
|
||||
switch (i) {
|
||||
case NETDEV_IFTYPE_ADHOC:
|
||||
s += sprintf(s, "%s ", "Ad-Hoc");
|
||||
break;
|
||||
case NETDEV_IFTYPE_STATION:
|
||||
s += sprintf(s, "%s ", "Station");
|
||||
break;
|
||||
case NETDEV_IFTYPE_AP:
|
||||
s += sprintf(s, "%s ", "AP");
|
||||
break;
|
||||
case NETDEV_IFTYPE_P2P_CLIENT:
|
||||
s += sprintf(s, "%s ", "P2P Client");
|
||||
break;
|
||||
case NETDEV_IFTYPE_P2P_GO:
|
||||
s += sprintf(s, "%s ", "P2P GO");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
l_info("\t\t\tInterface Types: %s", type_buf);
|
||||
|
||||
switch (band->freq) {
|
||||
case BAND_FREQ_2_4_GHZ:
|
||||
wiphy_print_mcs_info(he_cap->he_mcs_set,
|
||||
"HE RX <= 80MHz", 7, 9, 11);
|
||||
wiphy_print_mcs_info(he_cap->he_mcs_set + 2,
|
||||
"HE TX <= 80MHz", 7, 9, 11);
|
||||
break;
|
||||
case BAND_FREQ_5_GHZ:
|
||||
case BAND_FREQ_6_GHZ:
|
||||
wiphy_print_mcs_info(he_cap->he_mcs_set,
|
||||
"HE RX <= 80MHz", 7, 9, 11);
|
||||
wiphy_print_mcs_info(he_cap->he_mcs_set + 2,
|
||||
"HE TX <= 80MHz", 7, 9, 11);
|
||||
|
||||
if (test_bit(&width_set, 2)) {
|
||||
wiphy_print_mcs_info(he_cap->he_mcs_set + 4,
|
||||
"HE RX <= 160MHz", 7, 9, 11);
|
||||
wiphy_print_mcs_info(he_cap->he_mcs_set + 6,
|
||||
"HE TX <= 160MHz", 7, 9, 11);
|
||||
}
|
||||
|
||||
if (test_bit(&width_set, 3)) {
|
||||
wiphy_print_mcs_info(he_cap->he_mcs_set + 8,
|
||||
"HE RX <= 80+80MHz", 7, 9, 11);
|
||||
wiphy_print_mcs_info(he_cap->he_mcs_set + 10,
|
||||
"HE TX <= 80+80MHz", 7, 9, 11);
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void wiphy_print_band_info(struct band *band, const char *name)
|
||||
{
|
||||
int i;
|
||||
@ -995,6 +1063,20 @@ static void wiphy_print_band_info(struct band *band, const char *name)
|
||||
wiphy_print_mcs_info(band->vht_mcs_set, "RX", 7, 8, 9);
|
||||
wiphy_print_mcs_info(band->vht_mcs_set + 4, "TX", 7, 8, 9);
|
||||
}
|
||||
|
||||
if (band->he_capabilities) {
|
||||
const struct l_queue_entry *entry;
|
||||
|
||||
l_info("\t\tHE Capabilities");
|
||||
|
||||
for (entry = l_queue_get_entries(band->he_capabilities);
|
||||
entry; entry = entry->next) {
|
||||
const struct band_he_capabilities *he_cap = entry->data;
|
||||
|
||||
wiphy_print_he_capabilities(band, he_cap);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
static void wiphy_print_basic_info(struct wiphy *wiphy)
|
||||
@ -1208,6 +1290,90 @@ static struct band *band_new_from_message(struct l_genl_attr *band)
|
||||
return ret;
|
||||
}
|
||||
|
||||
static uint32_t get_iftypes(struct l_genl_attr *iftypes)
|
||||
{
|
||||
uint16_t type;
|
||||
uint16_t len;
|
||||
uint32_t types = 0;
|
||||
|
||||
while (l_genl_attr_next(iftypes, &type, &len, NULL)) {
|
||||
if (len != 0)
|
||||
continue;
|
||||
|
||||
types |= (1 << type);
|
||||
}
|
||||
|
||||
return types;
|
||||
}
|
||||
|
||||
static void parse_iftype_attrs(struct band *band, struct l_genl_attr *types)
|
||||
{
|
||||
uint16_t type;
|
||||
uint16_t len;
|
||||
const void *data;
|
||||
unsigned int count = 0;
|
||||
struct band_he_capabilities *he_cap =
|
||||
l_new(struct band_he_capabilities, 1);
|
||||
|
||||
while (l_genl_attr_next(types, &type, &len, &data)) {
|
||||
struct l_genl_attr iftypes;
|
||||
|
||||
switch (type) {
|
||||
case NL80211_BAND_IFTYPE_ATTR_IFTYPES:
|
||||
if (!l_genl_attr_recurse(types, &iftypes))
|
||||
goto parse_error;
|
||||
|
||||
he_cap->iftypes = get_iftypes(&iftypes);
|
||||
break;
|
||||
case NL80211_BAND_IFTYPE_ATTR_HE_CAP_PHY:
|
||||
if (len > sizeof(he_cap->he_phy_capa))
|
||||
continue;
|
||||
|
||||
memcpy(he_cap->he_phy_capa, data, len);
|
||||
count++;
|
||||
break;
|
||||
case NL80211_BAND_IFTYPE_ATTR_HE_CAP_MCS_SET:
|
||||
if (len > sizeof(he_cap->he_mcs_set))
|
||||
continue;
|
||||
|
||||
memcpy(he_cap->he_mcs_set, data, len);
|
||||
count++;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Since the capabilities element indicates what values are present in
|
||||
* the MCS set ensure both values are parsed
|
||||
*/
|
||||
if (count != 2 || !he_cap->iftypes)
|
||||
goto parse_error;
|
||||
|
||||
if (!band->he_capabilities)
|
||||
band->he_capabilities = l_queue_new();
|
||||
|
||||
l_queue_push_head(band->he_capabilities, he_cap);
|
||||
|
||||
return;
|
||||
|
||||
parse_error:
|
||||
l_free(he_cap);
|
||||
}
|
||||
|
||||
static void parse_band_iftype_data(struct band *band, struct l_genl_attr *ifdata)
|
||||
{
|
||||
while (l_genl_attr_next(ifdata, NULL, NULL, NULL)) {
|
||||
struct l_genl_attr types;
|
||||
|
||||
if (!l_genl_attr_recurse(ifdata, &types))
|
||||
continue;
|
||||
|
||||
parse_iftype_attrs(band, &types);
|
||||
}
|
||||
}
|
||||
|
||||
static void parse_supported_bands(struct wiphy *wiphy,
|
||||
struct l_genl_attr *bands)
|
||||
{
|
||||
@ -1256,15 +1422,17 @@ static void parse_supported_bands(struct wiphy *wiphy,
|
||||
} else
|
||||
band = *bandp;
|
||||
|
||||
|
||||
|
||||
while (l_genl_attr_next(&attr, &type, &len, &data)) {
|
||||
struct l_genl_attr freqs;
|
||||
struct l_genl_attr nested;
|
||||
|
||||
switch (type) {
|
||||
case NL80211_BAND_ATTR_FREQS:
|
||||
if (!l_genl_attr_recurse(&attr, &freqs))
|
||||
if (!l_genl_attr_recurse(&attr, &nested))
|
||||
continue;
|
||||
|
||||
parse_supported_frequencies(wiphy, &freqs);
|
||||
parse_supported_frequencies(wiphy, &nested);
|
||||
break;
|
||||
|
||||
case NL80211_BAND_ATTR_RATES:
|
||||
@ -1304,6 +1472,12 @@ static void parse_supported_bands(struct wiphy *wiphy,
|
||||
memcpy(band->ht_capabilities, data, len);
|
||||
band->ht_supported = true;
|
||||
break;
|
||||
case NL80211_BAND_ATTR_IFTYPE_DATA:
|
||||
if (!l_genl_attr_recurse(&attr, &nested))
|
||||
continue;
|
||||
|
||||
parse_band_iftype_data(band, &nested);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user