aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJohannes Berg <johannes@sipsolutions.net>2008-10-09 06:18:51 -0400
committerJohn W. Linville <linville@tuxdriver.com>2008-10-31 19:00:07 -0400
commite8975581f63870be42ff4662b293d1b0c8c21350 (patch)
tree3d0d67e73d009ea6480b459585c0a70fc35fa9da
parent0f4ac38b5999c3d51adad52d61c56c1b99c247ec (diff)
mac80211: introduce hw config change flags
This makes mac80211 notify the driver which configuration actually changed, e.g. channel etc. No driver changes, this is just plumbing, driver authors are expected to act on this if they want to. Also remove the HW CONFIG debug printk, it's incorrect, often we configure something else. Signed-off-by: Johannes Berg <johannes@sipsolutions.net> Signed-off-by: John W. Linville <linville@tuxdriver.com>
-rw-r--r--drivers/net/wireless/adm8211.c3
-rw-r--r--drivers/net/wireless/ath5k/base.c7
-rw-r--r--drivers/net/wireless/ath9k/main.c4
-rw-r--r--drivers/net/wireless/b43/main.c3
-rw-r--r--drivers/net/wireless/b43legacy/main.c3
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-agn.c3
-rw-r--r--drivers/net/wireless/iwlwifi/iwl3945-base.c7
-rw-r--r--drivers/net/wireless/libertas_tf/main.c4
-rw-r--r--drivers/net/wireless/mac80211_hwsim.c4
-rw-r--r--drivers/net/wireless/p54/p54common.c3
-rw-r--r--drivers/net/wireless/rt2x00/rt2x00.h2
-rw-r--r--drivers/net/wireless/rt2x00/rt2x00dev.c2
-rw-r--r--drivers/net/wireless/rt2x00/rt2x00mac.c3
-rw-r--r--drivers/net/wireless/rtl8180_dev.c3
-rw-r--r--drivers/net/wireless/rtl8187_dev.c3
-rw-r--r--drivers/net/wireless/zd1211rw/zd_mac.c4
-rw-r--r--include/net/mac80211.h30
-rw-r--r--net/mac80211/cfg.c3
-rw-r--r--net/mac80211/ieee80211_i.h2
-rw-r--r--net/mac80211/iface.c25
-rw-r--r--net/mac80211/main.c29
-rw-r--r--net/mac80211/scan.c12
-rw-r--r--net/mac80211/util.c3
-rw-r--r--net/mac80211/wext.c14
24 files changed, 116 insertions, 60 deletions
diff --git a/drivers/net/wireless/adm8211.c b/drivers/net/wireless/adm8211.c
index 6e18c9d36787..9a1e0c514c08 100644
--- a/drivers/net/wireless/adm8211.c
+++ b/drivers/net/wireless/adm8211.c
@@ -1314,9 +1314,10 @@ static int adm8211_set_ssid(struct ieee80211_hw *dev, u8 *ssid, size_t ssid_len)
1314 return 0; 1314 return 0;
1315} 1315}
1316 1316
1317static int adm8211_config(struct ieee80211_hw *dev, struct ieee80211_conf *conf) 1317static int adm8211_config(struct ieee80211_hw *dev, u32 changed)
1318{ 1318{
1319 struct adm8211_priv *priv = dev->priv; 1319 struct adm8211_priv *priv = dev->priv;
1320 struct ieee80211_conf *conf = &dev->conf;
1320 int channel = ieee80211_frequency_to_channel(conf->channel->center_freq); 1321 int channel = ieee80211_frequency_to_channel(conf->channel->center_freq);
1321 1322
1322 if (channel != priv->channel) { 1323 if (channel != priv->channel) {
diff --git a/drivers/net/wireless/ath5k/base.c b/drivers/net/wireless/ath5k/base.c
index 9e47d727e220..fcd688765d04 100644
--- a/drivers/net/wireless/ath5k/base.c
+++ b/drivers/net/wireless/ath5k/base.c
@@ -219,8 +219,7 @@ static int ath5k_add_interface(struct ieee80211_hw *hw,
219 struct ieee80211_if_init_conf *conf); 219 struct ieee80211_if_init_conf *conf);
220static void ath5k_remove_interface(struct ieee80211_hw *hw, 220static void ath5k_remove_interface(struct ieee80211_hw *hw,
221 struct ieee80211_if_init_conf *conf); 221 struct ieee80211_if_init_conf *conf);
222static int ath5k_config(struct ieee80211_hw *hw, 222static int ath5k_config(struct ieee80211_hw *hw, u32 changed);
223 struct ieee80211_conf *conf);
224static int ath5k_config_interface(struct ieee80211_hw *hw, 223static int ath5k_config_interface(struct ieee80211_hw *hw,
225 struct ieee80211_vif *vif, 224 struct ieee80211_vif *vif,
226 struct ieee80211_if_conf *conf); 225 struct ieee80211_if_conf *conf);
@@ -2780,10 +2779,10 @@ end:
2780 * TODO: Phy disable/diversity etc 2779 * TODO: Phy disable/diversity etc
2781 */ 2780 */
2782static int 2781static int
2783ath5k_config(struct ieee80211_hw *hw, 2782ath5k_config(struct ieee80211_hw *hw, u32 changed)
2784 struct ieee80211_conf *conf)
2785{ 2783{
2786 struct ath5k_softc *sc = hw->priv; 2784 struct ath5k_softc *sc = hw->priv;
2785 struct ieee80211_conf *conf = &hw->conf;
2787 2786
2788 sc->bintval = conf->beacon_int; 2787 sc->bintval = conf->beacon_int;
2789 sc->power_level = conf->power_level; 2788 sc->power_level = conf->power_level;
diff --git a/drivers/net/wireless/ath9k/main.c b/drivers/net/wireless/ath9k/main.c
index 5e087c92a6d9..f49910799ede 100644
--- a/drivers/net/wireless/ath9k/main.c
+++ b/drivers/net/wireless/ath9k/main.c
@@ -1230,11 +1230,11 @@ static void ath9k_remove_interface(struct ieee80211_hw *hw,
1230 __func__, error); 1230 __func__, error);
1231} 1231}
1232 1232
1233static int ath9k_config(struct ieee80211_hw *hw, 1233static int ath9k_config(struct ieee80211_hw *hw, u32 changed)
1234 struct ieee80211_conf *conf)
1235{ 1234{
1236 struct ath_softc *sc = hw->priv; 1235 struct ath_softc *sc = hw->priv;
1237 struct ieee80211_channel *curchan = hw->conf.channel; 1236 struct ieee80211_channel *curchan = hw->conf.channel;
1237 struct ieee80211_conf *conf = &hw->conf;
1238 int pos; 1238 int pos;
1239 1239
1240 DPRINTF(sc, ATH_DBG_CONFIG, "%s: Set channel: %d MHz\n", 1240 DPRINTF(sc, ATH_DBG_CONFIG, "%s: Set channel: %d MHz\n",
diff --git a/drivers/net/wireless/b43/main.c b/drivers/net/wireless/b43/main.c
index 6b85428b0e1d..2e81af1022e4 100644
--- a/drivers/net/wireless/b43/main.c
+++ b/drivers/net/wireless/b43/main.c
@@ -3320,11 +3320,12 @@ init_failure:
3320 return err; 3320 return err;
3321} 3321}
3322 3322
3323static int b43_op_config(struct ieee80211_hw *hw, struct ieee80211_conf *conf) 3323static int b43_op_config(struct ieee80211_hw *hw, u32 changed)
3324{ 3324{
3325 struct b43_wl *wl = hw_to_b43_wl(hw); 3325 struct b43_wl *wl = hw_to_b43_wl(hw);
3326 struct b43_wldev *dev; 3326 struct b43_wldev *dev;
3327 struct b43_phy *phy; 3327 struct b43_phy *phy;
3328 struct ieee80211_conf *conf = &hw->conf;
3328 unsigned long flags; 3329 unsigned long flags;
3329 int antenna; 3330 int antenna;
3330 int err = 0; 3331 int err = 0;
diff --git a/drivers/net/wireless/b43legacy/main.c b/drivers/net/wireless/b43legacy/main.c
index 867f01ce45c7..793cc396562f 100644
--- a/drivers/net/wireless/b43legacy/main.c
+++ b/drivers/net/wireless/b43legacy/main.c
@@ -2557,11 +2557,12 @@ init_failure:
2557} 2557}
2558 2558
2559static int b43legacy_op_dev_config(struct ieee80211_hw *hw, 2559static int b43legacy_op_dev_config(struct ieee80211_hw *hw,
2560 struct ieee80211_conf *conf) 2560 u32 changed)
2561{ 2561{
2562 struct b43legacy_wl *wl = hw_to_b43legacy_wl(hw); 2562 struct b43legacy_wl *wl = hw_to_b43legacy_wl(hw);
2563 struct b43legacy_wldev *dev; 2563 struct b43legacy_wldev *dev;
2564 struct b43legacy_phy *phy; 2564 struct b43legacy_phy *phy;
2565 struct ieee80211_conf *conf = &hw->conf;
2565 unsigned long flags; 2566 unsigned long flags;
2566 unsigned int new_phymode = 0xFFFF; 2567 unsigned int new_phymode = 0xFFFF;
2567 int antenna_tx; 2568 int antenna_tx;
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c
index e6695e80fb53..79a24410dd0a 100644
--- a/drivers/net/wireless/iwlwifi/iwl-agn.c
+++ b/drivers/net/wireless/iwlwifi/iwl-agn.c
@@ -2734,10 +2734,11 @@ static int iwl4965_mac_add_interface(struct ieee80211_hw *hw,
2734 * be set inappropriately and the driver currently sets the hardware up to 2734 * be set inappropriately and the driver currently sets the hardware up to
2735 * use it whenever needed. 2735 * use it whenever needed.
2736 */ 2736 */
2737static int iwl4965_mac_config(struct ieee80211_hw *hw, struct ieee80211_conf *conf) 2737static int iwl4965_mac_config(struct ieee80211_hw *hw, u32 changed)
2738{ 2738{
2739 struct iwl_priv *priv = hw->priv; 2739 struct iwl_priv *priv = hw->priv;
2740 const struct iwl_channel_info *ch_info; 2740 const struct iwl_channel_info *ch_info;
2741 struct ieee80211_conf *conf = &hw->conf;
2741 unsigned long flags; 2742 unsigned long flags;
2742 int ret = 0; 2743 int ret = 0;
2743 u16 channel; 2744 u16 channel;
diff --git a/drivers/net/wireless/iwlwifi/iwl3945-base.c b/drivers/net/wireless/iwlwifi/iwl3945-base.c
index d3a2966d9181..b1464c71ea0a 100644
--- a/drivers/net/wireless/iwlwifi/iwl3945-base.c
+++ b/drivers/net/wireless/iwlwifi/iwl3945-base.c
@@ -6415,7 +6415,7 @@ static void iwl3945_bg_abort_scan(struct work_struct *work)
6415 mutex_unlock(&priv->mutex); 6415 mutex_unlock(&priv->mutex);
6416} 6416}
6417 6417
6418static int iwl3945_mac_config(struct ieee80211_hw *hw, struct ieee80211_conf *conf); 6418static int iwl3945_mac_config(struct ieee80211_hw *hw, u32 changed);
6419 6419
6420static void iwl3945_bg_scan_completed(struct work_struct *work) 6420static void iwl3945_bg_scan_completed(struct work_struct *work)
6421{ 6421{
@@ -6428,7 +6428,7 @@ static void iwl3945_bg_scan_completed(struct work_struct *work)
6428 return; 6428 return;
6429 6429
6430 if (test_bit(STATUS_CONF_PENDING, &priv->status)) 6430 if (test_bit(STATUS_CONF_PENDING, &priv->status))
6431 iwl3945_mac_config(priv->hw, ieee80211_get_hw_conf(priv->hw)); 6431 iwl3945_mac_config(priv->hw, 0);
6432 6432
6433 ieee80211_scan_completed(priv->hw); 6433 ieee80211_scan_completed(priv->hw);
6434 6434
@@ -6616,10 +6616,11 @@ static int iwl3945_mac_add_interface(struct ieee80211_hw *hw,
6616 * be set inappropriately and the driver currently sets the hardware up to 6616 * be set inappropriately and the driver currently sets the hardware up to
6617 * use it whenever needed. 6617 * use it whenever needed.
6618 */ 6618 */
6619static int iwl3945_mac_config(struct ieee80211_hw *hw, struct ieee80211_conf *conf) 6619static int iwl3945_mac_config(struct ieee80211_hw *hw, u32 changed)
6620{ 6620{
6621 struct iwl3945_priv *priv = hw->priv; 6621 struct iwl3945_priv *priv = hw->priv;
6622 const struct iwl3945_channel_info *ch_info; 6622 const struct iwl3945_channel_info *ch_info;
6623 struct ieee80211_conf *conf = &hw->conf;
6623 unsigned long flags; 6624 unsigned long flags;
6624 int ret = 0; 6625 int ret = 0;
6625 6626
diff --git a/drivers/net/wireless/libertas_tf/main.c b/drivers/net/wireless/libertas_tf/main.c
index feff945ad856..241ddcfa352e 100644
--- a/drivers/net/wireless/libertas_tf/main.c
+++ b/drivers/net/wireless/libertas_tf/main.c
@@ -354,9 +354,11 @@ static void lbtf_op_remove_interface(struct ieee80211_hw *hw,
354 priv->vif = NULL; 354 priv->vif = NULL;
355} 355}
356 356
357static int lbtf_op_config(struct ieee80211_hw *hw, struct ieee80211_conf *conf) 357static int lbtf_op_config(struct ieee80211_hw *hw, u32 changed)
358{ 358{
359 struct lbtf_private *priv = hw->priv; 359 struct lbtf_private *priv = hw->priv;
360 struct ieee80211_conf *conf = &hw->conf;
361
360 if (conf->channel->center_freq != priv->cur_freq) { 362 if (conf->channel->center_freq != priv->cur_freq) {
361 priv->cur_freq = conf->channel->center_freq; 363 priv->cur_freq = conf->channel->center_freq;
362 lbtf_set_channel(priv, conf->channel->hw_value); 364 lbtf_set_channel(priv, conf->channel->hw_value);
diff --git a/drivers/net/wireless/mac80211_hwsim.c b/drivers/net/wireless/mac80211_hwsim.c
index 3f236b546683..e2aeef8de707 100644
--- a/drivers/net/wireless/mac80211_hwsim.c
+++ b/drivers/net/wireless/mac80211_hwsim.c
@@ -359,10 +359,10 @@ static void mac80211_hwsim_beacon(unsigned long arg)
359} 359}
360 360
361 361
362static int mac80211_hwsim_config(struct ieee80211_hw *hw, 362static int mac80211_hwsim_config(struct ieee80211_hw *hw, u32 changed)
363 struct ieee80211_conf *conf)
364{ 363{
365 struct mac80211_hwsim_data *data = hw->priv; 364 struct mac80211_hwsim_data *data = hw->priv;
365 struct ieee80211_conf *conf = &hw->conf;
366 366
367 printk(KERN_DEBUG "%s:%s (freq=%d radio_enabled=%d beacon_int=%d)\n", 367 printk(KERN_DEBUG "%s:%s (freq=%d radio_enabled=%d beacon_int=%d)\n",
368 wiphy_name(hw->wiphy), __func__, 368 wiphy_name(hw->wiphy), __func__,
diff --git a/drivers/net/wireless/p54/p54common.c b/drivers/net/wireless/p54/p54common.c
index b3e75eb4d5ba..b3c297ed00cd 100644
--- a/drivers/net/wireless/p54/p54common.c
+++ b/drivers/net/wireless/p54/p54common.c
@@ -1192,10 +1192,11 @@ static void p54_remove_interface(struct ieee80211_hw *dev,
1192 p54_set_filter(dev, 0, NULL); 1192 p54_set_filter(dev, 0, NULL);
1193} 1193}
1194 1194
1195static int p54_config(struct ieee80211_hw *dev, struct ieee80211_conf *conf) 1195static int p54_config(struct ieee80211_hw *dev, u32 changed)
1196{ 1196{
1197 int ret; 1197 int ret;
1198 struct p54_common *priv = dev->priv; 1198 struct p54_common *priv = dev->priv;
1199 struct ieee80211_conf *conf = &dev->conf;
1199 1200
1200 mutex_lock(&priv->conf_mutex); 1201 mutex_lock(&priv->conf_mutex);
1201 priv->rx_antenna = 2; /* automatic */ 1202 priv->rx_antenna = 2; /* automatic */
diff --git a/drivers/net/wireless/rt2x00/rt2x00.h b/drivers/net/wireless/rt2x00/rt2x00.h
index 1359a3768404..8ec8f7e9ec64 100644
--- a/drivers/net/wireless/rt2x00/rt2x00.h
+++ b/drivers/net/wireless/rt2x00/rt2x00.h
@@ -997,7 +997,7 @@ int rt2x00mac_add_interface(struct ieee80211_hw *hw,
997 struct ieee80211_if_init_conf *conf); 997 struct ieee80211_if_init_conf *conf);
998void rt2x00mac_remove_interface(struct ieee80211_hw *hw, 998void rt2x00mac_remove_interface(struct ieee80211_hw *hw,
999 struct ieee80211_if_init_conf *conf); 999 struct ieee80211_if_init_conf *conf);
1000int rt2x00mac_config(struct ieee80211_hw *hw, struct ieee80211_conf *conf); 1000int rt2x00mac_config(struct ieee80211_hw *hw, u32 changed);
1001int rt2x00mac_config_interface(struct ieee80211_hw *hw, 1001int rt2x00mac_config_interface(struct ieee80211_hw *hw,
1002 struct ieee80211_vif *vif, 1002 struct ieee80211_vif *vif,
1003 struct ieee80211_if_conf *conf); 1003 struct ieee80211_if_conf *conf);
diff --git a/drivers/net/wireless/rt2x00/rt2x00dev.c b/drivers/net/wireless/rt2x00/rt2x00dev.c
index 9e0472bd1edf..697806cf94e2 100644
--- a/drivers/net/wireless/rt2x00/rt2x00dev.c
+++ b/drivers/net/wireless/rt2x00/rt2x00dev.c
@@ -1245,7 +1245,7 @@ int rt2x00lib_resume(struct rt2x00_dev *rt2x00dev)
1245 /* 1245 /*
1246 * Reconfigure device. 1246 * Reconfigure device.
1247 */ 1247 */
1248 retval = rt2x00mac_config(rt2x00dev->hw, &rt2x00dev->hw->conf); 1248 retval = rt2x00mac_config(rt2x00dev->hw, ~0);
1249 if (retval) 1249 if (retval)
1250 goto exit; 1250 goto exit;
1251 1251
diff --git a/drivers/net/wireless/rt2x00/rt2x00mac.c b/drivers/net/wireless/rt2x00/rt2x00mac.c
index 2c6cc5c374ff..da7b49a364ff 100644
--- a/drivers/net/wireless/rt2x00/rt2x00mac.c
+++ b/drivers/net/wireless/rt2x00/rt2x00mac.c
@@ -335,9 +335,10 @@ void rt2x00mac_remove_interface(struct ieee80211_hw *hw,
335} 335}
336EXPORT_SYMBOL_GPL(rt2x00mac_remove_interface); 336EXPORT_SYMBOL_GPL(rt2x00mac_remove_interface);
337 337
338int rt2x00mac_config(struct ieee80211_hw *hw, struct ieee80211_conf *conf) 338int rt2x00mac_config(struct ieee80211_hw *hw, u32 changed)
339{ 339{
340 struct rt2x00_dev *rt2x00dev = hw->priv; 340 struct rt2x00_dev *rt2x00dev = hw->priv;
341 struct ieee80211_conf *conf = &hw->conf;
341 int radio_on; 342 int radio_on;
342 int status; 343 int status;
343 344
diff --git a/drivers/net/wireless/rtl8180_dev.c b/drivers/net/wireless/rtl8180_dev.c
index 9de8f57486df..e8d22393797f 100644
--- a/drivers/net/wireless/rtl8180_dev.c
+++ b/drivers/net/wireless/rtl8180_dev.c
@@ -692,9 +692,10 @@ static void rtl8180_remove_interface(struct ieee80211_hw *dev,
692 priv->vif = NULL; 692 priv->vif = NULL;
693} 693}
694 694
695static int rtl8180_config(struct ieee80211_hw *dev, struct ieee80211_conf *conf) 695static int rtl8180_config(struct ieee80211_hw *dev, u32 changed)
696{ 696{
697 struct rtl8180_priv *priv = dev->priv; 697 struct rtl8180_priv *priv = dev->priv;
698 struct ieee80211_conf *conf = &dev->conf;
698 699
699 priv->rf->set_chan(dev, conf); 700 priv->rf->set_chan(dev, conf);
700 701
diff --git a/drivers/net/wireless/rtl8187_dev.c b/drivers/net/wireless/rtl8187_dev.c
index 9ceae9017f86..2c69ab37c650 100644
--- a/drivers/net/wireless/rtl8187_dev.c
+++ b/drivers/net/wireless/rtl8187_dev.c
@@ -873,9 +873,10 @@ static void rtl8187_remove_interface(struct ieee80211_hw *dev,
873 mutex_unlock(&priv->conf_mutex); 873 mutex_unlock(&priv->conf_mutex);
874} 874}
875 875
876static int rtl8187_config(struct ieee80211_hw *dev, struct ieee80211_conf *conf) 876static int rtl8187_config(struct ieee80211_hw *dev, u32 changed)
877{ 877{
878 struct rtl8187_priv *priv = dev->priv; 878 struct rtl8187_priv *priv = dev->priv;
879 struct ieee80211_conf *conf = &dev->conf;
879 u32 reg; 880 u32 reg;
880 881
881 mutex_lock(&priv->conf_mutex); 882 mutex_lock(&priv->conf_mutex);
diff --git a/drivers/net/wireless/zd1211rw/zd_mac.c b/drivers/net/wireless/zd1211rw/zd_mac.c
index de45509d757e..6c3e21887fc8 100644
--- a/drivers/net/wireless/zd1211rw/zd_mac.c
+++ b/drivers/net/wireless/zd1211rw/zd_mac.c
@@ -743,9 +743,11 @@ static void zd_op_remove_interface(struct ieee80211_hw *hw,
743 zd_write_mac_addr(&mac->chip, NULL); 743 zd_write_mac_addr(&mac->chip, NULL);
744} 744}
745 745
746static int zd_op_config(struct ieee80211_hw *hw, struct ieee80211_conf *conf) 746static int zd_op_config(struct ieee80211_hw *hw, u32 changed)
747{ 747{
748 struct zd_mac *mac = zd_hw_mac(hw); 748 struct zd_mac *mac = zd_hw_mac(hw);
749 struct ieee80211_conf *conf = &hw->conf;
750
749 return zd_chip_set_channel(&mac->chip, conf->channel->hw_value); 751 return zd_chip_set_channel(&mac->chip, conf->channel->hw_value);
750} 752}
751 753
diff --git a/include/net/mac80211.h b/include/net/mac80211.h
index 5f28b7f89887..34e8569b59bb 100644
--- a/include/net/mac80211.h
+++ b/include/net/mac80211.h
@@ -464,12 +464,32 @@ static inline int __deprecated __IEEE80211_CONF_SHORT_SLOT_TIME(void)
464#define IEEE80211_CONF_SHORT_SLOT_TIME (__IEEE80211_CONF_SHORT_SLOT_TIME()) 464#define IEEE80211_CONF_SHORT_SLOT_TIME (__IEEE80211_CONF_SHORT_SLOT_TIME())
465 465
466/** 466/**
467 * enum ieee80211_conf_changed - denotes which configuration changed
468 *
469 * @IEEE80211_CONF_CHANGE_RADIO_ENABLED: the value of radio_enabled changed
470 * @IEEE80211_CONF_CHANGE_BEACON_INTERVAL: the beacon interval changed
471 * @IEEE80211_CONF_CHANGE_LISTEN_INTERVAL: the listen interval changed
472 * @IEEE80211_CONF_CHANGE_RADIOTAP: the radiotap flag changed
473 * @IEEE80211_CONF_CHANGE_PS: the PS flag changed
474 * @IEEE80211_CONF_CHANGE_POWER: the TX power changed
475 * @IEEE80211_CONF_CHANGE_CHANNEL: the channel changed
476 */
477enum ieee80211_conf_changed {
478 IEEE80211_CONF_CHANGE_RADIO_ENABLED = BIT(0),
479 IEEE80211_CONF_CHANGE_BEACON_INTERVAL = BIT(1),
480 IEEE80211_CONF_CHANGE_LISTEN_INTERVAL = BIT(2),
481 IEEE80211_CONF_CHANGE_RADIOTAP = BIT(3),
482 IEEE80211_CONF_CHANGE_PS = BIT(4),
483 IEEE80211_CONF_CHANGE_POWER = BIT(5),
484 IEEE80211_CONF_CHANGE_CHANNEL = BIT(6),
485};
486
487/**
467 * struct ieee80211_conf - configuration of the device 488 * struct ieee80211_conf - configuration of the device
468 * 489 *
469 * This struct indicates how the driver shall configure the hardware. 490 * This struct indicates how the driver shall configure the hardware.
470 * 491 *
471 * @radio_enabled: when zero, driver is required to switch off the radio. 492 * @radio_enabled: when zero, driver is required to switch off the radio.
472 * TODO make a flag
473 * @beacon_int: beacon interval (TODO make interface config) 493 * @beacon_int: beacon interval (TODO make interface config)
474 * @listen_interval: listen interval in units of beacon interval 494 * @listen_interval: listen interval in units of beacon interval
475 * @flags: configuration flags defined above 495 * @flags: configuration flags defined above
@@ -479,13 +499,13 @@ static inline int __deprecated __IEEE80211_CONF_SHORT_SLOT_TIME(void)
479 * @channel: the channel to tune to 499 * @channel: the channel to tune to
480 */ 500 */
481struct ieee80211_conf { 501struct ieee80211_conf {
482 int radio_enabled;
483
484 int beacon_int; 502 int beacon_int;
485 u16 listen_interval;
486 u32 flags; 503 u32 flags;
487 int power_level; 504 int power_level;
488 505
506 u16 listen_interval;
507 bool radio_enabled;
508
489 struct ieee80211_channel *channel; 509 struct ieee80211_channel *channel;
490 510
491 struct ieee80211_sta_ht_cap ht_cap; 511 struct ieee80211_sta_ht_cap ht_cap;
@@ -1214,7 +1234,7 @@ struct ieee80211_ops {
1214 struct ieee80211_if_init_conf *conf); 1234 struct ieee80211_if_init_conf *conf);
1215 void (*remove_interface)(struct ieee80211_hw *hw, 1235 void (*remove_interface)(struct ieee80211_hw *hw,
1216 struct ieee80211_if_init_conf *conf); 1236 struct ieee80211_if_init_conf *conf);
1217 int (*config)(struct ieee80211_hw *hw, struct ieee80211_conf *conf); 1237 int (*config)(struct ieee80211_hw *hw, u32 changed);
1218 int (*config_interface)(struct ieee80211_hw *hw, 1238 int (*config_interface)(struct ieee80211_hw *hw,
1219 struct ieee80211_vif *vif, 1239 struct ieee80211_vif *vif,
1220 struct ieee80211_if_conf *conf); 1240 struct ieee80211_if_conf *conf);
diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c
index a5dea617aab3..8ea30902d5db 100644
--- a/net/mac80211/cfg.c
+++ b/net/mac80211/cfg.c
@@ -394,7 +394,8 @@ static int ieee80211_config_beacon(struct ieee80211_sub_if_data *sdata,
394 */ 394 */
395 if (params->interval) { 395 if (params->interval) {
396 sdata->local->hw.conf.beacon_int = params->interval; 396 sdata->local->hw.conf.beacon_int = params->interval;
397 ieee80211_hw_config(sdata->local); 397 ieee80211_hw_config(sdata->local,
398 IEEE80211_CONF_CHANGE_BEACON_INTERVAL);
398 /* 399 /*
399 * We updated some parameter so if below bails out 400 * We updated some parameter so if below bails out
400 * it's not an error. 401 * it's not an error.
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h
index 88015838a63c..1deb787ff8dc 100644
--- a/net/mac80211/ieee80211_i.h
+++ b/net/mac80211/ieee80211_i.h
@@ -875,7 +875,7 @@ static inline int ieee80211_bssid_match(const u8 *raddr, const u8 *addr)
875} 875}
876 876
877 877
878int ieee80211_hw_config(struct ieee80211_local *local); 878int ieee80211_hw_config(struct ieee80211_local *local, u32 changed);
879int ieee80211_if_config(struct ieee80211_sub_if_data *sdata, u32 changed); 879int ieee80211_if_config(struct ieee80211_sub_if_data *sdata, u32 changed);
880void ieee80211_tx_set_protected(struct ieee80211_tx_data *tx); 880void ieee80211_tx_set_protected(struct ieee80211_tx_data *tx);
881void ieee80211_bss_info_change_notify(struct ieee80211_sub_if_data *sdata, 881void ieee80211_bss_info_change_notify(struct ieee80211_sub_if_data *sdata,
diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c
index 8336fee68d3e..df28c5f7c9c0 100644
--- a/net/mac80211/iface.c
+++ b/net/mac80211/iface.c
@@ -65,7 +65,7 @@ static int ieee80211_open(struct net_device *dev)
65 struct ieee80211_if_init_conf conf; 65 struct ieee80211_if_init_conf conf;
66 u32 changed = 0; 66 u32 changed = 0;
67 int res; 67 int res;
68 bool need_hw_reconfig = 0; 68 u32 hw_reconf_flags = 0;
69 u8 null_addr[ETH_ALEN] = {0}; 69 u8 null_addr[ETH_ALEN] = {0};
70 70
71 /* fail early if user set an invalid address */ 71 /* fail early if user set an invalid address */
@@ -152,7 +152,8 @@ static int ieee80211_open(struct net_device *dev)
152 res = local->ops->start(local_to_hw(local)); 152 res = local->ops->start(local_to_hw(local));
153 if (res) 153 if (res)
154 goto err_del_bss; 154 goto err_del_bss;
155 need_hw_reconfig = 1; 155 /* we're brought up, everything changes */
156 hw_reconf_flags = ~0;
156 ieee80211_led_radio(local, local->hw.conf.radio_enabled); 157 ieee80211_led_radio(local, local->hw.conf.radio_enabled);
157 } 158 }
158 159
@@ -198,8 +199,10 @@ static int ieee80211_open(struct net_device *dev)
198 199
199 /* must be before the call to ieee80211_configure_filter */ 200 /* must be before the call to ieee80211_configure_filter */
200 local->monitors++; 201 local->monitors++;
201 if (local->monitors == 1) 202 if (local->monitors == 1) {
202 local->hw.conf.flags |= IEEE80211_CONF_RADIOTAP; 203 local->hw.conf.flags |= IEEE80211_CONF_RADIOTAP;
204 hw_reconf_flags |= IEEE80211_CONF_CHANGE_RADIOTAP;
205 }
203 206
204 if (sdata->u.mntr_flags & MONITOR_FLAG_FCSFAIL) 207 if (sdata->u.mntr_flags & MONITOR_FLAG_FCSFAIL)
205 local->fif_fcsfail++; 208 local->fif_fcsfail++;
@@ -279,8 +282,8 @@ static int ieee80211_open(struct net_device *dev)
279 atomic_inc(&local->iff_promiscs); 282 atomic_inc(&local->iff_promiscs);
280 283
281 local->open_count++; 284 local->open_count++;
282 if (need_hw_reconfig) { 285 if (hw_reconf_flags) {
283 ieee80211_hw_config(local); 286 ieee80211_hw_config(local, hw_reconf_flags);
284 /* 287 /*
285 * set default queue parameters so drivers don't 288 * set default queue parameters so drivers don't
286 * need to initialise the hardware if the hardware 289 * need to initialise the hardware if the hardware
@@ -322,6 +325,7 @@ static int ieee80211_stop(struct net_device *dev)
322 struct ieee80211_local *local = sdata->local; 325 struct ieee80211_local *local = sdata->local;
323 struct ieee80211_if_init_conf conf; 326 struct ieee80211_if_init_conf conf;
324 struct sta_info *sta; 327 struct sta_info *sta;
328 u32 hw_reconf_flags = 0;
325 329
326 /* 330 /*
327 * Stop TX on this interface first. 331 * Stop TX on this interface first.
@@ -405,8 +409,10 @@ static int ieee80211_stop(struct net_device *dev)
405 } 409 }
406 410
407 local->monitors--; 411 local->monitors--;
408 if (local->monitors == 0) 412 if (local->monitors == 0) {
409 local->hw.conf.flags &= ~IEEE80211_CONF_RADIOTAP; 413 local->hw.conf.flags &= ~IEEE80211_CONF_RADIOTAP;
414 hw_reconf_flags |= IEEE80211_CONF_CHANGE_RADIOTAP;
415 }
410 416
411 if (sdata->u.mntr_flags & MONITOR_FLAG_FCSFAIL) 417 if (sdata->u.mntr_flags & MONITOR_FLAG_FCSFAIL)
412 local->fif_fcsfail--; 418 local->fif_fcsfail--;
@@ -504,8 +510,15 @@ static int ieee80211_stop(struct net_device *dev)
504 510
505 tasklet_disable(&local->tx_pending_tasklet); 511 tasklet_disable(&local->tx_pending_tasklet);
506 tasklet_disable(&local->tasklet); 512 tasklet_disable(&local->tasklet);
513
514 /* no reconfiguring after stop! */
515 hw_reconf_flags = 0;
507 } 516 }
508 517
518 /* do after stop to avoid reconfiguring when we stop anyway */
519 if (hw_reconf_flags)
520 ieee80211_hw_config(local, hw_reconf_flags);
521
509 return 0; 522 return 0;
510} 523}
511 524
diff --git a/net/mac80211/main.c b/net/mac80211/main.c
index 07f812755e55..c936017f6d48 100644
--- a/net/mac80211/main.c
+++ b/net/mac80211/main.c
@@ -197,31 +197,34 @@ int ieee80211_if_config(struct ieee80211_sub_if_data *sdata, u32 changed)
197 &sdata->vif, &conf); 197 &sdata->vif, &conf);
198} 198}
199 199
200int ieee80211_hw_config(struct ieee80211_local *local) 200int ieee80211_hw_config(struct ieee80211_local *local, u32 changed)
201{ 201{
202 struct ieee80211_channel *chan; 202 struct ieee80211_channel *chan;
203 int ret = 0; 203 int ret = 0;
204 int power;
204 205
205 if (local->sw_scanning) 206 if (local->sw_scanning)
206 chan = local->scan_channel; 207 chan = local->scan_channel;
207 else 208 else
208 chan = local->oper_channel; 209 chan = local->oper_channel;
209 210
210 local->hw.conf.channel = chan; 211 if (chan != local->hw.conf.channel) {
212 local->hw.conf.channel = chan;
213 changed |= IEEE80211_CONF_CHANGE_CHANNEL;
214 }
215
211 216
212 if (!local->hw.conf.power_level) 217 if (!local->hw.conf.power_level)
213 local->hw.conf.power_level = chan->max_power; 218 power = chan->max_power;
214 else 219 else
215 local->hw.conf.power_level = min(chan->max_power, 220 power = min(chan->max_power, local->hw.conf.power_level);
216 local->hw.conf.power_level); 221 if (local->hw.conf.power_level != power) {
217 222 changed |= IEEE80211_CONF_CHANGE_POWER;
218#ifdef CONFIG_MAC80211_VERBOSE_DEBUG 223 local->hw.conf.power_level = power;
219 printk(KERN_DEBUG "%s: HW CONFIG: freq=%d\n", 224 }
220 wiphy_name(local->hw.wiphy), chan->center_freq);
221#endif
222 225
223 if (local->open_count) { 226 if (changed && local->open_count) {
224 ret = local->ops->config(local_to_hw(local), &local->hw.conf); 227 ret = local->ops->config(local_to_hw(local), changed);
225 /* 228 /*
226 * HW reconfiguration should never fail, the driver has told 229 * HW reconfiguration should never fail, the driver has told
227 * us what it can support so it should live up to that promise. 230 * us what it can support so it should live up to that promise.
@@ -672,7 +675,7 @@ struct ieee80211_hw *ieee80211_alloc_hw(size_t priv_data_len,
672 local->fragmentation_threshold = IEEE80211_MAX_FRAG_THRESHOLD; 675 local->fragmentation_threshold = IEEE80211_MAX_FRAG_THRESHOLD;
673 local->short_retry_limit = 7; 676 local->short_retry_limit = 7;
674 local->long_retry_limit = 4; 677 local->long_retry_limit = 4;
675 local->hw.conf.radio_enabled = 1; 678 local->hw.conf.radio_enabled = true;
676 679
677 INIT_LIST_HEAD(&local->interfaces); 680 INIT_LIST_HEAD(&local->interfaces);
678 681
diff --git a/net/mac80211/scan.c b/net/mac80211/scan.c
index 0989b1c062e3..7372d7abb8c0 100644
--- a/net/mac80211/scan.c
+++ b/net/mac80211/scan.c
@@ -448,12 +448,17 @@ void ieee80211_scan_completed(struct ieee80211_hw *hw)
448 448
449 if (local->hw_scanning) { 449 if (local->hw_scanning) {
450 local->hw_scanning = false; 450 local->hw_scanning = false;
451 ieee80211_hw_config(local); 451 /*
452 * Somebody might have requested channel change during scan
453 * that we won't have acted upon, try now. ieee80211_hw_config
454 * will set the flag based on actual changes.
455 */
456 ieee80211_hw_config(local, 0);
452 goto done; 457 goto done;
453 } 458 }
454 459
455 local->sw_scanning = false; 460 local->sw_scanning = false;
456 ieee80211_hw_config(local); 461 ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_CHANNEL);
457 462
458 netif_tx_lock_bh(local->mdev); 463 netif_tx_lock_bh(local->mdev);
459 netif_addr_lock(local->mdev); 464 netif_addr_lock(local->mdev);
@@ -540,7 +545,8 @@ void ieee80211_scan_work(struct work_struct *work)
540 545
541 if (!skip) { 546 if (!skip) {
542 local->scan_channel = chan; 547 local->scan_channel = chan;
543 if (ieee80211_hw_config(local)) 548 if (ieee80211_hw_config(local,
549 IEEE80211_CONF_CHANGE_CHANNEL))
544 skip = 1; 550 skip = 1;
545 } 551 }
546 552
diff --git a/net/mac80211/util.c b/net/mac80211/util.c
index 9941a60a2327..3288c3de67ca 100644
--- a/net/mac80211/util.c
+++ b/net/mac80211/util.c
@@ -645,7 +645,8 @@ int ieee80211_set_freq(struct ieee80211_sub_if_data *sdata, int freqMHz)
645 if (local->sw_scanning || local->hw_scanning) 645 if (local->sw_scanning || local->hw_scanning)
646 ret = 0; 646 ret = 0;
647 else 647 else
648 ret = ieee80211_hw_config(local); 648 ret = ieee80211_hw_config(
649 local, IEEE80211_CONF_CHANGE_CHANNEL);
649 650
650 rate_control_clear(local); 651 rate_control_clear(local);
651 } 652 }
diff --git a/net/mac80211/wext.c b/net/mac80211/wext.c
index a3af15141244..94c4b35eeb14 100644
--- a/net/mac80211/wext.c
+++ b/net/mac80211/wext.c
@@ -656,7 +656,7 @@ static int ieee80211_ioctl_siwtxpower(struct net_device *dev,
656 union iwreq_data *data, char *extra) 656 union iwreq_data *data, char *extra)
657{ 657{
658 struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); 658 struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
659 bool need_reconfig = 0; 659 u32 reconf_flags = 0;
660 int new_power_level; 660 int new_power_level;
661 661
662 if ((data->txpower.flags & IW_TXPOW_TYPE) != IW_TXPOW_DBM) 662 if ((data->txpower.flags & IW_TXPOW_TYPE) != IW_TXPOW_DBM)
@@ -680,17 +680,17 @@ static int ieee80211_ioctl_siwtxpower(struct net_device *dev,
680 680
681 if (local->hw.conf.power_level != new_power_level) { 681 if (local->hw.conf.power_level != new_power_level) {
682 local->hw.conf.power_level = new_power_level; 682 local->hw.conf.power_level = new_power_level;
683 need_reconfig = 1; 683 reconf_flags |= IEEE80211_CONF_CHANGE_POWER;
684 } 684 }
685 685
686 if (local->hw.conf.radio_enabled != !(data->txpower.disabled)) { 686 if (local->hw.conf.radio_enabled != !(data->txpower.disabled)) {
687 local->hw.conf.radio_enabled = !(data->txpower.disabled); 687 local->hw.conf.radio_enabled = !(data->txpower.disabled);
688 need_reconfig = 1; 688 reconf_flags |= IEEE80211_CONF_CHANGE_RADIO_ENABLED;
689 ieee80211_led_radio(local, local->hw.conf.radio_enabled); 689 ieee80211_led_radio(local, local->hw.conf.radio_enabled);
690 } 690 }
691 691
692 if (need_reconfig) 692 if (reconf_flags)
693 ieee80211_hw_config(local); 693 ieee80211_hw_config(local, reconf_flags);
694 694
695 return 0; 695 return 0;
696} 696}
@@ -976,7 +976,7 @@ static int ieee80211_ioctl_siwpower(struct net_device *dev,
976 976
977 if (wrq->disabled) { 977 if (wrq->disabled) {
978 conf->flags &= ~IEEE80211_CONF_PS; 978 conf->flags &= ~IEEE80211_CONF_PS;
979 return ieee80211_hw_config(local); 979 return ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_PS);
980 } 980 }
981 981
982 switch (wrq->flags & IW_POWER_MODE) { 982 switch (wrq->flags & IW_POWER_MODE) {
@@ -989,7 +989,7 @@ static int ieee80211_ioctl_siwpower(struct net_device *dev,
989 return -EINVAL; 989 return -EINVAL;
990 } 990 }
991 991
992 return ieee80211_hw_config(local); 992 return ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_PS);
993} 993}
994 994
995static int ieee80211_ioctl_giwpower(struct net_device *dev, 995static int ieee80211_ioctl_giwpower(struct net_device *dev,