linux-wireless.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH v3 0/3] cfg80211/mac80211: ETSI requirements patches
@ 2018-03-28 10:24 Luca Coelho
  2018-03-28 10:24 ` [PATCH v3 1/3] cfg80211: read wmm rules from regulatory database Luca Coelho
                   ` (2 more replies)
  0 siblings, 3 replies; 9+ messages in thread
From: Luca Coelho @ 2018-03-28 10:24 UTC (permalink / raw)
  To: johannes; +Cc: linux-wireless, Luca Coelho

From: Luca Coelho <luciano.coelho@intel.com>

Hi,

Here are Haim's 3 patches for the new ETSI requirements that have been
pending due to fixes we had in our internl tree.  All the fixes have
been squased.

Please review and let me know if there are any issues.

Cheers,
Luca.

Haim Dreyfuss (3):
  cfg80211: read wmm rules from regulatory database
  mac80211: limit wmm params to comply with ETSI requirements
  cfg80211: Add API to allow querying regdb for wmm_rule

 include/net/cfg80211.h     |  28 +++++++
 include/net/regulatory.h   |  28 +++++++
 net/mac80211/cfg.c         |   3 +
 net/mac80211/ieee80211_i.h |   4 +
 net/mac80211/mlme.c        |   1 +
 net/mac80211/util.c        |  44 ++++++++++
 net/wireless/reg.c         | 204 +++++++++++++++++++++++++++++++++++++++++++--
 7 files changed, 303 insertions(+), 9 deletions(-)

-- 
2.16.2

^ permalink raw reply	[flat|nested] 9+ messages in thread

* [PATCH v3 1/3] cfg80211: read wmm rules from regulatory database
  2018-03-28 10:24 [PATCH v3 0/3] cfg80211/mac80211: ETSI requirements patches Luca Coelho
