Commit 0390bf7a authored by Roland Vossen's avatar Roland Vossen Committed by Greg Kroah-Hartman

staging: brcm80211: removed static function declarations in channel.c

Reported-by: default avatarJohannes Berg <johannes@sipsolutions.net>
Signed-off-by: default avatarRoland Vossen <rvossen@broadcom.com>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@suse.de>
parent d5adafb0
......@@ -29,6 +29,53 @@
brcms_c_valid_channel20_in_band((wlc)->cmi, bandunit, val)
#define VALID_CHANNEL20(wlc, val) brcms_c_valid_channel20((wlc)->cmi, val)
/* 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_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
struct brcms_cm_band {
/* struct locale_info flags */
u8 locale_flags;
......@@ -57,58 +104,6 @@ struct brcms_cm_info {
struct brcms_chanvec quiet_channels;
};
static int brcms_c_channels_init(struct brcms_cm_info *wlc_cm,
const struct country_info *country);
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);
static int brcms_c_set_countrycode(struct brcms_cm_info *wlc_cm,
const char *ccode);
static int brcms_c_set_countrycode_rev(struct brcms_cm_info *wlc_cm,
const char *country_abbrev,
const char *ccode, int regrev);
static int brcms_c_country_aggregate_map(struct brcms_cm_info *wlc_cm,
const char *ccode,
char *mapped_ccode, uint *mapped_regrev);
static const struct country_info *
brcms_c_country_lookup_direct(const char *ccode, uint regrev);
static const struct country_info *
brcms_c_countrycode_map(struct brcms_cm_info *wlc_cm,
const char *ccode, char *mapped_ccode,
uint *mapped_regrev);
static void brcms_c_channels_commit(struct brcms_cm_info *wlc_cm);
static void brcms_c_quiet_channels_reset(struct brcms_cm_info *wlc_cm);
static bool brcms_c_quiet_chanspec(struct brcms_cm_info *wlc_cm,
u16 chspec);
static bool brcms_c_valid_channel20_db(struct brcms_cm_info *wlc_cm, uint val);
static bool brcms_c_valid_channel20_in_band(struct brcms_cm_info *wlc_cm,
uint bandunit, uint val);
static bool brcms_c_valid_channel20(struct brcms_cm_info *wlc_cm, uint val);
static const struct country_info *
brcms_c_country_lookup(struct brcms_c_info *wlc, const char *ccode);
static void brcms_c_locale_get_channels(const struct locale_info *locale,
struct brcms_chanvec *valid_channels);
static const struct locale_info *brcms_c_get_locale_2g(u8 locale_idx);
static const struct locale_info *brcms_c_get_locale_5g(u8 locale_idx);
static bool brcms_c_japan(struct brcms_c_info *wlc);
static bool brcms_c_japan_ccode(const char *ccode);
static void brcms_c_channel_min_txpower_limits_with_local_constraint(
struct brcms_cm_info *wlc_cm, struct txpwr_limits *txpwr,
u8 local_constraint_qdbm);
static void brcms_c_locale_add_channels(struct brcms_chanvec *target,
const struct brcms_chanvec *channels);
static const struct locale_mimo_info *brcms_c_get_mimo_2g(u8 locale_idx);
static const struct locale_mimo_info *brcms_c_get_mimo_5g(u8 locale_idx);
/* QDB() macro takes a dB value and converts to a quarter dB value */
#define QDB(n) ((n) * BRCMS_TXPWR_DB_FACTOR)
/* Regulatory Matrix Spreadsheet (CLM) MIMO v3.7.9 */
/*
......@@ -200,50 +195,6 @@ static const struct brcms_chanvec restricted_set_12_13_14 = {
0x00, 0x00, 0x00, 0x00}
};
#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_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
/* global memory to provide working buffer for expanded locale */
static const struct brcms_chanvec *g_table_radar_set[] = {
......@@ -612,316 +563,249 @@ static const struct locale_mimo_info *brcms_c_get_mimo_5g(u8 locale_idx)
return g_mimo_5g_table[locale_idx];
}
struct brcms_cm_info *brcms_c_channel_mgr_attach(struct brcms_c_info *wlc)
static int
brcms_c_country_aggregate_map(struct brcms_cm_info *wlc_cm, const char *ccode,
char *mapped_ccode, uint *mapped_regrev)
{
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;
BCMMSG(wlc->wiphy, "wl%d\n", wlc->pub->unit);
return false;
}
wlc_cm = kzalloc(sizeof(struct brcms_cm_info), GFP_ATOMIC);
if (wlc_cm == NULL) {
wiphy_err(wlc->wiphy, "wl%d: %s: out of memory", pub->unit,
__func__);
return NULL;
}
wlc_cm->pub = pub;
wlc_cm->wlc = wlc;
wlc->cmi = wlc_cm;
/* 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)
{
uint size, i;
/* store the country code for passing up as a regulatory hint */
ccode = getvar(wlc->pub->vars, "ccode");
if (ccode)
strncpy(wlc->pub->srom_ccode, ccode, BRCM_CNTRY_BUF_SZ - 1);
/* Should just return 0 for single locale driver. */
/* Keep it this way in case we add more locales. (for now anyway) */
/*
* internal country information which must match
* regulatory constraints in firmware
* all other country def arrays are for regrev == 0, so if
* regrev is non-zero, fail
*/
memset(country_abbrev, 0, BRCM_CNTRY_BUF_SZ);
strncpy(country_abbrev, "X2", sizeof(country_abbrev) - 1);
country = brcms_c_country_lookup(wlc, country_abbrev);
if (regrev > 0)
return NULL;
/* save default country for exiting 11d regulatory mode */
strncpy(wlc->country_default, country_abbrev, BRCM_CNTRY_BUF_SZ - 1);
/* 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;
}
/* initialize autocountry_default to driver default */
strncpy(wlc->autocountry_default, "X2", BRCM_CNTRY_BUF_SZ - 1);
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;
int mapped;
brcms_c_set_countrycode(wlc_cm, country_abbrev);
/* 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;
}
return wlc_cm;
}
/* default mapping is the given ccode and regrev 0 */
strncpy(mapped_ccode, ccode, BRCM_CNTRY_BUF_SZ);
*mapped_regrev = 0;
void brcms_c_channel_mgr_detach(struct brcms_cm_info *wlc_cm)
{
kfree(wlc_cm);
}
/* 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;
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);
}
u8
brcms_c_channel_locale_flags_in_band(struct brcms_cm_info *wlc_cm,
uint bandunit)
{
return wlc_cm->bandstate[bandunit].locale_flags;
}
/* find the matching built-in country definition */
country = brcms_c_country_lookup_direct(mapped_ccode, *mapped_regrev);
/*
* 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)
{
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);
/* 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);
}
return country;
}
static int
brcms_c_set_countrycode_rev(struct brcms_cm_info *wlc_cm,
const char *country_abbrev,
const char *ccode, int regrev)
/* 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)
{
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
/*
* map the country code to a built-in country code, regrev, and
* country_info struct
*/
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;
}
country = brcms_c_countrycode_map(wlc->cmi, ccode, mapped_ccode,
&mapped_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;
return country;
}
/*
* set the driver's current country and regulatory information
* using a country code as the source. Look up built in country
* information found with the country code.
* reset the quiet channels vector to the union
* of the restricted and radar channel sets
*/
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)
static void brcms_c_quiet_channels_reset(struct brcms_cm_info *wlc_cm)
{
const struct locale_mimo_info *li_mimo;
const struct locale_info *locale;
struct brcms_c_info *wlc = wlc_cm->wlc;
char prev_country_abbrev[BRCM_CNTRY_BUF_SZ];
uint i, j;
struct brcms_band *band;
const struct brcms_chanvec *chanvec;
/* save current country state */
wlc_cm->country = country;
memset(&wlc_cm->quiet_channels, 0, sizeof(struct brcms_chanvec));
memset(&prev_country_abbrev, 0, BRCM_CNTRY_BUF_SZ);
strncpy(prev_country_abbrev, wlc_cm->country_abbrev,
BRCM_CNTRY_BUF_SZ - 1);
band = wlc->band;
for (i = 0; i < NBANDS(wlc);
i++, band = wlc->bandstate[OTHERBANDUNIT(wlc)]) {
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;
/* 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];
/* disable/restore nmode based on country regulations */
li_mimo = brcms_c_get_mimo_2g(country->locale_mimo_2G);
if (li_mimo && (li_mimo->flags & BRCMS_NO_MIMO)) {
brcms_c_set_nmode(wlc, OFF);
wlc->stf->no_cddstbc = true;
} else {
wlc->stf->no_cddstbc = false;
if (N_ENAB(wlc->pub) != wlc->protection->nmode_user)
brcms_c_set_nmode(wlc, wlc->protection->nmode_user);
}
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);
return;
}
/* 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)
/* 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)
{
const struct country_info *country;
char mapped_ccode[BRCM_CNTRY_BUF_SZ];
uint mapped_regrev;
struct brcms_c_info *wlc = wlc_cm->wlc;
/*
* 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 ((val < MAXCHANNEL) &&
isset(wlc_cm->bandstate[wlc->band->bandunit].valid_channels.vec,
val));
}
return country;
/* 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));
}
static const struct country_info *
brcms_c_countrycode_map(struct brcms_cm_info *wlc_cm, const char *ccode,
char *mapped_ccode, uint *mapped_regrev)
/* 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;
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)) {
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;
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 */
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);
}
return VALID_CHANNEL20(wlc, val) ||
(!wlc->bandlocked
&& VALID_CHANNEL20_IN_BAND(wlc, OTHERBANDUNIT(wlc), val));
}
return country;
/* JP, J1 - J10 are Japan ccodes */
static bool brcms_c_japan_ccode(const char *ccode)
{
return (ccode[0] == 'J' &&
(ccode[1] == 'P' || (ccode[1] >= '1' && ccode[1] <= '9')));
}
static int
brcms_c_country_aggregate_map(struct brcms_cm_info *wlc_cm, const char *ccode,
char *mapped_ccode, uint *mapped_regrev)
/* Returns true if currently set country is Japan or variant */
static bool brcms_c_japan(struct brcms_c_info *wlc)
{
return false;
return brcms_c_japan_ccode(wlc->cmi->country_abbrev);
}
/* 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 void
brcms_c_channel_min_txpower_limits_with_local_constraint(
struct brcms_cm_info *wlc_cm, struct txpwr_limits *txpwr,
u8 local_constraint_qdbm)
{
uint size, i;
int j;
/* Should just return 0 for single locale driver. */
/* Keep it this way in case we add more locales. (for now anyway) */
/* CCK Rates */
for (j = 0; j < WL_TX_POWER_CCK_NUM; j++)
txpwr->cck[j] = min(txpwr->cck[j], local_constraint_qdbm);
/*
* all other country def arrays are for regrev == 0, so if
* regrev is non-zero, fail
*/
if (regrev > 0)
return NULL;
/* 20 MHz Legacy OFDM SISO */
for (j = 0; j < WL_TX_POWER_OFDM_NUM; j++)
txpwr->ofdm[j] = min(txpwr->ofdm[j], local_constraint_qdbm);
/* 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;
}
/* 20 MHz Legacy OFDM CDD */
for (j = 0; j < BRCMS_NUM_RATES_OFDM; j++)
txpwr->ofdm_cdd[j] =
min(txpwr->ofdm_cdd[j], local_constraint_qdbm);
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, j;
struct brcms_band *band;
const struct locale_info *li;
struct brcms_chanvec sup_chan;
const struct locale_mimo_info *li_mimo;
/* 40 MHz Legacy OFDM SISO */
for (j = 0; j < BRCMS_NUM_RATES_OFDM; j++)
txpwr->ofdm_40_siso[j] =
min(txpwr->ofdm_40_siso[j], local_constraint_qdbm);
band = wlc->band;
for (i = 0; i < NBANDS(wlc);
i++, band = wlc->bandstate[OTHERBANDUNIT(wlc)]) {
/* 40 MHz Legacy OFDM CDD */
for (j = 0; j < BRCMS_NUM_RATES_OFDM; j++)
txpwr->ofdm_40_cdd[j] =
min(txpwr->ofdm_40_cdd[j], local_constraint_qdbm);
li = BAND_5G(band->bandtype) ?
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_5G(band->bandtype) ?
brcms_c_get_mimo_5g(country->locale_mimo_5G) :
brcms_c_get_mimo_2g(country->locale_mimo_2G);
/* 20MHz MCS 0-7 SISO */
for (j = 0; j < BRCMS_NUM_RATES_MCS_1_STREAM; j++)
txpwr->mcs_20_siso[j] =
min(txpwr->mcs_20_siso[j], local_constraint_qdbm);
/* merge the mimo non-mimo locale flags */
wlc_cm->bandstate[band->bandunit].locale_flags |=
li_mimo->flags;
/* 20MHz MCS 0-7 CDD */
for (j = 0; j < BRCMS_NUM_RATES_MCS_1_STREAM; j++)
txpwr->mcs_20_cdd[j] =
min(txpwr->mcs_20_cdd[j], local_constraint_qdbm);
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];
/* 20MHz MCS 0-7 STBC */
for (j = 0; j < BRCMS_NUM_RATES_MCS_1_STREAM; j++)
txpwr->mcs_20_stbc[j] =
min(txpwr->mcs_20_stbc[j], local_constraint_qdbm);
/*
* 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];
}
/* 20MHz MCS 8-15 MIMO */
for (j = 0; j < BRCMS_NUM_RATES_MCS_2_STREAM; j++)
txpwr->mcs_20_mimo[j] =
min(txpwr->mcs_20_mimo[j], local_constraint_qdbm);
brcms_c_quiet_channels_reset(wlc_cm);
brcms_c_channels_commit(wlc_cm);
/* 40MHz MCS 0-7 SISO */
for (j = 0; j < BRCMS_NUM_RATES_MCS_1_STREAM; j++)
txpwr->mcs_40_siso[j] =
min(txpwr->mcs_40_siso[j], local_constraint_qdbm);
/* 40MHz MCS 0-7 CDD */
for (j = 0; j < BRCMS_NUM_RATES_MCS_1_STREAM; j++)
txpwr->mcs_40_cdd[j] =
min(txpwr->mcs_40_cdd[j], local_constraint_qdbm);
/* 40MHz MCS 0-7 STBC */
for (j = 0; j < BRCMS_NUM_RATES_MCS_1_STREAM; j++)
txpwr->mcs_40_stbc[j] =
min(txpwr->mcs_40_stbc[j], local_constraint_qdbm);
/* 40MHz MCS 8-15 MIMO */
for (j = 0; j < BRCMS_NUM_RATES_MCS_2_STREAM; j++)
txpwr->mcs_40_mimo[j] =
min(txpwr->mcs_40_mimo[j], local_constraint_qdbm);
/* 40MHz MCS 32 */
txpwr->mcs32 = min(txpwr->mcs32, local_constraint_qdbm);
return 0;
}
/* Update the radio state (enable/disable) and tx power targets
......@@ -981,145 +865,225 @@ static void brcms_c_channels_commit(struct brcms_cm_info *wlc_cm)
}
}
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, j;
struct brcms_band *band;
const struct locale_info *li;
struct brcms_chanvec sup_chan;
const struct locale_mimo_info *li_mimo;
band = wlc->band;
for (i = 0; i < NBANDS(wlc);
i++, band = wlc->bandstate[OTHERBANDUNIT(wlc)]) {
li = BAND_5G(band->bandtype) ?
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_5G(band->bandtype) ?
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;
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
* 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);
brcms_c_channels_commit(wlc_cm);
return 0;
}
/*
* reset the quiet channels vector to the union
* of the restricted and radar channel sets
* set the driver's current country and regulatory information
* using a country code as the source. Look up built in country
* information found with the country code.
*/
static void brcms_c_quiet_channels_reset(struct brcms_cm_info *wlc_cm)
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)
{
const struct locale_mimo_info *li_mimo;
const struct locale_info *locale;
struct brcms_c_info *wlc = wlc_cm->wlc;
uint i, j;
struct brcms_band *band;
const struct brcms_chanvec *chanvec;
char prev_country_abbrev[BRCM_CNTRY_BUF_SZ];
memset(&wlc_cm->quiet_channels, 0, sizeof(struct brcms_chanvec));
/* save current country state */
wlc_cm->country = country;
band = wlc->band;
for (i = 0; i < NBANDS(wlc);
i++, band = wlc->bandstate[OTHERBANDUNIT(wlc)]) {
memset(&prev_country_abbrev, 0, BRCM_CNTRY_BUF_SZ);
strncpy(prev_country_abbrev, wlc_cm->country_abbrev,
BRCM_CNTRY_BUF_SZ - 1);
/* 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];
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;
/* disable/restore nmode based on country regulations */
li_mimo = brcms_c_get_mimo_2g(country->locale_mimo_2G);
if (li_mimo && (li_mimo->flags & BRCMS_NO_MIMO)) {
brcms_c_set_nmode(wlc, OFF);
wlc->stf->no_cddstbc = true;
} else {
wlc->stf->no_cddstbc = false;
if (N_ENAB(wlc->pub) != wlc->protection->nmode_user)
brcms_c_set_nmode(wlc, wlc->protection->nmode_user);
}
}
static bool
brcms_c_quiet_chanspec(struct brcms_cm_info *wlc_cm, u16 chspec)
{
return N_ENAB(wlc_cm->wlc->pub) && 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));
}
/* 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;
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);
return VALID_CHANNEL20(wlc, val) ||
(!wlc->bandlocked
&& VALID_CHANNEL20_IN_BAND(wlc, OTHERBANDUNIT(wlc), val));
}
brcms_c_channels_init(wlc_cm, country);
/* 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));
return;
}
/* 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)
static int
brcms_c_set_countrycode_rev(struct brcms_cm_info *wlc_cm,
const char *country_abbrev,
const char *ccode, int regrev)
{
struct brcms_c_info *wlc = wlc_cm->wlc;
const struct country_info *country;
char mapped_ccode[BRCM_CNTRY_BUF_SZ];
uint mapped_regrev;
return ((val < MAXCHANNEL) &&
isset(wlc_cm->bandstate[wlc->band->bandunit].valid_channels.vec,
val));
}
/* 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;
}
static void
brcms_c_channel_min_txpower_limits_with_local_constraint(
struct brcms_cm_info *wlc_cm, struct txpwr_limits *txpwr,
u8 local_constraint_qdbm)
{
int j;
if (country == NULL)
return -EINVAL;
/* CCK Rates */
for (j = 0; j < WL_TX_POWER_CCK_NUM; j++)
txpwr->cck[j] = min(txpwr->cck[j], local_constraint_qdbm);
/* set the driver state for the country */
brcms_c_set_country_common(wlc_cm, country_abbrev, mapped_ccode,
mapped_regrev, country);
/* 20 MHz Legacy OFDM SISO */
for (j = 0; j < WL_TX_POWER_OFDM_NUM; j++)
txpwr->ofdm[j] = min(txpwr->ofdm[j], local_constraint_qdbm);
return 0;
}
/* 20 MHz Legacy OFDM CDD */
for (j = 0; j < BRCMS_NUM_RATES_OFDM; j++)
txpwr->ofdm_cdd[j] =
min(txpwr->ofdm_cdd[j], local_constraint_qdbm);
/*
* 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)
{
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);
}
/* 40 MHz Legacy OFDM SISO */
for (j = 0; j < BRCMS_NUM_RATES_OFDM; j++)
txpwr->ofdm_40_siso[j] =
min(txpwr->ofdm_40_siso[j], local_constraint_qdbm);
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;
/* 40 MHz Legacy OFDM CDD */
for (j = 0; j < BRCMS_NUM_RATES_OFDM; j++)
txpwr->ofdm_40_cdd[j] =
min(txpwr->ofdm_40_cdd[j], local_constraint_qdbm);
BCMMSG(wlc->wiphy, "wl%d\n", wlc->pub->unit);
/* 20MHz MCS 0-7 SISO */
for (j = 0; j < BRCMS_NUM_RATES_MCS_1_STREAM; j++)
txpwr->mcs_20_siso[j] =
min(txpwr->mcs_20_siso[j], local_constraint_qdbm);
wlc_cm = kzalloc(sizeof(struct brcms_cm_info), GFP_ATOMIC);
if (wlc_cm == NULL) {
wiphy_err(wlc->wiphy, "wl%d: %s: out of memory", pub->unit,
__func__);
return NULL;
}
wlc_cm->pub = pub;
wlc_cm->wlc = wlc;
wlc->cmi = wlc_cm;
/* 20MHz MCS 0-7 CDD */
for (j = 0; j < BRCMS_NUM_RATES_MCS_1_STREAM; j++)
txpwr->mcs_20_cdd[j] =
min(txpwr->mcs_20_cdd[j], local_constraint_qdbm);
/* store the country code for passing up as a regulatory hint */
ccode = getvar(wlc->pub->vars, "ccode");
if (ccode)
strncpy(wlc->pub->srom_ccode, ccode, BRCM_CNTRY_BUF_SZ - 1);
/* 20MHz MCS 0-7 STBC */
for (j = 0; j < BRCMS_NUM_RATES_MCS_1_STREAM; j++)
txpwr->mcs_20_stbc[j] =
min(txpwr->mcs_20_stbc[j], local_constraint_qdbm);
/*
* 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);
/* 20MHz MCS 8-15 MIMO */
for (j = 0; j < BRCMS_NUM_RATES_MCS_2_STREAM; j++)
txpwr->mcs_20_mimo[j] =
min(txpwr->mcs_20_mimo[j], local_constraint_qdbm);
/* save default country for exiting 11d regulatory mode */
strncpy(wlc->country_default, country_abbrev, BRCM_CNTRY_BUF_SZ - 1);
/* 40MHz MCS 0-7 SISO */
for (j = 0; j < BRCMS_NUM_RATES_MCS_1_STREAM; j++)
txpwr->mcs_40_siso[j] =
min(txpwr->mcs_40_siso[j], local_constraint_qdbm);
/* initialize autocountry_default to driver default */
strncpy(wlc->autocountry_default, "X2", BRCM_CNTRY_BUF_SZ - 1);
/* 40MHz MCS 0-7 CDD */
for (j = 0; j < BRCMS_NUM_RATES_MCS_1_STREAM; j++)
txpwr->mcs_40_cdd[j] =
min(txpwr->mcs_40_cdd[j], local_constraint_qdbm);
brcms_c_set_countrycode(wlc_cm, country_abbrev);
/* 40MHz MCS 0-7 STBC */
for (j = 0; j < BRCMS_NUM_RATES_MCS_1_STREAM; j++)
txpwr->mcs_40_stbc[j] =
min(txpwr->mcs_40_stbc[j], local_constraint_qdbm);
return wlc_cm;
}
/* 40MHz MCS 8-15 MIMO */
for (j = 0; j < BRCMS_NUM_RATES_MCS_2_STREAM; j++)
txpwr->mcs_40_mimo[j] =
min(txpwr->mcs_40_mimo[j], local_constraint_qdbm);
void brcms_c_channel_mgr_detach(struct brcms_cm_info *wlc_cm)
{
kfree(wlc_cm);
}
/* 40MHz MCS 32 */
txpwr->mcs32 = min(txpwr->mcs32, local_constraint_qdbm);
u8
brcms_c_channel_locale_flags_in_band(struct brcms_cm_info *wlc_cm,
uint bandunit)
{
return wlc_cm->bandstate[bandunit].locale_flags;
}
static bool
brcms_c_quiet_chanspec(struct brcms_cm_info *wlc_cm, u16 chspec)
{
return N_ENAB(wlc_cm->wlc->pub) && 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
......@@ -1471,19 +1435,6 @@ brcms_c_channel_reg_limits(struct brcms_cm_info *wlc_cm, u16 chanspec,
return;
}
/* 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);
}
/* JP, J1 - J10 are Japan ccodes */
static bool brcms_c_japan_ccode(const char *ccode)
{
return (ccode[0] == 'J' &&
(ccode[1] == 'P' || (ccode[1] >= '1' && ccode[1] <= '9')));
}
/*
* Validate the chanspec for this locale, for 40MHZ we need to also
* check that the sidebands are valid 20MZH channels in this locale
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment