From 77c2ef443c1e19ee5932bd8fb5af8f3aefbc8f31 Mon Sep 17 00:00:00 2001 From: Luis R. Rodriguez Date: Mon, 14 Jul 2008 02:40:05 -0700 Subject: [PATCH] Add iwlwifi regulatory work. To: johannes@sipsolutions.net, linville@tuxdriver.com Cc: linux-wireless@vger.kernel.org Signed-off-by: Luis R. Rodriguez --- drivers/net/wireless/iwlwifi/iwl-core.c | 139 +++++++++++++++++++------------ 1 files changed, 87 insertions(+), 52 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-core.c b/drivers/net/wireless/iwlwifi/iwl-core.c index eee220c..8761d41 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.c +++ b/drivers/net/wireless/iwlwifi/iwl-core.c @@ -457,62 +457,12 @@ static void iwlcore_init_hw_rates(struct iwl_priv *priv, } } -/** - * iwlcore_init_geos - Initialize mac80211's geo/channel info based from eeprom - */ -static int iwlcore_init_geos(struct iwl_priv *priv) +static void update_geo_channels(struct iwl_priv *priv) { struct iwl_channel_info *ch; struct ieee80211_supported_band *sband; - struct ieee80211_channel *channels; struct ieee80211_channel *geo_ch; - struct ieee80211_rate *rates; - int i = 0; - - if (priv->bands[IEEE80211_BAND_2GHZ].n_bitrates || - priv->bands[IEEE80211_BAND_5GHZ].n_bitrates) { - IWL_DEBUG_INFO("Geography modes already initialized.\n"); - set_bit(STATUS_GEO_CONFIGURED, &priv->status); - return 0; - } - - channels = kzalloc(sizeof(struct ieee80211_channel) * - priv->channel_count, GFP_KERNEL); - if (!channels) - return -ENOMEM; - - rates = kzalloc((sizeof(struct ieee80211_rate) * (IWL_RATE_COUNT + 1)), - GFP_KERNEL); - if (!rates) { - kfree(channels); - return -ENOMEM; - } - - /* 5.2GHz channels start after the 2.4GHz channels */ - sband = &priv->bands[IEEE80211_BAND_5GHZ]; - sband->channels = &channels[ARRAY_SIZE(iwl_eeprom_band_1)]; - /* just OFDM */ - sband->bitrates = &rates[IWL_FIRST_OFDM_RATE]; - sband->n_bitrates = IWL_RATE_COUNT - IWL_FIRST_OFDM_RATE; - - if (priv->cfg->sku & IWL_SKU_N) - iwlcore_init_ht_hw_capab(priv, &sband->ht_info, - IEEE80211_BAND_5GHZ); - - sband = &priv->bands[IEEE80211_BAND_2GHZ]; - sband->channels = channels; - /* OFDM & CCK */ - sband->bitrates = rates; - sband->n_bitrates = IWL_RATE_COUNT; - - if (priv->cfg->sku & IWL_SKU_N) - iwlcore_init_ht_hw_capab(priv, &sband->ht_info, - IEEE80211_BAND_2GHZ); - - priv->ieee_channels = channels; - priv->ieee_rates = rates; - - iwlcore_init_hw_rates(priv, rates); + int i; for (i = 0; i < priv->channel_count; i++) { ch = &priv->channel_info[i]; @@ -576,7 +526,63 @@ static int iwlcore_init_geos(struct iwl_priv *priv) ": Tunable channels: %d 802.11bg, %d 802.11a channels\n", priv->bands[IEEE80211_BAND_2GHZ].n_channels, priv->bands[IEEE80211_BAND_5GHZ].n_channels); +} + +/** + * iwlcore_init_geos - Initialize mac80211's geo/channel info based from eeprom + */ +static int iwlcore_init_geos(struct iwl_priv *priv) +{ + struct ieee80211_supported_band *sband; + struct ieee80211_channel *channels; + struct ieee80211_rate *rates; + + if (priv->bands[IEEE80211_BAND_2GHZ].n_bitrates || + priv->bands[IEEE80211_BAND_5GHZ].n_bitrates) { + IWL_DEBUG_INFO("Geography modes already initialized.\n"); + set_bit(STATUS_GEO_CONFIGURED, &priv->status); + return 0; + } + + channels = kzalloc(sizeof(struct ieee80211_channel) * + priv->channel_count, GFP_KERNEL); + if (!channels) + return -ENOMEM; + rates = kzalloc((sizeof(struct ieee80211_rate) * (IWL_RATE_COUNT + 1)), + GFP_KERNEL); + if (!rates) { + kfree(channels); + return -ENOMEM; + } + + /* 5.2GHz channels start after the 2.4GHz channels */ + sband = &priv->bands[IEEE80211_BAND_5GHZ]; + sband->channels = &channels[ARRAY_SIZE(iwl_eeprom_band_1)]; + /* just OFDM */ + sband->bitrates = &rates[IWL_FIRST_OFDM_RATE]; + sband->n_bitrates = IWL_RATE_COUNT - IWL_FIRST_OFDM_RATE; + + if (priv->cfg->sku & IWL_SKU_N) + iwlcore_init_ht_hw_capab(priv, &sband->ht_info, + IEEE80211_BAND_5GHZ); + + sband = &priv->bands[IEEE80211_BAND_2GHZ]; + sband->channels = channels; + /* OFDM & CCK */ + sband->bitrates = rates; + sband->n_bitrates = IWL_RATE_COUNT; + + if (priv->cfg->sku & IWL_SKU_N) + iwlcore_init_ht_hw_capab(priv, &sband->ht_info, + IEEE80211_BAND_2GHZ); + + priv->ieee_channels = channels; + priv->ieee_rates = rates; + + iwlcore_init_hw_rates(priv, rates); + + update_geo_channels(priv); set_bit(STATUS_GEO_CONFIGURED, &priv->status); @@ -811,6 +817,30 @@ int iwl_set_rxon_channel(struct iwl_priv *priv, } EXPORT_SYMBOL(iwl_set_rxon_channel); +static int iwl_reg_notifier_call(struct notifier_block *nb, + unsigned long state, void *reg) +{ + struct wiphy *wiphy; + struct ieee80211_hw *hw; + struct iwl_priv *priv; + struct ieee80211_regdomain *rd = (struct ieee80211_regdomain *) reg; + + wiphy = container_of(nb, struct wiphy, reg_notifier); + hw = wiphy_to_hw(wiphy); + priv = (struct iwl_priv *) hw->priv; + + switch (state) { + case REGDOM_SET_BY_CORE: + case REGDOM_SET_BY_80211D: + case REGDOM_SET_BY_DRIVER: + printk("Yay geo\n"); + update_geo_channels(priv); + printk("End geo\n"); + break; + } + return 0; +} + int iwl_setup_mac(struct iwl_priv *priv) { int ret; @@ -836,11 +866,16 @@ int iwl_setup_mac(struct iwl_priv *priv) priv->hw->wiphy->bands[IEEE80211_BAND_5GHZ] = &priv->bands[IEEE80211_BAND_5GHZ]; + ret = register_regulatory_notifier(iwl_reg_notifier_call, hw->wiphy); + if (ret) + return ret; + ret = ieee80211_register_hw(priv->hw); if (ret) { IWL_ERROR("Failed to register hw (error %d)\n", ret); return ret; } + priv->mac80211_registered = 1; return 0; -- 1.5.4.3