diff options
author | Janusz Dziedzic <janusz.dziedzic@tieto.com> | 2013-12-05 14:42:58 -0500 |
---|---|---|
committer | Johannes Berg <johannes.berg@intel.com> | 2013-12-16 10:05:17 -0500 |
commit | 204e35a91c4b3327b7239d7687fbd4923edbbf08 (patch) | |
tree | 5cdcf56ed93325e22a9554e3be803278ed0b8c7b /net/wireless | |
parent | 31f1f4ec51bd264ba133ff0211b241546ba95c9d (diff) |
nl80211: add VHT support for set_bitrate_mask
Add VHT MCS/NSS set support for nl80211_set_tx_bitrate_mask().
This should be used mainly for test purpose, to check
different MCS/NSS VHT combinations.
Signed-off-by: Janusz Dziedzic <janusz.dziedzic@tieto.com>
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Diffstat (limited to 'net/wireless')
-rw-r--r-- | net/wireless/nl80211.c | 92 |
1 files changed, 86 insertions, 6 deletions
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c index 2d0c19c6133b..04681a46eda8 100644 --- a/net/wireless/nl80211.c +++ b/net/wireless/nl80211.c | |||
@@ -7328,11 +7328,72 @@ static bool ht_rateset_to_mask(struct ieee80211_supported_band *sband, | |||
7328 | return true; | 7328 | return true; |
7329 | } | 7329 | } |
7330 | 7330 | ||
7331 | static u16 vht_mcs_map_to_mcs_mask(u8 vht_mcs_map) | ||
7332 | { | ||
7333 | u16 mcs_mask = 0; | ||
7334 | |||
7335 | switch (vht_mcs_map) { | ||
7336 | case IEEE80211_VHT_MCS_NOT_SUPPORTED: | ||
7337 | break; | ||
7338 | case IEEE80211_VHT_MCS_SUPPORT_0_7: | ||
7339 | mcs_mask = 0x00FF; | ||
7340 | break; | ||
7341 | case IEEE80211_VHT_MCS_SUPPORT_0_8: | ||
7342 | mcs_mask = 0x01FF; | ||
7343 | break; | ||
7344 | case IEEE80211_VHT_MCS_SUPPORT_0_9: | ||
7345 | mcs_mask = 0x03FF; | ||
7346 | break; | ||
7347 | default: | ||
7348 | break; | ||
7349 | } | ||
7350 | |||
7351 | return mcs_mask; | ||
7352 | } | ||
7353 | |||
7354 | static void vht_build_mcs_mask(u16 vht_mcs_map, | ||
7355 | u16 vht_mcs_mask[NL80211_VHT_NSS_MAX]) | ||
7356 | { | ||
7357 | u8 nss; | ||
7358 | |||
7359 | for (nss = 0; nss < NL80211_VHT_NSS_MAX; nss++) { | ||
7360 | vht_mcs_mask[nss] = vht_mcs_map_to_mcs_mask(vht_mcs_map & 0x03); | ||
7361 | vht_mcs_map >>= 2; | ||
7362 | } | ||
7363 | } | ||
7364 | |||
7365 | static bool vht_set_mcs_mask(struct ieee80211_supported_band *sband, | ||
7366 | struct nl80211_txrate_vht *txrate, | ||
7367 | u16 mcs[NL80211_VHT_NSS_MAX]) | ||
7368 | { | ||
7369 | u16 tx_mcs_map = le16_to_cpu(sband->vht_cap.vht_mcs.tx_mcs_map); | ||
7370 | u16 tx_mcs_mask[NL80211_VHT_NSS_MAX] = {}; | ||
7371 | u8 i; | ||
7372 | |||
7373 | if (!sband->vht_cap.vht_supported) | ||
7374 | return false; | ||
7375 | |||
7376 | memset(mcs, 0, sizeof(u16) * NL80211_VHT_NSS_MAX); | ||
7377 | |||
7378 | /* Build vht_mcs_mask from VHT capabilities */ | ||
7379 | vht_build_mcs_mask(tx_mcs_map, tx_mcs_mask); | ||
7380 | |||
7381 | for (i = 0; i < NL80211_VHT_NSS_MAX; i++) { | ||
7382 | if ((tx_mcs_mask[i] & txrate->mcs[i]) == txrate->mcs[i]) | ||
7383 | mcs[i] = txrate->mcs[i]; | ||
7384 | else | ||
7385 | return false; | ||
7386 | } | ||
7387 | |||
7388 | return true; | ||
7389 | } | ||
7390 | |||
7331 | static const struct nla_policy nl80211_txattr_policy[NL80211_TXRATE_MAX + 1] = { | 7391 | static const struct nla_policy nl80211_txattr_policy[NL80211_TXRATE_MAX + 1] = { |
7332 | [NL80211_TXRATE_LEGACY] = { .type = NLA_BINARY, | 7392 | [NL80211_TXRATE_LEGACY] = { .type = NLA_BINARY, |
7333 | .len = NL80211_MAX_SUPP_RATES }, | 7393 | .len = NL80211_MAX_SUPP_RATES }, |
7334 | [NL80211_TXRATE_HT] = { .type = NLA_BINARY, | 7394 | [NL80211_TXRATE_HT] = { .type = NLA_BINARY, |
7335 | .len = NL80211_MAX_SUPP_HT_RATES }, | 7395 | .len = NL80211_MAX_SUPP_HT_RATES }, |
7396 | [NL80211_TXRATE_VHT] = { .len = sizeof(struct nl80211_txrate_vht)}, | ||
7336 | }; | 7397 | }; |
7337 | 7398 | ||
7338 | static int nl80211_set_tx_bitrate_mask(struct sk_buff *skb, | 7399 | static int nl80211_set_tx_bitrate_mask(struct sk_buff *skb, |
@@ -7345,6 +7406,7 @@ static int nl80211_set_tx_bitrate_mask(struct sk_buff *skb, | |||
7345 | struct net_device *dev = info->user_ptr[1]; | 7406 | struct net_device *dev = info->user_ptr[1]; |
7346 | struct nlattr *tx_rates; | 7407 | struct nlattr *tx_rates; |
7347 | struct ieee80211_supported_band *sband; | 7408 | struct ieee80211_supported_band *sband; |
7409 | u16 vht_tx_mcs_map; | ||
7348 | 7410 | ||
7349 | if (!rdev->ops->set_bitrate_mask) | 7411 | if (!rdev->ops->set_bitrate_mask) |
7350 | return -EOPNOTSUPP; | 7412 | return -EOPNOTSUPP; |
@@ -7361,6 +7423,12 @@ static int nl80211_set_tx_bitrate_mask(struct sk_buff *skb, | |||
7361 | memcpy(mask.control[i].ht_mcs, | 7423 | memcpy(mask.control[i].ht_mcs, |
7362 | sband->ht_cap.mcs.rx_mask, | 7424 | sband->ht_cap.mcs.rx_mask, |
7363 | sizeof(mask.control[i].ht_mcs)); | 7425 | sizeof(mask.control[i].ht_mcs)); |
7426 | |||
7427 | if (!sband->vht_cap.vht_supported) | ||
7428 | continue; | ||
7429 | |||
7430 | vht_tx_mcs_map = le16_to_cpu(sband->vht_cap.vht_mcs.tx_mcs_map); | ||
7431 | vht_build_mcs_mask(vht_tx_mcs_map, mask.control[i].vht_mcs); | ||
7364 | } | 7432 | } |
7365 | 7433 | ||
7366 | /* if no rates are given set it back to the defaults */ | 7434 | /* if no rates are given set it back to the defaults */ |
@@ -7399,20 +7467,32 @@ static int nl80211_set_tx_bitrate_mask(struct sk_buff *skb, | |||
7399 | mask.control[band].ht_mcs)) | 7467 | mask.control[band].ht_mcs)) |
7400 | return -EINVAL; | 7468 | return -EINVAL; |
7401 | } | 7469 | } |
7470 | if (tb[NL80211_TXRATE_VHT]) { | ||
7471 | if (!vht_set_mcs_mask( | ||
7472 | sband, | ||
7473 | nla_data(tb[NL80211_TXRATE_VHT]), | ||
7474 | mask.control[band].vht_mcs)) | ||
7475 | return -EINVAL; | ||
7476 | } | ||
7402 | 7477 | ||
7403 | if (mask.control[band].legacy == 0) { | 7478 | if (mask.control[band].legacy == 0) { |
7404 | /* don't allow empty legacy rates if HT | 7479 | /* don't allow empty legacy rates if HT or VHT |
7405 | * is not even supported. */ | 7480 | * are not even supported. |
7406 | if (!rdev->wiphy.bands[band]->ht_cap.ht_supported) | 7481 | */ |
7482 | if (!(rdev->wiphy.bands[band]->ht_cap.ht_supported || | ||
7483 | rdev->wiphy.bands[band]->vht_cap.vht_supported)) | ||
7407 | return -EINVAL; | 7484 | return -EINVAL; |
7408 | 7485 | ||
7409 | for (i = 0; i < IEEE80211_HT_MCS_MASK_LEN; i++) | 7486 | for (i = 0; i < IEEE80211_HT_MCS_MASK_LEN; i++) |
7410 | if (mask.control[band].ht_mcs[i]) | 7487 | if (mask.control[band].ht_mcs[i]) |
7411 | break; | 7488 | goto out; |
7489 | |||
7490 | for (i = 0; i < NL80211_VHT_NSS_MAX; i++) | ||
7491 | if (mask.control[band].vht_mcs[i]) | ||
7492 | goto out; | ||
7412 | 7493 | ||
7413 | /* legacy and mcs rates may not be both empty */ | 7494 | /* legacy and mcs rates may not be both empty */ |
7414 | if (i == IEEE80211_HT_MCS_MASK_LEN) | 7495 | return -EINVAL; |
7415 | return -EINVAL; | ||
7416 | } | 7496 | } |
7417 | } | 7497 | } |
7418 | 7498 | ||