aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDan Williams <dcbw@redhat.com>2007-05-25 16:46:33 -0400
committerJohn W. Linville <linville@tuxdriver.com>2007-06-11 14:28:42 -0400
commitef9a264b7a288a07c43ddb244c4f9ab0e8df90e4 (patch)
tree67dad09f719d1e91cb168143db2215b9a84dd942
parentd43fb8ee3dab261e475d4f5189cf86182139b7f4 (diff)
[PATCH] libertas: move channel changing into association framework
Handle channel changes through the deferred association framework rather than directly. Fixes errors when setting channels along with other parameters like mode and SSID. Signed-off-by: Dan Williams <dcbw@redhat.com> Signed-off-by: John W. Linville <linville@tuxdriver.com>
-rw-r--r--drivers/net/wireless/libertas/assoc.c81
-rw-r--r--drivers/net/wireless/libertas/dev.h1
-rw-r--r--drivers/net/wireless/libertas/fw.c2
-rw-r--r--drivers/net/wireless/libertas/join.c13
-rw-r--r--drivers/net/wireless/libertas/wext.c182
5 files changed, 117 insertions, 162 deletions
diff --git a/drivers/net/wireless/libertas/assoc.c b/drivers/net/wireless/libertas/assoc.c
index 4bc128fa5848..3f2dfaf879c5 100644
--- a/drivers/net/wireless/libertas/assoc.c
+++ b/drivers/net/wireless/libertas/assoc.c
@@ -22,6 +22,10 @@ static int assoc_helper_essid(wlan_private *priv,
22 22
23 lbs_deb_enter(LBS_DEB_ASSOC); 23 lbs_deb_enter(LBS_DEB_ASSOC);
24 24
25 /* FIXME: take channel into account when picking SSIDs if a channel
26 * is set.
27 */
28
25 lbs_deb_assoc("New SSID requested: %s\n", assoc_req->ssid.ssid); 29 lbs_deb_assoc("New SSID requested: %s\n", assoc_req->ssid.ssid);
26 if (assoc_req->mode == IW_MODE_INFRA) { 30 if (assoc_req->mode == IW_MODE_INFRA) {
27 if (adapter->prescan) { 31 if (adapter->prescan) {
@@ -158,6 +162,69 @@ done:
158} 162}
159 163
160 164
165static int update_channel(wlan_private * priv)
166{
167 /* the channel in f/w could be out of sync, get the current channel */
168 return libertas_prepare_and_send_command(priv, cmd_802_11_rf_channel,
169 cmd_opt_802_11_rf_channel_get,
170 cmd_option_waitforrsp, 0, NULL);
171}
172
173static int assoc_helper_channel(wlan_private *priv,
174 struct assoc_request * assoc_req)
175{
176 wlan_adapter *adapter = priv->adapter;
177 int ret = 0;
178
179 lbs_deb_enter(LBS_DEB_ASSOC);
180
181 ret = update_channel(priv);
182 if (ret < 0) {
183 lbs_deb_assoc("ASSOC: channel: error getting channel.");
184 }
185
186 if (assoc_req->channel == adapter->curbssparams.channel)
187 goto done;
188
189 lbs_deb_assoc("ASSOC: channel: %d -> %d\n",
190 adapter->curbssparams.channel, assoc_req->channel);
191
192 ret = libertas_prepare_and_send_command(priv, cmd_802_11_rf_channel,
193 cmd_opt_802_11_rf_channel_set,
194 cmd_option_waitforrsp, 0, &assoc_req->channel);
195 if (ret < 0) {
196 lbs_deb_assoc("ASSOC: channel: error setting channel.");
197 }
198
199 ret = update_channel(priv);
200 if (ret < 0) {
201 lbs_deb_assoc("ASSOC: channel: error getting channel.");
202 }
203
204 if (assoc_req->channel != adapter->curbssparams.channel) {
205 lbs_deb_assoc("ASSOC: channel: failed to update channel to %d",
206 assoc_req->channel);
207 goto done;
208 }
209
210 if ( assoc_req->secinfo.wep_enabled
211 && (assoc_req->wep_keys[0].len
212 || assoc_req->wep_keys[1].len
213 || assoc_req->wep_keys[2].len
214 || assoc_req->wep_keys[3].len)) {
215 /* Make sure WEP keys are re-sent to firmware */
216 set_bit(ASSOC_FLAG_WEP_KEYS, &assoc_req->flags);
217 }
218
219 /* Must restart/rejoin adhoc networks after channel change */
220 set_bit(ASSOC_FLAG_SSID, &assoc_req->flags);
221
222done:
223 lbs_deb_leave_args(LBS_DEB_ASSOC, "ret %d", ret);
224 return ret;
225}
226
227
161static int assoc_helper_wep_keys(wlan_private *priv, 228static int assoc_helper_wep_keys(wlan_private *priv,
162 struct assoc_request * assoc_req) 229 struct assoc_request * assoc_req)
163{ 230{
@@ -334,6 +401,11 @@ static int should_stop_adhoc(wlan_adapter *adapter,
334 return 1; 401 return 1;
335 } 402 }
336 403
404 if (test_bit(ASSOC_FLAG_CHANNEL, &assoc_req->flags)) {
405 if (assoc_req->channel != adapter->curbssparams.channel)
406 return 1;
407 }
408
337 return 0; 409 return 0;
338} 410}
339 411
@@ -423,6 +495,15 @@ lbs_deb_assoc("ASSOC(:%d) mode: ret = %d\n", __LINE__, ret);
423 } 495 }
424 } 496 }
425 497
498 if (test_bit(ASSOC_FLAG_CHANNEL, &assoc_req->flags)) {
499 ret = assoc_helper_channel(priv, assoc_req);
500 if (ret) {
501 lbs_deb_assoc("ASSOC(:%d) channel: ret = %d\n",
502 __LINE__, ret);
503 goto out;
504 }
505 }
506
426 if ( test_bit(ASSOC_FLAG_WEP_KEYS, &assoc_req->flags) 507 if ( test_bit(ASSOC_FLAG_WEP_KEYS, &assoc_req->flags)
427 || test_bit(ASSOC_FLAG_WEP_TX_KEYIDX, &assoc_req->flags)) { 508 || test_bit(ASSOC_FLAG_WEP_TX_KEYIDX, &assoc_req->flags)) {
428 ret = assoc_helper_wep_keys(priv, assoc_req); 509 ret = assoc_helper_wep_keys(priv, assoc_req);
diff --git a/drivers/net/wireless/libertas/dev.h b/drivers/net/wireless/libertas/dev.h
index 41d8a4cdd43b..4ca60d9323b4 100644
--- a/drivers/net/wireless/libertas/dev.h
+++ b/drivers/net/wireless/libertas/dev.h
@@ -287,7 +287,6 @@ struct _wlan_adapter {
287 u32 txantenna; 287 u32 txantenna;
288 u32 rxantenna; 288 u32 rxantenna;
289 289
290 u8 adhocchannel;
291 u32 fragthsd; 290 u32 fragthsd;
292 u32 rtsthsd; 291 u32 rtsthsd;
293 292
diff --git a/drivers/net/wireless/libertas/fw.c b/drivers/net/wireless/libertas/fw.c
index 56b272d62a86..2e535ef7e803 100644
--- a/drivers/net/wireless/libertas/fw.c
+++ b/drivers/net/wireless/libertas/fw.c
@@ -220,8 +220,6 @@ static void wlan_init_adapter(wlan_private * priv)
220 memset(&adapter->capinfo, 0, sizeof(adapter->capinfo)); 220 memset(&adapter->capinfo, 0, sizeof(adapter->capinfo));
221 adapter->capinfo.shortpreamble = SHORT_PREAMBLE_ALLOWED; 221 adapter->capinfo.shortpreamble = SHORT_PREAMBLE_ALLOWED;
222 222
223 adapter->adhocchannel = DEFAULT_AD_HOC_CHANNEL;
224
225 adapter->psmode = wlan802_11powermodecam; 223 adapter->psmode = wlan802_11powermodecam;
226 adapter->multipledtim = MRVDRV_DEFAULT_MULTIPLE_DTIM; 224 adapter->multipledtim = MRVDRV_DEFAULT_MULTIPLE_DTIM;
227 225
diff --git a/drivers/net/wireless/libertas/join.c b/drivers/net/wireless/libertas/join.c
index c9111b877067..a11ce3a6f611 100644
--- a/drivers/net/wireless/libertas/join.c
+++ b/drivers/net/wireless/libertas/join.c
@@ -158,7 +158,6 @@ int libertas_start_adhoc_network(wlan_private * priv, struct WLAN_802_11_SSID *a
158 158
159 libertas_set_radio_control(priv); 159 libertas_set_radio_control(priv);
160 160
161 lbs_deb_join("Adhoc channel = %d\n", adapter->adhocchannel);
162 lbs_deb_join("curbssparams.channel = %d\n", 161 lbs_deb_join("curbssparams.channel = %d\n",
163 adapter->curbssparams.channel); 162 adapter->curbssparams.channel);
164 lbs_deb_join("curbssparams.band = %d\n", adapter->curbssparams.band); 163 lbs_deb_join("curbssparams.band = %d\n", adapter->curbssparams.band);
@@ -513,15 +512,13 @@ int libertas_cmd_80211_ad_hoc_start(wlan_private * priv,
513 adhs->phyparamset.dsparamset.elementid = DS_PARA_IE_ID; 512 adhs->phyparamset.dsparamset.elementid = DS_PARA_IE_ID;
514 adhs->phyparamset.dsparamset.len = DS_PARA_IE_LEN; 513 adhs->phyparamset.dsparamset.len = DS_PARA_IE_LEN;
515 514
516 WARN_ON(!adapter->adhocchannel); 515 WARN_ON(!adapter->curbssparams.channel);
517 516
518 lbs_deb_join("ADHOC_S_CMD: Creating ADHOC on channel %d\n", 517 lbs_deb_join("ADHOC_S_CMD: Creating ADHOC on channel %d\n",
519 adapter->adhocchannel); 518 adapter->curbssparams.channel);
520
521 adapter->curbssparams.channel = adapter->adhocchannel;
522 519
523 pbssdesc->channel = adapter->adhocchannel; 520 pbssdesc->channel = adapter->curbssparams.channel;
524 adhs->phyparamset.dsparamset.currentchan = adapter->adhocchannel; 521 adhs->phyparamset.dsparamset.currentchan = adapter->curbssparams.channel;
525 522
526 memcpy(&pbssdesc->phyparamset, 523 memcpy(&pbssdesc->phyparamset,
527 &adhs->phyparamset, sizeof(union ieeetypes_phyparamset)); 524 &adhs->phyparamset, sizeof(union ieeetypes_phyparamset));
@@ -909,7 +906,7 @@ int libertas_ret_80211_ad_hoc_start(wlan_private * priv,
909 wireless_send_event(priv->dev, SIOCGIWAP, &wrqu, NULL); 906 wireless_send_event(priv->dev, SIOCGIWAP, &wrqu, NULL);
910 907
911 lbs_deb_join("ADHOC_RESP: - Joined/Started Ad Hoc\n"); 908 lbs_deb_join("ADHOC_RESP: - Joined/Started Ad Hoc\n");
912 lbs_deb_join("ADHOC_RESP: channel = %d\n", adapter->adhocchannel); 909 lbs_deb_join("ADHOC_RESP: channel = %d\n", adapter->curbssparams.channel);
913 lbs_deb_join("ADHOC_RESP: BSSID = %02x:%02x:%02x:%02x:%02x:%02x\n", 910 lbs_deb_join("ADHOC_RESP: BSSID = %02x:%02x:%02x:%02x:%02x:%02x\n",
914 padhocresult->BSSID[0], padhocresult->BSSID[1], 911 padhocresult->BSSID[0], padhocresult->BSSID[1],
915 padhocresult->BSSID[2], padhocresult->BSSID[3], 912 padhocresult->BSSID[2], padhocresult->BSSID[3],
diff --git a/drivers/net/wireless/libertas/wext.c b/drivers/net/wireless/libertas/wext.c
index 518371a76c36..40dd08018b49 100644
--- a/drivers/net/wireless/libertas/wext.c
+++ b/drivers/net/wireless/libertas/wext.c
@@ -157,103 +157,6 @@ static struct chan_freq_power *find_cfp_by_band_and_freq(wlan_adapter * adapter,
157 return cfp; 157 return cfp;
158} 158}
159 159
160static int updatecurrentchannel(wlan_private * priv)
161{
162 int ret;
163
164 /*
165 ** the channel in f/w could be out of sync, get the current channel
166 */
167 ret = libertas_prepare_and_send_command(priv, cmd_802_11_rf_channel,
168 cmd_opt_802_11_rf_channel_get,
169 cmd_option_waitforrsp, 0, NULL);
170
171 lbs_deb_wext("current channel %d\n",
172 priv->adapter->curbssparams.channel);
173
174 return ret;
175}
176
177static int setcurrentchannel(wlan_private * priv, int channel)
178{
179 lbs_deb_wext("set channel %d\n", channel);
180
181 /*
182 ** Current channel is not set to adhocchannel requested, set channel
183 */
184 return (libertas_prepare_and_send_command(priv, cmd_802_11_rf_channel,
185 cmd_opt_802_11_rf_channel_set,
186 cmd_option_waitforrsp, 0, &channel));
187}
188
189static int changeadhocchannel(wlan_private * priv, int channel)
190{
191 int ret = 0;
192 struct WLAN_802_11_SSID curadhocssid;
193 struct bss_descriptor * join_bss = NULL;
194 wlan_adapter *adapter = priv->adapter;
195
196 adapter->adhocchannel = channel;
197
198 updatecurrentchannel(priv);
199
200 if (adapter->curbssparams.channel == adapter->adhocchannel) {
201 /* adhocchannel is set to the current channel already */
202 goto out;
203 }
204
205 lbs_deb_wext("updating channel from %d to %d\n",
206 adapter->curbssparams.channel, adapter->adhocchannel);
207
208 setcurrentchannel(priv, adapter->adhocchannel);
209
210 updatecurrentchannel(priv);
211
212 if (adapter->curbssparams.channel != adapter->adhocchannel) {
213 lbs_deb_wext("failed to updated channel to %d, channel = %d\n",
214 adapter->adhocchannel, adapter->curbssparams.channel);
215 ret = -1;
216 goto out;
217 }
218
219 if (adapter->connect_status != libertas_connected)
220 goto out;
221
222 lbs_deb_wext("channel changed while in IBSS\n");
223
224 /* Copy the current ssid */
225 memcpy(&curadhocssid, &adapter->curbssparams.ssid,
226 sizeof(struct WLAN_802_11_SSID));
227
228 /* Exit Adhoc mode */
229 lbs_deb_wext("in changeadhocchannel(): sending Adhoc stop\n");
230 ret = libertas_stop_adhoc_network(priv);
231 if (ret)
232 goto out;
233
234 /* Scan for the network, do not save previous results. Stale
235 * scan data will cause us to join a non-existant adhoc network
236 */
237 libertas_send_specific_SSID_scan(priv, &curadhocssid, 1);
238
239 /* find out the BSSID that matches the current SSID */
240 join_bss = libertas_find_SSID_in_list(adapter, &curadhocssid, NULL,
241 IW_MODE_ADHOC);
242
243 if (join_bss) {
244 lbs_deb_wext("SSID found in list, so join\n");
245 libertas_join_adhoc_network(priv, join_bss);
246 } else {
247 lbs_deb_wext("SSID not found in list, "
248 "creating AdHoc with SSID '%s'\n",
249 curadhocssid.ssid);
250 libertas_start_adhoc_network(priv, &curadhocssid);
251 }
252
253out:
254 lbs_deb_leave_args(LBS_DEB_WEXT, "ret %d", ret);
255 return ret;
256}
257 160
258/** 161/**
259 * @brief Set Radio On/OFF 162 * @brief Set Radio On/OFF
@@ -1228,82 +1131,59 @@ out:
1228static int wlan_set_freq(struct net_device *dev, struct iw_request_info *info, 1131static int wlan_set_freq(struct net_device *dev, struct iw_request_info *info,
1229 struct iw_freq *fwrq, char *extra) 1132 struct iw_freq *fwrq, char *extra)
1230{ 1133{
1231 int ret = 0; 1134 int ret = -EINVAL;
1232 wlan_private *priv = dev->priv; 1135 wlan_private *priv = dev->priv;
1233 wlan_adapter *adapter = priv->adapter; 1136 wlan_adapter *adapter = priv->adapter;
1234 int rc = -EINPROGRESS; /* Call commit handler */
1235 struct chan_freq_power *cfp; 1137 struct chan_freq_power *cfp;
1138 struct assoc_request * assoc_req;
1236 1139
1237 lbs_deb_enter(LBS_DEB_WEXT); 1140 lbs_deb_enter(LBS_DEB_WEXT);
1238 1141
1239 /* 1142 mutex_lock(&adapter->lock);
1240 * If setting by frequency, convert to a channel 1143 assoc_req = wlan_get_association_request(adapter);
1241 */ 1144 if (!assoc_req) {
1242 if (fwrq->e == 1) { 1145 ret = -ENOMEM;
1146 goto out;
1147 }
1243 1148
1149 /* If setting by frequency, convert to a channel */
1150 if (fwrq->e == 1) {
1244 long f = fwrq->m / 100000; 1151 long f = fwrq->m / 100000;
1245 int c = 0;
1246 1152
1247 cfp = find_cfp_by_band_and_freq(adapter, 0, f); 1153 cfp = find_cfp_by_band_and_freq(adapter, 0, f);
1248 if (!cfp) { 1154 if (!cfp) {
1249 lbs_deb_wext("invalid freq %ld\n", f); 1155 lbs_deb_wext("invalid freq %ld\n", f);
1250 return -EINVAL; 1156 goto out;
1251 } 1157 }
1252 1158
1253 c = (int)cfp->channel;
1254
1255 if (c < 0)
1256 return -EINVAL;
1257
1258 fwrq->e = 0; 1159 fwrq->e = 0;
1259 fwrq->m = c; 1160 fwrq->m = (int) cfp->channel;
1260 } 1161 }
1261 1162
1262 /* 1163 /* Setting by channel number */
1263 * Setting by channel number
1264 */
1265 if (fwrq->m > 1000 || fwrq->e > 0) { 1164 if (fwrq->m > 1000 || fwrq->e > 0) {
1266 rc = -EOPNOTSUPP; 1165 goto out;
1267 } else { 1166 }
1268 int channel = fwrq->m;
1269 1167
1270 cfp = libertas_find_cfp_by_band_and_channel(adapter, 0, channel); 1168 cfp = libertas_find_cfp_by_band_and_channel(adapter, 0, fwrq->m);
1271 if (!cfp) { 1169 if (!cfp) {
1272 rc = -EINVAL; 1170 goto out;
1273 } else {
1274 if (adapter->mode == IW_MODE_ADHOC) {
1275 rc = changeadhocchannel(priv, channel);
1276 /* If station is WEP enabled, send the
1277 * command to set WEP in firmware
1278 */
1279 if (adapter->secinfo.wep_enabled) {
1280 lbs_deb_wext("set_freq: WEP enabled\n");
1281 ret = libertas_prepare_and_send_command(priv,
1282 cmd_802_11_set_wep,
1283 cmd_act_add,
1284 cmd_option_waitforrsp,
1285 0,
1286 NULL);
1287
1288 if (ret) {
1289 rc = ret;
1290 goto out;
1291 }
1292
1293 adapter->currentpacketfilter |=
1294 cmd_act_mac_wep_enable;
1295
1296 libertas_set_mac_packet_filter(priv);
1297 }
1298 } else {
1299 rc = -EOPNOTSUPP;
1300 }
1301 }
1302 } 1171 }
1303 1172
1173 assoc_req->channel = fwrq->m;
1174 ret = 0;
1175
1304out: 1176out:
1305 lbs_deb_leave_args(LBS_DEB_WEXT, "ret %d", rc); 1177 if (ret == 0) {
1306 return rc; 1178 set_bit(ASSOC_FLAG_CHANNEL, &assoc_req->flags);
1179 wlan_postpone_association_work(priv);
1180 } else {
1181 wlan_cancel_association_work(priv);
1182 }
1183 mutex_unlock(&adapter->lock);
1184
1185 lbs_deb_leave_args(LBS_DEB_WEXT, "ret %d", ret);
1186 return ret;
1307} 1187}
1308 1188
1309/** 1189/**