Search Linux Wireless

Re: [PATCH] cfg80211: VHT (11ac) Regulatory change

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On 08/27/2012 05:35 PM, Mahesh Palivela wrote:
On 08/26/2012 02:09 PM, Johannes Berg wrote:

We don't support 5/10 MHz (yet anyway), so we don't have to worry about
that.


Yes, but how's that related to how you specify the channel?

joahnnes

Please review below function if its inline with our email discussion.
---
Compiled the code. updated patch. Review the reg_chan_use_permitted().

 include/net/cfg80211.h |   36 ++++++++++++++++
net/wireless/reg.c | 104 ++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 140 insertions(+), 0 deletions(-)

diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h
index 4c518f1..9a17e3d 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,23 @@ 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
+ * @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 2303ee7..5a4bbe9 100644
--- a/net/wireless/reg.c
+++ b/net/wireless/reg.c
@@ -1124,6 +1124,110 @@ static void reg_process_beacons(struct wiphy *wiphy)
 	wiphy_update_beacon_reg(wiphy);
 }

+static bool reg_sec_chans_permitted(struct wiphy *wiphy,
+				    u32 center_freq,
+				    u32 bw_khz)
+{
+	struct ieee80211_channel *chan;
+	u32 left_end_freq, right_end_freq;
+
+	if (center_freq == 0 || bw_khz == 0)
+		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 subtracting 10 MHZ from each of them.
+	 */
+	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)
+{
+	int r;
+	u32 desired_bw_khz = MHZ_TO_KHZ(20);
+	const struct ieee80211_reg_rule *reg_rule = NULL;
+	const struct ieee80211_freq_range *freq_range = NULL;
+	bool ret;
+
+	assert_reg_lock();
+
+	// 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:
+		desired_bw_khz = MHZ_TO_KHZ(80);
+		break;
+
+	case IEEE80211_CHAN_WIDTH_160MHZ:
+	case IEEE80211_CHAN_WIDTH_80P80MHZ:
+		desired_bw_khz = MHZ_TO_KHZ(160);
+		break;
+	}
+
+	r = freq_reg_info_regd(wiphy,
+			       chan_config->prim_chan_freq,
+			       desired_bw_khz,
+			       &reg_rule,
+			       regd);
+
+	if (r) {
+		REG_DBG_PRINT("Disabling freq %d MHz as custom "
+			      "regd has no rule that fits a %d MHz "
+			      "wide channel\n",
+			      chan_config->prim_chan_freq,
+			      KHZ_TO_MHZ(desired_bw_khz));
+		return false;
+	}
+
+	freq_range = &reg_rule->freq_range;
+
+	if (freq_range->max_bandwidth_khz < desired_bw_khz)
+		return false;
+
+	if (chan_config->chan_width == IEEE80211_CHAN_WIDTH_80P80MHZ) {
+		ret = reg_sec_chans_permitted(wiphy,
+					      chan_config->center_freq1,
+					      desired_bw_khz/2);
+		if (ret == false)
+			return ret;
+		ret = reg_sec_chans_permitted(wiphy,
+					      chan_config->center_freq2,
+					      desired_bw_khz/2);
+	} else {
+		ret = reg_sec_chans_permitted(wiphy,
+					      chan_config->center_freq1,
+					      desired_bw_khz);
+	}
+	return ret;
+}
+
 static bool is_ht40_not_allowed(struct ieee80211_channel *chan)
 {
 	if (!chan)
--
To unsubscribe from this list: send the line "unsubscribe linux-wireless" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[Index of Archives]     [Linux Host AP]     [ATH6KL]     [Linux Wireless Personal Area Network]     [Linux Bluetooth]     [Linux Netdev]     [Kernel Newbies]     [Linux Kernel]     [IDE]     [Git]     [Netfilter]     [Bugtraq]     [Yosemite Hiking]     [MIPS Linux]     [ARM Linux]     [Linux RAID]

  Powered by Linux