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
678678 u32 legacy;
679679 u8 ht_mcs[IEEE80211_HT_MCS_MASK_LEN];
680680 u16 vht_mcs[NL80211_VHT_NSS_MAX];
681+ u16 he_mcs[NL80211_HE_NSS_MAX];
681682 enum nl80211_txrate_gi gi;
683+ enum nl80211_he_gi he_gi;
684+ enum nl80211_he_ltf he_ltf;
682685 } control[NUM_NL80211_BANDS];
683686 };
684687
include/uapi/linux/nl80211.h+28−0
@@ -3180,6 +3180,18 @@ enum nl80211_he_gi { · 3179 unmodified lines
31803180 NL80211_RATE_INFO_HE_GI_3_2,
31813181 };
31823182
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+ */
3189+enum nl80211_he_ltf {
3190+ NL80211_RATE_INFO_HE_1XLTF,
3191+ NL80211_RATE_INFO_HE_2XLTF,
3192+ NL80211_RATE_INFO_HE_4XLTF,
3193+};
3194+
31833195 /**
31843196 * enum nl80211_he_ru_alloc - HE RU allocation values
31853197 * @NL80211_RATE_INFO_HE_RU_ALLOC_26: 26-tone RU allocation
@@ -4735,6 +4747,10 @@ enum nl80211_key_attributes { · 1549 unmodified lines
47354747 * @NL80211_TXRATE_VHT: VHT rates allowed for TX rate selection,
47364748 * see &struct nl80211_txrate_vht
47374749 * @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.
47384754 * @__NL80211_TXRATE_AFTER_LAST: internal
47394755 * @NL80211_TXRATE_MAX: highest TX rate attribute
47404756 */
@@ -4744,6 +4760,9 @@ enum nl80211_tx_rate_attributes { · 3 unmodified lines
47444760 NL80211_TXRATE_HT,
47454761 NL80211_TXRATE_VHT,
47464762 NL80211_TXRATE_GI,
4763+ NL80211_TXRATE_HE,
4764+ NL80211_TXRATE_HE_GI,
4765+ NL80211_TXRATE_HE_LTF,
47474766
47484767 /* keep last */
47494768 __NL80211_TXRATE_AFTER_LAST,
@@ -4761,6 +4780,15 @@ struct nl80211_txrate_vht { · 11 unmodified lines
47614780 __u16 mcs[NL80211_VHT_NSS_MAX];
47624781 };
47634782
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+ */
4788+struct nl80211_txrate_he {
4789+ __u16 mcs[NL80211_HE_NSS_MAX];
4790+};
4791+
47644792 enum nl80211_txrate_gi {
47654793 NL80211_TXRATE_DEFAULT_GI,
47664794 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
336336 .len = NL80211_MAX_SUPP_HT_RATES },
337337 [NL80211_TXRATE_VHT] = NLA_POLICY_EXACT_LEN_WARN(sizeof(struct nl80211_txrate_vht)),
338338 [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),
339346 };
340347
341348 static const struct nla_policy
@@ -4430,21 +4437,106 @@ static bool vht_set_mcs_mask(struct ieee80211_supported_band *sband, · 4088 unmodified lines
44304437 return true;
44314438 }
44324439
4440+static 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+
4457+static 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+
4468+static 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+
4489+static 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+
44334521 static int nl80211_parse_tx_bitrate_mask(struct genl_info *info,
44344522 struct nlattr *attrs[],
44354523 enum nl80211_attrs attr,
4436− struct cfg80211_bitrate_mask *mask)
4524+ struct cfg80211_bitrate_mask *mask,
4525+ struct net_device *dev)
44374526 {
44384527 struct nlattr *tb[NL80211_TXRATE_MAX + 1];
44394528 struct cfg80211_registered_device *rdev = info->user_ptr[0];
4529+ struct wireless_dev *wdev = dev->ieee80211_ptr;
44404530 int rem, i;
44414531 struct nlattr *tx_rates;
44424532 struct ieee80211_supported_band *sband;
4443− u16 vht_tx_mcs_map;
4533+ u16 vht_tx_mcs_map, he_tx_mcs_map;
44444534
44454535 memset(mask, 0, sizeof(*mask));
44464536 /* Default to all rates enabled */
44474537 for (i = 0; i < NUM_NL80211_BANDS; i++) {
4538+ const struct ieee80211_sta_he_cap *he_cap;
4539+
44484540 sband = rdev->wiphy.bands[i];
44494541
44504542 if (!sband)
@@ -4460,6 +4552,16 @@ static int nl80211_parse_tx_bitrate_mask(struct genl_info *info, · 9 unmodified lines
44604552
44614553 vht_tx_mcs_map = le16_to_cpu(sband->vht_cap.vht_mcs.tx_mcs_map);
44624554 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;
44634565 }
44644566
44654567 /* 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
45154617 if (mask->control[band].gi > NL80211_TXRATE_FORCE_LGI)
45164618 return -EINVAL;
45174619 }
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]);
45184631
45194632 if (mask->control[band].legacy == 0) {
4520− /* don't allow empty legacy rates if HT or VHT
4633+ /* don't allow empty legacy rates if HT, VHT or HE
45214634 * are not even supported.
45224635 */
45234636 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)))
45254639 return -EINVAL;
45264640
45274641 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
45324646 if (mask->control[band].vht_mcs[i])
45334647 goto out;
45344648
4649+ for (i = 0; i < NL80211_HE_NSS_MAX; i++)
4650+ if (mask->control[band].he_mcs[i])
4651+ goto out;
4652+
45354653 /* legacy and mcs rates may not be both empty */
45364654 return -EINVAL;
45374655 }
@@ -4976,7 +5094,8 @@ static int nl80211_start_ap(struct sk_buff *skb, struct genl_info *info) · 438 unmodified lines
49765094 if (info->attrs[NL80211_ATTR_TX_RATES]) {
49775095 err = nl80211_parse_tx_bitrate_mask(info, info->attrs,
49785096 NL80211_ATTR_TX_RATES,
4979− &params.beacon_rate);
5097+ &params.beacon_rate,
5098+ dev);
49805099 if (err)
49815100 return err;
49825101
@@ -10780,7 +10899,8 @@ static int nl80211_set_tx_bitrate_mask(struct sk_buff *skb, · 5797 unmodified lines
1078010899 return -EOPNOTSUPP;
1078110900
1078210901 err = nl80211_parse_tx_bitrate_mask(info, info->attrs,
10783− NL80211_ATTR_TX_RATES, &mask);
10902+ NL80211_ATTR_TX_RATES, &mask,
10903+ dev);
1078410904 if (err)
1078510905 return err;
1078610906
@@ -11388,7 +11508,8 @@ static int nl80211_join_mesh(struct sk_buff *skb, struct genl_info *info) · 601 unmodified lines
1138811508 if (info->attrs[NL80211_ATTR_TX_RATES]) {
1138911509 err = nl80211_parse_tx_bitrate_mask(info, info->attrs,
1139011510 NL80211_ATTR_TX_RATES,
11391− &setup.beacon_rate);
11511+ &setup.beacon_rate,
11512+ dev);
1139211513 if (err)
1139311514 return err;
1139411515
@@ -14168,7 +14289,7 @@ static int parse_tid_conf(struct cfg80211_registered_device *rdev, · 2773 unmodified lines
1416814289 if (tid_conf->txrate_type != NL80211_TX_RATE_AUTOMATIC) {
1416914290 attr = NL80211_TID_CONFIG_ATTR_TX_RATE;
1417014291 err = nl80211_parse_tx_bitrate_mask(info, attrs, attr,
14171− &tid_conf->txrate_mask);
14292+ &tid_conf->txrate_mask, dev);
1417214293 if (err)
1417314294 return err;
1417414295

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