linux-wireless.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Karthikeyan Periyasamy <quic_periyasa@quicinc.com>
To: <ath12k@lists.infradead.org>, <johannes@sipsolutions.net>
Cc: <linux-wireless@vger.kernel.org>,
	Vasanthakumar Thiagarajan <quic_vthiagar@quicinc.com>,
	Karthikeyan Periyasamy <quic_periyasa@quicinc.com>
Subject: [PATCH 04/13] wifi: cfg80211/mac80211: extend iface comb advertisement for multi-hardware dev
Date: Thu, 28 Mar 2024 12:59:07 +0530	[thread overview]
Message-ID: <20240328072916.1164195-5-quic_periyasa@quicinc.com> (raw)
In-Reply-To: <20240328072916.1164195-1-quic_periyasa@quicinc.com>

From: Vasanthakumar Thiagarajan <quic_vthiagar@quicinc.com>

As originally discussed in the RFC [1], when a driver combines multiple
discrete hardware under one wiphy, it is required for the driver to be
able to advertise iface combination capabilities per underlying physical
hardware. Each underlying hardware's iface combination is described with
an identifier, which corresponds to the same index used in
wiphy->hw_chans[] to learn the channel capabilities of the respective
hardware. It’s important to note that supporting drivers also signal the
iface combination capabilities that are common for all the hardware
through the existing interface, maintaining backward compatibility with
user space. This commit implements provisions to advertise per-physical
hardware specific iface combination capabilities and includes sanity
checks on the advertised capabilities. The sanity check includes channel
validation against the entire range of DFS frequencies, irrespective of
regulatory configurations.

Example:

Say driver abstracts two discrete hardware under one wiphy,
wiphy->hw_chans[0] supporting 2 GHz and wiphy->hw_chans[1] supporting
5 GHz. Each hardware can operate on only one channel at any given time
but under the wiphy there can be concurrent interfaces on both the radios.
2 GHz hardware supports #STA <= 1, #AP <= 3 total 4 and 5 GHz hardware
supports #STA <= 1, #AP <= 4 total 5

struct ieee80211_iface_limit limits_common[] = {
	{ .max = 1, .types = BIT(NL80211_IFTYPE_STATION), },
	{ .max = 3, .types = BIT(NL80211_IFTYPE_AP), },
};

limits_common[] defines the minimum (common) capability out of all the
underlying hardware specific capabilities. This is reported in the existing
advertisement mechanism. Common max_interfaces across 2 GHz and 5 GHz is 4,
common num_different_channels is 1.

struct ieee80211_iface_limit limits_2ghz[] = {
	{ .max = 1, .types = BIT(NL80211_IFTYPE_STATION), },
	{ .max = 3, .types = BIT(NL80211_IFTYPE_AP), },
};

struct ieee80211_iface_limit limits_5ghz[] = {
	{ .max = 1, .types = BIT(NL80211_IFTYPE_STATION), },
	{ .max = 4, .types = BIT(NL80211_IFTYPE_AP), },
};

struct ieee80211_iface_combination combination = {
	.limits = limits_common,
	.max_interfaces = 4,
	.num_different_channels = 1,
	...
	.freq_range = {
			{
				.hw_chan_idx = 0,
				.limits = limits_2ghz,
				.max_interfaces = 4,
				.num_different_channels = 1,
				.n_limits = ARRAY_SIZE(limits_2ghz),
			},
			{
				.hw_chan_idx = 1,
				.limits = limits_5ghz,
				.max_interfaces = 5,
				.num_different_channels = 1,
				.n_limits = ARRAY_SIZE(limits_5ghz),
			},
		      },
};

[1]: https://lore.kernel.org/linux-wireless/20220920100518.19705-4-quic_vthiagar@quicinc.com/

Tested-on: QCN9274 hw2.0 PCI WLAN.WBE.1.1.1-00188-QCAHKSWPL_SILICONZ-1

Signed-off-by: Vasanthakumar Thiagarajan <quic_vthiagar@quicinc.com>
Co-developed-by: Karthikeyan Periyasamy <quic_periyasa@quicinc.com>
Signed-off-by: Karthikeyan Periyasamy <quic_periyasa@quicinc.com>
---
 include/net/cfg80211.h | 96 ++++++++++++++++++++++++++++++++++++++++++
 net/mac80211/main.c    | 46 ++++++++++++++++++++
 net/wireless/core.c    | 92 ++++++++++++++++++++++++++++++++++++++++
 3 files changed, 234 insertions(+)

diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h
index dde129e61b60..491d074fe430 100644
--- a/include/net/cfg80211.h
+++ b/include/net/cfg80211.h
@@ -5030,6 +5030,32 @@ struct ieee80211_iface_limit {
 	u16 types;
 };
 
+/**
+ * struct ieee80211_iface_per_hw - hardware specific interface combination
+ *
+ * Drivers registering multiple radios under a single wiphy can advertise
+ * radio specific interface combinations through this structure. Please note
+ * that to maintain the compatibility with the user space which is not aware
+ * of this extension of per-hardware interface combination signaling,
+ * the driver should still advertise it's interface combination (mostly
+ * common minimum capability) using the existing interface combination signaling
+ * method.
+ *
+ * @limits: limits for the given interface type
+ * @num_different_channels: number of different channels which can be active
+ *	concurrently in this hardware
+ * @max_interfaces: maximum number of total interfaces allowed in this group
+ * @n_limits: number of limitations
+ * @hw_chans_idx: index of hardware specific channel list as per wiphy @hw_chans
+ */
+struct ieee80211_iface_per_hw {
+	const struct ieee80211_iface_limit *limits;
+	u32 num_different_channels;
+	u16 max_interfaces;
+	u8 n_limits;
+	u8 hw_chans_idx;
+};
+
 /**
  * struct ieee80211_iface_combination - possible interface combination
  *
@@ -5088,6 +5114,62 @@ struct ieee80211_iface_limit {
  *		.num_different_channels = 2,
  *	};
  *
+ *
+ * 4. Hardware specific interface combination with driver supporting two
+ *    physical HW, first underlying HW supporting 2 GHz band and the other
+ *    supporting 5 GHz band.
+ *
+ *    Allow #STA <= 1, #AP <= 1, channels = 1, total 2 in 2 GHz radio and
+ *
+ *    Allow #STA <= 1, #AP <= 2, channels = 1, total 3 in 5 GHz radio
+ *
+ *    Drivers advertising per-hardware interface combination should also
+ *    advertise a sub-set of capabilities using existing interface mainly for
+ *    maintaining compatibility with the user space which is not aware of the
+ *    new per-hardware advertisement.
+ *
+ *    Sub-set interface combination advertised in the existing infrastructure:
+ *    Allow #STA <= 1, #AP <= 1, channels = 1, total 2
+ *
+ *    .. code-block:: c
+ *
+ *	struct ieee80211_iface_limit limits_overall[] = {
+ *		{ .max = 1, .types = BIT(NL80211_IFTYPE_STATION), },
+ *		{ .max = 1, .types = BIT(NL80211_IFTYPE_AP), },
+ *	};
+ *	struct ieee80211_iface_limit limits_2ghz[] = {
+ *		{ .max = 1, .types = BIT(NL80211_IFTYPE_STATION), },
+ *		{ .max = 1, .types = BIT(NL80211_IFTYPE_AP), },
+ *	};
+ *	struct ieee80211_iface_limit limits_5ghz[] = {
+ *		{ .max = 1, .types = BIT(NL80211_IFTYPE_STATION), },
+ *		{ .max = 2, .types = BIT(NL80211_IFTYPE_AP), },
+ *	};
+ *	struct ieee80211_iface_per_hw hw_combinations[] = {
+ *		{
+ *			.hw_chans_idx = 0,
+ *			.limits = limits_2ghz,
+ *			.num_different_channels = 1,
+ *			.max_interfaces = 2,
+ *			.n_limits = ARRAY_SIZE(limits_2ghz),
+ *		 },
+ *		{
+ *			.hw_chans_idx = 1,
+ *			.limits = limits_5ghz,
+ *			.num_different_channels = 1,
+ *			.max_interfaces = 3,
+ *			.n_limits = ARRAY_SIZE(limits_5ghz),
+ *		 },
+ *	};
+ *	struct ieee80211_iface_combination combination4 = {
+ *		.limits = limits_overall,
+ *		.n_limits = ARRAY_SIZE(limits_overall),
+ *		.max_interfaces = 2,
+ *		.num_different_channels = 1,
+ *		.iface_hw_list = hw_combinations,
+ *		.n_hw_list = ARRAY_SIZE(hw_combinations),
+ *	};
+ *
  */
 struct ieee80211_iface_combination {
 	/**
@@ -5145,6 +5227,20 @@ struct ieee80211_iface_combination {
 	 *   combination must be greater or equal to this value.
 	 */
 	u32 beacon_int_min_gcd;
+
+	/**
+	 * @iface_hw_list:
+	 * This wiphy has multiple underlying radios, describe interface
+	 * combination for each of them, valid only when the driver advertises
+	 * multi-radio presence in wiphy @hw_chans.
+	 */
+	const struct ieee80211_iface_per_hw *iface_hw_list;
+
+	/**
+	 * @n_hw_list:
+	 * number of hardware in @iface_hw_List
+	 */
+	u32 n_hw_list;
 };
 
 struct ieee80211_txrx_stypes {
diff --git a/net/mac80211/main.c b/net/mac80211/main.c
index 4eaea0a9975b..24765ab5121b 100644
--- a/net/mac80211/main.c
+++ b/net/mac80211/main.c
@@ -1083,6 +1083,46 @@ static int ieee80211_init_cipher_suites(struct ieee80211_local *local)
 	return 0;
 }
 
