2012-04-16 20:17:46

by Seth Forshee

[permalink] [raw]
Subject: [RFC PATCH 0/8] brcm80211: smac: rework regulatory support

Hi Arnd,

Here's the latest update to the brcmsmac regulatory rework that I've
been working on. I've broken it up into a series of smaller patches,
cleaned things up, and finished what changes I can with the information
available to me.

I've attempted to maintain the same high-level behavior that the
brcmsmac internal regulatory support currently enforces. I find a couple
of these to be questionable however, those being: the setting of the
radio disable state based on whether or not there are any channels
allowed by regulatory, and the handling of enabling/disabling OFDM.
Perhaps you can comment on whether or not these actions are needed.

All use of the internal regulatory data has been eliminated except for
the use of the MIMO power limits for filling out the txpwr_limits data.
I'm anticipating that you'll provide information on how this needs to be
handled. Otherwise I think these patches are very nearly complete, so
please let me know if you see anything that needs to be changed.

So far these changes are testing well on a MacBook Air 4,1 with BCM43224
wireless. I'm now able to see and associate with my AP on channel 52,
which was not possible previously.

Cheers,
Seth


Seth Forshee (8):
brcm80211: smac: don't set up tx power limits during initialization
brcm80211: smac: always set channel specified by mac80211
brcm80211: smac: clean up channel.c
brcm80211: smac: inform mac80211 of the X2 regulatory domain
brcm80211: smac: enable/disable radio on regulatory updates
brcm80211: smac: use mac80211 channel data for tx power limits
brcm80211: smac: don't validate channels against internal regulatory
data
brcm80211: smac: use current regulatory domain when checking whether
OFDM is allowed

drivers/net/wireless/brcm80211/brcmsmac/channel.c | 1229 ++++----------------
drivers/net/wireless/brcm80211/brcmsmac/channel.h | 5 +-
.../net/wireless/brcm80211/brcmsmac/mac80211_if.c | 2 +
drivers/net/wireless/brcm80211/brcmsmac/main.c | 36 +-
4 files changed, 268 insertions(+), 1004 deletions(-)



2012-04-16 20:17:57

by Seth Forshee

[permalink] [raw]
Subject: [RFC PATCH 5/8] brcm80211: smac: enable/disable radio on regulatory updates

Currently the radio disable state is only updated during initialization,
and it's only checked against the internal world domain. This is
unnecessary, as there are always valid channels against this domain.
Instead, check whether any channels are enabled in the regulatory
notifier and update the radio state accordingly.

Signed-off-by: Seth Forshee <[email protected]>
---
drivers/net/wireless/brcm80211/brcmsmac/channel.c | 66 ++++++++-------------
1 file changed, 25 insertions(+), 41 deletions(-)

diff --git a/drivers/net/wireless/brcm80211/brcmsmac/channel.c b/drivers/net/wireless/brcm80211/brcmsmac/channel.c
index fd5b807..590e8c1 100644
--- a/drivers/net/wireless/brcm80211/brcmsmac/channel.c
+++ b/drivers/net/wireless/brcm80211/brcmsmac/channel.c
@@ -681,46 +681,6 @@ brcms_c_channel_min_txpower_limits_with_local_constraint(

}

-/* Update the radio state (enable/disable) and tx power targets
- * based on a new set of channel/regulatory information
- */
-static void brcms_c_channels_commit(struct brcms_cm_info *wlc_cm)
-{
- struct brcms_c_info *wlc = wlc_cm->wlc;
- uint chan;
-
- /* search for the existence of any valid channel */
- for (chan = 0; chan < MAXCHANNEL; chan++) {
- if (brcms_c_valid_channel20_db(wlc->cmi, chan))
- break;
- }
- if (chan == MAXCHANNEL)
- chan = INVCHANNEL;
-
- /*
- * based on the channel search above, set or
- * clear WL_RADIO_COUNTRY_DISABLE.
- */
- if (chan == INVCHANNEL) {
- /*
- * country/locale with no valid channels, set
- * the radio disable bit
- */
- mboolset(wlc->pub->radio_disabled, WL_RADIO_COUNTRY_DISABLE);
- wiphy_err(wlc->wiphy, "wl%d: %s: no valid channel for \"%s\" "
- "nbands %d bandlocked %d\n", wlc->pub->unit,
- __func__, wlc_cm->world_regd->regdomain->alpha2,
- wlc->pub->_nbands, wlc->bandlocked);
- } else if (mboolisset(wlc->pub->radio_disabled,
- WL_RADIO_COUNTRY_DISABLE)) {
- /*
- * country/locale with valid channel, clear
- * the radio disable bit
- */
- mboolclr(wlc->pub->radio_disabled, WL_RADIO_COUNTRY_DISABLE);
- }
-}
-
static int
brcms_c_channels_init(struct brcms_cm_info *wlc_cm,
const struct country_info *country)
@@ -766,7 +726,6 @@ brcms_c_channels_init(struct brcms_cm_info *wlc_cm,
}

brcms_c_quiet_channels_reset(wlc_cm);
- brcms_c_channels_commit(wlc_cm);

return 0;
}
@@ -1240,12 +1199,37 @@ static int brcms_reg_notifier(struct wiphy *wiphy,
struct ieee80211_hw *hw = wiphy_to_ieee80211_hw(wiphy);
struct brcms_info *wl = hw->priv;
struct brcms_c_info *wlc = wl->wlc;
+ struct ieee80211_supported_band *sband;
+ struct ieee80211_channel *ch;
+ int band, i, n_channels = 0;

brcms_reg_apply_radar_flags(wiphy);

if (request && request->initiator == NL80211_REGDOM_SET_BY_COUNTRY_IE)
brcms_reg_apply_beaconing_flags(wiphy, request->initiator);

+ /* Disable radio if all channels disallowed by regulatory */
+ for (band = 0; band < IEEE80211_NUM_BANDS; band++) {
+ sband = wiphy->bands[band];
+ if (!sband)
+ continue;
+
+ for (i = 0; i < sband->n_channels; i++) {
+ ch = &sband->channels[i];
+
+ if (!(ch->flags & IEEE80211_CHAN_DISABLED))
+ n_channels++;
+ }
+ }
+
+ if (n_channels == 0) {
+ mboolset(wlc->pub->radio_disabled, WL_RADIO_COUNTRY_DISABLE);
+ wiphy_err(wlc->wiphy, "wl%d: %s: no valid channel for \"%s\"\n",
+ wlc->pub->unit, __func__, request->alpha2);
+ } else {
+ mboolclr(wlc->pub->radio_disabled, WL_RADIO_COUNTRY_DISABLE);
+ }
+
if (wlc->pub->_nbands > 1 || wlc->band->bandtype == BRCM_BAND_2G)
wlc_phy_chanspec_ch14_widefilter_set(wlc->band->pi,
brcms_c_japan_ccode(request->alpha2));
--
1.7.9.5


2012-04-16 20:17:50

by Seth Forshee

[permalink] [raw]
Subject: [RFC PATCH 2/8] brcm80211: smac: always set channel specified by mac80211

In some situations brcmsmac is choosing a channel internally. This makes
it difficult at times to know what channel to use for enforcing
regulatory constraints, so instead always use the channel from the
mac80211 configuration.

Signed-off-by: Seth Forshee <[email protected]>
---
drivers/net/wireless/brcm80211/brcmsmac/main.c | 30 +++++-------------------
1 file changed, 6 insertions(+), 24 deletions(-)

diff --git a/drivers/net/wireless/brcm80211/brcmsmac/main.c b/drivers/net/wireless/brcm80211/brcmsmac/main.c
index 7083db7..41d51cb 100644
--- a/drivers/net/wireless/brcm80211/brcmsmac/main.c
+++ b/drivers/net/wireless/brcm80211/brcmsmac/main.c
@@ -3150,20 +3150,6 @@ void brcms_c_reset(struct brcms_c_info *wlc)
brcms_b_reset(wlc->hw);
}

-/* Return the channel the driver should initialize during brcms_c_init.
- * the channel may have to be changed from the currently configured channel
- * if other configurations are in conflict (bandlocked, 11n mode disabled,
- * invalid channel for current country, etc.)
- */
-static u16 brcms_c_init_chanspec(struct brcms_c_info *wlc)
-{
- u16 chanspec =
- 1 | WL_CHANSPEC_BW_20 | WL_CHANSPEC_CTL_SB_NONE |
- WL_CHANSPEC_BAND_2G;
-
- return chanspec;
-}
-
void brcms_c_init_scb(struct scb *scb)
{
int i;
@@ -5152,6 +5138,8 @@ static void brcms_c_wme_retries_write(struct brcms_c_info *wlc)
/* make interface operational */
int brcms_c_up(struct brcms_c_info *wlc)
{
+ struct ieee80211_channel *ch;
+
BCMMSG(wlc->wiphy, "wl%d\n", wlc->pub->unit);

/* HW is turned off so don't try to access it */
@@ -5218,8 +5206,9 @@ int brcms_c_up(struct brcms_c_info *wlc)
wlc->pub->up = true;

if (wlc->bandinit_pending) {
+ ch = wlc->pub->ieee_hw->conf.channel;
brcms_c_suspend_mac_and_wait(wlc);
- brcms_c_set_chanspec(wlc, wlc->default_bss->chanspec);
+ brcms_c_set_chanspec(wlc, ch20mhz_chspec(ch->hw_value));
wlc->bandinit_pending = false;
brcms_c_enable_mac(wlc);
}
@@ -8224,19 +8213,12 @@ bool brcms_c_dpc(struct brcms_c_info *wlc, bool bounded)
void brcms_c_init(struct brcms_c_info *wlc, bool mute_tx)
{
struct bcma_device *core = wlc->hw->d11core;
+ struct ieee80211_channel *ch = wlc->pub->ieee_hw->conf.channel;
u16 chanspec;

BCMMSG(wlc->wiphy, "wl%d\n", wlc->pub->unit);

- /*
- * This will happen if a big-hammer was executed. In
- * that case, we want to go back to the channel that
- * we were on and not new channel
- */
- if (wlc->pub->associated)
- chanspec = wlc->home_chanspec;
- else
- chanspec = brcms_c_init_chanspec(wlc);
+ chanspec = ch20mhz_chspec(ch->hw_value);

brcms_b_init(wlc->hw, chanspec);

--
1.7.9.5


2012-04-16 20:53:22

by Seth Forshee

[permalink] [raw]
Subject: Re: [RFC PATCH 0/8] brcm80211: smac: rework regulatory support

On Mon, Apr 16, 2012 at 10:42:07PM +0200, Arend van Spriel wrote:
> >I've attempted to maintain the same high-level behavior that the
> >brcmsmac internal regulatory support currently enforces. I find a couple
> >of these to be questionable however, those being: the setting of the
> >radio disable state based on whether or not there are any channels
> >allowed by regulatory, and the handling of enabling/disabling OFDM.
> >Perhaps you can comment on whether or not these actions are needed.
>
> Regarding questionable things, you mean the transmit mute or is
> there another radio disable that I have not found yet. I only recall
> that channel 14 (JP only) does not allow OFDM so it may be to
> accommodate that. It may not be explicitly needed as mac80211
> provides the rate and/or modulation to use for the transmit frame.

I'm referring to radio_disabled in struct brcms_pub, specifically to the
setting and clearing of the WL_RADIO_COUNTRY_DISABLE bit in this field.
Patch 5 in the series deals specifically with this functionality.

Btw, I restored setting the transmit mute for passive channels in this
series, which I had to remove in earlier versions of these changes. Your
patch to enable tx after seeing a beacon fixed the issue I was seeing.

> >So far these changes are testing well on a MacBook Air 4,1 with BCM43224
> >wireless. I'm now able to see and associate with my AP on channel 52,
> >which was not possible previously.
>
> I will try to organize some regulatory testing over here with your patches.

Great, thanks!

Seth


2012-04-16 20:17:53

by Seth Forshee

[permalink] [raw]
Subject: [RFC PATCH 3/8] brcm80211: smac: clean up channel.c

Much of the code is either unsed or never put to any useful purpose.
Remove this code in advance of reworking the driver's regulatory
support.

Signed-off-by: Seth Forshee <[email protected]>
---
drivers/net/wireless/brcm80211/brcmsmac/channel.c | 254 +--------------------
1 file changed, 5 insertions(+), 249 deletions(-)

diff --git a/drivers/net/wireless/brcm80211/brcmsmac/channel.c b/drivers/net/wireless/brcm80211/brcmsmac/channel.c
index 71fce2c..1998c86 100644
--- a/drivers/net/wireless/brcm80211/brcmsmac/channel.c
+++ b/drivers/net/wireless/brcm80211/brcmsmac/channel.c
@@ -58,18 +58,8 @@
LOCALE_CHAN_12_13 | \
LOCALE_CHAN_14)

-#define LOCALE_RADAR_SET_NONE 0
-#define LOCALE_RADAR_SET_1 1
-
#define LOCALE_RESTRICTED_NONE 0
#define LOCALE_RESTRICTED_SET_2G_SHORT 1
-#define LOCALE_RESTRICTED_CHAN_165 2
-#define LOCALE_CHAN_ALL_5G 3
-#define LOCALE_RESTRICTED_JAPAN_LEGACY 4
-#define LOCALE_RESTRICTED_11D_2G 5
-#define LOCALE_RESTRICTED_11D_5G 6
-#define LOCALE_RESTRICTED_LOW_HI 7
-#define LOCALE_RESTRICTED_12_13_14 8

#define LOCALE_2G_IDX_i 0
#define LOCALE_5G_IDX_11 0
@@ -118,8 +108,6 @@
(((c) < 100) ? 2 : \
(((c) < 149) ? 3 : 4))))