@ 2018-03-28 10:24 ` Luca Coelho
  2018-03-28 10:24 ` [PATCH v3 2/3] mac80211: limit wmm params to comply with ETSI requirements Luca Coelho
  2018-03-28 10:24 ` [PATCH v3 3/3] cfg80211: Add API to allow querying regdb for wmm_rule Luca Coelho
  2 siblings, 0 replies; 9+ messages in thread
From: Luca Coelho @ 2018-03-28 10:24 UTC (permalink / raw)
  To: johannes; +Cc: linux-wireless, Haim Dreyfuss, Luca Coelho

From: Haim Dreyfuss <haim.dreyfuss@intel.com>

ETSI EN 301 893 v211 (2017-05) standard defines a new channel access
mechanism that all devices (WLAN and LAA) need to comply with.
The regulatory database can now be loaded into the kernel and also
has the option to load optional data.
In order to be able to comply with ETSI standard, we add wmm_rule into
regulatory rule and add the option to read its value from the regulatory
database.

Signed-off-by: Haim Dreyfuss <haim.dreyfuss@intel.com>
Signed-off-by: Luca Coelho <luciano.coelho@intel.com>
---
 include/net/regulatory.h |  28 +++++++++
 net/wireless/reg.c       | 146 ++++++++++++++++++++++++++++++++++++++++++++---
 2 files changed, 167 insertions(+), 7 deletions(-)

diff --git a/include/net/regulatory.h b/include/net/regulatory.h
index f83cacce3308..60f8cc86a447 100644
--- a/include/net/regulatory.h
+++ b/include/net/regulatory.h
@@ -4,6 +4,7 @@
  * regulatory support structures
  *
  * Copyright 2008-2009	Luis R. Rodriguez <mcgrof@qca.qualcomm.com>
+ * Copyright (C) 2018 Intel Corporation
  *
  * Permission to use, copy, modify, and/or distribute this software for any
  * purpose with or without fee is hereby granted, provided that the above
@@ -188,9 +189,35 @@ struct ieee80211_power_rule {
 	u32 max_eirp;
 };
 
+/**
+ * struct ieee80211_wmm_ac - used to store per ac wmm regulatory limitation
+ *
+ * The information provided in this structure is required for QoS
+ * transmit queue configuration. Cf. IEEE 802.11 7.3.2.29.
+ *
+ * @cw_min: minimum contention window [a value of the form
+ *      2^n-1 in the range 1..32767]
+ * @cw_max: maximum contention window [like @cw_min]
+ * @cot: maximum burst time in units of 32 usecs, 0 meaning disabled
+ * @aifsn: arbitration interframe space [0..255]
+ *
+ */
+struct ieee80211_wmm_ac {
+	u16 cw_min;
+	u16 cw_max;
+	u16 cot;
+	u8 aifsn;
+};
+
+struct ieee80211_wmm_rule {
+	struct ieee80211_wmm_ac client[IEEE80211_NUM_ACS];
+	struct ieee80211_wmm_ac ap[IEEE80211_NUM_ACS];
+};
+
 struct ieee80211_reg_rule {
 	struct ieee80211_freq_range freq_range;
 	struct ieee80211_power_rule power_rule;
+	struct ieee80211_wmm_rule *wmm_rule;
 	u32 flags;
 	u32 dfs_cac_ms;
 };
@@ -198,6 +225,7 @@ struct ieee80211_reg_rule {
 struct ieee80211_regdomain {
 	struct rcu_head rcu_head;
 	u32 n_reg_rules;
+	u32 n_wmm_rules;
 	char alpha2[3];
 	enum nl80211_dfs_regions dfs_region;
 	struct ieee80211_reg_rule reg_rules[];
diff --git a/net/wireless/reg.c b/net/wireless/reg.c
index 7b42f0bacfd8..7c7c0e0f8d9d 100644
--- a/net/wireless/reg.c
+++ b/net/wireless/reg.c
@@ -5,6 +5,7 @@
  * Copyright 2008-2011	Luis R. Rodriguez <mcgrof@qca.qualcomm.com>
  * Copyright 2013-2014  Intel Mobile Communications GmbH
  * Copyright      2017  Intel Deutschland GmbH
+ * Copyright (C) 2018 Intel Corporation
  *
  * Permission to use, copy, modify, and/or distribute this software for any
  * purpose with or without fee is hereby granted, provided that the above
@@ -424,23 +425,36 @@ static const struct ieee80211_regdomain *
 reg_copy_regd(const struct ieee80211_regdomain *src_regd)
 {
 	struct ieee80211_regdomain *regd;
-	int size_of_regd;
+	int size_of_regd, size_of_wmms;
 	unsigned int i;
+	struct ieee80211_wmm_rule *d_wmm, *s_wmm;
 
 	size_of_regd =
 		sizeof(struct ieee80211_regdomain) +
 		src_regd->n_reg_rules * sizeof(struct ieee80211_reg_rule);
+	size_of_wmms = src_regd->n_wmm_rules *
+		sizeof(struct ieee80211_wmm_rule);
 
-	regd = kzalloc(size_of_regd, GFP_KERNEL);
+	regd = kzalloc(size_of_regd + size_of_wmms, GFP_KERNEL);
 	if (!regd)
 		return ERR_PTR(-ENOMEM);
 
 	memcpy(regd, src_regd, sizeof(struct ieee80211_regdomain));
 
-	for (i = 0; i < src_regd->n_reg_rules; i++)
+	d_wmm = (struct ieee80211_wmm_rule *)((u8 *)regd + size_of_regd);
+	s_wmm = (struct ieee80211_wmm_rule *)((u8 *)src_regd + size_of_regd);
+	memcpy(d_wmm, s_wmm, size_of_wmms);
+
+	for (i = 0; i < src_regd->n_reg_rules; i++) {
 		memcpy(&regd->reg_rules[i], &src_regd->reg_rules[i],
 		       sizeof(struct ieee80211_reg_rule));
+		if (!src_regd->reg_rules[i].wmm_rule)
+			continue;
 
+		regd->reg_rules[i].wmm_rule = d_wmm +
+			(src_regd->reg_rules[i].wmm_rule - s_wmm) /
+			sizeof(struct ieee80211_wmm_rule);
+	}
 	return regd;
 }
 
@@ -595,6 +609,17 @@ enum fwdb_flags {
 	FWDB_FLAG_AUTO_BW	= BIT(4),
 };
 
+struct fwdb_wmm_ac {
+	u8 ecw;
+	u8 aifsn;
+	__be16 cot;
+} __packed;
+
+struct fwdb_wmm_rule {
+	struct fwdb_wmm_ac client[IEEE80211_NUM_ACS];
+	struct fwdb_wmm_ac ap[IEEE80211_NUM_ACS];
+} __packed;
+
 struct fwdb_rule {
 	u8 len;
 	u8 flags;
@@ -602,6 +627,7 @@ struct fwdb_rule {
 	__be32 start, end, max_bw;
 	/* start of optional data */
 	__be16 cac_timeout;
+	__be16 wmm_ptr;
 } __packed __aligned(4);
 
 #define FWDB_MAGIC 0x52474442
@@ -613,6 +639,31 @@ struct fwdb_header {
 	struct fwdb_country country[];
 } __packed __aligned(4);
 
+static int ecw2cw(int ecw)
+{
+	return (1 << ecw) - 1;
+}
+
+static bool valid_wmm(struct fwdb_wmm_rule *rule)
+{
+	struct fwdb_wmm_ac *ac = (struct fwdb_wmm_ac *)rule;
+	int i;
+
+	for (i = 0; i < IEEE80211_NUM_ACS * 2; i++) {
+		u16 cw_min = ecw2cw((ac[i].ecw & 0xf0) >> 4);
+		u16 cw_max = ecw2cw(ac[i].ecw & 0x0f);
+		u8 aifsn = ac[i].aifsn;
+
+		if (cw_min >= cw_max)
+			return false;
+
+		if (aifsn < 1)
+			return false;
+	}
+
+	return true;
+}
+
 static bool valid_rule(const u8 *data, unsigned int size, u16 rule_ptr)
 {
 	struct fwdb_rule *rule = (void *)(data + (rule_ptr << 2));
@@ -623,7 +674,18 @@ static bool valid_rule(const u8 *data, unsigned int size, u16 rule_ptr)
 	/* mandatory fields */
 	if (rule->len < offsetofend(struct fwdb_rule, max_bw))
 		return false;
+	if (rule->len >= offsetofend(struct fwdb_rule, wmm_ptr)) {
+		u32 wmm_ptr = be16_to_cpu(rule->wmm_ptr) << 2;
+		struct fwdb_wmm_rule *wmm;
 
+		if (wmm_ptr + sizeof(struct fwdb_wmm_rule) > size)
+			return false;
+
+		wmm = (void *)(data + wmm_ptr);
+
+		if (!valid_wmm(wmm))
+			return false;
+	}
 	return true;
 }
 
@@ -798,23 +860,62 @@ static bool valid_regdb(const u8 *data, unsigned int size)
 	return true;
 }
 
+static void set_wmm_rule(struct ieee80211_wmm_rule *rule,
+			 struct fwdb_wmm_rule *wmm)
+{
+	unsigned int i;
+
+	for (i = 0; i < IEEE80211_NUM_ACS; i++) {
+		rule->client[i].cw_min =
+			ecw2cw((wmm->client[i].ecw & 0xf0) >> 4);
+		rule->client[i].cw_max = ecw2cw(wmm->client[i].ecw & 0x0f);
+		rule->client[i].aifsn =  wmm->client[i].aifsn;
+		rule->client[i].cot = 1000 * be16_to_cpu(wmm->client[i].cot);
+		rule->ap[i].cw_min = ecw2cw((wmm->ap[i].ecw & 0xf0) >> 4);
+		rule->ap[i].cw_max = ecw2cw(wmm->ap[i].ecw & 0x0f);
+		rule->ap[i].aifsn = wmm->ap[i].aifsn;
+		rule->ap[i].cot = 1000 * be16_to_cpu(wmm->ap[i].cot);
+	}
+}
+
+struct wmm_ptrs {
+	struct ieee80211_wmm_rule *rule;
+	u32 ptr;
+};
+
+static struct ieee80211_wmm_rule *find_wmm_ptr(struct wmm_ptrs *wmm_ptrs,
+					       u32 wmm_ptr, int n_wmms)
+{
+	int i;
+
+	for (i = 0; i < n_wmms; i++) {
+		if (wmm_ptrs[i].ptr == wmm_ptr)
+			return wmm_ptrs[i].rule;
+	}
+	return NULL;
+}
+
 static int regdb_query_country(const struct fwdb_header *db,
 			       const struct fwdb_country *country)
 {
 	unsigned int ptr = be16_to_cpu(country->coll_ptr) << 2;
 	struct fwdb_collection *coll = (void *)((u8 *)db + ptr);
 	struct ieee80211_regdomain *regdom;
-	unsigned int size_of_regd;
-	unsigned int i;
+	struct ieee80211_regdomain *tmp_rd;
+	unsigned int size_of_regd, i, n_wmms = 0;
+	struct wmm_ptrs *wmm_ptrs;
 
-	size_of_regd =
-		sizeof(struct ieee80211_regdomain) +
+	size_of_regd = sizeof(struct ieee80211_regdomain) +
 		coll->n_rules * sizeof(struct ieee80211_reg_rule);
 
 	regdom = kzalloc(size_of_regd, GFP_KERNEL);
 	if (!regdom)
 		return -ENOMEM;
 
+	wmm_ptrs = kcalloc(coll->n_rules, sizeof(*wmm_ptrs), GFP_KERNEL);
+	if (!wmm_ptrs)
+		return -ENOMEM;
+
 	regdom->n_reg_rules = coll->n_rules;
 	regdom->alpha2[0] = country->alpha2[0];
 	regdom->alpha2[1] = country->alpha2[1];
@@ -851,7 +952,38 @@ static int regdb_query_country(const struct fwdb_header *db,
 		if (rule->len >= offsetofend(struct fwdb_rule, cac_timeout))
 			rrule->dfs_cac_ms =
 				1000 * be16_to_cpu(rule->cac_timeout);
+		if (rule->len >= offsetofend(struct fwdb_rule, wmm_ptr)) {
+			u32 wmm_ptr = be16_to_cpu(rule->wmm_ptr) << 2;
+			struct ieee80211_wmm_rule *wmm_pos =
+				find_wmm_ptr(wmm_ptrs, wmm_ptr, n_wmms);
+			struct fwdb_wmm_rule *wmm;
+			struct ieee80211_wmm_rule *wmm_rule;
+
+			if (wmm_pos) {
+				rrule->wmm_rule = wmm_pos;
+				continue;
+			}
+			wmm = (void *)((u8 *)db + wmm_ptr);
+			tmp_rd = krealloc(regdom, size_of_regd + (n_wmms + 1) *
+					  sizeof(struct ieee80211_wmm_rule),
+					  GFP_KERNEL);
+
+			if (!tmp_rd) {
+				kfree(regdom);
+				return -ENOMEM;
+			}
+			regdom = tmp_rd;
+
+			wmm_rule = (struct ieee80211_wmm_rule *)
+				((u8 *)regdom + size_of_regd + n_wmms *
+				sizeof(struct ieee80211_wmm_rule));
+
+			set_wmm_rule(wmm_rule, wmm);
+			wmm_ptrs[n_wmms].ptr = wmm_ptr;
+			wmm_ptrs[n_wmms++].rule = wmm_rule;
+		}
 	}
+	kfree(wmm_ptrs);
 
 	return reg_schedule_apply(regdom);
 }
-- 
2.16.2

^ permalink raw reply related	[flat|nested] 9+ messages in thread

* [PATCH v3 2/3] mac80211: limit wmm params to comply with ETSI requirements
  2018-03-28 10:24 [PATCH v3 0/3] cfg80211/mac80211: ETSI requirements patches Luca Coelho
  2018-03-28 10:24 ` [PATCH v3 1/3] cfg80211: read wmm rules from regulatory database Luca Coelho
