diff options
author | Sujith <Sujith.Manoharan@atheros.com> | 2009-01-05 22:58:37 -0500 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2009-01-29 15:59:50 -0500 |
commit | c481ec9705d4a5d566393bc17374cfd82c870715 (patch) | |
tree | 383b90aa8cf172ee81a7e91c49440cf75c8c0278 /net/mac80211/spectmgmt.c | |
parent | b522ed56ef90f5078a2a1253e390299723510a89 (diff) |
mac80211: Add 802.11h CSA support
Move to the advertised channel on reception of
a CSA element. This is needed for 802.11h compliance.
Signed-off-by: Sujith <Sujith.Manoharan@atheros.com>
Acked-by: Johannes Berg <johannes@sipsolutions.net>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'net/mac80211/spectmgmt.c')
-rw-r--r-- | net/mac80211/spectmgmt.c | 77 |
1 files changed, 77 insertions, 0 deletions
diff --git a/net/mac80211/spectmgmt.c b/net/mac80211/spectmgmt.c index f72bad636d8e..22ad4808e01a 100644 --- a/net/mac80211/spectmgmt.c +++ b/net/mac80211/spectmgmt.c | |||
@@ -84,3 +84,80 @@ void ieee80211_process_measurement_req(struct ieee80211_sub_if_data *sdata, | |||
84 | mgmt->sa, mgmt->bssid, | 84 | mgmt->sa, mgmt->bssid, |
85 | mgmt->u.action.u.measurement.dialog_token); | 85 | mgmt->u.action.u.measurement.dialog_token); |
86 | } | 86 | } |
87 | |||
88 | void ieee80211_chswitch_work(struct work_struct *work) | ||
89 | { | ||
90 | struct ieee80211_sub_if_data *sdata = | ||
91 | container_of(work, struct ieee80211_sub_if_data, u.sta.chswitch_work); | ||
92 | struct ieee80211_bss *bss; | ||
93 | struct ieee80211_if_sta *ifsta = &sdata->u.sta; | ||
94 | |||
95 | if (!netif_running(sdata->dev)) | ||
96 | return; | ||
97 | |||
98 | bss = ieee80211_rx_bss_get(sdata->local, ifsta->bssid, | ||
99 | sdata->local->hw.conf.channel->center_freq, | ||
100 | ifsta->ssid, ifsta->ssid_len); | ||
101 | if (!bss) | ||
102 | goto exit; | ||
103 | |||
104 | sdata->local->oper_channel = sdata->local->csa_channel; | ||
105 | if (!ieee80211_hw_config(sdata->local, IEEE80211_CONF_CHANGE_CHANNEL)) | ||
106 | bss->freq = sdata->local->oper_channel->center_freq; | ||
107 | |||
108 | ieee80211_rx_bss_put(sdata->local, bss); | ||
109 | exit: | ||
110 | ifsta->flags &= ~IEEE80211_STA_CSA_RECEIVED; | ||
111 | ieee80211_wake_queues_by_reason(&sdata->local->hw, | ||
112 | IEEE80211_QUEUE_STOP_REASON_CSA); | ||
113 | } | ||
114 | |||
115 | void ieee80211_chswitch_timer(unsigned long data) | ||
116 | { | ||
117 | struct ieee80211_sub_if_data *sdata = | ||
118 | (struct ieee80211_sub_if_data *) data; | ||
119 | struct ieee80211_if_sta *ifsta = &sdata->u.sta; | ||
120 | |||
121 | queue_work(sdata->local->hw.workqueue, &ifsta->chswitch_work); | ||
122 | } | ||
123 | |||
124 | void ieee80211_process_chanswitch(struct ieee80211_sub_if_data *sdata, | ||
125 | struct ieee80211_channel_sw_ie *sw_elem, | ||
126 | struct ieee80211_bss *bss) | ||
127 | { | ||
128 | struct ieee80211_channel *new_ch; | ||
129 | struct ieee80211_if_sta *ifsta = &sdata->u.sta; | ||
130 | int new_freq = ieee80211_channel_to_frequency(sw_elem->new_ch_num); | ||
131 | |||
132 | /* FIXME: Handle ADHOC later */ | ||
133 | if (sdata->vif.type != NL80211_IFTYPE_STATION) | ||
134 | return; | ||
135 | |||
136 | if (ifsta->state != IEEE80211_STA_MLME_ASSOCIATED) | ||
137 | return; | ||
138 | |||
139 | if (sdata->local->sw_scanning || sdata->local->hw_scanning) | ||
140 | return; | ||
141 | |||
142 | /* Disregard subsequent beacons if we are already running a timer | ||
143 | processing a CSA */ | ||
144 | |||
145 | if (ifsta->flags & IEEE80211_STA_CSA_RECEIVED) | ||
146 | return; | ||
147 | |||
148 | new_ch = ieee80211_get_channel(sdata->local->hw.wiphy, new_freq); | ||
149 | if (!new_ch || new_ch->flags & IEEE80211_CHAN_DISABLED) | ||
150 | return; | ||
151 | |||
152 | sdata->local->csa_channel = new_ch; | ||
153 | |||
154 | if (sw_elem->count <= 1) { | ||
155 | queue_work(sdata->local->hw.workqueue, &ifsta->chswitch_work); | ||
156 | } else { | ||
157 | ieee80211_stop_queues_by_reason(&sdata->local->hw, | ||
158 | IEEE80211_QUEUE_STOP_REASON_CSA); | ||
159 | ifsta->flags |= IEEE80211_STA_CSA_RECEIVED; | ||
160 | mod_timer(&ifsta->chswitch_timer, | ||
161 | jiffies + msecs_to_jiffies(sw_elem->count * bss->beacon_int)); | ||
162 | } | ||
163 | } | ||