mirror of
https://github.com/Telecominfraproject/wlan-ap.git
synced 2025-12-20 10:51:27 +00:00
312 lines
10 KiB
Diff
312 lines
10 KiB
Diff
From 933756ec29d0b4227d6bfab249b2514064ef0cc4 Mon Sep 17 00:00:00 2001
|
|
From: Vasanthakumar Thiagarajan <quic_vthiagar@quicinc.com>
|
|
Date: Sat, 8 Oct 2022 14:09:36 +0530
|
|
Subject: [PATCH 2/3] nl80211: Send multi-hw channel list and interface
|
|
combination to user space
|
|
|
|
Signed-off-by: Vasanthakumar Thiagarajan <quic_vthiagar@quicinc.com>
|
|
---
|
|
include/net/cfg80211.h | 18 ++---
|
|
include/uapi/linux/nl80211.h | 98 ++++++++++++++++++++++++++-
|
|
net/wireless/nl80211.c | 125 ++++++++++++++++++++++++++++++++++-
|
|
3 files changed, 230 insertions(+), 11 deletions(-)
|
|
|
|
--- a/include/uapi/linux/nl80211.h
|
|
+++ b/include/uapi/linux/nl80211.h
|
|
@@ -2803,6 +2803,11 @@ enum nl80211_commands {
|
|
* indicates that the sub-channel is punctured, set 0 indicates that the
|
|
* channel is active.
|
|
*
|
|
+ * @NL80211_ATTR_MULTI_HW_MACS: nested attribute to send the hardware mac
|
|
+ * specific channel capabilities to user space. Drivers registering
|
|
+ * multiple physical hardware under a wiphy can use this attribute,
|
|
+ * see &enum nl80211_multi_hw_mac_attrs.
|
|
+ *
|
|
* @NUM_NL80211_ATTR: total number of nl80211_attrs available
|
|
* @NL80211_ATTR_MAX: highest attribute number currently defined
|
|
* @__NL80211_ATTR_AFTER_LAST: internal use
|
|
@@ -3353,6 +3358,7 @@ enum nl80211_attrs {
|
|
|
|
NL80211_ATTR_AP_PS,
|
|
|
|
+ NL80211_ATTR_MULTI_HW_MACS,
|
|
/* add attributes here, update the policy in nl80211.c */
|
|
|
|
__NL80211_ATTR_AFTER_LAST,
|
|
@@ -5918,6 +5924,10 @@ enum nl80211_iface_limit_attrs {
|
|
* @NL80211_IFACE_COMB_BI_MIN_GCD: u32 attribute specifying the minimum GCD of
|
|
* different beacon intervals supported by all the interface combinations
|
|
* in this group (if not present, all beacon intervals be identical).
|
|
+ * @NL80211_IFACE_COMB_PER_HW_COMB: nested attribute specifying the interface
|
|
+ * combination for each underlying hardware when multiple hardware are
|
|
+ * registered under a single wiphy,
|
|
+ * see &enum nl80211_if_combination_per_hw_comb_attrs.
|
|
* @NUM_NL80211_IFACE_COMB: number of attributes
|
|
* @MAX_NL80211_IFACE_COMB: highest attribute number
|
|
*
|
|
@@ -5934,7 +5944,18 @@ enum nl80211_iface_limit_attrs {
|
|
* numbers = [ #{STA} <= 1, #{P2P-client,P2P-GO} <= 3 ], max = 4
|
|
* => allows a STA plus three P2P interfaces
|
|
*
|
|
- * The list of these four possibilities could completely be contained
|
|
+ * When describing per-hw combinations, the first possibility can
|
|
+ * further include the finer capabilities like below
|
|
+ * hw_chan_idx = 0, numbers = [ #{STA} <= 1, #{AP} <= 1 ],
|
|
+ * channels = 1, max = 2
|
|
+ * => allows a STA plus an AP interface on the underlying hw mac
|
|
+ * advertised at index 0 in wiphy @hw_chans array.
|
|
+ * hw_chan_idx = 1, numbers = [ #{STA} <= 1, #{AP} <= 2 ],
|
|
+ * channels = 1, max = 3
|
|
+ * => allows a STA plus two AP interfaces on the underlying hw mac
|
|
+ * advertised at index 1 in wiphy @hw_chans array.
|
|
+ *
|
|
+ * The list of these five possibilities could completely be contained
|
|
* within the %NL80211_ATTR_INTERFACE_COMBINATIONS attribute to indicate
|
|
* that any of these groups must match.
|
|
*
|
|
@@ -5953,12 +5974,44 @@ enum nl80211_if_combination_attrs {
|
|
NL80211_IFACE_COMB_RADAR_DETECT_WIDTHS,
|
|
NL80211_IFACE_COMB_RADAR_DETECT_REGIONS,
|
|
NL80211_IFACE_COMB_BI_MIN_GCD,
|
|
+ NL80211_IFACE_COMB_PER_HW_COMB,
|
|
|
|
/* keep last */
|
|
NUM_NL80211_IFACE_COMB,
|
|
MAX_NL80211_IFACE_COMB = NUM_NL80211_IFACE_COMB - 1
|
|
};
|
|
|
|
+/**
|
|
+ * enum nl80211_if_combination_per_hw_comb_attrs - per-hw iface combination
|
|
+ * attributes with multi-hw radios
|
|
+ *
|
|
+ * @NL80211_IFACE_COMB_PER_HW_COMB_UNSPEC: (reserved)
|
|
+ * @NL80211_IFACE_COMB_PER_HW_COMB_HW_IDX: u8 attribute specifying the index
|
|
+ * to the wiphy @hw_chans list for which the iface combination is being
|
|
+ * described.
|
|
+ * @NL80211_IFACE_COMB_PER_HW_COMB_LIMITS: nested attribute containing the
|
|
+ * limits for the given interface types, see
|
|
+ * &enum nl80211_iface_limit_attrs.
|
|
+ * @NL80211_IFACE_COMB_PER_HW_COMB_MAXIMUM: u32 attribute giving the maximum
|
|
+ * number of interfaces that can be created in this group. This number
|
|
+ * does not apply to the interfaces purely managed in software.
|
|
+ * @NL80211_IFACE_COMB_PER_HW_COMB_NUM_CHANNELS: u32 attribute specifying the
|
|
+ * number of different channels that can be used in this group.
|
|
+ * @NUM_NL80211_IFACE_COMB_PER_HW_COMB: number of attributes
|
|
+ * @MAX_NL80211_IFACE_COMB_PER_HW_COMB: highest attribute number
|
|
+ */
|
|
+enum nl80211_if_combination_per_hw_comb_attrs {
|
|
+ NL80211_IFACE_COMB_PER_HW_COMB_UNSPEC,
|
|
+ NL80211_IFACE_COMB_PER_HW_COMB_HW_IDX,
|
|
+ NL80211_IFACE_COMB_PER_HW_COMB_LIMITS,
|
|
+ NL80211_IFACE_COMB_PER_HW_COMB_MAXIMUM,
|
|
+ NL80211_IFACE_COMB_PER_HW_COMB_NUM_CHANNELS,
|
|
+
|
|
+ /* keep last */
|
|
+ NUM_NL80211_IFACE_COMB_PER_HW_COMB,
|
|
+ MAX_NL80211_IFACE_COMB_PER_HW_COMB =
|
|
+ NUM_NL80211_IFACE_COMB_PER_HW_COMB - 1
|
|
+};
|
|
|
|
/**
|
|
* enum nl80211_plink_state - state of a mesh peer link finite state machine
|
|
@@ -7898,4 +7951,46 @@ enum nl80211_beacon_tx_mode {
|
|
NL80211_BEACON_STAGGERED_MODE = 1,
|
|
NL80211_BEACON_BURST_MODE = 2,
|
|
};
|
|
+
|
|
+/**
|
|
+ * nl80211_multi_hw_mac_attrs - multi-hw mac attributes
|
|
+ *
|
|
+ *
|
|
+ * @NL80211_MULTI_HW_MAC_ATTR_INVALID: invalid
|
|
+ * @NL80211_MULTI_HW_MAC_ATTR_IDX: (u8) array index in wiphy @hw_chans to refer an
|
|
+ * underlying hw mac for which the supported channel list is advertised.
|
|
+ * @NL80211_MULTI_HW_MAC_ATTR_CHAN_LIST: nested attribute specifying list of
|
|
+ * supported channels, see &enum nl80211_multi_hw_mac_chan_list_attrs
|
|
+ * @__NL80211_MULTI_HW_MAC_ATTR_LAST: internal use
|
|
+ * @NL80211_MULTI_HW_MAC_ATTR_MAX: maximum multi-hw mac attribute
|
|
+ */
|
|
+enum nl80211_multi_hw_mac_attrs {
|
|
+ __NL80211_MULTI_HW_MAC_ATTR_INVALID,
|
|
+
|
|
+ NL80211_MULTI_HW_MAC_ATTR_IDX,
|
|
+ NL80211_MULTI_HW_MAC_ATTR_CHAN_LIST,
|
|
+
|
|
+ /* keep last */
|
|
+ __NL80211_MULTI_HW_MAC_ATTR_LAST,
|
|
+ NL80211_MULTI_HW_MAC_ATTR_MAX = __NL80211_MULTI_HW_MAC_ATTR_LAST - 1
|
|
+};
|
|
+
|
|
+/**
|
|
+ * nl80211_multi_hw_mac_chan_list_attrs - channel attributes for multi-hw
|
|
+ *
|
|
+ * @__NL80211_MULTI_HW_MAC_CHAN_LIST_ATTR_INVALID: invalid
|
|
+ * @NL80211_MULTI_HW_MAC_CHAN_LIST_ATTR_FREQ: channel center frequency in MHz
|
|
+ * @__NL80211_MULTI_HW_MAC_CHAN_LIST_ATTR_LAST: internal use
|
|
+ * @NL80211_MULTI_HW_MAC_CHAN_LIST_ATTR_MAX: maximum channel attribute
|
|
+ */
|
|
+enum nl80211_multi_hw_mac_chan_list_attrs {
|
|
+ __NL80211_MULTI_HW_MAC_CHAN_LIST_ATTR_INVALID,
|
|
+
|
|
+ NL80211_MULTI_HW_MAC_CHAN_LIST_ATTR_FREQ,
|
|
+
|
|
+ /* keep last */
|
|
+ __NL80211_MULTI_HW_MAC_CHAN_LIST_ATTR_LAST,
|
|
+ NL80211_MULTI_HW_MAC_CHAN_LIST_ATTR_MAX =
|
|
+ __NL80211_MULTI_HW_MAC_CHAN_LIST_ATTR_LAST - 1
|
|
+};
|
|
#endif /* __LINUX_NL80211_H */
|
|
--- a/net/wireless/nl80211.c
|
|
+++ b/net/wireless/nl80211.c
|
|
@@ -1653,6 +1653,71 @@ nla_put_failure:
|
|
return -ENOBUFS;
|
|
}
|
|
|
|
+static int
|
|
+nl80211_put_per_hw_iface_combinations(struct wiphy *wiphy, struct sk_buff *msg,
|
|
+ const struct ieee80211_iface_combination *c)
|
|
+{
|
|
+ struct nlattr *hw_combis;
|
|
+ int i;
|
|
+
|
|
+ hw_combis = nla_nest_start(msg, NL80211_IFACE_COMB_PER_HW_COMB);
|
|
+ if (!hw_combis)
|
|
+ return -ENOBUFS;
|
|
+
|
|
+ for (i = 0; i < c->n_hw_list; i++) {
|
|
+ struct nlattr *hw_combi, *limits;
|
|
+ int l;
|
|
+
|
|
+ hw_combi = nla_nest_start(msg, i + 1);
|
|
+ if (!hw_combi)
|
|
+ return -ENOBUFS;
|
|
+
|
|
+ if (nla_put_u8(msg, NL80211_IFACE_COMB_PER_HW_COMB_HW_IDX,
|
|
+ c->iface_hw_list[i].hw_chans_idx))
|
|
+ return -ENOBUFS;
|
|
+
|
|
+ limits = nla_nest_start(msg,
|
|
+ NL80211_IFACE_COMB_PER_HW_COMB_LIMITS);
|
|
+ if (!limits)
|
|
+ return -ENOBUFS;
|
|
+
|
|
+ for (l = 0; l < c->iface_hw_list->n_limits; l++) {
|
|
+ struct nlattr *limit;
|
|
+
|
|
+ limit = nla_nest_start(msg, l + 1);
|
|
+ if (!limit)
|
|
+ return -ENOBUFS;
|
|
+
|
|
+ if (nla_put_u16(msg, NL80211_IFACE_LIMIT_MAX,
|
|
+ c->iface_hw_list[i].limits[l].max))
|
|
+ return -ENOBUFS;
|
|
+
|
|
+ if (nla_put_u16(msg, NL80211_IFACE_LIMIT_TYPES,
|
|
+ c->iface_hw_list[i].limits[l].types))
|
|
+ return -ENOBUFS;
|
|
+
|
|
+ nla_nest_end(msg, limit);
|
|
+ }
|
|
+ nla_nest_end(msg, limits);
|
|
+
|
|
+ if (nla_put_u32(msg,
|
|
+ NL80211_IFACE_COMB_PER_HW_COMB_NUM_CHANNELS,
|
|
+ c->iface_hw_list[i].num_different_channels))
|
|
+ return -ENOBUFS;
|
|
+
|
|
+ if (nla_put_u16(msg,
|
|
+ NL80211_IFACE_COMB_PER_HW_COMB_MAXIMUM,
|
|
+ c->iface_hw_list[i].max_interfaces))
|
|
+ return -ENOBUFS;
|
|
+
|
|
+ nla_nest_end(msg, hw_combi);
|
|
+ }
|
|
+
|
|
+ nla_nest_end(msg, hw_combis);
|
|
+
|
|
+ return 0;
|
|
+}
|
|
+
|
|
static int nl80211_put_iface_combinations(struct wiphy *wiphy,
|
|
struct sk_buff *msg,
|
|
bool large)
|
|
@@ -1716,6 +1781,9 @@ static int nl80211_put_iface_combination
|
|
c->beacon_int_min_gcd))
|
|
goto nla_put_failure;
|
|
|
|
+ if (large && nl80211_put_per_hw_iface_combinations(wiphy, msg, c))
|
|
+ goto nla_put_failure;
|
|
+
|
|
nla_nest_end(msg, nl_combi);
|
|
}
|
|
|
|
@@ -2408,6 +2476,54 @@ fail:
|
|
return -ENOBUFS;
|
|
}
|
|
|
|
+static int nl80211_put_multi_hw_support(struct wiphy *wiphy,
|
|
+ struct sk_buff *msg)
|
|
+{
|
|
+ struct nlattr *hw_macs, *hw_mac;
|
|
+ struct nlattr *chans, *chan;
|
|
+ int i, c;
|
|
+
|
|
+ if (!wiphy->num_hw)
|
|
+ return 0;
|
|
+
|
|
+ hw_macs = nla_nest_start(msg, NL80211_ATTR_MULTI_HW_MACS);
|
|
+ if (!hw_macs)
|
|
+ return -ENOBUFS;
|
|
+
|
|
+ for (i = 0; i < wiphy->num_hw; i++) {
|
|
+ hw_mac = nla_nest_start(msg, i + 1);
|
|
+ if (!hw_mac)
|
|
+ return -ENOBUFS;
|
|
+
|
|
+ if (nla_put_u8(msg, NL80211_MULTI_HW_MAC_ATTR_IDX, i))
|
|
+ return -ENOBUFS;
|
|
+
|
|
+ chans = nla_nest_start(msg,
|
|
+ NL80211_MULTI_HW_MAC_ATTR_CHAN_LIST);
|
|
+ if (!chans)
|
|
+ return -ENOBUFS;
|
|
+
|
|
+ for (c = 0; c < wiphy->hw_chans[i]->n_chans; c++) {
|
|
+ chan = nla_nest_start(msg, c + 1);
|
|
+ if (!chan)
|
|
+ return -ENOBUFS;
|
|
+
|
|
+ if (nla_put_u32(msg,
|
|
+ NL80211_MULTI_HW_MAC_CHAN_LIST_ATTR_FREQ,
|
|
+ wiphy->hw_chans[i]->chans[c].center_freq))
|
|
+ return -ENOBUFS;
|
|
+
|
|
+ nla_nest_end(msg, chan);
|
|
+ }
|
|
+ nla_nest_end(msg, chans);
|
|
+
|
|
+ nla_nest_end(msg, hw_mac);
|
|
+ }
|
|
+
|
|
+ nla_nest_end(msg, hw_macs);
|
|
+ return 0;
|
|
+}
|
|
+
|
|
static int
|
|
nl80211_put_ru_punct_supp_bw(struct cfg80211_registered_device *rdev,
|
|
struct sk_buff *msg)
|
|
@@ -3030,6 +3146,13 @@ static int nl80211_send_wiphy(struct cfg
|
|
goto nla_put_failure;
|
|
|
|
/* done */
|
|
+ state->split_start++;
|
|
+ break;
|
|
+ case 17:
|
|
+ if (rdev->wiphy.flags & WIPHY_FLAG_SUPPORTS_MLO)
|
|
+ nla_put_flag(msg, NL80211_ATTR_MLO_SUPPORT);
|
|
+ if (nl80211_put_multi_hw_support(&rdev->wiphy, msg))
|
|
+ goto nla_put_failure;
|
|
state->split_start = 0;
|
|
break;
|
|
}
|