History

nl80211: add support for setting fixed HE rate/gi/ltf

This patch adds the nl80211 structs, definitions, policies and parsing code required to pass fixed HE rate, GI and LTF settings.

Miles Hu committed 6 years ago

Commit eb89a6a1 parent 493a0eb3 files · +160 −8Browse files

Unified · Split

3 files
  1. include/net/cfg80211.h +3 −0
  2. include/uapi/linux/nl80211.h +28 −0
  3. net/wireless/nl80211.c +129 −8
include/net/cfg80211.h+3−0
@@ -678,7 +678,10 @@ struct cfg80211_bitrate_mask { · 677 unmodified lines
678 u32 legacy;678 u32 legacy;
679 u8 ht_mcs[IEEE80211_HT_MCS_MASK_LEN];679 u8 ht_mcs[IEEE80211_HT_MCS_MASK_LEN];
680 u16 vht_mcs[NL80211_VHT_NSS_MAX];680 u16 vht_mcs[NL80211_VHT_NSS_MAX];
681 u16 he_mcs[NL80211_HE_NSS_MAX];
681 enum nl80211_txrate_gi gi;682 enum nl80211_txrate_gi gi;
683 enum nl80211_he_gi he_gi;
684 enum nl80211_he_ltf he_ltf;
682 } control[NUM_NL80211_BANDS];685 } control[NUM_NL80211_BANDS];
683};686};
684 687
include/uapi/linux/nl80211.h+28−0
@@ -3180,6 +3180,18 @@ enum nl80211_he_gi { · 3179 unmodified lines
3180 NL80211_RATE_INFO_HE_GI_3_2,3180 NL80211_RATE_INFO_HE_GI_3_2,
3181};3181};
3182 3182
3183/**
3184 * enum nl80211_he_ltf - HE long training field
3185 * @NL80211_RATE_INFO_HE_1xLTF: 3.2 usec
3186 * @NL80211_RATE_INFO_HE_2xLTF: 6.4 usec
3187 * @NL80211_RATE_INFO_HE_4xLTF: 12.8 usec
3188 */
3189enum nl80211_he_ltf {
3190 NL80211_RATE_INFO_HE_1XLTF,
3191 NL80211_RATE_INFO_HE_2XLTF,
3192 NL80211_RATE_INFO_HE_4XLTF,
3193};
3194
3183/**3195/**
3184 * enum nl80211_he_ru_alloc - HE RU allocation values3196 * enum nl80211_he_ru_alloc - HE RU allocation values
3185 * @NL80211_RATE_INFO_HE_RU_ALLOC_26: 26-tone RU allocation3197 * @NL80211_RATE_INFO_HE_RU_ALLOC_26: 26-tone RU allocation
@@ -4735,6 +4747,10 @@ enum nl80211_key_attributes { · 1549 unmodified lines
4735 * @NL80211_TXRATE_VHT: VHT rates allowed for TX rate selection,4747 * @NL80211_TXRATE_VHT: VHT rates allowed for TX rate selection,
4736 * see &struct nl80211_txrate_vht4748 * see &struct nl80211_txrate_vht
4737 * @NL80211_TXRATE_GI: configure GI, see &enum nl80211_txrate_gi4749 * @NL80211_TXRATE_GI: configure GI, see &enum nl80211_txrate_gi
4750 * @NL80211_TXRATE_HE: HE rates allowed for TX rate selection,
4751 * see &struct nl80211_txrate_he
4752 * @NL80211_TXRATE_HE_GI: configure HE GI, 0.8us, 1.6us and 3.2us.
4753 * @NL80211_TXRATE_HE_LTF: configure HE LTF, 1XLTF, 2XLTF and 4XLTF.
4738 * @__NL80211_TXRATE_AFTER_LAST: internal4754 * @__NL80211_TXRATE_AFTER_LAST: internal
4739 * @NL80211_TXRATE_MAX: highest TX rate attribute4755 * @NL80211_TXRATE_MAX: highest TX rate attribute
4740 */4756 */
@@ -4744,6 +4760,9 @@ enum nl80211_tx_rate_attributes { · 3 unmodified lines
4744 NL80211_TXRATE_HT,4760 NL80211_TXRATE_HT,
4745 NL80211_TXRATE_VHT,4761 NL80211_TXRATE_VHT,
4746 NL80211_TXRATE_GI,4762 NL80211_TXRATE_GI,
4763 NL80211_TXRATE_HE,
4764 NL80211_TXRATE_HE_GI,
4765 NL80211_TXRATE_HE_LTF,
4747 4766
4748 /* keep last */4767 /* keep last */
4749 __NL80211_TXRATE_AFTER_LAST,4768 __NL80211_TXRATE_AFTER_LAST,
@@ -4761,6 +4780,15 @@ struct nl80211_txrate_vht { · 11 unmodified lines
4761 __u16 mcs[NL80211_VHT_NSS_MAX];4780 __u16 mcs[NL80211_VHT_NSS_MAX];
4762};4781};
4763 4782
4783#define NL80211_HE_NSS_MAX 8
4784/**
4785 * struct nl80211_txrate_he - HE MCS/NSS txrate bitmap
4786 * @mcs: MCS bitmap table for each NSS (array index 0 for 1 stream, etc.)
4787 */
4788struct nl80211_txrate_he {
4789 __u16 mcs[NL80211_HE_NSS_MAX];
4790};
4791
4764enum nl80211_txrate_gi {4792enum nl80211_txrate_gi {
4765 NL80211_TXRATE_DEFAULT_GI,4793 NL80211_TXRATE_DEFAULT_GI,
4766 NL80211_TXRATE_FORCE_SGI,4794 NL80211_TXRATE_FORCE_SGI,
net/wireless/nl80211.c+129−8
@@ -336,6 +336,13 @@ static const struct nla_policy nl80211_txattr_policy[NL80211_TXRATE_MAX + 1] = { · 335 unmodified lines
336 .len = NL80211_MAX_SUPP_HT_RATES },336 .len = NL80211_MAX_SUPP_HT_RATES },
337 [NL80211_TXRATE_VHT] = NLA_POLICY_EXACT_LEN_WARN(sizeof(struct nl80211_txrate_vht)),337 [NL80211_TXRATE_VHT] = NLA_POLICY_EXACT_LEN_WARN(sizeof(struct nl80211_txrate_vht)),
338 [NL80211_TXRATE_GI] = { .type = NLA_U8 },338 [NL80211_TXRATE_GI] = { .type = NLA_U8 },
339 [NL80211_TXRATE_HE] = NLA_POLICY_EXACT_LEN(sizeof(struct nl80211_txrate_he)),
340 [NL80211_TXRATE_HE_GI] = NLA_POLICY_RANGE(NLA_U8,
341 NL80211_RATE_INFO_HE_GI_0_8,
342 NL80211_RATE_INFO_HE_GI_3_2),
343 [NL80211_TXRATE_HE_LTF] = NLA_POLICY_RANGE(NLA_U8,
344 NL80211_RATE_INFO_HE_1XLTF,
345 NL80211_RATE_INFO_HE_4XLTF),
339};346};
340 347
341static const struct nla_policy348static const struct nla_policy
@@ -4430,21 +4437,106 @@ static bool vht_set_mcs_mask(struct ieee80211_supported_band *sband, · 4088 unmodified lines
4430 return true;4437 return true;
4431}4438}
4432 4439
4440static u16 he_mcs_map_to_mcs_mask(u8 he_mcs_map)
4441{
4442 switch (he_mcs_map) {
4443 case IEEE80211_HE_MCS_NOT_SUPPORTED:
4444 return 0;
4445 case IEEE80211_HE_MCS_SUPPORT_0_7:
4446 return 0x00FF;
4447 case IEEE80211_HE_MCS_SUPPORT_0_9:
4448 return 0x03FF;
4449 case IEEE80211_HE_MCS_SUPPORT_0_11:
4450 return 0xFFF;
4451 default:
4452 break;
4453 }
4454 return 0;
4455}
4456
4457static void he_build_mcs_mask(u16 he_mcs_map,
4458 u16 he_mcs_mask[NL80211_HE_NSS_MAX])
4459{
4460 u8 nss;
4461
4462 for (nss = 0; nss < NL80211_HE_NSS_MAX; nss++) {
4463 he_mcs_mask[nss] = he_mcs_map_to_mcs_mask(he_mcs_map & 0x03);
4464 he_mcs_map >>= 2;
4465 }
4466}
4467
4468static u16 he_get_txmcsmap(struct genl_info *info,
4469 const struct ieee80211_sta_he_cap *he_cap)
4470{
4471 struct net_device *dev = info->user_ptr[1];
4472 struct wireless_dev *wdev = dev->ieee80211_ptr;
4473 __le16 tx_mcs;
4474
4475 switch (wdev->chandef.width) {
4476 case NL80211_CHAN_WIDTH_80P80:
4477 tx_mcs = he_cap->he_mcs_nss_supp.tx_mcs_80p80;
4478 break;
4479 case NL80211_CHAN_WIDTH_160:
4480 tx_mcs = he_cap->he_mcs_nss_supp.tx_mcs_160;
4481 break;
4482 default:
4483 tx_mcs = he_cap->he_mcs_nss_supp.tx_mcs_80;
4484 break;
4485 }
4486 return le16_to_cpu(tx_mcs);
4487}
4488
4489static bool he_set_mcs_mask(struct genl_info *info,
4490 struct wireless_dev *wdev,
4491 struct ieee80211_supported_band *sband,
4492 struct nl80211_txrate_he *txrate,
4493 u16 mcs[NL80211_HE_NSS_MAX])
4494{
4495 const struct ieee80211_sta_he_cap *he_cap;
4496 u16 tx_mcs_mask[NL80211_HE_NSS_MAX] = {};
4497 u16 tx_mcs_map = 0;
4498 u8 i;
4499
4500 he_cap = ieee80211_get_he_iftype_cap(sband, wdev->iftype);
4501 if (!he_cap)
4502 return false;
4503
4504 memset(mcs, 0, sizeof(u16) * NL80211_HE_NSS_MAX);
4505
4506 tx_mcs_map = he_get_txmcsmap(info, he_cap);
4507
4508 /* Build he_mcs_mask from HE capabilities */
4509 he_build_mcs_mask(tx_mcs_map, tx_mcs_mask);
4510
4511 for (i = 0; i < NL80211_HE_NSS_MAX; i++) {
4512 if ((tx_mcs_mask[i] & txrate->mcs[i]) == txrate->mcs[i])
4513 mcs[i] = txrate->mcs[i];
4514 else
4515 return false;
4516 }
4517
4518 return true;
4519}
4520
4433static int nl80211_parse_tx_bitrate_mask(struct genl_info *info,4521static int nl80211_parse_tx_bitrate_mask(struct genl_info *info,
4434 struct nlattr *attrs[],4522 struct nlattr *attrs[],
4435 enum nl80211_attrs attr,4523 enum nl80211_attrs attr,
4436 struct cfg80211_bitrate_mask *mask)4524 struct cfg80211_bitrate_mask *mask,
4525 struct net_device *dev)
4437{4526{
4438 struct nlattr *tb[NL80211_TXRATE_MAX + 1];4527 struct nlattr *tb[NL80211_TXRATE_MAX + 1];
4439 struct cfg80211_registered_device *rdev = info->user_ptr[0];4528 struct cfg80211_registered_device *rdev = info->user_ptr[0];
4529 struct wireless_dev *wdev = dev->ieee80211_ptr;
4440 int rem, i;4530 int rem, i;
4441 struct nlattr *tx_rates;4531 struct nlattr *tx_rates;
4442 struct ieee80211_supported_band *sband;4532 struct ieee80211_supported_band *sband;
4443 u16 vht_tx_mcs_map;4533 u16 vht_tx_mcs_map, he_tx_mcs_map;
4444 4534
4445 memset(mask, 0, sizeof(*mask));4535 memset(mask, 0, sizeof(*mask));
4446 /* Default to all rates enabled */4536 /* Default to all rates enabled */
4447 for (i = 0; i < NUM_NL80211_BANDS; i++) {4537 for (i = 0; i < NUM_NL80211_BANDS; i++) {
4538 const struct ieee80211_sta_he_cap *he_cap;
4539
4448 sband = rdev->wiphy.bands[i];4540 sband = rdev->wiphy.bands[i];
4449 4541
4450 if (!sband)4542 if (!sband)
@@ -4460,6 +4552,16 @@ static int nl80211_parse_tx_bitrate_mask(struct genl_info *info, · 9 unmodified lines
4460 4552
4461 vht_tx_mcs_map = le16_to_cpu(sband->vht_cap.vht_mcs.tx_mcs_map);4553 vht_tx_mcs_map = le16_to_cpu(sband->vht_cap.vht_mcs.tx_mcs_map);
4462 vht_build_mcs_mask(vht_tx_mcs_map, mask->control[i].vht_mcs);4554 vht_build_mcs_mask(vht_tx_mcs_map, mask->control[i].vht_mcs);
4555
4556 he_cap = ieee80211_get_he_iftype_cap(sband, wdev->iftype);
4557 if (!he_cap)
4558 continue;
4559
4560 he_tx_mcs_map = he_get_txmcsmap(info, he_cap);
4561 he_build_mcs_mask(he_tx_mcs_map, mask->control[i].he_mcs);
4562
4563 mask->control[i].he_gi = 0xFF;
4564 mask->control[i].he_ltf = 0xFF;
4463 }4565 }
4464 4566
4465 /* if no rates are given set it back to the defaults */4567 /* if no rates are given set it back to the defaults */
@@ -4515,13 +4617,25 @@ static int nl80211_parse_tx_bitrate_mask(struct genl_info *info, · 49 unmodified lines
4515 if (mask->control[band].gi > NL80211_TXRATE_FORCE_LGI)4617 if (mask->control[band].gi > NL80211_TXRATE_FORCE_LGI)
4516 return -EINVAL;4618 return -EINVAL;
4517 }4619 }
4620 if (tb[NL80211_TXRATE_HE] &&
4621 !he_set_mcs_mask(info, wdev, sband,
4622 nla_data(tb[NL80211_TXRATE_HE]),
4623 mask->control[band].he_mcs))
4624 return -EINVAL;
4625 if (tb[NL80211_TXRATE_HE_GI])
4626 mask->control[band].he_gi =
4627 nla_get_u8(tb[NL80211_TXRATE_HE_GI]);
4628 if (tb[NL80211_TXRATE_HE_LTF])
4629 mask->control[band].he_ltf =
4630 nla_get_u8(tb[NL80211_TXRATE_HE_LTF]);
4518 4631
4519 if (mask->control[band].legacy == 0) {4632 if (mask->control[band].legacy == 0) {
4520 /* don't allow empty legacy rates if HT or VHT4633 /* don't allow empty legacy rates if HT, VHT or HE
4521 * are not even supported.4634 * are not even supported.
4522 */4635 */
4523 if (!(rdev->wiphy.bands[band]->ht_cap.ht_supported ||4636 if (!(rdev->wiphy.bands[band]->ht_cap.ht_supported ||
4524 rdev->wiphy.bands[band]->vht_cap.vht_supported))4637 rdev->wiphy.bands[band]->vht_cap.vht_supported ||
4638 ieee80211_get_he_iftype_cap(sband, wdev->iftype)))
4525 return -EINVAL;4639 return -EINVAL;
4526 4640
4527 for (i = 0; i < IEEE80211_HT_MCS_MASK_LEN; i++)4641 for (i = 0; i < IEEE80211_HT_MCS_MASK_LEN; i++)
@@ -4532,6 +4646,10 @@ static int nl80211_parse_tx_bitrate_mask(struct genl_info *info, · 4 unmodified lines
4532 if (mask->control[band].vht_mcs[i])4646 if (mask->control[band].vht_mcs[i])
4533 goto out;4647 goto out;
4534 4648
4649 for (i = 0; i < NL80211_HE_NSS_MAX; i++)
4650 if (mask->control[band].he_mcs[i])
4651 goto out;
4652
4535 /* legacy and mcs rates may not be both empty */4653 /* legacy and mcs rates may not be both empty */
4536 return -EINVAL;4654 return -EINVAL;
4537 }4655 }
@@ -4976,7 +5094,8 @@ static int nl80211_start_ap(struct sk_buff *skb, struct genl_info *info) · 438 unmodified lines
4976 if (info->attrs[NL80211_ATTR_TX_RATES]) {5094 if (info->attrs[NL80211_ATTR_TX_RATES]) {
4977 err = nl80211_parse_tx_bitrate_mask(info, info->attrs,5095 err = nl80211_parse_tx_bitrate_mask(info, info->attrs,
4978 NL80211_ATTR_TX_RATES,5096 NL80211_ATTR_TX_RATES,
4979 &params.beacon_rate);5097 &params.beacon_rate,
5098 dev);
4980 if (err)5099 if (err)
4981 return err;5100 return err;
4982 5101
@@ -10780,7 +10899,8 @@ static int nl80211_set_tx_bitrate_mask(struct sk_buff *skb, · 5797 unmodified lines
10780 return -EOPNOTSUPP;10899 return -EOPNOTSUPP;
10781 10900
10782 err = nl80211_parse_tx_bitrate_mask(info, info->attrs,10901 err = nl80211_parse_tx_bitrate_mask(info, info->attrs,
10783 NL80211_ATTR_TX_RATES, &mask);10902 NL80211_ATTR_TX_RATES, &mask,
10903 dev);
10784 if (err)10904 if (err)
10785 return err;10905 return err;
10786 10906
@@ -11388,7 +11508,8 @@ static int nl80211_join_mesh(struct sk_buff *skb, struct genl_info *info) · 601 unmodified lines
11388 if (info->attrs[NL80211_ATTR_TX_RATES]) {11508 if (info->attrs[NL80211_ATTR_TX_RATES]) {
11389 err = nl80211_parse_tx_bitrate_mask(info, info->attrs,11509 err = nl80211_parse_tx_bitrate_mask(info, info->attrs,
11390 NL80211_ATTR_TX_RATES,11510 NL80211_ATTR_TX_RATES,
11391 &setup.beacon_rate);11511 &setup.beacon_rate,
11512 dev);
11392 if (err)11513 if (err)
11393 return err;11514 return err;
11394 11515
@@ -14168,7 +14289,7 @@ static int parse_tid_conf(struct cfg80211_registered_device *rdev, · 2773 unmodified lines
14168 if (tid_conf->txrate_type != NL80211_TX_RATE_AUTOMATIC) {14289 if (tid_conf->txrate_type != NL80211_TX_RATE_AUTOMATIC) {
14169 attr = NL80211_TID_CONFIG_ATTR_TX_RATE;14290 attr = NL80211_TID_CONFIG_ATTR_TX_RATE;
14170 err = nl80211_parse_tx_bitrate_mask(info, attrs, attr,14291 err = nl80211_parse_tx_bitrate_mask(info, attrs, attr,
14171 &tid_conf->txrate_mask);14292 &tid_conf->txrate_mask, dev);
14172 if (err)14293 if (err)
14173 return err;14294 return err;
14174 14295

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t