linux-wireless.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Mahesh Palivela <maheshp@posedge.com>
To: "linux-wireless@vger.kernel.org" <linux-wireless@vger.kernel.org>
Cc: "linville@tuxdriver.com" <linville@tuxdriver.com>,
	Johannes Berg <johannes@sipsolutions.net>,
	Stanislaw Gruszka <sgruszka@redhat.com>
Subject: [RFC v3] cfg80211: VHT regulatory
Date: Mon, 10 Sep 2012 15:36:36 +0530	[thread overview]
Message-ID: <504DBBAC.7040300@posedge.com> (raw)

VHT (11ac) regulatory new design. VHT channel center freq, bandwidth and 
primary channel are used to decide if that channel config is permitted 
in current regulatory domain.

Signed-off-by: Mahesh Palivela <maheshp@posedge.com>
---
Implementation of review comments by Johannes.

  include/net/cfg80211.h |   37 ++++++++++++++++
  net/wireless/reg.c     |  109 +++++++++++++++++++++++++++++++++++++++++
  2 files changed, 146 insertions(+), 0 deletions(-)

diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h
index 60597cf..50180e0 100644
--- a/include/net/cfg80211.h
+++ b/include/net/cfg80211.h
@@ -83,6 +83,25 @@ enum ieee80211_band {
  };

  /**
+ * enum ieee80211_chan_width - channel bandwidths
+ *
+ * @IEEE80211_CHAN_WIDTH_20MHZ_NOHT: 20 MHz chan bandwidth No HT
+ * @IEEE80211_CHAN_WIDTH_20MHZ: 20 MHz chan bandwidth
+ * @IEEE80211_CHAN_WIDTH_40MHZ: 40 MHz chan bandwidth
+ * @IEEE80211_CHAN_WIDTH_80MHZ: 80 MHz chan bandwidth
+ * @IEEE80211_CHAN_WIDTH_160MHZ: 160 MHz chan bandwidth
+ * @IEEE80211_CHAN_WIDTH_80P80MHZ: 80+80 MHz chan bandwidth
+ */
+enum ieee80211_chan_width {
+	IEEE80211_CHAN_WIDTH_20MHZ_NOHT,
+	IEEE80211_CHAN_WIDTH_20MHZ,
+	IEEE80211_CHAN_WIDTH_40MHZ,
+	IEEE80211_CHAN_WIDTH_80MHZ,
+	IEEE80211_CHAN_WIDTH_160MHZ,
+	IEEE80211_CHAN_WIDTH_80P80MHZ
+};
+
+/**
   * enum ieee80211_channel_flags - channel flags
   *
   * Channel flags set by the regulatory control code.
@@ -144,6 +163,24 @@ struct ieee80211_channel {
  };

  /**
+ * struct ieee80211_channel_config - channel config definition
+ *
+ * This structure describes channel configuration
+ *
+ * @chan_width1: channel bandwidth
+ * @center_freq1: center frequency of 1 st frequency segment
+ * @center_freq2: center frequency of 2 nd frequency segment
+ * 	Used only for 80+80 MHz combination
+ * @prim_chan_freq: primary channel frequency
+ */
+struct ieee80211_channel_config {
+	enum ieee80211_chan_width chan_width;
+	u16 center_freq1;
+	u16 center_freq2;
+	u16 prim_chan_freq;
+};
+
+/**
   * enum ieee80211_rate_flags - rate flags
   *
   * Hardware/specification flags for rates. These are structured
diff --git a/net/wireless/reg.c b/net/wireless/reg.c
index c6e0d46..31d6f7a 100644
--- a/net/wireless/reg.c
+++ b/net/wireless/reg.c
@@ -1124,6 +1124,115 @@ static void reg_process_beacons(struct wiphy *wiphy)
  	wiphy_update_beacon_reg(wiphy);
  }

+static bool reg_fits_reg_rule_sec_chans(struct wiphy *wiphy,
+					u32 center_freq,
+					u32 bw_khz,
+					const struct ieee80211_regdomain *regd)
+{
+	int r;
+	const struct ieee80211_reg_rule *reg_rule;
+	const struct ieee80211_freq_range *freq_range;
+	struct ieee80211_channel *chan;
+	u32 left_end_freq, right_end_freq;
+
+	WARN_ON(!center_freq);
+	WARN_ON(!bw_khz);
+
+	assert_reg_lock();
+
+	r = freq_reg_info_regd(wiphy,
+			       center_freq,
+			       bw_khz,
+			       &reg_rule,
+			       regd);
+
+	if (r) {
+		REG_DBG_PRINT("Couldn't find reg rule for freq %d KHz"
+			      "and %d MHz wide channel\n",
+			      center_freq,
+			      KHZ_TO_MHZ(bw_khz));
+		return false;
+	}
+
+	freq_range = &reg_rule->freq_range;
+
+	if (freq_range->max_bandwidth_khz < bw_khz)
+		return false;
+
+	/* find left and right arms of center freq */
+	left_end_freq = center_freq - (bw_khz/2);
+	right_end_freq = center_freq + (bw_khz/2);
+
+	/* left_end_freq and right_end_freq are edge of left and right
+	 * channels. Get center freq of left and right channels
+	 * by adding 10MHz to left_end_freq and subtracting 10 MHZ from
+	 * right_end_freq.
+	 */
+	left_end_freq += MHZ_TO_KHZ(10);
+	right_end_freq -= MHZ_TO_KHZ(10);
+
+	/* find out all possible secondary channels */
+	while (left_end_freq < right_end_freq) {
+		chan = ieee80211_get_channel(wiphy, left_end_freq);
+		if (chan == NULL ||
+		    chan->flags & IEEE80211_CHAN_DISABLED) {
+			return false;
+		}
+		left_end_freq -= MHZ_TO_KHZ(20);
+	}
+
+	return true;
+}
+
+bool reg_chan_use_permitted(struct wiphy *wiphy,
+			    struct ieee80211_channel_config *chan_config,
+			    const struct ieee80211_regdomain *regd)
+{
+	u32 desired_bw_khz = MHZ_TO_KHZ(20);
+	bool ret;
+
+	/* get chan BW from config */
+	switch (chan_config->chan_width) {
+	case IEEE80211_CHAN_WIDTH_20MHZ_NOHT:
+	case IEEE80211_CHAN_WIDTH_20MHZ:
+		desired_bw_khz = MHZ_TO_KHZ(20);
+		break;
+
+	case IEEE80211_CHAN_WIDTH_40MHZ:
+		desired_bw_khz = MHZ_TO_KHZ(40);
+		break;
+
+	case IEEE80211_CHAN_WIDTH_80MHZ:
+	case IEEE80211_CHAN_WIDTH_80P80MHZ:
+		desired_bw_khz = MHZ_TO_KHZ(80);
+		break;
+
+	case IEEE80211_CHAN_WIDTH_160MHZ:
+		desired_bw_khz = MHZ_TO_KHZ(160);
+		break;
+	default:
+		REG_DBG_PRINT("Invalid channel width %d\n",
+			      chan_config->chan_width);
+		return false;
+	}
+
+	ret = reg_fits_reg_rule_sec_chans(wiphy,
+					  chan_config->center_freq1,
+					  desired_bw_khz,
+					  regd);
+
+	if (ret == false)
+		return ret;
+
+	if (chan_config->chan_width == IEEE80211_CHAN_WIDTH_80P80MHZ) {
+		ret = reg_fits_reg_rule_sec_chans(wiphy,
+						  chan_config->center_freq2,
+						  desired_bw_khz,
+						  regd);
+	}
+	return ret;
+}
+
  static bool is_ht40_not_allowed(struct ieee80211_channel *chan)
  {
  	if (!chan)

             reply	other threads:[~2012-09-10 10:06 UTC|newest]

Thread overview: 11+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2012-09-10 10:06 Mahesh Palivela [this message]
2012-09-13 20:41 ` [RFC v3] cfg80211: VHT regulatory Luis R. Rodriguez
2012-09-14  8:18   ` Mahesh Palivela
2012-09-17 15:34     ` Johannes Berg
2012-09-17 18:56       ` Luis R. Rodriguez
2012-09-24 10:48         ` Johannes Berg
2012-09-24 23:24           ` Luis R. Rodriguez
2012-09-25  7:16             ` Johannes Berg
2012-09-25 19:06               ` Luis R. Rodriguez
2012-09-28  3:41                 ` Mahesh Palivela
2012-09-28  6:40                 ` Johannes Berg

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=504DBBAC.7040300@posedge.com \
    --to=maheshp@posedge.com \
    --cc=johannes@sipsolutions.net \
    --cc=linux-wireless@vger.kernel.org \
    --cc=linville@tuxdriver.com \
    --cc=sgruszka@redhat.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).