commit d6ad0bbbece16d10bc0adef0eeb04d6eff4b4ed5 Author: Jiri Slaby Date: Mon Jun 25 00:09:40 2007 +0200 regdomains are clean as heaven from now :) diff --git a/ath/if_ath_pci.c b/ath/if_ath_pci.c index 1246b12..337c724 100644 --- a/ath/if_ath_pci.c +++ b/ath/if_ath_pci.c @@ -233,15 +233,15 @@ static inline short ath_ieee2mhz(short chan) return 2212 + chan * 20; } -static inline unsigned int ath_copy_rates(struct ieee80211_rate *rates, - const struct ath5k_rate_table *rt) +static unsigned int ath_copy_rates(struct ieee80211_rate *rates, + const struct ath5k_rate_table *rt, unsigned int max) { unsigned int i; if (rt == NULL) return 0; - for (i = 0; i < rt->rate_count; i++, rates++) { + for (i = 0; i < rt->rate_count && max > 0; i++, rates++, max--) { rates->rate = rt->rates[i].rate_kbps / 100; rates->val = rt->rates[i].rate_code; rates->flags = rt->rates[i].modulation; @@ -250,6 +250,80 @@ static inline unsigned int ath_copy_rates(struct ieee80211_rate *rates, return i; } +static unsigned int ath_copy_channels(struct ath_hw *ah, + struct ieee80211_channel *channels, unsigned int mode, + unsigned int max) +{ + static const struct { unsigned int mode, mask, chan; } map[] = { + [MODE_IEEE80211A] = { CHANNEL_OFDM, CHANNEL_OFDM | CHANNEL_TURBO, CHANNEL_A }, + [MODE_ATHEROS_TURBO] = { CHANNEL_OFDM|CHANNEL_TURBO, CHANNEL_OFDM | CHANNEL_TURBO, CHANNEL_T }, + [MODE_IEEE80211B] = { CHANNEL_CCK, CHANNEL_CCK, CHANNEL_B }, + [MODE_IEEE80211G] = { CHANNEL_OFDM, CHANNEL_OFDM, CHANNEL_G }, + [MODE_ATHEROS_TURBOG] = { CHANNEL_OFDM | CHANNEL_TURBO, CHANNEL_OFDM | CHANNEL_TURBO, CHANNEL_TG }, + }; + static const struct ieee80211_regchannel chans_2ghz[] = + IEEE80211_CHANNELS_2GHZ; + static const struct ieee80211_regchannel chans_5ghz[] = + IEEE80211_CHANNELS_5GHZ; + const struct ieee80211_regchannel *chans; + enum ieee80211_regdomain dmn; + unsigned int i, count, size, chfreq, all, f; + + if (!test_bit(mode, ah->ah_modes)) + return 0; + + all = ah->ah_regdomain == DMN_DEFAULT || CHAN_DEBUG == 1; + + switch (mode) { + case MODE_IEEE80211A: + case MODE_ATHEROS_TURBO: + /* 1..220, but 2GHz frequencies are filtered by check_channel */ + size = all ? 220 : ARRAY_SIZE(chans_5ghz); + chans = chans_5ghz; + dmn = ieee80211_regdomain2flag(ah->ah_regdomain, + IEEE80211_CHANNELS_5GHZ_MIN); + chfreq = CHANNEL_5GHZ; + break; + case MODE_IEEE80211B: + case MODE_IEEE80211G: + case MODE_ATHEROS_TURBOG: + size = all ? 26 : ARRAY_SIZE(chans_2ghz); + chans = chans_2ghz; + dmn = ieee80211_regdomain2flag(ah->ah_regdomain, + IEEE80211_CHANNELS_2GHZ_MIN); + chfreq = CHANNEL_2GHZ; + break; + default: + printk(KERN_WARNING "bad mode, not copying channels\n"); + return 0; + } + + for (i = 0, count = 0; i < size && max > 0; i++) { + f = all ? ath_ieee2mhz(i + 1) : chans[i].chan; + /* Check if channel is supported by the chipset */ + if (ath5k_check_channel(ah, f, chfreq) == false) + continue; + + /* Match regulation domain */ + if (!all && !(IEEE80211_DMN(chans[i].domain) & + IEEE80211_DMN(dmn))) + continue; + + if (!all && (chans[i].mode & map[mode].mask) != map[mode].mode) + continue; + + /* Write channel and increment counter */ +// channels->chan = i; + channels->freq = f; + channels->val = map[mode].chan; + channels++; + count++; + max--; + } + + return count; +} + #if ATH_DEBUG_MODES static void ath_dump_modes(struct ieee80211_hw_mode *modes) { @@ -285,8 +359,7 @@ static int ath_getchannels(struct ieee80211_hw *hw) struct ath_softc *sc = hw->priv; struct ath_hw *ah = sc->ah; struct ieee80211_hw_mode *modes = sc->modes; - u32 domain_current = ah->ah_regdomain; - unsigned int i, c, domain_5ghz, domain_2ghz; + unsigned int i, max; int ret; enum { A = 0, @@ -296,131 +369,52 @@ static int ath_getchannels(struct ieee80211_hw *hw) TG = 4, }; + BUILD_BUG_ON(ARRAY_SIZE(sc->modes) < 5); + ah->ah_country_code = countrycode; modes[A].mode = MODE_IEEE80211A; - modes[A].channels = sc->channels; modes[B].mode = MODE_IEEE80211B; - modes[B].channels = sc->channels; modes[G].mode = MODE_IEEE80211G; - modes[G].channels = sc->channels; + max = ARRAY_SIZE(sc->rates); modes[A].rates = sc->rates; - modes[A].num_rates = ath_copy_rates(modes[A].rates, - ath5k_hw_get_rate_table(ah, MODE_IEEE80211A)); + max -= modes[A].num_rates = ath_copy_rates(modes[A].rates, + ath5k_hw_get_rate_table(ah, MODE_IEEE80211A), max); modes[B].rates = &modes[A].rates[modes[A].num_rates]; - modes[B].num_rates = ath_copy_rates(modes[B].rates, - ath5k_hw_get_rate_table(ah, MODE_IEEE80211B)); + max -= modes[B].num_rates = ath_copy_rates(modes[B].rates, + ath5k_hw_get_rate_table(ah, MODE_IEEE80211B), max); modes[G].rates = &modes[B].rates[modes[B].num_rates]; - modes[G].num_rates = ath_copy_rates(modes[G].rates, - ath5k_hw_get_rate_table(ah, MODE_IEEE80211G)); - - /* - * In debugging mode, enable all channels supported by the chipset - */ - if (domain_current == DMN_DEFAULT || CHAN_DEBUG == 1) { - short freq; - - /* channel 1 -2412MHz .. channel 26 (non-ieee) -2732MHz */ - for (i = 1, c = 0; i <= 26 && c < ATH_CHAN_MAX; i++) { - freq = ath_ieee2mhz(i); - if (ath5k_check_channel(ah, freq,CHANNEL_2GHZ) == false) - continue; - sc->channels[c].chan = i; - sc->channels[c].freq = freq; - sc->channels[c].val = CHANNEL_B | CHANNEL_G; - c++; - } - modes[B].num_channels = c; - modes[G].num_channels = c; - - for (i = 27; i <= 220 && c < ATH_CHAN_MAX; i++) { - freq = ath_ieee2mhz(i); - if (ath5k_check_channel(ah, freq,CHANNEL_5GHZ) == false) - continue; - sc->channels[c].chan = i; - sc->channels[c].freq = freq; - sc->channels[c].val = CHANNEL_A | CHANNEL_T| CHANNEL_XR; - c++; - } - modes[A].channels += modes[B].num_channels; /* skip B/G chans */ - modes[A].num_channels = c - modes[B].num_channels; + max -= modes[G].num_rates = ath_copy_rates(modes[G].rates, + ath5k_hw_get_rate_table(ah, MODE_IEEE80211G), max); - goto end; - } + if (!max) + printk(KERN_WARNING "yet another rates found, but there is not " + "sufficient space to store them\n"); - domain_5ghz = ieee80211_regdomain2flag(domain_current, - IEEE80211_CHANNELS_5GHZ_MIN); - domain_2ghz = ieee80211_regdomain2flag(domain_current, - IEEE80211_CHANNELS_2GHZ_MIN); -#if 0 - /* - * Create channel list based on chipset capabilities, regulation domain - * and mode. 5GHz... - */ - for (i = 0; hal->ah_capabilities.cap_range.range_5ghz_max > 0 && - i < ARRAY_SIZE(ath5k_5ghz_channels) && - c < max_channels; i++) { - /* Check if channel is supported by the chipset */ - if (ath5k_check_channel(hal, ath5k_5ghz_channels[i].rc_channel, - CHANNEL_5GHZ) == false) - continue; - - /* Match regulation domain */ - if ((IEEE80211_DMN(ath5k_5ghz_channels[i].rc_domain) & - IEEE80211_DMN(domain_5ghz)) == 0) - continue; - - /* Match modes */ - if (ath5k_5ghz_channels[i].rc_mode & CHANNEL_TURBO) - all_channels[c].channel_flags = CHANNEL_T; - else if (ath5k_5ghz_channels[i].rc_mode & CHANNEL_OFDM) - all_channels[c].channel_flags = CHANNEL_A; - else - continue; - - /* Write channel and increment counter */ - all_channels[c++].freq = ath5k_5ghz_channels[i].rc_channel; - } - - /* - * ...and 2GHz. - */ - for (i = 0; hal->ah_capabilities.cap_range.range_2ghz_max > 0 && - i < ARRAY_SIZE(ath5k_2ghz_channels) && - c < max_channels; i++) { - /* Check if channel is supported by the chipset */ - if (ath5k_check_channel(hal, ath5k_2ghz_channels[i].rc_channel, - CHANNEL_2GHZ) == false) - continue; - - /* Match regulation domain */ - if ((IEEE80211_DMN(ath5k_2ghz_channels[i].rc_domain) & - IEEE80211_DMN(domain_2ghz)) == 0) - continue; - - /* Match modes */ - if ((hal->ah_capabilities.cap_mode & AR5K_MODE_11B) && - (ath5k_2ghz_channels[i].rc_mode & CHANNEL_CCK)) - all_channels[c].channel_flags = CHANNEL_B; - - if ((hal->ah_capabilities.cap_mode & AR5K_MODE_11G) && - (ath5k_2ghz_channels[i].rc_mode &CHANNEL_OFDM)){ - all_channels[c].channel_flags |= CHANNEL_G; -/* if (ath5k_2ghz_channels[i].rc_mode & CHANNEL_TURBO) - all_channels[c].channel_flags |= CHANNEL_TG;*/ + max = ARRAY_SIZE(sc->channels); + modes[A].channels = sc->channels; + max -= modes[A].num_channels = ath_copy_channels(ah, modes[A].channels, + MODE_IEEE80211A, max); + modes[B].channels = &modes[A].channels[modes[A].num_channels]; + max -= modes[B].num_channels = ath_copy_channels(ah, modes[B].channels, + MODE_IEEE80211B, max); + modes[G].channels = &modes[B].channels[modes[B].num_channels]; + max -= modes[G].num_channels = ath_copy_channels(ah, modes[G].channels, + MODE_IEEE80211G, max); + + if (!max) + printk(KERN_WARNING "yet another modes found, but there is not " + "sufficient space to store them\n"); + + for (i = 0; i < ARRAY_SIZE(sc->modes); i++) + if (modes[i].num_channels) { + ret = ieee80211_register_hwmode(hw, &modes[i]); + if (ret) { + printk(KERN_ERR "can't register hwmode %u\n",i); + goto err; + } } - - /* Write channel and increment counter */ - all_channels[c++].freq = ath5k_2ghz_channels[i].rc_channel; - } -#endif -end: - ret = ieee80211_register_hwmode(hw, modes); - if (ret) { - printk(KERN_ERR "can't register hwmodes\n"); - goto err; - } ath_dump_modes(modes); return 0; diff --git a/ath/if_athvar.h b/ath/if_athvar.h index 7260f79..6e84246 100644 --- a/ath/if_athvar.h +++ b/ath/if_athvar.h @@ -169,7 +169,11 @@ struct ath_txq { (_tq)->axq_depth--; \ } while (0) -#define ATH_CHAN_MAX 255 /* XXX what's the max? */ +#if CHAN_DEBUG +#define ATH_CHAN_MAX (26+26+26+200+200) +#else +#define ATH_CHAN_MAX (14+14+14+252+20) /* XXX what's the max? */ +#endif struct ath_softc { void __iomem *iobase; /* address of the device */ diff --git a/openhal/ath5k_hw.c b/openhal/ath5k_hw.c index 2e88557..660c295 100644 --- a/openhal/ath5k_hw.c +++ b/openhal/ath5k_hw.c @@ -70,14 +70,6 @@ static int ath5k_eeprom_init(struct ath_hw *); static int ath5k_eeprom_read_mac(struct ath_hw *, u8 *); /* - * Supported channels - */ -static const struct -ieee80211_regchannel ath5k_5ghz_channels[] = IEEE80211_CHANNELS_5GHZ; -static const struct -ieee80211_regchannel ath5k_2ghz_channels[] = IEEE80211_CHANNELS_2GHZ; - -/* * Initial register dumps */ static const struct ath5k_ar5212_ini ar5212_ini[] = AR5K_AR5212_INI;