forked from luck/tmp_suning_uos_patched
ath9k: simplify regulatory code
Now that cfg80211 has its own regulatory infrastructure we can condense ath9k's regulatory code considerably. We only keep data we need to provide our own regulatory_hint(), reg_notifier() and information necessary for calibration. Atheros hardware supports 12 world regulatory domains, since these are custom we apply them through the the new wiphy_apply_custom_regulatory(). Although we have 12 we can consolidate these into 5 structures based on frequency and apply a different set of flags that differentiate them on a case by case basis through the reg_notifier(). If CRDA is not found our own custom world regulatory domain is applied, this is identical to cfg80211's except we enable passive scan on most frequencies. Signed-off-by: Luis R. Rodriguez <lrodriguez@atheros.com> Signed-off-by: John W. Linville <linville@tuxdriver.com>
This commit is contained in:
parent
24ed1da133
commit
5f8e077c0a
@ -457,22 +457,12 @@ struct ath9k_channel {
|
||||
struct ieee80211_channel *chan;
|
||||
u16 channel;
|
||||
u32 channelFlags;
|
||||
u8 privFlags;
|
||||
int8_t maxRegTxPower;
|
||||
int8_t maxTxPower;
|
||||
int8_t minTxPower;
|
||||
u32 chanmode;
|
||||
int32_t CalValid;
|
||||
bool oneTimeCalsDone;
|
||||
int8_t iCoff;
|
||||
int8_t qCoff;
|
||||
int16_t rawNoiseFloor;
|
||||
int8_t antennaMax;
|
||||
u32 regDmnFlags;
|
||||
u32 conformanceTestLimit[3]; /* 0:11a, 1: 11b, 2:11g */
|
||||
#ifdef ATH_NF_PER_CHAN
|
||||
struct ath9k_nfcal_hist nfCalHist[NUM_NF_READINGS];
|
||||
#endif
|
||||
};
|
||||
|
||||
#define IS_CHAN_A(_c) ((((_c)->channelFlags & CHANNEL_A) == CHANNEL_A) || \
|
||||
@ -500,7 +490,6 @@ struct ath9k_channel {
|
||||
((_c)->chanmode == CHANNEL_G_HT40MINUS))
|
||||
#define IS_CHAN_HT(_c) (IS_CHAN_HT20((_c)) || IS_CHAN_HT40((_c)))
|
||||
|
||||
#define IS_CHAN_IN_PUBLIC_SAFETY_BAND(_c) ((_c) > 4940 && (_c) < 4990)
|
||||
#define IS_CHAN_A_5MHZ_SPACED(_c) \
|
||||
((((_c)->channelFlags & CHANNEL_5GHZ) != 0) && \
|
||||
(((_c)->channel % 20) != 0) && \
|
||||
@ -790,15 +779,13 @@ struct ath_hal {
|
||||
u16 ah_currentRD;
|
||||
u16 ah_currentRDExt;
|
||||
u16 ah_currentRDInUse;
|
||||
u16 ah_currentRD5G;
|
||||
u16 ah_currentRD2G;
|
||||
char ah_iso[4];
|
||||
char alpha2[2];
|
||||
struct reg_dmn_pair_mapping *regpair;
|
||||
enum ath9k_power_mode ah_power_mode;
|
||||
enum ath9k_power_mode ah_restore_mode;
|
||||
|
||||
struct ath9k_channel ah_channels[150];
|
||||
struct ath9k_channel ah_channels[38];
|
||||
struct ath9k_channel *ah_curchan;
|
||||
u32 ah_nchan;
|
||||
|
||||
bool ah_isPciExpress;
|
||||
u16 ah_txTrigLevel;
|
||||
@ -807,10 +794,7 @@ struct ath_hal {
|
||||
u32 ah_rfkill_polarity;
|
||||
u32 ah_btactive_gpio;
|
||||
u32 ah_wlanactive_gpio;
|
||||
|
||||
#ifndef ATH_NF_PER_CHAN
|
||||
struct ath9k_nfcal_hist nfCalHist[NUM_NF_READINGS];
|
||||
#endif
|
||||
|
||||
bool sw_mgmt_crypto;
|
||||
};
|
||||
@ -825,8 +809,6 @@ struct ath_rate_table;
|
||||
|
||||
/* Helpers */
|
||||
|
||||
enum wireless_mode ath9k_hw_chan2wmode(struct ath_hal *ah,
|
||||
const struct ath9k_channel *chan);
|
||||
bool ath9k_hw_wait(struct ath_hal *ah, u32 reg, u32 mask, u32 val);
|
||||
u32 ath9k_hw_reverse_bits(u32 val, u32 n);
|
||||
bool ath9k_get_channel_edges(struct ath_hal *ah,
|
||||
@ -836,7 +818,6 @@ u16 ath9k_hw_computetxtime(struct ath_hal *ah,
|
||||
struct ath_rate_table *rates,
|
||||
u32 frameLen, u16 rateix,
|
||||
bool shortPreamble);
|
||||
u32 ath9k_hw_mhz2ieee(struct ath_hal *ah, u32 freq, u32 flags);
|
||||
void ath9k_hw_get_channel_centers(struct ath_hal *ah,
|
||||
struct ath9k_channel *chan,
|
||||
struct chan_centers *centers);
|
||||
@ -924,17 +905,18 @@ bool ath9k_hw_setslottime(struct ath_hal *ah, u32 us);
|
||||
void ath9k_hw_set11nmac2040(struct ath_hal *ah, enum ath9k_ht_macmode mode);
|
||||
|
||||
/* Regulatory */
|
||||
u16 ath9k_regd_get_rd(struct ath_hal *ah);
|
||||
bool ath9k_is_world_regd(struct ath_hal *ah);
|
||||
const struct ieee80211_regdomain *ath9k_world_regdomain(struct ath_hal *ah);
|
||||
const struct ieee80211_regdomain *ath9k_default_world_regdomain(void);
|
||||
|
||||
bool ath9k_regd_is_public_safety_sku(struct ath_hal *ah);
|
||||
struct ath9k_channel* ath9k_regd_check_channel(struct ath_hal *ah,
|
||||
const struct ath9k_channel *c);
|
||||
void ath9k_reg_apply_world_flags(struct wiphy *wiphy, enum reg_set_by setby);
|
||||
void ath9k_reg_apply_radar_flags(struct wiphy *wiphy);
|
||||
|
||||
int ath9k_regd_init(struct ath_hal *ah);
|
||||
bool ath9k_regd_is_eeprom_valid(struct ath_hal *ah);
|
||||
u32 ath9k_regd_get_ctl(struct ath_hal *ah, struct ath9k_channel *chan);
|
||||
u32 ath9k_regd_get_antenna_allowed(struct ath_hal *ah,
|
||||
struct ath9k_channel *chan);
|
||||
bool ath9k_regd_init_channels(struct ath_hal *ah,
|
||||
u32 maxchans, u32 *nchans, u8 *regclassids,
|
||||
u32 maxregids, u32 *nregids, u16 cc,
|
||||
bool enableOutdoor, bool enableExtendedChannels);
|
||||
int ath9k_reg_notifier(struct wiphy *wiphy, struct regulatory_request *request);
|
||||
|
||||
/* ANI */
|
||||
|
||||
|
@ -625,11 +625,7 @@ void ath9k_hw_loadnf(struct ath_hal *ah, struct ath9k_channel *chan)
|
||||
else
|
||||
chainmask = 0x3F;
|
||||
|
||||
#ifdef ATH_NF_PER_CHAN
|
||||
h = chan->nfCalHist;
|
||||
#else
|
||||
h = ah->nfCalHist;
|
||||
#endif
|
||||
|
||||
for (i = 0; i < NUM_NF_READINGS; i++) {
|
||||
if (chainmask & (1 << i)) {
|
||||
@ -697,11 +693,7 @@ int16_t ath9k_hw_getnf(struct ath_hal *ah,
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef ATH_NF_PER_CHAN
|
||||
h = chan->nfCalHist;
|
||||
#else
|
||||
h = ah->nfCalHist;
|
||||
#endif
|
||||
|
||||
ath9k_hw_update_nfcal_hist_buffer(h, nfarray);
|
||||
chan->rawNoiseFloor = h[0].privNF;
|
||||
@ -728,20 +720,12 @@ void ath9k_init_nfcal_hist_buffer(struct ath_hal *ah)
|
||||
|
||||
s16 ath9k_hw_getchan_noise(struct ath_hal *ah, struct ath9k_channel *chan)
|
||||
{
|
||||
struct ath9k_channel *ichan;
|
||||
s16 nf;
|
||||
|
||||
ichan = ath9k_regd_check_channel(ah, chan);
|
||||
if (ichan == NULL) {
|
||||
DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
|
||||
"invalid channel %u/0x%x; no mapping\n",
|
||||
chan->channel, chan->channelFlags);
|
||||
return ATH_DEFAULT_NOISE_FLOOR;
|
||||
}
|
||||
if (ichan->rawNoiseFloor == 0)
|
||||
if (chan->rawNoiseFloor == 0)
|
||||
nf = -96;
|
||||
else
|
||||
nf = ichan->rawNoiseFloor;
|
||||
nf = chan->rawNoiseFloor;
|
||||
|
||||
if (!ath9k_hw_nf_in_range(ah, nf))
|
||||
nf = ATH_DEFAULT_NOISE_FLOOR;
|
||||
@ -755,21 +739,13 @@ bool ath9k_hw_calibrate(struct ath_hal *ah, struct ath9k_channel *chan,
|
||||
{
|
||||
struct ath_hal_5416 *ahp = AH5416(ah);
|
||||
struct hal_cal_list *currCal = ahp->ah_cal_list_curr;
|
||||
struct ath9k_channel *ichan = ath9k_regd_check_channel(ah, chan);
|
||||
|
||||
*isCalDone = true;
|
||||
|
||||
if (ichan == NULL) {
|
||||
DPRINTF(ah->ah_sc, ATH_DBG_CHANNEL,
|
||||
"invalid channel %u/0x%x; no mapping\n",
|
||||
chan->channel, chan->channelFlags);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (currCal &&
|
||||
(currCal->calState == CAL_RUNNING ||
|
||||
currCal->calState == CAL_WAITING)) {
|
||||
ath9k_hw_per_calibration(ah, ichan, rxchainmask, currCal,
|
||||
ath9k_hw_per_calibration(ah, chan, rxchainmask, currCal,
|
||||
isCalDone);
|
||||
if (*isCalDone) {
|
||||
ahp->ah_cal_list_curr = currCal = currCal->calNext;
|
||||
@ -782,14 +758,12 @@ bool ath9k_hw_calibrate(struct ath_hal *ah, struct ath9k_channel *chan,
|
||||
}
|
||||
|
||||
if (longcal) {
|
||||
ath9k_hw_getnf(ah, ichan);
|
||||
ath9k_hw_getnf(ah, chan);
|
||||
ath9k_hw_loadnf(ah, ah->ah_curchan);
|
||||
ath9k_hw_start_nfcal(ah);
|
||||
|
||||
if ((ichan->channelFlags & CHANNEL_CW_INT) != 0) {
|
||||
chan->channelFlags |= CHANNEL_CW_INT;
|
||||
ichan->channelFlags &= ~CHANNEL_CW_INT;
|
||||
}
|
||||
if (chan->channelFlags & CHANNEL_CW_INT)
|
||||
chan->channelFlags &= ~CHANNEL_CW_INT;
|
||||
}
|
||||
|
||||
return true;
|
||||
@ -894,7 +868,6 @@ bool ath9k_hw_init_cal(struct ath_hal *ah,
|
||||
struct ath9k_channel *chan)
|
||||
{
|
||||
struct ath_hal_5416 *ahp = AH5416(ah);
|
||||
struct ath9k_channel *ichan = ath9k_regd_check_channel(ah, chan);
|
||||
|
||||
REG_WRITE(ah, AR_PHY_AGC_CONTROL,
|
||||
REG_READ(ah, AR_PHY_AGC_CONTROL) |
|
||||
@ -942,7 +915,7 @@ bool ath9k_hw_init_cal(struct ath_hal *ah,
|
||||
ath9k_hw_reset_calibration(ah, ahp->ah_cal_list_curr);
|
||||
}
|
||||
|
||||
ichan->CalValid = 0;
|
||||
chan->CalValid = 0;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -724,7 +724,6 @@ struct ath_softc {
|
||||
struct ieee80211_rate rates[IEEE80211_NUM_BANDS][ATH_RATE_MAX];
|
||||
struct ath_rate_table *hw_rate_table[ATH9K_MODE_MAX];
|
||||
struct ath_rate_table *cur_rate_table;
|
||||
struct ieee80211_channel channels[IEEE80211_NUM_BANDS][ATH_CHAN_MAX];
|
||||
struct ieee80211_supported_band sbands[IEEE80211_NUM_BANDS];
|
||||
struct ath_led radio_led;
|
||||
struct ath_led assoc_led;
|
||||
|
@ -187,46 +187,6 @@ u16 ath9k_hw_computetxtime(struct ath_hal *ah,
|
||||
return txTime;
|
||||
}
|
||||
|
||||
u32 ath9k_hw_mhz2ieee(struct ath_hal *ah, u32 freq, u32 flags)
|
||||
{
|
||||
if (flags & CHANNEL_2GHZ) {
|
||||
if (freq == 2484)
|
||||
return 14;
|
||||
if (freq < 2484)
|
||||
return (freq - 2407) / 5;
|
||||
else
|
||||
return 15 + ((freq - 2512) / 20);
|
||||
} else if (flags & CHANNEL_5GHZ) {
|
||||
if (ath9k_regd_is_public_safety_sku(ah) &&
|
||||
IS_CHAN_IN_PUBLIC_SAFETY_BAND(freq)) {
|
||||
return ((freq * 10) +
|
||||
(((freq % 5) == 2) ? 5 : 0) - 49400) / 5;
|
||||
} else if ((flags & CHANNEL_A) && (freq <= 5000)) {
|
||||
return (freq - 4000) / 5;
|
||||
} else {
|
||||
return (freq - 5000) / 5;
|
||||
}
|
||||
} else {
|
||||
if (freq == 2484)
|
||||
return 14;
|
||||
if (freq < 2484)
|
||||
return (freq - 2407) / 5;
|
||||
if (freq < 5000) {
|
||||
if (ath9k_regd_is_public_safety_sku(ah)
|
||||
&& IS_CHAN_IN_PUBLIC_SAFETY_BAND(freq)) {
|
||||
return ((freq * 10) +
|
||||
(((freq % 5) ==
|
||||
2) ? 5 : 0) - 49400) / 5;
|
||||
} else if (freq > 4900) {
|
||||
return (freq - 4000) / 5;
|
||||
} else {
|
||||
return 15 + ((freq - 2512) / 20);
|
||||
}
|
||||
}
|
||||
return (freq - 5000) / 5;
|
||||
}
|
||||
}
|
||||
|
||||
void ath9k_hw_get_channel_centers(struct ath_hal *ah,
|
||||
struct ath9k_channel *chan,
|
||||
struct chan_centers *centers)
|
||||
@ -1270,6 +1230,7 @@ static int ath9k_hw_process_ini(struct ath_hal *ah,
|
||||
{
|
||||
int i, regWrites = 0;
|
||||
struct ath_hal_5416 *ahp = AH5416(ah);
|
||||
struct ieee80211_channel *channel = chan->chan;
|
||||
u32 modesIndex, freqIndex;
|
||||
int status;
|
||||
|
||||
@ -1374,9 +1335,8 @@ static int ath9k_hw_process_ini(struct ath_hal *ah,
|
||||
|
||||
status = ath9k_hw_set_txpower(ah, chan,
|
||||
ath9k_regd_get_ctl(ah, chan),
|
||||
ath9k_regd_get_antenna_allowed(ah,
|
||||
chan),
|
||||
chan->maxRegTxPower * 2,
|
||||
channel->max_antenna_gain * 2,
|
||||
channel->max_power * 2,
|
||||
min((u32) MAX_RATE_POWER,
|
||||
(u32) ah->ah_powerLimit));
|
||||
if (status != 0) {
|
||||
@ -1669,6 +1629,7 @@ static bool ath9k_hw_channel_change(struct ath_hal *ah,
|
||||
struct ath9k_channel *chan,
|
||||
enum ath9k_ht_macmode macmode)
|
||||
{
|
||||
struct ieee80211_channel *channel = chan->chan;
|
||||
u32 synthDelay, qnum;
|
||||
|
||||
for (qnum = 0; qnum < AR_NUM_QCU; qnum++) {
|
||||
@ -1705,8 +1666,8 @@ static bool ath9k_hw_channel_change(struct ath_hal *ah,
|
||||
|
||||
if (ath9k_hw_set_txpower(ah, chan,
|
||||
ath9k_regd_get_ctl(ah, chan),
|
||||
ath9k_regd_get_antenna_allowed(ah, chan),
|
||||
chan->maxRegTxPower * 2,
|
||||
channel->max_antenna_gain * 2,
|
||||
channel->max_power * 2,
|
||||
min((u32) MAX_RATE_POWER,
|
||||
(u32) ah->ah_powerLimit)) != 0) {
|
||||
DPRINTF(ah->ah_sc, ATH_DBG_EEPROM,
|
||||
@ -2209,13 +2170,6 @@ int ath9k_hw_reset(struct ath_hal *ah, struct ath9k_channel *chan,
|
||||
ahp->ah_rxchainmask &= 0x3;
|
||||
}
|
||||
|
||||
if (ath9k_regd_check_channel(ah, chan) == NULL) {
|
||||
DPRINTF(ah->ah_sc, ATH_DBG_CHANNEL,
|
||||
"invalid channel %u/0x%x; no mapping\n",
|
||||
chan->channel, chan->channelFlags);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (!ath9k_hw_setpower(ah, ATH9K_PM_AWAKE))
|
||||
return -EIO;
|
||||
|
||||
@ -3718,13 +3672,14 @@ bool ath9k_hw_disable(struct ath_hal *ah)
|
||||
bool ath9k_hw_set_txpowerlimit(struct ath_hal *ah, u32 limit)
|
||||
{
|
||||
struct ath9k_channel *chan = ah->ah_curchan;
|
||||
struct ieee80211_channel *channel = chan->chan;
|
||||
|
||||
ah->ah_powerLimit = min(limit, (u32) MAX_RATE_POWER);
|
||||
|
||||
if (ath9k_hw_set_txpower(ah, chan,
|
||||
ath9k_regd_get_ctl(ah, chan),
|
||||
ath9k_regd_get_antenna_allowed(ah, chan),
|
||||
chan->maxRegTxPower * 2,
|
||||
channel->max_antenna_gain * 2,
|
||||
channel->max_power * 2,
|
||||
min((u32) MAX_RATE_POWER,
|
||||
(u32) ah->ah_powerLimit)) != 0)
|
||||
return false;
|
||||
|
@ -28,6 +28,77 @@ MODULE_DESCRIPTION("Support for Atheros 802.11n wireless LAN cards.");
|
||||
MODULE_SUPPORTED_DEVICE("Atheros 802.11n WLAN cards");
|
||||
MODULE_LICENSE("Dual BSD/GPL");
|
||||
|
||||
/* We use the hw_value as an index into our private channel structure */
|
||||
|
||||
#define CHAN2G(_freq, _idx) { \
|
||||
.center_freq = (_freq), \
|
||||
.hw_value = (_idx), \
|
||||
.max_power = 30, \
|
||||
}
|
||||
|
||||
#define CHAN5G(_freq, _idx) { \
|
||||
.band = IEEE80211_BAND_5GHZ, \
|
||||
.center_freq = (_freq), \
|
||||
.hw_value = (_idx), \
|
||||
.max_power = 30, \
|
||||
}
|
||||
|
||||
/* Some 2 GHz radios are actually tunable on 2312-2732
|
||||
* on 5 MHz steps, we support the channels which we know
|
||||
* we have calibration data for all cards though to make
|
||||
* this static */
|
||||
static struct ieee80211_channel ath9k_2ghz_chantable[] = {
|
||||
CHAN2G(2412, 0), /* Channel 1 */
|
||||
CHAN2G(2417, 1), /* Channel 2 */
|
||||
CHAN2G(2422, 2), /* Channel 3 */
|
||||
CHAN2G(2427, 3), /* Channel 4 */
|
||||
CHAN2G(2432, 4), /* Channel 5 */
|
||||
CHAN2G(2437, 5), /* Channel 6 */
|
||||
CHAN2G(2442, 6), /* Channel 7 */
|
||||
CHAN2G(2447, 7), /* Channel 8 */
|
||||
CHAN2G(2452, 8), /* Channel 9 */
|
||||
CHAN2G(2457, 9), /* Channel 10 */
|
||||
CHAN2G(2462, 10), /* Channel 11 */
|
||||
CHAN2G(2467, 11), /* Channel 12 */
|
||||
CHAN2G(2472, 12), /* Channel 13 */
|
||||
CHAN2G(2484, 13), /* Channel 14 */
|
||||
};
|
||||
|
||||
/* Some 5 GHz radios are actually tunable on XXXX-YYYY
|
||||
* on 5 MHz steps, we support the channels which we know
|
||||
* we have calibration data for all cards though to make
|
||||
* this static */
|
||||
static struct ieee80211_channel ath9k_5ghz_chantable[] = {
|
||||
/* _We_ call this UNII 1 */
|
||||
CHAN5G(5180, 14), /* Channel 36 */
|
||||
CHAN5G(5200, 15), /* Channel 40 */
|
||||
CHAN5G(5220, 16), /* Channel 44 */
|
||||
CHAN5G(5240, 17), /* Channel 48 */
|
||||
/* _We_ call this UNII 2 */
|
||||
CHAN5G(5260, 18), /* Channel 52 */
|
||||
CHAN5G(5280, 19), /* Channel 56 */
|
||||
CHAN5G(5300, 20), /* Channel 60 */
|
||||
CHAN5G(5320, 21), /* Channel 64 */
|
||||
/* _We_ call this "Middle band" */
|
||||
CHAN5G(5500, 22), /* Channel 100 */
|
||||
CHAN5G(5520, 23), /* Channel 104 */
|
||||
CHAN5G(5540, 24), /* Channel 108 */
|
||||
CHAN5G(5560, 25), /* Channel 112 */
|
||||
CHAN5G(5580, 26), /* Channel 116 */
|
||||
CHAN5G(5600, 27), /* Channel 120 */
|
||||
CHAN5G(5620, 28), /* Channel 124 */
|
||||
CHAN5G(5640, 29), /* Channel 128 */
|
||||
CHAN5G(5660, 30), /* Channel 132 */
|
||||
CHAN5G(5680, 31), /* Channel 136 */
|
||||
CHAN5G(5700, 32), /* Channel 140 */
|
||||
/* _We_ call this UNII 3 */
|
||||
CHAN5G(5745, 33), /* Channel 149 */
|
||||
CHAN5G(5765, 34), /* Channel 153 */
|
||||
CHAN5G(5785, 35), /* Channel 157 */
|
||||
CHAN5G(5805, 36), /* Channel 161 */
|
||||
CHAN5G(5825, 37), /* Channel 165 */
|
||||
};
|
||||
|
||||
static void ath_cache_conf_rate(struct ath_softc *sc,
|
||||
struct ieee80211_conf *conf)
|
||||
{
|
||||
@ -152,75 +223,6 @@ static void ath_setup_rates(struct ath_softc *sc, enum ieee80211_band band)
|
||||
}
|
||||
}
|
||||
|
||||
static int ath_setup_channels(struct ath_softc *sc)
|
||||
{
|
||||
struct ath_hal *ah = sc->sc_ah;
|
||||
int nchan, i, a = 0, b = 0;
|
||||
u8 regclassids[ATH_REGCLASSIDS_MAX];
|
||||
u32 nregclass = 0;
|
||||
struct ieee80211_supported_band *band_2ghz;
|
||||
struct ieee80211_supported_band *band_5ghz;
|
||||
struct ieee80211_channel *chan_2ghz;
|
||||
struct ieee80211_channel *chan_5ghz;
|
||||
struct ath9k_channel *c;
|
||||
|
||||
/* Fill in ah->ah_channels */
|
||||
if (!ath9k_regd_init_channels(ah, ATH_CHAN_MAX, (u32 *)&nchan,
|
||||
regclassids, ATH_REGCLASSIDS_MAX,
|
||||
&nregclass, CTRY_DEFAULT, false, 1)) {
|
||||
u32 rd = ah->ah_currentRD;
|
||||
DPRINTF(sc, ATH_DBG_FATAL,
|
||||
"Unable to collect channel list; "
|
||||
"regdomain likely %u country code %u\n",
|
||||
rd, CTRY_DEFAULT);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
band_2ghz = &sc->sbands[IEEE80211_BAND_2GHZ];
|
||||
band_5ghz = &sc->sbands[IEEE80211_BAND_5GHZ];
|
||||
chan_2ghz = sc->channels[IEEE80211_BAND_2GHZ];
|
||||
chan_5ghz = sc->channels[IEEE80211_BAND_5GHZ];
|
||||
|
||||
for (i = 0; i < nchan; i++) {
|
||||
c = &ah->ah_channels[i];
|
||||
if (IS_CHAN_2GHZ(c)) {
|
||||
chan_2ghz[a].band = IEEE80211_BAND_2GHZ;
|
||||
chan_2ghz[a].center_freq = c->channel;
|
||||
chan_2ghz[a].max_power = c->maxTxPower;
|
||||
c->chan = &chan_2ghz[a];
|
||||
|
||||
if (c->privFlags & CHANNEL_DISALLOW_ADHOC)
|
||||
chan_2ghz[a].flags |= IEEE80211_CHAN_NO_IBSS;
|
||||
if (c->channelFlags & CHANNEL_PASSIVE)
|
||||
chan_2ghz[a].flags |= IEEE80211_CHAN_PASSIVE_SCAN;
|
||||
|
||||
band_2ghz->n_channels = ++a;
|
||||
|
||||
DPRINTF(sc, ATH_DBG_CONFIG, "2MHz channel: %d, "
|
||||
"channelFlags: 0x%x\n",
|
||||
c->channel, c->channelFlags);
|
||||
} else if (IS_CHAN_5GHZ(c)) {
|
||||
chan_5ghz[b].band = IEEE80211_BAND_5GHZ;
|
||||
chan_5ghz[b].center_freq = c->channel;
|
||||
chan_5ghz[b].max_power = c->maxTxPower;
|
||||
c->chan = &chan_5ghz[a];
|
||||
|
||||
if (c->privFlags & CHANNEL_DISALLOW_ADHOC)
|
||||
chan_5ghz[b].flags |= IEEE80211_CHAN_NO_IBSS;
|
||||
if (c->channelFlags & CHANNEL_PASSIVE)
|
||||
chan_5ghz[b].flags |= IEEE80211_CHAN_PASSIVE_SCAN;
|
||||
|
||||
band_5ghz->n_channels = ++b;
|
||||
|
||||
DPRINTF(sc, ATH_DBG_CONFIG, "5MHz channel: %d, "
|
||||
"channelFlags: 0x%x\n",
|
||||
c->channel, c->channelFlags);
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Set/change channels. If the channel is really being changed, it's done
|
||||
* by reseting the chip. To accomplish this we must first cleanup any pending
|
||||
@ -582,19 +584,6 @@ irqreturn_t ath_isr(int irq, void *dev)
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
static int ath_get_channel(struct ath_softc *sc,
|
||||
struct ieee80211_channel *chan)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < sc->sc_ah->ah_nchan; i++) {
|
||||
if (sc->sc_ah->ah_channels[i].channel == chan->center_freq)
|
||||
return i;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
static u32 ath_get_extchanmode(struct ath_softc *sc,
|
||||
struct ieee80211_channel *chan,
|
||||
enum nl80211_channel_type channel_type)
|
||||
@ -1349,16 +1338,12 @@ static int ath_init(u16 devid, struct ath_softc *sc)
|
||||
for (i = 0; i < sc->sc_keymax; i++)
|
||||
ath9k_hw_keyreset(ah, (u16) i);
|
||||
|
||||
/* Collect the channel list using the default country code */
|
||||
|
||||
error = ath_setup_channels(sc);
|
||||
if (error)
|
||||
if (ath9k_regd_init(sc->sc_ah))
|
||||
goto bad;
|
||||
|
||||
/* default to MONITOR mode */
|
||||
sc->sc_ah->ah_opmode = NL80211_IFTYPE_MONITOR;
|
||||
|
||||
|
||||
/* Setup rate tables */
|
||||
|
||||
ath_rate_attach(sc);
|
||||
@ -1490,18 +1475,20 @@ static int ath_init(u16 devid, struct ath_softc *sc)
|
||||
|
||||
/* setup channels and rates */
|
||||
|
||||
sc->sbands[IEEE80211_BAND_2GHZ].channels =
|
||||
sc->channels[IEEE80211_BAND_2GHZ];
|
||||
sc->sbands[IEEE80211_BAND_2GHZ].channels = ath9k_2ghz_chantable;
|
||||
sc->sbands[IEEE80211_BAND_2GHZ].bitrates =
|
||||
sc->rates[IEEE80211_BAND_2GHZ];
|
||||
sc->sbands[IEEE80211_BAND_2GHZ].band = IEEE80211_BAND_2GHZ;
|
||||
sc->sbands[IEEE80211_BAND_2GHZ].n_channels =
|
||||
ARRAY_SIZE(ath9k_2ghz_chantable);
|
||||
|
||||
if (test_bit(ATH9K_MODE_11A, sc->sc_ah->ah_caps.wireless_modes)) {
|
||||
sc->sbands[IEEE80211_BAND_5GHZ].channels =
|
||||
sc->channels[IEEE80211_BAND_5GHZ];
|
||||
sc->sbands[IEEE80211_BAND_5GHZ].channels = ath9k_5ghz_chantable;
|
||||
sc->sbands[IEEE80211_BAND_5GHZ].bitrates =
|
||||
sc->rates[IEEE80211_BAND_5GHZ];
|
||||
sc->sbands[IEEE80211_BAND_5GHZ].band = IEEE80211_BAND_5GHZ;
|
||||
sc->sbands[IEEE80211_BAND_5GHZ].n_channels =
|
||||
ARRAY_SIZE(ath9k_5ghz_chantable);
|
||||
}
|
||||
|
||||
if (sc->sc_ah->ah_caps.hw_caps & ATH9K_HW_CAP_BT_COEX)
|
||||
@ -1550,6 +1537,9 @@ int ath_attach(u16 devid, struct ath_softc *sc)
|
||||
BIT(NL80211_IFTYPE_STATION) |
|
||||
BIT(NL80211_IFTYPE_ADHOC);
|
||||
|
||||
hw->wiphy->reg_notifier = ath9k_reg_notifier;
|
||||
hw->wiphy->strict_regulatory = true;
|
||||
|
||||
hw->queues = 4;
|
||||
hw->max_rates = 4;
|
||||
hw->max_rate_tries = ATH_11N_TXMAXTRY;
|
||||
@ -1588,11 +1578,36 @@ int ath_attach(u16 devid, struct ath_softc *sc)
|
||||
goto detach;
|
||||
#endif
|
||||
|
||||
if (ath9k_is_world_regd(sc->sc_ah)) {
|
||||
/* Anything applied here (prior to wiphy registratoin) gets
|
||||
* saved on the wiphy orig_* parameters */
|
||||
const struct ieee80211_regdomain *regd =
|
||||
ath9k_world_regdomain(sc->sc_ah);
|
||||
hw->wiphy->custom_regulatory = true;
|
||||
hw->wiphy->strict_regulatory = false;
|
||||
wiphy_apply_custom_regulatory(sc->hw->wiphy, regd);
|
||||
ath9k_reg_apply_radar_flags(hw->wiphy);
|
||||
ath9k_reg_apply_world_flags(hw->wiphy, REGDOM_SET_BY_INIT);
|
||||
} else {
|
||||
/* This gets applied in the case of the absense of CRDA,
|
||||
* its our own custom world regulatory domain, similar to
|
||||
* cfg80211's but we enable passive scanning */
|
||||
const struct ieee80211_regdomain *regd =
|
||||
ath9k_default_world_regdomain();
|
||||
wiphy_apply_custom_regulatory(sc->hw->wiphy, regd);
|
||||
ath9k_reg_apply_radar_flags(hw->wiphy);
|
||||
ath9k_reg_apply_world_flags(hw->wiphy, REGDOM_SET_BY_INIT);
|
||||
}
|
||||
|
||||
error = ieee80211_register_hw(hw);
|
||||
|
||||
if (!ath9k_is_world_regd(sc->sc_ah))
|
||||
regulatory_hint(hw->wiphy, sc->sc_ah->alpha2);
|
||||
|
||||
/* Initialize LED control */
|
||||
ath_init_leds(sc);
|
||||
|
||||
|
||||
return 0;
|
||||
detach:
|
||||
ath_detach(sc);
|
||||
@ -1818,6 +1833,37 @@ int ath_get_mac80211_qnum(u32 queue, struct ath_softc *sc)
|
||||
return qnum;
|
||||
}
|
||||
|
||||
/* XXX: Remove me once we don't depend on ath9k_channel for all
|
||||
* this redundant data */
|
||||
static void ath9k_update_ichannel(struct ath_softc *sc,
|
||||
struct ath9k_channel *ichan)
|
||||
{
|
||||
struct ieee80211_hw *hw = sc->hw;
|
||||
struct ieee80211_channel *chan = hw->conf.channel;
|
||||
struct ieee80211_conf *conf = &hw->conf;
|
||||
|
||||
ichan->channel = chan->center_freq;
|
||||
ichan->chan = chan;
|
||||
|
||||
if (chan->band == IEEE80211_BAND_2GHZ) {
|
||||
ichan->chanmode = CHANNEL_G;
|
||||
ichan->channelFlags = CHANNEL_2GHZ | CHANNEL_OFDM;
|
||||
} else {
|
||||
ichan->chanmode = CHANNEL_A;
|
||||
ichan->channelFlags = CHANNEL_5GHZ | CHANNEL_OFDM;
|
||||
}
|
||||
|
||||
sc->tx_chan_width = ATH9K_HT_MACMODE_20;
|
||||
|
||||
if (conf_is_ht(conf)) {
|
||||
if (conf_is_ht40(conf))
|
||||
sc->tx_chan_width = ATH9K_HT_MACMODE_2040;
|
||||
|
||||
ichan->chanmode = ath_get_extchanmode(sc, chan,
|
||||
conf->channel_type);
|
||||
}
|
||||
}
|
||||
|
||||
/**********************/
|
||||
/* mac80211 callbacks */
|
||||
/**********************/
|
||||
@ -1834,16 +1880,10 @@ static int ath9k_start(struct ieee80211_hw *hw)
|
||||
|
||||
/* setup initial channel */
|
||||
|
||||
pos = ath_get_channel(sc, curchan);
|
||||
if (pos == -1) {
|
||||
DPRINTF(sc, ATH_DBG_FATAL, "Invalid channel: %d\n", curchan->center_freq);
|
||||
return -EINVAL;
|
||||
}
|
||||
pos = curchan->hw_value;
|
||||
|
||||
sc->tx_chan_width = ATH9K_HT_MACMODE_20;
|
||||
sc->sc_ah->ah_channels[pos].chanmode =
|
||||
(curchan->band == IEEE80211_BAND_2GHZ) ? CHANNEL_G : CHANNEL_A;
|
||||
init_channel = &sc->sc_ah->ah_channels[pos];
|
||||
ath9k_update_ichannel(sc, init_channel);
|
||||
|
||||
/* Reset SERDES registers */
|
||||
ath9k_hw_configpcipowersave(sc->sc_ah, 0);
|
||||
@ -2127,32 +2167,13 @@ static int ath9k_config(struct ieee80211_hw *hw, u32 changed)
|
||||
|
||||
if (changed & IEEE80211_CONF_CHANGE_CHANNEL) {
|
||||
struct ieee80211_channel *curchan = hw->conf.channel;
|
||||
int pos;
|
||||
int pos = curchan->hw_value;
|
||||
|
||||
DPRINTF(sc, ATH_DBG_CONFIG, "Set channel: %d MHz\n",
|
||||
curchan->center_freq);
|
||||
|
||||
pos = ath_get_channel(sc, curchan);
|
||||
if (pos == -1) {
|
||||
DPRINTF(sc, ATH_DBG_FATAL, "Invalid channel: %d\n",
|
||||
curchan->center_freq);
|
||||
mutex_unlock(&sc->mutex);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
sc->tx_chan_width = ATH9K_HT_MACMODE_20;
|
||||
sc->sc_ah->ah_channels[pos].chanmode =
|
||||
(curchan->band == IEEE80211_BAND_2GHZ) ?
|
||||
CHANNEL_G : CHANNEL_A;
|
||||
|
||||
if (conf_is_ht(conf)) {
|
||||
if (conf_is_ht40(conf))
|
||||
sc->tx_chan_width = ATH9K_HT_MACMODE_2040;
|
||||
|
||||
sc->sc_ah->ah_channels[pos].chanmode =
|
||||
ath_get_extchanmode(sc, curchan,
|
||||
conf->channel_type);
|
||||
}
|
||||
/* XXX: remove me eventualy */
|
||||
ath9k_update_ichannel(sc, &sc->sc_ah->ah_channels[pos]);
|
||||
|
||||
ath_update_chainmask(sc, conf_is_ht(conf));
|
||||
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -19,126 +19,14 @@
|
||||
|
||||
#include "ath9k.h"
|
||||
|
||||
#define BMLEN 2
|
||||
#define BMZERO {(u64) 0, (u64) 0}
|
||||
|
||||
#define BM(_fa, _fb, _fc, _fd, _fe, _ff, _fg, _fh, _fi, _fj, _fk, _fl) \
|
||||
{((((_fa >= 0) && (_fa < 64)) ? \
|
||||
(((u64) 1) << _fa) : (u64) 0) | \
|
||||
(((_fb >= 0) && (_fb < 64)) ? \
|
||||
(((u64) 1) << _fb) : (u64) 0) | \
|
||||
(((_fc >= 0) && (_fc < 64)) ? \
|
||||
(((u64) 1) << _fc) : (u64) 0) | \
|
||||
(((_fd >= 0) && (_fd < 64)) ? \
|
||||
(((u64) 1) << _fd) : (u64) 0) | \
|
||||
(((_fe >= 0) && (_fe < 64)) ? \
|
||||
(((u64) 1) << _fe) : (u64) 0) | \
|
||||
(((_ff >= 0) && (_ff < 64)) ? \
|
||||
(((u64) 1) << _ff) : (u64) 0) | \
|
||||
(((_fg >= 0) && (_fg < 64)) ? \
|
||||
(((u64) 1) << _fg) : (u64) 0) | \
|
||||
(((_fh >= 0) && (_fh < 64)) ? \
|
||||
(((u64) 1) << _fh) : (u64) 0) | \
|
||||
(((_fi >= 0) && (_fi < 64)) ? \
|
||||
(((u64) 1) << _fi) : (u64) 0) | \
|
||||
(((_fj >= 0) && (_fj < 64)) ? \
|
||||
(((u64) 1) << _fj) : (u64) 0) | \
|
||||
(((_fk >= 0) && (_fk < 64)) ? \
|
||||
(((u64) 1) << _fk) : (u64) 0) | \
|
||||
(((_fl >= 0) && (_fl < 64)) ? \
|
||||
(((u64) 1) << _fl) : (u64) 0) | \
|
||||
((((_fa > 63) && (_fa < 128)) ? \
|
||||
(((u64) 1) << (_fa - 64)) : (u64) 0) | \
|
||||
(((_fb > 63) && (_fb < 128)) ? \
|
||||
(((u64) 1) << (_fb - 64)) : (u64) 0) | \
|
||||
(((_fc > 63) && (_fc < 128)) ? \
|
||||
(((u64) 1) << (_fc - 64)) : (u64) 0) | \
|
||||
(((_fd > 63) && (_fd < 128)) ? \
|
||||
(((u64) 1) << (_fd - 64)) : (u64) 0) | \
|
||||
(((_fe > 63) && (_fe < 128)) ? \
|
||||
(((u64) 1) << (_fe - 64)) : (u64) 0) | \
|
||||
(((_ff > 63) && (_ff < 128)) ? \
|
||||
(((u64) 1) << (_ff - 64)) : (u64) 0) | \
|
||||
(((_fg > 63) && (_fg < 128)) ? \
|
||||
(((u64) 1) << (_fg - 64)) : (u64) 0) | \
|
||||
(((_fh > 63) && (_fh < 128)) ? \
|
||||
(((u64) 1) << (_fh - 64)) : (u64) 0) | \
|
||||
(((_fi > 63) && (_fi < 128)) ? \
|
||||
(((u64) 1) << (_fi - 64)) : (u64) 0) | \
|
||||
(((_fj > 63) && (_fj < 128)) ? \
|
||||
(((u64) 1) << (_fj - 64)) : (u64) 0) | \
|
||||
(((_fk > 63) && (_fk < 128)) ? \
|
||||
(((u64) 1) << (_fk - 64)) : (u64) 0) | \
|
||||
(((_fl > 63) && (_fl < 128)) ? \
|
||||
(((u64) 1) << (_fl - 64)) : (u64) 0)))}
|
||||
|
||||
#define DEF_REGDMN FCC1_FCCA
|
||||
#define DEF_DMN_5 FCC1
|
||||
#define DEF_DMN_2 FCCA
|
||||
#define COUNTRY_ERD_FLAG 0x8000
|
||||
#define WORLDWIDE_ROAMING_FLAG 0x4000
|
||||
#define SUPER_DOMAIN_MASK 0x0fff
|
||||
#define COUNTRY_CODE_MASK 0x3fff
|
||||
#define CF_INTERFERENCE (CHANNEL_CW_INT | CHANNEL_RADAR_INT)
|
||||
#define CHANNEL_14 (2484)
|
||||
#define IS_11G_CH14(_ch,_cf) \
|
||||
(((_ch) == CHANNEL_14) && ((_cf) == CHANNEL_G))
|
||||
|
||||
#define NO_PSCAN 0x0ULL
|
||||
#define PSCAN_FCC 0x0000000000000001ULL
|
||||
#define PSCAN_FCC_T 0x0000000000000002ULL
|
||||
#define PSCAN_ETSI 0x0000000000000004ULL
|
||||
#define PSCAN_MKK1 0x0000000000000008ULL
|
||||
#define PSCAN_MKK2 0x0000000000000010ULL
|
||||
#define PSCAN_MKKA 0x0000000000000020ULL
|
||||
#define PSCAN_MKKA_G 0x0000000000000040ULL
|
||||
#define PSCAN_ETSIA 0x0000000000000080ULL
|
||||
#define PSCAN_ETSIB 0x0000000000000100ULL
|
||||
#define PSCAN_ETSIC 0x0000000000000200ULL
|
||||
#define PSCAN_WWR 0x0000000000000400ULL
|
||||
#define PSCAN_MKKA1 0x0000000000000800ULL
|
||||
#define PSCAN_MKKA1_G 0x0000000000001000ULL
|
||||
#define PSCAN_MKKA2 0x0000000000002000ULL
|
||||
#define PSCAN_MKKA2_G 0x0000000000004000ULL
|
||||
#define PSCAN_MKK3 0x0000000000008000ULL
|
||||
#define PSCAN_DEFER 0x7FFFFFFFFFFFFFFFULL
|
||||
#define IS_ECM_CHAN 0x8000000000000000ULL
|
||||
|
||||
#define isWwrSKU(_ah) \
|
||||
(((ath9k_regd_get_eepromRD((_ah)) & WORLD_SKU_MASK) == \
|
||||
WORLD_SKU_PREFIX) || \
|
||||
(ath9k_regd_get_eepromRD(_ah) == WORLD))
|
||||
|
||||
#define isWwrSKU_NoMidband(_ah) \
|
||||
((ath9k_regd_get_eepromRD((_ah)) == WOR3_WORLD) || \
|
||||
(ath9k_regd_get_eepromRD(_ah) == WOR4_WORLD) || \
|
||||
(ath9k_regd_get_eepromRD(_ah) == WOR5_ETSIC))
|
||||
|
||||
#define isUNII1OddChan(ch) \
|
||||
((ch == 5170) || (ch == 5190) || (ch == 5210) || (ch == 5230))
|
||||
|
||||
#define IS_HT40_MODE(_mode) \
|
||||
(((_mode == ATH9K_MODE_11NA_HT40PLUS || \
|
||||
_mode == ATH9K_MODE_11NG_HT40PLUS || \
|
||||
_mode == ATH9K_MODE_11NA_HT40MINUS || \
|
||||
_mode == ATH9K_MODE_11NG_HT40MINUS) ? true : false))
|
||||
|
||||
#define CHAN_FLAGS (CHANNEL_ALL|CHANNEL_HALF|CHANNEL_QUARTER)
|
||||
|
||||
#define swap_array(_a, _b, _size) { \
|
||||
u8 *s = _b; \
|
||||
int i = _size; \
|
||||
do { \
|
||||
u8 tmp = *_a; \
|
||||
*_a++ = *s; \
|
||||
*s++ = tmp; \
|
||||
} while (--i); \
|
||||
_a -= _size; \
|
||||
}
|
||||
|
||||
|
||||
#define HALF_MAXCHANBW 10
|
||||
|
||||
#define MULTI_DOMAIN_MASK 0xFF00
|
||||
|
||||
#define WORLD_SKU_MASK 0x00F0
|
||||
@ -147,81 +35,16 @@
|
||||
#define CHANNEL_HALF_BW 10
|
||||
#define CHANNEL_QUARTER_BW 5
|
||||
|
||||
typedef int ath_hal_cmp_t(const void *, const void *);
|
||||
|
||||
struct reg_dmn_pair_mapping {
|
||||
u16 regDmnEnum;
|
||||
u16 regDmn5GHz;
|
||||
u16 regDmn2GHz;
|
||||
u32 flags5GHz;
|
||||
u32 flags2GHz;
|
||||
u64 pscanMask;
|
||||
u16 singleCC;
|
||||
};
|
||||
|
||||
struct ccmap {
|
||||
char isoName[3];
|
||||
u16 countryCode;
|
||||
u16 reg_5ghz_ctl;
|
||||
u16 reg_2ghz_ctl;
|
||||
};
|
||||
|
||||
struct country_code_to_enum_rd {
|
||||
u16 countryCode;
|
||||
u16 regDmnEnum;
|
||||
const char *isoName;
|
||||
const char *name;
|
||||
bool allow11g;
|
||||
bool allow11aTurbo;
|
||||
bool allow11gTurbo;
|
||||
bool allow11ng20;
|
||||
bool allow11ng40;
|
||||
bool allow11na20;
|
||||
bool allow11na40;
|
||||
u16 outdoorChanStart;
|
||||
};
|
||||
|
||||
struct RegDmnFreqBand {
|
||||
u16 lowChannel;
|
||||
u16 highChannel;
|
||||
u8 powerDfs;
|
||||
u8 antennaMax;
|
||||
u8 channelBW;
|
||||
u8 channelSep;
|
||||
u64 useDfs;
|
||||
u64 usePassScan;
|
||||
u8 regClassId;
|
||||
};
|
||||
|
||||
struct regDomain {
|
||||
u16 regDmnEnum;
|
||||
u8 conformanceTestLimit;
|
||||
u64 dfsMask;
|
||||
u64 pscan;
|
||||
u32 flags;
|
||||
u64 chan11a[BMLEN];
|
||||
u64 chan11a_turbo[BMLEN];
|
||||
u64 chan11a_dyn_turbo[BMLEN];
|
||||
u64 chan11b[BMLEN];
|
||||
u64 chan11g[BMLEN];
|
||||
u64 chan11g_turbo[BMLEN];
|
||||
};
|
||||
|
||||
struct cmode {
|
||||
u32 mode;
|
||||
u32 flags;
|
||||
};
|
||||
|
||||
#define YES true
|
||||
#define NO false
|
||||
|
||||
struct japan_bandcheck {
|
||||
u16 freqbandbit;
|
||||
u32 eepromflagtocheck;
|
||||
};
|
||||
|
||||
struct common_mode_power {
|
||||
u16 lchan;
|
||||
u16 hchan;
|
||||
u8 pwrlvl;
|
||||
};
|
||||
|
||||
enum CountryCode {
|
||||
|
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue
Block a user