aboutsummaryrefslogtreecommitdiffstats
path: root/net/mac80211
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 /net/mac80211
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>
Diffstat (limited to 'net/mac80211')
-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
7 files changed, 56 insertions, 32 deletions
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,