OLD | NEW |
1 /* | 1 /* |
2 * Copyright 2002-2005, Instant802 Networks, Inc. | 2 * Copyright 2002-2005, Instant802 Networks, Inc. |
3 * Copyright 2005-2006, Devicescape Software, Inc. | 3 * Copyright 2005-2006, Devicescape Software, Inc. |
4 * Copyright 2006-2007 Jiri Benc <jbenc@suse.cz> | 4 * Copyright 2006-2007 Jiri Benc <jbenc@suse.cz> |
5 * | 5 * |
6 * This program is free software; you can redistribute it and/or modify | 6 * This program is free software; you can redistribute it and/or modify |
7 * it under the terms of the GNU General Public License version 2 as | 7 * it under the terms of the GNU General Public License version 2 as |
8 * published by the Free Software Foundation. | 8 * published by the Free Software Foundation. |
9 */ | 9 */ |
10 | 10 |
(...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
96 | 96 |
97 ieee80211_configure_filter(local); | 97 ieee80211_configure_filter(local); |
98 } | 98 } |
99 | 99 |
100 int ieee80211_hw_config(struct ieee80211_local *local, u32 changed) | 100 int ieee80211_hw_config(struct ieee80211_local *local, u32 changed) |
101 { | 101 { |
102 struct ieee80211_channel *chan, *scan_chan; | 102 struct ieee80211_channel *chan, *scan_chan; |
103 int ret = 0; | 103 int ret = 0; |
104 int power; | 104 int power; |
105 enum nl80211_channel_type channel_type; | 105 enum nl80211_channel_type channel_type; |
| 106 u32 offchannel_flag; |
106 | 107 |
107 might_sleep(); | 108 might_sleep(); |
108 | 109 |
109 scan_chan = local->scan_channel; | 110 scan_chan = local->scan_channel; |
110 | 111 |
| 112 offchannel_flag = local->hw.conf.flags & IEEE80211_CONF_OFFCHANNEL; |
111 if (scan_chan) { | 113 if (scan_chan) { |
112 chan = scan_chan; | 114 chan = scan_chan; |
113 channel_type = NL80211_CHAN_NO_HT; | 115 channel_type = NL80211_CHAN_NO_HT; |
114 local->hw.conf.flags |= IEEE80211_CONF_OFFCHANNEL; | 116 local->hw.conf.flags |= IEEE80211_CONF_OFFCHANNEL; |
115 » } else if (local->tmp_channel) { | 117 » } else if (local->tmp_channel && |
| 118 » » local->oper_channel != local->tmp_channel) { |
116 chan = scan_chan = local->tmp_channel; | 119 chan = scan_chan = local->tmp_channel; |
117 channel_type = local->tmp_channel_type; | 120 channel_type = local->tmp_channel_type; |
118 local->hw.conf.flags |= IEEE80211_CONF_OFFCHANNEL; | 121 local->hw.conf.flags |= IEEE80211_CONF_OFFCHANNEL; |
119 } else { | 122 } else { |
120 chan = local->oper_channel; | 123 chan = local->oper_channel; |
121 channel_type = local->_oper_channel_type; | 124 channel_type = local->_oper_channel_type; |
122 local->hw.conf.flags &= ~IEEE80211_CONF_OFFCHANNEL; | 125 local->hw.conf.flags &= ~IEEE80211_CONF_OFFCHANNEL; |
123 } | 126 } |
| 127 offchannel_flag ^= local->hw.conf.flags & IEEE80211_CONF_OFFCHANNEL; |
124 | 128 |
125 » if (chan != local->hw.conf.channel || | 129 » if (offchannel_flag || chan != local->hw.conf.channel || |
126 channel_type != local->hw.conf.channel_type) { | 130 channel_type != local->hw.conf.channel_type) { |
127 local->hw.conf.channel = chan; | 131 local->hw.conf.channel = chan; |
128 local->hw.conf.channel_type = channel_type; | 132 local->hw.conf.channel_type = channel_type; |
129 changed |= IEEE80211_CONF_CHANGE_CHANNEL; | 133 changed |= IEEE80211_CONF_CHANGE_CHANNEL; |
130 } | 134 } |
131 | 135 |
132 if (!conf_is_ht(&local->hw.conf)) { | 136 if (!conf_is_ht(&local->hw.conf)) { |
133 /* | 137 /* |
134 * mac80211.h documents that this is only valid | 138 * mac80211.h documents that this is only valid |
135 * when the channel is set to an HT type, and | 139 * when the channel is set to an HT type, and |
(...skipping 595 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
731 | 735 |
732 /* | 736 /* |
733 * At this point, interface list manipulations are fine | 737 * At this point, interface list manipulations are fine |
734 * because the driver cannot be handing us frames any | 738 * because the driver cannot be handing us frames any |
735 * more and the tasklet is killed. | 739 * more and the tasklet is killed. |
736 */ | 740 */ |
737 ieee80211_remove_interfaces(local); | 741 ieee80211_remove_interfaces(local); |
738 | 742 |
739 rtnl_unlock(); | 743 rtnl_unlock(); |
740 | 744 |
| 745 /* |
| 746 * Now all work items will be gone, but the |
| 747 * timer might still be armed, so delete it |
| 748 */ |
| 749 del_timer_sync(&local->work_timer); |
| 750 |
741 cancel_work_sync(&local->reconfig_filter); | 751 cancel_work_sync(&local->reconfig_filter); |
742 | 752 |
743 ieee80211_clear_tx_pending(local); | 753 ieee80211_clear_tx_pending(local); |
744 sta_info_stop(local); | 754 sta_info_stop(local); |
745 rate_control_deinitialize(local); | 755 rate_control_deinitialize(local); |
746 | 756 |
747 if (skb_queue_len(&local->skb_queue) || | 757 if (skb_queue_len(&local->skb_queue) || |
748 skb_queue_len(&local->skb_queue_unreliable)) | 758 skb_queue_len(&local->skb_queue_unreliable)) |
749 printk(KERN_WARNING "%s: skb_queue not empty\n", | 759 printk(KERN_WARNING "%s: skb_queue not empty\n", |
750 wiphy_name(local->hw.wiphy)); | 760 wiphy_name(local->hw.wiphy)); |
(...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
823 | 833 |
824 ieee80211_iface_exit(); | 834 ieee80211_iface_exit(); |
825 } | 835 } |
826 | 836 |
827 | 837 |
828 subsys_initcall(ieee80211_init); | 838 subsys_initcall(ieee80211_init); |
829 module_exit(ieee80211_exit); | 839 module_exit(ieee80211_exit); |
830 | 840 |
831 MODULE_DESCRIPTION("IEEE 802.11 subsystem"); | 841 MODULE_DESCRIPTION("IEEE 802.11 subsystem"); |
832 MODULE_LICENSE("GPL"); | 842 MODULE_LICENSE("GPL"); |
OLD | NEW |