@ 2018-03-28 10:24 ` Luca Coelho
  2018-03-28 17:29   ` Peter Oh
  2018-03-29  8:52   ` Johannes Berg
  2018-03-28 10:24 ` [PATCH v3 3/3] cfg80211: Add API to allow querying regdb for wmm_rule Luca Coelho
  2 siblings, 2 replies; 9+ messages in thread
From: Luca Coelho @ 2018-03-28 10:24 UTC (permalink / raw)
  To: johannes; +Cc: linux-wireless, Haim Dreyfuss, Luca Coelho

From: Haim Dreyfuss <haim.dreyfuss@intel.com>

ETSI has recently added new requirements that restrict the WMM
parameter values for 5GHz frequencies.  We need to take care of the
following scenarios in order to comply with these new requirements:

1. When using mac80211 default values;
2. When the userspace tries to configure its own values;
3. When associating to an AP which advertises WWM IE.

When associating to an AP, the client uses the values in the
advertised WMM IE.  But the AP may not comply with the new ETSI
requirements, so the client needs to check the current regulatory
rules and use those limits accordingly.

Signed-off-by: Haim Dreyfuss <haim.dreyfuss@intel.com>
Signed-off-by: Luca Coelho <luciano.coelho@intel.com>
---
 net/mac80211/cfg.c         |  3 +++
 net/mac80211/ieee80211_i.h |  4 ++++
 net/mac80211/mlme.c        |  1 +
 net/mac80211/util.c        | 44 ++++++++++++++++++++++++++++++++++++++++++++
 net/wireless/reg.c         |  4 ++--
 5 files changed, 54 insertions(+), 2 deletions(-)

diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c
index 5c4b105ca398..36d128ebbac8 100644
--- a/net/mac80211/cfg.c
+++ b/net/mac80211/cfg.c
@@ -4,6 +4,7 @@
  * Copyright 2006-2010	Johannes Berg <johannes@sipsolutions.net>
  * Copyright 2013-2015  Intel Mobile Communications GmbH
  * Copyright (C) 2015-2017 Intel Deutschland GmbH
+ * Copyright (C) 2018 Intel Corporation
  *
  * This file is GPLv2 as found in COPYING.
  */
@@ -2156,6 +2157,8 @@ static int ieee80211_set_txq_params(struct wiphy *wiphy,
 	 */
 	p.uapsd = false;
 
+	ieee80211_regulatory_limit_wmm_params(sdata, &p, params->ac);
+
 	sdata->tx_conf[params->ac] = p;
 	if (drv_conf_tx(local, sdata, params->ac, &p)) {
 		wiphy_debug(local->hw.wiphy,
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h
index ae9c33cd8ada..69c276ed6eb5 100644
--- a/net/mac80211/ieee80211_i.h
+++ b/net/mac80211/ieee80211_i.h
@@ -4,6 +4,7 @@
  * Copyright 2006-2007	Jiri Benc <jbenc@suse.cz>
  * Copyright 2007-2010	Johannes Berg <johannes@sipsolutions.net>
  * Copyright 2013-2015  Intel Mobile Communications GmbH
+ * Copyright (C) 2018 Intel Corporation
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 as
@@ -1865,6 +1866,9 @@ extern const void *const mac80211_wiphy_privid; /* for wiphy privid */
 int ieee80211_frame_duration(enum nl80211_band band, size_t len,
 			     int rate, int erp, int short_preamble,
 			     int shift);
+void ieee80211_regulatory_limit_wmm_params(struct ieee80211_sub_if_data *sdata,
+					   struct ieee80211_tx_queue_params *qparam,
+					   int ac);
 void ieee80211_set_wmm_default(struct ieee80211_sub_if_data *sdata,
 			       bool bss_notify, bool enable_qos);
 void ieee80211_xmit(struct ieee80211_sub_if_data *sdata,
diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c
index ea3ba03fb952..a3bcf953d423 100644
--- a/net/mac80211/mlme.c
+++ b/net/mac80211/mlme.c
@@ -1792,6 +1792,7 @@ static bool ieee80211_sta_wmm_params(struct ieee80211_local *local,
 				   params[ac].cw_min, params[ac].cw_max, aci);
 			return false;
 		}
+		ieee80211_regulatory_limit_wmm_params(sdata, &params[ac], ac);
 	}
 
 	for (ac = 0; ac < IEEE80211_NUM_ACS; ac++) {
diff --git a/net/mac80211/util.c b/net/mac80211/util.c
index 55cd2922627a..11f9cfc016d9 100644
--- a/net/mac80211/util.c
+++ b/net/mac80211/util.c
@@ -5,6 +5,7 @@
  * Copyright 2007	Johannes Berg <johannes@sipsolutions.net>
  * Copyright 2013-2014  Intel Mobile Communications GmbH
  * Copyright (C) 2015-2017	Intel Deutschland GmbH
+ * Copyright (C) 2018 Intel Corporation
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 as
@@ -1113,6 +1114,48 @@ u32 ieee802_11_parse_elems_crc(const u8 *start, size_t len, bool action,
 	return crc;
 }
 
+void ieee80211_regulatory_limit_wmm_params(struct ieee80211_sub_if_data *sdata,
+					   struct ieee80211_tx_queue_params
+					   *qparam, int ac)
+{
+	struct ieee80211_chanctx_conf *chanctx_conf;
+	const struct ieee80211_reg_rule *rrule;
+	struct ieee80211_wmm_ac *wmm_ac;
+	u16 center_freq = 0;
+
+	if (sdata->vif.type != NL80211_IFTYPE_AP &&
+	    sdata->vif.type != NL80211_IFTYPE_STATION)
+		return;
+
+	rcu_read_lock();
+	chanctx_conf = rcu_dereference(sdata->vif.chanctx_conf);
+	if (chanctx_conf)
+		center_freq = chanctx_conf->def.chan->center_freq;
+
+	if (!center_freq) {
+		rcu_read_unlock();
+		return;
+	}
+
+	rrule = freq_reg_info(sdata->wdev.wiphy, MHZ_TO_KHZ(center_freq));
+
+	if (IS_ERR_OR_NULL(rrule) || !rrule->wmm_rule) {
+		rcu_read_unlock();
+		return;
+	}
+
+	if (sdata->vif.type == NL80211_IFTYPE_AP)
+		wmm_ac = &rrule->wmm_rule->ap[ac];
+	else
+		wmm_ac = &rrule->wmm_rule->client[ac];
+	qparam->cw_min = max_t(u16, qparam->cw_min, wmm_ac->cw_min);
+	qparam->cw_max = max_t(u16, qparam->cw_max, wmm_ac->cw_max);
+	qparam->aifs = max_t(u8, qparam->aifs, wmm_ac->aifsn);
+	qparam->txop = !qparam->txop ? wmm_ac->cot / 32 :
+		min_t(u16, qparam->txop, wmm_ac->cot / 32);
+	rcu_read_unlock();
+}
+
 void ieee80211_set_wmm_default(struct ieee80211_sub_if_data *sdata,
 			       bool bss_notify, bool enable_qos)
 {
@@ -1206,6 +1249,7 @@ void ieee80211_set_wmm_default(struct ieee80211_sub_if_data *sdata,
 				break;
 			}
 		}
+		ieee80211_regulatory_limit_wmm_params(sdata, &qparam, ac);
 
 		qparam.uapsd = false;
 
diff --git a/net/wireless/reg.c b/net/wireless/reg.c
index 7c7c0e0f8d9d..2520734bd1db 100644
--- a/net/wireless/reg.c
+++ b/net/wireless/reg.c
@@ -135,12 +135,12 @@ static void restore_regulatory_settings(bool reset_user);
 
 static const struct ieee80211_regdomain *get_cfg80211_regdom(void)
 {
-	return rtnl_dereference(cfg80211_regdomain);
+	return rcu_dereference_rtnl(cfg80211_regdomain);
 }
 
 const struct ieee80211_regdomain *get_wiphy_regdom(struct wiphy *wiphy)
 {
-	return rtnl_dereference(wiphy->regd);
+	return rcu_dereference_rtnl(wiphy->regd);
 }
 
 static const char *reg_dfs_region_str(enum nl80211_dfs_regions dfs_region)
-- 
2.16.2

^ permalink raw reply related	[flat|nested] 9+ messages in thread

* [PATCH v3 3/3] cfg80211: Add API to allow querying regdb for wmm_rule
  2018-03-28 10:24 [PATCH v3 0/3] cfg80211/mac80211: ETSI requirements patches Luca Coelho
  2018-03-28 10:24 ` [PATCH v3 1/3] cfg80211: read wmm rules from regulatory database Luca Coelho
  2018-03-28 10:24 ` [PATCH v3 2/3] mac80211: limit wmm params to comply with ETSI requirements Luca Coelho
@ 2018-03-28 10:24 ` Luca Coelho
  2 siblings, 0 replies; 9+ messages in thread
From: Luca Coelho @ 2018-03-28 10:24 UTC (permalink / raw)
  To: johannes; +Cc: linux-wireless, Haim Dreyfuss, Luca Coelho

From: Haim Dreyfuss <haim.dreyfuss@intel.com>

In general regulatory self managed devices maintain their own
regulatory profiles thus it doesn't have to query the regulatory database
on country change.

ETSI has recently introduced a new channel access mechanism for 5GHz
that all wlan devices need to comply with.
These values are stored in the regulatory database.
There are self managed devices which can't maintain these
values on their own. Add API to allow self managed regulatory devices
to query the regulatory database for high band wmm rule.

Signed-off-by: Haim Dreyfuss <haim.dreyfuss@intel.com>
Signed-off-by: Luca Coelho <luciano.coelho@intel.com>
---
 include/net/cfg80211.h | 28 ++++++++++++++++++++++++++
 net/wireless/reg.c     | 54 ++++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 82 insertions(+)

diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h
index fc40843baed3..18f57ae25171 100644
--- a/include/net/cfg80211.h
+++ b/include/net/cfg80211.h
@@ -6,6 +6,7 @@
  * Copyright 2006-2010	Johannes Berg <johannes@sipsolutions.net>
  * Copyright 2013-2014 Intel Mobile Communications GmbH
  * Copyright 2015-2017	Intel Deutschland GmbH
+ * Copyright (C) 2018 Intel Corporation
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 as
@@ -4657,6 +4658,33 @@ const struct ieee80211_reg_rule *freq_reg_info(struct wiphy *wiphy,
  */
 const char *reg_initiator_name(enum nl80211_reg_initiator initiator);
 
+/**
+ * DOC: Internal regulatory db functions
+ *
+ */
+
+/**
+ * reg_query_regdb_wmm -  Query internal regulatory db for wmm rule
+ * Regulatory self-managed driver can use it to proactively
+ *
+ * @alpha2: the ISO/IEC 3166 alpha2 wmm rule to be queried.
+ * @freq: the freqency(in MHz) to be queried.
+ * @dbptr: pointer where the regdb wmm data is to be stored (or %NULL if
+ *	irrelevant). This can be used later for deduplication.
+ * @rule: pointer to store the wmm rule from the regulatory db.
+ *
+ * Self-managed wireless drivers can use this function to  query
+ * the internal regulatory database to check whether the given
+ * ISO/IEC 3166 alpha2 country and freq have wmm rule limitations.
+ *
+ * Drivers should check the return value, its possible you can get
+ * an -ENODATA.
+ *
+ * Return: 0 on success. -ENODATA.
+ */
+int reg_query_regdb_wmm(char *alpha2, int freq, u32 *ptr,
+			struct ieee80211_wmm_rule *rule);
+
 /*
  * callbacks for asynchronous cfg80211 methods, notification
  * functions and BSS handling helpers
diff --git a/net/wireless/reg.c b/net/wireless/reg.c
index 2520734bd1db..4f5e7d6c9f62 100644
--- a/net/wireless/reg.c
+++ b/net/wireless/reg.c
@@ -878,6 +878,60 @@ static void set_wmm_rule(struct ieee80211_wmm_rule *rule,
 	}
 }
 
+static int __regdb_query_wmm(const struct fwdb_header *db,
+			     const struct fwdb_country *country, int freq,
+			     u32 *dbptr, struct ieee80211_wmm_rule *rule)
+{
+	unsigned int ptr = be16_to_cpu(country->coll_ptr) << 2;
+	struct fwdb_collection *coll = (void *)((u8 *)db + ptr);
+	int i;
+
+	for (i = 0; i < coll->n_rules; i++) {
+		__be16 *rules_ptr = (void *)((u8 *)coll + ALIGN(coll->len, 2));
+		unsigned int rule_ptr = be16_to_cpu(rules_ptr[i]) << 2;
+		struct fwdb_rule *rrule = (void *)((u8 *)db + rule_ptr);
+		struct fwdb_wmm_rule *wmm;
+		unsigned int wmm_ptr;
+
+		if (rrule->len < offsetofend(struct fwdb_rule, wmm_ptr))
+			continue;
+
+		if (freq >= KHZ_TO_MHZ(be32_to_cpu(rrule->start)) &&
+		    freq <= KHZ_TO_MHZ(be32_to_cpu(rrule->end))) {
+			wmm_ptr = be16_to_cpu(rrule->wmm_ptr) << 2;
+			wmm = (void *)((u8 *)db + wmm_ptr);
+			set_wmm_rule(rule, wmm);
+			if (dbptr)
+				*dbptr = wmm_ptr;
+			return 0;
+		}
+	}
+
+	return -ENODATA;
+}
+
+int reg_query_regdb_wmm(char *alpha2, int freq, u32 *dbptr,
+			struct ieee80211_wmm_rule *rule)
+{
+	const struct fwdb_header *hdr = regdb;
+	const struct fwdb_country *country;
+
+	if (IS_ERR(regdb))
+		return PTR_ERR(regdb);
+
+	country = &hdr->country[0];
+	while (country->coll_ptr) {
+		if (alpha2_equal(alpha2, country->alpha2))
+			return __regdb_query_wmm(regdb, country, freq, dbptr,
+						 rule);
+
+		country++;
+	}
+
+	return -ENODATA;
+}
+EXPORT_SYMBOL(reg_query_regdb_wmm);
+
 struct wmm_ptrs {
 	struct ieee80211_wmm_rule *rule;
 	u32 ptr;
-- 
2.16.2

^ permalink raw reply related	[flat|nested] 9+ messages in thread

* Re: [PATCH v3 2/3] mac80211: limit wmm params to comply with ETSI requirements
  2018-03-28 10:24 ` [PATCH v3 2/3] mac80211: limit wmm params to comply with ETSI requirements Luca Coelho
@ 2018-03-28 17:29   ` Peter Oh
  2018-03-29  8:35     ` Johannes Berg
  2018-03-29  8:52   ` Johannes Berg
  1 sibling, 1 reply; 9+ messages in thread
From: Peter Oh @ 2018-03-28 17:29 UTC (permalink / raw)
  To: Luca Coelho, johannes; +Cc: linux-wireless, Haim Dreyfuss, Luca Coelho


> +	if (sdata->vif.type == NL80211_IFTYPE_AP)
> +		wmm_ac = &rrule->wmm_rule->ap[ac];
> +	else
> +		wmm_ac = &rrule->wmm_rule->client[ac];
> +	qparam->cw_min = max_t(u16, qparam->cw_min, wmm_ac->cw_min);
> +	qparam->cw_max = max_t(u16, qparam->cw_max, wmm_ac->cw_max);
not min_t() for cw_max?

Thanks,
Peter

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [PATCH v3 2/3] mac80211: limit wmm params to comply with ETSI requirements
  2018-03-28 17:29   ` Peter Oh
@ 2018-03-29  8:35     ` Johannes Berg
  2018-03-29  8:55       ` Arend van Spriel
  0 siblings, 1 reply; 9+ messages in thread
From: Johannes Berg @ 2018-03-29  8:35 UTC (permalink / raw)
  To: Peter Oh, Luca Coelho; +Cc: linux-wireless, Haim Dreyfuss, Luca Coelho

On Wed, 2018-03-28 at 10:29 -0700, Peter Oh wrote:
> > +	if (sdata->vif.type == NL80211_IFTYPE_AP)
> > +		wmm_ac = &rrule->wmm_rule->ap[ac];
> > +	else
> > +		wmm_ac = &rrule->wmm_rule->client[ac];
> > +	qparam->cw_min = max_t(u16, qparam->cw_min, wmm_ac->cw_min);
> > +	qparam->cw_max = max_t(u16, qparam->cw_max, wmm_ac->cw_max);
> 
> not min_t() for cw_max?

No, the regulations say you have to use a long content window, hence
limiting both min and max at the lower end (hence max_t).

johannes

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [PATCH v3 2/3] mac80211: limit wmm params to comply with ETSI requirements
  2018-03-28 10:24 ` [PATCH v3 2/3] mac80211: limit wmm params to comply with ETSI requirements Luca Coelho
  2018-03-28 17:29   ` Peter Oh
@ 2018-03-29  8:52   ` Johannes Berg
  1 sibling, 0 replies; 9+ messages in thread
From: Johannes Berg @ 2018-03-29  8:52 UTC (permalink / raw)
  To: Luca Coelho; +Cc: linux-wireless, Haim Dreyfuss, Luca Coelho

On Wed, 2018-03-28 at 13:24 +0300, Luca Coelho wrote:
> 
> --- a/net/wireless/reg.c
> +++ b/net/wireless/reg.c
> @@ -135,12 +135,12 @@ static void restore_regulatory_settings(bool reset_user);
>  
>  static const struct ieee80211_regdomain *get_cfg80211_regdom(void)
>  {
> -	return rtnl_dereference(cfg80211_regdomain);
> +	return rcu_dereference_rtnl(cfg80211_regdomain);
>  }
>  
>  const struct ieee80211_regdomain *get_wiphy_regdom(struct wiphy *wiphy)
>  {
> -	return rtnl_dereference(wiphy->regd);
> +	return rcu_dereference_rtnl(wiphy->regd);
>  }
>  
>  static const char *reg_dfs_region_str(enum nl80211_dfs_regions dfs_region)

This should've stayed a separate commit, I'll take that from our tree.

johannes

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [PATCH v3 2/3] mac80211: limit wmm params to comply with ETSI requirements
  2018-03-29  8:35     ` Johannes Berg
@ 2018-03-29  8:55       ` Arend van Spriel
  2018-03-29  8:59         ` Johannes Berg
  0 siblings, 1 reply; 9+ messages in thread
From: Arend van Spriel @ 2018-03-29  8:55 UTC (permalink / raw)
  To: Johannes Berg, Peter Oh, Luca Coelho
  Cc: linux-wireless, Haim Dreyfuss, Luca Coelho

On 3/29/2018 10:35 AM, Johannes Berg wrote:
> On Wed, 2018-03-28 at 10:29 -0700, Peter Oh wrote:
>>> +	if (sdata->vif.type == NL80211_IFTYPE_AP)
>>> +		wmm_ac = &rrule->wmm_rule->ap[ac];
>>> +	else
>>> +		wmm_ac = &rrule->wmm_rule->client[ac];
>>> +	qparam->cw_min = max_t(u16, qparam->cw_min, wmm_ac->cw_min);
>>> +	qparam->cw_max = max_t(u16, qparam->cw_max, wmm_ac->cw_max);
>>
>> not min_t() for cw_max?
>
> No, the regulations say you have to use a long content window, hence

Guess you mean "contention window" :-p

> limiting both min and max at the lower end (hence max_t).

Do you have any reference to the new ETSI requirements. I would like to 
know their motivation for putting requirements on WMM parameters.

Regards,
Arend

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [PATCH v3 2/3] mac80211: limit wmm params to comply with ETSI requirements
  2018-03-29  8:55       ` Arend van Spriel
@ 2018-03-29  8:59         ` Johannes Berg
  0 siblings, 0 replies; 9+ messages in thread
From: Johannes Berg @ 2018-03-29  8:59 UTC (permalink / raw)
  To: Arend van Spriel, Peter Oh, Luca Coelho
  Cc: linux-wireless, Haim Dreyfuss, Luca Coelho

On Thu, 2018-03-29 at 10:55 +0200, Arend van Spriel wrote:
> 
> > No, the regulations say you have to use a long content window, hence
> 
> Guess you mean "contention window" :-p

Heh, yes.

> > limiting both min and max at the lower end (hence max_t).
> 
> Do you have any reference to the new ETSI requirements. I would like to 
> know their motivation for putting requirements on WMM parameters.

It's for LAA - i.e. LTE on 5 GHz.

http://www.etsi.org/deliver/etsi_en/301800_301899/301893/02.01.01_60/en_301893v020101p.pdf

See Table 7 and Table 8 and references to it.

johannes

^ permalink raw reply	[flat|nested] 9+ messages in thread

end of thread, other threads:[~2018-03-29  8:59 UTC | newest]

Thread overview: 9+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2018-03-28 10:24 [PATCH v3 0/3] cfg80211/mac80211: ETSI requirements patches Luca Coelho
2018-03-28 10:24 ` [PATCH v3 1/3] cfg80211: read wmm rules from regulatory database Luca Coelho
2018-03-28 10:24 ` [PATCH v3 2/3] mac80211: limit wmm params to comply with ETSI requirements Luca Coelho
2018-03-28 17:29   ` Peter Oh
2018-03-29  8:35     ` Johannes Berg
2018-03-29  8:55       ` Arend van Spriel
2018-03-29  8:59         ` Johannes Berg
2018-03-29  8:52   ` Johannes Berg
2018-03-28 10:24 ` [PATCH v3 3/3] cfg80211: Add API to allow querying regdb for wmm_rule Luca Coelho

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).