-#define ISDFS_EU(fl) (((fl) & BRCMS_DFS_EU) == BRCMS_DFS_EU)
-
struct brcms_cm_band {
/* struct locale_info flags */
u8 locale_flags;
@@ -127,9 +115,6 @@ struct brcms_cm_band {
struct brcms_chanvec valid_channels;
/* List of restricted use channels */
const struct brcms_chanvec *restricted_channels;
- /* List of radar sensitive channels */
- const struct brcms_chanvec *radar_channels;
- u8 PAD[8];
};

/* locale per-channel tx power limits for MIMO frames
@@ -158,7 +143,6 @@ struct brcms_cm_info {
char srom_ccode[BRCM_CNTRY_BUF_SZ]; /* Country Code in SROM */
uint srom_regrev; /* Regulatory Rev for the SROM ccode */
const struct country_info *country; /* current country def */
- char ccode[BRCM_CNTRY_BUF_SZ]; /* current internal Country Code */
uint regrev; /* current Regulatory Revision */
char country_abbrev[BRCM_CNTRY_BUF_SZ]; /* current advertised ccode */
/* per-band state (one per phy/radio) */
@@ -171,14 +155,10 @@ struct brcms_cm_info {
/* locale channel and power info. */
struct locale_info {
u32 valid_channels;
- /* List of radar sensitive channels */
- u8 radar_channels;
/* List of channels used only if APs are detected */
u8 restricted_channels;
/* Max tx pwr in qdBm for each sub-band */
s8 maxpwr[BRCMS_MAXPWR_TBL_SIZE];
- /* Country IE advertised max tx pwr in dBm per sub-band */
- s8 pub_maxpwr[BAND_5G_PWR_LVLS];
u8 flags;
};

@@ -196,46 +176,10 @@ static const struct brcms_chanvec chanvec_none = {
0x00, 0x00, 0x00, 0x00}
};

-/* All 2.4 GHz HW channels */
-static const struct brcms_chanvec chanvec_all_2G = {
- {0xfe, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00}
-};
-
-/* All 5 GHz HW channels */
-static const struct brcms_chanvec chanvec_all_5G = {
- {0x00, 0x00, 0x00, 0x00, 0x54, 0x55, 0x11, 0x11,
- 0x01, 0x00, 0x00, 0x00, 0x10, 0x11, 0x11, 0x11,
- 0x11, 0x11, 0x20, 0x22, 0x22, 0x00, 0x00, 0x11,
- 0x11, 0x11, 0x11, 0x01}
-};
-
-/*
- * Radar channel sets
- */
-
-/* Channels 52 - 64, 100 - 140 */
-static const struct brcms_chanvec radar_set1 = {
- {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x11, /* 52 - 60 */
- 0x01, 0x00, 0x00, 0x00, 0x10, 0x11, 0x11, 0x11, /* 64, 100 - 124 */
- 0x11, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 128 - 140 */
- 0x00, 0x00, 0x00, 0x00}
-};
-
/*
* Restricted channel sets
*/

-/* Channels 34, 38, 42, 46 */
-static const struct brcms_chanvec restricted_set_japan_legacy = {
- {0x00, 0x00, 0x00, 0x00, 0x44, 0x44, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00}
-};
-
/* Channels 12, 13 */
static const struct brcms_chanvec restricted_set_2g_short = {
{0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
@@ -244,47 +188,11 @@ static const struct brcms_chanvec restricted_set_2g_short = {
0x00, 0x00, 0x00, 0x00}
};

-/* Channel 165 */
-static const struct brcms_chanvec restricted_chan_165 = {
- {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00}
-};
-
-/* Channels 36 - 48 & 149 - 165 */
-static const struct brcms_chanvec restricted_low_hi = {
- {0x00, 0x00, 0x00, 0x00, 0x10, 0x11, 0x01, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x20, 0x22, 0x22, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00}
-};
-
-/* Channels 12 - 14 */
-static const struct brcms_chanvec restricted_set_12_13_14 = {
- {0x00, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00}
-};
-
/* global memory to provide working buffer for expanded locale */

-static const struct brcms_chanvec *g_table_radar_set[] = {
- &chanvec_none,
- &radar_set1
-};
-
static const struct brcms_chanvec *g_table_restricted_chan[] = {
&chanvec_none, /* restricted_set_none */
&restricted_set_2g_short,
- &restricted_chan_165,
- &chanvec_all_5G,
- &restricted_set_japan_legacy,
- &chanvec_all_2G, /* restricted_set_11d_2G */
- &chanvec_all_5G, /* restricted_set_11d_5G */
- &restricted_low_hi,
- &restricted_set_12_13_14
};

static const struct brcms_chanvec locale_2g_01_11 = {
@@ -445,11 +353,9 @@ static void brcms_c_locale_get_channels(const struct locale_info *locale,
*/
static const struct locale_info locale_i = { /* locale i. channel 1 - 13 */
LOCALE_CHAN_01_11 | LOCALE_CHAN_12_13,
- LOCALE_RADAR_SET_NONE,
LOCALE_RESTRICTED_SET_2G_SHORT,
{QDB(19), QDB(19), QDB(19),
QDB(19), QDB(19), QDB(19)},
- {20, 20, 20, 0},
BRCMS_EIRP
};

@@ -459,10 +365,8 @@ static const struct locale_info locale_i = { /* locale i. channel 1 - 13 */
static const struct locale_info locale_11 = {
/* locale 11. channel 36 - 48, 52 - 64, 100 - 140, 149 - 165 */
LOCALE_CHAN_36_64 | LOCALE_CHAN_100_140 | LOCALE_CHAN_149_165,
- LOCALE_RADAR_SET_1,
LOCALE_RESTRICTED_NONE,
{QDB(21), QDB(21), QDB(21), QDB(21), QDB(21)},
- {23, 23, 23, 30, 30},
BRCMS_EIRP | BRCMS_DFS_EU
};

@@ -512,83 +416,6 @@ static const struct {
"X2", LOCALES(i, 11, bn, 11n)}, /* Worldwide RoW 2 */
};

-#ifdef SUPPORT_40MHZ
-/* 20MHz channel info for 40MHz pairing support */
-struct chan20_info {
- u8 sb;
- u8 adj_sbs;
-};
-
-/* indicates adjacent channels that are allowed for a 40 Mhz channel and
- * those that permitted by the HT
- */
-struct chan20_info chan20_info[] = {
- /* 11b/11g */
-/* 0 */ {1, (CH_UPPER_SB | CH_EWA_VALID)},
-/* 1 */ {2, (CH_UPPER_SB | CH_EWA_VALID)},
-/* 2 */ {3, (CH_UPPER_SB | CH_EWA_VALID)},
-/* 3 */ {4, (CH_UPPER_SB | CH_EWA_VALID)},
-/* 4 */ {5, (CH_UPPER_SB | CH_LOWER_SB | CH_EWA_VALID)},
-/* 5 */ {6, (CH_UPPER_SB | CH_LOWER_SB | CH_EWA_VALID)},
-/* 6 */ {7, (CH_UPPER_SB | CH_LOWER_SB | CH_EWA_VALID)},
-/* 7 */ {8, (CH_UPPER_SB | CH_LOWER_SB | CH_EWA_VALID)},
-/* 8 */ {9, (CH_UPPER_SB | CH_LOWER_SB | CH_EWA_VALID)},
-/* 9 */ {10, (CH_LOWER_SB | CH_EWA_VALID)},
-/* 10 */ {11, (CH_LOWER_SB | CH_EWA_VALID)},
-/* 11 */ {12, (CH_LOWER_SB)},
-/* 12 */ {13, (CH_LOWER_SB)},
-/* 13 */ {14, (CH_LOWER_SB)},
-
-/* 11a japan high */
-/* 14 */ {34, (CH_UPPER_SB)},
-/* 15 */ {38, (CH_LOWER_SB)},
-/* 16 */ {42, (CH_LOWER_SB)},
-/* 17 */ {46, (CH_LOWER_SB)},
-
-/* 11a usa low */
-/* 18 */ {36, (CH_UPPER_SB | CH_EWA_VALID)},
-/* 19 */ {40, (CH_LOWER_SB | CH_EWA_VALID)},
-/* 20 */ {44, (CH_UPPER_SB | CH_EWA_VALID)},
-/* 21 */ {48, (CH_LOWER_SB | CH_EWA_VALID)},
-/* 22 */ {52, (CH_UPPER_SB | CH_EWA_VALID)},
-/* 23 */ {56, (CH_LOWER_SB | CH_EWA_VALID)},
-/* 24 */ {60, (CH_UPPER_SB | CH_EWA_VALID)},
-/* 25 */ {64, (CH_LOWER_SB | CH_EWA_VALID)},
-
-/* 11a Europe */
-/* 26 */ {100, (CH_UPPER_SB | CH_EWA_VALID)},
-/* 27 */ {104, (CH_LOWER_SB | CH_EWA_VALID)},
-/* 28 */ {108, (CH_UPPER_SB | CH_EWA_VALID)},
-/* 29 */ {112, (CH_LOWER_SB | CH_EWA_VALID)},
-/* 30 */ {116, (CH_UPPER_SB | CH_EWA_VALID)},
-/* 31 */ {120, (CH_LOWER_SB | CH_EWA_VALID)},
-/* 32 */ {124, (CH_UPPER_SB | CH_EWA_VALID)},
-/* 33 */ {128, (CH_LOWER_SB | CH_EWA_VALID)},
-/* 34 */ {132, (CH_UPPER_SB | CH_EWA_VALID)},
-/* 35 */ {136, (CH_LOWER_SB | CH_EWA_VALID)},
-/* 36 */ {140, (CH_LOWER_SB)},
-
-/* 11a usa high, ref5 only */
-/* The 0x80 bit in pdiv means these are REF5, other entries are REF20 */
-/* 37 */ {149, (CH_UPPER_SB | CH_EWA_VALID)},
-/* 38 */ {153, (CH_LOWER_SB | CH_EWA_VALID)},
-/* 39 */ {157, (CH_UPPER_SB | CH_EWA_VALID)},
-/* 40 */ {161, (CH_LOWER_SB | CH_EWA_VALID)},
-/* 41 */ {165, (CH_LOWER_SB)},
-
-/* 11a japan */
-/* 42 */ {184, (CH_UPPER_SB)},
-/* 43 */ {188, (CH_LOWER_SB)},
-/* 44 */ {192, (CH_UPPER_SB)},
-/* 45 */ {196, (CH_LOWER_SB)},
-/* 46 */ {200, (CH_UPPER_SB)},
-/* 47 */ {204, (CH_LOWER_SB)},
-/* 48 */ {208, (CH_UPPER_SB)},
-/* 49 */ {212, (CH_LOWER_SB)},
-/* 50 */ {216, (CH_LOWER_SB)}
-};
-#endif /* SUPPORT_40MHZ */
-
static const struct locale_info *brcms_c_get_locale_2g(u8 locale_idx)
{
if (locale_idx >= ARRAY_SIZE(g_locale_2g_table))
@@ -621,13 +448,6 @@ static const struct locale_mimo_info *brcms_c_get_mimo_5g(u8 locale_idx)
return g_mimo_5g_table[locale_idx];
}

-static int
-brcms_c_country_aggregate_map(struct brcms_cm_info *wlc_cm, const char *ccode,
- char *mapped_ccode, uint *mapped_regrev)
-{
- return false;
-}
-
/*
* Indicates whether the country provided is valid to pass
* to cfg80211 or not.
@@ -697,7 +517,6 @@ brcms_c_countrycode_map(struct brcms_cm_info *wlc_cm, const char *ccode,
const struct country_info *country;
uint srom_regrev = wlc_cm->srom_regrev;
const char *srom_ccode = wlc_cm->srom_ccode;
- int mapped;

/* check for currently supported ccode size */
if (strlen(ccode) > (BRCM_CNTRY_BUF_SZ - 1)) {
@@ -716,12 +535,7 @@ brcms_c_countrycode_map(struct brcms_cm_info *wlc_cm, const char *ccode,
*/
if (!strcmp(srom_ccode, ccode)) {
*mapped_regrev = srom_regrev;
- mapped = 0;
wiphy_err(wlc->wiphy, "srom_code == ccode %s\n", __func__);
- } else {
- mapped =
- brcms_c_country_aggregate_map(wlc_cm, ccode, mapped_ccode,
- mapped_regrev);
}

/* find the matching built-in country definition */
@@ -979,8 +793,6 @@ brcms_c_channels_init(struct brcms_cm_info *wlc_cm,

wlc_cm->bandstate[band->bandunit].restricted_channels =
g_table_restricted_chan[li->restricted_channels];
- wlc_cm->bandstate[band->bandunit].radar_channels =
- g_table_radar_set[li->radar_channels];

/*
* set the channel availability, masking out the channels
@@ -1015,17 +827,11 @@ brcms_c_set_country_common(struct brcms_cm_info *wlc_cm,
{
const struct locale_info *locale;
struct brcms_c_info *wlc = wlc_cm->wlc;
- char prev_country_abbrev[BRCM_CNTRY_BUF_SZ];

/* save current country state */
wlc_cm->country = country;

- memset(&prev_country_abbrev, 0, BRCM_CNTRY_BUF_SZ);
- strncpy(prev_country_abbrev, wlc_cm->country_abbrev,
- BRCM_CNTRY_BUF_SZ - 1);
-
strncpy(wlc_cm->country_abbrev, country_abbrev, BRCM_CNTRY_BUF_SZ - 1);
- strncpy(wlc_cm->ccode, ccode, BRCM_CNTRY_BUF_SZ - 1);
wlc_cm->regrev = regrev;

if ((wlc->pub->_n_enab & SUPPORT_11N) !=
@@ -1091,16 +897,12 @@ brcms_c_set_countrycode_rev(struct brcms_cm_info *wlc_cm,
static int
brcms_c_set_countrycode(struct brcms_cm_info *wlc_cm, const char *ccode)
{
- char country_abbrev[BRCM_CNTRY_BUF_SZ];
- strncpy(country_abbrev, ccode, BRCM_CNTRY_BUF_SZ);
- return brcms_c_set_countrycode_rev(wlc_cm, country_abbrev, ccode, -1);
+ return brcms_c_set_countrycode_rev(wlc_cm, ccode, ccode, -1);
}

struct brcms_cm_info *brcms_c_channel_mgr_attach(struct brcms_c_info *wlc)
{
struct brcms_cm_info *wlc_cm;
- char country_abbrev[BRCM_CNTRY_BUF_SZ];
- const struct country_info *country;
struct brcms_pub *pub = wlc->pub;
char *ccode;

@@ -1118,21 +920,14 @@ struct brcms_cm_info *brcms_c_channel_mgr_attach(struct brcms_c_info *wlc)
if (ccode && brcms_c_country_valid(ccode))
strncpy(wlc->pub->srom_ccode, ccode, BRCM_CNTRY_BUF_SZ - 1);

- /*
- * internal country information which must match
- * regulatory constraints in firmware
- */
- memset(country_abbrev, 0, BRCM_CNTRY_BUF_SZ);
- strncpy(country_abbrev, "X2", sizeof(country_abbrev) - 1);
- country = brcms_c_country_lookup(wlc, country_abbrev);
-
/* save default country for exiting 11d regulatory mode */
- strncpy(wlc->country_default, country_abbrev, BRCM_CNTRY_BUF_SZ - 1);
+ strncpy(wlc->country_default, "X2", BRCM_CNTRY_BUF_SZ - 1);

/* initialize autocountry_default to driver default */
- strncpy(wlc->autocountry_default, "X2", BRCM_CNTRY_BUF_SZ - 1);
+ strncpy(wlc->autocountry_default, wlc->country_default,
+ BRCM_CNTRY_BUF_SZ - 1);

- brcms_c_set_countrycode(wlc_cm, country_abbrev);
+ brcms_c_set_countrycode(wlc_cm, wlc->country_default);

return wlc_cm;
}
@@ -1450,45 +1245,6 @@ brcms_c_valid_chanspec_ext(struct brcms_cm_info *wlc_cm, u16 chspec,
return brcms_c_valid_channel20(wlc_cm->wlc->cmi,
channel);
}
-#ifdef SUPPORT_40MHZ
- /*
- * We know we are now checking a 40MHZ channel, so we should
- * only be here for NPHYS
- */
- if (BRCMS_ISNPHY(wlc->band) || BRCMS_ISSSLPNPHY(wlc->band)) {
- u8 upper_sideband = 0, idx;
- u8 num_ch20_entries =
- sizeof(chan20_info) / sizeof(struct chan20_info);
-
- if (!VALID_40CHANSPEC_IN_BAND(wlc, chspec_bandunit(chspec)))
- return false;
-
- if (dualband) {
- if (!brcms_c_valid_channel20_db(wlc->cmi,
- lower_20_sb(channel)) ||
- !brcms_c_valid_channel20_db(wlc->cmi,
- upper_20_sb(channel)))
- return false;
- } else {
- if (!brcms_c_valid_channel20(wlc->cmi,
- lower_20_sb(channel)) ||
- !brcms_c_valid_channel20(wlc->cmi,
- upper_20_sb(channel)))
- return false;
- }
-
- /* find the lower sideband info in the sideband array */
- for (idx = 0; idx < num_ch20_entries; idx++) {
- if (chan20_info[idx].sb == lower_20_sb(channel))
- upper_sideband = chan20_info[idx].adj_sbs;
- }
- /* check that the lower sideband allows an upper sideband */
- if ((upper_sideband & (CH_UPPER_SB | CH_EWA_VALID)) ==
- (CH_UPPER_SB | CH_EWA_VALID))
- return true;
- return false;
- }
-#endif /* 40 MHZ */

return false;
}
--
1.7.9.5


2012-04-19 19:46:48

by Seth Forshee

[permalink] [raw]
Subject: Re: [RFC PATCH 0/8] brcm80211: smac: rework regulatory support

On Thu, Apr 19, 2012 at 09:31:02PM +0200, Arend van Spriel wrote:
> On 04/16/2012 10:17 PM, Seth Forshee wrote:
> >Hi Arnd,
> >
> >Here's the latest update to the brcmsmac regulatory rework that I've
> >been working on. I've broken it up into a series of smaller patches,
> >cleaned things up, and finished what changes I can with the information
> >available to me.
> >
>
> Hi Seth,
>
> Just to indicate what we are doing with regard to your patches. I
> organized a review internally for these patches. Waiting for one
> more to sent back comments. Just pinged him today. So end of this
> week I can probably sent you the collected comments.

Wonderful, thanks a lot. I'm looking forward to receiving feedback.

Seth


2012-04-16 20:18:04

by Seth Forshee

[permalink] [raw]
Subject: [RFC PATCH 8/8] brcm80211: smac: use current regulatory domain when checking whether OFDM is allowed

The brcmsmac internal regulatory data is being used to determine whether
OFDM should be allowed, and this is only done once during
initialization. To be effective this needs to be checked against
mac80211's regulatory rules for the current channel.

Signed-off-by: Seth Forshee <[email protected]>
---
drivers/net/wireless/brcm80211/brcmsmac/channel.c | 132 +++------------------
drivers/net/wireless/brcm80211/brcmsmac/channel.h | 3 -
drivers/net/wireless/brcm80211/brcmsmac/main.c | 6 +-
3 files changed, 15 insertions(+), 126 deletions(-)

diff --git a/drivers/net/wireless/brcm80211/brcmsmac/channel.c b/drivers/net/wireless/brcm80211/brcmsmac/channel.c
index a31a3de..814410e 100644
--- a/drivers/net/wireless/brcm80211/brcmsmac/channel.c
+++ b/drivers/net/wireless/brcm80211/brcmsmac/channel.c
@@ -30,13 +30,9 @@
/* QDB() macro takes a dB value and converts to a quarter dB value */
#define QDB(n) ((n) * BRCMS_TXPWR_DB_FACTOR)

-#define LOCALE_2G_IDX_i 0
-#define LOCALE_5G_IDX_11 0
#define LOCALE_MIMO_IDX_bn 0
#define LOCALE_MIMO_IDX_11n 0

-/* max of BAND_5G_PWR_LVLS and 6 for 2.4 GHz */
-#define BRCMS_MAXPWR_TBL_SIZE 6
/* max of BAND_5G_PWR_LVLS and 14 for 2.4 GHz */
#define BRCMS_MAXPWR_MIMO_TBL_SIZE 14

@@ -51,12 +47,8 @@

#define LC(id) LOCALE_MIMO_IDX_ ## id

-#define LC_2G(id) LOCALE_2G_IDX_ ## id
-
-#define LC_5G(id) LOCALE_5G_IDX_ ## id
-
-#define LOCALES(band2, band5, mimo2, mimo5) \
- {LC_2G(band2), LC_5G(band5), LC(mimo2), LC(mimo5)}
+#define LOCALES(mimo2, mimo5) \
+ {LC(mimo2), LC(mimo5)}

/* macro to get 5 GHz channel group index for tx power */
#define CHANNEL_POWER_IDX_5G(c) (((c) < 52) ? 0 : \
@@ -101,11 +93,6 @@ static const struct ieee80211_regdomain brcms_regdom_x2 = {
}
};

-struct brcms_cm_band {
- /* struct locale_info flags */
- u8 locale_flags;
-};
-
/* locale per-channel tx power limits for MIMO frames
* maxpwr arrays are index by channel for 2.4 GHz limits, and
* by sub-band for 5 GHz limits using CHANNEL_POWER_IDX_5G(channel)
@@ -115,13 +102,10 @@ struct locale_mimo_info {
s8 maxpwr20[BRCMS_MAXPWR_MIMO_TBL_SIZE];
/* tx 40 MHz power limits, qdBm units */
s8 maxpwr40[BRCMS_MAXPWR_MIMO_TBL_SIZE];
- u8 flags;
};

/* Country names and abbreviations with locale defined from ISO 3166 */
struct country_info {
- const u8 locale_2G; /* 2.4G band locale */
- const u8 locale_5G; /* 5G band locale */
const u8 locale_mimo_2G; /* 2.4G mimo info */
const u8 locale_mimo_5G; /* 5G mimo info */
};
@@ -135,35 +119,6 @@ struct brcms_cm_info {
struct brcms_pub *pub;
struct brcms_c_info *wlc;
const struct brcms_regd *world_regd;
- /* per-band state (one per phy/radio) */
- struct brcms_cm_band bandstate[MAXBANDS];
-};
-
-/* locale channel and power info. */
-struct locale_info {
- u8 flags;
-};
-
-/*
- * Locale Definitions - 2.4 GHz
- */
-static const struct locale_info locale_i = { /* locale i. channel 1 - 13 */
- BRCMS_EIRP
-};
-
-/*
- * Locale Definitions - 5 GHz
- */
-static const struct locale_info locale_11 = {
- BRCMS_EIRP | BRCMS_DFS_EU
-};
-
-static const struct locale_info *g_locale_2g_table[] = {
- &locale_i
-};
-
-static const struct locale_info *g_locale_5g_table[] = {
- &locale_11
};

/*
@@ -176,7 +131,6 @@ static const struct locale_mimo_info locale_bn = {
{0, 0, QDB(13), QDB(13), QDB(13),
QDB(13), QDB(13), QDB(13), QDB(13), QDB(13),
QDB(13), 0, 0},
- 0
};

static const struct locale_mimo_info *g_mimo_2g_table[] = {
@@ -189,7 +143,6 @@ static const struct locale_mimo_info *g_mimo_2g_table[] = {
static const struct locale_mimo_info locale_11n = {
{ /* 12.5 dBm */ 50, 50, 50, QDB(15), QDB(15)},
{QDB(14), QDB(15), QDB(15), QDB(15), QDB(15)},
- 0
};

static const struct locale_mimo_info *g_mimo_5g_table[] = {
@@ -199,27 +152,11 @@ static const struct locale_mimo_info *g_mimo_5g_table[] = {
static const struct brcms_regd cntry_locales[] = {
/* Worldwide Row 2, must always be at index 0 */
{
- .country = LOCALES(i, 11, bn, 11n),
+ .country = LOCALES(bn, 11n),
.regdomain = &brcms_regdom_x2,
},
};

-static const struct locale_info *brcms_c_get_locale_2g(u8 locale_idx)
-{
- if (locale_idx >= ARRAY_SIZE(g_locale_2g_table))
- return NULL; /* error condition */
-
- return g_locale_2g_table[locale_idx];
-}
-
-static const struct locale_info *brcms_c_get_locale_5g(u8 locale_idx)
-{
- if (locale_idx >= ARRAY_SIZE(g_locale_5g_table))
- return NULL; /* error condition */
-
- return g_locale_5g_table[locale_idx];
-}
-
static const struct locale_mimo_info *brcms_c_get_mimo_2g(u8 locale_idx)
{
if (locale_idx >= ARRAY_SIZE(g_mimo_2g_table))
@@ -372,36 +309,6 @@ brcms_c_channel_min_txpower_limits_with_local_constraint(

}

-static int
-brcms_c_channels_init(struct brcms_cm_info *wlc_cm,
- const struct country_info *country)
-{
- struct brcms_c_info *wlc = wlc_cm->wlc;
- uint i;
- struct brcms_band *band;
- const struct locale_info *li;
- const struct locale_mimo_info *li_mimo;
-
- band = wlc->band;
- for (i = 0; i < wlc->pub->_nbands;
- i++, band = wlc->bandstate[OTHERBANDUNIT(wlc)]) {
-
- li = (band->bandtype == BRCM_BAND_5G) ?
- brcms_c_get_locale_5g(country->locale_5G) :
- brcms_c_get_locale_2g(country->locale_2G);
- wlc_cm->bandstate[band->bandunit].locale_flags = li->flags;
- li_mimo = (band->bandtype == BRCM_BAND_5G) ?
- brcms_c_get_mimo_5g(country->locale_mimo_5G) :
- brcms_c_get_mimo_2g(country->locale_mimo_2G);
-
- /* merge the mimo non-mimo locale flags */
- wlc_cm->bandstate[band->bandunit].locale_flags |=
- li_mimo->flags;
- }
-
- return 0;
-}
-
/*
* set the driver's current country and regulatory information
* using a country code as the source. Look up built in country
@@ -411,8 +318,6 @@ static void
brcms_c_set_country(struct brcms_cm_info *wlc_cm,
const struct brcms_regd *regd)
{
- const struct country_info *country = &regd->country;
- const struct locale_info *locale;
struct brcms_c_info *wlc = wlc_cm->wlc;

if ((wlc->pub->_n_enab & SUPPORT_11N) !=
@@ -421,14 +326,8 @@ brcms_c_set_country(struct brcms_cm_info *wlc_cm,

brcms_c_stf_ss_update(wlc, wlc->bandstate[BAND_2G_INDEX]);
brcms_c_stf_ss_update(wlc, wlc->bandstate[BAND_5G_INDEX]);
- /* set or restore gmode as required by regulatory */
- locale = brcms_c_get_locale_2g(country->locale_2G);
- if (locale && (locale->flags & BRCMS_NO_OFDM))
- brcms_c_set_gmode(wlc, GMODE_LEGACY_B, false);
- else
- brcms_c_set_gmode(wlc, wlc->protection->gmode_user, false);

- brcms_c_channels_init(wlc_cm, country);
+ brcms_c_set_gmode(wlc, wlc->protection->gmode_user, false);

return;
}
@@ -482,20 +381,15 @@ void brcms_c_channel_mgr_detach(struct brcms_cm_info *wlc_cm)
kfree(wlc_cm);
}

-u8
-brcms_c_channel_locale_flags_in_band(struct brcms_cm_info *wlc_cm,
- uint bandunit)
-{
- return wlc_cm->bandstate[bandunit].locale_flags;
-}
-
void
brcms_c_channel_set_chanspec(struct brcms_cm_info *wlc_cm, u16 chanspec,
u8 local_constraint_qdbm)
{
struct brcms_c_info *wlc = wlc_cm->wlc;
struct ieee80211_channel *ch = wlc->pub->ieee_hw->conf.channel;
+ const struct ieee80211_reg_rule *reg_rule;
struct txpwr_limits txpwr;
+ int ret;

brcms_c_channel_reg_limits(wlc_cm, chanspec, &txpwr);

@@ -503,6 +397,13 @@ brcms_c_channel_set_chanspec(struct brcms_cm_info *wlc_cm, u16 chanspec,
wlc_cm, &txpwr, local_constraint_qdbm
);

+ /* set or restore gmode as required by regulatory */
+ ret = freq_reg_info(wlc->wiphy, ch->center_freq, 0, &reg_rule);
+ if (ret && (reg_rule->flags & NL80211_RRF_NO_OFDM))
+ brcms_c_set_gmode(wlc, GMODE_LEGACY_B, false);
+ else
+ brcms_c_set_gmode(wlc, wlc->protection->gmode_user, false);
+
brcms_b_set_chanspec(wlc->hw, chanspec,
!!(ch->flags & IEEE80211_CHAN_PASSIVE_SCAN),
&txpwr);
@@ -520,7 +421,6 @@ brcms_c_channel_reg_limits(struct brcms_cm_info *wlc_cm, u16 chanspec,
int delta;
const struct country_info *country;
struct brcms_band *band;
- const struct locale_info *li;
int conducted_max = BRCMS_TXPWR_MAX;
const struct locale_mimo_info *li_mimo;
int maxpwr20, maxpwr40;
@@ -536,17 +436,13 @@ brcms_c_channel_reg_limits(struct brcms_cm_info *wlc_cm, u16 chanspec,

chan = CHSPEC_CHANNEL(chanspec);
band = wlc->bandstate[chspec_bandunit(chanspec)];
- li = (band->bandtype == BRCM_BAND_5G) ?
- brcms_c_get_locale_5g(country->locale_5G) :
- brcms_c_get_locale_2g(country->locale_2G);
-
li_mimo = (band->bandtype == BRCM_BAND_5G) ?
brcms_c_get_mimo_5g(country->locale_mimo_5G) :
brcms_c_get_mimo_2g(country->locale_mimo_2G);

delta = band->antgain;

- if (li == &locale_i)
+ if (band->bandtype == BRCM_BAND_2G)
conducted_max = QDB(22);

maxpwr = QDB(ch->max_power) - delta;
diff --git a/drivers/net/wireless/brcm80211/brcmsmac/channel.h b/drivers/net/wireless/brcm80211/brcmsmac/channel.h
index dbe60ef..0d1da72 100644
--- a/drivers/net/wireless/brcm80211/brcmsmac/channel.h
+++ b/drivers/net/wireless/brcm80211/brcmsmac/channel.h
@@ -37,9 +37,6 @@ brcms_c_channel_mgr_attach(struct brcms_c_info *wlc);

extern void brcms_c_channel_mgr_detach(struct brcms_cm_info *wlc_cm);

-extern u8 brcms_c_channel_locale_flags_in_band(struct brcms_cm_info *wlc_cm,
- uint bandunit);
-
extern bool brcms_c_valid_chanspec_db(struct brcms_cm_info *wlc_cm,
u16 chspec);

diff --git a/drivers/net/wireless/brcm80211/brcmsmac/main.c b/drivers/net/wireless/brcm80211/brcmsmac/main.c
index 41d51cb..c949855 100644
--- a/drivers/net/wireless/brcm80211/brcmsmac/main.c
+++ b/drivers/net/wireless/brcm80211/brcmsmac/main.c
@@ -18,6 +18,7 @@

#include <linux/pci_ids.h>
#include <linux/if_ether.h>
+#include <net/cfg80211.h>
#include <net/mac80211.h>
#include <brcm_hw_ids.h>
#include <aiutils.h>
@@ -5409,11 +5410,6 @@ int brcms_c_set_gmode(struct brcms_c_info *wlc, u8 gmode, bool config)
else
return -EINVAL;

- /* Legacy or bust when no OFDM is supported by regulatory */
- if ((brcms_c_channel_locale_flags_in_band(wlc->cmi, band->bandunit) &
- BRCMS_NO_OFDM) && (gmode != GMODE_LEGACY_B))
- return -EINVAL;
-
/* update configuration value */
if (config)
brcms_c_protection_upd(wlc, BRCMS_PROT_G_USER, gmode);
--
1.7.9.5


2012-04-16 20:42:16

by Arend van Spriel

[permalink] [raw]
Subject: Re: [RFC PATCH 0/8] brcm80211: smac: rework regulatory support

On 04/16/2012 10:17 PM, Seth Forshee wrote:
> Hi Arnd,
>
> Here's the latest update to the brcmsmac regulatory rework that I've
> been working on. I've broken it up into a series of smaller patches,
> cleaned things up, and finished what changes I can with the information
> available to me.

I will go through the individual patches and comment on them. This code
could use some cleanup so it is appreciated.

> I've attempted to maintain the same high-level behavior that the
> brcmsmac internal regulatory support currently enforces. I find a couple
> of these to be questionable however, those being: the setting of the
> radio disable state based on whether or not there are any channels
> allowed by regulatory, and the handling of enabling/disabling OFDM.
> Perhaps you can comment on whether or not these actions are needed.

Regarding questionable things, you mean the transmit mute or is there
another radio disable that I have not found yet. I only recall that
channel 14 (JP only) does not allow OFDM so it may be to accommodate
that. It may not be explicitly needed as mac80211 provides the rate
and/or modulation to use for the transmit frame.

> All use of the internal regulatory data has been eliminated except for
> the use of the MIMO power limits for filling out the txpwr_limits data.
> I'm anticipating that you'll provide information on how this needs to be
> handled. Otherwise I think these patches are very nearly complete, so
> please let me know if you see anything that needs to be changed.

I asked for this internally, but I do not recall getting an answer. I
will make another attempt.

> So far these changes are testing well on a MacBook Air 4,1 with BCM43224
> wireless. I'm now able to see and associate with my AP on channel 52,
> which was not possible previously.

I will try to organize some regulatory testing over here with your patches.

Gr. AvS


2012-04-16 20:18:04

by Seth Forshee

[permalink] [raw]
Subject: [RFC PATCH 6/8] brcm80211: smac: use mac80211 channel data for tx power limits

Currently the limits from the internal X2 domain are used, regardless
of what regulatory rules are in effect. Instead use the power limits set
by the higher-level regulatory support.

The rules for the MIMO power limits are still always derived from the
world domain. Guidance from Broadcom is needed on how these limits
should be determined for other regulatory domains.

Signed-off-by: Seth Forshee <[email protected]>
---
drivers/net/wireless/brcm80211/brcmsmac/channel.c | 73 ++++-----------------
1 file changed, 14 insertions(+), 59 deletions(-)

diff --git a/drivers/net/wireless/brcm80211/brcmsmac/channel.c b/drivers/net/wireless/brcm80211/brcmsmac/channel.c
index 590e8c1..cda40c8 100644
--- a/drivers/net/wireless/brcm80211/brcmsmac/channel.c
+++ b/drivers/net/wireless/brcm80211/brcmsmac/channel.c
@@ -74,15 +74,6 @@
/* max of BAND_5G_PWR_LVLS and 14 for 2.4 GHz */
#define BRCMS_MAXPWR_MIMO_TBL_SIZE 14

-/* power level in group of 2.4GHz band channels:
- * maxpwr[0] - CCK channels [1]
- * maxpwr[1] - CCK channels [2-10]
- * maxpwr[2] - CCK channels [11-14]
- * maxpwr[3] - OFDM channels [1]
- * maxpwr[4] - OFDM channels [2-10]
- * maxpwr[5] - OFDM channels [11-14]
- */
-
/* maxpwr mapping to 5GHz band channels:
* maxpwr[0] - channels [34-48]
* maxpwr[1] - channels [52-60]
@@ -101,10 +92,6 @@
#define LOCALES(band2, band5, mimo2, mimo5) \
{LC_2G(band2), LC_5G(band5), LC(mimo2), LC(mimo5)}

-/* macro to get 2.4 GHz channel group index for tx power */
-#define CHANNEL_POWER_IDX_2G_CCK(c) (((c) < 2) ? 0 : (((c) < 11) ? 1 : 2))
-#define CHANNEL_POWER_IDX_2G_OFDM(c) (((c) < 2) ? 3 : (((c) < 11) ? 4 : 5))
-
/* macro to get 5 GHz channel group index for tx power */
#define CHANNEL_POWER_IDX_5G(c) (((c) < 52) ? 0 : \
(((c) < 62) ? 1 : \
@@ -198,8 +185,6 @@ struct locale_info {
u32 valid_channels;
/* List of channels used only if APs are detected */
u8 restricted_channels;
- /* Max tx pwr in qdBm for each sub-band */
- s8 maxpwr[BRCMS_MAXPWR_TBL_SIZE];
u8 flags;
};

@@ -395,8 +380,6 @@ static void brcms_c_locale_get_channels(const struct locale_info *locale,
static const struct locale_info locale_i = { /* locale i. channel 1 - 13 */
LOCALE_CHAN_01_11 | LOCALE_CHAN_12_13,
LOCALE_RESTRICTED_SET_2G_SHORT,
- {QDB(19), QDB(19), QDB(19),
- QDB(19), QDB(19), QDB(19)},
BRCMS_EIRP
};

@@ -407,7 +390,6 @@ static const struct locale_info locale_11 = {
/* locale 11. channel 36 - 48, 52 - 64, 100 - 140, 149 - 165 */
LOCALE_CHAN_36_64 | LOCALE_CHAN_100_140 | LOCALE_CHAN_149_165,
LOCALE_RESTRICTED_NONE,
- {QDB(21), QDB(21), QDB(21), QDB(21), QDB(21)},
BRCMS_EIRP | BRCMS_DFS_EU
};

@@ -852,6 +834,7 @@ brcms_c_channel_reg_limits(struct brcms_cm_info *wlc_cm, u16 chanspec,
struct txpwr_limits *txpwr)
{
struct brcms_c_info *wlc = wlc_cm->wlc;
+ struct ieee80211_channel *ch = wlc->pub->ieee_hw->conf.channel;
uint i;
uint chan;
int maxpwr;
@@ -860,7 +843,6 @@ brcms_c_channel_reg_limits(struct brcms_cm_info *wlc_cm, u16 chanspec,
struct brcms_band *band;
const struct locale_info *li;
int conducted_max = BRCMS_TXPWR_MAX;
- int conducted_ofdm_max = BRCMS_TXPWR_MAX;
const struct locale_mimo_info *li_mimo;
int maxpwr20, maxpwr40;
int maxpwr_idx;
@@ -868,6 +850,9 @@ brcms_c_channel_reg_limits(struct brcms_cm_info *wlc_cm, u16 chanspec,

memset(txpwr, 0, sizeof(struct txpwr_limits));

+ if (WARN_ON(!ch))
+ return;
+
country = &wlc_cm->world_regd->country;

chan = CHSPEC_CHANNEL(chanspec);
@@ -880,49 +865,24 @@ brcms_c_channel_reg_limits(struct brcms_cm_info *wlc_cm, u16 chanspec,
brcms_c_get_mimo_5g(country->locale_mimo_5G) :
brcms_c_get_mimo_2g(country->locale_mimo_2G);

- if (li->flags & BRCMS_EIRP) {
- delta = band->antgain;
- } else {
- delta = 0;
- if (band->antgain > QDB(6))
- delta = band->antgain - QDB(6); /* Excess over 6 dB */
- }
+ delta = band->antgain;

- if (li == &locale_i) {
+ if (li == &locale_i)
conducted_max = QDB(22);
- conducted_ofdm_max = QDB(22);
- }
+
+ maxpwr = QDB(ch->max_power) - delta;
+ maxpwr = max(maxpwr, 0);
+ maxpwr = min(maxpwr, conducted_max);

/* CCK txpwr limits for 2.4G band */
if (band->bandtype == BRCM_BAND_2G) {
- maxpwr = li->maxpwr[CHANNEL_POWER_IDX_2G_CCK(chan)];
-
- maxpwr = maxpwr - delta;
- maxpwr = max(maxpwr, 0);
- maxpwr = min(maxpwr, conducted_max);
-
for (i = 0; i < BRCMS_NUM_RATES_CCK; i++)
txpwr->cck[i] = (u8) maxpwr;
}

- /* OFDM txpwr limits for 2.4G or 5G bands */
- if (band->bandtype == BRCM_BAND_2G)
- maxpwr = li->maxpwr[CHANNEL_POWER_IDX_2G_OFDM(chan)];
- else
- maxpwr = li->maxpwr[CHANNEL_POWER_IDX_5G(chan)];
-
- maxpwr = maxpwr - delta;
- maxpwr = max(maxpwr, 0);
- maxpwr = min(maxpwr, conducted_ofdm_max);
-
- /* Keep OFDM lmit below CCK limit */
- if (band->bandtype == BRCM_BAND_2G)
- maxpwr = min_t(int, maxpwr, txpwr->cck[0]);
-
- for (i = 0; i < BRCMS_NUM_RATES_OFDM; i++)
+ for (i = 0; i < BRCMS_NUM_RATES_OFDM; i++) {
txpwr->ofdm[i] = (u8) maxpwr;

- for (i = 0; i < BRCMS_NUM_RATES_OFDM; i++) {
/*
* OFDM 40 MHz SISO has the same power as the corresponding
* MCS0-7 rate unless overriden by the locale specific code.
@@ -937,14 +897,9 @@ brcms_c_channel_reg_limits(struct brcms_cm_info *wlc_cm, u16 chanspec,
txpwr->ofdm_40_cdd[i] = 0;
}

- /* MIMO/HT specific limits */
- if (li_mimo->flags & BRCMS_EIRP) {
- delta = band->antgain;
- } else {
- delta = 0;
- if (band->antgain > QDB(6))
- delta = band->antgain - QDB(6); /* Excess over 6 dB */
- }
+ delta = 0;
+ if (band->antgain > QDB(6))
+ delta = band->antgain - QDB(6); /* Excess over 6 dB */

if (band->bandtype == BRCM_BAND_2G)
maxpwr_idx = (chan - 1);
--
1.7.9.5


2012-04-16 20:17:48

by Seth Forshee

[permalink] [raw]
Subject: [RFC PATCH 1/8] brcm80211: smac: don't set up tx power limits during initialization

This code is unnecessary, and in fact it's never executed because the
interface is never up when brcms_c_channels_commit() is called. Removing
it helps simplify the implementation of proper regulatory support.

Signed-off-by: Seth Forshee <[email protected]>
---
drivers/net/wireless/brcm80211/brcmsmac/channel.c | 8 --------
1 file changed, 8 deletions(-)

diff --git a/drivers/net/wireless/brcm80211/brcmsmac/channel.c b/drivers/net/wireless/brcm80211/brcmsmac/channel.c
index 0efe88e..71fce2c 100644
--- a/drivers/net/wireless/brcm80211/brcmsmac/channel.c
+++ b/drivers/net/wireless/brcm80211/brcmsmac/channel.c
@@ -908,7 +908,6 @@ static void brcms_c_channels_commit(struct brcms_cm_info *wlc_cm)
{
struct brcms_c_info *wlc = wlc_cm->wlc;
uint chan;
- struct txpwr_limits txpwr;

/* search for the existence of any valid channel */
for (chan = 0; chan < MAXCHANNEL; chan++) {
@@ -949,13 +948,6 @@ static void brcms_c_channels_commit(struct brcms_cm_info *wlc_cm)
wlc_phy_chanspec_ch14_widefilter_set(wlc->band->pi,
brcms_c_japan(wlc) ? true :
false);
-
- if (wlc->pub->up && chan != INVCHANNEL) {
- brcms_c_channel_reg_limits(wlc_cm, wlc->chanspec, &txpwr);
- brcms_c_channel_min_txpower_limits_with_local_constraint(wlc_cm,
- &txpwr, BRCMS_TXPWR_MAX);
- wlc_phy_txpower_limit_set(wlc->band->pi, &txpwr, wlc->chanspec);
- }
}

static int
--
1.7.9.5


2012-04-19 19:31:10

by Arend van Spriel

[permalink] [raw]
Subject: Re: [RFC PATCH 0/8] brcm80211: smac: rework regulatory support

On 04/16/2012 10:17 PM, Seth Forshee wrote:
> Hi Arnd,
>
> Here's the latest update to the brcmsmac regulatory rework that I've
> been working on. I've broken it up into a series of smaller patches,
> cleaned things up, and finished what changes I can with the information
> available to me.
>

Hi Seth,

Just to indicate what we are doing with regard to your patches. I
organized a review internally for these patches. Waiting for one more to
sent back comments. Just pinged him today. So end of this week I can
probably sent you the collected comments.

Gr. AvS


2012-04-30 17:12:14

by Seth Forshee

[permalink] [raw]
Subject: Re: [RFC PATCH 0/8] brcm80211: smac: rework regulatory support

On Thu, Apr 19, 2012 at 09:31:02PM +0200, Arend van Spriel wrote:
> On 04/16/2012 10:17 PM, Seth Forshee wrote:
> >Hi Arnd,
> >
> >Here's the latest update to the brcmsmac regulatory rework that I've
> >been working on. I've broken it up into a series of smaller patches,
> >cleaned things up, and finished what changes I can with the information
> >available to me.
> >
>
> Hi Seth,
>
> Just to indicate what we are doing with regard to your patches. I
> organized a review internally for these patches. Waiting for one
> more to sent back comments. Just pinged him today. So end of this
> week I can probably sent you the collected comments.

Hi Arend,

Any feedback yet from your internal review/testing?

Thanks,
Seth

2012-04-16 20:17:55

by Seth Forshee

[permalink] [raw]
Subject: [RFC PATCH 4/8] brcm80211: smac: inform mac80211 of the X2 regulatory domain

brcmsmac implements enforcement of regulatory constraints internally,
using a Broadcom-specific world roaming domain named X2. Besides being
duplication of functionality, this also causes some channels to be
unnecessarily disabled, as mac80211 is unaware of the X2 domain and thus
applies the more restrictive default world domain.

This patch is the first step in making brcmsmac cooperate with
mac80211's regulatory support. X2 is registered as a custom domain with
mac80211, so that at least both implementations will be enforcing the
same set of constraints. The internal enforcement of rules is kept for
now; this will be converted over to relying on mac80211 regulatory
enforcement in later patches.

Signed-off-by: Seth Forshee <[email protected]>
---
drivers/net/wireless/brcm80211/brcmsmac/channel.c | 392 +++++++++++---------
drivers/net/wireless/brcm80211/brcmsmac/channel.h | 2 +
.../net/wireless/brcm80211/brcmsmac/mac80211_if.c | 2 +
3 files changed, 217 insertions(+), 179 deletions(-)

diff --git a/drivers/net/wireless/brcm80211/brcmsmac/channel.c b/drivers/net/wireless/brcm80211/brcmsmac/channel.c
index 1998c86..fd5b807 100644
--- a/drivers/net/wireless/brcm80211/brcmsmac/channel.c
+++ b/drivers/net/wireless/brcm80211/brcmsmac/channel.c
@@ -15,7 +15,9 @@
*/

#include <linux/types.h>
+#include <net/cfg80211.h>
#include <net/mac80211.h>
+#include <net/regulatory.h>

#include <defs.h>
#include "pub.h"
@@ -23,6 +25,7 @@
#include "main.h"
#include "stf.h"
#include "channel.h"
+#include "mac80211_if.h"

/* QDB() macro takes a dB value and converts to a quarter dB value */
#define QDB(n) ((n) * BRCMS_TXPWR_DB_FACTOR)
@@ -108,6 +111,43 @@
(((c) < 100) ? 2 : \
(((c) < 149) ? 3 : 4))))

+#define BRCM_2GHZ_2412_2462 REG_RULE(2412-10, 2462+10, 40, 0, 19, 0)
+#define BRCM_2GHZ_2467_2472 REG_RULE(2467-10, 2472+10, 20, 0, 19, \
+ NL80211_RRF_PASSIVE_SCAN | \
+ NL80211_RRF_NO_IBSS)
+#define BRCM_2GHZ_2484 REG_RULE(2484-10, 2484+10, 40, 0, 19, \
+ NL80211_RRF_PASSIVE_SCAN | \
+ NL80211_RRF_NO_OFDM)
+
+#define BRCM_5GHZ_5180_5240 REG_RULE(5180-10, 5240+10, 40, 0, 21, \
+ NL80211_RRF_PASSIVE_SCAN | \
+ NL80211_RRF_NO_IBSS)
+#define BRCM_5GHZ_5260_5320 REG_RULE(5260-10, 5320+10, 40, 0, 21, \
+ NL80211_RRF_PASSIVE_SCAN | \
+ NL80211_RRF_DFS | \
+ NL80211_RRF_NO_IBSS)
+#define BRCM_5GHZ_5500_5700 REG_RULE(5500-10, 5700+10, 40, 0, 21, \
+ NL80211_RRF_PASSIVE_SCAN | \
+ NL80211_RRF_DFS | \
+ NL80211_RRF_NO_IBSS)
+#define BRCM_5GHZ_5745_5825 REG_RULE(5745-10, 5825+10, 40, 0, 21, \
+ NL80211_RRF_PASSIVE_SCAN | \
+ NL80211_RRF_NO_IBSS)
+
+static const struct ieee80211_regdomain brcms_regdom_x2 = {
+ .n_reg_rules = 7,
+ .alpha2 = "X2",
+ .reg_rules = {
+ BRCM_2GHZ_2412_2462,
+ BRCM_2GHZ_2467_2472,
+ BRCM_2GHZ_2484,
+ BRCM_5GHZ_5180_5240,
+ BRCM_5GHZ_5260_5320,
+ BRCM_5GHZ_5500_5700,
+ BRCM_5GHZ_5745_5825,
+ }
+};
+
struct brcms_cm_band {
/* struct locale_info flags */
u8 locale_flags;
@@ -137,14 +177,15 @@ struct country_info {
const u8 locale_mimo_5G; /* 5G mimo info */
};

+struct brcms_regd {
+ struct country_info country;
+ const struct ieee80211_regdomain *regdomain;
+};
+
struct brcms_cm_info {
struct brcms_pub *pub;
struct brcms_c_info *wlc;
- char srom_ccode[BRCM_CNTRY_BUF_SZ]; /* Country Code in SROM */
- uint srom_regrev; /* Regulatory Rev for the SROM ccode */
- const struct country_info *country; /* current country def */
- uint regrev; /* current Regulatory Revision */
- char country_abbrev[BRCM_CNTRY_BUF_SZ]; /* current advertised ccode */
+ const struct brcms_regd *world_regd;
/* per-band state (one per phy/radio) */
struct brcms_cm_band bandstate[MAXBANDS];
/* quiet channels currently for radar sensitivity or 11h support */
@@ -408,12 +449,12 @@ static const struct locale_mimo_info *g_mimo_5g_table[] = {
&locale_11n
};

-static const struct {
- char abbrev[BRCM_CNTRY_BUF_SZ]; /* country abbreviation */
- struct country_info country;
-} cntry_locales[] = {
+static const struct brcms_regd cntry_locales[] = {
+ /* Worldwide Row 2, must always be at index 0 */
{
- "X2", LOCALES(i, 11, bn, 11n)}, /* Worldwide RoW 2 */
+ .country = LOCALES(i, 11, bn, 11n),
+ .regdomain = &brcms_regdom_x2,
+ },
};

static const struct locale_info *brcms_c_get_locale_2g(u8 locale_idx)
@@ -482,93 +523,24 @@ static bool brcms_c_country_valid(const char *ccode)
return true;
}

-/* Lookup a country info structure from a null terminated country
- * abbreviation and regrev directly with no translation.
- */
-static const struct country_info *
-brcms_c_country_lookup_direct(const char *ccode, uint regrev)
+static const struct brcms_regd *brcms_world_regd(const char *regdom)
{
- uint size, i;
-
- /* Should just return 0 for single locale driver. */
- /* Keep it this way in case we add more locales. (for now anyway) */
-
- /*
- * all other country def arrays are for regrev == 0, so if
- * regrev is non-zero, fail
- */
- if (regrev > 0)
- return NULL;
-
- /* find matched table entry from country code */
- size = ARRAY_SIZE(cntry_locales);
- for (i = 0; i < size; i++) {
- if (strcmp(ccode, cntry_locales[i].abbrev) == 0)
- return &cntry_locales[i].country;
- }
- return NULL;
-}
+ const struct brcms_regd *regd = NULL;
+ int i;

-static const struct country_info *
-brcms_c_countrycode_map(struct brcms_cm_info *wlc_cm, const char *ccode,
- char *mapped_ccode, uint *mapped_regrev)
-{
- struct brcms_c_info *wlc = wlc_cm->wlc;
- const struct country_info *country;
- uint srom_regrev = wlc_cm->srom_regrev;
- const char *srom_ccode = wlc_cm->srom_ccode;
-
- /* check for currently supported ccode size */
- if (strlen(ccode) > (BRCM_CNTRY_BUF_SZ - 1)) {
- wiphy_err(wlc->wiphy, "wl%d: %s: ccode \"%s\" too long for "
- "match\n", wlc->pub->unit, __func__, ccode);
- return NULL;
- }
-
- /* default mapping is the given ccode and regrev 0 */
- strncpy(mapped_ccode, ccode, BRCM_CNTRY_BUF_SZ);
- *mapped_regrev = 0;
-
- /* If the desired country code matches the srom country code,
- * then the mapped country is the srom regulatory rev.
- * Otherwise look for an aggregate mapping.
- */
- if (!strcmp(srom_ccode, ccode)) {
- *mapped_regrev = srom_regrev;
- wiphy_err(wlc->wiphy, "srom_code == ccode %s\n", __func__);
- }
-
- /* find the matching built-in country definition */
- country = brcms_c_country_lookup_direct(mapped_ccode, *mapped_regrev);
-
- /* if there is not an exact rev match, default to rev zero */
- if (country == NULL && *mapped_regrev != 0) {
- *mapped_regrev = 0;
- country =
- brcms_c_country_lookup_direct(mapped_ccode, *mapped_regrev);
+ for (i = 0; i < ARRAY_SIZE(cntry_locales); i++) {
+ if (!strcmp(regdom, cntry_locales[i].regdomain->alpha2)) {
+ regd = &cntry_locales[i];
+ break;
+ }
}

- return country;
+ return regd;
}

-/* Lookup a country info structure from a null terminated country code
- * The lookup is case sensitive.
- */
-static const struct country_info *
-brcms_c_country_lookup(struct brcms_c_info *wlc, const char *ccode)
+static const struct brcms_regd *brcms_default_world_regd(void)
{
- const struct country_info *country;
- char mapped_ccode[BRCM_CNTRY_BUF_SZ];
- uint mapped_regrev;
-
- /*
- * map the country code to a built-in country code, regrev, and
- * country_info struct
- */
- country = brcms_c_countrycode_map(wlc->cmi, ccode, mapped_ccode,
- &mapped_regrev);
-
- return country;
+ return &cntry_locales[0];
}

/*
@@ -634,12 +606,6 @@ static bool brcms_c_japan_ccode(const char *ccode)
(ccode[1] == 'P' || (ccode[1] >= '1' && ccode[1] <= '9')));
}

-/* Returns true if currently set country is Japan or variant */
-static bool brcms_c_japan(struct brcms_c_info *wlc)
-{
- return brcms_c_japan_ccode(wlc->cmi->country_abbrev);
-}
-
static void
brcms_c_channel_min_txpower_limits_with_local_constraint(
struct brcms_cm_info *wlc_cm, struct txpwr_limits *txpwr,
@@ -743,8 +709,8 @@ static void brcms_c_channels_commit(struct brcms_cm_info *wlc_cm)
mboolset(wlc->pub->radio_disabled, WL_RADIO_COUNTRY_DISABLE);
wiphy_err(wlc->wiphy, "wl%d: %s: no valid channel for \"%s\" "
"nbands %d bandlocked %d\n", wlc->pub->unit,
- __func__, wlc_cm->country_abbrev, wlc->pub->_nbands,
- wlc->bandlocked);
+ __func__, wlc_cm->world_regd->regdomain->alpha2,
+ wlc->pub->_nbands, wlc->bandlocked);
} else if (mboolisset(wlc->pub->radio_disabled,
WL_RADIO_COUNTRY_DISABLE)) {
/*
@@ -753,15 +719,6 @@ static void brcms_c_channels_commit(struct brcms_cm_info *wlc_cm)
*/
mboolclr(wlc->pub->radio_disabled, WL_RADIO_COUNTRY_DISABLE);
}
-
- /*
- * Now that the country abbreviation is set, if the radio supports 2G,
- * then set channel 14 restrictions based on the new locale.
- */
- if (wlc->pub->_nbands > 1 || wlc->band->bandtype == BRCM_BAND_2G)
- wlc_phy_chanspec_ch14_widefilter_set(wlc->band->pi,
- brcms_c_japan(wlc) ? true :
- false);
}

static int
@@ -820,20 +777,13 @@ brcms_c_channels_init(struct brcms_cm_info *wlc_cm,
* information found with the country code.
*/
static void
-brcms_c_set_country_common(struct brcms_cm_info *wlc_cm,
- const char *country_abbrev,
- const char *ccode, uint regrev,
- const struct country_info *country)
+brcms_c_set_country(struct brcms_cm_info *wlc_cm,
+ const struct brcms_regd *regd)
{
+ const struct country_info *country = &regd->country;
const struct locale_info *locale;
struct brcms_c_info *wlc = wlc_cm->wlc;

- /* save current country state */
- wlc_cm->country = country;
-
- strncpy(wlc_cm->country_abbrev, country_abbrev, BRCM_CNTRY_BUF_SZ - 1);
- wlc_cm->regrev = regrev;
-
if ((wlc->pub->_n_enab & SUPPORT_11N) !=
wlc->protection->nmode_user)
brcms_c_set_nmode(wlc);
@@ -852,59 +802,11 @@ brcms_c_set_country_common(struct brcms_cm_info *wlc_cm,
return;
}

-static int
-brcms_c_set_countrycode_rev(struct brcms_cm_info *wlc_cm,
- const char *country_abbrev,
- const char *ccode, int regrev)
-{
- const struct country_info *country;
- char mapped_ccode[BRCM_CNTRY_BUF_SZ];
- uint mapped_regrev;
-
- /* if regrev is -1, lookup the mapped country code,
- * otherwise use the ccode and regrev directly
- */
- if (regrev == -1) {
- /*
- * map the country code to a built-in country
- * code, regrev, and country_info
- */
- country =
- brcms_c_countrycode_map(wlc_cm, ccode, mapped_ccode,
- &mapped_regrev);
- } else {
- /* find the matching built-in country definition */
- country = brcms_c_country_lookup_direct(ccode, regrev);
- strncpy(mapped_ccode, ccode, BRCM_CNTRY_BUF_SZ);
- mapped_regrev = regrev;
- }
-
- if (country == NULL)
- return -EINVAL;
-
- /* set the driver state for the country */
- brcms_c_set_country_common(wlc_cm, country_abbrev, mapped_ccode,
- mapped_regrev, country);
-
- return 0;
-}
-
-/*
- * set the driver's current country and regulatory information using
- * a country code as the source. Lookup built in country information
- * found with the country code.
- */
-static int
-brcms_c_set_countrycode(struct brcms_cm_info *wlc_cm, const char *ccode)
-{
- return brcms_c_set_countrycode_rev(wlc_cm, ccode, ccode, -1);
-}
-
struct brcms_cm_info *brcms_c_channel_mgr_attach(struct brcms_c_info *wlc)
{
struct brcms_cm_info *wlc_cm;
struct brcms_pub *pub = wlc->pub;
- char *ccode;
+ const char *ccode;

BCMMSG(wlc->wiphy, "wl%d\n", wlc->pub->unit);

@@ -917,17 +819,29 @@ struct brcms_cm_info *brcms_c_channel_mgr_attach(struct brcms_c_info *wlc)

/* store the country code for passing up as a regulatory hint */
ccode = getvar(wlc->hw->sih, BRCMS_SROM_CCODE);
- if (ccode && brcms_c_country_valid(ccode))
- strncpy(wlc->pub->srom_ccode, ccode, BRCM_CNTRY_BUF_SZ - 1);
+ if (ccode) {
+ wlc_cm->world_regd = brcms_world_regd(ccode);
+ if (brcms_c_country_valid(ccode))
+ strncpy(wlc->pub->srom_ccode, ccode,
+ BRCM_CNTRY_BUF_SZ - 1);
+ }
+
+ /*
+ * If no custom world domain is found in the SROM, use the
+ * default "X2" domain.
+ */
+ if (!wlc_cm->world_regd) {
+ wlc_cm->world_regd = brcms_default_world_regd();
+ ccode = wlc_cm->world_regd->regdomain->alpha2;
+ }

/* save default country for exiting 11d regulatory mode */
- strncpy(wlc->country_default, "X2", BRCM_CNTRY_BUF_SZ - 1);
+ strncpy(wlc->country_default, ccode, BRCM_CNTRY_BUF_SZ - 1);

/* initialize autocountry_default to driver default */
- strncpy(wlc->autocountry_default, wlc->country_default,
- BRCM_CNTRY_BUF_SZ - 1);
+ strncpy(wlc->autocountry_default, ccode, BRCM_CNTRY_BUF_SZ - 1);

- brcms_c_set_countrycode(wlc_cm, wlc->country_default);
+ brcms_c_set_country(wlc_cm, wlc_cm->world_regd);

return wlc_cm;
}
@@ -995,13 +909,7 @@ brcms_c_channel_reg_limits(struct brcms_cm_info *wlc_cm, u16 chanspec,

memset(txpwr, 0, sizeof(struct txpwr_limits));

- if (!brcms_c_valid_chanspec_db(wlc_cm, chanspec)) {
- country = brcms_c_country_lookup(wlc, wlc->autocountry_default);
- if (country == NULL)
- return;
- } else {
- country = wlc_cm->country;
- }
+ country = &wlc_cm->world_regd->country;

chan = CHSPEC_CHANNEL(chanspec);
band = wlc->bandstate[chspec_bandunit(chanspec)];
@@ -1253,3 +1161,129 @@ bool brcms_c_valid_chanspec_db(struct brcms_cm_info *wlc_cm, u16 chspec)
{
return brcms_c_valid_chanspec_ext(wlc_cm, chspec, true);
}
+
+bool brcms_is_radar_freq(u16 center_freq)
+{
+ return center_freq >= 5260 && center_freq <= 5700;
+}
+
+static void brcms_reg_apply_radar_flags(struct wiphy *wiphy)
+{
+ struct ieee80211_supported_band *sband;
+ struct ieee80211_channel *ch;
+ int i;
+
+ sband = wiphy->bands[IEEE80211_BAND_5GHZ];
+ if (!sband)
+ return;
+
+ for (i = 0; i < sband->n_channels; i++) {
+ ch = &sband->channels[i];
+
+ if (!brcms_is_radar_freq(ch->center_freq))
+ continue;
+
+ /*
+ * All channels in this range should be passive and have
+ * DFS enabled.
+ */
+ if (!(ch->flags & IEEE80211_CHAN_DISABLED))
+ ch->flags |= IEEE80211_CHAN_RADAR |
+ IEEE80211_CHAN_NO_IBSS |
+ IEEE80211_CHAN_PASSIVE_SCAN;
+ }
+}
+
+static void
+brcms_reg_apply_beaconing_flags(struct wiphy *wiphy,
+ enum nl80211_reg_initiator initiator)
+{
+ struct ieee80211_supported_band *sband;
+ struct ieee80211_channel *ch;
+ const struct ieee80211_reg_rule *reg_rule;
+ int band, i, ret;
+
+ for (band = 0; band < IEEE80211_NUM_BANDS; band++) {
+ sband = wiphy->bands[band];
+ if (!sband)
+ continue;
+
+ for (i = 0; i < sband->n_channels; i++) {
+ ch = &sband->channels[i];
+
+ if (brcms_is_radar_freq(ch->center_freq) ||
+ (ch->flags & IEEE80211_CHAN_RADAR))
+ continue;
+
+ if (initiator == NL80211_REGDOM_SET_BY_COUNTRY_IE) {
+ ret = freq_reg_info(wiphy, ch->center_freq,
+ 0, &reg_rule);
+ if (ret)
+ continue;
+
+ if (!(reg_rule->flags & NL80211_RRF_NO_IBSS))
+ ch->flags &= ~IEEE80211_CHAN_NO_IBSS;
+ if (!(reg_rule->flags & NL80211_RRF_PASSIVE_SCAN))
+ ch->flags &= ~IEEE80211_CHAN_PASSIVE_SCAN;
+ } else {
+ if (ch->beacon_found)
+ ch->flags &= ~(IEEE80211_CHAN_NO_IBSS |
+ IEEE80211_CHAN_PASSIVE_SCAN);
+ }
+ }
+ }
+}
+
+static int brcms_reg_notifier(struct wiphy *wiphy,
+ struct regulatory_request *request)
+{
+ struct ieee80211_hw *hw = wiphy_to_ieee80211_hw(wiphy);
+ struct brcms_info *wl = hw->priv;
+ struct brcms_c_info *wlc = wl->wlc;
+
+ brcms_reg_apply_radar_flags(wiphy);
+
+ if (request && request->initiator == NL80211_REGDOM_SET_BY_COUNTRY_IE)
+ brcms_reg_apply_beaconing_flags(wiphy, request->initiator);
+
+ if (wlc->pub->_nbands > 1 || wlc->band->bandtype == BRCM_BAND_2G)
+ wlc_phy_chanspec_ch14_widefilter_set(wlc->band->pi,
+ brcms_c_japan_ccode(request->alpha2));
+
+ return 0;
+}
+
+void brcms_c_regd_init(struct brcms_c_info *wlc)
+{
+ struct wiphy *wiphy = wlc->wiphy;
+ const struct brcms_regd *regd = wlc->cmi->world_regd;
+ struct ieee80211_supported_band *sband;
+ struct ieee80211_channel *ch;
+ struct brcms_chanvec sup_chan;
+ struct brcms_band *band;
+ int band_idx, i;
+
+ /* Disable any channels not supported by the phy */
+ for (band_idx = 0; band_idx < IEEE80211_NUM_BANDS; band_idx++) {
+ if (band_idx == IEEE80211_BAND_2GHZ)
+ band = wlc->bandstate[BAND_2G_INDEX];
+ else
+ band = wlc->bandstate[BAND_5G_INDEX];
+ wlc_phy_chanspec_band_validch(band->pi, band->bandtype,
+ &sup_chan);
+
+ sband = wiphy->bands[band_idx];
+ for (i = 0; i < sband->n_channels; i++) {
+ ch = &sband->channels[i];
+ if (!isset(sup_chan.vec, ch->hw_value))
+ ch->flags |= IEEE80211_CHAN_DISABLED;
+ }
+ }
+
+ wlc->wiphy->reg_notifier = brcms_reg_notifier;
+ wlc->wiphy->flags |= WIPHY_FLAG_CUSTOM_REGULATORY |
+ WIPHY_FLAG_STRICT_REGULATORY;
+ wiphy_apply_custom_regulatory(wlc->wiphy, regd->regdomain);
+ brcms_reg_apply_radar_flags(wiphy);
+ brcms_reg_apply_beaconing_flags(wiphy, NL80211_REGDOM_SET_BY_DRIVER);
+}
diff --git a/drivers/net/wireless/brcm80211/brcmsmac/channel.h b/drivers/net/wireless/brcm80211/brcmsmac/channel.h
index 808cb4f..dbe60ef 100644
--- a/drivers/net/wireless/brcm80211/brcmsmac/channel.h
+++ b/drivers/net/wireless/brcm80211/brcmsmac/channel.h
@@ -50,4 +50,6 @@ extern void brcms_c_channel_set_chanspec(struct brcms_cm_info *wlc_cm,
u16 chanspec,
u8 local_constraint_qdbm);

+extern void brcms_c_regd_init(struct brcms_c_info *wlc);
+
#endif /* _WLC_CHANNEL_H */
diff --git a/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c b/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c
index aa15558..f26e93c 100644
--- a/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c
+++ b/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c
@@ -1059,6 +1059,8 @@ static struct brcms_info *brcms_attach(struct bcma_device *pdev)
goto fail;
}

+ brcms_c_regd_init(wl->wlc);
+
memcpy(perm, &wl->pub->cur_etheraddr, ETH_ALEN);
if (WARN_ON(!is_valid_ether_addr(perm)))
goto fail;
--
1.7.9.5


2012-04-16 20:18:02

by Seth Forshee

[permalink] [raw]
Subject: [RFC PATCH 7/8] brcm80211: smac: don't validate channels against internal regulatory data

The core regulatory support will disable channels not allowed by
regulatory rules, so brcmsmac doesn't need to duplicate it.

Signed-off-by: Seth Forshee <[email protected]>
---
drivers/net/wireless/brcm80211/brcmsmac/channel.c | 344 +--------------------
1 file changed, 6 insertions(+), 338 deletions(-)

diff --git a/drivers/net/wireless/brcm80211/brcmsmac/channel.c b/drivers/net/wireless/brcm80211/brcmsmac/channel.c
index cda40c8..a31a3de 100644
--- a/drivers/net/wireless/brcm80211/brcmsmac/channel.c
+++ b/drivers/net/wireless/brcm80211/brcmsmac/channel.c
@@ -30,40 +30,6 @@
/* QDB() macro takes a dB value and converts to a quarter dB value */
#define QDB(n) ((n) * BRCMS_TXPWR_DB_FACTOR)

-#define LOCALE_CHAN_01_11 (1<<0)
-#define LOCALE_CHAN_12_13 (1<<1)
-#define LOCALE_CHAN_14 (1<<2)
-#define LOCALE_SET_5G_LOW_JP1 (1<<3) /* 34-48, step 2 */
-#define LOCALE_SET_5G_LOW_JP2 (1<<4) /* 34-46, step 4 */
-#define LOCALE_SET_5G_LOW1 (1<<5) /* 36-48, step 4 */
-#define LOCALE_SET_5G_LOW2 (1<<6) /* 52 */
-#define LOCALE_SET_5G_LOW3 (1<<7) /* 56-64, step 4 */
-#define LOCALE_SET_5G_MID1 (1<<8) /* 100-116, step 4 */
-#define LOCALE_SET_5G_MID2 (1<<9) /* 120-124, step 4 */
-#define LOCALE_SET_5G_MID3 (1<<10) /* 128 */
-#define LOCALE_SET_5G_HIGH1 (1<<11) /* 132-140, step 4 */
-#define LOCALE_SET_5G_HIGH2 (1<<12) /* 149-161, step 4 */
-#define LOCALE_SET_5G_HIGH3 (1<<13) /* 165 */
-#define LOCALE_CHAN_52_140_ALL (1<<14)
-#define LOCALE_SET_5G_HIGH4 (1<<15) /* 184-216 */
-
-#define LOCALE_CHAN_36_64 (LOCALE_SET_5G_LOW1 | \
- LOCALE_SET_5G_LOW2 | \
- LOCALE_SET_5G_LOW3)
-#define LOCALE_CHAN_52_64 (LOCALE_SET_5G_LOW2 | LOCALE_SET_5G_LOW3)
-#define LOCALE_CHAN_100_124 (LOCALE_SET_5G_MID1 | LOCALE_SET_5G_MID2)
-#define LOCALE_CHAN_100_140 (LOCALE_SET_5G_MID1 | LOCALE_SET_5G_MID2 | \
- LOCALE_SET_5G_MID3 | LOCALE_SET_5G_HIGH1)
-#define LOCALE_CHAN_149_165 (LOCALE_SET_5G_HIGH2 | LOCALE_SET_5G_HIGH3)
-#define LOCALE_CHAN_184_216 LOCALE_SET_5G_HIGH4
-
-#define LOCALE_CHAN_01_14 (LOCALE_CHAN_01_11 | \
- LOCALE_CHAN_12_13 | \
- LOCALE_CHAN_14)
-
-#define LOCALE_RESTRICTED_NONE 0
-#define LOCALE_RESTRICTED_SET_2G_SHORT 1
-
#define LOCALE_2G_IDX_i 0
#define LOCALE_5G_IDX_11 0
#define LOCALE_MIMO_IDX_bn 0
@@ -138,10 +104,6 @@ static const struct ieee80211_regdomain brcms_regdom_x2 = {
struct brcms_cm_band {
/* struct locale_info flags */
u8 locale_flags;
- /* List of valid channels in the country */
- struct brcms_chanvec valid_channels;
- /* List of restricted use channels */
- const struct brcms_chanvec *restricted_channels;
};

/* locale per-channel tx power limits for MIMO frames
@@ -175,211 +137,17 @@ struct brcms_cm_info {
const struct brcms_regd *world_regd;
/* per-band state (one per phy/radio) */
struct brcms_cm_band bandstate[MAXBANDS];
- /* quiet channels currently for radar sensitivity or 11h support */
- /* channels on which we cannot transmit */
- struct brcms_chanvec quiet_channels;
};

/* locale channel and power info. */
struct locale_info {
- u32 valid_channels;
- /* List of channels used only if APs are detected */
- u8 restricted_channels;
u8 flags;
};

-/* Regulatory Matrix Spreadsheet (CLM) MIMO v3.7.9 */
-
-/*
- * Some common channel sets
- */
-
-/* No channels */
-static const struct brcms_chanvec chanvec_none = {
- {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00}
-};
-
-/*
- * Restricted channel sets
- */
-
-/* Channels 12, 13 */
-static const struct brcms_chanvec restricted_set_2g_short = {
- {0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00}
-};
-
-/* global memory to provide working buffer for expanded locale */
-
-static const struct brcms_chanvec *g_table_restricted_chan[] = {
- &chanvec_none, /* restricted_set_none */
- &restricted_set_2g_short,
-};
-
-static const struct brcms_chanvec locale_2g_01_11 = {
- {0xfe, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00}
-};
-
-static const struct brcms_chanvec locale_2g_12_13 = {
- {0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00}
-};
-
-static const struct brcms_chanvec locale_2g_14 = {
- {0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00}
-};
-
-static const struct brcms_chanvec locale_5g_LOW_JP1 = {
- {0x00, 0x00, 0x00, 0x00, 0x54, 0x55, 0x01, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00}
-};
-
-static const struct brcms_chanvec locale_5g_LOW_JP2 = {
- {0x00, 0x00, 0x00, 0x00, 0x44, 0x44, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00}
-};
-
-static const struct brcms_chanvec locale_5g_LOW1 = {
- {0x00, 0x00, 0x00, 0x00, 0x10, 0x11, 0x01, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00}
-};
-
-static const struct brcms_chanvec locale_5g_LOW2 = {
- {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00}
-};
-
-static const struct brcms_chanvec locale_5g_LOW3 = {
- {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11,
- 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00}
-};
-
-static const struct brcms_chanvec locale_5g_MID1 = {
- {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x10, 0x11, 0x11, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00}
-};
-
-static const struct brcms_chanvec locale_5g_MID2 = {
- {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00}
-};
-
-static const struct brcms_chanvec locale_5g_MID3 = {
- {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00}
-};
-
-static const struct brcms_chanvec locale_5g_HIGH1 = {
- {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x10, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00}
-};
-
-static const struct brcms_chanvec locale_5g_HIGH2 = {
- {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x20, 0x22, 0x02, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00}
-};
-
-static const struct brcms_chanvec locale_5g_HIGH3 = {
- {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00}
-};
-
-static const struct brcms_chanvec locale_5g_52_140_ALL = {
- {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x11,
- 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
- 0x11, 0x11, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00}
-};
-
-static const struct brcms_chanvec locale_5g_HIGH4 = {
- {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11,
- 0x11, 0x11, 0x11, 0x11}
-};
-
-static const struct brcms_chanvec *g_table_locale_base[] = {
- &locale_2g_01_11,
- &locale_2g_12_13,
- &locale_2g_14,
- &locale_5g_LOW_JP1,
- &locale_5g_LOW_JP2,
- &locale_5g_LOW1,
- &locale_5g_LOW2,
- &locale_5g_LOW3,
- &locale_5g_MID1,
- &locale_5g_MID2,
- &locale_5g_MID3,
- &locale_5g_HIGH1,
- &locale_5g_HIGH2,
- &locale_5g_HIGH3,
- &locale_5g_52_140_ALL,
- &locale_5g_HIGH4
-};
-
-static void brcms_c_locale_add_channels(struct brcms_chanvec *target,
- const struct brcms_chanvec *channels)
-{
- u8 i;
- for (i = 0; i < sizeof(struct brcms_chanvec); i++)
- target->vec[i] |= channels->vec[i];
-}
-
-static void brcms_c_locale_get_channels(const struct locale_info *locale,
- struct brcms_chanvec *channels)
-{
- u8 i;
-
- memset(channels, 0, sizeof(struct brcms_chanvec));
-
- for (i = 0; i < ARRAY_SIZE(g_table_locale_base); i++) {
- if (locale->valid_channels & (1 << i))
- brcms_c_locale_add_channels(channels,
- g_table_locale_base[i]);
- }
-}
-
/*
* Locale Definitions - 2.4 GHz
*/
static const struct locale_info locale_i = { /* locale i. channel 1 - 13 */
- LOCALE_CHAN_01_11 | LOCALE_CHAN_12_13,
- LOCALE_RESTRICTED_SET_2G_SHORT,
BRCMS_EIRP
};

@@ -387,9 +155,6 @@ static const struct locale_info locale_i = { /* locale i. channel 1 - 13 */
* Locale Definitions - 5 GHz
*/
static const struct locale_info locale_11 = {
- /* locale 11. channel 36 - 48, 52 - 64, 100 - 140, 149 - 165 */
- LOCALE_CHAN_36_64 | LOCALE_CHAN_100_140 | LOCALE_CHAN_149_165,
- LOCALE_RESTRICTED_NONE,
BRCMS_EIRP | BRCMS_DFS_EU
};

@@ -525,62 +290,6 @@ static const struct brcms_regd *brcms_default_world_regd(void)
return &cntry_locales[0];
}

-/*
- * reset the quiet channels vector to the union
- * of the restricted and radar channel sets
- */
-static void brcms_c_quiet_channels_reset(struct brcms_cm_info *wlc_cm)
-{
- struct brcms_c_info *wlc = wlc_cm->wlc;
- uint i, j;
- struct brcms_band *band;
- const struct brcms_chanvec *chanvec;
-
- memset(&wlc_cm->quiet_channels, 0, sizeof(struct brcms_chanvec));
-
- band = wlc->band;
- for (i = 0; i < wlc->pub->_nbands;
- i++, band = wlc->bandstate[OTHERBANDUNIT(wlc)]) {
-
- /* initialize quiet channels for restricted channels */
- chanvec = wlc_cm->bandstate[band->bandunit].restricted_channels;
- for (j = 0; j < sizeof(struct brcms_chanvec); j++)
- wlc_cm->quiet_channels.vec[j] |= chanvec->vec[j];
-
- }
-}
-
-/* Is the channel valid for the current locale and current band? */
-static bool brcms_c_valid_channel20(struct brcms_cm_info *wlc_cm, uint val)
-{
- struct brcms_c_info *wlc = wlc_cm->wlc;
-
- return ((val < MAXCHANNEL) &&
- isset(wlc_cm->bandstate[wlc->band->bandunit].valid_channels.vec,
- val));
-}
-
-/* Is the channel valid for the current locale and specified band? */
-static bool brcms_c_valid_channel20_in_band(struct brcms_cm_info *wlc_cm,
- uint bandunit, uint val)
-{
- return ((val < MAXCHANNEL)
- && isset(wlc_cm->bandstate[bandunit].valid_channels.vec, val));
-}
-
-/* Is the channel valid for the current locale? (but don't consider channels not
- * available due to bandlocking)
- */
-static bool brcms_c_valid_channel20_db(struct brcms_cm_info *wlc_cm, uint val)
-{
- struct brcms_c_info *wlc = wlc_cm->wlc;
-
- return brcms_c_valid_channel20(wlc->cmi, val) ||
- (!wlc->bandlocked
- && brcms_c_valid_channel20_in_band(wlc->cmi,
- OTHERBANDUNIT(wlc), val));
-}
-
/* JP, J1 - J10 are Japan ccodes */
static bool brcms_c_japan_ccode(const char *ccode)
{
@@ -668,10 +377,9 @@ brcms_c_channels_init(struct brcms_cm_info *wlc_cm,
const struct country_info *country)
{
struct brcms_c_info *wlc = wlc_cm->wlc;
- uint i, j;
+ uint i;
struct brcms_band *band;
const struct locale_info *li;
- struct brcms_chanvec sup_chan;
const struct locale_mimo_info *li_mimo;

band = wlc->band;
@@ -689,26 +397,8 @@ brcms_c_channels_init(struct brcms_cm_info *wlc_cm,
/* merge the mimo non-mimo locale flags */
wlc_cm->bandstate[band->bandunit].locale_flags |=
li_mimo->flags;
-
- wlc_cm->bandstate[band->bandunit].restricted_channels =
- g_table_restricted_chan[li->restricted_channels];
-
- /*
- * set the channel availability, masking out the channels
- * that may not be supported on this phy.
- */
- wlc_phy_chanspec_band_validch(band->pi, band->bandtype,
- &sup_chan);
- brcms_c_locale_get_channels(li,
- &wlc_cm->bandstate[band->bandunit].
- valid_channels);
- for (j = 0; j < sizeof(struct brcms_chanvec); j++)
- wlc_cm->bandstate[band->bandunit].valid_channels.
- vec[j] &= sup_chan.vec[j];
}

- brcms_c_quiet_channels_reset(wlc_cm);
-
return 0;
}

@@ -799,23 +489,12 @@ brcms_c_channel_locale_flags_in_band(struct brcms_cm_info *wlc_cm,
return wlc_cm->bandstate[bandunit].locale_flags;
}

-static bool
-brcms_c_quiet_chanspec(struct brcms_cm_info *wlc_cm, u16 chspec)
-{
- return (wlc_cm->wlc->pub->_n_enab & SUPPORT_11N) &&
- CHSPEC_IS40(chspec) ?
- (isset(wlc_cm->quiet_channels.vec,
- lower_20_sb(CHSPEC_CHANNEL(chspec))) ||
- isset(wlc_cm->quiet_channels.vec,
- upper_20_sb(CHSPEC_CHANNEL(chspec)))) :
- isset(wlc_cm->quiet_channels.vec, CHSPEC_CHANNEL(chspec));
-}
-
void
brcms_c_channel_set_chanspec(struct brcms_cm_info *wlc_cm, u16 chanspec,
u8 local_constraint_qdbm)
{
struct brcms_c_info *wlc = wlc_cm->wlc;
+ struct ieee80211_channel *ch = wlc->pub->ieee_hw->conf.channel;
struct txpwr_limits txpwr;

brcms_c_channel_reg_limits(wlc_cm, chanspec, &txpwr);
@@ -825,7 +504,7 @@ brcms_c_channel_set_chanspec(struct brcms_cm_info *wlc_cm, u16 chanspec,
);

brcms_b_set_chanspec(wlc->hw, chanspec,
- (brcms_c_quiet_chanspec(wlc_cm, chanspec) != 0),
+ !!(ch->flags & IEEE80211_CHAN_PASSIVE_SCAN),
&txpwr);
}

@@ -1041,8 +720,7 @@ static bool brcms_c_chspec_malformed(u16 chanspec)
* and they are also a legal HT combination
*/
static bool
-brcms_c_valid_chanspec_ext(struct brcms_cm_info *wlc_cm, u16 chspec,
- bool dualband)
+brcms_c_valid_chanspec_ext(struct brcms_cm_info *wlc_cm, u16 chspec)
{
struct brcms_c_info *wlc = wlc_cm->wlc;
u8 channel = CHSPEC_CHANNEL(chspec);
@@ -1058,22 +736,12 @@ brcms_c_valid_chanspec_ext(struct brcms_cm_info *wlc_cm, u16 chspec,
chspec_bandunit(chspec))
return false;

- /* Check a 20Mhz channel */
- if (CHSPEC_IS20(chspec)) {
- if (dualband)
- return brcms_c_valid_channel20_db(wlc_cm->wlc->cmi,
- channel);
- else
- return brcms_c_valid_channel20(wlc_cm->wlc->cmi,
- channel);
- }
-
- return false;
+ return true;
}

bool brcms_c_valid_chanspec_db(struct brcms_cm_info *wlc_cm, u16 chspec)
{
- return brcms_c_valid_chanspec_ext(wlc_cm, chspec, true);
+ return brcms_c_valid_chanspec_ext(wlc_cm, chspec);
}

bool brcms_is_radar_freq(u16 center_freq)
--
1.7.9.5


2012-05-26 17:17:51

by Seth Forshee

[permalink] [raw]
Subject: Re: [RFC PATCH 3/8] brcm80211: smac: clean up channel.c

On Sat, May 26, 2012 at 12:33:05AM +0200, Arend van Spriel wrote:
> We are not supporting 40MHz right now, but it is on our roadmap. I would
> prefer to keep it, but git can recover it for me when that roadmap item
> is due.

The argument against keeping it is that it will be utterly broken by all
of the other changes. I could try to rework it along with the rest of
the code I guess, but I'd obviously be unable to test it.

I'll keep it in if you prefer, but I should probably add a comment
warning that the code needs some attention before it can be used.


2012-05-26 06:38:46

by Arend van Spriel

[permalink] [raw]
Subject: Re: [RFC PATCH 0/8] brcm80211: smac: rework regulatory support

On 05/26/2012 12:51 AM, Luis R. Rodriguez wrote:
>> It took a while. There were some discussions and we agreed that your
>> > changes establish a better integration with the regulatory framework.
>> > There are some concerns about the content of the crda database, but that
>> > is another thing outside the scope of your patches.
> BTW if you would like to address anything please let me know. If you'd like
> to review things in private too that's fine, just let me know. I
> should say that the staging area for the next generation regulatory
> code is being done through the regulatory simulator:
>
> git://github.com/mcgrof/regsim.git

Thanks, Luis. I mainly focused on the crda database and it has a
relation freqs<->pwr_limit. In our regulatory code we make a distinction
between 11n and abg as we believe that is necessary. Another example
would be 20MHz transmission in 40MHz channel. Maybe that is taken into
account in crda code, but I did not have a close look at it yet.

I will have a look at the regsim repository and follow up on that.

> Arend, in the future please trim all hunks that are not relevant to
> your replies, that makes review easier.

Will do.

Gr. AvS


2012-05-27 12:17:17

by Arend van Spriel

[permalink] [raw]
Subject: Re: [RFC PATCH 4/8] brcm80211: smac: inform mac80211 of the X2 regulatory domain

On 05/26/2012 07:18 PM, Seth Forshee wrote:
> On Sat, May 26, 2012 at 12:33:15AM +0200, Arend van Spriel wrote:
>>> +#define BRCM_2GHZ_2412_2462 REG_RULE(2412-10, 2462+10, 40, 0, 19, 0)
>>> +#define BRCM_2GHZ_2467_2472 REG_RULE(2467-10, 2472+10, 20, 0, 19, \
>>> + NL80211_RRF_PASSIVE_SCAN | \
>>> + NL80211_RRF_NO_IBSS)
>>> +#define BRCM_2GHZ_2484 REG_RULE(2484-10, 2484+10, 40, 0, 19, \
>>> + NL80211_RRF_PASSIVE_SCAN | \
>>> + NL80211_RRF_NO_OFDM)
>>> +
>>
>> If channels 12 and 13 are 20MHz only, shouldn't channel 14 above
>> (2484MHz) be 20MHz as well?
>
> Heh, good point. I'm trying to remember why I made 12 and 13 20MHz only
> though; maybe that's a mistake. Is there any reason why they couldn't
> all be 40MHz?

Not sure either. A number of countries have this rule so maybe it is
regulatory requirement.

>>
>> You can avoid this code if you/we do not add the channels to
>> wiphy->bands[IEEE80211_BAND_5GHZ]. The driver does not support DFS so we
>> better stay away from these channels, which was your original issue to
>> start this work if I recall correct :-( Sorry.
>
> This is what originally got me looking at the brcmsmac regulatory
> support, so it would be disappointing if at the end these channels still
> aren't usable.

Hence me saying sorry.

> My understanding of DFS is pretty rudamentary. Could you explain what
> support is needed? I do see that mac80211 doesn't really support power
> measurement requests, but if we can at least stop transmission when
> radar is present couldn't we still operate on the channels?

The hardware would need to signal the driver that a radar has been detected.

> Luis, any insight you can offer on the subject would be appreciated.
>
>>
>> can this be moved in brcms_c_channel_mgr_attach()?
>
> Not without rearranging the initialization, as brcms_c_regd_init() must
> be called after wiphy->bands has been set up. I don't see any reason why
> setting up the bands couldn't be moved to before channel_mgr_attach()
> though, and in that case regd_init() could be moved into
> channel_mgr_attach().

Please do. I prefer to keep regd_init() local to channel.c.

Gr. AvS


2012-05-25 22:33:23

by Arend van Spriel

[permalink] [raw]
Subject: Re: [RFC PATCH 3/8] brcm80211: smac: clean up channel.c

On 04/16/2012 10:17 PM, Seth Forshee wrote:
> Much of the code is either unsed or never put to any useful purpose.
> Remove this code in advance of reworking the driver's regulatory
> support.

Reviewed-by: Arend Van Spriel <[email protected]>
Reviewed-by: Pieter-Paul Giesberts <[email protected]>
Reviewed-by: Brett Rudley <[email protected]>
> Signed-off-by: Seth Forshee <[email protected]>
> ---
> drivers/net/wireless/brcm80211/brcmsmac/channel.c | 254 +--------------------
> 1 file changed, 5 insertions(+), 249 deletions(-)
>
> diff --git a/drivers/net/wireless/brcm80211/brcmsmac/channel.c b/drivers/net/wireless/brcm80211/brcmsmac/channel.c
> index 71fce2c..1998c86 100644
> --- a/drivers/net/wireless/brcm80211/brcmsmac/channel.c
> +++ b/drivers/net/wireless/brcm80211/brcmsmac/channel.c
>
> @@ -1450,45 +1245,6 @@ brcms_c_valid_chanspec_ext(struct brcms_cm_info *wlc_cm, u16 chspec,
> return brcms_c_valid_channel20(wlc_cm->wlc->cmi,
> channel);
> }
> -#ifdef SUPPORT_40MHZ
> - /*
> - * We know we are now checking a 40MHZ channel, so we should
> - * only be here for NPHYS
> - */
> - if (BRCMS_ISNPHY(wlc->band) || BRCMS_ISSSLPNPHY(wlc->band)) {
> - u8 upper_sideband = 0, idx;
> - u8 num_ch20_entries =
> - sizeof(chan20_info) / sizeof(struct chan20_info);
> -
> - if (!VALID_40CHANSPEC_IN_BAND(wlc, chspec_bandunit(chspec)))
> - return false;
> -
> - if (dualband) {
> - if (!brcms_c_valid_channel20_db(wlc->cmi,
> - lower_20_sb(channel)) ||
> - !brcms_c_valid_channel20_db(wlc->cmi,
> - upper_20_sb(channel)))
> - return false;
> - } else {
> - if (!brcms_c_valid_channel20(wlc->cmi,
> - lower_20_sb(channel)) ||
> - !brcms_c_valid_channel20(wlc->cmi,
> - upper_20_sb(channel)))
> - return false;
> - }
> -
> - /* find the lower sideband info in the sideband array */
> - for (idx = 0; idx < num_ch20_entries; idx++) {
> - if (chan20_info[idx].sb == lower_20_sb(channel))
> - upper_sideband = chan20_info[idx].adj_sbs;
> - }
> - /* check that the lower sideband allows an upper sideband */
> - if ((upper_sideband & (CH_UPPER_SB | CH_EWA_VALID)) ==
> - (CH_UPPER_SB | CH_EWA_VALID))
> - return true;
> - return false;
> - }
> -#endif /* 40 MHZ */
>
> return false;
> }

We are not supporting 40MHz right now, but it is on our roadmap. I would
prefer to keep it, but git can recover it for me when that roadmap item
is due.

Gr. AvS


2012-05-29 13:12:19

by Seth Forshee

[permalink] [raw]
Subject: Re: [RFC PATCH 4/8] brcm80211: smac: inform mac80211 of the X2 regulatory domain

On Sun, May 27, 2012 at 02:17:03PM +0200, Arend van Spriel wrote:
> On 05/26/2012 07:18 PM, Seth Forshee wrote:
> > On Sat, May 26, 2012 at 12:33:15AM +0200, Arend van Spriel wrote:
> >>> +#define BRCM_2GHZ_2412_2462 REG_RULE(2412-10, 2462+10, 40, 0, 19, 0)
> >>> +#define BRCM_2GHZ_2467_2472 REG_RULE(2467-10, 2472+10, 20, 0, 19, \
> >>> + NL80211_RRF_PASSIVE_SCAN | \
> >>> + NL80211_RRF_NO_IBSS)
> >>> +#define BRCM_2GHZ_2484 REG_RULE(2484-10, 2484+10, 40, 0, 19, \
> >>> + NL80211_RRF_PASSIVE_SCAN | \
> >>> + NL80211_RRF_NO_OFDM)
> >>> +
> >>
> >> If channels 12 and 13 are 20MHz only, shouldn't channel 14 above
> >> (2484MHz) be 20MHz as well?
> >
> > Heh, good point. I'm trying to remember why I made 12 and 13 20MHz only
> > though; maybe that's a mistake. Is there any reason why they couldn't
> > all be 40MHz?
>
> Not sure either. A number of countries have this rule so maybe it is
> regulatory requirement.

Maybe. I note that among the in-kernel rules, domain 00 only allows
20MHz for those frequencies, but ath and rtlwifi allow 40MHz. I'll be
conservative and leave them at 20MHz unless I hear otherwise from you.

> >> You can avoid this code if you/we do not add the channels to
> >> wiphy->bands[IEEE80211_BAND_5GHZ]. The driver does not support DFS so we
> >> better stay away from these channels, which was your original issue to
> >> start this work if I recall correct :-( Sorry.
> >
> > This is what originally got me looking at the brcmsmac regulatory
> > support, so it would be disappointing if at the end these channels still
> > aren't usable.
>
> Hence me saying sorry.
>
> > My understanding of DFS is pretty rudamentary. Could you explain what
> > support is needed? I do see that mac80211 doesn't really support power
> > measurement requests, but if we can at least stop transmission when
> > radar is present couldn't we still operate on the channels?
>
> The hardware would need to signal the driver that a radar has been detected.

Yes. I was trying to ask (not so clearly it turns out) whether or not
Broadcom hardware can do this.

I note that if I boot into OS X then I can use the DFS channels with
BCM43224. So obviously we should be able to use those frequencies. The
question I'm trying to get an answer to is what's needed in the Linux
driver to be in compliance. I'm planning to spend some time today
reading to better understand DFS in 802.11.


2012-05-26 07:19:41

by Luis R. Rodriguez

[permalink] [raw]
Subject: Re: [RFC PATCH 0/8] brcm80211: smac: rework regulatory support

On Fri, May 25, 2012 at 11:38 PM, Arend van Spriel <[email protected]> wrote:
> On 05/26/2012 12:51 AM, Luis R. Rodriguez wrote:
>>> It took a while. There were some discussions and we agreed that your
>>> > changes establish a better integration with the regulatory framework.
>>> > There are some concerns about the content of the crda database, but that
>>> > is another thing outside the scope of your patches.
>> BTW if you would like to address anything please let me know. If you'd like
>> to review things in private too that's fine, just let me know. I
>> should say that the staging area for the next generation regulatory
>> code is being done through the regulatory simulator:
>>
>> git://github.com/mcgrof/regsim.git
>
> Thanks, Luis. I mainly focused on the crda database and it has a
> relation freqs<->pwr_limit. In our regulatory code we make a distinction
> between 11n and abg as we believe that is necessary.

Atheros had similar poo. When I reviewed the architecture behind it,
it was simply a design consideration, it had nothing to with
regulatory. Nothing at all. In fact, all it did was add an overhead of
data.

> Another example
> would be 20MHz transmission in 40MHz channel.

Same thing here, turns out you can dynamically figure this out based
on the regulatory rules.

> Maybe that is taken into
> account in crda code, but I did not have a close look at it yet.

It is taken into account. In fact 802.11ac and 802.11ad are thing I've
already have considered as well.

> I will have a look at the regsim repository and follow up on that.

Great!

>> Arend, in the future please trim all hunks that are not relevant to
>> your replies, that makes review easier.
>
> Will do.

Thanks,

Luis

2012-05-25 22:34:10

by Arend van Spriel

[permalink] [raw]
Subject: Re: [RFC PATCH 6/8] brcm80211: smac: use mac80211 channel data for tx power limits

On 04/16/2012 10:17 PM, Seth Forshee wrote:
> Currently the limits from the internal X2 domain are used, regardless
> of what regulatory rules are in effect. Instead use the power limits set
> by the higher-level regulatory support.
>
> The rules for the MIMO power limits are still always derived from the
> world domain. Guidance from Broadcom is needed on how these limits
> should be determined for other regulatory domains.

Reviewed-by: Arend Van Spriel <[email protected]>
Reviewed-by: Pieter-Paul Giesberts <[email protected]>
> Signed-off-by: Seth Forshee <[email protected]>

I still have the question on the mimo power limits pending. We can
address it later.

Gr. AvS



2012-05-29 16:47:04

by Arend van Spriel

[permalink] [raw]
Subject: Re: [RFC PATCH 4/8] brcm80211: smac: inform mac80211 of the X2 regulatory domain

On 05/29/2012 03:12 PM, Seth Forshee wrote:
>> The hardware would need to signal the driver that a radar has been detected.
> Yes. I was trying to ask (not so clearly it turns out) whether or not
> Broadcom hardware can do this.

Sure.

> I note that if I boot into OS X then I can use the DFS channels with
> BCM43224. So obviously we should be able to use those frequencies. The
> question I'm trying to get an answer to is what's needed in the Linux
> driver to be in compliance. I'm planning to spend some time today
> reading to better understand DFS in 802.11

True. What I need to verify is whether the ucode for brcmsmac has DFS
enabled or not. I will let you know.

Gr. AvS


2012-05-29 13:03:54

by Arend van Spriel

[permalink] [raw]
Subject: Re: [RFC PATCH 3/8] brcm80211: smac: clean up channel.c

On 05/29/2012 02:46 PM, Seth Forshee wrote:
> On Sun, May 27, 2012 at 01:53:29PM +0200, Arend van Spriel wrote:
>> On 05/26/2012 07:17 PM, Seth Forshee wrote:
>>> On Sat, May 26, 2012 at 12:33:05AM +0200, Arend van Spriel wrote:
>>>> We are not supporting 40MHz right now, but it is on our roadmap. I would
>>>> prefer to keep it, but git can recover it for me when that roadmap item
>>>> is due.
>>>
>>> The argument against keeping it is that it will be utterly broken by all
>>> of the other changes. I could try to rework it along with the rest of
>>> the code I guess, but I'd obviously be unable to test it.
>>>
>>> I'll keep it in if you prefer, but I should probably add a comment
>>> warning that the code needs some attention before it can be used.
>>>
>>>
>>
>> Could you get rid of 40MHz stuff with a separate commit for my
>> convenience when 40MHz is added.
>
> Yes, I'll do that.
>
>

Appreciated.

Gr. AvS


2012-05-31 17:50:04

by Arend van Spriel

[permalink] [raw]
Subject: Re: [RFC PATCH 4/8] brcm80211: smac: inform mac80211 of the X2 regulatory domain

On 05/31/2012 04:46 PM, Seth Forshee wrote:
> So our options seem to be either calling ieee_hw_init() from
> brcms_c_attach() or breaking up brcms_c_attach() into two parts and
> calling ieee_hw_init() in the middle. Or else calling
> brcms_c_regd_init() from brcms_attach() as I have it now. What's your
> preference?

I am not in favor of breaking up the code for this. So leave it as you
have it now.

Gr. AvS


2012-05-25 22:31:54

by Arend van Spriel

[permalink] [raw]
Subject: Re: [RFC PATCH 0/8] brcm80211: smac: rework regulatory support

On 04/16/2012 10:17 PM, Seth Forshee wrote:
> Hi Arnd,

You missed an 'e' ;-)

> Here's the latest update to the brcmsmac regulatory rework that I've
> been working on. I've broken it up into a series of smaller patches,
> cleaned things up, and finished what changes I can with the information
> available to me.

It took a while. There were some discussions and we agreed that your
changes establish a better integration with the regulatory framework.
There are some concerns about the content of the crda database, but that
is another thing outside the scope of your patches.

> I've attempted to maintain the same high-level behavior that the
> brcmsmac internal regulatory support currently enforces.

Appreciated. We can add/change in subsequent patches. I collected review
comments internally including mine. I will provide them in response to
each individual patch.

General comment: you should run 'checkpatch.pl --strict' script over the
patches. I came across several issues that will probably be flagged by it.

Gr. AvS


2012-05-25 22:33:33

by Arend van Spriel

[permalink] [raw]
Subject: Re: [RFC PATCH 4/8] brcm80211: smac: inform mac80211 of the X2 regulatory domain

On 04/16/2012 10:17 PM, Seth Forshee wrote:
> brcmsmac implements enforcement of regulatory constraints internally,
> using a Broadcom-specific world roaming domain named X2. Besides being
> duplication of functionality, this also causes some channels to be
> unnecessarily disabled, as mac80211 is unaware of the X2 domain and thus
> applies the more restrictive default world domain.
>
> This patch is the first step in making brcmsmac cooperate with
> mac80211's regulatory support. X2 is registered as a custom domain with
> mac80211, so that at least both implementations will be enforcing the
> same set of constraints. The internal enforcement of rules is kept for
> now; this will be converted over to relying on mac80211 regulatory
> enforcement in later patches.

Reviewed-by: Arend Van Spriel <[email protected]>
Reviewed-by: Pieter-Paul Giesberts <[email protected]>
> Signed-off-by: Seth Forshee <[email protected]>
> ---
> drivers/net/wireless/brcm80211/brcmsmac/channel.c | 392 +++++++++++---------
> drivers/net/wireless/brcm80211/brcmsmac/channel.h | 2 +
> .../net/wireless/brcm80211/brcmsmac/mac80211_if.c | 2 +
> 3 files changed, 217 insertions(+), 179 deletions(-)
>
> diff --git a/drivers/net/wireless/brcm80211/brcmsmac/channel.c b/drivers/net/wireless/brcm80211/brcmsmac/channel.c
> index 1998c86..fd5b807 100644
> --- a/drivers/net/wireless/brcm80211/brcmsmac/channel.c
> +++ b/drivers/net/wireless/brcm80211/brcmsmac/channel.c
> @@ -15,7 +15,9 @@
> */
>
> #include <linux/types.h>
> +#include <net/cfg80211.h>
> #include <net/mac80211.h>
> +#include <net/regulatory.h>
>
> #include <defs.h>
> #include "pub.h"
> @@ -23,6 +25,7 @@
> #include "main.h"
> #include "stf.h"
> #include "channel.h"
> +#include "mac80211_if.h"
>
> /* QDB() macro takes a dB value and converts to a quarter dB value */
> #define QDB(n) ((n) * BRCMS_TXPWR_DB_FACTOR)
> @@ -108,6 +111,43 @@
> (((c) < 100) ? 2 : \
> (((c) < 149) ? 3 : 4))))
>
> +#define BRCM_2GHZ_2412_2462 REG_RULE(2412-10, 2462+10, 40, 0, 19, 0)
> +#define BRCM_2GHZ_2467_2472 REG_RULE(2467-10, 2472+10, 20, 0, 19, \
> + NL80211_RRF_PASSIVE_SCAN | \
> + NL80211_RRF_NO_IBSS)
> +#define BRCM_2GHZ_2484 REG_RULE(2484-10, 2484+10, 40, 0, 19, \
> + NL80211_RRF_PASSIVE_SCAN | \
> + NL80211_RRF_NO_OFDM)
> +

If channels 12 and 13 are 20MHz only, shouldn't channel 14 above
(2484MHz) be 20MHz as well?

> +#define BRCM_5GHZ_5180_5240 REG_RULE(5180-10, 5240+10, 40, 0, 21, \
> + NL80211_RRF_PASSIVE_SCAN | \
> + NL80211_RRF_NO_IBSS)
> +#define BRCM_5GHZ_5260_5320 REG_RULE(5260-10, 5320+10, 40, 0, 21, \
> + NL80211_RRF_PASSIVE_SCAN | \
> + NL80211_RRF_DFS | \
> + NL80211_RRF_NO_IBSS)
> +#define BRCM_5GHZ_5500_5700 REG_RULE(5500-10, 5700+10, 40, 0, 21, \
> + NL80211_RRF_PASSIVE_SCAN | \
> + NL80211_RRF_DFS | \
> + NL80211_RRF_NO_IBSS)
> +#define BRCM_5GHZ_5745_5825 REG_RULE(5745-10, 5825+10, 40, 0, 21, \
> + NL80211_RRF_PASSIVE_SCAN | \
> + NL80211_RRF_NO_IBSS)
> +
> +static const struct ieee80211_regdomain brcms_regdom_x2 = {
> + .n_reg_rules = 7,
> + .alpha2 = "X2",
> + .reg_rules = {
> + BRCM_2GHZ_2412_2462,
> + BRCM_2GHZ_2467_2472,
> + BRCM_2GHZ_2484,

The X2 domain did not support channel 14 so this is cheating ;-)

> + BRCM_5GHZ_5180_5240,
> + BRCM_5GHZ_5260_5320,
> + BRCM_5GHZ_5500_5700,
> + BRCM_5GHZ_5745_5825,
> + }
> +};
> +
> struct brcms_cm_band {
> /* struct locale_info flags */
> u8 locale_flags;
> @@ -137,14 +177,15 @@ struct country_info {
> const u8 locale_mimo_5G; /* 5G mimo info */
> };
>
> +struct brcms_regd {
> + struct country_info country;
> + const struct ieee80211_regdomain *regdomain;
> +};
> +
> struct brcms_cm_info {
> struct brcms_pub *pub;
> struct brcms_c_info *wlc;
> - char srom_ccode[BRCM_CNTRY_BUF_SZ]; /* Country Code in SROM */
> - uint srom_regrev; /* Regulatory Rev for the SROM ccode */
> - const struct country_info *country; /* current country def */
> - uint regrev; /* current Regulatory Revision */
> - char country_abbrev[BRCM_CNTRY_BUF_SZ]; /* current advertised ccode */
> + const struct brcms_regd *world_regd;
> /* per-band state (one per phy/radio) */
> struct brcms_cm_band bandstate[MAXBANDS];
> /* quiet channels currently for radar sensitivity or 11h support */
> @@ -408,12 +449,12 @@ static const struct locale_mimo_info *g_mimo_5g_table[] = {
> &locale_11n
> };
>
> -static const struct {
> - char abbrev[BRCM_CNTRY_BUF_SZ]; /* country abbreviation */
> - struct country_info country;
> -} cntry_locales[] = {
> +static const struct brcms_regd cntry_locales[] = {
> + /* Worldwide Row 2, must always be at index 0 */

Row is abbreviation for Rest of World, hence RoW. Come to think of it,
this actually makes the term Worldwide a bit redundant.

> {
> - "X2", LOCALES(i, 11, bn, 11n)}, /* Worldwide RoW 2 */
> + .country = LOCALES(i, 11, bn, 11n),
> + .regdomain = &brcms_regdom_x2,
> + },
> };
>
> static const struct locale_info *brcms_c_get_locale_2g(u8 locale_idx)
> @@ -482,93 +523,24 @@ static bool brcms_c_country_valid(const char *ccode)
> return true;
> }
>
> -/* Lookup a country info structure from a null terminated country
> - * abbreviation and regrev directly with no translation.
> - */
> -static const struct country_info *
> -brcms_c_country_lookup_direct(const char *ccode, uint regrev)
> +static const struct brcms_regd *brcms_world_regd(const char *regdom)
> {
> - uint size, i;
> -
> - /* Should just return 0 for single locale driver. */
> - /* Keep it this way in case we add more locales. (for now anyway) */
> -
> - /*
> - * all other country def arrays are for regrev == 0, so if
> - * regrev is non-zero, fail
> - */
> - if (regrev > 0)
> - return NULL;
> -
> - /* find matched table entry from country code */
> - size = ARRAY_SIZE(cntry_locales);
> - for (i = 0; i < size; i++) {
> - if (strcmp(ccode, cntry_locales[i].abbrev) == 0)
> - return &cntry_locales[i].country;
> - }
> - return NULL;
> -}
> + const struct brcms_regd *regd = NULL;
> + int i;
>
> -static const struct country_info *
> -brcms_c_countrycode_map(struct brcms_cm_info *wlc_cm, const char *ccode,
> - char *mapped_ccode, uint *mapped_regrev)
> -{
> - struct brcms_c_info *wlc = wlc_cm->wlc;
> - const struct country_info *country;
> - uint srom_regrev = wlc_cm->srom_regrev;
> - const char *srom_ccode = wlc_cm->srom_ccode;
> -
> - /* check for currently supported ccode size */
> - if (strlen(ccode) > (BRCM_CNTRY_BUF_SZ - 1)) {
> - wiphy_err(wlc->wiphy, "wl%d: %s: ccode \"%s\" too long for "
> - "match\n", wlc->pub->unit, __func__, ccode);
> - return NULL;
> - }
> -
> - /* default mapping is the given ccode and regrev 0 */
> - strncpy(mapped_ccode, ccode, BRCM_CNTRY_BUF_SZ);
> - *mapped_regrev = 0;
> -
> - /* If the desired country code matches the srom country code,
> - * then the mapped country is the srom regulatory rev.
> - * Otherwise look for an aggregate mapping.
> - */
> - if (!strcmp(srom_ccode, ccode)) {
> - *mapped_regrev = srom_regrev;
> - wiphy_err(wlc->wiphy, "srom_code == ccode %s\n", __func__);
> - }
> -
> - /* find the matching built-in country definition */
> - country = brcms_c_country_lookup_direct(mapped_ccode, *mapped_regrev);
> -
> - /* if there is not an exact rev match, default to rev zero */
> - if (country == NULL && *mapped_regrev != 0) {
> - *mapped_regrev = 0;
> - country =
> - brcms_c_country_lookup_direct(mapped_ccode, *mapped_regrev);
> + for (i = 0; i < ARRAY_SIZE(cntry_locales); i++) {
> + if (!strcmp(regdom, cntry_locales[i].regdomain->alpha2)) {
> + regd = &cntry_locales[i];
> + break;
> + }
> }
>
> - return country;
> + return regd;
> }
>
> -/* Lookup a country info structure from a null terminated country code
> - * The lookup is case sensitive.
> - */
> -static const struct country_info *
> -brcms_c_country_lookup(struct brcms_c_info *wlc, const char *ccode)
> +static const struct brcms_regd *brcms_default_world_regd(void)
> {
> - const struct country_info *country;
> - char mapped_ccode[BRCM_CNTRY_BUF_SZ];
> - uint mapped_regrev;
> -
> - /*
> - * map the country code to a built-in country code, regrev, and
> - * country_info struct
> - */
> - country = brcms_c_countrycode_map(wlc->cmi, ccode, mapped_ccode,
> - &mapped_regrev);
> -
> - return country;
> + return &cntry_locales[0];
> }
>
> /*
> @@ -634,12 +606,6 @@ static bool brcms_c_japan_ccode(const char *ccode)
> (ccode[1] == 'P' || (ccode[1] >= '1' && ccode[1] <= '9')));
> }
>
> -/* Returns true if currently set country is Japan or variant */
> -static bool brcms_c_japan(struct brcms_c_info *wlc)
> -{
> - return brcms_c_japan_ccode(wlc->cmi->country_abbrev);
> -}
> -
> static void
> brcms_c_channel_min_txpower_limits_with_local_constraint(
> struct brcms_cm_info *wlc_cm, struct txpwr_limits *txpwr,
> @@ -743,8 +709,8 @@ static void brcms_c_channels_commit(struct brcms_cm_info *wlc_cm)
> mboolset(wlc->pub->radio_disabled, WL_RADIO_COUNTRY_DISABLE);
> wiphy_err(wlc->wiphy, "wl%d: %s: no valid channel for \"%s\" "
> "nbands %d bandlocked %d\n", wlc->pub->unit,
> - __func__, wlc_cm->country_abbrev, wlc->pub->_nbands,
> - wlc->bandlocked);
> + __func__, wlc_cm->world_regd->regdomain->alpha2,
> + wlc->pub->_nbands, wlc->bandlocked);
> } else if (mboolisset(wlc->pub->radio_disabled,
> WL_RADIO_COUNTRY_DISABLE)) {
> /*
> @@ -753,15 +719,6 @@ static void brcms_c_channels_commit(struct brcms_cm_info *wlc_cm)
> */
> mboolclr(wlc->pub->radio_disabled, WL_RADIO_COUNTRY_DISABLE);
> }
> -
> - /*
> - * Now that the country abbreviation is set, if the radio supports 2G,
> - * then set channel 14 restrictions based on the new locale.
> - */
> - if (wlc->pub->_nbands > 1 || wlc->band->bandtype == BRCM_BAND_2G)
> - wlc_phy_chanspec_ch14_widefilter_set(wlc->band->pi,
> - brcms_c_japan(wlc) ? true :
> - false);
> }
>
> static int
> @@ -820,20 +777,13 @@ brcms_c_channels_init(struct brcms_cm_info *wlc_cm,
> * information found with the country code.
> */
> static void
> -brcms_c_set_country_common(struct brcms_cm_info *wlc_cm,
> - const char *country_abbrev,
> - const char *ccode, uint regrev,
> - const struct country_info *country)
> +brcms_c_set_country(struct brcms_cm_info *wlc_cm,
> + const struct brcms_regd *regd)
> {
> + const struct country_info *country = &regd->country;
> const struct locale_info *locale;
> struct brcms_c_info *wlc = wlc_cm->wlc;
>
> - /* save current country state */
> - wlc_cm->country = country;
> -
> - strncpy(wlc_cm->country_abbrev, country_abbrev, BRCM_CNTRY_BUF_SZ - 1);
> - wlc_cm->regrev = regrev;
> -
> if ((wlc->pub->_n_enab & SUPPORT_11N) !=
> wlc->protection->nmode_user)
> brcms_c_set_nmode(wlc);
> @@ -852,59 +802,11 @@ brcms_c_set_country_common(struct brcms_cm_info *wlc_cm,
> return;
> }
>
> -static int
> -brcms_c_set_countrycode_rev(struct brcms_cm_info *wlc_cm,
> - const char *country_abbrev,
> - const char *ccode, int regrev)
> -{
> - const struct country_info *country;
> - char mapped_ccode[BRCM_CNTRY_BUF_SZ];
> - uint mapped_regrev;
> -
> - /* if regrev is -1, lookup the mapped country code,
> - * otherwise use the ccode and regrev directly
> - */
> - if (regrev == -1) {
> - /*
> - * map the country code to a built-in country
> - * code, regrev, and country_info
> - */
> - country =
> - brcms_c_countrycode_map(wlc_cm, ccode, mapped_ccode,
> - &mapped_regrev);
> - } else {
> - /* find the matching built-in country definition */
> - country = brcms_c_country_lookup_direct(ccode, regrev);
> - strncpy(mapped_ccode, ccode, BRCM_CNTRY_BUF_SZ);
> - mapped_regrev = regrev;
> - }
> -
> - if (country == NULL)
> - return -EINVAL;
> -
> - /* set the driver state for the country */
> - brcms_c_set_country_common(wlc_cm, country_abbrev, mapped_ccode,
> - mapped_regrev, country);
> -
> - return 0;
> -}
> -
> -/*
> - * set the driver's current country and regulatory information using
> - * a country code as the source. Lookup built in country information
> - * found with the country code.
> - */
> -static int
> -brcms_c_set_countrycode(struct brcms_cm_info *wlc_cm, const char *ccode)
> -{
> - return brcms_c_set_countrycode_rev(wlc_cm, ccode, ccode, -1);
> -}
> -
> struct brcms_cm_info *brcms_c_channel_mgr_attach(struct brcms_c_info *wlc)
> {
> struct brcms_cm_info *wlc_cm;
> struct brcms_pub *pub = wlc->pub;
> - char *ccode;
> + const char *ccode;
>
> BCMMSG(wlc->wiphy, "wl%d\n", wlc->pub->unit);
>
> @@ -917,17 +819,29 @@ struct brcms_cm_info *brcms_c_channel_mgr_attach(struct brcms_c_info *wlc)
>
> /* store the country code for passing up as a regulatory hint */
> ccode = getvar(wlc->hw->sih, BRCMS_SROM_CCODE);
> - if (ccode && brcms_c_country_valid(ccode))
> - strncpy(wlc->pub->srom_ccode, ccode, BRCM_CNTRY_BUF_SZ - 1);
> + if (ccode) {
> + wlc_cm->world_regd = brcms_world_regd(ccode);
> + if (brcms_c_country_valid(ccode))
> + strncpy(wlc->pub->srom_ccode, ccode,
> + BRCM_CNTRY_BUF_SZ - 1);
> + }
> +
> + /*
> + * If no custom world domain is found in the SROM, use the
> + * default "X2" domain.
> + */
> + if (!wlc_cm->world_regd) {
> + wlc_cm->world_regd = brcms_default_world_regd();
> + ccode = wlc_cm->world_regd->regdomain->alpha2;
> + }
>
> /* save default country for exiting 11d regulatory mode */
> - strncpy(wlc->country_default, "X2", BRCM_CNTRY_BUF_SZ - 1);
> + strncpy(wlc->country_default, ccode, BRCM_CNTRY_BUF_SZ - 1);
>
> /* initialize autocountry_default to driver default */
> - strncpy(wlc->autocountry_default, wlc->country_default,
> - BRCM_CNTRY_BUF_SZ - 1);
> + strncpy(wlc->autocountry_default, ccode, BRCM_CNTRY_BUF_SZ - 1);
>
> - brcms_c_set_countrycode(wlc_cm, wlc->country_default);
> + brcms_c_set_country(wlc_cm, wlc_cm->world_regd);
>
> return wlc_cm;
> }
> @@ -995,13 +909,7 @@ brcms_c_channel_reg_limits(struct brcms_cm_info *wlc_cm, u16 chanspec,
>
> memset(txpwr, 0, sizeof(struct txpwr_limits));
>
> - if (!brcms_c_valid_chanspec_db(wlc_cm, chanspec)) {
> - country = brcms_c_country_lookup(wlc, wlc->autocountry_default);
> - if (country == NULL)
> - return;
> - } else {
> - country = wlc_cm->country;
> - }
> + country = &wlc_cm->world_regd->country;
>
> chan = CHSPEC_CHANNEL(chanspec);
> band = wlc->bandstate[chspec_bandunit(chanspec)];
> @@ -1253,3 +1161,129 @@ bool brcms_c_valid_chanspec_db(struct brcms_cm_info *wlc_cm, u16 chspec)
> {
> return brcms_c_valid_chanspec_ext(wlc_cm, chspec, true);
> }
> +
> +bool brcms_is_radar_freq(u16 center_freq)
> +{
> + return center_freq >= 5260 && center_freq <= 5700;

You can avoid this code if you/we do not add the channels to
wiphy->bands[IEEE80211_BAND_5GHZ]. The driver does not support DFS so we
better stay away from these channels, which was your original issue to
start this work if I recall correct :-( Sorry.

> +}
> +
> +static void brcms_reg_apply_radar_flags(struct wiphy *wiphy)
> +{
> + struct ieee80211_supported_band *sband;
> + struct ieee80211_channel *ch;
> + int i;
> +
> + sband = wiphy->bands[IEEE80211_BAND_5GHZ];
> + if (!sband)
> + return;
> +
> + for (i = 0; i < sband->n_channels; i++) {
> + ch = &sband->channels[i];
> +
> + if (!brcms_is_radar_freq(ch->center_freq))
> + continue;
> +
> + /*
> + * All channels in this range should be passive and have
> + * DFS enabled.
> + */
> + if (!(ch->flags & IEEE80211_CHAN_DISABLED))
> + ch->flags |= IEEE80211_CHAN_RADAR |
> + IEEE80211_CHAN_NO_IBSS |
> + IEEE80211_CHAN_PASSIVE_SCAN;
> + }
> +}
> +
> +static void
> +brcms_reg_apply_beaconing_flags(struct wiphy *wiphy,
> + enum nl80211_reg_initiator initiator)
> +{
> + struct ieee80211_supported_band *sband;
> + struct ieee80211_channel *ch;
> + const struct ieee80211_reg_rule *reg_rule;
> + int band, i, ret;
> +
> + for (band = 0; band < IEEE80211_NUM_BANDS; band++) {
> + sband = wiphy->bands[band];
> + if (!sband)
> + continue;
> +
> + for (i = 0; i < sband->n_channels; i++) {
> + ch = &sband->channels[i];
> +
> + if (brcms_is_radar_freq(ch->center_freq) ||
> + (ch->flags & IEEE80211_CHAN_RADAR))
> + continue;
> +
> + if (initiator == NL80211_REGDOM_SET_BY_COUNTRY_IE) {
> + ret = freq_reg_info(wiphy, ch->center_freq,
> + 0, &reg_rule);
> + if (ret)
> + continue;
> +
> + if (!(reg_rule->flags & NL80211_RRF_NO_IBSS))
> + ch->flags &= ~IEEE80211_CHAN_NO_IBSS;
> + if (!(reg_rule->flags & NL80211_RRF_PASSIVE_SCAN))
> + ch->flags &= ~IEEE80211_CHAN_PASSIVE_SCAN;
> + } else {
> + if (ch->beacon_found)

can save one indent when using else if () immediately here.

> + ch->flags &= ~(IEEE80211_CHAN_NO_IBSS |
> + IEEE80211_CHAN_PASSIVE_SCAN);
> + }
> + }
> + }
> +}
> +
> +static int brcms_reg_notifier(struct wiphy *wiphy,
> + struct regulatory_request *request)
> +{
> + struct ieee80211_hw *hw = wiphy_to_ieee80211_hw(wiphy);
> + struct brcms_info *wl = hw->priv;
> + struct brcms_c_info *wlc = wl->wlc;
> +
> + brcms_reg_apply_radar_flags(wiphy);
> +
> + if (request && request->initiator == NL80211_REGDOM_SET_BY_COUNTRY_IE)
> + brcms_reg_apply_beaconing_flags(wiphy, request->initiator);
> +
> + if (wlc->pub->_nbands > 1 || wlc->band->bandtype == BRCM_BAND_2G)
> + wlc_phy_chanspec_ch14_widefilter_set(wlc->band->pi,
> + brcms_c_japan_ccode(request->alpha2));
> +
> + return 0;
> +}
> +
> +void brcms_c_regd_init(struct brcms_c_info *wlc)
> +{
> + struct wiphy *wiphy = wlc->wiphy;
> + const struct brcms_regd *regd = wlc->cmi->world_regd;
> + struct ieee80211_supported_band *sband;
> + struct ieee80211_channel *ch;
> + struct brcms_chanvec sup_chan;
> + struct brcms_band *band;
> + int band_idx, i;
> +
> + /* Disable any channels not supported by the phy */
> + for (band_idx = 0; band_idx < IEEE80211_NUM_BANDS; band_idx++) {
> + if (band_idx == IEEE80211_BAND_2GHZ)
> + band = wlc->bandstate[BAND_2G_INDEX];
> + else
> + band = wlc->bandstate[BAND_5G_INDEX];
> + wlc_phy_chanspec_band_validch(band->pi, band->bandtype,
> + &sup_chan);
> +
> + sband = wiphy->bands[band_idx];
> + for (i = 0; i < sband->n_channels; i++) {
> + ch = &sband->channels[i];
> + if (!isset(sup_chan.vec, ch->hw_value))
> + ch->flags |= IEEE80211_CHAN_DISABLED;
> + }
> + }
> +
> + wlc->wiphy->reg_notifier = brcms_reg_notifier;
> + wlc->wiphy->flags |= WIPHY_FLAG_CUSTOM_REGULATORY |
> + WIPHY_FLAG_STRICT_REGULATORY;
> + wiphy_apply_custom_regulatory(wlc->wiphy, regd->regdomain);
> + brcms_reg_apply_radar_flags(wiphy);
> + brcms_reg_apply_beaconing_flags(wiphy, NL80211_REGDOM_SET_BY_DRIVER);
> +}
> diff --git a/drivers/net/wireless/brcm80211/brcmsmac/channel.h b/drivers/net/wireless/brcm80211/brcmsmac/channel.h
> index 808cb4f..dbe60ef 100644
> --- a/drivers/net/wireless/brcm80211/brcmsmac/channel.h
> +++ b/drivers/net/wireless/brcm80211/brcmsmac/channel.h
> @@ -50,4 +50,6 @@ extern void brcms_c_channel_set_chanspec(struct brcms_cm_info *wlc_cm,
> u16 chanspec,
> u8 local_constraint_qdbm);
>
> +extern void brcms_c_regd_init(struct brcms_c_info *wlc);
> +
> #endif /* _WLC_CHANNEL_H */
> diff --git a/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c b/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c
> index aa15558..f26e93c 100644
> --- a/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c
> +++ b/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c
> @@ -1059,6 +1059,8 @@ static struct brcms_info *brcms_attach(struct bcma_device *pdev)
> goto fail;
> }
>
> + brcms_c_regd_init(wl->wlc);
> +

can this be moved in brcms_c_channel_mgr_attach()?

> memcpy(perm, &wl->pub->cur_etheraddr, ETH_ALEN);
> if (WARN_ON(!is_valid_ether_addr(perm)))
> goto fail;

Gr. AvS


2012-05-25 22:51:59

by Luis R. Rodriguez

[permalink] [raw]
Subject: Re: [RFC PATCH 0/8] brcm80211: smac: rework regulatory support

On Fri, May 25, 2012 at 3:31 PM, Arend van Spriel <[email protected]> wrote:
> On 04/16/2012 10:17 PM, Seth Forshee wrote:
>> Hi Arnd,
>
> You missed an 'e' ;-)
>
>> Here's the latest update to the brcmsmac regulatory rework that I've
>> been working on. I've broken it up into a series of smaller patches,
>> cleaned things up, and finished what changes I can with the information
>> available to me.
>
> It took a while. There were some discussions and we agreed that your
> changes establish a better integration with the regulatory framework.
> There are some concerns about the content of the crda database, but that
> is another thing outside the scope of your patches.

BTW if you would like to address anything please let me know. If you'd like
to review things in private too that's fine, just let me know. I
should say that the staging area for the next generation regulatory
code is being done through the regulatory simulator:

git://github.com/mcgrof/regsim.git

If you have any early stage idea / changes this is where we should be
reviewing / strategizing on them. I should note that this does let you
use the code for regulatory anywhere, the kernel, firmware, whatever.
Due to synch issues with host / firmware database though my
recommendation is obviously to trust the host with the reg data,
unless you resolve the synch issues.

I suppose one way to deal with synch issues as a temporary stage
(before removing firmware reg stuff) is to send the data structure of
the regdomain to firmware so it can base prepare itself / not have any
issues.

>> I've attempted to maintain the same high-level behavior that the
>> brcmsmac internal regulatory support currently enforces.
>
> Appreciated. We can add/change in subsequent patches. I collected review
> comments internally including mine. I will provide them in response to
> each individual patch.
>
> General comment: you should run 'checkpatch.pl --strict' script over the
> patches. I came across several issues that will probably be flagged by it.

Arend, in the future please trim all hunks that are not relevant to
your replies, that makes review easier.

Luis

2012-05-27 12:18:27

by Arend van Spriel

[permalink] [raw]
Subject: Re: [RFC PATCH 5/8] brcm80211: smac: enable/disable radio on regulatory updates

On 05/26/2012 07:18 PM, Seth Forshee wrote:
>> I think we need to validate the channels against our phy as well. See
>> > brcms_c_channels_init().
> I disable channels not supported by the phy in brcms_c_regd_init(), so
> it's not necessary to check it again here.
>

Great. Missed that.

Gr. AvS


2012-05-01 12:14:26

by Arend van Spriel

[permalink] [raw]
Subject: Re: [RFC PATCH 0/8] brcm80211: smac: rework regulatory support

On 04/30/2012 07:12 PM, Seth Forshee wrote:
> On Thu, Apr 19, 2012 at 09:31:02PM +0200, Arend van Spriel wrote:
>> On 04/16/2012 10:17 PM, Seth Forshee wrote:
>>> Hi Arnd,
>>>
>>> Here's the latest update to the brcmsmac regulatory rework that I've
>>> been working on. I've broken it up into a series of smaller patches,
>>> cleaned things up, and finished what changes I can with the information
>>> available to me.
>>>
>>
>> Hi Seth,
>>
>> Just to indicate what we are doing with regard to your patches. I
>> organized a review internally for these patches. Waiting for one
>> more to sent back comments. Just pinged him today. So end of this
>> week I can probably sent you the collected comments.
>
> Hi Arend,
>
> Any feedback yet from your internal review/testing?
>
> Thanks,
> Seth
>

Hi Seth,

I was about to respond to each patch with collected comments. However,
one of the comments mentioned I should involve compliance staff on these
changes so I have to explain the general ideas behind your patches to
them. Sorry for the delay.

Gr. AvS


2012-05-26 17:17:33

by Seth Forshee

[permalink] [raw]
Subject: Re: [RFC PATCH 0/8] brcm80211: smac: rework regulatory support

On Sat, May 26, 2012 at 12:31:36AM +0200, Arend van Spriel wrote:
> On 04/16/2012 10:17 PM, Seth Forshee wrote:
> > Hi Arnd,
>
> You missed an 'e' ;-)

Oops! My apologies :)

