From patchwork Tue Aug 28 12:20:00 2012 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Mahesh Palivela X-Patchwork-Id: 1381211 Return-Path: X-Original-To: patchwork-linux-wireless@patchwork.kernel.org Delivered-To: patchwork-process-083081@patchwork1.kernel.org Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by patchwork1.kernel.org (Postfix) with ESMTP id 143A83FDF5 for ; Tue, 28 Aug 2012 12:20:44 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1751346Ab2H1MUH (ORCPT ); Tue, 28 Aug 2012 08:20:07 -0400 Received: from hub022-nj-5.exch022.serverdata.net ([206.225.164.188]:25126 "EHLO HUB022-nj-5.exch022.serverdata.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751202Ab2H1MUH (ORCPT ); Tue, 28 Aug 2012 08:20:07 -0400 Received: from [192.168.10.29] (122.183.20.86) by east.exch022.serverdata.net (10.240.6.49) with Microsoft SMTP Server (TLS) id 14.2.309.2; Tue, 28 Aug 2012 05:20:04 -0700 Message-ID: <503CB770.4050209@posedge.com> Date: Tue, 28 Aug 2012 17:50:00 +0530 From: Mahesh Palivela User-Agent: Mozilla/5.0 (X11; Linux i686; rv:14.0) Gecko/20120713 Thunderbird/14.0 MIME-Version: 1.0 To: Johannes Berg CC: Stanislaw Gruszka , Kalle Valo , "linux-wireless@vger.kernel.org" , "linville@tuxdriver.com" Subject: Re: [PATCH] cfg80211: VHT (11ac) Regulatory change References: <502E85D9.5050301@posedge.com> <1345480718.4459.37.camel@jlt3.sipsolutions.net> <87d32k7kga.fsf@purkki.adurom.net> <20120821081839.GA2380@redhat.com> <50338E84.3050709@posedge.com> <1345564421.10280.9.camel@jlt3.sipsolutions.net> <5033CE76.6040306@posedge.com> <1345619008.4635.3.camel@jlt3.sipsolutions.net> <20120822090104.GA4959@redhat.com> <1345626282.4635.8.camel@jlt3.sipsolutions.net> <20120822101252.GA6082@redhat.com> <50376671.7080007@posedge.com> <1345809927.6991.0.camel@jlt3.sipsolutions.net> <50377CD9.3090204@posedge.com> <1345970386.3622.5.camel@jlt4.sipsolutions.net> <503B627A.6060604@posedge.com> In-Reply-To: <503B627A.6060604@posedge.com> Sender: linux-wireless-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-wireless@vger.kernel.org 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(-) --- To unsubscribe from this list: send the line "unsubscribe linux-wireless" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html 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, + ®_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 = ®_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)