+static int
+ieee80211_check_per_hw_iface_comb(struct ieee80211_local *local,
+				  const struct ieee80211_iface_combination *c)
+{
+	int hw_idx, lmt_idx;
+	u32 hw_idx_bm = 0;
+
+	if (!local->hw.wiphy->num_hw)
+		return -EINVAL;
+
+	if (local->emulate_chanctx)
+		return -EINVAL;
+
+	for (hw_idx = 0; hw_idx < c->n_hw_list; hw_idx++) {
+		const struct ieee80211_iface_per_hw *hl;
+
+		hl = &c->iface_hw_list[hw_idx];
+
+		if (hl->hw_chans_idx >= local->hw.wiphy->num_hw)
+			return -EINVAL;
+
+		/* mac80211 doesn't support more than one IBSS interface right now */
+		for (lmt_idx = 0; lmt_idx < hl->n_limits; lmt_idx++) {
+			const struct ieee80211_iface_limit *limits;
+
+			limits = &hl->limits[lmt_idx];
+			if ((limits->types & BIT(NL80211_IFTYPE_ADHOC)) &&
+			    limits->max > 1)
+				return -EINVAL;
+		}
+
+		if (hw_idx_bm & BIT(hw_idx))
+			return -EINVAL;
+
+		hw_idx_bm |= BIT(hw_idx);
+	}
+
+	return 0;
+}
+
 int ieee80211_register_hw(struct ieee80211_hw *hw)
 {
 	struct ieee80211_local *local = hw_to_local(hw);
@@ -1323,6 +1363,12 @@ int ieee80211_register_hw(struct ieee80211_hw *hw)
 			if ((c->limits[j].types & BIT(NL80211_IFTYPE_ADHOC)) &&
 			    c->limits[j].max > 1)
 				return -EINVAL;
+
+		if (!c->n_hw_list)
+			continue;
+
+		if (ieee80211_check_per_hw_iface_comb(local, c))
+			return -EINVAL;
 	}
 
 	local->int_scan_req = kzalloc(sizeof(*local->int_scan_req) +
diff --git a/net/wireless/core.c b/net/wireless/core.c
index 2b810855a805..88de2839ed6b 100644
--- a/net/wireless/core.c
+++ b/net/wireless/core.c
@@ -600,6 +600,34 @@ struct wiphy *wiphy_new_nm(const struct cfg80211_ops *ops, int sizeof_priv,
 }
 EXPORT_SYMBOL(wiphy_new_nm);
 
+/**
+ * cfg80211_hw_chans_includes_dfs - check if per-hardware channel includes DFS
+ * @chans: hardware channel list
+ *
+ * Check if the given per-hardware list include channels in DFS range.
+ * Please note the channel is checked against the entire range of DFS
+ * freq in 5 GHz irrespective of regulatory configurations.
+ *
+ * This helper helps for the sanity checks on the channel advertisement from
+ * driver during the hw registration.
+ */
+static bool
+cfg80211_hw_chans_includes_dfs(const struct ieee80211_chans_per_hw *chans)
+{
+	int i;
+
+	for (i = 0; i < chans->n_chans; i++) {
+		if (chans->chans[i].band == NL80211_BAND_5GHZ &&
+		    ((chans->chans[i].center_freq >= 5250 &&
+		     chans->chans[i].center_freq <= 5340) ||
+		    (chans->chans[i].center_freq >= 5480 &&
+		     chans->chans[i].center_freq <= 5720)))
+			return true;
+	}
+
+	return false;
+}
+
 static int
 wiphy_verify_comb_limit(struct wiphy *wiphy,
 			const struct ieee80211_iface_limit *limits,
@@ -659,6 +687,63 @@ wiphy_verify_comb_limit(struct wiphy *wiphy,
 	return 0;
 }
 
+static int
+wiphy_verify_comb_per_hw(struct wiphy *wiphy,
+			 const struct ieee80211_iface_combination *comb)
+{
+	int i;
+	u32 hw_idx_bitmap = 0;
+	int ret;
+
+	for (i = 0; i < comb->n_hw_list; i++) {
+		const struct ieee80211_iface_per_hw *hl;
+		const struct ieee80211_chans_per_hw *chans;
+		u32 iface_cnt = 0;
+		u16 all_iftypes = 0;
+
+		hl = &comb->iface_hw_list[i];
+
+		if (hl->hw_chans_idx >= wiphy->num_hw)
+			return -EINVAL;
+
+		if (hw_idx_bitmap & BIT(hl->hw_chans_idx))
+			return -EINVAL;
+
+		hw_idx_bitmap |= BIT(hl->hw_chans_idx);
+		chans = wiphy->hw_chans[hl->hw_chans_idx];
+
+		if (WARN_ON(hl->max_interfaces < 2 &&
+			    (!comb->radar_detect_widths ||
+			     !(cfg80211_hw_chans_includes_dfs(chans)))))
+			return -EINVAL;
+
+		if (WARN_ON(!hl->num_different_channels))
+			return -EINVAL;
+
+		if (WARN_ON(comb->radar_detect_widths &&
+			    cfg80211_hw_chans_includes_dfs(chans) &&
+			    hl->num_different_channels > 1))
+			return -EINVAL;
+
+		if (WARN_ON(!hl->n_limits))
+			return -EINVAL;
+
+		ret = wiphy_verify_comb_limit(wiphy, hl->limits, hl->n_limits,
+					      comb->beacon_int_min_gcd,
+					      &iface_cnt, &all_iftypes);
+		if (ret)
+			return ret;
+
+		if (WARN_ON(all_iftypes & BIT(NL80211_IFTYPE_WDS)))
+			return -EINVAL;
+
+		if (WARN_ON(iface_cnt < comb->max_interfaces))
+			return -EINVAL;
+	}
+
+	return 0;
+}
+
 static int wiphy_verify_combinations(struct wiphy *wiphy)
 {
 	const struct ieee80211_iface_combination *c;
@@ -701,6 +786,13 @@ static int wiphy_verify_combinations(struct wiphy *wiphy)
 		/* You can't even choose that many! */
 		if (WARN_ON(cnt < c->max_interfaces))
 			return -EINVAL;
+
+		/* Do similar validations on the freq range specific interface
+		 * combinations when advertised.
+		 */
+		if (WARN_ON(c->n_hw_list &&
+			    wiphy_verify_comb_per_hw(wiphy, c)))
+			return -EINVAL;
 	}
 
 	return 0;
-- 
2.34.1


  parent reply	other threads:[~2024-03-28  7:30 UTC|newest]

Thread overview: 81+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2024-03-28  7:29 [PATCH 00/13] wifi: Add multi physical hardware iface combination support Karthikeyan Periyasamy
2024-03-28  7:29 ` [PATCH 01/13] wifi: cfg80211: Add provision to advertise multiple radio in one wiphy Karthikeyan Periyasamy
2024-03-28  7:46   ` Johannes Berg
2024-03-29 14:11     ` Vasanthakumar Thiagarajan
2024-03-29 14:30       ` Johannes Berg
2024-03-29 14:47         ` Ben Greear
2024-04-10  7:56           ` Johannes Berg
2024-04-10 14:37             ` Ben Greear
2024-04-10 15:42               ` Johannes Berg
2024-04-10 16:23                 ` Ben Greear
2024-04-10 16:43                   ` Jeff Johnson
2024-04-10 18:08                     ` Maxime Bizon
2024-04-11 16:26                       ` Vasanthakumar Thiagarajan
2024-04-11 16:39                         ` Maxime Bizon
2024-04-12  3:50                           ` Vasanthakumar Thiagarajan
2024-04-12  7:38                             ` Nicolas Escande
2024-04-12  8:01                               ` Vasanthakumar Thiagarajan
2024-04-12 12:00                                 ` James Dutton
2024-04-12 14:39                                   ` Vasanthakumar Thiagarajan
2024-04-10 18:01                   ` Maxime Bizon
2024-04-10 21:03                 ` Ben Greear
2024-04-12  4:11                   ` Vasanthakumar Thiagarajan
2024-04-12 14:08                     ` Ben Greear
2024-04-12 14:31                       ` Vasanthakumar Thiagarajan
2024-04-12 15:58                         ` Ben Greear
2024-04-13 15:40                           ` Ben Greear
2024-04-14 16:02                             ` Vasanthakumar Thiagarajan
2024-04-15 13:59                               ` Ben Greear
2024-04-14 15:52                           ` Vasanthakumar Thiagarajan
2024-04-15 13:53                             ` Ben Greear
2024-04-01  4:19     ` Karthikeyan Periyasamy
2024-04-10  9:08     ` Karthikeyan Periyasamy
2024-04-10  9:09       ` Johannes Berg
2024-04-10  9:15         ` Karthikeyan Periyasamy
2024-03-28  7:29 ` [PATCH 02/13] wifi: nl80211: send underlying multi-hardware channel capabilities to user space Karthikeyan Periyasamy
2024-03-28  7:49   ` Johannes Berg
2024-03-28 10:18     ` Karthikeyan Periyasamy
2024-03-28 12:01       ` Johannes Berg
2024-03-28 15:10         ` Karthikeyan Periyasamy
2024-03-28 16:09           ` Johannes Berg
2024-03-28 16:14             ` Jeff Johnson
2024-03-28 16:17               ` Jeff Johnson
2024-03-28 16:17               ` Johannes Berg
2024-03-28 16:18                 ` Johannes Berg
2024-03-28 18:49         ` Jakub Kicinski
2024-03-28 18:53           ` Johannes Berg
2024-03-28 18:57             ` Jakub Kicinski
2024-03-28 19:32               ` Johannes Berg
2024-03-29 14:21         ` Vasanthakumar Thiagarajan
2024-04-10  7:59           ` Johannes Berg
2024-04-10 16:52             ` Jeff Johnson
2024-03-28  7:29 ` [PATCH 03/13] wifi: cfg80211: Refactor the interface combination limit check Karthikeyan Periyasamy
2024-03-28  7:29 ` Karthikeyan Periyasamy [this message]
2024-03-28 13:22   ` [PATCH 04/13] wifi: cfg80211/mac80211: extend iface comb advertisement for multi-hardware dev Johannes Berg
2024-04-01  9:56     ` Karthikeyan Periyasamy
2024-03-28  7:29 ` [PATCH 05/13] wifi: nl80211: Refactor the interface combination limit check Karthikeyan Periyasamy
2024-03-28  7:29 ` [PATCH 06/13] wifi: nl80211: send iface combination to user space in multi-hardware wiphy Karthikeyan Periyasamy
2024-03-28 13:33   ` Johannes Berg
2024-03-28 16:19     ` Jeff Johnson
2024-03-29 14:34     ` Vasanthakumar Thiagarajan
2024-04-10  4:10       ` Karthikeyan Periyasamy
2024-04-10  6:59         ` Johannes Berg
2024-04-12  5:27       ` Karthikeyan Periyasamy
2024-04-15 14:27         ` Johannes Berg
2024-04-15 15:57           ` Karthikeyan Periyasamy
2024-03-28  7:29 ` [PATCH 07/13] wifi: cfg80211/mac80211: Refactor iface comb iterate callback for multi-hardware dev Karthikeyan Periyasamy
2024-03-28 13:36   ` Johannes Berg
2024-03-28  7:29 ` [PATCH 08/13] wifi: cfg80211: Refactor the iface combination iteration helper function Karthikeyan Periyasamy
2024-03-28 13:43   ` Johannes Berg
2024-04-02 16:35     ` Karthikeyan Periyasamy
2024-03-28  7:29 ` [PATCH 09/13] wifi: cfg80211: Add multi-hardware iface combination support Karthikeyan Periyasamy
2024-03-28 14:16   ` Johannes Berg
2024-04-03  9:58     ` Karthikeyan Periyasamy
2024-03-28  7:29 ` [PATCH 10/13] wifi: mac80211: expose channel context helper function Karthikeyan Periyasamy
2024-03-28  7:29 ` [PATCH 11/13] wifi: mac80211: Add multi-hardware support in the iface comb helper Karthikeyan Periyasamy
2024-03-28 14:41   ` Johannes Berg
2024-03-28 16:39     ` Jeff Johnson
2024-04-23 16:01     ` Karthikeyan Periyasamy
2024-03-28  7:29 ` [PATCH 12/13] wifi: ath12k: Introduce iface combination cleanup helper Karthikeyan Periyasamy
2024-03-28  7:29 ` [PATCH 13/13] wifi: ath12k: Advertise multi hardware iface combination Karthikeyan Periyasamy
2024-03-28 23:42   ` kernel test robot

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20240328072916.1164195-5-quic_periyasa@quicinc.com \
    --to=quic_periyasa@quicinc.com \
    --cc=ath12k@lists.infradead.org \
    --cc=johannes@sipsolutions.net \
    --cc=linux-wireless@vger.kernel.org \
    --cc=quic_vthiagar@quicinc.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).