> > Here's the latest update to the brcmsmac regulatory rework that I've
> > been working on. I've broken it up into a series of smaller patches,
> > cleaned things up, and finished what changes I can with the information
> > available to me.
>
> It took a while. There were some discussions and we agreed that your
> changes establish a better integration with the regulatory framework.
> There are some concerns about the content of the crda database, but that
> is another thing outside the scope of your patches.

Great!

> > I've attempted to maintain the same high-level behavior that the
> > brcmsmac internal regulatory support currently enforces.
>
> Appreciated. We can add/change in subsequent patches. I collected review
> comments internally including mine. I will provide them in response to
> each individual patch.

I've looked over the comments, and I agree with most of them. I'll
respond to each individually.

> General comment: you should run 'checkpatch.pl --strict' script over the
> patches. I came across several issues that will probably be flagged by it.

Yeah, I didn't bother with it for the RFC patches since I just wanted to
ensure that I had buy-in from you guys on the changes in general. I've
already got a few things cleaned up locally, and I'll run everything
through checkpatch before I send them again.

Thanks,
Seth


2012-05-26 17:18:20

by Seth Forshee

[permalink] [raw]
Subject: Re: [RFC PATCH 5/8] brcm80211: smac: enable/disable radio on regulatory updates

On Sat, May 26, 2012 at 12:33:31AM +0200, Arend van Spriel wrote:
> > @@ -1240,12 +1199,37 @@ static int brcms_reg_notifier(struct wiphy *wiphy,
> > struct ieee80211_hw *hw = wiphy_to_ieee80211_hw(wiphy);
> > struct brcms_info *wl = hw->priv;
> > struct brcms_c_info *wlc = wl->wlc;
> > + struct ieee80211_supported_band *sband;
> > + struct ieee80211_channel *ch;
> > + int band, i, n_channels = 0;
> >
> > brcms_reg_apply_radar_flags(wiphy);
> >
> > if (request && request->initiator == NL80211_REGDOM_SET_BY_COUNTRY_IE)
> > brcms_reg_apply_beaconing_flags(wiphy, request->initiator);
> >
> > + /* Disable radio if all channels disallowed by regulatory */
>
> I think we need to validate the channels against our phy as well. See
> brcms_c_channels_init().

I disable channels not supported by the phy in brcms_c_regd_init(), so
it's not necessary to check it again here.

> > + for (band = 0; band < IEEE80211_NUM_BANDS; band++) {
> > + sband = wiphy->bands[band];
> > + if (!sband)
> > + continue;
> > +
> > + for (i = 0; i < sband->n_channels; i++) {
> > + ch = &sband->channels[i];
> > +
> > + if (!(ch->flags & IEEE80211_CHAN_DISABLED))
> > + n_channels++;
>
> could break here when a valid channel is found.

Ack, I'll do that.


2012-05-01 16:12:47

by Seth Forshee

[permalink] [raw]
Subject: Re: [RFC PATCH 0/8] brcm80211: smac: rework regulatory support

On Tue, May 01, 2012 at 02:13:42PM +0200, Arend van Spriel wrote:
> I was about to respond to each patch with collected comments.
> However, one of the comments mentioned I should involve compliance
> staff on these changes so I have to explain the general ideas behind
> your patches to them. Sorry for the delay.

Thanks for the update. Let me know if I can be of any help.

Seth


2012-05-25 22:33:45

by Arend van Spriel

[permalink] [raw]
Subject: Re: [RFC PATCH 5/8] brcm80211: smac: enable/disable radio on regulatory updates

On 04/16/2012 10:17 PM, Seth Forshee wrote:
> Currently the radio disable state is only updated during initialization,
> and it's only checked against the internal world domain. This is
> unnecessary, as there are always valid channels against this domain.
> Instead, check whether any channels are enabled in the regulatory
> notifier and update the radio state accordingly.

Reviewed-by: Arend Van Spriel <[email protected]>
Reviewed-by: Pieter-Paul Giesberts <[email protected]>
> Signed-off-by: Seth Forshee <[email protected]>
> ---
> drivers/net/wireless/brcm80211/brcmsmac/channel.c | 66 ++++++++-------------
> 1 file changed, 25 insertions(+), 41 deletions(-)
>
> diff --git a/drivers/net/wireless/brcm80211/brcmsmac/channel.c b/drivers/net/wireless/brcm80211/brcmsmac/channel.c
> index fd5b807..590e8c1 100644
> --- a/drivers/net/wireless/brcm80211/brcmsmac/channel.c
> +++ b/drivers/net/wireless/brcm80211/brcmsmac/channel.c
> @@ -681,46 +681,6 @@ brcms_c_channel_min_txpower_limits_with_local_constraint(
>
> }
>
> -/* Update the radio state (enable/disable) and tx power targets
> - * based on a new set of channel/regulatory information
> - */
> -static void brcms_c_channels_commit(struct brcms_cm_info *wlc_cm)
> -{
> - struct brcms_c_info *wlc = wlc_cm->wlc;
> - uint chan;
> -
> - /* search for the existence of any valid channel */
> - for (chan = 0; chan < MAXCHANNEL; chan++) {
> - if (brcms_c_valid_channel20_db(wlc->cmi, chan))
> - break;
> - }
> - if (chan == MAXCHANNEL)
> - chan = INVCHANNEL;
> -
> - /*
> - * based on the channel search above, set or
> - * clear WL_RADIO_COUNTRY_DISABLE.
> - */
> - if (chan == INVCHANNEL) {
> - /*
> - * country/locale with no valid channels, set
> - * the radio disable bit
> - */
> - mboolset(wlc->pub->radio_disabled, WL_RADIO_COUNTRY_DISABLE);
> - wiphy_err(wlc->wiphy, "wl%d: %s: no valid channel for \"%s\" "
> - "nbands %d bandlocked %d\n", wlc->pub->unit,
> - __func__, wlc_cm->world_regd->regdomain->alpha2,
> - wlc->pub->_nbands, wlc->bandlocked);
> - } else if (mboolisset(wlc->pub->radio_disabled,
> - WL_RADIO_COUNTRY_DISABLE)) {
> - /*
> - * country/locale with valid channel, clear
> - * the radio disable bit
> - */
> - mboolclr(wlc->pub->radio_disabled, WL_RADIO_COUNTRY_DISABLE);
> - }
> -}
> -
> static int
> brcms_c_channels_init(struct brcms_cm_info *wlc_cm,
> const struct country_info *country)
> @@ -766,7 +726,6 @@ brcms_c_channels_init(struct brcms_cm_info *wlc_cm,
> }
>
> brcms_c_quiet_channels_reset(wlc_cm);
> - brcms_c_channels_commit(wlc_cm);
>
> return 0;
> }
> @@ -1240,12 +1199,37 @@ static int brcms_reg_notifier(struct wiphy *wiphy,
> struct ieee80211_hw *hw = wiphy_to_ieee80211_hw(wiphy);
> struct brcms_info *wl = hw->priv;
> struct brcms_c_info *wlc = wl->wlc;
> + struct ieee80211_supported_band *sband;
> + struct ieee80211_channel *ch;
> + int band, i, n_channels = 0;
>
> brcms_reg_apply_radar_flags(wiphy);
>
> if (request && request->initiator == NL80211_REGDOM_SET_BY_COUNTRY_IE)
> brcms_reg_apply_beaconing_flags(wiphy, request->initiator);
>
> + /* Disable radio if all channels disallowed by regulatory */

I think we need to validate the channels against our phy as well. See
brcms_c_channels_init().

> + for (band = 0; band < IEEE80211_NUM_BANDS; band++) {
> + sband = wiphy->bands[band];
> + if (!sband)
> + continue;
> +
> + for (i = 0; i < sband->n_channels; i++) {
> + ch = &sband->channels[i];
> +
> + if (!(ch->flags & IEEE80211_CHAN_DISABLED))
> + n_channels++;

could break here when a valid channel is found.

> + }
> + }
> +
> + if (n_channels == 0) {
> + mboolset(wlc->pub->radio_disabled, WL_RADIO_COUNTRY_DISABLE);
> + wiphy_err(wlc->wiphy, "wl%d: %s: no valid channel for \"%s\"\n",
> + wlc->pub->unit, __func__, request->alpha2);
> + } else {
> + mboolclr(wlc->pub->radio_disabled, WL_RADIO_COUNTRY_DISABLE);
> + }
> +
> if (wlc->pub->_nbands > 1 || wlc->band->bandtype == BRCM_BAND_2G)
> wlc_phy_chanspec_ch14_widefilter_set(wlc->band->pi,
> brcms_c_japan_ccode(request->alpha2));

Gr. AvS


2012-05-25 22:32:29

by Arend van Spriel

[permalink] [raw]
Subject: Re: [RFC PATCH 1/8] brcm80211: smac: don't set up tx power limits during initialization

On 04/16/2012 10:17 PM, Seth Forshee wrote:
> This code is unnecessary, and in fact it's never executed because the
> interface is never up when brcms_c_channels_commit() is called. Removing
> it helps simplify the implementation of proper regulatory support.

Reviewed-by: Arend Van Spriel <[email protected]>
Reviewed-by: Pieter-Paul Giesberts <[email protected]>
Reviewed-by: Brett Rudley <[email protected]>
> Signed-off-by: Seth Forshee <[email protected]>

No comments on this patch.

Gr. AvS


2012-05-25 22:32:49

by Arend van Spriel

[permalink] [raw]
Subject: Re: [RFC PATCH 2/8] brcm80211: smac: always set channel specified by mac80211

On 04/16/2012 10:17 PM, Seth Forshee wrote:
> In some situations brcmsmac is choosing a channel internally. This makes
> it difficult at times to know what channel to use for enforcing
> regulatory constraints, so instead always use the channel from the
> mac80211 configuration.

Reviewed-by: Arend Van Spriel <[email protected]>
Reviewed-by: Pieter-Paul Giesberts <[email protected]>
> Signed-off-by: Seth Forshee <[email protected]>

No comments here.

Gr. AvS



2012-05-27 11:53:45

by Arend van Spriel

[permalink] [raw]
Subject: Re: [RFC PATCH 3/8] brcm80211: smac: clean up channel.c

On 05/26/2012 07:17 PM, Seth Forshee wrote:
> On Sat, May 26, 2012 at 12:33:05AM +0200, Arend van Spriel wrote:
>> We are not supporting 40MHz right now, but it is on our roadmap. I would
>> prefer to keep it, but git can recover it for me when that roadmap item
>> is due.
>
> The argument against keeping it is that it will be utterly broken by all
> of the other changes. I could try to rework it along with the rest of
> the code I guess, but I'd obviously be unable to test it.
>
> I'll keep it in if you prefer, but I should probably add a comment
> warning that the code needs some attention before it can be used.
>
>

Could you get rid of 40MHz stuff with a separate commit for my
convenience when 40MHz is added.

Gr. AvS


2012-05-27 11:51:45

by Arend van Spriel

[permalink] [raw]
Subject: Re: [RFC PATCH 3/8] brcm80211: smac: clean up channel.c

On 05/26/2012 07:17 PM, Seth Forshee wrote:
> On Sat, May 26, 2012 at 12:33:05AM +0200, Arend van Spriel wrote:
>> We are not supporting 40MHz right now, but it is on our roadmap. I would
>> prefer to keep it, but git can recover it for me when that roadmap item
>> is due.
>
> The argument against keeping it is that it will be utterly broken by all
> of the other changes. I could try to rework it along with the rest of
> the code I guess, but I'd obviously be unable to test it.
>
> I'll keep it in if you prefer, but I should probably add a comment
> warning that the code needs some attention before it can be used.

Rethinking it I propose to get rid of it. 40MHz support is not complete
throughout the driver so it is not worth to keep this.

Gr. AvS


2012-05-29 12:46:53

by Seth Forshee

[permalink] [raw]
Subject: Re: [RFC PATCH 3/8] brcm80211: smac: clean up channel.c

On Sun, May 27, 2012 at 01:53:29PM +0200, Arend van Spriel wrote:
> On 05/26/2012 07:17 PM, Seth Forshee wrote:
> > On Sat, May 26, 2012 at 12:33:05AM +0200, Arend van Spriel wrote:
> >> We are not supporting 40MHz right now, but it is on our roadmap. I would
> >> prefer to keep it, but git can recover it for me when that roadmap item
> >> is due.
> >
> > The argument against keeping it is that it will be utterly broken by all
> > of the other changes. I could try to rework it along with the rest of
> > the code I guess, but I'd obviously be unable to test it.
> >
> > I'll keep it in if you prefer, but I should probably add a comment
> > warning that the code needs some attention before it can be used.
> >
> >
>
> Could you get rid of 40MHz stuff with a separate commit for my
> convenience when 40MHz is added.

Yes, I'll do that.


2012-05-26 17:18:04

by Seth Forshee

[permalink] [raw]
Subject: Re: [RFC PATCH 4/8] brcm80211: smac: inform mac80211 of the X2 regulatory domain

On Sat, May 26, 2012 at 12:33:15AM +0200, Arend van Spriel wrote:
> > +#define BRCM_2GHZ_2412_2462 REG_RULE(2412-10, 2462+10, 40, 0, 19, 0)
> > +#define BRCM_2GHZ_2467_2472 REG_RULE(2467-10, 2472+10, 20, 0, 19, \
> > + NL80211_RRF_PASSIVE_SCAN | \
> > + NL80211_RRF_NO_IBSS)
> > +#define BRCM_2GHZ_2484 REG_RULE(2484-10, 2484+10, 40, 0, 19, \
> > + NL80211_RRF_PASSIVE_SCAN | \
> > + NL80211_RRF_NO_OFDM)
> > +
>
> If channels 12 and 13 are 20MHz only, shouldn't channel 14 above
> (2484MHz) be 20MHz as well?

Heh, good point. I'm trying to remember why I made 12 and 13 20MHz only
though; maybe that's a mistake. Is there any reason why they couldn't
all be 40MHz?

> > +static const struct ieee80211_regdomain brcms_regdom_x2 = {
> > + .n_reg_rules = 7,
> > + .alpha2 = "X2",
> > + .reg_rules = {
> > + BRCM_2GHZ_2412_2462,
> > + BRCM_2GHZ_2467_2472,
> > + BRCM_2GHZ_2484,
>
> The X2 domain did not support channel 14 so this is cheating ;-)

Yep, my mistake. I'll remove it.

> > + /* Worldwide Row 2, must always be at index 0 */
>
> Row is abbreviation for Rest of World, hence RoW. Come to think of it,
> this actually makes the term Worldwide a bit redundant.

I'll fix it.

> > +bool brcms_is_radar_freq(u16 center_freq)
> > +{
> > + return center_freq >= 5260 && center_freq <= 5700;
>
> You can avoid this code if you/we do not add the channels to
> wiphy->bands[IEEE80211_BAND_5GHZ]. The driver does not support DFS so we
> better stay away from these channels, which was your original issue to
> start this work if I recall correct :-( Sorry.

This is what originally got me looking at the brcmsmac regulatory
support, so it would be disappointing if at the end these channels still
aren't usable.

My understanding of DFS is pretty rudamentary. Could you explain what
support is needed? I do see that mac80211 doesn't really support power
measurement requests, but if we can at least stop transmission when
radar is present couldn't we still operate on the channels?

Luis, any insight you can offer on the subject would be appreciated.

> > + } else {
> > + if (ch->beacon_found)
>
> can save one indent when using else if () immediately here.

I'll change this.

> > diff --git a/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c b/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c
> > index aa15558..f26e93c 100644
> > --- a/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c
> > +++ b/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c
> > @@ -1059,6 +1059,8 @@ static struct brcms_info *brcms_attach(struct bcma_device *pdev)
> > goto fail;
> > }
> >
> > + brcms_c_regd_init(wl->wlc);
> > +
>
> can this be moved in brcms_c_channel_mgr_attach()?

Not without rearranging the initialization, as brcms_c_regd_init() must
be called after wiphy->bands has been set up. I don't see any reason why
setting up the bands couldn't be moved to before channel_mgr_attach()
though, and in that case regd_init() could be moved into
channel_mgr_attach().


2012-05-25 22:34:10

by Arend van Spriel

[permalink] [raw]
Subject: Re: [RFC PATCH 7/8] brcm80211: smac: don't validate channels against internal regulatory data

On 04/16/2012 10:17 PM, Seth Forshee wrote:
> The core regulatory support will disable channels not allowed by
> regulatory rules, so brcmsmac doesn't need to duplicate it.

Reviewed-by: Arend Van Spriel <[email protected]>
Reviewed-by: Pieter-Paul Giesberts <[email protected]>
> Signed-off-by: Seth Forshee <[email protected]>

No comments.

Gr. AvS



2012-05-31 14:46:48

by Seth Forshee

[permalink] [raw]
Subject: Re: [RFC PATCH 4/8] brcm80211: smac: inform mac80211 of the X2 regulatory domain

On Sun, May 27, 2012 at 02:17:03PM +0200, Arend van Spriel wrote:
> >> can this be moved in brcms_c_channel_mgr_attach()?
> >
> > Not without rearranging the initialization, as brcms_c_regd_init() must
> > be called after wiphy->bands has been set up. I don't see any reason why
> > setting up the bands couldn't be moved to before channel_mgr_attach()
> > though, and in that case regd_init() could be moved into
> > channel_mgr_attach().
>
> Please do. I prefer to keep regd_init() local to channel.c.

Further inspection revealed dependencies here that I missed the first
time. ieee_hw_rate_init() relies on a couple of things done in
brcms_c_attach(), which is calling the channel_mgr_attach() function. As
far as I can tell we could still run ieee_hw_init() before
channel_mgr_attach(), but we need the first half of brcms_c_attach() to
run first.

So our options seem to be either calling ieee_hw_init() from
brcms_c_attach() or breaking up brcms_c_attach() into two parts and
calling ieee_hw_init() in the middle. Or else calling
brcms_c_regd_init() from brcms_attach() as I have it now. What's your
preference?

Thanks,
Seth


2012-05-25 22:34:54

by Arend van Spriel

[permalink] [raw]
Subject: Re: [RFC PATCH 8/8] brcm80211: smac: use current regulatory domain when checking whether OFDM is allowed

On 04/16/2012 10:17 PM, Seth Forshee wrote:
> The brcmsmac internal regulatory data is being used to determine whether
> OFDM should be allowed, and this is only done once during
> initialization. To be effective this needs to be checked against
> mac80211's regulatory rules for the current channel.

Reviewed-by: Arend Van Spriel <[email protected]>
Reviewed-by: Pieter-Paul Giesberts <[email protected]>
> Signed-off-by: Seth Forshee <[email protected]>
> ---

No comments here.

Gr. AvS



2012-06-07 18:18:15

by Luis R. Rodriguez

[permalink] [raw]
Subject: Re: [RFC PATCH 4/8] brcm80211: smac: inform mac80211 of the X2 regulatory domain

On Sat, May 26, 2012 at 12:18:00PM -0500, Seth Forshee wrote:
> My understanding of DFS is pretty rudamentary. Could you explain what
> support is needed? I do see that mac80211 doesn't really support power
> measurement requests, but if we can at least stop transmission when
> radar is present couldn't we still operate on the channels?
>
> Luis, any insight you can offer on the subject would be appreciated.

You can forget about DFS master support at this point. DFS client mode
is handled by mac80211 though.

Luis